413 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			413 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								from typing import Dict, Set, Any
							 | 
						||
| 
								 | 
							
								from collections import Counter
							 | 
						||
| 
								 | 
							
								from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification
							 | 
						||
| 
								 | 
							
								from ..AutoWorld import World, WebWorld
							 | 
						||
| 
								 | 
							
								from .Items import base_id, item_table, group_table, tears_set, reliquary_set, skill_set
							 | 
						||
| 
								 | 
							
								from .Locations import location_table, shop_set
							 | 
						||
| 
								 | 
							
								from .Exits import region_exit_table, exit_lookup_table
							 | 
						||
| 
								 | 
							
								from .Rules import rules
							 | 
						||
| 
								 | 
							
								from worlds.generic.Rules import set_rule
							 | 
						||
| 
								 | 
							
								from .Options import blasphemous_options
							 | 
						||
| 
								 | 
							
								from . import Vanilla
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BlasphemousWeb(WebWorld):
							 | 
						||
| 
								 | 
							
								    theme = "stone"
							 | 
						||
| 
								 | 
							
								    tutorials = [Tutorial(
							 | 
						||
| 
								 | 
							
								        "Multiworld Setup Guide",
							 | 
						||
| 
								 | 
							
								        "A guide to setting up the Blasphemous randomizer connected to an Archipelago Multiworld",
							 | 
						||
| 
								 | 
							
								        "English",
							 | 
						||
| 
								 | 
							
								        "setup_en.md",
							 | 
						||
| 
								 | 
							
								        "setup/en",
							 | 
						||
| 
								 | 
							
								        ["TRPG"]
							 | 
						||
| 
								 | 
							
								    )]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BlasphemousWorld(World):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Blasphemous is a challenging Metroidvania set in the cursed land of Cvstodia. Play as the Penitent One, trapped
							 | 
						||
| 
								 | 
							
								    in an endless cycle of death and rebirth, and free the world from it's terrible fate in your quest to break
							 | 
						||
| 
								 | 
							
								    your eternal damnation!
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    game: str = "Blasphemous"
							 | 
						||
| 
								 | 
							
								    web = BlasphemousWeb()
							 | 
						||
| 
								 | 
							
								    data_version: 1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    item_name_to_id = {item["name"]: (base_id + index) for index, item in enumerate(item_table)}
							 | 
						||
| 
								 | 
							
								    location_name_to_id = {loc["name"]: (base_id + index) for index, loc in enumerate(location_table)}
							 | 
						||
| 
								 | 
							
								    location_name_to_game_id = {loc["name"]: loc["game_id"] for loc in location_table}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    item_name_groups = group_table
							 | 
						||
| 
								 | 
							
								    option_definitions = blasphemous_options
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def set_rules(self):
							 | 
						||
| 
								 | 
							
								        rules(self)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def create_item(self, name: str) -> "BlasphemousItem":
							 | 
						||
| 
								 | 
							
								        item_id: int = self.item_name_to_id[name]
							 | 
						||
| 
								 | 
							
								        id = item_id - base_id
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return BlasphemousItem(name, item_table[id]["classification"], item_id, player=self.player)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def create_event(self, event: str):
							 | 
						||
| 
								 | 
							
								        return BlasphemousItem(event, ItemClassification.progression_skip_balancing, None, self.player)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_filler_item_name(self) -> str:
							 | 
						||
| 
								 | 
							
								        return self.multiworld.random.choice(tears_set)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def generate_basic(self):
							 | 
						||
| 
								 | 
							
								        placed_items = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        placed_items.extend(Vanilla.unrandomized_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.reliquary_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(reliquary_set)
							 | 
						||
| 
								 | 
							
								        elif self.multiworld.reliquary_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.append("Tears of Atonement (250)")
							 | 
						||
| 
								 | 
							
								            placed_items.append("Tears of Atonement (300)")
							 | 
						||
| 
								 | 
							
								            placed_items.append("Tears of Atonement (500)")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.cherub_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            for i in range(38):
							 | 
						||
| 
								 | 
							
								                placed_items.append("Child of Moonlight")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.life_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            for i in range(6):
							 | 
						||
| 
								 | 
							
								                placed_items.append("Life Upgrade")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.fervour_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            for i in range(6):
							 | 
						||
| 
								 | 
							
								                placed_items.append("Fervour Upgrade")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.sword_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            for i in range(7):
							 | 
						||
| 
								 | 
							
								                placed_items.append("Mea Culpa Upgrade")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.blessing_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.blessing_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.dungeon_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.dungeon_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.tirso_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.tirso_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.miriam_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.append("Cantina of the Blue Rose")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.redento_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.redento_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.jocinero_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.jocinero_dict.values())
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.altasgracias_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.altasgracias_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.tentudia_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.tentudia_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.gemino_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.gemino_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.guilt_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.append("Weight of True Guilt")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.ossuary_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.ossuary_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.boss_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.boss_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.wound_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.wound_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.mask_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.mask_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.eye_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.eye_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.herb_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.herb_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.church_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.church_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.shop_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.shop_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if self.multiworld.thorn_shuffle[self.player] == 2:
							 | 
						||
| 
								 | 
							
								            for i in range(8):
							 | 
						||
| 
								 | 
							
								                placed_items.append("Thorn Upgrade")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.candle_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.candle_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if self.multiworld.start_wheel[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.append("The Young Mason's Wheel")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.skill_randomizer[self.player]:
							 | 
						||
| 
								 | 
							
								            placed_items.extend(Vanilla.skill_dict.values())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        counter = Counter(placed_items)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pool = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for item in item_table:
							 | 
						||
| 
								 | 
							
								            count = item["count"] - counter[item["name"]]
							 | 
						||
| 
								 | 
							
								            
							 | 
						||
| 
								 | 
							
								            if count <= 0:
							 | 
						||
| 
								 | 
							
								                continue
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                for i in range(count):
							 | 
						||
| 
								 | 
							
								                    pool.append(self.create_item(item["name"]))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.multiworld.itempool += pool
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def pre_fill(self):
							 | 
						||
| 
								 | 
							
								        self.place_items_from_dict(Vanilla.unrandomized_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.cherub_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_set(Vanilla.cherub_set, "Child of Moonlight")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.life_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_set(Vanilla.life_set, "Life Upgrade")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.fervour_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_set(Vanilla.fervour_set, "Fervour Upgrade")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.sword_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_set(Vanilla.sword_set, "Mea Culpa Upgrade")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.blessing_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.blessing_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.dungeon_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.dungeon_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.tirso_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.tirso_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.miriam_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.multiworld.get_location("AtTotS: Miriam's gift", self.player)\
							 | 
						||
| 
								 | 
							
								                .place_locked_item(self.create_item("Cantina of the Blue Rose"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.redento_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.redento_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.jocinero_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.jocinero_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.altasgracias_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.altasgracias_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.tentudia_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.tentudia_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.gemino_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.gemino_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.guilt_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.multiworld.get_location("GotP: Confessor Dungeon room", self.player)\
							 | 
						||
| 
								 | 
							
								                .place_locked_item(self.create_item("Weight of True Guilt"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.ossuary_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.ossuary_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.boss_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.boss_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.wound_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.wound_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.mask_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.mask_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.eye_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.eye_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.herb_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.herb_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.church_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.church_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.shop_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.shop_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if self.multiworld.thorn_shuffle[self.player] == 2:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_set(Vanilla.thorn_set, "Thorn Upgrade")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.candle_shuffle[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.candle_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if self.multiworld.start_wheel[self.player]:
							 | 
						||
| 
								 | 
							
								            self.multiworld.get_location("BotSS: Beginning gift", self.player)\
							 | 
						||
| 
								 | 
							
								                .place_locked_item(self.create_item("The Young Mason's Wheel"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self.multiworld.skill_randomizer[self.player]:
							 | 
						||
| 
								 | 
							
								            self.place_items_from_dict(Vanilla.skill_dict)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if self.multiworld.thorn_shuffle[self.player] == 1:
							 | 
						||
| 
								 | 
							
								            self.multiworld.local_items[self.player].value.add("Thorn Upgrade")
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def place_items_from_set(self, location_set: Set[str], name: str):
							 | 
						||
| 
								 | 
							
								        for loc in location_set:
							 | 
						||
| 
								 | 
							
								            self.multiworld.get_location(loc, self.player)\
							 | 
						||
| 
								 | 
							
								                .place_locked_item(self.create_item(name))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    def place_items_from_dict(self, option_dict: Dict[str, str]):
							 | 
						||
| 
								 | 
							
								        for loc, item in option_dict.items():
							 | 
						||
| 
								 | 
							
								            self.multiworld.get_location(loc, self.player)\
							 | 
						||
| 
								 | 
							
								                .place_locked_item(self.create_item(item))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def create_regions(self) -> None:
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        player = self.player
							 | 
						||
| 
								 | 
							
								        world = self.multiworld
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        region_table: Dict[str, Region] = {
							 | 
						||
| 
								 | 
							
								            "menu"    : Region("Menu", player, world),
							 | 
						||
| 
								 | 
							
								            "albero"  : Region("Albero", player, world),
							 | 
						||
| 
								 | 
							
								            "attots"  : Region("All the Tears of the Sea", player, world),
							 | 
						||
| 
								 | 
							
								            "ar"      : Region("Archcathedral Rooftops", player, world),
							 | 
						||
| 
								 | 
							
								            "bottc"   : Region("Bridge of the Three Cavalries", player, world),
							 | 
						||
| 
								 | 
							
								            "botss"   : Region("Brotherhood of the Silent Sorrow", player, world),
							 | 
						||
| 
								 | 
							
								            "coolotcv": Region("Convent of Our Lady of the Charred Visage", player, world),
							 | 
						||
| 
								 | 
							
								            "dohh"    : Region("Deambulatory of His Holiness", player, world),
							 | 
						||
| 
								 | 
							
								            "dc"      : Region("Desecrated Cistern", player, world),
							 | 
						||
| 
								 | 
							
								            "eos"     : Region("Echoes of Salt", player, world),
							 | 
						||
| 
								 | 
							
								            "ft"      : Region("Ferrous Tree", player, world),
							 | 
						||
| 
								 | 
							
								            "gotp"    : Region("Graveyard of the Peaks", player, world),
							 | 
						||
| 
								 | 
							
								            "ga"      : Region("Grievance Ascends", player, world),
							 | 
						||
| 
								 | 
							
								            "hotd"    : Region("Hall of the Dawning", player, world),
							 | 
						||
| 
								 | 
							
								            "jondo"   : Region("Jondo", player, world),
							 | 
						||
| 
								 | 
							
								            "kottw"   : Region("Knot of the Three Words", player, world),
							 | 
						||
| 
								 | 
							
								            "lotnw"   : Region("Library of the Negated Words", player, world),
							 | 
						||
| 
								 | 
							
								            "md"      : Region("Mercy Dreams", player, world),
							 | 
						||
| 
								 | 
							
								            "mom"     : Region("Mother of Mothers", player, world),
							 | 
						||
| 
								 | 
							
								            "moted"   : Region("Mountains of the Endless Dusk", player, world),
							 | 
						||
| 
								 | 
							
								            "mah"     : Region("Mourning and Havoc", player, world),
							 | 
						||
| 
								 | 
							
								            "potss"   : Region("Patio of the Silent Steps", player, world),
							 | 
						||
| 
								 | 
							
								            "petrous" : Region("Petrous", player, world),
							 | 
						||
| 
								 | 
							
								            "thl"     : Region("The Holy Line", player, world),
							 | 
						||
| 
								 | 
							
								            "trpots"  : Region("The Resting Place of the Sister", player, world),
							 | 
						||
| 
								 | 
							
								            "tsc"     : Region("The Sleeping Canvases", player, world),
							 | 
						||
| 
								 | 
							
								            "wothp"   : Region("Wall of the Holy Prohibitions", player, world),
							 | 
						||
| 
								 | 
							
								            "wotbc"   : Region("Wasteland of the Buried Churches", player, world),
							 | 
						||
| 
								 | 
							
								            "wotw"    : Region("Where Olive Trees Wither", player, world),
							 | 
						||
| 
								 | 
							
								            "dungeon" : Region("Dungeons", player, world)
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for rname, reg in region_table.items():
							 | 
						||
| 
								 | 
							
								            world.regions.append(reg)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            for ename, exits in region_exit_table.items():
							 | 
						||
| 
								 | 
							
								                if ename == rname:
							 | 
						||
| 
								 | 
							
								                    for i in exits:
							 | 
						||
| 
								 | 
							
								                        ent = Entrance(player, i, reg)
							 | 
						||
| 
								 | 
							
								                        reg.exits.append(ent)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        for e, r in exit_lookup_table.items():
							 | 
						||
| 
								 | 
							
								                            if i == e:
							 | 
						||
| 
								 | 
							
								                                ent.connect(region_table[r])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for loc in location_table:
							 | 
						||
| 
								 | 
							
								            id = base_id + location_table.index(loc)
							 | 
						||
| 
								 | 
							
								            region_table[loc["region"]].locations\
							 | 
						||
| 
								 | 
							
								                .append(BlasphemousLocation(self.player, loc["name"], id, region_table[loc["region"]]))
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        victory = Location(self.player, "His Holiness Escribar", None, self.multiworld.get_region("Deambulatory of His Holiness", self.player))
							 | 
						||
| 
								 | 
							
								        victory.place_locked_item(self.create_event("Victory"))
							 | 
						||
| 
								 | 
							
								        self.multiworld.get_region("Deambulatory of His Holiness", self.player).locations.append(victory)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if self.multiworld.ending[self.player].value == 1:
							 | 
						||
| 
								 | 
							
								            set_rule(victory, lambda state: state.has("Thorn Upgrade", player, 8))
							 | 
						||
| 
								 | 
							
								        elif self.multiworld.ending[self.player].value == 2:
							 | 
						||
| 
								 | 
							
								            set_rule(victory, lambda state: state.has("Thorn Upgrade", player, 8) and \
							 | 
						||
| 
								 | 
							
								                state.has("Holy Wound of Abnegation", player))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    def fill_slot_data(self) -> Dict[str, Any]:
							 | 
						||
| 
								 | 
							
								        slot_data: Dict[str, Any] = {}
							 | 
						||
| 
								 | 
							
								        locations = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for loc in self.multiworld.get_filled_locations(self.player):
							 | 
						||
| 
								 | 
							
								            if loc.name == "His Holiness Escribar":
							 | 
						||
| 
								 | 
							
								                continue
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                data = {
							 | 
						||
| 
								 | 
							
								                    "id": self.location_name_to_game_id[loc.name],
							 | 
						||
| 
								 | 
							
								                    "ap_id": loc.address,
							 | 
						||
| 
								 | 
							
								                    "name": loc.item.name,
							 | 
						||
| 
								 | 
							
								                    "player_name": self.multiworld.player_name[loc.item.player]
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if loc.name in shop_set:
							 | 
						||
| 
								 | 
							
								                    data["type"] = loc.item.classification.name
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                locations.append(data)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        config = {
							 | 
						||
| 
								 | 
							
								            "versionCreated": "AP",
							 | 
						||
| 
								 | 
							
								            "general": {
							 | 
						||
| 
								 | 
							
								                "teleportationAlwaysUnlocked": bool(self.multiworld.prie_dieu_warp[self.player].value),
							 | 
						||
| 
								 | 
							
								                "skipCutscenes": bool(self.multiworld.skip_cutscenes[self.player].value),
							 | 
						||
| 
								 | 
							
								                "enablePenitence": bool(self.multiworld.penitence[self.player].value),
							 | 
						||
| 
								 | 
							
								                "hardMode": False,
							 | 
						||
| 
								 | 
							
								                "customSeed": 0,
							 | 
						||
| 
								 | 
							
								                "allowHints": bool(self.multiworld.corpse_hints[self.player].value)
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            "items": {
							 | 
						||
| 
								 | 
							
								                "type": 1,
							 | 
						||
| 
								 | 
							
								                "lungDamage": False,
							 | 
						||
| 
								 | 
							
								                "disableNPCDeath": True,
							 | 
						||
| 
								 | 
							
								                "startWithWheel": bool(self.multiworld.start_wheel[self.player].value),
							 | 
						||
| 
								 | 
							
								                "shuffleReliquaries": bool(self.multiworld.reliquary_shuffle[self.player].value)
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            "enemies": {
							 | 
						||
| 
								 | 
							
								                "type": self.multiworld.enemy_randomizer[self.player].value,
							 | 
						||
| 
								 | 
							
								                "maintainClass": bool(self.multiworld.enemy_groups[self.player].value),
							 | 
						||
| 
								 | 
							
								                "areaScaling": bool(self.multiworld.enemy_scaling[self.player].value)
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            "prayers": {
							 | 
						||
| 
								 | 
							
								                "type": 0,
							 | 
						||
| 
								 | 
							
								                "removeMirabis": False
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            "doors": {
							 | 
						||
| 
								 | 
							
								                "type": 0
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            "debug": {
							 | 
						||
| 
								 | 
							
								                "type": 0
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								        slot_data = {
							 | 
						||
| 
								 | 
							
								            "locations": locations,
							 | 
						||
| 
								 | 
							
								            "cfg": config,
							 | 
						||
| 
								 | 
							
								            "ending": self.multiworld.ending[self.player].value,
							 | 
						||
| 
								 | 
							
								            "death_link": bool(self.multiworld.death_link[self.player].value)
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								        return slot_data
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BlasphemousItem(Item):
							 | 
						||
| 
								 | 
							
								    game: str = "Blasphemous"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class BlasphemousLocation(Location):
							 | 
						||
| 
								 | 
							
								    game: str = "Blasphemous"
							 |