Files
Grinch-AP/worlds/celeste64/Options.py
PoryGone bf8c840293 Celeste 64: v1.3 Content Update (#4581)
### Features:

- New optional Location Checks
	- Checkpointsanity
- Hair Color
	- Allows for setting of Maddy's hair color in each of No Dash, One Dash, Two Dash, and Feather states
- Other Player Ghosts
	- A game config option allows you to see ghosts of other Celeste 64 players in the multiworld

### Quality of Life:

- Checkpoint Warping
	- Received Checkpoint items allow for warping to their respective checkpoint
		- These items are on their respective checkpoint location if Checkpointsanity is disabled
	- Logic accounts for being able to warp to otherwise inaccessible areas
	- Checkpoints are a possible option for a starting item on Standard Logic + Move Shuffle + Checkpointsanity
- New Options toggle to enable/disable background input

### Bug Fixes:

- Traffic Blocks now correctly appear disabled within Cassettes
2025-03-17 02:46:34 +01:00

306 lines
9.8 KiB
Python

from dataclasses import dataclass
import random
from Options import Choice, TextChoice, Range, Toggle, DeathLink, OptionGroup, PerGameCommonOptions, OptionError
from worlds.AutoWorld import World
class DeathLinkAmnesty(Range):
"""
How many deaths it takes to send a DeathLink
"""
display_name = "Death Link Amnesty"
range_start = 1
range_end = 30
default = 10
class TotalStrawberries(Range):
"""
How many Strawberries exist
"""
display_name = "Total Strawberries"
range_start = 0
range_end = 55
default = 20
class StrawberriesRequiredPercentage(Range):
"""
Percentage of existing Strawberries you must receive to finish
"""
display_name = "Strawberries Required Percentage"
range_start = 0
range_end = 100
default = 80
class LogicDifficulty(Choice):
"""
Whether the logic expects you to play the intended way, or to be able to use advanced tricks and skips
"""
display_name = "Logic Difficulty"
option_standard = 0
option_hard = 1
default = 0
class MoveShuffle(Toggle):
"""
Whether the following base movement abilities are shuffled into the item pool:
- Ground Dash
- Air Dash
- Skid Jump
- Climb
NOTE: Having Move Shuffle and Standard Logic Difficulty will guarantee that one of the four Move items will be immediately accessible
WARNING: Combining Move Shuffle and Hard Logic Difficulty can require very difficult tricks
"""
display_name = "Move Shuffle"
class Friendsanity(Toggle):
"""
Whether chatting with your friends grants location checks
"""
display_name = "Friendsanity"
class Signsanity(Toggle):
"""
Whether reading signs grants location checks
"""
display_name = "Signsanity"
class Carsanity(Toggle):
"""
Whether riding on cars grants location checks
"""
display_name = "Carsanity"
class Checkpointsanity(Toggle):
"""
Whether activating Checkpoints grants location checks
Activating this will also shuffle items into the pool which allow usage and warping to each Checkpoint
"""
display_name = "Checkpointsanity"
class ColorChoice(TextChoice):
option_strawberry = 0xDB2C00
option_empty = 0x6EC0FF
option_double = 0xFA91FF
option_golden = 0xF2D450
option_baddy = 0x9B3FB5
option_fire_red = 0xFF0000
option_maroon = 0x800000
option_salmon = 0xFF3A65
option_orange = 0xD86E0A
option_lime_green = 0x8DF920
option_bright_green = 0x0DAF05
option_forest_green = 0x132818
option_royal_blue = 0x0036BF
option_brown = 0xB78726
option_black = 0x000000
option_white = 0xFFFFFF
option_grey = 0x808080
option_any_color = -1
@classmethod
def from_text(cls, text: str) -> Choice:
text = text.lower()
if text == "random":
choice_list = list(cls.name_lookup)
choice_list.remove(cls.option_any_color)
return cls(random.choice(choice_list))
return super().from_text(text)
class MadelineOneDashHairColor(ColorChoice):
"""
What color Madeline's hair is when she has one dash
The `any_color` option will choose a fully random color
A custom color entry may be supplied as a 6-character RGB hex color code
e.g. F542C8
"""
display_name = "Madeline One Dash Hair Color"
default = ColorChoice.option_strawberry
class MadelineTwoDashHairColor(ColorChoice):
"""
What color Madeline's hair is when she has two dashes
The `any_color` option will choose a fully random color
A custom color entry may be supplied as a 6-character RGB hex color code
e.g. F542C8
"""
display_name = "Madeline Two Dash Hair Color"
default = ColorChoice.option_double
class MadelineNoDashHairColor(ColorChoice):
"""
What color Madeline's hair is when she has no dashes
The `any_color` option will choose a fully random color
A custom color entry may be supplied as a 6-character RGB hex color code
e.g. F542C8
"""
display_name = "Madeline No Dash Hair Color"
default = ColorChoice.option_empty
class MadelineFeatherHairColor(ColorChoice):
"""
What color Madeline's hair is when she has a feather
The `any_color` option will choose a fully random color
A custom color entry may be supplied as a 6-character RGB hex color code
e.g. F542C8
"""
display_name = "Madeline Feather Hair Color"
default = ColorChoice.option_golden
class BadelineChaserSource(Choice):
"""
What type of action causes more Badeline Chasers to start spawning
Locations: The number of locations you've checked contributes to Badeline Chasers
Strawberries: The number of Strawberry items you've received contributes to Badeline Chasers
"""
display_name = "Badeline Chaser Source"
option_locations = 0
option_strawberries = 1
default = 0
class BadelineChaserFrequency(Range):
"""
How many of the `Badeline Chaser Source` actions must occur to make each Badeline Chaser start spawning
NOTE: Choosing `0` disables Badeline Chasers entirely
WARNING: Turning on Badeline Chasers alongside Move Shuffle could result in extremely difficult situations
"""
display_name = "Badeline Chaser Frequency"
range_start = 0
range_end = 10
default = 0
class BadelineChaserSpeed(Range):
"""
How many seconds behind you each Badeline Chaser will be
"""
display_name = "Badeline Chaser Speed"
range_start = 2
range_end = 10
default = 3
celeste_64_option_groups = [
OptionGroup("Goal Options", [
TotalStrawberries,
StrawberriesRequiredPercentage,
]),
OptionGroup("Sanity Options", [
Friendsanity,
Signsanity,
Carsanity,
Checkpointsanity,
]),
OptionGroup("Aesthetic Options", [
MadelineOneDashHairColor,
MadelineTwoDashHairColor,
MadelineNoDashHairColor,
MadelineFeatherHairColor,
]),
OptionGroup("Badeline Chasers", [
BadelineChaserSource,
BadelineChaserFrequency,
BadelineChaserSpeed,
]),
]
@dataclass
class Celeste64Options(PerGameCommonOptions):
death_link: DeathLink
death_link_amnesty: DeathLinkAmnesty
total_strawberries: TotalStrawberries
strawberries_required_percentage: StrawberriesRequiredPercentage
logic_difficulty: LogicDifficulty
move_shuffle: MoveShuffle
friendsanity: Friendsanity
signsanity: Signsanity
carsanity: Carsanity
checkpointsanity: Checkpointsanity
madeline_one_dash_hair_color: MadelineOneDashHairColor
madeline_two_dash_hair_color: MadelineTwoDashHairColor
madeline_no_dash_hair_color: MadelineNoDashHairColor
madeline_feather_hair_color: MadelineFeatherHairColor
badeline_chaser_source: BadelineChaserSource
badeline_chaser_frequency: BadelineChaserFrequency
badeline_chaser_speed: BadelineChaserSpeed
def resolve_options(world: World):
# One Dash Hair
if isinstance(world.options.madeline_one_dash_hair_color.value, str):
try:
world.madeline_one_dash_hair_color = int(world.options.madeline_one_dash_hair_color.value.strip("#")[:6], 16)
except ValueError:
raise OptionError(f"Invalid input for option `madeline_one_dash_hair_color`:"
f"{world.options.madeline_one_dash_hair_color.value} for "
f"{world.player_name}")
elif world.options.madeline_one_dash_hair_color.value == ColorChoice.option_any_color:
world.madeline_one_dash_hair_color = world.random.randint(0, 0xFFFFFF)
else:
world.madeline_one_dash_hair_color = world.options.madeline_one_dash_hair_color.value
# Two Dash Hair
if isinstance(world.options.madeline_two_dash_hair_color.value, str):
try:
world.madeline_two_dash_hair_color = int(world.options.madeline_two_dash_hair_color.value.strip("#")[:6], 16)
except ValueError:
raise OptionError(f"Invalid input for option `madeline_two_dash_hair_color`:"
f"{world.options.madeline_two_dash_hair_color.value} for "
f"{world.player_name}")
elif world.options.madeline_two_dash_hair_color.value == ColorChoice.option_any_color:
world.madeline_two_dash_hair_color = world.random.randint(0, 0xFFFFFF)
else:
world.madeline_two_dash_hair_color = world.options.madeline_two_dash_hair_color.value
# No Dash Hair
if isinstance(world.options.madeline_no_dash_hair_color.value, str):
try:
world.madeline_no_dash_hair_color = int(world.options.madeline_no_dash_hair_color.value.strip("#")[:6], 16)
except ValueError:
raise OptionError(f"Invalid input for option `madeline_no_dash_hair_color`:"
f"{world.options.madeline_no_dash_hair_color.value} for "
f"{world.player_name}")
elif world.options.madeline_no_dash_hair_color.value == ColorChoice.option_any_color:
world.madeline_no_dash_hair_color = world.random.randint(0, 0xFFFFFF)
else:
world.madeline_no_dash_hair_color = world.options.madeline_no_dash_hair_color.value
# Feather Hair
if isinstance(world.options.madeline_feather_hair_color.value, str):
try:
world.madeline_feather_hair_color = int(world.options.madeline_feather_hair_color.value.strip("#")[:6], 16)
except ValueError:
raise OptionError(f"Invalid input for option `madeline_feather_hair_color`:"
f"{world.options.madeline_feather_hair_color.value} for "
f"{world.player_name}")
elif world.options.madeline_feather_hair_color.value == ColorChoice.option_any_color:
world.madeline_feather_hair_color = world.random.randint(0, 0xFFFFFF)
else:
world.madeline_feather_hair_color = world.options.madeline_feather_hair_color.value