mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-05-26 07:49:58 -07:00
5a9bc60a25
Shivers nearly always finishes last in multiworld games due to the fact you need all 20 pot pieces to win and the pot pieces open very few location checks. This option allows the pieces to be placed locally. This should allow Shivers to be finished earlier.
185 lines
8.2 KiB
Python
185 lines
8.2 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
|
|
|
|
#Pot piece shuffle location:
|
|
if self.options.location_pot_pieces == 0:
|
|
self.multiworld.local_items[self.player].value.update({name for name, data in item_table.items() if data.type == "pot"})
|
|
if self.options.location_pot_pieces == 1:
|
|
self.multiworld.non_local_items[self.player].value.update({name for name, data in item_table.items() if data.type == "pot"})
|
|
|
|
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"
|