diff --git a/KadeEngineLogo.png b/KadeEngineLogo.png
index 7a77f25..9279a4a 100644
Binary files a/KadeEngineLogo.png and b/KadeEngineLogo.png differ
diff --git a/Project.xml b/Project.xml
index d2cac59..eeffad6 100644
--- a/Project.xml
+++ b/Project.xml
@@ -112,6 +112,9 @@
+
+
+
diff --git a/README.md b/README.md
index fed6148..832467c 100644
--- a/README.md
+++ b/README.md
@@ -1,61 +1,68 @@
-
-
-[](https://ci.appveyor.com/project/KadeDev/kade-engine-windows/build/artifacts) [](https://ci.appveyor.com/project/KadeDev/kade-engine-macos/build/artifacts) [](https://ci.appveyor.com/project/KadeDev/kade-engine-linux/build/artifacts) [](https://ci.appveyor.com/project/daniel11420/KadeEngineWeb) [](https://discord.gg/MG6GQFh52U) [](https://github.com/KadeDev/Kade-Engine/issues) [](https://github.com/KadeDev/Kade-Engine/pulls) []() []()
-
-      
-
-# Friday Night Funkin': Kade Engine
-## Friday Night Funkin'
-**Friday Night Funkin'** is a rhythm game originally made for Ludum Dare 47 "Stuck In a Loop".
-
-Links: **[itch.io page](https://ninja-muffin24.itch.io/funkin) ⋅ [Newgrounds](https://www.newgrounds.com/portal/view/770371) ⋅ [source code on GitHub](https://github.com/ninjamuffin99/Funkin)**
-> Uh oh! Your tryin to kiss ur hot girlfriend, but her MEAN and EVIL dad is trying to KILL you! He's an ex-rockstar, the only way to get to his heart? The power of music...
-
-## Kade Engine
-**Kade Engine** is a mod for Friday Night Funkin', including a full engine rework, replays, and more.
-
-Links: **[GameBanana mod page](https://gamebanana.com/gamefiles/16761) ⋅ [play in browser](https://funkin.puyo.xyz) ⋅ [latest stable release](https://github.com/KadeDev/Kade-Engine/releases/latest) ⋅ [latest development build (windows)](https://ci.appveyor.com/project/KadeDev/kade-engine-windows/build/artifacts) ⋅ [latest development build (macOS)](https://ci.appveyor.com/project/KadeDev/kade-engine-macos/build/artifacts) ⋅ [latest development build (linux)](https://ci.appveyor.com/project/KadeDev/kade-engine-linux/build/artifacts)**
-
-**REMEMBER**: This is a **mod**. This is not the vanilla game and should be treated as a **modification**. This is not and probably will never be official, so don't get confused.
-
-## Website ([KadeDev.github.io/kade-engine/](https://KadeDev.github.io/Kade-Engine/))
-If you're looking for documentation, changelogs, or guides, you can find those on the Kade Engine website.
-
-# Previews ([skip](#features))
-
- 
-
-
-
-
-
-
-
-
-
-
-
-# Features
-
- - **New Input System**
- - An improved input system, similar to Quaver or Etterna, with less delays, less dropped inputs and other improvements.
- - **More information during gameplay**
- - While you're playing, we show you information about how you're doing, such as your accuracy, combo break count, notes per second, and your grade/rating.
- - **Better key layouts**
- - Instead of being forced to use WASD and the arrow keys, now you can play with DFJK!
- - **Replays** (in beta)
- - Have you ever gotten a crazy score but didn't record? The replay system solves that: it automatically saves a "replay" of your gameplay every time you complete a song, which you can play back inside of the game.
- - Replays just store information about what you're doing, they don't actually record the screen -- so they take up way less space on your disk than videos.
- - **Audio offset**
- - If your headphones are delayed, you can set an offset in the options menu to line the game up with the delay and play with synced audio like intended.
-
-# Credits
-### Friday Night Funkin'
- - [ninjamuffin99](https://twitter.com/ninja_muffin99) - Programming
- - [PhantomArcade3K](https://twitter.com/phantomarcade3k) and [Evilsk8r](https://twitter.com/evilsk8r) - Art
- - [Kawai Sprite](https://twitter.com/kawaisprite) - Music
-
-This game was made with love to Newgrounds and its community. Extra love to Tom Fulp.
-### Kade Engine
-- [KadeDeveloper](https://twitter.com/KadeDeveloper) - Maintainer and lead programmer
-- [The contributors](https://github.com/KadeDev/Kade-Engine/graphs/contributors)
+
+
+
+[](https://ci.appveyor.com/project/KadeDev/kade-engine-windows/branch/master/artifacts) [](https://ci.appveyor.com/project/KadeDev/kade-engine-macos/branch/master/artifacts) [](https://ci.appveyor.com/project/KadeDev/kade-engine-linux/branch/master/artifacts) [](https://ci.appveyor.com/project/daniel11420/KadeEngineWeb) [](https://discord.gg/MG6GQFh52U) [](https://github.com/KadeDev/Kade-Engine/issues) [](https://github.com/KadeDev/Kade-Engine/pulls) []() []()
+
+      
+
+# Friday Night Funkin': Kade Engine
+## Friday Night Funkin'
+**Friday Night Funkin'** is a rhythm game originally made for Ludum Dare 47 "Stuck In a Loop".
+
+Links: **[itch.io page](https://ninja-muffin24.itch.io/funkin) ⋅ [Newgrounds](https://www.newgrounds.com/portal/view/770371) ⋅ [source code on GitHub](https://github.com/ninjamuffin99/Funkin)**
+> Uh oh! Your tryin to kiss ur hot girlfriend, but her MEAN and EVIL dad is trying to KILL you! He's an ex-rockstar, the only way to get to his heart? The power of music...
+
+## Kade Engine
+**Kade Engine** is a mod for Friday Night Funkin', including a full engine rework, replays, and more.
+
+Links: **[GameBanana mod page](https://gamebanana.com/gamefiles/16761) ⋅ [play in browser](https://funkin.puyo.xyz) ⋅ [latest stable release](https://github.com/KadeDev/Kade-Engine/releases/latest) ⋅ [latest development build (windows)](https://ci.appveyor.com/project/KadeDev/kade-engine-windows/branch/master/artifacts) ⋅ [latest development build (macOS)](https://ci.appveyor.com/project/KadeDev/kade-engine-macos/branch/master/artifacts) ⋅ [latest development build (linux)](https://ci.appveyor.com/project/KadeDev/kade-engine-linux/branch/master/artifacts)**
+
+**REMEMBER**: This is a **mod**. This is not the vanilla game and should be treated as a **modification**. This is not and probably will never be official, so don't get confused.
+
+## Website ([KadeDev.github.io/kade-engine/](https://KadeDev.github.io/Kade-Engine/))
+If you're looking for documentation, changelogs, or guides, you can find those on the Kade Engine website.
+
+# Previews ([skip](#features))
+
+ 
+
+
+
+
+
+
+
+
+
+
+
+# Features
+
+ - **New Input System**
+ - An improved input system, similar to Quaver or Etterna, with less delays, less dropped inputs and other improvements.
+ - **More information during gameplay**
+ - While you're playing, we show you information about how you're doing, such as your accuracy, combo break count, notes per second, and your grade/rating.
+ - **Customizable keybinds**
+ - Instead of being forced to use WASD and the arrow keys, you can customize the keybinds to any keys you want!
+ - **Replays** (in beta)
+ - Have you ever gotten a crazy score but didn't record? The replay system solves that: it automatically saves a "replay" of your gameplay every time you complete a song, which you can play back inside of the game.
+ - Replays just store information about what you're doing, they don't actually record the screen -- so they take up way less space on your disk than videos.
+ - **Audio offset**
+ - If your headphones are delayed, you can set an offset in the options menu to line the game up with the delay and play with synced audio like intended.
+
+# Credits
+### Friday Night Funkin'
+ - [ninjamuffin99](https://twitter.com/ninja_muffin99) - Programming
+ - [PhantomArcade3K](https://twitter.com/phantomarcade3k) and [Evilsk8r](https://twitter.com/evilsk8r) - Art
+ - [Kawai Sprite](https://twitter.com/kawaisprite) - Music
+
+This game was made with love to Newgrounds and its community. Extra love to Tom Fulp.
+### Kade Engine
+- [KadeDeveloper](https://twitter.com/KadeDeveloper) - Maintainer and lead programmer
+- [The contributors](https://github.com/KadeDev/Kade-Engine/graphs/contributors)
+
+
+### Shoutouts
+- [GWebDev](https://github.com/GrowtopiaFli) - Video Code
+- [Rozebud](https://github.com/ThatRozebudDude) - Ideas (that I stole)
+- [Puyo](https://github.com/daniel11420) - Setting up appveyor and a lot of other help
\ No newline at end of file
diff --git a/appveyor-linux.yml b/appveyor-linux.yml
index 6e9a95a..804f7ac 100644
--- a/appveyor-linux.yml
+++ b/appveyor-linux.yml
@@ -28,6 +28,8 @@ install:
- haxelib git faxe https://github.com/uhrobots/faxe
- haxelib git polymod https://github.com/larsiusprime/polymod.git
- haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc
+ - haxelib git extension-webm https://github.com/KadeDev/extension-webm
+ - haxelib run lime rebuild extension-webm linux
- haxelib install linc_luajit
- haxelib list
- cd /home/appveyor/projects/kade-engine-linux
@@ -36,8 +38,8 @@ build_script:
- haxelib run lime build linux
after_build:
- - tar -cvf funkin-ke.tar -C /home/appveyor/projects/kade-engine-linux/export/release/linux/bin .
+ - tar -cvf KadeEngine-Linux.tar -C /home/appveyor/projects/kade-engine-linux/export/release/linux/bin .
artifacts:
-- path: funkin-ke.tar
- name: Linux build
\ No newline at end of file
+- path: KadeEngine-Linux.tar
+ name: Kade Engine for Linux
diff --git a/appveyor-macos.yml b/appveyor-macos.yml
index 15e048b..f3ed6f6 100644
--- a/appveyor-macos.yml
+++ b/appveyor-macos.yml
@@ -28,16 +28,18 @@ install:
- haxelib git faxe https://github.com/uhrobots/faxe
- haxelib git polymod https://github.com/larsiusprime/polymod.git
- haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc
+ - haxelib git extension-webm https://github.com/KadeDev/extension-webm
+ - haxelib run lime rebuild extension-webm macos
- haxelib install linc_luajit
- haxelib list
- cd /Users/appveyor/projects/kade-engine-macos
build_script:
- haxelib run lime build mac
-
after_build:
- - gtar -cvf funkin-ke.tar -C /Users/appveyor/projects/kade-engine-macos/export/release/macos/bin .
+ - hdiutil create /Users/appveyor/temp.dmg -ov -volname "KadeEngine-macOS" -fs HFS+ -srcfolder "/Users/appveyor/projects/kade-engine-macos/export/release/macos/bin"
+ - hdiutil convert /Users/appveyor/temp.dmg -format UDZO -o KadeEngine-macOS.dmg
artifacts:
-- path: funkin-ke.tar
- name: macOS build idk
+- path: KadeEngine-macOS.dmg
+ name: Kade Engine for macOS
diff --git a/appveyor-windows.yml b/appveyor-windows.yml
index 01bac78..caf4016 100644
--- a/appveyor-windows.yml
+++ b/appveyor-windows.yml
@@ -32,6 +32,8 @@ install:
- haxelib git faxe https://github.com/uhrobots/faxe
- haxelib git polymod https://github.com/larsiusprime/polymod.git
- haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc
+ - haxelib git extension-webm https://github.com/KadeDev/extension-webm
+ - haxelib run lime rebuild extension-webm windows
- haxelib install linc_luajit
- haxelib list
@@ -42,5 +44,5 @@ build_script:
artifacts:
- path: export/release/windows/bin
- name: Windows release
- type: zip
\ No newline at end of file
+ name: KadeEngine-Windows
+ type: zip
diff --git a/assets/preload/data/dad-battle/0.offset b/assets/preload/data/dadbattle/0.offset
similarity index 100%
rename from assets/preload/data/dad-battle/0.offset
rename to assets/preload/data/dadbattle/0.offset
diff --git a/assets/preload/data/dad-battle/dad-battle-easy.json b/assets/preload/data/dadbattle/dadbattle-easy.json
similarity index 100%
rename from assets/preload/data/dad-battle/dad-battle-easy.json
rename to assets/preload/data/dadbattle/dadbattle-easy.json
diff --git a/assets/preload/data/dad-battle/dad-battle-hard.json b/assets/preload/data/dadbattle/dadbattle-hard.json
similarity index 100%
rename from assets/preload/data/dad-battle/dad-battle-hard.json
rename to assets/preload/data/dadbattle/dadbattle-hard.json
diff --git a/assets/preload/data/dad-battle/dad-battle.json b/assets/preload/data/dadbattle/dadbattle.json
similarity index 100%
rename from assets/preload/data/dad-battle/dad-battle.json
rename to assets/preload/data/dadbattle/dadbattle.json
diff --git a/assets/preload/data/freeplaySonglist.txt b/assets/preload/data/freeplaySonglist.txt
index dd50762..a5939ad 100644
--- a/assets/preload/data/freeplaySonglist.txt
+++ b/assets/preload/data/freeplaySonglist.txt
@@ -6,7 +6,7 @@ Spookeez:spooky:2
South:spooky:2
Monster:monster:2
Pico:pico:3
-Philly:pico:3
+Philly Nice:pico:3
Blammed:pico:3
Satin Panties:mom:4
High:mom:4
diff --git a/assets/preload/data/philly/philly-easy.json b/assets/preload/data/philly/philly-easy.json
index ba3e4e9..6ad3bbb 100644
--- a/assets/preload/data/philly/philly-easy.json
+++ b/assets/preload/data/philly/philly-easy.json
@@ -1 +1 @@
-{"song":{"player1":"bf","notes":[{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[2914.28564,2,0],[3428.57129,1,257.142853],[3771.42847,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[4285.71436,2,0],[4800,1,257.142853],[5142.857,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[5657.14258,2,0],[6171.42871,1,257.142853],[6514.28564,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[6857.14258,0,0],[7200,2,0],[7542.857,2,0],[7885.71436,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[8400,2,0],[8914.285,1,257.142853],[9257.143,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[9771.429,2,0],[10285.7139,1,257.142853],[10628.5713,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[11142.8574,2,0],[11657.1426,1,257.142853],[12000,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[12342.8574,0,0],[12685.7139,2,0],[13028.5713,2,0],[13371.4287,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[14057.1426,2,0],[14400,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[15428.5713,3,0],[15771.4287,2,0],[16285.7139,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[16800,3,0],[17142.8574,0,0],[17485.7148,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[17828.57,3,0],[18171.4277,1,0],[18514.2852,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[19542.8574,2,0],[19885.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[20914.2852,3,0],[21257.1426,2,0],[21771.4277,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[22285.7148,3,0],[22628.57,0,0],[22971.4277,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[23314.2852,3,0],[23657.1426,1,0],[24000,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[24685.7148,2,0],[25371.4277,0,0],[25714.2852,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[26400,3,0],[26742.8574,2,0],[27257.1426,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[27771.4277,3,0],[28114.2852,0,0],[28457.1426,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[28800,3,0],[29142.8574,1,0],[29485.7148,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[30171.4277,2,0],[30857.1426,0,0],[31200,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[31885.7148,3,0],[32228.57,2,0],[32742.8574,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[33257.14,3,0],[33600,0,0],[33942.8555,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[34285.7148,3,0],[34628.57,1,0],[34971.43,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[35657.14,2,0],[36342.8555,2,0],[36685.7148,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[37028.57,2,0],[37714.2852,2,0],[38057.14,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[38400,2,0],[39085.7148,2,0],[39428.57,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[39771.43,2,0],[40457.14,2,0],[40800,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[41142.8555,2,0],[41828.57,2,0],[42171.43,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[42514.2852,2,0],[43200,2,0],[43542.8555,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[43885.7148,2,0],[44571.43,2,0],[44914.2852,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[45257.14,2,0],[45942.8555,2,0],[46285.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[46628.57,2,0],[47314.2852,2,0],[47657.14,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[48000,2,0],[48685.7148,2,0],[49028.57,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[49371.43,2,0],[50057.14,2,0],[50400,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[50742.8555,3,0],[51428.57,2,0],[51771.43,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[52114.2852,2,0],[52800,2,0],[53142.8555,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[53485.7148,2,0],[54171.43,2,0],[54514.2852,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[54857.14,2,0],[55542.8555,2,0],[55885.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[56228.57,3,0],[56914.2852,2,0],[57257.14,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[57600,3,0],[58285.7148,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[58971.43,2,0],[59314.2852,3,0],[59657.14,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[60342.8555,3,0],[61028.57,2,0],[61542.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[61714.2852,2,0],[62057.14,0,0],[62400,2,0],[62742.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[63085.7148,3,0],[63771.43,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[64457.14,2,0],[64800,3,0],[65142.8555,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[65828.57,3,0],[66514.28,2,0],[67028.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[67200,2,0],[67542.86,0,0],[67885.71,2,0],[68228.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[68571.43,2,0],[69257.14,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[69942.86,0,0],[70628.57,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[71314.28,3,0],[72000,2,0],[72342.86,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[72685.71,3,0],[73371.43,2,0],[73714.28,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[74057.14,2,0],[74742.86,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[75428.57,0,0],[76114.28,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[76800,3,0],[77485.71,2,0],[77828.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[78171.43,3,0],[78857.14,2,0],[79200,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[79542.86,2,0],[80228.57,2,0],[80571.43,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[80914.28,2,0],[81600,2,0],[81942.86,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[82285.71,2,0],[82971.43,2,0],[83314.28,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[83657.14,3,0],[84342.86,2,0],[84685.71,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[85028.57,2,0],[85714.28,2,0],[86057.14,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[86400,2,0],[87085.71,2,0],[87428.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[87771.43,2,0],[88457.14,2,0],[88800,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[89142.86,3,0],[89828.57,2,0],[90171.43,0,0],[90342.86,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[90514.28,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"lengthInSteps":16,"altAnim":false,"typeOfSection":0,"sectionNotes":[],"bpm":175,"changeBPM":false,"mustHitSection":true}],"player2":"pico","song":"Philly","stage":"philly","needsVoices":true,"validScore":true,"bpm":175,"speed":1}}
\ No newline at end of file
+{"song":{"player1":"bf","notes":[{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[2914.28564,2,0],[3428.57129,1,257.142853],[3771.42847,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[4285.71436,2,0],[4800,1,257.142853],[5142.857,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[5657.14258,2,0],[6171.42871,1,257.142853],[6514.28564,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[6857.14258,0,0],[7200,2,0],[7542.857,2,0],[7885.71436,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[8400,2,0],[8914.285,1,257.142853],[9257.143,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[9771.429,2,0],[10285.7139,1,257.142853],[10628.5713,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[11142.8574,2,0],[11657.1426,1,257.142853],[12000,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[12342.8574,0,0],[12685.7139,2,0],[13028.5713,2,0],[13371.4287,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[14057.1426,2,0],[14400,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[15428.5713,3,0],[15771.4287,2,0],[16285.7139,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[16800,3,0],[17142.8574,0,0],[17485.7148,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[17828.57,3,0],[18171.4277,1,0],[18514.2852,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[19542.8574,2,0],[19885.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[20914.2852,3,0],[21257.1426,2,0],[21771.4277,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[22285.7148,3,0],[22628.57,0,0],[22971.4277,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[23314.2852,3,0],[23657.1426,1,0],[24000,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[24685.7148,2,0],[25371.4277,0,0],[25714.2852,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[26400,3,0],[26742.8574,2,0],[27257.1426,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[27771.4277,3,0],[28114.2852,0,0],[28457.1426,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[28800,3,0],[29142.8574,1,0],[29485.7148,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[30171.4277,2,0],[30857.1426,0,0],[31200,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[31885.7148,3,0],[32228.57,2,0],[32742.8574,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[33257.14,3,0],[33600,0,0],[33942.8555,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[34285.7148,3,0],[34628.57,1,0],[34971.43,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[35657.14,2,0],[36342.8555,2,0],[36685.7148,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[37028.57,2,0],[37714.2852,2,0],[38057.14,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[38400,2,0],[39085.7148,2,0],[39428.57,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[39771.43,2,0],[40457.14,2,0],[40800,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[41142.8555,2,0],[41828.57,2,0],[42171.43,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[42514.2852,2,0],[43200,2,0],[43542.8555,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[43885.7148,2,0],[44571.43,2,0],[44914.2852,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[45257.14,2,0],[45942.8555,2,0],[46285.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[46628.57,2,0],[47314.2852,2,0],[47657.14,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[48000,2,0],[48685.7148,2,0],[49028.57,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[49371.43,2,0],[50057.14,2,0],[50400,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[50742.8555,3,0],[51428.57,2,0],[51771.43,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[52114.2852,2,0],[52800,2,0],[53142.8555,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[53485.7148,2,0],[54171.43,2,0],[54514.2852,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[54857.14,2,0],[55542.8555,2,0],[55885.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[56228.57,3,0],[56914.2852,2,0],[57257.14,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[57600,3,0],[58285.7148,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[58971.43,2,0],[59314.2852,3,0],[59657.14,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[60342.8555,3,0],[61028.57,2,0],[61542.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[61714.2852,2,0],[62057.14,0,0],[62400,2,0],[62742.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[63085.7148,3,0],[63771.43,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[64457.14,2,0],[64800,3,0],[65142.8555,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[65828.57,3,0],[66514.28,2,0],[67028.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[67200,2,0],[67542.86,0,0],[67885.71,2,0],[68228.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[68571.43,2,0],[69257.14,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[69942.86,0,0],[70628.57,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[71314.28,3,0],[72000,2,0],[72342.86,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[72685.71,3,0],[73371.43,2,0],[73714.28,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[74057.14,2,0],[74742.86,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[75428.57,0,0],[76114.28,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[76800,3,0],[77485.71,2,0],[77828.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[78171.43,3,0],[78857.14,2,0],[79200,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[79542.86,2,0],[80228.57,2,0],[80571.43,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[80914.28,2,0],[81600,2,0],[81942.86,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[82285.71,2,0],[82971.43,2,0],[83314.28,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[83657.14,3,0],[84342.86,2,0],[84685.71,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[85028.57,2,0],[85714.28,2,0],[86057.14,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[86400,2,0],[87085.71,2,0],[87428.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[87771.43,2,0],[88457.14,2,0],[88800,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[89142.86,3,0],[89828.57,2,0],[90171.43,0,0],[90342.86,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[90514.28,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"lengthInSteps":16,"altAnim":false,"typeOfSection":0,"sectionNotes":[],"bpm":175,"changeBPM":false,"mustHitSection":true}],"player2":"pico","song":"Philly Nice","stage":"philly","needsVoices":true,"validScore":true,"bpm":175,"speed":1}}
\ No newline at end of file
diff --git a/assets/preload/data/philly/philly-hard.json b/assets/preload/data/philly/philly-hard.json
index 2f35dff..5dcf8f2 100644
--- a/assets/preload/data/philly/philly-hard.json
+++ b/assets/preload/data/philly/philly-hard.json
@@ -1 +1 @@
-{"song":{"player1":"bf","notes":[{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[2914.28564,2,0],[3085.71436,0,0],[3428.57129,1,257.142853],[3771.42847,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[4285.71436,2,0],[4457.14258,0,0],[4800,1,257.142853],[5142.857,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[5657.14258,2,0],[5828.57129,0,0],[6171.42871,1,257.142853],[6514.28564,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[6857.14258,0,0],[7028.57129,3,0],[7200,2,0],[7542.857,2,0],[7885.71436,0,0],[8057.14258,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[8400,2,0],[8571.429,0,0],[8914.285,1,257.142853],[9257.143,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[9771.429,2,0],[9942.857,0,0],[10285.7139,1,257.142853],[10628.5713,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[11142.8574,2,0],[11314.2852,0,0],[11657.1426,1,257.142853],[12000,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[12342.8574,0,0],[12514.2852,3,0],[12685.7139,2,0],[13028.5713,2,0],[13371.4287,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[13885.7139,2,0],[14057.1426,0,0],[14400,0,0],[14742.8574,3,0],[14914.2852,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[15257.1426,3,0],[15428.5713,0,0],[15771.4287,2,0],[16114.2852,0,0],[16285.7139,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[16628.57,0,0],[16800,1,0],[16971.4277,3,0],[17142.8574,1,0],[17314.2852,0,0],[17485.7148,1,0],[17657.1426,3,0],[17742.8574,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[17828.57,3,0],[18000,3,0],[18171.4277,1,0],[18514.2852,2,0],[18857.1426,2,0],[19028.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[19371.4277,2,0],[19542.8574,0,0],[19885.7148,0,0],[20228.57,3,0],[20400,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[20742.8574,3,0],[20914.2852,0,0],[21257.1426,2,0],[21600,0,0],[21771.4277,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[22114.2852,0,0],[22285.7148,1,0],[22457.1426,3,0],[22628.57,1,0],[22800,0,0],[22971.4277,1,0],[23142.8574,3,0],[23228.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[23314.2852,3,0],[23485.7148,3,0],[23657.1426,1,0],[24000,2,0],[24342.8574,2,0],[24514.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[24685.7148,2,0],[24857.1426,2,0],[25028.57,0,0],[25371.4277,0,0],[25714.2852,3,0],[25885.7148,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[26228.57,3,0],[26400,0,0],[26742.8574,2,0],[27085.7148,0,0],[27257.1426,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[27600,0,0],[27771.4277,1,0],[27942.8574,3,0],[28114.2852,1,0],[28285.7148,0,0],[28457.1426,1,0],[28628.57,3,0],[28714.2852,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[28800,3,0],[28971.4277,3,0],[29142.8574,1,0],[29485.7148,2,0],[29828.57,2,0],[30000,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[30171.4277,2,0],[30342.8574,2,0],[30514.2852,0,0],[30857.1426,0,0],[31200,3,0],[31371.4277,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[31714.2852,3,0],[31885.7148,0,0],[32228.57,2,0],[32571.4277,0,0],[32742.8574,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[33085.7148,0,0],[33257.14,1,0],[33428.57,3,0],[33600,1,0],[33771.43,0,0],[33942.8555,1,0],[34114.2852,3,0],[34200,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[34285.7148,3,0],[34457.14,3,0],[34628.57,1,0],[34971.43,2,0],[35314.2852,2,0],[35485.7148,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[35657.14,2,0],[35828.57,3,0],[36000,1,0],[36171.43,0,0],[36342.8555,2,0],[36514.2852,3,0],[36685.7148,0,0],[36857.14,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[37028.57,2,0],[37200,3,0],[37371.43,2,0],[37542.8555,0,0],[37714.2852,2,0],[37885.7148,3,0],[38057.14,0,0],[38228.57,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[38400,2,0],[38571.43,3,0],[38742.8555,1,0],[38914.2852,0,0],[39085.7148,2,0],[39257.14,3,0],[39428.57,0,0],[39600,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[39771.43,2,0],[39942.8555,3,0],[40114.2852,2,0],[40285.7148,0,0],[40457.14,2,0],[40628.57,3,0],[40800,0,0],[40971.43,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[41142.8555,2,0],[41314.2852,3,0],[41485.7148,1,0],[41657.14,0,0],[41828.57,2,0],[42000,3,0],[42171.43,0,0],[42342.8555,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[42514.2852,2,0],[42685.7148,3,0],[42857.14,2,0],[43028.57,0,0],[43200,2,0],[43371.43,3,0],[43542.8555,0,0],[43714.2852,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[43885.7148,2,0],[44057.14,3,0],[44228.57,1,0],[44400,0,0],[44571.43,2,0],[44742.8555,3,0],[44914.2852,0,0],[45085.7148,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[45257.14,2,0],[45428.57,3,0],[45600,2,0],[45771.43,0,0],[45942.8555,2,0],[46114.2852,3,0],[46285.7148,0,0],[46457.14,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[46628.57,2,0],[46800,3,0],[46971.43,1,0],[47142.8555,0,0],[47314.2852,2,0],[47485.7148,3,0],[47657.14,0,0],[47828.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[48000,2,0],[48171.43,3,0],[48342.8555,2,0],[48514.2852,0,0],[48685.7148,2,0],[48857.14,3,0],[49028.57,0,0],[49200,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[49371.43,2,0],[49542.8555,3,0],[49714.2852,1,0],[49885.7148,0,0],[50057.14,2,0],[50228.57,3,0],[50400,0,0],[50571.43,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[50742.8555,2,0],[50914.2852,3,0],[51085.7148,2,0],[51257.14,0,0],[51428.57,2,0],[51600,3,0],[51771.43,0,0],[51942.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[52114.2852,2,0],[52285.7148,3,0],[52457.14,1,0],[52628.57,0,0],[52800,2,0],[52971.43,3,0],[53142.8555,0,0],[53314.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[53485.7148,2,0],[53657.14,3,0],[53828.57,2,0],[54000,0,0],[54171.43,2,0],[54342.8555,3,0],[54514.2852,0,0],[54685.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[54857.14,2,0],[55028.57,3,0],[55200,1,0],[55371.43,0,0],[55542.8555,2,0],[55714.2852,3,0],[55885.7148,0,0],[56057.14,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[56228.57,2,0],[56400,3,0],[56571.43,2,0],[56742.8555,0,0],[56914.2852,2,0],[57085.7148,3,0],[57257.14,0,0],[57428.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[57600,3,0],[57771.43,3,0],[57942.8555,1,0],[58114.2852,1,0],[58285.7148,2,0],[58457.14,2,0],[58800,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[58971.43,2,0],[59142.8555,3,0],[59228.57,0,0],[59314.2852,3,0],[59485.7148,3,0],[59657.14,2,0],[59828.57,0,0],[60000,0,0],[60171.43,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[60342.8555,3,0],[60514.2852,3,0],[60600,0,0],[60685.7148,3,0],[60857.14,1,0],[61028.57,2,0],[61200,2,0],[61371.43,0,0],[61542.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[61714.2852,2,0],[61885.7148,3,0],[62057.14,0,0],[62228.57,3,0],[62400,2,0],[62742.8555,1,0],[62914.2852,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[63085.7148,3,0],[63257.14,3,0],[63428.57,1,0],[63600,1,0],[63771.43,2,0],[63942.8555,2,0],[64285.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[64457.14,2,0],[64628.57,3,0],[64714.2852,0,0],[64800,3,0],[64971.43,3,0],[65142.8555,2,0],[65314.2852,0,0],[65485.7148,0,0],[65657.14,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[65828.57,3,0],[66000,3,0],[66085.71,0,0],[66171.43,3,0],[66342.86,1,0],[66514.28,2,0],[66685.71,2,0],[66857.14,0,0],[67028.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[67200,2,0],[67371.43,3,0],[67542.86,0,0],[67714.28,3,0],[67885.71,2,0],[68228.57,1,0],[68400,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[68571.43,2,0],[68914.28,1,0],[69085.71,3,0],[69257.14,2,0],[69600,1,0],[69771.43,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[69942.86,0,0],[70114.28,3,0],[70285.71,1,0],[70457.14,3,0],[70628.57,2,0],[70971.43,2,0],[71142.86,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[71314.28,3,0],[71485.71,1,0],[71657.14,0,0],[71828.57,3,0],[72000,2,0],[72342.86,0,0],[72514.28,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[72685.71,3,0],[72857.14,3,0],[73028.57,2,0],[73200,0,0],[73371.43,2,0],[73542.86,3,0],[73714.28,0,0],[73885.71,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[74057.14,2,0],[74400,1,0],[74571.43,3,0],[74742.86,2,0],[75085.71,1,0],[75257.14,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[75428.57,0,0],[75600,3,0],[75771.43,1,0],[75942.86,3,0],[76114.28,2,0],[76457.14,2,0],[76628.57,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[76800,3,0],[76971.43,1,0],[77142.86,0,0],[77314.28,3,0],[77485.71,2,0],[77828.57,0,0],[78000,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[78171.43,3,0],[78342.86,3,0],[78514.28,2,0],[78685.71,0,0],[78857.14,2,0],[79028.57,3,0],[79200,0,0],[79371.43,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[79542.86,2,0],[79714.28,3,0],[79885.71,1,0],[80057.14,0,0],[80228.57,2,0],[80400,3,0],[80571.43,0,0],[80742.86,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[80914.28,2,0],[81085.71,3,0],[81257.14,2,0],[81428.57,0,0],[81600,2,0],[81771.43,3,0],[81942.86,0,0],[82114.28,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[82285.71,2,0],[82457.14,3,0],[82628.57,1,0],[82800,0,0],[82971.43,2,0],[83142.86,3,0],[83314.28,0,0],[83485.71,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[83657.14,2,0],[83828.57,3,0],[84000,2,0],[84171.43,0,0],[84342.86,2,0],[84514.28,3,0],[84685.71,0,0],[84857.14,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[85028.57,2,0],[85200,3,0],[85371.43,1,0],[85542.86,0,0],[85714.28,2,0],[85885.71,3,0],[86057.14,0,0],[86228.57,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[86400,2,0],[86571.43,3,0],[86742.86,2,0],[86914.28,0,0],[87085.71,2,0],[87257.14,3,0],[87428.57,0,0],[87600,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[87771.43,2,0],[87942.86,3,0],[88114.28,1,0],[88285.71,0,0],[88457.14,2,0],[88628.57,3,0],[88800,0,0],[88971.43,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[89142.86,2,0],[89314.28,3,0],[89485.71,2,0],[89657.14,0,0],[89828.57,2,0],[90000,3,0],[90171.43,0,0],[90342.86,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[90514.28,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"lengthInSteps":16,"altAnim":false,"typeOfSection":0,"sectionNotes":[],"bpm":175,"changeBPM":false,"mustHitSection":true}],"player2":"pico","song":"Philly","stage":"philly","needsVoices":true,"validScore":true,"bpm":175,"speed":2}}
\ No newline at end of file
+{"song":{"player1":"bf","notes":[{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[2914.28564,2,0],[3085.71436,0,0],[3428.57129,1,257.142853],[3771.42847,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[4285.71436,2,0],[4457.14258,0,0],[4800,1,257.142853],[5142.857,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[5657.14258,2,0],[5828.57129,0,0],[6171.42871,1,257.142853],[6514.28564,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[6857.14258,0,0],[7028.57129,3,0],[7200,2,0],[7542.857,2,0],[7885.71436,0,0],[8057.14258,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[8400,2,0],[8571.429,0,0],[8914.285,1,257.142853],[9257.143,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[9771.429,2,0],[9942.857,0,0],[10285.7139,1,257.142853],[10628.5713,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[11142.8574,2,0],[11314.2852,0,0],[11657.1426,1,257.142853],[12000,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[12342.8574,0,0],[12514.2852,3,0],[12685.7139,2,0],[13028.5713,2,0],[13371.4287,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[13885.7139,2,0],[14057.1426,0,0],[14400,0,0],[14742.8574,3,0],[14914.2852,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[15257.1426,3,0],[15428.5713,0,0],[15771.4287,2,0],[16114.2852,0,0],[16285.7139,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[16628.57,0,0],[16800,1,0],[16971.4277,3,0],[17142.8574,1,0],[17314.2852,0,0],[17485.7148,1,0],[17657.1426,3,0],[17742.8574,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[17828.57,3,0],[18000,3,0],[18171.4277,1,0],[18514.2852,2,0],[18857.1426,2,0],[19028.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[19371.4277,2,0],[19542.8574,0,0],[19885.7148,0,0],[20228.57,3,0],[20400,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[20742.8574,3,0],[20914.2852,0,0],[21257.1426,2,0],[21600,0,0],[21771.4277,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[22114.2852,0,0],[22285.7148,1,0],[22457.1426,3,0],[22628.57,1,0],[22800,0,0],[22971.4277,1,0],[23142.8574,3,0],[23228.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[23314.2852,3,0],[23485.7148,3,0],[23657.1426,1,0],[24000,2,0],[24342.8574,2,0],[24514.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[24685.7148,2,0],[24857.1426,2,0],[25028.57,0,0],[25371.4277,0,0],[25714.2852,3,0],[25885.7148,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[26228.57,3,0],[26400,0,0],[26742.8574,2,0],[27085.7148,0,0],[27257.1426,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[27600,0,0],[27771.4277,1,0],[27942.8574,3,0],[28114.2852,1,0],[28285.7148,0,0],[28457.1426,1,0],[28628.57,3,0],[28714.2852,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[28800,3,0],[28971.4277,3,0],[29142.8574,1,0],[29485.7148,2,0],[29828.57,2,0],[30000,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[30171.4277,2,0],[30342.8574,2,0],[30514.2852,0,0],[30857.1426,0,0],[31200,3,0],[31371.4277,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[31714.2852,3,0],[31885.7148,0,0],[32228.57,2,0],[32571.4277,0,0],[32742.8574,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[33085.7148,0,0],[33257.14,1,0],[33428.57,3,0],[33600,1,0],[33771.43,0,0],[33942.8555,1,0],[34114.2852,3,0],[34200,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[34285.7148,3,0],[34457.14,3,0],[34628.57,1,0],[34971.43,2,0],[35314.2852,2,0],[35485.7148,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[35657.14,2,0],[35828.57,3,0],[36000,1,0],[36171.43,0,0],[36342.8555,2,0],[36514.2852,3,0],[36685.7148,0,0],[36857.14,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[37028.57,2,0],[37200,3,0],[37371.43,2,0],[37542.8555,0,0],[37714.2852,2,0],[37885.7148,3,0],[38057.14,0,0],[38228.57,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[38400,2,0],[38571.43,3,0],[38742.8555,1,0],[38914.2852,0,0],[39085.7148,2,0],[39257.14,3,0],[39428.57,0,0],[39600,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[39771.43,2,0],[39942.8555,3,0],[40114.2852,2,0],[40285.7148,0,0],[40457.14,2,0],[40628.57,3,0],[40800,0,0],[40971.43,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[41142.8555,2,0],[41314.2852,3,0],[41485.7148,1,0],[41657.14,0,0],[41828.57,2,0],[42000,3,0],[42171.43,0,0],[42342.8555,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[42514.2852,2,0],[42685.7148,3,0],[42857.14,2,0],[43028.57,0,0],[43200,2,0],[43371.43,3,0],[43542.8555,0,0],[43714.2852,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[43885.7148,2,0],[44057.14,3,0],[44228.57,1,0],[44400,0,0],[44571.43,2,0],[44742.8555,3,0],[44914.2852,0,0],[45085.7148,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[45257.14,2,0],[45428.57,3,0],[45600,2,0],[45771.43,0,0],[45942.8555,2,0],[46114.2852,3,0],[46285.7148,0,0],[46457.14,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[46628.57,2,0],[46800,3,0],[46971.43,1,0],[47142.8555,0,0],[47314.2852,2,0],[47485.7148,3,0],[47657.14,0,0],[47828.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[48000,2,0],[48171.43,3,0],[48342.8555,2,0],[48514.2852,0,0],[48685.7148,2,0],[48857.14,3,0],[49028.57,0,0],[49200,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[49371.43,2,0],[49542.8555,3,0],[49714.2852,1,0],[49885.7148,0,0],[50057.14,2,0],[50228.57,3,0],[50400,0,0],[50571.43,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[50742.8555,2,0],[50914.2852,3,0],[51085.7148,2,0],[51257.14,0,0],[51428.57,2,0],[51600,3,0],[51771.43,0,0],[51942.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[52114.2852,2,0],[52285.7148,3,0],[52457.14,1,0],[52628.57,0,0],[52800,2,0],[52971.43,3,0],[53142.8555,0,0],[53314.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[53485.7148,2,0],[53657.14,3,0],[53828.57,2,0],[54000,0,0],[54171.43,2,0],[54342.8555,3,0],[54514.2852,0,0],[54685.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[54857.14,2,0],[55028.57,3,0],[55200,1,0],[55371.43,0,0],[55542.8555,2,0],[55714.2852,3,0],[55885.7148,0,0],[56057.14,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[56228.57,2,0],[56400,3,0],[56571.43,2,0],[56742.8555,0,0],[56914.2852,2,0],[57085.7148,3,0],[57257.14,0,0],[57428.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[57600,3,0],[57771.43,3,0],[57942.8555,1,0],[58114.2852,1,0],[58285.7148,2,0],[58457.14,2,0],[58800,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[58971.43,2,0],[59142.8555,3,0],[59228.57,0,0],[59314.2852,3,0],[59485.7148,3,0],[59657.14,2,0],[59828.57,0,0],[60000,0,0],[60171.43,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[60342.8555,3,0],[60514.2852,3,0],[60600,0,0],[60685.7148,3,0],[60857.14,1,0],[61028.57,2,0],[61200,2,0],[61371.43,0,0],[61542.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[61714.2852,2,0],[61885.7148,3,0],[62057.14,0,0],[62228.57,3,0],[62400,2,0],[62742.8555,1,0],[62914.2852,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[63085.7148,3,0],[63257.14,3,0],[63428.57,1,0],[63600,1,0],[63771.43,2,0],[63942.8555,2,0],[64285.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[64457.14,2,0],[64628.57,3,0],[64714.2852,0,0],[64800,3,0],[64971.43,3,0],[65142.8555,2,0],[65314.2852,0,0],[65485.7148,0,0],[65657.14,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[65828.57,3,0],[66000,3,0],[66085.71,0,0],[66171.43,3,0],[66342.86,1,0],[66514.28,2,0],[66685.71,2,0],[66857.14,0,0],[67028.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[67200,2,0],[67371.43,3,0],[67542.86,0,0],[67714.28,3,0],[67885.71,2,0],[68228.57,1,0],[68400,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[68571.43,2,0],[68914.28,1,0],[69085.71,3,0],[69257.14,2,0],[69600,1,0],[69771.43,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[69942.86,0,0],[70114.28,3,0],[70285.71,1,0],[70457.14,3,0],[70628.57,2,0],[70971.43,2,0],[71142.86,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[71314.28,3,0],[71485.71,1,0],[71657.14,0,0],[71828.57,3,0],[72000,2,0],[72342.86,0,0],[72514.28,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[72685.71,3,0],[72857.14,3,0],[73028.57,2,0],[73200,0,0],[73371.43,2,0],[73542.86,3,0],[73714.28,0,0],[73885.71,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[74057.14,2,0],[74400,1,0],[74571.43,3,0],[74742.86,2,0],[75085.71,1,0],[75257.14,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[75428.57,0,0],[75600,3,0],[75771.43,1,0],[75942.86,3,0],[76114.28,2,0],[76457.14,2,0],[76628.57,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[76800,3,0],[76971.43,1,0],[77142.86,0,0],[77314.28,3,0],[77485.71,2,0],[77828.57,0,0],[78000,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[78171.43,3,0],[78342.86,3,0],[78514.28,2,0],[78685.71,0,0],[78857.14,2,0],[79028.57,3,0],[79200,0,0],[79371.43,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[79542.86,2,0],[79714.28,3,0],[79885.71,1,0],[80057.14,0,0],[80228.57,2,0],[80400,3,0],[80571.43,0,0],[80742.86,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[80914.28,2,0],[81085.71,3,0],[81257.14,2,0],[81428.57,0,0],[81600,2,0],[81771.43,3,0],[81942.86,0,0],[82114.28,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[82285.71,2,0],[82457.14,3,0],[82628.57,1,0],[82800,0,0],[82971.43,2,0],[83142.86,3,0],[83314.28,0,0],[83485.71,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[83657.14,2,0],[83828.57,3,0],[84000,2,0],[84171.43,0,0],[84342.86,2,0],[84514.28,3,0],[84685.71,0,0],[84857.14,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[85028.57,2,0],[85200,3,0],[85371.43,1,0],[85542.86,0,0],[85714.28,2,0],[85885.71,3,0],[86057.14,0,0],[86228.57,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[86400,2,0],[86571.43,3,0],[86742.86,2,0],[86914.28,0,0],[87085.71,2,0],[87257.14,3,0],[87428.57,0,0],[87600,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[87771.43,2,0],[87942.86,3,0],[88114.28,1,0],[88285.71,0,0],[88457.14,2,0],[88628.57,3,0],[88800,0,0],[88971.43,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[89142.86,2,0],[89314.28,3,0],[89485.71,2,0],[89657.14,0,0],[89828.57,2,0],[90000,3,0],[90171.43,0,0],[90342.86,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[90514.28,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"lengthInSteps":16,"altAnim":false,"typeOfSection":0,"sectionNotes":[],"bpm":175,"changeBPM":false,"mustHitSection":true}],"player2":"pico","song":"Philly Nice","stage":"philly","needsVoices":true,"validScore":true,"bpm":175,"speed":2}}
\ No newline at end of file
diff --git a/assets/preload/data/philly/philly.json b/assets/preload/data/philly/philly.json
index 9d9d05c..a201a1e 100644
--- a/assets/preload/data/philly/philly.json
+++ b/assets/preload/data/philly/philly.json
@@ -1 +1 @@
-{"song":{"player1":"bf","notes":[{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[2914.28564,2,0],[3428.57129,1,257.142853],[3771.42847,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[4285.71436,2,0],[4800,1,257.142853],[5142.857,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[5657.14258,2,0],[6171.42871,1,257.142853],[6514.28564,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[6857.14258,0,0],[7542.857,2,0],[7885.71436,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[8400,2,0],[8914.285,1,257.142853],[9257.143,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[9771.429,2,0],[10285.7139,1,257.142853],[10628.5713,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[11142.8574,2,0],[11657.1426,1,257.142853],[12000,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[12342.8574,0,0],[12685.7139,2,0],[13028.5713,2,0],[13371.4287,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[14057.1426,2,0],[14400,0,0],[14742.8574,3,0],[14914.2852,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[15428.5713,3,0],[15771.4287,2,0],[16114.2852,0,0],[16285.7139,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[16628.57,0,0],[16800,3,0],[17142.8574,0,0],[17485.7148,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[17828.57,3,0],[18171.4277,1,0],[18514.2852,2,0],[18857.1426,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[19542.8574,2,0],[19885.7148,0,0],[20228.57,3,0],[20400,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[20914.2852,3,0],[21257.1426,2,0],[21600,0,0],[21771.4277,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[22114.2852,0,0],[22285.7148,3,0],[22628.57,0,0],[22971.4277,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[23314.2852,3,0],[23657.1426,1,0],[24000,2,0],[24342.8574,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[24685.7148,2,0],[24857.1426,2,0],[25028.57,2,0],[25371.4277,0,0],[25714.2852,3,0],[25885.7148,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[26400,3,0],[26742.8574,2,0],[27085.7148,0,0],[27257.1426,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[27600,0,0],[27771.4277,3,0],[27942.8574,3,0],[28114.2852,0,0],[28285.7148,0,0],[28457.1426,3,0],[28628.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[28800,3,0],[29142.8574,1,0],[29485.7148,2,0],[29828.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[30171.4277,2,0],[30342.8574,2,0],[30514.2852,2,0],[30857.1426,0,0],[31200,3,0],[31371.4277,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[31885.7148,3,0],[32228.57,2,0],[32571.4277,0,0],[32742.8574,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[33085.7148,0,0],[33257.14,3,0],[33428.57,3,0],[33600,0,0],[33771.43,0,0],[33942.8555,3,0],[34114.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[34285.7148,3,0],[34628.57,1,0],[34971.43,2,0],[35314.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[35657.14,2,0],[36342.8555,2,0],[36514.2852,3,0],[36685.7148,0,0],[36857.14,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[37028.57,2,0],[37714.2852,2,0],[37885.7148,3,0],[38057.14,0,0],[38228.57,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[38400,2,0],[39085.7148,2,0],[39257.14,3,0],[39428.57,0,0],[39600,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[39771.43,2,0],[40457.14,2,0],[40628.57,3,0],[40800,0,0],[40971.43,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[41142.8555,2,0],[41828.57,2,0],[42000,3,0],[42171.43,0,0],[42342.8555,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[42514.2852,2,0],[43200,2,0],[43371.43,3,0],[43542.8555,0,0],[43714.2852,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[43885.7148,2,0],[44571.43,2,0],[44742.8555,3,0],[44914.2852,0,0],[45085.7148,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[45257.14,2,0],[45942.8555,2,0],[46114.2852,3,0],[46285.7148,0,0],[46457.14,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[46628.57,2,0],[46971.43,1,0],[47314.2852,2,0],[47485.7148,3,0],[47657.14,0,0],[47828.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[48000,2,0],[48342.8555,2,0],[48685.7148,2,0],[48857.14,3,0],[49028.57,0,0],[49200,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[49371.43,2,0],[49714.2852,1,0],[50057.14,2,0],[50228.57,3,0],[50400,0,0],[50571.43,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[50742.8555,2,0],[51085.7148,2,0],[51428.57,2,0],[51600,3,0],[51771.43,0,0],[51942.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[52114.2852,2,0],[52457.14,1,0],[52800,2,0],[52971.43,3,0],[53142.8555,0,0],[53314.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[53485.7148,2,0],[53828.57,2,0],[54171.43,2,0],[54342.8555,3,0],[54514.2852,0,0],[54685.7148,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[54857.14,2,0],[55200,1,0],[55542.8555,2,0],[55714.2852,3,0],[55885.7148,0,0],[56057.14,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[56228.57,2,0],[56571.43,2,0],[56914.2852,2,0],[57085.7148,3,0],[57257.14,0,0],[57428.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[57600,3,0],[57942.8555,1,0],[58285.7148,2,0],[58800,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[58971.43,2,0],[59314.2852,3,0],[59657.14,2,0],[60171.43,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[60342.8555,3,0],[60685.7148,1,0],[61028.57,2,0],[61542.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[61714.2852,2,0],[62057.14,0,0],[62400,2,0],[62742.8555,0,0],[62914.2852,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[63085.7148,3,0],[63428.57,1,0],[63771.43,2,0],[64285.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[64457.14,2,0],[64800,3,0],[65142.8555,2,0],[65657.14,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[65828.57,3,0],[66171.43,1,0],[66514.28,2,0],[67028.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[67200,2,0],[67542.86,0,0],[67885.71,2,0],[68228.57,0,0],[68400,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[68571.43,2,0],[68914.28,1,0],[69257.14,2,0],[69600,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[69942.86,0,0],[70285.71,1,0],[70628.57,2,0],[70971.43,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[71314.28,3,0],[71657.14,0,0],[72000,2,0],[72342.86,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[72685.71,3,0],[73028.57,2,0],[73371.43,2,0],[73542.86,3,0],[73714.28,0,0],[73885.71,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[74057.14,2,0],[74400,1,0],[74742.86,2,0],[75085.71,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[75428.57,0,0],[75771.43,1,0],[76114.28,2,0],[76457.14,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[76800,3,0],[77142.86,0,0],[77485.71,2,0],[77828.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[78171.43,3,0],[78514.28,2,0],[78857.14,2,0],[79028.57,3,0],[79200,0,0],[79371.43,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[79542.86,2,0],[79885.71,1,0],[80228.57,2,0],[80400,3,0],[80571.43,0,0],[80742.86,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[80914.28,2,0],[81257.14,2,0],[81600,2,0],[81771.43,3,0],[81942.86,0,0],[82114.28,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[82285.71,2,0],[82628.57,1,0],[82971.43,2,0],[83142.86,3,0],[83314.28,0,0],[83485.71,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[83657.14,2,0],[84000,2,0],[84342.86,2,0],[84514.28,3,0],[84685.71,0,0],[84857.14,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[85028.57,2,0],[85371.43,1,0],[85714.28,2,0],[85885.71,3,0],[86057.14,0,0],[86228.57,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[86400,2,0],[86742.86,2,0],[87085.71,2,0],[87257.14,3,0],[87428.57,0,0],[87600,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[87771.43,2,0],[88114.28,1,0],[88457.14,2,0],[88628.57,3,0],[88800,0,0],[88971.43,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[89142.86,2,0],[89485.71,2,0],[89828.57,2,0],[90000,3,0],[90171.43,0,0],[90342.86,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[90514.28,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"lengthInSteps":16,"altAnim":false,"typeOfSection":0,"sectionNotes":[],"bpm":175,"changeBPM":false,"mustHitSection":true}],"player2":"pico","song":"Philly","stage":"philly","needsVoices":true,"validScore":true,"bpm":175,"speed":1.3}}
\ No newline at end of file
+{"song":{"player1":"bf","notes":[{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[2914.28564,2,0],[3428.57129,1,257.142853],[3771.42847,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[4285.71436,2,0],[4800,1,257.142853],[5142.857,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[5657.14258,2,0],[6171.42871,1,257.142853],[6514.28564,3,171.428574]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[6857.14258,0,0],[7542.857,2,0],[7885.71436,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[8400,2,0],[8914.285,1,257.142853],[9257.143,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[9771.429,2,0],[10285.7139,1,257.142853],[10628.5713,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[11142.8574,2,0],[11657.1426,1,257.142853],[12000,3,171.428574]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[12342.8574,0,0],[12685.7139,2,0],[13028.5713,2,0],[13371.4287,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[14057.1426,2,0],[14400,0,0],[14742.8574,3,0],[14914.2852,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[15428.5713,3,0],[15771.4287,2,0],[16114.2852,0,0],[16285.7139,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[16628.57,0,0],[16800,3,0],[17142.8574,0,0],[17485.7148,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[17828.57,3,0],[18171.4277,1,0],[18514.2852,2,0],[18857.1426,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[19542.8574,2,0],[19885.7148,0,0],[20228.57,3,0],[20400,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[20914.2852,3,0],[21257.1426,2,0],[21600,0,0],[21771.4277,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[22114.2852,0,0],[22285.7148,3,0],[22628.57,0,0],[22971.4277,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[23314.2852,3,0],[23657.1426,1,0],[24000,2,0],[24342.8574,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[24685.7148,2,0],[24857.1426,2,0],[25028.57,2,0],[25371.4277,0,0],[25714.2852,3,0],[25885.7148,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[26400,3,0],[26742.8574,2,0],[27085.7148,0,0],[27257.1426,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[27600,0,0],[27771.4277,3,0],[27942.8574,3,0],[28114.2852,0,0],[28285.7148,0,0],[28457.1426,3,0],[28628.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[28800,3,0],[29142.8574,1,0],[29485.7148,2,0],[29828.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[30171.4277,2,0],[30342.8574,2,0],[30514.2852,2,0],[30857.1426,0,0],[31200,3,0],[31371.4277,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[31885.7148,3,0],[32228.57,2,0],[32571.4277,0,0],[32742.8574,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[33085.7148,0,0],[33257.14,3,0],[33428.57,3,0],[33600,0,0],[33771.43,0,0],[33942.8555,3,0],[34114.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[34285.7148,3,0],[34628.57,1,0],[34971.43,2,0],[35314.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[35657.14,2,0],[36342.8555,2,0],[36514.2852,3,0],[36685.7148,0,0],[36857.14,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[37028.57,2,0],[37714.2852,2,0],[37885.7148,3,0],[38057.14,0,0],[38228.57,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[38400,2,0],[39085.7148,2,0],[39257.14,3,0],[39428.57,0,0],[39600,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[39771.43,2,0],[40457.14,2,0],[40628.57,3,0],[40800,0,0],[40971.43,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[41142.8555,2,0],[41828.57,2,0],[42000,3,0],[42171.43,0,0],[42342.8555,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[42514.2852,2,0],[43200,2,0],[43371.43,3,0],[43542.8555,0,0],[43714.2852,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[43885.7148,2,0],[44571.43,2,0],[44742.8555,3,0],[44914.2852,0,0],[45085.7148,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[45257.14,2,0],[45942.8555,2,0],[46114.2852,3,0],[46285.7148,0,0],[46457.14,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[46628.57,2,0],[46971.43,1,0],[47314.2852,2,0],[47485.7148,3,0],[47657.14,0,0],[47828.57,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[48000,2,0],[48342.8555,2,0],[48685.7148,2,0],[48857.14,3,0],[49028.57,0,0],[49200,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[49371.43,2,0],[49714.2852,1,0],[50057.14,2,0],[50228.57,3,0],[50400,0,0],[50571.43,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[50742.8555,2,0],[51085.7148,2,0],[51428.57,2,0],[51600,3,0],[51771.43,0,0],[51942.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[52114.2852,2,0],[52457.14,1,0],[52800,2,0],[52971.43,3,0],[53142.8555,0,0],[53314.2852,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[53485.7148,2,0],[53828.57,2,0],[54171.43,2,0],[54342.8555,3,0],[54514.2852,0,0],[54685.7148,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[54857.14,2,0],[55200,1,0],[55542.8555,2,0],[55714.2852,3,0],[55885.7148,0,0],[56057.14,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[56228.57,2,0],[56571.43,2,0],[56914.2852,2,0],[57085.7148,3,0],[57257.14,0,0],[57428.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[57600,3,0],[57942.8555,1,0],[58285.7148,2,0],[58800,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[58971.43,2,0],[59314.2852,3,0],[59657.14,2,0],[60171.43,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[60342.8555,3,0],[60685.7148,1,0],[61028.57,2,0],[61542.8555,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[61714.2852,2,0],[62057.14,0,0],[62400,2,0],[62742.8555,0,0],[62914.2852,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[63085.7148,3,0],[63428.57,1,0],[63771.43,2,0],[64285.7148,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[64457.14,2,0],[64800,3,0],[65142.8555,2,0],[65657.14,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[65828.57,3,0],[66171.43,1,0],[66514.28,2,0],[67028.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[67200,2,0],[67542.86,0,0],[67885.71,2,0],[68228.57,0,0],[68400,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[68571.43,2,0],[68914.28,1,0],[69257.14,2,0],[69600,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[69942.86,0,0],[70285.71,1,0],[70628.57,2,0],[70971.43,2,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[71314.28,3,0],[71657.14,0,0],[72000,2,0],[72342.86,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[72685.71,3,0],[73028.57,2,0],[73371.43,2,0],[73542.86,3,0],[73714.28,0,0],[73885.71,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[74057.14,2,0],[74400,1,0],[74742.86,2,0],[75085.71,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[75428.57,0,0],[75771.43,1,0],[76114.28,2,0],[76457.14,2,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[76800,3,0],[77142.86,0,0],[77485.71,2,0],[77828.57,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[78171.43,3,0],[78514.28,2,0],[78857.14,2,0],[79028.57,3,0],[79200,0,0],[79371.43,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[79542.86,2,0],[79885.71,1,0],[80228.57,2,0],[80400,3,0],[80571.43,0,0],[80742.86,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[80914.28,2,0],[81257.14,2,0],[81600,2,0],[81771.43,3,0],[81942.86,0,0],[82114.28,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[82285.71,2,0],[82628.57,1,0],[82971.43,2,0],[83142.86,3,0],[83314.28,0,0],[83485.71,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[83657.14,2,0],[84000,2,0],[84342.86,2,0],[84514.28,3,0],[84685.71,0,0],[84857.14,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[85028.57,2,0],[85371.43,1,0],[85714.28,2,0],[85885.71,3,0],[86057.14,0,0],[86228.57,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[86400,2,0],[86742.86,2,0],[87085.71,2,0],[87257.14,3,0],[87428.57,0,0],[87600,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[87771.43,2,0],[88114.28,1,0],[88457.14,2,0],[88628.57,3,0],[88800,0,0],[88971.43,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[89142.86,2,0],[89485.71,2,0],[89828.57,2,0],[90000,3,0],[90171.43,0,0],[90342.86,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[90514.28,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[],"lengthInSteps":16,"mustHitSection":true},{"lengthInSteps":16,"altAnim":false,"typeOfSection":0,"sectionNotes":[],"bpm":175,"changeBPM":false,"mustHitSection":true}],"player2":"pico","song":"Philly Nice","stage":"philly","needsVoices":true,"validScore":true,"bpm":175,"speed":1.3}}
\ No newline at end of file
diff --git a/assets/preload/images/KadeEngineLogo.png b/assets/preload/images/KadeEngineLogo.png
index 7a77f25..0576090 100644
Binary files a/assets/preload/images/KadeEngineLogo.png and b/assets/preload/images/KadeEngineLogo.png differ
diff --git a/assets/preload/images/KadeEngineLogoBumpin.png b/assets/preload/images/KadeEngineLogoBumpin.png
new file mode 100644
index 0000000..985ef07
Binary files /dev/null and b/assets/preload/images/KadeEngineLogoBumpin.png differ
diff --git a/assets/preload/images/KadeEngineLogoBumpin.xml b/assets/preload/images/KadeEngineLogoBumpin.xml
new file mode 100644
index 0000000..a8bcb24
--- /dev/null
+++ b/assets/preload/images/KadeEngineLogoBumpin.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/preload/images/KadeEngineLogoOld.png b/assets/preload/images/KadeEngineLogoOld.png
new file mode 100644
index 0000000..c262f5b
Binary files /dev/null and b/assets/preload/images/KadeEngineLogoOld.png differ
diff --git a/assets/preload/images/storymenu/week6.png b/assets/preload/images/storymenu/week6.png
deleted file mode 100644
index 8a45fb5..0000000
Binary files a/assets/preload/images/storymenu/week6.png and /dev/null differ
diff --git a/assets/preload/videos/daWeirdVid/dontDelete.webm b/assets/preload/videos/daWeirdVid/dontDelete.webm
new file mode 100644
index 0000000..c8865c7
Binary files /dev/null and b/assets/preload/videos/daWeirdVid/dontDelete.webm differ
diff --git a/assets/shared/images/characters/Monster_Assets.png b/assets/shared/images/characters/Monster_Assets.png
index 10b7bbe..7307545 100644
Binary files a/assets/shared/images/characters/Monster_Assets.png and b/assets/shared/images/characters/Monster_Assets.png differ
diff --git a/assets/shared/images/characters/Monster_Assets.xml b/assets/shared/images/characters/Monster_Assets.xml
index 687d294..37341d5 100644
--- a/assets/shared/images/characters/Monster_Assets.xml
+++ b/assets/shared/images/characters/Monster_Assets.xml
@@ -1,109 +1,109 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/songs/dad-battle/Inst.mp3 b/assets/songs/dadbattle/Inst.mp3
similarity index 100%
rename from assets/songs/dad-battle/Inst.mp3
rename to assets/songs/dadbattle/Inst.mp3
diff --git a/assets/songs/dad-battle/Inst.ogg b/assets/songs/dadbattle/Inst.ogg
similarity index 100%
rename from assets/songs/dad-battle/Inst.ogg
rename to assets/songs/dadbattle/Inst.ogg
diff --git a/assets/songs/dad-battle/Voices.mp3 b/assets/songs/dadbattle/Voices.mp3
similarity index 100%
rename from assets/songs/dad-battle/Voices.mp3
rename to assets/songs/dadbattle/Voices.mp3
diff --git a/assets/songs/dad-battle/Voices.ogg b/assets/songs/dadbattle/Voices.ogg
similarity index 100%
rename from assets/songs/dad-battle/Voices.ogg
rename to assets/songs/dadbattle/Voices.ogg
diff --git a/docs/_includes/header.html b/docs/_includes/header.html
index b5765cd..9780191 100644
--- a/docs/_includes/header.html
+++ b/docs/_includes/header.html
@@ -26,7 +26,7 @@ hr {
-
+
diff --git a/docs/building.md b/docs/building.md
index c44a23b..fa8d5a9 100644
--- a/docs/building.md
+++ b/docs/building.md
@@ -28,13 +28,28 @@
- `haxelib git faxe https://github.com/uhrobots/faxe`
- `haxelib git polymod https://github.com/larsiusprime/polymod.git`
- `haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc`
+ - `haxelib install actuate`
+ - `haxelib git extension-webm https://github.com/KadeDev/extension-webm`
+ - `lime rebuild extension-webm windows`
### Windows-only dependencies (only for building *to* Windows. Building html5 on Windows does not require this)
If you are planning to build for Windows, you also need to install **Visual Studio 2019**. While installing it, *don't click on any of the options to install workloads*. Instead, go to the **individual components** tab and choose the following:
-- MSVC v142 - VS 2019 C++ x64/x86 build tools
-- Windows SDK (10.0.19041.0)
-This will install about 4 GB of crap, but is necessary to build for Windows.
+- MSVC v142 - VS 2019 C++ x64/x86 build tools
+- Windows SDK (10.0.17763.0)
+- C++ Profiling tools
+- C++ CMake tools for windows
+- C++ ATL for v142 build tools (x86 & x64)
+- C++ MFC for v142 build tools (x86 & x64)
+- C++/CLI support for v142 build tools (14.21)
+- C++ Modules for v142 build tools (x64/x86)
+- Clang Compiler for Windows
+- Windows 10 SDK (10.0.17134.0)
+- Windows 10 SDK (10.0.16299.0)
+- MSVC v141 - VS 2017 C++ x64/x86 build tools
+- MSVC v140 - VS 2015 C++ build tools (v14.00)
+
+This will install about 22 GB of crap, but is necessary to build for Windows.
### macOS-only dependencies (these are required for building on macOS at all, including html5.)
If you are running macOS, you'll need to install Xcode. You can download it from the macOS App Store or from the [Xcode website](https://developer.apple.com/xcode/).
diff --git a/docs/changelogs/changelog-1.5.2.md b/docs/changelogs/changelog-1.5.2.md
new file mode 100644
index 0000000..a3de9ee
--- /dev/null
+++ b/docs/changelogs/changelog-1.5.2.md
@@ -0,0 +1,14 @@
+# Changelog for 1.5.2
+
+Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`.
+
+### Additions
+- [PR #786](https://github.com/KadeDev/Kade-Engine/pull/786): Add Acceleration, Drag and Velocity to X and Y for Actors in modcharts
+
+### Bugfixes
+- [PR #756](https://github.com/KadeDev/Kade-Engine/pull/756): Fix bugs with combo counter
+- 💖 PRs [#763](https://github.com/KadeDev/Kade-Engine/pull/763), [#789](https://github.com/KadeDev/Kade-Engine/pull/789): Fix bug where songs with spaces in the name would crash
+- Fix skipping notes for judgements
+
+## Links
+[GitHub Release](https://github.com/KadeDev/Kade-Engine/releases/tag/1.5.2) · [Last Windows CI build]() · [Last macOS CI build]() · [Last Linux CI build]()
diff --git a/docs/changelogs/changelog-1.5.3.md b/docs/changelogs/changelog-1.5.3.md
new file mode 100644
index 0000000..745f5c2
--- /dev/null
+++ b/docs/changelogs/changelog-1.5.3.md
@@ -0,0 +1,19 @@
+# Changelog for 1.5.3
+
+Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`.
+
+### Additions
+- Score Screen (💖)
+- Show your highest combo in the freeplay menu
+- New asset loading system (💖)
+- New Logo (💖)
+
+### Changes
+- Rewrote the entire hit ranking system (💖)
+
+### Bugfixes
+- NPS not showing if accuracy is disabled
+- Fixed song names so they don't crash (💖)
+
+## Links
+[GitHub Release](https://github.com/KadeDev/Kade-Engine/releases/tag/1.5.3) · [Last Windows CI build](https://ci.appveyor.com/project/KadeDev/kade-engine-windows/builds/39671466) · [Last macOS CI build](https://ci.appveyor.com/project/KadeDev/kade-engine-macos/builds/39671465) · [Last Linux CI build](https://ci.appveyor.com/project/KadeDev/kade-engine-linux/builds/39671464)
diff --git a/docs/changelogs/changelog-template.md b/docs/changelogs/changelog-template.md
index acf810d..7cd0515 100644
--- a/docs/changelogs/changelog-template.md
+++ b/docs/changelogs/changelog-template.md
@@ -1,4 +1,4 @@
-# Latest changelog/Changelog for 1.0.0
+# Latest (master) changelog/Changelog for 1.0.0
Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`.
diff --git a/docs/changelogs/index.md b/docs/changelogs/index.md
index 30d502f..38dc1b7 100644
--- a/docs/changelogs/index.md
+++ b/docs/changelogs/index.md
@@ -1,4 +1,8 @@
# Changelogs
- [Latest](latest) (Contains changes that are not in a release yet)
+- [1.5.3](changelog-1.5.3)
+- [1.5.2](changelog-1.5.2)
+- [1.5.1](changelog-1.5.1)
+- [1.5.0](changelog-1.5.0)
- [1.4.2 and before](changelog-pre)
diff --git a/docs/changelogs/latest.md b/docs/changelogs/latest.md
index 25c08bb..5d6ee6f 100644
--- a/docs/changelogs/latest.md
+++ b/docs/changelogs/latest.md
@@ -1 +1,12 @@
-# Latest changelog
+# Latest (master) changelog
+
+Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`.
+
+### Additions
+- Nothing yet!
+
+### Changes
+- Nothing yet!
+
+### Bugfixes
+- Nothing yet!
\ No newline at end of file
diff --git a/docs/modchart.md b/docs/modchart.md
index 3dc8309..20b9f65 100644
--- a/docs/modchart.md
+++ b/docs/modchart.md
@@ -1,483 +1,2 @@
-# Lua Modcharts
-
-In the 1.4.2 release of Kade Engine, we introduced Mod Charts. Mod Charts are a way of changing gameplay without hard coded values. This is achieved by using the Lua Scripting language to create script files that run during runtime.
-
-Song data is located in `assets/data//`, so the Lua file containing your scripts should be located at exactly `assets/data//modchart.lua`. (replace with the name of the song. for example, `assets/data/milf/` for milf)
-
-If the file doesn't exist, Lua code won't be ran.
-
-## Examples
-
-Full Example
-
-```lua
-function start (song)
- print("Song: " .. song .. " @ " .. bpm .. " downscroll: " .. downscroll)
-end
-
-
-function update (elapsed) -- example https://twitter.com/KadeDeveloper/status/1382178179184422918
- local currentBeat = (songPos / 1000)*(bpm/60)
- for i=0,7 do
- setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i)
- setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i)
- end
-end
-
-function beatHit (beat)
- -- do nothing
-end
-
-function stepHit (step)
- -- do nothing
-end
-
-function keyPressed (key)
- -- do nothing
-end
-
-print("Mod Chart script loaded :)")
-```
-
-Spinning Receptor Example
-
-```lua
-function update (elapsed)
- for i=0,7 do
- setActorAngle(getActorAngle(i) + 15, i)
- end
-end
-```
-
-Spinning Hud Example
-
-```lua
-function update (elapsed)
- camHudAngle = camHudAngle + 0.005
-end
-```
-
-Spin at a specific part of the song
-
-```lua
-function update (elapsed)
- if curStep >= 352 and curStep < 400 then
- local currentBeat = (songPos / 1000)*(bpm/60)
- for i=0,7 do
- setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i)
- setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i)
- end
- else
- for i=0,7 do
- setActorX(_G['defaultStrum'..i..'X'],i)
- setActorY(_G['defaultStrum'..i..'Y'],i)
- end
- end
-end
-```
-
-Showing/Hiding receptors/the hud
-
-```lua
-function start (song)
- showOnlyStrums = true -- remove all hud elements besides notes and strums
- for i=0,3 do -- fade out the first 4 receptors (the ai receptors)
- tweenFadeIn(i,0,0.6)
- end
-end
-```
-
-Looping through all of the rendered notes
-
-```lua
-for i = 0, getRenderedNotes() do -- sets all of the rendered notes to 0 0 on the x and y axsis
- setRenderedNotePos(0,0,i)
-end
-```
-
-Centering BF's Side
-
-```lua
-function setDefault(id)
- _G['defaultStrum'..id..'X'] = getActorX(id)
-end
-
--- put this somewhere in a function
-
-for i = 4, 7 do -- go to the center
- tweenPosXAngle(i, _G['defaultStrum'..i..'X'] - 275,getActorAngle(i) + 360, 0.6, 'setDefault')
-end
-```
-
-
-### Available Hooks
-
-Current calls to functions include,
-
-| Name | Arguments | Description |
-| :-----: | :------------: | :----------------------------------------------------------: |
-| start | Song Name | Gets called when the song starts |
-| update | Elapsed frames | Gets called every frame (after the song starts) |
-| stepHit | Current Step | Gets called when ever a step hits (steps are in between beats, aka 4 steps are in a beat) |
-| beatHit | Current Beat | Gets called when ever a beat hits |
-| keyPressed | Key Pressed | Gets called when a key just got pressed (up, down, left, right, accept) |
-
-
-
-### Global Variables
-
-Kade Engine provides a list of global variables to be used in the lua scripting interface.
-
-| G Name | Type | Description |
-| :------------------: | :---: | :----------------------------------------------------------: |
-| bpm | Float | The current BPM of the song |
-| fpsCap | Int | The current FPS Cap (set by the player) |
-| downscroll | Bool | Whether the player is in downscroll or not |
-| cameraAngle | Float | The angle that the Main Camera should be rotated |
-| camHudAngle | Float | The angle that the Hud should be rotated |
-| followXOffset | Float | The x offset to be added when the camera moves between a character |
-| followYOffset | Float | The y offset to be added when the camera moves between a character |
-| showOnlyStrums | Bool | Whether to show the Hud and Strums or only the Strums |
-| strumLine1Visible | Bool | Whether to show the first strum line or not |
-| strumLine2Visible | Bool | Whether to show the secondstrum line or not |
-| defaultStrum0-7X | Float | (0-7 is strum0,strum1,strum2,etc) get the default X coordinate for the strum |
-| defaultStrum0-7Y | Float | (0-7 is strum0,strum1,strum2,etc) get the default Y coordinate for the strum |
-| defaultStrum0-7Angle | Float | (0-7 is strum0,strum1,strum2,etc) get the default Angle for the strum |
-| screenWidth | Int | The width of the current gamespace |
-| screenHeight | Int | The height of the current gamespace |
-| hudWidth | Int | The width of the hud |
-| hudHeight | Int | The height of the hud |
-| scrollSpeed | Int | The current scrollspeed |
-| mustHit | Bool | If the current section is a must hit section |
-| strumLineY | Float | The current Strum Line Y Position |
-
-## Functions
-
-Kade Engine exposes a lot of functions that let you modify elements in the game field.
-
-
-
-To get started every sprite has an id, and there are some id's that are accessible without creating one.
-
-These premade id's are the following:
-
-| Sprite Id | Value |
-| :--------: | :--------------------------------------: |
-| 0-7 | Represents Receptor 0-7 |
-| boyfriend | Represents the Boyfriend Actor (player1) |
-| dad | Represents the Dad Actor (player2) |
-| girlfriend | Represents the Girlfriend Actor |
-
-
-
-### Sprites
-
-##### makeSprite(string SpritePath,string SpriteId,bool DrawBehind)
-
-Creates a sprite out of the specified image, returns the id you gave it.
-
-*Note: Sprite Path is normally the FILE NAME so if your file is named `Image` it'll go to assets/data/songName/Image.png so don't include the extension*
-
-### Hud/Camera
-
-##### setHudPosition(int x, int y)
-
-Sets the game hud's position in space.
-
-##### getHudX()
-
-Returns the hud's x position
-
-##### getHudY()
-
-Returns the hud's y position
-
-##### setCamPosition(int x, int y)
-
-Set's the current camera's position in space
-
-##### getCameraX()
-
-Returns the current camera's x position
-
-##### getCameraY()
-
-Returns the current camera's y position
-
-##### setCamZoom(float zoomAmount)
-
-Set's the current camera's zoom
-
-##### setHudZoom(float zoomAmount)
-
-Set's the hud's zoom
-
-### Strumline
-
-##### setStrumlineY(float y)
-
-Set's the y position of the strumLine
-
-### Actors
-
-##### getRenderedNotes()
-
-Returns the amount of rendered notes.
-
-##### getRenderedNoteX(int id)
-
-Returns the x position of the rendered note id
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteY(int id)
-
-Returns the y position of the rendered note id
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteScaleX(int id)
-
-Returns the scale x of the rendered note id
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteScaleY(int id)
-
-Returns the scale y of the rendered note id
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteType(int id)
-
-Returns the note data of an note (0-3, left, down, up, right)
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteHit(int id)
-
-Returns whether a rendered note must be hit by the player or not
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### isSustain(int id)
-
-Returns whether a rendered note is a sustain note or not (if they appear as the trail)
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### isParentSustain(int id)
-
-Returns whether a rendered note's parrent is a sustain note or not (if they appear as the trail)
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteParentX(int id)
-
-Returns the current parent x of the specified rendered note's id
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteParentY(int id)
-
-Returns the current parent y of the specified rendered note's id
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteCalcX(int id)
-
-Returns what the game would normally put the specified rendered note x.
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### anyNotes()
-
-Returns true if there are rendered notes, and returns false if there are none
-
-##### getRenderedNoteStrumtime(int id)
-
-Returns strum time of the rendered note.
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteAlpha(int id)
-
-Returns the alpha of the rendered note id
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteWidth(int id)
-
-Returns the width of the specified rendered note.
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### getRenderedNoteAngle(int id)
-
-Returns the angle of the specified rendered note.
-
-*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
-
-##### setRenderedNotePos(int x, int y, int id)
-
-Set's the position of the rendered note id
-
-*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
-
-##### setRenderedNoteAlpha(float alpha, int id)
-
-Set's the alpha of the rendered note id
-
-*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
-
-##### setRenderedNoteScale(float scale, int id)
-
-Set's the scale of the rendered note id
-
-*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
-
-##### setRenderedNoteScaleX(float scale, int id) **Currently broken**
-
-Set's the scale x of the rendered note id
-
-*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
-
-##### setRenderedNoteScaleY(float scale, int id) **Currently broken**
-
-Set's the scale y of the rendered note id
-
-*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
-
-##### getActorX(string/int id)
-
-Returns the x position for the sprite id
-
-##### getActorY(string/int id)
-
-Returns the y position for the sprite id
-
-##### getActorScaleX(string/int id)
-
-Returns the scale x for the sprite id
-
-##### getActorScaleY(string/int id)
-
-Returns the scale y for the sprite id
-
-##### getActorAlpha(string/int id)
-
-Returns the alpha for the sprite id
-
-##### getActorAngle(string/int id)
-
-Returns the angle for the sprite id
-
-##### setActorX(int x, string/int id)
-
-Set's the x position for the sprite id
-
-##### setActorY(int y, string/int id)
-
-Set's the y position for the sprite id
-
-##### setActorAlpha(float alpha, string/int id)
-
-Set's the alpha for the sprite id
-
-##### setActorAngle(int alpha, string/int id)
-
-Set's the angle for the sprite id
-
-##### setActorScale(float scale, string/int id)
-
-Set's the scale for the sprite id
-
-##### setActorScaleXY(float scaleX, float scaleY, string/int id)
-
-Set's the x and y scale for the sprite id
-
-##### setActorFlipX(bool flip, string/int id)
-
-Set's the x flip for the sprite id
-
-##### setActorFlipY(bool flip, string/int id)
-
-Set's the y flip for the sprite id
-
-##### getActorWidth(string/int id)
-
-Returns the width for the sprite id
-
-##### getActorHeight(string/int id)
-
-Returns the height for the sprite id
-
-##### changeBoyfriendCharacter(string id)
-
-Changes the Boyfriend sprite to another character
-
-##### changeDadCharacter(string id)
-
-Changes the Dad sprite to another character
-
-##### playActorAnimation(string/int id, string anim, bool force, bool reverse)
-
-Plays an animation on a sprite
-
-### Tweens
-
-*Note, On Complete functions are based by the function name (and they also well get called when the tween completes)*
-
-##### tweenPos(string/int id, int toX, int toY, float time, string onComplete)
-
-Smoothly tween into a x and y position
-
-##### tweenPosXAngle(string/int id, int toX, float toAngle, float time, string onComplete)
-
-Smoothly tween into a x position and angle
-
-##### tweenPosYAngle(string/int id, int toY, float toAngle, float time, string onComplete)
-
-Smoothly tween into a y position and angle
-
-##### tweenAngle(string/int id, float toAngle, float time, string onComplete)
-
-Smoothly tween into a angle
-
-##### tweenFadeIn(string/int id, float toAlpha, float time, string onComplete)
-
-Smoothly fade in to an alpha
-
-##### tweenFadeOut(string/int id, float toAlpha, float time, string onComplete)
-
-Smoothly fade out to an alpha
-
-
-
-
-
-### Window & Screen
-
-##### getWindowX()
-
-Returns the window's x position
-
-##### getWindowY()
-
-Returns the window's y position
-
-##### getScreenWidth()
-
-Returns the width of the screen
-
-##### getScreenHeight()
-
-Returns the height of the screen
-
-##### setWindowPos(int x, int y)
-
-Sets the window's position
-
-##### resizeWindow(int width, int height)
-
-Resizes the window
+### RELOCATED
+Relocated to [here](https://github.com/KadeDev/Kade-Engine/wiki/)
diff --git a/source - Copy/APIStuff.hx b/source - Copy/APIStuff.hx
new file mode 100644
index 0000000..f05fa06
--- /dev/null
+++ b/source - Copy/APIStuff.hx
@@ -0,0 +1,7 @@
+package;
+
+class APIStuff
+{
+ public static var API:String = "";
+ public static var EncKey:String = "";
+}
diff --git a/source - Copy/Alphabet.hx b/source - Copy/Alphabet.hx
new file mode 100644
index 0000000..56d07e2
--- /dev/null
+++ b/source - Copy/Alphabet.hx
@@ -0,0 +1,358 @@
+package;
+
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxSpriteGroup;
+import flixel.math.FlxMath;
+import flixel.util.FlxTimer;
+
+using StringTools;
+
+/**
+ * Loosley based on FlxTypeText lolol
+ */
+class Alphabet extends FlxSpriteGroup
+{
+ public var delay:Float = 0.05;
+ public var paused:Bool = false;
+
+ // for menu shit
+ public var targetY:Float = 0;
+ public var isMenuItem:Bool = false;
+
+ public var text:String = "";
+
+ var _finalText:String = "";
+ var _curText:String = "";
+
+ public var widthOfWords:Float = FlxG.width;
+
+ var yMulti:Float = 1;
+
+ // custom shit
+ // amp, backslash, question mark, apostrophy, comma, angry faic, period
+ var lastSprite:AlphaCharacter;
+ var xPosResetted:Bool = false;
+ var lastWasSpace:Bool = false;
+
+ var listOAlphabets:List = new List();
+
+ var splitWords:Array = [];
+
+ var isBold:Bool = false;
+
+ public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false, shouldMove:Bool = false)
+ {
+ super(x, y);
+
+ _finalText = text;
+ this.text = text;
+ isBold = bold;
+
+ if (text != "")
+ {
+ if (typed)
+ {
+ startTypedText();
+ }
+ else
+ {
+ addText();
+ }
+
+ }
+ }
+
+ public function addText()
+ {
+ doSplitWords();
+
+ var xPos:Float = 0;
+ for (character in splitWords)
+ {
+ // if (character.fastCodeAt() == " ")
+ // {
+ // }
+
+ if (character == " " || character == "-")
+ {
+ lastWasSpace = true;
+ }
+
+ if (AlphaCharacter.alphabet.indexOf(character.toLowerCase()) != -1)
+ // if (AlphaCharacter.alphabet.contains(character.toLowerCase()))
+ {
+ if (lastSprite != null)
+ {
+ xPos = lastSprite.x + lastSprite.width;
+ }
+
+ if (lastWasSpace)
+ {
+ xPos += 40;
+ lastWasSpace = false;
+ }
+
+ // var letter:AlphaCharacter = new AlphaCharacter(30 * loopNum, 0);
+ var letter:AlphaCharacter = new AlphaCharacter(xPos, 0);
+ listOAlphabets.add(letter);
+
+ if (isBold)
+ letter.createBold(character);
+ else
+ {
+ letter.createLetter(character);
+ }
+
+ add(letter);
+
+ lastSprite = letter;
+ }
+
+ // loopNum += 1;
+ }
+ }
+
+ function doSplitWords():Void
+ {
+ splitWords = _finalText.split("");
+ }
+
+ public var personTalking:String = 'gf';
+
+ public function startTypedText():Void
+ {
+ _finalText = text;
+ doSplitWords();
+
+ // trace(arrayShit);
+
+ var loopNum:Int = 0;
+
+ var xPos:Float = 0;
+ var curRow:Int = 0;
+
+ new FlxTimer().start(0.05, function(tmr:FlxTimer)
+ {
+ // trace(_finalText.fastCodeAt(loopNum) + " " + _finalText.charAt(loopNum));
+ if (_finalText.fastCodeAt(loopNum) == "\n".code)
+ {
+ yMulti += 1;
+ xPosResetted = true;
+ xPos = 0;
+ curRow += 1;
+ }
+
+ if (splitWords[loopNum] == " ")
+ {
+ lastWasSpace = true;
+ }
+
+ #if (haxe >= "4.0.0")
+ var isNumber:Bool = AlphaCharacter.numbers.contains(splitWords[loopNum]);
+ var isSymbol:Bool = AlphaCharacter.symbols.contains(splitWords[loopNum]);
+ #else
+ var isNumber:Bool = AlphaCharacter.numbers.indexOf(splitWords[loopNum]) != -1;
+ var isSymbol:Bool = AlphaCharacter.symbols.indexOf(splitWords[loopNum]) != -1;
+ #end
+
+ if (AlphaCharacter.alphabet.indexOf(splitWords[loopNum].toLowerCase()) != -1 || isNumber || isSymbol)
+ // if (AlphaCharacter.alphabet.contains(splitWords[loopNum].toLowerCase()) || isNumber || isSymbol)
+
+ {
+ if (lastSprite != null && !xPosResetted)
+ {
+ lastSprite.updateHitbox();
+ xPos += lastSprite.width + 3;
+ // if (isBold)
+ // xPos -= 80;
+ }
+ else
+ {
+ xPosResetted = false;
+ }
+
+ if (lastWasSpace)
+ {
+ xPos += 20;
+ lastWasSpace = false;
+ }
+ // trace(_finalText.fastCodeAt(loopNum) + " " + _finalText.charAt(loopNum));
+
+ // var letter:AlphaCharacter = new AlphaCharacter(30 * loopNum, 0);
+ var letter:AlphaCharacter = new AlphaCharacter(xPos, 55 * yMulti);
+ listOAlphabets.add(letter);
+ letter.row = curRow;
+ if (isBold)
+ {
+ letter.createBold(splitWords[loopNum]);
+ }
+ else
+ {
+ if (isNumber)
+ {
+ letter.createNumber(splitWords[loopNum]);
+ }
+ else if (isSymbol)
+ {
+ letter.createSymbol(splitWords[loopNum]);
+ }
+ else
+ {
+ letter.createLetter(splitWords[loopNum]);
+ }
+
+ letter.x += 90;
+ }
+
+ if (FlxG.random.bool(40))
+ {
+ var daSound:String = "GF_";
+ FlxG.sound.play(Paths.soundRandom(daSound, 1, 4));
+ }
+
+ add(letter);
+
+ lastSprite = letter;
+ }
+
+ loopNum += 1;
+
+ tmr.time = FlxG.random.float(0.04, 0.09);
+ }, splitWords.length);
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (isMenuItem)
+ {
+ var scaledY = FlxMath.remapToRange(targetY, 0, 1, 0, 1.3);
+
+ y = FlxMath.lerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.30);
+ x = FlxMath.lerp(x, (targetY * 20) + 90, 0.30);
+ }
+
+ super.update(elapsed);
+ }
+}
+
+class AlphaCharacter extends FlxSprite
+{
+ public static var alphabet:String = "abcdefghijklmnopqrstuvwxyz";
+
+ public static var numbers:String = "1234567890";
+
+ public static var symbols:String = "|~#$%()*+-:;<=>@[]^_.,'!? ";
+
+ public var row:Int = 0;
+
+ public function new(x:Float, y:Float)
+ {
+ super(x, y);
+ var tex = Paths.getSparrowAtlas('alphabet');
+ frames = tex;
+
+ antialiasing = true;
+ }
+
+ public function createBold(letter:String)
+ {
+ animation.addByPrefix(letter, letter.toUpperCase() + " bold", 24);
+ animation.play(letter);
+ updateHitbox();
+ }
+
+ public function createLetter(letter:String):Void
+ {
+ var letterCase:String = "lowercase";
+ if (letter.toLowerCase() != letter)
+ {
+ letterCase = 'capital';
+ }
+
+ animation.addByPrefix(letter, letter + " " + letterCase, 24);
+ animation.play(letter);
+ updateHitbox();
+
+ FlxG.log.add('the row' + row);
+
+ y = (110 - height);
+ y += row * 60;
+ }
+
+ public function createNumber(letter:String):Void
+ {
+ animation.addByPrefix(letter, letter, 24);
+ animation.play(letter);
+
+ updateHitbox();
+ }
+
+ public function createSymbol(letter:String)
+ {
+ switch (letter)
+ {
+ case '.':
+ animation.addByPrefix(letter, 'period', 24);
+ animation.play(letter);
+ y += 50;
+ case "'":
+ animation.addByPrefix(letter, 'apostraphie', 24);
+ animation.play(letter);
+ y -= 0;
+ case "?":
+ animation.addByPrefix(letter, 'question mark', 24);
+ animation.play(letter);
+ case "!":
+ animation.addByPrefix(letter, 'exclamation point', 24);
+ animation.play(letter);
+ case '_':
+ animation.addByPrefix(letter, '_', 24);
+ animation.play(letter);
+ y += 50;
+ case "#":
+ animation.addByPrefix(letter, '#', 24);
+ animation.play(letter);
+ case "$":
+ animation.addByPrefix(letter, '$', 24);
+ animation.play(letter);
+ case "%":
+ animation.addByPrefix(letter, '%', 24);
+ animation.play(letter);
+ case "&":
+ animation.addByPrefix(letter, '&', 24);
+ animation.play(letter);
+ case "(":
+ animation.addByPrefix(letter, '(', 24);
+ animation.play(letter);
+ case ")":
+ animation.addByPrefix(letter, ')', 24);
+ animation.play(letter);
+ case "+":
+ animation.addByPrefix(letter, '+', 24);
+ animation.play(letter);
+ case "-":
+ animation.addByPrefix(letter, '-', 24);
+ animation.play(letter);
+ case '"':
+ animation.addByPrefix(letter, '"', 24);
+ animation.play(letter);
+ y -= 0;
+ case '@':
+ animation.addByPrefix(letter, '@', 24);
+ animation.play(letter);
+ case "^":
+ animation.addByPrefix(letter, '^', 24);
+ animation.play(letter);
+ y -= 0;
+ case ' ':
+ animation.addByPrefix(letter, 'space', 24);
+ animation.play(letter);
+ }
+
+ updateHitbox();
+ }
+}
diff --git a/source - Copy/AnimationDebug.hx b/source - Copy/AnimationDebug.hx
new file mode 100644
index 0000000..05b40d6
--- /dev/null
+++ b/source - Copy/AnimationDebug.hx
@@ -0,0 +1,195 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxObject;
+import flixel.FlxSprite;
+import flixel.FlxState;
+import flixel.addons.display.FlxGridOverlay;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.text.FlxText;
+import flixel.util.FlxColor;
+
+/**
+ *DEBUG MODE
+ */
+class AnimationDebug extends FlxState
+{
+ var bf:Boyfriend;
+ var dad:Character;
+ var char:Character;
+ var textAnim:FlxText;
+ var dumbTexts:FlxTypedGroup;
+ var animList:Array = [];
+ var curAnim:Int = 0;
+ var isDad:Bool = true;
+ var daAnim:String = 'spooky';
+ var camFollow:FlxObject;
+
+ public function new(daAnim:String = 'spooky')
+ {
+ super();
+ this.daAnim = daAnim;
+ }
+
+ override function create()
+ {
+ FlxG.sound.music.stop();
+
+ var gridBG:FlxSprite = FlxGridOverlay.create(10, 10);
+ gridBG.scrollFactor.set(0.5, 0.5);
+ add(gridBG);
+
+ if (daAnim == 'bf')
+ isDad = false;
+
+ if (isDad)
+ {
+ dad = new Character(0, 0, daAnim);
+ dad.screenCenter();
+ dad.debugMode = true;
+ add(dad);
+
+ char = dad;
+ dad.flipX = false;
+ }
+ else
+ {
+ bf = new Boyfriend(0, 0);
+ bf.screenCenter();
+ bf.debugMode = true;
+ add(bf);
+
+ char = bf;
+ bf.flipX = false;
+ }
+
+ dumbTexts = new FlxTypedGroup();
+ add(dumbTexts);
+
+ textAnim = new FlxText(300, 16);
+ textAnim.size = 26;
+ textAnim.scrollFactor.set();
+ add(textAnim);
+
+ genBoyOffsets();
+
+ camFollow = new FlxObject(0, 0, 2, 2);
+ camFollow.screenCenter();
+ add(camFollow);
+
+ FlxG.camera.follow(camFollow);
+
+ super.create();
+ }
+
+ function genBoyOffsets(pushList:Bool = true):Void
+ {
+ var daLoop:Int = 0;
+
+ for (anim => offsets in char.animOffsets)
+ {
+ var text:FlxText = new FlxText(10, 20 + (18 * daLoop), 0, anim + ": " + offsets, 15);
+ text.scrollFactor.set();
+ text.color = FlxColor.BLUE;
+ dumbTexts.add(text);
+
+ if (pushList)
+ animList.push(anim);
+
+ daLoop++;
+ }
+ }
+
+ function updateTexts():Void
+ {
+ dumbTexts.forEach(function(text:FlxText)
+ {
+ text.kill();
+ dumbTexts.remove(text, true);
+ });
+ }
+
+ override function update(elapsed:Float)
+ {
+ textAnim.text = char.animation.curAnim.name;
+
+ if (FlxG.keys.justPressed.E)
+ FlxG.camera.zoom += 0.25;
+ if (FlxG.keys.justPressed.Q)
+ FlxG.camera.zoom -= 0.25;
+
+ if (FlxG.keys.pressed.I || FlxG.keys.pressed.J || FlxG.keys.pressed.K || FlxG.keys.pressed.L)
+ {
+ if (FlxG.keys.pressed.I)
+ camFollow.velocity.y = -90;
+ else if (FlxG.keys.pressed.K)
+ camFollow.velocity.y = 90;
+ else
+ camFollow.velocity.y = 0;
+
+ if (FlxG.keys.pressed.J)
+ camFollow.velocity.x = -90;
+ else if (FlxG.keys.pressed.L)
+ camFollow.velocity.x = 90;
+ else
+ camFollow.velocity.x = 0;
+ }
+ else
+ {
+ camFollow.velocity.set();
+ }
+
+ if (FlxG.keys.justPressed.W)
+ {
+ curAnim -= 1;
+ }
+
+ if (FlxG.keys.justPressed.S)
+ {
+ curAnim += 1;
+ }
+
+ if (curAnim < 0)
+ curAnim = animList.length - 1;
+
+ if (curAnim >= animList.length)
+ curAnim = 0;
+
+ if (FlxG.keys.justPressed.S || FlxG.keys.justPressed.W || FlxG.keys.justPressed.SPACE)
+ {
+ char.playAnim(animList[curAnim]);
+
+ updateTexts();
+ genBoyOffsets(false);
+ }
+
+ var upP = FlxG.keys.anyJustPressed([UP]);
+ var rightP = FlxG.keys.anyJustPressed([RIGHT]);
+ var downP = FlxG.keys.anyJustPressed([DOWN]);
+ var leftP = FlxG.keys.anyJustPressed([LEFT]);
+
+ var holdShift = FlxG.keys.pressed.SHIFT;
+ var multiplier = 1;
+ if (holdShift)
+ multiplier = 10;
+
+ if (upP || rightP || downP || leftP)
+ {
+ updateTexts();
+ if (upP)
+ char.animOffsets.get(animList[curAnim])[1] += 1 * multiplier;
+ if (downP)
+ char.animOffsets.get(animList[curAnim])[1] -= 1 * multiplier;
+ if (leftP)
+ char.animOffsets.get(animList[curAnim])[0] += 1 * multiplier;
+ if (rightP)
+ char.animOffsets.get(animList[curAnim])[0] -= 1 * multiplier;
+
+ updateTexts();
+ genBoyOffsets(false);
+ char.playAnim(animList[curAnim]);
+ }
+
+ super.update(elapsed);
+ }
+}
diff --git a/source - Copy/BackgroundDancer.hx b/source - Copy/BackgroundDancer.hx
new file mode 100644
index 0000000..c572c1e
--- /dev/null
+++ b/source - Copy/BackgroundDancer.hx
@@ -0,0 +1,30 @@
+package;
+
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+
+class BackgroundDancer extends FlxSprite
+{
+ public function new(x:Float, y:Float)
+ {
+ super(x, y);
+
+ frames = Paths.getSparrowAtlas("limo/limoDancer",'week4');
+ animation.addByIndices('danceLeft', 'bg dancer sketch PINK', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
+ animation.addByIndices('danceRight', 'bg dancer sketch PINK', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
+ animation.play('danceLeft');
+ antialiasing = true;
+ }
+
+ var danceDir:Bool = false;
+
+ public function dance():Void
+ {
+ danceDir = !danceDir;
+
+ if (danceDir)
+ animation.play('danceRight', true);
+ else
+ animation.play('danceLeft', true);
+ }
+}
diff --git a/source - Copy/BackgroundGirls.hx b/source - Copy/BackgroundGirls.hx
new file mode 100644
index 0000000..8a84699
--- /dev/null
+++ b/source - Copy/BackgroundGirls.hx
@@ -0,0 +1,39 @@
+package;
+
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+
+class BackgroundGirls extends FlxSprite
+{
+ public function new(x:Float, y:Float)
+ {
+ super(x, y);
+
+ // BG fangirls dissuaded
+ frames = Paths.getSparrowAtlas('weeb/bgFreaks','week6');
+
+ animation.addByIndices('danceLeft', 'BG girls group', CoolUtil.numberArray(14), "", 24, false);
+ animation.addByIndices('danceRight', 'BG girls group', CoolUtil.numberArray(30, 15), "", 24, false);
+
+ animation.play('danceLeft');
+ }
+
+ var danceDir:Bool = false;
+
+ public function getScared():Void
+ {
+ animation.addByIndices('danceLeft', 'BG fangirls dissuaded', CoolUtil.numberArray(14), "", 24, false);
+ animation.addByIndices('danceRight', 'BG fangirls dissuaded', CoolUtil.numberArray(30, 15), "", 24, false);
+ dance();
+ }
+
+ public function dance():Void
+ {
+ danceDir = !danceDir;
+
+ if (danceDir)
+ animation.play('danceRight', true);
+ else
+ animation.play('danceLeft', true);
+ }
+}
diff --git a/source - Copy/BlendModeEffect.hx b/source - Copy/BlendModeEffect.hx
new file mode 100644
index 0000000..1c9038b
--- /dev/null
+++ b/source - Copy/BlendModeEffect.hx
@@ -0,0 +1,34 @@
+package;
+
+import flixel.util.FlxColor;
+import openfl.display.ShaderParameter;
+
+typedef BlendModeShader =
+{
+ var uBlendColor:ShaderParameter;
+}
+
+class BlendModeEffect
+{
+ public var shader(default, null):BlendModeShader;
+
+ @:isVar
+ public var color(default, set):FlxColor;
+
+ public function new(shader:BlendModeShader, color:FlxColor):Void
+ {
+ shader.uBlendColor.value = [];
+ this.shader = shader;
+ this.color = color;
+ }
+
+ function set_color(color:FlxColor):FlxColor
+ {
+ shader.uBlendColor.value[0] = color.redFloat;
+ shader.uBlendColor.value[1] = color.greenFloat;
+ shader.uBlendColor.value[2] = color.blueFloat;
+ shader.uBlendColor.value[3] = color.alphaFloat;
+
+ return this.color = color;
+ }
+}
diff --git a/source - Copy/Boyfriend.hx b/source - Copy/Boyfriend.hx
new file mode 100644
index 0000000..c9f87f9
--- /dev/null
+++ b/source - Copy/Boyfriend.hx
@@ -0,0 +1,43 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.util.FlxTimer;
+
+using StringTools;
+
+class Boyfriend extends Character
+{
+ public var stunned:Bool = false;
+
+ public function new(x:Float, y:Float, ?char:String = 'bf')
+ {
+ super(x, y, char, true);
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (!debugMode)
+ {
+ if (animation.curAnim.name.startsWith('sing'))
+ {
+ holdTimer += elapsed;
+ }
+ else
+ holdTimer = 0;
+
+ if (animation.curAnim.name.endsWith('miss') && animation.curAnim.finished && !debugMode)
+ {
+ playAnim('idle', true, false, 10);
+ }
+
+ if (animation.curAnim.name == 'firstDeath' && animation.curAnim.finished)
+ {
+ playAnim('deathLoop');
+ }
+ }
+
+ super.update(elapsed);
+ }
+}
diff --git a/source - Copy/ButtonRemapSubstate.hx b/source - Copy/ButtonRemapSubstate.hx
new file mode 100644
index 0000000..64ff079
--- /dev/null
+++ b/source - Copy/ButtonRemapSubstate.hx
@@ -0,0 +1,11 @@
+package;
+
+import flixel.FlxSubState;
+
+class ButtonRemapSubstate extends FlxSubState
+{
+ public function new()
+ {
+ super();
+ }
+}
diff --git a/source - Copy/Caching.hx b/source - Copy/Caching.hx
new file mode 100644
index 0000000..2c6fb50
--- /dev/null
+++ b/source - Copy/Caching.hx
@@ -0,0 +1,128 @@
+package;
+
+import haxe.Exception;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import sys.FileSystem;
+import sys.io.File;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.addons.transition.TransitionData;
+import flixel.graphics.FlxGraphic;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.math.FlxPoint;
+import flixel.math.FlxRect;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
+import flixel.text.FlxText;
+
+using StringTools;
+
+class Caching extends MusicBeatState
+{
+ var toBeDone = 0;
+ var done = 0;
+
+ var text:FlxText;
+ var kadeLogo:FlxSprite;
+
+ override function create()
+ {
+ FlxG.mouse.visible = false;
+
+ FlxG.worldBounds.set(0,0);
+
+ text = new FlxText(FlxG.width / 2, FlxG.height / 2 + 300,0,"Loading...");
+ text.size = 34;
+ text.alignment = FlxTextAlign.CENTER;
+ text.alpha = 0;
+
+ kadeLogo = new FlxSprite(FlxG.width / 2, FlxG.height / 2).loadGraphic(Paths.image('KadeEngineLogo'));
+ kadeLogo.x -= kadeLogo.width / 2;
+ kadeLogo.y -= kadeLogo.height / 2 + 100;
+ text.y -= kadeLogo.height / 2 - 125;
+ text.x -= 170;
+ kadeLogo.setGraphicSize(Std.int(kadeLogo.width * 0.6));
+
+ kadeLogo.alpha = 0;
+
+ add(kadeLogo);
+ add(text);
+
+ trace('starting caching..');
+
+ sys.thread.Thread.create(() -> {
+ cache();
+ });
+
+
+ super.create();
+ }
+
+ var calledDone = false;
+
+ override function update(elapsed)
+ {
+
+ if (toBeDone != 0 && done != toBeDone)
+ {
+ var alpha = HelperFunctions.truncateFloat(done / toBeDone * 100,2) / 100;
+ kadeLogo.alpha = alpha;
+ text.alpha = alpha;
+ text.text = "Loading... (" + done + "/" + toBeDone + ")";
+ }
+
+ super.update(elapsed);
+ }
+
+
+ function cache()
+ {
+
+ var images = [];
+ var music = [];
+
+ trace("caching images...");
+
+ for (i in FileSystem.readDirectory(FileSystem.absolutePath("assets/shared/images/characters")))
+ {
+ if (!i.endsWith(".png"))
+ continue;
+ images.push(i);
+ }
+
+ trace("caching music...");
+
+ for (i in FileSystem.readDirectory(FileSystem.absolutePath("assets/songs")))
+ {
+ music.push(i);
+ }
+
+ toBeDone = Lambda.count(images) + Lambda.count(music);
+
+ trace("LOADING: " + toBeDone + " OBJECTS.");
+
+ for (i in images)
+ {
+ var replaced = i.replace(".png","");
+ FlxG.bitmap.add(Paths.image("characters/" + replaced,"shared"));
+ trace("cached " + replaced);
+ done++;
+ }
+
+ for (i in music)
+ {
+ FlxG.sound.cache(Paths.inst(i));
+ FlxG.sound.cache(Paths.voices(i));
+ trace("cached " + i);
+ done++;
+ }
+
+ trace("Finished caching...");
+
+ FlxG.switchState(new TitleState());
+ }
+
+}
\ No newline at end of file
diff --git a/source - Copy/Character.hx b/source - Copy/Character.hx
new file mode 100644
index 0000000..f9df179
--- /dev/null
+++ b/source - Copy/Character.hx
@@ -0,0 +1,660 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.animation.FlxBaseAnimation;
+import flixel.graphics.frames.FlxAtlasFrames;
+
+using StringTools;
+
+class Character extends FlxSprite
+{
+ public var animOffsets:Map>;
+ public var debugMode:Bool = false;
+
+ public var isPlayer:Bool = false;
+ public var curCharacter:String = 'bf';
+
+ public var holdTimer:Float = 0;
+
+ public function new(x:Float, y:Float, ?character:String = "bf", ?isPlayer:Bool = false)
+ {
+ super(x, y);
+
+ animOffsets = new Map>();
+ curCharacter = character;
+ this.isPlayer = isPlayer;
+
+ var tex:FlxAtlasFrames;
+ antialiasing = true;
+
+ switch (curCharacter)
+ {
+ case 'gf':
+ // GIRLFRIEND CODE
+ tex = Paths.getSparrowAtlas('characters/GF_assets');
+ frames = tex;
+ animation.addByPrefix('cheer', 'GF Cheer', 24, false);
+ animation.addByPrefix('singLEFT', 'GF left note', 24, false);
+ animation.addByPrefix('singRIGHT', 'GF Right Note', 24, false);
+ animation.addByPrefix('singUP', 'GF Up Note', 24, false);
+ animation.addByPrefix('singDOWN', 'GF Down Note', 24, false);
+ animation.addByIndices('sad', 'gf sad', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], "", 24, false);
+ animation.addByIndices('danceLeft', 'GF Dancing Beat', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
+ animation.addByIndices('danceRight', 'GF Dancing Beat', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
+ animation.addByIndices('hairBlow', "GF Dancing Beat Hair blowing", [0, 1, 2, 3], "", 24);
+ animation.addByIndices('hairFall', "GF Dancing Beat Hair Landing", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], "", 24, false);
+ animation.addByPrefix('scared', 'GF FEAR', 24);
+
+ addOffset('cheer');
+ addOffset('sad', -2, -2);
+ addOffset('danceLeft', 0, -9);
+ addOffset('danceRight', 0, -9);
+
+ addOffset("singUP", 0, 4);
+ addOffset("singRIGHT", 0, -20);
+ addOffset("singLEFT", 0, -19);
+ addOffset("singDOWN", 0, -20);
+ addOffset('hairBlow', 45, -8);
+ addOffset('hairFall', 0, -9);
+
+ addOffset('scared', -2, -17);
+
+ playAnim('danceRight');
+
+ case 'gf-christmas':
+ tex = Paths.getSparrowAtlas('characters/gfChristmas');
+ frames = tex;
+ animation.addByPrefix('cheer', 'GF Cheer', 24, false);
+ animation.addByPrefix('singLEFT', 'GF left note', 24, false);
+ animation.addByPrefix('singRIGHT', 'GF Right Note', 24, false);
+ animation.addByPrefix('singUP', 'GF Up Note', 24, false);
+ animation.addByPrefix('singDOWN', 'GF Down Note', 24, false);
+ animation.addByIndices('sad', 'gf sad', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], "", 24, false);
+ animation.addByIndices('danceLeft', 'GF Dancing Beat', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
+ animation.addByIndices('danceRight', 'GF Dancing Beat', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
+ animation.addByIndices('hairBlow', "GF Dancing Beat Hair blowing", [0, 1, 2, 3], "", 24);
+ animation.addByIndices('hairFall', "GF Dancing Beat Hair Landing", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], "", 24, false);
+ animation.addByPrefix('scared', 'GF FEAR', 24);
+
+ addOffset('cheer');
+ addOffset('sad', -2, -2);
+ addOffset('danceLeft', 0, -9);
+ addOffset('danceRight', 0, -9);
+
+ addOffset("singUP", 0, 4);
+ addOffset("singRIGHT", 0, -20);
+ addOffset("singLEFT", 0, -19);
+ addOffset("singDOWN", 0, -20);
+ addOffset('hairBlow', 45, -8);
+ addOffset('hairFall', 0, -9);
+
+ addOffset('scared', -2, -17);
+
+ playAnim('danceRight');
+
+ case 'gf-car':
+ tex = Paths.getSparrowAtlas('characters/gfCar');
+ frames = tex;
+ animation.addByIndices('singUP', 'GF Dancing Beat Hair blowing CAR', [0], "", 24, false);
+ animation.addByIndices('danceLeft', 'GF Dancing Beat Hair blowing CAR', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
+ animation.addByIndices('danceRight', 'GF Dancing Beat Hair blowing CAR', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24,
+ false);
+
+ addOffset('danceLeft', 0);
+ addOffset('danceRight', 0);
+
+ playAnim('danceRight');
+
+ case 'gf-pixel':
+ tex = Paths.getSparrowAtlas('characters/gfPixel');
+ frames = tex;
+ animation.addByIndices('singUP', 'GF IDLE', [2], "", 24, false);
+ animation.addByIndices('danceLeft', 'GF IDLE', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
+ animation.addByIndices('danceRight', 'GF IDLE', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
+
+ addOffset('danceLeft', 0);
+ addOffset('danceRight', 0);
+
+ playAnim('danceRight');
+
+ setGraphicSize(Std.int(width * PlayState.daPixelZoom));
+ updateHitbox();
+ antialiasing = false;
+
+ case 'dad':
+ // DAD ANIMATION LOADING CODE
+ tex = Paths.getSparrowAtlas('characters/DADDY_DEAREST', 'shared');
+ frames = tex;
+ animation.addByPrefix('idle', 'Dad idle dance', 24);
+ animation.addByPrefix('singUP', 'Dad Sing Note UP', 24);
+ animation.addByPrefix('singRIGHT', 'Dad Sing Note RIGHT', 24);
+ animation.addByPrefix('singDOWN', 'Dad Sing Note DOWN', 24);
+ animation.addByPrefix('singLEFT', 'Dad Sing Note LEFT', 24);
+
+ addOffset('idle');
+ addOffset("singUP", -6, 50);
+ addOffset("singRIGHT", 0, 27);
+ addOffset("singLEFT", -10, 10);
+ addOffset("singDOWN", 0, -30);
+
+ playAnim('idle');
+ case 'spooky':
+ tex = Paths.getSparrowAtlas('characters/spooky_kids_assets');
+ frames = tex;
+ animation.addByPrefix('singUP', 'spooky UP NOTE', 24, false);
+ animation.addByPrefix('singDOWN', 'spooky DOWN note', 24, false);
+ animation.addByPrefix('singLEFT', 'note sing left', 24, false);
+ animation.addByPrefix('singRIGHT', 'spooky sing right', 24, false);
+ animation.addByIndices('danceLeft', 'spooky dance idle', [0, 2, 6], "", 12, false);
+ animation.addByIndices('danceRight', 'spooky dance idle', [8, 10, 12, 14], "", 12, false);
+
+ addOffset('danceLeft');
+ addOffset('danceRight');
+
+ addOffset("singUP", -20, 26);
+ addOffset("singRIGHT", -130, -14);
+ addOffset("singLEFT", 130, -10);
+ addOffset("singDOWN", -50, -130);
+
+ playAnim('danceRight');
+ case 'mom':
+ tex = Paths.getSparrowAtlas('characters/Mom_Assets');
+ frames = tex;
+
+ animation.addByPrefix('idle', "Mom Idle", 24, false);
+ animation.addByPrefix('singUP', "Mom Up Pose", 24, false);
+ animation.addByPrefix('singDOWN', "MOM DOWN POSE", 24, false);
+ animation.addByPrefix('singLEFT', 'Mom Left Pose', 24, false);
+ // ANIMATION IS CALLED MOM LEFT POSE BUT ITS FOR THE RIGHT
+ // CUZ DAVE IS DUMB!
+ animation.addByPrefix('singRIGHT', 'Mom Pose Left', 24, false);
+
+ addOffset('idle');
+ addOffset("singUP", 14, 71);
+ addOffset("singRIGHT", 10, -60);
+ addOffset("singLEFT", 250, -23);
+ addOffset("singDOWN", 20, -160);
+
+ playAnim('idle');
+
+ case 'mom-car':
+ tex = Paths.getSparrowAtlas('characters/momCar');
+ frames = tex;
+
+ animation.addByPrefix('idle', "Mom Idle", 24, false);
+ animation.addByPrefix('singUP', "Mom Up Pose", 24, false);
+ animation.addByPrefix('singDOWN', "MOM DOWN POSE", 24, false);
+ animation.addByPrefix('singLEFT', 'Mom Left Pose', 24, false);
+ // ANIMATION IS CALLED MOM LEFT POSE BUT ITS FOR THE RIGHT
+ // CUZ DAVE IS DUMB!
+ animation.addByPrefix('singRIGHT', 'Mom Pose Left', 24, false);
+
+ addOffset('idle');
+ addOffset("singUP", 14, 71);
+ addOffset("singRIGHT", 10, -60);
+ addOffset("singLEFT", 250, -23);
+ addOffset("singDOWN", 20, -160);
+
+ playAnim('idle');
+ case 'monster':
+ tex = Paths.getSparrowAtlas('characters/Monster_Assets');
+ frames = tex;
+ animation.addByPrefix('idle', 'monster idle', 24, false);
+ animation.addByPrefix('singUP', 'monster up note', 24, false);
+ animation.addByPrefix('singDOWN', 'monster down', 24, false);
+ animation.addByPrefix('singLEFT', 'Monster left note', 24, false);
+ animation.addByPrefix('singRIGHT', 'Monster Right note', 24, false);
+
+ addOffset('idle');
+ addOffset("singUP", -20, 50);
+ addOffset("singRIGHT", -51);
+ addOffset("singLEFT", -30);
+ addOffset("singDOWN", -30, -40);
+ playAnim('idle');
+ case 'monster-christmas':
+ tex = Paths.getSparrowAtlas('characters/monsterChristmas');
+ frames = tex;
+ animation.addByPrefix('idle', 'monster idle', 24, false);
+ animation.addByPrefix('singUP', 'monster up note', 24, false);
+ animation.addByPrefix('singDOWN', 'monster down', 24, false);
+ animation.addByPrefix('singLEFT', 'Monster left note', 24, false);
+ animation.addByPrefix('singRIGHT', 'Monster Right note', 24, false);
+
+ addOffset('idle');
+ addOffset("singUP", -20, 50);
+ addOffset("singRIGHT", -51);
+ addOffset("singLEFT", -30);
+ addOffset("singDOWN", -40, -94);
+ playAnim('idle');
+ case 'pico':
+ tex = Paths.getSparrowAtlas('characters/Pico_FNF_assetss');
+ frames = tex;
+ animation.addByPrefix('idle', "Pico Idle Dance", 24);
+ animation.addByPrefix('singUP', 'pico Up note0', 24, false);
+ animation.addByPrefix('singDOWN', 'Pico Down Note0', 24, false);
+ if (isPlayer)
+ {
+ animation.addByPrefix('singLEFT', 'Pico NOTE LEFT0', 24, false);
+ animation.addByPrefix('singRIGHT', 'Pico Note Right0', 24, false);
+ animation.addByPrefix('singRIGHTmiss', 'Pico Note Right Miss', 24, false);
+ animation.addByPrefix('singLEFTmiss', 'Pico NOTE LEFT miss', 24, false);
+ }
+ else
+ {
+ // Need to be flipped! REDO THIS LATER!
+ animation.addByPrefix('singLEFT', 'Pico Note Right0', 24, false);
+ animation.addByPrefix('singRIGHT', 'Pico NOTE LEFT0', 24, false);
+ animation.addByPrefix('singRIGHTmiss', 'Pico NOTE LEFT miss', 24, false);
+ animation.addByPrefix('singLEFTmiss', 'Pico Note Right Miss', 24, false);
+ }
+
+ animation.addByPrefix('singUPmiss', 'pico Up note miss', 24);
+ animation.addByPrefix('singDOWNmiss', 'Pico Down Note MISS', 24);
+
+ addOffset('idle');
+ addOffset("singUP", -29, 27);
+ addOffset("singRIGHT", -68, -7);
+ addOffset("singLEFT", 65, 9);
+ addOffset("singDOWN", 200, -70);
+ addOffset("singUPmiss", -19, 67);
+ addOffset("singRIGHTmiss", -60, 41);
+ addOffset("singLEFTmiss", 62, 64);
+ addOffset("singDOWNmiss", 210, -28);
+
+ playAnim('idle');
+
+ flipX = true;
+
+ case 'bf':
+ var tex = Paths.getSparrowAtlas('characters/BOYFRIEND', 'shared');
+ frames = tex;
+
+ trace(tex.frames.length);
+
+ animation.addByPrefix('idle', 'BF idle dance', 24, false);
+ animation.addByPrefix('singUP', 'BF NOTE UP0', 24, false);
+ animation.addByPrefix('singLEFT', 'BF NOTE LEFT0', 24, false);
+ animation.addByPrefix('singRIGHT', 'BF NOTE RIGHT0', 24, false);
+ animation.addByPrefix('singDOWN', 'BF NOTE DOWN0', 24, false);
+ animation.addByPrefix('singUPmiss', 'BF NOTE UP MISS', 24, false);
+ animation.addByPrefix('singLEFTmiss', 'BF NOTE LEFT MISS', 24, false);
+ animation.addByPrefix('singRIGHTmiss', 'BF NOTE RIGHT MISS', 24, false);
+ animation.addByPrefix('singDOWNmiss', 'BF NOTE DOWN MISS', 24, false);
+ animation.addByPrefix('hey', 'BF HEY', 24, false);
+
+ animation.addByPrefix('firstDeath', "BF dies", 24, false);
+ animation.addByPrefix('deathLoop', "BF Dead Loop", 24, true);
+ animation.addByPrefix('deathConfirm', "BF Dead confirm", 24, false);
+
+ animation.addByPrefix('scared', 'BF idle shaking', 24);
+
+ addOffset('idle', -5);
+ addOffset("singUP", -29, 27);
+ addOffset("singRIGHT", -38, -7);
+ addOffset("singLEFT", 12, -6);
+ addOffset("singDOWN", -10, -50);
+ addOffset("singUPmiss", -29, 27);
+ addOffset("singRIGHTmiss", -30, 21);
+ addOffset("singLEFTmiss", 12, 24);
+ addOffset("singDOWNmiss", -11, -19);
+ addOffset("hey", 7, 4);
+ addOffset('firstDeath', 37, 11);
+ addOffset('deathLoop', 37, 5);
+ addOffset('deathConfirm', 37, 69);
+ addOffset('scared', -4);
+
+ playAnim('idle');
+
+ flipX = true;
+
+ case 'bf-christmas':
+ var tex = Paths.getSparrowAtlas('characters/bfChristmas');
+ frames = tex;
+ animation.addByPrefix('idle', 'BF idle dance', 24, false);
+ animation.addByPrefix('singUP', 'BF NOTE UP0', 24, false);
+ animation.addByPrefix('singLEFT', 'BF NOTE LEFT0', 24, false);
+ animation.addByPrefix('singRIGHT', 'BF NOTE RIGHT0', 24, false);
+ animation.addByPrefix('singDOWN', 'BF NOTE DOWN0', 24, false);
+ animation.addByPrefix('singUPmiss', 'BF NOTE UP MISS', 24, false);
+ animation.addByPrefix('singLEFTmiss', 'BF NOTE LEFT MISS', 24, false);
+ animation.addByPrefix('singRIGHTmiss', 'BF NOTE RIGHT MISS', 24, false);
+ animation.addByPrefix('singDOWNmiss', 'BF NOTE DOWN MISS', 24, false);
+ animation.addByPrefix('hey', 'BF HEY', 24, false);
+
+ addOffset('idle', -5);
+ addOffset("singUP", -29, 27);
+ addOffset("singRIGHT", -38, -7);
+ addOffset("singLEFT", 12, -6);
+ addOffset("singDOWN", -10, -50);
+ addOffset("singUPmiss", -29, 27);
+ addOffset("singRIGHTmiss", -30, 21);
+ addOffset("singLEFTmiss", 12, 24);
+ addOffset("singDOWNmiss", -11, -19);
+ addOffset("hey", 7, 4);
+
+ playAnim('idle');
+
+ flipX = true;
+ case 'bf-car':
+ var tex = Paths.getSparrowAtlas('characters/bfCar');
+ frames = tex;
+ animation.addByPrefix('idle', 'BF idle dance', 24, false);
+ animation.addByPrefix('singUP', 'BF NOTE UP0', 24, false);
+ animation.addByPrefix('singLEFT', 'BF NOTE LEFT0', 24, false);
+ animation.addByPrefix('singRIGHT', 'BF NOTE RIGHT0', 24, false);
+ animation.addByPrefix('singDOWN', 'BF NOTE DOWN0', 24, false);
+ animation.addByPrefix('singUPmiss', 'BF NOTE UP MISS', 24, false);
+ animation.addByPrefix('singLEFTmiss', 'BF NOTE LEFT MISS', 24, false);
+ animation.addByPrefix('singRIGHTmiss', 'BF NOTE RIGHT MISS', 24, false);
+ animation.addByPrefix('singDOWNmiss', 'BF NOTE DOWN MISS', 24, false);
+
+ addOffset('idle', -5);
+ addOffset("singUP", -29, 27);
+ addOffset("singRIGHT", -38, -7);
+ addOffset("singLEFT", 12, -6);
+ addOffset("singDOWN", -10, -50);
+ addOffset("singUPmiss", -29, 27);
+ addOffset("singRIGHTmiss", -30, 21);
+ addOffset("singLEFTmiss", 12, 24);
+ addOffset("singDOWNmiss", -11, -19);
+ playAnim('idle');
+
+ flipX = true;
+ case 'bf-pixel':
+ frames = Paths.getSparrowAtlas('characters/bfPixel');
+ animation.addByPrefix('idle', 'BF IDLE', 24, false);
+ animation.addByPrefix('singUP', 'BF UP NOTE', 24, false);
+ animation.addByPrefix('singLEFT', 'BF LEFT NOTE', 24, false);
+ animation.addByPrefix('singRIGHT', 'BF RIGHT NOTE', 24, false);
+ animation.addByPrefix('singDOWN', 'BF DOWN NOTE', 24, false);
+ animation.addByPrefix('singUPmiss', 'BF UP MISS', 24, false);
+ animation.addByPrefix('singLEFTmiss', 'BF LEFT MISS', 24, false);
+ animation.addByPrefix('singRIGHTmiss', 'BF RIGHT MISS', 24, false);
+ animation.addByPrefix('singDOWNmiss', 'BF DOWN MISS', 24, false);
+
+ addOffset('idle');
+ addOffset("singUP");
+ addOffset("singRIGHT");
+ addOffset("singLEFT");
+ addOffset("singDOWN");
+ addOffset("singUPmiss");
+ addOffset("singRIGHTmiss");
+ addOffset("singLEFTmiss");
+ addOffset("singDOWNmiss");
+
+ setGraphicSize(Std.int(width * 6));
+ updateHitbox();
+
+ playAnim('idle');
+
+ width -= 100;
+ height -= 100;
+
+ antialiasing = false;
+
+ flipX = true;
+ case 'bf-pixel-dead':
+ frames = Paths.getSparrowAtlas('characters/bfPixelsDEAD');
+ animation.addByPrefix('singUP', "BF Dies pixel", 24, false);
+ animation.addByPrefix('firstDeath', "BF Dies pixel", 24, false);
+ animation.addByPrefix('deathLoop', "Retry Loop", 24, true);
+ animation.addByPrefix('deathConfirm', "RETRY CONFIRM", 24, false);
+ animation.play('firstDeath');
+
+ addOffset('firstDeath');
+ addOffset('deathLoop', -37);
+ addOffset('deathConfirm', -37);
+ playAnim('firstDeath');
+ // pixel bullshit
+ setGraphicSize(Std.int(width * 6));
+ updateHitbox();
+ antialiasing = false;
+ flipX = true;
+
+ case 'senpai':
+ frames = Paths.getSparrowAtlas('characters/senpai');
+ animation.addByPrefix('idle', 'Senpai Idle', 24, false);
+ animation.addByPrefix('singUP', 'SENPAI UP NOTE', 24, false);
+ animation.addByPrefix('singLEFT', 'SENPAI LEFT NOTE', 24, false);
+ animation.addByPrefix('singRIGHT', 'SENPAI RIGHT NOTE', 24, false);
+ animation.addByPrefix('singDOWN', 'SENPAI DOWN NOTE', 24, false);
+
+ addOffset('idle');
+ addOffset("singUP", 5, 37);
+ addOffset("singRIGHT");
+ addOffset("singLEFT", 40);
+ addOffset("singDOWN", 14);
+
+ playAnim('idle');
+
+ setGraphicSize(Std.int(width * 6));
+ updateHitbox();
+
+ antialiasing = false;
+ case 'senpai-angry':
+ frames = Paths.getSparrowAtlas('characters/senpai');
+ animation.addByPrefix('idle', 'Angry Senpai Idle', 24, false);
+ animation.addByPrefix('singUP', 'Angry Senpai UP NOTE', 24, false);
+ animation.addByPrefix('singLEFT', 'Angry Senpai LEFT NOTE', 24, false);
+ animation.addByPrefix('singRIGHT', 'Angry Senpai RIGHT NOTE', 24, false);
+ animation.addByPrefix('singDOWN', 'Angry Senpai DOWN NOTE', 24, false);
+
+ addOffset('idle');
+ addOffset("singUP", 5, 37);
+ addOffset("singRIGHT");
+ addOffset("singLEFT", 40);
+ addOffset("singDOWN", 14);
+ playAnim('idle');
+
+ setGraphicSize(Std.int(width * 6));
+ updateHitbox();
+
+ antialiasing = false;
+
+ case 'spirit':
+ frames = Paths.getPackerAtlas('characters/spirit');
+ animation.addByPrefix('idle', "idle spirit_", 24, false);
+ animation.addByPrefix('singUP', "up_", 24, false);
+ animation.addByPrefix('singRIGHT', "right_", 24, false);
+ animation.addByPrefix('singLEFT', "left_", 24, false);
+ animation.addByPrefix('singDOWN', "spirit down_", 24, false);
+
+ addOffset('idle', -220, -280);
+ addOffset('singUP', -220, -240);
+ addOffset("singRIGHT", -220, -280);
+ addOffset("singLEFT", -200, -280);
+ addOffset("singDOWN", 170, 110);
+
+ setGraphicSize(Std.int(width * 6));
+ updateHitbox();
+
+ playAnim('idle');
+
+ antialiasing = false;
+
+ case 'parents-christmas':
+ frames = Paths.getSparrowAtlas('characters/mom_dad_christmas_assets');
+ animation.addByPrefix('idle', 'Parent Christmas Idle', 24, false);
+ animation.addByPrefix('singUP', 'Parent Up Note Dad', 24, false);
+ animation.addByPrefix('singDOWN', 'Parent Down Note Dad', 24, false);
+ animation.addByPrefix('singLEFT', 'Parent Left Note Dad', 24, false);
+ animation.addByPrefix('singRIGHT', 'Parent Right Note Dad', 24, false);
+
+ animation.addByPrefix('singUP-alt', 'Parent Up Note Mom', 24, false);
+
+ animation.addByPrefix('singDOWN-alt', 'Parent Down Note Mom', 24, false);
+ animation.addByPrefix('singLEFT-alt', 'Parent Left Note Mom', 24, false);
+ animation.addByPrefix('singRIGHT-alt', 'Parent Right Note Mom', 24, false);
+
+ addOffset('idle');
+ addOffset("singUP", -47, 24);
+ addOffset("singRIGHT", -1, -23);
+ addOffset("singLEFT", -30, 16);
+ addOffset("singDOWN", -31, -29);
+ addOffset("singUP-alt", -47, 24);
+ addOffset("singRIGHT-alt", -1, -24);
+ addOffset("singLEFT-alt", -30, 15);
+ addOffset("singDOWN-alt", -30, -27);
+
+ playAnim('idle');
+ }
+
+ dance();
+
+ if (isPlayer)
+ {
+ flipX = !flipX;
+
+ // Doesn't flip for BF, since his are already in the right place???
+ if (!curCharacter.startsWith('bf'))
+ {
+ // var animArray
+ var oldRight = animation.getByName('singRIGHT').frames;
+ animation.getByName('singRIGHT').frames = animation.getByName('singLEFT').frames;
+ animation.getByName('singLEFT').frames = oldRight;
+
+ // IF THEY HAVE MISS ANIMATIONS??
+ if (animation.getByName('singRIGHTmiss') != null)
+ {
+ var oldMiss = animation.getByName('singRIGHTmiss').frames;
+ animation.getByName('singRIGHTmiss').frames = animation.getByName('singLEFTmiss').frames;
+ animation.getByName('singLEFTmiss').frames = oldMiss;
+ }
+ }
+ }
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (!curCharacter.startsWith('bf'))
+ {
+ if (animation.curAnim.name.startsWith('sing'))
+ {
+ holdTimer += elapsed;
+ }
+
+ var dadVar:Float = 4;
+
+ if (curCharacter == 'dad')
+ dadVar = 6.1;
+ if (holdTimer >= Conductor.stepCrochet * dadVar * 0.001)
+ {
+ trace('dance');
+ dance();
+ holdTimer = 0;
+ }
+ }
+
+ switch (curCharacter)
+ {
+ case 'gf':
+ if (animation.curAnim.name == 'hairFall' && animation.curAnim.finished)
+ playAnim('danceRight');
+ }
+
+ super.update(elapsed);
+ }
+
+ private var danced:Bool = false;
+
+ /**
+ * FOR GF DANCING SHIT
+ */
+ public function dance()
+ {
+ if (!debugMode)
+ {
+ switch (curCharacter)
+ {
+ case 'gf':
+ if (!animation.curAnim.name.startsWith('hair'))
+ {
+ danced = !danced;
+
+ if (danced)
+ playAnim('danceRight');
+ else
+ playAnim('danceLeft');
+ }
+
+ case 'gf-christmas':
+ if (!animation.curAnim.name.startsWith('hair'))
+ {
+ danced = !danced;
+
+ if (danced)
+ playAnim('danceRight');
+ else
+ playAnim('danceLeft');
+ }
+
+ case 'gf-car':
+ if (!animation.curAnim.name.startsWith('hair'))
+ {
+ danced = !danced;
+
+ if (danced)
+ playAnim('danceRight');
+ else
+ playAnim('danceLeft');
+ }
+ case 'gf-pixel':
+ if (!animation.curAnim.name.startsWith('hair'))
+ {
+ danced = !danced;
+
+ if (danced)
+ playAnim('danceRight');
+ else
+ playAnim('danceLeft');
+ }
+
+ case 'spooky':
+ danced = !danced;
+
+ if (danced)
+ playAnim('danceRight');
+ else
+ playAnim('danceLeft');
+ default:
+ playAnim('idle');
+ }
+ }
+ }
+
+ public function playAnim(AnimName:String, Force:Bool = false, Reversed:Bool = false, Frame:Int = 0):Void
+ {
+ animation.play(AnimName, Force, Reversed, Frame);
+
+ var daOffset = animOffsets.get(AnimName);
+ if (animOffsets.exists(AnimName))
+ {
+ offset.set(daOffset[0], daOffset[1]);
+ }
+ else
+ offset.set(0, 0);
+
+ if (curCharacter == 'gf')
+ {
+ if (AnimName == 'singLEFT')
+ {
+ danced = true;
+ }
+ else if (AnimName == 'singRIGHT')
+ {
+ danced = false;
+ }
+
+ if (AnimName == 'singUP' || AnimName == 'singDOWN')
+ {
+ danced = !danced;
+ }
+ }
+ }
+
+ public function addOffset(name:String, x:Float = 0, y:Float = 0)
+ {
+ animOffsets[name] = [x, y];
+ }
+}
diff --git a/source - Copy/ChartParser.hx b/source - Copy/ChartParser.hx
new file mode 100644
index 0000000..3884c0e
--- /dev/null
+++ b/source - Copy/ChartParser.hx
@@ -0,0 +1,80 @@
+package;
+
+import flixel.util.FlxStringUtil;
+
+using StringTools;
+
+class ChartParser
+{
+ static public function parse(songName:String, section:Int):Array
+ {
+ var IMG_WIDTH:Int = 8;
+ var regex:EReg = new EReg("[ \t]*((\r\n)|\r|\n)[ \t]*", "g");
+
+ var csvData = FlxStringUtil.imageToCSV(Paths.file('data/' + songName + '/' + songName + '_section' + section + '.png'));
+
+ var lines:Array = regex.split(csvData);
+ var rows:Array = lines.filter(function(line) return line != "");
+ csvData.replace("\n", ',');
+
+ var heightInTiles = rows.length;
+ var widthInTiles = 0;
+
+ var row:Int = 0;
+
+ // LMAOOOO STOLE ALL THIS FROM FLXBASETILEMAP LOLOL
+
+ var dopeArray:Array = [];
+ while (row < heightInTiles)
+ {
+ var rowString = rows[row];
+ if (rowString.endsWith(","))
+ rowString = rowString.substr(0, rowString.length - 1);
+ var columns = rowString.split(",");
+
+ if (columns.length == 0)
+ {
+ heightInTiles--;
+ continue;
+ }
+ if (widthInTiles == 0)
+ {
+ widthInTiles = columns.length;
+ }
+
+ var column = 0;
+ var pushedInColumn:Bool = false;
+ while (column < widthInTiles)
+ {
+ // the current tile to be added:
+ var columnString = columns[column];
+ var curTile = Std.parseInt(columnString);
+
+ if (curTile == null)
+ throw 'String in row $row, column $column is not a valid integer: "$columnString"';
+
+ if (curTile == 1)
+ {
+ if (column < 4)
+ dopeArray.push(column + 1);
+ else
+ {
+ var tempCol = (column + 1) * -1;
+ tempCol += 4;
+ dopeArray.push(tempCol);
+ }
+
+ pushedInColumn = true;
+ }
+
+ column++;
+ }
+
+ if (!pushedInColumn)
+ dopeArray.push(0);
+
+ row++;
+ }
+ return dopeArray;
+ }
+}
diff --git a/source - Copy/ChartingState.hx b/source - Copy/ChartingState.hx
new file mode 100644
index 0000000..c66295d
--- /dev/null
+++ b/source - Copy/ChartingState.hx
@@ -0,0 +1,1533 @@
+package;
+
+import flixel.FlxCamera;
+import flixel.addons.ui.FlxUIText;
+import haxe.zip.Writer;
+import Conductor.BPMChangeEvent;
+import Section.SwagSection;
+import Song.SwagSong;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.display.FlxGridOverlay;
+import flixel.addons.ui.FlxInputText;
+import flixel.addons.ui.FlxUI9SliceSprite;
+import flixel.addons.ui.FlxUI;
+import flixel.addons.ui.FlxUICheckBox;
+import flixel.addons.ui.FlxUIDropDownMenu;
+import flixel.addons.ui.FlxUIInputText;
+import flixel.addons.ui.FlxUINumericStepper;
+import flixel.addons.ui.FlxUITabMenu;
+import flixel.addons.ui.FlxUITooltip.FlxUITooltipStyle;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.group.FlxGroup;
+import flixel.math.FlxMath;
+import flixel.math.FlxPoint;
+import flixel.system.FlxSound;
+import flixel.text.FlxText;
+import flixel.ui.FlxButton;
+import flixel.ui.FlxSpriteButton;
+import flixel.util.FlxColor;
+import haxe.Json;
+import lime.utils.Assets;
+import openfl.events.Event;
+import openfl.events.IOErrorEvent;
+import openfl.events.IOErrorEvent;
+import openfl.events.IOErrorEvent;
+import openfl.media.Sound;
+import openfl.net.FileReference;
+import openfl.utils.ByteArray;
+
+using StringTools;
+
+class ChartingState extends MusicBeatState
+{
+ var _file:FileReference;
+
+ public var playClaps:Bool = false;
+
+ public var snap:Int = 1;
+
+ var UI_box:FlxUITabMenu;
+
+ /**
+ * Array of notes showing when each section STARTS in STEPS
+ * Usually rounded up??
+ */
+ var curSection:Int = 0;
+
+ public static var lastSection:Int = 0;
+
+ var bpmTxt:FlxText;
+
+ var strumLine:FlxSprite;
+ var curSong:String = 'Dad Battle';
+ var amountSteps:Int = 0;
+ var bullshitUI:FlxGroup;
+ var writingNotesText:FlxText;
+ var highlight:FlxSprite;
+
+ var GRID_SIZE:Int = 40;
+
+ var dummyArrow:FlxSprite;
+
+ var curRenderedNotes:FlxTypedGroup;
+ var curRenderedSustains:FlxTypedGroup;
+
+ var gridBG:FlxSprite;
+
+ var _song:SwagSong;
+
+ var typingShit:FlxInputText;
+ /*
+ * WILL BE THE CURRENT / LAST PLACED NOTE
+ **/
+ var curSelectedNote:Array;
+
+ var tempBpm:Float = 0;
+ var gridBlackLine:FlxSprite;
+ var vocals:FlxSound;
+
+ var player2:Character = new Character(0,0, "dad");
+ var player1:Boyfriend = new Boyfriend(0,0, "bf");
+
+ var leftIcon:HealthIcon;
+ var rightIcon:HealthIcon;
+
+ private var lastNote:Note;
+ var claps:Array = [];
+
+ public var snapText:FlxText;
+
+ override function create()
+ {
+ curSection = lastSection;
+
+ if (PlayState.SONG != null)
+ _song = PlayState.SONG;
+ else
+ {
+ _song = {
+ song: 'Test',
+ notes: [],
+ bpm: 150,
+ needsVoices: true,
+ player1: 'bf',
+ player2: 'dad',
+ gfVersion: 'gf',
+ noteStyle: 'normal',
+ stage: 'stage',
+ speed: 1,
+ validScore: false
+ };
+ }
+
+ gridBG = FlxGridOverlay.create(GRID_SIZE, GRID_SIZE, GRID_SIZE * 8, GRID_SIZE * 16);
+ add(gridBG);
+
+ var blackBorder:FlxSprite = new FlxSprite(60,10).makeGraphic(120,100,FlxColor.BLACK);
+ blackBorder.scrollFactor.set();
+
+ blackBorder.alpha = 0.3;
+
+ snapText = new FlxText(60,10,0,"Snap: 1/" + snap + " (Press Control to unsnap the cursor)\nAdd Notes: 1-8 (or click)\n", 14);
+ snapText.scrollFactor.set();
+
+ gridBlackLine = new FlxSprite(gridBG.x + gridBG.width / 2).makeGraphic(2, Std.int(gridBG.height), FlxColor.BLACK);
+ add(gridBlackLine);
+
+ curRenderedNotes = new FlxTypedGroup();
+ curRenderedSustains = new FlxTypedGroup();
+
+ FlxG.mouse.visible = true;
+ FlxG.save.bind('funkin', 'ninjamuffin99');
+
+ tempBpm = _song.bpm;
+
+ addSection();
+
+ // sections = _song.notes;
+
+ updateGrid();
+
+ loadSong(_song.song);
+ Conductor.changeBPM(_song.bpm);
+ Conductor.mapBPMChanges(_song);
+
+ leftIcon = new HealthIcon(_song.player1);
+ rightIcon = new HealthIcon(_song.player2);
+ leftIcon.scrollFactor.set(1, 1);
+ rightIcon.scrollFactor.set(1, 1);
+
+ leftIcon.setGraphicSize(0, 45);
+ rightIcon.setGraphicSize(0, 45);
+
+ add(leftIcon);
+ add(rightIcon);
+
+ leftIcon.setPosition(0, -100);
+ rightIcon.setPosition(gridBG.width / 2, -100);
+
+ bpmTxt = new FlxText(1000, 50, 0, "", 16);
+ bpmTxt.scrollFactor.set();
+ add(bpmTxt);
+
+ strumLine = new FlxSprite(0, 50).makeGraphic(Std.int(FlxG.width / 2), 4);
+ add(strumLine);
+
+ dummyArrow = new FlxSprite().makeGraphic(GRID_SIZE, GRID_SIZE);
+ add(dummyArrow);
+
+ var tabs = [
+ {name: "Song", label: 'Song Data'},
+ {name: "Section", label: 'Section Data'},
+ {name: "Note", label: 'Note Data'},
+ {name: "Assets", label: 'Assets'}
+ ];
+
+ UI_box = new FlxUITabMenu(null, tabs, true);
+
+ UI_box.resize(300, 400);
+ UI_box.x = FlxG.width / 2;
+ UI_box.y = 20;
+ add(UI_box);
+
+ addSongUI();
+ addSectionUI();
+ addNoteUI();
+
+ add(curRenderedNotes);
+ add(curRenderedSustains);
+
+ add(blackBorder);
+ add(snapText);
+
+
+
+ super.create();
+ }
+
+ function addSongUI():Void
+ {
+ var UI_songTitle = new FlxUIInputText(10, 10, 70, _song.song, 8);
+ typingShit = UI_songTitle;
+
+ var check_voices = new FlxUICheckBox(10, 25, null, null, "Has voice track", 100);
+ check_voices.checked = _song.needsVoices;
+ // _song.needsVoices = check_voices.checked;
+ check_voices.callback = function()
+ {
+ _song.needsVoices = check_voices.checked;
+ trace('CHECKED!');
+ };
+
+ var check_mute_inst = new FlxUICheckBox(10, 200, null, null, "Mute Instrumental (in editor)", 100);
+ check_mute_inst.checked = false;
+ check_mute_inst.callback = function()
+ {
+ var vol:Float = 1;
+
+ if (check_mute_inst.checked)
+ vol = 0;
+
+ FlxG.sound.music.volume = vol;
+ };
+
+ var saveButton:FlxButton = new FlxButton(110, 8, "Save", function()
+ {
+ saveLevel();
+ });
+
+ var reloadSong:FlxButton = new FlxButton(saveButton.x + saveButton.width + 10, saveButton.y, "Reload Audio", function()
+ {
+ loadSong(_song.song);
+ });
+
+ var reloadSongJson:FlxButton = new FlxButton(reloadSong.x, saveButton.y + 30, "Reload JSON", function()
+ {
+ loadJson(_song.song.toLowerCase());
+ });
+
+
+ var restart = new FlxButton(10,140,"Reset Chart", function()
+ {
+ for (ii in 0..._song.notes.length)
+ {
+ for (i in 0..._song.notes[ii].sectionNotes.length)
+ {
+ _song.notes[ii].sectionNotes = [];
+ }
+ }
+ resetSection(true);
+ });
+
+ var loadAutosaveBtn:FlxButton = new FlxButton(reloadSongJson.x, reloadSongJson.y + 30, 'load autosave', loadAutosave);
+ var stepperBPM:FlxUINumericStepper = new FlxUINumericStepper(10, 65, 0.1, 1, 1.0, 5000.0, 1);
+ stepperBPM.value = Conductor.bpm;
+ stepperBPM.name = 'song_bpm';
+
+ var stepperBPMLabel = new FlxText(74,65,'BPM');
+
+ var stepperSpeed:FlxUINumericStepper = new FlxUINumericStepper(10, 80, 0.1, 1, 0.1, 10, 1);
+ stepperSpeed.value = _song.speed;
+ stepperSpeed.name = 'song_speed';
+
+ var stepperSpeedLabel = new FlxText(74,80,'Scroll Speed');
+
+ var stepperVocalVol:FlxUINumericStepper = new FlxUINumericStepper(10, 95, 0.1, 1, 0.1, 10, 1);
+ stepperVocalVol.value = vocals.volume;
+ stepperVocalVol.name = 'song_vocalvol';
+
+ var stepperVocalVolLabel = new FlxText(74, 95, 'Vocal Volume');
+
+ var stepperSongVol:FlxUINumericStepper = new FlxUINumericStepper(10, 110, 0.1, 1, 0.1, 10, 1);
+ stepperSongVol.value = FlxG.sound.music.volume;
+ stepperSongVol.name = 'song_instvol';
+
+
+ var hitsounds = new FlxUICheckBox(10, stepperSongVol.y + 60, null, null, "Play hitsounds", 100);
+ hitsounds.checked = false;
+ hitsounds.callback = function()
+ {
+ playClaps = hitsounds.checked;
+ };
+
+ var stepperSongVolLabel = new FlxText(74, 110, 'Instrumental Volume');
+
+
+ var shiftNoteDialLabel = new FlxText(10, 245, 'Shift Note FWD by (Section)');
+ var stepperShiftNoteDial:FlxUINumericStepper = new FlxUINumericStepper(10, 260, 1, 0, -1000, 1000, 0);
+ stepperShiftNoteDial.name = 'song_shiftnote';
+ var shiftNoteDialLabel2 = new FlxText(10, 275, 'Shift Note FWD by (Step)');
+ var stepperShiftNoteDialstep:FlxUINumericStepper = new FlxUINumericStepper(10, 290, 1, 0, -1000, 1000, 0);
+ stepperShiftNoteDialstep.name = 'song_shiftnotems';
+ var shiftNoteDialLabel3 = new FlxText(10, 305, 'Shift Note FWD by (ms)');
+ var stepperShiftNoteDialms:FlxUINumericStepper = new FlxUINumericStepper(10, 320, 1, 0, -1000, 1000, 2);
+ stepperShiftNoteDialms.name = 'song_shiftnotems';
+
+ var shiftNoteButton:FlxButton = new FlxButton(10, 335, "Shift", function()
+ {
+ shiftNotes(Std.int(stepperShiftNoteDial.value),Std.int(stepperShiftNoteDialstep.value),Std.int(stepperShiftNoteDialms.value));
+ });
+
+ var characters:Array = CoolUtil.coolTextFile(Paths.txt('characterList'));
+ var gfVersions:Array = CoolUtil.coolTextFile(Paths.txt('gfVersionList'));
+ var stages:Array = CoolUtil.coolTextFile(Paths.txt('stageList'));
+ var noteStyles:Array = CoolUtil.coolTextFile(Paths.txt('noteStyleList'));
+
+ var player1DropDown = new FlxUIDropDownMenu(10, 100, FlxUIDropDownMenu.makeStrIdLabelArray(characters, true), function(character:String)
+ {
+ _song.player1 = characters[Std.parseInt(character)];
+ });
+ player1DropDown.selectedLabel = _song.player1;
+
+ var player1Label = new FlxText(10,80,64,'Player 1');
+
+ var player2DropDown = new FlxUIDropDownMenu(140, 100, FlxUIDropDownMenu.makeStrIdLabelArray(characters, true), function(character:String)
+ {
+ _song.player2 = characters[Std.parseInt(character)];
+ });
+ player2DropDown.selectedLabel = _song.player2;
+
+ var player2Label = new FlxText(140,80,64,'Player 2');
+
+ var gfVersionDropDown = new FlxUIDropDownMenu(10, 200, FlxUIDropDownMenu.makeStrIdLabelArray(gfVersions, true), function(gfVersion:String)
+ {
+ _song.gfVersion = gfVersions[Std.parseInt(gfVersion)];
+ });
+ gfVersionDropDown.selectedLabel = _song.gfVersion;
+
+ var gfVersionLabel = new FlxText(10,180,64,'Girlfriend');
+
+ var stageDropDown = new FlxUIDropDownMenu(140, 200, FlxUIDropDownMenu.makeStrIdLabelArray(stages, true), function(stage:String)
+ {
+ _song.stage = stages[Std.parseInt(stage)];
+ });
+ stageDropDown.selectedLabel = _song.stage;
+
+ var stageLabel = new FlxText(140,180,64,'Stage');
+
+ var noteStyleDropDown = new FlxUIDropDownMenu(10, 300, FlxUIDropDownMenu.makeStrIdLabelArray(noteStyles, true), function(noteStyle:String)
+ {
+ _song.noteStyle = noteStyles[Std.parseInt(noteStyle)];
+ });
+ noteStyleDropDown.selectedLabel = _song.noteStyle;
+
+ var noteStyleLabel = new FlxText(10,280,64,'Note Skin');
+
+ var tab_group_song = new FlxUI(null, UI_box);
+ tab_group_song.name = "Song";
+ tab_group_song.add(UI_songTitle);
+ tab_group_song.add(restart);
+ tab_group_song.add(check_voices);
+ tab_group_song.add(check_mute_inst);
+ tab_group_song.add(saveButton);
+ tab_group_song.add(reloadSong);
+ tab_group_song.add(reloadSongJson);
+ tab_group_song.add(loadAutosaveBtn);
+ tab_group_song.add(stepperBPM);
+ tab_group_song.add(stepperBPMLabel);
+ tab_group_song.add(stepperSpeed);
+ tab_group_song.add(stepperSpeedLabel);
+ tab_group_song.add(stepperVocalVol);
+ tab_group_song.add(stepperVocalVolLabel);
+ tab_group_song.add(stepperSongVol);
+ tab_group_song.add(stepperSongVolLabel);
+ tab_group_song.add(shiftNoteDialLabel);
+ tab_group_song.add(stepperShiftNoteDial);
+ tab_group_song.add(shiftNoteDialLabel2);
+ tab_group_song.add(stepperShiftNoteDialstep);
+ tab_group_song.add(shiftNoteDialLabel3);
+ tab_group_song.add(stepperShiftNoteDialms);
+ tab_group_song.add(shiftNoteButton);
+ tab_group_song.add(hitsounds);
+
+ var tab_group_assets = new FlxUI(null, UI_box);
+ tab_group_assets.name = "Assets";
+ tab_group_assets.add(noteStyleDropDown);
+ tab_group_assets.add(noteStyleLabel);
+ tab_group_assets.add(gfVersionDropDown);
+ tab_group_assets.add(gfVersionLabel);
+ tab_group_assets.add(stageDropDown);
+ tab_group_assets.add(stageLabel);
+ tab_group_assets.add(player1DropDown);
+ tab_group_assets.add(player2DropDown);
+ tab_group_assets.add(player1Label);
+ tab_group_assets.add(player2Label);
+
+ UI_box.addGroup(tab_group_song);
+ UI_box.addGroup(tab_group_assets);
+ UI_box.scrollFactor.set();
+
+ FlxG.camera.follow(strumLine);
+ }
+
+ var stepperLength:FlxUINumericStepper;
+ var check_mustHitSection:FlxUICheckBox;
+ var check_changeBPM:FlxUICheckBox;
+ var stepperSectionBPM:FlxUINumericStepper;
+ var check_altAnim:FlxUICheckBox;
+
+ function addSectionUI():Void
+ {
+ var tab_group_section = new FlxUI(null, UI_box);
+ tab_group_section.name = 'Section';
+
+ stepperLength = new FlxUINumericStepper(10, 10, 4, 0, 0, 999, 0);
+ stepperLength.value = _song.notes[curSection].lengthInSteps;
+ stepperLength.name = "section_length";
+
+ var stepperLengthLabel = new FlxText(74,10,'Section Length (in steps)');
+
+ stepperSectionBPM = new FlxUINumericStepper(10, 80, 1, Conductor.bpm, 0, 999, 0);
+ stepperSectionBPM.value = Conductor.bpm;
+ stepperSectionBPM.name = 'section_bpm';
+
+ var stepperCopy:FlxUINumericStepper = new FlxUINumericStepper(110, 132, 1, 1, -999, 999, 0);
+ var stepperCopyLabel = new FlxText(174,132,'sections back');
+
+ var copyButton:FlxButton = new FlxButton(10, 130, "Copy last section", function()
+ {
+ copySection(Std.int(stepperCopy.value));
+ });
+
+ var clearSectionButton:FlxButton = new FlxButton(10, 150, "Clear Section", clearSection);
+
+ var swapSection:FlxButton = new FlxButton(10, 170, "Swap Section", function()
+ {
+ for (i in 0..._song.notes[curSection].sectionNotes.length)
+ {
+ var note = _song.notes[curSection].sectionNotes[i];
+ note[1] = (note[1] + 4) % 8;
+ _song.notes[curSection].sectionNotes[i] = note;
+ updateGrid();
+ }
+ });
+ check_mustHitSection = new FlxUICheckBox(10, 30, null, null, "Camera Points to P1?", 100);
+ check_mustHitSection.name = 'check_mustHit';
+ check_mustHitSection.checked = true;
+ // _song.needsVoices = check_mustHit.checked;
+
+ check_altAnim = new FlxUICheckBox(10, 400, null, null, "Alternate Animation", 100);
+ check_altAnim.name = 'check_altAnim';
+
+ check_changeBPM = new FlxUICheckBox(10, 60, null, null, 'Change BPM', 100);
+ check_changeBPM.name = 'check_changeBPM';
+
+ tab_group_section.add(stepperLength);
+ tab_group_section.add(stepperLengthLabel);
+ tab_group_section.add(stepperSectionBPM);
+ tab_group_section.add(stepperCopy);
+ tab_group_section.add(stepperCopyLabel);
+ tab_group_section.add(check_mustHitSection);
+ tab_group_section.add(check_altAnim);
+ tab_group_section.add(check_changeBPM);
+ tab_group_section.add(copyButton);
+ tab_group_section.add(clearSectionButton);
+ tab_group_section.add(swapSection);
+
+ UI_box.addGroup(tab_group_section);
+ }
+
+ var stepperSusLength:FlxUINumericStepper;
+
+ var tab_group_note:FlxUI;
+
+ function addNoteUI():Void
+ {
+ tab_group_note = new FlxUI(null, UI_box);
+ tab_group_note.name = 'Note';
+
+ writingNotesText = new FlxUIText(20,100, 0, "");
+ writingNotesText.setFormat("Arial",20,FlxColor.WHITE,FlxTextAlign.LEFT,FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
+
+ stepperSusLength = new FlxUINumericStepper(10, 10, Conductor.stepCrochet / 2, 0, 0, Conductor.stepCrochet * _song.notes[curSection].lengthInSteps * 4);
+ stepperSusLength.value = 0;
+ stepperSusLength.name = 'note_susLength';
+
+ var stepperSusLengthLabel = new FlxText(74,10,'Note Sustain Length');
+
+ var applyLength:FlxButton = new FlxButton(10, 100, 'Apply Data');
+
+ tab_group_note.add(stepperSusLength);
+ tab_group_note.add(stepperSusLengthLabel);
+ tab_group_note.add(applyLength);
+
+ UI_box.addGroup(tab_group_note);
+
+ /*player2 = new Character(0,gridBG.y, _song.player2);
+ player1 = new Boyfriend(player2.width * 0.2,gridBG.y + player2.height, _song.player1);
+
+ player1.y = player1.y - player1.height;
+
+ player2.setGraphicSize(Std.int(player2.width * 0.2));
+ player1.setGraphicSize(Std.int(player1.width * 0.2));
+
+ UI_box.add(player1);
+ UI_box.add(player2);*/
+
+ }
+
+ function loadSong(daSong:String):Void
+ {
+ if (FlxG.sound.music != null)
+ {
+ FlxG.sound.music.stop();
+ // vocals.stop();
+ }
+
+ FlxG.sound.playMusic(Paths.inst(daSong), 0.6);
+
+ // WONT WORK FOR TUTORIAL OR TEST SONG!!! REDO LATER
+ vocals = new FlxSound().loadEmbedded(Paths.voices(daSong));
+ FlxG.sound.list.add(vocals);
+
+ FlxG.sound.music.pause();
+ vocals.pause();
+
+ FlxG.sound.music.onComplete = function()
+ {
+ vocals.pause();
+ vocals.time = 0;
+ FlxG.sound.music.pause();
+ FlxG.sound.music.time = 0;
+ changeSection();
+ };
+ }
+
+ function generateUI():Void
+ {
+ while (bullshitUI.members.length > 0)
+ {
+ bullshitUI.remove(bullshitUI.members[0], true);
+ }
+
+ // general shit
+ var title:FlxText = new FlxText(UI_box.x + 20, UI_box.y + 20, 0);
+ bullshitUI.add(title);
+ /*
+ var loopCheck = new FlxUICheckBox(UI_box.x + 10, UI_box.y + 50, null, null, "Loops", 100, ['loop check']);
+ loopCheck.checked = curNoteSelected.doesLoop;
+ tooltips.add(loopCheck, {title: 'Section looping', body: "Whether or not it's a simon says style section", style: tooltipType});
+ bullshitUI.add(loopCheck);
+
+ */
+ }
+
+ override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array)
+ {
+ if (id == FlxUICheckBox.CLICK_EVENT)
+ {
+ var check:FlxUICheckBox = cast sender;
+ var label = check.getLabel().text;
+ switch (label)
+ {
+ case 'Camera Points to P1?':
+ _song.notes[curSection].mustHitSection = check.checked;
+ case 'Change BPM':
+ _song.notes[curSection].changeBPM = check.checked;
+ FlxG.log.add('changed bpm shit');
+ case "Alternate Animation":
+ _song.notes[curSection].altAnim = check.checked;
+ }
+ }
+ else if (id == FlxUINumericStepper.CHANGE_EVENT && (sender is FlxUINumericStepper))
+ {
+ var nums:FlxUINumericStepper = cast sender;
+ var wname = nums.name;
+ FlxG.log.add(wname);
+ if (wname == 'section_length')
+ {
+ if (nums.value <= 4)
+ nums.value = 4;
+ _song.notes[curSection].lengthInSteps = Std.int(nums.value);
+ updateGrid();
+ }
+ else if (wname == 'song_speed')
+ {
+ if (nums.value <= 0)
+ nums.value = 0;
+ _song.speed = nums.value;
+ }
+ else if (wname == 'song_bpm')
+ {
+ if (nums.value <= 0)
+ nums.value = 1;
+ tempBpm = Std.int(nums.value);
+ Conductor.mapBPMChanges(_song);
+ Conductor.changeBPM(Std.int(nums.value));
+ }
+ else if (wname == 'note_susLength')
+ {
+ if (curSelectedNote == null)
+ return;
+
+ if (nums.value <= 0)
+ nums.value = 0;
+ curSelectedNote[2] = nums.value;
+ updateGrid();
+ }
+ else if (wname == 'section_bpm')
+ {
+ if (nums.value <= 0.1)
+ nums.value = 0.1;
+ _song.notes[curSection].bpm = Std.int(nums.value);
+ updateGrid();
+ }else if (wname == 'song_vocalvol')
+ {
+ if (nums.value <= 0.1)
+ nums.value = 0.1;
+ vocals.volume = nums.value;
+ }else if (wname == 'song_instvol')
+ {
+ if (nums.value <= 0.1)
+ nums.value = 0.1;
+ FlxG.sound.music.volume = nums.value;
+ }
+ }
+
+ // FlxG.log.add(id + " WEED " + sender + " WEED " + data + " WEED " + params);
+ }
+
+ var updatedSection:Bool = false;
+
+ /* this function got owned LOL
+ function lengthBpmBullshit():Float
+ {
+ if (_song.notes[curSection].changeBPM)
+ return _song.notes[curSection].lengthInSteps * (_song.notes[curSection].bpm / _song.bpm);
+ else
+ return _song.notes[curSection].lengthInSteps;
+ }*/
+
+ function stepStartTime(step):Float
+ {
+ return _song.bpm / (step / 4) / 60;
+ }
+
+ function sectionStartTime():Float
+ {
+ var daBPM:Float = _song.bpm;
+ var daPos:Float = 0;
+ for (i in 0...curSection)
+ {
+ if (_song.notes[i].changeBPM)
+ {
+ daBPM = _song.notes[i].bpm;
+ }
+ daPos += 4 * (1000 * 60 / daBPM);
+ }
+ return daPos;
+ }
+
+ var writingNotes:Bool = false;
+ var doSnapShit:Bool = true;
+
+ override function update(elapsed:Float)
+ {
+ updateHeads();
+
+ snapText.text = "Snap: 1/" + snap + " (" + (doSnapShit ? "Control to disable" : "Snap Disabled, Control to renable") + ")\nAdd Notes: 1-8 (or click)\n";
+
+ curStep = recalculateSteps();
+
+ /*if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.RIGHT)
+ snap = snap * 2;
+ if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.LEFT)
+ snap = Math.round(snap / 2);
+ if (snap >= 192)
+ snap = 192;
+ if (snap <= 1)
+ snap = 1;*/
+
+ if (FlxG.keys.justPressed.CONTROL)
+ doSnapShit = !doSnapShit;
+
+ Conductor.songPosition = FlxG.sound.music.time;
+ _song.song = typingShit.text;
+
+ var left = FlxG.keys.justPressed.ONE;
+ var down = FlxG.keys.justPressed.TWO;
+ var up = FlxG.keys.justPressed.THREE;
+ var right = FlxG.keys.justPressed.FOUR;
+ var leftO = FlxG.keys.justPressed.FIVE;
+ var downO = FlxG.keys.justPressed.SIX;
+ var upO = FlxG.keys.justPressed.SEVEN;
+ var rightO = FlxG.keys.justPressed.EIGHT;
+
+ var pressArray = [left, down, up, right, leftO, downO, upO, rightO];
+ var delete = false;
+ curRenderedNotes.forEach(function(note:Note)
+ {
+ if (strumLine.overlaps(note) && pressArray[Math.floor(Math.abs(note.noteData))])
+ {
+ deleteNote(note);
+ delete = true;
+ trace('deelte note');
+ }
+ });
+ for (p in 0...pressArray.length)
+ {
+ var i = pressArray[p];
+ if (i && !delete)
+ {
+ addNote(new Note(Conductor.songPosition,p));
+ }
+ }
+
+ strumLine.y = getYfromStrum((Conductor.songPosition - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps));
+
+
+
+ if (playClaps)
+ {
+ curRenderedNotes.forEach(function(note:Note)
+ {
+ if (FlxG.sound.music.playing)
+ {
+ FlxG.overlap(strumLine, note, function(_, _)
+ {
+ if(!claps.contains(note))
+ {
+ claps.push(note);
+ FlxG.sound.play(Paths.sound('SNAP'));
+ }
+ });
+ }
+ });
+ }
+ /*curRenderedNotes.forEach(function(note:Note) {
+ if (strumLine.overlaps(note) && strumLine.y == note.y) // yandere dev type shit
+ {
+ if (_song.notes[curSection].mustHitSection)
+ {
+ trace('must hit ' + Math.abs(note.noteData));
+ if (note.noteData < 4)
+ {
+ switch (Math.abs(note.noteData))
+ {
+ case 2:
+ player1.playAnim('singUP', true);
+ case 3:
+ player1.playAnim('singRIGHT', true);
+ case 1:
+ player1.playAnim('singDOWN', true);
+ case 0:
+ player1.playAnim('singLEFT', true);
+ }
+ }
+ if (note.noteData >= 4)
+ {
+ switch (note.noteData)
+ {
+ case 6:
+ player2.playAnim('singUP', true);
+ case 7:
+ player2.playAnim('singRIGHT', true);
+ case 5:
+ player2.playAnim('singDOWN', true);
+ case 4:
+ player2.playAnim('singLEFT', true);
+ }
+ }
+ }
+ else
+ {
+ trace('hit ' + Math.abs(note.noteData));
+ if (note.noteData < 4)
+ {
+ switch (Math.abs(note.noteData))
+ {
+ case 2:
+ player2.playAnim('singUP', true);
+ case 3:
+ player2.playAnim('singRIGHT', true);
+ case 1:
+ player2.playAnim('singDOWN', true);
+ case 0:
+ player2.playAnim('singLEFT', true);
+ }
+ }
+ if (note.noteData >= 4)
+ {
+ switch (note.noteData)
+ {
+ case 6:
+ player1.playAnim('singUP', true);
+ case 7:
+ player1.playAnim('singRIGHT', true);
+ case 5:
+ player1.playAnim('singDOWN', true);
+ case 4:
+ player1.playAnim('singLEFT', true);
+ }
+ }
+ }
+ }
+ });*/
+
+ if (curBeat % 4 == 0 && curStep >= 16 * (curSection + 1))
+ {
+ trace(curStep);
+ trace((_song.notes[curSection].lengthInSteps) * (curSection + 1));
+ trace('DUMBSHIT');
+
+ if (_song.notes[curSection + 1] == null)
+ {
+ addSection();
+ }
+
+ changeSection(curSection + 1, false);
+ }
+
+ FlxG.watch.addQuick('daBeat', curBeat);
+ FlxG.watch.addQuick('daStep', curStep);
+
+ if (FlxG.mouse.justPressed)
+ {
+ if (FlxG.mouse.overlaps(curRenderedNotes))
+ {
+ curRenderedNotes.forEach(function(note:Note)
+ {
+ if (FlxG.mouse.overlaps(note))
+ {
+ if (FlxG.keys.pressed.CONTROL)
+ {
+ selectNote(note);
+ }
+ else
+ {
+ deleteNote(note);
+ }
+ }
+ });
+ }
+ else
+ {
+ if (FlxG.mouse.x > gridBG.x
+ && FlxG.mouse.x < gridBG.x + gridBG.width
+ && FlxG.mouse.y > gridBG.y
+ && FlxG.mouse.y < gridBG.y + (GRID_SIZE * _song.notes[curSection].lengthInSteps))
+ {
+ FlxG.log.add('added note');
+ addNote();
+ }
+ }
+ }
+
+ if (FlxG.mouse.x > gridBG.x
+ && FlxG.mouse.x < gridBG.x + gridBG.width
+ && FlxG.mouse.y > gridBG.y
+ && FlxG.mouse.y < gridBG.y + (GRID_SIZE * _song.notes[curSection].lengthInSteps))
+ {
+ dummyArrow.x = Math.floor(FlxG.mouse.x / GRID_SIZE) * GRID_SIZE;
+ if (FlxG.keys.pressed.SHIFT)
+ dummyArrow.y = FlxG.mouse.y;
+ else
+ dummyArrow.y = Math.floor(FlxG.mouse.y / GRID_SIZE) * GRID_SIZE;
+ }
+
+ if (FlxG.keys.justPressed.ENTER)
+ {
+ lastSection = curSection;
+
+ PlayState.SONG = _song;
+ FlxG.sound.music.stop();
+ vocals.stop();
+ LoadingState.loadAndSwitchState(new PlayState());
+ }
+
+ if (FlxG.keys.justPressed.E)
+ {
+ changeNoteSustain(Conductor.stepCrochet);
+ }
+ if (FlxG.keys.justPressed.Q)
+ {
+ changeNoteSustain(-Conductor.stepCrochet);
+ }
+
+ if (FlxG.keys.justPressed.TAB)
+ {
+ if (FlxG.keys.pressed.SHIFT)
+ {
+ UI_box.selected_tab -= 1;
+ if (UI_box.selected_tab < 0)
+ UI_box.selected_tab = 2;
+ }
+ else
+ {
+ UI_box.selected_tab += 1;
+ if (UI_box.selected_tab >= 3)
+ UI_box.selected_tab = 0;
+ }
+ }
+
+ if (!typingShit.hasFocus)
+ {
+
+ if (FlxG.keys.pressed.CONTROL)
+ {
+ if (FlxG.keys.justPressed.Z && lastNote != null)
+ {
+ trace(curRenderedNotes.members.contains(lastNote) ? "delete note" : "add note");
+ if (curRenderedNotes.members.contains(lastNote))
+ deleteNote(lastNote);
+ else
+ addNote(lastNote);
+ }
+ }
+
+ var shiftThing:Int = 1;
+ if (FlxG.keys.pressed.SHIFT)
+ shiftThing = 4;
+ if (!FlxG.keys.pressed.CONTROL)
+ {
+ if (FlxG.keys.justPressed.RIGHT || FlxG.keys.justPressed.D)
+ changeSection(curSection + shiftThing);
+ if (FlxG.keys.justPressed.LEFT || FlxG.keys.justPressed.A)
+ changeSection(curSection - shiftThing);
+ }
+ if (FlxG.keys.justPressed.SPACE)
+ {
+ if (FlxG.sound.music.playing)
+ {
+ FlxG.sound.music.pause();
+ vocals.pause();
+ claps.splice(0, claps.length);
+ }
+ else
+ {
+ vocals.play();
+ FlxG.sound.music.play();
+ }
+ }
+
+ if (FlxG.keys.justPressed.R)
+ {
+ if (FlxG.keys.pressed.SHIFT)
+ resetSection(true);
+ else
+ resetSection();
+ }
+
+
+ if (FlxG.sound.music.time < 0 || curStep < 0)
+ FlxG.sound.music.time = 0;
+
+ if (FlxG.mouse.wheel != 0)
+ {
+ FlxG.sound.music.pause();
+ vocals.pause();
+ claps.splice(0, claps.length);
+
+ var stepMs = curStep * Conductor.stepCrochet;
+
+
+ trace(Conductor.stepCrochet / snap);
+
+ if (doSnapShit)
+ FlxG.sound.music.time = stepMs - (FlxG.mouse.wheel * Conductor.stepCrochet / snap);
+ else
+ FlxG.sound.music.time -= (FlxG.mouse.wheel * Conductor.stepCrochet * 0.4);
+ trace(stepMs + " + " + Conductor.stepCrochet / snap + " -> " + FlxG.sound.music.time);
+
+ vocals.time = FlxG.sound.music.time;
+ }
+
+ if (!FlxG.keys.pressed.SHIFT)
+ {
+ if (FlxG.keys.pressed.W || FlxG.keys.pressed.S)
+ {
+ FlxG.sound.music.pause();
+ vocals.pause();
+ claps.splice(0, claps.length);
+
+ var daTime:Float = 700 * FlxG.elapsed;
+
+ if (FlxG.keys.pressed.W)
+ {
+ FlxG.sound.music.time -= daTime;
+ }
+ else
+ FlxG.sound.music.time += daTime;
+
+ vocals.time = FlxG.sound.music.time;
+ }
+ }
+ else
+ {
+ if (FlxG.keys.justPressed.W || FlxG.keys.justPressed.S)
+ {
+ FlxG.sound.music.pause();
+ vocals.pause();
+
+ var daTime:Float = Conductor.stepCrochet * 2;
+
+ if (FlxG.keys.justPressed.W)
+ {
+ FlxG.sound.music.time -= daTime;
+ }
+ else
+ FlxG.sound.music.time += daTime;
+
+ vocals.time = FlxG.sound.music.time;
+ }
+ }
+ }
+
+ _song.bpm = tempBpm;
+
+ /* if (FlxG.keys.justPressed.UP)
+ Conductor.changeBPM(Conductor.bpm + 1);
+ if (FlxG.keys.justPressed.DOWN)
+ Conductor.changeBPM(Conductor.bpm - 1); */
+
+ bpmTxt.text = bpmTxt.text = Std.string(FlxMath.roundDecimal(Conductor.songPosition / 1000, 2))
+ + " / "
+ + Std.string(FlxMath.roundDecimal(FlxG.sound.music.length / 1000, 2))
+ + "\nSection: "
+ + curSection
+ + "\nCurStep: "
+ + curStep;
+ super.update(elapsed);
+ }
+
+ function changeNoteSustain(value:Float):Void
+ {
+ if (curSelectedNote != null)
+ {
+ if (curSelectedNote[2] != null)
+ {
+ curSelectedNote[2] += value;
+ curSelectedNote[2] = Math.max(curSelectedNote[2], 0);
+ }
+ }
+
+ updateNoteUI();
+ updateGrid();
+ }
+
+ override function beatHit()
+ {
+ trace('beat');
+
+ super.beatHit();
+ if (!player2.animation.curAnim.name.startsWith("sing"))
+ {
+ player2.playAnim('idle');
+ }
+ player1.dance();
+ }
+
+ function recalculateSteps():Int
+ {
+ var lastChange:BPMChangeEvent = {
+ stepTime: 0,
+ songTime: 0,
+ bpm: 0
+ }
+ for (i in 0...Conductor.bpmChangeMap.length)
+ {
+ if (FlxG.sound.music.time > Conductor.bpmChangeMap[i].songTime)
+ lastChange = Conductor.bpmChangeMap[i];
+ }
+
+ curStep = lastChange.stepTime + Math.floor((FlxG.sound.music.time - lastChange.songTime) / Conductor.stepCrochet);
+ updateBeat();
+
+ return curStep;
+ }
+
+ function resetSection(songBeginning:Bool = false):Void
+ {
+ updateGrid();
+
+ FlxG.sound.music.pause();
+ vocals.pause();
+
+ // Basically old shit from changeSection???
+ FlxG.sound.music.time = sectionStartTime();
+
+ if (songBeginning)
+ {
+ FlxG.sound.music.time = 0;
+ curSection = 0;
+ }
+
+ vocals.time = FlxG.sound.music.time;
+ updateCurStep();
+
+ updateGrid();
+ updateSectionUI();
+ }
+
+ function changeSection(sec:Int = 0, ?updateMusic:Bool = true):Void
+ {
+ trace('changing section' + sec);
+
+ if (_song.notes[sec] != null)
+ {
+ trace('naw im not null');
+ curSection = sec;
+
+ updateGrid();
+
+ if (updateMusic)
+ {
+ FlxG.sound.music.pause();
+ vocals.pause();
+
+ /*var daNum:Int = 0;
+ var daLength:Float = 0;
+ while (daNum <= sec)
+ {
+ daLength += lengthBpmBullshit();
+ daNum++;
+ }*/
+
+ FlxG.sound.music.time = sectionStartTime();
+ vocals.time = FlxG.sound.music.time;
+ updateCurStep();
+ }
+
+ updateGrid();
+ updateSectionUI();
+ }
+ else
+ trace('bro wtf I AM NULL');
+ }
+
+ function copySection(?sectionNum:Int = 1)
+ {
+ var daSec = FlxMath.maxInt(curSection, sectionNum);
+
+ for (note in _song.notes[daSec - sectionNum].sectionNotes)
+ {
+ var strum = note[0] + Conductor.stepCrochet * (_song.notes[daSec].lengthInSteps * sectionNum);
+
+ var copiedNote:Array = [strum, note[1], note[2]];
+ _song.notes[daSec].sectionNotes.push(copiedNote);
+ }
+
+ updateGrid();
+ }
+
+ function updateSectionUI():Void
+ {
+ var sec = _song.notes[curSection];
+
+ stepperLength.value = sec.lengthInSteps;
+ check_mustHitSection.checked = sec.mustHitSection;
+ check_altAnim.checked = sec.altAnim;
+ check_changeBPM.checked = sec.changeBPM;
+ stepperSectionBPM.value = sec.bpm;
+ }
+
+ function updateHeads():Void
+ {
+ if (check_mustHitSection.checked)
+ {
+ leftIcon.animation.play(_song.player1);
+ rightIcon.animation.play(_song.player2);
+ }
+ else
+ {
+ leftIcon.animation.play(_song.player2);
+ rightIcon.animation.play(_song.player1);
+ }
+ }
+
+ function updateNoteUI():Void
+ {
+ if (curSelectedNote != null)
+ stepperSusLength.value = curSelectedNote[2];
+ }
+
+ function updateGrid():Void
+ {
+ remove(gridBG);
+ gridBG = FlxGridOverlay.create(GRID_SIZE, GRID_SIZE, GRID_SIZE * 8, GRID_SIZE * _song.notes[curSection].lengthInSteps);
+ add(gridBG);
+
+ remove(gridBlackLine);
+ gridBlackLine = new FlxSprite(gridBG.x + gridBG.width / 2).makeGraphic(2, Std.int(gridBG.height), FlxColor.BLACK);
+ add(gridBlackLine);
+
+ while (curRenderedNotes.members.length > 0)
+ {
+ curRenderedNotes.remove(curRenderedNotes.members[0], true);
+ }
+
+ while (curRenderedSustains.members.length > 0)
+ {
+ curRenderedSustains.remove(curRenderedSustains.members[0], true);
+ }
+
+ var sectionInfo:Array = _song.notes[curSection].sectionNotes;
+
+ if (_song.notes[curSection].changeBPM && _song.notes[curSection].bpm > 0)
+ {
+ Conductor.changeBPM(_song.notes[curSection].bpm);
+ FlxG.log.add('CHANGED BPM!');
+ }
+ else
+ {
+ // get last bpm
+ var daBPM:Float = _song.bpm;
+ for (i in 0...curSection)
+ if (_song.notes[i].changeBPM)
+ daBPM = _song.notes[i].bpm;
+ Conductor.changeBPM(daBPM);
+ }
+
+ /* // PORT BULLSHIT, INCASE THERE'S NO SUSTAIN DATA FOR A NOTE
+ for (sec in 0..._song.notes.length)
+ {
+ for (notesse in 0..._song.notes[sec].sectionNotes.length)
+ {
+ if (_song.notes[sec].sectionNotes[notesse][2] == null)
+ {
+ trace('SUS NULL');
+ _song.notes[sec].sectionNotes[notesse][2] = 0;
+ }
+ }
+ }
+ */
+
+ for (i in sectionInfo)
+ {
+ var daNoteInfo = i[1];
+ var daStrumTime = i[0];
+ var daSus = i[2];
+
+ var note:Note = new Note(daStrumTime, daNoteInfo % 4,null,false,true);
+ note.sustainLength = daSus;
+ note.setGraphicSize(GRID_SIZE, GRID_SIZE);
+ note.updateHitbox();
+ note.x = Math.floor(daNoteInfo * GRID_SIZE);
+ note.y = Math.floor(getYfromStrum((daStrumTime - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps)));
+
+ if (curSelectedNote != null)
+ if (curSelectedNote[0] == note.strumTime)
+ lastNote = note;
+
+ curRenderedNotes.add(note);
+
+ if (daSus > 0)
+ {
+ var sustainVis:FlxSprite = new FlxSprite(note.x + (GRID_SIZE / 2),
+ note.y + GRID_SIZE).makeGraphic(8, Math.floor(FlxMath.remapToRange(daSus, 0, Conductor.stepCrochet * _song.notes[curSection].lengthInSteps, 0, gridBG.height)));
+ curRenderedSustains.add(sustainVis);
+ }
+ }
+ }
+
+ private function addSection(lengthInSteps:Int = 16):Void
+ {
+ var sec:SwagSection = {
+ lengthInSteps: lengthInSteps,
+ bpm: _song.bpm,
+ changeBPM: false,
+ mustHitSection: true,
+ sectionNotes: [],
+ typeOfSection: 0,
+ altAnim: false
+ };
+
+ _song.notes.push(sec);
+ }
+
+ function selectNote(note:Note):Void
+ {
+ var swagNum:Int = 0;
+
+ for (i in _song.notes[curSection].sectionNotes)
+ {
+ if (i.strumTime == note.strumTime && i.noteData % 4 == note.noteData)
+ {
+ curSelectedNote = _song.notes[curSection].sectionNotes[swagNum];
+ }
+
+ swagNum += 1;
+ }
+
+ updateGrid();
+ updateNoteUI();
+ }
+
+
+ function deleteNote(note:Note):Void
+ {
+ lastNote = note;
+ for (i in _song.notes[curSection].sectionNotes)
+ {
+ if (i[0] == note.strumTime && i[1] % 4 == note.noteData)
+ {
+ _song.notes[curSection].sectionNotes.remove(i);
+ }
+ }
+
+ updateGrid();
+ }
+
+ function clearSection():Void
+ {
+ _song.notes[curSection].sectionNotes = [];
+
+ updateGrid();
+ }
+
+ function clearSong():Void
+ {
+ for (daSection in 0..._song.notes.length)
+ {
+ _song.notes[daSection].sectionNotes = [];
+ }
+
+ updateGrid();
+ }
+
+ private function newSection(lengthInSteps:Int = 16,mustHitSection:Bool = false,altAnim:Bool = true):SwagSection
+ {
+ var sec:SwagSection = {
+ lengthInSteps: lengthInSteps,
+ bpm: _song.bpm,
+ changeBPM: false,
+ mustHitSection: mustHitSection,
+ sectionNotes: [],
+ typeOfSection: 0,
+ altAnim: altAnim
+ };
+
+ return sec;
+ }
+
+ function shiftNotes(measure:Int=0,step:Int=0,ms:Int = 0):Void
+ {
+ var newSong = [];
+
+ var millisecadd = (((measure*4)+step/4)*(60000/_song.bpm))+ms;
+ var totaladdsection = Std.int((millisecadd/(60000/_song.bpm)/4));
+ trace(millisecadd,totaladdsection);
+ if(millisecadd > 0)
+ {
+ for(i in 0...totaladdsection)
+ {
+ newSong.unshift(newSection());
+ }
+ }
+ for (daSection1 in 0..._song.notes.length)
+ {
+ newSong.push(newSection(16,_song.notes[daSection1].mustHitSection,_song.notes[daSection1].altAnim));
+ }
+
+ for (daSection in 0...(_song.notes.length))
+ {
+ var aimtosetsection = daSection+Std.int((totaladdsection));
+ if(aimtosetsection<0) aimtosetsection = 0;
+ newSong[aimtosetsection].mustHitSection = _song.notes[daSection].mustHitSection;
+ newSong[aimtosetsection].altAnim = _song.notes[daSection].altAnim;
+ //trace("section "+daSection);
+ for(daNote in 0...(_song.notes[daSection].sectionNotes.length))
+ {
+ var newtiming = _song.notes[daSection].sectionNotes[daNote][0]+millisecadd;
+ if(newtiming<0)
+ {
+ newtiming = 0;
+ }
+ var futureSection = Math.floor(newtiming/4/(60000/_song.bpm));
+ _song.notes[daSection].sectionNotes[daNote][0] = newtiming;
+ newSong[futureSection].sectionNotes.push(_song.notes[daSection].sectionNotes[daNote]);
+
+ //newSong.notes[daSection].sectionNotes.remove(_song.notes[daSection].sectionNotes[daNote]);
+ }
+
+ }
+ //trace("DONE BITCH");
+ _song.notes = newSong;
+ updateGrid();
+ updateSectionUI();
+ updateNoteUI();
+ }
+ private function addNote(?n:Note):Void
+ {
+ var noteStrum = getStrumTime(dummyArrow.y) + sectionStartTime();
+ var noteData = Math.floor(FlxG.mouse.x / GRID_SIZE);
+ var noteSus = 0;
+
+ if (n != null)
+ _song.notes[curSection].sectionNotes.push([n.strumTime, n.noteData, n.sustainLength]);
+ else
+ _song.notes[curSection].sectionNotes.push([noteStrum, noteData, noteSus]);
+
+ var thingy = _song.notes[curSection].sectionNotes[_song.notes[curSection].sectionNotes.length - 1];
+
+ curSelectedNote = thingy;
+
+ updateGrid();
+ updateNoteUI();
+
+ autosaveSong();
+ }
+
+ function getStrumTime(yPos:Float):Float
+ {
+ return FlxMath.remapToRange(yPos, gridBG.y, gridBG.y + gridBG.height, 0, 16 * Conductor.stepCrochet);
+ }
+
+ function getYfromStrum(strumTime:Float):Float
+ {
+ return FlxMath.remapToRange(strumTime, 0, 16 * Conductor.stepCrochet, gridBG.y, gridBG.y + gridBG.height);
+ }
+
+ /*
+ function calculateSectionLengths(?sec:SwagSection):Int
+ {
+ var daLength:Int = 0;
+
+ for (i in _song.notes)
+ {
+ var swagLength = i.lengthInSteps;
+
+ if (i.typeOfSection == Section.COPYCAT)
+ swagLength * 2;
+
+ daLength += swagLength;
+
+ if (sec != null && sec == i)
+ {
+ trace('swag loop??');
+ break;
+ }
+ }
+
+ return daLength;
+ }*/
+ private var daSpacing:Float = 0.3;
+
+ function loadLevel():Void
+ {
+ trace(_song.notes);
+ }
+
+ function getNotes():Array
+ {
+ var noteData:Array = [];
+
+ for (i in _song.notes)
+ {
+ noteData.push(i.sectionNotes);
+ }
+
+ return noteData;
+ }
+
+ function loadJson(song:String):Void
+ {
+ PlayState.SONG = Song.loadFromJson(song.toLowerCase(), song.toLowerCase());
+ LoadingState.loadAndSwitchState(new ChartingState());
+ }
+
+ function loadAutosave():Void
+ {
+ PlayState.SONG = Song.parseJSONshit(FlxG.save.data.autosave);
+ LoadingState.loadAndSwitchState(new ChartingState());
+ }
+
+ function autosaveSong():Void
+ {
+ FlxG.save.data.autosave = Json.stringify({
+ "song": _song
+ });
+ FlxG.save.flush();
+ }
+
+ private function saveLevel()
+ {
+ var json = {
+ "song": _song
+ };
+
+ var data:String = Json.stringify(json);
+
+ if ((data != null) && (data.length > 0))
+ {
+ _file = new FileReference();
+ _file.addEventListener(Event.COMPLETE, onSaveComplete);
+ _file.addEventListener(Event.CANCEL, onSaveCancel);
+ _file.addEventListener(IOErrorEvent.IO_ERROR, onSaveError);
+ _file.save(data.trim(), _song.song.toLowerCase() + ".json");
+ }
+ }
+
+ function onSaveComplete(_):Void
+ {
+ _file.removeEventListener(Event.COMPLETE, onSaveComplete);
+ _file.removeEventListener(Event.CANCEL, onSaveCancel);
+ _file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
+ _file = null;
+ FlxG.log.notice("Successfully saved LEVEL DATA.");
+ }
+
+ /**
+ * Called when the save file dialog is cancelled.
+ */
+ function onSaveCancel(_):Void
+ {
+ _file.removeEventListener(Event.COMPLETE, onSaveComplete);
+ _file.removeEventListener(Event.CANCEL, onSaveCancel);
+ _file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
+ _file = null;
+ }
+
+ /**
+ * Called if there is an error while saving the gameplay recording.
+ */
+ function onSaveError(_):Void
+ {
+ _file.removeEventListener(Event.COMPLETE, onSaveComplete);
+ _file.removeEventListener(Event.CANCEL, onSaveCancel);
+ _file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
+ _file = null;
+ FlxG.log.error("Problem saving Level data");
+ }
+}
diff --git a/source - Copy/Conductor.hx b/source - Copy/Conductor.hx
new file mode 100644
index 0000000..03847d1
--- /dev/null
+++ b/source - Copy/Conductor.hx
@@ -0,0 +1,78 @@
+package;
+
+import Song.SwagSong;
+import flixel.FlxG;
+
+/**
+ * ...
+ * @author
+ */
+
+typedef BPMChangeEvent =
+{
+ var stepTime:Int;
+ var songTime:Float;
+ var bpm:Float;
+}
+
+class Conductor
+{
+ public static var bpm:Float = 100;
+ public static var crochet:Float = ((60 / bpm) * 1000); // beats in milliseconds
+ public static var stepCrochet:Float = crochet / 4; // steps in milliseconds
+ public static var songPosition:Float;
+ public static var lastSongPos:Float;
+ public static var offset:Float = 0;
+
+ public static var safeFrames:Int = 10;
+ public static var safeZoneOffset:Float = Math.floor((safeFrames / 60) * 1000); // is calculated in create(), is safeFrames in milliseconds
+ public static var timeScale:Float = Conductor.safeZoneOffset / 166;
+
+ public static var bpmChangeMap:Array = [];
+
+ public function new()
+ {
+ }
+
+ public static function recalculateTimings()
+ {
+ Conductor.safeFrames = FlxG.save.data.frames;
+ Conductor.safeZoneOffset = Math.floor((Conductor.safeFrames / 60) * 1000);
+ Conductor.timeScale = Conductor.safeZoneOffset / 166;
+ }
+
+ public static function mapBPMChanges(song:SwagSong)
+ {
+ bpmChangeMap = [];
+
+ var curBPM:Float = song.bpm;
+ var totalSteps:Int = 0;
+ var totalPos:Float = 0;
+ for (i in 0...song.notes.length)
+ {
+ if(song.notes[i].changeBPM && song.notes[i].bpm != curBPM)
+ {
+ curBPM = song.notes[i].bpm;
+ var event:BPMChangeEvent = {
+ stepTime: totalSteps,
+ songTime: totalPos,
+ bpm: curBPM
+ };
+ bpmChangeMap.push(event);
+ }
+
+ var deltaSteps:Int = song.notes[i].lengthInSteps;
+ totalSteps += deltaSteps;
+ totalPos += ((60 / curBPM) * 1000 / 4) * deltaSteps;
+ }
+ trace("new BPM map BUDDY " + bpmChangeMap);
+ }
+
+ public static function changeBPM(newBpm:Float)
+ {
+ bpm = newBpm;
+
+ crochet = ((60 / bpm) * 1000);
+ stepCrochet = crochet / 4;
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/Controls.hx b/source - Copy/Controls.hx
new file mode 100644
index 0000000..ac44eed
--- /dev/null
+++ b/source - Copy/Controls.hx
@@ -0,0 +1,762 @@
+package;
+
+import flixel.FlxG;
+import flixel.input.FlxInput;
+import flixel.input.actions.FlxAction;
+import flixel.input.actions.FlxActionInput;
+import flixel.input.actions.FlxActionInputDigital;
+import flixel.input.actions.FlxActionManager;
+import flixel.input.actions.FlxActionSet;
+import flixel.input.gamepad.FlxGamepadButton;
+import flixel.input.gamepad.FlxGamepadInputID;
+import flixel.input.keyboard.FlxKey;
+
+#if (haxe >= "4.0.0")
+enum abstract Action(String) to String from String
+{
+ var UP = "up";
+ var LEFT = "left";
+ var RIGHT = "right";
+ var DOWN = "down";
+ var UP_P = "up-press";
+ var LEFT_P = "left-press";
+ var RIGHT_P = "right-press";
+ var DOWN_P = "down-press";
+ var UP_R = "up-release";
+ var LEFT_R = "left-release";
+ var RIGHT_R = "right-release";
+ var DOWN_R = "down-release";
+ var ACCEPT = "accept";
+ var BACK = "back";
+ var PAUSE = "pause";
+ var RESET = "reset";
+ var CHEAT = "cheat";
+}
+#else
+@:enum
+abstract Action(String) to String from String
+{
+ var UP = "up";
+ var LEFT = "left";
+ var RIGHT = "right";
+ var DOWN = "down";
+ var UP_P = "up-press";
+ var LEFT_P = "left-press";
+ var RIGHT_P = "right-press";
+ var DOWN_P = "down-press";
+ var UP_R = "up-release";
+ var LEFT_R = "left-release";
+ var RIGHT_R = "right-release";
+ var DOWN_R = "down-release";
+ var ACCEPT = "accept";
+ var BACK = "back";
+ var PAUSE = "pause";
+ var RESET = "reset";
+ var CHEAT = "cheat";
+}
+#end
+
+enum Device
+{
+ Keys;
+ Gamepad(id:Int);
+}
+
+/**
+ * Since, in many cases multiple actions should use similar keys, we don't want the
+ * rebinding UI to list every action. ActionBinders are what the user percieves as
+ * an input so, for instance, they can't set jump-press and jump-release to different keys.
+ */
+enum Control
+{
+ UP;
+ LEFT;
+ RIGHT;
+ DOWN;
+ RESET;
+ ACCEPT;
+ BACK;
+ PAUSE;
+ CHEAT;
+}
+
+enum KeyboardScheme
+{
+ Solo;
+ Duo(first:Bool);
+ None;
+ Custom;
+}
+
+/**
+ * A list of actions that a player would invoke via some input device.
+ * Uses FlxActions to funnel various inputs to a single action.
+ */
+class Controls extends FlxActionSet
+{
+ var _up = new FlxActionDigital(Action.UP);
+ var _left = new FlxActionDigital(Action.LEFT);
+ var _right = new FlxActionDigital(Action.RIGHT);
+ var _down = new FlxActionDigital(Action.DOWN);
+ var _upP = new FlxActionDigital(Action.UP_P);
+ var _leftP = new FlxActionDigital(Action.LEFT_P);
+ var _rightP = new FlxActionDigital(Action.RIGHT_P);
+ var _downP = new FlxActionDigital(Action.DOWN_P);
+ var _upR = new FlxActionDigital(Action.UP_R);
+ var _leftR = new FlxActionDigital(Action.LEFT_R);
+ var _rightR = new FlxActionDigital(Action.RIGHT_R);
+ var _downR = new FlxActionDigital(Action.DOWN_R);
+ var _accept = new FlxActionDigital(Action.ACCEPT);
+ var _back = new FlxActionDigital(Action.BACK);
+ var _pause = new FlxActionDigital(Action.PAUSE);
+ var _reset = new FlxActionDigital(Action.RESET);
+ var _cheat = new FlxActionDigital(Action.CHEAT);
+
+ #if (haxe >= "4.0.0")
+ var byName:Map = [];
+ #else
+ var byName:Map = new Map();
+ #end
+
+ public var gamepadsAdded:Array = [];
+ public var keyboardScheme = KeyboardScheme.None;
+
+ public var UP(get, never):Bool;
+
+ inline function get_UP()
+ return _up.check();
+
+ public var LEFT(get, never):Bool;
+
+ inline function get_LEFT()
+ return _left.check();
+
+ public var RIGHT(get, never):Bool;
+
+ inline function get_RIGHT()
+ return _right.check();
+
+ public var DOWN(get, never):Bool;
+
+ inline function get_DOWN()
+ return _down.check();
+
+ public var UP_P(get, never):Bool;
+
+ inline function get_UP_P()
+ return _upP.check();
+
+ public var LEFT_P(get, never):Bool;
+
+ inline function get_LEFT_P()
+ return _leftP.check();
+
+ public var RIGHT_P(get, never):Bool;
+
+ inline function get_RIGHT_P()
+ return _rightP.check();
+
+ public var DOWN_P(get, never):Bool;
+
+ inline function get_DOWN_P()
+ return _downP.check();
+
+ public var UP_R(get, never):Bool;
+
+ inline function get_UP_R()
+ return _upR.check();
+
+ public var LEFT_R(get, never):Bool;
+
+ inline function get_LEFT_R()
+ return _leftR.check();
+
+ public var RIGHT_R(get, never):Bool;
+
+ inline function get_RIGHT_R()
+ return _rightR.check();
+
+ public var DOWN_R(get, never):Bool;
+
+ inline function get_DOWN_R()
+ return _downR.check();
+
+ public var ACCEPT(get, never):Bool;
+
+ inline function get_ACCEPT()
+ return _accept.check();
+
+ public var BACK(get, never):Bool;
+
+ inline function get_BACK()
+ return _back.check();
+
+ public var PAUSE(get, never):Bool;
+
+ inline function get_PAUSE()
+ return _pause.check();
+
+ public var RESET(get, never):Bool;
+
+ inline function get_RESET()
+ return _reset.check();
+
+ public var CHEAT(get, never):Bool;
+
+ inline function get_CHEAT()
+ return _cheat.check();
+
+ #if (haxe >= "4.0.0")
+ public function new(name, scheme = None)
+ {
+ super(name);
+
+ add(_up);
+ add(_left);
+ add(_right);
+ add(_down);
+ add(_upP);
+ add(_leftP);
+ add(_rightP);
+ add(_downP);
+ add(_upR);
+ add(_leftR);
+ add(_rightR);
+ add(_downR);
+ add(_accept);
+ add(_back);
+ add(_pause);
+ add(_reset);
+ add(_cheat);
+
+ for (action in digitalActions)
+ byName[action.name] = action;
+
+ setKeyboardScheme(scheme, false);
+ }
+ #else
+ public function new(name, scheme:KeyboardScheme = null)
+ {
+ super(name);
+
+ add(_up);
+ add(_left);
+ add(_right);
+ add(_down);
+ add(_upP);
+ add(_leftP);
+ add(_rightP);
+ add(_downP);
+ add(_upR);
+ add(_leftR);
+ add(_rightR);
+ add(_downR);
+ add(_accept);
+ add(_back);
+ add(_pause);
+ add(_reset);
+ add(_cheat);
+
+ for (action in digitalActions)
+ byName[action.name] = action;
+
+ if (scheme == null)
+ scheme = None;
+ setKeyboardScheme(scheme, false);
+ }
+ #end
+
+ override function update()
+ {
+ super.update();
+ }
+
+ // inline
+ public function checkByName(name:Action):Bool
+ {
+ #if debug
+ if (!byName.exists(name))
+ throw 'Invalid name: $name';
+ #end
+ return byName[name].check();
+ }
+
+ public function getDialogueName(action:FlxActionDigital):String
+ {
+ var input = action.inputs[0];
+ return switch input.device
+ {
+ case KEYBOARD: return '[${(input.inputID : FlxKey)}]';
+ case GAMEPAD: return '(${(input.inputID : FlxGamepadInputID)})';
+ case device: throw 'unhandled device: $device';
+ }
+ }
+
+ public function getDialogueNameFromToken(token:String):String
+ {
+ return getDialogueName(getActionFromControl(Control.createByName(token.toUpperCase())));
+ }
+
+ function getActionFromControl(control:Control):FlxActionDigital
+ {
+ return switch (control)
+ {
+ case UP: _up;
+ case DOWN: _down;
+ case LEFT: _left;
+ case RIGHT: _right;
+ case ACCEPT: _accept;
+ case BACK: _back;
+ case PAUSE: _pause;
+ case RESET: _reset;
+ case CHEAT: _cheat;
+ }
+ }
+
+ static function init():Void
+ {
+ var actions = new FlxActionManager();
+ FlxG.inputs.add(actions);
+ }
+
+ /**
+ * Calls a function passing each action bound by the specified control
+ * @param control
+ * @param func
+ * @return ->Void)
+ */
+ function forEachBound(control:Control, func:FlxActionDigital->FlxInputState->Void)
+ {
+ switch (control)
+ {
+ case UP:
+ func(_up, PRESSED);
+ func(_upP, JUST_PRESSED);
+ func(_upR, JUST_RELEASED);
+ case LEFT:
+ func(_left, PRESSED);
+ func(_leftP, JUST_PRESSED);
+ func(_leftR, JUST_RELEASED);
+ case RIGHT:
+ func(_right, PRESSED);
+ func(_rightP, JUST_PRESSED);
+ func(_rightR, JUST_RELEASED);
+ case DOWN:
+ func(_down, PRESSED);
+ func(_downP, JUST_PRESSED);
+ func(_downR, JUST_RELEASED);
+ case ACCEPT:
+ func(_accept, JUST_PRESSED);
+ case BACK:
+ func(_back, JUST_PRESSED);
+ case PAUSE:
+ func(_pause, JUST_PRESSED);
+ case RESET:
+ func(_reset, JUST_PRESSED);
+ case CHEAT:
+ func(_cheat, JUST_PRESSED);
+ }
+ }
+
+ public function replaceBinding(control:Control, device:Device, ?toAdd:Int, ?toRemove:Int)
+ {
+ if (toAdd == toRemove)
+ return;
+
+ switch (device)
+ {
+ case Keys:
+ if (toRemove != null)
+ unbindKeys(control, [toRemove]);
+ if (toAdd != null)
+ bindKeys(control, [toAdd]);
+
+ case Gamepad(id):
+ if (toRemove != null)
+ unbindButtons(control, id, [toRemove]);
+ if (toAdd != null)
+ bindButtons(control, id, [toAdd]);
+ }
+ }
+
+ public function copyFrom(controls:Controls, ?device:Device)
+ {
+ #if (haxe >= "4.0.0")
+ for (name => action in controls.byName)
+ {
+ for (input in action.inputs)
+ {
+ if (device == null || isDevice(input, device))
+ byName[name].add(cast input);
+ }
+ }
+ #else
+ for (name in controls.byName.keys())
+ {
+ var action = controls.byName[name];
+ for (input in action.inputs)
+ {
+ if (device == null || isDevice(input, device))
+ byName[name].add(cast input);
+ }
+ }
+ #end
+
+ switch (device)
+ {
+ case null:
+ // add all
+ #if (haxe >= "4.0.0")
+ for (gamepad in controls.gamepadsAdded)
+ if (!gamepadsAdded.contains(gamepad))
+ gamepadsAdded.push(gamepad);
+ #else
+ for (gamepad in controls.gamepadsAdded)
+ if (gamepadsAdded.indexOf(gamepad) == -1)
+ gamepadsAdded.push(gamepad);
+ #end
+
+ mergeKeyboardScheme(controls.keyboardScheme);
+
+ case Gamepad(id):
+ gamepadsAdded.push(id);
+ case Keys:
+ mergeKeyboardScheme(controls.keyboardScheme);
+ }
+ }
+
+ inline public function copyTo(controls:Controls, ?device:Device)
+ {
+ controls.copyFrom(this, device);
+ }
+
+ function mergeKeyboardScheme(scheme:KeyboardScheme):Void
+ {
+ if (scheme != None)
+ {
+ switch (keyboardScheme)
+ {
+ case None:
+ keyboardScheme = scheme;
+ default:
+ keyboardScheme = Custom;
+ }
+ }
+ }
+
+ /**
+ * Sets all actions that pertain to the binder to trigger when the supplied keys are used.
+ * If binder is a literal you can inline this
+ */
+ public function bindKeys(control:Control, keys:Array)
+ {
+ #if (haxe >= "4.0.0")
+ inline forEachBound(control, (action, state) -> addKeys(action, keys, state));
+ #else
+ forEachBound(control, function(action, state) addKeys(action, keys, state));
+ #end
+ }
+
+ /**
+ * Sets all actions that pertain to the binder to trigger when the supplied keys are used.
+ * If binder is a literal you can inline this
+ */
+ public function unbindKeys(control:Control, keys:Array)
+ {
+ #if (haxe >= "4.0.0")
+ inline forEachBound(control, (action, _) -> removeKeys(action, keys));
+ #else
+ forEachBound(control, function(action, _) removeKeys(action, keys));
+ #end
+ }
+
+ inline static function addKeys(action:FlxActionDigital, keys:Array, state:FlxInputState)
+ {
+ for (key in keys)
+ action.addKey(key, state);
+ }
+
+ static function removeKeys(action:FlxActionDigital, keys:Array)
+ {
+ var i = action.inputs.length;
+ while (i-- > 0)
+ {
+ var input = action.inputs[i];
+ if (input.device == KEYBOARD && keys.indexOf(cast input.inputID) != -1)
+ action.remove(input);
+ }
+ }
+
+ public function setKeyboardScheme(scheme:KeyboardScheme, reset = true)
+ {
+
+ loadKeyBinds();
+ /*if (reset)
+ removeKeyboard();
+
+ keyboardScheme = scheme;
+
+ #if (haxe >= "4.0.0")
+ switch (scheme)
+ {
+ case Solo:
+ inline bindKeys(Control.UP, [FlxKey.fromString("W"), FlxKey.UP]);
+ inline bindKeys(Control.DOWN, [FlxKey.fromString("S"), FlxKey.DOWN]);
+ inline bindKeys(Control.LEFT, [FlxKey.fromString("A"), FlxKey.LEFT]);
+ inline bindKeys(Control.RIGHT, [FlxKey.fromString("D"), FlxKey.RIGHT]);
+ inline bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]);
+ inline bindKeys(Control.BACK, [BACKSPACE, ESCAPE]);
+ inline bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]);
+ inline bindKeys(Control.RESET, [FlxKey.fromString("R")]);
+ case Duo(true):
+ inline bindKeys(Control.UP, [W, K]);
+ inline bindKeys(Control.DOWN, [S, J]);
+ inline bindKeys(Control.LEFT, [A, H]);
+ inline bindKeys(Control.RIGHT, [D, L]);
+ inline bindKeys(Control.ACCEPT, [Z]);
+ inline bindKeys(Control.BACK, [X]);
+ inline bindKeys(Control.PAUSE, [ONE]);
+ inline bindKeys(Control.RESET, [R]);
+ case Duo(false):
+ inline bindKeys(Control.UP, [FlxKey.UP]);
+ inline bindKeys(Control.DOWN, [FlxKey.DOWN]);
+ inline bindKeys(Control.LEFT, [FlxKey.LEFT]);
+ inline bindKeys(Control.RIGHT, [FlxKey.RIGHT]);
+ inline bindKeys(Control.ACCEPT, [O]);
+ inline bindKeys(Control.BACK, [P]);
+ inline bindKeys(Control.PAUSE, [ENTER]);
+ inline bindKeys(Control.RESET, [BACKSPACE]);
+ case None: // nothing
+ case Custom: // nothing
+ }
+ #else
+ switch (scheme)
+ {
+ case Solo:
+ bindKeys(Control.UP, [W, K, FlxKey.UP]);
+ bindKeys(Control.DOWN, [S, J, FlxKey.DOWN]);
+ bindKeys(Control.LEFT, [A, H, FlxKey.LEFT]);
+ bindKeys(Control.RIGHT, [D, L, FlxKey.RIGHT]);
+ bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]);
+ bindKeys(Control.BACK, [BACKSPACE, ESCAPE]);
+ bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]);
+ bindKeys(Control.RESET, [R]);
+ case Duo(true):
+ bindKeys(Control.UP, [W, K]);
+ bindKeys(Control.DOWN, [S, J]);
+ bindKeys(Control.LEFT, [A, H]);
+ bindKeys(Control.RIGHT, [D, L]);
+ bindKeys(Control.ACCEPT, [Z]);
+ bindKeys(Control.BACK, [X]);
+ bindKeys(Control.PAUSE, [ONE]);
+ bindKeys(Control.RESET, [R]);
+ case Duo(false):
+ bindKeys(Control.UP, [FlxKey.UP]);
+ bindKeys(Control.DOWN, [FlxKey.DOWN]);
+ bindKeys(Control.LEFT, [FlxKey.LEFT]);
+ bindKeys(Control.RIGHT, [FlxKey.RIGHT]);
+ bindKeys(Control.ACCEPT, [O]);
+ bindKeys(Control.BACK, [P]);
+ bindKeys(Control.PAUSE, [ENTER]);
+ bindKeys(Control.RESET, [BACKSPACE]);
+ case None: // nothing
+ case Custom: // nothing
+ }
+ #end*/
+ }
+
+ public function loadKeyBinds()
+ {
+
+ //trace(FlxKey.fromString(FlxG.save.data.upBind));
+
+ removeKeyboard();
+ KeyBinds.keyCheck();
+
+ inline bindKeys(Control.UP, [FlxKey.fromString(FlxG.save.data.upBind), FlxKey.UP]);
+ inline bindKeys(Control.DOWN, [FlxKey.fromString(FlxG.save.data.downBind), FlxKey.DOWN]);
+ inline bindKeys(Control.LEFT, [FlxKey.fromString(FlxG.save.data.leftBind), FlxKey.LEFT]);
+ inline bindKeys(Control.RIGHT, [FlxKey.fromString(FlxG.save.data.rightBind), FlxKey.RIGHT]);
+ inline bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]);
+ inline bindKeys(Control.BACK, [BACKSPACE, ESCAPE]);
+ inline bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]);
+ inline bindKeys(Control.RESET, [FlxKey.fromString(FlxG.save.data.killBind)]);
+ }
+
+ function removeKeyboard()
+ {
+ for (action in this.digitalActions)
+ {
+ var i = action.inputs.length;
+ while (i-- > 0)
+ {
+ var input = action.inputs[i];
+ if (input.device == KEYBOARD)
+ action.remove(input);
+ }
+ }
+ }
+
+ public function addGamepad(id:Int, ?buttonMap:Map>):Void
+ {
+ gamepadsAdded.push(id);
+
+ #if (haxe >= "4.0.0")
+ for (control => buttons in buttonMap)
+ inline bindButtons(control, id, buttons);
+ #else
+ for (control in buttonMap.keys())
+ bindButtons(control, id, buttonMap[control]);
+ #end
+ }
+
+ inline function addGamepadLiteral(id:Int, ?buttonMap:Map>):Void
+ {
+ gamepadsAdded.push(id);
+
+ #if (haxe >= "4.0.0")
+ for (control => buttons in buttonMap)
+ inline bindButtons(control, id, buttons);
+ #else
+ for (control in buttonMap.keys())
+ bindButtons(control, id, buttonMap[control]);
+ #end
+ }
+
+ public function removeGamepad(deviceID:Int = FlxInputDeviceID.ALL):Void
+ {
+ for (action in this.digitalActions)
+ {
+ var i = action.inputs.length;
+ while (i-- > 0)
+ {
+ var input = action.inputs[i];
+ if (input.device == GAMEPAD && (deviceID == FlxInputDeviceID.ALL || input.deviceID == deviceID))
+ action.remove(input);
+ }
+ }
+
+ gamepadsAdded.remove(deviceID);
+ }
+
+ public function addDefaultGamepad(id):Void
+ {
+ #if !switch
+ addGamepadLiteral(id, [
+ Control.ACCEPT => [A],
+ Control.BACK => [B],
+ Control.UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP],
+ Control.DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN],
+ Control.LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT],
+ Control.RIGHT => [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT],
+ Control.PAUSE => [START],
+ Control.RESET => [Y]
+ ]);
+ #else
+ addGamepadLiteral(id, [
+ //Swap A and B for switch
+ Control.ACCEPT => [B],
+ Control.BACK => [A],
+ Control.UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP],
+ Control.DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN],
+ Control.LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT],
+ Control.RIGHT => [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT],
+ Control.PAUSE => [START],
+ //Swap Y and X for switch
+ Control.RESET => [Y],
+ Control.CHEAT => [X]
+ ]);
+ #end
+ }
+
+ /**
+ * Sets all actions that pertain to the binder to trigger when the supplied keys are used.
+ * If binder is a literal you can inline this
+ */
+ public function bindButtons(control:Control, id, buttons)
+ {
+ #if (haxe >= "4.0.0")
+ inline forEachBound(control, (action, state) -> addButtons(action, buttons, state, id));
+ #else
+ forEachBound(control, function(action, state) addButtons(action, buttons, state, id));
+ #end
+ }
+
+ /**
+ * Sets all actions that pertain to the binder to trigger when the supplied keys are used.
+ * If binder is a literal you can inline this
+ */
+ public function unbindButtons(control:Control, gamepadID:Int, buttons)
+ {
+ #if (haxe >= "4.0.0")
+ inline forEachBound(control, (action, _) -> removeButtons(action, gamepadID, buttons));
+ #else
+ forEachBound(control, function(action, _) removeButtons(action, gamepadID, buttons));
+ #end
+ }
+
+ inline static function addButtons(action:FlxActionDigital, buttons:Array, state, id)
+ {
+ for (button in buttons)
+ action.addGamepad(button, state, id);
+ }
+
+ static function removeButtons(action:FlxActionDigital, gamepadID:Int, buttons:Array)
+ {
+ var i = action.inputs.length;
+ while (i-- > 0)
+ {
+ var input = action.inputs[i];
+ if (isGamepad(input, gamepadID) && buttons.indexOf(cast input.inputID) != -1)
+ action.remove(input);
+ }
+ }
+
+ public function getInputsFor(control:Control, device:Device, ?list:Array):Array
+ {
+ if (list == null)
+ list = [];
+
+ switch (device)
+ {
+ case Keys:
+ for (input in getActionFromControl(control).inputs)
+ {
+ if (input.device == KEYBOARD)
+ list.push(input.inputID);
+ }
+ case Gamepad(id):
+ for (input in getActionFromControl(control).inputs)
+ {
+ if (input.deviceID == id)
+ list.push(input.inputID);
+ }
+ }
+ return list;
+ }
+
+ public function removeDevice(device:Device)
+ {
+ switch (device)
+ {
+ case Keys:
+ setKeyboardScheme(None);
+ case Gamepad(id):
+ removeGamepad(id);
+ }
+ }
+
+ static function isDevice(input:FlxActionInput, device:Device)
+ {
+ return switch device
+ {
+ case Keys: input.device == KEYBOARD;
+ case Gamepad(id): isGamepad(input, id);
+ }
+ }
+
+ inline static function isGamepad(input:FlxActionInput, deviceID:Int)
+ {
+ return input.device == GAMEPAD && (deviceID == FlxInputDeviceID.ALL || input.deviceID == deviceID);
+ }
+}
diff --git a/source - Copy/ControlsSubState.hx b/source - Copy/ControlsSubState.hx
new file mode 100644
index 0000000..f35d74c
--- /dev/null
+++ b/source - Copy/ControlsSubState.hx
@@ -0,0 +1,12 @@
+package;
+
+import flixel.FlxSprite;
+import flixel.FlxSubState;
+
+class ControlsSubState extends FlxSubState
+{
+ public function new()
+ {
+ super();
+ }
+}
diff --git a/source - Copy/ConvertScore.hx b/source - Copy/ConvertScore.hx
new file mode 100644
index 0000000..9eba969
--- /dev/null
+++ b/source - Copy/ConvertScore.hx
@@ -0,0 +1,21 @@
+class ConvertScore
+{
+ public static function convertScore(noteDiff:Float):Int
+ {
+ var daRating:String = Ratings.CalculateRating(noteDiff, 166);
+
+ switch(daRating)
+ {
+ case 'shit':
+ return -300;
+ case 'bad':
+ return 0;
+ case 'good':
+ return 200;
+ case 'sick':
+ return 350;
+ }
+ return 0;
+ }
+
+}
\ No newline at end of file
diff --git a/source - Copy/CoolUtil.hx b/source - Copy/CoolUtil.hx
new file mode 100644
index 0000000..24dc749
--- /dev/null
+++ b/source - Copy/CoolUtil.hx
@@ -0,0 +1,49 @@
+package;
+
+import lime.utils.Assets;
+
+using StringTools;
+
+class CoolUtil
+{
+ public static var difficultyArray:Array = ['Easy', "Normal", "Hard"];
+
+ public static function difficultyFromInt(difficulty:Int):String
+ {
+ return difficultyArray[difficulty];
+ }
+
+ public static function coolTextFile(path:String):Array
+ {
+ var daList:Array = Assets.getText(path).trim().split('\n');
+
+ for (i in 0...daList.length)
+ {
+ daList[i] = daList[i].trim();
+ }
+
+ return daList;
+ }
+
+ public static function coolStringFile(path:String):Array
+ {
+ var daList:Array = path.trim().split('\n');
+
+ for (i in 0...daList.length)
+ {
+ daList[i] = daList[i].trim();
+ }
+
+ return daList;
+ }
+
+ public static function numberArray(max:Int, ?min = 0):Array
+ {
+ var dumbArray:Array = [];
+ for (i in min...max)
+ {
+ dumbArray.push(i);
+ }
+ return dumbArray;
+ }
+}
diff --git a/source - Copy/DialogueBox.hx b/source - Copy/DialogueBox.hx
new file mode 100644
index 0000000..929eb24
--- /dev/null
+++ b/source - Copy/DialogueBox.hx
@@ -0,0 +1,260 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.text.FlxTypeText;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxSpriteGroup;
+import flixel.input.FlxKeyManager;
+import flixel.text.FlxText;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
+
+using StringTools;
+
+class DialogueBox extends FlxSpriteGroup
+{
+ var box:FlxSprite;
+
+ var curCharacter:String = '';
+
+ var dialogue:Alphabet;
+ var dialogueList:Array = [];
+
+ // SECOND DIALOGUE FOR THE PIXEL SHIT INSTEAD???
+ var swagDialogue:FlxTypeText;
+
+ var dropText:FlxText;
+
+ public var finishThing:Void->Void;
+
+ var portraitLeft:FlxSprite;
+ var portraitRight:FlxSprite;
+
+ var handSelect:FlxSprite;
+ var bgFade:FlxSprite;
+
+ public function new(talkingRight:Bool = true, ?dialogueList:Array)
+ {
+ super();
+
+ switch (PlayState.SONG.song.toLowerCase())
+ {
+ case 'senpai':
+ FlxG.sound.playMusic(Paths.music('Lunchbox'), 0);
+ FlxG.sound.music.fadeIn(1, 0, 0.8);
+ case 'thorns':
+ FlxG.sound.playMusic(Paths.music('LunchboxScary'), 0);
+ FlxG.sound.music.fadeIn(1, 0, 0.8);
+ }
+
+ bgFade = new FlxSprite(-200, -200).makeGraphic(Std.int(FlxG.width * 1.3), Std.int(FlxG.height * 1.3), 0xFFB3DFd8);
+ bgFade.scrollFactor.set();
+ bgFade.alpha = 0;
+ add(bgFade);
+
+ new FlxTimer().start(0.83, function(tmr:FlxTimer)
+ {
+ bgFade.alpha += (1 / 5) * 0.7;
+ if (bgFade.alpha > 0.7)
+ bgFade.alpha = 0.7;
+ }, 5);
+
+ box = new FlxSprite(-20, 45);
+
+ var hasDialog = false;
+ switch (PlayState.SONG.song.toLowerCase())
+ {
+ case 'senpai':
+ hasDialog = true;
+ box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-pixel');
+ box.animation.addByPrefix('normalOpen', 'Text Box Appear', 24, false);
+ box.animation.addByIndices('normal', 'Text Box Appear', [4], "", 24);
+ case 'roses':
+ hasDialog = true;
+ FlxG.sound.play(Paths.sound('ANGRY_TEXT_BOX'));
+
+ box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-senpaiMad');
+ box.animation.addByPrefix('normalOpen', 'SENPAI ANGRY IMPACT SPEECH', 24, false);
+ box.animation.addByIndices('normal', 'SENPAI ANGRY IMPACT SPEECH', [4], "", 24);
+
+ case 'thorns':
+ hasDialog = true;
+ box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-evil');
+ box.animation.addByPrefix('normalOpen', 'Spirit Textbox spawn', 24, false);
+ box.animation.addByIndices('normal', 'Spirit Textbox spawn', [11], "", 24);
+
+ var face:FlxSprite = new FlxSprite(320, 170).loadGraphic(Paths.image('weeb/spiritFaceForward'));
+ face.setGraphicSize(Std.int(face.width * 6));
+ add(face);
+ }
+
+ this.dialogueList = dialogueList;
+
+ if (!hasDialog)
+ return;
+
+ portraitLeft = new FlxSprite(-20, 40);
+ portraitLeft.frames = Paths.getSparrowAtlas('weeb/senpaiPortrait');
+ portraitLeft.animation.addByPrefix('enter', 'Senpai Portrait Enter', 24, false);
+ portraitLeft.setGraphicSize(Std.int(portraitLeft.width * PlayState.daPixelZoom * 0.9));
+ portraitLeft.updateHitbox();
+ portraitLeft.scrollFactor.set();
+ add(portraitLeft);
+ portraitLeft.visible = false;
+
+ portraitRight = new FlxSprite(0, 40);
+ portraitRight.frames = Paths.getSparrowAtlas('weeb/bfPortrait');
+ portraitRight.animation.addByPrefix('enter', 'Boyfriend portrait enter', 24, false);
+ portraitRight.setGraphicSize(Std.int(portraitRight.width * PlayState.daPixelZoom * 0.9));
+ portraitRight.updateHitbox();
+ portraitRight.scrollFactor.set();
+ add(portraitRight);
+ portraitRight.visible = false;
+
+ box.animation.play('normalOpen');
+ box.setGraphicSize(Std.int(box.width * PlayState.daPixelZoom * 0.9));
+ box.updateHitbox();
+ add(box);
+
+ box.screenCenter(X);
+ portraitLeft.screenCenter(X);
+
+ handSelect = new FlxSprite(FlxG.width * 0.9, FlxG.height * 0.9).loadGraphic(Paths.image('weeb/pixelUI/hand_textbox'));
+ add(handSelect);
+
+
+ if (!talkingRight)
+ {
+ // box.flipX = true;
+ }
+
+ dropText = new FlxText(242, 502, Std.int(FlxG.width * 0.6), "", 32);
+ dropText.font = 'Pixel Arial 11 Bold';
+ dropText.color = 0xFFD89494;
+ add(dropText);
+
+ swagDialogue = new FlxTypeText(240, 500, Std.int(FlxG.width * 0.6), "", 32);
+ swagDialogue.font = 'Pixel Arial 11 Bold';
+ swagDialogue.color = 0xFF3F2021;
+ swagDialogue.sounds = [FlxG.sound.load(Paths.sound('pixelText'), 0.6)];
+ add(swagDialogue);
+
+ dialogue = new Alphabet(0, 80, "", false, true);
+ // dialogue.x = 90;
+ // add(dialogue);
+ }
+
+ var dialogueOpened:Bool = false;
+ var dialogueStarted:Bool = false;
+
+ override function update(elapsed:Float)
+ {
+ // HARD CODING CUZ IM STUPDI
+ if (PlayState.SONG.song.toLowerCase() == 'roses')
+ portraitLeft.visible = false;
+ if (PlayState.SONG.song.toLowerCase() == 'thorns')
+ {
+ portraitLeft.color = FlxColor.BLACK;
+ swagDialogue.color = FlxColor.WHITE;
+ dropText.color = FlxColor.BLACK;
+ }
+
+ dropText.text = swagDialogue.text;
+
+ if (box.animation.curAnim != null)
+ {
+ if (box.animation.curAnim.name == 'normalOpen' && box.animation.curAnim.finished)
+ {
+ box.animation.play('normal');
+ dialogueOpened = true;
+ }
+ }
+
+ if (dialogueOpened && !dialogueStarted)
+ {
+ startDialogue();
+ dialogueStarted = true;
+ }
+
+ if (FlxG.keys.justPressed.ANY && dialogueStarted == true)
+ {
+ remove(dialogue);
+
+ FlxG.sound.play(Paths.sound('clickText'), 0.8);
+
+ if (dialogueList[1] == null && dialogueList[0] != null)
+ {
+ if (!isEnding)
+ {
+ isEnding = true;
+
+ if (PlayState.SONG.song.toLowerCase() == 'senpai' || PlayState.SONG.song.toLowerCase() == 'thorns')
+ FlxG.sound.music.fadeOut(2.2, 0);
+
+ new FlxTimer().start(0.2, function(tmr:FlxTimer)
+ {
+ box.alpha -= 1 / 5;
+ bgFade.alpha -= 1 / 5 * 0.7;
+ portraitLeft.visible = false;
+ portraitRight.visible = false;
+ swagDialogue.alpha -= 1 / 5;
+ dropText.alpha = swagDialogue.alpha;
+ }, 5);
+
+ new FlxTimer().start(1.2, function(tmr:FlxTimer)
+ {
+ finishThing();
+ kill();
+ });
+ }
+ }
+ else
+ {
+ dialogueList.remove(dialogueList[0]);
+ startDialogue();
+ }
+ }
+
+ super.update(elapsed);
+ }
+
+ var isEnding:Bool = false;
+
+ function startDialogue():Void
+ {
+ cleanDialog();
+ // var theDialog:Alphabet = new Alphabet(0, 70, dialogueList[0], false, true);
+ // dialogue = theDialog;
+ // add(theDialog);
+
+ // swagDialogue.text = ;
+ swagDialogue.resetText(dialogueList[0]);
+ swagDialogue.start(0.04, true);
+
+ switch (curCharacter)
+ {
+ case 'dad':
+ portraitRight.visible = false;
+ if (!portraitLeft.visible)
+ {
+ portraitLeft.visible = true;
+ portraitLeft.animation.play('enter');
+ }
+ case 'bf':
+ portraitLeft.visible = false;
+ if (!portraitRight.visible)
+ {
+ portraitRight.visible = true;
+ portraitRight.animation.play('enter');
+ }
+ }
+ }
+
+ function cleanDialog():Void
+ {
+ var splitName:Array = dialogueList[0].split(":");
+ curCharacter = splitName[1];
+ dialogueList[0] = dialogueList[0].substr(splitName[1].length + 2).trim();
+ }
+}
diff --git a/source - Copy/Discord.hx b/source - Copy/Discord.hx
new file mode 100644
index 0000000..00018e7
--- /dev/null
+++ b/source - Copy/Discord.hx
@@ -0,0 +1,89 @@
+package;
+
+#if windows
+import Sys.sleep;
+import discord_rpc.DiscordRpc;
+
+using StringTools;
+
+class DiscordClient
+{
+ public function new()
+ {
+ trace("Discord Client starting...");
+ DiscordRpc.start({
+ clientID: "557069829501091850", // change this to what ever the fuck you want lol
+ onReady: onReady,
+ onError: onError,
+ onDisconnected: onDisconnected
+ });
+ trace("Discord Client started.");
+
+ while (true)
+ {
+ DiscordRpc.process();
+ sleep(2);
+ //trace("Discord Client Update");
+ }
+
+ DiscordRpc.shutdown();
+ }
+
+ public static function shutdown()
+ {
+ DiscordRpc.shutdown();
+ }
+
+ static function onReady()
+ {
+ DiscordRpc.presence({
+ details: "In the Menus",
+ state: null,
+ largeImageKey: 'icon',
+ largeImageText: "fridaynightfunkin"
+ });
+ }
+
+ static function onError(_code:Int, _message:String)
+ {
+ trace('Error! $_code : $_message');
+ }
+
+ static function onDisconnected(_code:Int, _message:String)
+ {
+ trace('Disconnected! $_code : $_message');
+ }
+
+ public static function initialize()
+ {
+ var DiscordDaemon = sys.thread.Thread.create(() ->
+ {
+ new DiscordClient();
+ });
+ trace("Discord Client initialized");
+ }
+
+ public static function changePresence(details:String, state:Null, ?smallImageKey : String, ?hasStartTimestamp : Bool, ?endTimestamp: Float)
+ {
+ var startTimestamp:Float = if(hasStartTimestamp) Date.now().getTime() else 0;
+
+ if (endTimestamp > 0)
+ {
+ endTimestamp = startTimestamp + endTimestamp;
+ }
+
+ DiscordRpc.presence({
+ details: details,
+ state: state,
+ largeImageKey: 'icon',
+ largeImageText: "fridaynightfunkin",
+ smallImageKey : smallImageKey,
+ // Obtained times are in milliseconds so they are divided so Discord can use it
+ startTimestamp : Std.int(startTimestamp / 1000),
+ endTimestamp : Std.int(endTimestamp / 1000)
+ });
+
+ //trace('Discord RPC Updated. Arguments: $details, $state, $smallImageKey, $hasStartTimestamp, $endTimestamp');
+ }
+}
+#end
\ No newline at end of file
diff --git a/source - Copy/EtternaFunctions.hx b/source - Copy/EtternaFunctions.hx
new file mode 100644
index 0000000..9fcfbae
--- /dev/null
+++ b/source - Copy/EtternaFunctions.hx
@@ -0,0 +1,84 @@
+class EtternaFunctions
+{
+ // erf constants
+ public static var a1 = 0.254829592;
+ public static var a2 = -0.284496736;
+ public static var a3 = 1.421413741;
+ public static var a4 = -1.453152027;
+ public static var a5 = 1.061405429;
+ public static var p = 0.3275911;
+
+ public static function erf(x:Float):Float
+ {
+ // Save the sign of x
+ var sign = 1;
+ if (x < 0)
+ sign = -1;
+ x = Math.abs(x);
+
+ // A&S formula 7.1.26
+ var t = 1.0/(1.0 + p*x);
+ var y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*Math.exp(-x*x);
+
+ return sign*y;
+ }
+
+ public static function getNotes():Int
+ {
+ var notes:Int = 0;
+ for (i in 0...PlayState.SONG.notes.length)
+ {
+ for (ii in 0...PlayState.SONG.notes[i].sectionNotes.length)
+ {
+ var n = PlayState.SONG.notes[i].sectionNotes[ii];
+ if (n[1] <= 0)
+ notes++;
+ }
+ }
+ return notes;
+ }
+
+ public static function getHolds():Int
+ {
+ var notes:Int = 0;
+ for (i in 0...PlayState.SONG.notes.length)
+ {
+ trace(PlayState.SONG.notes[i]);
+ for (ii in 0...PlayState.SONG.notes[i].sectionNotes.length)
+ {
+ var n = PlayState.SONG.notes[i].sectionNotes[ii];
+ trace(n);
+ if (n[1] > 0)
+ notes++;
+ }
+ }
+ return notes;
+ }
+
+ public static function getMapMaxScore():Int
+ {
+ return (getNotes() * 350);
+ }
+
+ public static function wife3(maxms:Float, ts:Float)
+ {
+ var max_points = 1.0;
+ var miss_weight = -5.5;
+ var ridic= 5 * ts;
+ var max_boo_weight = 180 * ts;
+ var ts_pow = 0.75;
+ var zero = 65 * (Math.pow(ts,ts_pow));
+ var power = 2.5;
+ var dev = 22.7 * (Math.pow(ts,ts_pow));
+
+ if (maxms <= ridic) // anything below this (judge scaled) threshold is counted as full pts
+ return max_points;
+ else if (maxms <= zero) // ma/pa region, exponential
+ return max_points * erf((zero - maxms) / dev);
+ else if (maxms <= max_boo_weight)// cb region, linear
+ return (maxms - zero) * miss_weight / (max_boo_weight - zero);
+ else
+ return miss_weight;
+ }
+
+}
\ No newline at end of file
diff --git a/source - Copy/FreeplayState.hx b/source - Copy/FreeplayState.hx
new file mode 100644
index 0000000..daf04fb
--- /dev/null
+++ b/source - Copy/FreeplayState.hx
@@ -0,0 +1,332 @@
+package;
+
+import flash.text.TextField;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.display.FlxGridOverlay;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.math.FlxMath;
+import flixel.text.FlxText;
+import flixel.util.FlxColor;
+import lime.utils.Assets;
+
+
+#if windows
+import Discord.DiscordClient;
+#end
+
+using StringTools;
+
+class FreeplayState extends MusicBeatState
+{
+ var songs:Array = [];
+
+ var selector:FlxText;
+ var curSelected:Int = 0;
+ var curDifficulty:Int = 1;
+
+ var scoreText:FlxText;
+ var comboText:FlxText;
+ var diffText:FlxText;
+ var lerpScore:Int = 0;
+ var intendedScore:Int = 0;
+ var combo:String = '';
+
+ private var grpSongs:FlxTypedGroup;
+ private var curPlaying:Bool = false;
+
+ private var iconArray:Array = [];
+
+ override function create()
+ {
+ var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist'));
+
+ for (i in 0...initSonglist.length)
+ {
+ var data:Array = initSonglist[i].split(':');
+ songs.push(new SongMetadata(data[0], Std.parseInt(data[2]), data[1]));
+ }
+
+ /*
+ if (FlxG.sound.music != null)
+ {
+ if (!FlxG.sound.music.playing)
+ FlxG.sound.playMusic(Paths.music('freakyMenu'));
+ }
+ */
+
+ #if windows
+ // Updating Discord Rich Presence
+ DiscordClient.changePresence("In the Freeplay Menu", null);
+ #end
+
+ var isDebug:Bool = false;
+
+ #if debug
+ isDebug = true;
+ #end
+
+ // LOAD MUSIC
+
+ // LOAD CHARACTERS
+
+ var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuBGBlue'));
+ add(bg);
+
+ grpSongs = new FlxTypedGroup();
+ add(grpSongs);
+
+ for (i in 0...songs.length)
+ {
+ var songText:Alphabet = new Alphabet(0, (70 * i) + 30, songs[i].songName, true, false, true);
+ songText.isMenuItem = true;
+ songText.targetY = i;
+ grpSongs.add(songText);
+
+ var icon:HealthIcon = new HealthIcon(songs[i].songCharacter);
+ icon.sprTracker = songText;
+
+ // using a FlxGroup is too much fuss!
+ iconArray.push(icon);
+ add(icon);
+
+ // songText.x += 40;
+ // DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
+ // songText.screenCenter(X);
+ }
+
+ scoreText = new FlxText(FlxG.width * 0.7, 5, 0, "", 32);
+ // scoreText.autoSize = false;
+ scoreText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, RIGHT);
+ // scoreText.alignment = RIGHT;
+
+ var scoreBG:FlxSprite = new FlxSprite(scoreText.x - 6, 0).makeGraphic(Std.int(FlxG.width * 0.35), 66, 0xFF000000);
+ scoreBG.alpha = 0.6;
+ add(scoreBG);
+
+ diffText = new FlxText(scoreText.x, scoreText.y + 36, 0, "", 24);
+ diffText.font = scoreText.font;
+ add(diffText);
+
+ comboText = new FlxText(diffText.x + 100, diffText.y, 0, "", 24);
+ comboText.font = diffText.font;
+ add(comboText);
+
+ add(scoreText);
+
+ changeSelection();
+ changeDiff();
+
+ // FlxG.sound.playMusic(Paths.music('title'), 0);
+ // FlxG.sound.music.fadeIn(2, 0, 0.8);
+ selector = new FlxText();
+
+ selector.size = 40;
+ selector.text = ">";
+ // add(selector);
+
+ var swag:Alphabet = new Alphabet(1, 0, "swag");
+
+ // JUST DOIN THIS SHIT FOR TESTING!!!
+ /*
+ var md:String = Markdown.markdownToHtml(Assets.getText('CHANGELOG.md'));
+
+ var texFel:TextField = new TextField();
+ texFel.width = FlxG.width;
+ texFel.height = FlxG.height;
+ // texFel.
+ texFel.htmlText = md;
+
+ FlxG.stage.addChild(texFel);
+
+ // scoreText.textField.htmlText = md;
+
+ trace(md);
+ */
+
+ super.create();
+ }
+
+ public function addSong(songName:String, weekNum:Int, songCharacter:String)
+ {
+ songs.push(new SongMetadata(songName, weekNum, songCharacter));
+ }
+
+ public function addWeek(songs:Array, weekNum:Int, ?songCharacters:Array)
+ {
+ if (songCharacters == null)
+ songCharacters = ['dad'];
+
+ var num:Int = 0;
+ for (song in songs)
+ {
+ addSong(song, weekNum, songCharacters[num]);
+
+ if (songCharacters.length != 1)
+ num++;
+ }
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (FlxG.sound.music.volume < 0.7)
+ {
+ FlxG.sound.music.volume += 0.5 * FlxG.elapsed;
+ }
+
+ lerpScore = Math.floor(FlxMath.lerp(lerpScore, intendedScore, 0.4));
+
+ if (Math.abs(lerpScore - intendedScore) <= 10)
+ lerpScore = intendedScore;
+
+ scoreText.text = "PERSONAL BEST:" + lerpScore;
+ comboText.text = combo + '\n';
+
+ var upP = controls.UP_P;
+ var downP = controls.DOWN_P;
+ var accepted = controls.ACCEPT;
+
+ if (upP)
+ {
+ changeSelection(-1);
+ }
+ if (downP)
+ {
+ changeSelection(1);
+ }
+
+ if (controls.LEFT_P)
+ changeDiff(-1);
+ if (controls.RIGHT_P)
+ changeDiff(1);
+
+ if (controls.BACK)
+ {
+ FlxG.switchState(new MainMenuState());
+ }
+
+ if (accepted)
+ {
+ // adjusting the song name to be compatible
+ var songFormat = StringTools.replace(songs[curSelected].songName, " ", "-");
+ switch (songFormat) {
+ case 'Dad-Battle': songFormat = 'Dadbattle';
+ case 'Philly-Nice': songFormat = 'Philly';
+ }
+
+ trace(songs[curSelected].songName);
+
+ var poop:String = Highscore.formatSong(songFormat, curDifficulty);
+
+ trace(poop);
+
+ PlayState.SONG = Song.loadFromJson(poop, songs[curSelected].songName);
+ PlayState.isStoryMode = false;
+ PlayState.storyDifficulty = curDifficulty;
+ PlayState.storyWeek = songs[curSelected].week;
+ trace('CUR WEEK' + PlayState.storyWeek);
+ LoadingState.loadAndSwitchState(new PlayState());
+ }
+ }
+
+ function changeDiff(change:Int = 0)
+ {
+ curDifficulty += change;
+
+ if (curDifficulty < 0)
+ curDifficulty = 2;
+ if (curDifficulty > 2)
+ curDifficulty = 0;
+
+ // adjusting the highscore song name to be compatible (changeDiff)
+ var songHighscore = StringTools.replace(songs[curSelected].songName, " ", "-");
+ switch (songHighscore) {
+ case 'Dad-Battle': songHighscore = 'Dadbattle';
+ case 'Philly-Nice': songHighscore = 'Philly';
+ }
+
+ #if !switch
+ intendedScore = Highscore.getScore(songHighscore, curDifficulty);
+ combo = Highscore.getCombo(songHighscore, curDifficulty);
+ #end
+
+ diffText.text = CoolUtil.difficultyFromInt(curDifficulty).toUpperCase();
+ }
+
+ function changeSelection(change:Int = 0)
+ {
+ #if !switch
+ // NGio.logEvent('Fresh');
+ #end
+
+ // NGio.logEvent('Fresh');
+ FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
+
+ curSelected += change;
+
+ if (curSelected < 0)
+ curSelected = songs.length - 1;
+ if (curSelected >= songs.length)
+ curSelected = 0;
+
+ // selector.y = (70 * curSelected) + 30;
+
+ // adjusting the highscore song name to be compatible (changeSelection)
+ // would read original scores if we didn't change packages
+ var songHighscore = StringTools.replace(songs[curSelected].songName, " ", "-");
+ switch (songHighscore) {
+ case 'Dad-Battle': songHighscore = 'Dadbattle';
+ case 'Philly-Nice': songHighscore = 'Philly';
+ }
+
+ #if !switch
+ intendedScore = Highscore.getScore(songHighscore, curDifficulty);
+ combo = Highscore.getCombo(songHighscore, curDifficulty);
+ // lerpScore = 0;
+ #end
+
+ #if PRELOAD_ALL
+ FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0);
+ #end
+
+ var bullShit:Int = 0;
+
+ for (i in 0...iconArray.length)
+ {
+ iconArray[i].alpha = 0.6;
+ }
+
+ iconArray[curSelected].alpha = 1;
+
+ for (item in grpSongs.members)
+ {
+ item.targetY = bullShit - curSelected;
+ bullShit++;
+
+ item.alpha = 0.6;
+ // item.setGraphicSize(Std.int(item.width * 0.8));
+
+ if (item.targetY == 0)
+ {
+ item.alpha = 1;
+ // item.setGraphicSize(Std.int(item.width));
+ }
+ }
+ }
+}
+
+class SongMetadata
+{
+ public var songName:String = "";
+ public var week:Int = 0;
+ public var songCharacter:String = "";
+
+ public function new(song:String, week:Int, songCharacter:String)
+ {
+ this.songName = song;
+ this.week = week;
+ this.songCharacter = songCharacter;
+ }
+}
diff --git a/source - Copy/GameDimensions.hx b/source - Copy/GameDimensions.hx
new file mode 100644
index 0000000..db4a62a
--- /dev/null
+++ b/source - Copy/GameDimensions.hx
@@ -0,0 +1,7 @@
+package;
+
+class GameDimensions
+{
+ public static var width:Int = 1280;
+ public static var height:Int = 720;
+}
\ No newline at end of file
diff --git a/source - Copy/GameOverState.hx b/source - Copy/GameOverState.hx
new file mode 100644
index 0000000..c26c063
--- /dev/null
+++ b/source - Copy/GameOverState.hx
@@ -0,0 +1,82 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.input.gamepad.FlxGamepad;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+
+class GameOverState extends FlxTransitionableState
+{
+ var bfX:Float = 0;
+ var bfY:Float = 0;
+
+ public function new(x:Float, y:Float)
+ {
+ super();
+
+ bfX = x;
+ bfY = y;
+ }
+
+ override function create()
+ {
+ var loser:FlxSprite = new FlxSprite(100, 100);
+ var loseTex = Paths.getSparrowAtlas('lose');
+ loser.frames = loseTex;
+ loser.animation.addByPrefix('lose', 'lose', 24, false);
+ loser.animation.play('lose');
+ add(loser);
+
+ var bf:Boyfriend = new Boyfriend(bfX, bfY);
+ // bf.scrollFactor.set();
+ add(bf);
+ bf.playAnim('firstDeath');
+
+ FlxG.camera.follow(bf, LOCKON, 0.001);
+
+ var restart:FlxSprite = new FlxSprite(500, 50).loadGraphic(Paths.image('restart'));
+ restart.setGraphicSize(Std.int(restart.width * 0.6));
+ restart.updateHitbox();
+ restart.alpha = 0;
+ restart.antialiasing = true;
+ add(restart);
+
+ FlxG.sound.music.fadeOut(2, FlxG.sound.music.volume * 0.6);
+
+ FlxTween.tween(restart, {alpha: 1}, 1, {ease: FlxEase.quartInOut});
+ FlxTween.tween(restart, {y: restart.y + 40}, 7, {ease: FlxEase.quartInOut, type: PINGPONG});
+
+ super.create();
+ }
+
+ private var fading:Bool = false;
+
+ override function update(elapsed:Float)
+ {
+ var pressed:Bool = FlxG.keys.justPressed.ANY;
+
+ var gamepad:FlxGamepad = FlxG.gamepads.lastActive;
+
+ if (gamepad != null)
+ {
+ if (gamepad.justPressed.ANY)
+ pressed = true;
+ }
+
+ pressed = false;
+
+ if (pressed && !fading)
+ {
+ fading = true;
+ FlxG.sound.music.fadeOut(0.5, 0, function(twn:FlxTween)
+ {
+ FlxG.sound.music.stop();
+ LoadingState.loadAndSwitchState(new PlayState());
+ });
+ }
+ super.update(elapsed);
+ }
+}
diff --git a/source - Copy/GameOverSubstate.hx b/source - Copy/GameOverSubstate.hx
new file mode 100644
index 0000000..f784827
--- /dev/null
+++ b/source - Copy/GameOverSubstate.hx
@@ -0,0 +1,113 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxObject;
+import flixel.FlxSubState;
+import flixel.math.FlxPoint;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
+
+class GameOverSubstate extends MusicBeatSubstate
+{
+ var bf:Boyfriend;
+ var camFollow:FlxObject;
+
+ var stageSuffix:String = "";
+
+ public function new(x:Float, y:Float)
+ {
+ var daStage = PlayState.curStage;
+ var daBf:String = '';
+ switch (PlayState.SONG.player1)
+ {
+ case 'bf-pixel':
+ stageSuffix = '-pixel';
+ daBf = 'bf-pixel-dead';
+ default:
+ daBf = 'bf';
+ }
+
+ super();
+
+ Conductor.songPosition = 0;
+
+ bf = new Boyfriend(x, y, daBf);
+ add(bf);
+
+ camFollow = new FlxObject(bf.getGraphicMidpoint().x, bf.getGraphicMidpoint().y, 1, 1);
+ add(camFollow);
+
+ FlxG.sound.play(Paths.sound('fnf_loss_sfx' + stageSuffix));
+ Conductor.changeBPM(100);
+
+ // FlxG.camera.followLerp = 1;
+ // FlxG.camera.focusOn(FlxPoint.get(FlxG.width / 2, FlxG.height / 2));
+ FlxG.camera.scroll.set();
+ FlxG.camera.target = null;
+
+ bf.playAnim('firstDeath');
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (controls.ACCEPT)
+ {
+ endBullshit();
+ }
+
+ if (controls.BACK)
+ {
+ FlxG.sound.music.stop();
+
+ if (PlayState.isStoryMode)
+ FlxG.switchState(new StoryMenuState());
+ else
+ FlxG.switchState(new FreeplayState());
+ PlayState.loadRep = false;
+ }
+
+ if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.curFrame == 12)
+ {
+ FlxG.camera.follow(camFollow, LOCKON, 0.01);
+ }
+
+ if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.finished)
+ {
+ FlxG.sound.playMusic(Paths.music('gameOver' + stageSuffix));
+ }
+
+ if (FlxG.sound.music.playing)
+ {
+ Conductor.songPosition = FlxG.sound.music.time;
+ }
+ }
+
+ override function beatHit()
+ {
+ super.beatHit();
+
+ FlxG.log.add('beat');
+ }
+
+ var isEnding:Bool = false;
+
+ function endBullshit():Void
+ {
+ if (!isEnding)
+ {
+ isEnding = true;
+ bf.playAnim('deathConfirm', true);
+ FlxG.sound.music.stop();
+ FlxG.sound.play(Paths.music('gameOverEnd' + stageSuffix));
+ new FlxTimer().start(0.7, function(tmr:FlxTimer)
+ {
+ FlxG.camera.fade(FlxColor.BLACK, 2, false, function()
+ {
+ LoadingState.loadAndSwitchState(new PlayState());
+ });
+ });
+ }
+ }
+}
diff --git a/source - Copy/GameplayCustomizeState.hx b/source - Copy/GameplayCustomizeState.hx
new file mode 100644
index 0000000..7bcfa31
--- /dev/null
+++ b/source - Copy/GameplayCustomizeState.hx
@@ -0,0 +1,255 @@
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import flixel.text.FlxText;
+import flixel.math.FlxMath;
+import flixel.FlxCamera;
+import flixel.math.FlxPoint;
+import flixel.FlxObject;
+#if windows
+import Discord.DiscordClient;
+import sys.thread.Thread;
+#end
+
+import flixel.group.FlxGroup.FlxTypedGroup;
+import openfl.ui.Keyboard;
+import flixel.FlxSprite;
+import flixel.FlxG;
+
+class GameplayCustomizeState extends MusicBeatState
+{
+
+ var defaultX:Float = FlxG.width * 0.55 - 135;
+ var defaultY:Float = FlxG.height / 2 - 50;
+
+ var background:FlxSprite;
+ var curt:FlxSprite;
+ var front:FlxSprite;
+
+ var sick:FlxSprite;
+
+ var text:FlxText;
+ var blackBorder:FlxSprite;
+
+ var bf:Boyfriend;
+ var dad:Character;
+
+ var strumLine:FlxSprite;
+ var strumLineNotes:FlxTypedGroup;
+ var playerStrums:FlxTypedGroup;
+ private var camHUD:FlxCamera;
+
+ public override function create() {
+ #if windows
+ // Updating Discord Rich Presence
+ DiscordClient.changePresence("Customizing Gameplay", null);
+ #end
+
+ sick = new FlxSprite().loadGraphic(Paths.image('sick','shared'));
+ sick.scrollFactor.set();
+ background = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback','shared'));
+ curt = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains','shared'));
+ front = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront','shared'));
+
+ Conductor.changeBPM(102);
+ persistentUpdate = true;
+
+ super.create();
+
+ camHUD = new FlxCamera();
+ camHUD.bgColor.alpha = 0;
+ FlxG.cameras.add(camHUD);
+
+ background.scrollFactor.set(0.9,0.9);
+ curt.scrollFactor.set(0.9,0.9);
+ front.scrollFactor.set(0.9,0.9);
+
+ add(background);
+ add(front);
+ add(curt);
+
+ var camFollow = new FlxObject(0, 0, 1, 1);
+
+ dad = new Character(100, 100, 'dad');
+
+ bf = new Boyfriend(770, 450, 'bf');
+
+ var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x + 400, dad.getGraphicMidpoint().y);
+
+ camFollow.setPosition(camPos.x, camPos.y);
+
+ add(bf);
+ add(dad);
+
+ add(sick);
+
+ add(camFollow);
+
+ FlxG.camera.follow(camFollow, LOCKON, 0.01);
+ // FlxG.camera.setScrollBounds(0, FlxG.width, 0, FlxG.height);
+ FlxG.camera.zoom = 0.9;
+ FlxG.camera.focusOn(camFollow.getPosition());
+
+ strumLine = new FlxSprite(0, FlxG.save.data.strumline).makeGraphic(FlxG.width, 14);
+ strumLine.scrollFactor.set();
+ strumLine.alpha = 0.4;
+
+ add(strumLine);
+
+ if (FlxG.save.data.downscroll)
+ strumLine.y = FlxG.height - 165;
+
+ strumLineNotes = new FlxTypedGroup();
+ add(strumLineNotes);
+
+ playerStrums = new FlxTypedGroup();
+
+ sick.cameras = [camHUD];
+ strumLine.cameras = [camHUD];
+ playerStrums.cameras = [camHUD];
+
+ generateStaticArrows(0);
+ generateStaticArrows(1);
+
+ text = new FlxText(5, FlxG.height + 40, 0, "Drag around gameplay elements, R to reset, Escape to go back.", 12);
+ text.scrollFactor.set();
+ text.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+
+ blackBorder = new FlxSprite(-30,FlxG.height + 40).makeGraphic((Std.int(text.width + 900)),Std.int(text.height + 600),FlxColor.BLACK);
+ blackBorder.alpha = 0.5;
+
+ add(blackBorder);
+
+ add(text);
+
+ FlxTween.tween(text,{y: FlxG.height - 18},2,{ease: FlxEase.elasticInOut});
+ FlxTween.tween(blackBorder,{y: FlxG.height - 18},2, {ease: FlxEase.elasticInOut});
+
+ if (!FlxG.save.data.changedHit)
+ {
+ FlxG.save.data.changedHitX = defaultX;
+ FlxG.save.data.changedHitY = defaultY;
+ }
+
+ sick.x = FlxG.save.data.changedHitX;
+ sick.y = FlxG.save.data.changedHitY;
+
+
+ FlxG.mouse.visible = true;
+
+ }
+
+ override function update(elapsed:Float) {
+ if (FlxG.sound.music != null)
+ Conductor.songPosition = FlxG.sound.music.time;
+
+ super.update(elapsed);
+
+ FlxG.camera.zoom = FlxMath.lerp(0.9, FlxG.camera.zoom, 0.95);
+ camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95);
+
+ if (FlxG.mouse.overlaps(sick) && FlxG.mouse.pressed)
+ {
+ sick.x = FlxG.mouse.x - sick.width / 2;
+ sick.y = FlxG.mouse.y - sick.height;
+ }
+
+ for (i in playerStrums)
+ i.y = strumLine.y;
+ for (i in strumLineNotes)
+ i.y = strumLine.y;
+
+ if (FlxG.mouse.overlaps(sick) && FlxG.mouse.justReleased)
+ {
+ FlxG.save.data.changedHitX = sick.x;
+ FlxG.save.data.changedHitY = sick.y;
+ FlxG.save.data.changedHit = true;
+ }
+
+ if (FlxG.keys.justPressed.R)
+ {
+ sick.x = defaultX;
+ sick.y = defaultY;
+ FlxG.save.data.changedHitX = sick.x;
+ FlxG.save.data.changedHitY = sick.y;
+ FlxG.save.data.changedHit = false;
+ }
+
+ if (controls.BACK)
+ {
+ FlxG.mouse.visible = false;
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+ FlxG.switchState(new OptionsMenu());
+ }
+
+ }
+
+ override function beatHit()
+ {
+ super.beatHit();
+
+ bf.playAnim('idle');
+ dad.dance();
+
+ FlxG.camera.zoom += 0.015;
+ camHUD.zoom += 0.010;
+
+ trace('beat');
+
+ }
+
+
+ // ripped from play state cuz im lazy
+
+ private function generateStaticArrows(player:Int):Void
+ {
+ for (i in 0...4)
+ {
+ // FlxG.log.add(i);
+ var babyArrow:FlxSprite = new FlxSprite(0, strumLine.y);
+ babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets', 'shared');
+ babyArrow.animation.addByPrefix('green', 'arrowUP');
+ babyArrow.animation.addByPrefix('blue', 'arrowDOWN');
+ babyArrow.animation.addByPrefix('purple', 'arrowLEFT');
+ babyArrow.animation.addByPrefix('red', 'arrowRIGHT');
+ babyArrow.antialiasing = true;
+ babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7));
+ switch (Math.abs(i))
+ {
+ case 0:
+ babyArrow.x += Note.swagWidth * 0;
+ babyArrow.animation.addByPrefix('static', 'arrowLEFT');
+ babyArrow.animation.addByPrefix('pressed', 'left press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false);
+ case 1:
+ babyArrow.x += Note.swagWidth * 1;
+ babyArrow.animation.addByPrefix('static', 'arrowDOWN');
+ babyArrow.animation.addByPrefix('pressed', 'down press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false);
+ case 2:
+ babyArrow.x += Note.swagWidth * 2;
+ babyArrow.animation.addByPrefix('static', 'arrowUP');
+ babyArrow.animation.addByPrefix('pressed', 'up press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false);
+ case 3:
+ babyArrow.x += Note.swagWidth * 3;
+ babyArrow.animation.addByPrefix('static', 'arrowRIGHT');
+ babyArrow.animation.addByPrefix('pressed', 'right press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false);
+ }
+ babyArrow.updateHitbox();
+ babyArrow.scrollFactor.set();
+
+ babyArrow.ID = i;
+
+ if (player == 1)
+ playerStrums.add(babyArrow);
+
+ babyArrow.animation.play('static');
+ babyArrow.x += 50;
+ babyArrow.x += ((FlxG.width / 2) * player);
+
+ strumLineNotes.add(babyArrow);
+ }
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/GitarooPause.hx b/source - Copy/GitarooPause.hx
new file mode 100644
index 0000000..cb9705c
--- /dev/null
+++ b/source - Copy/GitarooPause.hx
@@ -0,0 +1,88 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+
+class GitarooPause extends MusicBeatState
+{
+ var replayButton:FlxSprite;
+ var cancelButton:FlxSprite;
+
+ var replaySelect:Bool = false;
+
+ public function new():Void
+ {
+ super();
+ }
+
+ override function create()
+ {
+ if (FlxG.sound.music != null)
+ FlxG.sound.music.stop();
+
+ var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('pauseAlt/pauseBG'));
+ add(bg);
+
+ var bf:FlxSprite = new FlxSprite(0, 30);
+ bf.frames = Paths.getSparrowAtlas('pauseAlt/bfLol');
+ bf.animation.addByPrefix('lol', "funnyThing", 13);
+ bf.animation.play('lol');
+ add(bf);
+ bf.screenCenter(X);
+
+ replayButton = new FlxSprite(FlxG.width * 0.28, FlxG.height * 0.7);
+ replayButton.frames = Paths.getSparrowAtlas('pauseAlt/pauseUI');
+ replayButton.animation.addByPrefix('selected', 'bluereplay', 0, false);
+ replayButton.animation.appendByPrefix('selected', 'yellowreplay');
+ replayButton.animation.play('selected');
+ add(replayButton);
+
+ cancelButton = new FlxSprite(FlxG.width * 0.58, replayButton.y);
+ cancelButton.frames = Paths.getSparrowAtlas('pauseAlt/pauseUI');
+ cancelButton.animation.addByPrefix('selected', 'bluecancel', 0, false);
+ cancelButton.animation.appendByPrefix('selected', 'cancelyellow');
+ cancelButton.animation.play('selected');
+ add(cancelButton);
+
+ changeThing();
+
+ super.create();
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (controls.LEFT_P || controls.RIGHT_P)
+ changeThing();
+
+ if (controls.ACCEPT)
+ {
+ if (replaySelect)
+ {
+ FlxG.switchState(new PlayState());
+ }
+ else
+ {
+ FlxG.switchState(new MainMenuState());
+ }
+ }
+
+ super.update(elapsed);
+ }
+
+ function changeThing():Void
+ {
+ replaySelect = !replaySelect;
+
+ if (replaySelect)
+ {
+ cancelButton.animation.curAnim.curFrame = 0;
+ replayButton.animation.curAnim.curFrame = 1;
+ }
+ else
+ {
+ cancelButton.animation.curAnim.curFrame = 1;
+ replayButton.animation.curAnim.curFrame = 0;
+ }
+ }
+}
diff --git a/source - Copy/GlobalVideo.hx b/source - Copy/GlobalVideo.hx
new file mode 100644
index 0000000..2c4f707
--- /dev/null
+++ b/source - Copy/GlobalVideo.hx
@@ -0,0 +1,95 @@
+package;
+
+import openfl.Lib;
+
+class GlobalVideo
+{
+ private static var video:VideoHandler;
+ private static var webm:WebmHandler;
+ public static var isWebm:Bool = false;
+ public static var isAndroid:Bool = false;
+ public static var daAlpha1:Float = 0.2;
+ public static var daAlpha2:Float = 1;
+
+ public static function setVid(vid:VideoHandler):Void
+ {
+ video = vid;
+ }
+
+ public static function getVid():VideoHandler
+ {
+ return video;
+ }
+
+ public static function setWebm(vid:WebmHandler):Void
+ {
+ webm = vid;
+ isWebm = true;
+ }
+
+ public static function getWebm():WebmHandler
+ {
+ return webm;
+ }
+
+ public static function get():Dynamic
+ {
+ if (isWebm)
+ {
+ return getWebm();
+ } else {
+ return getVid();
+ }
+ }
+
+ public static function calc(ind:Int):Dynamic
+ {
+ var stageWidth:Int = Lib.current.stage.stageWidth;
+ var stageHeight:Int = Lib.current.stage.stageHeight;
+
+ var width:Float = GameDimensions.width;
+ var height:Float = GameDimensions.height;
+
+ //trace("AH: " + stageWidth);
+ //trace(width);
+
+ var ratioX:Float = height / width;
+ var ratioY:Float = width / height;
+ var appliedWidth:Float = stageHeight * ratioY;
+ var appliedHeight:Float = stageWidth * ratioX;
+ //trace(appliedWidth);
+ var remainingX:Float = stageWidth - appliedWidth;
+ var remainingY:Float = stageHeight - appliedHeight;
+ remainingX = remainingX / 2;
+ remainingY = remainingY / 2;
+
+ appliedWidth = Std.int(appliedWidth);
+ appliedHeight = Std.int(appliedHeight);
+
+ if (appliedHeight > stageHeight)
+ {
+ remainingY = 0;
+ appliedHeight = stageHeight;
+ }
+
+ if (appliedWidth > stageWidth)
+ {
+ remainingX = 0;
+ appliedWidth = stageWidth;
+ }
+
+ switch(ind)
+ {
+ case 0:
+ return remainingX;
+ case 1:
+ return remainingY;
+ case 2:
+ return appliedWidth;
+ case 3:
+ return appliedHeight;
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/HealthIcon.hx b/source - Copy/HealthIcon.hx
new file mode 100644
index 0000000..74f46a1
--- /dev/null
+++ b/source - Copy/HealthIcon.hx
@@ -0,0 +1,58 @@
+package;
+
+import flixel.FlxSprite;
+
+class HealthIcon extends FlxSprite
+{
+ /**
+ * Used for FreeplayState! If you use it elsewhere, prob gonna annoying
+ */
+ public var sprTracker:FlxSprite;
+
+ public function new(char:String = 'bf', isPlayer:Bool = false)
+ {
+ super();
+
+ loadGraphic(Paths.image('iconGrid'), true, 150, 150);
+
+ antialiasing = true;
+ animation.add('bf', [0, 1], 0, false, isPlayer);
+ animation.add('bf-car', [0, 1], 0, false, isPlayer);
+ animation.add('bf-christmas', [0, 1], 0, false, isPlayer);
+ animation.add('bf-pixel', [21, 21], 0, false, isPlayer);
+ animation.add('spooky', [2, 3], 0, false, isPlayer);
+ animation.add('pico', [4, 5], 0, false, isPlayer);
+ animation.add('mom', [6, 7], 0, false, isPlayer);
+ animation.add('mom-car', [6, 7], 0, false, isPlayer);
+ animation.add('tankman', [8, 9], 0, false, isPlayer);
+ animation.add('face', [10, 11], 0, false, isPlayer);
+ animation.add('dad', [12, 13], 0, false, isPlayer);
+ animation.add('senpai', [22, 22], 0, false, isPlayer);
+ animation.add('senpai-angry', [22, 22], 0, false, isPlayer);
+ animation.add('spirit', [23, 23], 0, false, isPlayer);
+ animation.add('bf-old', [14, 15], 0, false, isPlayer);
+ animation.add('gf', [16], 0, false, isPlayer);
+ animation.add('gf-christmas', [16], 0, false, isPlayer);
+ animation.add('gf-pixel', [16], 0, false, isPlayer);
+ animation.add('parents-christmas', [17, 18], 0, false, isPlayer);
+ animation.add('monster', [19, 20], 0, false, isPlayer);
+ animation.add('monster-christmas', [19, 20], 0, false, isPlayer);
+ animation.play(char);
+
+ switch(char)
+ {
+ case 'bf-pixel' | 'senpai' | 'senpai-angry' | 'spirit' | 'gf-pixel':
+ antialiasing = false;
+ }
+
+ scrollFactor.set();
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (sprTracker != null)
+ setPosition(sprTracker.x + sprTracker.width + 10, sprTracker.y - 30);
+ }
+}
diff --git a/source - Copy/HelperFunctions.hx b/source - Copy/HelperFunctions.hx
new file mode 100644
index 0000000..b17dc6a
--- /dev/null
+++ b/source - Copy/HelperFunctions.hx
@@ -0,0 +1,15 @@
+import flixel.math.FlxMath;
+
+class HelperFunctions
+{
+ public static function truncateFloat( number : Float, precision : Int): Float {
+ var num = number;
+ num = num * Math.pow(10, precision);
+ num = Math.round( num ) / Math.pow(10, precision);
+ return num;
+ }
+
+ public static function GCD(a, b) {
+ return b == 0 ? FlxMath.absInt(a) : GCD(b, a % b);
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/Highscore.hx b/source - Copy/Highscore.hx
new file mode 100644
index 0000000..8d82fcb
--- /dev/null
+++ b/source - Copy/Highscore.hx
@@ -0,0 +1,159 @@
+package;
+
+import flixel.FlxG;
+
+using StringTools;
+class Highscore
+{
+ #if (haxe >= "4.0.0")
+ public static var songScores:Map = new Map();
+ public static var songCombos:Map = new Map();
+ #else
+ public static var songScores:Map = new Map();
+ public static var songCombos:Map = new Map();
+ #end
+
+
+ public static function saveScore(song:String, score:Int = 0, ?diff:Int = 0):Void
+ {
+ var daSong:String = formatSong(song, diff);
+
+
+ #if !switch
+ NGio.postScore(score, song);
+ #end
+
+ if(!FlxG.save.data.botplay)
+ {
+ if (songScores.exists(daSong))
+ {
+ if (songScores.get(daSong) < score)
+ setScore(daSong, score);
+ }
+ else
+ setScore(daSong, score);
+ }else trace('BotPlay detected. Score saving is disabled.');
+ }
+
+ public static function saveCombo(song:String, combo:String, ?diff:Int = 0):Void
+ {
+ var daSong:String = formatSong(song, diff);
+ var finalCombo:String = combo.split(')')[0].replace('(', '');
+
+ if(!FlxG.save.data.botplay)
+ {
+ if (songCombos.exists(daSong))
+ {
+ if (getComboInt(songCombos.get(daSong)) < getComboInt(finalCombo))
+ setCombo(daSong, finalCombo);
+ }
+ else
+ setCombo(daSong, finalCombo);
+ }
+ }
+
+ public static function saveWeekScore(week:Int = 1, score:Int = 0, ?diff:Int = 0):Void
+ {
+
+ #if !switch
+ NGio.postScore(score, "Week " + week);
+ #end
+
+ if(!FlxG.save.data.botplay)
+ {
+ var daWeek:String = formatSong('week' + week, diff);
+
+ if (songScores.exists(daWeek))
+ {
+ if (songScores.get(daWeek) < score)
+ setScore(daWeek, score);
+ }
+ else
+ setScore(daWeek, score);
+ }else trace('BotPlay detected. Score saving is disabled.');
+ }
+
+ /**
+ * YOU SHOULD FORMAT SONG WITH formatSong() BEFORE TOSSING IN SONG VARIABLE
+ */
+ static function setScore(song:String, score:Int):Void
+ {
+ // Reminder that I don't need to format this song, it should come formatted!
+ songScores.set(song, score);
+ FlxG.save.data.songScores = songScores;
+ FlxG.save.flush();
+ }
+
+ static function setCombo(song:String, combo:String):Void
+ {
+ // Reminder that I don't need to format this song, it should come formatted!
+ songCombos.set(song, combo);
+ FlxG.save.data.songCombos = songCombos;
+ FlxG.save.flush();
+ }
+
+ public static function formatSong(song:String, diff:Int):String
+ {
+ var daSong:String = song;
+
+ if (diff == 0)
+ daSong += '-easy';
+ else if (diff == 2)
+ daSong += '-hard';
+
+ return daSong;
+ }
+
+ static function getComboInt(combo:String):Int
+ {
+ switch(combo)
+ {
+ case 'SDCB':
+ return 1;
+ case 'FC':
+ return 2;
+ case 'GFC':
+ return 3;
+ case 'MFC':
+ return 4;
+ default:
+ return 0;
+ }
+ }
+
+ public static function getScore(song:String, diff:Int):Int
+ {
+ if (!songScores.exists(formatSong(song, diff)))
+ setScore(formatSong(song, diff), 0);
+
+ return songScores.get(formatSong(song, diff));
+ }
+
+ public static function getCombo(song:String, diff:Int):String
+ {
+ if (!songCombos.exists(formatSong(song, diff)))
+ setCombo(formatSong(song, diff), '');
+
+ return songCombos.get(formatSong(song, diff));
+ }
+
+ public static function getWeekScore(week:Int, diff:Int):Int
+ {
+ if (!songScores.exists(formatSong('week' + week, diff)))
+ setScore(formatSong('week' + week, diff), 0);
+
+ return songScores.get(formatSong('week' + week, diff));
+ }
+
+ public static function load():Void
+ {
+ if (FlxG.save.data.songScores != null)
+ {
+ songScores = FlxG.save.data.songScores;
+ }
+ if (FlxG.save.data.songCombos != null)
+ {
+ songCombos = FlxG.save.data.songCombos;
+ }
+ }
+}
diff --git a/source - Copy/HitGraph.hx b/source - Copy/HitGraph.hx
new file mode 100644
index 0000000..7b1d383
--- /dev/null
+++ b/source - Copy/HitGraph.hx
@@ -0,0 +1,279 @@
+import flixel.FlxG;
+import openfl.display.Bitmap;
+import openfl.display.BitmapData;
+import openfl.text.TextFieldAutoSize;
+import flixel.system.FlxAssets;
+import openfl.text.TextFormat;
+import flash.display.Graphics;
+import flash.display.Shape;
+import flash.display.Sprite;
+import flash.text.TextField;
+import flash.text.TextFormatAlign;
+import flixel.math.FlxMath;
+import flixel.util.FlxColor;
+import flixel.util.FlxDestroyUtil;
+
+/**
+ * stolen from https://github.com/HaxeFlixel/flixel/blob/master/flixel/system/debug/stats/StatsGraph.hx
+ */
+class HitGraph extends Sprite
+{
+ static inline var AXIS_COLOR:FlxColor = 0xffffff;
+ static inline var AXIS_ALPHA:Float = 0.5;
+ inline static var HISTORY_MAX:Int = 30;
+
+ public var minLabel:TextField;
+ public var curLabel:TextField;
+ public var maxLabel:TextField;
+ public var avgLabel:TextField;
+
+ public var minValue:Float = -(Math.floor((PlayState.rep.replay.sf / 60) * 1000) + 95);
+ public var maxValue:Float = Math.floor((PlayState.rep.replay.sf / 60) * 1000) + 95;
+
+ public var showInput:Bool = FlxG.save.data.inputShow;
+
+ public var graphColor:FlxColor;
+
+ public var history:Array = [];
+
+ public var bitmap:Bitmap;
+
+ var _axis:Shape;
+ var _width:Int;
+ var _height:Int;
+ var _unit:String;
+ var _labelWidth:Int;
+ var _label:String;
+
+ public function new(X:Int, Y:Int, Width:Int, Height:Int)
+ {
+ super();
+ x = X;
+ y = Y;
+ _width = Width;
+ _height = Height;
+
+ var bm = new BitmapData(Width,Height);
+ bm.draw(this);
+ bitmap = new Bitmap(bm);
+
+ _axis = new Shape();
+ _axis.x = _labelWidth + 10;
+
+ var ts = Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166;
+
+ var early = createTextField(10,10,FlxColor.WHITE,12);
+ var late = createTextField(10,_height - 20,FlxColor.WHITE,12);
+
+ early.text = "Early (" + -166 * ts + "ms)";
+ late.text = "Late (" + 166 * ts + "ms)";
+
+ addChild(early);
+ addChild(late);
+
+ addChild(_axis);
+
+ drawAxes();
+ }
+
+ /**
+ * Redraws the axes of the graph.
+ */
+ function drawAxes():Void
+ {
+ var gfx = _axis.graphics;
+ gfx.clear();
+ gfx.lineStyle(1, AXIS_COLOR, AXIS_ALPHA);
+
+ // y-Axis
+ gfx.moveTo(0, 0);
+ gfx.lineTo(0, _height);
+
+ // x-Axis
+ gfx.moveTo(0, _height);
+ gfx.lineTo(_width, _height);
+
+ gfx.moveTo(0, _height / 2);
+ gfx.lineTo(_width, _height / 2);
+
+ }
+
+ public static function createTextField(X:Float = 0, Y:Float = 0, Color:FlxColor = FlxColor.WHITE, Size:Int = 12):TextField
+ {
+ return initTextField(new TextField(), X, Y, Color, Size);
+ }
+
+ public static function initTextField(tf:T, X:Float = 0, Y:Float = 0, Color:FlxColor = FlxColor.WHITE, Size:Int = 12):T
+ {
+ tf.x = X;
+ tf.y = Y;
+ tf.multiline = false;
+ tf.wordWrap = false;
+ tf.embedFonts = true;
+ tf.selectable = false;
+ #if flash
+ tf.antiAliasType = AntiAliasType.NORMAL;
+ tf.gridFitType = GridFitType.PIXEL;
+ #end
+ tf.defaultTextFormat = new TextFormat("assets/fonts/vcr.ttf", Size, Color.to24Bit());
+ tf.alpha = Color.alphaFloat;
+ tf.autoSize = TextFieldAutoSize.LEFT;
+ return tf;
+ }
+
+ function drawJudgementLine(ms:Float):Void
+ {
+
+ var gfx:Graphics = graphics;
+
+ gfx.lineStyle(1, graphColor, 0.3);
+
+ var ts = Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166;
+ var range:Float = Math.max(maxValue - minValue, maxValue * 0.1);
+
+ var value = ((ms * ts) - minValue) / range;
+
+ var pointY = _axis.y + ((-value * _height - 1) + _height);
+
+ var graphX = _axis.x + 1;
+
+ if (ms == 45)
+ gfx.moveTo(graphX, _axis.y + pointY);
+
+ var graphX = _axis.x + 1;
+
+ gfx.drawRect(graphX,pointY, _width,1);
+
+ gfx.lineStyle(1, graphColor, 1);
+ }
+
+ /**
+ * Redraws the graph based on the values stored in the history.
+ */
+ function drawGraph():Void
+ {
+ var gfx:Graphics = graphics;
+ gfx.clear();
+ gfx.lineStyle(1, graphColor, 1);
+
+ gfx.beginFill(0x00FF00);
+ drawJudgementLine(45);
+ gfx.endFill();
+
+ gfx.beginFill(0xFF0000);
+ drawJudgementLine(90);
+ gfx.endFill();
+
+ gfx.beginFill(0x8b0000);
+ drawJudgementLine(135);
+ gfx.endFill();
+
+ gfx.beginFill(0x580000);
+ drawJudgementLine(166);
+ gfx.endFill();
+
+ gfx.beginFill(0x00FF00);
+ drawJudgementLine(-45);
+ gfx.endFill();
+
+ gfx.beginFill(0xFF0000);
+ drawJudgementLine(-90);
+ gfx.endFill();
+
+ gfx.beginFill(0x8b0000);
+ drawJudgementLine(-135);
+ gfx.endFill();
+
+ gfx.beginFill(0x580000);
+ drawJudgementLine(-166);
+ gfx.endFill();
+
+ var range:Float = Math.max(maxValue - minValue, maxValue * 0.1);
+ var graphX = _axis.x + 1;
+
+ if (showInput)
+ {
+ for (i in 0...PlayState.rep.replay.ana.anaArray.length)
+ {
+ var ana = PlayState.rep.replay.ana.anaArray[i];
+
+ var value = (ana.key * 25 - minValue) / range;
+
+ if (ana.hit)
+ gfx.beginFill(0xFFFF00);
+ else
+ gfx.beginFill(0xC2B280);
+
+ if (ana.hitTime < 0)
+ continue;
+
+ var pointY = (-value * _height - 1) + _height;
+ gfx.drawRect(graphX + fitX(ana.hitTime), pointY,2,2);
+ gfx.endFill();
+ }
+ }
+
+ for (i in 0...history.length)
+ {
+ var value = (history[i][0] - minValue) / range;
+ var judge = history[i][1];
+
+ switch(judge)
+ {
+ case "sick":
+ gfx.beginFill(0x00FFFF);
+ case "good":
+ gfx.beginFill(0x00FF00);
+ case "bad":
+ gfx.beginFill(0xFF0000);
+ case "shit":
+ gfx.beginFill(0x8b0000);
+ case "miss":
+ gfx.beginFill(0x580000);
+ default:
+ gfx.beginFill(0xFFFFFF);
+ }
+ var pointY = (-value * _height - 1) + _height;
+
+ /*if (i == 0)
+ gfx.moveTo(graphX, _axis.y + pointY);*/
+ gfx.drawRect(graphX + fitX(history[i][2]), pointY,4,4);
+
+ gfx.endFill();
+ }
+
+
+ var bm = new BitmapData(_width,_height);
+ bm.draw(this);
+ bitmap = new Bitmap(bm);
+ }
+
+ public function fitX(x:Float)
+ {
+ return (x / FlxG.sound.music.length) * width;
+ }
+
+ public function addToHistory(diff:Float, judge:String, time:Float)
+ {
+ history.push([diff,judge, time]);
+ }
+
+ public function update():Void
+ {
+ drawGraph();
+ }
+
+ public function average():Float
+ {
+ var sum:Float = 0;
+ for (value in history)
+ sum += value;
+ return sum / history.length;
+ }
+
+ public function destroy():Void
+ {
+ _axis = FlxDestroyUtil.removeChild(this, _axis);
+ history = null;
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/KadeEngineData.hx b/source - Copy/KadeEngineData.hx
new file mode 100644
index 0000000..ffbfd48
--- /dev/null
+++ b/source - Copy/KadeEngineData.hx
@@ -0,0 +1,101 @@
+import openfl.Lib;
+import flixel.FlxG;
+
+class KadeEngineData
+{
+ public static function initSave()
+ {
+ if (FlxG.save.data.newInput == null)
+ FlxG.save.data.newInput = true;
+
+ if (FlxG.save.data.downscroll == null)
+ FlxG.save.data.downscroll = false;
+
+ if (FlxG.save.data.dfjk == null)
+ FlxG.save.data.dfjk = false;
+
+ if (FlxG.save.data.accuracyDisplay == null)
+ FlxG.save.data.accuracyDisplay = true;
+
+ if (FlxG.save.data.offset == null)
+ FlxG.save.data.offset = 0;
+
+ if (FlxG.save.data.songPosition == null)
+ FlxG.save.data.songPosition = false;
+
+ if (FlxG.save.data.fps == null)
+ FlxG.save.data.fps = false;
+
+ if (FlxG.save.data.changedHit == null)
+ {
+ FlxG.save.data.changedHitX = -1;
+ FlxG.save.data.changedHitY = -1;
+ FlxG.save.data.changedHit = false;
+ }
+
+ if (FlxG.save.data.fpsRain == null)
+ FlxG.save.data.fpsRain = false;
+
+ if (FlxG.save.data.fpsCap == null)
+ FlxG.save.data.fpsCap = 120;
+
+ if (FlxG.save.data.fpsCap > 285 || FlxG.save.data.fpsCap < 60)
+ FlxG.save.data.fpsCap = 120; // baby proof so you can't hard lock ur copy of kade engine
+
+ if (FlxG.save.data.scrollSpeed == null)
+ FlxG.save.data.scrollSpeed = 1;
+
+ if (FlxG.save.data.npsDisplay == null)
+ FlxG.save.data.npsDisplay = false;
+
+ if (FlxG.save.data.frames == null)
+ FlxG.save.data.frames = 10;
+
+ if (FlxG.save.data.accuracyMod == null)
+ FlxG.save.data.accuracyMod = 1;
+
+ if (FlxG.save.data.watermark == null)
+ FlxG.save.data.watermark = true;
+
+ if (FlxG.save.data.ghost == null)
+ FlxG.save.data.ghost = true;
+
+ if (FlxG.save.data.distractions == null)
+ FlxG.save.data.distractions = true;
+
+ if (FlxG.save.data.flashing == null)
+ FlxG.save.data.flashing = true;
+
+ if (FlxG.save.data.resetButton == null)
+ FlxG.save.data.resetButton = false;
+
+ if (FlxG.save.data.botplay == null)
+ FlxG.save.data.botplay = false;
+
+ if (FlxG.save.data.cpuStrums == null)
+ FlxG.save.data.cpuStrums = false;
+
+ if (FlxG.save.data.strumline == null)
+ FlxG.save.data.strumline = false;
+
+ if (FlxG.save.data.customStrumLine == null)
+ FlxG.save.data.customStrumLine = 0;
+
+ if (FlxG.save.data.camzoom == null)
+ FlxG.save.data.camzoom = true;
+
+ if (FlxG.save.data.scoreScreen == null)
+ FlxG.save.data.scoreScreen = true;
+
+ if (FlxG.save.data.inputShow == null)
+ FlxG.save.data.inputShow = false;
+
+ Conductor.recalculateTimings();
+ PlayerSettings.player1.controls.loadKeyBinds();
+ KeyBinds.keyCheck();
+
+ Main.watermarks = FlxG.save.data.watermark;
+
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(FlxG.save.data.fpsCap);
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/KeyBindMenu.hx b/source - Copy/KeyBindMenu.hx
new file mode 100644
index 0000000..1d3f6e4
--- /dev/null
+++ b/source - Copy/KeyBindMenu.hx
@@ -0,0 +1,262 @@
+package;
+
+/// Code created by Rozebud for FPS Plus (thanks rozebud)
+// modified by KadeDev for use in Kade Engine/Tricky
+
+import flixel.util.FlxAxes;
+import flixel.FlxSubState;
+import Options.Option;
+import flixel.input.FlxInput;
+import flixel.input.keyboard.FlxKey;
+import flixel.FlxG;
+import flixel.FlxObject;
+import flixel.FlxSprite;
+import flixel.effects.FlxFlicker;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import io.newgrounds.NG;
+import lime.app.Application;
+import lime.utils.Assets;
+import flixel.math.FlxMath;
+import flixel.text.FlxText;
+import flixel.input.FlxKeyManager;
+
+
+using StringTools;
+
+class KeyBindMenu extends FlxSubState
+{
+
+ var keyTextDisplay:FlxText;
+ var keyWarning:FlxText;
+ var warningTween:FlxTween;
+ var keyText:Array = ["LEFT", "DOWN", "UP", "RIGHT"];
+ var defaultKeys:Array = ["A", "S", "W", "D", "R"];
+ var curSelected:Int = 0;
+
+ var keys:Array = [FlxG.save.data.leftBind,
+ FlxG.save.data.downBind,
+ FlxG.save.data.upBind,
+ FlxG.save.data.rightBind];
+
+ var tempKey:String = "";
+ var blacklist:Array = ["ESCAPE", "ENTER", "BACKSPACE", "SPACE"];
+
+ var blackBox:FlxSprite;
+ var infoText:FlxText;
+
+ var state:String = "select";
+
+ override function create()
+ {
+
+ for (i in 0...keys.length)
+ {
+ var k = keys[i];
+ if (k == null)
+ keys[i] = defaultKeys[i];
+ }
+
+ //FlxG.sound.playMusic('assets/music/configurator' + TitleState.soundExt);
+
+ persistentUpdate = persistentDraw = true;
+
+ keyTextDisplay = new FlxText(-10, 0, 1280, "", 72);
+ keyTextDisplay.scrollFactor.set(0, 0);
+ keyTextDisplay.setFormat("VCR OSD Mono", 42, FlxColor.WHITE, FlxTextAlign.CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ keyTextDisplay.borderSize = 2;
+ keyTextDisplay.borderQuality = 3;
+
+ blackBox = new FlxSprite(0,0).makeGraphic(FlxG.width,FlxG.height,FlxColor.BLACK);
+ add(blackBox);
+
+ infoText = new FlxText(-10, 580, 1280, "(Escape to save, backspace to leave without saving)", 72);
+ infoText.scrollFactor.set(0, 0);
+ infoText.setFormat("VCR OSD Mono", 24, FlxColor.WHITE, FlxTextAlign.CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ infoText.borderSize = 2;
+ infoText.borderQuality = 3;
+ infoText.alpha = 0;
+ infoText.screenCenter(FlxAxes.X);
+ add(infoText);
+ add(keyTextDisplay);
+
+ blackBox.alpha = 0;
+ keyTextDisplay.alpha = 0;
+
+ FlxTween.tween(keyTextDisplay, {alpha: 1}, 1, {ease: FlxEase.expoInOut});
+ FlxTween.tween(infoText, {alpha: 1}, 1.4, {ease: FlxEase.expoInOut});
+ FlxTween.tween(blackBox, {alpha: 0.7}, 1, {ease: FlxEase.expoInOut});
+
+ OptionsMenu.instance.acceptInput = false;
+
+ textUpdate();
+
+ super.create();
+ }
+
+ override function update(elapsed:Float)
+ {
+
+ switch(state){
+
+ case "select":
+ if (FlxG.keys.justPressed.UP)
+ {
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+ changeItem(-1);
+ }
+
+ if (FlxG.keys.justPressed.DOWN)
+ {
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+ changeItem(1);
+ }
+
+ if (FlxG.keys.justPressed.ENTER){
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+ state = "input";
+ }
+ else if(FlxG.keys.justPressed.ESCAPE){
+ quit();
+ }
+ else if (FlxG.keys.justPressed.BACKSPACE){
+ reset();
+ }
+
+ case "input":
+ tempKey = keys[curSelected];
+ keys[curSelected] = "?";
+ textUpdate();
+ state = "waiting";
+
+ case "waiting":
+ if(FlxG.keys.justPressed.ESCAPE){
+ keys[curSelected] = tempKey;
+ state = "select";
+ FlxG.sound.play(Paths.sound('confirmMenu'));
+ }
+ else if(FlxG.keys.justPressed.ENTER){
+ addKey(defaultKeys[curSelected]);
+ save();
+ state = "select";
+ }
+ else if(FlxG.keys.justPressed.ANY){
+ addKey(FlxG.keys.getIsDown()[0].ID.toString());
+ save();
+ state = "select";
+ }
+
+
+ case "exiting":
+
+
+ default:
+ state = "select";
+
+ }
+
+ if(FlxG.keys.justPressed.ANY)
+ textUpdate();
+
+ super.update(elapsed);
+
+ }
+
+ function textUpdate(){
+
+ keyTextDisplay.text = "\n\n";
+
+ for(i in 0...4){
+
+ var textStart = (i == curSelected) ? "> " : " ";
+ keyTextDisplay.text += textStart + keyText[i] + ": " + ((keys[i] != keyText[i]) ? (keys[i] + " / ") : "" ) + keyText[i] + " ARROW\n";
+
+ }
+
+ keyTextDisplay.screenCenter();
+
+ }
+
+ function save(){
+
+ FlxG.save.data.upBind = keys[2];
+ FlxG.save.data.downBind = keys[1];
+ FlxG.save.data.leftBind = keys[0];
+ FlxG.save.data.rightBind = keys[3];
+
+ FlxG.save.flush();
+
+ PlayerSettings.player1.controls.loadKeyBinds();
+
+ }
+
+ function reset(){
+
+ for(i in 0...5){
+ keys[i] = defaultKeys[i];
+ }
+ quit();
+
+ }
+
+ function quit(){
+
+ state = "exiting";
+
+ save();
+
+ OptionsMenu.instance.acceptInput = true;
+
+ FlxTween.tween(keyTextDisplay, {alpha: 0}, 1, {ease: FlxEase.expoInOut});
+ FlxTween.tween(blackBox, {alpha: 0}, 1.1, {ease: FlxEase.expoInOut, onComplete: function(flx:FlxTween){close();}});
+ FlxTween.tween(infoText, {alpha: 0}, 1, {ease: FlxEase.expoInOut});
+ }
+
+
+ function addKey(r:String){
+
+ var shouldReturn:Bool = true;
+
+ var notAllowed:Array = [];
+
+ for(x in blacklist){notAllowed.push(x);}
+
+ trace(notAllowed);
+
+ for(x in 0...keys.length)
+ {
+ var oK = keys[x];
+ if(oK == r)
+ keys[x] = null;
+ if (notAllowed.contains(oK))
+ return;
+ }
+
+ if(shouldReturn){
+ keys[curSelected] = r;
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+ }
+ else{
+ keys[curSelected] = tempKey;
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+ keyWarning.alpha = 1;
+ warningTween.cancel();
+ warningTween = FlxTween.tween(keyWarning, {alpha: 0}, 0.5, {ease: FlxEase.circOut, startDelay: 2});
+ }
+
+ }
+
+ function changeItem(_amount:Int = 0)
+ {
+ curSelected += _amount;
+
+ if (curSelected > 3)
+ curSelected = 0;
+ if (curSelected < 0)
+ curSelected = 3;
+ }
+}
diff --git a/source - Copy/KeyBinds.hx b/source - Copy/KeyBinds.hx
new file mode 100644
index 0000000..facd1ad
--- /dev/null
+++ b/source - Copy/KeyBinds.hx
@@ -0,0 +1,50 @@
+import flixel.FlxG;
+import flixel.input.FlxInput;
+import flixel.input.actions.FlxAction;
+import flixel.input.actions.FlxActionInput;
+import flixel.input.actions.FlxActionInputDigital;
+import flixel.input.actions.FlxActionManager;
+import flixel.input.actions.FlxActionSet;
+import flixel.input.gamepad.FlxGamepadButton;
+import flixel.input.gamepad.FlxGamepadInputID;
+import flixel.input.keyboard.FlxKey;
+
+class KeyBinds
+{
+
+ public static function resetBinds():Void{
+
+ FlxG.save.data.upBind = "W";
+ FlxG.save.data.downBind = "S";
+ FlxG.save.data.leftBind = "A";
+ FlxG.save.data.rightBind = "D";
+ FlxG.save.data.killBind = "R";
+ PlayerSettings.player1.controls.loadKeyBinds();
+
+ }
+
+ public static function keyCheck():Void
+ {
+ if(FlxG.save.data.upBind == null){
+ FlxG.save.data.upBind = "W";
+ trace("No UP");
+ }
+ if(FlxG.save.data.downBind == null){
+ FlxG.save.data.downBind = "S";
+ trace("No DOWN");
+ }
+ if(FlxG.save.data.leftBind == null){
+ FlxG.save.data.leftBind = "A";
+ trace("No LEFT");
+ }
+ if(FlxG.save.data.rightBind == null){
+ FlxG.save.data.rightBind = "D";
+ trace("No RIGHT");
+ }
+ if(FlxG.save.data.killBind == null){
+ FlxG.save.data.killBind = "R";
+ trace("No KILL");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/source - Copy/LoadReplayState.hx b/source - Copy/LoadReplayState.hx
new file mode 100644
index 0000000..3560888
--- /dev/null
+++ b/source - Copy/LoadReplayState.hx
@@ -0,0 +1,220 @@
+package;
+
+import Controls.KeyboardScheme;
+import Controls.Control;
+import flash.text.TextField;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.display.FlxGridOverlay;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.input.keyboard.FlxKey;
+import flixel.math.FlxMath;
+import flixel.text.FlxText;
+import flixel.util.FlxColor;
+import lime.utils.Assets;
+#if sys
+import sys.io.File;
+#end
+
+class LoadReplayState extends MusicBeatState
+{
+ var selector:FlxText;
+ var curSelected:Int = 0;
+
+ var songs:Array = [];
+
+ var controlsStrings:Array = [];
+ var actualNames:Array = [];
+
+ private var grpControls:FlxTypedGroup;
+ var versionShit:FlxText;
+ var poggerDetails:FlxText;
+ override function create()
+ {
+ var menuBG:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat'));
+ #if sys
+ controlsStrings = sys.FileSystem.readDirectory(Sys.getCwd() + "/assets/replays/");
+ #end
+ trace(controlsStrings);
+
+ controlsStrings.sort(Reflect.compare);
+
+ addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 1, ['dad']);
+ addWeek(['Spookeez', 'South', 'Monster'], 2, ['spooky']);
+ addWeek(['Pico', 'Philly', 'Blammed'], 3, ['pico']);
+
+ addWeek(['Satin-Panties', 'High', 'Milf'], 4, ['mom']);
+ addWeek(['Cocoa', 'Eggnog', 'Winter-Horrorland'], 5, ['parents-christmas', 'parents-christmas', 'monster-christmas']);
+
+ addWeek(['Senpai', 'Roses', 'Thorns'], 6, ['senpai', 'senpai', 'spirit']);
+
+
+ for(i in 0...controlsStrings.length)
+ {
+ var string:String = controlsStrings[i];
+ actualNames[i] = string;
+ var rep:Replay = Replay.LoadReplay(string);
+ controlsStrings[i] = string.split("time")[0] + " " + CoolUtil.difficultyFromInt(rep.replay.songDiff).toUpperCase();
+ }
+
+ if (controlsStrings.length == 0)
+ controlsStrings.push("No Replays...");
+
+ menuBG.color = 0xFFea71fd;
+ menuBG.setGraphicSize(Std.int(menuBG.width * 1.1));
+ menuBG.updateHitbox();
+ menuBG.screenCenter();
+ menuBG.antialiasing = true;
+ add(menuBG);
+
+ grpControls = new FlxTypedGroup();
+ add(grpControls);
+
+ for (i in 0...controlsStrings.length)
+ {
+ var controlLabel:Alphabet = new Alphabet(0, (70 * i) + 30, controlsStrings[i], true, false);
+ controlLabel.isMenuItem = true;
+ controlLabel.targetY = i;
+ grpControls.add(controlLabel);
+ // DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
+ }
+
+
+ versionShit = new FlxText(5, FlxG.height - 34, 0, "Replay Loader (ESCAPE TO GO BACK)\nNOTICE!!!! Replays are in a beta stage, and they are probably not 100% correct. expect misses and other stuff that isn't there!\n", 12);
+ versionShit.scrollFactor.set();
+ versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ add(versionShit);
+
+
+ poggerDetails = new FlxText(5, 34, 0, "Replay Details - \nnone", 12);
+ poggerDetails.scrollFactor.set();
+ poggerDetails.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ add(poggerDetails);
+
+ changeSelection(0);
+
+ super.create();
+ }
+
+ public function getWeekNumbFromSong(songName:String):Int
+ {
+ var week:Int = 0;
+ for (i in 0...songs.length)
+ {
+ var pog:FreeplayState.SongMetadata = songs[i];
+ if (pog.songName == songName)
+ week = pog.week;
+ }
+ return week;
+ }
+
+ public function addSong(songName:String, weekNum:Int, songCharacter:String)
+ {
+ songs.push(new FreeplayState.SongMetadata(songName, weekNum, songCharacter));
+ }
+
+ public function addWeek(songs:Array, weekNum:Int, ?songCharacters:Array)
+ {
+ if (songCharacters == null)
+ songCharacters = ['bf'];
+
+ var num:Int = 0;
+ for (song in songs)
+ {
+ addSong(song, weekNum, songCharacters[num]);
+
+ if (songCharacters.length != 1)
+ num++;
+ }
+ }
+
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (controls.BACK)
+ FlxG.switchState(new OptionsMenu());
+ if (controls.UP_P)
+ changeSelection(-1);
+ if (controls.DOWN_P)
+ changeSelection(1);
+
+
+ if (controls.ACCEPT && grpControls.members[curSelected].text != "No Replays...")
+ {
+ trace('loading ' + actualNames[curSelected]);
+ PlayState.rep = Replay.LoadReplay(actualNames[curSelected]);
+
+ PlayState.loadRep = true;
+
+ if (PlayState.rep.replay.replayGameVer == Replay.version)
+ {
+
+ // adjusting the song name to be compatible
+ var songFormat = StringTools.replace(PlayState.rep.replay.songName, " ", "-");
+ switch (songFormat) {
+ case 'Dad-Battle': songFormat = 'Dadbattle';
+ case 'Philly-Nice': songFormat = 'Philly';
+ // Replay v1.0 support
+ case 'dad-battle': songFormat = 'Dadbattle';
+ case 'philly-nice': songFormat = 'Philly';
+ }
+
+ var poop:String = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff);
+
+ PlayState.SONG = Song.loadFromJson(poop, PlayState.rep.replay.songName);
+ PlayState.isStoryMode = false;
+ PlayState.storyDifficulty = PlayState.rep.replay.songDiff;
+ PlayState.storyWeek = getWeekNumbFromSong(PlayState.rep.replay.songName);
+ LoadingState.loadAndSwitchState(new PlayState());
+ }
+ else
+ {
+ PlayState.rep = null;
+ PlayState.loadRep = false;
+ }
+ }
+ }
+
+ var isSettingControl:Bool = false;
+
+ function changeSelection(change:Int = 0)
+ {
+ #if !switch
+ // NGio.logEvent('Fresh');
+ #end
+
+ FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
+
+ curSelected += change;
+
+ if (curSelected < 0)
+ curSelected = grpControls.length - 1;
+ if (curSelected >= grpControls.length)
+ curSelected = 0;
+
+ var rep:Replay = Replay.LoadReplay(actualNames[curSelected]);
+
+ poggerDetails.text = "Replay Details - \nDate Created: " + rep.replay.timestamp + "\nSong: " + rep.replay.songName + "\nReplay Version: " + rep.replay.replayGameVer + ' (' + (rep.replay.replayGameVer != Replay.version ? "OUTDATED not useable!" : "Latest") + ')\n';
+
+ // selector.y = (70 * curSelected) + 30;
+
+ var bullShit:Int = 0;
+
+ for (item in grpControls.members)
+ {
+ item.targetY = bullShit - curSelected;
+ bullShit++;
+
+ item.alpha = 0.6;
+ // item.setGraphicSize(Std.int(item.width * 0.8));
+
+ if (item.targetY == 0)
+ {
+ item.alpha = 1;
+ // item.setGraphicSize(Std.int(item.width));
+ }
+ }
+ }
+}
diff --git a/source - Copy/LoadingState.hx b/source - Copy/LoadingState.hx
new file mode 100644
index 0000000..23bce2e
--- /dev/null
+++ b/source - Copy/LoadingState.hx
@@ -0,0 +1,310 @@
+package;
+
+import lime.app.Promise;
+import lime.app.Future;
+import flixel.FlxG;
+import flixel.FlxState;
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.util.FlxTimer;
+
+import openfl.utils.Assets;
+import lime.utils.Assets as LimeAssets;
+import lime.utils.AssetLibrary;
+import lime.utils.AssetManifest;
+
+import haxe.io.Path;
+
+class LoadingState extends MusicBeatState
+{
+ inline static var MIN_TIME = 1.0;
+
+ var target:FlxState;
+ var stopMusic = false;
+ var callbacks:MultiCallback;
+
+ var logo:FlxSprite;
+ var gfDance:FlxSprite;
+ var danceLeft = false;
+
+ function new(target:FlxState, stopMusic:Bool)
+ {
+ super();
+ this.target = target;
+ this.stopMusic = stopMusic;
+ }
+
+ override function create()
+ {
+ logo = new FlxSprite(-150, -100);
+ logo.frames = Paths.getSparrowAtlas('logoBumpin');
+ logo.antialiasing = true;
+ logo.animation.addByPrefix('bump', 'logo bumpin', 24);
+ logo.animation.play('bump');
+ logo.updateHitbox();
+ // logoBl.screenCenter();
+ // logoBl.color = FlxColor.BLACK;
+
+ gfDance = new FlxSprite(FlxG.width * 0.4, FlxG.height * 0.07);
+ gfDance.frames = Paths.getSparrowAtlas('gfDanceTitle');
+ gfDance.animation.addByIndices('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
+ gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
+ gfDance.antialiasing = true;
+ add(gfDance);
+ add(logo);
+
+ initSongsManifest().onComplete
+ (
+ function (lib)
+ {
+ callbacks = new MultiCallback(onLoad);
+ var introComplete = callbacks.add("introComplete");
+ checkLoadSong(getSongPath());
+ if (PlayState.SONG.needsVoices)
+ checkLoadSong(getVocalPath());
+ checkLibrary("shared");
+ if (PlayState.storyWeek > 0)
+ checkLibrary("week" + PlayState.storyWeek);
+ else
+ checkLibrary("tutorial");
+
+ var fadeTime = 0.5;
+ FlxG.camera.fade(FlxG.camera.bgColor, fadeTime, true);
+ new FlxTimer().start(fadeTime + MIN_TIME, function(_) introComplete());
+ }
+ );
+ }
+
+ function checkLoadSong(path:String)
+ {
+ if (!Assets.cache.hasSound(path))
+ {
+ var library = Assets.getLibrary("songs");
+ final symbolPath = path.split(":").pop();
+ // @:privateAccess
+ // library.types.set(symbolPath, SOUND);
+ // @:privateAccess
+ // library.pathGroups.set(symbolPath, [library.__cacheBreak(symbolPath)]);
+ var callback = callbacks.add("song:" + path);
+ Assets.loadSound(path).onComplete(function (_) { callback(); });
+ }
+ }
+
+ function checkLibrary(library:String)
+ {
+ trace(Assets.hasLibrary(library));
+ if (Assets.getLibrary(library) == null)
+ {
+ @:privateAccess
+ if (!LimeAssets.libraryPaths.exists(library))
+ throw "Missing library: " + library;
+
+ var callback = callbacks.add("library:" + library);
+ Assets.loadLibrary(library).onComplete(function (_) { callback(); });
+ }
+ }
+
+ override function beatHit()
+ {
+ super.beatHit();
+
+ logo.animation.play('bump');
+ danceLeft = !danceLeft;
+
+ if (danceLeft)
+ gfDance.animation.play('danceRight');
+ else
+ gfDance.animation.play('danceLeft');
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+ #if debug
+ if (FlxG.keys.justPressed.SPACE)
+ trace('fired: ' + callbacks.getFired() + " unfired:" + callbacks.getUnfired());
+ #end
+ }
+
+ function onLoad()
+ {
+ if (stopMusic && FlxG.sound.music != null)
+ FlxG.sound.music.stop();
+
+ FlxG.switchState(target);
+ }
+
+ static function getSongPath()
+ {
+ return Paths.inst(PlayState.SONG.song);
+ }
+
+ static function getVocalPath()
+ {
+ return Paths.voices(PlayState.SONG.song);
+ }
+
+ inline static public function loadAndSwitchState(target:FlxState, stopMusic = false)
+ {
+ FlxG.switchState(getNextState(target, stopMusic));
+ }
+
+ static function getNextState(target:FlxState, stopMusic = false):FlxState
+ {
+ Paths.setCurrentLevel("week" + PlayState.storyWeek);
+ #if NO_PRELOAD_ALL
+ var loaded = isSoundLoaded(getSongPath())
+ && (!PlayState.SONG.needsVoices || isSoundLoaded(getVocalPath()))
+ && isLibraryLoaded("shared");
+
+ if (!loaded)
+ return new LoadingState(target, stopMusic);
+ #end
+ if (stopMusic && FlxG.sound.music != null)
+ FlxG.sound.music.stop();
+
+ return target;
+ }
+
+ #if NO_PRELOAD_ALL
+ static function isSoundLoaded(path:String):Bool
+ {
+ return Assets.cache.hasSound(path);
+ }
+
+ static function isLibraryLoaded(library:String):Bool
+ {
+ return Assets.getLibrary(library) != null;
+ }
+ #end
+
+ override function destroy()
+ {
+ super.destroy();
+
+ callbacks = null;
+ }
+
+ static function initSongsManifest()
+ {
+ var id = "songs";
+ var promise = new Promise();
+
+ var library = LimeAssets.getLibrary(id);
+
+ if (library != null)
+ {
+ return Future.withValue(library);
+ }
+
+ var path = id;
+ var rootPath = null;
+
+ @:privateAccess
+ var libraryPaths = LimeAssets.libraryPaths;
+ if (libraryPaths.exists(id))
+ {
+ path = libraryPaths[id];
+ rootPath = Path.directory(path);
+ }
+ else
+ {
+ if (StringTools.endsWith(path, ".bundle"))
+ {
+ rootPath = path;
+ path += "/library.json";
+ }
+ else
+ {
+ rootPath = Path.directory(path);
+ }
+ @:privateAccess
+ path = LimeAssets.__cacheBreak(path);
+ }
+
+ AssetManifest.loadFromFile(path, rootPath).onComplete(function(manifest)
+ {
+ if (manifest == null)
+ {
+ promise.error("Cannot parse asset manifest for library \"" + id + "\"");
+ return;
+ }
+
+ var library = AssetLibrary.fromManifest(manifest);
+
+ if (library == null)
+ {
+ promise.error("Cannot open library \"" + id + "\"");
+ }
+ else
+ {
+ @:privateAccess
+ LimeAssets.libraries.set(id, library);
+ library.onChange.add(LimeAssets.onChange.dispatch);
+ promise.completeWith(Future.withValue(library));
+ }
+ }).onError(function(_)
+ {
+ promise.error("There is no asset library with an ID of \"" + id + "\"");
+ });
+
+ return promise.future;
+ }
+}
+
+class MultiCallback
+{
+ public var callback:Void->Void;
+ public var logId:String = null;
+ public var length(default, null) = 0;
+ public var numRemaining(default, null) = 0;
+
+ var unfired = new MapVoid>();
+ var fired = new Array();
+
+ public function new (callback:Void->Void, logId:String = null)
+ {
+ this.callback = callback;
+ this.logId = logId;
+ }
+
+ public function add(id = "untitled")
+ {
+ id = '$length:$id';
+ length++;
+ numRemaining++;
+ var func:Void->Void = null;
+ func = function ()
+ {
+ if (unfired.exists(id))
+ {
+ unfired.remove(id);
+ fired.push(id);
+ numRemaining--;
+
+ if (logId != null)
+ log('fired $id, $numRemaining remaining');
+
+ if (numRemaining == 0)
+ {
+ if (logId != null)
+ log('all callbacks fired');
+ callback();
+ }
+ }
+ else
+ log('already fired $id');
+ }
+ unfired[id] = func;
+ return func;
+ }
+
+ inline function log(msg):Void
+ {
+ if (logId != null)
+ trace('$logId: $msg');
+ }
+
+ public function getFired() return fired.copy();
+ public function getUnfired() return [for (id in unfired.keys()) id];
+}
\ No newline at end of file
diff --git a/source - Copy/LuaShader.hx b/source - Copy/LuaShader.hx
new file mode 100644
index 0000000..4e403c6
--- /dev/null
+++ b/source - Copy/LuaShader.hx
@@ -0,0 +1,72 @@
+/*import flixel.system.FlxAssets.FlxShader;
+
+class LuaShader extends FlxShader
+{
+ // SHADER SHIT FOR LUA CODE
+
+ public function new(frag,vert)
+ {
+ glFragmentSource = '
+ #pragma header
+ varying float openfl_Alphav;
+ varying vec4 openfl_ColorMultiplierv;
+ varying vec4 openfl_ColorOffsetv;
+ varying vec2 openfl_TextureCoordv;
+
+ uniform bool openfl_HasColorTransform;
+ uniform vec2 openfl_TextureSize;
+ uniform sampler2D bitmap;
+
+ uniform bool hasTransform;
+ uniform bool hasColorTransform;
+
+ uniform vec3 iResolution; // viewport resolution (in pixels)
+ uniform float iTime; // shader playback time (in seconds)
+ uniform float iTimeDelta; // render time (in seconds)
+ uniform int iFrame; // shader playback frame
+ uniform float iChannelTime[4]; // channel playback time (in seconds)
+ uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
+ uniform vec4 iMouse; // mouse pixel coords. xy: current, zw: click
+ uniform samplerXX iChannel0..3; // input channel. XX = 2D/Cube
+ uniform vec4 iDate; // (year, month, day, time in seconds)
+ uniform float iSampleRate; // sound sample rate (i.e., 44100)
+
+ vec4 flixel_texture2D(sampler2D bitmap, vec2 coord)
+ {
+ vec4 color = texture2D(bitmap, coord);
+ if (!hasTransform)
+ {
+ return color;
+ }
+
+ if (color.a == 0.0)
+ {
+ return vec4(0.0, 0.0, 0.0, 0.0);
+ }
+
+ if (!hasColorTransform)
+ {
+ return color * openfl_Alphav;
+ }
+
+ color = vec4(color.rgb / color.a, color.a);
+
+ mat4 colorMultiplier = mat4(0);
+ colorMultiplier[0][0] = openfl_ColorMultiplierv.x;
+ colorMultiplier[1][1] = openfl_ColorMultiplierv.y;
+ colorMultiplier[2][2] = openfl_ColorMultiplierv.z;
+ colorMultiplier[3][3] = openfl_ColorMultiplierv.w;
+
+ color = clamp(openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0);
+
+ if (color.a > 0.0)
+ {
+ return vec4(0.0, 0.0, 0.0, 0.0);
+ }
+
+ ' + frag;
+
+ iResolution
+ super();
+ }
+}*/
\ No newline at end of file
diff --git a/source - Copy/Main.hx b/source - Copy/Main.hx
new file mode 100644
index 0000000..6efcae3
--- /dev/null
+++ b/source - Copy/Main.hx
@@ -0,0 +1,121 @@
+package;
+
+
+import webm.WebmPlayer;
+import openfl.display.BlendMode;
+import openfl.text.TextFormat;
+import openfl.display.Application;
+import flixel.util.FlxColor;
+import flixel.FlxG;
+import flixel.FlxGame;
+import flixel.FlxState;
+import openfl.Assets;
+import openfl.Lib;
+import openfl.display.FPS;
+import openfl.display.Sprite;
+import openfl.events.Event;
+
+class Main extends Sprite
+{
+ var gameWidth:Int = 1280; // Width of the game in pixels (might be less / more in actual pixels depending on your zoom).
+ var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom).
+ var initialState:Class = TitleState; // The FlxState the game starts with.
+ var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions.
+ var framerate:Int = 120; // How many frames per second the game should run at.
+ var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode.
+ var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets
+
+ public static var watermarks = true; // Whether to put Kade Engine liteartly anywhere
+
+ // You can pretty much ignore everything from here on - your code should go in your states.
+
+ public static function main():Void
+ {
+
+ // quick checks
+
+ Lib.current.addChild(new Main());
+ }
+
+ public function new()
+ {
+ super();
+
+ if (stage != null)
+ {
+ init();
+ }
+ else
+ {
+ addEventListener(Event.ADDED_TO_STAGE, init);
+ }
+ }
+
+ public static var webmHandler:WebmHandler;
+
+ private function init(?E:Event):Void
+ {
+ if (hasEventListener(Event.ADDED_TO_STAGE))
+ {
+ removeEventListener(Event.ADDED_TO_STAGE, init);
+ }
+
+ setupGame();
+ }
+
+ private function setupGame():Void
+ {
+ var stageWidth:Int = Lib.current.stage.stageWidth;
+ var stageHeight:Int = Lib.current.stage.stageHeight;
+
+ if (zoom == -1)
+ {
+ var ratioX:Float = stageWidth / gameWidth;
+ var ratioY:Float = stageHeight / gameHeight;
+ zoom = Math.min(ratioX, ratioY);
+ gameWidth = Math.ceil(stageWidth / zoom);
+ gameHeight = Math.ceil(stageHeight / zoom);
+ }
+
+ initialState = Caching;
+
+ game = new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen);
+
+ addChild(game);
+
+ #if !mobile
+ fpsCounter = new FPS(10, 3, 0xFFFFFF);
+ addChild(fpsCounter);
+ toggleFPS(FlxG.save.data.fps);
+
+ #end
+ }
+
+ var game:FlxGame;
+
+ var fpsCounter:FPS;
+
+ public function toggleFPS(fpsEnabled:Bool):Void {
+ fpsCounter.visible = fpsEnabled;
+ }
+
+ public function changeFPSColor(color:FlxColor)
+ {
+ fpsCounter.textColor = color;
+ }
+
+ public function setFPSCap(cap:Float)
+ {
+ openfl.Lib.current.stage.frameRate = cap;
+ }
+
+ public function getFPSCap():Float
+ {
+ return openfl.Lib.current.stage.frameRate;
+ }
+
+ public function getFPS():Float
+ {
+ return fpsCounter.currentFPS;
+ }
+}
diff --git a/source - Copy/MainMenuState.hx b/source - Copy/MainMenuState.hx
new file mode 100644
index 0000000..d7a5590
--- /dev/null
+++ b/source - Copy/MainMenuState.hx
@@ -0,0 +1,263 @@
+package;
+
+import Controls.KeyboardScheme;
+import flixel.FlxG;
+import flixel.FlxObject;
+import flixel.FlxSprite;
+import flixel.effects.FlxFlicker;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
+import io.newgrounds.NG;
+import lime.app.Application;
+
+#if windows
+import Discord.DiscordClient;
+#end
+
+using StringTools;
+
+class MainMenuState extends MusicBeatState
+{
+ var curSelected:Int = 0;
+
+ var menuItems:FlxTypedGroup;
+
+ #if !switch
+ var optionShit:Array = ['story mode', 'freeplay', 'donate', 'options'];
+ #else
+ var optionShit:Array = ['story mode', 'freeplay'];
+ #end
+
+ var newGaming:FlxText;
+ var newGaming2:FlxText;
+ public static var firstStart:Bool = true;
+
+ public static var nightly:String = "";
+
+ public static var kadeEngineVer:String = "1.5.3" + nightly;
+ public static var gameVer:String = "0.2.7.1";
+
+ var magenta:FlxSprite;
+ var camFollow:FlxObject;
+ public static var finishedFunnyMove:Bool = false;
+
+ override function create()
+ {
+ #if windows
+ // Updating Discord Rich Presence
+ DiscordClient.changePresence("In the Menus", null);
+ #end
+
+ if (!FlxG.sound.music.playing)
+ {
+ FlxG.sound.playMusic(Paths.music('freakyMenu'));
+ }
+
+ persistentUpdate = persistentDraw = true;
+
+ var bg:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image('menuBG'));
+ bg.scrollFactor.x = 0;
+ bg.scrollFactor.y = 0.10;
+ bg.setGraphicSize(Std.int(bg.width * 1.1));
+ bg.updateHitbox();
+ bg.screenCenter();
+ bg.antialiasing = true;
+ add(bg);
+
+ camFollow = new FlxObject(0, 0, 1, 1);
+ add(camFollow);
+
+ magenta = new FlxSprite(-80).loadGraphic(Paths.image('menuDesat'));
+ magenta.scrollFactor.x = 0;
+ magenta.scrollFactor.y = 0.10;
+ magenta.setGraphicSize(Std.int(magenta.width * 1.1));
+ magenta.updateHitbox();
+ magenta.screenCenter();
+ magenta.visible = false;
+ magenta.antialiasing = true;
+ magenta.color = 0xFFfd719b;
+ add(magenta);
+ // magenta.scrollFactor.set();
+
+ menuItems = new FlxTypedGroup();
+ add(menuItems);
+
+ var tex = Paths.getSparrowAtlas('FNF_main_menu_assets');
+
+ for (i in 0...optionShit.length)
+ {
+ var menuItem:FlxSprite = new FlxSprite(0, FlxG.height * 1.6);
+ menuItem.frames = tex;
+ menuItem.animation.addByPrefix('idle', optionShit[i] + " basic", 24);
+ menuItem.animation.addByPrefix('selected', optionShit[i] + " white", 24);
+ menuItem.animation.play('idle');
+ menuItem.ID = i;
+ menuItem.screenCenter(X);
+ menuItems.add(menuItem);
+ menuItem.scrollFactor.set();
+ menuItem.antialiasing = true;
+ if (firstStart)
+ FlxTween.tween(menuItem,{y: 60 + (i * 160)},1 + (i * 0.25) ,{ease: FlxEase.expoInOut, onComplete: function(flxTween:FlxTween)
+ {
+ finishedFunnyMove = true;
+ changeItem();
+ }});
+ else
+ menuItem.y = 60 + (i * 160);
+ }
+
+ firstStart = false;
+
+ FlxG.camera.follow(camFollow, null, 0.60 * (60 / FlxG.save.data.fpsCap));
+
+ var versionShit:FlxText = new FlxText(5, FlxG.height - 18, 0, gameVer + (Main.watermarks ? " FNF - " + kadeEngineVer + " Kade Engine" : ""), 12);
+ versionShit.scrollFactor.set();
+ versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+ add(versionShit);
+
+ // NG.core.calls.event.logEvent('swag').send();
+
+
+ if (FlxG.save.data.dfjk)
+ controls.setKeyboardScheme(KeyboardScheme.Solo, true);
+ else
+ controls.setKeyboardScheme(KeyboardScheme.Duo(true), true);
+
+ changeItem();
+
+ super.create();
+ }
+
+ var selectedSomethin:Bool = false;
+
+ override function update(elapsed:Float)
+ {
+ if (FlxG.sound.music.volume < 0.8)
+ {
+ FlxG.sound.music.volume += 0.5 * FlxG.elapsed;
+ }
+
+ if (!selectedSomethin)
+ {
+ if (controls.UP_P)
+ {
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+ changeItem(-1);
+ }
+
+ if (controls.DOWN_P)
+ {
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+ changeItem(1);
+ }
+
+ if (controls.BACK)
+ {
+ FlxG.switchState(new TitleState());
+ }
+
+ if (controls.ACCEPT)
+ {
+ if (optionShit[curSelected] == 'donate')
+ {
+ fancyOpenURL("https://ninja-muffin24.itch.io/funkin");
+ }
+ else
+ {
+ selectedSomethin = true;
+ FlxG.sound.play(Paths.sound('confirmMenu'));
+
+ if (FlxG.save.data.flashing)
+ FlxFlicker.flicker(magenta, 1.1, 0.15, false);
+
+ menuItems.forEach(function(spr:FlxSprite)
+ {
+ if (curSelected != spr.ID)
+ {
+ FlxTween.tween(spr, {alpha: 0}, 1.3, {
+ ease: FlxEase.quadOut,
+ onComplete: function(twn:FlxTween)
+ {
+ spr.kill();
+ }
+ });
+ }
+ else
+ {
+ if (FlxG.save.data.flashing)
+ {
+ FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker)
+ {
+ goToState();
+ });
+ }
+ else
+ {
+ new FlxTimer().start(1, function(tmr:FlxTimer)
+ {
+ goToState();
+ });
+ }
+ }
+ });
+ }
+ }
+ }
+
+ super.update(elapsed);
+
+ menuItems.forEach(function(spr:FlxSprite)
+ {
+ spr.screenCenter(X);
+ });
+ }
+
+ function goToState()
+ {
+ var daChoice:String = optionShit[curSelected];
+
+ switch (daChoice)
+ {
+ case 'story mode':
+ FlxG.switchState(new StoryMenuState());
+ trace("Story Menu Selected");
+ case 'freeplay':
+ FlxG.switchState(new FreeplayState());
+
+ trace("Freeplay Menu Selected");
+
+ case 'options':
+ FlxG.switchState(new OptionsMenu());
+ }
+ }
+
+ function changeItem(huh:Int = 0)
+ {
+ if (finishedFunnyMove)
+ {
+ curSelected += huh;
+
+ if (curSelected >= menuItems.length)
+ curSelected = 0;
+ if (curSelected < 0)
+ curSelected = menuItems.length - 1;
+ }
+ menuItems.forEach(function(spr:FlxSprite)
+ {
+ spr.animation.play('idle');
+
+ if (spr.ID == curSelected && finishedFunnyMove)
+ {
+ spr.animation.play('selected');
+ camFollow.setPosition(spr.getGraphicMidpoint().x, spr.getGraphicMidpoint().y);
+ }
+
+ spr.updateHitbox();
+ });
+ }
+}
diff --git a/source - Copy/MenuCharacter.hx b/source - Copy/MenuCharacter.hx
new file mode 100644
index 0000000..1cf3e5b
--- /dev/null
+++ b/source - Copy/MenuCharacter.hx
@@ -0,0 +1,79 @@
+package;
+
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+
+class CharacterSetting
+{
+ public var x(default, null):Int;
+ public var y(default, null):Int;
+ public var scale(default, null):Float;
+ public var flipped(default, null):Bool;
+
+ public function new(x:Int = 0, y:Int = 0, scale:Float = 1.0, flipped:Bool = false)
+ {
+ this.x = x;
+ this.y = y;
+ this.scale = scale;
+ this.flipped = flipped;
+ }
+}
+
+class MenuCharacter extends FlxSprite
+{
+ private static var settings:Map = [
+ 'bf' => new CharacterSetting(0, -20, 1.0, true),
+ 'gf' => new CharacterSetting(50, 80, 1.5, true),
+ 'dad' => new CharacterSetting(-15, 130),
+ 'spooky' => new CharacterSetting(20, 30),
+ 'pico' => new CharacterSetting(0, 0, 1.0, true),
+ 'mom' => new CharacterSetting(-30, 140, 0.85),
+ 'parents-christmas' => new CharacterSetting(100, 130, 1.8),
+ 'senpai' => new CharacterSetting(-40, -45, 1.4)
+ ];
+
+ private var flipped:Bool = false;
+
+ public function new(x:Int, y:Int, scale:Float, flipped:Bool)
+ {
+ super(x, y);
+ this.flipped = flipped;
+
+ antialiasing = true;
+
+ frames = Paths.getSparrowAtlas('campaign_menu_UI_characters');
+
+ animation.addByPrefix('bf', "BF idle dance white", 24);
+ animation.addByPrefix('bfConfirm', 'BF HEY!!', 24, false);
+ animation.addByPrefix('gf', "GF Dancing Beat WHITE", 24);
+ animation.addByPrefix('dad', "Dad idle dance BLACK LINE", 24);
+ animation.addByPrefix('spooky', "spooky dance idle BLACK LINES", 24);
+ animation.addByPrefix('pico', "Pico Idle Dance", 24);
+ animation.addByPrefix('mom', "Mom Idle BLACK LINES", 24);
+ animation.addByPrefix('parents-christmas', "Parent Christmas Idle", 24);
+ animation.addByPrefix('senpai', "SENPAI idle Black Lines", 24);
+
+ setGraphicSize(Std.int(width * scale));
+ updateHitbox();
+ }
+
+ public function setCharacter(character:String):Void
+ {
+ if (character == '')
+ {
+ visible = false;
+ return;
+ }
+ else
+ {
+ visible = true;
+ }
+
+ animation.play(character);
+
+ var setting:CharacterSetting = settings[character];
+ offset.set(setting.x, setting.y);
+ setGraphicSize(Std.int(width * setting.scale));
+ flipX = setting.flipped != flipped;
+ }
+}
diff --git a/source - Copy/MenuItem.hx b/source - Copy/MenuItem.hx
new file mode 100644
index 0000000..5f8304b
--- /dev/null
+++ b/source - Copy/MenuItem.hx
@@ -0,0 +1,49 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxSpriteGroup;
+import flixel.math.FlxMath;
+import flixel.util.FlxColor;
+
+class MenuItem extends FlxSpriteGroup
+{
+ public var targetY:Float = 0;
+ public var week:FlxSprite;
+ public var flashingInt:Int = 0;
+
+ public function new(x:Float, y:Float, weekNum:Int = 0)
+ {
+ super(x, y);
+ week = new FlxSprite().loadGraphic(Paths.image('storymenu/week' + weekNum));
+ add(week);
+ }
+
+ private var isFlashing:Bool = false;
+
+ public function startFlashing():Void
+ {
+ isFlashing = true;
+ }
+
+ // if it runs at 60fps, fake framerate will be 6
+ // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still???
+ // so it runs basically every so many seconds, not dependant on framerate??
+ // I'm still learning how math works thanks whoever is reading this lol
+ var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10);
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+ y = FlxMath.lerp(y, (targetY * 120) + 480, 0.17 * (60 / FlxG.save.data.fpsCap));
+
+ if (isFlashing)
+ flashingInt += 1;
+
+ if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2))
+ week.color = 0xFF33ffff;
+ else if (FlxG.save.data.flashing)
+ week.color = FlxColor.WHITE;
+ }
+}
diff --git a/source - Copy/ModchartState.hx b/source - Copy/ModchartState.hx
new file mode 100644
index 0000000..6e194d1
--- /dev/null
+++ b/source - Copy/ModchartState.hx
@@ -0,0 +1,918 @@
+// this file is for modchart things, this is to declutter playstate.hx
+
+// Lua
+import openfl.display3D.textures.VideoTexture;
+import flixel.graphics.FlxGraphic;
+import flixel.graphics.frames.FlxAtlasFrames;
+#if windows
+import flixel.tweens.FlxEase;
+import openfl.filters.ShaderFilter;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import openfl.geom.Matrix;
+import openfl.display.BitmapData;
+import lime.app.Application;
+import flixel.FlxSprite;
+import llua.Convert;
+import llua.Lua;
+import llua.State;
+import llua.LuaL;
+import flixel.FlxBasic;
+import flixel.FlxCamera;
+import flixel.FlxG;
+
+class ModchartState
+{
+ //public static var shaders:Array = null;
+
+ public static var lua:State = null;
+
+ function callLua(func_name : String, args : Array, ?type : String) : Dynamic
+ {
+ var result : Any = null;
+
+ Lua.getglobal(lua, func_name);
+
+ for( arg in args ) {
+ Convert.toLua(lua, arg);
+ }
+
+ result = Lua.pcall(lua, args.length, 1, 0);
+ var p = Lua.tostring(lua,result);
+ var e = getLuaErrorMessage(lua);
+
+ if (e != null)
+ {
+ if (p != null)
+ {
+ Application.current.window.alert("LUA ERROR:\n" + p + "\nhaxe things: " + e,"Kade Engine Modcharts");
+ lua = null;
+ LoadingState.loadAndSwitchState(new MainMenuState());
+ }
+ // trace('err: ' + e);
+ }
+ if( result == null) {
+ return null;
+ } else {
+ return convert(result, type);
+ }
+
+ }
+
+ static function toLua(l:State, val:Any):Bool {
+ switch (Type.typeof(val)) {
+ case Type.ValueType.TNull:
+ Lua.pushnil(l);
+ case Type.ValueType.TBool:
+ Lua.pushboolean(l, val);
+ case Type.ValueType.TInt:
+ Lua.pushinteger(l, cast(val, Int));
+ case Type.ValueType.TFloat:
+ Lua.pushnumber(l, val);
+ case Type.ValueType.TClass(String):
+ Lua.pushstring(l, cast(val, String));
+ case Type.ValueType.TClass(Array):
+ Convert.arrayToLua(l, val);
+ case Type.ValueType.TObject:
+ objectToLua(l, val);
+ default:
+ trace("haxe value not supported - " + val + " which is a type of " + Type.typeof(val));
+ return false;
+ }
+
+ return true;
+
+ }
+
+ static function objectToLua(l:State, res:Any) {
+
+ var FUCK = 0;
+ for(n in Reflect.fields(res))
+ {
+ trace(Type.typeof(n).getName());
+ FUCK++;
+ }
+
+ Lua.createtable(l, FUCK, 0); // TODONE: I did it
+
+ for (n in Reflect.fields(res)){
+ if (!Reflect.isObject(n))
+ continue;
+ Lua.pushstring(l, n);
+ toLua(l, Reflect.field(res, n));
+ Lua.settable(l, -3);
+ }
+
+ }
+
+ function getType(l, type):Any
+ {
+ return switch Lua.type(l,type) {
+ case t if (t == Lua.LUA_TNIL): null;
+ case t if (t == Lua.LUA_TNUMBER): Lua.tonumber(l, type);
+ case t if (t == Lua.LUA_TSTRING): (Lua.tostring(l, type):String);
+ case t if (t == Lua.LUA_TBOOLEAN): Lua.toboolean(l, type);
+ case t: throw 'you don goofed up. lua type error ($t)';
+ }
+ }
+
+ function getReturnValues(l) {
+ var lua_v:Int;
+ var v:Any = null;
+ while((lua_v = Lua.gettop(l)) != 0) {
+ var type:String = getType(l,lua_v);
+ v = convert(lua_v, type);
+ Lua.pop(l, 1);
+ }
+ return v;
+ }
+
+
+ private function convert(v : Any, type : String) : Dynamic { // I didn't write this lol
+ if( Std.is(v, String) && type != null ) {
+ var v : String = v;
+ if( type.substr(0, 4) == 'array' ) {
+ if( type.substr(4) == 'float' ) {
+ var array : Array = v.split(',');
+ var array2 : Array = new Array();
+
+ for( vars in array ) {
+ array2.push(Std.parseFloat(vars));
+ }
+
+ return array2;
+ } else if( type.substr(4) == 'int' ) {
+ var array : Array = v.split(',');
+ var array2 : Array = new Array();
+
+ for( vars in array ) {
+ array2.push(Std.parseInt(vars));
+ }
+
+ return array2;
+ } else {
+ var array : Array = v.split(',');
+ return array;
+ }
+ } else if( type == 'float' ) {
+ return Std.parseFloat(v);
+ } else if( type == 'int' ) {
+ return Std.parseInt(v);
+ } else if( type == 'bool' ) {
+ if( v == 'true' ) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return v;
+ }
+ } else {
+ return v;
+ }
+ }
+
+ function getLuaErrorMessage(l) {
+ var v:String = Lua.tostring(l, -1);
+ Lua.pop(l, 1);
+ return v;
+ }
+
+ public function setVar(var_name : String, object : Dynamic){
+ // trace('setting variable ' + var_name + ' to ' + object);
+
+ Lua.pushnumber(lua,object);
+ Lua.setglobal(lua, var_name);
+ }
+
+ public function getVar(var_name : String, type : String) : Dynamic {
+ var result : Any = null;
+
+ // trace('getting variable ' + var_name + ' with a type of ' + type);
+
+ Lua.getglobal(lua, var_name);
+ result = Convert.fromLua(lua,-1);
+ Lua.pop(lua,1);
+
+ if( result == null ) {
+ return null;
+ } else {
+ var result = convert(result, type);
+ //trace(var_name + ' result: ' + result);
+ return result;
+ }
+ }
+
+ function getActorByName(id:String):Dynamic
+ {
+ // pre defined names
+ switch(id)
+ {
+ case 'boyfriend':
+ @:privateAccess
+ return PlayState.boyfriend;
+ case 'girlfriend':
+ @:privateAccess
+ return PlayState.gf;
+ case 'dad':
+ @:privateAccess
+ return PlayState.dad;
+ }
+ // lua objects or what ever
+ if (luaSprites.get(id) == null)
+ {
+ if (Std.parseInt(id) == null)
+ return Reflect.getProperty(PlayState.instance,id);
+ return PlayState.PlayState.strumLineNotes.members[Std.parseInt(id)];
+ }
+ return luaSprites.get(id);
+ }
+
+ function getPropertyByName(id:String)
+ {
+ return Reflect.field(PlayState.instance,id);
+ }
+
+ public static var luaSprites:Map = [];
+
+ function changeDadCharacter(id:String)
+ { var olddadx = PlayState.dad.x;
+ var olddady = PlayState.dad.y;
+ PlayState.instance.removeObject(PlayState.dad);
+ PlayState.dad = new Character(olddadx, olddady, id);
+ PlayState.instance.addObject(PlayState.dad);
+ PlayState.instance.iconP2.animation.play(id);
+ }
+
+ function changeBoyfriendCharacter(id:String)
+ { var oldboyfriendx = PlayState.boyfriend.x;
+ var oldboyfriendy = PlayState.boyfriend.y;
+ PlayState.instance.removeObject(PlayState.boyfriend);
+ PlayState.boyfriend = new Boyfriend(oldboyfriendx, oldboyfriendy, id);
+ PlayState.instance.addObject(PlayState.boyfriend);
+ PlayState.instance.iconP2.animation.play(id);
+ }
+
+ function makeAnimatedLuaSprite(spritePath:String,names:Array,prefixes:Array,startAnim:String, id:String)
+ {
+ #if sys
+ // pre lowercasing the song name (makeAnimatedLuaSprite)
+ var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+
+ var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + songLowercase + '/' + spritePath + ".png");
+
+ var sprite:FlxSprite = new FlxSprite(0,0);
+
+ sprite.frames = FlxAtlasFrames.fromSparrow(FlxGraphic.fromBitmapData(data), Sys.getCwd() + "assets/data/" + songLowercase + "/" + spritePath + ".xml");
+
+ trace(sprite.frames.frames.length);
+
+ for (p in 0...names.length)
+ {
+ var i = names[p];
+ var ii = prefixes[p];
+ sprite.animation.addByPrefix(i,ii,24,false);
+ }
+
+ luaSprites.set(id,sprite);
+
+ PlayState.instance.addObject(sprite);
+
+ sprite.animation.play(startAnim);
+ return id;
+ #end
+ }
+
+ function makeLuaSprite(spritePath:String,toBeCalled:String, drawBehind:Bool)
+ {
+ #if sys
+ // pre lowercasing the song name (makeLuaSprite)
+ var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+
+ var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + songLowercase + '/' + spritePath + ".png");
+
+ var sprite:FlxSprite = new FlxSprite(0,0);
+ var imgWidth:Float = FlxG.width / data.width;
+ var imgHeight:Float = FlxG.height / data.height;
+ var scale:Float = imgWidth <= imgHeight ? imgWidth : imgHeight;
+
+ // Cap the scale at x1
+ if (scale > 1)
+ scale = 1;
+
+ sprite.makeGraphic(Std.int(data.width * scale),Std.int(data.width * scale),FlxColor.TRANSPARENT);
+
+ var data2:BitmapData = sprite.pixels.clone();
+ var matrix:Matrix = new Matrix();
+ matrix.identity();
+ matrix.scale(scale, scale);
+ data2.fillRect(data2.rect, FlxColor.TRANSPARENT);
+ data2.draw(data, matrix, null, null, null, true);
+ sprite.pixels = data2;
+
+ luaSprites.set(toBeCalled,sprite);
+ // and I quote:
+ // shitty layering but it works!
+ @:privateAccess
+ {
+ if (drawBehind)
+ {
+ PlayState.instance.removeObject(PlayState.gf);
+ PlayState.instance.removeObject(PlayState.boyfriend);
+ PlayState.instance.removeObject(PlayState.dad);
+ }
+ PlayState.instance.addObject(sprite);
+ if (drawBehind)
+ {
+ PlayState.instance.addObject(PlayState.gf);
+ PlayState.instance.addObject(PlayState.boyfriend);
+ PlayState.instance.addObject(PlayState.dad);
+ }
+ }
+ #end
+ return toBeCalled;
+ }
+
+ public function die()
+ {
+ Lua.close(lua);
+ lua = null;
+ }
+
+ // LUA SHIT
+
+ function new()
+ {
+ trace('opening a lua state (because we are cool :))');
+ lua = LuaL.newstate();
+ LuaL.openlibs(lua);
+ trace("Lua version: " + Lua.version());
+ trace("LuaJIT version: " + Lua.versionJIT());
+ Lua.init_callbacks(lua);
+
+ //shaders = new Array();
+
+ // pre lowercasing the song name (new)
+ var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+
+ var result = LuaL.dofile(lua, Paths.lua(songLowercase + "/modchart")); // execute le file
+
+ if (result != 0)
+ {
+ Application.current.window.alert("LUA COMPILE ERROR:\n" + Lua.tostring(lua,result),"Kade Engine Modcharts");
+ lua = null;
+ LoadingState.loadAndSwitchState(new MainMenuState());
+ }
+
+ // get some fukin globals up in here bois
+
+ setVar("difficulty", PlayState.storyDifficulty);
+ setVar("bpm", Conductor.bpm);
+ setVar("scrollspeed", FlxG.save.data.scrollSpeed != 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed);
+ setVar("fpsCap", FlxG.save.data.fpsCap);
+ setVar("downscroll", FlxG.save.data.downscroll);
+ setVar("flashing", FlxG.save.data.flashing);
+ setVar("distractions", FlxG.save.data.distractions);
+
+ setVar("curStep", 0);
+ setVar("curBeat", 0);
+ setVar("crochet", Conductor.stepCrochet);
+ setVar("safeZoneOffset", Conductor.safeZoneOffset);
+
+ setVar("hudZoom", PlayState.instance.camHUD.zoom);
+ setVar("cameraZoom", FlxG.camera.zoom);
+
+ setVar("cameraAngle", FlxG.camera.angle);
+ setVar("camHudAngle", PlayState.instance.camHUD.angle);
+
+ setVar("followXOffset",0);
+ setVar("followYOffset",0);
+
+ setVar("showOnlyStrums", false);
+ setVar("strumLine1Visible", true);
+ setVar("strumLine2Visible", true);
+
+ setVar("screenWidth",FlxG.width);
+ setVar("screenHeight",FlxG.height);
+ setVar("windowWidth",FlxG.width);
+ setVar("windowHeight",FlxG.height);
+ setVar("hudWidth", PlayState.instance.camHUD.width);
+ setVar("hudHeight", PlayState.instance.camHUD.height);
+
+ setVar("mustHit", false);
+
+ setVar("strumLineY", PlayState.instance.strumLine.y);
+
+ // callbacks
+
+ // sprites
+
+ Lua_helper.add_callback(lua,"makeSprite", makeLuaSprite);
+
+ Lua_helper.add_callback(lua,"changeDadCharacter", changeDadCharacter);
+
+ Lua_helper.add_callback(lua,"changeBoyfriendCharacter", changeBoyfriendCharacter);
+
+ Lua_helper.add_callback(lua,"getProperty", getPropertyByName);
+
+ // Lua_helper.add_callback(lua,"makeAnimatedSprite", makeAnimatedLuaSprite);
+ // this one is still in development
+
+ Lua_helper.add_callback(lua,"destroySprite", function(id:String) {
+ var sprite = luaSprites.get(id);
+ if (sprite == null)
+ return false;
+ PlayState.instance.removeObject(sprite);
+ return true;
+ });
+
+ // hud/camera
+
+ Lua_helper.add_callback(lua,"initBackgroundVideo", function(videoName:String) {
+ trace('playing assets/videos/' + videoName + '.webm');
+ PlayState.instance.backgroundVideo("assets/videos/" + videoName + ".webm");
+ });
+
+ Lua_helper.add_callback(lua,"pauseVideo", function() {
+ if (!GlobalVideo.get().paused)
+ GlobalVideo.get().pause();
+ });
+
+ Lua_helper.add_callback(lua,"resumeVideo", function() {
+ if (GlobalVideo.get().paused)
+ GlobalVideo.get().pause();
+ });
+
+ Lua_helper.add_callback(lua,"restartVideo", function() {
+ GlobalVideo.get().restart();
+ });
+
+ Lua_helper.add_callback(lua,"getVideoSpriteX", function() {
+ return PlayState.instance.videoSprite.x;
+ });
+
+ Lua_helper.add_callback(lua,"getVideoSpriteY", function() {
+ return PlayState.instance.videoSprite.y;
+ });
+
+ Lua_helper.add_callback(lua,"setVideoSpritePos", function(x:Int,y:Int) {
+ PlayState.instance.videoSprite.setPosition(x,y);
+ });
+
+ Lua_helper.add_callback(lua,"setVideoSpriteScale", function(scale:Float) {
+ PlayState.instance.videoSprite.setGraphicSize(Std.int(PlayState.instance.videoSprite.width * scale));
+ });
+
+ Lua_helper.add_callback(lua,"setHudAngle", function (x:Float) {
+ PlayState.instance.camHUD.angle = x;
+ });
+
+ Lua_helper.add_callback(lua,"setHealth", function (heal:Float) {
+ PlayState.instance.health = heal;
+ });
+
+ Lua_helper.add_callback(lua,"setHudPosition", function (x:Int, y:Int) {
+ PlayState.instance.camHUD.x = x;
+ PlayState.instance.camHUD.y = y;
+ });
+
+ Lua_helper.add_callback(lua,"getHudX", function () {
+ return PlayState.instance.camHUD.x;
+ });
+
+ Lua_helper.add_callback(lua,"getHudY", function () {
+ return PlayState.instance.camHUD.y;
+ });
+
+ Lua_helper.add_callback(lua,"setCamPosition", function (x:Int, y:Int) {
+ FlxG.camera.x = x;
+ FlxG.camera.y = y;
+ });
+
+ Lua_helper.add_callback(lua,"getCameraX", function () {
+ return FlxG.camera.x;
+ });
+
+ Lua_helper.add_callback(lua,"getCameraY", function () {
+ return FlxG.camera.y;
+ });
+
+ Lua_helper.add_callback(lua,"setCamZoom", function(zoomAmount:Float) {
+ FlxG.camera.zoom = zoomAmount;
+ });
+
+ Lua_helper.add_callback(lua,"setHudZoom", function(zoomAmount:Float) {
+ PlayState.instance.camHUD.zoom = zoomAmount;
+ });
+
+ // strumline
+
+ Lua_helper.add_callback(lua, "setStrumlineY", function(y:Float)
+ {
+ PlayState.instance.strumLine.y = y;
+ });
+
+ // actors
+
+ Lua_helper.add_callback(lua,"getRenderedNotes", function() {
+ return PlayState.instance.notes.length;
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteX", function(id:Int) {
+ return PlayState.instance.notes.members[id].x;
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteY", function(id:Int) {
+ return PlayState.instance.notes.members[id].y;
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteType", function(id:Int) {
+ return PlayState.instance.notes.members[id].noteData;
+ });
+
+ Lua_helper.add_callback(lua,"isSustain", function(id:Int) {
+ return PlayState.instance.notes.members[id].isSustainNote;
+ });
+
+ Lua_helper.add_callback(lua,"isParentSustain", function(id:Int) {
+ return PlayState.instance.notes.members[id].prevNote.isSustainNote;
+ });
+
+
+ Lua_helper.add_callback(lua,"getRenderedNoteParentX", function(id:Int) {
+ return PlayState.instance.notes.members[id].prevNote.x;
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteParentY", function(id:Int) {
+ return PlayState.instance.notes.members[id].prevNote.y;
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteHit", function(id:Int) {
+ return PlayState.instance.notes.members[id].mustPress;
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteCalcX", function(id:Int) {
+ if (PlayState.instance.notes.members[id].mustPress)
+ return PlayState.playerStrums.members[Math.floor(Math.abs(PlayState.instance.notes.members[id].noteData))].x;
+ return PlayState.strumLineNotes.members[Math.floor(Math.abs(PlayState.instance.notes.members[id].noteData))].x;
+ });
+
+ Lua_helper.add_callback(lua,"anyNotes", function() {
+ return PlayState.instance.notes.members.length != 0;
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteStrumtime", function(id:Int) {
+ return PlayState.instance.notes.members[id].strumTime;
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteScaleX", function(id:Int) {
+ return PlayState.instance.notes.members[id].scale.x;
+ });
+
+ Lua_helper.add_callback(lua,"setRenderedNotePos", function(x:Float,y:Float, id:Int) {
+ if (PlayState.instance.notes.members[id] == null)
+ throw('error! you cannot set a rendered notes position when it doesnt exist! ID: ' + id);
+ else
+ {
+ PlayState.instance.notes.members[id].modifiedByLua = true;
+ PlayState.instance.notes.members[id].x = x;
+ PlayState.instance.notes.members[id].y = y;
+ }
+ });
+
+ Lua_helper.add_callback(lua,"setRenderedNoteAlpha", function(alpha:Float, id:Int) {
+ PlayState.instance.notes.members[id].modifiedByLua = true;
+ PlayState.instance.notes.members[id].alpha = alpha;
+ });
+
+ Lua_helper.add_callback(lua,"setRenderedNoteScale", function(scale:Float, id:Int) {
+ PlayState.instance.notes.members[id].modifiedByLua = true;
+ PlayState.instance.notes.members[id].setGraphicSize(Std.int(PlayState.instance.notes.members[id].width * scale));
+ });
+
+ Lua_helper.add_callback(lua,"setRenderedNoteScale", function(scaleX:Int, scaleY:Int, id:Int) {
+ PlayState.instance.notes.members[id].modifiedByLua = true;
+ PlayState.instance.notes.members[id].setGraphicSize(scaleX,scaleY);
+ });
+
+ Lua_helper.add_callback(lua,"getRenderedNoteWidth", function(id:Int) {
+ return PlayState.instance.notes.members[id].width;
+ });
+
+
+ Lua_helper.add_callback(lua,"setRenderedNoteAngle", function(angle:Float, id:Int) {
+ PlayState.instance.notes.members[id].modifiedByLua = true;
+ PlayState.instance.notes.members[id].angle = angle;
+ });
+
+ Lua_helper.add_callback(lua,"setActorX", function(x:Int,id:String) {
+ getActorByName(id).x = x;
+ });
+
+ Lua_helper.add_callback(lua,"setActorAccelerationX", function(x:Int,id:String) {
+ getActorByName(id).acceleration.x = x;
+ });
+
+ Lua_helper.add_callback(lua,"setActorDragX", function(x:Int,id:String) {
+ getActorByName(id).drag.x = x;
+ });
+
+ Lua_helper.add_callback(lua,"setActorVelocityX", function(x:Int,id:String) {
+ getActorByName(id).velocity.x = x;
+ });
+
+ Lua_helper.add_callback(lua,"playActorAnimation", function(id:String,anim:String,force:Bool = false,reverse:Bool = false) {
+ getActorByName(id).playAnim(anim, force, reverse);
+ });
+
+ Lua_helper.add_callback(lua,"setActorAlpha", function(alpha:Float,id:String) {
+ getActorByName(id).alpha = alpha;
+ });
+
+ Lua_helper.add_callback(lua,"setActorY", function(y:Int,id:String) {
+ getActorByName(id).y = y;
+ });
+
+ Lua_helper.add_callback(lua,"setActorAccelerationY", function(y:Int,id:String) {
+ getActorByName(id).acceleration.y = y;
+ });
+
+ Lua_helper.add_callback(lua,"setActorDragY", function(y:Int,id:String) {
+ getActorByName(id).drag.y = y;
+ });
+
+ Lua_helper.add_callback(lua,"setActorVelocityY", function(y:Int,id:String) {
+ getActorByName(id).velocity.y = y;
+ });
+
+ Lua_helper.add_callback(lua,"setActorAngle", function(angle:Int,id:String) {
+ getActorByName(id).angle = angle;
+ });
+
+ Lua_helper.add_callback(lua,"setActorScale", function(scale:Float,id:String) {
+ getActorByName(id).setGraphicSize(Std.int(getActorByName(id).width * scale));
+ });
+
+ Lua_helper.add_callback(lua, "setActorScaleXY", function(scaleX:Float, scaleY:Float, id:String)
+ {
+ getActorByName(id).setGraphicSize(Std.int(getActorByName(id).width * scaleX), Std.int(getActorByName(id).height * scaleY));
+ });
+
+ Lua_helper.add_callback(lua, "setActorFlipX", function(flip:Bool, id:String)
+ {
+ getActorByName(id).flipX = flip;
+ });
+
+ Lua_helper.add_callback(lua, "setActorFlipY", function(flip:Bool, id:String)
+ {
+ getActorByName(id).flipY = flip;
+ });
+
+ Lua_helper.add_callback(lua,"getActorWidth", function (id:String) {
+ return getActorByName(id).width;
+ });
+
+ Lua_helper.add_callback(lua,"getActorHeight", function (id:String) {
+ return getActorByName(id).height;
+ });
+
+ Lua_helper.add_callback(lua,"getActorAlpha", function(id:String) {
+ return getActorByName(id).alpha;
+ });
+
+ Lua_helper.add_callback(lua,"getActorAngle", function(id:String) {
+ return getActorByName(id).angle;
+ });
+
+ Lua_helper.add_callback(lua,"getActorX", function (id:String) {
+ return getActorByName(id).x;
+ });
+
+ Lua_helper.add_callback(lua,"getActorY", function (id:String) {
+ return getActorByName(id).y;
+ });
+
+ Lua_helper.add_callback(lua,"setWindowPos",function(x:Int,y:Int) {
+ Application.current.window.x = x;
+ Application.current.window.y = y;
+ });
+
+ Lua_helper.add_callback(lua,"getWindowX",function() {
+ return Application.current.window.x;
+ });
+
+ Lua_helper.add_callback(lua,"getWindowY",function() {
+ return Application.current.window.y;
+ });
+
+ Lua_helper.add_callback(lua,"resizeWindow",function(Width:Int,Height:Int) {
+ Application.current.window.resize(Width,Height);
+ });
+
+ Lua_helper.add_callback(lua,"getScreenWidth",function() {
+ return Application.current.window.display.currentMode.width;
+ });
+
+ Lua_helper.add_callback(lua,"getScreenHeight",function() {
+ return Application.current.window.display.currentMode.height;
+ });
+
+ Lua_helper.add_callback(lua,"getWindowWidth",function() {
+ return Application.current.window.width;
+ });
+
+ Lua_helper.add_callback(lua,"getWindowHeight",function() {
+ return Application.current.window.height;
+ });
+
+
+ // tweens
+
+ Lua_helper.add_callback(lua,"tweenCameraPos", function(toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {x: toX, y: toY}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenCameraAngle", function(toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {angle:toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenCameraZoom", function(toZoom:Float, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {zoom:toZoom}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudPos", function(toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {x: toX, y: toY}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudAngle", function(toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {angle:toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudZoom", function(toZoom:Float, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {zoom:toZoom}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPos", function(id:String, toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {x: toX, y: toY}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPosXAngle", function(id:String, toX:Int, toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {x: toX, angle: toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPosYAngle", function(id:String, toY:Int, toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {y: toY, angle: toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenAngle", function(id:String, toAngle:Int, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {angle: toAngle}, time, {ease: FlxEase.linear, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenCameraPosOut", function(toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {x: toX, y: toY}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenCameraAngleOut", function(toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {angle:toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenCameraZoomOut", function(toZoom:Float, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {zoom:toZoom}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudPosOut", function(toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {x: toX, y: toY}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudAngleOut", function(toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {angle:toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudZoomOut", function(toZoom:Float, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {zoom:toZoom}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPosOut", function(id:String, toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {x: toX, y: toY}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPosXAngleOut", function(id:String, toX:Int, toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {x: toX, angle: toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPosYAngleOut", function(id:String, toY:Int, toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {y: toY, angle: toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenAngleOut", function(id:String, toAngle:Int, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {angle: toAngle}, time, {ease: FlxEase.cubeOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenCameraPosIn", function(toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {x: toX, y: toY}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenCameraAngleIn", function(toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {angle:toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenCameraZoomIn", function(toZoom:Float, time:Float, onComplete:String) {
+ FlxTween.tween(FlxG.camera, {zoom:toZoom}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudPosIn", function(toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {x: toX, y: toY}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudAngleIn", function(toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {angle:toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenHudZoomIn", function(toZoom:Float, time:Float, onComplete:String) {
+ FlxTween.tween(PlayState.instance.camHUD, {zoom:toZoom}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,["camera"]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPosIn", function(id:String, toX:Int, toY:Int, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {x: toX, y: toY}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPosXAngleIn", function(id:String, toX:Int, toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {x: toX, angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenPosYAngleIn", function(id:String, toY:Int, toAngle:Float, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {y: toY, angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenAngleIn", function(id:String, toAngle:Int, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenFadeIn", function(id:String, toAlpha:Float, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {alpha: toAlpha}, time, {ease: FlxEase.circIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ Lua_helper.add_callback(lua,"tweenFadeOut", function(id:String, toAlpha:Float, time:Float, onComplete:String) {
+ FlxTween.tween(getActorByName(id), {alpha: toAlpha}, time, {ease: FlxEase.circOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
+ });
+
+ //forgot and accidentally commit to master branch
+ // shader
+
+ /*Lua_helper.add_callback(lua,"createShader", function(frag:String,vert:String) {
+ var shader:LuaShader = new LuaShader(frag,vert);
+
+ trace(shader.glFragmentSource);
+
+ shaders.push(shader);
+ // if theres 1 shader we want to say theres 0 since 0 index and length returns a 1 index.
+ return shaders.length == 1 ? 0 : shaders.length;
+ });
+
+
+ Lua_helper.add_callback(lua,"setFilterHud", function(shaderIndex:Int) {
+ PlayState.instance.camHUD.setFilters([new ShaderFilter(shaders[shaderIndex])]);
+ });
+
+ Lua_helper.add_callback(lua,"setFilterCam", function(shaderIndex:Int) {
+ FlxG.camera.setFilters([new ShaderFilter(shaders[shaderIndex])]);
+ });*/
+
+ // default strums
+
+ for (i in 0...PlayState.strumLineNotes.length) {
+ var member = PlayState.strumLineNotes.members[i];
+ trace(PlayState.strumLineNotes.members[i].x + " " + PlayState.strumLineNotes.members[i].y + " " + PlayState.strumLineNotes.members[i].angle + " | strum" + i);
+ //setVar("strum" + i + "X", Math.floor(member.x));
+ setVar("defaultStrum" + i + "X", Math.floor(member.x));
+ //setVar("strum" + i + "Y", Math.floor(member.y));
+ setVar("defaultStrum" + i + "Y", Math.floor(member.y));
+ //setVar("strum" + i + "Angle", Math.floor(member.angle));
+ setVar("defaultStrum" + i + "Angle", Math.floor(member.angle));
+ trace("Adding strum" + i);
+ }
+ }
+
+ public function executeState(name,args:Array)
+ {
+ return Lua.tostring(lua,callLua(name, args));
+ }
+
+ public static function createModchartState():ModchartState
+ {
+ return new ModchartState();
+ }
+}
+#end
diff --git a/source - Copy/MusicBeatState.hx b/source - Copy/MusicBeatState.hx
new file mode 100644
index 0000000..d98bd64
--- /dev/null
+++ b/source - Copy/MusicBeatState.hx
@@ -0,0 +1,123 @@
+package;
+
+#if windows
+import Discord.DiscordClient;
+#end
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import openfl.Lib;
+import Conductor.BPMChangeEvent;
+import flixel.FlxG;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.addons.ui.FlxUIState;
+import flixel.math.FlxRect;
+import flixel.util.FlxTimer;
+
+class MusicBeatState extends FlxUIState
+{
+ private var lastBeat:Float = 0;
+ private var lastStep:Float = 0;
+
+ private var curStep:Int = 0;
+ private var curBeat:Int = 0;
+ private var controls(get, never):Controls;
+
+ inline function get_controls():Controls
+ return PlayerSettings.player1.controls;
+
+ override function create()
+ {
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(FlxG.save.data.fpsCap);
+
+ if (transIn != null)
+ trace('reg ' + transIn.region);
+
+ super.create();
+ }
+
+
+ var array:Array = [
+ FlxColor.fromRGB(148, 0, 211),
+ FlxColor.fromRGB(75, 0, 130),
+ FlxColor.fromRGB(0, 0, 255),
+ FlxColor.fromRGB(0, 255, 0),
+ FlxColor.fromRGB(255, 255, 0),
+ FlxColor.fromRGB(255, 127, 0),
+ FlxColor.fromRGB(255, 0 , 0)
+ ];
+
+ var skippedFrames = 0;
+
+ override function update(elapsed:Float)
+ {
+ //everyStep();
+ var oldStep:Int = curStep;
+
+ updateCurStep();
+ updateBeat();
+
+ if (oldStep != curStep && curStep > 0)
+ stepHit();
+
+ if (FlxG.save.data.fpsRain && skippedFrames >= 6)
+ {
+ if (currentColor >= array.length)
+ currentColor = 0;
+ (cast (Lib.current.getChildAt(0), Main)).changeFPSColor(array[currentColor]);
+ currentColor++;
+ skippedFrames = 0;
+ }
+ else
+ skippedFrames++;
+
+ if ((cast (Lib.current.getChildAt(0), Main)).getFPSCap != FlxG.save.data.fpsCap && FlxG.save.data.fpsCap <= 290)
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(FlxG.save.data.fpsCap);
+
+ super.update(elapsed);
+ }
+
+ private function updateBeat():Void
+ {
+ lastBeat = curStep;
+ curBeat = Math.floor(curStep / 4);
+ }
+
+ public static var currentColor = 0;
+
+ private function updateCurStep():Void
+ {
+ var lastChange:BPMChangeEvent = {
+ stepTime: 0,
+ songTime: 0,
+ bpm: 0
+ }
+ for (i in 0...Conductor.bpmChangeMap.length)
+ {
+ if (Conductor.songPosition >= Conductor.bpmChangeMap[i].songTime)
+ lastChange = Conductor.bpmChangeMap[i];
+ }
+
+ curStep = lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet);
+ }
+
+ public function stepHit():Void
+ {
+
+ if (curStep % 4 == 0)
+ beatHit();
+ }
+
+ public function beatHit():Void
+ {
+ //do literally nothing dumbass
+ }
+
+ public function fancyOpenURL(schmancy:String)
+ {
+ #if linux
+ Sys.command('/usr/bin/xdg-open', [schmancy, "&"]);
+ #else
+ FlxG.openURL(schmancy);
+ #end
+ }
+}
diff --git a/source - Copy/MusicBeatSubstate.hx b/source - Copy/MusicBeatSubstate.hx
new file mode 100644
index 0000000..c6da0fb
--- /dev/null
+++ b/source - Copy/MusicBeatSubstate.hx
@@ -0,0 +1,65 @@
+package;
+
+import Conductor.BPMChangeEvent;
+import flixel.FlxG;
+import flixel.FlxSubState;
+
+class MusicBeatSubstate extends FlxSubState
+{
+ public function new()
+ {
+ super();
+ }
+
+ private var lastBeat:Float = 0;
+ private var lastStep:Float = 0;
+
+ private var curStep:Int = 0;
+ private var curBeat:Int = 0;
+ private var controls(get, never):Controls;
+
+ inline function get_controls():Controls
+ return PlayerSettings.player1.controls;
+
+ override function update(elapsed:Float)
+ {
+ //everyStep();
+ var oldStep:Int = curStep;
+
+ updateCurStep();
+ curBeat = Math.floor(curStep / 4);
+
+ if (oldStep != curStep && curStep > 0)
+ stepHit();
+
+
+ super.update(elapsed);
+ }
+
+ private function updateCurStep():Void
+ {
+ var lastChange:BPMChangeEvent = {
+ stepTime: 0,
+ songTime: 0,
+ bpm: 0
+ }
+ for (i in 0...Conductor.bpmChangeMap.length)
+ {
+ if (Conductor.songPosition > Conductor.bpmChangeMap[i].songTime)
+ lastChange = Conductor.bpmChangeMap[i];
+ }
+
+ curStep = lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet);
+ }
+
+ public function stepHit():Void
+ {
+ if (curStep % 4 == 0)
+ beatHit();
+ }
+
+ public function beatHit():Void
+ {
+ //do literally nothing dumbass
+ }
+}
diff --git a/source - Copy/NGio.hx b/source - Copy/NGio.hx
new file mode 100644
index 0000000..f8d8948
--- /dev/null
+++ b/source - Copy/NGio.hx
@@ -0,0 +1,200 @@
+package;
+
+import flixel.FlxG;
+import flixel.util.FlxSignal;
+import flixel.util.FlxTimer;
+import io.newgrounds.NG;
+import io.newgrounds.components.ScoreBoardComponent.Period;
+import io.newgrounds.objects.Medal;
+import io.newgrounds.objects.Score;
+import io.newgrounds.objects.ScoreBoard;
+import io.newgrounds.objects.events.Response;
+import io.newgrounds.objects.events.Result.GetCurrentVersionResult;
+import io.newgrounds.objects.events.Result.GetVersionResult;
+import lime.app.Application;
+import openfl.display.Stage;
+
+using StringTools;
+
+/**
+ * MADE BY GEOKURELI THE LEGENED GOD HERO MVP
+ */
+class NGio
+{
+ public static var isLoggedIn:Bool = false;
+ public static var scoreboardsLoaded:Bool = false;
+
+ public static var scoreboardArray:Array = [];
+
+ public static var ngDataLoaded(default, null):FlxSignal = new FlxSignal();
+ public static var ngScoresLoaded(default, null):FlxSignal = new FlxSignal();
+
+ public static var GAME_VER:String = "";
+ public static var GAME_VER_NUMS:String = '';
+ public static var gotOnlineVer:Bool = false;
+
+ public static function noLogin(api:String)
+ {
+ trace('INIT NOLOGIN');
+ GAME_VER = "v" + Application.current.meta.get('version');
+
+ if (api.length != 0)
+ {
+ NG.create(api);
+
+ new FlxTimer().start(2, function(tmr:FlxTimer)
+ {
+ var call = NG.core.calls.app.getCurrentVersion(GAME_VER).addDataHandler(function(response:Response)
+ {
+ GAME_VER = response.result.data.currentVersion;
+ GAME_VER_NUMS = GAME_VER.split(" ")[0].trim();
+ trace('CURRENT NG VERSION: ' + GAME_VER);
+ trace('CURRENT NG VERSION: ' + GAME_VER_NUMS);
+ gotOnlineVer = true;
+ });
+
+ call.send();
+ });
+ }
+ }
+
+ public function new(api:String, encKey:String, ?sessionId:String)
+ {
+ trace("connecting to newgrounds");
+
+ NG.createAndCheckSession(api, sessionId);
+
+ NG.core.verbose = true;
+ // Set the encryption cipher/format to RC4/Base64. AES128 and Hex are not implemented yet
+ NG.core.initEncryption(encKey); // Found in you NG project view
+
+ trace(NG.core.attemptingLogin);
+
+ if (NG.core.attemptingLogin)
+ {
+ /* a session_id was found in the loadervars, this means the user is playing on newgrounds.com
+ * and we should login shortly. lets wait for that to happen
+ */
+ trace("attempting login");
+ NG.core.onLogin.add(onNGLogin);
+ }
+ else
+ {
+ /* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to.
+ * Note: This will cause a new browser window to pop up where they can log in to newgrounds
+ */
+ NG.core.requestLogin(onNGLogin);
+ }
+ }
+
+ function onNGLogin():Void
+ {
+ trace('logged in! user:${NG.core.user.name}');
+ isLoggedIn = true;
+ FlxG.save.data.sessionId = NG.core.sessionId;
+ // FlxG.save.flush();
+ // Load medals then call onNGMedalFetch()
+ NG.core.requestMedals(onNGMedalFetch);
+
+ // Load Scoreboards hten call onNGBoardsFetch()
+ NG.core.requestScoreBoards(onNGBoardsFetch);
+
+ ngDataLoaded.dispatch();
+ }
+
+ // --- MEDALS
+ function onNGMedalFetch():Void
+ {
+ /*
+ // Reading medal info
+ for (id in NG.core.medals.keys())
+ {
+ var medal = NG.core.medals.get(id);
+ trace('loaded medal id:$id, name:${medal.name}, description:${medal.description}');
+ }
+
+ // Unlocking medals
+ var unlockingMedal = NG.core.medals.get(54352);// medal ids are listed in your NG project viewer
+ if (!unlockingMedal.unlocked)
+ unlockingMedal.sendUnlock();
+ */
+ }
+
+ // --- SCOREBOARDS
+ function onNGBoardsFetch():Void
+ {
+ /*
+ // Reading medal info
+ for (id in NG.core.scoreBoards.keys())
+ {
+ var board = NG.core.scoreBoards.get(id);
+ trace('loaded scoreboard id:$id, name:${board.name}');
+ }
+ */
+ // var board = NG.core.scoreBoards.get(8004);// ID found in NG project view
+
+ // Posting a score thats OVER 9000!
+ // board.postScore(FlxG.random.int(0, 1000));
+
+ // --- To view the scores you first need to select the range of scores you want to see ---
+
+ // add an update listener so we know when we get the new scores
+ // board.onUpdate.add(onNGScoresFetch);
+ trace("shoulda got score by NOW!");
+ // board.requestScores(20);// get the best 10 scores ever logged
+ // more info on scores --- http://www.newgrounds.io/help/components/#scoreboard-getscores
+ }
+
+ inline static public function postScore(score:Int = 0, song:String)
+ {
+ if (isLoggedIn)
+ {
+ for (id in NG.core.scoreBoards.keys())
+ {
+ var board = NG.core.scoreBoards.get(id);
+
+ if (song == board.name)
+ {
+ board.postScore(score, "Uhh meow?");
+ }
+
+ // trace('loaded scoreboard id:$id, name:${board.name}');
+ }
+ }
+ }
+
+ function onNGScoresFetch():Void
+ {
+ scoreboardsLoaded = true;
+
+ ngScoresLoaded.dispatch();
+ /*
+ for (score in NG.core.scoreBoards.get(8737).scores)
+ {
+ trace('score loaded user:${score.user.name}, score:${score.formatted_value}');
+
+ }
+ */
+
+ // var board = NG.core.scoreBoards.get(8004);// ID found in NG project view
+ // board.postScore(HighScore.score);
+
+ // NGio.scoreboardArray = NG.core.scoreBoards.get(8004).scores;
+ }
+
+ inline static public function logEvent(event:String)
+ {
+ NG.core.calls.event.logEvent(event).send();
+ trace('should have logged: ' + event);
+ }
+
+ inline static public function unlockMedal(id:Int)
+ {
+ if (isLoggedIn)
+ {
+ var medal = NG.core.medals.get(id);
+ if (!medal.unlocked)
+ medal.sendUnlock();
+ }
+ }
+}
diff --git a/source - Copy/Note.hx b/source - Copy/Note.hx
new file mode 100644
index 0000000..d294b51
--- /dev/null
+++ b/source - Copy/Note.hx
@@ -0,0 +1,238 @@
+package;
+
+import flixel.addons.effects.FlxSkewedSprite;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.math.FlxMath;
+import flixel.util.FlxColor;
+#if polymod
+import polymod.format.ParseRules.TargetSignatureElement;
+#end
+import PlayState;
+
+using StringTools;
+
+class Note extends FlxSprite
+{
+ public var strumTime:Float = 0;
+
+ public var mustPress:Bool = false;
+ public var noteData:Int = 0;
+ public var canBeHit:Bool = false;
+ public var tooLate:Bool = false;
+ public var wasGoodHit:Bool = false;
+ public var prevNote:Note;
+ public var modifiedByLua:Bool = false;
+ public var sustainLength:Float = 0;
+ public var isSustainNote:Bool = false;
+
+ public var noteScore:Float = 1;
+
+ public static var swagWidth:Float = 160 * 0.7;
+ public static var PURP_NOTE:Int = 0;
+ public static var GREEN_NOTE:Int = 2;
+ public static var BLUE_NOTE:Int = 1;
+ public static var RED_NOTE:Int = 3;
+
+ public var rating:String = "shit";
+
+ public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false, ?inCharter:Bool = false)
+ {
+ super();
+
+ if (prevNote == null)
+ prevNote = this;
+
+ this.prevNote = prevNote;
+ isSustainNote = sustainNote;
+
+ x += 50;
+ // MAKE SURE ITS DEFINITELY OFF SCREEN?
+ y -= 2000;
+ if (inCharter)
+ this.strumTime = strumTime;
+ else
+ this.strumTime = Math.round(strumTime);
+
+ if (this.strumTime < 0 )
+ this.strumTime = 0;
+
+ this.noteData = noteData;
+
+ var daStage:String = PlayState.curStage;
+
+ //defaults if no noteStyle was found in chart
+ var noteTypeCheck:String = 'normal';
+
+ if (PlayState.SONG.noteStyle == null) {
+ switch(PlayState.storyWeek) {case 6: noteTypeCheck = 'pixel';}
+ } else {noteTypeCheck = PlayState.SONG.noteStyle;}
+
+ switch (noteTypeCheck)
+ {
+ case 'pixel':
+ loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels','week6'), true, 17, 17);
+
+ animation.add('greenScroll', [6]);
+ animation.add('redScroll', [7]);
+ animation.add('blueScroll', [5]);
+ animation.add('purpleScroll', [4]);
+
+ if (isSustainNote)
+ {
+ loadGraphic(Paths.image('weeb/pixelUI/arrowEnds','week6'), true, 7, 6);
+
+ animation.add('purpleholdend', [4]);
+ animation.add('greenholdend', [6]);
+ animation.add('redholdend', [7]);
+ animation.add('blueholdend', [5]);
+
+ animation.add('purplehold', [0]);
+ animation.add('greenhold', [2]);
+ animation.add('redhold', [3]);
+ animation.add('bluehold', [1]);
+ }
+
+ setGraphicSize(Std.int(width * PlayState.daPixelZoom));
+ updateHitbox();
+ default:
+ frames = Paths.getSparrowAtlas('NOTE_assets');
+
+ animation.addByPrefix('greenScroll', 'green0');
+ animation.addByPrefix('redScroll', 'red0');
+ animation.addByPrefix('blueScroll', 'blue0');
+ animation.addByPrefix('purpleScroll', 'purple0');
+
+ animation.addByPrefix('purpleholdend', 'pruple end hold');
+ animation.addByPrefix('greenholdend', 'green hold end');
+ animation.addByPrefix('redholdend', 'red hold end');
+ animation.addByPrefix('blueholdend', 'blue hold end');
+
+ animation.addByPrefix('purplehold', 'purple hold piece');
+ animation.addByPrefix('greenhold', 'green hold piece');
+ animation.addByPrefix('redhold', 'red hold piece');
+ animation.addByPrefix('bluehold', 'blue hold piece');
+
+ setGraphicSize(Std.int(width * 0.7));
+ updateHitbox();
+ antialiasing = true;
+ }
+
+ switch (noteData)
+ {
+ case 0:
+ x += swagWidth * 0;
+ animation.play('purpleScroll');
+ case 1:
+ x += swagWidth * 1;
+ animation.play('blueScroll');
+ case 2:
+ x += swagWidth * 2;
+ animation.play('greenScroll');
+ case 3:
+ x += swagWidth * 3;
+ animation.play('redScroll');
+ }
+
+ // trace(prevNote);
+
+ // we make sure its downscroll and its a SUSTAIN NOTE (aka a trail, not a note)
+ // and flip it so it doesn't look weird.
+ // THIS DOESN'T FUCKING FLIP THE NOTE, CONTRIBUTERS DON'T JUST COMMENT THIS OUT JESUS
+ if (FlxG.save.data.downscroll && sustainNote)
+ flipY = true;
+
+ if (isSustainNote && prevNote != null)
+ {
+ noteScore * 0.2;
+ alpha = 0.6;
+
+ x += width / 2;
+
+ switch (noteData)
+ {
+ case 2:
+ animation.play('greenholdend');
+ case 3:
+ animation.play('redholdend');
+ case 1:
+ animation.play('blueholdend');
+ case 0:
+ animation.play('purpleholdend');
+ }
+
+ updateHitbox();
+
+ x -= width / 2;
+
+ if (PlayState.curStage.startsWith('school'))
+ x += 30;
+
+ if (prevNote.isSustainNote)
+ {
+ switch (prevNote.noteData)
+ {
+ case 0:
+ prevNote.animation.play('purplehold');
+ case 1:
+ prevNote.animation.play('bluehold');
+ case 2:
+ prevNote.animation.play('greenhold');
+ case 3:
+ prevNote.animation.play('redhold');
+ }
+
+
+ if(FlxG.save.data.scrollSpeed != 1)
+ prevNote.scale.y *= Conductor.stepCrochet / 100 * 1.5 * FlxG.save.data.scrollSpeed;
+ else
+ prevNote.scale.y *= Conductor.stepCrochet / 100 * 1.5 * PlayState.SONG.speed;
+ prevNote.updateHitbox();
+ // prevNote.setGraphicSize();
+ }
+ }
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (mustPress)
+ {
+ // ass
+ if (isSustainNote)
+ {
+ if (strumTime > Conductor.songPosition - (Conductor.safeZoneOffset * 1.5)
+ && strumTime < Conductor.songPosition + (Conductor.safeZoneOffset * 0.5))
+ canBeHit = true;
+ else
+ canBeHit = false;
+ }
+ else
+ {
+ if (strumTime > Conductor.songPosition - Conductor.safeZoneOffset
+ && strumTime < Conductor.songPosition + Conductor.safeZoneOffset)
+ canBeHit = true;
+ else
+ canBeHit = false;
+ }
+
+ if (strumTime < Conductor.songPosition - Conductor.safeZoneOffset * Conductor.timeScale && !wasGoodHit)
+ tooLate = true;
+ }
+ else
+ {
+ canBeHit = false;
+
+ if (strumTime <= Conductor.songPosition)
+ wasGoodHit = true;
+ }
+
+ if (tooLate)
+ {
+ if (alpha > 0.3)
+ alpha = 0.3;
+ }
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/OFLSprite.hx b/source - Copy/OFLSprite.hx
new file mode 100644
index 0000000..abea3a0
--- /dev/null
+++ b/source - Copy/OFLSprite.hx
@@ -0,0 +1,39 @@
+import flixel.util.FlxColor;
+import openfl.display.Sprite;
+import flixel.FlxSprite;
+
+/**
+ * designed to draw a Open FL Sprite as a FlxSprite (to allow layering and auto sizing for haxe flixel cameras)
+ * Custom made for Kade Engine
+ */
+class OFLSprite extends FlxSprite
+{
+ public var flSprite:Sprite;
+
+ public function new(x,y,width,height,Sprite:Sprite)
+ {
+ super(x,y);
+
+ makeGraphic(width,height,FlxColor.TRANSPARENT);
+
+ flSprite = Sprite;
+
+ pixels.draw(flSprite);
+ }
+
+ private var _frameCount:Int = 0;
+
+ override function update(elapsed:Float)
+ {
+ if (_frameCount != 2)
+ {
+ pixels.draw(flSprite);
+ _frameCount++;
+ }
+ }
+
+ public function updateDisplay()
+ {
+ pixels.draw(flSprite);
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/Options.hx b/source - Copy/Options.hx
new file mode 100644
index 0000000..4535fdd
--- /dev/null
+++ b/source - Copy/Options.hx
@@ -0,0 +1,678 @@
+package;
+
+import lime.app.Application;
+import lime.system.DisplayMode;
+import flixel.util.FlxColor;
+import Controls.KeyboardScheme;
+import flixel.FlxG;
+import openfl.display.FPS;
+import openfl.Lib;
+
+class OptionCategory
+{
+ private var _options:Array = new Array ();
+ public final function getOptions():Array
+ {
+ return _options;
+ }
+
+ public final function addOption(opt:Option)
+ {
+ _options.push(opt);
+ }
+
+
+ public final function removeOption(opt:Option)
+ {
+ _options.remove(opt);
+ }
+
+ private var _name:String = "New Category";
+ public final function getName() {
+ return _name;
+ }
+
+ public function new (catName:String, options:Array )
+ {
+ _name = catName;
+ _options = options;
+ }
+}
+
+class Option
+{
+ public function new()
+ {
+ display = updateDisplay();
+ }
+ private var description:String = "";
+ private var display:String;
+ private var acceptValues:Bool = false;
+ public final function getDisplay():String
+ {
+ return display;
+ }
+
+ public final function getAccept():Bool
+ {
+ return acceptValues;
+ }
+
+ public final function getDescription():String
+ {
+ return description;
+ }
+
+ public function getValue():String { return throw "stub!"; };
+
+ // Returns whether the label is to be updated.
+ public function press():Bool { return throw "stub!"; }
+ private function updateDisplay():String { return throw "stub!"; }
+ public function left():Bool { return throw "stub!"; }
+ public function right():Bool { return throw "stub!"; }
+}
+
+
+
+class DFJKOption extends Option
+{
+ private var controls:Controls;
+
+ public function new(controls:Controls)
+ {
+ super();
+ this.controls = controls;
+ }
+
+ public override function press():Bool
+ {
+ OptionsMenu.instance.openSubState(new KeyBindMenu());
+ return false;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Key Bindings";
+ }
+}
+
+class CpuStrums extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.cpuStrums = !FlxG.save.data.cpuStrums;
+
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return FlxG.save.data.cpuStrums ? "Light CPU Strums" : "CPU Strums stay static";
+ }
+
+}
+
+class DownscrollOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.downscroll = !FlxG.save.data.downscroll;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return FlxG.save.data.downscroll ? "Downscroll" : "Upscroll";
+ }
+}
+
+class GhostTapOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.ghost = !FlxG.save.data.ghost;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return FlxG.save.data.ghost ? "Ghost Tapping" : "No Ghost Tapping";
+ }
+}
+
+class AccuracyOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+ public override function press():Bool
+ {
+ FlxG.save.data.accuracyDisplay = !FlxG.save.data.accuracyDisplay;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Accuracy " + (!FlxG.save.data.accuracyDisplay ? "off" : "on");
+ }
+}
+
+class SongPositionOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+ public override function press():Bool
+ {
+ FlxG.save.data.songPosition = !FlxG.save.data.songPosition;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Song Position " + (!FlxG.save.data.songPosition ? "off" : "on");
+ }
+}
+
+class DistractionsAndEffectsOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+ public override function press():Bool
+ {
+ FlxG.save.data.distractions = !FlxG.save.data.distractions;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Distractions " + (!FlxG.save.data.distractions ? "off" : "on");
+ }
+}
+
+class ResetButtonOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+ public override function press():Bool
+ {
+ FlxG.save.data.resetButton = !FlxG.save.data.resetButton;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Reset Button " + (!FlxG.save.data.resetButton ? "off" : "on");
+ }
+}
+
+class FlashingLightsOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+ public override function press():Bool
+ {
+ FlxG.save.data.flashing = !FlxG.save.data.flashing;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Flashing Lights " + (!FlxG.save.data.flashing ? "off" : "on");
+ }
+}
+
+class ShowInput extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+ public override function press():Bool
+ {
+ FlxG.save.data.inputShow = !FlxG.save.data.inputShow;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return (FlxG.save.data.inputShow ? "Extended Score Info" : "Minimalized Info");
+ }
+}
+
+
+class Judgement extends Option
+{
+
+
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ acceptValues = true;
+ }
+
+ public override function press():Bool
+ {
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Safe Frames";
+ }
+
+ override function left():Bool {
+
+ if (Conductor.safeFrames == 1)
+ return false;
+
+ Conductor.safeFrames -= 1;
+ FlxG.save.data.frames = Conductor.safeFrames;
+
+ Conductor.recalculateTimings();
+ return true;
+ }
+
+ override function getValue():String {
+ return "Safe Frames: " + Conductor.safeFrames +
+ " - SIK: " + HelperFunctions.truncateFloat(22 * Conductor.timeScale, 0) +
+ "ms GD: " + HelperFunctions.truncateFloat(45 * Conductor.timeScale, 0) +
+ "ms BD: " + HelperFunctions.truncateFloat(135 * Conductor.timeScale, 0) +
+ "ms SHT: " + HelperFunctions.truncateFloat(155 * Conductor.timeScale, 0) +
+ "ms TOTAL: " + HelperFunctions.truncateFloat(Conductor.safeZoneOffset,0) + "ms";
+ }
+
+ override function right():Bool {
+
+ if (Conductor.safeFrames == 20)
+ return false;
+
+ Conductor.safeFrames += 1;
+ FlxG.save.data.frames = Conductor.safeFrames;
+
+ Conductor.recalculateTimings();
+ return true;
+ }
+}
+
+class FPSOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.fps = !FlxG.save.data.fps;
+ (cast (Lib.current.getChildAt(0), Main)).toggleFPS(FlxG.save.data.fps);
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "FPS Counter " + (!FlxG.save.data.fps ? "off" : "on");
+ }
+}
+
+class ScoreScreen extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.scoreScreen = !FlxG.save.data.scoreScreen;
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return (FlxG.save.data.scoreScreen ? "Show Score Screen" : "No Score Screen");
+ }
+}
+
+
+
+
+class FPSCapOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ acceptValues = true;
+ }
+
+ public override function press():Bool
+ {
+ return false;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "FPS Cap";
+ }
+
+ override function right():Bool {
+ if (FlxG.save.data.fpsCap >= 290)
+ {
+ FlxG.save.data.fpsCap = 290;
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290);
+ }
+ else
+ FlxG.save.data.fpsCap = FlxG.save.data.fpsCap + 10;
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(FlxG.save.data.fpsCap);
+
+ return true;
+ }
+
+ override function left():Bool {
+ if (FlxG.save.data.fpsCap > 290)
+ FlxG.save.data.fpsCap = 290;
+ else if (FlxG.save.data.fpsCap < 60)
+ FlxG.save.data.fpsCap = Application.current.window.displayMode.refreshRate;
+ else
+ FlxG.save.data.fpsCap = FlxG.save.data.fpsCap - 10;
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(FlxG.save.data.fpsCap);
+ return true;
+ }
+
+ override function getValue():String
+ {
+ return "Current FPS Cap: " + FlxG.save.data.fpsCap +
+ (FlxG.save.data.fpsCap == Application.current.window.displayMode.refreshRate ? "Hz (Refresh Rate)" : "");
+ }
+}
+
+
+class ScrollSpeedOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ acceptValues = true;
+ }
+
+ public override function press():Bool
+ {
+ return false;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Scroll Speed";
+ }
+
+ override function right():Bool {
+ FlxG.save.data.scrollSpeed += 0.1;
+
+ if (FlxG.save.data.scrollSpeed < 1)
+ FlxG.save.data.scrollSpeed = 1;
+
+ if (FlxG.save.data.scrollSpeed > 4)
+ FlxG.save.data.scrollSpeed = 4;
+ return true;
+ }
+
+ override function getValue():String {
+ return "Current Scroll Speed: " + HelperFunctions.truncateFloat(FlxG.save.data.scrollSpeed,1);
+ }
+
+ override function left():Bool {
+ FlxG.save.data.scrollSpeed -= 0.1;
+
+ if (FlxG.save.data.scrollSpeed < 1)
+ FlxG.save.data.scrollSpeed = 1;
+
+ if (FlxG.save.data.scrollSpeed > 4)
+ FlxG.save.data.scrollSpeed = 4;
+
+ return true;
+ }
+}
+
+
+class RainbowFPSOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.fpsRain = !FlxG.save.data.fpsRain;
+ (cast (Lib.current.getChildAt(0), Main)).changeFPSColor(FlxColor.WHITE);
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "FPS Rainbow " + (!FlxG.save.data.fpsRain ? "off" : "on");
+ }
+}
+
+class NPSDisplayOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.npsDisplay = !FlxG.save.data.npsDisplay;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "NPS Display " + (!FlxG.save.data.npsDisplay ? "off" : "on");
+ }
+}
+
+class ReplayOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ trace("switch");
+ FlxG.switchState(new LoadReplayState());
+ return false;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Load replays";
+ }
+}
+
+class AccuracyDOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.accuracyMod = FlxG.save.data.accuracyMod == 1 ? 0 : 1;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Accuracy Mode: " + (FlxG.save.data.accuracyMod == 0 ? "Accurate" : "Complex");
+ }
+}
+
+class CustomizeGameplay extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ trace("switch");
+ FlxG.switchState(new GameplayCustomizeState());
+ return false;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Customize Gameplay";
+ }
+}
+
+class WatermarkOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ Main.watermarks = !Main.watermarks;
+ FlxG.save.data.watermark = Main.watermarks;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Watermarks " + (Main.watermarks ? "on" : "off");
+ }
+}
+
+class OffsetMenu extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ trace("switch");
+ var poop:String = Highscore.formatSong("Tutorial", 1);
+
+ PlayState.SONG = Song.loadFromJson(poop, "Tutorial");
+ PlayState.isStoryMode = false;
+ PlayState.storyDifficulty = 0;
+ PlayState.storyWeek = 0;
+ PlayState.offsetTesting = true;
+ trace('CUR WEEK' + PlayState.storyWeek);
+ LoadingState.loadAndSwitchState(new PlayState());
+ return false;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Time your offset";
+ }
+}
+class BotPlay extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+
+ public override function press():Bool
+ {
+ FlxG.save.data.botplay = !FlxG.save.data.botplay;
+ trace('BotPlay : ' + FlxG.save.data.botplay);
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ return "BotPlay " + (FlxG.save.data.botplay ? "on" : "off");
+}
+
+class CamZoomOption extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+ public override function press():Bool
+ {
+ FlxG.save.data.camzoom = !FlxG.save.data.camzoom;
+ display = updateDisplay();
+ return true;
+ }
+
+ private override function updateDisplay():String
+ {
+ return "Camera Zoom " + (!FlxG.save.data.camzoom ? "off" : "on");
+ }
+}
diff --git a/source - Copy/OptionsMenu.hx b/source - Copy/OptionsMenu.hx
new file mode 100644
index 0000000..a79ade3
--- /dev/null
+++ b/source - Copy/OptionsMenu.hx
@@ -0,0 +1,294 @@
+package;
+
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import openfl.Lib;
+import Options;
+import Controls.Control;
+import flash.text.TextField;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.display.FlxGridOverlay;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.input.keyboard.FlxKey;
+import flixel.math.FlxMath;
+import flixel.text.FlxText;
+import flixel.util.FlxColor;
+import lime.utils.Assets;
+
+class OptionsMenu extends MusicBeatState
+{
+ public static var instance:OptionsMenu;
+
+ var selector:FlxText;
+ var curSelected:Int = 0;
+
+ var options:Array = [
+ new OptionCategory("Gameplay", [
+ new DFJKOption(controls),
+ new DownscrollOption("Change the layout of the strumline."),
+ new GhostTapOption("Ghost Tapping is when you tap a direction and it doesn't give you a miss."),
+ new Judgement("Customize your Hit Timings (LEFT or RIGHT)"),
+ #if desktop
+ new FPSCapOption("Cap your FPS"),
+ #end
+ new ScrollSpeedOption("Change your scroll speed (1 = Chart dependent)"),
+ new AccuracyDOption("Change how accuracy is calculated. (Accurate = Simple, Complex = Milisecond Based)"),
+ new ResetButtonOption("Toggle pressing R to gameover."),
+ // new OffsetMenu("Get a note offset based off of your inputs!"),
+ new CustomizeGameplay("Drag'n'Drop Gameplay Modules around to your preference")
+ ]),
+ new OptionCategory("Appearance", [
+ new DistractionsAndEffectsOption("Toggle stage distractions that can hinder your gameplay."),
+ new CamZoomOption("Toggle the camera zoom in-game."),
+ #if desktop
+ new RainbowFPSOption("Make the FPS Counter Rainbow"),
+ new AccuracyOption("Display accuracy information."),
+ new NPSDisplayOption("Shows your current Notes Per Second."),
+ new SongPositionOption("Show the songs current position (as a bar)"),
+ new CpuStrums("CPU's strumline lights up when a note hits it."),
+ #end
+ ]),
+
+ new OptionCategory("Misc", [
+ #if desktop
+ new FPSOption("Toggle the FPS Counter"),
+ new ReplayOption("View replays"),
+ #end
+ new FlashingLightsOption("Toggle flashing lights that can cause epileptic seizures and strain."),
+ new WatermarkOption("Enable and disable all watermarks from the engine."),
+ new BotPlay("Showcase your charts and mods with autoplay."),
+ new ScoreScreen("Show the score screen after the end of a song"),
+ new ShowInput("Display every single input in the score screen.")
+ ])
+
+ ];
+
+ public var acceptInput:Bool = true;
+
+ private var currentDescription:String = "";
+ private var grpControls:FlxTypedGroup;
+ public static var versionShit:FlxText;
+
+ var currentSelectedCat:OptionCategory;
+ var blackBorder:FlxSprite;
+ override function create()
+ {
+ instance = this;
+ var menuBG:FlxSprite = new FlxSprite().loadGraphic(Paths.image("menuDesat"));
+
+ menuBG.color = 0xFFea71fd;
+ menuBG.setGraphicSize(Std.int(menuBG.width * 1.1));
+ menuBG.updateHitbox();
+ menuBG.screenCenter();
+ menuBG.antialiasing = true;
+ add(menuBG);
+
+ grpControls = new FlxTypedGroup();
+ add(grpControls);
+
+ for (i in 0...options.length)
+ {
+ var controlLabel:Alphabet = new Alphabet(0, (70 * i) + 30, options[i].getName(), true, false, true);
+ controlLabel.isMenuItem = true;
+ controlLabel.targetY = i;
+ grpControls.add(controlLabel);
+ // DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
+ }
+
+ currentDescription = "none";
+
+ versionShit = new FlxText(5, FlxG.height + 40, 0, "Offset (Left, Right, Shift for slow): " + HelperFunctions.truncateFloat(FlxG.save.data.offset,2) + " - Description - " + currentDescription, 12);
+ versionShit.scrollFactor.set();
+ versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+
+ blackBorder = new FlxSprite(-30,FlxG.height + 40).makeGraphic((Std.int(versionShit.width + 900)),Std.int(versionShit.height + 600),FlxColor.BLACK);
+ blackBorder.alpha = 0.5;
+
+ add(blackBorder);
+
+ add(versionShit);
+
+ FlxTween.tween(versionShit,{y: FlxG.height - 18},2,{ease: FlxEase.elasticInOut});
+ FlxTween.tween(blackBorder,{y: FlxG.height - 18},2, {ease: FlxEase.elasticInOut});
+
+ super.create();
+ }
+
+ var isCat:Bool = false;
+
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (acceptInput)
+ {
+ if (controls.BACK && !isCat)
+ FlxG.switchState(new MainMenuState());
+ else if (controls.BACK)
+ {
+ isCat = false;
+ grpControls.clear();
+ for (i in 0...options.length)
+ {
+ var controlLabel:Alphabet = new Alphabet(0, (70 * i) + 30, options[i].getName(), true, false);
+ controlLabel.isMenuItem = true;
+ controlLabel.targetY = i;
+ grpControls.add(controlLabel);
+ // DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
+ }
+
+ curSelected = 0;
+
+ changeSelection(curSelected);
+ }
+ if (controls.UP_P)
+ changeSelection(-1);
+ if (controls.DOWN_P)
+ changeSelection(1);
+
+ if (isCat)
+ {
+ if (currentSelectedCat.getOptions()[curSelected].getAccept())
+ {
+ if (FlxG.keys.pressed.SHIFT)
+ {
+ if (FlxG.keys.pressed.RIGHT)
+ currentSelectedCat.getOptions()[curSelected].right();
+ if (FlxG.keys.pressed.LEFT)
+ currentSelectedCat.getOptions()[curSelected].left();
+ }
+ else
+ {
+ if (FlxG.keys.justPressed.RIGHT)
+ currentSelectedCat.getOptions()[curSelected].right();
+ if (FlxG.keys.justPressed.LEFT)
+ currentSelectedCat.getOptions()[curSelected].left();
+ }
+ }
+ else
+ {
+ if (FlxG.keys.pressed.SHIFT)
+ {
+ if (FlxG.keys.justPressed.RIGHT)
+ FlxG.save.data.offset += 0.1;
+ else if (FlxG.keys.justPressed.LEFT)
+ FlxG.save.data.offset -= 0.1;
+ }
+ else if (FlxG.keys.pressed.RIGHT)
+ FlxG.save.data.offset += 0.1;
+ else if (FlxG.keys.pressed.LEFT)
+ FlxG.save.data.offset -= 0.1;
+
+ versionShit.text = "Offset (Left, Right, Shift for slow): " + HelperFunctions.truncateFloat(FlxG.save.data.offset,2) + " - Description - " + currentDescription;
+ }
+ if (currentSelectedCat.getOptions()[curSelected].getAccept())
+ versionShit.text = currentSelectedCat.getOptions()[curSelected].getValue() + " - Description - " + currentDescription;
+ else
+ versionShit.text = "Offset (Left, Right, Shift for slow): " + HelperFunctions.truncateFloat(FlxG.save.data.offset,2) + " - Description - " + currentDescription;
+ }
+ else
+ {
+ if (FlxG.keys.pressed.SHIFT)
+ {
+ if (FlxG.keys.justPressed.RIGHT)
+ FlxG.save.data.offset += 0.1;
+ else if (FlxG.keys.justPressed.LEFT)
+ FlxG.save.data.offset -= 0.1;
+ }
+ else if (FlxG.keys.pressed.RIGHT)
+ FlxG.save.data.offset += 0.1;
+ else if (FlxG.keys.pressed.LEFT)
+ FlxG.save.data.offset -= 0.1;
+
+ versionShit.text = "Offset (Left, Right, Shift for slow): " + HelperFunctions.truncateFloat(FlxG.save.data.offset,2) + " - Description - " + currentDescription;
+ }
+
+
+ if (controls.RESET)
+ FlxG.save.data.offset = 0;
+
+ if (controls.ACCEPT)
+ {
+ if (isCat)
+ {
+ if (currentSelectedCat.getOptions()[curSelected].press()) {
+ grpControls.remove(grpControls.members[curSelected]);
+ var ctrl:Alphabet = new Alphabet(0, (70 * curSelected) + 30, currentSelectedCat.getOptions()[curSelected].getDisplay(), true, false);
+ ctrl.isMenuItem = true;
+ grpControls.add(ctrl);
+ }
+ }
+ else
+ {
+ currentSelectedCat = options[curSelected];
+ isCat = true;
+ grpControls.clear();
+ for (i in 0...currentSelectedCat.getOptions().length)
+ {
+ var controlLabel:Alphabet = new Alphabet(0, (70 * i) + 30, currentSelectedCat.getOptions()[i].getDisplay(), true, false);
+ controlLabel.isMenuItem = true;
+ controlLabel.targetY = i;
+ grpControls.add(controlLabel);
+ // DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
+ }
+ curSelected = 0;
+ }
+
+ changeSelection(curSelected);
+ }
+ }
+ FlxG.save.flush();
+ }
+
+ var isSettingControl:Bool = false;
+
+ function changeSelection(change:Int = 0)
+ {
+ #if !switch
+ // NGio.logEvent("Fresh");
+ #end
+
+ FlxG.sound.play(Paths.sound("scrollMenu"), 0.4);
+
+ curSelected += change;
+
+ if (curSelected < 0)
+ curSelected = grpControls.length - 1;
+ if (curSelected >= grpControls.length)
+ curSelected = 0;
+
+ if (isCat)
+ currentDescription = currentSelectedCat.getOptions()[curSelected].getDescription();
+ else
+ currentDescription = "Please select a category";
+ if (isCat)
+ {
+ if (currentSelectedCat.getOptions()[curSelected].getAccept())
+ versionShit.text = currentSelectedCat.getOptions()[curSelected].getValue() + " - Description - " + currentDescription;
+ else
+ versionShit.text = "Offset (Left, Right, Shift for slow): " + HelperFunctions.truncateFloat(FlxG.save.data.offset,2) + " - Description - " + currentDescription;
+ }
+ else
+ versionShit.text = "Offset (Left, Right, Shift for slow): " + HelperFunctions.truncateFloat(FlxG.save.data.offset,2) + " - Description - " + currentDescription;
+ // selector.y = (70 * curSelected) + 30;
+
+ var bullShit:Int = 0;
+
+ for (item in grpControls.members)
+ {
+ item.targetY = bullShit - curSelected;
+ bullShit++;
+
+ item.alpha = 0.6;
+ // item.setGraphicSize(Std.int(item.width * 0.8));
+
+ if (item.targetY == 0)
+ {
+ item.alpha = 1;
+ // item.setGraphicSize(Std.int(item.width));
+ }
+ }
+ }
+}
diff --git a/source - Copy/OptionsSubState.hx b/source - Copy/OptionsSubState.hx
new file mode 100644
index 0000000..2b63e0c
--- /dev/null
+++ b/source - Copy/OptionsSubState.hx
@@ -0,0 +1,70 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.text.FlxText;
+import flixel.util.FlxColor;
+
+class OptionsSubState extends MusicBeatSubstate
+{
+ var textMenuItems:Array = ['Master Volume', 'Sound Volume', 'Controls'];
+
+ var selector:FlxSprite;
+ var curSelected:Int = 0;
+
+ var grpOptionsTexts:FlxTypedGroup;
+
+ public function new()
+ {
+ super();
+
+ grpOptionsTexts = new FlxTypedGroup();
+ add(grpOptionsTexts);
+
+ selector = new FlxSprite().makeGraphic(5, 5, FlxColor.RED);
+ add(selector);
+
+ for (i in 0...textMenuItems.length)
+ {
+ var optionText:FlxText = new FlxText(20, 20 + (i * 50), 0, textMenuItems[i], 32);
+ optionText.ID = i;
+ grpOptionsTexts.add(optionText);
+ }
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (controls.UP_P)
+ curSelected -= 1;
+
+ if (controls.DOWN_P)
+ curSelected += 1;
+
+ if (curSelected < 0)
+ curSelected = textMenuItems.length - 1;
+
+ if (curSelected >= textMenuItems.length)
+ curSelected = 0;
+
+ grpOptionsTexts.forEach(function(txt:FlxText)
+ {
+ txt.color = FlxColor.WHITE;
+
+ if (txt.ID == curSelected)
+ txt.color = FlxColor.YELLOW;
+ });
+
+ if (controls.ACCEPT)
+ {
+ switch (textMenuItems[curSelected])
+ {
+ case "Controls":
+ FlxG.state.closeSubState();
+ FlxG.state.openSubState(new ControlsSubState());
+ }
+ }
+ }
+}
diff --git a/source - Copy/OutdatedSubState.hx b/source - Copy/OutdatedSubState.hx
new file mode 100644
index 0000000..a25c9fe
--- /dev/null
+++ b/source - Copy/OutdatedSubState.hx
@@ -0,0 +1,98 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.FlxSubState;
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
+import lime.app.Application;
+
+class OutdatedSubState extends MusicBeatState
+{
+ public static var leftState:Bool = false;
+
+ public static var needVer:String = "IDFK LOL";
+ public static var currChanges:String = "dk";
+
+ private var bgColors:Array = [
+ '#314d7f',
+ '#4e7093',
+ '#70526e',
+ '#594465'
+ ];
+ private var colorRotation:Int = 1;
+
+ override function create()
+ {
+ super.create();
+ var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('week54prototype', 'shared'));
+ bg.scale.x *= 1.55;
+ bg.scale.y *= 1.55;
+ bg.screenCenter();
+ add(bg);
+
+ var kadeLogo:FlxSprite = new FlxSprite(FlxG.width, 0).loadGraphic(Paths.image('KadeEngineLogo'));
+ kadeLogo.scale.y = 0.3;
+ kadeLogo.scale.x = 0.3;
+ kadeLogo.x -= kadeLogo.frameHeight;
+ kadeLogo.y -= 180;
+ kadeLogo.alpha = 0.8;
+ add(kadeLogo);
+
+ var txt:FlxText = new FlxText(0, 0, FlxG.width,
+ "Your Kade Engine is outdated!\nYou are on "
+ + MainMenuState.kadeEngineVer
+ + "\nwhile the most recent version is " + needVer + "."
+ + "\n\nWhat's new:\n\n"
+ + currChanges
+ + "\n& more changes and bugfixes in the full changelog"
+ + "\n\nPress Space to view the full changelog and update\nor ESCAPE to ignore this",
+ 32);
+
+ txt.setFormat("VCR OSD Mono", 32, FlxColor.fromRGB(200, 200, 200), CENTER);
+ txt.borderColor = FlxColor.BLACK;
+ txt.borderSize = 3;
+ txt.borderStyle = FlxTextBorderStyle.OUTLINE;
+ txt.screenCenter();
+ add(txt);
+
+ FlxTween.color(bg, 2, bg.color, FlxColor.fromString(bgColors[colorRotation]));
+ FlxTween.angle(kadeLogo, kadeLogo.angle, -10, 2, {ease: FlxEase.quartInOut});
+
+ new FlxTimer().start(2, function(tmr:FlxTimer)
+ {
+ FlxTween.color(bg, 2, bg.color, FlxColor.fromString(bgColors[colorRotation]));
+ if(colorRotation < (bgColors.length - 1)) colorRotation++;
+ else colorRotation = 0;
+ }, 0);
+
+ new FlxTimer().start(2, function(tmr:FlxTimer)
+ {
+ if(kadeLogo.angle == -10) FlxTween.angle(kadeLogo, kadeLogo.angle, 10, 2, {ease: FlxEase.quartInOut});
+ else FlxTween.angle(kadeLogo, kadeLogo.angle, -10, 2, {ease: FlxEase.quartInOut});
+ }, 0);
+
+ new FlxTimer().start(0.8, function(tmr:FlxTimer)
+ {
+ if(kadeLogo.alpha == 0.8) FlxTween.tween(kadeLogo, {alpha: 1}, 0.8, {ease: FlxEase.quartInOut});
+ else FlxTween.tween(kadeLogo, {alpha: 0.8}, 0.8, {ease: FlxEase.quartInOut});
+ }, 0);
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (controls.ACCEPT)
+ {
+ fancyOpenURL("https://kadedev.github.io/Kade-Engine/changelogs/changelog-" + needVer);
+ }
+ if (controls.BACK)
+ {
+ leftState = true;
+ FlxG.switchState(new MainMenuState());
+ }
+ super.update(elapsed);
+ }
+}
diff --git a/source - Copy/OverlayShader.hx b/source - Copy/OverlayShader.hx
new file mode 100644
index 0000000..4de9a55
--- /dev/null
+++ b/source - Copy/OverlayShader.hx
@@ -0,0 +1,33 @@
+package;
+
+import flixel.system.FlxAssets.FlxShader;
+
+class OverlayShader extends FlxShader
+{
+ @:glFragmentSource('
+ #pragma header
+ uniform vec4 uBlendColor;
+
+ vec3 blendLighten(base:Vec3, blend:Vec3) : Vec3 {
+ return mix(
+ 1.0 - 2.0 * (1.0 - base) * (1.0 - blend),
+ 2.0 * base * blend,
+ step( base, vec3(0.5) )
+ );
+ }
+
+ vec4 blendLighten(vec4 base, vec4 blend, float opacity)
+ {
+ return (blendLighten(base, blend) * opacity + base * (1.0 - opacity));
+ }
+
+ void main()
+ {
+ vec4 base = texture2D(bitmap, openfl_TextureCoordv);
+ gl_FragColor = blendLighten(base, uBlendColor, uBlendColor.a);
+ }')
+ public function new()
+ {
+ super();
+ }
+}
diff --git a/source - Copy/Paths.hx b/source - Copy/Paths.hx
new file mode 100644
index 0000000..075adbd
--- /dev/null
+++ b/source - Copy/Paths.hx
@@ -0,0 +1,137 @@
+package;
+
+import flixel.FlxG;
+import flixel.graphics.frames.FlxAtlasFrames;
+import openfl.utils.AssetType;
+import openfl.utils.Assets as OpenFlAssets;
+
+class Paths
+{
+ inline public static var SOUND_EXT = #if web "mp3" #else "ogg" #end;
+
+ static var currentLevel:String;
+
+ static public function setCurrentLevel(name:String)
+ {
+ currentLevel = name.toLowerCase();
+ }
+
+ static function getPath(file:String, type:AssetType, library:Null)
+ {
+ if (library != null)
+ return getLibraryPath(file, library);
+
+ if (currentLevel != null)
+ {
+ var levelPath = getLibraryPathForce(file, currentLevel);
+ if (OpenFlAssets.exists(levelPath, type))
+ return levelPath;
+
+ levelPath = getLibraryPathForce(file, "shared");
+ if (OpenFlAssets.exists(levelPath, type))
+ return levelPath;
+ }
+
+ return getPreloadPath(file);
+ }
+
+ static public function getLibraryPath(file:String, library = "preload")
+ {
+ return if (library == "preload" || library == "default") getPreloadPath(file); else getLibraryPathForce(file, library);
+ }
+
+ inline static function getLibraryPathForce(file:String, library:String)
+ {
+ return '$library:assets/$library/$file';
+ }
+
+ inline static function getPreloadPath(file:String)
+ {
+ return 'assets/$file';
+ }
+
+ inline static public function file(file:String, type:AssetType = TEXT, ?library:String)
+ {
+ return getPath(file, type, library);
+ }
+
+ inline static public function lua(key:String,?library:String)
+ {
+ return getPath('data/$key.lua', TEXT, library);
+ }
+
+ inline static public function luaImage(key:String, ?library:String)
+ {
+ return getPath('data/$key.png', IMAGE, library);
+ }
+
+ inline static public function txt(key:String, ?library:String)
+ {
+ return getPath('data/$key.txt', TEXT, library);
+ }
+
+ inline static public function xml(key:String, ?library:String)
+ {
+ return getPath('data/$key.xml', TEXT, library);
+ }
+
+ inline static public function json(key:String, ?library:String)
+ {
+ return getPath('data/$key.json', TEXT, library);
+ }
+
+ static public function sound(key:String, ?library:String)
+ {
+ return getPath('sounds/$key.$SOUND_EXT', SOUND, library);
+ }
+
+ inline static public function soundRandom(key:String, min:Int, max:Int, ?library:String)
+ {
+ return sound(key + FlxG.random.int(min, max), library);
+ }
+
+ inline static public function music(key:String, ?library:String)
+ {
+ return getPath('music/$key.$SOUND_EXT', MUSIC, library);
+ }
+
+ inline static public function voices(song:String)
+ {
+ var songLowercase = StringTools.replace(song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+ return 'songs:assets/songs/${songLowercase}/Voices.$SOUND_EXT';
+ }
+
+ inline static public function inst(song:String)
+ {
+ var songLowercase = StringTools.replace(song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+ return 'songs:assets/songs/${songLowercase}/Inst.$SOUND_EXT';
+ }
+
+ inline static public function image(key:String, ?library:String)
+ {
+ return getPath('images/$key.png', IMAGE, library);
+ }
+
+ inline static public function font(key:String)
+ {
+ return 'assets/fonts/$key';
+ }
+
+ inline static public function getSparrowAtlas(key:String, ?library:String)
+ {
+ return FlxAtlasFrames.fromSparrow(image(key, library), file('images/$key.xml', library));
+ }
+
+ inline static public function getPackerAtlas(key:String, ?library:String)
+ {
+ return FlxAtlasFrames.fromSpriteSheetPacker(image(key, library), file('images/$key.txt', library));
+ }
+}
diff --git a/source - Copy/PauseSubState.hx b/source - Copy/PauseSubState.hx
new file mode 100644
index 0000000..1eddcc0
--- /dev/null
+++ b/source - Copy/PauseSubState.hx
@@ -0,0 +1,275 @@
+package;
+
+import openfl.Lib;
+#if windows
+import llua.Lua;
+#end
+import Controls.Control;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.FlxSubState;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.input.keyboard.FlxKey;
+import flixel.system.FlxSound;
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+
+class PauseSubState extends MusicBeatSubstate
+{
+ var grpMenuShit:FlxTypedGroup;
+
+ var menuItems:Array = ['Resume', 'Restart Song', 'Exit to menu'];
+ var curSelected:Int = 0;
+
+ var pauseMusic:FlxSound;
+ var perSongOffset:FlxText;
+
+ var offsetChanged:Bool = false;
+
+ public function new(x:Float, y:Float)
+ {
+ super();
+
+ if (PlayState.instance.useVideo)
+ {
+ menuItems.remove("Resume");
+ if (GlobalVideo.get().playing)
+ GlobalVideo.get().pause();
+ }
+
+ pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true);
+ pauseMusic.volume = 0;
+ pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2)));
+
+ FlxG.sound.list.add(pauseMusic);
+
+ var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
+ bg.alpha = 0;
+ bg.scrollFactor.set();
+ add(bg);
+
+ var levelInfo:FlxText = new FlxText(20, 15, 0, "", 32);
+ levelInfo.text += PlayState.SONG.song;
+ levelInfo.scrollFactor.set();
+ levelInfo.setFormat(Paths.font("vcr.ttf"), 32);
+ levelInfo.updateHitbox();
+ add(levelInfo);
+
+ var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, "", 32);
+ levelDifficulty.text += CoolUtil.difficultyFromInt(PlayState.storyDifficulty).toUpperCase();
+ levelDifficulty.scrollFactor.set();
+ levelDifficulty.setFormat(Paths.font('vcr.ttf'), 32);
+ levelDifficulty.updateHitbox();
+ add(levelDifficulty);
+
+ levelDifficulty.alpha = 0;
+ levelInfo.alpha = 0;
+
+ levelInfo.x = FlxG.width - (levelInfo.width + 20);
+ levelDifficulty.x = FlxG.width - (levelDifficulty.width + 20);
+
+ FlxTween.tween(bg, {alpha: 0.6}, 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});
+
+ grpMenuShit = new FlxTypedGroup();
+ add(grpMenuShit);
+ perSongOffset = new FlxText(5, FlxG.height - 18, 0, "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.', 12);
+ perSongOffset.scrollFactor.set();
+ perSongOffset.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
+
+ #if cpp
+ add(perSongOffset);
+ #end
+
+ for (i in 0...menuItems.length)
+ {
+ var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false);
+ songText.isMenuItem = true;
+ songText.targetY = i;
+ grpMenuShit.add(songText);
+ }
+
+ changeSelection();
+
+ cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
+ }
+
+ override function update(elapsed:Float)
+ {
+ if (pauseMusic.volume < 0.5)
+ pauseMusic.volume += 0.01 * elapsed;
+
+ super.update(elapsed);
+
+ if (PlayState.instance.useVideo)
+ menuItems.remove('Resume');
+
+ var upP = controls.UP_P;
+ var downP = controls.DOWN_P;
+ var leftP = controls.LEFT_P;
+ var rightP = controls.RIGHT_P;
+ var accepted = controls.ACCEPT;
+ var oldOffset:Float = 0;
+
+ // pre lowercasing the song name (update)
+ var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+ var songPath = 'assets/data/' + songLowercase + '/';
+
+ if (upP)
+ {
+ changeSelection(-1);
+
+ }else if (downP)
+ {
+ changeSelection(1);
+ }
+
+ #if cpp
+ else if (leftP)
+ {
+ oldOffset = PlayState.songOffset;
+ PlayState.songOffset -= 1;
+ sys.FileSystem.rename(songPath + oldOffset + '.offset', songPath + PlayState.songOffset + '.offset');
+ perSongOffset.text = "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.';
+
+ // Prevent loop from happening every single time the offset changes
+ if(!offsetChanged)
+ {
+ grpMenuShit.clear();
+
+ menuItems = ['Restart Song', 'Exit to menu'];
+
+ for (i in 0...menuItems.length)
+ {
+ var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false);
+ songText.isMenuItem = true;
+ songText.targetY = i;
+ grpMenuShit.add(songText);
+ }
+
+ changeSelection();
+
+ cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
+ offsetChanged = true;
+ }
+ }else if (rightP)
+ {
+ oldOffset = PlayState.songOffset;
+ PlayState.songOffset += 1;
+ sys.FileSystem.rename(songPath + oldOffset + '.offset', songPath + PlayState.songOffset + '.offset');
+ perSongOffset.text = "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.';
+ if(!offsetChanged)
+ {
+ grpMenuShit.clear();
+
+ menuItems = ['Restart Song', 'Exit to menu'];
+
+ for (i in 0...menuItems.length)
+ {
+ var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false);
+ songText.isMenuItem = true;
+ songText.targetY = i;
+ grpMenuShit.add(songText);
+ }
+
+ changeSelection();
+
+ cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
+ offsetChanged = true;
+ }
+ }
+ #end
+
+ if (accepted)
+ {
+ var daSelected:String = menuItems[curSelected];
+
+ switch (daSelected)
+ {
+ case "Resume":
+ close();
+ case "Restart Song":
+ if (PlayState.instance.useVideo)
+ {
+ GlobalVideo.get().stop();
+ PlayState.instance.remove(PlayState.instance.videoSprite);
+ PlayState.instance.removedVideo = true;
+ }
+ FlxG.resetState();
+ case "Exit to menu":
+ if (PlayState.instance.useVideo)
+ {
+ GlobalVideo.get().stop();
+ PlayState.instance.remove(PlayState.instance.videoSprite);
+ PlayState.instance.removedVideo = true;
+ }
+ if(PlayState.loadRep)
+ {
+ FlxG.save.data.botplay = false;
+ FlxG.save.data.scrollSpeed = 1;
+ FlxG.save.data.downscroll = false;
+ }
+ PlayState.loadRep = false;
+ #if windows
+ if (PlayState.luaModchart != null)
+ {
+ PlayState.luaModchart.die();
+ PlayState.luaModchart = null;
+ }
+ #end
+ if (FlxG.save.data.fpsCap > 290)
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290);
+
+ FlxG.switchState(new MainMenuState());
+ }
+ }
+
+ if (FlxG.keys.justPressed.J)
+ {
+ // for reference later!
+ // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null);
+ }
+ }
+
+ override function destroy()
+ {
+ pauseMusic.destroy();
+
+ super.destroy();
+ }
+
+ function changeSelection(change:Int = 0):Void
+ {
+ curSelected += change;
+
+ if (curSelected < 0)
+ curSelected = menuItems.length - 1;
+ if (curSelected >= menuItems.length)
+ curSelected = 0;
+
+ var bullShit:Int = 0;
+
+ for (item in grpMenuShit.members)
+ {
+ item.targetY = bullShit - curSelected;
+ bullShit++;
+
+ item.alpha = 0.6;
+ // item.setGraphicSize(Std.int(item.width * 0.8));
+
+ if (item.targetY == 0)
+ {
+ item.alpha = 1;
+ // item.setGraphicSize(Std.int(item.width));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/PlayState.hx b/source - Copy/PlayState.hx
new file mode 100644
index 0000000..1edf6a1
--- /dev/null
+++ b/source - Copy/PlayState.hx
@@ -0,0 +1,3821 @@
+package;
+
+import Replay.Ana;
+import Replay.Analysis;
+import webm.WebmPlayer;
+import flixel.input.keyboard.FlxKey;
+import haxe.Exception;
+import openfl.geom.Matrix;
+import openfl.display.BitmapData;
+import openfl.utils.AssetType;
+import lime.graphics.Image;
+import flixel.graphics.FlxGraphic;
+import openfl.utils.AssetManifest;
+import openfl.utils.AssetLibrary;
+import flixel.system.FlxAssets;
+
+import lime.app.Application;
+import lime.media.AudioContext;
+import lime.media.AudioManager;
+import openfl.Lib;
+import Section.SwagSection;
+import Song.SwagSong;
+import WiggleEffect.WiggleEffectType;
+import flixel.FlxBasic;
+import flixel.FlxCamera;
+import flixel.FlxG;
+import flixel.FlxGame;
+import flixel.FlxObject;
+import flixel.FlxSprite;
+import flixel.FlxState;
+import flixel.FlxSubState;
+import flixel.addons.display.FlxGridOverlay;
+import flixel.addons.effects.FlxTrail;
+import flixel.addons.effects.FlxTrailArea;
+import flixel.addons.effects.chainable.FlxEffectSprite;
+import flixel.addons.effects.chainable.FlxWaveEffect;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.graphics.atlas.FlxAtlas;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.math.FlxMath;
+import flixel.math.FlxPoint;
+import flixel.math.FlxRect;
+import flixel.system.FlxSound;
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.ui.FlxBar;
+import flixel.util.FlxCollision;
+import flixel.util.FlxColor;
+import flixel.util.FlxSort;
+import flixel.util.FlxStringUtil;
+import flixel.util.FlxTimer;
+import haxe.Json;
+import lime.utils.Assets;
+import openfl.display.BlendMode;
+import openfl.display.StageQuality;
+import openfl.filters.ShaderFilter;
+
+#if windows
+import Discord.DiscordClient;
+#end
+#if windows
+import Sys;
+import sys.FileSystem;
+#end
+
+using StringTools;
+
+class PlayState extends MusicBeatState
+{
+ public static var instance:PlayState = null;
+
+ public static var curStage:String = '';
+ public static var SONG:SwagSong;
+ public static var isStoryMode:Bool = false;
+ public static var storyWeek:Int = 0;
+ public static var storyPlaylist:Array = [];
+ public static var storyDifficulty:Int = 1;
+ public static var weekSong:Int = 0;
+ public static var weekScore:Int = 0;
+ public static var shits:Int = 0;
+ public static var bads:Int = 0;
+ public static var goods:Int = 0;
+ public static var sicks:Int = 0;
+
+ public static var songPosBG:FlxSprite;
+ public static var songPosBar:FlxBar;
+
+ public static var rep:Replay;
+ public static var loadRep:Bool = false;
+
+ public static var noteBools:Array = [false, false, false, false];
+
+ var halloweenLevel:Bool = false;
+
+ var songLength:Float = 0;
+ var kadeEngineWatermark:FlxText;
+
+ #if windows
+ // Discord RPC variables
+ var storyDifficultyText:String = "";
+ var iconRPC:String = "";
+ var detailsText:String = "";
+ var detailsPausedText:String = "";
+ #end
+
+ private var vocals:FlxSound;
+
+ public var originalX:Float;
+
+ public static var dad:Character;
+ public static var gf:Character;
+ public static var boyfriend:Boyfriend;
+
+ public var notes:FlxTypedGroup;
+ private var unspawnNotes:Array = [];
+
+ public var strumLine:FlxSprite;
+ private var curSection:Int = 0;
+
+ private var camFollow:FlxObject;
+
+ private static var prevCamFollow:FlxObject;
+
+ public static var strumLineNotes:FlxTypedGroup = null;
+ public static var playerStrums:FlxTypedGroup = null;
+ public static var cpuStrums:FlxTypedGroup = null;
+
+ private var camZooming:Bool = false;
+ private var curSong:String = "";
+
+ private var gfSpeed:Int = 1;
+ public var health:Float = 1; //making public because sethealth doesnt work without it
+ private var combo:Int = 0;
+ public static var misses:Int = 0;
+ public static var campaignMisses:Int = 0;
+ public var accuracy:Float = 0.00;
+ private var accuracyDefault:Float = 0.00;
+ private var totalNotesHit:Float = 0;
+ private var totalNotesHitDefault:Float = 0;
+ private var totalPlayed:Int = 0;
+ private var ss:Bool = false;
+
+
+ private var healthBarBG:FlxSprite;
+ private var healthBar:FlxBar;
+ private var songPositionBar:Float = 0;
+
+ private var generatedMusic:Bool = false;
+ private var startingSong:Bool = false;
+
+ public var iconP1:HealthIcon; //making these public again because i may be stupid
+ public var iconP2:HealthIcon; //what could go wrong?
+ public var camHUD:FlxCamera;
+ private var camGame:FlxCamera;
+
+ public static var offsetTesting:Bool = false;
+
+ var notesHitArray:Array = [];
+ var currentFrames:Int = 0;
+
+ public var dialogue:Array = ['dad:blah blah blah', 'bf:coolswag'];
+
+ var halloweenBG:FlxSprite;
+ var isHalloween:Bool = false;
+
+ var phillyCityLights:FlxTypedGroup;
+ var phillyTrain:FlxSprite;
+ var trainSound:FlxSound;
+
+ var limo:FlxSprite;
+ var grpLimoDancers:FlxTypedGroup;
+ var fastCar:FlxSprite;
+ var songName:FlxText;
+ var upperBoppers:FlxSprite;
+ var bottomBoppers:FlxSprite;
+ var santa:FlxSprite;
+
+ var fc:Bool = true;
+
+ var bgGirls:BackgroundGirls;
+ var wiggleShit:WiggleEffect = new WiggleEffect();
+
+ var talking:Bool = true;
+ public var songScore:Int = 0;
+ var songScoreDef:Int = 0;
+ var scoreTxt:FlxText;
+ var replayTxt:FlxText;
+
+ public static var campaignScore:Int = 0;
+
+ var defaultCamZoom:Float = 1.05;
+
+ public static var daPixelZoom:Float = 6;
+
+ public static var theFunne:Bool = true;
+ var funneEffect:FlxSprite;
+ var inCutscene:Bool = false;
+ public static var repPresses:Int = 0;
+ public static var repReleases:Int = 0;
+
+ public static var timeCurrently:Float = 0;
+ public static var timeCurrentlyR:Float = 0;
+
+ // Will fire once to prevent debug spam messages and broken animations
+ private var triggeredAlready:Bool = false;
+
+ // Will decide if she's even allowed to headbang at all depending on the song
+ private var allowedToHeadbang:Bool = false;
+ // Per song additive offset
+ public static var songOffset:Float = 0;
+ // BotPlay text
+ private var botPlayState:FlxText;
+ // Replay shit
+ private var saveNotes:Array = [];
+ private var saveJudge:Array = [];
+ private var replayAna:Analysis = new Analysis(); // replay analysis
+
+ public static var highestCombo:Int = 0;
+
+ private var executeModchart = false;
+
+ // API stuff
+
+ public function addObject(object:FlxBasic) { add(object); }
+ public function removeObject(object:FlxBasic) { remove(object); }
+
+
+ override public function create()
+ {
+ instance = this;
+
+ if (FlxG.save.data.fpsCap > 290)
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(800);
+
+ if (FlxG.sound.music != null)
+ FlxG.sound.music.stop();
+
+ if (!isStoryMode)
+ {
+ sicks = 0;
+ bads = 0;
+ shits = 0;
+ goods = 0;
+ }
+ misses = 0;
+
+ repPresses = 0;
+ repReleases = 0;
+
+
+ PlayStateChangeables.useDownscroll = FlxG.save.data.downscroll;
+ PlayStateChangeables.safeFrames = FlxG.save.data.frames;
+ PlayStateChangeables.scrollSpeed = FlxG.save.data.scrollSpeed;
+ PlayStateChangeables.botPlay = FlxG.save.data.botplay;
+
+
+ // pre lowercasing the song name (create)
+ var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+
+ removedVideo = false;
+
+ #if windows
+ executeModchart = FileSystem.exists(Paths.lua(songLowercase + "/modchart"));
+ #end
+ #if !cpp
+ executeModchart = false; // FORCE disable for non cpp targets
+ #end
+
+ trace('Mod chart: ' + executeModchart + " - " + Paths.lua(songLowercase + "/modchart"));
+
+ #if windows
+ // Making difficulty text for Discord Rich Presence.
+ storyDifficultyText = CoolUtil.difficultyFromInt(storyDifficulty);
+
+ iconRPC = SONG.player2;
+
+ // To avoid having duplicate images in Discord assets
+ switch (iconRPC)
+ {
+ case 'senpai-angry':
+ iconRPC = 'senpai';
+ case 'monster-christmas':
+ iconRPC = 'monster';
+ case 'mom-car':
+ iconRPC = 'mom';
+ }
+
+ // String that contains the mode defined here so it isn't necessary to call changePresence for each mode
+ if (isStoryMode)
+ {
+ detailsText = "Story Mode: Week " + storyWeek;
+ }
+ else
+ {
+ detailsText = "Freeplay";
+ }
+
+ // String for when the game is paused
+ detailsPausedText = "Paused - " + detailsText;
+
+ // Updating Discord Rich Presence.
+ DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC);
+ #end
+
+
+ // var gameCam:FlxCamera = FlxG.camera;
+ camGame = new FlxCamera();
+ camHUD = new FlxCamera();
+ camHUD.bgColor.alpha = 0;
+
+ FlxG.cameras.reset(camGame);
+ FlxG.cameras.add(camHUD);
+
+ FlxCamera.defaultCameras = [camGame];
+
+ persistentUpdate = true;
+ persistentDraw = true;
+
+ if (SONG == null)
+ SONG = Song.loadFromJson('tutorial', 'tutorial');
+
+ Conductor.mapBPMChanges(SONG);
+ Conductor.changeBPM(SONG.bpm);
+
+ trace('INFORMATION ABOUT WHAT U PLAYIN WIT:\nFRAMES: ' + PlayStateChangeables.safeFrames + '\nZONE: ' + Conductor.safeZoneOffset + '\nTS: ' + Conductor.timeScale + '\nBotPlay : ' + PlayStateChangeables.botPlay);
+
+ //dialogue shit
+ switch (songLowercase)
+ {
+ case 'tutorial':
+ dialogue = ["Hey you're pretty cute.", 'Use the arrow keys to keep up \nwith me singing.'];
+ case 'bopeebo':
+ dialogue = [
+ 'HEY!',
+ "You think you can just sing\nwith my daughter like that?",
+ "If you want to date her...",
+ "You're going to have to go \nthrough ME first!"
+ ];
+ case 'fresh':
+ dialogue = ["Not too shabby boy.", ""];
+ case 'dadbattle':
+ dialogue = [
+ "gah you think you're hot stuff?",
+ "If you can beat me here...",
+ "Only then I will even CONSIDER letting you\ndate my daughter!"
+ ];
+ case 'senpai':
+ dialogue = CoolUtil.coolTextFile(Paths.txt('senpai/senpaiDialogue'));
+ case 'roses':
+ dialogue = CoolUtil.coolTextFile(Paths.txt('roses/rosesDialogue'));
+ case 'thorns':
+ dialogue = CoolUtil.coolTextFile(Paths.txt('thorns/thornsDialogue'));
+ }
+
+ //defaults if no stage was found in chart
+ var stageCheck:String = 'stage';
+
+ if (SONG.stage == null) {
+ switch(storyWeek)
+ {
+ case 2: stageCheck = 'halloween';
+ case 3: stageCheck = 'philly';
+ case 4: stageCheck = 'limo';
+ case 5: if (songLowercase == 'winter-horrorland') {stageCheck = 'mallEvil';} else {stageCheck = 'mall';}
+ case 6: if (songLowercase == 'thorns') {stageCheck = 'schoolEvil';} else {stageCheck = 'school';}
+ //i should check if its stage (but this is when none is found in chart anyway)
+ }
+ } else {stageCheck = SONG.stage;}
+
+ switch(stageCheck)
+ {
+ case 'halloween':
+ {
+ curStage = 'spooky';
+ halloweenLevel = true;
+
+ var hallowTex = Paths.getSparrowAtlas('halloween_bg','week2');
+
+ halloweenBG = new FlxSprite(-200, -100);
+ halloweenBG.frames = hallowTex;
+ halloweenBG.animation.addByPrefix('idle', 'halloweem bg0');
+ halloweenBG.animation.addByPrefix('lightning', 'halloweem bg lightning strike', 24, false);
+ halloweenBG.animation.play('idle');
+ halloweenBG.antialiasing = true;
+ add(halloweenBG);
+
+ isHalloween = true;
+ }
+ case 'philly':
+ {
+ curStage = 'philly';
+
+ var bg:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image('philly/sky', 'week3'));
+ bg.scrollFactor.set(0.1, 0.1);
+ add(bg);
+
+ var city:FlxSprite = new FlxSprite(-10).loadGraphic(Paths.image('philly/city', 'week3'));
+ city.scrollFactor.set(0.3, 0.3);
+ city.setGraphicSize(Std.int(city.width * 0.85));
+ city.updateHitbox();
+ add(city);
+
+ phillyCityLights = new FlxTypedGroup();
+ if(FlxG.save.data.distractions){
+ add(phillyCityLights);
+ }
+
+ for (i in 0...5)
+ {
+ var light:FlxSprite = new FlxSprite(city.x).loadGraphic(Paths.image('philly/win' + i, 'week3'));
+ light.scrollFactor.set(0.3, 0.3);
+ light.visible = false;
+ light.setGraphicSize(Std.int(light.width * 0.85));
+ light.updateHitbox();
+ light.antialiasing = true;
+ phillyCityLights.add(light);
+ }
+
+ var streetBehind:FlxSprite = new FlxSprite(-40, 50).loadGraphic(Paths.image('philly/behindTrain','week3'));
+ add(streetBehind);
+
+ phillyTrain = new FlxSprite(2000, 360).loadGraphic(Paths.image('philly/train','week3'));
+ if(FlxG.save.data.distractions){
+ add(phillyTrain);
+ }
+
+ trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes','week3'));
+ FlxG.sound.list.add(trainSound);
+
+ // var cityLights:FlxSprite = new FlxSprite().loadGraphic(AssetPaths.win0.png);
+
+ var street:FlxSprite = new FlxSprite(-40, streetBehind.y).loadGraphic(Paths.image('philly/street','week3'));
+ add(street);
+ }
+ case 'limo':
+ {
+ curStage = 'limo';
+ defaultCamZoom = 0.90;
+
+ var skyBG:FlxSprite = new FlxSprite(-120, -50).loadGraphic(Paths.image('limo/limoSunset','week4'));
+ skyBG.scrollFactor.set(0.1, 0.1);
+ add(skyBG);
+
+ var bgLimo:FlxSprite = new FlxSprite(-200, 480);
+ bgLimo.frames = Paths.getSparrowAtlas('limo/bgLimo','week4');
+ bgLimo.animation.addByPrefix('drive', "background limo pink", 24);
+ bgLimo.animation.play('drive');
+ bgLimo.scrollFactor.set(0.4, 0.4);
+ add(bgLimo);
+ if(FlxG.save.data.distractions){
+ grpLimoDancers = new FlxTypedGroup();
+ add(grpLimoDancers);
+
+ for (i in 0...5)
+ {
+ var dancer:BackgroundDancer = new BackgroundDancer((370 * i) + 130, bgLimo.y - 400);
+ dancer.scrollFactor.set(0.4, 0.4);
+ grpLimoDancers.add(dancer);
+ }
+ }
+
+ var overlayShit:FlxSprite = new FlxSprite(-500, -600).loadGraphic(Paths.image('limo/limoOverlay','week4'));
+ overlayShit.alpha = 0.5;
+ // add(overlayShit);
+
+ // var shaderBullshit = new BlendModeEffect(new OverlayShader(), FlxColor.RED);
+
+ // FlxG.camera.setFilters([new ShaderFilter(cast shaderBullshit.shader)]);
+
+ // overlayShit.shader = shaderBullshit;
+
+ var limoTex = Paths.getSparrowAtlas('limo/limoDrive','week4');
+
+ limo = new FlxSprite(-120, 550);
+ limo.frames = limoTex;
+ limo.animation.addByPrefix('drive', "Limo stage", 24);
+ limo.animation.play('drive');
+ limo.antialiasing = true;
+
+ fastCar = new FlxSprite(-300, 160).loadGraphic(Paths.image('limo/fastCarLol','week4'));
+ // add(limo);
+ }
+ case 'mall':
+ {
+ curStage = 'mall';
+
+ defaultCamZoom = 0.80;
+
+ var bg:FlxSprite = new FlxSprite(-1000, -500).loadGraphic(Paths.image('christmas/bgWalls','week5'));
+ bg.antialiasing = true;
+ bg.scrollFactor.set(0.2, 0.2);
+ bg.active = false;
+ bg.setGraphicSize(Std.int(bg.width * 0.8));
+ bg.updateHitbox();
+ add(bg);
+
+ upperBoppers = new FlxSprite(-240, -90);
+ upperBoppers.frames = Paths.getSparrowAtlas('christmas/upperBop','week5');
+ upperBoppers.animation.addByPrefix('bop', "Upper Crowd Bob", 24, false);
+ upperBoppers.antialiasing = true;
+ upperBoppers.scrollFactor.set(0.33, 0.33);
+ upperBoppers.setGraphicSize(Std.int(upperBoppers.width * 0.85));
+ upperBoppers.updateHitbox();
+ if(FlxG.save.data.distractions){
+ add(upperBoppers);
+ }
+
+
+ var bgEscalator:FlxSprite = new FlxSprite(-1100, -600).loadGraphic(Paths.image('christmas/bgEscalator','week5'));
+ bgEscalator.antialiasing = true;
+ bgEscalator.scrollFactor.set(0.3, 0.3);
+ bgEscalator.active = false;
+ bgEscalator.setGraphicSize(Std.int(bgEscalator.width * 0.9));
+ bgEscalator.updateHitbox();
+ add(bgEscalator);
+
+ var tree:FlxSprite = new FlxSprite(370, -250).loadGraphic(Paths.image('christmas/christmasTree','week5'));
+ tree.antialiasing = true;
+ tree.scrollFactor.set(0.40, 0.40);
+ add(tree);
+
+ bottomBoppers = new FlxSprite(-300, 140);
+ bottomBoppers.frames = Paths.getSparrowAtlas('christmas/bottomBop','week5');
+ bottomBoppers.animation.addByPrefix('bop', 'Bottom Level Boppers', 24, false);
+ bottomBoppers.antialiasing = true;
+ bottomBoppers.scrollFactor.set(0.9, 0.9);
+ bottomBoppers.setGraphicSize(Std.int(bottomBoppers.width * 1));
+ bottomBoppers.updateHitbox();
+ if(FlxG.save.data.distractions){
+ add(bottomBoppers);
+ }
+
+
+ var fgSnow:FlxSprite = new FlxSprite(-600, 700).loadGraphic(Paths.image('christmas/fgSnow','week5'));
+ fgSnow.active = false;
+ fgSnow.antialiasing = true;
+ add(fgSnow);
+
+ santa = new FlxSprite(-840, 150);
+ santa.frames = Paths.getSparrowAtlas('christmas/santa','week5');
+ santa.animation.addByPrefix('idle', 'santa idle in fear', 24, false);
+ santa.antialiasing = true;
+ if(FlxG.save.data.distractions){
+ add(santa);
+ }
+ }
+ case 'mallEvil':
+ {
+ curStage = 'mallEvil';
+ var bg:FlxSprite = new FlxSprite(-400, -500).loadGraphic(Paths.image('christmas/evilBG','week5'));
+ bg.antialiasing = true;
+ bg.scrollFactor.set(0.2, 0.2);
+ bg.active = false;
+ bg.setGraphicSize(Std.int(bg.width * 0.8));
+ bg.updateHitbox();
+ add(bg);
+
+ var evilTree:FlxSprite = new FlxSprite(300, -300).loadGraphic(Paths.image('christmas/evilTree','week5'));
+ evilTree.antialiasing = true;
+ evilTree.scrollFactor.set(0.2, 0.2);
+ add(evilTree);
+
+ var evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow",'week5'));
+ evilSnow.antialiasing = true;
+ add(evilSnow);
+ }
+ case 'school':
+ {
+ curStage = 'school';
+
+ // defaultCamZoom = 0.9;
+
+ var bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky','week6'));
+ bgSky.scrollFactor.set(0.1, 0.1);
+ add(bgSky);
+
+ var repositionShit = -200;
+
+ var bgSchool:FlxSprite = new FlxSprite(repositionShit, 0).loadGraphic(Paths.image('weeb/weebSchool','week6'));
+ bgSchool.scrollFactor.set(0.6, 0.90);
+ add(bgSchool);
+
+ var bgStreet:FlxSprite = new FlxSprite(repositionShit).loadGraphic(Paths.image('weeb/weebStreet','week6'));
+ bgStreet.scrollFactor.set(0.95, 0.95);
+ add(bgStreet);
+
+ var fgTrees:FlxSprite = new FlxSprite(repositionShit + 170, 130).loadGraphic(Paths.image('weeb/weebTreesBack','week6'));
+ fgTrees.scrollFactor.set(0.9, 0.9);
+ add(fgTrees);
+
+ var bgTrees:FlxSprite = new FlxSprite(repositionShit - 380, -800);
+ var treetex = Paths.getPackerAtlas('weeb/weebTrees','week6');
+ bgTrees.frames = treetex;
+ bgTrees.animation.add('treeLoop', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 12);
+ bgTrees.animation.play('treeLoop');
+ bgTrees.scrollFactor.set(0.85, 0.85);
+ add(bgTrees);
+
+ var treeLeaves:FlxSprite = new FlxSprite(repositionShit, -40);
+ treeLeaves.frames = Paths.getSparrowAtlas('weeb/petals','week6');
+ treeLeaves.animation.addByPrefix('leaves', 'PETALS ALL', 24, true);
+ treeLeaves.animation.play('leaves');
+ treeLeaves.scrollFactor.set(0.85, 0.85);
+ add(treeLeaves);
+
+ var widShit = Std.int(bgSky.width * 6);
+
+ bgSky.setGraphicSize(widShit);
+ bgSchool.setGraphicSize(widShit);
+ bgStreet.setGraphicSize(widShit);
+ bgTrees.setGraphicSize(Std.int(widShit * 1.4));
+ fgTrees.setGraphicSize(Std.int(widShit * 0.8));
+ treeLeaves.setGraphicSize(widShit);
+
+ fgTrees.updateHitbox();
+ bgSky.updateHitbox();
+ bgSchool.updateHitbox();
+ bgStreet.updateHitbox();
+ bgTrees.updateHitbox();
+ treeLeaves.updateHitbox();
+
+ bgGirls = new BackgroundGirls(-100, 190);
+ bgGirls.scrollFactor.set(0.9, 0.9);
+
+ if (songLowercase == 'roses')
+ {
+ if(FlxG.save.data.distractions){
+ bgGirls.getScared();
+ }
+ }
+
+ bgGirls.setGraphicSize(Std.int(bgGirls.width * daPixelZoom));
+ bgGirls.updateHitbox();
+ if(FlxG.save.data.distractions){
+ add(bgGirls);
+ }
+ }
+ case 'schoolEvil':
+ {
+ curStage = 'schoolEvil';
+
+ var waveEffectBG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 3, 2);
+ var waveEffectFG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 5, 2);
+
+ var posX = 400;
+ var posY = 200;
+
+ var bg:FlxSprite = new FlxSprite(posX, posY);
+ bg.frames = Paths.getSparrowAtlas('weeb/animatedEvilSchool','week6');
+ bg.animation.addByPrefix('idle', 'background 2', 24);
+ bg.animation.play('idle');
+ bg.scrollFactor.set(0.8, 0.9);
+ bg.scale.set(6, 6);
+ add(bg);
+
+ /*
+ var bg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolBG'));
+ bg.scale.set(6, 6);
+ // bg.setGraphicSize(Std.int(bg.width * 6));
+ // bg.updateHitbox();
+ add(bg);
+ var fg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolFG'));
+ fg.scale.set(6, 6);
+ // fg.setGraphicSize(Std.int(fg.width * 6));
+ // fg.updateHitbox();
+ add(fg);
+ wiggleShit.effectType = WiggleEffectType.DREAMY;
+ wiggleShit.waveAmplitude = 0.01;
+ wiggleShit.waveFrequency = 60;
+ wiggleShit.waveSpeed = 0.8;
+ */
+
+ // bg.shader = wiggleShit.shader;
+ // fg.shader = wiggleShit.shader;
+
+ /*
+ var waveSprite = new FlxEffectSprite(bg, [waveEffectBG]);
+ var waveSpriteFG = new FlxEffectSprite(fg, [waveEffectFG]);
+ // Using scale since setGraphicSize() doesnt work???
+ waveSprite.scale.set(6, 6);
+ waveSpriteFG.scale.set(6, 6);
+ waveSprite.setPosition(posX, posY);
+ waveSpriteFG.setPosition(posX, posY);
+ waveSprite.scrollFactor.set(0.7, 0.8);
+ waveSpriteFG.scrollFactor.set(0.9, 0.8);
+ // waveSprite.setGraphicSize(Std.int(waveSprite.width * 6));
+ // waveSprite.updateHitbox();
+ // waveSpriteFG.setGraphicSize(Std.int(fg.width * 6));
+ // waveSpriteFG.updateHitbox();
+ add(waveSprite);
+ add(waveSpriteFG);
+ */
+ }
+ case 'stage':
+ {
+ defaultCamZoom = 0.9;
+ curStage = 'stage';
+ var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback'));
+ bg.antialiasing = true;
+ bg.scrollFactor.set(0.9, 0.9);
+ bg.active = false;
+ add(bg);
+
+ var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront'));
+ stageFront.setGraphicSize(Std.int(stageFront.width * 1.1));
+ stageFront.updateHitbox();
+ stageFront.antialiasing = true;
+ stageFront.scrollFactor.set(0.9, 0.9);
+ stageFront.active = false;
+ add(stageFront);
+
+ var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains'));
+ stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9));
+ stageCurtains.updateHitbox();
+ stageCurtains.antialiasing = true;
+ stageCurtains.scrollFactor.set(1.3, 1.3);
+ stageCurtains.active = false;
+
+ add(stageCurtains);
+ }
+ default:
+ {
+ defaultCamZoom = 0.9;
+ curStage = 'stage';
+ var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback'));
+ bg.antialiasing = true;
+ bg.scrollFactor.set(0.9, 0.9);
+ bg.active = false;
+ add(bg);
+
+ var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront'));
+ stageFront.setGraphicSize(Std.int(stageFront.width * 1.1));
+ stageFront.updateHitbox();
+ stageFront.antialiasing = true;
+ stageFront.scrollFactor.set(0.9, 0.9);
+ stageFront.active = false;
+ add(stageFront);
+
+ var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains'));
+ stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9));
+ stageCurtains.updateHitbox();
+ stageCurtains.antialiasing = true;
+ stageCurtains.scrollFactor.set(1.3, 1.3);
+ stageCurtains.active = false;
+
+ add(stageCurtains);
+ }
+ }
+
+ //defaults if no gf was found in chart
+ var gfCheck:String = 'gf';
+
+ if (SONG.gfVersion == null) {
+ switch(storyWeek)
+ {
+ case 4: gfCheck = 'gf-car';
+ case 5: gfCheck = 'gf-christmas';
+ case 6: gfCheck = 'gf-pixel';
+ }
+ } else {gfCheck = SONG.gfVersion;}
+
+ var curGf:String = '';
+ switch (gfCheck)
+ {
+ case 'gf-car':
+ curGf = 'gf-car';
+ case 'gf-christmas':
+ curGf = 'gf-christmas';
+ case 'gf-pixel':
+ curGf = 'gf-pixel';
+ default:
+ curGf = 'gf';
+ }
+
+ gf = new Character(400, 130, curGf);
+ gf.scrollFactor.set(0.95, 0.95);
+
+ dad = new Character(100, 100, SONG.player2);
+
+ var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x, dad.getGraphicMidpoint().y);
+
+ switch (SONG.player2)
+ {
+ case 'gf':
+ dad.setPosition(gf.x, gf.y);
+ gf.visible = false;
+ if (isStoryMode)
+ {
+ camPos.x += 600;
+ tweenCamIn();
+ }
+
+ case "spooky":
+ dad.y += 200;
+ case "monster":
+ dad.y += 100;
+ case 'monster-christmas':
+ dad.y += 130;
+ case 'dad':
+ camPos.x += 400;
+ case 'pico':
+ camPos.x += 600;
+ dad.y += 300;
+ case 'parents-christmas':
+ dad.x -= 500;
+ case 'senpai':
+ dad.x += 150;
+ dad.y += 360;
+ camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y);
+ case 'senpai-angry':
+ dad.x += 150;
+ dad.y += 360;
+ camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y);
+ case 'spirit':
+ dad.x -= 150;
+ dad.y += 100;
+ camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y);
+ }
+
+
+
+ boyfriend = new Boyfriend(770, 450, SONG.player1);
+
+ // REPOSITIONING PER STAGE
+ switch (curStage)
+ {
+ case 'limo':
+ boyfriend.y -= 220;
+ boyfriend.x += 260;
+ if(FlxG.save.data.distractions){
+ resetFastCar();
+ add(fastCar);
+ }
+
+ case 'mall':
+ boyfriend.x += 200;
+
+ case 'mallEvil':
+ boyfriend.x += 320;
+ dad.y -= 80;
+ case 'school':
+ boyfriend.x += 200;
+ boyfriend.y += 220;
+ gf.x += 180;
+ gf.y += 300;
+ case 'schoolEvil':
+ if(FlxG.save.data.distractions){
+ // trailArea.scrollFactor.set();
+ var evilTrail = new FlxTrail(dad, null, 4, 24, 0.3, 0.069);
+ // evilTrail.changeValuesEnabled(false, false, false, false);
+ // evilTrail.changeGraphic()
+ add(evilTrail);
+ // evilTrail.scrollFactor.set(1.1, 1.1);
+ }
+
+
+ boyfriend.x += 200;
+ boyfriend.y += 220;
+ gf.x += 180;
+ gf.y += 300;
+ }
+
+ add(gf);
+
+ // Shitty layering but whatev it works LOL
+ if (curStage == 'limo')
+ add(limo);
+
+ add(dad);
+ add(boyfriend);
+ if (loadRep)
+ {
+ FlxG.watch.addQuick('rep rpesses',repPresses);
+ FlxG.watch.addQuick('rep releases',repReleases);
+ // FlxG.watch.addQuick('Queued',inputsQueued);
+
+ PlayStateChangeables.useDownscroll = rep.replay.isDownscroll;
+ PlayStateChangeables.safeFrames = rep.replay.sf;
+ PlayStateChangeables.botPlay = true;
+ }
+
+ trace('uh ' + PlayStateChangeables.safeFrames);
+
+ trace("SF CALC: " + Math.floor((PlayStateChangeables.safeFrames / 60) * 1000));
+
+ var doof:DialogueBox = new DialogueBox(false, dialogue);
+ // doof.x += 70;
+ // doof.y = FlxG.height * 0.5;
+ doof.scrollFactor.set();
+ doof.finishThing = startCountdown;
+
+ Conductor.songPosition = -5000;
+
+ strumLine = new FlxSprite(0, 50).makeGraphic(FlxG.width, 10);
+ strumLine.scrollFactor.set();
+
+ if (PlayStateChangeables.useDownscroll)
+ strumLine.y = FlxG.height - 165;
+
+ strumLineNotes = new FlxTypedGroup();
+ add(strumLineNotes);
+
+ playerStrums = new FlxTypedGroup();
+ cpuStrums = new FlxTypedGroup();
+
+ // startCountdown();
+
+ if (SONG.song == null)
+ trace('song is null???');
+ else
+ trace('song looks gucci');
+
+ generateSong(SONG.song);
+
+ trace('generated');
+
+ // add(strumLine);
+
+ camFollow = new FlxObject(0, 0, 1, 1);
+
+ camFollow.setPosition(camPos.x, camPos.y);
+
+ if (prevCamFollow != null)
+ {
+ camFollow = prevCamFollow;
+ prevCamFollow = null;
+ }
+
+ add(camFollow);
+
+ FlxG.camera.follow(camFollow, LOCKON, 0.04 * (30 / (cast (Lib.current.getChildAt(0), Main)).getFPS()));
+ // FlxG.camera.setScrollBounds(0, FlxG.width, 0, FlxG.height);
+ FlxG.camera.zoom = defaultCamZoom;
+ FlxG.camera.focusOn(camFollow.getPosition());
+
+ FlxG.worldBounds.set(0, 0, FlxG.width, FlxG.height);
+
+ FlxG.fixedTimestep = false;
+
+ if (FlxG.save.data.songPosition) // I dont wanna talk about this code :(
+ {
+ songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar'));
+ if (PlayStateChangeables.useDownscroll)
+ songPosBG.y = FlxG.height * 0.9 + 45;
+ songPosBG.screenCenter(X);
+ songPosBG.scrollFactor.set();
+ add(songPosBG);
+
+ songPosBar = new FlxBar(songPosBG.x + 4, songPosBG.y + 4, LEFT_TO_RIGHT, Std.int(songPosBG.width - 8), Std.int(songPosBG.height - 8), this,
+ 'songPositionBar', 0, 90000);
+ songPosBar.scrollFactor.set();
+ songPosBar.createFilledBar(FlxColor.GRAY, FlxColor.LIME);
+ add(songPosBar);
+
+ var songName = new FlxText(songPosBG.x + (songPosBG.width / 2) - (SONG.song.length * 5),songPosBG.y,0,SONG.song, 16);
+ if (PlayStateChangeables.useDownscroll)
+ songName.y -= 3;
+ songName.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
+ songName.scrollFactor.set();
+ add(songName);
+ songName.cameras = [camHUD];
+ }
+
+ healthBarBG = new FlxSprite(0, FlxG.height * 0.9).loadGraphic(Paths.image('healthBar'));
+ if (PlayStateChangeables.useDownscroll)
+ healthBarBG.y = 50;
+ healthBarBG.screenCenter(X);
+ healthBarBG.scrollFactor.set();
+ add(healthBarBG);
+
+ healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this,
+ 'health', 0, 2);
+ healthBar.scrollFactor.set();
+ healthBar.createFilledBar(0xFFFF0000, 0xFF66FF33);
+ // healthBar
+ add(healthBar);
+
+ // Add Kade Engine watermark
+ kadeEngineWatermark = new FlxText(4,healthBarBG.y + 50,0,SONG.song + " " + CoolUtil.difficultyFromInt(storyDifficulty) + (Main.watermarks ? " - KE " + MainMenuState.kadeEngineVer : ""), 16);
+ kadeEngineWatermark.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
+ kadeEngineWatermark.scrollFactor.set();
+ add(kadeEngineWatermark);
+
+ if (PlayStateChangeables.useDownscroll)
+ kadeEngineWatermark.y = FlxG.height * 0.9 + 45;
+
+ scoreTxt = new FlxText(FlxG.width / 2 - 235, healthBarBG.y + 50, 0, "", 20);
+
+ scoreTxt.screenCenter(X);
+
+ originalX = scoreTxt.x;
+
+
+ scoreTxt.scrollFactor.set();
+
+ scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, FlxTextAlign.CENTER, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
+
+ add(scoreTxt);
+
+ replayTxt = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (PlayStateChangeables.useDownscroll ? 100 : -100), 0, "REPLAY", 20);
+ replayTxt.setFormat(Paths.font("vcr.ttf"), 42, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
+ replayTxt.borderSize = 4;
+ replayTxt.borderQuality = 2;
+ replayTxt.scrollFactor.set();
+ if (loadRep)
+ {
+ add(replayTxt);
+ }
+ // Literally copy-paste of the above, fu
+ botPlayState = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (PlayStateChangeables.useDownscroll ? 100 : -100), 0, "BOTPLAY", 20);
+ botPlayState.setFormat(Paths.font("vcr.ttf"), 42, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
+ botPlayState.scrollFactor.set();
+ botPlayState.borderSize = 4;
+ botPlayState.borderQuality = 2;
+ if(PlayStateChangeables.botPlay && !loadRep) add(botPlayState);
+
+ iconP1 = new HealthIcon(SONG.player1, true);
+ iconP1.y = healthBar.y - (iconP1.height / 2);
+ add(iconP1);
+
+ iconP2 = new HealthIcon(SONG.player2, false);
+ iconP2.y = healthBar.y - (iconP2.height / 2);
+ add(iconP2);
+
+ strumLineNotes.cameras = [camHUD];
+ notes.cameras = [camHUD];
+ healthBar.cameras = [camHUD];
+ healthBarBG.cameras = [camHUD];
+ iconP1.cameras = [camHUD];
+ iconP2.cameras = [camHUD];
+ scoreTxt.cameras = [camHUD];
+ doof.cameras = [camHUD];
+ if (FlxG.save.data.songPosition)
+ {
+ songPosBG.cameras = [camHUD];
+ songPosBar.cameras = [camHUD];
+ }
+ kadeEngineWatermark.cameras = [camHUD];
+ if (loadRep)
+ replayTxt.cameras = [camHUD];
+
+ // if (SONG.song == 'South')
+ // FlxG.camera.alpha = 0.7;
+ // UI_camera.zoom = 1;
+
+ // cameras = [FlxG.cameras.list[1]];
+ startingSong = true;
+
+ trace('starting');
+
+ if (isStoryMode)
+ {
+ switch (StringTools.replace(curSong," ", "-").toLowerCase())
+ {
+ case "winter-horrorland":
+ var blackScreen:FlxSprite = new FlxSprite(0, 0).makeGraphic(Std.int(FlxG.width * 2), Std.int(FlxG.height * 2), FlxColor.BLACK);
+ add(blackScreen);
+ blackScreen.scrollFactor.set();
+ camHUD.visible = false;
+
+ new FlxTimer().start(0.1, function(tmr:FlxTimer)
+ {
+ remove(blackScreen);
+ FlxG.sound.play(Paths.sound('Lights_Turn_On'));
+ camFollow.y = -2050;
+ camFollow.x += 200;
+ FlxG.camera.focusOn(camFollow.getPosition());
+ FlxG.camera.zoom = 1.5;
+
+ new FlxTimer().start(0.8, function(tmr:FlxTimer)
+ {
+ camHUD.visible = true;
+ remove(blackScreen);
+ FlxTween.tween(FlxG.camera, {zoom: defaultCamZoom}, 2.5, {
+ ease: FlxEase.quadInOut,
+ onComplete: function(twn:FlxTween)
+ {
+ startCountdown();
+ }
+ });
+ });
+ });
+ case 'senpai':
+ schoolIntro(doof);
+ case 'roses':
+ FlxG.sound.play(Paths.sound('ANGRY'));
+ schoolIntro(doof);
+ case 'thorns':
+ schoolIntro(doof);
+ default:
+ startCountdown();
+ }
+ }
+ else
+ {
+ switch (curSong.toLowerCase())
+ {
+ default:
+ startCountdown();
+ }
+ }
+
+ if (!loadRep)
+ rep = new Replay("na");
+
+ super.create();
+ }
+
+ function schoolIntro(?dialogueBox:DialogueBox):Void
+ {
+ var black:FlxSprite = new FlxSprite(-100, -100).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK);
+ black.scrollFactor.set();
+ add(black);
+
+ var red:FlxSprite = new FlxSprite(-100, -100).makeGraphic(FlxG.width * 2, FlxG.height * 2, 0xFFff1b31);
+ red.scrollFactor.set();
+
+ var senpaiEvil:FlxSprite = new FlxSprite();
+ senpaiEvil.frames = Paths.getSparrowAtlas('weeb/senpaiCrazy');
+ senpaiEvil.animation.addByPrefix('idle', 'Senpai Pre Explosion', 24, false);
+ senpaiEvil.setGraphicSize(Std.int(senpaiEvil.width * 6));
+ senpaiEvil.scrollFactor.set();
+ senpaiEvil.updateHitbox();
+ senpaiEvil.screenCenter();
+
+ if (StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'roses' || StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'thorns')
+ {
+ remove(black);
+
+ if (StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'thorns')
+ {
+ add(red);
+ }
+ }
+
+ new FlxTimer().start(0.3, function(tmr:FlxTimer)
+ {
+ black.alpha -= 0.15;
+
+ if (black.alpha > 0)
+ {
+ tmr.reset(0.3);
+ }
+ else
+ {
+ if (dialogueBox != null)
+ {
+ inCutscene = true;
+
+ if (StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'thorns')
+ {
+ add(senpaiEvil);
+ senpaiEvil.alpha = 0;
+ new FlxTimer().start(0.3, function(swagTimer:FlxTimer)
+ {
+ senpaiEvil.alpha += 0.15;
+ if (senpaiEvil.alpha < 1)
+ {
+ swagTimer.reset();
+ }
+ else
+ {
+ senpaiEvil.animation.play('idle');
+ FlxG.sound.play(Paths.sound('Senpai_Dies'), 1, false, null, true, function()
+ {
+ remove(senpaiEvil);
+ remove(red);
+ FlxG.camera.fade(FlxColor.WHITE, 0.01, true, function()
+ {
+ add(dialogueBox);
+ }, true);
+ });
+ new FlxTimer().start(3.2, function(deadTime:FlxTimer)
+ {
+ FlxG.camera.fade(FlxColor.WHITE, 1.6, false);
+ });
+ }
+ });
+ }
+ else
+ {
+ add(dialogueBox);
+ }
+ }
+ else
+ startCountdown();
+
+ remove(black);
+ }
+ });
+ }
+
+ var startTimer:FlxTimer;
+ var perfectMode:Bool = false;
+
+ var luaWiggles:Array = [];
+
+ #if windows
+ public static var luaModchart:ModchartState = null;
+ #end
+
+ function startCountdown():Void
+ {
+ inCutscene = false;
+
+ generateStaticArrows(0);
+ generateStaticArrows(1);
+
+
+ #if windows
+ // pre lowercasing the song name (startCountdown)
+ var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+ if (executeModchart)
+ {
+ luaModchart = ModchartState.createModchartState();
+ luaModchart.executeState('start',[songLowercase]);
+ }
+ #end
+
+ talking = false;
+ startedCountdown = true;
+ Conductor.songPosition = 0;
+ Conductor.songPosition -= Conductor.crochet * 5;
+
+ var swagCounter:Int = 0;
+
+ startTimer = new FlxTimer().start(Conductor.crochet / 1000, function(tmr:FlxTimer)
+ {
+ dad.dance();
+ gf.dance();
+ boyfriend.playAnim('idle');
+
+ var introAssets:Map> = new Map>();
+ introAssets.set('default', ['ready', "set", "go"]);
+ introAssets.set('school', [
+ 'weeb/pixelUI/ready-pixel',
+ 'weeb/pixelUI/set-pixel',
+ 'weeb/pixelUI/date-pixel'
+ ]);
+ introAssets.set('schoolEvil', [
+ 'weeb/pixelUI/ready-pixel',
+ 'weeb/pixelUI/set-pixel',
+ 'weeb/pixelUI/date-pixel'
+ ]);
+
+ var introAlts:Array = introAssets.get('default');
+ var altSuffix:String = "";
+
+ for (value in introAssets.keys())
+ {
+ if (value == curStage)
+ {
+ introAlts = introAssets.get(value);
+ altSuffix = '-pixel';
+ }
+ }
+
+ switch (swagCounter)
+
+ {
+ case 0:
+ FlxG.sound.play(Paths.sound('intro3' + altSuffix), 0.6);
+ case 1:
+ var ready:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[0]));
+ ready.scrollFactor.set();
+ ready.updateHitbox();
+
+ if (curStage.startsWith('school'))
+ ready.setGraphicSize(Std.int(ready.width * daPixelZoom));
+
+ ready.screenCenter();
+ add(ready);
+ FlxTween.tween(ready, {y: ready.y += 100, alpha: 0}, Conductor.crochet / 1000, {
+ ease: FlxEase.cubeInOut,
+ onComplete: function(twn:FlxTween)
+ {
+ ready.destroy();
+ }
+ });
+ FlxG.sound.play(Paths.sound('intro2' + altSuffix), 0.6);
+ case 2:
+ var set:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[1]));
+ set.scrollFactor.set();
+
+ if (curStage.startsWith('school'))
+ set.setGraphicSize(Std.int(set.width * daPixelZoom));
+
+ set.screenCenter();
+ add(set);
+ FlxTween.tween(set, {y: set.y += 100, alpha: 0}, Conductor.crochet / 1000, {
+ ease: FlxEase.cubeInOut,
+ onComplete: function(twn:FlxTween)
+ {
+ set.destroy();
+ }
+ });
+ FlxG.sound.play(Paths.sound('intro1' + altSuffix), 0.6);
+ case 3:
+ var go:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[2]));
+ go.scrollFactor.set();
+
+ if (curStage.startsWith('school'))
+ go.setGraphicSize(Std.int(go.width * daPixelZoom));
+
+ go.updateHitbox();
+
+ go.screenCenter();
+ add(go);
+ FlxTween.tween(go, {y: go.y += 100, alpha: 0}, Conductor.crochet / 1000, {
+ ease: FlxEase.cubeInOut,
+ onComplete: function(twn:FlxTween)
+ {
+ go.destroy();
+ }
+ });
+ FlxG.sound.play(Paths.sound('introGo' + altSuffix), 0.6);
+ case 4:
+ }
+
+ swagCounter += 1;
+ // generateSong('fresh');
+ }, 5);
+ }
+
+ var previousFrameTime:Int = 0;
+ var lastReportedPlayheadPosition:Int = 0;
+ var songTime:Float = 0;
+
+
+ var songStarted = false;
+
+ function startSong():Void
+ {
+ startingSong = false;
+ songStarted = true;
+ previousFrameTime = FlxG.game.ticks;
+ lastReportedPlayheadPosition = 0;
+
+ if (!paused)
+ {
+ FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false);
+ }
+
+ FlxG.sound.music.onComplete = endSong;
+ vocals.play();
+
+ // Song duration in a float, useful for the time left feature
+ songLength = FlxG.sound.music.length;
+
+ if (FlxG.save.data.songPosition)
+ {
+ remove(songPosBG);
+ remove(songPosBar);
+ remove(songName);
+
+ songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar'));
+ if (PlayStateChangeables.useDownscroll)
+ songPosBG.y = FlxG.height * 0.9 + 45;
+ songPosBG.screenCenter(X);
+ songPosBG.scrollFactor.set();
+ add(songPosBG);
+
+ songPosBar = new FlxBar(songPosBG.x + 4, songPosBG.y + 4, LEFT_TO_RIGHT, Std.int(songPosBG.width - 8), Std.int(songPosBG.height - 8), this,
+ 'songPositionBar', 0, songLength - 1000);
+ songPosBar.numDivisions = 1000;
+ songPosBar.scrollFactor.set();
+ songPosBar.createFilledBar(FlxColor.GRAY, FlxColor.LIME);
+ add(songPosBar);
+
+ var songName = new FlxText(songPosBG.x + (songPosBG.width / 2) - (SONG.song.length * 5),songPosBG.y,0,SONG.song, 16);
+ if (PlayStateChangeables.useDownscroll)
+ songName.y -= 3;
+ songName.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
+ songName.scrollFactor.set();
+ add(songName);
+
+ songPosBG.cameras = [camHUD];
+ songPosBar.cameras = [camHUD];
+ songName.cameras = [camHUD];
+ }
+
+ // Song check real quick
+ switch(curSong)
+ {
+ case 'Bopeebo' | 'Philly Nice' | 'Blammed' | 'Cocoa' | 'Eggnog': allowedToHeadbang = true;
+ default: allowedToHeadbang = false;
+ }
+
+ if (useVideo)
+ GlobalVideo.get().resume();
+
+ #if windows
+ // Updating Discord Rich Presence (with Time Left)
+ DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC);
+ #end
+ }
+
+ var debugNum:Int = 0;
+
+ private function generateSong(dataPath:String):Void
+ {
+ // FlxG.log.add(ChartParser.parse());
+
+ var songData = SONG;
+ Conductor.changeBPM(songData.bpm);
+
+ curSong = songData.song;
+
+ if (SONG.needsVoices)
+ vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song));
+ else
+ vocals = new FlxSound();
+
+ trace('loaded vocals');
+
+ FlxG.sound.list.add(vocals);
+
+ notes = new FlxTypedGroup();
+ add(notes);
+
+ var noteData:Array;
+
+ // NEW SHIT
+ noteData = songData.notes;
+
+ var playerCounter:Int = 0;
+
+ // Per song offset check
+ #if windows
+ // pre lowercasing the song name (generateSong)
+ var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
+ switch (songLowercase) {
+ case 'dad-battle': songLowercase = 'dadbattle';
+ case 'philly-nice': songLowercase = 'philly';
+ }
+
+ var songPath = 'assets/data/' + songLowercase + '/';
+
+ for(file in sys.FileSystem.readDirectory(songPath))
+ {
+ var path = haxe.io.Path.join([songPath, file]);
+ if(!sys.FileSystem.isDirectory(path))
+ {
+ if(path.endsWith('.offset'))
+ {
+ trace('Found offset file: ' + path);
+ songOffset = Std.parseFloat(file.substring(0, file.indexOf('.off')));
+ break;
+ }else {
+ trace('Offset file not found. Creating one @: ' + songPath);
+ sys.io.File.saveContent(songPath + songOffset + '.offset', '');
+ }
+ }
+ }
+ #end
+ var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped
+ for (section in noteData)
+ {
+ var coolSection:Int = Std.int(section.lengthInSteps / 4);
+
+ for (songNotes in section.sectionNotes)
+ {
+ var daStrumTime:Float = songNotes[0] + FlxG.save.data.offset + songOffset;
+ if (daStrumTime < 0)
+ daStrumTime = 0;
+ var daNoteData:Int = Std.int(songNotes[1] % 4);
+
+ var gottaHitNote:Bool = section.mustHitSection;
+
+ if (songNotes[1] > 3)
+ {
+ gottaHitNote = !section.mustHitSection;
+ }
+
+ var oldNote:Note;
+ if (unspawnNotes.length > 0)
+ oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)];
+ else
+ oldNote = null;
+
+ var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote);
+ swagNote.sustainLength = songNotes[2];
+ swagNote.scrollFactor.set(0, 0);
+
+ var susLength:Float = swagNote.sustainLength;
+
+ susLength = susLength / Conductor.stepCrochet;
+ unspawnNotes.push(swagNote);
+
+ for (susNote in 0...Math.floor(susLength))
+ {
+ oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)];
+
+ var sustainNote:Note = new Note(daStrumTime + (Conductor.stepCrochet * susNote) + Conductor.stepCrochet, daNoteData, oldNote, true);
+ sustainNote.scrollFactor.set();
+ unspawnNotes.push(sustainNote);
+
+ sustainNote.mustPress = gottaHitNote;
+
+ if (sustainNote.mustPress)
+ {
+ sustainNote.x += FlxG.width / 2; // general offset
+ }
+ }
+
+ swagNote.mustPress = gottaHitNote;
+
+ if (swagNote.mustPress)
+ {
+ swagNote.x += FlxG.width / 2; // general offset
+ }
+ else
+ {
+ }
+ }
+ daBeats += 1;
+ }
+
+ // trace(unspawnNotes.length);
+ // playerCounter += 1;
+
+ unspawnNotes.sort(sortByShit);
+
+ generatedMusic = true;
+ }
+
+ function sortByShit(Obj1:Note, Obj2:Note):Int
+ {
+ return FlxSort.byValues(FlxSort.ASCENDING, Obj1.strumTime, Obj2.strumTime);
+ }
+
+ private function generateStaticArrows(player:Int):Void
+ {
+ for (i in 0...4)
+ {
+ // FlxG.log.add(i);
+ var babyArrow:FlxSprite = new FlxSprite(0, strumLine.y);
+
+ //defaults if no noteStyle was found in chart
+ var noteTypeCheck:String = 'normal';
+
+ if (SONG.noteStyle == null) {
+ switch(storyWeek) {case 6: noteTypeCheck = 'pixel';}
+ } else {noteTypeCheck = SONG.noteStyle;}
+
+ switch (noteTypeCheck)
+ {
+ case 'pixel':
+ babyArrow.loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17);
+ babyArrow.animation.add('green', [6]);
+ babyArrow.animation.add('red', [7]);
+ babyArrow.animation.add('blue', [5]);
+ babyArrow.animation.add('purplel', [4]);
+
+ babyArrow.setGraphicSize(Std.int(babyArrow.width * daPixelZoom));
+ babyArrow.updateHitbox();
+ babyArrow.antialiasing = false;
+
+ switch (Math.abs(i))
+ {
+ case 2:
+ babyArrow.x += Note.swagWidth * 2;
+ babyArrow.animation.add('static', [2]);
+ babyArrow.animation.add('pressed', [6, 10], 12, false);
+ babyArrow.animation.add('confirm', [14, 18], 12, false);
+ case 3:
+ babyArrow.x += Note.swagWidth * 3;
+ babyArrow.animation.add('static', [3]);
+ babyArrow.animation.add('pressed', [7, 11], 12, false);
+ babyArrow.animation.add('confirm', [15, 19], 24, false);
+ case 1:
+ babyArrow.x += Note.swagWidth * 1;
+ babyArrow.animation.add('static', [1]);
+ babyArrow.animation.add('pressed', [5, 9], 12, false);
+ babyArrow.animation.add('confirm', [13, 17], 24, false);
+ case 0:
+ babyArrow.x += Note.swagWidth * 0;
+ babyArrow.animation.add('static', [0]);
+ babyArrow.animation.add('pressed', [4, 8], 12, false);
+ babyArrow.animation.add('confirm', [12, 16], 24, false);
+ }
+
+ case 'normal':
+ babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets');
+ babyArrow.animation.addByPrefix('green', 'arrowUP');
+ babyArrow.animation.addByPrefix('blue', 'arrowDOWN');
+ babyArrow.animation.addByPrefix('purple', 'arrowLEFT');
+ babyArrow.animation.addByPrefix('red', 'arrowRIGHT');
+
+ babyArrow.antialiasing = true;
+ babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7));
+
+ switch (Math.abs(i))
+ {
+ case 0:
+ babyArrow.x += Note.swagWidth * 0;
+ babyArrow.animation.addByPrefix('static', 'arrowLEFT');
+ babyArrow.animation.addByPrefix('pressed', 'left press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false);
+ case 1:
+ babyArrow.x += Note.swagWidth * 1;
+ babyArrow.animation.addByPrefix('static', 'arrowDOWN');
+ babyArrow.animation.addByPrefix('pressed', 'down press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false);
+ case 2:
+ babyArrow.x += Note.swagWidth * 2;
+ babyArrow.animation.addByPrefix('static', 'arrowUP');
+ babyArrow.animation.addByPrefix('pressed', 'up press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false);
+ case 3:
+ babyArrow.x += Note.swagWidth * 3;
+ babyArrow.animation.addByPrefix('static', 'arrowRIGHT');
+ babyArrow.animation.addByPrefix('pressed', 'right press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false);
+ }
+
+ default:
+ babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets');
+ babyArrow.animation.addByPrefix('green', 'arrowUP');
+ babyArrow.animation.addByPrefix('blue', 'arrowDOWN');
+ babyArrow.animation.addByPrefix('purple', 'arrowLEFT');
+ babyArrow.animation.addByPrefix('red', 'arrowRIGHT');
+
+ babyArrow.antialiasing = true;
+ babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7));
+
+ switch (Math.abs(i))
+ {
+ case 0:
+ babyArrow.x += Note.swagWidth * 0;
+ babyArrow.animation.addByPrefix('static', 'arrowLEFT');
+ babyArrow.animation.addByPrefix('pressed', 'left press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false);
+ case 1:
+ babyArrow.x += Note.swagWidth * 1;
+ babyArrow.animation.addByPrefix('static', 'arrowDOWN');
+ babyArrow.animation.addByPrefix('pressed', 'down press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false);
+ case 2:
+ babyArrow.x += Note.swagWidth * 2;
+ babyArrow.animation.addByPrefix('static', 'arrowUP');
+ babyArrow.animation.addByPrefix('pressed', 'up press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false);
+ case 3:
+ babyArrow.x += Note.swagWidth * 3;
+ babyArrow.animation.addByPrefix('static', 'arrowRIGHT');
+ babyArrow.animation.addByPrefix('pressed', 'right press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false);
+ }
+ }
+
+ babyArrow.updateHitbox();
+ babyArrow.scrollFactor.set();
+
+ if (!isStoryMode)
+ {
+ babyArrow.y -= 10;
+ babyArrow.alpha = 0;
+ FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)});
+ }
+
+ babyArrow.ID = i;
+
+ switch (player)
+ {
+ case 0:
+ cpuStrums.add(babyArrow);
+ case 1:
+ playerStrums.add(babyArrow);
+ }
+
+ babyArrow.animation.play('static');
+ babyArrow.x += 50;
+ babyArrow.x += ((FlxG.width / 2) * player);
+
+ cpuStrums.forEach(function(spr:FlxSprite)
+ {
+ spr.centerOffsets(); //CPU arrows start out slightly off-center
+ });
+
+ strumLineNotes.add(babyArrow);
+ }
+ }
+
+ function tweenCamIn():Void
+ {
+ FlxTween.tween(FlxG.camera, {zoom: 1.3}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut});
+ }
+
+ override function openSubState(SubState:FlxSubState)
+ {
+ if (paused)
+ {
+ if (FlxG.sound.music != null)
+ {
+ FlxG.sound.music.pause();
+ vocals.pause();
+ }
+
+ #if windows
+ DiscordClient.changePresence("PAUSED on " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "Acc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC);
+ #end
+ if (!startTimer.finished)
+ startTimer.active = false;
+ }
+
+ super.openSubState(SubState);
+ }
+
+ override function closeSubState()
+ {
+ if (paused)
+ {
+ if (FlxG.sound.music != null && !startingSong)
+ {
+ resyncVocals();
+ }
+
+ if (!startTimer.finished)
+ startTimer.active = true;
+ paused = false;
+
+ #if windows
+ if (startTimer.finished)
+ {
+ DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses, iconRPC, true, songLength - Conductor.songPosition);
+ }
+ else
+ {
+ DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), iconRPC);
+ }
+ #end
+ }
+
+ super.closeSubState();
+ }
+
+
+ function resyncVocals():Void
+ {
+ vocals.pause();
+
+ FlxG.sound.music.play();
+ Conductor.songPosition = FlxG.sound.music.time;
+ vocals.time = Conductor.songPosition;
+ vocals.play();
+
+ #if windows
+ DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC);
+ #end
+ }
+
+ private var paused:Bool = false;
+ var startedCountdown:Bool = false;
+ var canPause:Bool = true;
+ var nps:Int = 0;
+ var maxNPS:Int = 0;
+
+ public static var songRate = 1.5;
+
+ public var stopUpdate = false;
+ public var removedVideo = false;
+
+ override public function update(elapsed:Float)
+ {
+ #if !debug
+ perfectMode = false;
+ #end
+
+ if (PlayStateChangeables.botPlay && FlxG.keys.justPressed.ONE)
+ camHUD.visible = !camHUD.visible;
+
+
+ if (useVideo && GlobalVideo.get() != null && !stopUpdate)
+ {
+ if (GlobalVideo.get().ended && !removedVideo)
+ {
+ remove(videoSprite);
+ FlxG.stage.window.onFocusOut.remove(focusOut);
+ FlxG.stage.window.onFocusIn.remove(focusIn);
+ removedVideo = true;
+ }
+ }
+
+
+
+ #if windows
+ if (executeModchart && luaModchart != null && songStarted)
+ {
+ luaModchart.setVar('songPos',Conductor.songPosition);
+ luaModchart.setVar('hudZoom', camHUD.zoom);
+ luaModchart.setVar('cameraZoom',FlxG.camera.zoom);
+ luaModchart.executeState('update', [elapsed]);
+
+ for (i in luaWiggles)
+ {
+ trace('wiggle le gaming');
+ i.update(elapsed);
+ }
+
+ /*for (i in 0...strumLineNotes.length) {
+ var member = strumLineNotes.members[i];
+ member.x = luaModchart.getVar("strum" + i + "X", "float");
+ member.y = luaModchart.getVar("strum" + i + "Y", "float");
+ member.angle = luaModchart.getVar("strum" + i + "Angle", "float");
+ }*/
+
+ FlxG.camera.angle = luaModchart.getVar('cameraAngle', 'float');
+ camHUD.angle = luaModchart.getVar('camHudAngle','float');
+
+ if (luaModchart.getVar("showOnlyStrums",'bool'))
+ {
+ healthBarBG.visible = false;
+ kadeEngineWatermark.visible = false;
+ healthBar.visible = false;
+ iconP1.visible = false;
+ iconP2.visible = false;
+ scoreTxt.visible = false;
+ }
+ else
+ {
+ healthBarBG.visible = true;
+ kadeEngineWatermark.visible = true;
+ healthBar.visible = true;
+ iconP1.visible = true;
+ iconP2.visible = true;
+ scoreTxt.visible = true;
+ }
+
+ var p1 = luaModchart.getVar("strumLine1Visible",'bool');
+ var p2 = luaModchart.getVar("strumLine2Visible",'bool');
+
+ for (i in 0...4)
+ {
+ strumLineNotes.members[i].visible = p1;
+ if (i <= playerStrums.length)
+ playerStrums.members[i].visible = p2;
+ }
+ }
+
+ #end
+
+ // reverse iterate to remove oldest notes first and not invalidate the iteration
+ // stop iteration as soon as a note is not removed
+ // all notes should be kept in the correct order and this is optimal, safe to do every frame/update
+ {
+ var balls = notesHitArray.length-1;
+ while (balls >= 0)
+ {
+ var cock:Date = notesHitArray[balls];
+ if (cock != null && cock.getTime() + 1000 < Date.now().getTime())
+ notesHitArray.remove(cock);
+ else
+ balls = 0;
+ balls--;
+ }
+ nps = notesHitArray.length;
+ if (nps > maxNPS)
+ maxNPS = nps;
+ }
+
+ if (FlxG.keys.justPressed.NINE)
+ {
+ if (iconP1.animation.curAnim.name == 'bf-old')
+ iconP1.animation.play(SONG.player1);
+ else
+ iconP1.animation.play('bf-old');
+ }
+
+ switch (curStage)
+ {
+ case 'philly':
+ if (trainMoving)
+ {
+ trainFrameTiming += elapsed;
+
+ if (trainFrameTiming >= 1 / 24)
+ {
+ updateTrainPos();
+ trainFrameTiming = 0;
+ }
+ }
+ // phillyCityLights.members[curLight].alpha -= (Conductor.crochet / 1000) * FlxG.elapsed;
+ }
+
+ super.update(elapsed);
+
+ scoreTxt.text = Ratings.CalculateRanking(songScore,songScoreDef,nps,maxNPS,accuracy);
+
+ var lengthInPx = scoreTxt.textField.length * scoreTxt.frameHeight; // bad way but does more or less a better job
+
+ scoreTxt.x = (originalX - (lengthInPx / 2)) + 335;
+
+ if (FlxG.keys.justPressed.ENTER && startedCountdown && canPause)
+ {
+ persistentUpdate = false;
+ persistentDraw = true;
+ paused = true;
+
+ // 1 / 1000 chance for Gitaroo Man easter egg
+ if (FlxG.random.bool(0.1))
+ {
+ trace('GITAROO MAN EASTER EGG');
+ FlxG.switchState(new GitarooPause());
+ }
+ else
+ openSubState(new PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
+ }
+
+ if (FlxG.keys.justPressed.SEVEN)
+ {
+ if (useVideo)
+ {
+ GlobalVideo.get().stop();
+ remove(videoSprite);
+ FlxG.stage.window.onFocusOut.remove(focusOut);
+ FlxG.stage.window.onFocusIn.remove(focusIn);
+ removedVideo = true;
+ }
+ #if windows
+ DiscordClient.changePresence("Chart Editor", null, null, true);
+ #end
+ FlxG.switchState(new ChartingState());
+ #if windows
+ if (luaModchart != null)
+ {
+ luaModchart.die();
+ luaModchart = null;
+ }
+ #end
+ }
+
+ // FlxG.watch.addQuick('VOL', vocals.amplitudeLeft);
+ // FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight);
+
+ iconP1.setGraphicSize(Std.int(FlxMath.lerp(150, iconP1.width, 0.50)));
+ iconP2.setGraphicSize(Std.int(FlxMath.lerp(150, iconP2.width, 0.50)));
+
+ iconP1.updateHitbox();
+ iconP2.updateHitbox();
+
+ var iconOffset:Int = 26;
+
+ iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01) - iconOffset);
+ iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01)) - (iconP2.width - iconOffset);
+
+ if (health > 2)
+ health = 2;
+ if (healthBar.percent < 20)
+ iconP1.animation.curAnim.curFrame = 1;
+ else
+ iconP1.animation.curAnim.curFrame = 0;
+
+ if (healthBar.percent > 80)
+ iconP2.animation.curAnim.curFrame = 1;
+ else
+ iconP2.animation.curAnim.curFrame = 0;
+
+ /* if (FlxG.keys.justPressed.NINE)
+ FlxG.switchState(new Charting()); */
+
+ #if debug
+ if (FlxG.keys.justPressed.SIX)
+ {
+ if (useVideo)
+ {
+ GlobalVideo.get().stop();
+ remove(videoSprite);
+ FlxG.stage.window.onFocusOut.remove(focusOut);
+ FlxG.stage.window.onFocusIn.remove(focusIn);
+ removedVideo = true;
+ }
+
+ FlxG.switchState(new AnimationDebug(SONG.player2));
+ #if windows
+ if (luaModchart != null)
+ {
+ luaModchart.die();
+ luaModchart = null;
+ }
+ #end
+ }
+
+ if (FlxG.keys.justPressed.ZERO)
+ {
+ FlxG.switchState(new AnimationDebug(SONG.player1));
+ #if windows
+ if (luaModchart != null)
+ {
+ luaModchart.die();
+ luaModchart = null;
+ }
+ #end
+ }
+
+ #end
+
+ if (startingSong)
+ {
+ if (startedCountdown)
+ {
+ Conductor.songPosition += FlxG.elapsed * 1000;
+ if (Conductor.songPosition >= 0)
+ startSong();
+ }
+ }
+ else
+ {
+ // Conductor.songPosition = FlxG.sound.music.time;
+ Conductor.songPosition += FlxG.elapsed * 1000;
+ /*@:privateAccess
+ {
+ FlxG.sound.music._channel.
+ }*/
+ songPositionBar = Conductor.songPosition;
+
+ if (!paused)
+ {
+ songTime += FlxG.game.ticks - previousFrameTime;
+ previousFrameTime = FlxG.game.ticks;
+
+ // Interpolation type beat
+ if (Conductor.lastSongPos != Conductor.songPosition)
+ {
+ songTime = (songTime + Conductor.songPosition) / 2;
+ Conductor.lastSongPos = Conductor.songPosition;
+ // Conductor.songPosition += FlxG.elapsed * 1000;
+ // trace('MISSED FRAME');
+ }
+ }
+
+ // Conductor.lastSongPos = FlxG.sound.music.time;
+ }
+
+ if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null)
+ {
+ // Make sure Girlfriend cheers only for certain songs
+ if(allowedToHeadbang)
+ {
+ // Don't animate GF if something else is already animating her (eg. train passing)
+ if(gf.animation.curAnim.name == 'danceLeft' || gf.animation.curAnim.name == 'danceRight' || gf.animation.curAnim.name == 'idle')
+ {
+ // Per song treatment since some songs will only have the 'Hey' at certain times
+ switch(curSong)
+ {
+ case 'Philly Nice':
+ {
+ // General duration of the song
+ if(curBeat < 250)
+ {
+ // Beats to skip or to stop GF from cheering
+ if(curBeat != 184 && curBeat != 216)
+ {
+ if(curBeat % 16 == 8)
+ {
+ // Just a garantee that it'll trigger just once
+ if(!triggeredAlready)
+ {
+ gf.playAnim('cheer');
+ triggeredAlready = true;
+ }
+ }else triggeredAlready = false;
+ }
+ }
+ }
+ case 'Bopeebo':
+ {
+ // Where it starts || where it ends
+ if(curBeat > 5 && curBeat < 130)
+ {
+ if(curBeat % 8 == 7)
+ {
+ if(!triggeredAlready)
+ {
+ gf.playAnim('cheer');
+ triggeredAlready = true;
+ }
+ }else triggeredAlready = false;
+ }
+ }
+ case 'Blammed':
+ {
+ if(curBeat > 30 && curBeat < 190)
+ {
+ if(curBeat < 90 || curBeat > 128)
+ {
+ if(curBeat % 4 == 2)
+ {
+ if(!triggeredAlready)
+ {
+ gf.playAnim('cheer');
+ triggeredAlready = true;
+ }
+ }else triggeredAlready = false;
+ }
+ }
+ }
+ case 'Cocoa':
+ {
+ if(curBeat < 170)
+ {
+ if(curBeat < 65 || curBeat > 130 && curBeat < 145)
+ {
+ if(curBeat % 16 == 15)
+ {
+ if(!triggeredAlready)
+ {
+ gf.playAnim('cheer');
+ triggeredAlready = true;
+ }
+ }else triggeredAlready = false;
+ }
+ }
+ }
+ case 'Eggnog':
+ {
+ if(curBeat > 10 && curBeat != 111 && curBeat < 220)
+ {
+ if(curBeat % 8 == 7)
+ {
+ if(!triggeredAlready)
+ {
+ gf.playAnim('cheer');
+ triggeredAlready = true;
+ }
+ }else triggeredAlready = false;
+ }
+ }
+ }
+ }
+ }
+
+ #if windows
+ if (luaModchart != null)
+ luaModchart.setVar("mustHit",PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection);
+ #end
+
+ if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection)
+ {
+ var offsetX = 0;
+ var offsetY = 0;
+ #if windows
+ if (luaModchart != null)
+ {
+ offsetX = luaModchart.getVar("followXOffset", "float");
+ offsetY = luaModchart.getVar("followYOffset", "float");
+ }
+ #end
+ camFollow.setPosition(dad.getMidpoint().x + 150 + offsetX, dad.getMidpoint().y - 100 + offsetY);
+ #if windows
+ if (luaModchart != null)
+ luaModchart.executeState('playerTwoTurn', []);
+ #end
+ // camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210);
+
+ switch (dad.curCharacter)
+ {
+ case 'mom':
+ camFollow.y = dad.getMidpoint().y;
+ case 'senpai':
+ camFollow.y = dad.getMidpoint().y - 430;
+ camFollow.x = dad.getMidpoint().x - 100;
+ case 'senpai-angry':
+ camFollow.y = dad.getMidpoint().y - 430;
+ camFollow.x = dad.getMidpoint().x - 100;
+ }
+
+ if (dad.curCharacter == 'mom')
+ vocals.volume = 1;
+ }
+
+ if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100)
+ {
+ var offsetX = 0;
+ var offsetY = 0;
+ #if windows
+ if (luaModchart != null)
+ {
+ offsetX = luaModchart.getVar("followXOffset", "float");
+ offsetY = luaModchart.getVar("followYOffset", "float");
+ }
+ #end
+ camFollow.setPosition(boyfriend.getMidpoint().x - 100 + offsetX, boyfriend.getMidpoint().y - 100 + offsetY);
+
+ #if windows
+ if (luaModchart != null)
+ luaModchart.executeState('playerOneTurn', []);
+ #end
+
+ switch (curStage)
+ {
+ case 'limo':
+ camFollow.x = boyfriend.getMidpoint().x - 300;
+ case 'mall':
+ camFollow.y = boyfriend.getMidpoint().y - 200;
+ case 'school':
+ camFollow.x = boyfriend.getMidpoint().x - 200;
+ camFollow.y = boyfriend.getMidpoint().y - 200;
+ case 'schoolEvil':
+ camFollow.x = boyfriend.getMidpoint().x - 200;
+ camFollow.y = boyfriend.getMidpoint().y - 200;
+ }
+ }
+ }
+
+ if (camZooming)
+ {
+ FlxG.camera.zoom = FlxMath.lerp(defaultCamZoom, FlxG.camera.zoom, 0.95);
+ camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95);
+ }
+
+ FlxG.watch.addQuick("beatShit", curBeat);
+ FlxG.watch.addQuick("stepShit", curStep);
+
+ if (curSong == 'Fresh')
+ {
+ switch (curBeat)
+ {
+ case 16:
+ camZooming = true;
+ gfSpeed = 2;
+ case 48:
+ gfSpeed = 1;
+ case 80:
+ gfSpeed = 2;
+ case 112:
+ gfSpeed = 1;
+ case 163:
+ // FlxG.sound.music.stop();
+ // FlxG.switchState(new TitleState());
+ }
+ }
+
+ if (curSong == 'Bopeebo')
+ {
+ switch (curBeat)
+ {
+ case 128, 129, 130:
+ vocals.volume = 0;
+ // FlxG.sound.music.stop();
+ // FlxG.switchState(new PlayState());
+ }
+ }
+
+ if (health <= 0)
+ {
+ boyfriend.stunned = true;
+
+ persistentUpdate = false;
+ persistentDraw = false;
+ paused = true;
+
+ vocals.stop();
+ FlxG.sound.music.stop();
+
+ openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
+
+ #if windows
+ // Game Over doesn't get his own variable because it's only used here
+ DiscordClient.changePresence("GAME OVER -- " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy),"\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC);
+ #end
+
+ // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
+ }
+ if (FlxG.save.data.resetButton)
+ {
+ if(FlxG.keys.justPressed.R)
+ {
+ boyfriend.stunned = true;
+
+ persistentUpdate = false;
+ persistentDraw = false;
+ paused = true;
+
+ vocals.stop();
+ FlxG.sound.music.stop();
+
+ openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
+
+ #if windows
+ // Game Over doesn't get his own variable because it's only used here
+ DiscordClient.changePresence("GAME OVER -- " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy),"\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC);
+ #end
+
+ // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
+ }
+ }
+
+ if (unspawnNotes[0] != null)
+ {
+ if (unspawnNotes[0].strumTime - Conductor.songPosition < 3500)
+ {
+ var dunceNote:Note = unspawnNotes[0];
+ notes.add(dunceNote);
+
+ var index:Int = unspawnNotes.indexOf(dunceNote);
+ unspawnNotes.splice(index, 1);
+ }
+ }
+
+ if (generatedMusic)
+ {
+ notes.forEachAlive(function(daNote:Note)
+ {
+
+ // instead of doing stupid y > FlxG.height
+ // we be men and actually calculate the time :)
+ if (daNote.tooLate)
+ {
+ daNote.active = false;
+ daNote.visible = false;
+ }
+ else
+ {
+ daNote.visible = true;
+ daNote.active = true;
+ }
+
+ if (!daNote.modifiedByLua)
+ {
+ if (PlayStateChangeables.useDownscroll)
+ {
+ if (daNote.mustPress)
+ daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2));
+ else
+ daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2));
+ if(daNote.isSustainNote)
+ {
+ // Remember = minus makes notes go up, plus makes them go down
+ if(daNote.animation.curAnim.name.endsWith('end') && daNote.prevNote != null)
+ daNote.y += daNote.prevNote.height;
+ else
+ daNote.y += daNote.height / 2;
+
+ // If not in botplay, only clip sustain notes when properly hit, botplay gets to clip it everytime
+ if(!PlayStateChangeables.botPlay)
+ {
+ if((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit && !daNote.canBeHit) && daNote.y - daNote.offset.y * daNote.scale.y + daNote.height >= (strumLine.y + Note.swagWidth / 2))
+ {
+ // Clip to strumline
+ var swagRect = new FlxRect(0, 0, daNote.frameWidth * 2, daNote.frameHeight * 2);
+ swagRect.height = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y;
+ swagRect.y = daNote.frameHeight - swagRect.height;
+
+ daNote.clipRect = swagRect;
+ }
+ }else {
+ var swagRect = new FlxRect(0, 0, daNote.frameWidth * 2, daNote.frameHeight * 2);
+ swagRect.height = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y;
+ swagRect.y = daNote.frameHeight - swagRect.height;
+
+ daNote.clipRect = swagRect;
+ }
+ }
+ }else
+ {
+ if (daNote.mustPress)
+ daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2));
+ else
+ daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2));
+ if(daNote.isSustainNote)
+ {
+ daNote.y -= daNote.height / 2;
+
+ if(!PlayStateChangeables.botPlay)
+ {
+ if((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit && !daNote.canBeHit) && daNote.y + daNote.offset.y * daNote.scale.y <= (strumLine.y + Note.swagWidth / 2))
+ {
+ // Clip to strumline
+ var swagRect = new FlxRect(0, 0, daNote.width / daNote.scale.x, daNote.height / daNote.scale.y);
+ swagRect.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y;
+ swagRect.height -= swagRect.y;
+
+ daNote.clipRect = swagRect;
+ }
+ }else {
+ var swagRect = new FlxRect(0, 0, daNote.width / daNote.scale.x, daNote.height / daNote.scale.y);
+ swagRect.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y;
+ swagRect.height -= swagRect.y;
+
+ daNote.clipRect = swagRect;
+ }
+ }
+ }
+ }
+
+
+ if (!daNote.mustPress && daNote.wasGoodHit)
+ {
+ if (SONG.song != 'Tutorial')
+ camZooming = true;
+
+ var altAnim:String = "";
+
+ if (SONG.notes[Math.floor(curStep / 16)] != null)
+ {
+ if (SONG.notes[Math.floor(curStep / 16)].altAnim)
+ altAnim = '-alt';
+ }
+
+ switch (Math.abs(daNote.noteData))
+ {
+ case 2:
+ dad.playAnim('singUP' + altAnim, true);
+ case 3:
+ dad.playAnim('singRIGHT' + altAnim, true);
+ case 1:
+ dad.playAnim('singDOWN' + altAnim, true);
+ case 0:
+ dad.playAnim('singLEFT' + altAnim, true);
+ }
+
+ if (FlxG.save.data.cpuStrums)
+ {
+ cpuStrums.forEach(function(spr:FlxSprite)
+ {
+ if (Math.abs(daNote.noteData) == spr.ID)
+ {
+ spr.animation.play('confirm', true);
+ }
+ if (spr.animation.curAnim.name == 'confirm' && !curStage.startsWith('school'))
+ {
+ spr.centerOffsets();
+ spr.offset.x -= 13;
+ spr.offset.y -= 13;
+ }
+ else
+ spr.centerOffsets();
+ });
+ }
+
+ #if windows
+ if (luaModchart != null)
+ luaModchart.executeState('playerTwoSing', [Math.abs(daNote.noteData), Conductor.songPosition]);
+ #end
+
+ dad.holdTimer = 0;
+
+ if (SONG.needsVoices)
+ vocals.volume = 1;
+
+ daNote.active = false;
+
+
+ daNote.kill();
+ notes.remove(daNote, true);
+ daNote.destroy();
+ }
+
+ if (daNote.mustPress && !daNote.modifiedByLua)
+ {
+ daNote.visible = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].visible;
+ daNote.x = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].x;
+ if (!daNote.isSustainNote)
+ daNote.angle = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].angle;
+ daNote.alpha = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].alpha;
+ }
+ else if (!daNote.wasGoodHit && !daNote.modifiedByLua)
+ {
+ daNote.visible = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].visible;
+ daNote.x = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].x;
+ if (!daNote.isSustainNote)
+ daNote.angle = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].angle;
+ daNote.alpha = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].alpha;
+ }
+
+
+
+ if (daNote.isSustainNote)
+ daNote.x += daNote.width / 2 + 17;
+
+
+ //trace(daNote.y);
+ // WIP interpolation shit? Need to fix the pause issue
+ // daNote.y = (strumLine.y - (songTime - daNote.strumTime) * (0.45 * PlayState.SONG.speed));
+
+ if ((daNote.mustPress && daNote.tooLate && !PlayStateChangeables.useDownscroll || daNote.mustPress && daNote.tooLate && PlayStateChangeables.useDownscroll) && daNote.mustPress)
+ {
+ if (daNote.isSustainNote && daNote.wasGoodHit)
+ {
+ daNote.kill();
+ notes.remove(daNote, true);
+ }
+ else
+ {
+ if (loadRep && daNote.isSustainNote)
+ {
+ // im tired and lazy this sucks I know i'm dumb
+ if (findByTime(daNote.strumTime) != null)
+ totalNotesHit += 1;
+ else
+ {
+ health -= 0.075;
+ vocals.volume = 0;
+ if (theFunne)
+ noteMiss(daNote.noteData, daNote);
+ }
+ }
+ else
+ {
+ health -= 0.075;
+ vocals.volume = 0;
+ if (theFunne)
+ noteMiss(daNote.noteData, daNote);
+ }
+ }
+
+ daNote.visible = false;
+ daNote.kill();
+ notes.remove(daNote, true);
+ }
+
+ });
+ }
+
+ if (FlxG.save.data.cpuStrums)
+ {
+ cpuStrums.forEach(function(spr:FlxSprite)
+ {
+ if (spr.animation.finished)
+ {
+ spr.animation.play('static');
+ spr.centerOffsets();
+ }
+ });
+ }
+
+ if (!inCutscene)
+ keyShit();
+
+
+ #if debug
+ if (FlxG.keys.justPressed.ONE)
+ endSong();
+ #end
+ }
+
+ function endSong():Void
+ {
+ if (useVideo)
+ {
+ GlobalVideo.get().stop();
+ FlxG.stage.window.onFocusOut.remove(focusOut);
+ FlxG.stage.window.onFocusIn.remove(focusIn);
+ PlayState.instance.remove(PlayState.instance.videoSprite);
+ }
+
+ if (isStoryMode)
+ campaignMisses = misses;
+
+ if (!loadRep)
+ rep.SaveReplay(saveNotes, saveJudge, replayAna);
+ else
+ {
+ PlayStateChangeables.botPlay = false;
+ PlayStateChangeables.scrollSpeed = 1;
+ PlayStateChangeables.useDownscroll = false;
+ }
+
+ if (FlxG.save.data.fpsCap > 290)
+ (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290);
+
+ #if windows
+ if (luaModchart != null)
+ {
+ luaModchart.die();
+ luaModchart = null;
+ }
+ #end
+
+ canPause = false;
+ FlxG.sound.music.volume = 0;
+ vocals.volume = 0;
+ FlxG.sound.music.pause();
+ vocals.pause();
+ if (SONG.validScore)
+ {
+ // adjusting the highscore song name to be compatible
+ // would read original scores if we didn't change packages
+ var songHighscore = StringTools.replace(PlayState.SONG.song, " ", "-");
+ switch (songHighscore) {
+ case 'Dad-Battle': songHighscore = 'Dadbattle';
+ case 'Philly-Nice': songHighscore = 'Philly';
+ }
+
+ #if !switch
+ Highscore.saveScore(songHighscore, Math.round(songScore), storyDifficulty);
+ Highscore.saveCombo(songHighscore, Ratings.GenerateLetterRank(accuracy), storyDifficulty);
+ #end
+ }
+
+ if (offsetTesting)
+ {
+ FlxG.sound.playMusic(Paths.music('freakyMenu'));
+ offsetTesting = false;
+ LoadingState.loadAndSwitchState(new OptionsMenu());
+ FlxG.save.data.offset = offsetTest;
+ }
+ else
+ {
+ if (isStoryMode)
+ {
+ campaignScore += Math.round(songScore);
+
+ storyPlaylist.remove(storyPlaylist[0]);
+
+ if (storyPlaylist.length <= 0)
+ {
+ transIn = FlxTransitionableState.defaultTransIn;
+ transOut = FlxTransitionableState.defaultTransOut;
+
+ paused = true;
+
+ FlxG.sound.music.stop();
+ vocals.stop();
+ if (FlxG.save.data.scoreScreen)
+ openSubState(new ResultsScreen());
+ else
+ {
+ FlxG.sound.playMusic(Paths.music('freakyMenu'));
+ FlxG.switchState(new MainMenuState());
+ }
+
+ #if windows
+ if (luaModchart != null)
+ {
+ luaModchart.die();
+ luaModchart = null;
+ }
+ #end
+
+ // if ()
+ StoryMenuState.weekUnlocked[Std.int(Math.min(storyWeek + 1, StoryMenuState.weekUnlocked.length - 1))] = true;
+
+ if (SONG.validScore)
+ {
+ NGio.unlockMedal(60961);
+ Highscore.saveWeekScore(storyWeek, campaignScore, storyDifficulty);
+ }
+
+ FlxG.save.data.weekUnlocked = StoryMenuState.weekUnlocked;
+ FlxG.save.flush();
+ }
+ else
+ {
+
+ // adjusting the song name to be compatible
+ var songFormat = StringTools.replace(PlayState.storyPlaylist[0], " ", "-");
+ switch (songFormat) {
+ case 'Dad-Battle': songFormat = 'Dadbattle';
+ case 'Philly-Nice': songFormat = 'Philly';
+ }
+
+ var poop:String = Highscore.formatSong(songFormat, storyDifficulty);
+
+ trace('LOADING NEXT SONG');
+ trace(poop);
+
+ if (StringTools.replace(PlayState.storyPlaylist[0], " ", "-").toLowerCase() == 'eggnog')
+ {
+ var blackShit:FlxSprite = new FlxSprite(-FlxG.width * FlxG.camera.zoom,
+ -FlxG.height * FlxG.camera.zoom).makeGraphic(FlxG.width * 3, FlxG.height * 3, FlxColor.BLACK);
+ blackShit.scrollFactor.set();
+ add(blackShit);
+ camHUD.visible = false;
+
+ FlxG.sound.play(Paths.sound('Lights_Shut_off'));
+ }
+
+ FlxTransitionableState.skipNextTransIn = true;
+ FlxTransitionableState.skipNextTransOut = true;
+ prevCamFollow = camFollow;
+
+
+ PlayState.SONG = Song.loadFromJson(poop, PlayState.storyPlaylist[0]);
+ FlxG.sound.music.stop();
+
+ LoadingState.loadAndSwitchState(new PlayState());
+ }
+ }
+ else
+ {
+ trace('WENT BACK TO FREEPLAY??');
+
+ paused = true;
+
+
+ FlxG.sound.music.stop();
+ vocals.stop();
+
+ if (FlxG.save.data.scoreScreen)
+ openSubState(new ResultsScreen());
+ else
+ FlxG.switchState(new FreeplayState());
+ }
+ }
+ }
+
+
+ var endingSong:Bool = false;
+
+ var hits:Array = [];
+ var offsetTest:Float = 0;
+
+ var timeShown = 0;
+ var currentTimingShown:FlxText = null;
+
+ private function popUpScore(daNote:Note):Void
+ {
+ var noteDiff:Float = -(daNote.strumTime - Conductor.songPosition);
+ var wife:Float = EtternaFunctions.wife3(-noteDiff, Conductor.timeScale);
+ // boyfriend.playAnim('hey');
+ vocals.volume = 1;
+ var placement:String = Std.string(combo);
+
+ var coolText:FlxText = new FlxText(0, 0, 0, placement, 32);
+ coolText.screenCenter();
+ coolText.x = FlxG.width * 0.55;
+ coolText.y -= 350;
+ coolText.cameras = [camHUD];
+ //
+
+ var rating:FlxSprite = new FlxSprite();
+ var score:Float = 350;
+
+ if (FlxG.save.data.accuracyMod == 1)
+ totalNotesHit += wife;
+
+ var daRating = daNote.rating;
+
+ switch(daRating)
+ {
+ case 'shit':
+ score = -300;
+ combo = 0;
+ misses++;
+ health -= 0.2;
+ ss = false;
+ shits++;
+ if (FlxG.save.data.accuracyMod == 0)
+ totalNotesHit += 0.25;
+ case 'bad':
+ daRating = 'bad';
+ score = 0;
+ health -= 0.06;
+ ss = false;
+ bads++;
+ if (FlxG.save.data.accuracyMod == 0)
+ totalNotesHit += 0.50;
+ case 'good':
+ daRating = 'good';
+ score = 200;
+ ss = false;
+ goods++;
+ if (health < 2)
+ health += 0.04;
+ if (FlxG.save.data.accuracyMod == 0)
+ totalNotesHit += 0.75;
+ case 'sick':
+ if (health < 2)
+ health += 0.1;
+ if (FlxG.save.data.accuracyMod == 0)
+ totalNotesHit += 1;
+ sicks++;
+ }
+
+ // trace('Wife accuracy loss: ' + wife + ' | Rating: ' + daRating + ' | Score: ' + score + ' | Weight: ' + (1 - wife));
+
+ if (daRating != 'shit' || daRating != 'bad')
+ {
+
+
+ songScore += Math.round(score);
+ songScoreDef += Math.round(ConvertScore.convertScore(noteDiff));
+
+ /* if (combo > 60)
+ daRating = 'sick';
+ else if (combo > 12)
+ daRating = 'good'
+ else if (combo > 4)
+ daRating = 'bad';
+ */
+
+ var pixelShitPart1:String = "";
+ var pixelShitPart2:String = '';
+
+ if (curStage.startsWith('school'))
+ {
+ pixelShitPart1 = 'weeb/pixelUI/';
+ pixelShitPart2 = '-pixel';
+ }
+
+ rating.loadGraphic(Paths.image(pixelShitPart1 + daRating + pixelShitPart2));
+ rating.screenCenter();
+ rating.y -= 50;
+ rating.x = coolText.x - 125;
+
+ if (FlxG.save.data.changedHit)
+ {
+ rating.x = FlxG.save.data.changedHitX;
+ rating.y = FlxG.save.data.changedHitY;
+ }
+ rating.acceleration.y = 550;
+ rating.velocity.y -= FlxG.random.int(140, 175);
+ rating.velocity.x -= FlxG.random.int(0, 10);
+
+ var msTiming = HelperFunctions.truncateFloat(noteDiff, 3);
+ if(PlayStateChangeables.botPlay && !loadRep) msTiming = 0;
+
+ if (loadRep)
+ msTiming = HelperFunctions.truncateFloat(findByTime(daNote.strumTime)[3], 3);
+
+ if (currentTimingShown != null)
+ remove(currentTimingShown);
+
+ currentTimingShown = new FlxText(0,0,0,"0ms");
+ timeShown = 0;
+ switch(daRating)
+ {
+ case 'shit' | 'bad':
+ currentTimingShown.color = FlxColor.RED;
+ case 'good':
+ currentTimingShown.color = FlxColor.GREEN;
+ case 'sick':
+ currentTimingShown.color = FlxColor.CYAN;
+ }
+ currentTimingShown.borderStyle = OUTLINE;
+ currentTimingShown.borderSize = 1;
+ currentTimingShown.borderColor = FlxColor.BLACK;
+ currentTimingShown.text = msTiming + "ms";
+ currentTimingShown.size = 20;
+
+ if (msTiming >= 0.03 && offsetTesting)
+ {
+ //Remove Outliers
+ hits.shift();
+ hits.shift();
+ hits.shift();
+ hits.pop();
+ hits.pop();
+ hits.pop();
+ hits.push(msTiming);
+
+ var total = 0.0;
+
+ for(i in hits)
+ total += i;
+
+
+
+ offsetTest = HelperFunctions.truncateFloat(total / hits.length,2);
+ }
+
+ if (currentTimingShown.alpha != 1)
+ currentTimingShown.alpha = 1;
+
+ if(!PlayStateChangeables.botPlay || loadRep) add(currentTimingShown);
+
+ var comboSpr:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'combo' + pixelShitPart2));
+ comboSpr.screenCenter();
+ comboSpr.x = rating.x;
+ comboSpr.y = rating.y + 100;
+ comboSpr.acceleration.y = 600;
+ comboSpr.velocity.y -= 150;
+
+ currentTimingShown.screenCenter();
+ currentTimingShown.x = comboSpr.x + 100;
+ currentTimingShown.y = rating.y + 100;
+ currentTimingShown.acceleration.y = 600;
+ currentTimingShown.velocity.y -= 150;
+
+ comboSpr.velocity.x += FlxG.random.int(1, 10);
+ currentTimingShown.velocity.x += comboSpr.velocity.x;
+ if(!PlayStateChangeables.botPlay || loadRep) add(rating);
+
+ if (!curStage.startsWith('school'))
+ {
+ rating.setGraphicSize(Std.int(rating.width * 0.7));
+ rating.antialiasing = true;
+ comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7));
+ comboSpr.antialiasing = true;
+ }
+ else
+ {
+ rating.setGraphicSize(Std.int(rating.width * daPixelZoom * 0.7));
+ comboSpr.setGraphicSize(Std.int(comboSpr.width * daPixelZoom * 0.7));
+ }
+
+ currentTimingShown.updateHitbox();
+ comboSpr.updateHitbox();
+ rating.updateHitbox();
+
+ currentTimingShown.cameras = [camHUD];
+ comboSpr.cameras = [camHUD];
+ rating.cameras = [camHUD];
+
+ var seperatedScore:Array = [];
+
+ var comboSplit:Array = (combo + "").split('');
+
+ if (combo > highestCombo)
+ highestCombo = combo;
+
+ // make sure we have 3 digits to display (looks weird otherwise lol)
+ if (comboSplit.length == 1)
+ {
+ seperatedScore.push(0);
+ seperatedScore.push(0);
+ }
+ else if (comboSplit.length == 2)
+ seperatedScore.push(0);
+
+ for(i in 0...comboSplit.length)
+ {
+ var str:String = comboSplit[i];
+ seperatedScore.push(Std.parseInt(str));
+ }
+
+ var daLoop:Int = 0;
+ for (i in seperatedScore)
+ {
+ var numScore:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'num' + Std.int(i) + pixelShitPart2));
+ numScore.screenCenter();
+ numScore.x = rating.x + (43 * daLoop) - 50;
+ numScore.y = rating.y + 100;
+ numScore.cameras = [camHUD];
+
+ if (!curStage.startsWith('school'))
+ {
+ numScore.antialiasing = true;
+ numScore.setGraphicSize(Std.int(numScore.width * 0.5));
+ }
+ else
+ {
+ numScore.setGraphicSize(Std.int(numScore.width * daPixelZoom));
+ }
+ numScore.updateHitbox();
+
+ numScore.acceleration.y = FlxG.random.int(200, 300);
+ numScore.velocity.y -= FlxG.random.int(140, 160);
+ numScore.velocity.x = FlxG.random.float(-5, 5);
+
+ add(numScore);
+
+ FlxTween.tween(numScore, {alpha: 0}, 0.2, {
+ onComplete: function(tween:FlxTween)
+ {
+ numScore.destroy();
+ },
+ startDelay: Conductor.crochet * 0.002
+ });
+
+ daLoop++;
+ }
+ /*
+ trace(combo);
+ trace(seperatedScore);
+ */
+
+ coolText.text = Std.string(seperatedScore);
+ // add(coolText);
+
+ FlxTween.tween(rating, {alpha: 0}, 0.2, {
+ startDelay: Conductor.crochet * 0.001,
+ onUpdate: function(tween:FlxTween)
+ {
+ if (currentTimingShown != null)
+ currentTimingShown.alpha -= 0.02;
+ timeShown++;
+ }
+ });
+
+ FlxTween.tween(comboSpr, {alpha: 0}, 0.2, {
+ onComplete: function(tween:FlxTween)
+ {
+ coolText.destroy();
+ comboSpr.destroy();
+ if (currentTimingShown != null && timeShown >= 20)
+ {
+ remove(currentTimingShown);
+ currentTimingShown = null;
+ }
+ rating.destroy();
+ },
+ startDelay: Conductor.crochet * 0.001
+ });
+
+ curSection += 1;
+ }
+ }
+
+ public function NearlyEquals(value1:Float, value2:Float, unimportantDifference:Float = 10):Bool
+ {
+ return Math.abs(FlxMath.roundDecimal(value1, 1) - FlxMath.roundDecimal(value2, 1)) < unimportantDifference;
+ }
+
+ var upHold:Bool = false;
+ var downHold:Bool = false;
+ var rightHold:Bool = false;
+ var leftHold:Bool = false;
+
+ private function keyShit():Void // I've invested in emma stocks
+ {
+ // control arrays, order L D R U
+ var holdArray:Array = [controls.LEFT, controls.DOWN, controls.UP, controls.RIGHT];
+ var pressArray:Array = [
+ controls.LEFT_P,
+ controls.DOWN_P,
+ controls.UP_P,
+ controls.RIGHT_P
+ ];
+ var releaseArray:Array = [
+ controls.LEFT_R,
+ controls.DOWN_R,
+ controls.UP_R,
+ controls.RIGHT_R
+ ];
+ #if windows
+ if (luaModchart != null){
+ if (controls.LEFT_P){luaModchart.executeState('keyPressed',["left"]);};
+ if (controls.DOWN_P){luaModchart.executeState('keyPressed',["down"]);};
+ if (controls.UP_P){luaModchart.executeState('keyPressed',["up"]);};
+ if (controls.RIGHT_P){luaModchart.executeState('keyPressed',["right"]);};
+ };
+ #end
+
+
+ // Prevent player input if botplay is on
+ if(PlayStateChangeables.botPlay)
+ {
+ holdArray = [false, false, false, false];
+ pressArray = [false, false, false, false];
+ releaseArray = [false, false, false, false];
+ }
+
+ var anas:Array = [null,null,null,null];
+
+ for (i in 0...pressArray.length)
+ if (pressArray[i])
+ anas[i] = new Ana(Conductor.songPosition, null, false, "miss", i);
+
+ // HOLDS, check for sustain notes
+ if (holdArray.contains(true) && /*!boyfriend.stunned && */ generatedMusic)
+ {
+ notes.forEachAlive(function(daNote:Note)
+ {
+ if (daNote.isSustainNote && daNote.canBeHit && daNote.mustPress && holdArray[daNote.noteData])
+ goodNoteHit(daNote);
+ });
+ }
+
+ // PRESSES, check for note hits
+ if (pressArray.contains(true) && /*!boyfriend.stunned && */ generatedMusic)
+ {
+ boyfriend.holdTimer = 0;
+
+ var possibleNotes:Array = []; // notes that can be hit
+ var directionList:Array = []; // directions that can be hit
+ var dumbNotes:Array = []; // notes to kill later
+ var directionsAccounted:Array = [false,false,false,false]; // we don't want to do judgments for more than one presses
+
+ notes.forEachAlive(function(daNote:Note)
+ {
+ if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit)
+ {
+ if (!directionsAccounted[daNote.noteData])
+ {
+ directionsAccounted[daNote.noteData] = true;
+ possibleNotes.push(daNote);
+ directionList.push(daNote.noteData);
+ }
+ }
+ });
+
+ for (note in dumbNotes)
+ {
+ FlxG.log.add("killing dumb ass note at " + note.strumTime);
+ note.kill();
+ notes.remove(note, true);
+ note.destroy();
+ }
+
+ possibleNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime));
+
+ if (perfectMode)
+ goodNoteHit(possibleNotes[0]);
+ else if (possibleNotes.length > 0)
+ {
+ if (!FlxG.save.data.ghost)
+ {
+ for (shit in 0...pressArray.length)
+ { // if a direction is hit that shouldn't be
+ if (pressArray[shit] && !directionList.contains(shit))
+ noteMiss(shit, null);
+ }
+ }
+ for (coolNote in possibleNotes)
+ {
+ if (pressArray[coolNote.noteData])
+ {
+ if (mashViolations != 0)
+ mashViolations--;
+ scoreTxt.color = FlxColor.WHITE;
+ var noteDiff:Float = -(coolNote.strumTime - Conductor.songPosition);
+ anas[coolNote.noteData].hit = true;
+ anas[coolNote.noteData].hitJudge = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000));
+ anas[coolNote.noteData].nearestNote = [coolNote.strumTime,coolNote.noteData,coolNote.sustainLength];
+ goodNoteHit(coolNote);
+ }
+ }
+ }
+ else if (!FlxG.save.data.ghost)
+ {
+ for (shit in 0...pressArray.length)
+ if (pressArray[shit])
+ noteMiss(shit, null);
+ }
+
+ }
+
+ if (!loadRep)
+ for (i in anas)
+ if (i != null)
+ replayAna.anaArray.push(i); // put em all there
+
+ notes.forEachAlive(function(daNote:Note)
+ {
+ if(PlayStateChangeables.useDownscroll && daNote.y > strumLine.y ||
+ !PlayStateChangeables.useDownscroll && daNote.y < strumLine.y)
+ {
+ // Force good note hit regardless if it's too late to hit it or not as a fail safe
+ if(PlayStateChangeables.botPlay && daNote.canBeHit && daNote.mustPress ||
+ PlayStateChangeables.botPlay && daNote.tooLate && daNote.mustPress)
+ {
+ if(loadRep)
+ {
+ //trace('ReplayNote ' + tmpRepNote.strumtime + ' | ' + tmpRepNote.direction);
+ var n = findByTime(daNote.strumTime);
+ trace(n);
+ if(n != null)
+ {
+ goodNoteHit(daNote);
+ boyfriend.holdTimer = daNote.sustainLength;
+ }
+ }else {
+ goodNoteHit(daNote);
+ boyfriend.holdTimer = daNote.sustainLength;
+ }
+ }
+ }
+ });
+
+ if (boyfriend.holdTimer > Conductor.stepCrochet * 4 * 0.001 && (!holdArray.contains(true) || PlayStateChangeables.botPlay))
+ {
+ if (boyfriend.animation.curAnim.name.startsWith('sing') && !boyfriend.animation.curAnim.name.endsWith('miss'))
+ boyfriend.playAnim('idle');
+ }
+
+ playerStrums.forEach(function(spr:FlxSprite)
+ {
+ if (pressArray[spr.ID] && spr.animation.curAnim.name != 'confirm')
+ spr.animation.play('pressed');
+ if (!holdArray[spr.ID])
+ spr.animation.play('static');
+
+ if (spr.animation.curAnim.name == 'confirm' && !curStage.startsWith('school'))
+ {
+ spr.centerOffsets();
+ spr.offset.x -= 13;
+ spr.offset.y -= 13;
+ }
+ else
+ spr.centerOffsets();
+ });
+ }
+
+ public function findByTime(time:Float):Array
+ {
+ for (i in rep.replay.songNotes)
+ {
+ //trace('checking ' + Math.round(i[0]) + ' against ' + Math.round(time));
+ if (i[0] == time)
+ return i;
+ }
+ return null;
+ }
+
+ public function findByTimeIndex(time:Float):Int
+ {
+ for (i in 0...rep.replay.songNotes.length)
+ {
+ //trace('checking ' + Math.round(i[0]) + ' against ' + Math.round(time));
+ if (rep.replay.songNotes[i][0] == time)
+ return i;
+ }
+ return -1;
+ }
+
+ public var fuckingVolume:Float = 1;
+ public var useVideo = false;
+
+ public static var webmHandler:WebmHandler;
+
+ public var playingDathing = false;
+
+ public var videoSprite:FlxSprite;
+
+ public function focusOut() {
+ if (paused)
+ return;
+ persistentUpdate = false;
+ persistentDraw = true;
+ paused = true;
+
+ if (FlxG.sound.music != null)
+ {
+ FlxG.sound.music.pause();
+ vocals.pause();
+ }
+
+ openSubState(new PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
+ }
+ public function focusIn()
+ {
+ // nada
+ }
+
+
+ public function backgroundVideo(source:String) // for background videos
+ {
+ useVideo = true;
+
+ FlxG.stage.window.onFocusOut.add(focusOut);
+ FlxG.stage.window.onFocusIn.add(focusIn);
+
+ var ourSource:String = "assets/videos/daWeirdVid/dontDelete.webm";
+ WebmPlayer.SKIP_STEP_LIMIT = 90;
+ var str1:String = "WEBM SHIT";
+ webmHandler = new WebmHandler();
+ webmHandler.source(ourSource);
+ webmHandler.makePlayer();
+ webmHandler.webm.name = str1;
+
+ GlobalVideo.setWebm(webmHandler);
+
+ GlobalVideo.get().source(source);
+ GlobalVideo.get().clearPause();
+ if (GlobalVideo.isWebm)
+ {
+ GlobalVideo.get().updatePlayer();
+ }
+ GlobalVideo.get().show();
+
+ if (GlobalVideo.isWebm)
+ {
+ GlobalVideo.get().restart();
+ } else {
+ GlobalVideo.get().play();
+ }
+
+ var data = webmHandler.webm.bitmapData;
+
+ videoSprite = new FlxSprite(-470,-30).loadGraphic(data);
+
+ videoSprite.setGraphicSize(Std.int(videoSprite.width * 1.2));
+
+ remove(gf);
+ remove(boyfriend);
+ remove(dad);
+ add(videoSprite);
+ add(gf);
+ add(boyfriend);
+ add(dad);
+
+ trace('poggers');
+
+ if (!songStarted)
+ webmHandler.pause();
+ else
+ webmHandler.resume();
+ }
+
+ function noteMiss(direction:Int = 1, daNote:Note):Void
+ {
+ if (!boyfriend.stunned)
+ {
+ health -= 0.04;
+ if (combo > 5 && gf.animOffsets.exists('sad'))
+ {
+ gf.playAnim('sad');
+ }
+ combo = 0;
+ misses++;
+
+ if (daNote != null)
+ {
+ if (!loadRep)
+ {
+ saveNotes.push([daNote.strumTime,0,direction,166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166]);
+ saveJudge.push("miss");
+ }
+ }
+ else
+ if (!loadRep)
+ {
+ saveNotes.push([Conductor.songPosition,0,direction,166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166]);
+ saveJudge.push("miss");
+ }
+
+ //var noteDiff:Float = Math.abs(daNote.strumTime - Conductor.songPosition);
+ //var wife:Float = EtternaFunctions.wife3(noteDiff, FlxG.save.data.etternaMode ? 1 : 1.7);
+
+ if (FlxG.save.data.accuracyMod == 1)
+ totalNotesHit -= 1;
+
+ songScore -= 10;
+
+ FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2));
+ // FlxG.sound.play(Paths.sound('missnote1'), 1, false);
+ // FlxG.log.add('played imss note');
+
+ switch (direction)
+ {
+ case 0:
+ boyfriend.playAnim('singLEFTmiss', true);
+ case 1:
+ boyfriend.playAnim('singDOWNmiss', true);
+ case 2:
+ boyfriend.playAnim('singUPmiss', true);
+ case 3:
+ boyfriend.playAnim('singRIGHTmiss', true);
+ }
+
+ #if windows
+ if (luaModchart != null)
+ luaModchart.executeState('playerOneMiss', [direction, Conductor.songPosition]);
+ #end
+
+
+ updateAccuracy();
+ }
+ }
+
+ /*function badNoteCheck()
+ {
+ // just double pasting this shit cuz fuk u
+ // REDO THIS SYSTEM!
+ var upP = controls.UP_P;
+ var rightP = controls.RIGHT_P;
+ var downP = controls.DOWN_P;
+ var leftP = controls.LEFT_P;
+
+ if (leftP)
+ noteMiss(0);
+ if (upP)
+ noteMiss(2);
+ if (rightP)
+ noteMiss(3);
+ if (downP)
+ noteMiss(1);
+ updateAccuracy();
+ }
+ */
+ function updateAccuracy()
+ {
+ totalPlayed += 1;
+ accuracy = Math.max(0,totalNotesHit / totalPlayed * 100);
+ accuracyDefault = Math.max(0, totalNotesHitDefault / totalPlayed * 100);
+ }
+
+
+ function getKeyPresses(note:Note):Int
+ {
+ var possibleNotes:Array = []; // copypasted but you already know that
+
+ notes.forEachAlive(function(daNote:Note)
+ {
+ if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate)
+ {
+ possibleNotes.push(daNote);
+ possibleNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime));
+ }
+ });
+ if (possibleNotes.length == 1)
+ return possibleNotes.length + 1;
+ return possibleNotes.length;
+ }
+
+ var mashing:Int = 0;
+ var mashViolations:Int = 0;
+
+ var etternaModeScore:Int = 0;
+
+ function noteCheck(controlArray:Array, note:Note):Void // sorry lol
+ {
+ var noteDiff:Float = -(note.strumTime - Conductor.songPosition);
+
+ note.rating = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000));
+
+ /* if (loadRep)
+ {
+ if (controlArray[note.noteData])
+ goodNoteHit(note, false);
+ else if (rep.replay.keyPresses.length > repPresses && !controlArray[note.noteData])
+ {
+ if (NearlyEquals(note.strumTime,rep.replay.keyPresses[repPresses].time, 4))
+ {
+ goodNoteHit(note, false);
+ }
+ }
+ } */
+
+ if (controlArray[note.noteData])
+ {
+ goodNoteHit(note, (mashing > getKeyPresses(note)));
+
+ /*if (mashing > getKeyPresses(note) && mashViolations <= 2)
+ {
+ mashViolations++;
+
+ goodNoteHit(note, (mashing > getKeyPresses(note)));
+ }
+ else if (mashViolations > 2)
+ {
+ // this is bad but fuck you
+ playerStrums.members[0].animation.play('static');
+ playerStrums.members[1].animation.play('static');
+ playerStrums.members[2].animation.play('static');
+ playerStrums.members[3].animation.play('static');
+ health -= 0.4;
+ trace('mash ' + mashing);
+ if (mashing != 0)
+ mashing = 0;
+ }
+ else
+ goodNoteHit(note, false);*/
+
+ }
+ }
+
+ function goodNoteHit(note:Note, resetMashViolation = true):Void
+ {
+
+ if (mashing != 0)
+ mashing = 0;
+
+ var noteDiff:Float = -(note.strumTime - Conductor.songPosition);
+
+ if(loadRep)
+ {
+ noteDiff = findByTime(note.strumTime)[3];
+ note.rating = rep.replay.songJudgements[findByTimeIndex(note.strumTime)];
+ }
+ else
+ note.rating = Ratings.CalculateRating(noteDiff);
+
+ if (note.rating == "miss")
+ return;
+
+ // add newest note to front of notesHitArray
+ // the oldest notes are at the end and are removed first
+ if (!note.isSustainNote)
+ notesHitArray.unshift(Date.now());
+
+ if (!resetMashViolation && mashViolations >= 1)
+ mashViolations--;
+
+ if (mashViolations < 0)
+ mashViolations = 0;
+
+ if (!note.wasGoodHit)
+ {
+ if (!note.isSustainNote)
+ {
+ popUpScore(note);
+ combo += 1;
+ }
+ else
+ totalNotesHit += 1;
+
+
+ switch (note.noteData)
+ {
+ case 2:
+ boyfriend.playAnim('singUP', true);
+ case 3:
+ boyfriend.playAnim('singRIGHT', true);
+ case 1:
+ boyfriend.playAnim('singDOWN', true);
+ case 0:
+ boyfriend.playAnim('singLEFT', true);
+ }
+
+ #if windows
+ if (luaModchart != null)
+ luaModchart.executeState('playerOneSing', [note.noteData, Conductor.songPosition]);
+ #end
+
+
+ if(!loadRep && note.mustPress)
+ {
+ var array = [note.strumTime,note.sustainLength,note.noteData,noteDiff];
+ if (note.isSustainNote)
+ array[1] = -1;
+ trace('pushing ' + array[0]);
+ saveNotes.push(array);
+ saveJudge.push(note.rating);
+ }
+
+ playerStrums.forEach(function(spr:FlxSprite)
+ {
+ if (Math.abs(note.noteData) == spr.ID)
+ {
+ spr.animation.play('confirm', true);
+ }
+ });
+
+ note.wasGoodHit = true;
+ vocals.volume = 1;
+
+ note.kill();
+ notes.remove(note, true);
+ note.destroy();
+
+ updateAccuracy();
+ }
+ }
+
+
+ var fastCarCanDrive:Bool = true;
+
+ function resetFastCar():Void
+ {
+ if(FlxG.save.data.distractions){
+ fastCar.x = -12600;
+ fastCar.y = FlxG.random.int(140, 250);
+ fastCar.velocity.x = 0;
+ fastCarCanDrive = true;
+ }
+ }
+
+ function fastCarDrive()
+ {
+ if(FlxG.save.data.distractions){
+ FlxG.sound.play(Paths.soundRandom('carPass', 0, 1), 0.7);
+
+ fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3;
+ fastCarCanDrive = false;
+ new FlxTimer().start(2, function(tmr:FlxTimer)
+ {
+ resetFastCar();
+ });
+ }
+ }
+
+ var trainMoving:Bool = false;
+ var trainFrameTiming:Float = 0;
+
+ var trainCars:Int = 8;
+ var trainFinishing:Bool = false;
+ var trainCooldown:Int = 0;
+
+ function trainStart():Void
+ {
+ if(FlxG.save.data.distractions){
+ trainMoving = true;
+ if (!trainSound.playing)
+ trainSound.play(true);
+ }
+ }
+
+ var startedMoving:Bool = false;
+
+ function updateTrainPos():Void
+ {
+ if(FlxG.save.data.distractions){
+ if (trainSound.time >= 4700)
+ {
+ startedMoving = true;
+ gf.playAnim('hairBlow');
+ }
+
+ if (startedMoving)
+ {
+ phillyTrain.x -= 400;
+
+ if (phillyTrain.x < -2000 && !trainFinishing)
+ {
+ phillyTrain.x = -1150;
+ trainCars -= 1;
+
+ if (trainCars <= 0)
+ trainFinishing = true;
+ }
+
+ if (phillyTrain.x < -4000 && trainFinishing)
+ trainReset();
+ }
+ }
+
+ }
+
+ function trainReset():Void
+ {
+ if(FlxG.save.data.distractions){
+ gf.playAnim('hairFall');
+ phillyTrain.x = FlxG.width + 200;
+ trainMoving = false;
+ // trainSound.stop();
+ // trainSound.time = 0;
+ trainCars = 8;
+ trainFinishing = false;
+ startedMoving = false;
+ }
+ }
+
+ function lightningStrikeShit():Void
+ {
+ FlxG.sound.play(Paths.soundRandom('thunder_', 1, 2));
+ halloweenBG.animation.play('lightning');
+
+ lightningStrikeBeat = curBeat;
+ lightningOffset = FlxG.random.int(8, 24);
+
+ boyfriend.playAnim('scared', true);
+ gf.playAnim('scared', true);
+ }
+
+ var danced:Bool = false;
+
+ override function stepHit()
+ {
+ super.stepHit();
+ if (FlxG.sound.music.time > Conductor.songPosition + 20 || FlxG.sound.music.time < Conductor.songPosition - 20)
+ {
+ resyncVocals();
+ }
+
+ #if windows
+ if (executeModchart && luaModchart != null)
+ {
+ luaModchart.setVar('curStep',curStep);
+ luaModchart.executeState('stepHit',[curStep]);
+ }
+ #end
+
+ // yes this updates every step.
+ // yes this is bad
+ // but i'm doing it to update misses and accuracy
+ #if windows
+ // Song duration in a float, useful for the time left feature
+ songLength = FlxG.sound.music.length;
+
+ // Updating Discord Rich Presence (with Time Left)
+ DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "Acc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC,true, songLength - Conductor.songPosition);
+ #end
+
+ }
+
+ var lightningStrikeBeat:Int = 0;
+ var lightningOffset:Int = 8;
+
+ override function beatHit()
+ {
+ super.beatHit();
+
+ if (generatedMusic)
+ {
+ notes.sort(FlxSort.byY, (PlayStateChangeables.useDownscroll ? FlxSort.ASCENDING : FlxSort.DESCENDING));
+ }
+
+ #if windows
+ if (executeModchart && luaModchart != null)
+ {
+ luaModchart.setVar('curBeat',curBeat);
+ luaModchart.executeState('beatHit',[curBeat]);
+ }
+ #end
+
+ if (curSong == 'Tutorial' && dad.curCharacter == 'gf') {
+ if (curBeat % 2 == 1 && dad.animOffsets.exists('danceLeft'))
+ dad.playAnim('danceLeft');
+ if (curBeat % 2 == 0 && dad.animOffsets.exists('danceRight'))
+ dad.playAnim('danceRight');
+ }
+
+ if (SONG.notes[Math.floor(curStep / 16)] != null)
+ {
+ if (SONG.notes[Math.floor(curStep / 16)].changeBPM)
+ {
+ Conductor.changeBPM(SONG.notes[Math.floor(curStep / 16)].bpm);
+ FlxG.log.add('CHANGED BPM!');
+ }
+ // else
+ // Conductor.changeBPM(SONG.bpm);
+
+ // Dad doesnt interupt his own notes
+ if (SONG.notes[Math.floor(curStep / 16)].mustHitSection && dad.curCharacter != 'gf')
+ dad.dance();
+ }
+ // FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM);
+ wiggleShit.update(Conductor.crochet);
+
+ if (FlxG.save.data.camzoom)
+ {
+ // HARDCODING FOR MILF ZOOMS!
+ if (curSong.toLowerCase() == 'milf' && curBeat >= 168 && curBeat < 200 && camZooming && FlxG.camera.zoom < 1.35)
+ {
+ FlxG.camera.zoom += 0.015;
+ camHUD.zoom += 0.03;
+ }
+
+ if (camZooming && FlxG.camera.zoom < 1.35 && curBeat % 4 == 0)
+ {
+ FlxG.camera.zoom += 0.015;
+ camHUD.zoom += 0.03;
+ }
+
+ }
+
+ iconP1.setGraphicSize(Std.int(iconP1.width + 30));
+ iconP2.setGraphicSize(Std.int(iconP2.width + 30));
+
+ iconP1.updateHitbox();
+ iconP2.updateHitbox();
+
+ if (curBeat % gfSpeed == 0)
+ {
+ gf.dance();
+ }
+
+ if (!boyfriend.animation.curAnim.name.startsWith("sing"))
+ {
+ boyfriend.playAnim('idle');
+ }
+
+
+ if (curBeat % 8 == 7 && curSong == 'Bopeebo')
+ {
+ boyfriend.playAnim('hey', true);
+ }
+
+ if (curBeat % 16 == 15 && SONG.song == 'Tutorial' && dad.curCharacter == 'gf' && curBeat > 16 && curBeat < 48)
+ {
+ boyfriend.playAnim('hey', true);
+ dad.playAnim('cheer', true);
+ }
+
+ switch (curStage)
+ {
+ case 'school':
+ if(FlxG.save.data.distractions){
+ bgGirls.dance();
+ }
+
+ case 'mall':
+ if(FlxG.save.data.distractions){
+ upperBoppers.animation.play('bop', true);
+ bottomBoppers.animation.play('bop', true);
+ santa.animation.play('idle', true);
+ }
+
+ case 'limo':
+ if(FlxG.save.data.distractions){
+ grpLimoDancers.forEach(function(dancer:BackgroundDancer)
+ {
+ dancer.dance();
+ });
+
+ if (FlxG.random.bool(10) && fastCarCanDrive)
+ fastCarDrive();
+ }
+ case "philly":
+ if(FlxG.save.data.distractions){
+ if (!trainMoving)
+ trainCooldown += 1;
+
+ if (curBeat % 4 == 0)
+ {
+ phillyCityLights.forEach(function(light:FlxSprite)
+ {
+ light.visible = false;
+ });
+
+ curLight = FlxG.random.int(0, phillyCityLights.length - 1);
+
+ phillyCityLights.members[curLight].visible = true;
+ // phillyCityLights.members[curLight].alpha = 1;
+ }
+
+ }
+
+ if (curBeat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8)
+ {
+ if(FlxG.save.data.distractions){
+ trainCooldown = FlxG.random.int(-4, 0);
+ trainStart();
+ }
+ }
+ }
+
+ if (isHalloween && FlxG.random.bool(10) && curBeat > lightningStrikeBeat + lightningOffset)
+ {
+ if(FlxG.save.data.distractions){
+ lightningStrikeShit();
+ }
+ }
+ }
+
+ var curLight:Int = 0;
+}
diff --git a/source - Copy/PlayStateChangeables.hx b/source - Copy/PlayStateChangeables.hx
new file mode 100644
index 0000000..8ee4995
--- /dev/null
+++ b/source - Copy/PlayStateChangeables.hx
@@ -0,0 +1,7 @@
+class PlayStateChangeables
+{
+ public static var useDownscroll:Bool;
+ public static var safeFrames:Int;
+ public static var scrollSpeed:Float;
+ public static var botPlay:Bool;
+}
\ No newline at end of file
diff --git a/source - Copy/PlayerSettings.hx b/source - Copy/PlayerSettings.hx
new file mode 100644
index 0000000..44cddc5
--- /dev/null
+++ b/source - Copy/PlayerSettings.hx
@@ -0,0 +1,89 @@
+package;
+
+import Controls;
+import flixel.FlxCamera;
+import flixel.FlxG;
+import flixel.util.FlxSignal;
+
+// import ui.DeviceManager;
+// import props.Player;
+class PlayerSettings
+{
+ static public var numPlayers(default, null) = 0;
+ static public var numAvatars(default, null) = 0;
+ static public var player1(default, null):PlayerSettings;
+ static public var player2(default, null):PlayerSettings;
+
+ #if (haxe >= "4.0.0")
+ static public final onAvatarAdd = new FlxTypedSignalVoid>();
+ static public final onAvatarRemove = new FlxTypedSignalVoid>();
+ #else
+ static public var onAvatarAdd = new FlxTypedSignalVoid>();
+ static public var onAvatarRemove = new FlxTypedSignalVoid>();
+ #end
+
+ public var id(default, null):Int;
+
+ #if (haxe >= "4.0.0")
+ public final controls:Controls;
+ #else
+ public var controls:Controls;
+ #end
+
+ // public var avatar:Player;
+ // public var camera(get, never):PlayCamera;
+
+ function new(id, scheme)
+ {
+ this.id = id;
+ this.controls = new Controls('player$id', scheme);
+ }
+
+ public function setKeyboardScheme(scheme)
+ {
+ controls.setKeyboardScheme(scheme);
+ }
+
+ static public function init():Void
+ {
+ if (player1 == null)
+ {
+ player1 = new PlayerSettings(0, Solo);
+ ++numPlayers;
+ }
+
+ var numGamepads = FlxG.gamepads.numActiveGamepads;
+ if (numGamepads > 0)
+ {
+ var gamepad = FlxG.gamepads.getByID(0);
+ if (gamepad == null)
+ throw 'Unexpected null gamepad. id:0';
+
+ player1.controls.addDefaultGamepad(0);
+ }
+
+ if (numGamepads > 1)
+ {
+ if (player2 == null)
+ {
+ player2 = new PlayerSettings(1, None);
+ ++numPlayers;
+ }
+
+ var gamepad = FlxG.gamepads.getByID(1);
+ if (gamepad == null)
+ throw 'Unexpected null gamepad. id:0';
+
+ player2.controls.addDefaultGamepad(1);
+ }
+
+ // DeviceManager.init();
+ }
+
+ static public function reset()
+ {
+ player1 = null;
+ player2 = null;
+ numPlayers = 0;
+ }
+}
diff --git a/source - Copy/Ratings.hx b/source - Copy/Ratings.hx
new file mode 100644
index 0000000..758f8bf
--- /dev/null
+++ b/source - Copy/Ratings.hx
@@ -0,0 +1,151 @@
+import flixel.FlxG;
+
+class Ratings
+{
+ public static function GenerateLetterRank(accuracy:Float) // generate a letter ranking
+ {
+ var ranking:String = "N/A";
+ if(FlxG.save.data.botplay && !PlayState.loadRep)
+ ranking = "BotPlay";
+
+ if (PlayState.misses == 0 && PlayState.bads == 0 && PlayState.shits == 0 && PlayState.goods == 0) // Marvelous (SICK) Full Combo
+ ranking = "(MFC)";
+ else if (PlayState.misses == 0 && PlayState.bads == 0 && PlayState.shits == 0 && PlayState.goods >= 1) // Good Full Combo (Nothing but Goods & Sicks)
+ ranking = "(GFC)";
+ else if (PlayState.misses == 0) // Regular FC
+ ranking = "(FC)";
+ else if (PlayState.misses < 10) // Single Digit Combo Breaks
+ ranking = "(SDCB)";
+ else
+ ranking = "(Clear)";
+
+ // WIFE TIME :)))) (based on Wife3)
+
+ var wifeConditions:Array = [
+ accuracy >= 99.9935, // AAAAA
+ accuracy >= 99.980, // AAAA:
+ accuracy >= 99.970, // AAAA.
+ accuracy >= 99.955, // AAAA
+ accuracy >= 99.90, // AAA:
+ accuracy >= 99.80, // AAA.
+ accuracy >= 99.70, // AAA
+ accuracy >= 99, // AA:
+ accuracy >= 96.50, // AA.
+ accuracy >= 93, // AA
+ accuracy >= 90, // A:
+ accuracy >= 85, // A.
+ accuracy >= 80, // A
+ accuracy >= 70, // B
+ accuracy >= 60, // C
+ accuracy < 60 // D
+ ];
+
+ for(i in 0...wifeConditions.length)
+ {
+ var b = wifeConditions[i];
+ if (b)
+ {
+ switch(i)
+ {
+ case 0:
+ ranking += " AAAAA";
+ case 1:
+ ranking += " AAAA:";
+ case 2:
+ ranking += " AAAA.";
+ case 3:
+ ranking += " AAAA";
+ case 4:
+ ranking += " AAA:";
+ case 5:
+ ranking += " AAA.";
+ case 6:
+ ranking += " AAA";
+ case 7:
+ ranking += " AA:";
+ case 8:
+ ranking += " AA.";
+ case 9:
+ ranking += " AA";
+ case 10:
+ ranking += " A:";
+ case 11:
+ ranking += " A.";
+ case 12:
+ ranking += " A";
+ case 13:
+ ranking += " B";
+ case 14:
+ ranking += " C";
+ case 15:
+ ranking += " D";
+ }
+ break;
+ }
+ }
+
+ if (accuracy == 0)
+ ranking = "N/A";
+ else if(FlxG.save.data.botplay && !PlayState.loadRep)
+ ranking = "BotPlay";
+
+ return ranking;
+ }
+
+ public static function CalculateRating(noteDiff:Float, ?customSafeZone:Float):String // Generate a judgement through some timing shit
+ {
+
+ var customTimeScale = Conductor.timeScale;
+
+ if (customSafeZone != null)
+ customTimeScale = customSafeZone / 166;
+
+ // trace(customTimeScale + ' vs ' + Conductor.timeScale);
+
+ // I HATE THIS IF CONDITION
+ // IF LEMON SEES THIS I'M SORRY :(
+
+ // trace('Hit Info\nDifference: ' + noteDiff + '\nZone: ' + Conductor.safeZoneOffset * 1.5 + "\nTS: " + customTimeScale + "\nLate: " + 155 * customTimeScale);
+
+ if (FlxG.save.data.botplay && !PlayState.loadRep)
+ return "sick"; // FUNNY
+
+
+ var rating = checkRating(noteDiff,customTimeScale);
+
+
+ return rating;
+ }
+
+ public static function checkRating(ms:Float, ts:Float)
+ {
+ var rating = "sick";
+ if (ms <= 166 * ts && ms >= 135 * ts)
+ rating = "shit";
+ if (ms < 135 * ts && ms >= 90 * ts)
+ rating = "bad";
+ if (ms < 90 * ts && ms >= 45 * ts)
+ rating = "good";
+ if (ms < 45 * ts && ms >= -45 * ts)
+ rating = "sick";
+ if (ms > -90 * ts && ms <= -45 * ts)
+ rating = "good";
+ if (ms > -135 * ts && ms <= -90 * ts)
+ rating = "bad";
+ if (ms > -166 * ts && ms <= -135 * ts)
+ rating = "shit";
+ return rating;
+ }
+
+ public static function CalculateRanking(score:Int,scoreDef:Int,nps:Int,maxNPS:Int,accuracy:Float):String
+ {
+ return
+ (FlxG.save.data.npsDisplay ? // NPS Toggle
+ "NPS: " + nps + " (Max " + maxNPS + ")" + (!PlayStateChangeables.botPlay || PlayState.loadRep ? " | " : "") : "") + // NPS
+ (!PlayStateChangeables.botPlay || PlayState.loadRep ? "Score:" + (Conductor.safeFrames != 10 ? score + " (" + scoreDef + ")" : "" + score) + // Score
+ (FlxG.save.data.accuracyDisplay ? // Accuracy Toggle
+ " | Combo Breaks:" + PlayState.misses + // Misses/Combo Breaks
+ " | Accuracy:" + (PlayStateChangeables.botPlay && !PlayState.loadRep ? "N/A" : HelperFunctions.truncateFloat(accuracy, 2) + " %") + // Accuracy
+ " | " + GenerateLetterRank(accuracy) : "") : ""); // Letter Rank
+ }
+}
diff --git a/source - Copy/Replay.hx b/source - Copy/Replay.hx
new file mode 100644
index 0000000..ed09053
--- /dev/null
+++ b/source - Copy/Replay.hx
@@ -0,0 +1,133 @@
+#if sys
+import sys.io.File;
+#end
+import Controls.Control;
+import flixel.FlxG;
+import openfl.events.IOErrorEvent;
+import openfl.events.Event;
+import openfl.net.FileReference;
+import lime.utils.Assets;
+import haxe.Json;
+import flixel.input.keyboard.FlxKey;
+import openfl.utils.Dictionary;
+
+class Ana
+{
+ public var hitTime:Float;
+ public var nearestNote:Array;
+ public var hit:Bool;
+ public var hitJudge:String;
+ public var key:Int;
+ public function new(_hitTime:Float,_nearestNote:Array,_hit:Bool,_hitJudge:String, _key:Int) {
+ hitTime = _hitTime;
+ nearestNote = _nearestNote;
+ hit = _hit;
+ hitJudge = _hitJudge;
+ key = _key;
+ }
+}
+
+class Analysis
+{
+ public var anaArray:Array;
+
+ public function new() {
+ anaArray = [];
+ }
+}
+
+typedef ReplayJSON =
+{
+ public var replayGameVer:String;
+ public var timestamp:Date;
+ public var songName:String;
+ public var songDiff:Int;
+ public var songNotes:Array;
+ public var songJudgements:Array;
+ public var noteSpeed:Float;
+ public var isDownscroll:Bool;
+ public var sf:Int;
+ public var ana:Analysis;
+}
+
+class Replay
+{
+ public static var version:String = "1.2"; // replay file version
+
+ public var path:String = "";
+ public var replay:ReplayJSON;
+ public function new(path:String)
+ {
+ this.path = path;
+ replay = {
+ songName: "No Song Found",
+ songDiff: 1,
+ noteSpeed: 1.5,
+ isDownscroll: false,
+ songNotes: [],
+ replayGameVer: version,
+ timestamp: Date.now(),
+ sf: Conductor.safeFrames,
+ ana: new Analysis(),
+ songJudgements: []
+ };
+ }
+
+ public static function LoadReplay(path:String):Replay
+ {
+ var rep:Replay = new Replay(path);
+
+ rep.LoadFromJSON();
+
+ trace('basic replay data:\nSong Name: ' + rep.replay.songName + '\nSong Diff: ' + rep.replay.songDiff);
+
+ return rep;
+ }
+
+ public function SaveReplay(notearray:Array, judge:Array, ana:Analysis)
+ {
+ var json = {
+ "songName": PlayState.SONG.song,
+ "songDiff": PlayState.storyDifficulty,
+ "noteSpeed": (FlxG.save.data.scrollSpeed > 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed),
+ "isDownscroll": FlxG.save.data.downscroll,
+ "songNotes": notearray,
+ "songJudgements": judge,
+ "timestamp": Date.now(),
+ "replayGameVer": version,
+ "sf": Conductor.safeFrames,
+ "ana": ana
+ };
+
+ var data:String = Json.stringify(json);
+
+ var time = Date.now().getTime();
+
+ #if sys
+ File.saveContent("assets/replays/replay-" + PlayState.SONG.song + "-time" + time + ".kadeReplay", data);
+
+ path = "replay-" + PlayState.SONG.song + "-time" + time + ".kadeReplay"; // for score screen shit
+
+ LoadFromJSON();
+
+ replay.ana = ana;
+ #end
+ }
+
+ public function LoadFromJSON()
+ {
+ #if sys
+ trace('loading ' + Sys.getCwd() + 'assets/replays/' + path + ' replay...');
+ try
+ {
+ var repl:ReplayJSON = cast Json.parse(File.getContent(Sys.getCwd() + "assets/replays/" + path));
+ replay = repl;
+ }
+ catch(e)
+ {
+ trace('failed!\n' + e.message);
+ }
+ #end
+ }
+
+}
diff --git a/source - Copy/ResultsScreen.hx b/source - Copy/ResultsScreen.hx
new file mode 100644
index 0000000..108c547
--- /dev/null
+++ b/source - Copy/ResultsScreen.hx
@@ -0,0 +1,252 @@
+package;
+
+import openfl.geom.Matrix;
+import openfl.display.BitmapData;
+import flixel.system.FlxSound;
+import flixel.util.FlxAxes;
+import flixel.FlxSubState;
+import Options.Option;
+import flixel.input.FlxInput;
+import flixel.input.keyboard.FlxKey;
+import flixel.FlxG;
+import flixel.FlxObject;
+import flixel.FlxSprite;
+import flixel.effects.FlxFlicker;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import io.newgrounds.NG;
+import lime.app.Application;
+import lime.utils.Assets;
+import flixel.math.FlxMath;
+import flixel.text.FlxText;
+import flixel.input.FlxKeyManager;
+
+
+using StringTools;
+
+class ResultsScreen extends FlxSubState
+{
+ public var background:FlxSprite;
+ public var text:FlxText;
+
+ public var anotherBackground:FlxSprite;
+ public var graph:HitGraph;
+ public var graphSprite:OFLSprite;
+
+ public var comboText:FlxText;
+ public var contText:FlxText;
+ public var settingsText:FlxText;
+
+ public var music:FlxSound;
+
+ public var graphData:BitmapData;
+
+ public var ranking:String;
+ public var accuracy:String;
+
+ override function create()
+ {
+ background = new FlxSprite(0,0).makeGraphic(FlxG.width,FlxG.height,FlxColor.BLACK);
+ background.scrollFactor.set();
+ add(background);
+
+ music = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true);
+ music.volume = 0;
+ music.play(false, FlxG.random.int(0, Std.int(music.length / 2)));
+
+ background.alpha = 0;
+
+ text = new FlxText(20,-55,0,"Song Cleared!");
+ text.size = 34;
+ text.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1);
+ text.color = FlxColor.WHITE;
+ text.scrollFactor.set();
+ add(text);
+
+ var score = PlayState.instance.songScore;
+ if (PlayState.isStoryMode)
+ {
+ score = PlayState.campaignScore;
+ text.text = "Week Cleared!";
+ }
+
+ comboText = new FlxText(20,-75,0,'Judgements:\nSicks - ${PlayState.sicks}\nGoods - ${PlayState.goods}\nBads - ${PlayState.bads}\n\nCombo Breaks: ${(PlayState.isStoryMode ? PlayState.campaignMisses : PlayState.misses)}\nHighest Combo: ${PlayState.highestCombo + 1}\n\nScore: ${PlayState.instance.songScore}\nAccuracy: ${HelperFunctions.truncateFloat(PlayState.instance.accuracy,2)}%\n\n${Ratings.GenerateLetterRank(PlayState.instance.accuracy)}\n\nF1 - View replay\nF2 - Replay song
+ ');
+ comboText.size = 28;
+ comboText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1);
+ comboText.color = FlxColor.WHITE;
+ comboText.scrollFactor.set();
+ add(comboText);
+
+ contText = new FlxText(FlxG.width - 475,FlxG.height + 50,0,'Press ENTER to continue.');
+ contText.size = 28;
+ contText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1);
+ contText.color = FlxColor.WHITE;
+ contText.scrollFactor.set();
+ add(contText);
+
+ anotherBackground = new FlxSprite(FlxG.width - 500,45).makeGraphic(450,240,FlxColor.BLACK);
+ anotherBackground.scrollFactor.set();
+ anotherBackground.alpha = 0;
+ add(anotherBackground);
+
+ graph = new HitGraph(FlxG.width - 500,45,495,240);
+ graph.alpha = 0;
+
+ graphSprite = new OFLSprite(FlxG.width - 510,45,460,240,graph);
+
+ graphSprite.scrollFactor.set();
+ graphSprite.alpha = 0;
+
+ add(graphSprite);
+
+
+ var sicks = HelperFunctions.truncateFloat(PlayState.sicks / PlayState.goods,1);
+ var goods = HelperFunctions.truncateFloat(PlayState.goods / PlayState.bads,1);
+
+ if (sicks == Math.POSITIVE_INFINITY)
+ sicks = 0;
+ if (goods == Math.POSITIVE_INFINITY)
+ goods = 0;
+
+ var mean:Float = 0;
+
+
+ for (i in 0...PlayState.rep.replay.songNotes.length)
+ {
+ // 0 = time
+ // 1 = length
+ // 2 = type
+ // 3 = diff
+ var obj = PlayState.rep.replay.songNotes[i];
+ // judgement
+ var obj2 = PlayState.rep.replay.songJudgements[i];
+
+ var obj3 = obj[0];
+
+ var diff = obj[3];
+ var judge = obj2;
+ mean += diff;
+ if (obj[1] != -1)
+ graph.addToHistory(diff, judge, obj3);
+ }
+
+ graph.update();
+
+ mean = HelperFunctions.truncateFloat(mean / PlayState.rep.replay.songNotes.length,2);
+
+ settingsText = new FlxText(20,FlxG.height + 50,0,'SF: ${PlayState.rep.replay.sf} | Ratio (SA/GA): ${Math.round(sicks)}:1 ${Math.round(goods)}:1 | Mean: ${mean}ms | Played on ${PlayState.SONG.song} ${CoolUtil.difficultyFromInt(PlayState.storyDifficulty).toUpperCase()}');
+ settingsText.size = 16;
+ settingsText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,2,1);
+ settingsText.color = FlxColor.WHITE;
+ settingsText.scrollFactor.set();
+ add(settingsText);
+
+
+ FlxTween.tween(background, {alpha: 0.5},0.5);
+ FlxTween.tween(text, {y:20},0.5,{ease: FlxEase.expoInOut});
+ FlxTween.tween(comboText, {y:145},0.5,{ease: FlxEase.expoInOut});
+ FlxTween.tween(contText, {y:FlxG.height - 45},0.5,{ease: FlxEase.expoInOut});
+ FlxTween.tween(settingsText, {y:FlxG.height - 35},0.5,{ease: FlxEase.expoInOut});
+ FlxTween.tween(anotherBackground, {alpha: 0.6},0.5, {onUpdate: function(tween:FlxTween) {
+ graph.alpha = FlxMath.lerp(0,1,tween.percent);
+ graphSprite.alpha = FlxMath.lerp(0,1,tween.percent);
+ }});
+
+ cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
+
+ super.create();
+ }
+
+
+ var frames = 0;
+
+ override function update(elapsed:Float)
+ {
+ if (music.volume < 0.5)
+ music.volume += 0.01 * elapsed;
+
+ // keybinds
+
+ if (FlxG.keys.justPressed.ENTER)
+ {
+ music.fadeOut(0.3);
+
+ PlayState.loadRep = false;
+ PlayState.rep = null;
+
+ if (PlayState.isStoryMode)
+ {
+ FlxG.sound.playMusic(Paths.music('freakyMenu'));
+ FlxG.switchState(new MainMenuState());
+ }
+ else
+ FlxG.switchState(new FreeplayState());
+ }
+
+ if (FlxG.keys.justPressed.EIGHT)
+ {
+ graph.showInput = !graph.showInput;
+ graph.update();
+ }
+
+ if (FlxG.keys.justPressed.F1)
+ {
+ trace(PlayState.rep.path);
+ PlayState.rep = Replay.LoadReplay(PlayState.rep.path);
+
+ PlayState.loadRep = true;
+
+ var songFormat = StringTools.replace(PlayState.rep.replay.songName, " ", "-");
+ switch (songFormat) {
+ case 'Dad-Battle': songFormat = 'Dadbattle';
+ case 'Philly-Nice': songFormat = 'Philly';
+ // Replay v1.0 support
+ case 'dad-battle': songFormat = 'Dadbattle';
+ case 'philly-nice': songFormat = 'Philly';
+ }
+
+ var poop:String = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff);
+
+ music.fadeOut(0.3);
+
+ PlayState.SONG = Song.loadFromJson(poop, PlayState.rep.replay.songName);
+ PlayState.isStoryMode = false;
+ PlayState.storyDifficulty = PlayState.rep.replay.songDiff;
+ PlayState.storyWeek = 0;
+ LoadingState.loadAndSwitchState(new PlayState());
+ }
+
+ if (FlxG.keys.justPressed.F2 )
+ {
+ PlayState.rep = null;
+
+ PlayState.loadRep = false;
+
+ var songFormat = StringTools.replace(PlayState.SONG.song, " ", "-");
+ switch (songFormat) {
+ case 'Dad-Battle': songFormat = 'Dadbattle';
+ case 'Philly-Nice': songFormat = 'Philly';
+ case 'dad-battle': songFormat = 'Dadbattle';
+ case 'philly-nice': songFormat = 'Philly';
+ }
+
+ var poop:String = Highscore.formatSong(songFormat, PlayState.storyDifficulty);
+
+ music.fadeOut(0.3);
+
+ PlayState.SONG = Song.loadFromJson(poop, PlayState.SONG.song);
+ PlayState.isStoryMode = false;
+ PlayState.storyDifficulty = PlayState.storyDifficulty;
+ PlayState.storyWeek = 0;
+ LoadingState.loadAndSwitchState(new PlayState());
+ }
+
+ super.update(elapsed);
+
+ }
+}
diff --git a/source - Copy/Section.hx b/source - Copy/Section.hx
new file mode 100644
index 0000000..f153da5
--- /dev/null
+++ b/source - Copy/Section.hx
@@ -0,0 +1,31 @@
+package;
+
+typedef SwagSection =
+{
+ var sectionNotes:Array;
+ var lengthInSteps:Int;
+ var typeOfSection:Int;
+ var mustHitSection:Bool;
+ var bpm:Float;
+ var changeBPM:Bool;
+ var altAnim:Bool;
+}
+
+class Section
+{
+ public var sectionNotes:Array = [];
+
+ public var lengthInSteps:Int = 16;
+ public var typeOfSection:Int = 0;
+ public var mustHitSection:Bool = true;
+
+ /**
+ * Copies the first section into the second section!
+ */
+ public static var COPYCAT:Int = 0;
+
+ public function new(lengthInSteps:Int = 16)
+ {
+ this.lengthInSteps = lengthInSteps;
+ }
+}
diff --git a/source - Copy/Snd.hx b/source - Copy/Snd.hx
new file mode 100644
index 0000000..33aedae
--- /dev/null
+++ b/source - Copy/Snd.hx
@@ -0,0 +1,1288 @@
+import faxe.Faxe;
+
+import SndTV;
+using StringTools;
+
+//praise delahee, i'll figure out what this shit means later!
+
+class Channel {
+ public var name:String;
+ public var onEnd : Void -> Void = null;
+ public var isDebug = false;
+
+ var started = true;
+ var paused = false;
+ var disposed = false;
+ var completed = false;
+
+ inline function new( ?name:String = null ){
+ if ( name == null )
+ this.name = C.EMPTY_STRING;
+ else
+ this.name = name;
+ }
+
+ public function poolBack(){
+ #if false
+ //trace("pool back");
+ #end
+ started = false;
+ paused = false;
+ disposed = true;
+ completed = true;
+ isDebug = false;
+ }
+
+ public function reset(){
+ started = false;
+ paused = false;
+ disposed = false;
+ completed = false;
+ isDebug = false;
+ }
+
+ public function stop(){
+ started = false;
+ }
+
+ public function pause(){
+ paused = false;
+ started = true;
+ }
+
+ public function resume(){
+ paused = true;
+ started = true;
+ }
+
+ public function dispose(){
+ setVolume(0);//prevent any further listen
+ disposed = true;
+ onEnd = null;
+ }
+
+ public function onComplete() {
+ completed = true;
+ #if !prod
+ //trace("onComplete " + haxe.Timer.stamp() );
+ #end
+ //stop();
+ if( onEnd!=null ) {
+ var cb = onEnd;
+ onEnd = null;
+ cb();
+ }
+ }
+
+ public function isComplete(){
+ #if !prod
+ if ( completed ){
+ //trace("already completed");
+ }
+
+ if ( started ){
+ //trace("started ok");
+ }
+ #end
+
+ return completed || (started && !isPlaying());
+ }
+
+ //returns in secs
+ public function getPlayCursorSec() : Float {
+ throw "override me";
+ return 0.0;
+ }
+
+ //returns in secs
+ public function getPlayCursorMs() : Float {
+ throw "override me";
+ return 0.0;
+ }
+
+ public function setPlayCursorSec(posSec:Float) {
+ setPlayCursorMs( posSec * 1000.0 );
+ }
+
+ public function setPlayCursorMs(posMs:Float) {
+ throw "override me";
+ }
+
+ public function isPlaying(){
+ throw "override me";
+ return false;
+ }
+
+ public function getVolume():Float{
+ throw "override me";
+ return 0.0;
+ }
+
+ public function setVolume(v:Float){
+ throw "override me";
+ }
+
+ public function setNbLoops(nb:Int){
+
+ }
+}
+
+class ChannelEventInstance extends Channel {//basically a sound instance
+ public static var EMPTY_STRING = "";
+ public var data : FmodStudioEventInstanceRef = null;
+
+ function new(?name:String){
+ super(name);
+ started = false;
+ //instance does not start playing
+ }
+
+ public static var pool = {
+ var p = new hxd.Pool(ChannelEventInstance);
+ //p.actives = null;
+ p;
+ }
+
+ public static function alloc(data : FmodStudioEventInstanceRef, ?name:String=null ){
+ var s = pool.alloc();
+
+ s.reset();
+
+ s.data = data;
+ s.name = name == null ? EMPTY_STRING : name;
+ return s;
+ }
+
+ public static function delete( c : ChannelEventInstance){
+ c.dispose();
+ pool.delete(c);
+ }
+
+ public function getData() return data;
+
+ public override function dispose(){
+ super.dispose();
+ if ( data != null){
+ data.release();
+ data = null;
+ }
+ }
+
+ public override function poolBack(){
+ super.poolBack();
+ ChannelEventInstance.delete(this);
+ }
+
+ public override function stop(){
+ if (data != null) data.stop(FmodStudioStopMode.StopAllowFadeout());
+ super.stop();
+ }
+
+ public override function pause(){
+ super.pause();
+ if(data!=null) data.setPaused(true);
+ }
+
+ public override function resume(){
+ super.resume();
+ if(data!=null) data.setPaused(false);
+ }
+
+ public override function isPlaying(){
+ if ( completed ) return false;
+
+ if ( data == null ) {
+ //#if !prod
+ //trace("[CEI]no data " + name);
+ //#end
+ return false;
+ }
+
+ var b : Bool = false;
+ data.getPaused( Cpp.addr(b));
+ #if !prod
+ //trace("getPaused:"+b);
+ #end
+ return !b;
+ }
+
+ //returns in secs
+ public override function getPlayCursorSec() : Float {
+ if ( data == null ) return 0.0;
+
+ var pos : Int = 0;
+ var res = data.getTimelinePosition( Cpp.addr(pos) );
+ var posF : Float = 1.0 * pos / 1000.0;
+ return posF;
+ }
+
+ //returns in secs
+ public override function getPlayCursorMs() : Float {
+ if ( data == null ) return 0.0;
+
+ var pos : Int = 0;
+ var res = data.getTimelinePosition( Cpp.addr(pos) );
+ return 1.0 * pos;
+ }
+
+ public override function setPlayCursorMs(posMs:Float) {
+ if ( data == null ) return;
+
+ if ( posMs < 0.0) posMs = 0.0;
+ var pos : Int = 0;
+ pos = Math.round( posMs );
+ var res = data.setTimelinePosition( pos );
+ if ( res != FMOD_OK){
+ #if debug
+ //trace("[SND][Channel]{"+name+"} Repositionning S err " + FaxeRef.fmodResultToString(res)+" to :"+pos+" ("+posMs+")");
+ #end
+ }
+
+ #if debug
+ //trace("setPlayCursorMs "+posMs);
+ #end
+ }
+
+ public override function setNbLoops(nb:Int){
+
+ }
+
+ public override function getVolume() : Float{
+ if (data == null ) return 0.0;
+
+ var vol : cpp.Float32 = 0.0;
+ var fvol : cpp.Float32 = 0.0;
+ var res = data.getVolume( Cpp.addr(vol),Cpp.addr(fvol) );
+ if ( res != FMOD_OK){
+ #if debug
+ //trace("[SND][Channel]{"+name+"} getVolume err " + FaxeRef.fmodResultToString(res));
+ #end
+ }
+ return vol;
+ }
+
+ public override function setVolume(v:Float){
+ if (data == null ){
+ //#if debug
+ //trace("no data for "+name);
+ //#end
+ return;
+ }
+
+ var res = data.setVolume( hxd.Math.clamp(v,0,1) );
+ if ( res != FMOD_OK){
+ //#if debug
+ //trace("[SND][Channel]{"+name+"} setVolume err " + FaxeRef.fmodResultToString(res));
+ //#end
+ }
+ else {
+ //if ( isDebug ){
+ //#if !prod
+ //trace("[SND][Channel]{"+name+"} setVolume ok " + v);
+ //#end
+ //}
+ }
+ }
+}
+
+class ChannelLowLevel extends Channel{
+
+ public static var EMPTY_STRING = "";
+ public var data : FmodChannelRef = null;
+
+ function new( data : FmodChannelRef, ?name:String ){
+ super(name);
+ this.data = data;
+ started = true;
+ }
+
+ public static var pool = {
+ var p = new hxd.Pool(ChannelLowLevel);
+ //p.actives = null;
+ p;
+ }
+
+ public static function alloc(data : FmodChannelRef, ?name ){
+ var s = pool.alloc();
+
+ s.reset();
+
+ s.data = data;
+ s.name = name == null?EMPTY_STRING:name;
+
+ return s;
+ }
+
+ public static function delete( c : ChannelLowLevel){
+ c.dispose();
+ pool.delete(c);
+ }
+
+ public function getData(){
+ return data;
+ }
+
+ public override function poolBack(){
+ super.poolBack();
+ ChannelLowLevel.delete(this);
+ }
+
+ public override function stop(){
+ if (data != null) data.stop();
+ super.stop();
+ }
+
+ public override function pause(){
+ super.pause();
+ if(data!=null) data.setPaused(true);
+ }
+
+ public override function resume(){
+ super.resume();
+ if(data!=null) data.setPaused(false);
+ }
+
+ public override function dispose(){
+ super.dispose();
+ data = null;
+ }
+
+ public override function isPlaying(){
+ if ( completed ) return false;
+
+ if (data == null) {
+ //#if !prod
+ //trace("no data no playing! "+name);
+ //#end
+ return false;
+ }
+ var b : Bool = false;
+ var res = data.isPlaying( Cpp.addr(b));
+ if ( res != FMOD_OK ){
+ //#if debug
+ //trace("[SND][ChannelLowLevel]{"+name+"} isPlaying err " + FaxeRef.fmodResultToString(res));
+ //#end
+ return false;
+ }
+ return b;
+ }
+
+ //returns in secs
+ public override function getPlayCursorSec() : Float {
+ if (data == null) return 0.0;
+
+ var pos : cpp.UInt32 = 0;
+ var res = data.getPosition( Cpp.addr(pos), faxe.Faxe.FmodTimeUnit.FTM_MS );
+ var posF : Float = 1.0 * pos * 1000.0;
+ return posF;
+ }
+
+ //returns in secs
+ public override function getPlayCursorMs() : Float {
+ if (data == null) return 0.0;
+
+ var pos : cpp.UInt32 = 0;
+ var res = data.getPosition( Cpp.addr(pos), faxe.Faxe.FmodTimeUnit.FTM_MS );
+ return 1.0 * pos;
+ }
+
+
+ public override function setPlayCursorMs(posMs:Float) {
+ if (data == null) return;
+
+ if ( posMs < 0.0) posMs = 0.0;
+ var posU : cpp.UInt32 = 0;
+ posU = Math.round( posMs );
+ var res = data.setPosition( posU, FmodTimeUnit.FTM_MS );
+ if ( res != FMOD_OK){
+ //#if debug
+ //trace("[SND][Channel]{"+name+"} Repositionning S err " + FaxeRef.fmodResultToString(res)+" to :"+posU+" ("+posMs+")");
+ //#end
+ }
+ }
+
+ public override function setNbLoops(nb:Int){
+ if (data == null) return;
+ data.setMode(FmodMode.FMOD_LOOP_NORMAL);
+ data.setLoopCount(nb);
+ }
+
+ public override function getVolume():Float{
+ if (data == null) return 0.0;
+
+ var vol : cpp.Float32 = 0.0;
+ var res = data.getVolume( Cpp.addr(vol) );
+ if ( res != FMOD_OK){
+ //#if debug
+ //trace("[SND][Channel]{"+name+"} getVolume err " + FaxeRef.fmodResultToString(res));
+ //#end
+ }
+ return vol;
+ }
+
+ public override function setVolume(v:Float){
+ if (data == null) {
+ //if ( isDebug ){
+ //#if !prod
+ //trace("[SND][Channel]{"+name+"} setVolume no data");
+ //#end
+ //}
+ return;
+ }
+
+ var vcl = hxd.Math.clamp(v, 0, 1);
+ var res = data.setVolume( vcl );
+ if ( res != FMOD_OK){
+ //#if !prod
+ //trace("[SND][Channel]{"+name+"} setVolume err " + FaxeRef.fmodResultToString(res));
+ //#end
+ }
+ else {
+ if ( isDebug ){
+ //#if !prod
+ //trace("[SND][Channel]{"+name+"} setVolume ok " + v+" corrected:"+vcl);
+ //#end
+ }
+ }
+ }
+
+
+}
+
+class Sound {
+ /**
+ * length is in seconds
+ */
+ public var name = "";
+ public var length(get, null) : Float;
+ public var id3 : Dynamic = null;
+ public var isDebug = false;
+
+ var disposed = false;
+
+ function new( ?name:String=null ){
+ disposed = false;
+ }
+
+ function get_length() : Float{
+ return 0.0;
+ }
+
+ //returns in msec
+ public function getDuration(): Float{
+ return getDurationMs();
+ }
+
+ public function getDurationSec() : Float{
+ return length;
+ }
+
+ public function getDurationMs() : Float{
+ return length * 1000.0;
+ }
+
+ public function dispose(){
+ if (disposed) return;
+ disposed = true;
+ }
+
+ public function play( ?offsetMs : Float = 0.0, ?nbLoops:Int = 1, ?volume:Float = 1.0 ) : Channel {
+ return null;
+ }
+}
+
+class SoundLowLevel extends Sound{
+
+ public var data : FmodSoundRef = null;
+
+ public function new( data : cpp.Pointer, ?name:String = null ){
+ super(name);
+ this.data = Cpp.ref(data);
+ }
+
+ public function getData(){
+ return data;
+ }
+
+ public override function dispose(){
+ super.dispose();
+
+ if ( Snd.released ) {
+ data = null;
+ return;
+ }
+
+ if(data!=null)
+ data.release();
+ data = null;
+ }
+
+ //returns in secs
+ override function get_length() : Float{
+ if (disposed) return 0.0;
+
+ var pos : cpp.UInt32 = 0;
+ var res = data.getLength( Cpp.addr(pos), FmodTimeUnit.FTM_MS );
+ if ( res != FMOD_OK ){
+ #if debug
+ //trace("impossible to retrieve sound len");
+ #end
+ }
+ var posF = 1.0 * pos / 1000.0;
+ return posF;
+ }
+
+ public override function play( ?offsetMs : Float = 0.0, ?nbLoops:Int = 1, ?volume:Float = 1.0) : Channel {
+ var nativeChan : FmodChannelRef = FaxeRef.playSoundWithHandle( data , false);
+ var chan = ChannelLowLevel.alloc( nativeChan, name );
+
+ #if debug
+ //trace("[Sound] offset " + offsetMs);
+ //trace("play " + haxe.Timer.stamp() );
+ #end
+
+ @:privateAccess chan.started = true;
+ @:privateAccess chan.completed = false;
+ @:privateAccess chan.disposed = false;
+ @:privateAccess chan.paused = false;
+
+
+ if( offsetMs != 0.0 ) chan.setPlayCursorMs( offsetMs );
+ if( volume != 1.0 ) chan.setVolume( volume );
+ if( nbLoops > 1 ) chan.setNbLoops( nbLoops );
+
+ return chan;
+ }
+}
+
+
+class SoundEvent extends Sound{
+
+ public var data : FmodStudioEventDescriptionRef = null;
+
+ public function new( data : FmodStudioEventDescriptionRef, ?name:String = null ){
+ super(name);
+ this.data = data;
+ }
+
+ public override function dispose(){
+ super.dispose();
+
+ if ( Snd.released ) {
+ data = null;
+ return;
+ }
+
+ if ( data != null){
+ data.releaseAllInstances();
+ data = null;
+ }
+ }
+ public function getData(){
+ return data;
+ }
+
+ //returns in secs
+ override function get_length() : Float{
+ if (disposed) return 0.0;
+
+ var pos : Int = 0;
+ var res = data.getLength( Cpp.addr(pos) );
+ if ( res != FMOD_OK ){
+ //#if !prod
+ //trace("impossible to retrieve sound len");
+ //#end
+ }
+ var posF = 1.0 * pos / 1000.0;
+ return posF;
+ }
+
+ public override function play( ?offsetMs : Float = 0.0, ?nbLoops:Int = 1, ?volume:Float = 1.0) : Channel{
+ var nativeInstance : FmodStudioEventInstanceRef = data.createInstance();
+ var chan = ChannelEventInstance.alloc( nativeInstance, name );
+
+ //#if !prod
+ //trace("play " + haxe.Timer.stamp() );
+ //#end
+ nativeInstance.start();
+
+ @:privateAccess chan.started = true;
+ @:privateAccess chan.completed = false;
+ @:privateAccess chan.disposed = false;
+ @:privateAccess chan.paused = false;
+
+ if( offsetMs != 0.0 ) chan.setPlayCursorMs( offsetMs );
+ if( volume != 1.0 ) chan.setVolume( volume );
+
+ return chan;
+ }
+}
+
+class Snd {
+ public static var EMPTY_STRING = "";
+ public static var PLAYING : hxd.Stack = new hxd.Stack();
+ static var MUTED = false;
+ static var DISABLED = false;
+ static var GLOBAL_VOLUME = 1.0;
+ static var TW = new SndTV();
+
+ public var name : String ;
+ public var pan : Float = 0.0;
+ public var volume(default,set) : Float = 1.0;
+ public var curPlay : Null = null;
+ public var bus = otherBus;
+ public var isDebug = true;
+ /**
+ * for when stop is called explicitly
+ * allows disposal
+ */
+ public var onStop = new hxd.Signal();
+ public var sound : Sound = null;
+
+ var onEnd : NullVoid> = null;
+ static var fmodSystem : FmodSystemRef = null;
+
+ public static var otherBus = new SndBus();
+ public static var sfxBus = new SndBus();
+ public static var musicBus = new SndBus();
+
+ public function new( snd : Sound, ?name:String ) {
+ volume = 1;
+ pan = 0;
+ sound = snd;
+ muted = false;
+ this.name = name==null?EMPTY_STRING:name;
+ }
+
+ public function isLoaded() {
+ return sound!=null;
+ }
+
+ //does not dispose sound, only instanced
+ public function stop(){
+
+ TW.terminate(this);//prevent reentrancy of fadeStop() stop() not cutting any sound
+
+ PLAYING.remove(this);
+
+ if ( isPlaying() && !onStop.isTriggering )
+ onStop.trigger();
+
+ if ( curPlay != null){
+ curPlay.dispose();
+ curPlay.poolBack();
+ curPlay = null;
+ #if !prod
+ //trace(name+" stopped");
+ //Lib.showStack();
+ #end
+ }
+
+ //bus = otherBus;
+ }
+
+ public function dispose(){
+ //#if !prod
+ //trace(name+" disposing");
+ //#end
+
+ if ( isPlaying() ){
+ stop();
+ }
+
+ if ( curPlay != null){
+ curPlay.dispose();
+ curPlay.poolBack();
+ curPlay = null;
+ //#if !prod
+ //trace(name+" disposed");
+ //#end
+ }
+
+ if ( sound != null) {
+ sound.dispose();
+ sound = null;
+ }
+
+ onStop.dispose();
+
+ onEnd = null;
+ curPlay = null;
+ }
+
+ /**
+ *
+ * @return in ms
+ */
+ public inline function getPlayCursor() : Float {
+ if ( curPlay == null) return 0.0;
+ return curPlay.getPlayCursorMs();
+ }
+
+
+ public function play(?vol:Float, ?pan:Float) : Snd {
+ if( vol == null ) vol = volume;
+ if( pan == null ) pan = this.pan;
+
+ start(0, vol, 0.0);
+
+ return this;
+ }
+
+ /**
+ * launches the sound, stops previous and rewrite the cur play dropping it into oblivion for the gc
+ */
+ public function start(loops:Int=0, vol:Float=1.0, ?startOffsetMs:Float=0.0) {
+ if ( DISABLED ) {
+ //#if debug
+ //trace("[SND] Disabled");
+ //#end
+ return;
+ }
+ if ( sound == null ){
+ //#if debug
+ //trace("[SND] no inner sound");
+ //#end
+ return;
+ }
+
+ if ( isPlaying() ){
+ //#if !prod
+ //trace(name+" interrupting ");
+ //#end
+
+ stop();
+ }
+
+ TW.terminate(this);
+
+ this.volume = vol;
+ this.pan = normalizePanning(pan);
+
+ PLAYING.push(this);
+ curPlay = sound.play( startOffsetMs, loops, getRealVolume());
+
+ if ( curPlay == null){
+ //#if !prod
+ //trace(" play missed?");
+ //#end
+ }
+ else {
+ //#if !prod
+ //trace("started");
+ //#end
+ }
+ }
+
+ /**
+ * launches the sound and rewrite the cur play dropping it into oblivion for the gc
+ */
+ public function startNoStop(?loops:Int=0, ?vol:Float=1.0, ?startOffsetMs:Float=0.0) : Null{
+ if ( DISABLED ) {
+ //#if debug
+ //trace("[SND] Disabled");
+ //#end
+ return null;
+ }
+ if ( sound == null ){
+ //#if debug
+ //trace("[SND] no inner sound");
+ //#end
+ return null;
+ }
+
+ this.volume = vol;
+ this.pan = normalizePanning(pan);
+
+ curPlay = sound.play( startOffsetMs, loops, getRealVolume());
+
+ return curPlay;
+ }
+
+ public inline function getDuration() {
+ return getDurationMs();
+ }
+
+ public inline function getDurationSec() {
+ return sound.length;
+ }
+
+ /**
+ * returns in ms
+ */
+ public inline function getDurationMs() {
+ return sound.length * 1000.0;
+ }
+
+ public static inline
+ function trunk(v:Float, digit:Int) : Float{
+ var hl = Math.pow( 10.0 , digit );
+ return Std.int( v * hl ) / hl;
+ }
+
+ public static function dumpMemory(){
+ var v0 : Int = 0;
+ var v1 : Int = 0;
+ var v2 : Int = 0;
+
+ var v0p : cpp.Pointer = Cpp.addr(v0);
+ var v1p : cpp.Pointer = Cpp.addr(v1);
+ var v2p : cpp.Pointer = Cpp.addr(v2);
+ var str = "";
+ var res = fmodSystem.getSoundRAM( v0p, v1p, v2p );
+ if ( res != FMOD_OK){
+ //#if debug
+ //trace("[SND] cannot fetch snd ram dump ");
+ //#end
+ }
+
+ inline function f( val :Float) : Float{
+ return trunk(val, 2);
+ }
+
+ if( v2 > 0 ){
+ str+="fmod Sound chip RAM all:" + f(v0 / 1024.0) + "KB \t max:" + f(v1 / 1024.0) + "KB \t total: " + f(v2 / 1024.0) + " KB\r\n";
+ }
+
+ v0 = 0;
+ v1 = 0;
+
+ var res = FaxeRef.Memory_GetStats( v0p, v1p, false );
+ str += "fmod Motherboard chip RAM all:" + f(v0 / 1024.0) + "KB \t max:" + f(v1 / 1024.0) + "KB \t total: " + f(v2 / 1024.0) + " KB";
+ return str;
+ }
+
+ public function playLoop(?loops = 9999, ?vol:Float=1.0, ?startOffset = 0.0) : Snd {
+ if( vol==null )
+ vol = volume;
+
+ start(loops, vol, startOffset);
+ return this;
+ }
+
+ function set_volume(v:Float) {
+ volume = v;
+ refresh();
+ return volume;
+ }
+
+ public function setVolume(v:Float) {
+ set_volume(v);
+ }
+
+ public inline function getRealPanning() {
+ return pan;
+ }
+
+ public function setPanning(p:Float) {
+ pan = p;
+ refresh();
+ }
+
+ public function onEndOnce(cb:Void->Void) {
+ onEnd = cb;
+ }
+
+ public function fadePlay(?fadeDuration = 100, ?endVolume:Float=1.0 ) {
+ var p = play(0.0001);
+ if ( p == null ){
+ //trace("nothing ret");
+ }
+ else {
+ if ( p.curPlay == null){
+ //trace("no curplay wtf?");
+ }
+ else
+ {
+ //trace("curplay ok");
+ }
+ }
+ tweenVolume(endVolume, fadeDuration);
+ return p;
+ }
+
+ public function fadePlayLoop(?fadeDuration = 100, ?endVolume:Float=1.0 , ?loops=9999) {
+ var p = playLoop(loops,0);
+ tweenVolume(endVolume, fadeDuration);
+ return p;
+ }
+
+ public function fadeStop( ?fadeDuration = 100 ) {
+ if ( !isPlaying()){
+ //#if !prod
+ //trace("not playing " + name+" winn not unfade");//can cause reentrancy issues
+ //#end
+ return null;
+ }
+
+ isDebug = true;
+ var t = tweenVolume(0, fadeDuration);
+ t.onEnd = _stop;
+ return t;
+ }
+
+ public var muted : Bool = false;
+
+ public function toggleMute() {
+ muted = !muted;//todo
+ setVolume(volume);
+ }
+ public function mute() {
+ muted = true;
+ setVolume(volume);
+ }
+ public function unmute() {
+ muted = false;
+ setVolume(volume);
+ }
+
+ public function isPlaying(){
+ if ( curPlay == null ){
+ #if !prod
+ //trace("no curplay");
+ #end
+ return false;
+ }
+ return curPlay.isPlaying();
+ }
+
+ public static function init(){
+ #if debug
+ trace("[Snd] fmod init");
+ #end
+ Faxe.fmod_init( 256 );
+ fmodSystem = FaxeRef.getSystem();
+ released = false;
+ }
+
+ public static var released = true;
+
+ public static function release(){
+ TW.terminateAll();
+ for (s in PLAYING)
+ s.dispose();
+ PLAYING.hardReset();
+ released = true;
+ //trace("releasing fmod");
+ Faxe.fmod_release();
+ #if !prod
+ trace("fmod released");
+ #end
+ }
+
+ public static function setGlobalVolume(vol:Float) {
+ GLOBAL_VOLUME = normalizeVolume(vol);
+ refreshAll();
+ }
+
+ function refresh() {
+ if ( curPlay != null ) {
+ var vol = getRealVolume();
+ //trace("r:"+vol);
+ curPlay.setVolume( vol );
+ }
+ else {
+ //#if debug
+ //trace("[Snd] no playin no refresh "+name);
+ //#end
+ }
+ }
+
+ public function setPlayCursorSec( pos:Float ) {
+ if (curPlay != null) {
+ curPlay.setPlayCursorSec(pos);
+ }
+ else {
+ //#if debug
+ //trace("setPlayCursorSec/no current instance");
+ //#end
+ }
+ }
+
+ public function setPlayCursorMs( pos:Float ){
+ if (curPlay != null)
+ curPlay.setPlayCursorMs(pos);
+ else {
+ //#if debug
+ //trace("setPlayCursorMs/no current instance");
+ //#end
+ }
+ }
+
+ public function tweenVolume(v:Float, ?easing:h2d.Tweenie.TType, ?milliseconds:Float=100) : TweenV {
+ if ( easing == null ) easing = h2d.Tweenie.TType.TEase;
+ var t = TW.create(this, TVVVolume, v, easing, milliseconds);
+ //#if !prod
+ //trace("tweening " + name+" to " + v);
+ //#end
+ return t;
+ }
+
+ public function tweenPan(v:Float, ?easing:h2d.Tweenie.TType, ?milliseconds:Float=100) : TweenV {
+ if ( easing == null ) easing = h2d.Tweenie.TType.TEase;
+ var t = TW.create(this, TVVPan, v, easing, milliseconds);
+ return t;
+ }
+
+ public inline function getRealVolume() {
+ var v = volume * GLOBAL_VOLUME * (DISABLED?0:1) * (MUTED?0:1) * (muted?0:1) * bus.volume;
+ if ( v <= 0.001)
+ v = 0.0;
+ return normalizeVolume(v);
+ }
+
+ static inline function normalizeVolume(f:Float) {
+ return hxd.Math.clamp(f, 0,1);
+ }
+
+ static inline function normalizePanning(f:Float) {
+ return hxd.Math.clamp(f, -1,1);
+ }
+
+ static var _stop = function(t:TweenV){
+ #if !prod
+ //if( t.parent != null )
+ //trace(t.parent.name+" cbk stopped");
+ //else
+ //trace(" unbound stop called");
+ #end
+ t.parent.stop();
+ }
+
+ static var _refresh = function(t:TweenV) {
+
+ //avoid unwanted crash
+ if ( released ){
+ //#if !prod
+ //trace("sorry released");
+ //#end
+ return;
+ }
+
+ t.parent.refresh();
+ }
+
+ static function refreshAll() {
+ for(s in PLAYING)
+ s.refresh();
+ }
+
+ function onComplete(){
+ //#if debug
+ //trace("onComplete " + haxe.Timer.stamp());
+ //#end
+
+ if (curPlay != null) {
+ curPlay.onComplete();
+ }
+
+ stop();
+ }
+
+ public function isComplete(){
+ if ( curPlay == null ) {
+ //#if!prod
+ //trace("comp: no cur play");
+ //#end
+ return true;
+ }
+ return curPlay.isComplete();
+ }
+
+ //////////////////////////////////////
+ /////////////////////STATICS//////////
+ //////////////////////////////////////
+
+ public static var DEBUG_TRACK = false;
+
+ //@:noDebug
+ public static function loadSound( path:String, streaming : Bool, blocking : Bool ) : Sound {
+
+ if ( released ) {
+ //#if(!prod)
+ //trace("FMOD not active "+path);
+ //#end
+ return null;
+ }
+
+ var mode = FMOD_DEFAULT;
+
+ if ( streaming ) mode |= FMOD_CREATESTREAM;
+ if ( !blocking ) mode |= FMOD_NONBLOCKING;
+
+ mode |= FmodMode.FMOD_2D;
+
+
+ if( DEBUG_TRACK) trace("Snd:loading " + path);
+
+ var snd : cpp.RawPointer = cast null;
+ var sndR : cpp.RawPointer> = cpp.RawPointer.addressOf(snd);
+
+ #if switch
+ if ( !path.startsWith("rom:"))
+ path = "rom://" + path;
+ #end
+
+ var res : FmodResult = fmodSystem.createSound(
+ Cpp.cstring(path),
+ mode,
+ Cpp.nullptr(),
+ sndR
+ );
+
+ if ( res != FMOD_OK){
+ #if(!prod)
+ trace("unable to load " + path + " code:" + res+" msg:"+FaxeRef.fmodResultToString(res));
+ #end
+ return null;
+ }
+
+ var n:String = null;
+
+ #if debug
+ n = new bm.Path(path).getFilename();
+ #end
+
+ return new SoundLowLevel(cpp.Pointer.fromRaw(snd),n);
+ }
+
+ public static function loadEvent( path:String ) : Sound {
+ if ( released ) {
+ //#if (!prod)
+ //trace("FMOD not active "+path);
+ //#end
+ return null;
+ }
+
+
+ if( DEBUG_TRACK) trace("Snd:loadingEvent " + path);
+
+ if ( !path.startsWith("event:/"))
+ path = "event:/" + path;
+
+ var fss : FmodStudioSystemRef = faxe.FaxeRef.getStudioSystem();
+ var ev = fss.getEvent( path);
+
+ if ( ev == null ) return null;
+
+ if ( !ev.isLoaded() ){
+ var t0 = haxe.Timer.stamp();
+ ev.loadSampleData();
+ var t1 = haxe.Timer.stamp();
+ #if debug
+ //trace("time to preload:" + (t1 - t0));
+ #end
+ }
+
+ return new SoundEvent( ev, path);
+ }
+
+ public static function fromFaxe( path:String ) : Snd {
+ if ( released ) {
+ //#if (!prod)
+ //trace("FMOD not active "+path);
+ //#end
+ return null;
+ }
+
+ var s : cpp.Pointer = faxe.Faxe.fmod_get_sound(path );
+ if ( s == null){
+ #if (!prod)
+ trace("unable to find " + path);
+ #end
+ return null;
+ }
+
+ var n:String = null;
+
+ #if debug
+ n = new bm.Path(path).getFilename();
+ #end
+
+ return new Snd( new SoundLowLevel(s,n), path);
+ }
+
+ public static function loadSfx( path:String ) : Snd {
+ var s : Sound = loadSound(path, false, false);
+ if ( s == null) return null;
+ return new Snd( s, s.name);
+ }
+
+ public static function loadSong( path:String ) : Snd {
+ var s : Sound = loadSound(path, true, true);
+ if ( s == null) return null;
+ return new Snd( s, s.name);
+ }
+
+ public static function load( path:String, streaming=false,blocking=true ) : Snd {
+ var s : Sound = loadSound(path, streaming, blocking);
+ if ( s == null) {
+ #if !prod
+ trace("no such file " + path);
+ #end
+ return null;
+ }
+ return new Snd( s, s.name);
+ }
+
+ public static function terminateTweens() {
+ TW.terminateAll();
+ }
+
+ public static function update() {
+ for ( p in PLAYING.backWardIterator())
+ if ( p.isComplete()){
+ #if !prod
+ //trace("[Snd] isComplete " + p);
+ #end
+ p.onComplete();
+ }
+ TW.update();//let tweens complete
+
+ if(!released ) Faxe.fmod_update();
+ }
+
+ public static function loadSingleBank( filename : String ) : Null{
+ if ( released ) {
+ #if debug
+ trace("FMOD not active "+filename);
+ #end
+ return null;
+ }
+
+ if ( filename.endsWith(".fsb")) {
+ #if debug
+ trace("fsb files not supported");
+ #end
+ return null;//old fmod format is not supported
+ }
+
+ var t0 = haxe.Timer.stamp();
+ var fsys = FaxeRef.getStudioSystem();
+ var fbank : cpp.RawPointer < FmodStudioBank > = null;
+
+ //trace("trying to load " + filename);
+
+ Lib.loadMode();
+ var result = fsys.loadBankFile(
+ cpp.ConstCharStar.fromString( filename ),
+ FmodStudioLoadBank.FMOD_STUDIO_LOAD_BANK_NONBLOCKING,
+ cpp.RawPointer.addressOf(fbank));
+ Lib.playMode();
+
+ if (result != FMOD_OK) {
+ #if debug
+ trace("FMOD failed to LOAD sound bank with errcode:" + result + " errmsg:" + FaxeRef.fmodResultToString(result) + "\n");
+ #end
+ return null;
+ }
+ //else
+ // trace("loading...");
+
+ var t1 = haxe.Timer.stamp();
+ #if debug
+ //trace("time to load bank:" + (t1 - t0)+"s");
+ #end
+ return cast fbank;
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/SndTV.hx b/source - Copy/SndTV.hx
new file mode 100644
index 0000000..62e69f4
--- /dev/null
+++ b/source - Copy/SndTV.hx
@@ -0,0 +1,332 @@
+import h2d.Tweenie.TType;
+
+//praise delahee, i'll figure out what this shit means later!
+
+enum TVVar{
+ TVVVolume;
+ TVVPan;
+}
+
+@:publicFields
+class TweenV {
+ static var GUID = 0;
+ var uid = 0;
+
+ var man : SndTV;
+ var parent : Snd;
+ var n : Float;
+ var ln : Float;
+ var speed : Float;
+ var from : Float;
+ var to : Float;
+ var type : TType;
+ var plays : Int; // -1 = infini, 1 et plus = nombre d'exécutions (1 par défaut)
+ var varType : TVVar;
+ var onUpdate : NullVoid>;
+ var onEnd : NullVoid>;
+ var isDebug = false;
+
+ public inline function new (
+ parent:Snd ,
+ n:Float ,
+ ln:Float ,
+ varType:TVVar,
+ speed:Float ,
+ from:Float ,
+ to:Float ,
+ type:h2d.Tweenie.TType ,
+ plays ,
+ onUpdate ,
+ onEnd
+ ) {
+ this.parent = parent ;
+ this.n = n ;
+ this.ln = ln ;
+ this.varType = varType ;
+ this.speed = speed ;
+ this.from = from ;
+ this.to = to ;
+ this.type = type ;
+ this.plays = plays ;
+ this.onUpdate = onUpdate ;
+ this.onEnd = onEnd ;
+ }
+
+ public inline function reset(
+ parent:Snd ,
+ n:Float ,
+ ln:Float ,
+ varType:TVVar,
+ speed:Float ,
+ from:Float ,
+ to:Float ,
+ type:TType ,
+ plays:Int ,
+ onUpdate ,
+ onEnd
+ ) {
+ this.parent = parent ;
+ this.n = n ;
+ this.ln = ln ;
+ this.speed = speed ;
+ this.from = from ;
+ this.to = to ;
+ this.type = type ;
+ this.plays = plays ;
+ this.onUpdate = onUpdate ;
+ this.onEnd = onEnd ;
+ this.varType = varType ;
+ isDebug = false;
+ uid = GUID++;
+ }
+
+ public function clear(){
+ n = 0.0;
+ ln = 0.0;
+ speed = 0.0;
+ plays = 0;
+ from = 0.0;
+ to = 0.0;
+ parent = null;
+ onEnd = null;
+ onUpdate = null;
+ isDebug = false;
+ uid = GUID++;
+ }
+
+
+ public
+ inline
+ function apply( val ) {
+ switch(varType){
+ case TVVVolume: {
+ parent.volume = val;
+ #if debug
+ if( isDebug )
+ trace("tv:" + val);
+ #end
+ }
+ case TVVPan: parent.pan = val;
+ }
+
+ }
+
+ public inline function kill( withCbk = true ) {
+ if ( withCbk )
+ man.terminateTween( this );
+ else
+ man.forceTerminateTween( this) ;
+ }
+
+}
+
+/**
+ * tween order is not respected
+ */
+class SndTV {
+ static var DEFAULT_DURATION = DateTools.seconds(1);
+ public var fps = 60.0;
+ public var isDebug = false;
+
+ var tlist : hxd.Stack;
+
+ public function new() {
+ tlist = new hxd.Stack();
+ tlist.reserve(8);
+ }
+
+ function onError(e) {
+ trace(e);
+ }
+
+ public function count() {
+ return tlist.length;
+ }
+
+ public inline function create(parent:Snd, vartype:TVVar, to:Float, ?tp:h2d.Tweenie.TType, ?duration_ms:Float) : TweenV{
+ return create_(parent, vartype, to, tp, duration_ms);
+ }
+
+ public function exists(p:Snd) {
+ for (t in tlist)
+ if (t.parent == p )
+ return true;
+ return false;
+ }
+
+ public var pool : hxd.Stack = new hxd.Stack();
+
+ function create_(p:Snd, vartype:TVVar,to:Float, ?tp:h2d.Tweenie.TType, ?duration_ms:Float) : TweenV{
+ if ( duration_ms==null )
+ duration_ms = DEFAULT_DURATION;
+
+ #if debug
+ if ( p == null ) trace("tween2 creation failed to:"+to+" tp:"+tp);
+ #end
+
+ if ( tp==null ) tp = TEase;
+
+ {
+ // on supprime les tweens précédents appliqués à la même variable
+ for(t in tlist.backWardIterator())
+ if(t.parent==p && t.varType == vartype) {
+ forceTerminateTween(t);
+ }
+ }
+
+ var from = switch( vartype ){
+ case TVVVolume : p.volume;
+ case TVVPan : p.pan;
+ }
+ var t : TweenV;
+ if (pool.length == 0){
+ t = new TweenV(
+ p,
+ 0.0,
+ 0.0,
+ vartype,
+ 1 / ( duration_ms*fps/1000 ), // une seconde
+ from,
+ to,
+ tp,
+ 1,
+ null,
+ null
+ );
+ }
+ else {
+ t = pool.pop();
+ t.reset(
+ p,
+ 0.0,
+ 0.0,
+ vartype,
+ 1 / ( duration_ms*fps/1000 ), // une seconde
+ from,
+ to,
+ tp,
+ 1,
+ null,
+ null
+ );
+
+ }
+
+ if( t.from==t.to )
+ t.ln = 1; // tweening inutile : mais on s'assure ainsi qu'un update() et un end() seront bien appelés
+
+ t.man = this;
+ tlist.push(t);
+
+ return t;
+ }
+
+ public static inline
+ function fastPow2(n:Float):Float {
+ return n*n;
+ }
+
+ public static inline
+ function fastPow3(n:Float):Float {
+ return n*n*n;
+ }
+
+ public static inline
+ function bezier(t:Float, p0:Float, p1:Float,p2:Float, p3:Float) {
+ return
+ fastPow3(1-t)*p0 +
+ 3*( t*fastPow2(1-t)*p1 + fastPow2(t)*(1-t)*p2 ) +
+ fastPow3(t)*p3;
+ }
+
+ // suppression du tween sans aucun appel aux callbacks onUpdate, onUpdateT et onEnd (!)
+ public function killWithoutCallbacks(parent:Snd) {
+ for (t in tlist.backWardIterator())
+ if (t.parent==parent ){
+ forceTerminateTween(t);
+ return true;
+ }
+ return false;
+ }
+
+ public function terminate(parent:Snd) {
+ for (t in tlist.backWardIterator())
+ if (t.parent==parent){
+ forceTerminateTween(t);
+ }
+ }
+
+ public function forceTerminateTween(t:TweenV) {
+ var tOk = tlist.remove(t);
+ if( tOk ){
+ t.clear();
+ pool.push(t);
+ }
+ }
+
+ public function terminateTween(t:TweenV, ?fl_allowLoop=false) {
+ var v = t.from + (t.to - t.from) * h2d.Tweenie.interp(t.type, 1);
+ t.apply(v);
+ onUpdate(t, 1);
+
+ var ouid = t.uid;
+
+ onEnd(t);
+
+ if( ouid == t.uid ){
+ if( fl_allowLoop && (t.plays==-1 || t.plays>1) ) {
+ if( t.plays!=-1 )
+ t.plays--;
+ t.n = t.ln = 0;
+ }
+ else {
+ forceTerminateTween(t);
+ }
+ }
+ }
+
+ public function terminateAll() {
+ for(t in tlist)
+ t.ln = 1;
+ update();
+ }
+
+ inline
+ function onUpdate(t:TweenV, n:Float) {
+ if ( t.onUpdate!=null )
+ t.onUpdate(t);
+ }
+
+ inline
+ function onEnd(t:TweenV) {
+ if ( t.onEnd!=null )
+ t.onEnd(t);
+ }
+
+ public function update(?tmod = 1.0) {
+ if ( tlist.length > 0 ) {
+ for (t in tlist.backWardIterator() ) {
+ var dist = t.to-t.from;
+ if (t.type==TRand)
+ t.ln+=if(Std.random(100)<33) t.speed * tmod else 0;
+ else
+ t.ln += t.speed * tmod;
+
+ t.n = h2d.Tweenie.interp(t.type, t.ln);
+
+ if ( t.ln<1 ) {
+ // en cours...
+ var val = t.from + t.n*dist;
+
+ t.apply(val);
+
+ onUpdate(t, t.ln);
+ }
+ else // fini !
+ {
+ terminateTween(t, true);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/Song.hx b/source - Copy/Song.hx
new file mode 100644
index 0000000..5329079
--- /dev/null
+++ b/source - Copy/Song.hx
@@ -0,0 +1,93 @@
+package;
+
+import Section.SwagSection;
+import haxe.Json;
+import haxe.format.JsonParser;
+import lime.utils.Assets;
+
+using StringTools;
+
+typedef SwagSong =
+{
+ var song:String;
+ var notes:Array;
+ var bpm:Float;
+ var needsVoices:Bool;
+ var speed:Float;
+
+ var player1:String;
+ var player2:String;
+ var gfVersion:String;
+ var noteStyle:String;
+ var stage:String;
+ var validScore:Bool;
+}
+
+class Song
+{
+ public var song:String;
+ public var notes:Array;
+ public var bpm:Float;
+ public var needsVoices:Bool = true;
+ public var speed:Float = 1;
+
+ public var player1:String = 'bf';
+ public var player2:String = 'dad';
+ public var gfVersion:String = '';
+ public var noteStyle:String = '';
+ public var stage:String = '';
+
+ public function new(song, notes, bpm)
+ {
+ this.song = song;
+ this.notes = notes;
+ this.bpm = bpm;
+ }
+
+ public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong
+ {
+ trace(jsonInput);
+
+ // pre lowercasing the folder name
+ var folderLowercase = StringTools.replace(folder, " ", "-").toLowerCase();
+ switch (folderLowercase) {
+ case 'dad-battle': folderLowercase = 'dadbattle';
+ case 'philly-nice': folderLowercase = 'philly';
+ }
+
+ trace('loading ' + folderLowercase + '/' + jsonInput.toLowerCase());
+
+ var rawJson = Assets.getText(Paths.json(folderLowercase + '/' + jsonInput.toLowerCase())).trim();
+
+ while (!rawJson.endsWith("}"))
+ {
+ rawJson = rawJson.substr(0, rawJson.length - 1);
+ // LOL GOING THROUGH THE BULLSHIT TO CLEAN IDK WHATS STRANGE
+ }
+
+ // FIX THE CASTING ON WINDOWS/NATIVE
+ // Windows???
+ // trace(songData);
+
+ // trace('LOADED FROM JSON: ' + songData.notes);
+ /*
+ for (i in 0...songData.notes.length)
+ {
+ trace('LOADED FROM JSON: ' + songData.notes[i].sectionNotes);
+ // songData.notes[i].sectionNotes = songData.notes[i].sectionNotes
+ }
+
+ daNotes = songData.notes;
+ daSong = songData.song;
+ daBpm = songData.bpm; */
+
+ return parseJSONshit(rawJson);
+ }
+
+ public static function parseJSONshit(rawJson:String):SwagSong
+ {
+ var swagShit:SwagSong = cast Json.parse(rawJson).song;
+ swagShit.validScore = true;
+ return swagShit;
+ }
+}
diff --git a/source - Copy/StoryMenuState.hx b/source - Copy/StoryMenuState.hx
new file mode 100644
index 0000000..443b8e0
--- /dev/null
+++ b/source - Copy/StoryMenuState.hx
@@ -0,0 +1,403 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.group.FlxGroup;
+import flixel.math.FlxMath;
+import flixel.text.FlxText;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
+import lime.net.curl.CURLCode;
+
+#if windows
+import Discord.DiscordClient;
+#end
+
+using StringTools;
+
+class StoryMenuState extends MusicBeatState
+{
+ var scoreText:FlxText;
+
+ var weekData:Array = [
+ ['Tutorial'],
+ ['Bopeebo', 'Fresh', 'Dad Battle'],
+ ['Spookeez', 'South', "Monster"],
+ ['Pico', 'Philly Nice', "Blammed"],
+ ['Satin Panties', "High", "Milf"],
+ ['Cocoa', 'Eggnog', 'Winter Horrorland'],
+ ['Senpai', 'Roses', 'Thorns']
+ ];
+ var curDifficulty:Int = 1;
+
+ public static var weekUnlocked:Array = [true, true, true, true, true, true, true];
+
+ var weekCharacters:Array = [
+ ['', 'bf', 'gf'],
+ ['dad', 'bf', 'gf'],
+ ['spooky', 'bf', 'gf'],
+ ['pico', 'bf', 'gf'],
+ ['mom', 'bf', 'gf'],
+ ['parents-christmas', 'bf', 'gf'],
+ ['senpai', 'bf', 'gf']
+ ];
+
+ var weekNames:Array = [
+ "",
+ "Daddy Dearest",
+ "Spooky Month",
+ "PICO",
+ "MOMMY MUST MURDER",
+ "RED SNOW",
+ "Hating Simulator ft. Moawling"
+ ];
+
+ var txtWeekTitle:FlxText;
+
+ var curWeek:Int = 0;
+
+ var txtTracklist:FlxText;
+
+ var grpWeekText:FlxTypedGroup;
+ var grpWeekCharacters:FlxTypedGroup;
+
+ var grpLocks:FlxTypedGroup;
+
+ var difficultySelectors:FlxGroup;
+ var sprDifficulty:FlxSprite;
+ var leftArrow:FlxSprite;
+ var rightArrow:FlxSprite;
+
+ override function create()
+ {
+ #if windows
+ // Updating Discord Rich Presence
+ DiscordClient.changePresence("In the Story Mode Menu", null);
+ #end
+
+ transIn = FlxTransitionableState.defaultTransIn;
+ transOut = FlxTransitionableState.defaultTransOut;
+
+ if (FlxG.sound.music != null)
+ {
+ if (!FlxG.sound.music.playing)
+ FlxG.sound.playMusic(Paths.music('freakyMenu'));
+ }
+
+ persistentUpdate = persistentDraw = true;
+
+ scoreText = new FlxText(10, 10, 0, "SCORE: 49324858", 36);
+ scoreText.setFormat("VCR OSD Mono", 32);
+
+ txtWeekTitle = new FlxText(FlxG.width * 0.7, 10, 0, "", 32);
+ txtWeekTitle.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, RIGHT);
+ txtWeekTitle.alpha = 0.7;
+
+ var rankText:FlxText = new FlxText(0, 10);
+ rankText.text = 'RANK: GREAT';
+ rankText.setFormat(Paths.font("vcr.ttf"), 32);
+ rankText.size = scoreText.size;
+ rankText.screenCenter(X);
+
+ var ui_tex = Paths.getSparrowAtlas('campaign_menu_UI_assets');
+ var yellowBG:FlxSprite = new FlxSprite(0, 56).makeGraphic(FlxG.width, 400, 0xFFF9CF51);
+
+ grpWeekText = new FlxTypedGroup();
+ add(grpWeekText);
+
+ var blackBarThingie:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 56, FlxColor.BLACK);
+ add(blackBarThingie);
+
+ grpWeekCharacters = new FlxTypedGroup();
+
+ grpLocks = new FlxTypedGroup();
+ add(grpLocks);
+
+ trace("Line 70");
+
+ for (i in 0...weekData.length)
+ {
+ var weekThing:MenuItem = new MenuItem(0, yellowBG.y + yellowBG.height + 10, i);
+ weekThing.y += ((weekThing.height + 20) * i);
+ weekThing.targetY = i;
+ grpWeekText.add(weekThing);
+
+ weekThing.screenCenter(X);
+ weekThing.antialiasing = true;
+ // weekThing.updateHitbox();
+
+ // Needs an offset thingie
+ if (!weekUnlocked[i])
+ {
+ var lock:FlxSprite = new FlxSprite(weekThing.width + 10 + weekThing.x);
+ lock.frames = ui_tex;
+ lock.animation.addByPrefix('lock', 'lock');
+ lock.animation.play('lock');
+ lock.ID = i;
+ lock.antialiasing = true;
+ grpLocks.add(lock);
+ }
+ }
+
+ trace("Line 96");
+
+ grpWeekCharacters.add(new MenuCharacter(0, 100, 0.5, false));
+ grpWeekCharacters.add(new MenuCharacter(450, 25, 0.9, true));
+ grpWeekCharacters.add(new MenuCharacter(850, 100, 0.5, true));
+
+ difficultySelectors = new FlxGroup();
+ add(difficultySelectors);
+
+ trace("Line 124");
+
+ leftArrow = new FlxSprite(grpWeekText.members[0].x + grpWeekText.members[0].width + 10, grpWeekText.members[0].y + 10);
+ leftArrow.frames = ui_tex;
+ leftArrow.animation.addByPrefix('idle', "arrow left");
+ leftArrow.animation.addByPrefix('press', "arrow push left");
+ leftArrow.animation.play('idle');
+ difficultySelectors.add(leftArrow);
+
+ sprDifficulty = new FlxSprite(leftArrow.x + 130, leftArrow.y);
+ sprDifficulty.frames = ui_tex;
+ sprDifficulty.animation.addByPrefix('easy', 'EASY');
+ sprDifficulty.animation.addByPrefix('normal', 'NORMAL');
+ sprDifficulty.animation.addByPrefix('hard', 'HARD');
+ sprDifficulty.animation.play('easy');
+ changeDifficulty();
+
+ difficultySelectors.add(sprDifficulty);
+
+ rightArrow = new FlxSprite(sprDifficulty.x + sprDifficulty.width + 50, leftArrow.y);
+ rightArrow.frames = ui_tex;
+ rightArrow.animation.addByPrefix('idle', 'arrow right');
+ rightArrow.animation.addByPrefix('press', "arrow push right", 24, false);
+ rightArrow.animation.play('idle');
+ difficultySelectors.add(rightArrow);
+
+ trace("Line 150");
+
+ add(yellowBG);
+ add(grpWeekCharacters);
+
+ txtTracklist = new FlxText(FlxG.width * 0.05, yellowBG.x + yellowBG.height + 100, 0, "Tracks", 32);
+ txtTracklist.alignment = CENTER;
+ txtTracklist.font = rankText.font;
+ txtTracklist.color = 0xFFe55777;
+ add(txtTracklist);
+ // add(rankText);
+ add(scoreText);
+ add(txtWeekTitle);
+
+ updateText();
+
+ trace("Line 165");
+
+ super.create();
+ }
+
+ override function update(elapsed:Float)
+ {
+ // scoreText.setFormat('VCR OSD Mono', 32);
+ lerpScore = Math.floor(FlxMath.lerp(lerpScore, intendedScore, 0.5));
+
+ scoreText.text = "WEEK SCORE:" + lerpScore;
+
+ txtWeekTitle.text = weekNames[curWeek].toUpperCase();
+ txtWeekTitle.x = FlxG.width - (txtWeekTitle.width + 10);
+
+ // FlxG.watch.addQuick('font', scoreText.font);
+
+ difficultySelectors.visible = weekUnlocked[curWeek];
+
+ grpLocks.forEach(function(lock:FlxSprite)
+ {
+ lock.y = grpWeekText.members[lock.ID].y;
+ });
+
+ if (!movedBack)
+ {
+ if (!selectedWeek)
+ {
+ if (controls.UP_P)
+ {
+ changeWeek(-1);
+ }
+
+ if (controls.DOWN_P)
+ {
+ changeWeek(1);
+ }
+
+ if (controls.RIGHT)
+ rightArrow.animation.play('press')
+ else
+ rightArrow.animation.play('idle');
+
+ if (controls.LEFT)
+ leftArrow.animation.play('press');
+ else
+ leftArrow.animation.play('idle');
+
+ if (controls.RIGHT_P)
+ changeDifficulty(1);
+ if (controls.LEFT_P)
+ changeDifficulty(-1);
+ }
+
+ if (controls.ACCEPT)
+ {
+ selectWeek();
+ }
+ }
+
+ if (controls.BACK && !movedBack && !selectedWeek)
+ {
+ FlxG.sound.play(Paths.sound('cancelMenu'));
+ movedBack = true;
+ FlxG.switchState(new MainMenuState());
+ }
+
+ super.update(elapsed);
+ }
+
+ var movedBack:Bool = false;
+ var selectedWeek:Bool = false;
+ var stopspamming:Bool = false;
+
+ function selectWeek()
+ {
+ if (weekUnlocked[curWeek])
+ {
+ if (stopspamming == false)
+ {
+ FlxG.sound.play(Paths.sound('confirmMenu'));
+
+ grpWeekText.members[curWeek].startFlashing();
+ grpWeekCharacters.members[1].animation.play('bfConfirm');
+ stopspamming = true;
+ }
+
+ PlayState.storyPlaylist = weekData[curWeek];
+ PlayState.isStoryMode = true;
+ selectedWeek = true;
+
+
+ PlayState.storyDifficulty = curDifficulty;
+
+ // adjusting the song name to be compatible
+ var songFormat = StringTools.replace(PlayState.storyPlaylist[0], " ", "-");
+ switch (songFormat) {
+ case 'Dad-Battle': songFormat = 'Dadbattle';
+ case 'Philly-Nice': songFormat = 'Philly';
+ }
+
+ var poop:String = Highscore.formatSong(songFormat, curDifficulty);
+ PlayState.sicks = 0;
+ PlayState.bads = 0;
+ PlayState.shits = 0;
+ PlayState.goods = 0;
+ PlayState.campaignMisses = 0;
+ PlayState.SONG = Song.loadFromJson(poop, PlayState.storyPlaylist[0]);
+ PlayState.storyWeek = curWeek;
+ PlayState.campaignScore = 0;
+ new FlxTimer().start(1, function(tmr:FlxTimer)
+ {
+ LoadingState.loadAndSwitchState(new PlayState(), true);
+ });
+ }
+ }
+
+ function changeDifficulty(change:Int = 0):Void
+ {
+ curDifficulty += change;
+
+ if (curDifficulty < 0)
+ curDifficulty = 2;
+ if (curDifficulty > 2)
+ curDifficulty = 0;
+
+ sprDifficulty.offset.x = 0;
+
+ switch (curDifficulty)
+ {
+ case 0:
+ sprDifficulty.animation.play('easy');
+ sprDifficulty.offset.x = 20;
+ case 1:
+ sprDifficulty.animation.play('normal');
+ sprDifficulty.offset.x = 70;
+ case 2:
+ sprDifficulty.animation.play('hard');
+ sprDifficulty.offset.x = 20;
+ }
+
+ sprDifficulty.alpha = 0;
+
+ // USING THESE WEIRD VALUES SO THAT IT DOESNT FLOAT UP
+ sprDifficulty.y = leftArrow.y - 15;
+ intendedScore = Highscore.getWeekScore(curWeek, curDifficulty);
+
+ #if !switch
+ intendedScore = Highscore.getWeekScore(curWeek, curDifficulty);
+ #end
+
+ FlxTween.tween(sprDifficulty, {y: leftArrow.y + 15, alpha: 1}, 0.07);
+ }
+
+ var lerpScore:Int = 0;
+ var intendedScore:Int = 0;
+
+ function changeWeek(change:Int = 0):Void
+ {
+ curWeek += change;
+
+ if (curWeek >= weekData.length)
+ curWeek = 0;
+ if (curWeek < 0)
+ curWeek = weekData.length - 1;
+
+ var bullShit:Int = 0;
+
+ for (item in grpWeekText.members)
+ {
+ item.targetY = bullShit - curWeek;
+ if (item.targetY == Std.int(0) && weekUnlocked[curWeek])
+ item.alpha = 1;
+ else
+ item.alpha = 0.6;
+ bullShit++;
+ }
+
+ FlxG.sound.play(Paths.sound('scrollMenu'));
+
+ updateText();
+ }
+
+ function updateText()
+ {
+ grpWeekCharacters.members[0].setCharacter(weekCharacters[curWeek][0]);
+ grpWeekCharacters.members[1].setCharacter(weekCharacters[curWeek][1]);
+ grpWeekCharacters.members[2].setCharacter(weekCharacters[curWeek][2]);
+
+ txtTracklist.text = "Tracks\n";
+ var stringThing:Array = weekData[curWeek];
+
+ for (i in stringThing)
+ txtTracklist.text += "\n" + i;
+
+ txtTracklist.text = txtTracklist.text.toUpperCase();
+
+ txtTracklist.screenCenter(X);
+ txtTracklist.x -= FlxG.width * 0.35;
+
+ txtTracklist.text += "\n";
+
+ #if !switch
+ intendedScore = Highscore.getWeekScore(curWeek, curDifficulty);
+ #end
+ }
+}
diff --git a/source - Copy/TitleState.hx b/source - Copy/TitleState.hx
new file mode 100644
index 0000000..b156d57
--- /dev/null
+++ b/source - Copy/TitleState.hx
@@ -0,0 +1,479 @@
+package;
+
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.FlxState;
+import flixel.addons.display.FlxGridOverlay;
+import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
+import flixel.addons.transition.FlxTransitionableState;
+import flixel.addons.transition.TransitionData;
+import flixel.graphics.FlxGraphic;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.group.FlxGroup;
+import flixel.input.gamepad.FlxGamepad;
+import flixel.math.FlxPoint;
+import flixel.math.FlxRect;
+import flixel.system.FlxSound;
+import flixel.system.ui.FlxSoundTray;
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.util.FlxColor;
+import flixel.util.FlxTimer;
+import io.newgrounds.NG;
+import lime.app.Application;
+import openfl.Assets;
+
+#if windows
+import Discord.DiscordClient;
+#end
+
+#if cpp
+import sys.thread.Thread;
+#end
+
+using StringTools;
+
+class TitleState extends MusicBeatState
+{
+ static var initialized:Bool = false;
+
+ var blackScreen:FlxSprite;
+ var credGroup:FlxGroup;
+ var credTextShit:Alphabet;
+ var textGroup:FlxGroup;
+ var ngSpr:FlxSprite;
+
+ var curWacky:Array = [];
+
+ var wackyImage:FlxSprite;
+
+ override public function create():Void
+ {
+ #if polymod
+ polymod.Polymod.init({modRoot: "mods", dirs: ['introMod']});
+ #end
+
+ #if sys
+ if (!sys.FileSystem.exists(Sys.getCwd() + "/assets/replays"))
+ sys.FileSystem.createDirectory(Sys.getCwd() + "/assets/replays");
+ #end
+
+ @:privateAccess
+ {
+ trace("Loaded " + openfl.Assets.getLibrary("default").assetsLoaded + " assets (DEFAULT)");
+ }
+
+ PlayerSettings.init();
+
+ #if windows
+ DiscordClient.initialize();
+
+ Application.current.onExit.add (function (exitCode) {
+ DiscordClient.shutdown();
+ });
+
+ #end
+
+ curWacky = FlxG.random.getObject(getIntroTextShit());
+
+ // DEBUG BULLSHIT
+
+ super.create();
+
+ // NGio.noLogin(APIStuff.API);
+
+ #if ng
+ var ng:NGio = new NGio(APIStuff.API, APIStuff.EncKey);
+ trace('NEWGROUNDS LOL');
+ #end
+
+ FlxG.save.bind('funkin', 'ninjamuffin99');
+
+ KadeEngineData.initSave();
+
+ Highscore.load();
+
+ if (FlxG.save.data.weekUnlocked != null)
+ {
+ // FIX LATER!!!
+ // WEEK UNLOCK PROGRESSION!!
+ // StoryMenuState.weekUnlocked = FlxG.save.data.weekUnlocked;
+
+ if (StoryMenuState.weekUnlocked.length < 4)
+ StoryMenuState.weekUnlocked.insert(0, true);
+
+ // QUICK PATCH OOPS!
+ if (!StoryMenuState.weekUnlocked[0])
+ StoryMenuState.weekUnlocked[0] = true;
+ }
+
+ #if FREEPLAY
+ FlxG.switchState(new FreeplayState());
+ #elseif CHARTING
+ FlxG.switchState(new ChartingState());
+ #else
+ new FlxTimer().start(1, function(tmr:FlxTimer)
+ {
+ startIntro();
+ });
+ #end
+ }
+
+ var logoBl:FlxSprite;
+ var gfDance:FlxSprite;
+ var danceLeft:Bool = false;
+ var titleText:FlxSprite;
+
+ function startIntro()
+ {
+ if (!initialized)
+ {
+ var diamond:FlxGraphic = FlxGraphic.fromClass(GraphicTransTileDiamond);
+ diamond.persist = true;
+ diamond.destroyOnNoUse = false;
+
+ FlxTransitionableState.defaultTransIn = new TransitionData(FADE, FlxColor.BLACK, 1, new FlxPoint(0, -1), {asset: diamond, width: 32, height: 32},
+ new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
+ FlxTransitionableState.defaultTransOut = new TransitionData(FADE, FlxColor.BLACK, 0.7, new FlxPoint(0, 1),
+ {asset: diamond, width: 32, height: 32}, new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
+
+ transIn = FlxTransitionableState.defaultTransIn;
+ transOut = FlxTransitionableState.defaultTransOut;
+
+ // HAD TO MODIFY SOME BACKEND SHIT
+ // IF THIS PR IS HERE IF ITS ACCEPTED UR GOOD TO GO
+ // https://github.com/HaxeFlixel/flixel-addons/pull/348
+
+ // var music:FlxSound = new FlxSound();
+ // music.loadStream(Paths.music('freakyMenu'));
+ // FlxG.sound.list.add(music);
+ // music.play();
+ FlxG.sound.playMusic(Paths.music('freakyMenu'), 0);
+
+ FlxG.sound.music.fadeIn(4, 0, 0.7);
+ }
+
+ Conductor.changeBPM(102);
+ persistentUpdate = true;
+
+ var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
+ // bg.antialiasing = true;
+ // bg.setGraphicSize(Std.int(bg.width * 0.6));
+ // bg.updateHitbox();
+ add(bg);
+
+ if(Main.watermarks) {
+ logoBl = new FlxSprite(-150, -100);
+ logoBl.frames = Paths.getSparrowAtlas('KadeEngineLogoBumpin');
+ logoBl.antialiasing = true;
+ logoBl.animation.addByPrefix('bump', 'logo bumpin', 24);
+ logoBl.animation.play('bump');
+ logoBl.updateHitbox();
+ // logoBl.screenCenter();
+ // logoBl.color = FlxColor.BLACK;
+ } else {
+ logoBl = new FlxSprite(-150, -100);
+ logoBl.frames = Paths.getSparrowAtlas('logoBumpin');
+ logoBl.antialiasing = true;
+ logoBl.animation.addByPrefix('bump', 'logo bumpin', 24);
+ logoBl.animation.play('bump');
+ logoBl.updateHitbox();
+ // logoBl.screenCenter();
+ // logoBl.color = FlxColor.BLACK;
+ }
+
+ gfDance = new FlxSprite(FlxG.width * 0.4, FlxG.height * 0.07);
+ gfDance.frames = Paths.getSparrowAtlas('gfDanceTitle');
+ gfDance.animation.addByIndices('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
+ gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
+ gfDance.antialiasing = true;
+ add(gfDance);
+ add(logoBl);
+
+ titleText = new FlxSprite(100, FlxG.height * 0.8);
+ titleText.frames = Paths.getSparrowAtlas('titleEnter');
+ titleText.animation.addByPrefix('idle', "Press Enter to Begin", 24);
+ titleText.animation.addByPrefix('press', "ENTER PRESSED", 24);
+ titleText.antialiasing = true;
+ titleText.animation.play('idle');
+ titleText.updateHitbox();
+ // titleText.screenCenter(X);
+ add(titleText);
+
+ var logo:FlxSprite = new FlxSprite().loadGraphic(Paths.image('logo'));
+ logo.screenCenter();
+ logo.antialiasing = true;
+ // add(logo);
+
+ // FlxTween.tween(logoBl, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG});
+ // FlxTween.tween(logo, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG, startDelay: 0.1});
+
+ credGroup = new FlxGroup();
+ add(credGroup);
+ textGroup = new FlxGroup();
+
+ blackScreen = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
+ credGroup.add(blackScreen);
+
+ credTextShit = new Alphabet(0, 0, "ninjamuffin99\nPhantomArcade\nkawaisprite\nevilsk8er", true);
+ credTextShit.screenCenter();
+
+ // credTextShit.alignment = CENTER;
+
+ credTextShit.visible = false;
+
+ ngSpr = new FlxSprite(0, FlxG.height * 0.52).loadGraphic(Paths.image('newgrounds_logo'));
+ add(ngSpr);
+ ngSpr.visible = false;
+ ngSpr.setGraphicSize(Std.int(ngSpr.width * 0.8));
+ ngSpr.updateHitbox();
+ ngSpr.screenCenter(X);
+ ngSpr.antialiasing = true;
+
+ FlxTween.tween(credTextShit, {y: credTextShit.y + 20}, 2.9, {ease: FlxEase.quadInOut, type: PINGPONG});
+
+ FlxG.mouse.visible = false;
+
+ if (initialized)
+ skipIntro();
+ else
+ initialized = true;
+
+ // credGroup.add(credTextShit);
+ }
+
+ function getIntroTextShit():Array>
+ {
+ var fullText:String = Assets.getText(Paths.txt('introText'));
+
+ var firstArray:Array = fullText.split('\n');
+ var swagGoodArray:Array> = [];
+
+ for (i in firstArray)
+ {
+ swagGoodArray.push(i.split('--'));
+ }
+
+ return swagGoodArray;
+ }
+
+ var transitioning:Bool = false;
+
+ override function update(elapsed:Float)
+ {
+ if (FlxG.sound.music != null)
+ Conductor.songPosition = FlxG.sound.music.time;
+ // FlxG.watch.addQuick('amp', FlxG.sound.music.amplitude);
+
+ if (FlxG.keys.justPressed.F)
+ {
+ FlxG.fullscreen = !FlxG.fullscreen;
+ }
+
+ var pressedEnter:Bool = FlxG.keys.justPressed.ENTER;
+
+ #if mobile
+ for (touch in FlxG.touches.list)
+ {
+ if (touch.justPressed)
+ {
+ pressedEnter = true;
+ }
+ }
+ #end
+
+ var gamepad:FlxGamepad = FlxG.gamepads.lastActive;
+
+ if (gamepad != null)
+ {
+ if (gamepad.justPressed.START)
+ pressedEnter = true;
+
+ #if switch
+ if (gamepad.justPressed.B)
+ pressedEnter = true;
+ #end
+ }
+
+ if (pressedEnter && !transitioning && skippedIntro)
+ {
+ #if !switch
+ NGio.unlockMedal(60960);
+
+ // If it's Friday according to da clock
+ if (Date.now().getDay() == 5)
+ NGio.unlockMedal(61034);
+ #end
+
+ if (FlxG.save.data.flashing)
+ titleText.animation.play('press');
+
+ FlxG.camera.flash(FlxColor.WHITE, 1);
+ FlxG.sound.play(Paths.sound('confirmMenu'), 0.7);
+
+ transitioning = true;
+ // FlxG.sound.music.stop();
+
+ MainMenuState.firstStart = true;
+
+ new FlxTimer().start(2, function(tmr:FlxTimer)
+ {
+ // Get current version of Kade Engine
+
+ var http = new haxe.Http("https://raw.githubusercontent.com/KadeDev/Kade-Engine/master/version.downloadMe");
+ var returnedData:Array = [];
+
+ http.onData = function (data:String)
+ {
+ returnedData[0] = data.substring(0, data.indexOf(';'));
+ returnedData[1] = data.substring(data.indexOf('-'), data.length);
+ if (!MainMenuState.kadeEngineVer.contains(returnedData[0].trim()) && !OutdatedSubState.leftState && MainMenuState.nightly == "")
+ {
+ trace('outdated lmao! ' + returnedData[0] + ' != ' + MainMenuState.kadeEngineVer);
+ OutdatedSubState.needVer = returnedData[0];
+ OutdatedSubState.currChanges = returnedData[1];
+ FlxG.switchState(new OutdatedSubState());
+ }
+ else
+ {
+ FlxG.switchState(new MainMenuState());
+ }
+ }
+
+ http.onError = function (error) {
+ trace('error: $error');
+ FlxG.switchState(new MainMenuState()); // fail but we go anyway
+ }
+
+ http.request();
+ });
+ // FlxG.sound.play(Paths.music('titleShoot'), 0.7);
+ }
+
+ if (pressedEnter && !skippedIntro && initialized)
+ {
+ skipIntro();
+ }
+
+ super.update(elapsed);
+ }
+
+ function createCoolText(textArray:Array)
+ {
+ for (i in 0...textArray.length)
+ {
+ var money:Alphabet = new Alphabet(0, 0, textArray[i], true, false);
+ money.screenCenter(X);
+ money.y += (i * 60) + 200;
+ credGroup.add(money);
+ textGroup.add(money);
+ }
+ }
+
+ function addMoreText(text:String)
+ {
+ var coolText:Alphabet = new Alphabet(0, 0, text, true, false);
+ coolText.screenCenter(X);
+ coolText.y += (textGroup.length * 60) + 200;
+ credGroup.add(coolText);
+ textGroup.add(coolText);
+ }
+
+ function deleteCoolText()
+ {
+ while (textGroup.members.length > 0)
+ {
+ credGroup.remove(textGroup.members[0], true);
+ textGroup.remove(textGroup.members[0], true);
+ }
+ }
+
+ override function beatHit()
+ {
+ super.beatHit();
+
+ logoBl.animation.play('bump');
+ danceLeft = !danceLeft;
+
+ if (danceLeft)
+ gfDance.animation.play('danceRight');
+ else
+ gfDance.animation.play('danceLeft');
+
+ FlxG.log.add(curBeat);
+
+ switch (curBeat)
+ {
+ case 1:
+ createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']);
+ // credTextShit.visible = true;
+ case 3:
+ addMoreText('present');
+ // credTextShit.text += '\npresent...';
+ // credTextShit.addText();
+ case 4:
+ deleteCoolText();
+ // credTextShit.visible = false;
+ // credTextShit.text = 'In association \nwith';
+ // credTextShit.screenCenter();
+ case 5:
+ if (Main.watermarks)
+ createCoolText(['Kade Engine', 'by']);
+ else
+ createCoolText(['In Partnership', 'with']);
+ case 7:
+ if (Main.watermarks)
+ addMoreText('KadeDeveloper');
+ else
+ {
+ addMoreText('Newgrounds');
+ ngSpr.visible = true;
+ }
+ // credTextShit.text += '\nNewgrounds';
+ case 8:
+ deleteCoolText();
+ ngSpr.visible = false;
+ // credTextShit.visible = false;
+
+ // credTextShit.text = 'Shoutouts Tom Fulp';
+ // credTextShit.screenCenter();
+ case 9:
+ createCoolText([curWacky[0]]);
+ // credTextShit.visible = true;
+ case 11:
+ addMoreText(curWacky[1]);
+ // credTextShit.text += '\nlmao';
+ case 12:
+ deleteCoolText();
+ // credTextShit.visible = false;
+ // credTextShit.text = "Friday";
+ // credTextShit.screenCenter();
+ case 13:
+ addMoreText('Friday');
+ // credTextShit.visible = true;
+ case 14:
+ addMoreText('Night');
+ // credTextShit.text += '\nNight';
+ case 15:
+ addMoreText('Funkin'); // credTextShit.text += '\nFunkin';
+
+ case 16:
+ skipIntro();
+ }
+ }
+
+ var skippedIntro:Bool = false;
+
+ function skipIntro():Void
+ {
+ if (!skippedIntro)
+ {
+ remove(ngSpr);
+
+ FlxG.camera.flash(FlxColor.WHITE, 4);
+ remove(credGroup);
+ skippedIntro = true;
+ }
+ }
+}
diff --git a/source - Copy/VideoHandler.hx b/source - Copy/VideoHandler.hx
new file mode 100644
index 0000000..1b01699
--- /dev/null
+++ b/source - Copy/VideoHandler.hx
@@ -0,0 +1,195 @@
+//This was made by GWebDev lol btw this uses actuate
+package;
+
+import motion.Actuate;
+import openfl.display.Sprite;
+import openfl.events.AsyncErrorEvent;
+import openfl.events.MouseEvent;
+import openfl.events.NetStatusEvent;
+import openfl.media.Video;
+import openfl.net.NetConnection;
+import openfl.net.NetStream;
+import flixel.FlxG;
+
+using StringTools;
+
+class VideoHandler
+{
+ public var netStream:NetStream;
+ public var video:Video;
+ public var isReady:Bool = false;
+ public var addOverlay:Bool = false;
+ public var vidPath:String = "";
+ public var ignoreShit:Bool = false;
+
+ public function new()
+ {
+ isReady = false;
+ }
+
+ public function source(?vPath:String):Void
+ {
+ if (vPath != null && vPath.length > 0)
+ {
+ vidPath = vPath;
+ }
+ }
+
+ public function init1():Void
+ {
+ isReady = false;
+ video = new Video();
+ video.visible = false;
+ }
+
+ public function init2():Void
+ {
+ #if web
+ var netConnection = new NetConnection ();
+ netConnection.connect (null);
+
+ netStream = new NetStream (netConnection);
+ netStream.client = { onMetaData: client_onMetaData };
+ netStream.addEventListener (AsyncErrorEvent.ASYNC_ERROR, netStream_onAsyncError);
+
+ netConnection.addEventListener (NetStatusEvent.NET_STATUS, netConnection_onNetStatus);
+ netConnection.addEventListener (NetStatusEvent.NET_STATUS, onPlay);
+ netConnection.addEventListener (NetStatusEvent.NET_STATUS, onEnd);
+ #end
+ }
+
+ public function client_onMetaData (metaData:Dynamic) {
+
+ video.attachNetStream (netStream);
+
+ video.width = FlxG.width;
+ video.height = FlxG.height;
+
+ }
+
+
+ public function netStream_onAsyncError (event:AsyncErrorEvent):Void {
+
+ trace ("Error loading video");
+
+ }
+
+
+ public function netConnection_onNetStatus (event:NetStatusEvent):Void {
+ trace (event.info.code);
+ }
+
+ public function play():Void
+ {
+ #if web
+ ignoreShit = true;
+ netStream.close();
+ init2();
+ netStream.play(vidPath);
+ ignoreShit = false;
+ #end
+ trace(vidPath);
+ }
+
+ public function stop():Void
+ {
+ netStream.close();
+ onStop();
+ }
+
+ public function restart():Void
+ {
+ play();
+ onRestart();
+ }
+
+ public function update(elapsed:Float):Void
+ {
+ video.x = GlobalVideo.calc(0);
+ video.y = GlobalVideo.calc(1);
+ video.width = GlobalVideo.calc(2);
+ video.height = GlobalVideo.calc(3);
+ }
+
+ public var stopped:Bool = false;
+ public var restarted:Bool = false;
+ public var played:Bool = false;
+ public var ended:Bool = false;
+ public var paused:Bool = false;
+
+ public function pause():Void
+ {
+ netStream.pause();
+ paused = true;
+ }
+
+ public function resume():Void
+ {
+ netStream.resume();
+ paused = false;
+ }
+
+ public function togglePause():Void
+ {
+ if (paused)
+ {
+ resume();
+ } else {
+ pause();
+ }
+ }
+
+ public function clearPause():Void
+ {
+ paused = false;
+ }
+
+ public function onStop():Void
+ {
+ if (!ignoreShit)
+ {
+ stopped = true;
+ }
+ }
+
+ public function onRestart():Void
+ {
+ restarted = true;
+ }
+
+ public function onPlay(event:NetStatusEvent):Void
+ {
+ if (event.info.code == "NetStream.Play.Start")
+ {
+ played = true;
+ }
+ }
+
+ public function onEnd(event:NetStatusEvent):Void
+ {
+ if (event.info.code == "NetStream.Play.Complete")
+ {
+ ended = true;
+ }
+ }
+
+ public function alpha():Void
+ {
+ video.alpha = GlobalVideo.daAlpha1;
+ }
+
+ public function unalpha():Void
+ {
+ video.alpha = GlobalVideo.daAlpha2;
+ }
+
+ public function hide():Void
+ {
+ video.visible = false;
+ }
+
+ public function show():Void
+ {
+ video.visible = true;
+ }
+}
\ No newline at end of file
diff --git a/source - Copy/WebmHandler.hx b/source - Copy/WebmHandler.hx
new file mode 100644
index 0000000..77b9391
--- /dev/null
+++ b/source - Copy/WebmHandler.hx
@@ -0,0 +1,169 @@
+package;
+
+import flixel.FlxG;
+import openfl.display.Sprite;
+#if desktop
+import webm.*;
+#end
+
+class WebmHandler
+{
+ #if desktop
+ public var webm:WebmPlayer;
+ public var vidPath:String = "";
+ public var io:WebmIo;
+ public var initialized:Bool = false;
+
+ public function new()
+ {
+ }
+
+ public function source(?vPath:String):Void
+ {
+ if (vPath != null && vPath.length > 0)
+ {
+ vidPath = vPath;
+ }
+ }
+
+ public function makePlayer():Void
+ {
+ io = new WebmIoFile(vidPath);
+ webm = new WebmPlayer();
+ webm.fuck(io, false);
+ webm.addEventListener(WebmEvent.PLAY, function(e) {
+ onPlay();
+ });
+ webm.addEventListener(WebmEvent.COMPLETE, function(e) {
+ onEnd();
+ });
+ webm.addEventListener(WebmEvent.STOP, function(e) {
+ onStop();
+ });
+ webm.addEventListener(WebmEvent.RESTART, function(e) {
+ onRestart();
+ });
+ webm.visible = false;
+ initialized = true;
+ }
+
+ public function updatePlayer():Void
+ {
+ io = new WebmIoFile(vidPath);
+ webm.fuck(io, false);
+ }
+
+ public function play():Void
+ {
+ if (initialized)
+ {
+ webm.play();
+ }
+ }
+
+ public function stop():Void
+ {
+ if (initialized)
+ {
+ webm.stop();
+ }
+ }
+
+ public function restart():Void
+ {
+ if (initialized)
+ {
+ webm.restart();
+ }
+ }
+
+ public function update(elapsed:Float)
+ {
+ webm.x = GlobalVideo.calc(0);
+ webm.y = GlobalVideo.calc(1);
+ webm.width = GlobalVideo.calc(2);
+ webm.height = GlobalVideo.calc(3);
+ }
+
+ public var stopped:Bool = false;
+ public var restarted:Bool = false;
+ public var played:Bool = false;
+ public var ended:Bool = false;
+ public var paused:Bool = false;
+
+ public function pause():Void
+ {
+ webm.changePlaying(false);
+ paused = true;
+ }
+
+ public function resume():Void
+ {
+ webm.changePlaying(true);
+ paused = false;
+ }
+
+ public function togglePause():Void
+ {
+ if (paused)
+ {
+ resume();
+ } else {
+ pause();
+ }
+ }
+
+ public function clearPause():Void
+ {
+ paused = false;
+ webm.removePause();
+ }
+
+ public function onStop():Void
+ {
+ stopped = true;
+ }
+
+ public function onRestart():Void
+ {
+ restarted = true;
+ }
+
+ public function onPlay():Void
+ {
+ played = true;
+ }
+
+ public function onEnd():Void
+ {
+ trace("IT ENDED!");
+ ended = true;
+ }
+
+ public function alpha():Void
+ {
+ webm.alpha = GlobalVideo.daAlpha1;
+ }
+
+ public function unalpha():Void
+ {
+ webm.alpha = GlobalVideo.daAlpha2;
+ }
+
+ public function hide():Void
+ {
+ webm.visible = false;
+ }
+
+ public function show():Void
+ {
+ webm.visible = true;
+ }
+ #else
+ public var webm:Sprite;
+ public function new()
+ {
+ trace("THIS IS ANDROID! or some shit...");
+ }
+ #end
+}
\ No newline at end of file
diff --git a/source - Copy/WiggleEffect.hx b/source - Copy/WiggleEffect.hx
new file mode 100644
index 0000000..ac2bd3b
--- /dev/null
+++ b/source - Copy/WiggleEffect.hx
@@ -0,0 +1,133 @@
+package;
+
+// STOLEN FROM HAXEFLIXEL DEMO LOL
+import flixel.system.FlxAssets.FlxShader;
+
+enum WiggleEffectType
+{
+ DREAMY;
+ WAVY;
+ HEAT_WAVE_HORIZONTAL;
+ HEAT_WAVE_VERTICAL;
+ FLAG;
+}
+
+class WiggleEffect
+{
+ public var shader(default, null):WiggleShader = new WiggleShader();
+ public var effectType(default, set):WiggleEffectType = DREAMY;
+ public var waveSpeed(default, set):Float = 0;
+ public var waveFrequency(default, set):Float = 0;
+ public var waveAmplitude(default, set):Float = 0;
+
+ public function new():Void
+ {
+ shader.uTime.value = [0];
+ }
+
+ public function update(elapsed:Float):Void
+ {
+ shader.uTime.value[0] += elapsed;
+ }
+
+ function set_effectType(v:WiggleEffectType):WiggleEffectType
+ {
+ effectType = v;
+ shader.effectType.value = [WiggleEffectType.getConstructors().indexOf(Std.string(v))];
+ return v;
+ }
+
+ function set_waveSpeed(v:Float):Float
+ {
+ waveSpeed = v;
+ shader.uSpeed.value = [waveSpeed];
+ return v;
+ }
+
+ function set_waveFrequency(v:Float):Float
+ {
+ waveFrequency = v;
+ shader.uFrequency.value = [waveFrequency];
+ return v;
+ }
+
+ function set_waveAmplitude(v:Float):Float
+ {
+ waveAmplitude = v;
+ shader.uWaveAmplitude.value = [waveAmplitude];
+ return v;
+ }
+}
+
+class WiggleShader extends FlxShader
+{
+ @:glFragmentSource('
+ #pragma header
+ //uniform float tx, ty; // x,y waves phase
+ uniform float uTime;
+
+ const int EFFECT_TYPE_DREAMY = 0;
+ const int EFFECT_TYPE_WAVY = 1;
+ const int EFFECT_TYPE_HEAT_WAVE_HORIZONTAL = 2;
+ const int EFFECT_TYPE_HEAT_WAVE_VERTICAL = 3;
+ const int EFFECT_TYPE_FLAG = 4;
+
+ uniform int effectType;
+
+ /**
+ * How fast the waves move over time
+ */
+ uniform float uSpeed;
+
+ /**
+ * Number of waves over time
+ */
+ uniform float uFrequency;
+
+ /**
+ * How much the pixels are going to stretch over the waves
+ */
+ uniform float uWaveAmplitude;
+
+ vec2 sineWave(vec2 pt)
+ {
+ float x = 0.0;
+ float y = 0.0;
+
+ if (effectType == EFFECT_TYPE_DREAMY)
+ {
+ float offsetX = sin(pt.y * uFrequency + uTime * uSpeed) * uWaveAmplitude;
+ pt.x += offsetX; // * (pt.y - 1.0); // <- Uncomment to stop bottom part of the screen from moving
+ }
+ else if (effectType == EFFECT_TYPE_WAVY)
+ {
+ float offsetY = sin(pt.x * uFrequency + uTime * uSpeed) * uWaveAmplitude;
+ pt.y += offsetY; // * (pt.y - 1.0); // <- Uncomment to stop bottom part of the screen from moving
+ }
+ else if (effectType == EFFECT_TYPE_HEAT_WAVE_HORIZONTAL)
+ {
+ x = sin(pt.x * uFrequency + uTime * uSpeed) * uWaveAmplitude;
+ }
+ else if (effectType == EFFECT_TYPE_HEAT_WAVE_VERTICAL)
+ {
+ y = sin(pt.y * uFrequency + uTime * uSpeed) * uWaveAmplitude;
+ }
+ else if (effectType == EFFECT_TYPE_FLAG)
+ {
+ y = sin(pt.y * uFrequency + 10.0 * pt.x + uTime * uSpeed) * uWaveAmplitude;
+ x = sin(pt.x * uFrequency + 5.0 * pt.y + uTime * uSpeed) * uWaveAmplitude;
+ }
+
+ return vec2(pt.x + x, pt.y + y);
+ }
+
+ void main()
+ {
+ vec2 uv = sineWave(openfl_TextureCoordv);
+ gl_FragColor = texture2D(bitmap, uv);
+ }')
+ public function new()
+ {
+ super();
+ }
+}
diff --git a/source - Copy/import.hx b/source - Copy/import.hx
new file mode 100644
index 0000000..e0a4198
--- /dev/null
+++ b/source - Copy/import.hx
@@ -0,0 +1 @@
+import Paths;
\ No newline at end of file
diff --git a/version.downloadMe b/version.downloadMe
index 65f6485..b03f579 100644
--- a/version.downloadMe
+++ b/version.downloadMe
@@ -1,11 +1,6 @@
-1.5.1;
-- 1.5.1: Bug Fixes
-- Added toggle for ghost tapping
-- Officially support macOS (and add macOS requirements to docs)
-- Autoplay
-- Clap assist for syncing charts
-- Bring back R to reset, but now you can toggle it in the options
-- You can now fully customize your keybinds
-- Change how replays work + store scroll speed and direction in replays
-- Opponent strumline now lights up when they hit a note, like the player's does
-- Now using the new recharts from Funkin v0.2.8
\ No newline at end of file
+1.5.3;
+- Score Screen
+- Rewrote the entire hit ranking system
+- Fixed song names so they don't crash
+- New asset loading system
+- New Logo
\ No newline at end of file