Remove the rest of option.class.value

This commit is contained in:
CookieCat
2024-05-13 14:38:34 -04:00
parent ecf6917019
commit c20076fd0c
6 changed files with 103 additions and 110 deletions

View File

@@ -7,6 +7,7 @@ from worlds.generic.Rules import add_rule, set_rule
from typing import List, Callable, TYPE_CHECKING
from .Regions import act_chapters
from .Locations import zero_jumps, zero_jumps_expert, zero_jumps_hard, death_wishes
from .Options import EndGoal
if TYPE_CHECKING:
from . import HatInTimeWorld
@@ -107,7 +108,7 @@ def set_dw_rules(world: "HatInTimeWorld"):
set_enemy_rules(world)
dw_list: List[str] = []
if world.options.DWShuffle.value > 0:
if world.options.DWShuffle:
dw_list = world.dw_shuffle
else:
for name in death_wishes.keys():
@@ -118,16 +119,15 @@ def set_dw_rules(world: "HatInTimeWorld"):
continue
dw = world.multiworld.get_region(name, world.player)
if world.options.DWShuffle.value == 0:
if name in dw_stamp_costs.keys():
for entrance in dw.entrances:
add_rule(entrance, lambda state, n=name: get_total_dw_stamps(state, world) >= dw_stamp_costs[n])
if not world.options.DWShuffle and name in dw_stamp_costs.keys():
for entrance in dw.entrances:
add_rule(entrance, lambda state, n=name: get_total_dw_stamps(state, world) >= dw_stamp_costs[n])
main_objective = world.multiworld.get_location(f"{name} - Main Objective", world.player)
all_clear = world.multiworld.get_location(f"{name} - All Clear", world.player)
main_stamp = world.multiworld.get_location(f"Main Stamp - {name}", world.player)
bonus_stamps = world.multiworld.get_location(f"Bonus Stamps - {name}", world.player)
if world.options.DWEnableBonus.value == 0:
if not world.options.DWEnableBonus:
# place nothing, but let the locations exist still, so we can use them for bonus stamp rules
all_clear.address = None
all_clear.place_locked_item(HatInTimeItem("Nothing", ItemClassification.filler, None, world.player))
@@ -143,10 +143,10 @@ def set_dw_rules(world: "HatInTimeWorld"):
add_rule(main_stamp, main_objective.access_rule)
add_rule(all_clear, main_objective.access_rule)
# Only set bonus stamp rules if we don't auto complete bonuses
if world.options.DWAutoCompleteBonuses.value == 0 and not world.is_bonus_excluded(all_clear.name):
if not world.options.DWAutoCompleteBonuses and not world.is_bonus_excluded(all_clear.name):
add_rule(bonus_stamps, all_clear.access_rule)
if world.options.DWShuffle.value > 0:
if world.options.DWShuffle:
for i in range(len(world.dw_shuffle)-1):
name = world.dw_shuffle[i+1]
prev_dw = world.multiworld.get_region(world.dw_shuffle[i], world.player)
@@ -171,7 +171,7 @@ def set_dw_rules(world: "HatInTimeWorld"):
for rule in access_rules:
add_rule(entrance, rule)
if world.options.EndGoal.value == 3:
if world.options.EndGoal == EndGoal.option_seal_the_deal:
world.multiworld.completion_condition[world.player] = lambda state: \
state.has("1 Stamp - Seal the Deal", world.player)
@@ -196,10 +196,10 @@ def add_dw_rules(world: "HatInTimeWorld", loc: Location):
for misc in data.misc_required:
add_rule(loc, lambda state, item=misc: state.has(item, world.player))
if data.paintings > 0 and world.options.ShuffleSubconPaintings.value > 0:
if data.paintings > 0 and world.options.ShuffleSubconPaintings:
add_rule(loc, lambda state, paintings=data.paintings: has_paintings(state, world, paintings))
if data.hit_type is not HitType.none and world.options.UmbrellaLogic.value > 0:
if data.hit_type is not HitType.none and world.options.UmbrellaLogic:
if data.hit_type == HitType.umbrella:
add_rule(loc, lambda state: state.has("Umbrella", world.player))
@@ -260,7 +260,7 @@ def modify_dw_rules(world: "HatInTimeWorld", name: str):
def get_total_dw_stamps(state: CollectionState, world: "HatInTimeWorld") -> int:
if world.options.DWShuffle.value > 0:
if world.options.DWShuffle:
return 999 # no stamp costs in death wish shuffle
count = 0
@@ -293,7 +293,7 @@ def set_candle_dw_rules(name: str, world: "HatInTimeWorld"):
# No Ice Hat/painting required in Expert for Toilet Zero Jumps
# This painting wall can only be skipped via cherry hover.
if get_difficulty(world) < Difficulty.EXPERT or world.options.NoPaintingSkips.value == 1:
if get_difficulty(world) < Difficulty.EXPERT or world.options.NoPaintingSkips:
set_rule(world.multiworld.get_location("Toilet of Doom (Zero Jumps)", world.player),
lambda state: can_use_hookshot(state, world) and can_hit(state, world)
and has_paintings(state, world, 1, False))
@@ -377,14 +377,13 @@ def create_enemy_events(world: "HatInTimeWorld"):
if (area == "Bon Voyage!" or area == "Time Rift - Deep Sea") and not world.is_dlc1():
continue
if area == "Time Rift - Tour" and (not world.is_dlc1()
or world.options.ExcludeTour.value > 0):
if area == "Time Rift - Tour" and (not world.is_dlc1() or world.options.ExcludeTour):
continue
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.dw_shuffle:
if world.options.DWShuffle and area in death_wishes.keys() and area not in world.dw_shuffle:
continue
region = world.multiworld.get_region(area, world.player)
@@ -394,10 +393,10 @@ def create_enemy_events(world: "HatInTimeWorld"):
event.show_in_spoiler = False
for name in triple_enemy_locations:
if name == "Time Rift - Tour" and (not world.is_dlc1() or world.options.ExcludeTour.value > 0):
if name == "Time Rift - Tour" and (not world.is_dlc1() or world.options.ExcludeTour):
continue
if world.options.DWShuffle.value > 0 and name in death_wishes.keys() \
if world.options.DWShuffle and name in death_wishes.keys() \
and name not in world.dw_shuffle:
continue
@@ -421,15 +420,13 @@ def set_enemy_rules(world: "HatInTimeWorld"):
if (area == "Bon Voyage!" or area == "Time Rift - Deep Sea") and not world.is_dlc1():
continue
if area == "Time Rift - Tour" and (not world.is_dlc1()
or world.options.ExcludeTour.value > 0):
if area == "Time Rift - Tour" and (not world.is_dlc1() or world.options.ExcludeTour):
continue
if area == "Bluefin Tunnel" and not world.is_dlc2():
continue
if world.options.DWShuffle.value > 0 and area in death_wishes \
and area not in world.dw_shuffle:
if world.options.DWShuffle and area in death_wishes and area not in world.dw_shuffle:
continue
event = world.multiworld.get_location(f"{enemy} - {area}", world.player)

View File

@@ -96,7 +96,7 @@ def calculate_yarn_costs(world: "HatInTimeWorld"):
extra_yarn = max_cost + world.options.MinExtraYarn - available_yarn
if extra_yarn > 0:
world.options.YarnAvailable.value += extra_yarn
world.options.YarnAvailable.value += extra_yarn
def item_dlc_enabled(world: "HatInTimeWorld", name: str) -> bool:

View File

@@ -16,20 +16,20 @@ def get_total_locations(world: "HatInTimeWorld") -> int:
if is_location_valid(world, name):
total += 1
if world.is_dlc1() and world.options.Tasksanity.value > 0:
total += world.options.TasksanityCheckCount.value
if world.is_dlc1() and world.options.Tasksanity:
total += world.options.TasksanityCheckCount
if world.is_dw():
if world.options.DWShuffle.value > 0:
if world.options.DWShuffle:
total += len(world.dw_shuffle)
if world.options.DWEnableBonus.value > 0:
if world.options.DWEnableBonus:
total += len(world.dw_shuffle)
else:
total += 37
if world.is_dlc2():
total += 1
if world.options.DWEnableBonus.value > 0:
if world.options.DWEnableBonus:
total += 37
if world.is_dlc2():
total += 1
@@ -60,39 +60,36 @@ def is_location_valid(world: "HatInTimeWorld", location: str) -> bool:
if not location_dlc_enabled(world, location):
return False
if world.options.ShuffleStorybookPages.value == 0 \
and location in storybook_pages.keys():
if not world.options.ShuffleStorybookPages and location in storybook_pages.keys():
return False
if world.options.ShuffleActContracts.value == 0 \
and location in contract_locations.keys():
if not world.options.ShuffleActContracts and location in contract_locations.keys():
return False
if location not in world.shop_locs and location in shop_locations:
return False
data = location_table.get(location) or event_locs.get(location)
if world.options.ExcludeTour.value > 0 and data.region == "Time Rift - Tour":
if world.options.ExcludeTour and data.region == "Time Rift - Tour":
return False
# No need for all those event items if we're not doing candles
if data.dlc_flags & HatDLC.death_wish:
if world.options.DWExcludeCandles.value > 0 and location in event_locs.keys():
if world.options.DWExcludeCandles and location in event_locs.keys():
return False
if world.options.DWShuffle.value > 0 \
and data.region in death_wishes and data.region not in world.dw_shuffle:
if world.options.DWShuffle 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.dw_shuffle:
if world.options.DWShuffle and "Zero Jumps" not in world.dw_shuffle:
return False
difficulty: int = world.options.LogicDifficulty.value
if location in zero_jumps_hard and difficulty < int(Difficulty.HARD):
difficulty: Difficulty = Difficulty(world.options.LogicDifficulty)
if location in zero_jumps_hard and difficulty < Difficulty.HARD:
return False
if location in zero_jumps_expert and difficulty < int(Difficulty.EXPERT):
if location in zero_jumps_expert and difficulty < Difficulty.EXPERT:
return False
return True

View File

@@ -4,6 +4,7 @@ from .Locations import location_table, storybook_pages, event_locs, is_location_
shop_locations, TASKSANITY_START_ID, snatcher_coins, zero_jumps, zero_jumps_expert, zero_jumps_hard
from typing import TYPE_CHECKING, List, Dict
from .Rules import set_rift_rules, get_difficulty
from .Options import ActRandomizer, EndGoal
if TYPE_CHECKING:
from . import HatInTimeWorld
@@ -453,7 +454,7 @@ def randomize_act_entrances(world: "HatInTimeWorld"):
rift_dict: Dict[str, Region] = {}
# Check if Plando's are valid, if so, map them
if len(world.options.ActPlando) > 0:
if world.options.ActPlando:
player_name = world.multiworld.get_player_name(world.player)
for (name1, name2) in world.options.ActPlando.items():
region: Region
@@ -507,7 +508,7 @@ def randomize_act_entrances(world: "HatInTimeWorld"):
first_act_mapped = True
break # we can stop here, as we only need one
if is_valid_act_combo(world, region, c, bool(world.options.ActRandomizer.value == 1), ignore_certain_rules):
if is_valid_act_combo(world, region, c, ignore_certain_rules):
valid_candidates.append(c)
if len(valid_candidates) > 0:
@@ -598,11 +599,11 @@ def connect_acts(world: "HatInTimeWorld", entrance_act: Region, exit_act: Region
def is_valid_act_combo(world: "HatInTimeWorld", entrance_act: Region,
exit_act: Region, separate_rifts: bool, ignore_certain_rules=False) -> bool:
exit_act: Region, ignore_certain_rules: bool = False) -> bool:
# Ignore certain rules that aren't to prevent impossible combos. This is needed for ActPlando.
if not ignore_certain_rules:
if separate_rifts and not ignore_certain_rules:
if world.options.ActRandomizer == ActRandomizer.option_light and not ignore_certain_rules:
# Don't map Time Rifts to normal acts
if "Time Rift" in entrance_act.name and "Time Rift" not in exit_act.name:
return False
@@ -616,7 +617,7 @@ def is_valid_act_combo(world: "HatInTimeWorld", entrance_act: Region,
or entrance_act.name not in purple_time_rifts and exit_act.name in purple_time_rifts:
return False
if world.options.FinaleShuffle.value > 0 and entrance_act.name in chapter_finales:
if world.options.FinaleShuffle and entrance_act.name in chapter_finales:
if exit_act.name not in chapter_finales:
return False
@@ -633,7 +634,7 @@ def is_valid_act_combo(world: "HatInTimeWorld", entrance_act: Region,
return False
# Prevent Contractual Obligations from being inaccessible if contracts are not shuffled
if world.options.ShuffleActContracts.value == 0:
if not world.options.ShuffleActContracts:
if (entrance_act.name == "Your Contract has Expired" or entrance_act.name == "The Subcon Well") \
and exit_act.name == "Contractual Obligations":
return False
@@ -646,12 +647,11 @@ def is_valid_first_act(world: "HatInTimeWorld", act: Region) -> bool:
return False
# Not completable without Umbrella
if world.options.UmbrellaLogic.value > 0 \
and (act.name == "Heating Up Mafia Town" or act.name == "Queen Vanessa's Manor"):
if world.options.UmbrellaLogic and (act.name == "Heating Up Mafia Town" or act.name == "Queen Vanessa's Manor"):
return False
# Subcon sphere 1 is too small without painting unlocks, and no acts are completable either
if world.options.ShuffleSubconPaintings.value > 0 and "Subcon Forest" in act_entrances[act.name]:
if world.options.ShuffleSubconPaintings and "Subcon Forest" in act_entrances[act.name]:
return False
return True
@@ -696,13 +696,13 @@ def is_act_blacklisted(world: "HatInTimeWorld", name: str) -> bool:
break
if name == "The Finale":
return not plando and world.options.EndGoal.value == 1
return not plando and world.options.EndGoal == EndGoal.option_finale
if name == "Rush Hour":
return not plando and world.options.EndGoal.value == 2
return not plando and world.options.EndGoal == EndGoal.option_rush_hour
if name == "Time Rift - Tour":
return world.options.ExcludeTour.value > 0
return bool(world.options.ExcludeTour)
return name in blacklisted_acts.values()
@@ -763,8 +763,7 @@ def create_region(world: "HatInTimeWorld", name: str) -> Region:
continue
if data.region == name:
if key in storybook_pages.keys() \
and world.options.ShuffleStorybookPages.value == 0:
if key in storybook_pages.keys() and not world.options.ShuffleStorybookPages:
continue
location = HatInTimeLocation(world.player, key, data.id, reg)
@@ -782,7 +781,7 @@ def create_badge_seller(world: "HatInTimeWorld") -> Region:
count = 0
max_items = 0
if world.options.BadgeSellerMaxItems.value > 0:
if world.options.BadgeSellerMaxItems > 0:
max_items = world.random.randint(world.options.BadgeSellerMinItems.value,
world.options.BadgeSellerMaxItems.value)
@@ -851,7 +850,7 @@ def create_region_and_connect(world: "HatInTimeWorld",
def get_first_chapter_region(world: "HatInTimeWorld") -> Region:
start_chapter: ChapterIndex = ChapterIndex(world.options.StartingChapter.value)
start_chapter: ChapterIndex = ChapterIndex(world.options.StartingChapter)
return world.multiworld.get_region(chapter_regions.get(start_chapter), world.player)

View File

@@ -5,6 +5,7 @@ from .Locations import location_table, zipline_unlocks, is_location_valid, contr
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
from .Options import EndGoal, CTRLogic
if TYPE_CHECKING:
from . import HatInTimeWorld
@@ -35,7 +36,7 @@ act_connections = {
def can_use_hat(state: CollectionState, world: "HatInTimeWorld", hat: HatType) -> bool:
if world.options.HatItems.value > 0:
if world.options.HatItems:
return state.has(hat_type_to_item[hat], world.player)
return state.count("Yarn", world.player) >= get_hat_cost(world, hat)
@@ -56,19 +57,19 @@ def can_sdj(state: CollectionState, world: "HatInTimeWorld"):
def painting_logic(world: "HatInTimeWorld") -> bool:
return world.options.ShuffleSubconPaintings.value > 0
return bool(world.options.ShuffleSubconPaintings)
# -1 = Normal, 0 = Moderate, 1 = Hard, 2 = Expert
def get_difficulty(world: "HatInTimeWorld") -> Difficulty:
return Difficulty(world.options.LogicDifficulty.value)
return Difficulty(world.options.LogicDifficulty)
def has_paintings(state: CollectionState, world: "HatInTimeWorld", count: int, allow_skip: bool = True) -> bool:
if not painting_logic(world):
return True
if world.options.NoPaintingSkips.value == 0 and allow_skip:
if not world.options.NoPaintingSkips and allow_skip:
# In Moderate there is a very easy trick to skip all the walls, except for the one guarding the boss arena
if get_difficulty(world) >= Difficulty.MODERATE:
return True
@@ -77,7 +78,7 @@ def has_paintings(state: CollectionState, world: "HatInTimeWorld", count: int, a
def zipline_logic(world: "HatInTimeWorld") -> bool:
return world.options.ShuffleAlpineZiplines.value > 0
return bool(world.options.ShuffleAlpineZiplines)
def can_use_hookshot(state: CollectionState, world: "HatInTimeWorld"):
@@ -85,7 +86,7 @@ def can_use_hookshot(state: CollectionState, world: "HatInTimeWorld"):
def can_hit(state: CollectionState, world: "HatInTimeWorld", umbrella_only: bool = False):
if world.options.UmbrellaLogic.value == 0:
if not world.options.UmbrellaLogic:
return True
return state.has("Umbrella", world.player) or not umbrella_only and can_use_hat(state, world, HatType.BREWING)
@@ -134,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)
starting_chapter = ChapterIndex(world.options.StartingChapter)
world.chapter_timepiece_costs[starting_chapter] = 0
# Chapter costs increase progressively. Randomly decide the chapter order, except for Finale
@@ -142,10 +143,10 @@ def set_rules(world: "HatInTimeWorld"):
ChapterIndex.SUBCON, ChapterIndex.ALPINE]
final_chapter = ChapterIndex.FINALE
if world.options.EndGoal.value == 2:
if world.options.EndGoal == EndGoal.option_rush_hour:
final_chapter = ChapterIndex.METRO
chapter_list.append(ChapterIndex.FINALE)
elif world.options.EndGoal.value == 3:
elif world.options.EndGoal == EndGoal.option_seal_the_deal:
final_chapter = None
chapter_list.append(ChapterIndex.FINALE)
@@ -203,7 +204,7 @@ def set_rules(world: "HatInTimeWorld"):
if final_chapter is not None:
final_chapter_cost: int
if world.options.FinalChapterMinCost.value == world.options.FinalChapterMaxCost.value:
if world.options.FinalChapterMinCost == world.options.FinalChapterMaxCost:
final_chapter_cost = world.options.FinalChapterMaxCost.value
else:
final_chapter_cost = world.random.randint(world.options.FinalChapterMinCost.value,
@@ -238,7 +239,7 @@ def set_rules(world: "HatInTimeWorld"):
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:
if not world.options.ActRandomizer:
set_default_rift_rules(world)
table = {**location_table, **event_locs}
@@ -258,10 +259,10 @@ def set_rules(world: "HatInTimeWorld"):
if data.hookshot:
add_rule(loc, lambda state: can_use_hookshot(state, world))
if data.paintings > 0 and world.options.ShuffleSubconPaintings.value > 0:
if data.paintings > 0 and world.options.ShuffleSubconPaintings:
add_rule(loc, lambda state, paintings=data.paintings: has_paintings(state, world, paintings))
if data.hit_type is not HitType.none and world.options.UmbrellaLogic.value > 0:
if data.hit_type is not HitType.none and world.options.UmbrellaLogic:
if data.hit_type == HitType.umbrella:
add_rule(loc, lambda state: state.has("Umbrella", world.player))
@@ -283,7 +284,7 @@ def set_rules(world: "HatInTimeWorld"):
# Illness starts the player past the intro
alpine_entrance = world.multiworld.get_entrance("AFR -> Alpine Skyline Area", world.player)
add_rule(alpine_entrance, lambda state: can_use_hookshot(state, world))
if world.options.UmbrellaLogic.value > 0:
if world.options.UmbrellaLogic:
add_rule(alpine_entrance, lambda state: state.has("Umbrella", world.player))
if zipline_logic(world):
@@ -347,9 +348,9 @@ def set_rules(world: "HatInTimeWorld"):
set_event_rules(world)
if world.options.EndGoal.value == 1:
if world.options.EndGoal == EndGoal.option_finale:
world.multiworld.completion_condition[world.player] = lambda state: state.has("Time Piece Cluster", world.player)
elif world.options.EndGoal.value == 2:
elif world.options.EndGoal == EndGoal.option_rush_hour:
world.multiworld.completion_condition[world.player] = lambda state: state.has("Rush Hour Cleared", world.player)
@@ -472,7 +473,7 @@ def set_moderate_rules(world: "HatInTimeWorld"):
and can_use_hat(state, world, HatType.BREWING))
# Moderate: Bluefin Tunnel + Pink Paw Station without tickets
if world.options.NoTicketSkips.value == 0:
if not world.options.NoTicketSkips:
set_rule(world.multiworld.get_entrance("-> Pink Paw Station", world.player), lambda state: True)
set_rule(world.multiworld.get_entrance("-> Bluefin Tunnel", world.player), lambda state: True)
@@ -523,7 +524,7 @@ def set_hard_rules(world: "HatInTimeWorld"):
lambda state: can_use_hat(state, world, HatType.ICE))
# Hard: clear Rush Hour with Brewing Hat only
if world.options.NoTicketSkips.value != 1:
if not world.options.NoTicketSkips:
set_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player),
lambda state: can_use_hat(state, world, HatType.BREWING))
else:
@@ -579,7 +580,7 @@ def set_expert_rules(world: "HatInTimeWorld"):
world.multiworld.get_region("Subcon Forest Area", world.player),
"Subcon Forest Entrance YCHE", world.player)
if world.options.NoPaintingSkips.value > 0:
if world.options.NoPaintingSkips:
add_rule(entrance, lambda state: has_paintings(state, world, 1))
set_rule(world.multiworld.get_location("Act Completion (Toilet of Doom)", world.player),
@@ -603,7 +604,7 @@ def set_expert_rules(world: "HatInTimeWorld"):
if world.is_dlc2():
# Expert: clear Rush Hour with nothing
if world.options.NoTicketSkips.value == 0:
if not world.options.NoTicketSkips:
set_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player), lambda state: True)
else:
set_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player),
@@ -660,20 +661,19 @@ def set_mafia_town_rules(world: "HatInTimeWorld"):
add_rule(world.multiworld.get_location("Mafia Town - Above Boats", world.player),
lambda state: state.has("HUMT Access", world.player), "or")
ctr_logic: int = world.options.CTRLogic.value
if ctr_logic == 3:
if world.options.CTRLogic == CTRLogic.option_nothing:
set_rule(world.multiworld.get_location("Act Completion (Cheating the Race)", world.player), lambda state: True)
elif ctr_logic == 2:
elif world.options.CTRLogic == CTRLogic.option_sprint:
add_rule(world.multiworld.get_location("Act Completion (Cheating the Race)", world.player),
lambda state: can_use_hat(state, world, HatType.SPRINT), "or")
elif ctr_logic == 1:
elif world.options.CTRLogic == CTRLogic.option_scooter:
add_rule(world.multiworld.get_location("Act Completion (Cheating the Race)", world.player),
lambda state: can_use_hat(state, world, HatType.SPRINT)
and state.has("Scooter Badge", world.player), "or")
def set_botb_rules(world: "HatInTimeWorld"):
if world.options.UmbrellaLogic.value == 0 and get_difficulty(world) < Difficulty.MODERATE:
if not world.options.UmbrellaLogic and get_difficulty(world) < Difficulty.MODERATE:
set_rule(world.multiworld.get_location("Dead Bird Studio - DJ Grooves Sign Chest", world.player),
lambda state: state.has("Umbrella", world.player) or can_use_hat(state, world, HatType.BREWING))
set_rule(world.multiworld.get_location("Dead Bird Studio - Tepee Chest", world.player),

View File

@@ -5,7 +5,7 @@ from .Regions import create_regions, randomize_act_entrances, chapter_act_info,
from .Locations import location_table, contract_locations, is_location_valid, get_location_names, TASKSANITY_START_ID, \
get_total_locations
from .Rules import set_rules
from .Options import AHITOptions, slot_data_options, adjust_options
from .Options import AHITOptions, slot_data_options, adjust_options, RandomizeHatOrder, EndGoal
from .Types import HatType, ChapterIndex, HatInTimeItem
from .DeathWishLocations import create_dw_regions, dw_classes, death_wishes
from .DeathWishRules import set_dw_rules, create_enemy_events
@@ -87,24 +87,24 @@ class HatInTimeWorld(World):
# If our starting chapter is 4 and act rando isn't on, force hookshot into inventory
# If starting chapter is 3 and painting shuffle is enabled, and act rando isn't, give one free painting unlock
start_chapter: int = self.options.StartingChapter.value
start_chapter: ChapterIndex = ChapterIndex(self.options.StartingChapter)
if start_chapter == 4 or start_chapter == 3:
if self.options.ActRandomizer.value == 0:
if start_chapter == 4:
if start_chapter == ChapterIndex.ALPINE or start_chapter == ChapterIndex.SUBCON:
if not self.options.ActRandomizer:
if start_chapter == ChapterIndex.ALPINE:
self.multiworld.push_precollected(self.create_item("Hookshot Badge"))
if self.options.UmbrellaLogic.value > 0:
if self.options.UmbrellaLogic:
self.multiworld.push_precollected(self.create_item("Umbrella"))
if start_chapter == 3 and self.options.ShuffleSubconPaintings.value > 0:
if start_chapter == ChapterIndex.SUBCON and self.options.ShuffleSubconPaintings:
self.multiworld.push_precollected(self.create_item("Progressive Painting Unlock"))
def create_regions(self):
# noinspection PyClassVar
self.topology_present = bool(self.options.ActRandomizer.value)
self.topology_present = bool(self.options.ActRandomizer)
create_regions(self)
if self.options.EnableDeathWish.value > 0:
if self.options.EnableDeathWish:
create_dw_regions(self)
if self.is_dw_only():
@@ -116,7 +116,7 @@ class HatInTimeWorld(World):
create_enemy_events(self)
# place vanilla contract locations if contract shuffle is off
if self.options.ShuffleActContracts.value == 0:
if not self.options.ShuffleActContracts:
for name in contract_locations.keys():
self.multiworld.get_location(name, self.player).place_locked_item(create_item(self, name))
@@ -124,9 +124,9 @@ class HatInTimeWorld(World):
if self.has_yarn():
calculate_yarn_costs(self)
if self.options.RandomizeHatOrder.value > 0:
if self.options.RandomizeHatOrder:
self.random.shuffle(self.hat_craft_order)
if self.options.RandomizeHatOrder.value == 2:
if self.options.RandomizeHatOrder == RandomizeHatOrder.option_time_stop_last:
self.hat_craft_order.remove(HatType.TIME_STOP)
self.hat_craft_order.append(HatType.TIME_STOP)
@@ -141,12 +141,12 @@ class HatInTimeWorld(World):
self.multiworld.completion_condition[self.player] = lambda state: state.has("Death Wish Only Mode",
self.player)
if self.options.DWEnableBonus.value == 0:
if not self.options.DWEnableBonus:
for name in death_wishes:
if name == "Snatcher Coins in Nyakuza Metro" and not self.is_dlc2():
continue
if self.options.DWShuffle.value > 0 and name not in self.dw_shuffle:
if self.options.DWShuffle and name not in self.dw_shuffle:
continue
full_clear = self.multiworld.get_location(f"{name} - All Clear", self.player)
@@ -156,7 +156,7 @@ class HatInTimeWorld(World):
return
if self.options.ActRandomizer.value > 0:
if self.options.ActRandomizer:
randomize_act_entrances(self)
set_rules(self)
@@ -192,7 +192,7 @@ class HatInTimeWorld(World):
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:
if self.options.ActRandomizer:
for name in self.act_connections.keys():
slot_data[name] = self.act_connections[name]
@@ -203,14 +203,14 @@ class HatInTimeWorld(World):
if self.is_dw():
i = 0
for name in self.excluded_dws:
if self.options.EndGoal.value == 3 and name == "Seal the Deal":
if self.options.EndGoal.value == EndGoal.option_seal_the_deal and name == "Seal the Deal":
continue
slot_data[f"excluded_dw{i}"] = dw_classes[name]
i += 1
i = 0
if self.options.DWAutoCompleteBonuses.value == 0:
if not self.options.DWAutoCompleteBonuses:
for name in self.excluded_bonuses:
if name in self.excluded_dws:
continue
@@ -218,7 +218,7 @@ class HatInTimeWorld(World):
slot_data[f"excluded_bonus{i}"] = dw_classes[name]
i += 1
if self.options.DWShuffle.value > 0:
if self.options.DWShuffle:
shuffled_dws = self.dw_shuffle
for i in range(len(shuffled_dws)):
slot_data[f"dw_{i}"] = dw_classes[shuffled_dws[i]]
@@ -244,7 +244,7 @@ class HatInTimeWorld(World):
return slot_data
def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]):
if self.is_dw_only() or self.options.ActRandomizer.value == 0:
if self.is_dw_only() or not self.options.ActRandomizer:
return
new_hint_data = {}
@@ -273,10 +273,10 @@ class HatInTimeWorld(World):
new_hint_data[location.address] = get_shuffled_region(self, region_name)
if self.is_dlc1() and self.options.Tasksanity.value > 0:
if self.is_dlc1() and self.options.Tasksanity:
ship_shape_region = get_shuffled_region(self, "Ship Shape")
id_start: int = TASKSANITY_START_ID
for i in range(self.options.TasksanityCheckCount.value):
for i in range(self.options.TasksanityCheckCount):
new_hint_data[id_start+i] = ship_shape_region
hint_data[self.player] = new_hint_data
@@ -289,23 +289,23 @@ class HatInTimeWorld(World):
spoiler_handle.write("Hat Cost: %s: %i\n" % (hat, self.hat_yarn_costs[hat]))
def has_yarn(self) -> bool:
return not self.is_dw_only() and self.options.HatItems.value == 0
return not self.is_dw_only() and not self.options.HatItems
def is_dlc1(self) -> bool:
return self.options.EnableDLC1.value > 0
return bool(self.options.EnableDLC1)
def is_dlc2(self) -> bool:
return self.options.EnableDLC2.value > 0
return bool(self.options.EnableDLC2)
def is_dw(self) -> bool:
return self.options.EnableDeathWish.value > 0
return bool(self.options.EnableDeathWish)
def is_dw_only(self) -> bool:
return self.is_dw() and self.options.DeathWishOnly.value > 0
return self.is_dw() and bool(self.options.DeathWishOnly)
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" \
if self.options.EndGoal.value == EndGoal.option_seal_the_deal and name == "Seal the Deal" \
and f"{name} - Main Objective" not in self.options.exclude_locations:
return False