SA2B: Option Groups and Dataclass (#3357)

* Merge Conflicts

* SA2B: Option Groups

* Re-add erroneously-removed import
This commit is contained in:
PoryGone 2024-05-21 17:48:23 -04:00 committed by GitHub
parent 92b1f3cd19
commit 5c66681233
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 252 additions and 97 deletions

View File

@ -1,18 +1,26 @@
import typing
from dataclasses import dataclass
from Options import Choice, Range, Option, Toggle, DeathLink, DefaultOnToggle, OptionList
from Options import Choice, Range, Toggle, DeathLink, DefaultOnToggle, OptionGroup, PerGameCommonOptions
class Goal(Choice):
"""
Determines the goal of the seed
Biolizard: Finish Cannon's Core and defeat the Biolizard and Finalhazard
Chaos Emerald Hunt: Find the Seven Chaos Emeralds and reach Green Hill Zone
Finalhazard Chaos Emerald Hunt: Find the Seven Chaos Emeralds and reach Green Hill Zone, then defeat Finalhazard
Grand Prix: Win every race in Kart Race Mode (all standard levels are disabled)
Boss Rush: Beat all of the bosses in the Boss Rush, ending with Finalhazard
Cannon's Core Boss Rush: Beat Cannon's Core, then beat all of the bosses in the Boss Rush, ending with Finalhazard
Boss Rush Chaos Emerald Hunt: Find the Seven Chaos Emeralds, then beat all of the bosses in the Boss Rush, ending with Finalhazard
Chaos Chao: Raise a Chaos Chao to win
"""
display_name = "Goal"
@ -46,9 +54,13 @@ class MissionShuffle(Toggle):
class BossRushShuffle(Choice):
"""
Determines how bosses in Boss Rush Mode are shuffled
Vanilla: Bosses appear in the Vanilla ordering
Shuffled: The same bosses appear, but in a random order
Chaos: Each boss is randomly chosen separately (one will always be King Boom Boo)
Singularity: One boss is chosen and placed in every slot (one will always be replaced with King Boom Boo)
"""
display_name = "Boss Rush Shuffle"
@ -196,9 +208,13 @@ class Keysanity(Toggle):
class Whistlesanity(Choice):
"""
Determines whether whistling at various spots grants checks
None: No Whistle Spots grant checks
Pipes: Whistling at Pipes grants checks (97 Locations)
Hidden: Whistling at Hidden Whistle Spots grants checks (32 Locations)
Both: Whistling at both Pipes and Hidden Whistle Spots grants checks (129 Locations)
"""
display_name = "Whistlesanity"
@ -228,8 +244,9 @@ class Omosanity(Toggle):
class Animalsanity(Toggle):
"""
Determines whether unique counts of animals grant checks.
ALL animals must be collected in a single run of a mission to get all checks.
(421 Locations)
ALL animals must be collected in a single run of a mission to get all checks.
"""
display_name = "Animalsanity"
@ -237,8 +254,11 @@ class Animalsanity(Toggle):
class KartRaceChecks(Choice):
"""
Determines whether Kart Race Mode grants checks
None: No Kart Races grant checks
Mini: Each Kart Race difficulty must be beaten only once
Full: Every Character must separately beat each Kart Race difficulty
"""
display_name = "Kart Race Checks"
@ -271,8 +291,11 @@ class NumberOfLevelGates(Range):
class LevelGateDistribution(Choice):
"""
Determines how levels are distributed between level gate regions
Early: Earlier regions will have more levels than later regions
Even: Levels will be evenly distributed between all regions
Late: Later regions will have more levels than earlier regions
"""
display_name = "Level Gate Distribution"
@ -296,7 +319,9 @@ class LevelGateCosts(Choice):
class MaximumEmblemCap(Range):
"""
Determines the maximum number of emblems that can be in the item pool.
If fewer available locations exist in the pool than this number, the number of available locations will be used instead.
Gate and Cannon's Core costs will be calculated based off of that number.
"""
display_name = "Max Emblem Cap"
@ -321,9 +346,13 @@ class RequiredRank(Choice):
class ChaoRaceDifficulty(Choice):
"""
Determines the number of Chao Race difficulty levels included. Easier difficulty settings means fewer Chao Race checks
None: No Chao Races have checks
Beginner: Beginner Races
Intermediate: Beginner, Challenge, Hero, and Dark Races
Expert: Beginner, Challenge, Hero, Dark and Jewel Races
"""
display_name = "Chao Race Difficulty"
@ -350,9 +379,10 @@ class ChaoKarateDifficulty(Choice):
class ChaoStadiumChecks(Choice):
"""
Determines which Chao Stadium activities grant checks
All: Each individual race and karate fight grants a check
Prize: Only the races which grant Chao Toys grant checks (final race of each Beginner and Jewel cup, 4th, 8th, and
12th Challenge Races, 2nd and 4th Hero and Dark Races, final fight of each Karate difficulty)
Prize: Only the races which grant Chao Toys grant checks (final race of each Beginner and Jewel cup, 4th, 8th, and 12th Challenge Races, 2nd and 4th Hero and Dark Races, final fight of each Karate difficulty)
"""
display_name = "Chao Stadium Checks"
option_all = 0
@ -374,6 +404,7 @@ class ChaoStats(Range):
class ChaoStatsFrequency(Range):
"""
Determines how many levels in each Chao Stat grant checks (up to the maximum set in the `chao_stats` option)
`1` means every level is included, `2` means every other level is included, `3` means every third, and so on
"""
display_name = "Chao Stats Frequency"
@ -408,8 +439,11 @@ class ChaoKindergarten(Choice):
"""
Determines whether learning the lessons from the Kindergarten Classroom grants checks
(WARNING: VERY SLOW)
None: No Kindergarten classes have checks
Basics: One class from each category (Drawing, Dance, Song, and Instrument) is a check (4 Locations)
Full: Every class is a check (23 Locations)
"""
display_name = "Chao Kindergarten Checks"
@ -443,8 +477,8 @@ class BlackMarketUnlockCosts(Choice):
class BlackMarketPriceMultiplier(Range):
"""
Determines how many rings the Black Market items cost
The base ring costs of items in the Black Market range from 50-100,
and are then multiplied by this value
The base ring costs of items in the Black Market range from 50-100, and are then multiplied by this value
"""
display_name = "Black Market Price Multiplier"
range_start = 0
@ -469,7 +503,9 @@ class ChaoEntranceRandomization(Toggle):
class RequiredCannonsCoreMissions(Choice):
"""
Determines how many Cannon's Core missions must be completed (for Biolizard or Cannon's Core goals)
First: Only the first mission must be completed
All Active: All active Cannon's Core missions must be completed
"""
display_name = "Required Cannon's Core Missions"
@ -665,8 +701,11 @@ class CannonsCoreMission5(DefaultOnToggle):
class RingLoss(Choice):
"""
How taking damage is handled
Classic: You lose all of your rings when hit
Modern: You lose 20 rings when hit
OHKO: You die immediately when hit (NOTE: Some Hard Logic tricks may require damage boosts!)
"""
display_name = "Ring Loss"
@ -693,9 +732,13 @@ class RingLink(Toggle):
class SADXMusic(Choice):
"""
Whether the randomizer will include Sonic Adventure DX Music in the music pool
SA2B: Only SA2B music will be played
SADX: Only SADX music will be played
Both: Both SA2B and SADX music will be played
NOTE: This option requires the player to own a PC copy of SADX and to follow the addition steps in the setup guide.
"""
display_name = "SADX Music"
@ -715,9 +758,13 @@ class SADXMusic(Choice):
class MusicShuffle(Choice):
"""
What type of Music Shuffle is used
None: No music is shuffled.
Levels: Level music is shuffled.
Full: Level, Menu, and Additional music is shuffled.
Singularity: Level, Menu, and Additional music is all replaced with a single random song.
"""
display_name = "Music Shuffle Type"
@ -731,10 +778,15 @@ class MusicShuffle(Choice):
class VoiceShuffle(Choice):
"""
What type of Voice Shuffle is used
None: No voices are shuffled.
Shuffled: Voices are shuffled.
Rude: Voices are shuffled, but some are replaced with rude words.
Chao: All voices are replaced with chao sounds.
Singularity: All voices are replaced with a single random voice.
"""
display_name = "Voice Shuffle Type"
@ -768,7 +820,9 @@ class Narrator(Choice):
class LogicDifficulty(Choice):
"""
What set of Upgrade Requirement logic to use
Standard: The logic assumes the "intended" usage of Upgrades to progress through levels
Hard: Some simple skips or sequence breaks may be required
"""
display_name = "Logic Difficulty"
@ -777,96 +831,195 @@ class LogicDifficulty(Choice):
default = 0
sa2b_options: typing.Dict[str, type(Option)] = {
"goal": Goal,
sa2b_option_groups = [
OptionGroup("General Options", [
Goal,
BossRushShuffle,
LogicDifficulty,
RequiredRank,
MaximumEmblemCap,
RingLoss,
]),
OptionGroup("Stages", [
MissionShuffle,
EmblemPercentageForCannonsCore,
RequiredCannonsCoreMissions,
NumberOfLevelGates,
LevelGateCosts,
LevelGateDistribution,
]),
OptionGroup("Sanity Options", [
Keysanity,
Whistlesanity,
Beetlesanity,
Omosanity,
Animalsanity,
KartRaceChecks,
]),
OptionGroup("Chao", [
BlackMarketSlots,
BlackMarketUnlockCosts,
BlackMarketPriceMultiplier,
ChaoRaceDifficulty,
ChaoKarateDifficulty,
ChaoStadiumChecks,
ChaoAnimalParts,
ChaoStats,
ChaoStatsFrequency,
ChaoStatsStamina,
ChaoStatsHidden,
ChaoKindergarten,
ShuffleStartingChaoEggs,
ChaoEntranceRandomization,
]),
OptionGroup("Junk and Traps", [
JunkFillPercentage,
TrapFillPercentage,
OmochaoTrapWeight,
TimestopTrapWeight,
ConfusionTrapWeight,
TinyTrapWeight,
GravityTrapWeight,
ExpositionTrapWeight,
IceTrapWeight,
SlowTrapWeight,
CutsceneTrapWeight,
ReverseTrapWeight,
PongTrapWeight,
MinigameTrapDifficulty,
]),
OptionGroup("Speed Missions", [
SpeedMissionCount,
SpeedMission2,
SpeedMission3,
SpeedMission4,
SpeedMission5,
]),
OptionGroup("Mech Missions", [
MechMissionCount,
MechMission2,
MechMission3,
MechMission4,
MechMission5,
]),
OptionGroup("Hunt Missions", [
HuntMissionCount,
HuntMission2,
HuntMission3,
HuntMission4,
HuntMission5,
]),
OptionGroup("Kart Missions", [
KartMissionCount,
KartMission2,
KartMission3,
KartMission4,
KartMission5,
]),
OptionGroup("Cannon's Core Missions", [
CannonsCoreMissionCount,
CannonsCoreMission2,
CannonsCoreMission3,
CannonsCoreMission4,
CannonsCoreMission5,
]),
OptionGroup("Aesthetics", [
SADXMusic,
MusicShuffle,
VoiceShuffle,
Narrator,
]),
]
"mission_shuffle": MissionShuffle,
"boss_rush_shuffle": BossRushShuffle,
"keysanity": Keysanity,
"whistlesanity": Whistlesanity,
"beetlesanity": Beetlesanity,
"omosanity": Omosanity,
"animalsanity": Animalsanity,
"kart_race_checks": KartRaceChecks,
@dataclass
class SA2BOptions(PerGameCommonOptions):
goal: Goal
boss_rush_shuffle: BossRushShuffle
logic_difficulty: LogicDifficulty
required_rank: RequiredRank
max_emblem_cap: MaximumEmblemCap
ring_loss: RingLoss
"logic_difficulty": LogicDifficulty,
"required_rank": RequiredRank,
"required_cannons_core_missions": RequiredCannonsCoreMissions,
mission_shuffle: MissionShuffle
required_cannons_core_missions: RequiredCannonsCoreMissions
emblem_percentage_for_cannons_core: EmblemPercentageForCannonsCore
number_of_level_gates: NumberOfLevelGates
level_gate_distribution: LevelGateDistribution
level_gate_costs: LevelGateCosts
"emblem_percentage_for_cannons_core": EmblemPercentageForCannonsCore,
"number_of_level_gates": NumberOfLevelGates,
"level_gate_distribution": LevelGateDistribution,
"level_gate_costs": LevelGateCosts,
"max_emblem_cap": MaximumEmblemCap,
keysanity: Keysanity
whistlesanity: Whistlesanity
beetlesanity: Beetlesanity
omosanity: Omosanity
animalsanity: Animalsanity
kart_race_checks: KartRaceChecks
"chao_race_difficulty": ChaoRaceDifficulty,
"chao_karate_difficulty": ChaoKarateDifficulty,
"chao_stadium_checks": ChaoStadiumChecks,
"chao_stats": ChaoStats,
"chao_stats_frequency": ChaoStatsFrequency,
"chao_stats_stamina": ChaoStatsStamina,
"chao_stats_hidden": ChaoStatsHidden,
"chao_animal_parts": ChaoAnimalParts,
"chao_kindergarten": ChaoKindergarten,
"black_market_slots": BlackMarketSlots,
"black_market_unlock_costs": BlackMarketUnlockCosts,
"black_market_price_multiplier": BlackMarketPriceMultiplier,
"shuffle_starting_chao_eggs": ShuffleStartingChaoEggs,
"chao_entrance_randomization": ChaoEntranceRandomization,
black_market_slots: BlackMarketSlots
black_market_unlock_costs: BlackMarketUnlockCosts
black_market_price_multiplier: BlackMarketPriceMultiplier
chao_race_difficulty: ChaoRaceDifficulty
chao_karate_difficulty: ChaoKarateDifficulty
chao_stadium_checks: ChaoStadiumChecks
chao_animal_parts: ChaoAnimalParts
chao_stats: ChaoStats
chao_stats_frequency: ChaoStatsFrequency
chao_stats_stamina: ChaoStatsStamina
chao_stats_hidden: ChaoStatsHidden
chao_kindergarten: ChaoKindergarten
shuffle_starting_chao_eggs: ShuffleStartingChaoEggs
chao_entrance_randomization: ChaoEntranceRandomization
"junk_fill_percentage": JunkFillPercentage,
"trap_fill_percentage": TrapFillPercentage,
"omochao_trap_weight": OmochaoTrapWeight,
"timestop_trap_weight": TimestopTrapWeight,
"confusion_trap_weight": ConfusionTrapWeight,
"tiny_trap_weight": TinyTrapWeight,
"gravity_trap_weight": GravityTrapWeight,
"exposition_trap_weight": ExpositionTrapWeight,
#"darkness_trap_weight": DarknessTrapWeight,
"ice_trap_weight": IceTrapWeight,
"slow_trap_weight": SlowTrapWeight,
"cutscene_trap_weight": CutsceneTrapWeight,
"reverse_trap_weight": ReverseTrapWeight,
"pong_trap_weight": PongTrapWeight,
"minigame_trap_difficulty": MinigameTrapDifficulty,
junk_fill_percentage: JunkFillPercentage
trap_fill_percentage: TrapFillPercentage
omochao_trap_weight: OmochaoTrapWeight
timestop_trap_weight: TimestopTrapWeight
confusion_trap_weight: ConfusionTrapWeight
tiny_trap_weight: TinyTrapWeight
gravity_trap_weight: GravityTrapWeight
exposition_trap_weight: ExpositionTrapWeight
#darkness_trap_weight: DarknessTrapWeight
ice_trap_weight: IceTrapWeight
slow_trap_weight: SlowTrapWeight
cutscene_trap_weight: CutsceneTrapWeight
reverse_trap_weight: ReverseTrapWeight
pong_trap_weight: PongTrapWeight
minigame_trap_difficulty: MinigameTrapDifficulty
"sadx_music": SADXMusic,
"music_shuffle": MusicShuffle,
"voice_shuffle": VoiceShuffle,
"narrator": Narrator,
"ring_loss": RingLoss,
sadx_music: SADXMusic
music_shuffle: MusicShuffle
voice_shuffle: VoiceShuffle
narrator: Narrator
"speed_mission_count": SpeedMissionCount,
"speed_mission_2": SpeedMission2,
"speed_mission_3": SpeedMission3,
"speed_mission_4": SpeedMission4,
"speed_mission_5": SpeedMission5,
speed_mission_count: SpeedMissionCount
speed_mission_2: SpeedMission2
speed_mission_3: SpeedMission3
speed_mission_4: SpeedMission4
speed_mission_5: SpeedMission5
"mech_mission_count": MechMissionCount,
"mech_mission_2": MechMission2,
"mech_mission_3": MechMission3,
"mech_mission_4": MechMission4,
"mech_mission_5": MechMission5,
mech_mission_count: MechMissionCount
mech_mission_2: MechMission2
mech_mission_3: MechMission3
mech_mission_4: MechMission4
mech_mission_5: MechMission5
"hunt_mission_count": HuntMissionCount,
"hunt_mission_2": HuntMission2,
"hunt_mission_3": HuntMission3,
"hunt_mission_4": HuntMission4,
"hunt_mission_5": HuntMission5,
hunt_mission_count: HuntMissionCount
hunt_mission_2: HuntMission2
hunt_mission_3: HuntMission3
hunt_mission_4: HuntMission4
hunt_mission_5: HuntMission5
"kart_mission_count": KartMissionCount,
"kart_mission_2": KartMission2,
"kart_mission_3": KartMission3,
"kart_mission_4": KartMission4,
"kart_mission_5": KartMission5,
kart_mission_count: KartMissionCount
kart_mission_2: KartMission2
kart_mission_3: KartMission3
kart_mission_4: KartMission4
kart_mission_5: KartMission5
"cannons_core_mission_count": CannonsCoreMissionCount,
"cannons_core_mission_2": CannonsCoreMission2,
"cannons_core_mission_3": CannonsCoreMission3,
"cannons_core_mission_4": CannonsCoreMission4,
"cannons_core_mission_5": CannonsCoreMission5,
cannons_core_mission_count: CannonsCoreMissionCount
cannons_core_mission_2: CannonsCoreMission2
cannons_core_mission_3: CannonsCoreMission3
cannons_core_mission_4: CannonsCoreMission4
cannons_core_mission_5: CannonsCoreMission5
"ring_link": RingLink,
"death_link": DeathLink,
}
ring_link: RingLink
death_link: DeathLink

View File

@ -3,20 +3,20 @@ import math
import logging
from BaseClasses import Item, MultiWorld, Tutorial, ItemClassification
from worlds.AutoWorld import WebWorld, World
from .AestheticData import chao_name_conversion, sample_chao_names, totally_real_item_names, \
all_exits, all_destinations, multi_rooms, single_rooms, room_to_exits_map, exit_to_room_map, valid_kindergarten_exits
from .GateBosses import get_gate_bosses, get_boss_rush_bosses, get_boss_name
from .Items import SA2BItem, ItemData, item_table, upgrades_table, emeralds_table, junk_table, trap_table, item_groups, \
eggs_table, fruits_table, seeds_table, hats_table, animals_table, chaos_drives_table
from .Locations import SA2BLocation, all_locations, setup_locations, chao_animal_event_location_table, black_market_location_table
from .Options import sa2b_options
from .Missions import get_mission_table, get_mission_count_table, get_first_and_last_cannons_core_missions
from .Names import ItemName, LocationName
from .Options import SA2BOptions, sa2b_option_groups
from .Regions import create_regions, shuffleable_regions, connect_regions, LevelGate, gate_0_whitelist_regions, \
gate_0_blacklist_regions
from .Rules import set_rules
from .Names import ItemName, LocationName
from .AestheticData import chao_name_conversion, sample_chao_names, totally_real_item_names, \
all_exits, all_destinations, multi_rooms, single_rooms, room_to_exits_map, exit_to_room_map, valid_kindergarten_exits
from worlds.AutoWorld import WebWorld, World
from .GateBosses import get_gate_bosses, get_boss_rush_bosses, get_boss_name
from .Missions import get_mission_table, get_mission_count_table, get_first_and_last_cannons_core_missions
import Patch
class SA2BWeb(WebWorld):
@ -30,8 +30,9 @@ class SA2BWeb(WebWorld):
"setup/en",
["RaspberrySpaceJam", "PoryGone", "Entiss"]
)
tutorials = [setup_en]
option_groups = sa2b_option_groups
def check_for_impossible_shuffle(shuffled_levels: typing.List[int], gate_0_range: int, multiworld: MultiWorld):
@ -54,7 +55,8 @@ class SA2BWorld(World):
Sonic Adventure 2 Battle is an action platforming game. Play as Sonic, Tails, Knuckles, Shadow, Rouge, and Eggman across 31 stages and prevent the destruction of the earth.
"""
game: str = "Sonic Adventure 2 Battle"
option_definitions = sa2b_options
options_dataclass = SA2BOptions
options: SA2BOptions
topology_present = False
data_version = 7