Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
34b04179ce
4
Main.py
4
Main.py
|
@ -77,7 +77,7 @@ def main(args, seed=None):
|
|||
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
||||
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
||||
|
||||
world.rom_seeds = {player: world.random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
||||
world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)}
|
||||
|
||||
logger.info('ALttP Berserker\'s Multiworld Version %s - Seed: %s\n', __version__, world.seed)
|
||||
|
||||
|
@ -199,7 +199,7 @@ def main(args, seed=None):
|
|||
|
||||
apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
|
||||
args.fastmenu[player], args.disablemusic[player], args.sprite[player],
|
||||
args.ow_palettes[player], args.uw_palettes[player])
|
||||
args.ow_palettes[player], args.uw_palettes[player], world, player)
|
||||
|
||||
mcsb_name = ''
|
||||
if all([world.mapshuffle[player], world.compassshuffle[player], world.keyshuffle[player],
|
||||
|
|
102
Rom.py
102
Rom.py
|
@ -236,9 +236,8 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
|||
'BeesLevel': 0,
|
||||
'RandomizeTileTrapPattern': world.enemy_shuffle[player] == 'chaos',
|
||||
'RandomizeTileTrapFloorTile': False,
|
||||
'AllowKillableThief': bool(world.random.randint(0, 1)) if 'thieves' in world.enemy_shuffle[player] else
|
||||
'AllowKillableThief': bool(world.rom_seeds[player].randint(0, 1)) if 'thieves' in world.enemy_shuffle[player] else
|
||||
world.enemy_shuffle[player] != 'none',
|
||||
# TODO: this is currently non-deterministic due to being called in a thread
|
||||
'RandomizeSpriteOnHit': random_sprite_on_hit,
|
||||
'DebugMode': False,
|
||||
'DebugForceEnemy': False,
|
||||
|
@ -276,7 +275,7 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
|||
|
||||
subprocess.check_call([os.path.abspath(enemizercli),
|
||||
'--rom', randopatch_path,
|
||||
'--seed', str(world.rom_seeds[player]),
|
||||
'--seed', str(world.rom_seeds[player].randint(0, 999999999)),
|
||||
'--binary',
|
||||
'--enemizer', options_path,
|
||||
'--output', enemizer_output_path],
|
||||
|
@ -290,7 +289,7 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
|||
if sprites:
|
||||
while len(sprites) < 32:
|
||||
sprites.extend(sprites)
|
||||
world.random.shuffle(sprites)
|
||||
world.rom_seeds[player].shuffle(sprites)
|
||||
|
||||
for i, path in enumerate(sprites[:32]):
|
||||
sprite = Sprite(path)
|
||||
|
@ -317,11 +316,11 @@ def _populate_sprite_table():
|
|||
if sprite.valid:
|
||||
_sprite_table[sprite.name.lower()] = filepath
|
||||
|
||||
def get_sprite_from_name(name):
|
||||
def get_sprite_from_name(name, local_random=random):
|
||||
_populate_sprite_table()
|
||||
name = name.lower()
|
||||
if name in ['random', 'randomonhit']:
|
||||
return Sprite(random.choice(list(_sprite_table.values())))
|
||||
return Sprite(local_random.choice(list(_sprite_table.values())))
|
||||
return Sprite(_sprite_table[name]) if name in _sprite_table else None
|
||||
|
||||
class Sprite(object):
|
||||
|
@ -483,7 +482,7 @@ class Sprite(object):
|
|||
return array_chunk(palette_as_colors, 15)
|
||||
|
||||
def patch_rom(world, rom, player, team, enemized):
|
||||
local_random = random.Random(world.rom_seeds[player])
|
||||
local_random = world.rom_seeds[player]
|
||||
|
||||
# progressive bow silver arrow hint hack
|
||||
prog_bow_locs = world.find_items('Progressive Bow', player)
|
||||
|
@ -1365,9 +1364,10 @@ def hud_format_text(text):
|
|||
return output[:32]
|
||||
|
||||
|
||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, ow_palettes, uw_palettes):
|
||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, ow_palettes, uw_palettes, world=None, player=1):
|
||||
local_random = random if not world else world.rom_seeds[player]
|
||||
if sprite and not isinstance(sprite, Sprite):
|
||||
sprite = Sprite(sprite) if os.path.isfile(sprite) else get_sprite_from_name(sprite)
|
||||
sprite = Sprite(sprite) if os.path.isfile(sprite) else get_sprite_from_name(sprite, local_random)
|
||||
|
||||
# enable instant item menu
|
||||
if fastmenu == 'instant':
|
||||
|
@ -1405,7 +1405,7 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
|||
|
||||
# set heart color
|
||||
if color == 'random':
|
||||
color = random.choice(['red', 'blue', 'green', 'yellow'])
|
||||
color = local_random.choice(['red', 'blue', 'green', 'yellow'])
|
||||
rom.write_byte(0x6FA1E, {'red': 0x24, 'blue': 0x2C, 'green': 0x3C, 'yellow': 0x28}[color])
|
||||
rom.write_byte(0x6FA20, {'red': 0x24, 'blue': 0x2C, 'green': 0x3C, 'yellow': 0x28}[color])
|
||||
rom.write_byte(0x6FA22, {'red': 0x24, 'blue': 0x2C, 'green': 0x3C, 'yellow': 0x28}[color])
|
||||
|
@ -1424,13 +1424,13 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
|||
|
||||
default_ow_palettes(rom)
|
||||
if ow_palettes == 'random':
|
||||
randomize_ow_palettes(rom)
|
||||
randomize_ow_palettes(rom, local_random)
|
||||
elif ow_palettes == 'blackout':
|
||||
blackout_ow_palettes(rom)
|
||||
|
||||
default_uw_palettes(rom)
|
||||
if uw_palettes == 'random':
|
||||
randomize_uw_palettes(rom)
|
||||
randomize_uw_palettes(rom, local_random)
|
||||
elif uw_palettes == 'blackout':
|
||||
blackout_uw_palettes(rom)
|
||||
|
||||
|
@ -1460,11 +1460,11 @@ def default_ow_palettes(rom):
|
|||
for address in [0x067FB4, 0x067F94, 0x067FC6, 0x067FE6, 0x067FE1, 0x05FEA9, 0x05FEB3]:
|
||||
rom.write_bytes(address, rom.orig_buffer[address:address+2])
|
||||
|
||||
def randomize_ow_palettes(rom):
|
||||
def randomize_ow_palettes(rom, local_random):
|
||||
grass, grass2, grass3, dirt, dirt2, water, clouds, dwdirt,\
|
||||
dwgrass, dwwater, dwdmdirt, dwdmgrass, dwdmclouds1, dwdmclouds2 = [[random.randint(60, 215) for _ in range(3)] for _ in range(14)]
|
||||
dwtree = [c + random.randint(-20, 10) for c in dwgrass]
|
||||
treeleaf = [c + random.randint(-20, 10) for c in grass]
|
||||
dwgrass, dwwater, dwdmdirt, dwdmgrass, dwdmclouds1, dwdmclouds2 = [[local_random.randint(60, 215) for _ in range(3)] for _ in range(14)]
|
||||
dwtree = [c + local_random.randint(-20, 10) for c in dwgrass]
|
||||
treeleaf = [c + local_random.randint(-20, 10) for c in grass]
|
||||
|
||||
patches = {0x067FB4: (grass, 0), 0x067F94: (grass, 0), 0x067FC6: (grass, 0), 0x067FE6: (grass, 0), 0x067FE1: (grass, 3), 0x05FEA9: (grass, 0), 0x05FEB3: (dwgrass, 1),
|
||||
0x0DD4AC: (grass, 2), 0x0DE6DE: (grass2, 2), 0x0DE6E0: (grass2, 1), 0x0DD4AE: (grass2, 1), 0x0DE9FA: (grass2, 1), 0x0DEA0E: (grass2, 1), 0x0DE9FE: (grass2, 0),
|
||||
|
@ -1518,9 +1518,9 @@ def default_uw_palettes(rom):
|
|||
return
|
||||
rom.write_bytes(0xDD734, rom.orig_buffer[0xDD734:0xDE544])
|
||||
|
||||
def randomize_uw_palettes(rom):
|
||||
def randomize_uw_palettes(rom, local_random):
|
||||
for dungeon in range(20):
|
||||
wall, pot, chest, floor1, floor2, floor3 = [[random.randint(60, 240) for _ in range(3)] for _ in range(6)]
|
||||
wall, pot, chest, floor1, floor2, floor3 = [[local_random.randint(60, 240) for _ in range(3)] for _ in range(6)]
|
||||
|
||||
for i in range(5):
|
||||
shade = 10 - (i * 2)
|
||||
|
@ -1579,6 +1579,8 @@ def write_string_to_rom(rom, target, string):
|
|||
|
||||
|
||||
def write_strings(rom, world, player, team):
|
||||
local_random = world.rom_seeds[player]
|
||||
|
||||
tt = TextTable()
|
||||
tt.removeUnwantedText()
|
||||
|
||||
|
@ -1607,9 +1609,9 @@ def write_strings(rom, world, player, team):
|
|||
if world.hints[player]:
|
||||
tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles can have hints!'
|
||||
hint_locations = HintLocations.copy()
|
||||
world.random.shuffle(hint_locations)
|
||||
local_random.shuffle(hint_locations)
|
||||
all_entrances = [entrance for entrance in world.get_entrances() if entrance.player == player]
|
||||
world.random.shuffle(all_entrances)
|
||||
local_random.shuffle(all_entrances)
|
||||
|
||||
#First we take care of the one inconvenient dungeon in the appropriately simple shuffles.
|
||||
entrances_to_hint = {}
|
||||
|
@ -1684,12 +1686,12 @@ def write_strings(rom, world, player, team):
|
|||
locations_to_hint = InconvenientLocations.copy()
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
locations_to_hint.extend(InconvenientVanillaLocations)
|
||||
world.random.shuffle(locations_to_hint)
|
||||
local_random.shuffle(locations_to_hint)
|
||||
hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 5
|
||||
del locations_to_hint[hint_count:]
|
||||
for location in locations_to_hint:
|
||||
if location == 'Swamp Left':
|
||||
if world.random.randint(0, 1) == 0:
|
||||
if local_random.randint(0, 1) == 0:
|
||||
first_item = hint_text(world.get_location('Swamp Palace - West Chest', player).item)
|
||||
second_item = hint_text(world.get_location('Swamp Palace - Big Key Chest', player).item)
|
||||
else:
|
||||
|
@ -1698,7 +1700,7 @@ def write_strings(rom, world, player, team):
|
|||
this_hint = ('The westmost chests in Swamp Palace contain ' + first_item + ' and ' + second_item + '.')
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Mire Left':
|
||||
if world.random.randint(0, 1) == 0:
|
||||
if local_random.randint(0, 1) == 0:
|
||||
first_item = hint_text(world.get_location('Misery Mire - Compass Chest', player).item)
|
||||
second_item = hint_text(world.get_location('Misery Mire - Big Key Chest', player).item)
|
||||
else:
|
||||
|
@ -1737,12 +1739,12 @@ def write_strings(rom, world, player, team):
|
|||
items_to_hint.extend(SmallKeys)
|
||||
if world.bigkeyshuffle[player]:
|
||||
items_to_hint.extend(BigKeys)
|
||||
world.random.shuffle(items_to_hint)
|
||||
local_random.shuffle(items_to_hint)
|
||||
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 8
|
||||
while hint_count > 0:
|
||||
this_item = items_to_hint.pop(0)
|
||||
this_location = world.find_items(this_item, player)
|
||||
world.random.shuffle(this_location)
|
||||
local_random.shuffle(this_location)
|
||||
#This looks dumb but prevents hints for Skull Woods Pinball Room's key safely with any item pool.
|
||||
if this_location:
|
||||
if this_location[0].name == 'Skull Woods - Pinball Room':
|
||||
|
@ -1754,7 +1756,7 @@ def write_strings(rom, world, player, team):
|
|||
|
||||
# All remaining hint slots are filled with junk hints. It is done this way to ensure the same junk hint isn't selected twice.
|
||||
junk_hints = junk_texts.copy()
|
||||
world.random.shuffle(junk_hints)
|
||||
local_random.shuffle(junk_hints)
|
||||
for location in hint_locations:
|
||||
tt[location] = junk_hints.pop(0)
|
||||
|
||||
|
@ -1762,7 +1764,7 @@ def write_strings(rom, world, player, team):
|
|||
|
||||
|
||||
silverarrows = world.find_items('Silver Bow', player)
|
||||
world.random.shuffle(silverarrows)
|
||||
local_random.shuffle(silverarrows)
|
||||
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
||||
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||
|
@ -1776,7 +1778,7 @@ def write_strings(rom, world, player, team):
|
|||
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||
|
||||
if any(prog_bow_locs):
|
||||
silverarrow_hint = (' %s?' % hint_text(world.random.choice(prog_bow_locs)).replace('Ganon\'s',
|
||||
silverarrow_hint = (' %s?' % hint_text(local_random.choice(prog_bow_locs)).replace('Ganon\'s',
|
||||
'my')) if progressive_silvers else '?\nI think not!'
|
||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||
|
||||
|
@ -1798,13 +1800,13 @@ def write_strings(rom, world, player, team):
|
|||
if world.goal[player] in ['dungeons']:
|
||||
tt['sign_ganon'] = 'You need to complete all the dungeons.'
|
||||
|
||||
tt['uncle_leaving_text'] = Uncle_texts[world.random.randint(0, len(Uncle_texts) - 1)]
|
||||
tt['end_triforce'] = "{NOBORDER}\n" + Triforce_texts[world.random.randint(0, len(Triforce_texts) - 1)]
|
||||
tt['bomb_shop_big_bomb'] = BombShop2_texts[world.random.randint(0, len(BombShop2_texts) - 1)]
|
||||
tt['uncle_leaving_text'] = Uncle_texts[local_random.randint(0, len(Uncle_texts) - 1)]
|
||||
tt['end_triforce'] = "{NOBORDER}\n" + Triforce_texts[local_random.randint(0, len(Triforce_texts) - 1)]
|
||||
tt['bomb_shop_big_bomb'] = BombShop2_texts[local_random.randint(0, len(BombShop2_texts) - 1)]
|
||||
|
||||
# this is what shows after getting the green pendant item in rando
|
||||
tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[world.random.randint(0, len(Sahasrahla2_texts) - 1)]
|
||||
tt['blind_by_the_light'] = Blind_texts[world.random.randint(0, len(Blind_texts) - 1)]
|
||||
tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[local_random.randint(0, len(Sahasrahla2_texts) - 1)]
|
||||
tt['blind_by_the_light'] = Blind_texts[local_random.randint(0, len(Blind_texts) - 1)]
|
||||
|
||||
if world.goal[player] in ['triforcehunt', 'localtriforcehunt']:
|
||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
|
||||
|
@ -1821,7 +1823,7 @@ def write_strings(rom, world, player, team):
|
|||
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
||||
tt['sign_ganon'] = 'You need to get to the pedestal... Ganon is invincible!'
|
||||
else:
|
||||
tt['ganon_fall_in'] = Ganon1_texts[world.random.randint(0, len(Ganon1_texts) - 1)]
|
||||
tt['ganon_fall_in'] = Ganon1_texts[local_random.randint(0, len(Ganon1_texts) - 1)]
|
||||
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
|
||||
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
|
||||
if world.goal[player] == 'ganontriforcehunt' and world.players > 1:
|
||||
|
@ -1829,7 +1831,7 @@ def write_strings(rom, world, player, team):
|
|||
elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']:
|
||||
tt['sign_ganon'] = 'You need to find %d Triforce pieces to defeat Ganon.' % world.treasure_hunt_count[player]
|
||||
|
||||
tt['kakariko_tavern_fisherman'] = TavernMan_texts[world.random.randint(0, len(TavernMan_texts) - 1)]
|
||||
tt['kakariko_tavern_fisherman'] = TavernMan_texts[local_random.randint(0, len(TavernMan_texts) - 1)]
|
||||
|
||||
pedestalitem = world.get_location('Master Sword Pedestal', player).item
|
||||
pedestal_text = 'Some Hot Air' if pedestalitem is None else hint_text(pedestalitem, True) if pedestalitem.pedestal_hint_text is not None else 'Unknown Item'
|
||||
|
@ -1860,38 +1862,38 @@ def write_strings(rom, world, player, team):
|
|||
credits = Credits()
|
||||
|
||||
sickkiditem = world.get_location('Sick Kid', player).item
|
||||
sickkiditem_text = world.random.choice(
|
||||
sickkiditem_text = local_random.choice(
|
||||
SickKid_texts) if sickkiditem is None or sickkiditem.sickkid_credit_text is None else sickkiditem.sickkid_credit_text
|
||||
|
||||
zoraitem = world.get_location('King Zora', player).item
|
||||
zoraitem_text = world.random.choice(
|
||||
zoraitem_text = local_random.choice(
|
||||
Zora_texts) if zoraitem is None or zoraitem.zora_credit_text is None else zoraitem.zora_credit_text
|
||||
|
||||
magicshopitem = world.get_location('Potion Shop', player).item
|
||||
magicshopitem_text = world.random.choice(
|
||||
magicshopitem_text = local_random.choice(
|
||||
MagicShop_texts) if magicshopitem is None or magicshopitem.magicshop_credit_text is None else magicshopitem.magicshop_credit_text
|
||||
|
||||
fluteboyitem = world.get_location('Flute Spot', player).item
|
||||
fluteboyitem_text = world.random.choice(
|
||||
fluteboyitem_text = local_random.choice(
|
||||
FluteBoy_texts) if fluteboyitem is None or fluteboyitem.fluteboy_credit_text is None else fluteboyitem.fluteboy_credit_text
|
||||
|
||||
credits.update_credits_line('castle', 0, world.random.choice(KingsReturn_texts))
|
||||
credits.update_credits_line('sanctuary', 0, world.random.choice(Sanctuary_texts))
|
||||
credits.update_credits_line('castle', 0, local_random.choice(KingsReturn_texts))
|
||||
credits.update_credits_line('sanctuary', 0, local_random.choice(Sanctuary_texts))
|
||||
|
||||
credits.update_credits_line('kakariko', 0,
|
||||
world.random.choice(Kakariko_texts).format(world.random.choice(Sahasrahla_names)))
|
||||
credits.update_credits_line('desert', 0, world.random.choice(DesertPalace_texts))
|
||||
credits.update_credits_line('hera', 0, world.random.choice(MountainTower_texts))
|
||||
credits.update_credits_line('house', 0, world.random.choice(LinksHouse_texts))
|
||||
local_random.choice(Kakariko_texts).format(local_random.choice(Sahasrahla_names)))
|
||||
credits.update_credits_line('desert', 0, local_random.choice(DesertPalace_texts))
|
||||
credits.update_credits_line('hera', 0, local_random.choice(MountainTower_texts))
|
||||
credits.update_credits_line('house', 0, local_random.choice(LinksHouse_texts))
|
||||
credits.update_credits_line('zora', 0, zoraitem_text)
|
||||
credits.update_credits_line('witch', 0, magicshopitem_text)
|
||||
credits.update_credits_line('lumberjacks', 0, world.random.choice(Lumberjacks_texts))
|
||||
credits.update_credits_line('lumberjacks', 0, local_random.choice(Lumberjacks_texts))
|
||||
credits.update_credits_line('grove', 0, fluteboyitem_text)
|
||||
credits.update_credits_line('well', 0, world.random.choice(WishingWell_texts))
|
||||
credits.update_credits_line('smithy', 0, world.random.choice(Blacksmiths_texts))
|
||||
credits.update_credits_line('well', 0, local_random.choice(WishingWell_texts))
|
||||
credits.update_credits_line('smithy', 0, local_random.choice(Blacksmiths_texts))
|
||||
credits.update_credits_line('kakariko2', 0, sickkiditem_text)
|
||||
credits.update_credits_line('bridge', 0, world.random.choice(DeathMountain_texts))
|
||||
credits.update_credits_line('woods', 0, world.random.choice(LostWoods_texts))
|
||||
credits.update_credits_line('bridge', 0, local_random.choice(DeathMountain_texts))
|
||||
credits.update_credits_line('woods', 0, local_random.choice(LostWoods_texts))
|
||||
credits.update_credits_line('pedestal', 0, pedestal_credit_text)
|
||||
|
||||
(pointers, data) = credits.get_bytes()
|
||||
|
|
Loading…
Reference in New Issue