diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 0f3f1efd..4f1084dc 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -36,7 +36,7 @@ jobs: run: | haxelib run lime build linux - name: Tar files - run: tar -zcvf CodenameEngine.tar.gz export/release/linux/bin + run: tar -zcvf CodenameEngine.tar.gz -C export/release/linux/bin . - name: Uploading artifact (entire build) uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 449f82c6..c11a793f 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -33,7 +33,7 @@ jobs: run: | haxelib run lime build mac - name: Tar files - run: tar -zcvf CodenameEngine.tar.gz export/release/macos/bin + run: tar -zcvf CodenameEngine.tar.gz -C export/release/macos/bin . - name: Uploading artifact (entire build) uses: actions/upload-artifact@v2 with: diff --git a/commandline/commands/Update.hx b/commandline/commands/Update.hx index 31e479e9..eb269572 100644 --- a/commandline/commands/Update.hx +++ b/commandline/commands/Update.hx @@ -7,8 +7,19 @@ import sys.io.Process; import sys.FileSystem; class Update { + private static function recursiveDelete(path:String) { + for(file in FileSystem.readDirectory(path)) { + var p = '$path/$file'; + if(FileSystem.isDirectory(p)) + recursiveDelete(p); + else + FileSystem.deleteFile(p); + } + FileSystem.deleteDirectory(path); + } + public static function main(args:Array) { - var args = ArgParser.parse(args, ["S" => "silent-progress", "silent" => "silent-progress"]); + var args = ArgParser.parse(args, ["s" => "silent-progress", "S" => "silent-progress", "silent" => "silent-progress"]); var CHECK_VSTUDIO = !args.existsOption("no-vscheck"); var REINSTALL_ALL = args.existsOption("reinstall"); var SILENT = args.existsOption("silent-progress"); @@ -18,7 +29,7 @@ class Update { FileSystem.createDirectory('.haxelib'); if (REINSTALL_ALL) { - FileSystem.deleteDirectory('.haxelib'); + recursiveDelete('.haxelib'); FileSystem.createDirectory('.haxelib'); } @@ -46,6 +57,7 @@ class Update { type: libNode.name }; if (libNode.has.global) lib.global = libNode.att.global; + if (libNode.has.skipDeps) lib.skipDeps = libNode.att.skipDeps; switch (lib.type) { case "lib": if (libNode.has.version) lib.version = libNode.att.version; @@ -58,11 +70,11 @@ class Update { data: lib }); case "cmd": - events.push({ type: CMD, data: { inLib: libNode.has.inLib ? libNode.att.inLib : null, + dir: libNode.has.dir ? libNode.att.dir : null, lines: { if(Lambda.count(libNode.nodes.line) > 0) [ @@ -101,9 +113,9 @@ class Update { if(args.args.length == 0) defines.push("all"); function parse(libNode:Access) { - if(libNode.name == "if") { + if(libNode.name == "if" || libNode.name == "unless") { var cond = libNode.att.cond; - if(!Utils.evaluateArgsCondition(cond, defines)) { + if(Utils.evaluateArgsCondition(cond, defines) != (libNode.name == "if")) { return; } @@ -120,21 +132,22 @@ class Update { } var commandSuffix = " --always"; - if (SILENT) commandSuffix += " --silent"; + if (SILENT) commandSuffix += " --quiet"; for(event in events) { switch(event.type) { case INSTALL: var lib:Library = event.data; - var globalism:Null = lib.global == "true" ? "--global" : null; - var globalSuffix = globalism != null ? ' $globalism' : ''; + var globalSuffix:Null = lib.global == "true" ? " --global" : ""; + var skipDeps = lib.skipDeps == "true" ? " --skip-dependencies" : ""; + var commandPrefix = commandSuffix + globalSuffix + skipDeps;// + " --no-timeout"; switch(lib.type) { case "lib": prettyPrint((lib.global == "true" ? "Globally installing" : "Locally installing") + ' "${lib.name}"...'); - Sys.command('haxelib install ${lib.name} ${lib.version != null ? " " + lib.version : " "}$globalSuffix$commandSuffix'); + Sys.command('haxelib$commandPrefix install ${lib.name} ${lib.version != null ? " " + lib.version : " "}'); case "git": prettyPrint((lib.global == "true" ? "Globally installing" : "Locally installing") + ' "${lib.name}" from git url "${lib.url}"'); - Sys.command('haxelib git ${lib.name} ${lib.url}${lib.ref != null ? ' ${lib.ref}' : ''}$globalSuffix$commandSuffix'); + Sys.command('haxelib$commandPrefix git ${lib.name} ${lib.url}${lib.ref != null ? ' ${lib.ref}' : ''}'); case "custom": Sys.command('haxelib dev ${lib.name} "./libraries/${lib.name}"'); default: @@ -143,6 +156,10 @@ class Update { case CMD: var cmd:CmdData = event.data; var lib = cmd.inLib; + var dir = ""; + if(cmd.dir != null) { + dir = "/" + cmd.dir; + } var oldCwd = Sys.getCwd(); if(lib != null) { var libPrefix = '.haxelib/$lib'; @@ -154,7 +171,7 @@ class Update { Sys.setCwd(oldCwd); continue; } - Sys.setCwd(devPath); + Sys.setCwd(devPath + dir); } else if(FileSystem.exists(libPrefix + '/.current')) { var version = StringTools.replace(File.getContent(libPrefix + '/.current'), ".", ","); if(!FileSystem.exists(libPrefix + '/$version')) { @@ -162,7 +179,7 @@ class Update { Sys.setCwd(oldCwd); continue; } - Sys.setCwd(libPrefix + '/$version'); + Sys.setCwd(libPrefix + '/$version' + dir); } else { Sys.println('Cannot find .dev or .current file in $libPrefix'); Sys.setCwd(oldCwd); @@ -262,6 +279,8 @@ typedef Library = { var name:String; var type:String; var ?global:String; + var ?skipDeps:String; + var ?recursive:String; var ?version:String; var ?ref:String; var ?url:String; @@ -273,7 +292,8 @@ typedef Event = { } typedef CmdData = { - var ?inLib:String; + var inLib:String; + var dir:String; var lines:Array; } diff --git a/libs.xml b/libs.xml index 038cf640..07425bfe 100644 --- a/libs.xml +++ b/libs.xml @@ -14,20 +14,32 @@ - - + + - - - + + + + + + + + + + + + Rebuilding Hxcpp... + + + @@ -35,11 +47,7 @@ Rebuilding Lime... - - - cd tools - haxe tools.hxml - cd ..s - + + diff --git a/setup-dev-branch.xml b/setup-dev-branch.xml index ed3eb905..82c27129 100644 --- a/setup-dev-branch.xml +++ b/setup-dev-branch.xml @@ -21,10 +21,6 @@ Rebuilding Lime... - - - cd tools - haxe tools.hxml - cd ..s - + + diff --git a/setup-dev.xml b/setup-dev.xml index dc2762ff..ba79d790 100644 --- a/setup-dev.xml +++ b/setup-dev.xml @@ -6,6 +6,18 @@ mkdir dev-libs + + + cd dev-libs + git clone https://github.com/NeeEoo/hxcpp hxcpp + cd .. + haxelib dev hxcpp dev-libs/hxcpp + + + + + + cd dev-libs @@ -24,12 +36,8 @@ - - - cd tools - haxe tools.hxml - cd ..s - + + diff --git a/source/funkin/backend/chart/Chart.hx b/source/funkin/backend/chart/Chart.hx index 1669879d..93279d43 100644 --- a/source/funkin/backend/chart/Chart.hx +++ b/source/funkin/backend/chart/Chart.hx @@ -56,6 +56,7 @@ class Chart { data.setFieldDefault("name", songName); data.setFieldDefault("beatsPerMeasure", 4); data.setFieldDefault("stepsPerBeat", 4); + data.setFieldDefault("needsVoices", true); data.setFieldDefault("icon", "face"); data.setFieldDefault("difficulties", []); data.setFieldDefault("coopAllowed", false); diff --git a/source/funkin/backend/chart/ChartData.hx b/source/funkin/backend/chart/ChartData.hx index 7e6ad795..3f8f3302 100644 --- a/source/funkin/backend/chart/ChartData.hx +++ b/source/funkin/backend/chart/ChartData.hx @@ -26,6 +26,7 @@ typedef ChartMetaData = { public var ?coopAllowed:Bool; public var ?opponentModeAllowed:Bool; public var ?customValues:Dynamic; + public var ?needsVoices:Bool; // NOT TO BE EXPORTED public var ?parsedColor:FlxColor; diff --git a/source/funkin/backend/chart/EventsData.hx b/source/funkin/backend/chart/EventsData.hx index 05f35bde..eff3fd8e 100644 --- a/source/funkin/backend/chart/EventsData.hx +++ b/source/funkin/backend/chart/EventsData.hx @@ -70,6 +70,8 @@ class EventsData { hscriptInterp.variables.set("StrumLine", TStrumLine); hscriptInterp.variables.set("ColorWheel", TColorWheel); hscriptInterp.variables.set("DropDown", Reflect.makeVarArgs((args) -> {return args.length > 0 ? TDropDown([for (arg in args) Std.string(arg)]) : TDropDown(["null"]);})); + hscriptInterp.variables.set("Character", TCharacter); + hscriptInterp.variables.set("Stage", TStage); var hscriptParser:Parser = new Parser(); hscriptParser.allowJSON = hscriptParser.allowMetadata = false; @@ -127,4 +129,6 @@ enum EventParamType { TStrumLine; TColorWheel; TDropDown(?options:Array); + TCharacter; + TStage; } diff --git a/source/funkin/backend/chart/FNFLegacyParser.hx b/source/funkin/backend/chart/FNFLegacyParser.hx index c6a5be3e..c7aa1711 100644 --- a/source/funkin/backend/chart/FNFLegacyParser.hx +++ b/source/funkin/backend/chart/FNFLegacyParser.hx @@ -41,6 +41,7 @@ class FNFLegacyParser { } result.meta.bpm = data.bpm; + result.meta.needsVoices = data.needsVoices.getDefault(true); var camFocusedBF:Bool = false; var altAnims:Bool = false; @@ -145,6 +146,7 @@ class FNFLegacyParser { notes: null, bpm: chart.meta.bpm, speed: chart.scrollSpeed, + needsVoices: chart.meta.needsVoices, player1: null, player2: null, @@ -208,6 +210,7 @@ typedef SwagSong = var ?stage:String; var ?noteTypes:Array; var ?events:Array; + var ?needsVoices:Bool; var player1:String; var player2:String; diff --git a/source/funkin/backend/scripting/GlobalScript.hx b/source/funkin/backend/scripting/GlobalScript.hx index d2d9323f..1ca88772 100644 --- a/source/funkin/backend/scripting/GlobalScript.hx +++ b/source/funkin/backend/scripting/GlobalScript.hx @@ -11,7 +11,11 @@ import funkin.backend.system.Conductor; class GlobalScript { public static var scripts:ScriptPack; + private static var initalized:Bool = false; + public static function init() { + if(initalized) return; + initalized = true; #if MOD_SUPPORT ModsFolder.onModSwitch.add(onModSwitch); #end diff --git a/source/funkin/backend/scripting/events/HealthIconChangeEvent.hx b/source/funkin/backend/scripting/events/HealthIconChangeEvent.hx new file mode 100644 index 00000000..a98493ef --- /dev/null +++ b/source/funkin/backend/scripting/events/HealthIconChangeEvent.hx @@ -0,0 +1,13 @@ +package funkin.backend.scripting.events; + +final class HealthIconChangeEvent extends CancellableEvent { + /** + * Amount + */ + public var amount:Int; + + /** + * The health icon + */ + public var healthIcon:funkin.game.HealthIcon; +} \ No newline at end of file diff --git a/source/funkin/backend/system/macros/BuildInfo.hx b/source/funkin/backend/system/macros/BuildInfo.hx index f86d67e2..5c2afe95 100644 --- a/source/funkin/backend/system/macros/BuildInfo.hx +++ b/source/funkin/backend/system/macros/BuildInfo.hx @@ -5,6 +5,7 @@ using StringTools; #if macro class BuildInfo { public static function printBuildInfo() { + if(haxe.macro.Context.defined("display")) return; var haxeVersion = haxe.macro.Context.definedValue("haxe"); Sys.println('[ BUILD INFO ]'); Sys.println('Haxe Version: ${haxeVersion}'); diff --git a/source/funkin/backend/system/macros/Macros.hx b/source/funkin/backend/system/macros/Macros.hx index e74231e6..61e05546 100644 --- a/source/funkin/backend/system/macros/Macros.hx +++ b/source/funkin/backend/system/macros/Macros.hx @@ -28,13 +28,21 @@ class Macros { var isHl = Context.defined("hl"); + var compathx4 = [ + "sys.db.Sqlite", + "sys.db.Mysql", + "sys.db.Connection", + "sys.db.ResultSet", + "haxe.remoting.Proxy", + ]; + if(Context.defined("sys")) { for(inc in ["sys", "openfl.net", "funkin.backend.system.net"]) { if(!isHl) - Compiler.include(inc); + Compiler.include(inc, compathx4); else { // TODO: Hashlink - //Compiler.include(inc, ["sys.net.UdpSocket", "openfl.net.DatagramSocket"]); // fixes FATAL ERROR : Failed to load function std@socket_set_broadcast + //Compiler.include(inc, compathx4.concat(["sys.net.UdpSocket", "openfl.net.DatagramSocket"]); // fixes FATAL ERROR : Failed to load function std@socket_set_broadcast } } } diff --git a/source/funkin/backend/utils/DiscordUtil.hx b/source/funkin/backend/utils/DiscordUtil.hx index 155b5f07..dfee8ad7 100644 --- a/source/funkin/backend/utils/DiscordUtil.hx +++ b/source/funkin/backend/utils/DiscordUtil.hx @@ -1,5 +1,6 @@ package funkin.backend.utils; +import flixel.util.FlxSignal.FlxTypedSignal; import flixel.sound.FlxSound; import flixel.util.typeLimit.OneOfTwo; import funkin.backend.scripting.*; // lazy @@ -107,14 +108,28 @@ class DiscordUtil public static function loadScript() { + #if DISCORD_RPC if (script != null) { call("destroy"); script = FlxDestroyUtil.destroy(script); } script = Script.create(Paths.script('data/discord')); + script.set("ActivityType", { + Playing: ActivityType.Playing, + PLAYING: ActivityType.Playing, + Streaming: ActivityType.Streaming, + STREAMING: ActivityType.Streaming, + Watching: ActivityType.Watching, + WATCHING: ActivityType.Watching, + Listening: ActivityType.Listening, + LISTENING: ActivityType.Listening, + Competing: ActivityType.Competing, + COMPETING: ActivityType.Competing + }); // script.setParent(DiscordUtil); script.load(); + #end } public static function changePresence(details:String, state:String, ?smallImageKey:String) @@ -218,6 +233,8 @@ class DiscordUtil Utils.safeSetWrapper(dp.joinSecret, data.joinSecret, fixString); Utils.safeSetWrapper(dp.spectateSecret, data.spectateSecret, fixString); Utils.safeSet(dp.instance, data.instance); + Utils.safeSet(dp.activityType, data.activityType); + Utils.safeSetWrapper(dp.streamUrl, data.streamUrl, fixString); if (data.matchSecret == null && data.joinSecret == null && data.spectateSecret == null) { Utils.safeSetWrapper(dp.button1Label, data.button1Label, fixString); @@ -252,6 +269,7 @@ class DiscordUtil handlers.joinGame = cpp.Function.fromStaticFunction(onJoin); handlers.joinRequest = cpp.Function.fromStaticFunction(onJoinReq); handlers.spectateGame = cpp.Function.fromStaticFunction(onSpectate); + handlers.anyResponse = cpp.Function.fromStaticFunction(onAnyResponse); Discord.Initialize(id, cpp.RawPointer.addressOf(handlers), 1, null); stopThread = false; @@ -309,7 +327,7 @@ class DiscordUtil Logs.logText(")") ], INFO); - call("onReady", [errorCode, cast(finalMsg, String)]); + call("onDisconnected", [errorCode, cast(finalMsg, String)]); } private static function onError(errorCode:Int, message:cpp.ConstCharStar):Void @@ -351,7 +369,38 @@ class DiscordUtil var req:DUser = DUser.initRaw(request); call("onJoinRequest", [req]); } + + public static var anyResponse:FlxTypedSignalVoid> = new FlxTypedSignalVoid>(); + + private static function onAnyResponse(data:cpp.ConstCharStar):Void + { + call("onAnyResponse", [data]); + anyResponse.dispatch(data); + } #end + + private static function getUUID():String { + var uuid = new StringBuf(); + for (i in 0...16) { + uuid.add(StringTools.hex(Math.floor(Math.random() * 16), 1)); + } + return uuid.toString(); + } + + public static function sendCustomCommand(data:Dynamic) { + #if DISCORD_RPC + if(data == null) return; + if(data.nonce == null) data.nonce = getUUID(); + var json = Json.stringify(data); + Discord.SendCustomCommand(json); + #end + } + + public static function setDebugMode(mode:Bool) { + #if DISCORD_RPC + Discord.SetDebugMode(mode); + #end + } } typedef DiscordJson = @@ -476,6 +525,8 @@ typedef DPresence = var ?button1Url:String; /* max 512 bytes */ var ?button2Label:String; /* max 32 bytes */ var ?button2Url:String; /* max 512 bytes */ + var ?activityType:ActivityType; + var ?streamUrl:String; /* max 512 bytes */ } typedef DEvents = diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index f16fa383..72ff1155 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -526,7 +526,7 @@ class Charter extends UIState { noteTypes = PlayState.SONG.noteTypes; FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff))); - if (Assets.exists(Paths.voices(__song, __diff))) // null or true + if (PlayState.SONG.meta.needsVoices != false && Assets.exists(Paths.voices(__song, __diff))) // null or true vocals = FlxG.sound.load(Paths.voices(__song, __diff)); else vocals = new FlxSound(); @@ -598,15 +598,22 @@ class Charter extends UIState { updateWaveforms(); } + inline function isSoundLoaded(sound:FlxSound) { + @:privateAccess + return sound != null && sound._sound != null && sound._sound.length > 0; + } + public function updateWaveforms() { - var wavesToGenerate:Array<{name:String, sound:FlxSound}> = [ - {name: "Inst.ogg", sound: FlxG.sound.music}, - ]; - if (@:privateAccess vocals._sound != null) //for some reason Assets.exists returns true regardless if the file actually exists + var wavesToGenerate:Array<{name:String, sound:FlxSound}> = []; + + if(isSoundLoaded(FlxG.sound.music)) + wavesToGenerate.push({name: "Inst.ogg", sound: FlxG.sound.music}); + + if (PlayState.SONG.meta.needsVoices != false && isSoundLoaded(vocals)) wavesToGenerate.push({name: "Voices.ogg", sound: vocals}); for (strumLine in strumLines) - if (strumLine.vocals != null && strumLine.strumLine.vocalsSuffix != null && strumLine.strumLine.vocalsSuffix != "") + if (strumLine.vocals != null && strumLine.strumLine.vocalsSuffix != null && strumLine.strumLine.vocalsSuffix != "" && isSoundLoaded(strumLine.vocals)) wavesToGenerate.push({ name: 'Voices${strumLine.strumLine.vocalsSuffix}.ogg', sound: strumLine.vocals diff --git a/source/funkin/editors/charter/CharterEventScreen.hx b/source/funkin/editors/charter/CharterEventScreen.hx index ec9ce660..20d84715 100644 --- a/source/funkin/editors/charter/CharterEventScreen.hx +++ b/source/funkin/editors/charter/CharterEventScreen.hx @@ -5,6 +5,8 @@ import flixel.util.FlxColor; import funkin.backend.chart.ChartData.ChartEvent; import funkin.backend.chart.EventsData; import funkin.backend.system.Conductor; +import funkin.game.Character; +import funkin.game.Stage; using StringTools; @@ -163,6 +165,20 @@ class CharterEventScreen extends UISubstateWindow { var dropdown = new UIDropDown(eventName.x, y, 320, 32, options, Std.int(Math.abs(options.indexOf(cast value)))); paramsPanel.add(dropdown); paramsFields.push(dropdown); dropdown; + case TCharacter: + addLabel(); + var charFileList = Character.getList(false); + var textBox:UIAutoCompleteTextBox = new UIAutoCompleteTextBox(eventName.x, y, cast value); + textBox.suggestItems = charFileList; + paramsPanel.add(textBox); paramsFields.push(textBox); + textBox; + case TStage: + addLabel(); + var stageFileList = Stage.getList(false); + var textBox:UIAutoCompleteTextBox = new UIAutoCompleteTextBox(eventName.x, y, cast value); + textBox.suggestItems = stageFileList; + paramsPanel.add(textBox); paramsFields.push(textBox); + textBox; default: paramsFields.push(null); null; diff --git a/source/funkin/game/HealthIcon.hx b/source/funkin/game/HealthIcon.hx index d55bf14b..1c7bb59d 100644 --- a/source/funkin/game/HealthIcon.hx +++ b/source/funkin/game/HealthIcon.hx @@ -24,6 +24,11 @@ class HealthIcon extends FlxSprite */ public var healthSteps:Map = null; + /** + * current animation state + */ + public var curAnimState:Int = -1; + /** * Helper for HScript who can't make maps * @param steps Something like this: `[[0, 1], [20, 0]]` @@ -91,7 +96,14 @@ class HealthIcon extends FlxSprite i = icon; } } - if (i >= 0) animation.curAnim.curFrame = i; + if (i >= 0 && curAnimState != i) { + var event = EventManager.get(funkin.backend.scripting.events.HealthIconChangeEvent).recycle(i, this); + funkin.backend.scripting.GlobalScript.event("onHealthIconAnimChange", event); + if (!event.cancelled) + animation.curAnim.curFrame = event.amount; + + curAnimState = event.amount; + } } } } diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index d287aa26..bac69c8b 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -1000,7 +1000,7 @@ class PlayState extends MusicBeatState curSong = songData.meta.name.toLowerCase(); inst = FlxG.sound.load(Paths.inst(SONG.meta.name, difficulty)); - if (Assets.exists(Paths.voices(SONG.meta.name, difficulty))) // null or true + if (SONG.meta.needsVoices != false && Assets.exists(Paths.voices(SONG.meta.name, difficulty))) // null or true vocals = FlxG.sound.load(Paths.voices(SONG.meta.name, difficulty)); else vocals = new FlxSound(); @@ -1424,6 +1424,7 @@ class PlayState extends MusicBeatState for (strumLine in strumLines.members) strumLine.vocals.stop(); deathCounter++; + openSubState(new GameOverSubstate(event.x, event.y, event.deathCharID, event.isPlayer, event.gameOverSong, event.lossSFX, event.retrySFX)); scripts.event("onPostGameOver", event); diff --git a/source/funkin/game/SplashHandler.hx b/source/funkin/game/SplashHandler.hx index dc6f7533..1776bdb8 100644 --- a/source/funkin/game/SplashHandler.hx +++ b/source/funkin/game/SplashHandler.hx @@ -40,7 +40,10 @@ class SplashHandler extends FlxTypedGroup { var __grp:SplashGroup; public function showSplash(name:String, strum:Strum) { __grp = getSplashGroup(name); - add(__grp.showOnStrum(strum)); + var event = funkin.backend.scripting.EventManager.get(funkin.backend.scripting.events.DynamicEvent).recycle(__grp.showOnStrum(strum), strum); + event = PlayState.instance.scripts.event("onSplashShown", event); + if (!event.cancelled) + add(event.value1); // max 8 rendered splashes while(members.length > 8) diff --git a/source/funkin/game/Strum.hx b/source/funkin/game/Strum.hx index 0e179f71..5a0299d8 100644 --- a/source/funkin/game/Strum.hx +++ b/source/funkin/game/Strum.hx @@ -14,6 +14,8 @@ class Strum extends FlxSprite { public var cpu = false; // Unused public var lastHit:Float = -5000; + public var strumLine = null; + public var scrollSpeed:Null = null; // custom scroll speed per strum public var noteAngle:Null = null; diff --git a/source/funkin/game/StrumLine.hx b/source/funkin/game/StrumLine.hx index d743dd79..e00e58f8 100644 --- a/source/funkin/game/StrumLine.hx +++ b/source/funkin/game/StrumLine.hx @@ -303,6 +303,7 @@ class StrumLine extends FlxTypedGroup { animPrefix = strumAnimPrefix[i % strumAnimPrefix.length]; var babyArrow:Strum = new Strum(startingPos.x + ((Note.swagWidth * strumScale) * i), startingPos.y); babyArrow.ID = i; + babyArrow.strumLine = this; if(data.scrollSpeed != null) babyArrow.scrollSpeed = data.scrollSpeed; diff --git a/source/funkin/menus/FreeplayState.hx b/source/funkin/menus/FreeplayState.hx index 3b7d0c05..fb85e1fb 100644 --- a/source/funkin/menus/FreeplayState.hx +++ b/source/funkin/menus/FreeplayState.hx @@ -196,6 +196,10 @@ class FreeplayState extends MusicBeatState * Path to the currently playing song instrumental. */ public var curPlayingInst:String = null; + /** + * If it should play the song automatically. + */ + public var autoplayShouldPlay:Bool = true; #end override function update(elapsed:Float) @@ -236,7 +240,17 @@ class FreeplayState extends MusicBeatState autoplayElapsed += elapsed; if (!disableAutoPlay && !songInstPlaying && (autoplayElapsed > timeUntilAutoplay || FlxG.keys.justPressed.SPACE)) { if (curPlayingInst != (curPlayingInst = Paths.inst(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty]))) { - var huh:Void->Void = function() FlxG.sound.playMusic(curPlayingInst, 0); + var huh:Void->Void = function() { + var soundPath = curPlayingInst; + var sound = null; + if (Assets.exists(soundPath, SOUND) || Assets.exists(soundPath, MUSIC)) + sound = Assets.getSound(soundPath); + else + FlxG.log.error('Could not find a Sound asset with an ID of \'$soundPath\'.'); + + if (sound != null && autoplayShouldPlay) + FlxG.sound.playMusic(sound, 0); + } if(!disableAsyncLoading) Main.execAsync(huh); else huh(); } @@ -289,6 +303,10 @@ class FreeplayState extends MusicBeatState if (event.cancelled) return; + #if PRELOAD_ALL + autoplayShouldPlay = false; + #end + Options.freeplayLastSong = songs[curSelected].name; Options.freeplayLastDifficulty = songs[curSelected].difficulties[curDifficulty];