mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-27 10:05:41 -05:00
42d8d55067
* Initial test suite * Fix some build warnings * Implemented working unit tests with coverage * Reduced some warnings * Fix a mac-specific issue * Add 2 additional unit test classes. * Multiple new unit tests * Some fixins * Remove auto-generated file * WIP on hiding ignored tests * Added list of debug hotkeys * Remove old website * Remove empty file * Add more unit tests * Fix bug where arrows would nudge BF * Fix bug where ctrl/alt would flash capsules * Fixed bug where bf-old easter egg broke * Remove duplicate lines * More test-related stuff * Some code cleanup * Add mocking and a test assets folder * More TESTS! * Update Hmm... * Update artist on Monster * More minor fixes to individual functions * 1.38% unit test coverage! * Even more tests? :O * More unit test work * Rework migration for BaseRegistry * gameover fix * Fix an issue with Lime * Fix issues with version parsing on data files * 100 total unit tests! * Added even MORE unit tests! * Additional test tweaks :3 * Fixed tests on windows by updating libraries. * Set versions for flixel-ui and hamcrest --------- Co-authored-by: Cameron Taylor <cameron.taylor.ninja@gmail.com>
186 lines
4.5 KiB
Haxe
186 lines
4.5 KiB
Haxe
package funkin.ui.story;
|
|
|
|
import flixel.FlxSprite;
|
|
import flixel.util.FlxColor;
|
|
import funkin.play.song.Song;
|
|
import funkin.data.IRegistryEntry;
|
|
import funkin.data.level.LevelRegistry;
|
|
import funkin.data.level.LevelData;
|
|
|
|
/**
|
|
* An object used to retrieve data about a story mode level (also known as "weeks").
|
|
* Can be scripted to override each function, for custom behavior.
|
|
*/
|
|
class Level implements IRegistryEntry<LevelData>
|
|
{
|
|
/**
|
|
* The ID of the story mode level.
|
|
*/
|
|
public final id:String;
|
|
|
|
/**
|
|
* Level data as parsed from the JSON file.
|
|
*/
|
|
public final _data:LevelData;
|
|
|
|
/**
|
|
* @param id The ID of the JSON file to parse.
|
|
*/
|
|
public function new(id:String)
|
|
{
|
|
this.id = id;
|
|
_data = _fetchData(id);
|
|
|
|
if (_data == null)
|
|
{
|
|
throw 'Could not parse level data for id: $id';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the list of songs in this level, as an array of IDs.
|
|
* @return Array<String>
|
|
*/
|
|
public function getSongs():Array<String>
|
|
{
|
|
// Copy the array so that it can't be modified on accident
|
|
return _data.songs.copy();
|
|
}
|
|
|
|
/**
|
|
* Retrieve the title of the level for display on the menu.
|
|
*/
|
|
public function getTitle():String
|
|
{
|
|
// TODO: Maybe add localization support?
|
|
return _data.name;
|
|
}
|
|
|
|
public function buildTitleGraphic():FlxSprite
|
|
{
|
|
var result = new FlxSprite().loadGraphic(Paths.image(_data.titleAsset));
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get the list of songs in this level, as an array of names, for display on the menu.
|
|
* @return Array<String>
|
|
*/
|
|
public function getSongDisplayNames(difficulty:String):Array<String>
|
|
{
|
|
var songList:Array<String> = getSongs() ?? [];
|
|
var songNameList:Array<String> = songList.map(function(songId) {
|
|
var song:Song = funkin.play.song.SongData.SongDataParser.fetchSong(songId);
|
|
if (song == null) return 'Unknown';
|
|
var songDifficulty:SongDifficulty = song.getDifficulty(difficulty);
|
|
if (songDifficulty == null) songDifficulty = song.getDifficulty();
|
|
var songName:String = songDifficulty?.songName;
|
|
return songName ?? 'Unknown';
|
|
});
|
|
return songNameList;
|
|
}
|
|
|
|
/**
|
|
* Whether this level is unlocked. If not, it will be greyed out on the menu and have a lock icon.
|
|
* TODO: Change this behavior in a later release.
|
|
*/
|
|
public function isUnlocked():Bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Whether this level is visible. If not, it will not be shown on the menu at all.
|
|
*/
|
|
public function isVisible():Bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public function buildBackground():FlxSprite
|
|
{
|
|
if (_data.background.startsWith('#'))
|
|
{
|
|
// Color specified
|
|
var color:FlxColor = FlxColor.fromString(_data.background);
|
|
return new FlxSprite().makeGraphic(FlxG.width, 400, color);
|
|
}
|
|
else
|
|
{
|
|
// Image specified
|
|
return new FlxSprite().loadGraphic(Paths.image(_data.background));
|
|
}
|
|
}
|
|
|
|
public function getDifficulties():Array<String>
|
|
{
|
|
var difficulties:Array<String> = [];
|
|
|
|
var songList = getSongs();
|
|
|
|
var firstSongId:String = songList[0];
|
|
var firstSong:Song = funkin.play.song.SongData.SongDataParser.fetchSong(firstSongId);
|
|
|
|
if (firstSong != null)
|
|
{
|
|
for (difficulty in firstSong.listDifficulties())
|
|
{
|
|
difficulties.push(difficulty);
|
|
}
|
|
}
|
|
|
|
// Filter to only include difficulties that are present in all songs
|
|
for (songIndex in 1...songList.length)
|
|
{
|
|
var songId:String = songList[songIndex];
|
|
var song:Song = funkin.play.song.SongData.SongDataParser.fetchSong(songId);
|
|
|
|
if (song == null) continue;
|
|
|
|
for (difficulty in difficulties)
|
|
{
|
|
if (!song.hasDifficulty(difficulty))
|
|
{
|
|
difficulties.remove(difficulty);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (difficulties.length == 0) difficulties = ['normal'];
|
|
|
|
return difficulties;
|
|
}
|
|
|
|
public function buildProps():Array<LevelProp>
|
|
{
|
|
var props:Array<LevelProp> = [];
|
|
|
|
if (_data.props.length == 0) return props;
|
|
|
|
for (propIndex in 0..._data.props.length)
|
|
{
|
|
var propData = _data.props[propIndex];
|
|
|
|
var propSprite:Null<LevelProp> = LevelProp.build(propData);
|
|
if (propSprite == null) continue;
|
|
|
|
propSprite.x += FlxG.width * 0.25 * propIndex;
|
|
props.push(propSprite);
|
|
}
|
|
|
|
return props;
|
|
}
|
|
|
|
public function destroy():Void {}
|
|
|
|
public function toString():String
|
|
{
|
|
return 'Level($id)';
|
|
}
|
|
|
|
public function _fetchData(id:String):Null<LevelData>
|
|
{
|
|
return LevelRegistry.instance.parseEntryDataWithMigration(id, LevelRegistry.instance.fetchEntryVersion(id));
|
|
}
|
|
}
|