mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-27 10:05:41 -05:00
Merge branch 'rewrite/master' into docs/compiling.md
This commit is contained in:
commit
b2e489582b
37 changed files with 375 additions and 243 deletions
6
.github/workflows/build-shit.yml
vendored
6
.github/workflows/build-shit.yml
vendored
|
@ -31,7 +31,7 @@ jobs:
|
||||||
sudo apt-get install -y libx11-dev xorg-dev libgl-dev libxi-dev libxext-dev libasound2-dev libxinerama-dev libxrandr-dev libgl1-mesa-dev
|
sudo apt-get install -y libx11-dev xorg-dev libgl-dev libxi-dev libxext-dev libasound2-dev libxinerama-dev libxrandr-dev libgl1-mesa-dev
|
||||||
- name: build game
|
- name: build game
|
||||||
run: |
|
run: |
|
||||||
haxelib run lime build html5 -release --times
|
haxelib run lime build html5 -release --times -DGITHUB_BUILD
|
||||||
ls
|
ls
|
||||||
- uses: ./.github/actions/upload-itch
|
- uses: ./.github/actions/upload-itch
|
||||||
with:
|
with:
|
||||||
|
@ -68,7 +68,7 @@ jobs:
|
||||||
key: ${{ runner.os }}-build-win-${{ github.ref_name }}-${{ hashFiles('**/hmm.json') }}
|
key: ${{ runner.os }}-build-win-${{ github.ref_name }}-${{ hashFiles('**/hmm.json') }}
|
||||||
- name: build game
|
- name: build game
|
||||||
run: |
|
run: |
|
||||||
haxelib run lime build windows -release -DNO_REDIRECT_ASSETS_FOLDER
|
haxelib run lime build windows -release -DNO_REDIRECT_ASSETS_FOLDER -DGITHUB_BUILD
|
||||||
dir
|
dir
|
||||||
env:
|
env:
|
||||||
HXCPP_COMPILE_CACHE: "${{ runner.temp }}\\hxcpp_cache"
|
HXCPP_COMPILE_CACHE: "${{ runner.temp }}\\hxcpp_cache"
|
||||||
|
@ -110,7 +110,7 @@ jobs:
|
||||||
key: ${{ runner.os }}-build-mac-${{ github.ref_name }}-${{ hashFiles('**/hmm.json') }}
|
key: ${{ runner.os }}-build-mac-${{ github.ref_name }}-${{ hashFiles('**/hmm.json') }}
|
||||||
- name: Build game
|
- name: Build game
|
||||||
run: |
|
run: |
|
||||||
haxelib run lime build macos -release --times
|
haxelib run lime build macos -release --times -DGITHUB_BUILD
|
||||||
ls
|
ls
|
||||||
env:
|
env:
|
||||||
HXCPP_COMPILE_CACHE: "${{ runner.temp }}/hxcpp_cache"
|
HXCPP_COMPILE_CACHE: "${{ runner.temp }}/hxcpp_cache"
|
||||||
|
|
16
Project.xml
16
Project.xml
|
@ -91,7 +91,8 @@
|
||||||
NOT USING A DIRECT THING TO THE ASSET!!!
|
NOT USING A DIRECT THING TO THE ASSET!!!
|
||||||
-->
|
-->
|
||||||
<assets path="assets/fonts" embed="true" />
|
<assets path="assets/fonts" embed="true" />
|
||||||
|
<!-- If compiled via github actions, enable force debug -->
|
||||||
|
<set name="FORCE_DEBUG_VERSION" if="GITHUB_BUILD"/>
|
||||||
<!-- _______________________________ Libraries ______________________________ -->
|
<!-- _______________________________ Libraries ______________________________ -->
|
||||||
<haxelib name="lime" /> <!-- Game engine backend -->
|
<haxelib name="lime" /> <!-- Game engine backend -->
|
||||||
<haxelib name="openfl" /> <!-- Game engine backend -->
|
<haxelib name="openfl" /> <!-- Game engine backend -->
|
||||||
|
@ -118,15 +119,15 @@
|
||||||
<!--Disable the Flixel core focus lost screen-->
|
<!--Disable the Flixel core focus lost screen-->
|
||||||
<haxedef name="FLX_NO_FOCUS_LOST_SCREEN" />
|
<haxedef name="FLX_NO_FOCUS_LOST_SCREEN" />
|
||||||
<!--Disable the Flixel core debugger. Automatically gets set whenever you compile in release mode!-->
|
<!--Disable the Flixel core debugger. Automatically gets set whenever you compile in release mode!-->
|
||||||
<haxedef name="FLX_NO_DEBUG" unless="debug" />
|
<haxedef name="FLX_NO_DEBUG" unless="debug || FORCE_DEBUG_VERSION" />
|
||||||
<!--Enable this for Nape release builds for a serious peformance improvement-->
|
<!--Enable this for Nape release builds for a serious peformance improvement-->
|
||||||
<haxedef name="NAPE_RELEASE_BUILD" unless="debug" />
|
<haxedef name="NAPE_RELEASE_BUILD" unless="debug" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Hide deprecation warnings until they're fixed.
|
Hide deprecation warnings until they're fixed.
|
||||||
TODO: REMOVE THIS!!!!
|
TODO: REMOVE THIS!!!!
|
||||||
|
<haxeflag name="-w" value="-WDeprecated" />
|
||||||
-->
|
-->
|
||||||
<haxeflag name="-w" value="-WDeprecated" />
|
|
||||||
|
|
||||||
<!-- Haxe 4.3.0+: Enable pretty syntax errors and stuff. -->
|
<!-- Haxe 4.3.0+: Enable pretty syntax errors and stuff. -->
|
||||||
<haxedef name="message.reporting" value="pretty" />
|
<haxedef name="message.reporting" value="pretty" />
|
||||||
|
@ -211,15 +212,8 @@
|
||||||
<haxedef name="openfl-enable-handle-error" />
|
<haxedef name="openfl-enable-handle-error" />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
|
||||||
<!-- TODO: Add a flag to Github Actions to turn this on or something. -->
|
|
||||||
|
|
||||||
<!-- Forces the version string to include the Git hash even on release builds (which are used for performance reasons). -->
|
|
||||||
<haxedef name="FORCE_DEBUG_VERSION" />
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Run a script before and after building. -->
|
<!-- Run a script before and after building. -->
|
||||||
<postbuild haxe="source/Prebuild.hx"/> -->
|
<prebuild haxe="source/Prebuild.hx"/> -->
|
||||||
<postbuild haxe="source/Postbuild.hx"/> -->
|
<postbuild haxe="source/Postbuild.hx"/> -->
|
||||||
|
|
||||||
<!-- Enable this on platforms which do not support dropping files onto the window. -->
|
<!-- Enable this on platforms which do not support dropping files onto the window. -->
|
||||||
|
|
2
assets
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit 594853037cbea06caa5c141b0d9ed3736818e592
|
Subproject commit 160acbd8a854a9f677ef7587396340e79a5ea6ca
|
15
hmm.json
15
hmm.json
|
@ -11,7 +11,7 @@
|
||||||
"name": "flixel",
|
"name": "flixel",
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"dir": null,
|
"dir": null,
|
||||||
"ref": "07c6018008801972d12275690fc144fcc22e3de6",
|
"ref": "25c84b29665329f7c6366342542a3978f29300ee",
|
||||||
"url": "https://github.com/FunkinCrew/flixel"
|
"url": "https://github.com/FunkinCrew/flixel"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -88,8 +88,10 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hxcpp-debug-server",
|
"name": "hxcpp-debug-server",
|
||||||
"type": "haxelib",
|
"type": "git",
|
||||||
"version": "1.2.4"
|
"dir": "hxcpp-debug-server",
|
||||||
|
"ref": "147294123f983e35f50a966741474438069a7a8f",
|
||||||
|
"url": "https://github.com/FunkinCrew/hxcpp-debugger"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hxp",
|
"name": "hxp",
|
||||||
|
@ -152,6 +154,13 @@
|
||||||
"ref": "0b53e478bc375ec51b760b650201ac7a965d2ef4",
|
"ref": "0b53e478bc375ec51b760b650201ac7a965d2ef4",
|
||||||
"url": "https://github.com/larsiusprime/polymod"
|
"url": "https://github.com/larsiusprime/polymod"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "thx.core",
|
||||||
|
"type": "git",
|
||||||
|
"dir": null,
|
||||||
|
"ref": "22605ff44f01971d599641790d6bae4869f7d9f4",
|
||||||
|
"url": "https://github.com/FunkinCrew/thx.core"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "thx.semver",
|
"name": "thx.semver",
|
||||||
"type": "haxelib",
|
"type": "haxelib",
|
||||||
|
|
|
@ -16,7 +16,7 @@ import flixel.addons.transition.FlxTransitionableState;
|
||||||
* var in:TransitionData = new TransitionData(...); // add your data where "..." is
|
* var in:TransitionData = new TransitionData(...); // add your data where "..." is
|
||||||
* var out:TransitionData = new TransitionData(...);
|
* var out:TransitionData = new TransitionData(...);
|
||||||
*
|
*
|
||||||
* FlxG.switchState(new FooState(in,out));
|
* FlxG.switchState(() -> new FooState(in,out));
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Method 2:
|
* Method 2:
|
||||||
|
@ -25,7 +25,7 @@ import flixel.addons.transition.FlxTransitionableState;
|
||||||
* FlxTransitionableSubState.defaultTransIn = new TransitionData(...);
|
* FlxTransitionableSubState.defaultTransIn = new TransitionData(...);
|
||||||
* FlxTransitionableSubState.defaultTransOut = new TransitionData(...);
|
* FlxTransitionableSubState.defaultTransOut = new TransitionData(...);
|
||||||
*
|
*
|
||||||
* FlxG.switchState(new FooState());
|
* FlxG.switchState(() -> new FooState());
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class FlxTransitionableSubState extends FlxSubState
|
class FlxTransitionableSubState extends FlxSubState
|
||||||
|
|
|
@ -89,7 +89,7 @@ class InitState extends FlxState
|
||||||
//
|
//
|
||||||
// FLIXEL DEBUG SETUP
|
// FLIXEL DEBUG SETUP
|
||||||
//
|
//
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
// Disable using ~ to open the console (we use that for the Editor menu)
|
// Disable using ~ to open the console (we use that for the Editor menu)
|
||||||
FlxG.debugger.toggleKeys = [F2];
|
FlxG.debugger.toggleKeys = [F2];
|
||||||
|
|
||||||
|
@ -141,16 +141,14 @@ class InitState extends FlxState
|
||||||
FlxG.sound.music.pause();
|
FlxG.sound.music.pause();
|
||||||
FlxG.sound.music.time += FlxG.elapsed * 1000;
|
FlxG.sound.music.time += FlxG.elapsed * 1000;
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
|
|
||||||
// Make errors and warnings less annoying.
|
// Make errors and warnings less annoying.
|
||||||
// TODO: Disable this so we know to fix warnings.
|
#if FORCE_DEBUG_VERSION
|
||||||
if (false)
|
LogStyle.ERROR.openConsole = false;
|
||||||
{
|
LogStyle.ERROR.errorSound = null;
|
||||||
LogStyle.ERROR.openConsole = false;
|
LogStyle.WARNING.openConsole = false;
|
||||||
LogStyle.ERROR.errorSound = null;
|
LogStyle.WARNING.errorSound = null;
|
||||||
LogStyle.WARNING.openConsole = false;
|
|
||||||
LogStyle.WARNING.errorSound = null;
|
|
||||||
}
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -251,17 +249,17 @@ class InitState extends FlxState
|
||||||
#elseif DIALOGUE // -DDIALOGUE
|
#elseif DIALOGUE // -DDIALOGUE
|
||||||
FlxG.switchState(new funkin.ui.debug.dialogue.ConversationDebugState());
|
FlxG.switchState(new funkin.ui.debug.dialogue.ConversationDebugState());
|
||||||
#elseif ANIMATE // -DANIMATE
|
#elseif ANIMATE // -DANIMATE
|
||||||
FlxG.switchState(new funkin.ui.debug.anim.FlxAnimateTest());
|
FlxG.switchState(() -> new funkin.ui.debug.anim.FlxAnimateTest());
|
||||||
#elseif WAVEFORM // -DWAVEFORM
|
#elseif WAVEFORM // -DWAVEFORM
|
||||||
FlxG.switchState(new funkin.ui.debug.WaveformTestState());
|
FlxG.switchState(() -> new funkin.ui.debug.WaveformTestState());
|
||||||
#elseif CHARTING // -DCHARTING
|
#elseif CHARTING // -DCHARTING
|
||||||
FlxG.switchState(new funkin.ui.debug.charting.ChartEditorState());
|
FlxG.switchState(() -> new funkin.ui.debug.charting.ChartEditorState());
|
||||||
#elseif STAGEBUILD // -DSTAGEBUILD
|
#elseif STAGEBUILD // -DSTAGEBUILD
|
||||||
FlxG.switchState(new funkin.ui.debug.stage.StageBuilderState());
|
FlxG.switchState(() -> new funkin.ui.debug.stage.StageBuilderState());
|
||||||
#elseif ANIMDEBUG // -DANIMDEBUG
|
#elseif ANIMDEBUG // -DANIMDEBUG
|
||||||
FlxG.switchState(new funkin.ui.debug.anim.DebugBoundingState());
|
FlxG.switchState(() -> new funkin.ui.debug.anim.DebugBoundingState());
|
||||||
#elseif LATENCY // -DLATENCY
|
#elseif LATENCY // -DLATENCY
|
||||||
FlxG.switchState(new funkin.LatencyState());
|
FlxG.switchState(() -> new funkin.LatencyState());
|
||||||
#else
|
#else
|
||||||
startGameNormally();
|
startGameNormally();
|
||||||
#end
|
#end
|
||||||
|
@ -277,7 +275,7 @@ class InitState extends FlxState
|
||||||
|
|
||||||
if (params.chart.shouldLoadChart)
|
if (params.chart.shouldLoadChart)
|
||||||
{
|
{
|
||||||
FlxG.switchState(new ChartEditorState(
|
FlxG.switchState(() -> new ChartEditorState(
|
||||||
{
|
{
|
||||||
fnfcTargetPath: params.chart.chartPath,
|
fnfcTargetPath: params.chart.chartPath,
|
||||||
}));
|
}));
|
||||||
|
@ -285,7 +283,7 @@ class InitState extends FlxState
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlxG.sound.cache(Paths.music('freakyMenu/freakyMenu'));
|
FlxG.sound.cache(Paths.music('freakyMenu/freakyMenu'));
|
||||||
FlxG.switchState(new TitleState());
|
FlxG.switchState(() -> new TitleState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +306,7 @@ class InitState extends FlxState
|
||||||
// TODO: Do this in the loading state.
|
// TODO: Do this in the loading state.
|
||||||
songData.cacheCharts(true);
|
songData.cacheCharts(true);
|
||||||
|
|
||||||
LoadingState.loadAndSwitchState(new funkin.play.PlayState(
|
LoadingState.loadAndSwitchState(() -> new funkin.play.PlayState(
|
||||||
{
|
{
|
||||||
targetSong: songData,
|
targetSong: songData,
|
||||||
targetDifficulty: difficultyId,
|
targetDifficulty: difficultyId,
|
||||||
|
@ -338,7 +336,7 @@ class InitState extends FlxState
|
||||||
|
|
||||||
var targetSong:funkin.play.song.Song = SongRegistry.instance.fetchEntry(targetSongId);
|
var targetSong:funkin.play.song.Song = SongRegistry.instance.fetchEntry(targetSongId);
|
||||||
|
|
||||||
LoadingState.loadAndSwitchState(new funkin.play.PlayState(
|
LoadingState.loadAndSwitchState(() -> new funkin.play.PlayState(
|
||||||
{
|
{
|
||||||
targetSong: targetSong,
|
targetSong: targetSong,
|
||||||
targetDifficulty: difficultyId,
|
targetDifficulty: difficultyId,
|
||||||
|
|
|
@ -936,6 +936,28 @@ class SongNoteDataRaw implements ICloneable<SongNoteDataRaw>
|
||||||
return SongNoteData.buildDirectionName(this.data, strumlineSize);
|
return SongNoteData.buildDirectionName(this.data, strumlineSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strumline index of the note, if applicable.
|
||||||
|
* Strips the direction from the data.
|
||||||
|
*
|
||||||
|
* 0 = player, 1 = opponent, etc.
|
||||||
|
*/
|
||||||
|
public function getStrumlineIndex(strumlineSize:Int = 4):Int
|
||||||
|
{
|
||||||
|
return Math.floor(this.data / strumlineSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the note is one that Boyfriend should try to hit (i.e. it's on his side).
|
||||||
|
* TODO: The name of this function is a little misleading; what about mines?
|
||||||
|
* @param strumlineSize Defaults to 4.
|
||||||
|
* @return True if it's Boyfriend's note.
|
||||||
|
*/
|
||||||
|
public function getMustHitNote(strumlineSize:Int = 4):Bool
|
||||||
|
{
|
||||||
|
return getStrumlineIndex(strumlineSize) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
@:jignored
|
@:jignored
|
||||||
var _stepTime:Null<Float> = null;
|
var _stepTime:Null<Float> = null;
|
||||||
|
|
||||||
|
@ -1024,28 +1046,6 @@ abstract SongNoteData(SongNoteDataRaw) from SongNoteDataRaw to SongNoteDataRaw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The strumline index of the note, if applicable.
|
|
||||||
* Strips the direction from the data.
|
|
||||||
*
|
|
||||||
* 0 = player, 1 = opponent, etc.
|
|
||||||
*/
|
|
||||||
public inline function getStrumlineIndex(strumlineSize:Int = 4):Int
|
|
||||||
{
|
|
||||||
return Math.floor(this.data / strumlineSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the note is one that Boyfriend should try to hit (i.e. it's on his side).
|
|
||||||
* TODO: The name of this function is a little misleading; what about mines?
|
|
||||||
* @param strumlineSize Defaults to 4.
|
|
||||||
* @return True if it's Boyfriend's note.
|
|
||||||
*/
|
|
||||||
public inline function getMustHitNote(strumlineSize:Int = 4):Bool
|
|
||||||
{
|
|
||||||
return getStrumlineIndex(strumlineSize) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@:jignored
|
@:jignored
|
||||||
public var isHoldNote(get, never):Bool;
|
public var isHoldNote(get, never):Bool;
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ class GameOverSubState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
animationSuffix = "";
|
animationSuffix = "";
|
||||||
musicSuffix = "";
|
musicSuffix = "";
|
||||||
|
blueBallSuffix = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function create()
|
override public function create()
|
||||||
|
@ -207,11 +208,11 @@ class GameOverSubState extends MusicBeatSubState
|
||||||
}
|
}
|
||||||
else if (PlayStatePlaylist.isStoryMode)
|
else if (PlayStatePlaylist.isStoryMode)
|
||||||
{
|
{
|
||||||
FlxG.switchState(new StoryMenuState());
|
FlxG.switchState(() -> new StoryMenuState());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlxG.switchState(new FreeplayState());
|
FlxG.switchState(() -> new FreeplayState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,11 +66,11 @@ class GitarooPause extends MusicBeatState
|
||||||
{
|
{
|
||||||
FlxTransitionableState.skipNextTransIn = false;
|
FlxTransitionableState.skipNextTransIn = false;
|
||||||
FlxTransitionableState.skipNextTransOut = false;
|
FlxTransitionableState.skipNextTransOut = false;
|
||||||
FlxG.switchState(new PlayState(previousParams));
|
FlxG.switchState(() -> new PlayState(previousParams));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ class PauseSubState extends MusicBeatSubState
|
||||||
var downP = controls.UI_DOWN_P;
|
var downP = controls.UI_DOWN_P;
|
||||||
var accepted = controls.ACCEPT;
|
var accepted = controls.ACCEPT;
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
// to pause the game and get screenshots easy, press H on pause menu!
|
// to pause the game and get screenshots easy, press H on pause menu!
|
||||||
if (FlxG.keys.justPressed.H)
|
if (FlxG.keys.justPressed.H)
|
||||||
{
|
{
|
||||||
|
@ -234,11 +234,11 @@ class PauseSubState extends MusicBeatSubState
|
||||||
if (PlayStatePlaylist.isStoryMode)
|
if (PlayStatePlaylist.isStoryMode)
|
||||||
{
|
{
|
||||||
PlayStatePlaylist.reset();
|
PlayStatePlaylist.reset();
|
||||||
openSubState(new funkin.ui.transition.StickerSubState(null, STORY));
|
openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.story.StoryMenuState()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
openSubState(new funkin.ui.transition.StickerSubState(null, FREEPLAY));
|
openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.freeplay.FreeplayState(null, sticker)));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'Exit to Chart Editor':
|
case 'Exit to Chart Editor':
|
||||||
|
|
|
@ -83,10 +83,16 @@ typedef PlayStateParams =
|
||||||
*/
|
*/
|
||||||
?targetDifficulty:String,
|
?targetDifficulty:String,
|
||||||
/**
|
/**
|
||||||
* The character to play as.
|
* The variation to play on.
|
||||||
* @default `bf`, or the first character in the song's character list.
|
* @default `Constants.DEFAULT_VARIATION` .
|
||||||
*/
|
*/
|
||||||
?targetCharacter:String,
|
?targetVariation:String,
|
||||||
|
/**
|
||||||
|
* The instrumental to play with.
|
||||||
|
* Significant if the `targetSong` supports alternate instrumentals.
|
||||||
|
* @default `null`
|
||||||
|
*/
|
||||||
|
?targetInstrumental:String,
|
||||||
/**
|
/**
|
||||||
* Whether the song should start in Practice Mode.
|
* Whether the song should start in Practice Mode.
|
||||||
* @default `false`
|
* @default `false`
|
||||||
|
@ -147,9 +153,9 @@ class PlayState extends MusicBeatSubState
|
||||||
public var currentDifficulty:String = Constants.DEFAULT_DIFFICULTY;
|
public var currentDifficulty:String = Constants.DEFAULT_DIFFICULTY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The player character being used for this level, as a character ID.
|
* The currently selected variation.
|
||||||
*/
|
*/
|
||||||
public var currentPlayerId:String = 'bf';
|
public var currentVariation:String = Constants.DEFAULT_VARIATION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently active Stage. This is the object containing all the props.
|
* The currently active Stage. This is the object containing all the props.
|
||||||
|
@ -448,7 +454,7 @@ class PlayState extends MusicBeatSubState
|
||||||
function get_currentChart():SongDifficulty
|
function get_currentChart():SongDifficulty
|
||||||
{
|
{
|
||||||
if (currentSong == null || currentDifficulty == null) return null;
|
if (currentSong == null || currentDifficulty == null) return null;
|
||||||
return currentSong.getDifficulty(currentDifficulty);
|
return currentSong.getDifficulty(currentDifficulty, currentVariation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -506,7 +512,7 @@ class PlayState extends MusicBeatSubState
|
||||||
// Apply parameters.
|
// Apply parameters.
|
||||||
currentSong = params.targetSong;
|
currentSong = params.targetSong;
|
||||||
if (params.targetDifficulty != null) currentDifficulty = params.targetDifficulty;
|
if (params.targetDifficulty != null) currentDifficulty = params.targetDifficulty;
|
||||||
if (params.targetCharacter != null) currentPlayerId = params.targetCharacter;
|
if (params.targetVariation != null) currentVariation = params.targetVariation;
|
||||||
isPracticeMode = params.practiceMode ?? false;
|
isPracticeMode = params.practiceMode ?? false;
|
||||||
isMinimalMode = params.minimalMode ?? false;
|
isMinimalMode = params.minimalMode ?? false;
|
||||||
startTimestamp = params.startTimestamp ?? 0.0;
|
startTimestamp = params.startTimestamp ?? 0.0;
|
||||||
|
@ -638,7 +644,7 @@ class PlayState extends MusicBeatSubState
|
||||||
rightWatermarkText.cameras = [camHUD];
|
rightWatermarkText.cameras = [camHUD];
|
||||||
|
|
||||||
// Initialize some debug stuff.
|
// Initialize some debug stuff.
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
// Display the version number (and git commit hash) in the bottom right corner.
|
// Display the version number (and git commit hash) in the bottom right corner.
|
||||||
this.rightWatermarkText.text = Constants.VERSION;
|
this.rightWatermarkText.text = Constants.VERSION;
|
||||||
|
|
||||||
|
@ -684,9 +690,9 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
message = 'The was a critical error selecting a difficulty for this song. Click OK to return to the main menu.';
|
message = 'The was a critical error selecting a difficulty for this song. Click OK to return to the main menu.';
|
||||||
}
|
}
|
||||||
else if (currentSong.getDifficulty(currentDifficulty) == null)
|
else if (currentChart == null)
|
||||||
{
|
{
|
||||||
message = 'The was a critical error retrieving data for this song on "$currentDifficulty" difficulty. Click OK to return to the main menu.';
|
message = 'The was a critical error retrieving data for this song on "$currentDifficulty" difficulty with variation "$currentVariation". Click OK to return to the main menu.';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display a popup. This blocks the application until the user clicks OK.
|
// Display a popup. This blocks the application until the user clicks OK.
|
||||||
|
@ -699,7 +705,7 @@ class PlayState extends MusicBeatSubState
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -828,11 +834,11 @@ class PlayState extends MusicBeatSubState
|
||||||
// It's a reference to Gitaroo Man, which doesn't let you pause the game.
|
// It's a reference to Gitaroo Man, which doesn't let you pause the game.
|
||||||
if (!isSubState && event.gitaroo)
|
if (!isSubState && event.gitaroo)
|
||||||
{
|
{
|
||||||
FlxG.switchState(new GitarooPause(
|
FlxG.switchState(() -> new GitarooPause(
|
||||||
{
|
{
|
||||||
targetSong: currentSong,
|
targetSong: currentSong,
|
||||||
targetDifficulty: currentDifficulty,
|
targetDifficulty: currentDifficulty,
|
||||||
targetCharacter: currentPlayerId,
|
targetVariation: currentVariation,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -907,7 +913,7 @@ class PlayState extends MusicBeatSubState
|
||||||
|
|
||||||
// Disable updates, preventing animations in the background from playing.
|
// Disable updates, preventing animations in the background from playing.
|
||||||
persistentUpdate = false;
|
persistentUpdate = false;
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
if (FlxG.keys.pressed.THREE)
|
if (FlxG.keys.pressed.THREE)
|
||||||
{
|
{
|
||||||
// TODO: Change the key or delete this?
|
// TODO: Change the key or delete this?
|
||||||
|
@ -918,7 +924,7 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
#end
|
#end
|
||||||
persistentDraw = false;
|
persistentDraw = false;
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
@ -1368,7 +1374,7 @@ class PlayState extends MusicBeatSubState
|
||||||
// Add the stage to the scene.
|
// Add the stage to the scene.
|
||||||
this.add(currentStage);
|
this.add(currentStage);
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
FlxG.console.registerObject('stage', currentStage);
|
FlxG.console.registerObject('stage', currentStage);
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
@ -1389,7 +1395,7 @@ class PlayState extends MusicBeatSubState
|
||||||
trace('Song difficulty could not be loaded.');
|
trace('Song difficulty could not be loaded.');
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentCharacterData:SongCharacterData = currentChart.characters; // Switch the character we are playing as by manipulating currentPlayerId.
|
var currentCharacterData:SongCharacterData = currentChart.characters; // Switch the variation we are playing on by manipulating targetVariation.
|
||||||
|
|
||||||
//
|
//
|
||||||
// GIRLFRIEND
|
// GIRLFRIEND
|
||||||
|
@ -1458,7 +1464,7 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
currentStage.addCharacter(girlfriend, GF);
|
currentStage.addCharacter(girlfriend, GF);
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
FlxG.console.registerObject('gf', girlfriend);
|
FlxG.console.registerObject('gf', girlfriend);
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
@ -1467,7 +1473,7 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
currentStage.addCharacter(boyfriend, BF);
|
currentStage.addCharacter(boyfriend, BF);
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
FlxG.console.registerObject('bf', boyfriend);
|
FlxG.console.registerObject('bf', boyfriend);
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
@ -1478,7 +1484,7 @@ class PlayState extends MusicBeatSubState
|
||||||
// Camera starts at dad.
|
// Camera starts at dad.
|
||||||
cameraFollowPoint.setPosition(dad.cameraFocusPoint.x, dad.cameraFocusPoint.y);
|
cameraFollowPoint.setPosition(dad.cameraFocusPoint.x, dad.cameraFocusPoint.y);
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
FlxG.console.registerObject('dad', dad);
|
FlxG.console.registerObject('dad', dad);
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
@ -2229,7 +2235,7 @@ class PlayState extends MusicBeatSubState
|
||||||
#end
|
#end
|
||||||
|
|
||||||
// Eject button
|
// Eject button
|
||||||
if (FlxG.keys.justPressed.F4) FlxG.switchState(new MainMenuState());
|
if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState());
|
||||||
|
|
||||||
if (FlxG.keys.justPressed.F5) debug_refreshModules();
|
if (FlxG.keys.justPressed.F5) debug_refreshModules();
|
||||||
|
|
||||||
|
@ -2247,13 +2253,13 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
disableKeys = true;
|
disableKeys = true;
|
||||||
persistentUpdate = false;
|
persistentUpdate = false;
|
||||||
FlxG.switchState(new ChartEditorState(
|
FlxG.switchState(() -> new ChartEditorState(
|
||||||
{
|
{
|
||||||
targetSongId: currentSong.id,
|
targetSongId: currentSong.id,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
// 1: End the song immediately.
|
// 1: End the song immediately.
|
||||||
if (FlxG.keys.justPressed.ONE) endSong();
|
if (FlxG.keys.justPressed.ONE) endSong();
|
||||||
|
|
||||||
|
@ -2267,7 +2273,7 @@ class PlayState extends MusicBeatSubState
|
||||||
// 9: Toggle the old icon.
|
// 9: Toggle the old icon.
|
||||||
if (FlxG.keys.justPressed.NINE) iconP1.toggleOldIcon();
|
if (FlxG.keys.justPressed.NINE) iconP1.toggleOldIcon();
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
// PAGEUP: Skip forward two sections.
|
// PAGEUP: Skip forward two sections.
|
||||||
// SHIFT+PAGEUP: Skip forward twenty sections.
|
// SHIFT+PAGEUP: Skip forward twenty sections.
|
||||||
if (FlxG.keys.justPressed.PAGEUP) changeSection(FlxG.keys.pressed.SHIFT ? 20 : 2);
|
if (FlxG.keys.justPressed.PAGEUP) changeSection(FlxG.keys.pressed.SHIFT ? 20 : 2);
|
||||||
|
@ -2589,14 +2595,16 @@ class PlayState extends MusicBeatSubState
|
||||||
// TODO: Do this in the loading state.
|
// TODO: Do this in the loading state.
|
||||||
targetSong.cacheCharts(true);
|
targetSong.cacheCharts(true);
|
||||||
|
|
||||||
var nextPlayState:PlayState = new PlayState(
|
LoadingState.loadAndSwitchState(() -> {
|
||||||
{
|
var nextPlayState:PlayState = new PlayState(
|
||||||
targetSong: targetSong,
|
{
|
||||||
targetDifficulty: PlayStatePlaylist.campaignDifficulty,
|
targetSong: targetSong,
|
||||||
targetCharacter: currentPlayerId,
|
targetDifficulty: PlayStatePlaylist.campaignDifficulty,
|
||||||
});
|
targetVariation: currentVariation,
|
||||||
nextPlayState.previousCameraFollowPoint = new FlxSprite(cameraFollowPoint.x, cameraFollowPoint.y);
|
});
|
||||||
LoadingState.loadAndSwitchState(nextPlayState);
|
nextPlayState.previousCameraFollowPoint = new FlxSprite(cameraFollowPoint.x, cameraFollowPoint.y);
|
||||||
|
return nextPlayState;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2605,14 +2613,16 @@ class PlayState extends MusicBeatSubState
|
||||||
// Load and cache the song's charts.
|
// Load and cache the song's charts.
|
||||||
// TODO: Do this in the loading state.
|
// TODO: Do this in the loading state.
|
||||||
targetSong.cacheCharts(true);
|
targetSong.cacheCharts(true);
|
||||||
var nextPlayState:PlayState = new PlayState(
|
LoadingState.loadAndSwitchState(() -> {
|
||||||
{
|
var nextPlayState:PlayState = new PlayState(
|
||||||
targetSong: targetSong,
|
{
|
||||||
targetDifficulty: PlayStatePlaylist.campaignDifficulty,
|
targetSong: targetSong,
|
||||||
targetCharacter: currentPlayerId,
|
targetDifficulty: PlayStatePlaylist.campaignDifficulty,
|
||||||
});
|
targetVariation: currentVariation,
|
||||||
nextPlayState.previousCameraFollowPoint = new FlxSprite(cameraFollowPoint.x, cameraFollowPoint.y);
|
});
|
||||||
LoadingState.loadAndSwitchState(nextPlayState);
|
nextPlayState.previousCameraFollowPoint = new FlxSprite(cameraFollowPoint.x, cameraFollowPoint.y);
|
||||||
|
return nextPlayState;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2650,13 +2660,16 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
// Stop the music.
|
// Stop the music.
|
||||||
FlxG.sound.music.pause();
|
FlxG.sound.music.pause();
|
||||||
vocals.stop();
|
if (vocals != null) vocals.stop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlxG.sound.music.pause();
|
FlxG.sound.music.pause();
|
||||||
vocals.pause();
|
if (vocals != null)
|
||||||
remove(vocals);
|
{
|
||||||
|
vocals.pause();
|
||||||
|
remove(vocals);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove reference to stage and remove sprites from it to save memory.
|
// Remove reference to stage and remove sprites from it to save memory.
|
||||||
|
@ -2768,7 +2781,7 @@ class PlayState extends MusicBeatSubState
|
||||||
FlxG.camera.focusOn(cameraFollowPoint.getPosition());
|
FlxG.camera.focusOn(cameraFollowPoint.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
/**
|
/**
|
||||||
* Jumps forward or backward a number of sections in the song.
|
* Jumps forward or backward a number of sections in the song.
|
||||||
* Accounts for BPM changes, does not prevent death from skipped notes.
|
* Accounts for BPM changes, does not prevent death from skipped notes.
|
||||||
|
|
|
@ -352,11 +352,11 @@ class ResultState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
if (params.storyMode)
|
if (params.storyMode)
|
||||||
{
|
{
|
||||||
FlxG.switchState(new StoryMenuState());
|
FlxG.switchState(() -> new StoryMenuState());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlxG.switchState(new FreeplayState());
|
FlxG.switchState(() -> new FreeplayState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,11 +148,12 @@ class HealthIcon extends FlxSprite
|
||||||
{
|
{
|
||||||
if (characterId == 'bf-old')
|
if (characterId == 'bf-old')
|
||||||
{
|
{
|
||||||
characterId = PlayState.instance.currentPlayerId;
|
PlayState.instance.currentStage.getBoyfriend().initHealthIcon(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
characterId = 'bf-old';
|
characterId = 'bf-old';
|
||||||
|
loadCharacter(characterId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
|
|
||||||
difficulty.characters = metadata.playData.characters;
|
difficulty.characters = metadata.playData.characters;
|
||||||
|
|
||||||
difficulties.set(diffId, difficulty);
|
var variationSuffix = (metadata.variation != Constants.DEFAULT_VARIATION) ? '-${metadata.variation}' : '';
|
||||||
|
difficulties.set('$diffId$variationSuffix', difficulty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,13 +219,14 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
for (diffId in chartNotes.keys())
|
for (diffId in chartNotes.keys())
|
||||||
{
|
{
|
||||||
// Retrieve the cached difficulty data.
|
// Retrieve the cached difficulty data.
|
||||||
var difficulty:Null<SongDifficulty> = difficulties.get(diffId);
|
var variationSuffix = (variation != Constants.DEFAULT_VARIATION) ? '-$variation' : '';
|
||||||
|
var difficulty:Null<SongDifficulty> = difficulties.get('$diffId$variationSuffix');
|
||||||
if (difficulty == null)
|
if (difficulty == null)
|
||||||
{
|
{
|
||||||
trace('Fabricated new difficulty for $diffId.');
|
trace('Fabricated new difficulty for $diffId.');
|
||||||
difficulty = new SongDifficulty(this, diffId, variation);
|
difficulty = new SongDifficulty(this, diffId, variation);
|
||||||
var metadata = _metadata.get(variation);
|
var metadata = _metadata.get(variation);
|
||||||
difficulties.set(diffId, difficulty);
|
difficulties.set('$diffId$variationSuffix', difficulty);
|
||||||
|
|
||||||
if (metadata != null)
|
if (metadata != null)
|
||||||
{
|
{
|
||||||
|
@ -254,41 +256,80 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
/**
|
/**
|
||||||
* Retrieve the metadata for a specific difficulty, including the chart if it is loaded.
|
* Retrieve the metadata for a specific difficulty, including the chart if it is loaded.
|
||||||
* @param diffId The difficulty ID, such as `easy` or `hard`.
|
* @param diffId The difficulty ID, such as `easy` or `hard`.
|
||||||
|
* @param variation The variation ID to fetch the difficulty for. Or you can use `variations`.
|
||||||
|
* @param variations A list of variations to fetch the difficulty for. Looks for the first variation that exists.
|
||||||
* @return The difficulty data.
|
* @return The difficulty data.
|
||||||
*/
|
*/
|
||||||
public inline function getDifficulty(?diffId:String):Null<SongDifficulty>
|
public function getDifficulty(?diffId:String, ?variation:String, ?variations:Array<String>):Null<SongDifficulty>
|
||||||
{
|
{
|
||||||
if (diffId == null) diffId = listDifficulties()[0];
|
if (diffId == null) diffId = listDifficulties(variation)[0];
|
||||||
|
if (variation == null) variation = Constants.DEFAULT_VARIATION;
|
||||||
|
if (variations == null) variations = [variation];
|
||||||
|
|
||||||
return difficulties.get(diffId);
|
for (currentVariation in variations)
|
||||||
|
{
|
||||||
|
var variationSuffix = (currentVariation != Constants.DEFAULT_VARIATION) ? '-$currentVariation' : '';
|
||||||
|
|
||||||
|
if (difficulties.exists('$diffId$variationSuffix'))
|
||||||
|
{
|
||||||
|
return difficulties.get('$diffId$variationSuffix');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFirstValidVariation(?diffId:String, ?possibleVariations:Array<String>):Null<String>
|
||||||
|
{
|
||||||
|
if (variations == null) possibleVariations = variations;
|
||||||
|
if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0];
|
||||||
|
|
||||||
|
for (variation in variations)
|
||||||
|
{
|
||||||
|
if (difficulties.exists('$diffId-$variation')) return variation;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all the difficulties in this song.
|
* List all the difficulties in this song.
|
||||||
* @param variationId Optionally filter by variation.
|
* @param variationId Optionally filter by a single variation.
|
||||||
|
* @param variationIds Optionally filter by multiple variations.
|
||||||
* @return The list of difficulties.
|
* @return The list of difficulties.
|
||||||
*/
|
*/
|
||||||
public function listDifficulties(?variationId:String):Array<String>
|
public function listDifficulties(?variationId:String, ?variationIds:Array<String>):Array<String>
|
||||||
{
|
{
|
||||||
if (variationId == '') variationId = null;
|
if (variationIds == null) variationIds = [];
|
||||||
|
if (variationId != null) variationIds.push(variationId);
|
||||||
|
|
||||||
var diffFiltered:Array<String> = difficulties.keys().array().filter(function(diffId:String):Bool {
|
// The difficulties array contains entries like 'normal', 'nightmare-erect', and 'normal-pico',
|
||||||
if (variationId == null) return true;
|
// so we have to map it to the actual difficulty names.
|
||||||
|
// We also filter out difficulties that don't match the variation or that don't exist.
|
||||||
|
|
||||||
|
var diffFiltered:Array<String> = difficulties.keys().array().map(function(diffId:String):Null<String> {
|
||||||
var difficulty:Null<SongDifficulty> = difficulties.get(diffId);
|
var difficulty:Null<SongDifficulty> = difficulties.get(diffId);
|
||||||
if (difficulty == null) return false;
|
if (difficulty == null) return null;
|
||||||
return difficulty.variation == variationId;
|
if (variationIds.length > 0 && !variationIds.contains(difficulty.variation)) return null;
|
||||||
});
|
return difficulty.difficulty;
|
||||||
|
}).nonNull().unique();
|
||||||
|
|
||||||
diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST));
|
diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST));
|
||||||
|
|
||||||
return diffFiltered;
|
return diffFiltered;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasDifficulty(diffId:String, ?variationId:String):Bool
|
public function hasDifficulty(diffId:String, ?variationId:String, ?variationIds:Array<String>):Bool
|
||||||
{
|
{
|
||||||
if (variationId == '') variationId = null;
|
if (variationIds == null) variationIds = [];
|
||||||
var difficulty:Null<SongDifficulty> = difficulties.get(diffId);
|
if (variationId != null) variationIds.push(variationId);
|
||||||
return variationId == null ? (difficulty != null) : (difficulty != null && difficulty.variation == variationId);
|
|
||||||
|
for (targetVariation in variationIds)
|
||||||
|
{
|
||||||
|
var variationSuffix = (targetVariation != Constants.DEFAULT_VARIATION) ? '-$targetVariation' : '';
|
||||||
|
if (difficulties.exists('$diffId$variationSuffix')) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -445,12 +486,14 @@ class SongDifficulty
|
||||||
{
|
{
|
||||||
if (instrumental != '' && characters.altInstrumentals.contains(instrumental))
|
if (instrumental != '' && characters.altInstrumentals.contains(instrumental))
|
||||||
{
|
{
|
||||||
FlxG.sound.cache(Paths.inst(this.song.id, instrumental));
|
var instId = '-$instrumental';
|
||||||
|
FlxG.sound.cache(Paths.inst(this.song.id, instId));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Fallback to default instrumental.
|
// Fallback to default instrumental.
|
||||||
FlxG.sound.cache(Paths.inst(this.song.id, characters.instrumental));
|
var instId = (characters.instrumental ?? '') != '' ? '-${characters.instrumental}' : '';
|
||||||
|
FlxG.sound.cache(Paths.inst(this.song.id, instId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -492,7 +535,8 @@ class SongDifficulty
|
||||||
var suffix:String = (variation != null && variation != '' && variation != 'default') ? '-$variation' : '';
|
var suffix:String = (variation != null && variation != '' && variation != 'default') ? '-$variation' : '';
|
||||||
|
|
||||||
// Automatically resolve voices by removing suffixes.
|
// Automatically resolve voices by removing suffixes.
|
||||||
// For example, if `Voices-bf-car.ogg` does not exist, check for `Voices-bf.ogg`.
|
// For example, if `Voices-bf-car-erect.ogg` does not exist, check for `Voices-bf-erect.ogg`.
|
||||||
|
// Then, check for `Voices-bf-car.ogg`, then `Voices-bf.ogg`.
|
||||||
|
|
||||||
var playerId:String = characters.player;
|
var playerId:String = characters.player;
|
||||||
var voicePlayer:String = Paths.voices(this.song.id, '-$playerId$suffix');
|
var voicePlayer:String = Paths.voices(this.song.id, '-$playerId$suffix');
|
||||||
|
@ -504,6 +548,19 @@ class SongDifficulty
|
||||||
// Try again.
|
// Try again.
|
||||||
voicePlayer = playerId == '' ? null : Paths.voices(this.song.id, '-${playerId}$suffix');
|
voicePlayer = playerId == '' ? null : Paths.voices(this.song.id, '-${playerId}$suffix');
|
||||||
}
|
}
|
||||||
|
if (voicePlayer == null)
|
||||||
|
{
|
||||||
|
// Try again without $suffix.
|
||||||
|
playerId = characters.player;
|
||||||
|
voicePlayer = Paths.voices(this.song.id, '-${playerId}');
|
||||||
|
while (voicePlayer != null && !Assets.exists(voicePlayer))
|
||||||
|
{
|
||||||
|
// Remove the last suffix.
|
||||||
|
playerId = playerId.split('-').slice(0, -1).join('-');
|
||||||
|
// Try again.
|
||||||
|
voicePlayer = playerId == '' ? null : Paths.voices(this.song.id, '-${playerId}$suffix');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var opponentId:String = characters.opponent;
|
var opponentId:String = characters.opponent;
|
||||||
var voiceOpponent:String = Paths.voices(this.song.id, '-${opponentId}$suffix');
|
var voiceOpponent:String = Paths.voices(this.song.id, '-${opponentId}$suffix');
|
||||||
|
@ -514,6 +571,19 @@ class SongDifficulty
|
||||||
// Try again.
|
// Try again.
|
||||||
voiceOpponent = opponentId == '' ? null : Paths.voices(this.song.id, '-${opponentId}$suffix');
|
voiceOpponent = opponentId == '' ? null : Paths.voices(this.song.id, '-${opponentId}$suffix');
|
||||||
}
|
}
|
||||||
|
if (voiceOpponent == null)
|
||||||
|
{
|
||||||
|
// Try again without $suffix.
|
||||||
|
opponentId = characters.opponent;
|
||||||
|
voiceOpponent = Paths.voices(this.song.id, '-${opponentId}');
|
||||||
|
while (voiceOpponent != null && !Assets.exists(voiceOpponent))
|
||||||
|
{
|
||||||
|
// Remove the last suffix.
|
||||||
|
opponentId = opponentId.split('-').slice(0, -1).join('-');
|
||||||
|
// Try again.
|
||||||
|
voiceOpponent = opponentId == '' ? null : Paths.voices(this.song.id, '-${opponentId}$suffix');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var result:Array<String> = [];
|
var result:Array<String> = [];
|
||||||
if (voicePlayer != null) result.push(voicePlayer);
|
if (voicePlayer != null) result.push(voicePlayer);
|
||||||
|
|
|
@ -74,7 +74,7 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler
|
||||||
function handleFunctionControls():Void
|
function handleFunctionControls():Void
|
||||||
{
|
{
|
||||||
// Emergency exit button.
|
// Emergency exit button.
|
||||||
if (FlxG.keys.justPressed.F4) FlxG.switchState(new MainMenuState());
|
if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState());
|
||||||
|
|
||||||
// This can now be used in EVERY STATE YAY!
|
// This can now be used in EVERY STATE YAY!
|
||||||
if (FlxG.keys.justPressed.F5) debug_refreshModules();
|
if (FlxG.keys.justPressed.F5) debug_refreshModules();
|
||||||
|
|
|
@ -59,7 +59,7 @@ class MusicBeatSubState extends FlxTransitionableSubState implements IEventHandl
|
||||||
else if (controls.VOLUME_DOWN) FlxG.sound.changeVolume(-0.1);
|
else if (controls.VOLUME_DOWN) FlxG.sound.changeVolume(-0.1);
|
||||||
|
|
||||||
// Emergency exit button.
|
// Emergency exit button.
|
||||||
if (FlxG.keys.justPressed.F4) FlxG.switchState(new MainMenuState());
|
if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState());
|
||||||
|
|
||||||
// This can now be used in EVERY STATE YAY!
|
// This can now be used in EVERY STATE YAY!
|
||||||
if (FlxG.keys.justPressed.F5) debug_refreshModules();
|
if (FlxG.keys.justPressed.F5) debug_refreshModules();
|
||||||
|
|
|
@ -87,12 +87,12 @@ class DebugMenuSubState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
FlxTransitionableState.skipNextTransIn = true;
|
FlxTransitionableState.skipNextTransIn = true;
|
||||||
|
|
||||||
FlxG.switchState(new ChartEditorState());
|
FlxG.switchState(() -> new ChartEditorState());
|
||||||
}
|
}
|
||||||
|
|
||||||
function openAnimationEditor()
|
function openAnimationEditor()
|
||||||
{
|
{
|
||||||
FlxG.switchState(new funkin.ui.debug.anim.DebugBoundingState());
|
FlxG.switchState(() -> new funkin.ui.debug.anim.DebugBoundingState());
|
||||||
trace('Animation Editor');
|
trace('Animation Editor');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -364,7 +364,7 @@ class DebugBoundingState extends FlxState
|
||||||
|
|
||||||
if (FlxG.keys.justPressed.H) hudCam.visible = !hudCam.visible;
|
if (FlxG.keys.justPressed.H) hudCam.visible = !hudCam.visible;
|
||||||
|
|
||||||
if (FlxG.keys.justPressed.F4) FlxG.switchState(new MainMenuState());
|
if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState());
|
||||||
|
|
||||||
MouseUtil.mouseCamDrag();
|
MouseUtil.mouseCamDrag();
|
||||||
MouseUtil.mouseWheelZoom();
|
MouseUtil.mouseWheelZoom();
|
||||||
|
|
|
@ -3183,7 +3183,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
handleTestKeybinds();
|
handleTestKeybinds();
|
||||||
handleHelpKeybinds();
|
handleHelpKeybinds();
|
||||||
|
|
||||||
#if debug
|
#if (debug || FORCE_DEBUG_VERSION)
|
||||||
handleQuickWatch();
|
handleQuickWatch();
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
@ -5097,7 +5097,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
stopWelcomeMusic();
|
stopWelcomeMusic();
|
||||||
// TODO: PR Flixel to make onComplete nullable.
|
// TODO: PR Flixel to make onComplete nullable.
|
||||||
if (audioInstTrack != null) audioInstTrack.onComplete = null;
|
if (audioInstTrack != null) audioInstTrack.onComplete = null;
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
|
|
||||||
resetWindowTitle();
|
resetWindowTitle();
|
||||||
|
|
||||||
|
@ -5363,8 +5363,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
{
|
{
|
||||||
targetSong: targetSong,
|
targetSong: targetSong,
|
||||||
targetDifficulty: selectedDifficulty,
|
targetDifficulty: selectedDifficulty,
|
||||||
// TODO: Add this.
|
targetVariation: selectedVariation,
|
||||||
// targetCharacter: targetCharacter,
|
|
||||||
practiceMode: playtestPracticeMode,
|
practiceMode: playtestPracticeMode,
|
||||||
minimalMode: minimal,
|
minimalMode: minimal,
|
||||||
startTimestamp: startTimestamp,
|
startTimestamp: startTimestamp,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package funkin.ui.debug.charting.handlers;
|
package funkin.ui.debug.charting.handlers;
|
||||||
|
|
||||||
import flixel.system.FlxAssets.FlxSoundAsset;
|
import flixel.system.FlxAssets.FlxSoundAsset;
|
||||||
import flixel.system.FlxSound;
|
import flixel.sound.FlxSound;
|
||||||
import funkin.audio.VoicesGroup;
|
import funkin.audio.VoicesGroup;
|
||||||
import funkin.audio.FunkinSound;
|
import funkin.audio.FunkinSound;
|
||||||
import funkin.play.character.BaseCharacter.CharacterType;
|
import funkin.play.character.BaseCharacter.CharacterType;
|
||||||
|
|
|
@ -72,28 +72,28 @@ class ChartEditorImportExportHandler
|
||||||
{
|
{
|
||||||
state.loadInstFromAsset(Paths.inst(songId, '-$variation'), variation);
|
state.loadInstFromAsset(Paths.inst(songId, '-$variation'), variation);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (difficultyId in song.listDifficulties())
|
for (difficultyId in song.listDifficulties(variation))
|
||||||
{
|
{
|
||||||
var diff:Null<SongDifficulty> = song.getDifficulty(difficultyId);
|
var diff:Null<SongDifficulty> = song.getDifficulty(difficultyId, variation);
|
||||||
if (diff == null) continue;
|
if (diff == null) continue;
|
||||||
|
|
||||||
var instId:String = diff.variation == Constants.DEFAULT_VARIATION ? '' : diff.variation;
|
var instId:String = diff.variation == Constants.DEFAULT_VARIATION ? '' : diff.variation;
|
||||||
var voiceList:Array<String> = diff.buildVoiceList(); // SongDifficulty accounts for variation already.
|
var voiceList:Array<String> = diff.buildVoiceList(); // SongDifficulty accounts for variation already.
|
||||||
|
|
||||||
if (voiceList.length == 2)
|
if (voiceList.length == 2)
|
||||||
{
|
{
|
||||||
state.loadVocalsFromAsset(voiceList[0], diff.characters.player, instId);
|
state.loadVocalsFromAsset(voiceList[0], diff.characters.player, instId);
|
||||||
state.loadVocalsFromAsset(voiceList[1], diff.characters.opponent, instId);
|
state.loadVocalsFromAsset(voiceList[1], diff.characters.opponent, instId);
|
||||||
}
|
}
|
||||||
else if (voiceList.length == 1)
|
else if (voiceList.length == 1)
|
||||||
{
|
{
|
||||||
state.loadVocalsFromAsset(voiceList[0], diff.characters.player, instId);
|
state.loadVocalsFromAsset(voiceList[0], diff.characters.player, instId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trace('[WARN] Strange quantity of voice paths for difficulty ${difficultyId}: ${voiceList.length}');
|
trace('[WARN] Strange quantity of voice paths for difficulty ${difficultyId}: ${voiceList.length}');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -290,7 +290,7 @@ class ChartEditorFreeplayToolbox extends ChartEditorBaseToolbox
|
||||||
// waveformMusic.waveform.forceUpdate = true;
|
// waveformMusic.waveform.forceUpdate = true;
|
||||||
var perfStart = haxe.Timer.stamp();
|
var perfStart = haxe.Timer.stamp();
|
||||||
var waveformData1 = playerVoice.waveformData;
|
var waveformData1 = playerVoice.waveformData;
|
||||||
var waveformData2 = opponentVoice.waveformData;
|
var waveformData2 = opponentVoice?.waveformData ?? playerVoice.waveformData; // this null check is for songs that only have 1 vocals file!
|
||||||
var waveformData3 = chartEditorState.audioInstTrack.waveformData;
|
var waveformData3 = chartEditorState.audioInstTrack.waveformData;
|
||||||
var waveformData = waveformData1.merge(waveformData2).merge(waveformData3);
|
var waveformData = waveformData1.merge(waveformData2).merge(waveformData3);
|
||||||
trace('Waveform data merging took: ${haxe.Timer.stamp() - perfStart} seconds');
|
trace('Waveform data merging took: ${haxe.Timer.stamp() - perfStart} seconds');
|
||||||
|
|
|
@ -276,8 +276,13 @@ class ChartEditorOffsetsToolbox extends ChartEditorBaseToolbox
|
||||||
|
|
||||||
// Build opponent waveform.
|
// Build opponent waveform.
|
||||||
// waveformOpponent.waveform.forceUpdate = true;
|
// waveformOpponent.waveform.forceUpdate = true;
|
||||||
waveformOpponent.waveform.waveformData = opponentVoice.waveformData;
|
// note: if song only has one set of vocals (Vocals.ogg/mp3) then this is null and crashes charting editor
|
||||||
waveformOpponent.waveform.duration = opponentVoice.length / Constants.MS_PER_SEC;
|
// so we null check
|
||||||
|
if (opponentVoice != null)
|
||||||
|
{
|
||||||
|
waveformOpponent.waveform.waveformData = opponentVoice.waveformData;
|
||||||
|
waveformOpponent.waveform.duration = opponentVoice.length / Constants.MS_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
// Build instrumental waveform.
|
// Build instrumental waveform.
|
||||||
// waveformInstrumental.waveform.forceUpdate = true;
|
// waveformInstrumental.waveform.forceUpdate = true;
|
||||||
|
|
|
@ -54,8 +54,26 @@ import funkin.util.MathUtil;
|
||||||
import lime.app.Future;
|
import lime.app.Future;
|
||||||
import lime.utils.Assets;
|
import lime.utils.Assets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters used to initialize the FreeplayState.
|
||||||
|
*/
|
||||||
|
typedef FreeplayStateParams =
|
||||||
|
{
|
||||||
|
?character:String,
|
||||||
|
};
|
||||||
|
|
||||||
class FreeplayState extends MusicBeatSubState
|
class FreeplayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// Params
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current character for this FreeplayState.
|
||||||
|
* You can't change this without transitioning to a new FreeplayState.
|
||||||
|
*/
|
||||||
|
final currentCharacter:String;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For the audio preview, the duration of the fade-in effect.
|
* For the audio preview, the duration of the fade-in effect.
|
||||||
*/
|
*/
|
||||||
|
@ -116,6 +134,8 @@ class FreeplayState extends MusicBeatSubState
|
||||||
var ostName:FlxText;
|
var ostName:FlxText;
|
||||||
var difficultyStars:DifficultyStars;
|
var difficultyStars:DifficultyStars;
|
||||||
|
|
||||||
|
var displayedVariations:Array<String>;
|
||||||
|
|
||||||
var dj:DJBoyfriend;
|
var dj:DJBoyfriend;
|
||||||
|
|
||||||
var letterSort:LetterSort;
|
var letterSort:LetterSort;
|
||||||
|
@ -124,12 +144,13 @@ class FreeplayState extends MusicBeatSubState
|
||||||
|
|
||||||
var stickerSubState:StickerSubState;
|
var stickerSubState:StickerSubState;
|
||||||
|
|
||||||
//
|
|
||||||
static var rememberedDifficulty:Null<String> = Constants.DEFAULT_DIFFICULTY;
|
static var rememberedDifficulty:Null<String> = Constants.DEFAULT_DIFFICULTY;
|
||||||
static var rememberedSongId:Null<String> = null;
|
static var rememberedSongId:Null<String> = null;
|
||||||
|
|
||||||
public function new(?stickers:StickerSubState = null)
|
public function new(?params:FreeplayStateParams, ?stickers:StickerSubState)
|
||||||
{
|
{
|
||||||
|
currentCharacter = params?.character ?? Constants.DEFAULT_CHARACTER;
|
||||||
|
|
||||||
if (stickers != null)
|
if (stickers != null)
|
||||||
{
|
{
|
||||||
stickerSubState = stickers;
|
stickerSubState = stickers;
|
||||||
|
@ -172,6 +193,10 @@ class FreeplayState extends MusicBeatSubState
|
||||||
// Add a null entry that represents the RANDOM option
|
// Add a null entry that represents the RANDOM option
|
||||||
songs.push(null);
|
songs.push(null);
|
||||||
|
|
||||||
|
// TODO: This makes custom variations disappear from Freeplay. Figure out a better solution later.
|
||||||
|
// Default character (BF) shows default and Erect variations. Pico shows only Pico variations.
|
||||||
|
displayedVariations = (currentCharacter == "bf") ? [Constants.DEFAULT_VARIATION, "erect"] : [currentCharacter];
|
||||||
|
|
||||||
// programmatically adds the songs via LevelRegistry and SongRegistry
|
// programmatically adds the songs via LevelRegistry and SongRegistry
|
||||||
for (levelId in LevelRegistry.instance.listBaseGameLevelIds())
|
for (levelId in LevelRegistry.instance.listBaseGameLevelIds())
|
||||||
{
|
{
|
||||||
|
@ -179,9 +204,12 @@ class FreeplayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
var song:Song = SongRegistry.instance.fetchEntry(songId);
|
var song:Song = SongRegistry.instance.fetchEntry(songId);
|
||||||
|
|
||||||
songs.push(new FreeplaySongData(levelId, songId, song));
|
// Only display songs which actually have available charts for the current character.
|
||||||
|
var availableDifficultiesForSong = song.listDifficulties(displayedVariations);
|
||||||
|
if (availableDifficultiesForSong.length == 0) continue;
|
||||||
|
|
||||||
for (difficulty in song.listDifficulties())
|
songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations));
|
||||||
|
for (difficulty in availableDifficultiesForSong)
|
||||||
{
|
{
|
||||||
diffIdsTotal.pushUnique(difficulty);
|
diffIdsTotal.pushUnique(difficulty);
|
||||||
}
|
}
|
||||||
|
@ -300,6 +328,8 @@ class FreeplayState extends MusicBeatSubState
|
||||||
x: -dj.width * 1.6,
|
x: -dj.width * 1.6,
|
||||||
speed: 0.5
|
speed: 0.5
|
||||||
});
|
});
|
||||||
|
// TODO: Replace this.
|
||||||
|
if (currentCharacter == "pico") dj.visible = false;
|
||||||
add(dj);
|
add(dj);
|
||||||
|
|
||||||
var bgDad:FlxSprite = new FlxSprite(pinkBack.width * 0.75, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad'));
|
var bgDad:FlxSprite = new FlxSprite(pinkBack.width * 0.75, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad'));
|
||||||
|
@ -869,6 +899,16 @@ class FreeplayState extends MusicBeatSubState
|
||||||
changeDiff(1);
|
changeDiff(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: DEBUG REMOVE THIS
|
||||||
|
if (FlxG.keys.justPressed.P)
|
||||||
|
{
|
||||||
|
var newParams:FreeplayStateParams =
|
||||||
|
{
|
||||||
|
character: currentCharacter == "bf" ? "pico" : "bf",
|
||||||
|
};
|
||||||
|
openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.freeplay.FreeplayState(newParams, sticker)));
|
||||||
|
}
|
||||||
|
|
||||||
if (controls.BACK && !typing.hasFocus)
|
if (controls.BACK && !typing.hasFocus)
|
||||||
{
|
{
|
||||||
FlxTween.globalManager.clear();
|
FlxTween.globalManager.clear();
|
||||||
|
@ -920,7 +960,7 @@ class FreeplayState extends MusicBeatSubState
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1086,13 +1126,7 @@ class FreeplayState extends MusicBeatSubState
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var targetDifficulty:String = currentDifficulty;
|
var targetDifficulty:String = currentDifficulty;
|
||||||
|
var targetVariation:String = targetSong.getFirstValidVariation(targetDifficulty);
|
||||||
// TODO: Implement Pico into the interface properly.
|
|
||||||
var targetCharacter:String = 'bf';
|
|
||||||
if (FlxG.keys.pressed.P)
|
|
||||||
{
|
|
||||||
targetCharacter = 'pico';
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayStatePlaylist.campaignId = cap.songData.levelId;
|
PlayStatePlaylist.campaignId = cap.songData.levelId;
|
||||||
|
|
||||||
|
@ -1106,11 +1140,11 @@ class FreeplayState extends MusicBeatSubState
|
||||||
|
|
||||||
new FlxTimer().start(1, function(tmr:FlxTimer) {
|
new FlxTimer().start(1, function(tmr:FlxTimer) {
|
||||||
Paths.setCurrentLevel(cap.songData.levelId);
|
Paths.setCurrentLevel(cap.songData.levelId);
|
||||||
LoadingState.loadAndSwitchState(new PlayState(
|
LoadingState.loadAndSwitchState(() -> new PlayState(
|
||||||
{
|
{
|
||||||
targetSong: targetSong,
|
targetSong: targetSong,
|
||||||
targetDifficulty: targetDifficulty,
|
targetDifficulty: targetDifficulty,
|
||||||
targetCharacter: targetCharacter,
|
targetVariation: targetVariation,
|
||||||
}), true);
|
}), true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1275,31 +1309,33 @@ class FreeplaySongData
|
||||||
public var songRating(default, null):Int = 0;
|
public var songRating(default, null):Int = 0;
|
||||||
|
|
||||||
public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY;
|
public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY;
|
||||||
|
public var displayedVariations(default, null):Array<String> = [Constants.DEFAULT_VARIATION];
|
||||||
|
|
||||||
function set_currentDifficulty(value:String):String
|
function set_currentDifficulty(value:String):String
|
||||||
{
|
{
|
||||||
if (currentDifficulty == value) return value;
|
if (currentDifficulty == value) return value;
|
||||||
|
|
||||||
currentDifficulty = value;
|
currentDifficulty = value;
|
||||||
updateValues();
|
updateValues(displayedVariations);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function new(levelId:String, songId:String, song:Song)
|
public function new(levelId:String, songId:String, song:Song, ?displayedVariations:Array<String>)
|
||||||
{
|
{
|
||||||
this.levelId = levelId;
|
this.levelId = levelId;
|
||||||
this.songId = songId;
|
this.songId = songId;
|
||||||
this.song = song;
|
this.song = song;
|
||||||
|
if (displayedVariations != null) this.displayedVariations = displayedVariations;
|
||||||
|
|
||||||
updateValues();
|
updateValues(displayedVariations);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateValues():Void
|
function updateValues(displayedVariations:Array<String>):Void
|
||||||
{
|
{
|
||||||
this.songDifficulties = song.listDifficulties();
|
this.songDifficulties = song.listDifficulties(displayedVariations);
|
||||||
if (!this.songDifficulties.contains(currentDifficulty)) currentDifficulty = Constants.DEFAULT_DIFFICULTY;
|
if (!this.songDifficulties.contains(currentDifficulty)) currentDifficulty = Constants.DEFAULT_DIFFICULTY;
|
||||||
|
|
||||||
var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty);
|
var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, displayedVariations);
|
||||||
if (songDifficulty == null) return;
|
if (songDifficulty == null) return;
|
||||||
this.songName = songDifficulty.songName;
|
this.songName = songDifficulty.songName;
|
||||||
this.songCharacter = songDifficulty.characters.opponent;
|
this.songCharacter = songDifficulty.characters.opponent;
|
||||||
|
|
|
@ -45,7 +45,7 @@ class HaxeUISubState extends MusicBeatSubState
|
||||||
super.update(elapsed);
|
super.update(elapsed);
|
||||||
|
|
||||||
// Force quit.
|
// Force quit.
|
||||||
if (FlxG.keys.justPressed.F4) FlxG.switchState(new MainMenuState());
|
if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState());
|
||||||
|
|
||||||
// Refresh the component.
|
// Refresh the component.
|
||||||
if (FlxG.keys.justPressed.F5)
|
if (FlxG.keys.justPressed.F5)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import flixel.FlxState;
|
||||||
import flixel.addons.transition.FlxTransitionableState;
|
import flixel.addons.transition.FlxTransitionableState;
|
||||||
import flixel.effects.FlxFlicker;
|
import flixel.effects.FlxFlicker;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
||||||
|
import flixel.util.typeLimit.NextState;
|
||||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||||
import flixel.input.touch.FlxTouch;
|
import flixel.input.touch.FlxTouch;
|
||||||
import flixel.text.FlxText;
|
import flixel.text.FlxText;
|
||||||
|
@ -94,7 +95,7 @@ class MainMenuState extends MusicBeatState
|
||||||
});
|
});
|
||||||
|
|
||||||
menuItems.enabled = true; // can move on intro
|
menuItems.enabled = true; // can move on intro
|
||||||
createMenuItem('storymode', 'mainmenu/storymode', function() startExitState(new StoryMenuState()));
|
createMenuItem('storymode', 'mainmenu/storymode', function() startExitState(() -> new StoryMenuState()));
|
||||||
createMenuItem('freeplay', 'mainmenu/freeplay', function() {
|
createMenuItem('freeplay', 'mainmenu/freeplay', function() {
|
||||||
persistentDraw = true;
|
persistentDraw = true;
|
||||||
persistentUpdate = false;
|
persistentUpdate = false;
|
||||||
|
@ -110,7 +111,7 @@ class MainMenuState extends MusicBeatState
|
||||||
#end
|
#end
|
||||||
|
|
||||||
createMenuItem('options', 'mainmenu/options', function() {
|
createMenuItem('options', 'mainmenu/options', function() {
|
||||||
startExitState(new funkin.ui.options.OptionsState());
|
startExitState(() -> new funkin.ui.options.OptionsState());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reset position of menu items.
|
// Reset position of menu items.
|
||||||
|
@ -255,7 +256,7 @@ class MainMenuState extends MusicBeatState
|
||||||
openSubState(prompt);
|
openSubState(prompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
function startExitState(state:FlxState)
|
function startExitState(state:NextState)
|
||||||
{
|
{
|
||||||
menuItems.enabled = false; // disable for exit
|
menuItems.enabled = false; // disable for exit
|
||||||
var duration = 0.4;
|
var duration = 0.4;
|
||||||
|
@ -313,7 +314,7 @@ class MainMenuState extends MusicBeatState
|
||||||
if (controls.BACK && menuItems.enabled && !menuItems.busy)
|
if (controls.BACK && menuItems.enabled && !menuItems.busy)
|
||||||
{
|
{
|
||||||
FlxG.sound.play(Paths.sound('cancelMenu'));
|
FlxG.sound.play(Paths.sound('cancelMenu'));
|
||||||
FlxG.switchState(new TitleState());
|
FlxG.switchState(() -> new TitleState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ class OptionsState extends MusicBeatState
|
||||||
{
|
{
|
||||||
currentPage.enabled = false;
|
currentPage.enabled = false;
|
||||||
// TODO: Animate this transition?
|
// TODO: Animate this transition?
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,8 @@ class Level implements IRegistryEntry<LevelData>
|
||||||
|
|
||||||
if (firstSong != null)
|
if (firstSong != null)
|
||||||
{
|
{
|
||||||
for (difficulty in firstSong.listDifficulties())
|
// Don't display alternate characters in Story Mode.
|
||||||
|
for (difficulty in firstSong.listDifficulties([Constants.DEFAULT_VARIATION, "erect"]))
|
||||||
{
|
{
|
||||||
difficulties.push(difficulty);
|
difficulties.push(difficulty);
|
||||||
}
|
}
|
||||||
|
@ -168,7 +169,7 @@ class Level implements IRegistryEntry<LevelData>
|
||||||
|
|
||||||
for (difficulty in difficulties)
|
for (difficulty in difficulties)
|
||||||
{
|
{
|
||||||
if (!song.hasDifficulty(difficulty))
|
if (!song.hasDifficulty(difficulty, [Constants.DEFAULT_VARIATION, "erect"]))
|
||||||
{
|
{
|
||||||
difficulties.remove(difficulty);
|
difficulties.remove(difficulty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -397,7 +397,7 @@ class StoryMenuState extends MusicBeatState
|
||||||
{
|
{
|
||||||
FlxG.sound.play(Paths.sound('cancelMenu'));
|
FlxG.sound.play(Paths.sound('cancelMenu'));
|
||||||
exitingMenu = true;
|
exitingMenu = true;
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +565,7 @@ class StoryMenuState extends MusicBeatState
|
||||||
FlxTransitionableState.skipNextTransIn = false;
|
FlxTransitionableState.skipNextTransIn = false;
|
||||||
FlxTransitionableState.skipNextTransOut = false;
|
FlxTransitionableState.skipNextTransOut = false;
|
||||||
|
|
||||||
LoadingState.loadAndSwitchState(new PlayState(
|
LoadingState.loadAndSwitchState(() -> new PlayState(
|
||||||
{
|
{
|
||||||
targetSong: targetSong,
|
targetSong: targetSong,
|
||||||
targetDifficulty: PlayStatePlaylist.campaignDifficulty,
|
targetDifficulty: PlayStatePlaylist.campaignDifficulty,
|
||||||
|
|
|
@ -105,6 +105,6 @@ class AttractState extends MusicBeatState
|
||||||
vid.destroy();
|
vid.destroy();
|
||||||
vid = null;
|
vid = null;
|
||||||
|
|
||||||
FlxG.switchState(new TitleState());
|
FlxG.switchState(() -> new TitleState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ class OutdatedSubState extends MusicBeatState
|
||||||
if (controls.BACK)
|
if (controls.BACK)
|
||||||
{
|
{
|
||||||
leftState = true;
|
leftState = true;
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
}
|
}
|
||||||
super.update(elapsed);
|
super.update(elapsed);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import flixel.tweens.FlxTween;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import flixel.util.FlxDirectionFlags;
|
import flixel.util.FlxDirectionFlags;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
|
import flixel.util.typeLimit.NextState;
|
||||||
import funkin.audio.visualize.SpectogramSprite;
|
import funkin.audio.visualize.SpectogramSprite;
|
||||||
import funkin.graphics.shaders.ColorSwap;
|
import funkin.graphics.shaders.ColorSwap;
|
||||||
import funkin.graphics.shaders.LeftMaskShader;
|
import funkin.graphics.shaders.LeftMaskShader;
|
||||||
|
@ -213,7 +214,7 @@ class TitleState extends MusicBeatState
|
||||||
*/
|
*/
|
||||||
function moveToAttract():Void
|
function moveToAttract():Void
|
||||||
{
|
{
|
||||||
FlxG.switchState(new AttractState());
|
FlxG.switchState(() -> new AttractState());
|
||||||
}
|
}
|
||||||
|
|
||||||
function playMenuMusic():Void
|
function playMenuMusic():Void
|
||||||
|
@ -294,7 +295,7 @@ class TitleState extends MusicBeatState
|
||||||
{
|
{
|
||||||
if (touch.justPressed)
|
if (touch.justPressed)
|
||||||
{
|
{
|
||||||
FlxG.switchState(new FreeplayState());
|
FlxG.switchState(() -> new FreeplayState());
|
||||||
pressedEnter = true;
|
pressedEnter = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,7 +314,7 @@ class TitleState extends MusicBeatState
|
||||||
// If you spam Enter, we should skip the transition.
|
// If you spam Enter, we should skip the transition.
|
||||||
if (pressedEnter && transitioning && skippedIntro)
|
if (pressedEnter && transitioning && skippedIntro)
|
||||||
{
|
{
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressedEnter && !transitioning && skippedIntro)
|
if (pressedEnter && !transitioning && skippedIntro)
|
||||||
|
@ -328,7 +329,7 @@ class TitleState extends MusicBeatState
|
||||||
FlxG.sound.play(Paths.sound('confirmMenu'), 0.7);
|
FlxG.sound.play(Paths.sound('confirmMenu'), 0.7);
|
||||||
transitioning = true;
|
transitioning = true;
|
||||||
|
|
||||||
var targetState:FlxState = new MainMenuState();
|
var targetState:NextState = () -> new MainMenuState();
|
||||||
|
|
||||||
new FlxTimer().start(2, function(tmr:FlxTimer) {
|
new FlxTimer().start(2, function(tmr:FlxTimer) {
|
||||||
// These assets are very unlikely to be used for the rest of gameplay, so it unloads them from cache/memory
|
// These assets are very unlikely to be used for the rest of gameplay, so it unloads them from cache/memory
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package funkin.ui.transition;
|
package funkin.ui.transition;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxState;
|
|
||||||
import flixel.math.FlxMath;
|
import flixel.math.FlxMath;
|
||||||
import flixel.tweens.FlxEase;
|
import flixel.tweens.FlxEase;
|
||||||
import flixel.tweens.FlxTween;
|
import flixel.tweens.FlxTween;
|
||||||
|
@ -21,12 +20,13 @@ import lime.utils.AssetManifest;
|
||||||
import lime.utils.Assets as LimeAssets;
|
import lime.utils.Assets as LimeAssets;
|
||||||
import openfl.filters.ShaderFilter;
|
import openfl.filters.ShaderFilter;
|
||||||
import openfl.utils.Assets;
|
import openfl.utils.Assets;
|
||||||
|
import flixel.util.typeLimit.NextState;
|
||||||
|
|
||||||
class LoadingState extends MusicBeatState
|
class LoadingState extends MusicBeatState
|
||||||
{
|
{
|
||||||
inline static var MIN_TIME = 1.0;
|
inline static var MIN_TIME = 1.0;
|
||||||
|
|
||||||
var target:FlxState;
|
var target:NextState;
|
||||||
var stopMusic = false;
|
var stopMusic = false;
|
||||||
var callbacks:MultiCallback;
|
var callbacks:MultiCallback;
|
||||||
var danceLeft = false;
|
var danceLeft = false;
|
||||||
|
@ -34,7 +34,7 @@ class LoadingState extends MusicBeatState
|
||||||
var loadBar:FlxSprite;
|
var loadBar:FlxSprite;
|
||||||
var funkay:FlxSprite;
|
var funkay:FlxSprite;
|
||||||
|
|
||||||
function new(target:FlxState, stopMusic:Bool)
|
function new(target:NextState, stopMusic:Bool)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
@ -172,12 +172,12 @@ class LoadingState extends MusicBeatState
|
||||||
return Paths.inst(PlayState.instance.currentSong.id);
|
return Paths.inst(PlayState.instance.currentSong.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static public function loadAndSwitchState(nextState:FlxState, shouldStopMusic = false):Void
|
inline static public function loadAndSwitchState(nextState:NextState, shouldStopMusic = false):Void
|
||||||
{
|
{
|
||||||
FlxG.switchState(getNextState(nextState, shouldStopMusic));
|
FlxG.switchState(getNextState(nextState, shouldStopMusic));
|
||||||
}
|
}
|
||||||
|
|
||||||
static function getNextState(nextState:FlxState, shouldStopMusic = false):FlxState
|
static function getNextState(nextState:NextState, shouldStopMusic = false):NextState
|
||||||
{
|
{
|
||||||
Paths.setCurrentLevel(PlayStatePlaylist.campaignId);
|
Paths.setCurrentLevel(PlayStatePlaylist.campaignId);
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ class LoadingState extends MusicBeatState
|
||||||
// && (!PlayState.currentSong.needsVoices || isSoundLoaded(getVocalPath()))
|
// && (!PlayState.currentSong.needsVoices || isSoundLoaded(getVocalPath()))
|
||||||
// && isLibraryLoaded('shared');
|
// && isLibraryLoaded('shared');
|
||||||
//
|
//
|
||||||
if (true) return new LoadingState(nextState, shouldStopMusic);
|
if (true) return () -> new LoadingState(nextState, shouldStopMusic);
|
||||||
#end
|
#end
|
||||||
if (shouldStopMusic && FlxG.sound.music != null) FlxG.sound.music.stop();
|
if (shouldStopMusic && FlxG.sound.music != null) FlxG.sound.music.stop();
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ class MultiCallback
|
||||||
public function getUnfired():Array<Void->Void>
|
public function getUnfired():Array<Void->Void>
|
||||||
return unfired.array();
|
return unfired.array();
|
||||||
|
|
||||||
public static function coolSwitchState(state:FlxState, transitionTex:String = "shaderTransitionStuff/coolDots", time:Float = 2)
|
public static function coolSwitchState(state:NextState, transitionTex:String = "shaderTransitionStuff/coolDots", time:Float = 2)
|
||||||
{
|
{
|
||||||
var screenShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("shaderTransitionStuff/coolDots"));
|
var screenShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("shaderTransitionStuff/coolDots"));
|
||||||
var screenWipeShit:ScreenWipeShader = new ScreenWipeShader();
|
var screenWipeShit:ScreenWipeShader = new ScreenWipeShader();
|
||||||
|
@ -343,9 +343,9 @@ class MultiCallback
|
||||||
ease: FlxEase.quadInOut,
|
ease: FlxEase.quadInOut,
|
||||||
onComplete: function(twn) {
|
onComplete: function(twn) {
|
||||||
screenShit.destroy();
|
screenShit.destroy();
|
||||||
FlxG.switchState(new MainMenuState());
|
FlxG.switchState(state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
FlxG.camera.setFilters([new ShaderFilter(screenWipeShit)]);
|
FlxG.camera.filters = [new ShaderFilter(screenWipeShit)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import funkin.ui.freeplay.FreeplayState;
|
||||||
import openfl.geom.Matrix;
|
import openfl.geom.Matrix;
|
||||||
import openfl.display.Sprite;
|
import openfl.display.Sprite;
|
||||||
import openfl.display.Bitmap;
|
import openfl.display.Bitmap;
|
||||||
|
import flixel.FlxState;
|
||||||
|
|
||||||
using Lambda;
|
using Lambda;
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
@ -30,7 +31,12 @@ class StickerSubState extends MusicBeatSubState
|
||||||
// yes... a damn OpenFL sprite!!!
|
// yes... a damn OpenFL sprite!!!
|
||||||
public var dipshit:Sprite;
|
public var dipshit:Sprite;
|
||||||
|
|
||||||
var nextState:NEXTSTATE = FREEPLAY;
|
/**
|
||||||
|
* The state to switch to after the stickers are done.
|
||||||
|
* This is a FUNCTION so we can pass it directly to `FlxG.switchState()`,
|
||||||
|
* and we can add constructor parameters in the caller.
|
||||||
|
*/
|
||||||
|
var targetState:StickerSubState->FlxState;
|
||||||
|
|
||||||
// what "folders" to potentially load from (as of writing only "keys" exist)
|
// what "folders" to potentially load from (as of writing only "keys" exist)
|
||||||
var soundSelections:Array<String> = [];
|
var soundSelections:Array<String> = [];
|
||||||
|
@ -38,10 +44,12 @@ class StickerSubState extends MusicBeatSubState
|
||||||
var soundSelection:String = "";
|
var soundSelection:String = "";
|
||||||
var sounds:Array<String> = [];
|
var sounds:Array<String> = [];
|
||||||
|
|
||||||
public function new(?oldStickers:Array<StickerSprite>, ?nextState:NEXTSTATE = FREEPLAY):Void
|
public function new(?oldStickers:Array<StickerSprite>, ?targetState:StickerSubState->FlxState):Void
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.targetState = (targetState == null) ? ((sticker) -> new MainMenuState()) : targetState;
|
||||||
|
|
||||||
// todo still
|
// todo still
|
||||||
// make sure that ONLY plays mp3/ogg files
|
// make sure that ONLY plays mp3/ogg files
|
||||||
// if there's no mp3/ogg file, then it regenerates/reloads the random folder
|
// if there's no mp3/ogg file, then it regenerates/reloads the random folder
|
||||||
|
@ -84,10 +92,6 @@ class StickerSubState extends MusicBeatSubState
|
||||||
|
|
||||||
trace(sounds);
|
trace(sounds);
|
||||||
|
|
||||||
// trace(assetsInList);
|
|
||||||
|
|
||||||
this.nextState = nextState;
|
|
||||||
|
|
||||||
grpStickers = new FlxTypedGroup<StickerSprite>();
|
grpStickers = new FlxTypedGroup<StickerSprite>();
|
||||||
add(grpStickers);
|
add(grpStickers);
|
||||||
|
|
||||||
|
@ -241,20 +245,8 @@ class StickerSubState extends MusicBeatSubState
|
||||||
dipshit.addChild(bitmap);
|
dipshit.addChild(bitmap);
|
||||||
FlxG.addChildBelowMouse(dipshit);
|
FlxG.addChildBelowMouse(dipshit);
|
||||||
|
|
||||||
switch (nextState)
|
FlxG.switchState(() -> targetState(this));
|
||||||
{
|
|
||||||
case FREEPLAY:
|
|
||||||
FlxG.switchState(new FreeplayState(this));
|
|
||||||
case STORY:
|
|
||||||
FlxG.switchState(new StoryMenuState(this));
|
|
||||||
case MAIN_MENU:
|
|
||||||
FlxG.switchState(new MainMenuState());
|
|
||||||
default:
|
|
||||||
FlxG.switchState(new MainMenuState());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sticky.angle *= FlxG.random.float(0, 0.05);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -368,10 +360,3 @@ typedef StickerShit =
|
||||||
stickers:Map<String, Array<String>>,
|
stickers:Map<String, Array<String>>,
|
||||||
stickerPacks:Map<String, Array<String>>
|
stickerPacks:Map<String, Array<String>>
|
||||||
}
|
}
|
||||||
|
|
||||||
enum abstract NEXTSTATE(String)
|
|
||||||
{
|
|
||||||
var MAIN_MENU = 'mainmenu';
|
|
||||||
var FREEPLAY = 'freeplay';
|
|
||||||
var STORY = 'story';
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class EvacuateDebugPlugin extends FlxBasic
|
||||||
|
|
||||||
if (FlxG.keys.justPressed.F4)
|
if (FlxG.keys.justPressed.F4)
|
||||||
{
|
{
|
||||||
FlxG.switchState(new funkin.ui.mainmenu.MainMenuState());
|
FlxG.switchState(() -> new funkin.ui.mainmenu.MainMenuState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,24 @@ class ArrayTools
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a copy of the array with all `null` elements removed.
|
||||||
|
* @param array The array to remove `null` elements from.
|
||||||
|
* @return A copy of the array with all `null` elements removed.
|
||||||
|
*/
|
||||||
|
public static function nonNull<T>(array:Array<Null<T>>):Array<T>
|
||||||
|
{
|
||||||
|
var result:Array<T> = [];
|
||||||
|
for (element in array)
|
||||||
|
{
|
||||||
|
if (element != null)
|
||||||
|
{
|
||||||
|
result.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the first element of the array that satisfies the predicate, or null if none do.
|
* Return the first element of the array that satisfies the predicate, or null if none do.
|
||||||
* @param input The array to search
|
* @param input The array to search
|
||||||
|
|
|
@ -18,9 +18,9 @@ class Int64Tools
|
||||||
|
|
||||||
public static function toFloat(i:Int64):Float
|
public static function toFloat(i:Int64):Float
|
||||||
{
|
{
|
||||||
var f:Float = Int64.getLow(i);
|
var f:Float = i.low;
|
||||||
if (f < 0) f += MAX_32_PRECISION;
|
if (f < 0) f += MAX_32_PRECISION;
|
||||||
return (Int64.getHigh(i) * MAX_32_PRECISION + f);
|
return (i.high * MAX_32_PRECISION + f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isToIntSafe(i:Int64):Bool
|
public static function isToIntSafe(i:Int64):Bool
|
||||||
|
|
Loading…
Reference in a new issue