From b502208b90cb6ea378f38dbf80551b3cbb6b7677 Mon Sep 17 00:00:00 2001 From: Ryiuu <161896371+Ryiuu04@users.noreply.github.com> Date: Tue, 6 Aug 2024 19:24:32 -0300 Subject: [PATCH] cool stuff + small fixes if you can't compile, install hxvlc 1.2.0 --- Project.xml | 1 + source/backend/CustomFadeTransition.hx | 30 +-- source/backend/Paths.hx | 124 ++++++--- source/flxanimate/FlxAnimate.hx | 67 +++++ source/flxanimate/frames/FlxAnimateFrames.hx | 180 ++++++++----- source/luafiles/FlxAnimateFunctions.hx | 14 +- source/luafiles/ModchartState.hx | 250 ++++++++++++++++++- source/objects/PsychVideoSprite.hx | 3 +- source/states/PlayState.hx | 148 ++++++++--- source/states/editors/ChartingState.hx | 108 +++++++- source/substates/PauseSubState.hx | 1 + 11 files changed, 759 insertions(+), 167 deletions(-) diff --git a/Project.xml b/Project.xml index 577b43b..857b067 100644 --- a/Project.xml +++ b/Project.xml @@ -135,6 +135,7 @@ + diff --git a/source/backend/CustomFadeTransition.hx b/source/backend/CustomFadeTransition.hx index 03d64ec..ecd39d6 100644 --- a/source/backend/CustomFadeTransition.hx +++ b/source/backend/CustomFadeTransition.hx @@ -41,20 +41,11 @@ class CustomFadeTransition extends MusicBeatSubstate transitionSprite = new FlxSprite(-2600); transitionSprite.loadGraphic(Paths.image('transition thingy')); - //transitionSprite.frames = Paths.getSparrowAtlas('circle thing', 'preload'); - //transitionSprite.animation.addByPrefix('transition', 'kevin_normal', 60, false); transitionSprite.scrollFactor.set(0, 0); add(transitionSprite); if (isTransIn) { - //transitionSprite.animation.play('transition', true, true, 28); - //transitionSprite.animation.callback = function(anim, framenumber, frameindex) - //{ - //if (framenumber == 0) - //close(); - //} - transitionSprite.x = -620; FlxTween.tween(transitionSprite, { x: 1280 }, 0.4, { @@ -66,15 +57,6 @@ class CustomFadeTransition extends MusicBeatSubstate } else { - // transitionSprite.animation.play('transition', true); - // transitionSprite.animation.callback = function(anim, framenumber, frameindex) - // { - //if (finishCallback != null && framenumber == 28) - //{ - //finishCallback(); - //} - //} - transitionSprite.x = -2600; FlxTween.tween(transitionSprite, { x: -620 }, 0.4, { @@ -86,11 +68,13 @@ class CustomFadeTransition extends MusicBeatSubstate } - if (nextCamera != null) - { - transitionSprite.cameras = [nextCamera]; - } - nextCamera = null; + //quick fix for the character editor/stage editor + var transitionCamera = new FlxCamera(); + transitionCamera.bgColor.alpha = 0; + FlxG.cameras.add(transitionCamera, false); + + transitionSprite.cameras = [transitionCamera]; + // } override function update(elapsed:Float) diff --git a/source/backend/Paths.hx b/source/backend/Paths.hx index dd94cc6..107fc5f 100644 --- a/source/backend/Paths.hx +++ b/source/backend/Paths.hx @@ -250,38 +250,35 @@ class Paths return FileSystem.absolutePath('assets/songs/${songLowercase}/'+pre+'Inst'+suf+'.$SOUND_EXT'); } - inline static public function voices2(song:String, ?library:String) + inline static public function voices2(song:String, postfix:String = null, ?library:String/*this library shit is even used?*/) { var songLowercase = StringTools.replace(song, " ", "-").toLowerCase(); - switch (songLowercase) { - case 'dad-battle': songLowercase = 'dadbattle'; - case 'philly-nice': songLowercase = 'philly'; - } var pre:String = ""; var suf:String = ""; if (Main.noCopyright && (Assets.exists('songs:assets/songs/${songLowercase}/'+'Voices'+'Alt'+'.$SOUND_EXT') || FileSystem.exists(Paths.modsSounds('songs', '${songLowercase}/'+pre+'VoicesAlt')))) suf = 'Alt'; - if (PlayState.isNeonight) - suf = 'NN'; - if (PlayState.isVitor) - suf = 'V'; - if (PlayState.isBETADCIU && CoolUtil.difficulties[0] == "Guest" && (Assets.exists('songs:assets/songs/${songLowercase}/'+'Voices'+'Guest'+'.$SOUND_EXT') || FileSystem.exists(Paths.modsSounds('songs', '${songLowercase}/'+pre+'VoicesGuest')))) - suf = 'Guest'; - if (PlayState.isBETADCIU && (Assets.exists('songs:assets/songs/${songLowercase}/'+'Voices'+'BETADCIU'+'.$SOUND_EXT') || FileSystem.exists(Paths.modsSounds('songs', '${songLowercase}/'+pre+'VoicesBETADCIU')))) - suf = 'BETADCIU'; - - if (FileSystem.exists(Paths.modsSounds('songs', '${songLowercase}/'+pre+'Voices'+suf))) - { - returnSound('songs', '${songLowercase}/'+pre+'Voices'+suf); - return Paths.modsSounds('songs', '${songLowercase}/'+pre+'Voices'+suf); - } - - return FileSystem.absolutePath('assets/songs/${songLowercase}/'+pre+'Voices'+suf+'.$SOUND_EXT'); - } - - inline static public function voices(song:String) + if (PlayState.isNeonight) + suf = 'NN'; + if (PlayState.isVitor) + suf = 'V'; + if (PlayState.isBETADCIU && CoolUtil.difficulties[0] == "Guest" && (Assets.exists('songs:assets/songs/${songLowercase}/'+'Voices'+'Guest'+'.$SOUND_EXT') || FileSystem.exists(Paths.modsSounds('songs', '${songLowercase}/'+pre+'VoicesGuest')))) + suf = 'Guest'; + if (PlayState.isBETADCIU && (Assets.exists('songs:assets/songs/${songLowercase}/'+'Voices'+'BETADCIU'+'.$SOUND_EXT') || FileSystem.exists(Paths.modsSounds('songs', '${songLowercase}/'+pre+'VoicesBETADCIU')))) + suf = 'BETADCIU'; + if (postfix != null) suf += '-' + postfix; + + if (FileSystem.exists(Paths.modsSounds('songs', '${songLowercase}/'+pre+'Voices'+suf))) + { + returnSound('songs', '${songLowercase}/'+pre+'Voices'+suf); + return Paths.modsSounds('songs', '${songLowercase}/'+pre+'Voices'+suf); + } + + return FileSystem.absolutePath('assets/songs/${songLowercase}/'+pre+'Voices'+suf+'.$SOUND_EXT'); + } + + inline static public function voices(song:String, ?postfix:String = null) { var songLowercase = StringTools.replace(song, " ", "-").toLowerCase(); switch (songLowercase) { @@ -299,11 +296,10 @@ class Paths suf = 'V'; if (PlayState.isBETADCIU && CoolUtil.difficulties[0] == "Guest") suf = 'Guest'; - if (PlayState.isBETADCIU && (songLowercase == 'kaboom' || songLowercase == 'triple-trouble')) + if (PlayState.isBETADCIU) suf = 'BETADCIU'; - if (Main.isMegalo && songLowercase == 'hill-of-the-void') - suf = 'Megalo'; - + if (postfix != null) suf += '-' + postfix; + return 'songs:assets/songs/${songLowercase}/'+pre+'Voices'+suf+'.$SOUND_EXT'; } @@ -953,4 +949,76 @@ class Paths return list; } #end + + #if flxanimate + public static function loadAnimateAtlas(spr:FlxAnimate, folderOrImg:Dynamic, spriteJson:Dynamic = null, animationJson:Dynamic = null) + { + var changedAnimJson = false; + var changedAtlasJson = false; + var changedImage = false; + + if(spriteJson != null) + { + changedAtlasJson = true; + spriteJson = File.getContent(spriteJson); + } + + if(animationJson != null) + { + changedAnimJson = true; + animationJson = File.getContent(animationJson); + } + + // is folder or image path + if(Std.isOfType(folderOrImg, String)) + { + var originalPath:String = folderOrImg; + for (i in 0...10) + { + var st:String = '$i'; + if(i == 0) st = ''; + + if(!changedAtlasJson) + { + spriteJson = getTextFromFile('images/$originalPath/spritemap$st.json'); + if(spriteJson != null) + { + trace('found Sprite Json'); + changedImage = true; + changedAtlasJson = true; + folderOrImg = returnGraphic('$originalPath/spritemap$st'); + break; + } + } + else if(fileExists('images/$originalPath/spritemap$st.png', IMAGE)) + { + trace('found Sprite PNG'); + changedImage = true; + folderOrImg = returnGraphic('$originalPath/spritemap$st'); + break; + } + } + + if(!changedImage) + { + trace('Changing folderOrImg to FlxGraphic'); + changedImage = true; + folderOrImg = returnGraphic(originalPath); + } + + if(!changedAnimJson) + { + trace('found Animation Json'); + changedAnimJson = true; + animationJson = getTextFromFile('images/$originalPath/Animation.json'); + } + } + + trace(folderOrImg); + //trace(spriteJson); + //trace(animationJson); + + spr.loadAtlasEx(folderOrImg, spriteJson, animationJson); + } + #end } \ No newline at end of file diff --git a/source/flxanimate/FlxAnimate.hx b/source/flxanimate/FlxAnimate.hx index 98ceeb4..ec09633 100644 --- a/source/flxanimate/FlxAnimate.hx +++ b/source/flxanimate/FlxAnimate.hx @@ -22,6 +22,7 @@ import flixel.math.FlxMatrix; import openfl.geom.ColorTransform; import flixel.math.FlxMath; import flixel.FlxBasic; +import flixel.system.FlxAssets.FlxGraphicAsset; typedef Settings = { ?ButtonSettings:Map, @@ -91,6 +92,72 @@ class FlxAnimate extends FlxSprite anim._loadAtlas(atlasSetting(Path)); frames = FlxAnimateFrames.fromTextureAtlas(Path); } + + public function loadAtlasEx(img:FlxGraphicAsset, pathOrStr:String = null, myJson:Dynamic = null) + { + var animJson:AnimAtlas = null; + if(myJson is String) + { + var trimmed:String = pathOrStr.trim(); + trimmed = trimmed.substr(trimmed.length - 5).toLowerCase(); + + if(trimmed == '.json') myJson = sys.io.File.getContent(myJson); //is a path + animJson = cast haxe.Json.parse(_removeBOM(myJson)); + } + else animJson = cast myJson; + + var isXml:Null = null; + var myData:Dynamic = pathOrStr; + + var trimmed:String = pathOrStr.trim(); + trimmed = trimmed.substr(trimmed.length - 5).toLowerCase(); + + if(trimmed == '.json') //Path is json + { + myData = sys.io.File.getContent(pathOrStr); + isXml = false; + } + else if (trimmed.substr(1) == '.xml') //Path is xml + { + myData = sys.io.File.getContent(pathOrStr); + isXml = true; + } + myData = _removeBOM(myData); + + // Automatic if everything else fails + switch(isXml) + { + case true: + myData = Xml.parse(myData); + case false: + myData = haxe.Json.parse(myData); + case null: + try + { + myData = haxe.Json.parse(myData); + isXml = false; + //trace('JSON parsed successfully!'); + } + catch(e) + { + myData = Xml.parse(myData); + isXml = true; + //trace('XML parsed successfully!'); + } + } + + anim._loadAtlas(animJson); + if(!isXml) frames = FlxAnimateFrames.fromAnimateAtlas(cast myData, img); + else frames = FlxAnimateFrames.fromSparrow(cast myData, img); + origin = anim.curInstance.symbol.transformationPoint; + } + + function _removeBOM(str:String) //Removes BOM byte order indicator + { + if (str.charCodeAt(0) == 0xFEFF) str = str.substr(1); //myData = myData.substr(2); + return str; + } + /** * the function `draw()` renders the symbol that `anim` has currently plus a pivot that you can toggle on or off. */ diff --git a/source/flxanimate/frames/FlxAnimateFrames.hx b/source/flxanimate/frames/FlxAnimateFrames.hx index 2b255f1..a91278f 100644 --- a/source/flxanimate/frames/FlxAnimateFrames.hx +++ b/source/flxanimate/frames/FlxAnimateFrames.hx @@ -42,10 +42,10 @@ class FlxAnimateFrames extends FlxAtlasFrames * @param Path Where the Sprites are, normally you use it once when calling FlxAnimate already * @return new sliced limbs for you to use ;) */ - public static function fromTextureAtlas(Path:String):FlxAtlasFrames + public static function fromTextureAtlas(Path:String):FlxAtlasFrames { var frames:FlxAnimateFrames = new FlxAnimateFrames(); - + if (zip != null || haxe.io.Path.extension(Path) == "zip") { #if html5 @@ -54,9 +54,9 @@ class FlxAnimateFrames extends FlxAtlasFrames #end var imagemap:Map = new Map(); var jsonMap:Map = new Map(); - var thing = (zip != null) ? zip : Zip.unzip(Zip.readZip(Assets.exists(Path) ? Assets.getBytes(Path) : File.getBytes(Path))); - for (list in thing) - { + var thing = (zip != null) ? zip : Zip.unzip(Zip.readZip(#if sys sys.io.File.getBytes(Path) #else Assets.getBytes(Path) #end)); + for (list in thing) + { if (haxe.io.Path.extension(list.fileName) == "json") { jsonMap.set(list.fileName,haxe.Json.parse(StringTools.replace(list.data.toString(), String.fromCharCode(0xFEFF), ""))); @@ -66,7 +66,7 @@ class FlxAnimateFrames extends FlxAtlasFrames var name = list.fileName.split("/"); imagemap.set(name[name.length - 1], list.data); } - } + } // Assuming the json has the same stuff as the image stuff for (curJson in jsonMap) { @@ -75,7 +75,7 @@ class FlxAnimateFrames extends FlxAtlasFrames { for (sprites in curJson.ATLAS.SPRITES) { - frames.pushFrame(textureAtlasHelper(curImage, sprites.SPRITE, curJson.meta)); + frames.pushFrame(textureAtlasHelper(FlxG.bitmap.add(curImage), sprites.SPRITE, curJson.meta)); } } else @@ -85,63 +85,84 @@ class FlxAnimateFrames extends FlxAtlasFrames } else { - if (Assets.exists('$Path/spritemap.json') || FileSystem.exists('$Path/spritemap.json')) + #if sys + var texts = sys.FileSystem.readDirectory(Path).filter((text) -> text.startsWith('spritemap') && text.toLowerCase().endsWith('.json')); + for(i in 0...texts.length) texts[i] = '$Path/' + texts[i]; + #else + var texts = Assets.list(TEXT).filter((text) -> StringTools.startsWith(text, '$Path/spritemap')); + #end + if (texts.length > 1) { - var isAssets = Assets.exists('$Path/spritemap.json'); - var curJson:AnimateAtlas = haxe.Json.parse(StringTools.replace((isAssets ? Assets.getText('$Path/spritemap.json') : File.getContent('$Path/spritemap.json')), String.fromCharCode(0xFEFF), "")); - var curSpritemap = isAssets ? Assets.getBitmapData('$Path/${curJson.meta.image}') : BitmapData.fromFile('$Path/${curJson.meta.image}'); - if (curSpritemap != null) + texts.sort(function (a, b) { - var graphic = FlxG.bitmap.add(curSpritemap); - var spritemapFrames = FlxAtlasFrames.findFrame(graphic); - if (spritemapFrames == null) - { - spritemapFrames = new FlxAnimateFrames(); - for (curSprite in curJson.ATLAS.SPRITES) - { - spritemapFrames.pushFrame(textureAtlasHelper(graphic.bitmap,curSprite.SPRITE, curJson.meta)); - } - } - graphic.addFrameCollection(spritemapFrames); - frames.concatFrames(spritemapFrames); - } - else - FlxG.log.error('the image called "${curJson.meta.image}" does not exist in Path $Path, maybe you changed the image Path somewhere else?'); - } - var i = 1; + var an = Std.parseInt(haxe.io.Path.withoutDirectory(a).charAt(9)); + var bn = Std.parseInt(haxe.io.Path.withoutDirectory(b).charAt(9)); + if (Math.isNaN(an) || Math.isNaN(bn)) + return 0; - while (Assets.exists('$Path/spritemap$i.json') || FileSystem.exists('$Path/spritemap$i.json')) + return an - bn; + }); + } + var spritemaps:Array<{image:BitmapData, json:AnimateAtlas}> = []; + for (text in texts) + { + #if sys + var txt = sys.io.File.getContent(text); + #else + var txt = Assets.getText(text); + #end + if (txt.charCodeAt(0) == 0xFEFF) + txt = txt.substring(1); + var json:AnimateAtlas = haxe.Json.parse(txt); + + #if sys + spritemaps.push({image: BitmapData.fromFile('$Path/${json.meta.image}'), json: json}); + #else + spritemaps.push({image: Assets.getBitmapData('$Path/${json.meta.image}'), json: json}); + #end + } + + for (spritemap in spritemaps) { - var isAssets = Assets.exists('$Path/spritemap$i.json'); - var curJson:AnimateAtlas = haxe.Json.parse(StringTools.replace((isAssets ? Assets.getText('$Path/spritemap$i.json') : File.getContent('$Path/spritemap$i.json')), String.fromCharCode(0xFEFF), "")); - trace("JSON FOR PATH " + Path + " IS: \n" + curJson); - var curSpritemap = (isAssets ? Assets.getBitmapData('$Path/${curJson.meta.image}') : BitmapData.fromFile('$Path/${curJson.meta.image}')); - if (curSpritemap != null) + if (spritemap.image == null) + { + FlxG.log.error('the image called "${spritemap.json.meta.image}" does not exist in Path $Path, maybe you changed the image Path somewhere else?'); + continue; + } + + var graphic = FlxG.bitmap.add(spritemap.image); + var spritemapFrames = FlxAtlasFrames.findFrame(graphic); + if (spritemapFrames == null) { - var graphic = FlxG.bitmap.add(curSpritemap); - var spritemapFrames = FlxAtlasFrames.findFrame(graphic); - if (spritemapFrames == null) + spritemapFrames = new FlxAnimateFrames(); + for (curSprite in spritemap.json.ATLAS.SPRITES) { - spritemapFrames = new FlxAnimateFrames(); - for (curSprite in curJson.ATLAS.SPRITES) - { - spritemapFrames.pushFrame(textureAtlasHelper(graphic.bitmap,curSprite.SPRITE, curJson.meta)); - } + spritemapFrames.pushFrame(textureAtlasHelper(graphic, curSprite.SPRITE, spritemap.json.meta)); } - graphic.addFrameCollection(spritemapFrames); - frames.concatFrames(spritemapFrames); } - else - FlxG.log.error('the image called "${curJson.meta.image}" does not exist in Path $Path, maybe you changed the image Path somewhere else?'); - i++; + graphic.addFrameCollection(spritemapFrames); + frames.animateConcat(spritemapFrames); + } + + if (frames.frames == []) + { + FlxG.log.error("the Frames parsing couldn't parse any of the frames, it's completely empty! \n Maybe you misspelled the Path?"); + return null; } } - if (frames.frames == []) + return frames; + } + + public function animateConcat(frames:FlxFramesCollection) + { + if (parents.indexOf(frames.parent) == -1) + parents.push(frames.parent); + for (frame in frames.frames) { - FlxG.log.error("the Frames parsing couldn't parse any of the frames, it's completely empty! \n Maybe you misspelled the Path?"); - return null; + this.frames.push(frame); + framesHash.set(frame.name, frame); } - return frames; + return this; } public function concatFrames(frames:FlxFramesCollection) @@ -154,6 +175,37 @@ class FlxAnimateFrames extends FlxAtlasFrames framesHash.set(frame.name, frame); } } + + /** + * + * @param Data the Json/XML file content/string + * @param Image the image which the file is referencing **WARNING:** if you set the path as a json, it's obligatory to set the image! + * @return A new instance of `FlxAtlasFrames` + */ + public static function fromAnimateAtlas(Data:AnimateAtlas, Image:FlxGraphicAsset):FlxAnimateFrames + { + var frames:FlxAnimateFrames = new FlxAnimateFrames(); + var graphic = FlxG.bitmap.add(Image); + var spritemapFrames = FlxAtlasFrames.findFrame(graphic); + if (spritemapFrames == null) + { + spritemapFrames = new FlxAnimateFrames(); + for (curSprite in Data.ATLAS.SPRITES) + { + spritemapFrames.pushFrame(textureAtlasHelper(graphic, curSprite.SPRITE, Data.meta)); + } + } + graphic.addFrameCollection(spritemapFrames); + frames.animateConcat(spritemapFrames); + + if (frames.frames == []) + { + trace("the Frames parsing couldn't parse any of the frames, it's completely empty! \n Maybe you misspelled the Path?"); + return null; + } + return frames; + } + /** * Sparrow spritesheet format parser with support of both of the versions and making the image completely optional to you. * @param Path The direction of the Xml you want to parse. @@ -479,24 +531,24 @@ class FlxAnimateFrames extends FlxAtlasFrames Frames.addAtlasFrame(frameRect, sourceSize, offset, name, angle); } - static function textureAtlasHelper(SpriteMap:BitmapData, limb:AnimateSpriteData, curMeta:Meta) + static function textureAtlasHelper(SpriteMap:FlxGraphic, limb:AnimateSpriteData, curMeta:Meta) { + var width = (limb.rotated) ? limb.h : limb.w; var height = (limb.rotated) ? limb.w : limb.h; - var sprite = new BitmapData(width, height, true, 0); - var matrix = new FlxMatrix(1,0,0,1,-limb.x,-limb.y); - if (limb.rotated) - { - matrix.rotateByNegative90(); - matrix.translate(0, height); - } - sprite.draw(SpriteMap, matrix); - + @:privateAccess - var curFrame = new FlxFrame(FlxG.bitmap.add(sprite)); + var curFrame = new FlxFrame(SpriteMap); + curFrame.name = limb.name; curFrame.sourceSize.set(width, height); - curFrame.frame = new FlxRect(0,0, width, height); + curFrame.frame = new FlxRect(limb.x, limb.y, limb.w, limb.h); + + if (limb.rotated) + { + curFrame.angle = ANGLE_NEG_90; + } + return curFrame; } diff --git a/source/luafiles/FlxAnimateFunctions.hx b/source/luafiles/FlxAnimateFunctions.hx index 7c7a5b3..63164ba 100644 --- a/source/luafiles/FlxAnimateFunctions.hx +++ b/source/luafiles/FlxAnimateFunctions.hx @@ -5,12 +5,12 @@ import openfl.utils.Assets; #if (LUA_ALLOWED && flxanimate) class FlxAnimateFunctions { - public static function implement(funk:FunkinLua) + public static function implement(funk:ModchartState) { var lua:State = funk.lua; - Lua_helper.add_callback(lua, "makeFlxAnimateSprite", function(tag:String, ?x:Float = 0, ?y:Float = 0, ?loadFolder:String = null) { + Lua_helper.add_callback(lua, "makeFlxAnimateSprite", function(tag:String, ?loadFolder:String = null, ?x:Float = 0, ?y:Float = 0) { tag = tag.replace('.', ''); - var lastSprite = PlayState.instance.variables.get(tag); + var lastSprite = PlayState.instance.modchartSprites.get(tag); if(lastSprite != null) { lastSprite.kill(); @@ -20,18 +20,18 @@ class FlxAnimateFunctions var mySprite:ModchartAnimateSprite = new ModchartAnimateSprite(x, y); if(loadFolder != null) Paths.loadAnimateAtlas(mySprite, loadFolder); - PlayState.instance.variables.set(tag, mySprite); + PlayState.instance.modchartSprites.set(tag, mySprite); mySprite.active = true; }); Lua_helper.add_callback(lua, "loadAnimateAtlas", function(tag:String, folderOrImg:Dynamic, ?spriteJson:Dynamic = null, ?animationJson:Dynamic = null) { - var spr:FlxAnimate = PlayState.instance.variables.get(tag); + var spr:FlxAnimate = PlayState.instance.modchartSprites.get(tag); if(spr != null) Paths.loadAnimateAtlas(spr, folderOrImg, spriteJson, animationJson); }); Lua_helper.add_callback(lua, "addAnimationBySymbol", function(tag:String, name:String, symbol:String, ?framerate:Float = 24, ?loop:Bool = false, ?matX:Float = 0, ?matY:Float = 0) { - var obj:Dynamic = PlayState.instance.variables.get(tag); + var obj:Dynamic = PlayState.instance.modchartSprites.get(tag); if(cast (obj, FlxAnimate) == null) return false; obj.anim.addBySymbol(name, symbol, framerate, loop, matX, matY); @@ -45,7 +45,7 @@ class FlxAnimateFunctions Lua_helper.add_callback(lua, "addAnimationBySymbolIndices", function(tag:String, name:String, symbol:String, ?indices:Any = null, ?framerate:Float = 24, ?loop:Bool = false, ?matX:Float = 0, ?matY:Float = 0) { - var obj:Dynamic = PlayState.instance.variables.get(tag); + var obj:Dynamic = PlayState.instance.modchartSprites.get(tag); if(cast (obj, FlxAnimate) == null) return false; if(indices == null) diff --git a/source/luafiles/ModchartState.hx b/source/luafiles/ModchartState.hx index bb1812f..d4c4c40 100644 --- a/source/luafiles/ModchartState.hx +++ b/source/luafiles/ModchartState.hx @@ -14,6 +14,7 @@ import openfl.display.BitmapData; import lime.app.Application; import flixel.FlxBasic; import flixel.FlxObject; +import flixel.addons.transition.FlxTransitionableState; import flixel.math.FlxPoint; import flixel.effects.FlxFlicker; import flixel.addons.effects.FlxTrail; @@ -55,6 +56,15 @@ import openfl.display.ShaderParameterType; import objects.*; import states.editors.ModpackMaker; +//bruh. +import states.StoryMenuState; +import states.GuestBETADCIUState; +import states.BETADCIUState; +import states.BonusSongsState; +import states.NeonightState; +import states.VitorState; +import states.FreeplayState; + import backend.Song; import backend.Highscore; @@ -69,6 +79,8 @@ import luafiles.ModchartText; import luafiles.ModchartText.*; import luafiles.CustomSubstate; +import substates.PauseSubState; + using StringTools; class ModchartState @@ -696,6 +708,7 @@ class ModchartState if (FlxG.save.data.uncacheCharacterSwitch && !dontDestroy) Paths.clearStoredMemory2(bfPath); + PlayState.instance.setOnScripts('boyfriendName', PlayState.instance.boyfriend.curCharacter); PlayState.instance.startCharacterLua(PlayState.instance.boyfriend.curCharacter); } @@ -774,6 +787,7 @@ class ModchartState if (FlxG.save.data.uncacheCharacterSwitch && !dontDestroy && daCurChar != PlayState.instance.dad.curCharacter) Paths.clearStoredMemory2(dadPath); + PlayState.instance.setOnScripts('dadName', PlayState.instance.dad.curCharacter); PlayState.instance.startCharacterLua(PlayState.instance.dad.curCharacter); } @@ -810,6 +824,7 @@ class ModchartState if (FlxG.save.data.uncacheCharacterSwitch && !dontDestroy) Paths.clearStoredMemory2(gfPath); + PlayState.instance.setOnScripts('gfName', PlayState.instance.gf.curCharacter); PlayState.instance.startCharacterLua(PlayState.instance.gf.curCharacter); } @@ -965,6 +980,8 @@ class ModchartState set('seenCutscene', PlayState.seenCutscene); set('scriptName', scriptName); + set('shadersEnabled', ClientPrefs.data.shaders); + if (PlayState.SONG != null) { set("bpm", PlayState.SONG.bpm); @@ -1398,7 +1415,7 @@ class ModchartState if(luaInstance.scriptName == cervix) { if(traceMsg) - luaTrace('The script "' + cervix + '" is already running!'); + luaTrace('The lua script "' + cervix + '" is already running!'); return; } @@ -1409,6 +1426,42 @@ class ModchartState } luaTrace("addLuaScript: Script doesn't exist!", false, false, FlxColor.RED); }); + + Lua_helper.add_callback(lua, "addHScript", function(luaFile:String, ?ignoreAlreadyRunning:Bool = false, ?traceMsg:Bool = true) { //I wonder if this will cause a crash -- future me here. okay it didn't. + var cervix = luaFile + ".hx"; + var scriptFound = false; + if(FileSystem.exists(FileSystem.absolutePath("assets/shared/"+cervix))) { + cervix = FileSystem.absolutePath("assets/shared/"+cervix); + scriptFound = true; + } + else if (FileSystem.exists(Paths.modFolders(cervix))) + { + cervix = Paths.modFolders(cervix); + scriptFound = true; + } + else { + cervix = Paths.getPreloadPath(cervix); + if(FileSystem.exists(cervix)) { + scriptFound = true; + } + } + + if(scriptFound) + { + if(!ignoreAlreadyRunning) + for (script in PlayState.instance.hscriptArray) + if(script.origin == cervix) + { + if(traceMsg) luaTrace('The hscript script "' + cervix + '" is already running!'); + return; + } + + PlayState.instance.initHScript(cervix); + return; + } + luaTrace("addHScript: Script doesn't exist!", false, false, FlxColor.RED); + }); + Lua_helper.add_callback(lua, "removeLuaScript", function(luaFile:String, ?ignoreAlreadyRunning:Bool = false) { //would be dope asf. var cervix = luaFile + ".lua"; var doPush = false; @@ -1458,6 +1511,42 @@ class ModchartState } luaTrace("removeLuaScript: Script doesn't exist!", false, false, FlxColor.RED); }); + + Lua_helper.add_callback(lua, "removeHScript", function(luaFile:String, ?ignoreAlreadyRunning:Bool = false) { //would be dope asf. + var cervix = luaFile + ".hx"; + var scriptFound = false; + if(FileSystem.exists(FileSystem.absolutePath("assets/shared/"+cervix))) { + cervix = FileSystem.absolutePath("assets/shared/"+cervix); + scriptFound = true; + } + else if (FileSystem.exists(Paths.modFolders(cervix))) + { + cervix = Paths.modFolders(cervix); + scriptFound = true; + } + else { + cervix = Paths.getPreloadPath(cervix); + if(FileSystem.exists(cervix)) { + scriptFound = true; + } + } + + if(scriptFound) + { + if(!ignoreAlreadyRunning) + { + for (script in PlayState.instance.hscriptArray) + if(script.origin == cervix) + { + //trace('Closing script ' + (script.origin != null ? script.origin : luaFile)); + script.destroy(); + return; + } + } + return; + } + luaTrace("removeHScript: Script doesn't exist!", false, false, FlxColor.RED); + }); //because the regular close function isn't working for me Lua_helper.add_callback(lua, "closeLuaScript", function(luaFile:String, ?ignoreAlreadyRunning:Bool = false) { //would be dope asf. @@ -1846,6 +1935,18 @@ class ModchartState PlayState.instance.healthBar.createFilledBar(left_color, right_color); PlayState.instance.healthBar.updateBar(); }); + + Lua_helper.add_callback(lua, "setTimeBarColors", function(left:String, right:String) { + var left_color:Null = null; + var right_color:Null = null; + if (left != null && left != '') + left_color = CoolUtil.colorFromString(left); + if (right != null && right != '') + right_color = CoolUtil.colorFromString(right); + + PlayState.instance.timeBar.createFilledBar(left_color, right_color); + PlayState.instance.timeBar.updateBar(); + }); Lua_helper.add_callback(lua,"getDominantColor", function(sprite:String){ var shit:Dynamic = LuaUtils.getObjectDirectly(sprite); @@ -1994,6 +2095,24 @@ class ModchartState } } }); + + Lua_helper.add_callback(lua, "getSoundPitch", function(tag:String) { + if(tag != null && tag.length > 0 && PlayState.instance.modchartSounds.exists(tag)) { + return PlayState.instance.modchartSounds.get(tag).pitch; + } + return 0; + }); + Lua_helper.add_callback(lua, "setSoundPitch", function(tag:String, value:Float, doPause:Bool = false) { + if(tag != null && tag.length > 0 && PlayState.instance.modchartSounds.exists(tag)) { + var theSound:FlxSound = PlayState.instance.modchartSounds.get(tag); + if(theSound != null) { + var wasResumed:Bool = theSound.playing; + if (doPause) theSound.pause(); + theSound.pitch = value; + if (doPause && wasResumed) theSound.play(); + } + } + }); Lua_helper.add_callback(lua, "close", function(printMessage:Bool = false) { closed = true; @@ -2204,6 +2323,15 @@ class ModchartState c.setRGB(r, g, b); LuaUtils.cameraFromString(camera).fade(c, d, f); }); + + Lua_helper.add_callback(lua, "cameraSetTarget", function(target:String) { + var isDad:Bool = false; + if(target == 'dad') { + isDad = true; + } + PlayState.instance.moveCamera(isDad); + return isDad; + }); Lua_helper.add_callback(lua, "cameraShake", function(camera:String, intensity:Float, duration:Float) { if (PlayState.instance != null){duration = duration / PlayState.instance.playbackRate;} @@ -2515,6 +2643,26 @@ class ModchartState default: shit.screenCenter(XY); } }); + + Lua_helper.add_callback(lua, "objectsOverlap", function(obj1:String, obj2:String) { + var namesArray:Array = [obj1, obj2]; + var objectsArray:Array = []; + for (i in 0...namesArray.length) + { + var real = PlayState.instance.getLuaObject(namesArray[i]); + if(real!=null) { + objectsArray.push(real); + } else { + objectsArray.push(Reflect.getProperty(LuaUtils.getTargetInstance(), namesArray[i])); + } + } + + if(!objectsArray.contains(null) && FlxG.overlap(objectsArray[0], objectsArray[1])) + { + return true; + } + return false; + }); Lua_helper.add_callback(lua,"playActorAnimation", function(obj:String,anim:String,force:Bool = false,reverse:Bool = false, ?frame:Int = 0) { var char:Character = LuaUtils.getObjectDirectly(obj); @@ -2831,11 +2979,108 @@ class ModchartState return true; #end }); - + + Lua_helper.add_callback(lua, "makeVideoSprite", function(tag:String, videoFile:String, ?x:Float, ?y:Float, ?camera:String, ?shouldLoop:Bool, ?muted:Bool) { + // I hate you FlxVideoSprite.... + #if VIDEOS_ALLOWED + tag = tag.replace('.', ''); + LuaUtils.resetSpriteTag(tag); + var leVSprite:PsychVideoSprite = null; + if(FileSystem.exists(Paths.video(videoFile)) && videoFile != null && videoFile.length > 0) { + + leVSprite = new PsychVideoSprite(); + leVSprite.addCallback('onFormat',()->{ + leVSprite.setPosition(x,y); + leVSprite.cameras = [LuaUtils.cameraFromString(camera)]; + }); + leVSprite.addCallback('onEnd',()->{ + if (Stage.instance.swagBacks.exists(tag)) { + Stage.instance.swagBacks.get(tag).destroy(); + Stage.instance.swagBacks.remove(tag); + } + + if (PlayState.instance.modchartSprites.exists(tag)) { + PlayState.instance.modchartSprites.get(tag).destroy(); + PlayState.instance.modchartSprites.remove(tag); + } + + PlayState.instance.callOnLuas('onVideoFinished', [tag]); + }); + var options:Array = []; + if (shouldLoop) options.push(PsychVideoSprite.looping); + if (muted) options.push(PsychVideoSprite.muted); + + leVSprite.load(Paths.video(videoFile), options); + leVSprite.antialiasing = true; + leVSprite.play(); + + if (isStageLua && !preloading){ + Stage.instance.swagBacks.set(tag, leVSprite); + } + else{ + PlayState.instance.modchartSprites.set(tag, leVSprite); + } + + } else { + luaTrace('makeVideoSprite: The video file "' + videoFile + '" cannot be found!', FlxColor.RED); + return; + } + leVSprite.active = true; + #else + luaTrace('Nuh Uh!!... - Platform not supported!'); + #end + }); + Lua_helper.add_callback(lua, "endSong", function(hmm:String) { PlayState.instance.KillNotes(); PlayState.instance.endSong(); }); + + Lua_helper.add_callback(lua, "restartSong", function(?skipTransition:Bool = false,?cutscene:Bool = false,?preloadAgain:Bool = false) { + PlayState.instance.persistentUpdate = false; + FlxG.camera.followLerp = 0; + if(skipTransition == true) PauseSubState.restartSong(false,cutscene,preloadAgain); + else PauseSubState.restartSong(skipTransition,cutscene,preloadAgain); + return true; + }); + + Lua_helper.add_callback(lua, "exitSong", function(?skipTransition:Bool = false) { + if(skipTransition) + { + FlxTransitionableState.skipNextTransIn = true; + FlxTransitionableState.skipNextTransOut = true; + } + + if(PlayState.isStoryMode) MusicBeatState.switchState(new StoryMenuState()); + + if (PlayState.isBETADCIU){ + if (CoolUtil.difficulties[0] == "Guest") + MusicBeatState.switchState(new states.GuestBETADCIUState()); + else + MusicBeatState.switchState(new states.BETADCIUState()); + }else{ + if (PlayState.isBonus) + MusicBeatState.switchState(new states.BonusSongsState()); + else if (PlayState.isNeonight) + MusicBeatState.switchState(new states.NeonightState()); + else if (PlayState.isVitor) + MusicBeatState.switchState(new states.VitorState()); + else + MusicBeatState.switchState(new states.FreeplayState()); + } + + #if DISCORD_ALLOWED DiscordClient.resetClientID(); #end + + PlayState.changedDifficulty = false; + PlayState.chartingMode = false; + PlayState.instance.transitioning = true; + FlxG.camera.followLerp = 0; + + FlxTransitionableState.skipNextTransIn = false;//visual bug fix + FlxTransitionableState.skipNextTransOut = false;//visual bug fix + + return true; + }); //idk if I wanna add events. alright I added the ones that are usable without that much tinkering. Lua_helper.add_callback(lua, "triggerEvent", function(name:String, arg1:Dynamic, arg2:Dynamic, ?arg3:Dynamic = "") { @@ -3588,6 +3833,7 @@ class ModchartState #if desktop DiscordClient.addLuaCallbacks(lua); #end #if hscript HScript.implement(this); #end + #if flxanimate FlxAnimateFunctions.implement(this); #end ReflectionFunctions.implement(this); TweenFunctions.implement(this); TextFunctions.implement(this); diff --git a/source/objects/PsychVideoSprite.hx b/source/objects/PsychVideoSprite.hx index ec65723..1371b08 100644 --- a/source/objects/PsychVideoSprite.hx +++ b/source/objects/PsychVideoSprite.hx @@ -1,10 +1,11 @@ package objects; +import hxvlc.flixel.FlxVideoSprite as VideoSprite; //Borrowed from Sonic Legacy for Free 4 Pirates //i wanted a few things -data //also srs moment fuck hxcodec its given me so many headaches. you was good in the past but we moved on bud! -class PsychVideoSprite extends FlxVideoSprite +class PsychVideoSprite extends VideoSprite { public static var heldVideos:Array = []; diff --git a/source/states/PlayState.hx b/source/states/PlayState.hx index 64575ce..61d0d18 100644 --- a/source/states/PlayState.hx +++ b/source/states/PlayState.hx @@ -129,6 +129,7 @@ using StringTools; #elseif (hxCodec >= "2.6.1") import hxcodec.VideoHandler as VideoHandler; #elseif (hxCodec == "2.6.0") import VideoHandler; #else import vlc.MP4Handler as VideoHandler; #end +import objects.PsychVideoSprite; #end class PlayState extends MusicBeatState @@ -203,6 +204,7 @@ class PlayState extends MusicBeatState #end public var vocals:FlxSound; + public var opponentVocals:FlxSound; public var inst:FlxSound; public var dad:Character; @@ -1110,8 +1112,8 @@ class PlayState extends MusicBeatState playerSingAnimations = singAnimations; - setOnLuas("mustHitSection", PlayState.SONG.notes[curSection].mustHitSection); //just so we can check the first section - setOnLuas('gfSection', SONG.notes[curSection].gfSection); //forgot to check this one too. + setOnScripts("mustHitSection", PlayState.SONG.notes[curSection].mustHitSection); //just so we can check the first section + setOnScripts('gfSection', SONG.notes[curSection].gfSection); //forgot to check this one too. callOnScripts('start', []); callOnScripts('onCreate', []); //psych @@ -1296,6 +1298,7 @@ class PlayState extends MusicBeatState paused = true; vocals.stop(); + opponentVocals.stop(); FlxG.sound.music.stop(); var daX = boyfriend.getScreenPosition().x; @@ -1367,14 +1370,14 @@ class PlayState extends MusicBeatState if (SONG.notes[curSection].changeBPM) { Conductor.changeBPM(SONG.notes[curSection].bpm); - setOnLuas('curBpm', Conductor.bpm); - setOnLuas('crochet', Conductor.crochet); - setOnLuas('stepCrochet', Conductor.stepCrochet); + setOnScripts('curBpm', Conductor.bpm); + setOnScripts('crochet', Conductor.crochet); + setOnScripts('stepCrochet', Conductor.stepCrochet); } - setOnLuas("mustHitSection", SONG.notes[curSection].mustHitSection); + setOnScripts("mustHitSection", SONG.notes[curSection].mustHitSection); //setOnLuas('altAnim', SONG.notes[curSection].altAnim); - setOnLuas('gfSection', SONG.notes[curSection].gfSection); + setOnScripts('gfSection', SONG.notes[curSection].gfSection); } setOnScripts('curSection', curSection); @@ -2440,6 +2443,7 @@ class PlayState extends MusicBeatState FlxG.sound.music.pause(); vocals.pause(); + opponentVocals.pause(); FlxG.sound.music.time = time; FlxG.sound.music.play(); @@ -2449,9 +2453,13 @@ class PlayState extends MusicBeatState if (Conductor.songPosition <= vocals.length) { vocals.time = time; + opponentVocals.time = time; + FlxG.sound.music.pitch = playbackRate; + opponentVocals.pitch = playbackRate; } vocals.play(); + opponentVocals.play(); songTime = time; } @@ -2484,21 +2492,21 @@ class PlayState extends MusicBeatState generateStaticArrows(1, boyfriend.noteSkin, !skipArrowStartTween, daStartAlpha); for (i in 0...playerStrums.length) { - setOnLuas('defaultPlayerStrumX' + i, playerStrums.members[i].x); - setOnLuas('defaultPlayerStrumY' + i, playerStrums.members[i].y); + setOnScripts('defaultPlayerStrumX' + i, playerStrums.members[i].x); + setOnScripts('defaultPlayerStrumY' + i, playerStrums.members[i].y); } for (i in 0...opponentStrums.length) { - setOnLuas('defaultOpponentStrumX' + i, opponentStrums.members[i].x); - setOnLuas('defaultOpponentStrumY' + i, opponentStrums.members[i].y); + setOnScripts('defaultOpponentStrumX' + i, opponentStrums.members[i].x); + setOnScripts('defaultOpponentStrumY' + i, opponentStrums.members[i].y); } //kade engine - for (i in 0...strumLineNotes.length){ + for (i in 0...strumLineNotes.length){//I wonder if someone still uses this... var member = PlayState.instance.strumLineNotes.members[i]; - setOnLuas("defaultStrum" + i + "X", Math.floor(member.x)); - setOnLuas("defaultStrum" + i + "Y", Math.floor(member.y)); - setOnLuas("defaultStrum" + i + "Angle", Math.floor(member.angle)); - setOnLuas("defaultStrum" + i + "Alpha", Math.floor(member.alpha)); + setOnScripts("defaultStrum" + i + "X", Math.floor(member.x)); + setOnScripts("defaultStrum" + i + "Y", Math.floor(member.y)); + setOnScripts("defaultStrum" + i + "Angle", Math.floor(member.angle)); + setOnScripts("defaultStrum" + i + "Alpha", Math.floor(member.alpha)); } callOnScripts('onStartCountdown', null, true); @@ -2744,6 +2752,7 @@ class PlayState extends MusicBeatState FlxG.sound.music.pitch = playbackRate; FlxG.sound.music.onComplete = songOutro; vocals.play(); + opponentVocals.play(); if (ClientPrefs.data.psychUI) { @@ -2769,6 +2778,7 @@ class PlayState extends MusicBeatState //trace('Oopsie doopsie! Paused sound'); FlxG.sound.music.pause(); vocals.pause(); + opponentVocals.pause(); } // Song duration in a float, useful for the time left feature @@ -2838,7 +2848,7 @@ class PlayState extends MusicBeatState curSong = songData.song; - if (SONG.needsVoices) + /*if (SONG.needsVoices) //If the new system glitches out for some reason I'll just re-enable this { if (!Assets.exists(Paths.voices(PlayState.SONG.song))) { @@ -2851,13 +2861,54 @@ class PlayState extends MusicBeatState vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.voices(PlayState.SONG.song)); } else - vocals = new FlxSound(); + vocals = new FlxSound();*/ + + vocals = new FlxSound(); + opponentVocals = new FlxSound(); + try + { + if (SONG.needsVoices)//WHY THERES SO MANY VOICES FUNCTIONS + { + var playerVocals = Paths.voices(songData.song, (boyfriend.vocalsFile == null || boyfriend.vocalsFile.length < 1) ? 'Player' : boyfriend.vocalsFile); + if (!Assets.exists(playerVocals)) playerVocals = null; + + var playerVocals2 = Paths.voices2(songData.song, (boyfriend.vocalsFile == null || boyfriend.vocalsFile.length < 1) ? 'Player' : boyfriend.vocalsFile); + if (!FileSystem.exists(playerVocals2)) playerVocals2 = null; + + if (!Assets.exists(playerVocals)) + if (FileSystem.exists(playerVocals2)) vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.currentTrackedSounds.exists(playerVocals2) ? Paths.currentTrackedSounds.get(playerVocals2) : Sound.fromFile(playerVocals2)); + else if (!FileSystem.exists(playerVocals2)) + if (Assets.exists(playerVocals)) vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(playerVocals); + + if(playerVocals == null && playerVocals2 == null){ //don't talk to me. + if (!Assets.exists(Paths.voices(PlayState.SONG.song))){ + if (Paths.currentTrackedSounds.exists(Paths.voices2(PlayState.SONG.song))) + vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.currentTrackedSounds.get(Paths.voices2(PlayState.SONG.song))); + else + vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Sound.fromFile(Paths.voices2(PlayState.SONG.song))); + }else + vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.voices(PlayState.SONG.song)); + } + + var oppVocals = Paths.voices(songData.song, (dad.vocalsFile == null || dad.vocalsFile.length < 1) ? 'Opponent' : dad.vocalsFile); + var oppVocals2 = Paths.voices2(songData.song, (dad.vocalsFile == null || dad.vocalsFile.length < 1) ? 'Opponent' : dad.vocalsFile); + + if (!Assets.exists(oppVocals)) + if (FileSystem.exists(oppVocals2)) opponentVocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.currentTrackedSounds.exists(oppVocals2) ? Paths.currentTrackedSounds.get(oppVocals2) : Sound.fromFile(oppVocals2)); + else + if (Assets.exists(oppVocals)) opponentVocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(oppVocals); + } + } + catch(e:Dynamic) {} + trace('loaded vocals'); - vocals.looped = false; - vocals.pitch = playbackRate; - FlxG.sound.list.add(vocals); + vocals.looped = false; + vocals.pitch = playbackRate; + opponentVocals.pitch = playbackRate; + FlxG.sound.list.add(vocals); + FlxG.sound.list.add(opponentVocals); notes = new FlxTypedGroup(); add(notes); @@ -3115,6 +3166,7 @@ class PlayState extends MusicBeatState { FlxG.sound.music.pause(); vocals.pause(); + opponentVocals.pause(); } #if desktop @@ -3166,6 +3218,10 @@ class PlayState extends MusicBeatState for (timer in modchartTimers) { timer.active = true; } + + #if VIDEOS_ALLOWED + PsychVideoSprite.globalResume(); + #end callOnScripts('onResume'); } @@ -3177,6 +3233,7 @@ class PlayState extends MusicBeatState public function resyncVocals():Void { vocals.pause(); + opponentVocals.pause(); FlxG.sound.music.play(); FlxG.sound.music.pitch = playbackRate; @@ -3186,10 +3243,17 @@ class PlayState extends MusicBeatState vocals.time = Conductor.songPosition; vocals.pitch = playbackRate; } + + if (Conductor.songPosition <= opponentVocals.length) + { + opponentVocals.time = Conductor.songPosition; + opponentVocals.pitch = playbackRate; + } vocals.play(); + opponentVocals.play(); #if desktop - DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | songMisses: " + songMisses , iconRPC); + DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAccuracy: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + songMisses , iconRPC); #end } @@ -3248,8 +3312,13 @@ class PlayState extends MusicBeatState if(FlxG.sound.music != null) { FlxG.sound.music.pause(); vocals.pause(); + opponentVocals.pause(); } + #if VIDEOS_ALLOWED + PsychVideoSprite.globalPause(); + #end + isPaused = true; openSubState(new substates.PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); //} @@ -3292,10 +3361,10 @@ class PlayState extends MusicBeatState #if desktop if (songStarted) { - setOnLuas('songPos',Conductor.songPosition); - setOnLuas('hudZoom', camHUD.zoom); - setOnLuas('cameraZoom',FlxG.camera.zoom); - callOnLuas('update', [elapsed]); + setOnScripts('songPos',Conductor.songPosition); + setOnScripts('hudZoom', camHUD.zoom); + setOnScripts('cameraZoom',FlxG.camera.zoom); + callOnScripts('update', [elapsed]); if (luaWiggles != []) { @@ -3750,6 +3819,8 @@ class PlayState extends MusicBeatState FlxG.sound.music.volume = 0; vocals.volume = 0; vocals.pause(); + opponentVocals.volume = 0; + opponentVocals.pause(); canPause = false; updateTime = false; endingSong = true; @@ -4472,9 +4543,10 @@ class PlayState extends MusicBeatState function updateAccuracy(?badHit:Bool = false) { - setOnLuas('score', songScore); - setOnLuas('misses', songMisses); - setOnLuas('hits', songHits); + setOnScripts('score', songScore); + setOnScripts('misses', songMisses); + setOnScripts('hits', songHits); + setOnScripts('combo', combo); var ret:Dynamic = callOnScripts('onRecalculateRating', null, true); @@ -4503,9 +4575,9 @@ class PlayState extends MusicBeatState callOnScripts('onUpdateScore', [badHit]); - setOnLuas('rating', ratingPercent); - setOnLuas('ratingName', ratingName); - setOnLuas('ratingFC', ratingFC); + setOnScripts('rating', ratingPercent); + setOnScripts('ratingName', ratingName); + setOnScripts('ratingFC', ratingFC); } function getKeyPresses(note:Note):Int @@ -4626,6 +4698,7 @@ class PlayState extends MusicBeatState time += 0.15; } + if(opponentVocals.length <= 0) vocals.volume = 1; StrumPlayAnim(true, Std.int(Math.abs(note.noteData)), time); note.hitByOpponent = true; @@ -4901,6 +4974,7 @@ class PlayState extends MusicBeatState usedTimeTravel = true; FlxG.sound.music.pause(); vocals.pause(); + opponentVocals.pause(); Conductor.songPosition = skipExactly; notes.forEachAlive(function(daNote:Note) { @@ -4922,6 +4996,8 @@ class PlayState extends MusicBeatState FlxG.sound.music.play(); vocals.time = Conductor.songPosition; vocals.play(); + opponentVocals.time = Conductor.songPosition; + opponentVocals.play(); new FlxTimer().start(0.5, function(tmr:FlxTimer) { usedTimeTravel = false; @@ -4935,6 +5011,7 @@ class PlayState extends MusicBeatState usedTimeTravel = true; FlxG.sound.music.pause(); vocals.pause(); + opponentVocals.pause(); Conductor.songPosition += 10000 * multiplier; notes.forEachAlive(function(daNote:Note) { @@ -4956,6 +5033,8 @@ class PlayState extends MusicBeatState FlxG.sound.music.play(); vocals.time = Conductor.songPosition; vocals.play(); + opponentVocals.time = Conductor.songPosition; + opponentVocals.play(); new FlxTimer().start(0.5, function(tmr:FlxTimer) { usedTimeTravel = false; @@ -5158,12 +5237,13 @@ class PlayState extends MusicBeatState if(generatedMusic) { if(vocals != null) vocals.pitch = value; + if(opponentVocals != null) opponentVocals.pitch = value; FlxG.sound.music.pitch = value; } playbackRate = value; FlxG.animationTimeScale = value; //Conductor.safeZoneOffset = (FlxG.save.data.safeFrames / 60) * 1000 * value; - setOnLuas('playbackRate', playbackRate); + setOnScripts('playbackRate', playbackRate); adjustCamFollow(); return value; @@ -5308,7 +5388,7 @@ class PlayState extends MusicBeatState notes.sort(FlxSort.byY, (FlxG.save.data.downscroll ? FlxSort.ASCENDING : FlxSort.DESCENDING)); } - setOnLuas('curBeat',curBeat); + setOnScripts('curBeat',curBeat); callOnScripts('beatHit', [curBeat]); callOnScripts('onBeatHit', [curBeat]); diff --git a/source/states/editors/ChartingState.hx b/source/states/editors/ChartingState.hx index 5484cf5..2a1d503 100644 --- a/source/states/editors/ChartingState.hx +++ b/source/states/editors/ChartingState.hx @@ -143,6 +143,7 @@ class ChartingState extends MusicBeatState var gridBlackLine:FlxSprite; var gridBlackLine2:FlxSprite; var vocals:FlxSound; + var opponentVocals:FlxSound = null; var leftIcon:HealthIcon; var rightIcon:HealthIcon; @@ -374,6 +375,9 @@ class ChartingState extends MusicBeatState add(nextRenderedSustains); add(nextRenderedNotes); + add(nextRenderedSustains); + add(nextRenderedNotes); + //loadEvents(); // it doesn't load the events unless I do this updateGrid(); @@ -538,6 +542,7 @@ class ChartingState extends MusicBeatState vol = 0; vocals.volume = vol; + if(opponentVocals != null) opponentVocals.volume = vol; } }; @@ -1287,7 +1292,7 @@ class ChartingState extends MusicBeatState eventPushedMap = null; #end - descText = new FlxText(20, 230, 0, eventStuff[0][0]); + descText = new FlxText(20, 210, 0, eventStuff[0][0]); var leEvents:Array = []; for (i in 0...eventStuff.length) { @@ -1429,13 +1434,41 @@ class ChartingState extends MusicBeatState else FlxG.sound.playMusic(Paths.inst(daSong), 0.6); - // WONT WORK FOR TUTORIAL OR TEST SONG!!! REDO LATER - if (FileSystem.exists(Paths.voices2(daSong))) - vocals = new FlxSound().loadEmbedded(Sound.fromFile(Paths.voices2(daSong))); - else - vocals = new FlxSound().loadEmbedded(Paths.voices(daSong)); + try + { + var playerVocals = Paths.voices(daSong, (characterData.vocalsP1 == null || characterData.vocalsP1.length < 1) ? 'Player' : characterData.vocalsP1); + if (!Assets.exists(playerVocals)) playerVocals = null; + + var playerVocals2 = Paths.voices2(daSong, (characterData.vocalsP1 == null || characterData.vocalsP1.length < 1) ? 'Player' : characterData.vocalsP1); + if (!FileSystem.exists(playerVocals2)) playerVocals2 = null; + + if (!Assets.exists(playerVocals)) + if (FileSystem.exists(playerVocals2)) vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.currentTrackedSounds.exists(playerVocals2) ? Paths.currentTrackedSounds.get(playerVocals2) : Sound.fromFile(playerVocals2)); + else if (!FileSystem.exists(playerVocals2)) + if (Assets.exists(playerVocals)) vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(playerVocals); + + if(playerVocals == null && playerVocals2 == null){ //don't talk to me. + if (!Assets.exists(Paths.voices(PlayState.SONG.song))){ + if (Paths.currentTrackedSounds.exists(Paths.voices2(PlayState.SONG.song))) + vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.currentTrackedSounds.get(Paths.voices2(PlayState.SONG.song))); + else + vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Sound.fromFile(Paths.voices2(PlayState.SONG.song))); + }else + vocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.voices(PlayState.SONG.song)); + } + var oppVocals = Paths.voices(daSong, (characterData.vocalsP2 == null || characterData.vocalsP2.length < 1) ? 'Opponent' : characterData.vocalsP2); + var oppVocals2 = Paths.voices2(daSong, (characterData.vocalsP2 == null || characterData.vocalsP2.length < 1) ? 'Opponent' : characterData.vocalsP2); + + if (!Assets.exists(oppVocals)) + if (FileSystem.exists(oppVocals2)) opponentVocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(Paths.currentTrackedSounds.exists(oppVocals2) ? Paths.currentTrackedSounds.get(oppVocals2) : Sound.fromFile(oppVocals2)); + else + if (Assets.exists(oppVocals)) opponentVocals = FlxG.sound.list.recycle(FlxSound).loadEmbedded(oppVocals); + } + catch(e:Dynamic) {} + FlxG.sound.list.add(vocals); + FlxG.sound.list.add(opponentVocals); pauseMusic(); @@ -1450,11 +1483,16 @@ class ChartingState extends MusicBeatState vocals.pause(); vocals.time = 0; } + if(opponentVocals != null) { + opponentVocals.pause(); + opponentVocals.time = 0; + } changeSection(); curSec = 0; updateGrid(); updateSectionUI(); vocals.play(); + if (opponentVocals != null)opponentVocals.play(); }; } @@ -1515,6 +1553,7 @@ class ChartingState extends MusicBeatState updateGrid(); case "song_vocalvol": vocals.volume = Math.max(nums.value, 0.1); + if (opponentVocals != null)opponentVocals.volume = Math.max(nums.value, 0.1); case "section_dtype": _song.notes[curSec].dType = Std.int(nums.value); updateGrid(); @@ -1671,6 +1710,8 @@ class ChartingState extends MusicBeatState Conductor.songPosition = FlxG.sound.music.time; else if (vocals != null) Conductor.songPosition = vocals.time; + else if (opponentVocals != null) + Conductor.songPosition = opponentVocals.time; else Conductor.songPosition = FlxG.sound.music.time; // it went back again? @@ -1747,6 +1788,7 @@ class ChartingState extends MusicBeatState FlxG.sound.music.pitch = playbackSpeed; vocals.pitch = playbackSpeed; + if (opponentVocals != null)opponentVocals.pitch = playbackSpeed; FlxG.watch.addQuick('daBeat', curBeat); @@ -1811,6 +1853,7 @@ class ChartingState extends MusicBeatState PlayState.SONG = _song; FlxG.sound.music.stop(); vocals.stop(); + if (opponentVocals != null) opponentVocals.stop(); if (FlxG.keys.pressed.SHIFT){ PlayState.startOnTime = Conductor.songPosition; @@ -1891,6 +1934,7 @@ class ChartingState extends MusicBeatState else { vocals.play(); + if (opponentVocals != null)opponentVocals.play(); FlxG.sound.music.play(); lilBf.animation.play("idle"); @@ -1911,6 +1955,7 @@ class ChartingState extends MusicBeatState pauseMusic(); FlxG.sound.music.time -= (FlxG.mouse.wheel * Conductor.stepCrochet * 0.4); vocals.time = FlxG.sound.music.time; + if (opponentVocals != null)opponentVocals.time = FlxG.sound.music.time; } if (!FlxG.keys.pressed.SHIFT) @@ -1933,6 +1978,7 @@ class ChartingState extends MusicBeatState FlxG.sound.music.time += daTime; vocals.time = FlxG.sound.music.time; + if (opponentVocals != null)opponentVocals.time = FlxG.sound.music.time; } } else @@ -1951,6 +1997,7 @@ class ChartingState extends MusicBeatState FlxG.sound.music.time += daTime; vocals.time = FlxG.sound.music.time; + if (opponentVocals != null)opponentVocals.time = FlxG.sound.music.time; } } } @@ -2141,6 +2188,7 @@ class ChartingState extends MusicBeatState } vocals.time = FlxG.sound.music.time; + if (opponentVocals != null)opponentVocals.time = FlxG.sound.music.time; updateCurStep(); updateGrid(); @@ -2166,6 +2214,7 @@ class ChartingState extends MusicBeatState FlxG.sound.music.time = sectionStartTime(); vocals.time = FlxG.sound.music.time; + if (opponentVocals != null)opponentVocals.time = FlxG.sound.music.time; updateCurStep(); } @@ -2199,6 +2248,48 @@ class ChartingState extends MusicBeatState updateHeads(); } + var characterData:Dynamic = { + vocalsP1: null, + vocalsP2: null + }; + + function updateJsonData():Void + { + for (i in 1...3) + { + var data:CharacterFile = loadCharacterFile(Reflect.field(_song, 'player$i')); + Reflect.setField(characterData, 'vocalsP$i', data.vocals_file != null ? data.vocals_file : ''); + } + } + + var characterFailed:Bool = false; + function loadCharacterFile(char:String):CharacterFile { + characterFailed = false; + var characterPath:String = 'characters/' + char + '.json'; + #if MODS_ALLOWED + var path:String = Paths.modFolders(characterPath); + if (!FileSystem.exists(path)) { + path = Paths.getSharedPath(characterPath); + } + + if (!FileSystem.exists(path)) + #else + var path:String = Paths.getSharedPath(characterPath); + if (!OpenFlAssets.exists(path)) + #end + { + path = Paths.getSharedPath('characters/' + Character.DEFAULT_CHARACTER + '.json'); //If a character couldn't be found, change him to BF just to prevent a crash + characterFailed = true; + } + + #if MODS_ALLOWED + var rawJson = File.getContent(path); + #else + var rawJson = OpenFlAssets.getText(path); + #end + return cast Json.parse(rawJson); + } + function updateHeads():Void { var healthIconP1:String = loadHealthIconFromCharacter(_song.player1); @@ -3328,8 +3419,6 @@ class ChartingState extends MusicBeatState } } } - - #else noteStyleList = CoolUtil.coolTextFile(Paths.txt('noteStyleList')); #end @@ -3343,6 +3432,9 @@ class ChartingState extends MusicBeatState if (vocals != null){ vocals.pause(); } + if (opponentVocals != null){ + opponentVocals.pause(); + } lilBf.animation.play("idle"); lilOpp.animation.play("idle"); diff --git a/source/substates/PauseSubState.hx b/source/substates/PauseSubState.hx index f174ab5..a9c11d8 100644 --- a/source/substates/PauseSubState.hx +++ b/source/substates/PauseSubState.hx @@ -300,6 +300,7 @@ class PauseSubState extends MusicBeatSubstate else { if (!useTransition){ + FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; }