Update to new options API

This commit is contained in:
CookieCat
2023-10-26 23:02:34 -04:00
parent 25a39a46ad
commit 2ce7b526fd
8 changed files with 252 additions and 252 deletions

View File

@@ -139,19 +139,19 @@ dw_classes = {
def create_dw_regions(world: World):
if world.multiworld.DWExcludeAnnoyingContracts[world.player].value > 0:
if world.options.DWExcludeAnnoyingContracts.value > 0:
for name in annoying_dws:
world.get_excluded_dws().append(name)
if world.multiworld.DWEnableBonus[world.player].value == 0 \
or world.multiworld.DWAutoCompleteBonuses[world.player].value > 0:
if world.options.DWEnableBonus.value == 0 \
or world.options.DWAutoCompleteBonuses.value > 0:
for name in death_wishes:
world.get_excluded_bonuses().append(name)
elif world.multiworld.DWExcludeAnnoyingBonuses[world.player].value > 0:
elif world.options.DWExcludeAnnoyingBonuses.value > 0:
for name in annoying_bonuses:
world.get_excluded_bonuses().append(name)
if world.multiworld.DWExcludeCandles[world.player].value > 0:
if world.options.DWExcludeCandles.value > 0:
for name in dw_candles:
if name in world.get_excluded_dws():
continue
@@ -162,9 +162,9 @@ def create_dw_regions(world: World):
entrance = connect_regions(spaceship, dw_map, "-> Death Wish Map", world.player)
add_rule(entrance, lambda state: state.has("Time Piece", world.player,
world.multiworld.DWTimePieceRequirement[world.player].value))
world.options.DWTimePieceRequirement.value))
if world.multiworld.DWShuffle[world.player].value > 0:
if world.options.DWShuffle.value > 0:
dw_list: List[str] = []
for name in death_wishes.keys():
if not world.is_dlc2() and name == "Snatcher Coins in Nyakuza Metro" or world.is_dw_excluded(name):
@@ -173,8 +173,8 @@ def create_dw_regions(world: World):
dw_list.append(name)
world.random.shuffle(dw_list)
count = world.random.randint(world.multiworld.DWShuffleCountMin[world.player].value,
world.multiworld.DWShuffleCountMax[world.player].value)
count = world.random.randint(world.options.DWShuffleCountMin.value,
world.options.DWShuffleCountMax.value)
dw_shuffle: List[str] = []
total = min(len(dw_list), count)
@@ -182,7 +182,7 @@ def create_dw_regions(world: World):
dw_shuffle.append(dw_list[i])
# Seal the Deal is always last if it's the goal
if world.multiworld.EndGoal[world.player].value == 3:
if world.options.EndGoal.value == 3:
if "Seal the Deal" in dw_shuffle:
dw_shuffle.remove("Seal the Deal")

View File

@@ -105,7 +105,7 @@ def set_dw_rules(world: World):
set_enemy_rules(world)
dw_list: List[str] = []
if world.multiworld.DWShuffle[world.player].value > 0:
if world.options.DWShuffle.value > 0:
dw_list = world.get_dw_shuffle()
else:
for name in death_wishes.keys():
@@ -124,12 +124,12 @@ def set_dw_rules(world: World):
temp_list.append(main_objective)
temp_list.append(full_clear)
if world.multiworld.DWShuffle[world.player].value == 0:
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 world.multiworld.DWEnableBonus[world.player].value == 0:
if world.options.DWEnableBonus.value == 0:
# place nothing, but let the locations exist still, so we can use them for bonus stamp rules
full_clear.address = None
full_clear.place_locked_item(HatInTimeItem("Nothing", ItemClassification.filler, None, world.player))
@@ -165,10 +165,10 @@ def set_dw_rules(world: World):
for misc in data.misc_required:
add_rule(loc, lambda state, item=misc: state.has(item, world.player))
if data.umbrella and world.multiworld.UmbrellaLogic[world.player].value > 0:
if data.umbrella and world.options.UmbrellaLogic.value > 0:
add_rule(loc, lambda state: state.has("Umbrella", world.player))
if data.paintings > 0 and world.multiworld.ShuffleSubconPaintings[world.player].value > 0:
if data.paintings > 0 and world.options.ShuffleSubconPaintings.value > 0:
add_rule(loc, lambda state, paintings=data.paintings: has_paintings(state, world, paintings))
if data.hit_requirement > 0:
@@ -184,11 +184,11 @@ def set_dw_rules(world: World):
elif loc.name == full_clear.name:
add_rule(loc, main_rule)
# Only set bonus stamp rules if we don't auto complete bonuses
if world.multiworld.DWAutoCompleteBonuses[world.player].value == 0 \
if world.options.DWAutoCompleteBonuses.value == 0 \
and not world.is_bonus_excluded(loc.name):
add_rule(bonus_stamps, loc.access_rule)
if world.multiworld.DWShuffle[world.player].value > 0:
if world.options.DWShuffle.value > 0:
dw_shuffle = world.get_dw_shuffle()
for i in range(len(dw_shuffle)):
if i == 0:
@@ -217,7 +217,7 @@ def set_dw_rules(world: World):
for rule in access_rules:
add_rule(entrance, rule)
if world.multiworld.EndGoal[world.player].value == 3:
if world.options.EndGoal.value == 3:
world.multiworld.completion_condition[world.player] = lambda state: state.has("1 Stamp - Seal the Deal",
world.player)
@@ -269,7 +269,7 @@ def modify_dw_rules(world: World, name: str):
def get_total_dw_stamps(state: CollectionState, world: World) -> int:
if world.multiworld.DWShuffle[world.player].value > 0:
if world.options.DWShuffle.value > 0:
return 999 # no stamp costs in death wish shuffle
count: int = 0
@@ -303,7 +303,7 @@ def set_candle_dw_rules(name: str, world: World):
# 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.multiworld.NoPaintingSkips[world.player].value == 1:
if get_difficulty(world) < Difficulty.EXPERT or world.options.NoPaintingSkips.value == 1:
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))
@@ -383,13 +383,13 @@ def create_enemy_events(world: World):
continue
if area == "Time Rift - Tour" and (not world.is_dlc1()
or world.multiworld.ExcludeTour[world.player].value > 0):
or world.options.ExcludeTour.value > 0):
continue
if area == "Bluefin Tunnel" and not world.is_dlc2():
continue
if world.multiworld.DWShuffle[world.player].value > 0 and area in death_wishes.keys() \
if world.options.DWShuffle.value > 0 and area in death_wishes.keys() \
and area not in world.get_dw_shuffle():
continue
@@ -400,14 +400,14 @@ def create_enemy_events(world: World):
event.show_in_spoiler = False
for name in triple_enemy_locations:
if name == "Time Rift - Tour" and (not world.is_dlc1() or world.multiworld.ExcludeTour[world.player].value > 0):
if name == "Time Rift - Tour" and (not world.is_dlc1() or world.options.ExcludeTour.value > 0):
continue
if world.multiworld.DWShuffle[world.player].value > 0 and name in death_wishes.keys() \
if world.options.DWShuffle.value > 0 and name in death_wishes.keys() \
and name not in world.get_dw_shuffle():
continue
region = world.multiworld.get_region(name, world.player)
region = world.options.get_region(name, world.player)
event = HatInTimeLocation(world.player, f"Triple Enemy Picture - {name}", None, region)
event.place_locked_item(HatInTimeItem("Triple Enemy Picture", ItemClassification.progression, None, world.player))
region.locations.append(event)
@@ -428,13 +428,13 @@ def set_enemy_rules(world: World):
continue
if area == "Time Rift - Tour" and (not world.is_dlc1()
or world.multiworld.ExcludeTour[world.player].value > 0):
or world.options.ExcludeTour.value > 0):
continue
if area == "Bluefin Tunnel" and not world.is_dlc2():
continue
if world.multiworld.DWShuffle[world.player].value > 0 and area in death_wishes \
if world.options.DWShuffle.value > 0 and area in death_wishes \
and area not in world.get_dw_shuffle():
continue

View File

@@ -8,13 +8,13 @@ from typing import Optional, List, Dict
def create_itempool(world: World) -> List[Item]:
itempool: List[Item] = []
if not world.is_dw_only() and world.multiworld.HatItems[world.player].value == 0:
if not world.is_dw_only() and world.options.HatItems.value == 0:
calculate_yarn_costs(world)
yarn_pool: List[Item] = create_multiple_items(world, "Yarn",
world.multiworld.YarnAvailable[world.player].value,
world.options.YarnAvailable.value,
ItemClassification.progression_skip_balancing)
for i in range(int(len(yarn_pool) * (0.01 * world.multiworld.YarnBalancePercent[world.player].value))):
for i in range(int(len(yarn_pool) * (0.01 * world.options.YarnBalancePercent.value))):
yarn_pool[i].classification = ItemClassification.progression
itempool += yarn_pool
@@ -26,7 +26,7 @@ def create_itempool(world: World) -> List[Item]:
if not item_dlc_enabled(world, name):
continue
if world.multiworld.HatItems[world.player].value == 0 and name in hat_type_to_item.values():
if world.options.HatItems.value == 0 and name in hat_type_to_item.values():
continue
item_type: ItemClassification = item_table.get(name).classification
@@ -37,7 +37,7 @@ def create_itempool(world: World) -> List[Item]:
continue
else:
if name == "Scooter Badge":
if world.multiworld.CTRLogic[world.player].value >= 1 or get_difficulty(world) >= Difficulty.MODERATE:
if world.options.CTRLogic.value >= 1 or get_difficulty(world) >= Difficulty.MODERATE:
item_type = ItemClassification.progression
elif name == "No Bonk Badge":
if get_difficulty(world) >= Difficulty.MODERATE:
@@ -50,17 +50,17 @@ def create_itempool(world: World) -> List[Item]:
if item_type is ItemClassification.filler or item_type is ItemClassification.trap:
continue
if name in act_contracts.keys() and world.multiworld.ShuffleActContracts[world.player].value == 0:
if name in act_contracts.keys() and world.options.ShuffleActContracts.value == 0:
continue
if name in alps_hooks.keys() and world.multiworld.ShuffleAlpineZiplines[world.player].value == 0:
if name in alps_hooks.keys() and world.options.ShuffleAlpineZiplines.value == 0:
continue
if name == "Progressive Painting Unlock" \
and world.multiworld.ShuffleSubconPaintings[world.player].value == 0:
and world.options.ShuffleSubconPaintings.value == 0:
continue
if world.multiworld.StartWithCompassBadge[world.player].value > 0 and name == "Compass Badge":
if world.options.StartWithCompassBadge.value > 0 and name == "Compass Badge":
continue
if name == "Time Piece":
@@ -72,10 +72,10 @@ def create_itempool(world: World) -> List[Item]:
if world.is_dlc2():
max_extra += 10
tp_count += min(max_extra, world.multiworld.MaxExtraTimePieces[world.player].value)
tp_count += min(max_extra, world.options.MaxExtraTimePieces.value)
tp_list: List[Item] = create_multiple_items(world, name, tp_count, item_type)
for i in range(int(len(tp_list) * (0.01 * world.multiworld.TimePieceBalancePercent[world.player].value))):
for i in range(int(len(tp_list) * (0.01 * world.options.TimePieceBalancePercent.value))):
tp_list[i].classification = ItemClassification.progression
itempool += tp_list
@@ -90,8 +90,8 @@ def create_itempool(world: World) -> List[Item]:
def calculate_yarn_costs(world: World):
mw = world.multiworld
p = world.player
min_yarn_cost = int(min(mw.YarnCostMin[p].value, mw.YarnCostMax[p].value))
max_yarn_cost = int(max(mw.YarnCostMin[p].value, mw.YarnCostMax[p].value))
min_yarn_cost = int(min(world.options.YarnCostMin.value, world.options.YarnCostMax.value))
max_yarn_cost = int(max(world.options.YarnCostMin.value, world.options.YarnCostMax.value))
max_cost: int = 0
for i in range(5):
@@ -99,13 +99,13 @@ def calculate_yarn_costs(world: World):
world.get_hat_yarn_costs()[HatType(i)] = cost
max_cost += cost
available_yarn: int = mw.YarnAvailable[p].value
available_yarn: int = world.options.YarnAvailable.value
if max_cost > available_yarn:
mw.YarnAvailable[p].value = max_cost
world.options.YarnAvailable.value = max_cost
available_yarn = max_cost
if max_cost + mw.MinExtraYarn[p].value > available_yarn:
mw.YarnAvailable[p].value += (max_cost + mw.MinExtraYarn[p].value) - available_yarn
if max_cost + world.options.MinExtraYarn.value > available_yarn:
world.options.YarnAvailable.value += (max_cost + world.options.MinExtraYarn.value) - available_yarn
def item_dlc_enabled(world: World, name: str) -> bool:
@@ -141,7 +141,7 @@ def create_multiple_items(world: World, name: str, count: int = 1,
def create_junk_items(world: World, count: int) -> List[Item]:
trap_chance = world.multiworld.TrapChance[world.player].value
trap_chance = world.options.TrapChance.value
junk_pool: List[Item] = []
junk_list: Dict[str, int] = {}
trap_list: Dict[str, int] = {}
@@ -157,11 +157,11 @@ def create_junk_items(world: World, count: int) -> List[Item]:
elif trap_chance > 0 and ic == ItemClassification.trap:
if name == "Baby Trap":
trap_list[name] = world.multiworld.BabyTrapWeight[world.player].value
trap_list[name] = world.options.BabyTrapWeight.value
elif name == "Laser Trap":
trap_list[name] = world.multiworld.LaserTrapWeight[world.player].value
trap_list[name] = world.options.LaserTrapWeight.value
elif name == "Parade Trap":
trap_list[name] = world.multiworld.ParadeTrapWeight[world.player].value
trap_list[name] = world.options.ParadeTrapWeight.value
for i in range(count):
if trap_chance > 0 and world.random.randint(1, 100) <= trap_chance:

View File

@@ -12,20 +12,20 @@ def get_total_locations(world: World) -> int:
if is_location_valid(world, name):
total += 1
if world.is_dlc1() and world.multiworld.Tasksanity[world.player].value > 0:
total += world.multiworld.TasksanityCheckCount[world.player].value
if world.is_dlc1() and world.options.Tasksanity.value > 0:
total += world.options.TasksanityCheckCount.value
if world.is_dw():
if world.multiworld.DWShuffle[world.player].value > 0:
if world.options.DWShuffle.value > 0:
total += len(world.get_dw_shuffle())
if world.multiworld.DWEnableBonus[world.player].value > 0:
if world.options.DWEnableBonus.value > 0:
total += len(world.get_dw_shuffle())
else:
total += 37
if world.is_dlc2():
total += 1
if world.multiworld.DWEnableBonus[world.player].value > 0:
if world.options.DWEnableBonus.value > 0:
total += 37
if world.is_dlc2():
total += 1
@@ -56,11 +56,11 @@ def is_location_valid(world: World, location: str) -> bool:
if not location_dlc_enabled(world, location):
return False
if world.multiworld.ShuffleStorybookPages[world.player].value == 0 \
if world.options.ShuffleStorybookPages.value == 0 \
and location in storybook_pages.keys():
return False
if world.multiworld.ShuffleActContracts[world.player].value == 0 \
if world.options.ShuffleActContracts.value == 0 \
and location in contract_locations.keys():
return False
@@ -68,23 +68,23 @@ def is_location_valid(world: World, location: str) -> bool:
return False
data = location_table.get(location) or event_locs.get(location)
if world.multiworld.ExcludeTour[world.player].value > 0 and data.region == "Time Rift - Tour":
if world.options.ExcludeTour.value > 0 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.multiworld.DWExcludeCandles[world.player].value > 0 and location in event_locs.keys():
if world.options.DWExcludeCandles.value > 0 and location in event_locs.keys():
return False
if world.multiworld.DWShuffle[world.player].value > 0 \
if world.options.DWShuffle.value > 0 \
and data.region in death_wishes and data.region not in world.get_dw_shuffle():
return False
if location in zero_jumps:
if world.multiworld.DWShuffle[world.player].value > 0 and "Zero Jumps" not in world.get_dw_shuffle():
if world.options.DWShuffle.value > 0 and "Zero Jumps" not in world.get_dw_shuffle():
return False
difficulty: int = world.multiworld.LogicDifficulty[world.player].value
difficulty: int = world.options.LogicDifficulty.value
if location in zero_jumps_hard and difficulty < int(Difficulty.HARD):
return False

View File

@@ -1,6 +1,7 @@
import typing
from worlds.AutoWorld import World
from Options import Option, Range, Toggle, DeathLink, Choice, OptionDict
from typing import List
from dataclasses import dataclass
from worlds.AutoWorld import World, PerGameCommonOptions
from Options import Range, Toggle, DeathLink, Choice, OptionDict
def adjust_options(world: World):
@@ -594,119 +595,118 @@ class ParadeTrapWeight(Range):
default = 20
ahit_options: typing.Dict[str, type(Option)] = {
@dataclass
class AHITOptions(PerGameCommonOptions):
EndGoal: EndGoal
ActRandomizer: ActRandomizer
ActPlando: ActPlando
ShuffleAlpineZiplines: ShuffleAlpineZiplines
FinaleShuffle: FinaleShuffle
LogicDifficulty: LogicDifficulty
YarnBalancePercent: YarnBalancePercent
TimePieceBalancePercent: TimePieceBalancePercent
RandomizeHatOrder: RandomizeHatOrder
UmbrellaLogic: UmbrellaLogic
StartWithCompassBadge: StartWithCompassBadge
CompassBadgeMode: CompassBadgeMode
ShuffleStorybookPages: ShuffleStorybookPages
ShuffleActContracts: ShuffleActContracts
ShuffleSubconPaintings: ShuffleSubconPaintings
NoPaintingSkips: NoPaintingSkips
StartingChapter: StartingChapter
CTRLogic: CTRLogic
"EndGoal": EndGoal,
"ActRandomizer": ActRandomizer,
"ActPlando": ActPlando,
"ShuffleAlpineZiplines": ShuffleAlpineZiplines,
"FinaleShuffle": FinaleShuffle,
"LogicDifficulty": LogicDifficulty,
"YarnBalancePercent": YarnBalancePercent,
"TimePieceBalancePercent": TimePieceBalancePercent,
"RandomizeHatOrder": RandomizeHatOrder,
"UmbrellaLogic": UmbrellaLogic,
"StartWithCompassBadge": StartWithCompassBadge,
"CompassBadgeMode": CompassBadgeMode,
"ShuffleStorybookPages": ShuffleStorybookPages,
"ShuffleActContracts": ShuffleActContracts,
"ShuffleSubconPaintings": ShuffleSubconPaintings,
"NoPaintingSkips": NoPaintingSkips,
"StartingChapter": StartingChapter,
"CTRLogic": CTRLogic,
EnableDLC1: EnableDLC1
Tasksanity: Tasksanity
TasksanityTaskStep: TasksanityTaskStep
TasksanityCheckCount: TasksanityCheckCount
ExcludeTour: ExcludeTour
ShipShapeCustomTaskGoal: ShipShapeCustomTaskGoal
"EnableDLC1": EnableDLC1,
"Tasksanity": Tasksanity,
"TasksanityTaskStep": TasksanityTaskStep,
"TasksanityCheckCount": TasksanityCheckCount,
"ExcludeTour": ExcludeTour,
"ShipShapeCustomTaskGoal": ShipShapeCustomTaskGoal,
EnableDeathWish: EnableDeathWish
DWShuffle: DWShuffle
DWShuffleCountMin: DWShuffleCountMin
DWShuffleCountMax: DWShuffleCountMax
DeathWishOnly: DeathWishOnly
DWEnableBonus: DWEnableBonus
DWAutoCompleteBonuses: DWAutoCompleteBonuses
DWExcludeAnnoyingContracts: DWExcludeAnnoyingContracts
DWExcludeAnnoyingBonuses: DWExcludeAnnoyingBonuses
DWExcludeCandles: DWExcludeCandles
DWTimePieceRequirement: DWTimePieceRequirement
"EnableDeathWish": EnableDeathWish,
"DWShuffle": DWShuffle,
"DWShuffleCountMin": DWShuffleCountMin,
"DWShuffleCountMax": DWShuffleCountMax,
"DeathWishOnly": DeathWishOnly,
"DWEnableBonus": DWEnableBonus,
"DWAutoCompleteBonuses": DWAutoCompleteBonuses,
"DWExcludeAnnoyingContracts": DWExcludeAnnoyingContracts,
"DWExcludeAnnoyingBonuses": DWExcludeAnnoyingBonuses,
"DWExcludeCandles": DWExcludeCandles,
"DWTimePieceRequirement": DWTimePieceRequirement,
EnableDLC2: EnableDLC2
BaseballBat: BaseballBat
MetroMinPonCost: MetroMinPonCost
MetroMaxPonCost: MetroMaxPonCost
NyakuzaThugMinShopItems: NyakuzaThugMinShopItems
NyakuzaThugMaxShopItems: NyakuzaThugMaxShopItems
"EnableDLC2": EnableDLC2,
"BaseballBat": BaseballBat,
"MetroMinPonCost": MetroMinPonCost,
"MetroMaxPonCost": MetroMaxPonCost,
"NyakuzaThugMinShopItems": NyakuzaThugMinShopItems,
"NyakuzaThugMaxShopItems": NyakuzaThugMaxShopItems,
LowestChapterCost: LowestChapterCost
HighestChapterCost: HighestChapterCost
ChapterCostIncrement: ChapterCostIncrement
ChapterCostMinDifference: ChapterCostMinDifference
MaxExtraTimePieces: MaxExtraTimePieces
"LowestChapterCost": LowestChapterCost,
"HighestChapterCost": HighestChapterCost,
"ChapterCostIncrement": ChapterCostIncrement,
"ChapterCostMinDifference": ChapterCostMinDifference,
"MaxExtraTimePieces": MaxExtraTimePieces,
FinalChapterMinCost: FinalChapterMinCost
FinalChapterMaxCost: FinalChapterMaxCost
"FinalChapterMinCost": FinalChapterMinCost,
"FinalChapterMaxCost": FinalChapterMaxCost,
YarnCostMin: YarnCostMin
YarnCostMax: YarnCostMax
YarnAvailable: YarnAvailable
MinExtraYarn: MinExtraYarn
HatItems: HatItems
"YarnCostMin": YarnCostMin,
"YarnCostMax": YarnCostMax,
"YarnAvailable": YarnAvailable,
"MinExtraYarn": MinExtraYarn,
"HatItems": HatItems,
MinPonCost: MinPonCost
MaxPonCost: MaxPonCost
BadgeSellerMinItems: BadgeSellerMinItems
BadgeSellerMaxItems: BadgeSellerMaxItems
"MinPonCost": MinPonCost,
"MaxPonCost": MaxPonCost,
"BadgeSellerMinItems": BadgeSellerMinItems,
"BadgeSellerMaxItems": BadgeSellerMaxItems,
TrapChance: TrapChance
BabyTrapWeight: BabyTrapWeight
LaserTrapWeight: LaserTrapWeight
ParadeTrapWeight: ParadeTrapWeight
"TrapChance": TrapChance,
"BabyTrapWeight": BabyTrapWeight,
"LaserTrapWeight": LaserTrapWeight,
"ParadeTrapWeight": ParadeTrapWeight,
death_link: DeathLink
"death_link": DeathLink,
}
slot_data_options: typing.Dict[str, type(Option)] = {
slot_data_options: List[str] = [
"EndGoal",
"ActRandomizer",
"ShuffleAlpineZiplines",
"LogicDifficulty",
"CTRLogic",
"RandomizeHatOrder",
"UmbrellaLogic",
"StartWithCompassBadge",
"CompassBadgeMode",
"ShuffleStorybookPages",
"ShuffleActContracts",
"ShuffleSubconPaintings",
"NoPaintingSkips",
"HatItems",
"EndGoal": EndGoal,
"ActRandomizer": ActRandomizer,
"ShuffleAlpineZiplines": ShuffleAlpineZiplines,
"LogicDifficulty": LogicDifficulty,
"CTRLogic": CTRLogic,
"RandomizeHatOrder": RandomizeHatOrder,
"UmbrellaLogic": UmbrellaLogic,
"StartWithCompassBadge": StartWithCompassBadge,
"CompassBadgeMode": CompassBadgeMode,
"ShuffleStorybookPages": ShuffleStorybookPages,
"ShuffleActContracts": ShuffleActContracts,
"ShuffleSubconPaintings": ShuffleSubconPaintings,
"NoPaintingSkips": NoPaintingSkips,
"HatItems": HatItems,
"EnableDLC1",
"Tasksanity",
"TasksanityTaskStep",
"TasksanityCheckCount",
"ShipShapeCustomTaskGoal",
"ExcludeTour",
"EnableDLC1": EnableDLC1,
"Tasksanity": Tasksanity,
"TasksanityTaskStep": TasksanityTaskStep,
"TasksanityCheckCount": TasksanityCheckCount,
"ShipShapeCustomTaskGoal": ShipShapeCustomTaskGoal,
"ExcludeTour": ExcludeTour,
"EnableDeathWish",
"DWShuffle",
"DeathWishOnly",
"DWEnableBonus",
"DWAutoCompleteBonuses",
"DWTimePieceRequirement",
"EnableDeathWish": EnableDeathWish,
"DWShuffle": DWShuffle,
"DeathWishOnly": DeathWishOnly,
"DWEnableBonus": DWEnableBonus,
"DWAutoCompleteBonuses": DWAutoCompleteBonuses,
"DWTimePieceRequirement": DWTimePieceRequirement,
"EnableDLC2",
"MetroMinPonCost",
"MetroMaxPonCost",
"BaseballBat",
"EnableDLC2": EnableDLC2,
"MetroMinPonCost": MetroMinPonCost,
"MetroMaxPonCost": MetroMaxPonCost,
"BaseballBat": BaseballBat,
"MinPonCost",
"MaxPonCost",
"MinPonCost": MinPonCost,
"MaxPonCost": MaxPonCost,
"death_link": DeathLink,
}
"death_link",
]

View File

@@ -270,7 +270,6 @@ blacklisted_combos = {
def create_regions(world: World):
w = world
mw = world.multiworld
p = world.player
# ------------------------------------------- HUB -------------------------------------------------- #
@@ -311,7 +310,7 @@ def create_regions(world: World):
ev_area = create_region_and_connect(w, "Dead Bird Studio - Elevator Area", "DBS -> Elevator Area", dbs)
post_ev_area = create_region_and_connect(w, "Dead Bird Studio - Post Elevator Area", "DBS -> Post Elevator Area", dbs)
connect_regions(basement, ev_area, "DBS Basement -> Elevator Area", p)
if world.multiworld.LogicDifficulty[world.player].value >= int(Difficulty.EXPERT):
if world.options.LogicDifficulty.value >= int(Difficulty.EXPERT):
connect_regions(basement, post_ev_area, "DBS Basement -> Post Elevator Area", p)
# ------------------------------------------- SUBCON FOREST --------------------------------------- #
@@ -397,10 +396,10 @@ def create_regions(world: World):
create_rift_connections(w, create_region(w, "Time Rift - Balcony"))
create_rift_connections(w, create_region(w, "Time Rift - Deep Sea"))
if mw.ExcludeTour[world.player].value == 0:
if w.options.ExcludeTour.value == 0:
create_rift_connections(w, create_region(w, "Time Rift - Tour"))
if mw.Tasksanity[p].value > 0:
if w.options.Tasksanity.value > 0:
create_tasksanity_locations(w)
connect_regions(cruise_ship, badge_seller, "CS -> Badge Seller", p)
@@ -440,7 +439,7 @@ def create_rift_connections(world: World, region: Region):
def create_tasksanity_locations(world: World):
ship_shape: Region = world.multiworld.get_region("Ship Shape", world.player)
id_start: int = get_tasksanity_start_id()
for i in range(world.multiworld.TasksanityCheckCount[world.player].value):
for i in range(world.options.TasksanityCheckCount.value):
location = HatInTimeLocation(world.player, f"Tasksanity Check {i+1}", id_start+i, ship_shape)
ship_shape.locations.append(location)
@@ -449,10 +448,10 @@ def is_valid_plando(world: World, region: str) -> bool:
if region in blacklisted_acts.values():
return False
if region not in world.multiworld.ActPlando[world.player].keys():
if region not in world.options.ActPlando.keys():
return False
act = world.multiworld.ActPlando[world.player].get(region)
act = world.options.ActPlando.get(region)
if act in blacklisted_acts.values():
return False
@@ -461,10 +460,10 @@ def is_valid_plando(world: World, region: str) -> bool:
and region in act_entrances.keys() and ("Act 1" in act_entrances[region] or "Free Roam" in act_entrances[region])
if is_first_act:
if act_chapters[act] == "Subcon Forest" and world.multiworld.ShuffleSubconPaintings[world.player].value > 0:
if act_chapters[act] == "Subcon Forest" and world.options.ShuffleSubconPaintings.value > 0:
return False
if world.multiworld.UmbrellaLogic[world.player].value > 0 \
if world.options.UmbrellaLogic.value > 0 \
and (act == "Heating Up Mafia Town" or act == "Queen Vanessa's Manor"):
return False
@@ -484,7 +483,7 @@ def is_valid_plando(world: World, region: str) -> bool:
if region == "Time Rift - The Owl Express" and act == "Murder on the Owl Express":
return False
return any(a.name == world.multiworld.ActPlando[world.player].get(region) for a in
return any(a.name == world.options.ActPlando.get(region) for a in
world.multiworld.get_regions(world.player))
@@ -492,7 +491,7 @@ def randomize_act_entrances(world: World):
region_list: typing.List[Region] = get_act_regions(world)
world.random.shuffle(region_list)
separate_rifts: bool = bool(world.multiworld.ActRandomizer[world.player].value == 1)
separate_rifts: bool = bool(world.options.ActRandomizer.value == 1)
for region in region_list.copy():
if (act_chapters[region.name] == "Alpine Skyline" or act_chapters[region.name] == "Nyakuza Metro") \
@@ -511,14 +510,14 @@ def randomize_act_entrances(world: World):
region_list.append(region)
for region in region_list.copy():
if region.name in world.multiworld.ActPlando[world.player].keys():
if region.name in world.options.ActPlando.keys():
if is_valid_plando(world, region.name):
region_list.remove(region)
region_list.append(region)
else:
print("Disallowing act plando for",
world.multiworld.player_name[world.player],
"-", region.name, ":", world.multiworld.ActPlando[world.player].get(region.name))
"-", region.name, ":", world.options.ActPlando.get(region.name))
# Reverse the list, so we can do what we want to do first
region_list.reverse()
@@ -543,7 +542,7 @@ def randomize_act_entrances(world: World):
and "Free Roam" not in act_entrances[region.name]:
continue
if region.name in world.multiworld.ActPlando[world.player].keys() and is_valid_plando(world, region.name):
if region.name in world.options.ActPlando.keys() and is_valid_plando(world, region.name):
has_guaranteed = True
i = 0
@@ -562,16 +561,16 @@ def randomize_act_entrances(world: World):
if candidate.name not in guaranteed_first_acts:
continue
if candidate.name in world.multiworld.ActPlando[world.player].values():
if candidate.name in world.options.ActPlando.values():
continue
# Not completable without Umbrella
if world.multiworld.UmbrellaLogic[world.player].value > 0 \
if world.options.UmbrellaLogic.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 \
if world.options.ShuffleSubconPaintings.value > 0 \
and "Subcon Forest" in act_entrances[candidate.name]:
continue
@@ -579,10 +578,10 @@ def randomize_act_entrances(world: World):
has_guaranteed = True
break
if region.name in world.multiworld.ActPlando[world.player].keys() and is_valid_plando(world, region.name):
if region.name in world.options.ActPlando.keys() and is_valid_plando(world, region.name):
candidate_list.clear()
candidate_list.append(
world.multiworld.get_region(world.multiworld.ActPlando[world.player].get(region.name), world.player))
world.multiworld.get_region(world.options.ActPlando.get(region.name), world.player))
break
# Already mapped onto something else
@@ -607,12 +606,12 @@ def randomize_act_entrances(world: World):
continue
# Prevent Contractual Obligations from being inaccessible if contracts are not shuffled
if world.multiworld.ShuffleActContracts[world.player].value == 0:
if world.options.ShuffleActContracts.value == 0:
if (region.name == "Your Contract has Expired" or region.name == "The Subcon Well") \
and candidate.name == "Contractual Obligations":
continue
if world.multiworld.FinaleShuffle[world.player].value > 0 and region.name in chapter_finales:
if world.options.FinaleShuffle.value > 0 and region.name in chapter_finales:
if candidate.name not in chapter_finales:
continue
@@ -687,17 +686,17 @@ def get_act_regions(world: World) -> typing.List[Region]:
def is_act_blacklisted(world: World, name: str) -> bool:
plando: bool = name in world.multiworld.ActPlando[world.player].keys() \
or name in world.multiworld.ActPlando[world.player].values()
plando: bool = name in world.options.ActPlando.keys() \
or name in world.options.ActPlando.values()
if name == "The Finale":
return not plando and world.multiworld.EndGoal[world.player].value == 1
return not plando and world.options.EndGoal.value == 1
if name == "Rush Hour":
return not plando and world.multiworld.EndGoal[world.player].value == 2
return not plando and world.options.EndGoal.value == 2
if name == "Time Rift - Tour":
return world.multiworld.ExcludeTour[world.player].value > 0
return world.options.ExcludeTour.value > 0
return name in blacklisted_acts.values()
@@ -714,7 +713,7 @@ def create_region(world: World, name: str) -> Region:
if data.region == name:
if key in storybook_pages.keys() \
and world.multiworld.ShuffleStorybookPages[world.player].value == 0:
and world.options.ShuffleStorybookPages.value == 0:
continue
location = HatInTimeLocation(world.player, key, data.id, reg)
@@ -732,9 +731,9 @@ def create_badge_seller(world: World) -> Region:
count: int = 0
max_items: int = 0
if world.multiworld.BadgeSellerMaxItems[world.player].value > 0:
max_items = world.random.randint(world.multiworld.BadgeSellerMinItems[world.player].value,
world.multiworld.BadgeSellerMaxItems[world.player].value)
if world.options.BadgeSellerMaxItems.value > 0:
max_items = world.random.randint(world.options.BadgeSellerMinItems.value,
world.options.BadgeSellerMaxItems.value)
if max_items <= 0:
world.set_badge_seller_count(0)
@@ -801,7 +800,7 @@ def create_region_and_connect(world: World,
def get_first_chapter_region(world: World) -> Region:
start_chapter: ChapterIndex = world.multiworld.StartingChapter[world.player]
start_chapter: ChapterIndex = world.options.StartingChapter.value
return world.multiworld.get_region(chapter_regions.get(start_chapter), world.player)
@@ -826,11 +825,11 @@ def get_shuffled_region(self, region: str) -> str:
def create_thug_shops(world: World):
min_items: int = min(world.multiworld.NyakuzaThugMinShopItems[world.player].value,
world.multiworld.NyakuzaThugMaxShopItems[world.player].value)
min_items: int = min(world.options.NyakuzaThugMinShopItems.value,
world.options.NyakuzaThugMaxShopItems.value)
max_items: int = max(world.multiworld.NyakuzaThugMaxShopItems[world.player].value,
world.multiworld.NyakuzaThugMinShopItems[world.player].value)
max_items: int = max(world.options.NyakuzaThugMaxShopItems.value,
world.options.NyakuzaThugMinShopItems.value)
count: int = -1
step: int = 0
old_name: str = ""

View File

@@ -32,7 +32,7 @@ act_connections = {
def can_use_hat(state: CollectionState, world: World, hat: HatType) -> bool:
if world.multiworld.HatItems[world.player].value > 0:
if world.options.HatItems.value > 0:
return state.has(hat_type_to_item[hat], world.player)
return state.count("Yarn", world.player) >= get_hat_cost(world, hat)
@@ -54,19 +54,19 @@ def can_sdj(state: CollectionState, world: World):
def painting_logic(world: World) -> bool:
return world.multiworld.ShuffleSubconPaintings[world.player].value > 0
return world.options.ShuffleSubconPaintings.value > 0
# -1 = Normal, 0 = Moderate, 1 = Hard, 2 = Expert
def get_difficulty(world: World) -> Difficulty:
return Difficulty(world.multiworld.LogicDifficulty[world.player].value)
return Difficulty(world.options.LogicDifficulty.value)
def has_paintings(state: CollectionState, world: World, count: int, allow_skip: bool = True) -> bool:
if not painting_logic(world):
return True
if world.multiworld.NoPaintingSkips[world.player].value == 0 and allow_skip:
if world.options.NoPaintingSkips.value == 0 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
@@ -75,7 +75,7 @@ def has_paintings(state: CollectionState, world: World, count: int, allow_skip:
def zipline_logic(world: World) -> bool:
return world.multiworld.ShuffleAlpineZiplines[world.player].value > 0
return world.options.ShuffleAlpineZiplines.value > 0
def can_use_hookshot(state: CollectionState, world: World):
@@ -83,7 +83,7 @@ def can_use_hookshot(state: CollectionState, world: World):
def can_hit(state: CollectionState, world: World, umbrella_only: bool = False):
if world.multiworld.UmbrellaLogic[world.player].value == 0:
if world.options.UmbrellaLogic.value == 0:
return True
return state.has("Umbrella", world.player) or not umbrella_only and can_use_hat(state, world, HatType.BREWING)
@@ -132,7 +132,7 @@ def can_clear_metro(state: CollectionState, world: World) -> bool:
def set_rules(world: World):
# First, chapter access
starting_chapter = ChapterIndex(world.multiworld.StartingChapter[world.player].value)
starting_chapter = ChapterIndex(world.options.StartingChapter.value)
world.set_chapter_cost(starting_chapter, 0)
# Chapter costs increase progressively. Randomly decide the chapter order, except for Finale
@@ -140,10 +140,10 @@ def set_rules(world: World):
ChapterIndex.SUBCON, ChapterIndex.ALPINE]
final_chapter = ChapterIndex.FINALE
if world.multiworld.EndGoal[world.player].value == 2:
if world.options.EndGoal.value == 2:
final_chapter = ChapterIndex.METRO
chapter_list.append(ChapterIndex.FINALE)
elif world.multiworld.EndGoal[world.player].value == 3:
elif world.options.EndGoal.value == 3:
final_chapter = None
chapter_list.append(ChapterIndex.FINALE)
@@ -185,11 +185,11 @@ def set_rules(world: World):
else:
chapter_list.insert(world.random.randint(index+1, len(chapter_list)), ChapterIndex.METRO)
lowest_cost: int = world.multiworld.LowestChapterCost[world.player].value
highest_cost: int = world.multiworld.HighestChapterCost[world.player].value
lowest_cost: int = world.options.LowestChapterCost.value
highest_cost: int = world.options.HighestChapterCost.value
cost_increment: int = world.multiworld.ChapterCostIncrement[world.player].value
min_difference: int = world.multiworld.ChapterCostMinDifference[world.player].value
cost_increment: int = world.options.ChapterCostIncrement.value
min_difference: int = world.options.ChapterCostMinDifference.value
last_cost: int = 0
cost: int
loop_count: int = 0
@@ -213,8 +213,8 @@ def set_rules(world: World):
if final_chapter is not None:
world.set_chapter_cost(final_chapter, world.random.randint(
world.multiworld.FinalChapterMinCost[world.player].value,
world.multiworld.FinalChapterMaxCost[world.player].value))
world.options.FinalChapterMinCost.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)))
@@ -243,7 +243,7 @@ def set_rules(world: World):
and state.has("Time Piece", world.player, world.get_chapter_cost(ChapterIndex.METRO))
and can_use_hat(state, world, HatType.DWELLER) and can_use_hat(state, world, HatType.ICE))
if world.multiworld.ActRandomizer[world.player].value == 0:
if world.options.ActRandomizer.value == 0:
set_default_rift_rules(world)
table = location_table | event_locs
@@ -267,10 +267,10 @@ def set_rules(world: World):
if data.hookshot:
add_rule(location, lambda state: can_use_hookshot(state, world))
if data.umbrella and world.multiworld.UmbrellaLogic[world.player].value > 0:
if data.umbrella and world.options.UmbrellaLogic.value > 0:
add_rule(location, lambda state: state.has("Umbrella", world.player))
if data.paintings > 0 and world.multiworld.ShuffleSubconPaintings[world.player].value > 0:
if data.paintings > 0 and world.options.ShuffleSubconPaintings.value > 0:
add_rule(location, lambda state, paintings=data.paintings: has_paintings(state, world, paintings))
if data.hit_requirement > 0:
@@ -288,7 +288,7 @@ def set_rules(world: World):
# 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.multiworld.UmbrellaLogic[world.player].value > 0:
if world.options.UmbrellaLogic.value > 0:
add_rule(alpine_entrance, lambda state: state.has("Umbrella", world.player))
if zipline_logic(world):
@@ -356,9 +356,9 @@ def set_rules(world: World):
set_event_rules(world)
if world.multiworld.EndGoal[world.player].value == 1:
if world.options.EndGoal.value == 1:
world.multiworld.completion_condition[world.player] = lambda state: state.has("Time Piece Cluster", world.player)
elif world.multiworld.EndGoal[world.player].value == 2:
elif world.options.EndGoal.value == 2:
world.multiworld.completion_condition[world.player] = lambda state: state.has("Rush Hour Cleared", world.player)
@@ -551,7 +551,7 @@ def set_expert_rules(world: World):
world.multiworld.get_region("Subcon Forest Area", world.player),
"Subcon Forest Entrance YCHE", world.player)
if world.multiworld.NoPaintingSkips[world.player].value > 0:
if world.options.NoPaintingSkips.value > 0:
add_rule(entrance, lambda state: has_paintings(state, world, 1))
set_rule(world.multiworld.get_location("Act Completion (Toilet of Doom)", world.player),
@@ -630,7 +630,7 @@ def set_mafia_town_rules(world: World):
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.multiworld.CTRLogic[world.player].value
ctr_logic: int = world.options.CTRLogic.value
if ctr_logic == 3:
set_rule(world.multiworld.get_location("Act Completion (Cheating the Race)", world.player), lambda state: True)
elif ctr_logic == 2:
@@ -643,7 +643,7 @@ def set_mafia_town_rules(world: World):
def set_botb_rules(world: World):
if world.multiworld.UmbrellaLogic[world.player].value == 0 and get_difficulty(world) < Difficulty.MODERATE:
if world.options.UmbrellaLogic.value == 0 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

@@ -3,7 +3,7 @@ from .Items import item_table, create_item, relic_groups, act_contracts, create_
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, get_tasksanity_start_id
from .Rules import set_rules
from .Options import ahit_options, slot_data_options, adjust_options
from .Options import AHITOptions, slot_data_options, adjust_options
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
@@ -49,7 +49,8 @@ class HatInTimeWorld(World):
item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = get_location_names()
# option_definitions = ahit_options
options_dataclass = AHITOptions
options: AHITOptions
act_connections: Dict[str, str] = {}
shop_locs: List[str] = []
item_name_groups = relic_groups
@@ -58,7 +59,7 @@ class HatInTimeWorld(World):
def generate_early(self):
adjust_options(self)
if self.multiworld.StartWithCompassBadge[self.player].value > 0:
if self.options.StartWithCompassBadge.value > 0:
self.multiworld.push_precollected(self.create_item("Compass Badge"))
if self.is_dw_only():
@@ -66,14 +67,14 @@ 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.multiworld.StartingChapter[self.player].value
start_chapter: int = self.options.StartingChapter.value
if start_chapter == 4 or start_chapter == 3:
if self.multiworld.ActRandomizer[self.player].value == 0:
if self.options.ActRandomizer.value == 0:
if start_chapter == 4:
self.multiworld.push_precollected(self.create_item("Hookshot Badge"))
if start_chapter == 3 and self.multiworld.ShuffleSubconPaintings[self.player].value > 0:
if start_chapter == 3 and self.options.ShuffleSubconPaintings.value > 0:
self.multiworld.push_precollected(self.create_item("Progressive Painting Unlock"))
def create_regions(self):
@@ -83,11 +84,11 @@ class HatInTimeWorld(World):
nyakuza_thug_items[self.player] = {}
badge_seller_count[self.player] = 0
self.shop_locs = []
self.topology_present = self.multiworld.ActRandomizer[self.player].value
self.topology_present = self.options.ActRandomizer.value
create_regions(self)
if self.multiworld.EnableDeathWish[self.player].value > 0:
if self.options.EnableDeathWish.value > 0:
create_dw_regions(self)
if self.is_dw_only():
@@ -100,7 +101,7 @@ class HatInTimeWorld(World):
create_enemy_events(self)
# place vanilla contract locations if contract shuffle is off
if self.multiworld.ShuffleActContracts[self.player].value == 0:
if self.options.ShuffleActContracts.value == 0:
for name in contract_locations.keys():
self.multiworld.get_location(name, self.player).place_locked_item(create_item(self, name))
@@ -111,9 +112,9 @@ class HatInTimeWorld(World):
hat_craft_order[self.player] = [HatType.SPRINT, HatType.BREWING, HatType.ICE,
HatType.DWELLER, HatType.TIME_STOP]
if self.multiworld.HatItems[self.player].value == 0 and self.multiworld.RandomizeHatOrder[self.player].value > 0:
if self.options.HatItems.value == 0 and self.options.RandomizeHatOrder.value > 0:
self.random.shuffle(hat_craft_order[self.player])
if self.multiworld.RandomizeHatOrder[self.player].value == 2:
if self.options.RandomizeHatOrder.value == 2:
hat_craft_order[self.player].remove(HatType.TIME_STOP)
hat_craft_order[self.player].append(HatType.TIME_STOP)
@@ -137,12 +138,12 @@ class HatInTimeWorld(World):
self.multiworld.completion_condition[self.player] = lambda state: state.has("Death Wish Only Mode",
self.player)
if self.multiworld.DWEnableBonus[self.player].value == 0:
if self.options.DWEnableBonus.value == 0:
for name in death_wishes:
if name == "Snatcher Coins in Nyakuza Metro" and not self.is_dlc2():
continue
if self.multiworld.DWShuffle[self.player].value > 0 and name not in self.get_dw_shuffle():
if self.options.DWShuffle.value > 0 and name not in self.get_dw_shuffle():
continue
full_clear = self.multiworld.get_location(f"{name} - All Clear", self.player)
@@ -152,7 +153,7 @@ class HatInTimeWorld(World):
return
if self.multiworld.ActRandomizer[self.player].value > 0:
if self.options.ActRandomizer.value > 0:
randomize_act_entrances(self)
set_rules(self)
@@ -175,7 +176,7 @@ class HatInTimeWorld(World):
"SeedNumber": str(self.multiworld.seed), # For shop prices
"SeedName": self.multiworld.seed_name}
if self.multiworld.HatItems[self.player].value == 0:
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])
@@ -187,7 +188,7 @@ class HatInTimeWorld(World):
slot_data.setdefault("Hat4", int(hat_craft_order[self.player][3]))
slot_data.setdefault("Hat5", int(hat_craft_order[self.player][4]))
if self.multiworld.ActRandomizer[self.player].value > 0:
if self.options.ActRandomizer.value > 0:
for name in self.act_connections.keys():
slot_data[name] = self.act_connections[name]
@@ -198,14 +199,14 @@ class HatInTimeWorld(World):
if self.is_dw():
i: int = 0
for name in excluded_dws[self.player]:
if self.multiworld.EndGoal[self.player].value == 3 and name == "Seal the Deal":
if self.options.EndGoal.value == 3 and name == "Seal the Deal":
continue
slot_data[f"excluded_dw{i}"] = dw_classes[name]
i += 1
i = 0
if self.multiworld.DWAutoCompleteBonuses[self.player].value == 0:
if self.options.DWAutoCompleteBonuses.value == 0:
for name in excluded_bonuses[self.player]:
if name in excluded_dws[self.player]:
continue
@@ -213,19 +214,19 @@ class HatInTimeWorld(World):
slot_data[f"excluded_bonus{i}"] = dw_classes[name]
i += 1
if self.multiworld.DWShuffle[self.player].value > 0:
if self.options.DWShuffle.value > 0:
shuffled_dws = self.get_dw_shuffle()
for i in range(len(shuffled_dws)):
slot_data[f"dw_{i}"] = dw_classes[shuffled_dws[i]]
for option_name in slot_data_options:
option = getattr(self.multiworld, option_name)[self.player]
slot_data[option_name] = option.value
for name, value in self.options.as_dict(*self.options_dataclass.type_hints).items():
if name in slot_data_options:
slot_data[name] = value
return slot_data
def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]):
if self.is_dw_only() or self.multiworld.ActRandomizer[self.player].value == 0:
if self.is_dw_only() or self.options.ActRandomizer.value == 0:
return
new_hint_data = {}
@@ -250,10 +251,10 @@ class HatInTimeWorld(World):
new_hint_data[location.address] = get_shuffled_region(self, region_name)
if self.is_dlc1() and self.multiworld.Tasksanity[self.player].value > 0:
if self.is_dlc1() and self.options.Tasksanity.value > 0:
ship_shape_region = get_shuffled_region(self, "Ship Shape")
id_start: int = get_tasksanity_start_id()
for i in range(self.multiworld.TasksanityCheckCount[self.player].value):
for i in range(self.options.TasksanityCheckCount.value):
new_hint_data[id_start+i] = ship_shape_region
hint_data[self.player] = new_hint_data
@@ -281,16 +282,16 @@ class HatInTimeWorld(World):
return chapter_timepiece_costs[self.player]
def is_dlc1(self) -> bool:
return self.multiworld.EnableDLC1[self.player].value > 0
return self.options.EnableDLC1.value > 0
def is_dlc2(self) -> bool:
return self.multiworld.EnableDLC2[self.player].value > 0
return self.options.EnableDLC2.value > 0
def is_dw(self) -> bool:
return self.multiworld.EnableDeathWish[self.player].value > 0
return self.options.EnableDeathWish.value > 0
def is_dw_only(self) -> bool:
return self.is_dw() and self.multiworld.DeathWishOnly[self.player].value > 0
return self.is_dw() and self.options.DeathWishOnly.value > 0
def get_excluded_dws(self):
return excluded_dws[self.player]
@@ -300,7 +301,7 @@ class HatInTimeWorld(World):
def is_dw_excluded(self, name: str) -> bool:
# don't exclude Seal the Deal if it's our goal
if self.multiworld.EndGoal[self.player].value == 3 and name == "Seal the Deal" \
if self.options.EndGoal.value == 3 and name == "Seal the Deal" \
and f"{name} - Main Objective" not in self.multiworld.exclude_locations[self.player]:
return False