Muse Dash: Add support for specifying specific DLCs (#2329)
This commit is contained in:
parent
fb6b66463d
commit
385803eb5c
|
@ -6,7 +6,7 @@ class SongData(NamedTuple):
|
|||
"""Special data container to contain the metadata of each song to make filtering work."""
|
||||
|
||||
code: Optional[int]
|
||||
song_is_free: bool
|
||||
album: str
|
||||
streamer_mode: bool
|
||||
easy: Optional[int]
|
||||
hard: Optional[int]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from .Items import SongData, AlbumData
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Dict, List, Set, Optional
|
||||
from collections import ChainMap
|
||||
|
||||
|
||||
|
@ -15,13 +15,21 @@ class MuseDashCollections:
|
|||
MUSIC_SHEET_NAME: str = "Music Sheet"
|
||||
MUSIC_SHEET_CODE: int = STARTING_CODE
|
||||
|
||||
FREE_ALBUMS = [
|
||||
FREE_ALBUMS: List[str] = [
|
||||
"Default Music",
|
||||
"Budget Is Burning: Nano Core",
|
||||
"Budget Is Burning Vol.1",
|
||||
]
|
||||
|
||||
DIFF_OVERRIDES = [
|
||||
MUSE_PLUS_DLC: str = "Muse Plus"
|
||||
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
|
||||
"MSR Anthology", # Part of Muse Plus. Goes away 20th Jan 2024.
|
||||
]
|
||||
|
||||
DIFF_OVERRIDES: List[str] = [
|
||||
"MuseDash ka nanika hi",
|
||||
"Rush-Hour",
|
||||
"Find this Month's Featured Playlist",
|
||||
|
@ -48,8 +56,8 @@ class MuseDashCollections:
|
|||
"Error SFX Trap": STARTING_CODE + 9,
|
||||
}
|
||||
|
||||
item_names_to_id = ChainMap({}, sfx_trap_items, vfx_trap_items)
|
||||
location_names_to_id = ChainMap(song_locations, album_locations)
|
||||
item_names_to_id: ChainMap = ChainMap({}, sfx_trap_items, vfx_trap_items)
|
||||
location_names_to_id: ChainMap = ChainMap(song_locations, album_locations)
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.item_names_to_id[self.MUSIC_SHEET_NAME] = self.MUSIC_SHEET_CODE
|
||||
|
@ -70,7 +78,6 @@ class MuseDashCollections:
|
|||
# Data is in the format 'Song|UID|Album|StreamerMode|EasyDiff|HardDiff|MasterDiff|SecretDiff'
|
||||
song_name = sections[0]
|
||||
# [1] is used in the client copy to make sure item id's match.
|
||||
song_is_free = album in self.FREE_ALBUMS
|
||||
steamer_mode = sections[3] == "True"
|
||||
|
||||
if song_name in self.DIFF_OVERRIDES:
|
||||
|
@ -84,7 +91,7 @@ class MuseDashCollections:
|
|||
diff_of_hard = self.parse_song_difficulty(sections[5])
|
||||
diff_of_master = self.parse_song_difficulty(sections[6])
|
||||
|
||||
self.song_items[song_name] = SongData(item_id_index, song_is_free, steamer_mode,
|
||||
self.song_items[song_name] = SongData(item_id_index, album, steamer_mode,
|
||||
diff_of_easy, diff_of_hard, diff_of_master)
|
||||
item_id_index += 1
|
||||
|
||||
|
@ -102,13 +109,13 @@ class MuseDashCollections:
|
|||
self.song_locations[f"{name}-1"] = location_id_index + 1
|
||||
location_id_index += 2
|
||||
|
||||
def get_songs_with_settings(self, dlc_songs: bool, streamer_mode_active: bool,
|
||||
def get_songs_with_settings(self, dlc_songs: Set[str], streamer_mode_active: bool,
|
||||
diff_lower: int, diff_higher: int) -> List[str]:
|
||||
"""Gets a list of all songs that match the filter settings. Difficulty thresholds are inclusive."""
|
||||
filtered_list = []
|
||||
|
||||
for songKey, songData in self.song_items.items():
|
||||
if not dlc_songs and not songData.song_is_free:
|
||||
if not self.song_matches_dlc_filter(songData, dlc_songs):
|
||||
continue
|
||||
|
||||
if streamer_mode_active and not songData.streamer_mode:
|
||||
|
@ -128,6 +135,19 @@ class MuseDashCollections:
|
|||
|
||||
return filtered_list
|
||||
|
||||
def song_matches_dlc_filter(self, song: SongData, dlc_songs: Set[str]) -> bool:
|
||||
if song.album in self.FREE_ALBUMS:
|
||||
return True
|
||||
|
||||
if song.album in dlc_songs:
|
||||
return True
|
||||
|
||||
# Muse Plus provides access to any DLC not included as a seperate pack
|
||||
if song.album not in self.DLC and self.MUSE_PLUS_DLC in dlc_songs:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def parse_song_difficulty(self, difficulty: str) -> Optional[int]:
|
||||
"""Attempts to parse the song difficulty."""
|
||||
if len(difficulty) <= 0 or difficulty == "?" or difficulty == "¿":
|
||||
|
|
|
@ -51,42 +51,42 @@ Mujinku-Vacuum|0-28|Default Music|False|5|7|11|
|
|||
MilK|0-36|Default Music|False|5|7|9|
|
||||
umpopoff|0-41|Default Music|False|0|?|0|
|
||||
Mopemope|0-45|Default Music|False|4|7|9|11
|
||||
The Happycore Idol|43-0|Just as Planned Plus|True|2|5|7|
|
||||
Amatsumikaboshi|43-1|Just as Planned Plus|True|4|6|8|10
|
||||
ARIGA THESIS|43-2|Just as Planned Plus|True|3|6|10|
|
||||
Night of Nights|43-3|Just as Planned Plus|False|4|7|10|
|
||||
#Psychedelic_Meguro_River|43-4|Just as Planned Plus|False|3|6|8|
|
||||
can you feel it|43-5|Just as Planned Plus|False|4|6|8|9
|
||||
Midnight O'clock|43-6|Just as Planned Plus|True|3|6|8|
|
||||
Rin|43-7|Just as Planned Plus|True|5|7|10|
|
||||
Smile-mileS|43-8|Just as Planned Plus|False|6|8|10|
|
||||
Believing and Being|43-9|Just as Planned Plus|True|4|6|9|
|
||||
Catalyst|43-10|Just as Planned Plus|False|5|7|9|
|
||||
don't!stop!eroero!|43-11|Just as Planned Plus|True|5|7|9|
|
||||
pa pi pu pi pu pi pa|43-12|Just as Planned Plus|False|6|8|10|
|
||||
Sand Maze|43-13|Just as Planned Plus|True|6|8|10|11
|
||||
Diffraction|43-14|Just as Planned Plus|True|5|8|10|
|
||||
AKUMU|43-15|Just as Planned Plus|False|4|6|8|
|
||||
Queen Aluett|43-16|Just as Planned Plus|True|7|9|11|
|
||||
DROPS|43-17|Just as Planned Plus|False|2|5|8|
|
||||
Frightfully-insane Flan-chan's frightful song|43-18|Just as Planned Plus|False|5|7|10|
|
||||
snooze|43-19|Just as Planned Plus|False|5|7|10|
|
||||
Kuishinbo Hacker feat.Kuishinbo Akachan|43-20|Just as Planned Plus|True|5|7|9|
|
||||
Inu no outa|43-21|Just as Planned Plus|True|3|5|7|
|
||||
Prism Fountain|43-22|Just as Planned Plus|True|7|9|11|
|
||||
Gospel|43-23|Just as Planned Plus|False|4|6|9|
|
||||
The Happycore Idol|43-0|MD Plus Project|True|2|5|7|
|
||||
Amatsumikaboshi|43-1|MD Plus Project|True|4|6|8|10
|
||||
ARIGA THESIS|43-2|MD Plus Project|True|3|6|10|
|
||||
Night of Nights|43-3|MD Plus Project|False|4|7|10|
|
||||
#Psychedelic_Meguro_River|43-4|MD Plus Project|False|3|6|8|
|
||||
can you feel it|43-5|MD Plus Project|False|4|6|8|9
|
||||
Midnight O'clock|43-6|MD Plus Project|True|3|6|8|
|
||||
Rin|43-7|MD Plus Project|True|5|7|10|
|
||||
Smile-mileS|43-8|MD Plus Project|False|6|8|10|
|
||||
Believing and Being|43-9|MD Plus Project|True|4|6|9|
|
||||
Catalyst|43-10|MD Plus Project|False|5|7|9|
|
||||
don't!stop!eroero!|43-11|MD Plus Project|True|5|7|9|
|
||||
pa pi pu pi pu pi pa|43-12|MD Plus Project|False|6|8|10|
|
||||
Sand Maze|43-13|MD Plus Project|True|6|8|10|11
|
||||
Diffraction|43-14|MD Plus Project|True|5|8|10|
|
||||
AKUMU|43-15|MD Plus Project|False|4|6|8|
|
||||
Queen Aluett|43-16|MD Plus Project|True|7|9|11|
|
||||
DROPS|43-17|MD Plus Project|False|2|5|8|
|
||||
Frightfully-insane Flan-chan's frightful song|43-18|MD Plus Project|False|5|7|10|
|
||||
snooze|43-19|MD Plus Project|False|5|7|10|
|
||||
Kuishinbo Hacker feat.Kuishinbo Akachan|43-20|MD Plus Project|True|5|7|9|
|
||||
Inu no outa|43-21|MD Plus Project|True|3|5|7|
|
||||
Prism Fountain|43-22|MD Plus Project|True|7|9|11|
|
||||
Gospel|43-23|MD Plus Project|False|4|6|9|
|
||||
East Ai Li Lovely|62-0|Happy Otaku Pack Vol.17|False|2|4|7|
|
||||
Mori Umi no Fune|62-1|Happy Otaku Pack Vol.17|True|5|7|9|
|
||||
Ooi|62-2|Happy Otaku Pack Vol.17|True|5|7|10|
|
||||
Numatta!!|62-3|Happy Otaku Pack Vol.17|True|5|7|9|
|
||||
SATELLITE|62-4|Happy Otaku Pack Vol.17|False|5|7|9|
|
||||
SATELLITE|62-4|Happy Otaku Pack Vol.17|False|5|7|9|10
|
||||
Fantasia Sonata Colorful feat. V!C|62-5|Happy Otaku Pack Vol.17|True|6|8|11|
|
||||
MuseDash ka nanika hi|61-0|Ola Dash|True|?|?|¿|
|
||||
Aleph-0|61-1|Ola Dash|True|7|9|11|
|
||||
Buttoba Supernova|61-2|Ola Dash|False|5|7|10|11
|
||||
Rush-Hour|61-3|Ola Dash|False|IG|Jh|a2|Eh
|
||||
3rd Avenue|61-4|Ola Dash|False|3|5|〇|
|
||||
WORLDINVADER|61-5|Ola Dash|True|5|8|10|
|
||||
WORLDINVADER|61-5|Ola Dash|True|5|8|10|11
|
||||
N3V3R G3T OV3R|60-0|maimai DX Limited-time Suite|True|4|7|10|
|
||||
Oshama Scramble!|60-1|maimai DX Limited-time Suite|True|5|7|10|
|
||||
Valsqotch|60-2|maimai DX Limited-time Suite|True|5|9|11|
|
||||
|
@ -450,13 +450,13 @@ Love Patrol|63-2|MUSE RADIO FM104|True|3|5|7|
|
|||
Mahorova|63-3|MUSE RADIO FM104|True|3|5|8|
|
||||
Yoru no machi|63-4|MUSE RADIO FM104|True|1|4|7|
|
||||
INTERNET YAMERO|63-5|MUSE RADIO FM104|True|6|8|10|
|
||||
Abracadabra|43-24|Just as Planned Plus|False|6|8|10|
|
||||
Squalldecimator feat. EZ-Ven|43-25|Just as Planned Plus|True|5|7|9|
|
||||
Amateras Rhythm|43-26|Just as Planned Plus|True|6|8|11|
|
||||
Record one's Dream|43-27|Just as Planned Plus|False|4|7|10|
|
||||
Lunatic|43-28|Just as Planned Plus|True|5|8|10|
|
||||
Jiumeng|43-29|Just as Planned Plus|True|3|6|8|
|
||||
The Day We Become Family|43-30|Just as Planned Plus|True|3|5|8|
|
||||
Abracadabra|43-24|MD Plus Project|False|6|8|10|
|
||||
Squalldecimator feat. EZ-Ven|43-25|MD Plus Project|True|5|7|9|
|
||||
Amateras Rhythm|43-26|MD Plus Project|True|6|8|11|
|
||||
Record one's Dream|43-27|MD Plus Project|False|4|7|10|
|
||||
Lunatic|43-28|MD Plus Project|True|5|8|10|
|
||||
Jiumeng|43-29|MD Plus Project|True|3|6|8|
|
||||
The Day We Become Family|43-30|MD Plus Project|True|3|5|8|
|
||||
Sutori ma FIRE!?!?|64-0|COSMIC RADIO PEROLIST|True|3|5|8|
|
||||
Tanuki Step|64-1|COSMIC RADIO PEROLIST|True|5|7|10|11
|
||||
Space Stationery|64-2|COSMIC RADIO PEROLIST|True|5|7|10|
|
||||
|
@ -469,3 +469,23 @@ BrainDance|65-0|Neon Abyss|True|3|6|9|
|
|||
My Focus!|65-1|NeonAbyss|True|5|7|10|
|
||||
ABABABA BURST|65-2|NeonAbyss|True|5|7|9|
|
||||
ULTRA HIGHER|65-3|NeonAbyss|True|4|7|10|
|
||||
Silver Bullet|43-31|MD Plus Project|True|5|7|10|
|
||||
Random|43-32|MD Plus Project|True|4|7|9|
|
||||
OTOGE-BOSS-KYOKU-CHAN|43-33|MD Plus Project|False|6|8|10|11
|
||||
Crow Rabbit|43-34|MD Plus Project|True|7|9|11|
|
||||
SyZyGy|43-35|MD Plus Project|True|6|8|10|11
|
||||
Mermaid Radio|43-36|MD Plus Project|True|3|5|7|
|
||||
Helixir|43-37|MD Plus Project|False|6|8|10|
|
||||
Highway Cruisin'|43-38|MD Plus Project|False|3|5|8|
|
||||
JACK PT BOSS|43-39|MD Plus Project|False|6|8|10|
|
||||
Time Capsule|43-40|MD Plus Project|False|7|9|11|
|
||||
39 Music!|66-0|Miku in Museland|False|3|5|8|
|
||||
Hand in Hand|66-1|Miku in Museland|False|1|3|6|
|
||||
Cynical Night Plan|66-2|Miku in Museland|False|4|6|8|
|
||||
God-ish|66-3|Miku in Museland|False|4|7|10|
|
||||
Darling Dance|66-4|Miku in Museland|False|4|7|9|
|
||||
Hatsune Creation Myth|66-5|Miku in Museland|False|6|8|10|
|
||||
The Vampire|66-6|Miku in Museland|False|4|6|9|
|
||||
Future Eve|66-7|Miku in Museland|False|4|8|11|
|
||||
Unknown Mother Goose|66-8|Miku in Museland|False|4|8|10|
|
||||
Shun-ran|66-9|Miku in Museland|False|4|7|9|
|
|
@ -1,10 +1,19 @@
|
|||
from typing import Dict
|
||||
from Options import Toggle, Option, Range, Choice, DeathLink, ItemSet
|
||||
from Options import Toggle, Option, Range, Choice, DeathLink, ItemSet, OptionSet, PerGameCommonOptions
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .MuseDashCollection import MuseDashCollections
|
||||
|
||||
class AllowJustAsPlannedDLCSongs(Toggle):
|
||||
"""Whether [Just as Planned]/[Muse Plus] DLC Songs, and all the DLCs along with it, will be included in the randomizer."""
|
||||
display_name = "Allow [Just as Planned]/[Muse Plus] DLC Songs"
|
||||
"""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."""
|
||||
display_name = "DLC Packs"
|
||||
default = {}
|
||||
valid_keys = [dlc for dlc in MuseDashCollections.DLC]
|
||||
|
||||
|
||||
class StreamerModeEnabled(Toggle):
|
||||
|
@ -159,21 +168,22 @@ class ExcludeSongs(ItemSet):
|
|||
display_name = "Exclude Songs"
|
||||
|
||||
|
||||
musedash_options: Dict[str, type(Option)] = {
|
||||
"allow_just_as_planned_dlc_songs": AllowJustAsPlannedDLCSongs,
|
||||
"streamer_mode_enabled": StreamerModeEnabled,
|
||||
"starting_song_count": StartingSongs,
|
||||
"additional_song_count": AdditionalSongs,
|
||||
"additional_item_percentage": AdditionalItemPercentage,
|
||||
"song_difficulty_mode": DifficultyMode,
|
||||
"song_difficulty_min": DifficultyModeOverrideMin,
|
||||
"song_difficulty_max": DifficultyModeOverrideMax,
|
||||
"grade_needed": GradeNeeded,
|
||||
"music_sheet_count_percentage": MusicSheetCountPercentage,
|
||||
"music_sheet_win_count_percentage": MusicSheetWinCountPercentage,
|
||||
"available_trap_types": TrapTypes,
|
||||
"trap_count_percentage": TrapCountPercentage,
|
||||
"death_link": DeathLink,
|
||||
"include_songs": IncludeSongs,
|
||||
"exclude_songs": ExcludeSongs
|
||||
}
|
||||
@dataclass
|
||||
class MuseDashOptions(PerGameCommonOptions):
|
||||
allow_just_as_planned_dlc_songs: AllowJustAsPlannedDLCSongs
|
||||
dlc_packs: DLCMusicPacks
|
||||
streamer_mode_enabled: StreamerModeEnabled
|
||||
starting_song_count: StartingSongs
|
||||
additional_song_count: AdditionalSongs
|
||||
additional_item_percentage: AdditionalItemPercentage
|
||||
song_difficulty_mode: DifficultyMode
|
||||
song_difficulty_min: DifficultyModeOverrideMin
|
||||
song_difficulty_max: DifficultyModeOverrideMax
|
||||
grade_needed: GradeNeeded
|
||||
music_sheet_count_percentage: MusicSheetCountPercentage
|
||||
music_sheet_win_count_percentage: MusicSheetWinCountPercentage
|
||||
available_trap_types: TrapTypes
|
||||
trap_count_percentage: TrapCountPercentage
|
||||
death_link: DeathLink
|
||||
include_songs: IncludeSongs
|
||||
exclude_songs: ExcludeSongs
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from worlds.AutoWorld import World, WebWorld
|
||||
from worlds.generic.Rules import set_rule
|
||||
from BaseClasses import Region, Item, ItemClassification, Entrance, Tutorial
|
||||
from typing import List
|
||||
from typing import List, ClassVar, Type
|
||||
from math import floor
|
||||
from Options import PerGameCommonOptions
|
||||
|
||||
from .Options import musedash_options
|
||||
from .Options import MuseDashOptions
|
||||
from .Items import MuseDashSongItem, MuseDashFixedItem
|
||||
from .Locations import MuseDashLocation
|
||||
from .MuseDashCollection import MuseDashCollections
|
||||
|
@ -47,9 +47,9 @@ class MuseDashWorld(World):
|
|||
|
||||
# World Options
|
||||
game = "Muse Dash"
|
||||
option_definitions = musedash_options
|
||||
options_dataclass: ClassVar[Type[PerGameCommonOptions]] = MuseDashOptions
|
||||
topology_present = False
|
||||
data_version = 9
|
||||
data_version = 10
|
||||
web = MuseDashWebWorld()
|
||||
|
||||
# Necessary Data
|
||||
|
@ -66,14 +66,17 @@ class MuseDashWorld(World):
|
|||
location_count: int
|
||||
|
||||
def generate_early(self):
|
||||
dlc_songs = self.multiworld.allow_just_as_planned_dlc_songs[self.player]
|
||||
streamer_mode = self.multiworld.streamer_mode_enabled[self.player]
|
||||
dlc_songs = {key for key in self.options.dlc_packs.value}
|
||||
if (self.options.allow_just_as_planned_dlc_songs.value):
|
||||
dlc_songs.add(self.md_collection.MUSE_PLUS_DLC)
|
||||
|
||||
streamer_mode = self.options.streamer_mode_enabled
|
||||
(lower_diff_threshold, higher_diff_threshold) = self.get_difficulty_range()
|
||||
|
||||
# The minimum amount of songs to make an ok rando would be Starting Songs + 10 interim songs + Goal song.
|
||||
# - Interim songs being equal to max starting song count.
|
||||
# Note: The worst settings still allow 25 songs (Streamer Mode + No DLC).
|
||||
starter_song_count = self.multiworld.starting_song_count[self.player].value
|
||||
starter_song_count = self.options.starting_song_count.value
|
||||
|
||||
while True:
|
||||
# In most cases this should only need to run once
|
||||
|
@ -104,9 +107,9 @@ class MuseDashWorld(World):
|
|||
def handle_plando(self, available_song_keys: List[str]) -> List[str]:
|
||||
song_items = self.md_collection.song_items
|
||||
|
||||
start_items = self.multiworld.start_inventory[self.player].value.keys()
|
||||
include_songs = self.multiworld.include_songs[self.player].value
|
||||
exclude_songs = self.multiworld.exclude_songs[self.player].value
|
||||
start_items = self.options.start_inventory.value.keys()
|
||||
include_songs = self.options.include_songs.value
|
||||
exclude_songs = self.options.exclude_songs.value
|
||||
|
||||
self.starting_songs = [s for s in start_items if s in song_items]
|
||||
self.included_songs = [s for s in include_songs if s in song_items and s not in self.starting_songs]
|
||||
|
@ -115,8 +118,8 @@ class MuseDashWorld(World):
|
|||
and s not in include_songs and s not in exclude_songs]
|
||||
|
||||
def create_song_pool(self, available_song_keys: List[str]):
|
||||
starting_song_count = self.multiworld.starting_song_count[self.player].value
|
||||
additional_song_count = self.multiworld.additional_song_count[self.player].value
|
||||
starting_song_count = self.options.starting_song_count.value
|
||||
additional_song_count = self.options.additional_song_count.value
|
||||
|
||||
self.random.shuffle(available_song_keys)
|
||||
|
||||
|
@ -150,7 +153,7 @@ class MuseDashWorld(World):
|
|||
|
||||
# Then attempt to fufill any remaining songs for interim songs
|
||||
if len(self.included_songs) < additional_song_count:
|
||||
for _ in range(len(self.included_songs), self.multiworld.additional_song_count[self.player]):
|
||||
for _ in range(len(self.included_songs), self.options.additional_song_count):
|
||||
if len(available_song_keys) <= 0:
|
||||
break
|
||||
self.included_songs.append(available_song_keys.pop())
|
||||
|
@ -258,40 +261,40 @@ class MuseDashWorld(World):
|
|||
state.has(self.md_collection.MUSIC_SHEET_NAME, self.player, self.get_music_sheet_win_count())
|
||||
|
||||
def get_available_traps(self) -> List[str]:
|
||||
dlc_songs = self.multiworld.allow_just_as_planned_dlc_songs[self.player]
|
||||
sfx_traps_available = self.options.allow_just_as_planned_dlc_songs.value
|
||||
|
||||
trap_list = []
|
||||
if self.multiworld.available_trap_types[self.player].value & 1 != 0:
|
||||
if self.options.available_trap_types.value & 1 != 0:
|
||||
trap_list += self.md_collection.vfx_trap_items.keys()
|
||||
|
||||
# SFX options are only available under Just as Planned DLC.
|
||||
if dlc_songs and self.multiworld.available_trap_types[self.player].value & 2 != 0:
|
||||
if sfx_traps_available and self.options.available_trap_types.value & 2 != 0:
|
||||
trap_list += self.md_collection.sfx_trap_items.keys()
|
||||
|
||||
return trap_list
|
||||
|
||||
def get_additional_item_percentage(self) -> int:
|
||||
trap_count = self.multiworld.trap_count_percentage[self.player].value
|
||||
song_count = self.multiworld.music_sheet_count_percentage[self.player].value
|
||||
return max(trap_count + song_count, self.multiworld.additional_item_percentage[self.player].value)
|
||||
trap_count = self.options.trap_count_percentage.value
|
||||
song_count = self.options.music_sheet_count_percentage.value
|
||||
return max(trap_count + song_count, self.options.additional_item_percentage.value)
|
||||
|
||||
def get_trap_count(self) -> int:
|
||||
multiplier = self.multiworld.trap_count_percentage[self.player].value / 100.0
|
||||
multiplier = self.options.trap_count_percentage.value / 100.0
|
||||
trap_count = (len(self.starting_songs) * 2) + len(self.included_songs)
|
||||
return max(0, floor(trap_count * multiplier))
|
||||
|
||||
def get_music_sheet_count(self) -> int:
|
||||
multiplier = self.multiworld.music_sheet_count_percentage[self.player].value / 100.0
|
||||
multiplier = self.options.music_sheet_count_percentage.value / 100.0
|
||||
song_count = (len(self.starting_songs) * 2) + len(self.included_songs)
|
||||
return max(1, floor(song_count * multiplier))
|
||||
|
||||
def get_music_sheet_win_count(self) -> int:
|
||||
multiplier = self.multiworld.music_sheet_win_count_percentage[self.player].value / 100.0
|
||||
multiplier = self.options.music_sheet_win_count_percentage.value / 100.0
|
||||
sheet_count = self.get_music_sheet_count()
|
||||
return max(1, floor(sheet_count * multiplier))
|
||||
|
||||
def get_difficulty_range(self) -> List[int]:
|
||||
difficulty_mode = self.multiworld.song_difficulty_mode[self.player]
|
||||
difficulty_mode = self.options.song_difficulty_mode
|
||||
|
||||
# Valid difficulties are between 1 and 11. But make it 0 to 12 for safety
|
||||
difficulty_bounds = [0, 12]
|
||||
|
@ -309,8 +312,8 @@ class MuseDashWorld(World):
|
|||
elif difficulty_mode == 5:
|
||||
difficulty_bounds[0] = 10
|
||||
elif difficulty_mode == 6:
|
||||
minimum_difficulty = self.multiworld.song_difficulty_min[self.player].value
|
||||
maximum_difficulty = self.multiworld.song_difficulty_max[self.player].value
|
||||
minimum_difficulty = self.options.song_difficulty_min.value
|
||||
maximum_difficulty = self.options.song_difficulty_max.value
|
||||
|
||||
difficulty_bounds[0] = min(minimum_difficulty, maximum_difficulty)
|
||||
difficulty_bounds[1] = max(minimum_difficulty, maximum_difficulty)
|
||||
|
@ -320,7 +323,7 @@ class MuseDashWorld(World):
|
|||
def fill_slot_data(self):
|
||||
return {
|
||||
"victoryLocation": self.victory_song_name,
|
||||
"deathLink": self.multiworld.death_link[self.player].value,
|
||||
"deathLink": self.options.death_link.value,
|
||||
"musicSheetWinCount": self.get_music_sheet_win_count(),
|
||||
"gradeNeeded": self.multiworld.grade_needed[self.player].value
|
||||
"gradeNeeded": self.options.grade_needed.value
|
||||
}
|
||||
|
|
|
@ -36,14 +36,27 @@ class CollectionsTest(unittest.TestCase):
|
|||
|
||||
def test_free_dlc_included_in_base_songs(self) -> None:
|
||||
collection = MuseDashCollections()
|
||||
songs = collection.get_songs_with_settings(False, False, 0, 11)
|
||||
songs = collection.get_songs_with_settings(set(), False, 0, 12)
|
||||
|
||||
self.assertIn("Glimmer", songs, "Budget Is Burning Vol.1 is not being included in base songs")
|
||||
self.assertIn("Out of Sense", songs, "Budget Is Burning: Nano Core is not being included in base songs")
|
||||
|
||||
def test_dlcs(self) -> None:
|
||||
collection = MuseDashCollections()
|
||||
free_song_count = len(collection.get_songs_with_settings(set(), False, 0, 12))
|
||||
known_mp_song = "The Happycore Idol"
|
||||
|
||||
for dlc in collection.DLC:
|
||||
songs_with_dlc = collection.get_songs_with_settings({dlc}, False, 0, 12)
|
||||
self.assertGreater(len(songs_with_dlc), free_song_count, f"DLC {dlc} did not include extra songs.")
|
||||
if dlc == collection.MUSE_PLUS_DLC:
|
||||
self.assertIn(known_mp_song, songs_with_dlc, f"Muse Plus missing muse plus song.")
|
||||
else:
|
||||
self.assertNotIn(known_mp_song, songs_with_dlc, f"DLC {dlc} includes Muse Plus songs.")
|
||||
|
||||
def test_remove_songs_are_not_generated(self) -> None:
|
||||
collection = MuseDashCollections()
|
||||
songs = collection.get_songs_with_settings(True, False, 0, 11)
|
||||
songs = collection.get_songs_with_settings({x for x in collection.DLC}, False, 0, 12)
|
||||
|
||||
for song_name in self.REMOVED_SONGS:
|
||||
self.assertNotIn(song_name, songs, f"Song '{song_name}' wasn't removed correctly.")
|
||||
|
|
|
@ -4,6 +4,7 @@ from . import MuseDashTestBase
|
|||
class DifficultyRanges(MuseDashTestBase):
|
||||
def test_all_difficulty_ranges(self) -> None:
|
||||
muse_dash_world = self.multiworld.worlds[1]
|
||||
dlc_set = {x for x in muse_dash_world.md_collection.DLC}
|
||||
difficulty_choice = self.multiworld.song_difficulty_mode[1]
|
||||
difficulty_min = self.multiworld.song_difficulty_min[1]
|
||||
difficulty_max = self.multiworld.song_difficulty_max[1]
|
||||
|
@ -12,7 +13,7 @@ class DifficultyRanges(MuseDashTestBase):
|
|||
self.assertEqual(inputRange[0], lower)
|
||||
self.assertEqual(inputRange[1], upper)
|
||||
|
||||
songs = muse_dash_world.md_collection.get_songs_with_settings(True, False, inputRange[0], inputRange[1])
|
||||
songs = muse_dash_world.md_collection.get_songs_with_settings(dlc_set, False, inputRange[0], inputRange[1])
|
||||
for songKey in songs:
|
||||
song = muse_dash_world.md_collection.song_items[songKey]
|
||||
if (song.easy is not None and inputRange[0] <= song.easy <= inputRange[1]):
|
||||
|
|
Loading…
Reference in New Issue