| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  | from functools import cached_property | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  | from typing import Optional, TYPE_CHECKING | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  | from BaseClasses import CollectionState, Entrance, Item, ItemClassification, Location, Region | 
					
						
							|  |  |  | from .regions import LOCATIONS, MEGA_SHARDS | 
					
						
							|  |  |  | from .shop import FIGURINES, SHOP_ITEMS | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | if TYPE_CHECKING: | 
					
						
							|  |  |  |     from . import MessengerWorld | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  | class MessengerEntrance(Entrance): | 
					
						
							|  |  |  |     world: Optional["MessengerWorld"] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  | class MessengerRegion(Region): | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |     parent: str | 
					
						
							|  |  |  |     entrance_type = MessengerEntrance | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, name: str, world: "MessengerWorld", parent: Optional[str] = None) -> None: | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  |         super().__init__(name, world.player, world.multiworld) | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |         self.parent = parent | 
					
						
							|  |  |  |         locations = [] | 
					
						
							|  |  |  |         if name in LOCATIONS: | 
					
						
							|  |  |  |             locations = [loc for loc in LOCATIONS[name]] | 
					
						
							|  |  |  |         # portal event locations since portals can be opened from their exit regions | 
					
						
							|  |  |  |         if name.endswith("Portal"): | 
					
						
							|  |  |  |             locations.append(name.replace(" -", "")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if name == "The Shop": | 
					
						
							| 
									
										
										
										
											2023-07-22 00:45:46 -05:00
										 |  |  |             shop_locations = {f"The Shop - {shop_loc}": world.location_name_to_id[f"The Shop - {shop_loc}"] | 
					
						
							|  |  |  |                               for shop_loc in SHOP_ITEMS} | 
					
						
							|  |  |  |             self.add_locations(shop_locations, MessengerShopLocation) | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |         elif name == "The Craftsman's Corner": | 
					
						
							| 
									
										
										
										
											2023-11-23 17:38:57 -06:00
										 |  |  |             self.add_locations({figurine: world.location_name_to_id[figurine] for figurine in FIGURINES}, | 
					
						
							|  |  |  |                                MessengerLocation) | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |         elif name == "Tower HQ": | 
					
						
							| 
									
										
										
										
											2023-07-22 00:45:46 -05:00
										 |  |  |             locations.append("Money Wrench") | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if world.options.shuffle_shards and name in MEGA_SHARDS: | 
					
						
							|  |  |  |             locations += MEGA_SHARDS[name] | 
					
						
							| 
									
										
										
										
											2023-11-10 22:49:55 -06:00
										 |  |  |         loc_dict = {loc: world.location_name_to_id.get(loc, None) for loc in locations} | 
					
						
							| 
									
										
										
										
											2023-07-22 00:45:46 -05:00
										 |  |  |         self.add_locations(loc_dict, MessengerLocation) | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.multiworld.regions.append(self) | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MessengerLocation(Location): | 
					
						
							|  |  |  |     game = "The Messenger" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-22 00:45:46 -05:00
										 |  |  |     def __init__(self, player: int, name: str, loc_id: Optional[int], parent: MessengerRegion) -> None: | 
					
						
							|  |  |  |         super().__init__(player, name, loc_id, parent) | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  |         if loc_id is None: | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |             if name == "Rescue Phantom": | 
					
						
							|  |  |  |                 name = "Do the Thing!" | 
					
						
							|  |  |  |             self.place_locked_item(MessengerItem(name, ItemClassification.progression, None, parent.player)) | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  | class MessengerShopLocation(MessengerLocation): | 
					
						
							| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  |     @cached_property | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  |     def cost(self) -> int: | 
					
						
							|  |  |  |         name = self.name.replace("The Shop - ", "")  # TODO use `remove_prefix` when 3.8 finally gets dropped | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |         world = self.parent_region.multiworld.worlds[self.player] | 
					
						
							| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  |         shop_data = SHOP_ITEMS[name] | 
					
						
							|  |  |  |         if shop_data.prerequisite: | 
					
						
							|  |  |  |             prereq_cost = 0 | 
					
						
							|  |  |  |             if isinstance(shop_data.prerequisite, set): | 
					
						
							|  |  |  |                 for prereq in shop_data.prerequisite: | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |                     loc = world.multiworld.get_location(prereq, self.player) | 
					
						
							|  |  |  |                     assert isinstance(loc, MessengerShopLocation) | 
					
						
							|  |  |  |                     prereq_cost += loc.cost | 
					
						
							| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |                 loc = world.multiworld.get_location(shop_data.prerequisite, self.player) | 
					
						
							|  |  |  |                 assert isinstance(loc, MessengerShopLocation) | 
					
						
							|  |  |  |                 prereq_cost += loc.cost | 
					
						
							| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  |             return world.shop_prices[name] + prereq_cost | 
					
						
							|  |  |  |         return world.shop_prices[name] | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-23 17:38:57 -06:00
										 |  |  |     def access_rule(self, state: CollectionState) -> bool: | 
					
						
							| 
									
										
										
										
											2024-03-11 17:23:41 -05:00
										 |  |  |         world = state.multiworld.worlds[self.player] | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         can_afford = state.has("Shards", self.player, min(self.cost, world.total_shards)) | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  |         return can_afford | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  | class MessengerItem(Item): | 
					
						
							|  |  |  |     game = "The Messenger" |