Some fixes for Custom Goals
- Changed spoiler meta output to include goaltext - Fixed GT Cutscene crash - Allow multiple %d to resolve in goaltext
This commit is contained in:
@@ -3274,16 +3274,20 @@ class Spoiler(object):
|
|||||||
custom = self.metadata['custom_goals'][player]
|
custom = self.metadata['custom_goals'][player]
|
||||||
if custom['gtentry'] and 'requirements' in custom['gtentry']:
|
if custom['gtentry'] and 'requirements' in custom['gtentry']:
|
||||||
outfile.write('GT Entry Requirement:'.ljust(line_width) + 'custom\n')
|
outfile.write('GT Entry Requirement:'.ljust(line_width) + 'custom\n')
|
||||||
|
outfile.write(' %s\n' % custom['gtentry']['goaltext'])
|
||||||
else:
|
else:
|
||||||
outfile.write('GT Entry Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_gt_orig[player]))
|
outfile.write('GT Entry Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_gt_orig[player]))
|
||||||
if custom['ganongoal'] and 'requirements' in custom['ganongoal']:
|
if custom['ganongoal'] and 'requirements' in custom['ganongoal']:
|
||||||
outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n')
|
outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n')
|
||||||
|
outfile.write(' %s\n' % custom['ganongoal']['goaltext'])
|
||||||
else:
|
else:
|
||||||
outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player]))
|
outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player]))
|
||||||
if custom['pedgoal'] and 'requirements' in custom['pedgoal']:
|
if custom['pedgoal'] and 'requirements' in custom['pedgoal']:
|
||||||
outfile.write('Pedestal Requirement:'.ljust(line_width) + 'custom\n')
|
outfile.write('Pedestal Requirement:'.ljust(line_width) + 'custom\n')
|
||||||
|
outfile.write(' %s\n' % custom['pedgoal']['goaltext'])
|
||||||
if custom['murahgoal'] and 'requirements' in custom['murahgoal']:
|
if custom['murahgoal'] and 'requirements' in custom['murahgoal']:
|
||||||
outfile.write('Murahdahla Requirement:'.ljust(line_width) + 'custom\n')
|
outfile.write('Murahdahla Requirement:'.ljust(line_width) + 'custom\n')
|
||||||
|
outfile.write(' %s\n' % custom['murahgoal']['goaltext'])
|
||||||
outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player])
|
outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player])
|
||||||
outfile.write('\n')
|
outfile.write('\n')
|
||||||
outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player])
|
outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player])
|
||||||
@@ -3396,20 +3400,22 @@ class Spoiler(object):
|
|||||||
player_name = '' if self.world.players == 1 else str(' (Player ' + str(player) + ')')
|
player_name = '' if self.world.players == 1 else str(' (Player ' + str(player) + ')')
|
||||||
goal = self.world.custom_goals[player]['gtentry']
|
goal = self.world.custom_goals[player]['gtentry']
|
||||||
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
|
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
|
||||||
outfile.write(str('GT Entry Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
|
pass
|
||||||
|
# outfile.write(str('GT Entry Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
|
||||||
elif self.world.crystals_gt_orig[player] == 'random':
|
elif self.world.crystals_gt_orig[player] == 'random':
|
||||||
outfile.write(str('Crystals Required for GT' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['gt_crystals'][player])))
|
outfile.write(str('Crystals Required for GT' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['gt_crystals'][player])))
|
||||||
goal = self.world.custom_goals[player]['ganongoal']
|
goal = self.world.custom_goals[player]['ganongoal']
|
||||||
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
|
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
|
||||||
outfile.write(str('Ganon Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
|
pass
|
||||||
|
# outfile.write(str('Ganon Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
|
||||||
elif self.world.crystals_ganon_orig[player] == 'random':
|
elif self.world.crystals_ganon_orig[player] == 'random':
|
||||||
outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player])))
|
outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player])))
|
||||||
goal = self.world.custom_goals[player]['pedgoal']
|
# goal = self.world.custom_goals[player]['pedgoal']
|
||||||
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
|
# if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
|
||||||
outfile.write(str('Pedestal Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
|
# outfile.write(str('Pedestal Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
|
||||||
goal = self.world.custom_goals[player]['murahgoal']
|
# goal = self.world.custom_goals[player]['murahgoal']
|
||||||
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
|
# if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
|
||||||
outfile.write(str('Murahdahla Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
|
# outfile.write(str('Murahdahla Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
|
||||||
outfile.write('\n\nPrizes:\n\n')
|
outfile.write('\n\nPrizes:\n\n')
|
||||||
for dungeon, prize in self.prizes.items():
|
for dungeon, prize in self.prizes.items():
|
||||||
outfile.write(str(dungeon + ':').ljust(line_width) + '%s\n' % prize)
|
outfile.write(str(dungeon + ':').ljust(line_width) + '%s\n' % prize)
|
||||||
|
|||||||
14
Main.py
14
Main.py
@@ -645,23 +645,23 @@ def resolve_random_settings(world, args):
|
|||||||
else:
|
else:
|
||||||
raise Exception(f'Invalid {list(r.keys())[0]} requirement target for {goal_type}')
|
raise Exception(f'Invalid {list(r.keys())[0]} requirement target for {goal_type}')
|
||||||
if req['condition'] & 0x7F == req_table['Pendants']:
|
if req['condition'] & 0x7F == req_table['Pendants']:
|
||||||
goal['logic']['pendants'] = req['target'] or 3
|
goal['logic']['pendants'] = req['target'] = req.get('target', 3)
|
||||||
elif req['condition'] & 0x7F == req_table['Crystals']:
|
elif req['condition'] & 0x7F == req_table['Crystals']:
|
||||||
goal['logic']['crystals'] = req['target'] or 7
|
goal['logic']['crystals'] = req['target'] = req.get('target', 7)
|
||||||
elif req['condition'] & 0x7F == req_table['PendantBosses']:
|
elif req['condition'] & 0x7F == req_table['PendantBosses']:
|
||||||
goal['logic']['pendant_bosses'] = req['target'] or 3
|
goal['logic']['pendant_bosses'] = req['target'] = req.get('target', 3)
|
||||||
elif req['condition'] & 0x7F == req_table['CrystalBosses']:
|
elif req['condition'] & 0x7F == req_table['CrystalBosses']:
|
||||||
goal['logic']['crystal_bosses'] = req['target'] or 7
|
goal['logic']['crystal_bosses'] = req['target'] = req.get('target', 7)
|
||||||
elif req['condition'] & 0x7F == req_table['PrizeBosses']:
|
elif req['condition'] & 0x7F == req_table['PrizeBosses']:
|
||||||
goal['logic']['bosses'] = req['target'] or 10
|
goal['logic']['bosses'] = req['target'] = req.get('target', 10)
|
||||||
elif req['condition'] & 0x7F == req_table['Aga1']:
|
elif req['condition'] & 0x7F == req_table['Aga1']:
|
||||||
goal['logic']['aga1'] = True
|
goal['logic']['aga1'] = True
|
||||||
elif req['condition'] & 0x7F == req_table['Aga2']:
|
elif req['condition'] & 0x7F == req_table['Aga2']:
|
||||||
goal['logic']['aga2'] = True
|
goal['logic']['aga2'] = True
|
||||||
elif req['condition'] & 0x7F == req_table['TriforcePieces']:
|
elif req['condition'] & 0x7F == req_table['TriforcePieces']:
|
||||||
goal['logic']['goal_items'] = req['target'] or None
|
goal['logic']['goal_items'] = req['target'] = req.get('target', None)
|
||||||
elif req['condition'] & 0x7F == req_table['CollectionRate']:
|
elif req['condition'] & 0x7F == req_table['CollectionRate']:
|
||||||
goal['logic']['collection'] = req['target'] or None
|
goal['logic']['collection'] = req['target'] = req.get('target', None)
|
||||||
goal['requirements'].append(req)
|
goal['requirements'].append(req)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise KeyError(f'Invalid {goal_type} requirement: {r}')
|
raise KeyError(f'Invalid {goal_type} requirement: {r}')
|
||||||
|
|||||||
15
Rom.py
15
Rom.py
@@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = 'a1c8a1c9b4a626f25a240d5b35b17ffe'
|
RANDOMIZERBASEHASH = '39c6d90d9aa4711fe3c95d85b1a9b16e'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -1270,8 +1270,11 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
goal_bytes += [req['target']]
|
goal_bytes += [req['target']]
|
||||||
else:
|
else:
|
||||||
goal_bytes += int16_as_bytes(req['target'])
|
goal_bytes += int16_as_bytes(req['target'])
|
||||||
elif 'target' in req:
|
elif req['condition'] & 0x80 == 0:
|
||||||
if req['condition'] & 0x7F < 0x08:
|
if req['condition'] & 0x7F == 0x06 or req['condition'] & 0x7F == 0x07:
|
||||||
|
# agahnims have no target value
|
||||||
|
pass
|
||||||
|
elif req['condition'] & 0x7F < 0x08:
|
||||||
goal_bytes += [req['target']]
|
goal_bytes += [req['target']]
|
||||||
else:
|
else:
|
||||||
goal_bytes += int16_as_bytes(req['target'])
|
goal_bytes += int16_as_bytes(req['target'])
|
||||||
@@ -2588,8 +2591,10 @@ def write_strings(rom, world, player, team):
|
|||||||
|
|
||||||
def get_custom_goal_text(type):
|
def get_custom_goal_text(type):
|
||||||
goal_text = world.custom_goals[player][type]['goaltext']
|
goal_text = world.custom_goals[player][type]['goaltext']
|
||||||
if '%d' in goal_text:
|
placeholder_count = goal_text.count('%d')
|
||||||
return goal_text % world.custom_goals[player][type]['requirements'][0]['target']
|
if placeholder_count > 0:
|
||||||
|
targets = [req['target'] for req in world.custom_goals[player][type]['requirements'] if 'target' in req][:placeholder_count]
|
||||||
|
return goal_text % tuple(targets)
|
||||||
return goal_text
|
return goal_text
|
||||||
|
|
||||||
if world.custom_goals[player]['gtentry'] and 'goaltext' in world.custom_goals[player]['gtentry']:
|
if world.custom_goals[player]['gtentry'] and 'goaltext' in world.custom_goals[player]['gtentry']:
|
||||||
|
|||||||
Binary file not shown.
@@ -76,7 +76,7 @@ This must be defined by player. Each player number should be listed with the app
|
|||||||
|
|
||||||
* `gtentry` (Ganon's Tower entrance)
|
* `gtentry` (Ganon's Tower entrance)
|
||||||
* `ganongoal` (Ganon vulnerability)
|
* `ganongoal` (Ganon vulnerability)
|
||||||
* `pedpull` (Master Sword Pedestal activation)
|
* `pedgoal` (Master Sword Pedestal activation)
|
||||||
* `murahgoal` (Murahdahla requirement, if given requirements, Murahdahla appears always and acts as an alternative way to beat the game)
|
* `murahgoal` (Murahdahla requirement, if given requirements, Murahdahla appears always and acts as an alternative way to beat the game)
|
||||||
|
|
||||||
These four custom goals use the following identical structure to define them. These goals have four primary subsections: `cutscene_gfx`, `goaltext`, `requirements`, and `logic`
|
These four custom goals use the following identical structure to define them. These goals have four primary subsections: `cutscene_gfx`, `goaltext`, `requirements`, and `logic`
|
||||||
|
|||||||
Reference in New Issue
Block a user