Initial Follower Shuffle Implementation

This commit is contained in:
codemann8
2025-04-30 06:41:43 -05:00
parent 267552bfee
commit fcaaab30a4
29 changed files with 316 additions and 50 deletions

View File

@@ -178,8 +178,9 @@ def boss_writes(world, player, rom):
remove_shell_from_boss_room(data_tables, dungeon.name, level, 0xF95)
if boss.name != 'Blind' and dungeon.name == 'Thieves Town' and level is None:
rom.write_byte(snes_to_pc(0x368101), 1) # set blind boss door flag
# maiden is deleted
del data_tables.uw_enemy_table.room_map[0x45][0]
if not world.shuffle_followers[player]:
# maiden is deleted
del data_tables.uw_enemy_table.room_map[0x45][0]
if not arrghus_can_swim and water_tiles_on:
remove_water_tiles(data_tables)

View File

@@ -3,7 +3,7 @@ from Utils import snes_to_pc
from source.dungeon.EnemyList import SpriteType, EnemySprite, sprite_translation
from source.dungeon.RoomList import Room010C
from source.enemizer.SpriteSheets import sub_group_choices
from source.enemizer.SpriteSheets import sub_group_choices, sheets_with_free_gfx
from source.enemizer.SpriteSheets import randomize_underworld_sprite_sheets, randomize_overworld_sprite_sheets
from source.enemizer.TilePattern import tile_patterns
@@ -314,6 +314,21 @@ def randomize_underworld_rooms(data_tables, world, player, custom_uw):
done = False
while not done:
chosen_sheet = random.choice(candidate_sheets)
if world.shuffle_followers[player] and room_id in [0x80, 0x45]:
initial_chosen = chosen_sheet
while True:
candidate_sheets.remove(chosen_sheet)
free_gfx = next((sheets_with_free_gfx[s] for s in chosen_sheet.sub_groups if s in sheets_with_free_gfx), None)
if free_gfx:
data_tables.room_headers[room_id].free_gfx = free_gfx
break
elif len(candidate_sheets):
chosen_sheet = random.choice(candidate_sheets)
else:
chosen_sheet = initial_chosen
# TODO: This shouldn't happen for the current use case
# May need to limit the candidate_sprites below if needing gfx slots
break
data_tables.room_headers[room_id].sprite_sheet = chosen_sheet.id - 0x40
candidate_sprites = get_possible_enemy_sprites(room_id, chosen_sheet, uw_candidates, data_tables)
randomized = True

View File

@@ -476,6 +476,34 @@ required_boss_sheets = {EnemySprite.ArmosKnight: 9, EnemySprite.Lanmolas: 11, En
EnemySprite.Blind: 32, EnemySprite.Kholdstare: 22, EnemySprite.Vitreous: 22,
EnemySprite.TrinexxRockHead: 23}
sheets_with_free_gfx = {
# intended for identifying gfx slots on each sheet that are unused during general enemization
# (ie. Catfish gfx unused when used elsewhere other than the usual Catfish screen)
# TODO: Could also provide sprite ID/s of replaced gfx slots indicated to be used as verification
0x0E: [0x08, 0x0C],
0x10: [0xCC, 0xCE, 0xEC, 0xEE],
0x11: [0xEA, 0xEC, 0xEE],
0x12: [0x88, 0x8A, 0xAA, 0x8C, 0xAC, 0x8E, 0xAE],
0x13: [0xA2, 0xA4],
0x14: [0xC0, 0xC2, 0xC4, 0xE0, 0xE2],
0x15: [0xC8, 0xEE],
0x18: [0x86, 0x8C, 0x8E],
0x19: [0xCE, 0xEC, 0xEE],
0x1C: [0xA0, 0xAC, 0xAE],
0x22: [0x8C, 0x8E, 0xAA, 0xAC, 0xAE],
0x24: [0xAC, 0xAE],
0x26: [0xA6, 0xA8, 0xAA, 0xAC, 0xAE],
0x27: [0x84, 0xA4],
0x29: [0x82, 0x84],
0x2A: [0x80, 0x82, 0x84, 0x86, 0x88],
0x2E: [0x80, 0x82, 0x84, 0x86, 0x88],
0x2F: [0x2C, 0x0A, 0x0C, 0x0E, 0x2E, 0x24],
0x36: [0xE7, 0xE9, 0xEB, 0xED, 0xC7, 0xC9, 0xCB, 0xCD],
0x48: [0x2B, 0x2D],
0x52: [0xE8, 0xC6, 0xC8, 0xCE, 0xEE, 0xCA, 0xCC, 0xEA],
0x53: [0xE8, 0xEA, 0xCA, 0xCC, 0xC6, 0xC8]
}
class SpriteSheet:
def __init__(self, id, default_sub_groups):