Modded Aircraft Support - dcs-liberation/dcs_liberation 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 Liberation. We prefer using the free time we can allocate to Liberation to develop features that will benefit the whole community of Liberation users.

I'm willing to support the mod in liberation myself!

Here is how to do it:

Pre-requisites:

  • A development environment for DCS Liberation, 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 aircraft is much more complicated than adding its name in a faction file.

In order for a modded aircraft to work with Liberation, 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/pydcs/dcs/blob/master/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 liberation, we then have to manually extract the new aircraft from the generated modded pydcs version, and create an extension (which is added to liberation code)

Aircraft data will be found in the file aircraft.py generated by pydcs. Search your aircraft 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-liberation/dcs_liberation/blob/develop/pydcs_extensions/a4ec/a4ec.py

As you can see, extensions for mods are stored in this folder : https://github.com/dcs-liberation/dcs_liberation/blob/develop/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 Liberation. 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):
    ...

Make sure your mod is imported in pydcs_extensions/__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 and QNewGameWizard.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"),
       modSettingsGroup = QtWidgets.QGroupBox("Mod Settings")
        a4_skyhawk = QtWidgets.QCheckBox()
        self.registerField("a4_skyhawk", a4_skyhawk)
        hercules = QtWidgets.QCheckBox()
        self.registerField("hercules", hercules)
        f22_raptor = QtWidgets.QCheckBox()
        self.registerField("f22_raptor", f22_raptor)
        jas39_gripen = QtWidgets.QCheckBox()
        self.registerField("jas39_gripen", jas39_gripen)
        su57_felon = QtWidgets.QCheckBox()
        self.registerField("su57_felon", su57_felon)
        modLayout = QtWidgets.QGridLayout()
        modLayout.addWidget(QtWidgets.QLabel("A-4E Skyhawk"), 1, 0)
        modLayout.addWidget(a4_skyhawk, 1, 1)
        modLayout.addWidget(QtWidgets.QLabel("F-22A Raptor"), 2, 0)
        modLayout.addWidget(f22_raptor, 2, 1)
        modLayout.addWidget(QtWidgets.QLabel("C-130J-30 Super Hercules"), 3, 0)
        modLayout.addWidget(hercules, 3, 1)
        modLayout.addWidget(QtWidgets.QLabel("JAS 39 Gripen"), 4, 0)
        modLayout.addWidget(jas39_gripen, 4, 1)
        modLayout.addWidget(QtWidgets.QLabel("Su-57 Felon"), 5, 0)
        modLayout.addWidget(su57_felon, 5, 1)
        modLayout.addWidget(QtWidgets.QLabel("Frenchpack"), 6, 0)
        modLayout.addWidget(frenchpack, 6, 1)

Step 3 : Liberation flight planner database setup:

DCS Liberation 7

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. Liberation 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 Liberation. 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 Liberation hints about which aircraft are better at each task.

For an overview of all tasks and weights in Liberation, run dcs_liberation.exe dump-task-priorities (from the command line). That will dump Liberation/Debug/priorities.yaml to your DCS Saved Games directory.

DCS Liberation 6

Open ai_flight_planner_db.py

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.

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.

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; Liberation will filter out mods that the player doesn't use.

Step 6: Resource files for aircraft

Add new yaml files for your aircraft in resources/units/aircraft/

See A-4E-C.yaml for reference.

Step 7: Add icons for the UI (Optional)

Add icons for the new plane there: https://github.com/dcs-liberation/dcs_liberation/tree/develop/resources/ui/units/aircrafts/icons

And a banner, there: https://github.com/dcs-liberation/dcs_liberation/tree/develop/resources/ui/units/aircrafts/banners

Step 8: Playtest

Play a few missions with the plane, test as much cases as you can.

Step 9: Release

Step 10: 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.