extra_keys setting for crossed door rando
This commit is contained in:
@@ -202,6 +202,7 @@ class World(object):
|
|||||||
set_player_attr('damage_challenge', 'normal')
|
set_player_attr('damage_challenge', 'normal')
|
||||||
set_player_attr('shuffle_damage_table', 'vanilla')
|
set_player_attr('shuffle_damage_table', 'vanilla')
|
||||||
set_player_attr('crystal_book', False)
|
set_player_attr('crystal_book', False)
|
||||||
|
set_player_attr('extra_keys', 0)
|
||||||
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', {})
|
||||||
@@ -1978,6 +1979,7 @@ class Dungeon(object):
|
|||||||
self.prize = None
|
self.prize = None
|
||||||
self.big_key = big_key
|
self.big_key = big_key
|
||||||
self.small_keys = small_keys
|
self.small_keys = small_keys
|
||||||
|
self.extra_small_keys = 0
|
||||||
self.dungeon_items = dungeon_items
|
self.dungeon_items = dungeon_items
|
||||||
self.bosses = dict()
|
self.bosses = dict()
|
||||||
self.player = player
|
self.player = player
|
||||||
@@ -3174,6 +3176,7 @@ class Spoiler(object):
|
|||||||
'damage_challenge': self.world.damage_challenge,
|
'damage_challenge': self.world.damage_challenge,
|
||||||
'shuffle_damage_table': self.world.shuffle_damage_table,
|
'shuffle_damage_table': self.world.shuffle_damage_table,
|
||||||
'crystal_book': self.world.crystal_book,
|
'crystal_book': self.world.crystal_book,
|
||||||
|
'extra_keys': self.world.extra_keys,
|
||||||
'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'],
|
||||||
@@ -3453,6 +3456,7 @@ class Spoiler(object):
|
|||||||
outfile.write('Damage Challenge:'.ljust(line_width) + '%s\n' % self.metadata['damage_challenge'][player])
|
outfile.write('Damage Challenge:'.ljust(line_width) + '%s\n' % self.metadata['damage_challenge'][player])
|
||||||
outfile.write('Damage Table Randomization:'.ljust(line_width) + '%s\n' % self.metadata['shuffle_damage_table'][player])
|
outfile.write('Damage Table Randomization:'.ljust(line_width) + '%s\n' % self.metadata['shuffle_damage_table'][player])
|
||||||
outfile.write('Crystal Book:'.ljust(line_width) + '%s\n' % yn(self.metadata['crystal_book'][player]))
|
outfile.write('Crystal Book:'.ljust(line_width) + '%s\n' % yn(self.metadata['crystal_book'][player]))
|
||||||
|
outfile.write('Extra Keys:'.ljust(line_width) + '%d%%\n' % self.metadata['extra_keys'][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']))
|
||||||
|
|
||||||
|
|||||||
5
CLI.py
5
CLI.py
@@ -163,8 +163,8 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
'shuffletavern', 'skullwoods', 'linked_drops',
|
'shuffletavern', 'skullwoods', 'linked_drops',
|
||||||
'pseudoboots', 'mirrorscroll', 'dark_rooms',
|
'pseudoboots', 'mirrorscroll', 'dark_rooms',
|
||||||
'damage_challenge', 'shuffle_damage_table',
|
'damage_challenge', 'shuffle_damage_table',
|
||||||
'crystal_book', 'retro', 'accessibility', 'hints',
|
'crystal_book', 'extra_keys', 'retro', 'accessibility',
|
||||||
'beemizer', 'experimental', 'dungeon_counters',
|
'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
||||||
'shufflebosses', 'shuffleenemies', 'enemy_health',
|
'shufflebosses', 'shuffleenemies', 'enemy_health',
|
||||||
'enemy_damage', 'shufflepots', 'ow_palettes',
|
'enemy_damage', 'shufflepots', 'ow_palettes',
|
||||||
'uw_palettes', 'sprite', 'triforce_gfx', 'disablemusic',
|
'uw_palettes', 'sprite', 'triforce_gfx', 'disablemusic',
|
||||||
@@ -254,6 +254,7 @@ def parse_settings():
|
|||||||
"damage_challenge": "normal",
|
"damage_challenge": "normal",
|
||||||
"shuffle_damage_table": "vanilla",
|
"shuffle_damage_table": "vanilla",
|
||||||
"crystal_book": False,
|
"crystal_book": False,
|
||||||
|
"extra_keys": 0,
|
||||||
|
|
||||||
"shuffleenemies": "none",
|
"shuffleenemies": "none",
|
||||||
"shufflebosses": "none",
|
"shufflebosses": "none",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import time
|
|||||||
from collections import defaultdict, deque
|
from collections import defaultdict, deque
|
||||||
from enum import Flag, unique
|
from enum import Flag, unique
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
from math import ceil
|
||||||
from typing import DefaultDict, Dict, List
|
from typing import DefaultDict, Dict, List
|
||||||
|
|
||||||
import RaceRandom as random
|
import RaceRandom as random
|
||||||
@@ -1599,7 +1600,11 @@ def assign_cross_keys(dungeon_builders, world, player):
|
|||||||
if actual_chest_keys == 0:
|
if actual_chest_keys == 0:
|
||||||
dungeon.small_keys = []
|
dungeon.small_keys = []
|
||||||
else:
|
else:
|
||||||
dungeon.small_keys = [ItemFactory(dungeon_keys[name], player)] * actual_chest_keys
|
extra_keys = ceil(actual_chest_keys * world.extra_keys[player] / 100)
|
||||||
|
logger.debug(f'Adding {extra_keys} extra small keys to {name}')
|
||||||
|
dungeon.extra_small_keys = extra_keys
|
||||||
|
created_keys = actual_chest_keys + extra_keys
|
||||||
|
dungeon.small_keys = [ItemFactory(dungeon_keys[name], player)] * created_keys
|
||||||
logger.info(f'{world.fish.translate("cli", "cli", "keydoor.shuffle.time.crossed")}: {time.process_time()-start}')
|
logger.info(f'{world.fish.translate("cli", "cli", "keydoor.shuffle.time.crossed")}: {time.process_time()-start}')
|
||||||
|
|
||||||
|
|
||||||
@@ -2171,7 +2176,10 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, all_
|
|||||||
if actual_chest_keys == 0:
|
if actual_chest_keys == 0:
|
||||||
dungeon.small_keys = []
|
dungeon.small_keys = []
|
||||||
else:
|
else:
|
||||||
dungeon.small_keys = [ItemFactory(dungeon_keys[dungeon_name], player) for _ in range(actual_chest_keys)]
|
extra_keys = ceil(actual_chest_keys * world.extra_keys[player] / 100)
|
||||||
|
dungeon.extra_small_keys = extra_keys
|
||||||
|
created_keys = actual_chest_keys + extra_keys
|
||||||
|
dungeon.small_keys = [ItemFactory(dungeon_keys[dungeon_name], player) for _ in range(created_keys)]
|
||||||
|
|
||||||
for name, small_list in small_map.items():
|
for name, small_list in small_map.items():
|
||||||
used_doors.update(flatten_pair_list(small_list))
|
used_doors.update(flatten_pair_list(small_list))
|
||||||
|
|||||||
3
Main.py
3
Main.py
@@ -564,6 +564,7 @@ def init_world(args, fish):
|
|||||||
world.damage_challenge = args.damage_challenge.copy()
|
world.damage_challenge = args.damage_challenge.copy()
|
||||||
world.shuffle_damage_table = args.shuffle_damage_table.copy()
|
world.shuffle_damage_table = args.shuffle_damage_table.copy()
|
||||||
world.crystal_book = args.crystal_book.copy()
|
world.crystal_book = args.crystal_book.copy()
|
||||||
|
world.extra_keys = {player: int(args.extra_keys[player]) for player in range(1, world.players + 1)}
|
||||||
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()
|
||||||
@@ -868,6 +869,7 @@ def copy_world(world):
|
|||||||
ret.damage_challenge = world.damage_challenge.copy()
|
ret.damage_challenge = world.damage_challenge.copy()
|
||||||
ret.shuffle_damage_table = world.shuffle_damage_table.copy()
|
ret.shuffle_damage_table = world.shuffle_damage_table.copy()
|
||||||
ret.crystal_book = world.crystal_book.copy()
|
ret.crystal_book = world.crystal_book.copy()
|
||||||
|
ret.extra_keys = world.extra_keys.copy()
|
||||||
ret.overworld_map = world.overworld_map.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()
|
||||||
@@ -1100,6 +1102,7 @@ def copy_world_premature(world, player, create_flute_exits=True):
|
|||||||
ret.damage_challenge = world.damage_challenge.copy()
|
ret.damage_challenge = world.damage_challenge.copy()
|
||||||
ret.shuffle_damage_table = world.shuffle_damage_table.copy()
|
ret.shuffle_damage_table = world.shuffle_damage_table.copy()
|
||||||
ret.crystal_book = world.crystal_book.copy()
|
ret.crystal_book = world.crystal_book.copy()
|
||||||
|
ret.extra_keys = world.extra_keys.copy()
|
||||||
ret.overworld_map = world.overworld_map.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()
|
||||||
|
|||||||
8
Rom.py
8
Rom.py
@@ -85,7 +85,7 @@ from Utils import int16_as_bytes, int32_as_bytes, local_path, snes_to_pc
|
|||||||
from Versions import DRVersion, GKVersion, ORVersion
|
from Versions import DRVersion, GKVersion, ORVersion
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '8945e9fdcefc02eb3ff3ad2a8892a180'
|
RANDOMIZERBASEHASH = '8a6d769751e2676e8d9da48871cb7634'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -818,11 +818,13 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
rom.write_byte(0x138002, 2)
|
rom.write_byte(0x138002, 2)
|
||||||
for name, layout in world.key_layout[player].items():
|
for name, layout in world.key_layout[player].items():
|
||||||
offset = compass_data[name][4]//2
|
offset = compass_data[name][4]//2
|
||||||
|
dungeon = world.get_dungeon(name, player)
|
||||||
if world.keyshuffle[player] == 'universal':
|
if world.keyshuffle[player] == 'universal':
|
||||||
rom.write_byte(0x187010+offset, layout.max_chests + layout.max_drops)
|
rom.write_byte(0x187010+offset, layout.max_chests + layout.max_drops)
|
||||||
else:
|
else:
|
||||||
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops) # not currently used
|
rom.write_byte(0x13f020+offset, layout.max_chests + layout.max_drops + dungeon.extra_small_keys) # not currently used
|
||||||
rom.write_byte(0x187010+offset, layout.max_chests)
|
rom.write_byte(0x187010+offset, layout.max_chests + dungeon.extra_small_keys)
|
||||||
|
rom.write_byte(0x187000+offset, dungeon.extra_small_keys)
|
||||||
builder = world.dungeon_layouts[player][name]
|
builder = world.dungeon_layouts[player][name]
|
||||||
bk_status = 1 if builder.bk_required else 0
|
bk_status = 1 if builder.bk_required else 0
|
||||||
bk_status = 2 if builder.bk_provided else bk_status
|
bk_status = 2 if builder.bk_provided else bk_status
|
||||||
|
|||||||
Binary file not shown.
@@ -665,6 +665,9 @@
|
|||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
|
"extra_keys": {
|
||||||
|
"type": "int"
|
||||||
|
},
|
||||||
"calc_playthrough": {
|
"calc_playthrough": {
|
||||||
"action": "store_false",
|
"action": "store_false",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
|
|||||||
@@ -425,6 +425,7 @@
|
|||||||
"AlwaysInLogic: Dark rooms are always considered to be in logic, even if the player cannot see"
|
"AlwaysInLogic: Dark rooms are always considered to be in logic, even if the player cannot see"
|
||||||
],
|
],
|
||||||
"crystal_book": [ " Book can be used indoors to flip the state of colored pegs (default: %(default)s)"],
|
"crystal_book": [ " Book can be used indoors to flip the state of colored pegs (default: %(default)s)"],
|
||||||
|
"extra_keys": [ " Percentage of extra small keys to create for each dungeon when door shuffle is enabled (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",
|
||||||
|
|||||||
Reference in New Issue
Block a user