| 
									
										
										
										
											2023-02-23 23:32:15 -08:00
										 |  |  | from enum import IntEnum | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  | from typing import Any, List, Dict, Set, Callable, Optional, TextIO | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  | from BaseClasses import ItemClassification, CollectionState, Region, Entrance, Location, Tutorial, LocationProgressType | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | from worlds.AutoWorld import World, WebWorld | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  | from .Overcooked2Levels import Overcooked2Dlc, Overcooked2Level, Overcooked2GenericLevel | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | from .Locations import Overcooked2Location, oc2_location_name_to_id, oc2_location_id_to_name | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  | from .Options import OC2Options, OC2OnToggle, LocationBalancingMode, DeathLinkMode | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  | from .Items import item_table, Overcooked2Item, item_name_to_id, item_id_to_name, item_to_unlock_event, item_frequencies, dlc_exclusives | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | from .Logic import has_requirements_for_level_star, has_requirements_for_level_access, level_shuffle_factory, is_item_progression, is_useful | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Overcooked2Web(WebWorld): | 
					
						
							|  |  |  |     theme = "partyTime" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bug_report_page = "https://github.com/toasterparty/oc2-modding/issues" | 
					
						
							|  |  |  |     setup_en = Tutorial( | 
					
						
							| 
									
										
										
										
											2024-02-20 11:22:32 -05:00
										 |  |  |         "Multiworld Setup Guide", | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |         "A guide to setting up the Overcooked! 2 randomizer on your computer.", | 
					
						
							|  |  |  |         "English", | 
					
						
							|  |  |  |         "setup_en.md", | 
					
						
							|  |  |  |         "setup/en", | 
					
						
							|  |  |  |         ["toasterparty"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tutorials = [setup_en] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-23 23:32:15 -08:00
										 |  |  | class PrepLevelMode(IntEnum): | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     original = 0 | 
					
						
							|  |  |  |     excluded = 1 | 
					
						
							|  |  |  |     ayce = 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Overcooked2World(World): | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-11-07 10:50:30 -08:00
										 |  |  |     Overcooked! 2 is a frantically paced arcade cooking game where | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     players race against the clock to complete orders for points. Bring | 
					
						
							|  |  |  |     peace to the Onion Kingdom once again by recovering lost items and abilities, | 
					
						
							|  |  |  |     earning stars to unlock levels, and defeating the unbread horde. Levels are | 
					
						
							|  |  |  |     randomized to increase gameplay variety. Play with up to 4 friends. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Autoworld API | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     game = "Overcooked! 2" | 
					
						
							|  |  |  |     web = Overcooked2Web() | 
					
						
							| 
									
										
										
										
											2023-02-17 00:25:56 -08:00
										 |  |  |     required_client_version = (0, 3, 8) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     topology_present: bool = False | 
					
						
							| 
									
										
										
										
											2023-02-17 00:25:56 -08:00
										 |  |  |     data_version = 3 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     item_name_to_id = item_name_to_id | 
					
						
							|  |  |  |     item_id_to_name = item_id_to_name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     location_id_to_name = oc2_location_id_to_name | 
					
						
							|  |  |  |     location_name_to_id = oc2_location_name_to_id | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |     options_dataclass = OC2Options | 
					
						
							|  |  |  |     options: OC2Options | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     itempool: List[Overcooked2Item] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Helper Functions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def is_level_horde(self, level_id: int) -> bool: | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         return self.options.include_horde_levels and \ | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             (self.level_mapping is not None) and \ | 
					
						
							|  |  |  |             level_id in self.level_mapping.keys() and \ | 
					
						
							|  |  |  |             self.level_mapping[level_id].is_horde | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_item(self, item: str, classification: ItemClassification = ItemClassification.progression) -> Overcooked2Item: | 
					
						
							|  |  |  |         return Overcooked2Item(item, classification, self.item_name_to_id[item], self.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_event(self, event: str, classification: ItemClassification) -> Overcooked2Item: | 
					
						
							|  |  |  |         return Overcooked2Item(event, classification, None, self.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def place_event(self, location_name: str, item_name: str, | 
					
						
							|  |  |  |                     classification: ItemClassification = ItemClassification.progression_skip_balancing): | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         location: Location = self.multiworld.get_location(location_name, self.player) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |         location.place_locked_item(self.create_event(item_name, classification)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def add_region(self, region_name: str): | 
					
						
							|  |  |  |         region = Region( | 
					
						
							|  |  |  |             region_name, | 
					
						
							|  |  |  |             self.player, | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |             self.multiworld, | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         self.multiworld.regions.append(region) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def connect_regions(self, source: str, target: str, rule: Optional[Callable[[CollectionState], bool]] = None): | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         sourceRegion = self.multiworld.get_region(source, self.player) | 
					
						
							|  |  |  |         targetRegion = self.multiworld.get_region(target, self.player) | 
					
						
							| 
									
										
										
										
											2024-02-25 14:56:27 -06:00
										 |  |  |         sourceRegion.connect(targetRegion, rule=rule) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def add_level_location( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         region_name: str, | 
					
						
							|  |  |  |         location_name: str, | 
					
						
							|  |  |  |         level_id: int, | 
					
						
							|  |  |  |         stars: int, | 
					
						
							|  |  |  |         is_event: bool = False, | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |         priority=False, | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     ) -> None: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if is_event: | 
					
						
							|  |  |  |             location_id = None | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             location_id = level_id | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         region = self.multiworld.get_region(region_name, self.player) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |         location = Overcooked2Location( | 
					
						
							|  |  |  |             self.player, | 
					
						
							|  |  |  |             location_name, | 
					
						
							|  |  |  |             location_id, | 
					
						
							|  |  |  |             region, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |         if priority: | 
					
						
							|  |  |  |             location.progress_type = LocationProgressType.PRIORITY | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             location.progress_type = LocationProgressType.DEFAULT | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |         # if level_id is none, then it's the 6-6 edge case | 
					
						
							|  |  |  |         if level_id is None: | 
					
						
							|  |  |  |             level_id = 36 | 
					
						
							|  |  |  |         if self.level_mapping is not None and level_id in self.level_mapping: | 
					
						
							|  |  |  |             level = self.level_mapping[level_id] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             level = Overcooked2GenericLevel(level_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         completion_condition: Callable[[CollectionState], bool] = \ | 
					
						
							|  |  |  |             lambda state, level=level, stars=stars: \ | 
					
						
							|  |  |  |             has_requirements_for_level_star(state, level, stars, self.player) | 
					
						
							|  |  |  |         location.access_rule = completion_condition | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         region.locations.append( | 
					
						
							|  |  |  |             location | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |     def get_n_random_locations(self, n: int) -> List[int]: | 
					
						
							|  |  |  |         """Return a list of n random non-repeating level locations""" | 
					
						
							|  |  |  |         levels = list() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if n == 0: | 
					
						
							|  |  |  |             return levels | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for level in Overcooked2Level(): | 
					
						
							|  |  |  |             if level.level_id == 36: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |             elif not self.options.kevin_levels and level.level_id > 36: | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             levels.append(level.level_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.multiworld.random.shuffle(levels) | 
					
						
							|  |  |  |         return levels[:n] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_priority_locations(self) -> List[int]: | 
					
						
							|  |  |  |         """Randomly generate list of priority locations, thus insulating this game
 | 
					
						
							|  |  |  |         from the negative effects of being shuffled with games that contain large | 
					
						
							|  |  |  |         ammounts of filler"""
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.multiworld.players == 1: | 
					
						
							|  |  |  |             # random priority locations have no desirable effect on solo seeds | 
					
						
							|  |  |  |             return list() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-19 18:36:18 -05:00
										 |  |  |         balancing_mode = self.options.location_balancing | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-23 23:32:15 -08:00
										 |  |  |         if balancing_mode == LocationBalancingMode.disabled: | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |             # Location balancing is disabled, progression density is purely determined by filler | 
					
						
							|  |  |  |             return list() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Count how many progression items are required for this overcooked instance | 
					
						
							|  |  |  |         game_item_count = len(self.itempool) | 
					
						
							|  |  |  |         game_progression_count = 0 | 
					
						
							|  |  |  |         for item in self.itempool: | 
					
						
							|  |  |  |             if item.classification == ItemClassification.progression: | 
					
						
							|  |  |  |                 game_progression_count += 1 | 
					
						
							|  |  |  |         game_progression_density = game_progression_count/game_item_count | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-23 23:32:15 -08:00
										 |  |  |         if balancing_mode == LocationBalancingMode.full: | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |             # Location balancing will be employed in an attempt to keep the number of | 
					
						
							|  |  |  |             # progression locations and proression items as close to equal as possible | 
					
						
							|  |  |  |             return self.get_n_random_locations(game_progression_count) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-23 23:32:15 -08:00
										 |  |  |         assert balancing_mode == LocationBalancingMode.compromise | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Count how many progression items are shuffled between all games | 
					
						
							|  |  |  |         total_item_count = len(self.multiworld.itempool) | 
					
						
							|  |  |  |         total_progression_count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for item in self.multiworld.itempool: | 
					
						
							|  |  |  |             if item.classification == ItemClassification.progression: | 
					
						
							|  |  |  |                 total_progression_count += 1 | 
					
						
							|  |  |  |         total_progression_density = total_progression_count/total_item_count | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if total_progression_density >= game_progression_density: | 
					
						
							|  |  |  |             # This game has more filler than the average of all other games. | 
					
						
							|  |  |  |             # It is not in need of location balancing | 
					
						
							|  |  |  |             return list() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Calculate the midpoint between the two ratios | 
					
						
							|  |  |  |         target_progression_ratio = (game_progression_density - total_progression_density) / 2.0 + total_progression_density | 
					
						
							|  |  |  |         target_progression_count = int((target_progression_ratio * game_item_count) + 0.5) # I'm sorry I round like an old person | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Location balancing will be employed in an attempt to find a compromise at | 
					
						
							|  |  |  |         # the half-way point between natural probability and full artifical balancing | 
					
						
							|  |  |  |         return self.get_n_random_locations(target_progression_count) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     # Helper Data | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |     player_name: str | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     level_unlock_counts: Dict[int, int]  # level_id, stars to purchase | 
					
						
							|  |  |  |     level_mapping: Dict[int, Overcooked2GenericLevel]  # level_id, level | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |     enabled_dlc: Set[Overcooked2Dlc] | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Autoworld Hooks | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def generate_early(self): | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |         self.player_name = self.multiworld.player_name[self.player] | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # 0.0 to 1.0 where 1.0 is World Record | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         self.star_threshold_scale = self.options.star_threshold_scale / 100.0 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |         # Parse DLCOptionSet back into enums | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         self.enabled_dlc = {Overcooked2Dlc(x) for x in self.options.include_dlcs.value} | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |         # Generate level unlock requirements such that the levels get harder to unlock | 
					
						
							|  |  |  |         # the further the game has progressed, and levels progress radially rather than linearly | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         self.level_unlock_counts = level_unlock_requirement_factory(self.options.stars_to_win.value) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Assign new kitchens to each spot on the overworld using pure random chance and nothing else | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         if self.options.shuffle_level_order: | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             self.level_mapping = \ | 
					
						
							|  |  |  |                 level_shuffle_factory( | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |                     self.multiworld.random, | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |                     self.options.prep_levels != PrepLevelMode.excluded, | 
					
						
							|  |  |  |                     self.options.include_horde_levels.result, | 
					
						
							|  |  |  |                     self.options.kevin_levels.result, | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |                     self.enabled_dlc, | 
					
						
							|  |  |  |                     self.player_name, | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |                 ) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.level_mapping = None | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |             if Overcooked2Dlc.STORY not in self.enabled_dlc: | 
					
						
							|  |  |  |                 raise Exception(f"Invalid OC2 settings({self.player_name}) Need either Level Shuffle disabled or 'Story' DLC enabled") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.enabled_dlc = {Overcooked2Dlc.STORY} | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |     def set_location_priority(self) -> None: | 
					
						
							| 
									
										
										
										
											2023-04-03 21:53:05 -07:00
										 |  |  |         priority_locations = self.get_priority_locations() | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |         for level in Overcooked2Level(): | 
					
						
							| 
									
										
										
										
											2023-04-03 21:53:05 -07:00
										 |  |  |             if level.level_id in priority_locations: | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |                 location: Location = self.multiworld.get_location(level.location_name_item, self.player) | 
					
						
							|  |  |  |                 location.progress_type = LocationProgressType.PRIORITY | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     def create_regions(self) -> None: | 
					
						
							|  |  |  |         # Menu -> Overworld | 
					
						
							|  |  |  |         self.add_region("Menu") | 
					
						
							|  |  |  |         self.add_region("Overworld") | 
					
						
							|  |  |  |         self.connect_regions("Menu", "Overworld") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |         # Create and populate "regions" (a.k.a. levels) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |         for level in Overcooked2Level(): | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |             if not self.options.kevin_levels and level.level_id > 36: | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Create Region (e.g. "1-1") | 
					
						
							|  |  |  |             self.add_region(level.level_name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Add Location to house progression item (1-star) | 
					
						
							|  |  |  |             if level.level_id == 36: | 
					
						
							|  |  |  |                 # 6-6 doesn't have progression, but it does have victory condition which is placed later | 
					
						
							|  |  |  |                 self.add_level_location( | 
					
						
							|  |  |  |                     level.level_name, | 
					
						
							|  |  |  |                     level.location_name_item, | 
					
						
							|  |  |  |                     None, | 
					
						
							|  |  |  |                     1, | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 # Location to house progression item | 
					
						
							|  |  |  |                 self.add_level_location( | 
					
						
							|  |  |  |                     level.level_name, | 
					
						
							|  |  |  |                     level.location_name_item, | 
					
						
							|  |  |  |                     level.level_id, | 
					
						
							|  |  |  |                     1, | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Location to house level completed event | 
					
						
							|  |  |  |                 self.add_level_location( | 
					
						
							|  |  |  |                     level.level_name, | 
					
						
							|  |  |  |                     level.location_name_level_complete, | 
					
						
							|  |  |  |                     level.level_id, | 
					
						
							|  |  |  |                     1, | 
					
						
							|  |  |  |                     is_event=True, | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-16 07:48:12 -08:00
										 |  |  |             # Add Locations to house star aquisition events | 
					
						
							|  |  |  |             if self.is_level_horde(level.level_id): | 
					
						
							|  |  |  |                 # in randomizer, horde levels grant a single star | 
					
						
							|  |  |  |                 star_counts = [1] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 star_counts = [1, 2, 3] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for n in star_counts: | 
					
						
							|  |  |  |                 self.add_level_location( | 
					
						
							|  |  |  |                     level.level_name, | 
					
						
							|  |  |  |                     level.location_name_star_event(n), | 
					
						
							|  |  |  |                     level.level_id, | 
					
						
							|  |  |  |                     n, | 
					
						
							|  |  |  |                     is_event=True, | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # Overworld -> Level | 
					
						
							|  |  |  |             required_star_count: int = self.level_unlock_counts[level.level_id] | 
					
						
							|  |  |  |             if level.level_id % 6 != 1 and level.level_id <= 36: | 
					
						
							|  |  |  |                 previous_level_completed_event_name: str = Overcooked2GenericLevel( | 
					
						
							|  |  |  |                     level.level_id - 1).shortname.split(" ")[1] + " Level Complete" | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 previous_level_completed_event_name = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             level_access_rule: Callable[[CollectionState], bool] = \ | 
					
						
							|  |  |  |                 lambda state, level_name=level.level_name, previous_level_completed_event_name=previous_level_completed_event_name, required_star_count=required_star_count: \ | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |                 has_requirements_for_level_access(state, level_name, previous_level_completed_event_name, required_star_count, self.options.ramp_tricks.result, self.player) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             self.connect_regions("Overworld", level.level_name, level_access_rule) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Level --> Overworld | 
					
						
							|  |  |  |             self.connect_regions(level.level_name, "Overworld") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         completion_condition: Callable[[CollectionState], bool] = lambda state: \ | 
					
						
							|  |  |  |             state.has("Victory", self.player) | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         self.multiworld.completion_condition[self.player] = completion_condition | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     def create_items(self): | 
					
						
							|  |  |  |         self.itempool = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Make Items | 
					
						
							|  |  |  |         # useful = list() | 
					
						
							|  |  |  |         # filler = list() | 
					
						
							|  |  |  |         # progression = list() | 
					
						
							| 
									
										
										
										
											2023-02-17 00:25:56 -08:00
										 |  |  |         for item_name in item_table:             | 
					
						
							|  |  |  |             if item_name in item_frequencies: | 
					
						
							|  |  |  |                 freq = item_frequencies[item_name] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 freq = 1 | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             if freq <= 0: | 
					
						
							|  |  |  |                 # not used | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |             if item_name in dlc_exclusives: | 
					
						
							|  |  |  |                 if not any(x in dlc_exclusives[item_name] for x in self.enabled_dlc): | 
					
						
							|  |  |  |                     # Item is always useless with these settings | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-12-16 07:48:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |             if not self.options.include_horde_levels and item_name in ["Calmer Unbread", "Coin Purse"]: | 
					
						
							| 
									
										
										
										
											2022-12-16 07:48:57 -08:00
										 |  |  |                 # skip horde-specific items if no horde levels | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |             if not self.options.kevin_levels: | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |                 if item_name.startswith("Kevin"): | 
					
						
							|  |  |  |                     # skip kevin items if no kevin levels | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if item_name == "Dark Green Ramp": | 
					
						
							|  |  |  |                     # skip dark green ramp if there's no Kevin-1 to reveal it | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |             if is_item_progression(item_name, self.level_mapping, self.options.kevin_levels): | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |                 # progression.append(item_name) | 
					
						
							|  |  |  |                 classification = ItemClassification.progression | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 if (is_useful(item_name)): | 
					
						
							|  |  |  |                     # useful.append(item_name) | 
					
						
							|  |  |  |                     classification = ItemClassification.useful | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     # filler.append(item_name) | 
					
						
							|  |  |  |                     classification = ItemClassification.filler | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:25:56 -08:00
										 |  |  |             while freq > 0: | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |                 self.itempool.append(self.create_item(item_name, classification)) | 
					
						
							| 
									
										
										
										
											2023-02-17 00:25:56 -08:00
										 |  |  |                 classification = ItemClassification.useful  # only the first progressive item can be progression | 
					
						
							|  |  |  |                 freq -= 1 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # print(f"progression: {progression}") | 
					
						
							|  |  |  |         # print(f"useful: {useful}") | 
					
						
							|  |  |  |         # print(f"filler: {filler}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Fill any free space with filler | 
					
						
							|  |  |  |         pool_count = len(oc2_location_name_to_id) | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         if not self.options.kevin_levels: | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             pool_count -= 8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while len(self.itempool) < pool_count: | 
					
						
							|  |  |  |             self.itempool.append(self.create_item("Bonus Star", ItemClassification.useful)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |         self.multiworld.itempool += self.itempool | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |     def place_events(self): | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |         # Add Events (Star Acquisition) | 
					
						
							|  |  |  |         for level in Overcooked2Level(): | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |             if not self.options.kevin_levels and level.level_id > 36: | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if level.level_id != 36: | 
					
						
							|  |  |  |                 self.place_event(level.location_name_level_complete, level.event_name_level_complete) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if self.is_level_horde(level.level_id): | 
					
						
							| 
									
										
										
										
											2022-12-16 07:48:12 -08:00
										 |  |  |                 # in randomizer, horde levels grant a single star | 
					
						
							|  |  |  |                 star_counts = [1] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 star_counts = [1, 2, 3] | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-16 07:48:12 -08:00
										 |  |  |             for n in star_counts: | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |                 self.place_event(level.location_name_star_event(n), "Star") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Add Victory Condition | 
					
						
							|  |  |  |         self.place_event("6-6 Completed", "Victory") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 00:21:56 -08:00
										 |  |  |     def set_rules(self): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def generate_basic(self) -> None: | 
					
						
							|  |  |  |         self.place_events() | 
					
						
							|  |  |  |         self.set_location_priority() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |     # Items get distributed to locations | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def fill_json_data(self) -> Dict[str, Any]: | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |         mod_name = f"AP-{self.multiworld.seed_name}-P{self.player}-{self.player_name}" | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Serialize Level Order | 
					
						
							|  |  |  |         story_level_order = dict() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         if self.options.shuffle_level_order: | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             for level_id in self.level_mapping: | 
					
						
							|  |  |  |                 level: Overcooked2GenericLevel = self.level_mapping[level_id] | 
					
						
							|  |  |  |                 story_level_order[str(level_id)] = { | 
					
						
							|  |  |  |                     "DLC": level.dlc.value, | 
					
						
							|  |  |  |                     "LevelID": level.level_id, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         custom_level_order = dict() | 
					
						
							|  |  |  |         custom_level_order["Story"] = story_level_order | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Serialize Unlock Requirements | 
					
						
							|  |  |  |         level_purchase_requirements = dict() | 
					
						
							|  |  |  |         for level_id in self.level_unlock_counts: | 
					
						
							|  |  |  |             level_purchase_requirements[str(level_id)] = self.level_unlock_counts[level_id] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Override Vanilla Unlock Chain Behavior | 
					
						
							|  |  |  |         # (all worlds accessible from the start and progressible in any order) | 
					
						
							|  |  |  |         level_unlock_requirements = dict() | 
					
						
							|  |  |  |         level_force_reveal = [ | 
					
						
							|  |  |  |             1,   # 1-1 | 
					
						
							|  |  |  |             7,   # 2-1 | 
					
						
							|  |  |  |             13,  # 3-1 | 
					
						
							|  |  |  |             19,  # 4-1 | 
					
						
							|  |  |  |             25,  # 5-1 | 
					
						
							|  |  |  |             31,  # 6-1 | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         for level_id in range(1, 37): | 
					
						
							|  |  |  |             if (level_id not in level_force_reveal): | 
					
						
							|  |  |  |                 level_unlock_requirements[str(level_id)] = level_id - 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Set Kevin Unlock Requirements | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         if self.options.kevin_levels: | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             def kevin_level_to_keyholder_level_id(level_id: int) -> Optional[int]: | 
					
						
							| 
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 |  |  |                 location = self.multiworld.find_item(f"Kevin-{level_id-36}", self.player) | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |                 if location.player != self.player: | 
					
						
							|  |  |  |                     return None  # This kevin level will be unlocked by the server at runtime | 
					
						
							|  |  |  |                 level_id = oc2_location_name_to_id[location.name] | 
					
						
							|  |  |  |                 return level_id | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for level_id in range(37, 45): | 
					
						
							|  |  |  |                 keyholder_level_id = kevin_level_to_keyholder_level_id(level_id) | 
					
						
							|  |  |  |                 if keyholder_level_id is not None: | 
					
						
							|  |  |  |                     level_unlock_requirements[str(level_id)] = keyholder_level_id | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Place Items at Level Completion Screens (local only) | 
					
						
							|  |  |  |         on_level_completed: Dict[str, list[Dict[str, str]]] = dict() | 
					
						
							| 
									
										
										
										
											2022-11-02 10:11:46 -05:00
										 |  |  |         locations = self.multiworld.get_filled_locations(self.player) | 
					
						
							|  |  |  |         for location in locations: | 
					
						
							|  |  |  |             if location.item.code is None: | 
					
						
							|  |  |  |                 continue  # it's an event | 
					
						
							|  |  |  |             if location.item.player != self.player: | 
					
						
							|  |  |  |                 continue  # not for us | 
					
						
							|  |  |  |             level_id = str(oc2_location_name_to_id[location.name]) | 
					
						
							|  |  |  |             on_level_completed[level_id] = [item_to_unlock_event(location.item.name)] | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Put it all together | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         star_threshold_scale = self.options.star_threshold_scale / 100 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         base_data = { | 
					
						
							|  |  |  |             # Changes Inherent to rando | 
					
						
							|  |  |  |             "DisableAllMods": False, | 
					
						
							|  |  |  |             "UnlockAllChefs": True, | 
					
						
							|  |  |  |             "UnlockAllDLC": True, | 
					
						
							|  |  |  |             "DisplayFPS": True, | 
					
						
							|  |  |  |             "SkipTutorial": True, | 
					
						
							|  |  |  |             "SkipAllOnionKing": True, | 
					
						
							|  |  |  |             "SkipTutorialPopups": True, | 
					
						
							|  |  |  |             "RevealAllLevels": False, | 
					
						
							|  |  |  |             "PurchaseAllLevels": False, | 
					
						
							|  |  |  |             "CheatsEnabled": False, | 
					
						
							|  |  |  |             "ImpossibleTutorial": True, | 
					
						
							|  |  |  |             "ForbidDLC": True, | 
					
						
							|  |  |  |             "ForceSingleSaveSlot": True, | 
					
						
							|  |  |  |             "DisableNGP": True, | 
					
						
							|  |  |  |             "LevelForceReveal": level_force_reveal, | 
					
						
							|  |  |  |             "SaveFolderName": mod_name, | 
					
						
							|  |  |  |             "CustomOrderTimeoutPenalty": 10, | 
					
						
							|  |  |  |             "LevelForceHide": [37, 38, 39, 40, 41, 42, 43, 44], | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |             "LocalDeathLink": self.options.deathlink != DeathLinkMode.disabled, | 
					
						
							|  |  |  |             "BurnTriggersDeath": self.options.deathlink == DeathLinkMode.death_and_overcook, | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # Game Modifications | 
					
						
							|  |  |  |             "LevelPurchaseRequirements": level_purchase_requirements, | 
					
						
							| 
									
										
										
										
											2022-11-30 18:44:08 -08:00
										 |  |  |             "Custom66TimerScale": max(0.4, 0.25 + (1.0 - star_threshold_scale)*0.6), | 
					
						
							| 
									
										
										
										
											2023-10-19 18:36:18 -05:00
										 |  |  |             "ShortHordeLevels": self.options.short_horde_levels.result, | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             "CustomLevelOrder": custom_level_order, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Items (Starting Inventory) | 
					
						
							|  |  |  |             "CustomOrderLifetime": 70.0,  # 100 is original | 
					
						
							|  |  |  |             "DisableWood": True, | 
					
						
							|  |  |  |             "DisableCoal": True, | 
					
						
							|  |  |  |             "DisableOnePlate": True, | 
					
						
							|  |  |  |             "DisableFireExtinguisher": True, | 
					
						
							|  |  |  |             "DisableBellows": True, | 
					
						
							|  |  |  |             "PlatesStartDirty": True, | 
					
						
							|  |  |  |             "MaxTipCombo": 2, | 
					
						
							|  |  |  |             "DisableDash": True, | 
					
						
							|  |  |  |             "WeakDash": True, | 
					
						
							|  |  |  |             "DisableThrow": True, | 
					
						
							|  |  |  |             "DisableCatch": True, | 
					
						
							|  |  |  |             "DisableControlStick": True, | 
					
						
							|  |  |  |             "DisableWokDrag": True, | 
					
						
							| 
									
										
										
										
											2023-02-17 00:25:56 -08:00
										 |  |  |             # "DisableRampButton": True, # Unused | 
					
						
							|  |  |  |             "DisableGreenRampButton" : True, | 
					
						
							|  |  |  |             "DisableYellowRampButton" : True, | 
					
						
							|  |  |  |             "DisableBlueRampButton" : True, | 
					
						
							|  |  |  |             "DisablePinkRampButton" : True, | 
					
						
							|  |  |  |             "DisableGreyRampButton" : True, | 
					
						
							|  |  |  |             "DisableRedRampButton" : True, | 
					
						
							|  |  |  |             "DisablePurpleRampButton" : True, | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             "WashTimeMultiplier": 1.4, | 
					
						
							|  |  |  |             "BurnSpeedMultiplier": 1.43, | 
					
						
							|  |  |  |             "MaxOrdersOnScreenOffset": -2, | 
					
						
							|  |  |  |             "ChoppingTimeScale": 1.4, | 
					
						
							|  |  |  |             "BackpackMovementScale": 0.75, | 
					
						
							|  |  |  |             "RespawnTime": 10.0, | 
					
						
							|  |  |  |             "CarnivalDispenserRefactoryTime": 4.0, | 
					
						
							|  |  |  |             "LevelUnlockRequirements": level_unlock_requirements, | 
					
						
							|  |  |  |             "LockedEmotes": [0, 1, 2, 3, 4, 5], | 
					
						
							|  |  |  |             "StarOffset": 0, | 
					
						
							|  |  |  |             "AggressiveHorde": True, | 
					
						
							|  |  |  |             "DisableEarnHordeMoney": True, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Item Unlocking | 
					
						
							|  |  |  |             "OnLevelCompleted": on_level_completed, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Set remaining data in the options dict | 
					
						
							|  |  |  |         bugs = ["FixDoubleServing", "FixSinkBug", "FixControlStickThrowBug", "FixEmptyBurnerThrow"] | 
					
						
							|  |  |  |         for bug in bugs: | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |             base_data[bug] = self.options.fix_bugs.result | 
					
						
							|  |  |  |         base_data["PreserveCookingProgress"] = self.options.always_preserve_cooking_progress.result | 
					
						
							|  |  |  |         base_data["TimerAlwaysStarts"] = self.options.prep_levels == PrepLevelMode.ayce | 
					
						
							|  |  |  |         base_data["LevelTimerScale"] = 0.666 if self.options.shorter_level_duration else 1.0 | 
					
						
							|  |  |  |         base_data["LeaderboardScoreScale"] = { | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  |             "FourStars": 1.0, | 
					
						
							|  |  |  |             "ThreeStars": star_threshold_scale, | 
					
						
							|  |  |  |             "TwoStars": star_threshold_scale * 0.75, | 
					
						
							|  |  |  |             "OneStar": star_threshold_scale * 0.35, | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-10-19 18:36:18 -05:00
										 |  |  |         base_data["AlwaysServeOldestOrder"] = self.options.always_serve_oldest_order.result | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return base_data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def fill_slot_data(self) -> Dict[str, Any]: | 
					
						
							|  |  |  |         return self.fill_json_data() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |     def write_spoiler(self, spoiler_handle: TextIO) -> None: | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         if not self.options.shuffle_level_order: | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         world: Overcooked2World = self | 
					
						
							| 
									
										
										
										
											2023-04-10 18:43:29 -07:00
										 |  |  |         spoiler_handle.write(f"\n\n{self.player_name}'s Level Order:\n\n") | 
					
						
							|  |  |  |         for overworld_id in world.level_mapping: | 
					
						
							|  |  |  |             overworld_name = Overcooked2GenericLevel(overworld_id).shortname.split("Story ")[1] | 
					
						
							|  |  |  |             kitchen_name = world.level_mapping[overworld_id].shortname | 
					
						
							|  |  |  |             spoiler_handle.write(f'{overworld_name} | {kitchen_name}\n') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-13 10:57:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | def level_unlock_requirement_factory(stars_to_win: int) -> Dict[int, int]: | 
					
						
							|  |  |  |     level_unlock_counts = dict() | 
					
						
							|  |  |  |     level = 1 | 
					
						
							|  |  |  |     sublevel = 1 | 
					
						
							|  |  |  |     for n in range(1, 37): | 
					
						
							|  |  |  |         progress: float = float(n)/36.0 | 
					
						
							|  |  |  |         progress *= progress  # x^2 curve | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         star_count = int(progress*float(stars_to_win)) | 
					
						
							|  |  |  |         min = (n-1)*3 | 
					
						
							|  |  |  |         if (star_count > min): | 
					
						
							|  |  |  |             star_count = min | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         level_id = (level-1)*6 + sublevel | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # print("%d-%d (%d) = %d" % (level, sublevel, level_id, star_count)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         level_unlock_counts[level_id] = star_count | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         level += 1 | 
					
						
							|  |  |  |         if level > 6: | 
					
						
							|  |  |  |             level = 1 | 
					
						
							|  |  |  |             sublevel += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # force sphere 1 to 0 stars to help keep our promises to the item fill algo | 
					
						
							|  |  |  |     level_unlock_counts[1] = 0  # 1-1 | 
					
						
							|  |  |  |     level_unlock_counts[7] = 0  # 2-1 | 
					
						
							|  |  |  |     level_unlock_counts[19] = 0  # 4-1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Force 5-1 into sphere 1 to help things out | 
					
						
							|  |  |  |     level_unlock_counts[25] = 1  # 5-1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for n in range(37, 46): | 
					
						
							|  |  |  |         level_unlock_counts[n] = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return level_unlock_counts |