Merge remote-tracking branch 'remotes/dcs-retribution/dcs-retribution/dev' into pretense-generator

This commit is contained in:
MetalStormGhost 2024-05-09 21:16:32 +03:00
commit 48861c53da
25 changed files with 262 additions and 73 deletions

View File

@ -1,5 +1,5 @@
name: Build Liberation package name: Build Retribution package
description: Assembles the full Liberation application. description: Assembles the full Retribution application.
runs: runs:
using: composite using: composite
steps: steps:

View File

@ -1,5 +1,5 @@
name: Liberation JS set-up name: Retribution JS set-up
description: Sets up the Liberation Javascript environment. description: Sets up the Retribution Javascript environment.
runs: runs:
using: composite using: composite
steps: steps:

View File

@ -1,5 +1,5 @@
name: Liberation Python set-up name: Retribution Python set-up
description: Sets up the Liberation Python environment. description: Sets up the Retribution Python environment.
runs: runs:
using: composite using: composite
steps: steps:

View File

@ -10,6 +10,8 @@
* **[Campaign Setup]** Allow adjustments to naval TGOs (except carriers) on turn 0 * **[Campaign Setup]** Allow adjustments to naval TGOs (except carriers) on turn 0
* **[Campaign Design]** Ability to configure specific carrier names & types in campaign's yaml file * **[Campaign Design]** Ability to configure specific carrier names & types in campaign's yaml file
* **[Mission Generation]** Ability to inject custom kneeboards * **[Mission Generation]** Ability to inject custom kneeboards
* **[Options]** Extend option (so it can be disabled when fixed in DCS) to force air-starts (except for the slots that work) at Ramon Airbase, similar to the Nevatim fix in Retribution 1.3.0
* **[Options]** New option in Settings: Default start type for Player flights.
## Fixes ## Fixes
* **[UI/UX]** A-10A flights can be edited again. * **[UI/UX]** A-10A flights can be edited again.

View File

@ -22,6 +22,10 @@ class FlightRoster(IFlightRoster):
def iter_pilots(self) -> Iterator[Pilot | None]: def iter_pilots(self) -> Iterator[Pilot | None]:
yield from self.pilots yield from self.pilots
@property
def player_count(self) -> int:
return len([p for p in self.pilots if p is not None and p.player])
def pilot_at(self, idx: int) -> Pilot | None: def pilot_at(self, idx: int) -> Pilot | None:
return self.pilots[idx] return self.pilots[idx]

View File

@ -26,6 +26,11 @@ class IFlightRoster(ABC):
def max_size(self) -> int: def max_size(self) -> int:
... ...
@property
@abstractmethod
def player_count(self) -> int:
...
@abstractmethod @abstractmethod
def resize(self, new_size: int) -> None: def resize(self, new_size: int) -> None:
... ...

View File

@ -76,6 +76,12 @@ class PackageBuilder:
member.assign_tgp_laser_code( member.assign_tgp_laser_code(
self.laser_code_registry.alloc_laser_code() self.laser_code_registry.alloc_laser_code()
) )
# If this is a client flight, set the start_type again to match the configured default
# https://github.com/dcs-liberation/dcs_liberation/issues/1567
if flight.roster is not None and flight.roster.player_count > 0:
flight.start_type = (
squadron.coalition.game.settings.default_start_type_client
)
self.package.add_flight(flight) self.package.add_flight(flight)
return True return True

View File

@ -363,7 +363,7 @@ class Debriefing:
seen = set() seen = set()
captures = [] captures = []
for capture in reversed(self.state_data.base_capture_events): for capture in reversed(self.state_data.base_capture_events):
# The ID string in the JSON file will be the UUID generated from liberation # The ID string in the JSON file will be the UUID generated from retribution
cp_id, new_owner_id_str, _name = capture.split("||") cp_id, new_owner_id_str, _name = capture.split("||")
# Only the most recent capture event matters. # Only the most recent capture event matters.

View File

@ -20,7 +20,7 @@ from dcs.planes import (
from dcs.point import PointAction from dcs.point import PointAction
from dcs.ships import KUZNECOW from dcs.ships import KUZNECOW
from dcs.terrain import NoParkingSlotError, Sinai, ParkingSlot from dcs.terrain import NoParkingSlotError, Sinai, ParkingSlot
from dcs.terrain.sinai.airports import Nevatim from dcs.terrain.sinai.airports import Nevatim, Ramon_Airbase
from dcs.unitgroup import ( from dcs.unitgroup import (
FlyingGroup, FlyingGroup,
ShipGroup, ShipGroup,
@ -132,6 +132,16 @@ class FlightGroupSpawner:
for slot in cp.dcs_airport.free_parking_slots(ac_type) for slot in cp.dcs_airport.free_parking_slots(ac_type)
if slot.slot_name in [str(n) for n in range(55, 66)] if slot.slot_name in [str(n) for n in range(55, 66)]
] ]
elif self._check_ramon_airbase_hack(cp):
ac_type = self.flight.unit_type.dcs_unit_type
slots = [
slot
for slot in cp.dcs_airport.free_parking_slots(ac_type)
if slot.slot_name
not in [
str(n) for n in [1, 2, 3, 4, 5, 6, 13, 14, 15, 16, 17, 18, 61]
]
]
group = self._generate_at_airfield( group = self._generate_at_airfield(
name=namegen.next_aircraft_name(self.country, self.flight), name=namegen.next_aircraft_name(self.country, self.flight),
airfield=cp, airfield=cp,
@ -215,6 +225,20 @@ class FlightGroupSpawner:
if slot.slot_name in [str(n) for n in range(55, 66)] if slot.slot_name in [str(n) for n in range(55, 66)]
] ]
return self._generate_at_airfield(name, cp, slots) return self._generate_at_airfield(name, cp, slots)
elif self._check_ramon_airbase_hack(cp):
# TODO: get rid of the ramon airbase hack once fixed in DCS...
slots = [
slot
for slot in cp.dcs_airport.free_parking_slots(
self.flight.squadron.aircraft.dcs_unit_type
)
if slot.slot_name
not in [
str(n)
for n in [1, 2, 3, 4, 5, 6, 13, 14, 15, 16, 17, 18, 61]
]
]
return self._generate_at_airfield(name, cp, slots)
else: else:
return self._generate_at_airfield(name, cp) return self._generate_at_airfield(name, cp)
else: else:
@ -237,6 +261,13 @@ class FlightGroupSpawner:
nevatim_hack &= isinstance(cp.dcs_airport, Nevatim) nevatim_hack &= isinstance(cp.dcs_airport, Nevatim)
return nevatim_hack return nevatim_hack
def _check_ramon_airbase_hack(self, cp: ControlPoint) -> bool:
# TODO: get rid of the ramon airbase hack once fixed in DCS...
ramon_airbase_hack = self.flight.coalition.game.settings.nevatim_parking_fix
ramon_airbase_hack &= isinstance(self.mission.terrain, Sinai)
ramon_airbase_hack &= isinstance(cp.dcs_airport, Ramon_Airbase)
return ramon_airbase_hack
def generate_mid_mission(self) -> FlyingGroup[Any]: def generate_mid_mission(self) -> FlyingGroup[Any]:
assert isinstance(self.flight.state, InFlight) assert isinstance(self.flight.state, InFlight)
name = namegen.next_aircraft_name(self.country, self.flight) name = namegen.next_aircraft_name(self.country, self.flight)

View File

@ -756,14 +756,22 @@ class Settings:
"will not be included in automatically planned OCA packages." "will not be included in automatically planned OCA packages."
), ),
) )
default_start_type_client: StartType = choices_option(
"Default start type for Player flights",
page=MISSION_GENERATOR_PAGE,
section=GAMEPLAY_SECTION,
choices={v.value: v for v in StartType},
default=StartType.COLD,
detail=("Default start type for flights containing Player/Client slots."),
)
nevatim_parking_fix: bool = boolean_option( nevatim_parking_fix: bool = boolean_option(
"Force air-starts for all aircraft at Nevatim", "Force air-starts for aircraft at Nevatim and Ramon Airbase inoperable parking slots",
page=MISSION_GENERATOR_PAGE, page=MISSION_GENERATOR_PAGE,
section=GAMEPLAY_SECTION, section=GAMEPLAY_SECTION,
default=True, # TODO: set to False or remove this when DCS is fixed default=True, # TODO: set to False or remove this when DCS is fixed
detail=( detail=(
"Air-starts forced for all aircraft at Nevatim except parking slots " "Air-starts forced for all aircraft at Nevatim and Ramon Airbase except parking slots "
"55 till 65, since those are the only ones that work." "which are known to work as of DCS World 2.9.4.53990."
), ),
) )
# Mission specific # Mission specific

View File

@ -1,4 +1,4 @@
"""Maps generated units back to their Liberation types.""" """Maps generated units back to their Retribution types."""
from __future__ import annotations from __future__ import annotations
import itertools import itertools

View File

@ -30,7 +30,7 @@ def _build_version_string() -> str:
return "-".join(components) return "-".join(components)
#: Current version of Liberation. #: Current version of Retribution.
VERSION = _build_version_string() VERSION = _build_version_string()
#: The latest version of the campaign format. Increment this version whenever all #: The latest version of the campaign format. Increment this version whenever all

View File

@ -89,8 +89,7 @@ class QFlightCreator(QDialog):
roster = None roster = None
else: else:
roster = FlightRoster( roster = FlightRoster(
squadron, squadron, initial_size=self.flight_size_spinner.value()
initial_size=self.flight_size_spinner.value(),
) )
self.roster_editor = FlightRosterEditor(squadron, roster) self.roster_editor = FlightRosterEditor(squadron, roster)
self.flight_size_spinner.valueChanged.connect(self.roster_editor.resize) self.flight_size_spinner.valueChanged.connect(self.roster_editor.resize)
@ -100,10 +99,12 @@ class QFlightCreator(QDialog):
roster_layout.addWidget(QLabel("Assigned pilots:")) roster_layout.addWidget(QLabel("Assigned pilots:"))
roster_layout.addLayout(self.roster_editor) roster_layout.addLayout(self.roster_editor)
self.roster_editor.pilots_changed.connect(self.on_pilot_selected)
# When an off-map spawn overrides the start type to in-flight, we save # When an off-map spawn overrides the start type to in-flight, we save
# the selected type into this value. If a non-off-map spawn is selected # the selected type into this value. If a non-off-map spawn is selected
# we restore the previous choice. # we restore the previous choice.
self.restore_start_type = self.game.settings.default_start_type self.restore_start_type: Optional[str] = None
self.start_type = QComboBox() self.start_type = QComboBox()
for start_type in StartType: for start_type in StartType:
self.start_type.addItem(start_type.value, start_type) self.start_type.addItem(start_type.value, start_type)
@ -140,6 +141,8 @@ class QFlightCreator(QDialog):
self.setLayout(layout) self.setLayout(layout)
self.roster_editor.pilots_changed.emit()
def reject(self) -> None: def reject(self) -> None:
super().reject() super().reject()
# Clear the roster to return pilots to the pool. # Clear the roster to return pilots to the pool.
@ -213,6 +216,8 @@ class QFlightCreator(QDialog):
) )
self.divert.change_aircraft(new_aircraft) self.divert.change_aircraft(new_aircraft)
self.roster_editor.pilots_changed.emit()
def on_departure_changed(self, departure: ControlPoint) -> None: def on_departure_changed(self, departure: ControlPoint) -> None:
if isinstance(departure, OffMapSpawn): if isinstance(departure, OffMapSpawn):
previous_type = self.start_type.currentData() previous_type = self.start_type.currentData()
@ -245,6 +250,8 @@ class QFlightCreator(QDialog):
) )
self.on_departure_changed(squadron.location) self.on_departure_changed(squadron.location)
self.roster_editor.pilots_changed.emit()
def update_max_size(self, available: int) -> None: def update_max_size(self, available: int) -> None:
aircraft = self.aircraft_selector.currentData() aircraft = self.aircraft_selector.currentData()
if aircraft is None: if aircraft is None:
@ -255,3 +262,23 @@ class QFlightCreator(QDialog):
default_size = max(2, available, aircraft.max_group_size) default_size = max(2, available, aircraft.max_group_size)
self.flight_size_spinner.setValue(default_size) self.flight_size_spinner.setValue(default_size)
try:
self.roster_editor.pilots_changed.emit()
except AttributeError:
return
def on_pilot_selected(self):
# Pilot selection detected. If this is a player flight, set start_type
# as configured for players in the settings.
# Otherwise, set the start_type as configured for AI.
# https://github.com/dcs-liberation/dcs_liberation/issues/1567
roster = self.roster_editor.roster
if roster is not None and roster.player_count > 0:
start_type = self.game.settings.default_start_type_client
else:
start_type = self.game.settings.default_start_type
self.start_type.setCurrentText(start_type.value)

View File

@ -96,11 +96,16 @@ class PilotControls(QHBoxLayout):
player_toggled = Signal() player_toggled = Signal()
def __init__( def __init__(
self, squadron: Optional[Squadron], roster: Optional[FlightRoster], idx: int self,
squadron: Optional[Squadron],
roster: Optional[FlightRoster],
idx: int,
pilots_changed: Signal,
) -> None: ) -> None:
super().__init__() super().__init__()
self.roster = roster self.roster = roster
self.pilot_index = idx self.pilot_index = idx
self.pilots_changed = pilots_changed
self.selector = PilotSelector(squadron, roster, idx) self.selector = PilotSelector(squadron, roster, idx)
self.selector.currentIndexChanged.connect(self.on_pilot_changed) self.selector.currentIndexChanged.connect(self.on_pilot_changed)
@ -131,6 +136,8 @@ class PilotControls(QHBoxLayout):
pilot.player = checked pilot.player = checked
self.player_toggled.emit() self.player_toggled.emit()
self.pilots_changed.emit()
def on_pilot_changed(self, index: int) -> None: def on_pilot_changed(self, index: int) -> None:
pilot = self.selector.itemData(index) pilot = self.selector.itemData(index)
self.player_checkbox.blockSignals(True) self.player_checkbox.blockSignals(True)
@ -143,6 +150,10 @@ class PilotControls(QHBoxLayout):
if self.roster is not None: if self.roster is not None:
self.player_checkbox.setEnabled(self.roster.squadron.aircraft.flyable) self.player_checkbox.setEnabled(self.roster.squadron.aircraft.flyable)
self.player_checkbox.blockSignals(False) self.player_checkbox.blockSignals(False)
# on_pilot_changed should emit pilots_changed in its finally block,
# otherwise the start-type isn't updated if you have a single client
# pilot which you switch to a non-client pilot
self.pilots_changed.emit()
def update_available_pilots(self) -> None: def update_available_pilots(self) -> None:
self.selector.rebuild() self.selector.rebuild()
@ -174,9 +185,12 @@ class PilotControls(QHBoxLayout):
class FlightRosterEditor(QVBoxLayout): class FlightRosterEditor(QVBoxLayout):
MAX_PILOTS = 4 MAX_PILOTS = 4
pilots_changed = Signal()
def __init__( def __init__(
self, squadron: Optional[Squadron], roster: Optional[IFlightRoster] self,
squadron: Optional[Squadron],
roster: Optional[IFlightRoster],
) -> None: ) -> None:
super().__init__() super().__init__()
self.roster = roster self.roster = roster
@ -190,7 +204,7 @@ class FlightRosterEditor(QVBoxLayout):
return callback return callback
controls = PilotControls(squadron, roster, pilot_idx) controls = PilotControls(squadron, roster, pilot_idx, self.pilots_changed)
controls.selector.available_pilots_changed.connect( controls.selector.available_pilots_changed.connect(
make_reset_callback(pilot_idx) make_reset_callback(pilot_idx)
) )
@ -226,7 +240,12 @@ class FlightRosterEditor(QVBoxLayout):
class QFlightSlotEditor(QGroupBox): class QFlightSlotEditor(QGroupBox):
flight_resized = Signal(int) flight_resized = Signal(int)
def __init__(self, package_model: PackageModel, flight: Flight, game: Game): def __init__(
self,
package_model: PackageModel,
flight: Flight,
game: Game,
):
super().__init__("Slots") super().__init__("Slots")
self.package_model = package_model self.package_model = package_model
self.flight = flight self.flight = flight

View File

@ -43,6 +43,25 @@ class QFlightStartType(QGroupBox):
) )
self.setLayout(self.layout) self.setLayout(self.layout)
def on_pilot_selected(self):
# Pilot selection detected. If this is a player flight, set start_type
# as configured for players in the settings.
# Otherwise, set the start_type as configured for AI.
# https://github.com/dcs-liberation/dcs_liberation/issues/1567
if self.flight.roster.player_count > 0:
self.flight.start_type = (
self.flight.coalition.game.settings.default_start_type_client
)
else:
self.flight.start_type = (
self.flight.coalition.game.settings.default_start_type
)
self.start_type.setCurrentText(self.flight.start_type.value)
self.package_model.update_tot()
def _on_start_type_selected(self): def _on_start_type_selected(self):
selected = self.start_type.currentData() selected = self.start_type.currentData()
self.flight.start_type = selected self.flight.start_type = selected

View File

@ -38,6 +38,17 @@ class QGeneralFlightSettingsTab(QFrame):
self.flight_slot_editor.flight_resized.connect(self.flight_size_changed) self.flight_slot_editor.flight_resized.connect(self.flight_size_changed)
for pc in self.flight_slot_editor.roster_editor.pilot_controls: for pc in self.flight_slot_editor.roster_editor.pilot_controls:
pc.player_toggled.connect(self.on_player_toggle) pc.player_toggled.connect(self.on_player_toggle)
pc.player_toggled.connect(
self.flight_slot_editor.roster_editor.pilots_changed
)
start_type = QFlightStartType(
package_model,
flight,
)
roster = self.flight_slot_editor.roster_editor
roster.pilots_changed.connect(start_type.on_pilot_selected)
widgets = [ widgets = [
QFlightTypeTaskInfo(flight), QFlightTypeTaskInfo(flight),
@ -46,7 +57,7 @@ class QGeneralFlightSettingsTab(QFrame):
game.game, package_model, flight, flight_wpt_list game.game, package_model, flight, flight_wpt_list
), ),
self.flight_slot_editor, self.flight_slot_editor,
QFlightStartType(package_model, flight), start_type,
QFlightCustomName(flight), QFlightCustomName(flight),
] ]
layout = QGridLayout() layout = QGridLayout()

View File

@ -154,34 +154,34 @@ class GeneratorOptions(QtWidgets.QWizardPage):
modLayout_row = 1 modLayout_row = 1
mod_pairs = [ mod_pairs = [
("F9F Panther (v2.8.7.101)", self.f9f_panther),
("A-4E Skyhawk (v2.2.0)", self.a4_skyhawk), ("A-4E Skyhawk (v2.2.0)", self.a4_skyhawk),
("A-6A Intruder (v2.7.5.01)", self.a6a_intruder), ("A-6A Intruder (v2.7.5.01)", self.a6a_intruder),
("A-7E Corsair II", self.a7e_corsair2), ("A-7E Corsair II", self.a7e_corsair2),
("C-130J-30 Super Hercules", self.hercules), ("C-130J-30 Super Hercules (v6.8.2)", self.hercules),
("F-4B/C Phantom II (2.8.7.204)", self.f4bc_phantom),
("F-15D Baz (v1.0)", self.f15d_baz),
("F-15I Ra'am (v1.0 by IDF Mods Project)", self.f_15_idf),
("F-16I Sufa & F-16D (v3.6 by IDF Mods Project)", self.f_16_idf),
("F/A-18E/F/G Super Hornet (version 2.2.5)", self.fa_18efg),
("F/A-18E/F Super Hornet AI Tanker (version 1.4)", self.fa18ef_tanker),
("F-22A Raptor", self.f22_raptor),
("F-84G Thunderjet (v2.5.7.01)", self.f84g_thunderjet),
("F-100 Super Sabre (v2.7.18.30765 patch 20.10.22)", self.f100_supersabre), ("F-100 Super Sabre (v2.7.18.30765 patch 20.10.22)", self.f100_supersabre),
("F-104 Starfighter (v2.7.11.222.01)", self.f104_starfighter), ("F-104 Starfighter (v2.7.11.222.01)", self.f104_starfighter),
("F-105 Thunderchief (v2.7.12.23x)", self.f105_thunderchief), ("F-105 Thunderchief (v2.7.12.23x)", self.f105_thunderchief),
("Frenchpack", self.frenchpack), ("F-15D Baz (v1.0)", self.f15d_baz),
("F-15I Ra'am (v1.0 by IDF Mods Project)", self.f_15_idf),
("F-16I Sufa & F-16D (v3.6 by IDF Mods Project)", self.f_16_idf),
("F-22A Raptor", self.f22_raptor),
("F-4B/C Phantom II (2.8.7.204)", self.f4bc_phantom),
("F-84G Thunderjet (v2.5.7.01)", self.f84g_thunderjet),
("F9F Panther (v2.8.7.101)", self.f9f_panther),
("F/A-18E/F Super Hornet AI Tanker (version 1.4)", self.fa18ef_tanker),
("F/A-18E/F/G Super Hornet (version 2.2.5)", self.fa_18efg),
("Frenchpack (v4.9.1)", self.frenchpack),
("High Digit SAMs", self.high_digit_sams), ("High Digit SAMs", self.high_digit_sams),
("Swedish Military Assets pack (1.10)", self.swedishmilitaryassetspack), ("IDF Assets Pack (v1.1 by IDF Mods Project)", self.irondome),
("JAS 39 Gripen (v1.8.5-beta)", self.jas39_gripen), ("JAS 39 Gripen (v1.8.5-beta)", self.jas39_gripen),
("OV-10A Bronco", self.ov10a_bronco), ("OV-10A Bronco", self.ov10a_bronco),
("Super Étendard (v2.5.5)", self.super_etendard),
("Su-30 Flanker-H (V2.7.3 beta)", self.su30_flanker_h),
("Su-57 Felon (build-04)", self.su57_felon),
("UH-60L Black Hawk (v1.3.1)", self.uh_60l),
("Star Wars Modpack 2.54+", self.SWPack),
("Spanish Naval Assets pack (desdemicabina 3.2.0)", self.spanishnavypack), ("Spanish Naval Assets pack (desdemicabina 3.2.0)", self.spanishnavypack),
("IDF Assets Pack (v1.1 by IDF Mods Project)", self.irondome), ("Star Wars Modpack 2.54+", self.SWPack),
("Su-30 Flanker-H (V2.7.3 beta)", self.su30_flanker_h),
("Su-57 Felon (build-04)", self.su57_felon),
("Super Étendard (v2.5.5)", self.super_etendard),
("Swedish Military Assets pack (1.10)", self.swedishmilitaryassetspack),
("UH-60L Black Hawk (v1.3.1)", self.uh_60l),
] ]
for i in range(len(mod_pairs)): for i in range(len(mod_pairs)):

View File

@ -148,7 +148,7 @@ class QLiberationPreferences(QFrame):
"You set an empty DCS Installation directory! " "You set an empty DCS Installation directory! "
"<br/><br/>Without this directory, DCS Retribution can not replace the MissionScripting.lua for you and will not work properly. " "<br/><br/>Without this directory, DCS Retribution can not replace the MissionScripting.lua for you and will not work properly. "
"In this case, you need to edit the MissionScripting.lua yourself. The easiest way to do it is to replace the original file (&lt;dcs_installation_directory&gt;/Scripts/MissionScripting.lua) with the file in dcs-liberation distribution (&lt;dcs_liberation_installation&gt;/resources/scripts/MissionScripting.lua)." "In this case, you need to edit the MissionScripting.lua yourself. The easiest way to do it is to replace the original file (&lt;dcs_installation_directory&gt;/Scripts/MissionScripting.lua) with the file in dcs-liberation distribution (&lt;dcs_liberation_installation&gt;/resources/scripts/MissionScripting.lua)."
"<br/><br/>You can find more information on how to manually change this file in the Liberation Wiki (Page: Dedicated Server Guide) on GitHub.</p>" "<br/><br/>You can find more information on how to manually change this file in the Retribution Wiki (Page: Dedicated Server Guide) on GitHub.</p>"
"<br/><br/>Are you sure that you want to leave the installation directory empty?" "<br/><br/>Are you sure that you want to leave the installation directory empty?"
"<br/><br/><strong>This is only recommended for expert users!</strong>", "<br/><br/><strong>This is only recommended for expert users!</strong>",
QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.Yes,
@ -164,7 +164,7 @@ class QLiberationPreferences(QFrame):
+ " is not a valid directory. DCS Retribution requires the installation directory to replace the MissionScripting.lua" + " is not a valid directory. DCS Retribution requires the installation directory to replace the MissionScripting.lua"
"<br/><br/>If you ignore this Error, DCS Retribution can not work properly and needs your attention. " "<br/><br/>If you ignore this Error, DCS Retribution can not work properly and needs your attention. "
"In this case, you need to edit the MissionScripting.lua yourself. The easiest way to do it is to replace the original file (&lt;dcs_installation_directory&gt;/Scripts/MissionScripting.lua) with the file in dcs-liberation distribution (&lt;dcs_liberation_installation&gt;/resources/scripts/MissionScripting.lua)." "In this case, you need to edit the MissionScripting.lua yourself. The easiest way to do it is to replace the original file (&lt;dcs_installation_directory&gt;/Scripts/MissionScripting.lua) with the file in dcs-liberation distribution (&lt;dcs_liberation_installation&gt;/resources/scripts/MissionScripting.lua)."
"<br/><br/>You can find more information on how to manually change this file in the Liberation Wiki (Page: Dedicated Server Guide) on GitHub.</p>" "<br/><br/>You can find more information on how to manually change this file in the Retribution Wiki (Page: Dedicated Server Guide) on GitHub.</p>"
"<br/><br/><strong>This is only recommended for expert users!</strong>", "<br/><br/><strong>This is only recommended for expert users!</strong>",
QMessageBox.StandardButton.Ignore, QMessageBox.StandardButton.Ignore,
QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.Ok,

View File

@ -3,7 +3,7 @@ theater: Caucasus
authors: Khopa authors: Khopa
recommended_player_faction: Russia 2010 recommended_player_faction: Russia 2010
recommended_enemy_faction: USA 1990 recommended_enemy_faction: USA 1990
description: <p>A small theater in Russia, progress from Mozdok to Maykop.</p><p>This scenario is pretty simple, and is ideal if you want to run a short campaign to try liberation. If your PC is not powerful, this is also the less performance heavy scenario.</p> description: <p>A small theater in Russia, progress from Mozdok to Maykop.</p><p>This scenario is pretty simple, and is ideal if you want to run a short campaign to try Retribution. If your PC is not powerful, this is also the less performance heavy scenario.</p>
miz: mozdok_to_maykop.miz miz: mozdok_to_maykop.miz
performance: 0 performance: 0
version: 9.0 version: 9.0

View File

@ -1,50 +1,95 @@
local unitPayloads = local unitPayloads = {
{
["name"] = "UH-60L", ["name"] = "UH-60L",
["payloads"] = ["payloads"] = {
{ [1] = {
[1] = ["name"] = "Liberation Air Assault",
{ ["pylons"] = {
["name"] = "Retribution Ferry",
["pylons"] =
{
[1] = { [1] = {
["CLSID"] = "{UH60_FUEL_TANK_230}", ["CLSID"] = "<CLEAN>",
["num"] = 7, ["num"] = 7,
}, },
[2] = { [2] = {
["CLSID"] = "{UH60_FUEL_TANK_230}", ["CLSID"] = "<CLEAN>",
["num"] = 1, ["num"] = 1,
}, },
[3] = { [3] = {
["CLSID"] = "{UH60_FUEL_TANK_230}", ["CLSID"] = "<CLEAN>",
["num"] = 2, ["num"] = 2,
}, },
[4] = { [4] = {
["CLSID"] = "{UH60_FUEL_TANK_230}", ["CLSID"] = "<CLEAN>",
["num"] = 6, ["num"] = 6,
}, },
[5] = { [5] = {
["CLSID"] = "{UH60_SEAT_GUNNER_L}",
["num"] = 3,
},
[6] = {
["CLSID"] = "{UH60_SEAT_CARGO_ALL}", ["CLSID"] = "{UH60_SEAT_CARGO_ALL}",
["num"] = 4, ["num"] = 4,
}, },
[7] = { },
["CLSID"] = "{UH60_SEAT_GUNNER_R}", ["tasks"] = {
["num"] = 5, [1] = 35,
},
},
[2] = {
["displayName"] = "Liberation Ferry",
["name"] = "Liberation Ferry",
["pylons"] = {
[1] = {
["CLSID"] = "<CLEAN>",
["num"] = 7,
},
[2] = {
["CLSID"] = "<CLEAN>",
["num"] = 1,
},
[3] = {
["CLSID"] = "{UH60_SEAT_CARGO_ALL}",
["num"] = 4,
},
[4] = {
["CLSID"] = "<CLEAN>",
["num"] = 6,
},
[5] = {
["CLSID"] = "<CLEAN>",
["num"] = 2,
}, },
}, },
["tasks"] = ["tasks"] = {
{ [1] = 35,
},
},
[3] = {
["displayName"] = "Liberation Transport",
["name"] = "Liberation Transport",
["pylons"] = {
[1] = {
["CLSID"] = "<CLEAN>",
["num"] = 7,
},
[2] = {
["CLSID"] = "<CLEAN>",
["num"] = 1,
},
[3] = {
["CLSID"] = "<CLEAN>",
["num"] = 2,
},
[4] = {
["CLSID"] = "<CLEAN>",
["num"] = 6,
},
[5] = {
["CLSID"] = "{UH60_SEAT_CARGO_ALL}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 35, [1] = 35,
[2] = 17,
}, },
}, },
}, },
["tasks"] = {}, ["tasks"] = {
},
["unitType"] = "UH-60L", ["unitType"] = "UH-60L",
} }
return unitPayloads return unitPayloads

View File

@ -12,8 +12,11 @@
"AJS-37 Viggen", "AJS-37 Viggen",
"AV-8B Harrier II Night Attack", "AV-8B Harrier II Night Attack",
"B-52H Stratofortress", "B-52H Stratofortress",
"C-101CC Aviojet",
"C-130", "C-130",
"C-130J-30 Super Hercules", "C-130J-30 Super Hercules",
"CH-47D",
"CH-53E",
"F-14A Tomcat (Block 135-GR Late)", "F-14A Tomcat (Block 135-GR Late)",
"F-14B Tomcat", "F-14B Tomcat",
"F-15C Eagle", "F-15C Eagle",
@ -22,6 +25,7 @@
"F/A-18C Hornet (Lot 20)", "F/A-18C Hornet (Lot 20)",
"F-4E Phantom II", "F-4E Phantom II",
"F-5E Tiger II", "F-5E Tiger II",
"Mi-8MTV2 Hip",
"MiG-21bis Fishbed-N", "MiG-21bis Fishbed-N",
"Mirage-F1B", "Mirage-F1B",
"Mirage-F1BE", "Mirage-F1BE",
@ -31,7 +35,9 @@
"S-3B Viking", "S-3B Viking",
"SA 342L Gazelle", "SA 342L Gazelle",
"SA 342M Gazelle", "SA 342M Gazelle",
"UH-1H Iroquois" "UH-1H Iroquois",
"UH-60A",
"UH-60L"
], ],
"awacs": [ "awacs": [
"E-2C Hawkeye", "E-2C Hawkeye",

View File

@ -2,23 +2,27 @@
"country": "Russia", "country": "Russia",
"name": "Russia 1980", "name": "Russia 1980",
"authors": "Starfire", "authors": "Starfire",
"description": "<p>Soviet army in the 1980s.</p>", "description": "<p>Soviet military in the 1980s.</p>",
"locales": [ "locales": [
"ru_RU" "ru_RU"
], ],
"aircrafts": [ "aircrafts": [
"IL-76MD",
"Mi-24V Hind-E", "Mi-24V Hind-E",
"Mi-24P Hind-F", "Mi-24P Hind-F",
"Mi-8MTV2 Hip", "Mi-8MTV2 Hip",
"MiG-21bis Fishbed-N", "MiG-21bis Fishbed-N",
"MiG-23MLD Flogger-K", "MiG-23MLD Flogger-K",
"MiG-25PD Foxbat-E", "MiG-25PD Foxbat-E",
"MiG-27K Flogger-J2",
"MiG-29A Fulcrum-A", "MiG-29A Fulcrum-A",
"MiG-31 Foxhound",
"Su-17M4 Fitter-K", "Su-17M4 Fitter-K",
"Su-24M Fencer-D", "Su-24M Fencer-D",
"Su-25 Frogfoot", "Su-25 Frogfoot",
"Su-27 Flanker-B",
"Tu-142 Bear-F", "Tu-142 Bear-F",
"Tu-22M3 Backfire-C", "Tu-22M3 Backfire-C",
"Tu-95MS Bear-H" "Tu-95MS Bear-H"
], ],
"awacs": [ "awacs": [
@ -60,7 +64,9 @@
"KS-19/SON-9" "KS-19/SON-9"
], ],
"naval_units": [ "naval_units": [
"Corvette 1241.1 Molniya" "Corvette 1241.1 Molniya",
"Corvette 1124.4 Grish",
"SSK 877V Kilo"
], ],
"air_defense_units": [ "air_defense_units": [
"SAM P19 \"Flat Face\" SR (SA-2/3)", "SAM P19 \"Flat Face\" SR (SA-2/3)",
@ -81,4 +87,4 @@
"carrier_names": [], "carrier_names": [],
"has_jtac": false, "has_jtac": false,
"doctrine": "coldwar" "doctrine": "coldwar"
} }

View File

@ -3,7 +3,7 @@
"defaultValue": true, "defaultValue": true,
"specificOptions": [ "specificOptions": [
{ {
"nameInUI": "Tailor CTLD for the Liberation specific missions", "nameInUI": "Tailor CTLD for the Retribution specific missions",
"mnemonic": "tailorctld", "mnemonic": "tailorctld",
"defaultValue": true "defaultValue": true
}, },

View File

@ -17,7 +17,7 @@ climate:
day_night_temperature_difference: 11.0 day_night_temperature_difference: 11.0
seasons: seasons:
# "winter" and "summer" are actually interpreted as northern hemisphere # "winter" and "summer" are actually interpreted as northern hemisphere
# seasons in liberation, so these seasons are all inverted. # seasons in Retribution, so these seasons are all inverted.
winter: winter:
average_pressure: 29.63 average_pressure: 29.63
average_temperature: 21.0 average_temperature: 21.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB