Archipelago/worlds/dlcquest/Options.py

125 lines
3.6 KiB
Python

from typing import Union, Dict, runtime_checkable, Protocol
from Options import Option, DeathLink, Choice, Toggle, SpecialRange
from dataclasses import dataclass
@runtime_checkable
class DLCQuestOption(Protocol):
internal_name: str
@dataclass
class DLCQuestOptions:
options: Dict[str, Union[bool, int]]
def __getitem__(self, item: Union[str, DLCQuestOption]) -> Union[bool, int]:
if isinstance(item, DLCQuestOption):
item = item.internal_name
return self.options.get(item, None)
class DoubleJumpGlitch(Choice):
"""Whether to include the double jump glitches in logic. Separated between the simple ones and the very difficult ones"""
internal_name = "double_jump_glitch"
display_name = "Double Jump glitch"
option_none = 0
option_simple = 1
option_all = 2
default = 0
class TimeIsMoney(Choice):
"""Whether the Time is Money pack is considered required to complete the grindstone.
If optional, you may be expected to grind 10 000 times by hand"""
internal_name = "time_is_money"
display_name = "Time Is Money"
option_required = 0
option_optional = 1
default = 0
class CoinSanity(Choice):
"""Whether collecting coins are checks
If none, you will collect your own coins"""
internal_name = "coinsanity"
display_name = "CoinSanity"
option_none = 0
option_coin = 1
default = 0
class CoinSanityRange(SpecialRange):
"""This is the amount of coins in a coin bundle
You need to collect that number of coins to get a location check, and when receiving coin items, you will get bundles of this size
It is highly recommended to not set this value below 10, as it generates a very large number of boring locations and items.
In the worst case, it is 1500+ checks for a single coin"""
internal_name = "coinbundlequantity"
display_name = "Coin Bundle Quantity"
range_start = 1
range_end = 100
default = 20
special_range_names = {
"low": 5,
"normal": 20,
"high": 50,
}
class EndingChoice(Choice):
"""Which ending is considered completion for the DLC Quest campaign, either any ending or the true ending"""
internal_name = "ending_choice"
display_name = "Ending Choice"
option_any = 0
option_true = 1
default = 1
class Campaign(Choice):
"""Which campaign you want to play"""
internal_name = "campaign"
display_name = "Campaign"
option_basic = 0
option_live_freemium_or_die = 1
option_both = 2
default = 0
class ItemShuffle(Choice):
"""Should Inventory Items be separate from their DLCs and shuffled in the item pool"""
internal_name = "item_shuffle"
display_name = "Item Shuffle"
option_disabled = 0
option_shuffled = 1
default = 0
DLCQuest_options: Dict[str, type(Option)] = {
option.internal_name: option
for option in [
DoubleJumpGlitch,
CoinSanity,
CoinSanityRange,
TimeIsMoney,
EndingChoice,
Campaign,
ItemShuffle,
]
}
default_options = {option.internal_name: option.default for option in DLCQuest_options.values()}
DLCQuest_options["death_link"] = DeathLink
def fetch_options(world, player: int) -> DLCQuestOptions:
return DLCQuestOptions({option: get_option_value(world, player, option) for option in DLCQuest_options})
def get_option_value(world, player: int, name: str) -> Union[bool, int]:
assert name in DLCQuest_options, f"{name} is not a valid option for DLC Quest."
value = getattr(world, name)
if issubclass(DLCQuest_options[name], Toggle):
return bool(value[player].value)
return value[player].value