Merge branch 'master' into msu_v32
This commit is contained in:
commit
96bea214da
|
@ -114,6 +114,7 @@ class World(object):
|
||||||
set_player_attr('glitch_boots', True)
|
set_player_attr('glitch_boots', True)
|
||||||
set_player_attr('progression_balancing', True)
|
set_player_attr('progression_balancing', True)
|
||||||
set_player_attr('local_items', set())
|
set_player_attr('local_items', set())
|
||||||
|
set_player_attr('triforce_pieces_required', 20)
|
||||||
|
|
||||||
def get_name_string_for_object(self, obj) -> str:
|
def get_name_string_for_object(self, obj) -> str:
|
||||||
return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'
|
return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'
|
||||||
|
@ -1193,7 +1194,8 @@ class Spoiler(object):
|
||||||
'shufflepots': self.world.shufflepots,
|
'shufflepots': self.world.shufflepots,
|
||||||
'players': self.world.players,
|
'players': self.world.players,
|
||||||
'teams': self.world.teams,
|
'teams': self.world.teams,
|
||||||
'progression_balancing' : self.world.progression_balancing
|
'progression_balancing': self.world.progression_balancing,
|
||||||
|
'triforce_pieces_required': self.world.triforce_pieces_required,
|
||||||
}
|
}
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
|
@ -1231,21 +1233,29 @@ class Spoiler(object):
|
||||||
self.hashes[player, team]))
|
self.hashes[player, team]))
|
||||||
outfile.write('Logic: %s\n' % self.metadata['logic'][player])
|
outfile.write('Logic: %s\n' % self.metadata['logic'][player])
|
||||||
if self.world.players > 1:
|
if self.world.players > 1:
|
||||||
outfile.write('Progression Balanced: %s\n' % ('Yes' if self.metadata['progression_balancing'][player] else 'No'))
|
outfile.write('Progression Balanced: %s\n' % (
|
||||||
|
'Yes' if self.metadata['progression_balancing'][player] else 'No'))
|
||||||
outfile.write('Mode: %s\n' % self.metadata['mode'][player])
|
outfile.write('Mode: %s\n' % self.metadata['mode'][player])
|
||||||
outfile.write('Retro: %s\n' % ('Yes' if self.metadata['retro'][player] else 'No'))
|
outfile.write(
|
||||||
|
'Retro: %s\n' % ('Yes' if self.metadata['retro'][player] else 'No'))
|
||||||
outfile.write('Swords: %s\n' % self.metadata['weapons'][player])
|
outfile.write('Swords: %s\n' % self.metadata['weapons'][player])
|
||||||
outfile.write('Goal: %s\n' % self.metadata['goal'][player])
|
outfile.write('Goal: %s\n' % self.metadata['goal'][player])
|
||||||
|
if "triforce" in self.metadata["goal"][player]: # triforce hunt
|
||||||
|
outfile.write(
|
||||||
|
"Pieces required for Triforce: %s\n" % self.metadata["triforce_pieces_required"][player])
|
||||||
outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player])
|
outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player])
|
||||||
outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player])
|
outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player])
|
||||||
outfile.write('Item Progression: %s\n' % self.metadata['progressive'][player])
|
outfile.write('Item Progression: %s\n' % self.metadata['progressive'][player])
|
||||||
outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player])
|
outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player])
|
||||||
outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player])
|
outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player])
|
||||||
outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player])
|
outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player])
|
||||||
outfile.write('Pyramid hole pre-opened: %s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No'))
|
outfile.write('Pyramid hole pre-opened: %s\n' % (
|
||||||
|
'Yes' if self.metadata['open_pyramid'][player] else 'No'))
|
||||||
outfile.write('Accessibility: %s\n' % self.metadata['accessibility'][player])
|
outfile.write('Accessibility: %s\n' % self.metadata['accessibility'][player])
|
||||||
outfile.write('Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No'))
|
outfile.write(
|
||||||
outfile.write('Compass shuffle: %s\n' % ('Yes' if self.metadata['compassshuffle'][player] else 'No'))
|
'Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No'))
|
||||||
|
outfile.write('Compass shuffle: %s\n' % (
|
||||||
|
'Yes' if self.metadata['compassshuffle'][player] else 'No'))
|
||||||
outfile.write('Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'][player] else 'No'))
|
outfile.write('Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'][player] else 'No'))
|
||||||
outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'][player] else 'No'))
|
outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'][player] else 'No'))
|
||||||
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player])
|
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player])
|
||||||
|
|
|
@ -81,14 +81,19 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
Local Triforce Hunt: Places 30 Triforce Pieces in your world, collect
|
Local Triforce Hunt: Places 30 Triforce Pieces in your world, collect
|
||||||
20 of them to beat the game.
|
20 of them to beat the game.
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'],
|
parser.add_argument('--triforce_pieces_required', default=defval(20),
|
||||||
|
type=lambda value: min(max(int(value), 1), 30),
|
||||||
|
help='''Set Triforce Pieces required to win a Triforce Hunt''')
|
||||||
|
parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?',
|
||||||
|
choices=['normal', 'hard', 'expert'],
|
||||||
help='''\
|
help='''\
|
||||||
Select game difficulty. Affects available itempool. (default: %(default)s)
|
Select game difficulty. Affects available itempool. (default: %(default)s)
|
||||||
Normal: Normal difficulty.
|
Normal: Normal difficulty.
|
||||||
Hard: A harder setting with less equipment and reduced health.
|
Hard: A harder setting with less equipment and reduced health.
|
||||||
Expert: A harder yet setting with minimum equipment and health.
|
Expert: A harder yet setting with minimum equipment and health.
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--item_functionality', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'],
|
parser.add_argument('--item_functionality', default=defval('normal'), const='normal', nargs='?',
|
||||||
|
choices=['normal', 'hard', 'expert'],
|
||||||
help='''\
|
help='''\
|
||||||
Select limits on item functionality to increase difficulty. (default: %(default)s)
|
Select limits on item functionality to increase difficulty. (default: %(default)s)
|
||||||
Normal: Normal functionality.
|
Normal: Normal functionality.
|
||||||
|
@ -328,7 +333,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
'local_items', 'retro', 'accessibility', 'hints', 'beemizer',
|
'local_items', 'retro', 'accessibility', 'hints', 'beemizer',
|
||||||
'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', "skip_progression_balancing",
|
'heartbeep', "skip_progression_balancing", "triforce_pieces_required",
|
||||||
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots']:
|
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots']:
|
||||||
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:
|
||||||
|
|
|
@ -33,7 +33,7 @@ Difficulty = namedtuple('Difficulty',
|
||||||
['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield',
|
['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield',
|
||||||
'basicshield', 'progressivearmor', 'basicarmor', 'swordless',
|
'basicshield', 'progressivearmor', 'basicarmor', 'swordless',
|
||||||
'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother',
|
'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother',
|
||||||
'triforcehunt', 'triforce_pieces_required', 'retro',
|
'triforcehunt', 'retro',
|
||||||
'extras', 'progressive_sword_limit', 'progressive_shield_limit',
|
'extras', 'progressive_sword_limit', 'progressive_shield_limit',
|
||||||
'progressive_armor_limit', 'progressive_bottle_limit',
|
'progressive_armor_limit', 'progressive_bottle_limit',
|
||||||
'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit'])
|
'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit'])
|
||||||
|
@ -57,7 +57,6 @@ difficulties = {
|
||||||
timedohko = ['Green Clock'] * 25,
|
timedohko = ['Green Clock'] * 25,
|
||||||
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
||||||
triforcehunt = ['Triforce Piece'] * 30,
|
triforcehunt = ['Triforce Piece'] * 30,
|
||||||
triforce_pieces_required = 20,
|
|
||||||
retro = ['Small Key (Universal)'] * 17 + ['Rupees (20)'] * 10,
|
retro = ['Small Key (Universal)'] * 17 + ['Rupees (20)'] * 10,
|
||||||
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
||||||
progressive_sword_limit = 4,
|
progressive_sword_limit = 4,
|
||||||
|
@ -84,7 +83,6 @@ difficulties = {
|
||||||
timedohko = ['Green Clock'] * 25,
|
timedohko = ['Green Clock'] * 25,
|
||||||
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
||||||
triforcehunt = ['Triforce Piece'] * 30,
|
triforcehunt = ['Triforce Piece'] * 30,
|
||||||
triforce_pieces_required = 20,
|
|
||||||
retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15,
|
retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15,
|
||||||
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
||||||
progressive_sword_limit = 3,
|
progressive_sword_limit = 3,
|
||||||
|
@ -111,7 +109,6 @@ difficulties = {
|
||||||
timedohko = ['Green Clock'] * 20 + ['Red Clock'] * 5,
|
timedohko = ['Green Clock'] * 20 + ['Red Clock'] * 5,
|
||||||
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10,
|
||||||
triforcehunt = ['Triforce Piece'] * 30,
|
triforcehunt = ['Triforce Piece'] * 30,
|
||||||
triforce_pieces_required = 20,
|
|
||||||
retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15,
|
retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15,
|
||||||
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra],
|
||||||
progressive_sword_limit = 2,
|
progressive_sword_limit = 2,
|
||||||
|
@ -146,7 +143,7 @@ def generate_itempool(world, player):
|
||||||
|
|
||||||
loc = Location(player, "Murahdahla", parent=region)
|
loc = Location(player, "Murahdahla", parent=region)
|
||||||
loc.access_rule = lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star',
|
loc.access_rule = lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star',
|
||||||
player) > \
|
player) >= \
|
||||||
state.world.treasure_hunt_count[player]
|
state.world.treasure_hunt_count[player]
|
||||||
region.locations.append(loc)
|
region.locations.append(loc)
|
||||||
world.dynamic_locations.append(loc)
|
world.dynamic_locations.append(loc)
|
||||||
|
@ -507,7 +504,7 @@ def get_pool_core(world, player: int):
|
||||||
if goal in {'triforcehunt', 'localtriforcehunt'}:
|
if goal in {'triforcehunt', 'localtriforcehunt'}:
|
||||||
pool.extend(diff.triforcehunt)
|
pool.extend(diff.triforcehunt)
|
||||||
extraitems -= len(diff.triforcehunt)
|
extraitems -= len(diff.triforcehunt)
|
||||||
treasure_hunt_count = diff.triforce_pieces_required
|
treasure_hunt_count = world.triforce_pieces_required[player]
|
||||||
treasure_hunt_icon = 'Triforce Piece'
|
treasure_hunt_icon = 'Triforce Piece'
|
||||||
|
|
||||||
for extra in diff.extras:
|
for extra in diff.extras:
|
||||||
|
|
1
Main.py
1
Main.py
|
@ -58,6 +58,7 @@ def main(args, seed=None):
|
||||||
world.progressive = args.progressive.copy()
|
world.progressive = args.progressive.copy()
|
||||||
world.dungeon_counters = args.dungeon_counters.copy()
|
world.dungeon_counters = args.dungeon_counters.copy()
|
||||||
world.glitch_boots = args.glitch_boots.copy()
|
world.glitch_boots = args.glitch_boots.copy()
|
||||||
|
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
||||||
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
||||||
|
|
||||||
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
||||||
|
|
|
@ -50,7 +50,7 @@ class Context():
|
||||||
|
|
||||||
self.ui_node = WebUI.WebUiClient()
|
self.ui_node = WebUI.WebUiClient()
|
||||||
self.custom_address = None
|
self.custom_address = None
|
||||||
self.webui_socket_port = port
|
self.webui_socket_port: typing.Optional[int] = port
|
||||||
|
|
||||||
self.exit_event = asyncio.Event()
|
self.exit_event = asyncio.Event()
|
||||||
self.watcher_event = asyncio.Event()
|
self.watcher_event = asyncio.Event()
|
||||||
|
@ -1007,7 +1007,10 @@ class ClientCommandProcessor(CommandProcessor):
|
||||||
self.ctx.ui_node.log_info(f"Setting slow mode to {self.ctx.slow_mode}")
|
self.ctx.ui_node.log_info(f"Setting slow mode to {self.ctx.slow_mode}")
|
||||||
|
|
||||||
def _cmd_web(self):
|
def _cmd_web(self):
|
||||||
|
if self.ctx.webui_socket_port:
|
||||||
webbrowser.open(f'http://localhost:5050?port={self.ctx.webui_socket_port}')
|
webbrowser.open(f'http://localhost:5050?port={self.ctx.webui_socket_port}')
|
||||||
|
else:
|
||||||
|
self.output("Web UI was never started.")
|
||||||
|
|
||||||
def default(self, raw: str):
|
def default(self, raw: str):
|
||||||
asyncio.create_task(self.ctx.send_msgs([['Say', raw]]))
|
asyncio.create_task(self.ctx.send_msgs([['Say', raw]]))
|
||||||
|
@ -1263,7 +1266,7 @@ async def main():
|
||||||
parser.add_argument('--disable_web_ui', default=False, action='store_true', help="Turn off emitting a webserver for the webbrowser based user interface.")
|
parser.add_argument('--disable_web_ui', default=False, action='store_true', help="Turn off emitting a webserver for the webbrowser based user interface.")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
||||||
|
port = None
|
||||||
if not args.disable_web_ui:
|
if not args.disable_web_ui:
|
||||||
# Find an available port on the host system to use for hosting the websocket server
|
# Find an available port on the host system to use for hosting the websocket server
|
||||||
while True:
|
while True:
|
||||||
|
|
|
@ -294,6 +294,10 @@ def roll_settings(weights):
|
||||||
|
|
||||||
ret.crystals_ganon = get_choice('ganon_open', weights)
|
ret.crystals_ganon = get_choice('ganon_open', weights)
|
||||||
|
|
||||||
|
ret.triforce_pieces_required = get_choice('triforce_pieces_required',
|
||||||
|
weights) if "triforce_pieces_required" in weights else 20
|
||||||
|
ret.triforce_pieces_required = min(max(1, int(ret.triforce_pieces_required)), 30)
|
||||||
|
|
||||||
ret.mode = get_choice('world_state', weights)
|
ret.mode = get_choice('world_state', weights)
|
||||||
if ret.mode == 'retro':
|
if ret.mode == 'retro':
|
||||||
ret.mode = 'open'
|
ret.mode = 'open'
|
||||||
|
|
1
Rom.py
1
Rom.py
|
@ -634,7 +634,6 @@ def patch_rom(world, rom, player, team, enemized):
|
||||||
rom.write_byte(0x18003A, 0x01 if world.dark_world_light_cone else 0x00)
|
rom.write_byte(0x18003A, 0x01 if world.dark_world_light_cone else 0x00)
|
||||||
|
|
||||||
GREEN_TWENTY_RUPEES = 0x47
|
GREEN_TWENTY_RUPEES = 0x47
|
||||||
TRIFORCE_PIECE = ItemFactory('Triforce Piece', player).code
|
|
||||||
GREEN_CLOCK = ItemFactory('Green Clock', player).code
|
GREEN_CLOCK = ItemFactory('Green Clock', player).code
|
||||||
|
|
||||||
rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on
|
rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on
|
||||||
|
|
|
@ -75,6 +75,15 @@ goals:
|
||||||
pedestal: 0 # Pull the Triforce from the Master Sword pedestal
|
pedestal: 0 # Pull the Triforce from the Master Sword pedestal
|
||||||
triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout the worlds, then turn them in to Murahadala in front of Hyrule Castle
|
triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout the worlds, then turn them in to Murahadala in front of Hyrule Castle
|
||||||
local_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout your world, then turn them in to Murahadala in front of Hyrule Castle
|
local_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout your world, then turn them in to Murahadala in front of Hyrule Castle
|
||||||
|
triforce_pieces_required: # set to how many out of 30 triforce pieces you need to win the game in a triforce hunt. 20 is the default. Max is 30, Min is 1.
|
||||||
|
# format "pieces: chance"
|
||||||
|
15: 0
|
||||||
|
20: 1
|
||||||
|
21: 0
|
||||||
|
22: 0
|
||||||
|
23: 0
|
||||||
|
24: 0
|
||||||
|
25: 0
|
||||||
tower_open: # Crystals required to open GT
|
tower_open: # Crystals required to open GT
|
||||||
'0': 8
|
'0': 8
|
||||||
'1': 7
|
'1': 7
|
||||||
|
|
|
@ -73,9 +73,9 @@ begin
|
||||||
if (RegQueryStringValue(HKEY_LOCAL_MACHINE,
|
if (RegQueryStringValue(HKEY_LOCAL_MACHINE,
|
||||||
'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64', 'Version', strVersion)) then
|
'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64', 'Version', strVersion)) then
|
||||||
begin
|
begin
|
||||||
// Is the installed version at least 14.24 ?
|
// Is the installed version at least the packaged one ?
|
||||||
Log('VC Redist x64 Version : found ' + strVersion);
|
Log('VC Redist x64 Version : found ' + strVersion);
|
||||||
Result := (CompareStr(strVersion, 'v14.24.28127.4') < 0);
|
Result := (CompareStr(strVersion, 'v14.26.28720') < 0);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
|
Loading…
Reference in New Issue