From 317c127730efb5a133a175e047a30df249391821 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 25 May 2023 18:33:39 -0400 Subject: [PATCH 1/3] Deprecation warning fixes (no actual logic changes tho) --- source/funkin/Controls.hx | 3 +- source/funkin/FreeplayState.hx | 4 +- source/funkin/InputFormatter.hx | 2 +- source/funkin/LatencyState.hx | 11 +- source/funkin/MusicBeatState.hx | 15 +- source/funkin/PauseSubState.hx | 2 +- source/funkin/TankCutscene.hx | 2 +- .../audio/visualize/PolygonSpectogram.hx | 2 +- source/funkin/audiovis/ABotVis.hx | 5 +- source/funkin/audiovis/SpectogramSprite.hx | 5 +- source/funkin/audiovis/VisShit.hx | 8 +- source/funkin/charting/ChartingState.hx | 64 +++---- source/funkin/play/GameOverSubstate.hx | 11 +- .../play/character/AnimateAtlasCharacter.hx | 6 +- source/funkin/play/song/Song.hx | 162 ++++++++++++++++-- source/funkin/play/song/SongData.hx | 6 +- source/funkin/play/song/SongValidator.hx | 2 +- .../ui/animDebugShit/DebugBoundingState.hx | 25 +-- .../ui/debug/charting/ChartEditorState.hx | 10 +- 19 files changed, 223 insertions(+), 122 deletions(-) diff --git a/source/funkin/Controls.hx b/source/funkin/Controls.hx index 9fc2610ba..243570c27 100644 --- a/source/funkin/Controls.hx +++ b/source/funkin/Controls.hx @@ -46,8 +46,7 @@ enum Control #end } -@:enum -abstract Action(String) to String from String +enum abstract Action(String) to String from String { var UI_UP = "ui_up"; var UI_LEFT = "ui_left"; diff --git a/source/funkin/FreeplayState.hx b/source/funkin/FreeplayState.hx index 8a635bfda..fb2119c55 100644 --- a/source/funkin/FreeplayState.hx +++ b/source/funkin/FreeplayState.hx @@ -882,10 +882,10 @@ class FreeplayState extends MusicBeatSubstate } } - override function switchTo(nextState:FlxState):Bool + override function startOutro(onComplete:() -> Void):Void { clearDaCache(songs[curSelected].songName); - return super.switchTo(nextState); + super.startOutro(onComplete); } function changeDiff(change:Int = 0) diff --git a/source/funkin/InputFormatter.hx b/source/funkin/InputFormatter.hx index ebcba22fa..2a7011f64 100644 --- a/source/funkin/InputFormatter.hx +++ b/source/funkin/InputFormatter.hx @@ -144,7 +144,7 @@ class InputFormatter } @:forward -@:enum abstract ControllerName(String) from String to String +enum abstract ControllerName(String) from String to String { var OUYA = "Ouya"; var PS4 = "PS4"; diff --git a/source/funkin/LatencyState.hx b/source/funkin/LatencyState.hx index 256efde5c..bb0008ef9 100644 --- a/source/funkin/LatencyState.hx +++ b/source/funkin/LatencyState.hx @@ -5,7 +5,7 @@ import flixel.FlxSubState; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxGroup; import flixel.math.FlxMath; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.system.debug.stats.StatsGraph; import flixel.text.FlxText; import flixel.util.FlxColor; @@ -52,8 +52,7 @@ class LatencyState extends MusicBeatSubstate FlxG.addChildBelowMouse(realStats); #end - FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, key -> - { + FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, key -> { trace(key.charCode); if (key.charCode == 120) generateBeatStuff(); @@ -154,8 +153,7 @@ class LatencyState extends MusicBeatSubstate override function beatHit():Bool { - if (curBeat % 8 == 0) blocks.forEach(blok -> - { + if (curBeat % 8 == 0) blocks.forEach(blok -> { blok.alpha = 0; }); @@ -248,8 +246,7 @@ class LatencyState extends MusicBeatSubstate FlxG.resetState(); }*/ - noteGrp.forEach(function(daNote:Note) - { + noteGrp.forEach(function(daNote:Note) { daNote.y = (strumLine.y - ((Conductor.songPosition - Conductor.audioOffset) - daNote.data.strumTime) * 0.45); daNote.x = strumLine.x + 30; diff --git a/source/funkin/MusicBeatState.hx b/source/funkin/MusicBeatState.hx index 5896f6131..3614695c0 100644 --- a/source/funkin/MusicBeatState.hx +++ b/source/funkin/MusicBeatState.hx @@ -146,15 +146,20 @@ class MusicBeatState extends FlxUIState sort(SortUtil.byZIndex, FlxSort.ASCENDING); } - override function switchTo(nextState:FlxState):Bool + override function startOutro(onComplete:() -> Void):Void { - var event = new StateChangeScriptEvent(ScriptEvent.STATE_CHANGE_BEGIN, nextState, true); + var event = new StateChangeScriptEvent(ScriptEvent.STATE_CHANGE_BEGIN, null, true); dispatchEvent(event); - if (event.eventCanceled) return false; - - return super.switchTo(nextState); + if (event.eventCanceled) + { + return; + } + else + { + onComplete(); + } } public override function openSubState(targetSubstate:FlxSubState):Void diff --git a/source/funkin/PauseSubState.hx b/source/funkin/PauseSubState.hx index 747335943..67b58f41d 100644 --- a/source/funkin/PauseSubState.hx +++ b/source/funkin/PauseSubState.hx @@ -3,7 +3,7 @@ package funkin; import flixel.FlxSprite; import flixel.addons.transition.FlxTransitionableState; import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.text.FlxText; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; diff --git a/source/funkin/TankCutscene.hx b/source/funkin/TankCutscene.hx index 9b1078eae..4bc7349ad 100644 --- a/source/funkin/TankCutscene.hx +++ b/source/funkin/TankCutscene.hx @@ -1,7 +1,7 @@ package funkin; import flixel.FlxSprite; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; class TankCutscene extends FlxSprite { diff --git a/source/funkin/audio/visualize/PolygonSpectogram.hx b/source/funkin/audio/visualize/PolygonSpectogram.hx index c9f1c5dbf..6b7e280ec 100644 --- a/source/funkin/audio/visualize/PolygonSpectogram.hx +++ b/source/funkin/audio/visualize/PolygonSpectogram.hx @@ -2,7 +2,7 @@ package funkin.audio.visualize; import flixel.math.FlxMath; import flixel.math.FlxPoint; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.util.FlxColor; import funkin.audiovis.VisShit; import funkin.graphics.rendering.MeshRender; diff --git a/source/funkin/audiovis/ABotVis.hx b/source/funkin/audiovis/ABotVis.hx index 482c1b00e..2018a99b3 100644 --- a/source/funkin/audiovis/ABotVis.hx +++ b/source/funkin/audiovis/ABotVis.hx @@ -6,7 +6,7 @@ import flixel.addons.plugin.taskManager.FlxTask; import flixel.graphics.frames.FlxAtlasFrames; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.math.FlxMath; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import funkin.ui.PreferencesMenu.CheckboxThingie; using Lambda; @@ -86,8 +86,7 @@ class ABotVis extends FlxTypedSpriteGroup for (i in 0...group.members.length) { - var getSliceShit = function(s:Int) - { + var getSliceShit = function(s:Int) { var powShit = FlxMath.remapToRange(s, 0, group.members.length, 0, CoolUtil.coolBaseLog(10, freqShit[0].length)); return Math.round(Math.pow(10, powShit)); }; diff --git a/source/funkin/audiovis/SpectogramSprite.hx b/source/funkin/audiovis/SpectogramSprite.hx index 62291403c..c4f8234eb 100644 --- a/source/funkin/audiovis/SpectogramSprite.hx +++ b/source/funkin/audiovis/SpectogramSprite.hx @@ -5,7 +5,7 @@ import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.math.FlxMath; import flixel.math.FlxPoint; import flixel.math.FlxVector; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.util.FlxColor; import funkin.audio.visualize.PolygonSpectogram.VISTYPE; import funkin.audiovis.VisShit.CurAudioInfo; @@ -75,8 +75,7 @@ class SpectogramSprite extends FlxTypedSpriteGroup default: } - forEach(spr -> - { + forEach(spr -> { spr.visible = spr.ID % wavOptimiz == 0; }); diff --git a/source/funkin/audiovis/VisShit.hx b/source/funkin/audiovis/VisShit.hx index 3dd7f5aaa..ee531a977 100644 --- a/source/funkin/audiovis/VisShit.hx +++ b/source/funkin/audiovis/VisShit.hx @@ -1,7 +1,7 @@ package funkin.audiovis; import flixel.math.FlxMath; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import funkin.audiovis.dsp.FFT; import haxe.Timer; import lime.system.ThreadPool; @@ -41,8 +41,7 @@ class VisShit // helpers, note that spectrum indexes suppose non-negative frequencies final binSize = fs / fftN; - final indexToFreq = function(k:Int) - { + final indexToFreq = function(k:Int) { var powShit:Float = FlxMath.remapToRange(k, 0, halfN, 0, CoolUtil.coolBaseLog(10, halfN)); // 4.3 is almost the log of 20Khz or so. Close enuf lol return 1.0 * (Math.pow(10, powShit)); // we need the `1.0` to avoid overflows @@ -51,8 +50,7 @@ class VisShit // "melodic" band-pass filter final minFreq = 20.70; final maxFreq = 4000.01; - final melodicBandPass = function(k:Int, s:Float) - { + final melodicBandPass = function(k:Int, s:Float) { final freq = indexToFreq(k); final filter = freq > minFreq - binSize && freq < maxFreq + binSize ? 1 : 0; return s; diff --git a/source/funkin/charting/ChartingState.hx b/source/funkin/charting/ChartingState.hx index d9bc7f5e2..e8402727f 100644 --- a/source/funkin/charting/ChartingState.hx +++ b/source/funkin/charting/ChartingState.hx @@ -1,6 +1,5 @@ package funkin.charting; -import flixel.FlxSprite; import flixel.addons.display.FlxGridOverlay; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.ui.FlxInputText; @@ -10,22 +9,24 @@ import flixel.addons.ui.FlxUIDropDownMenu; import flixel.addons.ui.FlxUIInputText; import flixel.addons.ui.FlxUINumericStepper; import flixel.addons.ui.FlxUITabMenu; +import flixel.FlxSprite; import flixel.group.FlxGroup; import flixel.math.FlxMath; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.text.FlxText; import flixel.ui.FlxButton; import flixel.util.FlxColor; -import funkin.Conductor.BPMChangeEvent; -import funkin.Section.SwagSection; -import funkin.SongLoad.SwagSong; import funkin.audio.visualize.PolygonSpectogram; import funkin.audiovis.ABotVis; import funkin.audiovis.SpectogramSprite; +import funkin.Conductor.BPMChangeEvent; import funkin.graphics.rendering.MeshRender; import funkin.noteStuff.NoteBasic.NoteData; import funkin.play.HealthIcon; import funkin.play.PlayState; +import funkin.Section.SwagSection; +import funkin.SongLoad.SwagSong; +import funkin.audio.VoicesGroup; import haxe.Json; import lime.media.AudioBuffer; import lime.utils.Assets; @@ -193,16 +194,14 @@ class ChartingState extends MusicBeatState var check_voices = new FlxUICheckBox(10, 25, null, null, "Has voice track", 100); check_voices.checked = _song.needsVoices; // _song.needsVoices = check_voices.checked; - check_voices.callback = function() - { + check_voices.callback = function() { _song.needsVoices = check_voices.checked; trace('CHECKED!'); }; var check_mute_inst = new FlxUICheckBox(10, 200, null, null, "Mute Instrumental (in editor)", 100); check_mute_inst.checked = false; - check_mute_inst.callback = function() - { + check_mute_inst.callback = function() { var vol:Float = 1; if (check_mute_inst.checked) vol = 0; @@ -210,23 +209,19 @@ class ChartingState extends MusicBeatState FlxG.sound.music.volume = vol; }; - var saveButton:FlxButton = new FlxButton(110, 8, "Save", function() - { + var saveButton:FlxButton = new FlxButton(110, 8, "Save", function() { saveLevel(); }); - var saveCompiler:FlxButton = new FlxButton(110, 30, "Save compile", function() - { + var saveCompiler:FlxButton = new FlxButton(110, 30, "Save compile", function() { saveLevel(true); }); - var reloadSong:FlxButton = new FlxButton(saveButton.x + saveButton.width + 10, saveButton.y, "Reload Audio", function() - { + var reloadSong:FlxButton = new FlxButton(saveButton.x + saveButton.width + 10, saveButton.y, "Reload Audio", function() { loadSong(_song.song); }); - var reloadSongJson:FlxButton = new FlxButton(reloadSong.x, saveButton.y + 30, "Reload JSON", function() - { + var reloadSongJson:FlxButton = new FlxButton(reloadSong.x, saveButton.y + 30, "Reload JSON", function() { FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; loadJson(_song.song.toLowerCase()); @@ -245,22 +240,19 @@ class ChartingState extends MusicBeatState var characters:Array = CoolUtil.coolTextFile(Paths.txt('characterList')); - var player1DropDown = new FlxUIDropDownMenu(10, 100, FlxUIDropDownMenu.makeStrIdLabelArray(characters, true), function(character:String) - { + var player1DropDown = new FlxUIDropDownMenu(10, 100, FlxUIDropDownMenu.makeStrIdLabelArray(characters, true), function(character:String) { _song.player1 = characters[Std.parseInt(character)]; updateHeads(); }); player1DropDown.selectedLabel = _song.player1; - var player2DropDown = new FlxUIDropDownMenu(140, 100, FlxUIDropDownMenu.makeStrIdLabelArray(characters, true), function(character:String) - { + var player2DropDown = new FlxUIDropDownMenu(140, 100, FlxUIDropDownMenu.makeStrIdLabelArray(characters, true), function(character:String) { _song.player2 = characters[Std.parseInt(character)]; updateHeads(); }); player2DropDown.selectedLabel = _song.player2; - var difficultyDropDown = new FlxUIDropDownMenu(10, 230, FlxUIDropDownMenu.makeStrIdLabelArray(_song.difficulties, true), function(diff:String) - { + var difficultyDropDown = new FlxUIDropDownMenu(10, 230, FlxUIDropDownMenu.makeStrIdLabelArray(_song.difficulties, true), function(diff:String) { SongLoad.curDiff = _song.difficulties[Std.parseInt(diff)]; SongLoad.checkAndCreateNotemap(SongLoad.curDiff); @@ -273,8 +265,7 @@ class ChartingState extends MusicBeatState var difficultyAdder = new FlxUIInputText(130, 230, 100, "", 12); - var addDiff:FlxButton = new FlxButton(130, 250, "Add Difficulty", function() - { + var addDiff:FlxButton = new FlxButton(130, 250, "Add Difficulty", function() { difficultyAdder.text = ""; // something to regenerate difficulties }); @@ -325,15 +316,13 @@ class ChartingState extends MusicBeatState var stepperCopy:FlxUINumericStepper = new FlxUINumericStepper(110, 130, 1, 1, -999, 999, 0); - var copyButton:FlxButton = new FlxButton(10, 130, "Copy last section", function() - { + var copyButton:FlxButton = new FlxButton(10, 130, "Copy last section", function() { copySection(Std.int(stepperCopy.value)); }); var clearSectionButton:FlxButton = new FlxButton(10, 150, "Clear", clearSection); - var swapSection:FlxButton = new FlxButton(10, 170, "Swap section", function() - { + var swapSection:FlxButton = new FlxButton(10, 170, "Swap section", function() { for (i in 0...SongLoad.getSong()[curSection].sectionNotes.length) { var note:Note = new Note(0, 0); @@ -417,8 +406,7 @@ class ChartingState extends MusicBeatState // @:privateAccess // library.pathGroups.set(symbolPath, [library.__cacheBreak(symbolPath)]); // var callback = callbacks.add("song:" + pathShit); - openfl.utils.Assets.loadSound(pathShit).onComplete(function(_) - { + openfl.utils.Assets.loadSound(pathShit).onComplete(function(_) { // callback(); }); } @@ -443,7 +431,7 @@ class ChartingState extends MusicBeatState add(playheadTest); // WONT WORK FOR TUTORIAL OR TEST SONG!!! REDO LATER - vocals = VoicesGroup.build(daSong, _song.voiceList); + vocals = new VoicesGroup(); // vocals = new FlxSound().loadEmbedded(Paths.voices(daSong)); // FlxG.sound.list.add(vocals); @@ -477,8 +465,7 @@ class ChartingState extends MusicBeatState vocals.pause(); - FlxG.sound.music.onComplete = function() - { + FlxG.sound.music.onComplete = function() { vocals.pause(); vocals.time = 0; FlxG.sound.music.pause(); @@ -742,8 +729,7 @@ class ChartingState extends MusicBeatState if (FlxG.mouse.overlaps(curRenderedNotes)) { - curRenderedNotes.forEach(function(note:Note) - { + curRenderedNotes.forEach(function(note:Note) { if (FlxG.mouse.overlaps(note)) { selectNote(note); @@ -766,8 +752,7 @@ class ChartingState extends MusicBeatState { if (FlxG.mouse.overlaps(curRenderedNotes)) { - curRenderedNotes.forEach(function(note:Note) - { + curRenderedNotes.forEach(function(note:Note) { if (FlxG.mouse.overlaps(note)) { trace('tryin to delete note...'); @@ -1151,8 +1136,7 @@ class ChartingState extends MusicBeatState // null if checks jus cuz i put updateGrid() in some weird places! if (staticSpecGrp != null) { - staticSpecGrp.forEach(function(spec) - { + staticSpecGrp.forEach(function(spec) { if (spec != null) spec.generateSection(sectionStartTime(), (Conductor.stepCrochet * 32) / 1000); }); } diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubstate.hx index ddedf257c..079490501 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubstate.hx @@ -2,7 +2,7 @@ package funkin.play; import flixel.FlxObject; import flixel.FlxSprite; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.util.FlxColor; import flixel.util.FlxTimer; import funkin.modding.events.ScriptEvent; @@ -208,11 +208,9 @@ class GameOverSubstate extends MusicBeatSubstate boyfriend.playAnimation('deathConfirm' + animationSuffix, true); // After the animation finishes... - new FlxTimer().start(0.7, function(tmr:FlxTimer) - { + new FlxTimer().start(0.7, function(tmr:FlxTimer) { // ...fade out the graphics. Then after that happens... - FlxG.camera.fade(FlxColor.BLACK, 2, false, function() - { + FlxG.camera.fade(FlxColor.BLACK, 2, false, function() { // ...close the GameOverSubstate. FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true); PlayState.needsReset = true; @@ -276,8 +274,7 @@ class GameOverSubstate extends MusicBeatSubstate if (PreferencesMenu.getPref('censor-naughty')) randomCensor = [1, 3, 8, 13, 17, 21]; - FlxG.sound.play(Paths.sound('jeffGameover/jeffGameover-' + FlxG.random.int(1, 25, randomCensor)), 1, false, null, true, function() - { + FlxG.sound.play(Paths.sound('jeffGameover/jeffGameover-' + FlxG.random.int(1, 25, randomCensor)), 1, false, null, true, function() { // Once the quote ends, fade in the game over music. if (!isEnding && gameOverMusic != null) { diff --git a/source/funkin/play/character/AnimateAtlasCharacter.hx b/source/funkin/play/character/AnimateAtlasCharacter.hx index 483e1b1b8..7e7a979a4 100644 --- a/source/funkin/play/character/AnimateAtlasCharacter.hx +++ b/source/funkin/play/character/AnimateAtlasCharacter.hx @@ -25,8 +25,8 @@ typedef AnimateAtlasAnimation = { name:String, prefix:String, - offset:Null>, - loop:Bool, + offsets:Null>, + looped:Bool, } /** @@ -107,7 +107,7 @@ class AnimateAtlasCharacter extends BaseCharacter { super.onAnimationFinished(prefix); - if (getAnimationData() != null && getAnimationData().loop) + if (getAnimationData() != null && getAnimationData().looped) { playAnimation(prefix, true, false); } diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 853846414..19c24e7a8 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -1,7 +1,10 @@ package funkin.play.song; -import funkin.VoicesGroup; -import funkin.play.event.SongEvent; +import flixel.sound.FlxSound; +import openfl.utils.Assets; +import funkin.modding.events.ScriptEvent; +import funkin.modding.IScriptedClass; +import funkin.audio.VoicesGroup; import funkin.play.song.SongData.SongChartData; import funkin.play.song.SongData.SongDataParser; import funkin.play.song.SongData.SongEventData; @@ -20,7 +23,7 @@ import funkin.play.song.SongData.SongTimeFormat; * It also receives script events; scripted classes which extend this class * can be used to perform custom gameplay behaviors only on specific songs. */ -class Song // implements IPlayStateScriptedClass +class Song implements IPlayStateScriptedClass { public final songId:String; @@ -29,6 +32,11 @@ class Song // implements IPlayStateScriptedClass final variations:Array; final difficulties:Map; + /** + * Set to false if the song was edited in the charter and should not be saved as a high score. + */ + public var validScore:Bool = true; + public function new(id:String) { this.songId = id; @@ -59,6 +67,9 @@ class Song // implements IPlayStateScriptedClass // Variations may have different artist, time format, generatedBy, etc. for (metadata in _metadata) { + // There may be more difficulties in the chart file than in the metadata, + // (i.e. non-playable charts like the one used for Pico on the speaker in Stress) + // but all the difficulties in the metadata must be in the chart file. for (diffId in metadata.playData.difficulties) { var difficulty:SongDifficulty = new SongDifficulty(this, diffId, metadata.variation); @@ -70,7 +81,7 @@ class Song // implements IPlayStateScriptedClass difficulty.timeFormat = metadata.timeFormat; difficulty.divisions = metadata.divisions; difficulty.timeChanges = metadata.timeChanges; - difficulty.loop = metadata.loop; + difficulty.looped = metadata.looped; difficulty.generatedBy = metadata.generatedBy; difficulty.stage = metadata.playData.stage; @@ -111,8 +122,9 @@ class Song // implements IPlayStateScriptedClass var difficulty:Null = difficulties.get(diffId); if (difficulty == null) { - trace('Could not find difficulty $diffId for song $songId'); - continue; + trace('Fabricated new difficulty for $diffId.'); + difficulty = new SongDifficulty(this, diffId, variation); + difficulties.set(diffId, difficulty); } // Add the chart data to the difficulty. difficulty.notes = chartData.notes.get(diffId); @@ -151,6 +163,46 @@ class Song // implements IPlayStateScriptedClass { return 'Song($songId)'; } + + public function onPause(event:PauseScriptEvent):Void {}; + + public function onResume(event:ScriptEvent):Void {}; + + public function onSongLoaded(event:SongLoadScriptEvent):Void {}; + + public function onSongStart(event:ScriptEvent):Void {}; + + public function onSongEnd(event:ScriptEvent):Void {}; + + public function onGameOver(event:ScriptEvent):Void {}; + + public function onSongRetry(event:ScriptEvent):Void {}; + + public function onNoteHit(event:NoteScriptEvent):Void {}; + + public function onNoteMiss(event:NoteScriptEvent):Void {}; + + public function onNoteGhostMiss(event:GhostMissNoteScriptEvent):Void {}; + + public function onSongEvent(event:SongEventScriptEvent):Void {}; + + public function onStepHit(event:SongTimeScriptEvent):Void {}; + + public function onBeatHit(event:SongTimeScriptEvent):Void {}; + + public function onCountdownStart(event:CountdownScriptEvent):Void {}; + + public function onCountdownStep(event:CountdownScriptEvent):Void {}; + + public function onCountdownEnd(event:CountdownScriptEvent):Void {}; + + public function onScriptEvent(event:ScriptEvent):Void {}; + + public function onCreate(event:ScriptEvent):Void {}; + + public function onDestroy(event:ScriptEvent):Void {}; + + public function onUpdate(event:UpdateScriptEvent):Void {}; } class SongDifficulty @@ -184,7 +236,7 @@ class SongDifficulty public var songArtist:String = SongValidator.DEFAULT_ARTIST; public var timeFormat:SongTimeFormat = SongValidator.DEFAULT_TIMEFORMAT; public var divisions:Int = SongValidator.DEFAULT_DIVISIONS; - public var loop:Bool = SongValidator.DEFAULT_LOOP; + public var looped:Bool = SongValidator.DEFAULT_LOOPED; public var generatedBy:String = SongValidator.DEFAULT_GENERATEDBY; public var timeChanges:Array = []; @@ -231,31 +283,109 @@ class SongDifficulty return cast events; } - public inline function cacheInst() + public inline function cacheInst():Void { FlxG.sound.cache(Paths.inst(this.song.songId)); } - public inline function playInst(volume:Float = 1.0, looped:Bool = false) + public inline function playInst(volume:Float = 1.0, looped:Bool = false):Void { FlxG.sound.playMusic(Paths.inst(this.song.songId), volume, looped); } - public inline function cacheVocals() + /** + * Cache the vocals for a given character. + * @param id The character we are about to play. + */ + public inline function cacheVocals(?id:String = 'bf'):Void { - FlxG.sound.cache(Paths.voices(this.song.songId)); + for (voice in buildVoiceList(id)) + { + FlxG.sound.cache(voice); + } } - public function buildVoiceList():Array + /** + * Build a list of vocal files for the given character. + * Automatically resolves suffixed character IDs (so bf-car will resolve to bf if needed). + * + * @param id The character we are about to play. + */ + public function buildVoiceList(?id:String = 'bf'):Array { - // TODO: Implement. + var playableCharData:SongPlayableChar = getPlayableChar(id); + if (playableCharData == null) + { + trace('Could not find playable char $id for song ${this.song.songId}'); + return []; + } - return [""]; + // Automatically resolve voices by removing suffixes. + // For example, if `Voices-bf-car.ogg` does not exist, check for `Voices-bf.ogg`. + + var playerId:String = id; + var voicePlayer:String = Paths.voices(this.song.songId, '-$id'); + while (voicePlayer != null && !Assets.exists(voicePlayer)) + { + // Remove the last suffix. + // For example, bf-car becomes bf. + playerId = playerId.split('-').slice(0, -1).join('-'); + // Try again. + voicePlayer = playerId == '' ? null : Paths.voices(this.song.songId, '-${playerId}'); + } + + var opponentId:String = playableCharData.opponent; + var voiceOpponent:String = Paths.voices(this.song.songId, '-${opponentId}'); + while (voiceOpponent != null && !Assets.exists(voiceOpponent)) + { + // Remove the last suffix. + opponentId = opponentId.split('-').slice(0, -1).join('-'); + // Try again. + voiceOpponent = opponentId == '' ? null : Paths.voices(this.song.songId, '-${opponentId}'); + } + + var result:Array = []; + if (voicePlayer != null) result.push(voicePlayer); + if (voiceOpponent != null) result.push(voiceOpponent); + if (voicePlayer == null && voiceOpponent == null) + { + // Try to use `Voices.ogg` if no other voices are found. + if (Assets.exists(Paths.voices(this.song.songId, ''))) result.push(Paths.voices(this.song.songId, '')); + } + return result; } - public function buildVocals(charId:String = "bf"):VoicesGroup + /** + * Create a VoicesGroup, an audio object that can play the vocals for all characters. + * @param charId The player ID. + * @return The generated vocal group. + */ + public function buildVocals(charId:String = 'bf'):VoicesGroup { - var result:VoicesGroup = VoicesGroup.build(this.song.songId, this.buildVoiceList()); + var result:VoicesGroup = new VoicesGroup(); + + var voiceList:Array = buildVoiceList(charId); + + if (voiceList.length == 0) + { + trace('Could not find any voices for song ${this.song.songId}'); + return result; + } + + // Add player vocals. + if (voiceList[0] != null) result.addPlayerVoice(new FlxSound().loadEmbedded(Assets.getSound(voiceList[0]))); + // Add opponent vocals. + if (voiceList[1] != null) result.addOpponentVoice(new FlxSound().loadEmbedded(Assets.getSound(voiceList[1]))); + + // Add additional vocals. + if (voiceList.length > 2) + { + for (i in 2...voiceList.length) + { + result.add(new FlxSound().loadEmbedded(Assets.getSound(voiceList[i]))); + } + } + return result; } } diff --git a/source/funkin/play/song/SongData.hx b/source/funkin/play/song/SongData.hx index 60ae32ec1..a8fc0e4d7 100644 --- a/source/funkin/play/song/SongData.hx +++ b/source/funkin/play/song/SongData.hx @@ -220,7 +220,7 @@ typedef RawSongMetadata = var timeFormat:SongTimeFormat; var divisions:Int; var timeChanges:Array; - var loop:Bool; + var looped:Bool; var playData:SongPlayData; var generatedBy:String; @@ -243,7 +243,7 @@ abstract SongMetadata(RawSongMetadata) timeFormat: 'ms', divisions: 96, timeChanges: [new SongTimeChange(-1, 0, 100, 4, 4, [4, 4, 4, 4])], - loop: false, + looped: false, playData: { songVariations: [], @@ -271,7 +271,7 @@ abstract SongMetadata(RawSongMetadata) result.timeFormat = this.timeFormat; result.divisions = this.divisions; result.timeChanges = this.timeChanges; - result.loop = this.loop; + result.looped = this.looped; result.playData = this.playData; result.generatedBy = this.generatedBy; diff --git a/source/funkin/play/song/SongValidator.hx b/source/funkin/play/song/SongValidator.hx index c065743ad..950113bcf 100644 --- a/source/funkin/play/song/SongValidator.hx +++ b/source/funkin/play/song/SongValidator.hx @@ -17,7 +17,7 @@ class SongValidator public static final DEFAULT_ARTIST:String = "Unknown"; public static final DEFAULT_TIMEFORMAT:SongTimeFormat = SongTimeFormat.MILLISECONDS; public static final DEFAULT_DIVISIONS:Int = -1; - public static final DEFAULT_LOOP:Bool = false; + public static final DEFAULT_LOOPED:Bool = false; public static final DEFAULT_STAGE:String = "mainStage"; public static final DEFAULT_SCROLLSPEED:Float = 1.0; diff --git a/source/funkin/ui/animDebugShit/DebugBoundingState.hx b/source/funkin/ui/animDebugShit/DebugBoundingState.hx index 339bf15ac..a21384e76 100644 --- a/source/funkin/ui/animDebugShit/DebugBoundingState.hx +++ b/source/funkin/ui/animDebugShit/DebugBoundingState.hx @@ -10,7 +10,7 @@ import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxFrame; import flixel.group.FlxGroup; import flixel.math.FlxPoint; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.text.FlxText; import flixel.util.FlxColor; import flixel.util.FlxSpriteUtil; @@ -76,8 +76,7 @@ class DebugBoundingState extends FlxState // uiStuff.findComponent("btnViewSpriteSheet").onClick = _ -> curView = SPRITESHEET; var dropdown:DropDown = cast uiStuff.findComponent("swapper"); - dropdown.onChange = function(e:UIEvent) - { + dropdown.onChange = function(e:UIEvent) { trace(e.type); curView = cast e.data.curView; trace(e.data); @@ -147,8 +146,7 @@ class DebugBoundingState extends FlxState swagOutlines.antialiasing = true; spriteSheetView.add(swagOutlines); - FlxG.stage.window.onDropFile.add(function(path:String) - { + FlxG.stage.window.onDropFile.add(function(path:String) { // WACKY ASS TESTING SHIT FOR WEB FILE LOADING?? #if web var swagList:FileList = cast path; @@ -157,9 +155,8 @@ class DebugBoundingState extends FlxState trace(objShit); var funnysound = new FlxSound().loadStream('https://cdn.discordapp.com/attachments/767500676166451231/817821618251759666/Flutter.mp3', false, false, - null, function() - { - trace('LOADED SHIT??'); + null, function() { + trace('LOADED SHIT??'); }); funnysound.volume = 1; @@ -167,8 +164,7 @@ class DebugBoundingState extends FlxState var urlShit = new URLLoader(new URLRequest(objShit)); - new FlxTimer().start(3, function(tmr:FlxTimer) - { + new FlxTimer().start(3, function(tmr:FlxTimer) { // music lol! if (urlShit.dataFormat == BINARY) { @@ -255,8 +251,7 @@ class DebugBoundingState extends FlxState charDropdown.dataSource.add({text: char}); } - charDropdown.onChange = function(e:UIEvent) - { + charDropdown.onChange = function(e:UIEvent) { loadAnimShit(e.data.text); }; } @@ -306,8 +301,7 @@ class DebugBoundingState extends FlxState if (!LimeAssets.libraryPaths.exists(library)) throw "Missing library: " + library; // var callback = callbacks.add("library:" + library); - Assets.loadLibrary(library).onComplete(function(_) - { + Assets.loadLibrary(library).onComplete(function(_) { trace('LOADED... awesomeness...'); // callback(); }); @@ -483,8 +477,7 @@ class DebugBoundingState extends FlxState } animDropDownMenu.setData(FlxUIDropDownMenu.makeStrIdLabelArray(animThing, true)); - animDropDownMenu.callback = function(str:String) - { + animDropDownMenu.callback = function(str:String) { // clears the canvas onionSkinChar.pixels.fillRect(new Rectangle(0, 0, FlxG.width * 2, FlxG.height * 2), 0x00000000); diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 63ff44be2..4e050b19b 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -13,12 +13,12 @@ import flixel.FlxSprite; import flixel.group.FlxSpriteGroup; import flixel.math.FlxPoint; import flixel.math.FlxRect; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; import flixel.util.FlxColor; import flixel.util.FlxSort; import flixel.util.FlxTimer; import funkin.audio.visualize.PolygonSpectogram; -import funkin.audio.VocalGroup; +import funkin.audio.VoicesGroup; import funkin.input.Cursor; import funkin.modding.events.ScriptEvent; import funkin.play.HealthIcon; @@ -596,14 +596,14 @@ class ChartEditorState extends HaxeUIState /** * The audio track for the vocals. */ - var audioVocalTrackGroup:VocalGroup; + var audioVocalTrackGroup:VoicesGroup; /** * A map of the audio tracks for each character's vocals. * - Keys are the character IDs. * - Values are the FlxSound objects to play that character's vocals. * - * When switching characters, the elements of the VocalGroup will be swapped to match the new character. + * When switching characters, the elements of the VoicesGroup will be swapped to match the new character. */ var audioVocalTracks:Map = new Map(); @@ -961,7 +961,7 @@ class ChartEditorState extends HaxeUIState // Initialize the song chart data. songChartData = new Map(); - audioVocalTrackGroup = new VocalGroup(); + audioVocalTrackGroup = new VoicesGroup(); } /** From 2f10de3594283a6addadf1793ff3b751a730a8e2 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 25 May 2023 18:34:26 -0400 Subject: [PATCH 2/3] New refactor to VoicesGroup to make multiple vocal tracks actually work --- source/funkin/SongLoad.hx | 17 +- source/funkin/audio/FlxAudioGroup.hx | 194 ------------------ .../{VoicesGroup.hx => audio/SoundGroup.hx} | 104 +++++++--- source/funkin/audio/VocalGroup.hx | 119 ----------- source/funkin/audio/VoicesGroup.hx | 68 ++++++ source/funkin/play/PlayState.hx | 59 +++--- 6 files changed, 183 insertions(+), 378 deletions(-) delete mode 100644 source/funkin/audio/FlxAudioGroup.hx rename source/funkin/{VoicesGroup.hx => audio/SoundGroup.hx} (55%) delete mode 100644 source/funkin/audio/VocalGroup.hx create mode 100644 source/funkin/audio/VoicesGroup.hx diff --git a/source/funkin/SongLoad.hx b/source/funkin/SongLoad.hx index 07c21e22c..d4ad0023e 100644 --- a/source/funkin/SongLoad.hx +++ b/source/funkin/SongLoad.hx @@ -119,16 +119,21 @@ class SongLoad switch (diff) { case 'easy': - speedShit = songData.speed.easy; + speedShit = songData?.speed?.easy ?? 1.0; case 'normal': - speedShit = songData.speed.normal; + speedShit = songData?.speed?.normal ?? 1.0; case 'hard': - speedShit = songData.speed.hard; + speedShit = songData?.speed?.hard ?? 1.0; } - if (songData.speedMap[diff] == null) songData.speedMap[diff] = 1; - - speedShit = songData.speedMap[diff]; + if (songData?.speedMap == null || songData?.speedMap[diff] == null) + { + speedShit = 1; + } + else + { + speedShit = songData.speedMap[diff]; + } return speedShit; } diff --git a/source/funkin/audio/FlxAudioGroup.hx b/source/funkin/audio/FlxAudioGroup.hx deleted file mode 100644 index b506eaed9..000000000 --- a/source/funkin/audio/FlxAudioGroup.hx +++ /dev/null @@ -1,194 +0,0 @@ -package funkin.audio; - -import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.system.FlxSound; - -/** - * A group of FlxSounds which can be controlled as a whole. - * - * Add sounds to the group using `add()`, and then control them - * as a whole using the properties and methods of this class. - * - * It is assumed that all the sounds will play at the same time, - * and have the same duration. - */ -class FlxAudioGroup extends FlxTypedGroup -{ - /** - * The position in time of the sounds in the group. - * Measured in milliseconds. - */ - public var time(get, set):Float; - - function get_time():Float - { - if (getFirstAlive() != null) return getFirstAlive().time; - else - return 0; - } - - function set_time(time:Float):Float - { - forEachAlive(function(sound:FlxSound) { - // account for different offsets per sound? - sound.time = time; - }); - - return time; - } - - /** - * The volume of the sounds in the group. - */ - public var volume(get, set):Float; - - function get_volume():Float - { - if (getFirstAlive() != null) return getFirstAlive().volume; - else - return 1.0; - } - - function set_volume(volume:Float):Float - { - forEachAlive(function(sound:FlxSound) { - sound.volume = volume; - }); - - return volume; - } - - /** - * The pitch of the sounds in the group, as a multiplier of 1.0x. - * `2.0` would play the audio twice as fast with a higher pitch, - * and `0.5` would play the audio at half speed with a lower pitch. - */ - public var pitch(get, set):Float; - - function get_pitch():Float - { - #if FLX_PITCH - if (getFirstAlive() != null) return getFirstAlive().pitch; - else - #end - return 1; - } - - function set_pitch(val:Float):Float - { - #if FLX_PITCH - trace('Setting audio pitch to ' + val); - forEachAlive(function(sound:FlxSound) { - sound.pitch = val; - }); - #end - return val; - } - - /** - * Whether members of the group should be destroyed when they finish playing. - */ - public var autoDestroyMembers(default, set):Bool = false; - - function set_autoDestroyMembers(value:Bool):Bool - { - autoDestroyMembers = value; - forEachAlive(function(sound:FlxSound) { - sound.autoDestroy = value; - }); - return value; - } - - /** - * Add a sound to the group. - */ - public override function add(sound:FlxSound):FlxSound - { - var result:FlxSound = super.add(sound); - - if (result == null) return null; - - // Apply parameters to the new sound. - result.autoDestroy = this.autoDestroyMembers; - result.pitch = this.pitch; - result.volume = this.volume; - - // We have to play, then pause the sound to set the time, - // else the sound will restart immediately when played. - result.play(true, 0.0); - result.pause(); - result.time = this.time; - - return result; - } - - /** - * Pause all the sounds in the group. - */ - public function pause() - { - forEachAlive(function(sound:FlxSound) { - sound.pause(); - }); - } - - /** - * Play all the sounds in the group. - */ - public function play(forceRestart:Bool = false, startTime:Float = 0.0, ?endTime:Float) - { - forEachAlive(function(sound:FlxSound) { - sound.play(forceRestart, startTime, endTime); - }); - } - - /** - * Resume all the sounds in the group. - */ - public function resume() - { - forEachAlive(function(sound:FlxSound) { - sound.resume(); - }); - } - - /** - * Stop all the sounds in the group. - */ - public function stop() - { - forEachAlive(function(sound:FlxSound) { - sound.stop(); - }); - } - - public override function clear():Void - { - this.stop(); - - super.clear(); - } - - /** - * Calculates the deviation of the sounds in the group from the target time. - * - * @param targetTime The time to compare the sounds to. - * If null, the current time of the first sound in the group is used. - * @return The largest deviation of the sounds in the group from the target time. - */ - public function calcDeviation(?targetTime:Float):Float - { - var deviation:Float = 0; - - forEachAlive(function(sound:FlxSound) { - if (targetTime == null) targetTime = sound.time; - else - { - var diff:Float = sound.time - targetTime; - if (Math.abs(diff) > Math.abs(deviation)) deviation = diff; - } - }); - - return deviation; - } -} diff --git a/source/funkin/VoicesGroup.hx b/source/funkin/audio/SoundGroup.hx similarity index 55% rename from source/funkin/VoicesGroup.hx rename to source/funkin/audio/SoundGroup.hx index cf1014f29..df197148b 100644 --- a/source/funkin/VoicesGroup.hx +++ b/source/funkin/audio/SoundGroup.hx @@ -1,11 +1,13 @@ -package funkin; +package funkin.audio; import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.system.FlxSound; +import flixel.sound.FlxSound; -// different than FlxSoundGroup cuz this can control all the sounds time and shit -// when needed -class VoicesGroup extends FlxTypedGroup +/** + * A group of FlxSounds that are all synced together. + * Unlike FlxSoundGroup, you cann also control their time and pitch. + */ +class SoundGroup extends FlxTypedGroup { public var time(get, set):Float; @@ -13,16 +15,15 @@ class VoicesGroup extends FlxTypedGroup public var pitch(get, set):Float; - // make it a group that you add to? public function new() { super(); } - // TODO: Remove this. - public static function build(song:String, ?files:Array = null):VoicesGroup + @:deprecated("Create sound files and call add() instead") + public static function build(song:String, ?files:Array = null):SoundGroup { - var result = new VoicesGroup(); + var result = new SoundGroup(); if (files == null) { @@ -42,18 +43,17 @@ class VoicesGroup extends FlxTypedGroup } /** - * Finds the largest deviation from the desired time inside this VoicesGroup. + * Finds the largest deviation from the desired time inside this SoundGroup. * * @param targetTime The time to check against. - * If none is provided, it checks the time of all members against the first member of this VoicesGroup. + * If none is provided, it checks the time of all members against the first member of this SoundGroup. * @return The largest deviation from the target time found. */ public function checkSyncError(?targetTime:Float):Float { var error:Float = 0; - forEachAlive(function(snd) - { + forEachAlive(function(snd) { if (targetTime == null) targetTime = snd.time; else { @@ -64,31 +64,78 @@ class VoicesGroup extends FlxTypedGroup return error; } - // prob a better / cleaner way to do all these forEach stuff? + /** + * Add a sound to the group. + */ + public override function add(sound:FlxSound):FlxSound + { + var result:FlxSound = super.add(sound); + + if (result == null) return null; + + // We have to play, then pause the sound to set the time, + // else the sound will restart immediately when played. + result.play(true, 0.0); + result.pause(); + result.time = this.time; + + // Apply parameters to the new sound. + result.pitch = this.pitch; + result.volume = this.volume; + + return result; + } + + /** + * Pause all the sounds in the group. + */ public function pause() { - forEachAlive(function(snd) - { - snd.pause(); + forEachAlive(function(sound:FlxSound) { + sound.pause(); }); } - public function play() + /** + * Play all the sounds in the group. + */ + public function play(forceRestart:Bool = false, startTime:Float = 0.0, ?endTime:Float) { - forEachAlive(function(snd) - { - snd.play(); + forEachAlive(function(sound:FlxSound) { + sound.play(forceRestart, startTime, endTime); }); } + /** + * Resume all the sounds in the group. + */ + public function resume() + { + forEachAlive(function(sound:FlxSound) { + sound.resume(); + }); + } + + /** + * Stop all the sounds in the group. + */ public function stop() { - forEachAlive(function(snd) - { - snd.stop(); + forEachAlive(function(sound:FlxSound) { + sound.stop(); }); } + /** + * Remove all sounds from the group. + */ + public override function clear():Void + { + this.stop(); + + super.clear(); + } + function get_time():Float { if (getFirstAlive() != null) return getFirstAlive().time; @@ -98,8 +145,7 @@ class VoicesGroup extends FlxTypedGroup function set_time(time:Float):Float { - forEachAlive(function(snd) - { + forEachAlive(function(snd) { // account for different offsets per sound? snd.time = time; }); @@ -117,8 +163,7 @@ class VoicesGroup extends FlxTypedGroup // in PlayState, adjust the code so that it only mutes the player1 vocal tracks? function set_volume(volume:Float):Float { - forEachAlive(function(snd) - { + forEachAlive(function(snd) { snd.volume = volume; }); @@ -138,8 +183,7 @@ class VoicesGroup extends FlxTypedGroup { #if FLX_PITCH trace('Setting audio pitch to ' + val); - forEachAlive(function(snd) - { + forEachAlive(function(snd) { snd.pitch = val; }); #end diff --git a/source/funkin/audio/VocalGroup.hx b/source/funkin/audio/VocalGroup.hx deleted file mode 100644 index 31539eab1..000000000 --- a/source/funkin/audio/VocalGroup.hx +++ /dev/null @@ -1,119 +0,0 @@ -package funkin.audio; - -import flixel.system.FlxSound; - -/** - * An audio group that allows for specific control of vocal tracks. - */ -class VocalGroup extends FlxAudioGroup -{ - /** - * The player's vocal track. - */ - var playerVocals:FlxSound; - - /** - * The opponent's vocal track. - */ - var opponentVocals:FlxSound; - - /** - * The volume of the player's vocal track. - * Nore that this value is multiplied by the overall volume of the group. - */ - public var playerVolume(default, set):Float; - - function set_playerVolume(value:Float):Float - { - playerVolume = value; - if (playerVocals != null) - { - // Make sure volume is capped at 1.0. - playerVocals.volume = Math.min(playerVolume * this.volume, 1.0); - } - return playerVolume; - } - - /** - * The volume of the opponent's vocal track. - * Nore that this value is multiplied by the overall volume of the group. - */ - public var opponentVolume(default, set):Float; - - function set_opponentVolume(value:Float):Float - { - opponentVolume = value; - if (opponentVocals != null) - { - // Make sure volume is capped at 1.0. - opponentVocals.volume = opponentVolume * this.volume; - } - return opponentVolume; - } - - /** - * Sets up the player's vocal track. - * Stops and removes the existing player track if one exists. - */ - public function setPlayerVocals(sound:FlxSound):FlxSound - { - if (playerVocals != null) - { - playerVocals.stop(); - remove(playerVocals); - playerVocals = null; - } - - playerVocals = add(sound); - playerVocals.volume = this.playerVolume * this.volume; - - return playerVocals; - } - - /** - * Sets up the opponent's vocal track. - * Stops and removes the existing player track if one exists. - */ - public function setOpponentVocals(sound:FlxSound):FlxSound - { - if (opponentVocals != null) - { - opponentVocals.stop(); - remove(opponentVocals); - opponentVocals = null; - } - - opponentVocals = add(sound); - opponentVocals.volume = this.opponentVolume * this.volume; - - return opponentVocals; - } - - /** - * In this extension of FlxAudioGroup, there is a separate overall volume - * which affects all the members of the group. - */ - var _volume = 1.0; - - override function get_volume():Float - { - return _volume; - } - - override function set_volume(value:Float):Float - { - _volume = super.set_volume(value); - - if (playerVocals != null) - { - playerVocals.volume = playerVolume * _volume; - } - - if (opponentVocals != null) - { - opponentVocals.volume = opponentVolume * _volume; - } - - return _volume; - } -} diff --git a/source/funkin/audio/VoicesGroup.hx b/source/funkin/audio/VoicesGroup.hx new file mode 100644 index 000000000..9f688eb48 --- /dev/null +++ b/source/funkin/audio/VoicesGroup.hx @@ -0,0 +1,68 @@ +package funkin.audio; + +import flixel.sound.FlxSound; +import flixel.group.FlxGroup.FlxTypedGroup; + +class VoicesGroup extends SoundGroup +{ + var playerVoices:FlxTypedGroup; + var opponentVoices:FlxTypedGroup; + + /** + * Control the volume of only the sounds in the player group. + */ + public var playerVolume(default, set):Float; + + /** + * Control the volume of only the sounds in the opponent group. + */ + public var opponentVolume(default, set):Float; + + public function new() + { + super(); + playerVoices = new FlxTypedGroup(); + opponentVoices = new FlxTypedGroup(); + } + + /** + * Add a voice to the player group. + */ + public function addPlayerVoice(sound:FlxSound):Void + { + super.add(sound); + playerVoices.add(sound); + } + + function set_playerVolume(volume:Float):Float + { + playerVoices.forEachAlive(function(voice:FlxSound) { + voice.volume = volume; + }); + return playerVolume = volume; + } + + /** + * Add a voice to the opponent group. + */ + public function addOpponentVoice(sound:FlxSound):Void + { + super.add(sound); + opponentVoices.add(sound); + } + + function set_opponentVolume(volume:Float):Float + { + opponentVoices.forEachAlive(function(voice:FlxSound) { + voice.volume = volume; + }); + return opponentVolume = volume; + } + + public override function clear():Void + { + playerVoices.clear(); + opponentVoices.clear(); + super.clear(); + } +} diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 0d99744a1..b261a54d9 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1,11 +1,13 @@ package funkin.play; +import funkin.play.song.SongData.SongDataParser; +import flixel.sound.FlxSound; +import flixel.addons.transition.FlxTransitionableState; import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxSprite; import flixel.FlxState; import flixel.FlxSubState; -import flixel.addons.transition.FlxTransitionableState; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.input.keyboard.FlxKey; import flixel.math.FlxMath; @@ -17,18 +19,14 @@ import flixel.ui.FlxBar; import flixel.util.FlxColor; import flixel.util.FlxSort; import flixel.util.FlxTimer; -import funkin.Highscore.Tallies; -import funkin.Note; -import funkin.Section.SwagSection; -import funkin.SongLoad.SwagSong; import funkin.charting.ChartingState; +import funkin.Highscore.Tallies; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEventDispatcher; -import funkin.play.Strumline.StrumlineArrow; -import funkin.play.Strumline.StrumlineStyle; +import funkin.Note; import funkin.play.character.BaseCharacter; -import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.character.CharacterData; +import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.cutscene.VanillaCutscenes; import funkin.play.event.SongEvent.SongEventParser; import funkin.play.scoring.Scoring; @@ -39,6 +37,11 @@ import funkin.play.song.SongData.SongPlayableChar; import funkin.play.song.SongValidator; import funkin.play.stage.Stage; import funkin.play.stage.StageData.StageDataParser; +import funkin.play.Strumline.StrumlineArrow; +import funkin.play.Strumline.StrumlineStyle; +import funkin.Section.SwagSection; +import funkin.SongLoad.SwagSong; +import funkin.audio.VoicesGroup; import funkin.ui.PopUpStuff; import funkin.ui.PreferencesMenu; import funkin.ui.stageBuildShit.StageOffsetSubstate; @@ -359,7 +362,7 @@ class PlayState extends MusicBeatState if (currentChart != null) { currentChart.cacheInst(); - currentChart.cacheVocals(); + currentChart.cacheVocals('bf'); } else { @@ -1059,9 +1062,11 @@ class PlayState extends MusicBeatState currentSong.song = currentSong.song; - if (currentSong.needsVoices) vocals = VoicesGroup.build(currentSong.song, currentSong.voiceList); - else - vocals = VoicesGroup.build(currentSong.song, null); + vocals = new VoicesGroup(); + var playerVocals:FlxSound = FlxG.sound.load(Paths.voices(currentSong.song, 'bf'), 1.0, false); + vocals.addPlayerVoice(playerVocals); + var opponentVocals:FlxSound = FlxG.sound.load(Paths.voices(currentSong.song, 'dad'), 1.0, false); + vocals.addOpponentVoice(opponentVocals); vocals.members[0].onComplete = function() { vocalsFinished = true; @@ -1427,6 +1432,8 @@ class PlayState extends MusicBeatState FlxG.sound.music.volume = 1; vocals.volume = 1; + vocals.playerVolume = 1; + vocals.opponentVolume = 1; currentStage.resetStage(); @@ -1719,7 +1726,7 @@ class PlayState extends MusicBeatState else { // Volume of DAD. - if (currentSong != null && currentSong.needsVoices) vocals.volume = 1; + if (currentSong != null && currentSong.needsVoices) vocals.opponentVolume = 1; } } @@ -1903,7 +1910,7 @@ class PlayState extends MusicBeatState // if () StoryMenuState.weekUnlocked[Std.int(Math.min(storyWeek + 1, StoryMenuState.weekUnlocked.length - 1))] = true; - if (currentSong.validScore) + if (currentSong?.validScore) { NGio.unlockMedal(60961); Highscore.saveWeekScore(storyWeek, campaignScore, storyDifficulty); @@ -1929,7 +1936,7 @@ class PlayState extends MusicBeatState FlxG.sound.music.stop(); vocals.stop(); - if (currentSong.song.toLowerCase() == 'eggnog') + if ((currentSong?.song ?? '').toLowerCase() == 'eggnog') { var blackShit:FlxSprite = new FlxSprite(-FlxG.width * FlxG.camera.zoom, -FlxG.height * FlxG.camera.zoom).makeGraphic(FlxG.width * 3, FlxG.height * 3, FlxColor.BLACK); @@ -1948,7 +1955,7 @@ class PlayState extends MusicBeatState { previousCameraFollowPoint = cameraFollowPoint; - currentSong = SongLoad.loadFromJson(storyPlaylist[0].toLowerCase() + difficulty, storyPlaylist[0]); + currentSong_NEW = SongDataParser.fetchSong(PlayState.storyPlaylist[0].toLowerCase()); LoadingState.loadAndSwitchState(new PlayState()); } } @@ -1992,7 +1999,7 @@ class PlayState extends MusicBeatState { var noteDiff:Float = Math.abs(strumtime - Conductor.songPosition); // boyfriend.playAnimation('hey'); - vocals.volume = 1; + vocals.playerVolume = 1; var isSick:Bool = false; var score = Scoring.scoreNote(noteDiff, PBOT1); @@ -2124,7 +2131,6 @@ class PlayState extends MusicBeatState // TODO: Un-hardcode this stuff. if (currentStage.getDad().characterId == 'mom') { - vocals.volume = 1; } if (currentSong.song.toLowerCase() == 'tutorial') @@ -2312,7 +2318,7 @@ class PlayState extends MusicBeatState if (event.playSound) { - vocals.volume = 0; + vocals.playerVolume = 0; FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2)); } } @@ -2367,7 +2373,7 @@ class PlayState extends MusicBeatState }); } } - vocals.volume = 0; + vocals.playerVolume = 0; if (Highscore.tallies.combo != 0) { @@ -2405,7 +2411,7 @@ class PlayState extends MusicBeatState playerStrumline.getArrow(note.data.noteData).playAnimation('confirm', true); note.wasGoodHit = true; - vocals.volume = 1; + vocals.playerVolume = 1; if (!note.isSustainNote) { @@ -2742,15 +2748,10 @@ class PlayState extends MusicBeatState * This function is called whenever Flixel switches switching to a new FlxState. * @return Whether to actually switch to the new state. */ - override function switchTo(nextState:FlxState):Bool + override function startOutro(onComplete:() -> Void):Void { - var result = super.switchTo(nextState); + performCleanup(); - if (result) - { - performCleanup(); - } - - return result; + onComplete(); } } From dc932eb8d7f8f44087fd2e8322151debe94c23c6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 25 May 2023 19:36:32 -0400 Subject: [PATCH 3/3] A few bug fixes related to vocal tracks --- hmm.json | 4 ++-- source/funkin/audio/SoundGroup.hx | 6 ++++++ source/funkin/play/PlayState.hx | 2 +- source/funkin/play/song/Song.hx | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/hmm.json b/hmm.json index 9061d594b..e92868545 100644 --- a/hmm.json +++ b/hmm.json @@ -89,7 +89,7 @@ { "name": "json2object", "type": "haxelib", - "version": null + "version": "3.11.0" }, { "name": "lime", @@ -118,4 +118,4 @@ "version": "0.2.2" } ] -} +} \ No newline at end of file diff --git a/source/funkin/audio/SoundGroup.hx b/source/funkin/audio/SoundGroup.hx index df197148b..69c52c3d0 100644 --- a/source/funkin/audio/SoundGroup.hx +++ b/source/funkin/audio/SoundGroup.hx @@ -79,6 +79,10 @@ class SoundGroup extends FlxTypedGroup result.pause(); result.time = this.time; + result.onComplete = function() { + this.onComplete(); + } + // Apply parameters to the new sound. result.pitch = this.pitch; result.volume = this.volume; @@ -86,6 +90,8 @@ class SoundGroup extends FlxTypedGroup return result; } + public dynamic function onComplete():Void {} + /** * Pause all the sounds in the group. */ diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 4698c7e7e..047a1b5fe 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1093,7 +1093,7 @@ class PlayState extends MusicBeatState // TODO: Fix grouped vocals vocals = currentChart.buildVocals(); - vocals.members[0].onComplete = function() { + vocals.onComplete = function() { vocalsFinished = true; } diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 93f7d42a3..a712de1cc 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -305,7 +305,7 @@ class SongDifficulty public inline function playInst(volume:Float = 1.0, looped:Bool = false):Void { - var suffix:String = variation == null ? null : '-$variation'; + var suffix:String = (variation ?? '') != '' ? '-$variation' : ''; FlxG.sound.playMusic(Paths.inst(this.song.songId, suffix), volume, looped); } @@ -336,7 +336,7 @@ class SongDifficulty return []; } - var suffix:String = variation != null ? '-$variation' : ''; + var suffix:String = (variation ?? '') != '' ? '-$variation' : ''; // Automatically resolve voices by removing suffixes. // For example, if `Voices-bf-car.ogg` does not exist, check for `Voices-bf.ogg`.