SMW: v1.1 Content Update (#1344)
* Make Bowser unkillable on Egg Hunt * Increment Data Package version Changed a location name. * Baseline for Bowser Rooms shuffling * Add boss shuffle * Remove extra space * Overworld Palette Shuffle * Fix Literature Trap typo * Handle Queuing traps and new Timer Trap * Fix trap name and actually create them * Early Climb and Overworld Speed * Add correct tooltip for Early Climb * Tooltip text edit * Address unconnected regions * Add option to fully exclude Special Zone levels from the seed * Fix Chocolate Island 4 Dragon Coins logic * Update worlds/smw/Client.py to use `getattr`
This commit is contained in:
parent
428344b6bc
commit
dc2aa5f41e
|
@ -136,6 +136,15 @@ valid_background_colors = {
|
|||
0xFFF45A: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], # Castle
|
||||
}
|
||||
|
||||
valid_ow_palettes = {
|
||||
0x2D1E: [0x00, 0x01, 0x03], # Main OW
|
||||
0x2D1F: [0x00, 0x03, 0x04], # Yoshi's Island
|
||||
0x2D20: [0x00, 0x01, 0x03, 0x04], # Vanilla Dome
|
||||
0x2D21: [0x00, 0x02, 0x03, 0x04], # Forest of Illusion
|
||||
0x2D22: [0x00, 0x01, 0x03, 0x04], # Valley of Bowser
|
||||
0x2D24: [0x00, 0x02, 0x03], # Star Road
|
||||
}
|
||||
|
||||
def generate_shuffled_level_music(world, player):
|
||||
shuffled_level_music = level_music_value_data.copy()
|
||||
|
||||
|
@ -158,6 +167,12 @@ def generate_shuffled_ow_music(world, player):
|
|||
|
||||
return shuffled_ow_music
|
||||
|
||||
def generate_shuffled_ow_palettes(rom, world, player):
|
||||
if world.overworld_palette_shuffle[player]:
|
||||
for address, valid_palettes in valid_ow_palettes.items():
|
||||
chosen_palette = world.random.choice(valid_palettes)
|
||||
rom.write_byte(address, chosen_palette)
|
||||
|
||||
def generate_shuffled_header_data(rom, world, player):
|
||||
if world.music_shuffle[player] != "full" and not world.foreground_palette_shuffle[player] and not world.background_palette_shuffle[player]:
|
||||
return
|
||||
|
|
|
@ -169,7 +169,74 @@ class SMWSNIClient(SNIClient):
|
|||
|
||||
await snes_flush_writes(ctx)
|
||||
|
||||
return
|
||||
|
||||
def add_trap_to_queue(self, trap_item, trap_msg):
|
||||
self.trap_queue = getattr(self, "trap_queue", [])
|
||||
|
||||
self.trap_queue.append((trap_item, trap_msg))
|
||||
|
||||
|
||||
async def handle_trap_queue(self, ctx):
|
||||
from SNIClient import snes_buffered_write, snes_flush_writes, snes_read
|
||||
|
||||
if not hasattr(self, "trap_queue") or len(self.trap_queue) == 0:
|
||||
return
|
||||
|
||||
game_state = await snes_read(ctx, SMW_GAME_STATE_ADDR, 0x1)
|
||||
if game_state[0] != 0x14:
|
||||
return
|
||||
|
||||
mario_state = await snes_read(ctx, SMW_MARIO_STATE_ADDR, 0x1)
|
||||
if mario_state[0] != 0x00:
|
||||
return
|
||||
|
||||
pause_state = await snes_read(ctx, SMW_PAUSE_ADDR, 0x1)
|
||||
if pause_state[0] != 0x00:
|
||||
return
|
||||
|
||||
next_trap, message = self.trap_queue.pop(0)
|
||||
|
||||
from worlds.smw.Rom import trap_rom_data
|
||||
if next_trap.item in trap_rom_data:
|
||||
trap_active = await snes_read(ctx, WRAM_START + trap_rom_data[next_trap.item][0], 0x3)
|
||||
|
||||
if next_trap.item == 0xBC0016:
|
||||
# Timer Trap
|
||||
if trap_active[0] == 0 or (trap_active[0] == 1 and trap_active[1] == 0 and trap_active[2] == 0):
|
||||
# Trap already active
|
||||
self.add_trap_to_queue(next_trap, message)
|
||||
return
|
||||
else:
|
||||
snes_buffered_write(ctx, WRAM_START + trap_rom_data[next_trap.item][0], bytes([0x01]))
|
||||
snes_buffered_write(ctx, WRAM_START + trap_rom_data[next_trap.item][0] + 1, bytes([0x00]))
|
||||
snes_buffered_write(ctx, WRAM_START + trap_rom_data[next_trap.item][0] + 2, bytes([0x00]))
|
||||
else:
|
||||
if trap_active[0] > 0:
|
||||
# Trap already active
|
||||
self.add_trap_to_queue(next_trap, message)
|
||||
return
|
||||
else:
|
||||
verify_game_state = await snes_read(ctx, SMW_GAME_STATE_ADDR, 0x1)
|
||||
if verify_game_state[0] == 0x14 and len(trap_rom_data[next_trap.item]) > 2:
|
||||
snes_buffered_write(ctx, SMW_SFX_ADDR, bytes([trap_rom_data[next_trap.item][2]]))
|
||||
|
||||
new_item_count = trap_rom_data[next_trap.item][1]
|
||||
snes_buffered_write(ctx, WRAM_START + trap_rom_data[next_trap.item][0], bytes([new_item_count]))
|
||||
|
||||
current_level = await snes_read(ctx, SMW_CURRENT_LEVEL_ADDR, 0x1)
|
||||
if current_level[0] in SMW_BAD_TEXT_BOX_LEVELS:
|
||||
return
|
||||
|
||||
boss_state = await snes_read(ctx, SMW_BOSS_STATE_ADDR, 0x1)
|
||||
if boss_state[0] in SMW_BOSS_STATES:
|
||||
return
|
||||
|
||||
active_boss = await snes_read(ctx, SMW_ACTIVE_BOSS_ADDR, 0x1)
|
||||
if active_boss[0] != 0x00:
|
||||
return
|
||||
|
||||
if ctx.receive_option == 1 or (ctx.receive_option == 2 and ((next_trap.flags & 1) != 0)):
|
||||
self.add_message_to_queue(message)
|
||||
|
||||
|
||||
async def game_watcher(self, ctx):
|
||||
|
@ -229,13 +296,14 @@ class SMWSNIClient(SNIClient):
|
|||
await snes_flush_writes(ctx)
|
||||
|
||||
await self.handle_message_queue(ctx)
|
||||
await self.handle_trap_queue(ctx)
|
||||
|
||||
new_checks = []
|
||||
event_data = await snes_read(ctx, SMW_EVENT_ROM_DATA, 0x60)
|
||||
progress_data = bytearray(await snes_read(ctx, SMW_PROGRESS_DATA, 0x0F))
|
||||
dragon_coins_data = bytearray(await snes_read(ctx, SMW_DRAGON_COINS_DATA, 0x0C))
|
||||
dragon_coins_active = await snes_read(ctx, SMW_DRAGON_COINS_ACTIVE_ADDR, 0x1)
|
||||
from worlds.smw.Rom import item_rom_data, ability_rom_data
|
||||
from worlds.smw.Rom import item_rom_data, ability_rom_data, trap_rom_data
|
||||
from worlds.smw.Levels import location_id_to_level_id, level_info_dict
|
||||
from worlds import AutoWorldRegister
|
||||
for loc_name, level_data in location_id_to_level_id.items():
|
||||
|
@ -307,7 +375,7 @@ class SMWSNIClient(SNIClient):
|
|||
ctx.location_names[item.location], recv_index, len(ctx.items_received)))
|
||||
|
||||
if ctx.receive_option == 1 or (ctx.receive_option == 2 and ((item.flags & 1) != 0)):
|
||||
if item.item != 0xBC0012:
|
||||
if item.item != 0xBC0012 and item.item not in trap_rom_data:
|
||||
# Don't send messages for Boss Tokens
|
||||
item_name = ctx.item_names[item.item]
|
||||
player_name = ctx.player_names[item.player]
|
||||
|
@ -316,7 +384,13 @@ class SMWSNIClient(SNIClient):
|
|||
self.add_message_to_queue(receive_message)
|
||||
|
||||
snes_buffered_write(ctx, SMW_RECV_PROGRESS_ADDR, bytes([recv_index]))
|
||||
if item.item in item_rom_data:
|
||||
if item.item in trap_rom_data:
|
||||
item_name = ctx.item_names[item.item]
|
||||
player_name = ctx.player_names[item.player]
|
||||
|
||||
receive_message = generate_received_text(item_name, player_name)
|
||||
self.add_trap_to_queue(item, receive_message)
|
||||
elif item.item in item_rom_data:
|
||||
item_count = await snes_read(ctx, WRAM_START + item_rom_data[item.item][0], 0x1)
|
||||
increment = item_rom_data[item.item][1]
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ trap_table = {
|
|||
ItemName.ice_trap: ItemData(0xBC0013, False, True),
|
||||
ItemName.stun_trap: ItemData(0xBC0014, False, True),
|
||||
ItemName.literature_trap: ItemData(0xBC0015, False, True),
|
||||
ItemName.timer_trap: ItemData(0xBC0016, False, True),
|
||||
}
|
||||
|
||||
event_table = {
|
||||
|
|
|
@ -1,6 +1,80 @@
|
|||
|
||||
from .Names import LocationName
|
||||
|
||||
|
||||
class BowserRoom():
|
||||
name: str
|
||||
exitAddress: int
|
||||
roomID: int
|
||||
|
||||
def __init__(self, name: str, exitAddress: int, roomID: int):
|
||||
self.name = name
|
||||
self.exitAddress = exitAddress
|
||||
self.roomID = roomID
|
||||
|
||||
full_bowser_rooms = [
|
||||
BowserRoom("Hallway 1 - Door 1", 0x3A680, 0x0D),
|
||||
BowserRoom("Hallway 1 - Door 2", 0x3A684, 0x0D),
|
||||
BowserRoom("Hallway 1 - Door 3", 0x3A688, 0x0D),
|
||||
BowserRoom("Hallway 1 - Door 4", 0x3A68C, 0x0D),
|
||||
BowserRoom("Hallway 2 - Door 1", 0x3A8CB, 0xD0),
|
||||
BowserRoom("Hallway 2 - Door 2", 0x3A8CF, 0xD0),
|
||||
BowserRoom("Hallway 2 - Door 3", 0x3A8D3, 0xD0),
|
||||
BowserRoom("Hallway 2 - Door 4", 0x3A8D7, 0xD0),
|
||||
|
||||
BowserRoom("Room 1", 0x3A705, 0xD4),
|
||||
BowserRoom("Room 2", 0x3A763, 0xD3),
|
||||
BowserRoom("Room 3", 0x3A800, 0xD2),
|
||||
BowserRoom("Room 4", 0x3A83D, 0xD1),
|
||||
BowserRoom("Room 5", 0x3A932, 0xCF),
|
||||
BowserRoom("Room 6", 0x3A9E1, 0xCE),
|
||||
BowserRoom("Room 7", 0x3AA75, 0xCD),
|
||||
BowserRoom("Room 8", 0x3AAC7, 0xCC),
|
||||
]
|
||||
|
||||
standard_bowser_rooms = [
|
||||
BowserRoom("Room 1", 0x3A705, 0xD4),
|
||||
BowserRoom("Room 2", 0x3A763, 0xD3),
|
||||
BowserRoom("Room 3", 0x3A800, 0xD2),
|
||||
BowserRoom("Room 4", 0x3A83D, 0xD1),
|
||||
BowserRoom("Room 5", 0x3A932, 0xCF),
|
||||
BowserRoom("Room 6", 0x3A9E1, 0xCE),
|
||||
BowserRoom("Room 7", 0x3AA75, 0xCD),
|
||||
BowserRoom("Room 8", 0x3AAC7, 0xCC),
|
||||
]
|
||||
|
||||
|
||||
class BossRoom():
|
||||
name: str
|
||||
exitAddress: int
|
||||
exitAddressAlt: int
|
||||
roomID: int
|
||||
|
||||
def __init__(self, name: str, exitAddress: int, roomID: int, exitAddressAlt=None):
|
||||
self.name = name
|
||||
self.exitAddress = exitAddress
|
||||
self.roomID = roomID
|
||||
self.exitAddressAlt = exitAddressAlt
|
||||
|
||||
|
||||
submap_boss_rooms = [
|
||||
BossRoom("#1 Lemmy Koopa", 0x311E3, 0xF6), # Submap 0x1F6
|
||||
BossRoom("#3 Lemmy Koopa", 0x33749, 0xF2), # Submap 0x1F2
|
||||
BossRoom("Valley Reznor", 0x3A132, 0xDE), # Submap 0x1DE
|
||||
BossRoom("#7 Larry Koopa", 0x3A026, 0xEB), # Submap 0x1EB
|
||||
]
|
||||
|
||||
ow_boss_rooms = [
|
||||
BossRoom("#2 Morton Koopa Jr.", 0x3209B, 0xE5), # OW 0x0E5
|
||||
BossRoom("Vanilla Reznor", 0x33EAB, 0xDF), # OW 0x0DF
|
||||
BossRoom("#4 Ludwig von Koopa", 0x346EA, 0xD9), # OW 0x0D9
|
||||
BossRoom("Forest Reznor", 0x3643E, 0xD5, 0x36442), # OW 0x0D5
|
||||
BossRoom("#5 Roy Koopa", 0x35ABC, 0xCC), # OW 0x0CC
|
||||
BossRoom("Chocolate Reznor", 0x3705B, 0xE2), # OW 0x0E2
|
||||
BossRoom("#6 Wendy O. Koopa", 0x38BB5, 0xD3), # OW 0x0D3
|
||||
]
|
||||
|
||||
|
||||
class SMWPath():
|
||||
thisEndDirection: int
|
||||
otherLevelID: int
|
||||
|
@ -203,6 +277,9 @@ hard_single_levels = [
|
|||
0x3B,
|
||||
0x3A,
|
||||
0x37,
|
||||
]
|
||||
|
||||
special_zone_levels = [
|
||||
0x4E,
|
||||
0x4F,
|
||||
0x50,
|
||||
|
@ -443,6 +520,7 @@ def generate_level_list(world, player):
|
|||
world.random.shuffle(easy_single_levels_copy)
|
||||
hard_single_levels_copy = hard_single_levels.copy()
|
||||
world.random.shuffle(hard_single_levels_copy)
|
||||
special_zone_levels_copy = special_zone_levels.copy()
|
||||
easy_double_levels_copy = easy_double_levels.copy()
|
||||
world.random.shuffle(easy_double_levels_copy)
|
||||
hard_double_levels_copy = hard_double_levels.copy()
|
||||
|
@ -474,6 +552,8 @@ def generate_level_list(world, player):
|
|||
shuffled_level_list.append(0x16)
|
||||
|
||||
single_levels_copy = (easy_single_levels_copy.copy() + hard_single_levels_copy.copy())
|
||||
if not world.exclude_special_zone[player]:
|
||||
single_levels_copy.extend(special_zone_levels_copy)
|
||||
world.random.shuffle(single_levels_copy)
|
||||
|
||||
castle_fortress_levels_copy = (easy_castle_fortress_levels_copy.copy() + hard_castle_fortress_levels_copy.copy())
|
||||
|
@ -566,14 +646,17 @@ def generate_level_list(world, player):
|
|||
|
||||
# Special Zone
|
||||
shuffled_level_list.append(0x4D)
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
if not world.exclude_special_zone[player]:
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
shuffled_level_list.append(single_levels_copy.pop(0))
|
||||
else:
|
||||
shuffled_level_list.extend(special_zone_levels_copy)
|
||||
shuffled_level_list.append(0x48)
|
||||
|
||||
return shuffled_level_list
|
||||
|
|
|
@ -212,6 +212,28 @@ all_locations = {
|
|||
**yoshi_house_location_table,
|
||||
}
|
||||
|
||||
special_zone_level_names = [
|
||||
LocationName.special_zone_1_exit_1,
|
||||
LocationName.special_zone_2_exit_1,
|
||||
LocationName.special_zone_3_exit_1,
|
||||
LocationName.special_zone_4_exit_1,
|
||||
LocationName.special_zone_5_exit_1,
|
||||
LocationName.special_zone_6_exit_1,
|
||||
LocationName.special_zone_7_exit_1,
|
||||
LocationName.special_zone_8_exit_1,
|
||||
]
|
||||
|
||||
special_zone_dragon_coin_names = [
|
||||
LocationName.special_zone_1_dragon,
|
||||
LocationName.special_zone_2_dragon,
|
||||
LocationName.special_zone_3_dragon,
|
||||
LocationName.special_zone_4_dragon,
|
||||
LocationName.special_zone_5_dragon,
|
||||
LocationName.special_zone_6_dragon,
|
||||
LocationName.special_zone_7_dragon,
|
||||
LocationName.special_zone_8_dragon,
|
||||
]
|
||||
|
||||
location_table = {}
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ blue_switch_palace = "Blue Switch Palace"
|
|||
ice_trap = "Ice Trap"
|
||||
stun_trap = "Stun Trap"
|
||||
literature_trap = "Literature Trap"
|
||||
timer_trap = "Timer Trap"
|
||||
|
||||
# Other Definitions
|
||||
victory = "The Princess"
|
||||
|
|
|
@ -25,7 +25,7 @@ lit_trap_text_list = [
|
|||
[[0x18, 0x4e, 0x54, 0x1f, 0x47, 0x40, 0x55, 0x44, 0x1f, 0x41, 0x51, 0x40, 0x48, 0x4d, 0x52, 0x1f, 0x48, 0xcd, 0x58, 0x4e, 0x54, 0x51, 0x1f, 0x47, 0x44, 0x40, 0x43, 0x1b, 0x1f, 0x18, 0x4e, 0x54, 0x9f, 0x47, 0x40, 0x55, 0x44, 0x1f, 0x45, 0x44, 0x44, 0x53, 0x1f, 0x48, 0x4d, 0x1f, 0x58, 0x4e, 0x54, 0x51, 0x9f, 0x52, 0x47, 0x4e, 0x44, 0x52, 0x1b, 0x1f, 0x18, 0x4e, 0x54, 0x1f, 0x42, 0x40, 0x4d, 0x9f, 0x52, 0x53, 0x44, 0x44, 0x51, 0x1f, 0x58, 0x4e, 0x54, 0x51, 0x52, 0x44, 0x4b, 0x45, 0x1f, 0x40, 0x4d, 0xd8, 0x43, 0x48, 0x51, 0x44, 0x42, 0x53, 0x48, 0x4e, 0x4d, 0x1f, 0x58, 0x4e, 0x54, 0x9f, 0x42, 0x47, 0x4e, 0x4e, 0x52, 0x44, 0x1b, 0x1f, 0x18, 0x4e, 0x54, 0x5d, 0x51, 0x44, 0x1f, 0x4e, 0x4d, 0x9f, 0x58, 0x4e, 0x54, 0x51, 0x1f, 0x4e, 0x56, 0x4d, 0x1b, 0x1f, 0x0, 0x4d, 0x43, 0x1f, 0x58, 0x4e, 0x54, 0x9f, ], [0x4a, 0x4d, 0x4e, 0x56, 0x1f, 0x56, 0x47, 0x40, 0x53, 0x1f, 0x58, 0x4e, 0x54, 0x9f, 0x4a, 0x4d, 0x4e, 0x56, 0x1b, 0x1f, 0x0, 0x4d, 0x43, 0x1f, 0x18, 0xe, 0x14, 0x1f, 0x40, 0x51, 0x44, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x4e, 0x4d, 0x44, 0x1f, 0x56, 0x47, 0x4e, 0x5d, 0x4b, 0x4b, 0x9f, 0x43, 0x44, 0x42, 0x48, 0x43, 0x44, 0x1f, 0x56, 0x47, 0x44, 0x51, 0x44, 0x1f, 0x53, 0x4e, 0x9f, 0x46, 0x4e, 0x1b, 0x1b, 0x1b, 0x1f, 0x1c, 0x12, 0x54, 0x44, 0x52, 0x52, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
|
||||
[[0x16, 0x47, 0x44, 0x4d, 0x1f, 0x58, 0x4e, 0x54, 0x1f, 0x47, 0x40, 0x55, 0x44, 0x9f, 0x44, 0x4b, 0x48, 0x4c, 0x48, 0x4d, 0x40, 0x53, 0x44, 0x43, 0x1f, 0x40, 0x4b, 0x4b, 0x9f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x48, 0x52, 0x9f, 0x48, 0x4c, 0x4f, 0x4e, 0x52, 0x52, 0x48, 0x41, 0x4b, 0x44, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x4d, 0x9f, 0x56, 0x47, 0x40, 0x53, 0x44, 0x55, 0x44, 0x51, 0x1f, 0x51, 0x44, 0x4c, 0x40, 0x48, 0x4d, 0x52, 0x1d, 0x9f, 0x47, 0x4e, 0x56, 0x44, 0x55, 0x44, 0x51, 0x9f, 0x48, 0x4c, 0x4f, 0x51, 0x4e, 0x41, 0x40, 0x41, 0x4b, 0x44, 0x1d, 0x1f, 0x4c, 0x54, 0x52, 0x53, 0x9f, 0x41, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x53, 0x51, 0x54, 0x53, 0x47, 0x1b, 0x9f, ], [0x1c, 0x3, 0x4e, 0x58, 0x4b, 0x44, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
|
||||
[[0x5d, 0xc, 0x58, 0x1f, 0x4c, 0x48, 0x4d, 0x43, 0x1d, 0x5d, 0x1f, 0x47, 0x44, 0x9f, 0x52, 0x40, 0x48, 0x43, 0x1d, 0x1f, 0x5d, 0x51, 0x44, 0x41, 0x44, 0x4b, 0x52, 0x1f, 0x40, 0x53, 0x9f, 0x52, 0x53, 0x40, 0x46, 0x4d, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1b, 0x1f, 0x6, 0x48, 0x55, 0x44, 0x9f, 0x4c, 0x44, 0x1f, 0x4f, 0x51, 0x4e, 0x41, 0x4b, 0x44, 0x4c, 0x52, 0x1d, 0x1f, 0x46, 0x48, 0x55, 0x44, 0x9f, 0x4c, 0x44, 0x1f, 0x56, 0x4e, 0x51, 0x4a, 0x1d, 0x1f, 0x46, 0x48, 0x55, 0x44, 0x1f, 0x4c, 0x44, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x4c, 0x4e, 0x52, 0x53, 0x1f, 0x40, 0x41, 0x52, 0x53, 0x51, 0x54, 0x52, 0x44, 0x9f, 0x42, 0x51, 0x58, 0x4f, 0x53, 0x4e, 0x46, 0x51, 0x40, 0x4c, 0x1f, 0x4e, 0x51, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4c, 0x4e, 0x52, 0x53, 0x1f, 0x48, 0x4d, 0x53, 0x51, 0x48, 0x42, 0x40, 0x53, 0x44, 0x9f, ], [0x40, 0x4d, 0x40, 0x4b, 0x58, 0x52, 0x48, 0x52, 0x1d, 0x1f, 0x40, 0x4d, 0x43, 0x1f, 0x8, 0x1f, 0x40, 0xcc, 0x48, 0x4d, 0x1f, 0x4c, 0x58, 0x1f, 0x4e, 0x56, 0x4d, 0x1f, 0x4f, 0x51, 0x4e, 0x4f, 0x44, 0x51, 0x9f, 0x40, 0x53, 0x4c, 0x4e, 0x52, 0x4f, 0x47, 0x44, 0x51, 0x44, 0x1b, 0x1f, 0x8, 0x1f, 0x42, 0x40, 0x4d, 0x9f, 0x43, 0x48, 0x52, 0x4f, 0x44, 0x4d, 0x52, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x4d, 0x1f, 0x56, 0x48, 0x53, 0xc7, 0x40, 0x51, 0x53, 0x48, 0x45, 0x48, 0x42, 0x48, 0x40, 0x4b, 0x9f, 0x52, 0x53, 0x48, 0x4c, 0x54, 0x4b, 0x40, 0x4d, 0x53, 0x52, 0x1b, 0x1f, 0x1, 0x54, 0x53, 0x1f, 0x8, 0x9f, 0x40, 0x41, 0x47, 0x4e, 0x51, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x43, 0x54, 0x4b, 0x4b, 0x9f, 0x51, 0x4e, 0x54, 0x53, 0x48, 0x4d, 0x44, 0x1f, 0x4e, 0x45, 0x9f, ], [0x44, 0x57, 0x48, 0x52, 0x53, 0x44, 0x4d, 0x42, 0x44, 0x1b, 0x1f, 0x8, 0x1f, 0x42, 0x51, 0x40, 0x55, 0xc4, 0x45, 0x4e, 0x51, 0x1f, 0x4c, 0x44, 0x4d, 0x53, 0x40, 0x4b, 0x9f, 0x44, 0x57, 0x40, 0x4b, 0x53, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1b, 0x1f, 0x13, 0x47, 0x40, 0x53, 0x9f, 0x48, 0x52, 0x1f, 0x56, 0x47, 0x58, 0x1f, 0x8, 0x1f, 0x47, 0x40, 0x55, 0x44, 0x9f, 0x42, 0x47, 0x4e, 0x52, 0x44, 0x4d, 0x1f, 0x4c, 0x58, 0x1f, 0x4e, 0x56, 0x4d, 0x9f, 0x4f, 0x40, 0x51, 0x53, 0x48, 0x42, 0x54, 0x4b, 0x40, 0x51, 0x9f, 0x4f, 0x51, 0x4e, 0x45, 0x44, 0x52, 0x52, 0x48, 0x4e, 0x4d, 0x1d, 0x1f, 0x4e, 0x51, 0x9f, 0x51, 0x40, 0x53, 0x47, 0x44, 0x51, 0x1f, 0x42, 0x51, 0x44, 0x40, 0x53, 0x44, 0x43, 0x1f, 0x48, 0x53, 0x9d, ], [0x45, 0x4e, 0x51, 0x1f, 0x8, 0x1f, 0x40, 0x4c, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x4e, 0x4d, 0x4b, 0x58, 0x9f, 0x4e, 0x4d, 0x44, 0x1f, 0x48, 0x4d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x56, 0x4e, 0x51, 0x4b, 0x43, 0x1b, 0xdd, 0x1c, 0x3, 0x4e, 0x58, 0x4b, 0x44, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
|
||||
[[0xb, 0x48, 0x45, 0x44, 0x1f, 0x48, 0x52, 0x1f, 0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x4b, 0xd8, 0x52, 0x53, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x40, 0x4d, 0x9f, 0x40, 0x4d, 0x58, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x1f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x53, 0x47, 0xc4, 0x4c, 0x48, 0x4d, 0x43, 0x1f, 0x4e, 0x45, 0x1f, 0x4c, 0x40, 0x4d, 0x1f, 0x42, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x48, 0x4d, 0x55, 0x44, 0x4d, 0x53, 0x1b, 0x1f, 0x16, 0x44, 0x1f, 0x56, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x4d, 0x4e, 0x53, 0x1f, 0x43, 0x40, 0x51, 0x44, 0x1f, 0x53, 0x4e, 0x9f, 0x42, 0x4e, 0x4d, 0x42, 0x44, 0x48, 0x55, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x52, 0x1f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x40, 0x51, 0x44, 0x9f, ], [0x51, 0x44, 0x40, 0x4b, 0x4b, 0x58, 0x1f, 0x4c, 0x44, 0x51, 0x44, 0x9f, 0x42, 0x4e, 0x4c, 0x4c, 0x4e, 0x4d, 0x4f, 0x4b, 0x40, 0x42, 0x44, 0x52, 0x1f, 0x4e, 0x45, 0x9f, 0x44, 0x57, 0x48, 0x52, 0x53, 0x44, 0x4d, 0x42, 0x44, 0x1b, 0x1f, 0x8, 0x45, 0x1f, 0x56, 0x44, 0x9f, 0x42, 0x4e, 0x54, 0x4b, 0x43, 0x1f, 0x45, 0x4b, 0x58, 0x1f, 0x4e, 0x54, 0x53, 0x1f, 0x4e, 0x45, 0x9f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x56, 0x48, 0x4d, 0x43, 0x4e, 0x56, 0x1f, 0x47, 0x40, 0x4d, 0x43, 0x9f, 0x48, 0x4d, 0x1f, 0x47, 0x40, 0x4d, 0x43, 0x1d, 0x1f, 0x47, 0x4e, 0x55, 0x44, 0x51, 0x9f, 0x4e, 0x55, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x48, 0x52, 0x1f, 0x46, 0x51, 0x44, 0x40, 0x53, 0x9f, 0x42, 0x48, 0x53, 0x58, 0x1d, 0x1f, 0x46, 0x44, 0x4d, 0x53, 0x4b, 0x58, 0x9f, ], [0x51, 0x44, 0x4c, 0x4e, 0x55, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x51, 0x4e, 0x4e, 0x45, 0x52, 0x1d, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x40, 0x4d, 0x43, 0x1f, 0x4f, 0x44, 0x44, 0x4f, 0x1f, 0x48, 0x4d, 0x1f, 0x40, 0xd3, 0x53, 0x47, 0x44, 0x1f, 0x50, 0x54, 0x44, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x52, 0x9f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x40, 0x51, 0x44, 0x1f, 0x46, 0x4e, 0x48, 0x4d, 0x46, 0x9f, 0x4e, 0x4d, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x52, 0x53, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x9f, 0x42, 0x4e, 0x48, 0x4d, 0x42, 0x48, 0x43, 0x44, 0x4d, 0x42, 0x44, 0x52, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4f, 0x4b, 0x40, 0x4d, 0x4d, 0x48, 0x4d, 0x46, 0x52, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x42, 0x51, 0x4e, 0x52, 0x52, 0x1c, 0x4f, 0x54, 0x51, 0x4f, 0x4e, 0x52, 0x44, 0x52, 0x1d, 0x9f, ], [0x53, 0x47, 0x44, 0x1f, 0x56, 0x4e, 0x4d, 0x43, 0x44, 0x51, 0x45, 0x54, 0x4b, 0x9f, 0x42, 0x47, 0x40, 0x48, 0x4d, 0x52, 0x1f, 0x4e, 0x45, 0x1f, 0x44, 0x55, 0x44, 0x4d, 0x53, 0x52, 0x1d, 0x9f, 0x56, 0x4e, 0x51, 0x4a, 0x48, 0x4d, 0x46, 0x1f, 0x53, 0x47, 0x51, 0x4e, 0x54, 0x46, 0x47, 0x9f, 0x46, 0x44, 0x4d, 0x44, 0x51, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x52, 0x1d, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x4b, 0x44, 0x40, 0x43, 0x48, 0x4d, 0x46, 0x1f, 0x53, 0x4e, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4c, 0x4e, 0x52, 0x53, 0x1f, 0x4e, 0x54, 0x53, 0x51, 0x44, 0x9f, 0x51, 0x44, 0x52, 0x54, 0x4b, 0x53, 0x52, 0x1d, 0x1f, 0x48, 0x53, 0x1f, 0x56, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x4c, 0x40, 0x4a, 0x44, 0x1f, 0x40, 0x4b, 0x4b, 0x1f, 0x45, 0x48, 0x42, 0x53, 0x48, 0x4e, 0x4d, 0x9f, ], [0x56, 0x48, 0x53, 0x47, 0x1f, 0x48, 0x53, 0x52, 0x9f, 0x42, 0x4e, 0x4d, 0x55, 0x44, 0x4d, 0x53, 0x48, 0x4e, 0x4d, 0x40, 0x4b, 0x48, 0x53, 0x48, 0x44, 0x52, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x45, 0x4e, 0x51, 0x44, 0x52, 0x44, 0x44, 0x4d, 0x9f, 0x42, 0x4e, 0x4d, 0x42, 0x4b, 0x54, 0x52, 0x48, 0x4e, 0x4d, 0x52, 0x1f, 0x4c, 0x4e, 0x52, 0x53, 0x9f, 0x52, 0x53, 0x40, 0x4b, 0x44, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x54, 0x4d, 0x4f, 0x51, 0x4e, 0x45, 0x48, 0x53, 0x40, 0x41, 0x4b, 0x44, 0x1b, 0x9f, 0x1c, 0x3, 0x4e, 0x58, 0x4b, 0x44, 0x1f, 0x9f, 0x9f, ]],
|
||||
[[0xb, 0x48, 0x45, 0x44, 0x1f, 0x48, 0x52, 0x1f, 0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x4b, 0xd8, 0x52, 0x53, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x40, 0x4d, 0x9f, 0x40, 0x4d, 0x58, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x1f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x53, 0x47, 0xc4, 0x4c, 0x48, 0x4d, 0x43, 0x1f, 0x4e, 0x45, 0x1f, 0x4c, 0x40, 0x4d, 0x1f, 0x42, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x48, 0x4d, 0x55, 0x44, 0x4d, 0x53, 0x1b, 0x1f, 0x16, 0x44, 0x1f, 0x56, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x4d, 0x4e, 0x53, 0x1f, 0x43, 0x40, 0x51, 0x44, 0x1f, 0x53, 0x4e, 0x9f, 0x42, 0x4e, 0x4d, 0x42, 0x44, 0x48, 0x55, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x52, 0x1f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x40, 0x51, 0x44, 0x9f, ], [0x51, 0x44, 0x40, 0x4b, 0x4b, 0x58, 0x1f, 0x4c, 0x44, 0x51, 0x44, 0x9f, 0x42, 0x4e, 0x4c, 0x4c, 0x4e, 0x4d, 0x4f, 0x4b, 0x40, 0x42, 0x44, 0x52, 0x1f, 0x4e, 0x45, 0x9f, 0x44, 0x57, 0x48, 0x52, 0x53, 0x44, 0x4d, 0x42, 0x44, 0x1b, 0x1f, 0x8, 0x45, 0x1f, 0x56, 0x44, 0x9f, 0x42, 0x4e, 0x54, 0x4b, 0x43, 0x1f, 0x45, 0x4b, 0x58, 0x1f, 0x4e, 0x54, 0x53, 0x1f, 0x4e, 0x45, 0x9f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x56, 0x48, 0x4d, 0x43, 0x4e, 0x56, 0x1f, 0x47, 0x40, 0x4d, 0x43, 0x9f, 0x48, 0x4d, 0x1f, 0x47, 0x40, 0x4d, 0x43, 0x1d, 0x1f, 0x47, 0x4e, 0x55, 0x44, 0x51, 0x9f, 0x4e, 0x55, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x48, 0x52, 0x1f, 0x46, 0x51, 0x44, 0x40, 0x53, 0x9f, 0x42, 0x48, 0x53, 0x58, 0x1d, 0x1f, 0x46, 0x44, 0x4d, 0x53, 0x4b, 0x58, 0x9f, ], [0x51, 0x44, 0x4c, 0x4e, 0x55, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x51, 0x4e, 0x4e, 0x45, 0x52, 0x1d, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x4f, 0x44, 0x44, 0x4f, 0x1f, 0x48, 0x4d, 0x1f, 0x40, 0xd3, 0x53, 0x47, 0x44, 0x1f, 0x50, 0x54, 0x44, 0x44, 0x51, 0x1f, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x52, 0x9f, 0x56, 0x47, 0x48, 0x42, 0x47, 0x1f, 0x40, 0x51, 0x44, 0x1f, 0x46, 0x4e, 0x48, 0x4d, 0x46, 0x9f, 0x4e, 0x4d, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x52, 0x53, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x9f, 0x42, 0x4e, 0x48, 0x4d, 0x42, 0x48, 0x43, 0x44, 0x4d, 0x42, 0x44, 0x52, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4f, 0x4b, 0x40, 0x4d, 0x4d, 0x48, 0x4d, 0x46, 0x52, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x42, 0x51, 0x4e, 0x52, 0x52, 0x1c, 0x4f, 0x54, 0x51, 0x4f, 0x4e, 0x52, 0x44, 0x52, 0x1d, 0x9f, ], [0x53, 0x47, 0x44, 0x1f, 0x56, 0x4e, 0x4d, 0x43, 0x44, 0x51, 0x45, 0x54, 0x4b, 0x9f, 0x42, 0x47, 0x40, 0x48, 0x4d, 0x52, 0x1f, 0x4e, 0x45, 0x1f, 0x44, 0x55, 0x44, 0x4d, 0x53, 0x52, 0x1d, 0x9f, 0x56, 0x4e, 0x51, 0x4a, 0x48, 0x4d, 0x46, 0x1f, 0x53, 0x47, 0x51, 0x4e, 0x54, 0x46, 0x47, 0x9f, 0x46, 0x44, 0x4d, 0x44, 0x51, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x52, 0x1d, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x4b, 0x44, 0x40, 0x43, 0x48, 0x4d, 0x46, 0x1f, 0x53, 0x4e, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4c, 0x4e, 0x52, 0x53, 0x1f, 0x4e, 0x54, 0x53, 0x51, 0x44, 0x9f, 0x51, 0x44, 0x52, 0x54, 0x4b, 0x53, 0x52, 0x1d, 0x1f, 0x48, 0x53, 0x1f, 0x56, 0x4e, 0x54, 0x4b, 0x43, 0x9f, 0x4c, 0x40, 0x4a, 0x44, 0x1f, 0x40, 0x4b, 0x4b, 0x1f, 0x45, 0x48, 0x42, 0x53, 0x48, 0x4e, 0x4d, 0x9f, ], [0x56, 0x48, 0x53, 0x47, 0x1f, 0x48, 0x53, 0x52, 0x9f, 0x42, 0x4e, 0x4d, 0x55, 0x44, 0x4d, 0x53, 0x48, 0x4e, 0x4d, 0x40, 0x4b, 0x48, 0x53, 0x48, 0x44, 0x52, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x45, 0x4e, 0x51, 0x44, 0x52, 0x44, 0x44, 0x4d, 0x9f, 0x42, 0x4e, 0x4d, 0x42, 0x4b, 0x54, 0x52, 0x48, 0x4e, 0x4d, 0x52, 0x1f, 0x4c, 0x4e, 0x52, 0x53, 0x9f, 0x52, 0x53, 0x40, 0x4b, 0x44, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x54, 0x4d, 0x4f, 0x51, 0x4e, 0x45, 0x48, 0x53, 0x40, 0x41, 0x4b, 0x44, 0x1b, 0x9f, 0x1c, 0x3, 0x4e, 0x58, 0x4b, 0x44, 0x1f, 0x9f, 0x9f, ]],
|
||||
[[0x13, 0x47, 0x44, 0x1f, 0x52, 0x53, 0x4e, 0x51, 0x58, 0x1f, 0x52, 0x4e, 0x1f, 0x45, 0x40, 0x51, 0x1b, 0x9f, 0x8, 0x4d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x41, 0x44, 0x46, 0x48, 0x4d, 0x4d, 0x48, 0x4d, 0x46, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x14, 0x4d, 0x48, 0x55, 0x44, 0x51, 0x52, 0x44, 0x1f, 0x56, 0x40, 0x52, 0x9f, 0x42, 0x51, 0x44, 0x40, 0x53, 0x44, 0x43, 0x1b, 0x1f, 0x13, 0x47, 0x48, 0x52, 0x1f, 0x47, 0x40, 0x52, 0x9f, 0x4c, 0x40, 0x43, 0x44, 0x1f, 0x40, 0x1f, 0x4b, 0x4e, 0x53, 0x1f, 0x4e, 0x45, 0x9f, 0x4f, 0x44, 0x4e, 0x4f, 0x4b, 0x44, 0x1f, 0x55, 0x44, 0x51, 0x58, 0x1f, 0x40, 0x4d, 0x46, 0x51, 0x58, 0x9f, 0x40, 0x4d, 0x43, 0x1f, 0x41, 0x44, 0x44, 0x4d, 0x1f, 0x56, 0x48, 0x43, 0x44, 0x4b, 0x58, 0x9f, 0x51, 0x44, 0x46, 0x40, 0x51, 0x43, 0x44, 0x43, 0x1f, 0x40, 0x52, 0x1f, 0x40, 0x1f, 0x41, 0x40, 0x43, 0x9f, ], [0x4c, 0x4e, 0x55, 0x44, 0x1b, 0x1f, 0x1c, 0x0, 0x43, 0x40, 0x4c, 0x52, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
|
||||
[[0x5, 0x4e, 0x51, 0x1f, 0x48, 0x4d, 0x52, 0x53, 0x40, 0x4d, 0x42, 0x44, 0x1d, 0x1f, 0x4e, 0x4d, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x4f, 0x4b, 0x40, 0x4d, 0x44, 0x53, 0x1f, 0x4, 0x40, 0x51, 0x53, 0x47, 0x1d, 0x9f, 0x4c, 0x40, 0x4d, 0x1f, 0x47, 0x40, 0x43, 0x1f, 0x40, 0x4b, 0x56, 0x40, 0x58, 0x52, 0x9f, 0x40, 0x52, 0x52, 0x54, 0x4c, 0x44, 0x43, 0x1f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x47, 0x44, 0x9f, 0x56, 0x40, 0x52, 0x1f, 0x4c, 0x4e, 0x51, 0x44, 0x9f, 0x48, 0x4d, 0x53, 0x44, 0x4b, 0x4b, 0x48, 0x46, 0x44, 0x4d, 0x53, 0x1f, 0x53, 0x47, 0x40, 0x4d, 0x9f, 0x43, 0x4e, 0x4b, 0x4f, 0x47, 0x48, 0x4d, 0x52, 0x1f, 0x41, 0x44, 0x42, 0x40, 0x54, 0x52, 0x44, 0x9f, 0x47, 0x44, 0x1f, 0x47, 0x40, 0x43, 0x1f, 0x40, 0x42, 0x47, 0x48, 0x44, 0x55, 0x44, 0x43, 0x1f, 0x52, 0xce, ], [0x4c, 0x54, 0x42, 0x47, 0x1c, 0x53, 0x47, 0x44, 0x1f, 0x56, 0x47, 0x44, 0x44, 0x4b, 0x1d, 0x9f, 0xd, 0x44, 0x56, 0x1f, 0x18, 0x4e, 0x51, 0x4a, 0x1d, 0x1f, 0x56, 0x40, 0x51, 0x52, 0x1f, 0x40, 0x4d, 0xc3, 0x52, 0x4e, 0x1f, 0x4e, 0x4d, 0x1c, 0x56, 0x47, 0x48, 0x4b, 0x52, 0x53, 0x1f, 0x40, 0x4b, 0x4b, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x43, 0x4e, 0x4b, 0x4f, 0x47, 0x48, 0x4d, 0x52, 0x1f, 0x47, 0x40, 0x43, 0x9f, 0x44, 0x55, 0x44, 0x51, 0x1f, 0x43, 0x4e, 0x4d, 0x44, 0x1f, 0x56, 0x40, 0x52, 0x1f, 0x4c, 0x54, 0x42, 0xca, 0x40, 0x41, 0x4e, 0x54, 0x53, 0x1f, 0x48, 0x4d, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x56, 0x40, 0x53, 0x44, 0xd1, 0x47, 0x40, 0x55, 0x48, 0x4d, 0x46, 0x1f, 0x40, 0x1f, 0x46, 0x4e, 0x4e, 0x43, 0x9f, 0x53, 0x48, 0x4c, 0x44, 0x1b, 0x1f, 0x1, 0x54, 0x53, 0x9f, ], [0x42, 0x4e, 0x4d, 0x55, 0x44, 0x51, 0x52, 0x44, 0x4b, 0x58, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x43, 0x4e, 0x4b, 0x4f, 0x47, 0x48, 0x4d, 0x52, 0x1f, 0x47, 0x40, 0x43, 0x9f, 0x40, 0x4b, 0x56, 0x40, 0x58, 0x52, 0x1f, 0x41, 0x44, 0x4b, 0x48, 0x44, 0x55, 0x44, 0x43, 0x9f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x53, 0x47, 0x44, 0x58, 0x1f, 0x56, 0x44, 0x51, 0x44, 0x1f, 0x45, 0x40, 0xd1, 0x4c, 0x4e, 0x51, 0x44, 0x1f, 0x48, 0x4d, 0x53, 0x44, 0x4b, 0x4b, 0x48, 0x46, 0x44, 0x4d, 0x53, 0x9f, 0x53, 0x47, 0x40, 0x4d, 0x1f, 0x4c, 0x40, 0x4d, 0x1b, 0x45, 0x4e, 0x51, 0x9f, 0x4f, 0x51, 0x44, 0x42, 0x48, 0x52, 0x44, 0x4b, 0x58, 0x1f, 0x53, 0x47, 0x44, 0x1f, 0x52, 0x40, 0x4c, 0xc4, 0x51, 0x44, 0x40, 0x52, 0x4e, 0x4d, 0x52, 0x1b, 0x1f, 0x1c, 0x0, 0x43, 0x40, 0x4c, 0x52, 0x1f, 0x9f, ]],
|
||||
[[0x8, 0x53, 0x1f, 0x48, 0x52, 0x1f, 0x4a, 0x4d, 0x4e, 0x56, 0x4d, 0x1f, 0x53, 0x47, 0x40, 0x53, 0x9f, 0x53, 0x47, 0x44, 0x51, 0x44, 0x1f, 0x40, 0x51, 0x44, 0x1f, 0x40, 0x4d, 0x9f, 0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x1f, 0x4d, 0x54, 0x4c, 0x41, 0x44, 0x51, 0x1f, 0x4e, 0xc5, 0x56, 0x4e, 0x51, 0x4b, 0x43, 0x52, 0x1d, 0x1f, 0x52, 0x48, 0x4c, 0x4f, 0x4b, 0x58, 0x9f, 0x41, 0x44, 0x42, 0x40, 0x54, 0x52, 0x44, 0x1f, 0x53, 0x47, 0x44, 0x51, 0x44, 0x1f, 0x48, 0x52, 0x9f, 0x40, 0x4d, 0x1f, 0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x1f, 0x40, 0x4c, 0x4e, 0x54, 0x4d, 0xd3, 0x4e, 0x45, 0x1f, 0x52, 0x4f, 0x40, 0x42, 0x44, 0x1f, 0x45, 0x4e, 0x51, 0x1f, 0x53, 0x47, 0x44, 0x4c, 0x9f, 0x53, 0x4e, 0x1f, 0x41, 0x44, 0x1f, 0x48, 0x4d, 0x1b, 0x1f, 0x7, 0x4e, 0x56, 0x44, 0x55, 0x44, 0x51, 0x9d, ], [0x4d, 0x4e, 0x53, 0x1f, 0x44, 0x55, 0x44, 0x51, 0x58, 0x1f, 0x4e, 0x4d, 0x44, 0x1f, 0x4e, 0x45, 0x9f, 0x53, 0x47, 0x44, 0x4c, 0x1f, 0x48, 0x52, 0x1f, 0x48, 0x4d, 0x47, 0x40, 0x41, 0x48, 0x53, 0x44, 0x43, 0x9b, 0x13, 0x47, 0x44, 0x51, 0x44, 0x45, 0x4e, 0x51, 0x44, 0x1d, 0x1f, 0x53, 0x47, 0x44, 0x51, 0x44, 0x9f, 0x4c, 0x54, 0x52, 0x53, 0x1f, 0x41, 0x44, 0x1f, 0x40, 0x1f, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x9f, 0x4d, 0x54, 0x4c, 0x41, 0x44, 0x51, 0x1f, 0x4e, 0x45, 0x9f, 0x48, 0x4d, 0x47, 0x40, 0x41, 0x48, 0x53, 0x44, 0x43, 0x1f, 0x56, 0x4e, 0x51, 0x4b, 0x43, 0x52, 0x1b, 0x9f, 0x0, 0x4d, 0x58, 0x1f, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x44, 0x1f, 0x4d, 0x54, 0x4c, 0x41, 0x44, 0x51, 0x9f, 0x43, 0x48, 0x55, 0x48, 0x43, 0x44, 0x43, 0x1f, 0x41, 0x58, 0x9f, ], [0x48, 0x4d, 0x45, 0x48, 0x4d, 0x48, 0x53, 0x58, 0x1f, 0x48, 0x52, 0x1f, 0x40, 0x52, 0x9f, 0x4d, 0x44, 0x40, 0x51, 0x1f, 0x53, 0x4e, 0x1f, 0x4d, 0x4e, 0x53, 0x47, 0x48, 0x4d, 0x46, 0x1f, 0x40, 0xd2, 0x4c, 0x40, 0x4a, 0x44, 0x52, 0x1f, 0x4d, 0x4e, 0x1f, 0x4e, 0x43, 0x43, 0x52, 0x1d, 0x1f, 0x52, 0x4e, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x40, 0x55, 0x44, 0x51, 0x40, 0x46, 0x44, 0x9f, 0x4f, 0x4e, 0x4f, 0x54, 0x4b, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1f, 0x4e, 0x45, 0x1f, 0x40, 0x4b, 0x4b, 0x9f, 0x53, 0x47, 0x44, 0x1f, 0x4f, 0x4b, 0x40, 0x4d, 0x44, 0x53, 0x52, 0x1f, 0x48, 0x4d, 0x1f, 0x53, 0x47, 0xc4, 0x14, 0x4d, 0x48, 0x55, 0x44, 0x51, 0x52, 0x44, 0x1f, 0x42, 0x40, 0x4d, 0x1f, 0x41, 0x44, 0x9f, 0x52, 0x40, 0x48, 0x43, 0x1f, 0x53, 0x4e, 0x1f, 0x41, 0x44, 0x1f, 0x59, 0x44, 0x51, 0x4e, 0x1b, 0x9f, ], [0x5, 0x51, 0x4e, 0x4c, 0x1f, 0x53, 0x47, 0x48, 0x52, 0x1f, 0x48, 0x53, 0x9f, 0x45, 0x4e, 0x4b, 0x4b, 0x4e, 0x56, 0x52, 0x1f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4f, 0x4e, 0x4f, 0x54, 0x4b, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1f, 0x4e, 0x45, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x56, 0x47, 0x4e, 0x4b, 0x44, 0x1f, 0x14, 0x4d, 0x48, 0x55, 0x44, 0x51, 0x52, 0x44, 0x1f, 0x48, 0x52, 0x9f, 0x40, 0x4b, 0x52, 0x4e, 0x1f, 0x59, 0x44, 0x51, 0x4e, 0x1d, 0x1f, 0x40, 0x4d, 0x43, 0x9f, 0x53, 0x47, 0x40, 0x53, 0x1f, 0x40, 0x4d, 0x58, 0x1f, 0x4f, 0x44, 0x4e, 0x4f, 0x4b, 0x44, 0x9f, 0x58, 0x4e, 0x54, 0x1f, 0x4c, 0x40, 0x58, 0x1f, 0x4c, 0x44, 0x44, 0x53, 0x1f, 0x45, 0x51, 0x4e, 0x4c, 0x9f, 0x53, 0x48, 0x4c, 0x44, 0x1f, 0x53, 0x4e, 0x1f, 0x53, 0x48, 0x4c, 0x44, 0x1f, 0x40, 0x51, 0x44, 0x9f, ], [0x4c, 0x44, 0x51, 0x44, 0x4b, 0x58, 0x1f, 0x53, 0x47, 0x44, 0x9f, 0x4f, 0x51, 0x4e, 0x43, 0x54, 0x42, 0x53, 0x52, 0x1f, 0x4e, 0x45, 0x1f, 0x40, 0x9f, 0x43, 0x44, 0x51, 0x40, 0x4d, 0x46, 0x44, 0x43, 0x9f, 0x48, 0x4c, 0x40, 0x46, 0x48, 0x4d, 0x40, 0x53, 0x48, 0x4e, 0x4d, 0x1b, 0x9f, 0x1c, 0x0, 0x43, 0x40, 0x4c, 0x52, 0x1f, 0x9f, 0x9f, 0x9f, 0x9f, ]],
|
||||
|
|
|
@ -58,7 +58,7 @@ class BowserCastleDoors(Choice):
|
|||
Vanilla: Front and Back Doors behave as vanilla
|
||||
Fast: Both doors behave as the Back Door
|
||||
Slow: Both doors behave as the Front Door
|
||||
"Front Door" requires beating all 8 Rooms
|
||||
"Front Door" rooms depend on the `bowser_castle_rooms` option
|
||||
"Back Door" only requires going through the dark hallway to Bowser
|
||||
"""
|
||||
display_name = "Bowser Castle Doors"
|
||||
|
@ -68,6 +68,40 @@ class BowserCastleDoors(Choice):
|
|||
default = 0
|
||||
|
||||
|
||||
class BowserCastleRooms(Choice):
|
||||
"""
|
||||
How the rooms of Bowser's Castle Front Door behave
|
||||
Vanilla: You can choose which rooms to enter, as in vanilla
|
||||
Random Two Room: Two random rooms are chosen
|
||||
Random Five Room: Five random rooms are chosen
|
||||
Gauntlet: All eight rooms must be cleared
|
||||
Labyrinth: Which room leads to Bowser?
|
||||
"""
|
||||
display_name = "Bowser Castle Rooms"
|
||||
option_vanilla = 0
|
||||
option_random_two_room = 1
|
||||
option_random_five_room = 2
|
||||
option_gauntlet = 3
|
||||
option_labyrinth = 4
|
||||
default = 1
|
||||
|
||||
|
||||
class BossShuffle(Choice):
|
||||
"""
|
||||
How the rooms of Bowser's Castle Front Door behave
|
||||
None: Bosses are not shuffled
|
||||
Simple: Four Reznors and the seven Koopalings are shuffled around
|
||||
Full: Each boss location gets a fully random boss
|
||||
Singularity: One or two bosses are chosen and placed at every boss location
|
||||
"""
|
||||
display_name = "Boss Shuffle"
|
||||
option_none = 0
|
||||
option_simple = 1
|
||||
option_full = 2
|
||||
option_singularity = 3
|
||||
default = 0
|
||||
|
||||
|
||||
class LevelShuffle(Toggle):
|
||||
"""
|
||||
Whether levels are shuffled
|
||||
|
@ -75,6 +109,14 @@ class LevelShuffle(Toggle):
|
|||
display_name = "Level Shuffle"
|
||||
|
||||
|
||||
class ExcludeSpecialZone(Toggle):
|
||||
"""
|
||||
If active, this option will prevent any progression items from being placed in Special Zone levels.
|
||||
Additionally, if Level Shuffle is active, Special Zone levels will not be shuffled away from their vanilla tiles.
|
||||
"""
|
||||
display_name = "Exclude Special Zone"
|
||||
|
||||
|
||||
class SwapDonutGhostHouseExits(Toggle):
|
||||
"""
|
||||
If enabled, this option will swap which overworld direction the two exits of the level at the Donut Ghost House
|
||||
|
@ -148,6 +190,13 @@ class LiteratureTrapWeight(BaseTrapWeight):
|
|||
display_name = "Literature Trap Weight"
|
||||
|
||||
|
||||
class TimerTrapWeight(BaseTrapWeight):
|
||||
"""
|
||||
Likelihood of a receiving a trap which causes the timer to run low
|
||||
"""
|
||||
display_name = "Timer Trap Weight"
|
||||
|
||||
|
||||
class Autosave(DefaultOnToggle):
|
||||
"""
|
||||
Whether a save prompt will appear after every level
|
||||
|
@ -155,6 +204,25 @@ class Autosave(DefaultOnToggle):
|
|||
display_name = "Autosave"
|
||||
|
||||
|
||||
class EarlyClimb(Toggle):
|
||||
"""
|
||||
Force Climb to appear early in the seed as a local item.
|
||||
This is particularly useful to prevent BK when Level Shuffle is disabled
|
||||
"""
|
||||
display_name = "Early Climb"
|
||||
|
||||
|
||||
class OverworldSpeed(Choice):
|
||||
"""
|
||||
How fast Mario moves on the overworld
|
||||
"""
|
||||
display_name = "Overworld Speed"
|
||||
option_slow = 0
|
||||
option_vanilla = 1
|
||||
option_fast = 2
|
||||
default = 1
|
||||
|
||||
|
||||
class MusicShuffle(Choice):
|
||||
"""
|
||||
Music shuffle type
|
||||
|
@ -201,6 +269,13 @@ class BackgroundPaletteShuffle(Toggle):
|
|||
display_name = "Background Palette Shuffle"
|
||||
|
||||
|
||||
class OverworldPaletteShuffle(Toggle):
|
||||
"""
|
||||
Whether to shuffle overworld palettes
|
||||
"""
|
||||
display_name = "Overworld Palette Shuffle"
|
||||
|
||||
|
||||
class StartingLifeCount(Range):
|
||||
"""
|
||||
How many extra lives to start the game with
|
||||
|
@ -220,7 +295,10 @@ smw_options: typing.Dict[str, type(Option)] = {
|
|||
"percentage_of_yoshi_eggs": PercentageOfYoshiEggs,
|
||||
"dragon_coin_checks": DragonCoinChecks,
|
||||
"bowser_castle_doors": BowserCastleDoors,
|
||||
"bowser_castle_rooms": BowserCastleRooms,
|
||||
"level_shuffle": LevelShuffle,
|
||||
"exclude_special_zone": ExcludeSpecialZone,
|
||||
"boss_shuffle": BossShuffle,
|
||||
"swap_donut_gh_exits": SwapDonutGhostHouseExits,
|
||||
#"display_sent_item_popups": DisplaySentItemPopups,
|
||||
"display_received_item_popups": DisplayReceivedItemPopups,
|
||||
|
@ -228,10 +306,14 @@ smw_options: typing.Dict[str, type(Option)] = {
|
|||
"ice_trap_weight": IceTrapWeight,
|
||||
"stun_trap_weight": StunTrapWeight,
|
||||
"literature_trap_weight": LiteratureTrapWeight,
|
||||
"timer_trap_weight": TimerTrapWeight,
|
||||
"autosave": Autosave,
|
||||
"early_climb": EarlyClimb,
|
||||
"overworld_speed": OverworldSpeed,
|
||||
"music_shuffle": MusicShuffle,
|
||||
"mario_palette": MarioPalette,
|
||||
"foreground_palette_shuffle": ForegroundPaletteShuffle,
|
||||
"background_palette_shuffle": BackgroundPaletteShuffle,
|
||||
"overworld_palette_shuffle": OverworldPaletteShuffle,
|
||||
"starting_life_count": StartingLifeCount,
|
||||
}
|
||||
|
|
|
@ -11,14 +11,6 @@ def create_regions(world, player: int, active_locations):
|
|||
menu_region = create_region(world, player, active_locations, 'Menu', None)
|
||||
|
||||
yoshis_island_region = create_region(world, player, active_locations, LocationName.yoshis_island_region, None)
|
||||
donut_plains_region = create_region(world, player, active_locations, LocationName.donut_plains_region, None)
|
||||
vanilla_dome_region = create_region(world, player, active_locations, LocationName.vanilla_dome_region, None)
|
||||
twin_bridges_region = create_region(world, player, active_locations, LocationName.twin_bridges_region, None)
|
||||
forest_of_illusion_region = create_region(world, player, active_locations, LocationName.forest_of_illusion_region, None)
|
||||
chocolate_island_region = create_region(world, player, active_locations, LocationName.chocolate_island_region, None)
|
||||
valley_of_bowser_region = create_region(world, player, active_locations, LocationName.valley_of_bowser_region, None)
|
||||
star_road_region = create_region(world, player, active_locations, LocationName.star_road_region, None)
|
||||
special_zone_region = create_region(world, player, active_locations, LocationName.special_zone_region, None)
|
||||
|
||||
|
||||
yoshis_house_tile = create_region(world, player, active_locations, LocationName.yoshis_house_tile, None)
|
||||
|
@ -472,14 +464,6 @@ def create_regions(world, player: int, active_locations):
|
|||
world.regions += [
|
||||
menu_region,
|
||||
yoshis_island_region,
|
||||
donut_plains_region,
|
||||
vanilla_dome_region,
|
||||
twin_bridges_region,
|
||||
forest_of_illusion_region,
|
||||
chocolate_island_region,
|
||||
valley_of_bowser_region,
|
||||
star_road_region,
|
||||
special_zone_region,
|
||||
yoshis_house_tile,
|
||||
yoshis_house_region,
|
||||
yoshis_island_1_tile,
|
||||
|
@ -824,7 +808,7 @@ def create_regions(world, player: int, active_locations):
|
|||
(state.has(ItemName.yellow_switch_palace, player) or state.has(ItemName.red_switch_palace, player)))))
|
||||
add_location_to_region(world, player, active_locations, LocationName.chocolate_island_3_region, LocationName.chocolate_island_3_dragon)
|
||||
add_location_to_region(world, player, active_locations, LocationName.chocolate_island_4_region, LocationName.chocolate_island_4_dragon,
|
||||
lambda state: (state.has(ItemName.mario_run, player) and
|
||||
lambda state: (state.has(ItemName.p_switch, player) and
|
||||
state.has(ItemName.progressive_powerup, player, 3)))
|
||||
add_location_to_region(world, player, active_locations, LocationName.chocolate_island_5_region, LocationName.chocolate_island_5_dragon,
|
||||
lambda state: (state.has(ItemName.mario_swim, player) or
|
||||
|
@ -866,6 +850,8 @@ def connect_regions(world, player, level_to_tile_dict):
|
|||
names: typing.Dict[str, int] = {}
|
||||
|
||||
connect(world, player, names, "Menu", LocationName.yoshis_island_region)
|
||||
connect(world, player, names, LocationName.yoshis_island_region, LocationName.yoshis_house_tile)
|
||||
connect(world, player, names, LocationName.yoshis_house_tile, LocationName.donut_plains_top_secret)
|
||||
connect(world, player, names, LocationName.yoshis_island_region, LocationName.yoshis_island_1_tile)
|
||||
connect(world, player, names, LocationName.yoshis_island_region, LocationName.yoshis_island_2_tile)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Utils
|
||||
from worlds.Files import APDeltaPatch
|
||||
from .Aesthetics import generate_shuffled_header_data
|
||||
from .Levels import level_info_dict
|
||||
from .Aesthetics import generate_shuffled_header_data, generate_shuffled_ow_palettes
|
||||
from .Levels import level_info_dict, full_bowser_rooms, standard_bowser_rooms, submap_boss_rooms, ow_boss_rooms
|
||||
from .Names.TextBox import generate_goal_text, title_text_mapping, generate_text_box
|
||||
|
||||
USHASH = 'cdd3c8c37322978ca8669b34bc89c804'
|
||||
|
@ -36,18 +36,13 @@ item_rom_data = {
|
|||
0xBC000F: [0x1F27, 0x1, 0x1C], # Green Switch Palace
|
||||
0xBC0010: [0x1F2A, 0x1, 0x1C], # Red Switch Palace
|
||||
0xBC0011: [0x1F29, 0x1, 0x1C], # Blue Switch Palace
|
||||
|
||||
0xBC0013: [0x0086, 0x1, 0x0E], # Ice Trap
|
||||
0xBC0014: [0x18BD, 0x7F, 0x18], # Stun Trap
|
||||
}
|
||||
|
||||
music_rom_data = [
|
||||
|
||||
]
|
||||
|
||||
level_music_ids = [
|
||||
|
||||
]
|
||||
trap_rom_data = {
|
||||
0xBC0013: [0x0086, 0x1, 0x0E], # Ice Trap
|
||||
0xBC0014: [0x18BD, 0x7F, 0x18], # Stun Trap
|
||||
0xBC0016: [0x0F31, 0x1], # Timer Trap
|
||||
}
|
||||
|
||||
|
||||
class SMWDeltaPatch(APDeltaPatch):
|
||||
|
@ -728,6 +723,103 @@ def handle_swap_donut_gh_exits(rom):
|
|||
rom.write_bytes(0x26371, bytes([0x32]))
|
||||
|
||||
|
||||
def handle_bowser_rooms(rom, world, player):
|
||||
if world.bowser_castle_rooms[player] == "random_two_room":
|
||||
chosen_rooms = world.random.sample(standard_bowser_rooms, 2)
|
||||
|
||||
rom.write_byte(0x3A680, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A684, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A688, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A68C, chosen_rooms[0].roomID)
|
||||
|
||||
for i in range(1, len(chosen_rooms)):
|
||||
rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID)
|
||||
|
||||
rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD)
|
||||
|
||||
elif world.bowser_castle_rooms[player] == "random_five_room":
|
||||
chosen_rooms = world.random.sample(standard_bowser_rooms, 5)
|
||||
|
||||
rom.write_byte(0x3A680, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A684, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A688, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A68C, chosen_rooms[0].roomID)
|
||||
|
||||
for i in range(1, len(chosen_rooms)):
|
||||
rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID)
|
||||
|
||||
rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD)
|
||||
|
||||
elif world.bowser_castle_rooms[player] == "gauntlet":
|
||||
chosen_rooms = standard_bowser_rooms.copy()
|
||||
world.random.shuffle(chosen_rooms)
|
||||
|
||||
rom.write_byte(0x3A680, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A684, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A688, chosen_rooms[0].roomID)
|
||||
rom.write_byte(0x3A68C, chosen_rooms[0].roomID)
|
||||
|
||||
for i in range(1, len(chosen_rooms)):
|
||||
rom.write_byte(chosen_rooms[i-1].exitAddress, chosen_rooms[i].roomID)
|
||||
|
||||
rom.write_byte(chosen_rooms[len(chosen_rooms)-1].exitAddress, 0xBD)
|
||||
elif world.bowser_castle_rooms[player] == "labyrinth":
|
||||
bowser_rooms_copy = full_bowser_rooms.copy()
|
||||
|
||||
entrance_point = bowser_rooms_copy.pop(0)
|
||||
|
||||
world.random.shuffle(bowser_rooms_copy)
|
||||
|
||||
rom.write_byte(entrance_point.exitAddress, bowser_rooms_copy[0].roomID)
|
||||
for i in range(0, len(bowser_rooms_copy) - 1):
|
||||
rom.write_byte(bowser_rooms_copy[i].exitAddress, bowser_rooms_copy[i+1].roomID)
|
||||
|
||||
rom.write_byte(bowser_rooms_copy[len(bowser_rooms_copy)-1].exitAddress, 0xBD)
|
||||
|
||||
|
||||
def handle_boss_shuffle(rom, world, player):
|
||||
if world.boss_shuffle[player] == "simple":
|
||||
submap_boss_rooms_copy = submap_boss_rooms.copy()
|
||||
ow_boss_rooms_copy = ow_boss_rooms.copy()
|
||||
|
||||
world.random.shuffle(submap_boss_rooms_copy)
|
||||
world.random.shuffle(ow_boss_rooms_copy)
|
||||
|
||||
for i in range(len(submap_boss_rooms_copy)):
|
||||
rom.write_byte(submap_boss_rooms[i].exitAddress, submap_boss_rooms_copy[i].roomID)
|
||||
|
||||
for i in range(len(ow_boss_rooms_copy)):
|
||||
rom.write_byte(ow_boss_rooms[i].exitAddress, ow_boss_rooms_copy[i].roomID)
|
||||
|
||||
if ow_boss_rooms[i].exitAddressAlt is not None:
|
||||
rom.write_byte(ow_boss_rooms[i].exitAddressAlt, ow_boss_rooms_copy[i].roomID)
|
||||
|
||||
elif world.boss_shuffle[player] == "full":
|
||||
for i in range(len(submap_boss_rooms)):
|
||||
chosen_boss = world.random.choice(submap_boss_rooms)
|
||||
rom.write_byte(submap_boss_rooms[i].exitAddress, chosen_boss.roomID)
|
||||
|
||||
for i in range(len(ow_boss_rooms)):
|
||||
chosen_boss = world.random.choice(ow_boss_rooms)
|
||||
rom.write_byte(ow_boss_rooms[i].exitAddress, chosen_boss.roomID)
|
||||
|
||||
if ow_boss_rooms[i].exitAddressAlt is not None:
|
||||
rom.write_byte(ow_boss_rooms[i].exitAddressAlt, chosen_boss.roomID)
|
||||
|
||||
elif world.boss_shuffle[player] == "singularity":
|
||||
chosen_submap_boss = world.random.choice(submap_boss_rooms)
|
||||
chosen_ow_boss = world.random.choice(ow_boss_rooms)
|
||||
|
||||
for i in range(len(submap_boss_rooms)):
|
||||
rom.write_byte(submap_boss_rooms[i].exitAddress, chosen_submap_boss.roomID)
|
||||
|
||||
for i in range(len(ow_boss_rooms)):
|
||||
rom.write_byte(ow_boss_rooms[i].exitAddress, chosen_ow_boss.roomID)
|
||||
|
||||
if ow_boss_rooms[i].exitAddressAlt is not None:
|
||||
rom.write_byte(ow_boss_rooms[i].exitAddressAlt, chosen_ow_boss.roomID)
|
||||
|
||||
|
||||
def patch_rom(world, rom, player, active_level_dict):
|
||||
local_random = world.slot_seeds[player]
|
||||
|
||||
|
@ -739,18 +831,8 @@ def patch_rom(world, rom, player, active_level_dict):
|
|||
intro_text = generate_text_box("Bowser has stolen all of Mario's abilities. Can you help Mario travel across Dinosaur land to get them back and save the Princess from him?")
|
||||
rom.write_bytes(0x2A5D9, intro_text)
|
||||
|
||||
# Force all 8 Bowser's Castle Rooms
|
||||
rom.write_byte(0x3A680, 0xD4)
|
||||
rom.write_byte(0x3A684, 0xD4)
|
||||
rom.write_byte(0x3A688, 0xD4)
|
||||
rom.write_byte(0x3A68C, 0xD4)
|
||||
rom.write_byte(0x3A705, 0xD3)
|
||||
rom.write_byte(0x3A763, 0xD2)
|
||||
rom.write_byte(0x3A800, 0xD1)
|
||||
rom.write_byte(0x3A83D, 0xCF)
|
||||
rom.write_byte(0x3A932, 0xCE)
|
||||
rom.write_byte(0x3A9E1, 0xCD)
|
||||
rom.write_byte(0x3AA75, 0xCC)
|
||||
handle_bowser_rooms(rom, world, player)
|
||||
handle_boss_shuffle(rom, world, player)
|
||||
|
||||
# Prevent Title Screen Deaths
|
||||
rom.write_byte(0x1C6A, 0x80)
|
||||
|
@ -805,6 +887,11 @@ def patch_rom(world, rom, player, active_level_dict):
|
|||
if world.autosave[player]:
|
||||
rom.write_bytes(0x20F93, bytearray([0x00]))
|
||||
|
||||
if world.overworld_speed[player] == "fast":
|
||||
rom.write_bytes(0x21414, bytearray([0x20, 0x10]))
|
||||
elif world.overworld_speed[player] == "slow":
|
||||
rom.write_bytes(0x21414, bytearray([0x05, 0x05]))
|
||||
|
||||
# Starting Life Count
|
||||
rom.write_bytes(0x1E25, bytearray([world.starting_life_count[player].value - 1]))
|
||||
|
||||
|
@ -835,6 +922,8 @@ def patch_rom(world, rom, player, active_level_dict):
|
|||
if world.music_shuffle[player] != "none":
|
||||
handle_music_shuffle(rom, world, player)
|
||||
|
||||
generate_shuffled_ow_palettes(rom, world, player)
|
||||
|
||||
generate_shuffled_header_data(rom, world, player)
|
||||
|
||||
if world.swap_donut_gh_exits[player]:
|
||||
|
|
|
@ -5,12 +5,12 @@ import threading
|
|||
|
||||
from BaseClasses import Item, MultiWorld, Tutorial, ItemClassification
|
||||
from .Items import SMWItem, ItemData, item_table
|
||||
from .Locations import SMWLocation, all_locations, setup_locations
|
||||
from .Locations import SMWLocation, all_locations, setup_locations, special_zone_level_names, special_zone_dragon_coin_names
|
||||
from .Options import smw_options
|
||||
from .Regions import create_regions, connect_regions
|
||||
from .Levels import full_level_list, generate_level_list, location_id_to_level_id
|
||||
from .Rules import set_rules
|
||||
from ..generic.Rules import add_rule
|
||||
from ..generic.Rules import add_rule, exclusion_rules
|
||||
from .Names import ItemName, LocationName
|
||||
from .Client import SMWSNIClient
|
||||
from ..AutoWorld import WebWorld, World
|
||||
|
@ -41,7 +41,7 @@ class SMWWorld(World):
|
|||
game: str = "Super Mario World"
|
||||
option_definitions = smw_options
|
||||
topology_present = False
|
||||
data_version = 2
|
||||
data_version = 3
|
||||
required_client_version = (0, 3, 5)
|
||||
|
||||
item_name_to_id = {name: data.code for name, data in item_table.items()}
|
||||
|
@ -74,6 +74,10 @@ class SMWWorld(World):
|
|||
|
||||
return slot_data
|
||||
|
||||
def generate_early(self):
|
||||
if self.multiworld.early_climb[self.player]:
|
||||
self.multiworld.local_early_items[self.player][ItemName.mario_climb] = 1
|
||||
|
||||
def generate_basic(self):
|
||||
itempool: typing.List[SMWItem] = []
|
||||
|
||||
|
@ -89,6 +93,15 @@ class SMWWorld(World):
|
|||
add_rule(self.multiworld.get_region(LocationName.chocolate_island_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 5))
|
||||
add_rule(self.multiworld.get_region(LocationName.valley_of_bowser_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 6))
|
||||
|
||||
if self.multiworld.exclude_special_zone[self.player]:
|
||||
exclusion_pool = set()
|
||||
if self.multiworld.dragon_coin_checks[self.player]:
|
||||
exclusion_pool.update(special_zone_level_names)
|
||||
exclusion_pool.update(special_zone_dragon_coin_names)
|
||||
elif self.multiworld.number_of_yoshi_eggs[self.player].value <= 72:
|
||||
exclusion_pool.update(special_zone_level_names)
|
||||
exclusion_rules(self.multiworld, self.player, exclusion_pool)
|
||||
|
||||
total_required_locations = 96
|
||||
if self.multiworld.dragon_coin_checks[self.player]:
|
||||
total_required_locations += 49
|
||||
|
@ -120,6 +133,7 @@ class SMWWorld(World):
|
|||
trap_weights += ([ItemName.ice_trap] * self.multiworld.ice_trap_weight[self.player].value)
|
||||
trap_weights += ([ItemName.stun_trap] * self.multiworld.stun_trap_weight[self.player].value)
|
||||
trap_weights += ([ItemName.literature_trap] * self.multiworld.literature_trap_weight[self.player].value)
|
||||
trap_weights += ([ItemName.timer_trap] * self.multiworld.timer_trap_weight[self.player].value)
|
||||
trap_count = 0 if (len(trap_weights) == 0) else math.ceil(junk_count * (self.multiworld.trap_fill_percentage[self.player].value / 100.0))
|
||||
junk_count -= trap_count
|
||||
|
||||
|
|
Loading…
Reference in New Issue