mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-14 19:25:16 -05:00
Merge branch 'rewrite/master' into bugfix/two-fixes
This commit is contained in:
commit
9d3131bc8d
34 changed files with 840 additions and 390 deletions
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
@ -111,6 +111,11 @@
|
||||||
"target": "hl",
|
"target": "hl",
|
||||||
"args": ["-debug"]
|
"args": ["-debug"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Windows / Debug (Discord)",
|
||||||
|
"target": "windows",
|
||||||
|
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS", "-DFEATURE_DISCORD_RPC"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Windows / Debug (FlxAnimate Test)",
|
"label": "Windows / Debug (FlxAnimate Test)",
|
||||||
"target": "windows",
|
"target": "windows",
|
||||||
|
|
|
@ -19,7 +19,7 @@ Please check out our [Contributor's guide](./CONTRIBUTORS.md) on how you can act
|
||||||
|
|
||||||
# Credits and Special Thanks
|
# Credits and Special Thanks
|
||||||
|
|
||||||
Full credits can be found in-game, or wherever the credits.json file is.
|
Full credits can be found in-game, or in the `credits.json` file which is located [here](https://github.com/FunkinCrew/funkin.assets/blob/main/exclude/data/credits.json).
|
||||||
|
|
||||||
## Programming
|
## Programming
|
||||||
- [ninjamuffin99](https://twitter.com/ninja_muffin99) - Lead Programmer
|
- [ninjamuffin99](https://twitter.com/ninja_muffin99) - Lead Programmer
|
||||||
|
|
2
art
2
art
|
@ -1 +1 @@
|
||||||
Subproject commit 1f64f3e7403a090b164f4442d10152b2be5d3d0a
|
Subproject commit fbd3e3df77734606d88516770b71b56e6fa04bce
|
2
assets
2
assets
|
@ -1 +1 @@
|
||||||
Subproject commit 8140f8255c0db78135dbfa7b6d329f52c363f51b
|
Subproject commit b2404b6b1cba47da8eef4910f49985d54318186b
|
|
@ -6,7 +6,7 @@
|
||||||
"name": "EliteMasterEric"
|
"name": "EliteMasterEric"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"api_version": "0.1.0",
|
"api_version": "0.5.0",
|
||||||
"mod_version": "1.0.0",
|
"mod_version": "1.0.0",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
}
|
}
|
||||||
|
|
14
hmm.json
14
hmm.json
|
@ -7,13 +7,6 @@
|
||||||
"ref": "a1eab7b9bf507b87200a3341719054fe427f3b15",
|
"ref": "a1eab7b9bf507b87200a3341719054fe427f3b15",
|
||||||
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
|
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "discord_rpc",
|
|
||||||
"type": "git",
|
|
||||||
"dir": null,
|
|
||||||
"ref": "2d83fa863ef0c1eace5f1cf67c3ac315d1a3a8a5",
|
|
||||||
"url": "https://github.com/FunkinCrew/linc_discord-rpc"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "flixel",
|
"name": "flixel",
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -108,6 +101,13 @@
|
||||||
"ref": "147294123f983e35f50a966741474438069a7a8f",
|
"ref": "147294123f983e35f50a966741474438069a7a8f",
|
||||||
"url": "https://github.com/FunkinCrew/hxcpp-debugger"
|
"url": "https://github.com/FunkinCrew/hxcpp-debugger"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "hxdiscord_rpc",
|
||||||
|
"type": "git",
|
||||||
|
"dir": null,
|
||||||
|
"ref": "82c47ecc1a454b7dd644e4fcac7e91155f176dec",
|
||||||
|
"url": "https://github.com/FunkinCrew/hxdiscord_rpc"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "hxjsonast",
|
"name": "hxjsonast",
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
17
project.hxp
17
project.hxp
|
@ -214,6 +214,12 @@ class Project extends HXProject {
|
||||||
*/
|
*/
|
||||||
static final FEATURE_OPEN_URL:FeatureFlag = "FEATURE_OPEN_URL";
|
static final FEATURE_OPEN_URL:FeatureFlag = "FEATURE_OPEN_URL";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `-DFEATURE_SCREENSHOTS`
|
||||||
|
* If this flag is enabled, the game will support the screenshots feature.
|
||||||
|
*/
|
||||||
|
static final FEATURE_SCREENSHOTS:FeatureFlag = "FEATURE_SCREENSHOTS";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `-DFEATURE_CHART_EDITOR`
|
* `-DFEATURE_CHART_EDITOR`
|
||||||
* If this flag is enabled, the Chart Editor will be accessible from the debug menu.
|
* If this flag is enabled, the Chart Editor will be accessible from the debug menu.
|
||||||
|
@ -473,10 +479,9 @@ class Project extends HXProject {
|
||||||
// Should default to true on workspace builds and false on release builds.
|
// Should default to true on workspace builds and false on release builds.
|
||||||
REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop());
|
REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop());
|
||||||
|
|
||||||
// Should be true on release, non-tester builds.
|
// Should be true on desktop, release, non-tester builds.
|
||||||
// We don't want testers to accidentally leak songs to their Discord friends!
|
// We don't want testers to accidentally leak songs to their Discord friends!
|
||||||
// TODO: Re-enable this.
|
FEATURE_DISCORD_RPC.apply(this, isDesktop() && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
|
||||||
FEATURE_DISCORD_RPC.apply(this, false && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this));
|
|
||||||
|
|
||||||
// Should be true only on web builds.
|
// Should be true only on web builds.
|
||||||
// Audio context issues only exist there.
|
// Audio context issues only exist there.
|
||||||
|
@ -494,6 +499,10 @@ class Project extends HXProject {
|
||||||
// Should be true except on web builds.
|
// Should be true except on web builds.
|
||||||
// Chart editor doesn't work there.
|
// Chart editor doesn't work there.
|
||||||
FEATURE_CHART_EDITOR.apply(this, !isWeb());
|
FEATURE_CHART_EDITOR.apply(this, !isWeb());
|
||||||
|
|
||||||
|
// Should be true except on web builds.
|
||||||
|
// Screenshots doesn't work there.
|
||||||
|
FEATURE_SCREENSHOTS.apply(this, !isWeb());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -644,7 +653,7 @@ class Project extends HXProject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FEATURE_DISCORD_RPC.isEnabled(this)) {
|
if (FEATURE_DISCORD_RPC.isEnabled(this)) {
|
||||||
addHaxelib('discord_rpc'); // Discord API
|
addHaxelib('hxdiscord_rpc'); // Discord API
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FEATURE_NEWGROUNDS.isEnabled(this)) {
|
if (FEATURE_NEWGROUNDS.isEnabled(this)) {
|
||||||
|
|
|
@ -1,42 +1,42 @@
|
||||||
package funkin;
|
package funkin;
|
||||||
|
|
||||||
import funkin.data.freeplay.player.PlayerRegistry;
|
|
||||||
import funkin.ui.debug.charting.ChartEditorState;
|
|
||||||
import funkin.ui.transition.LoadingState;
|
|
||||||
import flixel.FlxState;
|
|
||||||
import flixel.addons.transition.FlxTransitionableState;
|
import flixel.addons.transition.FlxTransitionableState;
|
||||||
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
|
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
|
||||||
import flixel.addons.transition.TransitionData;
|
import flixel.addons.transition.TransitionData;
|
||||||
|
import flixel.FlxSprite;
|
||||||
|
import flixel.FlxState;
|
||||||
import flixel.graphics.FlxGraphic;
|
import flixel.graphics.FlxGraphic;
|
||||||
import flixel.math.FlxPoint;
|
import flixel.math.FlxPoint;
|
||||||
import flixel.math.FlxRect;
|
import flixel.math.FlxRect;
|
||||||
import flixel.FlxSprite;
|
|
||||||
import flixel.system.debug.log.LogStyle;
|
import flixel.system.debug.log.LogStyle;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import funkin.util.macro.MacroUtil;
|
|
||||||
import funkin.util.WindowUtil;
|
|
||||||
import funkin.play.PlayStatePlaylist;
|
|
||||||
import openfl.display.BitmapData;
|
|
||||||
import funkin.data.story.level.LevelRegistry;
|
|
||||||
import funkin.data.notestyle.NoteStyleRegistry;
|
|
||||||
import funkin.data.freeplay.style.FreeplayStyleRegistry;
|
|
||||||
import funkin.data.event.SongEventRegistry;
|
|
||||||
import funkin.data.stage.StageRegistry;
|
|
||||||
import funkin.data.dialogue.conversation.ConversationRegistry;
|
import funkin.data.dialogue.conversation.ConversationRegistry;
|
||||||
import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry;
|
import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry;
|
||||||
import funkin.data.dialogue.speaker.SpeakerRegistry;
|
import funkin.data.dialogue.speaker.SpeakerRegistry;
|
||||||
import funkin.data.freeplay.album.AlbumRegistry;
|
import funkin.data.freeplay.album.AlbumRegistry;
|
||||||
|
import funkin.data.freeplay.player.PlayerRegistry;
|
||||||
|
import funkin.data.freeplay.style.FreeplayStyleRegistry;
|
||||||
|
import funkin.data.notestyle.NoteStyleRegistry;
|
||||||
import funkin.data.song.SongRegistry;
|
import funkin.data.song.SongRegistry;
|
||||||
|
import funkin.data.event.SongEventRegistry;
|
||||||
|
import funkin.data.stage.StageRegistry;
|
||||||
|
import funkin.data.story.level.LevelRegistry;
|
||||||
|
import funkin.modding.module.ModuleHandler;
|
||||||
import funkin.play.character.CharacterData.CharacterDataParser;
|
import funkin.play.character.CharacterData.CharacterDataParser;
|
||||||
import funkin.play.notes.notekind.NoteKindManager;
|
import funkin.play.notes.notekind.NoteKindManager;
|
||||||
import funkin.modding.module.ModuleHandler;
|
import funkin.play.PlayStatePlaylist;
|
||||||
|
import funkin.ui.debug.charting.ChartEditorState;
|
||||||
import funkin.ui.title.TitleState;
|
import funkin.ui.title.TitleState;
|
||||||
|
import funkin.ui.transition.LoadingState;
|
||||||
import funkin.util.CLIUtil;
|
import funkin.util.CLIUtil;
|
||||||
import funkin.util.CLIUtil.CLIParams;
|
import funkin.util.CLIUtil.CLIParams;
|
||||||
|
import funkin.util.macro.MacroUtil;
|
||||||
import funkin.util.TimerUtil;
|
import funkin.util.TimerUtil;
|
||||||
import funkin.util.TrackerUtil;
|
import funkin.util.TrackerUtil;
|
||||||
|
import funkin.util.WindowUtil;
|
||||||
|
import openfl.display.BitmapData;
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
import Discord.DiscordClient;
|
import funkin.api.discord.DiscordClient;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,10 +125,10 @@ class InitState extends FlxState
|
||||||
// DISCORD API SETUP
|
// DISCORD API SETUP
|
||||||
//
|
//
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
DiscordClient.initialize();
|
DiscordClient.instance.init();
|
||||||
|
|
||||||
Application.current.onExit.add(function(exitCode) {
|
lime.app.Application.current.onExit.add(function(exitCode) {
|
||||||
DiscordClient.shutdown();
|
DiscordClient.instance.shutdown();
|
||||||
});
|
});
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
@ -148,10 +148,12 @@ class InitState extends FlxState
|
||||||
#if FEATURE_DEBUG_FUNCTIONS
|
#if FEATURE_DEBUG_FUNCTIONS
|
||||||
funkin.util.plugins.MemoryGCPlugin.initialize();
|
funkin.util.plugins.MemoryGCPlugin.initialize();
|
||||||
#end
|
#end
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
|
funkin.util.plugins.ScreenshotPlugin.initialize();
|
||||||
|
#end
|
||||||
funkin.util.plugins.EvacuateDebugPlugin.initialize();
|
funkin.util.plugins.EvacuateDebugPlugin.initialize();
|
||||||
funkin.util.plugins.ForceCrashPlugin.initialize();
|
funkin.util.plugins.ForceCrashPlugin.initialize();
|
||||||
funkin.util.plugins.ReloadAssetsDebugPlugin.initialize();
|
funkin.util.plugins.ReloadAssetsDebugPlugin.initialize();
|
||||||
funkin.util.plugins.ScreenshotPlugin.initialize();
|
|
||||||
funkin.util.plugins.VolumePlugin.initialize();
|
funkin.util.plugins.VolumePlugin.initialize();
|
||||||
funkin.util.plugins.WatchPlugin.initialize();
|
funkin.util.plugins.WatchPlugin.initialize();
|
||||||
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
package funkin.api.discord;
|
|
||||||
|
|
||||||
import Sys.sleep;
|
|
||||||
#if FEATURE_DISCORD_RPC
|
|
||||||
import discord_rpc.DiscordRpc;
|
|
||||||
#end
|
|
||||||
|
|
||||||
class DiscordClient
|
|
||||||
{
|
|
||||||
#if FEATURE_DISCORD_RPC
|
|
||||||
public function new()
|
|
||||||
{
|
|
||||||
trace("Discord Client starting...");
|
|
||||||
DiscordRpc.start(
|
|
||||||
{
|
|
||||||
clientID: "814588678700924999",
|
|
||||||
onReady: onReady,
|
|
||||||
onError: onError,
|
|
||||||
onDisconnected: onDisconnected
|
|
||||||
});
|
|
||||||
trace("Discord Client started.");
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
DiscordRpc.process();
|
|
||||||
sleep(2);
|
|
||||||
// trace("Discord Client Update");
|
|
||||||
}
|
|
||||||
|
|
||||||
DiscordRpc.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function shutdown()
|
|
||||||
{
|
|
||||||
DiscordRpc.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
static function onReady()
|
|
||||||
{
|
|
||||||
DiscordRpc.presence(
|
|
||||||
{
|
|
||||||
details: "In the Menus",
|
|
||||||
state: null,
|
|
||||||
largeImageKey: 'icon',
|
|
||||||
largeImageText: "Friday Night Funkin'"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static function onError(_code:Int, _message:String)
|
|
||||||
{
|
|
||||||
trace('Error! $_code : $_message');
|
|
||||||
}
|
|
||||||
|
|
||||||
static function onDisconnected(_code:Int, _message:String)
|
|
||||||
{
|
|
||||||
trace('Disconnected! $_code : $_message');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function initialize()
|
|
||||||
{
|
|
||||||
var DiscordDaemon = sys.thread.Thread.create(() -> {
|
|
||||||
new DiscordClient();
|
|
||||||
});
|
|
||||||
trace("Discord Client initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function changePresence(details:String, ?state:String, ?smallImageKey:String, ?hasStartTimestamp:Bool, ?endTimestamp:Float)
|
|
||||||
{
|
|
||||||
var startTimestamp:Float = if (hasStartTimestamp) Date.now().getTime() else 0;
|
|
||||||
|
|
||||||
if (endTimestamp > 0)
|
|
||||||
{
|
|
||||||
endTimestamp = startTimestamp + endTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
DiscordRpc.presence(
|
|
||||||
{
|
|
||||||
details: details,
|
|
||||||
state: state,
|
|
||||||
largeImageKey: 'icon',
|
|
||||||
largeImageText: "Friday Night Funkin'",
|
|
||||||
smallImageKey: smallImageKey,
|
|
||||||
// Obtained times are in milliseconds so they are divided so Discord can use it
|
|
||||||
startTimestamp: Std.int(startTimestamp / 1000),
|
|
||||||
endTimestamp: Std.int(endTimestamp / 1000)
|
|
||||||
});
|
|
||||||
|
|
||||||
// trace('Discord RPC Updated. Arguments: $details, $state, $smallImageKey, $hasStartTimestamp, $endTimestamp');
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
}
|
|
204
source/funkin/api/discord/DiscordClient.hx
Normal file
204
source/funkin/api/discord/DiscordClient.hx
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
package funkin.api.discord;
|
||||||
|
|
||||||
|
#if FEATURE_DISCORD_RPC
|
||||||
|
import hxdiscord_rpc.Discord;
|
||||||
|
import hxdiscord_rpc.Types;
|
||||||
|
import sys.thread.Thread;
|
||||||
|
|
||||||
|
class DiscordClient
|
||||||
|
{
|
||||||
|
static final CLIENT_ID:String = "816168432860790794";
|
||||||
|
|
||||||
|
public static var instance(get, never):DiscordClient;
|
||||||
|
static var _instance:Null<DiscordClient> = null;
|
||||||
|
|
||||||
|
static function get_instance():DiscordClient
|
||||||
|
{
|
||||||
|
if (DiscordClient._instance == null) _instance = new DiscordClient();
|
||||||
|
if (DiscordClient._instance == null) throw "Could not initialize singleton DiscordClient!";
|
||||||
|
return DiscordClient._instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
var handlers:DiscordEventHandlers;
|
||||||
|
|
||||||
|
private function new()
|
||||||
|
{
|
||||||
|
trace('[DISCORD] Initializing event handlers...');
|
||||||
|
|
||||||
|
handlers = DiscordEventHandlers.create();
|
||||||
|
|
||||||
|
handlers.ready = cpp.Function.fromStaticFunction(onReady);
|
||||||
|
handlers.disconnected = cpp.Function.fromStaticFunction(onDisconnected);
|
||||||
|
handlers.errored = cpp.Function.fromStaticFunction(onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function init():Void
|
||||||
|
{
|
||||||
|
trace('[DISCORD] Initializing connection...');
|
||||||
|
|
||||||
|
// Discord.initialize(CLIENT_ID, handlers, true, null);
|
||||||
|
Discord.Initialize(CLIENT_ID, cpp.RawPointer.addressOf(handlers), 1, null);
|
||||||
|
|
||||||
|
createDaemon();
|
||||||
|
}
|
||||||
|
|
||||||
|
var daemon:Thread = null;
|
||||||
|
|
||||||
|
function createDaemon():Void
|
||||||
|
{
|
||||||
|
daemon = Thread.create(doDaemonWork);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doDaemonWork():Void
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
trace('[DISCORD] Performing client update...');
|
||||||
|
|
||||||
|
#if DISCORD_DISABLE_IO_THREAD
|
||||||
|
Discord.updateConnection();
|
||||||
|
#end
|
||||||
|
|
||||||
|
Discord.runCallbacks();
|
||||||
|
Sys.sleep(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shutdown():Void
|
||||||
|
{
|
||||||
|
trace('[DISCORD] Shutting down...');
|
||||||
|
|
||||||
|
Discord.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPresence(params:DiscordClientPresenceParams):Void
|
||||||
|
{
|
||||||
|
trace('[DISCORD] Updating presence... (${params})');
|
||||||
|
|
||||||
|
Discord.updatePresence(buildPresence(params));
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPresence(params:DiscordClientPresenceParams):DiscordRichPresence
|
||||||
|
{
|
||||||
|
var presence = DiscordRichPresence.create();
|
||||||
|
|
||||||
|
// Presence should always be playing the game.
|
||||||
|
presence.type = DiscordActivityType_Playing;
|
||||||
|
|
||||||
|
// Text when hovering over the large image. We just leave this as the game name.
|
||||||
|
presence.largeImageText = "Friday Night Funkin'";
|
||||||
|
|
||||||
|
// State should be generally what the person is doing, like "In the Menus" or "Pico (Pico Mix) [Freeplay Hard]"
|
||||||
|
presence.state = cast(params.state, Null<String>);
|
||||||
|
// Details should be what the person is specifically doing, including stuff like timestamps (maybe something like "03:24 elapsed").
|
||||||
|
presence.details = cast(params.details, Null<String>);
|
||||||
|
|
||||||
|
// The large image displaying what the user is doing.
|
||||||
|
// This should probably be album art.
|
||||||
|
// IMPORTANT NOTE: This can be an asset key uploaded to Discord's developer panel OR any URL you like.
|
||||||
|
presence.largeImageKey = cast(params.largeImageKey, Null<String>) ?? "album-volume1";
|
||||||
|
|
||||||
|
trace('[DISCORD] largeImageKey: ${presence.largeImageKey}');
|
||||||
|
|
||||||
|
// TODO: Make this use the song's album art.
|
||||||
|
// presence.largeImageKey = "icon";
|
||||||
|
// presence.largeImageKey = "https://f4.bcbits.com/img/a0746694746_16.jpg";
|
||||||
|
|
||||||
|
// The small inset image for what the user is doing.
|
||||||
|
// This can be the opponent's health icon?
|
||||||
|
// NOTE: Like largeImageKey, this can be a URL, or an asset key.
|
||||||
|
presence.smallImageKey = cast(params.smallImageKey, Null<String>);
|
||||||
|
|
||||||
|
// NOTE: In previous versions, this showed as "Elapsed", but now shows as playtime and doesn't look good
|
||||||
|
// presence.startTimestamp = time - 10;
|
||||||
|
// presence.endTimestamp = time + 30;
|
||||||
|
|
||||||
|
final button1:DiscordButton = DiscordButton.create();
|
||||||
|
button1.label = "Play on Web";
|
||||||
|
button1.url = Constants.URL_NEWGROUNDS;
|
||||||
|
presence.buttons[0] = button1;
|
||||||
|
|
||||||
|
final button2:DiscordButton = DiscordButton.create();
|
||||||
|
button2.label = "Download";
|
||||||
|
button2.url = Constants.URL_ITCH;
|
||||||
|
presence.buttons[1] = button2;
|
||||||
|
|
||||||
|
return presence;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: WHAT THE FUCK get this pointer bullfuckery out of here
|
||||||
|
private static function onReady(request:cpp.RawConstPointer<DiscordUser>):Void
|
||||||
|
{
|
||||||
|
trace('[DISCORD] Client has connected!');
|
||||||
|
|
||||||
|
final username:String = request[0].username;
|
||||||
|
final globalName:String = request[0].username;
|
||||||
|
final discriminator:Int = Std.parseInt(request[0].discriminator);
|
||||||
|
|
||||||
|
if (discriminator != 0)
|
||||||
|
{
|
||||||
|
trace('[DISCORD] User: ${username}#${discriminator} (${globalName})');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trace('[DISCORD] User: @${username} (${globalName})');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function onDisconnected(errorCode:Int, message:cpp.ConstCharStar):Void
|
||||||
|
{
|
||||||
|
trace('[DISCORD] Client has disconnected! ($errorCode) "${cast (message, String)}"');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function onError(errorCode:Int, message:cpp.ConstCharStar):Void
|
||||||
|
{
|
||||||
|
trace('[DISCORD] Client has received an error! ($errorCode) "${cast (message, String)}"');
|
||||||
|
}
|
||||||
|
|
||||||
|
// public var type(get, set):DiscordActivityType;
|
||||||
|
// public var state(get, set):String;
|
||||||
|
// public var details(get, set):String;
|
||||||
|
// public var startTimestamp(get, set):Int;
|
||||||
|
// public var endTimestamp(get, set):Int;
|
||||||
|
// public var largeImageKey(get, set):String;
|
||||||
|
// public var largeImageText(get, set):String;
|
||||||
|
// public var smallImageKey(get, set):String;
|
||||||
|
// public var smallImageText(get, set):String;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// public var partyId(get, set)
|
||||||
|
// public var partySize(get, set)
|
||||||
|
// public var partyMax(get, set)
|
||||||
|
// public var partyPrivacy(get, set)
|
||||||
|
//
|
||||||
|
// public var buttons(get, set)
|
||||||
|
//
|
||||||
|
// public var matchSecret(get, set)
|
||||||
|
// public var joinSecret(get, set)
|
||||||
|
// public var spectateSecret(get, set)
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef DiscordClientPresenceParams =
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The first row of text below the game title.
|
||||||
|
*/
|
||||||
|
var state:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The second row of text below the game title.
|
||||||
|
* Use `null` to display no text.
|
||||||
|
*/
|
||||||
|
var details:Null<String>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A large, 4-row high image to the left of the content.
|
||||||
|
*/
|
||||||
|
var ?largeImageKey:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A small, inset image to the bottom right of `largeImageKey`.
|
||||||
|
*/
|
||||||
|
var ?smallImageKey:String;
|
||||||
|
}
|
||||||
|
#end
|
|
@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.0.2]
|
||||||
|
### Added
|
||||||
|
- Added the ability to specify `flipX` and `flipY` on stage props to horizontally or vertically flip, respectively.
|
||||||
|
|
||||||
## [1.0.1]
|
## [1.0.1]
|
||||||
### Added
|
### Added
|
||||||
- Added the ability to specify a hexadecimal color in the `assetPath` field instead of a texture key.
|
- Added the ability to specify a hexadecimal color in the `assetPath` field instead of a texture key.
|
||||||
|
|
|
@ -118,6 +118,22 @@ typedef StageDataProp =
|
||||||
@:default(false)
|
@:default(false)
|
||||||
var isPixel:Bool;
|
var isPixel:Bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to true, the prop will be flipped horizontally.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
@:default(false)
|
||||||
|
var flipX:Bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to true, the prop will be flipped vertically.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
@:optional
|
||||||
|
@:default(false)
|
||||||
|
var flipY:Bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Either the scale of the prop as a float, or the [w, h] scale as an array of two floats.
|
* Either the scale of the prop as a float, or the [w, h] scale as an array of two floats.
|
||||||
* Pro tip: On pixel-art levels, save the sprite small and set this value to 6 or so to save memory.
|
* Pro tip: On pixel-art levels, save the sprite small and set this value to 6 or so to save memory.
|
||||||
|
|
|
@ -11,9 +11,9 @@ class StageRegistry extends BaseRegistry<Stage, StageData>
|
||||||
* Handle breaking changes by incrementing this value
|
* Handle breaking changes by incrementing this value
|
||||||
* and adding migration to the `migrateStageData()` function.
|
* and adding migration to the `migrateStageData()` function.
|
||||||
*/
|
*/
|
||||||
public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.0";
|
public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.2";
|
||||||
|
|
||||||
public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
|
public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=1.0.0 <=1.0.2";
|
||||||
|
|
||||||
public static var instance(get, never):StageRegistry;
|
public static var instance(get, never):StageRegistry;
|
||||||
static var _instance:Null<StageRegistry> = null;
|
static var _instance:Null<StageRegistry> = null;
|
||||||
|
|
|
@ -59,7 +59,9 @@ class Controls extends FlxActionSet
|
||||||
var _back = new FunkinAction(Action.BACK);
|
var _back = new FunkinAction(Action.BACK);
|
||||||
var _pause = new FunkinAction(Action.PAUSE);
|
var _pause = new FunkinAction(Action.PAUSE);
|
||||||
var _reset = new FunkinAction(Action.RESET);
|
var _reset = new FunkinAction(Action.RESET);
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
var _window_screenshot = new FunkinAction(Action.WINDOW_SCREENSHOT);
|
var _window_screenshot = new FunkinAction(Action.WINDOW_SCREENSHOT);
|
||||||
|
#end
|
||||||
var _window_fullscreen = new FunkinAction(Action.WINDOW_FULLSCREEN);
|
var _window_fullscreen = new FunkinAction(Action.WINDOW_FULLSCREEN);
|
||||||
var _freeplay_favorite = new FunkinAction(Action.FREEPLAY_FAVORITE);
|
var _freeplay_favorite = new FunkinAction(Action.FREEPLAY_FAVORITE);
|
||||||
var _freeplay_left = new FunkinAction(Action.FREEPLAY_LEFT);
|
var _freeplay_left = new FunkinAction(Action.FREEPLAY_LEFT);
|
||||||
|
@ -67,8 +69,12 @@ class Controls extends FlxActionSet
|
||||||
var _freeplay_char_select = new FunkinAction(Action.FREEPLAY_CHAR_SELECT);
|
var _freeplay_char_select = new FunkinAction(Action.FREEPLAY_CHAR_SELECT);
|
||||||
var _cutscene_advance = new FunkinAction(Action.CUTSCENE_ADVANCE);
|
var _cutscene_advance = new FunkinAction(Action.CUTSCENE_ADVANCE);
|
||||||
var _debug_menu = new FunkinAction(Action.DEBUG_MENU);
|
var _debug_menu = new FunkinAction(Action.DEBUG_MENU);
|
||||||
|
#if FEATURE_CHART_EDITOR
|
||||||
var _debug_chart = new FunkinAction(Action.DEBUG_CHART);
|
var _debug_chart = new FunkinAction(Action.DEBUG_CHART);
|
||||||
|
#end
|
||||||
|
#if FEATURE_STAGE_EDITOR
|
||||||
var _debug_stage = new FunkinAction(Action.DEBUG_STAGE);
|
var _debug_stage = new FunkinAction(Action.DEBUG_STAGE);
|
||||||
|
#end
|
||||||
var _volume_up = new FunkinAction(Action.VOLUME_UP);
|
var _volume_up = new FunkinAction(Action.VOLUME_UP);
|
||||||
var _volume_down = new FunkinAction(Action.VOLUME_DOWN);
|
var _volume_down = new FunkinAction(Action.VOLUME_DOWN);
|
||||||
var _volume_mute = new FunkinAction(Action.VOLUME_MUTE);
|
var _volume_mute = new FunkinAction(Action.VOLUME_MUTE);
|
||||||
|
@ -243,10 +249,12 @@ class Controls extends FlxActionSet
|
||||||
inline function get_WINDOW_FULLSCREEN()
|
inline function get_WINDOW_FULLSCREEN()
|
||||||
return _window_fullscreen.check();
|
return _window_fullscreen.check();
|
||||||
|
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
public var WINDOW_SCREENSHOT(get, never):Bool;
|
public var WINDOW_SCREENSHOT(get, never):Bool;
|
||||||
|
|
||||||
inline function get_WINDOW_SCREENSHOT()
|
inline function get_WINDOW_SCREENSHOT()
|
||||||
return _window_screenshot.check();
|
return _window_screenshot.check();
|
||||||
|
#end
|
||||||
|
|
||||||
public var FREEPLAY_FAVORITE(get, never):Bool;
|
public var FREEPLAY_FAVORITE(get, never):Bool;
|
||||||
|
|
||||||
|
@ -278,15 +286,19 @@ class Controls extends FlxActionSet
|
||||||
inline function get_DEBUG_MENU()
|
inline function get_DEBUG_MENU()
|
||||||
return _debug_menu.check();
|
return _debug_menu.check();
|
||||||
|
|
||||||
|
#if FEATURE_CHART_EDITOR
|
||||||
public var DEBUG_CHART(get, never):Bool;
|
public var DEBUG_CHART(get, never):Bool;
|
||||||
|
|
||||||
inline function get_DEBUG_CHART()
|
inline function get_DEBUG_CHART()
|
||||||
return _debug_chart.check();
|
return _debug_chart.check();
|
||||||
|
#end
|
||||||
|
|
||||||
|
#if FEATURE_STAGE_EDITOR
|
||||||
public var DEBUG_STAGE(get, never):Bool;
|
public var DEBUG_STAGE(get, never):Bool;
|
||||||
|
|
||||||
inline function get_DEBUG_STAGE()
|
inline function get_DEBUG_STAGE()
|
||||||
return _debug_stage.check();
|
return _debug_stage.check();
|
||||||
|
#end
|
||||||
|
|
||||||
public var VOLUME_UP(get, never):Bool;
|
public var VOLUME_UP(get, never):Bool;
|
||||||
|
|
||||||
|
@ -319,7 +331,7 @@ class Controls extends FlxActionSet
|
||||||
add(_back);
|
add(_back);
|
||||||
add(_pause);
|
add(_pause);
|
||||||
add(_reset);
|
add(_reset);
|
||||||
add(_window_screenshot);
|
#if FEATURE_SCREENSHOTS add(_window_screenshot); #end
|
||||||
add(_window_fullscreen);
|
add(_window_fullscreen);
|
||||||
add(_freeplay_favorite);
|
add(_freeplay_favorite);
|
||||||
add(_freeplay_left);
|
add(_freeplay_left);
|
||||||
|
@ -327,8 +339,8 @@ class Controls extends FlxActionSet
|
||||||
add(_freeplay_char_select);
|
add(_freeplay_char_select);
|
||||||
add(_cutscene_advance);
|
add(_cutscene_advance);
|
||||||
add(_debug_menu);
|
add(_debug_menu);
|
||||||
add(_debug_chart);
|
#if FEATURE_CHART_EDITOR add(_debug_chart); #end
|
||||||
add(_debug_stage);
|
#if FEATURE_STAGE_EDITOR add(_debug_stage); #end
|
||||||
add(_volume_up);
|
add(_volume_up);
|
||||||
add(_volume_down);
|
add(_volume_down);
|
||||||
add(_volume_mute);
|
add(_volume_mute);
|
||||||
|
@ -444,7 +456,7 @@ class Controls extends FlxActionSet
|
||||||
case BACK: _back;
|
case BACK: _back;
|
||||||
case PAUSE: _pause;
|
case PAUSE: _pause;
|
||||||
case RESET: _reset;
|
case RESET: _reset;
|
||||||
case WINDOW_SCREENSHOT: _window_screenshot;
|
#if FEATURE_SCREENSHOTS case WINDOW_SCREENSHOT: _window_screenshot; #end
|
||||||
case WINDOW_FULLSCREEN: _window_fullscreen;
|
case WINDOW_FULLSCREEN: _window_fullscreen;
|
||||||
case FREEPLAY_FAVORITE: _freeplay_favorite;
|
case FREEPLAY_FAVORITE: _freeplay_favorite;
|
||||||
case FREEPLAY_LEFT: _freeplay_left;
|
case FREEPLAY_LEFT: _freeplay_left;
|
||||||
|
@ -452,8 +464,8 @@ class Controls extends FlxActionSet
|
||||||
case FREEPLAY_CHAR_SELECT: _freeplay_char_select;
|
case FREEPLAY_CHAR_SELECT: _freeplay_char_select;
|
||||||
case CUTSCENE_ADVANCE: _cutscene_advance;
|
case CUTSCENE_ADVANCE: _cutscene_advance;
|
||||||
case DEBUG_MENU: _debug_menu;
|
case DEBUG_MENU: _debug_menu;
|
||||||
case DEBUG_CHART: _debug_chart;
|
#if FEATURE_CHART_EDITOR case DEBUG_CHART: _debug_chart; #end
|
||||||
case DEBUG_STAGE: _debug_stage;
|
#if FEATURE_STAGE_EDITOR case DEBUG_STAGE: _debug_stage; #end
|
||||||
case VOLUME_UP: _volume_up;
|
case VOLUME_UP: _volume_up;
|
||||||
case VOLUME_DOWN: _volume_down;
|
case VOLUME_DOWN: _volume_down;
|
||||||
case VOLUME_MUTE: _volume_mute;
|
case VOLUME_MUTE: _volume_mute;
|
||||||
|
@ -516,8 +528,10 @@ class Controls extends FlxActionSet
|
||||||
func(_pause, JUST_PRESSED);
|
func(_pause, JUST_PRESSED);
|
||||||
case RESET:
|
case RESET:
|
||||||
func(_reset, JUST_PRESSED);
|
func(_reset, JUST_PRESSED);
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
case WINDOW_SCREENSHOT:
|
case WINDOW_SCREENSHOT:
|
||||||
func(_window_screenshot, JUST_PRESSED);
|
func(_window_screenshot, JUST_PRESSED);
|
||||||
|
#end
|
||||||
case WINDOW_FULLSCREEN:
|
case WINDOW_FULLSCREEN:
|
||||||
func(_window_fullscreen, JUST_PRESSED);
|
func(_window_fullscreen, JUST_PRESSED);
|
||||||
case FREEPLAY_FAVORITE:
|
case FREEPLAY_FAVORITE:
|
||||||
|
@ -532,10 +546,14 @@ class Controls extends FlxActionSet
|
||||||
func(_cutscene_advance, JUST_PRESSED);
|
func(_cutscene_advance, JUST_PRESSED);
|
||||||
case DEBUG_MENU:
|
case DEBUG_MENU:
|
||||||
func(_debug_menu, JUST_PRESSED);
|
func(_debug_menu, JUST_PRESSED);
|
||||||
|
#if FEATURE_CHART_EDITOR
|
||||||
case DEBUG_CHART:
|
case DEBUG_CHART:
|
||||||
func(_debug_chart, JUST_PRESSED);
|
func(_debug_chart, JUST_PRESSED);
|
||||||
|
#end
|
||||||
|
#if FEATURE_STAGE_EDITOR
|
||||||
case DEBUG_STAGE:
|
case DEBUG_STAGE:
|
||||||
func(_debug_stage, JUST_PRESSED);
|
func(_debug_stage, JUST_PRESSED);
|
||||||
|
#end
|
||||||
case VOLUME_UP:
|
case VOLUME_UP:
|
||||||
func(_volume_up, JUST_PRESSED);
|
func(_volume_up, JUST_PRESSED);
|
||||||
case VOLUME_DOWN:
|
case VOLUME_DOWN:
|
||||||
|
@ -744,7 +762,9 @@ class Controls extends FlxActionSet
|
||||||
bindKeys(Control.BACK, getDefaultKeybinds(scheme, Control.BACK));
|
bindKeys(Control.BACK, getDefaultKeybinds(scheme, Control.BACK));
|
||||||
bindKeys(Control.PAUSE, getDefaultKeybinds(scheme, Control.PAUSE));
|
bindKeys(Control.PAUSE, getDefaultKeybinds(scheme, Control.PAUSE));
|
||||||
bindKeys(Control.RESET, getDefaultKeybinds(scheme, Control.RESET));
|
bindKeys(Control.RESET, getDefaultKeybinds(scheme, Control.RESET));
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
bindKeys(Control.WINDOW_SCREENSHOT, getDefaultKeybinds(scheme, Control.WINDOW_SCREENSHOT));
|
bindKeys(Control.WINDOW_SCREENSHOT, getDefaultKeybinds(scheme, Control.WINDOW_SCREENSHOT));
|
||||||
|
#end
|
||||||
bindKeys(Control.WINDOW_FULLSCREEN, getDefaultKeybinds(scheme, Control.WINDOW_FULLSCREEN));
|
bindKeys(Control.WINDOW_FULLSCREEN, getDefaultKeybinds(scheme, Control.WINDOW_FULLSCREEN));
|
||||||
bindKeys(Control.FREEPLAY_FAVORITE, getDefaultKeybinds(scheme, Control.FREEPLAY_FAVORITE));
|
bindKeys(Control.FREEPLAY_FAVORITE, getDefaultKeybinds(scheme, Control.FREEPLAY_FAVORITE));
|
||||||
bindKeys(Control.FREEPLAY_LEFT, getDefaultKeybinds(scheme, Control.FREEPLAY_LEFT));
|
bindKeys(Control.FREEPLAY_LEFT, getDefaultKeybinds(scheme, Control.FREEPLAY_LEFT));
|
||||||
|
@ -752,8 +772,12 @@ class Controls extends FlxActionSet
|
||||||
bindKeys(Control.FREEPLAY_CHAR_SELECT, getDefaultKeybinds(scheme, Control.FREEPLAY_CHAR_SELECT));
|
bindKeys(Control.FREEPLAY_CHAR_SELECT, getDefaultKeybinds(scheme, Control.FREEPLAY_CHAR_SELECT));
|
||||||
bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE));
|
bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE));
|
||||||
bindKeys(Control.DEBUG_MENU, getDefaultKeybinds(scheme, Control.DEBUG_MENU));
|
bindKeys(Control.DEBUG_MENU, getDefaultKeybinds(scheme, Control.DEBUG_MENU));
|
||||||
|
#if FEATURE_CHART_EDITOR
|
||||||
bindKeys(Control.DEBUG_CHART, getDefaultKeybinds(scheme, Control.DEBUG_CHART));
|
bindKeys(Control.DEBUG_CHART, getDefaultKeybinds(scheme, Control.DEBUG_CHART));
|
||||||
|
#end
|
||||||
|
#if FEATURE_STAGE_EDITOR
|
||||||
bindKeys(Control.DEBUG_STAGE, getDefaultKeybinds(scheme, Control.DEBUG_STAGE));
|
bindKeys(Control.DEBUG_STAGE, getDefaultKeybinds(scheme, Control.DEBUG_STAGE));
|
||||||
|
#end
|
||||||
bindKeys(Control.VOLUME_UP, getDefaultKeybinds(scheme, Control.VOLUME_UP));
|
bindKeys(Control.VOLUME_UP, getDefaultKeybinds(scheme, Control.VOLUME_UP));
|
||||||
bindKeys(Control.VOLUME_DOWN, getDefaultKeybinds(scheme, Control.VOLUME_DOWN));
|
bindKeys(Control.VOLUME_DOWN, getDefaultKeybinds(scheme, Control.VOLUME_DOWN));
|
||||||
bindKeys(Control.VOLUME_MUTE, getDefaultKeybinds(scheme, Control.VOLUME_MUTE));
|
bindKeys(Control.VOLUME_MUTE, getDefaultKeybinds(scheme, Control.VOLUME_MUTE));
|
||||||
|
@ -781,15 +805,15 @@ class Controls extends FlxActionSet
|
||||||
case Control.PAUSE: return [P, ENTER, ESCAPE];
|
case Control.PAUSE: return [P, ENTER, ESCAPE];
|
||||||
case Control.RESET: return [R];
|
case Control.RESET: return [R];
|
||||||
case Control.WINDOW_FULLSCREEN: return [F11]; // We use F for other things LOL.
|
case Control.WINDOW_FULLSCREEN: return [F11]; // We use F for other things LOL.
|
||||||
case Control.WINDOW_SCREENSHOT: return [F3];
|
#if FEATURE_SCREENSHOTS case Control.WINDOW_SCREENSHOT: return [F3]; #end
|
||||||
case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu
|
case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu
|
||||||
case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu
|
case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu
|
||||||
case Control.FREEPLAY_RIGHT: return [E]; // Switch tabs on the menu
|
case Control.FREEPLAY_RIGHT: return [E]; // Switch tabs on the menu
|
||||||
case Control.FREEPLAY_CHAR_SELECT: return [TAB];
|
case Control.FREEPLAY_CHAR_SELECT: return [TAB];
|
||||||
case Control.CUTSCENE_ADVANCE: return [Z, ENTER];
|
case Control.CUTSCENE_ADVANCE: return [Z, ENTER];
|
||||||
case Control.DEBUG_MENU: return [GRAVEACCENT];
|
case Control.DEBUG_MENU: return [GRAVEACCENT];
|
||||||
case Control.DEBUG_CHART: return [];
|
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
|
||||||
case Control.DEBUG_STAGE: return [];
|
#if FEATURE_STAGE_EDITOR case Control.DEBUG_STAGE: return []; #end
|
||||||
case Control.VOLUME_UP: return [PLUS, NUMPADPLUS];
|
case Control.VOLUME_UP: return [PLUS, NUMPADPLUS];
|
||||||
case Control.VOLUME_DOWN: return [MINUS, NUMPADMINUS];
|
case Control.VOLUME_DOWN: return [MINUS, NUMPADMINUS];
|
||||||
case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO];
|
case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO];
|
||||||
|
@ -809,7 +833,7 @@ class Controls extends FlxActionSet
|
||||||
case Control.BACK: return [H, X];
|
case Control.BACK: return [H, X];
|
||||||
case Control.PAUSE: return [ONE];
|
case Control.PAUSE: return [ONE];
|
||||||
case Control.RESET: return [R];
|
case Control.RESET: return [R];
|
||||||
case Control.WINDOW_SCREENSHOT: return [F3];
|
#if FEATURE_SCREENSHOTS case Control.WINDOW_SCREENSHOT: return [F3]; #end
|
||||||
case Control.WINDOW_FULLSCREEN: return [F11];
|
case Control.WINDOW_FULLSCREEN: return [F11];
|
||||||
case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu
|
case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu
|
||||||
case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu
|
case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu
|
||||||
|
@ -817,8 +841,8 @@ class Controls extends FlxActionSet
|
||||||
case Control.FREEPLAY_CHAR_SELECT: return [TAB];
|
case Control.FREEPLAY_CHAR_SELECT: return [TAB];
|
||||||
case Control.CUTSCENE_ADVANCE: return [G, Z];
|
case Control.CUTSCENE_ADVANCE: return [G, Z];
|
||||||
case Control.DEBUG_MENU: return [GRAVEACCENT];
|
case Control.DEBUG_MENU: return [GRAVEACCENT];
|
||||||
case Control.DEBUG_CHART: return [];
|
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
|
||||||
case Control.DEBUG_STAGE: return [];
|
#if FEATURE_STAGE_EDITOR case Control.DEBUG_STAGE: return []; #end
|
||||||
case Control.VOLUME_UP: return [PLUS];
|
case Control.VOLUME_UP: return [PLUS];
|
||||||
case Control.VOLUME_DOWN: return [MINUS];
|
case Control.VOLUME_DOWN: return [MINUS];
|
||||||
case Control.VOLUME_MUTE: return [ZERO];
|
case Control.VOLUME_MUTE: return [ZERO];
|
||||||
|
@ -838,7 +862,7 @@ class Controls extends FlxActionSet
|
||||||
case Control.BACK: return [ESCAPE];
|
case Control.BACK: return [ESCAPE];
|
||||||
case Control.PAUSE: return [ONE];
|
case Control.PAUSE: return [ONE];
|
||||||
case Control.RESET: return [R];
|
case Control.RESET: return [R];
|
||||||
case Control.WINDOW_SCREENSHOT: return [];
|
#if FEATURE_SCREENSHOTS case Control.WINDOW_SCREENSHOT: return []; #end
|
||||||
case Control.WINDOW_FULLSCREEN: return [];
|
case Control.WINDOW_FULLSCREEN: return [];
|
||||||
case Control.FREEPLAY_FAVORITE: return [];
|
case Control.FREEPLAY_FAVORITE: return [];
|
||||||
case Control.FREEPLAY_LEFT: return [];
|
case Control.FREEPLAY_LEFT: return [];
|
||||||
|
@ -846,8 +870,8 @@ class Controls extends FlxActionSet
|
||||||
case Control.FREEPLAY_CHAR_SELECT: return [];
|
case Control.FREEPLAY_CHAR_SELECT: return [];
|
||||||
case Control.CUTSCENE_ADVANCE: return [ENTER];
|
case Control.CUTSCENE_ADVANCE: return [ENTER];
|
||||||
case Control.DEBUG_MENU: return [];
|
case Control.DEBUG_MENU: return [];
|
||||||
case Control.DEBUG_CHART: return [];
|
#if FEATURE_CHART_EDITOR case Control.DEBUG_CHART: return []; #end
|
||||||
case Control.DEBUG_STAGE: return [];
|
#if FEATURE_STAGE_EDITOR case Control.DEBUG_STAGE: return []; #end
|
||||||
case Control.VOLUME_UP: return [NUMPADPLUS];
|
case Control.VOLUME_UP: return [NUMPADPLUS];
|
||||||
case Control.VOLUME_DOWN: return [NUMPADMINUS];
|
case Control.VOLUME_DOWN: return [NUMPADMINUS];
|
||||||
case Control.VOLUME_MUTE: return [NUMPADZERO];
|
case Control.VOLUME_MUTE: return [NUMPADZERO];
|
||||||
|
@ -952,7 +976,9 @@ class Controls extends FlxActionSet
|
||||||
Control.PAUSE => getDefaultGamepadBinds(Control.PAUSE),
|
Control.PAUSE => getDefaultGamepadBinds(Control.PAUSE),
|
||||||
Control.RESET => getDefaultGamepadBinds(Control.RESET),
|
Control.RESET => getDefaultGamepadBinds(Control.RESET),
|
||||||
Control.WINDOW_FULLSCREEN => getDefaultGamepadBinds(Control.WINDOW_FULLSCREEN),
|
Control.WINDOW_FULLSCREEN => getDefaultGamepadBinds(Control.WINDOW_FULLSCREEN),
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
Control.WINDOW_SCREENSHOT => getDefaultGamepadBinds(Control.WINDOW_SCREENSHOT),
|
Control.WINDOW_SCREENSHOT => getDefaultGamepadBinds(Control.WINDOW_SCREENSHOT),
|
||||||
|
#end
|
||||||
Control.CUTSCENE_ADVANCE => getDefaultGamepadBinds(Control.CUTSCENE_ADVANCE),
|
Control.CUTSCENE_ADVANCE => getDefaultGamepadBinds(Control.CUTSCENE_ADVANCE),
|
||||||
Control.FREEPLAY_FAVORITE => getDefaultGamepadBinds(Control.FREEPLAY_FAVORITE),
|
Control.FREEPLAY_FAVORITE => getDefaultGamepadBinds(Control.FREEPLAY_FAVORITE),
|
||||||
Control.FREEPLAY_LEFT => getDefaultGamepadBinds(Control.FREEPLAY_LEFT),
|
Control.FREEPLAY_LEFT => getDefaultGamepadBinds(Control.FREEPLAY_LEFT),
|
||||||
|
@ -961,8 +987,12 @@ class Controls extends FlxActionSet
|
||||||
Control.VOLUME_DOWN => getDefaultGamepadBinds(Control.VOLUME_DOWN),
|
Control.VOLUME_DOWN => getDefaultGamepadBinds(Control.VOLUME_DOWN),
|
||||||
Control.VOLUME_MUTE => getDefaultGamepadBinds(Control.VOLUME_MUTE),
|
Control.VOLUME_MUTE => getDefaultGamepadBinds(Control.VOLUME_MUTE),
|
||||||
Control.DEBUG_MENU => getDefaultGamepadBinds(Control.DEBUG_MENU),
|
Control.DEBUG_MENU => getDefaultGamepadBinds(Control.DEBUG_MENU),
|
||||||
|
#if FEATURE_CHART_EDITOR
|
||||||
Control.DEBUG_CHART => getDefaultGamepadBinds(Control.DEBUG_CHART),
|
Control.DEBUG_CHART => getDefaultGamepadBinds(Control.DEBUG_CHART),
|
||||||
|
#end
|
||||||
|
#if FEATURE_STAGE_EDITOR
|
||||||
Control.DEBUG_STAGE => getDefaultGamepadBinds(Control.DEBUG_STAGE),
|
Control.DEBUG_STAGE => getDefaultGamepadBinds(Control.DEBUG_STAGE),
|
||||||
|
#end
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,8 +1026,10 @@ class Controls extends FlxActionSet
|
||||||
return [FlxGamepadInputID.BACK]; // Back (i.e. Select)
|
return [FlxGamepadInputID.BACK]; // Back (i.e. Select)
|
||||||
case Control.WINDOW_FULLSCREEN:
|
case Control.WINDOW_FULLSCREEN:
|
||||||
[];
|
[];
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
case Control.WINDOW_SCREENSHOT:
|
case Control.WINDOW_SCREENSHOT:
|
||||||
[];
|
[];
|
||||||
|
#end
|
||||||
case Control.CUTSCENE_ADVANCE:
|
case Control.CUTSCENE_ADVANCE:
|
||||||
return [A];
|
return [A];
|
||||||
case Control.FREEPLAY_FAVORITE:
|
case Control.FREEPLAY_FAVORITE:
|
||||||
|
@ -1014,10 +1046,14 @@ class Controls extends FlxActionSet
|
||||||
[];
|
[];
|
||||||
case Control.DEBUG_MENU:
|
case Control.DEBUG_MENU:
|
||||||
[];
|
[];
|
||||||
|
#if FEATURE_CHART_EDITOR
|
||||||
case Control.DEBUG_CHART:
|
case Control.DEBUG_CHART:
|
||||||
[];
|
[];
|
||||||
|
#end
|
||||||
|
#if FEATURE_STAGE_EDITOR
|
||||||
case Control.DEBUG_STAGE:
|
case Control.DEBUG_STAGE:
|
||||||
[];
|
[];
|
||||||
|
#end
|
||||||
default:
|
default:
|
||||||
// Fallthrough.
|
// Fallthrough.
|
||||||
}
|
}
|
||||||
|
@ -1582,7 +1618,7 @@ enum Control
|
||||||
FREEPLAY_RIGHT;
|
FREEPLAY_RIGHT;
|
||||||
FREEPLAY_CHAR_SELECT;
|
FREEPLAY_CHAR_SELECT;
|
||||||
// WINDOW
|
// WINDOW
|
||||||
WINDOW_SCREENSHOT;
|
#if FEATURE_SCREENSHOTS WINDOW_SCREENSHOT; #end
|
||||||
WINDOW_FULLSCREEN;
|
WINDOW_FULLSCREEN;
|
||||||
// VOLUME
|
// VOLUME
|
||||||
VOLUME_UP;
|
VOLUME_UP;
|
||||||
|
@ -1590,8 +1626,8 @@ enum Control
|
||||||
VOLUME_MUTE;
|
VOLUME_MUTE;
|
||||||
// DEBUG
|
// DEBUG
|
||||||
DEBUG_MENU;
|
DEBUG_MENU;
|
||||||
DEBUG_CHART;
|
#if FEATURE_CHART_EDITOR DEBUG_CHART; #end
|
||||||
DEBUG_STAGE;
|
#if FEATURE_STAGE_EDITOR DEBUG_STAGE; #end
|
||||||
}
|
}
|
||||||
|
|
||||||
enum abstract Action(String) to String from String
|
enum abstract Action(String) to String from String
|
||||||
|
@ -1628,7 +1664,9 @@ enum abstract Action(String) to String from String
|
||||||
var RESET = "reset";
|
var RESET = "reset";
|
||||||
// WINDOW
|
// WINDOW
|
||||||
var WINDOW_FULLSCREEN = "window_fullscreen";
|
var WINDOW_FULLSCREEN = "window_fullscreen";
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
var WINDOW_SCREENSHOT = "window_screenshot";
|
var WINDOW_SCREENSHOT = "window_screenshot";
|
||||||
|
#end
|
||||||
// CUTSCENE
|
// CUTSCENE
|
||||||
var CUTSCENE_ADVANCE = "cutscene_advance";
|
var CUTSCENE_ADVANCE = "cutscene_advance";
|
||||||
// FREEPLAY
|
// FREEPLAY
|
||||||
|
@ -1642,8 +1680,12 @@ enum abstract Action(String) to String from String
|
||||||
var VOLUME_MUTE = "volume_mute";
|
var VOLUME_MUTE = "volume_mute";
|
||||||
// DEBUG
|
// DEBUG
|
||||||
var DEBUG_MENU = "debug_menu";
|
var DEBUG_MENU = "debug_menu";
|
||||||
|
#if FEATURE_CHART_EDITOR
|
||||||
var DEBUG_CHART = "debug_chart";
|
var DEBUG_CHART = "debug_chart";
|
||||||
|
#end
|
||||||
|
#if FEATURE_STAGE_EDITOR
|
||||||
var DEBUG_STAGE = "debug_stage";
|
var DEBUG_STAGE = "debug_stage";
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Device
|
enum Device
|
||||||
|
|
|
@ -27,11 +27,18 @@ import polymod.Polymod;
|
||||||
class PolymodHandler
|
class PolymodHandler
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The API version that mods should comply with.
|
* The API version for the current version of the game. Since 0.5.0, we've just made this the game version!
|
||||||
* Indicates which mods are compatible with this version of the game.
|
|
||||||
* Minor updates rarely impact mods but major versions often do.
|
* Minor updates rarely impact mods but major versions often do.
|
||||||
*/
|
*/
|
||||||
static final API_VERSION:String = "0.5.0"; // Constants.VERSION;
|
// static final API_VERSION:String = Constants.VERSION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Semantic Versioning rule
|
||||||
|
* Indicates which mods are compatible with this version of the game.
|
||||||
|
* Using more complex rules allows mods from older compatible versions to stay functioning,
|
||||||
|
* while preventing mods made for future versions from being installed.
|
||||||
|
*/
|
||||||
|
static final API_VERSION_RULE:String = ">=0.5.0 <0.6.0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Where relative to the executable that mods are located.
|
* Where relative to the executable that mods are located.
|
||||||
|
@ -131,7 +138,7 @@ class PolymodHandler
|
||||||
// Framework being used to load assets.
|
// Framework being used to load assets.
|
||||||
framework: OPENFL,
|
framework: OPENFL,
|
||||||
// The current version of our API.
|
// The current version of our API.
|
||||||
apiVersionRule: API_VERSION,
|
apiVersionRule: API_VERSION_RULE,
|
||||||
// Call this function any time an error occurs.
|
// Call this function any time an error occurs.
|
||||||
errorCallback: PolymodErrorHandler.onPolymodError,
|
errorCallback: PolymodErrorHandler.onPolymodError,
|
||||||
// Enforce semantic version patterns for each mod.
|
// Enforce semantic version patterns for each mod.
|
||||||
|
@ -338,7 +345,7 @@ class PolymodHandler
|
||||||
var modMetadata:Array<ModMetadata> = Polymod.scan(
|
var modMetadata:Array<ModMetadata> = Polymod.scan(
|
||||||
{
|
{
|
||||||
modRoot: MOD_FOLDER,
|
modRoot: MOD_FOLDER,
|
||||||
apiVersionRule: API_VERSION,
|
apiVersionRule: API_VERSION_RULE,
|
||||||
fileSystem: modFileSystem,
|
fileSystem: modFileSystem,
|
||||||
errorCallback: PolymodErrorHandler.onPolymodError
|
errorCallback: PolymodErrorHandler.onPolymodError
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,8 +15,8 @@ import flixel.tweens.FlxEase;
|
||||||
import flixel.tweens.FlxTween;
|
import flixel.tweens.FlxTween;
|
||||||
import flixel.ui.FlxBar;
|
import flixel.ui.FlxBar;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import flixel.util.FlxTimer;
|
|
||||||
import flixel.util.FlxStringUtil;
|
import flixel.util.FlxStringUtil;
|
||||||
|
import flixel.util.FlxTimer;
|
||||||
import funkin.api.newgrounds.NGio;
|
import funkin.api.newgrounds.NGio;
|
||||||
import funkin.audio.FunkinSound;
|
import funkin.audio.FunkinSound;
|
||||||
import funkin.audio.VoicesGroup;
|
import funkin.audio.VoicesGroup;
|
||||||
|
@ -44,12 +44,12 @@ import funkin.play.cutscene.dialogue.Conversation;
|
||||||
import funkin.play.cutscene.VanillaCutscenes;
|
import funkin.play.cutscene.VanillaCutscenes;
|
||||||
import funkin.play.cutscene.VideoCutscene;
|
import funkin.play.cutscene.VideoCutscene;
|
||||||
import funkin.play.notes.NoteDirection;
|
import funkin.play.notes.NoteDirection;
|
||||||
|
import funkin.play.notes.notekind.NoteKindManager;
|
||||||
import funkin.play.notes.NoteSplash;
|
import funkin.play.notes.NoteSplash;
|
||||||
import funkin.play.notes.NoteSprite;
|
import funkin.play.notes.NoteSprite;
|
||||||
import funkin.play.notes.notestyle.NoteStyle;
|
import funkin.play.notes.notestyle.NoteStyle;
|
||||||
import funkin.play.notes.Strumline;
|
import funkin.play.notes.Strumline;
|
||||||
import funkin.play.notes.SustainTrail;
|
import funkin.play.notes.SustainTrail;
|
||||||
import funkin.play.notes.notekind.NoteKindManager;
|
|
||||||
import funkin.play.scoring.Scoring;
|
import funkin.play.scoring.Scoring;
|
||||||
import funkin.play.song.Song;
|
import funkin.play.song.Song;
|
||||||
import funkin.play.stage.Stage;
|
import funkin.play.stage.Stage;
|
||||||
|
@ -68,7 +68,7 @@ import openfl.display.BitmapData;
|
||||||
import openfl.geom.Rectangle;
|
import openfl.geom.Rectangle;
|
||||||
import openfl.Lib;
|
import openfl.Lib;
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
import Discord.DiscordClient;
|
import funkin.api.discord.DiscordClient;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -447,10 +447,8 @@ class PlayState extends MusicBeatSubState
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
// Discord RPC variables
|
// Discord RPC variables
|
||||||
var storyDifficultyText:String = '';
|
var discordRPCAlbum:String = '';
|
||||||
var iconRPC:String = '';
|
var discordRPCIcon:String = '';
|
||||||
var detailsText:String = '';
|
|
||||||
var detailsPausedText:String = '';
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -817,6 +815,7 @@ class PlayState extends MusicBeatSubState
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
this.remove(currentStage);
|
||||||
FlxG.switchState(() -> new MainMenuState());
|
FlxG.switchState(() -> new MainMenuState());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -965,6 +964,7 @@ 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)
|
||||||
{
|
{
|
||||||
|
this.remove(currentStage);
|
||||||
FlxG.switchState(() -> new GitarooPause(
|
FlxG.switchState(() -> new GitarooPause(
|
||||||
{
|
{
|
||||||
targetSong: currentSong,
|
targetSong: currentSong,
|
||||||
|
@ -992,7 +992,15 @@ class PlayState extends MusicBeatSubState
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
|
DiscordClient.instance.setPresence(
|
||||||
|
{
|
||||||
|
details: 'Paused - ${buildDiscordRPCDetails()}',
|
||||||
|
|
||||||
|
state: buildDiscordRPCState(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1081,8 +1089,14 @@ class PlayState extends MusicBeatSubState
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
// Game Over doesn't get his own variable because it's only used here
|
DiscordClient.instance.setPresence(
|
||||||
DiscordClient.changePresence('Game Over - ' + detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
|
{
|
||||||
|
details: 'Game Over - ${buildDiscordRPCDetails()}',
|
||||||
|
state: buildDiscordRPCState(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
else if (isPlayerDying)
|
else if (isPlayerDying)
|
||||||
|
@ -1293,14 +1307,29 @@ class PlayState extends MusicBeatSubState
|
||||||
Countdown.resumeCountdown();
|
Countdown.resumeCountdown();
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
if (startTimer.finished)
|
if (Conductor.instance.songPosition > 0)
|
||||||
{
|
{
|
||||||
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true,
|
// DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true,
|
||||||
currentSongLengthMs - Conductor.instance.songPosition);
|
// currentSongLengthMs - Conductor.instance.songPosition);
|
||||||
|
DiscordClient.instance.setPresence(
|
||||||
|
{
|
||||||
|
state: buildDiscordRPCState(),
|
||||||
|
details: buildDiscordRPCDetails(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC);
|
DiscordClient.instance.setPresence(
|
||||||
|
{
|
||||||
|
state: buildDiscordRPCState(),
|
||||||
|
details: buildDiscordRPCDetails(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
@ -1326,16 +1355,32 @@ class PlayState extends MusicBeatSubState
|
||||||
#end
|
#end
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause)
|
if (health > Constants.HEALTH_MIN && !isGamePaused && FlxG.autoPause)
|
||||||
{
|
{
|
||||||
if (Conductor.instance.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song
|
if (Conductor.instance.songPosition > 0.0)
|
||||||
+ ' ('
|
{
|
||||||
+ storyDifficultyText
|
DiscordClient.instance.setPresence(
|
||||||
+ ')', iconRPC, true,
|
{
|
||||||
currentSongLengthMs
|
state: buildDiscordRPCState(),
|
||||||
- Conductor.instance.songPosition);
|
details: buildDiscordRPCDetails(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
|
}
|
||||||
else
|
else
|
||||||
DiscordClient.changePresence(detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
|
{
|
||||||
|
DiscordClient.instance.setPresence(
|
||||||
|
{
|
||||||
|
state: buildDiscordRPCState(),
|
||||||
|
details: buildDiscordRPCDetails(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
|
// DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true,
|
||||||
|
// currentSongLengthMs - Conductor.instance.songPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
@ -1352,8 +1397,17 @@ class PlayState extends MusicBeatSubState
|
||||||
#end
|
#end
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText,
|
if (health > Constants.HEALTH_MIN && !isGamePaused && FlxG.autoPause)
|
||||||
currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
|
{
|
||||||
|
DiscordClient.instance.setPresence(
|
||||||
|
{
|
||||||
|
state: buildDiscordRPCState(),
|
||||||
|
details: buildDiscordRPCDetails(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
|
}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
super.onFocusLost();
|
super.onFocusLost();
|
||||||
|
@ -1366,6 +1420,7 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
funkin.modding.PolymodHandler.forceReloadAssets();
|
funkin.modding.PolymodHandler.forceReloadAssets();
|
||||||
lastParams.targetSong = SongRegistry.instance.fetchEntry(currentSong.id);
|
lastParams.targetSong = SongRegistry.instance.fetchEntry(currentSong.id);
|
||||||
|
this.remove(currentStage);
|
||||||
LoadingState.loadPlayState(lastParams);
|
LoadingState.loadPlayState(lastParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1650,6 +1705,11 @@ class PlayState extends MusicBeatSubState
|
||||||
iconP2.zIndex = 850;
|
iconP2.zIndex = 850;
|
||||||
add(iconP2);
|
add(iconP2);
|
||||||
iconP2.cameras = [camHUD];
|
iconP2.cameras = [camHUD];
|
||||||
|
|
||||||
|
#if FEATURE_DISCORD_RPC
|
||||||
|
discordRPCAlbum = 'album-${currentChart.album}';
|
||||||
|
discordRPCIcon = 'icon-${currentCharacterData.opponent}';
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1765,29 +1825,53 @@ class PlayState extends MusicBeatSubState
|
||||||
function initDiscord():Void
|
function initDiscord():Void
|
||||||
{
|
{
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
storyDifficultyText = difficultyString();
|
// Determine the details strings once and reuse them.
|
||||||
iconRPC = currentSong.player2;
|
|
||||||
|
|
||||||
// To avoid having duplicate images in Discord assets
|
|
||||||
switch (iconRPC)
|
|
||||||
{
|
|
||||||
case 'senpai-angry':
|
|
||||||
iconRPC = 'senpai';
|
|
||||||
case 'monster-christmas':
|
|
||||||
iconRPC = 'monster';
|
|
||||||
case 'mom-car':
|
|
||||||
iconRPC = 'mom';
|
|
||||||
}
|
|
||||||
|
|
||||||
// String that contains the mode defined here so it isn't necessary to call changePresence for each mode
|
|
||||||
detailsText = isStoryMode ? 'Story Mode: Week $storyWeek' : 'Freeplay';
|
|
||||||
detailsPausedText = 'Paused - $detailsText';
|
|
||||||
|
|
||||||
// Updating Discord Rich Presence.
|
// Updating Discord Rich Presence.
|
||||||
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC);
|
DiscordClient.instance.setPresence(
|
||||||
|
{
|
||||||
|
state: buildDiscordRPCState(),
|
||||||
|
details: buildDiscordRPCDetails(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildDiscordRPCDetails():String
|
||||||
|
{
|
||||||
|
if (PlayStatePlaylist.isStoryMode)
|
||||||
|
{
|
||||||
|
return 'Story Mode: ${PlayStatePlaylist.campaignTitle}';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isChartingMode)
|
||||||
|
{
|
||||||
|
return 'Chart Editor [Playtest]';
|
||||||
|
}
|
||||||
|
else if (isPracticeMode)
|
||||||
|
{
|
||||||
|
return 'Freeplay [Practice]';
|
||||||
|
}
|
||||||
|
else if (isBotPlayMode)
|
||||||
|
{
|
||||||
|
return 'Freeplay [Bot Play]';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 'Freeplay';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildDiscordRPCState():String
|
||||||
|
{
|
||||||
|
var discordRPCDifficulty = PlayState.instance.currentDifficulty.replace('-', ' ').toTitleCase();
|
||||||
|
return '${currentChart.songName} [${discordRPCDifficulty}]';
|
||||||
|
}
|
||||||
|
|
||||||
function initPreciseInputs():Void
|
function initPreciseInputs():Void
|
||||||
{
|
{
|
||||||
PreciseInputManager.instance.onInputPressed.add(onKeyPress);
|
PreciseInputManager.instance.onInputPressed.add(onKeyPress);
|
||||||
|
@ -1976,13 +2060,21 @@ class PlayState extends MusicBeatSubState
|
||||||
vocals.volume = 1.0;
|
vocals.volume = 1.0;
|
||||||
vocals.pitch = playbackRate;
|
vocals.pitch = playbackRate;
|
||||||
vocals.time = FlxG.sound.music.time;
|
vocals.time = FlxG.sound.music.time;
|
||||||
trace('${FlxG.sound.music.time}');
|
// trace('${FlxG.sound.music.time}');
|
||||||
trace('${vocals.time}');
|
// trace('${vocals.time}');
|
||||||
resyncVocals();
|
resyncVocals();
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
// Updating Discord Rich Presence (with Time Left)
|
// Updating Discord Rich Presence (with Time Left)
|
||||||
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true, currentSongLengthMs);
|
DiscordClient.instance.setPresence(
|
||||||
|
{
|
||||||
|
state: buildDiscordRPCState(),
|
||||||
|
details: buildDiscordRPCDetails(),
|
||||||
|
|
||||||
|
largeImageKey: discordRPCAlbum,
|
||||||
|
smallImageKey: discordRPCIcon
|
||||||
|
});
|
||||||
|
// DiscordClient.changePresence(detailsText, '${currentChart.songName} ($discordRPCDifficulty)', discordRPCIcon, true, currentSongLengthMs);
|
||||||
#end
|
#end
|
||||||
|
|
||||||
if (startTimestamp > 0)
|
if (startTimestamp > 0)
|
||||||
|
@ -2578,7 +2670,7 @@ class PlayState extends MusicBeatSubState
|
||||||
*/
|
*/
|
||||||
function debugKeyShit():Void
|
function debugKeyShit():Void
|
||||||
{
|
{
|
||||||
#if FEATURE_CHART_EDITOR
|
#if FEATURE_STAGE_EDITOR
|
||||||
// Open the stage editor overlaying the current state.
|
// Open the stage editor overlaying the current state.
|
||||||
if (controls.DEBUG_STAGE)
|
if (controls.DEBUG_STAGE)
|
||||||
{
|
{
|
||||||
|
@ -2587,7 +2679,9 @@ class PlayState extends MusicBeatSubState
|
||||||
persistentUpdate = false;
|
persistentUpdate = false;
|
||||||
openSubState(new StageOffsetSubState());
|
openSubState(new StageOffsetSubState());
|
||||||
}
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
#if FEATURE_CHART_EDITOR
|
||||||
// Redirect to the chart editor playing the current song.
|
// Redirect to the chart editor playing the current song.
|
||||||
if (controls.DEBUG_CHART)
|
if (controls.DEBUG_CHART)
|
||||||
{
|
{
|
||||||
|
@ -2595,11 +2689,13 @@ class PlayState extends MusicBeatSubState
|
||||||
persistentUpdate = false;
|
persistentUpdate = false;
|
||||||
if (isChartingMode)
|
if (isChartingMode)
|
||||||
{
|
{
|
||||||
|
// Close the playtest substate.
|
||||||
FlxG.sound.music?.pause();
|
FlxG.sound.music?.pause();
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
this.remove(currentStage);
|
||||||
FlxG.switchState(() -> new ChartEditorState(
|
FlxG.switchState(() -> new ChartEditorState(
|
||||||
{
|
{
|
||||||
targetSongId: currentSong.id,
|
targetSongId: currentSong.id,
|
||||||
|
@ -2949,6 +3045,7 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION;
|
targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION;
|
||||||
}
|
}
|
||||||
|
this.remove(currentStage);
|
||||||
LoadingState.loadPlayState(
|
LoadingState.loadPlayState(
|
||||||
{
|
{
|
||||||
targetSong: targetSong,
|
targetSong: targetSong,
|
||||||
|
@ -2966,6 +3063,7 @@ class PlayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION;
|
targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION;
|
||||||
}
|
}
|
||||||
|
this.remove(currentStage);
|
||||||
LoadingState.loadPlayState(
|
LoadingState.loadPlayState(
|
||||||
{
|
{
|
||||||
targetSong: targetSong,
|
targetSong: targetSong,
|
||||||
|
|
|
@ -74,6 +74,8 @@ class ResultState extends MusicBeatSubState
|
||||||
|
|
||||||
var playerCharacterId:Null<String>;
|
var playerCharacterId:Null<String>;
|
||||||
|
|
||||||
|
var introMusicAudio:Null<FunkinSound>;
|
||||||
|
|
||||||
var rankBg:FunkinSprite;
|
var rankBg:FunkinSprite;
|
||||||
final cameraBG:FunkinCamera;
|
final cameraBG:FunkinCamera;
|
||||||
final cameraScroll:FunkinCamera;
|
final cameraScroll:FunkinCamera;
|
||||||
|
@ -413,7 +415,8 @@ class ResultState extends MusicBeatSubState
|
||||||
if (Assets.exists(introMusic))
|
if (Assets.exists(introMusic))
|
||||||
{
|
{
|
||||||
// Play the intro music.
|
// Play the intro music.
|
||||||
FunkinSound.load(introMusic, 1.0, false, true, true, () -> {
|
introMusicAudio = FunkinSound.load(introMusic, 1.0, false, true, true, () -> {
|
||||||
|
introMusicAudio = null;
|
||||||
FunkinSound.playMusic(getMusicPath(playerCharacter, rank),
|
FunkinSound.playMusic(getMusicPath(playerCharacter, rank),
|
||||||
{
|
{
|
||||||
startingVolume: 1.0,
|
startingVolume: 1.0,
|
||||||
|
@ -727,9 +730,34 @@ class ResultState extends MusicBeatSubState
|
||||||
|
|
||||||
if (controls.PAUSE)
|
if (controls.PAUSE)
|
||||||
{
|
{
|
||||||
if (FlxG.sound.music != null)
|
if (introMusicAudio != null) {
|
||||||
|
@:nullSafety(Off)
|
||||||
|
introMusicAudio.onComplete = null;
|
||||||
|
|
||||||
|
FlxTween.tween(introMusicAudio, {volume: 0}, 0.8, {
|
||||||
|
onComplete: _ -> {
|
||||||
|
if (introMusicAudio != null) {
|
||||||
|
introMusicAudio.stop();
|
||||||
|
introMusicAudio.destroy();
|
||||||
|
introMusicAudio = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
FlxTween.tween(introMusicAudio, {pitch: 3}, 0.1,
|
||||||
{
|
{
|
||||||
FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8);
|
onComplete: _ -> {
|
||||||
|
FlxTween.tween(introMusicAudio, {pitch: 0.5}, 0.4);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (FlxG.sound.music != null)
|
||||||
|
{
|
||||||
|
FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8, {
|
||||||
|
onComplete: _ -> {
|
||||||
|
FlxG.sound.music.stop();
|
||||||
|
FlxG.sound.music.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1,
|
FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1,
|
||||||
{
|
{
|
||||||
onComplete: _ -> {
|
onComplete: _ -> {
|
||||||
|
|
|
@ -147,7 +147,7 @@ class AnimateAtlasCharacter extends BaseCharacter
|
||||||
|
|
||||||
if (getAnimationData() != null && getAnimationData().looped)
|
if (getAnimationData() != null && getAnimationData().looped)
|
||||||
{
|
{
|
||||||
playAnimation(prefix, true, false);
|
playAnimation(currentAnimName, true, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -299,7 +299,7 @@ class BaseCharacter extends Bopper
|
||||||
{
|
{
|
||||||
super.onAnimationFinished(animationName);
|
super.onAnimationFinished(animationName);
|
||||||
|
|
||||||
trace('${characterId} has finished animation: ${animationName}');
|
// trace('${characterId} has finished animation: ${animationName}');
|
||||||
if ((animationName.endsWith(Constants.ANIMATION_END_SUFFIX) && !animationName.startsWith('idle') && !animationName.startsWith('dance'))
|
if ((animationName.endsWith(Constants.ANIMATION_END_SUFFIX) && !animationName.startsWith('idle') && !animationName.startsWith('dance'))
|
||||||
|| animationName.startsWith('combo')
|
|| animationName.startsWith('combo')
|
||||||
|| animationName.startsWith('drop'))
|
|| animationName.startsWith('drop'))
|
||||||
|
@ -317,6 +317,11 @@ class BaseCharacter extends Bopper
|
||||||
this.cameraFocusPoint = new FlxPoint(charCenterX + _data.cameraOffsets[0], charCenterY + _data.cameraOffsets[1]);
|
this.cameraFocusPoint = new FlxPoint(charCenterX + _data.cameraOffsets[0], charCenterY + _data.cameraOffsets[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHealthIconId():String
|
||||||
|
{
|
||||||
|
return _data?.healthIcon?.id ?? Constants.DEFAULT_HEALTH_ICON;
|
||||||
|
}
|
||||||
|
|
||||||
public function initHealthIcon(isOpponent:Bool):Void
|
public function initHealthIcon(isOpponent:Bool):Void
|
||||||
{
|
{
|
||||||
if (!isOpponent)
|
if (!isOpponent)
|
||||||
|
@ -326,7 +331,7 @@ class BaseCharacter extends Bopper
|
||||||
trace('[WARN] Player 1 health icon not found!');
|
trace('[WARN] Player 1 health icon not found!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PlayState.instance.iconP1.configure(_data.healthIcon);
|
PlayState.instance.iconP1.configure(_data?.healthIcon);
|
||||||
PlayState.instance.iconP1.flipX = !PlayState.instance.iconP1.flipX; // BF is looking the other way.
|
PlayState.instance.iconP1.flipX = !PlayState.instance.iconP1.flipX; // BF is looking the other way.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -336,7 +341,7 @@ class BaseCharacter extends Bopper
|
||||||
trace('[WARN] Player 2 health icon not found!');
|
trace('[WARN] Player 2 health icon not found!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PlayState.instance.iconP2.configure(_data.healthIcon);
|
PlayState.instance.iconP2.configure(_data?.healthIcon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +401,7 @@ class BaseCharacter extends Bopper
|
||||||
FlxG.watch.addQuick('singTimeSec-${characterId}', singTimeSec);
|
FlxG.watch.addQuick('singTimeSec-${characterId}', singTimeSec);
|
||||||
if (holdTimer > singTimeSec && shouldStopSinging)
|
if (holdTimer > singTimeSec && shouldStopSinging)
|
||||||
{
|
{
|
||||||
trace('holdTimer reached ${holdTimer}sec (> ${singTimeSec}), stopping sing animation');
|
// trace('holdTimer reached ${holdTimer}sec (> ${singTimeSec}), stopping sing animation');
|
||||||
holdTimer = 0;
|
holdTimer = 0;
|
||||||
|
|
||||||
var currentAnimation:String = getCurrentAnimation();
|
var currentAnimation:String = getCurrentAnimation();
|
||||||
|
@ -630,7 +635,7 @@ class BaseCharacter extends Bopper
|
||||||
var anim:String = 'sing${dir.nameUpper}${miss ? 'miss' : ''}${suffix != '' ? '-${suffix}' : ''}';
|
var anim:String = 'sing${dir.nameUpper}${miss ? 'miss' : ''}${suffix != '' ? '-${suffix}' : ''}';
|
||||||
|
|
||||||
// restart even if already playing, because the character might sing the same note twice.
|
// restart even if already playing, because the character might sing the same note twice.
|
||||||
trace('Playing ${anim}...');
|
// trace('Playing ${anim}...');
|
||||||
playAnimation(anim, true);
|
playAnimation(anim, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,12 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
* The note style to use if this one doesn't have a certain asset.
|
* The note style to use if this one doesn't have a certain asset.
|
||||||
* This can be recursive, ehe.
|
* This can be recursive, ehe.
|
||||||
*/
|
*/
|
||||||
final fallback:Null<NoteStyle>;
|
var fallback(get, never):Null<NoteStyle>;
|
||||||
|
|
||||||
|
function get_fallback():Null<NoteStyle> {
|
||||||
|
if (_data == null || _data.fallback == null) return null;
|
||||||
|
return NoteStyleRegistry.instance.fetchEntry(_data.fallback);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id The ID of the JSON file to parse.
|
* @param id The ID of the JSON file to parse.
|
||||||
|
@ -43,9 +48,6 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
_data = _fetchData(id);
|
_data = _fetchData(id);
|
||||||
|
|
||||||
var fallbackID = _data.fallback;
|
|
||||||
if (fallbackID != null) this.fallback = NoteStyleRegistry.instance.fetchEntry(fallbackID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -140,7 +142,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
if (raw)
|
if (raw)
|
||||||
{
|
{
|
||||||
var rawPath:Null<String> = _data?.assets?.note?.assetPath;
|
var rawPath:Null<String> = _data?.assets?.note?.assetPath;
|
||||||
if (rawPath == null && fallback != null) return fallback.getNoteAssetPath(true);
|
if (rawPath == null) return fallback?.getNoteAssetPath(true);
|
||||||
return rawPath;
|
return rawPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,12 +180,13 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
|
|
||||||
public function isNoteAnimated():Bool
|
public function isNoteAnimated():Bool
|
||||||
{
|
{
|
||||||
return _data.assets?.note?.animated ?? false;
|
// LOL is double ?? bad practice?
|
||||||
|
return _data.assets?.note?.animated ?? fallback?.isNoteAnimated() ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNoteScale():Float
|
public function getNoteScale():Float
|
||||||
{
|
{
|
||||||
return _data.assets?.note?.scale ?? 1.0;
|
return _data.assets?.note?.scale ?? fallback?.getNoteScale() ?? 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchNoteAnimationData(dir:NoteDirection):Null<AnimationData>
|
function fetchNoteAnimationData(dir:NoteDirection):Null<AnimationData>
|
||||||
|
@ -196,16 +199,15 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
case RIGHT: _data.assets?.note?.data?.right?.toNamed();
|
case RIGHT: _data.assets?.note?.data?.right?.toNamed();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (result == null && fallback != null) ? fallback.fetchNoteAnimationData(dir) : result;
|
return result ?? fallback?.fetchNoteAnimationData(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHoldNoteAssetPath(raw:Bool = false):Null<String>
|
public function getHoldNoteAssetPath(raw:Bool = false):Null<String>
|
||||||
{
|
{
|
||||||
if (raw)
|
if (raw)
|
||||||
{
|
{
|
||||||
// TODO: figure out why ?. didn't work here
|
var rawPath:Null<String> = _data?.assets?.holdNote?.assetPath;
|
||||||
var rawPath:Null<String> = (_data?.assets?.holdNote == null) ? null : _data?.assets?.holdNote?.assetPath;
|
return rawPath ?? fallback?.getHoldNoteAssetPath(true);
|
||||||
return (rawPath == null && fallback != null) ? fallback.getHoldNoteAssetPath(true) : rawPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// library:path
|
// library:path
|
||||||
|
@ -217,23 +219,17 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
|
|
||||||
public function isHoldNotePixel():Bool
|
public function isHoldNotePixel():Bool
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.holdNote;
|
return _data?.assets?.holdNote?.isPixel ?? fallback?.isHoldNotePixel() ?? false;
|
||||||
if (data == null && fallback != null) return fallback.isHoldNotePixel();
|
|
||||||
return data?.isPixel ?? false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchHoldNoteScale():Float
|
public function fetchHoldNoteScale():Float
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.holdNote;
|
return _data?.assets?.holdNote?.scale ?? fallback?.fetchHoldNoteScale() ?? 1.0;
|
||||||
if (data == null && fallback != null) return fallback.fetchHoldNoteScale();
|
|
||||||
return data?.scale ?? 1.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHoldNoteOffsets():Array<Float>
|
public function getHoldNoteOffsets():Array<Float>
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.holdNote;
|
return _data?.assets?.holdNote?.offsets ?? fallback?.getHoldNoteOffsets() ?? [0.0, 0.0];
|
||||||
if (data == null && fallback != null) return fallback.getHoldNoteOffsets();
|
|
||||||
return data?.offsets ?? [0.0, 0.0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyStrumlineFrames(target:StrumlineNote):Void
|
public function applyStrumlineFrames(target:StrumlineNote):Void
|
||||||
|
@ -258,9 +254,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
if (raw)
|
if (raw)
|
||||||
{
|
{
|
||||||
var rawPath:Null<String> = _data?.assets?.noteStrumline?.assetPath;
|
return _data?.assets?.noteStrumline?.assetPath ?? fallback?.getStrumlineAssetPath(true);
|
||||||
if (rawPath == null && fallback != null) return fallback.getStrumlineAssetPath(true);
|
|
||||||
return rawPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// library:path
|
// library:path
|
||||||
|
@ -282,11 +276,19 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
FlxAnimationUtil.addAtlasAnimations(target, getStrumlineAnimationData(dir));
|
FlxAnimationUtil.addAtlasAnimations(target, getStrumlineAnimationData(dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the animation data for the strumline.
|
||||||
|
* NOTE: This function only queries the fallback note style if all the animations are missing for a given direction.
|
||||||
|
*
|
||||||
|
* @param dir The direction to fetch the animation data for.
|
||||||
|
* @return The animation data for the strumline in that direction.
|
||||||
|
*/
|
||||||
function getStrumlineAnimationData(dir:NoteDirection):Array<AnimationData>
|
function getStrumlineAnimationData(dir:NoteDirection):Array<AnimationData>
|
||||||
{
|
{
|
||||||
var result:Array<Null<AnimationData>> = switch (dir)
|
var result:Array<Null<AnimationData>> = switch (dir)
|
||||||
{
|
{
|
||||||
case NoteDirection.LEFT: [
|
case NoteDirection.LEFT:
|
||||||
|
[
|
||||||
_data.assets.noteStrumline?.data?.leftStatic?.toNamed('static'),
|
_data.assets.noteStrumline?.data?.leftStatic?.toNamed('static'),
|
||||||
_data.assets.noteStrumline?.data?.leftPress?.toNamed('press'),
|
_data.assets.noteStrumline?.data?.leftPress?.toNamed('press'),
|
||||||
_data.assets.noteStrumline?.data?.leftConfirm?.toNamed('confirm'),
|
_data.assets.noteStrumline?.data?.leftConfirm?.toNamed('confirm'),
|
||||||
|
@ -313,14 +315,17 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
default: [];
|
default: [];
|
||||||
};
|
};
|
||||||
|
|
||||||
return thx.Arrays.filterNull(result);
|
// New variable so we can change the type.
|
||||||
|
var filteredResult:Array<AnimationData> = thx.Arrays.filterNull(result);
|
||||||
|
|
||||||
|
if (filteredResult.length == 0) return fallback?.getStrumlineAnimationData(dir) ?? [];
|
||||||
|
|
||||||
|
return filteredResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStrumlineOffsets():Array<Float>
|
public function getStrumlineOffsets():Array<Float>
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.noteStrumline;
|
return _data?.assets?.noteStrumline?.offsets ?? fallback?.getStrumlineOffsets() ?? [0.0, 0.0];
|
||||||
if (data == null && fallback != null) return fallback.getStrumlineOffsets();
|
|
||||||
return data?.offsets ?? [0.0, 0.0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyStrumlineOffsets(target:StrumlineNote):Void
|
public function applyStrumlineOffsets(target:StrumlineNote):Void
|
||||||
|
@ -332,21 +337,17 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
|
|
||||||
public function getStrumlineScale():Float
|
public function getStrumlineScale():Float
|
||||||
{
|
{
|
||||||
return _data?.assets?.noteStrumline?.scale ?? 1.0;
|
return _data?.assets?.noteStrumline?.scale ?? fallback?.getStrumlineScale() ?? 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isNoteSplashEnabled():Bool
|
public function isNoteSplashEnabled():Bool
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.noteSplash?.data;
|
return _data?.assets?.noteSplash?.data?.enabled ?? fallback?.isNoteSplashEnabled() ?? false;
|
||||||
if (data == null) return fallback?.isNoteSplashEnabled() ?? false;
|
|
||||||
return data.enabled ?? false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isHoldNoteCoverEnabled():Bool
|
public function isHoldNoteCoverEnabled():Bool
|
||||||
{
|
{
|
||||||
var data = _data?.assets?.holdNoteCover?.data;
|
return _data?.assets?.holdNoteCover?.data?.enabled ?? fallback?.isHoldNoteCoverEnabled() ?? false;
|
||||||
if (data == null) return fallback?.isHoldNoteCoverEnabled() ?? false;
|
|
||||||
return data.enabled ?? false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -457,20 +458,20 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
case THREE:
|
case THREE:
|
||||||
var result = _data.assets.countdownThree?.isPixel;
|
var result = _data.assets.countdownThree?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
|
if (result == null) result = fallback?.isCountdownSpritePixel(step) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case TWO:
|
case TWO:
|
||||||
var result = _data.assets.countdownTwo?.isPixel;
|
var result = _data.assets.countdownTwo?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
|
if (result == null) result = fallback?.isCountdownSpritePixel(step) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case ONE:
|
case ONE:
|
||||||
var result = _data.assets.countdownOne?.isPixel;
|
var result = _data.assets.countdownOne?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
|
if (result == null) result = fallback?.isCountdownSpritePixel(step) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case GO:
|
case GO:
|
||||||
var result = _data.assets.countdownGo?.isPixel;
|
var result = _data.assets.countdownGo?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step);
|
if (result == null) result = fallback?.isCountdownSpritePixel(step) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -482,20 +483,20 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
case THREE:
|
case THREE:
|
||||||
var result = _data.assets.countdownThree?.offsets;
|
var result = _data.assets.countdownThree?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
|
if (result == null) result = fallback?.getCountdownSpriteOffsets(step) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case TWO:
|
case TWO:
|
||||||
var result = _data.assets.countdownTwo?.offsets;
|
var result = _data.assets.countdownTwo?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
|
if (result == null) result = fallback?.getCountdownSpriteOffsets(step) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case ONE:
|
case ONE:
|
||||||
var result = _data.assets.countdownOne?.offsets;
|
var result = _data.assets.countdownOne?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
|
if (result == null) result = fallback?.getCountdownSpriteOffsets(step) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case GO:
|
case GO:
|
||||||
var result = _data.assets.countdownGo?.offsets;
|
var result = _data.assets.countdownGo?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step);
|
if (result == null) result = fallback?.getCountdownSpriteOffsets(step) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
default:
|
default:
|
||||||
return [0, 0];
|
return [0, 0];
|
||||||
}
|
}
|
||||||
|
@ -520,7 +521,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
null;
|
null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rawPath == null && fallback != null) ? fallback.getCountdownSoundPath(step, true) : rawPath;
|
return (rawPath == null) ? fallback?.getCountdownSoundPath(step, true) : rawPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// library:path
|
// library:path
|
||||||
|
@ -584,20 +585,20 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
case "sick":
|
case "sick":
|
||||||
var result = _data.assets.judgementSick?.isPixel;
|
var result = _data.assets.judgementSick?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
|
if (result == null) result = fallback?.isJudgementSpritePixel(rating) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case "good":
|
case "good":
|
||||||
var result = _data.assets.judgementGood?.isPixel;
|
var result = _data.assets.judgementGood?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
|
if (result == null) result = fallback?.isJudgementSpritePixel(rating) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case "bad":
|
case "bad":
|
||||||
var result = _data.assets.judgementBad?.isPixel;
|
var result = _data.assets.judgementBad?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
|
if (result == null) result = fallback?.isJudgementSpritePixel(rating) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case "shit":
|
case "shit":
|
||||||
var result = _data.assets.judgementShit?.isPixel;
|
var result = _data.assets.judgementShit?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
|
if (result == null) result = fallback?.isJudgementSpritePixel(rating) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -635,20 +636,20 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
case "sick":
|
case "sick":
|
||||||
var result = _data.assets.judgementSick?.offsets;
|
var result = _data.assets.judgementSick?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
|
if (result == null) result = fallback?.getJudgementSpriteOffsets(rating) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case "good":
|
case "good":
|
||||||
var result = _data.assets.judgementGood?.offsets;
|
var result = _data.assets.judgementGood?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
|
if (result == null) result = fallback?.getJudgementSpriteOffsets(rating) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case "bad":
|
case "bad":
|
||||||
var result = _data.assets.judgementBad?.offsets;
|
var result = _data.assets.judgementBad?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
|
if (result == null) result = fallback?.getJudgementSpriteOffsets(rating) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case "shit":
|
case "shit":
|
||||||
var result = _data.assets.judgementShit?.offsets;
|
var result = _data.assets.judgementShit?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating);
|
if (result == null) result = fallback?.getJudgementSpriteOffsets(rating) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
default:
|
default:
|
||||||
return [0, 0];
|
return [0, 0];
|
||||||
}
|
}
|
||||||
|
@ -749,44 +750,44 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
var result = _data.assets.comboNumber0?.isPixel;
|
var result = _data.assets.comboNumber0?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 1:
|
case 1:
|
||||||
var result = _data.assets.comboNumber1?.isPixel;
|
var result = _data.assets.comboNumber1?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 2:
|
case 2:
|
||||||
var result = _data.assets.comboNumber2?.isPixel;
|
var result = _data.assets.comboNumber2?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 3:
|
case 3:
|
||||||
var result = _data.assets.comboNumber3?.isPixel;
|
var result = _data.assets.comboNumber3?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 4:
|
case 4:
|
||||||
var result = _data.assets.comboNumber4?.isPixel;
|
var result = _data.assets.comboNumber4?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 5:
|
case 5:
|
||||||
var result = _data.assets.comboNumber5?.isPixel;
|
var result = _data.assets.comboNumber5?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 6:
|
case 6:
|
||||||
var result = _data.assets.comboNumber6?.isPixel;
|
var result = _data.assets.comboNumber6?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 7:
|
case 7:
|
||||||
var result = _data.assets.comboNumber7?.isPixel;
|
var result = _data.assets.comboNumber7?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 8:
|
case 8:
|
||||||
var result = _data.assets.comboNumber8?.isPixel;
|
var result = _data.assets.comboNumber8?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
case 9:
|
case 9:
|
||||||
var result = _data.assets.comboNumber9?.isPixel;
|
var result = _data.assets.comboNumber9?.isPixel;
|
||||||
if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit);
|
if (result == null) result = fallback?.isComboNumSpritePixel(digit) ?? false;
|
||||||
return result ?? false;
|
return result;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -836,44 +837,44 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
var result = _data.assets.comboNumber0?.offsets;
|
var result = _data.assets.comboNumber0?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 1:
|
case 1:
|
||||||
var result = _data.assets.comboNumber1?.offsets;
|
var result = _data.assets.comboNumber1?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 2:
|
case 2:
|
||||||
var result = _data.assets.comboNumber2?.offsets;
|
var result = _data.assets.comboNumber2?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 3:
|
case 3:
|
||||||
var result = _data.assets.comboNumber3?.offsets;
|
var result = _data.assets.comboNumber3?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 4:
|
case 4:
|
||||||
var result = _data.assets.comboNumber4?.offsets;
|
var result = _data.assets.comboNumber4?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 5:
|
case 5:
|
||||||
var result = _data.assets.comboNumber5?.offsets;
|
var result = _data.assets.comboNumber5?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 6:
|
case 6:
|
||||||
var result = _data.assets.comboNumber6?.offsets;
|
var result = _data.assets.comboNumber6?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 7:
|
case 7:
|
||||||
var result = _data.assets.comboNumber7?.offsets;
|
var result = _data.assets.comboNumber7?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 8:
|
case 8:
|
||||||
var result = _data.assets.comboNumber8?.offsets;
|
var result = _data.assets.comboNumber8?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
case 9:
|
case 9:
|
||||||
var result = _data.assets.comboNumber9?.offsets;
|
var result = _data.assets.comboNumber9?.offsets;
|
||||||
if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit);
|
if (result == null) result = fallback?.getComboNumSpriteOffsets(digit) ?? [0, 0];
|
||||||
return result ?? [0, 0];
|
return result;
|
||||||
default:
|
default:
|
||||||
return [0, 0];
|
return [0, 0];
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,6 +156,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
{
|
{
|
||||||
for (vari in _data.playData.songVariations)
|
for (vari in _data.playData.songVariations)
|
||||||
{
|
{
|
||||||
|
if (!validateVariationId(vari)) {
|
||||||
|
trace(' [WARN] Variation id "$vari" is invalid, skipping...');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var variMeta:Null<SongMetadata> = fetchVariationMetadata(id, vari);
|
var variMeta:Null<SongMetadata> = fetchVariationMetadata(id, vari);
|
||||||
if (variMeta != null)
|
if (variMeta != null)
|
||||||
{
|
{
|
||||||
|
@ -407,7 +412,6 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
if (possibleVariations == null)
|
if (possibleVariations == null)
|
||||||
{
|
{
|
||||||
possibleVariations = getVariationsByCharacter(currentCharacter);
|
possibleVariations = getVariationsByCharacter(currentCharacter);
|
||||||
possibleVariations.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
|
|
||||||
}
|
}
|
||||||
if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0];
|
if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0];
|
||||||
|
|
||||||
|
@ -428,7 +432,12 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
*/
|
*/
|
||||||
public function getVariationsByCharacter(?char:PlayableCharacter):Array<String>
|
public function getVariationsByCharacter(?char:PlayableCharacter):Array<String>
|
||||||
{
|
{
|
||||||
if (char == null) return variations;
|
if (char == null)
|
||||||
|
{
|
||||||
|
var result = variations;
|
||||||
|
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
var result = [];
|
var result = [];
|
||||||
trace('Evaluating variations for ${this.id} ${char.id}: ${this.variations}');
|
trace('Evaluating variations for ${this.id} ${char.id}: ${this.variations}');
|
||||||
|
@ -445,6 +454,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,18 +476,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
|
|
||||||
if (variationIds.length == 0) return [];
|
if (variationIds.length == 0) return [];
|
||||||
|
|
||||||
// The difficulties array contains entries like 'normal', 'nightmare-erect', and 'normal-pico',
|
var diffFiltered:Array<String> = variationIds.map(function(variationId:String):Array<String> {
|
||||||
// so we have to map it to the actual difficulty names.
|
var metadata = _metadata.get(variationId);
|
||||||
// We also filter out difficulties that don't match the variation or that don't exist.
|
return metadata?.playData?.difficulties ?? [];
|
||||||
|
|
||||||
var diffFiltered:Array<String> = difficulties.keys()
|
|
||||||
.array()
|
|
||||||
.map(function(diffId:String):Null<String> {
|
|
||||||
var difficulty:Null<SongDifficulty> = difficulties.get(diffId);
|
|
||||||
if (difficulty == null) return null;
|
|
||||||
if (variationIds.length > 0 && !variationIds.contains(difficulty.variation)) return null;
|
|
||||||
return difficulty.difficulty;
|
|
||||||
})
|
})
|
||||||
|
.flatten()
|
||||||
.filterNull()
|
.filterNull()
|
||||||
.distinct();
|
.distinct();
|
||||||
|
|
||||||
|
@ -489,11 +493,15 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST));
|
diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST_FULL));
|
||||||
|
|
||||||
return diffFiltered;
|
return diffFiltered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: This line of code makes me sad, but you can't really fix it without a breaking migration.
|
||||||
|
* @return `easy`, `erect`, `normal-pico`, etc.
|
||||||
|
*/
|
||||||
public function listSuffixedDifficulties(variationIds:Array<String>, ?showLocked:Bool, ?showHidden:Bool):Array<String>
|
public function listSuffixedDifficulties(variationIds:Array<String>, ?showLocked:Bool, ?showHidden:Bool):Array<String>
|
||||||
{
|
{
|
||||||
var result = [];
|
var result = [];
|
||||||
|
@ -509,6 +517,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST_FULL));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,6 +639,19 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
||||||
var meta:Null<SongMetadata> = SongRegistry.instance.parseEntryMetadataWithMigration(id, vari, version);
|
var meta:Null<SongMetadata> = SongRegistry.instance.parseEntryMetadataWithMigration(id, vari, version);
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final VARIATION_REGEX = ~/^[a-z][a-z0-9]+$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that the variation ID is valid.
|
||||||
|
* Auto-accept if it's one of the base game default variations.
|
||||||
|
* Reject if the ID starts with a number, or contains invalid characters.
|
||||||
|
*/
|
||||||
|
static function validateVariationId(variation:String):Bool {
|
||||||
|
if (Constants.DEFAULT_VARIATION_LIST.contains(variation)) return true;
|
||||||
|
|
||||||
|
return VARIATION_REGEX.match(variation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SongDifficulty
|
class SongDifficulty
|
||||||
|
|
|
@ -258,6 +258,9 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
|
||||||
|
|
||||||
propSprite.zIndex = dataProp.zIndex;
|
propSprite.zIndex = dataProp.zIndex;
|
||||||
|
|
||||||
|
propSprite.flipX = dataProp.flipX;
|
||||||
|
propSprite.flipY = dataProp.flipY;
|
||||||
|
|
||||||
switch (dataProp.animType)
|
switch (dataProp.animType)
|
||||||
{
|
{
|
||||||
case 'packer':
|
case 'packer':
|
||||||
|
|
|
@ -603,11 +603,14 @@ class Save
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var newCompletion = (newScoreData.tallies.sick + newScoreData.tallies.good) / newScoreData.tallies.totalNotes;
|
||||||
|
var previousCompletion = (previousScoreData.tallies.sick + previousScoreData.tallies.good) / previousScoreData.tallies.totalNotes;
|
||||||
|
|
||||||
// Set the high score and the high rank separately.
|
// Set the high score and the high rank separately.
|
||||||
var newScore:SaveScoreData =
|
var newScore:SaveScoreData =
|
||||||
{
|
{
|
||||||
score: (previousScoreData.score > newScoreData.score) ? previousScoreData.score : newScoreData.score,
|
score: (previousScoreData.score > newScoreData.score) ? previousScoreData.score : newScoreData.score,
|
||||||
tallies: (previousRank > newRank) ? previousScoreData.tallies : newScoreData.tallies
|
tallies: (previousRank > newRank || previousCompletion > newCompletion) ? previousScoreData.tallies : newScoreData.tallies
|
||||||
};
|
};
|
||||||
|
|
||||||
song.set(difficultyId, newScore);
|
song.set(difficultyId, newScore);
|
||||||
|
|
|
@ -50,8 +50,13 @@ class PixelatedIcon extends FlxFilteredSprite
|
||||||
if (!openfl.utils.Assets.exists(Paths.image(charPath)))
|
if (!openfl.utils.Assets.exists(Paths.image(charPath)))
|
||||||
{
|
{
|
||||||
trace('[WARN] Character ${char} has no freeplay icon.');
|
trace('[WARN] Character ${char} has no freeplay icon.');
|
||||||
|
this.visible = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
var isAnimated = openfl.utils.Assets.exists(Paths.file('images/$charPath.xml'));
|
var isAnimated = openfl.utils.Assets.exists(Paths.file('images/$charPath.xml'));
|
||||||
|
|
||||||
|
|
|
@ -2274,8 +2274,25 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
||||||
this.openBackupAvailableDialog(welcomeDialog);
|
this.openBackupAvailableDialog(welcomeDialog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FEATURE_DISCORD_RPC
|
||||||
|
updateDiscordRPC();
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FEATURE_DISCORD_RPC
|
||||||
|
function updateDiscordRPC():Void
|
||||||
|
{
|
||||||
|
funkin.api.discord.DiscordClient.instance.setPresence(
|
||||||
|
{
|
||||||
|
// TODO: Make this display the song name and update when it changes.
|
||||||
|
// state: '${currentSongName} [${selectedDifficulty}]',
|
||||||
|
state: null,
|
||||||
|
details: 'Chart Editor [Charting]'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
function setupWelcomeMusic()
|
function setupWelcomeMusic()
|
||||||
{
|
{
|
||||||
this.welcomeMusic.loadEmbedded(Paths.music('chartEditorLoop/chartEditorLoop'));
|
this.welcomeMusic.loadEmbedded(Paths.music('chartEditorLoop/chartEditorLoop'));
|
||||||
|
|
|
@ -54,6 +54,9 @@ import funkin.util.SortUtil;
|
||||||
import openfl.display.BlendMode;
|
import openfl.display.BlendMode;
|
||||||
import funkin.data.freeplay.style.FreeplayStyleRegistry;
|
import funkin.data.freeplay.style.FreeplayStyleRegistry;
|
||||||
import funkin.data.song.SongData.SongMusicData;
|
import funkin.data.song.SongData.SongMusicData;
|
||||||
|
#if FEATURE_DISCORD_RPC
|
||||||
|
import funkin.api.discord.DiscordClient;
|
||||||
|
#end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters used to initialize the FreeplayState.
|
* Parameters used to initialize the FreeplayState.
|
||||||
|
@ -144,11 +147,37 @@ class FreeplayState extends MusicBeatSubState
|
||||||
|
|
||||||
var songs:Array<Null<FreeplaySongData>> = [];
|
var songs:Array<Null<FreeplaySongData>> = [];
|
||||||
|
|
||||||
|
// List of available difficulties for the current song, without `-variation` at the end (no duplicates or nulls).
|
||||||
var diffIdsCurrent:Array<String> = [];
|
var diffIdsCurrent:Array<String> = [];
|
||||||
|
// List of available difficulties for the total song list, without `-variation` at the end (no duplicates or nulls).
|
||||||
var diffIdsTotal:Array<String> = [];
|
var diffIdsTotal:Array<String> = [];
|
||||||
|
// List of available difficulties for the current song, with `-variation` at the end (no duplicates or nulls).
|
||||||
|
var suffixedDiffIdsCurrent:Array<String> = [];
|
||||||
|
// List of available difficulties for the total song list, with `-variation` at the end (no duplicates or nulls).
|
||||||
|
var suffixedDiffIdsTotal:Array<String> = [];
|
||||||
|
|
||||||
var curSelected:Int = 0;
|
var curSelected:Int = 0;
|
||||||
var currentDifficulty:String = Constants.DEFAULT_DIFFICULTY;
|
var currentSuffixedDifficulty:String = Constants.DEFAULT_DIFFICULTY;
|
||||||
|
var currentUnsuffixedDifficulty(get, never):String;
|
||||||
|
|
||||||
|
function get_currentUnsuffixedDifficulty():String
|
||||||
|
{
|
||||||
|
if (Constants.DEFAULT_DIFFICULTY_LIST_FULL.contains(currentSuffixedDifficulty)) return currentSuffixedDifficulty;
|
||||||
|
|
||||||
|
// Else, we need to strip the suffix.
|
||||||
|
return currentSuffixedDifficulty.substring(0, currentSuffixedDifficulty.lastIndexOf('-'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentVariation(get, never):String;
|
||||||
|
|
||||||
|
function get_currentVariation():String
|
||||||
|
{
|
||||||
|
if (Constants.DEFAULT_DIFFICULTY_LIST.contains(currentSuffixedDifficulty)) return Constants.DEFAULT_VARIATION;
|
||||||
|
if (Constants.DEFAULT_DIFFICULTY_LIST_ERECT.contains(currentSuffixedDifficulty)) return 'erect';
|
||||||
|
|
||||||
|
// Else, we need to isolate the suffix.
|
||||||
|
return currentSuffixedDifficulty.substring(currentSuffixedDifficulty.lastIndexOf('-') + 1, currentSuffixedDifficulty.length);
|
||||||
|
}
|
||||||
|
|
||||||
public var fp:FreeplayScore;
|
public var fp:FreeplayScore;
|
||||||
|
|
||||||
|
@ -312,7 +341,7 @@ class FreeplayState extends MusicBeatSubState
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
// Updating Discord Rich Presence
|
// Updating Discord Rich Presence
|
||||||
DiscordClient.changePresence('In the Menus', null);
|
DiscordClient.instance.setPresence({state: 'In the Menus', details: null});
|
||||||
#end
|
#end
|
||||||
|
|
||||||
var isDebug:Bool = false;
|
var isDebug:Bool = false;
|
||||||
|
@ -356,11 +385,15 @@ class FreeplayState extends MusicBeatSubState
|
||||||
trace('Available Difficulties: $availableDifficultiesForSong');
|
trace('Available Difficulties: $availableDifficultiesForSong');
|
||||||
if (availableDifficultiesForSong.length == 0) continue;
|
if (availableDifficultiesForSong.length == 0) continue;
|
||||||
|
|
||||||
songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations));
|
songs.push(new FreeplaySongData(levelId, songId, song, currentCharacter, displayedVariations));
|
||||||
for (difficulty in unsuffixedDifficulties)
|
for (difficulty in unsuffixedDifficulties)
|
||||||
{
|
{
|
||||||
diffIdsTotal.pushUnique(difficulty);
|
diffIdsTotal.pushUnique(difficulty);
|
||||||
}
|
}
|
||||||
|
for (difficulty in availableDifficultiesForSong)
|
||||||
|
{
|
||||||
|
suffixedDiffIdsTotal.pushUnique(difficulty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +486,7 @@ class FreeplayState extends MusicBeatSubState
|
||||||
wait: 0.1
|
wait: 0.1
|
||||||
});
|
});
|
||||||
|
|
||||||
for (diffId in diffIdsTotal)
|
for (diffId in suffixedDiffIdsTotal)
|
||||||
{
|
{
|
||||||
var diffSprite:DifficultySprite = new DifficultySprite(diffId);
|
var diffSprite:DifficultySprite = new DifficultySprite(diffId);
|
||||||
diffSprite.difficultyId = diffId;
|
diffSprite.difficultyId = diffId;
|
||||||
|
@ -467,7 +500,7 @@ class FreeplayState extends MusicBeatSubState
|
||||||
for (diffSprite in grpDifficulties.group.members)
|
for (diffSprite in grpDifficulties.group.members)
|
||||||
{
|
{
|
||||||
if (diffSprite == null) continue;
|
if (diffSprite == null) continue;
|
||||||
if (diffSprite.difficultyId == currentDifficulty) diffSprite.visible = true;
|
if (diffSprite.difficultyId == currentSuffixedDifficulty) diffSprite.visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
albumRoll.albumId = null;
|
albumRoll.albumId = null;
|
||||||
|
@ -743,17 +776,14 @@ class FreeplayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
var tempSongs:Array<Null<FreeplaySongData>> = songs;
|
var tempSongs:Array<Null<FreeplaySongData>> = songs;
|
||||||
|
|
||||||
// Remember just the difficulty because it's important for song sorting.
|
|
||||||
currentDifficulty = rememberedDifficulty;
|
|
||||||
|
|
||||||
if (filterStuff != null) tempSongs = sortSongs(tempSongs, filterStuff);
|
if (filterStuff != null) tempSongs = sortSongs(tempSongs, filterStuff);
|
||||||
|
|
||||||
// Filter further by current selected difficulty.
|
// Filter further by current selected difficulty.
|
||||||
if (currentDifficulty != null)
|
if (currentSuffixedDifficulty != null)
|
||||||
{
|
{
|
||||||
tempSongs = tempSongs.filter(song -> {
|
tempSongs = tempSongs.filter(song -> {
|
||||||
if (song == null) return true; // Random
|
if (song == null) return true; // Random
|
||||||
return song.songDifficulties.contains(currentDifficulty);
|
return song.suffixedSongDifficulties.contains(currentSuffixedDifficulty);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1344,7 +1374,6 @@ class FreeplayState extends MusicBeatSubState
|
||||||
var dyTouch:Float = 0;
|
var dyTouch:Float = 0;
|
||||||
var velTouch:Float = 0;
|
var velTouch:Float = 0;
|
||||||
|
|
||||||
var veloctiyLoopShit:Float = 0;
|
|
||||||
var touchTimer:Float = 0;
|
var touchTimer:Float = 0;
|
||||||
|
|
||||||
var initTouchPos:FlxPoint = new FlxPoint();
|
var initTouchPos:FlxPoint = new FlxPoint();
|
||||||
|
@ -1756,16 +1785,18 @@ class FreeplayState extends MusicBeatSubState
|
||||||
{
|
{
|
||||||
touchTimer = 0;
|
touchTimer = 0;
|
||||||
|
|
||||||
var currentDifficultyIndex:Int = diffIdsCurrent.indexOf(currentDifficulty);
|
var currentDifficultyIndex:Int = suffixedDiffIdsCurrent.indexOf(currentSuffixedDifficulty);
|
||||||
|
|
||||||
if (currentDifficultyIndex == -1) currentDifficultyIndex = diffIdsCurrent.indexOf(Constants.DEFAULT_DIFFICULTY);
|
if (currentDifficultyIndex == -1) currentDifficultyIndex = suffixedDiffIdsCurrent.indexOf(Constants.DEFAULT_DIFFICULTY);
|
||||||
|
|
||||||
currentDifficultyIndex += change;
|
currentDifficultyIndex += change;
|
||||||
|
|
||||||
if (currentDifficultyIndex < 0) currentDifficultyIndex = diffIdsCurrent.length - 1;
|
if (currentDifficultyIndex < 0) currentDifficultyIndex = suffixedDiffIdsCurrent.length - 1;
|
||||||
if (currentDifficultyIndex >= diffIdsCurrent.length) currentDifficultyIndex = 0;
|
if (currentDifficultyIndex >= suffixedDiffIdsCurrent.length) currentDifficultyIndex = 0;
|
||||||
|
|
||||||
currentDifficulty = diffIdsCurrent[currentDifficultyIndex];
|
currentSuffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex];
|
||||||
|
|
||||||
|
trace('Switching to difficulty: ${currentSuffixedDifficulty}');
|
||||||
|
|
||||||
var daSong:Null<FreeplaySongData> = grpCapsules.members[curSelected].songData;
|
var daSong:Null<FreeplaySongData> = grpCapsules.members[curSelected].songData;
|
||||||
if (daSong != null)
|
if (daSong != null)
|
||||||
|
@ -1776,22 +1807,20 @@ class FreeplayState extends MusicBeatSubState
|
||||||
FlxG.log.warn('WARN: could not find song with id (${daSong.songId})');
|
FlxG.log.warn('WARN: could not find song with id (${daSong.songId})');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty, currentCharacter) ?? '';
|
|
||||||
|
|
||||||
// TODO: This line of code makes me sad, but you can't really fix it without a breaking migration.
|
var suffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex];
|
||||||
var suffixedDifficulty = (targetVariation != Constants.DEFAULT_VARIATION
|
|
||||||
&& targetVariation != 'erect') ? '$currentDifficulty-${targetVariation}' : currentDifficulty;
|
|
||||||
var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSong.songId, suffixedDifficulty);
|
var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSong.songId, suffixedDifficulty);
|
||||||
trace(songScore);
|
trace(songScore);
|
||||||
intendedScore = songScore?.score ?? 0;
|
intendedScore = songScore?.score ?? 0;
|
||||||
intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
|
intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
|
||||||
rememberedDifficulty = suffixedDifficulty;
|
rememberedDifficulty = suffixedDifficulty;
|
||||||
|
currentSuffixedDifficulty = suffixedDifficulty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
intendedScore = 0;
|
intendedScore = 0;
|
||||||
intendedCompletion = 0.0;
|
intendedCompletion = 0.0;
|
||||||
rememberedDifficulty = currentDifficulty;
|
rememberedDifficulty = currentSuffixedDifficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intendedCompletion == Math.POSITIVE_INFINITY || intendedCompletion == Math.NEGATIVE_INFINITY || Math.isNaN(intendedCompletion))
|
if (intendedCompletion == Math.POSITIVE_INFINITY || intendedCompletion == Math.NEGATIVE_INFINITY || Math.isNaN(intendedCompletion))
|
||||||
|
@ -1806,7 +1835,7 @@ class FreeplayState extends MusicBeatSubState
|
||||||
for (diffSprite in grpDifficulties.group.members)
|
for (diffSprite in grpDifficulties.group.members)
|
||||||
{
|
{
|
||||||
if (diffSprite == null) continue;
|
if (diffSprite == null) continue;
|
||||||
if (diffSprite.difficultyId == currentDifficulty)
|
if (diffSprite.difficultyId == currentSuffixedDifficulty)
|
||||||
{
|
{
|
||||||
if (change != 0)
|
if (change != 0)
|
||||||
{
|
{
|
||||||
|
@ -1833,7 +1862,9 @@ class FreeplayState extends MusicBeatSubState
|
||||||
if (songCapsule == null) continue;
|
if (songCapsule == null) continue;
|
||||||
if (songCapsule.songData != null)
|
if (songCapsule.songData != null)
|
||||||
{
|
{
|
||||||
songCapsule.songData.currentDifficulty = currentDifficulty;
|
songCapsule.songData.currentVariation = currentVariation;
|
||||||
|
songCapsule.songData.currentUnsuffixedDifficulty = currentUnsuffixedDifficulty;
|
||||||
|
songCapsule.songData.currentSuffixedDifficulty = currentSuffixedDifficulty;
|
||||||
songCapsule.init(null, null, songCapsule.songData);
|
songCapsule.init(null, null, songCapsule.songData);
|
||||||
songCapsule.checkClip();
|
songCapsule.checkClip();
|
||||||
}
|
}
|
||||||
|
@ -1921,8 +1952,9 @@ class FreeplayState extends MusicBeatSubState
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var targetSong:Song = targetSongNullable;
|
var targetSong:Song = targetSongNullable;
|
||||||
var targetDifficultyId:String = currentDifficulty;
|
var targetDifficultyId:String = currentUnsuffixedDifficulty;
|
||||||
var targetVariation:Null<String> = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter);
|
var targetVariation:Null<String> = currentVariation;
|
||||||
|
trace('target song: ${targetSongId} (${targetVariation})');
|
||||||
var targetLevelId:Null<String> = cap?.songData?.levelId;
|
var targetLevelId:Null<String> = cap?.songData?.levelId;
|
||||||
PlayStatePlaylist.campaignId = targetLevelId ?? null;
|
PlayStatePlaylist.campaignId = targetLevelId ?? null;
|
||||||
|
|
||||||
|
@ -2002,8 +2034,8 @@ class FreeplayState extends MusicBeatSubState
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var targetSong:Song = targetSongNullable;
|
var targetSong:Song = targetSongNullable;
|
||||||
var targetDifficultyId:String = currentDifficulty;
|
var targetDifficultyId:String = currentUnsuffixedDifficulty;
|
||||||
var targetVariation:Null<String> = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter);
|
var targetVariation:Null<String> = currentVariation;
|
||||||
var targetLevelId:Null<String> = cap?.songData?.levelId;
|
var targetLevelId:Null<String> = cap?.songData?.levelId;
|
||||||
PlayStatePlaylist.campaignId = targetLevelId ?? null;
|
PlayStatePlaylist.campaignId = targetLevelId ?? null;
|
||||||
|
|
||||||
|
@ -2069,7 +2101,7 @@ class FreeplayState extends MusicBeatSubState
|
||||||
|
|
||||||
if (rememberedDifficulty != null)
|
if (rememberedDifficulty != null)
|
||||||
{
|
{
|
||||||
currentDifficulty = rememberedDifficulty;
|
currentSuffixedDifficulty = rememberedDifficulty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2087,10 +2119,11 @@ class FreeplayState extends MusicBeatSubState
|
||||||
var daSongCapsule:SongMenuItem = grpCapsules.members[curSelected];
|
var daSongCapsule:SongMenuItem = grpCapsules.members[curSelected];
|
||||||
if (daSongCapsule.songData != null)
|
if (daSongCapsule.songData != null)
|
||||||
{
|
{
|
||||||
var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSongCapsule.songData.songId, currentDifficulty);
|
var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSongCapsule.songData.songId, currentSuffixedDifficulty);
|
||||||
intendedScore = songScore?.score ?? 0;
|
intendedScore = songScore?.score ?? 0;
|
||||||
intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
|
intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
|
||||||
diffIdsCurrent = daSongCapsule.songData.songDifficulties;
|
diffIdsCurrent = daSongCapsule.songData.songDifficulties;
|
||||||
|
suffixedDiffIdsCurrent = daSongCapsule.songData.suffixedSongDifficulties;
|
||||||
rememberedSongId = daSongCapsule.songData.songId;
|
rememberedSongId = daSongCapsule.songData.songId;
|
||||||
changeDiff();
|
changeDiff();
|
||||||
}
|
}
|
||||||
|
@ -2099,6 +2132,7 @@ class FreeplayState extends MusicBeatSubState
|
||||||
intendedScore = 0;
|
intendedScore = 0;
|
||||||
intendedCompletion = 0.0;
|
intendedCompletion = 0.0;
|
||||||
diffIdsCurrent = diffIdsTotal;
|
diffIdsCurrent = diffIdsTotal;
|
||||||
|
suffixedDiffIdsCurrent = suffixedDiffIdsTotal;
|
||||||
rememberedSongId = null;
|
rememberedSongId = null;
|
||||||
rememberedDifficulty = Constants.DEFAULT_DIFFICULTY;
|
rememberedDifficulty = Constants.DEFAULT_DIFFICULTY;
|
||||||
albumRoll.albumId = null;
|
albumRoll.albumId = null;
|
||||||
|
@ -2143,17 +2177,18 @@ class FreeplayState extends MusicBeatSubState
|
||||||
if (previewSongId == null) return;
|
if (previewSongId == null) return;
|
||||||
|
|
||||||
var previewSong:Null<Song> = SongRegistry.instance.fetchEntry(previewSongId);
|
var previewSong:Null<Song> = SongRegistry.instance.fetchEntry(previewSongId);
|
||||||
var currentVariation = previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST;
|
if (previewSong == null) return;
|
||||||
var songDifficulty:Null<SongDifficulty> = previewSong?.getDifficulty(currentDifficulty,
|
// var currentVariation = previewSong.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST;
|
||||||
previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST);
|
var targetDifficultyId:String = currentUnsuffixedDifficulty;
|
||||||
|
var targetVariation:Null<String> = currentVariation;
|
||||||
|
var songDifficulty:Null<SongDifficulty> = previewSong.getDifficulty(targetDifficultyId, targetVariation ?? Constants.DEFAULT_VARIATION);
|
||||||
|
|
||||||
var baseInstrumentalId:String = previewSong?.getBaseInstrumentalId(currentDifficulty, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? '';
|
var baseInstrumentalId:String = previewSong.getBaseInstrumentalId(targetDifficultyId, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? '';
|
||||||
var altInstrumentalIds:Array<String> = previewSong?.listAltInstrumentalIds(currentDifficulty,
|
var altInstrumentalIds:Array<String> = previewSong.listAltInstrumentalIds(targetDifficultyId,
|
||||||
songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? [];
|
songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? [];
|
||||||
|
|
||||||
var instSuffix:String = baseInstrumentalId;
|
var instSuffix:String = baseInstrumentalId;
|
||||||
|
|
||||||
// TODO: Make this a UI element.
|
|
||||||
#if FEATURE_DEBUG_FUNCTIONS
|
#if FEATURE_DEBUG_FUNCTIONS
|
||||||
if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL)
|
if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL)
|
||||||
{
|
{
|
||||||
|
@ -2312,6 +2347,7 @@ class FreeplaySongData
|
||||||
public var songId(default, null):String = '';
|
public var songId(default, null):String = '';
|
||||||
|
|
||||||
public var songDifficulties(default, null):Array<String> = [];
|
public var songDifficulties(default, null):Array<String> = [];
|
||||||
|
public var suffixedSongDifficulties(default, null):Array<String> = [];
|
||||||
|
|
||||||
public var songName(default, null):String = '';
|
public var songName(default, null):String = '';
|
||||||
public var songCharacter(default, null):String = '';
|
public var songCharacter(default, null):String = '';
|
||||||
|
@ -2319,22 +2355,25 @@ class FreeplaySongData
|
||||||
public var difficultyRating(default, null):Int = 0;
|
public var difficultyRating(default, null):Int = 0;
|
||||||
public var albumId(default, null):Null<String> = null;
|
public var albumId(default, null):Null<String> = null;
|
||||||
|
|
||||||
public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY;
|
public var currentCharacter:PlayableCharacter;
|
||||||
|
public var currentVariation:String = Constants.DEFAULT_VARIATION;
|
||||||
|
public var currentSuffixedDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY;
|
||||||
|
public var currentUnsuffixedDifficulty:String = Constants.DEFAULT_DIFFICULTY;
|
||||||
|
|
||||||
public var scoringRank:Null<ScoringRank> = null;
|
public var scoringRank:Null<ScoringRank> = null;
|
||||||
|
|
||||||
var displayedVariations:Array<String> = [Constants.DEFAULT_VARIATION];
|
var displayedVariations:Array<String> = [Constants.DEFAULT_VARIATION];
|
||||||
|
|
||||||
function set_currentDifficulty(value:String):String
|
function set_currentSuffixedDifficulty(value:String):String
|
||||||
{
|
{
|
||||||
if (currentDifficulty == value) return value;
|
if (currentSuffixedDifficulty == value) return value;
|
||||||
|
|
||||||
currentDifficulty = value;
|
currentSuffixedDifficulty = value;
|
||||||
updateValues(displayedVariations);
|
updateValues(displayedVariations);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function new(levelId:String, songId:String, song:Song, ?displayedVariations:Array<String>)
|
public function new(levelId:String, songId:String, song:Song, currentCharacter:PlayableCharacter, ?displayedVariations:Array<String>)
|
||||||
{
|
{
|
||||||
this.levelId = levelId;
|
this.levelId = levelId;
|
||||||
this.songId = songId;
|
this.songId = songId;
|
||||||
|
@ -2342,6 +2381,7 @@ class FreeplaySongData
|
||||||
|
|
||||||
this.isFav = Save.instance.isSongFavorited(songId);
|
this.isFav = Save.instance.isSongFavorited(songId);
|
||||||
|
|
||||||
|
this.currentCharacter = currentCharacter;
|
||||||
if (displayedVariations != null) this.displayedVariations = displayedVariations;
|
if (displayedVariations != null) this.displayedVariations = displayedVariations;
|
||||||
|
|
||||||
updateValues(displayedVariations);
|
updateValues(displayedVariations);
|
||||||
|
@ -2368,15 +2408,18 @@ class FreeplaySongData
|
||||||
function updateValues(variations:Array<String>):Void
|
function updateValues(variations:Array<String>):Void
|
||||||
{
|
{
|
||||||
this.songDifficulties = song.listDifficulties(null, variations, false, false);
|
this.songDifficulties = song.listDifficulties(null, variations, false, false);
|
||||||
if (!this.songDifficulties.contains(currentDifficulty))
|
this.suffixedSongDifficulties = song.listSuffixedDifficulties(variations, false, false);
|
||||||
|
if (!this.songDifficulties.contains(currentUnsuffixedDifficulty))
|
||||||
{
|
{
|
||||||
currentDifficulty = Constants.DEFAULT_DIFFICULTY;
|
currentSuffixedDifficulty = Constants.DEFAULT_DIFFICULTY;
|
||||||
// This method gets called again by the setter-method
|
// This method gets called again by the setter-method
|
||||||
// or the difficulty didn't change, so there's no need to continue.
|
// or the difficulty didn't change, so there's no need to continue.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, null, variations);
|
var targetVariation:Null<String> = currentVariation;
|
||||||
|
|
||||||
|
var songDifficulty:SongDifficulty = song.getDifficulty(currentUnsuffixedDifficulty, targetVariation);
|
||||||
if (songDifficulty == null) return;
|
if (songDifficulty == null) return;
|
||||||
this.songStartingBpm = songDifficulty.getStartingBPM();
|
this.songStartingBpm = songDifficulty.getStartingBPM();
|
||||||
this.songName = songDifficulty.songName;
|
this.songName = songDifficulty.songName;
|
||||||
|
@ -2392,10 +2435,7 @@ class FreeplaySongData
|
||||||
this.albumId = songDifficulty.album;
|
this.albumId = songDifficulty.album;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This line of code makes me sad, but you can't really fix it without a breaking migration.
|
var suffixedDifficulty = currentSuffixedDifficulty;
|
||||||
// `easy`, `erect`, `normal-pico`, etc.
|
|
||||||
var suffixedDifficulty = (songDifficulty.variation != Constants.DEFAULT_VARIATION
|
|
||||||
&& songDifficulty.variation != 'erect') ? '$currentDifficulty-${songDifficulty.variation}' : currentDifficulty;
|
|
||||||
|
|
||||||
this.scoringRank = Save.instance.getSongRank(songId, suffixedDifficulty);
|
this.scoringRank = Save.instance.getSongRank(songId, suffixedDifficulty);
|
||||||
|
|
||||||
|
|
|
@ -678,7 +678,7 @@ class SongMenuItem extends FlxSpriteGroup
|
||||||
public function confirm():Void
|
public function confirm():Void
|
||||||
{
|
{
|
||||||
if (songText != null) songText.flickerText();
|
if (songText != null) songText.flickerText();
|
||||||
if (pixelIcon != null)
|
if (pixelIcon != null && pixelIcon.visible)
|
||||||
{
|
{
|
||||||
pixelIcon.animation.play('confirm');
|
pixelIcon.animation.play('confirm');
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import funkin.ui.story.StoryMenuState;
|
||||||
import funkin.ui.Prompt;
|
import funkin.ui.Prompt;
|
||||||
import funkin.util.WindowUtil;
|
import funkin.util.WindowUtil;
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
import Discord.DiscordClient;
|
import funkin.api.discord.DiscordClient;
|
||||||
#end
|
#end
|
||||||
#if newgrounds
|
#if newgrounds
|
||||||
import funkin.ui.NgPrompt;
|
import funkin.ui.NgPrompt;
|
||||||
|
@ -55,8 +55,7 @@ class MainMenuState extends MusicBeatState
|
||||||
override function create():Void
|
override function create():Void
|
||||||
{
|
{
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
// Updating Discord Rich Presence
|
DiscordClient.instance.setPresence({state: "In the Menus", details: null});
|
||||||
DiscordClient.changePresence("In the Menus", null);
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
FlxG.cameras.reset(new FunkinCamera('mainMenu'));
|
FlxG.cameras.reset(new FunkinCamera('mainMenu'));
|
||||||
|
@ -362,6 +361,7 @@ class MainMenuState extends MusicBeatState
|
||||||
// Ctrl+Alt+Shift+R = Score/Rank conflict test
|
// Ctrl+Alt+Shift+R = Score/Rank conflict test
|
||||||
// Ctrl+Alt+Shift+N = Mark all characters as not seen
|
// Ctrl+Alt+Shift+N = Mark all characters as not seen
|
||||||
// Ctrl+Alt+Shift+E = Dump save data
|
// Ctrl+Alt+Shift+E = Dump save data
|
||||||
|
// Ctrl+Alt+Shift+L = Force crash and create a log dump
|
||||||
|
|
||||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.P)
|
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.P)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,10 +28,14 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page
|
||||||
[NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT],
|
[NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT],
|
||||||
[UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK],
|
[UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK],
|
||||||
[CUTSCENE_ADVANCE],
|
[CUTSCENE_ADVANCE],
|
||||||
[FREEPLAY_FAVORITE, FREEPLAY_LEFT, FREEPLAY_RIGHT],
|
[FREEPLAY_FAVORITE, FREEPLAY_LEFT, FREEPLAY_RIGHT, FREEPLAY_CHAR_SELECT],
|
||||||
[WINDOW_FULLSCREEN, WINDOW_SCREENSHOT],
|
[WINDOW_FULLSCREEN, #if FEATURE_SCREENSHOTS WINDOW_SCREENSHOT, #end],
|
||||||
[VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE],
|
[VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE],
|
||||||
[DEBUG_MENU, DEBUG_CHART]
|
[
|
||||||
|
DEBUG_MENU,
|
||||||
|
#if FEATURE_CHART_EDITOR DEBUG_CHART, #end
|
||||||
|
#if FEATURE_STAGE_EDITOR DEBUG_STAGE, #end
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
var itemGroups:Array<Array<InputItem>> = [for (i in 0...controlGroups.length) []];
|
var itemGroups:Array<Array<InputItem>> = [for (i in 0...controlGroups.length) []];
|
||||||
|
@ -137,7 +141,8 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page
|
||||||
|
|
||||||
if (currentHeader != null && name.indexOf(currentHeader) == 0) name = name.substr(currentHeader.length);
|
if (currentHeader != null && name.indexOf(currentHeader) == 0) name = name.substr(currentHeader.length);
|
||||||
|
|
||||||
var label = labels.add(new AtlasText(100, y, name, AtlasFont.BOLD));
|
var formatName = name.replace('_', ' ');
|
||||||
|
var label = labels.add(new AtlasText(100, y, formatName, AtlasFont.BOLD));
|
||||||
label.alpha = 0.6;
|
label.alpha = 0.6;
|
||||||
for (i in 0...COLUMNS)
|
for (i in 0...COLUMNS)
|
||||||
createItem(label.x + 550 + i * 400, y, control, i);
|
createItem(label.x + 550 + i * 400, y, control, i);
|
||||||
|
|
|
@ -23,6 +23,10 @@ import funkin.ui.MusicBeatState;
|
||||||
import funkin.ui.transition.LoadingState;
|
import funkin.ui.transition.LoadingState;
|
||||||
import funkin.ui.transition.StickerSubState;
|
import funkin.ui.transition.StickerSubState;
|
||||||
import funkin.util.MathUtil;
|
import funkin.util.MathUtil;
|
||||||
|
import openfl.utils.Assets;
|
||||||
|
#if FEATURE_DISCORD_RPC
|
||||||
|
import funkin.api.discord.DiscordClient;
|
||||||
|
#end
|
||||||
|
|
||||||
class StoryMenuState extends MusicBeatState
|
class StoryMenuState extends MusicBeatState
|
||||||
{
|
{
|
||||||
|
@ -217,7 +221,7 @@ class StoryMenuState extends MusicBeatState
|
||||||
|
|
||||||
#if FEATURE_DISCORD_RPC
|
#if FEATURE_DISCORD_RPC
|
||||||
// Updating Discord Rich Presence
|
// Updating Discord Rich Presence
|
||||||
DiscordClient.changePresence('In the Menus', null);
|
DiscordClient.instance.setPresence({state: 'In the Menus', details: null});
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -485,6 +485,12 @@ class TitleState extends MusicBeatState
|
||||||
case 13:
|
case 13:
|
||||||
addMoreText('Friday');
|
addMoreText('Friday');
|
||||||
case 14:
|
case 14:
|
||||||
|
// easter egg for when the game is trending with the wrong spelling
|
||||||
|
// the random intro text would be "trending--only on x"
|
||||||
|
|
||||||
|
if (curWacky[0] == "trending")
|
||||||
|
addMoreText('Nigth');
|
||||||
|
else
|
||||||
addMoreText('Night');
|
addMoreText('Night');
|
||||||
case 15:
|
case 15:
|
||||||
addMoreText('Funkin');
|
addMoreText('Funkin');
|
||||||
|
|
|
@ -78,7 +78,12 @@ class Constants
|
||||||
/**
|
/**
|
||||||
* Link to download the game on Itch.io.
|
* Link to download the game on Itch.io.
|
||||||
*/
|
*/
|
||||||
public static final URL_ITCH:String = 'https://ninja-muffin24.itch.io/funkin/purchase';
|
public static final URL_ITCH:String = 'https://ninja-muffin24.itch.io/funkin';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to play the game on Newgrounds.
|
||||||
|
*/
|
||||||
|
public static final URL_NEWGROUNDS:String = 'https://www.newgrounds.com/portal/view/770371';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link to the game's page on Kickstarter.
|
* Link to the game's page on Kickstarter.
|
||||||
|
@ -186,6 +191,11 @@ class Constants
|
||||||
*/
|
*/
|
||||||
public static final DEFAULT_DIFFICULTY_LIST:Array<String> = ['easy', 'normal', 'hard'];
|
public static final DEFAULT_DIFFICULTY_LIST:Array<String> = ['easy', 'normal', 'hard'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default list of difficulties for Erect mode.
|
||||||
|
*/
|
||||||
|
public static final DEFAULT_DIFFICULTY_LIST_ERECT:Array<String> = ['erect', 'nightmare'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of all difficulties used by the base game.
|
* List of all difficulties used by the base game.
|
||||||
* Includes Erect and Nightmare.
|
* Includes Erect and Nightmare.
|
||||||
|
|
|
@ -22,8 +22,8 @@ class ForceCrashPlugin extends FlxBasic
|
||||||
{
|
{
|
||||||
super.update(elapsed);
|
super.update(elapsed);
|
||||||
|
|
||||||
// Ctrl + Shift + L = Crash the game for debugging purposes
|
// Ctrl + Alt + Shift + L = Crash the game for debugging purposes
|
||||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.SHIFT && FlxG.keys.pressed.L)
|
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.pressed.L)
|
||||||
{
|
{
|
||||||
// TODO: Make this message 87% funnier.
|
// TODO: Make this message 87% funnier.
|
||||||
throw "DEBUG: Crashing the game via debug keybind!";
|
throw "DEBUG: Crashing the game via debug keybind!";
|
||||||
|
|
|
@ -103,7 +103,11 @@ class ScreenshotPlugin extends FlxBasic
|
||||||
|
|
||||||
public function hasPressedScreenshot():Bool
|
public function hasPressedScreenshot():Bool
|
||||||
{
|
{
|
||||||
|
#if FEATURE_SCREENSHOTS
|
||||||
return PlayerSettings.player1.controls.WINDOW_SCREENSHOT;
|
return PlayerSettings.player1.controls.WINDOW_SCREENSHOT;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updatePreferences():Void
|
public function updatePreferences():Void
|
||||||
|
|
Loading…
Reference in a new issue