diff --git a/archipelago.json b/archipelago.json index 6614a0301..855eedf5e 100644 --- a/archipelago.json +++ b/archipelago.json @@ -1,6 +1,6 @@ { "minimum_ap_version": "0.6.5", - "world_version": "1.4.24", + "world_version": "1.4.25", "authors": ["2dos", "AlmostSeagull", "Ballaam", "Green Bean", "Killklli", "Lrauq", "PoryGone", "Umed"], "version": 7, "compatible_version": 7, diff --git a/archipelago/DK64Client.py b/archipelago/DK64Client.py index 444966c36..592734524 100644 --- a/archipelago/DK64Client.py +++ b/archipelago/DK64Client.py @@ -306,6 +306,25 @@ async def validate_client_connection(self): if not self.memory_pointer: self.memory_pointer = self.n64_client.read_u32(DK64MemoryMap.memory_pointer) self.n64_client.write_u8(self.memory_pointer + DK64MemoryMap.connection, 0xFF) + if self.n64_client.read_u8(DK64MemoryMap.eeprom_determined) == 1: + if self.n64_client.read_u32(DK64MemoryMap.save_type) != 2: + # Map emulator IDs to their setup guides + emulator_setup_guides = { + "Project64": "https://dev.dk64randomizer.com/wiki/index.html?title=Consoles-and-Emulators:-Project-64", + "Project64_v4": "https://dev.dk64randomizer.com/wiki/index.html?title=Consoles-and-Emulators:-Project-64", + "RMG": "https://dev.dk64randomizer.com/wiki/index.html?title=Consoles-and-Emulators:-Rosalies-Mupen-GUI", + "ParallelLauncher": "https://dev.dk64randomizer.com/wiki/index.html?title=Consoles-and-Emulators:-Parallel-Launcher", + "RetroArch": "https://dev.dk64randomizer.com/wiki/index.html?title=Consoles-and-Emulators:-RetroArch", + "BizHawk": "https://dev.dk64randomizer.com/wiki/index.html?title=Consoles-and-Emulators:-BizHawk-DK64-Edition", + "Simple64": "https://dev.dk64randomizer.com/wiki/index.html?title=Consoles-and-Emulators:-Simple64", + } + + emulator_id = self.n64_client.emulator_info.id.name + setup_guide = emulator_setup_guides.get(emulator_id, "https://dev.dk64randomizer.com/wiki/index.html?title=Consoles-and-Emulators") + + logger.error(f"{self.n64_client.emulator_info.id.name} is not set up correctly! Please follow the appropriate setup guide to ensure the game works!") + logger.error(f"{setup_guide}") + raise Exception("Bad emulator setup") # ==================== MESSAGING METHODS ==================== diff --git a/archipelago/Logic.py b/archipelago/Logic.py index 649e042f5..c7bcbe134 100644 --- a/archipelago/Logic.py +++ b/archipelago/Logic.py @@ -1538,7 +1538,7 @@ def CanFreeChunky(self): return self.IsKong(self.settings.chunky_freeing_kong) or self.settings.free_trade_items # Otherwise you need the right slam level (usually 1) else: - return self.hasMoveSwitchsanity(Switches.FactoryFreeKong, level=Levels.FranticFactory, default_slam_level=1) and (self.slope_resets or self.handstand) + return self.hasMoveSwitchsanity(Switches.FactoryFreeKong, level=Levels.FranticFactory, default_slam_level=1) def CanOpenForestLobbyGoneDoor(self): """Check if the player can open the door to the gone pad in forest lobby.""" diff --git a/archipelago/client/common.py b/archipelago/client/common.py index 7874e4dea..eb9bca502 100644 --- a/archipelago/client/common.py +++ b/archipelago/client/common.py @@ -38,6 +38,8 @@ class DK64MemoryMap: CurrentGamemode = 0x80755314 NextGamemode = 0x80755318 current_map = 0x8076A0A8 + save_type = 0x807EDEAC + eeprom_determined = 0x807467E0 safety_text_timer = 0x02A end_credits = 0x1B0 send_death = 0x05C # If donk player dies. Set this back to 0 upon receiving that the donk player has died diff --git a/randomizer/Enums/Events.jsonc b/randomizer/Enums/Events.jsonc index fb3d7a8ac..12abbedb6 100644 --- a/randomizer/Enums/Events.jsonc +++ b/randomizer/Enums/Events.jsonc @@ -237,6 +237,7 @@ "HelmLobbyW1aTagged": 206, "HelmLobbyW1bTagged": 207, "KilledRabbit": 208, - "LankyMushroomSlamSwitch": 209 + "LankyMushroomSlamSwitch": 209, + "ChunkyFreed": 210 } } diff --git a/randomizer/Logic.py b/randomizer/Logic.py index 129bcff96..c36e1bab5 100644 --- a/randomizer/Logic.py +++ b/randomizer/Logic.py @@ -974,7 +974,7 @@ def CanFreeChunky(self): return self.IsKong(self.settings.chunky_freeing_kong) or self.settings.free_trade_items # Otherwise you need the right slam level (usually 1) else: - return self.hasMoveSwitchsanity(Switches.FactoryFreeKong, level=Levels.FranticFactory, default_slam_level=1) and (self.slope_resets or self.handstand) + return self.hasMoveSwitchsanity(Switches.FactoryFreeKong, level=Levels.FranticFactory, default_slam_level=1) def CanOpenForestLobbyGoneDoor(self): """Check if the player can open the door to the gone pad in forest lobby.""" diff --git a/randomizer/LogicFiles/FranticFactory.py b/randomizer/LogicFiles/FranticFactory.py index f02fe7170..9cf5ffc39 100644 --- a/randomizer/LogicFiles/FranticFactory.py +++ b/randomizer/LogicFiles/FranticFactory.py @@ -142,8 +142,8 @@ ]), Regions.BeyondHatch: Region("Beyond Hatch", HintRegion.Storage, Levels.FranticFactory, True, -1, [ - LocationLogic(Locations.ChunkyKong, lambda l: l.CanFreeChunky()), - LocationLogic(Locations.FactoryLankyFreeChunky, lambda l: l.CanFreeChunky()), + LocationLogic(Locations.ChunkyKong, lambda l: Events.ChunkyFreed in l.Events), + LocationLogic(Locations.FactoryLankyFreeChunky, lambda l: Events.ChunkyFreed in l.Events), LocationLogic(Locations.FactoryChunkyDarkRoom, lambda l: ((l.punch and l.chunky) or l.CanPhase()) and ((l.punch and l.CanSlamSwitch(Levels.FranticFactory, 1)) or l.generalclips) and l.ischunky), LocationLogic(Locations.RainbowCoin_Location02, lambda l: (l.punch and l.chunky) or l.CanPhase()), LocationLogic(Locations.FactoryKasplatStorage, lambda l: not l.settings.kasplat_rando), @@ -173,7 +173,7 @@ ]), Regions.FactoryStoragePipe: Region("Factory Storage Pipe", HintRegion.Storage, Levels.FranticFactory, False, None, [], [ - # If we were to move the switch to Chunky's cage back up this pipe, the event would go here. + Event(Events.ChunkyFreed, lambda l: l.CanFreeChunky()) ], [ TransitionFront(Regions.BeyondHatch, lambda _: True), ]), diff --git a/randomizer/Patching/ApplyRandomizer.py b/randomizer/Patching/ApplyRandomizer.py index 67cc797f5..23b0bd591 100644 --- a/randomizer/Patching/ApplyRandomizer.py +++ b/randomizer/Patching/ApplyRandomizer.py @@ -673,7 +673,6 @@ def patching_response(spoiler): randomize_coins(spoiler, ROM_COPY) place_mayhem_coins(spoiler, ROM_COPY) ApplyShopRandomizer(spoiler, ROM_COPY) - showWinCondition(spoiler.settings, ROM_COPY) remove5DSCameraPoint(spoiler, ROM_COPY) alterTextboxRequirements(spoiler) spoiler.arcade_item_reward = Items.NintendoCoin @@ -729,6 +728,7 @@ def patching_response(spoiler): applyKongModelSwaps(spoiler.settings, ROM_COPY) updateHelmFaces(spoiler.settings, ROM_COPY) updateSnidePanel(spoiler.settings, ROM_COPY) + showWinCondition(spoiler.settings, ROM_COPY) patchAssembly(ROM_COPY, spoiler) ApplyMirrorMode(spoiler.settings, ROM_COPY) diff --git a/randomizer/Patching/EnemyRando.py b/randomizer/Patching/EnemyRando.py index da4d61df0..2bbf3e11e 100644 --- a/randomizer/Patching/EnemyRando.py +++ b/randomizer/Patching/EnemyRando.py @@ -559,6 +559,14 @@ def writeEnemy(spoiler, ROM_COPY: LocalROM, cont_map_spawner_address: int, new_e new_speed = 255 ROM_COPY.seek(cont_map_spawner_address + spawner.offset + speed_offset) ROM_COPY.writeMultipleBytes(new_speed, 1) + # Cap Klobber Speed + if new_enemy_id in (Enemies.Klobber, Enemies.Kaboom): + for speed_offset in [0xC, 0xD]: + ROM_COPY.seek(cont_map_spawner_address + spawner.offset + speed_offset) + current_speed = int.from_bytes(ROM_COPY.readBytes(1), "big") + new_speed = max(1, int(current_speed * 0.6)) + ROM_COPY.seek(cont_map_spawner_address + spawner.offset + speed_offset) + ROM_COPY.writeMultipleBytes(new_speed, 1) # Fix Tiny 5DI enemy to not respawn ROM_COPY.seek(cont_map_spawner_address + spawner.offset + 0x13) id = int.from_bytes(ROM_COPY.readBytes(1), "big") diff --git a/typings/randomizer/Enums/Events.d.ts b/typings/randomizer/Enums/Events.d.ts index eda474cc4..1bae5374c 100644 --- a/typings/randomizer/Enums/Events.d.ts +++ b/typings/randomizer/Enums/Events.d.ts @@ -208,4 +208,5 @@ export enum Events { HelmLobbyW1bTagged = 207, KilledRabbit = 208, LankyMushroomSlamSwitch = 209, + ChunkyFreed = 210, } diff --git a/typings/randomizer/Enums/Events.pyi b/typings/randomizer/Enums/Events.pyi index f3acda9da..a78e30545 100644 --- a/typings/randomizer/Enums/Events.pyi +++ b/typings/randomizer/Enums/Events.pyi @@ -210,3 +210,4 @@ class Events(IntEnum): HelmLobbyW1bTagged = 207 KilledRabbit = 208 LankyMushroomSlamSwitch = 209 + ChunkyFreed = 210