diff --git a/BaseClasses.py b/BaseClasses.py index dbed1e52..b47e7e51 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -119,6 +119,10 @@ class World(object): set_player_attr('treasure_hunt_icon', 'Triforce Piece') set_player_attr('treasure_hunt_count', 0) set_player_attr('clock_mode', False) + set_player_attr('countdown_start_time', 10) + set_player_attr('red_clock_time', -2) + set_player_attr('blue_clock_time', 2) + set_player_attr('green_clock_time', 4) set_player_attr('can_take_damage', True) set_player_attr('glitch_boots', True) set_player_attr('progression_balancing', True) diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 7b45c9d0..222c367c 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -129,6 +129,14 @@ def parse_arguments(argv, no_defaults=False): Timed mode. If time runs out, you lose (but can still keep playing). ''') + parser.add_argument('--countdown_start_time', default=defval(10), type=int, + help='''Set amount of time, in minutes, to start with in Timed Countdown and Timed OHKO modes''') + parser.add_argument('--red_clock_time', default=defval(-2), type=int, + help='''Set amount of time, in minutes, to add from picking up red clocks; negative removes time instead''') + parser.add_argument('--blue_clock_time', default=defval(2), type=int, + help='''Set amount of time, in minutes, to add from picking up blue clocks; negative removes time instead''') + parser.add_argument('--green_clock_time', default=defval(4), type=int, + help='''Set amount of time, in minutes, to add from picking up green clocks; negative removes time instead''') 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) @@ -366,6 +374,7 @@ def parse_arguments(argv, no_defaults=False): for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', 'shuffle', 'crystals_ganon', 'crystals_gt', 'open_pyramid', 'timer', + 'countdown_start_time', 'red_clock_time', 'blue_clock_time', 'green_clock_time', 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory', 'local_items', 'retro', 'accessibility', 'hints', 'beemizer', 'shufflebosses', 'enemy_shuffle', 'enemy_health', 'enemy_damage', 'shufflepots', diff --git a/Gui.py b/Gui.py index fba0e930..aa3a6220 100755 --- a/Gui.py +++ b/Gui.py @@ -120,6 +120,56 @@ def guiMain(args=None): balancingCheckbutton.pack(expand=True, anchor=W) patchesCheckbutton.pack(expand=True, anchor=W) + + + timerOptionsFrame = LabelFrame(rightHalfFrame, text="Timer options") + for i in range(3): + timerOptionsFrame.columnconfigure(i, weight=1) + timerOptionsFrame.rowconfigure(i, weight=1) + + timerModeFrame = Frame(timerOptionsFrame) + timerModeFrame.grid(row=0, column=0, columnspan=3, sticky=E, padx=3) + timerVar = StringVar() + timerVar.set('none') + timerModeMenu = OptionMenu(timerModeFrame, timerVar, 'none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown') + timerLabel = Label(timerModeFrame, text='Timer setting') + timerLabel.pack(side=LEFT) + timerModeMenu.pack(side=LEFT) + + timerCountdownFrame = Frame(timerOptionsFrame) + timerCountdownFrame.grid(row=1, column=0, columnspan=3, sticky=E, padx=3) + timerCountdownLabel = Label(timerCountdownFrame, text='Countdown starting time') + timerCountdownLabel.pack(side=LEFT) + timerCountdownVar = IntVar(value=10) + timerCountdownSpinbox = Spinbox(timerCountdownFrame, from_=0, to=480, width=3, textvariable=timerCountdownVar) + timerCountdownSpinbox.pack(side=LEFT) + + timerRedFrame = Frame(timerOptionsFrame) + timerRedFrame.grid(row=2, column=0, sticky=E, padx=3) + timerRedLabel = Label(timerRedFrame, text='Clock adjustments: Red') + timerRedLabel.pack(side=LEFT) + timerRedVar = IntVar(value=-2) + timerRedSpinbox = Spinbox(timerRedFrame, from_=-60, to=60, width=3, textvariable=timerRedVar) + timerRedSpinbox.pack(side=LEFT) + + timerBlueFrame = Frame(timerOptionsFrame) + timerBlueFrame.grid(row=2, column=1, sticky=E, padx=3) + timerBlueLabel = Label(timerBlueFrame, text='Blue') + timerBlueLabel.pack(side=LEFT) + timerBlueVar = IntVar(value=2) + timerBlueSpinbox = Spinbox(timerBlueFrame, from_=-60, to=60, width=3, textvariable=timerBlueVar) + timerBlueSpinbox.pack(side=LEFT) + + timerGreenFrame = Frame(timerOptionsFrame) + timerGreenFrame.grid(row=2, column=2, sticky=E, padx=3) + timerGreenLabel = Label(timerGreenFrame, text='Green') + timerGreenLabel.pack(side=LEFT) + timerGreenVar = IntVar(value=4) + timerGreenSpinbox = Spinbox(timerGreenFrame, from_=-60, to=60, width=3, textvariable=timerGreenVar) + timerGreenSpinbox.pack(side=LEFT) + + + romOptionsFrame = LabelFrame(rightHalfFrame, text="Rom options") romOptionsFrame.columnconfigure(0, weight=1) romOptionsFrame.columnconfigure(1, weight=1) @@ -266,6 +316,7 @@ def guiMain(args=None): romSelectButton.pack(side=LEFT) checkBoxFrame.pack(side=TOP, anchor=W, padx=5, pady=10) + timerOptionsFrame.pack(expand=True, fill=BOTH, padx=3) romOptionsFrame.pack(expand=True, fill=BOTH, padx=3) drowDownFrame = Frame(topFrame) @@ -344,14 +395,6 @@ def guiMain(args=None): itemfunctionLabel = Label(itemfunctionFrame, text='Difficulty: item functionality') itemfunctionLabel.pack(side=LEFT) - timerFrame = Frame(drowDownFrame) - timerVar = StringVar() - timerVar.set('none') - timerOptionMenu = OptionMenu(timerFrame, timerVar, 'none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown') - timerOptionMenu.pack(side=RIGHT) - timerLabel = Label(timerFrame, text='Timer setting') - timerLabel.pack(side=LEFT) - dungeonCounterFrame = Frame(drowDownFrame) dungeonCounterVar = StringVar() dungeonCounterVar.set('auto') @@ -412,7 +455,6 @@ def guiMain(args=None): swordFrame.pack(expand=True, anchor=E) difficultyFrame.pack(expand=True, anchor=E) itemfunctionFrame.pack(expand=True, anchor=E) - timerFrame.pack(expand=True, anchor=E) dungeonCounterFrame.pack(expand=True, anchor=E) progressiveFrame.pack(expand=True, anchor=E) accessibilityFrame.pack(expand=True, anchor=E) @@ -538,6 +580,10 @@ def guiMain(args=None): guiargs.difficulty = difficultyVar.get() guiargs.item_functionality = itemfunctionVar.get() guiargs.timer = timerVar.get() + guiargs.countdown_start_time = timerCountdownVar.get() + guiargs.red_clock_time = timerRedVar.get() + guiargs.blue_clock_time = timerBlueVar.get() + guiargs.green_clock_time = timerGreenVar.get() guiargs.skip_progression_balancing = not balancingVar.get() if guiargs.timer == "none": guiargs.timer = False @@ -1424,6 +1470,10 @@ def guiMain(args=None): difficultyVar.set(args.difficulty) itemfunctionVar.set(args.item_functionality) timerVar.set(args.timer) + timerCountdownVar.set(args.countdown_start_time) + timerRedVar.set(args.red_clock_time) + timerBlueVar.set(args.blue_clock_time) + timerGreenVar.set(args.green_clock_time) progressiveVar.set(args.progressive) accessibilityVar.set(args.accessibility) goalVar.set(args.goal) diff --git a/Main.py b/Main.py index e96b4bbc..1ec3aee7 100644 --- a/Main.py +++ b/Main.py @@ -72,6 +72,10 @@ def main(args, seed=None): world.tile_shuffle = args.tile_shuffle.copy() world.beemizer = args.beemizer.copy() world.timer = args.timer.copy() + world.countdown_start_time = args.countdown_start_time.copy() + world.red_clock_time = args.red_clock_time.copy() + world.blue_clock_time = args.blue_clock_time.copy() + world.green_clock_time = args.green_clock_time.copy() world.shufflepots = args.shufflepots.copy() world.progressive = args.progressive.copy() world.dungeon_counters = args.dungeon_counters.copy() diff --git a/Mystery.py b/Mystery.py index e5045acb..2857521a 100644 --- a/Mystery.py +++ b/Mystery.py @@ -444,6 +444,11 @@ def roll_settings(weights): 'timed_countdown': 'timed-countdown', 'display': 'display'}[get_choice('timer', weights, False)] + ret.countdown_start_time = int(get_choice('countdown_start_time', weights, 10)) + ret.red_clock_time = int(get_choice('red_clock_time', weights, -2)) + ret.blue_clock_time = int(get_choice('blue_clock_time', weights, 2)) + ret.green_clock_time = int(get_choice('green_clock_time', weights, 4)) + ret.dungeon_counters = get_choice('dungeon_counters', weights, 'default') ret.progressive = convert_to_on_off(get_choice('progressive', weights, 'on')) diff --git a/Rom.py b/Rom.py index 7ac7fb78..3cf7c9d0 100644 --- a/Rom.py +++ b/Rom.py @@ -1021,47 +1021,30 @@ def patch_rom(world, rom, player, team, enemized): rom.write_byte(0x180044, 0x01) # hammer activates tablets # set up clocks for timed modes - if world.shuffle[player] == 'vanilla': - ERtimeincrease = 0 - elif world.shuffle[player] in ['dungeonssimple', 'dungeonsfull']: - ERtimeincrease = 10 - else: - ERtimeincrease = 20 - if world.keyshuffle[player] or world.bigkeyshuffle[player] or world.mapshuffle[player]: - ERtimeincrease = ERtimeincrease + 15 - if world.clock_mode[player] == False: - rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode - rom.write_int32(0x180200, 0) # red clock adjustment time (in frames, sint32) - rom.write_int32(0x180204, 0) # blue clock adjustment time (in frames, sint32) - rom.write_int32(0x180208, 0) # green clock adjustment time (in frames, sint32) - rom.write_int32(0x18020C, 0) # starting time (in frames, sint32) - elif world.clock_mode[player] == 'ohko': + if world.clock_mode[player] in ['ohko', 'countdown-ohko']: rom.write_bytes(0x180190, [0x01, 0x02, 0x01]) # ohko timer with resetable timer functionality - rom.write_int32(0x180200, 0) # red clock adjustment time (in frames, sint32) - rom.write_int32(0x180204, 0) # blue clock adjustment time (in frames, sint32) - rom.write_int32(0x180208, 0) # green clock adjustment time (in frames, sint32) - rom.write_int32(0x18020C, 0) # starting time (in frames, sint32) - elif world.clock_mode[player] == 'countdown-ohko': - rom.write_bytes(0x180190, [0x01, 0x02, 0x01]) # ohko timer with resetable timer functionality - rom.write_int32(0x180200, -100 * 60 * 60 * 60) # red clock adjustment time (in frames, sint32) - rom.write_int32(0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) - rom.write_int32(0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) - if world.difficulty_adjustments[player] in ['easy', 'normal']: - rom.write_int32(0x18020C, (10 + ERtimeincrease) * 60 * 60) # starting time (in frames, sint32) - else: - rom.write_int32(0x18020C, int((5 + ERtimeincrease / 2) * 60 * 60)) # starting time (in frames, sint32) - if world.clock_mode[player] == 'stopwatch': + elif world.clock_mode[player] == 'stopwatch': rom.write_bytes(0x180190, [0x02, 0x01, 0x00]) # set stopwatch mode - rom.write_int32(0x180200, -2 * 60 * 60) # red clock adjustment time (in frames, sint32) - rom.write_int32(0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) - rom.write_int32(0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) - rom.write_int32(0x18020C, 0) # starting time (in frames, sint32) - if world.clock_mode[player] == 'countdown': + elif world.clock_mode[player] == 'countdown': rom.write_bytes(0x180190, [0x01, 0x01, 0x00]) # set countdown, with no reset available - rom.write_int32(0x180200, -2 * 60 * 60) # red clock adjustment time (in frames, sint32) - rom.write_int32(0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) - rom.write_int32(0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) - rom.write_int32(0x18020C, (40 + ERtimeincrease) * 60 * 60) # starting time (in frames, sint32) + else: + rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode + + # Set up requested clock settings + if world.clock_mode[player] in ['countdown-ohko', 'stopwatch', 'countdown']: + rom.write_int32(0x180200, world.red_clock_time[player] * 60 * 60) # red clock adjustment time (in frames, sint32) + rom.write_int32(0x180204, world.blue_clock_time[player] * 60 * 60) # blue clock adjustment time (in frames, sint32) + rom.write_int32(0x180208, world.green_clock_time[player] * 60 * 60) # green clock adjustment time (in frames, sint32) + else: + rom.write_int32(0x180200, 0) # red clock adjustment time (in frames, sint32) + rom.write_int32(0x180204, 0) # blue clock adjustment time (in frames, sint32) + rom.write_int32(0x180208, 0) # green clock adjustment time (in frames, sint32) + + # Set up requested start time for countdown modes + if world.clock_mode[player] in ['countdown-ohko', 'countdown']: + rom.write_int32(0x18020C, world.countdown_start_time[player] * 60 * 60) # starting time (in frames, sint32) + else: + rom.write_int32(0x18020C, 0) # starting time (in frames, sint32) # set up goals for treasure hunt rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28]) diff --git a/WebHostLib/static/static/playerSettings.json b/WebHostLib/static/static/playerSettings.json index a84f381d..3c82daef 100644 --- a/WebHostLib/static/static/playerSettings.json +++ b/WebHostLib/static/static/playerSettings.json @@ -1206,6 +1206,110 @@ } } }, + "countdown_start_time": { + "keyString": "countdown_start_time", + "friendlyName": "Countdown Starting Time", + "description": "The amount of time, in minutes, to start with in Timed Countdown and Timed OHKO modes.", + "inputType": "range", + "subOptions": { + "0": { + "keyString": "countdown_start_time.0", + "friendlyName": 0, + "description": "Start with no time on the timer. In Timed OHKO mode, start in OHKO mode.", + "defaultValue": 0 + }, + "10": { + "keyString": "countdown_start_time.10", + "friendlyName": 10, + "description": "Start with 10 minutes on the timer.", + "defaultValue": 50 + }, + "20": { + "keyString": "countdown_start_time.20", + "friendlyName": 20, + "description": "Start with 20 minutes on the timer.", + "defaultValue": 0 + }, + "30": { + "keyString": "countdown_start_time.30", + "friendlyName": 30, + "description": "Start with 30 minutes on the timer.", + "defaultValue": 0 + }, + "60": { + "keyString": "countdown_start_time.60", + "friendlyName": 60, + "description": "Start with an hour on the timer.", + "defaultValue": 0 + } + } + }, + "red_clock_time": { + "keyString": "red_clock_time", + "friendlyName": "Red Clock Time", + "description": "The amount of time, in minutes, to add to or subtract from the timer upon picking up a red clock.", + "inputType": "range", + "subOptions": { + "-2": { + "keyString": "red_clock_time.-2", + "friendlyName": -2, + "description": "Subtract 2 minutes from the timer upon picking up a red clock.", + "defaultValue": 0 + }, + "1": { + "keyString": "red_clock_time.1", + "friendlyName": 1, + "description": "Add a minute to the timer upon picking up a red clock.", + "defaultValue": 50 + } + } + }, + "blue_clock_time": { + "keyString": "blue_clock_time", + "friendlyName": "Blue Clock Time", + "description": "The amount of time, in minutes, to add to or subtract from the timer upon picking up a blue clock.", + "inputType": "range", + "subOptions": { + "1": { + "keyString": "blue_clock_time.1", + "friendlyName": 1, + "description": "Add a minute to the timer upon picking up a blue clock.", + "defaultValue": 0 + }, + "2": { + "keyString": "blue_clock_time.2", + "friendlyName": 2, + "description": "Add 2 minutes to the timer upon picking up a blue clock.", + "defaultValue": 50 + } + } + }, + "green_clock_time": { + "keyString": "green_clock_time", + "friendlyName": "Green Clock Time", + "description": "The amount of time, in minutes, to add to or subtract from the timer upon picking up a green clock.", + "inputType": "range", + "subOptions": { + "4": { + "keyString": "green_clock_time.4", + "friendlyName": 4, + "description": "Add 4 minutes to the timer upon picking up a green clock.", + "defaultValue": 50 + }, + "10": { + "keyString": "green_clock_time.10", + "friendlyName": 10, + "description": "Add 10 minutes to the timer upon picking up a green clock.", + "defaultValue": 0 + }, + "15": { + "keyString": "green_clock_time.15", + "friendlyName": 15, + "description": "Add 15 minutes to the timer upon picking up a green clock.", + "defaultValue": 0 + } + } + }, "glitch_boots": { "keyString": "glitch_boots", "friendlyName": "Glitch Boots", diff --git a/WebHostLib/static/static/playerSettings.yaml b/WebHostLib/static/static/playerSettings.yaml index ddd21714..758b30aa 100644 --- a/WebHostLib/static/static/playerSettings.yaml +++ b/WebHostLib/static/static/playerSettings.yaml @@ -232,6 +232,22 @@ timer: ohko: 0 # Timer always at zero. Permanent OHKO. timed_countdown: 0 # Starts the clock with forty minutes. Same clocks as timed mode, but if the clock hits zero you lose. You can still keep playing, though. display: 0 # Displays a timer, but otherwise does not affect gameplay or the item pool. +countdown_start_time: # For timed_ohko and timed_countdown timer modes, the amount of time in minutes to start with + 0: 0 # For timed_ohko, starts in OHKO mode when starting the game + 10: 50 + 20: 0 + 30: 0 + 60: 0 +red_clock_time: # For all timer modes, the amount of time in minutes to gain or lose when picking up a red clock + -2: 50 + 1: 0 +blue_clock_time: # For all timer modes, the amount of time in minutes to gain or lose when picking up a blue clock + 1: 0 + 2: 50 +green_clock_time: # For all timer modes, the amount of time in minutes to gain or lose when picking up a green clock + 4: 50 + 10: 0 + 15: 0 # Can be uncommented to use it # local_items: # Force certain items to appear in your world only, not across the multiworld. Recognizes some group names, like "Swords" # - "Moon Pearl" diff --git a/playerSettings.yaml b/playerSettings.yaml index 04aed0b0..83df46e2 100644 --- a/playerSettings.yaml +++ b/playerSettings.yaml @@ -232,6 +232,22 @@ timer: ohko: 0 # Timer always at zero. Permanent OHKO. timed_countdown: 0 # Starts the clock with forty minutes. Same clocks as timed mode, but if the clock hits zero you lose. You can still keep playing, though. display: 0 # Displays a timer, but otherwise does not affect gameplay or the item pool. +countdown_start_time: # For timed_ohko and timed_countdown timer modes, the amount of time in minutes to start with + 0: 0 # For timed_ohko, starts in OHKO mode when starting the game + 10: 50 + 20: 0 + 30: 0 + 60: 0 +red_clock_time: # For all timer modes, the amount of time in minutes to gain or lose when picking up a red clock + -2: 50 + 1: 0 +blue_clock_time: # For all timer modes, the amount of time in minutes to gain or lose when picking up a blue clock + 1: 0 + 2: 50 +green_clock_time: # For all timer modes, the amount of time in minutes to gain or lose when picking up a green clock + 4: 50 + 10: 0 + 15: 0 # Can be uncommented to use it # local_items: # Force certain items to appear in your world only, not across the multiworld. Recognizes some group names, like "Swords" # - "Moon Pearl"