diff --git a/Project.xml b/Project.xml
index ffb6961..2d23bb6 100644
--- a/Project.xml
+++ b/Project.xml
@@ -3,7 +3,7 @@
xsi:schemaLocation="http://lime.openfl.org/project/1.0.4 http://lime.openfl.org/xsd/project-1.0.4.xsd">
-
+
@@ -52,7 +52,7 @@ xsi:schemaLocation="http://lime.openfl.org/project/1.0.4 http://lime.openfl.org/
-
+
@@ -62,10 +62,10 @@ xsi:schemaLocation="http://lime.openfl.org/project/1.0.4 http://lime.openfl.org/
-
+
-
+
diff --git a/README.md b/README.md
index 8c3dd58..e176b51 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
![GitHub repo size](https://img.shields.io/github/repo-size/Slushi-Github/Slushi-Engine)
-[Gamejolt](https://gamejolt.com/games/SlushiEngine/884361) - [GameBanana](https://gamebanana.com/tools/17953)
+[GameBanana](https://gamebanana.com/tools/17953) - [Gamejolt](https://gamejolt.com/games/SlushiEngine/884361)
Slushi Engine is an FNF' engine that allows you to make modcharts with [Modcharting Tools](https://github.com/EdwhakKB/FNF-Modcharting-Tools) and other [SC Engine](https://github.com/EdwhakKB/SC-SP-ENGINE) utilities, while also being able to make a unique kind of modchart that uses Windows functions!
diff --git a/README_ES.md b/README_ES.md
index 0d1e158..ae30e5b 100644
--- a/README_ES.md
+++ b/README_ES.md
@@ -17,7 +17,7 @@
![GitHub repo size](https://img.shields.io/github/repo-size/Slushi-Github/Slushi-Engine)
-[Gamejolt](https://gamejolt.com/games/SlushiEngine/884361) - [GameBanana](https://gamebanana.com/tools/17953)
+[GameBanana](https://gamebanana.com/tools/17953) - [Gamejolt](https://gamejolt.com/games/SlushiEngine/884361)
Slushi Engine es un motor de FNF' que te permite hacer modcharts con [Modcharting Tools](https://github.com/EdwhakKB/FNF-Modcharting-Tools) y otras utilidades del [SC Engine](https://github.com/EdwhakKB/SC-SP-ENGINE), ¡mientras que también te permite hacer un tipo único de modchart que utiliza funciones de Windows!
diff --git a/assets/shared/data/characters/bf.json b/assets/shared/data/characters/bf.json
index 81833b7..11b1124 100644
--- a/assets/shared/data/characters/bf.json
+++ b/assets/shared/data/characters/bf.json
@@ -141,7 +141,7 @@
"flip_x": true,
"healthbar_colors": [49, 176, 209],
"camera_position": [0, 0],
- "noteSkin": "noteSkins/NOTE_assets",
+ "noteSkin": "",
"sing_duration": 4,
"scale": 1,
"_editor_isPlayer": true
diff --git a/assets/shared/data/fonts/wendy.ttf b/assets/shared/data/fonts/wendy.ttf
new file mode 100644
index 0000000..bba4525
Binary files /dev/null and b/assets/shared/data/fonts/wendy.ttf differ
diff --git a/assets/shared/images/noteSkins/NOTE_assets-notitg.png b/assets/shared/images/noteSkins/NOTE_assets-notitg.png
new file mode 100644
index 0000000..d2aacfb
Binary files /dev/null and b/assets/shared/images/noteSkins/NOTE_assets-notitg.png differ
diff --git a/assets/shared/images/noteSkins/NOTE_assets-notitg.xml b/assets/shared/images/noteSkins/NOTE_assets-notitg.xml
new file mode 100644
index 0000000..2b8655b
--- /dev/null
+++ b/assets/shared/images/noteSkins/NOTE_assets-notitg.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/shared/images/noteSkins/list.txt b/assets/shared/images/noteSkins/list.txt
index 9c1e166..038c415 100644
--- a/assets/shared/images/noteSkins/list.txt
+++ b/assets/shared/images/noteSkins/list.txt
@@ -1,2 +1,3 @@
Future
-Chip
\ No newline at end of file
+Chip
+NotITG
\ No newline at end of file
diff --git a/assets/slushiEngineAssets/SLEAssets/BGs/SlushiBGMainMenu.png b/assets/slushiEngineAssets/BGs/SlushiBGMainMenu.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/BGs/SlushiBGMainMenu.png
rename to assets/slushiEngineAssets/BGs/SlushiBGMainMenu.png
diff --git a/assets/slushiEngineAssets/SLEAssets/BGs/SlushiBGModchartEditor.png b/assets/slushiEngineAssets/BGs/SlushiBGModchartEditor.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/BGs/SlushiBGModchartEditor.png
rename to assets/slushiEngineAssets/BGs/SlushiBGModchartEditor.png
diff --git a/assets/slushiEngineAssets/BGs/SlushiBGPauseSubState.png b/assets/slushiEngineAssets/BGs/SlushiBGPauseSubState.png
new file mode 100644
index 0000000..60ec8b7
Binary files /dev/null and b/assets/slushiEngineAssets/BGs/SlushiBGPauseSubState.png differ
diff --git a/assets/slushiEngineAssets/SLEAssets/Musics/SLE_HackNet_Resonance.ogg b/assets/slushiEngineAssets/Musics/SLE_HackNet_Resonance.ogg
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/Musics/SLE_HackNet_Resonance.ogg
rename to assets/slushiEngineAssets/Musics/SLE_HackNet_Resonance.ogg
diff --git a/assets/slushiEngineAssets/SLEAssets/OthersAssets/COMO QUE LO DETECTO COMO UN VIRUS MI ENGINE.png b/assets/slushiEngineAssets/OthersAssets/COMO QUE LO DETECTO COMO UN VIRUS MI ENGINE.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/OthersAssets/COMO QUE LO DETECTO COMO UN VIRUS MI ENGINE.png
rename to assets/slushiEngineAssets/OthersAssets/COMO QUE LO DETECTO COMO UN VIRUS MI ENGINE.png
diff --git a/assets/slushiEngineAssets/SLEAssets/OthersAssets/ImageNotFound.png b/assets/slushiEngineAssets/OthersAssets/ImageNotFound.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/OthersAssets/ImageNotFound.png
rename to assets/slushiEngineAssets/OthersAssets/ImageNotFound.png
diff --git a/assets/slushiEngineAssets/SLEAssets/OthersAssets/WhenTeRickrolean.png b/assets/slushiEngineAssets/OthersAssets/WhenTeRickrolean.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/OthersAssets/WhenTeRickrolean.png
rename to assets/slushiEngineAssets/OthersAssets/WhenTeRickrolean.png
diff --git a/assets/slushiEngineAssets/SLEAssets/OthersAssets/brutus.png b/assets/slushiEngineAssets/OthersAssets/brutus.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/OthersAssets/brutus.png
rename to assets/slushiEngineAssets/OthersAssets/brutus.png
diff --git a/assets/slushiEngineAssets/SLEAssets/OthersAssets/nothing.png b/assets/slushiEngineAssets/OthersAssets/nothing.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/OthersAssets/nothing.png
rename to assets/slushiEngineAssets/OthersAssets/nothing.png
diff --git a/assets/slushiEngineAssets/SLEAssets/OthersAssets/player.png b/assets/slushiEngineAssets/OthersAssets/player.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/OthersAssets/player.png
rename to assets/slushiEngineAssets/OthersAssets/player.png
diff --git a/assets/slushiEngineAssets/SLEAssets/OthersAssets/player.xml b/assets/slushiEngineAssets/OthersAssets/player.xml
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/OthersAssets/player.xml
rename to assets/slushiEngineAssets/OthersAssets/player.xml
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/CreditsOption.png b/assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/CreditsOption.png
deleted file mode 100644
index fa5b1a2..0000000
Binary files a/assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/CreditsOption.png and /dev/null differ
diff --git a/assets/slushiEngineAssets/SLEAssets/SLEHUDImages/BG.png b/assets/slushiEngineAssets/SlushiEngineHUDAssets/BG.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SLEHUDImages/BG.png
rename to assets/slushiEngineAssets/SlushiEngineHUDAssets/BG.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SLEHUDImages/Notes.png b/assets/slushiEngineAssets/SlushiEngineHUDAssets/Notes.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SLEHUDImages/Notes.png
rename to assets/slushiEngineAssets/SlushiEngineHUDAssets/Notes.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SLEHUDImages/SCEngineText.png b/assets/slushiEngineAssets/SlushiEngineHUDAssets/SCEngineText.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SLEHUDImages/SCEngineText.png
rename to assets/slushiEngineAssets/SlushiEngineHUDAssets/SCEngineText.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SLEHUDImages/Slushi.png b/assets/slushiEngineAssets/SlushiEngineHUDAssets/Slushi.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SLEHUDImages/Slushi.png
rename to assets/slushiEngineAssets/SlushiEngineHUDAssets/Slushi.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SLEHUDImages/SlushiEngineText.png b/assets/slushiEngineAssets/SlushiEngineHUDAssets/SlushiEngineText.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SLEHUDImages/SlushiEngineText.png
rename to assets/slushiEngineAssets/SlushiEngineHUDAssets/SlushiEngineText.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSCE.png b/assets/slushiEngineAssets/SlushiEngineLogoSCE.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSCE.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSCE.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/Notes.png b/assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/Notes.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/Notes.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/Notes.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/SCEngineText.png b/assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/SCEngineText.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/SCEngineText.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/SCEngineText.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/Slushi.png b/assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/Slushi.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/Slushi.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/Slushi.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/SlushiEngineText.png b/assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/SlushiEngineText.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/SlushiEngineText.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/SlushiEngineText.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/blueNote.png b/assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/blueNote.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/blueNote.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/blueNote.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/greenNote.png b/assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/greenNote.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/greenNote.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/greenNote.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/purpleNote.png b/assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/purpleNote.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/purpleNote.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/purpleNote.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/redNote.png b/assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/redNote.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiEngineLogoSeparatedParts/redNote.png
rename to assets/slushiEngineAssets/SlushiEngineLogoSeparatedParts/redNote.png
diff --git a/assets/slushiEngineAssets/SlushiFreeplayStateAssets/BG.png b/assets/slushiEngineAssets/SlushiFreeplayStateAssets/BG.png
new file mode 100644
index 0000000..99ad8eb
Binary files /dev/null and b/assets/slushiEngineAssets/SlushiFreeplayStateAssets/BG.png differ
diff --git a/assets/slushiEngineAssets/SlushiFreeplayStateAssets/DANOTE.png b/assets/slushiEngineAssets/SlushiFreeplayStateAssets/DANOTE.png
new file mode 100644
index 0000000..681e0e5
Binary files /dev/null and b/assets/slushiEngineAssets/SlushiFreeplayStateAssets/DANOTE.png differ
diff --git a/assets/slushiEngineAssets/SlushiMainMenuAssets/CreditsOption.png b/assets/slushiEngineAssets/SlushiMainMenuAssets/CreditsOption.png
new file mode 100644
index 0000000..693e1de
Binary files /dev/null and b/assets/slushiEngineAssets/SlushiMainMenuAssets/CreditsOption.png differ
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/FreeplayOption.png b/assets/slushiEngineAssets/SlushiMainMenuAssets/FreeplayOption.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/FreeplayOption.png
rename to assets/slushiEngineAssets/SlushiMainMenuAssets/FreeplayOption.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/ModsOption.png b/assets/slushiEngineAssets/SlushiMainMenuAssets/ModsOption.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/ModsOption.png
rename to assets/slushiEngineAssets/SlushiMainMenuAssets/ModsOption.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/OptionsOption.png b/assets/slushiEngineAssets/SlushiMainMenuAssets/OptionsOption.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/OptionsOption.png
rename to assets/slushiEngineAssets/SlushiMainMenuAssets/OptionsOption.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/StoryModeOption.png b/assets/slushiEngineAssets/SlushiMainMenuAssets/StoryModeOption.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiMainMenuAssets/StoryModeOption.png
rename to assets/slushiEngineAssets/SlushiMainMenuAssets/StoryModeOption.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle0.png b/assets/slushiEngineAssets/SlushiTitleStateAssets/Particle0.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle0.png
rename to assets/slushiEngineAssets/SlushiTitleStateAssets/Particle0.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle1.png b/assets/slushiEngineAssets/SlushiTitleStateAssets/Particle1.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle1.png
rename to assets/slushiEngineAssets/SlushiTitleStateAssets/Particle1.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle2.png b/assets/slushiEngineAssets/SlushiTitleStateAssets/Particle2.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle2.png
rename to assets/slushiEngineAssets/SlushiTitleStateAssets/Particle2.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle3.png b/assets/slushiEngineAssets/SlushiTitleStateAssets/Particle3.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle3.png
rename to assets/slushiEngineAssets/SlushiTitleStateAssets/Particle3.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle4.png b/assets/slushiEngineAssets/SlushiTitleStateAssets/Particle4.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle4.png
rename to assets/slushiEngineAssets/SlushiTitleStateAssets/Particle4.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle5.png b/assets/slushiEngineAssets/SlushiTitleStateAssets/Particle5.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/Particle5.png
rename to assets/slushiEngineAssets/SlushiTitleStateAssets/Particle5.png
diff --git a/assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/continueSprite.png b/assets/slushiEngineAssets/SlushiTitleStateAssets/continueSprite.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/SlushiTitleStateAssets/continueSprite.png
rename to assets/slushiEngineAssets/SlushiTitleStateAssets/continueSprite.png
diff --git a/assets/slushiEngineAssets/SLEAssets/Sounds/beep.ogg b/assets/slushiEngineAssets/Sounds/beep.ogg
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/Sounds/beep.ogg
rename to assets/slushiEngineAssets/Sounds/beep.ogg
diff --git a/assets/slushiEngineAssets/SLEAssets/Sounds/beep2.ogg b/assets/slushiEngineAssets/Sounds/beep2.ogg
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/Sounds/beep2.ogg
rename to assets/slushiEngineAssets/Sounds/beep2.ogg
diff --git a/assets/slushiEngineAssets/SLEAssets/Sounds/vineBoom.ogg b/assets/slushiEngineAssets/Sounds/vineBoom.ogg
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/Sounds/vineBoom.ogg
rename to assets/slushiEngineAssets/Sounds/vineBoom.ogg
diff --git a/assets/slushiEngineAssets/SLEAssets/Unused/SlushiWagSticker.gif b/assets/slushiEngineAssets/Unused/SlushiWagSticker.gif
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/Unused/SlushiWagSticker.gif
rename to assets/slushiEngineAssets/Unused/SlushiWagSticker.gif
diff --git a/assets/slushiEngineAssets/SLEAssets/WinSL_Assets/windowIcon.ico b/assets/slushiEngineAssets/WinSL_Assets/windowIcon.ico
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/WinSL_Assets/windowIcon.ico
rename to assets/slushiEngineAssets/WinSL_Assets/windowIcon.ico
diff --git a/assets/slushiEngineAssets/SLEAssets/optionsAssets/OptionsBG.png b/assets/slushiEngineAssets/optionsAssets/OptionsBG.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/optionsAssets/OptionsBG.png
rename to assets/slushiEngineAssets/optionsAssets/OptionsBG.png
diff --git a/assets/slushiEngineAssets/SLEAssets/optionsAssets/SLEWindow.png b/assets/slushiEngineAssets/optionsAssets/SLEWindow.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/optionsAssets/SLEWindow.png
rename to assets/slushiEngineAssets/optionsAssets/SLEWindow.png
diff --git a/assets/slushiEngineAssets/SLEAssets/optionsAssets/WindowCloseButton.png b/assets/slushiEngineAssets/optionsAssets/WindowCloseButton.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/optionsAssets/WindowCloseButton.png
rename to assets/slushiEngineAssets/optionsAssets/WindowCloseButton.png
diff --git a/assets/slushiEngineAssets/SLEAssets/optionsAssets/Windows10Cursor.png b/assets/slushiEngineAssets/optionsAssets/Windows10Cursor.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/optionsAssets/Windows10Cursor.png
rename to assets/slushiEngineAssets/optionsAssets/Windows10Cursor.png
diff --git a/assets/slushiEngineAssets/SLEAssets/optionsAssets/Windows11Notification.png b/assets/slushiEngineAssets/optionsAssets/Windows11Notification.png
similarity index 100%
rename from assets/slushiEngineAssets/SLEAssets/optionsAssets/Windows11Notification.png
rename to assets/slushiEngineAssets/optionsAssets/Windows11Notification.png
diff --git a/docs/development/BuildInstructions.md b/docs/development/BuildInstructions.md
index 96a2c86..c0f3546 100644
--- a/docs/development/BuildInstructions.md
+++ b/docs/development/BuildInstructions.md
@@ -11,7 +11,8 @@ Set up [Visual Studio](https://aka.ms/vs/17/release/vs_BuildTools.exe) dependenc
select "Individual Components" and make sure to download the following:
- "MSVC v143 VS 2022 C++ x64/x86" and "Windows 10/11 SDK"
+ - MSVC v143 VS 2022 C++ x64/x86
+ - Windows 10/11 SDK
Set up Haxe libs of the engine:
diff --git a/docs/development/SLELuaSpanish/sections/Others.lua b/docs/development/SLELuaSpanish/sections/Others.lua
index 3eb3dfa..bdeb3bd 100644
--- a/docs/development/SLELuaSpanish/sections/Others.lua
+++ b/docs/development/SLELuaSpanish/sections/Others.lua
@@ -1,4 +1,18 @@
--- Others.lua -- Version: 1.1.0 -- Ultima modificación: 2/9/2024
+-- Others.lua -- Version: 1.2.0 -- Ultima modificación: 19/12/2024
+
+-- retorna un string con el nombre de la cámara para Lua, pero puedes usarlo como una variable nativa de Lua
+camGame = "game"
+camHUD = "hud"
+camOther = "other"
+camNoteStuff = "notestuff"
+camSLEHUD = "slehud"
+camThings = "camthings"
+camThings2 = "camthings2"
+camThings3 = "camthings3"
+camThings4 = "camthings4"
+camThings5 = "camthings5"
+camWaterMark = "camwatermark"
+
function printInGameplay(text, time)
--[[
@@ -63,4 +77,19 @@ function tweenNumer(tag, startNum, endNum, duration, ease)
duration: El tiempo del tween (float).
ease: El tipo de easing a aplicar (por defecto "linear") (string).
]]--
+end
+
+function getSLEVersion()
+ --[[
+ Obtiene la versión de Slushi Engine.
+ return: La versión de SLE (string).
+ ]]--
+end
+
+function getMTCurrentModifiers(equalizer)
+ --[[
+ Obtiene los modifiers actuales con sus valores del modchart hecho con Modcharting Tools.
+ equalizer: String para separar los modifiers, por defecto ":" (string).
+ return: Los modifiers actuales (string).
+ ]]--
end
\ No newline at end of file
diff --git a/docs/development/SLELuaSpanish/sections/Shaders.lua b/docs/development/SLELuaSpanish/sections/Shaders.lua
index a298be8..aa641de 100644
--- a/docs/development/SLELuaSpanish/sections/Shaders.lua
+++ b/docs/development/SLELuaSpanish/sections/Shaders.lua
@@ -1,4 +1,47 @@
--- Shaders.lua -- Versión 1.0 -- Ultima modificación: 23/08/2024
+-- Shaders.lua -- Versión 1.1.0 -- Ultima modificación: 23/12/2024
+
+function addShader3DToCamStrumsAndCamNotes()
+ --[[
+ Añade un shader 3D a la camara de los strums y las notas.
+ ]]--
+end
+
+function addShader3DToNotes()
+ --[[
+ Añade un shader 3D a las notas. (acortacion de addShader3DToCamStrumsAndCamNotes)
+ ]]--
+end
+
+function removeShader3DFromCamStrumsAndCamNotes()
+ --[[
+ Elimina el shader 3D de la camara de los strums y las notas.
+ ]]--
+end
+
+function removeShader3DFromNotes()
+ --[[
+ Elimina el shader 3D de las notas (acortacion de removeShader3DFromCamStrumsAndCamNotes).
+ ]]--
+end
+
+function setNotesShader3DProperty(prop, value)
+ --[[
+ Establece una propiedad del shader 3D de las notas.
+ prop: La propiedad a establecer (string).
+ value: El valor de la propiedad (Dynamic).
+ ]]--
+end
+
+function doTweenNotesShader3D(prop, tag, value, time, ease)
+ --[[
+ Realiza un tween en una propiedad del shader 3D de las notas.
+ prop: La propiedad a establecer (string).
+ tag: La etiqueta de la interpolación (string).
+ value: El valor final del tween (Dynamic).
+ time: El tiempo de la interpolación (float).
+ ease: El tipo de easing a aplicar (por defecto "linear") (string).
+ ]]--
+end
function addWhiteShaderToNotes()
--[[
diff --git a/docs/development/SLELuaSpanish/sections/WinSL.lua b/docs/development/SLELuaSpanish/sections/WinSL.lua
index 433744d..0a3cf80 100644
--- a/docs/development/SLELuaSpanish/sections/WinSL.lua
+++ b/docs/development/SLELuaSpanish/sections/WinSL.lua
@@ -1,4 +1,4 @@
--- WinSL.lua -- Version 1.0 -- Ultima modificación: 23/08/2024
+-- WinSL.lua -- Version 1.0.0 -- Ultima modificación: 23/08/2024
function winSL_console_getVersion()
--[[
diff --git a/docs/development/SLELuaSpanish/sections/Window.lua b/docs/development/SLELuaSpanish/sections/Window.lua
index 640d09e..f7e6f2d 100644
--- a/docs/development/SLELuaSpanish/sections/Window.lua
+++ b/docs/development/SLELuaSpanish/sections/Window.lua
@@ -1,70 +1,65 @@
--- Window.lua -- Versión 1.0 -- Ultima modificación: 23/08/2024
+-- Window.lua -- Versión 1.1.0 -- Ultima modificación: 23/12/2024
+--[[
+ [Window.lua] es una seccion
+]] --
-function windowTrans(trans, camToApply)
+function windowTransparent(transparent, camToApply)
--[[
Activa o desactiva la transparencia de la ventana.
- trans: Booleano que indica si activar (true) o desactivar (false) la transparencia.
+ transparent: Booleano que indica si activar (true) o desactivar (false) la transparencia.
camToApply: Nombre de la cámara a la cual se aplicará el efecto de transparencia (string).
- ]]--
+ ]] --
end
-function windowAlpha(alpha)
+function setWindowAlpha(alpha)
--[[
Ajusta la opacidad de la ventana.
alpha: Valor de opacidad a establecer (float).
- ]]--
+ ]] --
end
-function doTweenWinAlpha(toValue, duration, ease)
+function doTweenWinAlpha(value, duration, ease)
--[[
Realiza un tween en la opacidad de la ventana.
- fromValue: Valor inicial de opacidad (float).
- toValue: Valor final de opacidad (float).
+ value: Valor de la opacidad (float).
duration: Duración del tween (float).
ease: Tipo de easing a aplicar (string).
- ]]--
+ ]] --
end
function centerWindow()
--[[
Centra la ventana en la pantalla.
- ]]--
+ ]] --
end
-function setWindowVisible(visible)
+function setMainWindowVisible(visible)
--[[
Muestra u oculta la ventana.
visible: Booleano que indica si la ventana debe ser visible (true) o no (false).
- ]]--
-end -- USE_CAREFULLY
+ ]] --
+end -- USE_CAREFULLY
-function winAlert(text, title)
+function windowAlert(text, title)
--[[
Muestra una alerta en la ventana.
text: Texto del mensaje de alerta (string).
title: Título de la ventana de alerta (string).
- ]]--
+ ]] --
end
-function canResizableWindow(mode)
+function resizableWindow(mode)
--[[
Habilita o deshabilita la capacidad de cambiar el tamaño de la ventana.
mode: Booleano que indica si habilitar (true) o deshabilitar (false) la capacidad de redimensionar.
- ]]--
+ ]] --
end
function windowMaximized(mode)
--[[
Maximiza o restaura la ventana.
mode: Booleano que indica si maximizar (true) o restaurar (false) la ventana.
- ]]--
-end
-
-function DisableCloseButton(mode)
- --[[
- Habilita o deshabilita el botón de cierre de la ventana.
- mode: Booleano que indica si deshabilitar (true) o habilitar (false) el botón de cierre.
- ]]--
+ ]] --
end
function doTweenWinPos(mode, tag, value, duration, ease)
@@ -75,13 +70,22 @@ function doTweenWinPos(mode, tag, value, duration, ease)
value: Valor final de la posición (int).
duration: Duración del tween (float).
ease: Tipo de easing a aplicar (string).
- ]]--
+ ]] --
+end
+
+function centerWindowTween(tag, duration, ease)
+ --[[
+ Centra la ventana en la pantalla con un tween.
+ tag: Etiqueta del tween (string).
+ duration: Duración del tween (float).
+ ease: Tipo de easing a aplicar (string).
+ ]] --
end
function resetWindowParameters()
--[[
Restaura los parámetros de la ventana a su configuración predeterminada.
- ]]--
+ ]] --
end
function doTweenWinSize(mode, toValue, duration, ease)
@@ -91,14 +95,21 @@ function doTweenWinSize(mode, toValue, duration, ease)
toValue: Valor final del tamaño (float).
duration: Duración del tween (float).
ease: Tipo de easing a aplicar (por defecto "linear") (string).
- ]]--
+ ]] --
end
-function winTitle(text)
+function setWindowTitle(text)
--[[
Cambia el título de la ventana.
text: Nuevo título de la ventana (si pones "defualt", se pone el nombre por defecto del programa) (string).
- ]]--
+ ]] --
+end
+
+function getWindowTitle()
+ --[[
+ Obtiene el título de la ventana.
+ return: El título de la ventana (string).
+ ]] --
end
function setWindowPos(mode, value)
@@ -106,31 +117,31 @@ function setWindowPos(mode, value)
Establece la posición de la ventana.
mode: La propiedad a establecer ("X" o "Y") (string).
value: Valor de la posición (int).
- ]]--
+ ]] --
end
function getWindowPos(mode)
--[[
Obtiene la posición de la ventana.
mode: La propiedad a obtener ("X" o "Y") (string).
- ]]--
- return 0
+ return: La posición de la ventana (int).
+ ]] --
end
function getScreenSize(mode)
--[[
Obtiene el tamaño de la pantalla.
mode: La propiedad a obtener ("WIDTH", "W", "HEIGHT", "H") (string).
- ]]--
- return 0
+ return: El tamaño de la pantalla (int).
+ ]] --
end
function getWindowSize(mode)
--[[
Obtiene el tamaño de la ventana.
mode: La propiedad a obtener ("WIDTH", "W", "HEIGHT", "H") (string).
- ]]--
- return 0
+ return: El tamaño de la ventana (int).
+ ]] --
end
function setWindowSize(mode, value)
@@ -138,15 +149,24 @@ function setWindowSize(mode, value)
Establece el tamaño de la ventana.
mode: La propiedad a establecer ("WIDTH", "W", "HEIGHT", "H") (string).
value: Valor del tamaño (int).
- ]]--
+ ]] --
end
-function setWindowBorderColor(r, g, b, mode)
+function setWindowBorderColor(rgb, mode)
--[[
Establece el color del borde de la ventana (solo Windows 11).
- r: Valor rojo (int).
- g: Valor verde (int).
- b: Valor azul (int).
+ rgb: Color del borde (Array).
+ mode: Booleano que indica si permitir cambios de color con las notas (true) o no (false).
+ ]] --
+end
+
+function tweenWindowBorderColor(fromColor, toColor, duration, ease, mode)
+ --[[
+ Realiza un tween en el color del borde de la ventana (solo Windows 11).
+ fromColor: Color inicial del borde (Array).
+ toColor: Color final del borde (Array).
+ duration: Duración del tween (float).
+ ease: Tipo de easing a aplicar (string).
mode: Booleano que indica si permitir cambios de color con las notas (true) o no (false).
- ]]--
+ ]] --
end
diff --git a/docs/development/SLELuaSpanish/sections/Windows.lua b/docs/development/SLELuaSpanish/sections/Windows.lua
index b0db353..8622017 100644
--- a/docs/development/SLELuaSpanish/sections/Windows.lua
+++ b/docs/development/SLELuaSpanish/sections/Windows.lua
@@ -1,4 +1,4 @@
--- Windows.lua -- Versión 1.0 -- Ultima modificación: 23/08/2024
+-- Windows.lua -- Versión 1.1.0 -- Ultima modificación: 27/12/2024
function resetAllCPPFunctions()
--[[
@@ -6,12 +6,6 @@ function resetAllCPPFunctions()
]]--
end
-function getRAM()
- --[[
- Obtiene la cantidad de memoria RAM disponible en el sistema.
- ]]--
-end
-
function hideTaskBar(hide)
--[[
Oculta o muestra la barra de tareas.
@@ -22,7 +16,7 @@ end
function setWallpaper(image)
--[[
Establece una imagen como fondo de pantalla.
- image: Nombre de la imagen a usar como fondo (string).
+ image: Nombre de la imagen a usar como fondo, si pones "defualt", se pone el fondo anterior o original (string).
]]--
end
@@ -33,13 +27,7 @@ function winScreenCapture(nameToSave)
]]--
end
-function setOldWindowsWallpaper()
- --[[
- Restaura el fondo de pantalla anterior de Windows.
- ]]--
-end
-
-function moveDesktopWindows(mode, value)
+function setDesktopWindowsPos(mode, value)
--[[
Mueve las iconos del escritorio en una dirección específica.
mode: Dirección para mover ("X", "Y", "XY").
@@ -47,11 +35,11 @@ function moveDesktopWindows(mode, value)
]]--
end
-function doTweenDesktopWindows(mode, toValue, duration, ease)
+function doTweenDesktopWindowsPos(mode, value, duration, ease)
--[[
Realiza un tween en las ventanas del escritorio.
mode: Dirección del tween ("X", "Y", "XY").
- toValue: Valor final del tween.
+ value: Valor final del tween.
duration: Duración del tween.
ease: Tipo de easing (por defecto "linear").
]]--
@@ -90,7 +78,7 @@ function getWindowsVersion()
]]--
end
-function sendNoti(desc, title)
+function sendNotification(desc, title)
--[[
Envía una notificación en Windows.
desc: Descripción de la notificación (string).
@@ -122,33 +110,70 @@ end
function setOtherWindowLayeredMode(window)
--[[
Establece el modo de capa de otra ventana de Windows.
- window: Nombre de la ventana ("desktop", "taskBar").
+ window: Nombre de la ventana ("desktop", "taskBar") (string).
+ ]]--
+end
+
+-- EFECTOS GDI DE WINDOWS -------------------------------------------------------------
+--- En Windows, existe una manera de generar graficos, por medio de las funciones GDI
+--- que estan en la API de Windows.
+--- Son efectos vistos en virus o malware que esta hecho con ese proposito de generar tales efectos
+--- Algunos de los malwares usan estos efectos pueden ser:
+--- - MENZ
+--- - Sulfoxide.exe
+---
+--- Los efectos GDI, hacen un uso intensivo de la CPU
+--- por eso en Slushi Engine, estos efectos corren en un hilo aparte del CPU para que
+--- no afecte al juego principal.
+---
+--- ============================================================
+--- Los efectos incluidos en SLE a la fecha de [19/12/2024] son:
+--- - DrawIcons - Dibuja iconos de Windows en la pantalla en posiciones aleatorias.
+--- - ScreenBlink - Realiza un efecto de parpadeo en la pantalla.
+--- - ScreenGlitches - Realiza un efecto de errores graficos en la pantalla.
+--- - ScreenShake - Realiza un efecto de agitación en la pantalla.
+--- - ScreenTunnel - Realiza un efecto de túnel en la pantalla.
+--- ============================================================
+---
+--- Los efectos GDI ocurren a pantalla completa modificnado todo lo que se muestre en esta
+--- por ende pueden ser incomodos para algunos jugadores, por lo que se recomienda usarlos con precaucion.
+--- Igualmente el jugador tiene la posibilidad de desactivar
+--- estos efectos en las opciones de Slushi Engine.
+
+function startGDIThread()
+ --[[
+ Prepara un hilo del CPU separado para correr los efectos GDI.
]]--
-end
-
----------------------------------------------------------------
+end -- USE_CAREFULLY
-function windowsEffectModifier(tag, gdiEffect, activeEffect)
+function prepareGDIEffect(effect, wait)
--[[
- Modifica un efecto GDI en Windows.
- tag: Etiqueta del efecto (string).
- gdiEffect: Tipo de efecto GDI (string).
- activeEffect: true para activar, false para desactivar.
+ Inializa un efecto GDI, mas no necesariamente se muestra en la pantalla.
+ effect: Nombre del efecto GDI (string).
+ wait: Tiempo en milisegundos para esperar a que el efecto se muestre en pantalla, esto para
+ alentar el efecto cuanto mas alto sea el valor de wait (float).
]]--
end -- USE_CAREFULLY
-function setWinEffectProperty(tag, prop, value)
+function setGDIEffectWaitTime(effect, wait)
--[[
- Establece una propiedad para un efecto GDI en Windows.
- tag: Etiqueta del efecto (string).
- prop: Propiedad a modificar (string).
- value: Valor a establecer (dynamic).
+ Establece el tiempo en milisegundos para esperar a que el efecto se muestre en pantalla
+ effect: Nombre del efecto GDI (string).
+ wait: Tiempo en milisegundos para esperar a que el efecto se muestre en pantalla (float).
]]--
end -- USE_CAREFULLY
-function setTitleTextToWindows(titleText)
+function enableGDIEffect(effect, enabled)
--[[
- Establece el texto del título en la ventana de Windows.
- titleText: Texto del título (string).
+ Habilita o deshabilita un efecto GDI.
+ effect: Nombre del efecto GDI (string).
+ enabled: true para habilitar, false para deshabilitar.
]]--
end -- USE_CAREFULLY
+
+function removeGDIEffect(effect)
+ --[[
+ Elimina un efecto GDI.
+ effect: Nombre del efecto GDI (string).
+ ]]--
+end -- USE_CAREFULLY
\ No newline at end of file
diff --git a/example_mods/C18H27NO3/data/songs/c18h27no3/c18h27no3-slushi.json b/example_mods/C18H27NO3/data/songs/c18h27no3/c18h27no3-slushi.json
new file mode 100644
index 0000000..0985f8a
--- /dev/null
+++ b/example_mods/C18H27NO3/data/songs/c18h27no3/c18h27no3-slushi.json
@@ -0,0 +1,2054 @@
+{
+ "song": {
+ "speed": 3,
+ "stage": "",
+ "player1": "bf",
+ "player2": "gf",
+ "events": [],
+ "notes": [
+ {
+ "gfSection": false,
+ "altAnim": false,
+ "typeOfSection": 0,
+ "sectionNotes": [
+ [
+ 12610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 12896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 13181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 13467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 13753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 14039,
+ 2,
+ 0
+ ],
+ [
+ 14181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 14324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 14610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 14896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 15181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 15467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 15753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 16039,
+ 2,
+ 0
+ ],
+ [
+ 16324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 16467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 16610.4285714286,
+ 3,
+ 0
+ ],
+ [
+ 16896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 17181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 17467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 17753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 18039,
+ 1,
+ 0
+ ],
+ [
+ 18324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 18610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 18753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 18896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 19181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 19467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 19753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 20039,
+ 3,
+ 0
+ ],
+ [
+ 20324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 20610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 20896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 21039,
+ 3,
+ 0
+ ],
+ [
+ 21181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 21467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 22896.1428571429,
+ 0,
+ 0
+ ],
+ [
+ 23181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 23467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 23753.2857142857,
+ 3,
+ 0
+ ],
+ [
+ 23896.1428571429,
+ 0,
+ 0
+ ],
+ [
+ 24181.8571428571,
+ 0,
+ 0
+ ],
+ [
+ 24467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 24610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 24896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 25181.8571428571,
+ 0,
+ 0
+ ],
+ [
+ 25467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 25753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 26039,
+ 3,
+ 0
+ ],
+ [
+ 26181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 26467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 26753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 26896.1428571429,
+ 0,
+ 0
+ ],
+ [
+ 27181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 27467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 27753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 28039,
+ 0,
+ 0
+ ],
+ [
+ 28324.7142857143,
+ 1,
+ 0
+ ],
+ [
+ 28467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 28753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 29039,
+ 1,
+ 0
+ ],
+ [
+ 29181.8571428571,
+ 0,
+ 0
+ ],
+ [
+ 29467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 29753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 30039,
+ 2,
+ 0
+ ],
+ [
+ 30324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 30610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 30753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 31039,
+ 1,
+ 0
+ ],
+ [
+ 31324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 31467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 31753.2857142857,
+ 3,
+ 0
+ ],
+ [
+ 32039,
+ 0,
+ 0
+ ],
+ [
+ 32324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 32610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 32896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 33039,
+ 0,
+ 0
+ ],
+ [
+ 33324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 33610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 33753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 34039,
+ 3,
+ 0
+ ],
+ [
+ 34324.7142857143,
+ 1,
+ 0
+ ],
+ [
+ 34610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 34896.1428571429,
+ 0,
+ 0
+ ],
+ [
+ 35181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 35324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 35610.4285714286,
+ 3,
+ 0
+ ],
+ [
+ 35896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 36039,
+ 2,
+ 0
+ ],
+ [
+ 36324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 36610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 36896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 37181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 37467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 37610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 37896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 38181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 38324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 38610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 38896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 39181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 39467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 39753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 39896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 40181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 40467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 40610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 40753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 40896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 41039,
+ 0,
+ 0
+ ],
+ [
+ 41181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 41467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 41753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 42039,
+ 0,
+ 0
+ ],
+ [
+ 42324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 42610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 42896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 43181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 43324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 43467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 43753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 44039,
+ 2,
+ 0
+ ],
+ [
+ 44324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 44610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 44896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 45181.8571428571,
+ 0,
+ 0
+ ],
+ [
+ 45467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 45610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 45753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 45896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 46039,
+ 0,
+ 0
+ ],
+ [
+ 46181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 46324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 46610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 46896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 47181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 47467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 47753.2857142857,
+ 3,
+ 0
+ ],
+ [
+ 48039,
+ 1,
+ 0
+ ],
+ [
+ 48324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 48610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 48896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 49181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 49467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 49753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 49896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 50039,
+ 0,
+ 0
+ ],
+ [
+ 50324.7142857143,
+ 1,
+ 0
+ ],
+ [
+ 50467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 50610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 50753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 50896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 51181.8571428571,
+ 0,
+ 0
+ ],
+ [
+ 51467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 51753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 52039,
+ 3,
+ 0
+ ],
+ [
+ 52324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 52396.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 52467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 52539,
+ 3,
+ 0
+ ],
+ [
+ 52610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 52896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 53181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 53467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 53753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 54039,
+ 2,
+ 0
+ ],
+ [
+ 54324.7142857143,
+ 0,
+ 285.71428571429
+ ],
+ [
+ 54610.4285714286,
+ 3,
+ 285.714285714283
+ ],
+ [
+ 54896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 55181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 55467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 55753.2857142857,
+ 3,
+ 0
+ ],
+ [
+ 56039,
+ 1,
+ 0
+ ],
+ [
+ 56324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 56610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 56896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 57181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 57467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 57753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 58039,
+ 1,
+ 0
+ ],
+ [
+ 58324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 58610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 58896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 59181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 59467.5714285714,
+ 0,
+ 571.428571428565
+ ],
+ [
+ 60039,
+ 3,
+ 0
+ ],
+ [
+ 60181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 60324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 60467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 60610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 60753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 60896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 61039,
+ 3,
+ 0
+ ],
+ [
+ 61181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 61324.7142857143,
+ 2,
+ 428.571428571435
+ ],
+ [
+ 61753.2857142857,
+ 1,
+ 571.428571428565
+ ],
+ [
+ 62324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 62467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 62610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 62753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 62896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 63039,
+ 3,
+ 0
+ ],
+ [
+ 63181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 63324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 63467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 63610.4285714286,
+ 2,
+ 428.571428571428
+ ],
+ [
+ 64039,
+ 0,
+ 571.428571428572
+ ],
+ [
+ 64610.4285714286,
+ 3,
+ 0
+ ],
+ [
+ 64753.2857142857,
+ 3,
+ 0
+ ],
+ [
+ 64896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 65039,
+ 3,
+ 0
+ ],
+ [
+ 65181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 65324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 65467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 65610.4285714286,
+ 3,
+ 0
+ ],
+ [
+ 65753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 65896.1428571429,
+ 0,
+ 428.57142857142
+ ],
+ [
+ 66324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 66467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 66610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 66753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 66896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 67039,
+ 1,
+ 0
+ ],
+ [
+ 67181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 67324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 67467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 67753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 67896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 68039,
+ 0,
+ 0
+ ],
+ [
+ 68181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 68324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 68610.4285714286,
+ 3,
+ 571.42857142858
+ ],
+ [
+ 69181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 69324.7142857143,
+ 1,
+ 0
+ ],
+ [
+ 69467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 69610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 69753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 69896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 70039,
+ 2,
+ 0
+ ],
+ [
+ 70181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 70324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 70467.5714285714,
+ 3,
+ 428.571428571435
+ ],
+ [
+ 70896.1428571429,
+ 0,
+ 571.428571428565
+ ],
+ [
+ 71467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 71610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 71753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 71896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 72039,
+ 2,
+ 0
+ ],
+ [
+ 72181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 72324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 72467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 72610.4285714286,
+ 3,
+ 0
+ ],
+ [
+ 72753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 72896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 73039,
+ 0,
+ 0
+ ],
+ [
+ 73181.8571428571,
+ 3,
+ 571.428571428565
+ ],
+ [
+ 73467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 73753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 73896.1428571429,
+ 0,
+ 0
+ ],
+ [
+ 74039,
+ 0,
+ 0
+ ],
+ [
+ 74181.8571428571,
+ 0,
+ 0
+ ],
+ [
+ 74324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 74467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 74610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 74753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 74896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 75039,
+ 2,
+ 0
+ ],
+ [
+ 75181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 75467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 75610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 75753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 75896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 76039,
+ 2,
+ 0
+ ],
+ [
+ 76181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 76324.7142857143,
+ 2,
+ 0
+ ],
+ [
+ 76467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 76610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 76753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 76896.1428571429,
+ 0,
+ 0
+ ],
+ [
+ 77039,
+ 2,
+ 0
+ ],
+ [
+ 77181.8571428571,
+ 1,
+ 571.428571428565
+ ],
+ [
+ 77253.2857142857,
+ 3,
+ 500
+ ],
+ [
+ 78896.1428571429,
+ 1,
+ 0
+ ],
+ [
+ 78896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 80039,
+ 1,
+ 0
+ ],
+ [
+ 80039,
+ 3,
+ 0
+ ],
+ [
+ 81181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 81181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 82324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 82896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 83467.5714285714,
+ 1,
+ 0
+ ],
+ [
+ 84039,
+ 3,
+ 0
+ ],
+ [
+ 84610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 84610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 84896.1428571429,
+ 0,
+ 0
+ ],
+ [
+ 84896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 85181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 85181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 85467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 85467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 85753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 85896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 86039,
+ 0,
+ 0
+ ],
+ [
+ 86181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 86324.7142857143,
+ 1,
+ 0
+ ],
+ [
+ 86467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 86610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 86753.2857142857,
+ 3,
+ 0
+ ],
+ [
+ 86896.1428571429,
+ 2,
+ 1142.85714285713
+ ],
+ [
+ 86967.5714285714,
+ 1,
+ 1071.42857142857
+ ],
+ [
+ 90324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 90610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 90753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 90896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 91181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 91467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 91610.4285714286,
+ 3,
+ 0
+ ],
+ [
+ 91753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 92039,
+ 1,
+ 0
+ ],
+ [
+ 92324.7142857143,
+ 1,
+ 0
+ ],
+ [
+ 92610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 92896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 93039,
+ 2,
+ 0
+ ],
+ [
+ 93181.8571428571,
+ 3,
+ 0
+ ],
+ [
+ 93467.5714285714,
+ 3,
+ 0
+ ],
+ [
+ 93753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 93896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 94039,
+ 0,
+ 0
+ ],
+ [
+ 94181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 94324.7142857143,
+ 0,
+ 0
+ ],
+ [
+ 94610.4285714286,
+ 0,
+ 0
+ ],
+ [
+ 94896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 95181.8571428571,
+ 2,
+ 0
+ ],
+ [
+ 95324.7142857143,
+ 1,
+ 0
+ ],
+ [
+ 95467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 95753.2857142857,
+ 2,
+ 0
+ ],
+ [
+ 96039,
+ 3,
+ 0
+ ],
+ [
+ 96181.8571428571,
+ 0,
+ 0
+ ],
+ [
+ 96324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 96610.4285714286,
+ 1,
+ 0
+ ],
+ [
+ 96896.1428571429,
+ 2,
+ 0
+ ],
+ [
+ 97181.8571428571,
+ 0,
+ 0
+ ],
+ [
+ 97467.5714285714,
+ 0,
+ 0
+ ],
+ [
+ 97753.2857142857,
+ 1,
+ 0
+ ],
+ [
+ 98039,
+ 2,
+ 0
+ ],
+ [
+ 98324.7142857143,
+ 3,
+ 0
+ ],
+ [
+ 98610.4285714286,
+ 2,
+ 0
+ ],
+ [
+ 98896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 99181.8571428571,
+ 1,
+ 0
+ ],
+ [
+ 99467.5714285714,
+ 2,
+ 0
+ ],
+ [
+ 99753.2857142857,
+ 0,
+ 0
+ ],
+ [
+ 99896.1428571429,
+ 3,
+ 0
+ ],
+ [
+ 100039,
+ 0,
+ 0
+ ],
+ [
+ 100324.714285714,
+ 0,
+ 0
+ ],
+ [
+ 100610.428571429,
+ 1,
+ 0
+ ],
+ [
+ 100753.285714286,
+ 2,
+ 0
+ ],
+ [
+ 100896.142857143,
+ 1,
+ 0
+ ],
+ [
+ 101181.857142857,
+ 2,
+ 0
+ ],
+ [
+ 101467.571428571,
+ 2,
+ 0
+ ],
+ [
+ 101753.285714286,
+ 3,
+ 0
+ ],
+ [
+ 102039,
+ 1,
+ 0
+ ],
+ [
+ 102181.857142857,
+ 2,
+ 0
+ ],
+ [
+ 102324.714285714,
+ 1,
+ 0
+ ],
+ [
+ 102610.428571429,
+ 1,
+ 0
+ ],
+ [
+ 102896.142857143,
+ 3,
+ 0
+ ],
+ [
+ 103039,
+ 0,
+ 0
+ ],
+ [
+ 103181.857142857,
+ 3,
+ 0
+ ],
+ [
+ 103324.714285714,
+ 0,
+ 0
+ ],
+ [
+ 103467.571428571,
+ 3,
+ 0
+ ],
+ [
+ 103753.285714286,
+ 3,
+ 0
+ ],
+ [
+ 104039,
+ 0,
+ 0
+ ],
+ [
+ 104324.714285714,
+ 2,
+ 0
+ ],
+ [
+ 104467.571428571,
+ 1,
+ 0
+ ],
+ [
+ 104610.428571429,
+ 2,
+ 0
+ ],
+ [
+ 104896.142857143,
+ 2,
+ 0
+ ],
+ [
+ 105181.857142857,
+ 0,
+ 0
+ ],
+ [
+ 105324.714285714,
+ 1,
+ 0
+ ],
+ [
+ 105467.571428571,
+ 0,
+ 0
+ ],
+ [
+ 105610.428571429,
+ 1,
+ 0
+ ],
+ [
+ 105753.285714286,
+ 2,
+ 0
+ ],
+ [
+ 105896.142857143,
+ 3,
+ 0
+ ],
+ [
+ 106039,
+ 2,
+ 0
+ ],
+ [
+ 106181.857142857,
+ 3,
+ 0
+ ],
+ [
+ 106324.714285714,
+ 0,
+ 0
+ ],
+ [
+ 106467.571428571,
+ 2,
+ 0
+ ],
+ [
+ 106610.428571429,
+ 0,
+ 0
+ ],
+ [
+ 106753.285714286,
+ 2,
+ 0
+ ],
+ [
+ 106896.142857143,
+ 1,
+ 0
+ ],
+ [
+ 107039,
+ 3,
+ 0
+ ],
+ [
+ 107181.857142857,
+ 1,
+ 0
+ ],
+ [
+ 107324.714285714,
+ 3,
+ 0
+ ],
+ [
+ 107467.571428571,
+ 2,
+ 1142.85714285713
+ ],
+ [
+ 108610.428571429,
+ 3,
+ 571.42857142858
+ ],
+ [
+ 109181.857142857,
+ 0,
+ 571.428571428565
+ ],
+ [
+ 109753.285714286,
+ 2,
+ 285.71428571429
+ ],
+ [
+ 110039,
+ 1,
+ 285.71428571429
+ ],
+ [
+ 110324.714285714,
+ 2,
+ 285.714285714275
+ ],
+ [
+ 110610.428571429,
+ 0,
+ 285.714285714304
+ ],
+ [
+ 110896.142857143,
+ 1,
+ 571.428571428565
+ ],
+ [
+ 111467.571428571,
+ 2,
+ 285.714285714275
+ ],
+ [
+ 111753.285714286,
+ 1,
+ 285.71428571429
+ ],
+ [
+ 112039,
+ 0,
+ 571.428571428565
+ ],
+ [
+ 112610.428571429,
+ 3,
+ 571.42857142858
+ ],
+ [
+ 113181.857142857,
+ 1,
+ 2285.71428571429
+ ],
+ [
+ 115467.571428571,
+ 0,
+ 0
+ ]
+ ],
+ "bpm": 210,
+ "sectionBeats": 4,
+ "changeBPM": false,
+ "mustHitSection": true
+ }
+ ],
+ "validScore": true,
+ "gfVersion": "gf",
+ "bpm": 210,
+ "needsVoices": false,
+ "notITG": true,
+ "song": "C18H27NO3",
+ "sleHUD": true
+ }
+}
\ No newline at end of file
diff --git a/example_mods/C18H27NO3/data/songs/c18h27no3/modchart.json b/example_mods/C18H27NO3/data/songs/c18h27no3/modchart.json
new file mode 100644
index 0000000..92ddc17
--- /dev/null
+++ b/example_mods/C18H27NO3/data/songs/c18h27no3/modchart.json
@@ -0,0 +1,1526 @@
+{
+ "modifiers": [
+ [
+ "PosX",
+ "XModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "PosY",
+ "YModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "PosYD",
+ "YDModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "PosZ",
+ "ZModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Confusion",
+ "ConfusionModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "SkewX",
+ "SkewXModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "DrunkX",
+ "DrunkXModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "DrunkZ",
+ "DrunkZModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "TipsyY",
+ "TipsyYModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "TipsyZ",
+ "TipsyZModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Reverse",
+ "ReverseModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Speed",
+ "SpeedModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "StrumAngle",
+ "StrumAngleModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "StrumLineRotate",
+ "StrumLineRotateModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "SlushiX",
+ "BeatXModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "IncomingAngle",
+ "IncomingAngleModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "InvertSine",
+ "InvertSineModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Boost",
+ "BoostModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Brake",
+ "BrakeModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Boomerang",
+ "BoomerangModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Tornado",
+ "TornadoModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Invert",
+ "InvertModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Flip",
+ "FlipModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "EaseX",
+ "EaseXModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "ShakyNotes",
+ "ShakyNotesModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "AlphaOpo",
+ "AlphaModifier",
+ "Opponent",
+ -1,
+ -1
+ ],
+ [
+ "AlphaPF1",
+ "AlphaModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "AlphaPF2",
+ "AlphaModifier",
+ "Player",
+ 2,
+ -1
+ ],
+ [
+ "AlphaPF0",
+ "AlphaModifier",
+ "Player",
+ 0,
+ -1
+ ],
+ [
+ "Wavering",
+ "WaveingModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "BounceZ",
+ "BounceZModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Dizzy",
+ "DizzyModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "PosXPF1",
+ "XModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "PosYDPF1",
+ "YDModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "PosZPF1",
+ "ZModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "EaseXPF1",
+ "EaseXModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "EaseXPF0",
+ "EaseXModifier",
+ "Player",
+ 0,
+ -1
+ ],
+ [
+ "InvertSineZ",
+ "InvertSineZModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "Hidden",
+ "HiddenModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "laneAlpha",
+ "TargetAlphaModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "Sudden",
+ "SuddenModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "SpeedPF1",
+ "SpeedModifier",
+ "Player",
+ 1,
+ -1
+ ],
+ [
+ "noteAlphaPF0",
+ "NoteAlphaModifier",
+ "Player",
+ 0,
+ -1
+ ],
+ [
+ "ReversePF0",
+ "ReverseModifier",
+ "Player",
+ 0,
+ -1
+ ],
+ [
+ "BounceX",
+ "BounceXModifier",
+ "Player",
+ -1,
+ -1
+ ],
+ [
+ "EaseXPF2",
+ "EaseXModifier",
+ "Player",
+ 2,
+ -1
+ ],
+ [
+ "PosYDPF0",
+ "YDModifier",
+ "Player",
+ 0,
+ -1
+ ],
+ [
+ "PosYDPF2",
+ "YDModifier",
+ "Player",
+ 0,
+ -1
+ ],
+ [
+ "Alpha",
+ "AlphaModifier",
+ "Player",
+ -1,
+ -1
+ ]
+ ],
+ "playfields": 3,
+ "events": [
+ [
+ "ease",
+ [
+ 0,
+ "0",
+ "cubeInOut",
+ "1,AlphaOpo,1,AlphaPF1,1,AlphaPF2"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 0.25,
+ "0",
+ "cubeInOut",
+ "-315,PosX,-270,PosY,90,IncomingAngle:x,-130,IncomingAngle:y,1,Wavering,2,Boomerang,-0.5,InvertSine,,,400,PosZ,-4,BounceZ,0.5,BounceZ:speed,1,AlphaPF0,3,TipsyZ:speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 37.25,
+ "5",
+ "cubeInOut",
+ "0,PosZ,0,AlphaPF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 40.75,
+ "1",
+ "cubeInOut",
+ "0.8,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 56.5,
+ "1",
+ "cubeInOut",
+ "2,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 60,
+ "1",
+ "cubeInOut",
+ "4,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 49,
+ "1",
+ "cubeInOut",
+ "1.5,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 61.75,
+ "1",
+ "cubeInOut",
+ "5,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 64.25,
+ "1",
+ "cubeInOut",
+ "7,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 66.25,
+ "1",
+ "cubeInOut",
+ "9,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 68.5,
+ "1",
+ "cubeInOut",
+ "11,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 73.25,
+ "1",
+ "cubeInOut",
+ "13,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 73.25,
+ "3",
+ "backInOut",
+ "360,Confusion,0,Dizzy"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 77,
+ "3",
+ "backInOut",
+ "0,Confusion,360,StrumLineRotate:x,0,PosY,1,Reverse,0,Boomerang,0,InvertSine,0,IncomingAngle:y,,,0,TipsyZ,0,BounceZ,0,Wavering"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 42.75,
+ "1",
+ "cubeInOut",
+ "0.1,Dizzy"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 80.25,
+ 1,
+ "cubeInOut",
+ "1,SlushiX,0.4,InvertSine,0.6,DrunkX"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 110,
+ "1.8",
+ "circOutIn",
+ "360,SkewX,0,StrumLineRotate:x,360,Confusion"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 126.25,
+ "1.8",
+ "circOutIn",
+ "0,SkewX,0,StrumLineRotate:x,0,Confusion,0,Reverse,,"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 136.25,
+ "1.8",
+ "backInOut",
+ "20,SkewX,20,IncomingAngle:y"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 131.5,
+ "0",
+ "backInOut",
+ "0,IncomingAngle:y,0,IncomingAngle:x"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 137.75,
+ "1.8",
+ "backInOut",
+ "-20,SkewX,-20,IncomingAngle:y"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 140.25,
+ "1.8",
+ "circInOut",
+ "360,SkewX,360,IncomingAngle:y,1,Reverse"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 142.5,
+ "0.7",
+ "circInOut",
+ "6,BounceZ,14,BounceZ:speed,12,ShakyNotes:speed,6,ShakyNotes"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 144.25,
+ "0.7",
+ "circInOut",
+ "0,BounceZ,0,BounceZ:speed,0,ShakyNotes"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 79.5,
+ 1,
+ "cubeInOut",
+ "2,DrunkX:speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 144.5,
+ "0.7",
+ "circInOut",
+ "-450,PosZPF1,0,AlphaPF1,-30,PosYD,10,EaseXPF1,7,EaseXPF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 144,
+ "0.7",
+ "circInOut",
+ "4,EaseXPF1:speed,6,EaseXPF0:speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 174.5,
+ "0.7",
+ "circInOut",
+ "10,StrumLineRotate:y"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 172.75,
+ "0",
+ "circInOut",
+ "0,IncomingAngle:x,0,IncomingAngle:y"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 175.75,
+ "0.7",
+ "circInOut",
+ "-10,StrumLineRotate:y"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 176.25,
+ "2",
+ "circInOut",
+ "360,StrumLineRotate:y"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 190.25,
+ "1",
+ "circInOut",
+ "-30,StrumLineRotate:x,,"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 191,
+ "1",
+ "circInOut",
+ "360,StrumLineRotate:x,,"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 200.25,
+ "1",
+ "circInOut",
+ "0.5,Speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 201.5,
+ "1",
+ "circInOut",
+ "1,Speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 204,
+ "1",
+ "circInOut",
+ "1.3,Speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 206.25,
+ "1",
+ "circInOut",
+ "0.7,Speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 208,
+ "1",
+ "circInOut",
+ "1.5,Speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 208.5,
+ "2",
+ "backInOut",
+ "1,Speed,0,StrumLineRotate:x,0,SlushiX,0,InvertSine,0,EaseXPF0,0,EaseXPF1,0,PosZPF1,1,AlphaPF1,0,DrunkX"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 212.25,
+ "0",
+ "backInOut",
+ "40,StrumLineRotate:x,10,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 212.25,
+ "2",
+ "backInOut",
+ "0,StrumLineRotate:x,0,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 220.25,
+ "0",
+ "backInOut",
+ "-40,StrumLineRotate:x,10,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 220.25,
+ "2",
+ "backInOut",
+ "0,StrumLineRotate:x,0,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 228.25,
+ "0",
+ "backInOut",
+ "40,StrumLineRotate:x,-10,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 228.25,
+ "2",
+ "backInOut",
+ "0,StrumLineRotate:x,0,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 244.25,
+ "0",
+ "backInOut",
+ "-40,StrumLineRotate:x,-10,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 244.25,
+ "2",
+ "backInOut",
+ "0,StrumLineRotate:x,0,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 252.25,
+ "0",
+ "backInOut",
+ "40,StrumLineRotate:x,-10,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 252.25,
+ "2",
+ "backInOut",
+ "0,StrumLineRotate:x,0,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 260.25,
+ "0",
+ "backInOut",
+ "-40,StrumLineRotate:x,-10,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 260.25,
+ "2",
+ "backInOut",
+ "0,StrumLineRotate:x,0,InvertSineZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 238,
+ "0.3",
+ "cubeInOut",
+ "3,BounceZ,20,BounceZ:speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 240.25,
+ "2",
+ "cubeInOut",
+ "0,BounceZ,0,BounceZ:speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 264,
+ "2",
+ "cubeInOut",
+ "3,ShakyNotes"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 272,
+ "2",
+ "cubeInOut",
+ "0,ShakyNotes,-120,PosZ,,"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 272.75,
+ "0",
+ "backInOut",
+ "-270,PosYDPF1,0,AlphaPF1,1,laneAlpha,1,noteAlphaPF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 273,
+ "0",
+ "backInOut",
+ "0.3,Hidden:start,4,Hidden:end,-0.2,Hidden:offset,22,Hidden,0.01,SpeedPF1"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 273.25,
+ "2",
+ "backInOut",
+ "2,TipsyZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 275.5,
+ "2",
+ "expoInOut",
+ "1,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 279.5,
+ "2",
+ "expoInOut",
+ "0,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 283.75,
+ "2",
+ "expoInOut",
+ "1,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 287.75,
+ "2",
+ "expoInOut",
+ "0,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 289.25,
+ "2",
+ "expoInOut",
+ "1,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 291.5,
+ "2",
+ "expoInOut",
+ "0,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 293.75,
+ "2",
+ "expoInOut",
+ "1,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 297,
+ "1",
+ "expoInOut",
+ "1,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 298.25,
+ "1",
+ "expoInOut",
+ "0,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 295.99078125,
+ "1.3",
+ "expoInOut",
+ "0,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 299,
+ "1",
+ "expoInOut",
+ "1,ReversePF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 299.5,
+ "1",
+ "expoInOut",
+ "0,noteAlphaPF0,1,AlphaPF1"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 304.5,
+ "4",
+ "backInOut",
+ "3,InvertSineZ,3,InvertSine,-2,Boomerang,-360,IncomingAngle:y,1,Reverse,0,ReversePF0,0,PosYDPF1"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 308,
+ "1",
+ "expoInOut",
+ "0,InvertSineZ,0,InvertSine,0,Boomerang,0,Tornado,0,Boomerang,0,TipsyZ,0,PosZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 303.5,
+ "1",
+ "expoInOut",
+ "3,InvertSineZ,90,IncomingAngle:x"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 316,
+ "1",
+ "expoInOut",
+ "-180,PosZ,-250,PosYDPF1,-140,PosYDPF2,40,PosYDPF0"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 316.25,
+ "1",
+ "expoInOut",
+ "0.3,AlphaPF2,0.2,AlphaPF1"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 315.75,
+ "1",
+ "expoInOut",
+ "0,Hidden,1,SpeedPF1,0,laneAlpha"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 316.5,
+ "1",
+ "expoInOut",
+ "9,EaseXPF1,8,EaseXPF1:speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 316.5,
+ "1",
+ "expoInOut",
+ "9,EaseXPF0,6,EaseXPF0:speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 316.5,
+ "1",
+ "expoInOut",
+ "9,EaseXPF2,10,EaseXPF2:speed"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 380.5,
+ "1",
+ "expoInOut",
+ "0,AlphaPF2,0,AlphaPF1,0,PosYDPF1,0,PosYDPF0,0,PosYDPF2,0,EaseXPF1,0,EaseXPF2,0,EaseXPF0,-270,PosYD,0.5,Flip"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 380.5,
+ "1",
+ "expoInOut",
+ "120,IncomingAngle:y,1,Boomerang,1,Tornado,-5,InvertSine,-4,InvertSineZ,2,BounceZ,0.2,BounceZ:speed,1,Brake"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 404.75,
+ "5",
+ "expoInOut",
+ "1,Alpha"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 399.5,
+ "3",
+ "backOutIn",
+ "-400,PosZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ],
+ [
+ "ease",
+ [
+ 404.25,
+ "1",
+ "backOutIn",
+ "0,PosZ"
+ ],
+ [
+ false,
+ 1,
+ 1
+ ]
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/example_mods/C18H27NO3/data/weeks/c18h27no3.json b/example_mods/C18H27NO3/data/weeks/c18h27no3.json
new file mode 100644
index 0000000..72d719c
--- /dev/null
+++ b/example_mods/C18H27NO3/data/weeks/c18h27no3.json
@@ -0,0 +1 @@
+{"songs":[["C18H27NO3","gf",[0,0,0]]],"hideFreeplay":false,"difficulties":"slushi","storyName":"","weekName":"c18h27no3-week","freeplayColor":[0,0,0],"hideStoryMode":true,"weekBefore":"none","startUnlocked":true,"blockOpponentMode":true}
\ No newline at end of file
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode1.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode1.png
new file mode 100644
index 0000000..1a93d92
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode1.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode10.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode10.png
new file mode 100644
index 0000000..3d43d4e
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode10.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode2.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode2.png
new file mode 100644
index 0000000..66f8c11
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode2.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode3.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode3.png
new file mode 100644
index 0000000..6d92314
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode3.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode4.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode4.png
new file mode 100644
index 0000000..82fa224
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode4.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode5.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode5.png
new file mode 100644
index 0000000..0b6b7cb
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode5.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode6.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode6.png
new file mode 100644
index 0000000..dfd6da4
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode6.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode7.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode7.png
new file mode 100644
index 0000000..76144a0
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode7.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode8.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode8.png
new file mode 100644
index 0000000..20cfef3
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode8.png differ
diff --git a/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode9.png b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode9.png
new file mode 100644
index 0000000..46b582a
Binary files /dev/null and b/example_mods/C18H27NO3/images/slushiSongs/c18h27no3/slushiCodes/slushiCode9.png differ
diff --git a/example_mods/C18H27NO3/scripts/songs/c18h27no3/modchart.lua b/example_mods/C18H27NO3/scripts/songs/c18h27no3/modchart.lua
new file mode 100644
index 0000000..7fc4a20
--- /dev/null
+++ b/example_mods/C18H27NO3/scripts/songs/c18h27no3/modchart.lua
@@ -0,0 +1,369 @@
+-- Generated by StepMania to FNF Converter v1.3.5 (By Slushi) --
+
+function onCreatePost()
+ startGDIThread(); -- :3
+ prepareGDIEffect("ScreenGlitches", 0);
+
+ resizableWindow(false);
+ addShader3DToNotes();
+ initShaderFromSource("chromAB", "ChromAbBlueSwapEffect");
+ initShaderFromSource("threeShader", "ThreeDEffect");
+ initShaderFromSource("glitch", "GlitchedEffect");
+ initShaderFromSource("mosaic", "MosaicEffect");
+ initShaderFromSource("angel", "AngelEffect");
+ initShaderFromSource("individualGlitches", "IndividualGlitchesEffect");
+
+ setCameraShader(camNoteStuff, "chromAB");
+ setCameraShader(camSLEHUD, "chromAB");
+ setCameraShader(camThings2, "chromAB");
+ setCameraShader(camWaterMark, "chromAB");
+
+ setCameraShader(camSLEHUD, "threeShader");
+ setCameraShader(camThings2, "threeShader");
+ setCameraShader(camWaterMark, "threeShader");
+
+ setCameraShader(camNoteStuff, "mosaic");
+ setCameraShader(camSLEHUD, "mosaic");
+ setCameraShader(camThings2, "mosaic");
+ setCameraShader(camWaterMark, "mosaic");
+
+ setCameraShader(camNoteStuff, "angel");
+ setCameraShader(camSLEHUD, "angel");
+ setCameraShader(camThings2, "angel");
+ setCameraShader(camWaterMark, "angel");
+
+ setProperty('camZooming', false);
+ setProperty('healthBar.visible', false);
+ setProperty('healthBarBG.visible', false);
+ setProperty('scoreTxtSprite.visible', false);
+ setProperty('scoreTxt.visible', false);
+ setProperty('timeBar.visible', false);
+ setProperty('timeBarBG.visible', false);
+ setProperty('timeTxt.visible', false);
+ setProperty('camGame.visible', false);
+ setProperty('camHUD.visible', false);
+ tweenObjectFromSLEHUD("BLACKALPHA", 1, 0.1, "linear");
+ setProperty('camSLEHUD.alpha', 0);
+ setProperty('camThings2.alpha', 0);
+ setPropertyFromClass("slushi.slushiUtils.SlushiEngineHUD", "instance.slushiSprite.visible", false);
+
+ makeLuaText("mtModsText", "TEST", 0, 0.0, 0.0);
+ setTextFont("mtModsText", "vcr.ttf");
+ setTextSize("mtModsText", 16);
+ setScrollFactor("mtModsText", 0.0, 0.0)
+ setTextAlignment("mtModsText", "CENTER");
+ screenCenter("mtModsText", "XY");
+ addLuaText("mtModsText");
+ setObjectCamera("mtModsText", camThings2);
+ setProperty("mtModsText.y", getProperty("mtModsText.y") + 60);
+
+ for i = 1, 10 do
+ makeLuaSprite("slushiCodeImage" .. i, "slushiSongs/c18h27no3/slushiCodes/slushiCode" .. i, 0, 0);
+ screenCenter("slushiCodeImage" .. i, "XY");
+ addLuaSprite("slushiCodeImage" .. i, false);
+ setObjectCamera("slushiCodeImage" .. i, camThings);
+ setProperty("slushiCodeImage" .. i .. ".alpha", 0);
+ end
+end
+
+local beat = 0;
+local useNegative = false;
+function onBeatHit()
+ beat = curBeat;
+ if curBeat >= 12 and curBeat <= 44 then
+ if curBeat % 4 == 0 then
+ useNegative = not useNegative;
+ local randomNumber = getRandomInt(1, 10);
+ local randomNumber2 = getRandomInt(0, 256);
+ local randomNumber3 = getRandomInt(350, 450);
+ startTween("tweenSLImgTween1A" .. randomNumber2, "slushiCodeImage" .. randomNumber, { alpha = 1 }, 1,
+ { ease = "linear" });
+ setProperty("slushiCodeImage" .. randomNumber .. ".y",
+ getProperty("slushiCodeImage" .. randomNumber .. ".y") + 420);
+ if useNegative then
+ setProperty("slushiCodeImage" .. randomNumber .. ".x",
+ getProperty("slushiCodeImage" .. randomNumber .. ".x") - randomNumber3);
+ else
+ setProperty("slushiCodeImage" .. randomNumber .. ".x",
+ getProperty("slushiCodeImage" .. randomNumber .. ".x") + randomNumber3);
+ end
+ setProperty("slushiCodeImage" .. randomNumber .. ".angle", 5);
+ startTween("tweenSLImgTween2A" .. randomNumber2, "slushiCodeImage" .. randomNumber, { y = -1200 }, 8,
+ { ease = "linear" });
+ end
+ end
+
+ if curBeat == 60 then
+ tweenShaderFloat("chromABTweenA", "chromAB", "strength", 0.005, 1, "linear");
+ end
+
+ if curBeat == 62 then
+ tweenShaderFloat("chromABTween2", "chromAB", "strength", -0.005, 1, "linear");
+ end
+
+ if curBeat == 64 then
+ tweenShaderFloat("chromABTween3", "chromAB", "strength", 0.005, 1, "linear");
+ end
+
+ if curBeat == 66 then
+ tweenShaderFloat("chromABTween4", "chromAB", "strength", -0.005, 1, "linear");
+ end
+
+ if curBeat == 68 then
+ tweenShaderFloat("chromABTween5", "chromAB", "strength", 0.010, 1, "linear");
+ end
+
+ if curBeat == 73 then
+ tweenShaderFloat("chromABTween6", "chromAB", "strength", 0, 2, "elasticInOut");
+ end
+
+ if curBeat == 78 then
+ setProperty("camSLEHUD.zoom", getProperty("camSLEHUD.zoom") + 15);
+ setProperty("camSLEHUD.angle", 10);
+ setProperty('camSLEHUD.alpha', 1);
+
+ setProperty("camThings2.zoom", getProperty("camThings2.zoom") + 15);
+ setProperty("camThings2.angle", 10);
+ setProperty('camThings2.alpha', 1);
+ tweenObjectFromSLEHUD("BLACKALPHA", 0.8, 1.5, "linear");
+ startTween("camTween", "camSLEHUD", { zoom = 1 }, 1, { ease = "linear" });
+ startTween("camTween2", "camSLEHUD", { angle = 0 }, 1, { ease = "linear" });
+ startTween("camTween3", "camThings2", { zoom = 1 }, 1, { ease = "linear" });
+ startTween("camTween4", "camThings2", { angle = 0 }, 1, { ease = "linear" });
+ end
+
+ if curBeat >= 80 and curBeat <= 144 then
+ if curBeat % 2 == 0 then
+ setWindowPos("X", getWindowPos("X") - 20);
+ doTweenWinPos("X", "windowTween1", getWindowPos("X") + 20, 0.2, "linear");
+
+ setWindowPos("Y", getWindowPos("Y") - 20);
+ doTweenWinPos("Y", "windowTween2", getWindowPos("Y") + 20, 0.2, "linear");
+ else
+ setWindowPos("X", getWindowPos("X") + 20);
+ doTweenWinPos("X", "windowTween3", getWindowPos("X") - 20, 0.2, "linear");
+
+ setWindowPos("Y", getWindowPos("Y") + 20);
+ doTweenWinPos("Y", "windowTween4", getWindowPos("Y") - 20, 0.2, "linear");
+ end
+ end
+
+ if curBeat == 110 then
+ tweenShaderFloat("mosaicTween", "mosaic", "strength", 0, 1, "circoutin", 8);
+ end
+
+ if curBeat == 126 then
+ tweenShaderFloat("mosaicTween2", "mosaic", "strength", 0, 1, "circoutin", 8);
+ end
+
+ if curBeat == 136 then
+ tweenShaderFloat("mosaicTween3", "mosaic", "strength", 6, 0.6, "backinout");
+ end
+
+ if curBeat == 137 then
+ tweenShaderFloat("mosaicTween4", "mosaic", "strength", -6, 0.6, "backinout");
+ end
+
+ if curBeat == 140 then
+ tweenShaderFloat("mosaicTween5", "mosaic", "strength", 0, 0.6, "backinout");
+ end
+
+ if curBeat == 144 then
+ setCameraShader(camNoteStuff, "individualGlitches");
+ setCameraShader(camSLEHUD, "individualGlitches");
+ setCameraShader(camThings2, "individualGlitches");
+ setCameraShader(camWaterMark, "individualGlitches");
+ tweenShaderFloat("individualGlitchesTween", "individualGlitches", "binaryIntensity", 0.2, 0.6, "linear");
+ end
+
+ if curBeat == 208 then
+ removeCameraShader(camNoteStuff, "individualGlitches");
+ removeCameraShader(camSLEHUD, "individualGlitches");
+ removeCameraShader(camThings2, "individualGlitches");
+ removeCameraShader(camWaterMark, "individualGlitches");
+ startTween("camTween1", "camSLEHUD", { angle = 0 }, 0.8, { ease = "linear" });
+ startTween("camTween2", "camThings2", { angle = 0 }, 0.8, { ease = "linear" });
+ startTween("camTween3", "camWaterMark", { angle = 0 }, 0.8, { ease = "linear" });
+ centerWindowTween("centerWindowTween", 0.8, "linear");
+ end
+
+ if curBeat == 212 then
+ tweenShaderFloat("chromABTween7", "chromAB", "strength", 0, 1, "linear", -0.015);
+ tweenShaderFloat("threeShaderTween2", "threeShader", "yrot", 0, 0.6, "linear", -0.4);
+ setNotesShader3DProperty("yrot", 0.4);
+ doTweenNotesShader3D("y", "threeShaderTween4", 0, 0.6, "linear");
+ setWindowPos("X", getWindowPos("X") - 20);
+ doTweenWinPos("X", "windowTween1", getWindowPos("X") + 20, 0.2, "linear");
+ setDesktopWindowsPos("X", getDesktopWindowsPos("X") - 40);
+ doTweenDesktopWindowsPos("X", getDesktopWindowsPos("X") + 40, 0.2, "linear");
+ end
+ if curBeat == 220 then
+ tweenShaderFloat("chromABTween8", "chromAB", "strength", 0, 1, "linear", 0.015);
+ tweenShaderFloat("threeShaderTween3", "threeShader", "yrot", 0, 0.6, "linear", 0.4);
+ setNotesShader3DProperty("yrot", -0.4);
+ doTweenNotesShader3D("y", "threeShaderTween5", 0, 0.6, "linear");
+ setWindowPos("X", getWindowPos("X") + 20)
+ doTweenWinPos("X", "windowTween2", getWindowPos("X") - 20, 0.2, "linear");
+ setDesktopWindowsPos("X", getDesktopWindowsPos("X") + 40);
+ doTweenDesktopWindowsPos("X", getDesktopWindowsPos("X") - 40, 0.2, "linear");
+ end
+ if curBeat == 228 then
+ tweenShaderFloat("chromABTween7", "chromAB", "strength", 0, 1, "linear", -0.015);
+ tweenShaderFloat("threeShaderTween4", "threeShader", "xrot", 0, 0.6, "linear", -0.4);
+ setNotesShader3DProperty("xrot", 0.4);
+ doTweenNotesShader3D("x", "threeShaderTween6", 0, 0.6, "linear");
+ setWindowPos("Y", getWindowPos("Y") - 20);
+ doTweenWinPos("Y", "windowTween3", getWindowPos("Y") + 20, 0.2, "linear");
+ setDesktopWindowsPos("Y", getDesktopWindowsPos("Y") - 40);
+ doTweenDesktopWindowsPos("Y", getDesktopWindowsPos("Y") + 40, 0.2, "linear");
+ end
+ if curBeat == 240 then
+ tweenShaderFloat("chromABTween8", "chromAB", "strength", 0, 1, "linear", 0.015);
+ tweenShaderFloat("threeShaderTween5", "threeShader", "xrot", 0, 0.6, "linear", 0.4);
+ setNotesShader3DProperty("xrot", -0.4);
+ doTweenNotesShader3D("x", "threeShaderTween7", 0, 0.6, "linear");
+ setWindowPos("Y", getWindowPos("Y") + 20);
+ doTweenWinPos("Y", "windowTween4", getWindowPos("Y") - 20, 0.2, "linear");
+ setDesktopWindowsPos("Y", getDesktopWindowsPos("Y") + 40);
+ doTweenDesktopWindowsPos("Y", getDesktopWindowsPos("Y") - 40, 0.2, "linear");
+ end
+ if curBeat == 244 then
+ tweenShaderFloat("chromABTween7", "chromAB", "strength", 0, 1, "linear", -0.015);
+ tweenShaderFloat("threeShaderTween6", "threeShader", "zrot", 0, 0.6, "linear", -0.4);
+ setNotesShader3DProperty("zrot", 0.4);
+ doTweenNotesShader3D("z", "threeShaderTween8", 0, 0.6, "linear");
+ setWindowPos("X", getWindowPos("X") - 20);
+ setWindowPos("Y", getWindowPos("Y") - 20);
+ doTweenWinPos("X", "windowTween5", getWindowPos("X") + 20, 0.2, "linear");
+ doTweenWinPos("Y", "windowTween6", getWindowPos("Y") + 20, 0.2, "linear");
+ setDesktopWindowsPos("X", getDesktopWindowsPos("X") - 40);
+ setDesktopWindowsPos("Y", getDesktopWindowsPos("Y") - 40);
+ doTweenDesktopWindowsPos("X", getDesktopWindowsPos("X") + 40, 0.2, "linear");
+ doTweenDesktopWindowsPos("Y", getDesktopWindowsPos("Y") + 40, 0.2, "linear");
+ end
+ if curBeat == 252 then
+ tweenShaderFloat("chromABTween7", "chromAB", "strength", 0, 1, "linear", 0.015);
+ tweenShaderFloat("threeShaderTween7", "threeShader", "zrot", 0, 0.6, "linear", 0.4);
+ setNotesShader3DProperty("zrot", -0.4);
+ doTweenNotesShader3D("z", "threeShaderTween9", 0, 0.6, "linear");
+ setWindowPos("X", getWindowPos("X") + 20);
+ setWindowPos("Y", getWindowPos("Y") + 20);
+ doTweenWinPos("X", "windowTween7", getWindowPos("X") - 20, 0.2, "linear");
+ doTweenWinPos("Y", "windowTween8", getWindowPos("Y") - 20, 0.2, "linear");
+ setDesktopWindowsPos("X", getDesktopWindowsPos("X") + 40);
+ setDesktopWindowsPos("Y", getDesktopWindowsPos("Y") + 40);
+ doTweenDesktopWindowsPos("X", getDesktopWindowsPos("X") - 40, 0.2, "linear");
+ doTweenDesktopWindowsPos("Y", getDesktopWindowsPos("Y") - 40, 0.2, "linear");
+ end
+ if curBeat == 260 then
+ tweenShaderFloat("chromABTween7", "chromAB", "strength", 0, 1, "linear", -0.015);
+ tweenShaderFloat("threeShaderTween8", "threeShader", "yrot", 0, 0.6, "linear", -0.4);
+ setNotesShader3DProperty("yrot", 0.4);
+ doTweenNotesShader3D("y", "threeShaderTween8", 0, 0.6, "linear");
+ setWindowPos("X", getWindowPos("X") - 20)
+ doTweenWinPos("X", "windowTween8", getWindowPos("X") + 20, 0.2, "linear");
+ setDesktopWindowsPos("X", getDesktopWindowsPos("X") - 40);
+ doTweenDesktopWindowsPos("X", getDesktopWindowsPos("X") + 40, 0.2, "linear");
+ end
+
+ if curBeat == 272 then
+ setCameraShader(camNoteStuff, "individualGlitches");
+ setCameraShader(camSLEHUD, "individualGlitches");
+ setCameraShader(camThings2, "individualGlitches");
+ setCameraShader(camWaterMark, "individualGlitches");
+ tweenShaderFloat("individualGlitchesTween", "individualGlitches", "binaryIntensity", 0.2, 3, "linear");
+ tweenShaderFloat("angelTween", "angel", "strength", 0.4, 0.6, "linear");
+ end
+
+ if curBeat == 275 or curBeat == 279 or curBeat == 283 or curBeat == 287 or curBeat == 289 or curBeat == 291 or curBeat == 293 or curBeat == 295 or curBeat == 297 or curBeat == 298 or curBeat == 299 then
+ tweenShaderFloat("individualGlitchesTween", "individualGlitches", "binaryIntensity", 0, 0.6, "linear", 0.2);
+ tweenWindowBorderColor({255, 0, 0}, {0, 0, 0}, 0.6, "linear", false);
+ end
+
+ if curBeat == 308 then
+ setShaderProperty("individualGlitches", "binaryIntensity", 0.2);
+ setShaderProperty("angel", "strength", 0.4);
+ end
+
+ if curBeat == 316 then
+ removeCameraShader(camNoteStuff, "individualGlitches");
+ removeCameraShader(camSLEHUD, "individualGlitches");
+ removeCameraShader(camThings2, "individualGlitches");
+ removeCameraShader(camWaterMark, "individualGlitches");
+ setShaderProperty("angel", "strength", 0);
+
+ enableGDIEffect("ScreenGlitches", true);
+ hideTaskBar(true);
+ -- enableGDIEffect("DrawIcons", true);
+ -- enableGDIEffect("ScreenShake", true);
+ end
+
+ if curBeat >= 316 and curBeat <= 380 then
+ if curBeat % 2 == 0 then
+ setDesktopWindowsPos("X", getDesktopWindowsPos("X") - 40);
+ doTweenDesktopWindowsPos("X", getDesktopWindowsPos("X") + 40, 0.2, "linear");
+ tweenWindowBorderColor({255, 0, 0}, {0, 0, 0}, 0.3, "linear", false);
+ else
+ setDesktopWindowsPos("X", getDesktopWindowsPos("X") + 40);
+ doTweenDesktopWindowsPos("X", getDesktopWindowsPos("X") - 40, 0.2, "linear");
+ tweenWindowBorderColor({0, 0, 0}, {255, 0, 0}, 0.3, "linear", false);
+ end
+ end
+
+ if curBeat == 404 then
+ enableGDIEffect("ScreenGlitches", false);
+ end
+end
+
+function onStepHit()
+ if curStep >= 1250 and curStep < 1264 then
+ local screenWidth = getScreenSize("WIDTH")
+ local screenHeight = getScreenSize("HEIGHT")
+ local windowWidth = getWindowSize("WIDTH")
+ local windowHeight = getWindowSize("HEIGHT")
+ local maxX = screenWidth - windowWidth
+ local maxY = screenHeight - windowHeight
+
+ local randomX = getRandomInt(0, maxX)
+ local randomY = getRandomInt(0, maxY)
+
+ setWindowPos("X", randomX)
+ setWindowPos("Y", randomY)
+ end
+
+ if curStep == 1265 then
+ centerWindowTween("centerWindowTween2", 0.6, "linear");
+ end
+end
+
+local speed = 2
+local elapsedTime = 0
+local angleRange = 8
+
+local levitationSpeed = 1.6
+local levitationHeight = 0.4
+local elapsedTime2 = 0
+local initialWindowX = getWindowPos("X")
+
+function onUpdatePost(elapsed)
+ --[[
+ getMTCurrentModifiers() only exists because the same code that has that function in source, did not work in HScript
+ So.. New function to SLE's Lua API XD
+ ]]
+ setTextString("mtModsText", "Actual modifiers:\n" .. getMTCurrentModifiers(":"));
+ screenCenter("mtModsText", "X");
+
+ elapsedTime = elapsedTime + (elapsed * speed)
+ local angle = math.sin(elapsedTime) * angleRange
+
+ elapsedTime2 = elapsedTime2 + (elapsed * levitationSpeed)
+ local y = math.sin(elapsedTime2) * levitationHeight
+ setProperty("mtModsText.y", getProperty("mtModsText.y") + y);
+
+ if beat >= 144 and beat <= 208 then
+ setProperty("camSLEHUD.angle", angle);
+ setProperty("camWaterMark.angle", angle);
+ setProperty("camThings2.angle", angle);
+ setWindowPos("X", 300 * math.cos(elapsedTime) / 5 + initialWindowX);
+ end
+end
diff --git a/example_mods/C18H27NO3/songs/c18h27no3/Inst.ogg b/example_mods/C18H27NO3/songs/c18h27no3/Inst.ogg
new file mode 100644
index 0000000..9112129
Binary files /dev/null and b/example_mods/C18H27NO3/songs/c18h27no3/Inst.ogg differ
diff --git a/funkinscsource/Main.hx b/funkinscsource/Main.hx
index b696135..2f31672 100644
--- a/funkinscsource/Main.hx
+++ b/funkinscsource/Main.hx
@@ -53,8 +53,6 @@ class Main extends Sprite
// utils.logging.CrashHandler.queryStatus();
// #end
- // WindowsFuncs.initThreadForWindowRespondingHandler();
-
setupGame();
}
diff --git a/funkinscsource/codenameengine/scripting/Script.hx b/funkinscsource/codenameengine/scripting/Script.hx
index a5b5e0d..637c33b 100644
--- a/funkinscsource/codenameengine/scripting/Script.hx
+++ b/funkinscsource/codenameengine/scripting/Script.hx
@@ -112,14 +112,14 @@ class Script extends FlxBasic implements IFlxDestroyable
// Shaders
"ColorSwap" => shaders.ColorSwap,
// States
- "FreeplayState" => states.freeplay.FreeplayState,
+ "FreeplayState" => slushi.states.freeplay.SlushiFreeplayState,
"MainMenuState" => states.MainMenuState,
"PlayState" => states.PlayState,
"StoryMenuState" => states.StoryMenuState,
"TitleState" => states.TitleState,
// SubStates
"GameOverSubstate" => substates.GameOverSubstate,
- "PauseSubState" => substates.PauseSubState,
+ "PauseSubState" => slushi.substates.SlushiPauseSubState,
// External Usages For Engine
"Countdown" => backend.Countdown,
diff --git a/funkinscsource/debug/FPSCounter.hx b/funkinscsource/debug/FPSCounter.hx
index f8990e0..55b27d5 100644
--- a/funkinscsource/debug/FPSCounter.hx
+++ b/funkinscsource/debug/FPSCounter.hx
@@ -30,8 +30,6 @@ class FPSCounter extends TextField
public var taskMemoryMegas:Dynamic = 0;
- public static var currentTotalMemory:Dynamic = 0;
-
public var memoryUsage:String = '';
@:noCompletion private var cacheCount:Int;
@@ -115,8 +113,6 @@ class FPSCounter extends TextField
FlxTween.tween(this, {x: 0, y: 0}, 0.1, {ease: FlxEase.quadOut});
}
- currentTotalMemory = memoryMegas;
-
text = 'FPS: $currentFPS'
+ (ClientPrefs.data.memoryDisplay ? ' | Memory: ${CoolUtil.getSizeString(memoryMegas)} / ${CoolUtil.getSizeString(taskMemoryMegas)}' : '')
+ (ClientPrefs.data.dateDisplay ? '\nDate: $stringTimeToReturn' : '')
diff --git a/funkinscsource/import.hx b/funkinscsource/import.hx
index b3f45a2..2b572c2 100644
--- a/funkinscsource/import.hx
+++ b/funkinscsource/import.hx
@@ -2,13 +2,14 @@
import lime.app.Application;
import openfl.Lib;
+import lime.system.System;
// Windows things
#if windows
import slushi.windows.CppAPI;
import slushi.windows.WindowsCPP;
import slushi.windows.WindowsCPP.MessageBoxIcon;
import slushi.windows.WindowsFuncs;
-import slushi.windows.WinConsoleUtils;
+import slushi.windows.WindowsTerminalCPP;
#end
// Window, main class of the engine and other things
import slushi.windowThings.WindowFuncs;
diff --git a/funkinscsource/objects/PsychVideoSprite.hx b/funkinscsource/objects/PsychVideoSprite.hx
index 5c1c00c..678d02d 100644
--- a/funkinscsource/objects/PsychVideoSprite.hx
+++ b/funkinscsource/objects/PsychVideoSprite.hx
@@ -53,25 +53,25 @@ class PsychVideoSprite #if (VIDEOS_ALLOWED && hxvlc) extends FlxVideoSprite #end
return b;
}
- public override function pause()
- {
- super.pause();
- if (FlxG.autoPause)
- {
- if (FlxG.signals.focusGained.has(bitmap.resume)) FlxG.signals.focusGained.remove(bitmap.resume);
- if (FlxG.signals.focusLost.has(bitmap.pause)) FlxG.signals.focusLost.remove(bitmap.pause);
- }
- }
-
- public override function resume()
- {
- super.resume();
- if (FlxG.autoPause)
- {
- if (!FlxG.signals.focusGained.has(bitmap.resume)) FlxG.signals.focusGained.add(bitmap.resume);
- if (!FlxG.signals.focusLost.has(bitmap.pause)) FlxG.signals.focusLost.add(bitmap.pause);
- }
- }
+ // public override function pause()
+ // {
+ // super.pause();
+ // if (FlxG.autoPause)
+ // {
+ // if (FlxG.signals.focusGained.has(bitmap.resume)) FlxG.signals.focusGained.remove(bitmap.resume);
+ // if (FlxG.signals.focusLost.has(bitmap.pause)) FlxG.signals.focusLost.remove(bitmap.pause);
+ // }
+ // }
+
+ // public override function resume()
+ // {
+ // super.resume();
+ // if (FlxG.autoPause)
+ // {
+ // if (!FlxG.signals.focusGained.has(bitmap.resume)) FlxG.signals.focusGained.add(bitmap.resume);
+ // if (!FlxG.signals.focusLost.has(bitmap.pause)) FlxG.signals.focusLost.add(bitmap.pause);
+ // }
+ // }
// maybe temp?
public function addCallback(vidCallBack:String, func:Void->Void)
diff --git a/funkinscsource/psychlua/FunkinLua.hx b/funkinscsource/psychlua/FunkinLua.hx
index 857b98e..49f395f 100644
--- a/funkinscsource/psychlua/FunkinLua.hx
+++ b/funkinscsource/psychlua/FunkinLua.hx
@@ -19,7 +19,7 @@ import objects.Character;
import objects.HealthIcon;
import states.MainMenuState;
import states.StoryMenuState;
-import substates.PauseSubState;
+import slushi.substates.SlushiPauseSubState;
import substates.GameOverSubstate;
import psychlua.LuaUtils;
import psychlua.LuaUtils.LuaTweenOptions;
@@ -1082,7 +1082,7 @@ class FunkinLua
set("restartSong", function(?skipTransition:Bool = false) {
game.persistentUpdate = false;
FlxG.camera.followLerp = 0;
- PauseSubState.restartSong(skipTransition);
+ SlushiPauseSubState.restartSong(skipTransition);
return true;
});
set("exitSong", function(?skipTransition:Bool = false) {
@@ -1096,7 +1096,7 @@ class FunkinLua
{
if (PlayState.isStoryMode) MusicBeatState.switchState(new StoryMenuState());
else
- MusicBeatState.switchState(new states.freeplay.FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
}
#if BASE_GAME_FILES
else
@@ -1107,7 +1107,7 @@ class FunkinLua
game.openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker)));
}
else
- game.openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new states.freeplay.FreeplayState(sticker)));
+ game.openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new slushi.states.freeplay.SlushiFreeplayState(sticker)));
}
#end
diff --git a/funkinscsource/psychlua/LuaUtils.hx b/funkinscsource/psychlua/LuaUtils.hx
index c0ee063..51c926e 100644
--- a/funkinscsource/psychlua/LuaUtils.hx
+++ b/funkinscsource/psychlua/LuaUtils.hx
@@ -857,16 +857,16 @@ class LuaUtils
case 'camslehud' | 'slehud':
return PlayState.instance.camSLEHUD;
- case 'camfor3d':
- return PlayState.instance.camFor3D;
- case 'camfor3d2':
- return PlayState.instance.camFor3D2;
- case 'camfor3d3':
- return PlayState.instance.camFor3D3;
- case 'camfor3d4':
- return PlayState.instance.camFor3D4;
- case 'camfor3d5':
- return PlayState.instance.camFor3D5;
+ case 'camthings':
+ return PlayState.instance.camThings;
+ case 'camthings2':
+ return PlayState.instance.camThings2;
+ case 'camthings3':
+ return PlayState.instance.camThings3;
+ case 'camthings4':
+ return PlayState.instance.camThings4;
+ case 'camthings5':
+ return PlayState.instance.camThings5;
case 'camwatermark' | 'watermark':
return PlayState.instance.camWaterMark;
}
@@ -900,16 +900,16 @@ class LuaUtils
camera = 'mainCam';
case 'camslehud' | 'slehud':
camera = 'camSLEHUD';
- case 'camfor3d':
- camera = 'camFor3D';
- case 'camfor3d2':
- camera = 'camFor3D2';
- case 'camfor3d3':
- camera = 'camFor3D3';
- case 'camfor3d4':
- camera = 'camFor3D4';
- case 'camfor3d5':
- camera = 'camFor3D5';
+ case 'camthings':
+ camera = 'camThings';
+ case 'camthings2':
+ camera = 'camThings2';
+ case 'camthings3':
+ camera = 'camThings3';
+ case 'camthings4':
+ camera = 'camThings4';
+ case 'camthings5':
+ camera = 'camThings5';
case 'camwatermark' | 'watermark':
camera = 'camWaterMark';
default:
@@ -1338,19 +1338,19 @@ class LuaUtils
return FunkinLua.lua_Cameras.get("main");
case 'camslehud' | 'slehud':
- return FunkinLua.lua_Cameras.get("slehud");
- case 'camfor3d':
- return FunkinLua.lua_Cameras.get("camFor3D");
- case 'camfor3d2':
- return FunkinLua.lua_Cameras.get("camFor3D2");
- case 'camfor3d3':
- return FunkinLua.lua_Cameras.get("camFor3D3");
- case 'camfor3d4':
- return FunkinLua.lua_Cameras.get("camFor3D4");
- case 'camfor3d5':
- return FunkinLua.lua_Cameras.get("camFor3D5");
+ return FunkinLua.lua_Cameras.get("camSLEHUD");
+ case 'camthings':
+ return FunkinLua.lua_Cameras.get("camThings");
+ case 'camthings2':
+ return FunkinLua.lua_Cameras.get("camThings2");
+ case 'camthings3':
+ return FunkinLua.lua_Cameras.get("camThings3");
+ case 'camthings4':
+ return FunkinLua.lua_Cameras.get("camThings4");
+ case 'camthings5':
+ return FunkinLua.lua_Cameras.get("camThings5");
case 'camwatermark' | 'watermark':
- return FunkinLua.lua_Cameras.get("camWatermark");
+ return FunkinLua.lua_Cameras.get("camWaterWark");
}
return FunkinLua.lua_Cameras.get("game");
diff --git a/funkinscsource/scripting/SCScript.hx b/funkinscsource/scripting/SCScript.hx
index fd453ea..5ce141d 100644
--- a/funkinscsource/scripting/SCScript.hx
+++ b/funkinscsource/scripting/SCScript.hx
@@ -105,7 +105,7 @@ class SCScript extends flixel.FlxBasic
"TitleState" => states.TitleState,
// SubStates
"GameOverSubstate" => substates.GameOverSubstate,
- "PauseSubState" => substates.PauseSubState,
+ "PauseSubState" => slushi.substates.SlushiPauseSubState,
// External Usages For Engine
"Countdown" => backend.Countdown,
diff --git a/funkinscsource/slushi/MainGame.hx b/funkinscsource/slushi/MainGame.hx
index 7145b88..8d0e42f 100644
--- a/funkinscsource/slushi/MainGame.hx
+++ b/funkinscsource/slushi/MainGame.hx
@@ -3,8 +3,8 @@ package slushi;
import flixel.FlxGame;
import flixel.FlxState;
import slushi.slushiUtils.crashHandler.CrashHandler;
-import slushi.winSL.WinSLCrashHandler;
import slushi.substates.DebugSubState;
+import slushi.windows.winGDIThings.WinGDIThread;
/*
* This class is the base game, the FlxGame, modified to make the in-game crash handler that contains the Slushi Engine functional.
@@ -24,6 +24,7 @@ class MainGame extends FlxGame
#if windows
WindowsFuncs.resetAllCPPFunctions();
WindowFuncs.resetWindowParameters();
+ WinGDIThread.stopThread();
#end
try
@@ -38,7 +39,7 @@ class MainGame extends FlxGame
{
if (!crashHandlerAlredyOpen)
{
- CrashHandler.symbolPrevent(error);
+ CrashHandler.symbolPrevent(error, 0);
crashHandlerAlredyOpen = true;
}
}
@@ -48,10 +49,12 @@ class MainGame extends FlxGame
{
if (FlxG.keys.justPressed.F3)
{
- if (Type.getClass(FlxG.state) == PlayState) {
+ if (Type.getClass(FlxG.state) == PlayState)
+ {
DebugSubState.onPlayState = true;
}
- else {
+ else
+ {
DebugSubState.onPlayState = false;
}
FlxG.state.openSubState(new DebugSubState());
@@ -69,7 +72,7 @@ class MainGame extends FlxGame
{
if (!crashHandlerAlredyOpen)
{
- CrashHandler.symbolPrevent(error);
+ CrashHandler.symbolPrevent(error, 1);
crashHandlerAlredyOpen = true;
}
}
@@ -86,7 +89,7 @@ class MainGame extends FlxGame
{
if (!crashHandlerAlredyOpen)
{
- CrashHandler.symbolPrevent(error);
+ CrashHandler.symbolPrevent(error, 2);
crashHandlerAlredyOpen = true;
}
}
diff --git a/funkinscsource/slushi/SlushiMain.hx b/funkinscsource/slushi/SlushiMain.hx
index 42357c3..5498fc0 100644
--- a/funkinscsource/slushi/SlushiMain.hx
+++ b/funkinscsource/slushi/SlushiMain.hx
@@ -6,6 +6,9 @@ import slushi.others.BuildDemoText;
import slushi.slushiUtils.crashHandler.CrashHandler;
import tjson.TJSON as Json;
import slushi.states.SlushiTitleState;
+import slushi.windows.winGDIThings.WinGDIThread;
+import haxe.Http;
+import slushi.others.EngineMacros;
/*
* This is the main class for the Slushi Engine initialization, this loads all initial functions of Windows C++ API
@@ -15,22 +18,23 @@ import slushi.states.SlushiTitleState;
*/
class SlushiMain
{
- // Versions of the things in the engine and base engine (SCE)
- public static var buildNumber:String = "19102024";
+ // Versions of the things in the engine and SCE
+ public static var buildNumber:String = EngineMacros.prepareBuildNumber();
public static var sceGitCommit:String = "4eaf8c4";
- public static var slushiEngineVersion:String = '0.3.8';
- public static var winSLVersion:String = '1.3.0';
- public static var slCrashHandlerVersion:String = '1.4.0';
+ public static var slushiEngineVersion:String = '0.4.0';
+ public static var sleThingsVersions = {
+ winSLVersion: '1.3.0',
+ slCrashHandlerVersion: '1.4.0'
+ };
- public static var slushiColor = FlxColor.fromRGB(143, 217, 209); // 0xff8FD9D1 0xffd6f3de
- private static var pathsToCreate:Array = ['./engineUtils', './engineUtils/SMToConvert'];
+ public static var slushiColor:FlxColor = FlxColor.fromRGB(143, 217, 209); // 0xff8FD9D1 0xffd6f3de
+ private static var pathsToCreate:Array = ['./slEngineUtils', './slEngineUtils/SMToConvert', './mods/images/windowsAssets/'];
public static function loadSlushiEngineFunctions()
{
#if windows
preventAdminExecution();
CppAPI._setWindowLayered();
- CppAPI.centerWindow();
WindowsFuncs.resetAllCPPFunctions();
WindowsFuncs.saveCurrentWindowsWallpaper();
if (ClientPrefs.data.useSavedWallpaper)
@@ -39,12 +43,12 @@ class SlushiMain
}
WindowsFuncs.setSlushiColorToWindow();
#end
+ WindowFuncs.centerWindow();
+ CrashHandler.initCrashHandler();
SystemInfo.init();
- createEngineUtilsFolder();
+ createSLEngineFolders();
Application.current.window.onClose.add(SlushiMain.onCloseWindow);
- CrashHandler.initCrashHandler();
-
#if THIS_IS_A_BUILD_TEST
var textWarn:BuildDemoText = new BuildDemoText();
Lib.current.stage.addChild(textWarn);
@@ -53,8 +57,9 @@ class SlushiMain
inline public static function getSLEPath(file:String = ''):String
{
- final finalFile = 'assets/slushiEngineAssets/SLEAssets/$file';
- if (FileSystem.exists(finalFile)) {
+ final finalFile = 'assets/slushiEngineAssets/$file';
+ if (FileSystem.exists(finalFile))
+ {
return finalFile;
}
else if (finalFile.endsWith('.png'))
@@ -74,42 +79,60 @@ class SlushiMain
}
}
- public static function createEngineUtilsFolder()
+ private static function createSLEngineFolders()
{
- var paths:Array = pathsToCreate;
-
- for (path in paths)
- if (!FileSystem.exists(path))
- FileSystem.createDirectory(path);
+ for (path in pathsToCreate)
+ {
+ try
+ {
+ if (!FileSystem.exists(path))
+ {
+ FileSystem.createDirectory(path);
+ }
+ }
+ catch (e)
+ {
+ Debug.logSLEError('Error creating [$path]: $e');
+ }
+ }
}
public static function onCloseWindow()
{
Sys.println("\033[0m");
+ CustomFuncs.removeAllFilesFromCacheDirectory();
#if windows
- Debug.logSLEInfo("Reseting all C++ functions...\n\n");
+ Debug.logSLEInfo("Reseting all C++ functions...\n");
+ WinGDIThread.stopThread();
WindowsFuncs.resetAllCPPFunctions();
// Delete the saved wallpaper if it exists
@:privateAccess
- if (FileSystem.exists(WindowsFuncs.savedWallpaperPath))
+ try
{
- FileSystem.deleteFile(WindowsFuncs.savedWallpaperPath);
+ if (FileSystem.exists(WindowsFuncs.savedWallpaperPath))
+ {
+ FileSystem.deleteFile(WindowsFuncs.savedWallpaperPath);
+ }
+ }
+ catch (e)
+ {
+ Debug.logSLEError('Error deleting saved wallpaper: $e');
}
// Close the game without animations if it is in a crash, preventing a posible loop
if (CrashHandler.inCrash)
{
- Sys.exit(1);
+ System.exit(1);
return;
}
Application.current.window.onClose.cancel();
- var numTween:NumTween = FlxTween.num(CppAPI.getWindowOppacity(), 0, 0.7, {
+ var numTween:NumTween = FlxTween.num(CppAPI.getWindowOppacity(), 0, 0.6, {
onComplete: function(twn:FlxTween)
{
- Sys.exit(0);
+ System.exit(0);
}
});
numTween.onUpdate = function(twn:FlxTween)
@@ -117,7 +140,7 @@ class SlushiMain
CppAPI.setWindowOppacity(numTween.value);
}
#else
- Application.current.window.close();
+ System.exit(0);
#end
}
@@ -126,7 +149,7 @@ class SlushiMain
if (ClientPrefs.data.checkForUpdates)
{
Debug.logSLEInfo('Checking for new version...');
- var http = new haxe.Http("https://raw.githubusercontent.com/Slushi-Github/Slushi-Engine/main/gitVersion.json");
+ var http = new Http("https://raw.githubusercontent.com/Slushi-Github/Slushi-Engine/main/gitVersion.json");
var jsonData:Dynamic = null;
http.onData = function(data:String)
@@ -138,20 +161,33 @@ class SlushiMain
catch (e)
{
Debug.logSLEError('Error parsing JSON: $e');
+ return;
}
var currentVersion = slushiEngineVersion;
var gitVersion = jsonData.engineVersion;
- Debug.logInfo('version online: [' + gitVersion + '], this version: [' + currentVersion + ']');
- if (gitVersion != currentVersion)
+
+ Debug.logSLEInfo('Version online: [' + gitVersion + '], this version: [' + currentVersion + ']');
+
+ var currentVersionNum = CustomFuncs.parseVersion(currentVersion);
+ var gitVersionNum = CustomFuncs.parseVersion(gitVersion);
+
+ if (currentVersionNum > gitVersionNum)
{
- Debug.logSLEWarn('Versions arent matching!');
+ Debug.logSLEInfo('The version is higher than the one on Github so this is a development version, skipping update check.');
+ SlushiTitleState.gitVersion.needUpdate = false;
+ slushiEngineVersion += ' - [DEV]';
+ }
+ else if (currentVersionNum < gitVersionNum)
+ {
+ Debug.logSLEWarn('A new version is available!');
SlushiTitleState.gitVersion.needUpdate = true;
SlushiTitleState.gitVersion.newVersion = gitVersion;
}
else
{
Debug.logSLEInfo('Versions are matching!');
+ SlushiTitleState.gitVersion.needUpdate = false;
}
}
@@ -169,14 +205,24 @@ class SlushiMain
/**
* Even though SLE does not require administrator permissions for absolutely nothing, I do NOT want the engine
* to be able to run with those permissions, it DOES NOT NEED THEM.
+ *
+ * Except when running SLE on Linux or MacOS through Wine, Wine will always run a
+ * Windows program with administrator permissions apparently, making it
+ * impossible to run SLE this way before.
*/
private static function preventAdminExecution()
{
#if windows
+ if (WindowsCPP.detectWine())
+ {
+ Debug.logSLEWarn("Wine detected! Skipping admin check because Wine always runs as admin.");
+ return;
+ }
+
if (WindowsCPP.isRunningAsAdmin())
{
CppAPI.showMessageBox("SLE is running as an administrator, please don't do that.", "Slushi Engine: HEY!!", MSG_WARNING);
- Sys.exit(1);
+ System.exit(1);
}
#end
}
diff --git a/funkinscsource/slushi/others/CustomFuncs.hx b/funkinscsource/slushi/others/CustomFuncs.hx
index 8479e31..be60e7e 100644
--- a/funkinscsource/slushi/others/CustomFuncs.hx
+++ b/funkinscsource/slushi/others/CustomFuncs.hx
@@ -1,6 +1,7 @@
package slushi.others;
import haxe.io.Path;
+import slushi.others.systemUtils.HiddenProcess;
/**
* This class contains custom functions for the engine, but not usually used in the engine itself
@@ -31,56 +32,53 @@ class CustomFuncs
return all;
}
- public static function getAllPath():String
+ public static function getProgramPath():String
{
var allPath:String = Path.directory(Sys.programPath()).replace("\\", "/");
return allPath;
}
- public static function realResetGame(?arg:String):Void
+ public static function realResetGame(?args:Array = null):Void
{
- #if windows
- new Process("SLE.exe", [arg]);
- Sys.exit(0);
- #else
- Sys.exit(0);
- #end
+ new HiddenProcess(Sys.programPath(), args);
+ System.exit(0);
}
- public static function setWinBorderColorFromInt(color:Int):Void
+ public static function parseVersion(version:String):Int
{
- #if windows
- var red:Int = (color >> 16) & 0xFF;
- var green:Int = (color >> 8) & 0xFF;
- var blue:Int = color & 0xFF;
- var rgb:Array = [red, green, blue];
- WindowsFuncs.setWindowBorderColor(rgb);
- #end
+ var parts = version.split(".");
+ var major = Std.parseInt(parts[0]);
+ var minor = parts.length > 1 ? Std.parseInt(parts[1]) : 0;
+ var patch = parts.length > 2 ? Std.parseInt(parts[2]) : 0;
+ return (major * 10000) + (minor * 100) + patch; // Ej: "1.2.3" -> 10203
}
- // Thanks Glowsoony for this code
- public static function getRGBFromFlxColor(red:FlxColor, green:FlxColor, blue:FlxColor):Array
+ public static function removeAllFilesFromCacheDirectory():Void
{
- // Función para convertir el valor entero a componentes RGB
- function getRGB(color:Int):Array
+ final path = "./assets/slushiEngineAssets/OthersAssets/SLCache";
+ try
{
- var red = (color >> 16) & 0xFF;
- var green = (color >> 8) & 0xFF;
- var blue = color & 0xFF;
- return [red, green, blue];
+ if (FileSystem.exists(path))
+ {
+ var directory = FileSystem.readDirectory(path);
+ for (file in directory)
+ {
+ FileSystem.deleteFile(Path.join([path, file]));
+ }
+ }
+ }
+ catch (e:Dynamic)
+ {
+ Debug.logError('Error removing files from cache directory: $e');
}
-
- // Convertir cada FlxColor a su representación entera
- var flxColorRed = cast red; // No es necesario volver a convertir desde RGB si ya tienes un FlxColor
- var flxColorGreen = cast green;
- var flxColorBlue = cast blue;
-
- // Obtener los valores RGB de cada color
- var redRGB = getRGB(flxColorRed);
- var greenRGB = getRGB(flxColorGreen);
- var blueRGB = getRGB(flxColorBlue);
-
- // Devolver el arreglo con los componentes RGB
- return [redRGB[0], greenRGB[1], blueRGB[2]];
}
-}
\ No newline at end of file
+
+ public static function colorIntToRGB(color:Int):Array
+ {
+ var red:Int = (color >> 16) & 0xFF;
+ var green:Int = (color >> 8) & 0xFF;
+ var blue:Int = color & 0xFF;
+ var rgb:Array = [red, green, blue];
+ return rgb;
+ }
+}
diff --git a/funkinscsource/slushi/others/EngineMacros.hx b/funkinscsource/slushi/others/EngineMacros.hx
index de41937..5c0feae 100644
--- a/funkinscsource/slushi/others/EngineMacros.hx
+++ b/funkinscsource/slushi/others/EngineMacros.hx
@@ -1,55 +1,66 @@
package slushi.others;
-import sys.io.File;
+import CompileTime;
/**
* A simple macro for showing information about the engine compilation
*
* Author: Slushi
*/
-
class EngineMacros
{
- #if macro
- static var ENGINE_VERSION = "0.3.8";
- static var CUSTOM_BUILD_NAME = "not defined";
-
- public static function initialize_compilation() {
- Sys.println('\n\x1b[38;5;236m== STARTING COMPILATION ===================\033[0m');
- Sys.println('---- \033[96mSlushi Engine\033[0m version: \x1b[38;5;236m[\033[0m\x1b[38;5;11m${ENGINE_VERSION}\033[0m\x1b[38;5;236m]\033[0m ----');
-
- Sys.println('\x1b[38;5;7mBuild info:\033[0m');
- #if SLUSHI_CPP_CODE
- Sys.println('C++ Code is \x1b[38;5;10menabled\x1b[0m');
- #else
- Sys.println('C++ Code is \x1b[38;5;1mdisabled\x1b[0m');
- #end
- #if SLUSHI_LUA
- Sys.println('Slushi Lua is \x1b[38;5;10menabled\x1b[0m');
- #else
- Sys.println('Slushi Lua is \x1b[38;5;1mdisabled\x1b[0m');
- #end
- #if CUSTOM_BUILD
- Sys.println('This is a custom build?: \x1b[38;5;10mYES\x1b[0m');
- Sys.println('Custom build name: \x1b[38;5;242m${CUSTOM_BUILD_NAME}\x1b[0m');
- #else
- Sys.println('This is a custom build?: \x1b[38;5;1mNO\x1b[0m');
- #end
- #if THIS_IS_A_BUILD_TEST
- Sys.println('Compiling a \x1b[38;5;11mtest build\x1b[0m!');
- #end
- #if windows
- Sys.println('Compiling for \x1b[38;5;4mWindows\x1b[0m');
- #elseif linux
- Sys.println('Compiling for \x1b[38;5;5mLinux\x1b[0m');
- #elseif macos
- Sys.println('Compiling for MacOS');
- #end
-
- Sys.println('-----------');
- Sys.println('Trying to initialize the compilation...');
- Sys.println('Date on start compilation: \033[32m${Date.now().toString()}\033[0m');
- Sys.println('\x1b[38;5;234m==========================\033[0m\n\x1b[38;5;8m');
- }
- #end
-}
\ No newline at end of file
+ #if macro
+ static var ENGINE_VERSION = "0.4.0";
+ static var CUSTOM_BUILD_NAME = "not defined";
+
+ public static function showBuildInfo()
+ {
+ Sys.println('\n\x1b[38;5;236m== STARTING COMPILATION ===================\033[0m');
+ Sys.println('---- \033[96mSlushi Engine\033[0m version: \x1b[38;5;236m[\033[0m\x1b[38;5;11m${ENGINE_VERSION}\033[0m\x1b[38;5;236m]\033[0m ----');
+
+ Sys.println('\x1b[38;5;7mBuild info:\033[0m');
+ #if SLUSHI_CPP_CODE
+ Sys.println('C++ Code is \x1b[38;5;10menabled\x1b[0m');
+ #else
+ Sys.println('C++ Code is \x1b[38;5;1mdisabled\x1b[0m');
+ #end
+ #if SLUSHI_LUA
+ Sys.println('Slushi Lua is \x1b[38;5;10menabled\x1b[0m');
+ #else
+ Sys.println('Slushi Lua is \x1b[38;5;1mdisabled\x1b[0m');
+ #end
+ #if CUSTOM_BUILD
+ Sys.println('This is a custom build?: \x1b[38;5;10mYES -- \x1b[38;5;242m${CUSTOM_BUILD_NAME}\x1b[0m');
+ #else
+ Sys.println('This is a custom build?: \x1b[38;5;1mNO\x1b[0m');
+ #end
+ #if THIS_IS_A_BUILD_TEST
+ Sys.println('Compiling a \x1b[38;5;11mtest build\x1b[0m!');
+ #end
+ #if windows
+ Sys.println('Compiling for \x1b[38;5;4mWindows\x1b[0m');
+ #elseif linux
+ Sys.println('Compiling for \x1b[38;5;5mLinux\x1b[0m');
+ #elseif macos
+ Sys.println('Compiling for MacOS');
+ #end
+
+ Sys.println('-----------');
+ Sys.println('Trying to initialize the compilation...');
+ Sys.println('Date on start compilation: \033[32m${Date.now().toString()}\033[0m');
+ Sys.println('\x1b[38;5;234m==========================\033[0m\n\x1b[38;5;8m');
+ }
+ #end
+
+ public static function prepareBuildNumber():String {
+ var currentDate = CompileTime.buildDate();
+
+ var day:String = Std.string(currentDate.getDate());
+ var month:String = Std.string(currentDate.getMonth() + 1);
+ var year:String = Std.string(currentDate.getFullYear());
+
+ var finalText:String = day + month + year;
+
+ return finalText;
+ }
+}
diff --git a/funkinscsource/slushi/others/SlushiSongs.hx b/funkinscsource/slushi/others/SlushiSongs.hx
index 7e0cc2a..8d9cd7f 100644
--- a/funkinscsource/slushi/others/SlushiSongs.hx
+++ b/funkinscsource/slushi/others/SlushiSongs.hx
@@ -5,7 +5,20 @@ package slushi.others;
*
* Author: Slushi
*/
+class SlushiSongs
+{
+ private static var slSongs:Array> = [["C18H27NO3", "slushi"]];
-class SlushiSongs {
- public static var slSongs:Array = [];
-}
\ No newline at end of file
+ public static function checkSong(songName:String, difficulty:String):Bool
+ {
+ for (i in slSongs)
+ {
+ if (songName == i[0] && difficulty == i[1])
+ {
+ return true;
+ break;
+ }
+ }
+ return false;
+ }
+}
diff --git a/funkinscsource/slushi/slushiLua/OthersLua.hx b/funkinscsource/slushi/slushiLua/OthersLua.hx
index 9e52b5b..de06151 100644
--- a/funkinscsource/slushi/slushiLua/OthersLua.hx
+++ b/funkinscsource/slushi/slushiLua/OthersLua.hx
@@ -2,11 +2,11 @@ package slushi.slushiLua;
import slushi.slushiUtils.SlushiEngineHUD;
import slushi.slushiUtils.SlushiDebugText;
-
import psychlua.FunkinLua;
import psychlua.LuaUtils;
-
import lime.system.System;
+import objects.note.StrumArrow;
+import objects.note.Note;
class OthersLua
{
@@ -14,6 +14,18 @@ class OthersLua
{
Debug.logSLEInfo('Loaded Slushi Others Lua functions!');
+ funkLua.set("camGame", "game");
+ funkLua.set("camHUD", "hud");
+ funkLua.set("camOther", "other");
+ funkLua.set("camNoteStuff", "notestuff");
+ funkLua.set("camSLEHUD", "slehud");
+ funkLua.set("camThings", "camthings");
+ funkLua.set("camThings2", "camthings2");
+ funkLua.set("camThings3", "camthings3");
+ funkLua.set("camThings4", "camthings4");
+ funkLua.set("camThings5", "camthings5");
+ funkLua.set("camWaterMark", "camwatermark");
+
funkLua.set("printInGameplay", function(text:Dynamic = '', time:Float = 6)
{
if (text == null)
@@ -23,7 +35,8 @@ class OthersLua
funkLua.set("tweenObjectFromSLEHUD", function(mode:String, value:Dynamic, time:Float, ease:String = "linear")
{
- switch(mode) {
+ switch (mode)
+ {
case "X":
SlushiEngineHUD.instance.moveSLELogoX(value, time, ease);
case "Y":
@@ -55,7 +68,7 @@ class OthersLua
funkLua.set("CopyCamera", function(camTag:String, camToCopy:String)
{
- var variables = MusicBeatState.getVariables("Tween");
+ var variables = MusicBeatState.getVariables("Camera");
if (!variables.exists(camTag))
{
var camera = new backend.CameraCopy(LuaUtils.cameraFromString(camToCopy));
@@ -67,8 +80,9 @@ class OthersLua
}
});
- funkLua.set("removeCopyCamera", function(camTag:String) {
- var variables = MusicBeatState.getVariables("Tween");
+ funkLua.set("removeCopyCamera", function(camTag:String)
+ {
+ var variables = MusicBeatState.getVariables("Camera");
if (variables.exists(camTag))
{
@@ -79,21 +93,64 @@ class OthersLua
}
});
- funkLua.set("tweenNumer", function(tag:String, startNum:Float, endNum:Float, duration:Float, ease:String = "linear") {
-
+ funkLua.set("tweenNumer", function(tag:String, startNum:Float, endNum:Float, duration:Float, ease:String = "linear")
+ {
var variables = MusicBeatState.getVariables("Tween");
variables.set(tag, FlxTween.num(startNum, endNum, duration, {
ease: LuaUtils.getTweenEaseByString(ease),
- onComplete: function(twn:FlxTween) {
+ onComplete: function(twn:FlxTween)
+ {
variables.remove(tag);
- if (PlayState.instance != null) PlayState.instance.callOnLuas('onTweenCompleted', [tag]);
+ if (PlayState.instance != null)
+ PlayState.instance.callOnLuas('onTweenCompleted', [tag]);
return endNum;
},
- onUpdate: function(tween:FlxTween) {
+ onUpdate: function(tween:FlxTween)
+ {
return tween.percent;
}
}));
});
+
+ funkLua.set("getSLEVersion", function():String
+ {
+ var version = SlushiMain.slushiEngineVersion;
+
+ // This should not happen in an official build, but well, to avoid problems
+ if (version.contains(' - [DEV]'))
+ version = version.replace(' - [DEV]', '');
+
+ return version;
+ });
+
+ funkLua.set("getMTCurrentModifiers", function(equalizer:String = ":"):String
+ {
+ var leText = '';
+ // if (!PlayState.instance.notITGMod)
+ // Debug.logSLEInfo('getMTCurrentModifiers called while not in ITG mode!');
+ // return '';
+
+ // Code from Hitmans AD
+ for (modName => mod in PlayState.instance.playfieldRenderer.modifierTable.modifiers)
+ {
+ if (mod.currentValue != mod.baseValue)
+ {
+ leText += modName + equalizer + " " + FlxMath.roundDecimal(mod.currentValue, 2);
+ for (subModName => subMod in mod.subValues)
+ {
+ leText += " " + subModName + equalizer + " " + FlxMath.roundDecimal(subMod.value, 2);
+ }
+ leText += "\n";
+ }
+ }
+
+ return leText;
+ });
+
+ funkLua.set("colorIntToRGB", function(color:Int):Array
+ {
+ return CustomFuncs.colorIntToRGB(color);
+ });
}
}
diff --git a/funkinscsource/slushi/slushiLua/ShadersLua.hx b/funkinscsource/slushi/slushiLua/ShadersLua.hx
index 35fe5b6..2321f46 100644
--- a/funkinscsource/slushi/slushiLua/ShadersLua.hx
+++ b/funkinscsource/slushi/slushiLua/ShadersLua.hx
@@ -14,11 +14,11 @@ class ShadersLua
Debug.logSLEInfo('Loaded Slushi Shaders Lua functions!');
FunkinLua.lua_Cameras.set("camSLEHUD", {cam: PlayState.instance.camSLEHUD, shaders: [], shaderNames: []});
- FunkinLua.lua_Cameras.set("camFor3D", {cam: PlayState.instance.camFor3D, shaders: [], shaderNames: []});
- FunkinLua.lua_Cameras.set("camFor3D2", {cam: PlayState.instance.camFor3D2, shaders: [], shaderNames: []});
- FunkinLua.lua_Cameras.set("camFor3D3", {cam: PlayState.instance.camFor3D3, shaders: [], shaderNames: []});
- FunkinLua.lua_Cameras.set("camFor3D4", {cam: PlayState.instance.camFor3D4, shaders: [], shaderNames: []});
- FunkinLua.lua_Cameras.set("camFor3D5", {cam: PlayState.instance.camFor3D5, shaders: [], shaderNames: []});
+ FunkinLua.lua_Cameras.set("camThings", {cam: PlayState.instance.camThings, shaders: [], shaderNames: []});
+ FunkinLua.lua_Cameras.set("camThings2", {cam: PlayState.instance.camThings2, shaders: [], shaderNames: []});
+ FunkinLua.lua_Cameras.set("camThings3", {cam: PlayState.instance.camThings3, shaders: [], shaderNames: []});
+ FunkinLua.lua_Cameras.set("camThings4", {cam: PlayState.instance.camThings4, shaders: [], shaderNames: []});
+ FunkinLua.lua_Cameras.set("camThings5", {cam: PlayState.instance.camThings5, shaders: [], shaderNames: []});
FunkinLua.lua_Cameras.set("camWaterWark", {cam: PlayState.instance.camWaterMark, shaders: [], shaderNames: []});
funkLua.set("addShader3DToCamStrumsAndCamNotes", function()
diff --git a/funkinscsource/slushi/slushiLua/SlushiLua.hx b/funkinscsource/slushi/slushiLua/SlushiLua.hx
index bae019a..766e33e 100644
--- a/funkinscsource/slushi/slushiLua/SlushiLua.hx
+++ b/funkinscsource/slushi/slushiLua/SlushiLua.hx
@@ -1,21 +1,23 @@
package slushi.slushiLua;
+import psychlua.FunkinLua;
+
/*
* This class contains ALL Lua functions for Slushi Engine, it is one of the most important files since it
* is what allows to make modcharts using the features of the engine through Lua, and more.
*
* Author: Slushi
-*/
-
-import psychlua.FunkinLua;
-
+ */
class SlushiLua
{
public static var apliedWindowTransparent:Bool = false;
- public static var slushi_InternalSprites:Map = new Map();
+ public static var slushi_InternalObjects:Map = new Map();
public static function loadSlushiLua(funkLua:FunkinLua)
- {
+ {
+ if (slushi_InternalObjects != null)
+ slushi_InternalObjects.clear();
+
Debug.logSLEInfo("Loading Slushi Lua functions...");
#if (SLUSHI_LUA && LUA_ALLOWED)
WindowsLua.loadWindowsLua(funkLua);
diff --git a/funkinscsource/slushi/slushiLua/WinSLLua.hx b/funkinscsource/slushi/slushiLua/WinSLLua.hx
index 780a4fa..f35c652 100644
--- a/funkinscsource/slushi/slushiLua/WinSLLua.hx
+++ b/funkinscsource/slushi/slushiLua/WinSLLua.hx
@@ -14,7 +14,7 @@ class WinSLLua
funkLua.set("winSL_console_getVersion", function()
{
- return SlushiMain.winSLVersion;
+ return SlushiMain.sleThingsVersions.winSLVersion;
});
funkLua.set("winSL_console_printLetterByLetter", function(text:String, time:Float)
@@ -27,28 +27,28 @@ class WinSLLua
switch (mode)
{
case true:
- WinConsoleUtils.allocConsole();
- WinConsoleUtils.setConsoleTitle('WinSL ${SlushiMain.winSLVersion}');
- WinConsoleUtils.setConsoleWindowIcon(SlushiMain.getSLEPath("WinSL_Assets/windowIcon.ico"));
- WinConsoleUtils.setWinConsoleColor();
+ WindowsTerminalCPP.allocConsole();
+ WindowsTerminalCPP.setConsoleTitle('WinSL ${SlushiMain.sleThingsVersions.winSLVersion}');
+ WindowsTerminalCPP.setConsoleWindowIcon(SlushiMain.getSLEPath("WinSL_Assets/windowIcon.ico"));
+ WindowsTerminalCPP.setWinConsoleColor();
case false:
- WinConsoleUtils.hideConsoleWindow();
+ WindowsTerminalCPP.hideConsoleWindow();
}
});
funkLua.set("winSL_console_disableResize", function()
{
- WinConsoleUtils.disableResizeWindow();
+ WindowsTerminalCPP.disableResizeWindow();
});
funkLua.set("winSL_console_disableClose", function()
{
- WinConsoleUtils.disableCloseWindow();
+ WindowsTerminalCPP.disableCloseWindow();
});
funkLua.set("winSL_console_setTitle", function(title:String)
{
- WinConsoleUtils.setConsoleTitle(title);
+ WindowsTerminalCPP.setConsoleTitle(title);
});
funkLua.set("winSL_console_setWinPos", function(mode:String, value:Int)
@@ -56,9 +56,9 @@ class WinSLLua
switch (mode)
{
case "X":
- WinConsoleUtils.setConsoleWindowPositionX(value);
+ WindowsTerminalCPP.setConsoleWindowPositionX(value);
case "Y" :
- WinConsoleUtils.setConsoleWindowPositionY(value);
+ WindowsTerminalCPP.setConsoleWindowPositionY(value);
default:
printInDisplay("winSL_console_setWinPos: Invalid mode!", FlxColor.RED);
}
@@ -69,20 +69,20 @@ class WinSLLua
switch (mode)
{
case "X":
- var numTween:NumTween = FlxTween.num(WinConsoleUtils.returnConsolePositionX(), value, time, {
+ var numTween:NumTween = FlxTween.num(WindowsTerminalCPP.returnConsolePositionX(), value, time, {
ease: LuaUtils.getTweenEaseByString(ease),
});
numTween.onUpdate = function(twn:FlxTween)
{
- WinConsoleUtils.setConsoleWindowPositionX(Std.int(numTween.value));
+ WindowsTerminalCPP.setConsoleWindowPositionX(Std.int(numTween.value));
}
case "Y":
- var numTween:NumTween = FlxTween.num(WinConsoleUtils.returnConsolePositionY(), value, time, {
+ var numTween:NumTween = FlxTween.num(WindowsTerminalCPP.returnConsolePositionY(), value, time, {
ease: LuaUtils.getTweenEaseByString(ease),
});
numTween.onUpdate = function(twn:FlxTween)
{
- WinConsoleUtils.setConsoleWindowPositionY(Std.int(numTween.value));
+ WindowsTerminalCPP.setConsoleWindowPositionY(Std.int(numTween.value));
}
default:
printInDisplay("winSL_console_tweenWinPos: Invalid mode!", FlxColor.RED);
@@ -94,9 +94,9 @@ class WinSLLua
switch (mode)
{
case "X":
- return WinConsoleUtils.returnConsolePositionX();
+ return WindowsTerminalCPP.returnConsolePositionX();
case "Y":
- return WinConsoleUtils.returnConsolePositionY();
+ return WindowsTerminalCPP.returnConsolePositionY();
default:
printInDisplay("winSL_console_getWinPos: Invalid mode!", FlxColor.RED);
return 0;
@@ -105,7 +105,7 @@ class WinSLLua
funkLua.set("winSL_console_centerWindow", function()
{
- WinConsoleUtils.centerConsoleWindow();
+ WindowsTerminalCPP.centerConsoleWindow();
});
#end
}
diff --git a/funkinscsource/slushi/slushiLua/WindowLua.hx b/funkinscsource/slushi/slushiLua/WindowLua.hx
index 44bef67..d9fe673 100644
--- a/funkinscsource/slushi/slushiLua/WindowLua.hx
+++ b/funkinscsource/slushi/slushiLua/WindowLua.hx
@@ -10,7 +10,7 @@ class WindowLua
{
Debug.logSLEInfo("Loaded Slushi Window Lua functions!");
- funkLua.set("windowTrans", function(trans:Bool, camToApply:String = 'game')
+ funkLua.set("windowTransparent", function(transparent:Bool, camToApply:String = 'game')
{
#if windows
var blackSprite:FlxSprite = null;
@@ -24,7 +24,7 @@ class WindowLua
PlayState.instance.add(blackSprite);
}
- if (trans)
+ if (transparent)
{
CppAPI.getWindowsTransparent();
SlushiLua.apliedWindowTransparent = true;
@@ -40,25 +40,25 @@ class WindowLua
}
}
#else
- printInDisplay("windowTrans: Platform unsupported for Window transparent!", FlxColor.RED);
+ printInDisplay("windowTransparent: Platform unsupported for Window transparent!", FlxColor.RED);
#end
});
- funkLua.set("windowAlpha", function(alpha:Float)
+ funkLua.set("setWindowAlpha", function(alpha:Float)
{
#if windows
if (ClientPrefs.data.windowAlpha)
WindowFuncs.windowAlpha(alpha);
#else
- printInDisplay("WindowAlpha: Platform unsupported for this function", FlxColor.RED);
+ printInDisplay("setWindowAlpha: Platform unsupported for this function", FlxColor.RED);
#end
});
- funkLua.set("doTweenWinAlpha", function(toValue:Float, duration:Float, ease:String = "linear")
+ funkLua.set("doTweenWinAlpha", function(value:Float, duration:Float, ease:String = "linear")
{
#if windows
if (ClientPrefs.data.windowAlpha)
- WindowFuncs.doTweenWindowAlpha(toValue, duration, ease);
+ WindowFuncs.doTweenWindowAlpha(value, duration, ease);
#else
printInDisplay("doTweenWinAlpha: Platform unsupported for this function", FlxColor.RED);
#end
@@ -66,29 +66,24 @@ class WindowLua
funkLua.set("centerWindow", function()
{
- #if windows
- CppAPI.centerWindow();
- #else
- printInDisplay("centerWindow: Platform unsupported for this function", FlxColor.RED);
- #end
+ WindowFuncs.centerWindow();
});
- funkLua.set("setWindowVisible", function(visible:Bool)
+ funkLua.set("setMainWindowVisible", function(visible:Bool)
{
#if windows
CppAPI.setWindowVisible(visible);
#else
- printInDisplay("setWindowVisible: Platform unsupported for this function", FlxColor.RED);
+ printInDisplay("setMainWindowVisible: Platform unsupported for this function", FlxColor.RED);
#end
});
- #if desktop
funkLua.set("windowAlert", function(text:String, title:String)
{
WindowFuncs.windowAlert(text, title);
});
- funkLua.set("canResizableWindow", function(mode:Bool)
+ funkLua.set("resizableWindow", function(mode:Bool)
{
WindowFuncs.windowResizable(mode);
});
@@ -98,14 +93,6 @@ class WindowLua
WindowFuncs.windowMaximized(mode);
});
- funkLua.set("DisableCloseButton", function(mode:Bool)
- {
- if (mode)
- {
- Application.current.window.onClose.cancel();
- }
- });
-
funkLua.set("doTweenWinPos", function(mode:String, tag:String, value:Int, duration:Float, ease:String)
{
switch (mode)
@@ -141,6 +128,28 @@ class WindowLua
}
});
+ // funkLua.set("doubleWindowTweenX", function(offset:Float, duration:Float, ease:String)
+ // {
+ // WindowFuncs.doubleWindowTweenX(offset, duration, ease);
+ // });
+
+ funkLua.set("centerWindowTween", function(tag:String, duration:Float, ease:String)
+ {
+ var variables = MusicBeatState.getVariables("Tween");
+ var valueX = Std.int((WindowFuncs.getScreenSizeInWidth() - WindowFuncs.getWindowSizeInWidth()) / 2);
+ var valueY = Std.int((WindowFuncs.getScreenSizeInHeight() - WindowFuncs.getWindowSizeInHeight()) / 2);
+ tag = LuaUtils.formatVariable('tween_$tag');
+
+ variables.set(tag, FlxTween.tween(Application.current.window, {x: valueX, y: valueY}, duration, {
+ ease: LuaUtils.getTweenEaseByString(ease),
+ onComplete: function(twn:FlxTween)
+ {
+ PlayState.instance.callOnLuas('onTweenCompleted', [tag]);
+ variables.remove(tag);
+ }
+ }));
+ });
+
funkLua.set("resetWindowParameters", function()
{
WindowFuncs.resetWindowParameters();
@@ -159,11 +168,16 @@ class WindowLua
}
});
- funkLua.set("winTitle", function(text:String)
+ funkLua.set("setWindowTitle", function(text:String)
{
WindowFuncs.winTitle(text);
});
+ funkLua.set("getWindowTitle", function():String
+ {
+ return Application.current.window.title;
+ });
+
funkLua.set("setWindowPos", function(mode:String, value:Int)
{
switch (mode)
@@ -231,24 +245,28 @@ class WindowLua
printInDisplay("setWindowSize: Invalid mode!", FlxColor.RED);
}
});
- #end
- funkLua.set("setWindowBorderColor", function(r:Int = 0, g:Int = 0, b:Int = 0, mode:Bool = true)
+ funkLua.set("setWindowBorderColor", function(rgb:Array, mode:Bool = true)
{
#if windows
- if (WindowsFuncs.getWindowsVersion() != 0 && WindowsFuncs.getWindowsVersion() == 11)
+ if (SlushiEngineHUD.instance != null)
{
- if (SlushiEngineHUD.instance != null)
- {
- SlushiEngineHUD.instance.canChangeWindowColorWithNoteHit = mode;
- }
- CppAPI.setWindowBorderColor(r, g, b);
+ SlushiEngineHUD.instance.canChangeWindowColorWithNoteHit = mode;
}
- else
+ WindowsFuncs.setWindowBorderColor(rgb);
+ #end
+ });
+
+ funkLua.set("tweenWindowBorderColor", function(fromColor:Array, toColor:Array, duration:Float, ease:String = "linear", mode:Bool = true)
+ {
+ #if windows
+ if (SlushiEngineHUD.instance != null)
{
- printInDisplay("setWindowBorderColor: You no are in Windows 11, sorry", FlxColor.RED);
+ SlushiEngineHUD.instance.canChangeWindowColorWithNoteHit = mode;
}
+
+ WindowsFuncs.tweenWindowBorderColor(fromColor, toColor, duration, ease);
#end
- });
+ });
}
}
diff --git a/funkinscsource/slushi/slushiLua/WindowsLua.hx b/funkinscsource/slushi/slushiLua/WindowsLua.hx
index 6538bbe..661ca83 100644
--- a/funkinscsource/slushi/slushiLua/WindowsLua.hx
+++ b/funkinscsource/slushi/slushiLua/WindowsLua.hx
@@ -1,7 +1,8 @@
package slushi.slushiLua;
import psychlua.FunkinLua;
-import slushi.windows.WindowsGDIEffects;
+import slushi.windows.winGDIThings.SlushiWinGDI;
+import slushi.windows.winGDIThings.WinGDIThread;
class WindowsLua
{
@@ -31,20 +32,19 @@ class WindowsLua
funkLua.set("setWallpaper", function(image:String)
{
#if (windows && SLUSHI_CPP_CODE)
- var allPath:String = CustomFuncs.getAllPath() + 'mods/images/winAssets/' + image + '.png';
+ var allPath:String = CustomFuncs.getProgramPath() + 'mods/images/windowsAssets/' + image + '.png';
if (ClientPrefs.data.changeWallPaper)
{
if (image == "default")
{
WindowsFuncs.setOldWindowsWallpaper();
+ return;
}
- else
- {
- WindowsFuncs.changedWallpaper = true;
- CppAPI.setWallpaper(allPath);
- Debug.logSLEInfo("Wallpaper changed to: " + allPath);
- }
+
+ WindowsFuncs.changedWallpaper = true;
+ CppAPI.setWallpaper(allPath);
+ Debug.logSLEInfo("Wallpaper changed to: " + allPath);
}
#else
printInDisplay("setWallpaper: Function disabled in this build!", FlxColor.RED);
@@ -54,18 +54,18 @@ class WindowsLua
funkLua.set("winScreenCapture", function(nameToSave:String)
{
#if (windows)
- var allPath:String = CustomFuncs.getAllPath() + 'mods/images/winAssets/' + nameToSave + '.png';
+ var allPath:String = CustomFuncs.getProgramPath() + 'mods/images/windowsAssets/' + nameToSave + '.png';
if (ClientPrefs.data.winScreenShots)
{
CppAPI.screenCapture(allPath);
Debug.logSLEInfo("Screenshot saved to: " + allPath);
}
#else
- printInDisplay("setWallpaper: Function disabled in this build!", FlxColor.RED);
+ printInDisplay("winScreenCapture: Function disabled in this build!", FlxColor.RED);
#end
});
- funkLua.set("moveDesktopWindows", function(mode:String, value:Int)
+ funkLua.set("setDesktopWindowsPos", function(mode:String, value:Int)
{
#if (windows && SLUSHI_CPP_CODE)
if (ClientPrefs.data.winDesktopIcons)
@@ -79,21 +79,21 @@ class WindowsLua
case "XY":
CppAPI.moveDesktopWindowsInXY(value, value);
default:
- printInDisplay("moveDesktopWindows: Invalid value!", FlxColor.RED);
+ printInDisplay("setDesktopWindowsPos: Invalid value!", FlxColor.RED);
}
}
#else
- printInDisplay("moveDesktopWindows: Platform unsupported for this function!", FlxColor.RED);
+ printInDisplay("setDesktopWindowsPos: Platform unsupported for this function!", FlxColor.RED);
#end
});
- funkLua.set("doTweenDesktopWindows", function(mode:String, toValue:Float, duration:Float, ease:String = "linear")
+ funkLua.set("doTweenDesktopWindowsPos", function(mode:String, toValue:Float, duration:Float, ease:String = "linear")
{
#if (windows && SLUSHI_CPP_CODE)
if (ClientPrefs.data.winDesktopIcons)
WindowsFuncs.doTweenDesktopWindows(mode, toValue, duration, ease);
#else
- printInDisplay("doTweenDesktopWindows: Platform unsupported for this function!", FlxColor.RED);
+ printInDisplay("doTweenDesktopWindowsPos: Platform unsupported for this function!", FlxColor.RED);
#end
});
@@ -103,7 +103,7 @@ class WindowsLua
if (ClientPrefs.data.winDesktopIcons)
WindowsFuncs.doTweenDesktopWindowsAlpha(fromValue, toValue, duration, ease);
#else
- printInDisplay("setDesktopWindowsAlpha: Platform unsupported for this function!", FlxColor.RED);
+ printInDisplay("doTweenDesktopWindowsAlpha: Platform unsupported for this function!", FlxColor.RED);
#end
});
@@ -113,7 +113,7 @@ class WindowsLua
if (ClientPrefs.data.winDesktopIcons)
WindowsFuncs.doTweenTaskBarAlpha(fromValue, toValue, duration, ease);
#else
- printInDisplay("setDesktopWindowsAlpha: Platform unsupported for this function!", FlxColor.RED);
+ printInDisplay("doTweenTaskBarAlpha: Platform unsupported for this function!", FlxColor.RED);
#end
});
@@ -147,13 +147,13 @@ class WindowsLua
#end
});
- funkLua.set("sendNoti", function(desc:String, title:String)
+ funkLua.set("sendNotification", function(desc:String, title:String)
{
#if windows
if (ClientPrefs.data.windowsNotifications)
WindowsFuncs.sendWindowsNotification(desc, title);
#else
- printInDisplay("sendNoti: Platform unsupported for this function!", FlxColor.RED);
+ printInDisplay("sendNotification: Platform unsupported for this function!", FlxColor.RED);
#end
});
@@ -221,23 +221,55 @@ class WindowsGDI
{
Debug.logSLEInfo("Loaded Slushi Windows GDI Lua functions!");
- funkLua.set("windowsEffectModifier", function(tag:String = "", gdiEffect:String, activeEffect:Bool)
+ funkLua.set("startGDIThread", function()
+ {
+ #if windows
+ if (ClientPrefs.data.gdiEffects)
+ {
+ WinGDIThread.initThread();
+ }
+ #else
+ printInDisplay("startThread: Platform unsupported for this function", FlxColor.RED);
+ #end
+ });
+
+ funkLua.set("prepareGDIEffect", function(effect:String, wait:Float = 0)
+ {
+ #if windows
+ if (ClientPrefs.data.gdiEffects)
+ SlushiWinGDI.prepareGDIEffect(effect, wait);
+ #else
+ printInDisplay("prepareGDIEffect: Platform unsupported for this function", FlxColor.RED);
+ #end
+ });
+
+ funkLua.set("setGDIEffectWaitTime", function(effect:String, wait:Float = 0)
+ {
+ #if windows
+ if (ClientPrefs.data.gdiEffects)
+ SlushiWinGDI.setGDIEffectWaitTime(effect, wait);
+ #else
+ printInDisplay("setGDIEffectWaitTime: Platform unsupported for this function", FlxColor.RED);
+ #end
+ });
+
+ funkLua.set("enableGDIEffect", function(effect:String, enabled:Bool)
{
#if windows
if (ClientPrefs.data.gdiEffects)
- WindowsGDIEffects.checkEffect(tag, gdiEffect, activeEffect);
+ SlushiWinGDI.enableGDIEffect(effect, enabled);
#else
- printInDisplay("windowsEffectModifier: Platform unsupported for this function", FlxColor.RED);
+ printInDisplay("enableGDIEffect: Platform unsupported for this function", FlxColor.RED);
#end
});
- funkLua.set("setWinEffectProperty", function(tag:String, prop:String, value:Dynamic)
+ funkLua.set("removeGDIEffect", function(effect:String)
{
#if windows
if (ClientPrefs.data.gdiEffects)
- WindowsGDIEffects.setWinEffectProperty(tag, prop, value);
+ SlushiWinGDI.removeGDIEffect(effect);
#else
- printInDisplay("setWinEffectProperty: Platform unsupported for this function", FlxColor.RED);
+ printInDisplay("removeGDIEffect: Platform unsupported for this function", FlxColor.RED);
#end
});
@@ -245,7 +277,7 @@ class WindowsGDI
{
#if windows
if (ClientPrefs.data.gdiEffects)
- WindowsGDIEffects._setCustomTitleTextToWindows(titleText);
+ SlushiWinGDI._setCustomTitleTextToWindows(titleText);
#else
printInDisplay("setTitleTextToWindows: Platform unsupported for this function", FlxColor.RED);
#end
diff --git a/funkinscsource/slushi/slushiUtils/Debug.hx b/funkinscsource/slushi/slushiUtils/Debug.hx
index d3d21c9..be5624c 100644
--- a/funkinscsource/slushi/slushiUtils/Debug.hx
+++ b/funkinscsource/slushi/slushiUtils/Debug.hx
@@ -19,6 +19,7 @@ class Debug
static final LOG_STYLE_SLE_ERROR:LogStyle = new LogStyle('[ERROR] ', 'FF8888', 12, true, false, false, 'flixel/sounds/beep', true);
static final LOG_STYLE_SLE_WARN:LogStyle = new LogStyle('[WARN] ', 'D9F85C', 12, true, false, false, 'flixel/sounds/beep', true);
static final LOG_STYLE_SLE_INFO:LogStyle = new LogStyle('[INFO] ', '5CF878', 12, false);
+ static final LOG_STYLE_SLE_SUCCESS:LogStyle = new LogStyle('[TRACE] ', '5CF878', 12, false);
static var logFileWriter:DebugLogWriter = null;
@@ -110,6 +111,16 @@ class Debug
writeToLogFile(output, 'SLEERROR');
}
+
+ public static inline function logSLESuccess(input:Dynamic, ?pos:haxe.PosInfos):Void
+ {
+ if (input == null)
+ return;
+ var output = formatOutput(input, pos);
+ writeToFlxGLog(output, LOG_STYLE_SLE_SUCCESS);
+ writeToLogFile(output, 'SLE_INFO');
+ }
+
/**
* Displays a popup with the provided text.
* This interrupts the game, so make sure it's REALLY important.
@@ -370,7 +381,7 @@ class Debug
class DebugLogWriter
{
static final LOG_FOLDER = "assets/debugLogs/logs";
- public static final LOG_LEVELS = ['SLE_INFO', 'SLE_WARN', 'SLE_ERROR', 'ERROR', 'WARN', 'INFO', 'TRACE'];
+ public static final LOG_LEVELS = ['SLE_INFO', 'SLE_WARN', 'SLE_ERROR', 'SLE_SUCCESS', 'ERROR', 'WARN', 'INFO', 'TRACE'];
/**
* Set this to the current timestamp that the game started.
@@ -462,6 +473,8 @@ class DebugLogWriter
return "\033[33;2m";
case 'SLE_ERROR':
return "\033[31;2m";
+ case 'SLE_SUCCESS':
+ return "\x1b[38;5;70m";
case 'ERROR':
return "\033[31m";
case 'WARN':
@@ -524,4 +537,4 @@ class DebugLogWriter
haxe.Log.trace(msg, null);
#end
}
-}
+}
\ No newline at end of file
diff --git a/funkinscsource/slushi/slushiUtils/LyricsUtils.hx b/funkinscsource/slushi/slushiUtils/LyricsUtils.hx
index be8c304..bf8a359 100644
--- a/funkinscsource/slushi/slushiUtils/LyricsUtils.hx
+++ b/funkinscsource/slushi/slushiUtils/LyricsUtils.hx
@@ -4,7 +4,7 @@ import tjson.TJSON as Json;
import psychlua.LuaUtils;
/*
- * This class is used to display lyrics on the gameplay, using a json file
+ * This class is used to display lyrics on the gameplay, using a JSON file
*
* Author: Slushi
*/
@@ -59,7 +59,7 @@ class LyricsUtils extends FlxSprite
if (lyricsJsonData.textConfig.textColor == null)
mainText.color = FlxColor.WHITE;
if (lyricsJsonData.textConfig.camera == null)
- mainText.camera = LuaUtils.cameraFromString("camfor3d");
+ mainText.camera = LuaUtils.cameraFromString("camthings");
}
catch (e)
{
@@ -117,6 +117,7 @@ class LyricsUtils extends FlxSprite
catch (e)
{
Debug.logSLEError('Failed to load lyrics file data: $e');
+ stop = true;
}
}
diff --git a/funkinscsource/slushi/slushiUtils/SlushiDebugText.hx b/funkinscsource/slushi/slushiUtils/SlushiDebugText.hx
index e2e9083..be8897e 100644
--- a/funkinscsource/slushi/slushiUtils/SlushiDebugText.hx
+++ b/funkinscsource/slushi/slushiUtils/SlushiDebugText.hx
@@ -46,8 +46,6 @@ class SlushiDebugText extends FlxSpriteGroup
FlxTween.tween(text, {x: text.x + 15}, 0.4, {ease: FlxEase.linear});
- logInfo("Text to print: " + textToPrint);
-
new FlxTimer().start(timeToHide, function(tmr:FlxTimer)
{
FlxTween.tween(txtSpriteBG, {alpha: 0}, 0.4, {ease: FlxEase.linear});
diff --git a/funkinscsource/slushi/slushiUtils/SlushiEngineHUD.hx b/funkinscsource/slushi/slushiUtils/SlushiEngineHUD.hx
index 605bd59..0e43703 100644
--- a/funkinscsource/slushi/slushiUtils/SlushiEngineHUD.hx
+++ b/funkinscsource/slushi/slushiUtils/SlushiEngineHUD.hx
@@ -7,7 +7,6 @@ import psychlua.LuaUtils;
*
* Author: Slushi
*/
-
class SlushiEngineHUD extends FlxSprite
{
public static var instance:SlushiEngineHUD;
@@ -31,38 +30,40 @@ class SlushiEngineHUD extends FlxSprite
posX: 20,
posY: 52,
// Colors:
- SwagColor: 0xff8FD9D1,
- SickColor: 0xFFFFFB00,
- GoodColor: 0xFF00EB1F,
- BadColor: 0xFFFF2600,
- ShitColor: 0xFF555555
+ swagColor: 0xff8FD9D1,
+ sickColor: 0xFFFFFB00,
+ goodColor: 0xFF00EB1F,
+ badColor: 0xFFFF2600,
+ shitColor: 0xFF555555
};
static var comboText:FlxText;
- static var SwagText:FlxText;
- static var SickText:FlxText;
- static var GoodText:FlxText;
- static var BadText:FlxText;
- static var ShitText:FlxText;
+ static var swagText:FlxText;
+ static var sickText:FlxText;
+ static var goodText:FlxText;
+ static var badText:FlxText;
+ static var shitText:FlxText;
public var sleVer:FlxText;
public var scengine:FlxText;
- static var camSLEHUD:FlxCamera;
- static var camWaterMark:FlxCamera;
- static var camHUD:FlxCamera;
+ private static var camSLEHUD:FlxCamera;
+ private static var camWaterMark:FlxCamera;
+ private static var camHUD:FlxCamera;
+
+ private static var leftNoteColor:Array = [194, 75, 153];
+ private static var downNoteColor:Array = [0, 253, 253];
+ private static var upNoteColor:Array = [18, 250, 5];
+ private static var rightNoteColor:Array = [249, 58, 63];
+ private static var slushiWindowColor:Array = [214, 243, 222];
- static var leftNoteColor:Array = [194, 75, 153];
- static var downNoteColor:Array = [0, 253, 253];
- static var upNoteColor:Array = [18, 250, 5];
- static var rightNoteColor:Array = [249, 58, 63];
- static var slushiWindowColor:Array = [214, 243, 222];
public var canChangeWindowColorWithNoteHit:Bool = true;
- static var tweenDuration:Float = 0.3;
- static var windowColorNumTween:NumTween;
- static var forward:Bool = false;
- static var comboTxtTween:FlxTween;
- static var comboAlphaTween:FlxTween;
+ private static var tweenDuration:Float = 0.3;
+ private static var windowColorNumTween:NumTween;
+ private static var forward:Bool = false;
+
+ private static var comboTxtTween:FlxTween;
+ private static var comboAlphaTween:FlxTween;
public function new()
{
@@ -82,14 +83,14 @@ class SlushiEngineHUD extends FlxSprite
// camHUD.visible = false;
bgSprite = new FlxSprite(0, 0);
- bgSprite.loadGraphic(SlushiMain.getSLEPath('SLEHUDImages/BG.png'));
+ bgSprite.loadGraphic(SlushiMain.getSLEPath('SlushiEngineHUDAssets/BG.png'));
bgSprite.scrollFactor.set(0, 0);
bgSprite.antialiasing = ClientPrefs.data.antialiasing;
bgSprite.cameras = [camSLEHUD];
addToCurrentState(bgSprite);
slushiSprite = new FlxSprite(SLELogo.posX, SLELogo.posY);
- slushiSprite.loadGraphic(SlushiMain.getSLEPath('SLEHUDImages/Slushi.png'));
+ slushiSprite.loadGraphic(SlushiMain.getSLEPath('SlushiEngineHUDAssets/Slushi.png'));
slushiSprite.scrollFactor.set(0, 0);
slushiSprite.scale.set(0.8, 0.8);
slushiSprite.antialiasing = ClientPrefs.data.antialiasing;
@@ -97,7 +98,7 @@ class SlushiEngineHUD extends FlxSprite
addToCurrentState(slushiSprite);
sceSprite = new FlxSprite(SLELogo.posX, SLELogo.posY);
- sceSprite.loadGraphic(SlushiMain.getSLEPath('SLEHUDImages/SCEngineText.png'));
+ sceSprite.loadGraphic(SlushiMain.getSLEPath('SlushiEngineHUDAssets/SCEngineText.png'));
sceSprite.scrollFactor.set(0, 0);
sceSprite.scale.set(0.8, 0.8);
sceSprite.antialiasing = ClientPrefs.data.antialiasing;
@@ -105,7 +106,7 @@ class SlushiEngineHUD extends FlxSprite
addToCurrentState(sceSprite);
notesSprite = new FlxSprite(SLELogo.posX, SLELogo.posY);
- notesSprite.loadGraphic(SlushiMain.getSLEPath('SLEHUDImages/Notes.png'));
+ notesSprite.loadGraphic(SlushiMain.getSLEPath('SlushiEngineHUDAssets/Notes.png'));
notesSprite.scrollFactor.set(0, 0);
notesSprite.scale.set(0.8, 0.8);
notesSprite.antialiasing = ClientPrefs.data.antialiasing;
@@ -113,7 +114,7 @@ class SlushiEngineHUD extends FlxSprite
addToCurrentState(notesSprite);
sleSprite = new FlxSprite(SLELogo.posX, SLELogo.posY);
- sleSprite.loadGraphic(SlushiMain.getSLEPath('SLEHUDImages/SlushiEngineText.png'));
+ sleSprite.loadGraphic(SlushiMain.getSLEPath('SlushiEngineHUDAssets/SlushiEngineText.png'));
sleSprite.scrollFactor.set(0, 0);
sleSprite.scale.set(0.8, 0.8);
sleSprite.antialiasing = ClientPrefs.data.antialiasing;
@@ -140,52 +141,46 @@ class SlushiEngineHUD extends FlxSprite
// COMBO: //////////////////////////////////////////
- SwagText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "SICK!!!");
- SwagText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
- SwagText.scrollFactor.set();
- SwagText.borderSize = 1.25;
- SwagText.color = data_judgements.SwagColor;
- SwagText.cameras = [camSLEHUD];
-
- SickText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "SICK!!");
- SickText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
- SickText.scrollFactor.set();
- SickText.borderSize = 1.25;
- SickText.color = data_judgements.SickColor;
- SickText.cameras = [camSLEHUD];
-
- GoodText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "Good!");
- GoodText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
- GoodText.scrollFactor.set();
- GoodText.borderSize = 1.25;
- GoodText.color = data_judgements.GoodColor;
- GoodText.cameras = [camSLEHUD];
-
- BadText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "Bad");
- BadText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
- BadText.scrollFactor.set();
- BadText.borderSize = 1.25;
- BadText.color = data_judgements.BadColor;
- BadText.cameras = [camSLEHUD];
-
- ShitText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "Shit...");
- ShitText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
- ShitText.scrollFactor.set();
- ShitText.borderSize = 1.25;
- ShitText.color = data_judgements.ShitColor;
- ShitText.cameras = [camSLEHUD];
-
- addToCurrentState(SwagText);
- addToCurrentState(SickText);
- addToCurrentState(GoodText);
- addToCurrentState(BadText);
- addToCurrentState(ShitText);
-
- SickText.alpha = 0;
- SwagText.alpha = 0;
- GoodText.alpha = 0;
- BadText.alpha = 0;
- ShitText.alpha = 0;
+ swagText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "SICK!!!");
+ swagText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ swagText.scrollFactor.set();
+ swagText.borderSize = 1.25;
+ swagText.color = data_judgements.swagColor;
+ swagText.cameras = [camSLEHUD];
+
+ sickText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "SICK!!");
+ sickText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ sickText.scrollFactor.set();
+ sickText.borderSize = 1.25;
+ sickText.color = data_judgements.sickColor;
+ sickText.cameras = [camSLEHUD];
+
+ goodText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "Good!");
+ goodText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ goodText.scrollFactor.set();
+ goodText.borderSize = 1.25;
+ goodText.color = data_judgements.goodColor;
+ goodText.cameras = [camSLEHUD];
+
+ badText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "Bad");
+ badText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ badText.scrollFactor.set();
+ badText.borderSize = 1.25;
+ badText.color = data_judgements.badColor;
+ badText.cameras = [camSLEHUD];
+
+ shitText = new FlxText(comboText.x + data_judgements.posX, data_judgements.posY, 0, "Shit...");
+ shitText.setFormat(Paths.font("wendy.ttf"), 30, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ shitText.scrollFactor.set();
+ shitText.borderSize = 1.25;
+ shitText.color = data_judgements.shitColor;
+ shitText.cameras = [camSLEHUD];
+
+ for (comboTextobj in [swagText, sickText, goodText, badText, shitText])
+ {
+ addToCurrentState(comboTextobj);
+ comboTextobj.alpha = 0;
+ }
/////////////////////////////////////////////////////////////
}
@@ -197,7 +192,7 @@ class SlushiEngineHUD extends FlxSprite
sleVer.visible = !ClientPrefs.data.hideHud;
addToCurrentState(sleVer);
- scengine = new FlxText(10, FlxG.height - 42, 0, "SC Engine v" + states.MainMenuState.SCEVersion +' (${SlushiMain.sceGitCommit})', 10);
+ scengine = new FlxText(10, FlxG.height - 42, 0, "SC Engine v" + states.MainMenuState.SCEVersion + ' (${SlushiMain.sceGitCommit})', 10);
scengine.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
scengine.scrollFactor.set();
scengine.borderSize = 1.25;
@@ -217,8 +212,10 @@ class SlushiEngineHUD extends FlxSprite
if (PlayState.instance.useSLEHUD)
{
if (PlayState.instance != null)
+ {
comboText.text = "COMBO: " + PlayState.instance.combo;
- comboText.screenCenter(X);
+ }
+ comboText.screenCenter(X);
}
}
@@ -273,12 +270,12 @@ class SlushiEngineHUD extends FlxSprite
}
/* Y gracias Trock por hacerme este codigo para en un principio Lua
- (And thanks Trock for making me this code for Lua in the first place)
- function onTimerCompleted(tag)
- local nameAlpha = string.gsub(tag, "Timer", "Alpha")
- local textAlpha = string.gsub(tag, "Timer", "Text")
- doTweenAlpha(nameAlpha, textAlpha, 0, data_judgements.timeTween, "Linear")
- end
+ (And thanks Trock for making me this code for Lua in the first place)
+ function onTimerCompleted(tag)
+ local nameAlpha = string.gsub(tag, "Timer", "Alpha")
+ local textAlpha = string.gsub(tag, "Timer", "Text")
+ doTweenAlpha(nameAlpha, textAlpha, 0, data_judgements.timeTween, "Linear")
+ end
*/
}
@@ -287,40 +284,40 @@ class SlushiEngineHUD extends FlxSprite
switch (rating)
{
case "swag":
- SwagText.alpha = 1;
+ swagText.alpha = 1;
doComboAlpha(0);
- SickText.alpha = 0;
- GoodText.alpha = 0;
- BadText.alpha = 0;
- ShitText.alpha = 0;
+ sickText.alpha = 0;
+ goodText.alpha = 0;
+ badText.alpha = 0;
+ shitText.alpha = 0;
case "sick":
- SickText.alpha = 1;
+ sickText.alpha = 1;
doComboAlpha(1);
- SwagText.alpha = 0;
- GoodText.alpha = 0;
- BadText.alpha = 0;
- ShitText.alpha = 0;
+ swagText.alpha = 0;
+ goodText.alpha = 0;
+ badText.alpha = 0;
+ shitText.alpha = 0;
case "good":
- GoodText.alpha = 1;
+ goodText.alpha = 1;
doComboAlpha(2);
- BadText.alpha = 0;
- SwagText.alpha = 0;
- BadText.alpha = 0;
- ShitText.alpha = 0;
+ badText.alpha = 0;
+ swagText.alpha = 0;
+ badText.alpha = 0;
+ shitText.alpha = 0;
case "bad":
- BadText.alpha = 1;
+ badText.alpha = 1;
doComboAlpha(3);
- GoodText.alpha = 0;
- SwagText.alpha = 0;
- SickText.alpha = 0;
- ShitText.alpha = 0;
+ goodText.alpha = 0;
+ swagText.alpha = 0;
+ sickText.alpha = 0;
+ shitText.alpha = 0;
case "shit":
- ShitText.alpha = 1;
+ shitText.alpha = 1;
doComboAlpha(4);
- BadText.alpha = 0;
- SwagText.alpha = 0;
- GoodText.alpha = 0;
- SickText.alpha = 0;
+ badText.alpha = 0;
+ swagText.alpha = 0;
+ goodText.alpha = 0;
+ sickText.alpha = 0;
}
}
@@ -329,14 +326,14 @@ class SlushiEngineHUD extends FlxSprite
if (!PlayState.instance.useSLEHUD)
return;
- var newScale = 1.2;
+ final newScale = 1.2;
if (comboTxtTween != null)
comboTxtTween.cancel();
comboText.scale.x = newScale;
comboText.scale.y = newScale;
-
+
comboTxtTween = PlayState.instance.createTween(comboText.scale, {x: 1, y: 1}, 0.2, {
onComplete: function(twn:FlxTween)
{
@@ -353,40 +350,40 @@ class SlushiEngineHUD extends FlxSprite
switch (comboToTween)
{
case 0:
- SwagText.alpha = 1;
- comboAlphaTween = PlayState.instance.createTween(SwagText, {alpha: 0}, 0.2, {
+ swagText.alpha = 1;
+ comboAlphaTween = PlayState.instance.createTween(swagText, {alpha: 0}, 0.2, {
onComplete: function(twn:FlxTween)
{
comboAlphaTween = null;
}
});
case 1:
- SickText.alpha = 1;
- comboAlphaTween = PlayState.instance.createTween(SickText, {alpha: 0}, 0.2, {
+ sickText.alpha = 1;
+ comboAlphaTween = PlayState.instance.createTween(sickText, {alpha: 0}, 0.2, {
onComplete: function(twn:FlxTween)
{
comboAlphaTween = null;
}
});
case 2:
- GoodText.alpha = 1;
- comboAlphaTween = PlayState.instance.createTween(GoodText, {alpha: 0}, 0.2, {
+ goodText.alpha = 1;
+ comboAlphaTween = PlayState.instance.createTween(goodText, {alpha: 0}, 0.2, {
onComplete: function(twn:FlxTween)
{
comboAlphaTween = null;
}
});
case 3:
- BadText.alpha = 1;
- comboAlphaTween = PlayState.instance.createTween(BadText, {alpha: 0}, 0.2, {
+ badText.alpha = 1;
+ comboAlphaTween = PlayState.instance.createTween(badText, {alpha: 0}, 0.2, {
onComplete: function(twn:FlxTween)
{
comboAlphaTween = null;
}
});
case 4:
- ShitText.alpha = 1;
- comboAlphaTween = PlayState.instance.createTween(ShitText, {alpha: 0}, 0.2, {
+ shitText.alpha = 1;
+ comboAlphaTween = PlayState.instance.createTween(shitText, {alpha: 0}, 0.2, {
onComplete: function(twn:FlxTween)
{
comboAlphaTween = null;
@@ -395,6 +392,77 @@ class SlushiEngineHUD extends FlxSprite
}
}
+ public static function setParamsFromPlayerNote(noteStrumTime:Float, isSustain:Bool, noteID:Int)
+ {
+ if (PlayState.instance.useSLEHUD)
+ {
+ setRatingText(noteStrumTime - Conductor.songPosition);
+ if (!isSustain)
+ {
+ doComboAngle();
+ }
+ }
+ #if windows
+ if (ClientPrefs.data.changeWindowBorderColorWithNoteHit && instance.canChangeWindowColorWithNoteHit && !isSustain)
+ {
+ setWindowColorWithNoteHit(noteID);
+ }
+ #end
+ }
+
+ public static function setNotITGNotesInSteps(curStep:Int):Void
+ {
+ // AHHH GACIAS EDWHAK POR ESTO!!!!
+ var animSkins:Array = ['Default', 'Future', 'NotITG'];
+ if ((PlayState.SONG.notITG || PlayState.SONG.options.notITG) && PlayState.instance.notITGMod)
+ {
+ for (i in 0...animSkins.length)
+ {
+ if (ClientPrefs.data.noteSkin.contains(animSkins[i]))
+ {
+ if (curStep % 4 == 0)
+ {
+ for (this2 in PlayState.instance.opponentStrums)
+ {
+ if (this2.animation.curAnim.name == 'static')
+ {
+ this2.rgbShader.r = 0xFF808080;
+ this2.rgbShader.b = 0xFF474747;
+ this2.rgbShader.enabled = true;
+ }
+ }
+ for (this2 in PlayState.instance.playerStrums)
+ {
+ if (this2.animation.curAnim.name == 'static')
+ {
+ this2.rgbShader.r = 0xFF808080;
+ this2.rgbShader.b = 0xFF474747;
+ this2.rgbShader.enabled = true;
+ }
+ }
+ }
+ else if (curStep % 4 == 1)
+ {
+ for (this2 in PlayState.instance.opponentStrums)
+ {
+ if (this2.animation.curAnim.name == 'static')
+ {
+ this2.rgbShader.enabled = false;
+ }
+ }
+ for (this2 in PlayState.instance.playerStrums)
+ {
+ if (this2.animation.curAnim.name == 'static')
+ {
+ this2.rgbShader.enabled = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
public static function setOthersParamOfTheHUD()
{
if (PlayState.instance.useSLEHUD)
@@ -421,7 +489,6 @@ class SlushiEngineHUD extends FlxSprite
PlayState.instance.timeTxt.y = FlxG.height - 44;
PlayState.instance.botplayTxt.y = PlayState.instance.timeBar.y - 78;
- PlayState.instance.timeBarNew.camera = camSLEHUD;
Debug.logSLEInfo('Trying to optimize and prepare the engine...');
for (i in [PlayState.instance.boyfriend, PlayState.instance.dad, PlayState.instance.gf])
if (i != null)
@@ -437,7 +504,7 @@ class SlushiEngineHUD extends FlxSprite
//////////////////////////////////////////////////////////////////////////////////////////////
#if windows
- public static function setWindowColorWithNoteHit(note:Int/*, currentNoteColor:Array*/):Void
+ public static function setWindowColorWithNoteHit(note:Int /*, currentNoteColor:Array*/):Void
{
switch (note)
{
@@ -462,95 +529,89 @@ class SlushiEngineHUD extends FlxSprite
}
static function startColorTween(index:Int, forward:Bool, duration:Float):Void
+ {
+ var tweenActived:Bool = false;
+
+ if (tweenActived)
+ return;
+
+ var targetColor:Array = [];
+ var startColor:Array = [];
+
+ switch (index)
{
- var tweenActived:Bool = false;
-
- if (tweenActived)
- return;
-
- var targetColor:Array = [];
- var startColor:Array = [];
-
- switch (index)
- {
- case 0:
- startColor = slushiWindowColor;
- targetColor = leftNoteColor;
- case 1:
- startColor = slushiWindowColor;
- targetColor = downNoteColor;
- case 2:
- startColor = slushiWindowColor;
- targetColor = upNoteColor;
- case 3:
- startColor = slushiWindowColor;
- targetColor = rightNoteColor;
- }
-
- if (!forward)
- {
- var temp:Array = startColor;
- startColor = targetColor;
- targetColor = temp;
- }
-
- tweenActived = true;
- if (windowColorNumTween != null)
+ case 0:
+ startColor = slushiWindowColor;
+ targetColor = leftNoteColor;
+ case 1:
+ startColor = slushiWindowColor;
+ targetColor = downNoteColor;
+ case 2:
+ startColor = slushiWindowColor;
+ targetColor = upNoteColor;
+ case 3:
+ startColor = slushiWindowColor;
+ targetColor = rightNoteColor;
+ }
+
+ if (!forward)
+ {
+ var temp:Array = startColor;
+ startColor = targetColor;
+ targetColor = temp;
+ }
+
+ tweenActived = true;
+ if (windowColorNumTween != null)
+ {
+ windowColorNumTween.cancel();
+ windowColorNumTween = null;
+ }
+
+ windowColorNumTween = FlxTween.num(0, 1, duration, {
+ onComplete: function(tween:FlxTween)
{
- windowColorNumTween.cancel();
- windowColorNumTween = null;
- }
-
- windowColorNumTween = FlxTween.num(0, 1, duration, {
- onComplete: function(tween:FlxTween)
+ if (forward)
{
- if (forward)
- {
- startColorTween(index, false, duration);
- }
+ startColorTween(index, false, duration);
}
- });
-
- windowColorNumTween.onUpdate = function(tween:FlxTween)
+ }
+ });
+
+ windowColorNumTween.onUpdate = function(tween:FlxTween)
+ {
+ var interpolatedColor:Array = [];
+ for (i in 0...3)
{
- var interpolatedColor:Array = [];
- for (i in 0...3)
- {
- var newValue:Int = startColor[i] + Std.int((targetColor[i] - startColor[i]) * windowColorNumTween.value);
- newValue = Std.int(Math.max(0, Math.min(255, newValue)));
- interpolatedColor.push(newValue);
- }
- WindowsFuncs.setWindowBorderColor(interpolatedColor);
- tweenActived = false;
- };
- }
+ var newValue:Int = startColor[i] + Std.int((targetColor[i] - startColor[i]) * windowColorNumTween.value);
+ newValue = Std.int(Math.max(0, Math.min(255, newValue)));
+ interpolatedColor.push(newValue);
+ }
+ WindowsFuncs.setWindowBorderColor(interpolatedColor);
+ tweenActived = false;
+ };
+ }
// static function startColorTween(index:Int, forward:Bool, duration:Float, currentNoteColor:Array):Void
// {
// var tweenActived:Bool = false;
-
// if (tweenActived)
// return;
-
// Debug.logSLEInfo("Note color RGB: " + currentNoteColor[0] + ", " + currentNoteColor[1] + ", " + currentNoteColor[2]);
-
// var targetColor:Array = currentNoteColor;
// var startColor:Array = slushiWindowColor;
-
// if (!forward)
// {
// var temp:Array = startColor;
// startColor = targetColor;
// targetColor = temp;
// }
-
// tweenActived = true;
// if (windowColorNumTween != null)
// {
// windowColorNumTween.cancel();
// windowColorNumTween = null;
// }
-
// windowColorNumTween = FlxTween.num(0, 1, duration, {
// onComplete: function(tween:FlxTween)
// {
@@ -560,7 +621,6 @@ class SlushiEngineHUD extends FlxSprite
// }
// }
// });
-
// windowColorNumTween.onUpdate = function(tween:FlxTween)
// {
// var interpolatedColor:Array = [];
@@ -575,46 +635,44 @@ class SlushiEngineHUD extends FlxSprite
// };
// }
#end
-
//////////////////////////////////////////////////////////////////////////////////////////////
public function moveSLELogoX(xValue:Float, time:Float, ease:String)
{
- FlxTween.tween(slushiSprite, {x: xValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sceSprite, {x: xValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(notesSprite, {x: xValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sleSprite, {x: xValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ for (sleHUDObj in [slushiSprite, sceSprite, notesSprite, sleSprite])
+ {
+ FlxTween.tween(sleHUDObj, {x: xValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ }
if (xValue == -1)
{
- FlxTween.tween(slushiSprite, {x: SLELogo.posX}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sceSprite, {x: SLELogo.posX}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(notesSprite, {x: SLELogo.posX}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sleSprite, {x: SLELogo.posX}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ for (sleHUDObj in [slushiSprite, sceSprite, notesSprite, sleSprite])
+ {
+ FlxTween.tween(sleHUDObj, {x: SLELogo.posX}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ }
}
}
public function moveSLELogoY(yValue:Float, time:Float, ease:String)
{
- FlxTween.tween(slushiSprite, {y: yValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sceSprite, {y: yValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(notesSprite, {y: yValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sleSprite, {y: yValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
-
+ for (sleHUDObj in [slushiSprite, sceSprite, notesSprite, sleSprite])
+ {
+ FlxTween.tween(sleHUDObj, {y: yValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ }
if (yValue == -1)
{
- FlxTween.tween(slushiSprite, {y: SLELogo.posY}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sceSprite, {y: SLELogo.posY}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(notesSprite, {y: SLELogo.posY}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sleSprite, {y: SLELogo.posY}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ for (sleHUDObj in [slushiSprite, sceSprite, notesSprite, sleSprite])
+ {
+ FlxTween.tween(sleHUDObj, {y: SLELogo.posY}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ }
}
}
public function moveSLELogoAngle(angleValue:Float, time:Float, ease:String)
{
- FlxTween.tween(slushiSprite, {angle: angleValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sceSprite, {angle: angleValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(notesSprite, {angle: angleValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
- FlxTween.tween(sleSprite, {angle: angleValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ for (sleHUDObj in [slushiSprite, sceSprite, notesSprite, sleSprite])
+ {
+ FlxTween.tween(sleHUDObj, {angle: angleValue}, time, {ease: LuaUtils.getTweenEaseByString(ease)});
+ }
}
public function setblackAlpha(alphaValue:Float, time:Float)
@@ -626,4 +684,4 @@ class SlushiEngineHUD extends FlxSprite
FlxTween.tween(blackGraphic, {alpha: SLELogo.blackAlpha}, time, {ease: FlxEase.quadInOut});
}
}
-}
\ No newline at end of file
+}
diff --git a/funkinscsource/slushi/slushiUtils/crashHandler/CrashHandler.hx b/funkinscsource/slushi/slushiUtils/crashHandler/CrashHandler.hx
index 78123d3..0b7485f 100644
--- a/funkinscsource/slushi/slushiUtils/crashHandler/CrashHandler.hx
+++ b/funkinscsource/slushi/slushiUtils/crashHandler/CrashHandler.hx
@@ -5,10 +5,8 @@ import haxe.CallStack;
import haxe.io.Path;
import flixel.system.scaleModes.*;
import flixel.group.FlxGroup;
-
import lime.system.System;
import utils.DateUtil;
-
import states.StoryMenuState;
import states.freeplay.FreeplayState;
import states.MainMenuState;
@@ -19,11 +17,15 @@ import states.MainMenuState;
class CrashHandler
{
public static var inCrash:Bool = false;
+ public static var crashes:Int = 0;
+ public static var crashesLimit:Int = 5;
public static var createdCrashInGame:Bool = false;
+ private static var flxFuncNum:Int = -1;
- public static function symbolPrevent(error:Dynamic)
+ public static function symbolPrevent(error:Dynamic, ?flxFuncInt:Int = -1):Void
{
onUncaughtError(error);
+ flxFuncNum = flxFuncInt;
}
public static function initCrashHandler()
@@ -41,19 +43,17 @@ class CrashHandler
private static function onCPPError(message:Dynamic):Void
{
- var randomsMsg:String = "";
- var errMsg:String = "";
var mainText:String = 'C++ side critical error!:\n';
#if cpp
throw Std.string(message);
- Sys.exit(1);
+ System.exit(1);
#if windows
CppAPI.showMessageBox(mainText + message, "Slushi Engine [C++]: Crash Handler", MSG_ERROR);
- Sys.exit(1);
+ System.exit(1);
#else
WindowFuncs.windowAlert(mainText + message, "Slushi Engine [C++]: Crash Handler");
- Sys.exit(1);
+ System.exit(1);
#end
#end
}
@@ -65,20 +65,36 @@ class CrashHandler
"It was Bolo!", // Glowsoony
"El pollo ardiente", // Edwhak
"Apuesto que este error viene de SCE y no SLE, verdad..?", // Slushi
- "Null References: The Billion Dollar Mistake" // Trock
+ "Null References: The Billion Dollar Mistake", // Trock
+ "GLOW PAGAME EL POLLO", // Slushi
];
static function onUncaughtError(e:Dynamic):Void
{
- if (inCrash) {
- Debug.logSLEWarn("Trying to make a second crash while is already in a crash with error: [" + e + "], skipping this...");
+ if (inCrash)
+ {
+ Debug.logSLEWarn("Trying to make a another crash while is already in a crash with error: [" + e + "]. Crash counter: [" + crashes + "], skipping it...");
+ crashes++;
+ if (crashes == crashesLimit)
+ {
+ Debug.logSLEWarn("Too many crashes, quitting...");
+ #if windows
+ CppAPI.showMessageBox("Many crashes occurred in a short time, SLE will close to avoid entering a loop.\n\nThe logs can be found in [./assets/debugLogs/crashes/]\nPlease contact with @slushi_ds in Discord or add an issue in the engine repository if you think it is a bug in SLE.",
+ "Slushi Engine: Crash Handler", MSG_INFORMATION);
+ #else
+ WindowFuncs.windowAlert("Too many crashes, the engine will close!\n\nThe logs can be found in [./assets/debugLogs/crashes/]\nPlease contact with @slushi_ds in Discord or add an issue in the engine repository if you think it is a bug in SLE.",
+ "Slushi Engine: Crash Handler");
+ #end
+ System.exit(1);
+ }
return;
};
+
inCrash = true;
var randomsMsg:String = "";
- var errMsg:String = "";
- var callstackText:String = "";
+ var callStackText:String = "";
+ var callStackForEditorText:String = "";
var path:String;
var callStack:Array = CallStack.exceptionStack(true);
var dateNow:String = Date.now().toString().replace(" ", "_").replace(":", "'");
@@ -91,11 +107,20 @@ class CrashHandler
switch (stackItem)
{
case FilePos(s, file, line, column):
- callstackText += errMsg + file + " (line " + line + ")\n";
+ callStackText += file + " (line " + line + ")\n";
+ if (callStackForEditorText == "")
+ {
+ // Underline only the first line
+ callStackForEditorText += "\033[4m" + file + "#" + line + "\033[24m\n";
+ }
+ else
+ {
+ callStackForEditorText += file + "#" + line + "\n";
+ }
case CFunction:
- callstackText += "Non-Haxe (C) Function";
+ callStackText += "Non-Haxe (C) Function";
case Module(c):
- callstackText += 'Module ${c}';
+ callStackText += 'Module ${c}';
default:
Sys.println(stackItem);
}
@@ -104,13 +129,13 @@ class CrashHandler
randomsMsg = quotes[Std.random(quotes.length)];
var finalTerminalText:String = "";
- finalTerminalText += "Call Stack:\n" + callstackText;
+ finalTerminalText += "Call Stack:\n" + callStackForEditorText;
finalTerminalText += "\nUncaught Error:\n" + e;
var finalGameplayText:String = "";
- finalGameplayText += "Call Stack:\n" + callstackText;
+ finalGameplayText += "Call Stack:\n" + callStackText;
finalGameplayText += "\n---------------------"
- + "\n"
+ + "\nCrash on Flixel function: [" + whereItCrashes(flxFuncNum) + "]\n"
+ randomsMsg
+ "\n---------------------"
+ "\n\nThis build is running in "
@@ -119,18 +144,22 @@ class CrashHandler
+ SlushiMain.slushiEngineVersion
+ " -- SCE v"
+ MainMenuState.SCEVersion
- + " (" + SlushiMain.sceGitCommit + ")"
- + "\nPlease contact with @slushi_ds in Discord or add an issue in the engine repository if you think this is a bug of SLE."
+ + " ("
+ + SlushiMain.sceGitCommit
+ + ")"
+ + "\nPlease contact with @slushi_ds in Discord or add an issue in the repository \nif you think this is a bug of SLE."
+ "\n\n"
+ "Uncaught Error:\n"
+ e
+ "\n\n"
- + "For more info go to: [assets/debugLogs/crashes]";
+ + "For more info go to: [assets/debugLogs/crashes/SLEngineCrash_"
+ + dateNow
+ + ".log]";
if (!FileSystem.exists("./assets/debugLogs/crashes/"))
FileSystem.createDirectory("./assets/debugLogs/crashes/");
- File.saveContent(path, buildCrashReportForFile(e, callstackText, randomsMsg));
+ File.saveContent(path, buildCrashReportForFile(e, callStackText, randomsMsg));
Debug.logError("\nCRASH:\n\x1b[38;5;1m" + finalTerminalText + "\033[0m\n\n");
@@ -140,6 +169,7 @@ class CrashHandler
#if SLUSHI_CPP_CODE
WindowsFuncs.resetAllCPPFunctions();
#end
+ WindowFuncs.resetWindowParameters();
}
static function buildCrashReportForFile(errorMessage:String, callStack:String, randomQuote:String):String
@@ -148,7 +178,7 @@ class CrashHandler
fullContents += 'Slushi Engine Crash Report\n';
fullContents += '=====================\n';
- fullContents += 'Slushi Crash Handler util v${SlushiMain.slCrashHandlerVersion}\n';
+ fullContents += 'Slushi Engine Crash Handler Util v${SlushiMain.sleThingsVersions.slCrashHandlerVersion}\n';
fullContents += '=====================\n';
@@ -157,10 +187,10 @@ class CrashHandler
fullContents += 'Generated by: Slushi Engine v${SlushiMain.slushiEngineVersion} - SC Engine v${MainMenuState.SCEVersion} (${SlushiMain.sceGitCommit})\n';
fullContents += 'System timestamp: ${DateUtil.generateTimestamp(true)}\n';
var driverInfo = FlxG?.stage?.context3D?.driverInfo ?? 'N/A';
- fullContents += 'GPU Driver info: ${driverInfo}\n';
+ fullContents += 'GPU Driver info: \n${driverInfo}\n';
fullContents += 'Platform: ${System.platformLabel}\n';
@:privateAccess
- fullContents += 'Render method: ${utils.logging.CrashHandler.renderMethod()}\n';
+ fullContents += 'Render method: ${utils.logging.CrashHandler.renderMethod()}\n';
fullContents += '\n';
@@ -182,7 +212,7 @@ class CrashHandler
fullContents += 'More info:\n';
- fullContents += 'Please contact with @slushi_ds in Discord or add an issue in the Slushi Engine repository if you think it is a bug in SLE.\n';
+ fullContents += 'Please contact with @slushi_ds in Discord or add an issue in the engine repository if you think it is a bug in SLE.\n';
fullContents += '\n';
@@ -191,6 +221,7 @@ class CrashHandler
fullContents += 'Flixel Current State: ${currentState}\n';
fullContents += 'Flixel Current SubState: ${currentSubState}\n';
+ fullContents += 'Crashed on Flixel function: [${whereItCrashes(flxFuncNum)}]\n';
fullContents += '\n';
@@ -232,14 +263,27 @@ class CrashHandler
fullContents += 'Version: ${SlushiMain.slushiEngineVersion}\n';
fullContents += 'Build number: ${SlushiMain.buildNumber}\n';
- fullContents += 'SCE Github commit: ${SlushiMain.sceGitCommit}\n';
-
- fullContents += '\n';
-
+ fullContents += 'SCE build Github commit: ${SlushiMain.sceGitCommit}\n';
fullContents += 'C++ Code: ' + #if SLUSHI_CPP_CODE 'YES' #else 'NO' #end + '\n';
fullContents += 'Slushi Lua: ' + #if SLUSHI_LUA 'YES' #else 'NO' #end + '\n';
fullContents += 'Custom build: ' + #if CUSTOM_BUILD 'YES' #else 'NO' #end + '\n';
return fullContents;
}
-}
\ No newline at end of file
+
+ private static function whereItCrashes(number:Int):String
+ {
+ switch (number) {
+ case 0:
+ return "Create";
+ case 1:
+ return "Update";
+ case 2:
+ return "Draw";
+ default:
+ return "Unknown";
+ }
+
+ return "Unknown";
+ }
+}
diff --git a/funkinscsource/slushi/slushiUtils/crashHandler/GameplayCrashHandler.hx b/funkinscsource/slushi/slushiUtils/crashHandler/GameplayCrashHandler.hx
index a20cec8..5cf49be 100644
--- a/funkinscsource/slushi/slushiUtils/crashHandler/GameplayCrashHandler.hx
+++ b/funkinscsource/slushi/slushiUtils/crashHandler/GameplayCrashHandler.hx
@@ -2,10 +2,10 @@ package slushi.slushiUtils.crashHandler;
import flixel.system.scaleModes.*;
import flixel.group.FlxGroup;
-
import states.StoryMenuState;
import states.freeplay.FreeplayState;
import states.MainMenuState;
+import slushi.states.freeplay.SlushiFreeplayState;
class GameplayCrashHandler
{
@@ -23,7 +23,15 @@ class GameplayCrashHandler
return;
}
+ // Stop the PlayState, to avoid a loop if the crash occurred in an update function
+ if (Type.getClass(FlxG.state) == PlayState)
+ {
+ PlayState.instance.paused = true;
+ }
+
WindowFuncs.winTitle("Slushi Engine: Crash Handler Mode");
+ WindowFuncs.resetWindowParameters();
+ WindowsFuncs.setWindowBorderColor([0, 46, 114]);
if (Main.fpsVar != null)
Main.fpsVar.visible = false;
FlxG.mouse.useSystemCursor = false;
@@ -43,12 +51,12 @@ class GameplayCrashHandler
var split:Array = contents.split("\n");
- var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
+ var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width + 100, FlxG.height + 100, FlxColor.BLACK);
bg.scrollFactor.set();
assetGrp.add(bg);
bg.alpha = 0.7;
- var watermark = new FlxText(10, 0, 0, "Slushi Engine Crash Handler [v" + SlushiMain.slCrashHandlerVersion + "] by Slushi");
+ var watermark = new FlxText(10, 0, 0, "Slushi Engine Crash Handler [v" + SlushiMain.sleThingsVersions.slCrashHandlerVersion + "] by Slushi");
watermark.setFormat(Paths.font("vcr.ttf"), 20, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
watermark.scrollFactor.set();
watermark.borderSize = 1.25;
@@ -116,21 +124,24 @@ class GameplayCrashHandler
Main.fpsVar.visible = ClientPrefs.data.showFPS;
WindowFuncs.windowResizable(true);
WindowFuncs.winTitle("default");
+
if (Type.getClass(FlxG.state) == PlayState)
{
- if (!PlayState.isStoryMode)
+ if (PlayState.isStoryMode)
{
MainGame.crashHandlerAlredyOpen = false;
- MusicBeatState.switchState(new FreeplayState());
+ MusicBeatState.switchState(new StoryMenuState());
CrashHandler.inCrash = false;
CrashHandler.createdCrashInGame = false;
+ CrashHandler.crashes = 0;
}
else
{
MainGame.crashHandlerAlredyOpen = false;
- MusicBeatState.switchState(new StoryMenuState());
+ MusicBeatState.switchState(new SlushiFreeplayState());
CrashHandler.inCrash = false;
CrashHandler.createdCrashInGame = false;
+ CrashHandler.crashes = 0;
}
}
else
@@ -139,7 +150,23 @@ class GameplayCrashHandler
FlxG.switchState(Type.createInstance(Type.getClass(MainGame.oldState), []));
CrashHandler.inCrash = false;
CrashHandler.createdCrashInGame = false;
+ CrashHandler.crashes = 0;
}
+
+ for (obj in assetGrp)
+ {
+ if (obj != null)
+ {
+ obj.destroy();
+ }
+ }
+
+ if (camCrashHandler != null)
+ {
+ camCrashHandler.destroy();
+ }
+
+ Paths.clearUnusedMemory();
});
});
}
diff --git a/funkinscsource/slushi/slushiUtils/shaders/SLEFlxShaderUtil.hx b/funkinscsource/slushi/slushiUtils/shaders/SLEFlxShaderUtil.hx
deleted file mode 100644
index b7aedda..0000000
--- a/funkinscsource/slushi/slushiUtils/shaders/SLEFlxShaderUtil.hx
+++ /dev/null
@@ -1,88 +0,0 @@
-package slushi.slushiUtils.shaders;
-
-import openfl.display3D._internal.GLShader;
-import openfl.display3D._internal.GLProgram;
-
-import flixel.system.FlxAssets.FlxShader;
-
-/**
- * This code helps the program itself to both alert the user that a
- * shader did not compile correctly (due to its GPU/GPU driver) and to
- * prevent the program from crashing.
- * The object or camera where it was applied could be have unexpected results
- * that would have been expected if the shader compiled correctly.
- *
- * @:author Slushi
- */
-
-class SLEFlxShaderUtil extends FlxShader
-{
- public var shaderName:String = "UNKNOWN";
-
- @:noCompletion override private function __createGLShader(source:String, type:Int):GLShader
- {
- #if (openfl >= "9.2.2")
- @:privateAccess
- var gl = __context.gl;
-
- var shader = gl.createShader(type);
- gl.shaderSource(shader, source);
- gl.compileShader(shader);
- var shaderInfoLog = gl.getShaderInfoLog(shader);
- var hasInfoLog = shaderInfoLog != null && StringTools.trim(shaderInfoLog) != "";
- var compileStatus = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
-
- if (hasInfoLog || compileStatus == 0)
- {
- var message = (type == gl.VERTEX_SHADER) ? "Can\'t compile [VERTEX] shader:\n" : "Can\'t compile [FRAGMENT] shader:\n";
- message += shaderInfoLog;
- if (compileStatus == 0) {
- #if windows
- CppAPI.showMessageBox(message, "Slushi Engine: Error compiling shader!", MSG_ERROR);
- #else
- WindowFuncs.windowAlert(message, "Slushi Engine: Error compiling shader!");
- #end
- Debug.logError("Error compiling shader: \n" + message + "\n");
- }
- else if (hasInfoLog){
- Debug.logInfo(message);
- }
- }
- return shader;
- #end
- }
-
- override private function __createGLProgram(vertexSource:String, fragmentSource:String):GLProgram
- {
- @:privateAccess
- var gl = __context.gl;
-
- var vertexShader = __createGLShader(vertexSource, gl.VERTEX_SHADER);
- var fragmentShader = __createGLShader(fragmentSource, gl.FRAGMENT_SHADER);
-
- var program = gl.createProgram();
-
- // Fix support for drivers that don't draw if attribute 0 is disabled
- for (param in __paramFloat)
- {
- if (param.name.indexOf("Position") > -1 && StringTools.startsWith(param.name, "openfl_"))
- {
- gl.bindAttribLocation(program, 0, param.name);
- break;
- }
- }
-
- gl.attachShader(program, vertexShader);
- gl.attachShader(program, fragmentShader);
- gl.linkProgram(program);
-
- if (gl.getProgramParameter(program, gl.LINK_STATUS) == 0)
- {
- var message = "Unable to initialize the shader program";
- message += "\n" + gl.getProgramInfoLog(program);
- Debug.logError("\nError initializing shader program:\n" + message + "\n");
- }
-
- return program;
- }
-}
\ No newline at end of file
diff --git a/funkinscsource/slushi/states/SlushiMainMenuState.hx b/funkinscsource/slushi/states/SlushiMainMenuState.hx
index 1bca84d..ce0df53 100644
--- a/funkinscsource/slushi/states/SlushiMainMenuState.hx
+++ b/funkinscsource/slushi/states/SlushiMainMenuState.hx
@@ -4,7 +4,6 @@ import flixel.effects.FlxFlicker;
import flixel.graphics.frames.FlxFilterFrames;
import flash.filters.GlowFilter;
import slushi.substates.ConsoleSubState;
-
import states.CreditsState;
import states.MainMenuState;
import states.editors.MasterEditorMenu;
@@ -12,16 +11,15 @@ import states.freeplay.FreeplayState;
import states.StoryMenuState;
import options.OptionsState;
import states.ModsMenuState;
+import slushi.states.freeplay.SlushiFreeplayState;
/**
* The main menu state for Slushi Engine
*
* Author: Slushi
*/
-
class SlushiMainMenuState extends MusicBeatState
{
- public static final psychEngineVersion:String = MainMenuState.psychEngineVersion;
public static var SCEVersion:String = MainMenuState.SCEVersion;
public static var slushiEngineVersion:String = SlushiMain.slushiEngineVersion;
@@ -39,12 +37,17 @@ class SlushiMainMenuState extends MusicBeatState
var sleLogoCamShader:ThreeDEffect;
+ var curOption:Int = 0;
+
var finishedIntro:Bool = false;
var clickedOption:Bool = false;
- var danceIntro:Bool = false;
var shaderSpeed:Int = 4;
var sineElap:Float = 0;
var numTween:NumTween;
+ var tweenOptionAlphaData = {
+ tween: null,
+ currentOption: 0
+ };
var camOther:FlxCamera;
var camSLELogo:FlxCamera;
@@ -69,7 +72,7 @@ class SlushiMainMenuState extends MusicBeatState
super.create();
persistentUpdate = true;
-
+
camOther = new FlxCamera();
camOptions = new FlxCamera();
camSLELogo = new FlxCamera();
@@ -146,6 +149,14 @@ class SlushiMainMenuState extends MusicBeatState
glowFilter2 = new GlowFilter(SlushiMain.slushiColor, 1, 40, 40, 1.5, 1);
glowFilter3 = new GlowFilter(SlushiMain.slushiColor, 1, 40, 40, 1.5, 1);
glowFilter4 = new GlowFilter(SlushiMain.slushiColor, 1, 40, 40, 1.5, 1);
+
+ // for (glowFilter in [glowFilter0, glowFilter1, glowFilter2, glowFilter3, glowFilter4])
+ // {
+ // glowFilter = new GlowFilter(SlushiMain.slushiColor, 1, 40, 40, 1.5, 1);
+ // glowFilter.blurX = 0;
+ // glowFilter.blurY = 0;
+ // }
+
sprFilter0 = createFilterFrames(freeplaySprite, glowFilter0);
sprFilter1 = createFilterFrames(storyModeSprite, glowFilter1);
sprFilter2 = createFilterFrames(modsSprite, glowFilter2);
@@ -237,15 +248,16 @@ class SlushiMainMenuState extends MusicBeatState
ease: FlxEase.elasticInOut,
onComplete: function(twn:FlxTween)
{
- MusicBeatState.switchState(new FreeplayState());
+ MusicBeatState.switchState(new SlushiFreeplayState());
}
});
}
FlxTween.tween(camOther, {alpha: 1}, time, {ease: FlxEase.linear});
FlxG.sound.play(Paths.sound('confirmMenu'));
FlxFlicker.flicker(freeplaySprite, 1.2, 0.06, false, false);
- FlxTween.tween(freeplaySprite, {x: (FlxG.width - freeplaySprite.width) / 2, y: (FlxG.height - freeplaySprite.height) / 2}, time,
+ FlxTween.tween(freeplaySprite, {x: (FlxG.width - freeplaySprite.width) / 2, y: (FlxG.height - freeplaySprite.height) / 2, alpha: 0}, time,
{ease: FlxEase.elasticInOut});
+ FlxTween.tween(freeplaySprite.scale, {x: 1.3, y: 1.3}, time, {ease: FlxEase.linear});
clickedOption = true;
numTween = FlxTween.num(0, shaderValue, 1.2);
numTween.onUpdate = function(twn:FlxTween)
@@ -267,8 +279,9 @@ class SlushiMainMenuState extends MusicBeatState
}
FlxTween.tween(camOther, {alpha: 1}, time, {ease: FlxEase.linear});
FlxG.sound.play(Paths.sound('confirmMenu'));
- FlxTween.tween(storyModeSprite, {x: (FlxG.width - storyModeSprite.width) / 2, y: (FlxG.height - storyModeSprite.height) / 2}, time,
+ FlxTween.tween(storyModeSprite, {x: (FlxG.width - storyModeSprite.width) / 2, y: (FlxG.height - storyModeSprite.height) / 2, alpha: 0}, time,
{ease: FlxEase.elasticInOut});
+ FlxTween.tween(storyModeSprite.scale, {x: 1.3, y: 1.3}, time, {ease: FlxEase.linear});
FlxFlicker.flicker(storyModeSprite, 1.2, 0.06, false, false);
clickedOption = true;
numTween = FlxTween.num(0, shaderValue, 1.2);
@@ -291,7 +304,8 @@ class SlushiMainMenuState extends MusicBeatState
}
FlxTween.tween(camOther, {alpha: 1}, time, {ease: FlxEase.linear});
FlxG.sound.play(Paths.sound('confirmMenu'));
- FlxTween.tween(modsSprite, {x: (FlxG.width - modsSprite.width) / 2, y: (FlxG.height - modsSprite.height) / 2}, time, {ease: FlxEase.linear});
+ FlxTween.tween(modsSprite, {x: (FlxG.width - modsSprite.width) / 2, y: (FlxG.height - modsSprite.height) / 2, alpha: 0}, time, {ease: FlxEase.elasticInOut});
+ FlxTween.tween(modsSprite.scale, {x: 1.3, y: 1.3}, time, {ease: FlxEase.linear});
FlxFlicker.flicker(modsSprite, 1.2, 0.06, false, false);
clickedOption = true;
numTween = FlxTween.num(0, shaderValue, 1.2);
@@ -314,8 +328,9 @@ class SlushiMainMenuState extends MusicBeatState
}
FlxTween.tween(camOther, {alpha: 1}, time, {ease: FlxEase.linear});
FlxG.sound.play(Paths.sound('confirmMenu'));
- FlxTween.tween(creditsSprite, {x: (FlxG.width - creditsSprite.width) / 2, y: (FlxG.height - creditsSprite.height) / 2}, time,
+ FlxTween.tween(creditsSprite, {x: (FlxG.width - creditsSprite.width) / 2, y: (FlxG.height - creditsSprite.height) / 2, alpha: 0}, time,
{ease: FlxEase.elasticInOut});
+ FlxTween.tween(creditsSprite.scale, {x: 1.3, y: 1.3}, time, {ease: FlxEase.linear});
FlxFlicker.flicker(creditsSprite, 1.2, 0.06, false, false);
clickedOption = true;
numTween = FlxTween.num(0, shaderValue, 1.2);
@@ -345,8 +360,9 @@ class SlushiMainMenuState extends MusicBeatState
}
FlxTween.tween(camOther, {alpha: 1}, time, {ease: FlxEase.linear});
FlxG.sound.play(Paths.sound('confirmMenu'));
- FlxTween.tween(optionsSprite, {x: (FlxG.width - optionsSprite.width) / 2, y: (FlxG.height - optionsSprite.height) / 2}, time,
+ FlxTween.tween(optionsSprite, {x: (FlxG.width - optionsSprite.width) / 2, y: (FlxG.height - optionsSprite.height) / 2, alpha: 0}, time,
{ease: FlxEase.elasticInOut});
+ FlxTween.tween(optionsSprite.scale, {x: 1.3, y: 1.3}, time, {ease: FlxEase.linear});
FlxFlicker.flicker(optionsSprite, 1.2, 0.06, false, false);
clickedOption = true;
numTween = FlxTween.num(0, shaderValue, 1.2);
diff --git a/funkinscsource/slushi/states/SlushiTitleState.hx b/funkinscsource/slushi/states/SlushiTitleState.hx
index 0210572..620e388 100644
--- a/funkinscsource/slushi/states/SlushiTitleState.hx
+++ b/funkinscsource/slushi/states/SlushiTitleState.hx
@@ -38,7 +38,8 @@ class SlushiTitleState extends MusicBeatState
public static var gitVersion = {
needUpdate: false,
- newVersion: ""
+ newVersion: "",
+ alreadyChecked: false
};
override public function create()
@@ -69,7 +70,12 @@ class SlushiTitleState extends MusicBeatState
Highscore.load();
Assets.cache.enabled = true;
- SlushiMain.getBuildVer();
+
+ if (!gitVersion.alreadyChecked)
+ {
+ SlushiMain.getBuildVer();
+ gitVersion.alreadyChecked = true;
+ }
if(gitVersion.needUpdate) {
var finalText:FlxText = new FlxText(0, 0, 0, "Hey! You are using an old version of Slushi Engine\n\nVersion: " + gitVersion.newVersion + " > " + SlushiMain.slushiEngineVersion + "\n\nPlease download the latest version\nThanks for use SLE :3", 12);
@@ -78,7 +84,6 @@ class SlushiTitleState extends MusicBeatState
finalText.screenCenter();
finalText.y -= 20;
add(finalText);
- // finalText.alpha = 0;
FlxTween.tween(finalText, {alpha: 1}, 0.3, {ease: FlxEase.quadOut});
FlxTween.tween(finalText, {y: finalText.y + 20}, 0.3, {ease: FlxEase.quadOut, onComplete: function(twn:FlxTween) {
new FlxTimer().start(3, function(twn:FlxTimer)
@@ -290,7 +295,7 @@ class SlushiTitleState extends MusicBeatState
{
super.stepHit();
- if (curStep == 15 && curStep != 266)
+ if (curStep >= 15 && curStep <= 266)
{
if (curStep % 16 == 0)
{
diff --git a/funkinscsource/slushi/states/freeplay/SlushiFreeplayHealthIcon.hx b/funkinscsource/slushi/states/freeplay/SlushiFreeplayHealthIcon.hx
new file mode 100644
index 0000000..667782e
--- /dev/null
+++ b/funkinscsource/slushi/states/freeplay/SlushiFreeplayHealthIcon.hx
@@ -0,0 +1,20 @@
+package slushi.states.freeplay;
+
+import objects.HealthIcon;
+
+class SlushiFreeplayHealthIcon extends HealthIcon
+{
+ public var songTxtTracker:FlxSprite;
+
+ override public function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (songTxtTracker != null) {
+ setPosition(
+ songTxtTracker.x + (songTxtTracker.width / 2) - (this.width / 2) + offsetX,
+ songTxtTracker.y - 100 + offsetY
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/funkinscsource/slushi/states/freeplay/SlushiFreeplayState.hx b/funkinscsource/slushi/states/freeplay/SlushiFreeplayState.hx
new file mode 100644
index 0000000..1bed50f
--- /dev/null
+++ b/funkinscsource/slushi/states/freeplay/SlushiFreeplayState.hx
@@ -0,0 +1,1374 @@
+package slushi.states.freeplay;
+
+import flixel.effects.FlxFlicker;
+import flixel.math.FlxMath;
+import flixel.util.FlxStringUtil;
+import flixel.ui.FlxBar;
+import haxe.Json;
+import backend.WeekData;
+import backend.Highscore;
+import openfl.utils.Assets as OpenFlAssets;
+import slushi.states.freeplay.SlushiMusicPlayer;
+import objects.CoolText;
+import substates.GameplayChangersSubstate;
+import substates.ResetScoreSubState;
+import vslice.transition.StickerSubState;
+import utils.SoundUtil;
+import states.freeplay.FreeplaySongMetaData;
+import slushi.states.freeplay.SlushiFreeplayHealthIcon;
+import states.MainMenuState;
+import states.StoryMenuState;
+import states.editors.WeekEditorState;
+import states.ErrorState;
+import objects.Character.CharacterFile;
+import objects.Character;
+import flixel.addons.effects.FlxTrail;
+import backend.PsychCamera;
+import objects.note.*;
+import slushi.others.SlushiSongs;
+import shaders.FunkinSourcedShaders.WaveBurstEffect;
+
+/**
+ * The freeplay state for Slushi Engine
+ *
+ * Author: Slushi
+ */
+class SlushiFreeplayState extends MusicBeatState
+{
+ public static var instance:SlushiFreeplayState = null;
+ private static var lastDifficultyName:String = Difficulty.getDefault();
+ private static var curSelected:Int = 0;
+
+ private var grpSongs:FlxTypedGroup;
+ private var curPlaying:Bool = false;
+ private var iconArray:Array = [];
+
+ public var rate:Float = 1.0;
+ public var lastRate:Float = 1.0;
+
+ public var curInstPlaying:Int = -1;
+
+ public var scoreBG:FlxSprite;
+ public var scoreText:CoolText;
+ public var opponentText:CoolText;
+ public var diffText:CoolText;
+ public var comboText:CoolText;
+ public var downText:CoolText;
+
+ public var leText:String = "";
+
+ public var scorecolorDifficulty:Map = [
+ 'EASY' => FlxColor.GREEN,
+ 'NORMAL' => FlxColor.YELLOW,
+ 'HARD' => FlxColor.RED,
+ 'ERECT' => FlxColor.fromString('#FD579D'),
+ 'NIGHTMARE' => FlxColor.fromString('#4E28FB')
+ ];
+
+ public var curStringDifficulty:String = 'NORMAL';
+
+ var songs:Array = [];
+
+ var selector:FlxText;
+ var lerpSelected:Float = 0;
+ var curDifficulty:Int = -1;
+
+ var lerpScore:Int;
+ var lerpAccuracy:Float = 0;
+ var intendedScore:Int = 0;
+ var intendedAccuracy:Float = 0;
+ var rating:String;
+ var combo:String = 'N/A';
+
+ var missingTextBG:FlxSprite;
+ var missingText:FlxText;
+
+ var opponentMode:Bool = false;
+
+ var bg:FlxSprite;
+ var intendedColor:Int;
+ var player:SlushiMusicPlayer;
+
+ #if BASE_GAME_FILES
+ var stickerSubState:StickerSubState;
+
+ var camNotes:FlxCamera;
+ var camBG:FlxCamera;
+
+ public var camSongs:FlxCamera;
+
+ public function new(?stickers:StickerSubState)
+ {
+ if (stickers != null)
+ stickerSubState = stickers;
+ super();
+ }
+ #end
+
+ override function create()
+ {
+ instance = this;
+
+ persistentUpdate = true;
+ PlayState.isStoryMode = false;
+ WeekData.reloadWeekFiles(false);
+
+ if (WeekData.weeksList.length < 1)
+ {
+ FlxTransitionableState.skipNextTransIn = true;
+ persistentUpdate = false;
+ MusicBeatState.switchState(new ErrorState("NO WEEKS ADDED FOR FREEPLAY\n\nPress ACCEPT to go to the Week Editor Menu.\nPress BACK to return to Main Menu.",
+ function() MusicBeatState.switchState(new WeekEditorState()), function()
+ {
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+ MusicBeatState.switchState(new MainMenuState());
+ }));
+ return;
+ }
+
+ camNotes = initPsychCamera();
+ camBG = new FlxCamera();
+ camSongs = new FlxCamera();
+ camNotes.bgColor.alpha = 0;
+ camBG.bgColor.alpha = 0;
+ camSongs.bgColor.alpha = 0;
+ FlxG.cameras.add(camNotes, false);
+ FlxG.cameras.add(camBG, false);
+ FlxG.cameras.add(camSongs, false);
+
+ #if BASE_GAME_FILES
+ if (stickerSubState != null)
+ {
+ openSubState(stickerSubState);
+ stickerSubState.degenStickers();
+ }
+ #end
+
+ #if DISCORD_ALLOWED
+ // Updating Discord Rich Presence
+ DiscordClient.changePresence('Searching to play song - SL Freeplay Menu', null);
+ #end
+
+ for (i in 0...WeekData.weeksList.length)
+ {
+ if (weekIsLocked(WeekData.weeksList[i]))
+ continue;
+
+ var leWeek:WeekData = WeekData.weeksLoaded.get(WeekData.weeksList[i]);
+ var leSongs:Array = [];
+ var leChars:Array = [];
+
+ for (j in 0...leWeek.songs.length)
+ {
+ leSongs.push(leWeek.songs[j][0]);
+ leChars.push(leWeek.songs[j][1]);
+ }
+
+ WeekData.setDirectoryFromWeek(leWeek);
+ for (song in leWeek.songs)
+ {
+ addSong(song[0], i, song[1],
+ (song[2] == null || song[2].length < 3) ? FlxColor.fromRGB(146, 113, 253) : FlxColor.fromRGB(song[2][0], song[2][1], song[2][2]),
+ song[3] != null ? song[3] : false);
+ }
+ }
+ Mods.loadTopMod();
+
+ bg = new FlxSprite().loadGraphic(SlushiMain.getSLEPath('SlushiFreeplayStateAssets/BG.png'));
+ bg.antialiasing = ClientPrefs.data.antialiasing;
+ add(bg);
+ bg.screenCenter();
+ bg.camera = camBG;
+
+ grpSongs = new FlxTypedGroup();
+
+ for (i in 0...songs.length)
+ {
+ var songText:Alphabet = new Alphabet(90, 320, songs[i].songName, true);
+ songText.targetY = i;
+
+ songText.screenCenter(X);
+ songText.scaleX = Math.min(1, 980 / songText.width);
+ songText.snapToPosition();
+
+ Mods.currentModDirectory = songs[i].folder;
+ var icon:SlushiFreeplayHealthIcon = new SlushiFreeplayHealthIcon(songs[i].songCharacter);
+ icon.songTxtTracker = songText;
+
+ // too laggy with a lot of songs, so i had to recode the logic for it
+ songText.visible = songText.active = songText.isMenuItem = false;
+ icon.visible = icon.active = false;
+
+ if (curPlaying && i == instPlaying)
+ {
+ if (icon.hasWinning)
+ icon.animation.curAnim.curFrame = 2;
+ }
+
+ // using a FlxGroup is too much fuss!
+ iconArray.push(icon);
+ add(icon);
+ icon.camera = camSongs;
+ grpSongs.add(songText);
+ }
+
+ add(grpSongs);
+ grpSongs.camera = camSongs;
+
+ WeekData.setDirectoryFromWeek();
+
+ scoreText = new CoolText(FlxG.width * 0.6525, 10, 31, 31, Paths.bitmapFont('fonts/vcr'));
+ scoreText.autoSize = true;
+ scoreText.fieldWidth = FlxG.width;
+ scoreText.antialiasing = FlxG.save.data.antialiasing;
+
+ scoreBG = new FlxSprite((FlxG.width * 0.65) - 6, 0).makeGraphic(Std.int(FlxG.width * 0.4), 270, 0xFF000000);
+ scoreBG.color = FlxColor.fromString('0xFF000000');
+ scoreBG.alpha = 0.6;
+ add(scoreBG);
+
+ comboText = new CoolText(scoreText.x, scoreText.y + 36, 23, 23, Paths.bitmapFont('fonts/vcr'));
+ comboText.autoSize = true;
+
+ comboText.antialiasing = ClientPrefs.data.antialiasing;
+ add(comboText);
+
+ opponentText = new CoolText(scoreText.x, scoreText.y + 66, 23, 23, Paths.bitmapFont('fonts/vcr'));
+ opponentText.autoSize = true;
+
+ opponentText.antialiasing = ClientPrefs.data.antialiasing;
+ add(opponentText);
+
+ diffText = new CoolText(scoreText.x - 4, scoreText.y + 96, 23, 23, Paths.bitmapFont('fonts/vcr'));
+ diffText.antialiasing = ClientPrefs.data.antialiasing;
+ add(diffText);
+
+ add(scoreText);
+
+ missingTextBG = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
+ missingTextBG.alpha = 0.6;
+ missingTextBG.visible = false;
+ add(missingTextBG);
+
+ missingText = new FlxText(50, 0, FlxG.width - 100, '', 24);
+ missingText.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ missingText.scrollFactor.set();
+ missingText.visible = false;
+ add(missingText);
+
+ var textBG:FlxSprite = new FlxSprite(0, FlxG.height - 26).makeGraphic(FlxG.width, 27, 0xFF000000);
+ textBG.alpha = 0.6;
+ add(textBG);
+
+ leText = Language.getPhrase("freeplay_tip",
+ "Press SPACE to listen to the Song / Press CTRL to open the Gameplay Changers Menu / Press RESET to Reset your Score and Accuracy.");
+ downText = new CoolText(textBG.x - 600, textBG.y + 4, 14.5, 16, Paths.bitmapFont('fonts/vcr'));
+ // downText.autoSize = true;
+ downText.antialiasing = ClientPrefs.data.antialiasing;
+ downText.scrollFactor.set();
+ downText.updateHitbox();
+ downText.text = leText;
+ add(downText);
+
+ for (obj in [
+ scoreText,
+ comboText,
+ opponentText,
+ diffText,
+ downText,
+ missingText,
+ textBG,
+ missingTextBG,
+ scoreBG,
+ ])
+ obj.camera = camSongs;
+
+ if (curSelected >= songs.length)
+ curSelected = 0;
+ bg.color = songs[curSelected].color;
+ intendedColor = bg.color;
+ lerpSelected = curSelected;
+
+ // Set the window border color from the current song's color
+ // Idea from VS Camellia ALT (https://gamebanana.com/mods/413258) (They use my code to set the window border color XD)
+ WindowsFuncs.setWindowBorderColorFromInt(intendedColor);
+
+ curDifficulty = Math.round(Math.max(0, Difficulty.list.indexOf(lastDifficultyName)));
+
+ player = new SlushiMusicPlayer(this);
+ add(player);
+
+ if (MainMenuState.freakyPlaying)
+ {
+ if (!FlxG.sound.music.playing)
+ FlxG.sound.playMusic(SlushiMain.getSLEPath("Musics/SLE_HackNet_Resonance.ogg"));
+ }
+
+ if (inst != null)
+ inst = null;
+
+ changeSelection();
+ updateTexts();
+ super.create();
+
+ if (FlxG.sound.music != null && !FlxG.sound.music.playing && !MainMenuState.freakyPlaying && !resetSong)
+ {
+ playSong();
+ }
+ }
+
+ override function closeSubState()
+ {
+ changeSelection(0, false);
+ opponentMode = ClientPrefs.getGameplaySetting('opponent');
+ opponentText.text = "OPPONENT MODE: " + (opponentMode ? "ON" : "OFF");
+ opponentText.updateHitbox();
+ changeDiff(0);
+ persistentUpdate = true;
+ super.closeSubState();
+ }
+
+ public function addSong(songName:String, weekNum:Int, songCharacter:String, color:Int, blockOpponentMode:Bool)
+ {
+ songs.push(new FreeplaySongMetaData(songName, weekNum, songCharacter, color, blockOpponentMode));
+ }
+
+ function weekIsLocked(name:String):Bool
+ {
+ var leWeek:WeekData = WeekData.weeksLoaded.get(name);
+ return (!leWeek.startUnlocked
+ && leWeek.weekBefore.length > 0
+ && (!StoryMenuState.weekCompleted.exists(leWeek.weekBefore) || !StoryMenuState.weekCompleted.get(leWeek.weekBefore)));
+ }
+
+ public var curInstPlayingtxt:String = "N/A";
+
+ public var inst:FlxSound = null;
+ public var vocals:FlxSound = null;
+ public var opponentVocals:FlxSound = null;
+
+ public var instPlayingtxt:String = "N/A"; // its not really a text but who cares?
+ public var canSelectSong:Bool = true;
+
+ var completed:Bool = false;
+ var holdTime:Float = 0;
+ var instPlaying:Int = -1;
+ var startedBopping:Bool = false;
+
+ var stopMusicPlay:Bool = false;
+
+ override function update(elapsed:Float)
+ {
+ if (WeekData.weeksList.length < 1)
+ {
+ super.update(elapsed);
+ return;
+ }
+
+ lerpScore = Math.floor(FlxMath.lerp(intendedScore, lerpScore, Math.exp(-elapsed * 24)));
+ lerpAccuracy = FlxMath.lerp(intendedAccuracy, lerpAccuracy, Math.exp(-elapsed * 12));
+
+ if (player != null && player.playingMusic)
+ {
+ var bpmRatio = Conductor.bpm / 100;
+ if (ClientPrefs.data.camZooms)
+ {
+ FlxG.camera.zoom = FlxMath.lerp(1, FlxG.camera.zoom, CoolUtil.boundTo(1 - (elapsed * 3.125 * bpmRatio * player.playbackRate), 0, 1));
+ }
+
+ for (i in 0...iconArray.length)
+ {
+ if (iconArray[i] != null)
+ {
+ var mult:Float = FlxMath.lerp(1, iconArray[i].scale.x, CoolUtil.boundTo(1 - (elapsed * 35 * player.playbackRate), 0, 1));
+ iconArray[i].scale.set(mult, mult);
+ iconArray[i].updateHitbox();
+ }
+ }
+
+ if (PlayState.SONG != null)
+ {
+ if (Conductor.bpm != PlayState.SONG.bpm)
+ {
+ Conductor.bpm = PlayState.SONG.bpm;
+ }
+ }
+
+ #if DISCORD_ALLOWED
+ DiscordClient.changePresence('Listening to ' + Paths.formatToSongPath(songs[curSelected].songName), null);
+ #end
+ }
+
+ if (!player.playingMusic)
+ {
+ if (FlxG.camera.zoom != 1)
+ FlxG.camera.zoom = 1;
+ #if DISCORD_ALLOWED
+ DiscordClient.changePresence('Searching to play song - SL Freeplay Menu', null);
+ #end
+ }
+
+ for (icon in iconArray)
+ {
+ if (curSelected != iconArray.indexOf(icon))
+ {
+ if (icon.animation.curAnim != null && icon.getLastAnimationPlayed() != 'normal')
+ icon.playAnim('normal', true);
+ continue;
+ }
+ icon.playAnim('losing', false);
+
+ if (!player.playingMusic)
+ {
+ icon.scale.set(1, 1);
+ icon.updateHitbox();
+ }
+ }
+
+ var mult:Float = FlxMath.lerp(1, bg.scale.x, CoolUtil.clamp(1 - (elapsed * 9), 0, 1));
+ bg.scale.set(mult, mult);
+ bg.updateHitbox();
+ bg.offset.set();
+
+ if (Math.abs(lerpScore - intendedScore) <= 10)
+ lerpScore = intendedScore;
+ if (Math.abs(lerpAccuracy - intendedAccuracy) <= 0.01)
+ lerpAccuracy = intendedAccuracy;
+
+ var ratingSplit:Array = Std.string(CoolUtil.floorDecimal(lerpAccuracy * 100, 2)).split('.');
+ if (ratingSplit.length < 2) // No decimals, add an empty space
+ ratingSplit.push('');
+
+ while (ratingSplit[1].length < 2) // Less than 2 decimals in it, add decimals then
+ ratingSplit[1] += '0';
+
+ scoreText.text = Language.getPhrase('personal_best', 'PERSONAL BEST: {1}', [lerpScore]);
+ scoreText.updateHitbox();
+
+ if (combo == "")
+ {
+ comboText.text = Language.getPhrase('fp_unknown_rank', "RANK: N/A");
+ comboText.alpha = 0.5;
+ }
+ else
+ {
+ comboText.text = Language.getPhrase('fp_ranking', "RANK: {1} | {2} ({3}" + "%)\n", [rating, combo, ratingSplit.join('.')]);
+ comboText.alpha = 1;
+ }
+
+ comboText.updateHitbox();
+
+ opponentMode = (ClientPrefs.getGameplaySetting('opponent') && !songs[curSelected].blockOpponentMode);
+ opponentText.text = Language.getPhrase('fp_opponent_mode', "OPPONENT MODE: {1}", [opponentMode ? "ON" : "OFF"]);
+ opponentText.updateHitbox();
+
+ var shiftMult:Int = 1;
+ if (FlxG.keys.pressed.SHIFT)
+ shiftMult = 3;
+
+ if (player != null && !player.playingMusic)
+ {
+ if (songs.length > 1)
+ {
+ if (FlxG.keys.justPressed.HOME)
+ {
+ curSelected = 0;
+ changeSelection();
+ holdTime = 0;
+ }
+ else if (FlxG.keys.justPressed.END)
+ {
+ curSelected = songs.length - 1;
+ changeSelection();
+ holdTime = 0;
+ }
+ if (controls.UI_UP_P)
+ {
+ changeSelection(-shiftMult);
+ holdTime = 0;
+ }
+ if (controls.UI_DOWN_P)
+ {
+ changeSelection(shiftMult);
+ holdTime = 0;
+ }
+
+ if (controls.UI_DOWN || controls.UI_UP)
+ {
+ var checkLastHold:Int = Math.floor((holdTime - 0.5) * 10);
+ holdTime += elapsed;
+ var checkNewHold:Int = Math.floor((holdTime - 0.5) * 10);
+
+ if (holdTime > 0.5 && checkNewHold - checkLastHold > 0)
+ changeSelection((checkNewHold - checkLastHold) * (controls.UI_UP ? -shiftMult : shiftMult));
+ }
+
+ if (FlxG.mouse.wheel != 0)
+ {
+ FlxG.sound.play(Paths.sound('scrollMenu'), 0.2);
+ changeSelection(-shiftMult * FlxG.mouse.wheel, false);
+ }
+
+ if (FlxG.mouse.justPressedRight)
+ {
+ changeDiff(1);
+ _updateSongLastDifficulty();
+ }
+ if (FlxG.mouse.justPressedRight)
+ {
+ changeDiff(-1);
+ _updateSongLastDifficulty();
+ }
+ }
+
+ if (controls.UI_LEFT_P)
+ {
+ changeDiff(-1);
+ _updateSongLastDifficulty();
+ }
+ else if (controls.UI_RIGHT_P)
+ {
+ changeDiff(1);
+ _updateSongLastDifficulty();
+ }
+ else if (controls.UI_UP_P || controls.UI_DOWN_P)
+ changeDiff();
+ }
+
+ if (controls.BACK || completed && exit)
+ {
+ if (player != null && !player.playingMusic)
+ {
+ MusicBeatState.switchState(new slushi.states.SlushiMainMenuState());
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+ if (!MainMenuState.freakyPlaying)
+ {
+ MainMenuState.freakyPlaying = true;
+ Conductor.bpm = 102.0;
+ FlxG.sound.playMusic(SlushiMain.getSLEPath("Musics/SLE_HackNet_Resonance.ogg"));
+ }
+ }
+ else
+ {
+ alreadyPlayingSong = false;
+ instPlaying = -1;
+
+ Conductor.bpm = 102.0;
+ Conductor.songPosition = 0;
+
+ exit = true;
+ completed = false;
+
+ player.playingMusic = false;
+ player.switchPlayMusic();
+
+ if (inst != null)
+ {
+ remove(inst);
+ inst.stop();
+ inst.volume = 0;
+ inst.time = 0;
+ }
+ inst = null;
+
+ if (vocals != null)
+ {
+ vocals.stop();
+ vocals.volume = 0;
+ vocals.time = 0;
+ vocals = null;
+ }
+
+ if (opponentVocals != null)
+ {
+ opponentVocals.stop();
+ opponentVocals.volume = 0;
+ opponentVocals.time = 0;
+ opponentVocals = null;
+ }
+ }
+ }
+
+ if (FlxG.keys.justPressed.CONTROL && !player.playingMusic)
+ {
+ persistentUpdate = false;
+ openSubState(new GameplayChangersSubstate());
+ }
+ else if (FlxG.keys.justPressed.SPACE)
+ {
+ playSong();
+ }
+ else if (controls.RESET && !player.playingMusic)
+ {
+ persistentUpdate = false;
+ openSubState(new ResetScoreSubState(songs[curSelected].songName, curDifficulty, songs[curSelected].songCharacter, -1, opponentMode));
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+ }
+ else
+ {
+ try
+ {
+ for (item in grpSongs.members)
+ if ((controls.ACCEPT
+ || ((FlxG.mouse.overlaps(item) || (FlxG.mouse.overlaps(iconArray[curSelected]))) && FlxG.mouse.pressed))
+ && !FlxG.keys.justPressed.SPACE
+ && canSelectSong)
+ {
+ canSelectSong = false;
+ var llll = FlxG.sound.play(Paths.sound('confirmMenu')).length;
+ updateTexts(elapsed, true);
+ grpSongs.forEach(function(e:Alphabet)
+ {
+ if (e.text == songs[curSelected].songName)
+ {
+ try
+ {
+ tryLeaving(e, llll);
+ }
+ catch (e:haxe.Exception)
+ {
+ Debug.logError('ERROR! ${e.message}');
+
+ var errorStr:String = e.message;
+ if (errorStr.contains('There is no TEXT asset with an ID of'))
+ errorStr = 'Missing file: '
+ + errorStr.substring(errorStr.indexOf(Paths.formatToSongPath(songs[curSelected].songName)),
+ errorStr.length - 1); // Missing chart
+ missingText.text = 'ERROR WHILE LOADING CHART:\n$errorStr';
+ missingText.screenCenter(Y);
+ missingText.visible = true;
+ missingTextBG.visible = true;
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+ }
+ }
+ });
+ break;
+ }
+
+ #if (MODS_ALLOWED && DISCORD_ALLOWED)
+ DiscordClient.loadModRPC();
+ #end
+ }
+ catch (e:haxe.Exception)
+ {
+ Debug.logError('ERROR! ${e.message}');
+
+ var errorStr:String = e.message;
+ if (errorStr.contains('There is no TEXT asset with an ID of'))
+ errorStr = 'Missing file: '
+ + errorStr.substring(errorStr.indexOf(Paths.formatToSongPath(songs[curSelected].songName)), errorStr.length - 1); // Missing chart
+ else
+ errorStr += '\n\n' + e.stack;
+
+ missingText.screenCenter(Y);
+ missingText.visible = true;
+ missingTextBG.visible = true;
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+
+ updateTexts(elapsed);
+ super.update(elapsed);
+ return;
+ }
+ }
+
+ if (canSelectSong)
+ updateTexts(elapsed);
+
+ super.update(elapsed);
+ }
+
+ function tryLeaving(e:Alphabet, llll:Float = 0)
+ {
+ if (player != null)
+ player.fadingOut = true;
+ FlxFlicker.flicker(e);
+ for (i in [bg, scoreBG, scoreText, opponentText, diffText, comboText])
+ FlxTween.tween(i, {alpha: 0}, llll / 1000);
+ if (inst != null)
+ inst.fadeOut(llll / 1000, 0);
+ if (vocals != null)
+ vocals.fadeOut(llll / 1000, 0);
+ if (opponentVocals != null)
+ opponentVocals.fadeOut(llll / 1000, 0);
+ if (FlxG.sound.music != null)
+ FlxG.sound.music.fadeOut(llll / 1000, 0);
+
+ FlxG.camera.fade(FlxColor.BLACK, llll / 1000, false, moveToSong, true);
+ }
+
+ var alreadyPlayingSong:Bool = false;
+ var resetSong:Bool = false;
+ var exit:Bool = true;
+
+ private function playSong():Void
+ {
+ try
+ {
+ if (instPlaying == curSelected && player.playingMusic && !resetSong)
+ {
+ player.pauseOrResume(!player.playing);
+ }
+ else
+ {
+ if (MainMenuState.freakyPlaying != false)
+ MainMenuState.freakyPlaying = false;
+ if (FlxG.sound.music != null)
+ {
+ FlxG.sound.music.stop();
+ }
+ if (inst != null)
+ inst.stop();
+ if (vocals != null)
+ vocals.stop();
+ if (opponentVocals != null)
+ opponentVocals.stop();
+
+ if (instPlaying != curSelected)
+ {
+ instPlaying = -1;
+ if (inst != null)
+ {
+ remove(inst);
+ inst.destroy();
+ inst = null;
+ }
+
+ Mods.currentModDirectory = songs[curSelected].folder;
+
+ var poop:String = Highscore.formatSong(songs[curSelected].songName.toLowerCase(), curDifficulty);
+ Song.loadFromJson(poop, songs[curSelected].songName.toLowerCase());
+ curInstPlayingtxt = instPlayingtxt = songs[curSelected].songName.toLowerCase();
+
+ var songPath:String = null;
+ songPath = PlayState.SONG.songId;
+
+ if (PlayState.SONG.needsVoices)
+ {
+ final currentPrefix:String = (PlayState.SONG.options.vocalsPrefix != null ? PlayState.SONG.options.vocalsPrefix : '');
+ final currentSuffix:String = (PlayState.SONG.options.vocalsSuffix != null ? PlayState.SONG.options.vocalsSuffix : '');
+
+ vocals = new FlxSound();
+ try
+ {
+ final vocalPl:String = getFromCharacter(PlayState.SONG.characters.player).vocals_file;
+ final vocalSuffix:String = (vocalPl != null && vocalPl.length > 0) ? vocalPl : 'Player';
+ final normalVocals = Paths.voices(currentPrefix, songPath, currentSuffix);
+ var loadedPlayerVocals = SoundUtil.findVocalOrInst((PlayState.SONG._extraData != null
+ && PlayState.SONG._extraData._vocalSettings != null) ? PlayState.SONG._extraData._vocalSettings : {
+ song: songPath,
+ prefix: currentPrefix,
+ suffix: currentSuffix,
+ externVocal: vocalSuffix,
+ character: PlayState.SONG.characters.player,
+ difficulty: Difficulty.getString(curDifficulty)
+ });
+ if (loadedPlayerVocals == null && normalVocals != null)
+ loadedPlayerVocals = normalVocals;
+
+ if (loadedPlayerVocals != null && loadedPlayerVocals.length > 0)
+ {
+ vocals.loadEmbedded(loadedPlayerVocals);
+ vocals.volume = 0;
+ add(vocals);
+ }
+ else
+ {
+ remove(vocals);
+ vocals = null;
+ }
+ }
+ catch (e:haxe.Exception)
+ {
+ Debug.logError('vocal couldn\'t load ${e.message}');
+ remove(vocals);
+ vocals = null;
+ }
+
+ opponentVocals = new FlxSound();
+ try
+ {
+ final vocalOp:String = getFromCharacter(PlayState.SONG.characters.opponent).vocals_file;
+ final vocalSuffix:String = (vocalOp != null && vocalOp.length > 0) ? vocalOp : 'Opponent';
+ var loadedVocals = SoundUtil.findVocalOrInst((PlayState.SONG._extraData != null
+ && PlayState.SONG._extraData._vocalOppSettings != null) ? PlayState.SONG._extraData._vocalOppSettings : {
+ song: songPath,
+ prefix: currentPrefix,
+ suffix: currentSuffix,
+ externVocal: vocalSuffix,
+ character: PlayState.SONG.characters.opponent,
+ difficulty: Difficulty.getString(curDifficulty)
+ });
+ if (loadedVocals != null && loadedVocals.length > 0)
+ {
+ opponentVocals.loadEmbedded(loadedVocals);
+ opponentVocals.volume = 0;
+ add(opponentVocals);
+ }
+ else
+ {
+ remove(opponentVocals);
+ opponentVocals = null;
+ }
+ }
+ catch (e:haxe.Exception)
+ {
+ Debug.logError('opponent vocal couldn\'t load ${e.message}');
+ remove(opponentVocals);
+ opponentVocals = null;
+ }
+ }
+
+ inst = new FlxSound();
+ try
+ {
+ final currentPrefix:String = (PlayState.SONG.options.instrumentalPrefix != null ? PlayState.SONG.options.instrumentalPrefix : '');
+ final currentSuffix:String = (PlayState.SONG.options.instrumentalSuffix != null ? PlayState.SONG.options.instrumentalSuffix : '');
+ inst.loadEmbedded(SoundUtil.findVocalOrInst((PlayState.SONG._extraData != null
+ && PlayState.SONG._extraData._instSettings != null) ? PlayState.SONG._extraData._instSettings : {
+ song: songPath,
+ prefix: currentPrefix,
+ suffix: currentSuffix,
+ externVocal: "",
+ character: "",
+ difficulty: Difficulty.getString(curDifficulty)
+ }, 'INST'));
+ inst.volume = 0;
+ add(inst);
+ }
+ catch (e:haxe.Exception)
+ {
+ Debug.logError('inst couldn\'t load ${e.message}');
+ remove(inst);
+ inst = null;
+ }
+
+ songPath = null;
+ }
+
+ Conductor.bpm = PlayState.SONG.bpm;
+ Conductor.mapBPMChanges(PlayState.SONG);
+
+ player.curTime = 0;
+
+ inst.time = 0;
+ if (vocals != null)
+ vocals.time = 0;
+ if (opponentVocals != null)
+ opponentVocals.volume = 0;
+
+ inst.play();
+ if (vocals != null)
+ vocals.play();
+ if (opponentVocals != null)
+ opponentVocals.play();
+ instPlaying = curSelected;
+
+ player.playingMusic = true;
+ player.curTime = 0;
+ player.switchPlayMusic();
+ // player.pauseOrResume(true);
+
+ exit = false;
+
+ if (inst != null)
+ {
+ inst.onComplete = function()
+ {
+ if (vocals != null)
+ vocals.time = 0;
+ if (opponentVocals != null)
+ opponentVocals.time = 0;
+ inst.time = 0;
+ remove(inst);
+ if (vocals != null)
+ remove(vocals);
+ if (opponentVocals != null)
+ remove(opponentVocals);
+ inst.destroy();
+ if (vocals != null)
+ vocals.destroy();
+ if (opponentVocals != null)
+ opponentVocals.destroy();
+ vocals = null;
+ opponentVocals = null;
+ inst = null;
+ completed = true;
+ exit = false;
+
+ player.curTime = 0;
+ player.playingMusic = false;
+ player.switchPlayMusic();
+
+ for (i in 0...iconArray.length)
+ {
+ iconArray[i].scale.set(1, 1);
+ iconArray[i].updateHitbox();
+ iconArray[i].angle = 0;
+ }
+ }
+ }
+ }
+ }
+ catch (e:haxe.Exception)
+ {
+ Debug.logError('ERROR! ${e.message}');
+ }
+ }
+
+ function getFromCharacter(char:String):CharacterFile
+ {
+ try
+ {
+ var path:String = Paths.getPath('data/characters/$char.json', TEXT);
+ #if MODS_ALLOWED
+ var character:Dynamic = Json.parse(File.getContent(path));
+ #else
+ var character:Dynamic = Json.parse(Assets.getText(path));
+ #end
+ return character;
+ }
+ catch (e:Dynamic)
+ {
+ }
+ return null;
+ }
+
+ public function moveToSong()
+ {
+ if (inst != null)
+ inst = null;
+ if (vocals != null)
+ vocals = null;
+ if (opponentVocals != null)
+ opponentVocals = null;
+ Conductor.songPosition = 0;
+ Conductor.bpmChangeMap = [];
+ player.playingMusic = false;
+ persistentUpdate = false;
+ curInstPlayingtxt = instPlayingtxt = '';
+ MainMenuState.freakyPlaying = false;
+ FlxG.sound.music.stop();
+
+ Debug.logInfo('CURRENT WEEK: ' + WeekData.getWeekFileName());
+
+ try
+ {
+ var poop:String = Highscore.formatSong(Paths.formatToSongPath(songs[curSelected].songName), curDifficulty);
+ Song.loadFromJson(poop, Paths.formatToSongPath(songs[curSelected].songName));
+ PlayState.isStoryMode = false;
+ PlayState.storyDifficulty = curDifficulty;
+ Debug.logInfo(poop);
+ }
+ catch (e:haxe.Exception)
+ {
+ Debug.logError('ERROR! ${e.message}');
+
+ var errorStr:String = e.message;
+ if (errorStr.contains('There is no TEXT asset with an ID of'))
+ errorStr = 'Missing file: '
+ + errorStr.substring(errorStr.indexOf(Paths.formatToSongPath(songs[curSelected].songName)), errorStr.length - 1); // Missing chart
+ missingText.text = 'ERROR WHILE LOADING CHART:\n$errorStr';
+ missingText.screenCenter(Y);
+ missingText.visible = true;
+ missingTextBG.visible = true;
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+ canSelectSong = true;
+ persistentUpdate = true;
+ return;
+ }
+
+ // restore this functionality
+ LoadingState.prepareToSong();
+ LoadingState.loadAndSwitchState(new states.PlayState());
+ #if !SHOW_LOADING_SCREEN
+ if (FlxG.sound.music != null)
+ FlxG.sound.music.volume = 0;
+ #end
+ stopMusicPlay = true;
+ }
+
+ function changeDiff(change:Int = 0)
+ {
+ if (player.playingMusic)
+ return;
+ curDifficulty = FlxMath.wrap(curDifficulty + change, 0, Difficulty.list.length - 1);
+
+ final songData = Highscore.getSongScore(songs[curSelected].songName, curDifficulty, opponentMode);
+ #if !switch
+ intendedScore = songData.mainData.score;
+ intendedAccuracy = songData.rankData.accuracy;
+ combo = songData.rankData.comboRank;
+ rating = songData.rankData.rating;
+ #end
+
+ lastDifficultyName = Difficulty.getString(curDifficulty, false);
+ var displayDiff:String = Difficulty.getString(curDifficulty);
+ if (Difficulty.list.length > 1)
+ diffText.text = 'DIFFICULTY: < ' + displayDiff.toUpperCase() + ' >';
+ else
+ diffText.text = 'DIFFICULTY: ' + displayDiff.toUpperCase();
+
+ curStringDifficulty = lastDifficultyName;
+
+ missingText.visible = false;
+ missingTextBG.visible = false;
+ diffText.alpha = 1;
+
+ diffText.useTextColor = true;
+ FlxTween.color(diffText, 0.3, diffText.textColor,
+ scorecolorDifficulty.exists(curStringDifficulty) ? scorecolorDifficulty.get(curStringDifficulty) : FlxColor.WHITE, {
+ ease: FlxEase.quadInOut
+ });
+ }
+
+ function changeSelection(change:Int = 0, playSound:Bool = true)
+ {
+ if (player.playingMusic)
+ return;
+
+ curSelected = FlxMath.wrap(curSelected + change, 0, songs.length - 1);
+ _updateSongLastDifficulty();
+ if (playSound)
+ FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
+
+ var newColor:Int = songs[curSelected].color;
+ if (newColor != intendedColor)
+ {
+ intendedColor = newColor;
+
+ FlxTween.cancelTweensOf(bg);
+ FlxTween.color(bg, 1, bg.color, intendedColor);
+
+ // Set the window border color with a tween from the current song's color
+ // Idea from VS Camellia ALT (https://gamebanana.com/mods/413258) (They use my code to set the window border color XD)
+ WindowsFuncs.cancelWindowBorderColorTween();
+ WindowsFuncs.tweenWindowBorderColor(CustomFuncs.colorIntToRGB(bg.color), CustomFuncs.colorIntToRGB(intendedColor), 1, "linear");
+ }
+
+ for (num => item in grpSongs.members)
+ {
+ var icon:SlushiFreeplayHealthIcon = iconArray[num];
+ icon.alpha = item.alpha = (item.targetY == curSelected) ? 1 : 0.2;
+ if (icon.hasWinning)
+ icon.animation.curAnim.curFrame = (icon == iconArray[curSelected]) ? 2 : 0;
+ }
+
+ Mods.currentModDirectory = songs[curSelected].folder;
+ PlayState.storyWeek = songs[curSelected].week;
+ Difficulty.loadFromWeek();
+ bg.loadGraphic(SlushiMain.getSLEPath('SlushiFreeplayStateAssets/BG.png'));
+
+ var savedDiff:String = songs[curSelected].lastDifficulty;
+ var lastDiff:Int = Difficulty.list.indexOf(lastDifficultyName);
+ if (savedDiff != null && !Difficulty.list.contains(savedDiff) && Difficulty.list.contains(savedDiff))
+ curDifficulty = Math.round(Math.max(0, Difficulty.list.indexOf(savedDiff)));
+ else if (lastDiff > -1)
+ curDifficulty = lastDiff;
+ else if (Difficulty.list.contains(Difficulty.getDefault()))
+ curDifficulty = Math.round(Math.max(0, Difficulty.list.indexOf(Difficulty.getDefault())));
+ else
+ curDifficulty = 0;
+
+ changeDiff();
+ _updateSongLastDifficulty();
+ }
+
+ inline private function _updateSongLastDifficulty()
+ {
+ if (curDifficulty < 1)
+ songs[curSelected].lastDifficulty = Difficulty.list[0];
+ else if (Difficulty.list.length < 1)
+ songs[curSelected].lastDifficulty = Difficulty.list[0];
+ else
+ songs[curSelected].lastDifficulty = Difficulty.getString(curDifficulty, false);
+ }
+
+ var _drawDistance:Int = 4;
+ var _lastVisibles:Array = [];
+
+ public function updateTexts(elapsed:Float = 0.0, accepted:Bool = false)
+ {
+ lerpSelected = FlxMath.lerp(curSelected, lerpSelected, Math.exp(-elapsed * 9.6));
+ for (i in _lastVisibles)
+ {
+ grpSongs.members[i].visible = grpSongs.members[i].active = false;
+ iconArray[i].visible = iconArray[i].active = false;
+ }
+ _lastVisibles = [];
+
+ var min:Int = Math.round(Math.max(0, Math.min(songs.length, lerpSelected - _drawDistance)));
+ var max:Int = Math.round(Math.max(0, Math.min(songs.length, lerpSelected + _drawDistance)));
+ for (i in min...max)
+ {
+ var item:Alphabet = grpSongs.members[i];
+ item.visible = item.active = true;
+
+ if (item.text == songs[curSelected].songName)
+ {
+ player.songTextY = item.y;
+ }
+
+ if (accepted)
+ {
+ var musicLength:Float = FlxG.sound.play(Paths.sound('confirmMenu')).length;
+ if (item.text != songs[curSelected].songName)
+ {
+ for (cam in [camNotes, camBG, camSongs])
+ {
+ FlxTween.tween(cam, {angle: 10}, musicLength / 1000);
+ FlxTween.tween(cam, {zoom: 1.6}, musicLength / 1000);
+ }
+
+
+ if (SlushiSongs.checkSong(songs[curSelected].songName, Difficulty.getString(curDifficulty)) && ClientPrefs.data.shaders)
+ {
+ var shader:WaveBurstEffect = new WaveBurstEffect();
+ for (cam in [camNotes, camBG, camSongs])
+ {
+ cam.setFilters([new ShaderFilter(shader.shader)]);
+ }
+
+ var numTween = FlxTween.num(0, 0.2, musicLength / 1000, {ease: FlxEase.quartOut});
+ numTween.onUpdate = function(twn:FlxTween)
+ {
+ shader.strength = numTween.value;
+ }
+ }
+
+ FlxTween.tween(item, {y: 6000}, musicLength / 1000);
+ var randomInt = FlxG.random.int(0, 1);
+ if (randomInt == 0)
+ FlxTween.tween(item, {angle: 10}, musicLength / 1000);
+ else if (randomInt == 1)
+ FlxTween.tween(item, {angle: -10}, musicLength / 1000);
+ }
+ else
+ {
+ // FlxTween.tween(item.scale, {x: 1.35, y: 1.35}, musicLength / 1000, {ease: FlxEase.quartOut});
+ FlxTween.tween(item, {y: item.y + 30}, musicLength / 1000);
+ }
+ }
+ else
+ {
+ item.x = ((item.targetY - lerpSelected) * item.distancePerItem.x) + item.startPosition.x;
+ item.screenCenter(X);
+ }
+
+ item.y = ((item.targetY - lerpSelected) * 1.8 * item.distancePerItem.y) + item.startPosition.y;
+
+ var icon:SlushiFreeplayHealthIcon = iconArray[i];
+ icon.visible = icon.active = true;
+ _lastVisibles.push(i);
+ }
+ }
+
+ function loadCharacterFile(char:String):CharacterFile
+ {
+ var characterPath:String = 'data/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('data/characters/' + Character.DEFAULT_CHARACTER +
+ '.json'); // If a character couldn't be found, change him to BF just to prevent a crash
+ }
+
+ #if MODS_ALLOWED
+ var rawJson = File.getContent(path);
+ #else
+ var rawJson = OpenFlAssets.getText(path);
+ #end
+ return cast haxe.Json.parse(rawJson);
+ }
+
+ /**
+ * [noteEffect] and [noteEffectUP] are code from Hitmans AD
+ */
+ private function noteEffect()
+ {
+ // if (!ClientPrefs.data.lowQuality)
+ // return;
+
+ var note:FlxSprite = new FlxSprite().loadGraphic(SlushiMain.getSLEPath("SlushiFreeplayStateAssets/DANOTE.png"));
+ note.antialiasing = ClientPrefs.data.antialiasing;
+ note.cameras = [camNotes];
+ var randomFloat:Float = FlxG.random.float(0.3, 0.6);
+ note.scale.set(randomFloat, randomFloat);
+ note.updateHitbox();
+ note.y = -200;
+ note.x = FlxG.random.int(0, FlxG.width);
+ note.angle = FlxG.random.int(0, 360);
+ note.alpha = 0.3;
+
+ var noteRGBFirstColumn:Array = [];
+ for (row in ClientPrefs.data.arrowRGB)
+ {
+ noteRGBFirstColumn.push(row[0]);
+ }
+
+ var randomIndex:Int = FlxG.random.int(0, noteRGBFirstColumn.length - 1);
+ note.color = noteRGBFirstColumn[randomIndex];
+ add(note);
+
+ var noteTrail = new FlxTrail(note, null, 2, 4, 0.15, 0.10);
+ noteTrail.cameras = [camNotes];
+ noteTrail.alpha = 0.3;
+ noteTrail.color = note.color;
+ add(noteTrail);
+ FlxTween.tween(noteTrail, {alpha: 0}, 2, {ease: FlxEase.quadInOut});
+ FlxTween.tween(note, {
+ x: note.x - 125,
+ y: 730,
+ angle: note.angle + 360,
+ alpha: 0
+ }, 2, {
+ ease: FlxEase.quadInOut,
+ onComplete: function(twn:FlxTween)
+ {
+ remove(note);
+ remove(noteTrail);
+ }
+ });
+ }
+
+ private function noteEffectUP()
+ {
+ // if (!ClientPrefs.data.lowQuality)
+ // return;
+
+ var note:FlxSprite = new FlxSprite().loadGraphic(SlushiMain.getSLEPath("SlushiFreeplayStateAssets/DANOTE.png"));
+ note.antialiasing = ClientPrefs.data.antialiasing;
+ note.cameras = [camNotes];
+ note.scale.set(0.5, 0.5);
+ note.updateHitbox();
+ note.y = FlxG.height + 100;
+ note.x = FlxG.random.int(0, FlxG.width);
+ note.angle = FlxG.random.int(0, 360);
+ note.alpha = 0.3;
+
+ var firstColumn:Array = [];
+ for (row in ClientPrefs.data.arrowRGB)
+ {
+ firstColumn.push(row[0]);
+ }
+
+ var randomIndex:Int = FlxG.random.int(0, firstColumn.length - 1);
+ note.color = firstColumn[randomIndex];
+ add(note);
+
+ var noteTrail = new FlxTrail(note, null, 2, 4, 0.15, 0.10);
+ noteTrail.cameras = [camNotes];
+ noteTrail.alpha = 0.3;
+ noteTrail.color = note.color;
+ insert(members.indexOf(note), noteTrail);
+ FlxTween.tween(noteTrail, {alpha: 0}, 2, {ease: FlxEase.quadInOut});
+ FlxTween.tween(note, {
+ x: note.x - 125,
+ y: 0,
+ angle: note.angle + 360,
+ alpha: 0
+ }, 2, {
+ ease: FlxEase.quadInOut,
+ onComplete: function(twn:FlxTween)
+ {
+ remove(note);
+ remove(noteTrail);
+ }
+ });
+ }
+
+ override function stepHit()
+ {
+ super.stepHit();
+
+ if (!player.playingMusic)
+ return;
+
+ if (curStep % 4 == 0)
+ {
+ noteEffect();
+ }
+ else
+ {
+ noteEffectUP();
+ }
+ }
+
+ override function beatHit()
+ {
+ super.beatHit();
+
+ if (!player.playingMusic)
+ return;
+
+ if (!Application.current.window.maximized)
+ {
+ // SlushiModifier moment XDD
+ if (curBeat % 2 == 0)
+ {
+ WindowFuncs.setWinPositionInX(WindowFuncs.getWindowPositionInX() - 10);
+ FlxTween.tween(Application.current.window, {x: WindowFuncs.getWindowPositionInX() + 10}, 0.2, {ease: FlxEase.quadOut});
+ }
+ else
+ {
+ WindowFuncs.setWinPositionInX(WindowFuncs.getWindowPositionInX() + 10);
+ FlxTween.tween(Application.current.window, {x: WindowFuncs.getWindowPositionInX() - 10}, 0.2, {ease: FlxEase.quadOut});
+ }
+ }
+
+ if (curBeat % 2 == 0)
+ bg.scale.set(1.06, 1.06);
+ bg.updateHitbox();
+ bg.offset.set();
+ for (icon in iconArray)
+ {
+ if (curSelected == iconArray.indexOf(icon))
+ continue;
+ icon.playAnim('normal', true);
+ }
+ for (i in 0...iconArray.length)
+ {
+ iconArray[i].iconBopSpeed = 1;
+ iconArray[i].beatHit(curBeat);
+ }
+ }
+
+ override function sectionHit()
+ {
+ super.sectionHit();
+
+ if (player.playingMusic)
+ {
+ if (ClientPrefs.data.camZooms && FlxG.camera.zoom < 1.35)
+ {
+ FlxG.camera.zoom += 0.03 / rate;
+ }
+ }
+ }
+
+ override function destroy()
+ {
+ #if desktop
+ for (music in [inst, vocals, opponentVocals])
+ {
+ if (music != null)
+ {
+ remove(music);
+ music.destroy();
+ music = null;
+ }
+ }
+ #end
+ player.destroy();
+ super.destroy();
+ }
+}
diff --git a/funkinscsource/slushi/states/freeplay/SlushiMusicPlayer.hx b/funkinscsource/slushi/states/freeplay/SlushiMusicPlayer.hx
new file mode 100644
index 0000000..4e4071a
--- /dev/null
+++ b/funkinscsource/slushi/states/freeplay/SlushiMusicPlayer.hx
@@ -0,0 +1,382 @@
+package slushi.states.freeplay;
+
+import flixel.group.FlxGroup;
+import flixel.ui.FlxBar;
+import slushi.states.freeplay.SlushiFreeplayState;
+import flixel.util.FlxStringUtil;
+
+/**
+ * Music player used for Freeplay
+ *
+ * Author: ??? - Modified by Slushi
+ */
+@:access(slushi.states.freeplay.SlushiFreeplayState)
+class SlushiMusicPlayer extends FlxGroup
+{
+ public var instance:SlushiFreeplayState;
+ public var controls:Controls;
+
+ public var playing(get, never):Bool;
+
+ public var playingMusic:Bool = false;
+ public var curTime:Float;
+
+ var timeTxt:FlxText;
+ var progressBar:FlxBar;
+ var playbackSymbols:Array = [];
+ var playbackTxt:FlxText;
+
+ public var wasPlaying:Bool;
+
+ public var holdPitchTime:Float = 0;
+ public var playbackRate(default, set):Float = 1;
+
+ public var fadingOut:Bool;
+
+ public var backgroundLol:FlxSprite;
+
+ public var songTextY:Float = 0;
+
+ public var sineValue:Float = 0;
+
+ public function new(instance:SlushiFreeplayState)
+ {
+ super();
+
+ this.instance = instance;
+ this.controls = instance.controls;
+
+ var xPos:Float = FlxG.width * 0.7;
+
+ timeTxt = new FlxText(xPos, 0, 0, "", 32);
+ timeTxt.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, RIGHT);
+ add(timeTxt);
+
+ for (i in 0...2)
+ {
+ var text:FlxText = new FlxText();
+ text.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, CENTER);
+ text.text = '^';
+ if (i == 1)
+ text.flipY = true;
+ text.visible = false;
+ playbackSymbols.push(text);
+ add(text);
+ }
+
+ progressBar = new FlxBar(timeTxt.x, timeTxt.y + timeTxt.height, LEFT_TO_RIGHT, Std.int(timeTxt.width), 8, null, "", 0, Math.POSITIVE_INFINITY);
+ progressBar.createFilledBar(FlxColor.WHITE, SlushiMain.slushiColor);
+ add(progressBar);
+
+ playbackTxt = new FlxText(FlxG.width * 0.6, 20, 0, "", 32);
+ playbackTxt.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE);
+ add(playbackTxt);
+
+ backgroundLol = new FlxSprite(0, 0).makeGraphic(Std.int(FlxG.width), Std.int(FlxG.height), 0xFF000000);
+ backgroundLol.alpha = 0;
+ add(backgroundLol);
+
+ switchPlayMusic();
+
+ camera = SlushiFreeplayState.instance.camSongs;
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (!playingMusic)
+ {
+ Conductor.songPosition = -5000 / Conductor.songPosition;
+ return;
+ }
+
+ Conductor.songPosition = SlushiFreeplayState.instance.inst.time;
+
+ if (playing && !wasPlaying)
+ {
+ timeTxt.alpha = 1;
+ }
+ else
+ {
+ if (timeTxt != null && timeTxt.visible)
+ {
+ sineValue += 180 * elapsed;
+ timeTxt.alpha = 1 - Math.sin((Math.PI * sineValue) / 180);
+ }
+ }
+
+ if (controls.UI_LEFT_P)
+ {
+ if (playing)
+ wasPlaying = true;
+
+ pauseOrResume();
+
+ curTime = SlushiFreeplayState.instance.inst.time - 1000;
+ instance.holdTime = 0;
+
+ if (curTime < 0)
+ curTime = 0;
+
+ SlushiFreeplayState.instance.inst.time = curTime;
+ setVocalsTime(curTime);
+ }
+ if (controls.UI_RIGHT_P)
+ {
+ if (playing)
+ wasPlaying = true;
+
+ pauseOrResume();
+
+ curTime = SlushiFreeplayState.instance.inst.time + 1000;
+ instance.holdTime = 0;
+
+ if (curTime > SlushiFreeplayState.instance.inst.length)
+ curTime = SlushiFreeplayState.instance.inst.length;
+
+ SlushiFreeplayState.instance.inst.time = curTime;
+ setVocalsTime(curTime);
+ }
+
+ if (controls.UI_LEFT || controls.UI_RIGHT)
+ {
+ instance.holdTime += elapsed;
+ if (instance.holdTime > 0.5)
+ {
+ curTime += 40000 * elapsed * (controls.UI_LEFT ? -1 : 1);
+ }
+
+ var difference:Float = Math.abs(curTime - SlushiFreeplayState.instance.inst.time);
+ if (curTime + difference > SlushiFreeplayState.instance.inst.length)
+ curTime = SlushiFreeplayState.instance.inst.length;
+ else if (curTime - difference < 0)
+ curTime = 0;
+
+ SlushiFreeplayState.instance.inst.time = curTime;
+ setVocalsTime(curTime);
+ }
+
+ if (controls.UI_LEFT_R || controls.UI_RIGHT_R)
+ {
+ SlushiFreeplayState.instance.inst.time = curTime;
+ setVocalsTime(curTime);
+
+ if (wasPlaying)
+ {
+ pauseOrResume(true);
+ wasPlaying = false;
+ }
+ }
+ if (controls.UI_UP_P)
+ {
+ holdPitchTime = 0;
+ playbackRate += 0.05;
+ setPlaybackRate();
+ }
+ else if (controls.UI_DOWN_P)
+ {
+ holdPitchTime = 0;
+ playbackRate -= 0.05;
+ setPlaybackRate();
+ }
+ if (controls.UI_DOWN || controls.UI_UP)
+ {
+ holdPitchTime += elapsed;
+ if (holdPitchTime > 0.6)
+ {
+ playbackRate += 0.05 * (controls.UI_UP ? 1 : -1);
+ setPlaybackRate();
+ }
+ }
+
+ if (controls.RESET)
+ {
+ playbackRate = 1;
+ setPlaybackRate();
+
+ SlushiFreeplayState.instance.inst.time = 0;
+ setVocalsTime(0);
+
+ updateTimeTxt();
+ }
+
+ if (playing && !fadingOut)
+ {
+ if (SlushiFreeplayState.instance.inst != null)
+ SlushiFreeplayState.instance.inst.volume = 0.8;
+ if (SlushiFreeplayState.instance.vocals != null)
+ SlushiFreeplayState.instance.vocals.volume = (SlushiFreeplayState.instance.vocals.length > SlushiFreeplayState.instance.inst.time) ? 0.8 : 0;
+ if (SlushiFreeplayState.instance.opponentVocals != null)
+ SlushiFreeplayState.instance.opponentVocals.volume = (SlushiFreeplayState.instance.opponentVocals.length > SlushiFreeplayState.instance.inst.time) ? 0.8 : 0;
+
+ if ((SlushiFreeplayState.instance.vocals != null
+ && SlushiFreeplayState.instance.vocals.length > SlushiFreeplayState.instance.inst.time
+ && Math.abs(SlushiFreeplayState.instance.inst.time - SlushiFreeplayState.instance.vocals.time) >= 25)
+ || (SlushiFreeplayState.instance.opponentVocals != null
+ && SlushiFreeplayState.instance.opponentVocals.length > SlushiFreeplayState.instance.inst.time
+ && Math.abs(SlushiFreeplayState.instance.inst.time - SlushiFreeplayState.instance.opponentVocals.time) >= 25))
+ {
+ pauseOrResume();
+ setVocalsTime(SlushiFreeplayState.instance.inst.time);
+ pauseOrResume(true);
+ }
+ }
+ if (playingMusic)
+ {
+ positionSong();
+ updateTimeTxt();
+ updatePlaybackTxt();
+ }
+ }
+
+ function setVocalsTime(time:Float)
+ {
+ if (SlushiFreeplayState.instance.vocals != null && SlushiFreeplayState.instance.vocals.length > time)
+ SlushiFreeplayState.instance.vocals.time = time;
+ if (SlushiFreeplayState.instance.opponentVocals != null && SlushiFreeplayState.instance.opponentVocals.length > time)
+ SlushiFreeplayState.instance.opponentVocals.time = time;
+ }
+
+ public function pauseOrResume(resume:Bool = false)
+ {
+ if (resume)
+ {
+ if (!SlushiFreeplayState.instance.inst.playing)
+ SlushiFreeplayState.instance.inst.resume();
+
+ if (SlushiFreeplayState.instance.vocals != null
+ && SlushiFreeplayState.instance.vocals.length > SlushiFreeplayState.instance.inst.time
+ && !SlushiFreeplayState.instance.vocals.playing)
+ SlushiFreeplayState.instance.vocals.resume();
+ if (SlushiFreeplayState.instance.opponentVocals != null
+ && SlushiFreeplayState.instance.opponentVocals.length > SlushiFreeplayState.instance.inst.time
+ && !SlushiFreeplayState.instance.opponentVocals.playing)
+ SlushiFreeplayState.instance.opponentVocals.resume();
+ }
+ else
+ {
+ SlushiFreeplayState.instance.inst.pause();
+
+ if (SlushiFreeplayState.instance.vocals != null)
+ SlushiFreeplayState.instance.vocals.pause();
+
+ if (SlushiFreeplayState.instance.opponentVocals != null)
+ SlushiFreeplayState.instance.opponentVocals.pause();
+ }
+ }
+
+ function positionSong()
+ {
+ timeTxt.y = songTextY + 90;
+ timeTxt.screenCenter(X);
+
+ progressBar.setGraphicSize(Std.int(timeTxt.width), 5);
+ progressBar.y = timeTxt.y + timeTxt.height;
+ progressBar.screenCenter(X);
+
+ playbackTxt.screenCenter();
+ playbackTxt.y = progressBar.y + 50;
+
+ for (i in 0...2)
+ {
+ var text = playbackSymbols[i];
+ text.x = playbackTxt.x + playbackTxt.width / 2 - 10;
+ text.y = playbackTxt.y;
+ if (i == 0)
+ text.y -= playbackTxt.height;
+ else
+ text.y += playbackTxt.height;
+ }
+ }
+
+ public function switchPlayMusic()
+ {
+ active = visible = playingMusic;
+
+ instance.scoreBG.visible = instance.diffText.visible = instance.scoreText.visible = instance.comboText.visible = instance.opponentText.visible = !playingMusic; // Hide Freeplay texts and boxes if playingMusic is true
+
+ timeTxt.visible = playbackTxt.visible = progressBar.visible = playingMusic; // Show Music Player texts and boxes if playingMusic is true
+
+ for (i in playbackSymbols)
+ i.visible = playingMusic;
+
+ holdPitchTime = 0;
+ instance.holdTime = 0;
+ playbackRate = 1;
+ updatePlaybackTxt();
+
+ if (playingMusic)
+ {
+ instance.downText.text = Language.getPhrase('musicplayer_tip', "Press SPACE to Pause / Press ESCAPE to Exit / Press R to Reset the Song");
+ instance.downText.x = -210;
+ positionSong();
+
+ progressBar.setRange(0, SlushiFreeplayState.instance.inst.length);
+ progressBar.setParent(SlushiFreeplayState.instance.inst, "time");
+ progressBar.numDivisions = 1600;
+
+ updateTimeTxt();
+ // backgroundLol.alpha = .5;
+ }
+ else
+ {
+ progressBar.setRange(0, Math.POSITIVE_INFINITY);
+ progressBar.setParent(null, "");
+ progressBar.numDivisions = 0;
+
+ instance.downText.text = instance.leText;
+ instance.downText.x = -600;
+ // backgroundLol.alpha = 0;
+ }
+ progressBar.updateBar();
+ }
+
+ function updatePlaybackTxt()
+ {
+ var text = "";
+ if (playbackRate is Int)
+ text = playbackRate + '.00';
+ else
+ {
+ var playbackRate = Std.string(playbackRate);
+ if (playbackRate.split('.')[1].length < 2)
+ playbackRate += '0';
+
+ text = playbackRate;
+ }
+ playbackTxt.text = text + 'x';
+ }
+
+ function updateTimeTxt()
+ {
+ var text = FlxStringUtil.formatTime(FlxMath.roundDecimal(Conductor.songPosition / 1000 / playbackRate, 2), false)
+ + ' / '
+ + FlxStringUtil.formatTime(FlxMath.roundDecimal(SlushiFreeplayState.instance.inst.length / 1000 / playbackRate, 2), false);
+ timeTxt.text = '< ' + text + ' >';
+ }
+
+ function setPlaybackRate()
+ {
+ SlushiFreeplayState.instance.inst.pitch = playbackRate;
+ if (SlushiFreeplayState.instance.vocals != null)
+ SlushiFreeplayState.instance.vocals.pitch = playbackRate;
+ if (SlushiFreeplayState.instance.opponentVocals != null)
+ SlushiFreeplayState.instance.opponentVocals.pitch = playbackRate;
+ }
+
+ function get_playing():Bool
+ {
+ return SlushiFreeplayState.instance.inst.playing;
+ }
+
+ function set_playbackRate(value:Float):Float
+ {
+ var value = FlxMath.roundDecimal(value, 2);
+ if (value > 3)
+ value = 3;
+ else if (value <= 0.25)
+ value = 0.25;
+ return playbackRate = value;
+ }
+}
diff --git a/funkinscsource/slushi/substates/DebugSubState.hx b/funkinscsource/slushi/substates/DebugSubState.hx
index e43fcca..da9e91f 100644
--- a/funkinscsource/slushi/substates/DebugSubState.hx
+++ b/funkinscsource/slushi/substates/DebugSubState.hx
@@ -21,6 +21,8 @@ class DebugSubState extends MusicBeatSubState
'[In Gameplay] F3 + P: Active Practice mode',
'F3 + C: Center the window',
'F3 + F: Force crash',
+ 'F3 + S: Show a terminal',
+ 'F3 + W: Enter WinSL mode'
];
public static var onPlayState:Bool = false;
@@ -51,7 +53,6 @@ class DebugSubState extends MusicBeatSubState
buildNumber.setFormat("VCR OSD Mono", 25, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
buildNumber.scrollFactor.set();
buildNumber.screenCenter(X);
- // buildNumber.x -= 200;
buildNumber.alpha = 0.6;
add(buildNumber);
@@ -150,13 +151,23 @@ class DebugSubState extends MusicBeatSubState
});
}
- if (FlxG.keys.pressed.F3 && FlxG.keys.pressed.C && !Application.current.window.maximized && !Application.current.window.fullscreen)
+ if (FlxG.keys.pressed.F3
+ && FlxG.keys.justPressed.C
+ && !Application.current.window.maximized
+ && !Application.current.window.fullscreen)
{
- #if windows
- CppAPI.centerWindow();
- #else
WindowFuncs.setWinPositionInX(Std.int((WindowFuncs.getScreenSizeInWidth() - WindowFuncs.getWindowSizeInWidth()) / 2));
WindowFuncs.setWinPositionInY(Std.int((WindowFuncs.getScreenSizeInHeight() - WindowFuncs.getWindowSizeInHeight()) / 2));
+ }
+
+ if (FlxG.keys.pressed.F3 && FlxG.keys.justPressed.S)
+ {
+ #if windows
+ WindowsTerminalCPP.allocConsole();
+ WindowsTerminalCPP.setConsoleTitle('WinSL [${SlushiMain.sleThingsVersions.winSLVersion}] - Viewing SlushiEngine_${SlushiMain.buildNumber}.vm terminal');
+ WindowsTerminalCPP.setConsoleWindowIcon(SlushiMain.getSLEPath("WinSL_Assets/windowIcon.ico"));
+ WindowsTerminalCPP.setWinConsoleColor();
+ WindowsTerminalCPP.disableCloseWindow();
#end
}
@@ -166,4 +177,4 @@ class DebugSubState extends MusicBeatSubState
}
super.update(elapsed);
}
-}
\ No newline at end of file
+}
diff --git a/funkinscsource/slushi/substates/SlushiPauseSubState.hx b/funkinscsource/slushi/substates/SlushiPauseSubState.hx
new file mode 100644
index 0000000..6d569ff
--- /dev/null
+++ b/funkinscsource/slushi/substates/SlushiPauseSubState.hx
@@ -0,0 +1,772 @@
+package slushi.substates;
+
+import backend.WeekData;
+import backend.Highscore;
+import states.StoryMenuState;
+import options.OptionsState;
+import flixel.util.FlxStringUtil;
+
+class SlushiPauseSubState extends MusicBeatSubState
+{
+ public static var songName:String = null;
+
+ var grpMenuShit:FlxTypedGroup;
+
+ var menuItems:Array = [];
+ var menuItemsOG:Array = ['Resume', 'Restart Song', 'Change Difficulty', 'Options', 'Exit to menu'];
+ var difficultyChoices = [];
+ var optionChoices = [];
+ var curSelected:Int = 0;
+
+ var pauseMusic:FlxSound;
+ var optionsText:FlxText;
+ var practiceText:FlxText;
+ var skipTimeText:FlxText;
+ var skipTimeTracker:Alphabet;
+ var curTime:Float = Math.max(0, Conductor.songPosition);
+
+ var missingTextBG:FlxSprite;
+ var missingText:FlxText;
+
+ var music:FlxSound = FlxG.sound.music;
+
+ var settings = {
+ music: ClientPrefs.data.pauseMusic
+ };
+
+ var num:Int = 0;
+
+ var bg:FlxSprite;
+ var slBG:FlxSprite;
+
+ override function create()
+ {
+ game.paused = true;
+
+ if (Difficulty.list.length < 2)
+ menuItemsOG.remove('Change Difficulty'); // No need to change difficulty if there is only one!
+
+ if (PlayState.chartingMode)
+ {
+ menuItemsOG.insert(2, 'Leave Charting Mode');
+ }
+ else if (PlayState.modchartMode)
+ {
+ menuItemsOG.insert(2, 'Leave ModChart Mode');
+ }
+
+ if (PlayState.chartingMode || PlayState.modchartMode)
+ {
+ if (!game.startingSong)
+ {
+ num = 1;
+ menuItemsOG.insert(3, 'Skip Time');
+ }
+ menuItemsOG.insert(3 + num, 'End Song');
+ menuItemsOG.insert(4 + num, 'Toggle Practice Mode');
+ menuItemsOG.insert(5 + num, 'Toggle Botplay');
+ }
+ menuItems = menuItemsOG;
+
+ for (i in 0...Difficulty.list.length)
+ {
+ var diff:String = Difficulty.getString(i);
+ difficultyChoices.push(diff);
+ }
+ difficultyChoices.push('BACK');
+
+ for (i in OptionsState.options)
+ {
+ optionChoices.push(i);
+ }
+ optionChoices.push('BACK');
+
+ if (pauseMusic != null)
+ pauseMusic = null;
+
+ pauseMusic = new FlxSound();
+ try
+ {
+ var pauseSong:String = getPauseSong();
+ if (pauseSong != null)
+ pauseMusic.loadEmbedded(Paths.music(pauseSong), true, true);
+ }
+ catch (e:Dynamic)
+ {
+ }
+ pauseMusic.volume = 0;
+ pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2)));
+ FlxG.sound.list.add(pauseMusic);
+
+ bg = new FlxSprite().makeGraphic(1, 1, FlxColor.BLACK);
+ bg.scale.set(FlxG.width, FlxG.height);
+ bg.updateHitbox();
+ bg.alpha = 0;
+ bg.scrollFactor.set();
+ add(bg);
+
+ slBG = new FlxSprite().loadGraphic(SlushiMain.getSLEPath('BGs/SlushiBGPauseSubState.png'));
+ slBG.antialiasing = ClientPrefs.data.antialiasing;
+ slBG.updateHitbox();
+ slBG.screenCenter();
+ slBG.alpha = 0;
+ slBG.color = SlushiMain.slushiColor;
+ add(slBG);
+
+ var levelInfo:FlxText = new FlxText(20, 15, 0, 'Song: ' + PlayState.SONG.songId, 32);
+ levelInfo.scrollFactor.set();
+ levelInfo.setFormat(Paths.font("vcr.ttf"), 32);
+ levelInfo.updateHitbox();
+ add(levelInfo);
+
+ var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, 'Difficulty: ' + Difficulty.getString().toUpperCase(), 32);
+ levelDifficulty.scrollFactor.set();
+ levelDifficulty.setFormat(Paths.font('vcr.ttf'), 32);
+ levelDifficulty.updateHitbox();
+ add(levelDifficulty);
+
+ var blueballedTxt:FlxText = new FlxText(20, 15 + 64, 0, Language.getPhrase("blueballed", "Blueballed: {1}", [PlayState.deathCounter]), 32);
+ blueballedTxt.scrollFactor.set();
+ blueballedTxt.setFormat(Paths.font('vcr.ttf'), 32);
+ blueballedTxt.updateHitbox();
+ add(blueballedTxt);
+
+ practiceText = new FlxText(20, 15 + 101, 0, Language.getPhrase("Practice Mode").toUpperCase(), 32);
+ practiceText.scrollFactor.set();
+ practiceText.setFormat(Paths.font('vcr.ttf'), 32);
+ practiceText.x = FlxG.width - (practiceText.width + 20);
+ practiceText.updateHitbox();
+ practiceText.visible = game.practiceMode;
+ add(practiceText);
+
+ var chartingText:FlxText = new FlxText(20, 15 + 101, 0, "", 32);
+ chartingText.scrollFactor.set();
+ if (PlayState.chartingMode)
+ chartingText.text = Language.getPhrase("Charting Mode").toUpperCase();
+ else if (PlayState.modchartMode)
+ chartingText.text = Language.getPhrase("Modchart Mode").toUpperCase();
+ else
+ chartingText.text = "";
+ chartingText.setFormat(Paths.font('vcr.ttf'), 32);
+ chartingText.x = FlxG.width - (chartingText.width + 20);
+ chartingText.y = FlxG.height - (chartingText.height + 20);
+ chartingText.updateHitbox();
+ chartingText.visible = (PlayState.chartingMode || PlayState.modchartMode);
+ add(chartingText);
+
+ var notITGText:FlxText = new FlxText(20, 15 + 101, 0, Language.getPhrase("Modchart Disabled").toUpperCase(), 32);
+ notITGText.scrollFactor.set();
+ notITGText.setFormat(Paths.font('vcr.ttf'), 32);
+ notITGText.x = FlxG.width - (notITGText.width + 20);
+ notITGText.y = FlxG.height - (notITGText.height + 60);
+ notITGText.updateHitbox();
+ notITGText.visible = !ClientPrefs.getGameplaySetting('modchart');
+ add(chartingText);
+
+ blueballedTxt.alpha = 0;
+ levelDifficulty.alpha = 0;
+ levelInfo.alpha = 0;
+ chartingText.alpha = 0;
+ practiceText.alpha = 0;
+ practiceText.y -= 5;
+
+ levelInfo.x = FlxG.width - (levelInfo.width + 20);
+ levelDifficulty.x = FlxG.width - (levelDifficulty.width + 20);
+ blueballedTxt.x = FlxG.width - (blueballedTxt.width + 20);
+
+ // thank you crowplexus for the portuguese translation!! - subpurr
+ optionsText = new FlxText(20, 15 + 101, 0,
+ Language.getPhrase("options_in_pause_warning", "WARNING: Not all options are supported!\nSome options may not update until you restart."), 32);
+ optionsText.scrollFactor.set();
+ optionsText.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ optionsText.borderSize = 4;
+ optionsText.y = FlxG.height - (optionsText.height + 20);
+ optionsText.updateHitbox();
+
+ FlxTween.tween(bg, {alpha: 0.6}, 0.4, {ease: FlxEase.quartInOut});
+ FlxTween.tween(slBG, {alpha: 0.8}, 0.4, {ease: FlxEase.quartInOut});
+ FlxTween.tween(chartingText, {alpha: 1}, 0.4, {ease: FlxEase.quartInOut});
+ FlxTween.tween(levelInfo, {alpha: 1, y: 20}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.3});
+ FlxTween.tween(levelDifficulty, {alpha: 1, y: levelDifficulty.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.5});
+ FlxTween.tween(blueballedTxt, {alpha: 1, y: blueballedTxt.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.7});
+ FlxTween.tween(practiceText, {alpha: 1, y: practiceText.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.9});
+
+ grpMenuShit = new FlxTypedGroup();
+ add(grpMenuShit);
+
+ missingTextBG = new FlxSprite().makeGraphic(1, 1, FlxColor.BLACK);
+ missingTextBG.scale.set(FlxG.width, FlxG.height);
+ missingTextBG.updateHitbox();
+ missingTextBG.alpha = 0.6;
+ missingTextBG.visible = false;
+ add(missingTextBG);
+
+ missingText = new FlxText(50, 0, FlxG.width - 100, '', 24);
+ missingText.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ missingText.scrollFactor.set();
+ missingText.visible = false;
+ add(missingText);
+
+ regenMenu();
+ cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
+
+ super.create();
+ }
+
+ function getPauseSong()
+ {
+ var formattedSongName:String = (songName != null ? Paths.formatToSongPath(songName) : '');
+ var formattedPauseMusic:String = Paths.formatToSongPath(ClientPrefs.data.pauseMusic);
+ if (formattedSongName == 'none' || (formattedSongName != 'none' && formattedPauseMusic == 'none'))
+ return null;
+
+ return (formattedSongName != '') ? formattedSongName : formattedPauseMusic;
+ }
+
+ var holdTime:Float = 0;
+ var cantUnpause:Float = 0.1;
+
+ public var getReady:FlxSprite;
+ public var countdownReady:FlxSprite;
+ public var countdownSet:FlxSprite;
+ public var countdownGo:FlxSprite;
+ public var inCountDown:Bool = false;
+ public var unPauseTimer:FlxTimer;
+
+ var stoppedUpdatingMusic:Bool = false;
+
+ override function update(elapsed:Float)
+ {
+ if (controls.BACK)
+ {
+ close();
+ game.canResync = true;
+ return;
+ }
+
+ if (game != null)
+ game.paused = true;
+ cantUnpause -= elapsed;
+ if (!stoppedUpdatingMusic)
+ { // Reason to no put != null outside is to not confuse the game to not "stop" when intended.
+ if (pauseMusic != null && pauseMusic.volume < 0.5)
+ pauseMusic.volume += 0.01 * elapsed;
+ }
+ else
+ {
+ if (pauseMusic != null)
+ pauseMusic.volume = 0;
+ }
+
+ super.update(elapsed);
+
+ updateSkipTextStuff();
+
+ if (controls.UI_UP_P && !inCountDown)
+ {
+ changeSelection(-1);
+ }
+ if (controls.UI_DOWN_P && !inCountDown)
+ {
+ changeSelection(1);
+ }
+ if (FlxG.mouse.wheel != 0)
+ changeSelection(-FlxG.mouse.wheel);
+
+ var daSelected:String = menuItems[curSelected];
+ switch (daSelected)
+ {
+ case 'Skip Time':
+ if (controls.UI_LEFT_P)
+ {
+ FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
+ curTime -= 1000;
+ holdTime = 0;
+ }
+ if (controls.UI_RIGHT_P)
+ {
+ FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
+ curTime += 1000;
+ holdTime = 0;
+ }
+
+ if (controls.UI_LEFT || controls.UI_RIGHT)
+ {
+ holdTime += elapsed;
+ if (holdTime > 0.5)
+ {
+ curTime += 45000 * elapsed * (controls.UI_LEFT ? -1 : 1);
+ }
+
+ if (curTime >= music.length)
+ curTime -= music.length;
+ else if (curTime < 0)
+ curTime += music.length;
+ updateSkipTimeText();
+ }
+ }
+
+ if (FlxG.keys.justPressed.F5 && !inCountDown)
+ {
+ FlxTransitionableState.skipNextTransIn = true;
+ FlxTransitionableState.skipNextTransOut = true;
+ PlayState.nextReloadAll = true;
+ MusicBeatState.resetState();
+ }
+
+ if ((controls.ACCEPT && (cantUnpause <= 0 || !controls.controllerMode)) && !inCountDown)
+ {
+ // Finally
+ if (menuItems == difficultyChoices)
+ {
+ var songLowercase:String = Paths.formatToSongPath(PlayState.SONG.songId);
+ var poop:String = Highscore.formatSong(songLowercase, curSelected);
+ try
+ {
+ if (menuItems.length - 1 != curSelected && difficultyChoices.contains(daSelected))
+ {
+ Song.loadFromJson(poop, songLowercase);
+ PlayState.storyDifficulty = curSelected;
+ LoadingState.loadAndSwitchState(new PlayState());
+ music.volume = 0;
+ PlayState.changedDifficulty = true;
+ PlayState.chartingMode = false;
+ PlayState.modchartMode = false;
+ return;
+ }
+ }
+ catch (e:haxe.Exception)
+ {
+ Debug.logError('ERROR! ${e.message}');
+
+ var errorStr:String = e.message;
+ if (errorStr.startsWith('[lime.utils.Assets] ERROR:'))
+ errorStr = 'Missing file: ' + errorStr.substring(errorStr.indexOf(songLowercase), errorStr.length - 1); // Missing chart
+ else
+ errorStr += '\n\n' + e.stack;
+ missingText.text = 'ERROR WHILE LOADING CHART:\n$errorStr';
+ missingText.screenCenter(Y);
+ missingText.visible = true;
+ missingTextBG.visible = true;
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+
+ super.update(elapsed);
+ return;
+ }
+
+ menuItems = menuItemsOG;
+ regenMenu();
+ }
+
+ if (menuItems == optionChoices)
+ {
+ switch (daSelected)
+ {
+ case 'Note Options':
+ OptionsState.onPlayState = true;
+ FlxTransitionableState.skipNextTransOut = true;
+ FlxTransitionableState.skipNextTransIn = true;
+ MusicBeatState.switchState(new options.NoteOptions());
+ game.canResync = false;
+ case 'Controls':
+ openSubState(new options.ControlsSubState());
+ case 'Graphics':
+ openSubState(new options.GraphicsSettingsSubState());
+ case 'Visuals':
+ openSubState(new options.VisualsSettingsSubState());
+ case 'Gameplay':
+ openSubState(new options.GameplaySettingsSubState());
+ case 'Misc':
+ openSubState(new options.MiscSettingsSubState());
+ case 'Adjust Delay and Combo':
+ OptionsState.onPlayState = true;
+ MusicBeatState.switchState(new options.NoteOffsetState());
+ game.canResync = false;
+ case 'Language':
+ openSubState(new options.LanguageSubState());
+ default:
+ ClientPrefs.saveSettings();
+ ClientPrefs.loadPrefs();
+ ClientPrefs.keybindSaveLoad();
+ menuItems = menuItemsOG;
+ regenMenu();
+ remove(optionsText); // no need for visible, just remove it
+ }
+ return;
+ }
+
+ if (!stoppedUpdatingMusic)
+ {
+ stoppedUpdatingMusic = true;
+ destroyMusic();
+ }
+ menuOptions(daSelected);
+ }
+ }
+
+ var isCountDown:Bool = false;
+
+ function menuOptions(daSelected:String)
+ {
+ switch (daSelected)
+ {
+ case "Resume":
+ if (ClientPrefs.data.pauseCountDown)
+ {
+ unPauseTimer = new FlxTimer().start(Conductor.crochet / 1000 / music.pitch, function(hmmm:FlxTimer)
+ {
+ switch (hmmm.loopsLeft)
+ {
+ case 4 | 3 | 2 | 1:
+ pauseCountDown();
+ case 0:
+ if (hmmm.finished)
+ pauseCountDown();
+ }
+ }, 5);
+ isCountDown = true;
+ for (item in grpMenuShit.members)
+ {
+ FlxTween.tween(item, {alpha: 0}, 0.56, {ease: FlxEase.quadOut});
+ }
+ }
+ inCountDown = true;
+ if (!isCountDown)
+ close();
+ case 'Change Difficulty':
+ menuItems = difficultyChoices;
+ deleteSkipTimeText();
+ regenMenu();
+ case 'Toggle Practice Mode':
+ game.practiceMode = !game.practiceMode;
+ PlayState.changedDifficulty = true;
+ practiceText.visible = game.practiceMode;
+ case "Restart Song", "Leave Charting Mode", "Leave ModChart Mode":
+ LoadingState.loadAndSwitchState(new PlayState());
+
+ switch (daSelected)
+ {
+ case "Leave Charting Mode":
+ PlayState.chartingMode = false;
+ case "Leave ModChart Mode":
+ PlayState.modchartMode = false;
+ }
+ case 'Skip Time':
+ if (curTime < Conductor.songPosition)
+ {
+ PlayState.startOnTime = curTime;
+ restartSong(true);
+ }
+ else
+ {
+ if (curTime != Conductor.songPosition)
+ {
+ game.clearNotesBefore(curTime);
+ game.setSongTime(curTime);
+ }
+ close();
+ }
+ case 'Toggle Botplay':
+ game.cpuControlled = !game.cpuControlled;
+ PlayState.changedDifficulty = true;
+ game.botplayTxt.visible = game.cpuControlled;
+ game.botplayTxt.alpha = 1;
+ game.botplaySine = 0;
+ case 'Options':
+ menuItems = optionChoices;
+ deleteSkipTimeText();
+ regenMenu();
+ add(optionsText); // ensure it's at front
+ case 'End Song':
+ close();
+ game.notes.clear();
+ game.unspawnNotes.clear();
+ game.finishSong(true);
+ case "Exit to menu":
+ #if DISCORD_ALLOWED DiscordClient.resetClientID(); #end
+ PlayState.deathCounter = 0;
+ PlayState.seenCutscene = false;
+
+ Mods.loadTopMod();
+
+ if (ClientPrefs.data.behaviourType != 'VSLICE')
+ {
+ if (PlayState.isStoryMode)
+ MusicBeatState.switchState(new StoryMenuState());
+ else
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
+ }
+ #if BASE_GAME_FILES
+ else
+ {
+ if (PlayState.isStoryMode)
+ {
+ PlayState.storyPlaylist = [];
+ openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker)));
+ }
+ else
+ openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new slushi.states.freeplay.SlushiFreeplayState(sticker)));
+ }
+ #end
+
+ game.canResync = false;
+ FlxG.sound.playMusic(SlushiMain.getSLEPath("Musics/SLE_HackNet_Resonance.ogg"));
+ PlayState.changedDifficulty = false;
+ PlayState.chartingMode = false;
+ PlayState.modchartMode = false;
+ game.alreadyEndedSong = false;
+ FlxG.camera.followLerp = 0;
+ if (PlayState.forceMiddleScroll)
+ {
+ if (PlayState.savePrefixScrollR && PlayState.prefixRightScroll)
+ {
+ ClientPrefs.data.middleScroll = false;
+ }
+ }
+ else if (PlayState.forceRightScroll)
+ {
+ if (PlayState.savePrefixScrollM && PlayState.prefixMiddleScroll)
+ {
+ ClientPrefs.data.middleScroll = true;
+ }
+ }
+ }
+ }
+
+ function destroyMusic()
+ {
+ pauseMusic.volume = 0;
+ pauseMusic.destroy();
+ pauseMusic = null;
+ }
+
+ var CDANumber:Int = 5;
+ var game:PlayState = PlayState.instance;
+
+ function pauseCountDown()
+ {
+ if (game == null)
+ return;
+ game.stageIntroSoundsSuffix = game.stage.stageIntroSoundsSuffix != null ? game.stage.stageIntroSoundsSuffix : '';
+ game.stageIntroSoundsPrefix = game.stage.stageIntroSoundsPrefix != null ? game.stage.stageIntroSoundsPrefix : '';
+
+ var introAssets:Map> = new Map>();
+ var introImagesArray:Array = switch (PlayState.stageUI)
+ {
+ case "pixel": [
+ '${PlayState.stageUI}UI/ready-pixel',
+ '${PlayState.stageUI}UI/set-pixel',
+ '${PlayState.stageUI}UI/date-pixel'
+ ];
+ case "normal": ["ready", "set", "go"];
+ default: [
+ '${PlayState.stageUI}UI/ready',
+ '${PlayState.stageUI}UI/set',
+ '${PlayState.stageUI}UI/go'
+ ];
+ }
+ if (game.stage.stageIntroAssets != null)
+ introAssets.set(PlayState.curStage, game.stage.stageIntroAssets);
+ else
+ introAssets.set(PlayState.stageUI, introImagesArray);
+
+ var isPixelated:Bool = PlayState.isPixelStage;
+ var introAlts:Array = (game.stage.stageIntroAssets != null ? introAssets.get(PlayState.curStage) : introAssets.get(PlayState.stageUI));
+ var antialias:Bool = (ClientPrefs.data.antialiasing && !isPixelated);
+ for (value in introAssets.keys())
+ {
+ if (value == PlayState.curStage)
+ {
+ introAlts = introAssets.get(value);
+
+ if (game.stageIntroSoundsSuffix != null && game.stageIntroSoundsSuffix.length > 0)
+ game.introSoundsSuffix = game.stageIntroSoundsSuffix;
+ else
+ game.introSoundsSuffix = '';
+
+ if (game.stageIntroSoundsPrefix != null && game.stageIntroSoundsPrefix.length > 0)
+ game.introSoundsPrefix = game.stageIntroSoundsPrefix;
+ else
+ game.introSoundsPrefix = '';
+ }
+ }
+
+ CDANumber -= 1;
+
+ var introArrays0:Array = [];
+ var introArrays1:Array = [];
+ var introArrays2:Array = [];
+ var introArrays3:Array = [];
+ if (game.stage.stageIntroSpriteScales != null)
+ {
+ introArrays0 = game.stage.stageIntroSpriteScales[0];
+ introArrays1 = game.stage.stageIntroSpriteScales[1];
+ introArrays2 = game.stage.stageIntroSpriteScales[2];
+ introArrays3 = game.stage.stageIntroSpriteScales[3];
+ }
+
+ switch (CDANumber)
+ {
+ case 4:
+ var isNotNull = (introAlts.length > 3 ? introAlts[0] : "missingRating");
+ getReady = createCountdownSprite(isNotNull, antialias, game.introSoundsPrefix + 'intro3' + game.introSoundsSuffix, introArrays0);
+ case 3:
+ countdownReady = createCountdownSprite(introAlts[introAlts.length - 3], antialias, game.introSoundsPrefix + 'intro2' + game.introSoundsSuffix,
+ introArrays1);
+ case 2:
+ countdownSet = createCountdownSprite(introAlts[introAlts.length - 2], antialias, game.introSoundsPrefix + 'intro1' + game.introSoundsSuffix,
+ introArrays2);
+ case 1:
+ countdownGo = createCountdownSprite(introAlts[introAlts.length - 1], antialias, game.introSoundsPrefix + 'introGo' + game.introSoundsSuffix,
+ introArrays3);
+ case 0:
+ close();
+ }
+ }
+
+ inline private function createCountdownSprite(image:String, antialias:Bool, soundName:String, scale:Array = null):FlxSprite
+ {
+ var spr:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image(image));
+ spr.scrollFactor.set();
+ spr.updateHitbox();
+
+ if (image.contains("-pixel") && scale == null)
+ spr.setGraphicSize(Std.int(spr.width * PlayState.daPixelZoom));
+
+ if (scale != null)
+ spr.scale.set(scale[0], scale[1]);
+
+ spr.screenCenter();
+ spr.antialiasing = antialias;
+ add(spr);
+ FlxTween.tween(spr, {y: spr.y + 100, alpha: 0}, Conductor.crochet / 1000, {
+ ease: FlxEase.cubeInOut,
+ onComplete: function(twn:FlxTween)
+ {
+ remove(spr);
+ spr.destroy();
+ }
+ });
+ if (!game.stage.disabledIntroSounds)
+ FlxG.sound.play(Paths.sound(soundName), 0.6);
+ return spr;
+ }
+
+ function deleteSkipTimeText()
+ {
+ if (skipTimeText != null)
+ {
+ skipTimeText.kill();
+ remove(skipTimeText);
+ skipTimeText.destroy();
+ }
+ skipTimeText = null;
+ skipTimeTracker = null;
+ }
+
+ public static function restartSong(noTrans:Bool = false)
+ {
+ if (PlayState.instance != null)
+ {
+ PlayState.instance.paused = true; // For lua
+ if (PlayState.instance.vocals != null)
+ {
+ PlayState.instance.vocals.volume = 0;
+ }
+
+ if (PlayState.instance.splitVocals && PlayState.instance.opponentVocals != null)
+ {
+ PlayState.instance.opponentVocals.volume = 0;
+ }
+ }
+ if (FlxG.sound.music != null)
+ FlxG.sound.music.volume = 0;
+
+ if (noTrans)
+ {
+ FlxTransitionableState.skipNextTransIn = true;
+ FlxTransitionableState.skipNextTransOut = true;
+ }
+ MusicBeatState.resetState();
+ }
+
+ override function destroy()
+ {
+ if (pauseMusic != null)
+ pauseMusic.destroy();
+ game.canResync = true;
+
+ super.destroy();
+ }
+
+ function changeSelection(change:Int = 0):Void
+ {
+ curSelected = FlxMath.wrap(curSelected + change, 0, menuItems.length - 1);
+ for (num => item in grpMenuShit.members)
+ {
+ item.targetY = num - curSelected;
+ item.alpha = (item.targetY == 0) ? 1 : 0.6;
+
+ if (item.targetY == 0 && item == skipTimeTracker)
+ {
+ curTime = Math.max(0, Conductor.songPosition);
+ updateSkipTimeText();
+ }
+ }
+
+ missingText.visible = false;
+ missingTextBG.visible = false;
+ FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
+ }
+
+ function regenMenu():Void
+ {
+ for (i in 0...grpMenuShit.members.length)
+ {
+ var obj:Alphabet = grpMenuShit.members[0];
+ obj.kill();
+ grpMenuShit.remove(obj, true);
+ obj.destroy();
+ }
+ for (num => str in menuItems)
+ {
+ var item = new Alphabet(90, 320, Language.getPhrase('pause_$str', str), true);
+ item.isMenuItem = true;
+ item.targetY = num;
+ grpMenuShit.add(item);
+ if (!PlayState.chartingMode || !PlayState.modchartMode)
+ item.screenCenter(X);
+
+ if (str == 'Skip Time')
+ {
+ skipTimeText = new FlxText(0, 0, 0, '', 64);
+ skipTimeText.setFormat(Paths.font("vcr.ttf"), 64, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ skipTimeText.scrollFactor.set();
+ skipTimeText.borderSize = 2;
+ skipTimeTracker = item;
+ add(skipTimeText);
+
+ updateSkipTextStuff();
+ updateSkipTimeText();
+ }
+ }
+
+ curSelected = 0;
+ changeSelection();
+ }
+
+ function updateSkipTextStuff()
+ {
+ if (skipTimeText == null || skipTimeTracker == null)
+ return;
+
+ skipTimeText.x = skipTimeTracker.x + skipTimeTracker.width + 60;
+ skipTimeText.y = skipTimeTracker.y;
+ skipTimeText.visible = (skipTimeTracker.alpha >= 1);
+ }
+
+ function updateSkipTimeText()
+ skipTimeText.text = FlxStringUtil.formatTime(Math.max(0, Math.floor(curTime / 1000)), false)
+ + ' / '
+ + FlxStringUtil.formatTime(Math.max(0, Math.floor(music.length / 1000)), false);
+}
diff --git a/funkinscsource/slushi/winSL/Main.hx b/funkinscsource/slushi/winSL/Main.hx
index d132d50..b35f1bf 100644
--- a/funkinscsource/slushi/winSL/Main.hx
+++ b/funkinscsource/slushi/winSL/Main.hx
@@ -2,7 +2,6 @@ package slushi.winSL;
import Sys;
import haxe.Timer;
-
import sys.io.File;
import sys.FileSystem;
import sys.io.FileInput;
@@ -20,62 +19,73 @@ import haxe.io.Path;
*
* Author: Trock (Modified by Slushi)
*/
+class Main
+{
+ public static var finishedStartup:Bool = false;
-class Main {
- static function clear():Void {
- Modules.ModuleUtils.clearConsole();
- }
+ static function clear():Void
+ {
+ Modules.ModuleUtils.clearConsole();
+ }
- static function startup():Void {
- clear();
+ static function startup():Void
+ {
+ clear();
- Sys.sleep(0.5);
- Sys.println('WinSL [${SlushiMain.winSLVersion}] - Running on ${Sys.systemName()}');
- Sys.sleep(1.2);
- var userName:String = Sys.environment().get("USERNAME");
- if (userName == null)
- userName = Sys.environment().get("USER");
- Sys.println("Started by " + (userName != null ? userName : "an unknown user"));
- Sys.sleep(1.2);
- Sys.println("Already initialized all Microsoft Windows API functions");
- Sys.sleep(0.6);
- // Sys.println('Warning: Possible [MODCHARTS] detected in WinSL/SlushiEngine_${SlushiMain.buildNumber}.vm that may cause an overload and break the Sandbox provided by WinSL.');
- Sys.sleep(0.6);
- Sys.println("Loading WinSL environment...");
- WinSLConsoleUtils.printLetterByLetter('Loading internal Modules....Done\n', 0.035);
- Sys.sleep(0.6);
- WinSLConsoleUtils.printLetterByLetter('Finalizing WinSL environment initialization....Done\n', 0.035);
- WinSLConsoleUtils.printLetterByLetter('-------------\n\n', 0.045);
- Sys.sleep(0.4);
- }
+ Sys.sleep(0.5);
+ Sys.println('WinSL [${SlushiMain.sleThingsVersions.winSLVersion}] - Running on ${Sys.systemName()}');
+ Sys.sleep(1.2);
+ var userName:String = Sys.environment().get("USERNAME");
+ if (userName == null)
+ userName = Sys.environment().get("USER");
+ Sys.println("Started by " + (userName != null ? userName : "an unknown user"));
+ Sys.sleep(1.2);
+ #if windows
+ Sys.println("Already initialized all Microsoft Windows API functions");
+ #else
+ Sys.println("Cannot initialize Microsoft Windows API functions, platform not supported");
+ #end
+ Sys.sleep(0.6);
+ // Sys.println('Warning: Possible [MODCHARTS] detected in WinSL/SlushiEngine_${SlushiMain.buildNumber}.vm that may cause an overload and break the Sandbox provided by WinSL.');
+ Sys.sleep(0.6);
+ Sys.println("Loading WinSL environment...");
+ WinSLConsoleUtils.printLetterByLetter('Loading internal Modules....Done\n', 0.035);
+ Sys.sleep(0.6);
+ WinSLConsoleUtils.printLetterByLetter('Finalizing WinSL environment initialization....Done\n', 0.035);
+ WinSLConsoleUtils.printLetterByLetter('-------------\n\n', 0.045);
+ Sys.sleep(0.4);
+ }
- static public function main():Void {
- startup();
+ static public function main():Void
+ {
+ startup();
- var parser = new Parser([
- new Module(ModuleType.TOKENIZER, Others.tokenize),
- new Module(ModuleType.EXTRACTOR, Others.extract),
- new Module(ModuleType.OPERATOR_HANDLER, Others.process)
- ]);
+ var parser = new Parser([
+ new Module(ModuleType.TOKENIZER, Others.tokenize),
+ new Module(ModuleType.EXTRACTOR, Others.extract),
+ new Module(ModuleType.OPERATOR_HANDLER, Others.process)
+ ]);
- var stdin = Sys.stdin();
- var stdout = Sys.stdout();
+ var stdin = Sys.stdin();
+ var stdout = Sys.stdout();
- var cwd = Sys.getCwd() + "/assets/slushiEngineAssets/SLEAssets/WinSL_Assets/";
- var pathStr = Path.join([cwd, 'sandbox']);
+ var cwd = Sys.getCwd() + "/assets/slushiEngineAssets/WinSL_Assets/";
+ var pathStr = Path.join([cwd, 'sandbox']);
- if (!FileSystem.exists(pathStr)) {
- FileSystem.createDirectory(pathStr);
- }
+ if (!FileSystem.exists(pathStr))
+ {
+ FileSystem.createDirectory(pathStr);
+ }
- var path = FileSystem.exists(pathStr) ? pathStr : FileSystem.fullPath("sandbox");
+ var path = FileSystem.exists(pathStr) ? pathStr : FileSystem.fullPath("sandbox");
- var terminal = new Terminal(parser, stdin, stdout, {'path': path, 'sandbox_path': path});
+ var terminal = new Terminal(parser, stdin, stdout, {'path': path, 'sandbox_path': path});
- for (module in Modules.getModules()) {
- terminal.registerCommandModule(module);
- }
+ for (module in Modules.getModules())
+ {
+ terminal.registerCommandModule(module);
+ }
- terminal.run();
- }
-}
\ No newline at end of file
+ terminal.run();
+ }
+}
diff --git a/funkinscsource/slushi/winSL/Modules.hx b/funkinscsource/slushi/winSL/Modules.hx
index b40cd00..1d0561d 100644
--- a/funkinscsource/slushi/winSL/Modules.hx
+++ b/funkinscsource/slushi/winSL/Modules.hx
@@ -4,396 +4,459 @@ import slushi.winSL.termvm.Terminal;
import slushi.winSL.termvm.CommandModule;
/**
- * Custom modules for the WinSL terminal.
+ * Custom sourced modules for the WinSL terminal.
*
* Author: Slushi
*/
-
-class Modules {
- public static var modules:Array = [];
-
- public static function getModules():Array {
- modules = [
- new CommandModule(["soy"], SoyModule.soy),
- new CommandModule(["itsthisforthat", "ittft"], ItsThisForThatModule.itsthisforthat),
- new CommandModule(["WriteTheWord", "writetheword"], WriteTheWordModule.writeTheWord),
- new CommandModule(["convertSM", "convertsm"], ConvertToFNFModule.main)
- ];
- return modules;
- }
+class Modules
+{
+ public static var modules:Array = [];
+
+ public static function getModules():Array
+ {
+ modules = [
+ new CommandModule(["soy"], SoyModule.soy),
+ new CommandModule(["itsthisforthat", "ittft"], ItsThisForThatModule.itsthisforthat),
+ new CommandModule(["WriteTheWord", "writetheword"], WriteTheWordModule.writeTheWord),
+ new CommandModule(["convertSM", "convertsm"], ConvertToFNFModule.main)
+ ];
+ return modules;
+ }
}
-class ModuleUtils {
- public static function clearConsole():Void {
- #if windows
- return WinConsoleUtils.clearTerminal();
- #else
- Sys.print("\033[3J\033[H\033[2J");
- #end
- }
-
- public static function getSandboxPath():String {
- return SlushiMain.getSLEPath("WinSL_Assets/sandbox/");
- }
-
- public static function getWinSLVersion():String {
- return SlushiMain.winSLVersion;
- }
-
- public static function printAlert(text:String, alertType:String):Void {
- switch(alertType) {
- case "error":
- Sys.println("\033[31m" + text + "\033[0m");
- case "warning":
- Sys.println("\033[33m" + text + "\033[0m");
- case "success":
- Sys.println("\033[32m" + text + "\033[0m");
- case "info":
- Sys.println("\033[34m" + text + "\033[0m");
- default:
- Sys.println(text);
- }
- }
-
- public static function wait(time:Float):Void {
- Sys.sleep(time);
- }
+class ModuleUtils
+{
+ public static function clearConsole():Void
+ {
+ #if windows
+ return WindowsTerminalCPP.clearTerminal();
+ #else
+ Sys.print("\033[3J\033[H\033[2J");
+ #end
+ }
+
+ public static function getSandboxPath():String
+ {
+ return SlushiMain.getSLEPath("WinSL_Assets/sandbox/");
+ }
+
+ public static function getWinSLVersion():String
+ {
+ return SlushiMain.sleThingsVersions.winSLVersion;
+ }
+
+ public static function printAlert(text:String, alertType:String):Void
+ {
+ switch (alertType)
+ {
+ case "error":
+ Sys.println("\033[31m[ERROR]\033[0m " + text);
+ case "warning":
+ Sys.println("\033[33m[WARNING]\033[0m " + text);
+ case "success":
+ Sys.println("\033[32m[SUCCESS]\033[0m " + text);
+ case "info":
+ Sys.println("\033[34m[INFO]\033[0m " + text);
+ default:
+ Sys.println(text);
+ }
+ }
+
+ public static function wait(time:Float):Void
+ {
+ Sys.sleep(time);
+ }
}
-class SoyModule {
- public static function soy(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void {
- if(args[0] != null){
- terminal.stdout.writeString("hola " + args[0] + "!\n");
- }
- else{
- terminal.stdout.writeString("Necesitas introducir un argumento.\n");
- }
- }
+class SoyModule
+{
+ public static function soy(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void
+ {
+ if (args[0] != null)
+ {
+ terminal.stdout.writeString("hola " + args[0] + "!\n");
+ }
+ else
+ {
+ terminal.stdout.writeString("Necesitas introducir un argumento.\n");
+ }
+ }
}
-class ItsThisForThatModule extends ModuleUtils {
- public static function itsthisforthat(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void {
- var urlToRequest:String = "https://itsthisforthat.com/api.php?text";
- var http = new Http(urlToRequest);
-
- http.onData = function(response:String) {
- terminal.stdout.writeString(response + "\n");
- }
-
- http.onError = function(error:String) {
- printAlert('Error while getting [itsthisforthat.com] API data: ' + error, 'error');
- }
-
- http.request();
- }
+class ItsThisForThatModule extends ModuleUtils
+{
+ public static function itsthisforthat(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void
+ {
+ var urlToRequest:String = "https://itsthisforthat.com/api.php?text";
+ var http = new Http(urlToRequest);
+
+ http.onData = function(response:String)
+ {
+ terminal.stdout.writeString(response + "\n");
+ }
+
+ http.onError = function(error:String)
+ {
+ printAlert('Error while getting [itsthisforthat.com] API data: ' + error, 'error');
+ }
+
+ http.request();
+ }
}
-class WriteTheWordModule extends ModuleUtils {
-
- static var points = 0;
+class WriteTheWordModule extends ModuleUtils
+{
+ static var points = 0;
- static var terminalForGame:Terminal;
+ static var terminalForGame:Terminal;
- public static function writeTheWord(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void {
+ public static function writeTheWord(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void
+ {
+ terminalForGame = terminal;
- terminalForGame = terminal;
+ terminal.stdout.writeString("Welcome to Write The Word!\n");
+ terminal.stdout.writeString("Type the word as fast as you can, and accumulate as many points as possible.\n");
- terminal.stdout.writeString("Welcome to Write The Word!\n");
- terminal.stdout.writeString("Type the word as fast as you can, and accumulate as many points as possible.\n");
+ wait(3);
- wait(3);
+ clearConsole();
- clearConsole();
+ game();
- game();
+ wait(0.8);
- wait(0.8);
+ terminal.stdout.writeString('You want to continue? (y/n) ');
- terminal.stdout.writeString('You want to continue? (y/n) ');
+ if (terminal.stdin.readLine().toString() == 'y')
+ {
+ game();
+ }
+ else
+ {
+ terminal.stdout.writeString("Your total points: " + points + "\n");
+ terminal.stdout.writeString('Bye!\n\n');
+ }
+ }
- if (terminal.stdin.readLine().toString() == 'y') {
- game();
- }
- else {
- terminal.stdout.writeString("Your total points: " + points + "\n");
- terminal.stdout.writeString('Bye!\n\n');
- }
- }
+ static function game():Void
+ {
+ var startTime:Float;
+ var endTime:Float;
+ var input:String;
- static function game():Void {
- var startTime:Float;
- var endTime:Float;
- var input:String;
+ var word = getWord();
- var word = getWord();
+ terminalForGame.stdout.writeString("Press Enter to start\n");
- terminalForGame.stdout.writeString("Press Enter to start\n");
+ terminalForGame.stdin.readLine();
- terminalForGame.stdin.readLine();
+ wait(1);
- wait(1);
+ terminalForGame.stdout.writeString("Go!\n");
- terminalForGame.stdout.writeString("Go!\n");
+ terminalForGame.stdout.writeString("Type the word!: " + word + "\n--> ");
- terminalForGame.stdout.writeString("Type the word!: " + word + "\n--> ");
+ startTime = Date.now().getTime();
- startTime = Date.now().getTime();
+ input = terminalForGame.stdin.readLine();
- input = terminalForGame.stdin.readLine();
+ endTime = Date.now().getTime();
- endTime = Date.now().getTime();
+ var elapsedTime = endTime - startTime;
- var elapsedTime = endTime - startTime;
+ var finalTime = Math.floor(elapsedTime / 1000);
- var finalTime = Math.floor(elapsedTime / 1000);
+ if (input == word)
+ {
+ if (elapsedTime < 1000)
+ {
+ terminalForGame.stdout.writeString('Great job! you took ' + finalTime + ' seconds, +10 points\n');
+ points += 10;
+ }
+ else if (elapsedTime < 2000)
+ {
+ terminalForGame.stdout.writeString('Good! you took ' + finalTime + ' seconds, +7 points\n');
+ points += 7;
+ }
+ else if (elapsedTime < 3000)
+ {
+ terminalForGame.stdout.writeString('Well done! you took ' + finalTime + ' seconds, +5 points\n');
+ points += 5;
+ }
+ else
+ {
+ terminalForGame.stdout.writeString('You took ' + finalTime + ' seconds, +2 points\n');
+ }
+ }
+ else
+ {
+ terminalForGame.stdout.writeString('Wrong! The word was ' + word + ', you took ' + finalTime + ' seconds, -5 points\n');
+ points -= 5;
+ }
+ }
- if (input == word) {
- if (elapsedTime < 1000) {
- terminalForGame.stdout.writeString('Great job! you took ' + finalTime + ' seconds, +10 points\n');
- points += 10;
- } else if (elapsedTime < 2000) {
- terminalForGame.stdout.writeString('Good! you took ' + finalTime + ' seconds, +7 points\n');
- points += 7;
- } else if (elapsedTime < 3000) {
- terminalForGame.stdout.writeString('Well done! you took ' + finalTime + ' seconds, +5 points\n');
- points += 5;
- }
- else {
- terminalForGame.stdout.writeString('You took ' + finalTime + ' seconds, +2 points\n');
- }
- } else {
- terminalForGame.stdout.writeString('Wrong! The word was ' + word + ', you took ' + finalTime + ' seconds, -5 points\n');
- points -= 5;
- }
- }
+ static function getWord():String
+ {
+ var urlToRequest:String = "https://random-word-api.herokuapp.com/word";
+ var http = new Http(urlToRequest);
+ var word:String = null;
- static function getWord():String {
- var urlToRequest:String = "https://random-word-api.herokuapp.com/word";
- var http = new Http(urlToRequest);
- var word:String = null;
+ http.onData = function(response:String)
+ {
+ word = response;
+ }
- http.onData = function(response:String) {
- word = response;
- }
-
- http.onError = function(error:String) {
- printAlert('Error while getting [random-word-api.herokuapp.com] API data: ' + error, 'error');
- }
+ http.onError = function(error:String)
+ {
+ printAlert('Error while getting [random-word-api.herokuapp.com] API data: ' + error, 'error');
+ }
- http.request();
+ http.request();
- final finalWord = word.replace('["', '').replace('"]', '');
+ final finalWord = word.replace('["', '').replace('"]', '');
- return finalWord;
- }
+ return finalWord;
+ }
}
-class ConvertToFNFModule {
- static var curSMFile:SMFile;
- static var finalFNFFile:String = '';
- static var finalFNFFileName:String = '';
- static var finalFNFFileNameLowerCase:String = '';
- static var finalDifficulty:String = '';
- static var finalSpeed:Float = 1.0;
-
- public static function main(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void {
- if (args[0] == null) {
- return terminal.stdout.writeString("You need to specify the path to an SM file.\n");
- }
-
- var smFilePath:String = "./engineUtils/SMToConvert/" + args[0];
-
- if (!smFilePath.endsWith(".sm")) {
- return terminal.stdout.writeString("You need to specify a .sm file.\n");
- }
-
- if (!FileSystem.exists(smFilePath)) {
- terminal.stdout.writeString("File not found: [" + args[0] + "]\n");
- terminal.stdout.writeString('You can put it in "engineUtils/SMToConvert"\n');
- return;
- }
-
- terminal.stdout.writeString("Welcome to StepMania to FNF converter v1.3!\n");
-
- terminal.stdout.writeString("Loading SM file...\n");
- Sys.sleep(1.2);
-
- try {
- parseSMFile(smFilePath);
- }
- catch (e) {
- terminal.stdout.writeString("Error: " + e.toString() + "\n");
- return;
- }
-
- terminal.stdout.writeString("Enter the desired song name (press Enter to use SM file name): ");
- var songName:String = terminal.stdin.readLine().toString();
- if (songName == "") {
- songName = curSMFile.title;
- }
-
- while (true) {
- terminal.stdout.writeString("Enter the desired difficulty: ");
- var difficulty:String = terminal.stdin.readLine().toString();
- if (difficulty == "") {
- return terminal.stdout.writeString("You need to specify a difficulty.\n");
- }
- else{
- finalDifficulty = difficulty;
- break;
- }
- }
-
- terminal.stdout.writeString("Enter the desired speed (press Enter to use 3.0): ");
- var speed:String = terminal.stdin.readLine().toString();
- if (speed == "") {
- finalSpeed = 3.0;
- }
- else{
- finalSpeed = Std.parseFloat(speed);
- }
-
- Sys.sleep(1.2);
-
- terminal.stdout.writeString("Generating FNF chart...\n");
- generateChart(songName);
-
- while (true) {
- terminal.stdout.writeString("Do you like delete the original SM file? (y/n): ");
- if (terminal.stdin.readLine().toString() == "y") {
- if(FileSystem.exists(smFilePath))
- FileSystem.deleteFile(smFilePath);
- terminal.stdout.writeString("Done!\n");
- break;
- }
- else {
- break;
- }
- }
-
- while (true) {
- terminal.stdout.writeString("Do you want create the rest of the files for the FNF Song (like week JSON)? (y/n): ");
- if (terminal.stdin.readLine().toString() == "y") {
- createMoreFiles();
- terminal.stdout.writeString("Done!\n");
- break;
- }
- else {
- break;
- }
- }
- }
-
- static function parseSMFile(smFilePath:String):Void {
- var smContent:String = File.getContent(smFilePath);
- smContent = smContent.replace('\r\n', '\n');
- curSMFile = new SMFile(smContent);
-
- Sys.println("Song name: " + curSMFile.title);
- Sys.println("Song BPMS: " + curSMFile.bpms);
- Sys.println("Song offset: " + curSMFile.chartOffset + "\n");
- }
-
- static function generateChart(songName:String):Void {
- var cfg: SongConfig = {
- song: (songName != '') ? songName : 'SMSong',
- speed: finalSpeed, // You can set the default speed or ask the user for input
- player1: 'bf',
- player2: 'gf',
- gfVersion: 'gf'
- };
-
- var fnfchart:Dynamic = curSMFile.makeFNFChart(0, cfg, true);
-
- var jsonContent:String = haxe.Json.stringify(fnfchart, null, '\t');
-
- var outputFileName:String = cfg.song;
- var outputFilePath:String = "./engineUtils/SMToConvert/" + outputFileName.toLowerCase() + ".json";
-
- if (FileSystem.exists(outputFilePath)) {
- FileSystem.deleteFile(outputFilePath);
- Sys.println("Deleted existing file: " + outputFilePath + "\n");
- }
-
- File.saveContent(outputFilePath, jsonContent);
-
- finalFNFFileNameLowerCase = outputFileName.toLowerCase().replace(' ', '-');
- finalFNFFileName = outputFileName;
- finalFNFFile = outputFilePath;
-
- Sys.println("Conversion complete! Check the output file\n");
- Sys.sleep(1.4);
- }
-
- static function createMoreFiles() {
- var modsChartsFolder:String = './mods/data/songs/';
- var modsWeeksFolder:String = './mods/data/weeks/';
- var modsSongOGGFolder:String = './mods/songs/';
- var modsLuaFolder:String = './mods/scripts/songs/';
- var finalPath:String = '';
-
- var oggFile = "";
-
- var directory = FileSystem.readDirectory("./engineUtils/SMToConvert");
-
- for (file in directory) {
- if(file.endsWith(".ogg")) {
- oggFile = file;
- break;
- }
- }
-
- if(FileSystem.exists(finalFNFFile)) {
- if(!FileSystem.exists('$modsChartsFolder$finalFNFFileNameLowerCase')){
- FileSystem.createDirectory('$modsChartsFolder$finalFNFFileNameLowerCase');
- }
- finalPath = '$modsChartsFolder$finalFNFFileNameLowerCase/';
- File.copy(finalFNFFile, '$finalPath$finalFNFFileNameLowerCase-$finalDifficulty.json');
- Sys.println("Copied " + finalFNFFile + " to " + finalPath + finalFNFFileNameLowerCase + "-" + finalDifficulty + ".json");
- Sys.sleep(0.8);
- }
-
- if(FileSystem.exists("./engineUtils/SMToConvert/" + oggFile)) {
- {
- if(!FileSystem.exists('$modsSongOGGFolder$finalFNFFileNameLowerCase')){
- FileSystem.createDirectory('$modsSongOGGFolder$finalFNFFileNameLowerCase');
- }
- finalPath = '$modsSongOGGFolder$finalFNFFileNameLowerCase/';
- File.copy("./engineUtils/SMToConvert/" + oggFile, '$finalPath' + 'Inst.ogg');
- Sys.println("Copied " + "./engineUtils/SMToConvert/" + oggFile + " to " + finalPath + 'Inst.ogg');
- Sys.sleep(0.8);
- }
- }
- else {
- Sys.println("File not found: [" + oggFile + "]\n");
- return;
- }
+typedef WeekJSONFile =
+{
+ // JSON variables
+ var songs:Array;
+
+ var weekBefore:String;
+ var storyName:String;
+ var weekName:String;
+ var freeplayColor:Array;
+ var startUnlocked:Bool;
+ var hideStoryMode:Bool;
+ var hideFreeplay:Bool;
+ var difficulties:String;
+ var blockOpponentMode:Null;
+}
- var weekStructure:String = '
+class ConvertToFNFModule
+{
+ static var converterVersion = "1.3.5";
+ static var curSMFile:SMFile;
+ static var finalFNFFile:String = "";
+ static var finalFNFFileName:String = "";
+ static var finalFNFFileNameLowerCase:String = "";
+ static var finalDifficulty:String = "";
+ static var finalSpeed:Float = 3.0;
+ static var smFilePath:String = "./slEngineUtils/SMToConvert/";
+
+ public static function main(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void
+ {
+ if (args[0] == null)
+ {
+ return terminal.stdout.writeString("You need to specify the path to an SM file.\n");
+ }
+
+ smFilePath += args[0];
+
+ if (!smFilePath.endsWith(".sm"))
+ {
+ return terminal.stdout.writeString("You need to specify a .sm file.\n");
+ }
+
+ if (!FileSystem.exists(smFilePath))
+ {
+ terminal.stdout.writeString("File not found: [" + args[0] + "]\n");
+ terminal.stdout.writeString('You can put it in "slEngineUtils/SMToConvert"\n');
+ return;
+ }
+
+ terminal.stdout.writeString("Welcome to StepMania to FNF converter v" + converterVersion + "!\n");
+
+ terminal.stdout.writeString("Loading SM file...\n");
+ wait(1.2);
+
+ try
+ {
+ parseSMFile(smFilePath);
+ }
+ catch (e)
+ {
+ terminal.stdout.writeString("Error: " + e.toString() + "\n");
+ return;
+ }
+
+ terminal.stdout.writeString("Enter the desired song name (press Enter to use SM file name): ");
+ var songName:String = terminal.stdin.readLine().toString();
+ if (songName == "")
+ {
+ songName = curSMFile.title;
+ }
+
+ while (true)
+ {
+ terminal.stdout.writeString("Enter the desired difficulty: ");
+ var difficulty:String = terminal.stdin.readLine().toString().toLowerCase();
+ if (difficulty != "")
+ {
+ finalDifficulty = difficulty;
+ break;
+ }
+ }
+
+ terminal.stdout.writeString("Enter the desired speed (press Enter to use 3.0): ");
+ var speed:String = terminal.stdin.readLine().toString();
+ if (speed != "")
+ {
+ finalSpeed = Std.parseFloat(speed);
+ }
+
+ wait(1.2);
+
+ terminal.stdout.writeString("Generating FNF chart...\n");
+ generateChart(songName);
+
+ while (true)
+ {
+ terminal.stdout.writeString("Do you want create the rest of the files for the FNF Song (like week JSON)? (y/n): ");
+ if (terminal.stdin.readLine().toString() == "y")
+ {
+ createMoreFiles();
+ terminal.stdout.writeString("Done!\n");
+ break;
+ }
+ if (terminal.stdin.readLine().toString() == "n")
+ {
+ terminal.stdout.writeString("Finished!\n");
+ break;
+ }
+ }
+ }
+
+ static function parseSMFile(smFilePath:String):Void
+ {
+ var smContent:String = File.getContent(smFilePath);
+ smContent = smContent.replace('\r\n', '\n');
+ curSMFile = new SMFile(smContent);
+
+ Sys.println("SM name: " + curSMFile.title);
+ Sys.println("SM BPMS: " + curSMFile.bpms.join(', '));
+ Sys.println("SM offset: " + curSMFile.chartOffset + "\n");
+ }
+
+ static function generateChart(songName:String):Void
+ {
+ var cfg:SongConfig = {
+ song: (songName != '') ? songName : 'SMSong',
+ speed: finalSpeed,
+ player1: 'bf',
+ player2: 'gf',
+ gfVersion: 'gf'
+ };
+
+ var fnfchart:Dynamic = curSMFile.makeFNFChart(0, cfg, true);
+ var jsonContent:String = Json.stringify(fnfchart, null, '\t');
+
+ var outputFileName:String = cfg.song;
+ var outputFilePath:String = "./slEngineUtils/SMToConvert/converted/" + outputFileName.toLowerCase() + ".json";
+
+ if (FileSystem.exists(outputFilePath))
+ {
+ FileSystem.deleteFile(outputFilePath);
+ Sys.println("Deleted existing file [" + outputFilePath + "]");
+ }
+
+ if (!FileSystem.exists("./slEngineUtils/SMToConvert/converted"))
{
- "songs": [
- ["$finalFNFFileName", "gf", [0, 0, 0]]
- ],
-
- "difficulties": "$finalDifficulty",
-
- "storyName": "",
- "weekBefore": "none",
- "weekName": "",
- "startUnlocked": true,
- "hideStoryMode": true,
- "hideFreeplay": false,
- }';
-
- File.saveContent('$modsWeeksFolder$finalFNFFileNameLowerCase.json', weekStructure);
- Sys.println('Created $modsWeeksFolder$finalFNFFileNameLowerCase.json file');
- Sys.sleep(0.8);
-
- var luaStructure:String = '-- Generated by StepMania to FNF Converter v1.3 (By Slushi) --\n\nfunction onCreatePost()\nend\n\nfunction onBeatHit()\nend\n\nfunction onUpdatePost(elapsed)\nend';
- if(!FileSystem.exists('$modsLuaFolder$finalFNFFileNameLowerCase')) {
- FileSystem.createDirectory('$modsLuaFolder$finalFNFFileNameLowerCase');
+ FileSystem.createDirectory("./slEngineUtils/SMToConvert/converted");
}
- File.saveContent('$modsLuaFolder$finalFNFFileNameLowerCase/modchart.lua', luaStructure);
- Sys.println('Created $modsLuaFolder$finalFNFFileNameLowerCase/modchart.lua file');
- }
-}
\ No newline at end of file
+
+ File.saveContent(outputFilePath, jsonContent);
+
+ finalFNFFileNameLowerCase = outputFileName.toLowerCase().replace(' ', '-');
+ finalFNFFileName = outputFileName;
+ finalFNFFile = outputFilePath;
+
+ Sys.println("Conversion complete in [" + outputFilePath + "]!\n");
+ wait(1.4);
+ }
+
+ static function createMoreFiles()
+ {
+ var modsChartsFolder:String = "./mods/data/songs/";
+ var modsWeeksFolder:String = "./mods/data/weeks/";
+ var modsSongOGGFolder:String = "./mods/songs/";
+ var modsLuaFolder:String = "./mods/scripts/songs/";
+ var finalPath:String = "";
+ var oggFile = "";
+
+ var directory = FileSystem.readDirectory("./slEngineUtils/SMToConvert");
+
+ for (file in directory)
+ {
+ if (file.endsWith(".ogg"))
+ {
+ oggFile = file;
+ break;
+ }
+ }
+
+ if (FileSystem.exists(finalFNFFile))
+ {
+ if (!FileSystem.exists('$modsChartsFolder$finalFNFFileNameLowerCase'))
+ {
+ FileSystem.createDirectory('$modsChartsFolder$finalFNFFileNameLowerCase');
+ }
+ finalPath = '$modsChartsFolder$finalFNFFileNameLowerCase/';
+ File.copy(finalFNFFile, '$finalPath$finalFNFFileNameLowerCase-$finalDifficulty.json');
+ Sys.println("Copied [" + finalFNFFile + "] to [" + finalPath + finalFNFFileNameLowerCase + "-" + finalDifficulty + ".json]");
+ wait(0.8);
+ }
+
+ if (FileSystem.exists("./slEngineUtils/SMToConvert/" + oggFile))
+ {
+ {
+ if (!FileSystem.exists('$modsSongOGGFolder$finalFNFFileNameLowerCase'))
+ {
+ FileSystem.createDirectory('$modsSongOGGFolder$finalFNFFileNameLowerCase');
+ }
+ finalPath = '$modsSongOGGFolder$finalFNFFileNameLowerCase/';
+ File.copy("./slEngineUtils/SMToConvert/" + oggFile, '$finalPath' + 'Inst.ogg');
+ Sys.println("Copied " + "[./slEngineUtils/SMToConvert/" + oggFile + "] to [" + finalPath + "Inst.ogg]");
+ wait(0.8);
+ }
+ }
+ else
+ {
+ Sys.println("OGG file not found: [" + oggFile + "]");
+ Sys.println('You can put it in [$modsSongOGGFolder$finalFNFFileNameLowerCase/] and rename it to "Inst.ogg"');
+ Sys.println("Continuing...\n");
+ }
+
+ /**
+ * All this is just to be able to format the JSON
+ * file correctly, instead of being a string that is stored in a JSON file.
+ */
+ var weekJsonStructure:WeekJSONFile = {
+ songs: [[finalFNFFileName, "gf", [0, 0, 0]]],
+
+ difficulties: finalDifficulty,
+ storyName: "",
+ weekBefore: "none",
+ weekName: finalFNFFileNameLowerCase + "-week",
+ startUnlocked: true,
+ hideStoryMode: true,
+ hideFreeplay: false,
+ freeplayColor: [0, 0, 0],
+ blockOpponentMode: true
+ }
+
+ File.saveContent('$modsWeeksFolder$finalFNFFileNameLowerCase.json', Json.stringify(weekJsonStructure));
+ Sys.println('Created [$modsWeeksFolder$finalFNFFileNameLowerCase.json] file');
+ wait(0.8);
+
+ var luaStructure:String = '-- Generated by StepMania to FNF Converter v${converterVersion} (By Slushi) --\n\nfunction onCreatePost()\nend\n\nfunction onBeatHit()\nend\n\nfunction onStepHit()\nend\n\nfunction onUpdatePost(elapsed)\nend';
+ if (!FileSystem.exists('$modsLuaFolder$finalFNFFileNameLowerCase'))
+ {
+ FileSystem.createDirectory('$modsLuaFolder$finalFNFFileNameLowerCase');
+ }
+ File.saveContent('$modsLuaFolder$finalFNFFileNameLowerCase/modchart.lua', luaStructure);
+ Sys.println('Created [$modsLuaFolder$finalFNFFileNameLowerCase/modchart.lua] file');
+ }
+}
diff --git a/funkinscsource/slushi/winSL/WinSLConsoleUtils.hx b/funkinscsource/slushi/winSL/WinSLConsoleUtils.hx
index 4a2c4dc..d90c338 100644
--- a/funkinscsource/slushi/winSL/WinSLConsoleUtils.hx
+++ b/funkinscsource/slushi/winSL/WinSLConsoleUtils.hx
@@ -16,12 +16,12 @@ class WinSLConsoleUtils
FlxG.sound.music.stop();
}
Sys.println("\033[0m");
- WinConsoleUtils.allocConsole();
- WinConsoleUtils.setConsoleTitle('WinSL ${SlushiMain.winSLVersion}');
- WinConsoleUtils.setConsoleWindowIcon(SlushiMain.getSLEPath("WinSL_Assets/windowIcon.ico"));
- WinConsoleUtils.centerConsoleWindow();
- WinConsoleUtils.setWinConsoleColor();
- WinConsoleUtils.hideMainWindow();
+ WindowsTerminalCPP.allocConsole();
+ WindowsTerminalCPP.setConsoleTitle('WinSL [${SlushiMain.sleThingsVersions.winSLVersion}]');
+ WindowsTerminalCPP.setConsoleWindowIcon(SlushiMain.getSLEPath("WinSL_Assets/windowIcon.ico"));
+ WindowsTerminalCPP.centerConsoleWindow();
+ WindowsTerminalCPP.setWinConsoleColor();
+ WindowsTerminalCPP.hideMainWindow();
Main.main();
#end
}
diff --git a/funkinscsource/slushi/winSL/WinSLCrashHandler.hx b/funkinscsource/slushi/winSL/WinSLCrashHandler.hx
index 4bb3a62..2814adf 100644
--- a/funkinscsource/slushi/winSL/WinSLCrashHandler.hx
+++ b/funkinscsource/slushi/winSL/WinSLCrashHandler.hx
@@ -67,6 +67,6 @@ class WinSLCrashHandler {
#end
}
- Sys.exit(1);
+ System.exit(1);
}
}
\ No newline at end of file
diff --git a/funkinscsource/slushi/winSL/import.hx b/funkinscsource/slushi/winSL/import.hx
index c948c47..fc5caad 100644
--- a/funkinscsource/slushi/winSL/import.hx
+++ b/funkinscsource/slushi/winSL/import.hx
@@ -3,3 +3,4 @@ import slushi.winSL.Modules.ModuleUtils.*;
// ConvertToFNFModule
import slushi.slushiUtils.stepManiaTools.*;
import slushi.slushiUtils.stepManiaTools.SMFile.SongConfig;
+import haxe.Json;
diff --git a/funkinscsource/slushi/winSL/termvm/Terminal.hx b/funkinscsource/slushi/winSL/termvm/Terminal.hx
index 8062fb9..d26c938 100644
--- a/funkinscsource/slushi/winSL/termvm/Terminal.hx
+++ b/funkinscsource/slushi/winSL/termvm/Terminal.hx
@@ -8,14 +8,15 @@ import haxe.io.Output;
import haxe.io.Bytes;
import slushi.winSL.termvm.Parser;
import haxe.CallStack;
+#if (fuzzaldrin && WINSL_SUGGEST_COMMAND)
import fuzzaldrin.Fuzzaldrin;
+#end
/**
* The main class of WinSL, the terminal for SLE.
*
* Author: Trock (Modified by Slushi)
*/
-
class Terminal
{
public var parser:Parser;
@@ -27,7 +28,8 @@ class Terminal
public var numberOfCrashes:Int = 0;
public var commandRoot:String = "";
- public var defaultString:String = "> ";
+ public var defaultString:String = "\x1b[38;5;236m>\x1b[0m ";
+
public static var instance:Terminal = null;
public function new(parser:Parser, stdin:Input, stdout:Output, ?metadata:Dynamic)
@@ -45,7 +47,7 @@ class Terminal
registerCommandModule(new CommandModule(["exit", "EXIT"], ExitModule.execute));
registerCommandModule(new CommandModule(["cls", "clear", "CLS", "CLEAR"], ClearModule.execute));
registerCommandModule(new CommandModule(["stop", "STOP"], StopModule.execute));
- registerCommandModule(new CommandModule(["resetVM", "resetvm", "backToVM", "backtovm", "reset"], ResetVMModule.execute));
+ registerCommandModule(new CommandModule(["resetVM", "resetvm", "backToVM", "backtovm", "reset"], ResetVMModule.execute));
registerCommandModule(new CommandModule(["set", "SET"], SetVariableModule.execute));
registerCommandModule(new CommandModule(["get", "GET"], GetVariableModule.execute));
}
@@ -78,23 +80,30 @@ class Terminal
return commandNames;
}
- public function runOnce():Array {
- stdout.writeString(defaultString);
- stdout.flush();
- try {
- var commandLine:String = stdin.readLine();
- if (commandLine != null && commandLine.length > 0 && commandLine != "") {
- var parsedCommands:Array = parser.parse(commandLine);
- for (parsedCommand in parsedCommands) {
- commandRoot = parsedCommand.command[0];
- var args:Array = processArguments(parsedCommand.command.slice(1));
-
- if (commandModules.exists(commandRoot)) {
- var module:CommandModule = commandModules.get(commandRoot);
- module.execute(this, commandRoot, args, metadata);
- } else {
+ public function runOnce():Array
+ {
+ stdout.writeString(defaultString);
+ stdout.flush();
+ try
+ {
+ var commandLine:String = stdin.readLine();
+ if (commandLine != null && commandLine.length > 0 && commandLine != "")
+ {
+ var parsedCommands:Array = parser.parse(commandLine);
+ for (parsedCommand in parsedCommands)
+ {
+ commandRoot = parsedCommand.command[0];
+ var args:Array = processArguments(parsedCommand.command.slice(1));
+
+ if (commandModules.exists(commandRoot))
+ {
+ var module:CommandModule = commandModules.get(commandRoot);
+ module.execute(this, commandRoot, args, metadata);
+ }
+ else
+ {
#if (fuzzaldrin && WINSL_SUGGEST_COMMAND)
- var candidates = extractCommandNames(commandModules);
+ var candidates = extractCommandNames(commandModules);
var results = Fuzzaldrin.filter(candidates, commandRoot);
if (results.length > 0)
stdout.writeString("Command " + commandRoot + " not found. Did you mean: \"" + results[0] + "\"?\n");
@@ -103,19 +112,22 @@ class Terminal
#else
stdout.writeString("Command " + commandRoot + " not found.\n");
#end
- }
- }
- stdout.flush();
- return parsedCommands;
- }
- else {
- stdout.writeString("");
- }
- } catch (e:Eof) {
- getCrashHandler(e);
- }
- return [];
- }
+ }
+ }
+ stdout.flush();
+ return parsedCommands;
+ }
+ else
+ {
+ stdout.writeString("");
+ }
+ }
+ catch (e:Eof)
+ {
+ getCrashHandler(e);
+ }
+ return [];
+ }
public function run():Void
{
@@ -132,23 +144,29 @@ class Terminal
}
}
- private function processArguments(args:Array):Array {
- return args.map(function(arg:String):String {
- var regExp = ~/^\$\{(.+)\}$/;
- var result:String = arg;
- if (regExp.match(arg)) {
- var varName:String = regExp.replace(arg, "$1");
- var value:Dynamic = getVariable(varName);
- if (value != null) {
- result = value.toString();
- } else {
- result = "NullVar";
- stdout.writeString("\x1b[38;5;235mVariable " + varName + " not found.\x1b[0m\n");
- }
- }
- return result;
- });
- }
+ private function processArguments(args:Array):Array
+ {
+ return args.map(function(arg:String):String
+ {
+ var regExp = ~/^\$\{(.+)\}$/;
+ var result:String = arg;
+ if (regExp.match(arg))
+ {
+ var varName:String = regExp.replace(arg, "$1");
+ var value:Dynamic = getVariable(varName);
+ if (value != null)
+ {
+ result = value.toString();
+ }
+ else
+ {
+ result = "NullVar";
+ stdout.writeString("\x1b[38;5;235mVariable " + varName + " not found.\x1b[0m\n");
+ }
+ }
+ return result;
+ });
+ }
function getCrashHandler(input:Dynamic)
{
@@ -158,7 +176,7 @@ class Terminal
{
WinSLCrashHandler.onVMCrash(input, true);
}
- Sys.println('\n\x1b[38;5;236m-------\x1b[0m\n\x1b[38;5;1mWinSL Critical Error!\x1b[0m\nERROR: $input\n\x1b[38;5;236m-------\x1b[0m\nCall Stack:\n${getSomeInfoOfCrash()}\n\n');
+ Sys.println('\n\x1b[38;5;236m-------\x1b[0m\n\x1b[38;5;1mWinSL Critical Error!\x1b[0m\n\x1b[38;5;1mERROR:\x1b[0m $input\n\nCall Stack:\n${getSomeInfoOfCrash()}\x1b[38;5;236m-------\x1b[0m\n');
}
function getSomeInfoOfCrash():String
@@ -185,14 +203,14 @@ class Terminal
/**
* Internal or default commands for the terminal.
*/
-
class ExitModule
{
public static function execute(terminal:Terminal, commandRoot:String, args:Array, metadata:Dynamic):Void
{
terminal.stdout.writeString("Bye!\n");
Sys.sleep(1.2);
- Sys.exit(0);
+ slushi.winSL.Modules.ModuleUtils.clearConsole();
+ System.exit(0);
}
}
@@ -208,7 +226,7 @@ class StopModule
{
public static function execute(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void
{
- Sys.exit(0);
+ System.exit(0);
}
}
@@ -216,11 +234,12 @@ class SetVariableModule
{
public static function execute(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void
{
- if (args.length != 2 || args[0] == null || args[1] == "") {
- terminal.stdout.writeString("Usage: set \n");
- return;
- }
-
+ if (args.length != 2 || args[0] == null || args[1] == "")
+ {
+ terminal.stdout.writeString("Usage: set \n");
+ return;
+ }
+
terminal.setVariable(args[0], args[1]);
}
}
@@ -233,12 +252,13 @@ class GetVariableModule
}
}
-class ResetVMModule {
- public static function execute(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void {
-
- terminal.stdout.writeString("Resetting VM and exiting of WinSL terminal...\n");
- Sys.sleep(2);
+class ResetVMModule
+{
+ public static function execute(terminal:Terminal, command:String, args:Array, metadata:Dynamic):Void
+ {
+ terminal.stdout.writeString("Resetting VM and exiting of WinSL terminal...\n");
+ Sys.sleep(2);
CustomFuncs.realResetGame();
- Sys.exit(0);
- }
-}
\ No newline at end of file
+ System.exit(0);
+ }
+}
diff --git a/funkinscsource/slushi/windowThings/WindowFuncs.hx b/funkinscsource/slushi/windowThings/WindowFuncs.hx
index 72f2545..4534ede 100644
--- a/funkinscsource/slushi/windowThings/WindowFuncs.hx
+++ b/funkinscsource/slushi/windowThings/WindowFuncs.hx
@@ -115,6 +115,12 @@ class WindowFuncs
#end
}
+ public static function centerWindow()
+ {
+ setWinPositionInX(Std.int((getScreenSizeInWidth() - getWindowSizeInWidth()) / 2));
+ setWinPositionInY(Std.int((getScreenSizeInHeight() - getWindowSizeInHeight()) / 2));
+ }
+
public static function doTweenWindowAlpha(toValue:Float, duration:Float, ease:String = "linear")
{
#if windows
@@ -145,6 +151,17 @@ class WindowFuncs
}
}
+ // public static function doubleWindowTweenX(offset:Float, duration:Float, ease:String):Void
+ // {
+ // var startX:Int = getWindowPositionInX();
+
+ // var numTween:NumTween = FlxTween.num(startX + offset, startX, duration, {ease: psychlua.LuaUtils.getTweenEaseByString(ease)});
+ // numTween.onUpdate = function(twn:FlxTween)
+ // {
+ // Application.current.window.x -= Std.int(numTween.value);
+ // }
+ // }
+
public static function resetWindowParameters()
{
#if windows
@@ -153,12 +170,7 @@ class WindowFuncs
if (!Application.current.window.maximized || !Application.current.window.fullscreen)
{
- #if windows
- CppAPI.centerWindow();
- #else
- setWinPositionInX(Std.int((getScreenSizeInWidth() - getWindowSizeInWidth()) / 2));
- setWinPositionInY(Std.int((getScreenSizeInHeight() - getWindowSizeInHeight()) / 2));
- #end
+ centerWindow();
}
if (!Application.current.window.resizable)
diff --git a/funkinscsource/slushi/windows/CppAPI.hx b/funkinscsource/slushi/windows/CppAPI.hx
index e7646fe..8a21052 100644
--- a/funkinscsource/slushi/windows/CppAPI.hx
+++ b/funkinscsource/slushi/windows/CppAPI.hx
@@ -6,15 +6,9 @@ package slushi.windows;
*
* Author: Slushi
*/
-
class CppAPI
{
#if (windows && cpp)
- public static function screenCapture(path:String)
- {
- WindowsCPP.windowsScreenShot(path);
- }
-
public static function showMessageBox(message:String, caption:String, icon:MessageBoxIcon = MSG_WARNING)
{
WindowsCPP.showMessageBox(caption, message, icon);
@@ -50,11 +44,6 @@ class CppAPI
WindowsCPP._setWindowLayered();
}
- public static function centerWindow()
- {
- WindowsCPP.centerWindow();
- }
-
public static function setSlushiColorToWindow()
{
return WindowsCPP.setSlushiWindowColor();
@@ -66,6 +55,11 @@ class CppAPI
}
#if SLUSHI_CPP_CODE
+ public static function screenCapture(path:String)
+ {
+ WindowsCPP.windowsScreenShot(path);
+ }
+
public static function hideTaskbar(hide:Bool)
{
WindowsCPP.hideTaskbar(hide);
diff --git a/funkinscsource/slushi/windows/ProgramRespondingUtil.hx b/funkinscsource/slushi/windows/ProgramRespondingUtil.hx
deleted file mode 100644
index adec8e1..0000000
--- a/funkinscsource/slushi/windows/ProgramRespondingUtil.hx
+++ /dev/null
@@ -1,60 +0,0 @@
-package slushi.windows;
-
-#if windows
-@:cppFileCode('
-#include
-#include
-#include
-#include
-#include
-
-#define TIMEOUT 5000
-
-bool IsWindowResponsive(HWND hwnd, DWORD timeoutMs) {
- LRESULT result = SendMessageTimeout(
- hwnd,
- WM_NULL,
- 0, 0,
- SMTO_ABORTIFHUNG,
- timeoutMs,
- nullptr
- );
-
- return (result != 0);
-}
-
-void CheckIfWindowResponsive(HWND hwnd) {
- while (true) {
- std::this_thread::sleep_for(std::chrono::seconds(10));
-
- if (!IsWindowResponsive(hwnd, TIMEOUT)) {
- std::cout << "[C++ Function - CheckIfWindowResponsive] The engine window is not responding!" << std::endl;
- int response = MessageBox(hwnd,
- "The engine window is not responding. Do you want to close it?",
- "Slushi Engine [C++] - Info",
- MB_ICONINFORMATION | MB_YESNO);
-
- if (response == IDNO) {
- PostMessage(hwnd, WM_CLOSE, 0, 0);
- break;
- }
- }
- }
-}
-')
-#end
-class ProgramRespondingUtil
-{
- #if windows
- @:functionCode('
- HWND hwnd = GetActiveWindow();
-
- // Crear un hilo separado para monitorear la ventana ya existente
- std::thread monitorThread(CheckIfWindowResponsive, hwnd);
- monitorThread.detach(); // Ejecutar en segundo plano
- ')
- public static function initThread()
- {
- }
- #end
-}
diff --git a/funkinscsource/slushi/windows/WindowsCPP.hx b/funkinscsource/slushi/windows/WindowsCPP.hx
index ae840b3..debc2fe 100644
--- a/funkinscsource/slushi/windows/WindowsCPP.hx
+++ b/funkinscsource/slushi/windows/WindowsCPP.hx
@@ -9,6 +9,7 @@ package slushi.windows;
* Author: Slushi
*/
// Windows API for Haxe v1.0.0
+
@:buildXml('
@@ -170,6 +171,21 @@ int screenCapture(int x, int y, int w, int h, LPCSTR fname)
class WindowsCPP
{
#if windows
+ @:functionCode('
+ HMODULE ntdll = GetModuleHandleA("ntdll.dll");
+ if (ntdll) {
+ void* wine_get_version = GetProcAddress(ntdll, "wine_get_version");
+ if (wine_get_version) {
+ return true;
+ }
+ }
+ return false;
+ ')
+ public static function detectWine():Bool
+ {
+ return false;
+ }
+
@:functionCode('
MessageBox(GET_ENGINE_WINDOW(), message, caption, icon | MB_SETFOREGROUND);
')
@@ -177,6 +193,14 @@ class WindowsCPP
{
}
+ @:functionCode('
+ // Play a Beep sound, in the computer default sound device (not the motherboard speaker), with the given frequency and duration
+ Beep(freq, duration);
+ ')
+ public static function beep(freq:Int, duration:Int)
+ {
+ }
+
@:functionCode('
globalWindowTitle = windowTitle;
')
@@ -261,9 +285,37 @@ class WindowsCPP
{
}
+ // @:functionCode('
+ // HWND window = GET_ENGINE_WINDOW();
+
+ // COLORREF color = 0;
+
+ // // Obtener el color del borde de la ventana (atributo 34)
+ // if (S_OK == DwmGetWindowAttribute(window, 34, &color, sizeof(COLORREF))) {
+ // std::vector rgb;
+ // rgb.emplace_back(GetRValue(color)); // Red
+ // rgb.emplace_back(GetGValue(color)); // Green
+ // rgb.emplace_back(GetBValue(color)); // Blue
+
+ // Array_obj* hxRGB = new Array_obj(rgb.size(), rgb.size());
+ // for (int i = 0; i < rgb.size(); i++) {
+ // hxRGB->Item(i) = rgb[i];
+ // }
+ // return hxRGB;
+ // } else {
+ // // Devolver un array vacío si falla
+ // std::cerr << "[C++ Function - getWindowBorderColor] Error getting window border color. Error code: " << GetLastError() << std::endl;
+ // return new Array_obj(0, 0);
+ // }
+ // ')
+ // public static function getWindowBorderColor():Array
+ // {
+ // return [];
+ // }
+
@:functionCode('
- HWND window = GET_ENGINE_WINDOW();
- SetWindowLong(window, GWL_EXSTYLE, GetWindowLong(window, GWL_EXSTYLE) ^ WS_EX_LAYERED);
+ HWND window = GET_ENGINE_WINDOW();
+ SetWindowLong(window, GWL_EXSTYLE, GetWindowLong(window, GWL_EXSTYLE) ^ WS_EX_LAYERED);
')
public static function _setWindowLayered()
{
@@ -308,48 +360,6 @@ class WindowsCPP
return 0;
}
- @:functionCode('
- HWND hwnd = GET_ENGINE_WINDOW();
- int screenWidth = GetSystemMetrics(SM_CXSCREEN);
- int screenHeight = GetSystemMetrics(SM_CYSCREEN);
-
- RECT windowRect;
- GetWindowRect(hwnd, &windowRect);
- int windowWidth = windowRect.right - windowRect.left;
- int windowHeight = windowRect.bottom - windowRect.top;
-
- int centerX = (screenWidth - windowWidth) / 2;
- int centerY = (screenHeight - windowHeight) / 2;
-
- SetWindowPos(hwnd, NULL, centerX, centerY, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
- ')
- @:noCompletion
- public static function centerWindow()
- {
- }
-
- @:functionCode('
- POINT MousePoint;
- GetCursorPos(&MousePoint);
-
- return MousePoint.x;
- ')
- static public function getCursorPositionX()
- {
- return 0;
- }
-
- @:functionCode('
- POINT MousePoint;
- GetCursorPos(&MousePoint);
-
- return MousePoint.y;
- ')
- static public function getCursorPositionY()
- {
- return 0;
- }
-
@:functionCode('
BOOL isAdmin = FALSE;
SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
@@ -374,6 +384,7 @@ class WindowsCPP
}
// thx Trock for this
+
@:functionCode('
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
@@ -549,25 +560,25 @@ class WindowsCPP
}
@:functionCode('
- HWND window;
- HWND window2;
-
- switch (numberMode) {
- case 0:
- window = FindWindowW(L"Progman", L"Program Manager");
- window = GetWindow(window, GW_CHILD);
- case 1:
- window = FindWindowA("Shell_traywnd", nullptr);
- window2 = FindWindowA("Shell_SecondaryTrayWnd", nullptr);
- }
+ HWND window;
+ HWND window2;
+
+ switch (numberMode) {
+ case 0:
+ window = FindWindowW(L"Progman", L"Program Manager");
+ window = GetWindow(window, GW_CHILD);
+ case 1:
+ window = FindWindowA("Shell_traywnd", nullptr);
+ window2 = FindWindowA("Shell_SecondaryTrayWnd", nullptr);
+ }
- if (numberMode != 1) {
- SetWindowLong(window, GWL_EXSTYLE, GetWindowLong(window, GWL_EXSTYLE) ^ WS_EX_LAYERED);
- }
- else {
- SetWindowLong(window, GWL_EXSTYLE, GetWindowLong(window, GWL_EXSTYLE) ^ WS_EX_LAYERED);
- SetWindowLong(window2, GWL_EXSTYLE, GetWindowLong(window2, GWL_EXSTYLE) ^ WS_EX_LAYERED);
- }
+ if (numberMode != 1) {
+ SetWindowLong(window, GWL_EXSTYLE, GetWindowLong(window, GWL_EXSTYLE) ^ WS_EX_LAYERED);
+ }
+ else {
+ SetWindowLong(window, GWL_EXSTYLE, GetWindowLong(window, GWL_EXSTYLE) ^ WS_EX_LAYERED);
+ SetWindowLong(window2, GWL_EXSTYLE, GetWindowLong(window2, GWL_EXSTYLE) ^ WS_EX_LAYERED);
+ }
')
public static function _setWindowLayeredMode(numberMode:Int)
{
diff --git a/funkinscsource/slushi/windows/WindowsFuncs.hx b/funkinscsource/slushi/windows/WindowsFuncs.hx
index ab42412..17e365a 100644
--- a/funkinscsource/slushi/windows/WindowsFuncs.hx
+++ b/funkinscsource/slushi/windows/WindowsFuncs.hx
@@ -1,10 +1,9 @@
package slushi.windows;
-import sys.io.Process;
+import slushi.others.systemUtils.HiddenProcess;
import sys.io.File;
import lime.system.System;
import psychlua.LuaUtils;
-import slushi.windows.ProgramRespondingUtil;
/*
* This file is one that facilitates the use of Windows functions that come from WindowsCPP.hx within SLE.
@@ -17,13 +16,14 @@ class WindowsFuncs
private static var _windowsWallpaperPath:String = null;
public static var changedWallpaper:Bool = false;
- private static final savedWallpaperPath:String = "assets/slushiEngineAssets/SLEAssets/OthersAssets/Cache/savedWindowswallpaper.png";
+ private static final savedWallpaperPath:String = "assets/slushiEngineAssets/OthersAssets/Cache/savedWindowswallpaper.png";
+
+ private static var windowBorderColorTween:NumTween;
public static function changeWindowsWallpaper(path:String)
{
#if windows
- var allPath:String = CustomFuncs.getAllPath() + 'assets/' + path;
- allPath = allPath.split("\\").join("/");
+ var allPath:String = CustomFuncs.getProgramPath() + 'assets/' + path;
CppAPI.setWallpaper(allPath);
changedWallpaper = true;
Debug.logSLEInfo("Wallpaper changed to: " + allPath);
@@ -33,8 +33,7 @@ class WindowsFuncs
public static function screenCapture(path:String)
{
#if windows
- var allPath:String = CustomFuncs.getAllPath() + 'assets/images/SLEAssets/Cache/' + path;
- allPath = allPath.split("\\").join("/");
+ var allPath:String = CustomFuncs.getProgramPath() + 'assets/slushiEngineAssets/OthersAssets/Cache/' + path;
CppAPI.screenCapture(allPath);
Debug.logSLEInfo("Screenshot saved to: " + allPath);
#end
@@ -64,10 +63,8 @@ class WindowsFuncs
var finalPath = savedWallpaperPath;
try
{
- if (!FileSystem.exists('assets/slushiEngineAssets/SLEAssets/OthersAssets/Cache'))
- FileSystem.createDirectory('assets/slushiEngineAssets/SLEAssets/OthersAssets/Cache');
-
File.copy(_windowsWallpaperPath, finalPath);
+ Debug.logSLEInfo("Saved a copy of the wallpaper");
}
catch (e)
{
@@ -79,7 +76,7 @@ class WindowsFuncs
public static function setOldWindowsWallpaper()
{
#if windows
- if (changedWallpaper == false)
+ if (!changedWallpaper)
return;
changedWallpaper = false;
@@ -120,7 +117,7 @@ class WindowsFuncs
+ "$notifier.Show($toast);}\"";
if (title != null && title != "" && desc != null && desc != "" && getWindowsVersion() != 7)
- new Process(powershellCommand);
+ new HiddenProcess(powershellCommand);
#end
}
@@ -191,23 +188,85 @@ class WindowsFuncs
#end
}
- public static function getCursorPos():{x:Int, y:Int}
+ public static function setWindowBorderColorFromInt(color:Int):Void
{
- var mousePos = {x: 0, y: 0};
#if windows
- mousePos = {x: WindowsCPP.getCursorPositionX(), y: WindowsCPP.getCursorPositionY()};
+ if (getWindowsVersion() != 11)
+ return;
+
+ var red:Int = (color >> 16) & 0xFF;
+ var green:Int = (color >> 8) & 0xFF;
+ var blue:Int = color & 0xFF;
+ var rgb:Array = [red, green, blue];
+ WindowsFuncs.setWindowBorderColor(rgb);
#end
- return mousePos;
}
- public static function initThreadForWindowRespondingHandler()
+ public static function tweenWindowBorderColor(fromColor:Array, toColor:Array, duration:Float, ease:String):Void
{
#if windows
- Sys.println("[slushi.windows.WindowsFuncs.initThreadForWindowRespondingHandler] - Starting thread for window responding handler...");
- ProgramRespondingUtil.initThread();
+ if (getWindowsVersion() != 11)
+ return;
+
+ windowBorderColorTween = FlxTween.num(0, 1, duration, {
+ ease: LuaUtils.getTweenEaseByString(ease)
+ });
+
+ var startColor:Array = fromColor;
+ var targetColor:Array = toColor;
+
+ windowBorderColorTween.onUpdate = function(tween:FlxTween)
+ {
+ var interpolatedColor:Array = [];
+ for (i in 0...3)
+ {
+ var newValue:Int = startColor[i] + Std.int((targetColor[i] - startColor[i]) * windowBorderColorTween.value);
+ newValue = Std.int(Math.max(0, Math.min(255, newValue)));
+ interpolatedColor.push(newValue);
+ }
+ WindowsFuncs.setWindowBorderColor(interpolatedColor);
+ };
#end
}
+ // public static function tweenWindowBorderColorFromActualColor(toColor:Array, duration:Float, ease:String):Void
+ // {
+ // #if windows
+ // if (getWindowsVersion() != 11)
+ // return;
+
+ // var fromColor:Array = WindowsCPP.getWindowBorderColor();
+
+ // windowBorderColorTween = FlxTween.num(0, 1, duration, {
+ // ease: LuaUtils.getTweenEaseByString(ease)
+ // });
+
+ // var startColor:Array = fromColor;
+ // var targetColor:Array = toColor;
+
+ // windowBorderColorTween.onUpdate = function(tween:FlxTween)
+ // {
+ // var interpolatedColor:Array = [];
+ // for (i in 0...3)
+ // {
+ // var newValue:Int = startColor[i] + Std.int((targetColor[i] - startColor[i]) * windowBorderColorTween.value);
+ // newValue = Std.int(Math.max(0, Math.min(255, newValue)));
+ // interpolatedColor.push(newValue);
+ // }
+ // WindowsFuncs.setWindowBorderColor(interpolatedColor);
+ // };
+ // #end
+ // }
+
+ public static function cancelWindowBorderColorTween():Void
+ {
+ if (windowBorderColorTween != null)
+ {
+ windowBorderColorTween.cancel();
+ windowBorderColorTween = null;
+ }
+ }
+
//////////////////////////////////////////////////////////////////////////////////////////
#if windows
public static function doTweenDesktopWindows(mode:String, toValue:Float, duration:Float, ease:String)
@@ -250,26 +309,3 @@ class WindowsFuncs
}
#end
}
-
-class DeprecatedFuncs
-{
- #if windows
- public static function doTweenDesktopWindowsInX(fromValue:Float, toValue:Float, duration:Float, ease:String = "linear")
- {
- var numTween:NumTween = FlxTween.num(fromValue, toValue, duration, {ease: LuaUtils.getTweenEaseByString(ease)});
- numTween.onUpdate = function(twn:FlxTween)
- {
- CppAPI.moveDesktopWindowsInX(Std.int(numTween.value));
- }
- }
-
- public static function doTweenDesktopWindowsInY(fromValue:Float, toValue:Float, duration:Float, ease:String = "linear")
- {
- var numTween:NumTween = FlxTween.num(fromValue, toValue, duration, {ease: LuaUtils.getTweenEaseByString(ease)});
- numTween.onUpdate = function(twn:FlxTween)
- {
- CppAPI.moveDesktopWindowsInY(Std.int(numTween.value));
- }
- }
- #end
-}
diff --git a/funkinscsource/slushi/windows/WindowsGDIEffects.hx b/funkinscsource/slushi/windows/WindowsGDIEffects.hx
deleted file mode 100644
index dc0d122..0000000
--- a/funkinscsource/slushi/windows/WindowsGDIEffects.hx
+++ /dev/null
@@ -1,281 +0,0 @@
-package slushi.windows;
-
-/**
- * This file has the functions related to the Windows GDI, there are MENZ virus GDI effects.
- *
- * Author: Slushi
- */
-
-#if windows
-@:cppFileCode('
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-
-#define UNICODE
-
-#pragma comment(lib, "Dwmapi")
-#pragma comment(lib, "ntdll.lib")
-#pragma comment(lib, "User32.lib")
-#pragma comment(lib, "Shell32.lib")
-#pragma comment(lib, "gdi32.lib")
-
-/////////////////////////////////////////////////////////////////////////////
-
-#define elapsedTime 0
-
-int payloadDrawErrors(BOOLEAN mode) {
- if (mode) {
- int ix = GetSystemMetrics(SM_CXICON) / 2;
- int iy = GetSystemMetrics(SM_CYICON) / 2;
-
- HWND hwnd = GetDesktopWindow();
- HDC hdc = GetWindowDC(hwnd);
-
- POINT cursor;
- GetCursorPos(&cursor);
-
- DrawIcon(hdc, cursor.x - ix, cursor.y - iy, LoadIcon(NULL, IDI_ERROR));
-
- if (rand() % (int)(10/(elapsedTime/500.0+1)+1) == 0) {
- DrawIcon(hdc, rand()%GetSystemMetrics(SM_CXSCREEN), rand()%GetSystemMetrics(SM_CYSCREEN), LoadIcon(NULL, IDI_WARNING));
- }
-
- ReleaseDC(hwnd, hdc);
-
- out: return 2;
- }
-}
-
-int payloadBlink(BOOLEAN mode) {
- if (mode) {
- HWND hwnd = GetDesktopWindow();
- HDC hdc = GetWindowDC(hwnd);
- RECT rekt;
- GetWindowRect(hwnd, &rekt);
- BitBlt(hdc, 0, 0, rekt.right - rekt.left, rekt.bottom - rekt.top, hdc, 0, 0, NOTSRCCOPY);
- ReleaseDC(hwnd, hdc);
-
- out: return 100;
- }
-}
-
-int payloadGlitchs(BOOLEAN mode) {
- if (mode) {
- HWND hwnd = GetDesktopWindow();
- HDC hdc = GetWindowDC(hwnd);
- RECT rekt;
- GetWindowRect(hwnd, &rekt);
-
- int x1 = rand() % (rekt.right - 100);
- int y1 = rand() % (rekt.bottom - 100);
- int x2 = rand() % (rekt.right - 100);
- int y2 = rand() % (rekt.bottom - 100);
- int width = rand() % 600;
- int height = rand() % 600;
-
- BitBlt(hdc, x1, y1, width, height, hdc, x2, y2, SRCCOPY);
- ReleaseDC(hwnd, hdc);
-
- out: return 200.0 / (elapsedTime / 5.0 + 1) + 3;
- }
-}
-
-int payloadTunnel(BOOLEAN mode) {
- if (mode) {
- HWND hwnd = GetDesktopWindow();
- HDC hdc = GetWindowDC(hwnd);
- RECT rekt;
- GetWindowRect(hwnd, &rekt);
- StretchBlt(hdc, 50, 50, rekt.right - 100, rekt.bottom - 100, hdc, 0, 0, rekt.right, rekt.bottom, SRCCOPY);
- ReleaseDC(hwnd, hdc);
-
- out: return 200.0 / (elapsedTime / 5.0 + 1) + 4;
- }
-}
-
-int payloadScreenShake(BOOLEAN mode) {
- if (mode) {
- HDC hdc = GetDC(0);
- int x = SM_CXSCREEN;
- int y = SM_CYSCREEN;
- int w = GetSystemMetrics(0);
- int h = GetSystemMetrics(1);
- BitBlt(hdc, rand() % 2, rand() % 2, w, h, hdc, rand() % 2, rand() % 2, SRCCOPY);
- Sleep(10);
- ReleaseDC(0, hdc);
- }
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {
-
- LPWSTR newText = (LPWSTR)lParam;
-
- SendMessageTimeoutW(hwnd, WM_SETTEXT, NULL, (LPARAM)newText, SMTO_ABORTIFHUNG, 0, NULL);
-
- return TRUE;
-}
-
-')
-#end
-class WindowsGDIEffects
-{
- #if windows
- @:functionCode('
- payloadDrawErrors(mode);
- ')
- public static function _drawIcons(mode:Bool) {}
-
- @:functionCode('
- payloadBlink(mode);
- ')
- public static function _screenBlink(mode:Bool) {}
-
- @:functionCode('
- payloadGlitchs(mode);
- ')
- public static function _payloadGlitchs(mode:Bool) {}
-
- @:functionCode('
- payloadTunnel(mode);
- ')
- public static function _payloadTunnel(mode:Bool) {}
-
- @:functionCode('
- payloadScreenShake(mode);
- ')
- public static function _payloadScreenShake(mode:Bool) {}
-
- @:functionCode('
- std::string s = text;
- std::wstring_convert> converter;
- std::wstring wide = converter.from_bytes(s);
-
- LPCWSTR result = wide.c_str();
-
- EnumChildWindows(GetDesktopWindow(), EnumChildProc, (LPARAM)result);
- ')
- public static function _setCustomTitleTextToWindows(text:String = "...") {}
- #end
-
- /////////////////////////////////////////////////////////////////////////////
-
- static var gdiEffects:Array = [
- "drawIcons", "screenBlink", "screenGlitches", "screenTunnel"
- ];
-
- static var invalidGDIEffects:Array = [
- "SetTitleTextToWindows"
- ];
-
- public static var slushi_WinGDIEffect:Map = [];
-
- public static function checkEffect(tag:String = "", gdiEffect:String, ?initalValue:Dynamic = true) {
- #if windows
- if(invalidGDIEffects.contains(gdiEffect))
- return printInDisplay('WindowsGDIEffects/checkEffect: [${gdiEffect}] is not supported for this function!', FlxColor.RED);
-
- var effectClass = Type.resolveClass('slushi.windows.WinGDI_' + gdiEffect);
- if (effectClass != null)
- {
- var initEffect = Type.createInstance(effectClass, []);
- slushi_WinGDIEffect.set(tag, initEffect);
- Debug.logSLEInfo('created [${gdiEffect}] GDI effect from class [WinGDI_${gdiEffect}]');
- }
- else{
- Debug.logSLEError('[WinGDI_${gdiEffect}] not found!');
- printInDisplay('WindowsGDIEffects/checkEffect: [${gdiEffect}] not found!', FlxColor.RED);
- }
- #end
- }
-
- public static function setWinEffectProperty(tag:String, prop:String, ?initalValue:Dynamic = true) {
- #if windows
- var effect = slushi_WinGDIEffect.get(tag);
-
- if(effect != null){
- Reflect.setProperty(effect, prop, initalValue);
- }
- else{
- Debug.logSLEWarn('Uknown tag [${tag}]');
- printInDisplay('WindowsGDIEffects/setWinEffectProperty: [${tag}] not found', FlxColor.WHITE);
- }
- #end
- }
-}
-
-class SlushiWindowsEffects
-{
- public var activeGDIEffect:Bool = true;
- public var effectSpeed:Float = 1.0;
-
- public var aditionalValue:Dynamic;
-
- // thx TheoDevelop
- var progress:Float;
- var defaultTime:Float = 1;
-
- // ANTI CRASH !!!!!!!!!!!!!!!!!!!!!!!!
- final antiCrash = (num) -> return Math.min(0.00001, num);
- var reset:Null;
-
- public function update(elapsed:Float){
- progress += elapsed;
-
- reset = (antiCrash(defaultTime) / antiCrash(effectSpeed));
- }
-}
-
-#if windows
-class WinGDI_ScreenBlink extends SlushiWindowsEffects
-{
- override public function update(elapsed:Float):Void
- {
- if (activeGDIEffect)
- {
- if(progress >= reset)
- {
- WindowsGDIEffects._screenBlink(activeGDIEffect);
- progress = 0;
- }
- }
- super.update(elapsed);
- }
-}
-
-class WinGDI_SetTitleTextToWindows extends SlushiWindowsEffects
-{
- public var titleText:String = "Null";
-
- public function new()
- {
- WindowsGDIEffects._setCustomTitleTextToWindows(titleText);
- }
-}
-
-class WinGDI_ScreenShake extends SlushiWindowsEffects
-{
- override public function update(elapsed:Float):Void
- {
- if(activeGDIEffect)
- WindowsGDIEffects._payloadScreenShake(activeGDIEffect);
- }
-}
-#end
\ No newline at end of file
diff --git a/funkinscsource/slushi/windows/WinConsoleUtils.hx b/funkinscsource/slushi/windows/WindowsTerminalCPP.hx
similarity index 99%
rename from funkinscsource/slushi/windows/WinConsoleUtils.hx
rename to funkinscsource/slushi/windows/WindowsTerminalCPP.hx
index faae31b..689ac21 100644
--- a/funkinscsource/slushi/windows/WinConsoleUtils.hx
+++ b/funkinscsource/slushi/windows/WindowsTerminalCPP.hx
@@ -30,7 +30,7 @@ package slushi.windows;
#pragma comment(lib, "gdi32.lib")
')
#end
-class WinConsoleUtils
+class WindowsTerminalCPP
{
#if windows
@:functionCode('
diff --git a/funkinscsource/slushi/windows/winGDIThings/SlushiWinGDI.hx b/funkinscsource/slushi/windows/winGDIThings/SlushiWinGDI.hx
new file mode 100644
index 0000000..1f0fd89
--- /dev/null
+++ b/funkinscsource/slushi/windows/winGDIThings/SlushiWinGDI.hx
@@ -0,0 +1,315 @@
+package slushi.windows.winGDIThings;
+
+/*
+ * This is the main class of the Windows GDI effects in SLE, it has the C++ code of the effects,
+ * and there are functions to prepare, start and remove an added effect
+ * (some of the GDI effect code is taken from the MENZ malware source code)
+ *
+ * Author: Slushi
+ */
+#if windows
+@:cppFileCode('
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#define UNICODE
+
+#pragma comment(lib, "Dwmapi")
+#pragma comment(lib, "ntdll.lib")
+#pragma comment(lib, "User32.lib")
+#pragma comment(lib, "Shell32.lib")
+#pragma comment(lib, "gdi32.lib")
+
+/////////////////////////////////////////////////////////////////////////////
+
+static float elapsedTime = 0;
+
+int payloadDrawErrors() {
+ int ix = GetSystemMetrics(SM_CXICON) / 2;
+ int iy = GetSystemMetrics(SM_CYICON) / 2;
+
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+
+ POINT cursor;
+ GetCursorPos(&cursor);
+
+ DrawIcon(hdc, cursor.x - ix, cursor.y - iy, LoadIcon(NULL, IDI_ERROR));
+
+ if (rand() % (int)(10/(elapsedTime/500.0+1)+1) == 0) {
+ DrawIcon(hdc, rand()%GetSystemMetrics(SM_CXSCREEN), rand()%GetSystemMetrics(SM_CYSCREEN), LoadIcon(NULL, IDI_WARNING));
+ }
+
+ ReleaseDC(hwnd, hdc);
+
+ out: return 2;
+}
+
+int payloadBlink() {
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+ RECT rekt;
+ GetWindowRect(hwnd, &rekt);
+ BitBlt(hdc, 0, 0, rekt.right - rekt.left, rekt.bottom - rekt.top, hdc, 0, 0, NOTSRCCOPY);
+ ReleaseDC(hwnd, hdc);
+
+ out: return 100;
+}
+
+int payloadGlitchs() {
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+ RECT rekt;
+ GetWindowRect(hwnd, &rekt);
+
+ int x1 = rand() % (rekt.right - 100);
+ int y1 = rand() % (rekt.bottom - 100);
+ int x2 = rand() % (rekt.right - 100);
+ int y2 = rand() % (rekt.bottom - 100);
+ int width = rand() % 600;
+ int height = rand() % 600;
+
+ BitBlt(hdc, x1, y1, width, height, hdc, x2, y2, SRCCOPY);
+ ReleaseDC(hwnd, hdc);
+
+ out: return 200.0 / (elapsedTime / 5.0 + 1) + 3;
+}
+
+int payloadTunnel() {
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+ RECT rekt;
+ GetWindowRect(hwnd, &rekt);
+ StretchBlt(hdc, 50, 50, rekt.right - 100, rekt.bottom - 100, hdc, 0, 0, rekt.right, rekt.bottom, SRCCOPY);
+ ReleaseDC(hwnd, hdc);
+
+ out: return 200.0 / (elapsedTime / 5.0 + 1) + 4;
+}
+
+int payloadScreenShake() {
+ HDC hdc = GetDC(0);
+ int x = SM_CXSCREEN;
+ int y = SM_CYSCREEN;
+ int w = GetSystemMetrics(0);
+ int h = GetSystemMetrics(1);
+ BitBlt(hdc, rand() % 2, rand() % 2, w, h, hdc, rand() % 2, rand() % 2, SRCCOPY);
+ Sleep(10);
+ ReleaseDC(0, hdc);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {
+
+ LPWSTR newText = (LPWSTR)lParam;
+
+ SendMessageTimeoutW(hwnd, WM_SETTEXT, NULL, (LPARAM)newText, SMTO_ABORTIFHUNG, 0, NULL);
+
+ return TRUE;
+}
+
+')
+#end
+class SlushiWinGDI
+{
+ #if windows
+ @:functionCode('
+ elapsedTime = elapsed;
+ ')
+ public static function setElapsedTime(elapsed:Float)
+ {
+ }
+
+ @:functionCode('
+ payloadDrawErrors();
+ ')
+ public static function _drawIcons()
+ {
+ }
+
+ @:functionCode('
+ payloadBlink();
+ ')
+ public static function _screenBlink()
+ {
+ }
+
+ @:functionCode('
+ payloadGlitchs();
+ ')
+ public static function _screenGlitches()
+ {
+ }
+
+ @:functionCode('
+ payloadTunnel();
+ ')
+ public static function _screenTunnel()
+ {
+ }
+
+ @:functionCode('
+ payloadScreenShake();
+ ')
+ public static function _screenShake()
+ {
+ }
+
+ @:functionCode('
+ std::string s = text;
+ std::wstring_convert> converter;
+ std::wstring wide = converter.from_bytes(s);
+
+ LPCWSTR result = wide.c_str();
+
+ EnumChildWindows(GetDesktopWindow(), EnumChildProc, (LPARAM)result);
+ ')
+ public static function _setCustomTitleTextToWindows(text:String = "...")
+ {
+ }
+ #end
+
+ /////////////////////////////////////////////////////////////////////////////
+ public static function prepareGDIEffect(effect:String, wait:Float = 0)
+ {
+ #if windows
+ var effectClass = Type.resolveClass('slushi.windows.winGDIThings.SLWinEffect_' + effect);
+ if (effectClass != null)
+ {
+ var initEffect = Type.createInstance(effectClass, []);
+ WinGDIThread.gdiEffects.set(effect, new SlushiWinGDIEffectData(initEffect, wait, false));
+ Debug.logSLEInfo('created [${effect}] GDI effect from class [SLWinEffect_${effect}]');
+ }
+ else
+ {
+ Debug.logSLEError('[SLWinEffect_${effect}] not found!');
+ printInDisplay('SlushiWinGDI/prepareGDIEffect: [${effect}] not found!', FlxColor.RED);
+ }
+ #end
+ }
+
+ public static function setGDIEffectWaitTime(effect:String, wait:Float)
+ {
+ #if windows
+ var gdi = WinGDIThread.gdiEffects.get(effect);
+ if (gdi != null)
+ {
+ gdi.wait = wait;
+ }
+ else
+ {
+ Debug.logSLEError('[SLWinEffect_${effect}] not found!');
+ printInDisplay('SlushiWinGDI/setGDIEFfectProperty: [${effect}] not found!', FlxColor.RED);
+ }
+ #end
+ }
+
+ public static function removeGDIEffect(effect:String)
+ {
+ #if windows
+ var gdi = WinGDIThread.gdiEffects.get(effect);
+ if (gdi != null)
+ {
+ WinGDIThread.gdiEffects.remove(effect);
+ }
+ else
+ {
+ Debug.logSLEError('[SLWinEffect_${effect}] not found!');
+ printInDisplay('SlushiWinGDI/removeGDIEffect: [${effect}] not found!', FlxColor.RED);
+ }
+ #end
+ }
+
+ public static function enableGDIEffect(effect:String, enabled:Bool = true)
+ {
+ #if windows
+ var gdi = WinGDIThread.gdiEffects.get(effect);
+ if (gdi != null)
+ {
+ gdi.enabled = enabled;
+ }
+ else
+ {
+ Debug.logSLEError('[SLWinEffect_${effect}] not found!');
+ printInDisplay('SlushiWinGDI/enableGDIEffect: [${effect}] not found!', FlxColor.RED);
+ }
+ #end
+ }
+}
+
+class SlushiWinGDIEffect
+{
+ #if windows
+ public function update()
+ {
+ }
+ #end
+}
+
+#if windows
+class SLWinEffect_DrawIcons extends SlushiWinGDIEffect
+{
+ override public function update()
+ {
+ SlushiWinGDI._drawIcons();
+ }
+}
+
+class SLWinEffect_ScreenBlink extends SlushiWinGDIEffect
+{
+ override public function update()
+ {
+ SlushiWinGDI._screenBlink();
+ }
+}
+
+class SLWinEffect_ScreenGlitches extends SlushiWinGDIEffect
+{
+ override public function update()
+ {
+ SlushiWinGDI._screenGlitches();
+ }
+}
+
+class SLWinEffect_ScreenShake extends SlushiWinGDIEffect
+{
+ override public function update()
+ {
+ SlushiWinGDI._screenShake();
+ }
+}
+
+class SLWinEffect_ScreenTunnel extends SlushiWinGDIEffect
+{
+ override public function update()
+ {
+ SlushiWinGDI._screenTunnel();
+ }
+}
+
+class SLWinEffect_SetTitleTextToWindows extends SlushiWinGDIEffect
+{
+ public var text:String = "";
+
+ override public function update()
+ {
+ SlushiWinGDI._setCustomTitleTextToWindows(text);
+ }
+}
+#end
diff --git a/funkinscsource/slushi/windows/winGDIThings/SlushiWinGDIEffectData.hx b/funkinscsource/slushi/windows/winGDIThings/SlushiWinGDIEffectData.hx
new file mode 100644
index 0000000..b140ca2
--- /dev/null
+++ b/funkinscsource/slushi/windows/winGDIThings/SlushiWinGDIEffectData.hx
@@ -0,0 +1,22 @@
+package slushi.windows.winGDIThings;
+
+import slushi.windows.winGDIThings.SlushiWinGDI.SlushiWinGDIEffect;
+
+/*
+ * This is a simple class that contains data from the GDI effect before it is started
+ *
+ * Author: Slushi
+ */
+class SlushiWinGDIEffectData
+{
+ public var gdiEffect:SlushiWinGDIEffect;
+ public var wait:Float = 0;
+ public var enabled:Bool = false;
+
+ public function new(_gdiEffect:SlushiWinGDIEffect, _wait:Float = 0, _enabled:Bool = false)
+ {
+ this.gdiEffect = _gdiEffect;
+ this.wait = _wait;
+ this.enabled = _enabled;
+ }
+}
diff --git a/funkinscsource/slushi/windows/winGDIThings/WinGDIThread.hx b/funkinscsource/slushi/windows/winGDIThings/WinGDIThread.hx
new file mode 100644
index 0000000..302014b
--- /dev/null
+++ b/funkinscsource/slushi/windows/winGDIThings/WinGDIThread.hx
@@ -0,0 +1,87 @@
+package slushi.windows.winGDIThings;
+
+import sys.thread.Thread;
+
+/*
+ * This class starts an external thread to the main one of the engine, it is used so that
+ * Windows GDI effects do not generate lag in the game due to the fact that they consume quite some
+ *
+ * Author: Slushi
+ */
+class WinGDIThread
+{
+ public static var mainThread:Thread;
+ public static var gdiEffects:Map = [];
+ public static var runningThread:Bool = true;
+ public static var elapsedTime:Float = 0;
+ public static var temporarilyPaused:Bool = false;
+
+ public static function initThread()
+ {
+ if (mainThread != null)
+ return;
+
+ Debug.logSLEInfo('Starting Windows GDI Thread...');
+
+ mainThread = Thread.create(() ->
+ {
+ Debug.logSLEInfo('Windows GDI Thread running...');
+ while (runningThread)
+ {
+ /**
+ * Check if the game is focused or if the PlayState is paused or the player is dead
+ * This prevents GDI effects from continuing to be generated at times when they should not be
+ */
+ if (!Main.focused)
+ {
+ return;
+ }
+ if (PlayState.instance != null)
+ {
+ if (PlayState.instance.paused)
+ {
+ return;
+ }
+ else if (PlayState.instance.isDead)
+ {
+ return;
+ }
+ }
+ if (temporarilyPaused)
+ {
+ return;
+ }
+
+ elapsedTime++;
+ SlushiWinGDI.setElapsedTime(elapsedTime);
+
+ for (gdi in gdiEffects)
+ {
+ if (!gdi.enabled)
+ continue;
+
+ if (gdi.wait > 0)
+ {
+ // Wait if wait time is greater than 0, slows down the effect
+ Sys.sleep(gdi.wait);
+ }
+ gdi.gdiEffect.update();
+ }
+ }
+ });
+ }
+
+ public static function stopThread()
+ {
+ if (mainThread != null)
+ {
+ Debug.logSLEInfo('Stopping Windows GDI Thread...');
+ runningThread = false;
+ temporarilyPaused = false;
+ mainThread = null;
+ }
+ gdiEffects.clear();
+ elapsedTime = 0;
+ SlushiWinGDI.setElapsedTime(elapsedTime);
+ }
+}
diff --git a/funkinscsource/states/MainMenuState.hx b/funkinscsource/states/MainMenuState.hx
index 4ed2f0f..38be709 100644
--- a/funkinscsource/states/MainMenuState.hx
+++ b/funkinscsource/states/MainMenuState.hx
@@ -310,7 +310,7 @@ class MainMenuState extends MusicBeatState
}
case RIGHT:
- if (controls.UI_LEFT_P)
+ if (controls.UI_LEFT_P)
{
curColumn = CENTER;
changeItem();
@@ -370,7 +370,7 @@ class MainMenuState extends MusicBeatState
case 'story_mode':
MusicBeatState.switchState(new StoryMenuState());
case 'freeplay':
- MusicBeatState.switchState(new states.freeplay.FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
#if MODS_ALLOWED
case 'mods':
MusicBeatState.switchState(new ModsMenuState());
diff --git a/funkinscsource/states/PlayState.hx b/funkinscsource/states/PlayState.hx
index 6a60e4a..b39e233 100644
--- a/funkinscsource/states/PlayState.hx
+++ b/funkinscsource/states/PlayState.hx
@@ -43,7 +43,7 @@ import states.MusicBeatState.subStates;
import states.freeplay.FreeplayState;
import states.editors.ChartingState;
import states.editors.CharacterEditorState;
-import substates.PauseSubState;
+import slushi.substates.SlushiPauseSubState;
import substates.GameOverSubstate;
import substates.ResultsScreenKadeSubstate;
import openfl.filters.ShaderFilter;
@@ -237,11 +237,11 @@ class PlayState extends MusicBeatState
// Slushi Engine cameras
public var camSLEHUD:FlxCamera;
- public var camFor3D:FlxCamera;
- public var camFor3D2:FlxCamera;
- public var camFor3D3:FlxCamera;
- public var camFor3D4:FlxCamera;
- public var camFor3D5:FlxCamera;
+ public var camThings:FlxCamera;
+ public var camThings2:FlxCamera;
+ public var camThings3:FlxCamera;
+ public var camThings4:FlxCamera;
+ public var camThings5:FlxCamera;
public var camWaterMark:FlxCamera;
public var cameraSpeed:Float = 1;
@@ -480,7 +480,7 @@ class PlayState extends MusicBeatState
if (SONG == null)
{
Debug.displayAlert("PlayState Was Not Able To Load Any Songs!", "PlayState Error");
- MusicBeatState.switchState(new FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
return;
}
@@ -646,7 +646,7 @@ class PlayState extends MusicBeatState
// for lua
instance = this;
- PauseSubState.songName = null; // Reset to default
+ SlushiPauseSubState.songName = null; // Reset to default
playbackRate = ClientPrefs.getGameplaySetting('songspeed');
swagHits = sickHits = goodHits = badHits = shitHits = songMisses = highestCombo = 0;
@@ -732,18 +732,18 @@ class PlayState extends MusicBeatState
camPause.bgColor.alpha = 0;
camSLEHUD = new FlxCamera();
- camFor3D = new FlxCamera();
- camFor3D2 = new FlxCamera();
- camFor3D3 = new FlxCamera();
- camFor3D4 = new FlxCamera();
- camFor3D5 = new FlxCamera();
+ camThings = new FlxCamera();
+ camThings2 = new FlxCamera();
+ camThings3 = new FlxCamera();
+ camThings4 = new FlxCamera();
+ camThings5 = new FlxCamera();
camWaterMark = new FlxCamera();
camSLEHUD.bgColor.alpha = 0;
- camFor3D.bgColor.alpha = 0;
- camFor3D2.bgColor.alpha = 0;
- camFor3D3.bgColor.alpha = 0;
- camFor3D4.bgColor.alpha = 0;
- camFor3D5.bgColor.alpha = 0;
+ camThings.bgColor.alpha = 0;
+ camThings2.bgColor.alpha = 0;
+ camThings3.bgColor.alpha = 0;
+ camThings4.bgColor.alpha = 0;
+ camThings5.bgColor.alpha = 0;
camWaterMark.bgColor.alpha = 0;
// Video Camera if you put funni videos or smth
@@ -756,11 +756,11 @@ class PlayState extends MusicBeatState
FlxG.cameras.add(camHUD, false);
FlxG.cameras.add(camSLEHUD, false);
- FlxG.cameras.add(camFor3D, false);
- FlxG.cameras.add(camFor3D2, false);
- FlxG.cameras.add(camFor3D3, false);
- FlxG.cameras.add(camFor3D4, false);
- FlxG.cameras.add(camFor3D5, false);
+ FlxG.cameras.add(camThings, false);
+ FlxG.cameras.add(camThings2, false);
+ FlxG.cameras.add(camThings3, false);
+ FlxG.cameras.add(camThings4, false);
+ FlxG.cameras.add(camThings5, false);
// for jumescares and shit
FlxG.cameras.add(camOther, false);
@@ -1420,7 +1420,7 @@ class PlayState extends MusicBeatState
}
Paths.image('alphabet');
- if (PauseSubState.songName != null) Paths.music(PauseSubState.songName);
+ if (SlushiPauseSubState.songName != null) Paths.music(SlushiPauseSubState.songName);
else if (Paths.formatToSongPath(ClientPrefs.data.pauseMusic) != 'none') Paths.music(Paths.formatToSongPath(ClientPrefs.data.pauseMusic));
resetRPC();
@@ -3424,7 +3424,7 @@ class PlayState extends MusicBeatState
{
if (endCallback != null) endCallback();
else
- MusicBeatState.switchState(new FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
super.update(elapsed);
return;
}
@@ -4273,7 +4273,7 @@ class PlayState extends MusicBeatState
}
}
- var pauseSubState = new PauseSubState();
+ var pauseSubState = new SlushiPauseSubState();
openSubState(pauseSubState);
pauseSubState.camera = camPause;
@@ -5344,7 +5344,7 @@ class PlayState extends MusicBeatState
Debug.logTrace('WENT BACK TO FREEPLAY??');
Mods.loadTopMod();
#if DISCORD_ALLOWED DiscordClient.resetClientID(); #end
- MusicBeatState.switchState(new FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
FlxG.sound.playMusic(SlushiMain.getSLEPath("Musics/SLE_HackNet_Resonance.ogg"));
changedDifficulty = false;
}
@@ -6678,19 +6678,8 @@ class PlayState extends MusicBeatState
note.wasGoodHit = true;
- if (useSLEHUD) {
- SlushiEngineHUD.setRatingText(note.strumTime - Conductor.songPosition);
- if(!isSus) {
- SlushiEngineHUD.doComboAngle();
- }
- }
- #if windows
- if(ClientPrefs.data.changeWindowBorderColorWithNoteHit && SlushiEngineHUD.instance.canChangeWindowColorWithNoteHit && !isSus)
- {
- // var convertedColor = CustomFuncs.getRGBFromFlxColor(note.rgbShader.r, note.rgbShader.g, note.rgbShader.b);
- SlushiEngineHUD.setWindowColorWithNoteHit(leData/*, convertedColor*/);
- }
- #end
+ // Simpler just leave this line for future times when you want to port SLE to another version of SCE.
+ SlushiEngineHUD.setParamsFromPlayerNote(note.strumTime, isSus, leData);
if (note.hitsound != null && note.hitsoundVolume > 0 && !note.hitsoundDisabled) FlxG.sound.play(Paths.sound(note.hitsound), note.hitsoundVolume);
@@ -7083,6 +7072,8 @@ class PlayState extends MusicBeatState
}
}
+ SlushiEngineHUD.setNotITGNotesInSteps(curStep);
+
if (bopOnStep)
{
if (camZooming && camZoomingBopStep > 0 && camZoomingMultStep > 0 && FlxG.camera.zoom < maxCamZoom && ClientPrefs.data.camZooms
diff --git a/funkinscsource/states/WarnFreeplay.hx b/funkinscsource/states/WarnFreeplay.hx
index e40c887..ac5e38a 100644
--- a/funkinscsource/states/WarnFreeplay.hx
+++ b/funkinscsource/states/WarnFreeplay.hx
@@ -48,7 +48,7 @@ class WarnFreeplay extends states.MusicBeatState
FlxG.sound.play(Paths.sound('confirmMenu'));
FlxFlicker.flicker(warnText, 1, 0.1, false, true, function(flk:FlxFlicker) {
new FlxTimer().start(0.5, function(tmr:FlxTimer) {
- MusicBeatState.switchState(new states.freeplay.FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
});
});
}
diff --git a/funkinscsource/states/freeplay/FreeplayState.hx b/funkinscsource/states/freeplay/FreeplayState.hx
index 8662ed4..f0f3d97 100644
--- a/funkinscsource/states/freeplay/FreeplayState.hx
+++ b/funkinscsource/states/freeplay/FreeplayState.hx
@@ -271,7 +271,7 @@ class FreeplayState extends MusicBeatState
// Set the window border color from the current song's color
// Idea from VS Camellia ALT (https://gamebanana.com/mods/413258) (They use my code to set the window border color XD)
- CustomFuncs.setWinBorderColorFromInt(intendedColor);
+ WindowsFuncs.setWindowBorderColorFromInt(intendedColor);
curDifficulty = Math.round(Math.max(0, Difficulty.list.indexOf(lastDifficultyName)));
@@ -999,7 +999,7 @@ class FreeplayState extends MusicBeatState
// Set the window border color from the current song's color
// Idea from VS Camellia ALT (https://gamebanana.com/mods/413258) (They use my code to set the window border color XD)
- CustomFuncs.setWinBorderColorFromInt(intendedColor);
+ WindowsFuncs.setWindowBorderColorFromInt(intendedColor);
FlxTween.cancelTweensOf(bg);
FlxTween.color(bg, 1, bg.color, intendedColor);
diff --git a/funkinscsource/substates/GameOverSubstate.hx b/funkinscsource/substates/GameOverSubstate.hx
index a3e134b..5284633 100644
--- a/funkinscsource/substates/GameOverSubstate.hx
+++ b/funkinscsource/substates/GameOverSubstate.hx
@@ -60,6 +60,8 @@ class GameOverSubstate extends MusicBeatSubState
{
instance = this;
+ WindowsFuncs.tweenWindowBorderColor([255, 0, 0], [0, 0, 0], 1, 'linear');
+
Conductor.songPosition = 0;
if (boyfriend == null)
@@ -170,7 +172,7 @@ class GameOverSubstate extends MusicBeatSubState
{
if (PlayState.isStoryMode) MusicBeatState.switchState(new StoryMenuState());
else
- MusicBeatState.switchState(new states.freeplay.FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
}
#if BASE_GAME_FILES
else
@@ -181,7 +183,7 @@ class GameOverSubstate extends MusicBeatSubState
openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker)));
}
else
- openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new states.freeplay.FreeplayState(sticker)));
+ openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new slushi.states.freeplay.SlushiFreeplayState(sticker)));
}
#end
@@ -240,6 +242,9 @@ class GameOverSubstate extends MusicBeatSubState
{
if (!isEnding)
{
+
+ WindowsFuncs.tweenWindowBorderColor([185, 157, 0], CustomFuncs.colorIntToRGB(SlushiMain.slushiColor), 2, 'linear');
+
isEnding = true;
if (boyfriend.hasOffsetAnimation('deathConfirm')) boyfriend.playAnim('deathConfirm', true);
diff --git a/funkinscsource/substates/PauseSubState.hx b/funkinscsource/substates/PauseSubState.hx
index 325c8da..40c24d2 100644
--- a/funkinscsource/substates/PauseSubState.hx
+++ b/funkinscsource/substates/PauseSubState.hx
@@ -467,7 +467,7 @@ class PauseSubState extends MusicBeatSubState
{
if (PlayState.isStoryMode) MusicBeatState.switchState(new StoryMenuState());
else
- MusicBeatState.switchState(new states.freeplay.FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
}
#if BASE_GAME_FILES
else
@@ -478,7 +478,7 @@ class PauseSubState extends MusicBeatSubState
openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker)));
}
else
- openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new states.freeplay.FreeplayState(sticker)));
+ openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new slushi.states.freeplay.SlushiFreeplayState(sticker)));
}
#end
diff --git a/funkinscsource/substates/ResultsScreenKadeSubstate.hx b/funkinscsource/substates/ResultsScreenKadeSubstate.hx
index 91da8c7..eb74c40 100644
--- a/funkinscsource/substates/ResultsScreenKadeSubstate.hx
+++ b/funkinscsource/substates/ResultsScreenKadeSubstate.hx
@@ -264,7 +264,7 @@ class ResultsScreenKadeSubstate extends substates.MusicBeatSubState
close();
if (PlayState.isStoryMode) MusicBeatState.switchState(new StoryMenuState());
else
- MusicBeatState.switchState(new states.freeplay.FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
}, true);
}
});
diff --git a/funkinscsource/substates/vslice/ResultState.hx b/funkinscsource/substates/vslice/ResultState.hx
index 8752c42..24b855c 100644
--- a/funkinscsource/substates/vslice/ResultState.hx
+++ b/funkinscsource/substates/vslice/ResultState.hx
@@ -106,6 +106,8 @@ class ResultState extends MusicBeatSubState
score = new ResultScore(35, 305, 10, params.scoreData.mainData.score);
rankBg = new FunkinSCSprite(0, 0);
+
+ WindowsFuncs.setWindowBorderColor([254, 199, 92]);
}
override function create():Void
@@ -895,7 +897,7 @@ class ResultState extends MusicBeatSubState
Debug.logInfo('WENT BACK TO FREEPLAY?? - HIGH SCORE');
Mods.loadTopMod();
#if DISCORD_ALLOWED DiscordClient.resetClientID(); #end
- MusicBeatState.switchState(new FreeplayState());
+ MusicBeatState.switchState(new slushi.states.freeplay.SlushiFreeplayState());
FlxG.sound.playMusic(SlushiMain.getSLEPath("Musics/SLE_HackNet_Resonance.ogg"));
}
});
@@ -905,7 +907,7 @@ class ResultState extends MusicBeatSubState
Debug.logInfo('rank is lower...... and/or equal');
Debug.logInfo('WENT BACK TO FREEPLAY?? - LOW SCORE');
Mods.loadTopMod();
- openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new FreeplayState(sticker)));
+ openSubState(new vslice.transition.StickerSubState(null, (sticker) -> new slushi.states.freeplay.SlushiFreeplayState(sticker)));
FlxG.sound.playMusic(SlushiMain.getSLEPath("Musics/SLE_HackNet_Resonance.ogg"));
}
}
diff --git a/funkinscsource/utils/logging/CrashHandler.hx b/funkinscsource/utils/logging/CrashHandler.hx
index 4455a2e..6f7b403 100644
--- a/funkinscsource/utils/logging/CrashHandler.hx
+++ b/funkinscsource/utils/logging/CrashHandler.hx
@@ -84,7 +84,7 @@ class CrashHandler
#if DISCORD_ALLOWED
DiscordClient.shutdown();
#end
- Sys.exit(1);
+ System.exit(1);
}
catch (e:Dynamic)
{
diff --git a/gitVersion.json b/gitVersion.json
index 3048e47..3e0bf39 100644
--- a/gitVersion.json
+++ b/gitVersion.json
@@ -1,3 +1,3 @@
{
- "engineVersion": "0.3.8"
+ "engineVersion": "0.4.0"
}
\ No newline at end of file
diff --git a/hmm.json b/hmm.json
index 3c08c1b..3afd1fb 100644
--- a/hmm.json
+++ b/hmm.json
@@ -60,6 +60,11 @@
"type": "haxelib",
"version": null
},
+ {
+ "name": "compiletime",
+ "type": "haxelib",
+ "version": null
+ },
{
"name": "flixel",
"type": "git",
@@ -72,7 +77,7 @@
"type": "git",
"dir": null,
"ref": "dev",
- "url": "https://github.com/glowsoony/flixel-addons"
+ "url": "https://github.com/Slushi-Github/SLE-flixel-addons"
},
{
"name": "fnf-modcharting-tools",