Modded Unit Support - dcs-retribution/dcs-retribution GitHub Wiki
Hey, can you add support for ?
Well, we could, but...
It takes a lot of time to add support for a mod in Retribution. We prefer using the free time we can allocate to Retribution to develop features that will benefit the whole community of Retribution users.
I'm willing to support the mod in Retribution myself!
Here is how to do it:
Pre-requisites:
- A development environment for DCS Retribution, see Developer's Guide
- Basic Python programming knowledge
- Basic Lua programming knowledge
- A DCS World open beta installation
Step 1: Pydcs extensions injection:
Adding support for a modded unit is much more complicated than adding its name in a faction file.
In order for a modded units to work with Retribution, we need to generate a data export for it to work with pydcs
Pydcs is the library we use to generate the .miz files, it is awesome, but it is not magical and can't support modded content natively if we don't tell it how do to do it. Its database also need to be updated every time DCS is updated.
Updating pydcs database is done by adding a script to DCS World to be executed on the game startup to export some aircraft data.
See the script here : https://github.com/dcs-retribution/pydcs/blob/retribution/tools/pydcs_export.lua;
Copy this script on your computer and do what is explained in the comments :
-- execute(dofile) this script at the end of
-- of 'DCS World\MissionEditor\modules\me_mission.lua'
-- base.dofile("C:\\Users\\peint\\Documents\\dcs\\tools\\pydcs_export.lua")
Modify the first line "export_path" so it match an existing folder on your computer :
local export_path = "D:\\Work\\DCS\\dcs\\dcs\\"
Running this script generate most of pydcs data in the target folder when launching DCS.
If DCS stops loading at 10%, it's normal. If it doesn't start at all after 5 minutes and stay blocked at 10%, there might be an error in the script, so check <DCS World Save directory>/dcs.log
for clues.
If you run it with mods installed, it generates a version of pydcs with support for the currently installed mods.
As pydcs does not have the ambition of supporting every existing mods, we do not push modded content to the official pydcs version, which only supports vanilla DCS.
So to add support for modded aircrafts in Retribution, we then have to manually extract the new aircraft from the generated modded pydcs version, and create an extension (which is added to Retribution code)
Aircraft data will be found in the file aircraft.py, vehicles/infantry in vehicles.py, ships in ships.py, etc. generated by pydcs. Search your unit class in this file, and add it to a custom file. Your mod might have added new weapons, they'll be found in weapons.py, and you have to fetch them as well.
Example of final file for the popular A-4E-C mod : https://github.com/dcs-retribution/dcs-retribution/blob/dev/pydcs_extensions/a4ec/a4ec.py Example of final file for the CurrentHill USA Military assets pack: https://github.com/dcs-retribution/dcs-retribution/blob/dev/pydcs_extensions/usamilitaryassetspack/usamilitaryassetspack.py
As you can see, extensions for mods are stored in this folder : https://github.com/dcs-retribution/dcs-retribution/blob/dev/pydcs_extensions
These file contains a lot of metadata we need to be able to generate missions, such as possible liveries, possible payloads for each pylons, specific weapons ids ... and so on.
Step 2: Pydcs extensions injection:
Once you've created your extension, you need to inject it's content into the pydcs version run by Retribution. In the Python file you created for the mod, decorate each unit type with either @planemod
, @vehiclemod
, or @helicoptermod
. For example:
@planemod
class A_4E_C(PlaneType):
...
Any custom weapons with the mod should be included in the same file as the python class for the vehicle itself. After the weapons are defined, they must be injected into the pydcs
weapons table. You do this by including the following line at the top of the file:
from pydcs_extensions.weapon_injector import inject_weapons
and the following line after the weapons definition class:
inject_weapons(CustomWeaponsClass)
where CustomWeaponsClass
is the name of the weapons class you created. For the A4EC listed above, that name is WeaponsA4EC
.
See A-4E-C.yaml for reference.
Make sure your mod is imported in pydcs_extensions/__init__.py
and in pydcs_extensions/<your mod extension>/__init__.py
Step 2 : Campaign start setup
For campaign start setup and mod settings support, add your plane to the files start_generator.py, faction.py, QNewGameWizard.py, and QGeneratorSettings.py
a4_skyhawk: bool = False
f22_raptor: bool = False
hercules: bool = False
jas39_gripen: bool = False
su57_felon: bool = False
frenchpack: bool = False
# aircraft
if not mod_settings.a4_skyhawk:
self.remove_aircraft("A-4E-C")
if not mod_settings.hercules:
self.remove_aircraft("Hercules")
if not mod_settings.f22_raptor:
self.remove_aircraft("F-22A")
if not mod_settings.jas39_gripen:
self.remove_aircraft("JAS39Gripen")
self.remove_aircraft("JAS39Gripen_AG")
if not mod_settings.su57_felon:
self.remove_aircraft("Su-57")
mod_settings = ModSettings(
a4_skyhawk=self.field("a4_skyhawk"),
f22_raptor=self.field("f22_raptor"),
f104_starfighter=self.field("f104_starfighter"),
hercules=self.field("hercules"),
jas39_gripen=self.field("jas39_gripen"),
su57_felon=self.field("su57_felon"),
frenchpack=self.field("frenchpack"),
QGeneratorSettings.py snippet:
self.a4_skyhawk = QtWidgets.QCheckBox()
self.registerField("a4_skyhawk", self.a4_skyhawk)
self.a6a_intruder = QtWidgets.QCheckBox()
self.registerField("a6a_intruder", self.a6a_intruder)
self.a7e_corsair2 = QtWidgets.QCheckBox()
self.registerField("a7e_corsair2", self.a7e_corsair2)
self.ea6b_prowler = QtWidgets.QCheckBox()
self.registerField("ea6b_prowler", self.ea6b_prowler)
QGeneratorSettings.py snippet:
("A-4E Skyhawk (v2.2.0)", self.a4_skyhawk),
("A-6A Intruder (v2.7.5.01)", self.a6a_intruder),
("A-7E Corsair II", self.a7e_corsair2),
("C-130J-30 Super Hercules (v6.8.2)", self.hercules),
("Cold War Assets mod (v1.0)", self.coldwarassets),
Step 3 : Retribution unit file setup:
DCS Retribution
The aircraft preferences per task are kept in each aircraft's yaml file in resources/units/aircraft/*.yaml
. Each task is assigned a weight describing the aircraft's relative strength at the given task. Aircraft with a higher weight for a given task will be preferred over those with a lower weight. If a task is omitted from the yaml file, the aircraft will not be capable of performing that mission type. For example:
# From FA-18C_hornet.yaml
tasks:
Anti-ship: 150
BAI: 740
BARCAP: 450
CAS: 740
DEAD: 440
Escort: 450
Fighter sweep: 450
Intercept: 450
OCA/Aircraft: 740
OCA/Runway: 600
SEAD: 160
SEAD Escort: 160
Strike: 600
TARCAP: 450
# From F-16C_50.yaml
tasks:
BAI: 750
BARCAP: 460
CAS: 750
DEAD: 450
Escort: 460
Fighter sweep: 460
Intercept: 460
OCA/Aircraft: 750
OCA/Runway: 610
SEAD: 170
SEAD Escort: 170
Strike: 610
TARCAP: 460
The hornet has a BAI weight of 740 while the viper has a BAI weight of 750. Retribution will prefer choosing vipers to hornets when deciding which aircraft is better suited to BAI.
Aircraft can have identical weights for a task. When multiple aircraft have the same weight for a task, they are treated as equal by Retribution. Selection criteria vary by many factors; one may be chosen randomly from the set of equal aircraft, one may be chosen arbitrarily, or a different but similar aircraft may be chosen. These weights are only guidelines. Use them to give Retribution hints about which aircraft are better at each task.
For an overview of all tasks and weights in Retribution, run dcs-retribution.exe dump-task-priorities
(from the command line). That will dump Retribution/Debug/priorities.yaml
to your DCS Saved Games directory.
See A-4E-C.yaml for reference.
Similarly for ground units, each unit has a yaml file in resources/units/ground_units/*.yaml
. This file determines what type of unit it is, the price, and the name of available variants. It is important to note that the ID of the vehicle from the pydcs export must match the name of the unit yaml file. Example:
# From CH_KrAZ6322.yaml
class: Logistics
description: "The KrAZ-6322 is a Ukrainian off-road six-wheel drive truck intended for extreme
conditions. It has been produced since 1994 and is manufactured at the KrAZ factory in Kremenchuk,
Ukraine. It was first presented at the 1994 defence industry trade show in Kyiv."
introduced: 1994
manufacturer: KrAZ
origin: Ukraine
price: 3
role: Tactical Transport Vehicle
variants:
"[CH] KrAZ-6322 Truck": {}
DCS Liberation 6 (info retained for archival purposes only)
Please note, that this is no longer required in DCS Retribution, as the capability list has been replaced by the task weights, detailed above. These instructions are only retained for DCS Liberation version 6 reference purposes.
Add your plane to the lists it needs to be in, so DCS Liberation is aware of its capabilities. These lists are in priority order:
Example:
CAP_CAPABLE = [
# ....
Su_57,
F_22A,
# ....
]
Step 4: Create default payload and inject custom weapons
See Custom Loadouts Create default loadouts for the new plane.
Step 5: Factions
See Custom Factions and add the mods to the appropriate factions. If there are no appropriate factions, create a new one, but you don't need to worry about breaking existing factions by "requiring" the mod; Retribution will filter out mods that the player doesn't use.
Step 6: Layouts and groups
If you're implementing a mod pack with SAM or AntiShip site units, you may want to create a new group so they can be used for LORAD/MERAD/SHORAD. Example from MIM-104 Patriot:
name: MIM-104 Patriot (Mobile)
tasks:
- LORAD
units:
- "[CH] MIM-104 AN/MPQ-65 STR (HEMTT)"
- "[CH] MIM-104 AN/MPQ-65A STR (HEMTT)"
- "[CH] MIM-104 LTAMDS STR (HEMTT)"
- "[CH] MIM-104 ECS (HEMTT)"
- "[CH] MIM-104 EPP (HEMTT)"
- "[CH] MIM-104 M903 PAC-2 GEM/T LN (HEMTT)"
- "[CH] MIM-104 M903 PAC-3 MSE LN (HEMTT)"
- "[CH] Oshkosh HEMTT M977"
layouts:
- MIM-104 Patriot Battery
As you can see, each group has a layout. If possible, you should attempt to reuse existing layouts like 6 Launcher Circle
. Sometimes these sites do require their own layout like the MIM-104. In the layout file you can specify the unit class or unit type you want to use if you need to be more specific. Example:
name: MIM-104 Patriot Battery
tasks:
- LORAD
groups:
- Patriot:
- name: Patriot Battery 0
unit_count:
- 2
unit_classes:
- SearchTrackRadar
- name: Patriot Battery 1
unit_count:
- 1
unit_classes:
- Logistics
- name: Patriot Battery 2
unit_count:
- 1
unit_types:
- MIM104_ECS
- name: Patriot Battery 3
unit_count:
- 1
unit_classes:
- Logistics
- name: Patriot Battery 4
unit_count:
- 1
unit_types:
- MIM104_EPP
- name: Patriot Battery 5
unit_count:
- 8
unit_classes:
- Launcher
- PD:
- name: Patriot Battery 7
optional: true
sub_task: PointDefense
unit_count:
- 1
- 2
unit_classes:
- SHORAD
- name: Patriot Battery 6
sub_task: AAA
optional: true
unit_count:
- 1
- 2
unit_classes:
- AAA
layout_file: resources/layouts/anti_air/Patriot_Battery.miz
This layout file points to the Patriot_Battery.miz file which the normal patriot site is using. Since the patriot site layout was very similar but a little too specific, the contributor chose to create a new layout file instead.
Note: In the groups file you use the variant name of the unit while in the layout file you use the ID of the unit.
Step 7: Update radar db:
Like before, if you implemented a SAM site or a ship that has a radar, you want to include it in the radar db. Example:
from pydcs_extensions import usamilitaryassetspack as usamap
TELARS/Track Radars/Launcher Tracker Pairs/Units with Radar:
usamap.MIM104_ANMPQ65,
usamap.MIM104_ANMPQ65A,
usamap.MIM104_ANMPQ65_HEMTT,
usamap.MIM104_ANMPQ65A_HEMTT,
usamap.MIM104_LTAMDS,
usamap.MIM104_LTAMDS_HEMTT,
usamap.CH_THAAD_ANTPY2,
Step 8: Add icons for the UI (Optional)
Add icons for the new plane there: https://github.com/dcs-retribution/dcs-retribution/tree/dev/resources/ui/units/aircrafts/icons
And a banner, there: https://github.com/dcs-retribution/dcs-retribution/tree/dev/resources/ui/units/aircrafts/banners
Icons should be 91x24 and banners are 720x360 pixels both in jpeg format.
Step 9: Playtest
Play a few missions with the plane, test as much cases as you can.
Step 10: Release
Step 11: Maintenance
Redo the data export thing (Step 1), every time said mod is updated, if needed create new loadouts and account for new capabilities in db.