Merge remote-tracking branch 'upstream/DoorDevUnstable' into OverworldShuffleDev
This commit is contained in:
@@ -606,7 +606,7 @@ class CollectionState(object):
|
|||||||
queue.append((new_entrance, new_crystal_state))
|
queue.append((new_entrance, new_crystal_state))
|
||||||
# else those connections that are not accessible yet
|
# else those connections that are not accessible yet
|
||||||
if self.is_small_door(connection):
|
if self.is_small_door(connection):
|
||||||
door = connection.door
|
door = connection.door if connection.door.smallKey else connection.door.controller
|
||||||
dungeon_name = connection.parent_region.dungeon.name
|
dungeon_name = connection.parent_region.dungeon.name
|
||||||
key_logic = self.world.key_logic[player][dungeon_name]
|
key_logic = self.world.key_logic[player][dungeon_name]
|
||||||
if door.name not in self.reached_doors[player]:
|
if door.name not in self.reached_doors[player]:
|
||||||
@@ -620,7 +620,7 @@ class CollectionState(object):
|
|||||||
checklist[connection.name] = (connection, crystal_state)
|
checklist[connection.name] = (connection, crystal_state)
|
||||||
elif door.name not in self.opened_doors[player]:
|
elif door.name not in self.opened_doors[player]:
|
||||||
opened_doors = self.opened_doors[player]
|
opened_doors = self.opened_doors[player]
|
||||||
door = connection.door
|
door = connection.door if connection.door.smallKey else connection.door.controller
|
||||||
if door.name not in opened_doors:
|
if door.name not in opened_doors:
|
||||||
self.door_counter[player][1][dungeon_name] += 1
|
self.door_counter[player][1][dungeon_name] += 1
|
||||||
opened_doors.add(door.name)
|
opened_doors.add(door.name)
|
||||||
@@ -1003,7 +1003,12 @@ class CollectionState(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_small_door(connection):
|
def is_small_door(connection):
|
||||||
return connection and connection.door and connection.door.smallKey
|
return connection and connection.door and (connection.door.smallKey or
|
||||||
|
CollectionState.is_controlled_by_small(connection))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_controlled_by_small(connection):
|
||||||
|
return connection.door.controller and connection.door.controller.smallKey
|
||||||
|
|
||||||
def is_door_open(self, door_name, player):
|
def is_door_open(self, door_name, player):
|
||||||
return door_name in self.opened_doors[player]
|
return door_name in self.opened_doors[player]
|
||||||
@@ -1835,6 +1840,7 @@ class Door(object):
|
|||||||
self.bk_shuffle_req = False
|
self.bk_shuffle_req = False
|
||||||
self.standard_restricted = False # flag if portal is not allowed in HC in standard
|
self.standard_restricted = False # flag if portal is not allowed in HC in standard
|
||||||
self.lw_restricted = False # flag if portal is not allowed in DW
|
self.lw_restricted = False # flag if portal is not allowed in DW
|
||||||
|
self.rupee_bow_restricted = False # flag if portal is not allowed in HC in standard+rupee_bow
|
||||||
# self.incognitoPos = -1
|
# self.incognitoPos = -1
|
||||||
# self.sectorLink = False
|
# self.sectorLink = False
|
||||||
|
|
||||||
|
|||||||
@@ -368,7 +368,8 @@ def choose_portals(world, player):
|
|||||||
|
|
||||||
if world.doorShuffle[player] in ['basic', 'crossed']:
|
if world.doorShuffle[player] in ['basic', 'crossed']:
|
||||||
cross_flag = world.doorShuffle[player] == 'crossed'
|
cross_flag = world.doorShuffle[player] == 'crossed'
|
||||||
bk_shuffle = world.bigkeyshuffle[player]
|
# key drops allow the big key in the right place in Desert Tiles 2
|
||||||
|
bk_shuffle = world.bigkeyshuffle[player] or world.keydropshuffle[player]
|
||||||
std_flag = world.mode[player] == 'standard'
|
std_flag = world.mode[player] == 'standard'
|
||||||
# roast incognito doors
|
# roast incognito doors
|
||||||
world.get_room(0x60, player).delete(5)
|
world.get_room(0x60, player).delete(5)
|
||||||
@@ -415,6 +416,7 @@ def choose_portals(world, player):
|
|||||||
for dungeon, info in shuffled_info:
|
for dungeon, info in shuffled_info:
|
||||||
outstanding_portals = list(dungeon_portals[dungeon])
|
outstanding_portals = list(dungeon_portals[dungeon])
|
||||||
hc_flag = std_flag and dungeon == 'Hyrule Castle'
|
hc_flag = std_flag and dungeon == 'Hyrule Castle'
|
||||||
|
rupee_bow_flag = hc_flag and world.retro[player] # rupee bow
|
||||||
if hc_flag:
|
if hc_flag:
|
||||||
sanc = world.get_portal('Sanctuary', player)
|
sanc = world.get_portal('Sanctuary', player)
|
||||||
sanc.destination = True
|
sanc.destination = True
|
||||||
@@ -424,14 +426,14 @@ def choose_portals(world, player):
|
|||||||
info.required_passage = {x: y for x, y in info.required_passage.items() if len(y) > 0}
|
info.required_passage = {x: y for x, y in info.required_passage.items() if len(y) > 0}
|
||||||
for target_region, possible_portals in info.required_passage.items():
|
for target_region, possible_portals in info.required_passage.items():
|
||||||
candidates = find_portal_candidates(master_door_list, dungeon, need_passage=True, crossed=cross_flag,
|
candidates = find_portal_candidates(master_door_list, dungeon, need_passage=True, crossed=cross_flag,
|
||||||
bk_shuffle=bk_shuffle)
|
bk_shuffle=bk_shuffle, rupee_bow=rupee_bow_flag)
|
||||||
choice, portal = assign_portal(candidates, possible_portals, world, player)
|
choice, portal = assign_portal(candidates, possible_portals, world, player)
|
||||||
portal.destination = True
|
portal.destination = True
|
||||||
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
|
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
|
||||||
dead_end_choices = info.total - 1 - len(portal_assignment[dungeon])
|
dead_end_choices = info.total - 1 - len(portal_assignment[dungeon])
|
||||||
for i in range(0, dead_end_choices):
|
for i in range(0, dead_end_choices):
|
||||||
candidates = find_portal_candidates(master_door_list, dungeon, dead_end_allowed=True,
|
candidates = find_portal_candidates(master_door_list, dungeon, dead_end_allowed=True,
|
||||||
crossed=cross_flag, bk_shuffle=bk_shuffle)
|
crossed=cross_flag, bk_shuffle=bk_shuffle, rupee_bow=rupee_bow_flag)
|
||||||
possible_portals = outstanding_portals if not info.sole_entrance else [x for x in outstanding_portals if x != info.sole_entrance]
|
possible_portals = outstanding_portals if not info.sole_entrance else [x for x in outstanding_portals if x != info.sole_entrance]
|
||||||
choice, portal = assign_portal(candidates, possible_portals, world, player)
|
choice, portal = assign_portal(candidates, possible_portals, world, player)
|
||||||
if choice.deadEnd:
|
if choice.deadEnd:
|
||||||
@@ -443,7 +445,7 @@ def choose_portals(world, player):
|
|||||||
the_rest = info.total - len(portal_assignment[dungeon])
|
the_rest = info.total - len(portal_assignment[dungeon])
|
||||||
for i in range(0, the_rest):
|
for i in range(0, the_rest):
|
||||||
candidates = find_portal_candidates(master_door_list, dungeon, crossed=cross_flag,
|
candidates = find_portal_candidates(master_door_list, dungeon, crossed=cross_flag,
|
||||||
bk_shuffle=bk_shuffle, standard=hc_flag)
|
bk_shuffle=bk_shuffle, standard=hc_flag, rupee_bow=rupee_bow_flag)
|
||||||
choice, portal = assign_portal(candidates, outstanding_portals, world, player)
|
choice, portal = assign_portal(candidates, outstanding_portals, world, player)
|
||||||
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
|
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
|
||||||
|
|
||||||
@@ -562,7 +564,7 @@ def disconnect_portal(portal, world, player):
|
|||||||
|
|
||||||
|
|
||||||
def find_portal_candidates(door_list, dungeon, need_passage=False, dead_end_allowed=False, crossed=False,
|
def find_portal_candidates(door_list, dungeon, need_passage=False, dead_end_allowed=False, crossed=False,
|
||||||
bk_shuffle=False, standard=False):
|
bk_shuffle=False, standard=False, rupee_bow=False):
|
||||||
ret = [x for x in door_list if bk_shuffle or not x.bk_shuffle_req]
|
ret = [x for x in door_list if bk_shuffle or not x.bk_shuffle_req]
|
||||||
if crossed:
|
if crossed:
|
||||||
ret = [x for x in ret if not x.dungeonLink or x.dungeonLink == dungeon or x.dungeonLink.startswith('link')]
|
ret = [x for x in ret if not x.dungeonLink or x.dungeonLink == dungeon or x.dungeonLink.startswith('link')]
|
||||||
@@ -574,6 +576,8 @@ def find_portal_candidates(door_list, dungeon, need_passage=False, dead_end_allo
|
|||||||
ret = [x for x in ret if not x.deadEnd]
|
ret = [x for x in ret if not x.deadEnd]
|
||||||
if standard:
|
if standard:
|
||||||
ret = [x for x in ret if not x.standard_restricted]
|
ret = [x for x in ret if not x.standard_restricted]
|
||||||
|
if rupee_bow:
|
||||||
|
ret = [x for x in ret if not x.rupee_bow_restricted]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@@ -2047,7 +2051,7 @@ class DROptions(Flag):
|
|||||||
Town_Portal = 0x02 # If on, Players will start with mirror scroll
|
Town_Portal = 0x02 # If on, Players will start with mirror scroll
|
||||||
Map_Info = 0x04
|
Map_Info = 0x04
|
||||||
Debug = 0x08
|
Debug = 0x08
|
||||||
# Rails = 0x10 # Unused bit now
|
Fix_EG = 0x10 # used to be Rails = 0x10 # Unused bit now
|
||||||
OriginalPalettes = 0x20
|
OriginalPalettes = 0x20
|
||||||
# Open_PoD_Wall = 0x40 # No longer pre-opening pod wall - unused
|
# Open_PoD_Wall = 0x40 # No longer pre-opening pod wall - unused
|
||||||
# Open_Desert_Wall = 0x80 # No longer pre-opening desert wall - unused
|
# Open_Desert_Wall = 0x80 # No longer pre-opening desert wall - unused
|
||||||
|
|||||||
7
Doors.py
7
Doors.py
@@ -1490,8 +1490,11 @@ def create_doors(world, player):
|
|||||||
world.get_door('GT Petting Zoo SE', player).dead_end()
|
world.get_door('GT Petting Zoo SE', player).dead_end()
|
||||||
world.get_door('GT DMs Room SW', player).dead_end()
|
world.get_door('GT DMs Room SW', player).dead_end()
|
||||||
world.get_door("GT Bob\'s Room SE", player).passage = False
|
world.get_door("GT Bob\'s Room SE", player).passage = False
|
||||||
world.get_door('Desert Tiles 2 SE', player).bk_shuffle_req = True # key-drop note (todo)
|
world.get_door('Desert Tiles 2 SE', player).bk_shuffle_req = True # key-drop note: allows this to be a portal
|
||||||
world.get_door('Swamp Lobby S', player).standard_restricted = True # key-drop note (todo)
|
world.get_door('Swamp Lobby S', player).standard_restricted = True
|
||||||
|
world.get_door('PoD Mimics 2 SW', player).rupee_bow_restricted = True # bow statue
|
||||||
|
# enemizer logic could get rid of the following restriction
|
||||||
|
world.get_door('PoD Pit Room S', player).rupee_bow_restricted = True # so mimics 1 shouldn't be required
|
||||||
|
|
||||||
# can't unlink from boss right now
|
# can't unlink from boss right now
|
||||||
world.get_door('Hera Lobby S', player).dungeonLink = 'Tower of Hera'
|
world.get_door('Hera Lobby S', player).dungeonLink = 'Tower of Hera'
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ class PlacementRule(object):
|
|||||||
if loc.item and loc.item.bigkey:
|
if loc.item and loc.item.bigkey:
|
||||||
bk_blocked = True
|
bk_blocked = True
|
||||||
break
|
break
|
||||||
else:
|
elif len(self.check_locations_w_bk) > self.needed_keys_w_bk:
|
||||||
def loc_has_bk(l):
|
def loc_has_bk(l):
|
||||||
return (big_key_loc is not None and big_key_loc == l) or (l.item and l.item.bigkey)
|
return (big_key_loc is not None and big_key_loc == l) or (l.item and l.item.bigkey)
|
||||||
|
|
||||||
|
|||||||
2
Main.py
2
Main.py
@@ -30,7 +30,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc
|
|||||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
__version__ = '0.5.1.2-u'
|
__version__ = '0.5.1.4-u'
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ CLI: ```--bombbag```
|
|||||||
|
|
||||||
# Bug Fixes and Notes.
|
# Bug Fixes and Notes.
|
||||||
|
|
||||||
|
* 0.5.1.4
|
||||||
|
* Revert quadrant glitch fix for baserom
|
||||||
|
* Fix for inverted
|
||||||
|
* 0.5.1.3
|
||||||
|
* Certain lobbies forbidden in standard when rupee bow is enabled
|
||||||
|
* PoD EG disarmed when mirroring (except in nologic)
|
||||||
|
* Fixed issue with key logic
|
||||||
|
* Updated baserom
|
||||||
* 0.5.1.2
|
* 0.5.1.2
|
||||||
* Allowed Blind's Cell to be shuffled anywhere if Blind is not the boss of Thieves Town
|
* Allowed Blind's Cell to be shuffled anywhere if Blind is not the boss of Thieves Town
|
||||||
* Remove unique annotation from a FastEnum that was causing problems
|
* Remove unique annotation from a FastEnum that was causing problems
|
||||||
|
|||||||
11
Rom.py
11
Rom.py
@@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = 'c81153d8bb571e41fe472d36274f47b3'
|
RANDOMIZERBASEHASH = 'cfafbec1231207dc4a7f1992ea7500c6'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -769,6 +769,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
dr_flags |= DROptions.OriginalPalettes
|
dr_flags |= DROptions.OriginalPalettes
|
||||||
if world.experimental[player]:
|
if world.experimental[player]:
|
||||||
dr_flags |= DROptions.DarkWorld_Spawns
|
dr_flags |= DROptions.DarkWorld_Spawns
|
||||||
|
if world.logic[player] != 'nologic':
|
||||||
|
dr_flags |= DROptions.Fix_EG
|
||||||
|
|
||||||
|
|
||||||
# fix hc big key problems (map and compass too)
|
# fix hc big key problems (map and compass too)
|
||||||
@@ -2501,6 +2503,7 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
|||||||
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00]) # indicates the overworld door being used for the single entrance spawn point
|
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00]) # indicates the overworld door being used for the single entrance spawn point
|
||||||
if (world.mode[player] == 'inverted') != (0x05 in world.owswaps[player][0] and world.owMixed[player]):
|
if (world.mode[player] == 'inverted') != (0x05 in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
rom.write_bytes(snes_to_pc(0x1BC655), [0x4A, 0x1D, 0x82]) # add warp under rock
|
rom.write_bytes(snes_to_pc(0x1BC655), [0x4A, 0x1D, 0x82]) # add warp under rock
|
||||||
|
rom.write_byte(snes_to_pc(0x1BC428), 0x00) # remove secret portal
|
||||||
if (world.mode[player] == 'inverted') != (0x07 in world.owswaps[player][0] and world.owMixed[player]):
|
if (world.mode[player] == 'inverted') != (0x07 in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
rom.write_bytes(snes_to_pc(0x1BC387), [0xDD, 0xD1]) # add warps under rocks
|
rom.write_bytes(snes_to_pc(0x1BC387), [0xDD, 0xD1]) # add warps under rocks
|
||||||
rom.write_bytes(snes_to_pc(0x1BD1DD), [0xA4, 0x06, 0x82, 0x9E, 0x06, 0x82, 0xFF, 0xFF]) # add warps under rocks
|
rom.write_bytes(snes_to_pc(0x1BD1DD), [0xA4, 0x06, 0x82, 0x9E, 0x06, 0x82, 0xFF, 0xFF]) # add warps under rocks
|
||||||
@@ -2510,6 +2513,8 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
|||||||
world.fix_trock_doors[player] = True
|
world.fix_trock_doors[player] = True
|
||||||
if (world.mode[player] == 'inverted') != (0x10 in world.owswaps[player][0] and world.owMixed[player]):
|
if (world.mode[player] == 'inverted') != (0x10 in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
rom.write_bytes(snes_to_pc(0x1BC67A), [0x2E, 0x0B, 0x82]) # add warp under rock
|
rom.write_bytes(snes_to_pc(0x1BC67A), [0x2E, 0x0B, 0x82]) # add warp under rock
|
||||||
|
rom.write_byte(snes_to_pc(0x1BC43A), 0x00) # remove secret portal
|
||||||
|
|
||||||
if (world.mode[player] == 'inverted') != (0x1B in world.owswaps[player][0] and world.owMixed[player]):
|
if (world.mode[player] == 'inverted') != (0x1B in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
write_int16(rom, 0x15AEE + 2 * 0x06, 0x0020) # post aga hyrule castle spawn
|
write_int16(rom, 0x15AEE + 2 * 0x06, 0x0020) # post aga hyrule castle spawn
|
||||||
rom.write_byte(0x15B8C + 0x06, 0x1B)
|
rom.write_byte(0x15B8C + 0x06, 0x1B)
|
||||||
@@ -2607,13 +2612,17 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
|||||||
rom.write_byte(0xDBB73 + 0x52, 0x01)
|
rom.write_byte(0xDBB73 + 0x52, 0x01)
|
||||||
if (world.mode[player] == 'inverted') != (0x2F in world.owswaps[player][0] and world.owMixed[player]):
|
if (world.mode[player] == 'inverted') != (0x2F in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82]) # add warp under rock
|
rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82]) # add warp under rock
|
||||||
|
rom.write_byte(snes_to_pc(0x1BC590), 0x00) # remove secret portal
|
||||||
if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owMixed[player]):
|
if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
rom.write_bytes(snes_to_pc(0x1BC81E), [0x94, 0x1D, 0x82]) # add warp under rock
|
rom.write_bytes(snes_to_pc(0x1BC81E), [0x94, 0x1D, 0x82]) # add warp under rock
|
||||||
|
rom.write_byte(snes_to_pc(0x1BC5A1), 0x00) # remove secret portal
|
||||||
if (world.mode[player] == 'inverted') != (0x33 in world.owswaps[player][0] and world.owMixed[player]):
|
if (world.mode[player] == 'inverted') != (0x33 in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
rom.write_bytes(snes_to_pc(0x1BC3DF), [0xD8, 0xD1]) # add warp under rock
|
rom.write_bytes(snes_to_pc(0x1BC3DF), [0xD8, 0xD1]) # add warp under rock
|
||||||
rom.write_bytes(snes_to_pc(0x1BD1D8), [0xA8, 0x02, 0x82, 0xFF, 0xFF]) # add warp under rock
|
rom.write_bytes(snes_to_pc(0x1BD1D8), [0xA8, 0x02, 0x82, 0xFF, 0xFF]) # add warp under rock
|
||||||
|
rom.write_byte(snes_to_pc(0x1BC5B1), 0x00) # remove secret portal
|
||||||
if (world.mode[player] == 'inverted') != (0x35 in world.owswaps[player][0] and world.owMixed[player]):
|
if (world.mode[player] == 'inverted') != (0x35 in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82]) # add warp under rock
|
rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82]) # add warp under rock
|
||||||
|
rom.write_byte(snes_to_pc(0x1BC5C7), 0x00) # remove secret portal
|
||||||
|
|
||||||
# apply inverted map changes
|
# apply inverted map changes
|
||||||
for b in range(0x00, len(inverted_buffer)):
|
for b in range(0x00, len(inverted_buffer)):
|
||||||
|
|||||||
12
Rules.py
12
Rules.py
@@ -342,7 +342,11 @@ def global_rules(world, player):
|
|||||||
set_rule(world.get_entrance('Mire Lobby Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
set_rule(world.get_entrance('Mire Lobby Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('Mire Post-Gap Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
set_rule(world.get_entrance('Mire Post-Gap Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('Mire Falling Bridge WN', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player)) # this is due to the fact the the door opposite is blocked
|
set_rule(world.get_entrance('Mire Falling Bridge WN', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player)) # this is due to the fact the the door opposite is blocked
|
||||||
set_rule(world.get_entrance('Mire 2 NE', player), lambda state: state.has_sword(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player)) # need to defeat wizzrobes, bombs don't work ...
|
set_rule(world.get_entrance('Mire 2 NE', player), lambda state: state.has_sword(player) or
|
||||||
|
(state.has('Fire Rod', player) and (state.can_use_bombs(player) or state.can_extend_magic(player, 9))) or # 9 fr shots or 8 with some bombs
|
||||||
|
(state.has('Ice Rod', player) and state.can_use_bombs(player)) or # freeze popo and throw, bomb to finish
|
||||||
|
state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player)) # need to defeat wizzrobes, bombs don't work ...
|
||||||
|
# byrna could work with sufficient magic
|
||||||
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
||||||
set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player))
|
set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player))
|
set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player))
|
||||||
@@ -2340,7 +2344,11 @@ def add_key_logic_rules(world, player):
|
|||||||
key_logic = world.key_logic[player]
|
key_logic = world.key_logic[player]
|
||||||
for d_name, d_logic in key_logic.items():
|
for d_name, d_logic in key_logic.items():
|
||||||
for door_name, rule in d_logic.door_rules.items():
|
for door_name, rule in d_logic.door_rules.items():
|
||||||
add_rule(world.get_entrance(door_name, player), eval_small_key_door(door_name, d_name, player))
|
door_entrance = world.get_entrance(door_name, player)
|
||||||
|
add_rule(door_entrance, eval_small_key_door(door_name, d_name, player))
|
||||||
|
if door_entrance.door.dependents:
|
||||||
|
for dep in door_entrance.door.dependents:
|
||||||
|
add_rule(dep.entrance, eval_small_key_door(door_name, d_name, player))
|
||||||
for location in d_logic.bk_restricted:
|
for location in d_logic.bk_restricted:
|
||||||
if not location.forced_item:
|
if not location.forced_item:
|
||||||
forbid_item(location, d_logic.bk_name, player)
|
forbid_item(location, d_logic.bk_name, player)
|
||||||
|
|||||||
@@ -125,6 +125,11 @@ org $07a955 ; <- Bank07.asm : around 6564 (JP is a bit different) (STZ $05FC : S
|
|||||||
jsl BlockEraseFix
|
jsl BlockEraseFix
|
||||||
nop #2
|
nop #2
|
||||||
|
|
||||||
|
org $02A0A8
|
||||||
|
Mirror_SaveRoomData:
|
||||||
|
org $07A95B ; < bank_07.asm ; #_07A95B: JSL Mirror_SaveRoomData
|
||||||
|
jsl EGFixOnMirror
|
||||||
|
|
||||||
org $02b82a
|
org $02b82a
|
||||||
jsl FixShopCode
|
jsl FixShopCode
|
||||||
|
|
||||||
|
|||||||
@@ -73,8 +73,9 @@ TrapDoorFixer:
|
|||||||
rts
|
rts
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
stz $047a
|
lda.l DRFlags : and #$10 : beq +
|
||||||
inc $11
|
stz $047a
|
||||||
|
+ inc $11
|
||||||
lda $ef
|
lda $ef
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,12 @@ MirrorCheckOverride:
|
|||||||
rtl
|
rtl
|
||||||
+ lda.l DRScroll : rtl
|
+ lda.l DRScroll : rtl
|
||||||
|
|
||||||
|
EGFixOnMirror:
|
||||||
|
lda.l DRFlags : and #$10 : beq +
|
||||||
|
stz $047a
|
||||||
|
+ jsl Mirror_SaveRoomData
|
||||||
|
rtl
|
||||||
|
|
||||||
BlockEraseFix:
|
BlockEraseFix:
|
||||||
lda $7ef353 : and #$02 : beq +
|
lda $7ef353 : and #$02 : beq +
|
||||||
stz $05fc : stz $05fd
|
stz $05fc : stz $05fd
|
||||||
|
|||||||
Reference in New Issue
Block a user