Ganonhunt
This commit is contained in:
@@ -55,7 +55,7 @@ def start():
|
|||||||
Palace, to allow for an alternative to firerod.
|
Palace, to allow for an alternative to firerod.
|
||||||
Vanilla: Swords are in vanilla locations.
|
Vanilla: Swords are in vanilla locations.
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--goal', default='ganon', const='ganon', nargs='?', choices=['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals', 'all_items', 'completionist'],
|
parser.add_argument('--goal', default='ganon', const='ganon', nargs='?', choices=['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'ganonhunt', 'crystals', 'all_items', 'completionist'],
|
||||||
help='''\
|
help='''\
|
||||||
Select completion goal. (default: %(default)s)
|
Select completion goal. (default: %(default)s)
|
||||||
Ganon: Collect all crystals, beat Agahnim 2 then
|
Ganon: Collect all crystals, beat Agahnim 2 then
|
||||||
@@ -66,6 +66,8 @@ def start():
|
|||||||
Agahnim fights and then defeat Ganon.
|
Agahnim fights and then defeat Ganon.
|
||||||
Triforce Hunt: Places 30 Triforce Pieces in the world, collect
|
Triforce Hunt: Places 30 Triforce Pieces in the world, collect
|
||||||
20 of them to beat the game.
|
20 of them to beat the game.
|
||||||
|
Ganonhunt: Places 30 Triforce Pieces in the world, collect
|
||||||
|
20 of them to beat Ganon.
|
||||||
All Items: Requires collecting 216 items to defeat Ganon.
|
All Items: Requires collecting 216 items to defeat Ganon.
|
||||||
Completionist: Same as above, plus All Dungeons
|
Completionist: Same as above, plus All Dungeons
|
||||||
''')
|
''')
|
||||||
|
|||||||
21
ItemList.py
21
ItemList.py
@@ -35,8 +35,8 @@ Difficulty = namedtuple('Difficulty',
|
|||||||
['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield',
|
['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield',
|
||||||
'basicshield', 'progressivearmor', 'basicarmor', 'swordless',
|
'basicshield', 'progressivearmor', 'basicarmor', 'swordless',
|
||||||
'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother',
|
'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother',
|
||||||
'triforcehunt', 'triforce_pieces_required', 'retro',
|
'triforcehunt', 'ganonhunt', 'triforce_pieces_required', 'ganonhunt_pieces_required',
|
||||||
'extras', 'progressive_sword_limit', 'progressive_shield_limit',
|
'retro', 'extras', 'progressive_sword_limit', 'progressive_shield_limit',
|
||||||
'progressive_armor_limit', 'progressive_bottle_limit',
|
'progressive_armor_limit', 'progressive_bottle_limit',
|
||||||
'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit'])
|
'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit'])
|
||||||
|
|
||||||
@@ -59,7 +59,9 @@ difficulties = {
|
|||||||
timedohko = ['Green Clock'] * 25,
|
timedohko = ['Green Clock'] * 25,
|
||||||
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
||||||
triforcehunt = ['Triforce Piece'] * 30,
|
triforcehunt = ['Triforce Piece'] * 30,
|
||||||
|
ganonhunt = ['Triforce Piece'] * 50,
|
||||||
triforce_pieces_required = 20,
|
triforce_pieces_required = 20,
|
||||||
|
ganonhunt_pieces_required = 40,
|
||||||
retro = ['Small Key (Universal)'] * 17 + ['Rupees (20)'] * 10,
|
retro = ['Small Key (Universal)'] * 17 + ['Rupees (20)'] * 10,
|
||||||
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
||||||
progressive_sword_limit = 4,
|
progressive_sword_limit = 4,
|
||||||
@@ -86,7 +88,9 @@ difficulties = {
|
|||||||
timedohko = ['Green Clock'] * 25,
|
timedohko = ['Green Clock'] * 25,
|
||||||
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
||||||
triforcehunt = ['Triforce Piece'] * 30,
|
triforcehunt = ['Triforce Piece'] * 30,
|
||||||
|
ganonhunt = ['Triforce Piece'] * 50,
|
||||||
triforce_pieces_required = 20,
|
triforce_pieces_required = 20,
|
||||||
|
ganonhunt_pieces_required = 40,
|
||||||
retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15,
|
retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15,
|
||||||
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
||||||
progressive_sword_limit = 3,
|
progressive_sword_limit = 3,
|
||||||
@@ -113,7 +117,9 @@ difficulties = {
|
|||||||
timedohko = ['Green Clock'] * 20 + ['Red Clock'] * 5,
|
timedohko = ['Green Clock'] * 20 + ['Red Clock'] * 5,
|
||||||
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
||||||
triforcehunt = ['Triforce Piece'] * 30,
|
triforcehunt = ['Triforce Piece'] * 30,
|
||||||
|
ganonhunt = ['Triforce Piece'] * 50,
|
||||||
triforce_pieces_required = 20,
|
triforce_pieces_required = 20,
|
||||||
|
ganonhunt_pieces_required = 40,
|
||||||
retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15,
|
retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15,
|
||||||
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
||||||
progressive_sword_limit = 2,
|
progressive_sword_limit = 2,
|
||||||
@@ -127,7 +133,7 @@ difficulties = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def generate_itempool(world, player):
|
def generate_itempool(world, player):
|
||||||
if (world.difficulty not in ['normal', 'hard', 'expert'] or world.goal not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals', 'all_items', 'completionist']
|
if (world.difficulty not in ['normal', 'hard', 'expert'] or world.goal not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'ganonhunt', 'crystals', 'all_items', 'completionist']
|
||||||
or world.mode not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']):
|
or world.mode not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']):
|
||||||
raise NotImplementedError('Not supported yet')
|
raise NotImplementedError('Not supported yet')
|
||||||
|
|
||||||
@@ -457,11 +463,16 @@ def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, r
|
|||||||
pool.extend(diff.timedohko)
|
pool.extend(diff.timedohko)
|
||||||
extraitems -= len(diff.timedohko)
|
extraitems -= len(diff.timedohko)
|
||||||
clock_mode = 'countdown-ohko'
|
clock_mode = 'countdown-ohko'
|
||||||
if goal == 'triforcehunt':
|
if goal in ['triforcehunt']:
|
||||||
pool.extend(diff.triforcehunt)
|
pool.extend(diff.triforcehunt)
|
||||||
extraitems -= len(diff.triforcehunt)
|
extraitems -= len(diff.triforcehunt)
|
||||||
treasure_hunt_count = diff.triforce_pieces_required
|
treasure_hunt_count = diff.triforce_pieces_required
|
||||||
treasure_hunt_icon = 'Triforce Piece'
|
treasure_hunt_icon = 'Triforce Piece'
|
||||||
|
if goal in ['ganonhunt']:
|
||||||
|
pool.extend(diff.ganonhunt)
|
||||||
|
extraitems -= len(diff.ganonhunt)
|
||||||
|
treasure_hunt_count = diff.ganonhunt_pieces_required
|
||||||
|
treasure_hunt_icon = 'Triforce Piece'
|
||||||
|
|
||||||
for extra in diff.extras:
|
for extra in diff.extras:
|
||||||
if extraitems > 0:
|
if extraitems > 0:
|
||||||
@@ -582,7 +593,7 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
|||||||
treasure_hunt_count = max(min(customitemarray[65], 99), 1) #To display, count must be between 1 and 99.
|
treasure_hunt_count = max(min(customitemarray[65], 99), 1) #To display, count must be between 1 and 99.
|
||||||
treasure_hunt_icon = 'Triforce Piece'
|
treasure_hunt_icon = 'Triforce Piece'
|
||||||
# Ensure game is always possible to complete here, force sufficient pieces if the player is unwilling.
|
# Ensure game is always possible to complete here, force sufficient pieces if the player is unwilling.
|
||||||
if (customitemarray[64] < treasure_hunt_count) and (goal == 'triforcehunt') and (customitemarray[66] == 0):
|
if (customitemarray[64] < treasure_hunt_count) and (goal in ['triforcehunt', 'ganonhunt']) and (customitemarray[66] == 0):
|
||||||
extrapieces = treasure_hunt_count - customitemarray[64]
|
extrapieces = treasure_hunt_count - customitemarray[64]
|
||||||
pool.extend(['Triforce Piece'] * extrapieces)
|
pool.extend(['Triforce Piece'] * extrapieces)
|
||||||
itemtotal = itemtotal + extrapieces
|
itemtotal = itemtotal + extrapieces
|
||||||
|
|||||||
18
Rom.py
18
Rom.py
@@ -905,6 +905,8 @@ def patch_rom(world, player, rom):
|
|||||||
rom.write_byte(0x18003E, 0x0A) # make ganon invincible until all items
|
rom.write_byte(0x18003E, 0x0A) # make ganon invincible until all items
|
||||||
elif world.goal in ['completionist']:
|
elif world.goal in ['completionist']:
|
||||||
rom.write_byte(0x18003E, 0x0B) # make ganon invincible until all items and dungeons
|
rom.write_byte(0x18003E, 0x0B) # make ganon invincible until all items and dungeons
|
||||||
|
elif world.goal in ['ganonhunt']:
|
||||||
|
rom.write_byte(0x18003E, 0x05) # make ganon invincible until goal triforce pieces
|
||||||
else:
|
else:
|
||||||
rom.write_byte(0x18003E, 0x03) # make ganon invincible until all crystals and aga 2 are collected
|
rom.write_byte(0x18003E, 0x03) # make ganon invincible until all crystals and aga 2 are collected
|
||||||
|
|
||||||
@@ -1040,7 +1042,7 @@ def patch_rom(world, player, rom):
|
|||||||
# write total item count and item counter hud mode
|
# write total item count and item counter hud mode
|
||||||
item_total = len(world.get_filled_locations()) - 18 # minus non-item locations
|
item_total = len(world.get_filled_locations()) - 18 # minus non-item locations
|
||||||
rom.write_int16(0x180196, item_total+1)
|
rom.write_int16(0x180196, item_total+1)
|
||||||
if world.item_counter_hud[player] and world.goal != 'triforcehunt':
|
if world.item_counter_hud[player] and world.goal not in ['triforcehunt', 'ganonhunt']:
|
||||||
rom.write_byte(0x180039, 0x01)
|
rom.write_byte(0x180039, 0x01)
|
||||||
else:
|
else:
|
||||||
rom.write_byte(0x180039, 0x00)
|
rom.write_byte(0x180039, 0x00)
|
||||||
@@ -1337,10 +1339,11 @@ def write_strings(rom, world, player):
|
|||||||
if world.goal == 'ganon':
|
if world.goal == 'ganon':
|
||||||
ganon_crystals_singular = 'To beat Ganon you must collect %d crystal and defeat his minion at the top of his tower.'
|
ganon_crystals_singular = 'To beat Ganon you must collect %d crystal and defeat his minion at the top of his tower.'
|
||||||
ganon_crystals_plural = 'To beat Ganon you must collect %d crystals and defeat his minion at the top of his tower.'
|
ganon_crystals_plural = 'To beat Ganon you must collect %d crystals and defeat his minion at the top of his tower.'
|
||||||
|
tt['sign_ganon'] = (ganon_crystals_singular if world.crystals_needed_for_ganon == 1 else ganon_crystals_plural) % world.crystals_needed_for_ganon
|
||||||
tt['sign_ganon'] = (ganon_crystals_singular if world.crystals_needed_for_ganon == 1 else ganon_crystals_plural) % world.crystals_needed_for_ganon
|
if world.goal == 'ganonhunt':
|
||||||
|
ganon_triforce_singular = 'To beat Ganon you must collect %d triforce pieces and defeat his minion at the top of his tower.'
|
||||||
|
ganon_triforce_plural = 'To beat Ganon you must collect %d triforce pieces and defeat his minion at the top of his tower.'
|
||||||
|
tt['sign_ganon'] = (ganon_triforce_singular if world.treasure_hunt_count == 1 else ganon_triforce_plural) % world.treasure_hunt_count
|
||||||
|
|
||||||
if world.goal in ['dungeons']:
|
if world.goal in ['dungeons']:
|
||||||
tt['sign_ganon'] = 'You need to complete all the dungeons.'
|
tt['sign_ganon'] = 'You need to complete all the dungeons.'
|
||||||
@@ -1358,6 +1361,11 @@ def write_strings(rom, world, player):
|
|||||||
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
|
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 ['ganonhunt']:
|
||||||
|
tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)]
|
||||||
|
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['sign_ganon'] = 'You need %d triforce pieces to beat Ganon.'
|
||||||
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.'
|
||||||
|
|||||||
12
Rules.py
12
Rules.py
@@ -466,7 +466,10 @@ def global_rules(world, player):
|
|||||||
forbid_item(world.get_location(location, player), 'Big Key (Ganons Tower)', player)
|
forbid_item(world.get_location(location, player), 'Big Key (Ganons Tower)', player)
|
||||||
|
|
||||||
set_rule(world.get_location('Ganon', player), lambda state: state.has_beam_sword(player) and state.has_fire_source(player) and state.has_crystals(world.crystals_needed_for_ganon, player)
|
set_rule(world.get_location('Ganon', player), lambda state: state.has_beam_sword(player) and state.has_fire_source(player) and state.has_crystals(world.crystals_needed_for_ganon, player)
|
||||||
and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or (state.has('Silver Arrows', player) and state.can_shoot_arrows(player)) or state.has('Lamp', player) or state.can_extend_magic(player, 12))) # need to light torch a sufficient amount of times
|
and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or (state.has('Silver Arrows', player) and state.can_shoot_arrows(player)) or state.has('Lamp', player) or state.can_extend_magic(player, 12))
|
||||||
|
and (False if world.goal == 'completionist' and (world.accessibility != 'locations') else True)
|
||||||
|
and (False if (world.goal == 'ganonhunt' and not state.has('Triforce Piece', player, world.treasure_hunt_count)) else True)
|
||||||
|
)
|
||||||
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop
|
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop
|
||||||
|
|
||||||
set_rule(world.get_entrance('Ganons Tower', player), lambda state: False) # This is a safety for the TR function below to not require GT entrance in its key logic.
|
set_rule(world.get_entrance('Ganons Tower', player), lambda state: False) # This is a safety for the TR function below to not require GT entrance in its key logic.
|
||||||
@@ -876,7 +879,10 @@ def inverted_rules(world, player):
|
|||||||
forbid_item(world.get_location(location, player), 'Big Key (Ganons Tower)', player)
|
forbid_item(world.get_location(location, player), 'Big Key (Ganons Tower)', player)
|
||||||
|
|
||||||
set_rule(world.get_location('Ganon', player), lambda state: state.has_beam_sword(player) and state.has_fire_source(player) and state.has_crystals(world.crystals_needed_for_ganon, player)
|
set_rule(world.get_location('Ganon', player), lambda state: state.has_beam_sword(player) and state.has_fire_source(player) and state.has_crystals(world.crystals_needed_for_ganon, player)
|
||||||
and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or (state.has('Silver Arrows', player) and state.can_shoot_arrows(player)) or state.has('Lamp', player) or state.can_extend_magic(player, 12))) # need to light torch a sufficient amount of times
|
and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or (state.has('Silver Arrows', player) and state.can_shoot_arrows(player)) or state.has('Lamp', player) or state.can_extend_magic(player, 12))
|
||||||
|
and (False if world.goal == 'completionist' and (world.accessibility != 'locations') else True)
|
||||||
|
and (False if (world.goal == 'ganonhunt' and not state.has('Triforce Piece', player, world.treasure_hunt_count)) else True)
|
||||||
|
)
|
||||||
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop
|
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop
|
||||||
|
|
||||||
set_rule(world.get_entrance('Inverted Ganons Tower', player), lambda state: False) # This is a safety for the TR function below to not require GT entrance in its key logic.
|
set_rule(world.get_entrance('Inverted Ganons Tower', player), lambda state: False) # This is a safety for the TR function below to not require GT entrance in its key logic.
|
||||||
@@ -1055,7 +1061,7 @@ def set_trock_key_rules(world, player):
|
|||||||
# No matter what, the Big Key cannot be in the Big Chest or held by Trinexx.
|
# No matter what, the Big Key cannot be in the Big Chest or held by Trinexx.
|
||||||
non_big_key_locations = ['Turtle Rock - Big Chest', 'Turtle Rock - Boss']
|
non_big_key_locations = ['Turtle Rock - Big Chest', 'Turtle Rock - Boss']
|
||||||
|
|
||||||
def tr_big_key_chest_keys_needed(world, state):
|
def tr_big_key_chest_keys_needed(state):
|
||||||
# This function handles the key requirements for the TR Big Chest in the situations it having the Big Key should logically require 2 keys, small key
|
# This function handles the key requirements for the TR Big Chest in the situations it having the Big Key should logically require 2 keys, small key
|
||||||
# should logically require no keys, and anything else should logically require 4 keys.
|
# should logically require no keys, and anything else should logically require 4 keys.
|
||||||
item = item_name(state, 'Turtle Rock - Big Key Chest', player)
|
item = item_name(state, 'Turtle Rock - Big Key Chest', player)
|
||||||
|
|||||||
Reference in New Issue
Block a user