Merge branch 'Dev' into DoorDev
This commit is contained in:
@@ -284,7 +284,7 @@ class World(object):
|
|||||||
|
|
||||||
def has_beaten_game(self, state, player=None):
|
def has_beaten_game(self, state, player=None):
|
||||||
if player:
|
if player:
|
||||||
return state.has('Triforce', player) or (self.goal in ['triforcehunt'] and (state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) > self.treasure_hunt_count))
|
return state.has('Triforce', player)
|
||||||
else:
|
else:
|
||||||
return all((self.has_beaten_game(state, p) for p in range(1, self.players + 1)))
|
return all((self.has_beaten_game(state, p) for p in range(1, self.players + 1)))
|
||||||
|
|
||||||
|
|||||||
@@ -119,11 +119,11 @@ def can_place_boss(world, boss, dungeon_name, level=None):
|
|||||||
if world.swords in ['swordless'] and boss == 'Kholdstare' and dungeon_name != 'Ice Palace':
|
if world.swords in ['swordless'] and boss == 'Kholdstare' and dungeon_name != 'Ice Palace':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if dungeon_name == 'Ganons Tower' and level == 'top':
|
if dungeon_name in ['Ganons Tower', 'Inverted Ganons Tower'] and level == 'top':
|
||||||
if boss in ["Armos Knights", "Arrghus", "Blind", "Trinexx", "Lanmolas"]:
|
if boss in ["Armos Knights", "Arrghus", "Blind", "Trinexx", "Lanmolas"]:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if dungeon_name == 'Ganons Tower' and level == 'middle':
|
if dungeon_name in ['Ganons Tower', 'Inverted Ganons Tower'] and level == 'middle':
|
||||||
if boss in ["Blind"]:
|
if boss in ["Blind"]:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -3507,8 +3507,8 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
|
|||||||
('Bumper Cave (Top)', 'Dark Death Mountain Healer Fairy'),
|
('Bumper Cave (Top)', 'Dark Death Mountain Healer Fairy'),
|
||||||
('Bumper Cave Exit (Top)', 'Death Mountain Return Ledge'),
|
('Bumper Cave Exit (Top)', 'Death Mountain Return Ledge'),
|
||||||
('Bumper Cave Exit (Bottom)', 'Light World'),
|
('Bumper Cave Exit (Bottom)', 'Light World'),
|
||||||
('Death Mountain Return Cave (East)', 'Bumper Cave'),
|
('Death Mountain Return Cave (West)', 'Bumper Cave'),
|
||||||
('Death Mountain Return Cave (West)', 'Death Mountain Return Cave'),
|
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
|
||||||
('Death Mountain Return Cave Exit (West)', 'Death Mountain'),
|
('Death Mountain Return Cave Exit (West)', 'Death Mountain'),
|
||||||
('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
|
('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
|
||||||
('Hookshot Cave Exit (South)', 'Dark Death Mountain'),
|
('Hookshot Cave Exit (South)', 'Dark Death Mountain'),
|
||||||
|
|||||||
17
ItemList.py
17
ItemList.py
@@ -137,6 +137,23 @@ def generate_itempool(world, player):
|
|||||||
else:
|
else:
|
||||||
world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False)
|
world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False)
|
||||||
|
|
||||||
|
if world.goal in ['triforcehunt']:
|
||||||
|
if world.mode == 'inverted':
|
||||||
|
region = world.get_region('Light World',player)
|
||||||
|
else:
|
||||||
|
region = world.get_region('Hyrule Castle Courtyard', player)
|
||||||
|
|
||||||
|
loc = Location(player, "Murahdahla", parent=region)
|
||||||
|
loc.access_rule = lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) > state.world.treasure_hunt_count
|
||||||
|
region.locations.append(loc)
|
||||||
|
world.dynamic_locations.append(loc)
|
||||||
|
|
||||||
|
world.clear_location_cache()
|
||||||
|
|
||||||
|
world.push_item(loc, ItemFactory('Triforce', player), False)
|
||||||
|
loc.event = True
|
||||||
|
loc.locked = True
|
||||||
|
|
||||||
world.get_location('Ganon', player).event = True
|
world.get_location('Ganon', player).event = True
|
||||||
world.get_location('Ganon', player).locked = True
|
world.get_location('Ganon', player).locked = True
|
||||||
world.push_item(world.get_location('Agahnim 1', player), ItemFactory('Beat Agahnim 1', player), False)
|
world.push_item(world.get_location('Agahnim 1', player), ItemFactory('Beat Agahnim 1', player), False)
|
||||||
|
|||||||
5
Main.py
5
Main.py
@@ -285,6 +285,11 @@ def copy_dynamic_regions_and_locations(world, ret):
|
|||||||
for location in world.dynamic_locations:
|
for location in world.dynamic_locations:
|
||||||
new_reg = ret.get_region(location.parent_region.name, location.parent_region.player)
|
new_reg = ret.get_region(location.parent_region.name, location.parent_region.player)
|
||||||
new_loc = Location(location.player, location.name, location.address, location.crystal, location.hint_text, new_reg)
|
new_loc = Location(location.player, location.name, location.address, location.crystal, location.hint_text, new_reg)
|
||||||
|
# todo: this is potentially dangerous. later refactor so we
|
||||||
|
# can apply dynamic region rules on top of copied world like other rules
|
||||||
|
new_loc.access_rule = location.access_rule
|
||||||
|
new_loc.always_allow = location.always_allow
|
||||||
|
new_loc.item_rule = location.item_rule
|
||||||
new_reg.locations.append(new_loc)
|
new_reg.locations.append(new_loc)
|
||||||
|
|
||||||
ret.clear_location_cache()
|
ret.clear_location_cache()
|
||||||
|
|||||||
9
Rom.py
9
Rom.py
@@ -842,6 +842,7 @@ def patch_rom(world, player, rom):
|
|||||||
# set up goals for treasure hunt
|
# set up goals for treasure hunt
|
||||||
rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon == 'Triforce Piece' else [0x0D, 0x28])
|
rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon == 'Triforce Piece' else [0x0D, 0x28])
|
||||||
rom.write_byte(0x180167, world.treasure_hunt_count % 256)
|
rom.write_byte(0x180167, world.treasure_hunt_count % 256)
|
||||||
|
rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled)
|
||||||
|
|
||||||
# TODO: a proper race rom mode should be implemented, that changes the following flag, and rummages the table (or uses the future encryption feature, etc)
|
# TODO: a proper race rom mode should be implemented, that changes the following flag, and rummages the table (or uses the future encryption feature, etc)
|
||||||
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
|
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
|
||||||
@@ -1282,17 +1283,18 @@ def write_strings(rom, world, player):
|
|||||||
random.shuffle(silverarrows)
|
random.shuffle(silverarrows)
|
||||||
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
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'] = '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
|
||||||
|
|
||||||
prog_bow_locs = world.find_items('Progressive Bow', player)
|
prog_bow_locs = world.find_items('Progressive Bow', player)
|
||||||
distinguished_prog_bow_loc = next((location for location in prog_bow_locs if location.item.code == 0x65), None)
|
distinguished_prog_bow_loc = next((location for location in prog_bow_locs if location.item.code == 0x65), None)
|
||||||
if distinguished_prog_bow_loc:
|
if distinguished_prog_bow_loc:
|
||||||
prog_bow_locs.remove(distinguished_prog_bow_loc)
|
prog_bow_locs.remove(distinguished_prog_bow_loc)
|
||||||
silverarrow_hint = (' %s?' % hint_text(distinguished_prog_bow_loc).replace('Ganon\'s', 'my'))
|
silverarrow_hint = (' %s?' % hint_text(distinguished_prog_bow_loc).replace('Ganon\'s', 'my'))
|
||||||
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
|
||||||
|
|
||||||
if any(prog_bow_locs):
|
if any(prog_bow_locs):
|
||||||
silverarrow_hint = (' %s?' % hint_text(random.choice(prog_bow_locs)).replace('Ganon\'s', 'my'))
|
silverarrow_hint = (' %s?' % hint_text(random.choice(prog_bow_locs)).replace('Ganon\'s', 'my'))
|
||||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||||
|
|
||||||
|
|
||||||
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
||||||
@@ -1323,6 +1325,7 @@ def write_strings(rom, world, player):
|
|||||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
|
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
|
||||||
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
||||||
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
|
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
|
||||||
|
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\nhidden in a hollow tree. If you bring\n%d triforce pieces, I can reassemble it." % world.treasure_hunt_count
|
||||||
elif world.goal in ['pedestal']:
|
elif world.goal in ['pedestal']:
|
||||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
|
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
|
||||||
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
||||||
@@ -1406,8 +1409,6 @@ def set_inverted_mode(world, rom):
|
|||||||
rom.write_int16s(snes_to_pc(0x02E849), [0x0043, 0x0056, 0x0058, 0x006C, 0x006F, 0x0070, 0x007B, 0x007F, 0x001B]) # dw flute
|
rom.write_int16s(snes_to_pc(0x02E849), [0x0043, 0x0056, 0x0058, 0x006C, 0x006F, 0x0070, 0x007B, 0x007F, 0x001B]) # dw flute
|
||||||
rom.write_int16(snes_to_pc(0x02E8D5), 0x07C8)
|
rom.write_int16(snes_to_pc(0x02E8D5), 0x07C8)
|
||||||
rom.write_int16(snes_to_pc(0x02E8F7), 0x01F8)
|
rom.write_int16(snes_to_pc(0x02E8F7), 0x01F8)
|
||||||
rom.write_byte(0x7A943, 0xF0)
|
|
||||||
rom.write_byte(0x7A96D, 0xD0)
|
|
||||||
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof
|
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof
|
||||||
# the following bytes should only be written in vanilla
|
# the following bytes should only be written in vanilla
|
||||||
# or they'll overwrite the randomizer's shuffles
|
# or they'll overwrite the randomizer's shuffles
|
||||||
|
|||||||
1
Text.py
1
Text.py
@@ -1890,5 +1890,6 @@ class TextTable(object):
|
|||||||
text['ganon_phase_3_no_silvers_alt'] = CompressedTextMapper.convert("You can't best me without silver arrows!")
|
text['ganon_phase_3_no_silvers_alt'] = CompressedTextMapper.convert("You can't best me without silver arrows!")
|
||||||
text['ganon_phase_3_no_silvers'] = CompressedTextMapper.convert("You can't best me without silver arrows!")
|
text['ganon_phase_3_no_silvers'] = CompressedTextMapper.convert("You can't best me without silver arrows!")
|
||||||
text['ganon_phase_3_silvers'] = CompressedTextMapper.convert("Oh no! Silver! My one true weakness!")
|
text['ganon_phase_3_silvers'] = CompressedTextMapper.convert("Oh no! Silver! My one true weakness!")
|
||||||
|
text['murahdahla'] = CompressedTextMapper.convert("Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n{PAUSE3}\n… … …\nWait! you can see me? I knew I should have\nhidden in a hollow tree.")
|
||||||
text['end_pad_data'] = bytearray([0xfb])
|
text['end_pad_data'] = bytearray([0xfb])
|
||||||
text['terminator'] = bytearray([0xFF, 0xFF])
|
text['terminator'] = bytearray([0xFF, 0xFF])
|
||||||
|
|||||||
Reference in New Issue
Block a user