| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  | from functools import cached_property | 
					
						
							|  |  |  | from typing import Optional, TYPE_CHECKING, cast | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  | from BaseClasses import CollectionState, Item, ItemClassification, Location, Region | 
					
						
							| 
									
										
										
										
											2023-10-08 07:33:39 -05:00
										 |  |  | from .constants import NOTES, PHOBEKINS, PROG_ITEMS, USEFUL_ITEMS | 
					
						
							|  |  |  | from .options import Goal | 
					
						
							|  |  |  | from .regions import MEGA_SHARDS, REGIONS, SEALS | 
					
						
							|  |  |  | from .shop import FIGURINES, PROG_SHOP_ITEMS, SHOP_ITEMS, USEFUL_SHOP_ITEMS | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | if TYPE_CHECKING: | 
					
						
							|  |  |  |     from . import MessengerWorld | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MessengerRegion(Region): | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |      | 
					
						
							|  |  |  |     def __init__(self, name: str, world: "MessengerWorld") -> None: | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  |         super().__init__(name, world.player, world.multiworld) | 
					
						
							| 
									
										
										
										
											2023-07-22 00:45:46 -05:00
										 |  |  |         locations = [loc for loc in REGIONS[self.name]] | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  |         if self.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} | 
					
						
							|  |  |  |             shop_locations.update(**{figurine: world.location_name_to_id[figurine] for figurine in FIGURINES}) | 
					
						
							|  |  |  |             self.add_locations(shop_locations, MessengerShopLocation) | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  |         elif self.name == "Tower HQ": | 
					
						
							| 
									
										
										
										
											2023-07-22 00:45:46 -05:00
										 |  |  |             locations.append("Money Wrench") | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         if world.options.shuffle_seals and self.name in SEALS: | 
					
						
							| 
									
										
										
										
											2023-07-22 00:45:46 -05:00
										 |  |  |             locations += [seal_loc for seal_loc in SEALS[self.name]] | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         if world.options.shuffle_shards and self.name in MEGA_SHARDS: | 
					
						
							| 
									
										
										
										
											2023-07-22 00:45:46 -05:00
										 |  |  |             locations += [shard for shard in MEGA_SHARDS[self.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) | 
					
						
							| 
									
										
										
										
											2023-11-10 22:49:55 -06:00
										 |  |  |         world.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: | 
					
						
							|  |  |  |             self.place_locked_item(MessengerItem(name, parent.player, None)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         world = cast("MessengerWorld", self.parent_region.multiworld.worlds[self.player]) | 
					
						
							| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  |         # short circuit figurines which all require demon's bane be purchased, but nothing else | 
					
						
							|  |  |  |         if "Figurine" in name: | 
					
						
							|  |  |  |             return world.figurine_prices[name] +\ | 
					
						
							|  |  |  |                 cast(MessengerShopLocation, world.multiworld.get_location("The Shop - Demon's Bane", self.player)).cost | 
					
						
							|  |  |  |         shop_data = SHOP_ITEMS[name] | 
					
						
							|  |  |  |         if shop_data.prerequisite: | 
					
						
							|  |  |  |             prereq_cost = 0 | 
					
						
							|  |  |  |             if isinstance(shop_data.prerequisite, set): | 
					
						
							|  |  |  |                 for prereq in shop_data.prerequisite: | 
					
						
							|  |  |  |                     prereq_cost +=\ | 
					
						
							|  |  |  |                         cast(MessengerShopLocation, | 
					
						
							|  |  |  |                              world.multiworld.get_location(prereq, self.player)).cost | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 prereq_cost +=\ | 
					
						
							|  |  |  |                     cast(MessengerShopLocation, | 
					
						
							|  |  |  |                          world.multiworld.get_location(shop_data.prerequisite, self.player)).cost | 
					
						
							|  |  |  |             return world.shop_prices[name] + prereq_cost | 
					
						
							|  |  |  |         return world.shop_prices[name] | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def can_afford(self, state: CollectionState) -> bool: | 
					
						
							| 
									
										
										
										
											2023-10-10 15:30:20 -05:00
										 |  |  |         world = cast("MessengerWorld", state.multiworld.worlds[self.player]) | 
					
						
							|  |  |  |         can_afford = state.has("Shards", self.player, min(self.cost, world.total_shards)) | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  |         if "Figurine" in self.name: | 
					
						
							| 
									
										
										
										
											2023-07-24 19:41:20 -05:00
										 |  |  |             can_afford = state.has("Money Wrench", self.player) and can_afford\ | 
					
						
							| 
									
										
										
										
											2023-07-18 22:01:44 -05:00
										 |  |  |                 and state.can_reach("Money Wrench", "Location", self.player) | 
					
						
							| 
									
										
										
										
											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" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  |     def __init__(self, name: str, player: int, item_id: Optional[int] = None, override_progression: bool = False, | 
					
						
							|  |  |  |                  count: int = 0) -> None: | 
					
						
							|  |  |  |         if count: | 
					
						
							|  |  |  |             item_class = ItemClassification.progression_skip_balancing | 
					
						
							|  |  |  |         elif item_id is None or override_progression or name in {*NOTES, *PROG_ITEMS, *PHOBEKINS, *PROG_SHOP_ITEMS}: | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  |             item_class = ItemClassification.progression | 
					
						
							| 
									
										
										
										
											2023-06-27 18:39:52 -05:00
										 |  |  |         elif name in {*USEFUL_ITEMS, *USEFUL_SHOP_ITEMS}: | 
					
						
							| 
									
										
										
										
											2023-03-12 09:05:50 -05:00
										 |  |  |             item_class = ItemClassification.useful | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             item_class = ItemClassification.filler | 
					
						
							|  |  |  |         super().__init__(name, item_class, item_id, player) |