mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Compare commits
92 Commits
update_rea
...
pydcs_upda
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9b09e51e5 | ||
|
|
5ad4493ec2 | ||
|
|
4a827f2f1c | ||
|
|
4c3a100835 | ||
|
|
bc371a1b99 | ||
|
|
3a9a2f5a3f | ||
|
|
d0d22b3d21 | ||
|
|
fefe57b75e | ||
|
|
82258f331c | ||
|
|
4e86b5211c | ||
|
|
6cd3043b60 | ||
|
|
d8ba7c7d4d | ||
|
|
c3d4ddae44 | ||
|
|
9d774c8976 | ||
|
|
e47e95f89f | ||
|
|
fa41b00ef0 | ||
|
|
c29c61ade3 | ||
|
|
14ccc0753d | ||
|
|
9ab5d0e892 | ||
|
|
562d9cb6cf | ||
|
|
805b036761 | ||
|
|
df43d2eed6 | ||
|
|
5d0ddea753 | ||
|
|
25b93b5d6d | ||
|
|
0e9a8ac1a1 | ||
|
|
b008305275 | ||
|
|
a3ca82cccb | ||
|
|
a0cb6d042e | ||
|
|
d72c119b7c | ||
|
|
2ddf73a845 | ||
|
|
fd9e40d5aa | ||
|
|
79f170e474 | ||
|
|
ad328334db | ||
|
|
db5af55c49 | ||
|
|
6774f0bd43 | ||
|
|
8237b15436 | ||
|
|
1b90a68bd9 | ||
|
|
cb9cf52e16 | ||
|
|
020e9797c5 | ||
|
|
9909ce6507 | ||
|
|
529cc31a72 | ||
|
|
38c3cdbf16 | ||
|
|
a76c0d298e | ||
|
|
7543b5f79f | ||
|
|
708402b955 | ||
|
|
6a9cebe9b1 | ||
|
|
36b687f7ef | ||
|
|
524125b455 | ||
|
|
1be87ec16b | ||
|
|
9066fafcb1 | ||
|
|
fd8632a71d | ||
|
|
352216bb5e | ||
|
|
271ddf4503 | ||
|
|
cef81c16c3 | ||
|
|
4e2c3dbc51 | ||
|
|
d905f0cf7f | ||
|
|
99bbdc3e77 | ||
|
|
4040f50d8a | ||
|
|
11304542bd | ||
|
|
cbf5f5ed90 | ||
|
|
6433d3159e | ||
|
|
b376ab135f | ||
|
|
99089cc3d0 | ||
|
|
13ff69c4df | ||
|
|
55c77ed7c3 | ||
|
|
4c5d968dd7 | ||
|
|
dc3d1b0b5b | ||
|
|
75f904275c | ||
|
|
f59051c9f8 | ||
|
|
c8c78d0b2a | ||
|
|
0ade5b9861 | ||
|
|
9611c01b93 | ||
|
|
3234a2b28a | ||
|
|
8aa38a83ff | ||
|
|
7d5bb0356f | ||
|
|
143b775639 | ||
|
|
f296925c22 | ||
|
|
dfe0c0b315 | ||
|
|
bd5087b3c7 | ||
|
|
88ebb8b612 | ||
|
|
63702f859d | ||
|
|
cc5e2ba26c | ||
|
|
b0a8d53fa6 | ||
|
|
77b7f777f6 | ||
|
|
e59da610e9 | ||
|
|
b61310d229 | ||
|
|
6550400604 | ||
|
|
1ee1113e48 | ||
|
|
01f22d6da7 | ||
|
|
8e6893d550 | ||
|
|
fa9d5525c0 | ||
|
|
5127022910 |
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -31,7 +31,7 @@ body:
|
||||
If the bug was found in a development build, select "Development build"
|
||||
and provide a link to the build in the field below.
|
||||
options:
|
||||
- 10.0.0
|
||||
- 12.0.1
|
||||
- Development build
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/new-game-bug.yml
vendored
2
.github/ISSUE_TEMPLATE/new-game-bug.yml
vendored
@@ -39,7 +39,7 @@ body:
|
||||
If the bug was found in a development build, select "Development build"
|
||||
and provide a link to the build in the field below.
|
||||
options:
|
||||
- 10.0.0
|
||||
- 12.0.1
|
||||
- Development build
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
@@ -6,7 +6,7 @@ runs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.11.4"
|
||||
cache: pip
|
||||
|
||||
- name: Install environment
|
||||
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
Compress-Archive -Path .\dist\dcs_liberation\ -DestinationPath
|
||||
dist\dcs_liberation.zip
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dcs_liberation
|
||||
path: dist/dcs_liberation.zip
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: psf/black@stable
|
||||
with:
|
||||
version: ~=23.11
|
||||
version: ~=24.3.0
|
||||
src: "."
|
||||
options: "--check"
|
||||
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
with:
|
||||
release: true
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dcs_liberation
|
||||
path: dist/
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
needs: [build]
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v4.1.7
|
||||
with:
|
||||
name: dcs_liberation
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
(Github Readme Banner and Splash screen Artwork by Andriy Dankovych, CC BY-SA 4.0)
|
||||
|
||||
[](https://patreon.com/khopa)
|
||||
|
||||
[](https://github.com/dcs-liberation/dcs_liberation/releases)
|
||||
|
||||
[](https://discord.gg/bKrtrkJ)
|
||||
@@ -17,11 +15,6 @@
|
||||
DCS Liberation is a [DCS World](https://www.digitalcombatsimulator.com/en/products/world/) turn based single-player or co-op dynamic campaign.
|
||||
It is an external program that generates full and complex DCS missions and manage a persistent combat environment.
|
||||
|
||||
**Note that DCS Liberation does not support the stable release of DCS. We can
|
||||
only guarantee compatibility with either the open beta or the stable release,
|
||||
and more people play the open beta. DCS stable _might_ work sometimes, but it's
|
||||
untested, and we will be unable to fix any bugs unique to stable DCS.**
|
||||
|
||||

|
||||
|
||||
## Downloads
|
||||
|
||||
67
changelog.md
67
changelog.md
@@ -1,13 +1,78 @@
|
||||
# 12.1.0
|
||||
|
||||
Saves from 12.x are compatible with 12.1.0.
|
||||
|
||||
## Features/Improvements
|
||||
|
||||
* **[Engine]** Support for DCS 2.9.10.3948.
|
||||
* **[Data]** Support for CH-47 Chinook.
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[Data]** Added/updated CBU weapons data.
|
||||
* **[Data]** Added Strike mission type for KA-50 (all playable variants).
|
||||
* **[Mission Generation]** Fixed crash when using factions that have Eastern callsign conventions.
|
||||
|
||||
# 12.0.0
|
||||
|
||||
Saves from 11.x are not compatible with 12.0.0.
|
||||
|
||||
## Features/Improvements
|
||||
|
||||
* **[Engine]** Support for DCS 2.9.9.2280.
|
||||
* **[Campaign]** Flights are assigned different callsigns appropriate to the faction.
|
||||
* **[Campaign]** Removed deprecated settings for generating persistent and invulnerable AWACs and tankers.
|
||||
* **[Data]** Added ability to restrict weapons usage for a faction to a different year from the nominal weapon introduction year. Updated faction data to restrict more advanced missiles from Soviet client states during the cold war. Updated Egypt 2000 faction to restrict AIM-120 usage.
|
||||
* **[Mission Generation]** Added option to skip combat when fast forwarding, which progresses fast forward as if the combat did not occur. Simplified fast forward settings by consolidating "Fast forward mission to first contact" and "Player missions interrupt fast forward" into a single setting and expanding options for "Auto-resolve combat during fast-forward (WIP)".
|
||||
* **[Mods]** F/A-18 E/F/G Super Hornet mod version updated to 2.3.
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[Data]** Added/updated weapons data for F4E weapons such as AIM-7, AIM-9, AGM-12, AGM-45 and AGM-65.
|
||||
* **[Campaign]** Do not allow aircraft from a captured control point to retreat if the captured control point has a damaged runway.
|
||||
* **[Campaign]** Do not allow ground units to be transferred to LHAs, CVNs or off map spawns.
|
||||
* **[Mission Generation]** Fixed aircraft not spawning correctly on CVNs, LHAs and FARPs.
|
||||
|
||||
# 11.1.1
|
||||
|
||||
Saves from 11.0.0 are compatible with 11.1.1. See Known Issues section for exceptions.
|
||||
|
||||
## Features/Improvements
|
||||
|
||||
* **[Engine]** Support for DCS 2.9.5.55918 including Heatblur F-4E and Polychop OH-58D Kiowa Warrior support.
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[Campaign]** Fixed double counting of parked aircraft kills when DCS reports multiple kill events.
|
||||
* **[Campaign]** Fixed error where frontline units are not re-deployed when multiple control points were captured in one turn or when control points are captured "out of order" using air-assault missions.
|
||||
* **[Cheat Menu]** Re-deploy frontline units when using cheats to capture control points, so that cheats behave the same way as capturing a control point in-mission.
|
||||
* **[Data]** Added FuSe-65 Early Warning Radar.
|
||||
* **[Data]** Updated Peru 1995 and Germany 1944 factions.
|
||||
* **[Flight Planning]** Theater refuelling flight plans (those not tied to a particular package) will remain on station for a longer period, specifically the desired mission duration + 30 minutes. By default, this increases the on-station time from 1 hour to 1.5 hours.
|
||||
* **[Mission Generation]** Patched bug where Liberation crashed when aborting a turn when Fighter Sweep missions were planned.
|
||||
* **[Radios]** Added radio setup for F-5E, F-86, Mi-8 and Mi-24.
|
||||
* **[UI]** Naval control points (carriers, LHAs) can no longer be moved onto land.
|
||||
|
||||
## Known Issues
|
||||
|
||||
* When loading saves from 11.0, loadouts with AGM-45B (Imp), typically on A-4E-C mod, will have the AGM-45B replaced with an empty pylon due to changes in DCS for this weapon. The AGM-45A is not affected by this issue.
|
||||
|
||||
# 11.0.0
|
||||
|
||||
Saves from 10.x are not compatible with 11.0.0.
|
||||
|
||||
## Features/Improvements
|
||||
|
||||
* **[Engine]** Support for DCS 2.9.3.51704 Open Beta.
|
||||
* **[Engine]** Support for DCS 2.9.3.51704.
|
||||
* **[Campaign]** Improved tracking of parked aircraft deaths. Parked aircraft are now considered dead once sufficient damage is done, meaning guns, rockets and AGMs are viable weapons for OCA/Aircraft missions. Previously Liberation relied on DCS death tracking which required parked aircraft to be hit with more powerful weapons e.g. 2000lb bombs as they were uncontrolled.
|
||||
* **[Campaign]** Track damage to theater ground objects across turns. Damage can accumulate across turns leading to death of the unit. This behavior only applies to SAMs, ships and other units that appear on the Liberation map. Frontline units and buildings are not tracked (yet).
|
||||
* **[Mods]** F/A-18 E/F/G Super Hornet mod (v2.2.5) support added.
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[Mission Generation]** When planning anti-ship missions against carriers or LHAs, target escorts (if present) if the carrier/LHA is sunk.
|
||||
* **[UI]** Identify that a carrier or LHA is sunk instead of "damaged".
|
||||
|
||||
# 10.0.0
|
||||
|
||||
Saves from 9.x are not compatible with 10.0.0.
|
||||
|
||||
1795
client/package-lock.json
generated
1795
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@
|
||||
"@types/react": "^18.0.21",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/react-redux": "^7.1.24",
|
||||
"axios": "^1.6.0",
|
||||
"axios": "^1.7.4",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"esri-leaflet": "^3.0.8",
|
||||
"leaflet": "^1.9.2",
|
||||
@@ -74,7 +74,7 @@
|
||||
"msw": "^1.2.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"wait-on": "^6.0.1"
|
||||
"wait-on": "^8.0.0"
|
||||
},
|
||||
"jest": {
|
||||
"transformIgnorePatterns": [
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
project = "DCS Liberation"
|
||||
copyright = "2023, DCS Liberation Team"
|
||||
copyright = "2024, DCS Liberation Team"
|
||||
author = "DCS Liberation Team"
|
||||
release = "11.0.0"
|
||||
release = "12.0.0"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Objective adjacency lists."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, Iterator, List, Optional, TYPE_CHECKING
|
||||
|
||||
@@ -21,6 +21,7 @@ from ..sidc import (
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.callsigns.callsigngenerator import Callsign
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.sim.gameupdateevents import GameUpdateEvents
|
||||
from game.sim.simulationresults import SimulationResults
|
||||
@@ -49,6 +50,7 @@ class Flight(SidcDescribable):
|
||||
custom_name: Optional[str] = None,
|
||||
cargo: Optional[TransferOrder] = None,
|
||||
roster: Optional[FlightRoster] = None,
|
||||
callsign: Optional[Callsign] = None,
|
||||
) -> None:
|
||||
self.id = uuid.uuid4()
|
||||
self.package = package
|
||||
@@ -69,6 +71,8 @@ class Flight(SidcDescribable):
|
||||
# Only used by transport missions.
|
||||
self.cargo = cargo
|
||||
|
||||
self.callsign = callsign
|
||||
|
||||
# Flight properties that can be set in the mission editor. This is used for
|
||||
# things like HMD selection, ripple quantity, etc. Any values set here will take
|
||||
# the place of the defaults defined by DCS.
|
||||
|
||||
@@ -5,6 +5,7 @@ MissionPlanner. Those only plan basic information like the objective, aircraft
|
||||
type, and the size of the flight. The FlightPlanBuilder is responsible for
|
||||
generating the waypoints for the mission.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
|
||||
@@ -30,8 +30,7 @@ LayoutT = TypeVar("LayoutT", bound=FormationLayout)
|
||||
class FormationFlightPlan(LoiterFlightPlan[LayoutT], ABC):
|
||||
@property
|
||||
@abstractmethod
|
||||
def package_speed_waypoints(self) -> set[FlightWaypoint]:
|
||||
...
|
||||
def package_speed_waypoints(self) -> set[FlightWaypoint]: ...
|
||||
|
||||
@property
|
||||
def combat_speed_waypoints(self) -> set[FlightWaypoint]:
|
||||
@@ -69,13 +68,11 @@ class FormationFlightPlan(LoiterFlightPlan[LayoutT], ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def join_time(self) -> datetime:
|
||||
...
|
||||
def join_time(self) -> datetime: ...
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def split_time(self) -> datetime:
|
||||
...
|
||||
def split_time(self) -> datetime: ...
|
||||
|
||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> datetime | None:
|
||||
if waypoint == self.layout.join:
|
||||
|
||||
@@ -60,8 +60,7 @@ class IBuilder(ABC, Generic[FlightPlanT, LayoutT]):
|
||||
return self.flight.departure.theater
|
||||
|
||||
@abstractmethod
|
||||
def build(self, dump_debug_info: bool = False) -> FlightPlanT:
|
||||
...
|
||||
def build(self, dump_debug_info: bool = False) -> FlightPlanT: ...
|
||||
|
||||
@property
|
||||
def package(self) -> Package:
|
||||
|
||||
@@ -30,8 +30,7 @@ class LoiterFlightPlan(StandardFlightPlan[LayoutT], ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def push_time(self) -> datetime:
|
||||
...
|
||||
def push_time(self) -> datetime: ...
|
||||
|
||||
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> datetime | None:
|
||||
if waypoint == self.layout.hold:
|
||||
|
||||
@@ -17,7 +17,13 @@ class TheaterRefuelingFlightPlan(RefuelingFlightPlan):
|
||||
|
||||
@property
|
||||
def patrol_duration(self) -> timedelta:
|
||||
return timedelta(hours=1)
|
||||
# Add 30 minutes to desired_player_mission_duration as TOTs for flights
|
||||
# can sit up to this time. This extension means the tanker remains on
|
||||
# station for the flights' return.
|
||||
return (
|
||||
self.flight.coalition.game.settings.desired_player_mission_duration
|
||||
+ timedelta(minutes=30)
|
||||
)
|
||||
|
||||
|
||||
class Builder(IBuilder[TheaterRefuelingFlightPlan, PatrollingLayout]):
|
||||
|
||||
@@ -14,5 +14,4 @@ class UiZone:
|
||||
|
||||
class UiZoneDisplay(abc.ABC):
|
||||
@abc.abstractmethod
|
||||
def ui_zone(self) -> UiZone:
|
||||
...
|
||||
def ui_zone(self) -> UiZone: ...
|
||||
|
||||
@@ -57,14 +57,12 @@ class FlightState(ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def cancelable(self) -> bool:
|
||||
...
|
||||
def cancelable(self) -> bool: ...
|
||||
|
||||
@abstractmethod
|
||||
def on_game_tick(
|
||||
self, events: GameUpdateEvents, time: datetime, duration: timedelta
|
||||
) -> None:
|
||||
...
|
||||
) -> None: ...
|
||||
|
||||
@property
|
||||
def in_flight(self) -> bool:
|
||||
@@ -95,17 +93,14 @@ class FlightState(ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def is_waiting_for_start(self) -> bool:
|
||||
...
|
||||
def is_waiting_for_start(self) -> bool: ...
|
||||
|
||||
@abstractmethod
|
||||
def estimate_position(self) -> Point:
|
||||
...
|
||||
def estimate_position(self) -> Point: ...
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def spawn_type(self) -> StartType:
|
||||
...
|
||||
def spawn_type(self) -> StartType: ...
|
||||
|
||||
def a2a_commit_region(self) -> Optional[ThreatPoly]:
|
||||
return None
|
||||
|
||||
@@ -67,16 +67,13 @@ class InFlight(FlightState, ABC):
|
||||
)
|
||||
|
||||
@abstractmethod
|
||||
def estimate_position(self) -> Point:
|
||||
...
|
||||
def estimate_position(self) -> Point: ...
|
||||
|
||||
@abstractmethod
|
||||
def estimate_altitude(self) -> tuple[Distance, str]:
|
||||
...
|
||||
def estimate_altitude(self) -> tuple[Distance, str]: ...
|
||||
|
||||
@abstractmethod
|
||||
def estimate_speed(self) -> Speed:
|
||||
...
|
||||
def estimate_speed(self) -> Speed: ...
|
||||
|
||||
def estimate_fuel_at_current_waypoint(self) -> float:
|
||||
initial_fuel = super().estimate_fuel()
|
||||
|
||||
@@ -8,6 +8,9 @@ from .atdeparture import AtDeparture
|
||||
from .taxi import Taxi
|
||||
from ..starttype import StartType
|
||||
|
||||
from game.settings.settings import FastForwardStopCondition
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.ato.flight import Flight
|
||||
from game.settings import Settings
|
||||
@@ -37,7 +40,8 @@ class StartUp(AtDeparture):
|
||||
def should_halt_sim(self) -> bool:
|
||||
if (
|
||||
self.flight.client_count > 0
|
||||
and self.settings.player_mission_interrupts_sim_at is StartType.COLD
|
||||
and self.settings.fast_forward_stop_condition
|
||||
== FastForwardStopCondition.PLAYER_STARTUP
|
||||
):
|
||||
logging.info(
|
||||
f"Interrupting simulation because {self.flight} has players and has "
|
||||
|
||||
@@ -9,6 +9,8 @@ from .navigating import Navigating
|
||||
from ..starttype import StartType
|
||||
from ...utils import LBS_TO_KG
|
||||
|
||||
from game.settings.settings import FastForwardStopCondition
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.ato.flight import Flight
|
||||
from game.settings import Settings
|
||||
@@ -45,7 +47,8 @@ class Takeoff(AtDeparture):
|
||||
def should_halt_sim(self) -> bool:
|
||||
if (
|
||||
self.flight.client_count > 0
|
||||
and self.settings.player_mission_interrupts_sim_at is StartType.RUNWAY
|
||||
and self.settings.fast_forward_stop_condition
|
||||
== FastForwardStopCondition.PLAYER_TAKEOFF
|
||||
):
|
||||
logging.info(
|
||||
f"Interrupting simulation because {self.flight} has players and has "
|
||||
|
||||
@@ -8,6 +8,8 @@ from .atdeparture import AtDeparture
|
||||
from .takeoff import Takeoff
|
||||
from ..starttype import StartType
|
||||
|
||||
from game.settings.settings import FastForwardStopCondition
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.ato.flight import Flight
|
||||
from game.settings import Settings
|
||||
@@ -37,7 +39,8 @@ class Taxi(AtDeparture):
|
||||
def should_halt_sim(self) -> bool:
|
||||
if (
|
||||
self.flight.client_count > 0
|
||||
and self.settings.player_mission_interrupts_sim_at is StartType.WARM
|
||||
and self.settings.fast_forward_stop_condition
|
||||
== FastForwardStopCondition.PLAYER_TAXI
|
||||
):
|
||||
logging.info(
|
||||
f"Interrupting simulation because {self.flight} has players and has "
|
||||
|
||||
@@ -9,26 +9,20 @@ if TYPE_CHECKING:
|
||||
|
||||
class IFlightRoster(ABC):
|
||||
@abstractmethod
|
||||
def iter_pilots(self) -> Iterator[Pilot | None]:
|
||||
...
|
||||
def iter_pilots(self) -> Iterator[Pilot | None]: ...
|
||||
|
||||
@abstractmethod
|
||||
def pilot_at(self, idx: int) -> Pilot | None:
|
||||
...
|
||||
def pilot_at(self, idx: int) -> Pilot | None: ...
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def max_size(self) -> int:
|
||||
...
|
||||
def max_size(self) -> int: ...
|
||||
|
||||
@abstractmethod
|
||||
def resize(self, new_size: int) -> None:
|
||||
...
|
||||
def resize(self, new_size: int) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
def set_pilot(self, index: int, pilot: Optional[Pilot]) -> None:
|
||||
...
|
||||
def set_pilot(self, index: int, pilot: Optional[Pilot]) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
def clear(self) -> None:
|
||||
...
|
||||
def clear(self) -> None: ...
|
||||
|
||||
@@ -10,6 +10,8 @@ from dcs.unittype import FlyingType
|
||||
|
||||
from game.data.weapons import Pylon, Weapon, WeaponType
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.factions.faction import Faction
|
||||
|
||||
from .flighttype import FlightType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -52,6 +54,7 @@ class Loadout:
|
||||
weapon: Weapon,
|
||||
pylon: Pylon,
|
||||
date: datetime.date,
|
||||
faction: Faction,
|
||||
skip_types: Optional[Iterable[WeaponType]] = None,
|
||||
) -> Optional[Weapon]:
|
||||
if skip_types is None:
|
||||
@@ -59,14 +62,16 @@ class Loadout:
|
||||
for fallback in weapon.fallbacks:
|
||||
if not pylon.can_equip(fallback):
|
||||
continue
|
||||
if not fallback.available_on(date):
|
||||
if not fallback.available_on(date, faction):
|
||||
continue
|
||||
if fallback.weapon_group.type in skip_types:
|
||||
continue
|
||||
return fallback
|
||||
return None
|
||||
|
||||
def degrade_for_date(self, unit_type: AircraftType, date: datetime.date) -> Loadout:
|
||||
def degrade_for_date(
|
||||
self, unit_type: AircraftType, date: datetime.date, faction: Faction
|
||||
) -> Loadout:
|
||||
if self.date is not None and self.date <= date:
|
||||
return Loadout(self.name, self.pylons, self.date, self.is_custom)
|
||||
|
||||
@@ -75,9 +80,9 @@ class Loadout:
|
||||
if weapon is None:
|
||||
del new_pylons[pylon_number]
|
||||
continue
|
||||
if not weapon.available_on(date):
|
||||
if not weapon.available_on(date, faction):
|
||||
pylon = Pylon.for_aircraft(unit_type, pylon_number)
|
||||
fallback = self._fallback_for(weapon, pylon, date)
|
||||
fallback = self._fallback_for(weapon, pylon, date, faction)
|
||||
if fallback is None:
|
||||
del new_pylons[pylon_number]
|
||||
else:
|
||||
@@ -89,11 +94,11 @@ class Loadout:
|
||||
# If the loadout was chosen explicitly by the user, assume they know what
|
||||
# they're doing. They may be coordinating buddy-lase.
|
||||
if not loadout.is_custom:
|
||||
loadout.replace_lgbs_if_no_tgp(unit_type, date)
|
||||
loadout.replace_lgbs_if_no_tgp(unit_type, date, faction)
|
||||
return loadout
|
||||
|
||||
def replace_lgbs_if_no_tgp(
|
||||
self, unit_type: AircraftType, date: datetime.date
|
||||
self, unit_type: AircraftType, date: datetime.date, faction: Faction
|
||||
) -> None:
|
||||
if self.has_weapon_of_type(WeaponType.TGP):
|
||||
return
|
||||
@@ -106,7 +111,7 @@ class Loadout:
|
||||
if weapon is not None and weapon.weapon_group.type is WeaponType.LGB:
|
||||
pylon = Pylon.for_aircraft(unit_type, pylon_number)
|
||||
fallback = self._fallback_for(
|
||||
weapon, pylon, date, skip_types={WeaponType.LGB}
|
||||
weapon, pylon, date, faction, skip_types={WeaponType.LGB}
|
||||
)
|
||||
if fallback is None:
|
||||
del new_pylons[pylon_number]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Support for working with DCS group callsigns."""
|
||||
|
||||
import logging
|
||||
import re
|
||||
from typing import Any
|
||||
253
game/callsigns/callsigngenerator.py
Normal file
253
game/callsigns/callsigngenerator.py
Normal file
@@ -0,0 +1,253 @@
|
||||
from __future__ import annotations
|
||||
from abc import ABC
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from collections import deque
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from dcs.country import Country
|
||||
from dcs.countries import countries_by_name
|
||||
|
||||
from game.ato.flight import Flight
|
||||
from game.ato.flighttype import FlightType
|
||||
|
||||
|
||||
MAX_GROUP_ID = 99
|
||||
|
||||
|
||||
class CallsignCategory(StrEnum):
|
||||
AIR = "Air"
|
||||
TANKERS = "Tankers"
|
||||
AWACS = "AWACS"
|
||||
GROUND_UNITS = "GroundUnits"
|
||||
HELIPADS = "Helipad"
|
||||
GRASS_AIRFIELDS = "GrassAirfield"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Callsign:
|
||||
name: Optional[
|
||||
str
|
||||
] # Callsign name e.g. "Enfield" for western callsigns. None for eastern callsigns.
|
||||
group_id: int # ID of the group e.g. 2 in Enfield-2-3 for western callsigns. First two digits of eastern callsigns.
|
||||
unit_id: int # ID of the unit e.g. 3 in Enfield-2-3 for western callsigns. Last digit of eastern callsigns.
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.group_id < 1 or self.group_id > MAX_GROUP_ID:
|
||||
raise ValueError(
|
||||
f"Invalid group ID {self.group_id}. Group IDs have to be between 1 and {MAX_GROUP_ID}."
|
||||
)
|
||||
if self.unit_id < 1 or self.unit_id > 9:
|
||||
raise ValueError(
|
||||
f"Invalid unit ID {self.unit_id}. Unit IDs have to be between 1 and 9."
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.name is not None:
|
||||
return f"{self.name}{self.group_id}{self.unit_id}"
|
||||
else:
|
||||
return str(self.group_id * 10 + self.unit_id)
|
||||
|
||||
def lead_callsign(self) -> Callsign:
|
||||
return Callsign(self.name, self.group_id, 1)
|
||||
|
||||
def unit_callsign(self, unit_id: int) -> Callsign:
|
||||
return Callsign(self.name, self.group_id, unit_id)
|
||||
|
||||
def group_name(self) -> str:
|
||||
if self.name is not None:
|
||||
return f"{self.name}-{self.group_id}"
|
||||
else:
|
||||
return str(self.lead_callsign())
|
||||
|
||||
def pydcs_dict(self, country: str) -> dict[Any, Any]:
|
||||
country_obj = countries_by_name[country]()
|
||||
for category in CallsignCategory:
|
||||
if category in country_obj.callsign:
|
||||
for index, name in enumerate(country_obj.callsign[category]):
|
||||
if name == self.name:
|
||||
return {
|
||||
"name": str(self),
|
||||
1: index + 1,
|
||||
2: self.group_id,
|
||||
3: self.unit_id,
|
||||
}
|
||||
raise ValueError(f"Could not find callsign {name} in {country}.")
|
||||
|
||||
|
||||
class WesternGroupIdRegistry:
|
||||
|
||||
def __init__(self, country: Country, max_group_id: int = MAX_GROUP_ID):
|
||||
self._names: dict[str, deque[int]] = {}
|
||||
for category in CallsignCategory:
|
||||
if category in country.callsign:
|
||||
for name in country.callsign[category]:
|
||||
self._names[name] = deque()
|
||||
self._max_group_id = max_group_id
|
||||
self.reset()
|
||||
|
||||
def reset(self) -> None:
|
||||
for name in self._names:
|
||||
self._names[name] = deque()
|
||||
for i in range(
|
||||
self._max_group_id, 0, -1
|
||||
): # Put group IDs on FIFO queue so 1 gets popped first
|
||||
self._names[name].appendleft(i)
|
||||
|
||||
def alloc_group_id(self, name: str) -> int:
|
||||
return self._names[name].popleft()
|
||||
|
||||
def release_group_id(self, callsign: Callsign) -> None:
|
||||
if callsign.name is None:
|
||||
raise ValueError("Releasing eastern callsign")
|
||||
self._names[callsign.name].appendleft(callsign.group_id)
|
||||
|
||||
|
||||
class EasternGroupIdRegistry:
|
||||
|
||||
def __init__(self, max_group_id: int = MAX_GROUP_ID):
|
||||
self._max_group_id = max_group_id
|
||||
self._queue: deque[int] = deque()
|
||||
self.reset()
|
||||
|
||||
def reset(self) -> None:
|
||||
self._queue = deque()
|
||||
for i in range(
|
||||
self._max_group_id, 0, -1
|
||||
): # Put group IDs on FIFO queue so 1 gets popped first
|
||||
self._queue.appendleft(i)
|
||||
|
||||
def alloc_group_id(self) -> int:
|
||||
return self._queue.popleft()
|
||||
|
||||
def release_group_id(self, callsign: Callsign) -> None:
|
||||
self._queue.appendleft(callsign.group_id)
|
||||
|
||||
|
||||
class RoundRobinNameAllocator:
|
||||
|
||||
def __init__(self, names: List[str]):
|
||||
self.names = names
|
||||
self._index = 0
|
||||
|
||||
def allocate(self) -> str:
|
||||
this_index = self._index
|
||||
if this_index == len(self.names) - 1:
|
||||
self._index = 0
|
||||
else:
|
||||
self._index += 1
|
||||
return self.names[this_index]
|
||||
|
||||
|
||||
class FlightTypeNameAllocator:
|
||||
def __init__(self, names: List[str]):
|
||||
self.names = names
|
||||
|
||||
def allocate(self, flight: Flight) -> str:
|
||||
index = self.FLIGHT_TYPE_LOOKUP.get(flight.flight_type, 0)
|
||||
return self.names[index]
|
||||
|
||||
FLIGHT_TYPE_LOOKUP: dict[FlightType, int] = {
|
||||
FlightType.TARCAP: 1,
|
||||
FlightType.BARCAP: 1,
|
||||
FlightType.INTERCEPTION: 1,
|
||||
FlightType.SWEEP: 1,
|
||||
FlightType.CAS: 2,
|
||||
FlightType.ANTISHIP: 2,
|
||||
FlightType.BAI: 2,
|
||||
FlightType.STRIKE: 3,
|
||||
FlightType.OCA_RUNWAY: 3,
|
||||
FlightType.OCA_AIRCRAFT: 3,
|
||||
FlightType.SEAD: 4,
|
||||
FlightType.DEAD: 4,
|
||||
FlightType.ESCORT: 5,
|
||||
FlightType.AIR_ASSAULT: 6,
|
||||
FlightType.TRANSPORT: 7,
|
||||
FlightType.FERRY: 7,
|
||||
}
|
||||
|
||||
|
||||
class WesternFlightCallsignGenerator:
|
||||
"""Generate western callsign for lead unit in a group"""
|
||||
|
||||
def __init__(self, country: str) -> None:
|
||||
self._country = countries_by_name[country]()
|
||||
self._group_id_registry = WesternGroupIdRegistry(self._country)
|
||||
self._awacs_name_allocator = None
|
||||
self._tankers_name_allocator = None
|
||||
|
||||
if CallsignCategory.AWACS in self._country.callsign:
|
||||
self._awacs_name_allocator = RoundRobinNameAllocator(
|
||||
self._country.callsign[CallsignCategory.AWACS]
|
||||
)
|
||||
if CallsignCategory.TANKERS in self._country.callsign:
|
||||
self._tankers_name_allocator = RoundRobinNameAllocator(
|
||||
self._country.callsign[CallsignCategory.TANKERS]
|
||||
)
|
||||
self._air_name_allocator = FlightTypeNameAllocator(
|
||||
self._country.callsign[CallsignCategory.AIR]
|
||||
)
|
||||
|
||||
def reset(self) -> None:
|
||||
self._group_id_registry.reset()
|
||||
|
||||
def alloc_callsign(self, flight: Flight) -> Callsign:
|
||||
if flight.flight_type == FlightType.AEWC:
|
||||
if self._awacs_name_allocator is None:
|
||||
raise ValueError(f"{self._country.name} does not have AWACs callsigns")
|
||||
name = self._awacs_name_allocator.allocate()
|
||||
elif flight.flight_type == FlightType.REFUELING:
|
||||
if self._tankers_name_allocator is None:
|
||||
raise ValueError(f"{self._country.name} does not have tanker callsigns")
|
||||
name = self._tankers_name_allocator.allocate()
|
||||
else:
|
||||
name = self._air_name_allocator.allocate(flight)
|
||||
group_id = self._group_id_registry.alloc_group_id(name)
|
||||
return Callsign(name, group_id, 1)
|
||||
|
||||
def release_callsign(self, callsign: Callsign) -> None:
|
||||
self._group_id_registry.release_group_id(callsign)
|
||||
|
||||
|
||||
class EasternFlightCallsignGenerator:
|
||||
"""Generate eastern callsign for lead unit in a group"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._group_id_registry = EasternGroupIdRegistry()
|
||||
|
||||
def reset(self) -> None:
|
||||
self._group_id_registry.reset()
|
||||
|
||||
def alloc_callsign(self, flight: Flight) -> Callsign:
|
||||
group_id = self._group_id_registry.alloc_group_id()
|
||||
return Callsign(None, group_id, 1)
|
||||
|
||||
def release_callsign(self, callsign: Callsign) -> None:
|
||||
self._group_id_registry.release_group_id(callsign)
|
||||
|
||||
|
||||
class FlightCallsignGenerator:
|
||||
|
||||
def __init__(self, country: str):
|
||||
self._use_western_callsigns = countries_by_name[country]().use_western_callsigns
|
||||
self._generators: dict[
|
||||
bool, WesternFlightCallsignGenerator | EasternFlightCallsignGenerator
|
||||
] = {}
|
||||
if self._use_western_callsigns:
|
||||
self._generators[self._use_western_callsigns] = (
|
||||
WesternFlightCallsignGenerator(country)
|
||||
)
|
||||
else:
|
||||
self._generators[self._use_western_callsigns] = (
|
||||
EasternFlightCallsignGenerator()
|
||||
)
|
||||
|
||||
def reset(self) -> None:
|
||||
self._generators[self._use_western_callsigns].reset()
|
||||
|
||||
def alloc_callsign(self, flight: Flight) -> Callsign:
|
||||
return self._generators[self._use_western_callsigns].alloc_callsign(flight)
|
||||
|
||||
def release_callsign(self, callsign: Callsign) -> None:
|
||||
self._generators[self._use_western_callsigns].release_callsign(callsign)
|
||||
@@ -14,12 +14,10 @@ class FactionRecommendation(ABC):
|
||||
self.name = name
|
||||
|
||||
@abstractmethod
|
||||
def register_campaign_specific_faction(self, factions: Factions) -> None:
|
||||
...
|
||||
def register_campaign_specific_faction(self, factions: Factions) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
def get_faction(self, factions: Factions) -> Faction:
|
||||
...
|
||||
def get_faction(self, factions: Factions) -> Faction: ...
|
||||
|
||||
@staticmethod
|
||||
def from_field(
|
||||
|
||||
@@ -61,6 +61,8 @@ class MizCampaignLoader:
|
||||
AirDefence.Hawk_ln.id,
|
||||
AirDefence.S_75M_Volhov.id,
|
||||
AirDefence.X_5p73_s_125_ln.id,
|
||||
AirDefence.NASAMS_LN_B.id,
|
||||
AirDefence.NASAMS_LN_C.id,
|
||||
}
|
||||
|
||||
SHORT_RANGE_SAM_UNIT_TYPES = {
|
||||
|
||||
@@ -7,6 +7,7 @@ from faker import Faker
|
||||
|
||||
from game.armedforces.armedforces import ArmedForces
|
||||
from game.ato.airtaaskingorder import AirTaskingOrder
|
||||
from game.callsigns.callsigngenerator import FlightCallsignGenerator
|
||||
from game.campaignloader.defaultsquadronassigner import DefaultSquadronAssigner
|
||||
from game.commander import TheaterCommander
|
||||
from game.commander.missionscheduler import MissionScheduler
|
||||
@@ -46,6 +47,7 @@ class Coalition:
|
||||
self.air_wing = AirWing(player, game, self.faction)
|
||||
self.armed_forces = ArmedForces(self.faction)
|
||||
self.transfers = PendingTransfers(game, player)
|
||||
self.callsign_generator = FlightCallsignGenerator(faction.country)
|
||||
|
||||
# Late initialized because the two coalitions in the game are mutually
|
||||
# dependent, so must be both constructed before this property can be set.
|
||||
@@ -163,6 +165,8 @@ class Coalition:
|
||||
# is handled correctly.
|
||||
self.transfers.perform_transfers()
|
||||
|
||||
self.callsign_generator.reset()
|
||||
|
||||
def preinit_turn_0(self) -> None:
|
||||
"""Runs final Coalition initialization.
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from game.callsigns.callsigngenerator import FlightCallsignGenerator
|
||||
from game.theater import ControlPoint, MissionTarget, OffMapSpawn
|
||||
from game.utils import nautical_miles
|
||||
from ..ato.flight import Flight
|
||||
@@ -26,6 +27,7 @@ class PackageBuilder:
|
||||
closest_airfields: ClosestAirfields,
|
||||
air_wing: AirWing,
|
||||
laser_code_registry: LaserCodeRegistry,
|
||||
callsign_generator: FlightCallsignGenerator,
|
||||
flight_db: Database[Flight],
|
||||
is_player: bool,
|
||||
package_country: str,
|
||||
@@ -38,6 +40,7 @@ class PackageBuilder:
|
||||
self.package = Package(location, flight_db, auto_asap=asap)
|
||||
self.air_wing = air_wing
|
||||
self.laser_code_registry = laser_code_registry
|
||||
self.callsign_generator = callsign_generator
|
||||
self.start_type = start_type
|
||||
|
||||
def plan_flight(self, plan: ProposedFlight) -> bool:
|
||||
@@ -71,6 +74,7 @@ class PackageBuilder:
|
||||
member.assign_tgp_laser_code(
|
||||
self.laser_code_registry.alloc_laser_code()
|
||||
)
|
||||
flight.callsign = self.callsign_generator.alloc_callsign(flight)
|
||||
self.package.add_flight(flight)
|
||||
return True
|
||||
|
||||
@@ -100,4 +104,6 @@ class PackageBuilder:
|
||||
"""Returns any planned flights to the inventory."""
|
||||
flights = list(self.package.flights)
|
||||
for flight in flights:
|
||||
if flight.callsign is not None:
|
||||
self.callsign_generator.release_callsign(flight.callsign)
|
||||
self.package.remove_flight(flight)
|
||||
|
||||
@@ -142,6 +142,7 @@ class PackageFulfiller:
|
||||
ObjectiveDistanceCache.get_closest_airfields(mission.location),
|
||||
self.air_wing,
|
||||
self.coalition.laser_code_registry,
|
||||
self.coalition.callsign_generator,
|
||||
self.flight_db,
|
||||
self.is_player,
|
||||
self.coalition.country_name,
|
||||
|
||||
@@ -21,8 +21,7 @@ class FrontLineStanceTask(TheaterCommanderTask, ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def stance(self) -> CombatStance:
|
||||
...
|
||||
def stance(self) -> CombatStance: ...
|
||||
|
||||
@staticmethod
|
||||
def management_allowed(state: TheaterState) -> bool:
|
||||
@@ -49,8 +48,7 @@ class FrontLineStanceTask(TheaterCommanderTask, ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def have_sufficient_front_line_advantage(self) -> bool:
|
||||
...
|
||||
def have_sufficient_front_line_advantage(self) -> bool: ...
|
||||
|
||||
@property
|
||||
def ground_force_balance(self) -> float:
|
||||
|
||||
@@ -54,8 +54,7 @@ class PackagePlanningTask(TheaterCommanderTask, Generic[MissionTargetT]):
|
||||
coalition.ato.add_package(self.package)
|
||||
|
||||
@abstractmethod
|
||||
def propose_flights(self) -> None:
|
||||
...
|
||||
def propose_flights(self) -> None: ...
|
||||
|
||||
def propose_flight(
|
||||
self,
|
||||
@@ -118,9 +117,9 @@ class PackagePlanningTask(TheaterCommanderTask, Generic[MissionTargetT]):
|
||||
target_ranges: list[
|
||||
tuple[Union[IadsGroundObject, NavalGroundObject], Distance]
|
||||
] = []
|
||||
all_iads: Iterator[
|
||||
Union[IadsGroundObject, NavalGroundObject]
|
||||
] = itertools.chain(state.enemy_air_defenses, state.enemy_ships)
|
||||
all_iads: Iterator[Union[IadsGroundObject, NavalGroundObject]] = (
|
||||
itertools.chain(state.enemy_air_defenses, state.enemy_ships)
|
||||
)
|
||||
for target in all_iads:
|
||||
distance = meters(target.distance_to(self.target))
|
||||
if range_type is RangeType.Detection:
|
||||
|
||||
@@ -12,5 +12,4 @@ if TYPE_CHECKING:
|
||||
|
||||
class TheaterCommanderTask(PrimitiveTask[TheaterState]):
|
||||
@abstractmethod
|
||||
def execute(self, coalition: Coalition) -> None:
|
||||
...
|
||||
def execute(self, coalition: Coalition) -> None: ...
|
||||
|
||||
@@ -52,6 +52,7 @@ even though it is a primitive task used by many other tasks.
|
||||
|
||||
https://en.wikipedia.org/wiki/Hierarchical_task_network
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
@@ -2,11 +2,11 @@ from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import yaml
|
||||
from typing import Any, ClassVar
|
||||
from typing import Any, ClassVar, Optional
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
|
||||
from dcs.task import OptAAMissileAttackRange
|
||||
from game.data.units import UnitClass
|
||||
from game.utils import Distance, feet, nautical_miles
|
||||
|
||||
@@ -115,6 +115,25 @@ class Cap:
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Tactics:
|
||||
|
||||
#: Air-to-air missile attack range options
|
||||
air_to_air_missile_attack_range: Optional[OptAAMissileAttackRange.Values]
|
||||
|
||||
#: Air defence units evade ARMs
|
||||
air_defence_evades_anti_radiation_missiles: bool
|
||||
|
||||
@staticmethod
|
||||
def from_dict(data: dict[str, Any]) -> Tactics:
|
||||
return Tactics(
|
||||
air_to_air_missile_attack_range=None,
|
||||
air_defence_evades_anti_radiation_missiles=data.get(
|
||||
"air_defence_evades_anti_radiation_missiles", False
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Doctrine:
|
||||
#: Name of the doctrine, used to assign a doctrine in a faction.
|
||||
@@ -159,6 +178,9 @@ class Doctrine:
|
||||
#: Doctrine for Fighter Sweep missions.
|
||||
sweep: Sweep
|
||||
|
||||
#: Tactics options
|
||||
tactics: Tactics
|
||||
|
||||
_by_name: ClassVar[dict[str, Doctrine]] = {}
|
||||
_loaded: ClassVar[bool] = False
|
||||
|
||||
@@ -219,6 +241,7 @@ class Doctrine:
|
||||
cas=Cas.from_dict(data["cas"]),
|
||||
cap=Cap.from_dict(data["cap"]),
|
||||
sweep=Sweep.from_dict(data["sweep"]),
|
||||
tactics=Tactics.from_dict(data.get("tactics", {})),
|
||||
)
|
||||
)
|
||||
cls._loaded = True
|
||||
|
||||
@@ -14,6 +14,8 @@ from dcs.flyingunit import FlyingUnit
|
||||
from dcs.weapons_data import weapon_ids
|
||||
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.factions.faction import Faction
|
||||
|
||||
|
||||
PydcsWeapon = Any
|
||||
PydcsWeaponAssignment = tuple[int, PydcsWeapon]
|
||||
@@ -77,8 +79,12 @@ class Weapon:
|
||||
WeaponGroup.load_all()
|
||||
cls._loaded = True
|
||||
|
||||
def available_on(self, date: datetime.date) -> bool:
|
||||
def available_on(self, date: datetime.date, faction: Faction) -> bool:
|
||||
introduction_year = self.weapon_group.introduction_year
|
||||
if self.weapon_group.name in faction.weapons_introduction_year_overrides:
|
||||
introduction_year = faction.weapons_introduction_year_overrides[
|
||||
self.weapon_group.name
|
||||
]
|
||||
if introduction_year is None:
|
||||
return True
|
||||
return date >= datetime.date(introduction_year, 1, 1)
|
||||
@@ -243,9 +249,9 @@ class Pylon:
|
||||
def make_pydcs_assignment(self, weapon: Weapon) -> PydcsWeaponAssignment:
|
||||
return self.number, weapon.pydcs_data
|
||||
|
||||
def available_on(self, date: datetime.date) -> Iterator[Weapon]:
|
||||
def available_on(self, date: datetime.date, faction: Faction) -> Iterator[Weapon]:
|
||||
for weapon in self.allowed:
|
||||
if weapon.available_on(date):
|
||||
if weapon.available_on(date, faction):
|
||||
yield weapon
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -34,6 +34,10 @@ from game.radio.channels import (
|
||||
ViggenRadioChannelAllocator,
|
||||
ViperChannelNamer,
|
||||
WarthogChannelNamer,
|
||||
PhantomChannelNamer,
|
||||
HindChannelNamer,
|
||||
HipChannelNamer,
|
||||
KiowaChannelNamer,
|
||||
)
|
||||
from game.utils import (
|
||||
Distance,
|
||||
@@ -110,6 +114,10 @@ class RadioConfig:
|
||||
"apache": ApacheChannelNamer,
|
||||
"a10c-legacy": LegacyWarthogChannelNamer,
|
||||
"a10c-ii": WarthogChannelNamer,
|
||||
"phantom": PhantomChannelNamer,
|
||||
"hind": HindChannelNamer,
|
||||
"hip": HipChannelNamer,
|
||||
"kiowa": KiowaChannelNamer,
|
||||
}[config.get("namer", "default")]
|
||||
|
||||
|
||||
@@ -498,9 +506,11 @@ class AircraftType(UnitType[Type[FlyingType]]):
|
||||
patrol_altitude=patrol_config.altitude,
|
||||
patrol_speed=patrol_config.speed,
|
||||
max_mission_range=mission_range,
|
||||
cruise_speed=knots(data["cruise_speed_kt_indicated"])
|
||||
if "cruise_speed_kt_indicated" in data
|
||||
else None,
|
||||
cruise_speed=(
|
||||
knots(data["cruise_speed_kt_indicated"])
|
||||
if "cruise_speed_kt_indicated" in data
|
||||
else None
|
||||
),
|
||||
fuel_consumption=fuel_consumption,
|
||||
default_livery=data.get("default_livery"),
|
||||
intra_flight_radio=radio_config.intra_flight,
|
||||
|
||||
@@ -60,9 +60,9 @@ class GroundUnitType(UnitType[Type[VehicleType]]):
|
||||
reversed_heading: bool = False
|
||||
|
||||
_by_name: ClassVar[dict[str, GroundUnitType]] = {}
|
||||
_by_unit_type: ClassVar[
|
||||
dict[type[VehicleType], list[GroundUnitType]]
|
||||
] = defaultdict(list)
|
||||
_by_unit_type: ClassVar[dict[type[VehicleType], list[GroundUnitType]]] = (
|
||||
defaultdict(list)
|
||||
)
|
||||
|
||||
def __setstate__(self, state: dict[str, Any]) -> None:
|
||||
# Update any existing models with new data on load.
|
||||
|
||||
@@ -17,12 +17,10 @@ class LaserCodeConfig(ABC):
|
||||
)
|
||||
|
||||
@abstractmethod
|
||||
def iter_prop_ids(self) -> Iterator[str]:
|
||||
...
|
||||
def iter_prop_ids(self) -> Iterator[str]: ...
|
||||
|
||||
@abstractmethod
|
||||
def property_dict_for_code(self, code: int) -> dict[str, int]:
|
||||
...
|
||||
def property_dict_for_code(self, code: int) -> dict[str, int]: ...
|
||||
|
||||
|
||||
class SinglePropertyLaserCodeConfig(LaserCodeConfig):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC
|
||||
import itertools
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
@@ -9,7 +9,9 @@ from typing import (
|
||||
Dict,
|
||||
Iterator,
|
||||
List,
|
||||
Optional,
|
||||
TYPE_CHECKING,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
from uuid import UUID
|
||||
@@ -21,8 +23,10 @@ from game.theater import Airfield, ControlPoint
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
from game.ato.flight import Flight
|
||||
from game.dcs.unittype import UnitType
|
||||
from game.sim.simulationresults import SimulationResults
|
||||
from game.transfers import CargoShip
|
||||
from game.theater import TheaterUnit
|
||||
from game.unitmap import (
|
||||
AirliftUnits,
|
||||
ConvoyUnit,
|
||||
@@ -90,6 +94,103 @@ class BaseCaptureEvent:
|
||||
captured_by_player: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
class UnitHitpointUpdate(ABC):
|
||||
unit: Any
|
||||
hit_points: int
|
||||
|
||||
@classmethod
|
||||
def from_json(
|
||||
cls, data: dict[str, Any], unit_map: UnitMap
|
||||
) -> Optional[UnitHitpointUpdate]:
|
||||
raise NotImplementedError()
|
||||
|
||||
def is_dead(self) -> bool:
|
||||
# Use hit_points > 1 to indicate unit is alive, rather than >=1 (DCS logic) to account for uncontrolled units which often have a
|
||||
# health floor of 1
|
||||
if self.hit_points > 1:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_friendly(self, to_player: bool) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@dataclass
|
||||
class FlyingUnitHitPointUpdate(UnitHitpointUpdate):
|
||||
unit: FlyingUnit
|
||||
|
||||
@classmethod
|
||||
def from_json(
|
||||
cls, data: dict[str, Any], unit_map: UnitMap
|
||||
) -> Optional[FlyingUnitHitPointUpdate]:
|
||||
unit = unit_map.flight(data["name"])
|
||||
if unit is None:
|
||||
return None
|
||||
return cls(unit, int(float(data["hit_points"])))
|
||||
|
||||
def is_friendly(self, to_player: bool) -> bool:
|
||||
if to_player:
|
||||
return self.unit.flight.departure.captured
|
||||
return not self.unit.flight.departure.captured
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheaterUnitHitPointUpdate(UnitHitpointUpdate):
|
||||
unit: TheaterUnitMapping
|
||||
|
||||
@classmethod
|
||||
def from_json(
|
||||
cls, data: dict[str, Any], unit_map: UnitMap
|
||||
) -> Optional[TheaterUnitHitPointUpdate]:
|
||||
unit = unit_map.theater_units(data["name"])
|
||||
if unit is None:
|
||||
return None
|
||||
|
||||
if unit.theater_unit.unit_type is None:
|
||||
logging.debug(
|
||||
f"Ground unit {data['name']} does not have a valid unit type."
|
||||
)
|
||||
return None
|
||||
|
||||
if unit.theater_unit.hit_points is None:
|
||||
logging.debug(f"Ground unit {data['name']} does not have hit_points set.")
|
||||
return None
|
||||
|
||||
sim_hit_points = int(
|
||||
float(data["hit_points"])
|
||||
) # Hit points out of the sim i.e. new unit hit points - damage in this turn
|
||||
previous_turn_hit_points = (
|
||||
unit.theater_unit.hit_points
|
||||
) # Hit points at the end of the previous turn
|
||||
full_health_hit_points = (
|
||||
unit.theater_unit.unit_type.hit_points
|
||||
) # Hit points of a new unit
|
||||
|
||||
# Hit points left after damage this turn is subtracted from hit points at the end of the previous turn
|
||||
new_hit_points = previous_turn_hit_points - (
|
||||
full_health_hit_points - sim_hit_points
|
||||
)
|
||||
|
||||
return cls(unit, new_hit_points)
|
||||
|
||||
def is_dead(self) -> bool:
|
||||
# Some TheaterUnits can start with low health of around 1, make sure we don't always kill them off.
|
||||
if (
|
||||
self.unit.theater_unit.unit_type is not None
|
||||
and self.unit.theater_unit.unit_type.hit_points is not None
|
||||
and self.unit.theater_unit.unit_type.hit_points <= 1
|
||||
):
|
||||
return False
|
||||
return super().is_dead()
|
||||
|
||||
def is_friendly(self, to_player: bool) -> bool:
|
||||
return self.unit.theater_unit.ground_object.is_friendly(to_player)
|
||||
|
||||
def commit(self) -> None:
|
||||
self.unit.theater_unit.hit_points = self.hit_points
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StateData:
|
||||
#: True if the mission ended. If False, the mission exited abnormally.
|
||||
@@ -108,6 +209,10 @@ class StateData:
|
||||
#: Mangled names of bases that were captured during the mission.
|
||||
base_capture_events: List[str]
|
||||
|
||||
# List of descriptions of damage done to units. Each list element is a dict like the following
|
||||
# {"name": "<damaged unit name>", "hit_points": <hit points as float>}
|
||||
unit_hit_point_updates: List[dict[str, Any]]
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, data: Dict[str, Any], unit_map: UnitMap) -> StateData:
|
||||
def clean_unit_list(unit_list: List[Any]) -> List[str]:
|
||||
@@ -147,6 +252,7 @@ class StateData:
|
||||
killed_ground_units=killed_ground_units,
|
||||
destroyed_statics=data["destroyed_objects_positions"],
|
||||
base_capture_events=data["base_capture_events"],
|
||||
unit_hit_point_updates=data["unit_hit_point_updates"],
|
||||
)
|
||||
|
||||
|
||||
@@ -284,6 +390,25 @@ class Debriefing:
|
||||
player_losses.append(aircraft)
|
||||
else:
|
||||
enemy_losses.append(aircraft)
|
||||
|
||||
# Keep track of damaged units that are counted as killed so we don't double count
|
||||
# when DCS reports damage multiple times.
|
||||
units_killed_by_damage = set()
|
||||
for unit_data in self.state_data.unit_hit_point_updates:
|
||||
damaged_unit = FlyingUnitHitPointUpdate.from_json(unit_data, self.unit_map)
|
||||
if damaged_unit is None:
|
||||
continue
|
||||
if damaged_unit.is_dead():
|
||||
# If unit already killed, nothing to do.
|
||||
if unit_data["name"] in self.state_data.killed_aircraft:
|
||||
continue
|
||||
if unit_data["name"] in units_killed_by_damage:
|
||||
continue
|
||||
units_killed_by_damage.add(unit_data["name"])
|
||||
if damaged_unit.is_friendly(to_player=True):
|
||||
player_losses.append(damaged_unit.unit)
|
||||
else:
|
||||
enemy_losses.append(damaged_unit.unit)
|
||||
return AirLosses(player_losses, enemy_losses)
|
||||
|
||||
def dead_ground_units(self) -> GroundLosses:
|
||||
@@ -356,8 +481,29 @@ class Debriefing:
|
||||
losses.enemy_airlifts.append(airlift_unit)
|
||||
continue
|
||||
|
||||
for unit_data in self.state_data.unit_hit_point_updates:
|
||||
damaged_unit = TheaterUnitHitPointUpdate.from_json(unit_data, self.unit_map)
|
||||
if damaged_unit is None:
|
||||
continue
|
||||
if damaged_unit.is_dead():
|
||||
if unit_data["name"] in self.state_data.killed_ground_units:
|
||||
continue
|
||||
if damaged_unit.is_friendly(to_player=True):
|
||||
losses.player_ground_objects.append(damaged_unit.unit)
|
||||
else:
|
||||
losses.enemy_ground_objects.append(damaged_unit.unit)
|
||||
|
||||
return losses
|
||||
|
||||
def unit_hit_point_update_events(self) -> List[TheaterUnitHitPointUpdate]:
|
||||
damaged_units = []
|
||||
for unit_data in self.state_data.unit_hit_point_updates:
|
||||
unit = TheaterUnitHitPointUpdate.from_json(unit_data, self.unit_map)
|
||||
if unit is None:
|
||||
continue
|
||||
damaged_units.append(unit)
|
||||
return damaged_units
|
||||
|
||||
def base_capture_events(self) -> List[BaseCaptureEvent]:
|
||||
"""Keeps only the last instance of a base capture event for each base ID."""
|
||||
blue_coalition_id = 2
|
||||
|
||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
import itertools
|
||||
import logging
|
||||
from dataclasses import dataclass, field
|
||||
import datetime
|
||||
from functools import cached_property
|
||||
from typing import Any, Dict, Iterator, List, Optional, TYPE_CHECKING, Type
|
||||
|
||||
@@ -118,6 +119,13 @@ class Faction:
|
||||
#: both will use it.
|
||||
unrestricted_satnav: bool = False
|
||||
|
||||
#: Overrides default weapons introduction years for faction. Maps names of
|
||||
#: weapons groups to their introduction years.
|
||||
weapons_introduction_year_overrides: Dict[str, int] = field(default_factory=dict)
|
||||
|
||||
#: Set to True if the faction has access to countermeasures (chaff and flares).
|
||||
countermeasures_available: bool = True
|
||||
|
||||
def has_access_to_dcs_type(self, unit_type: Type[DcsUnitType]) -> bool:
|
||||
# Vehicle and Ship Units
|
||||
if any(unit_type == u.dcs_unit_type for u in self.accessible_units):
|
||||
@@ -262,6 +270,12 @@ class Faction:
|
||||
|
||||
faction.unrestricted_satnav = json.get("unrestricted_satnav", False)
|
||||
|
||||
faction.weapons_introduction_year_overrides = json.get(
|
||||
"weapons_introduction_year_overrides", {}
|
||||
)
|
||||
|
||||
faction.countermeasures_available = json.get("countermeasures_available", True)
|
||||
|
||||
return faction
|
||||
|
||||
@property
|
||||
@@ -300,8 +314,11 @@ class Faction:
|
||||
self.remove_aircraft("Su-57")
|
||||
if not mod_settings.ov10a_bronco:
|
||||
self.remove_aircraft("Bronco-OV-10A")
|
||||
if not mod_settings.superhornet:
|
||||
self.remove_aircraft("Super-Hornet")
|
||||
if not mod_settings.fa18efg:
|
||||
self.remove_aircraft("FA_18E")
|
||||
self.remove_aircraft("FA_18F")
|
||||
self.remove_aircraft("EA_18G")
|
||||
|
||||
# frenchpack
|
||||
if not mod_settings.frenchpack:
|
||||
self.remove_vehicle("AMX10RCR")
|
||||
|
||||
@@ -15,15 +15,12 @@ if TYPE_CHECKING:
|
||||
|
||||
class WaypointAction(ABC):
|
||||
@abstractmethod
|
||||
def describe(self) -> str:
|
||||
...
|
||||
def describe(self) -> str: ...
|
||||
|
||||
@abstractmethod
|
||||
def update_state(
|
||||
self, state: ActionState, time: datetime, duration: timedelta
|
||||
) -> timedelta:
|
||||
...
|
||||
) -> timedelta: ...
|
||||
|
||||
@abstractmethod
|
||||
def iter_tasks(self, ctx: TaskContext) -> Iterator[Task]:
|
||||
...
|
||||
def iter_tasks(self, ctx: TaskContext) -> Iterator[Task]: ...
|
||||
|
||||
@@ -28,14 +28,12 @@ def point_at_heading(p: Point, heading: Heading, distance: Distance) -> Point:
|
||||
|
||||
class Prerequisite(ABC):
|
||||
@abstractmethod
|
||||
def is_satisfied(self) -> bool:
|
||||
...
|
||||
def is_satisfied(self) -> bool: ...
|
||||
|
||||
@abstractmethod
|
||||
def describe_debug_info(
|
||||
self, to_geojson: Callable[[BaseGeometry], dict[str, Any]]
|
||||
) -> dict[str, Any]:
|
||||
...
|
||||
) -> dict[str, Any]: ...
|
||||
|
||||
|
||||
class DistancePrerequisite(Prerequisite):
|
||||
|
||||
14
game/htn.py
14
game/htn.py
@@ -11,8 +11,7 @@ WorldStateT = TypeVar("WorldStateT", bound="WorldState[Any]")
|
||||
|
||||
class WorldState(ABC, Generic[WorldStateT]):
|
||||
@abstractmethod
|
||||
def clone(self) -> WorldStateT:
|
||||
...
|
||||
def clone(self) -> WorldStateT: ...
|
||||
|
||||
|
||||
class Task(Generic[WorldStateT]):
|
||||
@@ -24,18 +23,17 @@ Method = Sequence[Task[WorldStateT]]
|
||||
|
||||
class PrimitiveTask(Task[WorldStateT], Generic[WorldStateT], ABC):
|
||||
@abstractmethod
|
||||
def preconditions_met(self, state: WorldStateT) -> bool:
|
||||
...
|
||||
def preconditions_met(self, state: WorldStateT) -> bool: ...
|
||||
|
||||
@abstractmethod
|
||||
def apply_effects(self, state: WorldStateT) -> None:
|
||||
...
|
||||
def apply_effects(self, state: WorldStateT) -> None: ...
|
||||
|
||||
|
||||
class CompoundTask(Task[WorldStateT], Generic[WorldStateT], ABC):
|
||||
@abstractmethod
|
||||
def each_valid_method(self, state: WorldStateT) -> Iterator[Method[WorldStateT]]:
|
||||
...
|
||||
def each_valid_method(
|
||||
self, state: WorldStateT
|
||||
) -> Iterator[Method[WorldStateT]]: ...
|
||||
|
||||
|
||||
PrimitiveTaskT = TypeVar("PrimitiveTaskT", bound=PrimitiveTask[Any])
|
||||
|
||||
@@ -10,9 +10,11 @@ class Information:
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "[{}][{}] {} {}".format(
|
||||
self.timestamp.strftime("%Y-%m-%d %H:%M:%S")
|
||||
if self.timestamp is not None
|
||||
else "",
|
||||
(
|
||||
self.timestamp.strftime("%Y-%m-%d %H:%M:%S")
|
||||
if self.timestamp is not None
|
||||
else ""
|
||||
),
|
||||
self.turn,
|
||||
self.title,
|
||||
self.text,
|
||||
|
||||
@@ -9,9 +9,7 @@ if TYPE_CHECKING:
|
||||
|
||||
class ILaserCodeRegistry(ABC):
|
||||
@abstractmethod
|
||||
def alloc_laser_code(self) -> LaserCode:
|
||||
...
|
||||
def alloc_laser_code(self) -> LaserCode: ...
|
||||
|
||||
@abstractmethod
|
||||
def release_code(self, code: LaserCode) -> None:
|
||||
...
|
||||
def release_code(self, code: LaserCode) -> None: ...
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Logging APIs."""
|
||||
|
||||
import logging
|
||||
import logging.config
|
||||
import os
|
||||
|
||||
@@ -6,7 +6,7 @@ from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from dcs.flyingunit import FlyingUnit
|
||||
|
||||
from game.callsigns import create_group_callsign_from_unit
|
||||
from game.callsigns.callsign import create_group_callsign_from_unit
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.ato import FlightType, FlightWaypoint, Package
|
||||
|
||||
@@ -10,7 +10,8 @@ from dcs.unit import Skill
|
||||
from dcs.unitgroup import FlyingGroup
|
||||
|
||||
from game.ato import Flight, FlightType
|
||||
from game.callsigns import callsign_for_support_unit
|
||||
from game.callsigns.callsign import callsign_for_support_unit
|
||||
from game.callsigns.callsigngenerator import Callsign, FlightCallsignGenerator
|
||||
from game.data.weapons import Pylon
|
||||
from game.missiongenerator.logisticsgenerator import LogisticsGenerator
|
||||
from game.missiongenerator.missiondata import AwacsInfo, MissionData, TankerInfo
|
||||
@@ -115,6 +116,8 @@ class FlightGroupConfigurator:
|
||||
self.flight.flight_plan.waypoints,
|
||||
)
|
||||
|
||||
self.set_callsigns()
|
||||
|
||||
return FlightData(
|
||||
package=self.flight.package,
|
||||
aircraft_type=self.flight.unit_type,
|
||||
@@ -242,7 +245,11 @@ class FlightGroupConfigurator:
|
||||
|
||||
loadout = member.loadout
|
||||
if self.game.settings.restrict_weapons_by_date:
|
||||
loadout = loadout.degrade_for_date(self.flight.unit_type, self.game.date)
|
||||
loadout = loadout.degrade_for_date(
|
||||
self.flight.unit_type,
|
||||
self.game.date,
|
||||
self.flight.squadron.coalition.faction,
|
||||
)
|
||||
|
||||
for pylon_number, weapon in loadout.pylons.items():
|
||||
if weapon is None:
|
||||
@@ -269,3 +276,17 @@ class FlightGroupConfigurator:
|
||||
# our own tracking, so undo that.
|
||||
# https://github.com/pydcs/dcs/commit/303a81a8e0c778599fe136dd22cb2ae8123639a6
|
||||
unit.fuel = self.flight.unit_type.dcs_unit_type.fuel_max
|
||||
|
||||
def set_callsigns(self) -> None:
|
||||
if self.flight.callsign is None:
|
||||
return
|
||||
for unit_index, unit in enumerate(self.group.units):
|
||||
unit_callsign = self.flight.callsign.unit_callsign(unit_index + 1)
|
||||
if (
|
||||
unit_callsign.name is None
|
||||
): # pydcs needs unit.callsign to be set for eastern callsigns
|
||||
unit.callsign = str(unit_callsign) # type: ignore
|
||||
else: # Use western callsign
|
||||
unit.callsign_dict = unit_callsign.pydcs_dict(
|
||||
country=self.flight.country
|
||||
)
|
||||
|
||||
@@ -20,8 +20,14 @@ class AntiShipIngressBuilder(PydcsWaypointBuilder):
|
||||
group_names.append(target.name)
|
||||
elif isinstance(target, NavalControlPoint):
|
||||
carrier_name = target.get_carrier_group_name()
|
||||
if carrier_name:
|
||||
if carrier_name and self.mission.find_group(
|
||||
carrier_name
|
||||
): # Found a carrier, target it.
|
||||
group_names.append(carrier_name)
|
||||
else: # Could not find carrier/LHA, indicating it was sunk. Target other groups if present e.g. escorts.
|
||||
for ground_object in target.ground_objects:
|
||||
for group in ground_object.groups:
|
||||
group_names.append(group.group_name)
|
||||
else:
|
||||
logging.error(
|
||||
"Unexpected target type for anti-ship mission: %s",
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import List, TYPE_CHECKING, Tuple, Type
|
||||
|
||||
from dcs.mission import Mission, StartType
|
||||
from dcs.planes import IL_78M, KC130, KC135MPRS, KC_135, PlaneType
|
||||
from dcs.task import (
|
||||
AWACS,
|
||||
ActivateBeaconCommand,
|
||||
MainTask,
|
||||
Refueling,
|
||||
SetImmortalCommand,
|
||||
SetInvisibleCommand,
|
||||
)
|
||||
from dcs.unittype import UnitType
|
||||
|
||||
from game.ato import FlightType
|
||||
from game.callsigns import callsign_for_support_unit
|
||||
from game.naming import namegen
|
||||
from game.radio.radios import RadioRegistry
|
||||
from game.radio.tacan import TacanBand, TacanRegistry, TacanUsage
|
||||
from game.utils import Heading
|
||||
from .airconflictdescription import AirConflictDescription
|
||||
from .missiondata import AwacsInfo, MissionData, TankerInfo
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
|
||||
TANKER_DISTANCE = 15000
|
||||
TANKER_ALT = 4572
|
||||
TANKER_HEADING_OFFSET = 45
|
||||
|
||||
AWACS_DISTANCE = 150000
|
||||
AWACS_ALT = 13000
|
||||
|
||||
|
||||
class AirSupportGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
mission: Mission,
|
||||
conflict: AirConflictDescription,
|
||||
game: Game,
|
||||
radio_registry: RadioRegistry,
|
||||
tacan_registry: TacanRegistry,
|
||||
mission_data: MissionData,
|
||||
) -> None:
|
||||
self.mission = mission
|
||||
self.conflict = conflict
|
||||
self.game = game
|
||||
self.radio_registry = radio_registry
|
||||
self.tacan_registry = tacan_registry
|
||||
self.mission_data = mission_data
|
||||
|
||||
@classmethod
|
||||
def support_tasks(cls) -> List[Type[MainTask]]:
|
||||
return [Refueling, AWACS]
|
||||
|
||||
@staticmethod
|
||||
def _get_tanker_params(unit_type: Type[UnitType]) -> Tuple[int, int]:
|
||||
if unit_type is KC130:
|
||||
return TANKER_ALT - 500, 596
|
||||
elif unit_type is KC_135:
|
||||
return TANKER_ALT, 770
|
||||
elif unit_type is KC135MPRS:
|
||||
return TANKER_ALT + 500, 596
|
||||
return TANKER_ALT, 574
|
||||
|
||||
def generate(self) -> None:
|
||||
player_cp = (
|
||||
self.conflict.blue_cp
|
||||
if self.conflict.blue_cp.captured
|
||||
else self.conflict.red_cp
|
||||
)
|
||||
|
||||
country = self.mission.country(self.game.blue.country_name)
|
||||
|
||||
if not self.game.settings.disable_legacy_tanker:
|
||||
fallback_tanker_number = 0
|
||||
|
||||
for i, tanker_unit_type in enumerate(
|
||||
self.game.faction_for(player=True).tankers
|
||||
):
|
||||
unit_type = tanker_unit_type.dcs_unit_type
|
||||
if not issubclass(unit_type, PlaneType):
|
||||
logging.warning(f"Refueling aircraft {unit_type} must be a plane")
|
||||
continue
|
||||
|
||||
# TODO: Make loiter altitude a property of the unit type.
|
||||
alt, airspeed = self._get_tanker_params(tanker_unit_type.dcs_unit_type)
|
||||
freq = self.radio_registry.alloc_uhf()
|
||||
tacan = self.tacan_registry.alloc_for_band(
|
||||
TacanBand.Y, TacanUsage.AirToAir
|
||||
)
|
||||
tanker_heading = Heading.from_degrees(
|
||||
self.conflict.red_cp.position.heading_between_point(
|
||||
self.conflict.blue_cp.position
|
||||
)
|
||||
+ TANKER_HEADING_OFFSET * i
|
||||
)
|
||||
tanker_position = player_cp.position.point_from_heading(
|
||||
tanker_heading.degrees, TANKER_DISTANCE
|
||||
)
|
||||
tanker_group = self.mission.refuel_flight(
|
||||
country=country,
|
||||
name=namegen.next_tanker_name(country, tanker_unit_type),
|
||||
airport=None,
|
||||
plane_type=unit_type,
|
||||
position=tanker_position,
|
||||
altitude=alt,
|
||||
race_distance=58000,
|
||||
frequency=freq.mhz,
|
||||
start_type=StartType.Warm,
|
||||
speed=airspeed,
|
||||
tacanchannel=str(tacan),
|
||||
)
|
||||
tanker_group.set_frequency(freq.mhz)
|
||||
|
||||
callsign = callsign_for_support_unit(tanker_group)
|
||||
tacan_callsign = {
|
||||
"Texaco": "TEX",
|
||||
"Arco": "ARC",
|
||||
"Shell": "SHL",
|
||||
}.get(callsign)
|
||||
if tacan_callsign is None:
|
||||
# The dict above is all the callsigns currently in the game, but
|
||||
# non-Western countries don't use the callsigns and instead just
|
||||
# use numbers. It's possible that none of those nations have
|
||||
# TACAN compatible refueling aircraft, but fallback just in
|
||||
# case.
|
||||
tacan_callsign = f"TK{fallback_tanker_number}"
|
||||
fallback_tanker_number += 1
|
||||
|
||||
if tanker_unit_type != IL_78M:
|
||||
# Override PyDCS tacan channel.
|
||||
tanker_group.points[0].tasks.pop()
|
||||
tanker_group.points[0].tasks.append(
|
||||
ActivateBeaconCommand(
|
||||
tacan.number,
|
||||
tacan.band.value,
|
||||
tacan_callsign,
|
||||
True,
|
||||
tanker_group.units[0].id,
|
||||
True,
|
||||
)
|
||||
)
|
||||
|
||||
tanker_group.points[0].tasks.append(SetInvisibleCommand(True))
|
||||
tanker_group.points[0].tasks.append(SetImmortalCommand(True))
|
||||
|
||||
self.mission_data.tankers.append(
|
||||
TankerInfo(
|
||||
group_name=str(tanker_group.name),
|
||||
callsign=callsign,
|
||||
variant=tanker_unit_type.display_name,
|
||||
freq=freq,
|
||||
tacan=tacan,
|
||||
start_time=None,
|
||||
end_time=None,
|
||||
blue=True,
|
||||
)
|
||||
)
|
||||
|
||||
if not self.game.settings.disable_legacy_aewc:
|
||||
possible_awacs = [
|
||||
a
|
||||
for a in self.game.faction_for(player=True).aircrafts
|
||||
if a.capable_of(FlightType.AEWC)
|
||||
]
|
||||
|
||||
if not possible_awacs:
|
||||
logging.warning("No AWACS for faction")
|
||||
return
|
||||
|
||||
awacs_unit = possible_awacs[0]
|
||||
freq = self.radio_registry.alloc_uhf()
|
||||
|
||||
unit_type = awacs_unit.dcs_unit_type
|
||||
if not issubclass(unit_type, PlaneType):
|
||||
logging.warning(f"AWACS aircraft {unit_type} must be a plane")
|
||||
return
|
||||
|
||||
awacs_flight = self.mission.awacs_flight(
|
||||
country=country,
|
||||
name=namegen.next_awacs_name(country),
|
||||
plane_type=unit_type,
|
||||
altitude=AWACS_ALT,
|
||||
airport=None,
|
||||
position=self.conflict.center.random_point_within(
|
||||
AWACS_DISTANCE, AWACS_DISTANCE
|
||||
),
|
||||
frequency=freq.mhz,
|
||||
start_type=StartType.Warm,
|
||||
)
|
||||
awacs_flight.set_frequency(freq.mhz)
|
||||
|
||||
awacs_flight.points[0].tasks.append(SetInvisibleCommand(True))
|
||||
awacs_flight.points[0].tasks.append(SetImmortalCommand(True))
|
||||
|
||||
self.mission_data.awacs.append(
|
||||
AwacsInfo(
|
||||
group_name=str(awacs_flight.name),
|
||||
callsign=callsign_for_support_unit(awacs_flight),
|
||||
freq=freq,
|
||||
depature_location=None,
|
||||
start_time=None,
|
||||
end_time=None,
|
||||
blue=True,
|
||||
)
|
||||
)
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Briefing generation logic
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
@@ -16,7 +17,7 @@ from game.radio.radios import RadioFrequency
|
||||
from game.runways import RunwayData
|
||||
from game.theater import ControlPoint, FrontLine
|
||||
from .aircraft.flightdata import FlightData
|
||||
from .airsupportgenerator import AwacsInfo, TankerInfo
|
||||
from .missiondata import AwacsInfo, TankerInfo
|
||||
from .flotgenerator import JtacInfo
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@@ -27,7 +27,7 @@ from dcs.triggers import Event, TriggerOnce
|
||||
from dcs.unit import Skill, Vehicle
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
|
||||
from game.callsigns import callsign_for_support_unit
|
||||
from game.callsigns.callsign import callsign_for_support_unit
|
||||
from game.data.units import UnitClass
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
|
||||
@@ -22,6 +22,7 @@ https://forums.eagle.ru/showthread.php?t=206360 claims that kneeboard pages can
|
||||
only be added per airframe, so PvP missions where each side have the same
|
||||
aircraft will be able to see the enemy's kneeboard for the same airframe.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import math
|
||||
import textwrap
|
||||
@@ -46,7 +47,7 @@ from game.theater.bullseye import Bullseye
|
||||
from game.utils import Distance, UnitSystem, meters, mps, pounds
|
||||
from game.weather.weather import Weather
|
||||
from .aircraft.flightdata import FlightData
|
||||
from .airsupportgenerator import AwacsInfo, TankerInfo
|
||||
from .missiondata import AwacsInfo, TankerInfo
|
||||
from .briefinggenerator import CommInfo, JtacInfo, MissionInfoGenerator
|
||||
from ..ato import Package
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ from game.theater import Airfield
|
||||
from game.theater.bullseye import Bullseye
|
||||
from game.unitmap import UnitMap
|
||||
from .airconflictdescription import AirConflictDescription
|
||||
from .airsupportgenerator import AirSupportGenerator
|
||||
from .briefinggenerator import BriefingGenerator, MissionInfoGenerator
|
||||
from .cargoshipgenerator import CargoShipGenerator
|
||||
from .convoygenerator import ConvoyGenerator
|
||||
@@ -240,17 +239,6 @@ class MissionGenerator:
|
||||
def generate_air_units(self, tgo_generator: TgoGenerator) -> None:
|
||||
"""Generate the air units for the Operation"""
|
||||
|
||||
# Air Support (Tanker & Awacs)
|
||||
air_support_generator = AirSupportGenerator(
|
||||
self.mission,
|
||||
AirConflictDescription.for_theater(self.game.theater),
|
||||
self.game,
|
||||
self.radio_registry,
|
||||
self.tacan_registry,
|
||||
self.mission_data,
|
||||
)
|
||||
air_support_generator.generate()
|
||||
|
||||
# Generate Aircraft Activity on the map
|
||||
aircraft_generator = AircraftGenerator(
|
||||
self.mission,
|
||||
@@ -260,7 +248,7 @@ class MissionGenerator:
|
||||
self.radio_registry,
|
||||
self.tacan_registry,
|
||||
self.unit_map,
|
||||
mission_data=air_support_generator.mission_data,
|
||||
mission_data=self.mission_data,
|
||||
helipads=tgo_generator.helipads,
|
||||
)
|
||||
|
||||
@@ -286,7 +274,7 @@ class MissionGenerator:
|
||||
if not flight.client_units:
|
||||
continue
|
||||
flight.aircraft_type.assign_channels_for_flight(
|
||||
flight, air_support_generator.mission_data
|
||||
flight, self.mission_data
|
||||
)
|
||||
|
||||
self.mission_data.briefing_data = aircraft_generator.briefing_data
|
||||
|
||||
@@ -5,6 +5,7 @@ groups, statics, missile sites, and AA sites for the mission. Each of these
|
||||
objectives is defined in the Theater by a TheaterGroundObject. These classes
|
||||
create the pydcs groups and statics for those areas and add them to the mission.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
@@ -48,12 +48,10 @@ class PurchaseAdapter(Generic[ItemType]):
|
||||
return self.pending_delivery_quantity(item) < 0
|
||||
|
||||
@abstractmethod
|
||||
def current_quantity_of(self, item: ItemType) -> int:
|
||||
...
|
||||
def current_quantity_of(self, item: ItemType) -> int: ...
|
||||
|
||||
@abstractmethod
|
||||
def pending_delivery_quantity(self, item: ItemType) -> int:
|
||||
...
|
||||
def pending_delivery_quantity(self, item: ItemType) -> int: ...
|
||||
|
||||
def expected_quantity_next_turn(self, item: ItemType) -> int:
|
||||
return self.current_quantity_of(item) + self.pending_delivery_quantity(item)
|
||||
@@ -65,36 +63,28 @@ class PurchaseAdapter(Generic[ItemType]):
|
||||
return self.can_sell(item) or self.has_pending_orders(item)
|
||||
|
||||
@abstractmethod
|
||||
def can_sell(self, item: ItemType) -> bool:
|
||||
...
|
||||
def can_sell(self, item: ItemType) -> bool: ...
|
||||
|
||||
@abstractmethod
|
||||
def do_purchase(self, item: ItemType) -> None:
|
||||
...
|
||||
def do_purchase(self, item: ItemType) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
def do_cancel_purchase(self, item: ItemType) -> None:
|
||||
...
|
||||
def do_cancel_purchase(self, item: ItemType) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
def do_sale(self, item: ItemType) -> None:
|
||||
...
|
||||
def do_sale(self, item: ItemType) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
def do_cancel_sale(self, item: ItemType) -> None:
|
||||
...
|
||||
def do_cancel_sale(self, item: ItemType) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
def price_of(self, item: ItemType) -> int:
|
||||
...
|
||||
def price_of(self, item: ItemType) -> int: ...
|
||||
|
||||
@abstractmethod
|
||||
def name_of(self, item: ItemType, multiline: bool = False) -> str:
|
||||
...
|
||||
def name_of(self, item: ItemType, multiline: bool = False) -> str: ...
|
||||
|
||||
@abstractmethod
|
||||
def unit_type_of(self, item: ItemType) -> UnitType[Any]:
|
||||
...
|
||||
def unit_type_of(self, item: ItemType) -> UnitType[Any]: ...
|
||||
|
||||
|
||||
class AircraftPurchaseAdapter(PurchaseAdapter[Squadron]):
|
||||
|
||||
@@ -389,3 +389,64 @@ class WarthogChannelNamer(ChannelNamer):
|
||||
@classmethod
|
||||
def name(cls) -> str:
|
||||
return "a10c-ii"
|
||||
|
||||
|
||||
class PhantomChannelNamer(ChannelNamer):
|
||||
"""Channel namer for the F4-E."""
|
||||
|
||||
@staticmethod
|
||||
def channel_name(radio_id: int, channel_id: int) -> str:
|
||||
radio_name = [
|
||||
"COMM", # AN/ARC-164 COMM
|
||||
"AUX", # AN/ARC-164 AUX
|
||||
][radio_id - 1]
|
||||
return f"{radio_name} Ch {channel_id}"
|
||||
|
||||
@classmethod
|
||||
def name(cls) -> str:
|
||||
return "phantom"
|
||||
|
||||
|
||||
class HindChannelNamer(ChannelNamer):
|
||||
"""Channel namer for Mi-24 Hind"""
|
||||
|
||||
@staticmethod
|
||||
def channel_name(radio_id: int, channel_id: int) -> str:
|
||||
radio_name = [
|
||||
"R863",
|
||||
"R828",
|
||||
][radio_id - 1]
|
||||
return f"{radio_name} Ch {channel_id-1}"
|
||||
|
||||
@classmethod
|
||||
def name(cls) -> str:
|
||||
return "hind"
|
||||
|
||||
|
||||
class HipChannelNamer(ChannelNamer):
|
||||
"""Channel namer for Mi-8 Hip"""
|
||||
|
||||
@staticmethod
|
||||
def channel_name(radio_id: int, channel_id: int) -> str:
|
||||
radio_name = [
|
||||
"R863",
|
||||
"R828",
|
||||
][radio_id - 1]
|
||||
return f"{radio_name} Ch {channel_id}"
|
||||
|
||||
@classmethod
|
||||
def name(cls) -> str:
|
||||
return "hip"
|
||||
|
||||
|
||||
class KiowaChannelNamer(ChannelNamer):
|
||||
"""Channel namer for OH58D Kiowa Warrior"""
|
||||
|
||||
@staticmethod
|
||||
def channel_name(radio_id: int, channel_id: int) -> str:
|
||||
radio_name = ["UHF AM", "VHF AM", "VHF FM1", "VHF FM2"][radio_id - 1]
|
||||
return f"{radio_name} Ch {channel_id}"
|
||||
|
||||
@classmethod
|
||||
def name(cls) -> str:
|
||||
return "kiowa"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Radio frequency types and allocators."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
@@ -159,6 +160,7 @@ RADIOS: List[Radio] = [
|
||||
Radio("AN/ARC-164", (RadioRange(MHz(225), MHz(400), MHz(1), Modulation.AM),)),
|
||||
Radio("AN/ARC-186(V) AM", (RadioRange(MHz(116), MHz(152), MHz(1), Modulation.AM),)),
|
||||
Radio("AN/ARC-186(V) FM", (RadioRange(MHz(30), MHz(76), MHz(1), Modulation.FM),)),
|
||||
Radio("AN/ARC-201", (RadioRange(MHz(30), MHz(88), kHz(25), Modulation.FM),)),
|
||||
Radio(
|
||||
"AN/ARC-210",
|
||||
(
|
||||
@@ -185,6 +187,7 @@ RADIOS: List[Radio] = [
|
||||
),
|
||||
),
|
||||
Radio("AN/ARC-222", (RadioRange(MHz(116), MHz(152), MHz(1), Modulation.AM),)),
|
||||
Radio("AN/ARC-27", (RadioRange(MHz(225), MHz(400), kHz(100), Modulation.AM),)),
|
||||
Radio("SCR-522", (RadioRange(MHz(100), MHz(156), MHz(1), Modulation.AM),)),
|
||||
Radio("A.R.I. 1063", (RadioRange(MHz(100), MHz(156), MHz(1), Modulation.AM),)),
|
||||
Radio("BC-1206", (RadioRange(kHz(200), kHz(400), kHz(10), Modulation.AM),)),
|
||||
@@ -292,6 +295,9 @@ 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),)),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""TACAN channel handling."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Runway information and selection."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Tools for aiding in save compat removal after compatibility breaks."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import TypeVar
|
||||
|
||||
|
||||
@@ -89,6 +89,11 @@ def set_destination(
|
||||
detail=f"Cannot move {cp} more than "
|
||||
f"{cp.max_move_distance.nautical_miles}nm.",
|
||||
)
|
||||
if cp.is_fleet and not game.theater.is_in_sea(point):
|
||||
raise HTTPException(
|
||||
status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Cannot move naval control point {cp} onto land.",
|
||||
)
|
||||
cp.target_position = point
|
||||
from .. import EventStream
|
||||
|
||||
|
||||
@@ -28,6 +28,23 @@ class AutoAtoBehavior(Enum):
|
||||
Prefer = "Prefer player pilots"
|
||||
|
||||
|
||||
@unique
|
||||
class FastForwardStopCondition(Enum):
|
||||
DISABLED = "Fast forward disabled"
|
||||
FIRST_CONTACT = "First contact"
|
||||
PLAYER_TAKEOFF = "Player takeoff time"
|
||||
PLAYER_TAXI = "Player taxi time"
|
||||
PLAYER_STARTUP = "Player startup time"
|
||||
MANUAL = "Manual fast forward control"
|
||||
|
||||
|
||||
@unique
|
||||
class CombatResolutionMethod(Enum):
|
||||
PAUSE = "Pause simulation"
|
||||
RESOLVE = "Resolve combat"
|
||||
SKIP = "Skip combat"
|
||||
|
||||
|
||||
DIFFICULTY_PAGE = "Difficulty"
|
||||
|
||||
AI_DIFFICULTY_SECTION = "AI Difficulty"
|
||||
@@ -173,30 +190,6 @@ class Settings:
|
||||
"extremely incomplete so does not affect all weapons."
|
||||
),
|
||||
)
|
||||
disable_legacy_aewc: bool = boolean_option(
|
||||
"Spawn invulnerable, always-available AEW&C aircraft (deprecated)",
|
||||
page=CAMPAIGN_MANAGEMENT_PAGE,
|
||||
section=GENERAL_SECTION,
|
||||
default=True,
|
||||
invert=True,
|
||||
detail=(
|
||||
"If checked, an invulnerable friendly AEW&C aircraft that begins the "
|
||||
"mission on station will be be spawned. This behavior will be removed in a "
|
||||
"future release."
|
||||
),
|
||||
)
|
||||
disable_legacy_tanker: bool = boolean_option(
|
||||
"Spawn invulnerable, always-available tanker aircraft (deprecated)",
|
||||
page=CAMPAIGN_MANAGEMENT_PAGE,
|
||||
section=GENERAL_SECTION,
|
||||
default=True,
|
||||
invert=True,
|
||||
detail=(
|
||||
"If checked, an invulnerable friendly tanker aircraft that begins the "
|
||||
"mission on station will be be spawned. This behavior will be removed in a "
|
||||
"future release."
|
||||
),
|
||||
)
|
||||
# Pilots and Squadrons
|
||||
ai_pilot_levelling: bool = boolean_option(
|
||||
"Allow AI pilot leveling",
|
||||
@@ -317,7 +310,7 @@ class Settings:
|
||||
"Tactical commander",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
section=COMMANDERS_SECTION,
|
||||
default=1,
|
||||
default=0,
|
||||
min=0,
|
||||
max=100,
|
||||
)
|
||||
@@ -333,7 +326,7 @@ class Settings:
|
||||
"Observer",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
section=COMMANDERS_SECTION,
|
||||
default=1,
|
||||
default=0,
|
||||
min=0,
|
||||
max=100,
|
||||
)
|
||||
@@ -351,19 +344,6 @@ class Settings:
|
||||
"run out of fuel when players would not."
|
||||
),
|
||||
)
|
||||
fast_forward_to_first_contact: bool = boolean_option(
|
||||
"Fast forward mission to first contact (WIP)",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
section=GAMEPLAY_SECTION,
|
||||
default=False,
|
||||
detail=(
|
||||
"If enabled, the mission will be generated at the point of first contact. "
|
||||
"If you enable this option, you will not be able to create new flights "
|
||||
'after pressing "TAKE OFF". Doing so will create an error the next time '
|
||||
'you press "TAKE OFF". Save your game first if you want to make '
|
||||
"modifications."
|
||||
),
|
||||
)
|
||||
reload_pre_sim_checkpoint_on_abort: bool = boolean_option(
|
||||
"Reset mission to pre-take off conditions on abort",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
@@ -375,37 +355,44 @@ class Settings:
|
||||
"your game after aborting take off."
|
||||
),
|
||||
)
|
||||
player_mission_interrupts_sim_at: Optional[StartType] = choices_option(
|
||||
"Player missions interrupt fast forward",
|
||||
fast_forward_stop_condition: FastForwardStopCondition = choices_option(
|
||||
"Fast forward until",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
section=GAMEPLAY_SECTION,
|
||||
default=None,
|
||||
default=FastForwardStopCondition.DISABLED,
|
||||
choices={
|
||||
"Never": None,
|
||||
"At startup time": StartType.COLD,
|
||||
"At taxi time": StartType.WARM,
|
||||
"At takeoff time": StartType.RUNWAY,
|
||||
"No fast forward": FastForwardStopCondition.DISABLED,
|
||||
"Player startup time": FastForwardStopCondition.PLAYER_STARTUP,
|
||||
"Player taxi time": FastForwardStopCondition.PLAYER_TAXI,
|
||||
"Player takeoff time": FastForwardStopCondition.PLAYER_TAKEOFF,
|
||||
"First contact": FastForwardStopCondition.FIRST_CONTACT,
|
||||
"Manual": FastForwardStopCondition.MANUAL,
|
||||
},
|
||||
detail=(
|
||||
"Determines what player mission states will interrupt fast-forwarding to "
|
||||
"first contact, if enabled. If never is selected player missions will not "
|
||||
"impact simulation and player missions may be generated mid-flight. The "
|
||||
"other options will cause the mission to be generated as soon as a player "
|
||||
"mission reaches the set state or at first contact, whichever comes first."
|
||||
"Determines when fast forwarding stops: "
|
||||
"No fast forward: disables fast forward. "
|
||||
"Player startup time: fast forward until player startup time. "
|
||||
"Player taxi time: fast forward until player taxi time. "
|
||||
"Player takeoff time: fast forward until player takeoff time. "
|
||||
"First contact: fast forward until first contact between blue and red units. "
|
||||
"Manual: manually control fast forward. Show manual controls with --show-sim-speed-controls."
|
||||
),
|
||||
)
|
||||
auto_resolve_combat: bool = boolean_option(
|
||||
"Auto-resolve combat during fast-forward (WIP)",
|
||||
combat_resolution_method: CombatResolutionMethod = choices_option(
|
||||
"Resolve combat when fast forwarding by",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
section=GAMEPLAY_SECTION,
|
||||
default=False,
|
||||
default=CombatResolutionMethod.PAUSE,
|
||||
choices={
|
||||
"Pause": CombatResolutionMethod.PAUSE,
|
||||
"Resolving combat (WIP)": CombatResolutionMethod.RESOLVE,
|
||||
"Skipping combat": CombatResolutionMethod.SKIP,
|
||||
},
|
||||
detail=(
|
||||
'Requires a "Player missions interrupt fast forward" setting other than '
|
||||
'"Never" If enabled, aircraft entering combat during fast forward will have'
|
||||
"their combat auto-resolved after a period of time. This allows the "
|
||||
"simulation to advance further into the mission before requiring mission "
|
||||
"generation, but simulation is currently very rudimentary so may result in "
|
||||
"huge losses."
|
||||
"Determines what happens when combat occurs when fast forwarding. "
|
||||
"Pause: pause fast forward and generate mission. Fast forwarding may stop before the condition specified in the above setting. "
|
||||
"Resolving combat (WIP): auto resolve combat. This method is very rudimentary and will result in large losses. "
|
||||
"Skipping combat: skip combat as if it did not occur."
|
||||
),
|
||||
)
|
||||
supercarrier: bool = boolean_option(
|
||||
@@ -467,6 +454,12 @@ class Settings:
|
||||
default=timedelta(minutes=60),
|
||||
min=30,
|
||||
max=150,
|
||||
detail=(
|
||||
"Period of time after the start of a turn where "
|
||||
"there is coverage by one or more CAP flight(s), "
|
||||
"refuelling flights not tied to a specific package are on station, "
|
||||
"and other flights have their TOTs."
|
||||
),
|
||||
)
|
||||
|
||||
# Performance
|
||||
|
||||
10
game/sidc.py
10
game/sidc.py
@@ -10,6 +10,7 @@ from the output.
|
||||
https://nso.nato.int/nso/nsdd/main/standards/ap-details/1912/EN
|
||||
https://www.spatialillusions.com/milsymbol/docs/milsymbol-APP6d.html
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
@@ -330,18 +331,15 @@ class SymbolIdentificationCode:
|
||||
class SidcDescribable(ABC):
|
||||
@property
|
||||
@abstractmethod
|
||||
def standard_identity(self) -> StandardIdentity:
|
||||
...
|
||||
def standard_identity(self) -> StandardIdentity: ...
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def sidc_status(self) -> Status:
|
||||
...
|
||||
def sidc_status(self) -> Status: ...
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def symbol_set_and_entity(self) -> tuple[SymbolSet, Entity]:
|
||||
...
|
||||
def symbol_set_and_entity(self) -> tuple[SymbolSet, Entity]: ...
|
||||
|
||||
def sidc(self) -> SymbolIdentificationCode:
|
||||
symbol_set, entity = self.symbol_set_and_entity
|
||||
|
||||
@@ -10,6 +10,7 @@ from typing_extensions import TYPE_CHECKING
|
||||
from game.ato.flightstate import (
|
||||
Uninitialized,
|
||||
)
|
||||
from game.settings.settings import FastForwardStopCondition, CombatResolutionMethod
|
||||
from .combat import CombatInitiator, FrozenCombat
|
||||
from .gameupdateevents import GameUpdateEvents
|
||||
from .simulationresults import SimulationResults
|
||||
@@ -32,7 +33,7 @@ class AircraftSimulation:
|
||||
def on_game_tick(
|
||||
self, events: GameUpdateEvents, time: datetime, duration: timedelta
|
||||
) -> None:
|
||||
if not self.game.settings.auto_resolve_combat 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"
|
||||
@@ -42,7 +43,13 @@ class AircraftSimulation:
|
||||
|
||||
still_active = []
|
||||
for combat in self.combats:
|
||||
if combat.on_game_tick(time, duration, self.results, events):
|
||||
if combat.on_game_tick(
|
||||
time,
|
||||
duration,
|
||||
self.results,
|
||||
events,
|
||||
self.game.settings.combat_resolution_method,
|
||||
):
|
||||
events.end_combat(combat)
|
||||
else:
|
||||
still_active.append(combat)
|
||||
@@ -61,7 +68,7 @@ class AircraftSimulation:
|
||||
events.complete_simulation()
|
||||
return
|
||||
|
||||
if not self.game.settings.auto_resolve_combat and self.combats:
|
||||
if not self._auto_resolve_combat() and self.combats:
|
||||
events.complete_simulation()
|
||||
|
||||
def set_initial_flight_states(self) -> None:
|
||||
@@ -80,3 +87,11 @@ class AircraftSimulation:
|
||||
)
|
||||
for package in packages:
|
||||
yield from package.flights
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING
|
||||
from shapely.ops import unary_union
|
||||
|
||||
from game.ato.flightstate import InCombat, InFlight
|
||||
from game.settings.settings import CombatResolutionMethod
|
||||
from game.utils import dcs_to_shapely_point
|
||||
from .joinablecombat import JoinableCombat
|
||||
from .. import GameUpdateEvents
|
||||
@@ -67,7 +68,15 @@ class AirCombat(JoinableCombat):
|
||||
events: GameUpdateEvents,
|
||||
time: datetime,
|
||||
elapsed_time: timedelta,
|
||||
resolution_method: CombatResolutionMethod,
|
||||
) -> None:
|
||||
|
||||
if resolution_method is CombatResolutionMethod.SKIP:
|
||||
for flight in self.flights:
|
||||
assert isinstance(flight.state, InCombat)
|
||||
flight.state.exit_combat(events, time, elapsed_time)
|
||||
return
|
||||
|
||||
blue = []
|
||||
red = []
|
||||
for flight in self.flights:
|
||||
|
||||
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING
|
||||
from .frozencombat import FrozenCombat
|
||||
from .. import GameUpdateEvents
|
||||
from ...ato.flightstate import InCombat
|
||||
from game.settings.settings import CombatResolutionMethod
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.ato import Flight
|
||||
@@ -34,6 +35,7 @@ class AtIp(FrozenCombat):
|
||||
events: GameUpdateEvents,
|
||||
time: datetime,
|
||||
elapsed_time: timedelta,
|
||||
resolution_method: CombatResolutionMethod,
|
||||
) -> None:
|
||||
logging.debug(
|
||||
f"{self.flight} attack on {self.flight.package.target} auto-resolved with "
|
||||
|
||||
@@ -7,6 +7,7 @@ from datetime import datetime, timedelta
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from game.ato.flightstate import InCombat
|
||||
from game.settings.settings import CombatResolutionMethod
|
||||
from .frozencombat import FrozenCombat
|
||||
from .. import GameUpdateEvents
|
||||
|
||||
@@ -43,8 +44,14 @@ class DefendingSam(FrozenCombat):
|
||||
events: GameUpdateEvents,
|
||||
time: datetime,
|
||||
elapsed_time: timedelta,
|
||||
resolution_method: CombatResolutionMethod,
|
||||
) -> None:
|
||||
assert isinstance(self.flight.state, InCombat)
|
||||
|
||||
if resolution_method is CombatResolutionMethod.SKIP:
|
||||
self.flight.state.exit_combat(events, time, elapsed_time)
|
||||
return
|
||||
|
||||
if random.random() >= 0.5:
|
||||
logging.debug(f"Air defense combat auto-resolved with {self.flight} lost")
|
||||
self.flight.kill(results, events)
|
||||
|
||||
@@ -7,6 +7,7 @@ from datetime import datetime, timedelta
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from game.ato.flightstate import InCombat, InFlight
|
||||
from game.settings.settings import CombatResolutionMethod
|
||||
from .. import GameUpdateEvents
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -26,10 +27,11 @@ class FrozenCombat(ABC):
|
||||
duration: timedelta,
|
||||
results: SimulationResults,
|
||||
events: GameUpdateEvents,
|
||||
resolution_method: CombatResolutionMethod,
|
||||
) -> bool:
|
||||
self.elapsed_time += duration
|
||||
if self.elapsed_time >= self.freeze_duration:
|
||||
self.resolve(results, events, time, self.elapsed_time)
|
||||
self.resolve(results, events, time, self.elapsed_time, resolution_method)
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -40,20 +42,17 @@ class FrozenCombat(ABC):
|
||||
events: GameUpdateEvents,
|
||||
time: datetime,
|
||||
elapsed_time: timedelta,
|
||||
) -> None:
|
||||
...
|
||||
resolution_method: CombatResolutionMethod,
|
||||
) -> None: ...
|
||||
|
||||
@abstractmethod
|
||||
def because(self) -> str:
|
||||
...
|
||||
def because(self) -> str: ...
|
||||
|
||||
@abstractmethod
|
||||
def describe(self) -> str:
|
||||
...
|
||||
def describe(self) -> str: ...
|
||||
|
||||
@abstractmethod
|
||||
def iter_flights(self) -> Iterator[Flight]:
|
||||
...
|
||||
def iter_flights(self) -> Iterator[Flight]: ...
|
||||
|
||||
def update_flight_states(self) -> None:
|
||||
for flight in self.iter_flights():
|
||||
|
||||
@@ -18,8 +18,7 @@ class JoinableCombat(FrozenCombat, ABC):
|
||||
self.flights = flights
|
||||
|
||||
@abstractmethod
|
||||
def joinable_by(self, flight: Flight) -> bool:
|
||||
...
|
||||
def joinable_by(self, flight: Flight) -> bool: ...
|
||||
|
||||
def join(self, flight: Flight) -> None:
|
||||
assert isinstance(flight.state, InFlight)
|
||||
|
||||
@@ -65,7 +65,7 @@ class GameLoop:
|
||||
self.start()
|
||||
logging.info("Running sim to first contact")
|
||||
while not self.completed:
|
||||
self.tick(suppress_events=True)
|
||||
self.tick(suppress_events=False)
|
||||
|
||||
def pause_and_generate_miz(self, output: Path) -> None:
|
||||
self.pause()
|
||||
|
||||
@@ -34,6 +34,7 @@ class MissionResultsProcessor:
|
||||
self.commit_damaged_runways(debriefing)
|
||||
self.commit_captures(debriefing, events)
|
||||
self.commit_front_line_battle_impact(debriefing, events)
|
||||
self.commit_unit_damage(debriefing)
|
||||
self.record_carcasses(debriefing)
|
||||
|
||||
def commit_air_losses(self, debriefing: Debriefing) -> None:
|
||||
@@ -307,42 +308,52 @@ class MissionResultsProcessor:
|
||||
f"{enemy_cp.name}. {status_msg}",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def commit_unit_damage(debriefing: Debriefing) -> None:
|
||||
for damaged_unit in debriefing.unit_hit_point_update_events():
|
||||
logging.info(
|
||||
f"{damaged_unit.unit.theater_unit.name} damaged, setting hit points to {damaged_unit.hit_points}"
|
||||
)
|
||||
damaged_unit.commit()
|
||||
|
||||
def redeploy_units(self, cp: ControlPoint) -> None:
|
||||
""" "
|
||||
Auto redeploy units to newly captured base
|
||||
"""
|
||||
# Find the set of friendly CPs that can either contribute or receive frontline units
|
||||
all_ally_connected_cps = cp.transitive_connected_friendly_points() + [cp]
|
||||
|
||||
ally_connected_cps = [
|
||||
ocp for ocp in cp.connected_points if cp.captured == ocp.captured
|
||||
]
|
||||
enemy_connected_cps = [
|
||||
ocp for ocp in cp.connected_points if cp.captured != ocp.captured
|
||||
]
|
||||
# Split into frontline CPs that are connected to enemy CPs and should receive units
|
||||
# vs. non-frontline CPs that are not connected to enemy CPs and should send units.
|
||||
frontline_cps = []
|
||||
non_frontline_cps = []
|
||||
for cp in all_ally_connected_cps:
|
||||
is_frontline = False
|
||||
for ocp in cp.connected_points:
|
||||
if not ocp.captured:
|
||||
is_frontline = True
|
||||
break
|
||||
if is_frontline:
|
||||
frontline_cps.append(cp)
|
||||
else:
|
||||
non_frontline_cps.append(cp)
|
||||
|
||||
# If the newly captured cp does not have enemy connected cp,
|
||||
# then it is not necessary to redeploy frontline units there.
|
||||
if len(enemy_connected_cps) == 0:
|
||||
# If there are no frontline CPs, then nothing to do.
|
||||
if len(frontline_cps) == 0:
|
||||
return
|
||||
|
||||
# From each ally cp, send reinforcements
|
||||
for ally_cp in ally_connected_cps:
|
||||
self.redeploy_between(cp, ally_cp)
|
||||
# Equally split between all frontline CPs
|
||||
move_factor = 1.0 / len(frontline_cps)
|
||||
for non_frontline_cp in non_frontline_cps:
|
||||
for frontline_cp in frontline_cps:
|
||||
self.redeploy_between(frontline_cp, non_frontline_cp, move_factor)
|
||||
|
||||
def redeploy_between(self, destination: ControlPoint, source: ControlPoint) -> None:
|
||||
def redeploy_between(
|
||||
self, destination: ControlPoint, source: ControlPoint, move_factor: float
|
||||
) -> None:
|
||||
total_units_redeployed = 0
|
||||
moved_units = {}
|
||||
|
||||
if source.has_active_frontline or not destination.captured:
|
||||
# If there are still active front lines to defend at the
|
||||
# transferring CP we should not transfer all units.
|
||||
#
|
||||
# Opfor also does not transfer all of their units.
|
||||
# TODO: Balance the CPs rather than moving half from everywhere.
|
||||
move_factor = 0.5
|
||||
else:
|
||||
# Otherwise we can move everything.
|
||||
move_factor = 1
|
||||
|
||||
for frontline_unit, count in source.base.armor.items():
|
||||
moved_units[frontline_unit] = int(count * move_factor)
|
||||
total_units_redeployed = total_units_redeployed + int(count * move_factor)
|
||||
|
||||
@@ -472,8 +472,7 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def heading(self) -> Heading:
|
||||
...
|
||||
def heading(self) -> Heading: ...
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
@@ -594,8 +593,7 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def can_deploy_ground_units(self) -> bool:
|
||||
...
|
||||
def can_deploy_ground_units(self) -> bool: ...
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
@@ -764,6 +762,9 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
|
||||
def aircraft_retreat_destination(
|
||||
self, squadron: Squadron
|
||||
) -> Optional[ControlPoint]:
|
||||
if not self.runway_is_operational():
|
||||
return None
|
||||
|
||||
closest = ObjectiveDistanceCache.get_closest_airfields(self)
|
||||
max_retreat_distance = squadron.aircraft.max_mission_range
|
||||
# Skip the first airbase because that's the airbase we're retreating
|
||||
@@ -877,8 +878,7 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
|
||||
return None
|
||||
|
||||
@abstractmethod
|
||||
def can_operate(self, aircraft: AircraftType) -> bool:
|
||||
...
|
||||
def can_operate(self, aircraft: AircraftType) -> bool: ...
|
||||
|
||||
def unclaimed_parking(self) -> int:
|
||||
return self.total_aircraft_parking - self.allocated_aircraft().total
|
||||
@@ -889,8 +889,7 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
|
||||
theater: ConflictTheater,
|
||||
conditions: Conditions,
|
||||
dynamic_runways: Dict[str, RunwayData],
|
||||
) -> RunwayData:
|
||||
...
|
||||
) -> RunwayData: ...
|
||||
|
||||
def stub_runway_data(self) -> RunwayData:
|
||||
return RunwayData(
|
||||
@@ -907,13 +906,11 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def runway_is_destroyable(self) -> bool:
|
||||
...
|
||||
def runway_is_destroyable(self) -> bool: ...
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def runway_status(self) -> RunwayStatus:
|
||||
...
|
||||
def runway_status(self) -> RunwayStatus: ...
|
||||
|
||||
@abstractmethod
|
||||
def describe_runway_status(self) -> str | None:
|
||||
@@ -1071,13 +1068,11 @@ class ControlPoint(MissionTarget, SidcDescribable, ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def category(self) -> str:
|
||||
...
|
||||
def category(self) -> str: ...
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def status(self) -> ControlPointStatus:
|
||||
...
|
||||
def status(self) -> ControlPointStatus: ...
|
||||
|
||||
|
||||
class Airfield(ControlPoint):
|
||||
@@ -1283,7 +1278,10 @@ class NavalControlPoint(ControlPoint, ABC):
|
||||
return RunwayStatus(damaged=not self.runway_is_operational())
|
||||
|
||||
def describe_runway_status(self) -> str:
|
||||
return f"Flight deck {self.runway_status.describe()}"
|
||||
if self.runway_is_operational():
|
||||
return f"Flight deck {self.runway_status.describe()}"
|
||||
# Special handling for not operational carriers/LHAs
|
||||
return f"Sunk"
|
||||
|
||||
@property
|
||||
def runway_can_be_repaired(self) -> bool:
|
||||
|
||||
@@ -107,7 +107,7 @@ class FrontLine(MissionTarget):
|
||||
yield from [
|
||||
FlightType.CAS,
|
||||
FlightType.AEWC,
|
||||
FlightType.REFUELING
|
||||
FlightType.REFUELING,
|
||||
# TODO: FlightType.TROOP_TRANSPORT
|
||||
# TODO: FlightType.EVAC
|
||||
]
|
||||
|
||||
@@ -66,7 +66,7 @@ class ModSettings:
|
||||
frenchpack: bool = False
|
||||
high_digit_sams: bool = False
|
||||
ov10a_bronco: bool = False
|
||||
superhornet: bool = False
|
||||
fa18efg: bool = False
|
||||
|
||||
def save_player_settings(self) -> None:
|
||||
"""Saves the player's global settings to the user directory."""
|
||||
|
||||
@@ -35,6 +35,8 @@ class TheaterUnit:
|
||||
position: PointWithHeading
|
||||
# The parent ground object
|
||||
ground_object: TheaterGroundObject
|
||||
# Number of hit points the unit has
|
||||
hit_points: Optional[int] = None
|
||||
# State of the unit, dead or alive
|
||||
alive: bool = True
|
||||
|
||||
@@ -42,13 +44,17 @@ class TheaterUnit:
|
||||
def from_template(
|
||||
id: int, dcs_type: Type[DcsUnitType], t: LayoutUnit, go: TheaterGroundObject
|
||||
) -> TheaterUnit:
|
||||
return TheaterUnit(
|
||||
unit = TheaterUnit(
|
||||
id,
|
||||
t.name,
|
||||
dcs_type,
|
||||
PointWithHeading.from_point(t.position, Heading.from_degrees(t.heading)),
|
||||
go,
|
||||
)
|
||||
# if the TheaterUnit represents a GroundUnitType or ShipUnitType, initialize health to full hit points
|
||||
if unit.unit_type is not None:
|
||||
unit.hit_points = unit.unit_type.hit_points
|
||||
return unit
|
||||
|
||||
@property
|
||||
def unit_type(self) -> Optional[UnitType[Any]]:
|
||||
@@ -70,14 +76,12 @@ class TheaterUnit:
|
||||
|
||||
@property
|
||||
def display_name(self) -> str:
|
||||
dead_label = " [DEAD]" if not self.alive else ""
|
||||
unit_label = self.unit_type or self.type.name or self.name
|
||||
return f"{str(self.id).zfill(4)} | {unit_label}{dead_label}"
|
||||
return f"{str(self.id).zfill(4)} | {unit_label}{self._status_label()}"
|
||||
|
||||
@property
|
||||
def short_name(self) -> str:
|
||||
dead_label = " [DEAD]" if not self.alive else ""
|
||||
return f"<b>{self.type.id[0:18]}</b> {dead_label}"
|
||||
return f"<b>{self.type.id[0:18]}</b> {self._status_label()}"
|
||||
|
||||
@property
|
||||
def is_static(self) -> bool:
|
||||
@@ -117,6 +121,18 @@ class TheaterUnit:
|
||||
unit_range = getattr(self.type, "threat_range", None)
|
||||
return meters(unit_range if unit_range is not None and self.alive else 0)
|
||||
|
||||
def _status_label(self) -> str:
|
||||
if not self.alive:
|
||||
return " [DEAD]"
|
||||
if self.unit_type is None:
|
||||
return ""
|
||||
if self.hit_points is None:
|
||||
return ""
|
||||
if self.unit_type.hit_points == self.hit_points:
|
||||
return ""
|
||||
damage_percentage = 100 - int(100 * self.hit_points / self.unit_type.hit_points)
|
||||
return f" [DAMAGED {damage_percentage}%]"
|
||||
|
||||
|
||||
class SceneryUnit(TheaterUnit):
|
||||
"""Special TheaterUnit for handling scenery ground objects"""
|
||||
|
||||
@@ -8,7 +8,7 @@ from enum import Enum, auto
|
||||
from typing import Dict, Iterator, List, Optional, Set, Tuple
|
||||
|
||||
from .conflicttheater import ConflictTheater
|
||||
from .controlpoint import ControlPoint
|
||||
from .controlpoint import ControlPoint, ControlPointType
|
||||
|
||||
|
||||
class NoPathError(RuntimeError):
|
||||
@@ -47,9 +47,9 @@ class TransitConnection(Enum):
|
||||
|
||||
class TransitNetwork:
|
||||
def __init__(self) -> None:
|
||||
self.nodes: Dict[
|
||||
ControlPoint, Dict[ControlPoint, TransitConnection]
|
||||
] = defaultdict(dict)
|
||||
self.nodes: Dict[ControlPoint, Dict[ControlPoint, TransitConnection]] = (
|
||||
defaultdict(dict)
|
||||
)
|
||||
|
||||
def has_destinations(self, control_point: ControlPoint) -> bool:
|
||||
return bool(self.nodes[control_point])
|
||||
@@ -160,7 +160,14 @@ class TransitNetworkBuilder:
|
||||
self.airports: Set[ControlPoint] = {
|
||||
cp
|
||||
for cp in self.control_points
|
||||
if cp.is_friendly(for_player) and cp.runway_is_operational()
|
||||
if cp.is_friendly(for_player)
|
||||
and cp.runway_is_operational()
|
||||
and cp.cptype
|
||||
not in [
|
||||
ControlPointType.LHA_GROUP,
|
||||
ControlPointType.AIRCRAFT_CARRIER_GROUP,
|
||||
ControlPointType.OFF_MAP,
|
||||
] # TransitNetwork is for ground units, so do not consider LHAs, CVNs or off map spawns.
|
||||
}
|
||||
|
||||
def build(self) -> TransitNetwork:
|
||||
|
||||
@@ -29,6 +29,7 @@ transports and processing the turn's transit actions.
|
||||
|
||||
Routing is handled by TransitNetwork.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
@@ -494,9 +495,9 @@ TransportType = TypeVar("TransportType", bound=MultiGroupTransport)
|
||||
class TransportMap(Generic[TransportType]):
|
||||
def __init__(self) -> None:
|
||||
# Dict of origin -> destination -> transport.
|
||||
self.transports: dict[
|
||||
ControlPoint, dict[ControlPoint, TransportType]
|
||||
] = defaultdict(dict)
|
||||
self.transports: dict[ControlPoint, dict[ControlPoint, TransportType]] = (
|
||||
defaultdict(dict)
|
||||
)
|
||||
|
||||
def create_transport(
|
||||
self, origin: ControlPoint, destination: ControlPoint
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Maps generated units back to their Liberation types."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
MAJOR_VERSION = 11
|
||||
MINOR_VERSION = 0
|
||||
MAJOR_VERSION = 12
|
||||
MINOR_VERSION = 1
|
||||
MICRO_VERSION = 0
|
||||
VERSION_NUMBER = ".".join(str(v) for v in (MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION))
|
||||
|
||||
|
||||
@@ -101,8 +101,7 @@ class Weather(ABC):
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def archetype(self) -> WeatherArchetype:
|
||||
...
|
||||
def archetype(self) -> WeatherArchetype: ...
|
||||
|
||||
@property
|
||||
def pressure_adjustment(self) -> float:
|
||||
|
||||
@@ -25,8 +25,7 @@ class WeibullWindSpeedParameters:
|
||||
|
||||
class WindSpeedGenerator(ABC):
|
||||
@abstractmethod
|
||||
def random_wind(self) -> WindConditions:
|
||||
...
|
||||
def random_wind(self) -> WindConditions: ...
|
||||
|
||||
@staticmethod
|
||||
def from_data(data: dict[str, Any]) -> WindSpeedGenerator:
|
||||
|
||||
@@ -9,6 +9,7 @@ from .jas39 import *
|
||||
from .ov10a import *
|
||||
from .su57 import *
|
||||
from .uh60l import *
|
||||
from .fa18efg import *
|
||||
|
||||
|
||||
def load_mods() -> None:
|
||||
|
||||
@@ -940,63 +940,63 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
1,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
1,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
1,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
1,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
1,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU3_WP61 = (1, Weapons.LAU3_WP61)
|
||||
LAU3_WP1B = (1, Weapons.LAU3_WP1B)
|
||||
@@ -1004,7 +1004,7 @@ class A_4E_C(PlaneType):
|
||||
LAU3_WP156 = (1, Weapons.LAU3_WP156)
|
||||
LAU3_HE151 = (1, Weapons.LAU3_HE151)
|
||||
AGM_45A_Shrike_ARM = (1, Weapons.AGM_45A_Shrike_ARM)
|
||||
AGM_45B_Shrike_ARM__Imp_ = (1, Weapons.AGM_45B_Shrike_ARM__Imp_)
|
||||
AGM_45B_Shrike_ARM = (1, Weapons.AGM_45B_Shrike_ARM)
|
||||
Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
1,
|
||||
Weapons.Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets,
|
||||
@@ -1069,15 +1069,15 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
2,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
2,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
2,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
_2_x_LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts__M156__Wht_Phos__TER__ = (
|
||||
2,
|
||||
@@ -1093,15 +1093,15 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
_2_x_LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts__M156__Wht_Phos__TER__ = (
|
||||
2,
|
||||
@@ -1117,35 +1117,35 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE__TER__ = (
|
||||
2,
|
||||
@@ -1181,7 +1181,7 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
2,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_MK_71__HE_FRAG__TER__ = (
|
||||
2,
|
||||
@@ -1213,7 +1213,7 @@ class A_4E_C(PlaneType):
|
||||
WeaponsA4EC._2_x_LAU_3_pod___19_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice__TER__,
|
||||
)
|
||||
AGM_45A_Shrike_ARM = (2, Weapons.AGM_45A_Shrike_ARM)
|
||||
AGM_45B_Shrike_ARM__Imp_ = (2, Weapons.AGM_45B_Shrike_ARM__Imp_)
|
||||
AGM_45B_Shrike_ARM = (2, Weapons.AGM_45B_Shrike_ARM)
|
||||
Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
2,
|
||||
Weapons.Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets,
|
||||
@@ -1329,15 +1329,15 @@ class A_4E_C(PlaneType):
|
||||
Fuel_Tank_150_gallons__EMPTY_ = (3, WeaponsA4EC.Fuel_Tank_150_gallons__EMPTY_)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
3,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
3,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
3,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
_2_x_LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts__M156__Wht_Phos__TER_ = (
|
||||
3,
|
||||
@@ -1365,15 +1365,15 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
_2_x_LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts__M156__Wht_Phos__TER_ = (
|
||||
3,
|
||||
@@ -1405,43 +1405,43 @@ class A_4E_C(PlaneType):
|
||||
LAU3_WP1B = (3, Weapons.LAU3_WP1B)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
3,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE__TER_ = (
|
||||
3,
|
||||
@@ -1509,7 +1509,7 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
3,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_MK_71__HE_FRAG__TER_ = (
|
||||
3,
|
||||
@@ -1706,15 +1706,15 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
4,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
4,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
4,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
_2_x_LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts__M156__Wht_Phos__TER___ = (
|
||||
4,
|
||||
@@ -1730,15 +1730,15 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
_2_x_LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts__M156__Wht_Phos__TER___ = (
|
||||
4,
|
||||
@@ -1754,35 +1754,35 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE__TER___ = (
|
||||
4,
|
||||
@@ -1818,7 +1818,7 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
4,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_MK_71__HE_FRAG__TER___ = (
|
||||
4,
|
||||
@@ -1850,7 +1850,7 @@ class A_4E_C(PlaneType):
|
||||
WeaponsA4EC._2_x_LAU_3_pod___19_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice__TER___,
|
||||
)
|
||||
AGM_45A_Shrike_ARM = (4, Weapons.AGM_45A_Shrike_ARM)
|
||||
AGM_45B_Shrike_ARM__Imp_ = (4, Weapons.AGM_45B_Shrike_ARM__Imp_)
|
||||
AGM_45B_Shrike_ARM = (4, Weapons.AGM_45B_Shrike_ARM)
|
||||
Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
4,
|
||||
Weapons.Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets,
|
||||
@@ -1984,63 +1984,63 @@ class A_4E_C(PlaneType):
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
5,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
5,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
5,
|
||||
Weapons.LAU_3_pod___19_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_3___19_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
5,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU3_WP61 = (5, Weapons.LAU3_WP61)
|
||||
LAU3_WP1B = (5, Weapons.LAU3_WP1B)
|
||||
@@ -2048,7 +2048,7 @@ class A_4E_C(PlaneType):
|
||||
LAU3_WP156 = (5, Weapons.LAU3_WP156)
|
||||
LAU3_HE151 = (5, Weapons.LAU3_HE151)
|
||||
AGM_45A_Shrike_ARM = (5, Weapons.AGM_45A_Shrike_ARM)
|
||||
AGM_45B_Shrike_ARM__Imp_ = (5, Weapons.AGM_45B_Shrike_ARM__Imp_)
|
||||
AGM_45B_Shrike_ARM = (5, Weapons.AGM_45B_Shrike_ARM)
|
||||
Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
5,
|
||||
Weapons.Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets,
|
||||
|
||||
@@ -97,32 +97,40 @@ class VSN_F104C(PlaneType):
|
||||
4,
|
||||
Weapons.BL_755_CBU___450kg__147_Frag_Pen_bomblets,
|
||||
)
|
||||
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,
|
||||
)
|
||||
S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__ = (
|
||||
4,
|
||||
Weapons.S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__,
|
||||
Weapons.APU_68___S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk_,
|
||||
)
|
||||
B_8M1___20_S_8OFP2 = (4, Weapons.B_8M1___20_S_8OFP2)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange = (
|
||||
4,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange,
|
||||
)
|
||||
Mk_82_Snakeye___500lb_GP_Bomb_HD = (4, Weapons.Mk_82_Snakeye___500lb_GP_Bomb_HD)
|
||||
Mk_83___1000lb_GP_Bomb_LD = (4, Weapons.Mk_83___1000lb_GP_Bomb_LD)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
AIM_9L_Sidewinder_IR_AAM = (4, Weapons.AIM_9L_Sidewinder_IR_AAM)
|
||||
AIM_9B_Sidewinder_IR_AAM = (4, Weapons.AIM_9B_Sidewinder_IR_AAM)
|
||||
@@ -134,7 +142,7 @@ class VSN_F104C(PlaneType):
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
4,
|
||||
@@ -150,7 +158,7 @@ class VSN_F104C(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
4,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_81___250lb_GP_Bombs_LD = (
|
||||
4,
|
||||
@@ -189,32 +197,40 @@ class VSN_F104C(PlaneType):
|
||||
8,
|
||||
Weapons.BL_755_CBU___450kg__147_Frag_Pen_bomblets,
|
||||
)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
|
||||
8,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
|
||||
)
|
||||
S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__ = (
|
||||
8,
|
||||
Weapons.S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__,
|
||||
Weapons.APU_68___S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk_,
|
||||
)
|
||||
B_8M1___20_S_8OFP2 = (8, Weapons.B_8M1___20_S_8OFP2)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange = (
|
||||
8,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange,
|
||||
)
|
||||
Mk_82_Snakeye___500lb_GP_Bomb_HD = (8, Weapons.Mk_82_Snakeye___500lb_GP_Bomb_HD)
|
||||
Mk_83___1000lb_GP_Bomb_LD = (8, Weapons.Mk_83___1000lb_GP_Bomb_LD)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
AIM_9L_Sidewinder_IR_AAM = (8, Weapons.AIM_9L_Sidewinder_IR_AAM)
|
||||
AIM_9B_Sidewinder_IR_AAM = (8, Weapons.AIM_9B_Sidewinder_IR_AAM)
|
||||
@@ -226,7 +242,7 @@ class VSN_F104C(PlaneType):
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
8,
|
||||
@@ -242,7 +258,7 @@ class VSN_F104C(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
8,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_81___250lb_GP_Bombs_LD = (
|
||||
8,
|
||||
@@ -334,32 +350,40 @@ class VSN_F104G(PlaneType):
|
||||
4,
|
||||
Weapons.BL_755_CBU___450kg__147_Frag_Pen_bomblets,
|
||||
)
|
||||
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,
|
||||
)
|
||||
S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__ = (
|
||||
4,
|
||||
Weapons.S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__,
|
||||
Weapons.APU_68___S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk_,
|
||||
)
|
||||
B_8M1___20_S_8OFP2 = (4, Weapons.B_8M1___20_S_8OFP2)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange = (
|
||||
4,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange,
|
||||
)
|
||||
Mk_82_Snakeye___500lb_GP_Bomb_HD = (4, Weapons.Mk_82_Snakeye___500lb_GP_Bomb_HD)
|
||||
Mk_83___1000lb_GP_Bomb_LD = (4, Weapons.Mk_83___1000lb_GP_Bomb_LD)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
AIM_9L_Sidewinder_IR_AAM = (4, Weapons.AIM_9L_Sidewinder_IR_AAM)
|
||||
AIM_9B_Sidewinder_IR_AAM = (4, Weapons.AIM_9B_Sidewinder_IR_AAM)
|
||||
@@ -371,7 +395,7 @@ class VSN_F104G(PlaneType):
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
4,
|
||||
@@ -387,7 +411,7 @@ class VSN_F104G(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
4,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_81___250lb_GP_Bombs_LD = (
|
||||
4,
|
||||
@@ -435,32 +459,40 @@ class VSN_F104G(PlaneType):
|
||||
8,
|
||||
Weapons.BL_755_CBU___450kg__147_Frag_Pen_bomblets,
|
||||
)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
|
||||
8,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
|
||||
)
|
||||
S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__ = (
|
||||
8,
|
||||
Weapons.S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__,
|
||||
Weapons.APU_68___S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk_,
|
||||
)
|
||||
B_8M1___20_S_8OFP2 = (8, Weapons.B_8M1___20_S_8OFP2)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange = (
|
||||
8,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange,
|
||||
)
|
||||
Mk_82_Snakeye___500lb_GP_Bomb_HD = (8, Weapons.Mk_82_Snakeye___500lb_GP_Bomb_HD)
|
||||
Mk_83___1000lb_GP_Bomb_LD = (8, Weapons.Mk_83___1000lb_GP_Bomb_LD)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
AIM_9L_Sidewinder_IR_AAM = (8, Weapons.AIM_9L_Sidewinder_IR_AAM)
|
||||
AIM_9B_Sidewinder_IR_AAM = (8, Weapons.AIM_9B_Sidewinder_IR_AAM)
|
||||
@@ -472,7 +504,7 @@ class VSN_F104G(PlaneType):
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
8,
|
||||
@@ -488,7 +520,7 @@ class VSN_F104G(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
8,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_81___250lb_GP_Bombs_LD = (
|
||||
8,
|
||||
@@ -577,6 +609,10 @@ class VSN_F104S(PlaneType):
|
||||
AIM_9M_Sidewinder_IR_AAM = (3, Weapons.AIM_9M_Sidewinder_IR_AAM)
|
||||
AIM_9P_Sidewinder_IR_AAM = (3, Weapons.AIM_9P_Sidewinder_IR_AAM)
|
||||
AIM_9P5_Sidewinder_IR_AAM = (3, Weapons.AIM_9P5_Sidewinder_IR_AAM)
|
||||
AIM_7E_2_Sparrow_Semi_Active_Radar = (
|
||||
3,
|
||||
Weapons.AIM_7E_2_Sparrow_Semi_Active_Radar,
|
||||
)
|
||||
AIM_7F_Sparrow_Semi_Active_Radar = (3, Weapons.AIM_7F_Sparrow_Semi_Active_Radar)
|
||||
|
||||
class Pylon4:
|
||||
@@ -622,6 +658,10 @@ class VSN_F104S(PlaneType):
|
||||
AIM_9M_Sidewinder_IR_AAM = (9, Weapons.AIM_9M_Sidewinder_IR_AAM)
|
||||
AIM_9P_Sidewinder_IR_AAM = (9, Weapons.AIM_9P_Sidewinder_IR_AAM)
|
||||
AIM_9P5_Sidewinder_IR_AAM = (9, Weapons.AIM_9P5_Sidewinder_IR_AAM)
|
||||
AIM_7E_2_Sparrow_Semi_Active_Radar = (
|
||||
9,
|
||||
Weapons.AIM_7E_2_Sparrow_Semi_Active_Radar,
|
||||
)
|
||||
AIM_7F_Sparrow_Semi_Active_Radar = (9, Weapons.AIM_7F_Sparrow_Semi_Active_Radar)
|
||||
|
||||
class Pylon10:
|
||||
@@ -717,11 +757,19 @@ class VSN_F104S_AG(PlaneType):
|
||||
Weapons.BL_755_CBU___450kg__147_Frag_Pen_bomblets,
|
||||
)
|
||||
CBU_97___10_x_SFW_Cluster_Bomb = (3, Weapons.CBU_97___10_x_SFW_Cluster_Bomb)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
|
||||
3,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
|
||||
)
|
||||
S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__ = (
|
||||
3,
|
||||
Weapons.S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__,
|
||||
Weapons.APU_68___S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk_,
|
||||
)
|
||||
B_8M1___20_S_8OFP2 = (3, Weapons.B_8M1___20_S_8OFP2)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange = (
|
||||
3,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange,
|
||||
)
|
||||
AIM_9L_Sidewinder_IR_AAM = (3, Weapons.AIM_9L_Sidewinder_IR_AAM)
|
||||
AIM_9B_Sidewinder_IR_AAM = (3, Weapons.AIM_9B_Sidewinder_IR_AAM)
|
||||
AGM_88C_HARM___High_Speed_Anti_Radiation_Missile_ = (
|
||||
@@ -754,32 +802,40 @@ class VSN_F104S_AG(PlaneType):
|
||||
Weapons.BL_755_CBU___450kg__147_Frag_Pen_bomblets,
|
||||
)
|
||||
CBU_97___10_x_SFW_Cluster_Bomb = (4, Weapons.CBU_97___10_x_SFW_Cluster_Bomb)
|
||||
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,
|
||||
)
|
||||
S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__ = (
|
||||
4,
|
||||
Weapons.S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__,
|
||||
Weapons.APU_68___S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk_,
|
||||
)
|
||||
B_8M1___20_S_8OFP2 = (4, Weapons.B_8M1___20_S_8OFP2)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange = (
|
||||
4,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange,
|
||||
)
|
||||
Mk_82_Snakeye___500lb_GP_Bomb_HD = (4, Weapons.Mk_82_Snakeye___500lb_GP_Bomb_HD)
|
||||
Mk_83___1000lb_GP_Bomb_LD = (4, Weapons.Mk_83___1000lb_GP_Bomb_LD)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
AIM_9M_Sidewinder_IR_AAM = (4, Weapons.AIM_9M_Sidewinder_IR_AAM)
|
||||
AIM_9L_Sidewinder_IR_AAM = (4, Weapons.AIM_9L_Sidewinder_IR_AAM)
|
||||
@@ -792,7 +848,7 @@ class VSN_F104S_AG(PlaneType):
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
4,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
4,
|
||||
@@ -808,7 +864,7 @@ class VSN_F104S_AG(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
4,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_81___250lb_GP_Bombs_LD = (
|
||||
4,
|
||||
@@ -867,32 +923,40 @@ class VSN_F104S_AG(PlaneType):
|
||||
Weapons.BL_755_CBU___450kg__147_Frag_Pen_bomblets,
|
||||
)
|
||||
CBU_97___10_x_SFW_Cluster_Bomb = (8, Weapons.CBU_97___10_x_SFW_Cluster_Bomb)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
|
||||
8,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
|
||||
)
|
||||
S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__ = (
|
||||
8,
|
||||
Weapons.S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__,
|
||||
Weapons.APU_68___S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk_,
|
||||
)
|
||||
B_8M1___20_S_8OFP2 = (8, Weapons.B_8M1___20_S_8OFP2)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange = (
|
||||
8,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange,
|
||||
)
|
||||
Mk_82_Snakeye___500lb_GP_Bomb_HD = (8, Weapons.Mk_82_Snakeye___500lb_GP_Bomb_HD)
|
||||
Mk_83___1000lb_GP_Bomb_LD = (8, Weapons.Mk_83___1000lb_GP_Bomb_LD)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.BRU_33_2_x_LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
AIM_9B_Sidewinder_IR_AAM = (8, Weapons.AIM_9B_Sidewinder_IR_AAM)
|
||||
AIM_9L_Sidewinder_IR_AAM = (8, Weapons.AIM_9L_Sidewinder_IR_AAM)
|
||||
@@ -904,7 +968,7 @@ class VSN_F104S_AG(PlaneType):
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
8,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
8,
|
||||
@@ -920,7 +984,7 @@ class VSN_F104S_AG(PlaneType):
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
8,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_81___250lb_GP_Bombs_LD = (
|
||||
8,
|
||||
@@ -960,11 +1024,19 @@ class VSN_F104S_AG(PlaneType):
|
||||
Weapons.BL_755_CBU___450kg__147_Frag_Pen_bomblets,
|
||||
)
|
||||
CBU_97___10_x_SFW_Cluster_Bomb = (9, Weapons.CBU_97___10_x_SFW_Cluster_Bomb)
|
||||
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,
|
||||
)
|
||||
S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__ = (
|
||||
9,
|
||||
Weapons.S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk__,
|
||||
Weapons.APU_68___S_24B___240mm_UnGd_Rkt__235kg__HE_Frag___Low_Smk_,
|
||||
)
|
||||
B_8M1___20_S_8OFP2 = (9, Weapons.B_8M1___20_S_8OFP2)
|
||||
B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange = (
|
||||
9,
|
||||
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8TsM_SM_Orange,
|
||||
)
|
||||
AIM_9P_Sidewinder_IR_AAM = (9, Weapons.AIM_9P_Sidewinder_IR_AAM)
|
||||
AIM_9P5_Sidewinder_IR_AAM = (9, Weapons.AIM_9P5_Sidewinder_IR_AAM)
|
||||
AIM_9L_Sidewinder_IR_AAM = (9, Weapons.AIM_9L_Sidewinder_IR_AAM)
|
||||
|
||||
@@ -8,7 +8,7 @@ from game.modsupport import planemod
|
||||
from pydcs_extensions.weapon_injector import inject_weapons
|
||||
|
||||
|
||||
class WeaponsF4:
|
||||
class WeaponsF4BC:
|
||||
F4B_Gunpod_w_SAPHEI_T = {
|
||||
"clsid": "{VSN_F4B_Equalizer}",
|
||||
"name": "F4B Gunpod w/SAPHEI-T",
|
||||
@@ -79,9 +79,19 @@ class WeaponsF4:
|
||||
"name": "BRU 42A MK82*3 LAU105 AIM9J*2",
|
||||
"weight": 1500,
|
||||
}
|
||||
LAU_118a_and_AGM_45A_Shrike___Passive_radar_homing_Anti_Radiation_Missile = {
|
||||
"clsid": "{F4C_LAU118_AGM45A}",
|
||||
"name": "LAU-118a and AGM-45A Shrike - Passive radar homing Anti-Radiation-Missile",
|
||||
"weight": 177,
|
||||
}
|
||||
SUU_23A_M61_Gunpod_HE_AP_HE_INV_ = {
|
||||
"clsid": "{VSN_F4B_Equalizer}",
|
||||
"name": "SUU-23A M61 Gunpod HE/AP/HE-INV.",
|
||||
"weight": 744.362,
|
||||
}
|
||||
|
||||
|
||||
inject_weapons(WeaponsF4)
|
||||
inject_weapons(WeaponsF4BC)
|
||||
|
||||
|
||||
@planemod
|
||||
@@ -99,9 +109,32 @@ class VSN_F4B(PlaneType):
|
||||
chaff_charge_size = 1
|
||||
flare_charge_size = 1
|
||||
category = "Interceptor" # {78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F}
|
||||
radio_frequency = 127.5
|
||||
radio_frequency = 264
|
||||
|
||||
livery_name = "VSN_F4B" # from type
|
||||
panel_radio = {
|
||||
1: {
|
||||
"channels": {
|
||||
1: 264,
|
||||
2: 265,
|
||||
4: 254,
|
||||
8: 258,
|
||||
16: 267,
|
||||
17: 251,
|
||||
9: 262,
|
||||
18: 253,
|
||||
5: 250,
|
||||
10: 259,
|
||||
11: 268,
|
||||
3: 256,
|
||||
6: 270,
|
||||
12: 269,
|
||||
13: 260,
|
||||
7: 257,
|
||||
14: 263,
|
||||
15: 261,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
class Pylon1:
|
||||
Smoke_Generator___red_ = (1, Weapons.Smoke_Generator___red_)
|
||||
@@ -112,31 +145,34 @@ class VSN_F4B(PlaneType):
|
||||
Smoke_Generator___orange_ = (1, Weapons.Smoke_Generator___orange_)
|
||||
|
||||
class Pylon2:
|
||||
GBU_10___2000lb_Laser_Guided_Bomb = (
|
||||
2,
|
||||
Weapons.GBU_10___2000lb_Laser_Guided_Bomb,
|
||||
)
|
||||
GBU_12___500lb_Laser_Guided_Bomb = (2, Weapons.GBU_12___500lb_Laser_Guided_Bomb)
|
||||
BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets = (
|
||||
2,
|
||||
Weapons.BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets,
|
||||
)
|
||||
TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD = (
|
||||
2,
|
||||
Weapons.TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD = (
|
||||
2,
|
||||
Weapons.BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD,
|
||||
)
|
||||
Mk_84___2000lb_GP_Bomb_LD = (2, Weapons.Mk_84___2000lb_GP_Bomb_LD)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
2,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
2,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
Smokewinder___red = (2, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (2, Weapons.Smokewinder___green)
|
||||
@@ -145,29 +181,20 @@ class VSN_F4B(PlaneType):
|
||||
Smokewinder___yellow = (2, Weapons.Smokewinder___yellow)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
2,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_41A_with_6_x_Mk_82___500lb_GP_Bomb_LD = (
|
||||
2,
|
||||
Weapons.BRU_41A_with_6_x_Mk_82___500lb_GP_Bomb_LD,
|
||||
)
|
||||
BRU_33_with_2_x_GBU_12___500lb_Laser_Guided_Bomb = (
|
||||
2,
|
||||
Weapons.BRU_33_with_2_x_GBU_12___500lb_Laser_Guided_Bomb,
|
||||
)
|
||||
BIN_200 = (2, Weapons.BIN_200)
|
||||
VSN_F4EL_PTB = (2, Weapons.VSN_F4EL_PTB)
|
||||
VSN_F4EL_PTB = (2, WeaponsF4BC.VSN_F4EL_PTB)
|
||||
|
||||
class Pylon3:
|
||||
GBU_10___2000lb_Laser_Guided_Bomb = (
|
||||
3,
|
||||
Weapons.GBU_10___2000lb_Laser_Guided_Bomb,
|
||||
)
|
||||
GBU_12___500lb_Laser_Guided_Bomb = (3, Weapons.GBU_12___500lb_Laser_Guided_Bomb)
|
||||
BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets = (
|
||||
3,
|
||||
Weapons.BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets,
|
||||
@@ -179,19 +206,19 @@ class VSN_F4B(PlaneType):
|
||||
Mk_84___2000lb_GP_Bomb_LD = (3, Weapons.Mk_84___2000lb_GP_Bomb_LD)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
3,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
3,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_105_2_AIM_9L = (3, Weapons.LAU_105_2_AIM_9L)
|
||||
LAU_105_with_2_x_AIM_9P_Sidewinder_IR_AAM = (
|
||||
@@ -203,8 +230,8 @@ class VSN_F4B(PlaneType):
|
||||
3,
|
||||
Weapons.LAU_7_with_2_x_AIM_9B_Sidewinder_IR_AAM,
|
||||
)
|
||||
LAU_105_2_AIM_9J = (3, Weapons.LAU_105_2_AIM_9J)
|
||||
LAU_105_2_AIM_9JULI = (3, Weapons.LAU_105_2_AIM_9JULI)
|
||||
LAU_105_2_AIM_9J = (3, WeaponsF4BC.LAU_105_2_AIM_9J)
|
||||
LAU_105_2_AIM_9JULI = (3, WeaponsF4BC.LAU_105_2_AIM_9JULI)
|
||||
AIM_7F_Sparrow_Semi_Active_Radar = (3, Weapons.AIM_7F_Sparrow_Semi_Active_Radar)
|
||||
AIM_7E_2_Sparrow_Semi_Active_Radar = (
|
||||
3,
|
||||
@@ -224,13 +251,19 @@ class VSN_F4B(PlaneType):
|
||||
Weapons.BRU_33_with_2_x_Mk_83___1000lb_GP_Bomb_LD,
|
||||
)
|
||||
BIN_200 = (3, Weapons.BIN_200)
|
||||
F4B_LAU105_AIM9J_2_BRU42A_M117_3 = (3, Weapons.F4B_LAU105_AIM9J_2_BRU42A_M117_3)
|
||||
F4B_LAU105_AIM9J_2_BRU42A_MK82_3 = (3, Weapons.F4B_LAU105_AIM9J_2_BRU42A_MK82_3)
|
||||
F4B_LAU105_AIM9J_2_BRU42A_M117_3 = (
|
||||
3,
|
||||
WeaponsF4BC.F4B_LAU105_AIM9J_2_BRU42A_M117_3,
|
||||
)
|
||||
F4B_LAU105_AIM9J_2_BRU42A_MK82_3 = (
|
||||
3,
|
||||
WeaponsF4BC.F4B_LAU105_AIM9J_2_BRU42A_MK82_3,
|
||||
)
|
||||
F4B_LAU105_AIM9J_2_TER9A_MK82SE_3 = (
|
||||
3,
|
||||
Weapons.F4B_LAU105_AIM9J_2_TER9A_MK82SE_3,
|
||||
WeaponsF4BC.F4B_LAU105_AIM9J_2_TER9A_MK82SE_3,
|
||||
)
|
||||
F4B_LAU105_AIM9J_2_MER_MK20_3 = (3, Weapons.F4B_LAU105_AIM9J_2_MER_MK20_3)
|
||||
F4B_LAU105_AIM9J_2_MER_MK20_3 = (3, WeaponsF4BC.F4B_LAU105_AIM9J_2_MER_MK20_3)
|
||||
|
||||
class Pylon4:
|
||||
AIM_7F_Sparrow_Semi_Active_Radar = (4, Weapons.AIM_7F_Sparrow_Semi_Active_Radar)
|
||||
@@ -245,6 +278,7 @@ class VSN_F4B(PlaneType):
|
||||
5,
|
||||
Weapons.AIM_7E_2_Sparrow_Semi_Active_Radar,
|
||||
)
|
||||
ALQ_131___ECM_Pod = (5, Weapons.ALQ_131___ECM_Pod)
|
||||
|
||||
class Pylon6:
|
||||
Smokewinder___red = (6, Weapons.Smokewinder___red)
|
||||
@@ -258,16 +292,18 @@ class VSN_F4B(PlaneType):
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
6,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD = (
|
||||
6,
|
||||
Weapons.BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD,
|
||||
)
|
||||
ALQ_131___ECM_Pod = (6, Weapons.ALQ_131___ECM_Pod)
|
||||
F4B_Gunpod_w_SAPHEI_T = (6, Weapons.F4B_Gunpod_w_SAPHEI_T)
|
||||
VSN_F4EC_PTB = (6, Weapons.VSN_F4EC_PTB)
|
||||
VSN_F4B_C2_PTB = (6, Weapons.VSN_F4B_C2_PTB)
|
||||
SUU_23A_M61_Gunpod_HE_AP_HE_INV_ = (
|
||||
6,
|
||||
WeaponsF4BC.SUU_23A_M61_Gunpod_HE_AP_HE_INV_,
|
||||
)
|
||||
VSN_F4EC_PTB = (6, WeaponsF4BC.VSN_F4EC_PTB)
|
||||
VSN_F4B_C2_PTB = (6, WeaponsF4BC.VSN_F4B_C2_PTB)
|
||||
|
||||
class Pylon7:
|
||||
AIM_7F_Sparrow_Semi_Active_Radar = (7, Weapons.AIM_7F_Sparrow_Semi_Active_Radar)
|
||||
@@ -284,11 +320,6 @@ class VSN_F4B(PlaneType):
|
||||
)
|
||||
|
||||
class Pylon9:
|
||||
GBU_10___2000lb_Laser_Guided_Bomb = (
|
||||
9,
|
||||
Weapons.GBU_10___2000lb_Laser_Guided_Bomb,
|
||||
)
|
||||
GBU_12___500lb_Laser_Guided_Bomb = (9, Weapons.GBU_12___500lb_Laser_Guided_Bomb)
|
||||
BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets = (
|
||||
9,
|
||||
Weapons.BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets,
|
||||
@@ -300,19 +331,19 @@ class VSN_F4B(PlaneType):
|
||||
Mk_84___2000lb_GP_Bomb_LD = (9, Weapons.Mk_84___2000lb_GP_Bomb_LD)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
9,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
9,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
9,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
9,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_105_2_AIM_9L = (9, Weapons.LAU_105_2_AIM_9L)
|
||||
LAU_105_with_2_x_AIM_9P_Sidewinder_IR_AAM = (
|
||||
@@ -324,8 +355,8 @@ class VSN_F4B(PlaneType):
|
||||
9,
|
||||
Weapons.LAU_7_with_2_x_AIM_9B_Sidewinder_IR_AAM,
|
||||
)
|
||||
LAU_105_2_AIM_9J = (9, Weapons.LAU_105_2_AIM_9J)
|
||||
LAU_105_2_AIM_9JULI = (9, Weapons.LAU_105_2_AIM_9JULI)
|
||||
LAU_105_2_AIM_9J = (9, WeaponsF4BC.LAU_105_2_AIM_9J)
|
||||
LAU_105_2_AIM_9JULI = (9, WeaponsF4BC.LAU_105_2_AIM_9JULI)
|
||||
AIM_7F_Sparrow_Semi_Active_Radar = (9, Weapons.AIM_7F_Sparrow_Semi_Active_Radar)
|
||||
AIM_7E_2_Sparrow_Semi_Active_Radar = (
|
||||
9,
|
||||
@@ -345,43 +376,49 @@ class VSN_F4B(PlaneType):
|
||||
Weapons.BRU_33_with_2_x_Mk_83___1000lb_GP_Bomb_LD,
|
||||
)
|
||||
BIN_200 = (9, Weapons.BIN_200)
|
||||
F4B_LAU105_AIM9J_2_BRU42A_M117_3 = (9, Weapons.F4B_LAU105_AIM9J_2_BRU42A_M117_3)
|
||||
F4B_LAU105_AIM9J_2_BRU42A_MK82_3 = (9, Weapons.F4B_LAU105_AIM9J_2_BRU42A_MK82_3)
|
||||
F4B_LAU105_AIM9J_2_BRU42A_M117_3 = (
|
||||
9,
|
||||
WeaponsF4BC.F4B_LAU105_AIM9J_2_BRU42A_M117_3,
|
||||
)
|
||||
F4B_LAU105_AIM9J_2_BRU42A_MK82_3 = (
|
||||
9,
|
||||
WeaponsF4BC.F4B_LAU105_AIM9J_2_BRU42A_MK82_3,
|
||||
)
|
||||
F4B_LAU105_AIM9J_2_TER9A_MK82SE_3 = (
|
||||
9,
|
||||
Weapons.F4B_LAU105_AIM9J_2_TER9A_MK82SE_3,
|
||||
WeaponsF4BC.F4B_LAU105_AIM9J_2_TER9A_MK82SE_3,
|
||||
)
|
||||
F4B_LAU105_AIM9J_2_MER_MK20_3 = (9, Weapons.F4B_LAU105_AIM9J_2_MER_MK20_3)
|
||||
F4B_LAU105_AIM9J_2_MER_MK20_3 = (9, WeaponsF4BC.F4B_LAU105_AIM9J_2_MER_MK20_3)
|
||||
|
||||
class Pylon10:
|
||||
GBU_10___2000lb_Laser_Guided_Bomb = (
|
||||
10,
|
||||
Weapons.GBU_10___2000lb_Laser_Guided_Bomb,
|
||||
)
|
||||
GBU_12___500lb_Laser_Guided_Bomb = (
|
||||
10,
|
||||
Weapons.GBU_12___500lb_Laser_Guided_Bomb,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets = (
|
||||
10,
|
||||
Weapons.BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets,
|
||||
)
|
||||
Mk_84___2000lb_GP_Bomb_LD = (10, Weapons.Mk_84___2000lb_GP_Bomb_LD)
|
||||
TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD = (
|
||||
10,
|
||||
Weapons.TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD = (
|
||||
10,
|
||||
Weapons.BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
10,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
10,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
10,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
10,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
Smokewinder___red = (10, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (10, Weapons.Smokewinder___green)
|
||||
@@ -390,27 +427,26 @@ class VSN_F4B(PlaneType):
|
||||
Smokewinder___yellow = (10, Weapons.Smokewinder___yellow)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
10,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
10,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_41A_with_6_x_Mk_82___500lb_GP_Bomb_LD = (
|
||||
10,
|
||||
Weapons.BRU_41A_with_6_x_Mk_82___500lb_GP_Bomb_LD,
|
||||
)
|
||||
BRU_33_with_2_x_GBU_12___500lb_Laser_Guided_Bomb = (
|
||||
10,
|
||||
Weapons.BRU_33_with_2_x_GBU_12___500lb_Laser_Guided_Bomb,
|
||||
)
|
||||
BIN_200 = (10, Weapons.BIN_200)
|
||||
VSN_F4ER_PTB = (10, Weapons.VSN_F4ER_PTB)
|
||||
VSN_F4ER_PTB = (10, WeaponsF4BC.VSN_F4ER_PTB)
|
||||
|
||||
# ERRR <CLEAN>
|
||||
# ERRR <CLEAN>
|
||||
|
||||
class Pylon11:
|
||||
# all added manually - did not pull using database export
|
||||
BRU42A_M117_3_LAU105_AIM9J_2 = (11, Weapons.BRU_42A_M117_3_LAU105_AIM9J_2)
|
||||
BRU42A_MK82_3_LAU105_AIM9J_2 = (11, Weapons.BRU_42A_MK82_3_LAU105_AIM9J_2)
|
||||
BRU42A_M117_3_LAU105_AIM9J_2 = (11, WeaponsF4BC.BRU_42A_M117_3_LAU105_AIM9J_2)
|
||||
BRU42A_MK82_3_LAU105_AIM9J_2 = (11, WeaponsF4BC.BRU_42A_MK82_3_LAU105_AIM9J_2)
|
||||
TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD = (
|
||||
11,
|
||||
Weapons.TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD,
|
||||
@@ -422,8 +458,8 @@ class VSN_F4B(PlaneType):
|
||||
|
||||
class Pylon12:
|
||||
# all added manually - did not pull using database export
|
||||
BRU42A_M117_3_LAU105_AIM9J_2 = (12, Weapons.BRU_42A_M117_3_LAU105_AIM9J_2)
|
||||
BRU42A_MK82_3_LAU105_AIM9J_2 = (12, Weapons.BRU_42A_MK82_3_LAU105_AIM9J_2)
|
||||
BRU42A_M117_3_LAU105_AIM9J_2 = (12, WeaponsF4BC.BRU_42A_M117_3_LAU105_AIM9J_2)
|
||||
BRU42A_MK82_3_LAU105_AIM9J_2 = (12, WeaponsF4BC.BRU_42A_MK82_3_LAU105_AIM9J_2)
|
||||
TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD = (
|
||||
12,
|
||||
Weapons.TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD,
|
||||
@@ -445,6 +481,7 @@ class VSN_F4B(PlaneType):
|
||||
task.CAS,
|
||||
task.AFAC,
|
||||
task.RunwayAttack,
|
||||
task.PinpointStrike,
|
||||
]
|
||||
task_default = task.CAP
|
||||
|
||||
@@ -464,9 +501,32 @@ class VSN_F4C(PlaneType):
|
||||
chaff_charge_size = 1
|
||||
flare_charge_size = 1
|
||||
category = "Interceptor" # {78EFB7A2-FD52-4b57-A6A6-3BF0E1D6555F}
|
||||
radio_frequency = 127.5
|
||||
radio_frequency = 264
|
||||
|
||||
livery_name = "VSN_F4C" # from type
|
||||
panel_radio = {
|
||||
1: {
|
||||
"channels": {
|
||||
1: 264,
|
||||
2: 265,
|
||||
4: 254,
|
||||
8: 258,
|
||||
16: 267,
|
||||
17: 251,
|
||||
9: 262,
|
||||
18: 253,
|
||||
5: 250,
|
||||
10: 259,
|
||||
11: 268,
|
||||
3: 256,
|
||||
6: 270,
|
||||
12: 269,
|
||||
13: 260,
|
||||
7: 257,
|
||||
14: 263,
|
||||
15: 261,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
class Pylon1:
|
||||
Smoke_Generator___red_ = (1, Weapons.Smoke_Generator___red_)
|
||||
@@ -477,31 +537,34 @@ class VSN_F4C(PlaneType):
|
||||
Smoke_Generator___orange_ = (1, Weapons.Smoke_Generator___orange_)
|
||||
|
||||
class Pylon2:
|
||||
GBU_10___2000lb_Laser_Guided_Bomb = (
|
||||
2,
|
||||
Weapons.GBU_10___2000lb_Laser_Guided_Bomb,
|
||||
)
|
||||
GBU_12___500lb_Laser_Guided_Bomb = (2, Weapons.GBU_12___500lb_Laser_Guided_Bomb)
|
||||
BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets = (
|
||||
2,
|
||||
Weapons.BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets,
|
||||
)
|
||||
Mk_84___2000lb_GP_Bomb_LD = (2, Weapons.Mk_84___2000lb_GP_Bomb_LD)
|
||||
TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD = (
|
||||
2,
|
||||
Weapons.TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD = (
|
||||
2,
|
||||
Weapons.BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
2,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
2,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
Smokewinder___red = (2, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (2, Weapons.Smokewinder___green)
|
||||
@@ -510,29 +573,20 @@ class VSN_F4C(PlaneType):
|
||||
Smokewinder___yellow = (2, Weapons.Smokewinder___yellow)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
2,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_41A_with_6_x_Mk_82___500lb_GP_Bomb_LD = (
|
||||
2,
|
||||
Weapons.BRU_41A_with_6_x_Mk_82___500lb_GP_Bomb_LD,
|
||||
)
|
||||
BRU_33_with_2_x_GBU_12___500lb_Laser_Guided_Bomb = (
|
||||
2,
|
||||
Weapons.BRU_33_with_2_x_GBU_12___500lb_Laser_Guided_Bomb,
|
||||
)
|
||||
BIN_200 = (2, Weapons.BIN_200)
|
||||
VSN_F4EL_PTB = (2, Weapons.VSN_F4EL_PTB)
|
||||
VSN_F4EL_PTB = (2, WeaponsF4BC.VSN_F4EL_PTB)
|
||||
|
||||
class Pylon3:
|
||||
GBU_10___2000lb_Laser_Guided_Bomb = (
|
||||
3,
|
||||
Weapons.GBU_10___2000lb_Laser_Guided_Bomb,
|
||||
)
|
||||
GBU_12___500lb_Laser_Guided_Bomb = (3, Weapons.GBU_12___500lb_Laser_Guided_Bomb)
|
||||
BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets = (
|
||||
3,
|
||||
Weapons.BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets,
|
||||
@@ -542,23 +596,25 @@ class VSN_F4C(PlaneType):
|
||||
Weapons.BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD,
|
||||
)
|
||||
Mk_84___2000lb_GP_Bomb_LD = (3, Weapons.Mk_84___2000lb_GP_Bomb_LD)
|
||||
AGM_45B_Shrike_ARM__Imp_ = (3, Weapons.AGM_45B_Shrike_ARM__Imp_)
|
||||
AGM_45A_Shrike_ARM = (3, Weapons.AGM_45A_Shrike_ARM)
|
||||
LAU_118A___AGM_45B_Shrike_ARM = (
|
||||
3,
|
||||
Weapons.LAU_118A___AGM_45B_Shrike_ARM,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
3,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
3,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_105_2_AIM_9L = (3, Weapons.LAU_105_2_AIM_9L)
|
||||
LAU_105_with_2_x_AIM_9P_Sidewinder_IR_AAM = (
|
||||
@@ -570,8 +626,8 @@ class VSN_F4C(PlaneType):
|
||||
3,
|
||||
Weapons.LAU_7_with_2_x_AIM_9B_Sidewinder_IR_AAM,
|
||||
)
|
||||
LAU_105_2_AIM_9J = (3, Weapons.LAU_105_2_AIM_9J)
|
||||
LAU_105_2_AIM_9JULI = (3, Weapons.LAU_105_2_AIM_9JULI)
|
||||
LAU_105_2_AIM_9J = (3, WeaponsF4BC.LAU_105_2_AIM_9J)
|
||||
LAU_105_2_AIM_9JULI = (3, WeaponsF4BC.LAU_105_2_AIM_9JULI)
|
||||
Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
3,
|
||||
Weapons.Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets,
|
||||
@@ -586,6 +642,10 @@ class VSN_F4C(PlaneType):
|
||||
Weapons.BRU_33_with_2_x_Mk_83___1000lb_GP_Bomb_LD,
|
||||
)
|
||||
BIN_200 = (3, Weapons.BIN_200)
|
||||
LAU_118a_and_AGM_45A_Shrike___Passive_radar_homing_Anti_Radiation_Missile = (
|
||||
3,
|
||||
WeaponsF4BC.LAU_118a_and_AGM_45A_Shrike___Passive_radar_homing_Anti_Radiation_Missile,
|
||||
)
|
||||
|
||||
class Pylon4:
|
||||
AIM_7F_Sparrow_Semi_Active_Radar = (4, Weapons.AIM_7F_Sparrow_Semi_Active_Radar)
|
||||
@@ -600,6 +660,7 @@ class VSN_F4C(PlaneType):
|
||||
5,
|
||||
Weapons.AIM_7E_2_Sparrow_Semi_Active_Radar,
|
||||
)
|
||||
ALQ_131___ECM_Pod = (5, Weapons.ALQ_131___ECM_Pod)
|
||||
|
||||
class Pylon6:
|
||||
Smokewinder___red = (6, Weapons.Smokewinder___red)
|
||||
@@ -613,16 +674,18 @@ class VSN_F4C(PlaneType):
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
6,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD = (
|
||||
6,
|
||||
Weapons.BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD,
|
||||
)
|
||||
ALQ_131___ECM_Pod = (6, Weapons.ALQ_131___ECM_Pod)
|
||||
F4B_Gunpod_w_SAPHEI_T = (6, Weapons.F4B_Gunpod_w_SAPHEI_T)
|
||||
VSN_F4EC_PTB = (6, Weapons.VSN_F4EC_PTB)
|
||||
VSN_F4B_C2_PTB = (6, Weapons.VSN_F4B_C2_PTB)
|
||||
SUU_23A_M61_Gunpod_HE_AP_HE_INV_ = (
|
||||
6,
|
||||
WeaponsF4BC.SUU_23A_M61_Gunpod_HE_AP_HE_INV_,
|
||||
)
|
||||
VSN_F4EC_PTB = (6, WeaponsF4BC.VSN_F4EC_PTB)
|
||||
VSN_F4B_C2_PTB = (6, WeaponsF4BC.VSN_F4B_C2_PTB)
|
||||
|
||||
class Pylon7:
|
||||
AIM_7F_Sparrow_Semi_Active_Radar = (7, Weapons.AIM_7F_Sparrow_Semi_Active_Radar)
|
||||
@@ -639,11 +702,6 @@ class VSN_F4C(PlaneType):
|
||||
)
|
||||
|
||||
class Pylon9:
|
||||
GBU_10___2000lb_Laser_Guided_Bomb = (
|
||||
9,
|
||||
Weapons.GBU_10___2000lb_Laser_Guided_Bomb,
|
||||
)
|
||||
GBU_12___500lb_Laser_Guided_Bomb = (9, Weapons.GBU_12___500lb_Laser_Guided_Bomb)
|
||||
BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets = (
|
||||
9,
|
||||
Weapons.BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets,
|
||||
@@ -653,23 +711,25 @@ class VSN_F4C(PlaneType):
|
||||
Weapons.BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD,
|
||||
)
|
||||
Mk_84___2000lb_GP_Bomb_LD = (9, Weapons.Mk_84___2000lb_GP_Bomb_LD)
|
||||
AGM_45B_Shrike_ARM__Imp_ = (9, Weapons.AGM_45B_Shrike_ARM__Imp_)
|
||||
AGM_45A_Shrike_ARM = (9, Weapons.AGM_45A_Shrike_ARM)
|
||||
LAU_118A___AGM_45B_Shrike_ARM = (
|
||||
9,
|
||||
Weapons.LAU_118A___AGM_45B_Shrike_ARM,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
9,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
9,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
9,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
9,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_105_2_AIM_9L = (9, Weapons.LAU_105_2_AIM_9L)
|
||||
LAU_105_with_2_x_AIM_9P_Sidewinder_IR_AAM = (
|
||||
@@ -681,8 +741,8 @@ class VSN_F4C(PlaneType):
|
||||
9,
|
||||
Weapons.LAU_7_with_2_x_AIM_9B_Sidewinder_IR_AAM,
|
||||
)
|
||||
LAU_105_2_AIM_9J = (9, Weapons.LAU_105_2_AIM_9J)
|
||||
LAU_105_2_AIM_9JULI = (9, Weapons.LAU_105_2_AIM_9JULI)
|
||||
LAU_105_2_AIM_9J = (9, WeaponsF4BC.LAU_105_2_AIM_9J)
|
||||
LAU_105_2_AIM_9JULI = (9, WeaponsF4BC.LAU_105_2_AIM_9JULI)
|
||||
Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets = (
|
||||
9,
|
||||
Weapons.Mk_20_Rockeye___490lbs_CBU__247_x_HEAT_Bomblets,
|
||||
@@ -697,36 +757,40 @@ class VSN_F4C(PlaneType):
|
||||
Weapons.BRU_33_with_2_x_Mk_83___1000lb_GP_Bomb_LD,
|
||||
)
|
||||
BIN_200 = (9, Weapons.BIN_200)
|
||||
LAU_118a_and_AGM_45A_Shrike___Passive_radar_homing_Anti_Radiation_Missile = (
|
||||
9,
|
||||
WeaponsF4BC.LAU_118a_and_AGM_45A_Shrike___Passive_radar_homing_Anti_Radiation_Missile,
|
||||
)
|
||||
|
||||
class Pylon10:
|
||||
GBU_10___2000lb_Laser_Guided_Bomb = (
|
||||
10,
|
||||
Weapons.GBU_10___2000lb_Laser_Guided_Bomb,
|
||||
)
|
||||
GBU_12___500lb_Laser_Guided_Bomb = (
|
||||
10,
|
||||
Weapons.GBU_12___500lb_Laser_Guided_Bomb,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets = (
|
||||
10,
|
||||
Weapons.BRU_42_with_3_x_Mk_20_Rockeye___490lbs_CBUs__247_x_HEAT_Bomblets,
|
||||
)
|
||||
Mk_84___2000lb_GP_Bomb_LD = (10, Weapons.Mk_84___2000lb_GP_Bomb_LD)
|
||||
TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD = (
|
||||
10,
|
||||
Weapons.TER_9A_with_3_x_Mk_82_Snakeye___500lb_GP_Bomb_HD,
|
||||
)
|
||||
BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD = (
|
||||
10,
|
||||
Weapons.BRU_42_with_3_x_Mk_82___500lb_GP_Bombs_LD,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
10,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
10,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
_3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
10,
|
||||
Weapons._3_x_LAU_61_pods___57_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_42_3_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
10,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
Smokewinder___red = (10, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (10, Weapons.Smokewinder___green)
|
||||
@@ -735,22 +799,21 @@ class VSN_F4C(PlaneType):
|
||||
Smokewinder___yellow = (10, Weapons.Smokewinder___yellow)
|
||||
BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
10,
|
||||
Weapons.BRU_33_with_2_x_LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.BRU_33_2_x_LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
10,
|
||||
Weapons.BRU_33_with_2_x_LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.BRU_33_2_x_LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
BRU_41A_with_6_x_Mk_82___500lb_GP_Bomb_LD = (
|
||||
10,
|
||||
Weapons.BRU_41A_with_6_x_Mk_82___500lb_GP_Bomb_LD,
|
||||
)
|
||||
BRU_33_with_2_x_GBU_12___500lb_Laser_Guided_Bomb = (
|
||||
10,
|
||||
Weapons.BRU_33_with_2_x_GBU_12___500lb_Laser_Guided_Bomb,
|
||||
)
|
||||
BIN_200 = (10, Weapons.BIN_200)
|
||||
VSN_F4ER_PTB = (10, Weapons.VSN_F4ER_PTB)
|
||||
VSN_F4ER_PTB = (10, WeaponsF4BC.VSN_F4ER_PTB)
|
||||
|
||||
# ERRR <CLEAN>
|
||||
# ERRR <CLEAN>
|
||||
|
||||
pylons: Set[int] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
|
||||
|
||||
@@ -764,5 +827,7 @@ class VSN_F4C(PlaneType):
|
||||
task.CAS,
|
||||
task.AFAC,
|
||||
task.RunwayAttack,
|
||||
task.SEAD,
|
||||
task.PinpointStrike,
|
||||
]
|
||||
task_default = task.CAP
|
||||
|
||||
1
pydcs_extensions/fa18efg/__init__.py
Normal file
1
pydcs_extensions/fa18efg/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .fa18efg import *
|
||||
2813
pydcs_extensions/fa18efg/fa18efg.py
Normal file
2813
pydcs_extensions/fa18efg/fa18efg.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -736,7 +736,7 @@ class Hercules(PlaneType):
|
||||
class Pylon2:
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
Smokewinder___red = (2, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (2, Weapons.Smokewinder___green)
|
||||
@@ -753,7 +753,7 @@ class Hercules(PlaneType):
|
||||
class Pylon3:
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
Smokewinder___red = (3, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (3, Weapons.Smokewinder___green)
|
||||
@@ -770,7 +770,7 @@ class Hercules(PlaneType):
|
||||
class Pylon4:
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
4,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
Smokewinder___red = (4, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (4, Weapons.Smokewinder___green)
|
||||
@@ -787,7 +787,7 @@ class Hercules(PlaneType):
|
||||
class Pylon5:
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
Smokewinder___red = (5, Weapons.Smokewinder___red)
|
||||
Smokewinder___green = (5, Weapons.Smokewinder___green)
|
||||
|
||||
@@ -57,7 +57,7 @@ class Bronco_OV_10A(PlaneType):
|
||||
1,
|
||||
Weapons.LAU_7_with_AIM_9B_Sidewinder_IR_AAM,
|
||||
)
|
||||
LAU_33A = (1, Weapons.LAU_33A)
|
||||
LAU_33A = (1, WeaponsOV10A.LAU_33A)
|
||||
|
||||
# ERRR {MK-81}
|
||||
|
||||
@@ -75,67 +75,67 @@ class Bronco_OV_10A(PlaneType):
|
||||
M260_HYDRA_WP = (2, Weapons.M260_HYDRA_WP)
|
||||
LAU_10R_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
2,
|
||||
Weapons.LAU_10R_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE_,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
2,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU_61R_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons.LAU_61R_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
2,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
2,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
|
||||
# ERRR {MK-81}
|
||||
@@ -154,77 +154,77 @@ class Bronco_OV_10A(PlaneType):
|
||||
M260_HYDRA_WP = (3, Weapons.M260_HYDRA_WP)
|
||||
LAU_10R_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
3,
|
||||
Weapons.LAU_10R_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE_,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
3,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU_61R_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons.LAU_61R_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
3,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
3,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
|
||||
class Pylon4:
|
||||
Fuel_Tank_150_gallons_ = (4, Weapons.Fuel_Tank_150_gallons_)
|
||||
Fuel_Tank_150_gallons_ = (4, WeaponsOV10A.Fuel_Tank_150_gallons_)
|
||||
# ERRR {MK-81}
|
||||
Mk_82___500lb_GP_Bomb_LD = (4, Weapons.Mk_82___500lb_GP_Bomb_LD)
|
||||
Mk_82_Snakeye___500lb_GP_Bomb_HD = (4, Weapons.Mk_82_Snakeye___500lb_GP_Bomb_HD)
|
||||
Mk_83___1000lb_GP_Bomb_LD = (4, Weapons.Mk_83___1000lb_GP_Bomb_LD)
|
||||
M117___750lb_GP_Bomb_LD = (4, Weapons.M117___750lb_GP_Bomb_LD)
|
||||
Mk4_mod_0 = (4, Weapons.Mk4_mod_0)
|
||||
Mk4_mod_0 = (4, WeaponsOV10A.Mk4_mod_0)
|
||||
|
||||
# ERRR {MK-81}
|
||||
|
||||
@@ -242,67 +242,67 @@ class Bronco_OV_10A(PlaneType):
|
||||
M260_HYDRA_WP = (5, Weapons.M260_HYDRA_WP)
|
||||
LAU_10R_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
5,
|
||||
Weapons.LAU_10R_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE_,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
5,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU_61R_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
5,
|
||||
Weapons.LAU_61R_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
5,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
5,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
5,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
|
||||
# ERRR {MK-81}
|
||||
@@ -321,67 +321,67 @@ class Bronco_OV_10A(PlaneType):
|
||||
M260_HYDRA_WP = (6, Weapons.M260_HYDRA_WP)
|
||||
LAU_10R_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
6,
|
||||
Weapons.LAU_10R_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE_,
|
||||
)
|
||||
LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG = (
|
||||
6,
|
||||
Weapons.LAU_10_pod___4_x_127mm_ZUNI__UnGd_Rkts_Mk71__HE_FRAG,
|
||||
Weapons.LAU_10___4_x_UnGd_Rkts__127_mm_Zuni_Mk__24_Mod__1_HE,
|
||||
)
|
||||
LAU_61R_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
6,
|
||||
Weapons.LAU_61R_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
6,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE_,
|
||||
)
|
||||
LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
6,
|
||||
Weapons.LAU_61_pod___19_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_61___19_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk1__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_FFAR__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Mk_4_FFAR_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M151__HE,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M151_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M156__Wht_Phos,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M156_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M257__Para_Illum,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M257_IL,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_M274__Practice_Smk,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_M274_TP_SM,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk1__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_1_HE,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk5__HEAT,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_5_HEAT,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_Mk61__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_Mk_61_TP,
|
||||
)
|
||||
LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice = (
|
||||
6,
|
||||
Weapons.LAU_68_pod___7_x_2_75_Hydra__UnGd_Rkts_WTU_1_B__Practice,
|
||||
Weapons.LAU_68___7_x_UnGd_Rkts__70_mm_Hydra_70_WTU_1_B_TP,
|
||||
)
|
||||
|
||||
class Pylon7:
|
||||
@@ -393,13 +393,13 @@ class Bronco_OV_10A(PlaneType):
|
||||
7,
|
||||
Weapons.LAU_7_with_AIM_9B_Sidewinder_IR_AAM,
|
||||
)
|
||||
LAU_33A = (7, Weapons.LAU_33A)
|
||||
LAU_33A = (7, WeaponsOV10A.LAU_33A)
|
||||
|
||||
class Pylon8:
|
||||
OV10_Paratrooper = (8, Weapons.OV10_Paratrooper)
|
||||
OV10_Paratrooper = (8, WeaponsOV10A.OV10_Paratrooper)
|
||||
|
||||
class Pylon9:
|
||||
OV10_SMOKE = (9, Weapons.OV10_SMOKE)
|
||||
OV10_SMOKE = (9, WeaponsOV10A.OV10_SMOKE)
|
||||
|
||||
pylons: Set[int] = {1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
|
||||
|
||||
@@ -14,11 +14,23 @@ class Su57Weapons:
|
||||
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",
|
||||
"weight": 250,
|
||||
}
|
||||
K_77M_Active_Rdr = {"clsid": "{RVV-M}", "name": "K-77M Active Rdr", "weight": 190}
|
||||
KS_172_Passive_Rdr = {
|
||||
"clsid": "{RVV-L}",
|
||||
"name": "KS-172 Passive Rdr",
|
||||
"weight": 748,
|
||||
}
|
||||
|
||||
|
||||
inject_weapons(Su57Weapons)
|
||||
@@ -44,8 +56,9 @@ class Su_57(PlaneType):
|
||||
|
||||
class Pylon1:
|
||||
R_73__AA_11_Archer____Infra_Red = (1, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
RVV_AE = (1, Su57Weapons.RVV_AE)
|
||||
RVV_M = (1, Su57Weapons.RVV_M)
|
||||
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)
|
||||
Smoke_Generator___blue = (1, Weapons.Smoke_Generator___blue)
|
||||
@@ -96,13 +109,17 @@ class Su_57(PlaneType):
|
||||
2,
|
||||
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_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
|
||||
2,
|
||||
Weapons.B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag,
|
||||
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
|
||||
)
|
||||
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
|
||||
2,
|
||||
Weapons.S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator,
|
||||
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
|
||||
)
|
||||
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
|
||||
2,
|
||||
@@ -143,10 +160,10 @@ class Su_57(PlaneType):
|
||||
2,
|
||||
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
|
||||
)
|
||||
RVV_BD = (2, Su57Weapons.RVV_BD)
|
||||
RVV_AE = (2, Su57Weapons.RVV_AE)
|
||||
RVV_M = (2, Su57Weapons.RVV_M)
|
||||
RVV_L = (2, Su57Weapons.RVV_L)
|
||||
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,
|
||||
@@ -213,13 +230,17 @@ class Su_57(PlaneType):
|
||||
4,
|
||||
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_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
|
||||
4,
|
||||
Weapons.B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag,
|
||||
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
|
||||
)
|
||||
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
|
||||
4,
|
||||
Weapons.S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator,
|
||||
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
|
||||
)
|
||||
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
|
||||
4,
|
||||
@@ -260,10 +281,10 @@ class Su_57(PlaneType):
|
||||
4,
|
||||
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
|
||||
)
|
||||
RVV_BD = (4, Su57Weapons.RVV_BD)
|
||||
RVV_AE = (4, Su57Weapons.RVV_AE)
|
||||
RVV_M = (4, Su57Weapons.RVV_M)
|
||||
RVV_L = (4, Su57Weapons.RVV_L)
|
||||
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,
|
||||
@@ -273,26 +294,26 @@ class Su_57(PlaneType):
|
||||
|
||||
class Pylon5:
|
||||
R_77__AA_12_Adder____Active_Rdr = (5, Weapons.R_77__AA_12_Adder____Active_Rdr)
|
||||
RVV_AE = (5, Su57Weapons.RVV_AE)
|
||||
RVV_M = (5, Su57Weapons.RVV_M)
|
||||
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)
|
||||
RVV_AE = (6, Su57Weapons.RVV_AE)
|
||||
RVV_M = (6, Su57Weapons.RVV_M)
|
||||
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)
|
||||
RVV_AE = (7, Su57Weapons.RVV_AE)
|
||||
RVV_M = (7, Su57Weapons.RVV_M)
|
||||
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)
|
||||
RVV_AE = (8, Su57Weapons.RVV_AE)
|
||||
RVV_M = (8, Su57Weapons.RVV_M)
|
||||
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:
|
||||
@@ -338,13 +359,17 @@ class Su_57(PlaneType):
|
||||
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_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag,
|
||||
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
|
||||
)
|
||||
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
|
||||
9,
|
||||
Weapons.S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator,
|
||||
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
|
||||
)
|
||||
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
|
||||
9,
|
||||
@@ -385,10 +410,10 @@ class Su_57(PlaneType):
|
||||
9,
|
||||
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
|
||||
)
|
||||
RVV_BD = (9, Su57Weapons.RVV_BD)
|
||||
RVV_AE = (9, Su57Weapons.RVV_AE)
|
||||
RVV_M = (9, Su57Weapons.RVV_M)
|
||||
RVV_L = (9, Su57Weapons.RVV_L)
|
||||
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,
|
||||
@@ -448,13 +473,17 @@ class Su_57(PlaneType):
|
||||
11,
|
||||
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_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
|
||||
11,
|
||||
Weapons.B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag,
|
||||
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
|
||||
)
|
||||
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
|
||||
11,
|
||||
Weapons.S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator,
|
||||
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
|
||||
)
|
||||
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
|
||||
11,
|
||||
@@ -499,10 +528,10 @@ class Su_57(PlaneType):
|
||||
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
|
||||
)
|
||||
# ERRR {R-33}
|
||||
RVV_BD = (11, Su57Weapons.RVV_BD)
|
||||
RVV_AE = (11, Su57Weapons.RVV_AE)
|
||||
RVV_M = (11, Su57Weapons.RVV_M)
|
||||
RVV_L = (11, Su57Weapons.RVV_L)
|
||||
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 = (
|
||||
@@ -519,8 +548,8 @@ class Su_57(PlaneType):
|
||||
|
||||
class Pylon12:
|
||||
R_73__AA_11_Archer____Infra_Red = (12, Weapons.R_73__AA_11_Archer____Infra_Red)
|
||||
RVV_AE = (12, Su57Weapons.RVV_AE)
|
||||
RVV_M = (12, Su57Weapons.RVV_M)
|
||||
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)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Application-wide dialog management."""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from game.ato.flight import Flight
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Qt data models for game objects."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
@@ -176,6 +177,9 @@ class PackageModel(QAbstractListModel):
|
||||
"""Removes the given flight from the package."""
|
||||
with self.game_model.sim_controller.paused_sim():
|
||||
index = self.package.flights.index(flight)
|
||||
self.game_model.game.blue.callsign_generator.release_callsign(
|
||||
flight.callsign
|
||||
)
|
||||
self.beginRemoveRows(QModelIndex(), index, index)
|
||||
self.package.remove_flight(flight)
|
||||
self.endRemoveRows()
|
||||
@@ -301,6 +305,10 @@ class AtoModel(QAbstractListModel):
|
||||
self.package_models.release(package)
|
||||
index = self.ato.packages.index(package)
|
||||
self.beginRemoveRows(QModelIndex(), index, index)
|
||||
for flight in package.flights:
|
||||
self.game_model.game.blue.callsign_generator.release_callsign(
|
||||
flight.callsign
|
||||
)
|
||||
self.ato.remove_package(package)
|
||||
self.endRemoveRows()
|
||||
# noinspection PyUnresolvedReferences
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Spin box for selecting the number of aircraft in a flight."""
|
||||
|
||||
from PySide6.QtWidgets import QSpinBox
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""A layout containing a widget with an associated label."""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
@@ -16,6 +16,7 @@ from game import Game, persistence
|
||||
from game.ato.package import Package
|
||||
from game.ato.traveltime import TotEstimator
|
||||
from game.profiling import logged_duration
|
||||
from game.settings.settings import FastForwardStopCondition
|
||||
from game.utils import meters
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.simcontroller import SimController
|
||||
@@ -248,50 +249,6 @@ class QTopPanel(QFrame):
|
||||
mbox.exec_()
|
||||
return True
|
||||
|
||||
def check_valid_autoresolve_settings(self) -> bool:
|
||||
if not self.game.settings.fast_forward_to_first_contact:
|
||||
return True
|
||||
|
||||
if not self.game.settings.auto_resolve_combat:
|
||||
return True
|
||||
|
||||
has_clients = self.ato_has_clients()
|
||||
if (
|
||||
has_clients
|
||||
and self.game.settings.player_mission_interrupts_sim_at is not None
|
||||
):
|
||||
return True
|
||||
|
||||
if has_clients:
|
||||
message = textwrap.dedent(
|
||||
"""\
|
||||
You have enabled settings to fast forward and to auto-resolve combat,
|
||||
but have not selected any interrupt condition. Fast forward will never
|
||||
stop with your current settings. To use auto- resolve, you must choose a
|
||||
"Player missions interrupt fast forward" setting other than "Never".
|
||||
"""
|
||||
)
|
||||
else:
|
||||
message = textwrap.dedent(
|
||||
"""\
|
||||
You have enabled settings to fast forward and to auto-resolve combat,
|
||||
but have no players. Fast forward will never stop with your current
|
||||
settings. Auto-resolve and fast forward cannot be used without player
|
||||
flights and a "Player missions interrupt fast forward" setting other
|
||||
than "Never".
|
||||
"""
|
||||
)
|
||||
|
||||
mbox = QMessageBox(
|
||||
QMessageBox.Icon.Critical,
|
||||
"Incompatible fast-forward settings",
|
||||
message,
|
||||
parent=self,
|
||||
)
|
||||
mbox.setEscapeButton(mbox.addButton(QMessageBox.StandardButton.Close))
|
||||
mbox.exec()
|
||||
return False
|
||||
|
||||
def launch_mission(self):
|
||||
"""Finishes planning and waits for mission completion."""
|
||||
if not self.ato_has_clients() and not self.confirm_no_client_launch():
|
||||
@@ -307,10 +264,10 @@ class QTopPanel(QFrame):
|
||||
if not self.confirm_negative_start_time(negative_starts):
|
||||
return
|
||||
|
||||
if not self.check_valid_autoresolve_settings():
|
||||
return
|
||||
|
||||
if self.game.settings.fast_forward_to_first_contact:
|
||||
if self.game.settings.fast_forward_stop_condition not in [
|
||||
FastForwardStopCondition.DISABLED,
|
||||
FastForwardStopCondition.MANUAL,
|
||||
]:
|
||||
with logged_duration("Simulating to first contact"):
|
||||
self.sim_controller.run_to_first_contact()
|
||||
self.sim_controller.generate_miz(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user