Skip to content

Commit 7e29330

Browse files
committed
Merge branch 'OverworldShuffleDev' into OverworldShuffle
2 parents 3f77398 + f66ec98 commit 7e29330

10 files changed

Lines changed: 99 additions & 59 deletions

File tree

BaseClasses.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3274,16 +3274,20 @@ def yn(flag):
32743274
custom = self.metadata['custom_goals'][player]
32753275
if custom['gtentry'] and 'requirements' in custom['gtentry']:
32763276
outfile.write('GT Entry Requirement:'.ljust(line_width) + 'custom\n')
3277+
outfile.write(' %s\n' % custom['gtentry']['goaltext'])
32773278
else:
32783279
outfile.write('GT Entry Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_gt_orig[player]))
32793280
if custom['ganongoal'] and 'requirements' in custom['ganongoal']:
32803281
outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n')
3282+
outfile.write(' %s\n' % custom['ganongoal']['goaltext'])
32813283
else:
32823284
outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player]))
32833285
if custom['pedgoal'] and 'requirements' in custom['pedgoal']:
32843286
outfile.write('Pedestal Requirement:'.ljust(line_width) + 'custom\n')
3287+
outfile.write(' %s\n' % custom['pedgoal']['goaltext'])
32853288
if custom['murahgoal'] and 'requirements' in custom['murahgoal']:
32863289
outfile.write('Murahdahla Requirement:'.ljust(line_width) + 'custom\n')
3290+
outfile.write(' %s\n' % custom['murahgoal']['goaltext'])
32873291
outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player])
32883292
outfile.write('\n')
32893293
outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player])
@@ -3396,20 +3400,22 @@ def to_file(self, filename):
33963400
player_name = '' if self.world.players == 1 else str(' (Player ' + str(player) + ')')
33973401
goal = self.world.custom_goals[player]['gtentry']
33983402
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
3399-
outfile.write(str('GT Entry Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
3403+
pass
3404+
# outfile.write(str('GT Entry Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
34003405
elif self.world.crystals_gt_orig[player] == 'random':
34013406
outfile.write(str('Crystals Required for GT' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['gt_crystals'][player])))
34023407
goal = self.world.custom_goals[player]['ganongoal']
34033408
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
3404-
outfile.write(str('Ganon Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
3409+
pass
3410+
# outfile.write(str('Ganon Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
34053411
elif self.world.crystals_ganon_orig[player] == 'random':
34063412
outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player])))
3407-
goal = self.world.custom_goals[player]['pedgoal']
3408-
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
3409-
outfile.write(str('Pedestal Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
3410-
goal = self.world.custom_goals[player]['murahgoal']
3411-
if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
3412-
outfile.write(str('Murahdahla Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
3413+
# goal = self.world.custom_goals[player]['pedgoal']
3414+
# if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
3415+
# outfile.write(str('Pedestal Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
3416+
# goal = self.world.custom_goals[player]['murahgoal']
3417+
# if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00:
3418+
# outfile.write(str('Murahdahla Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext'])
34133419
outfile.write('\n\nPrizes:\n\n')
34143420
for dungeon, prize in self.prizes.items():
34153421
outfile.write(str(dungeon + ':').ljust(line_width) + '%s\n' % prize)

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 0.6.1.2
4+
- Various fixes for Custom Goal Framework
5+
- Added custom gfx for Pedestal and Murahdahla
6+
- Re-fixed purple chest follower dupe
7+
- Updated tournament winners texts
8+
39
## 0.6.1.1
410
- Fixed issue with Bosses goals in Custom Goal Framework
511
- Fixed error when using Custom Goals with no extra values

Main.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -645,23 +645,23 @@ def process_goal(goal_type):
645645
else:
646646
raise Exception(f'Invalid {list(r.keys())[0]} requirement target for {goal_type}')
647647
if req['condition'] & 0x7F == req_table['Pendants']:
648-
goal['logic']['pendants'] = req['target'] or 3
648+
goal['logic']['pendants'] = req['target'] = req.get('target', 3)
649649
elif req['condition'] & 0x7F == req_table['Crystals']:
650-
goal['logic']['crystals'] = req['target'] or 7
650+
goal['logic']['crystals'] = req['target'] = req.get('target', 7)
651651
elif req['condition'] & 0x7F == req_table['PendantBosses']:
652-
goal['logic']['pendant_bosses'] = req['target'] or 3
652+
goal['logic']['pendant_bosses'] = req['target'] = req.get('target', 3)
653653
elif req['condition'] & 0x7F == req_table['CrystalBosses']:
654-
goal['logic']['crystal_bosses'] = req['target'] or 7
654+
goal['logic']['crystal_bosses'] = req['target'] = req.get('target', 7)
655655
elif req['condition'] & 0x7F == req_table['PrizeBosses']:
656-
goal['logic']['bosses'] = req['target'] or 10
656+
goal['logic']['bosses'] = req['target'] = req.get('target', 10)
657657
elif req['condition'] & 0x7F == req_table['Aga1']:
658658
goal['logic']['aga1'] = True
659659
elif req['condition'] & 0x7F == req_table['Aga2']:
660660
goal['logic']['aga2'] = True
661661
elif req['condition'] & 0x7F == req_table['TriforcePieces']:
662-
goal['logic']['goal_items'] = req['target'] or None
662+
goal['logic']['goal_items'] = req['target'] = req.get('target', None)
663663
elif req['condition'] & 0x7F == req_table['CollectionRate']:
664-
goal['logic']['collection'] = req['target'] or None
664+
goal['logic']['collection'] = req['target'] = req.get('target', None)
665665
goal['requirements'].append(req)
666666
except KeyError:
667667
raise KeyError(f'Invalid {goal_type} requirement: {r}')

OverworldShuffle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from OverworldGlitchRules import create_owg_connections
99
from Utils import bidict
1010

11-
version_number = '0.6.1.1'
11+
version_number = '0.6.1.2'
1212
# branch indicator is intentionally different across branches
1313
version_branch = ''
1414

Rom.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444

4545
JAP10HASH = '03a63945398191337e896e5771f77173'
46-
RANDOMIZERBASEHASH = '72c4b2d00057d1faced32871d8081f3a'
46+
RANDOMIZERBASEHASH = '2039c11b935d3b81f78810d9f4be19d6'
4747

4848

4949
class JsonRom(object):
@@ -1270,8 +1270,11 @@ def get_goal_bytes(type):
12701270
goal_bytes += [req['target']]
12711271
else:
12721272
goal_bytes += int16_as_bytes(req['target'])
1273-
elif 'target' in req:
1274-
if req['condition'] & 0x7F < 0x08:
1273+
elif req['condition'] & 0x80 == 0:
1274+
if req['condition'] & 0x7F == 0x06 or req['condition'] & 0x7F == 0x07:
1275+
# agahnims have no target value
1276+
pass
1277+
elif req['condition'] & 0x7F < 0x08:
12751278
goal_bytes += [req['target']]
12761279
else:
12771280
goal_bytes += int16_as_bytes(req['target'])
@@ -1338,12 +1341,19 @@ def get_goal_bytes(type):
13381341
if start_address > 0x81D8:
13391342
raise Exception("Custom Goal data too long to fit in allocated space, try reducing the amount of requirements.")
13401343

1341-
# gt entry
1342-
gtentry = world.custom_goals[player]['gtentry']
1343-
if gtentry and 'cutscene_gfx' in gtentry:
1344-
gfx = gtentry['cutscene_gfx']
1345-
write_int16(rom, snes_to_pc(0x3081D8), gfx[0])
1346-
rom.write_byte(snes_to_pc(0x3081E6), gfx[1])
1344+
# goal cutscene gfx
1345+
goals = {
1346+
#goal: gfx addr, palette addr
1347+
'gtentry': (0x3081D8, 0x3081E6),
1348+
'pedgoal': (0x3081ED, 0x3081F3),
1349+
'murahgoal': (0x3081F6, 0x3081FC),
1350+
}
1351+
for goal_type, gfx_addr in goals.items():
1352+
goal = world.custom_goals[player][goal_type]
1353+
if goal and 'cutscene_gfx' in goal:
1354+
gfx = goal['cutscene_gfx']
1355+
write_int16(rom, snes_to_pc(gfx_addr[0]), gfx[0])
1356+
rom.write_byte(snes_to_pc(gfx_addr[1]), gfx[1])
13471357

13481358
# block HC upstairs doors in rain state in standard mode
13491359
prevent_rain = world.mode[player] == 'standard' and world.shuffle[player] != 'vanilla' and world.logic[player] != 'nologic'
@@ -1751,7 +1761,7 @@ def get_reveal_bytes(itemName):
17511761
gen, seedstring = rom_header.split('|', 1)
17521762
gen = f'{gen:<3}'
17531763
seedstring = f'{int(seedstring):09}' if seedstring.isdigit() else seedstring[:9]
1754-
rom.name = bytearray(f'{gen}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21]
1764+
rom.name = bytearray(f'OR{gen}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21]
17551765
elif len(rom_header) <= 9:
17561766
seedstring = f'{int(rom_header):09}' if rom_header.isdigit() else rom_header
17571767
rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21]
@@ -2581,8 +2591,10 @@ def missing_prize():
25812591

25822592
def get_custom_goal_text(type):
25832593
goal_text = world.custom_goals[player][type]['goaltext']
2584-
if '%d' in goal_text:
2585-
return goal_text % world.custom_goals[player][type]['requirements'][0]['target']
2594+
placeholder_count = goal_text.count('%d')
2595+
if placeholder_count > 0:
2596+
targets = [req['target'] for req in world.custom_goals[player][type]['requirements'] if 'target' in req][:placeholder_count]
2597+
return goal_text % tuple(targets)
25862598
return goal_text
25872599

25882600
if world.custom_goals[player]['gtentry'] and 'goaltext' in world.custom_goals[player]['gtentry']:

Rules.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,6 +1805,9 @@ def check_rule_list(state, r_list):
18051805
add_rule(world.get_location('Hyrule Castle Tree', player), lambda state: state.has('Zelda Delivered', player))
18061806
add_rule(world.get_location('Central Bonk Rocks Tree', player), lambda state: state.has('Zelda Delivered', player))
18071807

1808+
if not world.is_copied_world:
1809+
add_rule(world.get_location('Hyrule Castle Courtyard Tree Pull', player), lambda state: state.has('Zelda Delivered', player))
1810+
18081811
# don't allow bombs to get past here before zelda is rescued
18091812
set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: (state.can_use_bombs(player) and state.has('Zelda Delivered', player)) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) # or state.has('Cane of Somaria', player))
18101813

Text.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1782,6 +1782,8 @@ def setDefaultText(self):
17821782
text['hylian_text_2'] = CompressedTextMapper.convert("%%^= %==%\n ^ =%^=\n==%= ^^%^")
17831783
text['desert_entry_translated'] = CompressedTextMapper.convert("Kneel before this stone, and magic will move around you.")
17841784
text['telepathic_tile_under_ganon'] = CompressedTextMapper.convert("Doors Async League winners\n{HARP}\n"
1785+
" ~~~2025~~~\nSchulzer\n\n"
1786+
" ~~~2024~~~\nhumbugh\n\n"
17851787
" ~~~2023~~~\nEriror\n\n"
17861788
" ~~~2022~~~\nAndy\n\n"
17871789
" ~~~2021~~~\nprdwong")
@@ -1795,7 +1797,8 @@ def setDefaultText(self):
17951797
text['telepathic_tile_ice_stalfos_knights_room'] = CompressedTextMapper.convert("{NOBORDER}\nKnock 'em down and then bomb them dead.")
17961798
text['telepathic_tile_tower_of_hera_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a bad place, with a guy who will make you fall…\n\n\na lot.")
17971799
text['houlihan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n"
1798-
" ~~~2023~~~\nnGanonsGoneWild\n\n"
1800+
" ~~~2024~~~\nGammachuu\n\n"
1801+
" ~~~2023~~~\nGanonsGoneWild\n\n"
17991802
" ~~~2022~~~\nObscure\n\n"
18001803
" ~~~2021~~~\nDaaanty\n\n"
18011804
" ~~~2019~~~\nJet082\n\n"
@@ -2029,6 +2032,7 @@ def setDefaultText(self):
20292032
text['ganon_phase_3_alt'] = CompressedTextMapper.convert("Got wax in your ears? I cannot die!")
20302033
# 190
20312034
text['sign_east_death_mountain_bridge'] = CompressedTextMapper.convert("Glitched\ntournament\nwinners\n{HARP}\n"
2035+
"~~~HMG 2025~~~\nSkele\n"
20322036
"~~~No Logic 2024~~~\ntam\n\n"
20332037
"~~~HMG 2023~~~\ntam\n\n"
20342038
"~~~No Logic 2022~~~\nChexhuman\n\n"

data/base2current.bps

142 Bytes
Binary file not shown.

source/classes/CustomSettings.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -577,9 +577,13 @@ def write_to_file(self, destination):
577577

578578

579579
def load_yaml(path):
580-
if os.path.exists(Path(path)):
581-
with open(path, "r", encoding="utf-8") as f:
582-
return yaml.load(f, Loader=yaml.SafeLoader)
583-
elif urllib.parse.urlparse(path).scheme in ['http', 'https']:
584-
return yaml.load(urllib.request.urlopen(path), Loader=yaml.FullLoader)
580+
try:
581+
if os.path.exists(Path(path)):
582+
with open(path, "r", encoding="utf-8") as f:
583+
return yaml.load(f, Loader=yaml.SafeLoader)
584+
elif urllib.parse.urlparse(path).scheme in ['http', 'https']:
585+
return yaml.load(urllib.request.urlopen(path), Loader=yaml.FullLoader)
586+
except yaml.YAMLError as e:
587+
error_msg = f"Error parsing YAML file '{path}':\n{str(e)}"
588+
raise ValueError(error_msg) from e
585589

source/gui/bottom.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -77,32 +77,37 @@ def generateRom():
7777
argsDump['sprite'] = argsDump['sprite'].name
7878
save_settings(parent, argsDump, "last.json")
7979

80-
guiargs = create_guiargs(parent)
81-
# get default values for missing parameters
82-
cliargs = ['--multi', str(guiargs.multi)]
83-
if hasattr(guiargs, 'customizer'):
84-
cliargs.extend(['--customizer', str(guiargs.customizer)])
85-
for k,v in vars(parse_cli(cliargs)).items():
86-
if k not in vars(guiargs):
87-
setattr(guiargs, k, v)
88-
elif type(v) is dict: # use same settings for every player
89-
players = guiargs.multi if len(v) == 0 else len(v)
90-
setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, players + 1)})
91-
argsDump = vars(guiargs)
92-
93-
needEnemizer = False
94-
falsey = ["none", "default", False, 0]
95-
for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]:
96-
if enemizerOption in argsDump:
97-
if isinstance(argsDump[enemizerOption], dict):
98-
for playerID,playerSetting in argsDump[enemizerOption].items():
99-
if not playerSetting in falsey:
100-
needEnemizer = True
101-
elif not argsDump[enemizerOption] in falsey:
102-
needEnemizer = True
103-
seeds = []
104-
10580
try:
81+
guiargs = create_guiargs(parent)
82+
# get default values for missing parameters
83+
cliargs = ['--multi', str(guiargs.multi)]
84+
if hasattr(guiargs, 'customizer'):
85+
cliargs.extend(['--customizer', str(guiargs.customizer)])
86+
87+
for k,v in vars(parse_cli(cliargs)).items():
88+
if k not in vars(guiargs):
89+
setattr(guiargs, k, v)
90+
elif type(v) is dict: # use same settings for every player
91+
players = guiargs.multi if len(v) == 0 else len(v)
92+
setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, players + 1)})
93+
if guiargs.multi == 1 and guiargs.names.endswith("=="):
94+
# allow settings code thru player names entry
95+
guiargs.code[1] = guiargs.names
96+
guiargs.names = ""
97+
argsDump = vars(guiargs)
98+
99+
needEnemizer = False
100+
falsey = ["none", "default", False, 0]
101+
for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]:
102+
if enemizerOption in argsDump:
103+
if isinstance(argsDump[enemizerOption], dict):
104+
for playerID,playerSetting in argsDump[enemizerOption].items():
105+
if not playerSetting in falsey:
106+
needEnemizer = True
107+
elif not argsDump[enemizerOption] in falsey:
108+
needEnemizer = True
109+
seeds = []
110+
106111
if guiargs.count is not None and guiargs.seed:
107112
seed = guiargs.seed
108113
for _ in range(guiargs.count):

0 commit comments

Comments
 (0)