179 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from .Items import item_table, ShiversItem
 | |
| from .Rules import set_rules
 | |
| from BaseClasses import Item, Tutorial, Region, Location
 | |
| from Fill import fill_restrictive
 | |
| from worlds.AutoWorld import WebWorld, World
 | |
| from . import Constants, Rules
 | |
| from .Options import ShiversOptions
 | |
| 
 | |
| 
 | |
| class ShiversWeb(WebWorld):
 | |
|     tutorials = [Tutorial(
 | |
|         "Shivers Setup Guide",
 | |
|         "A guide to setting up Shivers for Multiworld.",
 | |
|         "English",
 | |
|         "setup_en.md",
 | |
|         "setup/en",
 | |
|         ["GodlFire", "Mathx2"]
 | |
|     )]
 | |
| 
 | |
| class ShiversWorld(World):
 | |
|     """
 | |
|     Shivers is a horror themed point and click adventure. Explore the mysteries of Windlenot's Museum of the Strange and Unusual.
 | |
|     """
 | |
| 
 | |
|     game: str = "Shivers"
 | |
|     topology_present = False
 | |
|     web = ShiversWeb()
 | |
|     options_dataclass = ShiversOptions
 | |
|     options: ShiversOptions
 | |
| 
 | |
|     item_name_to_id = {name: data.code for name, data in item_table.items()}
 | |
|     location_name_to_id = Constants.location_name_to_id
 | |
|     
 | |
|     def create_item(self, name: str) -> Item:
 | |
|         data = item_table[name]
 | |
|         return ShiversItem(name, data.classification, data.code, self.player)
 | |
| 
 | |
|     def create_event(self, region_name: str, event_name: str) -> None:
 | |
|         region = self.multiworld.get_region(region_name, self.player)
 | |
|         loc = ShiversLocation(self.player, event_name, None, region)
 | |
|         loc.place_locked_item(self.create_event_item(event_name))
 | |
|         region.locations.append(loc)
 | |
| 
 | |
|     def create_regions(self) -> None:
 | |
|         # Create regions
 | |
|         for region_name, exits in Constants.region_info["regions"]:
 | |
|             r = Region(region_name, self.player, self.multiworld)
 | |
|             self.multiworld.regions.append(r)
 | |
|             for exit_name in exits:
 | |
|                 r.create_exit(exit_name)
 | |
| 
 | |
| 
 | |
|         # Bind mandatory connections
 | |
|         for entr_name, region_name in Constants.region_info["mandatory_connections"]:
 | |
|             e = self.multiworld.get_entrance(entr_name, self.player)
 | |
|             r = self.multiworld.get_region(region_name, self.player)
 | |
|             e.connect(r)
 | |
|         
 | |
|         # Locations
 | |
|         # Build exclusion list
 | |
|         self.removed_locations = set()
 | |
|         if not self.options.include_information_plaques:
 | |
|             self.removed_locations.update(Constants.exclusion_info["plaques"])
 | |
|         if not self.options.elevators_stay_solved:
 | |
|             self.removed_locations.update(Constants.exclusion_info["elevators"])
 | |
|         if not self.options.early_lightning:
 | |
|             self.removed_locations.update(Constants.exclusion_info["lightning"])
 | |
| 
 | |
|         # Add locations
 | |
|         for region_name, locations in Constants.location_info["locations_by_region"].items():
 | |
|             region = self.multiworld.get_region(region_name, self.player)
 | |
|             for loc_name in locations:
 | |
|                 if loc_name not in self.removed_locations:
 | |
|                     loc = ShiversLocation(self.player, loc_name, self.location_name_to_id.get(loc_name, None), region)
 | |
|                     region.locations.append(loc)
 | |
| 
 | |
|     def create_items(self) -> None:
 | |
|         #Add items to item pool
 | |
|         itempool = []
 | |
|         for name, data in item_table.items():
 | |
|             if data.type in {"pot", "key", "ability", "filler2"}:
 | |
|                 itempool.append(self.create_item(name))
 | |
| 
 | |
|         #Add Filler
 | |
|         itempool += [self.create_item("Easier Lyre") for i in range(9)]
 | |
| 
 | |
|         #Extra filler is random between Heals and Easier Lyre. Heals weighted 95%.
 | |
|         filler_needed = len(self.multiworld.get_unfilled_locations(self.player)) - 24 - len(itempool)
 | |
|         itempool += [self.random.choices([self.create_item("Heal"), self.create_item("Easier Lyre")], weights=[95, 5])[0] for i in range(filler_needed)]
 | |
| 
 | |
| 
 | |
|         #Place library escape items. Choose a location to place the escape item
 | |
|         library_region = self.multiworld.get_region("Library", self.player)
 | |
|         librarylocation = self.random.choice([loc for loc in library_region.locations if not loc.name.startswith("Accessible:")])
 | |
| 
 | |
|         #Roll for which escape items will be placed in the Library
 | |
|         library_random = self.random.randint(1, 3)
 | |
|         if library_random == 1: 
 | |
|             librarylocation.place_locked_item(self.create_item("Crawling"))
 | |
| 
 | |
|             itempool = [item for item in itempool if item.name != "Crawling"]
 | |
| 
 | |
|         elif library_random == 2: 
 | |
|             librarylocation.place_locked_item(self.create_item("Key for Library Room"))
 | |
| 
 | |
|             itempool = [item for item in itempool if item.name != "Key for Library Room"]
 | |
|         elif library_random == 3: 
 | |
|             librarylocation.place_locked_item(self.create_item("Key for Three Floor Elevator"))
 | |
|             
 | |
|             librarylocationkeytwo = self.random.choice([loc for loc in library_region.locations if not loc.name.startswith("Accessible:") and loc != librarylocation])
 | |
|             librarylocationkeytwo.place_locked_item(self.create_item("Key for Egypt Room"))
 | |
| 
 | |
|             itempool = [item for item in itempool if item.name not in ["Key for Three Floor Elevator", "Key for Egypt Room"]]
 | |
| 
 | |
|         #If front door option is on, determine which set of keys will be used for lobby access and add front door key to item pool
 | |
|         lobby_access_keys = 1
 | |
|         if self.options.front_door_usable:
 | |
|             lobby_access_keys = self.random.randint(1, 2)
 | |
|             itempool += [self.create_item("Key for Front Door")]
 | |
|         else:
 | |
|             itempool += [self.create_item("Heal")]
 | |
| 
 | |
|         self.multiworld.itempool += itempool
 | |
| 
 | |
|         #Lobby acess:
 | |
|         if self.options.lobby_access == 1:
 | |
|             if lobby_access_keys == 1:
 | |
|                 self.multiworld.early_items[self.player]["Key for Underground Lake Room"] = 1
 | |
|                 self.multiworld.early_items[self.player]["Key for Office Elevator"] = 1
 | |
|                 self.multiworld.early_items[self.player]["Key for Office"] = 1
 | |
|             elif lobby_access_keys == 2:
 | |
|                 self.multiworld.early_items[self.player]["Key for Front Door"] = 1
 | |
|         if self.options.lobby_access == 2:
 | |
|             if lobby_access_keys == 1:
 | |
|                 self.multiworld.local_early_items[self.player]["Key for Underground Lake Room"] = 1
 | |
|                 self.multiworld.local_early_items[self.player]["Key for Office Elevator"] = 1
 | |
|                 self.multiworld.local_early_items[self.player]["Key for Office"] = 1
 | |
|             elif lobby_access_keys == 2:
 | |
|                 self.multiworld.local_early_items[self.player]["Key for Front Door"] = 1
 | |
| 
 | |
|     def pre_fill(self) -> None:
 | |
|         # Prefills event storage locations with duplicate pots
 | |
|         storagelocs = []
 | |
|         storageitems = []
 | |
|         self.storage_placements = []
 | |
| 
 | |
|         for locations in Constants.location_info["locations_by_region"].values():
 | |
|             for loc_name in locations:
 | |
|                 if loc_name.startswith("Accessible: "):
 | |
|                     storagelocs.append(self.multiworld.get_location(loc_name, self.player))
 | |
| 
 | |
|         storageitems += [self.create_item(name) for name, data in item_table.items() if data.type == 'potduplicate']
 | |
|         storageitems += [self.create_item("Empty") for i in range(3)]
 | |
| 
 | |
|         state = self.multiworld.get_all_state(True)
 | |
| 
 | |
|         self.random.shuffle(storagelocs)
 | |
|         self.random.shuffle(storageitems)
 | |
|         
 | |
|         fill_restrictive(self.multiworld, state, storagelocs.copy(), storageitems, True, True)
 | |
| 
 | |
|         self.storage_placements = {location.name: location.item.name for location in storagelocs}
 | |
| 
 | |
|     set_rules = set_rules
 | |
| 
 | |
|     def fill_slot_data(self) -> dict:
 | |
| 
 | |
|         return {
 | |
|             "storageplacements": self.storage_placements,
 | |
|             "excludedlocations": {str(excluded_location).replace('ExcludeLocations(', '').replace(')', '') for excluded_location in self.multiworld.exclude_locations.values()},
 | |
|             "elevatorsstaysolved": {self.options.elevators_stay_solved.value},
 | |
|             "earlybeth": {self.options.early_beth.value},
 | |
|             "earlylightning": {self.options.early_lightning.value},
 | |
|         }
 | |
| 
 | |
| 
 | |
| class ShiversLocation(Location):
 | |
|     game = "Shivers"
 | 
