From 3e31502fc0e16971ba9b89ae6ca5b5d3dd925566 Mon Sep 17 00:00:00 2001 From: Kevin Cathcart Date: Sat, 18 Nov 2017 20:36:42 -0500 Subject: [PATCH] Add untimed OHKO mode --- BaseClasses.py | 2 +- EntranceRandomizer.py | 4 +++- Gui.py | 2 +- ItemList.py | 8 +++++--- README.md | 20 +++++++++++++------- Rom.py | 42 ++++++++++++++++++++++++------------------ 6 files changed, 47 insertions(+), 31 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 66631f27..9a241504 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -232,7 +232,7 @@ class World(object): goal = ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'].index(self.goal) shuffle = ['vanilla', 'simple', 'restricted', 'full', 'madness', 'insanity', 'dungeonsfull', 'dungeonssimple'].index(self.shuffle) difficulty = ['easy', 'normal', 'hard', 'expert', 'insane'].index(self.difficulty) - timer = ['none', 'display', 'timed', 'timed-ohko', 'timed-countdown'].index(self.timer) + timer = ['none', 'display', 'timed', 'timed-ohko', 'timed-countdown','ohko'].index(self.timer) progressive = ['on', 'off', 'random'].index(self.progressive) algorithm = ['freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26', 'balanced'].index(self.algorithm) beatableonly = 1 if self.check_beatable_only else 0 diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 97b28df3..8ca0e098 100644 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -60,7 +60,7 @@ if __name__ == '__main__': Expert: A harder yet setting with minimum equipment and health. Insane: A setting with the absolute minimum in equipment and no extra health. ''') - parser.add_argument('--timer', default='none', const='normal', nargs='?', choices=['none', 'display', 'timed', 'timed-ohko', 'timed-countdown'], + parser.add_argument('--timer', default='none', const='normal', nargs='?', choices=['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'], help='''\ Select game timer setting. Affects available itempool. (default: %(default)s) None: No timer. @@ -74,6 +74,8 @@ if __name__ == '__main__': Timed OHKO: Starts clock at 10 minutes. Green Clocks add 5 minutes (Total: 25). As long as clock is at 0, Link will die in one hit. + OHKO: Like Timed OHKO, but no clock items are present + and the clock is permenantly at zero. Timed Countdown: Starts with clock at 40 minutes. Same clocks as Timed mode. If time runs out, you lose (but can still keep playing). diff --git a/Gui.py b/Gui.py index 788d143c..8c86856b 100644 --- a/Gui.py +++ b/Gui.py @@ -113,7 +113,7 @@ def guiMain(args=None): timerFrame = Frame(drowDownFrame) timerVar = StringVar() timerVar.set('none') - timerOptionMenu = OptionMenu(timerFrame, timerVar, 'none', 'display', 'timed', 'timed-ohko', 'timed-countdown') + 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) diff --git a/ItemList.py b/ItemList.py index e897d10b..693dd87b 100644 --- a/ItemList.py +++ b/ItemList.py @@ -178,7 +178,7 @@ difficulties= { def generate_itempool(world): if (world.difficulty not in ['easy', 'normal', 'hard', 'expert', 'insane'] or world.goal not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'] - or world.mode not in ['open', 'standard', 'swordless'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']): + or world.mode not in ['open', 'standard', 'swordless'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']): raise NotImplementedError('Not supported yet') world.push_item('Ganon', ItemFactory('Triforce'), False) @@ -243,6 +243,8 @@ def get_pool_core(progressive,shuffle,difficulty,timer, goal, mode): if timer == 'display': clock_mode = 'stopwatch' + elif timer == 'ohko': + clock_mode = 'ohko' diff = difficulties[difficulty] pool.extend(diff.baseitems) @@ -292,7 +294,7 @@ def get_pool_core(progressive,shuffle,difficulty,timer, goal, mode): elif timer == 'timed-ohko': pool.extend(diff.timedohko) extraitems -= len(diff.timedohko) - clock_mode = 'ohko' + clock_mode = 'countdown-ohko' if goal == 'triforcehunt': pool.extend(diff.triforcehunt) extraitems -= len(diff.triforcehunt) @@ -316,7 +318,7 @@ def get_pool_core(progressive,shuffle,difficulty,timer, goal, mode): if __name__ == '__main__': for difficulty in ['easy', 'normal', 'hard', 'expert', 'insane']: for goal in ['ganon', 'triforcehunt', 'pedestal']: - for timer in ['none', 'display', 'timed', 'timed-ohko', 'timed-countdown']: + for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']: for mode in ['open', 'standard', 'swordless']: for progressive in ['on','off']: for shuffle in ['full','insane']: diff --git a/README.md b/README.md index 9611d8c4..e29dabbf 100644 --- a/README.md +++ b/README.md @@ -30,13 +30,13 @@ Output a Spoiler File (default: False) --logic [{noglitches,minorglitches}] ``` -Select Enforcement of Item Requirements. +Select Enforcement of Item Requirements. ### No Glitches The game can be completed without knowing how to perform glitches of any kind. -### Minor Glitches +### Minor Glitches May require Fake Flippers, Bunny Revival. (default: noglitches) @@ -54,7 +54,7 @@ Gives lightcone in Hyrule Castle Sewers even without the Lamp. ### Open -This mode starts with the option to start in your house or the sanctuary, you are free to explore. +This mode starts with the option to start in your house or the sanctuary, you are free to explore. Special notes: @@ -84,11 +84,11 @@ Select completion goal. Standard game completion requiring you to collect the 7 crystals, defeat Agahnim 2 and then beat Ganon. -### Pedestal +### Pedestal Places the Triforce at the Master Sword Pedestal. Ganon cannot be damaged. -### All Dungeons +### All Dungeons Ganon cannot be damaged until all dungeons (including Hyrule Castle Tower and Ganons Tower) are cleared. @@ -143,7 +143,7 @@ This setting is a modest step up from Expert. The main difference is that the pl additional health. ``` ---timer [{none,display,timed,timed-ohko,timed-countdown}] +--timer [{none,display,timed,timed-ohko,ohko,timed-countdown}] ``` Select the timer setting. @@ -168,10 +168,16 @@ Displays a countdown timer on screen that, when it hits zero, will put the playe knockout state until more time is added to the clock via some of the Green Clocks that will be added to the itempool. +### OHKO + +The player into a one hit state the entire game. This is the same as Timed-OHKO, +except that the clock starts at zero, and there are no Clock items, so it will +always stay at zero, resulting in a permanent one hit knockout state. + ### Timed-countdown Displays a countdown timer on screen that can be increased with Green Clocks and Blue Clocks or -increased with Red Clocks found in chests that will be added to the itempool. The goal of this mode +decreased with Red Clocks found in chests that will be added to the itempool. The goal of this mode is to finish the game without the timer reaching zero, but the game will continue uninterrupted if the player runs out of time. diff --git a/Rom.py b/Rom.py index c3c3b8ac..e1bf18ce 100644 --- a/Rom.py +++ b/Rom.py @@ -391,33 +391,39 @@ def patch_rom(world, rom, hashtable, beep='normal', sprite=None): # set up clocks for timed modes if world.clock_mode == 'off': rom.write_bytes(0x180190, [0x00, 0x00, 0x00]) # turn off clock mode - rom.write_bytes(0x180200, [0x00, 0x00, 0x00, 0x00]) # red clock adjustment time (in frames, sint32) - rom.write_bytes(0x180204, [0x00, 0x00, 0x00, 0x00]) # blue clock adjustment time (in frames, sint32) - rom.write_bytes(0x180208, [0x00, 0x00, 0x00, 0x00]) # green clock adjustment time (in frames, sint32) - rom.write_bytes(0x18020C, [0x00, 0x00, 0x00, 0x00]) # starting time (in frames, sint32) + rom.write_int32_to_rom(0x180200, 0) # red clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180204, 0) # blue clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180208, 0) # green clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x18020C, 0) # starting time (in frames, sint32) elif world.clock_mode == 'ohko': rom.write_bytes(0x180190, [0x01, 0x02, 0x01]) # ohko timer with resetable timer functionality - rom.write_bytes(0x180200, [0x00, 0x00, 0x00, 0x81]) # red clock adjustment time (in frames, sint32) - rom.write_bytes(0x180204, [0x20, 0x1C, 0x00, 0x00]) # blue clock adjustment time (in frames, sint32) - rom.write_bytes(0x180208, [0x40, 0x38, 0x00, 0x00]) # green clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180200, 0) # red clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180204, 0) # blue clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180208, 0) # green clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x18020C, 0) # starting time (in frames, sint32) + elif world.clock_mode == 'countdown-ohko': + rom.write_bytes(0x180190, [0x01, 0x02, 0x01]) # ohko timer with resetable timer functionality + rom.write_int32_to_rom(0x180200, -100 * 60 * 60 * 60) # red clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) if world.difficulty == 'easy': - rom.write_bytes(0x18020C, [0x40, 0x19, 0x01, 0x00]) # starting time (in frames, sint32) + rom.write_int32_to_rom(0x18020C, 20 * 60 * 60) # starting time (in frames, sint32) elif world.difficulty == 'normal': - rom.write_bytes(0x18020C, [0xA0, 0x8C, 0x00, 0x00]) # starting time (in frames, sint32) + rom.write_int32_to_rom(0x18020C, 10 * 60 * 60) # starting time (in frames, sint32) else: - rom.write_bytes(0x18020C, [0x50, 0x46, 0x00, 0x00]) # starting time (in frames, sint32) + rom.write_int32_to_rom(0x18020C, 5 * 60 * 60) # starting time (in frames, sint32) if world.clock_mode == 'stopwatch': rom.write_bytes(0x180190, [0x02, 0x01, 0x00]) # set stopwatch mode - rom.write_bytes(0x180200, [0xE0, 0xE3, 0xFF, 0xFF]) # red clock adjustment time (in frames, sint32) - rom.write_bytes(0x180204, [0x20, 0x1C, 0x00, 0x00]) # blue clock adjustment time (in frames, sint32) - rom.write_bytes(0x180208, [0x40, 0x38, 0x00, 0x00]) # green clock adjustment time (in frames, sint32) - rom.write_bytes(0x18020C, [0x00, 0x00, 0x00, 0x00]) # starting time (in frames, sint32) + rom.write_int32_to_rom(0x180200, -2 * 60 * 60) # red clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x18020C, 0) # starting time (in frames, sint32) if world.clock_mode == 'countdown': rom.write_bytes(0x180190, [0x01, 0x01, 0x00]) # set countdown, with no reset available - rom.write_bytes(0x180200, [0xE0, 0xE3, 0xFF, 0xFF]) # red clock adjustment time (in frames, sint32) - rom.write_bytes(0x180204, [0x20, 0x1C, 0x00, 0x00]) # blue clock adjustment time (in frames, sint32) - rom.write_bytes(0x180208, [0x40, 0x38, 0x00, 0x00]) # green clock adjustment time (in frames, sint32) - rom.write_bytes(0x18020C, [0x80, 0x32, 0x02, 0x00]) # starting time (in frames, sint32) + rom.write_int32_to_rom(0x180200, -2 * 60 * 60) # red clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180204, 2 * 60 * 60) # blue clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x180208, 4 * 60 * 60) # green clock adjustment time (in frames, sint32) + rom.write_int32_to_rom(0x18020C, 40 * 60 * 60) # starting time (in frames, sint32) # set up goals for treasure hunt rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon == 'Triforce Piece' else [0x0D, 0x28])