Fix random weapons for Standard Mode
Now works roughly like VT, except that swords are somwhat more common and bombs-only escape is not supported (because I don't want to make 'Bombs (10)' an advancement item) Swordless Standard Mode should also work now Assured and Vanilla weapons still need to be implemented.
This commit is contained in:
parent
ef7c3d4f06
commit
b8ea2eb4b1
20
ItemList.py
20
ItemList.py
|
@ -387,13 +387,6 @@ def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, r
|
|||
|
||||
if swords == 'swordless':
|
||||
pool.extend(diff.swordless)
|
||||
elif mode == 'standard':
|
||||
if want_progressives():
|
||||
placed_items.append(('Link\'s Uncle', 'Progressive Sword'))
|
||||
pool.extend(diff.progressivesword)
|
||||
else:
|
||||
placed_items.append(('Link\'s Uncle', 'Fighter Sword'))
|
||||
pool.extend(diff.basicsword)
|
||||
else:
|
||||
if want_progressives():
|
||||
pool.extend(diff.progressivesword)
|
||||
|
@ -557,14 +550,6 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
|||
itemtotal = itemtotal + 1
|
||||
|
||||
if mode == 'standard':
|
||||
if progressive == 'off':
|
||||
placed_items.append(('Link\'s Uncle', 'Fighter Sword'))
|
||||
pool.extend(['Fighter Sword'] * max((customitemarray[32] - 1), 0))
|
||||
pool.extend(['Progressive Sword'] * customitemarray[36])
|
||||
else:
|
||||
placed_items.append(('Link\'s Uncle', 'Progressive Sword'))
|
||||
pool.extend(['Fighter Sword'] * customitemarray[32])
|
||||
pool.extend(['Progressive Sword'] * max((customitemarray[36] - 1), 0))
|
||||
if retro:
|
||||
key_location = random.choice(['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', 'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
|
||||
placed_items.append((key_location, 'Small Key (Universal)'))
|
||||
|
@ -572,10 +557,11 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
|||
else:
|
||||
pool.extend(['Small Key (Universal)'] * customitemarray[68])
|
||||
else:
|
||||
pool.extend(['Fighter Sword'] * customitemarray[32])
|
||||
pool.extend(['Progressive Sword'] * customitemarray[36])
|
||||
pool.extend(['Small Key (Universal)'] * customitemarray[68])
|
||||
|
||||
pool.extend(['Fighter Sword'] * customitemarray[32])
|
||||
pool.extend(['Progressive Sword'] * customitemarray[36])
|
||||
|
||||
if shuffle == 'insanity_legacy':
|
||||
placed_items.append(('Link\'s House', 'Magic Mirror'))
|
||||
placed_items.append(('Sanctuary', 'Moon Pearl'))
|
||||
|
|
34
Rom.py
34
Rom.py
|
@ -551,7 +551,13 @@ def patch_rom(world, player, rom):
|
|||
# set open mode:
|
||||
if world.mode in ['open', 'inverted']:
|
||||
rom.write_byte(0x180032, 0x01) # open mode
|
||||
if world.mode == 'inverted':
|
||||
set_inverted_mode(world, rom)
|
||||
elif world.mode == 'standard':
|
||||
rom.write_byte(0x180032, 0x00) # standard mode
|
||||
|
||||
uncle_location = world.get_location('Link\'s Uncle', player)
|
||||
if uncle_location.item is None or uncle_location.item.name not in ['Master Sword', 'Tempered Sword', 'Fighter Sword', 'Golden Sword', 'Progressive Sword']:
|
||||
# disable sword sprite from uncle
|
||||
rom.write_bytes(0x6D263, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||
rom.write_bytes(0x6D26B, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||
|
@ -563,10 +569,6 @@ def patch_rom(world, player, rom):
|
|||
rom.write_bytes(0x6D2EB, [0x00, 0x00, 0xf7, 0xff, 0x02, 0x0E])
|
||||
rom.write_bytes(0x6D31B, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
||||
rom.write_bytes(0x6D323, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
||||
if world.mode == 'inverted':
|
||||
set_inverted_mode(world, rom)
|
||||
elif world.mode == 'standard':
|
||||
rom.write_byte(0x180032, 0x00) # standard mode
|
||||
|
||||
# set light cones
|
||||
rom.write_byte(0x180038, 0x01 if world.sewer_light_cone else 0x00)
|
||||
|
@ -866,12 +868,6 @@ def patch_rom(world, player, rom):
|
|||
rom.write_bytes(0x180080, [50, 50, 70, 70]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10)
|
||||
|
||||
rom.write_byte(0x18004D, 0x00) # Escape assist (off)
|
||||
rom.write_byte(0x18004E, 0x00) # escape fills
|
||||
rom.write_int16(0x180183, 0) # rupee fill (for bow if rupee arrows enabled)
|
||||
rom.write_bytes(0x180185, [0x00, 0x00, 0x00]) # uncle item refills
|
||||
rom.write_bytes(0x180188, [0x00, 0x00, 0x00]) # zelda item refills
|
||||
rom.write_bytes(0x18018B, [0x00, 0x00, 0x00]) # uncle item refills
|
||||
|
||||
|
||||
if world.goal in ['pedestal', 'triforcehunt']:
|
||||
rom.write_byte(0x18003E, 0x01) # make ganon invincible
|
||||
|
@ -950,6 +946,24 @@ def patch_rom(world, player, rom):
|
|||
rom.write_bytes(0x6D2FB, [0x00, 0x00, 0xf7, 0xff, 0x02, 0x0E])
|
||||
rom.write_bytes(0x6D313, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
|
||||
|
||||
rom.write_byte(0x18004E, 0) # Escape Fill (nothing)
|
||||
rom.write_int16(0x180183, 300) # Escape fill rupee bow
|
||||
rom.write_bytes(0x180185, [0,0,0]) # Uncle respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x180188, [0,0,0]) # Zelda respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x18018B, [0,0,0]) # Mantle respawn refills (magic, bombs, arrows)
|
||||
if world.mode == 'standard':
|
||||
if uncle_location.item is not None and uncle_location.item.name in ['Bow', 'Progressive Bow']:
|
||||
rom.write_byte(0x18004E, 1) # Escape Fill (arrows)
|
||||
rom.write_int16(0x180183, 300) # Escape fill rupee bow
|
||||
rom.write_bytes(0x180185, [0,0,70]) # Uncle respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x180188, [0,0,10]) # Zelda respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x18018B, [0,0,10]) # Mantle respawn refills (magic, bombs, arrows)
|
||||
elif uncle_location.item is not None and uncle_location.item.name in ['Cane of Somaria', 'Cane of Byrna', 'Fire Rod']:
|
||||
rom.write_byte(0x18004E, 4) # Escape Fill (magic)
|
||||
rom.write_bytes(0x180185, [0x80,0,0]) # Uncle respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x180188, [0x20,0,0]) # Zelda respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x18018B, [0x20,0,0]) # Mantle respawn refills (magic, bombs, arrows)
|
||||
|
||||
# patch swamp: Need to enable permanent drain of water as dam or swamp were moved
|
||||
rom.write_byte(0x18003D, 0x01 if world.swamp_patch_required[player] else 0x00)
|
||||
|
||||
|
|
63
Rules.py
63
Rules.py
|
@ -1,5 +1,6 @@
|
|||
import collections
|
||||
import logging
|
||||
from BaseClasses import CollectionState
|
||||
|
||||
|
||||
def set_rules(world, player):
|
||||
|
@ -7,17 +8,17 @@ def set_rules(world, player):
|
|||
if world.logic == 'nologic':
|
||||
logging.getLogger('').info('WARNING! Seeds generated under this logic often require major glitches and may be impossible!')
|
||||
if world.mode != 'inverted':
|
||||
world.get_region('Links House', player).can_reach = lambda state: True
|
||||
world.get_region('Sanctuary', player).can_reach = lambda state: True
|
||||
world.get_region('Links House', player).can_reach_private = lambda state: True
|
||||
world.get_region('Sanctuary', player).can_reach_private = lambda state: True
|
||||
old_rule = world.get_region('Old Man House', player).can_reach
|
||||
world.get_region('Old Man House', player).can_reach = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state)
|
||||
world.get_region('Old Man House', player).can_reach_private = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state)
|
||||
return
|
||||
else:
|
||||
world.get_region('Inverted Links House', player).can_reach = lambda state: True
|
||||
world.get_region('Inverted Dark Sanctuary', player).entrances[0].parent_region.can_reach = lambda state: True
|
||||
world.get_region('Inverted Links House', player).can_reach_private = lambda state: True
|
||||
world.get_region('Inverted Dark Sanctuary', player).entrances[0].parent_region.can_reach_private = lambda state: True
|
||||
if world.shuffle != 'vanilla':
|
||||
old_rule = world.get_region('Old Man House', player).can_reach
|
||||
world.get_region('Old Man House', player).can_reach = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state)
|
||||
world.get_region('Old Man House', player).can_reach_private = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state)
|
||||
return
|
||||
if world.mode != 'inverted':
|
||||
global_rules(world, player)
|
||||
|
@ -90,6 +91,9 @@ def forbid_item(location, item, player):
|
|||
old_rule = location.item_rule
|
||||
location.item_rule = lambda i: (i.name != item or i.player != player) and old_rule(i)
|
||||
|
||||
def add_item_rule(location, rule):
|
||||
old_rule = location.item_rule
|
||||
location.item_rule = lambda item: rule(item) and old_rule(item)
|
||||
|
||||
def item_in_locations(state, item, player, locations):
|
||||
for location in locations:
|
||||
|
@ -111,15 +115,20 @@ def global_rules(world, player):
|
|||
forbid_item(location, 'Triforce Piece', player)
|
||||
|
||||
# ganon can only carry triforce
|
||||
world.get_location('Ganon', player).item_rule = lambda item: item.name == 'Triforce' and item.player == player
|
||||
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
|
||||
|
||||
# these are default save&quit points and always accessible
|
||||
world.get_region('Links House', player).can_reach = lambda state: True
|
||||
world.get_region('Sanctuary', player).can_reach = lambda state: True
|
||||
if world.mode == 'standard':
|
||||
world.get_region('Hyrule Castle Secret Entrance', player).can_reach_private = lambda state: True
|
||||
old_rule = world.get_region('Links House', player).can_reach
|
||||
world.get_region('Links House', player).can_reach_private = lambda state: state.can_reach('Sanctuary', 'Region', player) or old_rule(state)
|
||||
else:
|
||||
# these are default save&quit points and always accessible
|
||||
world.get_region('Links House', player).can_reach_private = lambda state: True
|
||||
world.get_region('Sanctuary', player).can_reach_private = lambda state: True
|
||||
|
||||
# we can s&q to the old man house after we rescue him. This may be somewhere completely different if caves are shuffled!
|
||||
old_rule = world.get_region('Old Man House', player).can_reach
|
||||
world.get_region('Old Man House', player).can_reach = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state)
|
||||
world.get_region('Old Man House', player).can_reach_private = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state)
|
||||
|
||||
# overworld requirements
|
||||
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player))
|
||||
|
@ -454,14 +463,20 @@ def global_rules(world, player):
|
|||
set_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt, player))
|
||||
|
||||
def inverted_rules(world, player):
|
||||
world.get_location('Ganon', player).item_rule = lambda item: item.name == 'Triforce' and item.player == player
|
||||
world.get_region('Inverted Links House', player).can_reach = lambda state: True
|
||||
world.get_region('Inverted Dark Sanctuary', player).entrances[0].parent_region.can_reach = lambda state: True
|
||||
if world.goal == 'triforcehunt':
|
||||
for location in world.get_locations():
|
||||
if location.player != player:
|
||||
forbid_item(location, 'Triforce Piece', player)
|
||||
|
||||
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)
|
||||
|
||||
world.get_region('Inverted Links House', player).can_reach_private = lambda state: True
|
||||
world.get_region('Inverted Dark Sanctuary', player).entrances[0].parent_region.can_reach_private = lambda state: True
|
||||
|
||||
# we can s&q to the old man house after we rescue him. This may be somewhere completely different if caves are shuffled!
|
||||
if world.shuffle != 'vanilla':
|
||||
old_rule = world.get_region('Old Man House', player).can_reach
|
||||
world.get_region('Old Man House', player).can_reach = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state)
|
||||
world.get_region('Old Man House', player).can_reach_private = lambda state: state.can_reach('Old Man', 'Location', player) or old_rule(state)
|
||||
# overworld requirements
|
||||
set_rule(world.get_location('Maze Race', player), lambda state: state.has_Pearl(player))
|
||||
set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has_Pearl(player))
|
||||
|
@ -930,9 +945,21 @@ def swordless_rules(world, player):
|
|||
|
||||
|
||||
def standard_rules(world, player):
|
||||
for loc in ['Sanctuary', 'Sewers - Secret Room - Left', 'Sewers - Secret Room - Middle',
|
||||
'Sewers - Secret Room - Right']:
|
||||
add_rule(world.get_location(loc, player), lambda state: state.can_kill_most_things(player) and state.has_key('Small Key (Escape)', player))
|
||||
add_rule(world.get_entrance('Sewers Door', player), lambda state: state.can_kill_most_things(player))
|
||||
|
||||
set_rule(world.get_entrance('Hyrule Castle Exit (East)', player), lambda state: state.can_reach('Sanctuary', 'Region', player))
|
||||
set_rule(world.get_entrance('Hyrule Castle Exit (West)', player), lambda state: state.can_reach('Sanctuary', 'Region', player))
|
||||
|
||||
# ensures the required weapon for escape lands on uncle (unless player has it pre-equipped)
|
||||
add_rule(world.get_location('Secret Passage', player), lambda state: state.can_kill_most_things(player))
|
||||
add_rule(world.get_location('Hyrule Castle - Map Chest', player), lambda state: state.can_kill_most_things(player))
|
||||
|
||||
def uncle_item_rule(item):
|
||||
copy_state = CollectionState(world)
|
||||
copy_state.collect(item)
|
||||
return copy_state.can_reach('Sanctuary', 'Region', player)
|
||||
|
||||
add_item_rule(world.get_location('Link\'s Uncle', player), uncle_item_rule)
|
||||
|
||||
# easiest way to enforce key placement not relevant for open
|
||||
set_rule(world.get_location('Sewers - Dark Cross', player), lambda state: state.can_kill_most_things(player))
|
||||
|
|
Loading…
Reference in New Issue