Merged in DR v1.4.8

This commit is contained in:
codemann8
2025-01-15 22:26:04 -06:00
23 changed files with 158 additions and 103 deletions

View File

@@ -21,11 +21,20 @@ class CustomSettings(object):
self.relative_dir = None
self.world_rep = {}
self.player_range = None
self.player_map = {} # player number to name
def load_yaml(self, file):
self.file_source = load_yaml(file)
head, filename = os.path.split(file)
self.relative_dir = head
if 'version' in self.file_source and self.file_source['version'].startswith('2'):
player_number = 1
for key in self.file_source.keys():
if key in ['meta', 'version']:
continue
else:
self.player_map[player_number] = key
player_number += 1
def determine_seed(self, default_seed):
if 'meta' in self.file_source:
@@ -179,6 +188,7 @@ class CustomSettings(object):
args.restrict_boss_items[p] = get_setting(settings['restrict_boss_items'], args.restrict_boss_items[p])
args.overworld_map[p] = get_setting(settings['overworld_map'], args.overworld_map[p])
args.pseudoboots[p] = get_setting(settings['pseudoboots'], args.pseudoboots[p])
args.mirrorscroll[p] = get_setting(settings['mirrorscroll'], args.mirrorscroll[p])
args.triforce_goal[p] = get_setting(settings['triforce_goal'], args.triforce_goal[p])
args.triforce_pool[p] = get_setting(settings['triforce_pool'], args.triforce_pool[p])
args.triforce_goal_min[p] = get_setting(settings['triforce_goal_min'], args.triforce_goal_min[p])
@@ -189,6 +199,7 @@ class CustomSettings(object):
args.triforce_max_difference[p] = get_setting(settings['triforce_max_difference'], args.triforce_max_difference[p])
args.beemizer[p] = get_setting(settings['beemizer'], args.beemizer[p])
args.aga_randomness[p] = get_setting(settings['aga_randomness'], args.aga_randomness[p])
args.money_balance[p] = get_setting(settings['money_balance'], args.money_balance[p])
# mystery usage
args.usestartinventory[p] = get_setting(settings['usestartinventory'], args.usestartinventory[p])
@@ -219,6 +230,9 @@ class CustomSettings(object):
return self.file_source['placements']
return None
def get_prices(self, player):
return self.get_attribute_by_player_composite('prices', player)
def get_advanced_placements(self):
if 'advanced_placements' in self.file_source:
return self.file_source['advanced_placements']
@@ -284,6 +298,34 @@ class CustomSettings(object):
return self.file_source['enemies']
return None
def get_attribute_by_player_composite(self, attribute, player):
attempt = self.get_attribute_by_player_new(attribute, player)
if attempt is not None:
return attempt
attempt = self.get_attribute_by_player(attribute, player)
return attempt
def get_attribute_by_player(self, attribute, player):
if attribute in self.file_source:
if player in self.file_source[attribute]:
return self.file_source[attribute][player]
return None
def get_attribute_by_player_new(self, attribute, player):
player_id = self.get_player_id(player)
if player_id is not None:
if attribute in self.file_source[player_id]:
return self.file_source[player_id][attribute]
return None
def get_player_id(self, player):
if player in self.file_source:
return player
if player in self.player_map and self.player_map[player] in self.file_source:
return self.player_map[player]
return None
def create_from_world(self, world, settings):
self.player_range = range(1, world.players + 1)
settings_dict, meta_dict = {}, {}
@@ -355,10 +397,12 @@ class CustomSettings(object):
settings_dict[p]['linked_drops'] = world.linked_drops[p]
settings_dict[p]['overworld_map'] = world.overworld_map[p]
settings_dict[p]['pseudoboots'] = world.pseudoboots[p]
settings_dict[p]['mirrorscroll'] = world.mirrorscroll[p]
settings_dict[p]['triforce_goal'] = world.treasure_hunt_count[p]
settings_dict[p]['triforce_pool'] = world.treasure_hunt_total[p]
settings_dict[p]['beemizer'] = world.beemizer[p]
settings_dict[p]['aga_randomness'] = world.aga_randomness[p]
settings_dict[p]['money_balance'] = world.money_balance[p]
if world.precollected_items:
start_inv[p] = []
for item in world.precollected_items:

View File

@@ -57,6 +57,7 @@ SETTINGSTOPROCESS = {
"item": {
"hints": "hints",
"pseudoboots": "pseudoboots",
"mirrorscroll": "mirrorscroll",
'collection_rate': 'collection_rate',
"race": "race",

View File

@@ -1657,9 +1657,9 @@ def init_vanilla_sprites():
create_sprite(0x00b3, EnemySprite.Beamos, 0x00, 0, 0x06, 0x18, 'Mire Spikes')
create_sprite(0x00b3, EnemySprite.FourWayShooter, 0x00, 0, 0x0a, 0x1a, 'Mire Spikes')
create_sprite(0x00b3, EnemySprite.Stalfos, 0x00, 0, 0x07, 0x1c, 'Mire Spikes')
create_sprite(0x00b5, EnemySprite.FirebarCW, 0x00, 0, 0x16, 0x0a, 'TR Dark Ride')
create_sprite(0x00b5, EnemySprite.FirebarCW, 0x00, 0, 0x09, 0x0f, 'TR Dark Ride')
create_sprite(0x00b5, EnemySprite.FirebarCW, 0x00, 0, 0x16, 0x16, 'TR Dark Ride')
create_sprite(0x00b5, EnemySprite.FirebarCW, 0x00, 0, 0x16, 0x0a, 'TR Dark Ride Ledges')
create_sprite(0x00b5, EnemySprite.FirebarCW, 0x00, 0, 0x09, 0x0f, 'TR Dark Ride Ledges')
create_sprite(0x00b5, EnemySprite.FirebarCW, 0x00, 0, 0x16, 0x16, 'TR Dark Ride Ledges')
create_sprite(0x00b6, EnemySprite.Chainchomp, 0x00, 0, 0x06, 0x07, 'TR Chain Chomps Top')
create_sprite(0x00b6, EnemySprite.Chainchomp, 0x00, 0, 0x0a, 0x07, 'TR Chain Chomps Top')
create_sprite(0x00b6, EnemySprite.CrystalSwitch, 0x00, 0, 0x03, 0x04)

View File

@@ -275,7 +275,7 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
rem_entrances.update(lw_entrances)
rem_entrances.update(dw_entrances)
else:
# cross world mandantory
# cross world mandatory
entrance_list = list(entrances)
if avail.swapped:
forbidden = [e for e in Forbidden_Swap_Entrances if e in entrance_list]
@@ -321,16 +321,13 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
avail.decoupled_exits.remove(bomb_shop)
rem_exits.remove(bomb_shop)
def bonk_fairy_exception(x): # (Bonk Fairy not eligible in standard)
return not avail.is_standard() or x != 'Bonk Fairy (Light)'
# old man S&Q cave
if not cross_world and not avail.assumed_loose_caves:
#TODO: Add Swapped ER support for this
# OM Cave entrance in lw/dw if cross_world off
if 'Old Man Cave Exit (West)' in rem_exits:
world_limiter = DW_Entrances if avail.inverted else LW_Entrances
om_cave_options = sorted([x for x in rem_entrances if x in world_limiter and bonk_fairy_exception(x)])
om_cave_options = sorted([x for x in rem_entrances if x in world_limiter and bonk_fairy_exception(avail, x)])
om_cave_choice = random.choice(om_cave_options)
if not avail.coupled:
connect_exit('Old Man Cave Exit (West)', om_cave_choice, avail)
@@ -344,7 +341,7 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
for ext in om_house:
if ext in rem_exits:
world_limiter = DW_Entrances if avail.inverted else LW_Entrances
om_house_options = [x for x in rem_entrances if x in world_limiter and bonk_fairy_exception(x)]
om_house_options = [x for x in rem_entrances if x in world_limiter and bonk_fairy_exception(avail, x)]
om_house_choice = random.choice(om_house_options)
if not avail.coupled:
connect_exit(ext, om_house_choice, avail)
@@ -361,7 +358,7 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
lw_entrances, dw_entrances = [], []
left = sorted(rem_entrances)
for x in left:
if bonk_fairy_exception(x):
if bonk_fairy_exception(avail, x):
lw_entrances.append(x) if x in LW_Entrances else dw_entrances.append(x)
do_same_world_connectors(lw_entrances, dw_entrances, multi_exit_caves, avail)
if avail.world.doorShuffle[avail.player] != 'vanilla':
@@ -371,7 +368,7 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
unused_entrances.update(lw_entrances)
unused_entrances.update(dw_entrances)
else:
entrance_list = sorted([x for x in rem_entrances if bonk_fairy_exception(x)])
entrance_list = sorted([x for x in rem_entrances if bonk_fairy_exception(avail, x)])
do_cross_world_connectors(entrance_list, multi_exit_caves, avail)
unused_entrances.update(entrance_list)
@@ -1527,6 +1524,8 @@ def do_vanilla_connect(pool_def, avail):
avail.entrances.remove(entrance)
avail.exits.remove(target)
def bonk_fairy_exception(avail, x): # (Bonk Fairy not eligible in standard)
return not avail.is_standard() or x != 'Bonk Fairy (Light)'
def do_mandatory_connections(avail, entrances, cave_options, must_exit):
if len(must_exit) == 0:
@@ -1614,7 +1613,8 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
if len(cave) == 2:
entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit]
and e not in invalid_cave_connections[tuple(cave)] and e not in must_exit
and (not avail.swapped or rnd_cave[0] != avail.combine_map[e]))
and (not avail.swapped or rnd_cave[0] != avail.combine_map[e])
and bonk_fairy_exception(avail, e))
entrances.remove(entrance)
connect_two_way(entrance, rnd_cave[0], avail)
if avail.swapped and avail.combine_map[entrance] != rnd_cave[0]:
@@ -1639,7 +1639,7 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
cave_entrances.append(entrance)
else:
entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit] and e not in must_exit
and (not avail.swapped or cave_exit != avail.combine_map[e]))
and (not avail.swapped or cave_exit != avail.combine_map[e]) and bonk_fairy_exception(avail, e))
cave_entrances.append(entrance)
entrances.remove(entrance)
connect_two_way(entrance, cave_exit, avail)
@@ -1670,7 +1670,7 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
continue
else:
entrance = next(e for e in entrances[::-1] if e not in invalid_cave_connections[tuple(cave)]
and (not avail.swapped or cave_exit != avail.combine_map[e]))
and (not avail.swapped or cave_exit != avail.combine_map[e]) and bonk_fairy_exception(avail, e))
invalid_cave_connections[tuple(cave)] = set()
entrances.remove(entrance)
connect_two_way(entrance, cave_exit, avail)

View File

@@ -152,6 +152,7 @@ def roll_settings(weights):
ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle != 'none' else 'off'
ret.pseudoboots = get_choice_bool('pseudoboots')
ret.mirrorscroll = get_choice_bool('mirrorscroll')
ret.shopsanity = get_choice_bool('shopsanity')
keydropshuffle = get_choice_bool('keydropshuffle')
ret.dropshuffle = get_choice('dropshuffle') if 'dropshuffle' in weights else 'none'