Skip to content

Commit

Permalink
Muse Dash: Option Groups and Options Rework (ArchipelagoMW#3434)
Browse files Browse the repository at this point in the history
* Ensure that included/starter songs only include those within enabled dlcs.

* Allow filtering traps by trap instead of by category.

* Add in the currently available limited time dlcs to the dlc list.

* Add the option group to the webhost and cleanup some errors.

* Fix trap list.

* Update tests. Add new ones to test correctness of new features.

* Remove the old Just As Planned option

* Make traps order alphabetically. Also adjust the title for traps.

* Adjust new lines to better fit the website.

* Style fixes.

* Test adjustments and a fix due to test no longer having just as planned dlc.

* Undo spacing changes as it breaks yaml generation.

* Fix indenting in webhost.

* Add the old options in as removed. Also clean up unused import.

* Remove references to the old allow_just_as_planned_dlc_songs option in Muse Dash tests.

* Add newline to end of file.

---------

Co-authored-by: NewSoupVi <[email protected]>
  • Loading branch information
2 people authored and agilbert1412 committed Jun 13, 2024
1 parent 0decf50 commit 3dc93d8
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 104 deletions.
30 changes: 19 additions & 11 deletions worlds/musedash/MuseDashCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ class MuseDashCollections:
]

MUSE_PLUS_DLC: str = "Muse Plus"

# Ordering matters for webhost. Order goes: Muse Plus, Time Limited Muse Plus Dlcs, Paid Dlcs
DLC: List[str] = [
# MUSE_PLUS_DLC, # To be included when OptionSets are rendered as part of basic settings.
# "maimai DX Limited-time Suite", # Part of Muse Plus. Goes away 31st Jan 2026.
"Miku in Museland", # Paid DLC not included in Muse Plus
"Rin Len's Mirrorland", # Paid DLC not included in Muse Plus
"MSR Anthology", # Now no longer available.
MUSE_PLUS_DLC,
"CHUNITHM COURSE MUSE", # Part of Muse Plus. Goes away 22nd May 2027.
"maimai DX Limited-time Suite", # Part of Muse Plus. Goes away 31st Jan 2026.
"MSR Anthology", # Now no longer available.
"Miku in Museland", # Paid DLC not included in Muse Plus
"Rin Len's Mirrorland", # Paid DLC not included in Muse Plus
]

DIFF_OVERRIDES: List[str] = [
Expand All @@ -50,22 +53,24 @@ class MuseDashCollections:
song_items: Dict[str, SongData] = {}
song_locations: Dict[str, int] = {}

vfx_trap_items: Dict[str, int] = {
trap_items: Dict[str, int] = {
"Bad Apple Trap": STARTING_CODE + 1,
"Pixelate Trap": STARTING_CODE + 2,
"Ripple Trap": STARTING_CODE + 3,
"Vignette Trap": STARTING_CODE + 4,
"Chromatic Aberration Trap": STARTING_CODE + 5,
"Background Freeze Trap": STARTING_CODE + 6,
"Gray Scale Trap": STARTING_CODE + 7,
"Focus Line Trap": STARTING_CODE + 10,
}

sfx_trap_items: Dict[str, int] = {
"Nyaa SFX Trap": STARTING_CODE + 8,
"Error SFX Trap": STARTING_CODE + 9,
"Focus Line Trap": STARTING_CODE + 10,
}

sfx_trap_items: List[str] = [
"Nyaa SFX Trap",
"Error SFX Trap",
]

filler_items: Dict[str, int] = {
"Great To Perfect (10 Pack)": STARTING_CODE + 30,
"Miss To Great (5 Pack)": STARTING_CODE + 31,
Expand All @@ -78,7 +83,7 @@ class MuseDashCollections:
"Extra Life": 1,
}

item_names_to_id: ChainMap = ChainMap({}, filler_items, sfx_trap_items, vfx_trap_items)
item_names_to_id: ChainMap = ChainMap({}, filler_items, trap_items)
location_names_to_id: ChainMap = ChainMap(song_locations, album_locations)

def __init__(self) -> None:
Expand Down Expand Up @@ -171,6 +176,9 @@ def get_songs_with_settings(self, dlc_songs: Set[str], streamer_mode_active: boo

return filtered_list

def filter_songs_to_dlc(self, song_list: List[str], dlc_songs: Set[str]) -> List[str]:
return [song for song in song_list if self.song_matches_dlc_filter(self.song_items[song], dlc_songs)]

def song_matches_dlc_filter(self, song: SongData, dlc_songs: Set[str]) -> bool:
if song.album in self.FREE_ALBUMS:
return True
Expand Down
109 changes: 74 additions & 35 deletions worlds/musedash/Options.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
from typing import Dict
from Options import Toggle, Option, Range, Choice, DeathLink, ItemSet, OptionSet, PerGameCommonOptions
from Options import Toggle, Range, Choice, DeathLink, ItemSet, OptionSet, PerGameCommonOptions, OptionGroup, Removed
from dataclasses import dataclass

from .MuseDashCollection import MuseDashCollections


class AllowJustAsPlannedDLCSongs(Toggle):
"""Whether [Muse Plus] DLC Songs, and all the albums included in it, can be chosen as randomised songs.
Note: The [Just As Planned] DLC contains all [Muse Plus] songs."""
display_name = "Allow [Muse Plus] DLC Songs"


class DLCMusicPacks(OptionSet):
"""Which non-[Muse Plus] DLC packs can be chosen as randomised songs."""
"""
Choose which DLC Packs will be included in the pool of chooseable songs.
Note: The [Just As Planned] DLC contains all [Muse Plus] songs.
"""
display_name = "DLC Packs"
default = {}
valid_keys = [dlc for dlc in MuseDashCollections.DLC]


class StreamerModeEnabled(Toggle):
"""In Muse Dash, an option named 'Streamer Mode' removes songs which may trigger copyright issues when streaming.
If this is enabled, only songs available under Streamer Mode will be available for randomization."""
"""
In Muse Dash, an option named 'Streamer Mode' removes songs which may trigger copyright issues when streaming.
If this is enabled, only songs available under Streamer Mode will be available for randomization.
"""
display_name = "Streamer Mode Only Songs"


Expand All @@ -33,7 +33,8 @@ class StartingSongs(Range):


class AdditionalSongs(Range):
"""The total number of songs that will be placed in the randomization pool.
"""
The total number of songs that will be placed in the randomization pool.
- This does not count any starting songs or the goal song.
- The final song count may be lower due to other settings.
"""
Expand All @@ -44,7 +45,8 @@ class AdditionalSongs(Range):


class DifficultyMode(Choice):
"""Ensures that at any chosen song has at least 1 value falling within these values.
"""
Ensures that at any chosen song has at least 1 value falling within these values.
- Any: All songs are available
- Easy: 1, 2 or 3
- Medium: 4, 5
Expand All @@ -66,8 +68,11 @@ class DifficultyMode(Choice):

# Todo: Investigate options to make this non randomizable
class DifficultyModeOverrideMin(Range):
"""Ensures that 1 difficulty has at least 1 this value or higher per song.
- Difficulty Mode must be set to Manual."""
"""
Ensures that 1 difficulty has at least 1 this value or higher per song.
Note: Difficulty Mode must be set to Manual.
"""
display_name = "Manual Difficulty Min"
range_start = 1
range_end = 11
Expand All @@ -76,16 +81,20 @@ class DifficultyModeOverrideMin(Range):

# Todo: Investigate options to make this non randomizable
class DifficultyModeOverrideMax(Range):
"""Ensures that 1 difficulty has at least 1 this value or lower per song.
- Difficulty Mode must be set to Manual."""
"""
Ensures that 1 difficulty has at least 1 this value or lower per song.
Note: Difficulty Mode must be set to Manual.
"""
display_name = "Manual Difficulty Max"
range_start = 1
range_end = 11
default = 8


class GradeNeeded(Choice):
"""Completing a song will require a grade of this value or higher in order to unlock items.
"""
Completing a song will require a grade of this value or higher in order to unlock items.
The grades are as follows:
- Silver S (SS): >= 95% accuracy
- Pink S (S): >= 90% accuracy
Expand All @@ -104,7 +113,9 @@ class GradeNeeded(Choice):


class MusicSheetCountPercentage(Range):
"""Controls how many music sheets are added to the pool based on the number of songs, including starting songs.
"""
Controls how many music sheets are added to the pool based on the number of songs, including starting songs.
Higher numbers leads to more consistent game lengths, but will cause individual music sheets to be less important.
"""
range_start = 10
Expand All @@ -121,19 +132,18 @@ class MusicSheetWinCountPercentage(Range):
display_name = "Music Sheets Needed to Win"


class TrapTypes(Choice):
"""This controls the types of traps that can be added to the pool.
class ChosenTraps(OptionSet):
"""
This controls the types of traps that can be added to the pool.
- Traps last the length of a song, or until you die.
- VFX Traps consist of visual effects that play over the song. (i.e. Grayscale.)
- SFX Traps consist of changing your sfx setting to one possibly more annoying sfx.
Traps last the length of a song, or until you die.
Note: SFX traps are only available if [Just as Planned] DLC songs are enabled.
"""
display_name = "Available Trap Types"
option_None = 0
option_VFX = 1
option_SFX = 2
option_All = 3
default = 3
display_name = "Chosen Traps"
default = {}
valid_keys = {trap for trap in MuseDashCollections.trap_items.keys()}


class TrapCountPercentage(Range):
Expand All @@ -145,24 +155,49 @@ class TrapCountPercentage(Range):


class IncludeSongs(ItemSet):
"""Any song listed here will be guaranteed to be included as part of the seed.
- Difficulty options will be skipped for these songs.
- If there being too many included songs, songs will be randomly chosen without regard for difficulty.
- If you want these songs immediately, use start_inventory instead.
"""
These songs will be guaranteed to show up within the seed.
- You must have the DLC enabled to play these songs.
- Difficulty options will not affect these songs.
- If there are too many included songs, this will act as a whitelist ignoring song difficulty.
"""
verify_item_name = True
display_name = "Include Songs"


class ExcludeSongs(ItemSet):
"""Any song listed here will be excluded from being a part of the seed."""
"""
These songs will be guaranteed to not show up within the seed.
Note: Does not affect songs within the "Include Songs" list.
"""
verify_item_name = True
display_name = "Exclude Songs"


md_option_groups = [
OptionGroup("Song Choice", [
DLCMusicPacks,
StreamerModeEnabled,
IncludeSongs,
ExcludeSongs,
]),
OptionGroup("Difficulty", [
GradeNeeded,
DifficultyMode,
DifficultyModeOverrideMin,
DifficultyModeOverrideMax,
DeathLink,
]),
OptionGroup("Traps", [
ChosenTraps,
TrapCountPercentage,
]),
]


@dataclass
class MuseDashOptions(PerGameCommonOptions):
allow_just_as_planned_dlc_songs: AllowJustAsPlannedDLCSongs
dlc_packs: DLCMusicPacks
streamer_mode_enabled: StreamerModeEnabled
starting_song_count: StartingSongs
Expand All @@ -173,8 +208,12 @@ class MuseDashOptions(PerGameCommonOptions):
grade_needed: GradeNeeded
music_sheet_count_percentage: MusicSheetCountPercentage
music_sheet_win_count_percentage: MusicSheetWinCountPercentage
available_trap_types: TrapTypes
chosen_traps: ChosenTraps
trap_count_percentage: TrapCountPercentage
death_link: DeathLink
include_songs: IncludeSongs
exclude_songs: ExcludeSongs

# Removed
allow_just_as_planned_dlc_songs: Removed
available_trap_types: Removed
6 changes: 3 additions & 3 deletions worlds/musedash/Presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
MuseDashPresets: Dict[str, Dict[str, Any]] = {
# An option to support Short Sync games. 40 songs.
"No DLC - Short": {
"allow_just_as_planned_dlc_songs": False,
"dlc_packs": [],
"starting_song_count": 5,
"additional_song_count": 34,
"music_sheet_count_percentage": 20,
"music_sheet_win_count_percentage": 90,
},
# An option to support Short Sync games but adds variety. 40 songs.
"DLC - Short": {
"allow_just_as_planned_dlc_songs": True,
"dlc_packs": ["Muse Plus"],
"starting_song_count": 5,
"additional_song_count": 34,
"music_sheet_count_percentage": 20,
"music_sheet_win_count_percentage": 90,
},
# An option to support Longer Sync/Async games. 100 songs.
"DLC - Long": {
"allow_just_as_planned_dlc_songs": True,
"dlc_packs": ["Muse Plus"],
"starting_song_count": 8,
"additional_song_count": 91,
"music_sheet_count_percentage": 20,
Expand Down
Loading

0 comments on commit 3dc93d8

Please sign in to comment.