From 9177b98a143ed9e109f1090f0b93a983628c38e1 Mon Sep 17 00:00:00 2001 From: Nennneko5787 Date: Sat, 15 Oct 2022 12:04:18 +0900 Subject: [PATCH] msTiming and other minor fixes & additions --- README.md | 182 ++++++++++++---------------- gitVersion.txt | 2 +- source/ClientPrefs.hx | 6 + source/FreeplayState.hx | 6 +- source/FunkinLua.hx | 7 ++ source/Main.hx | 2 +- source/MainMenuState.hx | 2 +- source/PauseSubState.hx | 63 ++++++++-- source/PlayState.hx | 99 +++++++++++++-- source/editors/ChartingState.hx | 5 +- source/options/VisualsUISubState.hx | 14 +++ 11 files changed, 255 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index 507d926fa5e..f0b995c2703 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,78 @@ -# Friday Night Funkin' - Psych Engine -Engine originally used on [Mind Games Mod](https://gamebanana.com/mods/301107), intended to be a fix for the vanilla version's many issues while keeping the casual play aspect of it. Also aiming to be an easier alternative to newbie coders. - -## Installation: -You must have [the most up-to-date version of Haxe](https://haxe.org/download/), seriously, stop using 4.1.5, it misses some stuff. - -Follow a Friday Night Funkin' source code compilation tutorial, after this you will need to install LuaJIT. - -To install LuaJIT do this: `haxelib git linc_luajit https://github.com/nebulazorua/linc_luajit` on a Command prompt/PowerShell - -...Or if you don't want your mod to be able to run .lua scripts, delete the "LUA_ALLOWED" line on Project.xml - - -If you get an error about StatePointer when using Lua, run `haxelib remove linc_luajit` into Command Prompt/PowerShell, then re-install linc_luajit. - -If you want video support on your mod, simply do `haxelib install hxCodec` on a Command prompt/PowerShell - -otherwise, you can delete the "VIDEOS_ALLOWED" Line on Project.xml - -## Credits: -* Shadow Mario - Programmer -* RiverOaken - Artist -* Yoshubs - Assistant Programmer - -### Special Thanks -* bbpanzu - Ex-Programmer -* shubs - New Input System -* SqirraRNG - Crash Handler and Base code for Chart Editor's Waveform -* KadeDev - Fixed some cool stuff on Chart Editor and other PRs -* iFlicky - Composer of Psync and Tea Time, also made the Dialogue Sounds -* PolybiusProxy - .MP4 Video Loader Library (hxCodec) -* Keoiki - Note Splash Animations -* Smokey - Sprite Atlas Support -* Nebula the Zorua - LUA JIT Fork and some Lua reworks -_____________________________________ - -# Features - -## Attractive animated dialogue boxes: - -![](https://user-images.githubusercontent.com/44785097/127706669-71cd5cdb-5c2a-4ecc-871b-98a276ae8070.gif) - - -## Mod Support -* Probably one of the main points of this engine, you can code in .lua files outside of the source code, making your own weeks without even messing with the source! -* Comes with a Mod Organizing/Disabling Menu. - - -## Atleast one change to every week: -### Week 1: - * New Dad Left sing sprite - * Unused stage lights are now used -### Week 2: - * Both BF and Skid & Pump does "Hey!" animations - * Thunders does a quick light flash and zooms the camera in slightly - * Added a quick transition/cutscene to Monster -### Week 3: - * BF does "Hey!" during Philly Nice - * Blammed has a cool new colors flash during that sick part of the song -### Week 4: - * Better hair physics for Mom/Boyfriend (Maybe even slightly better than Week 7's :eyes:) - * Henchmen die during all songs. Yeah :( -### Week 5: - * Bottom Boppers and GF does "Hey!" animations during Cocoa and Eggnog - * On Winter Horrorland, GF bops her head slower in some parts of the song. -### Week 6: - * On Thorns, the HUD is hidden during the cutscene - * Also there's the Background girls being spooky during the "Hey!" parts of the Instrumental - -## Cool new Chart Editor changes and countless bug fixes -![](https://github.com/ShadowMario/FNF-PsychEngine/blob/main/docs/img/chart.png?raw=true) -* You can now chart "Event" notes, which are bookmarks that trigger specific actions that usually were hardcoded on the vanilla version of the game. -* Your song's BPM can now have decimal values -* You can manually adjust a Note's strum time if you're really going for milisecond precision -* You can change a note's type on the Editor, it comes with two example types: - * Alt Animation: Forces an alt animation to play, useful for songs like Ugh/Stress - * Hey: Forces a "Hey" animation instead of the base Sing animation, if Boyfriend hits this note, Girlfriend will do a "Hey!" too. - -## Multiple editors to assist you in making your own Mod -![Screenshot_3](https://user-images.githubusercontent.com/44785097/144629914-1fe55999-2f18-4cc1-bc70-afe616d74ae5.png) -* Working both for Source code modding and Downloaded builds! - -## Story mode menu rework: -![](https://i.imgur.com/UB2EKpV.png) -* Added a different BG to every song (less Tutorial) -* All menu characters are now in individual spritesheets, makes modding it easier. - -## Credits menu -![Screenshot_1](https://user-images.githubusercontent.com/44785097/144632635-f263fb22-b879-4d6b-96d6-865e9562b907.png) -* You can add a head icon, name, description and a Redirect link for when the player presses Enter while the item is currently selected. - -## Awards/Achievements -* The engine comes with 16 example achievements that you can mess with and learn how it works (Check Achievements.hx and search for "checkForAchievement" on PlayState.hx) - -## Options menu: -* You can change Note colors, Delay and Combo Offset, Controls and Preferences there. - * On Preferences you can toggle Downscroll, Middlescroll, Anti-Aliasing, Framerate, Low Quality, Note Splashes, Flashing Lights, etc. - -## Other gameplay features: -* When the enemy hits a note, their strum note also glows. -* Lag doesn't impact the camera movement and player icon scaling anymore. -* Some stuff based on Week 7's changes has been put in (Background colors on Freeplay, Note splashes) -* You can reset your Score on Freeplay/Story Mode by pressing Reset button. -* You can listen to a song or adjust Scroll Speed/Damage taken/etc. on Freeplay by pressing Space. +Note: This document uses the DeepL translation and the text may be incorrect. +# Friday Night Funkin' - nekoEngine +A mod that has only the good features of Kade Engine, Psych Engine and Leather Engine (or maybe not). +This mod is a Psych Engine fork. + +## Build nekoEngine: +You must have [the most up-to-date version of Haxe](https://haxe.org/download/), seriously, stop using 4.1.5, it misses some stuff. + +To build nekoEngine, execute the following command at the prompt/PowerShell. +
+haxelib install lime
+haxelib install openfl
+haxelib install flixel
+haxelib install flixel-addons
+haxelib install flixel-ui
+haxelib install hscript
+haxelib install newgrounds
+haxelib run lime setup
+haxelib install flixel-tools
+haxelib run flixel-tools setup
+haxelib git polymod https://github.com/larsiusprime/polymod.git
+haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc
+haxelib git linc_luajit https://github.com/nebulazorua/linc_luajit
+haxelib install hxCodec
+haxelib install hxcpp
+
+At the moment, you can optionally fix the transition bug in songs with zoomed-out cameras. +
+haxelib git flixel-addons https://github.com/HaxeFlixel/flixel-addons
+
+Once all of these are installed, build using the following command in the root folder of the project +### Windows +To build the Windows version, download the Visual Studio 2019 installer [here](https://download.visualstudio.microsoft.com/download/pr/3105fcfe-e771-41d6-9a1c-fc971e7d03a7/8eb13958dc429a6e6f7e0d6704d43a55f18d02a253608351b6bf6723ffdaf24e/vs_Community.exe), run the installer, go to the individual components tab and and select the following items + +* MSVC v142 - VS 2019 C++ x64/x86 build tools +* Windows SDK (10.0.17763.0) + +
+lime build windows
+
+If you want to build a release version, use the following command +
+lime build windows -release
+
+If you want to build the 32-bit version, add the following arguments to the command +
+-32 -D 32bits
+
+### Mac +
+lime build mac
+
+If you want to build a release version, use the following command +
+lime build mac -release
+
+### Linux +
+lime build linux
+
+If you want to build a release version, use the following command +
+lime build linux -release
+
+### HTML +
+lime test html5 -release
+
+## Features +You can use all the features of the Psych Engine and some of the following +* Timing display (in milliseconds) when a note is hit +* Automatic playback of songs in the free play menu (must be enabled in the settings) +* Japanese language support +* Support for Psych Engine mods +## Items to be added in the future +* Fixed display of milliseconds when a note is hit. +* Fixed support for 1~21 key notation +* Make it possible to hit opponent's notes \ No newline at end of file diff --git a/gitVersion.txt b/gitVersion.txt index 8a9ecc2ea99..7bcd0e3612d 100644 --- a/gitVersion.txt +++ b/gitVersion.txt @@ -1 +1 @@ -0.0.1 \ No newline at end of file +0.0.2 \ No newline at end of file diff --git a/source/ClientPrefs.hx b/source/ClientPrefs.hx index ecd145baa6e..66cb3fda1e9 100644 --- a/source/ClientPrefs.hx +++ b/source/ClientPrefs.hx @@ -93,6 +93,7 @@ class ClientPrefs { public static var defaultKeys:Map> = null; public static var freeplayAutoPlaySong:Bool = false; + public static var msTiming:Bool = true; public static function loadDefaultKeys() { defaultKeys = keyBinds.copy(); @@ -141,6 +142,7 @@ class ClientPrefs { FlxG.save.data.comboStacking = comboStacking; FlxG.save.data.language = language; FlxG.save.data.freeplayAutoPlaySong = freeplayAutoPlaySong; + FlxG.save.data.msTiming = msTiming; FlxG.save.flush(); @@ -306,6 +308,10 @@ class ClientPrefs { { freeplayAutoPlaySong = FlxG.save.data.freeplayAutoPlaySong; } + if (FlxG.save.data.msTiming != null) + { + msTiming = FlxG.save.data.msTiming; + } } inline public static function getGameplaySetting(name:String, defaultValue:Dynamic):Dynamic { diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index 1ca574de53e..ca9a24143e4 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -384,8 +384,10 @@ class FreeplayState extends MusicBeatState } FlxG.sound.music.volume = 0; - - destroyFreeplayVocals(); + + if (ClientPrefs.freeplayAutoPlaySong){ + destroyFreeplayVocals(); + } } else if(controls.RESET) { diff --git a/source/FunkinLua.hx b/source/FunkinLua.hx index 720325f8d57..cd4d4d9fc91 100644 --- a/source/FunkinLua.hx +++ b/source/FunkinLua.hx @@ -52,6 +52,8 @@ import hscript.Interp; import hscript.Expr; #end +import flash.system.System; //Funkin_End(Lua) + #if desktop import Discord; #end @@ -2755,6 +2757,11 @@ class FunkinLua { return list; }); + Lua_helper.add_callback(lua, "funkin_end", function() { + System.exit(0); + return; + }); + call('onCreate', []); #end } diff --git a/source/Main.hx b/source/Main.hx index 56be353fd16..ad88171f96d 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -130,7 +130,7 @@ class Main extends Sprite } } - errMsg += "\nUncaught Error: " + e.error + "\nPlease report this error to the GitHub page: https://github.com/ShadowMario/FNF-PsychEngine\n\n> Crash Handler written by: sqirra-rng"; + errMsg += "\nUncaught Error: " + e.error + "\nPlease report this error to the GitHub page: https://github.com/nennneko5787/FNF-nekoEngine\n\n> Crash Handler written by: sqirra-rng"; if (!FileSystem.exists("./crash/")) FileSystem.createDirectory("./crash/"); diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 9ac6a656f7a..72f9b04cdb5 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -25,7 +25,7 @@ using StringTools; class MainMenuState extends MusicBeatState { - public static var nekoEngineVersion:String = '0.0.1'; //This is also used for Discord RPC + public static var nekoEngineVersion:String = '0.0.2'; //This is also used for Discord RPC public static var psychEngineVersion:String = '0.6.2'; //This is also used for Discord RPC public static var curSelected:Int = 0; diff --git a/source/PauseSubState.hx b/source/PauseSubState.hx index 6a81af17de9..c55dcfeb489 100644 --- a/source/PauseSubState.hx +++ b/source/PauseSubState.hx @@ -20,11 +20,14 @@ class PauseSubState extends MusicBeatSubstate var grpMenuShit:FlxTypedGroup; var menuItems:Array = []; - var menuItemsOG:Array = ['Resume', 'Restart Song', 'Change Difficulty', 'Exit to menu']; + var menuItemsOG:Array = ['Resume', 'Restart Song', 'Change Difficulty', 'GamePlay Options', 'Exit to menu']; var difficultyChoices = []; + var gameplayOptions:Array = ['Instakill on Miss', 'Practice Mode', 'Botplay']; var curSelected:Int = 0; var pauseMusic:FlxSound; + var instakillText:FlxText; + var botplayText:FlxText; var practiceText:FlxText; var skipTimeText:FlxText; var skipTimeTracker:Alphabet; @@ -49,8 +52,8 @@ class PauseSubState extends MusicBeatSubstate menuItemsOG.insert(3, 'Skip Time'); } menuItemsOG.insert(3 + num, 'End Song'); - menuItemsOG.insert(4 + num, 'Toggle Practice Mode'); - menuItemsOG.insert(5 + num, 'Toggle Botplay'); + //menuItemsOG.insert(4 + num, 'Toggle Practice Mode'); + //menuItemsOG.insert(5 + num, 'Toggle Botplay'); } menuItems = menuItemsOG; @@ -60,6 +63,7 @@ class PauseSubState extends MusicBeatSubstate } difficultyChoices.push('BACK'); + gameplayOptions.push('BACK'); pauseMusic = new FlxSound(); if(songName != null) { @@ -98,7 +102,15 @@ class PauseSubState extends MusicBeatSubstate blueballedTxt.updateHitbox(); add(blueballedTxt); - practiceText = new FlxText(20, 15 + 101, 0, "PRACTICE MODE", 32); + instakillText = new FlxText(20, 15 + 101, 0, "INSTANT ON KILL", 32); + instakillText.scrollFactor.set(); + instakillText.setFormat(Paths.font('vcr.ttf'), 32); + instakillText.x = FlxG.width - (instakillText.width + 20); + instakillText.updateHitbox(); + instakillText.visible = PlayState.instance.instakillOnMiss; + add(instakillText); + + practiceText = new FlxText(20, 15 + 133, 0, "PRACTICE MODE", 32); practiceText.scrollFactor.set(); practiceText.setFormat(Paths.font('vcr.ttf'), 32); practiceText.x = FlxG.width - (practiceText.width + 20); @@ -106,6 +118,14 @@ class PauseSubState extends MusicBeatSubstate practiceText.visible = PlayState.instance.practiceMode; add(practiceText); + botplayText = new FlxText(20, 15 + 165, 0, "BOTPLAY", 32); + botplayText.scrollFactor.set(); + botplayText.setFormat(Paths.font('vcr.ttf'), 32); + botplayText.x = FlxG.width - (botplayText.width + 20); + botplayText.updateHitbox(); + botplayText.visible = PlayState.instance.cpuControlled; + add(botplayText); + var chartingText:FlxText = new FlxText(20, 15 + 101, 0, "CHARTING MODE", 32); chartingText.scrollFactor.set(); chartingText.setFormat(Paths.font('vcr.ttf'), 32); @@ -210,6 +230,29 @@ class PauseSubState extends MusicBeatSubstate regenMenu(); } + if (menuItems == gameplayOptions) + { + switch (daSelected) + { + case 'Instakill on Miss': + PlayState.instance.instakillOnMiss = !PlayState.instance.instakillOnMiss; + PlayState.changedDifficulty = true; + instakillText.visible = PlayState.instance.instakillOnMiss; + case 'Practice Mode': + PlayState.instance.practiceMode = !PlayState.instance.practiceMode; + PlayState.changedDifficulty = true; + practiceText.visible = PlayState.instance.practiceMode; + case 'Botplay': + PlayState.instance.cpuControlled = !PlayState.instance.cpuControlled; + PlayState.changedDifficulty = true; + botplayText.visible = PlayState.instance.cpuControlled; + case 'BACK': + menuItems = menuItemsOG; + deleteSkipTimeText(); + regenMenu(); + } + } + switch (daSelected) { case "Resume": @@ -218,10 +261,12 @@ class PauseSubState extends MusicBeatSubstate menuItems = difficultyChoices; deleteSkipTimeText(); regenMenu(); + /* case 'Toggle Practice Mode': PlayState.instance.practiceMode = !PlayState.instance.practiceMode; PlayState.changedDifficulty = true; practiceText.visible = PlayState.instance.practiceMode; + */ case "Restart Song": restartSong(); case "Leave Charting Mode": @@ -245,12 +290,10 @@ class PauseSubState extends MusicBeatSubstate case "End Song": close(); PlayState.instance.finishSong(true); - case 'Toggle Botplay': - PlayState.instance.cpuControlled = !PlayState.instance.cpuControlled; - PlayState.changedDifficulty = true; - PlayState.instance.botplayTxt.visible = PlayState.instance.cpuControlled; - PlayState.instance.botplayTxt.alpha = 1; - PlayState.instance.botplaySine = 0; + case 'GamePlay Options': + menuItems = gameplayOptions; + deleteSkipTimeText(); + regenMenu(); case "Exit to menu": PlayState.deathCounter = 0; PlayState.seenCutscene = false; diff --git a/source/PlayState.hx b/source/PlayState.hx index b92bcbd2a41..d5fb8195763 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -266,9 +266,16 @@ class PlayState extends MusicBeatState public var songHits:Int = 0; public var songMisses:Int = 0; public var scoreTxt:FlxText; + + var allNotesMs:Float = 0; + var averageMs:Float = 0; + var timeTxt:FlxText; var scoreTxtTween:FlxTween; + var msTimeTxt:FlxText = null; + var timeShown:Int = 0; + public static var campaignScore:Int = 0; public static var campaignMisses:Int = 0; public static var seenCutscene:Bool = false; @@ -4252,20 +4259,90 @@ class PlayState extends MusicBeatState coolText.text = Std.string(seperatedScore); // add(coolText); - FlxTween.tween(rating, {alpha: 0}, 0.2, { - startDelay: Conductor.crochet * 0.001 - }); + if (ClientPrefs.msTiming == true) + { + allNotesMs += noteDiff; + averageMs = allNotesMs/songHits; - FlxTween.tween(comboSpr, {alpha: 0}, 0.2, { - onComplete: function(tween:FlxTween) + remove(msTimeTxt); + msTimeTxt = new FlxText(0, 0, 0, "0ms"); + timeShown = 0; + switch (daRating.name) { - coolText.destroy(); - comboSpr.destroy(); + case 'shit' | 'bad': + msTimeTxt.color = FlxColor.RED; + case 'good': + msTimeTxt.color = FlxColor.GREEN; + case 'sick': + msTimeTxt.color = FlxColor.CYAN; + } + msTimeTxt.borderStyle = OUTLINE; + msTimeTxt.borderSize = 1; + msTimeTxt.borderColor = FlxColor.BLACK; + msTimeTxt.text = Std.string(Math.round(noteDiff)) + "ms"; + msTimeTxt.size = 20; + + if (msTimeTxt.alpha != 1) + msTimeTxt.alpha = 1; + + add(msTimeTxt); + + msTimeTxt.screenCenter(); + msTimeTxt.x = comboSpr.x + 100; + msTimeTxt.y = rating.y + 100; + msTimeTxt.acceleration.y = 600; + msTimeTxt.velocity.y -= 150; + + msTimeTxt.velocity.x += comboSpr.velocity.x; + + msTimeTxt.updateHitbox(); + + msTimeTxt.cameras = [camHUD]; + } + + if (ClientPrefs.msTiming == true) + { + FlxTween.tween(rating, {alpha: 0}, 0.2, { + startDelay: Conductor.crochet * 0.001, + onUpdate: function(tween:FlxTween) + { + if (msTimeTxt != null) + msTimeTxt.alpha -= 0.02; + timeShown++; + } + }); + + FlxTween.tween(comboSpr, {alpha: 0}, 0.2, { + onComplete: function(tween:FlxTween) + { + coolText.destroy(); + comboSpr.destroy(); + if (msTimeTxt != null && timeShown >= 20 && ClientPrefs.msTiming == true) + { + remove(msTimeTxt); + msTimeTxt = null; + } + rating.destroy(); + }, + startDelay: Conductor.crochet * 0.002 + }); + }else{ + FlxTween.tween(rating, {alpha: 0}, 0.2, { + startDelay: Conductor.crochet * 0.001, + }); + + FlxTween.tween(comboSpr, {alpha: 0}, 0.2, { + onComplete: function(tween:FlxTween) + { + coolText.destroy(); + comboSpr.destroy(); + + rating.destroy(); + }, + startDelay: Conductor.crochet * 0.002 + }); + } - rating.destroy(); - }, - startDelay: Conductor.crochet * 0.002 - }); } public var strumsBlocked:Array = []; diff --git a/source/editors/ChartingState.hx b/source/editors/ChartingState.hx index a0f8824c1d1..0a006ac2acd 100644 --- a/source/editors/ChartingState.hx +++ b/source/editors/ChartingState.hx @@ -1671,11 +1671,10 @@ class ChartingState extends MusicBeatState if (FlxG.keys.justPressed.BACKSPACE) { - //if(onMasterEditor) { + PlayState.chartingMode = false; MusicBeatState.switchState(new editors.MasterEditorMenu()); FlxG.sound.playMusic(Paths.music('freakyMenu')); - //} - FlxG.mouse.visible = false; + FlxG.mouse.visible = false; return; } diff --git a/source/options/VisualsUISubState.hx b/source/options/VisualsUISubState.hx index 1b9f57591db..91c6850dd52 100644 --- a/source/options/VisualsUISubState.hx +++ b/source/options/VisualsUISubState.hx @@ -160,6 +160,13 @@ class VisualsUISubState extends BaseOptionsMenu 'bool', false); addOption(option); + + var option:Option = new Option('Milliseconds display when a note is struck', + "If unchecked, the milliseconds display when a note is hit is hidden." , + 'msTiming', + 'bool', + true); + addOption(option); } if (ClientPrefs.language == "Japanese") @@ -288,6 +295,13 @@ class VisualsUISubState extends BaseOptionsMenu 'bool', false); addOption(option); + + var option:Option = new Option('Milliseconds display when a note is struck', + "チェックを外した場合、ノーツを打ったときのミリ秒表示が非表示になります。" , + 'msTiming', + 'bool', + true); + addOption(option); } super();