From 62df9fb131d2c3e4d29cf1c15f31ec3a1b04b354 Mon Sep 17 00:00:00 2001 From: zhexu14 <64713351+zhexu14@users.noreply.github.com> Date: Mon, 29 Jun 2026 12:45:02 +1000 Subject: [PATCH] Load weapon settings from payload lua files and save weapon settings to pylon data in miz file --- dcs/flyingunit.py | 5 ++++- dcs/unittype.py | 14 ++++++++++++-- tests/test_mission.py | 31 +++++++++++++++++++++++++++++- tests/test_unittype.py | 43 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/dcs/flyingunit.py b/dcs/flyingunit.py index 5cc2e652..54402b93 100644 --- a/dcs/flyingunit.py +++ b/dcs/flyingunit.py @@ -92,7 +92,10 @@ def load_pylon(self, weapon, pylon=None): raise RuntimeError("Plane {pn} has no pylon {p}.".format(pn=self.unit_type.id, p=pylon)) if weapon is None: return self.pylons.pop(pylon, None) - self.pylons[pylon] = {"CLSID": weapon[1]["clsid"]} + pylon_data = {"CLSID": weapon[1]["clsid"]} + if "settings" in weapon[1]: + pylon_data["settings"] = weapon[1]["settings"] + self.pylons[pylon] = pylon_data return True def store_loadout(self, filename): diff --git a/dcs/unittype.py b/dcs/unittype.py index 3e55d833..62803f32 100644 --- a/dcs/unittype.py +++ b/dcs/unittype.py @@ -162,7 +162,12 @@ def loadout(cls, _task): tasks = [payload["tasks"][x] for x in payload["tasks"]] if _task.id in tasks: pylons = payload["pylons"] - r = [(pylons[x]["num"], {"clsid": pylons[x]["CLSID"]}) for x in pylons] + r = [] + for pylon in pylons: + pylon_data = {"clsid": pylons[pylon]["CLSID"]} + if "settings" in pylons[pylon]: + pylon_data["settings"] = pylons[pylon]["settings"] + r.append((pylons[pylon]["num"], pylon_data)) return r return None @@ -173,7 +178,12 @@ def loadout_by_name(cls, loadout_name): if payload is None: return None pylons = payload["pylons"] - r = [(pylons[x]["num"], {"clsid": pylons[x]["CLSID"]}) for x in pylons] + r = [] + for pylon in pylons: + pylon_data = {"clsid": pylons[pylon]["CLSID"]} + if "settings" in pylons[pylon]: + pylon_data["settings"] = pylons[pylon]["settings"] + r.append((pylons[pylon]["num"], pylon_data)) return r return None diff --git a/tests/test_mission.py b/tests/test_mission.py index 591f3344..8ddff939 100644 --- a/tests/test_mission.py +++ b/tests/test_mission.py @@ -933,7 +933,7 @@ def test_smoke_required_modules(self) -> None: m.load_file(mizname) self.assertEqual(m.required_modules, {"WWII Armour and Technics": "WWII Armour and Technics"}) - saved_miz = "tests/missions/Mission_with_required_modules_saved.miz" + saved_miz = "missions/Mission_with_required_modules_saved.miz" m.save(saved_miz) m2 = dcs.mission.Mission() m2.load_file(saved_miz) @@ -1476,6 +1476,35 @@ def test_ground_control_password(self) -> None: self.assertIn(Coalition.Blue.value, m2.groundControl.dict()["passwords"][GroundControlRole.OBSERVER.value]) self.assertIn(Coalition.Red.value, m2.groundControl.dict()["passwords"][GroundControlRole.JTAC.value]) + + def test_unit_payload(self): + m = dcs.mission.Mission(terrain=dcs.terrain.Syria()) + + country_name = "USA" + group_name = "F/A-18C" + group = m.flight_group_from_airport( + m.country(country_name), + group_name, + dcs.planes.FA_18C_hornet, + group_size=1, + airport=m.terrain.airports["Damascus"] + ) + unit = group.units[0] + unit.reset_loadout() + unit.load_pylon((1, {"clsid": "test_without_settings"})) + unit.load_pylon((2, {"clsid": "test_with_settings", "settings": {"first": 1, "second": 2}})) + mission_file = Path('missions/payload.miz') + m.save(mission_file) + + m = dcs.mission.Mission() + self.assertEqual(0, len(m.load_file('missions/payload.miz'))) + group = m.country(country_name).find_group(group_name) + self.assertIsNotNone(group) + self.assertIsInstance(group, dcs.unitgroup.FlyingGroup) + self.assertEqual(1, len(group.units)) + unit = group.units[0] + self.assertIsInstance(unit, FlyingUnit) + self.assertDictEqual(unit.pylons, {1: {"CLSID": "test_without_settings"}, 2: {"CLSID": "test_with_settings", "settings": {"first": 1, "second": 2}}}) class UpdateWarehousesTest(unittest.TestCase): diff --git a/tests/test_unittype.py b/tests/test_unittype.py index 0f607a73..0a76e22b 100644 --- a/tests/test_unittype.py +++ b/tests/test_unittype.py @@ -7,6 +7,7 @@ from dcs.liveries.liveryscanner import LiveryScanner from dcs.payloads import PayloadDirectories from dcs.planes import F_16C_50 +from dcs.task import CAP from dcs.unittype import FlyingType @@ -130,3 +131,45 @@ def test_standard_payload_definition(tmp_path: Path) -> None: F_16C_50.payloads = None payloads = F_16C_50.load_payloads() assert "test_payload" in payloads + assert payloads["test_payload"] == {'displayName': 'test_payload', 'name': 'test_payload', 'pylons': {1: {'CLSID': '{C8E06185-7CD6-4C90-959F-044679E90751}', 'num': 1}}, 'tasks': {1: 11}} + assert F_16C_50.loadout_by_name("test_payload") == [(1, {'clsid': '{C8E06185-7CD6-4C90-959F-044679E90751}'})] + assert F_16C_50.loadout(CAP) == [(1, {'clsid': '{C8E06185-7CD6-4C90-959F-044679E90751}'})] + + +def test_payload_definition_with_fuze_settings(tmp_path: Path) -> None: + PayloadDirectories.set_preferred(tmp_path) + + (tmp_path / "test.lua").write_text(textwrap.dedent("""\ + local unitPayloads = { + ["name"] = "F-16C_50", + ["payloads"] = { + [1] = { + ["displayName"] = "test_payload", + ["name"] = "test_payload", + ["pylons"] = { + [1] = { + ["CLSID"] = "{C8E06185-7CD6-4C90-959F-044679E90751}", + ["num"] = 1, + ["settings"] = { + ["first"] = 1, + ["second"] = "A", + }, + }, + }, + ["tasks"] = { + [1] = 11, + }, + }, + }, + ["unitType"] = "F-16C_50", + } + return unitPayloads + """)) + # Clears cached payloads to force re-load + FlyingType._payload_cache = None + F_16C_50.payloads = None + payloads = F_16C_50.load_payloads() + assert "test_payload" in payloads + assert payloads["test_payload"] == {'displayName': 'test_payload', 'name': 'test_payload', 'pylons': {1: {'CLSID': '{C8E06185-7CD6-4C90-959F-044679E90751}', 'num': 1, 'settings': {'first': 1, 'second': 'A'}}}, 'tasks': {1: 11}} + assert F_16C_50.loadout_by_name("test_payload") == [(1, {'clsid': '{C8E06185-7CD6-4C90-959F-044679E90751}', 'settings': {'first': 1, 'second': 'A'}})] + assert F_16C_50.loadout(CAP) == [(1, {'clsid': '{C8E06185-7CD6-4C90-959F-044679E90751}', 'settings': {'first': 1, 'second': 'A'}})]