make triforce pieces required an option

This commit is contained in:
Fabian Dill 2020-06-07 15:22:24 +02:00
parent 68f453f802
commit 17f884d047
6 changed files with 34 additions and 18 deletions

View File

@ -114,6 +114,7 @@ class World(object):
set_player_attr('glitch_boots', True) set_player_attr('glitch_boots', True)
set_player_attr('progression_balancing', True) set_player_attr('progression_balancing', True)
set_player_attr('local_items', set()) set_player_attr('local_items', set())
set_player_attr('triforce_pieces_required', 20)
def get_name_string_for_object(self, obj) -> str: def get_name_string_for_object(self, obj) -> str:
return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})' return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'
@ -1193,7 +1194,8 @@ class Spoiler(object):
'shufflepots': self.world.shufflepots, 'shufflepots': self.world.shufflepots,
'players': self.world.players, 'players': self.world.players,
'teams': self.world.teams, 'teams': self.world.teams,
'progression_balancing' : self.world.progression_balancing 'progression_balancing': self.world.progression_balancing,
'triforce_pieces_required': self.world.triforce_pieces_required,
} }
def to_json(self): def to_json(self):
@ -1227,25 +1229,33 @@ class Spoiler(object):
outfile.write('\nPlayer %d: %s\n' % (player, self.world.get_player_names(player))) outfile.write('\nPlayer %d: %s\n' % (player, self.world.get_player_names(player)))
for team in range(self.world.teams): for team in range(self.world.teams):
outfile.write('%s%s\n' % ( outfile.write('%s%s\n' % (
f"Hash - {self.world.player_names[player][team]} (Team {team + 1}): " if self.world.teams > 1 else 'Hash: ', f"Hash - {self.world.player_names[player][team]} (Team {team + 1}): " if self.world.teams > 1 else 'Hash: ',
self.hashes[player, team])) self.hashes[player, team]))
outfile.write('Logic: %s\n' % self.metadata['logic'][player]) outfile.write('Logic: %s\n' % self.metadata['logic'][player])
if self.world.players > 1: if self.world.players > 1:
outfile.write('Progression Balanced: %s\n' % ('Yes' if self.metadata['progression_balancing'][player] else 'No')) outfile.write('Progression Balanced: %s\n' % (
'Yes' if self.metadata['progression_balancing'][player] else 'No'))
outfile.write('Mode: %s\n' % self.metadata['mode'][player]) outfile.write('Mode: %s\n' % self.metadata['mode'][player])
outfile.write('Retro: %s\n' % ('Yes' if self.metadata['retro'][player] else 'No')) outfile.write(
'Retro: %s\n' % ('Yes' if self.metadata['retro'][player] else 'No'))
outfile.write('Swords: %s\n' % self.metadata['weapons'][player]) outfile.write('Swords: %s\n' % self.metadata['weapons'][player])
outfile.write('Goal: %s\n' % self.metadata['goal'][player]) outfile.write('Goal: %s\n' % self.metadata['goal'][player])
if "triforce" in self.metadata["goal"][player]: # triforce hunt
outfile.write(
"Pieces required for Triforce: %s\n" % self.metadata["triforce_pieces_required"][player])
outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player]) outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player])
outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player]) outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player])
outfile.write('Item Progression: %s\n' % self.metadata['progressive'][player]) outfile.write('Item Progression: %s\n' % self.metadata['progressive'][player])
outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player]) outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player])
outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player]) outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player])
outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player]) outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player])
outfile.write('Pyramid hole pre-opened: %s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No')) outfile.write('Pyramid hole pre-opened: %s\n' % (
'Yes' if self.metadata['open_pyramid'][player] else 'No'))
outfile.write('Accessibility: %s\n' % self.metadata['accessibility'][player]) outfile.write('Accessibility: %s\n' % self.metadata['accessibility'][player])
outfile.write('Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No')) outfile.write(
outfile.write('Compass shuffle: %s\n' % ('Yes' if self.metadata['compassshuffle'][player] else 'No')) 'Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No'))
outfile.write('Compass shuffle: %s\n' % (
'Yes' if self.metadata['compassshuffle'][player] else 'No'))
outfile.write('Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'][player] else 'No')) outfile.write('Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'][player] else 'No'))
outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'][player] else 'No')) outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'][player] else 'No'))
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player]) outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player])

View File

@ -81,15 +81,20 @@ def parse_arguments(argv, no_defaults=False):
Local Triforce Hunt: Places 30 Triforce Pieces in your world, collect Local Triforce Hunt: Places 30 Triforce Pieces in your world, collect
20 of them to beat the game. 20 of them to beat the game.
''') ''')
parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'], parser.add_argument('--triforce_pieces_required', default=defval(20),
type=lambda value: min(max(int(value), 1), 30),
help='''Set Triforce Pieces required to win a Triforce Hunt''')
parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?',
choices=['normal', 'hard', 'expert'],
help='''\ help='''\
Select game difficulty. Affects available itempool. (default: %(default)s) Select game difficulty. Affects available itempool. (default: %(default)s)
Normal: Normal difficulty. Normal: Normal difficulty.
Hard: A harder setting with less equipment and reduced health. Hard: A harder setting with less equipment and reduced health.
Expert: A harder yet setting with minimum equipment and health. Expert: A harder yet setting with minimum equipment and health.
''') ''')
parser.add_argument('--item_functionality', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'], parser.add_argument('--item_functionality', default=defval('normal'), const='normal', nargs='?',
help='''\ choices=['normal', 'hard', 'expert'],
help='''\
Select limits on item functionality to increase difficulty. (default: %(default)s) Select limits on item functionality to increase difficulty. (default: %(default)s)
Normal: Normal functionality. Normal: Normal functionality.
Hard: Reduced functionality. Hard: Reduced functionality.
@ -329,7 +334,7 @@ def parse_arguments(argv, no_defaults=False):
'local_items', 'retro', 'accessibility', 'hints', 'beemizer', 'local_items', 'retro', 'accessibility', 'hints', 'beemizer',
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
'heartbeep', "skip_progression_balancing", 'heartbeep', "skip_progression_balancing", "triforce_pieces_required",
'remote_items', 'progressive', 'extendedmsu', 'dungeon_counters', 'glitch_boots']: 'remote_items', 'progressive', 'extendedmsu', 'dungeon_counters', 'glitch_boots']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1: if player == 1:

View File

@ -33,7 +33,7 @@ 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', 'retro',
'extras', 'progressive_sword_limit', 'progressive_shield_limit', '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'])
@ -57,7 +57,6 @@ 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,
triforce_pieces_required = 20,
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,
@ -84,7 +83,6 @@ 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,
triforce_pieces_required = 20,
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,
@ -111,7 +109,6 @@ 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,
triforce_pieces_required = 20,
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,
@ -507,7 +504,7 @@ def get_pool_core(world, player: int):
if goal in {'triforcehunt', 'localtriforcehunt'}: if goal in {'triforcehunt', 'localtriforcehunt'}:
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 = world.triforce_pieces_required[player]
treasure_hunt_icon = 'Triforce Piece' treasure_hunt_icon = 'Triforce Piece'
for extra in diff.extras: for extra in diff.extras:

View File

@ -59,6 +59,7 @@ def main(args, seed=None):
world.dungeon_counters = args.dungeon_counters.copy() world.dungeon_counters = args.dungeon_counters.copy()
world.extendedmsu = args.extendedmsu.copy() world.extendedmsu = args.extendedmsu.copy()
world.glitch_boots = args.glitch_boots.copy() world.glitch_boots = args.glitch_boots.copy()
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.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)} world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}

View File

@ -294,6 +294,10 @@ def roll_settings(weights):
ret.crystals_ganon = get_choice('ganon_open', weights) ret.crystals_ganon = get_choice('ganon_open', weights)
ret.triforce_pieces_required = get_choice('triforce_pieces_required',
weights) if "triforce_pieces_required" in weights else 20
ret.triforce_pieces_required = min(max(1, int(ret.triforce_pieces_required)), 30)
ret.mode = get_choice('world_state', weights) ret.mode = get_choice('world_state', weights)
if ret.mode == 'retro': if ret.mode == 'retro':
ret.mode = 'open' ret.mode = 'open'

1
Rom.py
View File

@ -637,7 +637,6 @@ def patch_rom(world, rom, player, team, enemized):
rom.write_byte(0x18003A, 0x01 if world.dark_world_light_cone else 0x00) rom.write_byte(0x18003A, 0x01 if world.dark_world_light_cone else 0x00)
GREEN_TWENTY_RUPEES = 0x47 GREEN_TWENTY_RUPEES = 0x47
TRIFORCE_PIECE = ItemFactory('Triforce Piece', player).code
GREEN_CLOCK = ItemFactory('Green Clock', player).code GREEN_CLOCK = ItemFactory('Green Clock', player).code
rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on