Merge branch 'OverworldShuffleDev' into OverworldShuffle
This commit is contained in:
@@ -29,6 +29,7 @@ weights/
|
|||||||
/Players/
|
/Players/
|
||||||
/QUsb2Snes/
|
/QUsb2Snes/
|
||||||
/output/
|
/output/
|
||||||
|
/enemizer/
|
||||||
|
|
||||||
base2current.json
|
base2current.json
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -168,6 +168,7 @@ class World(object):
|
|||||||
set_player_attr('potshuffle', False)
|
set_player_attr('potshuffle', False)
|
||||||
set_player_attr('pot_contents', None)
|
set_player_attr('pot_contents', None)
|
||||||
set_player_attr('pseudoboots', False)
|
set_player_attr('pseudoboots', False)
|
||||||
|
set_player_attr('mirrorscroll', False)
|
||||||
set_player_attr('collection_rate', False)
|
set_player_attr('collection_rate', False)
|
||||||
set_player_attr('colorizepots', True)
|
set_player_attr('colorizepots', True)
|
||||||
set_player_attr('pot_pool', {})
|
set_player_attr('pot_pool', {})
|
||||||
@@ -177,6 +178,7 @@ class World(object):
|
|||||||
set_player_attr('trap_door_mode', 'optional')
|
set_player_attr('trap_door_mode', 'optional')
|
||||||
set_player_attr('key_logic_algorithm', 'partial')
|
set_player_attr('key_logic_algorithm', 'partial')
|
||||||
set_player_attr('aga_randomness', True)
|
set_player_attr('aga_randomness', True)
|
||||||
|
set_player_attr('money_balance', 100)
|
||||||
|
|
||||||
set_player_attr('shopsanity', False)
|
set_player_attr('shopsanity', False)
|
||||||
set_player_attr('mixed_travel', 'prevent')
|
set_player_attr('mixed_travel', 'prevent')
|
||||||
@@ -3059,6 +3061,7 @@ class Spoiler(object):
|
|||||||
'potshuffle': self.world.potshuffle,
|
'potshuffle': self.world.potshuffle,
|
||||||
'shopsanity': self.world.shopsanity,
|
'shopsanity': self.world.shopsanity,
|
||||||
'pseudoboots': self.world.pseudoboots,
|
'pseudoboots': self.world.pseudoboots,
|
||||||
|
'mirrorscroll': self.world.mirrorscroll,
|
||||||
'triforcegoal': self.world.treasure_hunt_count,
|
'triforcegoal': self.world.treasure_hunt_count,
|
||||||
'triforcepool': self.world.treasure_hunt_total,
|
'triforcepool': self.world.treasure_hunt_total,
|
||||||
'race': self.world.settings.world_rep['meta']['race'],
|
'race': self.world.settings.world_rep['meta']['race'],
|
||||||
@@ -3307,6 +3310,7 @@ class Spoiler(object):
|
|||||||
outfile.write('Enemy Logic:'.ljust(line_width) + '%s\n' % self.metadata['any_enemy_logic'][player])
|
outfile.write('Enemy Logic:'.ljust(line_width) + '%s\n' % self.metadata['any_enemy_logic'][player])
|
||||||
outfile.write('\n')
|
outfile.write('\n')
|
||||||
outfile.write('Pseudoboots:'.ljust(line_width) + '%s\n' % yn(self.metadata['pseudoboots'][player]))
|
outfile.write('Pseudoboots:'.ljust(line_width) + '%s\n' % yn(self.metadata['pseudoboots'][player]))
|
||||||
|
outfile.write('Mirror Scroll:'.ljust(line_width) + '%s\n' % yn(self.metadata['mirrorscroll'][player]))
|
||||||
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
|
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
|
||||||
outfile.write('Race:'.ljust(line_width) + '%s\n' % yn(self.world.settings.world_rep['meta']['race']))
|
outfile.write('Race:'.ljust(line_width) + '%s\n' % yn(self.world.settings.world_rep['meta']['race']))
|
||||||
|
|
||||||
@@ -3681,7 +3685,7 @@ overworld_map_mode = {'default': 0, 'compass': 1, 'map': 2}
|
|||||||
trap_door_mode = {'vanilla': 0, 'optional': 1, 'boss': 2, 'oneway': 3}
|
trap_door_mode = {'vanilla': 0, 'optional': 1, 'boss': 2, 'oneway': 3}
|
||||||
key_logic_algo = {'dangerous': 0, 'partial': 1, 'strict': 2}
|
key_logic_algo = {'dangerous': 0, 'partial': 1, 'strict': 2}
|
||||||
|
|
||||||
# byte 15: SSLL ??DD (skullwoods, linked_drops, 2 free bytes, door_type)
|
# byte 15: SSLL M?DD (skullwoods, linked_drops, mirrorscroll, 1 free byte, door_type)
|
||||||
skullwoods_mode = {'original': 0, 'restricted': 1, 'loose': 2, 'followlinked': 3}
|
skullwoods_mode = {'original': 0, 'restricted': 1, 'loose': 2, 'followlinked': 3}
|
||||||
linked_drops_mode = {'unset': 0, 'linked': 1, 'independent': 2}
|
linked_drops_mode = {'unset': 0, 'linked': 1, 'independent': 2}
|
||||||
door_type_mode = {'original': 0, 'big': 1, 'all': 2, 'chaos': 3}
|
door_type_mode = {'original': 0, 'big': 1, 'all': 2, 'chaos': 3}
|
||||||
@@ -3742,7 +3746,7 @@ class Settings(object):
|
|||||||
| trap_door_mode[w.trap_door_mode[p]] << 3 | key_logic_algo[w.key_logic_algorithm[p]]),
|
| trap_door_mode[w.trap_door_mode[p]] << 3 | key_logic_algo[w.key_logic_algorithm[p]]),
|
||||||
|
|
||||||
(skullwoods_mode[w.skullwoods[p]] << 6 | linked_drops_mode[w.linked_drops[p]] << 4
|
(skullwoods_mode[w.skullwoods[p]] << 6 | linked_drops_mode[w.linked_drops[p]] << 4
|
||||||
| door_type_mode[w.door_type_mode[p]]),
|
| (0x8 if w.mirrorscroll[p] else 0) | door_type_mode[w.door_type_mode[p]]),
|
||||||
])
|
])
|
||||||
return base64.b64encode(code, "+-".encode()).decode()
|
return base64.b64encode(code, "+-".encode()).decode()
|
||||||
|
|
||||||
@@ -3835,6 +3839,7 @@ class Settings(object):
|
|||||||
if len(settings) > 15:
|
if len(settings) > 15:
|
||||||
args.skullwoods[p] = r(skullwoods_mode)[(settings[15] & 0xc0) >> 6]
|
args.skullwoods[p] = r(skullwoods_mode)[(settings[15] & 0xc0) >> 6]
|
||||||
args.linked_drops[p] = r(linked_drops_mode)[(settings[15] & 0x30) >> 4]
|
args.linked_drops[p] = r(linked_drops_mode)[(settings[15] & 0x30) >> 4]
|
||||||
|
args.mirrorscroll[p] = True if settings[15] & 0x8 else False
|
||||||
args.door_type_mode[p] = r(door_type_mode)[(settings[15] & 0x3)]
|
args.door_type_mode[p] = r(door_type_mode)[(settings[15] & 0x3)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.5.1.4
|
||||||
|
- Fixed incorrect ganon silvers hint
|
||||||
|
- \~Merged in DR v1.4.8.1~
|
||||||
|
|
||||||
## 0.5.1.3
|
## 0.5.1.3
|
||||||
- Fixed some minor issues with mystery multiworld
|
- Fixed some minor issues with mystery multiworld
|
||||||
- Corrected some generation issues with Nearby dungeon item shuffles
|
- Corrected some generation issues with Nearby dungeon item shuffles
|
||||||
|
|||||||
@@ -139,13 +139,14 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
|
'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
|
||||||
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern',
|
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern',
|
||||||
'skullwoods', 'linked_drops',
|
'skullwoods', 'linked_drops',
|
||||||
'pseudoboots', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
'pseudoboots', 'mirrorscroll', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
||||||
'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', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle',
|
'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle',
|
||||||
'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', 'shuffle_sfxinstruments',
|
'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', 'shuffle_sfxinstruments',
|
||||||
'shuffle_songinstruments', 'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode',
|
'shuffle_songinstruments', 'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode',
|
||||||
'bonk_drops', 'trap_door_mode', 'key_logic_algorithm', 'door_self_loops', 'any_enemy_logic', 'aga_randomness']:
|
'bonk_drops', 'trap_door_mode', 'key_logic_algorithm', 'door_self_loops', 'any_enemy_logic', 'aga_randomness',
|
||||||
|
'money_balance']:
|
||||||
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:
|
||||||
setattr(ret, name, {1: value})
|
setattr(ret, name, {1: value})
|
||||||
@@ -208,6 +209,7 @@ def parse_settings():
|
|||||||
"overworld_map": "default",
|
"overworld_map": "default",
|
||||||
"take_any": "none",
|
"take_any": "none",
|
||||||
"pseudoboots": False,
|
"pseudoboots": False,
|
||||||
|
"mirrorscroll": False,
|
||||||
|
|
||||||
"shuffleenemies": "none",
|
"shuffleenemies": "none",
|
||||||
"shufflebosses": "none",
|
"shufflebosses": "none",
|
||||||
@@ -239,6 +241,7 @@ def parse_settings():
|
|||||||
"mixed_travel": "prevent",
|
"mixed_travel": "prevent",
|
||||||
"standardize_palettes": "standardize",
|
"standardize_palettes": "standardize",
|
||||||
'aga_randomness': True,
|
'aga_randomness': True,
|
||||||
|
'money_balance': 100,
|
||||||
|
|
||||||
"triforce_pool": 0,
|
"triforce_pool": 0,
|
||||||
"triforce_goal": 0,
|
"triforce_goal": 0,
|
||||||
|
|||||||
+4
-2
@@ -3884,8 +3884,10 @@ logical_connections = [
|
|||||||
('TR Crystaroller Chest to Middle Barrier - Blue', 'TR Crystaroller Middle'),
|
('TR Crystaroller Chest to Middle Barrier - Blue', 'TR Crystaroller Middle'),
|
||||||
('TR Crystaroller Middle Ranged Crystal Exit', 'TR Crystaroller Middle'),
|
('TR Crystaroller Middle Ranged Crystal Exit', 'TR Crystaroller Middle'),
|
||||||
('TR Crystaroller Bottom Ranged Crystal Exit', 'TR Crystaroller Bottom'),
|
('TR Crystaroller Bottom Ranged Crystal Exit', 'TR Crystaroller Bottom'),
|
||||||
('TR Dark Ride Path', 'TR Dark Ride Ledges'),
|
('TR Dark Ride Normal Path', 'TR Dark Ride South Platform'),
|
||||||
('TR Dark Ride Ledges Path', 'TR Dark Ride'),
|
('TR Dark Ride Backward Path', 'TR Dark Ride North Platform'),
|
||||||
|
('TR Dark Ride Ledge Path', 'TR Dark Ride Ledges'),
|
||||||
|
('TR Dark Ride Return Path', 'TR Dark Ride South Platform'),
|
||||||
('TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze Interior'),
|
('TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze Interior'),
|
||||||
('TR Crystal Maze Start to Crystal', 'TR Crystal Maze Start - Crystal'),
|
('TR Crystal Maze Start to Crystal', 'TR Crystal Maze Start - Crystal'),
|
||||||
('TR Crystal Maze Start Crystal Exit', 'TR Crystal Maze Start'),
|
('TR Crystal Maze Start Crystal Exit', 'TR Crystal Maze Start'),
|
||||||
|
|||||||
@@ -1061,8 +1061,10 @@ def create_doors(world, player):
|
|||||||
create_door(player, 'TR Crystaroller Down Stairs', Sprl).dir(Dn, 0x04, 0, HTH).ss(A, 0x12, 0x80, True, True).small_key().pos(0),
|
create_door(player, 'TR Crystaroller Down Stairs', Sprl).dir(Dn, 0x04, 0, HTH).ss(A, 0x12, 0x80, True, True).small_key().pos(0),
|
||||||
create_door(player, 'TR Dark Ride Up Stairs', Sprl).dir(Up, 0xb5, 0, HTH).ss(A, 0x1b, 0x6c),
|
create_door(player, 'TR Dark Ride Up Stairs', Sprl).dir(Up, 0xb5, 0, HTH).ss(A, 0x1b, 0x6c),
|
||||||
create_door(player, 'TR Dark Ride SW', Nrml).dir(So, 0xb5, Left, High).trap(0x4).pos(0).portal(Z, 0x22),
|
create_door(player, 'TR Dark Ride SW', Nrml).dir(So, 0xb5, Left, High).trap(0x4).pos(0).portal(Z, 0x22),
|
||||||
create_door(player, 'TR Dark Ride Path', Lgcl),
|
create_door(player, 'TR Dark Ride Normal Path', Lgcl),
|
||||||
create_door(player, 'TR Dark Ride Ledges Path', Lgcl),
|
create_door(player, 'TR Dark Ride Ledge Path', Lgcl),
|
||||||
|
create_door(player, 'TR Dark Ride Backward Path', Lgcl),
|
||||||
|
create_door(player, 'TR Dark Ride Return Path', Lgcl),
|
||||||
create_door(player, 'TR Dash Bridge NW', Nrml).dir(No, 0xc5, Left, High).pos(1),
|
create_door(player, 'TR Dash Bridge NW', Nrml).dir(No, 0xc5, Left, High).pos(1),
|
||||||
create_door(player, 'TR Dash Bridge SW', Nrml).dir(So, 0xc5, Left, High).pos(2).portal(Z, 0x02),
|
create_door(player, 'TR Dash Bridge SW', Nrml).dir(So, 0xc5, Left, High).pos(2).portal(Z, 0x02),
|
||||||
create_door(player, 'TR Dash Bridge WS', Nrml).dir(We, 0xc5, Bot, High).small_key().pos(0),
|
create_door(player, 'TR Dash Bridge WS', Nrml).dir(We, 0xc5, Bot, High).small_key().pos(0),
|
||||||
|
|||||||
+2
-1
@@ -181,7 +181,8 @@ tr_regions = [
|
|||||||
'TR Big View', 'TR Big Chest', 'TR Big Chest Entrance', 'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull',
|
'TR Big View', 'TR Big Chest', 'TR Big Chest Entrance', 'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull',
|
||||||
'TR Rupees', 'TR Crystaroller Bottom', 'TR Crystaroller Middle', 'TR Crystaroller Top',
|
'TR Rupees', 'TR Crystaroller Bottom', 'TR Crystaroller Middle', 'TR Crystaroller Top',
|
||||||
'TR Crystaroller Top - Crystal', 'TR Crystaroller Chest', 'TR Crystaroller Middle - Ranged Crystal',
|
'TR Crystaroller Top - Crystal', 'TR Crystaroller Chest', 'TR Crystaroller Middle - Ranged Crystal',
|
||||||
'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride', 'TR Dark Ride Ledges', 'TR Dash Bridge', 'TR Eye Bridge',
|
'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride North Platform', 'TR Dark Ride South Platform',
|
||||||
|
'TR Dark Ride Ledges', 'TR Dash Bridge', 'TR Eye Bridge',
|
||||||
'TR Crystal Maze Start', 'TR Crystal Maze Start - Crystal', 'TR Crystal Maze Interior', 'TR Crystal Maze End',
|
'TR Crystal Maze Start', 'TR Crystal Maze Start - Crystal', 'TR Crystal Maze Interior', 'TR Crystal Maze End',
|
||||||
'TR Crystal Maze End - Ranged Crystal', 'TR Final Abyss Balcony', 'TR Final Abyss Ledge', 'TR Boss', 'TR Boss Spoils',
|
'TR Crystal Maze End - Ranged Crystal', 'TR Final Abyss Balcony', 'TR Final Abyss Ledge', 'TR Boss', 'TR Boss Spoils',
|
||||||
'Turtle Rock Main Portal', 'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal',
|
'Turtle Rock Main Portal', 'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal',
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ def fill_dungeons_restrictive(world, shuffled_locations):
|
|||||||
break
|
break
|
||||||
for wix in reversed(to_remove):
|
for wix in reversed(to_remove):
|
||||||
del smalls[wix]
|
del smalls[wix]
|
||||||
|
|
||||||
# remove 2 swamp locations from pool
|
# remove 2 swamp locations from pool
|
||||||
hybrid_locations = []
|
hybrid_locations = []
|
||||||
to_remove = []
|
to_remove = []
|
||||||
@@ -91,7 +90,6 @@ def fill_dungeons_restrictive(world, shuffled_locations):
|
|||||||
break
|
break
|
||||||
for i in reversed(to_remove):
|
for i in reversed(to_remove):
|
||||||
shuffled_locations.pop(i)
|
shuffled_locations.pop(i)
|
||||||
|
|
||||||
# place 2 HMG keys
|
# place 2 HMG keys
|
||||||
hybrid_state_base = all_state_base.copy()
|
hybrid_state_base = all_state_base.copy()
|
||||||
for x in bigs + smalls + prizes + others:
|
for x in bigs + smalls + prizes + others:
|
||||||
@@ -1122,14 +1120,16 @@ def balance_money_progression(world):
|
|||||||
solvent = set()
|
solvent = set()
|
||||||
insolvent = set()
|
insolvent = set()
|
||||||
for player in range(1, world.players+1):
|
for player in range(1, world.players+1):
|
||||||
if wallet[player] >= sphere_costs[player] >= 0:
|
modifier = world.money_balance[player]/100
|
||||||
|
if wallet[player] >= sphere_costs[player] * modifier >= 0:
|
||||||
solvent.add(player)
|
solvent.add(player)
|
||||||
if sphere_costs[player] > 0 and sphere_costs[player] > wallet[player]:
|
if sphere_costs[player] > 0 and sphere_costs[player] * modifier > wallet[player]:
|
||||||
insolvent.add(player)
|
insolvent.add(player)
|
||||||
if len([p for p in solvent if len(locked_by_money[p]) > 0]) == 0:
|
if len([p for p in solvent if len(locked_by_money[p]) > 0]) == 0:
|
||||||
if len(insolvent) > 0:
|
if len(insolvent) > 0:
|
||||||
target_player = min(insolvent, key=lambda p: sphere_costs[p]-wallet[p])
|
target_player = min(insolvent, key=lambda p: sphere_costs[p]-wallet[p])
|
||||||
difference = sphere_costs[target_player]-wallet[target_player]
|
target_modifier = world.money_balance[target_player]/100
|
||||||
|
difference = sphere_costs[target_player] * target_modifier - wallet[target_player]
|
||||||
logger.debug(f'Money balancing needed: Player {target_player} short {difference}')
|
logger.debug(f'Money balancing needed: Player {target_player} short {difference}')
|
||||||
else:
|
else:
|
||||||
difference = 0
|
difference = 0
|
||||||
@@ -1169,7 +1169,8 @@ def balance_money_progression(world):
|
|||||||
solvent.add(target_player)
|
solvent.add(target_player)
|
||||||
# apply solvency
|
# apply solvency
|
||||||
for player in solvent:
|
for player in solvent:
|
||||||
wallet[player] -= sphere_costs[player]
|
modifier = world.money_balance[player]/100
|
||||||
|
wallet[player] -= sphere_costs[player] * modifier
|
||||||
for location in locked_by_money[player]:
|
for location in locked_by_money[player]:
|
||||||
if isinstance(location, str) and location == 'Kiki':
|
if isinstance(location, str) and location == 'Kiki':
|
||||||
kiki_paid[player] = True
|
kiki_paid[player] = True
|
||||||
|
|||||||
+1
-1
@@ -124,7 +124,7 @@ class InitialSram:
|
|||||||
if startingstate.has('Beat Agahnim 1', player):
|
if startingstate.has('Beat Agahnim 1', player):
|
||||||
self.pre_open_lumberjack()
|
self.pre_open_lumberjack()
|
||||||
if world.mode[player] == 'standard':
|
if world.mode[player] == 'standard':
|
||||||
self.set_progress_indicator(0x80)
|
self.set_progress_indicator(0x80) # todo: probably missing some code rom side for this
|
||||||
else:
|
else:
|
||||||
self.set_progress_indicator(0x03)
|
self.set_progress_indicator(0x03)
|
||||||
|
|
||||||
|
|||||||
+24
-36
@@ -837,7 +837,8 @@ def customize_shops(world, player):
|
|||||||
if retro_bow and item.name == 'Single Arrow':
|
if retro_bow and item.name == 'Single Arrow':
|
||||||
price = 80
|
price = 80
|
||||||
# randomize price
|
# randomize price
|
||||||
shop.add_inventory(idx, item.name, randomize_price(price), max_repeat, player=item.player)
|
price = final_price(loc, price, world, player)
|
||||||
|
shop.add_inventory(idx, item.name, price, max_repeat, player=item.player)
|
||||||
if item.name in cap_replacements and shop_name not in retro_shops and item.player == player:
|
if item.name in cap_replacements and shop_name not in retro_shops and item.player == player:
|
||||||
possible_replacements.append((shop, idx, location, item))
|
possible_replacements.append((shop, idx, location, item))
|
||||||
# randomize shopkeeper
|
# randomize shopkeeper
|
||||||
@@ -854,8 +855,10 @@ def customize_shops(world, player):
|
|||||||
if len(choices) > 0:
|
if len(choices) > 0:
|
||||||
shop, idx, loc, item = random.choice(choices)
|
shop, idx, loc, item = random.choice(choices)
|
||||||
upgrade = ItemFactory('Bomb Upgrade (+5)', player)
|
upgrade = ItemFactory('Bomb Upgrade (+5)', player)
|
||||||
shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6,
|
up_price = final_price(loc.name, upgrade.price, world, player)
|
||||||
item.name, randomize_price(item.price), player=item.player)
|
rep_price = final_price(loc.name, item.price, world, player)
|
||||||
|
shop.add_inventory(idx, upgrade.name, up_price, 6,
|
||||||
|
item.name, rep_price, player=item.player)
|
||||||
loc.item = upgrade
|
loc.item = upgrade
|
||||||
upgrade.location = loc
|
upgrade.location = loc
|
||||||
if not found_arrow_upgrade and len(possible_replacements) > 0:
|
if not found_arrow_upgrade and len(possible_replacements) > 0:
|
||||||
@@ -866,8 +869,10 @@ def customize_shops(world, player):
|
|||||||
if len(choices) > 0:
|
if len(choices) > 0:
|
||||||
shop, idx, loc, item = random.choice(choices)
|
shop, idx, loc, item = random.choice(choices)
|
||||||
upgrade = ItemFactory('Arrow Upgrade (+5)', player)
|
upgrade = ItemFactory('Arrow Upgrade (+5)', player)
|
||||||
shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6,
|
up_price = final_price(loc.name, upgrade.price, world, player)
|
||||||
item.name, randomize_price(item.price), player=item.player)
|
rep_price = final_price(loc.name, item.price, world, player)
|
||||||
|
shop.add_inventory(idx, upgrade.name, up_price, 6,
|
||||||
|
item.name, rep_price, player=item.player)
|
||||||
loc.item = upgrade
|
loc.item = upgrade
|
||||||
upgrade.location = loc
|
upgrade.location = loc
|
||||||
change_shop_items_to_rupees(world, player, shops_to_customize)
|
change_shop_items_to_rupees(world, player, shops_to_customize)
|
||||||
@@ -875,6 +880,15 @@ def customize_shops(world, player):
|
|||||||
check_hints(world, player)
|
check_hints(world, player)
|
||||||
|
|
||||||
|
|
||||||
|
def final_price(location, price, world, player):
|
||||||
|
if world.customizer and world.customizer.get_prices(player):
|
||||||
|
custom_prices = world.customizer.get_prices(player)
|
||||||
|
if location in custom_prices:
|
||||||
|
# todo: validate valid price
|
||||||
|
return custom_prices[location]
|
||||||
|
return randomize_price(price)
|
||||||
|
|
||||||
|
|
||||||
def randomize_price(price):
|
def randomize_price(price):
|
||||||
half_price = price // 2
|
half_price = price // 2
|
||||||
max_price = price - half_price
|
max_price = price - half_price
|
||||||
@@ -914,12 +928,16 @@ def balance_prices(world, player):
|
|||||||
shop_locations = []
|
shop_locations = []
|
||||||
for shop, loc_list in shop_to_location_table.items():
|
for shop, loc_list in shop_to_location_table.items():
|
||||||
for loc in loc_list:
|
for loc in loc_list:
|
||||||
|
if world.customizer and world.customizer.get_prices(player) and loc in world.customizer.get_prices(player):
|
||||||
|
needed_money += world.customizer.get_prices(player)[loc]
|
||||||
|
continue # considered a fixed price and shouldn't be altered
|
||||||
loc = world.get_location(loc, player)
|
loc = world.get_location(loc, player)
|
||||||
shop_locations.append(loc)
|
shop_locations.append(loc)
|
||||||
slot = shop_to_location_table[loc.parent_region.name].index(loc.name)
|
slot = shop_to_location_table[loc.parent_region.name].index(loc.name)
|
||||||
needed_money += loc.parent_region.shop.inventory[slot]['price']
|
needed_money += loc.parent_region.shop.inventory[slot]['price']
|
||||||
|
|
||||||
target = available_money - needed_money
|
modifier = world.money_balance[player]/100
|
||||||
|
target = available_money - needed_money * modifier
|
||||||
# remove the first set of shops from consideration (or used them for discounting)
|
# remove the first set of shops from consideration (or used them for discounting)
|
||||||
state, done = CollectionState(world), False
|
state, done = CollectionState(world), False
|
||||||
unchecked_locations = world.get_locations().copy()
|
unchecked_locations = world.get_locations().copy()
|
||||||
@@ -1255,32 +1273,11 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer
|
|||||||
assert loc not in placed_items
|
assert loc not in placed_items
|
||||||
placed_items[loc] = item
|
placed_items[loc] = item
|
||||||
|
|
||||||
# Correct for insanely oversized item counts and take initial steps to handle undersized pools.
|
|
||||||
# Bow to Silver Arrows Upgrade, including Generic Keys & Rupoors
|
|
||||||
for x in [*range(0, 69)]:
|
|
||||||
key = CONST.CUSTOMITEMS[x]
|
|
||||||
if customitemarray[key] > total_items_to_place:
|
|
||||||
customitemarray[key] = total_items_to_place
|
|
||||||
|
|
||||||
# Triforce
|
|
||||||
if customitemarray["triforce"] > total_items_to_place:
|
|
||||||
customitemarray["triforce"] = total_items_to_place
|
|
||||||
|
|
||||||
# Triforce Pieces
|
# Triforce Pieces
|
||||||
if goal in ['triforcehunt', 'trinity', 'ganonhunt']:
|
if goal in ['triforcehunt', 'trinity', 'ganonhunt']:
|
||||||
g, t = set_default_triforce(goal, customitemarray["triforcepiecesgoal"], customitemarray["triforcepieces"])
|
g, t = set_default_triforce(goal, customitemarray["triforcepiecesgoal"], customitemarray["triforcepieces"])
|
||||||
customitemarray["triforcepiecesgoal"], customitemarray["triforcepieces"] = g, t
|
customitemarray["triforcepiecesgoal"], customitemarray["triforcepieces"] = g, t
|
||||||
|
|
||||||
itemtotal = 0
|
|
||||||
# Bow to Silver Arrows Upgrade, including Generic Keys & Rupoors
|
|
||||||
for x in [*range(0, 66 + 1), 68, 69]:
|
|
||||||
key = CONST.CUSTOMITEMS[x]
|
|
||||||
itemtotal = itemtotal + customitemarray[key]
|
|
||||||
# Triforce
|
|
||||||
itemtotal = itemtotal + customitemarray["triforce"]
|
|
||||||
# Generic Keys
|
|
||||||
itemtotal = itemtotal + customitemarray["generickeys"]
|
|
||||||
|
|
||||||
customitems = [
|
customitems = [
|
||||||
"Bow", "Silver Arrows", "Blue Boomerang", "Red Boomerang", "Hookshot", "Mushroom", "Magic Powder",
|
"Bow", "Silver Arrows", "Blue Boomerang", "Red Boomerang", "Hookshot", "Mushroom", "Magic Powder",
|
||||||
"Fire Rod", "Ice Rod", "Bombos", "Ether", "Quake",
|
"Fire Rod", "Ice Rod", "Bombos", "Ether", "Quake",
|
||||||
@@ -1322,7 +1319,6 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer
|
|||||||
and (goal in ['triforcehunt', 'trinity', 'ganonhunt']) and (customitemarray["triforce"] == 0)):
|
and (goal in ['triforcehunt', 'trinity', 'ganonhunt']) and (customitemarray["triforce"] == 0)):
|
||||||
extrapieces = treasure_hunt_count - customitemarray["triforcepieces"]
|
extrapieces = treasure_hunt_count - customitemarray["triforcepieces"]
|
||||||
pool.extend(['Triforce Piece'] * extrapieces)
|
pool.extend(['Triforce Piece'] * extrapieces)
|
||||||
itemtotal = itemtotal + extrapieces
|
|
||||||
|
|
||||||
if timer in ['display', 'timed', 'timed-countdown']:
|
if timer in ['display', 'timed', 'timed-countdown']:
|
||||||
clock_mode = 'countdown' if timer == 'timed-countdown' else 'stopwatch'
|
clock_mode = 'countdown' if timer == 'timed-countdown' else 'stopwatch'
|
||||||
@@ -1333,7 +1329,6 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer
|
|||||||
|
|
||||||
if goal in ['pedestal', 'trinity']:
|
if goal in ['pedestal', 'trinity']:
|
||||||
place_item('Master Sword Pedestal', 'Triforce')
|
place_item('Master Sword Pedestal', 'Triforce')
|
||||||
itemtotal = itemtotal + 1
|
|
||||||
|
|
||||||
if mode == 'standard':
|
if mode == 'standard':
|
||||||
if world.keyshuffle[player] == 'universal':
|
if world.keyshuffle[player] == 'universal':
|
||||||
@@ -1350,13 +1345,6 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer
|
|||||||
pool.extend(['Magic Mirror'] * customitemarray["mirror"])
|
pool.extend(['Magic Mirror'] * customitemarray["mirror"])
|
||||||
pool.extend(['Moon Pearl'] * customitemarray["pearl"])
|
pool.extend(['Moon Pearl'] * customitemarray["pearl"])
|
||||||
|
|
||||||
if world.keyshuffle[player] == 'universal':
|
|
||||||
itemtotal = itemtotal - 28 # Corrects for small keys not being in item pool in Retro Mode
|
|
||||||
if itemtotal < total_items_to_place:
|
|
||||||
nothings = total_items_to_place - itemtotal
|
|
||||||
# print("Placing " + str(nothings) + " Nothings")
|
|
||||||
pool.extend(['Nothing'] * nothings)
|
|
||||||
|
|
||||||
start_inventory = [x for x in world.precollected_items if x.player == player]
|
start_inventory = [x for x in world.precollected_items if x.player == player]
|
||||||
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic'] and all(x.name != 'Pegasus Boots' for x in start_inventory):
|
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic'] and all(x.name != 'Pegasus Boots' for x in start_inventory):
|
||||||
precollected_items.append('Pegasus Boots')
|
precollected_items.append('Pegasus Boots')
|
||||||
|
|||||||
+7
-1
@@ -814,7 +814,13 @@ def key_wasted(new_door, old_door, old_counter, new_counter, key_layout, world,
|
|||||||
|
|
||||||
|
|
||||||
def find_next_counter(new_door, old_counter, key_layout, prize_flag=None):
|
def find_next_counter(new_door, old_counter, key_layout, prize_flag=None):
|
||||||
proposed_doors = {**old_counter.open_doors, **dict.fromkeys([new_door, new_door.dest])}
|
prop_doors = next((item_or_tuple for item_or_tuple in key_layout.proposal
|
||||||
|
if new_door == item_or_tuple or (isinstance(item_or_tuple, tuple) and new_door in item_or_tuple)), None)
|
||||||
|
if prop_doors:
|
||||||
|
prop_doors = list(prop_doors) if isinstance(prop_doors, tuple) else [prop_doors]
|
||||||
|
proposed_doors = {**old_counter.open_doors, **dict.fromkeys(prop_doors)}
|
||||||
|
else:
|
||||||
|
proposed_doors = {**old_counter.open_doors}
|
||||||
bk_open = old_counter.big_key_opened or new_door.bigKey
|
bk_open = old_counter.big_key_opened or new_door.bigKey
|
||||||
prize_flag = prize_flag if prize_flag else old_counter.prize_doors_opened
|
prize_flag = prize_flag if prize_flag else old_counter.prize_doors_opened
|
||||||
return find_counter(proposed_doors, bk_open, key_layout, prize_flag)
|
return find_counter(proposed_doors, bk_open, key_layout, prize_flag)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ from source.enemizer.DamageTables import DamageTable
|
|||||||
from source.enemizer.Enemizer import randomize_enemies
|
from source.enemizer.Enemizer import randomize_enemies
|
||||||
from source.rom.DataTables import init_data_tables
|
from source.rom.DataTables import init_data_tables
|
||||||
|
|
||||||
version_number = '1.4.7.2'
|
version_number = '1.4.8.1'
|
||||||
version_branch = '-u'
|
version_branch = '-u'
|
||||||
__version__ = f'{version_number}{version_branch}'
|
__version__ = f'{version_number}{version_branch}'
|
||||||
|
|
||||||
@@ -501,12 +501,14 @@ def init_world(args, fish):
|
|||||||
world.skullwoods = args.skullwoods.copy()
|
world.skullwoods = args.skullwoods.copy()
|
||||||
world.linked_drops = args.linked_drops.copy()
|
world.linked_drops = args.linked_drops.copy()
|
||||||
world.pseudoboots = args.pseudoboots.copy()
|
world.pseudoboots = args.pseudoboots.copy()
|
||||||
|
world.mirrorscroll = args.mirrorscroll.copy()
|
||||||
world.overworld_map = args.overworld_map.copy()
|
world.overworld_map = args.overworld_map.copy()
|
||||||
world.take_any = args.take_any.copy()
|
world.take_any = args.take_any.copy()
|
||||||
world.restrict_boss_items = args.restrict_boss_items.copy()
|
world.restrict_boss_items = args.restrict_boss_items.copy()
|
||||||
world.collection_rate = args.collection_rate.copy()
|
world.collection_rate = args.collection_rate.copy()
|
||||||
world.colorizepots = args.colorizepots.copy()
|
world.colorizepots = args.colorizepots.copy()
|
||||||
world.aga_randomness = args.aga_randomness.copy()
|
world.aga_randomness = args.aga_randomness.copy()
|
||||||
|
world.money_balance = args.money_balance.copy()
|
||||||
|
|
||||||
|
|
||||||
return world
|
return world
|
||||||
@@ -589,7 +591,13 @@ def copy_world(world):
|
|||||||
ret.shuffle_bonk_drops = world.shuffle_bonk_drops.copy()
|
ret.shuffle_bonk_drops = world.shuffle_bonk_drops.copy()
|
||||||
ret.open_pyramid = world.open_pyramid.copy()
|
ret.open_pyramid = world.open_pyramid.copy()
|
||||||
ret.shufflelinks = world.shufflelinks.copy()
|
ret.shufflelinks = world.shufflelinks.copy()
|
||||||
|
ret.shuffletavern = world.shuffletavern.copy()
|
||||||
ret.shuffle_ganon = world.shuffle_ganon.copy()
|
ret.shuffle_ganon = world.shuffle_ganon.copy()
|
||||||
|
ret.skullwoods = world.skullwoods.copy()
|
||||||
|
ret.linked_drops = world.linked_drops.copy()
|
||||||
|
ret.pseudoboots = world.pseudoboots.copy()
|
||||||
|
ret.mirrorscroll = world.mirrorscroll.copy()
|
||||||
|
ret.overworld_map = world.overworld_map.copy()
|
||||||
ret.take_any = world.take_any.copy()
|
ret.take_any = world.take_any.copy()
|
||||||
ret.boss_shuffle = world.boss_shuffle.copy()
|
ret.boss_shuffle = world.boss_shuffle.copy()
|
||||||
ret.enemy_shuffle = world.enemy_shuffle.copy()
|
ret.enemy_shuffle = world.enemy_shuffle.copy()
|
||||||
@@ -604,6 +612,7 @@ def copy_world(world):
|
|||||||
ret.trap_door_mode = world.trap_door_mode.copy()
|
ret.trap_door_mode = world.trap_door_mode.copy()
|
||||||
ret.key_logic_algorithm = world.key_logic_algorithm.copy()
|
ret.key_logic_algorithm = world.key_logic_algorithm.copy()
|
||||||
ret.aga_randomness = world.aga_randomness.copy()
|
ret.aga_randomness = world.aga_randomness.copy()
|
||||||
|
ret.money_balance = world.money_balance.copy()
|
||||||
ret.experimental = world.experimental.copy()
|
ret.experimental = world.experimental.copy()
|
||||||
ret.shopsanity = world.shopsanity.copy()
|
ret.shopsanity = world.shopsanity.copy()
|
||||||
ret.dropshuffle = world.dropshuffle.copy()
|
ret.dropshuffle = world.dropshuffle.copy()
|
||||||
@@ -802,7 +811,13 @@ def copy_world_premature(world, player):
|
|||||||
ret.shuffle_bonk_drops = world.shuffle_bonk_drops.copy()
|
ret.shuffle_bonk_drops = world.shuffle_bonk_drops.copy()
|
||||||
ret.open_pyramid = world.open_pyramid.copy()
|
ret.open_pyramid = world.open_pyramid.copy()
|
||||||
ret.shufflelinks = world.shufflelinks.copy()
|
ret.shufflelinks = world.shufflelinks.copy()
|
||||||
|
ret.shuffletavern = world.shuffletavern.copy()
|
||||||
ret.shuffle_ganon = world.shuffle_ganon.copy()
|
ret.shuffle_ganon = world.shuffle_ganon.copy()
|
||||||
|
ret.skullwoods = world.skullwoods.copy()
|
||||||
|
ret.linked_drops = world.linked_drops.copy()
|
||||||
|
ret.pseudoboots = world.pseudoboots.copy()
|
||||||
|
ret.mirrorscroll = world.mirrorscroll.copy()
|
||||||
|
ret.overworld_map = world.overworld_map.copy()
|
||||||
ret.take_any = world.take_any.copy()
|
ret.take_any = world.take_any.copy()
|
||||||
ret.boss_shuffle = world.boss_shuffle.copy()
|
ret.boss_shuffle = world.boss_shuffle.copy()
|
||||||
ret.enemy_shuffle = world.enemy_shuffle.copy()
|
ret.enemy_shuffle = world.enemy_shuffle.copy()
|
||||||
@@ -817,6 +832,7 @@ def copy_world_premature(world, player):
|
|||||||
ret.trap_door_mode = world.trap_door_mode.copy()
|
ret.trap_door_mode = world.trap_door_mode.copy()
|
||||||
ret.key_logic_algorithm = world.key_logic_algorithm.copy()
|
ret.key_logic_algorithm = world.key_logic_algorithm.copy()
|
||||||
ret.aga_randomness = world.aga_randomness.copy()
|
ret.aga_randomness = world.aga_randomness.copy()
|
||||||
|
ret.money_balance = world.money_balance.copy()
|
||||||
ret.experimental = world.experimental.copy()
|
ret.experimental = world.experimental.copy()
|
||||||
ret.shopsanity = world.shopsanity.copy()
|
ret.shopsanity = world.shopsanity.copy()
|
||||||
ret.dropshuffle = world.dropshuffle.copy()
|
ret.dropshuffle = world.dropshuffle.copy()
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType
|
|||||||
from OverworldGlitchRules import create_owg_connections
|
from OverworldGlitchRules import create_owg_connections
|
||||||
from Utils import bidict
|
from Utils import bidict
|
||||||
|
|
||||||
version_number = '0.5.1.3'
|
version_number = '0.5.1.4'
|
||||||
# branch indicator is intentionally different across branches
|
# branch indicator is intentionally different across branches
|
||||||
version_branch = ''
|
version_branch = ''
|
||||||
|
|
||||||
|
|||||||
+14
-16
@@ -141,20 +141,18 @@ These are now independent of retro mode and have three options: None, Random, an
|
|||||||
|
|
||||||
# Patch Notes
|
# Patch Notes
|
||||||
|
|
||||||
* 1.4.7.2
|
* 1.4.8.1
|
||||||
- Fixed an issue with shuffle_ganon/fix_gtower_exit causing a generation failure
|
- Fixed broken doors generation
|
||||||
|
- Fixed bomb/arrow upgrade ignoring custom pricing
|
||||||
|
- Extended `money_balance` to apply to price balancing for non-custom shops.
|
||||||
|
* 1.4.8
|
||||||
|
- New option: Mirror Scroll - to add the item to the starting inventory in non-doors modes (Thanks Telethar!)
|
||||||
|
- Customizer: Ability to customize shop prices and control money balancing. `money_balance` is a percentage betwen 0 and 100 that attempts to ensure you have that much percentage of money available for purchases. (100 is default, 0 essentially ignores money considerations)
|
||||||
|
- Fixed a key logic bug with decoupled doors when a big key door leads to a small key door (the small key door was missing appropriate logic)
|
||||||
|
- Fixed an ER bug where Bonk Fairy could be used for a mandatory connector in standard mode (boots could allow escape to be skipped)
|
||||||
|
- Fixed an issue with flute activation in rain mode. (thanks Codemann!)
|
||||||
|
- Fixed an issue with enemies in TR Dark Ride room not requiring Somaria. (Refactored the room for decoupled logic better)
|
||||||
- More HMG fixes by Muffins
|
- More HMG fixes by Muffins
|
||||||
* 1.4.7.1
|
- Fixed an issue with multi-player HMG
|
||||||
- Fixed an issue with the repaired "beemizer" setting not being backwards compatible
|
- Fixed an issue limiting number of items specified in the item pool on the GUI
|
||||||
* 1.4.7
|
- Minor documentation fixes (thanks Codemann!)
|
||||||
- Fixed generation error with Big Key in starting inventory (thanks Cody!)
|
|
||||||
- HMG/NL logic fixes by Muffins
|
|
||||||
- Enemizer: Disabled Walking Zora in the UW due to crash with Swamola (they ignore a lot of collison anyway)
|
|
||||||
- Enemizer: Fixed an issue with enemizer bush sprites
|
|
||||||
- Enemizer: Banned new Mimics from being the randomized bush sprite due to crash
|
|
||||||
- "Beatable" or "accessibility: none" can now use randomized trap doors to seal off entire parts of dungeons (was intended, bug prevented the logic skip)
|
|
||||||
- Logic error with enemizer and standard should use new enemy logic rules
|
|
||||||
- Fixed a bug with the inconsistent treatment of the beemizer setting
|
|
||||||
- Fixed an issue with returning Blacksmith in Simple shuffle (when blacksmith is at Link's House)
|
|
||||||
- Fixed an issue with dark sanctuary spawn at tavern north door (thanks Codemann!)
|
|
||||||
- Various enemy bans for the last few months
|
|
||||||
|
|||||||
+3
-2
@@ -907,8 +907,9 @@ def create_dungeon_regions(world, player):
|
|||||||
create_dungeon_region(player, 'TR Crystaroller Chest', 'Turtle Rock', ['Turtle Rock - Crystaroller Room'], ['TR Crystaroller Chest to Middle Barrier - Blue']),
|
create_dungeon_region(player, 'TR Crystaroller Chest', 'Turtle Rock', ['Turtle Rock - Crystaroller Room'], ['TR Crystaroller Chest to Middle Barrier - Blue']),
|
||||||
create_dungeon_region(player, 'TR Crystaroller Middle - Ranged Crystal', 'Turtle Rock', None, ['TR Crystaroller Middle Ranged Crystal Exit']),
|
create_dungeon_region(player, 'TR Crystaroller Middle - Ranged Crystal', 'Turtle Rock', None, ['TR Crystaroller Middle Ranged Crystal Exit']),
|
||||||
create_dungeon_region(player, 'TR Crystaroller Bottom - Ranged Crystal', 'Turtle Rock', None, ['TR Crystaroller Bottom Ranged Crystal Exit']),
|
create_dungeon_region(player, 'TR Crystaroller Bottom - Ranged Crystal', 'Turtle Rock', None, ['TR Crystaroller Bottom Ranged Crystal Exit']),
|
||||||
create_dungeon_region(player, 'TR Dark Ride', 'Turtle Rock', None, ['TR Dark Ride Up Stairs', 'TR Dark Ride SW', 'TR Dark Ride Path']),
|
create_dungeon_region(player, 'TR Dark Ride North Platform', 'Turtle Rock', None, ['TR Dark Ride Up Stairs', 'TR Dark Ride Normal Path', 'TR Dark Ride Ledge Path']),
|
||||||
create_dungeon_region(player, 'TR Dark Ride Ledges', 'Turtle Rock', None, ['TR Dark Ride Ledges Path']),
|
create_dungeon_region(player, 'TR Dark Ride South Platform', 'Turtle Rock', None, ['TR Dark Ride SW', 'TR Dark Ride Backward Path']),
|
||||||
|
create_dungeon_region(player, 'TR Dark Ride Ledges', 'Turtle Rock', None, ['TR Dark Ride Return Path']),
|
||||||
create_dungeon_region(player, 'TR Dash Bridge', 'Turtle Rock', None, ['TR Dash Bridge NW', 'TR Dash Bridge SW', 'TR Dash Bridge WS']),
|
create_dungeon_region(player, 'TR Dash Bridge', 'Turtle Rock', None, ['TR Dash Bridge NW', 'TR Dash Bridge SW', 'TR Dash Bridge WS']),
|
||||||
create_dungeon_region(player, 'TR Eye Bridge', 'Turtle Rock', ['Turtle Rock - Eye Bridge - Bottom Left', 'Turtle Rock - Eye Bridge - Bottom Right',
|
create_dungeon_region(player, 'TR Eye Bridge', 'Turtle Rock', ['Turtle Rock - Eye Bridge - Bottom Left', 'Turtle Rock - Eye Bridge - Bottom Right',
|
||||||
'Turtle Rock - Eye Bridge - Top Left', 'Turtle Rock - Eye Bridge - Top Right'],
|
'Turtle Rock - Eye Bridge - Top Left', 'Turtle Rock - Eye Bridge - Top Right'],
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = 'a84f59e5e76492f6a5693835823e6292'
|
RANDOMIZERBASEHASH = 'b439d99c7f41914eedb9f4097ecc8cc7'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -690,7 +690,11 @@ def patch_rom(world, rom, player, team, is_mystery=False):
|
|||||||
rom.write_byte(0x157D0, exit.target)
|
rom.write_byte(0x157D0, exit.target)
|
||||||
|
|
||||||
# setup dr option flags based on experimental, etc.
|
# setup dr option flags based on experimental, etc.
|
||||||
dr_flags = DROptions.Eternal_Mini_Bosses if world.doorShuffle[player] == 'vanilla' else DROptions.Town_Portal
|
dr_flags = DROptions.NoOptions
|
||||||
|
if world.mirrorscroll[player] or world.doorShuffle[player] != 'vanilla':
|
||||||
|
dr_flags |= DROptions.Town_Portal
|
||||||
|
if world.doorShuffle[player] == 'vanilla':
|
||||||
|
dr_flags |= DROptions.Eternal_Mini_Bosses
|
||||||
if world.doorShuffle[player] not in ['vanilla', 'basic']:
|
if world.doorShuffle[player] not in ['vanilla', 'basic']:
|
||||||
dr_flags |= DROptions.Map_Info
|
dr_flags |= DROptions.Map_Info
|
||||||
if ((world.collection_rate[player] or world.goal[player] == 'completionist')
|
if ((world.collection_rate[player] or world.goal[player] == 'completionist')
|
||||||
|
|||||||
@@ -601,10 +601,11 @@ def global_rules(world, player):
|
|||||||
lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player))
|
lambda state: state.has('Cane of Somaria', player) and state.has('Fire Rod', player))
|
||||||
set_rule(world.get_entrance('TR Big Chest Entrance Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has('Hookshot', player))
|
set_rule(world.get_entrance('TR Big Chest Entrance Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has('Hookshot', player))
|
||||||
set_rule(world.get_entrance('TR Big Chest Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has_Boots(player))
|
set_rule(world.get_entrance('TR Big Chest Gap', player), lambda state: state.has('Cane of Somaria', player) or state.has_Boots(player))
|
||||||
set_rule(world.get_entrance('TR Dark Ride Up Stairs', player), lambda state: state.has('Cane of Somaria', player))
|
set_rule(world.get_entrance('TR Dark Ride SW', player), lambda state: state.has('Cane of Somaria', player)) # due to needing the switch
|
||||||
set_rule(world.get_entrance('TR Dark Ride SW', player), lambda state: state.has('Cane of Somaria', player))
|
set_rule(world.get_entrance('TR Dark Ride Normal Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
set_rule(world.get_entrance('TR Dark Ride Path', player), lambda state: state.has('Cane of Somaria', player))
|
set_rule(world.get_entrance('TR Dark Ride Backward Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
set_rule(world.get_entrance('TR Dark Ride Ledges Path', player), lambda state: state.has('Cane of Somaria', player))
|
set_rule(world.get_entrance('TR Dark Ride Return Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
|
set_rule(world.get_entrance('TR Dark Ride Ledge Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
for location in world.get_region('TR Dark Ride Ledges', player).locations:
|
for location in world.get_region('TR Dark Ride Ledges', player).locations:
|
||||||
set_rule(location, lambda state: state.has('Cane of Somaria', player))
|
set_rule(location, lambda state: state.has('Cane of Somaria', player))
|
||||||
set_rule(world.get_entrance('TR Final Abyss Balcony Path', player), lambda state: state.has('Cane of Somaria', player))
|
set_rule(world.get_entrance('TR Final Abyss Balcony Path', player), lambda state: state.has('Cane of Somaria', player))
|
||||||
@@ -1385,8 +1386,9 @@ def add_conditional_lamps(world, player):
|
|||||||
add_lamp_requirement(spot, player)
|
add_lamp_requirement(spot, player)
|
||||||
|
|
||||||
dark_rooms = {
|
dark_rooms = {
|
||||||
'TR Dark Ride': {'sewer': False, 'entrances': ['TR Dark Ride Up Stairs', 'TR Dark Ride SW', 'TR Dark Ride Path'], 'locations': []},
|
'TR Dark Ride North Platform': {'sewer': False, 'entrances': ['TR Dark Ride Up Stairs', 'TR Dark Ride Normal Path', 'TR Dark Ride Ledge Path'], 'locations': []},
|
||||||
'TR Dark Ride Ledges': {'sewer': False, 'entrances': ['TR Dark Ride Ledges Path'], 'locations': []},
|
'TR Dark Ride South Platform': {'sewer': False, 'entrances': ['TR Dark Ride SW', 'TR Dark Ride Backward Path'], 'locations': []},
|
||||||
|
'TR Dark Ride Ledges': {'sewer': False, 'entrances': ['TR Dark Ride Return Path'], 'locations': []},
|
||||||
'Mire Dark Shooters': {'sewer': False, 'entrances': ['Mire Dark Shooters Up Stairs', 'Mire Dark Shooters SW', 'Mire Dark Shooters SE'], 'locations': []},
|
'Mire Dark Shooters': {'sewer': False, 'entrances': ['Mire Dark Shooters Up Stairs', 'Mire Dark Shooters SW', 'Mire Dark Shooters SE'], 'locations': []},
|
||||||
'Mire Key Rupees': {'sewer': False, 'entrances': ['Mire Key Rupees NE'], 'locations': []},
|
'Mire Key Rupees': {'sewer': False, 'entrances': ['Mire Key Rupees NE'], 'locations': []},
|
||||||
'Mire Block X': {'sewer': False, 'entrances': ['Mire Block X NW', 'Mire Block X WS'], 'locations': []},
|
'Mire Block X': {'sewer': False, 'entrances': ['Mire Block X NW', 'Mire Block X WS'], 'locations': []},
|
||||||
@@ -1920,7 +1922,7 @@ bunny_revivable_entrances = {
|
|||||||
"Ice Many Pots", "Mire South Fish", "Mire Right Bridge", "Mire Left Bridge",
|
"Ice Many Pots", "Mire South Fish", "Mire Right Bridge", "Mire Left Bridge",
|
||||||
"TR Boss", "Eastern Hint Tile Blocked Path", "Thieves Spike Switch",
|
"TR Boss", "Eastern Hint Tile Blocked Path", "Thieves Spike Switch",
|
||||||
"Thieves Boss", "Mire Spike Barrier", "Mire Cross", "Mire Hidden Shooters",
|
"Thieves Boss", "Mire Spike Barrier", "Mire Cross", "Mire Hidden Shooters",
|
||||||
"Mire Spikes", "TR Final Abyss Balcony", "TR Dark Ride", "TR Pokey 1", "TR Tile Room",
|
"Mire Spikes", "TR Final Abyss Balcony", "TR Dark Ride South Platform", "TR Pokey 1", "TR Tile Room",
|
||||||
"TR Roller Room", "Eastern Cannonball", "Thieves Hallway", "Ice Switch Room",
|
"TR Roller Room", "Eastern Cannonball", "Thieves Hallway", "Ice Switch Room",
|
||||||
"Mire Tile Room", "Mire Conveyor Crystal", "Mire Hub", "TR Dash Bridge",
|
"Mire Tile Room", "Mire Conveyor Crystal", "Mire Hub", "TR Dash Bridge",
|
||||||
"TR Hub", "Eastern Boss", "Eastern Lobby", "Thieves Ambush",
|
"TR Hub", "Eastern Boss", "Eastern Lobby", "Thieves Ambush",
|
||||||
@@ -1988,8 +1990,8 @@ bunny_impassible_doors = {
|
|||||||
'TR Lobby Ledge Gap', 'TR Hub SW', 'TR Hub SE', 'TR Hub ES', 'TR Hub EN', 'TR Hub NW', 'TR Hub NE', 'TR Hub Path',
|
'TR Lobby Ledge Gap', 'TR Hub SW', 'TR Hub SE', 'TR Hub ES', 'TR Hub EN', 'TR Hub NW', 'TR Hub NE', 'TR Hub Path',
|
||||||
'TR Hub Ledges Path', 'TR Torches NW', 'TR Pokey 2 Bottom to Top Barrier - Blue',
|
'TR Hub Ledges Path', 'TR Torches NW', 'TR Pokey 2 Bottom to Top Barrier - Blue',
|
||||||
'TR Pokey 2 Top to Bottom Barrier - Blue', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap',
|
'TR Pokey 2 Top to Bottom Barrier - Blue', 'TR Twin Pokeys SW', 'TR Twin Pokeys EN', 'TR Big Chest Gap',
|
||||||
'TR Big Chest Entrance Gap', 'TR Lazy Eyes ES', 'TR Tongue Pull WS', 'TR Tongue Pull NE', 'TR Dark Ride Up Stairs',
|
'TR Big Chest Entrance Gap', 'TR Lazy Eyes ES', 'TR Tongue Pull WS', 'TR Tongue Pull NE', 'TR Dark Ride SW', # due to needing the switch
|
||||||
'TR Dark Ride SW', 'TR Dark Ride Path', 'TR Dark Ride Ledges Path',
|
'TR Dark Ride Normal Path', 'TR Dark Ride Ledge Path', 'TR Dark Ride Backward Path', 'TR Dark Ride Return Path',
|
||||||
'TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze End to Interior Barrier - Blue',
|
'TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze End to Interior Barrier - Blue',
|
||||||
'TR Final Abyss Balcony Path', 'TR Final Abyss Ledge Path', 'GT Hope Room EN', 'GT Blocked Stairs Block Path',
|
'TR Final Abyss Balcony Path', 'TR Final Abyss Ledge Path', 'GT Hope Room EN', 'GT Blocked Stairs Block Path',
|
||||||
'GT Bob\'s Room Hole', 'GT Speed Torch SE', 'GT Speed Torch South Path', 'GT Speed Torch North Path',
|
'GT Bob\'s Room Hole', 'GT Speed Torch SE', 'GT Speed Torch South Path', 'GT Speed Torch North Path',
|
||||||
|
|||||||
Binary file not shown.
@@ -46,6 +46,13 @@ Player 1's settings will be determined by rolling the mystery weights and player
|
|||||||
|
|
||||||
Start inventory is not supported here. It has a separate section.
|
Start inventory is not supported here. It has a separate section.
|
||||||
|
|
||||||
|
#### Extra Settings
|
||||||
|
|
||||||
|
Some settings are intended to only be accessed using the customizer:
|
||||||
|
|
||||||
|
* `aga_randomness` setting this to false, turns off blue balls and ganon warp randomness
|
||||||
|
* `money_balance` this is a percent (0-100). For numbers less than 100, both price balancing and money balancing will only attempt to ensure the player has access to only a percentage of the required funds. When 0, this should effectively disable money balancing. Grinding for rupees may be necessary whenever this is less than 100.
|
||||||
|
|
||||||
###### Not Yet Implemented
|
###### Not Yet Implemented
|
||||||
|
|
||||||
Rom/Adjust flags like sprite, quickswap are not outputing with the print_template_yaml or print_custom_yaml settings
|
Rom/Adjust flags like sprite, quickswap are not outputing with the print_template_yaml or print_custom_yaml settings
|
||||||
@@ -310,3 +317,18 @@ drops:
|
|||||||
```
|
```
|
||||||
|
|
||||||
Prize packs expect a list of eight items each (anything not specified will be whatever randomization would have normally occurred). The special drops expect a single item. Packs 1 through 7 are supported. Prize pack 0 is not customizable.
|
Prize packs expect a list of eight items each (anything not specified will be whatever randomization would have normally occurred). The special drops expect a single item. Packs 1 through 7 are supported. Prize pack 0 is not customizable.
|
||||||
|
|
||||||
|
## prices
|
||||||
|
|
||||||
|
This must be defined by player. You may have the prices of items in shops defined using the following
|
||||||
|
|
||||||
|
```
|
||||||
|
prices:
|
||||||
|
1:
|
||||||
|
Capacity Upgrade - Left: 100
|
||||||
|
Capacity Upgrade - Right: 200
|
||||||
|
Dark Death Mountain Shop - Left: 100
|
||||||
|
Dark Death Mountain Shop - Middle: 150
|
||||||
|
Dark Death Mountain Shop - Right: 300
|
||||||
|
Dark Lake Hylia Shop - Left: 200
|
||||||
|
```
|
||||||
@@ -166,6 +166,10 @@ bosses:
|
|||||||
Palace of Darkness: Arrghus
|
Palace of Darkness: Arrghus
|
||||||
Thieves Town: Blind
|
Thieves Town: Blind
|
||||||
Ganons Tower (top): Vitreous
|
Ganons Tower (top): Vitreous
|
||||||
|
prices:
|
||||||
|
1:
|
||||||
|
Capacity Upgrade - Left: 5
|
||||||
|
Capacity Upgrade - Right: 216
|
||||||
start_inventory:
|
start_inventory:
|
||||||
1:
|
1:
|
||||||
- Pegasus Boots
|
- Pegasus Boots
|
||||||
|
|||||||
@@ -553,6 +553,10 @@
|
|||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
|
"mirrorscroll": {
|
||||||
|
"action": "store_true",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
"calc_playthrough": {
|
"calc_playthrough": {
|
||||||
"action": "store_false",
|
"action": "store_false",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
@@ -623,6 +627,7 @@
|
|||||||
"action": "store_false",
|
"action": "store_false",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
|
"money_balance": {},
|
||||||
"settingsonload": {
|
"settingsonload": {
|
||||||
"choices": [
|
"choices": [
|
||||||
"default",
|
"default",
|
||||||
|
|||||||
@@ -394,6 +394,7 @@
|
|||||||
],
|
],
|
||||||
"collection_rate": [ "Display collection rate (default: %(default)s)" ],
|
"collection_rate": [ "Display collection rate (default: %(default)s)" ],
|
||||||
"pseudoboots": [ " Start with pseudo boots that allow dashing but no item checks (default: %(default)s)"],
|
"pseudoboots": [ " Start with pseudo boots that allow dashing but no item checks (default: %(default)s)"],
|
||||||
|
"mirrorscroll": [ " Players starts with mirror scroll that allows mirror in dungeons but not overworld (default: %(default)s"],
|
||||||
"bombbag": ["Start with 0 bomb capacity. Two capacity upgrades (+10) are added to the pool (default: %(default)s)" ],
|
"bombbag": ["Start with 0 bomb capacity. Two capacity upgrades (+10) are added to the pool (default: %(default)s)" ],
|
||||||
"any_enemy_logic": [
|
"any_enemy_logic": [
|
||||||
"How to handle potential traversal between dungeon in Crossed door shuffle",
|
"How to handle potential traversal between dungeon in Crossed door shuffle",
|
||||||
|
|||||||
@@ -287,6 +287,7 @@
|
|||||||
"randomizer.item.retro": "Retro mode",
|
"randomizer.item.retro": "Retro mode",
|
||||||
"randomizer.item.pseudoboots": "Pseudoboots",
|
"randomizer.item.pseudoboots": "Pseudoboots",
|
||||||
"randomizer.item.collection_rate": "Display Collection Rate",
|
"randomizer.item.collection_rate": "Display Collection Rate",
|
||||||
|
"randomizer.item.mirrorscroll": "Mirror Scroll",
|
||||||
|
|
||||||
"randomizer.item.worldstate": "World State",
|
"randomizer.item.worldstate": "World State",
|
||||||
"randomizer.item.worldstate.standard": "Standard",
|
"randomizer.item.worldstate.standard": "Standard",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"checkboxes": {
|
"checkboxes": {
|
||||||
"hints": { "type": "checkbox" },
|
"hints": { "type": "checkbox" },
|
||||||
"pseudoboots": { "type": "checkbox" },
|
"pseudoboots": { "type": "checkbox" },
|
||||||
|
"mirrorscroll": { "type": "checkbox" },
|
||||||
"collection_rate": {"type": "checkbox"},
|
"collection_rate": {"type": "checkbox"},
|
||||||
"race": { "type": "checkbox" }
|
"race": { "type": "checkbox" }
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,11 +21,20 @@ class CustomSettings(object):
|
|||||||
self.relative_dir = None
|
self.relative_dir = None
|
||||||
self.world_rep = {}
|
self.world_rep = {}
|
||||||
self.player_range = None
|
self.player_range = None
|
||||||
|
self.player_map = {} # player number to name
|
||||||
|
|
||||||
def load_yaml(self, file):
|
def load_yaml(self, file):
|
||||||
self.file_source = load_yaml(file)
|
self.file_source = load_yaml(file)
|
||||||
head, filename = os.path.split(file)
|
head, filename = os.path.split(file)
|
||||||
self.relative_dir = head
|
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):
|
def determine_seed(self, default_seed):
|
||||||
if 'meta' in self.file_source:
|
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.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.overworld_map[p] = get_setting(settings['overworld_map'], args.overworld_map[p])
|
||||||
args.pseudoboots[p] = get_setting(settings['pseudoboots'], args.pseudoboots[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_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_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])
|
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.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.beemizer[p] = get_setting(settings['beemizer'], args.beemizer[p])
|
||||||
args.aga_randomness[p] = get_setting(settings['aga_randomness'], args.aga_randomness[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
|
# mystery usage
|
||||||
args.usestartinventory[p] = get_setting(settings['usestartinventory'], args.usestartinventory[p])
|
args.usestartinventory[p] = get_setting(settings['usestartinventory'], args.usestartinventory[p])
|
||||||
@@ -219,6 +230,9 @@ class CustomSettings(object):
|
|||||||
return self.file_source['placements']
|
return self.file_source['placements']
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_prices(self, player):
|
||||||
|
return self.get_attribute_by_player_composite('prices', player)
|
||||||
|
|
||||||
def get_advanced_placements(self):
|
def get_advanced_placements(self):
|
||||||
if 'advanced_placements' in self.file_source:
|
if 'advanced_placements' in self.file_source:
|
||||||
return self.file_source['advanced_placements']
|
return self.file_source['advanced_placements']
|
||||||
@@ -284,6 +298,34 @@ class CustomSettings(object):
|
|||||||
return self.file_source['enemies']
|
return self.file_source['enemies']
|
||||||
return None
|
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):
|
def create_from_world(self, world, settings):
|
||||||
self.player_range = range(1, world.players + 1)
|
self.player_range = range(1, world.players + 1)
|
||||||
settings_dict, meta_dict = {}, {}
|
settings_dict, meta_dict = {}, {}
|
||||||
@@ -355,10 +397,12 @@ class CustomSettings(object):
|
|||||||
settings_dict[p]['linked_drops'] = world.linked_drops[p]
|
settings_dict[p]['linked_drops'] = world.linked_drops[p]
|
||||||
settings_dict[p]['overworld_map'] = world.overworld_map[p]
|
settings_dict[p]['overworld_map'] = world.overworld_map[p]
|
||||||
settings_dict[p]['pseudoboots'] = world.pseudoboots[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_goal'] = world.treasure_hunt_count[p]
|
||||||
settings_dict[p]['triforce_pool'] = world.treasure_hunt_total[p]
|
settings_dict[p]['triforce_pool'] = world.treasure_hunt_total[p]
|
||||||
settings_dict[p]['beemizer'] = world.beemizer[p]
|
settings_dict[p]['beemizer'] = world.beemizer[p]
|
||||||
settings_dict[p]['aga_randomness'] = world.aga_randomness[p]
|
settings_dict[p]['aga_randomness'] = world.aga_randomness[p]
|
||||||
|
settings_dict[p]['money_balance'] = world.money_balance[p]
|
||||||
if world.precollected_items:
|
if world.precollected_items:
|
||||||
start_inv[p] = []
|
start_inv[p] = []
|
||||||
for item in world.precollected_items:
|
for item in world.precollected_items:
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ SETTINGSTOPROCESS = {
|
|||||||
"item": {
|
"item": {
|
||||||
"hints": "hints",
|
"hints": "hints",
|
||||||
"pseudoboots": "pseudoboots",
|
"pseudoboots": "pseudoboots",
|
||||||
|
"mirrorscroll": "mirrorscroll",
|
||||||
'collection_rate': 'collection_rate',
|
'collection_rate': 'collection_rate',
|
||||||
"race": "race",
|
"race": "race",
|
||||||
|
|
||||||
|
|||||||
@@ -1657,9 +1657,9 @@ def init_vanilla_sprites():
|
|||||||
create_sprite(0x00b3, EnemySprite.Beamos, 0x00, 0, 0x06, 0x18, 'Mire Spikes')
|
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.FourWayShooter, 0x00, 0, 0x0a, 0x1a, 'Mire Spikes')
|
||||||
create_sprite(0x00b3, EnemySprite.Stalfos, 0x00, 0, 0x07, 0x1c, '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, 0x16, 0x0a, 'TR Dark Ride Ledges')
|
||||||
create_sprite(0x00b5, EnemySprite.FirebarCW, 0x00, 0, 0x09, 0x0f, 'TR Dark Ride')
|
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')
|
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, 0x06, 0x07, 'TR Chain Chomps Top')
|
||||||
create_sprite(0x00b6, EnemySprite.Chainchomp, 0x00, 0, 0x0a, 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)
|
create_sprite(0x00b6, EnemySprite.CrystalSwitch, 0x00, 0, 0x03, 0x04)
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
|
|||||||
rem_entrances.update(lw_entrances)
|
rem_entrances.update(lw_entrances)
|
||||||
rem_entrances.update(dw_entrances)
|
rem_entrances.update(dw_entrances)
|
||||||
else:
|
else:
|
||||||
# cross world mandantory
|
# cross world mandatory
|
||||||
entrance_list = list(entrances)
|
entrance_list = list(entrances)
|
||||||
if avail.swapped:
|
if avail.swapped:
|
||||||
forbidden = [e for e in Forbidden_Swap_Entrances if e in entrance_list]
|
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)
|
avail.decoupled_exits.remove(bomb_shop)
|
||||||
rem_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
|
# old man S&Q cave
|
||||||
if not cross_world and not avail.assumed_loose_caves:
|
if not cross_world and not avail.assumed_loose_caves:
|
||||||
#TODO: Add Swapped ER support for this
|
#TODO: Add Swapped ER support for this
|
||||||
# OM Cave entrance in lw/dw if cross_world off
|
# OM Cave entrance in lw/dw if cross_world off
|
||||||
if 'Old Man Cave Exit (West)' in rem_exits:
|
if 'Old Man Cave Exit (West)' in rem_exits:
|
||||||
world_limiter = DW_Entrances if avail.inverted else LW_Entrances
|
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)
|
om_cave_choice = random.choice(om_cave_options)
|
||||||
if not avail.coupled:
|
if not avail.coupled:
|
||||||
connect_exit('Old Man Cave Exit (West)', om_cave_choice, avail)
|
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:
|
for ext in om_house:
|
||||||
if ext in rem_exits:
|
if ext in rem_exits:
|
||||||
world_limiter = DW_Entrances if avail.inverted else LW_Entrances
|
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)
|
om_house_choice = random.choice(om_house_options)
|
||||||
if not avail.coupled:
|
if not avail.coupled:
|
||||||
connect_exit(ext, om_house_choice, avail)
|
connect_exit(ext, om_house_choice, avail)
|
||||||
@@ -361,7 +358,7 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
|
|||||||
lw_entrances, dw_entrances = [], []
|
lw_entrances, dw_entrances = [], []
|
||||||
left = sorted(rem_entrances)
|
left = sorted(rem_entrances)
|
||||||
for x in left:
|
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)
|
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)
|
do_same_world_connectors(lw_entrances, dw_entrances, multi_exit_caves, avail)
|
||||||
if avail.world.doorShuffle[avail.player] != 'vanilla':
|
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(lw_entrances)
|
||||||
unused_entrances.update(dw_entrances)
|
unused_entrances.update(dw_entrances)
|
||||||
else:
|
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)
|
do_cross_world_connectors(entrance_list, multi_exit_caves, avail)
|
||||||
unused_entrances.update(entrance_list)
|
unused_entrances.update(entrance_list)
|
||||||
|
|
||||||
@@ -1527,6 +1524,8 @@ def do_vanilla_connect(pool_def, avail):
|
|||||||
avail.entrances.remove(entrance)
|
avail.entrances.remove(entrance)
|
||||||
avail.exits.remove(target)
|
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):
|
def do_mandatory_connections(avail, entrances, cave_options, must_exit):
|
||||||
if len(must_exit) == 0:
|
if len(must_exit) == 0:
|
||||||
@@ -1614,7 +1613,8 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
|
|||||||
if len(cave) == 2:
|
if len(cave) == 2:
|
||||||
entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit]
|
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 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)
|
entrances.remove(entrance)
|
||||||
connect_two_way(entrance, rnd_cave[0], avail)
|
connect_two_way(entrance, rnd_cave[0], avail)
|
||||||
if avail.swapped and avail.combine_map[entrance] != rnd_cave[0]:
|
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)
|
cave_entrances.append(entrance)
|
||||||
else:
|
else:
|
||||||
entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit] and e not in must_exit
|
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)
|
cave_entrances.append(entrance)
|
||||||
entrances.remove(entrance)
|
entrances.remove(entrance)
|
||||||
connect_two_way(entrance, cave_exit, avail)
|
connect_two_way(entrance, cave_exit, avail)
|
||||||
@@ -1670,7 +1670,7 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
entrance = next(e for e in entrances[::-1] if e not in invalid_cave_connections[tuple(cave)]
|
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()
|
invalid_cave_connections[tuple(cave)] = set()
|
||||||
entrances.remove(entrance)
|
entrances.remove(entrance)
|
||||||
connect_two_way(entrance, cave_exit, avail)
|
connect_two_way(entrance, cave_exit, avail)
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ def roll_settings(weights):
|
|||||||
ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle != 'none' else 'off'
|
ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle != 'none' else 'off'
|
||||||
|
|
||||||
ret.pseudoboots = get_choice_bool('pseudoboots')
|
ret.pseudoboots = get_choice_bool('pseudoboots')
|
||||||
|
ret.mirrorscroll = get_choice_bool('mirrorscroll')
|
||||||
ret.shopsanity = get_choice_bool('shopsanity')
|
ret.shopsanity = get_choice_bool('shopsanity')
|
||||||
keydropshuffle = get_choice_bool('keydropshuffle')
|
keydropshuffle = get_choice_bool('keydropshuffle')
|
||||||
ret.dropshuffle = get_choice('dropshuffle') if 'dropshuffle' in weights else 'none'
|
ret.dropshuffle = get_choice('dropshuffle') if 'dropshuffle' in weights else 'none'
|
||||||
|
|||||||
Reference in New Issue
Block a user