diff --git a/worlds/rac3/client/rac3_interface.py b/worlds/rac3/client/rac3_interface.py index b08d180958b6..f9bb5aebcf58 100644 --- a/worlds/rac3/client/rac3_interface.py +++ b/worlds/rac3/client/rac3_interface.py @@ -56,8 +56,7 @@ from worlds.rac3.constants.player_action import PLAYER_ACTION_NAMES, RAC3PLAYERACTION from worlds.rac3.constants.player_type import PLAYER_TYPE_TO_NAME, RAC3PLAYERTYPE from worlds.rac3.constants.progress_flag import HALO_JUMP_TO_REGION, RAC3PROGRESSFLAG -from worlds.rac3.constants.region import (PLANET_LOAD_OFFSET, PLANET_NAME_FROM_ID, PLANET_VENDOR_OFFSET, - PLANETS_WITH_HACKER_PUZZLES, PLANETS_WITH_REFRACTOR_PUZZLES, +from worlds.rac3.constants.region import (PLANET_LOAD_OFFSET, PLANET_NAME_FROM_ID, PLANET_VENDOR_OFFSET, PLANETS_WITH_HACKER_PUZZLES, PLANETS_WITH_REFRACTOR_PUZZLES, PLANETS_WITH_TYHRRANOID_PUZZLES, RAC3REGION, REGION_TO_HACKER_DOOR_COUNT, RESPAWN_COORDS_OFFSET) from worlds.rac3.constants.ship_slot import RAC3SHIPSLOT, SHIP_SLOTS @@ -70,6 +69,7 @@ from worlds.rac3.constants.version import (GAME_ID_TO_OFFSET, GAME_ID_TO_VERSION, PAL_SHIFTED_PLANETS, RAC3VERSION, VERSION_TO_BLACK_SCREEN_ORIGINAL_VALUE, jp_convert_address, jp_get_pause_physical_address, ) +from worlds.rac3.constants.wrench import RAC3WRENCH class Rac3Interface(GameInterface): @@ -97,6 +97,7 @@ class Options: starting_weapons: dict[str, int] bolt_and_xp_multiplier: int progressive_weapons: int + progressive_wrench: int armor_upgrade: int skill_points: int trophies: int @@ -324,6 +325,7 @@ def proc_option(self, slot_data: dict[str, Any]): self.options.starting_weapons = slot_data[RAC3OPTION.STARTING_WEAPONS] self.options.bolt_and_xp_multiplier = slot_data[RAC3OPTION.BOLT_AND_XP_MULTIPLIER] self.options.progressive_weapons = slot_data[RAC3OPTION.PROGRESSIVE_WEAPONS] + self.options.progressive_wrench = slot_data[RAC3OPTION.PROGRESSIVE_WRENCH] self.options.armor_upgrade = slot_data[RAC3OPTION.ARMOR_UPGRADE] self.options.skill_points = slot_data[RAC3OPTION.SKILL_POINTS] self.options.trophies = slot_data[RAC3OPTION.TROPHIES] @@ -925,6 +927,8 @@ def item_received(self, case RAC3ITEM.CLANK: self.UnlockItem[RAC3ITEM.HELI_PACK].status = 1 self.UnlockItem[RAC3ITEM.THRUSTER_PACK].status = 1 + #case RAC3ITEM.PROGRESSIVE_WRENCH: + # pass case RAC3ITEM.TITANIUM_BOLT: pass case RAC3ITEM.BOLTS: @@ -1780,6 +1784,7 @@ def late_update(self): self.gadget_cycler() self.planet_cycler() self.weapon_cycler() + self.wrench_cycler() self.vidcomic_cycler() self.armor_cycler() self.timer_cycler() @@ -1926,8 +1931,6 @@ def weapon_cycler(self): for name in non_prog_weapon_data.keys(): unlock_addr = non_prog_weapon_data[name].UNLOCK_ADDRESS ammo_addr = non_prog_weapon_data[name].AMMO_ADDRESS - xp_addr = non_prog_weapon_data[name].XP_ADDRESS - level_addr = non_prog_weapon_data[name].LEVEL_ADDRESS if self.UnlockItem[name].status: if self.UnlockItem[name].unlock_delay: self._write8(unlock_addr, 1) @@ -1945,8 +1948,6 @@ def weapon_cycler(self): # Prevent the player from using locked weapons and leveling them to accidentally break vendors self._write8(unlock_addr, 0) self._write32(ammo_addr, 0) - self._write32(xp_addr, 0) - self._write8(level_addr, UPGRADE_DICT[name][0]) if self.equipped_item > 1 and self.UnlockItem[ITEM_NAME_FROM_ID[self.equipped_item]].status == 0: if self.last_used_1 == 0: @@ -1967,6 +1968,22 @@ def weapon_cycler(self): else: self.update_weapon_equip(self.last_used_3, self.last_used_3, self.last_used_4, self.last_used_5) + def wrench_cycler(self): + """Cycle through the wrench properties and update its state""" + if self.options.progressive_wrench: + prog_wrench = self.UnlockItem[RAC3ITEM.PROGRESSIVE_WRENCH] + if self.planet != RAC3REGION.MENU and self.between_planets is False: + wrench_instruction = RAC3WRENCH.get_wrench_property_address(self.planet, self.current_game) + RAC3WRENCH.BASE_ITEM_ID_OFFSET + wrench_upgrade = RAC3WRENCH.get_wrench_property_address(self.planet, self.current_game) + RAC3WRENCH.UPGRADE_ID_OFFSET + target_id = UPGRADE_DICT[RAC3ITEM.WRENCH][prog_wrench.status] + if self._read32(wrench_instruction) == 0xA0620009: + for _ in range(6): + self._write8(wrench_upgrade, target_id) + wrench_upgrade += RAC3WRENCH.PER_LEVEL_OFFSET + + else: + return + def update_weapon_equip(self, equip: int | None, last_0: int | None, last_1: int | None, last_2: int | None): """Writes new values to the player's last used item history""" diff --git a/worlds/rac3/constants/data/address.py b/worlds/rac3/constants/data/address.py index 314150423825..ba6603080fb5 100644 --- a/worlds/rac3/constants/data/address.py +++ b/worlds/rac3/constants/data/address.py @@ -27,6 +27,7 @@ def __init__(self, data: tuple[int, CHECKTYPE, int]): RAC3ADDRESSDATA((RAC3STATUS.CRYSTALS_CURRENT, CHECKTYPE.BYTE, 0)), *[RAC3ADDRESSDATA((weapon.AMMO_ADDRESS, CHECKTYPE.INT, weapon.AMMO)) for weapon in non_prog_weapon_data.values()], *[RAC3ADDRESSDATA((weapon.XP_ADDRESS, CHECKTYPE.INT, 0)) for weapon in non_prog_weapon_data.values()], + *[RAC3ADDRESSDATA((weapon.LEVEL_ADDRESS, CHECKTYPE.BYTE, weapon.ID)) for weapon in non_prog_weapon_data.values()], # Stored Fillers RAC3ADDRESSDATA((RAC3STATUS.BOLT_PACKS, CHECKTYPE.INT, 0)), RAC3ADDRESSDATA((RAC3STATUS.NANOTECH_EXP_PACKS, CHECKTYPE.INT, 0)), diff --git a/worlds/rac3/constants/data/item.py b/worlds/rac3/constants/data/item.py index 693eacf10e9c..bdffab97ecf9 100644 --- a/worlds/rac3/constants/data/item.py +++ b/worlds/rac3/constants/data/item.py @@ -166,6 +166,16 @@ def construct_vidcomic(idx: int, else: tags: list[str] = [RAC3ITEMTAG.VIDCOMIC] return RAC3ITEMDATA(idx, address, ap_classification=ItemClassification.progression, tags=tags) + + @staticmethod + def construct_wrench(idx: int, + tag: list[str] | None = None): + """Construct a progressive OmniWrench item""" + if tag: + tags: list[str] = [*tag, RAC3ITEMTAG.PROG_WRENCH] + else: + tags: list[str] = [RAC3ITEMTAG.PROG_WRENCH] + return RAC3ITEMDATA(idx, ap_classification=ItemClassification.progression, tags=tags) @staticmethod def construct_trap(idx: int, @@ -367,8 +377,6 @@ def construct_cheat(idx: int, RAC3ITEM.PLASMA_COIL_V2: RAC3ITEMDATA.construct_weapon_level(0xA0, 3000, 15, 8000), RAC3ITEM.LAVA_GUN_V2: RAC3ITEMDATA.construct_weapon_level(0xA1, 240, 150, 600), RAC3ITEM.MINI_TURRET_V2: RAC3ITEMDATA.construct_weapon_level(0xA2, 800, 10, 400), - RAC3ITEM.WRENCH_V2: RAC3ITEMDATA.construct_unused(0xA4), - RAC3ITEM.WRENCH_V3: RAC3ITEMDATA.construct_unused(0xA5), RAC3ITEM.BOUNCER_V2: RAC3ITEMDATA.construct_weapon_level(0xA6, 1400, 10, 2500), RAC3ITEM.SHIELD_CHARGER_V2: RAC3ITEMDATA.construct_weapon_level(0xA7, 100, 3, 2200), RAC3ITEM.MINI_TURRET_V3: RAC3ITEMDATA.construct_weapon_level(0xA8, 1000, 12, 1000), @@ -401,11 +409,6 @@ def construct_cheat(idx: int, RAC3ITEM.TESLA_BARRIER_V6: RAC3ITEMDATA.construct_weapon_level(0xC3, 300, 4, tags=[RAC3ITEMTAG.NGPLUS]), RAC3ITEM.TESLA_BARRIER_V7: RAC3ITEMDATA.construct_weapon_level(0xC4, 400, 5, 12000, [RAC3ITEMTAG.NGPLUS]), RAC3ITEM.TESLA_BARRIER_V8: RAC3ITEMDATA.construct_weapon_level(0xC5, 500, 5, 30000, [RAC3ITEMTAG.NGPLUS]), - RAC3ITEM.WRENCH_V4: RAC3ITEMDATA.construct_unused(0xC6), - RAC3ITEM.WRENCH_V5: RAC3ITEMDATA.construct_unused(0xC7), - RAC3ITEM.WRENCH_V6: RAC3ITEMDATA.construct_unused(0xC8), - RAC3ITEM.WRENCH_V7: RAC3ITEMDATA.construct_unused(0xC9), - RAC3ITEM.WRENCH_V8: RAC3ITEMDATA.construct_unused(0xCA), # Progressive RAC3ITEM.PROGRESSIVE_PLASMA_COIL: RAC3ITEMDATA.construct_rac2_prog(0xCB, ItemClassification.progression_skip_balancing), RAC3ITEM.PROGRESSIVE_LAVA_GUN: RAC3ITEMDATA.construct_rac2_prog(0xCC, ItemClassification.progression_skip_balancing), @@ -438,6 +441,15 @@ def construct_cheat(idx: int, RAC3ITEMDATA.construct_weapon_prog(0xDD, ItemClassification.progression_skip_balancing), RAC3ITEM.PROGRESSIVE_RY3N0: RAC3ITEMDATA.construct_weapon_prog(0xDE, ItemClassification.progression_skip_balancing, [RAC3ITEMTAG.NGPLUS]), + RAC3ITEM.PROGRESSIVE_WRENCH: + RAC3ITEMDATA.construct_wrench(0xDF, [RAC3ITEMTAG.PROGRESSIVE]), + RAC3ITEM.WRENCH_V2: RAC3ITEMDATA.construct_wrench(0xA4), + RAC3ITEM.WRENCH_V3: RAC3ITEMDATA.construct_wrench(0xA5), + RAC3ITEM.WRENCH_V4: RAC3ITEMDATA.construct_wrench(0xC6), + RAC3ITEM.WRENCH_V5: RAC3ITEMDATA.construct_wrench(0xC7), + RAC3ITEM.WRENCH_V6: RAC3ITEMDATA.construct_wrench(0xC8), + RAC3ITEM.WRENCH_V7: RAC3ITEMDATA.construct_wrench(0xC9), + RAC3ITEM.WRENCH_V8: RAC3ITEMDATA.construct_wrench(0xCA), # Infobots RAC3ITEM.VELDIN: RAC3ITEMDATA.construct_infobot(0xE1, ItemClassification.progression), RAC3ITEM.FLORANA: RAC3ITEMDATA.construct_infobot(0xE2, ItemClassification.progression), @@ -526,6 +538,7 @@ def from_tag(tag: str) -> dict[str, RAC3ITEMDATA]: ngplus_data: dict[str, RAC3ITEMDATA] = from_tag(RAC3ITEMTAG.NGPLUS) non_prog_weapon_data: dict[str, RAC3ITEMDATA] = from_tag(RAC3ITEMTAG.NON_PROG_WEAPON) prog_weapon_data: dict[str, RAC3ITEMDATA] = from_tag(RAC3ITEMTAG.PROG_WEAPON) +prog_wrench_data: dict[str, RAC3ITEMDATA] = from_tag(RAC3ITEMTAG.PROG_WRENCH) progressive_data: dict[str, RAC3ITEMDATA] = from_tag(RAC3ITEMTAG.PROGRESSIVE) trap_data: dict[str, RAC3ITEMDATA] = from_tag(RAC3ITEMTAG.TRAP) unused_data: dict[str, RAC3ITEMDATA] = from_tag(RAC3ITEMTAG.UNUSED) @@ -542,6 +555,7 @@ def from_tag(tag: str) -> dict[str, RAC3ITEMDATA]: item_counts: dict[str, int] = { **dict.fromkeys(non_prog_weapon_data.keys(), 1), **dict.fromkeys(prog_weapon_data.keys(), 5), + **dict.fromkeys(prog_wrench_data.keys(), 5), **dict.fromkeys(gadget_data.keys(), 1), **dict.fromkeys(cheat_data.keys(), 1), RAC3ITEM.CLANK: 1, @@ -555,6 +569,7 @@ def from_tag(tag: str) -> dict[str, RAC3ITEMDATA]: ngplus_item_counts: dict[str, int] = { **dict.fromkeys(non_prog_weapon_data.keys(), 1), **dict.fromkeys(prog_weapon_data.keys(), 8), + **dict.fromkeys(prog_wrench_data.keys(), 8), **dict.fromkeys(gadget_data.keys(), 1), **dict.fromkeys(cheat_data.keys(), 1), RAC3ITEM.CLANK: 1, @@ -599,6 +614,7 @@ def from_tag(tag: str) -> dict[str, RAC3ITEMDATA]: RAC3ITEMTAG.NGPLUS: set(ngplus_data.keys()), RAC3ITEMTAG.NON_PROG_WEAPON: set(non_prog_weapon_data.keys()), RAC3ITEMTAG.PROG_WEAPON: set(prog_weapon_data.keys()), + RAC3ITEMTAG.PROG_WRENCH: set(prog_wrench_data.keys()), RAC3ITEMTAG.PROGRESSIVE: set(progressive_data.keys()), RAC3ITEMTAG.TRAP: set(trap_data.keys()), RAC3ITEMTAG.UNUSED: set(unused_data.keys()), diff --git a/worlds/rac3/constants/function.py b/worlds/rac3/constants/function.py new file mode 100644 index 000000000000..ce67dfb84bbc --- /dev/null +++ b/worlds/rac3/constants/function.py @@ -0,0 +1,983 @@ +"""This module contains the constant base addresses used when reading in game functions""" + +from worlds.rac3.constants.region import RAC3REGION +from worlds.rac3.constants.version import RAC3VERSION + +class RAC3FUNCTION: + """Constant addresses for functions""" + + WRENCH_FUNCTION_BASE_NTSC = 0x004DFB38 + WRENCH_FUNCTION_BASE_PAL = 0x004E3F68 + EQUIP_WRENCH_BASE_NTSC = 0x004BDB58 + EQUIP_WRENCH_BASE_PAL = 0x004C1DA8 + EQUIP_WRENCH_BASE_JP = 0x004C89E0 + SWING_WRENCH_BASE_NTSC = 0x004D38F0 + SWING_WRENCH_BASE_PAL = 0x004D7C78 + CHECK_FLOOR_BASE_NTSC = 0x004C0B40 # Value: A6221470, if A6220000 or NOP'd, nothing is written in the CURRENT_FLOOR address + CHECK_FLOOR_BASE_PAL = 0x004C4D98 + ENEMY_SPEED_BASE_NTSC = 0x00410494 # -0x54 to its function start. Value: 3C043F7F, tampering with 3F7F directly affects the enemies speed + ENEMY_SPEED_BASE_PAL = 0x00413A04 + ENEMY_SPEED_BASE_JP = 0x0041AA54 + RATCHET_SKELETON_BASE_NTSC = 0x004112F0 # -0x90 to its function start. Value: 23010004, tampering with the last byte directly affects Ratchet's moby + RATCHET_SKELETON_BASE_PAL = 0x00414870 + RATCHET_SKELETON_BASE_JP = 0x0041B8B0 + SHIP_KEYS_BASE_NTSC = 0x0047ECB4 # -0x304 to its function start. Value: 3C02001D, +0x4, value: 90425533. + SHIP_KEYS_BASE_PAL = 0x00482B24 # Forms 0x001D5533, which is the Phoenix infobot flag, which is required to enter the ship + PLAYER_STATE_LOCK_BASE_NTSC = 0x004CF420 # -0x68 to its function start. Value: AE1125C4, if AE110000 or NOP'd, player state freezes and can be written over + PLAYER_STATE_LOCK_BASE_PAL = 0x004D3728 + PLAYER_STATE_LOCK_BASE_JP = 0x004DA2E8 + JUMP_FUNCTION_BASE_NTSC = 0x004C2908 # -0x98 to its function start. Value: 1040000E, if NOP'd, Ratchet cannot gain height when jumping + JUMP_FUNCTION_BASE_PAL = 0x004C6B60 + JUMP_FUNCTION_BASE_JP = 0x004CD790 + INVERSE_JUMP_BASE_NTSC = 0x004C2B88 # -0x318 to its function start. Value: 247000F0, if NOP'd, double jumps will pull Ratchet down instead + INVERSE_JUMP_BASE_PAL = 0x004C6DE0 # Same offsets as JUMP_FUNCTION + INVERSE_JUMP_BASE_JP = 0x004CDA10 + TELEPORT_BASE_NTSC = 0x00419970 # +0x14 to TELEPORT_ADDRESS. Value: A0E50020, if NOP'd, player cannot use teleport plataforms + TELEPORT_BASE_PAL = 0x0041CF28 + TELEPORT_BASE_JP = 0x00423F30 + MAGNETISM_BASE_NTSC = 0x004B98CC # -0x114 to its function start. Value: A4820368, if A4820360, magnetism is disabled + MAGNETISM_BASE_PAL = 0x004BDB14 + MAGNETISM_BASE_JP = 0x004C4754 + GRAV_BOOTS_EVERYWHERE_BASE_NTSC = 0x004B9808 # -0x50 to its function start. Value: A6200368, if tampered with, every surface is magnetic + GRAV_BOOTS_EVERYWHERE_BASE_PAL = 0x004BDA50 # theoretically, this could be accomplished with just the CHECK_FLOOR function, but this one is saved + GRAV_BOOTS_EVERYWHERE_BASE_JP = 0x004C4690 # just for reference and future use + + ORIGINAL_CHECK_FLOOR_VALUE = 0xA6221470 + ORIGINAL_ENEMY_SPEED_VALUE = 0x3C043F7F + ORIGINAL_RATCHET_SKELETON_VALUE = 0x23010004 + ORIGINAL_SHIP_KEYS_1_VALUE = 0x3C02001D + ORIGINAL_SHIP_KEYS_2_VALUE = 0x90425533 + ORIGINAL_PLAYER_STATE_LOCK_VALUE = 0xAE1125C4 + ORIGINAL_JUMP_FUNCTION_VALUE = 0x1040000E + ORIGINAL_INVERSE_JUMP_VALUE = 0x247000F0 + ORIGINAL_TELEPORT_VALUE = 0xA0E50020 + ORIGINAL_MAGNETISM_VALUE = 0xA4820368 + ORIGINAL_GRAV_BOOTS_EVERYWHERE_VALUE = 0xA6200368 + + @staticmethod + def get_check_floor_address(planet: str, game_id: str = '') -> int: + """Provides the address that effectively allows or disallows the CURRENT_FLOOR to be overwritten""" + ADDRESS_OFFSET = 0x30C + match game_id: + case RAC3VERSION.US_ID: + addr = RAC3FUNCTION.CHECK_FLOOR_BASE_NTSC + CHECK_FLOOR_OFFSET_NTSC[planet] + ADDRESS_OFFSET + return addr + case RAC3VERSION.EU_ID: + addr = RAC3FUNCTION.CHECK_FLOOR_BASE_PAL + CHECK_FLOOR_OFFSET_PAL[planet] + ADDRESS_OFFSET + return addr + #case RAC3VERSION.JP_ID: + #addr = RAC3FUNCTION.CHECK_FLOOR_BASE_JP + CHECK_FLOOR_OFFSET_JP[planet] + #return addr + case _: + addr = RAC3FUNCTION.CHECK_FLOOR_BASE_NTSC + CHECK_FLOOR_OFFSET_NTSC[planet] + ADDRESS_OFFSET + return addr + + @staticmethod + def get_enemy_speed_address(planet: str, game_id: str = '') -> int: + """Provides the address that effectively affects the enemies speed""" # Most likely causes enemy-related bugs if too fast. Use with caution + match game_id: + case RAC3VERSION.US_ID: + addr = RAC3FUNCTION.ENEMY_SPEED_BASE_NTSC + ENEMY_SPEED_OFFSET_NTSC[planet] + return addr + case RAC3VERSION.EU_ID: + addr = RAC3FUNCTION.ENEMY_SPEED_BASE_PAL + ENEMY_SPEED_OFFSET_PAL[planet] + return addr + case RAC3VERSION.JP_ID: + addr = RAC3FUNCTION.ENEMY_SPEED_BASE_JP + ENEMY_SPEED_OFFSET_JP[planet] + return addr + case _: + addr = RAC3FUNCTION.ENEMY_SPEED_BASE_NTSC + ENEMY_SPEED_OFFSET_NTSC[planet] + return addr + + @staticmethod + def get_ratchet_skeleton_address(planet: str, game_id: str = '') -> int: + """Provides the address that affects Ratchet's moby bones""" + match game_id: + case RAC3VERSION.US_ID: + addr = RAC3FUNCTION.RATCHET_SKELETON_BASE_NTSC + RATCHET_SKELETON_OFFSET_NTSC[planet] + return addr + case RAC3VERSION.EU_ID: + addr = RAC3FUNCTION.RATCHET_SKELETON_BASE_PAL + RATCHET_SKELETON_OFFSET_PAL[planet] + return addr + case RAC3VERSION.JP_ID: + addr = RAC3FUNCTION.RATCHET_SKELETON_BASE_JP + RATCHET_SKELETON_OFFSET_JP[planet] + return addr + case _: + addr = RAC3FUNCTION.RATCHET_SKELETON_BASE_NTSC + RATCHET_SKELETON_OFFSET_NTSC[planet] + return addr + + @staticmethod + def get_ship_keys_address(planet: str, game_id: str = '') -> int: + """Provides the address that can effectively change what allows the player to enter the ship""" + match game_id: + case RAC3VERSION.US_ID: + addr = RAC3FUNCTION.SHIP_KEYS_BASE_NTSC + SHIP_KEYS_OFFSET_NTSC[planet] + return addr + case RAC3VERSION.EU_ID: + addr = RAC3FUNCTION.SHIP_KEYS_BASE_PAL + SHIP_KEYS_OFFSET_PAL[planet] + return addr + #case RAC3VERSION.JP_ID: + #addr = RAC3FUNCTION.SHIP_KEYS_BASE_JP + SHIP_KEYS_OFFSET_JP[planet] + #return addr + case _: + addr = RAC3FUNCTION.SHIP_KEYS_BASE_NTSC + SHIP_KEYS_OFFSET_NTSC[planet] + return addr + + @staticmethod + def get_player_state_lock_address(planet: str, game_id: str = '') -> int: + """Provides the address that effectively unlocks player state to write whatever to it""" # Can cause crashes with untested action states + match game_id: + case RAC3VERSION.US_ID: + addr = RAC3FUNCTION.PLAYER_STATE_LOCK_BASE_NTSC + PLAYER_STATE_LOCK_OFFSET_NTSC[planet] + return addr + case RAC3VERSION.EU_ID: + addr = RAC3FUNCTION.PLAYER_STATE_LOCK_BASE_PAL + PLAYER_STATE_LOCK_OFFSET_PAL[planet] + return addr + case RAC3VERSION.JP_ID: + addr = RAC3FUNCTION.PLAYER_STATE_LOCK_BASE_JP + PLAYER_STATE_LOCK_OFFSET_JP[planet] + return addr + case _: + addr = RAC3FUNCTION.PLAYER_STATE_LOCK_BASE_NTSC + PLAYER_STATE_LOCK_OFFSET_NTSC[planet] + return addr + +WRENCH_FUNCTION_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x2FDE8, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x1D488, + RAC3REGION.MARCADIA: 0x3A348, + RAC3REGION.DAXX: 0x28BB0, + RAC3REGION.PHOENIX_ASSAULT: 0x13758, + RAC3REGION.ANNIHILATION_NATION: 0x2EBA8, + RAC3REGION.AQUATOS: 0x9CE0, + RAC3REGION.TYHRRANOSIS: 0x42CE0, + RAC3REGION.ZELDRIN_STARPORT: 0x12910, + RAC3REGION.OBANI_GEMINI: 0x5E10, + RAC3REGION.BLACKWATER_CITY: 0x313B0, + RAC3REGION.HOLOSTAR_STUDIOS: 0xFA10, + RAC3REGION.KOROS: 0x1A668, + RAC3REGION.METROPOLIS: 0x412F8, + RAC3REGION.CRASH_SITE: 0x9008, + RAC3REGION.ARIDIA: 0x42688, + RAC3REGION.QWARKS_HIDEOUT: 0x21250, + RAC3REGION.COMMAND_CENTER_2: 0x4F830, + RAC3REGION.OBANI_DRACO: 0x6C88, + RAC3REGION.COMMAND_CENTER: 0x36978, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0x13C00, + RAC3REGION.MUSEUM: 0x14BD8, + RAC3REGION.METROPOLIS_RANGERS: 0x38900, + RAC3REGION.AQUATOS_BASE: -0x16E8, + RAC3REGION.AQUATOS_SEWERS: -0x89F8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x3B238 +} +WRENCH_FUNCTION_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x2F990, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x1D418, + RAC3REGION.MARCADIA: 0x3A208, + RAC3REGION.DAXX: 0x28E18, + RAC3REGION.PHOENIX_ASSAULT: 0x130E0, + RAC3REGION.ANNIHILATION_NATION: 0x2E6D0, + RAC3REGION.AQUATOS: 0x9D10, + RAC3REGION.TYHRRANOSIS: 0x42A80, + RAC3REGION.ZELDRIN_STARPORT: 0x12B80, + RAC3REGION.OBANI_GEMINI: 0x5AF8, + RAC3REGION.BLACKWATER_CITY: 0x310D8, + RAC3REGION.HOLOSTAR_STUDIOS: 0xF918, + RAC3REGION.KOROS: 0x1A350, + RAC3REGION.METROPOLIS: 0x41120, + RAC3REGION.CRASH_SITE: 0x8A30, + RAC3REGION.ARIDIA: 0x42770, + RAC3REGION.QWARKS_HIDEOUT: 0x214E0, + RAC3REGION.COMMAND_CENTER_2: 0x4F9D8, + RAC3REGION.OBANI_DRACO: 0x67B0, + RAC3REGION.COMMAND_CENTER: 0x366A8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0x13778, + RAC3REGION.MUSEUM: 0x14800, + RAC3REGION.METROPOLIS_RANGERS: 0x38928, + RAC3REGION.AQUATOS_BASE: -0x1DF0, + RAC3REGION.AQUATOS_SEWERS: -0x8950, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x3B0E0 +} +EQUIP_WRENCH_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x2ACD8, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x182D8, + RAC3REGION.MARCADIA: 0x39BD8, + RAC3REGION.DAXX: 0x23AB8, + RAC3REGION.PHOENIX_ASSAULT: 0xE6B0, + RAC3REGION.ANNIHILATION_NATION: 0x29B00, + RAC3REGION.AQUATOS: 0xBB60, + RAC3REGION.TYHRRANOSIS: 0x43688, + RAC3REGION.ZELDRIN_STARPORT: 0xD818, + RAC3REGION.OBANI_GEMINI: 0xD18, + RAC3REGION.BLACKWATER_CITY: 0x2C2A0, + RAC3REGION.HOLOSTAR_STUDIOS: 0xA918, + RAC3REGION.KOROS: 0x15570, + RAC3REGION.METROPOLIS: 0x3C1E8, + RAC3REGION.CRASH_SITE: 0x3F60, + RAC3REGION.ARIDIA: 0x3D578, + RAC3REGION.QWARKS_HIDEOUT: 0x1EA58, + RAC3REGION.COMMAND_CENTER_2: 0x4A720, + RAC3REGION.OBANI_DRACO: 0x1B90, + RAC3REGION.COMMAND_CENTER: 0x31868, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xCEA8, + RAC3REGION.MUSEUM: 0xFAC8, + RAC3REGION.METROPOLIS_RANGERS: 0x337F0, + RAC3REGION.AQUATOS_BASE: 0x6C0, + RAC3REGION.AQUATOS_SEWERS: -0xDAF0, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x36128 +} +EQUIP_WRENCH_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x2A858, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x18240, + RAC3REGION.MARCADIA: 0x39AA0, + RAC3REGION.DAXX: 0x23CF8, + RAC3REGION.PHOENIX_ASSAULT: 0xE010, + RAC3REGION.ANNIHILATION_NATION: 0x29600, + RAC3REGION.AQUATOS: 0xBBB0, + RAC3REGION.TYHRRANOSIS: 0x43448, + RAC3REGION.ZELDRIN_STARPORT: 0xDA60, + RAC3REGION.OBANI_GEMINI: 0x9D8, + RAC3REGION.BLACKWATER_CITY: 0x2BFA0, + RAC3REGION.HOLOSTAR_STUDIOS: 0xA7F8, + RAC3REGION.KOROS: 0x15230, + RAC3REGION.METROPOLIS: 0x3BFE8, + RAC3REGION.CRASH_SITE: 0x3960, + RAC3REGION.ARIDIA: 0x3D638, + RAC3REGION.QWARKS_HIDEOUT: 0x1ED10, + RAC3REGION.COMMAND_CENTER_2: 0x4A8A0, + RAC3REGION.OBANI_DRACO: 0x1690, + RAC3REGION.COMMAND_CENTER: 0x31570, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xC9F0, + RAC3REGION.MUSEUM: 0xF6C8, + RAC3REGION.METROPOLIS_RANGERS: 0x337F0, + RAC3REGION.AQUATOS_BASE: -0x30, + RAC3REGION.AQUATOS_SEWERS: -0xDA70, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x35FA8 +} +EQUIP_WRENCH_OFFSET_JP: dict[str, int] = { + RAC3REGION.VELDIN: 0x2AC40, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x18240, + RAC3REGION.MARCADIA: 0x39B40, + RAC3REGION.DAXX: 0x23AB8, + RAC3REGION.PHOENIX_ASSAULT: 0xE670, + RAC3REGION.ANNIHILATION_NATION: 0x29A28, + RAC3REGION.AQUATOS: 0xBC20, + RAC3REGION.TYHRRANOSIS: 0x43270, + RAC3REGION.ZELDRIN_STARPORT: 0xD918, + RAC3REGION.OBANI_GEMINI: 0xD58, + RAC3REGION.BLACKWATER_CITY: 0x2C248, + RAC3REGION.HOLOSTAR_STUDIOS: 0xAA58, + RAC3REGION.KOROS: 0x155F0, + RAC3REGION.METROPOLIS: 0x3C150, + RAC3REGION.CRASH_SITE: 0x3FA0, + RAC3REGION.ARIDIA: 0x3D5A0, + RAC3REGION.QWARKS_HIDEOUT: 0x1EB58, + RAC3REGION.COMMAND_CENTER_2: 0x4A6C8, + RAC3REGION.OBANI_DRACO: 0x1BD0, + RAC3REGION.COMMAND_CENTER: 0x31890, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xCE68, + RAC3REGION.MUSEUM: 0xFB48, + RAC3REGION.METROPOLIS_RANGERS: 0x33758, + RAC3REGION.AQUATOS_BASE: 0x780, + RAC3REGION.AQUATOS_SEWERS: -0xDA70, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x36150 +} +SWING_WRENCH_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x2DD88, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x1B388, + RAC3REGION.MARCADIA: 0x39820, + RAC3REGION.DAXX: 0x26B68, + RAC3REGION.PHOENIX_ASSAULT: 0x11760, + RAC3REGION.ANNIHILATION_NATION: 0x2CBB0, + RAC3REGION.AQUATOS: 0x96D8, + RAC3REGION.TYHRRANOSIS: 0x42DD8, + RAC3REGION.ZELDRIN_STARPORT: 0x108C8, + RAC3REGION.OBANI_GEMINI: 0x3DC8, + RAC3REGION.BLACKWATER_CITY: 0x2F350, + RAC3REGION.HOLOSTAR_STUDIOS: 0xD9C8, + RAC3REGION.KOROS: 0x18620, + RAC3REGION.METROPOLIS: 0x3F298, + RAC3REGION.CRASH_SITE: 0x7010, + RAC3REGION.ARIDIA: 0x40628, + RAC3REGION.QWARKS_HIDEOUT: 0x1F928, + RAC3REGION.COMMAND_CENTER_2: 0x4D7D0, + RAC3REGION.OBANI_DRACO: 0x4C40, + RAC3REGION.COMMAND_CENTER: 0x34918, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0x11120, + RAC3REGION.MUSEUM: 0x12B78, + RAC3REGION.METROPOLIS_RANGERS: 0x368A0, + RAC3REGION.AQUATOS_BASE: -0x1BD8, + RAC3REGION.AQUATOS_SEWERS: -0xAA40, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x391D8 +} +SWING_WRENCH_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x2D928, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x1B310, + RAC3REGION.MARCADIA: 0x396E8, + RAC3REGION.DAXX: 0x26DC8, + RAC3REGION.PHOENIX_ASSAULT: 0x110E0, + RAC3REGION.ANNIHILATION_NATION: 0x2C6D0, + RAC3REGION.AQUATOS: 0x9710, + RAC3REGION.TYHRRANOSIS: 0x42B80, + RAC3REGION.ZELDRIN_STARPORT: 0x10B30, + RAC3REGION.OBANI_GEMINI: 0x3AA8, + RAC3REGION.BLACKWATER_CITY: 0x2F070, + RAC3REGION.HOLOSTAR_STUDIOS: 0xD8C8, + RAC3REGION.KOROS: 0x18300, + RAC3REGION.METROPOLIS: 0x3F0B8, + RAC3REGION.CRASH_SITE: 0x6A30, + RAC3REGION.ARIDIA: 0x40708, + RAC3REGION.QWARKS_HIDEOUT: 0x1FBB0, + RAC3REGION.COMMAND_CENTER_2: 0x4D970, + RAC3REGION.OBANI_DRACO: 0x4760, + RAC3REGION.COMMAND_CENTER: 0x34640, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0x10C90, + RAC3REGION.MUSEUM: 0x12798, + RAC3REGION.METROPOLIS_RANGERS: 0x368C0, + RAC3REGION.AQUATOS_BASE: -0x22D8, + RAC3REGION.AQUATOS_SEWERS: -0xA9A0, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x39078 +} +CHECK_FLOOR_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x2AF28, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x18528, + RAC3REGION.MARCADIA: 0x39D80, + RAC3REGION.DAXX: 0x23D08, + RAC3REGION.PHOENIX_ASSAULT: 0xE900, + RAC3REGION.ANNIHILATION_NATION: 0x29D50, + RAC3REGION.AQUATOS: 0xBD58, + RAC3REGION.TYHRRANOSIS: 0x43688, + RAC3REGION.ZELDRIN_STARPORT: 0xDA68, + RAC3REGION.OBANI_GEMINI: 0xF68, + RAC3REGION.BLACKWATER_CITY: 0x2C4F0, + RAC3REGION.HOLOSTAR_STUDIOS: 0xAB68, + RAC3REGION.KOROS: 0x157C0, + RAC3REGION.METROPOLIS: 0x3C438, + RAC3REGION.CRASH_SITE: 0x41B0, + RAC3REGION.ARIDIA: 0x3D7C8, + RAC3REGION.QWARKS_HIDEOUT: 0x1EC68, + RAC3REGION.COMMAND_CENTER_2: 0x4A970, + RAC3REGION.OBANI_DRACO: 0x1DE0, + RAC3REGION.COMMAND_CENTER: 0x31AB8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xD250, + RAC3REGION.MUSEUM: 0xFD18, + RAC3REGION.METROPOLIS_RANGERS: 0x33A40, + RAC3REGION.AQUATOS_BASE: 0x868, + RAC3REGION.AQUATOS_SEWERS: -0xD8A0, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x36378 +} +CHECK_FLOOR_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x2AAA8, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x18490, + RAC3REGION.MARCADIA: 0x39C48, + RAC3REGION.DAXX: 0x23F48, + RAC3REGION.PHOENIX_ASSAULT: 0xE260, + RAC3REGION.ANNIHILATION_NATION: 0x29850, + RAC3REGION.AQUATOS: 0xBDA8, + RAC3REGION.TYHRRANOSIS: 0x43448, + RAC3REGION.ZELDRIN_STARPORT: 0xDCB0, + RAC3REGION.OBANI_GEMINI: 0xC28, + RAC3REGION.BLACKWATER_CITY: 0x2C1F0, + RAC3REGION.HOLOSTAR_STUDIOS: 0xAA48, + RAC3REGION.KOROS: 0x15480, + RAC3REGION.METROPOLIS: 0x3C238, + RAC3REGION.CRASH_SITE: 0x3BB0, + RAC3REGION.ARIDIA: 0x3D888, + RAC3REGION.QWARKS_HIDEOUT: 0x1EF20, + RAC3REGION.COMMAND_CENTER_2: 0x4AAF0, + RAC3REGION.OBANI_DRACO: 0x18E0, + RAC3REGION.COMMAND_CENTER: 0x317C0, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xCD98, + RAC3REGION.MUSEUM: 0xF918, + RAC3REGION.METROPOLIS_RANGERS: 0x33A40, + RAC3REGION.AQUATOS_BASE: 0x178, + RAC3REGION.AQUATOS_SEWERS: -0xD820, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x361F8 +} +ENEMY_SPEED_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x28598, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x158C8, + RAC3REGION.MARCADIA: 0x379B8, + RAC3REGION.DAXX: 0x21188, + RAC3REGION.PHOENIX_ASSAULT: 0xB908, + RAC3REGION.ANNIHILATION_NATION: 0x28B08, + RAC3REGION.AQUATOS: 0xAA88, + RAC3REGION.TYHRRANOSIS: 0x41AF0, + RAC3REGION.ZELDRIN_STARPORT: 0xB388, + RAC3REGION.OBANI_GEMINI: 0x688, + RAC3REGION.BLACKWATER_CITY: 0x296B8, + RAC3REGION.HOLOSTAR_STUDIOS: 0x8A08, + RAC3REGION.KOROS: 0x12DC8, + RAC3REGION.METROPOLIS: 0x38D78, + RAC3REGION.CRASH_SITE: 0x31C8, + RAC3REGION.ARIDIA: 0x3A688, + RAC3REGION.QWARKS_HIDEOUT: 0x1C408, + RAC3REGION.COMMAND_CENTER_2: 0x47A48, + RAC3REGION.OBANI_DRACO: 0x15C8, + RAC3REGION.COMMAND_CENTER: 0x2D6F8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xB288, + RAC3REGION.MUSEUM: 0xEF98, + RAC3REGION.METROPOLIS_RANGERS: 0x30C08, + RAC3REGION.AQUATOS_BASE: 0xA48, + RAC3REGION.AQUATOS_SEWERS: -0xD478, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x33688 +} +ENEMY_SPEED_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x28118, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x157C8, + RAC3REGION.MARCADIA: 0x37878, + RAC3REGION.DAXX: 0x213C8, + RAC3REGION.PHOENIX_ASSAULT: 0xB248, + RAC3REGION.ANNIHILATION_NATION: 0x28608, + RAC3REGION.AQUATOS: 0xAA88, + RAC3REGION.TYHRRANOSIS: 0x418B0, + RAC3REGION.ZELDRIN_STARPORT: 0xB588, + RAC3REGION.OBANI_GEMINI: 0x348, + RAC3REGION.BLACKWATER_CITY: 0x293B8, + RAC3REGION.HOLOSTAR_STUDIOS: 0x88C8, + RAC3REGION.KOROS: 0x12A88, + RAC3REGION.METROPOLIS: 0x38B78, + RAC3REGION.CRASH_SITE: 0x2BC8, + RAC3REGION.ARIDIA: 0x3A748, + RAC3REGION.QWARKS_HIDEOUT: 0x1C648, + RAC3REGION.COMMAND_CENTER_2: 0x47BC8, + RAC3REGION.OBANI_DRACO: 0x10C8, + RAC3REGION.COMMAND_CENTER: 0x2D3B8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xADC8, + RAC3REGION.MUSEUM: 0xEB98, + RAC3REGION.METROPOLIS_RANGERS: 0x30C08, + RAC3REGION.AQUATOS_BASE: 0x308, + RAC3REGION.AQUATOS_SEWERS: -0xD3F8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x33508 +} +ENEMY_SPEED_OFFSET_JP: dict[str, int] = { + RAC3REGION.VELDIN: 0x284D8, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x15808, + RAC3REGION.MARCADIA: 0x378F8, + RAC3REGION.DAXX: 0x21188, + RAC3REGION.PHOENIX_ASSAULT: 0xB8C8, + RAC3REGION.ANNIHILATION_NATION: 0x28A08, + RAC3REGION.AQUATOS: 0xAB48, + RAC3REGION.TYHRRANOSIS: 0x416B0, + RAC3REGION.ZELDRIN_STARPORT: 0xB488, + RAC3REGION.OBANI_GEMINI: 0x6C8, + RAC3REGION.BLACKWATER_CITY: 0x29638, + RAC3REGION.HOLOSTAR_STUDIOS: 0x8B48, + RAC3REGION.KOROS: 0x12E48, + RAC3REGION.METROPOLIS: 0x38CB8, + RAC3REGION.CRASH_SITE: 0x3208, + RAC3REGION.ARIDIA: 0x3A688, + RAC3REGION.QWARKS_HIDEOUT: 0x1C508, + RAC3REGION.COMMAND_CENTER_2: 0x479C8, + RAC3REGION.OBANI_DRACO: 0x1608, + RAC3REGION.COMMAND_CENTER: 0x2D6F8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xB248, + RAC3REGION.MUSEUM: 0xF018, + RAC3REGION.METROPOLIS_RANGERS: 0x30B48, + RAC3REGION.AQUATOS_BASE: 0xB08, + RAC3REGION.AQUATOS_SEWERS: -0xD3F8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x33688 +} +RATCHET_SKELETON_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x28598, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x158C8, + RAC3REGION.MARCADIA: 0x379B8, + RAC3REGION.DAXX: 0x21188, + RAC3REGION.PHOENIX_ASSAULT: 0xB908, + RAC3REGION.ANNIHILATION_NATION: 0x28B08, + RAC3REGION.AQUATOS: 0xAA48, + RAC3REGION.TYHRRANOSIS: 0x41AF0, + RAC3REGION.ZELDRIN_STARPORT: 0xB388, + RAC3REGION.OBANI_GEMINI: 0x688, + RAC3REGION.BLACKWATER_CITY: 0x296B8, + RAC3REGION.HOLOSTAR_STUDIOS: 0x8A08, + RAC3REGION.KOROS: 0x12DC8, + RAC3REGION.METROPOLIS: 0x38D78, + RAC3REGION.CRASH_SITE: 0x31C8, + RAC3REGION.ARIDIA: 0x3A688, + RAC3REGION.QWARKS_HIDEOUT: 0x1C408, + RAC3REGION.COMMAND_CENTER_2: 0x47A48, + RAC3REGION.OBANI_DRACO: 0x15C8, + RAC3REGION.COMMAND_CENTER: 0x2D6F8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xB288, + RAC3REGION.MUSEUM: 0xEF98, + RAC3REGION.METROPOLIS_RANGERS: 0x30C08, + RAC3REGION.AQUATOS_BASE: 0xA48, + RAC3REGION.AQUATOS_SEWERS: -0xD478, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x33688 +} +RATCHET_SKELETON_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x28118, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x157C8, + RAC3REGION.MARCADIA: 0x37878, + RAC3REGION.DAXX: 0x213C8, + RAC3REGION.PHOENIX_ASSAULT: 0xB248, + RAC3REGION.ANNIHILATION_NATION: 0x28608, + RAC3REGION.AQUATOS: 0xAA88, + RAC3REGION.TYHRRANOSIS: 0x418B0, + RAC3REGION.ZELDRIN_STARPORT: 0xB588, + RAC3REGION.OBANI_GEMINI: 0x348, + RAC3REGION.BLACKWATER_CITY: 0x293B8, + RAC3REGION.HOLOSTAR_STUDIOS: 0x88C8, + RAC3REGION.KOROS: 0x12A88, + RAC3REGION.METROPOLIS: 0x38B78, + RAC3REGION.CRASH_SITE: 0x2BC8, + RAC3REGION.ARIDIA: 0x3A748, + RAC3REGION.QWARKS_HIDEOUT: 0x1C648, + RAC3REGION.COMMAND_CENTER_2: 0x47BC8, + RAC3REGION.OBANI_DRACO: 0x10C8, + RAC3REGION.COMMAND_CENTER: 0x2D3B8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xADC8, + RAC3REGION.MUSEUM: 0xEB98, + RAC3REGION.METROPOLIS_RANGERS: 0x30C08, + RAC3REGION.AQUATOS_BASE: 0x308, + RAC3REGION.AQUATOS_SEWERS: -0xD3F8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x33508 +} +RATCHET_SKELETON_OFFSET_JP: dict[str, int] = { + RAC3REGION.VELDIN: 0x284D8, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x15808, + RAC3REGION.MARCADIA: 0x378F8, + RAC3REGION.DAXX: 0x21188, + RAC3REGION.PHOENIX_ASSAULT: 0xB8C8, + RAC3REGION.ANNIHILATION_NATION: 0x28A08, + RAC3REGION.AQUATOS: 0xAB48, + RAC3REGION.TYHRRANOSIS: 0x416B0, + RAC3REGION.ZELDRIN_STARPORT: 0xB488, + RAC3REGION.OBANI_GEMINI: 0x6C8, + RAC3REGION.BLACKWATER_CITY: 0x29638, + RAC3REGION.HOLOSTAR_STUDIOS: 0x8B48, + RAC3REGION.KOROS: 0x12E48, + RAC3REGION.METROPOLIS: 0x38CB8, + RAC3REGION.CRASH_SITE: 0x3208, + RAC3REGION.ARIDIA: 0x3A688, + RAC3REGION.QWARKS_HIDEOUT: 0x1C508, + RAC3REGION.COMMAND_CENTER_2: 0x479C8, + RAC3REGION.OBANI_DRACO: 0x1608, + RAC3REGION.COMMAND_CENTER: 0x2D6F8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xB248, + RAC3REGION.MUSEUM: 0xF018, + RAC3REGION.METROPOLIS_RANGERS: 0x30B48, + RAC3REGION.AQUATOS_BASE: 0xB08, + RAC3REGION.AQUATOS_SEWERS: -0xD3F8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x33688 +} +SHIP_KEYS_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x29E20, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x17498, + RAC3REGION.MARCADIA: 0x39920, + RAC3REGION.DAXX: 0x22BA0, + RAC3REGION.PHOENIX_ASSAULT: 0xD640, + RAC3REGION.ANNIHILATION_NATION: 0x28C58, + RAC3REGION.AQUATOS: 0xBD18, + RAC3REGION.TYHRRANOSIS: 0x43A10, + RAC3REGION.ZELDRIN_STARPORT: 0xC8F0, + RAC3REGION.OBANI_GEMINI: -0x190, + RAC3REGION.BLACKWATER_CITY: 0x2B188, + RAC3REGION.HOLOSTAR_STUDIOS: 0x9B78, + RAC3REGION.KOROS: 0x145F8, + RAC3REGION.METROPOLIS: 0x3B250, + RAC3REGION.CRASH_SITE: 0x3290, + RAC3REGION.ARIDIA: 0x3C558, + RAC3REGION.QWARKS_HIDEOUT: 0x1E408, + RAC3REGION.COMMAND_CENTER_2: 0x49868, + RAC3REGION.OBANI_DRACO: 0xCE8, + RAC3REGION.COMMAND_CENTER: 0x307E8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xB788, + RAC3REGION.MUSEUM: 0xEEF0, + RAC3REGION.METROPOLIS_RANGERS: 0x327D0, + RAC3REGION.AQUATOS_BASE: 0x5C0, + RAC3REGION.AQUATOS_SEWERS: -0xE8A0, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x351A0 +} +SHIP_KEYS_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x299A0, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x17400, + RAC3REGION.MARCADIA: 0x397E0, + RAC3REGION.DAXX: 0x22DE0, + RAC3REGION.PHOENIX_ASSAULT: 0xCFA0, + RAC3REGION.ANNIHILATION_NATION: 0x28758, + RAC3REGION.AQUATOS: 0xBD60, + RAC3REGION.TYHRRANOSIS: 0x437D0, + RAC3REGION.ZELDRIN_STARPORT: 0xCB38, + RAC3REGION.OBANI_GEMINI: -0x4D0, + RAC3REGION.BLACKWATER_CITY: 0x2AE88, + RAC3REGION.HOLOSTAR_STUDIOS: 0x9A58, + RAC3REGION.KOROS: 0x142B8, + RAC3REGION.METROPOLIS: 0x3B050, + RAC3REGION.CRASH_SITE: 0x2C90, + RAC3REGION.ARIDIA: 0x3C618, + RAC3REGION.QWARKS_HIDEOUT: 0x1E6C0, + RAC3REGION.COMMAND_CENTER_2: 0x499E8, + RAC3REGION.OBANI_DRACO: 0x7E8, + RAC3REGION.COMMAND_CENTER: 0x304F0, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xB2D8, + RAC3REGION.MUSEUM: 0xEAF0, + RAC3REGION.METROPOLIS_RANGERS: 0x327D0, + RAC3REGION.AQUATOS_BASE: -0x138, + RAC3REGION.AQUATOS_SEWERS: -0xE820, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x35020 +} +PLAYER_STATE_LOCK_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x2D160, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x1A760, + RAC3REGION.MARCADIA: 0x39598, + RAC3REGION.DAXX: 0x25F40, + RAC3REGION.PHOENIX_ASSAULT: 0x10B38, + RAC3REGION.ANNIHILATION_NATION: 0x2BF88, + RAC3REGION.AQUATOS: 0x99C0, + RAC3REGION.TYHRRANOSIS: 0x43050, + RAC3REGION.ZELDRIN_STARPORT: 0xFCA0, + RAC3REGION.OBANI_GEMINI: 0x31A0, + RAC3REGION.BLACKWATER_CITY: 0x2E728, + RAC3REGION.HOLOSTAR_STUDIOS: 0xCDA0, + RAC3REGION.KOROS: 0x179F8, + RAC3REGION.METROPOLIS: 0x3E670, + RAC3REGION.CRASH_SITE: 0x63E8, + RAC3REGION.ARIDIA: 0x3FA00, + RAC3REGION.QWARKS_HIDEOUT: 0x1F928, + RAC3REGION.COMMAND_CENTER_2: 0x4CBA8, + RAC3REGION.OBANI_DRACO: 0x4018, + RAC3REGION.COMMAND_CENTER: 0x33CF0, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0x101F0, + RAC3REGION.MUSEUM: 0x11F50, + RAC3REGION.METROPOLIS_RANGERS: 0x35C78, + RAC3REGION.AQUATOS_BASE: -0x1A60, + RAC3REGION.AQUATOS_SEWERS: -0xB668, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x385B0 +} +PLAYER_STATE_LOCK_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x2CD10, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x1A6F8, + RAC3REGION.MARCADIA: 0x39468, + RAC3REGION.DAXX: 0x261B0, + RAC3REGION.PHOENIX_ASSAULT: 0x104C8, + RAC3REGION.ANNIHILATION_NATION: 0x2BAB8, + RAC3REGION.AQUATOS: 0x9A00, + RAC3REGION.TYHRRANOSIS: 0x42E00, + RAC3REGION.ZELDRIN_STARPORT: 0xFF18, + RAC3REGION.OBANI_GEMINI: 0x2E90, + RAC3REGION.BLACKWATER_CITY: 0x2E458, + RAC3REGION.HOLOSTAR_STUDIOS: 0xCCB0, + RAC3REGION.KOROS: 0x176E8, + RAC3REGION.METROPOLIS: 0x3E4A0, + RAC3REGION.CRASH_SITE: 0x5E18, + RAC3REGION.ARIDIA: 0x3FAF0, + RAC3REGION.QWARKS_HIDEOUT: 0x1FBE0, + RAC3REGION.COMMAND_CENTER_2: 0x4CD58, + RAC3REGION.OBANI_DRACO: 0x3B48, + RAC3REGION.COMMAND_CENTER: 0x33A28, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xFD68, + RAC3REGION.MUSEUM: 0x11B80, + RAC3REGION.METROPOLIS_RANGERS: 0x35CA8, + RAC3REGION.AQUATOS_BASE: -0x2158, + RAC3REGION.AQUATOS_SEWERS: -0xB5B8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x38460 +} +PLAYER_STATE_LOCK_OFFSET_JP: dict[str, int] = { + RAC3REGION.VELDIN: 0x2D0C8, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x1A6C8, + RAC3REGION.MARCADIA: 0x39500, + RAC3REGION.DAXX: 0x25F40, + RAC3REGION.PHOENIX_ASSAULT: 0x10AF8, + RAC3REGION.ANNIHILATION_NATION: 0x2BEB0, + RAC3REGION.AQUATOS: 0x9A80, + RAC3REGION.TYHRRANOSIS: 0x42C38, + RAC3REGION.ZELDRIN_STARPORT: 0xFDA0, + RAC3REGION.OBANI_GEMINI: 0x31E0, + RAC3REGION.BLACKWATER_CITY: 0x2E6D0, + RAC3REGION.HOLOSTAR_STUDIOS: 0xCEE0, + RAC3REGION.KOROS: 0x17A78, + RAC3REGION.METROPOLIS: 0x3E5D8, + RAC3REGION.CRASH_SITE: 0x6428, + RAC3REGION.ARIDIA: 0x3FA28, + RAC3REGION.QWARKS_HIDEOUT: 0x1FA28, + RAC3REGION.COMMAND_CENTER_2: 0x4CB50, + RAC3REGION.OBANI_DRACO: 0x4058, + RAC3REGION.COMMAND_CENTER: 0x33D18, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0x101B0, + RAC3REGION.MUSEUM: 0x11FD0, + RAC3REGION.METROPOLIS_RANGERS: 0x35BE0, + RAC3REGION.AQUATOS_BASE: -0x19A0, + RAC3REGION.AQUATOS_SEWERS: -0xB5E8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x385D8 +} +JUMP_FUNCTION_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x2AFF0, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x185F0, + RAC3REGION.MARCADIA: 0x39D18, + RAC3REGION.DAXX: 0x23DD0, + RAC3REGION.PHOENIX_ASSAULT: 0xE9C8, + RAC3REGION.ANNIHILATION_NATION: 0x29E18, + RAC3REGION.AQUATOS: 0xBC60, + RAC3REGION.TYHRRANOSIS: 0x43670, + RAC3REGION.ZELDRIN_STARPORT: 0xDB30, + RAC3REGION.OBANI_GEMINI: 0x1030, + RAC3REGION.BLACKWATER_CITY: 0x2C5B8, + RAC3REGION.HOLOSTAR_STUDIOS: 0xAC30, + RAC3REGION.KOROS: 0x15888, + RAC3REGION.METROPOLIS: 0x3C500, + RAC3REGION.CRASH_SITE: 0x4278, + RAC3REGION.ARIDIA: 0x3D890, + RAC3REGION.QWARKS_HIDEOUT: 0x1ECA0, + RAC3REGION.COMMAND_CENTER_2: 0x4AA38, + RAC3REGION.OBANI_DRACO: 0x1EA8, + RAC3REGION.COMMAND_CENTER: 0x31B80, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xD318, + RAC3REGION.MUSEUM: 0xFDE0, + RAC3REGION.METROPOLIS_RANGERS: 0x33B08, + RAC3REGION.AQUATOS_BASE: 0x7E8, + RAC3REGION.AQUATOS_SEWERS: -0xD7D8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x36440 +} +JUMP_FUNCTION_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x2AB70, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x18558, + RAC3REGION.MARCADIA: 0x39BE0, + RAC3REGION.DAXX: 0x24010, + RAC3REGION.PHOENIX_ASSAULT: 0xE328, + RAC3REGION.ANNIHILATION_NATION: 0x29918, + RAC3REGION.AQUATOS: 0xBCB0, + RAC3REGION.TYHRRANOSIS: 0x43430, + RAC3REGION.ZELDRIN_STARPORT: 0xDD78, + RAC3REGION.OBANI_GEMINI: 0xCF0, + RAC3REGION.BLACKWATER_CITY: 0x2C2B8, + RAC3REGION.HOLOSTAR_STUDIOS: 0xAB10, + RAC3REGION.KOROS: 0x15548, + RAC3REGION.METROPOLIS: 0x3C300, + RAC3REGION.CRASH_SITE: 0x3C78, + RAC3REGION.ARIDIA: 0x3D950, + RAC3REGION.QWARKS_HIDEOUT: 0x1EF58, + RAC3REGION.COMMAND_CENTER_2: 0x4ABB8, + RAC3REGION.OBANI_DRACO: 0x19A8, + RAC3REGION.COMMAND_CENTER: 0x31888, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xCE60, + RAC3REGION.MUSEUM: 0xF9E0, + RAC3REGION.METROPOLIS_RANGERS: 0x33B08, + RAC3REGION.AQUATOS_BASE: 0xF8, + RAC3REGION.AQUATOS_SEWERS: -0xD758, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x362C0 +} +JUMP_FUNCTION_OFFSET_JP: dict[str, int] = { + RAC3REGION.VELDIN: 0x2AF58, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x18558, + RAC3REGION.MARCADIA: 0x39C80, + RAC3REGION.DAXX: 0x23DD0, + RAC3REGION.PHOENIX_ASSAULT: 0xE988, + RAC3REGION.ANNIHILATION_NATION: 0x29D40, + RAC3REGION.AQUATOS: 0xBD20, + RAC3REGION.TYHRRANOSIS: 0x43258, + RAC3REGION.ZELDRIN_STARPORT: 0xDC30, + RAC3REGION.OBANI_GEMINI: 0x1070, + RAC3REGION.BLACKWATER_CITY: 0x2C560, + RAC3REGION.HOLOSTAR_STUDIOS: 0xAD70, + RAC3REGION.KOROS: 0x15908, + RAC3REGION.METROPOLIS: 0x3C468, + RAC3REGION.CRASH_SITE: 0x42B8, + RAC3REGION.ARIDIA: 0x3D8B8, + RAC3REGION.QWARKS_HIDEOUT: 0x1EDA0, + RAC3REGION.COMMAND_CENTER_2: 0x4A9E0, + RAC3REGION.OBANI_DRACO: 0x1EE8, + RAC3REGION.COMMAND_CENTER: 0x31BA8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xD2D8, + RAC3REGION.MUSEUM: 0xFE60, + RAC3REGION.METROPOLIS_RANGERS: 0x33A70, + RAC3REGION.AQUATOS_BASE: 0x8A8, + RAC3REGION.AQUATOS_SEWERS: -0xD758, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x36468 +} +TELEPORT_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x28648, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x158C8, + RAC3REGION.MARCADIA: 0x37A68, + RAC3REGION.DAXX: 0x21188, + RAC3REGION.PHOENIX_ASSAULT: 0xB908, + RAC3REGION.ANNIHILATION_NATION: 0x28BB8, + RAC3REGION.AQUATOS: 0xAA88, + RAC3REGION.TYHRRANOSIS: 0x41BA0, + RAC3REGION.ZELDRIN_STARPORT: 0xB388, + RAC3REGION.OBANI_GEMINI: 0x688, + RAC3REGION.BLACKWATER_CITY: 0x29768, + RAC3REGION.HOLOSTAR_STUDIOS: 0x8AB8, + RAC3REGION.KOROS: 0x12DC8, + RAC3REGION.METROPOLIS: 0x38E28, + RAC3REGION.CRASH_SITE: 0x31C8, + RAC3REGION.ARIDIA: 0x3A738, + RAC3REGION.QWARKS_HIDEOUT: 0x1C408, + RAC3REGION.COMMAND_CENTER_2: 0x47A48, + RAC3REGION.OBANI_DRACO: 0x15C8, + RAC3REGION.COMMAND_CENTER: 0x2D7A8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xB288, + RAC3REGION.MUSEUM: 0xEF98, + RAC3REGION.METROPOLIS_RANGERS: 0x30CB8, + RAC3REGION.AQUATOS_BASE: 0xAF8, + RAC3REGION.AQUATOS_SEWERS: -0xD478, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x33738 +} +TELEPORT_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x281C8, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x157C8, + RAC3REGION.MARCADIA: 0x37928, + RAC3REGION.DAXX: 0x213C8, + RAC3REGION.PHOENIX_ASSAULT: 0xB248, + RAC3REGION.ANNIHILATION_NATION: 0x286B8, + RAC3REGION.AQUATOS: 0xAA88, + RAC3REGION.TYHRRANOSIS: 0x41960, + RAC3REGION.ZELDRIN_STARPORT: 0xB588, + RAC3REGION.OBANI_GEMINI: 0x348, + RAC3REGION.BLACKWATER_CITY: 0x29468, + RAC3REGION.HOLOSTAR_STUDIOS: 0x8978, + RAC3REGION.KOROS: 0x12A88, + RAC3REGION.METROPOLIS: 0x38C28, + RAC3REGION.CRASH_SITE: 0x2BC8, + RAC3REGION.ARIDIA: 0x3A7F8, + RAC3REGION.QWARKS_HIDEOUT: 0x1C648, + RAC3REGION.COMMAND_CENTER_2: 0x47BC8, + RAC3REGION.OBANI_DRACO: 0x10C8, + RAC3REGION.COMMAND_CENTER: 0x2D468, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xADC8, + RAC3REGION.MUSEUM: 0xEB98, + RAC3REGION.METROPOLIS_RANGERS: 0x30CB8, + RAC3REGION.AQUATOS_BASE: 0x3B8, + RAC3REGION.AQUATOS_SEWERS: -0xD3F8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x335B8 +} +TELEPORT_OFFSET_JP: dict[str, int] = { + RAC3REGION.VELDIN: 0x28588, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x15808, + RAC3REGION.MARCADIA: 0x379A8, + RAC3REGION.DAXX: 0x21188, + RAC3REGION.PHOENIX_ASSAULT: 0xB8C8, + RAC3REGION.ANNIHILATION_NATION: 0x28AB8, + RAC3REGION.AQUATOS: 0xAB48, + RAC3REGION.TYHRRANOSIS: 0x41760, + RAC3REGION.ZELDRIN_STARPORT: 0xB488, + RAC3REGION.OBANI_GEMINI: 0x6C8, + RAC3REGION.BLACKWATER_CITY: 0x296E8, + RAC3REGION.HOLOSTAR_STUDIOS: 0x8BF8, + RAC3REGION.KOROS: 0x12E48, + RAC3REGION.METROPOLIS: 0x38D68, + RAC3REGION.CRASH_SITE: 0x3208, + RAC3REGION.ARIDIA: 0x3A738, + RAC3REGION.QWARKS_HIDEOUT: 0x1C508, + RAC3REGION.COMMAND_CENTER_2: 0x479C8, + RAC3REGION.OBANI_DRACO: 0x1608, + RAC3REGION.COMMAND_CENTER: 0x2D7A8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xB248, + RAC3REGION.MUSEUM: 0xF018, + RAC3REGION.METROPOLIS_RANGERS: 0x30BF8, + RAC3REGION.AQUATOS_BASE: 0xBB8, + RAC3REGION.AQUATOS_SEWERS: -0xD3F8, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x33738 +} +MAGNETISM_OFFSET_NTSC: dict[str, int] = { + RAC3REGION.VELDIN: 0x2A738, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x17D38, + RAC3REGION.MARCADIA: 0x39F74, + RAC3REGION.DAXX: 0x23518, + RAC3REGION.PHOENIX_ASSAULT: 0xE110, + RAC3REGION.ANNIHILATION_NATION: 0x29560, + RAC3REGION.AQUATOS: 0xC09C, + RAC3REGION.TYHRRANOSIS: 0x43AD4, + RAC3REGION.ZELDRIN_STARPORT: 0xD278, + RAC3REGION.OBANI_GEMINI: 0x778, + RAC3REGION.BLACKWATER_CITY: 0x2BD00, + RAC3REGION.HOLOSTAR_STUDIOS: 0xA378, + RAC3REGION.KOROS: 0x14FD0, + RAC3REGION.METROPOLIS: 0x3BC48, + RAC3REGION.CRASH_SITE: 0x39C0, + RAC3REGION.ARIDIA: 0x3CFD8, + RAC3REGION.QWARKS_HIDEOUT: 0x1E630, + RAC3REGION.COMMAND_CENTER_2: 0x4A180, + RAC3REGION.OBANI_DRACO: 0x15F0, + RAC3REGION.COMMAND_CENTER: 0x312C8, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xC908, + RAC3REGION.MUSEUM: 0xF528, + RAC3REGION.METROPOLIS_RANGERS: 0x33250, + RAC3REGION.AQUATOS_BASE: 0xA5C, + RAC3REGION.AQUATOS_SEWERS: -0xE090, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x35B88 +} +MAGNETISM_OFFSET_PAL: dict[str, int] = { + RAC3REGION.VELDIN: 0x2A2B8, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x17CA0, + RAC3REGION.MARCADIA: 0x39E34, + RAC3REGION.DAXX: 0x23758, + RAC3REGION.PHOENIX_ASSAULT: 0xDA70, + RAC3REGION.ANNIHILATION_NATION: 0x29060, + RAC3REGION.AQUATOS: 0xC0E4, + RAC3REGION.TYHRRANOSIS: 0x43894, + RAC3REGION.ZELDRIN_STARPORT: 0xD4C0, + RAC3REGION.OBANI_GEMINI: 0x438, + RAC3REGION.BLACKWATER_CITY: 0x2BA00, + RAC3REGION.HOLOSTAR_STUDIOS: 0xA258, + RAC3REGION.KOROS: 0x14C90, + RAC3REGION.METROPOLIS: 0x3BA48, + RAC3REGION.CRASH_SITE: 0x33C0, + RAC3REGION.ARIDIA: 0x3D098, + RAC3REGION.QWARKS_HIDEOUT: 0x1E8E8, + RAC3REGION.COMMAND_CENTER_2: 0x4A300, + RAC3REGION.OBANI_DRACO: 0x10F0, + RAC3REGION.COMMAND_CENTER: 0x30FD0, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xC450, + RAC3REGION.MUSEUM: 0xF128, + RAC3REGION.METROPOLIS_RANGERS: 0x33250, + RAC3REGION.AQUATOS_BASE: 0x364, + RAC3REGION.AQUATOS_SEWERS: -0xE010, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x35A08 +} +MAGNETISM_OFFSET_JP: dict[str, int] = { + RAC3REGION.VELDIN: 0x2A6A0, + RAC3REGION.FLORANA: 0x0, + RAC3REGION.STARSHIP_PHOENIX: 0x17CA0, + RAC3REGION.MARCADIA: 0x39EDC, + RAC3REGION.DAXX: 0x23518, + RAC3REGION.PHOENIX_ASSAULT: 0xE0D0, + RAC3REGION.ANNIHILATION_NATION: 0x29488, + RAC3REGION.AQUATOS: 0xC15C, + RAC3REGION.TYHRRANOSIS: 0x436BC, + RAC3REGION.ZELDRIN_STARPORT: 0xD378, + RAC3REGION.OBANI_GEMINI: 0x7B8, + RAC3REGION.BLACKWATER_CITY: 0x2BCA8, + RAC3REGION.HOLOSTAR_STUDIOS: 0xA4B8, + RAC3REGION.KOROS: 0x15050, + RAC3REGION.METROPOLIS: 0x3BBB0, + RAC3REGION.CRASH_SITE: 0x3A00, + RAC3REGION.ARIDIA: 0x3D000, + RAC3REGION.QWARKS_HIDEOUT: 0x1E730, + RAC3REGION.COMMAND_CENTER_2: 0x4A128, + RAC3REGION.OBANI_DRACO: 0x1630, + RAC3REGION.COMMAND_CENTER: 0x312F0, + RAC3REGION.HOLOSTAR_STUDIOS_CLANK: 0xC8C8, + RAC3REGION.MUSEUM: 0xF5A8, + RAC3REGION.METROPOLIS_RANGERS: 0x331B8, + RAC3REGION.AQUATOS_BASE: 0xB1C, + RAC3REGION.AQUATOS_SEWERS: -0xE010, + RAC3REGION.TYHRRANOSIS_RANGERS: 0x35BB0 +} \ No newline at end of file diff --git a/worlds/rac3/constants/instruction.py b/worlds/rac3/constants/instruction.py index 42e738240786..327366f83774 100644 --- a/worlds/rac3/constants/instruction.py +++ b/worlds/rac3/constants/instruction.py @@ -13,11 +13,15 @@ class RAC3INSTRUCTION: PHOENIX_CAN_BUY_ARMOR_JP = 0x004B13E0 # 1062001A beq v1,v0,0x004B144C PHOENIX_HYPERSHOT_QUICK_SELECT_REMOVAL_NTSC = 0x0040D0A8 # AC600000 sw zero,0x0(v1) PHOENIX_HYPERSHOT_QUICK_SELECT_REMOVAL_PAL = 0x0040FA08 # AC600000 sw zero,0x0(v1) + PHOENIX_HOLDING_WRENCH_V2_NTSC = 0x004FD27C NATION_SLEEP_GAS_HEALTH_UPDATE = 0x0032F884 # 0x2442FFFF addiu v0,v0,-0x1 NATION_HEALTH_REFILL = 0x00330068 # AC652850 sw a1,0x2850(v1) NATION_LEVELUP_HEALING = 0x00319C78 # 00621821 addu v1,v1,v0 NATION_LEVELUP_MILESTONE_HEALING = 0x00319CA4 # ACA22850 sw a0,0x2850(v1) - + #NATION_HOLDING_WRENCH_V2_NTSC = 0x0050E99C # 240200A4 addiu v0,zero,0xA4 + #NATION_WRENCH_UPGRADE_NTSC = 0x0050EA30 # A0620009 sb v0,0x9(v1) + #VELDIN_WRITE_TO_WRENCH_V2_NTSC = 0x0050FBDC # 240200A4 addiu v0,zero,0xA4 + #VELDIN_WRENCH_UPGRADE_NTSC = 0x0050FC70 # A0620009 sb v0,0x9(v1) ORIGINAL_INSTRUCTIONS: dict[int, int] = { RAC3INSTRUCTION.PHOENIX_CAN_BUY_ARMOR_NTSC: 0x1062001A, @@ -29,6 +33,7 @@ class RAC3INSTRUCTION: RAC3INSTRUCTION.NATION_HEALTH_REFILL: 0xAC652850, RAC3INSTRUCTION.NATION_LEVELUP_HEALING: 0x00621821, RAC3INSTRUCTION.NATION_LEVELUP_MILESTONE_HEALING: 0xACA22850, + #RAC3INSTRUCTION.VELDIN_WRENCH_UPGRADE_NTSC: 0xA0620009 } PATCHED_INSTRUCTIONS: dict[int, int] = { @@ -41,6 +46,7 @@ class RAC3INSTRUCTION: RAC3INSTRUCTION.NATION_HEALTH_REFILL: 0x00000000, RAC3INSTRUCTION.NATION_LEVELUP_HEALING: 0x00000000, RAC3INSTRUCTION.NATION_LEVELUP_MILESTONE_HEALING: 0x00000000, + #RAC3INSTRUCTION.VELDIN_WRENCH_UPGRADE_NTSC: 0xA0620000, } PATCH_INSTRUCTION_TO_NAME: dict[int, str] = { @@ -53,6 +59,7 @@ class RAC3INSTRUCTION: RAC3INSTRUCTION.NATION_HEALTH_REFILL: "Annihilation Nation: 1-HP: Health refill removal", RAC3INSTRUCTION.NATION_LEVELUP_HEALING: "Annihilation Nation: 1-HP: Level up healing removal", RAC3INSTRUCTION.NATION_LEVELUP_MILESTONE_HEALING: "Annihilation Nation: 1-HP: Level up milestone healing removal", + #RAC3INSTRUCTION.VELDIN_WRENCH_UPGRADE_NTSC: "Veldin: Wrench upgrades decoupled from Nanotech (NTSC)", } PATCH_INSTRUCTION_TO_PLANET: dict[int, str] = { @@ -65,6 +72,7 @@ class RAC3INSTRUCTION: RAC3INSTRUCTION.NATION_HEALTH_REFILL: RAC3REGION.ANNIHILATION_NATION, RAC3INSTRUCTION.NATION_LEVELUP_HEALING: RAC3REGION.ANNIHILATION_NATION, RAC3INSTRUCTION.NATION_LEVELUP_MILESTONE_HEALING: RAC3REGION.ANNIHILATION_NATION, + #RAC3INSTRUCTION.VELDIN_WRENCH_UPGRADE_NTSC: RAC3REGION.VELDIN, } # None in PATCH_INSTRUCTION_TO_GAME_IDS means the patch applies to all versions. @@ -78,4 +86,5 @@ class RAC3INSTRUCTION: RAC3INSTRUCTION.NATION_HEALTH_REFILL: [RAC3VERSION.US_ID, RAC3VERSION.US_GH_ID], RAC3INSTRUCTION.NATION_LEVELUP_HEALING: [RAC3VERSION.US_ID, RAC3VERSION.US_GH_ID], RAC3INSTRUCTION.NATION_LEVELUP_MILESTONE_HEALING: [RAC3VERSION.US_ID, RAC3VERSION.US_GH_ID], + #RAC3INSTRUCTION.VELDIN_WRENCH_UPGRADE_NTSC: [RAC3VERSION.US_ID, RAC3VERSION.US_GH_ID], } diff --git a/worlds/rac3/constants/item_tags.py b/worlds/rac3/constants/item_tags.py index b455fcee0591..5f8b62e092a5 100644 --- a/worlds/rac3/constants/item_tags.py +++ b/worlds/rac3/constants/item_tags.py @@ -12,6 +12,7 @@ class RAC3ITEMTAG: NGPLUS = "NG+" NON_PROG_WEAPON = "Non-Progressive Weapon" PROG_WEAPON = "Progressive Weapon" + PROG_WRENCH = "Progressive Wrench" PROGRESSIVE = "Progressive" TRAP = "Trap" UNUSED = "Unused" diff --git a/worlds/rac3/constants/items.py b/worlds/rac3/constants/items.py index 7081407c4465..a5667941a97b 100644 --- a/worlds/rac3/constants/items.py +++ b/worlds/rac3/constants/items.py @@ -231,6 +231,7 @@ class RAC3ITEM: PROGRESSIVE_VIDCOMIC = "Progressive VidComic" PROGRESSIVE_ARMOR = "Progressive Armor" PROGRESSIVE_PACK = "Progressive Pack" + PROGRESSIVE_WRENCH = "Progressive Omniwrench" VELDIN = "Infobot: Veldin" FLORANA = "Infobot: Florana" diff --git a/worlds/rac3/constants/options.py b/worlds/rac3/constants/options.py index ab344f26387d..dc83453cace5 100644 --- a/worlds/rac3/constants/options.py +++ b/worlds/rac3/constants/options.py @@ -12,6 +12,7 @@ class RAC3OPTION: STARTING_WEAPONS = "Starting Weapons" BOLT_AND_XP_MULTIPLIER = "Bolt and XP Multiplier" PROGRESSIVE_WEAPONS = "Progressive Weapons" + PROGRESSIVE_WRENCH = "Progressive Wrench" ARMOR_UPGRADE = "Armor Upgrade" SKILL_POINTS = "Skill Points" TROPHIES = "Trophies" diff --git a/worlds/rac3/constants/status.py b/worlds/rac3/constants/status.py index 9bb23af6999e..b8188876c069 100644 --- a/worlds/rac3/constants/status.py +++ b/worlds/rac3/constants/status.py @@ -10,6 +10,7 @@ class RAC3STATUS: SECOND_PREV_ACTION = 0x001A71BC ACTION_TYPE = 0x001A71AC LEVEL_TABLE = 0x001425C0 + WRENCH_LEVEL= 0x001425C9 BOLTS = 0x00142660 MAX_HEALTH = 0x00142668 LAST_USED_0 = 0x00142670 @@ -108,6 +109,7 @@ class RAC3STATUS: NANOTECH_EXP_PACKS = 0x00142DE8 WEAPON_LEVEL_PACKS = 0x00142DEC JACKPOT_PACKS = 0x00142DF0 + CURRENT_FLOOR = 0x001A6050 # these values are high enough to vary based on planet VIDCOMIC_PAUSE = 0x001D7C48 PLANET_LOAD_BASE = 0x001DE544 diff --git a/worlds/rac3/constants/wrench.py b/worlds/rac3/constants/wrench.py new file mode 100644 index 000000000000..f3492f6a2699 --- /dev/null +++ b/worlds/rac3/constants/wrench.py @@ -0,0 +1,69 @@ +"""This module provides constant address offsets, for use when reading data regarding the OmniWrench""" + +from worlds.rac3.constants.function import (RAC3FUNCTION, WRENCH_FUNCTION_OFFSET_PAL, WRENCH_FUNCTION_OFFSET_NTSC, EQUIP_WRENCH_OFFSET_NTSC, + EQUIP_WRENCH_OFFSET_PAL, EQUIP_WRENCH_OFFSET_JP, SWING_WRENCH_OFFSET_NTSC, SWING_WRENCH_OFFSET_PAL) +from worlds.rac3.constants.version import RAC3VERSION + +class RAC3WRENCH: + """Base struct for the Wrench function data, containing common address offsets""" + NANOTECH_THRESHOLD_OFFSET: int = 0x2B0 # Contains the instruction that holds the Nanotech required to reach a certain upgrade. + NANOTECH_DIFFERENCE_CHECK_OFFSET: int = 0x2B4 # Example: For V2, this address contains the decimal number 25. 25 + 15 = 40, OmniWrench V3. + UPGRADE_ID_OFFSET: int = 0x2BC # Contains the ID that will be written to the BASE_ITEM_ID. + BASE_ITEM_ID_OFFSET: int = 0x350 # Contains the item ID that the function will write to. If 00 or 01, the OmniWrench is decoupled from Nanotech + # and the function will write there instead. + PER_LEVEL_OFFSET: int = 0x18 # Starting at WRENCH_FUNCTION_BASE + NANOTECH_THRESHOLD_OFFSET, + # every +0x18 will contain an upgrade. +0x90 directly jumps from V2 to V8. + + #SWING_WRENCH_BASE_NTSC = 0x004D38F0 + SWING_WRENCH_ADDRESS_OFFSET: int = 0xD8 # 24020009, if 24020000 or NOP'd, you cannot swing the wrench. + + #EQUIP_WRENCH_BASE_NTSC = 0x004BDB58 + EQUIP_WRENCH_ADDRESS_OFFSET: int = 0x174 # 908228CA, if 90820000 or NOP'd, you cannot equip the wrench. + HELD_WRENCH_ADDRESS_OFFSET: int = 0x1B0 # 24040009, if 24040000 or NOP'd, the player will hold nothing when pressing square. + + #todo: Research and write the offsets in their determined file + + @staticmethod + def get_wrench_property_address(planet: str, game_id: str = '') -> int: + """Provides the wrench property address for reading data""" + match game_id: + case RAC3VERSION.US_ID: + addr = RAC3FUNCTION.WRENCH_FUNCTION_BASE_NTSC + WRENCH_FUNCTION_OFFSET_NTSC[planet] + return addr + case RAC3VERSION.EU_ID: + addr = RAC3FUNCTION.WRENCH_FUNCTION_BASE_PAL + WRENCH_FUNCTION_OFFSET_PAL[planet] + return addr + case _: + addr = RAC3FUNCTION.WRENCH_FUNCTION_BASE_NTSC + WRENCH_FUNCTION_OFFSET_NTSC[planet] + return addr + + @staticmethod + def get_swing_wrench_address(planet: str, game_id: str = '') -> int: + """Provides one of the many address that effectively allows or disallows the player to swing the wrench""" + match game_id: + case RAC3VERSION.US_ID: + addr = RAC3FUNCTION.SWING_WRENCH_BASE_NTSC + SWING_WRENCH_OFFSET_NTSC[planet] + return addr + case RAC3VERSION.EU_ID: + addr = RAC3FUNCTION.SWING_WRENCH_BASE_PAL + SWING_WRENCH_OFFSET_PAL[planet] + return addr + case _: + addr = RAC3FUNCTION.SWING_WRENCH_BASE_NTSC + SWING_WRENCH_OFFSET_NTSC[planet] + return addr + + @staticmethod + def get_equip_wrench_address(planet: str, game_id: str = '') -> int: + """Provides one of the many address that effectively allows or disallows the player to equip the wrench""" + match game_id: + case RAC3VERSION.US_ID: + addr = RAC3FUNCTION.EQUIP_WRENCH_BASE_NTSC + EQUIP_WRENCH_OFFSET_NTSC[planet] + return addr + case RAC3VERSION.EU_ID: + addr = RAC3FUNCTION.EQUIP_WRENCH_BASE_PAL + EQUIP_WRENCH_OFFSET_PAL[planet] + return addr + case RAC3VERSION.JP_ID: + addr = RAC3FUNCTION.EQUIP_WRENCH_BASE_JP + EQUIP_WRENCH_OFFSET_JP[planet] + return addr + case _: + addr = RAC3FUNCTION.EQUIP_WRENCH_BASE_NTSC + EQUIP_WRENCH_OFFSET_NTSC[planet] + return addr diff --git a/worlds/rac3/items.py b/worlds/rac3/items.py index d15b1fbf4f4f..c39ae745d7d5 100644 --- a/worlds/rac3/items.py +++ b/worlds/rac3/items.py @@ -43,12 +43,16 @@ def create_itempool(world: "RaC3World") -> list[Item]: if options.ngplus_items.value: if name == RAC3ITEM.PROGRESSIVE_RY3N0: item_amount: int = 5 + if name == RAC3ITEM.PROGRESSIVE_WRENCH: + item_amount: int = 7 else: item_amount: int = ngplus_item_counts.get(name, 1) elif name != RAC3ITEM.PROGRESSIVE_RY3N0: item_amount: int = item_counts.get(name, 1) else: continue + if not options.ngplus_items.value and name == RAC3ITEM.PROGRESSIVE_WRENCH: + item_amount: int = 4 # Already placed items (Starting items and vanilla) if name in world.preplaced_items: count = world.preplaced_items.count(name) @@ -62,6 +66,10 @@ def create_itempool(world: "RaC3World") -> list[Item]: if RAC3ITEMTAG.NON_PROG_WEAPON in item_tags and options.progressive_weapons.value: continue + # Progressive Wrench option + if RAC3ITEMTAG.PROG_WRENCH in item_tags and not options.progressive_wrench.value: + continue + # NG+ Item option if RAC3ITEMTAG.NGPLUS in item_tags: if not options.ngplus_items.value: diff --git a/worlds/rac3/options/prog_wrench_options.py b/worlds/rac3/options/prog_wrench_options.py new file mode 100644 index 000000000000..891ec2325b5e --- /dev/null +++ b/worlds/rac3/options/prog_wrench_options.py @@ -0,0 +1,20 @@ +"""This module contains options for the Progressive OmniWrench in the item pool""" + +from Options import Choice +from worlds.rac3.constants.options import RAC3OPTION + + +class ProgressiveWrench(Choice): + """ + Determines if Progresive OmniWrench items are included in the item pool. + ------------------------------------------------------------------------------------ + Disable for the vanilla OmniWrench behaviour. + Enable for OmniWrench upgrades to be included in the item pool. + ------------------------------------------------------------------------------------ + Note: Experimental feature. Even if enabled, you will start with the OmniWrench V1. + """ + display_name = RAC3OPTION.PROGRESSIVE_WRENCH + option_disabled = 0 + option_enabled = 1 + default = 0 + diff --git a/worlds/rac3/rac3options.py b/worlds/rac3/rac3options.py index a84ad8c78bb7..c5e34fbec157 100644 --- a/worlds/rac3/rac3options.py +++ b/worlds/rac3/rac3options.py @@ -19,6 +19,7 @@ from worlds.rac3.options.ngplus_vendor_options import NGPlusVendor from worlds.rac3.options.one_hp_options import OneHpChallenge from worlds.rac3.options.prog_weapons_options import ProgressiveWeapons +from worlds.rac3.options.prog_wrench_options import ProgressiveWrench from worlds.rac3.options.rangers_options import Rangers from worlds.rac3.options.ratchet_skins_options import RatchetSkin from worlds.rac3.options.scout_vendors_options import ScoutVendors @@ -60,6 +61,7 @@ class RaC3Options(PerGameCommonOptions): starting_weapons: StartingWeapons bolt_and_xp_multiplier: BoltAndXPMultiplier progressive_weapons: ProgressiveWeapons + progressive_wrench: ProgressiveWrench armor_upgrade: ArmorUpgrade filler_weight: FillerWeight traps_enabled: EnableTraps @@ -113,6 +115,7 @@ class RaC3Options(PerGameCommonOptions): StartingWeapons, NGPlusItems, ProgressiveWeapons, + ProgressiveWrench, ArmorUpgrade, ClankOptions, EnableTraps, @@ -159,6 +162,7 @@ class RaC3Options(PerGameCommonOptions): RAC3OPTION.STARTING_WEAPONS, RAC3OPTION.BOLT_AND_XP_MULTIPLIER, RAC3OPTION.PROGRESSIVE_WEAPONS, + RAC3OPTION.PROGRESSIVE_WRENCH, RAC3OPTION.NGPLUS_ITEMS, RAC3OPTION.NGPLUS_START, RAC3OPTION.ARMOR_UPGRADE, diff --git a/worlds/rac3/rules.py b/worlds/rac3/rules.py index db6e9127264c..0dc7a41d8199 100644 --- a/worlds/rac3/rules.py +++ b/worlds/rac3/rules.py @@ -88,6 +88,12 @@ def set_rules(world: "RaC3World"): if ngplus_enabled: progressive_requirement += 5 if world.options.ngplus_items.value else 4 + progressive_wrench_requirement = 1 + if world.options.progressive_wrench.value != 0: + progressive_wrench_requirement += 4 if world.options.ngplus_items.value else 3 + else: progressive_wrench_requirement = 0 + + region_rules_dict: dict[str, Callable] = { # Intro Florana @@ -357,7 +363,8 @@ def set_rules(world: "RaC3World"): and state.can_reach_location(RAC3LOCATION.NATION_WHIP_IT_GOOD, world.player), RAC3SKILLPOINT.NATION_BASH: - lambda state: state.can_reach_location(RAC3LOCATION.NATION_BBQ_BOULEVARD, world.player), + lambda state: state.can_reach_location(RAC3LOCATION.NATION_BBQ_BOULEVARD, world.player) + and state.has(RAC3ITEM.PROGRESSIVE_WRENCH, world.player, progressive_wrench_requirement), RAC3LOCATION.NATION_MEET_COURTNEY: lambda state: state.can_reach_location(RAC3LOCATION.NATION_BBQ_BOULEVARD, world.player), RAC3LOCATION.NATION_INFOBOT_HOLOSTAR: @@ -577,7 +584,8 @@ def set_rules(world: "RaC3World"): RAC3TBOLT.OBANI_GEMINI_2: lambda state: state.has(RAC3ITEM.REFRACTOR, world.player), RAC3LOCATION.OBANI_GEMINI_SKIDD: lambda state: state.has(RAC3ITEM.REFRACTOR, world.player), - # RAC3SKILLPOINT.BLACKWATER_BASH + RAC3SKILLPOINT.BLACKWATER_BASH: + lambda state: state.has(RAC3ITEM.PROGRESSIVE_WRENCH, world.player, progressive_wrench_requirement), # RAC3LOCATION.BLACKWATER_CITY_RANGERS_1 RAC3LOCATION.BLACKWATER_CITY_RANGERS_2: lambda state: state.can_reach_location(RAC3LOCATION.BLACKWATER_CITY_RANGERS_1, world.player), diff --git a/worlds/rac3/universal_tracker.py b/worlds/rac3/universal_tracker.py index 03d197fb2adb..db605fe3f644 100644 --- a/worlds/rac3/universal_tracker.py +++ b/worlds/rac3/universal_tracker.py @@ -21,6 +21,7 @@ def setup_options_from_slot_data(world: "RaC3World") -> None: world.options.starting_weapons.value = world.passthrough[RAC3OPTION.STARTING_WEAPONS] world.options.bolt_and_xp_multiplier.value = world.passthrough[RAC3OPTION.BOLT_AND_XP_MULTIPLIER] world.options.progressive_weapons.value = world.passthrough[RAC3OPTION.PROGRESSIVE_WEAPONS] + world.options.progressive_wrench.value = world.passthrough[RAC3OPTION.PROGRESSIVE_WRENCH] world.options.armor_upgrade.value = world.passthrough[RAC3OPTION.ARMOR_UPGRADE] world.options.skill_points.value = world.passthrough[RAC3OPTION.SKILL_POINTS] world.options.trophies.value = world.passthrough[RAC3OPTION.TROPHIES] diff --git a/worlds/rac3/world.py b/worlds/rac3/world.py index 0722d73599b2..e6cf963e60f9 100644 --- a/worlds/rac3/world.py +++ b/worlds/rac3/world.py @@ -249,6 +249,7 @@ def fill_slot_data(self) -> dict[str, Any]: RAC3OPTION.STARTING_WEAPONS: self.options.starting_weapons.value, RAC3OPTION.BOLT_AND_XP_MULTIPLIER: self.options.bolt_and_xp_multiplier.value, RAC3OPTION.PROGRESSIVE_WEAPONS: self.options.progressive_weapons.value, + RAC3OPTION.PROGRESSIVE_WRENCH: self.options.progressive_wrench.value, RAC3OPTION.ARMOR_UPGRADE: self.options.armor_upgrade.value, RAC3OPTION.SKILL_POINTS: self.options.skill_points.value, RAC3OPTION.TROPHIES: self.options.trophies.value,