From b9aa2228bd3e833dc24d09c73ce81402acb2fd59 Mon Sep 17 00:00:00 2001 From: Thanatos <117127188+ThanatosGit@users.noreply.github.com> Date: Wed, 8 May 2024 03:40:59 +0200 Subject: [PATCH] mypy (#334) --- .github/workflows/python.yml | 40 +++++++++++++++ pyproject.toml | 16 ++++++ src/open_samus_returns_rando/__init__.py | 2 +- .../__pyinstaller/__init__.py | 2 +- src/open_samus_returns_rando/cli.py | 6 +-- src/open_samus_returns_rando/constants.py | 4 +- src/open_samus_returns_rando/debug.py | 8 +-- src/open_samus_returns_rando/lua_editor.py | 23 +++++---- .../misc_patches/collision_camera_table.py | 2 +- .../misc_patches/credits.py | 6 +-- .../misc_patches/elevators.py | 6 +-- .../misc_patches/exefs.py | 9 ---- .../misc_patches/lua_util.py | 11 ++-- .../misc_patches/spawn_points.py | 4 +- .../misc_patches/text_patches.py | 6 +-- src/open_samus_returns_rando/patch_util.py | 2 +- .../patcher_editor.py | 18 +++---- .../pickups/custom_pickups.py | 4 +- .../pickups/pickup.py | 22 ++++---- .../samus_returns_patcher.py | 19 ++----- .../specific_patches/chozo_seal_patches.py | 8 +-- .../specific_patches/cosmetic_patches.py | 4 +- .../specific_patches/door_patches.py | 51 ++++++++++--------- .../specific_patches/game_patches.py | 12 ++--- .../specific_patches/heat_room_patches.py | 6 +-- .../specific_patches/hint_patches.py | 2 +- .../specific_patches/map_icons.py | 2 +- .../specific_patches/metroid_patches.py | 16 +++--- .../specific_patches/static_fixes.py | 28 +++++----- .../specific_patches/tunable_patches.py | 6 +-- .../validator_with_default.py | 11 ++-- 31 files changed, 204 insertions(+), 152 deletions(-) delete mode 100644 src/open_samus_returns_rando/misc_patches/exefs.py diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index d72449b5..d7287482 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -103,6 +103,46 @@ jobs: run: venv/bin/python -m open_samus_returns_rando --input-path "$SAMUS_RETURNS_PATH" --output-path export/ --input-json tests/test_files/starter_preset_patcher.json + mypy: + runs-on: 'ubuntu-latest' + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Workaround for worktree config + run: git config --unset-all extensions.worktreeConfig || true + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: "pip" + + - name: Install Python packages + run: python -m pip install .[typing] + + - name: Mypy on modified files + uses: tsuyoshicho/action-mypy@v4 + with: + github_token: ${{ secrets.github_token }} + # Change reviewdog reporter if you need [github-pr-check,github-check,github-pr-review]. + reporter: github-check + setup_method: install + fail_on_error: false + + - name: Mypy on required files + uses: tsuyoshicho/action-mypy@v4 + with: + github_token: ${{ secrets.github_token }} + # Change reviewdog reporter if you need [github-pr-check,github-check,github-pr-review]. + reporter: github-check + setup_method: install + target: --config-file=pyproject.toml + fail_on_error: true + pypi: runs-on: 'ubuntu-latest' diff --git a/pyproject.toml b/pyproject.toml index 88534123..10313507 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,3 +65,19 @@ target-version = "py39" # Flag errors (`C901`) whenever the complexity level exceeds 25. # Defaults to 10, but we're being very flexible right now max-complexity = 25 + +[project.optional-dependencies] +typing = [ + "types-jsonschema", + "construct-typing", + "types-pyinstaller", + "mypy" +] + +[tool.mypy] +files = [ + "src/" +] +follow_imports = "silent" +disallow_untyped_defs = true +local_partial_types = true diff --git a/src/open_samus_returns_rando/__init__.py b/src/open_samus_returns_rando/__init__.py index b7b368b7..d05e9c16 100644 --- a/src/open_samus_returns_rando/__init__.py +++ b/src/open_samus_returns_rando/__init__.py @@ -3,7 +3,7 @@ from .patch_util import patch_with_status_update -def patch(input_path: Path, output_path: Path, configuration: dict): +def patch(input_path: Path, output_path: Path, configuration: dict) -> None: from .samus_returns_patcher import patch_extracted return patch_extracted(input_path, output_path, configuration) diff --git a/src/open_samus_returns_rando/__pyinstaller/__init__.py b/src/open_samus_returns_rando/__pyinstaller/__init__.py index b02db232..699081ea 100644 --- a/src/open_samus_returns_rando/__pyinstaller/__init__.py +++ b/src/open_samus_returns_rando/__pyinstaller/__init__.py @@ -13,5 +13,5 @@ # This function returns a list containing only the path to this # directory, which is the location of these hooks. -def get_hook_dirs(): +def get_hook_dirs() -> list[str]: return [os.path.dirname(__file__)] # noqa: PTH120 diff --git a/src/open_samus_returns_rando/cli.py b/src/open_samus_returns_rando/cli.py index 35ecd507..f79060e2 100644 --- a/src/open_samus_returns_rando/cli.py +++ b/src/open_samus_returns_rando/cli.py @@ -7,7 +7,7 @@ from open_samus_returns_rando import samus_returns_patcher -def create_parser(): +def create_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser() parser.add_argument("--input-path", required=True, type=Path, help="Path to where the extracted Metroid: Samus Returns romfs to randomize can be found.") @@ -18,7 +18,7 @@ def create_parser(): return parser -def setup_logging(): +def setup_logging() -> None: handlers = { 'default': { 'level': 'DEBUG', @@ -49,7 +49,7 @@ def setup_logging(): logging.info("Hello world.") -def main(): +def main() -> None: setup_logging() parser = create_parser() args = parser.parse_args() diff --git a/src/open_samus_returns_rando/constants.py b/src/open_samus_returns_rando/constants.py index 58d45a8a..67a5a33c 100644 --- a/src/open_samus_returns_rando/constants.py +++ b/src/open_samus_returns_rando/constants.py @@ -21,12 +21,12 @@ "s110_surfaceb", ] -def get_package_name(package_name: str, file_name: str): +def get_package_name(package_name: str, file_name: str) -> str: without = ["bcmdl", "bcwav", "bctex", "bcskla", "bcptl"] for ending in without: if file_name.endswith(ending): return package_name.replace("_discardables", "") return package_name -def lua_pkgs(pkgs: list[str]): +def lua_pkgs(pkgs: list[str]) -> list[str]: return [get_package_name(level_pkg, "lc") for level_pkg in pkgs] diff --git a/src/open_samus_returns_rando/debug.py b/src/open_samus_returns_rando/debug.py index 0f9ea8e8..3f6dcea3 100644 --- a/src/open_samus_returns_rando/debug.py +++ b/src/open_samus_returns_rando/debug.py @@ -1,15 +1,15 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def unpack_new_actor(new_actor: dict): +def unpack_new_actor(new_actor: dict) -> tuple[str, str, str, list[float]]: scenario_name = new_actor["new_actor"]["scenario"] new_actor_name = new_actor["new_actor"]["actor"] collision_camera_name = new_actor["collision_camera_name"] - new_pos = (new_actor["location"]["x"], new_actor["location"]["y"], new_actor["location"]["z"]) + new_pos = [new_actor["location"]["x"], new_actor["location"]["y"], new_actor["location"]["z"]] return scenario_name,new_actor_name,collision_camera_name,new_pos -def debug_spawn_points(editor: PatcherEditor, spawn_config: list[dict]): +def debug_spawn_points(editor: PatcherEditor, spawn_config: list[dict]) -> None: # create custom spawn point _EXAMPLE_SP = {"scenario": "s010_area1", "layer": "5", "actor": "StartPoint0"} base_actor = editor.resolve_actor_reference(_EXAMPLE_SP) @@ -20,7 +20,7 @@ def debug_spawn_points(editor: PatcherEditor, spawn_config: list[dict]): scenario.add_actor_to_entity_groups(collision_camera_name, new_actor_name) -def debug_custom_pickups(editor: PatcherEditor, pickup_config: list[dict]): +def debug_custom_pickups(editor: PatcherEditor, pickup_config: list[dict]) -> None: # create custom pickup _EXAMPLE_PICKUP = {"scenario": "s000_surface", "layer": "9", "actor": "LE_PowerUP_Morphball"} base_actor = editor.resolve_actor_reference(_EXAMPLE_PICKUP) diff --git a/src/open_samus_returns_rando/lua_editor.py b/src/open_samus_returns_rando/lua_editor.py index c612f45e..df7f852d 100644 --- a/src/open_samus_returns_rando/lua_editor.py +++ b/src/open_samus_returns_rando/lua_editor.py @@ -1,4 +1,5 @@ import itertools +from collections.abc import Iterable from construct import Container from mercury_engine_data_structures.formats.lua import Lua @@ -105,14 +106,14 @@ def ensure_files(self, editor: PatcherEditor) -> None: class LuaEditor: - def __init__(self): - self._item_classes = {} - self._metroid_dict = {} - self._dna_count_dict = {} - self._hint_dict = {} + def __init__(self) -> None: + self._item_classes: dict[str, ScriptClass] = {} + self._metroid_dict: dict[str, dict[str, str]] = {} + self._dna_count_dict: dict[str, int] = {} + self._hint_dict: dict[str, dict[str, list[str]]] = {} self._progressive_models = "" self._custom_level_scripts: dict[str, dict] = self._read_levels() - self._metroid_imports = [] + self._metroid_imports: list[str] = [] def _read_levels(self) -> dict[str, dict]: return { @@ -120,7 +121,7 @@ def _read_levels(self) -> dict[str, dict]: for scenario in ALL_SCENARIOS } - def get_parent_for(self, item_id) -> str: + def get_parent_for(self, item_id: str) -> str: return SPECIFIC_CLASSES.get(item_id, "RandomizerPowerup") def create_script_class(self, pickup: dict, actordef_id: str = "") -> ScriptClass: @@ -174,7 +175,7 @@ def create_script_class(self, pickup: dict, actordef_id: str = "") -> ScriptClas return new_script_class - def add_progressive_models(self, pickup: dict, actordef_name: str): + def add_progressive_models(self, pickup: dict, actordef_name: str) -> None: progressive_models = [ { "item": lua_util.wrap_string(resource["item_id"]), @@ -233,7 +234,7 @@ def _create_custom_init(self, editor: PatcherEditor, configuration: dict) -> str final_inventory.update(inventory) # Use itertools batched when upgrading to python 3.12 - def chunks(array: list[str], n: int): + def chunks(array: list[str], n: int) -> Iterable[list[str]]: for i in range(0, len(array), n): yield array[i:i + n] @@ -260,7 +261,7 @@ def chunks(array: list[str], n: int): return lua_util.replace_lua_template("custom_init.lua", replacement) - def _add_replacement_files(self, editor: PatcherEditor, configuration: dict): + def _add_replacement_files(self, editor: PatcherEditor, configuration: dict) -> None: # Update init.lc lua_util.create_script_copy(editor, "system/scripts/init") @@ -280,7 +281,7 @@ def _add_replacement_files(self, editor: PatcherEditor, configuration: dict): lua_util.replace_script(editor, "actors/props/heatzone/scripts/heatzone", "custom/heatzone.lua") lua_util.replace_script(editor, "gui/scripts/sprites_splashes", "custom/sprites_splashes.lua") - def save_modifications(self, editor: PatcherEditor, configuration: dict): + def save_modifications(self, editor: PatcherEditor, configuration: dict) -> None: self._add_replacement_files(editor, configuration) # add new system scripts diff --git a/src/open_samus_returns_rando/misc_patches/collision_camera_table.py b/src/open_samus_returns_rando/misc_patches/collision_camera_table.py index 247b4ffb..549f9be6 100644 --- a/src/open_samus_returns_rando/misc_patches/collision_camera_table.py +++ b/src/open_samus_returns_rando/misc_patches/collision_camera_table.py @@ -4,7 +4,7 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def create_collision_camera_table(editor: PatcherEditor, configuration: dict): +def create_collision_camera_table(editor: PatcherEditor, configuration: dict) -> None: py_dict: dict = configuration["cosmetic_patches"]["camera_names_dict"] # Surface diff --git a/src/open_samus_returns_rando/misc_patches/credits.py b/src/open_samus_returns_rando/misc_patches/credits.py index 90f72864..a84245b7 100644 --- a/src/open_samus_returns_rando/misc_patches/credits.py +++ b/src/open_samus_returns_rando/misc_patches/credits.py @@ -23,7 +23,7 @@ ] } -def _create_randomizer_credits(spoiler_log: dict[str, str]): +def _create_randomizer_credits(spoiler_log: dict[str, str]) -> tuple[list[tuple[str, str]], int, int, int]: rando_credits: list[tuple[str, str]] = [ ("Randomizer Credits", "CREDIT_TITLE"), ] @@ -46,7 +46,7 @@ def _create_randomizer_credits(spoiler_log: dict[str, str]): amount_subtitle = 0 amount_credit = 0 - def new_sort(prefix: str, item) -> tuple[str, str]: + def new_sort(prefix: str, item: str) -> tuple[str, str]: nonlocal amount_title nonlocal amount_subtitle nonlocal amount_credit @@ -67,7 +67,7 @@ def new_sort(prefix: str, item) -> tuple[str, str]: return rando_credits, amount_title, amount_subtitle, amount_credit -def patch_credits(editor: PatcherEditor, spoiler_log: dict[str, str]): +def patch_credits(editor: PatcherEditor, spoiler_log: dict[str, str]) -> None: english_files = [ "system/localization/mse_english.txt", ] diff --git a/src/open_samus_returns_rando/misc_patches/elevators.py b/src/open_samus_returns_rando/misc_patches/elevators.py index ece7c649..21d10fd4 100644 --- a/src/open_samus_returns_rando/misc_patches/elevators.py +++ b/src/open_samus_returns_rando/misc_patches/elevators.py @@ -4,7 +4,7 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def create_elevator_table(editor: PatcherEditor, configuration: dict): +def create_elevator_table(editor: PatcherEditor, configuration: dict) -> None: py_dict: dict = configuration["elevators"] file = lua_util.replace_lua_template("elevators.lua", {"elevator_dict": py_dict}, True) @@ -15,7 +15,7 @@ def create_elevator_table(editor: PatcherEditor, configuration: dict): ) -def update_elevators(editor: PatcherEditor, configuration: dict): +def update_elevators(editor: PatcherEditor, configuration: dict) -> None: for scenario_name, elevators in configuration["elevators"].items(): scenario = editor.get_scenario(scenario_name) for elevator in elevators: @@ -23,6 +23,6 @@ def update_elevators(editor: PatcherEditor, configuration: dict): platform["arguments"][1]["value"] = "Scenario.RandoOnElevatorUse" -def patch_elevators(editor: PatcherEditor, configuration: dict): +def patch_elevators(editor: PatcherEditor, configuration: dict) -> None: create_elevator_table(editor, configuration) update_elevators(editor, configuration) diff --git a/src/open_samus_returns_rando/misc_patches/exefs.py b/src/open_samus_returns_rando/misc_patches/exefs.py deleted file mode 100644 index 56ad1b55..00000000 --- a/src/open_samus_returns_rando/misc_patches/exefs.py +++ /dev/null @@ -1,9 +0,0 @@ -import ips - - -class DSPatch(ips.Patch): - def __init__(self): - super().__init__(False) - - def add_record(self, offset, content, rle_size=-1): - return super().add_record(offset, content, rle_size) diff --git a/src/open_samus_returns_rando/misc_patches/lua_util.py b/src/open_samus_returns_rando/misc_patches/lua_util.py index e34ce0f8..71040f4a 100644 --- a/src/open_samus_returns_rando/misc_patches/lua_util.py +++ b/src/open_samus_returns_rando/misc_patches/lua_util.py @@ -1,4 +1,5 @@ import re +import typing from construct import Container from mercury_engine_data_structures.file_tree_editor import FileTreeEditor @@ -6,7 +7,7 @@ from open_samus_returns_rando.files import files_path, templates_path -def replace_lua_template(file: str, replacement: dict[str, str], wrap_strings: bool = False) -> str: +def replace_lua_template(file: str, replacement: dict[str, typing.Any], wrap_strings: bool = False) -> str: code = templates_path().joinpath(file).read_text() for key, content in replacement.items(): # Replace `TEMPLATE("key")`-style replacements @@ -23,7 +24,7 @@ def replace_lua_template(file: str, replacement: dict[str, str], wrap_strings: b return code -def lua_convert(data, wrap_strings: bool = False) -> str: +def lua_convert(data: typing.Any, wrap_strings: bool = False) -> str: if isinstance(data, list): return "{\n" + "\n".join( f"{lua_convert(item, wrap_strings)}," @@ -46,7 +47,7 @@ def wrap_string(data: str) -> str: return f'"{data}"' -def create_script_copy(editor: FileTreeEditor, path: str): +def create_script_copy(editor: FileTreeEditor, path: str) -> None: original = path + "_original.lc" if not editor.does_asset_exists(original): original_lc = editor.get_raw_asset(path + ".lc") @@ -57,13 +58,13 @@ def create_script_copy(editor: FileTreeEditor, path: str): ) -def replace_script(editor: FileTreeEditor, path: str, replacement_path: str): +def replace_script(editor: FileTreeEditor, path: str, replacement_path: str) -> None: create_script_copy(editor, path) lua_content = files_path().joinpath(replacement_path).read_text() lua_resource = Lua(Container(lua_text=lua_content), editor.target_game) editor.replace_asset(path + ".lc", lua_resource) -def replace_script_with_content(editor: FileTreeEditor, path: str, lua_content: str): +def replace_script_with_content(editor: FileTreeEditor, path: str, lua_content: str) -> None: create_script_copy(editor, path) lua_resource = Lua(Container(lua_text=lua_content), editor.target_game) editor.replace_asset(path + ".lc", lua_resource) diff --git a/src/open_samus_returns_rando/misc_patches/spawn_points.py b/src/open_samus_returns_rando/misc_patches/spawn_points.py index b3f80a09..fc102dd7 100644 --- a/src/open_samus_returns_rando/misc_patches/spawn_points.py +++ b/src/open_samus_returns_rando/misc_patches/spawn_points.py @@ -24,7 +24,7 @@ class NewSpawnPoint(typing.NamedTuple): ] -def add_spawnpoints(editor: PatcherEditor, new_spawnpoint: NewSpawnPoint): +def add_spawnpoints(editor: PatcherEditor, new_spawnpoint: NewSpawnPoint) -> None: template_sp = editor.get_scenario("s000_surface").raw.actors[5]["ST_SG_Alpha_001"] scenario_name = new_spawnpoint.scenario @@ -38,6 +38,6 @@ def add_spawnpoints(editor: PatcherEditor, new_spawnpoint: NewSpawnPoint): scenario_file.add_actor_to_entity_groups(entity_group, new_spawnpoint.name, True) -def patch_custom_spawn_points(editor: PatcherEditor): +def patch_custom_spawn_points(editor: PatcherEditor) -> None: for new_spawnpoint in new_spawnpoints: add_spawnpoints(editor, new_spawnpoint) diff --git a/src/open_samus_returns_rando/misc_patches/text_patches.py b/src/open_samus_returns_rando/misc_patches/text_patches.py index b55b94c1..01883e21 100644 --- a/src/open_samus_returns_rando/misc_patches/text_patches.py +++ b/src/open_samus_returns_rando/misc_patches/text_patches.py @@ -23,7 +23,7 @@ } -def patch_text(editor: PatcherEditor, key: str, value: str): +def patch_text(editor: PatcherEditor, key: str, value: str) -> None: for text_file in ALL_TEXT_FILES: text = editor.get_file(f"system/localization/{text_file}", Txt) text.strings[key] = value @@ -34,12 +34,12 @@ def get_text(editor: PatcherEditor, key: str, text_file: str = "us_english.txt") return text.strings[key] -def apply_text_patches(editor: PatcherEditor, patches: dict[str, str]): +def apply_text_patches(editor: PatcherEditor, patches: dict[str, str]) -> None: for k, v in patches.items(): patch_text(editor, k, v) -def add_spiderboost_status(editor: PatcherEditor): +def add_spiderboost_status(editor: PatcherEditor) -> None: status = "GUI_STATUS_POWERBOMB" original = get_text(editor, status) new = original.replace( diff --git a/src/open_samus_returns_rando/patch_util.py b/src/open_samus_returns_rando/patch_util.py index dc0dbc8c..b2e2c6e1 100644 --- a/src/open_samus_returns_rando/patch_util.py +++ b/src/open_samus_returns_rando/patch_util.py @@ -6,7 +6,7 @@ def patch_with_status_update(input_path: Path, output_path: Path, configuration: dict, - status_update: typing.Callable[[float, str], None]): + status_update: typing.Callable[[float, str], None]) -> None: from open_samus_returns_rando.samus_returns_patcher import patch_extracted # messages depends on the layout but it is a good approximation total_logs = 410 diff --git a/src/open_samus_returns_rando/patcher_editor.py b/src/open_samus_returns_rando/patcher_editor.py index d8231042..e877c31b 100644 --- a/src/open_samus_returns_rando/patcher_editor.py +++ b/src/open_samus_returns_rando/patcher_editor.py @@ -23,21 +23,21 @@ def __init__(self, root: Path): super().__init__(root, Game.SAMUS_RETURNS) self.memory_files = {} - def get_file(self, path: str, type_hint: type[T] = BaseResource) -> T: + def get_file(self, path: str, type_hint: type[T] = BaseResource) -> T: # type: ignore if path not in self.memory_files: - self.memory_files[path] = self.get_parsed_asset(path, type_hint=type_hint) - return self.memory_files[path] + self.memory_files[path] = self.get_parsed_asset(path, type_hint=type_hint) # type: ignore + return self.memory_files[path] # type: ignore def get_level_pkgs(self, name: str) -> set[str]: return set(self.find_pkgs(path_for_level(name) + ".bmsld")) def get_all_level_pkgs(self) -> list[str]: - def get_nested_list(): + def get_nested_list() -> typing.Iterable[set[str]]: for scenario in ALL_SCENARIOS: yield self.get_level_pkgs(scenario) return [pkg for all_level_pkgs in get_nested_list() for pkg in all_level_pkgs] - def ensure_present_in_scenario(self, scenario: str, asset): + def ensure_present_in_scenario(self, scenario: str, asset: str) -> None: for pkg in self.get_level_pkgs(scenario): self.ensure_present(get_package_name(pkg, asset), asset) @@ -50,13 +50,13 @@ def resolve_actor_reference(self, ref: dict) -> Container: layer = int(ref.get("layer", "default")) return scenario.raw.actors[layer][ref["actor"]] - def flush_modified_assets(self): + def flush_modified_assets(self) -> None: for name, resource in self.memory_files.items(): self.replace_asset(name, resource) self.memory_files = {} - def copy_actor(self, scenario: str, coords, template_actor: Container, new_name: str, - layer_index: int, offset: tuple = (0, 0, 0)): + def copy_actor(self, scenario: str, coords: list[float], template_actor: Container, new_name: str, + layer_index: int, offset: tuple = (0, 0, 0)) -> Container: new_actor = copy.deepcopy(template_actor) current_scenario = self.get_scenario(scenario) current_scenario.raw.actors[layer_index][new_name] = new_actor @@ -66,7 +66,7 @@ def copy_actor(self, scenario: str, coords, template_actor: Container, new_name: return new_actor - def remove_entity(self, reference: dict): + def remove_entity(self, reference: dict)-> None: scenario = self.get_scenario(reference["scenario"]) layer = reference["layer"] actor_name = reference["actor"] diff --git a/src/open_samus_returns_rando/pickups/custom_pickups.py b/src/open_samus_returns_rando/pickups/custom_pickups.py index 842fe7bd..8d6307d7 100644 --- a/src/open_samus_returns_rando/pickups/custom_pickups.py +++ b/src/open_samus_returns_rando/pickups/custom_pickups.py @@ -20,7 +20,7 @@ class NewPickups(typing.NamedTuple): ] -def add_pickups(editor: PatcherEditor, new_pickup: NewPickups): +def add_pickups(editor: PatcherEditor, new_pickup: NewPickups) -> None: template_pickup = editor.get_scenario("s000_surface").raw.actors[9]["LE_PowerUP_Morphball"] PICKUP_ICON = Container({ @@ -43,6 +43,6 @@ def add_pickups(editor: PatcherEditor, new_pickup: NewPickups): scenario_file.add_actor_to_entity_groups(entity_group, new_pickup.name, True) -def patch_custom_pickups(editor: PatcherEditor): +def patch_custom_pickups(editor: PatcherEditor) -> None: for new_pickup in new_pickups: add_pickups(editor, new_pickup) diff --git a/src/open_samus_returns_rando/pickups/pickup.py b/src/open_samus_returns_rando/pickups/pickup.py index a7b9c179..23b5e071 100644 --- a/src/open_samus_returns_rando/pickups/pickup.py +++ b/src/open_samus_returns_rando/pickups/pickup.py @@ -70,7 +70,7 @@ }) @functools.cache -def _read_template_powerup(): +def _read_template_powerup() -> dict: with templates_path().joinpath("template_powerup_bmsad.json").open() as f: return json.load(f) @@ -85,10 +85,10 @@ def __init__(self, lua_editor: LuaEditor, pickup: dict, pickup_id: int, configur self.pickup_id = pickup_id self.configuration = configuration - def patch(self, editor: PatcherEditor): + def patch(self, editor: PatcherEditor) -> None: raise NotImplementedError - def get_scenario(self): + def get_scenario(self) -> str: raise NotImplementedError class ActorPickup(BasePickup): @@ -128,7 +128,7 @@ def add_new_bmsad(self, editor: PatcherEditor, actordef_id: str, pkgs_for_level: new_template, script_class = self.patch_item_pickup(new_template) new_path = script_class.get_bmsad_path() - editor.add_new_asset(new_path, Bmsad(new_template, editor.target_game), in_pkgs=pkgs_for_level) + editor.add_new_asset(new_path, Bmsad(new_template, editor.target_game), in_pkgs=pkgs_for_level) # type: ignore return script_class @@ -248,7 +248,7 @@ def patch_model(self, model_names: list[str], bmsad: dict) -> None: MODELUPDATER["fields"]["vInitAngWorldOffset"]["value"][0] = 0.0 - def patch(self, editor: PatcherEditor): + def patch(self, editor: PatcherEditor) -> None: actor_reference = self.pickup["pickup_actor"] actor_name = actor_reference["actor"] model_names: list[str] = self.pickup["model"] @@ -298,17 +298,17 @@ def patch(self, editor: PatcherEditor): for dep in model_data.dependencies: editor.ensure_present(get_package_name(level_pkg, dep), dep) - def get_scenario(self): + def get_scenario(self) -> str: return self.pickup["pickup_actor"]["scenario"] class MetroidPickup(BasePickup): - def patch(self, editor: PatcherEditor): + def patch(self, editor: PatcherEditor) -> None: script_class = self.lua_editor.create_script_class(self.pickup, f"metroid_{self.pickup_id}") script_class.ensure_files(editor) self.lua_editor.add_metroid_pickup(self.pickup["metroid_callback"], script_class) - def get_scenario(self): + def get_scenario(self) -> str: return self.pickup["metroid_callback"]["scenario"] @@ -330,13 +330,15 @@ def ensure_base_models(editor: PatcherEditor) -> None: for dep in model_data.dependencies: editor.ensure_present(get_package_name(level_pkg, dep), dep) -def count_dna(lua_scripts: LuaEditor, pickup_object: BasePickup): +def count_dna(lua_scripts: LuaEditor, pickup_object: BasePickup) -> None: item_id = pickup_object.pickup["resources"][0][0]["item_id"] if item_id.startswith("ITEM_RANDO_DNA"): scenario: str = pickup_object.get_scenario() lua_scripts.add_dna(scenario) -def patch_pickups(editor: PatcherEditor, lua_scripts: LuaEditor, pickups_config: list[dict], configuration: dict): +def patch_pickups( + editor: PatcherEditor, lua_scripts: LuaEditor, pickups_config: list[dict], configuration: dict + ) -> None: ActorPickup._bmsad_dict = {} editor.add_new_asset( "actors/items/randomizerpowerup/scripts/randomizerpowerup.lc", diff --git a/src/open_samus_returns_rando/samus_returns_patcher.py b/src/open_samus_returns_rando/samus_returns_patcher.py index eda6c166..71f4eb6c 100644 --- a/src/open_samus_returns_rando/samus_returns_patcher.py +++ b/src/open_samus_returns_rando/samus_returns_patcher.py @@ -12,7 +12,6 @@ from open_samus_returns_rando.misc_patches.collision_camera_table import create_collision_camera_table from open_samus_returns_rando.misc_patches.credits import patch_credits from open_samus_returns_rando.misc_patches.elevators import patch_elevators -from open_samus_returns_rando.misc_patches.exefs import DSPatch from open_samus_returns_rando.misc_patches.spawn_points import patch_custom_spawn_points from open_samus_returns_rando.misc_patches.text_patches import add_spiderboost_status, apply_text_patches from open_samus_returns_rando.patcher_editor import PatcherEditor @@ -30,11 +29,11 @@ T = typing.TypeVar("T") -def _read_schema(): +def _read_schema() -> dict: with Path(__file__).parent.joinpath("files", "schema.json").open() as f: return json.load(f) -def add_custom_files(editor: PatcherEditor): +def add_custom_files(editor: PatcherEditor) -> None: custom_romfs = files_path().joinpath("romfs") for child in custom_romfs.rglob("*"): if not child.is_file(): @@ -49,16 +48,10 @@ def add_custom_files(editor: PatcherEditor): editor.replace_asset(asset_name, raw_bytes) -def patch_exefs(exefs_patches: Path): - exefs_patches.mkdir(parents=True, exist_ok=True) - patch = DSPatch() - # file needs to be named code.ips for Citra - exefs_patches.joinpath("code.ips").write_bytes(bytes(patch)) - -def validate(configuration: dict): +def validate(configuration: dict) -> None: DefaultValidatingDraft7Validator(_read_schema()).validate(configuration) -def patch_extracted(input_path: Path, output_path: Path, configuration: dict): +def patch_extracted(input_path: Path, output_path: Path, configuration: dict) -> None: LOG.info("Will patch files from %s", input_path) validate(configuration) @@ -125,10 +118,6 @@ def patch_extracted(input_path: Path, output_path: Path, configuration: dict): shutil.rmtree(out_romfs, ignore_errors=True) shutil.rmtree(out_exefs, ignore_errors=True) - # Create Exefs patches (currently there are none) - LOG.info("Creating exefs patches") - patch_exefs(out_exefs) - LOG.info("Saving modified lua scripts") lua_scripts.save_modifications(editor, configuration) diff --git a/src/open_samus_returns_rando/specific_patches/chozo_seal_patches.py b/src/open_samus_returns_rando/specific_patches/chozo_seal_patches.py index 1475f4e1..9c1d0d5f 100644 --- a/src/open_samus_returns_rando/specific_patches/chozo_seal_patches.py +++ b/src/open_samus_returns_rando/specific_patches/chozo_seal_patches.py @@ -30,7 +30,7 @@ }) -def patch_seals(editor: PatcherEditor): +def patch_seals(editor: PatcherEditor) -> None: systemmechdna_name = "actors/props/systemmechdna/charclasses/systemmechdna.bmsad" save_station_name = "actors/props/savestation/charclasses/savestation.bmsad" chozoseal_name = "actors/props/chozoseal/charclasses/chozoseal.bmsad" @@ -110,7 +110,7 @@ class NewChozoSeal(typing.NamedTuple): ), ] -def add_chozo_seals(editor: PatcherEditor, new_seal: NewChozoSeal): +def add_chozo_seals(editor: PatcherEditor, new_seal: NewChozoSeal) -> None: template_ap = editor.get_scenario("s000_surface").raw.actors[16]["LE_ChozoUnlockAreaDNA"] template_platform = editor.get_scenario("s000_surface").raw.actors[10]["LE_Platform_ChozoUnlockAreaDNA"] @@ -146,7 +146,7 @@ def add_chozo_seals(editor: PatcherEditor, new_seal: NewChozoSeal): editor.ensure_present_in_scenario(scenario_name, asset) -def update_item_seals(editor:PatcherEditor): +def update_item_seals(editor:PatcherEditor) -> None: CHOZO_SEALS = { "s000_surface": ["LE_ChozoUnlockAreaDNA"], "s010_area1": ["LE_ChozoUnlockAreaDNA"], @@ -168,7 +168,7 @@ def update_item_seals(editor:PatcherEditor): editor.ensure_present_in_scenario(scenario_name, asset) -def patch_chozo_seals(editor: PatcherEditor): +def patch_chozo_seals(editor: PatcherEditor) -> None: patch_seals(editor) for new_seal in new_seals: add_chozo_seals(editor, new_seal) diff --git a/src/open_samus_returns_rando/specific_patches/cosmetic_patches.py b/src/open_samus_returns_rando/specific_patches/cosmetic_patches.py index 9fe470da..6c6ca14c 100644 --- a/src/open_samus_returns_rando/specific_patches/cosmetic_patches.py +++ b/src/open_samus_returns_rando/specific_patches/cosmetic_patches.py @@ -3,12 +3,12 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def patch_cosmetics(editor: PatcherEditor, configuration: dict): +def patch_cosmetics(editor: PatcherEditor, configuration: dict) -> None: tunables = editor.get_file("system/tunables/tunables.bmtun", Bmtun) tunable_cosmetics(tunables, configuration) -def tunable_cosmetics(tunables: Bmtun, configuration: dict): +def tunable_cosmetics(tunables: Bmtun, configuration: dict) -> None: aim = tunables.raw["classes"]["CTunableAim"]["tunables"] aim["vLaserLockedColor0"]["value"] = configuration["laser_locked_color"] aim["vLaserUnlockedColor0"]["value"] = configuration["laser_unlocked_color"] diff --git a/src/open_samus_returns_rando/specific_patches/door_patches.py b/src/open_samus_returns_rando/specific_patches/door_patches.py index 9db24b60..b201891f 100644 --- a/src/open_samus_returns_rando/specific_patches/door_patches.py +++ b/src/open_samus_returns_rando/specific_patches/door_patches.py @@ -1,6 +1,7 @@ import copy import re +import typing from enum import Enum from construct import Container, ListContainer @@ -39,7 +40,7 @@ "unk2": 1, "unk3": 0, "args": Container({ - 601445949: Container({ + "601445949": Container({ "type": "s", "value": "RemoveDoors", }), @@ -47,7 +48,7 @@ }) -def _patch_missile_covers(editor: PatcherEditor): +def _patch_missile_covers(editor: PatcherEditor) -> None: ALL_MISSILE_SHIELDS = { "s000_surface": ["LE_MissileShield_Door_002", "LE_MissileShield_Door_006"], "s010_area1": ["LE_DoorShieldMissile", "LE_DoorShieldMissile001"], @@ -72,7 +73,7 @@ def _patch_missile_covers(editor: PatcherEditor): actor["rotation"][1] = 90 -def _patch_beam_bmsads(editor: PatcherEditor): +def _patch_beam_bmsads(editor: PatcherEditor) -> None: creature_bmsad_files = [ "actors/props/doorspazerbeam/charclasses/doorspazerbeam.bmsad", "actors/props/doorcreature/charclasses/doorcreature.bmsad", @@ -92,10 +93,10 @@ def _patch_beam_bmsads(editor: PatcherEditor): # modify doorwave collision if i == 2: # Param6 and Param7 seems to be a position - cr_bmsad.components["COLLISION"].functions[1].params["Param7"].value = 148.0 + cr_bmsad.components["COLLISION"].functions[1].params["Param7"].value = 148.0 # type: ignore # Param9 and Param10 are a rectangular - cr_bmsad.components["COLLISION"].functions[1].params["Param9"].value = 370.0 - cr_bmsad.components["COLLISION"].functions[1].params["Param10"].value = 300.0 + cr_bmsad.components["COLLISION"].functions[1].params["Param9"].value = 370.0 # type: ignore + cr_bmsad.components["COLLISION"].functions[1].params["Param10"].value = 300.0 # type: ignore editor.add_new_asset( "actors/props/doors/scripts/doors.lc", @@ -104,7 +105,7 @@ def _patch_beam_bmsads(editor: PatcherEditor): ) -def _patch_beam_covers(editor: PatcherEditor): +def _patch_beam_covers(editor: PatcherEditor) -> None: ALL_BEAM_COVERS = { "s000_surface": ["LE_PlasmaShield_Door_008"], "s010_area1": ["LE_DoorShieldWave008", "LE_SpazerShield_Door007"], @@ -127,7 +128,7 @@ def _patch_beam_covers(editor: PatcherEditor): actor = scenario.raw.actors[9][cover_name] new_actor_name = f"{cover_name}_o" new_actor = editor.copy_actor( - scenario_name, (actor["position"][0], actor["position"][1], actor["position"][2]), + scenario_name, [actor["position"][0], actor["position"][1], actor["position"][2]], actor, new_actor_name, 9 ) new_actor["rotation"][0] = 0 @@ -149,7 +150,7 @@ def _patch_beam_covers(editor: PatcherEditor): scenario.insert_into_entity_group(group, new_actor_name) -def _patch_charge_doors(editor: PatcherEditor): +def _patch_charge_doors(editor: PatcherEditor) -> None: CHARGE_DOORS = { "s000_surface": ["Door004", "Door011"], "s010_area1": ["Door002"], @@ -166,7 +167,7 @@ def _patch_charge_doors(editor: PatcherEditor): scenario.raw.actors[15][door].type = "doorpowerpower" -def _patch_one_way_doors(editor: PatcherEditor): +def _patch_one_way_doors(editor: PatcherEditor) -> None: ONE_WAY_DOORS = { # Bombs, Right Exterior Door -> Interior, Exterior Alpha "s010_area1": ["Door004", "Door012", "Door016"], @@ -252,7 +253,7 @@ def __init__(self, rdv_door_type: str, door_data: ActorData, minimap_name: str, self.rotation = rotation @classmethod - def get_type(cls, type: str): + def get_type(cls, type: str) -> typing.Self: for e in cls: if e.type == type: return e @@ -263,9 +264,9 @@ class DoorPatcher: def __init__(self, editor: PatcherEditor): self.editor = editor self._example_shield = editor.get_scenario("s000_surface").raw.actors[9]["LE_PlasmaShield_Door_008"] - self._index_per_scenario = {} + self._index_per_scenario: dict[str, int] = {} - def _patch_to_power(self, door_actor: Container, scenario: Bmsld): + def _patch_to_power(self, door_actor: Container, scenario: Bmsld) -> None: for life_component in door_actor.components: shield = life_component["arguments"][3]["value"] if shield != "": @@ -276,20 +277,20 @@ def _patch_to_power(self, door_actor: Container, scenario: Bmsld): door_actor.components.pop() door_actor.components[0]["arguments"][2]["value"] = False door_actor.components[0]["arguments"][3]["value"] = "" - door_actor.type = ActorData.DOOR_POWER.value[0] + door_actor["type"] = ActorData.DOOR_POWER.value[0] def _create_shield( self, scenario_name: str, position: tuple[float, float, float], shield_name: str, new_type: str ) -> Container: new_actor = self.editor.copy_actor( - scenario_name, (position[0], position[1], position[2]), + scenario_name, [position[0], position[1], position[2]], self._example_shield, shield_name, 9 ) new_actor["type"] = new_type return new_actor - def patch_door(self, editor: PatcherEditor, actor_ref: dict, door_type_str: str): + def patch_door(self, editor: PatcherEditor, actor_ref: dict, door_type_str: str) -> None: scenario_name = actor_ref["scenario"] actor_name = actor_ref["actor"] scenario = self.editor.get_scenario(scenario_name) @@ -304,7 +305,10 @@ def patch_door(self, editor: PatcherEditor, actor_ref: dict, door_type_str: str) ) self.patch_minimap(editor, scenario_name, actor_name, left_shield_name, right_shield_name, new_door) - def patch_minimap(self, editor, scenario_name, actor_name, left_shield_name, right_shield_name, new_door): + def patch_minimap( + self, editor: PatcherEditor, scenario_name:str, actor_name:str, + left_shield_name:str, right_shield_name:str, new_door: DoorType + ) -> None: scenario_minimap = editor.get_file(f"gui/minimaps/c10_samus/{scenario_name}.bmsmsd", Bmsmsd) tiles = scenario_minimap.raw["tiles"] @@ -376,8 +380,8 @@ def patch_minimap(self, editor, scenario_name, actor_name, left_shield_name, rig def patch_actor( self, new_door: DoorType, scenario_name: str, actor_name: str, scenario: Bmsld, - door_actor, index: int, left_shield_name: str, right_shield_name: str - ): + door_actor: Container, index: int, left_shield_name: str, right_shield_name: str + ) -> None: if door_actor is None: raise ValueError(f"Actor {actor_name} not found in scenario {scenario_name}") @@ -385,9 +389,10 @@ def patch_actor( # patch to desired type if not new_door.need_shield: - door_actor.type = new_door.door.value[0] + door_actor["type"] = new_door.door.value[0] # all other use shields else: + assert new_door.shield is not None shield_position = (door_actor["position"][0], door_actor["position"][1], door_actor["position"][2]) new_actor_l = self._create_shield( scenario_name, shield_position, left_shield_name, new_door.shield.value[0] @@ -413,7 +418,7 @@ def patch_actor( # bad special case to force DoorManicMinerBot to doorclosed... if actor_name == "DoorManicMinerBot": - door_actor.type = re.sub("(doorpower|doorcharge)", "doorclosed", door_actor.type) + door_actor["type"] = re.sub("(doorpower|doorcharge)", "doorclosed", door_actor.type) # ensure required files for folder in new_door.required_asset_folders: @@ -421,14 +426,14 @@ def patch_actor( self.editor.ensure_present_in_scenario(scenario_name, asset) -def _static_door_patches(editor: PatcherEditor): +def _static_door_patches(editor: PatcherEditor) -> None: _patch_one_way_doors(editor) _patch_missile_covers(editor) _patch_beam_bmsads(editor) _patch_beam_covers(editor) _patch_charge_doors(editor) -def patch_doors(editor: PatcherEditor, door_patches: list[dict]): +def patch_doors(editor: PatcherEditor, door_patches: list[dict]) -> None: _static_door_patches(editor) door_patcher = DoorPatcher(editor) diff --git a/src/open_samus_returns_rando/specific_patches/game_patches.py b/src/open_samus_returns_rando/specific_patches/game_patches.py index 5c8a66ca..323e7ca4 100644 --- a/src/open_samus_returns_rando/specific_patches/game_patches.py +++ b/src/open_samus_returns_rando/specific_patches/game_patches.py @@ -3,7 +3,7 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def apply_game_patches(editor: PatcherEditor, configuration: dict): +def apply_game_patches(editor: PatcherEditor, configuration: dict) -> None: # Weapon patches _remove_pb_weaknesses(editor, configuration) @@ -16,7 +16,7 @@ def apply_game_patches(editor: PatcherEditor, configuration: dict): _patch_reverse_area8(editor, configuration) -def _remove_pb_weaknesses(editor: PatcherEditor, configuration: dict): +def _remove_pb_weaknesses(editor: PatcherEditor, configuration: dict) -> None: # Charge Door if configuration["charge_door_buff"]: for door in ["doorchargecharge", "doorclosedcharge"]: @@ -58,7 +58,7 @@ def _remove_pb_weaknesses(editor: PatcherEditor, configuration: dict): ] = Container({"type": "bool", "value": False}) -def _remove_grapple_blocks(editor: PatcherEditor, configuration: dict): +def _remove_grapple_blocks(editor: PatcherEditor, configuration: dict) -> None: ELEVATOR_GRAPPLE_BLOCKS = { # Area 4 West to Area 4 East "s040_area4": ["LE_GrappleMov_001"], @@ -84,7 +84,7 @@ def _remove_grapple_blocks(editor: PatcherEditor, configuration: dict): ) -def _remove_super_missile_weakness(editor: PatcherEditor): +def _remove_super_missile_weakness(editor: PatcherEditor) -> None: missile_door = editor.get_file( "actors/props/doorshieldmissile/charclasses/doorshieldmissile.bmsad", Bmsad ) @@ -93,7 +93,7 @@ def _remove_super_missile_weakness(editor: PatcherEditor): func.params.Param1.value = "MISSILE" -def _patch_crumble_blocks(editor: PatcherEditor, configuration: dict): +def _patch_crumble_blocks(editor: PatcherEditor, configuration: dict) -> None: # Crumble blocks after Scan Pulse if configuration["patch_surface_crumbles"]: surface = editor.get_file( @@ -119,7 +119,7 @@ def _patch_crumble_blocks(editor: PatcherEditor, configuration: dict): area1_chozo_seal_crumbles["types"][0]["blocks"][4]["respawn_time"] = 0.0 -def _patch_reverse_area8(editor: PatcherEditor, configuration: dict): +def _patch_reverse_area8(editor: PatcherEditor, configuration: dict) -> None: if configuration["reverse_area8"]: editor.remove_entity( {"scenario": "s100_area10", "layer": 9, "actor": "LE_ValveQueen"} diff --git a/src/open_samus_returns_rando/specific_patches/heat_room_patches.py b/src/open_samus_returns_rando/specific_patches/heat_room_patches.py index 36cc2f3d..d4402c40 100644 --- a/src/open_samus_returns_rando/specific_patches/heat_room_patches.py +++ b/src/open_samus_returns_rando/specific_patches/heat_room_patches.py @@ -5,7 +5,7 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def _patch_area_2b(editor: PatcherEditor): +def _patch_area_2b(editor: PatcherEditor) -> None: # area2b => shape is already correct but ms forgot to add one room heat_trigger_2b = {"scenario": "s025_area2b", "layer": "2", "actor": "TG_SP_Heat_001"} scenario_2b = editor.get_scenario(heat_trigger_2b["scenario"]) @@ -75,7 +75,7 @@ def _get_new_logic_shape(editor: PatcherEditor, new_actor: NewHeatActor) -> Cont return ls_copy -def add_heat_actors(editor: PatcherEditor, new_heat_actor: NewHeatActor): +def add_heat_actors(editor: PatcherEditor, new_heat_actor: NewHeatActor)-> None: template_ht = editor.get_scenario("s010_area1").raw.actors[2]["TG_Heat_001"] scenario_name = new_heat_actor.scenario @@ -95,7 +95,7 @@ def add_heat_actors(editor: PatcherEditor, new_heat_actor: NewHeatActor): scenario_file.add_actor_to_entity_groups(entity_group, new_heat_actor.trigger_name, True) -def patch_heat_rooms(editor: PatcherEditor): +def patch_heat_rooms(editor: PatcherEditor)-> None: _patch_area_2b(editor) for new_heat_actor in new_heat_actors: add_heat_actors(editor, new_heat_actor) diff --git a/src/open_samus_returns_rando/specific_patches/hint_patches.py b/src/open_samus_returns_rando/specific_patches/hint_patches.py index d6dc8cc6..18542ccd 100644 --- a/src/open_samus_returns_rando/specific_patches/hint_patches.py +++ b/src/open_samus_returns_rando/specific_patches/hint_patches.py @@ -1,6 +1,6 @@ from open_samus_returns_rando.lua_editor import LuaEditor -def patch_hints(lua_scripts: LuaEditor, hints: list): +def patch_hints(lua_scripts: LuaEditor, hints: list) -> None: for hint in hints: lua_scripts.add_hint(hint) diff --git a/src/open_samus_returns_rando/specific_patches/map_icons.py b/src/open_samus_returns_rando/specific_patches/map_icons.py index 24b81177..1d260042 100644 --- a/src/open_samus_returns_rando/specific_patches/map_icons.py +++ b/src/open_samus_returns_rando/specific_patches/map_icons.py @@ -4,7 +4,7 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def patch_tiles(editor: PatcherEditor): +def patch_tiles(editor: PatcherEditor) -> None: SCENARIO_TO_DOORS = { "s000_surface": ["Door004", "Door011"], "s010_area1": ["Door002", "Door004", "Door012", "Door016"], diff --git a/src/open_samus_returns_rando/specific_patches/metroid_patches.py b/src/open_samus_returns_rando/specific_patches/metroid_patches.py index 402bd634..ccd09dae 100644 --- a/src/open_samus_returns_rando/specific_patches/metroid_patches.py +++ b/src/open_samus_returns_rando/specific_patches/metroid_patches.py @@ -5,7 +5,7 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def _patch_metroids(editor: PatcherEditor): +def _patch_metroids(editor: PatcherEditor) -> None: METROID_FILES = [ "actors/characters/alpha/charclasses/alpha.bmsad", "actors/characters/alphaevolved/charclasses/alphaevolved.bmsad", @@ -56,12 +56,12 @@ def _patch_metroids(editor: PatcherEditor): class NewStartPoint(typing.NamedTuple): scenario: str - tg_name: str - tg_position: list[float] - st_name: str + tg_name: str | None + tg_position: list[float] | None + st_name: str | None st_position: list[float] st_rotation: int - st_out_name: str + st_out_name: str | None entity_groups: list[str] @@ -101,7 +101,7 @@ class NewStartPoint(typing.NamedTuple): ] -def add_startpoints(editor: PatcherEditor, new_startpoint: NewStartPoint): +def add_startpoints(editor: PatcherEditor, new_startpoint: NewStartPoint) -> None: template_tg = editor.get_scenario("s025_area2b").raw.actors[0]["TG_SetCheckpoint_001_Gamma_001"] template_st = editor.get_scenario("s025_area2b").raw.actors[5]["ST_SG_Gamma_001"] @@ -109,7 +109,7 @@ def add_startpoints(editor: PatcherEditor, new_startpoint: NewStartPoint): scenario_file = editor.get_scenario(scenario_name) # Copy the actors - if new_startpoint.tg_name is not None: + if new_startpoint.tg_name is not None and new_startpoint.tg_position is not None : editor.copy_actor(scenario_name, new_startpoint.tg_position, template_tg, new_startpoint.tg_name, 0) if new_startpoint.st_name is not None: editor.copy_actor(scenario_name, new_startpoint.st_position, template_st, new_startpoint.st_name, 5) @@ -140,7 +140,7 @@ def add_startpoints(editor: PatcherEditor, new_startpoint: NewStartPoint): ][3]["value"] = ("CurrentScenario.OnEnter_" + new_startpoint.tg_name[3:]) -def patch_metroids(editor: PatcherEditor): +def patch_metroids(editor: PatcherEditor) -> None: _patch_metroids(editor) for new_startpoint in new_startpoints: add_startpoints(editor, new_startpoint) diff --git a/src/open_samus_returns_rando/specific_patches/static_fixes.py b/src/open_samus_returns_rando/specific_patches/static_fixes.py index 5b269e5f..996b1065 100644 --- a/src/open_samus_returns_rando/specific_patches/static_fixes.py +++ b/src/open_samus_returns_rando/specific_patches/static_fixes.py @@ -1,4 +1,5 @@ import copy +import typing from construct import Container, ListContainer from mercury_engine_data_structures.formats import Bmsad, Bmsbk, Bmtun @@ -45,7 +46,7 @@ ] -def patch_multi_room_gammas(editor: PatcherEditor): +def patch_multi_room_gammas(editor: PatcherEditor) -> None: for reference in MULTI_ROOM_GAMMAS: editor.remove_entity(reference) @@ -70,7 +71,7 @@ def patch_multi_room_gammas(editor: PatcherEditor): scenario.raw["actors"][4]["Gamma_002_A"]["position"][0] = 17100.0 -def patch_pickup_rotation(editor: PatcherEditor): +def patch_pickup_rotation(editor: PatcherEditor) -> None: PICKUPS = { "s030_area3": ["LE_PowerUp_GrappleBeam"], "s050_area5": ["LE_PowerUp_SpaceJump"], @@ -82,7 +83,7 @@ def patch_pickup_rotation(editor: PatcherEditor): actor["rotation"][1] = 0.0 -def patch_pickup_position(editor: PatcherEditor): +def patch_pickup_position(editor: PatcherEditor) -> None: PICKUPS = { "s000_surface": ["LE_SpecialAbility_ScanningPulse"], "s010_area1": ["LE_PowerUp_SpiderBall"], @@ -100,27 +101,27 @@ def patch_pickup_position(editor: PatcherEditor): actor["position"][1] -= 49.0 -def remove_area7_grapple_block(editor: PatcherEditor): +def remove_area7_grapple_block(editor: PatcherEditor) -> None: editor.remove_entity( {"scenario": "s090_area9", "layer": 9, "actor": "LE_GrappleDest_007"} ) -def patch_a7_save_screw_blocks(editor: PatcherEditor): +def patch_a7_save_screw_blocks(editor: PatcherEditor) -> None: area7 = editor.get_file( "maps/levels/c10_samus/s090_area9/s090_area9.bmsbk", Bmsbk ) area7.raw["block_groups"][56]["types"][0]["block_type"] = "power_beam" -def shoot_supers_without_missiles(editor: PatcherEditor): +def shoot_supers_without_missiles(editor: PatcherEditor) -> None: samus_bmsad = editor.get_file( "actors/characters/samus/charclasses/samus.bmsad", Bmsad ) samus_bmsad.raw["components"]["GUN"]["functions"][20]["params"]["Param5"]["value"] = "ITEM_MISSILE_CHECK" -def nerf_ridley_fight(editor: PatcherEditor): +def nerf_ridley_fight(editor: PatcherEditor) -> None: ''' All beams (except Ice) will use the same factor as Plasma which is 0.12 Power Beam: 25 -> 3 @@ -144,7 +145,7 @@ def nerf_ridley_fight(editor: PatcherEditor): ridley_tunables["fGrabPlasmaBeamWeaponBoostPhaseDisplacement"]["value"] = 1.1 -def increase_pb_drop_chance(editor: PatcherEditor): +def increase_pb_drop_chance(editor: PatcherEditor) -> None: ACTOR_FILES = [ "alpha", "alphaevolved", @@ -202,7 +203,7 @@ def increase_pb_drop_chance(editor: PatcherEditor): drop["fPowerBombProbability"]["value"] *= 2 -def fix_wrong_cc_actor_deletions(editor: PatcherEditor): +def fix_wrong_cc_actor_deletions(editor: PatcherEditor) -> None: # Prevents hidden item actors from being deleted when its block is broken from an adjacent cc CUSTOM_BLOCK = Container({ "pos": ListContainer([ @@ -273,15 +274,16 @@ def fix_wrong_cc_actor_deletions(editor: PatcherEditor): else: new_group = copy.deepcopy(BOMB_GROUP) new_block = copy.deepcopy(CUSTOM_BLOCK) - new_block.pos = pos - new_block.name1 = sg_casca - new_group.types[0].blocks.append(new_block) + new_block["pos"] = pos + new_block["name1"] = sg_casca + types: ListContainer = typing.cast(ListContainer, new_group["types"]) + types[0]["blocks"].append(new_block) bmsbk.raw.block_groups.append(new_group) bmsbk_cc_obj = next(cc_obj for cc_obj in bmsbk.raw.collision_cameras if cc_name in cc_obj.name) bmsbk_cc_obj.entries.append(len(bmsbk.raw.block_groups) - 1) -def apply_static_fixes(editor: PatcherEditor): +def apply_static_fixes(editor: PatcherEditor) -> None: patch_multi_room_gammas(editor) patch_pickup_rotation(editor) patch_pickup_position(editor) diff --git a/src/open_samus_returns_rando/specific_patches/tunable_patches.py b/src/open_samus_returns_rando/specific_patches/tunable_patches.py index bb32702d..6a9551a7 100644 --- a/src/open_samus_returns_rando/specific_patches/tunable_patches.py +++ b/src/open_samus_returns_rando/specific_patches/tunable_patches.py @@ -2,19 +2,19 @@ from open_samus_returns_rando.patcher_editor import PatcherEditor -def patch_tunables(editor: PatcherEditor, configuration: dict): +def patch_tunables(editor: PatcherEditor, configuration: dict) -> None: tunables = editor.get_file("system/tunables/tunables.bmtun", Bmtun) _patch_scan_pulse(tunables) _reserves_per_tank(tunables, configuration) -def _patch_scan_pulse(tunables: Bmtun): +def _patch_scan_pulse(tunables: Bmtun) -> None: tunables.raw["classes"]["CTunableAbilityScanningPulse"]["tunables"][ "fConsumptionOnActivation" ]["value"] = 0.0 -def _reserves_per_tank(tunables: Bmtun, configuration: dict): +def _reserves_per_tank(tunables: Bmtun, configuration: dict) -> None: amiibo = tunables.raw["classes"]["Amiibo|CTunableReserveTanks"]["tunables"] amiibo["fLifeTankSize"]["value"] = configuration["life_tank_size"] amiibo["fSETankSize"]["value"] = configuration["aeion_tank_size"] diff --git a/src/open_samus_returns_rando/validator_with_default.py b/src/open_samus_returns_rando/validator_with_default.py index c200cab2..f6701536 100644 --- a/src/open_samus_returns_rando/validator_with_default.py +++ b/src/open_samus_returns_rando/validator_with_default.py @@ -1,10 +1,15 @@ +import typing + from jsonschema import Draft7Validator, validators -def extend_with_default(validator_class): - validate_properties = validator_class.VALIDATORS["properties"] +# FIXME: Types +def extend_with_default(validator_class: typing.Any) -> typing.Any: + validate_properties: typing.Any = validator_class.VALIDATORS["properties"] - def set_defaults(validator, properties, instance, schema): + def set_defaults( + validator: typing.Any, properties: typing.Any, instance:typing.Any, schema:typing.Any + ) -> typing.Any: for property, subschema in properties.items(): if "default" in subschema: instance.setdefault(property, subschema["default"])