import random from dataclasses import dataclass from typing import List from Options import DeathLinkMixin, Choice, Toggle, OptionDict, Range, PlandoBosses, DefaultOnToggle, \ PerGameCommonOptions, Visibility, NamedRange, OptionGroup, PlandoConnections from .names import location_name class RemoteItems(DefaultOnToggle): """ Enables receiving items from your own world, primarily for co-op play. """ display_name = "Remote Items" class KDL3PlandoConnections(PlandoConnections): entrances = exits = {f"{i} {j}" for i in location_name.level_names for j in range(1, 7)} class Goal(Choice): """ Zero: collect the Heart Stars, and defeat Zero in the Hyper Zone. Boss Butch: collect the Heart Stars, and then complete the boss rematches in the Boss Butch mode. MG5: collect the Heart Stars, and then complete a perfect run through the minigame gauntlet within the Super MG5 Jumping: collect the Heart Stars, and then reach a designated score within the Jumping sub-game """ display_name = "Goal" option_zero = 0 option_boss_butch = 1 option_MG5 = 2 option_jumping = 3 default = 0 @classmethod def get_option_name(cls, value: int) -> str: if value == 2: return cls.name_lookup[value].upper() return super().get_option_name(value) class GoalSpeed(Choice): """ Normal: the goal is unlocked after purifying the five bosses Fast: the goal is unlocked after acquiring the target number of Heart Stars """ display_name = "Goal Speed" option_normal = 0 option_fast = 1 class MaxHeartStars(Range): """ Maximum number of heart stars to include in the pool of items. If fewer available locations exist in the pool than this number, the number of available locations will be used instead. """ display_name = "Max Heart Stars" range_start = 5 # set to 5 so strict bosses does not degrade range_end = 99 # previously set to 50, set to highest it can be should there be less locations than heart stars default = 30 class HeartStarsRequired(Range): """ Percentage of heart stars required to purify the five bosses and reach Zero. Each boss will require a differing amount of heart stars to purify. """ display_name = "Required Heart Stars" range_start = 1 range_end = 100 default = 50 class LevelShuffle(Choice): """ None: No stage shuffling. Same World: shuffles stages around their world. Pattern: shuffles stages according to the stage pattern (stage 3 will always be a minigame stage, etc.) Shuffled: shuffles stages across all worlds. """ display_name = "Stage Shuffle" option_none = 0 option_same_world = 1 option_pattern = 2 option_shuffled = 3 default = 0 class BossShuffle(PlandoBosses): """ None: Bosses will remain in their vanilla locations Shuffled: Bosses will be shuffled amongst each other Full: Bosses will be randomized Singularity: All (non-Zero) bosses will be replaced with a single boss Supports plando placement. """ bosses = frozenset(location_name.boss_names.keys()) locations = frozenset(location_name.level_names.keys()) duplicate_bosses = True @classmethod def can_place_boss(cls, boss: str, location: str) -> bool: # Kirby has no logic about requiring bosses in specific locations (since we load in their stage) return True display_name = "Boss Shuffle" option_none = 0 option_shuffled = 1 option_full = 2 option_singularity = 3 class BossShuffleAllowBB(Choice): """ Allow Boss Butch variants of bosses in Boss Shuffle. Enabled: any boss placed will have a 50% chance of being the Boss Butch variant, including bosses not present Enforced: all bosses will be their Boss Butch variant. Boss Butch boss changes are only visual. """ display_name = "Allow Boss Butch Bosses" option_disabled = 0 option_enabled = 1 option_enforced = 2 default = 0 class AnimalRandomization(Choice): """ Disabled: all animal positions will be vanilla. Shuffled: all animal positions will be shuffled amongst each other. Full: random animals will be placed across the levels. At least one of each animal is guaranteed. """ display_name = "Animal Randomization" option_disabled = 0 option_shuffled = 1 option_full = 2 default = 0 class CopyAbilityRandomization(Choice): """ Disabled: enemies give regular copy abilities and health. Enabled: all enemies will have the copy ability received from them randomized. Enabled Plus Minus: enemies (except minibosses) can additionally give you anywhere from +2 health to -1 health when eaten. """ display_name = "Copy Ability Randomization" option_disabled = 0 option_enabled = 1 option_enabled_plus_minus = 2 class StrictBosses(DefaultOnToggle): """ If enabled, one will not be able to move onto the next world until the previous world's boss has been purified. """ display_name = "Strict Bosses" class OpenWorld(DefaultOnToggle): """ If enabled, all 6 stages will be unlocked upon entering a world for the first time. A certain amount of stages will need to be completed in order to unlock the bosses """ display_name = "Open World" class OpenWorldBossRequirement(Range): """ The amount of stages completed needed to unlock the boss of a world when Open World is turned on. """ display_name = "Open World Boss Requirement" range_start = 1 range_end = 6 default = 3 class BossRequirementRandom(Toggle): """ If enabled, boss purification will require a random amount of Heart Stars. Depending on options, this may have boss purification unlock in a random order. """ display_name = "Randomize Purification Requirement" class JumpingTarget(Range): """ The required score needed to complete the Jumping minigame. """ display_name = "Jumping Target Score" range_start = 1 range_end = 25 default = 10 class GameLanguage(Choice): """ The language that the game should display. This does not have to match the given rom. """ display_name = "Game Language" option_japanese = 0 option_english = 1 default = 1 class FillerPercentage(Range): """ Percentage of non-required Heart Stars to be converted to filler items (1-Ups, Maxim Tomatoes, Invincibility Candy). """ display_name = "Filler Percentage" range_start = 0 range_end = 100 default = 50 class TrapPercentage(Range): """ Percentage of filler items to be converted to trap items (Gooey Bags, Slowness, Eject Ability). """ display_name = "Trap Percentage" range_start = 0 range_end = 100 default = 50 class GooeyTrapPercentage(Range): """ Chance that any given trap is a Gooey Bag (spawns Gooey when you receive it). """ display_name = "Gooey Trap Percentage" range_start = 0 range_end = 100 default = 50 class SlowTrapPercentage(Range): """ Chance that any given trap is Slowness (halves your max speed for 15 seconds when you receive it). """ display_name = "Slowness Trap Percentage" range_start = 0 range_end = 100 default = 50 class AbilityTrapPercentage(Range): """ Chance that any given trap is an Eject Ability (ejects your ability when you receive it). """ display_name = "Ability Trap Percentage" range_start = 0 range_end = 100 default = 50 class ConsumableChecks(Toggle): """ When enabled, adds all 1-Ups and Maxim Tomatoes as possible locations. """ display_name = "Consumable-sanity" class StarChecks(Toggle): """ When enabled, every star in a given stage will become a check. Will increase the possible filler pool to include 1/3/5 stars. """ display_name = "Starsanity" class KirbyFlavorPreset(Choice): """ The color of Kirby, from a list of presets. """ display_name = "Kirby Flavor" option_default = 0 option_bubblegum = 1 option_cherry = 2 option_blueberry = 3 option_lemon = 4 option_kiwi = 5 option_grape = 6 option_chocolate = 7 option_marshmallow = 8 option_licorice = 9 option_watermelon = 10 option_orange = 11 option_lime = 12 option_lavender = 13 option_miku = 14 option_custom = 15 default = 0 @classmethod def from_text(cls, text: str) -> Choice: text = text.lower() if text == "random": choice_list = list(cls.name_lookup) choice_list.remove(14) return cls(random.choice(choice_list)) return super().from_text(text) class KirbyFlavor(OptionDict): """ A custom color for Kirby. To use a custom color, set the preset to Custom and then define a dict of keys from "1" to "15", with their values being an HTML hex color. """ display_name = "Custom Kirby Flavor" default = { "1": "B01810", "2": "F0E0E8", "3": "C8A0A8", "4": "A87070", "5": "E02018", "6": "F0A0B8", "7": "D07880", "8": "A85048", "9": "E8D0D0", "10": "E85048", "11": "D0C0C0", "12": "B08888", "13": "E87880", "14": "F8F8F8", "15": "B03830", } visibility = Visibility.template | Visibility.spoiler # likely never supported on guis class GooeyFlavorPreset(Choice): """ The color of Gooey, from a list of presets. """ display_name = "Gooey Flavor" option_default = 0 option_bubblegum = 1 option_cherry = 2 option_blueberry = 3 option_lemon = 4 option_kiwi = 5 option_grape = 6 option_chocolate = 7 option_marshmallow = 8 option_licorice = 9 option_watermelon = 10 option_orange = 11 option_lime = 12 option_lavender = 13 option_custom = 14 default = 0 @classmethod def from_text(cls, text: str) -> Choice: text = text.lower() if text == "random": choice_list = list(cls.name_lookup) choice_list.remove(14) return cls(random.choice(choice_list)) return super().from_text(text) class GooeyFlavor(OptionDict): """ A custom color for Gooey. To use a custom color, set the preset to Custom and then define a dict of keys from "1" to "15", with their values being an HTML hex color. """ display_name = "Custom Gooey Flavor" default = { "1": "000808", "2": "102838", "3": "183048", "4": "183878", "5": "1838A0", "6": "B01810", "7": "E85048", "8": "D0C0C0", "9": "F8F8F8", } visibility = Visibility.template | Visibility.spoiler # likely never supported on guis class MusicShuffle(Choice): """ None: default music will play Shuffled: music will be shuffled amongst each other Full: random music will play in each room Note that certain songs will not be chosen in shuffled or full """ display_name = "Music Randomization" option_none = 0 option_shuffled = 1 option_full = 2 default = 0 class VirtualConsoleChanges(Choice): """ Adds the ability to enable 2 of the Virtual Console changes. Flash Reduction: reduces the flashing during the Zero battle. Color Changes: changes the color of the background within the Zero Boss Butch rematch. """ display_name = "Virtual Console Changes" option_none = 0 option_flash_reduction = 1 option_color_changes = 2 option_both = 3 default = 1 class Gifting(Toggle): """ When enabled, the goal game item will be sent to other compatible games as a gift, and you can receive gifts from other players. This can be enabled during gameplay using the client. """ display_name = "Gifting" class TotalHeartStars(NamedRange): """ Deprecated. Use max_heart_stars instead. Supported for only one version. """ default = -1 range_start = 5 range_end = 99 special_range_names = { "default": -1 } visibility = Visibility.none @dataclass class KDL3Options(PerGameCommonOptions, DeathLinkMixin): remote_items: RemoteItems plando_connections: KDL3PlandoConnections game_language: GameLanguage goal: Goal goal_speed: GoalSpeed max_heart_stars: MaxHeartStars heart_stars_required: HeartStarsRequired filler_percentage: FillerPercentage trap_percentage: TrapPercentage gooey_trap_weight: GooeyTrapPercentage slow_trap_weight: SlowTrapPercentage ability_trap_weight: AbilityTrapPercentage jumping_target: JumpingTarget stage_shuffle: LevelShuffle boss_shuffle: BossShuffle allow_bb: BossShuffleAllowBB animal_randomization: AnimalRandomization copy_ability_randomization: CopyAbilityRandomization strict_bosses: StrictBosses open_world: OpenWorld ow_boss_requirement: OpenWorldBossRequirement boss_requirement_random: BossRequirementRandom consumables: ConsumableChecks starsanity: StarChecks gifting: Gifting kirby_flavor_preset: KirbyFlavorPreset kirby_flavor: KirbyFlavor gooey_flavor_preset: GooeyFlavorPreset gooey_flavor: GooeyFlavor music_shuffle: MusicShuffle virtual_console: VirtualConsoleChanges total_heart_stars: TotalHeartStars # remove in 2 versions kdl3_option_groups: List[OptionGroup] = [ OptionGroup("Goal Options", [Goal, GoalSpeed, MaxHeartStars, HeartStarsRequired, JumpingTarget, ]), OptionGroup("World Options", [RemoteItems, StrictBosses, OpenWorld, OpenWorldBossRequirement, ConsumableChecks, StarChecks, FillerPercentage, TrapPercentage, GooeyTrapPercentage, SlowTrapPercentage, AbilityTrapPercentage, LevelShuffle, BossShuffle, AnimalRandomization, CopyAbilityRandomization, BossRequirementRandom, Gifting, ]), OptionGroup("Cosmetic Options", [GameLanguage, BossShuffleAllowBB, KirbyFlavorPreset, KirbyFlavor, GooeyFlavorPreset, GooeyFlavor, MusicShuffle, VirtualConsoleChanges, ]), ]