diff --git a/worlds/kh1/Client.py b/worlds/kh1/Client.py index e333ae6829d3..8417f0c7046e 100644 --- a/worlds/kh1/Client.py +++ b/worlds/kh1/Client.py @@ -99,26 +99,40 @@ def on_package(self, cmd: str, args: dict): f.close() #Handle Slot Data - if "EXP Multiplier" in list(args['slot_data'].keys()): - xp_mult = args['slot_data']["EXP Multiplier"] - else: - xp_mult = 1.0 - with open(os.path.join(self.game_communication_path, "xpmult.cfg"), 'w') as f: - f.write(str(xp_mult)) - f.close() - if "Required Reports" in list(args['slot_data'].keys()): + ####if "EXP Multiplier" in list(args['slot_data'].keys()): + #### xp_mult = args['slot_data']["EXP Multiplier"] + ####else: + #### xp_mult = 1.0 + ####with open(os.path.join(self.game_communication_path, "xpmult.cfg"), 'w') as f: + #### f.write(str(xp_mult)) + #### f.close() + #### + ####if "Required Reports" in list(args['slot_data'].keys()): + #### reports_required = args['slot_data']["Required Reports"] + ####else: + #### reports_required = 4 + ####with open(os.path.join(self.game_communication_path, "required_reports.cfg"), 'w') as f: + #### f.write(str(reports_required)) + #### f.close() + ####if "Keyblade Stats" in list(args['slot_data'].keys()): + #### keyblade_stats = args['slot_data']["Keyblade Stats"] + #### with open(os.path.join(self.game_communication_path, "keyblade_stats.cfg"), 'w') as f: + #### f.write(str(keyblade_stats)) + #### f.close() + for key in list(args['slot_data'].keys()): + with open(os.path.join(self.game_communication_path, key + ".cfg"), 'w') as f: + f.write(str(args['slot_data'][key])) + f.close() + + ###Support Legacy Games + if "Required Reports" in list(args['slot_data'].keys()) and "required_reports_eotw" not in list(args['slot_data'].keys()): reports_required = args['slot_data']["Required Reports"] - else: - reports_required = 4 - with open(os.path.join(self.game_communication_path, "required_reports.cfg"), 'w') as f: - f.write(str(reports_required)) - f.close() - if "Keyblade Stats" in list(args['slot_data'].keys()): - keyblade_stats = args['slot_data']["Keyblade Stats"] - with open(os.path.join(self.game_communication_path, "keyblade_stats.cfg"), 'w') as f: - f.write(str(keyblade_stats)) + with open(os.path.join(self.game_communication_path, "required_reports.cfg"), 'w') as f: + f.write(str(reports_required)) f.close() + ###End Support Legacy Games + #End Handle Slot Data if cmd in {"ReceivedItems"}: diff --git a/worlds/kh1/Items.py b/worlds/kh1/Items.py index fa93045c9960..eca62ed53006 100644 --- a/worlds/kh1/Items.py +++ b/worlds/kh1/Items.py @@ -509,7 +509,7 @@ def get_items_by_category(category: str, disclude: list) -> Dict[str, KH1ItemDat "Atlantica": KH1ItemData("Worlds", code = 264_7007, classification = ItemClassification.progression, max_quantity = 1, weight = 10), "Neverland": KH1ItemData("Worlds", code = 264_7008, classification = ItemClassification.progression, max_quantity = 1, weight = 10), "Hollow Bastion": KH1ItemData("Worlds", code = 264_7009, classification = ItemClassification.progression, max_quantity = 1, weight = 10), - #"End of the World": KH1ItemData("Worlds", code = 264_7010, classification = ItemClassification.progression, max_quantity = 1, weight = 10), + "End of the World": KH1ItemData("Worlds", code = 264_7010, classification = ItemClassification.progression, max_quantity = 1, weight = 10), "Monstro": KH1ItemData("Worlds", code = 264_7011, classification = ItemClassification.progression, max_quantity = 1, weight = 10), "Blue Trinity": KH1ItemData("Trinities", code = 264_8001, classification = ItemClassification.progression, max_quantity = 1, weight = 10), "Red Trinity": KH1ItemData("Trinities", code = 264_8002, classification = ItemClassification.progression, max_quantity = 1, weight = 10), diff --git a/worlds/kh1/Options.py b/worlds/kh1/Options.py index 629d7b2fda2a..4f069c5daa00 100644 --- a/worlds/kh1/Options.py +++ b/worlds/kh1/Options.py @@ -100,22 +100,25 @@ class HundredAcreWood(Toggle): class SuperBosses(Toggle): """ - Toggle whether to include checks behind Super Bosses. This is ignored if Super Boss Hunt is your goal. + Toggle whether to include checks behind Super Bosses. """ display_name = "Super Bosses" +class Cups(Toggle): + """ + Toggle whether to include checks behind completing Phil, Pegasus, Hercules, or Hades cups. Please note that the items will still appear in the multiworld, as they are required to challenge Sephiroth. + """ + display_name = "Cups" + class Goal(Choice): """ - Determines the goal of your playthrough. - Depending on your setting for Require Final Ansem, this will either yield Victory or required Ansem Reports to enter End of the World. - Note: If requiring Final Ansem, with more than 1 Ansem Report in the pool (or more than 5 if you are using the Super Boss Hunt goal), the goal(s) will not be required, but will remain a way to get a report. + Determines when victory is achieved in your playthrough. Sephiroth: Defeat Sephiroth. Unknown: Defeat Unknown. Postcards: Turn in all 10 postcards in Traverse Town Final Ansem: Enter End of the World and defeat Ansem as normal Puppies: Rescue and return all 99 puppies in Traverse Town. - Super Boss Hunt: Ansem Reports are set to appear as rewards for defeating Phantom, Kurt Zisa, Sephiroth, Ice Titan, and Unknown. Forces require Final Ansem on. """ display_name = "Goal" option_sephiroth = 0 @@ -123,14 +126,28 @@ class Goal(Choice): option_postcards = 2 option_final_ansem = 3 option_puppies = 4 - option_super_boss_hunt = 5 default = 3 -class RequireFinalAnsem(Toggle): - """ - Determines whether the Victory item is behind your goal or if your goal will provide an Ansem's Report to enter End of the World and defeat Ansem. - """ - display_name = "Require Final Ansem" +class EndoftheWorldUnlock(Choice): + """Determines how End of the World is Unlocked""" + display_name = "End of the World Unlock" + option_item = 0 + option_reports = 1 + default = 1 + +class FinalRestDoor(Choice): + """Determines what conditions need to be met to manifest the door in Final Rest, allowing the player to challenge Ansem + + Reports: A certain number of Ansem's Reports are required. That number is defined in another setting. + Puppies: Having all 99 puppies is required. + Postcards: Turning in all 10 postcards is required. + Superbosses: Defeating Sephiroth, Unknown, Kurt Zisa, and Phantom are required. + """ + display_name = "Final Rest Door" + option_reports = 0 + option_puppies = 1 + option_postcards = 2 + option_superbosses = 3 class Puppies(Choice): """ @@ -143,7 +160,7 @@ class Puppies(Choice): option_full = 0 option_triplets = 1 option_individual = 2 - default = 0 + default = 1 class EXPMultiplier(NamedRange): """ @@ -152,7 +169,7 @@ class EXPMultiplier(NamedRange): display_name = "EXP Multiplier" default = 16 range_start = default / 4 - range_end = 160 + range_end = 128 special_range_names = { "0.25x": default / 4, "0.5x": default / 2, @@ -161,17 +178,25 @@ class EXPMultiplier(NamedRange): "3x": default * 3, "4x": default * 4, "8x": default * 8, - "10x": default * 10, } -class RequiredReports(Range): +class RequiredReportsEotW(Range): """ - Determines the number of Ansem's Reports needed to open End of the World + If End of the World Unlock is set to "Reports", determines the number of Ansem's Reports required to open End of the World. """ display_name = "Reports to Open End of the World" default = 4 range_start = 1 range_end = 13 + +class RequiredReportsDoor(Range): + """ + If Final Rest Door is set to "Reports", determines the number of Ansem's Reports required to manifest the door in Final Rest to challenge Ansem. + """ + display_name = "Reports to Open Final Rest Door" + default = 4 + range_start = 1 + range_end = 13 class ReportsInPool(Range): """ @@ -257,12 +282,15 @@ class BadStartingWeapons(Toggle): @dataclass class KH1Options(PerGameCommonOptions): goal: Goal - require_final_ansem: RequireFinalAnsem - required_reports: RequiredReports + end_of_the_world_unlock: EndoftheWorldUnlock + final_rest_door: FinalRestDoor + required_reports_eotw: RequiredReportsEotW + required_reports_door: RequiredReportsDoor reports_in_pool: ReportsInPool super_bosses: SuperBosses atlantica: Atlantica hundred_acre_wood: HundredAcreWood + cups: Cups puppies: Puppies exp_multiplier: EXPMultiplier randomize_keyblade_stats: RandomizeKeybladeStats diff --git a/worlds/kh1/Regions.py b/worlds/kh1/Regions.py index 05ea92c0762e..6e01cde647d3 100644 --- a/worlds/kh1/Regions.py +++ b/worlds/kh1/Regions.py @@ -304,7 +304,7 @@ def create_regions(multiworld: MultiWorld, player: int, options): regions["Neverland"].locations.append("Neverland Seal Keyhole Fairy Harp Event") regions["Neverland"].locations.append("Neverland Seal Keyhole Tinker Bell Event") regions["Neverland"].locations.append("Neverland Seal Keyhole Glide Event") - if options.super_bosses or options.goal.current_key == "super_boss_hunt": + if options.super_bosses: regions["Neverland"].locations.append("Neverland Defeat Phantom Stop Event") regions["Neverland"].locations.append("Neverland Defeat Captain Hook Ars Arcanum Event") regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Riku I White Trinity Event") @@ -354,39 +354,40 @@ def create_regions(multiworld: MultiWorld, player: int, options): regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Maleficent Ansem's Report 5") #regions["Hollow Bastion"].locations.append("Hollow Bastion Speak with Aerith Ansem's Report 6") regions["Halloween Town"].locations.append("Halloween Town Defeat Oogie Boogie Ansem's Report 7") - regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Hades Ansem's Report 8") + if options.cups: + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Hades Ansem's Report 8") regions["Neverland"].locations.append("Neverland Defeat Hook Ansem's Report 9") #regions["Hollow Bastion"].locations.append("Hollow Bastion Speak with Aerith Ansem's Report 10") - if options.super_bosses or options.goal.current_key == "super_boss_hunt": + if options.super_bosses: regions["Agrabah"].locations.append("Agrabah Defeat Kurt Zisa Ansem's Report 11") - if options.super_bosses or options.goal.current_key == "super_boss_hunt" or options.goal.current_key == "sephiroth": + if options.super_bosses or options.goal.current_key == "sephiroth": regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Sephiroth Ansem's Report 12") - if options.super_bosses or options.goal.current_key == "super_boss_hunt" or options.goal.current_key == "unknown": + if options.super_bosses or options.goal.current_key == "unknown": regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Unknown Ansem's Report 13") for i in range(options.level_checks): regions["Levels"].locations.append("Level " + str(i+1).rjust(3,'0')) - - regions["Olympus Coliseum"].locations.append("Complete Phil Cup") - regions["Olympus Coliseum"].locations.append("Complete Phil Cup Solo") - regions["Olympus Coliseum"].locations.append("Complete Phil Cup Time Trial") - regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup") - regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup Solo") - regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup Time Trial") - regions["Olympus Coliseum"].locations.append("Complete Hercules Cup") - regions["Olympus Coliseum"].locations.append("Complete Hercules Cup Solo") - regions["Olympus Coliseum"].locations.append("Complete Hercules Cup Time Trial") - regions["Olympus Coliseum"].locations.append("Complete Hades Cup") - regions["Olympus Coliseum"].locations.append("Complete Hades Cup Solo") - regions["Olympus Coliseum"].locations.append("Complete Hades Cup Time Trial") - regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Cloud and Leon Event") - regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Yuffie Event") - regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Cerberus Event") - regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Behemoth Event") - regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Hades Event") - regions["Olympus Coliseum"].locations.append("Hercules Cup Defeat Cloud Event") - regions["Olympus Coliseum"].locations.append("Hercules Cup Yellow Trinity Event") + if options.cups: + regions["Olympus Coliseum"].locations.append("Complete Phil Cup") + regions["Olympus Coliseum"].locations.append("Complete Phil Cup Solo") + regions["Olympus Coliseum"].locations.append("Complete Phil Cup Time Trial") + regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup") + regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup Solo") + regions["Olympus Coliseum"].locations.append("Complete Pegasus Cup Time Trial") + regions["Olympus Coliseum"].locations.append("Complete Hercules Cup") + regions["Olympus Coliseum"].locations.append("Complete Hercules Cup Solo") + regions["Olympus Coliseum"].locations.append("Complete Hercules Cup Time Trial") + regions["Olympus Coliseum"].locations.append("Complete Hades Cup") + regions["Olympus Coliseum"].locations.append("Complete Hades Cup Solo") + regions["Olympus Coliseum"].locations.append("Complete Hades Cup Time Trial") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Cloud and Leon Event") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Yuffie Event") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Cerberus Event") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Behemoth Event") + regions["Olympus Coliseum"].locations.append("Hades Cup Defeat Hades Event") + regions["Olympus Coliseum"].locations.append("Hercules Cup Defeat Cloud Event") + regions["Olympus Coliseum"].locations.append("Hercules Cup Yellow Trinity Event") #regions["Traverse Town"].locations.append("Traverse Town Magician's Study Turn in Naturespark") #regions["Traverse Town"].locations.append("Traverse Town Magician's Study Turn in Watergleam") @@ -413,11 +414,12 @@ def create_regions(multiworld: MultiWorld, player: int, options): regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 90 Puppies") regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 99 Puppies Reward 1") regions["Traverse Town"].locations.append("Traverse Town Piano Room Return 99 Puppies Reward 2") - if options.super_bosses or options.goal.current_key == "super_boss_hunt" or options.goal.current_key == "sephiroth": + if options.super_bosses or options.goal.current_key == "sephiroth": regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Sephiroth One-Winged Angel Event") - if options.super_bosses or options.goal.current_key == "super_boss_hunt": + if options.cups: regions["Olympus Coliseum"].locations.append("Olympus Coliseum Defeat Ice Titan Diamond Dust Event") - regions["Olympus Coliseum"].locations.append("Olympus Coliseum Gates Purple Jar After Defeating Hades") + if options.cups: + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Gates Purple Jar After Defeating Hades") regions["Halloween Town"].locations.append("Halloween Town Guillotine Square Ring Jack's Doorbell 3 Times") #regions["Neverland"].locations.append("Neverland Clock Tower 01:00 Door") #regions["Neverland"].locations.append("Neverland Clock Tower 02:00 Door") @@ -459,7 +461,8 @@ def create_regions(multiworld: MultiWorld, player: int, options): regions["Deep Jungle"].locations.append("Deep Jungle Camp Save Gorillas") regions["Deep Jungle"].locations.append("Deep Jungle Bamboo Thicket Save Gorillas") regions["Deep Jungle"].locations.append("Deep Jungle Climbing Trees Save Gorillas") - regions["Olympus Coliseum"].locations.append("Olympus Coliseum Olympia Chest") + if options.cups: + regions["Olympus Coliseum"].locations.append("Olympus Coliseum Olympia Chest") regions["Deep Jungle"].locations.append("Deep Jungle Jungle Slider 10 Fruits") regions["Deep Jungle"].locations.append("Deep Jungle Jungle Slider 20 Fruits") regions["Deep Jungle"].locations.append("Deep Jungle Jungle Slider 30 Fruits") @@ -468,9 +471,9 @@ def create_regions(multiworld: MultiWorld, player: int, options): #regions["Traverse Town"].locations.append("Traverse Town 1st District Speak with Cid Event") regions["Wonderland"].locations.append("Wonderland Bizarre Room Read Book") regions["Olympus Coliseum"].locations.append("Olympus Coliseum Coliseum Gates Green Trinity") - if options.super_bosses or options.goal.current_key == "super_boss_hunt": + if options.super_bosses: regions["Agrabah"].locations.append("Agrabah Defeat Kurt Zisa Zantetsuken Event") - if options.super_bosses or options.goal.current_key == "super_boss_hunt" or options.goal.current_key == "unknown": + if options.super_bosses or options.goal.current_key == "unknown": regions["Hollow Bastion"].locations.append("Hollow Bastion Defeat Unknown EXP Necklace Event") regions["Traverse Town"].locations.append("Traverse Town Synth Log") @@ -481,7 +484,7 @@ def create_regions(multiworld: MultiWorld, player: int, options): regions["Traverse Town"].locations.append("Traverse Town Synth Mushroom") - if options.goal.current_key == "final_ansem" or options.require_final_ansem or options.goal.current_key == "super_boss_hunt": + if options.goal.current_key == "final_ansem": regions["End of the World"].locations.append("Final Ansem") # Set up the regions correctly. diff --git a/worlds/kh1/Rules.py b/worlds/kh1/Rules.py index b346bdd013d8..aa87ed86f777 100644 --- a/worlds/kh1/Rules.py +++ b/worlds/kh1/Rules.py @@ -75,10 +75,20 @@ def has_all_magic_lvx(state: CollectionState, player: int, level) -> bool: def has_offensive_magic(state: CollectionState, player: int) -> bool: return state.has_any({"Progressive Fire", "Progressive Blizzard", "Progressive Thunder", "Progressive Gravity", "Progressive Stop"}, player) -def has_reports(state: CollectionState, player: int, required_reports: int) -> bool: - return state.has_group("Reports", player, required_reports) +def has_reports(state: CollectionState, player: int, eotw_required_reports: int) -> bool: + return state.has_group("Reports", player, eotw_required_reports) -def set_rules(multiworld: MultiWorld, player: int, options, required_reports): +def has_final_rest_door(state: CollectionState, player:int, final_rest_door_requirement: str, final_rest_door_required_reports: int): + if final_rest_door_requirement == "reports": + return state.has_group("Reports", player, final_rest_door_required_reports) + if final_rest_door_requirement == "puppies": + return has_puppies(state, player, 99) + if final_rest_door_requirement == "postcards": + return has_postcards(state, player, 10) + if final_rest_door_requirement == "superbosses": + return state.has_all({"Olympus Coliseum", "Neverland", "Agrabah", "Hollow Bastion", "Green Trinity", "Phil Cup", "Pegasus Cup", "Hercules Cup"}, player) and has_emblems(state, player) + +def set_rules(multiworld: MultiWorld, player: int, options, eotw_required_reports: int, final_rest_door_required_reports: int, final_rest_door_requirement: str): #Location rules. #Keys #multiworld.get_location("Destiny Islands Chest" , player).access_rule = lambda state: has_item(state, player, "") @@ -351,7 +361,7 @@ def set_rules(multiworld: MultiWorld, player: int, options, required_reports): multiworld.get_location("Neverland Seal Keyhole Fairy Harp Event" , player).access_rule = lambda state: has_item(state, player, "Green Trinity") multiworld.get_location("Neverland Seal Keyhole Tinker Bell Event" , player).access_rule = lambda state: has_item(state, player, "Green Trinity") multiworld.get_location("Neverland Seal Keyhole Glide Event" , player).access_rule = lambda state: has_item(state, player, "Green Trinity") - if options.super_bosses or options.goal.current_key == "super_boss_hunt": + if options.super_bosses: multiworld.get_location("Neverland Defeat Phantom Stop Event" , player).access_rule = lambda state: has_item(state, player, "Green Trinity") and has_all_magic_lvx(state, player, 2) multiworld.get_location("Neverland Defeat Captain Hook Ars Arcanum Event" , player).access_rule = lambda state: has_item(state, player, "Green Trinity") #multiworld.get_location("Hollow Bastion Defeat Riku I White Trinity Event" , player).access_rule = lambda state: has_item(state, player, "") @@ -401,36 +411,38 @@ def set_rules(multiworld: MultiWorld, player: int, options, required_reports): multiworld.get_location("Hollow Bastion Defeat Maleficent Ansem's Report 5" , player).access_rule = lambda state: has_emblems(state, player) #multiworld.get_location("Hollow Bastion Speak with Aerith Ansem's Report 6" , player).access_rule = lambda state: has_emblems(state, player) multiworld.get_location("Halloween Town Defeat Oogie Boogie Ansem's Report 7" , player).access_rule = lambda state: has_item(state, player, "Jack-In-The-Box") and has_item(state, player, "Progressive Fire") - multiworld.get_location("Olympus Coliseum Defeat Hades Ansem's Report 8" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + if options.cups: + multiworld.get_location("Olympus Coliseum Defeat Hades Ansem's Report 8" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) multiworld.get_location("Neverland Defeat Hook Ansem's Report 9" , player).access_rule = lambda state: has_item(state, player, "Green Trinity") #multiworld.get_location("Hollow Bastion Speak with Aerith Ansem's Report 10" , player).access_rule = lambda state: has_emblems(state, player) - if options.super_bosses or options.goal.current_key == "super_boss_hunt": + if options.super_bosses: multiworld.get_location("Agrabah Defeat Kurt Zisa Ansem's Report 11" , player).access_rule = lambda state: has_emblems(state, player) and has_x_worlds(state, player, 7) - if options.super_bosses or options.goal.current_key == "super_boss_hunt" or options.goal.current_key == "sephiroth": + if options.super_bosses or options.goal.current_key == "sephiroth": multiworld.get_location("Olympus Coliseum Defeat Sephiroth Ansem's Report 12" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - if options.super_bosses or options.goal.current_key == "super_boss_hunt" or options.goal.current_key == "unknown": + if options.super_bosses or options.goal.current_key == "unknown": multiworld.get_location("Hollow Bastion Defeat Unknown Ansem's Report 13" , player).access_rule = lambda state: has_emblems(state, player) and has_x_worlds(state, player, 7) - multiworld.get_location("Complete Phil Cup" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") - multiworld.get_location("Complete Phil Cup Solo" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") - multiworld.get_location("Complete Phil Cup Time Trial" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") - multiworld.get_location("Complete Pegasus Cup" , player).access_rule = lambda state: has_item(state, player, "Pegasus Cup") - multiworld.get_location("Complete Pegasus Cup Solo" , player).access_rule = lambda state: has_item(state, player, "Pegasus Cup") - multiworld.get_location("Complete Pegasus Cup Time Trial" , player).access_rule = lambda state: has_item(state, player, "Pegasus Cup") - multiworld.get_location("Complete Hercules Cup" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") - multiworld.get_location("Complete Hercules Cup Solo" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") - multiworld.get_location("Complete Hercules Cup Time Trial" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") - multiworld.get_location("Complete Hades Cup" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - multiworld.get_location("Complete Hades Cup Solo" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - multiworld.get_location("Complete Hades Cup Time Trial" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - multiworld.get_location("Hades Cup Defeat Cloud and Leon Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - multiworld.get_location("Hades Cup Defeat Yuffie Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - multiworld.get_location("Hades Cup Defeat Cerberus Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - multiworld.get_location("Hades Cup Defeat Behemoth Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - multiworld.get_location("Hades Cup Defeat Hades Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - multiworld.get_location("Hercules Cup Defeat Cloud Event" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") - multiworld.get_location("Hercules Cup Yellow Trinity Event" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") - + if options.cups: + multiworld.get_location("Complete Phil Cup" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") + multiworld.get_location("Complete Phil Cup Solo" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") + multiworld.get_location("Complete Phil Cup Time Trial" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") + multiworld.get_location("Complete Pegasus Cup" , player).access_rule = lambda state: has_item(state, player, "Pegasus Cup") + multiworld.get_location("Complete Pegasus Cup Solo" , player).access_rule = lambda state: has_item(state, player, "Pegasus Cup") + multiworld.get_location("Complete Pegasus Cup Time Trial" , player).access_rule = lambda state: has_item(state, player, "Pegasus Cup") + multiworld.get_location("Complete Hercules Cup" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") + multiworld.get_location("Complete Hercules Cup Solo" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") + multiworld.get_location("Complete Hercules Cup Time Trial" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") + multiworld.get_location("Complete Hades Cup" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Complete Hades Cup Solo" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Complete Hades Cup Time Trial" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Hades Cup Defeat Cloud and Leon Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Hades Cup Defeat Yuffie Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Hades Cup Defeat Cerberus Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Hades Cup Defeat Behemoth Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Hades Cup Defeat Hades Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Hercules Cup Defeat Cloud Event" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") + multiworld.get_location("Hercules Cup Yellow Trinity Event" , player).access_rule = lambda state: has_item(state, player, "Hercules Cup") + #multiworld.get_location("Traverse Town Magician's Study Turn in Naturespark" , player).access_rule = lambda state: has_item(state, player, "Naturespark") and has_item(state, player, "Progressive Fire") #multiworld.get_location("Traverse Town Magician's Study Turn in Watergleam" , player).access_rule = lambda state: has_item(state, player, "Watergleam") and has_item(state, player, "Progressive Fire") #multiworld.get_location("Traverse Town Magician's Study Turn in Fireglow" , player).access_rule = lambda state: has_item(state, player, "Fireglow") and has_item(state, player, "Progressive Fire") @@ -456,11 +468,11 @@ def set_rules(multiworld: MultiWorld, player: int, options, required_reports): multiworld.get_location("Traverse Town Piano Room Return 90 Puppies" , player).access_rule = lambda state: has_puppies(state, player, 90) multiworld.get_location("Traverse Town Piano Room Return 99 Puppies Reward 1" , player).access_rule = lambda state: has_puppies(state, player, 99) multiworld.get_location("Traverse Town Piano Room Return 99 Puppies Reward 2" , player).access_rule = lambda state: has_puppies(state, player, 99) - if options.super_bosses or options.goal.current_key == "super_boss_hunt" or options.goal.current_key == "sephiroth": + if options.super_bosses or options.goal.current_key == "sephiroth": multiworld.get_location("Olympus Coliseum Defeat Sephiroth One-Winged Angel Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) - if options.super_bosses or options.goal.current_key == "super_boss_hunt": + if options.cups: multiworld.get_location("Olympus Coliseum Defeat Ice Titan Diamond Dust Event" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) and has_item(state, player, "Guard") - multiworld.get_location("Olympus Coliseum Gates Purple Jar After Defeating Hades" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + multiworld.get_location("Olympus Coliseum Gates Purple Jar After Defeating Hades" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) #multiworld.get_location("Halloween Town Guillotine Square Ring Jack's Doorbell 3 Times" , player).access_rule = lambda state: has_item(state, player, "") #multiworld.get_location("Neverland Clock Tower 01:00 Door" , player).access_rule = lambda state: has_item(state, player, "Green Trinity") #multiworld.get_location("Neverland Clock Tower 02:00 Door" , player).access_rule = lambda state: has_item(state, player, "Green Trinity") @@ -502,7 +514,8 @@ def set_rules(multiworld: MultiWorld, player: int, options, required_reports): multiworld.get_location("Deep Jungle Camp Save Gorillas" , player).access_rule = lambda state: has_slides(state, player) multiworld.get_location("Deep Jungle Bamboo Thicket Save Gorillas" , player).access_rule = lambda state: has_slides(state, player) multiworld.get_location("Deep Jungle Climbing Trees Save Gorillas" , player).access_rule = lambda state: has_slides(state, player) - multiworld.get_location("Olympus Coliseum Olympia Chest" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) + if options.cups: + multiworld.get_location("Olympus Coliseum Olympia Chest" , player).access_rule = lambda state: has_item(state, player, "Phil Cup") and has_item(state, player, "Pegasus Cup") and has_item(state, player, "Hercules Cup") and has_x_worlds(state, player, 7) multiworld.get_location("Deep Jungle Jungle Slider 10 Fruits" , player).access_rule = lambda state: has_item(state, player, "Slide 1") multiworld.get_location("Deep Jungle Jungle Slider 20 Fruits" , player).access_rule = lambda state: has_item(state, player, "Slide 1") multiworld.get_location("Deep Jungle Jungle Slider 30 Fruits" , player).access_rule = lambda state: has_item(state, player, "Slide 1") @@ -523,9 +536,8 @@ def set_rules(multiworld: MultiWorld, player: int, options, required_reports): multiworld.get_location("Traverse Town Synth Fish" , player).access_rule = lambda state: has_at_least(state, player, "Empty Bottle", 6) and has_item(state, player, "Green Trinity") multiworld.get_location("Traverse Town Synth Mushroom" , player).access_rule = lambda state: has_at_least(state, player, "Empty Bottle", 6) and has_item(state, player, "Green Trinity") - - #multiworld.get_location("Final Ansem" , player).access_rule = lambda state: has_item(state, player, "") - + if options.goal.current_key == "final_ansem": + multiworld.get_location("Final Ansem" , player).access_rule = lambda state: has_final_rest_door(state, player, final_rest_door_requirement, final_rest_door_required_reports) for i in range(options.level_checks): multiworld.get_location("Level " + str(i+1).rjust(3,'0') , player).access_rule = lambda state, level_num=i: has_x_worlds(state, player, min(((level_num//10)*2), 8)) @@ -540,7 +552,7 @@ def set_rules(multiworld: MultiWorld, player: int, options, required_reports): multiworld.get_entrance("Halloween Town" , player).access_rule = lambda state: has_item(state, player,"Halloween Town") and has_x_worlds(state, player, 2) multiworld.get_entrance("Neverland" , player).access_rule = lambda state: has_item(state, player,"Neverland") and has_x_worlds(state, player, 4) multiworld.get_entrance("Hollow Bastion" , player).access_rule = lambda state: has_item(state, player,"Hollow Bastion") and has_x_worlds(state, player, 5) - multiworld.get_entrance("End of the World" , player).access_rule = lambda state: has_x_worlds(state, player, 7) and has_reports(state, player, required_reports) + multiworld.get_entrance("End of the World" , player).access_rule = lambda state: has_x_worlds(state, player, 7) and (has_reports(state, player, eotw_required_reports) or has_item(state, player,"End of the World")) multiworld.get_entrance("100 Acre Wood" , player).access_rule = lambda state: has_item(state, player, "Progressive Fire") # Win condition. diff --git a/worlds/kh1/__init__.py b/worlds/kh1/__init__.py index 0079396ffeb0..3f7c035b8255 100644 --- a/worlds/kh1/__init__.py +++ b/worlds/kh1/__init__.py @@ -50,8 +50,10 @@ class KH1World(World): location_name_groups = location_name_groups def create_items(self): - if self.options.reports_in_pool < self.options.required_reports: - print("LESS REPORTS IN POOL THAN REQUIRED REPORTS, SWAPPING") + + print("Reports in Pool: " + str(self.determine_reports_in_pool())) + print("Reports to Open Final Rest Door: " + str(self.determine_reports_required_to_open_final_rest_door())) + print("Reports to Open End of the World: " + str(self.determine_reports_required_to_open_end_of_the_world())) item_pool: List[KH1Item] = [] possible_level_up_item_pool = [] @@ -86,10 +88,6 @@ def create_items(self): self.multiworld.get_location(level_up_locations[i], self.player).place_locked_item(self.create_item(level_up_item_pool.pop())) i = i + 1 total_locations = len(self.multiworld.get_unfilled_locations(self.player)) - 1 - if self.options.goal.current_key == "super_boss_hunt": - total_locations = total_locations - 5 - elif self.options.goal.current_key != "final_ansem" and self.options.require_final_ansem: - total_locations = total_locations - 1 non_filler_item_categories = ["Key", "Magic", "Worlds", "Trinities", "Cups", "Summons", "Abilities", "Shared Abilities", "Keyblades", "Accessory", "Weapons", "Puppies"] if self.options.hundred_acre_wood: non_filler_item_categories.append("Torn Pages") @@ -109,16 +107,14 @@ def create_items(self): elif name == "Atlantica" or name == "Mermaid Kick": if self.options.atlantica: item_pool += [self.create_item(name) for _ in range(0, quantity)] + elif name == "End of the World": + if self.options.end_of_the_world_unlock.current_key == "item": + item_pool += [self.create_item(name) for _ in range(0, quantity)] else: item_pool += [self.create_item(name) for _ in range(0, quantity)] - reports_in_pool = max(int(self.options.required_reports), int(self.options.reports_in_pool)) - if self.options.goal.current_key == "super_boss_hunt": - i = 5 - elif self.options.require_final_ansem and self.options.goal.current_key != "final_ansem": - i = 1 - else: - i = 0 + i = 0 + reports_in_pool = self.determine_reports_in_pool() while i < reports_in_pool: item_pool += [self.create_item("Ansem's Report " + str(i+1))] i = i + 1 @@ -149,27 +145,13 @@ def create_items(self): def pre_fill(self) -> None: goal_dict = { - "sephiroth": ["Olympus Coliseum Defeat Sephiroth Ansem's Report 12"], - "unknown": ["Hollow Bastion Defeat Unknown Ansem's Report 13"], - "postcards": ["Traverse Town Mail Postcard 10 Event"], - "final_ansem": ["Final Ansem"], - "puppies": ["Traverse Town Piano Room Return 99 Puppies Reward 2"], - "super_boss_hunt": ["Olympus Coliseum Defeat Sephiroth Ansem's Report 12" - , "Hollow Bastion Defeat Unknown Ansem's Report 13" - , "Agrabah Defeat Kurt Zisa Ansem's Report 11" - , "Neverland Defeat Phantom Stop Event" - , "Olympus Coliseum Defeat Ice Titan Diamond Dust Event"], + "sephiroth": "Olympus Coliseum Defeat Sephiroth Ansem's Report 12", + "unknown": "Hollow Bastion Defeat Unknown Ansem's Report 13", + "postcards": "Traverse Town Mail Postcard 10 Event", + "final_ansem": "Final Ansem", + "puppies": "Traverse Town Piano Room Return 99 Puppies Reward 2" } - if (self.options.require_final_ansem or self.options.goal.current_key == "super_boss_hunt") and self.options.goal.current_key != "final_ansem": - self.multiworld.get_location("Final Ansem", self.player).place_locked_item(self.create_item("Victory")) - report_no = 1 - for location_name in goal_dict[self.options.goal.current_key]: - self.multiworld.get_location(location_name, self.player).place_locked_item(self.create_item("Ansem's Report " + str(report_no))) - report_no = report_no + 1 - elif self.options.goal.current_key == "final_ansem": - self.multiworld.get_location("Final Ansem", self.player).place_locked_item(self.create_item("Victory")) - else: - self.multiworld.get_location(goal_dict[self.options.goal.current_key][0], self.player).place_locked_item(self.create_item("Victory")) + self.multiworld.get_location(goal_dict[self.options.goal.current_key], self.player).place_locked_item(self.create_item("Victory")) def get_filler_item_name(self) -> str: fillers = {} @@ -181,22 +163,21 @@ def get_filler_item_name(self) -> str: return self.random.choices([filler for filler in fillers.keys()], weights, k=1)[0] def fill_slot_data(self) -> dict: - if self.options.goal.current_key == "super_boss_hunt": - reports_in_pool = max(self.options.reports_in_pool, 5) - else: - reports_in_pool = self.options.reports_in_pool - required_reports = min(int(self.options.required_reports.value), reports_in_pool) - slot_data = {"EXP Multiplier": int(self.options.exp_multiplier)/16 - ,"Required Reports": int(required_reports)} + required_reports_eotw = self.determine_reports_required_to_open_end_of_the_world() + required_reports_door = self.determine_reports_required_to_open_final_rest_door() + slot_data = {"xpmult": int(self.options.exp_multiplier)/16 + ,"required_reports_eotw": int(required_reports_eotw) + ,"required_reports_door": int(required_reports_door) + ,"door": self.options.final_rest_door.current_key} if self.options.randomize_keyblade_stats: min_str_bonus = min(self.options.keyblade_min_str, self.options.keyblade_max_str) max_str_bonus = max(self.options.keyblade_min_str, self.options.keyblade_max_str) min_mp_bonus = min(self.options.keyblade_min_mp, self.options.keyblade_max_mp) max_mp_bonus = max(self.options.keyblade_min_mp, self.options.keyblade_max_mp) - slot_data["Keyblade Stats"] = "" + slot_data["keyblade_stats"] = "" for i in range(22): if i < 4 and self.options.bad_starting_weapons: - slot_data["Keyblade Stats"] = slot_data["Keyblade Stats"] + "1,0," + slot_data["keyblade_stats"] = slot_data["keyblade_stats"] + "1,0," else: if min_str_bonus != max_str_bonus: str_bonus = int(self.random.randrange(min_str_bonus,max_str_bonus)) @@ -206,8 +187,8 @@ def fill_slot_data(self) -> dict: mp_bonus = int(self.random.randrange(min_mp_bonus,max_mp_bonus)) else: mp_bonus = int(min_mp_bonus) - slot_data["Keyblade Stats"] = slot_data["Keyblade Stats"] + str(str_bonus) + "," + str(mp_bonus) + "," - slot_data["Keyblade Stats"] = slot_data["Keyblade Stats"][:-1] + slot_data["keyblade_stats"] = slot_data["keyblade_stats"] + str(str_bonus) + "," + str(mp_bonus) + "," + slot_data["keyblade_stats"] = slot_data["keyblade_stats"][:-1] return slot_data def create_item(self, name: str) -> KH1Item: @@ -223,7 +204,41 @@ def set_rules(self): reports_in_pool = max(self.options.reports_in_pool, 5) else: reports_in_pool = self.options.reports_in_pool - set_rules(self.multiworld, self.player, self.options, min(self.options.required_reports, reports_in_pool)) + set_rules(self.multiworld, self.player, self.options, self.determine_reports_required_to_open_end_of_the_world(), self.determine_reports_required_to_open_final_rest_door(), self.options.final_rest_door.current_key) def create_regions(self): - create_regions(self.multiworld, self.player, self.options) \ No newline at end of file + create_regions(self.multiworld, self.player, self.options) + + def get_numbers_of_reports_to_consider(self): + numbers_to_consider = [] + if self.options.end_of_the_world_unlock.current_key == "reports": + numbers_to_consider.append(self.options.required_reports_eotw) + if self.options.final_rest_door.current_key == "reports": + numbers_to_consider.append(self.options.required_reports_door) + if self.options.final_rest_door.current_key == "reports" or self.options.end_of_the_world_unlock.current_key == "reports": + numbers_to_consider.append(self.options.reports_in_pool) + numbers_to_consider.sort() + return numbers_to_consider + + def determine_reports_in_pool(self): + numbers_to_consider = self.get_numbers_of_reports_to_consider() + if len(numbers_to_consider) > 0: + return max(numbers_to_consider) + else: + return 0 + + def determine_reports_required_to_open_end_of_the_world(self): + if self.options.end_of_the_world_unlock.current_key == "reports": + numbers_to_consider = self.get_numbers_of_reports_to_consider() + if len(numbers_to_consider) > 0: + return numbers_to_consider[0] + return 14 + + def determine_reports_required_to_open_final_rest_door(self): + if self.options.final_rest_door.current_key == "reports": + numbers_to_consider = self.get_numbers_of_reports_to_consider() + if len(numbers_to_consider) == 3: + return numbers_to_consider[1] + elif len(numbers_to_consider) == 2: + return numbers_to_consider[0] + return 14 \ No newline at end of file diff --git a/worlds/kh1/test/test_goal.py b/worlds/kh1/test/test_goal.py index 8c1b65e76c73..ce2aaf7fa7a4 100644 --- a/worlds/kh1/test/test_goal.py +++ b/worlds/kh1/test/test_goal.py @@ -26,9 +26,4 @@ class TestFinalAnsem(KH1TestBase): class TestPuppies(KH1TestBase): options = { "Goal": 4, - } - -class TestSuperBossHunt(KH1TestBase): - options = { - "Goal": 5, } \ No newline at end of file