More stuff from review

This commit is contained in:
CookieCat
2024-03-26 19:32:11 -04:00
parent 67e8f62784
commit e53e75de5f
9 changed files with 245 additions and 258 deletions

View File

@@ -149,21 +149,21 @@ dw_classes = {
def create_dw_regions(world: "HatInTimeWorld"):
if world.options.DWExcludeAnnoyingContracts.value > 0:
for name in annoying_dws:
world.get_excluded_dws().append(name)
world.excluded_dws.append(name)
if world.options.DWEnableBonus.value == 0 \
or world.options.DWAutoCompleteBonuses.value > 0:
for name in death_wishes:
world.get_excluded_bonuses().append(name)
world.excluded_bonuses.append(name)
elif world.options.DWExcludeAnnoyingBonuses.value > 0:
for name in annoying_bonuses:
world.get_excluded_bonuses().append(name)
world.excluded_bonuses.append(name)
if world.options.DWExcludeCandles.value > 0:
for name in dw_candles:
if name in world.get_excluded_dws():
if name in world.excluded_dws:
continue
world.get_excluded_dws().append(name)
world.excluded_dws.append(name)
spaceship = world.multiworld.get_region("Spaceship", world.player)
dw_map: Region = create_region(world, "Death Wish Map")
@@ -193,7 +193,7 @@ def create_dw_regions(world: "HatInTimeWorld"):
dw_shuffle.append("Seal the Deal")
world.set_dw_shuffle(dw_shuffle)
world.dw_shuffle = dw_shuffle
prev_dw: Region
for i in range(len(dw_shuffle)):
name = dw_shuffle[i]
@@ -220,7 +220,7 @@ def create_dw_regions(world: "HatInTimeWorld"):
bonus_stamps.place_locked_item(HatInTimeItem(f"2 Stamps - {name}",
ItemClassification.progression, None, world.player))
if name in world.get_excluded_dws():
if name in world.excluded_dws:
main_objective.progress_type = LocationProgressType.EXCLUDED
full_clear.progress_type = LocationProgressType.EXCLUDED
elif world.is_bonus_excluded(name):
@@ -232,7 +232,7 @@ def create_dw_regions(world: "HatInTimeWorld"):
else:
for key, loc_id in death_wishes.items():
if key == "Snatcher Coins in Nyakuza Metro" and not world.is_dlc2():
world.get_excluded_dws().append(key)
world.excluded_dws.append(key)
continue
dw = create_region(world, key)
@@ -258,7 +258,7 @@ def create_dw_regions(world: "HatInTimeWorld"):
bonus_stamps.place_locked_item(HatInTimeItem(f"2 Stamps - {key}",
ItemClassification.progression, None, world.player))
if key in world.get_excluded_dws():
if key in world.excluded_dws:
main_objective.progress_type = LocationProgressType.EXCLUDED
full_clear.progress_type = LocationProgressType.EXCLUDED
elif world.is_bonus_excluded(key):

View File

@@ -103,13 +103,13 @@ required_snatcher_coins = {
def set_dw_rules(world: "HatInTimeWorld"):
if "Snatcher's Hit List" not in world.get_excluded_dws() \
or "Camera Tourist" not in world.get_excluded_dws():
if "Snatcher's Hit List" not in world.excluded_dws \
or "Camera Tourist" not in world.excluded_dws:
set_enemy_rules(world)
dw_list: List[str] = []
if world.options.DWShuffle.value > 0:
dw_list = world.get_dw_shuffle()
dw_list = world.dw_shuffle
else:
for name in death_wishes.keys():
dw_list.append(name)
@@ -196,13 +196,12 @@ def set_dw_rules(world: "HatInTimeWorld"):
add_rule(bonus_stamps, loc.access_rule)
if world.options.DWShuffle.value > 0:
dw_shuffle = world.get_dw_shuffle()
for i in range(len(dw_shuffle)):
for i in range(len(world.dw_shuffle)):
if i == 0:
continue
name = dw_shuffle[i]
prev_dw = world.multiworld.get_region(dw_shuffle[i-1], world.player)
name = world.dw_shuffle[i]
prev_dw = world.multiworld.get_region(world.dw_shuffle[i-1], world.player)
entrance = world.multiworld.get_entrance(f"{prev_dw.name} -> {name}", world.player)
add_rule(entrance, lambda state, n=prev_dw.name: state.has(f"1 Stamp - {n}", world.player))
else:
@@ -330,10 +329,16 @@ def set_candle_dw_rules(name: str, world: "HatInTimeWorld"):
and state.has("Triple Enemy Picture", world.player))
elif "Snatcher Coins" in name:
coins: List[str] = []
for coin in required_snatcher_coins[name]:
add_rule(main_objective, lambda state: state.has(coin, world.player), "or")
coins.append(coin)
add_rule(full_clear, lambda state: state.has(coin, world.player))
# any coin works for the main objective
add_rule(main_objective, lambda state: state.has(coins[0], world.player)
or state.has(coins[1], world.player)
or state.has(coins[2], world.player))
def get_zero_jump_clear_count(state: CollectionState, world: "HatInTimeWorld") -> int:
total = 0
@@ -378,7 +383,7 @@ def can_reach_all_bosses(state: CollectionState, world: "HatInTimeWorld") -> boo
def create_enemy_events(world: "HatInTimeWorld"):
no_tourist = "Camera Tourist" in world.get_excluded_dws() or "Camera Tourist" in world.get_excluded_bonuses()
no_tourist = "Camera Tourist" in world.excluded_dws or "Camera Tourist" in world.excluded_bonuses
for enemy, regions in hit_list.items():
if no_tourist and enemy in bosses:
@@ -395,7 +400,7 @@ def create_enemy_events(world: "HatInTimeWorld"):
if area == "Bluefin Tunnel" and not world.is_dlc2():
continue
if world.options.DWShuffle.value > 0 and area in death_wishes.keys() \
and area not in world.get_dw_shuffle():
and area not in world.dw_shuffle:
continue
region = world.multiworld.get_region(area, world.player)
@@ -409,7 +414,7 @@ def create_enemy_events(world: "HatInTimeWorld"):
continue
if world.options.DWShuffle.value > 0 and name in death_wishes.keys() \
and name not in world.get_dw_shuffle():
and name not in world.dw_shuffle:
continue
region = world.multiworld.get_region(name, world.player)
@@ -422,7 +427,7 @@ def create_enemy_events(world: "HatInTimeWorld"):
def set_enemy_rules(world: "HatInTimeWorld"):
no_tourist = "Camera Tourist" in world.get_excluded_dws() or "Camera Tourist" in world.get_excluded_bonuses()
no_tourist = "Camera Tourist" in world.excluded_dws or "Camera Tourist" in world.excluded_bonuses
for enemy, regions in hit_list.items():
if no_tourist and enemy in bosses:
@@ -440,7 +445,7 @@ def set_enemy_rules(world: "HatInTimeWorld"):
continue
if world.options.DWShuffle.value > 0 and area in death_wishes \
and area not in world.get_dw_shuffle():
and area not in world.dw_shuffle:
continue
event = world.multiworld.get_location(f"{enemy} - {area}", world.player)

View File

@@ -97,7 +97,7 @@ def calculate_yarn_costs(world: "HatInTimeWorld"):
max_cost = 0
for i in range(5):
cost: int = mw.random.randint(min(min_yarn_cost, max_yarn_cost), max(max_yarn_cost, min_yarn_cost))
world.get_hat_yarn_costs()[HatType(i)] = cost
world.hat_yarn_costs[HatType(i)] = cost
max_cost += cost
available_yarn: int = world.options.YarnAvailable.value

View File

@@ -12,7 +12,7 @@ def get_total_locations(world: "HatInTimeWorld") -> int:
total = 0
if not world.is_dw_only():
for (name) in location_table.keys():
for name in location_table.keys():
if is_location_valid(world, name):
total += 1
@@ -21,9 +21,9 @@ def get_total_locations(world: "HatInTimeWorld") -> int:
if world.is_dw():
if world.options.DWShuffle.value > 0:
total += len(world.get_dw_shuffle())
total += len(world.dw_shuffle)
if world.options.DWEnableBonus.value > 0:
total += len(world.get_dw_shuffle())
total += len(world.dw_shuffle)
else:
total += 37
if world.is_dlc2():
@@ -81,11 +81,11 @@ def is_location_valid(world: "HatInTimeWorld", location: str) -> bool:
return False
if world.options.DWShuffle.value > 0 \
and data.region in death_wishes and data.region not in world.get_dw_shuffle():
and data.region in death_wishes and data.region not in world.dw_shuffle:
return False
if location in zero_jumps:
if world.options.DWShuffle.value > 0 and "Zero Jumps" not in world.get_dw_shuffle():
if world.options.DWShuffle.value > 0 and "Zero Jumps" not in world.dw_shuffle:
return False
difficulty: int = world.options.LogicDifficulty.value
@@ -298,10 +298,10 @@ ahit_locations = {
# Alpine Skyline
"Alpine Skyline - Goat Village: Below Hookpoint": LocData(2000334856, "Alpine Skyline Area (TIHS)"),
"Alpine Skyline - Goat Village: Hidden Branch": LocData(2000334855, "Alpine Skyline Area (TIHS)"),
"Alpine Skyline - Goat Refinery": LocData(2000333635, "Alpine Skyline Area (TIHS)"),
"Alpine Skyline - Bird Pass Fork": LocData(2000335911, "Alpine Skyline Area (TIHS)"),
"Alpine Skyline - Goat Refinery": LocData(2000333635, "Alpine Skyline Area (TIHS)", hookshot=True),
"Alpine Skyline - Bird Pass Fork": LocData(2000335911, "Alpine Skyline Area (TIHS)", hookshot=True),
"Alpine Skyline - Yellow Band Hills": LocData(2000335756, "Alpine Skyline Area (TIHS)",
"Alpine Skyline - Yellow Band Hills": LocData(2000335756, "Alpine Skyline Area (TIHS)", hookshot=True,
required_hats=[HatType.BREWING]),
"Alpine Skyline - The Purrloined Village: Horned Stone": LocData(2000335561, "Alpine Skyline Area"),
@@ -318,7 +318,7 @@ ahit_locations = {
"Alpine Skyline - Mystifying Time Mesa: Zipline": LocData(2000337058, "Alpine Skyline Area"),
"Alpine Skyline - Mystifying Time Mesa: Gate Puzzle": LocData(2000336052, "Alpine Skyline Area"),
"Alpine Skyline - Ember Summit": LocData(2000336311, "Alpine Skyline Area (TIHS)"),
"Alpine Skyline - Ember Summit": LocData(2000336311, "Alpine Skyline Area (TIHS)", hookshot=True),
"Alpine Skyline - The Lava Cake: Center Fence Cage": LocData(2000335448, "The Lava Cake"),
"Alpine Skyline - The Lava Cake: Outer Island Chest": LocData(2000334291, "The Lava Cake"),
"Alpine Skyline - The Lava Cake: Dweller Pillars": LocData(2000335417, "The Lava Cake"),
@@ -327,7 +327,7 @@ ahit_locations = {
"Alpine Skyline - The Twilight Bell: Wide Purple Platform": LocData(2000336478, "The Twilight Bell"),
"Alpine Skyline - The Twilight Bell: Ice Platform": LocData(2000335826, "The Twilight Bell"),
"Alpine Skyline - Goat Outpost Horn": LocData(2000334760, "Alpine Skyline Area"),
"Alpine Skyline - Windy Passage": LocData(2000334776, "Alpine Skyline Area (TIHS)"),
"Alpine Skyline - Windy Passage": LocData(2000334776, "Alpine Skyline Area (TIHS)", hookshot=True),
"Alpine Skyline - The Windmill: Inside Pon Cluster": LocData(2000336395, "The Windmill"),
"Alpine Skyline - The Windmill: Entrance": LocData(2000335783, "The Windmill"),
"Alpine Skyline - The Windmill: Dropdown": LocData(2000335815, "The Windmill"),
@@ -867,54 +867,112 @@ zero_jumps = {
dlc_flags=HatDLC.dlc2_dw),
}
# noinspection PyDictDuplicateKeys
snatcher_coins = {
"Snatcher Coin - Top of HQ": LocData(0, "Down with the Mafia!", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ": LocData(0, "Cheating the Race", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ (DWTM)": LocData(0, "Down with the Mafia!", snatcher_coin="Snatcher Coin - Top of HQ",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ": LocData(0, "Heating Up Mafia Town",
hit_type=HitType.umbrella, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ (CTR)": LocData(0, "Cheating the Race", snatcher_coin="Snatcher Coin - Top of HQ",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ": LocData(0, "The Golden Vault", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ": LocData(0, "Beat the Heat", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ (HUMT)": LocData(0, "Heating Up Mafia Town", snatcher_coin="Snatcher Coin - Top of HQ",
hit_type=HitType.umbrella, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower": LocData(0, "Mafia Town Area (HUMT)", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower": LocData(0, "Beat the Heat", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower": LocData(0, "Collect-a-thon", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower": LocData(0, "She Speedran from Outer Space", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower": LocData(0, "Mafia's Jumps", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Under Ruined Tower": LocData(0, "Mafia Town Area", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Under Ruined Tower": LocData(0, "Collect-a-thon", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Under Ruined Tower": LocData(0, "She Speedran from Outer Space", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ (TGV)": LocData(0, "The Golden Vault", snatcher_coin="Snatcher Coin - Top of HQ",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Red House": LocData(0, "Dead Bird Studio - Elevator Area", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Red House": LocData(0, "Security Breach", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Train Rush": LocData(0, "Train Rush", hookshot=True, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of HQ (DW: BTH)": LocData(0, "Beat the Heat", snatcher_coin="Snatcher Coin - Top of HQ",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Train Rush": LocData(0, "10 Seconds until Self-Destruct", hookshot=True,
"Snatcher Coin - Top of Tower": LocData(0, "Mafia Town Area (HUMT)", snatcher_coin="Snatcher Coin - Top of Tower",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower (DW: BTH)": LocData(0, "Beat the Heat", snatcher_coin="Snatcher Coin - Top of Tower",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower (DW: CAT)": LocData(0, "Collect-a-thon", snatcher_coin="Snatcher Coin - Top of Tower",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower (SSFOS)": LocData(0, "She Speedran from Outer Space",
snatcher_coin="Snatcher Coin - Top of Tower",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Tower (DW: MJ)": LocData(0, "Mafia's Jumps", snatcher_coin="Snatcher Coin - Top of Tower",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Under Ruined Tower": LocData(0, "Mafia Town Area",
snatcher_coin="Snatcher Coin - Under Ruined Tower",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Under Ruined Tower (DW: CAT)": LocData(0, "Collect-a-thon",
snatcher_coin="Snatcher Coin - Under Ruined Tower",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Under Ruined Tower (DW: SSFOS)": LocData(0, "She Speedran from Outer Space",
snatcher_coin="Snatcher Coin - Under Ruined Tower",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Red House (DBS)": LocData(0, "Dead Bird Studio - Elevator Area",
snatcher_coin="Snatcher Coin - Top of Red House",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Top of Red House (DW: SB)": LocData(0, "Security Breach",
snatcher_coin="Snatcher Coin - Top of Red House",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Train Rush": LocData(0, "Train Rush", snatcher_coin="Snatcher Coin - Train Rush",
hookshot=True, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Train Rush (10 Seconds)": LocData(0, "10 Seconds until Self-Destruct",
snatcher_coin="Snatcher Coin - Train Rush",
hookshot=True, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Picture Perfect": LocData(0, "Picture Perfect", snatcher_coin="Snatcher Coin - Picture Perfect",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Swamp Tree": LocData(0, "Subcon Forest Area", snatcher_coin="Snatcher Coin - Swamp Tree",
hookshot=True, paintings=1,
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Picture Perfect": LocData(0, "Picture Perfect", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Swamp Tree (Speedrun Well)": LocData(0, "Speedrun Well",
snatcher_coin="Snatcher Coin - Swamp Tree",
hookshot=True, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Swamp Tree": LocData(0, "Subcon Forest Area", hookshot=True, paintings=1,
"Snatcher Coin - Manor Roof": LocData(0, "Subcon Forest Area", snatcher_coin="Snatcher Coin - Manor Roof",
hit_type=HitType.dweller_bell, paintings=1,
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Swamp Tree": LocData(0, "Speedrun Well", hookshot=True, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Giant Time Piece": LocData(0, "Subcon Forest Area",
snatcher_coin="Snatcher Coin - Giant Time Piece",
paintings=3, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Manor Roof": LocData(0, "Subcon Forest Area", hit_type=HitType.dweller_bell, paintings=1,
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Goat Village Top": LocData(0, "Alpine Skyline Area (TIHS)",
snatcher_coin="Snatcher Coin - Goat Village Top",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Giant Time Piece": LocData(0, "Subcon Forest Area", paintings=3, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Goat Village Top (Illness Speedrun)": LocData(0, "The Illness has Speedrun",
snatcher_coin="Snatcher Coin - Goat Village Top",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Goat Village Top": LocData(0, "Alpine Skyline Area (TIHS)", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Goat Village Top": LocData(0, "The Illness has Speedrun", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Lava Cake": LocData(0, "The Lava Cake", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Windmill": LocData(0, "The Windmill", dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Windmill": LocData(0, "Wound-Up Windmill", hookshot=True, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Lava Cake": LocData(0, "The Lava Cake", snatcher_coin="Snatcher Coin - Lava Cake",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Green Clean Tower": LocData(0, "Green Clean Station", dlc_flags=HatDLC.dlc2_dw),
"Snatcher Coin - Bluefin Cat Train": LocData(0, "Bluefin Tunnel", dlc_flags=HatDLC.dlc2_dw),
"Snatcher Coin - Pink Paw Fence": LocData(0, "Pink Paw Station", dlc_flags=HatDLC.dlc2_dw),
"Snatcher Coin - Windmill": LocData(0, "The Windmill", snatcher_coin="Snatcher Coin - Windmill",
dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Windmill (DW: WUW)": LocData(0, "Wound-Up Windmill", snatcher_coin="Snatcher Coin - Windmill",
hookshot=True, dlc_flags=HatDLC.death_wish),
"Snatcher Coin - Green Clean Tower": LocData(0, "Green Clean Station",
snatcher_coin="Snatcher Coin - Green Clean Tower",
dlc_flags=HatDLC.dlc2_dw),
"Snatcher Coin - Bluefin Cat Train": LocData(0, "Bluefin Tunnel",
snatcher_coin="Snatcher Coin - Bluefin Tunnel",
dlc_flags=HatDLC.dlc2_dw),
"Snatcher Coin - Pink Paw Fence": LocData(0, "Pink Paw Station",
snatcher_coin="Snatcher Coin - Pink Paw Fence",
dlc_flags=HatDLC.dlc2_dw),
}
event_locs = {

View File

@@ -1,5 +1,5 @@
from typing import List, TYPE_CHECKING
from schema import Schema
from schema import Schema, Optional
from dataclasses import dataclass
from worlds.AutoWorld import PerGameCommonOptions
from Options import Range, Toggle, DeathLink, Choice, OptionDict, DefaultOnToggle
@@ -128,7 +128,7 @@ class ActPlando(OptionDict):
"""Plando acts onto other acts. For example, \"Train Rush\": \"Alpine Free Roam\""""
display_name = "Act Plando"
schema = Schema({
str: str
Optional(str): str
})
@@ -516,7 +516,8 @@ class DWShuffleCountMax(Range):
class DWEnableBonus(Toggle):
"""In Death Wish, add a location for completing all of a DW contract's bonuses, in addition to the location for completing the DW contract normally.
"""In Death Wish, add a location for completing all of a DW contract's bonuses,
in addition to the location for completing the DW contract normally.
WARNING!! Only for the brave! This option can create VERY DIFFICULT SEEDS!
ONLY turn this on if you know what you are doing to yourself and everyone else in the multiworld!
Using Peace and Tranquility to auto-complete the bonuses will NOT count!"""

View File

@@ -788,7 +788,7 @@ def create_badge_seller(world: "HatInTimeWorld") -> Region:
world.options.BadgeSellerMaxItems.value)
if max_items <= 0:
world.set_badge_seller_count(0)
world.badge_seller_count = 0
return badge_seller
for (key, data) in shop_locations.items():
@@ -803,7 +803,7 @@ def create_badge_seller(world: "HatInTimeWorld") -> Region:
if count >= max_items:
break
world.set_badge_seller_count(max_items)
world.badge_seller_count = max_items
return badge_seller
@@ -867,9 +867,9 @@ def update_chapter_act_info(world: "HatInTimeWorld", original_region: Region, ne
world.act_connections[original_act_info] = new_act_info
def get_shuffled_region(self, region: str) -> str:
def get_shuffled_region(world: "HatInTimeWorld", region: str) -> str:
ci: str = chapter_act_info[region]
for key, val in self.act_connections.items():
for key, val in world.act_connections.items():
if val == ci:
for name in chapter_act_info.keys():
if chapter_act_info[name] == key:
@@ -882,7 +882,6 @@ def create_thug_shops(world: "HatInTimeWorld"):
count = -1
step = 0
old_name = ""
thug_items = world.get_nyakuza_thug_items()
for key, data in shop_locations.items():
if data.nyakuza_thug == "":
@@ -892,14 +891,14 @@ def create_thug_shops(world: "HatInTimeWorld"):
continue
try:
if thug_items[data.nyakuza_thug] <= 0:
if world.nyakuza_thug_items[data.nyakuza_thug] <= 0:
continue
except KeyError:
pass
if count == -1:
count = world.random.randint(min_items, max_items)
thug_items.setdefault(data.nyakuza_thug, count)
world.nyakuza_thug_items.setdefault(data.nyakuza_thug, count)
if count <= 0:
continue
@@ -915,8 +914,6 @@ def create_thug_shops(world: "HatInTimeWorld"):
step = 0
count = -1
world.set_nyakuza_thug_items(thug_items)
def create_events(world: "HatInTimeWorld") -> int:
count = 0
@@ -928,7 +925,7 @@ def create_events(world: "HatInTimeWorld") -> int:
item_name: str = name
if world.is_dw():
if name in snatcher_coins.keys():
name = f"{name} ({data.region})"
item_name = data.snatcher_coin
elif name in zero_jumps:
if get_difficulty(world) < Difficulty.HARD and name in zero_jumps_hard:
continue

View File

@@ -1,8 +1,8 @@
from worlds.AutoWorld import CollectionState
from worlds.generic.Rules import add_rule, set_rule
from .Locations import location_table, zipline_unlocks, is_location_valid, contract_locations, \
shop_locations, event_locs, snatcher_coins
from .Types import HatType, ChapterIndex, hat_type_to_item, Difficulty, HatDLC, HitType
shop_locations, event_locs
from .Types import HatType, ChapterIndex, hat_type_to_item, Difficulty, HitType
from BaseClasses import Location, Entrance, Region
from typing import TYPE_CHECKING, List, Callable, Union, Dict
@@ -43,9 +43,8 @@ def can_use_hat(state: CollectionState, world: "HatInTimeWorld", hat: HatType) -
def get_hat_cost(world: "HatInTimeWorld", hat: HatType) -> int:
cost = 0
costs = world.get_hat_yarn_costs()
for h in world.get_hat_craft_order():
cost += costs[h]
for h in world.hat_craft_order:
cost += world.hat_yarn_costs[h]
if h == hat:
break
@@ -136,7 +135,7 @@ def can_clear_metro(state: CollectionState, world: "HatInTimeWorld") -> bool:
def set_rules(world: "HatInTimeWorld"):
# First, chapter access
starting_chapter = ChapterIndex(world.options.StartingChapter.value)
world.set_chapter_cost(starting_chapter, 0)
world.chapter_timepiece_costs[starting_chapter] = 0
# Chapter costs increase progressively. Randomly decide the chapter order, except for Finale
chapter_list: List[ChapterIndex] = [ChapterIndex.MAFIA, ChapterIndex.BIRDS,
@@ -160,8 +159,8 @@ def set_rules(world: "HatInTimeWorld"):
world.random.shuffle(chapter_list)
if starting_chapter is not ChapterIndex.ALPINE and (world.is_dlc1() or world.is_dlc2()):
index1: int = 69
index2: int = 69
index1 = 69
index2 = 69
pos: int
lowest_index: int
chapter_list.remove(ChapterIndex.ALPINE)
@@ -180,75 +179,63 @@ def set_rules(world: "HatInTimeWorld"):
chapter_list.insert(pos, ChapterIndex.ALPINE)
if world.is_dlc1() and world.is_dlc2() and final_chapter is not ChapterIndex.METRO:
chapter_list.remove(ChapterIndex.METRO)
index = chapter_list.index(ChapterIndex.CRUISE)
if index >= len(chapter_list):
chapter_list.append(ChapterIndex.METRO)
else:
chapter_list.insert(world.random.randint(index+1, len(chapter_list)), ChapterIndex.METRO)
lowest_cost: int = world.options.LowestChapterCost.value
highest_cost: int = world.options.HighestChapterCost.value
cost_increment: int = world.options.ChapterCostIncrement.value
min_difference: int = world.options.ChapterCostMinDifference.value
last_cost = 0
loop_count = 0
for chapter in chapter_list:
min_range: int = lowest_cost + (cost_increment * loop_count)
for i, chapter in enumerate(chapter_list):
min_range: int = lowest_cost + (cost_increment * i)
if min_range >= highest_cost:
min_range = highest_cost-1
value: int = world.random.randint(min_range, min(highest_cost, max(lowest_cost, last_cost + cost_increment)))
cost = world.random.randint(value, min(value + cost_increment, highest_cost))
if loop_count >= 1:
if i >= 1:
if last_cost + min_difference > cost:
cost = last_cost + min_difference
cost = min(cost, highest_cost)
world.set_chapter_cost(chapter, cost)
world.chapter_timepiece_costs[chapter] = cost
last_cost = cost
loop_count += 1
if final_chapter is not None:
world.set_chapter_cost(final_chapter, world.random.randint(
world.chapter_timepiece_costs[final_chapter] = world.random.randint(
world.options.FinalChapterMinCost.value,
world.options.FinalChapterMaxCost.value))
world.options.FinalChapterMaxCost.value)
add_rule(world.multiworld.get_entrance("Telescope -> Mafia Town", world.player),
lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.MAFIA)))
lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.MAFIA]))
add_rule(world.multiworld.get_entrance("Telescope -> Battle of the Birds", world.player),
lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.BIRDS)))
lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.BIRDS]))
add_rule(world.multiworld.get_entrance("Telescope -> Subcon Forest", world.player),
lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.SUBCON)))
lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.SUBCON]))
add_rule(world.multiworld.get_entrance("Telescope -> Alpine Skyline", world.player),
lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE)))
lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE]))
add_rule(world.multiworld.get_entrance("Telescope -> Time's End", world.player),
lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.FINALE))
lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.FINALE])
and can_use_hat(state, world, HatType.BREWING) and can_use_hat(state, world, HatType.DWELLER))
if world.is_dlc1():
add_rule(world.multiworld.get_entrance("Telescope -> The Arctic Cruise", world.player),
lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE))
and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.CRUISE)))
lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE])
and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.CRUISE]))
if world.is_dlc2():
add_rule(world.multiworld.get_entrance("Telescope -> Nyakuza Metro", world.player),
lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE))
and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.METRO))
lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE])
and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.METRO])
and can_use_hat(state, world, HatType.DWELLER) and can_use_hat(state, world, HatType.ICE))
if world.options.ActRandomizer.value == 0:
set_default_rift_rules(world)
table = {**location_table, **event_locs}
loc: Location
for (key, data) in table.items():
if not is_location_valid(world, key):
continue
@@ -256,9 +243,6 @@ def set_rules(world: "HatInTimeWorld"):
if key in contract_locations.keys():
continue
if data.dlc_flags & HatDLC.death_wish and key in snatcher_coins.keys():
key = f"{key} ({data.region})"
loc = world.multiworld.get_location(key, world.player)
for hat in data.required_hats:
@@ -319,33 +303,12 @@ def set_rules(world: "HatInTimeWorld"):
add_rule(world.multiworld.get_location(loc, world.player),
lambda state, z=zipline: state.has(z, world.player))
for loc in world.multiworld.get_region("Alpine Skyline Area (TIHS)", world.player).locations:
if "Goat Village" in loc.name:
continue
# This needs some special handling
if loc.name == "Alpine Skyline - Goat Refinery":
add_rule(loc, lambda state: state.has("AFR Access", world.player)
and can_use_hookshot(state, world)
and can_hit(state, world, True))
difficulty: Difficulty = Difficulty(world.options.LogicDifficulty.value)
if difficulty >= Difficulty.MODERATE:
add_rule(loc, lambda state: state.has("TIHS Access", world.player)
and can_use_hat(state, world, HatType.SPRINT), "or")
elif difficulty >= Difficulty.HARD:
add_rule(loc, lambda state: state.has("TIHS Access", world.player, "or"))
continue
add_rule(loc, lambda state: can_use_hookshot(state, world))
dummy_entrances: List[Entrance] = []
for (key, acts) in act_connections.items():
if "Arctic Cruise" in key and not world.is_dlc1():
continue
i: int = 1
entrance: Entrance = world.multiworld.get_entrance(key, world.player)
region: Region = entrance.connected_region
access_rules: List[Callable[[CollectionState], bool]] = []
@@ -354,7 +317,7 @@ def set_rules(world: "HatInTimeWorld"):
# Entrances to this act that we have to set access_rules on
entrances: List[Entrance] = []
for act in acts:
for i, act in enumerate(acts, start=1):
act_entrance: Entrance = world.multiworld.get_entrance(act, world.player)
access_rules.append(act_entrance.access_rule)
required_region = act_entrance.connected_region
@@ -369,8 +332,6 @@ def set_rules(world: "HatInTimeWorld"):
rule = world.multiworld.get_location(name, world.player).access_rule
access_rules.append(rule)
i += 1
for e in entrances:
for rules in access_rules:
add_rule(e, rules)
@@ -389,7 +350,7 @@ def set_rules(world: "HatInTimeWorld"):
def set_specific_rules(world: "HatInTimeWorld"):
add_rule(world.multiworld.get_location("Mafia Boss Shop Item", world.player),
lambda state: state.has("Time Piece", world.player, 12)
and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.BIRDS)))
and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.BIRDS]))
add_rule(world.multiworld.get_location("Spaceship - Rumbi Abuse", world.player),
lambda state: state.has("Time Piece", world.player, 4))
@@ -457,6 +418,11 @@ def set_moderate_rules(world: "HatInTimeWorld"):
set_rule(world.multiworld.get_location("Alpine Skyline - Mystifying Time Mesa: Zipline", world.player),
lambda state: can_use_hookshot(state, world))
# Moderate: Goat Refinery from TIHS with Sprint only
add_rule(world.multiworld.get_location("Alpine Skyline - Goat Refinery", world.player),
lambda state: state.has("TIHS Access", world.player)
and can_use_hat(state, world, HatType.SPRINT), "or")
# Moderate: Finale without Hookshot
set_rule(world.multiworld.get_location("Act Completion (The Finale)", world.player),
lambda state: can_use_hat(state, world, HatType.DWELLER))
@@ -530,6 +496,10 @@ def set_hard_rules(world: "HatInTimeWorld"):
add_rule(world.multiworld.get_entrance("Telescope -> Time's End", world.player),
lambda state: can_use_hat(state, world, HatType.ICE), "or")
# Hard: Goat Refinery from TIHS with nothing
add_rule(world.multiworld.get_location("Alpine Skyline - Goat Refinery", world.player),
lambda state: state.has("TIHS Access", world.player, "or"))
if world.is_dlc1():
# Hard: clear Deep Sea without Dweller Mask
set_rule(world.multiworld.get_location("Act Completion (Time Rift - Deep Sea)", world.player),
@@ -555,7 +525,7 @@ def set_hard_rules(world: "HatInTimeWorld"):
def set_expert_rules(world: "HatInTimeWorld"):
# Finale Telescope with no hats
set_rule(world.multiworld.get_entrance("Telescope -> Time's End", world.player),
lambda state: state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.FINALE)))
lambda state: state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.FINALE]))
# Expert: Mafia Town - Above Boats, Top of Lighthouse, and Hot Air Balloon with nothing
set_rule(world.multiworld.get_location("Mafia Town - Above Boats", world.player), lambda state: True)
@@ -753,6 +723,11 @@ def set_alps_rules(world: "HatInTimeWorld"):
add_rule(world.multiworld.get_entrance("Alpine Skyline - Finale", world.player),
lambda state: can_clear_alpine(state, world))
add_rule(world.multiworld.get_location("Alpine Skyline - Goat Refinery", world.player),
lambda state: state.has("AFR Access", world.player)
and can_use_hookshot(state, world)
and can_hit(state, world, True))
def set_dlc1_rules(world: "HatInTimeWorld"):
add_rule(world.multiworld.get_entrance("Cruise Ship Entrance BV", world.player),
@@ -810,11 +785,11 @@ def set_rift_rules(world: "HatInTimeWorld", regions: Dict[str, Region]):
# This is accessing the regions in place of these time rifts, so we can set the rules on all the entrances.
for entrance in regions["Time Rift - Gallery"].entrances:
add_rule(entrance, lambda state: can_use_hat(state, world, HatType.BREWING)
and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.BIRDS)))
and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.BIRDS]))
for entrance in regions["Time Rift - The Lab"].entrances:
add_rule(entrance, lambda state: can_use_hat(state, world, HatType.DWELLER)
and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE)))
and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE]))
for entrance in regions["Time Rift - Sewers"].entrances:
add_rule(entrance, lambda state: can_clear_act(state, world, "Mafia Town - Act 4"))
@@ -895,11 +870,11 @@ def set_default_rift_rules(world: "HatInTimeWorld"):
for entrance in world.multiworld.get_region("Time Rift - Gallery", world.player).entrances:
add_rule(entrance, lambda state: can_use_hat(state, world, HatType.BREWING)
and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.BIRDS)))
and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.BIRDS]))
for entrance in world.multiworld.get_region("Time Rift - The Lab", world.player).entrances:
add_rule(entrance, lambda state: can_use_hat(state, world, HatType.DWELLER)
and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.ALPINE)))
and state.has("Time Piece", world.player, world.chapter_timepiece_costs[ChapterIndex.ALPINE]))
for entrance in world.multiworld.get_region("Time Rift - Sewers", world.player).entrances:
add_rule(entrance, lambda state: can_clear_act(state, world, "Mafia Town - Act 4"))
@@ -970,9 +945,6 @@ def set_event_rules(world: "HatInTimeWorld"):
if not is_location_valid(world, name):
continue
if data.dlc_flags & HatDLC.death_wish and name in snatcher_coins.keys():
name = f"{name} ({data.region})"
event: Location = world.multiworld.get_location(name, world.player)
if data.act_event:

View File

@@ -69,6 +69,7 @@ class LocData(NamedTuple):
# Other
act_event: Optional[bool] = False # Only used for event locations. Copy access rule from act completion
nyakuza_thug: Optional[str] = "" # Name of Nyakuza thug NPC (for metro shops)
snatcher_coin: Optional[str] = "" # Only for Snatcher Coin event locations, name of the Snatcher Coin item
class ItemData(NamedTuple):

View File

@@ -1,4 +1,4 @@
from BaseClasses import Item, ItemClassification, Tutorial, Location
from BaseClasses import Item, ItemClassification, Tutorial, Location, MultiWorld
from .Items import item_table, create_item, relic_groups, act_contracts, create_itempool
from .Regions import create_regions, randomize_act_entrances, chapter_act_info, create_events, get_shuffled_region
from .Locations import location_table, contract_locations, is_location_valid, get_location_names, TASKSANITY_START_ID, \
@@ -24,15 +24,6 @@ components.append(Component("A Hat in Time Client", "AHITClient", func=launch_cl
icon_paths['yatta'] = local_path('data', 'yatta.png')
hat_craft_order: Dict[int, List[HatType]] = {}
hat_yarn_costs: Dict[int, Dict[HatType, int]] = {}
chapter_timepiece_costs: Dict[int, Dict[ChapterIndex, int]] = {}
excluded_dws: Dict[int, List[str]] = {}
excluded_bonuses: Dict[int, List[str]] = {}
dw_shuffle: Dict[int, List[str]] = {}
nyakuza_thug_items: Dict[int, Dict[str, int]] = {}
badge_seller_count: Dict[int, int] = {}
class AWebInTime(WebWorld):
theme = "partyTime"
@@ -60,11 +51,33 @@ class HatInTimeWorld(World):
options_dataclass = AHITOptions
options: AHITOptions
act_connections: Dict[str, str] = {}
shop_locs: List[str] = []
item_name_groups = relic_groups
web = AWebInTime()
def __init__(self, multiworld: "MultiWorld", player: int):
super().__init__(multiworld, player)
self.act_connections: Dict[str, str] = {}
self.shop_locs: List[str] = []
self.hat_craft_order: List[HatType] = [HatType.SPRINT, HatType.BREWING, HatType.ICE,
HatType.DWELLER, HatType.TIME_STOP]
self.hat_yarn_costs: Dict[HatType, int] = {HatType.SPRINT: -1, HatType.BREWING: -1, HatType.ICE: -1,
HatType.DWELLER: -1, HatType.TIME_STOP: -1}
self.chapter_timepiece_costs: Dict[ChapterIndex, int] = {ChapterIndex.MAFIA: -1,
ChapterIndex.BIRDS: -1,
ChapterIndex.SUBCON: -1,
ChapterIndex.ALPINE: -1,
ChapterIndex.FINALE: -1,
ChapterIndex.CRUISE: -1,
ChapterIndex.METRO: -1}
self.excluded_dws: List[str] = []
self.excluded_bonuses: List[str] = []
self.dw_shuffle: List[str] = []
self.nyakuza_thug_items: Dict[str, int] = {}
self.badge_seller_count: int = 0
def generate_early(self):
adjust_options(self)
@@ -87,12 +100,6 @@ class HatInTimeWorld(World):
self.multiworld.push_precollected(self.create_item("Progressive Painting Unlock"))
def create_regions(self):
excluded_dws[self.player] = []
excluded_bonuses[self.player] = []
dw_shuffle[self.player] = []
nyakuza_thug_items[self.player] = {}
badge_seller_count[self.player] = 0
self.shop_locs = []
# noinspection PyClassVar
self.topology_present = bool(self.options.ActRandomizer.value)
@@ -105,8 +112,8 @@ class HatInTimeWorld(World):
create_events(self)
if self.is_dw():
if "Snatcher's Hit List" not in self.get_excluded_dws() \
or "Camera Tourist" not in self.get_excluded_dws():
if "Snatcher's Hit List" not in self.excluded_dws \
or "Camera Tourist" not in self.excluded_dws:
create_enemy_events(self)
# place vanilla contract locations if contract shuffle is off
@@ -115,30 +122,15 @@ class HatInTimeWorld(World):
self.multiworld.get_location(name, self.player).place_locked_item(create_item(self, name))
def create_items(self):
hat_yarn_costs[self.player] = {HatType.SPRINT: -1, HatType.BREWING: -1, HatType.ICE: -1,
HatType.DWELLER: -1, HatType.TIME_STOP: -1}
hat_craft_order[self.player] = [HatType.SPRINT, HatType.BREWING, HatType.ICE,
HatType.DWELLER, HatType.TIME_STOP]
if self.options.HatItems.value == 0 and self.options.RandomizeHatOrder.value > 0:
self.random.shuffle(hat_craft_order[self.player])
self.random.shuffle(self.hat_craft_order)
if self.options.RandomizeHatOrder.value == 2:
hat_craft_order[self.player].remove(HatType.TIME_STOP)
hat_craft_order[self.player].append(HatType.TIME_STOP)
self.hat_craft_order.remove(HatType.TIME_STOP)
self.hat_craft_order.append(HatType.TIME_STOP)
self.multiworld.itempool += create_itempool(self)
def set_rules(self):
self.act_connections = {}
chapter_timepiece_costs[self.player] = {ChapterIndex.MAFIA: -1,
ChapterIndex.BIRDS: -1,
ChapterIndex.SUBCON: -1,
ChapterIndex.ALPINE: -1,
ChapterIndex.FINALE: -1,
ChapterIndex.CRUISE: -1,
ChapterIndex.METRO: -1}
if self.is_dw_only():
# we already have all items if this is the case, no need for rules
self.multiworld.push_precollected(HatInTimeItem("Death Wish Only Mode", ItemClassification.progression,
@@ -152,7 +144,7 @@ class HatInTimeWorld(World):
if name == "Snatcher Coins in Nyakuza Metro" and not self.is_dlc2():
continue
if self.options.DWShuffle.value > 0 and name not in self.get_dw_shuffle():
if self.options.DWShuffle.value > 0 and name not in self.dw_shuffle:
continue
full_clear = self.multiworld.get_location(f"{name} - All Clear", self.player)
@@ -174,41 +166,41 @@ class HatInTimeWorld(World):
return create_item(self, name)
def fill_slot_data(self) -> dict:
slot_data: dict = {"Chapter1Cost": chapter_timepiece_costs[self.player][ChapterIndex.MAFIA],
"Chapter2Cost": chapter_timepiece_costs[self.player][ChapterIndex.BIRDS],
"Chapter3Cost": chapter_timepiece_costs[self.player][ChapterIndex.SUBCON],
"Chapter4Cost": chapter_timepiece_costs[self.player][ChapterIndex.ALPINE],
"Chapter5Cost": chapter_timepiece_costs[self.player][ChapterIndex.FINALE],
"Chapter6Cost": chapter_timepiece_costs[self.player][ChapterIndex.CRUISE],
"Chapter7Cost": chapter_timepiece_costs[self.player][ChapterIndex.METRO],
"BadgeSellerItemCount": badge_seller_count[self.player],
slot_data: dict = {"Chapter1Cost": self.chapter_timepiece_costs[ChapterIndex.MAFIA],
"Chapter2Cost": self.chapter_timepiece_costs[ChapterIndex.BIRDS],
"Chapter3Cost": self.chapter_timepiece_costs[ChapterIndex.SUBCON],
"Chapter4Cost": self.chapter_timepiece_costs[ChapterIndex.ALPINE],
"Chapter5Cost": self.chapter_timepiece_costs[ChapterIndex.FINALE],
"Chapter6Cost": self.chapter_timepiece_costs[ChapterIndex.CRUISE],
"Chapter7Cost": self.chapter_timepiece_costs[ChapterIndex.METRO],
"BadgeSellerItemCount": self.badge_seller_count,
"SeedNumber": str(self.multiworld.seed), # For shop prices
"SeedName": self.multiworld.seed_name,
"TotalLocations": get_total_locations(self)}
if self.options.HatItems.value == 0:
slot_data.setdefault("SprintYarnCost", hat_yarn_costs[self.player][HatType.SPRINT])
slot_data.setdefault("BrewingYarnCost", hat_yarn_costs[self.player][HatType.BREWING])
slot_data.setdefault("IceYarnCost", hat_yarn_costs[self.player][HatType.ICE])
slot_data.setdefault("DwellerYarnCost", hat_yarn_costs[self.player][HatType.DWELLER])
slot_data.setdefault("TimeStopYarnCost", hat_yarn_costs[self.player][HatType.TIME_STOP])
slot_data.setdefault("Hat1", int(hat_craft_order[self.player][0]))
slot_data.setdefault("Hat2", int(hat_craft_order[self.player][1]))
slot_data.setdefault("Hat3", int(hat_craft_order[self.player][2]))
slot_data.setdefault("Hat4", int(hat_craft_order[self.player][3]))
slot_data.setdefault("Hat5", int(hat_craft_order[self.player][4]))
slot_data.setdefault("SprintYarnCost", self.hat_yarn_costs[HatType.SPRINT])
slot_data.setdefault("BrewingYarnCost", self.hat_yarn_costs[HatType.BREWING])
slot_data.setdefault("IceYarnCost", self.hat_yarn_costs[HatType.ICE])
slot_data.setdefault("DwellerYarnCost", self.hat_yarn_costs[HatType.DWELLER])
slot_data.setdefault("TimeStopYarnCost", self.hat_yarn_costs[HatType.TIME_STOP])
slot_data.setdefault("Hat1", int(self.hat_craft_order[0]))
slot_data.setdefault("Hat2", int(self.hat_craft_order[1]))
slot_data.setdefault("Hat3", int(self.hat_craft_order[2]))
slot_data.setdefault("Hat4", int(self.hat_craft_order[3]))
slot_data.setdefault("Hat5", int(self.hat_craft_order[4]))
if self.options.ActRandomizer.value > 0:
for name in self.act_connections.keys():
slot_data[name] = self.act_connections[name]
if self.is_dlc2() and not self.is_dw_only():
for name in nyakuza_thug_items[self.player].keys():
slot_data[name] = nyakuza_thug_items[self.player][name]
for name in self.nyakuza_thug_items.keys():
slot_data[name] = self.nyakuza_thug_items[name]
if self.is_dw():
i = 0
for name in excluded_dws[self.player]:
for name in self.excluded_dws:
if self.options.EndGoal.value == 3 and name == "Seal the Deal":
continue
@@ -217,15 +209,15 @@ class HatInTimeWorld(World):
i = 0
if self.options.DWAutoCompleteBonuses.value == 0:
for name in excluded_bonuses[self.player]:
if name in excluded_dws[self.player]:
for name in self.excluded_bonuses:
if name in self.excluded_dws:
continue
slot_data[f"excluded_bonus{i}"] = dw_classes[name]
i += 1
if self.options.DWShuffle.value > 0:
shuffled_dws = self.get_dw_shuffle()
shuffled_dws = self.dw_shuffle
for i in range(len(shuffled_dws)):
slot_data[f"dw_{i}"] = dw_classes[shuffled_dws[i]]
@@ -281,26 +273,11 @@ class HatInTimeWorld(World):
hint_data[self.player] = new_hint_data
def write_spoiler_header(self, spoiler_handle: TextIO):
for i in self.get_chapter_costs():
spoiler_handle.write("Chapter %i Cost: %i\n" % (i, self.get_chapter_costs()[ChapterIndex(i)]))
for i in self.chapter_timepiece_costs:
spoiler_handle.write("Chapter %i Cost: %i\n" % (i, self.chapter_timepiece_costs[ChapterIndex(i)]))
for hat in hat_craft_order[self.player]:
spoiler_handle.write("Hat Cost: %s: %i\n" % (hat, hat_yarn_costs[self.player][hat]))
def set_chapter_cost(self, chapter: ChapterIndex, cost: int):
chapter_timepiece_costs[self.player][chapter] = cost
def get_chapter_cost(self, chapter: ChapterIndex) -> int:
return chapter_timepiece_costs[self.player][chapter]
def get_hat_craft_order(self):
return hat_craft_order[self.player]
def get_hat_yarn_costs(self):
return hat_yarn_costs[self.player]
def get_chapter_costs(self):
return chapter_timepiece_costs[self.player]
for hat in self.hat_craft_order:
spoiler_handle.write("Hat Cost: %s: %i\n" % (hat, self.hat_yarn_costs[hat]))
def is_dlc1(self) -> bool:
return self.options.EnableDLC1.value > 0
@@ -314,43 +291,19 @@ class HatInTimeWorld(World):
def is_dw_only(self) -> bool:
return self.is_dw() and self.options.DeathWishOnly.value > 0
def get_excluded_dws(self):
return excluded_dws[self.player]
def get_excluded_bonuses(self):
return excluded_bonuses[self.player]
def is_dw_excluded(self, name: str) -> bool:
# don't exclude Seal the Deal if it's our goal
if self.options.EndGoal.value == 3 and name == "Seal the Deal" \
and f"{name} - Main Objective" not in self.options.exclude_locations:
return False
if name in excluded_dws[self.player]:
if name in self.excluded_dws:
return True
return f"{name} - Main Objective" in self.options.exclude_locations
def is_bonus_excluded(self, name: str) -> bool:
if self.is_dw_excluded(name) or name in excluded_bonuses[self.player]:
if self.is_dw_excluded(name) or name in self.excluded_bonuses:
return True
return f"{name} - All Clear" in self.options.exclude_locations
def get_dw_shuffle(self):
return dw_shuffle[self.player]
def set_dw_shuffle(self, shuffle: List[str]):
dw_shuffle[self.player] = shuffle
def get_badge_seller_count(self) -> int:
return badge_seller_count[self.player]
def set_badge_seller_count(self, value: int):
badge_seller_count[self.player] = value
def get_nyakuza_thug_items(self):
return nyakuza_thug_items[self.player]
def set_nyakuza_thug_items(self, items: Dict[str, int]):
nyakuza_thug_items[self.player] = items