diff --git a/openage/convert/processor/conversion/de2/modpack_subprocessor.py b/openage/convert/processor/conversion/de2/modpack_subprocessor.py index 810ff96752..5af6fdf8b5 100644 --- a/openage/convert/processor/conversion/de2/modpack_subprocessor.py +++ b/openage/convert/processor/conversion/de2/modpack_subprocessor.py @@ -1,4 +1,4 @@ -# Copyright 2020-2023 the openage authors. See copying.md for legal info. +# Copyright 2020-2024 the openage authors. See copying.md for legal info. # # pylint: disable=too-few-public-methods @@ -40,7 +40,7 @@ def _get_aoe2_base(cls, full_data_set: GenieObjectContainer) -> Modpack: mod_def = modpack.get_info() - mod_def.set_info("de2_base", "0.5.1", versionstr="1.0c", repo="openage") + mod_def.set_info("de2_base", "0.6.0", versionstr="Update 118476+", repo="openage") mod_def.add_include("data/**") diff --git a/openage/convert/processor/conversion/de2/nyan_subprocessor.py b/openage/convert/processor/conversion/de2/nyan_subprocessor.py index 4474751136..b688cc3e7c 100644 --- a/openage/convert/processor/conversion/de2/nyan_subprocessor.py +++ b/openage/convert/processor/conversion/de2/nyan_subprocessor.py @@ -446,6 +446,9 @@ def building_line_to_game_entity(building_line: GenieBuildingLineGroup) -> None: abilities_set.append(AoCAbilitySubprocessor.terrain_requirement_ability(building_line)) abilities_set.append(AoCAbilitySubprocessor.visibility_ability(building_line)) + if building_line.get_head_unit()["speed"].value > 0: + abilities_set.append(AoCAbilitySubprocessor.move_ability(building_line)) + # Config abilities if building_line.is_creatable(): abilities_set.append(AoCAbilitySubprocessor.constructable_ability(building_line)) diff --git a/openage/convert/processor/conversion/de2/processor.py b/openage/convert/processor/conversion/de2/processor.py index d78fb218d9..19001b9087 100644 --- a/openage/convert/processor/conversion/de2/processor.py +++ b/openage/convert/processor/conversion/de2/processor.py @@ -312,7 +312,10 @@ def create_extra_building_lines(full_data_set: GenieObjectContainer) -> None: process. :type full_data_set: class: ...dataformat.aoc.genie_object_container.GenieObjectContainer """ - extra_units = (1734,) # Folwark + extra_units = ( + 1734, # Folwark + 1808, # Mule Cart + ) for unit_id in extra_units: building_line = GenieBuildingLineGroup(unit_id, full_data_set) diff --git a/openage/convert/processor/conversion/de2/tech_subprocessor.py b/openage/convert/processor/conversion/de2/tech_subprocessor.py index 2f2aaf9e76..c9c3a71c17 100644 --- a/openage/convert/processor/conversion/de2/tech_subprocessor.py +++ b/openage/convert/processor/conversion/de2/tech_subprocessor.py @@ -1,4 +1,4 @@ -# Copyright 2020-2023 the openage authors. See copying.md for legal info. +# Copyright 2020-2024 the openage authors. See copying.md for legal info. # # pylint: disable=too-many-locals,too-many-branches @@ -155,7 +155,11 @@ class DE2TechSubprocessor: 267: DE2UpgradeResourceSubprocessor.forager_wood_gather_upgrade, 268: DE2UpgradeResourceSubprocessor.resource_decay_upgrade, 269: DE2UpgradeResourceSubprocessor.tech_reward_upgrade, + 272: DE2UpgradeResourceSubprocessor.cliff_defense_upgrade, + 273: DE2UpgradeResourceSubprocessor.elevation_defense_upgrade, 274: DE2UpgradeResourceSubprocessor.chieftains_upgrade, + 280: DE2UpgradeResourceSubprocessor.conversion_range_upgrade, + 282: DE2UpgradeResourceSubprocessor.unknown_recharge_rate_upgrade, } @classmethod diff --git a/openage/convert/processor/conversion/de2/upgrade_resource_subprocessor.py b/openage/convert/processor/conversion/de2/upgrade_resource_subprocessor.py index a394061fa1..9abf477831 100644 --- a/openage/convert/processor/conversion/de2/upgrade_resource_subprocessor.py +++ b/openage/convert/processor/conversion/de2/upgrade_resource_subprocessor.py @@ -1,4 +1,4 @@ -# Copyright 2020-2023 the openage authors. See copying.md for legal info. +# Copyright 2020-2024 the openage authors. See copying.md for legal info. # # pylint: disable=too-many-locals,too-many-lines,too-many-statements,too-many-public-methods,invalid-name # @@ -123,6 +123,31 @@ def cliff_attack_upgrade( return patches + @staticmethod + def cliff_defense_upgrade( + converter_group: ConverterObjectGroup, + value: typing.Union[int, float], + operator: MemberOperator, + team: bool = False + ) -> list[ForwardRef]: + """ + Creates a patch for the cliff defense multiplier effect (ID: 272). + + :param converter_group: Tech/Civ that gets the patch. + :type converter_group: ...dataformat.converter_object.ConverterObjectGroup + :param value: Value used for patching the member. + :type value: MemberOperator + :param operator: Operator used for patching the member. + :type operator: MemberOperator + :returns: The forward references for the generated patches. + :rtype: list + """ + patches = [] + + # TODO: Implement + + return patches + @staticmethod def conversion_min_adjustment_upgrade( converter_group: ConverterObjectGroup, @@ -258,6 +283,31 @@ def conversion_building_chance_upgrade( return patches + @staticmethod + def conversion_range_upgrade( + converter_group: ConverterObjectGroup, + value: typing.Union[int, float], + operator: MemberOperator, + team: bool = False + ) -> list[ForwardRef]: + """ + Creates a patch for the conversion range modifer (ID: 280). + + :param converter_group: Tech/Civ that gets the patch. + :type converter_group: ...dataformat.converter_object.ConverterObjectGroup + :param value: Value used for patching the member. + :type value: MemberOperator + :param operator: Operator used for patching the member. + :type operator: MemberOperator + :returns: The forward references for the generated patches. + :rtype: list + """ + patches = [] + + # TODO: Implement + + return patches + @staticmethod def cuman_tc_upgrade( converter_group: ConverterObjectGroup, @@ -441,6 +491,31 @@ def elevation_attack_upgrade( return patches + @staticmethod + def elevation_defense_upgrade( + converter_group: ConverterObjectGroup, + value: typing.Union[int, float], + operator: MemberOperator, + team: bool = False + ) -> list[ForwardRef]: + """ + Creates a patch for the elevation defense multiplier effect (ID: 273). + + :param converter_group: Tech/Civ that gets the patch. + :type converter_group: ...dataformat.converter_object.ConverterObjectGroup + :param value: Value used for patching the member. + :type value: MemberOperator + :param operator: Operator used for patching the member. + :type operator: MemberOperator + :returns: The forward references for the generated patches. + :rtype: list + """ + patches = [] + + # TODO: Implement + + return patches + @staticmethod def feitoria_gold_upgrade( converter_group: ConverterObjectGroup, @@ -851,6 +926,31 @@ def trade_food_bonus_upgrade( return patches + @staticmethod + def unknown_recharge_rate_upgrade( + converter_group: ConverterObjectGroup, + value: typing.Union[int, float], + operator: MemberOperator, + team: bool = False + ) -> list[ForwardRef]: + """ + Creates a patch for the unknown recharge rate bonus effect (ID: 282). + + :param converter_group: Tech/Civ that gets the patch. + :type converter_group: ...dataformat.converter_object.ConverterObjectGroup + :param value: Value used for patching the member. + :type value: MemberOperator + :param operator: Operator used for patching the member. + :type operator: MemberOperator + :returns: The forward references for the generated patches. + :rtype: list + """ + patches = [] + + # TODO: Implement + + return patches + @staticmethod def workshop_food_gen_upgrade( converter_group: ConverterObjectGroup, diff --git a/openage/convert/service/init/CMakeLists.txt b/openage/convert/service/init/CMakeLists.txt index 3c7e404c69..aa588dcb29 100644 --- a/openage/convert/service/init/CMakeLists.txt +++ b/openage/convert/service/init/CMakeLists.txt @@ -1,7 +1,6 @@ add_py_modules( __init__.py api_export_required.py - changelog.py conversion_required.py modpack_search.py mount_asset_dirs.py diff --git a/openage/convert/service/init/api_export_required.py b/openage/convert/service/init/api_export_required.py index 90b78309d7..8bb3a51850 100644 --- a/openage/convert/service/init/api_export_required.py +++ b/openage/convert/service/init/api_export_required.py @@ -21,7 +21,7 @@ def api_export_required(asset_dir: UnionPath) -> bool: """ - Returns true if the openage nyan API modpack cannot be found. + Returns true if the openage nyan API modpack cannot be found or is outdated. TODO: Remove once the API modpack is generated by default. diff --git a/openage/convert/service/init/changelog.py b/openage/convert/service/init/changelog.py deleted file mode 100644 index 0c63aac864..0000000000 --- a/openage/convert/service/init/changelog.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright 2015-2022 the openage authors. See copying.md for legal info. - -""" -Asset version change log - -used to determine whether assets that were converted by an earlier version of -openage are still up to date. -""" -from __future__ import annotations -import typing -from ....log import warn -from ....testing.testing import TestError - -# filename where to store the versioning information -ASSET_VERSION_FILENAME = "asset_version" - -# filename where to store the gamespec version hash -GAMESPEC_VERSION_FILENAME = "gamespec_version" - -# available components for reconversion -COMPONENTS = { - "graphics", - "sounds", - "metadata", - "interface", -} - -# each line represents changes to the assets. -# the last line is the most recent change. -CHANGES = ( - {"graphics", "sounds"}, - {"sounds"}, - {"graphics"}, - {"interface"}, - {"interface"}, - {"metadata"}, - {"metadata"}, - {"graphics"}, -) - -# the current version number equals the number of changes -ASSET_VERSION = len(CHANGES) - 1 - - -def changes(asset_version: int) -> set: - """ - return all changed components since the passed version number. - """ - if asset_version >= len(CHANGES): - warn("asset version from the future: %d", asset_version) - warn("current version is: %d", ASSET_VERSION) - warn("leaving assets as they are.") - return set() - - changed_components = set() - - # TODO: Reimplement with proper detection based on file hashing - - return changed_components - - -def test() -> typing.NoReturn: - """ - verify only allowed versions are stored in the changes - """ - for entry in CHANGES: - if entry > COMPONENTS: - invalid = entry - COMPONENTS - raise TestError(f"'{invalid}': invalid changelog entry") diff --git a/openage/convert/service/init/modpack_search.py b/openage/convert/service/init/modpack_search.py index ea8bf87c24..8d89b73da1 100644 --- a/openage/convert/service/init/modpack_search.py +++ b/openage/convert/service/init/modpack_search.py @@ -1,4 +1,4 @@ -# Copyright 2023-2023 the openage authors. See copying.md for legal info. +# Copyright 2023-2024 the openage authors. See copying.md for legal info. """ Search for and enumerate openage modpacks. @@ -86,17 +86,21 @@ def query_modpack(proposals: set[str]) -> str: Query interactively for a modpack from a selection of proposals. """ print("\nPlease select a modpack before starting.") - print("Insert the index of one of the proposals (Default = 0):") + print("Enter the index of one of the proposals (Default = 0):") proposals = sorted(proposals) for index, proposal in enumerate(proposals): print(f"({index}) {proposal}") user_selection = input("> ") - if user_selection.isdecimal() and int(user_selection) < len(proposals): - selection = proposals[int(user_selection)] + if user_selection == "": + selection = proposals[0] else: - selection = proposals[0] + while not (user_selection.isdecimal() and int(user_selection) < len(proposals)): + print(f"'{user_selection}' is not a valid index. Please try again.") + user_selection = input("> ") + + selection = proposals[int(user_selection)] return selection diff --git a/openage/convert/tool/driver.py b/openage/convert/tool/driver.py index ba974f42e8..cdd1ed04a3 100644 --- a/openage/convert/tool/driver.py +++ b/openage/convert/tool/driver.py @@ -16,7 +16,6 @@ from ..service.debug_info import debug_gamedata_format from ..service.debug_info import debug_string_resources, \ debug_registered_graphics, debug_modpack, debug_execution_time -from ..service.init.changelog import (ASSET_VERSION) from ..service.read.gamedata import get_gamespec from ..service.read.palette import get_palettes from ..service.read.register_media import get_existing_graphics @@ -40,8 +39,6 @@ def convert(args: Namespace) -> None: # clean args (set by convert_metadata for convert_media) del args.palettes - info(f"asset conversion complete; asset version: {ASSET_VERSION}", ) - def convert_metadata(args: Namespace) -> None: """ @@ -105,8 +102,11 @@ def convert_metadata(args: Namespace) -> None: ModpackExporter.export(modpack, args) debug_modpack(args.debugdir, args.debug_info, modpack) - export_end = timeit.default_timer() - info("Finished modpack export (%.2f seconds)", export_end - export_start) + export_end = timeit.default_timer() + info("Finished export of modpack '%s' v%s (%.2f seconds)", + modpack.info.packagename, + modpack.info.version, + export_end - export_start) stages_time = { "read": read_end - read_start, diff --git a/openage/convert/value_object/conversion/de2/internal_nyan_names.py b/openage/convert/value_object/conversion/de2/internal_nyan_names.py index 6d1fe7f380..30f9826ba3 100644 --- a/openage/convert/value_object/conversion/de2/internal_nyan_names.py +++ b/openage/convert/value_object/conversion/de2/internal_nyan_names.py @@ -1,4 +1,4 @@ -# Copyright 2020-2023 the openage authors. See copying.md for legal info. +# Copyright 2020-2024 the openage authors. See copying.md for legal info. # # pylint: disable=line-too-long @@ -51,6 +51,13 @@ 1790: ("Centurion", "centurion"), 1795: ("Dromon", "dromon"), + # TMR + 1800: ("CompositeBowman", "composite_bowman"), + 1803: ("Monaspa", "monaspa"), + 1811: ("WarriorPriest", "warrior_priest"), + 1813: ("Savar", "savar"), + 1817: ("QizilbashWarrior", "qizilbash_warrior"), + # TODO: These are upgrades 1737: ("EliteUrumiSwordsman", "elite_urumi_swordsman"), 1743: ("EliteChakramThrower", "elite_chakram_thrower"), @@ -60,6 +67,9 @@ 1761: ("EliteRRatha", "elite_rratha"), 1792: ("EliteCenturion", "elite_centurion"), 1793: ("Legionary", "legionary"), + + 1802: ("EliteCompositeBowman", "elite_composite_bowman"), + 1805: ("EliteMonaspa", "elite_monaspa"), } # key: head unit id; value: (nyan object name, filename prefix) @@ -75,6 +85,9 @@ # DOI 1754: ("Caravanserai", "caravanserai"), + + # TMR + 1808: ("MuleCart", "mule_cart"), } # key: (head) unit id; value: (nyan object name, filename prefix) @@ -91,6 +104,8 @@ # key: head unit id; value: (nyan object name, filename prefix) # contains only new techs of DE2 TECH_GROUP_LOOKUPS = { + 46: ("Devotion", "devotion"), + 488: ("Kamandaran", "kamandaran"), 678: ("EliteKonnik", "elite_konnik"), 680: ("EliteKeshik", "elite_keshik"), @@ -139,11 +154,23 @@ 840: ("EliteGhulam", "elite_ghulam"), 843: ("EliteSHrivamshaRider", "elite_shrivamsha_rider"), + 875: ("Gambesons", "gambesons"), + # ROR 882: ("EliteCenturion", "elite_centurion"), 883: ("Ballistas", "ballistas"), 884: ("Comitatensis", "comitatensis"), 885: ("Legionary", "legionary"), + + # TMR + 918: ("EliteCompositeBowman", "elite_composite_bowman"), + 920: ("EliteMonaspa", "elite_monaspa"), + 921: ("Fereters", "fereters"), + 922: ("CilicianFleet", "cilician_fleet"), + 923: ("SvanTowers", "svan_towers"), + 924: ("AsnuariCavalry", "asnuari_cavalry"), + 929: ("FortifiedChurch", "fortified_church"), + 967: ("EliteQizilbashWarrior", "elite_qizilbash_warrior"), } # key: civ index; value: (nyan object name, filename prefix) @@ -170,6 +197,10 @@ # ROR 43: ("Romans", "romans"), + + # TMR + 44: ("Armenians", "armenians"), + 45: ("Georgians", "georgians"), } # key: civ index; value: (civ ids, nyan object name, filename prefix) @@ -177,7 +208,7 @@ GRAPHICS_SET_LOOKUPS = { 0: ((0, 1, 2, 13, 14, 36), "WesternEuropean", "western_european"), 4: ((7, 37), "Byzantine", "byzantine"), - 6: ((19, 24, 43), "Mediterranean", "mediterranean"), + 6: ((19, 24, 43, 44, 45), "Mediterranean", "mediterranean"), 7: ((20, 40, 41, 42), "Indian", "indian"), 8: ((22, 23, 32, 35, 38, 39), "EasternEuropean", "eastern_european"), 11: ((33, 34), "CentralAsian", "central_asian"), diff --git a/openage/convert/value_object/read/media/datfile/lookup_dicts.py b/openage/convert/value_object/read/media/datfile/lookup_dicts.py index 80b0dd5955..7f52816dff 100644 --- a/openage/convert/value_object/read/media/datfile/lookup_dicts.py +++ b/openage/convert/value_object/read/media/datfile/lookup_dicts.py @@ -431,6 +431,7 @@ 149: "SHEAR", 150: "REGENERATION", 151: "FEITORIA", + 153: "RESOURCE_FOLLOW", 154: "LOOT", # Chieftains tech; looting on killing villagers, monks, trade carts 155: "BOOST_MOVE_AND_ATTACK", 768: "UNKNOWN_768", @@ -752,6 +753,7 @@ 0x04: "CAVALRY", 0x07: "SWGB_NO_JEDI", 0x08: "MONK", + 0x09: "DE2_FORTIFIED_CHURCH", 0x0b: "NOCAVALRY", 0x0f: "ALL", 0x10: "SWGB_LIVESTOCK", diff --git a/openage/convert/value_object/read/media/datfile/unit.py b/openage/convert/value_object/read/media/datfile/unit.py index c0cdc29172..ae0e7c5f99 100644 --- a/openage/convert/value_object/read/media/datfile/unit.py +++ b/openage/convert/value_object/read/media/datfile/unit.py @@ -1,4 +1,4 @@ -# Copyright 2013-2023 the openage authors. See copying.md for legal info. +# Copyright 2013-2024 the openage authors. See copying.md for legal info. # TODO pylint: disable=C,R,too-many-lines from __future__ import annotations @@ -695,7 +695,8 @@ def get_data_format_members( if game_version.edition.game_id == "AOE2DE": data_format.extend([ - (READ_GEN, "drop_sites", StorageType.ARRAY_ID, "int16_t[3]"), + (READ, "drop_sites_count", StorageType.INT_MEMBER, "int16_t"), + (READ_GEN, "drop_sites", StorageType.ARRAY_ID, "int16_t[drop_sites_count]"), ]) else: data_format.extend([ diff --git a/openage/testing/testlist.py b/openage/testing/testlist.py index 37f323e8a8..8227537697 100644 --- a/openage/testing/testlist.py +++ b/openage/testing/testlist.py @@ -26,7 +26,6 @@ def tests_py(): yield "openage.assets.test" yield ("openage.cabextract.test.test", "test CAB archive extraction", lambda env: env["has_assets"]) - yield "openage.convert.service.init.changelog.test" yield "openage.cppinterface.exctranslate_tests.cpp_to_py" yield ("openage.cppinterface.exctranslate_tests.cpp_to_py_bounce", "translates the exception back and forth a few times")