mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-14 19:25:16 -05:00
The actual code for custom freeplay music LOL
This commit is contained in:
parent
2f59363432
commit
36505f75c1
7 changed files with 108 additions and 40 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -4,14 +4,28 @@ All notable changes will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.5.0] - 2024-08-??
|
||||
## [0.5.0] - 2024-09-12
|
||||
### Added
|
||||
- Added a new Character Select screen to switch between playable characters in Freeplay
|
||||
- Modding isn't 100% there but we're working on it!
|
||||
- Added Pico as a playable character! Unlock him by completing Weekend 1 (if you haven't already done that)
|
||||
- The songs from Weekend 1 have moved; you must now switch to Pico in Freeplay to access them
|
||||
- Added ## new Pico remixes! Access them by selecting Pico from in the Character Select screen
|
||||
- Added 10 new Pico remixes! Access them by selecting Pico from in the Character Select screen
|
||||
- Bopeebo (Pico Mix)
|
||||
- Fresh (Pico Mix)
|
||||
- DadBattle (Pico Mix)
|
||||
- Spookeez (Pico Mix)
|
||||
- South (Pico Mix)
|
||||
- Philly Nice (Pico Mix)
|
||||
- Blammed (Pico Mix)
|
||||
- Eggnog (Pico Mix)
|
||||
- Ugh (Pico Mix)
|
||||
- Guns (Pico Mix)
|
||||
- Added 1 new Boyfriend remix! Access it by selecting Pico from in the Character Select screen
|
||||
- Darnell (BF Mix)
|
||||
- Added 2 new Erect remixes! Access them by switching difficulty on the song
|
||||
- Cocoa Erect
|
||||
- Ugh Erect
|
||||
- Implemented support for a new Instrumental Selector in Freeplay
|
||||
- Beating a Pico remix lets you use that instrumental when playing as Boyfriend
|
||||
- Added the first batch of Erect Stages! These graphical overhauls of the original stages will be used when playing Erect remixes and Pico remixes
|
||||
|
|
38
source/funkin/Assets.hx
Normal file
38
source/funkin/Assets.hx
Normal file
|
@ -0,0 +1,38 @@
|
|||
package funkin;
|
||||
|
||||
/**
|
||||
* A wrapper around `openfl.utils.Assets` which disallows access to the harmful functions.
|
||||
* Later we'll add Funkin-specific caching to this.
|
||||
*/
|
||||
class Assets
|
||||
{
|
||||
public static function getText(path:String):String
|
||||
{
|
||||
return openfl.utils.Assets.getText(path);
|
||||
}
|
||||
|
||||
public static function getMusic(path:String):openfl.media.Sound
|
||||
{
|
||||
return openfl.utils.Assets.getMusic(path);
|
||||
}
|
||||
|
||||
public static function getBitmapData(path:String):openfl.display.BitmapData
|
||||
{
|
||||
return openfl.utils.Assets.getBitmapData(path);
|
||||
}
|
||||
|
||||
public static function getBytes(path:String):haxe.io.Bytes
|
||||
{
|
||||
return openfl.utils.Assets.getBytes(path);
|
||||
}
|
||||
|
||||
public static function exists(path:String, ?type:openfl.utils.AssetType):Bool
|
||||
{
|
||||
return openfl.utils.Assets.exists(path, type);
|
||||
}
|
||||
|
||||
public static function list(type:openfl.utils.AssetType):Array<String>
|
||||
{
|
||||
return openfl.utils.Assets.list(type);
|
||||
}
|
||||
}
|
|
@ -253,6 +253,8 @@ class PlayerCharSelectData
|
|||
|
||||
typedef PlayerResultsData =
|
||||
{
|
||||
var music:PlayerResultsMusicData;
|
||||
|
||||
var perfect:Array<PlayerResultsAnimationData>;
|
||||
var excellent:Array<PlayerResultsAnimationData>;
|
||||
var great:Array<PlayerResultsAnimationData>;
|
||||
|
@ -260,6 +262,27 @@ typedef PlayerResultsData =
|
|||
var loss:Array<PlayerResultsAnimationData>;
|
||||
};
|
||||
|
||||
typedef PlayerResultsMusicData =
|
||||
{
|
||||
@:optional
|
||||
var PERFECT_GOLD:String;
|
||||
|
||||
@:optional
|
||||
var PERFECT:String;
|
||||
|
||||
@:optional
|
||||
var EXCELLENT:String;
|
||||
|
||||
@:optional
|
||||
var GREAT:String;
|
||||
|
||||
@:optional
|
||||
var GOOD:String;
|
||||
|
||||
@:optional
|
||||
var SHIT:String;
|
||||
}
|
||||
|
||||
typedef PlayerResultsAnimationData =
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -404,12 +404,12 @@ class ResultState extends MusicBeatSubState
|
|||
// }
|
||||
|
||||
new FlxTimer().start(rank.getMusicDelay(), _ -> {
|
||||
if (rank.hasMusicIntro())
|
||||
var introMusic:String = Paths.music(getMusicPath(playerCharacter, rank) + '/' + getMusicPath(playerCharacter, rank) + '-intro');
|
||||
if (Assets.exists(introMusic))
|
||||
{
|
||||
// Play the intro music.
|
||||
var introMusic:String = Paths.music(rank.getMusicPath() + '/' + rank.getMusicPath() + '-intro');
|
||||
FunkinSound.load(introMusic, 1.0, false, true, true, () -> {
|
||||
FunkinSound.playMusic(rank.getMusicPath(),
|
||||
FunkinSound.playMusic(getMusicPath(playerCharacter, rank),
|
||||
{
|
||||
startingVolume: 1.0,
|
||||
overrideExisting: true,
|
||||
|
@ -420,7 +420,7 @@ class ResultState extends MusicBeatSubState
|
|||
}
|
||||
else
|
||||
{
|
||||
FunkinSound.playMusic(rank.getMusicPath(),
|
||||
FunkinSound.playMusic(getMusicPath(playerCharacter, rank),
|
||||
{
|
||||
startingVolume: 1.0,
|
||||
overrideExisting: true,
|
||||
|
@ -441,6 +441,11 @@ class ResultState extends MusicBeatSubState
|
|||
super.create();
|
||||
}
|
||||
|
||||
function getMusicPath(playerCharacter:Null<PlayableCharacter>, rank:ScoringRank):String
|
||||
{
|
||||
return playerCharacter?.getResultsMusicPath(rank) ?? 'resultsNORMAL';
|
||||
}
|
||||
|
||||
var rankTallyTimer:Null<FlxTimer> = null;
|
||||
var clearPercentTarget:Int = 100;
|
||||
var clearPercentLerp:Int = 0;
|
||||
|
|
|
@ -556,40 +556,6 @@ enum abstract ScoringRank(String)
|
|||
}
|
||||
}
|
||||
|
||||
public function getMusicPath():String
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return 'resultsPERFECT';
|
||||
case PERFECT:
|
||||
return 'resultsPERFECT';
|
||||
case EXCELLENT:
|
||||
return 'resultsEXCELLENT';
|
||||
case GREAT:
|
||||
return 'resultsNORMAL';
|
||||
case GOOD:
|
||||
return 'resultsNORMAL';
|
||||
case SHIT:
|
||||
return 'resultsSHIT';
|
||||
default:
|
||||
return 'resultsNORMAL';
|
||||
}
|
||||
}
|
||||
|
||||
public function hasMusicIntro():Bool
|
||||
{
|
||||
switch (abstract)
|
||||
{
|
||||
case EXCELLENT:
|
||||
return true;
|
||||
case SHIT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getFreeplayRankIconAsset():String
|
||||
{
|
||||
switch (abstract)
|
||||
|
|
|
@ -386,6 +386,7 @@ class FreeplayDJ extends FlxAtlasSprite
|
|||
}
|
||||
else
|
||||
{
|
||||
FlxG.log.warn("Freeplay character does not have 'charSelect' animation!");
|
||||
currentState = Confirm;
|
||||
// Call this immediately; otherwise, we get locked out of Character Select.
|
||||
onCharSelectComplete();
|
||||
|
|
|
@ -119,6 +119,27 @@ class PlayableCharacter implements IRegistryEntry<PlayerData>
|
|||
}
|
||||
}
|
||||
|
||||
public function getResultsMusicPath(rank:ScoringRank):String
|
||||
{
|
||||
switch (rank)
|
||||
{
|
||||
case PERFECT_GOLD:
|
||||
return _data?.results?.music?.PERFECT_GOLD ?? "resultsPERFECT";
|
||||
case PERFECT:
|
||||
return _data?.results?.music?.PERFECT ?? "resultsPERFECT";
|
||||
case EXCELLENT:
|
||||
return _data?.results?.music?.EXCELLENT ?? "resultsEXCELLENT";
|
||||
case GREAT:
|
||||
return _data?.results?.music?.GREAT ?? "resultsNORMAL";
|
||||
case GOOD:
|
||||
return _data?.results?.music?.GOOD ?? "resultsNORMAL";
|
||||
case SHIT:
|
||||
return _data?.results?.music?.SHIT ?? "resultsSHIT";
|
||||
default:
|
||||
return _data?.results?.music?.GOOD ?? "resultsNORMAL";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this character is unlocked.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue