mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-28 08:53:23 -07:00
Update to new options API
This commit is contained in:
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user