Files
Archipelago/worlds/ahit/Regions.py
CookieCat b5475ac242 a
2023-08-29 12:38:29 -04:00

775 lines
36 KiB
Python

from worlds.AutoWorld import World
from BaseClasses import Region, Entrance, ItemClassification, Location
from .Locations import HatInTimeLocation, location_table, storybook_pages, event_locs, is_location_valid, shop_locations
from .Items import HatInTimeItem
from .Types import ChapterIndex
import typing
from .Rules import set_rift_rules
# ChapterIndex: region
chapter_regions = {
ChapterIndex.SPACESHIP: "Spaceship",
ChapterIndex.MAFIA: "Mafia Town",
ChapterIndex.BIRDS: "Battle of the Birds",
ChapterIndex.SUBCON: "Subcon Forest",
ChapterIndex.ALPINE: "Alpine Skyline",
ChapterIndex.FINALE: "Time's End",
ChapterIndex.CRUISE: "The Arctic Cruise",
ChapterIndex.METRO: "Nyakuza Metro",
}
# entrance: region
act_entrances = {
"Welcome to Mafia Town": "Mafia Town - Act 1",
"Barrel Battle": "Mafia Town - Act 2",
"She Came from Outer Space": "Mafia Town - Act 3",
"Down with the Mafia!": "Mafia Town - Act 4",
"Cheating the Race": "Mafia Town - Act 5",
"Heating Up Mafia Town": "Mafia Town - Act 6",
"The Golden Vault": "Mafia Town - Act 7",
"Dead Bird Studio": "Battle of the Birds - Act 1",
"Murder on the Owl Express": "Battle of the Birds - Act 2",
"Picture Perfect": "Battle of the Birds - Act 3",
"Train Rush": "Battle of the Birds - Act 4",
"The Big Parade": "Battle of the Birds - Act 5",
"Award Ceremony": "Battle of the Birds - Finale A",
"Dead Bird Studio Basement": "Battle of the Birds - Finale B",
"Contractual Obligations": "Subcon Forest - Act 1",
"The Subcon Well": "Subcon Forest - Act 2",
"Toilet of Doom": "Subcon Forest - Act 3",
"Queen Vanessa's Manor": "Subcon Forest - Act 4",
"Mail Delivery Service": "Subcon Forest - Act 5",
"Your Contract has Expired": "Subcon Forest - Finale",
"Alpine Free Roam": "Alpine Skyline - Free Roam",
"The Illness has Spread": "Alpine Skyline - Finale",
"The Finale": "Time's End - Act 1",
"Bon Voyage!": "The Arctic Cruise - Act 1",
"Ship Shape": "The Arctic Cruise - Act 2",
"Rock the Boat": "The Arctic Cruise - Finale",
"Nyakuza Free Roam": "Nyakuza Metro - Free Roam",
"Rush Hour": "Nyakuza Metro - Finale",
}
act_chapters = {
"Time Rift - Gallery": "Spaceship",
"Time Rift - The Lab": "Spaceship",
"Welcome to Mafia Town": "Mafia Town",
"Barrel Battle": "Mafia Town",
"She Came from Outer Space": "Mafia Town",
"Down with the Mafia!": "Mafia Town",
"Cheating the Race": "Mafia Town",
"Heating Up Mafia Town": "Mafia Town",
"The Golden Vault": "Mafia Town",
"Time Rift - Mafia of Cooks": "Mafia Town",
"Time Rift - Sewers": "Mafia Town",
"Time Rift - Bazaar": "Mafia Town",
"Dead Bird Studio": "Battle of the Birds",
"Murder on the Owl Express": "Battle of the Birds",
"Picture Perfect": "Battle of the Birds",
"Train Rush": "Battle of the Birds",
"The Big Parade": "Battle of the Birds",
"Award Ceremony": "Battle of the Birds",
"Dead Bird Studio Basement": "Battle of the Birds",
"Time Rift - Dead Bird Studio": "Battle of the Birds",
"Time Rift - The Owl Express": "Battle of the Birds",
"Time Rift - The Moon": "Battle of the Birds",
"Contractual Obligations": "Subcon Forest",
"The Subcon Well": "Subcon Forest",
"Toilet of Doom": "Subcon Forest",
"Queen Vanessa's Manor": "Subcon Forest",
"Mail Delivery Service": "Subcon Forest",
"Your Contract has Expired": "Subcon Forest",
"Time Rift - Sleepy Subcon": "Subcon Forest",
"Time Rift - Pipe": "Subcon Forest",
"Time Rift - Village": "Subcon Forest",
"Alpine Free Roam": "Alpine Skyline",
"The Illness has Spread": "Alpine Skyline",
"Time Rift - Alpine Skyline": "Alpine Skyline",
"Time Rift - The Twilight Bell": "Alpine Skyline",
"Time Rift - Curly Tail Trail": "Alpine Skyline",
"The Finale": "Time's End",
"Time Rift - Tour": "Time's End",
"Bon Voyage!": "The Arctic Cruise",
"Ship Shape": "The Arctic Cruise",
"Rock the Boat": "The Arctic Cruise",
"Time Rift - Balcony": "The Arctic Cruise",
"Time Rift - Deep Sea": "The Arctic Cruise",
"Nyakuza Free Roam": "Nyakuza Metro",
"Rush Hour": "Nyakuza Metro",
"Time Rift - Rumbi Factory": "Nyakuza Metro",
}
# region: list[Region]
rift_access_regions = {
"Time Rift - Gallery": ["Spaceship"],
"Time Rift - The Lab": ["Spaceship"],
"Time Rift - Sewers": ["Welcome to Mafia Town", "Barrel Battle", "She Came from Outer Space",
"Down with the Mafia!", "Cheating the Race", "Heating Up Mafia Town",
"The Golden Vault"],
"Time Rift - Bazaar": ["Welcome to Mafia Town", "Barrel Battle", "She Came from Outer Space",
"Down with the Mafia!", "Cheating the Race", "Heating Up Mafia Town",
"The Golden Vault"],
"Time Rift - Mafia of Cooks": ["Welcome to Mafia Town", "Barrel Battle", "She Came from Outer Space",
"Down with the Mafia!", "Cheating the Race", "The Golden Vault"],
"Time Rift - The Owl Express": ["Murder on the Owl Express"],
"Time Rift - The Moon": ["Picture Perfect", "The Big Parade"],
"Time Rift - Dead Bird Studio": ["Dead Bird Studio", "Dead Bird Studio Basement"],
"Time Rift - Pipe": ["Contractual Obligations", "The Subcon Well",
"Toilet of Doom", "Queen Vanessa's Manor",
"Mail Delivery Service"],
"Time Rift - Village": ["Contractual Obligations", "The Subcon Well",
"Toilet of Doom", "Queen Vanessa's Manor",
"Mail Delivery Service"],
"Time Rift - Sleepy Subcon": ["Contractual Obligations", "The Subcon Well",
"Toilet of Doom", "Queen Vanessa's Manor",
"Mail Delivery Service"],
"Time Rift - The Twilight Bell": ["Alpine Free Roam"],
"Time Rift - Curly Tail Trail": ["Alpine Free Roam"],
"Time Rift - Alpine Skyline": ["Alpine Free Roam", "The Illness has Spread"],
"Time Rift - Tour": ["Time's End"],
"Time Rift - Balcony": ["Cruise Ship"],
"Time Rift - Deep Sea": ["Bon Voyage!"],
"Time Rift - Rumbi Factory": ["Nyakuza Free Roam"],
}
# Hat_ChapterActInfo, from the game files to be used in act shuffle
chapter_act_info = {
"Time Rift - Gallery": "hatintime_chapterinfo.spaceship.Spaceship_WaterRift_Gallery",
"Time Rift - The Lab": "hatintime_chapterinfo.spaceship.Spaceship_WaterRift_MailRoom",
"Welcome to Mafia Town": "hatintime_chapterinfo.MafiaTown.MafiaTown_Welcome",
"Barrel Battle": "hatintime_chapterinfo.MafiaTown.MafiaTown_BarrelBattle",
"She Came from Outer Space": "hatintime_chapterinfo.MafiaTown.MafiaTown_AlienChase",
"Down with the Mafia!": "hatintime_chapterinfo.MafiaTown.MafiaTown_MafiaBoss",
"Cheating the Race": "hatintime_chapterinfo.MafiaTown.MafiaTown_Race",
"Heating Up Mafia Town": "hatintime_chapterinfo.MafiaTown.MafiaTown_Lava",
"The Golden Vault": "hatintime_chapterinfo.MafiaTown.MafiaTown_GoldenVault",
"Time Rift - Mafia of Cooks": "hatintime_chapterinfo.MafiaTown.MafiaTown_CaveRift_Mafia",
"Time Rift - Sewers": "hatintime_chapterinfo.MafiaTown.MafiaTown_WaterRift_Easy",
"Time Rift - Bazaar": "hatintime_chapterinfo.MafiaTown.MafiaTown_WaterRift_Hard",
"Dead Bird Studio": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_DeadBirdStudio",
"Murder on the Owl Express": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_Murder",
"Picture Perfect": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_PicturePerfect",
"Train Rush": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_TrainRush",
"The Big Parade": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_Parade",
"Award Ceremony": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_AwardCeremony",
"Dead Bird Studio Basement": "DeadBirdBasement", # Dead Bird Studio Basement has no ChapterActInfo
"Time Rift - Dead Bird Studio": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_CaveRift_Basement",
"Time Rift - The Owl Express": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_WaterRift_Panels",
"Time Rift - The Moon": "hatintime_chapterinfo.BattleOfTheBirds.BattleOfTheBirds_WaterRift_Parade",
"Contractual Obligations": "hatintime_chapterinfo.subconforest.SubconForest_IceWall",
"The Subcon Well": "hatintime_chapterinfo.subconforest.SubconForest_Cave",
"Toilet of Doom": "hatintime_chapterinfo.subconforest.SubconForest_Toilet",
"Queen Vanessa's Manor": "hatintime_chapterinfo.subconforest.SubconForest_Manor",
"Mail Delivery Service": "hatintime_chapterinfo.subconforest.SubconForest_MailDelivery",
"Your Contract has Expired": "hatintime_chapterinfo.subconforest.SubconForest_SnatcherBoss",
"Time Rift - Sleepy Subcon": "hatintime_chapterinfo.subconforest.SubconForest_CaveRift_Raccoon",
"Time Rift - Pipe": "hatintime_chapterinfo.subconforest.SubconForest_WaterRift_Hookshot",
"Time Rift - Village": "hatintime_chapterinfo.subconforest.SubconForest_WaterRift_Dwellers",
"Alpine Free Roam": "hatintime_chapterinfo.AlpineSkyline.AlpineSkyline_IntroMountain",
"The Illness has Spread": "hatintime_chapterinfo.AlpineSkyline.AlpineSkyline_Finale",
"Time Rift - Alpine Skyline": "hatintime_chapterinfo.AlpineSkyline.AlpineSkyline_CaveRift_Alpine",
"Time Rift - The Twilight Bell": "hatintime_chapterinfo.AlpineSkyline.AlpineSkyline_WaterRift_Goats",
"Time Rift - Curly Tail Trail": "hatintime_chapterinfo.AlpineSkyline.AlpineSkyline_WaterRift_Cats",
"The Finale": "hatintime_chapterinfo.TheFinale.TheFinale_FinalBoss",
"Time Rift - Tour": "hatintime_chapterinfo_dlc1.spaceship.CaveRift_Tour",
"Bon Voyage!": "hatintime_chapterinfo_dlc1.Cruise.Cruise_Boarding",
"Ship Shape": "hatintime_chapterinfo_dlc1.Cruise.Cruise_Working",
"Rock the Boat": "hatintime_chapterinfo_dlc1.Cruise.Cruise_Sinking",
"Time Rift - Balcony": "hatintime_chapterinfo_dlc1.Cruise.Cruise_WaterRift_Slide",
"Time Rift - Deep Sea": "hatintime_chapterinfo_dlc1.Cruise.Cruise_CaveRift",
"Nyakuza Free Roam": "hatintime_chapterinfo_dlc2.metro.Metro_FreeRoam",
"Rush Hour": "hatintime_chapterinfo_dlc2.metro.Metro_Escape",
"Time Rift - Rumbi Factory": "hatintime_chapterinfo_dlc2.metro.Metro_RumbiFactory"
}
# Guarantee that the first level a player can access is a location dense area beatable with no items
guaranteed_first_acts = [
"Welcome to Mafia Town",
"Barrel Battle",
"She Came from Outer Space",
"Down with the Mafia!",
"Heating Up Mafia Town", # Removed in umbrella logic
"The Golden Vault",
"Contractual Obligations", # Removed in painting logic
"Queen Vanessa's Manor", # Removed in umbrella/painting logic
]
purple_time_rifts = [
"Time Rift - Mafia of Cooks",
"Time Rift - Dead Bird Studio",
"Time Rift - Sleepy Subcon",
"Time Rift - Alpine Skyline",
"Time Rift - Deep Sea",
"Time Rift - Tour",
"Time Rift - Rumbi Factory",
]
chapter_finales = [
"Dead Bird Studio Basement",
"Your Contract has Expired",
"The Illness has Spread",
"Rock the Boat",
"Rush Hour",
]
# Acts blacklisted in act shuffle
# entrance: region
blacklisted_acts = {
"Battle of the Birds - Finale A": "Award Ceremony",
"Time's End - Act 1": "The Finale",
}
def create_regions(world: World):
w = world
mw = world.multiworld
p = world.player
# ------------------------------------------- HUB -------------------------------------------------- #
menu = create_region(w, "Menu")
spaceship = create_region_and_connect(w, "Spaceship", "Save File -> Spaceship", menu)
create_rift_connections(w, create_region(w, "Time Rift - Gallery"))
create_rift_connections(w, create_region(w, "Time Rift - The Lab"))
# ------------------------------------------- MAFIA TOWN ------------------------------------------- #
mafia_town = create_region_and_connect(w, "Mafia Town", "Telescope -> Mafia Town", spaceship)
mt_act1 = create_region_and_connect(w, "Welcome to Mafia Town", "Mafia Town - Act 1", mafia_town)
mt_act2 = create_region_and_connect(w, "Barrel Battle", "Mafia Town - Act 2", mafia_town)
mt_act3 = create_region_and_connect(w, "She Came from Outer Space", "Mafia Town - Act 3", mafia_town)
mt_act4 = create_region_and_connect(w, "Down with the Mafia!", "Mafia Town - Act 4", mafia_town)
mt_act6 = create_region_and_connect(w, "Heating Up Mafia Town", "Mafia Town - Act 6", mafia_town)
mt_act5 = create_region_and_connect(w, "Cheating the Race", "Mafia Town - Act 5", mafia_town)
mt_act7 = create_region_and_connect(w, "The Golden Vault", "Mafia Town - Act 7", mafia_town)
# ------------------------------------------- BOTB ------------------------------------------------- #
botb = create_region_and_connect(w, "Battle of the Birds", "Telescope -> Battle of the Birds", spaceship)
dbs = create_region_and_connect(w, "Dead Bird Studio", "Battle of the Birds - Act 1", botb)
create_region_and_connect(w, "Murder on the Owl Express", "Battle of the Birds - Act 2", botb)
create_region_and_connect(w, "Picture Perfect", "Battle of the Birds - Act 3", botb)
create_region_and_connect(w, "Train Rush", "Battle of the Birds - Act 4", botb)
create_region_and_connect(w, "The Big Parade", "Battle of the Birds - Act 5", botb)
create_region_and_connect(w, "Award Ceremony", "Battle of the Birds - Finale A", botb)
create_region_and_connect(w, "Dead Bird Studio Basement", "Battle of the Birds - Finale B", botb)
create_rift_connections(w, create_region(w, "Time Rift - Dead Bird Studio"))
create_rift_connections(w, create_region(w, "Time Rift - The Owl Express"))
create_rift_connections(w, create_region(w, "Time Rift - The Moon"))
# Items near the Dead Bird Studio elevator can be reached from the basement act
ev_area = create_region_and_connect(w, "Dead Bird Studio - Elevator Area", "DBS -> Elevator Area", dbs)
connect_regions(mw.get_region("Dead Bird Studio Basement", p), ev_area, "DBS Basement -> Elevator Area", p)
# ------------------------------------------- SUBCON FOREST --------------------------------------- #
subcon_forest = create_region_and_connect(w, "Subcon Forest", "Telescope -> Subcon Forest", spaceship)
sf_act1 = create_region_and_connect(w, "Contractual Obligations", "Subcon Forest - Act 1", subcon_forest)
sf_act2 = create_region_and_connect(w, "The Subcon Well", "Subcon Forest - Act 2", subcon_forest)
sf_act3 = create_region_and_connect(w, "Toilet of Doom", "Subcon Forest - Act 3", subcon_forest)
sf_act4 = create_region_and_connect(w, "Queen Vanessa's Manor", "Subcon Forest - Act 4", subcon_forest)
sf_act5 = create_region_and_connect(w, "Mail Delivery Service", "Subcon Forest - Act 5", subcon_forest)
create_region_and_connect(w, "Your Contract has Expired", "Subcon Forest - Finale", subcon_forest)
# ------------------------------------------- ALPINE SKYLINE ------------------------------------------ #
alpine_skyline = create_region_and_connect(w, "Alpine Skyline", "Telescope -> Alpine Skyline", spaceship)
alpine_freeroam = create_region_and_connect(w, "Alpine Free Roam", "Alpine Skyline - Free Roam", alpine_skyline)
alpine_area = create_region_and_connect(w, "Alpine Skyline Area", "AFR -> Alpine Skyline Area", alpine_freeroam)
goat_village = create_region_and_connect(w, "Goat Village", "ASA -> Goat Village", alpine_area)
create_region_and_connect(w, "The Birdhouse", "-> The Birdhouse", alpine_area)
create_region_and_connect(w, "The Lava Cake", "-> The Lava Cake", alpine_area)
create_region_and_connect(w, "The Windmill", "-> The Windmill", alpine_area)
create_region_and_connect(w, "The Twilight Bell", "-> The Twilight Bell", alpine_area)
illness = create_region_and_connect(w, "The Illness has Spread", "Alpine Skyline - Finale", alpine_skyline)
connect_regions(illness, alpine_area, "TIHS -> Alpine Skyline Area", p)
connect_regions(illness, goat_village, "TIHS -> Goat Village", p)
create_rift_connections(w, create_region(w, "Time Rift - Alpine Skyline"))
create_rift_connections(w, create_region(w, "Time Rift - The Twilight Bell"))
create_rift_connections(w, create_region(w, "Time Rift - Curly Tail Trail"))
# ------------------------------------------- OTHER -------------------------------------------------- #
mt_area: Region = create_region(w, "Mafia Town Area")
mt_area_humt: Region = create_region(w, "Mafia Town Area (HUMT)")
connect_regions(mt_area, mt_area_humt, "MT Area -> MT Area (HUMT)", p)
connect_regions(mt_act1, mt_area, "Mafia Town Entrance WTMT", p)
connect_regions(mt_act2, mt_area, "Mafia Town Entrance BB", p)
connect_regions(mt_act3, mt_area, "Mafia Town Entrance SCFOS", p)
connect_regions(mt_act4, mt_area, "Mafia Town Entrance DWTM", p)
connect_regions(mt_act5, mt_area, "Mafia Town Entrance CTR", p)
connect_regions(mt_act6, mt_area_humt, "Mafia Town Entrance HUMT", p)
connect_regions(mt_act7, mt_area, "Mafia Town Entrance TGV", p)
create_rift_connections(w, create_region(w, "Time Rift - Mafia of Cooks"))
create_rift_connections(w, create_region(w, "Time Rift - Sewers"))
create_rift_connections(w, create_region(w, "Time Rift - Bazaar"))
sf_area: Region = create_region(w, "Subcon Forest Area")
connect_regions(sf_act1, sf_area, "Subcon Forest Entrance CO", p)
connect_regions(sf_act2, sf_area, "Subcon Forest Entrance SW", p)
connect_regions(sf_act3, sf_area, "Subcon Forest Entrance TOD", p)
connect_regions(sf_act4, sf_area, "Subcon Forest Entrance QVM", p)
connect_regions(sf_act5, sf_area, "Subcon Forest Entrance MDS", p)
create_rift_connections(w, create_region(w, "Time Rift - Sleepy Subcon"))
create_rift_connections(w, create_region(w, "Time Rift - Pipe"))
create_rift_connections(w, create_region(w, "Time Rift - Village"))
badge_seller = create_badge_seller(w)
connect_regions(mt_area, badge_seller, "MT Area -> Badge Seller", p)
connect_regions(mt_area_humt, badge_seller, "MT Area (HUMT) -> Badge Seller", p)
connect_regions(sf_area, badge_seller, "SF Area -> Badge Seller", p)
connect_regions(mw.get_region("Dead Bird Studio", p), badge_seller, "DBS -> Badge Seller", p)
connect_regions(mw.get_region("Picture Perfect", p), badge_seller, "PP -> Badge Seller", p)
connect_regions(mw.get_region("Train Rush", p), badge_seller, "TR -> Badge Seller", p)
connect_regions(mw.get_region("Goat Village", p), badge_seller, "GV -> Badge Seller", p)
times_end = create_region_and_connect(w, "Time's End", "Telescope -> Time's End", spaceship)
create_region_and_connect(w, "The Finale", "Time's End - Act 1", times_end)
# ------------------------------------------- DLC1 ------------------------------------------------- #
if mw.EnableDLC1[p].value > 0:
arctic_cruise = create_region_and_connect(w, "The Arctic Cruise", "Telescope -> The Arctic Cruise", spaceship)
cruise_ship = create_region(w, "Cruise Ship")
ac_act1 = create_region_and_connect(w, "Bon Voyage!", "The Arctic Cruise - Act 1", arctic_cruise)
ac_act2 = create_region_and_connect(w, "Ship Shape", "The Arctic Cruise - Act 2", arctic_cruise)
ac_act3 = create_region_and_connect(w, "Rock the Boat", "The Arctic Cruise - Finale", arctic_cruise)
connect_regions(ac_act1, cruise_ship, "Cruise Ship Entrance BV", p)
connect_regions(ac_act2, cruise_ship, "Cruise Ship Entrance SS", p)
connect_regions(ac_act3, cruise_ship, "Cruise Ship Entrance RTB", p)
create_rift_connections(w, create_region(w, "Time Rift - Balcony"))
create_rift_connections(w, create_region(w, "Time Rift - Deep Sea"))
create_rift_connections(w, create_region(w, "Time Rift - Tour"))
if mw.Tasksanity[p].value > 0:
create_tasksanity_locations(w)
# force recache
mw.get_region("Time Rift - Deep Sea", p)
connect_regions(mw.get_region("Cruise Ship", p), badge_seller, "CS -> Badge Seller", p)
if mw.EnableDLC2[p].value > 0:
nyakuza_metro = create_region_and_connect(w, "Nyakuza Metro", "Telescope -> Nyakuza Metro", spaceship)
metro_freeroam = create_region_and_connect(w, "Nyakuza Free Roam", "Nyakuza Metro - Free Roam", nyakuza_metro)
create_region_and_connect(w, "Rush Hour", "Nyakuza Metro - Finale", nyakuza_metro)
yellow = create_region_and_connect(w, "Yellow Overpass Station", "-> Yellow Overpass Station", metro_freeroam)
green = create_region_and_connect(w, "Green Clean Station", "-> Green Clean Station", metro_freeroam)
pink = create_region_and_connect(w, "Pink Paw Station", "-> Pink Paw Station", metro_freeroam)
create_region_and_connect(w, "Bluefin Tunnel", "-> Bluefin Tunnel", metro_freeroam) # No manhole
create_region_and_connect(w, "Yellow Overpass Manhole", "-> Yellow Overpass Manhole", yellow)
create_region_and_connect(w, "Green Clean Manhole", "-> Green Clean Manhole", green)
create_region_and_connect(w, "Pink Paw Manhole", "-> Pink Paw Manhole", pink)
create_rift_connections(w, create_region(w, "Time Rift - Rumbi Factory"))
create_thug_shops(w)
# force recache
mw.get_region("Time Rift - Sewers", p)
def create_rift_connections(world: World, region: Region):
i = 1
for name in rift_access_regions[region.name]:
act_region = world.multiworld.get_region(name, world.player)
entrance_name = "{name} Portal - Entrance {num}"
connect_regions(act_region, region, entrance_name.format(name=region.name, num=i), world.player)
i += 1
def create_tasksanity_locations(world: World):
ship_shape: Region = world.multiworld.get_region("Ship Shape", world.player)
id_start: int = 300204
for i in range(world.multiworld.TasksanityCheckCount[world.player].value):
location = HatInTimeLocation(world.player, format("Tasksanity Check %i" % (i+1)), id_start+i, ship_shape)
ship_shape.locations.append(location)
# world.location_name_to_id.setdefault(location.name, location.address)
def randomize_act_entrances(world: World):
region_list: typing.List[Region] = get_act_regions(world)
world.multiworld.random.shuffle(region_list)
separate_rifts: bool = bool(world.multiworld.ActRandomizer[world.player].value == 1)
for region in region_list.copy():
if (act_chapters[region.name] == "Alpine Skyline" or act_chapters[region.name] == "Nyakuza Metro") \
and "Time Rift" not in region.name:
region_list.remove(region)
region_list.append(region)
for region in region_list.copy():
if "Time Rift" in region.name:
region_list.remove(region)
region_list.append(region)
# Reverse the list, so we can do what we want to do first
region_list.reverse()
shuffled_list: typing.List[Region] = []
mapped_list: typing.List[Region] = []
rift_dict: typing.Dict[str, Region] = {}
first_chapter: Region = get_first_chapter_region(world)
has_guaranteed: bool = False
i: int = 0
while i < len(region_list):
region = region_list[i]
i += 1
# Get the first accessible act, so we can map that to something first
if not has_guaranteed:
if act_chapters[region.name] != first_chapter.name:
continue
if region.name not in act_entrances.keys() or "Act 1" not in act_entrances[region.name] \
and "Free Roam" not in act_entrances[region.name]:
continue
i = 0
# Already mapped to something else
if region in mapped_list:
continue
mapped_list.append(region)
# Look for candidates to map this act to
candidate_list: typing.List[Region] = []
for candidate in region_list:
if world.multiworld.VanillaAlpine[world.player].value > 0 and region.name == "Alpine Free Roam" \
or world.multiworld.VanillaAlpine[world.player].value == 2 and region.name == "The Illness has Spread":
candidate_list.append(region)
break
if world.multiworld.VanillaMetro[world.player].value > 0 and region.name == "Nyakuza Free Roam":
candidate_list.append(region)
break
if region.name == "Rush Hour":
if world.multiworld.EndGoal[world.player].value == 2 or \
world.multiworld.VanillaMetro[world.player].value == 2:
candidate_list.append(region)
break
# We're mapping something to the first act, make sure it is valid
if not has_guaranteed:
if candidate.name not in guaranteed_first_acts:
continue
# Not completable without Umbrella
if world.multiworld.UmbrellaLogic[world.player].value > 0 \
and (candidate.name == "Heating Up Mafia Town" or candidate.name == "Queen Vanessa's Manor"):
continue
# Subcon sphere 1 is too small without painting unlocks, and no acts are completable either
if world.multiworld.ShuffleSubconPaintings[world.player].value > 0 \
and "Subcon Forest" in act_entrances[candidate.name]:
continue
candidate_list.append(candidate)
has_guaranteed = True
break
# Already mapped onto something else
if candidate in shuffled_list:
continue
if separate_rifts:
# Don't map Time Rifts to normal acts
if "Time Rift" in region.name and "Time Rift" not in candidate.name:
continue
# Don't map normal acts to Time Rifts
if "Time Rift" not in region.name and "Time Rift" in candidate.name:
continue
# Separate purple rifts
if region.name in purple_time_rifts and candidate.name not in purple_time_rifts \
or region.name not in purple_time_rifts and candidate.name in purple_time_rifts:
continue
# Don't map Alpine to its own finale
if region.name == "The Illness has Spread" and candidate.name == "Alpine Free Roam":
continue
# Ditto for Metro
if region.name == "Rush Hour" and candidate.name == "Nyakuza Free Roam":
continue
# CTR entrance and Tour aren't a finale, but have a fuck ton of unlock requirements
if world.multiworld.NoFreeRoamFinale[world.player].value > 0 and "Free Roam" in candidate.name:
if region.name in chapter_finales or region.name == "Cheating the Race" \
or world.multiworld.EndGoal[world.player].value == 1 and region.name == "Time Rift - Tour":
continue
if region.name in rift_access_regions and candidate.name in rift_access_regions[region.name]:
continue
candidate_list.append(candidate)
candidate: Region = candidate_list[world.multiworld.random.randint(0, len(candidate_list)-1)]
shuffled_list.append(candidate)
# Vanilla
if candidate.name == region.name:
if region.name in rift_access_regions.keys():
rift_dict.setdefault(region.name, candidate)
world.update_chapter_act_info(region, candidate)
continue
if region.name in rift_access_regions.keys():
connect_time_rift(world, region, candidate)
rift_dict.setdefault(region.name, candidate)
else:
if candidate.name in rift_access_regions.keys():
for e in candidate.entrances.copy():
e.parent_region.exits.remove(e)
e.connected_region.entrances.remove(e)
del e.parent_region
del e.connected_region
entrance = world.multiworld.get_entrance(act_entrances[region.name], world.player)
reconnect_regions(entrance, world.multiworld.get_region(act_chapters[region.name], world.player), candidate)
world.update_chapter_act_info(region, candidate)
for name in blacklisted_acts.values():
if not is_act_blacklisted(world, name):
continue
region: Region = world.multiworld.get_region(name, world.player)
world.update_chapter_act_info(region, region)
set_rift_rules(world, rift_dict)
def connect_time_rift(world: World, time_rift: Region, exit_region: Region):
count: int = len(rift_access_regions[time_rift.name])
i: int = 1
while i <= count:
name = format("%s Portal - Entrance %i" % (time_rift.name, i))
entrance: Entrance = world.multiworld.get_entrance(name, world.player)
reconnect_regions(entrance, entrance.parent_region, exit_region)
i += 1
def get_act_regions(world: World) -> typing.List[Region]:
act_list: typing.List[Region] = []
for region in world.multiworld.get_regions(world.player):
if region.name in chapter_act_info.keys():
if not is_act_blacklisted(world, region.name):
act_list.append(region)
return act_list
def is_act_blacklisted(world: World, name: str) -> bool:
if name == "The Finale":
return world.multiworld.EndGoal[world.player].value == 1
return name in blacklisted_acts.values()
def create_region(world: World, name: str) -> Region:
reg = Region(name, world.player, world.multiworld)
for (key, data) in location_table.items():
if data.nyakuza_thug != "":
continue
if data.region == name:
if key in storybook_pages.keys() \
and world.multiworld.ShuffleStorybookPages[world.player].value == 0:
continue
location = HatInTimeLocation(world.player, key, data.id, reg)
reg.locations.append(location)
if location.name in shop_locations:
world.shop_locs.append(location.name)
world.multiworld.regions.append(reg)
return reg
def create_badge_seller(world: World) -> Region:
badge_seller = Region("Badge Seller", world.player, world.multiworld)
world.multiworld.regions.append(badge_seller)
count: int = 0
max_items: int = 0
if world.multiworld.BadgeSellerMaxItems[world.player].value > 0:
max_items = world.multiworld.random.randint(world.multiworld.BadgeSellerMinItems[world.player].value,
world.multiworld.BadgeSellerMaxItems[world.player].value)
if max_items <= 0:
world.badge_seller_count = 0
return badge_seller
for (key, data) in shop_locations.items():
if "Badge Seller" not in key:
continue
location = HatInTimeLocation(world.player, key, data.id, badge_seller)
badge_seller.locations.append(location)
world.shop_locs.append(location.name)
count += 1
if count >= max_items:
break
world.badge_seller_count = max_items
return badge_seller
def connect_regions(start_region: Region, exit_region: Region, entrancename: str, player: int):
entrance = Entrance(player, entrancename, start_region)
start_region.exits.append(entrance)
entrance.connect(exit_region)
# Takes an entrance, removes its old connections, and reconnects it between the two regions specified.
def reconnect_regions(entrance: Entrance, start_region: Region, exit_region: Region):
if entrance in entrance.connected_region.entrances:
entrance.connected_region.entrances.remove(entrance)
if entrance in entrance.parent_region.exits:
entrance.parent_region.exits.remove(entrance)
if entrance in start_region.exits:
start_region.exits.remove(entrance)
if entrance in exit_region.entrances:
exit_region.entrances.remove(entrance)
entrance.parent_region = start_region
start_region.exits.append(entrance)
entrance.connect(exit_region)
def create_region_and_connect(world: World,
name: str, entrancename: str, connected_region: Region, is_exit: bool = True) -> Region:
reg: Region = create_region(world, name)
entrance_region: Region
exit_region: Region
if is_exit:
entrance_region = connected_region
exit_region = reg
else:
entrance_region = reg
exit_region = connected_region
connect_regions(entrance_region, exit_region, entrancename, world.player)
return reg
def get_first_chapter_region(world: World) -> Region:
start_chapter: ChapterIndex = world.multiworld.StartingChapter[world.player]
return world.multiworld.get_region(chapter_regions.get(start_chapter), world.player)
def get_act_original_chapter(world: World, act_name: str) -> Region:
return world.multiworld.get_region(act_chapters[act_name], world.player)
def create_thug_shops(world: World):
min_items: int = world.multiworld.NyakuzaThugMinShopItems[world.player].value
max_items: int = world.multiworld.NyakuzaThugMaxShopItems[world.player].value
count: int = -1
step: int = 0
old_name: str = ""
for key, data in shop_locations.items():
if data.nyakuza_thug == "":
continue
if old_name != "" and old_name == data.nyakuza_thug:
continue
try:
if world.nyakuza_thug_items[data.nyakuza_thug] <= 0:
continue
except KeyError:
pass
if count == -1:
count = world.multiworld.random.randint(min_items, max_items)
world.nyakuza_thug_items.setdefault(data.nyakuza_thug, count)
if count <= 0:
continue
if count >= 1:
region = world.multiworld.get_region(data.region, world.player)
loc = HatInTimeLocation(world.player, key, data.id, region)
region.locations.append(loc)
world.shop_locs.append(loc.name)
step += 1
if step >= count:
old_name = data.nyakuza_thug
step = 0
count = -1
def create_events(world: World) -> int:
count: int = 0
for (name, data) in event_locs.items():
if not is_location_valid(world, name):
continue
event: Location = create_event(name, world.multiworld.get_region(data.region, world.player), world)
if data.act_complete_event:
act_completion: str = format("Act Completion (%s)" % data.region)
event.access_rule = world.multiworld.get_location(act_completion, world.player).access_rule
count += 1
return count
def create_event(name: str, region: Region, world: World) -> Location:
event = HatInTimeLocation(world.player, name, None, region)
region.locations.append(event)
event.place_locked_item(HatInTimeItem(name, ItemClassification.progression, None, world.player))
return event