2024-03-05 15:59:55 +00:00
|
|
|
import random
|
|
|
|
from dataclasses import dataclass
|
2024-08-31 11:15:00 +00:00
|
|
|
from typing import List
|
2024-03-05 15:59:55 +00:00
|
|
|
|
2024-08-31 11:15:00 +00:00
|
|
|
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"
|
2024-03-05 15:59:55 +00:00
|
|
|
|
|
|
|
|
2024-06-01 11:34:41 +00:00
|
|
|
class KDL3PlandoConnections(PlandoConnections):
|
2024-08-31 11:15:00 +00:00
|
|
|
entrances = exits = {f"{i} {j}" for i in location_name.level_names for j in range(1, 7)}
|
2024-06-01 11:34:41 +00:00
|
|
|
|
|
|
|
|
2024-03-05 15:59:55 +00:00
|
|
|
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)
|
|
|
|
|
2024-08-31 11:15:00 +00:00
|
|
|
|
2024-03-05 15:59:55 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2024-08-31 11:15:00 +00:00
|
|
|
class MaxHeartStars(Range):
|
2024-03-05 15:59:55 +00:00
|
|
|
"""
|
|
|
|
Maximum number of heart stars to include in the pool of items.
|
2024-08-31 11:15:00 +00:00
|
|
|
If fewer available locations exist in the pool than this number, the number of available locations will be used instead.
|
2024-03-05 15:59:55 +00:00
|
|
|
"""
|
|
|
|
display_name = "Max Heart Stars"
|
|
|
|
range_start = 5 # set to 5 so strict bosses does not degrade
|
2024-08-31 11:15:00 +00:00
|
|
|
range_end = 99 # previously set to 50, set to highest it can be should there be less locations than heart stars
|
2024-03-05 15:59:55 +00:00
|
|
|
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.
|
|
|
|
"""
|
2024-08-31 11:15:00 +00:00
|
|
|
bosses = frozenset(location_name.boss_names.keys())
|
2024-03-05 15:59:55 +00:00
|
|
|
|
2024-08-31 11:15:00 +00:00
|
|
|
locations = frozenset(location_name.level_names.keys())
|
2024-03-05 15:59:55 +00:00
|
|
|
|
|
|
|
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
|
2024-08-31 11:15:00 +00:00
|
|
|
option_miku = 14
|
|
|
|
option_custom = 15
|
2024-03-05 15:59:55 +00:00
|
|
|
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.
|
|
|
|
"""
|
2024-08-31 11:15:00 +00:00
|
|
|
display_name = "Custom Kirby Flavor"
|
2024-03-05 15:59:55 +00:00
|
|
|
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",
|
|
|
|
}
|
2024-08-31 11:15:00 +00:00
|
|
|
visibility = Visibility.template | Visibility.spoiler # likely never supported on guis
|
2024-03-05 15:59:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
"""
|
2024-08-31 11:15:00 +00:00
|
|
|
display_name = "Custom Gooey Flavor"
|
2024-03-05 15:59:55 +00:00
|
|
|
default = {
|
|
|
|
"1": "000808",
|
|
|
|
"2": "102838",
|
|
|
|
"3": "183048",
|
|
|
|
"4": "183878",
|
|
|
|
"5": "1838A0",
|
|
|
|
"6": "B01810",
|
|
|
|
"7": "E85048",
|
|
|
|
"8": "D0C0C0",
|
|
|
|
"9": "F8F8F8",
|
|
|
|
}
|
2024-08-31 11:15:00 +00:00
|
|
|
visibility = Visibility.template | Visibility.spoiler # likely never supported on guis
|
2024-03-05 15:59:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
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"
|
|
|
|
|
|
|
|
|
2024-08-31 11:15:00 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2024-03-05 15:59:55 +00:00
|
|
|
@dataclass
|
2024-08-31 11:15:00 +00:00
|
|
|
class KDL3Options(PerGameCommonOptions, DeathLinkMixin):
|
|
|
|
remote_items: RemoteItems
|
2024-06-01 11:34:41 +00:00
|
|
|
plando_connections: KDL3PlandoConnections
|
2024-03-05 15:59:55 +00:00
|
|
|
game_language: GameLanguage
|
|
|
|
goal: Goal
|
|
|
|
goal_speed: GoalSpeed
|
2024-08-31 11:15:00 +00:00
|
|
|
max_heart_stars: MaxHeartStars
|
2024-03-05 15:59:55 +00:00
|
|
|
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
|
2024-08-31 11:15:00 +00:00
|
|
|
|
|
|
|
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, ]),
|
|
|
|
]
|