Merge branch 'master' into owg_test
This commit is contained in:
commit
c6a61e9008
|
@ -114,6 +114,20 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
Timed mode. If time runs out, you lose (but can
|
Timed mode. If time runs out, you lose (but can
|
||||||
still keep playing).
|
still keep playing).
|
||||||
''')
|
''')
|
||||||
|
parser.add_argument('--dungeon_counters', default=defval('default'), const='default', nargs='?', choices=['default', 'on', 'pickup', 'off'],
|
||||||
|
help='''\
|
||||||
|
Select dungeon counter display settings. (default: %(default)s)
|
||||||
|
(Note, since timer takes up the same space on the hud as dungeon
|
||||||
|
counters, timer settings override dungeon counter settings.)
|
||||||
|
Default: Dungeon counters only show when the compass is
|
||||||
|
picked up, or otherwise sent, only when compass
|
||||||
|
shuffle is turned on.
|
||||||
|
On: Dungeon counters are always displayed.
|
||||||
|
Pickup: Dungeon counters are shown when the compass is
|
||||||
|
picked up, even when compass shuffle is turned
|
||||||
|
off.
|
||||||
|
Off: Dungeon counters are never shown.
|
||||||
|
''')
|
||||||
parser.add_argument('--progressive', default=defval('on'), const='normal', nargs='?', choices=['on', 'off', 'random'],
|
parser.add_argument('--progressive', default=defval('on'), const='normal', nargs='?', choices=['on', 'off', 'random'],
|
||||||
help='''\
|
help='''\
|
||||||
Select progressive equipment setting. Affects available itempool. (default: %(default)s)
|
Select progressive equipment setting. Affects available itempool. (default: %(default)s)
|
||||||
|
@ -288,6 +302,10 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
ret = parser.parse_args(argv)
|
ret = parser.parse_args(argv)
|
||||||
if ret.timer == "none":
|
if ret.timer == "none":
|
||||||
ret.timer = False
|
ret.timer = False
|
||||||
|
if ret.dungeon_counters == 'on':
|
||||||
|
ret.dungeon_counters = True
|
||||||
|
elif ret.dungeon_counters == 'off':
|
||||||
|
ret.dungeon_counters = False
|
||||||
if ret.keysanity:
|
if ret.keysanity:
|
||||||
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = [True] * 4
|
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = [True] * 4
|
||||||
|
|
||||||
|
@ -303,7 +321,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
'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',
|
'heartbeep',
|
||||||
'remote_items', 'progressive', 'extendedmsu']:
|
'remote_items', 'progressive', 'extendedmsu', 'dungeon_counters']:
|
||||||
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})
|
||||||
|
|
16
Gui.py
16
Gui.py
|
@ -289,6 +289,14 @@ def guiMain(args=None):
|
||||||
timerLabel = Label(timerFrame, text='Timer setting')
|
timerLabel = Label(timerFrame, text='Timer setting')
|
||||||
timerLabel.pack(side=LEFT)
|
timerLabel.pack(side=LEFT)
|
||||||
|
|
||||||
|
dungeonCounterFrame = Frame(drowDownFrame)
|
||||||
|
dungeonCounterVar = StringVar()
|
||||||
|
dungeonCounterVar.set('auto')
|
||||||
|
dungeonCounterOptionMenu = OptionMenu(dungeonCounterFrame, dungeonCounterVar, 'auto', 'off', 'on', 'on_compass_pickup')
|
||||||
|
dungeonCounterOptionMenu.pack(side=RIGHT)
|
||||||
|
dungeonCounterLabel = Label(dungeonCounterFrame, text='Dungeon Chest Counters')
|
||||||
|
dungeonCounterLabel.pack(side=LEFT)
|
||||||
|
|
||||||
progressiveFrame = Frame(drowDownFrame)
|
progressiveFrame = Frame(drowDownFrame)
|
||||||
progressiveVar = StringVar()
|
progressiveVar = StringVar()
|
||||||
progressiveVar.set('on')
|
progressiveVar.set('on')
|
||||||
|
@ -330,6 +338,7 @@ def guiMain(args=None):
|
||||||
difficultyFrame.pack(expand=True, anchor=E)
|
difficultyFrame.pack(expand=True, anchor=E)
|
||||||
itemfunctionFrame.pack(expand=True, anchor=E)
|
itemfunctionFrame.pack(expand=True, anchor=E)
|
||||||
timerFrame.pack(expand=True, anchor=E)
|
timerFrame.pack(expand=True, anchor=E)
|
||||||
|
dungeonCounterFrame.pack(expand=True, anchor=E)
|
||||||
progressiveFrame.pack(expand=True, anchor=E)
|
progressiveFrame.pack(expand=True, anchor=E)
|
||||||
accessibilityFrame.pack(expand=True, anchor=E)
|
accessibilityFrame.pack(expand=True, anchor=E)
|
||||||
algorithmFrame.pack(expand=True, anchor=E)
|
algorithmFrame.pack(expand=True, anchor=E)
|
||||||
|
@ -427,6 +436,13 @@ def guiMain(args=None):
|
||||||
guiargs.timer = timerVar.get()
|
guiargs.timer = timerVar.get()
|
||||||
if guiargs.timer == "none":
|
if guiargs.timer == "none":
|
||||||
guiargs.timer = False
|
guiargs.timer = False
|
||||||
|
guiargs.dungeon_counters = dungeonCounterVar.get()
|
||||||
|
if guiargs.dungeon_counters == "on_compass_pickup":
|
||||||
|
guiargs.dungeon_counters = "pickup"
|
||||||
|
elif guiargs.dungeon_counters == "on":
|
||||||
|
guiargs.dungeon_counters = True
|
||||||
|
elif guiargs.dungeon_counters == "off":
|
||||||
|
guiargs.dungeon_counters = False
|
||||||
guiargs.progressive = progressiveVar.get()
|
guiargs.progressive = progressiveVar.get()
|
||||||
guiargs.accessibility = accessibilityVar.get()
|
guiargs.accessibility = accessibilityVar.get()
|
||||||
guiargs.algorithm = algorithmVar.get()
|
guiargs.algorithm = algorithmVar.get()
|
||||||
|
|
1
Main.py
1
Main.py
|
@ -57,6 +57,7 @@ def main(args, seed=None):
|
||||||
world.timer = args.timer.copy()
|
world.timer = args.timer.copy()
|
||||||
world.shufflepots = args.shufflepots.copy()
|
world.shufflepots = args.shufflepots.copy()
|
||||||
world.progressive = args.progressive.copy()
|
world.progressive = args.progressive.copy()
|
||||||
|
world.dungeon_counters = args.dungeon_counters.copy()
|
||||||
world.extendedmsu = args.extendedmsu.copy()
|
world.extendedmsu = args.extendedmsu.copy()
|
||||||
|
|
||||||
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)}
|
||||||
|
|
|
@ -347,15 +347,20 @@ async def snes_connect(ctx : Context, address):
|
||||||
seen_problems.add(problem)
|
seen_problems.add(problem)
|
||||||
logging.error(f"Error connecting to QUsb2snes ({problem})")
|
logging.error(f"Error connecting to QUsb2snes ({problem})")
|
||||||
if len(seen_problems) == 1:
|
if len(seen_problems) == 1:
|
||||||
#this is the first problem. Let's try launching QUsb2snes if it isn't already running
|
# this is the first problem. Let's try launching QUsb2snes if it isn't already running
|
||||||
qusb2snes_path = Utils.get_options()["general_options"]["qusb2snes"]
|
qusb2snes_path = Utils.get_options()["general_options"]["qusb2snes"]
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
if not os.path.isfile(qusb2snes_path):
|
||||||
|
qusb2snes_path = Utils.local_path(qusb2snes_path)
|
||||||
|
|
||||||
if os.path.isfile(qusb2snes_path):
|
if os.path.isfile(qusb2snes_path):
|
||||||
logging.info(f"Attempting to start {qusb2snes_path}")
|
logging.info(f"Attempting to start {qusb2snes_path}")
|
||||||
import subprocess
|
import subprocess
|
||||||
subprocess.Popen(qusb2snes_path, cwd=os.path.dirname(qusb2snes_path))
|
subprocess.Popen(qusb2snes_path, cwd=os.path.dirname(qusb2snes_path))
|
||||||
else:
|
else:
|
||||||
logging.info(f"Attempt to start (Q)Usb2Snes was aborted as path {qusb2snes_path} was not found, please start it yourself if it is not running")
|
logging.info(
|
||||||
|
f"Attempt to start (Q)Usb2Snes was aborted as path {qusb2snes_path} was not found, please start it yourself if it is not running")
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
else:
|
else:
|
||||||
|
|
214
MultiServer.py
214
MultiServer.py
|
@ -6,6 +6,7 @@ import logging
|
||||||
import zlib
|
import zlib
|
||||||
import collections
|
import collections
|
||||||
import typing
|
import typing
|
||||||
|
import inspect
|
||||||
|
|
||||||
import ModuleUpdate
|
import ModuleUpdate
|
||||||
|
|
||||||
|
@ -66,6 +67,7 @@ class Context:
|
||||||
self.hints_used = collections.defaultdict(int)
|
self.hints_used = collections.defaultdict(int)
|
||||||
self.hints_sent = collections.defaultdict(set)
|
self.hints_sent = collections.defaultdict(set)
|
||||||
self.item_cheat = item_cheat
|
self.item_cheat = item_cheat
|
||||||
|
self.running = True
|
||||||
|
|
||||||
def get_save(self) -> dict:
|
def get_save(self) -> dict:
|
||||||
return {
|
return {
|
||||||
|
@ -124,7 +126,7 @@ def notify_client(client: Client, text: str):
|
||||||
asyncio.create_task(send_msgs(client.socket, [['Print', text]]))
|
asyncio.create_task(send_msgs(client.socket, [['Print', text]]))
|
||||||
|
|
||||||
|
|
||||||
# separated out, due to compatibilty between client's
|
# separated out, due to compatibilty between clients
|
||||||
def notify_hints(ctx: Context, team: int, hints: typing.List[Utils.Hint]):
|
def notify_hints(ctx: Context, team: int, hints: typing.List[Utils.Hint]):
|
||||||
cmd = [["Hint", hints]]
|
cmd = [["Hint", hints]]
|
||||||
texts = [['Print', format_hint(ctx, team, hint)] for hint in hints]
|
texts = [['Print', format_hint(ctx, team, hint)] for hint in hints]
|
||||||
|
@ -499,94 +501,145 @@ async def process_client_cmd(ctx: Context, client: Client, cmd, args):
|
||||||
notify_client(client, response)
|
notify_client(client, response)
|
||||||
|
|
||||||
|
|
||||||
def set_password(ctx : Context, password):
|
def set_password(ctx: Context, password):
|
||||||
ctx.password = password
|
ctx.password = password
|
||||||
logging.warning('Password set to ' + password if password else 'Password disabled')
|
logging.warning('Password set to ' + password if password else 'Password disabled')
|
||||||
|
|
||||||
|
|
||||||
|
class CommandProcessor():
|
||||||
|
commands: typing.Dict[str, typing.Callable]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.commands = {name[5:].lower(): method for name, method in inspect.getmembers(self) if
|
||||||
|
name.startswith("_cmd_")}
|
||||||
|
|
||||||
|
def output(self, text: str):
|
||||||
|
print(text)
|
||||||
|
|
||||||
|
def __call__(self, raw: str):
|
||||||
|
if not raw:
|
||||||
|
return
|
||||||
|
command = raw.split()
|
||||||
|
basecommand = command[0]
|
||||||
|
if basecommand[0] == "/":
|
||||||
|
method = self.commands.get(basecommand[1:].lower(), None)
|
||||||
|
if not method:
|
||||||
|
self._error_unknown_command(basecommand[1:])
|
||||||
|
else:
|
||||||
|
method(*command[1:])
|
||||||
|
else:
|
||||||
|
self.default(raw)
|
||||||
|
|
||||||
|
def get_help_text(self) -> str:
|
||||||
|
s = ""
|
||||||
|
for command, method in self.commands.items():
|
||||||
|
spec = inspect.signature(method).parameters
|
||||||
|
s += f"/{command} {' '.join(spec)}\n {method.__doc__}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
def _cmd_help(self):
|
||||||
|
"""Returns the help listing"""
|
||||||
|
self.output(self.get_help_text())
|
||||||
|
|
||||||
|
def default(self, raw: str):
|
||||||
|
self.output("Echo: " + raw)
|
||||||
|
|
||||||
|
def _error_unknown_command(self, raw: str):
|
||||||
|
self.output(f"Could not find command {raw}. Known commands: {', '.join(self.commands)}")
|
||||||
|
|
||||||
|
|
||||||
|
class ServerCommandProcessor(CommandProcessor):
|
||||||
|
ctx: Context
|
||||||
|
|
||||||
|
def __init__(self, ctx: Context):
|
||||||
|
self.ctx = ctx
|
||||||
|
super(ServerCommandProcessor, self).__init__()
|
||||||
|
|
||||||
|
def default(self, raw: str):
|
||||||
|
notify_all(self.ctx, '[Server]: ' + raw)
|
||||||
|
|
||||||
|
def _cmd_kick(self, player_name: str):
|
||||||
|
"""Kick specified player from the server"""
|
||||||
|
for client in self.ctx.clients:
|
||||||
|
if client.auth and client.name.lower() == player_name.lower() and client.socket and not client.socket.closed:
|
||||||
|
asyncio.create_task(client.socket.close())
|
||||||
|
self.output(f"Kicked {client.name}")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.output("Could not find player to kick")
|
||||||
|
|
||||||
|
def _cmd_players(self):
|
||||||
|
"""Get information about connected players"""
|
||||||
|
self.output(get_connected_players_string(self.ctx))
|
||||||
|
|
||||||
|
def _cmd_exit(self):
|
||||||
|
"""Shutdown the server"""
|
||||||
|
asyncio.create_task(self.ctx.server.ws_server._close())
|
||||||
|
self.ctx.running = False
|
||||||
|
|
||||||
|
def _cmd_password(self, new_password: str = ""):
|
||||||
|
"""Set the server password. Leave the password text empty to remove the password"""
|
||||||
|
set_password(self.ctx, new_password if new_password else None)
|
||||||
|
|
||||||
|
def _cmd_forfeit(self, player_name: str):
|
||||||
|
"""Send out the remaining items from a player's game to their intended recipients"""
|
||||||
|
seeked_player = player_name.lower()
|
||||||
|
for (team, slot), name in self.ctx.player_names.items():
|
||||||
|
if name.lower() == seeked_player:
|
||||||
|
forfeit_player(self.ctx, team, slot)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.output("Could not find player to forfeit")
|
||||||
|
|
||||||
|
def _cmd_send(self, player_name: str, *item_name: str):
|
||||||
|
"""Sends an item to the specified player"""
|
||||||
|
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
|
||||||
|
if usable:
|
||||||
|
item = " ".join(item_name)
|
||||||
|
item, usable, response = get_intended_text(item, Items.item_table.keys())
|
||||||
|
if usable:
|
||||||
|
for client in self.ctx.clients:
|
||||||
|
if client.name == seeked_player:
|
||||||
|
new_item = ReceivedItem(Items.item_table[item][3], -1, client.slot)
|
||||||
|
get_received_items(self.ctx, client.team, client.slot).append(new_item)
|
||||||
|
notify_all(self.ctx, 'Cheat console: sending "' + item + '" to ' + client.name)
|
||||||
|
send_new_items(self.ctx)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.output(response)
|
||||||
|
else:
|
||||||
|
self.output(response)
|
||||||
|
|
||||||
|
def _cmd_hint(self, player_name: str, *item_or_location: str):
|
||||||
|
"""Send out a hint for a player's item or location to their team"""
|
||||||
|
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
|
||||||
|
if usable:
|
||||||
|
for (team, slot), name in self.ctx.player_names.items():
|
||||||
|
if name == seeked_player:
|
||||||
|
item = " ".join(item_or_location)
|
||||||
|
item, usable, response = get_intended_text(item)
|
||||||
|
if usable:
|
||||||
|
if item in Items.item_table: # item name
|
||||||
|
hints = collect_hints(self.ctx, team, slot, item)
|
||||||
|
notify_hints(self.ctx, team, hints)
|
||||||
|
else: # location name
|
||||||
|
hints = collect_hints_location(self.ctx, team, slot, item)
|
||||||
|
notify_hints(self.ctx, team, hints)
|
||||||
|
else:
|
||||||
|
self.output(response)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.output(response)
|
||||||
|
|
||||||
|
|
||||||
async def console(ctx: Context):
|
async def console(ctx: Context):
|
||||||
session = prompt_toolkit.PromptSession()
|
session = prompt_toolkit.PromptSession()
|
||||||
running = True
|
cmd_processor = ServerCommandProcessor(ctx)
|
||||||
while running:
|
while ctx.running:
|
||||||
with patch_stdout():
|
with patch_stdout():
|
||||||
input_text = await session.prompt_async()
|
input_text = await session.prompt_async()
|
||||||
try:
|
try:
|
||||||
|
cmd_processor(input_text)
|
||||||
command = input_text.split()
|
|
||||||
if not command:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if command[0] == '/exit':
|
|
||||||
await ctx.server.ws_server._close()
|
|
||||||
running = False
|
|
||||||
|
|
||||||
if command[0] == '/players':
|
|
||||||
logging.info(get_connected_players_string(ctx))
|
|
||||||
if command[0] == '/password':
|
|
||||||
set_password(ctx, command[1] if len(command) > 1 else None)
|
|
||||||
if command[0] == '/kick' and len(command) > 1:
|
|
||||||
team = int(command[2]) - 1 if len(command) > 2 and command[2].isdigit() else None
|
|
||||||
for client in ctx.clients:
|
|
||||||
if client.auth and client.name.lower() == command[1].lower() and (team is None or team == client.team):
|
|
||||||
if client.socket and not client.socket.closed:
|
|
||||||
await client.socket.close()
|
|
||||||
|
|
||||||
if command[0] == '/forfeitslot' and len(command) > 1 and command[1].isdigit():
|
|
||||||
if len(command) > 2 and command[2].isdigit():
|
|
||||||
team = int(command[1]) - 1
|
|
||||||
slot = int(command[2])
|
|
||||||
else:
|
|
||||||
team = 0
|
|
||||||
slot = int(command[1])
|
|
||||||
forfeit_player(ctx, team, slot)
|
|
||||||
if command[0] == '/forfeitplayer' and len(command) > 1:
|
|
||||||
seeked_player = command[1].lower()
|
|
||||||
for (team, slot), name in ctx.player_names.items():
|
|
||||||
if name.lower() == seeked_player:
|
|
||||||
forfeit_player(ctx, team, slot)
|
|
||||||
if command[0] == '/senditem':
|
|
||||||
if len(command) <= 2:
|
|
||||||
logging.info("Use /senditem {Playername} {itemname}\nFor example /senditem Berserker Lamp")
|
|
||||||
else:
|
|
||||||
seeked_player, usable, response = get_intended_text(command[1], ctx.player_names.values())
|
|
||||||
if usable:
|
|
||||||
item = " ".join(command[2:])
|
|
||||||
item, usable, response = get_intended_text(item, Items.item_table.keys())
|
|
||||||
if usable:
|
|
||||||
for client in ctx.clients:
|
|
||||||
if client.name == seeked_player:
|
|
||||||
new_item = ReceivedItem(Items.item_table[item][3], -1, client.slot)
|
|
||||||
get_received_items(ctx, client.team, client.slot).append(new_item)
|
|
||||||
notify_all(ctx, 'Cheat console: sending "' + item + '" to ' + client.name)
|
|
||||||
send_new_items(ctx)
|
|
||||||
else:
|
|
||||||
logging.warning(response)
|
|
||||||
else:
|
|
||||||
logging.warning(response)
|
|
||||||
if command[0] == '/hint':
|
|
||||||
if len(command) <= 2:
|
|
||||||
logging.info("Use /hint {Playername} {itemname/locationname}\nFor example /hint Berserker Lamp")
|
|
||||||
else:
|
|
||||||
seeked_player, usable, response = get_intended_text(command[1], ctx.player_names.values())
|
|
||||||
if usable:
|
|
||||||
for (team, slot), name in ctx.player_names.items():
|
|
||||||
if name == seeked_player:
|
|
||||||
item = " ".join(command[2:])
|
|
||||||
item, usable, response = get_intended_text(item)
|
|
||||||
if usable:
|
|
||||||
if item in Items.item_table: #item name
|
|
||||||
hints = collect_hints(ctx, team, slot, item)
|
|
||||||
notify_hints(ctx, team, hints)
|
|
||||||
else: #location name
|
|
||||||
hints = collect_hints_location(ctx, team, slot, item)
|
|
||||||
notify_hints(ctx, team, hints)
|
|
||||||
else:
|
|
||||||
logging.warning(response)
|
|
||||||
else:
|
|
||||||
logging.warning(response)
|
|
||||||
|
|
||||||
if command[0][0] != '/':
|
|
||||||
notify_all(ctx, '[Server]: ' + input_text)
|
|
||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
@ -702,4 +755,3 @@ async def main(args: argparse.Namespace):
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
loop.run_until_complete(main(parse_args()))
|
loop.run_until_complete(main(parse_args()))
|
||||||
loop.close()
|
|
||||||
|
|
|
@ -268,6 +268,8 @@ def roll_settings(weights):
|
||||||
'timed_countdown': 'timed-countdown',
|
'timed_countdown': 'timed-countdown',
|
||||||
'display': 'display'}[get_choice('timer', weights)] if 'timer' in weights.keys() else False
|
'display': 'display'}[get_choice('timer', weights)] if 'timer' in weights.keys() else False
|
||||||
|
|
||||||
|
ret.dungeon_counters = get_choice('dungeon_counters', weights) if 'dungeon_counters' in weights else 'default'
|
||||||
|
|
||||||
ret.progressive = convert_to_on_off(get_choice('progressive', weights)) if "progressive" in weights else 'on'
|
ret.progressive = convert_to_on_off(get_choice('progressive', weights)) if "progressive" in weights else 'on'
|
||||||
inventoryweights = weights.get('startinventory', {})
|
inventoryweights = weights.get('startinventory', {})
|
||||||
startitems = []
|
startitems = []
|
||||||
|
|
10
Rom.py
10
Rom.py
|
@ -1127,9 +1127,11 @@ def patch_rom(world, rom, player, team, enemized):
|
||||||
rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] else 0x00) # maps showing crystals on overworld
|
rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] else 0x00) # maps showing crystals on overworld
|
||||||
|
|
||||||
# compasses showing dungeon count
|
# compasses showing dungeon count
|
||||||
if world.clock_mode[player]:
|
if world.clock_mode[player] or not world.dungeon_counters[player]:
|
||||||
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location
|
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location
|
||||||
elif world.compassshuffle[player]:
|
elif world.dungeon_counters[player] == True:
|
||||||
|
rom.write_byte(0x18003C, 0x02) # always on
|
||||||
|
elif world.compassshuffle[player] or world.dungeon_counters[player] == 'pickup':
|
||||||
rom.write_byte(0x18003C, 0x01) # show on pickup
|
rom.write_byte(0x18003C, 0x01) # show on pickup
|
||||||
else:
|
else:
|
||||||
rom.write_byte(0x18003C, 0x00)
|
rom.write_byte(0x18003C, 0x00)
|
||||||
|
@ -1144,8 +1146,8 @@ def patch_rom(world, rom, player, team, enemized):
|
||||||
#
|
#
|
||||||
rom.write_byte(0x180045, ((0x01 if world.keyshuffle[player] else 0x00)
|
rom.write_byte(0x180045, ((0x01 if world.keyshuffle[player] else 0x00)
|
||||||
| (0x02 if world.bigkeyshuffle[player] else 0x00)
|
| (0x02 if world.bigkeyshuffle[player] else 0x00)
|
||||||
| (0x04 if world.compassshuffle[player] else 0x00)
|
| (0x04 if world.mapshuffle[player] else 0x00)
|
||||||
| (0x08 if world.mapshuffle[player] else 0x00))) # free roaming items in menu
|
| (0x08 if world.compassshuffle[player] else 0x00))) # free roaming items in menu
|
||||||
|
|
||||||
# Map reveals
|
# Map reveals
|
||||||
reveal_bytes = {
|
reveal_bytes = {
|
||||||
|
|
|
@ -46,6 +46,11 @@ dungeon_items: # alternative to the 4 shuffles above this, does nothing until th
|
||||||
mc: 0 # shuffle Maps and Compass
|
mc: 0 # shuffle Maps and Compass
|
||||||
none: 1 # shuffle none of the 4
|
none: 1 # shuffle none of the 4
|
||||||
mcsb: 0 # shuffle all of the 4, any combination of m, c, s and b will shuffle the respective item, or not if it's missing, so you can add more options here
|
mcsb: 0 # shuffle all of the 4, any combination of m, c, s and b will shuffle the respective item, or not if it's missing, so you can add more options here
|
||||||
|
dungeon_counters:
|
||||||
|
on: 0 # always display amount of items checked in a dungeon
|
||||||
|
pickup: 0 # show when compass is picked up
|
||||||
|
default: 1 # show when compass is picked up if the compass itself is shuffled
|
||||||
|
off: 0 # never show item count in dungeons
|
||||||
accessibility:
|
accessibility:
|
||||||
items: 0 # Guarantees you will be able to acquire all items, but you may not be able to access all locations
|
items: 0 # Guarantees you will be able to acquire all items, but you may not be able to access all locations
|
||||||
locations: 1 # Guarantees you will be able to access all locations, and therefore all items
|
locations: 1 # Guarantees you will be able to access all locations, and therefore all items
|
||||||
|
|
Loading…
Reference in New Issue