| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  | from typing import Dict, List, NamedTuple, Optional, TYPE_CHECKING | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  | from BaseClasses import Region, Entrance, MultiWorld | 
					
						
							|  |  |  | from .locations import location_table, RiskOfRainLocation, get_classic_item_pickups | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if TYPE_CHECKING: | 
					
						
							|  |  |  |     from . import RiskOfRainWorld | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RoRRegionData(NamedTuple): | 
					
						
							|  |  |  |     locations: Optional[List[str]] | 
					
						
							|  |  |  |     region_exits: Optional[List[str]] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  | def create_explore_regions(ror2_world: "RiskOfRainWorld") -> None: | 
					
						
							|  |  |  |     player = ror2_world.player | 
					
						
							|  |  |  |     ror2_options = ror2_world.options | 
					
						
							|  |  |  |     multiworld = ror2_world.multiworld | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |     # Default Locations | 
					
						
							|  |  |  |     non_dlc_regions: Dict[str, RoRRegionData] = { | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |         "Menu":                                 RoRRegionData(None, ["Distant Roost", "Distant Roost (2)", | 
					
						
							| 
									
										
										
										
											2024-06-04 13:24:14 -06:00
										 |  |  |                                                                      "Titanic Plains", "Titanic Plains (2)", | 
					
						
							|  |  |  |                                                                      "Verdant Falls"]), | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         "Distant Roost":                        RoRRegionData([], ["OrderedStage_1"]), | 
					
						
							|  |  |  |         "Distant Roost (2)":                    RoRRegionData([], ["OrderedStage_1"]), | 
					
						
							|  |  |  |         "Titanic Plains":                       RoRRegionData([], ["OrderedStage_1"]), | 
					
						
							|  |  |  |         "Titanic Plains (2)":                   RoRRegionData([], ["OrderedStage_1"]), | 
					
						
							| 
									
										
										
										
											2024-06-04 13:24:14 -06:00
										 |  |  |         "Verdant Falls":                        RoRRegionData([], ["OrderedStage_1"]), | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         "Abandoned Aqueduct":                   RoRRegionData([], ["OrderedStage_2"]), | 
					
						
							|  |  |  |         "Wetland Aspect":                       RoRRegionData([], ["OrderedStage_2"]), | 
					
						
							|  |  |  |         "Rallypoint Delta":                     RoRRegionData([], ["OrderedStage_3"]), | 
					
						
							|  |  |  |         "Scorched Acres":                       RoRRegionData([], ["OrderedStage_3"]), | 
					
						
							|  |  |  |         "Abyssal Depths":                       RoRRegionData([], ["OrderedStage_4"]), | 
					
						
							|  |  |  |         "Siren's Call":                         RoRRegionData([], ["OrderedStage_4"]), | 
					
						
							|  |  |  |         "Sundered Grove":                       RoRRegionData([], ["OrderedStage_4"]), | 
					
						
							|  |  |  |         "Sky Meadow":                           RoRRegionData([], ["Hidden Realm: Bulwark's Ambry", "OrderedStage_5"]), | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     # SOTV Regions | 
					
						
							|  |  |  |     dlc_regions: Dict[str, RoRRegionData] = { | 
					
						
							|  |  |  |         "Siphoned Forest":                      RoRRegionData([], ["OrderedStage_1"]), | 
					
						
							|  |  |  |         "Aphelian Sanctuary":                   RoRRegionData([], ["OrderedStage_2"]), | 
					
						
							|  |  |  |         "Sulfur Pools":                         RoRRegionData([], ["OrderedStage_3"]) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     other_regions: Dict[str, RoRRegionData] = { | 
					
						
							| 
									
										
										
										
											2023-02-17 14:08:18 -07:00
										 |  |  |         "Commencement":                         RoRRegionData(None, ["Victory", "Petrichor V"]), | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |         "OrderedStage_5":                       RoRRegionData(None, ["Hidden Realm: A Moment, Fractured", | 
					
						
							|  |  |  |                                                                      "Commencement"]), | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         "OrderedStage_1":                       RoRRegionData(None, ["Hidden Realm: Bazaar Between Time", | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |                                                                      "Hidden Realm: Gilded Coast", "Abandoned Aqueduct", | 
					
						
							|  |  |  |                                                                      "Wetland Aspect"]), | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         "OrderedStage_2":                       RoRRegionData(None, ["Rallypoint Delta", "Scorched Acres"]), | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |         "OrderedStage_3":                       RoRRegionData(None, ["Abyssal Depths", "Siren's Call", | 
					
						
							|  |  |  |                                                                      "Sundered Grove"]), | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         "OrderedStage_4":                       RoRRegionData(None, ["Sky Meadow"]), | 
					
						
							|  |  |  |         "Hidden Realm: A Moment, Fractured":    RoRRegionData(None, ["Hidden Realm: A Moment, Whole"]), | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |         "Hidden Realm: A Moment, Whole":        RoRRegionData(None, ["Victory", "Petrichor V"]), | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         "Void Fields":                          RoRRegionData(None, []), | 
					
						
							|  |  |  |         "Victory":                              RoRRegionData(None, None), | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |         "Petrichor V":                          RoRRegionData(None, []), | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         "Hidden Realm: Bulwark's Ambry":        RoRRegionData(None, None), | 
					
						
							|  |  |  |         "Hidden Realm: Bazaar Between Time":    RoRRegionData(None, ["Void Fields"]), | 
					
						
							|  |  |  |         "Hidden Realm: Gilded Coast":           RoRRegionData(None, None) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     dlc_other_regions: Dict[str, RoRRegionData] = { | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |         "The Planetarium":                      RoRRegionData(None, ["Victory", "Petrichor V"]), | 
					
						
							| 
									
										
										
										
											2023-06-26 22:47:52 -06:00
										 |  |  |         "Void Locus":                           RoRRegionData(None, ["The Planetarium"]) | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     # Totals of each item | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |     chests = int(ror2_options.chests_per_stage) | 
					
						
							|  |  |  |     shrines = int(ror2_options.shrines_per_stage) | 
					
						
							|  |  |  |     scavengers = int(ror2_options.scavengers_per_stage) | 
					
						
							|  |  |  |     scanners = int(ror2_options.scanner_per_stage) | 
					
						
							|  |  |  |     newt = int(ror2_options.altars_per_stage) | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |     all_location_regions = {**non_dlc_regions} | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |     if ror2_options.dlc_sotv: | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         all_location_regions = {**non_dlc_regions, **dlc_regions} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Locations | 
					
						
							|  |  |  |     for key in all_location_regions: | 
					
						
							|  |  |  |         if key == "Menu": | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         # Chests | 
					
						
							|  |  |  |         for i in range(0, chests): | 
					
						
							|  |  |  |             all_location_regions[key].locations.append(f"{key}: Chest {i + 1}") | 
					
						
							|  |  |  |         # Shrines | 
					
						
							|  |  |  |         for i in range(0, shrines): | 
					
						
							|  |  |  |             all_location_regions[key].locations.append(f"{key}: Shrine {i + 1}") | 
					
						
							|  |  |  |         # Scavengers | 
					
						
							|  |  |  |         if scavengers > 0: | 
					
						
							|  |  |  |             for i in range(0, scavengers): | 
					
						
							|  |  |  |                 all_location_regions[key].locations.append(f"{key}: Scavenger {i + 1}") | 
					
						
							|  |  |  |         # Radio Scanners | 
					
						
							|  |  |  |         if scanners > 0: | 
					
						
							|  |  |  |             for i in range(0, scanners): | 
					
						
							|  |  |  |                 all_location_regions[key].locations.append(f"{key}: Radio Scanner {i + 1}") | 
					
						
							|  |  |  |         # Newt Altars | 
					
						
							|  |  |  |         if newt > 0: | 
					
						
							|  |  |  |             for i in range(0, newt): | 
					
						
							|  |  |  |                 all_location_regions[key].locations.append(f"{key}: Newt Altar {i + 1}") | 
					
						
							|  |  |  |     regions_pool: Dict = {**all_location_regions, **other_regions} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # DLC Locations | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |     if ror2_options.dlc_sotv: | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         non_dlc_regions["Menu"].region_exits.append("Siphoned Forest") | 
					
						
							| 
									
										
										
										
											2023-07-05 21:45:43 -06:00
										 |  |  |         other_regions["OrderedStage_1"].region_exits.append("Aphelian Sanctuary") | 
					
						
							|  |  |  |         other_regions["OrderedStage_2"].region_exits.append("Sulfur Pools") | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         other_regions["Void Fields"].region_exits.append("Void Locus") | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |         other_regions["Commencement"].region_exits.append("The Planetarium") | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |         regions_pool: Dict = {**all_location_regions, **other_regions, **dlc_other_regions} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |     # Check to see if Victory needs to be removed from regions | 
					
						
							|  |  |  |     if ror2_options.victory == "mithrix": | 
					
						
							|  |  |  |         other_regions["Hidden Realm: A Moment, Whole"].region_exits.pop(0) | 
					
						
							|  |  |  |         dlc_other_regions["The Planetarium"].region_exits.pop(0) | 
					
						
							|  |  |  |     elif ror2_options.victory == "voidling": | 
					
						
							|  |  |  |         other_regions["Commencement"].region_exits.pop(0) | 
					
						
							|  |  |  |         other_regions["Hidden Realm: A Moment, Whole"].region_exits.pop(0) | 
					
						
							|  |  |  |     elif ror2_options.victory == "limbo": | 
					
						
							|  |  |  |         other_regions["Commencement"].region_exits.pop(0) | 
					
						
							|  |  |  |         dlc_other_regions["The Planetarium"].region_exits.pop(0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |     # Create all the regions | 
					
						
							|  |  |  |     for name, data in regions_pool.items(): | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  |         multiworld.regions.append(create_explore_region(multiworld, player, name, data)) | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Connect all the regions to their exits | 
					
						
							|  |  |  |     for name, data in regions_pool.items(): | 
					
						
							|  |  |  |         create_connections_in_regions(multiworld, player, name, data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  | def create_explore_region(multiworld: MultiWorld, player: int, name: str, data: RoRRegionData) -> Region: | 
					
						
							| 
									
										
										
										
											2023-02-13 18:06:43 -06:00
										 |  |  |     region = Region(name, player, multiworld) | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |     if data.locations: | 
					
						
							|  |  |  |         for location_name in data.locations: | 
					
						
							|  |  |  |             location_data = location_table.get(location_name) | 
					
						
							|  |  |  |             location = RiskOfRainLocation(player, location_name, location_data, region) | 
					
						
							|  |  |  |             region.locations.append(location) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return region | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  | def create_connections_in_regions(multiworld: MultiWorld, player: int, name: str, data: RoRRegionData) -> None: | 
					
						
							| 
									
										
										
										
											2023-02-05 13:51:03 -07:00
										 |  |  |     region = multiworld.get_region(name, player) | 
					
						
							|  |  |  |     if data.region_exits: | 
					
						
							| 
									
										
										
										
											2024-02-25 14:56:27 -06:00
										 |  |  |         region.add_exits(data.region_exits) | 
					
						
							| 
									
										
										
										
											2023-11-22 08:20:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def create_classic_regions(ror2_world: "RiskOfRainWorld") -> None: | 
					
						
							|  |  |  |     player = ror2_world.player | 
					
						
							|  |  |  |     ror2_options = ror2_world.options | 
					
						
							|  |  |  |     multiworld = ror2_world.multiworld | 
					
						
							|  |  |  |     menu = create_classic_region(multiworld, player, "Menu") | 
					
						
							|  |  |  |     multiworld.regions.append(menu) | 
					
						
							|  |  |  |     # By using a victory region, we can define it as being connected to by several regions | 
					
						
							|  |  |  |     #   which can then determine the availability of the victory. | 
					
						
							|  |  |  |     victory_region = create_classic_region(multiworld, player, "Victory") | 
					
						
							|  |  |  |     multiworld.regions.append(victory_region) | 
					
						
							|  |  |  |     petrichor = create_classic_region(multiworld, player, "Petrichor V", | 
					
						
							|  |  |  |                                       get_classic_item_pickups(ror2_options.total_locations.value)) | 
					
						
							|  |  |  |     multiworld.regions.append(petrichor) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # classic mode can get to victory from the beginning of the game | 
					
						
							|  |  |  |     to_victory = Entrance(player, "beating game", petrichor) | 
					
						
							|  |  |  |     petrichor.exits.append(to_victory) | 
					
						
							|  |  |  |     to_victory.connect(victory_region) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connection = Entrance(player, "Lobby", menu) | 
					
						
							|  |  |  |     menu.exits.append(connection) | 
					
						
							|  |  |  |     connection.connect(petrichor) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def create_classic_region(multiworld: MultiWorld, player: int, name: str, locations: Dict[str, int] = {}) -> Region: | 
					
						
							|  |  |  |     ret = Region(name, player, multiworld) | 
					
						
							|  |  |  |     for location_name, location_id in locations.items(): | 
					
						
							|  |  |  |         ret.locations.append(RiskOfRainLocation(player, location_name, location_id, ret)) | 
					
						
							|  |  |  |     return ret |