Skip to content

Commit

Permalink
Muse Dash: Add New Game (#1723)
Browse files Browse the repository at this point in the history
* Alpha 1 Muse dash stuff.

* Add in an option to limit to only base game songs.

* Make all items progression instead of progression_skip_balancing.

* Add in extra_goal_song_items to help make runs less about completing every song.

* Change ID range to be in a more open area, and add some comments.

* Add in Streamer Mode and difficulty range options. Rearrange data files so its easier to get all data at once.

* Fix generation issues.

* Fix up the maximum and remove old option.

* Remove empty items and the option to make filler songs empty.

* Support emerald hunt mode. Make difficulties an option rather than 2 sliders.

* Fix DLC Song option being inverted.

* Fix item counting being broken if there was more than 1 world.

* Make compatible with .apworld specification.

* Make All item names ASCII compatible.

* Add in the additional_item_percentage option.

* Add a test to ensure the item names are within the normal ascii range.

* Add in death link.

* Remove the album from the item name. Not really needed anymore.

* Add the 2 budget is burning albums under the free songs heading. Adds a couple more songs without dlc.

* Sanitise Album names.

* Added the grade needed choice.

* Update songs to v3.1.0

* Adjust difficulty ranges. Add Expert and Master.

* Fix setup_en.md being out of date.

* Add a manual override.

* Add testing for diff ranges. Fix bugs introduced there. Limit option to 11 to not generate an impossible seed.

* Remove regions from Muse Dash.

* Some Oops...

* Attempt to make tests happy.

* Remove supports weighting false to stop webhost test failing.

* Adjusted settings

* Adjust music sheets to use percentages. Various cleanups.

* Fixes to new code.

* Add Ola Dash Album. Add support for overriding song difficulty. Other stylisation changes.

* Attempt fix tests.

* Ooops missed one.

* flake8 suggestions.

* Remove FM 17314 SUGAR RADIO as that song is a bit weird.

* Update document pages.

* Add trap support

* Lower additional song count by 10.

* Tests broke on my end. Using github to test this.

* Looks like I was accidentally adding ~.

* Fix the one song that crashes OoT hint generation

* Various documentation changes.

* Website documents fixup.

* Doc updates part 2.

* Oops. Doc updates part 3.

* Add Muse Dash to the apworld list.

* Add trailing comma.

* Add a couple plando options.

* Set data_version to 1.

* Add in some handling incase someone decides a song is both starter and included.

* Remove brackets around ifs.

* Oops. Accidentally removed a necessary bracket.

* Fix filtering crash due to me mixing up c# and python .remove().

* Add Happy Otaku Pack Vol.17. Also increment data version.

* Update links to melon loader to be the latest.

* Clean up song selection code by shuffling once then popping.

* Add UID to the Data text file, so the same file can be used client and server.

* Increment Data Version because some names have changed.

* Correct some names.

* Update data to v3.4.0 (Addition of Muse Radio FM104)

* Add support for SFX traps. Adjusted how traps were setup a bit.

* Update the docs to include a troubleshooting section.

* Small fixes.

* Remove unnecessary brackets.

* Add .net downloads to docs.

* Avoid failing generation if strict difficulty settings are applied with no dlc songs and streamer mode.

* Forgot to add the worst starting song count.

* Make minimum song count be Starting Songs + 11 instead of Starting Songs * 2 + 1.

* Fix up several issues where song count could mismatch the requested amount.

* Add a test to ensure world size doesn't grow.

* Fix some oversights.

* Remove unnecessary brackets.

* Fix up passing the tuple out when just the key would suffice.

* Adjust typing based on Phar's suggestions.

* Apply the rest of Phar's suggestions with minor tweaks to other parts to suit suggestions.

* Adjust some more stuff to fit 120 characters.

* Some more pep8 stuff and fix tests.

* Some pep8 in tests.
  • Loading branch information
DeamonHunter authored Jun 29, 2023
1 parent 3fba94f commit 77b0852
Show file tree
Hide file tree
Showing 13 changed files with 1,382 additions and 0 deletions.
34 changes: 34 additions & 0 deletions worlds/musedash/Items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from typing import NamedTuple, Optional, Union
from BaseClasses import Item, ItemClassification


class SongData(NamedTuple):
"""Special data container to contain the metadata of each song to make filtering work."""

code: Optional[int]
song_is_free: bool
streamer_mode: bool
easy: str = Optional[int]
hard: int = Optional[int]
master: int = Optional[int]
secret: int = Optional[int]


class AlbumData(NamedTuple):
"""Special data container to contain the metadata of each album to make filtering work. Currently not used."""

code: Optional[int]


class MuseDashSongItem(Item):
game: str = "Muse Dash"

def __init__(self, name: str, player: int, data: Union[SongData, AlbumData]) -> None:
super().__init__(name, ItemClassification.progression, data.code, player)


class MuseDashFixedItem(Item):
game: str = "Muse Dash"

def __init__(self, name: str, classification: ItemClassification, code: Optional[int], player: int) -> None:
super().__init__(name, classification, code, player)
5 changes: 5 additions & 0 deletions worlds/musedash/Locations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from BaseClasses import Location


class MuseDashLocation(Location):
game: str = "Muse Dash"
136 changes: 136 additions & 0 deletions worlds/musedash/MuseDashCollection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
from .Items import SongData, AlbumData
from typing import Dict, List, Optional


def load_text_file(name: str) -> str:
import pkgutil
return pkgutil.get_data(__name__, name).decode()


class MuseDashCollections:
"""Contains all the data of Muse Dash, loaded from MuseDashData.txt."""

MUSIC_SHEET_CODE: int

FREE_ALBUMS = [
"Default Music",
"Budget Is Burning: Nano Core",
"Budget is Burning Vol.1"
]

DIFF_OVERRIDES = [
"MuseDash ka nanika hi",
"Rush-Hour",
"Find this Month's Featured Playlist",
"PeroPero in the Universe",
"CHAOS Glitch"
]

album_items: Dict[str, AlbumData] = {}
album_locations: Dict[str, int] = {}
song_items: Dict[str, SongData] = {}
song_locations: Dict[str, int] = {}

vfx_trap_items: Dict[str, int] = {
"Bad Apple Trap": 1,
"Pixelate Trap": 2,
"Random Wave Trap": 3,
"Shadow Edge Trap": 4,
"Chromatic Aberration Trap": 5,
"Background Freeze Trap": 6,
"Gray Scale Trap": 7,
}

sfx_trap_items: Dict[str, int] = {
"Nyaa SFX Trap": 8,
"Error SFX Trap": 9,
}

def __init__(self, start_item_id: int, items_per_location: int):
self.MUSIC_SHEET_CODE = start_item_id

self.vfx_trap_items = {k: (v + start_item_id) for (k, v) in self.vfx_trap_items.items()}
self.sfx_trap_items = {k: (v + start_item_id) for (k, v) in self.sfx_trap_items.items()}

item_id_index = start_item_id + 50
location_id_index = start_item_id

full_file = load_text_file("MuseDashData.txt")

for line in full_file.splitlines():
line = line.strip()
sections = line.split("|")

if sections[2] not in self.album_items:
self.album_items[sections[2]] = AlbumData(item_id_index)
item_id_index += 1

# 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 = sections[2] in self.FREE_ALBUMS
steamer_mode = sections[3] == "True"

if song_name in self.DIFF_OVERRIDES:
# Note: These difficulties may not actually be representative of these songs.
# The game does not provide these difficulties so they have to be filled in.
diff_of_easy = 4
diff_of_hard = 7
diff_of_master = 10
else:
diff_of_easy = self.parse_song_difficulty(sections[4])
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,
diff_of_easy, diff_of_hard, diff_of_master)
item_id_index += 1

for name in self.album_items.keys():
for i in range(0, items_per_location):
new_name = f"{name}-{i}"
self.album_locations[new_name] = location_id_index
location_id_index += 1

for name in self.song_items.keys():
for i in range(0, items_per_location):
new_name = f"{name}-{i}"
self.song_locations[new_name] = location_id_index
location_id_index += 1

def get_songs_with_settings(self, dlc_songs: bool, 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:
continue

if streamer_mode_active and not songData.streamer_mode:
continue

if songData.easy is not None and diff_lower <= songData.easy <= diff_higher:
filtered_list.append(songKey)
continue

if songData.hard is not None and diff_lower <= songData.hard <= diff_higher:
filtered_list.append(songKey)
continue

if songData.master is not None and diff_lower <= songData.master <= diff_higher:
filtered_list.append(songKey)
continue

return filtered_list

def parse_song_difficulty(self, difficulty: str) -> Optional[int]:
"""Attempts to parse the song difficulty."""
if len(difficulty) <= 0 or difficulty == "?" or difficulty == "¿":
return None

# Curse the 2023 april fools update. Used on 3rd Avenue.
if difficulty == "〇":
return 10

return int(difficulty)
Loading

0 comments on commit 77b0852

Please sign in to comment.