forked from mirror/Archipelago
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
288 lines
11 KiB
Python
288 lines
11 KiB
Python
from typing import TYPE_CHECKING
|
|
from dataclasses import dataclass
|
|
|
|
from . import Locations
|
|
from Options import Choice, DefaultOnToggle, Toggle, Range, OptionList, StartInventoryPool, PerGameCommonOptions
|
|
|
|
if TYPE_CHECKING:
|
|
from . import MK64World
|
|
|
|
|
|
class TwoPlayer(Toggle):
|
|
"""(NOT YET SUPPORTED)
|
|
Start with two characters unlocked and shuffle a separate Player 2 set of item powers into the item pool.
|
|
|
|
This is the intended way to do local multiplayer, but you can still access the 2-player grand prix mode
|
|
with this off, and the 1-player grand prix mode with it on."""
|
|
display_name = "Two Player Couch Co-op"
|
|
|
|
|
|
class GameMode(Choice):
|
|
"""Determines how to advance through the game. Cups is closest to the vanilla game.
|
|
|
|
Cups: Courses are raced in sets of four, place 4th or better to advance each race. Unlock each cup progressively.
|
|
The Cups victory condition is beating the Special Cup on 150cc.
|
|
|
|
Courses (NOT YET SUPPORTED): Each course is run individually. Unlock the final courses progressively to reach the
|
|
final race. The Courses victory condition is winning 1st place on the last course."""
|
|
display_name = "Game Mode"
|
|
option_cups = 0
|
|
option_courses = 1
|
|
default = 0
|
|
|
|
|
|
class LogicDifficulty(Choice):
|
|
"""Scales the logic threshhold where skill is involved. Specifically, how many good items are available before you
|
|
are expected to be able to qualify and win on tough courses.
|
|
|
|
Basic: Makes sure you have plenty of good items early. For easier play, or skipping 50 cc.
|
|
(Basic is more likely to fail generation. To raise chances try increasing shuffle_item_box_clusters and
|
|
minimum_filler_items. Future versions will be less fragile to generation failure.)
|
|
|
|
Advanced: Balanced runs for a competent karter.
|
|
|
|
Expert: Low logic, high randomness, high skill. Few good items may be available early in the run.
|
|
|
|
No Logic: If fences are enabled, THE RUN MAY BE NEAR IMPOSSIBLE!"""
|
|
display_name = "Logic Difficulty"
|
|
option_basic = 6
|
|
option_advanced = 3
|
|
option_expert = 0
|
|
option_no_logic = -100
|
|
default = 6
|
|
|
|
|
|
class LockedCourses(Range):
|
|
"""(NOT YET SUPPORTED)
|
|
In Courses Game Mode, how many final courses are locked until Progressive Course Unlock items are found."""
|
|
display_name = "Locked Courses"
|
|
range_start = 0
|
|
range_end = 15
|
|
default = 4
|
|
|
|
|
|
class CourseOrder(Choice):
|
|
"""The order for the courses to be arranged in."""
|
|
display_name = "Course Order"
|
|
option_vanilla = 0
|
|
option_shuffle = 1
|
|
option_short_to_long = 2
|
|
option_long_to_short = 3
|
|
option_alphabetical = 4
|
|
default = 1
|
|
|
|
|
|
class FinalCoursePool(OptionList):
|
|
"""When Course Order is set to shuffle, the final course will be chosen from the Final Course Pool.
|
|
Leaving this blank will allow any course to come last.
|
|
|
|
For Rainbow Road to come last use: ["Rainbow Road"].
|
|
|
|
For Bowser's Castle to come last use: ["Bowser's Castle"].
|
|
|
|
For any course longer than 1000 meters to come last use: ["Rainbow Road", "Wario Stadium", "Toad's Turnpike"]."""
|
|
display_name = "Final Course Pool"
|
|
valid_keys = frozenset({course_name.casefold() for course_name in Locations.course_locations.keys()})
|
|
valid_keys_casefold = True
|
|
|
|
|
|
class MirrorCourseChance(Range):
|
|
"""(NOT YET SUPPORTED) Percent chance for a course to be mirrored."""
|
|
display_name = "Mirror Course Chance"
|
|
range_start = 0
|
|
range_end = 100
|
|
default = 0
|
|
|
|
|
|
class TwoLapCourses(Choice):
|
|
"""Reduce the number of laps in a race from 3 to 2 on long courses."""
|
|
display_name = "Two Lap Courses"
|
|
option_off = 0
|
|
option_rainbow_road = 1
|
|
option_wario_stadium = 2
|
|
option_rainbow_road_and_wario_stadium = 3
|
|
default = 0
|
|
|
|
|
|
class HazardLocations(DefaultOnToggle):
|
|
"""Whether to include hazards which can be destroyed or defeated by the star power as location checks."""
|
|
display_name = "Add Hazard Locations"
|
|
|
|
|
|
class SecretLocations(DefaultOnToggle):
|
|
"""Whether to add 10 location checks as item pickups in noteworthy locations on certain courses."""
|
|
display_name = "Add Course Secret Locations"
|
|
|
|
|
|
class ShuffleDriftAbilities(Choice):
|
|
"""Optionally shuffle into the item pool the ability to drift and the ability to use mini-turbos as progressive
|
|
unlocks per kart. "Plentiful" shuffles a 3rd progressive unlock into the pool. "Free Drift" means karts start
|
|
with the ability to drift. "Free mini-turbo" means both abilities will be obtained together."""
|
|
display_name = "Shuffle Drift Abilities"
|
|
option_off = 0
|
|
option_on = 1
|
|
option_plentiful = 2
|
|
option_free_drift = 3
|
|
option_free_mini_turbo = 4
|
|
alias_vanilla = 0
|
|
alias_shuffle = 0
|
|
alias_false = 0
|
|
alias_on = 1
|
|
alias_yes = 1
|
|
alias_true = 1
|
|
default = 1
|
|
|
|
|
|
class TractionTires(DefaultOnToggle):
|
|
"""Optionally shuffle into the item pool the ability to have traction on off-road and winter surface types,
|
|
per kart. "Off" means karts always have traction, as in the vanilla game."""
|
|
display_name = "Add Traction Tires"
|
|
|
|
|
|
class StartingItems(DefaultOnToggle):
|
|
"""Optionally shuffle into the item pool a random item power to start each race with, per kart. For example
|
|
Mario may be able to start each race with a blue shell. Which item is random per kart."""
|
|
display_name = "Add Starting Items"
|
|
|
|
|
|
class ShuffleRailings(DefaultOnToggle):
|
|
"""Whether to shuffle most track railings into the item pool."""
|
|
display_name = "Shuffle Railings"
|
|
|
|
|
|
class Fences(DefaultOnToggle):
|
|
"""Adds colored fences to every course to add variety to the player's racing lines, and blocks about 20% of
|
|
item boxes. Also adds Yellow/Red/Green/Blue Switch items to the item pool which disable that color of fences.
|
|
Fences only affect player karts; shells and CPU karts path through them."""
|
|
display_name = "Fences Block Paths"
|
|
|
|
|
|
class FeatherItem(DefaultOnToggle):
|
|
"""Adds the feather item as seen in Super Mario Kart and the early demos of Mario Kart 64. It can be used to vault
|
|
fences. Having access to the feather puts locations blocked by fences in logic."""
|
|
display_name = "Feather Item"
|
|
|
|
|
|
class ShuffleItemBoxRespawning(Toggle):
|
|
"""Causes item boxes to not respawn mid-race, and shuffles one "item box respawning" item into the item pool."""
|
|
display_name = "Shuffle Item Box Respawning"
|
|
|
|
|
|
class ConsistentItemBoxes(Choice):
|
|
"""Make each item box always give the same item. "On" will always show which item will be given instead of a
|
|
question mark (?) inside the item boxes. "Identify" will only show which item will be given after triggering the
|
|
item roulette once."""
|
|
display_name = "Consistent Item Boxes"
|
|
option_off = 0
|
|
option_on = 1
|
|
option_identify = 2
|
|
default = 0
|
|
|
|
|
|
class ShuffleSpecialItemBoxes(DefaultOnToggle):
|
|
"""Whether to shuffle the special item boxes which always give blue shells into the item pool. One is attached to
|
|
the hot air balloon on Luigi Raceway, and the other is on the big rock on Koopa Troopa Beach."""
|
|
display_name = "Shuffle Special Item Boxes"
|
|
|
|
|
|
class ShuffleItemBoxClusters(Range):
|
|
"""How many item box clusters to shuffle into the item pool. At least one item spot from each shuffled cluster will
|
|
be used as a location check.
|
|
(More shuffled clusters helps generation succeed. Future versions will be less fragile to generation failure.)"""
|
|
display_name = "Shuffle Item Box Clusters"
|
|
range_start = 0
|
|
range_end = 72
|
|
default = 36
|
|
|
|
|
|
class FillerTrapPercentage(Range):
|
|
"""What percentage of filler items will be traps."""
|
|
display_name = "Filler Trap Percentage"
|
|
range_start = 0
|
|
range_end = 100
|
|
default = 20
|
|
|
|
|
|
class MinimumFillerItems(Range):
|
|
"""Force more filler items than needed to match the number of locations.
|
|
(More filler items helps generation succeed. Future versions will be less fragile to generation failure.)"""
|
|
display_name = "Minimum Filler Items"
|
|
range_start = 0
|
|
range_end = 40
|
|
default = 30
|
|
|
|
|
|
class FixResultsMusic(DefaultOnToggle):
|
|
"""Fixes the race win results screen music so the first section repeats 2 times, not 64 times.
|
|
The official soundtrack uses this AABB form."""
|
|
display_name = "Fix Winning Results Music"
|
|
|
|
|
|
class SoundMode(Choice): # TODO: Add support for this
|
|
"""(NOT YET SUPPORTED)
|
|
Sets the sound mode in the game's option menu ahead of time."""
|
|
display_name = "Sound Mode"
|
|
option_stereo = 0
|
|
option_headphones = 1
|
|
option_mono = 2
|
|
default = 0
|
|
|
|
|
|
# Options as they will appear in YAML settings
|
|
@dataclass
|
|
class MK64Options(PerGameCommonOptions):
|
|
start_inventory_from_pool: StartInventoryPool
|
|
two_player: TwoPlayer
|
|
game_mode: GameMode
|
|
locked_courses: LockedCourses
|
|
course_order: CourseOrder
|
|
logic_difficulty: LogicDifficulty
|
|
final_course_pool: FinalCoursePool
|
|
mirror_course_chance: MirrorCourseChance
|
|
two_lap_courses: TwoLapCourses
|
|
hazard_locations: HazardLocations
|
|
secret_locations: SecretLocations
|
|
shuffle_drift_abilities: ShuffleDriftAbilities
|
|
add_traction_tires: TractionTires
|
|
add_starting_items: StartingItems
|
|
shuffle_railings: ShuffleRailings
|
|
fences: Fences
|
|
feather_item: FeatherItem
|
|
shuffle_item_box_respawning: ShuffleItemBoxRespawning
|
|
consistent_item_boxes: ConsistentItemBoxes
|
|
shuffle_special_item_boxes: ShuffleSpecialItemBoxes
|
|
shuffle_item_box_clusters: ShuffleItemBoxClusters
|
|
filler_trap_percentage: FillerTrapPercentage
|
|
minimum_filler_items: MinimumFillerItems
|
|
fix_results_music: FixResultsMusic
|
|
sound_mode: SoundMode
|
|
|
|
|
|
# Used for shorthand/faster access to relevant options during world generation
|
|
class Opt:
|
|
def __init__(self, world: "MK64World"):
|
|
# Relevant Options
|
|
self.two_player = world.options.two_player.value
|
|
self.mode = world.options.game_mode.value
|
|
self.course_order = world.options.course_order.value
|
|
self.locked_courses = world.options.locked_courses.value
|
|
self.logic = world.options.logic_difficulty.value
|
|
self.final_pool = world.options.final_course_pool.value
|
|
self.mirror_chance = world.options.mirror_course_chance.value
|
|
self.two_lap_courses = world.options.two_lap_courses.value
|
|
self.hazards = world.options.hazard_locations.value
|
|
self.secrets = world.options.secret_locations.value
|
|
self.drift = world.options.shuffle_drift_abilities.value
|
|
self.traction = world.options.add_traction_tires.value
|
|
self.starting_items = world.options.add_starting_items.value
|
|
self.railings = world.options.shuffle_railings.value
|
|
self.fences = world.options.fences.value
|
|
self.feather = world.options.feather_item.value
|
|
self.box_respawning = world.options.shuffle_item_box_respawning.value
|
|
self.consistent = world.options.consistent_item_boxes.value
|
|
self.special_boxes = world.options.shuffle_special_item_boxes.value
|
|
self.clusters = world.options.shuffle_item_box_clusters.value
|
|
self.trap_percentage = world.options.filler_trap_percentage.value
|
|
self.min_filler = world.options.minimum_filler_items.value
|
|
self.fix_music = world.options.fix_results_music.value
|