diff --git a/.vscode/.temp b/.vscode/.temp new file mode 100644 index 0000000..177a799 --- /dev/null +++ b/.vscode/.temp @@ -0,0 +1 @@ +TBA: tasks.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..0930c09 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "lime", + "command": "test", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "lime", + "command": "build", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/KadeEngineWithBackground.png b/KadeEngineWithBackground.png index 374a0c1..8629a24 100644 Binary files a/KadeEngineWithBackground.png and b/KadeEngineWithBackground.png differ diff --git a/Project.xml b/Project.xml index eeffad6..86cd7c8 100644 --- a/Project.xml +++ b/Project.xml @@ -7,6 +7,8 @@ + + @@ -57,6 +59,7 @@ +
@@ -69,6 +72,7 @@ +
@@ -89,7 +93,9 @@ - + + + @@ -160,6 +166,8 @@ + + diff --git a/README.md b/README.md index 832467c..deaf970 100644 --- a/README.md +++ b/README.md @@ -24,17 +24,23 @@ If you're looking for documentation, changelogs, or guides, you can find those o # Previews ([skip](#features)) -![Tutorial (Hard) on Downscroll](https://user-images.githubusercontent.com/15311104/113989685-fa5aea80-9850-11eb-9180-f5819a774c79.gif) ![Milf (Hard) on Downscroll](https://user-images.githubusercontent.com/15311104/113990845-2c208100-9852-11eb-8e6d-f1c9e8439871.gif) +![Title Screen](art/readme/KadeEngineTitleScreen.png) -![Roses (Hard) on Upscroll](https://user-images.githubusercontent.com/15311104/113993573-e31dfc00-9854-11eb-82ae-1f29dc8a0b04.png) +![Week Select](art/readme/KadeEngineWeekSelect.png) -![Milf (Hard) on Downscroll](https://user-images.githubusercontent.com/15311104/113991654-f4660900-9852-11eb-8c3d-f3927571f19b.png) +![Freeplay](art/readme/KadeEngineFreeplay.png) -![He malding](https://user-images.githubusercontent.com/15311104/113993693-02b52480-9855-11eb-9975-eb8a7a1be8d1.png) +![Options](art/readme/KadeEngineOptions.png) -![Free Play selection screen](https://i.imgur.com/LR0eWIC.png) +![Senpai Gameplay (Hard, Upscroll)](art/readme/KadeEnginePixelGameplay.png) -![Options Menu](https://i.imgur.com/LBXW9C1.png) +![Roses Dialogue](art/readme/KadeEngineDialogue.png) + +![Pause Screen](art/readme/KadeEnginePauseScreen.png) + +![Results Screen](art/readme/KadeEngineResultsScreen.png) + +![Replay Loader](art/readme/KadeEngineReplayLoader.png) # Features @@ -43,12 +49,15 @@ If you're looking for documentation, changelogs, or guides, you can find those o - **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! + - Instead of being forced to use WASD and the arrow keys, you can set any keybinds 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. + - If your speakers or 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! + - **And much, much more!** + - There's so much more in store than just what's listed here! If you can imagine a quality of life feature, it's probably + either already included in Kade Engine or is being worked on! # Credits ### Friday Night Funkin' @@ -65,4 +74,6 @@ This game was made with love to Newgrounds and its community. Extra love to Tom ### 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 +- [Puyo](https://github.com/puyoxyz) - Setting up appveyor and a lot of other help +- [Smokey](https://github.com/Smokey555) - telling me that I should do the tricky asset loading +- [Poco](https://github.com/poco0317) - math degree (aka most of the fucking math in this project) diff --git a/appveyor-linux.yml b/appveyor-linux.yml index 647af3d..6dfee0f 100644 --- a/appveyor-linux.yml +++ b/appveyor-linux.yml @@ -9,7 +9,7 @@ install: - cd /home/appveyor - sudo add-apt-repository ppa:haxe/releases -y - sudo apt update - - sudo apt install neko tar -y + - sudo apt install neko tar gcc-7 g++-7 gcc-7-multilib g++-7-multilib -y - wget https://github.com/HaxeFoundation/haxe/releases/download/4.1.5/haxe-4.1.5-linux64.tar.gz - mkdir $HAXE_INSTALLDIR - tar -xf haxe-4.1.5-linux64.tar.gz -C $HAXE_INSTALLDIR @@ -29,8 +29,9 @@ install: - 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 - - lime rebuild extension-webm linux + - haxelib run lime rebuild extension-webm linux - haxelib install linc_luajit + - haxelib install actuate - haxelib list - cd /home/appveyor/projects/kade-engine-linux diff --git a/appveyor-macos.yml b/appveyor-macos.yml index 476a070..47c0bcd 100644 --- a/appveyor-macos.yml +++ b/appveyor-macos.yml @@ -29,8 +29,9 @@ install: - 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 - - lime rebuild extension-webm macos + - haxelib run lime rebuild extension-webm macos - haxelib install linc_luajit + - haxelib install actuate - haxelib list - cd /Users/appveyor/projects/kade-engine-macos diff --git a/appveyor-windows.yml b/appveyor-windows.yml index 65acce8..58d5d98 100644 --- a/appveyor-windows.yml +++ b/appveyor-windows.yml @@ -18,6 +18,7 @@ install: - haxelib setup "%HAXELIB_ROOT%" # Install project dependencies - haxelib install lime 7.9.0 + - RefreshEnv - haxelib install openfl - haxelib install flixel - haxelib run lime setup flixel @@ -32,7 +33,13 @@ 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 install actuate + #- haxelib git extension-webm https://github.com/KadeDev/extension-webm + #- haxelib run lime rebuild extension-webm windows + #why here's dublicate lmao - haxelib list # No tests idk lol diff --git a/art/flashFiles/NOTE_assets.fla b/art/flashFiles/NOTE_assets.fla index 523cc95..d3e4f32 100644 Binary files a/art/flashFiles/NOTE_assets.fla and b/art/flashFiles/NOTE_assets.fla differ diff --git a/art/readme/KadeEngineDialogue.png b/art/readme/KadeEngineDialogue.png new file mode 100644 index 0000000..36ebeb8 Binary files /dev/null and b/art/readme/KadeEngineDialogue.png differ diff --git a/art/readme/KadeEngineFreeplay.png b/art/readme/KadeEngineFreeplay.png new file mode 100644 index 0000000..a3ed2a9 Binary files /dev/null and b/art/readme/KadeEngineFreeplay.png differ diff --git a/art/readme/KadeEngineOptions.png b/art/readme/KadeEngineOptions.png new file mode 100644 index 0000000..2005272 Binary files /dev/null and b/art/readme/KadeEngineOptions.png differ diff --git a/art/readme/KadeEnginePauseScreen.png b/art/readme/KadeEnginePauseScreen.png new file mode 100644 index 0000000..c31edf7 Binary files /dev/null and b/art/readme/KadeEnginePauseScreen.png differ diff --git a/art/readme/KadeEnginePixelGameplay.png b/art/readme/KadeEnginePixelGameplay.png new file mode 100644 index 0000000..20416ab Binary files /dev/null and b/art/readme/KadeEnginePixelGameplay.png differ diff --git a/art/readme/KadeEngineReplayLoader.png b/art/readme/KadeEngineReplayLoader.png new file mode 100644 index 0000000..4c7fc9c Binary files /dev/null and b/art/readme/KadeEngineReplayLoader.png differ diff --git a/art/readme/KadeEngineResultsScreen.png b/art/readme/KadeEngineResultsScreen.png new file mode 100644 index 0000000..110bade Binary files /dev/null and b/art/readme/KadeEngineResultsScreen.png differ diff --git a/art/readme/KadeEngineTitleScreen.png b/art/readme/KadeEngineTitleScreen.png new file mode 100644 index 0000000..405fe80 Binary files /dev/null and b/art/readme/KadeEngineTitleScreen.png differ diff --git a/art/readme/KadeEngineWeekSelect.png b/art/readme/KadeEngineWeekSelect.png new file mode 100644 index 0000000..d8327c8 Binary files /dev/null and b/art/readme/KadeEngineWeekSelect.png differ diff --git a/assets/preload/data/freeplaySonglist.txt b/assets/preload/data/freeplaySonglist.txt index a5939ad..7af8115 100644 --- a/assets/preload/data/freeplaySonglist.txt +++ b/assets/preload/data/freeplaySonglist.txt @@ -1,4 +1,4 @@ -Tutorial:gf:1 +Tutorial:gf:0 Bopeebo:dad:1 Fresh:dad:1 Dad Battle:dad:1 diff --git a/assets/preload/data/satin-panties/satin-panties-hard.json b/assets/preload/data/satin-panties/satin-panties-hard.json index 27ac0b6..d1578b2 100644 --- a/assets/preload/data/satin-panties/satin-panties-hard.json +++ b/assets/preload/data/satin-panties/satin-panties-hard.json @@ -1 +1,2904 @@ -{"song":{"player1":"bf-car","gfVersion":"gf-car","notes":[{"sectionNotes":[[0,0,0],[272.727264,0,0],[545.4545,0,0],[818.181763,0,0],[954.5454,0,0],[1227.27271,0,0],[1363.63635,0,0],[1636.36353,0,0],[1909.09082,0,0],[2045.45447,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[2181.818,3,0],[2454.54541,3,0],[2727.27271,3,0],[3000,3,0],[3136.36353,3,0],[3409.09082,3,0],[3545.45435,3,0],[3818.18164,3,0],[4090.909,3,0],[4227.27246,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[4636.36328,2,0],[4909.091,3,0],[5181.818,2,0],[5318.18164,3,0],[5590.90869,0,0],[5863.636,2,0],[6000,3,0],[6272.727,0,0],[6409.091,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[6818.18164,2,0],[7090.90869,3,0],[7363.636,2,0],[7500,3,0],[7772.727,0,0],[8045.454,2,0],[8181.818,3,0],[8318.182,0,0],[8454.545,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[8727.272,6,545.4545],[9000,2,0],[9272.727,3,0],[9545.454,2,0],[9681.818,3,0],[9954.545,0,0],[10227.2725,2,0],[10363.6357,3,0],[10636.3633,0,0],[10772.7266,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[11181.8174,2,0],[11454.5449,3,0],[11727.2725,2,0],[11863.6357,3,0],[12136.3633,0,0],[12409.0908,2,0],[12545.4541,3,0],[12681.8174,0,0],[12818.1816,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[13090.9082,6,545.4545],[13363.6357,1,0],[13500,1,0],[13636.3633,0,0],[13909.0908,0,0],[14045.4541,3,0],[14181.8174,2,272.727264],[14590.9082,3,0],[14727.2725,0,0],[15000,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[15272.7266,3,272.727264],[15681.8174,0,0],[15954.5449,0,0],[16090.9082,0,0],[16227.2725,0,0],[16363.6357,2,272.727264],[16772.7266,3,0],[16909.09,0,0],[17045.4531,1,0],[17181.8184,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[17454.5449,6,545.4545],[17727.2715,1,0],[17863.6367,1,0],[18000,0,0],[18272.7266,0,0],[18409.09,3,0],[18545.4531,2,272.727264],[18954.5449,3,0],[19090.9082,0,0],[19363.6367,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[19636.3633,3,272.727264],[20045.4531,0,0],[20318.1816,0,0],[20454.5449,0,0],[20590.9082,0,0],[20727.2715,2,272.727264],[21136.3633,3,0],[21272.7266,0,0],[21409.09,1,0],[21545.4531,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[21818.1816,6,409.090881],[21818.1816,2,409.090881],[22363.6348,7,0],[22363.6348,3,0],[22500,6,0],[22500,2,0],[22636.3633,7,0],[22636.3633,3,0],[22772.7266,6,0],[22772.7266,2,0],[22909.09,4,0],[22909.09,0,0],[23045.4531,5,0],[23045.4531,1,0],[23181.8184,4,0],[23181.8184,0,0],[23318.1816,5,0],[23318.1816,1,0],[23454.5449,4,0],[23454.5449,0,0],[23590.9082,7,0],[23590.9082,3,0],[23727.2715,4,0],[23727.2715,0,0],[23863.6348,7,0],[23863.6348,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[24000,1,409.090881],[24000,5,409.090881],[24545.4531,4,0],[24545.4531,0,0],[24681.8184,7,0],[24681.8184,3,0],[24818.1816,4,0],[24818.1816,0,0],[24954.5449,7,0],[24954.5449,3,0],[25090.9082,6,136.363632],[25090.9082,2,136.363632],[25363.6348,7,0],[25363.6348,3,0],[25636.3633,7,0],[25636.3633,3,0],[25909.09,5,0],[25909.09,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[26181.8164,4,409.090881],[26181.8164,3,409.090881],[26727.2715,0,409.090881],[26727.2715,7,409.090881],[27272.7266,6,0],[27272.7266,2,0],[27545.4531,6,0],[27545.4531,2,0],[27681.8164,6,0],[27681.8164,2,0],[27818.1816,7,409.090881],[27818.1816,0,409.090881]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[28363.6348,5,409.090881],[28363.6348,1,409.090881],[28909.09,7,409.090881],[28909.09,3,409.090881],[29454.5449,6,409.090881],[29454.5449,2,409.090881],[30000,4,0],[30000,0,0],[30272.7266,7,409.090881],[30272.7266,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[30545.4531,5,545.4545],[30818.1816,2,0],[30954.5449,3,0],[31090.9082,0,0],[31363.6348,1,0],[31636.3633,3,0],[31772.7266,0,0],[31909.09,3,0],[32181.8164,3,0],[32318.1816,0,0],[32454.5449,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[33000,1,0],[33136.3633,3,0],[33272.7266,0,136.363632],[33545.4531,1,0],[33818.18,2,0],[33954.543,3,0],[34090.9063,0,0],[34227.2734,0,0],[34363.6367,3,0],[34500,0,0],[34636.3633,0,0],[34772.7266,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[34909.09,7,0],[35045.4531,6,0],[35181.8164,2,0],[35181.8164,7,0],[35318.18,3,0],[35454.543,0,0],[35727.2734,1,0],[36000,3,0],[36136.3633,0,0],[36272.7266,3,0],[36545.4531,3,0],[36681.8164,0,0],[36818.18,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[37363.6367,1,0],[37500,3,0],[37636.3633,0,136.363632],[37909.09,1,0],[38181.8164,2,0],[38318.18,3,0],[38454.543,0,0],[38590.9063,0,0],[38727.2734,7,0],[38727.2734,3,0],[38863.6367,4,0],[38863.6367,0,0],[39000,5,0],[39000,0,0],[39136.3633,7,0],[39136.3633,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[39272.7266,2,136.363632],[39272.7266,7,0],[39409.09,6,0],[39545.4531,7,0],[39545.4531,2,0],[39681.8164,3,0],[39818.18,0,0],[39954.543,1,0],[40090.9063,3,0],[40227.2734,1,0],[40363.6367,3,0],[40500,0,0],[40636.3633,3,0],[40772.7266,1,0],[40909.09,3,0],[41045.4531,0,0],[41181.8164,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[41454.543,0,0],[41727.27,1,0],[41863.6367,3,0],[42000,0,136.363632],[42272.7266,1,0],[42545.4531,2,0],[42681.8164,3,0],[42818.18,0,0],[42954.543,0,0],[43090.9063,7,0],[43090.9063,3,0],[43227.27,4,0],[43227.27,0,0],[43363.6367,5,0],[43363.6367,0,0],[43500,7,0],[43500,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[43636.3633,2,136.363632],[43909.09,2,0],[44045.4531,3,0],[44181.8164,0,0],[44318.18,1,0],[44454.543,3,0],[44590.9063,1,0],[44727.27,3,0],[44863.6367,0,0],[45000,3,0],[45136.3633,1,0],[45272.7266,3,0],[45409.09,0,0],[45545.4531,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[45818.18,0,0],[46090.9063,1,0],[46227.27,3,0],[46363.6367,0,136.363632],[46636.3633,1,0],[46909.09,2,0],[47045.4531,3,0],[47181.8164,0,0],[47318.18,0,0],[47454.543,3,0],[47590.9063,0,0],[47727.27,0,0],[47863.6367,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[48272.7266,2,0],[48409.09,3,0],[48545.4531,0,0],[48681.8164,3,0],[48818.18,0,0],[48954.543,2,0],[49090.9063,3,0],[49363.6367,3,0],[49636.3633,1,0],[49909.09,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[50454.543,3,0],[50590.9063,1,0],[50727.27,0,0],[50863.6367,3,0],[51000,2,0],[51272.7266,0,0],[51545.4531,2,0],[51818.18,0,0],[52090.9063,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[52363.6328,6,545.4545],[52636.3633,2,0],[52772.7266,3,0],[52909.09,0,0],[53045.4531,3,0],[53181.8164,0,0],[53318.18,2,0],[53454.543,3,0],[53727.27,3,0],[54000,1,0],[54272.7266,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[54818.18,3,0],[54954.543,1,0],[55090.9063,0,0],[55227.27,3,0],[55363.6328,2,0],[55636.3633,0,0],[55909.09,2,0],[56181.8164,0,0],[56454.543,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[56727.27,6,409.090881],[56727.27,2,409.090881],[57272.7266,3,0],[57272.7266,7,0],[57409.09,2,0],[57409.09,6,0],[57545.4531,3,0],[57545.4531,7,0],[57681.8164,2,0],[57681.8164,6,0],[57818.18,0,0],[57818.18,4,0],[57954.543,1,0],[57954.543,5,0],[58090.9063,0,0],[58090.9063,4,0],[58227.27,1,0],[58227.27,5,0],[58363.6328,0,0],[58363.6328,4,0],[58500,3,0],[58500,7,0],[58636.3633,0,0],[58636.3633,4,0],[58772.7266,3,0],[58772.7266,7,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[58909.09,1,409.090881],[58909.09,5,409.090881],[59454.543,4,0],[59454.543,0,0],[59590.9063,7,0],[59590.9063,3,0],[59727.27,4,0],[59727.27,0,0],[59863.6328,7,0],[59863.6328,3,0],[60000,6,136.363632],[60000,2,136.363632],[60272.7266,7,0],[60272.7266,3,0],[60545.4531,7,0],[60545.4531,3,0],[60818.18,5,0],[60818.18,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[61090.9063,0,409.090881],[61090.9063,7,409.090881],[61636.3633,4,409.090881],[61636.3633,3,409.090881],[62181.8164,2,0],[62181.8164,6,0],[62454.543,2,0],[62454.543,6,0],[62590.9063,2,0],[62590.9063,6,0],[62727.27,3,409.090881],[62727.27,4,409.090881]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[63272.7266,5,409.090881],[63272.7266,1,409.090881],[63818.18,7,409.090881],[63818.18,3,409.090881],[64363.6328,6,409.090881],[64363.6328,2,409.090881],[64909.09,4,0],[64909.09,0,0],[65181.8164,7,0],[65181.8164,3,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[65454.543,5,545.4545],[65454.543,2,0],[65727.27,2,0],[65863.63,3,0],[66000,0,0],[66272.73,1,0],[66545.45,3,0],[66681.81,0,0],[66818.18,3,0],[67090.91,3,0],[67227.27,0,0],[67363.63,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[67909.0859,1,0],[68045.45,3,0],[68181.81,0,136.363632],[68454.55,1,0],[68727.27,2,0],[68818.18,0,0],[68909.0859,3,0],[69000,0,0],[69181.81,0,0],[69272.73,3,0],[69363.63,0,0],[69454.55,3,0],[69545.45,1,0],[69727.27,0,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[69818.18,5,409.090881],[70090.91,2,0],[70227.27,3,0],[70363.63,0,0],[70363.63,7,409.090881],[70636.36,1,0],[70909.0859,3,0],[70909.0859,6,409.090881],[71045.45,0,0],[71181.81,3,0],[71454.55,3,0],[71454.55,7,409.090881],[71590.91,0,0],[71727.27,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[72000,5,409.090881],[72272.73,1,0],[72409.0859,3,0],[72545.45,0,136.363632],[72545.45,7,409.090881],[72818.18,1,0],[73090.91,2,0],[73181.81,0,0],[73272.73,3,0],[73363.63,0,0],[73545.45,0,0],[73636.36,3,0],[73727.27,0,0],[73818.18,3,0],[73909.0859,1,0],[74090.91,0,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[74181.81,0,136.363632],[74181.81,5,409.090881],[74454.55,2,0],[74590.91,3,0],[74727.27,0,0],[74727.27,7,409.090881],[74863.63,1,0],[75000,3,0],[75136.36,1,0],[75272.73,3,0],[75272.73,6,409.090881],[75409.0859,0,0],[75545.45,3,0],[75681.81,1,0],[75818.18,3,0],[75818.18,7,409.090881],[75954.55,0,0],[76090.91,1,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[76363.63,0,0],[76363.63,5,409.090881],[76636.36,1,0],[76772.73,3,0],[76909.0859,0,136.363632],[76909.0859,7,409.090881],[77181.81,1,0],[77454.55,2,0],[77454.55,6,409.090881],[77590.91,3,0],[77727.27,0,0],[77863.63,0,0],[78000,3,0],[78000,7,0],[78136.36,0,0],[78136.36,4,0],[78272.73,0,0],[78272.73,4,0],[78409.0859,1,0],[78409.0859,5,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[78545.45,0,136.363632],[78818.18,2,0],[78954.55,3,0],[79090.91,0,0],[79227.27,1,0],[79363.63,3,0],[79500,1,0],[79636.36,3,0],[79772.73,0,0],[79909.0859,3,0],[80045.45,1,0],[80181.81,3,0],[80318.18,0,0],[80454.55,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[80727.27,0,0],[81000,1,0],[81136.36,3,0],[81272.73,0,136.363632],[81545.45,1,0],[81818.18,2,0],[81954.54,3,0],[82090.91,0,0],[82227.27,0,0],[82363.63,3,0],[82500,0,0],[82636.36,0,0],[82772.73,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[82909.0859,7,1090.909],[83181.81,2,0],[83454.54,3,0],[83727.27,2,0],[83863.63,3,0],[84136.36,0,0],[84409.0859,2,0],[84545.45,3,0],[84818.18,0,0],[84954.54,3,0]],"lengthInSteps":16,"mustHitSection":false},{"sectionNotes":[[85363.63,2,0],[85636.36,3,0],[85909.0859,2,0],[86045.45,3,0],[86318.18,0,0],[86590.91,2,0],[86727.27,3,0],[86863.63,0,0],[87000,1,0]],"lengthInSteps":16,"mustHitSection":true},{"sectionNotes":[[87272.73,2,545.4545]],"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":110,"changeBPM":false,"mustHitSection":true}],"player2":"mom-car","song":"Satin Panties","stage":"limo","needsVoices":true,"validScore":true,"bpm":110,"speed":1.8}} \ No newline at end of file +{ + "song": { + "player1": "bf-car", + "player2": "mom-car", + "notes": [ + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 0, + 0, + 0 + ], + [ + 272.727264, + 0, + 0 + ], + [ + 545.4545, + 0, + 0 + ], + [ + 818.181763, + 0, + 0 + ], + [ + 954.5454, + 0, + 0 + ], + [ + 1227.27271, + 0, + 0 + ], + [ + 1363.63635, + 0, + 0 + ], + [ + 1636.36353, + 0, + 0 + ], + [ + 1909.09082, + 0, + 0 + ], + [ + 2045.45447, + 0, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 2181.818, + 3, + 0 + ], + [ + 2454.54541, + 3, + 0 + ], + [ + 2727.27271, + 3, + 0 + ], + [ + 3000, + 3, + 0 + ], + [ + 3136.36353, + 3, + 0 + ], + [ + 3409.09082, + 3, + 0 + ], + [ + 3545.45435, + 3, + 0 + ], + [ + 3818.18164, + 3, + 0 + ], + [ + 4090.909, + 3, + 0 + ], + [ + 4227.27246, + 3, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 4636.36328, + 2, + 0 + ], + [ + 4909.091, + 3, + 0 + ], + [ + 5181.818, + 2, + 0 + ], + [ + 5318.18164, + 3, + 0 + ], + [ + 5590.90869, + 0, + 0 + ], + [ + 5863.636, + 2, + 0 + ], + [ + 6000, + 3, + 0 + ], + [ + 6272.727, + 0, + 0 + ], + [ + 6409.091, + 3, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 6818.18164, + 2, + 0 + ], + [ + 7090.90869, + 3, + 0 + ], + [ + 7363.636, + 2, + 0 + ], + [ + 7500, + 3, + 0 + ], + [ + 7772.727, + 0, + 0 + ], + [ + 8045.454, + 2, + 0 + ], + [ + 8181.818, + 3, + 0 + ], + [ + 8318.182, + 0, + 0 + ], + [ + 8454.545, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 8727.272, + 6, + 545.4545 + ], + [ + 9000, + 2, + 0 + ], + [ + 9272.727, + 3, + 0 + ], + [ + 9545.454, + 2, + 0 + ], + [ + 9681.818, + 3, + 0 + ], + [ + 9954.545, + 0, + 0 + ], + [ + 10227.2725, + 2, + 0 + ], + [ + 10363.6357, + 3, + 0 + ], + [ + 10636.3633, + 0, + 0 + ], + [ + 10772.7266, + 3, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 11181.8174, + 2, + 0 + ], + [ + 11454.5449, + 3, + 0 + ], + [ + 11727.2725, + 2, + 0 + ], + [ + 11863.6357, + 3, + 0 + ], + [ + 12136.3633, + 0, + 0 + ], + [ + 12409.0908, + 2, + 0 + ], + [ + 12545.4541, + 3, + 0 + ], + [ + 12681.8174, + 0, + 0 + ], + [ + 12818.1816, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 13090.9082, + 6, + 545.4545 + ], + [ + 13363.6357, + 1, + 0 + ], + [ + 13500, + 1, + 0 + ], + [ + 13636.3633, + 0, + 0 + ], + [ + 13909.0908, + 0, + 0 + ], + [ + 14045.4541, + 3, + 0 + ], + [ + 14181.8174, + 2, + 272.727264 + ], + [ + 14590.9082, + 3, + 0 + ], + [ + 14727.2725, + 0, + 0 + ], + [ + 15000, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 15272.7266, + 3, + 272.727264 + ], + [ + 15681.8174, + 0, + 0 + ], + [ + 15954.5449, + 0, + 0 + ], + [ + 16090.9082, + 0, + 0 + ], + [ + 16227.2725, + 0, + 0 + ], + [ + 16363.6357, + 2, + 272.727264 + ], + [ + 16772.7266, + 3, + 0 + ], + [ + 16909.09, + 0, + 0 + ], + [ + 17045.4531, + 1, + 0 + ], + [ + 17181.8184, + 0, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 17454.5449, + 6, + 545.4545 + ], + [ + 17727.2715, + 1, + 0 + ], + [ + 17863.6367, + 1, + 0 + ], + [ + 18000, + 0, + 0 + ], + [ + 18272.7266, + 0, + 0 + ], + [ + 18409.09, + 3, + 0 + ], + [ + 18545.4531, + 2, + 272.727264 + ], + [ + 18954.5449, + 3, + 0 + ], + [ + 19090.9082, + 0, + 0 + ], + [ + 19363.6367, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 19636.3633, + 3, + 272.727264 + ], + [ + 20045.4531, + 0, + 0 + ], + [ + 20318.1816, + 0, + 0 + ], + [ + 20454.5449, + 0, + 0 + ], + [ + 20590.9082, + 0, + 0 + ], + [ + 20727.2715, + 2, + 272.727264 + ], + [ + 21136.3633, + 3, + 0 + ], + [ + 21272.7266, + 0, + 0 + ], + [ + 21409.09, + 1, + 0 + ], + [ + 21545.4531, + 0, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 21818.1816, + 6, + 409.090881 + ], + [ + 21818.1816, + 2, + 409.090881 + ], + [ + 22363.6348, + 7, + 0 + ], + [ + 22363.6348, + 3, + 0 + ], + [ + 22500, + 6, + 0 + ], + [ + 22500, + 2, + 0 + ], + [ + 22636.3633, + 7, + 0 + ], + [ + 22636.3633, + 3, + 0 + ], + [ + 22772.7266, + 6, + 0 + ], + [ + 22772.7266, + 2, + 0 + ], + [ + 22909.09, + 4, + 0 + ], + [ + 22909.09, + 0, + 0 + ], + [ + 23045.4531, + 5, + 0 + ], + [ + 23045.4531, + 1, + 0 + ], + [ + 23181.8184, + 4, + 0 + ], + [ + 23181.8184, + 0, + 0 + ], + [ + 23318.1816, + 5, + 0 + ], + [ + 23318.1816, + 1, + 0 + ], + [ + 23454.5449, + 4, + 0 + ], + [ + 23454.5449, + 0, + 0 + ], + [ + 23590.9082, + 7, + 0 + ], + [ + 23590.9082, + 3, + 0 + ], + [ + 23727.2715, + 4, + 0 + ], + [ + 23727.2715, + 0, + 0 + ], + [ + 23863.6348, + 7, + 0 + ], + [ + 23863.6348, + 3, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 24000, + 1, + 409.090881 + ], + [ + 24000, + 5, + 409.090881 + ], + [ + 24545.4531, + 4, + 0 + ], + [ + 24545.4531, + 0, + 0 + ], + [ + 24681.8184, + 7, + 0 + ], + [ + 24681.8184, + 3, + 0 + ], + [ + 24818.1816, + 4, + 0 + ], + [ + 24818.1816, + 0, + 0 + ], + [ + 24954.5449, + 7, + 0 + ], + [ + 24954.5449, + 3, + 0 + ], + [ + 25090.9082, + 6, + 136.363632 + ], + [ + 25090.9082, + 2, + 136.363632 + ], + [ + 25363.6348, + 7, + 0 + ], + [ + 25363.6348, + 3, + 0 + ], + [ + 25636.3633, + 7, + 0 + ], + [ + 25636.3633, + 3, + 0 + ], + [ + 25909.09, + 5, + 0 + ], + [ + 25909.09, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 26181.8164, + 4, + 409.090881 + ], + [ + 26181.8164, + 3, + 409.090881 + ], + [ + 26727.2715, + 0, + 409.090881 + ], + [ + 26727.2715, + 7, + 409.090881 + ], + [ + 27272.7266, + 6, + 0 + ], + [ + 27272.7266, + 2, + 0 + ], + [ + 27545.4531, + 6, + 0 + ], + [ + 27545.4531, + 2, + 0 + ], + [ + 27681.8164, + 6, + 0 + ], + [ + 27681.8164, + 2, + 0 + ], + [ + 27818.1816, + 7, + 409.090881 + ], + [ + 27818.1816, + 0, + 409.090881 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 28363.6348, + 5, + 409.090881 + ], + [ + 28363.6348, + 1, + 409.090881 + ], + [ + 28909.09, + 7, + 409.090881 + ], + [ + 28909.09, + 3, + 409.090881 + ], + [ + 29454.5449, + 6, + 409.090881 + ], + [ + 29454.5449, + 2, + 409.090881 + ], + [ + 30000, + 4, + 0 + ], + [ + 30000, + 0, + 0 + ], + [ + 30272.7266, + 7, + 409.090881 + ], + [ + 30272.7266, + 3, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 30545.4531, + 5, + 545.4545 + ], + [ + 30818.1816, + 2, + 0 + ], + [ + 30954.5449, + 3, + 0 + ], + [ + 31090.9082, + 0, + 0 + ], + [ + 31363.6348, + 1, + 0 + ], + [ + 31636.3633, + 3, + 0 + ], + [ + 31772.7266, + 0, + 0 + ], + [ + 31909.09, + 3, + 0 + ], + [ + 32181.8164, + 3, + 0 + ], + [ + 32318.1816, + 0, + 0 + ], + [ + 32454.5449, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 33000, + 1, + 0 + ], + [ + 33136.3633, + 3, + 0 + ], + [ + 33272.7266, + 0, + 136.363632 + ], + [ + 33545.4531, + 1, + 0 + ], + [ + 33818.18, + 2, + 0 + ], + [ + 33954.543, + 3, + 0 + ], + [ + 34090.9063, + 0, + 0 + ], + [ + 34227.2734, + 0, + 0 + ], + [ + 34363.6367, + 3, + 0 + ], + [ + 34500, + 0, + 0 + ], + [ + 34636.3633, + 0, + 0 + ], + [ + 34772.7266, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 34909.09, + 7, + 0 + ], + [ + 35045.4531, + 6, + 0 + ], + [ + 35181.8164, + 2, + 0 + ], + [ + 35181.8164, + 7, + 0 + ], + [ + 35318.18, + 3, + 0 + ], + [ + 35454.543, + 0, + 0 + ], + [ + 35727.2734, + 1, + 0 + ], + [ + 36000, + 3, + 0 + ], + [ + 36136.3633, + 0, + 0 + ], + [ + 36272.7266, + 3, + 0 + ], + [ + 36545.4531, + 3, + 0 + ], + [ + 36681.8164, + 0, + 0 + ], + [ + 36818.18, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 37363.6367, + 1, + 0 + ], + [ + 37500, + 3, + 0 + ], + [ + 37636.3633, + 0, + 136.363632 + ], + [ + 37909.09, + 1, + 0 + ], + [ + 38181.8164, + 2, + 0 + ], + [ + 38318.18, + 3, + 0 + ], + [ + 38454.543, + 0, + 0 + ], + [ + 38590.9063, + 0, + 0 + ], + [ + 38727.2734, + 7, + 0 + ], + [ + 38727.2734, + 3, + 0 + ], + [ + 38863.6367, + 4, + 0 + ], + [ + 38863.6367, + 0, + 0 + ], + [ + 39000, + 5, + 0 + ], + [ + 39000, + 0, + 0 + ], + [ + 39136.3633, + 7, + 0 + ], + [ + 39136.3633, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 39272.7266, + 2, + 136.363632 + ], + [ + 39272.7266, + 7, + 0 + ], + [ + 39409.09, + 6, + 0 + ], + [ + 39545.4531, + 7, + 0 + ], + [ + 39545.4531, + 2, + 0 + ], + [ + 39681.8164, + 3, + 0 + ], + [ + 39818.18, + 0, + 0 + ], + [ + 39954.543, + 1, + 0 + ], + [ + 40090.9063, + 3, + 0 + ], + [ + 40227.2734, + 1, + 0 + ], + [ + 40363.6367, + 3, + 0 + ], + [ + 40500, + 0, + 0 + ], + [ + 40636.3633, + 3, + 0 + ], + [ + 40772.7266, + 1, + 0 + ], + [ + 40909.09, + 3, + 0 + ], + [ + 41045.4531, + 0, + 0 + ], + [ + 41181.8164, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 41454.543, + 0, + 0 + ], + [ + 41727.27, + 1, + 0 + ], + [ + 41863.6367, + 3, + 0 + ], + [ + 42000, + 0, + 136.363632 + ], + [ + 42272.7266, + 1, + 0 + ], + [ + 42545.4531, + 2, + 0 + ], + [ + 42681.8164, + 3, + 0 + ], + [ + 42818.18, + 0, + 0 + ], + [ + 42954.543, + 0, + 0 + ], + [ + 43090.9063, + 7, + 0 + ], + [ + 43090.9063, + 3, + 0 + ], + [ + 43227.27, + 4, + 0 + ], + [ + 43227.27, + 0, + 0 + ], + [ + 43363.6367, + 5, + 0 + ], + [ + 43363.6367, + 0, + 0 + ], + [ + 43500, + 7, + 0 + ], + [ + 43500, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 43636.3633, + 2, + 136.363632 + ], + [ + 43909.09, + 2, + 0 + ], + [ + 44045.4531, + 3, + 0 + ], + [ + 44181.8164, + 0, + 0 + ], + [ + 44318.18, + 1, + 0 + ], + [ + 44454.543, + 3, + 0 + ], + [ + 44590.9063, + 1, + 0 + ], + [ + 44727.27, + 3, + 0 + ], + [ + 44863.6367, + 0, + 0 + ], + [ + 45000, + 3, + 0 + ], + [ + 45136.3633, + 1, + 0 + ], + [ + 45272.7266, + 3, + 0 + ], + [ + 45409.09, + 0, + 0 + ], + [ + 45545.4531, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 45818.18, + 0, + 0 + ], + [ + 46090.9063, + 1, + 0 + ], + [ + 46227.27, + 3, + 0 + ], + [ + 46363.6367, + 0, + 136.363632 + ], + [ + 46636.3633, + 1, + 0 + ], + [ + 46909.09, + 2, + 0 + ], + [ + 47045.4531, + 3, + 0 + ], + [ + 47181.8164, + 0, + 0 + ], + [ + 47318.18, + 0, + 0 + ], + [ + 47454.543, + 3, + 0 + ], + [ + 47590.9063, + 0, + 0 + ], + [ + 47727.27, + 0, + 0 + ], + [ + 47863.6367, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 48272.7266, + 2, + 0 + ], + [ + 48409.09, + 3, + 0 + ], + [ + 48545.4531, + 0, + 0 + ], + [ + 48681.8164, + 3, + 0 + ], + [ + 48818.18, + 0, + 0 + ], + [ + 48954.543, + 2, + 0 + ], + [ + 49090.9063, + 3, + 0 + ], + [ + 49363.6367, + 3, + 0 + ], + [ + 49636.3633, + 1, + 0 + ], + [ + 49909.09, + 0, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 50454.543, + 3, + 0 + ], + [ + 50590.9063, + 1, + 0 + ], + [ + 50727.27, + 0, + 0 + ], + [ + 50863.6367, + 3, + 0 + ], + [ + 51000, + 2, + 0 + ], + [ + 51272.7266, + 0, + 0 + ], + [ + 51545.4531, + 2, + 0 + ], + [ + 51818.18, + 0, + 0 + ], + [ + 52090.9063, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 52363.6328, + 6, + 545.4545 + ], + [ + 52636.3633, + 2, + 0 + ], + [ + 52772.7266, + 3, + 0 + ], + [ + 52909.09, + 0, + 0 + ], + [ + 53045.4531, + 3, + 0 + ], + [ + 53181.8164, + 0, + 0 + ], + [ + 53318.18, + 2, + 0 + ], + [ + 53454.543, + 3, + 0 + ], + [ + 53727.27, + 3, + 0 + ], + [ + 54000, + 1, + 0 + ], + [ + 54272.7266, + 0, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 54818.18, + 3, + 0 + ], + [ + 54954.543, + 1, + 0 + ], + [ + 55090.9063, + 0, + 0 + ], + [ + 55227.27, + 3, + 0 + ], + [ + 55363.6328, + 2, + 0 + ], + [ + 55636.3633, + 0, + 0 + ], + [ + 55909.09, + 2, + 0 + ], + [ + 56181.8164, + 0, + 0 + ], + [ + 56454.543, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 56727.27, + 6, + 409.090881 + ], + [ + 56727.27, + 2, + 409.090881 + ], + [ + 57272.7266, + 3, + 0 + ], + [ + 57272.7266, + 7, + 0 + ], + [ + 57409.09, + 2, + 0 + ], + [ + 57409.09, + 6, + 0 + ], + [ + 57545.4531, + 3, + 0 + ], + [ + 57545.4531, + 7, + 0 + ], + [ + 57681.8164, + 2, + 0 + ], + [ + 57681.8164, + 6, + 0 + ], + [ + 57818.18, + 0, + 0 + ], + [ + 57818.18, + 4, + 0 + ], + [ + 57954.543, + 1, + 0 + ], + [ + 57954.543, + 5, + 0 + ], + [ + 58090.9063, + 0, + 0 + ], + [ + 58090.9063, + 4, + 0 + ], + [ + 58227.27, + 1, + 0 + ], + [ + 58227.27, + 5, + 0 + ], + [ + 58363.6328, + 0, + 0 + ], + [ + 58363.6328, + 4, + 0 + ], + [ + 58500, + 3, + 0 + ], + [ + 58500, + 7, + 0 + ], + [ + 58636.3633, + 0, + 0 + ], + [ + 58636.3633, + 4, + 0 + ], + [ + 58772.7266, + 3, + 0 + ], + [ + 58772.7266, + 7, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 58909.09, + 1, + 409.090881 + ], + [ + 58909.09, + 5, + 409.090881 + ], + [ + 59454.543, + 4, + 0 + ], + [ + 59454.543, + 0, + 0 + ], + [ + 59590.9063, + 7, + 0 + ], + [ + 59590.9063, + 3, + 0 + ], + [ + 59727.27, + 4, + 0 + ], + [ + 59727.27, + 0, + 0 + ], + [ + 59863.6328, + 7, + 0 + ], + [ + 59863.6328, + 3, + 0 + ], + [ + 60000, + 6, + 136.363632 + ], + [ + 60000, + 2, + 136.363632 + ], + [ + 60272.7266, + 7, + 0 + ], + [ + 60272.7266, + 3, + 0 + ], + [ + 60545.4531, + 7, + 0 + ], + [ + 60545.4531, + 3, + 0 + ], + [ + 60818.18, + 5, + 0 + ], + [ + 60818.18, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 61090.9063, + 0, + 409.090881 + ], + [ + 61090.9063, + 7, + 409.090881 + ], + [ + 61636.3633, + 4, + 409.090881 + ], + [ + 61636.3633, + 3, + 409.090881 + ], + [ + 62181.8164, + 2, + 0 + ], + [ + 62181.8164, + 6, + 0 + ], + [ + 62454.543, + 2, + 0 + ], + [ + 62454.543, + 6, + 0 + ], + [ + 62590.9063, + 2, + 0 + ], + [ + 62590.9063, + 6, + 0 + ], + [ + 62727.27, + 3, + 409.090881 + ], + [ + 62727.27, + 4, + 409.090881 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 63272.7266, + 5, + 409.090881 + ], + [ + 63272.7266, + 1, + 409.090881 + ], + [ + 63818.18, + 7, + 409.090881 + ], + [ + 63818.18, + 3, + 409.090881 + ], + [ + 64363.6328, + 6, + 409.090881 + ], + [ + 64363.6328, + 2, + 409.090881 + ], + [ + 64909.09, + 4, + 0 + ], + [ + 64909.09, + 0, + 0 + ], + [ + 65181.8164, + 7, + 0 + ], + [ + 65181.8164, + 3, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 65454.543, + 5, + 545.4545 + ], + [ + 65454.543, + 2, + 0 + ], + [ + 65727.27, + 2, + 0 + ], + [ + 65863.63, + 3, + 0 + ], + [ + 66000, + 0, + 0 + ], + [ + 66272.73, + 1, + 0 + ], + [ + 66545.45, + 3, + 0 + ], + [ + 66681.81, + 0, + 0 + ], + [ + 66818.18, + 3, + 0 + ], + [ + 67090.91, + 3, + 0 + ], + [ + 67227.27, + 0, + 0 + ], + [ + 67363.63, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 67909.0859, + 1, + 0 + ], + [ + 68045.45, + 3, + 0 + ], + [ + 68181.81, + 0, + 136.363632 + ], + [ + 68454.55, + 1, + 0 + ], + [ + 68727.27, + 2, + 0 + ], + [ + 69000, + 0, + 0 + ], + [ + 69272.73, + 3, + 0 + ], + [ + 69545.45, + 1, + 0 + ], + [ + 68818.1818181819, + 0, + 0 + ], + [ + 68909.090909091, + 3, + 0 + ], + [ + 69181.8181818182, + 0, + 0 + ], + [ + 69363.6363636364, + 0, + 0 + ], + [ + 69454.5454545455, + 3, + 0 + ], + [ + 69727.2727272728, + 0, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 69818.18, + 5, + 409.090881 + ], + [ + 70090.91, + 2, + 0 + ], + [ + 70227.27, + 3, + 0 + ], + [ + 70363.63, + 0, + 0 + ], + [ + 70363.63, + 7, + 409.090881 + ], + [ + 70636.36, + 1, + 0 + ], + [ + 70909.0859, + 3, + 0 + ], + [ + 70909.0859, + 6, + 409.090881 + ], + [ + 71045.45, + 0, + 0 + ], + [ + 71181.81, + 3, + 0 + ], + [ + 71454.55, + 3, + 0 + ], + [ + 71454.55, + 7, + 409.090881 + ], + [ + 71590.91, + 0, + 0 + ], + [ + 71727.27, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 72000, + 5, + 409.090881 + ], + [ + 72272.73, + 1, + 0 + ], + [ + 72409.0859, + 3, + 0 + ], + [ + 72545.45, + 0, + 136.363632 + ], + [ + 72545.45, + 7, + 409.090881 + ], + [ + 72818.18, + 1, + 0 + ], + [ + 73090.91, + 2, + 0 + ], + [ + 73363.63, + 0, + 0 + ], + [ + 73636.36, + 3, + 0 + ], + [ + 73909.0859, + 1, + 0 + ], + [ + 73181.8181818182, + 0, + 0 + ], + [ + 73272.7272727273, + 3, + 0 + ], + [ + 73545.4545454546, + 0, + 0 + ], + [ + 73727.2727272727, + 0, + 0 + ], + [ + 73818.1818181819, + 3, + 0 + ], + [ + 74090.9090909091, + 0, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 74181.81, + 0, + 136.363632 + ], + [ + 74181.81, + 5, + 409.090881 + ], + [ + 74454.55, + 2, + 0 + ], + [ + 74590.91, + 3, + 0 + ], + [ + 74727.27, + 0, + 0 + ], + [ + 74727.27, + 7, + 409.090881 + ], + [ + 74863.63, + 1, + 0 + ], + [ + 75000, + 3, + 0 + ], + [ + 75136.36, + 1, + 0 + ], + [ + 75272.73, + 3, + 0 + ], + [ + 75272.73, + 6, + 409.090881 + ], + [ + 75409.0859, + 0, + 0 + ], + [ + 75545.45, + 3, + 0 + ], + [ + 75681.81, + 1, + 0 + ], + [ + 75818.18, + 3, + 0 + ], + [ + 75818.18, + 7, + 409.090881 + ], + [ + 75954.55, + 0, + 0 + ], + [ + 76090.91, + 1, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 76363.63, + 0, + 0 + ], + [ + 76363.63, + 5, + 409.090881 + ], + [ + 76636.36, + 1, + 0 + ], + [ + 76772.73, + 3, + 0 + ], + [ + 76909.0859, + 0, + 136.363632 + ], + [ + 76909.0859, + 7, + 409.090881 + ], + [ + 77181.81, + 1, + 0 + ], + [ + 77454.55, + 2, + 0 + ], + [ + 77454.55, + 6, + 409.090881 + ], + [ + 77590.91, + 3, + 0 + ], + [ + 77727.27, + 0, + 0 + ], + [ + 77863.63, + 0, + 0 + ], + [ + 78000, + 3, + 0 + ], + [ + 78000, + 7, + 0 + ], + [ + 78136.36, + 0, + 0 + ], + [ + 78136.36, + 4, + 0 + ], + [ + 78272.73, + 0, + 0 + ], + [ + 78272.73, + 4, + 0 + ], + [ + 78409.0859, + 1, + 0 + ], + [ + 78409.0859, + 5, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 78545.45, + 0, + 136.363632 + ], + [ + 78818.18, + 2, + 0 + ], + [ + 78954.55, + 3, + 0 + ], + [ + 79090.91, + 0, + 0 + ], + [ + 79227.27, + 1, + 0 + ], + [ + 79363.63, + 3, + 0 + ], + [ + 79500, + 1, + 0 + ], + [ + 79636.36, + 3, + 0 + ], + [ + 79772.73, + 0, + 0 + ], + [ + 79909.0859, + 3, + 0 + ], + [ + 80045.45, + 1, + 0 + ], + [ + 80181.81, + 3, + 0 + ], + [ + 80318.18, + 0, + 0 + ], + [ + 80454.55, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 80727.27, + 0, + 0 + ], + [ + 81000, + 1, + 0 + ], + [ + 81136.36, + 3, + 0 + ], + [ + 81272.73, + 0, + 136.363632 + ], + [ + 81545.45, + 1, + 0 + ], + [ + 81818.18, + 2, + 0 + ], + [ + 81954.54, + 3, + 0 + ], + [ + 82090.91, + 0, + 0 + ], + [ + 82227.27, + 0, + 0 + ], + [ + 82363.63, + 3, + 0 + ], + [ + 82500, + 0, + 0 + ], + [ + 82636.36, + 0, + 0 + ], + [ + 82772.73, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 82909.0859, + 7, + 1090.909 + ], + [ + 83181.81, + 2, + 0 + ], + [ + 83454.54, + 3, + 0 + ], + [ + 83727.27, + 2, + 0 + ], + [ + 83863.63, + 3, + 0 + ], + [ + 84136.36, + 0, + 0 + ], + [ + 84409.0859, + 2, + 0 + ], + [ + 84545.45, + 3, + 0 + ], + [ + 84818.18, + 0, + 0 + ], + [ + 84954.54, + 3, + 0 + ] + ], + "mustHitSection": false + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 85363.63, + 2, + 0 + ], + [ + 85636.36, + 3, + 0 + ], + [ + 85909.0859, + 2, + 0 + ], + [ + 86045.45, + 3, + 0 + ], + [ + 86318.18, + 0, + 0 + ], + [ + 86590.91, + 2, + 0 + ], + [ + 86727.27, + 3, + 0 + ], + [ + 86863.63, + 0, + 0 + ], + [ + 87000, + 1, + 0 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [ + [ + 87272.73, + 2, + 545.4545 + ] + ], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [], + "mustHitSection": true + }, + { + "lengthInSteps": 16, + "sectionNotes": [], + "mustHitSection": true + }, + { + "sectionNotes": [], + "typeOfSection": 0, + "lengthInSteps": 16, + "altAnim": false, + "mustHitSection": true, + "changeBPM": false, + "bpm": 110 + }, + { + "lengthInSteps": 16, + "altAnim": false, + "typeOfSection": 0, + "sectionNotes": [], + "bpm": 110, + "changeBPM": false, + "mustHitSection": true + } + ], + "gfVersion": "gf-car", + "song": "Satin Panties", + "stage": "limo", + "needsVoices": true, + "validScore": true, + "speed": 1.8, + "bpm": 110 + } +} \ No newline at end of file diff --git a/assets/preload/data/test/test.json b/assets/preload/data/test/test.json new file mode 100644 index 0000000..6ccba5e --- /dev/null +++ b/assets/preload/data/test/test.json @@ -0,0 +1 @@ +{"song": {"song": "Test", "notes": [{"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[668.578947368421, 3, 947.3684210526317], [1615.9473684210527, 1, 631.578947368421], [2247.5263157894738, 0, 315.7894736842104]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[2563.315789473684, 3, 631.5789473684213], [3194.8947368421054, 2, 631.5789473684208], [3826.4736842105262, 1, 631.5789473684213], [4773.8421052631575, 1, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[5089.631578947368, 2, 0], [5563.315789473684, 1, 0], [5879.105263157895, 3, 0], [6037.0, 1, 0], [6194.894736842105, 0, 0], [6352.789473684211, 2, 315.78947368420995], [6668.578947368421, 1, 315.78947368421086], [6984.368421052632, 0, 0], [7142.263157894737, 1, 0], [7300.1578947368425, 2, 0], [7458.0526315789475, 0, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[7615.9473684210525, 1, 1578.9473684210525], [7615.9473684210525, 3, 947.3684210526326], [8721.21052631579, 3, 0], [8879.105263157895, 0, 0], [9194.894736842105, 2, 0], [9352.78947368421, 1, 0], [9352.78947368421, 3, 0], [9510.684210526315, 0, 0], [9510.684210526315, 2, 0], [9668.578947368422, 0, 0], [9668.578947368422, 2, 0], [9826.473684210527, 1, 0], [9826.473684210527, 3, 0], [9984.368421052632, 0, 0], [9984.368421052632, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[10142.263157894737, 3, 0], [10458.052631578947, 3, 0], [10773.842105263158, 3, 0], [11089.631578947368, 1, 0], [11247.526315789473, 2, 0], [11405.421052631578, 0, 0], [11721.21052631579, 0, 0], [12037.0, 0, 0], [12194.894736842105, 2, 0], [12352.78947368421, 1, 0], [12510.684210526315, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[12668.578947368422, 3, 0], [12984.368421052632, 1, 0], [13300.157894736842, 2, 315.78947368421177], [13615.947368421053, 0, 0], [13773.842105263158, 1, 0], [13931.736842105263, 3, 1263.1578947368416], [14563.315789473685, 0, 0], [14721.21052631579, 1, 0], [14879.105263157895, 2, 0], [15037.0, 1, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[15194.894736842105, 0, 0], [15352.78947368421, 2, 0], [15510.684210526315, 0, 631.5789473684217], [16142.263157894737, 2, 0], [16300.157894736842, 1, 0], [16458.052631578947, 0, 0], [16773.842105263157, 0, 0], [17089.63157894737, 0, 0], [17405.42105263158, 1, 315.78947368420995]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[17721.21052631579, 0, 1263.1578947368398], [17721.21052631579, 3, 1263.1578947368398], [18984.36842105263, 1, 0], [18984.36842105263, 2, 0], [19300.157894736843, 1, 0], [19300.157894736843, 2, 0], [19615.947368421053, 1, 0], [19615.947368421053, 2, 0], [19826.473684210527, 1, 0], [19826.473684210527, 2, 0], [20037.0, 1, 0], [20037.0, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[20247.526315789473, 3, 631.5789473684199], [20879.105263157893, 1, 0], [21194.894736842107, 1, 0], [21510.684210526317, 1, 0], [21826.473684210527, 1, 0], [22142.263157894737, 1, 0], [22300.157894736843, 2, 0], [22458.052631578947, 0, 0], [22615.947368421053, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[22773.842105263157, 3, 0], [22931.736842105263, 1, 0], [23089.63157894737, 2, 0], [23405.42105263158, 1, 0], [23721.21052631579, 1, 0], [24037.0, 1, 0], [24352.78947368421, 2, 0], [24510.684210526317, 3, 0], [24668.57894736842, 1, 0], [24826.473684210527, 2, 0], [24984.36842105263, 1, 0], [25142.263157894737, 0, 473.68421052631675]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[25773.842105263157, 2, 0], [25931.736842105263, 3, 0], [26089.63157894737, 1, 0], [26247.526315789473, 2, 0], [26563.315789473683, 1, 0], [26879.105263157893, 0, 0], [27194.894736842107, 0, 0], [27352.78947368421, 1, 0], [27510.684210526317, 2, 0], [27668.57894736842, 3, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[27826.473684210527, 2, 0], [28142.263157894737, 2, 0], [28458.052631578947, 3, 1894.7368421052633], [28615.947368421053, 2, 0], [28773.842105263157, 1, 0], [28931.736842105263, 0, 0], [29089.63157894737, 2, 0], [29247.526315789473, 1, 0], [29405.42105263158, 0, 0], [29563.315789473683, 1, 0], [29879.105263157893, 2, 0], [30037.0, 1, 0], [30194.894736842107, 0, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[30352.78947368421, 2, 0], [30431.736842105263, 1, 0], [30510.684210526317, 0, 0], [30668.57894736842, 0, 0], [30826.473684210527, 0, 0], [30905.42105263158, 1, 0], [30984.36842105263, 2, 0], [31142.263157894737, 3, 0], [31300.157894736843, 1, 0], [31458.052631578947, 2, 0], [31615.947368421053, 0, 0], [31773.842105263157, 2, 0], [31931.736842105263, 1, 0], [32089.63157894737, 2, 0], [32405.42105263158, 2, 0], [32721.21052631579, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[32879.10526315789, 2, 0], [32958.05263157895, 3, 0], [33037.0, 1, 0], [33194.89473684211, 0, 0], [33352.78947368421, 2, 0], [33510.68421052631, 1, 0], [33668.57894736842, 2, 0], [33826.47368421053, 3, 0], [33984.36842105263, 1, 0], [34063.31578947369, 2, 0], [34142.26315789474, 0, 0], [34300.15789473684, 0, 0], [34458.05263157895, 1, 0], [34615.94736842105, 2, 0], [34694.89473684211, 1, 0], [34773.84210526316, 2, 0], [34931.73684210526, 3, 0], [35089.63157894737, 1, 0], [35247.52631578947, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[35405.42105263158, 0, 0], [35563.31578947369, 1, 0], [35721.21052631579, 2, 0], [35879.10526315789, 3, 0], [36194.89473684211, 2, 0], [36352.78947368421, 1, 0], [36510.68421052631, 0, 0], [36826.47368421053, 2, 0], [36984.36842105263, 1, 0], [37142.26315789474, 0, 236.84210526315292], [37458.05263157895, 0, 236.8421052631602], [37773.84210526316, 0, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[37931.73684210526, 2, 0], [38089.63157894737, 1, 0], [38247.52631578947, 0, 0], [38405.42105263158, 1, 0], [38563.31578947369, 3, 0], [38721.21052631579, 3, 0], [38879.10526315789, 2, 552.6315789473665], [39510.68421052631, 1, 315.7894736842136], [39826.47368421053, 3, 1263.1578947368398]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[41721.21052631579, 1, 631.5789473684272], [42431.73684210526, 0, 0], [42510.68421052631, 1, 0], [42589.63157894737, 2, 0], [42668.57894736842, 3, 0], [42747.52631578947, 2, 0], [42826.47368421053, 1, 0], [42905.42105263158, 0, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[42984.36842105263, 3, 631.5789473684199], [43615.94736842105, 1, 552.6315789473665], [44247.52631578947, 1, 631.5789473684199], [44958.05263157895, 0, 0], [45037.0, 1, 0], [45115.94736842105, 2, 0], [45194.89473684211, 3, 0], [45273.84210526316, 1, 0], [45352.78947368421, 2, 0], [45431.73684210526, 1, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[45510.68421052631, 3, 631.5789473684272], [46142.26315789474, 1, 0], [46142.26315789474, 2, 631.5789473684199], [46300.15789473684, 0, 0], [46458.05263157895, 1, 0], [46615.94736842105, 0, 0], [46773.84210526316, 1, 0], [46773.84210526316, 3, 631.5789473684199], [46931.73684210526, 0, 0], [47089.63157894737, 1, 0], [47247.52631578947, 0, 0], [47405.42105263158, 1, 0], [47405.42105263158, 2, 631.5789473684199], [47484.36842105263, 0, 0], [47563.31578947369, 1, 0], [47642.26315789474, 0, 0], [47721.21052631579, 1, 0], [47800.15789473684, 0, 0], [47879.10526315789, 1, 0], [47958.05263157895, 0, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[48037.0, 1, 0], [48194.89473684211, 2, 0], [48352.78947368421, 1, 315.7894736842063], [48668.57894736842, 2, 236.8421052631602], [48984.36842105263, 1, 0], [49063.31578947369, 2, 0], [49142.26315789474, 3, 0], [49221.21052631579, 2, 0], [49300.15789473684, 0, 631.5789473684199], [49458.05263157895, 1, 0], [49615.94736842105, 2, 0], [49773.84210526316, 1, 0], [49931.73684210526, 2, 0], [50010.68421052631, 0, 0], [50089.63157894737, 1, 0], [50168.57894736842, 2, 0], [50247.52631578947, 1, 0], [50326.47368421053, 2, 0], [50405.42105263158, 3, 0], [50484.36842105263, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[50563.31578947369, 1, 631.5789473684199], [50563.31578947369, 3, 631.5789473684199], [51194.89473684211, 0, 631.5789473684199], [51194.89473684211, 2, 631.5789473684199], [51826.47368421053, 3, 0], [51984.36842105263, 2, 0], [52142.26315789474, 1, 0], [52300.15789473684, 3, 0], [52458.05263157895, 2, 0], [52615.94736842105, 1, 0], [52773.84210526316, 3, 0], [52931.73684210526, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[53089.63157894737, 1, 0], [53247.52631578947, 3, 0], [53405.42105263158, 2, 0], [53563.31578947369, 1, 0], [53721.21052631579, 3, 0], [53879.10526315789, 2, 0], [54037.0, 1, 0], [54194.89473684211, 0, 0], [54352.78947368421, 1, 0], [54510.68421052631, 2, 0], [54668.57894736842, 3, 0], [54826.47368421053, 2, 0], [54984.36842105263, 1, 0], [55142.26315789474, 3, 0], [55300.15789473684, 2, 0], [55458.05263157895, 1, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[55615.94736842105, 3, 0], [55773.84210526316, 2, 0], [55931.73684210526, 1, 0], [56089.63157894737, 3, 0], [56247.52631578947, 2, 0], [56405.42105263158, 1, 0], [56563.31578947369, 3, 0], [56721.21052631579, 2, 0], [56879.10526315789, 1, 0], [57037.0, 0, 0], [57194.89473684211, 1, 0], [57352.78947368421, 0, 0], [57510.68421052631, 1, 0], [57668.57894736842, 2, 0], [57826.47368421053, 0, 0], [57984.36842105263, 1, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[58142.26315789474, 2, 0], [58300.15789473684, 3, 0], [58458.05263157895, 2, 0], [58615.94736842105, 1, 0], [58773.84210526316, 0, 0], [58931.73684210526, 1, 0], [59089.63157894737, 2, 0], [59247.52631578947, 3, 0], [59405.42105263158, 2, 0], [59563.31578947369, 3, 0], [59721.21052631579, 0, 0], [59879.10526315789, 1, 0], [60037.0, 2, 0], [60194.89473684211, 0, 0], [60352.78947368421, 1, 0], [60510.68421052631, 2, 0]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": [[60668.57894736842, 3, 0], [60826.47368421053, 2, 0], [60984.36842105263, 0, 0], [61142.26315789474, 1, 0], [61300.15789473684, 2, 0], [61458.05263157895, 0, 0], [61615.94736842105, 1, 0], [61773.84210526316, 2, 0], [61931.73684210526, 3, 0], [62089.63157894737, 2, 0], [62247.52631578947, 1, 2210.5263157894733]]}, {"lengthInSteps": 16, "bpm": 95.0, "changeBPM": false, "mustHitSection": true, "typeOfSection": 0, "sectionNotes": []}], "bpm": 95.0, "sections": 0, "needsVoices": false, "player1": "bf", "player2": "gf", "sectionLengths": [], "speed": 3}} \ No newline at end of file diff --git a/assets/preload/data/weekNames.txt b/assets/preload/data/weekNames.txt new file mode 100644 index 0000000..09b7036 --- /dev/null +++ b/assets/preload/data/weekNames.txt @@ -0,0 +1,7 @@ +Tutorial +Daddy Dearest +Spooky Month +PICO +MOMMY MUST MURDER +RED SNOW +Hating Simulator ft. Moawling \ No newline at end of file diff --git a/assets/preload/images/campaign_menu_UI_assets.xml b/assets/preload/images/campaign_menu_UI_assets.xml index f35ead1..ed6ed76 100644 --- a/assets/preload/images/campaign_menu_UI_assets.xml +++ b/assets/preload/images/campaign_menu_UI_assets.xml @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/assets/preload/images/iconGrid.png b/assets/preload/images/iconGrid.png deleted file mode 100644 index 9d3b1c0..0000000 Binary files a/assets/preload/images/iconGrid.png and /dev/null differ diff --git a/assets/preload/images/icons/icon-bf-old.png b/assets/preload/images/icons/icon-bf-old.png new file mode 100644 index 0000000..7d47aa0 Binary files /dev/null and b/assets/preload/images/icons/icon-bf-old.png differ diff --git a/assets/preload/images/icons/icon-bf-pixel.png b/assets/preload/images/icons/icon-bf-pixel.png new file mode 100644 index 0000000..661ea7f Binary files /dev/null and b/assets/preload/images/icons/icon-bf-pixel.png differ diff --git a/assets/preload/images/icons/icon-bf.png b/assets/preload/images/icons/icon-bf.png new file mode 100644 index 0000000..fc27bdd Binary files /dev/null and b/assets/preload/images/icons/icon-bf.png differ diff --git a/assets/preload/images/icons/icon-dad.png b/assets/preload/images/icons/icon-dad.png new file mode 100644 index 0000000..f068dd1 Binary files /dev/null and b/assets/preload/images/icons/icon-dad.png differ diff --git a/assets/preload/images/icons/icon-face.png b/assets/preload/images/icons/icon-face.png new file mode 100644 index 0000000..65dc76c Binary files /dev/null and b/assets/preload/images/icons/icon-face.png differ diff --git a/assets/preload/images/icons/icon-gf.png b/assets/preload/images/icons/icon-gf.png new file mode 100644 index 0000000..48de50f Binary files /dev/null and b/assets/preload/images/icons/icon-gf.png differ diff --git a/assets/preload/images/icons/icon-mom.png b/assets/preload/images/icons/icon-mom.png new file mode 100644 index 0000000..4eb9984 Binary files /dev/null and b/assets/preload/images/icons/icon-mom.png differ diff --git a/assets/preload/images/icons/icon-monster.png b/assets/preload/images/icons/icon-monster.png new file mode 100644 index 0000000..c9e05d0 Binary files /dev/null and b/assets/preload/images/icons/icon-monster.png differ diff --git a/assets/preload/images/icons/icon-parents.png b/assets/preload/images/icons/icon-parents.png new file mode 100644 index 0000000..5d820c5 Binary files /dev/null and b/assets/preload/images/icons/icon-parents.png differ diff --git a/assets/preload/images/icons/icon-pico.png b/assets/preload/images/icons/icon-pico.png new file mode 100644 index 0000000..8a36a61 Binary files /dev/null and b/assets/preload/images/icons/icon-pico.png differ diff --git a/assets/preload/images/icons/icon-senpai.png b/assets/preload/images/icons/icon-senpai.png new file mode 100644 index 0000000..bc294eb Binary files /dev/null and b/assets/preload/images/icons/icon-senpai.png differ diff --git a/assets/preload/images/icons/icon-sm.png b/assets/preload/images/icons/icon-sm.png new file mode 100644 index 0000000..16cdc0e Binary files /dev/null and b/assets/preload/images/icons/icon-sm.png differ diff --git a/assets/preload/images/icons/icon-spirit.png b/assets/preload/images/icons/icon-spirit.png new file mode 100644 index 0000000..441c48b Binary files /dev/null and b/assets/preload/images/icons/icon-spirit.png differ diff --git a/assets/preload/images/icons/icon-spooky.png b/assets/preload/images/icons/icon-spooky.png new file mode 100644 index 0000000..bbfe340 Binary files /dev/null and b/assets/preload/images/icons/icon-spooky.png differ diff --git a/assets/preload/images/icons/icon-tankman.png b/assets/preload/images/icons/icon-tankman.png new file mode 100644 index 0000000..25a2ed3 Binary files /dev/null and b/assets/preload/images/icons/icon-tankman.png differ diff --git a/assets/preload/images/storymenu/week6.png b/assets/preload/images/storymenu/week6.png index 8a45fb5..fca67f0 100644 Binary files a/assets/preload/images/storymenu/week6.png and b/assets/preload/images/storymenu/week6.png differ diff --git a/assets/preload/music/freakyMenu.mp3 b/assets/preload/music/freakyMenu.mp3 index 8132bfe..c8b0a56 100644 Binary files a/assets/preload/music/freakyMenu.mp3 and b/assets/preload/music/freakyMenu.mp3 differ diff --git a/assets/preload/music/freakyMenu.ogg b/assets/preload/music/freakyMenu.ogg index 372111d..a3ac889 100644 Binary files a/assets/preload/music/freakyMenu.ogg and b/assets/preload/music/freakyMenu.ogg differ diff --git a/assets/shared/images/NOTE_assets.png b/assets/shared/images/NOTE_assets.png index 7d50636..2b348a2 100644 Binary files a/assets/shared/images/NOTE_assets.png and b/assets/shared/images/NOTE_assets.png differ diff --git a/assets/shared/images/NOTE_assets.xml b/assets/shared/images/NOTE_assets.xml index 82a997a..d3e1257 100644 --- a/assets/shared/images/NOTE_assets.xml +++ b/assets/shared/images/NOTE_assets.xml @@ -1,53 +1,92 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/shared/images/characters/bf-carOffsets.txt b/assets/shared/images/characters/bf-carOffsets.txt new file mode 100644 index 0000000..5bbfae1 --- /dev/null +++ b/assets/shared/images/characters/bf-carOffsets.txt @@ -0,0 +1,9 @@ +idle -5 0 +singUP -29 27 +singRIGHT -38 -7 +singLEFT 12 -6 +singDOWN -10 -50 +singUPmiss -29 27 +singRIGHTmiss -30 21 +singLEFTmiss 12 24 +singDOWNmiss -11 -19 diff --git a/assets/shared/images/characters/bf-christmasOffsets.txt b/assets/shared/images/characters/bf-christmasOffsets.txt new file mode 100644 index 0000000..0142844 --- /dev/null +++ b/assets/shared/images/characters/bf-christmasOffsets.txt @@ -0,0 +1,10 @@ +idle -5 0 +singUP -29 27 +singRIGHT -38 -7 +singLEFT 12 -6 +singDOWN -10 -50 +singUPmiss -29 27 +singRIGHTmiss -30 21 +singLEFTmiss 12 24 +singDOWNmiss -11 -19 +hey 7 4 diff --git a/assets/shared/images/characters/bf-pixel-deadOffsets.txt b/assets/shared/images/characters/bf-pixel-deadOffsets.txt new file mode 100644 index 0000000..3544a2c --- /dev/null +++ b/assets/shared/images/characters/bf-pixel-deadOffsets.txt @@ -0,0 +1,3 @@ +firstDeath 0 0 +deathLoop -30 -12 +deathConfirm -30 -12 diff --git a/assets/shared/images/characters/bf-pixelOffsets.txt b/assets/shared/images/characters/bf-pixelOffsets.txt new file mode 100644 index 0000000..b8a8292 --- /dev/null +++ b/assets/shared/images/characters/bf-pixelOffsets.txt @@ -0,0 +1,9 @@ +idle 0 0 +singUP 0 0 +singRIGHT 0 0 +singLEFT 0 0 +singDOWN 0 0 +singUPmiss 0 0 +singRIGHTmiss 0 0 +singLEFTmiss 0 0 +singDOWNmiss 0 0 diff --git a/assets/shared/images/characters/bfOffsets.txt b/assets/shared/images/characters/bfOffsets.txt new file mode 100644 index 0000000..6ec2321 --- /dev/null +++ b/assets/shared/images/characters/bfOffsets.txt @@ -0,0 +1,14 @@ +idle -5 0 +singUP -29 27 +singRIGHT -38 -7 +singLEFT 12 -6 +singDOWN -10 -50 +singUPmiss -29 27 +singRIGHTmiss -30 21 +singLEFTmiss 12 24 +singDOWNmiss -11 -19 +hey 7 4 +firstDeath 37 11 +deathLoop 37 5 +deathConfirm 37 69 +scared -4 0 diff --git a/assets/shared/images/characters/bfPixelsDEAD.xml b/assets/shared/images/characters/bfPixelsDEAD.xml index 2d741ca..be3478c 100644 --- a/assets/shared/images/characters/bfPixelsDEAD.xml +++ b/assets/shared/images/characters/bfPixelsDEAD.xml @@ -1,7 +1,7 @@  - - + + @@ -58,8 +58,8 @@ - - + + diff --git a/assets/shared/images/characters/dadOffsets.txt b/assets/shared/images/characters/dadOffsets.txt new file mode 100644 index 0000000..69ba153 --- /dev/null +++ b/assets/shared/images/characters/dadOffsets.txt @@ -0,0 +1,5 @@ +idle 0 0 +singUP -6 50 +singRIGHT 0 27 +singLEFT -10 10 +singDOWN 0 -30 diff --git a/assets/shared/images/characters/gf-carOffsets.txt b/assets/shared/images/characters/gf-carOffsets.txt new file mode 100644 index 0000000..9862aae --- /dev/null +++ b/assets/shared/images/characters/gf-carOffsets.txt @@ -0,0 +1,2 @@ +danceLeft 0 0 +danceRight 0 0 diff --git a/assets/shared/images/characters/gf-christmasOffsets.txt b/assets/shared/images/characters/gf-christmasOffsets.txt new file mode 100644 index 0000000..05abb7a --- /dev/null +++ b/assets/shared/images/characters/gf-christmasOffsets.txt @@ -0,0 +1,11 @@ +cheer 0 0 +sad -2 -21 +danceLeft 0 -9 +danceRight 0 -9 +singUP 0 4 +singRIGHT 0 -20 +singLEFT 0 -19 +singDOWN 0 -20 +hairBlow 45 -8 +hairFall 0 -9 +scared -2 -17 diff --git a/assets/shared/images/characters/gf-pixelOffsets.txt b/assets/shared/images/characters/gf-pixelOffsets.txt new file mode 100644 index 0000000..9862aae --- /dev/null +++ b/assets/shared/images/characters/gf-pixelOffsets.txt @@ -0,0 +1,2 @@ +danceLeft 0 0 +danceRight 0 0 diff --git a/assets/shared/images/characters/gfOffsets.txt b/assets/shared/images/characters/gfOffsets.txt new file mode 100644 index 0000000..05abb7a --- /dev/null +++ b/assets/shared/images/characters/gfOffsets.txt @@ -0,0 +1,11 @@ +cheer 0 0 +sad -2 -21 +danceLeft 0 -9 +danceRight 0 -9 +singUP 0 4 +singRIGHT 0 -20 +singLEFT 0 -19 +singDOWN 0 -20 +hairBlow 45 -8 +hairFall 0 -9 +scared -2 -17 diff --git a/assets/shared/images/characters/mom-carOffsets.txt b/assets/shared/images/characters/mom-carOffsets.txt new file mode 100644 index 0000000..65cbecd --- /dev/null +++ b/assets/shared/images/characters/mom-carOffsets.txt @@ -0,0 +1,5 @@ +idle 0 0 +singUP 14 71 +singRIGHT 10 -60 +singLEFT 250 -23 +singDOWN 20 -160 diff --git a/assets/shared/images/characters/momOffsets.txt b/assets/shared/images/characters/momOffsets.txt new file mode 100644 index 0000000..65cbecd --- /dev/null +++ b/assets/shared/images/characters/momOffsets.txt @@ -0,0 +1,5 @@ +idle 0 0 +singUP 14 71 +singRIGHT 10 -60 +singLEFT 250 -23 +singDOWN 20 -160 diff --git a/assets/shared/images/characters/monster-christmasOffsets.txt b/assets/shared/images/characters/monster-christmasOffsets.txt new file mode 100644 index 0000000..a357046 --- /dev/null +++ b/assets/shared/images/characters/monster-christmasOffsets.txt @@ -0,0 +1,5 @@ +idle 0 0 +singUP -20 50 +singRIGHT -51 0 +singLEFT -30 0 +singDOWN -40 -94 diff --git a/assets/shared/images/characters/monsterOffsets.txt b/assets/shared/images/characters/monsterOffsets.txt new file mode 100644 index 0000000..e211a5f --- /dev/null +++ b/assets/shared/images/characters/monsterOffsets.txt @@ -0,0 +1,5 @@ +idle 0 0 +singUP -20 94 +singRIGHT -51 30 +singLEFT -30 20 +singDOWN -50 -80 diff --git a/assets/shared/images/characters/parents-christmasOffsets.txt b/assets/shared/images/characters/parents-christmasOffsets.txt new file mode 100644 index 0000000..bdee13c --- /dev/null +++ b/assets/shared/images/characters/parents-christmasOffsets.txt @@ -0,0 +1,9 @@ +idle 0 0 +singUP -47 24 +singRIGHT -1 -23 +singLEFT -30 16 +singDOWN -31 -29 +singUP-alt -47 24 +singRIGHT-alt -1 -24 +singLEFT-alt -30 15 +singDOWN-alt -30 -27 diff --git a/assets/shared/images/characters/picoOffsets.txt b/assets/shared/images/characters/picoOffsets.txt new file mode 100644 index 0000000..e209da7 --- /dev/null +++ b/assets/shared/images/characters/picoOffsets.txt @@ -0,0 +1,9 @@ +idle 0 0 +singUP -29 27 +singRIGHT -68 -7 +singLEFT 65 9 +singDOWN 200 -70 +singUPmiss -19 67 +singRIGHTmiss -60 41 +singLEFTmiss 62 64 +singDOWNmiss 210 -28 diff --git a/assets/shared/images/characters/senpai-angryOffsets.txt b/assets/shared/images/characters/senpai-angryOffsets.txt new file mode 100644 index 0000000..c118259 --- /dev/null +++ b/assets/shared/images/characters/senpai-angryOffsets.txt @@ -0,0 +1,5 @@ +idle 0 0 +singUP 5 37 +singRIGHT 0 0 +singLEFT 40 0 +singDOWN 14 0 diff --git a/assets/shared/images/characters/senpaiOffsets.txt b/assets/shared/images/characters/senpaiOffsets.txt new file mode 100644 index 0000000..c118259 --- /dev/null +++ b/assets/shared/images/characters/senpaiOffsets.txt @@ -0,0 +1,5 @@ +idle 0 0 +singUP 5 37 +singRIGHT 0 0 +singLEFT 40 0 +singDOWN 14 0 diff --git a/assets/shared/images/characters/spiritOffsets.txt b/assets/shared/images/characters/spiritOffsets.txt new file mode 100644 index 0000000..ed2442d --- /dev/null +++ b/assets/shared/images/characters/spiritOffsets.txt @@ -0,0 +1,5 @@ +idle -220 -280 +singUP -220 -240 +singRIGHT -220 -280 +singLEFT -200 -280 +singDOWN 170 110 diff --git a/assets/shared/images/characters/spookyOffsets.txt b/assets/shared/images/characters/spookyOffsets.txt new file mode 100644 index 0000000..c14c5e7 --- /dev/null +++ b/assets/shared/images/characters/spookyOffsets.txt @@ -0,0 +1,6 @@ +danceLeft 0 0 +danceRight 0 0 +singUP -20 26 +singRIGHT -130 -14 +singLEFT 130 -10 +singDOWN -50 -130 diff --git a/assets/shared/sounds/CLAP.mp3 b/assets/shared/sounds/CLAP.mp3 new file mode 100644 index 0000000..21b3f27 Binary files /dev/null and b/assets/shared/sounds/CLAP.mp3 differ diff --git a/assets/shared/sounds/SNAP.mp3 b/assets/shared/sounds/SNAP.mp3 new file mode 100644 index 0000000..67971fe Binary files /dev/null and b/assets/shared/sounds/SNAP.mp3 differ diff --git a/assets/sm/HOW TO ADD SM FILES.txt b/assets/sm/HOW TO ADD SM FILES.txt new file mode 100644 index 0000000..b9fa864 --- /dev/null +++ b/assets/sm/HOW TO ADD SM FILES.txt @@ -0,0 +1,5 @@ +Put both the .sm and .ogg in the same folder and put the folder in this folder. Launch the game and go into freeplay, it'll load into the song list. + +Limitations: +- You can only use songs that have one difficulty, so if a song has more than one. Remove all but the one you want to play. (it doesn't matter if it's challenge or what ever) +- The song must be a .ogg \ No newline at end of file diff --git a/assets/songs/spookeez/Inst.mp3 b/assets/songs/spookeez/Inst.mp3 index ee4577a..0a111e8 100644 Binary files a/assets/songs/spookeez/Inst.mp3 and b/assets/songs/spookeez/Inst.mp3 differ diff --git a/assets/songs/spookeez/Inst.ogg b/assets/songs/spookeez/Inst.ogg index e14fd8b..b8d7b70 100644 Binary files a/assets/songs/spookeez/Inst.ogg and b/assets/songs/spookeez/Inst.ogg differ diff --git a/assets/songs/spookeez/Voices.mp3 b/assets/songs/spookeez/Voices.mp3 index 854301d..481a7f3 100644 Binary files a/assets/songs/spookeez/Voices.mp3 and b/assets/songs/spookeez/Voices.mp3 differ diff --git a/assets/songs/spookeez/Voices.ogg b/assets/songs/spookeez/Voices.ogg index 1429044..1a8c30e 100644 Binary files a/assets/songs/spookeez/Voices.ogg and b/assets/songs/spookeez/Voices.ogg differ diff --git a/assets/songs/test/Inst.mp3 b/assets/songs/test/Inst.mp3 deleted file mode 100644 index 87d9932..0000000 Binary files a/assets/songs/test/Inst.mp3 and /dev/null differ diff --git a/assets/songs/test/Inst.ogg b/assets/songs/test/Inst.ogg index f39e2b1..7a16671 100644 Binary files a/assets/songs/test/Inst.ogg and b/assets/songs/test/Inst.ogg differ diff --git a/assets/songs/test/Voices.mp3 b/assets/songs/test/Voices.mp3 deleted file mode 100644 index 9625266..0000000 Binary files a/assets/songs/test/Voices.mp3 and /dev/null differ diff --git a/assets/songs/test/Voices.ogg b/assets/songs/test/Voices.ogg deleted file mode 100644 index 49f0f5d..0000000 Binary files a/assets/songs/test/Voices.ogg and /dev/null differ diff --git a/docs/_includes/header.html b/docs/_includes/header.html index 9780191..a354247 100644 --- a/docs/_includes/header.html +++ b/docs/_includes/header.html @@ -26,7 +26,7 @@ hr {

Changelogs Building - Modchart Documentation + Modcharts Guides
 


diff --git a/docs/building.md b/docs/building.md index fa8d5a9..e824a0f 100644 --- a/docs/building.md +++ b/docs/building.md @@ -30,26 +30,19 @@ - `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` + - `lime rebuild extension-webm ` ### 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 +- MSVC v141 - VS 2017 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. +This will install about 7 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.4.md b/docs/changelogs/changelog-1.5.4.md new file mode 100644 index 0000000..0c4e1e9 --- /dev/null +++ b/docs/changelogs/changelog-1.5.4.md @@ -0,0 +1,17 @@ +# Latest (master) changelog + +Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`. + +### Additions +- Controller Support (💖) + +### Changes +- KeyBinds don't effect menu screen options anymore. +- Updated some image assets +- Fixed spookeez audio sync + +### Bugfixes +- Fixed Input Drops/Disappering Notes (💖) +- Fixed HitGraph/Result Screen bugs +- Fixed the chart editor +- Fixed HTML5 Build issues \ No newline at end of file diff --git a/docs/changelogs/changelog-1.6.md b/docs/changelogs/changelog-1.6.md new file mode 100644 index 0000000..57e70d5 --- /dev/null +++ b/docs/changelogs/changelog-1.6.md @@ -0,0 +1,35 @@ +# Latest (master) changelog + +Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`. + +### Additions +- 💖 Full reworked charter +- Note quantization +- 💖 BPM Changes & Scroll Speed Change Support +- 💖 StepMania File Format support +- Anti-Aliasing option for low end pc's +- 💖 Pre-loading for characters option +- New Logo +- 💖 New Main Menu Remix +- 💖 Difficulty Calculator +- Week Locking +- Character Offset Files +- Many new options + +### Changes +- Reworked Health Drain to be harsher +- 💖 Held notes being weird as fuck (completely reworked them) +- Many beat based things actually go to the beat (blue balls, title screen, etc) +- Losing Icon for Father Dearest & Mommy Mearest together + +### Bugfixes +- BF Animation ending too early +- Held note end fix (this made me mad) +- Up arrow having a 8 pixels next to it +- Stop crashes with "R" +- Fixed dropped inputs for stacked notes. +- Fixed multiple crashes +- Fixed spirit being weird +- Fixed a lot of desyncs +- Ghost Tapping works now +- Pressing 7 while dying no longer freezes you in time. \ No newline at end of file diff --git a/docs/guides/weeks.md b/docs/guides/weeks.md index 90b89ca..7fcdfc0 100644 --- a/docs/guides/weeks.md +++ b/docs/guides/weeks.md @@ -15,8 +15,10 @@ Scroll down to Line 26, or Search (Windows/Linux: `Ctrl+F`, Mac: `Cmd+F`) for "w --- ```haxe -var weekData:Array = [ - +static function weekData():Array +{ + return [ + ['Tutorial'], ['Bopeebo', 'Fresh', 'Dadbattle'], @@ -30,8 +32,9 @@ var weekData:Array = [ ['Cocoa', 'Eggnog', 'Winter-Horrorland'], ['Senpai', 'Roses', 'Thorns'] - -]; + + ]; +} ``` --- @@ -45,8 +48,10 @@ Example --- ```haxe -var weekData:Array = [ - +static function weekData():Array +{ + return [ + ['Tutorial'], ['Bopeebo', 'Fresh', 'Dadbattle'], @@ -58,12 +63,13 @@ var weekData:Array = [ ['Satin-Panties', "High", "Milf"], ['Cocoa', 'Eggnog', 'Winter-Horrorland'], - + ['Senpai', 'Roses', 'Thorns'], ['Ugh', 'Guns', 'Stress'] - -]; + + ]; +} ``` --- @@ -103,32 +109,21 @@ var weekCharacters:Array = [ ### Step 4. Week Names -Underneath the song list, there should be another array called `weekNames`. Creating a new line in that array, just enter a string that represents what you want the week to be called. +In `assets/preload/data`, there should be a .txt file called `weekNames`. Creating a new line in that file, just enter a string that represents what you want the week to be called. Example --- --- -```haxe -var weekNames:Array = [ - - "How to Funk", - - "Daddy dearest", - - "Spooky Month", - - "PICO", - - "Mommy Must Murder", - - "Red Snow", - - "Hating Simulator ft. Moawlings", - - "Tankman" - -]; +``` +Tutorial +Daddy Dearest +Spooky Month +PICO +MOMMY MUST MURDER +RED SNOW +Hating Simulator ft. Moawling +TANKMAN ``` --- @@ -137,22 +132,29 @@ var weekNames:Array = [ ### Step 5. Graphics -Displaying a week icon for your custom week is as simple as dropping a .png into `assets/images/storymenu`. Rename the file to `week7.png`, `week8.png`, etc. +Displaying a week icon for your custom week is as simple as dropping a .png into `assets/preload/images/storymenu`. Rename the file to `week7.png`, `week8.png`, etc. Example --- --- + ![frrf](https://user-images.githubusercontent.com/68293280/118160164-cdab6d00-b3d2-11eb-9b29-a940eaf45025.png) ![frrf 2](https://user-images.githubusercontent.com/68293280/118160865-b8830e00-b3d3-11eb-8a23-818a1b4cfdb2.png) -NOTE: You will have to add a new item to `weekUnlocked`, so that the week is playable. - ![frrf 3](https://user-images.githubusercontent.com/68293280/118161461-7908f180-b3d4-11eb-89fa-e531ae5804d8.png) +======= +![weeks1](https://user-images.githubusercontent.com/55949451/122635123-69bb4900-d0e2-11eb-8bcc-1071cfda4e35.png) + +NOTE: You will have to add a new item to `weekUnlocked`, so that the week is playable. +Locate to line 39 and add in a new boolean called True so that the week can be playable. +--- + +![weeks2](https://user-images.githubusercontent.com/55949451/122635129-763fa180-d0e2-11eb-841e-3456e74a50ba.png) \* *for this screenshot I removed tankman from weekCharacters as it would crash because I don't have a tankman character added* ### Conclusion If you followed all of the steps correctly, you have successfully created a new week in the Story Mode. diff --git a/source/Alphabet.hx b/source/Alphabet.hx index 56d07e2..eec323d 100644 --- a/source/Alphabet.hx +++ b/source/Alphabet.hx @@ -44,8 +44,14 @@ class Alphabet extends FlxSpriteGroup var isBold:Bool = false; + var pastX:Float = 0; + var pastY:Float = 0; + public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false, shouldMove:Bool = false) { + pastX = x; + pastY = y; + super(x, y); _finalText = text; @@ -66,6 +72,24 @@ class Alphabet extends FlxSpriteGroup } } + public function reType(text) + { + for (i in listOAlphabets) + remove(i); + _finalText = text; + this.text = text; + + lastSprite = null; + + updateHitbox(); + + listOAlphabets.clear(); + x = pastX; + y = pastY; + + addText(); + } + public function addText() { doSplitWords(); @@ -254,8 +278,10 @@ class AlphaCharacter extends FlxSprite super(x, y); var tex = Paths.getSparrowAtlas('alphabet'); frames = tex; - - antialiasing = true; + if(FlxG.save.data.antialiasing) + { + antialiasing = true; + } } public function createBold(letter:String) diff --git a/source/AnimationDebug.hx b/source/AnimationDebug.hx index 05b40d6..46d2188 100644 --- a/source/AnimationDebug.hx +++ b/source/AnimationDebug.hx @@ -118,6 +118,9 @@ class AnimationDebug extends FlxState if (FlxG.keys.justPressed.Q) FlxG.camera.zoom -= 0.25; + if (FlxG.keys.justPressed.F) + char.flipX = !char.flipX; + if (FlxG.keys.pressed.I || FlxG.keys.pressed.J || FlxG.keys.pressed.K || FlxG.keys.pressed.L) { if (FlxG.keys.pressed.I) diff --git a/source/BackgroundDancer.hx b/source/BackgroundDancer.hx index c572c1e..07ef6da 100644 --- a/source/BackgroundDancer.hx +++ b/source/BackgroundDancer.hx @@ -1,5 +1,6 @@ package; +import flixel.FlxG; import flixel.FlxSprite; import flixel.graphics.frames.FlxAtlasFrames; @@ -13,7 +14,10 @@ class BackgroundDancer extends FlxSprite 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; + if(FlxG.save.data.antialiasing) + { + antialiasing = true; + } } var danceDir:Bool = false; diff --git a/source/Caching.hx b/source/Caching.hx index 2c6fb50..568c921 100644 --- a/source/Caching.hx +++ b/source/Caching.hx @@ -1,10 +1,20 @@ +#if sys package; +import lime.app.Application; +#if windows +import Discord.DiscordClient; +#end +import openfl.display.BitmapData; +import openfl.utils.Assets; +import flixel.ui.FlxBar; import haxe.Exception; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; +#if cpp import sys.FileSystem; import sys.io.File; +#end import flixel.FlxG; import flixel.FlxSprite; import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond; @@ -22,107 +32,152 @@ using StringTools; class Caching extends MusicBeatState { - var toBeDone = 0; - var done = 0; + var toBeDone = 0; + var done = 0; + + var loaded = false; + + var text:FlxText; + var kadeLogo:FlxSprite; + + public static var bitmapData:Map; + + var images = []; + var music = []; + var charts = []; - var text:FlxText; - var kadeLogo:FlxSprite; override function create() { - FlxG.mouse.visible = false; - FlxG.worldBounds.set(0,0); + FlxG.save.bind('funkin', 'ninjamuffin99'); - text = new FlxText(FlxG.width / 2, FlxG.height / 2 + 300,0,"Loading..."); - text.size = 34; - text.alignment = FlxTextAlign.CENTER; - text.alpha = 0; + PlayerSettings.init(); - 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)); + KadeEngineData.initSave(); - kadeLogo.alpha = 0; + FlxG.mouse.visible = false; - add(kadeLogo); - add(text); + FlxG.worldBounds.set(0,0); - trace('starting caching..'); - - sys.thread.Thread.create(() -> { - cache(); - }); + bitmapData = new Map(); + + 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.antialiasing = true; + + kadeLogo.alpha = 0; + + #if cpp + if (FlxG.save.data.cacheImages) + { + 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); + } + #end + + toBeDone = Lambda.count(images) + Lambda.count(music); + + var bar = new FlxBar(10,FlxG.height - 50,FlxBarFillDirection.LEFT_TO_RIGHT,FlxG.width,40,null,"done",0,toBeDone); + bar.color = FlxColor.PURPLE; + + add(bar); + + add(kadeLogo); + add(text); + + trace('starting caching..'); + + #if cpp + // update thread + + sys.thread.Thread.create(() -> { + while(!loaded) + { + 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 + ")"; + } + } + + }); + + // cache thread + + sys.thread.Thread.create(() -> { + cache(); + }); + #end + + super.create(); + } + + var calledDone = false; + + override function update(elapsed) + { + super.update(elapsed); + } - super.create(); - } + function cache() + { + trace("LOADING: " + toBeDone + " OBJECTS."); - var calledDone = false; + for (i in images) + { + var replaced = i.replace(".png",""); + var data:BitmapData = BitmapData.fromFile("assets/shared/images/characters/" + i); + trace('id ' + replaced + ' file - assets/shared/images/characters/' + i + ' ${data.width}'); + var graph = FlxGraphic.fromBitmapData(data); + graph.persist = true; + graph.destroyOnNoUse = false; + bitmapData.set(replaced,graph); + done++; + } - 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); - } + for (i in music) + { + FlxG.sound.cache(Paths.inst(i)); + FlxG.sound.cache(Paths.voices(i)); + trace("cached " + i); + done++; + } - function cache() - { + trace("Finished caching..."); - var images = []; - var music = []; + loaded = true; - trace("caching images..."); + trace(Assets.cache.hasBitmapData('GF_assets')); - for (i in FileSystem.readDirectory(FileSystem.absolutePath("assets/shared/images/characters"))) - { - if (!i.endsWith(".png")) - continue; - images.push(i); - } + FlxG.switchState(new TitleState()); + } - 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 +} +#end \ No newline at end of file diff --git a/source/Character.hx b/source/Character.hx index f9df179..194a013 100644 --- a/source/Character.hx +++ b/source/Character.hx @@ -26,13 +26,16 @@ class Character extends FlxSprite this.isPlayer = isPlayer; var tex:FlxAtlasFrames; - antialiasing = true; + if(FlxG.save.data.antialiasing) + { + antialiasing = true; + } switch (curCharacter) { case 'gf': // GIRLFRIEND CODE - tex = Paths.getSparrowAtlas('characters/GF_assets'); + tex = Paths.getSparrowAtlas('GF_assets','shared',true); frames = tex; animation.addByPrefix('cheer', 'GF Cheer', 24, false); animation.addByPrefix('singLEFT', 'GF left note', 24, false); @@ -46,24 +49,12 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('danceRight'); case 'gf-christmas': - tex = Paths.getSparrowAtlas('characters/gfChristmas'); + tex = Paths.getSparrowAtlas('gfChristmas','shared',true); frames = tex; animation.addByPrefix('cheer', 'GF Cheer', 24, false); animation.addByPrefix('singLEFT', 'GF left note', 24, false); @@ -77,44 +68,30 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('danceRight'); case 'gf-car': - tex = Paths.getSparrowAtlas('characters/gfCar'); + tex = Paths.getSparrowAtlas('gfCar','shared',true); 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); + loadOffsetFile(curCharacter); playAnim('danceRight'); case 'gf-pixel': - tex = Paths.getSparrowAtlas('characters/gfPixel'); + tex = Paths.getSparrowAtlas('gfPixel','shared',true); 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); + loadOffsetFile(curCharacter); playAnim('danceRight'); @@ -124,7 +101,7 @@ class Character extends FlxSprite case 'dad': // DAD ANIMATION LOADING CODE - tex = Paths.getSparrowAtlas('characters/DADDY_DEAREST', 'shared'); + tex = Paths.getSparrowAtlas('DADDY_DEAREST','shared',true); frames = tex; animation.addByPrefix('idle', 'Dad idle dance', 24); animation.addByPrefix('singUP', 'Dad Sing Note UP', 24); @@ -132,15 +109,11 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('idle'); case 'spooky': - tex = Paths.getSparrowAtlas('characters/spooky_kids_assets'); + tex = Paths.getSparrowAtlas('spooky_kids_assets','shared',true); frames = tex; animation.addByPrefix('singUP', 'spooky UP NOTE', 24, false); animation.addByPrefix('singDOWN', 'spooky DOWN note', 24, false); @@ -149,17 +122,11 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('danceRight'); case 'mom': - tex = Paths.getSparrowAtlas('characters/Mom_Assets'); + tex = Paths.getSparrowAtlas('Mom_Assets','shared',true); frames = tex; animation.addByPrefix('idle', "Mom Idle", 24, false); @@ -170,16 +137,12 @@ class Character extends FlxSprite // 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); + loadOffsetFile(curCharacter); playAnim('idle'); case 'mom-car': - tex = Paths.getSparrowAtlas('characters/momCar'); + tex = Paths.getSparrowAtlas('momCar','shared',true); frames = tex; animation.addByPrefix('idle', "Mom Idle", 24, false); @@ -190,15 +153,11 @@ class Character extends FlxSprite // 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); + loadOffsetFile(curCharacter); playAnim('idle'); case 'monster': - tex = Paths.getSparrowAtlas('characters/Monster_Assets'); + tex = Paths.getSparrowAtlas('Monster_Assets','shared',true); frames = tex; animation.addByPrefix('idle', 'monster idle', 24, false); animation.addByPrefix('singUP', 'monster up note', 24, false); @@ -206,14 +165,10 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('idle'); case 'monster-christmas': - tex = Paths.getSparrowAtlas('characters/monsterChristmas'); + tex = Paths.getSparrowAtlas('monsterChristmas','shared',true); frames = tex; animation.addByPrefix('idle', 'monster idle', 24, false); animation.addByPrefix('singUP', 'monster up note', 24, false); @@ -221,14 +176,10 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('idle'); case 'pico': - tex = Paths.getSparrowAtlas('characters/Pico_FNF_assetss'); + tex = Paths.getSparrowAtlas('Pico_FNF_assetss','shared',true); frames = tex; animation.addByPrefix('idle', "Pico Idle Dance", 24); animation.addByPrefix('singUP', 'pico Up note0', 24, false); @@ -252,22 +203,14 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('idle'); flipX = true; case 'bf': - var tex = Paths.getSparrowAtlas('characters/BOYFRIEND', 'shared'); + var tex = Paths.getSparrowAtlas('BOYFRIEND','shared',true); frames = tex; trace(tex.frames.length); @@ -284,32 +227,19 @@ class Character extends FlxSprite animation.addByPrefix('hey', 'BF HEY', 24, false); animation.addByPrefix('firstDeath', "BF dies", 24, false); - animation.addByPrefix('deathLoop', "BF Dead Loop", 24, true); + animation.addByPrefix('deathLoop', "BF Dead Loop", 24, false); 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); + loadOffsetFile(curCharacter); playAnim('idle'); flipX = true; case 'bf-christmas': - var tex = Paths.getSparrowAtlas('characters/bfChristmas'); + var tex = Paths.getSparrowAtlas('bfChristmas','shared',true); frames = tex; animation.addByPrefix('idle', 'BF idle dance', 24, false); animation.addByPrefix('singUP', 'BF NOTE UP0', 24, false); @@ -322,22 +252,13 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('idle'); flipX = true; case 'bf-car': - var tex = Paths.getSparrowAtlas('characters/bfCar'); + var tex = Paths.getSparrowAtlas('bfCar','shared',true); frames = tex; animation.addByPrefix('idle', 'BF idle dance', 24, false); animation.addByPrefix('singUP', 'BF NOTE UP0', 24, false); @@ -349,20 +270,12 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('idle'); flipX = true; case 'bf-pixel': - frames = Paths.getSparrowAtlas('characters/bfPixel'); + frames = Paths.getSparrowAtlas('bfPixel','shared',true); animation.addByPrefix('idle', 'BF IDLE', 24, false); animation.addByPrefix('singUP', 'BF UP NOTE', 24, false); animation.addByPrefix('singLEFT', 'BF LEFT NOTE', 24, false); @@ -373,15 +286,7 @@ class Character extends FlxSprite 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"); + loadOffsetFile(curCharacter); setGraphicSize(Std.int(width * 6)); updateHitbox(); @@ -395,16 +300,14 @@ class Character extends FlxSprite flipX = true; case 'bf-pixel-dead': - frames = Paths.getSparrowAtlas('characters/bfPixelsDEAD'); + frames = Paths.getSparrowAtlas('bfPixelsDEAD','shared',true); 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('deathLoop', "Retry Loop", 24, false); animation.addByPrefix('deathConfirm', "RETRY CONFIRM", 24, false); animation.play('firstDeath'); - addOffset('firstDeath'); - addOffset('deathLoop', -37); - addOffset('deathConfirm', -37); + loadOffsetFile(curCharacter); playAnim('firstDeath'); // pixel bullshit setGraphicSize(Std.int(width * 6)); @@ -413,18 +316,14 @@ class Character extends FlxSprite flipX = true; case 'senpai': - frames = Paths.getSparrowAtlas('characters/senpai'); + frames = Paths.getSparrowAtlas('senpai','shared',true); 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); + loadOffsetFile(curCharacter); playAnim('idle'); @@ -433,18 +332,14 @@ class Character extends FlxSprite antialiasing = false; case 'senpai-angry': - frames = Paths.getSparrowAtlas('characters/senpai'); + frames = Paths.getSparrowAtlas('senpai','shared',true); 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); + loadOffsetFile(curCharacter); playAnim('idle'); setGraphicSize(Std.int(width * 6)); @@ -453,18 +348,14 @@ class Character extends FlxSprite antialiasing = false; case 'spirit': - frames = Paths.getPackerAtlas('characters/spirit'); + frames = Paths.getPackerAtlas('spirit','shared',false); 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); + loadOffsetFile(curCharacter); setGraphicSize(Std.int(width * 6)); updateHitbox(); @@ -474,7 +365,7 @@ class Character extends FlxSprite antialiasing = false; case 'parents-christmas': - frames = Paths.getSparrowAtlas('characters/mom_dad_christmas_assets'); + frames = Paths.getSparrowAtlas('mom_dad_christmas_assets','shared',true); 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); @@ -487,15 +378,7 @@ class Character extends FlxSprite 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); + loadOffsetFile(curCharacter); playAnim('idle'); } @@ -525,6 +408,17 @@ class Character extends FlxSprite } } + public function loadOffsetFile(character:String) + { + var offset:Array = CoolUtil.coolTextFile(Paths.txt('images/characters/' + character + "Offsets", 'shared')); + + for (i in 0...offset.length) + { + var data:Array = offset[i].split(' '); + addOffset(data[0], Std.parseInt(data[1]), Std.parseInt(data[2])); + } + } + override function update(elapsed:Float) { if (!curCharacter.startsWith('bf')) @@ -561,13 +455,13 @@ class Character extends FlxSprite /** * FOR GF DANCING SHIT */ - public function dance() + public function dance(forced:Bool = false) { if (!debugMode) { switch (curCharacter) { - case 'gf': + case 'gf' | 'gf-christmas' | 'gf-car' | 'gf-pixel': if (!animation.curAnim.name.startsWith('hair')) { danced = !danced; @@ -577,39 +471,6 @@ class Character extends FlxSprite 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; @@ -618,7 +479,7 @@ class Character extends FlxSprite else playAnim('danceLeft'); default: - playAnim('idle'); + playAnim('idle', forced); } } } diff --git a/source/ChartingState.hx b/source/ChartingState.hx index 8e959f9..33cb1c4 100644 --- a/source/ChartingState.hx +++ b/source/ChartingState.hx @@ -1,6 +1,13 @@ package; +import openfl.system.System; +#if sys +import sys.io.File; +#end +import flixel.addons.ui.FlxUIButton; +import flixel.addons.ui.StrNameLabel; import flixel.FlxCamera; +import flixel.FlxObject; import flixel.addons.ui.FlxUIText; import haxe.zip.Writer; import Conductor.BPMChangeEvent; @@ -41,13 +48,24 @@ using StringTools; class ChartingState extends MusicBeatState { + public static var instance:ChartingState; + var _file:FileReference; public var playClaps:Bool = false; - public var snap:Int = 1; + public var snap:Int = 16; + + public var deezNuts:Map = new Map(); // snap conversion map var UI_box:FlxUITabMenu; + var UI_options:FlxUITabMenu; + + public static var lengthInSteps:Float = 0; + public static var lengthInBeats:Float = 0; + + public var beatsShown:Float = 1; // for the zoom factor + public var zoomFactor:Float = 1; /** * Array of notes showing when each section STARTS in STEPS @@ -68,14 +86,20 @@ class ChartingState extends MusicBeatState var GRID_SIZE:Int = 40; + var subDivisions:Float = 1; + var defaultSnap:Bool = true; + var dummyArrow:FlxSprite; + var curRenderedNotes:FlxTypedGroup; var curRenderedSustains:FlxTypedGroup; var gridBG:FlxSprite; - var _song:SwagSong; + public var sectionRenderes:FlxTypedGroup; + + public static var _song:SwagSong; var typingShit:FlxInputText; /* @@ -90,25 +114,55 @@ class ChartingState extends MusicBeatState var player2:Character = new Character(0,0, "dad"); var player1:Boyfriend = new Boyfriend(0,0, "bf"); - var leftIcon:HealthIcon; - var rightIcon:HealthIcon; + public static var leftIcon:HealthIcon; + + var height = 0; + + public static var rightIcon:HealthIcon; private var lastNote:Note; + + public var lines:FlxTypedGroup; + var claps:Array = []; public var snapText:FlxText; + var camFollow:FlxObject; + + public static var latestChartVersion = "2"; + override function create() { curSection = lastSection; + trace(1 > Math.POSITIVE_INFINITY); + + FlxG.mouse.visible = true; + + instance = this; + + deezNuts.set(4,1); + deezNuts.set(8,2); + deezNuts.set(16,4); + deezNuts.set(32,8); + deezNuts.set(64,16); + + sectionRenderes = new FlxTypedGroup(); + lines = new FlxTypedGroup(); + texts = new FlxTypedGroup(); + + TimingStruct.clearTimings(); + if (PlayState.SONG != null) _song = PlayState.SONG; else { _song = { + chartVersion: latestChartVersion, song: 'Test', notes: [], + eventObjects: [], bpm: 150, needsVoices: true, player1: 'bf', @@ -121,19 +175,21 @@ class ChartingState extends MusicBeatState }; } - gridBG = FlxGridOverlay.create(GRID_SIZE, GRID_SIZE, GRID_SIZE * 8, GRID_SIZE * 16); - add(gridBG); + addGrid(1); - var blackBorder:FlxSprite = new FlxSprite(60,10).makeGraphic(120,100,FlxColor.BLACK); - blackBorder.scrollFactor.set(); + if (_song.chartVersion == null) + _song.chartVersion = "2"; + - blackBorder.alpha = 0.3; + //var blackBorder:FlxSprite = new FlxSprite(60,10).makeGraphic(120,100,FlxColor.BLACK); + //blackBorder.scrollFactor.set(); - snapText = new FlxText(60,10,0,"Snap: 1/" + snap + " (Press Control to unsnap the cursor)\nAdd Notes: 1-8 (or click)\n", 14); + //blackBorder.alpha = 0.3; + + + snapText = new FlxText(60,10,0,"", 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(); @@ -147,16 +203,122 @@ class ChartingState extends MusicBeatState // 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); + + var index = 0; + + if (_song.eventObjects == null) + _song.eventObjects = [new Song.Event("Init BPM",0,_song.bpm,"BPM Change")]; + + if (_song.eventObjects.length == 0) + _song.eventObjects = [new Song.Event("Init BPM",0,_song.bpm,"BPM Change")]; + + + trace("goin"); + + var currentIndex = 0; + for (i in _song.eventObjects) + { + var name = Reflect.field(i,"name"); + var type = Reflect.field(i,"type"); + var pos = Reflect.field(i,"position"); + var value = Reflect.field(i,"value"); + + if (type == "BPM Change") + { + var beat:Float = pos; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + currentIndex++; + } + } + + var lastSeg = TimingStruct.AllTimings[TimingStruct.AllTimings.length - 1]; + + for (i in 0...TimingStruct.AllTimings.length) + { + var seg = TimingStruct.AllTimings[i]; + if (i == TimingStruct.AllTimings.length - 1) + lastSeg = seg; + } + + recalculateAllSectionTimes(); + + trace("Song length in MS: " + FlxG.sound.music.length); + + for(i in 0...9000000) // REALLY HIGH BEATS just cuz like ig this is the upper limit, I mean ur chart is probably going to run like ass anyways + { + var seg = TimingStruct.getTimingAtBeat(i); + + + var start:Float = (i - seg.startBeat) / (seg.bpm / 60); + + var time = (seg.startTime + start) * 1000; + + if (time > FlxG.sound.music.length) + break; + + lengthInBeats = i; + } + + lengthInSteps = lengthInBeats * 4; + + trace('LENGTH IN STEPS ' + lengthInSteps + ' | LENGTH IN BEATS ' + lengthInBeats + ' | SECTIONS: ' + Math.floor(((lengthInSteps + 16)) / 16)); + + var sections = Math.floor(((lengthInSteps + 16)) / 16); + + var targetY = getYfromStrum(FlxG.sound.music.length); + + trace("TARGET " + targetY); + + for (awfgaw in 0...Math.round(targetY / 640) + 1920) // grids/steps + { + var renderer = new SectionRender(0,640 * awfgaw,GRID_SIZE); + if (_song.notes[awfgaw] == null) + _song.notes.push(newSection(16,true,false)); + renderer.section = _song.notes[awfgaw]; + + sectionRenderes.add(renderer); + + var down = getYfromStrum(renderer.section.startTime) * zoomFactor; + + var sectionicon = _song.notes[awfgaw].mustHitSection ? new HealthIcon(_song.player1).clone() : new HealthIcon(_song.player2).clone(); + sectionicon.x = -95; + sectionicon.y = down - 75; + sectionicon.setGraphicSize(0, 45); + + renderer.icon = sectionicon; + renderer.lastUpdated = _song.notes[awfgaw].mustHitSection; + + add(sectionicon); + height = Math.floor(renderer.y); + } + + + + trace(height); + + gridBlackLine = new FlxSprite(gridBG.width / 2).makeGraphic(2, height, FlxColor.BLACK); + + //leftIcon.scrollFactor.set(); + //rightIcon.scrollFactor.set(); + leftIcon.setGraphicSize(0, 45); rightIcon.setGraphicSize(0, 45); @@ -167,16 +329,16 @@ class ChartingState extends MusicBeatState leftIcon.setPosition(0, -100); rightIcon.setPosition(gridBG.width / 2, -100); + leftIcon.scrollFactor.set(); + rightIcon.scrollFactor.set(); + 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); + strumLine = new FlxSprite(0, 0).makeGraphic(Std.int(GRID_SIZE * 8), 4); dummyArrow = new FlxSprite().makeGraphic(GRID_SIZE, GRID_SIZE); - add(dummyArrow); - var tabs = [ {name: "Song", label: 'Song Data'}, {name: "Section", label: 'Section Data'}, @@ -185,27 +347,614 @@ class ChartingState extends MusicBeatState ]; UI_box = new FlxUITabMenu(null, tabs, true); - + + UI_box.scrollFactor.set(); UI_box.resize(300, 400); - UI_box.x = FlxG.width / 2; + UI_box.x = FlxG.width / 2 + 40; UI_box.y = 20; + + var opt_tabs = [{name: "Options", label:'Song Options'}, {name: "Events", label:'Song Events'}]; + + UI_options = new FlxUITabMenu(null, opt_tabs, true); + + UI_options.scrollFactor.set(); + UI_options.selected_tab = 0; + UI_options.resize(300, 200); + UI_options.x = UI_box.x; + UI_options.y = FlxG.height - 300; + add(UI_options); add(UI_box); + addSongUI(); addSectionUI(); addNoteUI(); + addOptionsUI(); + addEventsUI(); + + regenerateLines(); + + + updateGrid(); + + trace("bruh"); + + + add(sectionRenderes); + add(dummyArrow); + add(strumLine); + add(lines); + add(texts); + add(gridBlackLine); add(curRenderedNotes); add(curRenderedSustains); - add(blackBorder); + trace("bruh"); + + //add(blackBorder); add(snapText); + trace("bruh"); + trace("create"); + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in _song.eventObjects) + { + if (i.type == "BPM Change") + { + var beat:Float = i.position; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,i.value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + currentIndex++; + } + } super.create(); } + public var texts:FlxTypedGroup; + + function regenerateLines() + { + while(lines.members.length > 0) + { + lines.members[0].destroy(); + lines.members.remove(lines.members[0]); + } + + while(texts.members.length > 0) + { + texts.members[0].destroy(); + texts.members.remove(texts.members[0]); + } + trace("removed lines and texts"); + + if (_song.eventObjects != null) + for(i in _song.eventObjects) + { + var seg = TimingStruct.getTimingAtBeat(i.position); + + var posi:Float = 0; + + if (seg != null) + { + var start:Float = (i.position - seg.startBeat) / (seg.bpm / 60); + + posi = seg.startTime + start; + } + + var pos = getYfromStrum(posi * 1000) * zoomFactor; + + if (pos < 0) + pos = 0; + + var type = i.type; + + var text = new FlxText(-190, pos,0,i.name + "\n" + type + "\n" + i.value,12); + var line = new FlxSprite(0, pos).makeGraphic(Std.int(GRID_SIZE * 8), 4, FlxColor.BLUE); + + line.alpha = 0.2; + + lines.add(line); + texts.add(text); + + add(line); + add(text); + } + + for (i in sectionRenderes) + { + var pos = getYfromStrum(i.section.startTime) * zoomFactor; + i.icon.y = pos - 75; + + var line = new FlxSprite(0, pos).makeGraphic(Std.int(GRID_SIZE * 8), 4, FlxColor.BLACK); + line.alpha = 0.4; + lines.add(line); + } + } + + function addGrid(?divisions:Float = 1) + { + // This here is because non-integer numbers aren't supported as grid sizes, making the grid slowly 'drift' as it goes on + var h = GRID_SIZE / divisions; + if (Math.floor(h) != h) + h = GRID_SIZE; + + remove(gridBG); + gridBG = FlxGridOverlay.create(GRID_SIZE, Std.int(h), GRID_SIZE * 8,GRID_SIZE * 16); + trace(gridBG.height); + //gridBG.scrollFactor.set(); + //gridBG.x += 358; + //gridBG.y += 390; + trace("height of " + (Math.floor(lengthInSteps))); + + + /*for(i in 0...Math.floor(lengthInSteps)) + { + trace("Creating sprite " + i); + var grid = FlxGridOverlay.create(GRID_SIZE, Std.int(h), GRID_SIZE * 8, GRID_SIZE * 16); + add(grid); + if (i > lengthInSteps) + break; + }*/ + + var totalHeight = 0; + + //add(gridBG); + + + remove(gridBlackLine); + gridBlackLine = new FlxSprite(0 + gridBG.width / 2).makeGraphic(2, Std.int(Math.floor(lengthInSteps)), FlxColor.BLACK); + add(gridBlackLine); + } + + var stepperDiv:FlxUINumericStepper; + var check_snap:FlxUICheckBox; + var listOfEvents:FlxUIDropDownMenu; + var currentSelectedEventName:String = ""; + var savedType:String = ""; + var savedValue:String = ""; + var currentEventPosition:Float = 0; + + function containsName(name:String, events:Array):Song.Event + { + for (i in events) + { + var thisName = Reflect.field(i,"name"); + + if (thisName == name) + return i; + } + return null; + } + + public var chartEvents:Array = []; + + public var Typeables:Array = []; + + function addEventsUI() + { + if (_song.eventObjects == null) + { + _song.eventObjects = [new Song.Event("Init BPM",0,_song.bpm,"BPM Change")]; + } + + var firstEvent = ""; + + if (Lambda.count(_song.eventObjects) != 0) + { + firstEvent = _song.eventObjects[0].name; + } + + var listLabel = new FlxText(10, 5, 'List of Events'); + var nameLabel = new FlxText(150, 5, 'Event Name'); + var eventName = new FlxUIInputText(150,20,80,""); + var typeLabel = new FlxText(10, 45, 'Type of Event'); + var eventType = new FlxUIDropDownMenu(10,60,FlxUIDropDownMenu.makeStrIdLabelArray(["BPM Change", "Scroll Speed Change"], true)); + var valueLabel = new FlxText(150, 45, 'Event Value'); + var eventValue = new FlxUIInputText(150,60,80,""); + var eventSave = new FlxButton(10,155,"Save Event", function() { + var pog:Song.Event = new Song.Event(currentSelectedEventName,currentEventPosition,HelperFunctions.truncateFloat(Std.parseFloat(savedValue), 3),savedType); + + trace("trying to save " + currentSelectedEventName); + + var obj = containsName(pog.name,_song.eventObjects); + + + if (pog.name == "") + return; + + trace("yeah we can save it"); + + if (obj != null) + _song.eventObjects.remove(obj); + _song.eventObjects.push(pog); + + trace(_song.eventObjects.length); + + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in _song.eventObjects) + { + var name = Reflect.field(i,"name"); + var type = Reflect.field(i,"type"); + var pos = Reflect.field(i,"position"); + var value = Reflect.field(i,"value"); + + trace(i.type); + if (type == "BPM Change") + { + var beat:Float = pos; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + currentIndex++; + } + } + + if (pog.type == "BPM Change") + recalculateAllSectionTimes(); + + regenerateLines(); + + var listofnames = []; + + for (key => value in _song.eventObjects) { + listofnames.push(value.name); + } + + listOfEvents.setData(FlxUIDropDownMenu.makeStrIdLabelArray(listofnames, true)); + + listOfEvents.selectedLabel = pog.name; + + trace('end'); + }); + var posLabel = new FlxText(150, 85, 'Event Position'); + var eventPos = new FlxUIInputText(150,100,80,""); + var eventAdd = new FlxButton(95,155,"Add Event", function() { + + var pog:Song.Event = new Song.Event("New Event " + HelperFunctions.truncateFloat(curDecimalBeat, 3),HelperFunctions.truncateFloat(curDecimalBeat, 3),_song.bpm,"BPM Change"); + + trace("adding " + pog.name); + + var obj = containsName(pog.name,_song.eventObjects); + + if (obj != null) + return; + + trace("yeah we can add it"); + + _song.eventObjects.push(pog); + + eventName.text = pog.name; + eventType.selectedLabel = pog.type; + eventValue.text = pog.value + ""; + eventPos.text = pog.position + ""; + currentSelectedEventName = pog.name; + currentEventPosition = pog.position; + + savedType = pog.type; + savedValue = pog.value + ""; + + var listofnames = []; + + for (key => value in _song.eventObjects) { + listofnames.push(value.name); + } + + listOfEvents.setData(FlxUIDropDownMenu.makeStrIdLabelArray(listofnames, true)); + + listOfEvents.selectedLabel = pog.name; + + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in _song.eventObjects) + { + var name = Reflect.field(i,"name"); + var type = Reflect.field(i,"type"); + var pos = Reflect.field(i,"position"); + var value = Reflect.field(i,"value"); + + trace(i.type); + if (type == "BPM Change") + { + var beat:Float = pos; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + currentIndex++; + } + } + trace("BPM CHANGES:"); + + for (i in TimingStruct.AllTimings) + trace(i.bpm + " - START: " + i.startBeat + " - END: " + i.endBeat + " - START-TIME: " + i.startTime); + + recalculateAllSectionTimes(); + + regenerateLines(); + + + }); + var eventRemove = new FlxButton(180,155,"Remove Event", function() { + + trace("lets see if we can remove " + listOfEvents.selectedLabel); + + var obj = containsName(listOfEvents.selectedLabel,_song.eventObjects); + + trace(obj); + + if (obj == null) + return; + + trace("yeah we can remove it it"); + + _song.eventObjects.remove(obj); + + var firstEvent = _song.eventObjects[0]; + + if (firstEvent == null) + { + _song.eventObjects.push(new Song.Event("Init BPM",0,_song.bpm,"BPM Change")); + firstEvent = _song.eventObjects[0]; + } + + eventName.text = firstEvent.name; + eventType.selectedLabel = firstEvent.type; + eventValue.text = firstEvent.value + ""; + eventPos.text = firstEvent.position + ""; + currentSelectedEventName = firstEvent.name; + currentEventPosition = firstEvent.position; + + savedType = firstEvent.type; + savedValue = firstEvent.value + ""; + + var listofnames = []; + + for (key => value in _song.eventObjects) { + listofnames.push(value.name); + } + + listOfEvents.setData(FlxUIDropDownMenu.makeStrIdLabelArray(listofnames, true)); + + listOfEvents.selectedLabel = firstEvent.name; + + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in _song.eventObjects) + { + var name = Reflect.field(i,"name"); + var type = Reflect.field(i,"type"); + var pos = Reflect.field(i,"position"); + var value = Reflect.field(i,"value"); + + trace(i.type); + if (type == "BPM Change") + { + var beat:Float = pos; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + currentIndex++; + } + } + + recalculateAllSectionTimes(); + + regenerateLines(); + + + }); + var updatePos = new FlxButton(150,120,"Update Pos", function() { + var obj = containsName(currentSelectedEventName,_song.eventObjects); + if (obj == null) + return; + currentEventPosition = curDecimalBeat; + obj.position = currentEventPosition; + eventPos.text = currentEventPosition + ""; + }); + + + + var listofnames = []; + + var firstEventObject = null; + + for (event in _song.eventObjects) { + var name = Reflect.field(event,"name"); + var type = Reflect.field(event,"type"); + var pos = Reflect.field(event,"position"); + var value = Reflect.field(event,"value"); + + trace(value); + + var eventt = new Song.Event(name,pos,value,type); + + chartEvents.push(eventt); + listofnames.push(name); + } + + _song.eventObjects = chartEvents; + + if (listofnames.length == 0) + listofnames.push(""); + + if (_song.eventObjects.length != 0) + firstEventObject = _song.eventObjects[0]; + trace("bruh"); + + + if (firstEvent != "") + { + trace(firstEventObject); + eventName.text = firstEventObject.name; + trace("bruh"); + eventType.selectedLabel = firstEventObject.type; + trace("bruh"); + eventValue.text = firstEventObject.value + ""; + trace("bruh"); + currentSelectedEventName = firstEventObject.name; + trace("bruh"); + currentEventPosition = firstEventObject.position; + trace("bruh"); + eventPos.text = currentEventPosition + ""; + trace("bruh"); + } + + listOfEvents = new FlxUIDropDownMenu(10,20, FlxUIDropDownMenu.makeStrIdLabelArray(listofnames, true), function(name:String) + { + var event = containsName(listOfEvents.selectedLabel,_song.eventObjects); + + if (event == null) + return; + + trace('selecting ' + name + ' found: ' + event); + + eventName.text = event.name; + eventValue.text = event.value + ""; + eventPos.text = event.position + ""; + eventType.selectedLabel = event.type; + currentSelectedEventName = event.name; + currentEventPosition = event.position; + }); + + eventValue.callback = function(string:String, string2:String) + { + trace(string + " - value"); + savedValue = string; + }; + + eventType.callback = function(type:String) + { + savedType = eventType.selectedLabel; + }; + + eventName.callback = function(string:String, string2:String) + { + var obj = containsName(currentSelectedEventName,_song.eventObjects); + if (obj == null) + { + currentSelectedEventName = string; + return; + } + obj = containsName(string,_song.eventObjects); + if (obj != null) + return; + obj = containsName(currentSelectedEventName,_song.eventObjects); + obj.name = string; + currentSelectedEventName = string; + }; + trace("bruh"); + + Typeables.push(eventPos); + Typeables.push(eventValue); + Typeables.push(eventName); + + var tab_events = new FlxUI(null, UI_options); + tab_events.name = "Events"; + tab_events.add(posLabel); + tab_events.add(valueLabel); + tab_events.add(nameLabel); + tab_events.add(listLabel); + tab_events.add(typeLabel); + tab_events.add(eventName); + tab_events.add(eventType); + tab_events.add(listOfEvents); + tab_events.add(eventValue); + tab_events.add(eventSave); + tab_events.add(eventAdd); + tab_events.add(eventRemove); + tab_events.add(eventPos); + tab_events.add(updatePos); + UI_options.addGroup(tab_events); + } + + function addOptionsUI() + { + + + var hitsounds = new FlxUICheckBox(10, 60, null, null, "Play hitsounds", 100); + hitsounds.checked = false; + hitsounds.callback = function() + { + playClaps = hitsounds.checked; + }; + + var check_mute_inst = new FlxUICheckBox(10, 90, null, null, "Mute Instrumental", 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; + }; + + check_snap = new FlxUICheckBox(80, 25, null, null, "Snap to grid", 100); + check_snap.checked = defaultSnap; + // _song.needsVoices = check_voices.checked; + check_snap.callback = function() + { + defaultSnap = check_snap.checked; + trace('CHECKED!'); + }; + + var tab_options = new FlxUI(null, UI_options); + tab_options.name = "Options"; + tab_options.add(hitsounds); + tab_options.add(check_mute_inst); + UI_options.addGroup(tab_options); + } + function addSongUI():Void { var UI_songTitle = new FlxUIInputText(10, 10, 70, _song.song, 8); @@ -220,18 +969,6 @@ class ChartingState extends MusicBeatState 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(); @@ -274,7 +1011,14 @@ class ChartingState extends MusicBeatState var stepperSpeedLabel = new FlxText(74,80,'Scroll Speed'); var stepperVocalVol:FlxUINumericStepper = new FlxUINumericStepper(10, 95, 0.1, 1, 0.1, 10, 1); + #if sys + if (!PlayState.isSM) + stepperVocalVol.value = vocals.volume; + else + stepperVocalVol.value = 1; + #else stepperVocalVol.value = vocals.volume; + #end stepperVocalVol.name = 'song_vocalvol'; var stepperVocalVolLabel = new FlxText(74, 95, 'Vocal Volume'); @@ -283,14 +1027,6 @@ class ChartingState extends MusicBeatState 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'); @@ -309,10 +1045,10 @@ class ChartingState extends MusicBeatState 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 characters:Array = CoolUtil.coolTextFile(Paths.txt('data/characterList')); + var gfVersions:Array = CoolUtil.coolTextFile(Paths.txt('data/gfVersionList')); + var stages:Array = CoolUtil.coolTextFile(Paths.txt('data/stageList')); + var noteStyles:Array = CoolUtil.coolTextFile(Paths.txt('data/noteStyleList')); var player1DropDown = new FlxUIDropDownMenu(10, 100, FlxUIDropDownMenu.makeStrIdLabelArray(characters, true), function(character:String) { @@ -354,12 +1090,13 @@ class ChartingState extends MusicBeatState 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(check_mute_inst); tab_group_song.add(saveButton); tab_group_song.add(reloadSong); tab_group_song.add(reloadSongJson); @@ -379,7 +1116,7 @@ class ChartingState extends MusicBeatState tab_group_song.add(shiftNoteDialLabel3); tab_group_song.add(stepperShiftNoteDialms); tab_group_song.add(shiftNoteButton); - tab_group_song.add(hitsounds); + //tab_group_song.add(hitsounds); var tab_group_assets = new FlxUI(null, UI_box); tab_group_assets.name = "Assets"; @@ -396,9 +1133,11 @@ class ChartingState extends MusicBeatState UI_box.addGroup(tab_group_song); UI_box.addGroup(tab_group_assets); - UI_box.scrollFactor.set(); + + camFollow = new FlxObject(280, 0, 1, 1); + add(camFollow); - FlxG.camera.follow(strumLine); + FlxG.camera.follow(camFollow); } var stepperLength:FlxUINumericStepper; @@ -412,15 +1151,6 @@ class ChartingState extends MusicBeatState 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'); @@ -431,39 +1161,87 @@ class ChartingState extends MusicBeatState }); var clearSectionButton:FlxButton = new FlxButton(10, 150, "Clear Section", clearSection); + var startSection:FlxButton = new FlxButton(10, 85, "Play Here", function() { + PlayState.SONG = _song; + FlxG.sound.music.stop(); + if (!PlayState.isSM) + vocals.stop(); + PlayState.startTime = lastUpdatedSection.startTime; + LoadingState.loadAndSwitchState(new PlayState()); + }); var swapSection:FlxButton = new FlxButton(10, 170, "Swap Section", function() { - for (i in 0..._song.notes[curSection].sectionNotes.length) + + var sect = lastUpdatedSection; + + if (sect == null) + return; + + for (i in 0...sect.sectionNotes.length) { - var note = _song.notes[curSection].sectionNotes[i]; - note[1] = (note[1] + 4) % 8; - _song.notes[curSection].sectionNotes[i] = note; + var note = sect.sectionNotes[i]; + if (note[1] < 4) + note[1] += 4; + else + note[1] -= 4; + sect.sectionNotes[i] = note; updateGrid(); } }); - check_mustHitSection = new FlxUICheckBox(10, 30, null, null, "Camera Points to P1?", 100); - check_mustHitSection.name = 'check_mustHit'; + check_mustHitSection = new FlxUICheckBox(10, 30, null, null, "Camera Points to P1?", 100,null,function() { + var sect = lastUpdatedSection; + + trace(sect); + + if (sect == null) + return; + + sect.mustHitSection = check_mustHitSection.checked; + + for (i in sectionRenderes) + { + if (i.section.startTime == sect.startTime) + { + var cachedY = i.icon.y; + remove(i.icon); + var sectionicon = check_mustHitSection.checked ? new HealthIcon(_song.player1).clone() : new HealthIcon(_song.player2).clone(); + sectionicon.x = -95; + sectionicon.y = cachedY; + sectionicon.setGraphicSize(0, 45); + + i.icon = sectionicon; + i.lastUpdated = sect.mustHitSection; + + add(sectionicon); + } + } + }); check_mustHitSection.checked = true; // _song.needsVoices = check_mustHit.checked; - check_altAnim = new FlxUICheckBox(10, 400, null, null, "Alternate Animation", 100); + check_altAnim = new FlxUICheckBox(10, 340, 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'; + var refresh = new FlxButton(10, 60, 'Refresh Section', function() { + var section = getSectionByTime(Conductor.songPosition); - tab_group_section.add(stepperLength); - tab_group_section.add(stepperLengthLabel); - tab_group_section.add(stepperSectionBPM); + if (section == null) + return; + + check_mustHitSection.checked = section.mustHitSection; + check_altAnim.checked = section.altAnim; + }); + + tab_group_section.add(refresh); 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); + tab_group_section.add(startSection); UI_box.addGroup(tab_group_section); } @@ -480,7 +1258,7 @@ class ChartingState extends MusicBeatState 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 = new FlxUINumericStepper(10, 10, Conductor.stepCrochet / 2, 0, 0, Conductor.stepCrochet * 16 * 4); stepperSusLength.value = 0; stepperSusLength.name = 'note_susLength'; @@ -494,8 +1272,8 @@ class ChartingState extends MusicBeatState 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); + /*player2 = new Character(0,0, _song.player2); + player1 = new Boyfriend(player2.width * 0.2,0 + player2.height, _song.player1); player1.y = player1.y - player1.height; @@ -506,6 +1284,8 @@ class ChartingState extends MusicBeatState UI_box.add(player2);*/ } + + function loadSong(daSong:String):Void { @@ -514,23 +1294,41 @@ class ChartingState extends MusicBeatState FlxG.sound.music.stop(); // vocals.stop(); } - + #if sys + if (PlayState.isSM) + { + trace("Loading " + PlayState.pathToSm + "/" + PlayState.sm.header.MUSIC); + var bytes = File.getBytes(PlayState.pathToSm + "/" + PlayState.sm.header.MUSIC); + var sound = new Sound(); + sound.loadCompressedDataFromByteArray(bytes.getData(), bytes.length); + FlxG.sound.playMusic(sound); + } + else + FlxG.sound.playMusic(Paths.inst(daSong), 0.6); + #else FlxG.sound.playMusic(Paths.inst(daSong), 0.6); + #end // WONT WORK FOR TUTORIAL OR TEST SONG!!! REDO LATER + #if sys + if (PlayState.isSM) + vocals = null; + else + vocals = new FlxSound().loadEmbedded(Paths.voices(daSong)); + #else vocals = new FlxSound().loadEmbedded(Paths.voices(daSong)); + #end FlxG.sound.list.add(vocals); FlxG.sound.music.pause(); - vocals.pause(); + if (!PlayState.isSM) + vocals.pause(); FlxG.sound.music.onComplete = function() { - vocals.pause(); - vocals.time = 0; + if (!PlayState.isSM) + vocals.pause(); FlxG.sound.music.pause(); - FlxG.sound.music.time = 0; - changeSection(); }; } @@ -561,13 +1359,8 @@ class ChartingState extends MusicBeatState 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; + getSectionByTime(Conductor.songPosition).altAnim = check.checked; } } else if (id == FlxUINumericStepper.CHANGE_EVENT && (sender is FlxUINumericStepper)) @@ -575,53 +1368,56 @@ class ChartingState extends MusicBeatState 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') + switch (wname) { - 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; + case 'section_length': + if (nums.value <= 4) + nums.value = 4; + getSectionByTime(Conductor.songPosition).lengthInSteps = Std.int(nums.value); + updateGrid(); + + case 'song_speed': + if (nums.value <= 0) + nums.value = 0; + _song.speed = nums.value; + + case 'song_bpm': + if (nums.value <= 0) + nums.value = 1; + tempBpm = Std.int(nums.value); + Conductor.mapBPMChanges(_song); + Conductor.changeBPM(Std.int(nums.value)); + + case 'note_susLength': + if (curSelectedNote == null) + return; + + if (nums.value <= 0) + nums.value = 0; + curSelectedNote[2] = nums.value; + updateGrid(); + + case 'section_bpm': + if (nums.value <= 0.1) + nums.value = 0.1; + getSectionByTime(Conductor.songPosition).bpm = Std.int(nums.value); + updateGrid(); + + case 'song_vocalvol': + if (nums.value <= 0.1) + nums.value = 0.1; + if (!PlayState.isSM) + vocals.volume = nums.value; + + case 'song_instvol': + if (nums.value <= 0.1) + nums.value = 0.1; + FlxG.sound.music.volume = nums.value; + + case 'divisions': + subDivisions = nums.value; + updateGrid(); } } @@ -633,58 +1429,303 @@ class ChartingState extends MusicBeatState /* this function got owned LOL function lengthBpmBullshit():Float { - if (_song.notes[curSection].changeBPM) - return _song.notes[curSection].lengthInSteps * (_song.notes[curSection].bpm / _song.bpm); + if (getSectionByTime(Conductor.songPosition).changeBPM) + return getSectionByTime(Conductor.songPosition).lengthInSteps * (getSectionByTime(Conductor.songPosition).bpm / _song.bpm); else - return _song.notes[curSection].lengthInSteps; + return getSectionByTime(Conductor.songPosition).lengthInSteps; }*/ + + function stepStartTime(step):Float { - return _song.bpm / (step / 4) / 60; + return Conductor.bpm / (step / 4) / 60; } - function sectionStartTime():Float + function sectionStartTime(?customIndex:Int = -1):Float { - var daBPM:Float = _song.bpm; + if (customIndex == -1) + customIndex = curSection; + var daBPM:Float = Conductor.bpm; var daPos:Float = 0; - for (i in 0...curSection) + for (i in 0...customIndex) { - 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; + var doSnapShit:Bool = false; + + public var diff:Float = 0; + + public var changeIndex = 0; + + public var currentBPM:Float = 0; + public var lastBPM:Float = 0; + + public var updateFrame = 0; + public var lastUpdatedSection:SwagSection = null; + + public function resizeEverything() + { + curRenderedNotes.forEach(function(note) { + var seg = TimingStruct.getTimingAtTimestamp(note.strumTime); + note.y = getYfromStrum(note.strumTime) * zoomFactor; + var stepCrochet = (((60 / seg.bpm) * 1000) / 4); + if (note.sustainLength >= 2) + { + note.noteCharterObject.y = note.y + GRID_SIZE; + note.noteCharterObject.makeGraphic(8,Math.floor((getYfromStrum(note.strumTime + note.sustainLength) * zoomFactor) - note.y),FlxColor.WHITE); + } + }); + + regenerateLines(); + } + + 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"; + for(i in sectionRenderes) + { + var diff = i.y - strumLine.y; + if (diff < 4000 && diff >= -4000) + { + i.active = true; + i.visible = true; + } + else + { + i.active = false; + i.visible = false; + } + } - curStep = recalculateSteps(); + for(i in curRenderedNotes) + { + var diff = i.y - strumLine.y; + if (diff < 4000 && diff >= -4000) + { + i.active = true; + i.visible = true; + } + else + { + i.active = false; + i.visible = false; + } + } - /*if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.RIGHT) + + var doInput = true; + + for (i in Typeables) + { + if (i.hasFocus) + doInput = false; + } + + if (doInput) + { + if (FlxG.mouse.wheel != 0) + { + FlxG.sound.music.pause(); + + if (!PlayState.isSM) + vocals.pause(); + claps.splice(0, claps.length); + + + if (FlxG.keys.pressed.CONTROL) + { + var amount = FlxG.mouse.wheel; + + if(amount > 0) + amount = 0; + + var increase:Float = 0; + + if (amount < 0) + increase = -0.02; + else + increase = 0.02; + + + zoomFactor += increase; + + if (zoomFactor > 2) + zoomFactor = 2; + + if (zoomFactor < 0.1) + zoomFactor = 0.1; + + resizeEverything(); + } + else + { + var amount = FlxG.mouse.wheel; + + if(amount > 0 && strumLine.y < 0) + amount = 0; + + if (doSnapShit) + { + var increase:Float = 0; + var beats:Float = 0; + + if (amount < 0) + { + increase = 1 / deezNuts.get(snap); + beats = (Math.floor((curDecimalBeat * deezNuts.get(snap)) + 0.001) / deezNuts.get(snap)) + increase; + } + else + { + increase = -1 / deezNuts.get(snap); + beats = ((Math.ceil(curDecimalBeat * deezNuts.get(snap)) - 0.001) / deezNuts.get(snap)) + increase; + } + + trace("SNAP - " + snap + " INCREASE - " + increase + " - GO TO BEAT " + beats); + + var data = TimingStruct.getTimingAtBeat(beats); + + if (beats <= 0) + FlxG.sound.music.time = 0; + + var bpm = data != null ? data.bpm : _song.bpm; + + if (data != null) + { + + FlxG.sound.music.time = (data.startTime + ((beats - data.startBeat) / (bpm/60)) ) * 1000; + } + } + if (!PlayState.isSM) + vocals.time = FlxG.sound.music.time; + } + } + } + + if (updateFrame == 4) + { + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in _song.eventObjects) + { + if (i.type == "BPM Change") + { + var beat:Float = i.position; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,i.value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + currentIndex++; + } + } + + recalculateAllSectionTimes(); + + regenerateLines(); + updateFrame++; + } + else if (updateFrame != 5) + updateFrame++; + + snapText.text = "Snap: 1/" + snap + " (" + (doSnapShit ? "Shift to disable, Left or Right to increase/decrease" : "Snap Disabled, Shift to renable.") + ")\nAdd Notes: 1-8 (or click)\nZoom: " + zoomFactor; + + + if (FlxG.keys.justPressed.RIGHT) snap = snap * 2; - if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.LEFT) + if (FlxG.keys.justPressed.LEFT) snap = Math.round(snap / 2); - if (snap >= 192) - snap = 192; - if (snap <= 1) - snap = 1;*/ - - if (FlxG.keys.justPressed.CONTROL) + if (snap >= 64) + snap = 64; + if (snap <= 4) + snap = 4; + /* + if (FlxG.keys.justPressed.SHIFT) doSnapShit = !doSnapShit; + */ + + doSnapShit = defaultSnap; + if (FlxG.keys.pressed.SHIFT) + { + doSnapShit = !defaultSnap; + } + + + check_snap.checked = doSnapShit; Conductor.songPosition = FlxG.sound.music.time; _song.song = typingShit.text; + + var timingSeg = TimingStruct.getTimingAtTimestamp(Conductor.songPosition); + + var start = Conductor.songPosition; + + if (timingSeg != null) + { + var timingSegBpm = timingSeg.bpm; + currentBPM = timingSegBpm; + + if (currentBPM != Conductor.bpm) + { + trace("BPM CHANGE to " + currentBPM); + Conductor.changeBPM(currentBPM, false); + } + + var pog:Float = (curDecimalBeat - timingSeg.startBeat) / (Conductor.bpm / 60); + + start = (timingSeg.startTime + pog) * 1000; + } + + + var weird = getSectionByTime(start, true); + + FlxG.watch.addQuick("Section",weird); + + if (weird != null) + { + if (lastUpdatedSection != getSectionByTime(start,true)) + { + lastUpdatedSection = weird; + check_mustHitSection.checked = weird.mustHitSection; + check_altAnim.checked = weird.altAnim; + } + } + + + strumLine.y = getYfromStrum(start) * zoomFactor; + camFollow.y = strumLine.y; + + + bpmTxt.text = Std.string(FlxMath.roundDecimal(Conductor.songPosition / 1000, 2)) + + " / " + + Std.string(FlxMath.roundDecimal(FlxG.sound.music.length / 1000, 2)) + + "\nCur Section: " + + curSection + + "\nCurBPM: " + + currentBPM + + "\nCurBeat: " + + HelperFunctions.truncateFloat(curDecimalBeat,3) + + "\nZoom: " + + zoomFactor; + + var left = FlxG.keys.justPressed.ONE; var down = FlxG.keys.justPressed.TWO; var up = FlxG.keys.justPressed.THREE; @@ -696,6 +1737,8 @@ class ChartingState extends MusicBeatState var pressArray = [left, down, up, right, leftO, downO, upO, rightO]; var delete = false; + if (doInput) + { curRenderedNotes.forEach(function(note:Note) { if (strumLine.overlaps(note) && pressArray[Math.floor(Math.abs(note.noteData))]) @@ -713,10 +1756,7 @@ class ChartingState extends MusicBeatState addNote(new Note(Conductor.songPosition,p)); } } - - strumLine.y = getYfromStrum((Conductor.songPosition - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps)); - - + } if (playClaps) { @@ -724,21 +1764,21 @@ class ChartingState extends MusicBeatState { if (FlxG.sound.music.playing) { - FlxG.overlap(strumLine, note, function(_, _) + if (strumLine.overlaps(note)) { 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) + if (getSectionByTime(Conductor.songPosition).mustHitSection) { trace('must hit ' + Math.abs(note.noteData)); if (note.noteData < 4) @@ -805,23 +1845,10 @@ class ChartingState extends MusicBeatState } });*/ - 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); + FlxG.watch.addQuick('daBeat', curDecimalBeat); + if (FlxG.mouse.justPressed) { if (FlxG.mouse.overlaps(curRenderedNotes)) @@ -843,10 +1870,10 @@ class ChartingState extends MusicBeatState } 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)) + if (FlxG.mouse.x > 0 + && FlxG.mouse.x < 0 + gridBG.width + && FlxG.mouse.y > 0 + && FlxG.mouse.y < 0 + height) { FlxG.log.add('added note'); addNote(); @@ -854,35 +1881,42 @@ class ChartingState extends MusicBeatState } } - 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)) + if (FlxG.mouse.x > 0 + && FlxG.mouse.x < gridBG.width + && FlxG.mouse.y > 0 + && FlxG.mouse.y < height) { + dummyArrow.visible = true; + 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; + + dummyArrow.y = (Math.floor(FlxG.mouse.y / (GRID_SIZE / deezNuts.get(snap))) * (GRID_SIZE / deezNuts.get(snap))); + } + else + { + dummyArrow.visible = false; } + if (doInput) + { if (FlxG.keys.justPressed.ENTER) { lastSection = curSection; PlayState.SONG = _song; FlxG.sound.music.stop(); + if (!PlayState.isSM) vocals.stop(); LoadingState.loadAndSwitchState(new PlayState()); } if (FlxG.keys.justPressed.E) { - changeNoteSustain(Conductor.stepCrochet); + changeNoteSustain(((60 / (timingSeg != null ? timingSeg.bpm : _song.bpm)) * 1000) / 4); } if (FlxG.keys.justPressed.Q) { - changeNoteSustain(-Conductor.stepCrochet); + changeNoteSustain(-(((60 / (timingSeg != null ? timingSeg.bpm : _song.bpm)) * 1000) / 4)); } if (FlxG.keys.justPressed.TAB) @@ -919,65 +1953,33 @@ class ChartingState extends MusicBeatState 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(); + if (!PlayState.isSM) vocals.pause(); claps.splice(0, claps.length); } else { + if (!PlayState.isSM) 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) + if (FlxG.sound.music.time < 0 || curDecimalBeat < 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(); + if (!PlayState.isSM) vocals.pause(); claps.splice(0, claps.length); @@ -990,6 +1992,7 @@ class ChartingState extends MusicBeatState else FlxG.sound.music.time += daTime; + if (!PlayState.isSM) vocals.time = FlxG.sound.music.time; } } @@ -998,6 +2001,7 @@ class ChartingState extends MusicBeatState if (FlxG.keys.justPressed.W || FlxG.keys.justPressed.S) { FlxG.sound.music.pause(); + if (!PlayState.isSM) vocals.pause(); var daTime:Float = Conductor.stepCrochet * 2; @@ -1009,25 +2013,18 @@ class ChartingState extends MusicBeatState else FlxG.sound.music.time += daTime; + if (!PlayState.isSM) 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); } @@ -1046,58 +2043,21 @@ class ChartingState extends MusicBeatState 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(); + if (!PlayState.isSM) vocals.pause(); // Basically old shit from changeSection??? - FlxG.sound.music.time = sectionStartTime(); - - if (songBeginning) - { - FlxG.sound.music.time = 0; - curSection = 0; - } + FlxG.sound.music.time = 0; + if (!PlayState.isSM) vocals.time = FlxG.sound.music.time; - updateCurStep(); updateGrid(); - updateSectionUI(); + if (!songBeginning) + updateSectionUI(); } function changeSection(sec:Int = 0, ?updateMusic:Bool = true):Void @@ -1114,6 +2074,7 @@ class ChartingState extends MusicBeatState if (updateMusic) { FlxG.sound.music.pause(); + if (!PlayState.isSM) vocals.pause(); /*var daNum:Int = 0; @@ -1125,6 +2086,7 @@ class ChartingState extends MusicBeatState }*/ FlxG.sound.music.time = sectionStartTime(); + if (!PlayState.isSM) vocals.time = FlxG.sound.music.time; updateCurStep(); } @@ -1139,13 +2101,17 @@ class ChartingState extends MusicBeatState function copySection(?sectionNum:Int = 1) { var daSec = FlxMath.maxInt(curSection, sectionNum); + var sect = lastUpdatedSection; + + if (sect == null) + return; 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); + sect.sectionNotes.push(copiedNote); } updateGrid(); @@ -1153,26 +2119,32 @@ class ChartingState extends MusicBeatState function updateSectionUI():Void { - var sec = _song.notes[curSection]; + var sec = getSectionByTime(Conductor.songPosition); - stepperLength.value = sec.lengthInSteps; - check_mustHitSection.checked = sec.mustHitSection; - check_altAnim.checked = sec.altAnim; - check_changeBPM.checked = sec.changeBPM; - stepperSectionBPM.value = sec.bpm; + if (sec == null) + { + check_mustHitSection.checked = true; + check_altAnim.checked = false; + } + else + { + check_mustHitSection.checked = sec.mustHitSection; + check_altAnim.checked = sec.altAnim; + check_changeBPM.checked = sec.changeBPM; + } } function updateHeads():Void { if (check_mustHitSection.checked) { - leftIcon.animation.play(_song.player1); - rightIcon.animation.play(_song.player2); + leftIcon.changeIcon(_song.player1); + rightIcon.changeIcon(_song.player2); } else { - leftIcon.animation.play(_song.player2); - rightIcon.animation.play(_song.player1); + leftIcon.changeIcon(_song.player2); + rightIcon.changeIcon(_song.player1); } } @@ -1184,14 +2156,6 @@ class ChartingState extends MusicBeatState 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); @@ -1202,23 +2166,6 @@ class ChartingState extends MusicBeatState 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) { @@ -1233,37 +2180,69 @@ class ChartingState extends MusicBeatState } */ - for (i in sectionInfo) + var currentSection = 0; + + for (section in _song.notes) { - var daNoteInfo = i[1]; - var daStrumTime = i[0]; - var daSus = i[2]; - - var note:Note = new Note(daStrumTime, daNoteInfo % 4); - 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) + for (i in section.sectionNotes) { - 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); + var seg = TimingStruct.getTimingAtTimestamp(i[0]); + var daNoteInfo = i[1]; + var daStrumTime = i[0]; + var daSus = i[2]; + + var note:Note = new Note(daStrumTime, daNoteInfo % 4,null,false,true); + note.rawNoteData = daNoteInfo; + note.sustainLength = daSus; + note.setGraphicSize(Math.floor(GRID_SIZE), Math.floor(GRID_SIZE)); + note.updateHitbox(); + note.x = Math.floor(daNoteInfo * GRID_SIZE); + + note.y = Math.floor(getYfromStrum(daStrumTime) * zoomFactor); + + if (curSelectedNote != null) + if (curSelectedNote[0] == note.strumTime) + lastNote = note; + + curRenderedNotes.add(note); + + var stepCrochet = (((60 / seg.bpm) * 1000) / 4); + + if (daSus > 0) + { + var sustainVis:FlxSprite = new FlxSprite(note.x + (GRID_SIZE / 2), + note.y + GRID_SIZE).makeGraphic(8, Math.floor((getYfromStrum(note.strumTime + note.sustainLength) * zoomFactor) - note.y)); + + note.noteCharterObject = sustainVis; + + curRenderedSustains.add(sustainVis); + } } + currentSection++; } + } private function addSection(lengthInSteps:Int = 16):Void { + var daPos:Float = 0; + var start:Float = 0; + + var bpm = _song.bpm; + for (i in 0...curSection) + { + for(ii in TimingStruct.AllTimings) + { + var data = TimingStruct.getTimingAtTimestamp(start); + if ((data != null ? data.bpm : _song.bpm) != bpm && bpm != ii.bpm) + bpm = ii.bpm; + } + start += (4 * (60 / bpm)) * 1000; + } + var sec:SwagSection = { + startTime: daPos, + endTime: Math.POSITIVE_INFINITY, lengthInSteps: lengthInSteps, bpm: _song.bpm, changeBPM: false, @@ -1280,11 +2259,11 @@ class ChartingState extends MusicBeatState { var swagNum:Int = 0; - for (i in _song.notes[curSection].sectionNotes) + for (i in getSectionByTime(note.strumTime).sectionNotes) { - if (i.strumTime == note.strumTime && i.noteData % 4 == note.noteData) + if (i[0] == note.strumTime && i[1] == note.rawNoteData) { - curSelectedNote = _song.notes[curSection].sectionNotes[swagNum]; + curSelectedNote = getSectionByTime(note.strumTime).sectionNotes[swagNum]; } swagNum += 1; @@ -1298,20 +2277,40 @@ class ChartingState extends MusicBeatState function deleteNote(note:Note):Void { lastNote = note; - for (i in _song.notes[curSection].sectionNotes) + + var section = getSectionByTime(note.strumTime); + + trace(section); + + var found = false; + + for (i in section.sectionNotes) { - if (i[0] == note.strumTime && i[1] % 4 == note.noteData) + if (i[0] == note.strumTime && i[1] == note.rawNoteData) { - _song.notes[curSection].sectionNotes.remove(i); + section.sectionNotes.remove(i); + found = true; + } + } + + if (!found) // backup check + { + for(i in _song.notes) + { + for (n in i.sectionNotes) + if (n[0] == note.strumTime && n[1] == note.rawNoteData) + i.sectionNotes.remove(n); } } + trace("DELETED!"); + updateGrid(); } function clearSection():Void { - _song.notes[curSection].sectionNotes = []; + getSectionByTime(Conductor.songPosition).sectionNotes = []; updateGrid(); } @@ -1328,7 +2327,26 @@ class ChartingState extends MusicBeatState private function newSection(lengthInSteps:Int = 16,mustHitSection:Bool = false,altAnim:Bool = true):SwagSection { + + var daPos:Float = 0; + + var currentSeg = TimingStruct.AllTimings[TimingStruct.AllTimings.length - 1]; + + var currentBeat = 4; + + for(i in _song.notes) + currentBeat += 4; + + if (currentSeg == null) + return null; + + var start:Float = (currentBeat - currentSeg.startBeat) / (currentSeg.bpm / 60); + + daPos = (currentSeg.startTime + start) * 1000; + var sec:SwagSection = { + startTime: daPos, + endTime: Math.POSITIVE_INFINITY, lengthInSteps: lengthInSteps, bpm: _song.bpm, changeBPM: false, @@ -1338,15 +2356,67 @@ class ChartingState extends MusicBeatState altAnim: altAnim }; + return sec; } + function recalculateAllSectionTimes() + { + + /*if (TimingStruct.AllTimings.length > 0) + { + trace("Song length in MS: " + FlxG.sound.music.length); + + for(i in 0...9000000) // REALLY HIGH BEATS just cuz like ig this is the upper limit, I mean ur chart is probably going to run like ass anyways + { + var seg = TimingStruct.getTimingAtBeat(i); + + var time = (i / (seg.bpm / 60)) * 1000; + + if (time > FlxG.sound.music.length) + break; + + lengthInBeats = i; + } + + lengthInSteps = lengthInBeats * 4; + + trace('LENGTH IN STEPS ' + lengthInSteps + ' | LENGTH IN BEATS ' + lengthInBeats); + }*/ + + trace("RECALCULATING SECTION TIMES"); + for (i in 0..._song.notes.length) // loops through sections + { + var section = _song.notes[i]; + + var currentBeat = 4 * i; + + var currentSeg = TimingStruct.getTimingAtBeat(currentBeat); + + if (currentSeg == null) + return; + + var start:Float = (currentBeat - currentSeg.startBeat) / (currentSeg.bpm / 60); + + section.startTime = (currentSeg.startTime + start) * 1000; + + if (i != 0) + _song.notes[i - 1].endTime = section.startTime; + section.endTime = Math.POSITIVE_INFINITY; + + } + once = true; + } + + var once = false; + + 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)); + var millisecadd = (((measure*4)+step/4)*(60000/currentBPM))+ms; + var totaladdsection = Std.int((millisecadd/(60000/currentBPM)/4)); trace(millisecadd,totaladdsection); if(millisecadd > 0) { @@ -1374,7 +2444,7 @@ class ChartingState extends MusicBeatState { newtiming = 0; } - var futureSection = Math.floor(newtiming/4/(60000/_song.bpm)); + var futureSection = Math.floor(newtiming/4/(60000/currentBPM)); _song.notes[daSection].sectionNotes[daNote][0] = newtiming; newSong[futureSection].sectionNotes.push(_song.notes[daSection].sectionNotes[daNote]); @@ -1384,22 +2454,68 @@ class ChartingState extends MusicBeatState } //trace("DONE BITCH"); _song.notes = newSong; + recalculateAllSectionTimes(); updateGrid(); updateSectionUI(); updateNoteUI(); } + + public function getSectionByTime(ms:Float, ?changeCurSectionIndex:Bool = false):SwagSection + { + var index = 0; + + + + for (i in _song.notes) + { + if (ms >= i.startTime && ms < i.endTime) + { + if (changeCurSectionIndex) + curSection = index; + return i; + } + index++; + } + + + return null; + } + + public function getNoteByTime(ms:Float) + { + for(i in _song.notes) + { + for(n in i.sectionNotes) + if (n[0] == ms) + return i; + } + return null; + } + + private function addNote(?n:Note):Void { - var noteStrum = getStrumTime(dummyArrow.y) + sectionStartTime(); + var strum = getStrumTime(dummyArrow.y) / zoomFactor; + + trace(strum + " from " + dummyArrow.y); + + trace("adding note with " + strum + " from dummyArrow"); + + var section = getSectionByTime(strum); + + if (section == null) + return; + + var noteStrum = strum; 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]); + section.sectionNotes.push([n.strumTime, n.noteData, n.sustainLength]); else - _song.notes[curSection].sectionNotes.push([noteStrum, noteData, noteSus]); + section.sectionNotes.push([noteStrum, noteData, noteSus]); - var thingy = _song.notes[curSection].sectionNotes[_song.notes[curSection].sectionNotes.length - 1]; + var thingy = section.sectionNotes[section.sectionNotes.length - 1]; curSelectedNote = thingy; @@ -1411,12 +2527,12 @@ class ChartingState extends MusicBeatState function getStrumTime(yPos:Float):Float { - return FlxMath.remapToRange(yPos, gridBG.y, gridBG.y + gridBG.height, 0, 16 * Conductor.stepCrochet); + return FlxMath.remapToRange(yPos, 0, lengthInSteps, 0, lengthInSteps); } function getYfromStrum(strumTime:Float):Float { - return FlxMath.remapToRange(strumTime, 0, 16 * Conductor.stepCrochet, gridBG.y, gridBG.y + gridBG.height); + return FlxMath.remapToRange(strumTime, 0, lengthInSteps, 0, lengthInSteps); } /* @@ -1463,7 +2579,12 @@ class ChartingState extends MusicBeatState function loadJson(song:String):Void { - PlayState.SONG = Song.loadFromJson(song.toLowerCase(), song.toLowerCase()); + var format = StringTools.replace(PlayState.SONG.song.toLowerCase(), " ", "-"); + switch (format) { + case 'Dad-Battle': format = 'Dadbattle'; + case 'Philly-Nice': format = 'Philly'; + } + PlayState.SONG = Song.loadFromJson(format, format); LoadingState.loadAndSwitchState(new ChartingState()); } @@ -1487,7 +2608,7 @@ class ChartingState extends MusicBeatState "song": _song }; - var data:String = Json.stringify(json); + var data:String = Json.stringify(json,null," "); if ((data != null) && (data.length > 0)) { @@ -1510,7 +2631,7 @@ class ChartingState extends MusicBeatState /** * Called when the save file dialog is cancelled. - */ + */ function onSaveCancel(_):Void { _file.removeEventListener(Event.COMPLETE, onSaveComplete); diff --git a/source/Conductor.hx b/source/Conductor.hx index 03847d1..f5c40c1 100644 --- a/source/Conductor.hx +++ b/source/Conductor.hx @@ -68,7 +68,23 @@ class Conductor trace("new BPM map BUDDY " + bpmChangeMap); } - public static function changeBPM(newBpm:Float) + public static function recalculateTimingStruct(SONG:Song) + { + for(i in SONG.eventObjects) + { + /*TimingStruct.addTiming(beat,bpm,endBeat, Std.parseFloat(OFFSET)); + + if (changeEvents.length != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + }*/ + } + } + + public static function changeBPM(newBpm:Float, ?recalcLength = true) { bpm = newBpm; diff --git a/source/Controls.hx b/source/Controls.hx index ac44eed..0219115 100644 --- a/source/Controls.hx +++ b/source/Controls.hx @@ -1,5 +1,6 @@ package; +import flixel.input.gamepad.FlxGamepad; import flixel.FlxG; import flixel.input.FlxInput; import flixel.input.actions.FlxAction; @@ -571,15 +572,29 @@ class Controls extends FlxActionSet //trace(FlxKey.fromString(FlxG.save.data.upBind)); removeKeyboard(); + if (gamepadsAdded.length != 0) + removeGamepad(); KeyBinds.keyCheck(); - + + var buttons = new Map>(); + + buttons.set(Control.UP,[FlxGamepadInputID.fromString(FlxG.save.data.gpupBind)]); + buttons.set(Control.LEFT,[FlxGamepadInputID.fromString(FlxG.save.data.gpleftBind)]); + buttons.set(Control.DOWN,[FlxGamepadInputID.fromString(FlxG.save.data.gpdownBind)]); + buttons.set(Control.RIGHT,[FlxGamepadInputID.fromString(FlxG.save.data.gprightBind)]); + buttons.set(Control.ACCEPT,[FlxGamepadInputID.A]); + buttons.set(Control.BACK,[FlxGamepadInputID.B]); + buttons.set(Control.PAUSE,[FlxGamepadInputID.START]); + + addGamepad(0,buttons); + 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.PAUSE, [ENTER, ESCAPE]); inline bindKeys(Control.RESET, [FlxKey.fromString(FlxG.save.data.killBind)]); } @@ -599,6 +614,9 @@ class Controls extends FlxActionSet public function addGamepad(id:Int, ?buttonMap:Map>):Void { + if (gamepadsAdded.contains(id)) + gamepadsAdded.remove(id); + gamepadsAdded.push(id); #if (haxe >= "4.0.0") diff --git a/source/CoolUtil.hx b/source/CoolUtil.hx index 92cc2c0..24dc749 100644 --- a/source/CoolUtil.hx +++ b/source/CoolUtil.hx @@ -6,11 +6,11 @@ using StringTools; class CoolUtil { - public static var difficultyArray:Array = ['EASY', "NORMAL", "HARD"]; + public static var difficultyArray:Array = ['Easy', "Normal", "Hard"]; - public static function difficultyString():String + public static function difficultyFromInt(difficulty:Int):String { - return difficultyArray[PlayState.storyDifficulty]; + return difficultyArray[difficulty]; } public static function coolTextFile(path:String):Array diff --git a/source/DialogueBox.hx b/source/DialogueBox.hx index 929eb24..07363c6 100644 --- a/source/DialogueBox.hx +++ b/source/DialogueBox.hx @@ -155,7 +155,7 @@ class DialogueBox extends FlxSpriteGroup portraitLeft.visible = false; if (PlayState.SONG.song.toLowerCase() == 'thorns') { - portraitLeft.color = FlxColor.BLACK; + portraitLeft.visible = false; swagDialogue.color = FlxColor.WHITE; dropText.color = FlxColor.BLACK; } @@ -177,7 +177,7 @@ class DialogueBox extends FlxSpriteGroup dialogueStarted = true; } - if (FlxG.keys.justPressed.ANY && dialogueStarted == true) + if (PlayerSettings.player1.controls.ACCEPT && dialogueStarted == true) { remove(dialogue); diff --git a/source/DiffCalc.hx b/source/DiffCalc.hx new file mode 100644 index 0000000..5022cb8 --- /dev/null +++ b/source/DiffCalc.hx @@ -0,0 +1,372 @@ +import openfl.system.System; +import flixel.math.FlxMath; +import Song.SwagSong; + +class SmallNote // basically Note.hx but small as fuck +{ + public var strumTime:Float; + public var noteData:Int; + + public function new(strum,data) + { + strumTime = strum; + noteData = data; + } +} + +class DiffCalc +{ + public static var scale = 3 * 1.8; + + public static var lastDiffHandOne:Array = []; + public static var lastDiffHandTwo:Array = []; + + public static function CalculateDiff(song:SwagSong, ?accuracy:Float = .93) + { + trace('calcuilafjwaf'); + // cleaned notes + var cleanedNotes:Array = []; + + if (song.notes == null) + return 0.0; + + if (song.notes.length == 0) + return 0.0; + + // find all of the notes + for(i in song.notes) // sections + { + for (ii in i.sectionNotes) // notes + { + if (ii[1] > 3 && !i.mustHitSection) + cleanedNotes.push(new SmallNote(ii[0],Math.floor(Math.abs(ii[1])))); + else if (ii[1] < 4 && i.mustHitSection) + cleanedNotes.push(new SmallNote(ii[0],Math.floor(Math.abs(ii[1])))); + } + } + + trace(cleanedNotes.length + " - playable notes"); + + var handOne:Array = []; + var handTwo:Array = []; + + cleanedNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime)); + + + + var firstNoteTime = cleanedNotes[0].strumTime; + + // normalize the notes + + for(i in cleanedNotes) + { + i.strumTime = (i.strumTime - firstNoteTime) * 2; + } + + for (i in cleanedNotes) + { + switch(i.noteData) + { + case 0: + handOne.push(i); + case 1: + handOne.push(i); + case 2: + handTwo.push(i); + case 3: + handTwo.push(i); + } + } + + // collect all of the notes in each col + + var leftHandCol:Array = []; // d 0 + var leftMHandCol:Array = []; // f 1 + var rightMHandCol:Array = []; // j 2 + var rightHandCol:Array = []; // k 3 + + for(i in 0...handOne.length - 1) + { + if (handOne[i].noteData == 0) + leftHandCol.push(handOne[i].strumTime); + else + leftMHandCol.push(handOne[i].strumTime); + } + for(i in 0...handTwo.length - 1) + { + if (handTwo[i].noteData == 3) + rightHandCol.push(handTwo[i].strumTime); + else + rightMHandCol.push(handTwo[i].strumTime); + } + + + // length in segments of the song + var length = ((cleanedNotes[cleanedNotes.length - 1].strumTime / 1000) / 0.5); + + // hackey way of creating a array with a length + var segmentsOne = new haxe.ds.Vector(Math.floor(length)); + + var segmentsTwo = new haxe.ds.Vector(Math.floor(length)); + + // set em all to array's (so no null's) + + for(i in 0...segmentsOne.length) + segmentsOne[i] = new Array(); + for(i in 0...segmentsTwo.length) + segmentsTwo[i] = new Array(); + + // algo loop + for(i in handOne) + { + var index = Std.int((((i.strumTime * 2) / 1000))); + if (index + 1 > length) + continue; + segmentsOne[index].push(i); + } + + for(i in handTwo) + { + var index = Std.int((((i.strumTime * 2) / 1000))); + if (index + 1 > length) + continue; + segmentsTwo[index].push(i); + } + + // Remove 0 intervals + /*for(i in 0...segmentsOne.length) + { + if (segmentsOne[i].length == 0) + segmentsOne[i] = null; + } + + for(i in 0...segmentsTwo.length) + { + if (segmentsTwo[i].length == 0) + segmentsTwo[i] = null; + }*/ + + // get nps for both hands + + var hand_npsOne:Array = new Array(); + var hand_npsTwo:Array = new Array(); + + for(i in segmentsOne) + { + if (i == null) + continue; + hand_npsOne.push(i.length * scale * 1.6); + } + for(i in segmentsTwo) + { + if (i == null) + continue; + hand_npsTwo.push(i.length * scale * 1.6); + } + + // get the diff vector's for all of the hands + + var hand_diffOne:Array = new Array(); + var hand_diffTwo:Array = new Array(); + + for(i in 0...segmentsOne.length) + { + var ve = segmentsOne[i]; + if (ve == null) + continue; + var fuckYouOne:Array = []; + var fuckYouTwo:Array = []; + for(note in ve) + { + switch(note.noteData) + { + case 0: // fingie 1 + fuckYouOne.push(note); + case 1: // fingie 2 + fuckYouTwo.push(note); + } + } + + var one = fingieCalc(fuckYouOne,leftHandCol); + var two = fingieCalc(fuckYouTwo,leftMHandCol); + + + var bigFuck = ((((one > two ? one : two) * 8) + (hand_npsOne[i] / scale) * 5) / 13) * scale; + + //trace(bigFuck + " - hand one [" + i + "]"); + + + hand_diffOne.push(bigFuck); + } + + for(i in 0...segmentsTwo.length) + { + var ve = segmentsTwo[i]; + if (ve == null) + continue; + var fuckYouOne:Array = []; + var fuckYouTwo:Array = []; + for(note in ve) + { + switch(note.noteData) + { + case 2: // fingie 1 + fuckYouOne.push(note); + case 3: // fingie 2 + fuckYouTwo.push(note); + } + } + + var one = fingieCalc(fuckYouOne,rightMHandCol); + var two = fingieCalc(fuckYouTwo,rightHandCol); + + var bigFuck = ((((one > two ? one : two) * 8) + (hand_npsTwo[i] / scale) * 5) / 13) * scale; + + hand_diffTwo.push(bigFuck); + + // trace(bigFuck + " - hand two [" + i + "]"); + } + + for (i in 0...4) + { + smoothBrain(hand_npsOne,0); + smoothBrain(hand_npsTwo,0); + + smoothBrainTwo(hand_diffOne); + smoothBrainTwo(hand_diffTwo); + } + + //trace(hand_diffOne); + //trace(hand_diffTwo); + + //trace(hand_npsOne); + //trace(hand_npsTwo); + + var point_npsOne:Array = new Array(); + var point_npsTwo:Array = new Array(); + + for(i in segmentsOne) + { + if (i == null) + continue; + point_npsOne.push(i.length); + } + for(i in segmentsTwo) + { + if (i == null) + continue; + point_npsTwo.push(i.length); + } + + var maxPoints:Float = 0; + + for(i in point_npsOne) + maxPoints += i; + for(i in point_npsTwo) + maxPoints += i; + + if (accuracy > .965) + accuracy = .965; + + lastDiffHandOne = hand_diffOne; + lastDiffHandTwo = hand_diffTwo; + + + return HelperFunctions.truncateFloat(chisel(accuracy,hand_diffOne,hand_diffTwo,point_npsOne,point_npsTwo,maxPoints),2); + } + + public static function chisel(scoreGoal:Float,diffOne:Array,diffTwo:Array,pointsOne:Array,pointsTwo:Array,maxPoints:Float) + { + var lowerBound:Float = 0; + var upperBound:Float = 100; + + while(upperBound - lowerBound > 0.01) + { + var average:Float = (upperBound + lowerBound) / 2; + var amtOfPoints:Float = calcuate(average,diffOne,pointsOne) + calcuate(average,diffTwo,pointsTwo); + if (amtOfPoints / maxPoints < scoreGoal) + lowerBound = average; + else + upperBound = average; + + } + return upperBound; + } + + public static function calcuate(midPoint:Float,diff:Array,points:Array) + { + var output:Float = 0; + + for (i in 0...diff.length) + { + var res = diff[i]; + if (midPoint > res) + output += points[i]; + else + output += points[i] * Math.pow(midPoint / res,1.2); + } + return output; + } + + public static function findStupid(strumTime:Float, array:Array) + { + for(i in 0...array.length) + if (array[i] == strumTime) + return i; + return -1; + } + + public static function fingieCalc(floats:Array, columArray:Array):Float + { + var sum:Float = 0; + if (floats.length == 0) + return 0; + var startIndex = findStupid(floats[0].strumTime,columArray); + if (startIndex == -1) + return 0; + for(i in floats) + { + sum += columArray[startIndex + 1] - columArray[startIndex]; + startIndex++; + } + + if (sum == 0) + return 0; + + return (1375 * (floats.length)) / sum; + } + + // based arrayer + // basicily smmoth the shit + public static function smoothBrain(npsVector:Array, weirdchamp:Float) + { + var floatOne = weirdchamp; + var floatTwo = weirdchamp; + + for (i in 0...npsVector.length) + { + var result = npsVector[i]; + + var chunker = floatOne; + floatOne = floatTwo; + floatTwo = result; + + npsVector[i] = (chunker + floatOne + floatTwo) / 3; + } + } + + // Smooth the shit but less + public static function smoothBrainTwo(diffVector:Array) + { + var floatZero:Float = 0; + + for(i in 0...diffVector.length) + { + var result = diffVector[i]; + + var fuck = floatZero; + floatZero = result; + diffVector[i] = (fuck + floatZero) / 2; + } + } +} \ No newline at end of file diff --git a/source/DiffOverview.hx b/source/DiffOverview.hx new file mode 100644 index 0000000..4f27fcc --- /dev/null +++ b/source/DiffOverview.hx @@ -0,0 +1,506 @@ +package; + +import Conductor.BPMChangeEvent; +import flixel.FlxCamera; +import flixel.math.FlxRect; +import Song.SwagSong; +import Section.SwagSection; +import flixel.system.FlxSound; +import flixel.input.gamepad.FlxGamepad; +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.util.FlxSort; +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 DiffOverview extends FlxSubState +{ + var blackBox:FlxSprite; + + var handOne:Array; + var handTwo:Array; + + var giantText:FlxText; + + var SONG:SwagSong; + var strumLine:FlxSprite; + var camHUD:FlxCamera; + + var offset:FlxText; + + public static var playerStrums:FlxTypedGroup = null; + + override function create() + { + Conductor.songPosition = 0; + Conductor.lastSongPos = 0; + + camHUD = new FlxCamera(); + camHUD.bgColor.alpha = 0; + var camGame = new FlxCamera(); + + FlxG.cameras.add(camGame); + + FlxG.cameras.add(camHUD); + + FlxCamera.defaultCameras = [camGame]; + + playerStrums = new FlxTypedGroup(); + + SONG = FreeplayState.songData.get(FreeplayState.songs[FreeplayState.curSelected].songName)[FreeplayState.curDifficulty]; + + strumLine = new FlxSprite(0, (FlxG.height / 2) - 295).makeGraphic(FlxG.width, 10); + strumLine.scrollFactor.set(); + + blackBox = new FlxSprite(0, 0).makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); + blackBox.alpha = 0; + add(blackBox); + + FreeplayState.openedPreview = true; + + handOne = DiffCalc.lastDiffHandOne; + handTwo = DiffCalc.lastDiffHandTwo; + 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'); + if(FlxG.save.data.antialiasing) + { + babyArrow.antialiasing = true; + } + babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7)); + + switch (Math.abs(i)) + { + 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); + 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 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); + } + + babyArrow.updateHitbox(); + babyArrow.scrollFactor.set(); + + babyArrow.y -= 10; + babyArrow.alpha = 1; + + babyArrow.ID = i; + + playerStrums.add(babyArrow); + + babyArrow.animation.play('static'); + babyArrow.x += 50; + babyArrow.x += ((FlxG.width / 2)); + } + + add(playerStrums); + + generateSong("assItch"); + + playerStrums.cameras = [camHUD]; + notes.cameras = [camHUD]; + blackBox.cameras = [camHUD]; + + blackBox.x = playerStrums.members[0].x; + blackBox.y = strumLine.y; + + camHUD.zoom = 0.6; + camHUD.alpha = 0; + camHUD.height = 5000; + blackBox.height = camHUD.height; + + camHUD.x += 280; + + blackBox.y -= 100; + blackBox.x -= 100; + + offset = new FlxText(10,FlxG.height - 40,0,"Offset: " + HelperFunctions.truncateFloat(FlxG.save.data.offset,0) + " (LEFT/RIGHT to decrease/increase)",16); + offset.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1); + offset.color = FlxColor.WHITE; + offset.scrollFactor.set(); + //add(offset); + + FlxTween.tween(blackBox, {alpha: 0.5}, 1, {ease: FlxEase.expoInOut}); + FlxTween.tween(camHUD, {alpha: 1}, 0.5, {ease: FlxEase.expoInOut}); + FlxTween.tween(offset, {alpha: 1}, 0.5, {ease: FlxEase.expoInOut}); + + trace('pog'); + + super.create(); + } + + function endSong() + { + if (stopDoingShit) + return; + } + + function resyncVocals():Void + { + vocals.pause(); + + FlxG.sound.music.play(); + Conductor.songPosition = FlxG.sound.music.time; + vocals.time = Conductor.songPosition; + vocals.play(); + } + + public var stopDoingShit = false; + + public var currentStep = 0; + public var oldStep = 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]; + } + + currentStep = lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet); + } + + function stepHit() + { + if (FlxG.sound.music.time > Conductor.songPosition + 20 || FlxG.sound.music.time < Conductor.songPosition - 20) + { + trace("resync"); + resyncVocals(); + } + oldStep = currentStep; + } + + function offsetChange() + { + for (i in unspawnNotes) + i.strumTime = i.baseStrum + FlxG.save.data.offset; + for (i in notes) + i.strumTime = i.baseStrum + FlxG.save.data.offset; + } + + var frames = 0; + + override function update(elapsed:Float) + { + super.update(elapsed); + + + // input + + if (frames < 10) + { + frames++; + return; + } + + if (stopDoingShit) + return; + + updateCurStep(); + + if (oldStep != currentStep && currentStep > 0) + stepHit(); + + if (FlxG.keys.pressed.SPACE) + { + stopDoingShit = true; + quit(); + } + + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + if (gamepad != null) + if (gamepad.justPressed.X) + { + stopDoingShit = true; + quit(); + } + + /*if (FlxG.keys.pressed.RIGHT) + { + if (FlxG.keys.pressed.SHIFT) + { + FlxG.save.data.offset++; + offsetChange(); + } + } + if (FlxG.keys.pressed.LEFT) + { + if (FlxG.keys.pressed.SHIFT) + { + FlxG.save.data.offset--; + offsetChange(); + } + } + + if (FlxG.keys.justPressed.RIGHT) + { + FlxG.save.data.offset++; + offsetChange(); + } + if (FlxG.keys.justPressed.LEFT) + { + FlxG.save.data.offset--; + offsetChange(); + } + + + offset.text = "Offset: " + HelperFunctions.truncateFloat(FlxG.save.data.offset,0) + " (LEFT/RIGHT to decrease/increase, SHIFT to go faster) - Time: " + HelperFunctions.truncateFloat(Conductor.songPosition / 1000,0) + "s - Step: " + currentStep; + */ + + if (vocals != null) + if (vocals.playing) + Conductor.songPosition += FlxG.elapsed * 1000; + + 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); + } + } + + + + 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; + } + + daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y + - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(SONG.speed, + 2)); + + if (daNote.isSustainNote) + { + daNote.y -= daNote.height / 2; + + 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 = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y; + swagRect.height -= swagRect.y; + + daNote.clipRect = swagRect; + } + } + + 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; + + // auto hit + + if(daNote.y < strumLine.y) + { + // Force good note hit regardless if it's too late to hit it or not as a fail safe + if(daNote.canBeHit && daNote.mustPress || daNote.tooLate && daNote.mustPress) + { + + daNote.wasGoodHit = true; + vocals.volume = 1; + + daNote.kill(); + notes.remove(daNote, true); + daNote.destroy(); + } + } + }); + + } + + function quit() + { + FlxTween.tween(blackBox, {alpha: 0}, 1, {ease: FlxEase.expoInOut}); + FlxTween.tween(camHUD, {alpha: 0}, 1, {ease: FlxEase.expoInOut}); + FlxTween.tween(offset, {alpha: 0}, 1, {ease: FlxEase.expoInOut}); + + vocals.fadeOut(); + + FreeplayState.openedPreview = false; + } + + var vocals:FlxSound; + + var notes:FlxTypedGroup; + var unspawnNotes:Array = []; + + public function generateSong(dataPath:String):Void + { + // FlxG.log.add(ChartParser.parse()); + + var songData = FreeplayState.songData.get(FreeplayState.songs[FreeplayState.curSelected].songName)[FreeplayState.curDifficulty]; + Conductor.changeBPM(songData.bpm); + + if (SONG.needsVoices) + vocals = new FlxSound().loadEmbedded(Paths.voices(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; + + 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; + 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,false, true); + + + if (!gottaHitNote) + continue; + + swagNote.baseStrum = Math.round(songNotes[0]); + + 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, 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); + + Conductor.mapBPMChanges(SONG); + Conductor.changeBPM(SONG.bpm); + + FlxG.sound.playMusic(Paths.inst(SONG.song), 1, false); + FlxG.sound.music.onComplete = endSong; + vocals.play(); + } + + function sortByShit(Obj1:Note, Obj2:Note):Int + { + return FlxSort.byValues(FlxSort.ASCENDING, Obj1.strumTime, Obj2.strumTime); + } +} diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index 91ca64a..96d0c30 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -1,5 +1,15 @@ package; - +import lime.app.Application; +import openfl.utils.Future; +import openfl.media.Sound; +import flixel.system.FlxSound; +#if sys +import smTools.SMFile; +import sys.FileSystem; +import sys.io.File; +#end +import Song.SwagSong; +import flixel.input.gamepad.FlxGamepad; import flash.text.TextField; import flixel.FlxG; import flixel.FlxSprite; @@ -19,15 +29,17 @@ using StringTools; class FreeplayState extends MusicBeatState { - var songs:Array = []; + public static var songs:Array = []; var selector:FlxText; - var curSelected:Int = 0; - var curDifficulty:Int = 1; + public static var curSelected:Int = 0; + public static var curDifficulty:Int = 1; var scoreText:FlxText; var comboText:FlxText; var diffText:FlxText; + var diffCalcText:FlxText; + var previewtext:FlxText; var lerpScore:Int = 0; var intendedScore:Int = 0; var combo:String = ''; @@ -37,16 +49,110 @@ class FreeplayState extends MusicBeatState private var iconArray:Array = []; + public static var openedPreview = false; + + public static var songData:Map> = []; + + public static function loadDiff(diff:Int, format:String, name:String, array:Array) + { + try + { + array.push(Song.loadFromJson(Highscore.formatSong(format, diff), name)); + } + catch(ex) + { + // do nada + } + } + override function create() { - var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist')); + var initSonglist = CoolUtil.coolTextFile(Paths.txt('data/freeplaySonglist')); + + //var diffList = ""; + + songData = []; + songs = []; for (i in 0...initSonglist.length) { var data:Array = initSonglist[i].split(':'); - songs.push(new SongMetadata(data[0], Std.parseInt(data[2]), data[1])); + var meta = new SongMetadata(data[0], Std.parseInt(data[2]), data[1]); + var format = StringTools.replace(meta.songName, " ", "-"); + switch (format) { + case 'Dad-Battle': format = 'Dadbattle'; + case 'Philly-Nice': format = 'Philly'; + } + + var diffs = []; + var diffsThatExist = []; + + + #if sys + if (FileSystem.exists('assets/data/${format}/${format}-hard.json')) + diffsThatExist.push("Hard"); + if (FileSystem.exists('assets/data/${format}/${format}-easy.json')) + diffsThatExist.push("Easy"); + if (FileSystem.exists('assets/data/${format}/${format}.json')) + diffsThatExist.push("Normal"); + + if (diffsThatExist.length == 0) + { + Application.current.window.alert("No difficulties found for chart, skipping.",meta.songName + " Chart"); + continue; + } + #else + diffsThatExist = ["Easy","Normal","Hard"]; + #end + if (diffsThatExist.contains("Easy")) + FreeplayState.loadDiff(0,format,meta.songName,diffs); + if (diffsThatExist.contains("Normal")) + FreeplayState.loadDiff(1,format,meta.songName,diffs); + if (diffsThatExist.contains("Hard")) + FreeplayState.loadDiff(2,format,meta.songName,diffs); + + meta.diffs = diffsThatExist; + + if (diffsThatExist.length != 3) + trace("I ONLY FOUND " + diffsThatExist); + + FreeplayState.songData.set(meta.songName,diffs); + trace('loaded diffs for ' + meta.songName); + songs.push(meta); + } + trace("tryin to load sm files"); + + #if sys + for(i in FileSystem.readDirectory("assets/sm/")) + { + trace(i); + if (FileSystem.isDirectory("assets/sm/" + i)) + { + trace("Reading SM file dir " + i); + for (file in FileSystem.readDirectory("assets/sm/" + i)) + { + if (file.contains(" ")) + FileSystem.rename("assets/sm/" + i + "/" + file,"assets/sm/" + i + "/" + file.replace(" ","_")); + if (file.endsWith(".sm")) + { + trace("reading " + file); + var file:SMFile = SMFile.loadFile("assets/sm/" + i + "/" + file.replace(" ","_")); + trace("Converting " + file.header.TITLE); + var data = file.convertToFNF("assets/sm/" + i + "/converted.json"); + var meta = new SongMetadata(file.header.TITLE, 0, "sm",file,"assets/sm/" + i); + songs.push(meta); + var song = Song.loadFromJsonRAW(data); + songData.set(file.header.TITLE, [song,song,song]); + } + } + } + } + #end + + //trace("\n" + diffList); + /* if (FlxG.sound.music != null) { @@ -66,11 +172,17 @@ class FreeplayState extends MusicBeatState isDebug = true; #end + persistentUpdate = true; + // LOAD MUSIC // LOAD CHARACTERS var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuBGBlue')); + if(FlxG.save.data.antialiasing) + { + bg.antialiasing = true; + } add(bg); grpSongs = new FlxTypedGroup(); @@ -100,7 +212,7 @@ class FreeplayState extends MusicBeatState 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); + var scoreBG:FlxSprite = new FlxSprite(scoreText.x - 6, 0).makeGraphic(Std.int(FlxG.width * 0.35), 105, 0xFF000000); scoreBG.alpha = 0.6; add(scoreBG); @@ -108,6 +220,14 @@ class FreeplayState extends MusicBeatState diffText.font = scoreText.font; add(diffText); + diffCalcText = new FlxText(scoreText.x, scoreText.y + 66, 0, "", 24); + diffCalcText.font = scoreText.font; + add(diffCalcText); + + previewtext = new FlxText(scoreText.x, scoreText.y + 94, 0, "" + (KeyBinds.gamepad ? "X" : "SPACE") + " to preview", 24); + previewtext.font = scoreText.font; + //add(previewtext); + comboText = new FlxText(diffText.x + 100, diffText.y, 0, "", 24); comboText.font = diffText.font; add(comboText); @@ -166,7 +286,7 @@ class FreeplayState extends MusicBeatState num++; } } - + override function update(elapsed:Float) { super.update(elapsed); @@ -184,9 +304,40 @@ class FreeplayState extends MusicBeatState scoreText.text = "PERSONAL BEST:" + lerpScore; comboText.text = combo + '\n'; - var upP = controls.UP_P; - var downP = controls.DOWN_P; - var accepted = controls.ACCEPT; + if (FlxG.sound.music.volume > 0.8) + { + FlxG.sound.music.volume -= 0.5 * FlxG.elapsed; + } + + var upP = FlxG.keys.justPressed.UP; + var downP = FlxG.keys.justPressed.DOWN; + var accepted = FlxG.keys.justPressed.ENTER; + + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + if (gamepad != null) + { + + if (gamepad.justPressed.DPAD_UP) + { + changeSelection(-1); + } + if (gamepad.justPressed.DPAD_DOWN) + { + changeSelection(1); + } + if (gamepad.justPressed.DPAD_LEFT) + { + changeDiff(-1); + } + if (gamepad.justPressed.DPAD_RIGHT) + { + changeDiff(1); + } + + //if (gamepad.justPressed.X && !openedPreview) + //openSubState(new DiffOverview()); + } if (upP) { @@ -197,9 +348,12 @@ class FreeplayState extends MusicBeatState changeSelection(1); } - if (controls.LEFT_P) + //if (FlxG.keys.justPressed.SPACE && !openedPreview) + //openSubState(new DiffOverview()); + + if (FlxG.keys.justPressed.LEFT) changeDiff(-1); - if (controls.RIGHT_P) + if (FlxG.keys.justPressed.RIGHT) changeDiff(1); if (controls.BACK) @@ -215,24 +369,45 @@ class FreeplayState extends MusicBeatState case 'Dad-Battle': songFormat = 'Dadbattle'; case 'Philly-Nice': songFormat = 'Philly'; } - - trace(songs[curSelected].songName); + var hmm; + try + { + hmm = songData.get(songs[curSelected].songName)[curDifficulty]; + if (hmm == null) + return; + } + catch(ex) + { + return; + } - var poop:String = Highscore.formatSong(songFormat, curDifficulty); - trace(poop); - - PlayState.SONG = Song.loadFromJson(poop, songs[curSelected].songName); + PlayState.SONG = hmm; PlayState.isStoryMode = false; PlayState.storyDifficulty = curDifficulty; PlayState.storyWeek = songs[curSelected].week; trace('CUR WEEK' + PlayState.storyWeek); + #if sys + if (songs[curSelected].songCharacter == "sm") + { + PlayState.isSM = true; + PlayState.sm = songs[curSelected].sm; + PlayState.pathToSm = songs[curSelected].path; + } + else + PlayState.isSM = false; + #else + PlayState.isSM = false; + #end LoadingState.loadAndSwitchState(new PlayState()); } } function changeDiff(change:Int = 0) { + if (!songs[curSelected].diffs.contains(CoolUtil.difficultyFromInt(curDifficulty + change))) + return; + curDifficulty += change; if (curDifficulty < 0) @@ -240,6 +415,7 @@ class FreeplayState extends MusicBeatState if (curDifficulty > 2) curDifficulty = 0; + // adjusting the highscore song name to be compatible (changeDiff) var songHighscore = StringTools.replace(songs[curSelected].songName, " ", "-"); switch (songHighscore) { @@ -251,16 +427,8 @@ class FreeplayState extends MusicBeatState intendedScore = Highscore.getScore(songHighscore, curDifficulty); combo = Highscore.getCombo(songHighscore, curDifficulty); #end - - switch (curDifficulty) - { - case 0: - diffText.text = "EASY"; - case 1: - diffText.text = 'NORMAL'; - case 2: - diffText.text = "HARD"; - } + diffCalcText.text = 'RATING: ${DiffCalc.CalculateDiff(songData.get(songs[curSelected].songName)[curDifficulty])}'; + diffText.text = CoolUtil.difficultyFromInt(curDifficulty).toUpperCase(); } function changeSelection(change:Int = 0) @@ -272,6 +440,8 @@ class FreeplayState extends MusicBeatState // NGio.logEvent('Fresh'); FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); + + curSelected += change; if (curSelected < 0) @@ -279,6 +449,19 @@ class FreeplayState extends MusicBeatState if (curSelected >= songs.length) curSelected = 0; + if (songs[curSelected].diffs.length != 3) + { + switch(songs[curSelected].diffs[0]) + { + case "Easy": + curDifficulty = 0; + case "Normal": + curDifficulty = 1; + case "Hard": + curDifficulty = 2; + } + } + // selector.y = (70 * curSelected) + 30; // adjusting the highscore song name to be compatible (changeSelection) @@ -295,10 +478,38 @@ class FreeplayState extends MusicBeatState // lerpScore = 0; #end + diffCalcText.text = 'RATING: ${DiffCalc.CalculateDiff(songData.get(songs[curSelected].songName)[curDifficulty])}'; + #if PRELOAD_ALL - FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0); + if (songs[curSelected].songCharacter == "sm") + { + var data = songs[curSelected]; + trace("Loading " + data.path + "/" + data.sm.header.MUSIC); + var bytes = File.getBytes(data.path + "/" + data.sm.header.MUSIC); + var sound = new Sound(); + sound.loadCompressedDataFromByteArray(bytes.getData(), bytes.length); + FlxG.sound.playMusic(sound); + } + else + FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0); #end + var hmm; + try + { + hmm = songData.get(songs[curSelected].songName)[curDifficulty]; + if (hmm != null) + Conductor.changeBPM(hmm.bpm); + } + catch(ex) + {} + + if (openedPreview) + { + closeSubState(); + openSubState(new DiffOverview()); + } + var bullShit:Int = 0; for (i in 0...iconArray.length) @@ -329,12 +540,29 @@ class SongMetadata { public var songName:String = ""; public var week:Int = 0; + #if sys + public var sm:SMFile; + public var path:String; + #end public var songCharacter:String = ""; + public var diffs = []; + + #if sys + public function new(song:String, week:Int, songCharacter:String, ?sm:SMFile = null, ?path:String = "") + { + this.songName = song; + this.week = week; + this.songCharacter = songCharacter; + this.sm = sm; + this.path = path; + } + #else public function new(song:String, week:Int, songCharacter:String) { this.songName = song; this.week = week; this.songCharacter = songCharacter; } + #end } diff --git a/source/GameOverState.hx b/source/GameOverState.hx index c26c063..250095e 100644 --- a/source/GameOverState.hx +++ b/source/GameOverState.hx @@ -41,7 +41,10 @@ class GameOverState extends FlxTransitionableState restart.setGraphicSize(Std.int(restart.width * 0.6)); restart.updateHitbox(); restart.alpha = 0; - restart.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + restart.antialiasing = true; + } add(restart); FlxG.sound.music.fadeOut(2, FlxG.sound.music.volume * 0.6); diff --git a/source/GameOverSubstate.hx b/source/GameOverSubstate.hx index f784827..5cef652 100644 --- a/source/GameOverSubstate.hx +++ b/source/GameOverSubstate.hx @@ -48,6 +48,8 @@ class GameOverSubstate extends MusicBeatSubstate bf.playAnim('firstDeath'); } + var startVibin:Bool = false; + override function update(elapsed:Float) { super.update(elapsed); @@ -76,6 +78,7 @@ class GameOverSubstate extends MusicBeatSubstate if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.finished) { FlxG.sound.playMusic(Paths.music('gameOver' + stageSuffix)); + startVibin = true; } if (FlxG.sound.music.playing) @@ -88,6 +91,10 @@ class GameOverSubstate extends MusicBeatSubstate { super.beatHit(); + if (startVibin && !isEnding) + { + bf.playAnim('deathLoop', true); + } FlxG.log.add('beat'); } @@ -97,6 +104,7 @@ class GameOverSubstate extends MusicBeatSubstate { if (!isEnding) { + PlayState.startTime = 0; isEnding = true; bf.playAnim('deathConfirm', true); FlxG.sound.music.stop(); diff --git a/source/GameplayCustomizeState.hx b/source/GameplayCustomizeState.hx index 7bcfa31..26e29e6 100644 --- a/source/GameplayCustomizeState.hx +++ b/source/GameplayCustomizeState.hx @@ -33,6 +33,7 @@ class GameplayCustomizeState extends MusicBeatState var bf:Boyfriend; var dad:Character; + var gf:Character; var strumLine:FlxSprite; var strumLineNotes:FlxTypedGroup; @@ -42,7 +43,7 @@ class GameplayCustomizeState extends MusicBeatState public override function create() { #if windows // Updating Discord Rich Presence - DiscordClient.changePresence("Customizing Gameplay", null); + DiscordClient.changePresence("Customizing Gameplay Modules", null); #end sick = new FlxSprite().loadGraphic(Paths.image('sick','shared')); @@ -51,7 +52,7 @@ class GameplayCustomizeState extends MusicBeatState curt = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains','shared')); front = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront','shared')); - Conductor.changeBPM(102); + //Conductor.changeBPM(102); persistentUpdate = true; super.create(); @@ -74,10 +75,14 @@ class GameplayCustomizeState extends MusicBeatState bf = new Boyfriend(770, 450, 'bf'); + gf = new Character(400, 130, 'gf'); + gf.scrollFactor.set(0.95, 0.95); + var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x + 400, dad.getGraphicMidpoint().y); camFollow.setPosition(camPos.x, camPos.y); + add(gf); add(bf); add(dad); @@ -111,7 +116,7 @@ class GameplayCustomizeState extends MusicBeatState 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 = new FlxText(5, FlxG.height + 40, 0, "Click and drag around gameplay elements to customize their positions.\nPress R to reset.\nPress Escape to go back.", 12); text.scrollFactor.set(); text.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); @@ -188,8 +193,9 @@ class GameplayCustomizeState extends MusicBeatState { super.beatHit(); - bf.playAnim('idle'); - dad.dance(); + bf.playAnim('idle', true); + dad.dance(true); + gf.dance(); FlxG.camera.zoom += 0.015; camHUD.zoom += 0.010; diff --git a/source/GitarooPause.hx b/source/GitarooPause.hx index cb9705c..a8c5f99 100644 --- a/source/GitarooPause.hx +++ b/source/GitarooPause.hx @@ -22,12 +22,20 @@ class GitarooPause extends MusicBeatState FlxG.sound.music.stop(); var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('pauseAlt/pauseBG')); + if(FlxG.save.data.antialiasing) + { + bg.antialiasing = true; + } 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'); + if(FlxG.save.data.antialiasing) + { + bf.antialiasing = true; + } add(bf); bf.screenCenter(X); @@ -36,6 +44,10 @@ class GitarooPause extends MusicBeatState replayButton.animation.addByPrefix('selected', 'bluereplay', 0, false); replayButton.animation.appendByPrefix('selected', 'yellowreplay'); replayButton.animation.play('selected'); + if(FlxG.save.data.antialiasing) + { + replayButton.antialiasing = true; + } add(replayButton); cancelButton = new FlxSprite(FlxG.width * 0.58, replayButton.y); @@ -43,6 +55,10 @@ class GitarooPause extends MusicBeatState cancelButton.animation.addByPrefix('selected', 'bluecancel', 0, false); cancelButton.animation.appendByPrefix('selected', 'cancelyellow'); cancelButton.animation.play('selected'); + if(FlxG.save.data.antialiasing) + { + cancelButton.antialiasing = true; + } add(cancelButton); changeThing(); diff --git a/source/HealthIcon.hx b/source/HealthIcon.hx index 74f46a1..8104468 100644 --- a/source/HealthIcon.hx +++ b/source/HealthIcon.hx @@ -1,53 +1,60 @@ package; +import flixel.FlxG; import flixel.FlxSprite; +using StringTools; + class HealthIcon extends FlxSprite { + public var char:String = 'bf'; + public var isPlayer:Bool = false; + public var isOldIcon:Bool = false; + /** * Used for FreeplayState! If you use it elsewhere, prob gonna annoying */ public var sprTracker:FlxSprite; - public function new(char:String = 'bf', isPlayer:Bool = false) + 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); + this.char = char; + this.isPlayer = isPlayer; - switch(char) + isPlayer = isOldIcon = false; + + if (FlxG.save.data.antialiasing) { - case 'bf-pixel' | 'senpai' | 'senpai-angry' | 'spirit' | 'gf-pixel': - antialiasing = false; + switch(char) + { + case 'bf-pixel' | 'senpai' | 'senpai-angry' | 'spirit' | 'gf-pixel': + antialiasing = false; + default: + antialiasing = true; + } } + changeIcon(char); scrollFactor.set(); } + public function swapOldIcon() + { + (isOldIcon = !isOldIcon) ? changeIcon("bf-old") : changeIcon(char); + } + + public function changeIcon(char:String) + { + if (char != 'bf-pixel' && char != 'bf-old') + char = char.split("-")[0]; + + loadGraphic(Paths.image('icons/icon-' + char), true, 150, 150); + animation.add(char, [0, 1], 0, false, isPlayer); + animation.play(char); + } + override function update(elapsed:Float) { super.update(elapsed); diff --git a/source/HelperFunctions.hx b/source/HelperFunctions.hx index b17dc6a..4b704c1 100644 --- a/source/HelperFunctions.hx +++ b/source/HelperFunctions.hx @@ -12,4 +12,5 @@ class HelperFunctions 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/HitGraph.hx b/source/HitGraph.hx index e3b3790..169d823 100644 --- a/source/HitGraph.hx +++ b/source/HitGraph.hx @@ -1,3 +1,4 @@ +import flixel.FlxG; import openfl.display.Bitmap; import openfl.display.BitmapData; import openfl.text.TextFieldAutoSize; @@ -29,6 +30,8 @@ class HitGraph extends Sprite 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 = []; @@ -185,14 +188,33 @@ class HitGraph extends Sprite drawJudgementLine(-166); gfx.endFill(); - - var inc:Float = _width / (PlayState.rep.replay.songNotes.length); 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]; @@ -212,21 +234,28 @@ class HitGraph extends Sprite gfx.beginFill(0xFFFFFF); } var pointY = (-value * _height - 1) + _height; + /*if (i == 0) gfx.moveTo(graphX, _axis.y + pointY);*/ - gfx.drawRect(graphX + (i * inc), pointY,4,4); + gfx.drawRect(fitX(history[i][2]), pointY,4,4); gfx.endFill(); } + var bm = new BitmapData(_width,_height); bm.draw(this); bitmap = new Bitmap(bm); } - public function addToHistory(diff:Float, judge:String) + public function fitX(x:Float) { - history.push([diff,judge]); + 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 diff --git a/source/KadeEngineData.hx b/source/KadeEngineData.hx index 0a8204d..eb0b876 100644 --- a/source/KadeEngineData.hx +++ b/source/KadeEngineData.hx @@ -1,3 +1,4 @@ +import flixel.input.gamepad.FlxGamepad; import openfl.Lib; import flixel.FlxG; @@ -5,12 +6,21 @@ class KadeEngineData { public static function initSave() { - if (FlxG.save.data.newInput == null) + if (FlxG.save.data.weekUnlocked == null) + FlxG.save.data.weekUnlocked = 7; + + 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.antialiasing == null) + FlxG.save.data.antialiasing = true; + + if (FlxG.save.data.missSounds == null) + FlxG.save.data.missSounds = true; + if (FlxG.save.data.dfjk == null) FlxG.save.data.dfjk = false; @@ -62,6 +72,9 @@ class KadeEngineData if (FlxG.save.data.distractions == null) FlxG.save.data.distractions = true; + + if (FlxG.save.data.stepMania == null) + FlxG.save.data.stepMania = false; if (FlxG.save.data.flashing == null) FlxG.save.data.flashing = true; @@ -87,6 +100,22 @@ class KadeEngineData if (FlxG.save.data.scoreScreen == null) FlxG.save.data.scoreScreen = true; + if (FlxG.save.data.inputShow == null) + FlxG.save.data.inputShow = false; + + if (FlxG.save.data.optimize == null) + FlxG.save.data.optimize = false; + + if (FlxG.save.data.cacheImages == null) + FlxG.save.data.cacheImages = false; + + if (FlxG.save.data.editor == null) + FlxG.save.data.editor = true; + + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + KeyBinds.gamepad = gamepad != null; + Conductor.recalculateTimings(); PlayerSettings.player1.controls.loadKeyBinds(); KeyBinds.keyCheck(); diff --git a/source/KeyBindMenu.hx b/source/KeyBindMenu.hx index 1d3f6e4..e7efdc8 100644 --- a/source/KeyBindMenu.hx +++ b/source/KeyBindMenu.hx @@ -3,6 +3,7 @@ package; /// Code created by Rozebud for FPS Plus (thanks rozebud) // modified by KadeDev for use in Kade Engine/Tricky +import flixel.input.gamepad.FlxGamepad; import flixel.util.FlxAxes; import flixel.FlxSubState; import Options.Option; @@ -36,15 +37,19 @@ class KeyBindMenu extends FlxSubState var warningTween:FlxTween; var keyText:Array = ["LEFT", "DOWN", "UP", "RIGHT"]; var defaultKeys:Array = ["A", "S", "W", "D", "R"]; + var defaultGpKeys:Array = ["DPAD_LEFT", "DPAD_DOWN", "DPAD_UP", "DPAD_RIGHT"]; var curSelected:Int = 0; var keys:Array = [FlxG.save.data.leftBind, FlxG.save.data.downBind, FlxG.save.data.upBind, FlxG.save.data.rightBind]; - + var gpKeys:Array = [FlxG.save.data.gpleftBind, + FlxG.save.data.gpdownBind, + FlxG.save.data.gpupBind, + FlxG.save.data.gprightBind]; var tempKey:String = ""; - var blacklist:Array = ["ESCAPE", "ENTER", "BACKSPACE", "SPACE"]; + var blacklist:Array = ["ESCAPE", "ENTER", "BACKSPACE", "SPACE", "TAB"]; var blackBox:FlxSprite; var infoText:FlxText; @@ -60,10 +65,17 @@ class KeyBindMenu extends FlxSubState if (k == null) keys[i] = defaultKeys[i]; } + + for (i in 0...gpKeys.length) + { + var k = gpKeys[i]; + if (k == null) + gpKeys[i] = defaultGpKeys[i]; + } //FlxG.sound.playMusic('assets/music/configurator' + TitleState.soundExt); - persistentUpdate = persistentDraw = true; + persistentUpdate = true; keyTextDisplay = new FlxText(-10, 0, 1280, "", 72); keyTextDisplay.scrollFactor.set(0, 0); @@ -74,7 +86,7 @@ class KeyBindMenu extends FlxSubState 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 = new FlxText(-10, 580, 1280, 'Current Mode: ${KeyBinds.gamepad ? 'GAMEPAD' : 'KEYBOARD'}. Press TAB to switch\n(${KeyBinds.gamepad ? 'RIGHT Trigger' : 'Escape'} to save, ${KeyBinds.gamepad ? 'LEFT Trigger' : 'Backspace'} to leave without saving. ${KeyBinds.gamepad ? 'START To change a keybind' : ''})', 72); infoText.scrollFactor.set(0, 0); infoText.setFormat("VCR OSD Mono", 24, FlxColor.WHITE, FlxTextAlign.CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); infoText.borderSize = 2; @@ -98,23 +110,37 @@ class KeyBindMenu extends FlxSubState super.create(); } + var frames = 0; + override function update(elapsed:Float) { + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + if (frames <= 10) + frames++; + + infoText.text = 'Current Mode: ${KeyBinds.gamepad ? 'GAMEPAD' : 'KEYBOARD'}. Press TAB to switch\n(${KeyBinds.gamepad ? 'RIGHT Trigger' : 'Escape'} to save, ${KeyBinds.gamepad ? 'LEFT Trigger' : 'Backspace'} to leave without saving. ${KeyBinds.gamepad ? 'START To change a keybind' : ''})\n${lastKey != "" ? lastKey + " is blacklisted!" : ""}'; switch(state){ case "select": if (FlxG.keys.justPressed.UP) - { - FlxG.sound.play(Paths.sound('scrollMenu')); - changeItem(-1); - } + { + 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.DOWN) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeItem(1); + } + + if (FlxG.keys.justPressed.TAB) + { + KeyBinds.gamepad = !KeyBinds.gamepad; + textUpdate(); + } if (FlxG.keys.justPressed.ENTER){ FlxG.sound.play(Paths.sound('scrollMenu')); @@ -123,31 +149,87 @@ class KeyBindMenu extends FlxSubState else if(FlxG.keys.justPressed.ESCAPE){ quit(); } - else if (FlxG.keys.justPressed.BACKSPACE){ + else if (FlxG.keys.justPressed.BACKSPACE){ reset(); } + if (gamepad != null) // GP Logic + { + if (gamepad.justPressed.DPAD_UP) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeItem(-1); + textUpdate(); + } + if (gamepad.justPressed.DPAD_DOWN) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeItem(1); + textUpdate(); + } + + if (gamepad.justPressed.START && frames > 10){ + FlxG.sound.play(Paths.sound('scrollMenu')); + state = "input"; + } + else if(gamepad.justPressed.LEFT_TRIGGER){ + quit(); + } + else if (gamepad.justPressed.RIGHT_TRIGGER){ + reset(); + } + } case "input": tempKey = keys[curSelected]; keys[curSelected] = "?"; + if (KeyBinds.gamepad) + gpKeys[curSelected] = "?"; textUpdate(); state = "waiting"; case "waiting": - if(FlxG.keys.justPressed.ESCAPE){ - keys[curSelected] = tempKey; - state = "select"; - FlxG.sound.play(Paths.sound('confirmMenu')); + if (gamepad != null && KeyBinds.gamepad) // GP Logic + { + if(FlxG.keys.justPressed.ESCAPE){ // just in case you get stuck + gpKeys[curSelected] = tempKey; + state = "select"; + FlxG.sound.play(Paths.sound('confirmMenu')); + } + + if (gamepad.justPressed.START) + { + addKeyGamepad(defaultKeys[curSelected]); + save(); + state = "select"; + } + + if (gamepad.justPressed.ANY) + { + trace(gamepad.firstJustPressedID()); + addKeyGamepad(gamepad.firstJustPressedID()); + save(); + state = "select"; + textUpdate(); + } + } - 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"; + else + { + 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"; + } } @@ -170,11 +252,24 @@ class KeyBindMenu extends FlxSubState keyTextDisplay.text = "\n\n"; - for(i in 0...4){ + if (KeyBinds.gamepad) + { + for(i in 0...4){ - var textStart = (i == curSelected) ? "> " : " "; - keyTextDisplay.text += textStart + keyText[i] + ": " + ((keys[i] != keyText[i]) ? (keys[i] + " / ") : "" ) + keyText[i] + " ARROW\n"; + var textStart = (i == curSelected) ? "> " : " "; + trace(gpKeys[i]); + keyTextDisplay.text += textStart + keyText[i] + ": " + gpKeys[i] + "\n"; + + } + } + else + { + 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(); @@ -187,6 +282,11 @@ class KeyBindMenu extends FlxSubState FlxG.save.data.downBind = keys[1]; FlxG.save.data.leftBind = keys[0]; FlxG.save.data.rightBind = keys[3]; + + FlxG.save.data.gpupBind = gpKeys[2]; + FlxG.save.data.gpdownBind = gpKeys[1]; + FlxG.save.data.gpleftBind = gpKeys[0]; + FlxG.save.data.gprightBind = gpKeys[3]; FlxG.save.flush(); @@ -217,6 +317,38 @@ class KeyBindMenu extends FlxSubState } + function addKeyGamepad(r:String){ + + var shouldReturn:Bool = true; + + var notAllowed:Array = ["START"]; + + for(x in 0...gpKeys.length) + { + var oK = gpKeys[x]; + if(oK == r) + gpKeys[x] = null; + if (notAllowed.contains(oK)) + { + gpKeys[x] = null; + lastKey = r; + return; + } + } + + if(shouldReturn){ + gpKeys[curSelected] = r; + FlxG.sound.play(Paths.sound('scrollMenu')); + } + else{ + gpKeys[curSelected] = tempKey; + lastKey = r; + } + + } + + public var lastKey:String = ""; + function addKey(r:String){ var shouldReturn:Bool = true; @@ -233,19 +365,29 @@ class KeyBindMenu extends FlxSubState if(oK == r) keys[x] = null; if (notAllowed.contains(oK)) + { + keys[x] = null; + lastKey = oK; return; + } } + if (r.contains("NUMPAD")) + { + keys[curSelected] = null; + lastKey = r; + return; + } + + lastKey = ""; + 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}); + lastKey = r; } } diff --git a/source/KeyBinds.hx b/source/KeyBinds.hx index facd1ad..b9c704d 100644 --- a/source/KeyBinds.hx +++ b/source/KeyBinds.hx @@ -12,6 +12,8 @@ import flixel.input.keyboard.FlxKey; class KeyBinds { + public static var gamepad:Bool = false; + public static function resetBinds():Void{ FlxG.save.data.upBind = "W"; @@ -19,6 +21,10 @@ class KeyBinds FlxG.save.data.leftBind = "A"; FlxG.save.data.rightBind = "D"; FlxG.save.data.killBind = "R"; + FlxG.save.data.gpupBind = "DPAD_UP"; + FlxG.save.data.gpdownBind = "DPAD_DOWN"; + FlxG.save.data.gpleftBind = "DPAD_LEFT"; + FlxG.save.data.gprightBind = "DPAD_RIGHT"; PlayerSettings.player1.controls.loadKeyBinds(); } @@ -29,22 +35,49 @@ class KeyBinds FlxG.save.data.upBind = "W"; trace("No UP"); } + if (StringTools.contains(FlxG.save.data.upBind,"NUMPAD")) + FlxG.save.data.upBind = "W"; if(FlxG.save.data.downBind == null){ FlxG.save.data.downBind = "S"; trace("No DOWN"); } + if (StringTools.contains(FlxG.save.data.downBind,"NUMPAD")) + FlxG.save.data.downBind = "S"; if(FlxG.save.data.leftBind == null){ FlxG.save.data.leftBind = "A"; trace("No LEFT"); } + if (StringTools.contains(FlxG.save.data.leftBind,"NUMPAD")) + FlxG.save.data.leftBind = "A"; if(FlxG.save.data.rightBind == null){ FlxG.save.data.rightBind = "D"; trace("No RIGHT"); } - if(FlxG.save.data.killBind == null){ + if (StringTools.contains(FlxG.save.data.rightBind,"NUMPAD")) + FlxG.save.data.rightBind = "D"; + + if(FlxG.save.data.gpupBind == null){ + FlxG.save.data.gpupBind = "DPAD_UP"; + trace("No GUP"); + } + if(FlxG.save.data.gpdownBind == null){ + FlxG.save.data.gpdownBind = "DPAD_DOWN"; + trace("No GDOWN"); + } + if(FlxG.save.data.gpleftBind == null){ + FlxG.save.data.gpleftBind = "DPAD_LEFT"; + trace("No GLEFT"); + } + if(FlxG.save.data.gprightBind == null){ + FlxG.save.data.gprightBind = "DPAD_RIGHT"; + trace("No GRIGHT"); + } + if(FlxG.save.data.killBind == null){ FlxG.save.data.killBind = "R"; trace("No KILL"); } + + trace('${FlxG.save.data.leftBind}-${FlxG.save.data.downBind}-${FlxG.save.data.upBind}-${FlxG.save.data.rightBind}'); } -} \ No newline at end of file +} diff --git a/source/LoadReplayState.hx b/source/LoadReplayState.hx index b654f24..135c5ae 100644 --- a/source/LoadReplayState.hx +++ b/source/LoadReplayState.hx @@ -1,5 +1,12 @@ package; +import haxe.Exception; +import lime.app.Application; + +#if sys +import smTools.SMFile; +import sys.FileSystem; +#end import Controls.KeyboardScheme; import Controls.Control; import flash.text.TextField; @@ -54,7 +61,7 @@ class LoadReplayState extends MusicBeatState var string:String = controlsStrings[i]; actualNames[i] = string; var rep:Replay = Replay.LoadReplay(string); - controlsStrings[i] = string.split("time")[0] + " " + (rep.replay.songDiff == 2 ? "HARD" : rep.replay.songDiff == 1 ? "EASY" : "NORMAL"); + controlsStrings[i] = string.split("time")[0] + " " + CoolUtil.difficultyFromInt(rep.replay.songDiff).toUpperCase(); } if (controlsStrings.length == 0) @@ -64,7 +71,10 @@ class LoadReplayState extends MusicBeatState menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); menuBG.updateHitbox(); menuBG.screenCenter(); - menuBG.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + menuBG.antialiasing = true; + } add(menuBG); grpControls = new FlxTypedGroup(); @@ -161,9 +171,55 @@ class LoadReplayState extends MusicBeatState case 'philly-nice': songFormat = 'Philly'; } - var poop:String = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff); + var poop = ""; + + #if sys + if (PlayState.rep.replay.sm) + if (!FileSystem.exists(StringTools.replace(PlayState.rep.replay.chartPath,"converted.json",""))) + { + Application.current.window.alert("The SM file in this replay does not exist!","SM Replays"); + return; + } + #end - PlayState.SONG = Song.loadFromJson(poop, PlayState.rep.replay.songName); + PlayState.isSM = PlayState.rep.replay.sm; + #if sys + if (PlayState.isSM) + PlayState.pathToSm = StringTools.replace(PlayState.rep.replay.chartPath,"converted.json",""); + #end + + #if sys + if (PlayState.isSM) + { + poop = File.getContent(PlayState.rep.replay.chartPath); + try + { + PlayState.sm = SMFile.loadFile(PlayState.pathToSm + "/" + StringTools.replace(PlayState.rep.replay.songName," ", "_") + ".sm"); + } + catch(e:Exception) + { + Application.current.window.alert("Make sure that the SM file is called " + PlayState.pathToSm + "/" + StringTools.replace(PlayState.rep.replay.songName," ", "_") + ".sm!\nAs I couldn't read it.","SM Replays"); + return; + } + } + else + poop = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff); + #else + poop = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff); + #end + + try + { + if (PlayState.isSM) + PlayState.SONG = Song.loadFromJsonRAW(poop); + else + PlayState.SONG = Song.loadFromJson(poop, PlayState.rep.replay.songName); + } + catch(e:Exception) + { + Application.current.window.alert("Failed to load the song! Does the JSON exist?","Replays"); + return; + } PlayState.isStoryMode = false; PlayState.storyDifficulty = PlayState.rep.replay.songDiff; PlayState.storyWeek = getWeekNumbFromSong(PlayState.rep.replay.songName); diff --git a/source/LoadingState.hx b/source/LoadingState.hx index 23bce2e..6609fa4 100644 --- a/source/LoadingState.hx +++ b/source/LoadingState.hx @@ -38,7 +38,10 @@ class LoadingState extends MusicBeatState { logo = new FlxSprite(-150, -100); logo.frames = Paths.getSparrowAtlas('logoBumpin'); - logo.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + logo.antialiasing = true; + } logo.animation.addByPrefix('bump', 'logo bumpin', 24); logo.animation.play('bump'); logo.updateHitbox(); @@ -49,7 +52,10 @@ class LoadingState extends MusicBeatState 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; + if(FlxG.save.data.antialiasing) + { + gfDance.antialiasing = true; + } add(gfDance); add(logo); diff --git a/source/Main.hx b/source/Main.hx index e04c2f5..f17cec3 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -1,10 +1,11 @@ package; - -import webm.WebmPlayer; +import lime.app.Application; +#if windows +import Discord.DiscordClient; +#end import openfl.display.BlendMode; import openfl.text.TextFormat; -import openfl.display.Application; import flixel.util.FlxColor; import flixel.FlxG; import flixel.FlxGame; @@ -25,7 +26,7 @@ class Main extends Sprite 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 + public static var watermarks = true; // Whether to put Kade Engine literally anywhere // You can pretty much ignore everything from here on - your code should go in your states. @@ -77,17 +78,30 @@ class Main extends Sprite gameHeight = Math.ceil(stageHeight / zoom); } - initialState = Caching; - - game = new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen); + #if !cpp + framerate = 60; + #end + #if cpp + initialState = Caching; + game = new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen); + #else + game = new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen); + #end addChild(game); + #if windows + DiscordClient.initialize(); + + Application.current.onExit.add (function (exitCode) { + DiscordClient.shutdown(); + }); + + #end #if !mobile fpsCounter = new FPS(10, 3, 0xFFFFFF); addChild(fpsCounter); toggleFPS(FlxG.save.data.fps); - #end } diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index e3e0756..2d676ae 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -1,5 +1,6 @@ package; +import flixel.input.gamepad.FlxGamepad; import Controls.KeyboardScheme; import flixel.FlxG; import flixel.FlxObject; @@ -39,7 +40,7 @@ class MainMenuState extends MusicBeatState public static var nightly:String = ""; - public static var kadeEngineVer:String = "1.5.3" + nightly; + public static var kadeEngineVer:String = "1.6" + nightly; public static var gameVer:String = "0.2.7.1"; var magenta:FlxSprite; @@ -66,7 +67,10 @@ class MainMenuState extends MusicBeatState bg.setGraphicSize(Std.int(bg.width * 1.1)); bg.updateHitbox(); bg.screenCenter(); - bg.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + bg.antialiasing = true; + } add(bg); camFollow = new FlxObject(0, 0, 1, 1); @@ -79,7 +83,10 @@ class MainMenuState extends MusicBeatState magenta.updateHitbox(); magenta.screenCenter(); magenta.visible = false; - magenta.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + magenta.antialiasing = true; + } magenta.color = 0xFFfd719b; add(magenta); // magenta.scrollFactor.set(); @@ -100,7 +107,10 @@ class MainMenuState extends MusicBeatState menuItem.screenCenter(X); menuItems.add(menuItem); menuItem.scrollFactor.set(); - menuItem.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + menuItem.antialiasing = true; + } if (firstStart) FlxTween.tween(menuItem,{y: 60 + (i * 160)},1 + (i * 0.25) ,{ease: FlxEase.expoInOut, onComplete: function(flxTween:FlxTween) { @@ -144,13 +154,29 @@ class MainMenuState extends MusicBeatState if (!selectedSomethin) { - if (controls.UP_P) + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + if (gamepad != null) + { + if (gamepad.justPressed.DPAD_UP) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeItem(-1); + } + if (gamepad.justPressed.DPAD_DOWN) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeItem(1); + } + } + + if (FlxG.keys.justPressed.UP) { FlxG.sound.play(Paths.sound('scrollMenu')); changeItem(-1); } - if (controls.DOWN_P) + if (FlxG.keys.justPressed.DOWN) { FlxG.sound.play(Paths.sound('scrollMenu')); changeItem(1); @@ -165,7 +191,7 @@ class MainMenuState extends MusicBeatState { if (optionShit[curSelected] == 'donate') { - fancyOpenURL("https://www.kickstarter.com/projects/funkin/friday-night-funkin-the-full-ass-game"); + fancyOpenURL("https://ninja-muffin24.itch.io/funkin"); } else { diff --git a/source/MenuCharacter.hx b/source/MenuCharacter.hx index 1cf3e5b..c35e25a 100644 --- a/source/MenuCharacter.hx +++ b/source/MenuCharacter.hx @@ -1,6 +1,7 @@ package; import flixel.FlxSprite; +import flixel.FlxG; import flixel.graphics.frames.FlxAtlasFrames; class CharacterSetting @@ -33,25 +34,34 @@ class MenuCharacter extends FlxSprite ]; private var flipped:Bool = false; + //questionable variable name lmfao + private var goesLeftNRight:Bool = false; + private var danceLeft:Bool = false; + private var character:String = ''; public function new(x:Int, y:Int, scale:Float, flipped:Bool) { super(x, y); this.flipped = flipped; - antialiasing = true; + if(FlxG.save.data.antialiasing) + { + antialiasing = true; + } frames = Paths.getSparrowAtlas('campaign_menu_UI_characters'); - animation.addByPrefix('bf', "BF idle dance white", 24); + animation.addByPrefix('bf', "BF idle dance white", 24, false); 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); + animation.addByIndices('gf-left', 'GF Dancing Beat WHITE', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false); + animation.addByIndices('gf-right', 'GF Dancing Beat WHITE', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false); + animation.addByPrefix('dad', "Dad idle dance BLACK LINE", 24, false); + animation.addByIndices('spooky-left', 'spooky dance idle BLACK LINES', [0, 2, 6], "", 12, false); + animation.addByIndices('spooky-right', 'spooky dance idle BLACK LINES', [8, 10, 12, 14], "", 12, false); + animation.addByPrefix('pico', "Pico Idle Dance", 24, false); + animation.addByPrefix('mom', "Mom Idle BLACK LINES", 24, false); + animation.addByPrefix('parents-christmas', "Parent Christmas Idle", 24, false); + animation.addByPrefix('senpai', "SENPAI idle Black Lines", 24, false); setGraphicSize(Std.int(width * scale)); updateHitbox(); @@ -59,6 +69,8 @@ class MenuCharacter extends FlxSprite public function setCharacter(character:String):Void { + var sameCharacter:Bool = character == this.character; + this.character = character; if (character == '') { visible = false; @@ -69,11 +81,33 @@ class MenuCharacter extends FlxSprite visible = true; } - animation.play(character); + if (!sameCharacter) { + bopHead(true); + } var setting:CharacterSetting = settings[character]; offset.set(setting.x, setting.y); setGraphicSize(Std.int(width * setting.scale)); flipX = setting.flipped != flipped; } + + public function bopHead(LastFrame:Bool = false):Void + { + if (character == 'gf' || character == 'spooky') { + danceLeft = !danceLeft; + + if (danceLeft) + animation.play(character + "-left", true); + else + animation.play(character + "-right", true); + } else { + //no spooky nor girlfriend so we do da normal animation + if (animation.name == "bfConfirm") + return; + animation.play(character, true); + } + if (LastFrame) { + animation.finish(); + } + } } diff --git a/source/ModchartShader.hx b/source/ModchartShader.hx new file mode 100644 index 0000000..9077d22 --- /dev/null +++ b/source/ModchartShader.hx @@ -0,0 +1,74 @@ +import flixel.system.FlxAssets.FlxShader; + +class ModchartShader extends FlxShader +{ + public var vertexHeader = "attribute float openfl_Alpha; + attribute vec4 openfl_ColorMultiplier; + attribute vec4 openfl_ColorOffset; + attribute vec4 openfl_Position; + attribute vec2 openfl_TextureCoord; + varying float openfl_Alphav; + varying vec4 openfl_ColorMultiplierv; + varying vec4 openfl_ColorOffsetv; + varying vec2 openfl_TextureCoordv; + uniform mat4 openfl_Matrix; + uniform bool openfl_HasColorTransform; + uniform vec2 openfl_TextureSize;"; + public var vertexBody = "openfl_Alphav = openfl_Alpha; + openfl_TextureCoordv = openfl_TextureCoord; + if (openfl_HasColorTransform) { + openfl_ColorMultiplierv = openfl_ColorMultiplier; + openfl_ColorOffsetv = openfl_ColorOffset / 255.0; + } + gl_Position = openfl_Matrix * openfl_Position;"; + public var vertexSource = "#pragma header + void main(void) { + #pragma body + }"; + public var fragmentHeader = "varying float openfl_Alphav; + varying vec4 openfl_ColorMultiplierv; + varying vec4 openfl_ColorOffsetv; + varying vec2 openfl_TextureCoordv; + uniform bool openfl_HasColorTransform; + uniform sampler2D openfl_Texture; + uniform vec2 openfl_TextureSize;"; + public var fragmentBody = "vec4 color = texture2D (openfl_Texture, openfl_TextureCoordv); + if (color.a == 0.0) { + gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); + } else if (openfl_HasColorTransform) { + 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] = 1.0; // openfl_ColorMultiplierv.w; + color = clamp (openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0); + if (color.a > 0.0) { + gl_FragColor = vec4 (color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); + } else { + gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); + } + } else { + gl_FragColor = color * openfl_Alphav; + }"; + + public function new(frag:String,?vert:String = "") + { + if (vert != "") + glVertexSource = vert; + glFragmentSource = frag; + + if (glVertexSource != null) + { + glVertexSource = StringTools.replace(glVertexSource, "#pragma header", vertexHeader); + glVertexSource = StringTools.replace(glVertexSource, "#pragma body", vertexBody); + } + + if (glVertexSource != null) + { + glFragmentSource = StringTools.replace(glFragmentSource, "#pragma header", fragmentHeader); + glFragmentSource = StringTools.replace(glFragmentSource, "#pragma body", fragmentBody); + } + super(); + } +} \ No newline at end of file diff --git a/source/ModchartState.hx b/source/ModchartState.hx index 6e194d1..311ae08 100644 --- a/source/ModchartState.hx +++ b/source/ModchartState.hx @@ -241,7 +241,7 @@ class ModchartState PlayState.instance.removeObject(PlayState.dad); PlayState.dad = new Character(olddadx, olddady, id); PlayState.instance.addObject(PlayState.dad); - PlayState.instance.iconP2.animation.play(id); + PlayState.instance.iconP2.changeIcon(id); } function changeBoyfriendCharacter(id:String) @@ -250,7 +250,7 @@ class ModchartState PlayState.instance.removeObject(PlayState.boyfriend); PlayState.boyfriend = new Boyfriend(oldboyfriendx, oldboyfriendy, id); PlayState.instance.addObject(PlayState.boyfriend); - PlayState.instance.iconP2.animation.play(id); + PlayState.instance.iconP1.changeIcon(id); } function makeAnimatedLuaSprite(spritePath:String,names:Array,prefixes:Array,startAnim:String, id:String) @@ -297,7 +297,12 @@ class ModchartState case 'philly-nice': songLowercase = 'philly'; } - var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + songLowercase + '/' + spritePath + ".png"); + var path = Sys.getCwd() + "assets/data/" + songLowercase + '/'; + + if (PlayState.isSM) + path = PlayState.pathToSm + "/"; + + var data:BitmapData = BitmapData.fromFile(path + spritePath + ".png"); var sprite:FlxSprite = new FlxSprite(0,0); var imgWidth:Float = FlxG.width / data.width; @@ -347,6 +352,8 @@ class ModchartState lua = null; } + public var luaWiggles:Map = new Map(); + // LUA SHIT function new() @@ -367,7 +374,11 @@ class ModchartState case 'philly-nice': songLowercase = 'philly'; } - var result = LuaL.dofile(lua, Paths.lua(songLowercase + "/modchart")); // execute le file + var path = Paths.lua(songLowercase + "/modchart"); + if (PlayState.isSM) + path = PlayState.pathToSm + "/modchart.lua"; + + var result = LuaL.dofile(lua, path); // execute le file if (result != 0) { @@ -427,6 +438,41 @@ class ModchartState Lua_helper.add_callback(lua,"getProperty", getPropertyByName); + Lua_helper.add_callback(lua,"setNoteWiggle", function(wiggleId) { + PlayState.instance.camNotes.setFilters([new ShaderFilter(luaWiggles.get(wiggleId).shader)]); + }); + + Lua_helper.add_callback(lua,"setSustainWiggle", function(wiggleId) { + PlayState.instance.camSustains.setFilters([new ShaderFilter(luaWiggles.get(wiggleId).shader)]); + }); + + Lua_helper.add_callback(lua,"createWiggle", function(freq:Float,amplitude:Float,speed:Float) { + var wiggle = new WiggleEffect(); + wiggle.waveAmplitude = amplitude; + wiggle.waveSpeed = speed; + wiggle.waveFrequency = freq; + + var id = Lambda.count(luaWiggles) + 1 + ""; + + luaWiggles.set(id,wiggle); + return id; + }); + + Lua_helper.add_callback(lua,"setWiggleTime", function(wiggleId:String,time:Float) { + var wiggle = luaWiggles.get(wiggleId); + + wiggle.shader.uTime.value = [time]; + }); + + + Lua_helper.add_callback(lua,"setWiggleAmplitude", function(wiggleId:String,amp:Float) { + var wiggle = luaWiggles.get(wiggleId); + + wiggle.waveAmplitude = amp; + }); + + + // Lua_helper.add_callback(lua,"makeAnimatedSprite", makeAnimatedLuaSprite); // this one is still in development diff --git a/source/MusicBeatState.hx b/source/MusicBeatState.hx index d98bd64..7a3bde8 100644 --- a/source/MusicBeatState.hx +++ b/source/MusicBeatState.hx @@ -3,15 +3,11 @@ 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 { @@ -20,6 +16,7 @@ class MusicBeatState extends FlxUIState private var curStep:Int = 0; private var curBeat:Int = 0; + private var curDecimalBeat:Float = 0; private var controls(get, never):Controls; inline function get_controls():Controls @@ -27,6 +24,7 @@ class MusicBeatState extends FlxUIState override function create() { + TimingStruct.clearTimings(); (cast (Lib.current.getChildAt(0), Main)).setFPSCap(FlxG.save.data.fpsCap); if (transIn != null) @@ -51,13 +49,50 @@ class MusicBeatState extends FlxUIState override function update(elapsed:Float) { //everyStep(); - var oldStep:Int = curStep; + var nextStep:Int = updateCurStep(); - updateCurStep(); - updateBeat(); + if (nextStep >= 0) + { + if (nextStep > curStep) + { + for (i in curStep...nextStep) + { + curStep++; + updateBeat(); + stepHit(); + } + } + else if (nextStep < curStep) + { + //Song reset? + curStep = nextStep; + updateBeat(); + stepHit(); + } + } - if (oldStep != curStep && curStep > 0) - stepHit(); + if (Conductor.songPosition < 0) + curDecimalBeat = 0; + else + { + if (TimingStruct.AllTimings.length > 1) + { + var data = TimingStruct.getTimingAtTimestamp(Conductor.songPosition); + + FlxG.watch.addQuick("Current Conductor Timing Seg", data.bpm); + + Conductor.crochet = ((60 / data.bpm) * 1000); + + var percent = (Conductor.songPosition - (data.startTime * 1000)) / (data.length * 1000); + + curDecimalBeat = data.startBeat + (((Conductor.songPosition/1000) - data.startTime) * (data.bpm / 60)); + } + else + { + curDecimalBeat = (Conductor.songPosition / 1000) * (Conductor.bpm/60); + Conductor.crochet = ((60 / Conductor.bpm) * 1000); + } + } if (FlxG.save.data.fpsRain && skippedFrames >= 6) { @@ -78,13 +113,13 @@ class MusicBeatState extends FlxUIState private function updateBeat():Void { - lastBeat = curStep; + lastBeat = curBeat; curBeat = Math.floor(curStep / 4); } public static var currentColor = 0; - private function updateCurStep():Void + private function updateCurStep():Int { var lastChange:BPMChangeEvent = { stepTime: 0, @@ -97,12 +132,11 @@ class MusicBeatState extends FlxUIState lastChange = Conductor.bpmChangeMap[i]; } - curStep = lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet); + return lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet); } public function stepHit():Void { - if (curStep % 4 == 0) beatHit(); } diff --git a/source/MusicBeatSubstate.hx b/source/MusicBeatSubstate.hx index c6da0fb..ee15697 100644 --- a/source/MusicBeatSubstate.hx +++ b/source/MusicBeatSubstate.hx @@ -24,19 +24,38 @@ class MusicBeatSubstate extends FlxSubState override function update(elapsed:Float) { //everyStep(); - var oldStep:Int = curStep; - - updateCurStep(); - curBeat = Math.floor(curStep / 4); - - if (oldStep != curStep && curStep > 0) - stepHit(); + var nextStep = updateCurStep(); + if (nextStep >= 0) + { + if (nextStep > curStep) + { + for (i in curStep...nextStep) + { + curStep++; + updateBeat(); + stepHit(); + } + } + else if (nextStep < curStep) + { + //Song reset? + curStep = nextStep; + updateBeat(); + stepHit(); + } + } super.update(elapsed); } - private function updateCurStep():Void + private function updateBeat():Void + { + lastBeat = curBeat; + curBeat = Math.floor(curStep / 4); + } + + private function updateCurStep():Int { var lastChange:BPMChangeEvent = { stepTime: 0, @@ -49,7 +68,7 @@ class MusicBeatSubstate extends FlxSubState lastChange = Conductor.bpmChangeMap[i]; } - curStep = lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet); + return lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet); } public function stepHit():Void diff --git a/source/Note.hx b/source/Note.hx index f7f915e..700c14e 100644 --- a/source/Note.hx +++ b/source/Note.hx @@ -16,9 +16,13 @@ using StringTools; class Note extends FlxSprite { public var strumTime:Float = 0; + public var baseStrum:Float = 0; + + public var rStrumTime:Float = 0; public var mustPress:Bool = false; public var noteData:Int = 0; + public var rawNoteData:Int = 0; public var canBeHit:Bool = false; public var tooLate:Bool = false; public var wasGoodHit:Bool = false; @@ -26,9 +30,15 @@ class Note extends FlxSprite public var modifiedByLua:Bool = false; public var sustainLength:Float = 0; public var isSustainNote:Bool = false; + public var originColor:Int = 0; // The sustain note's original note's color + public var noteSection:Int = 0; + + public var noteCharterObject:FlxSprite; public var noteScore:Float = 1; + public var noteYOff:Int = 0; + public static var swagWidth:Float = 160 * 0.7; public static var PURP_NOTE:Int = 0; public static var GREEN_NOTE:Int = 2; @@ -37,7 +47,21 @@ class Note extends FlxSprite public var rating:String = "shit"; - public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false) + public var modAngle:Float = 0; // The angle set by modcharts + public var localAngle:Float = 0; // The angle to be edited inside Note.hx + + public var dataColor:Array = ['purple', 'blue', 'green', 'red']; + public var quantityColor:Array = [RED_NOTE, 2, BLUE_NOTE, 2, PURP_NOTE, 2, BLUE_NOTE, 2]; + public var arrowAngles:Array = [180, 90, 270, 0]; + + public var isParent:Bool = false; + public var parent:Note = null; + public var spotInLine:Int = 0; + public var sustainActive:Bool = true; + + public var children:Array = []; + + public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false, ?inCharter:Bool = false) { super(); @@ -50,7 +74,24 @@ class Note extends FlxSprite x += 50; // MAKE SURE ITS DEFINITELY OFF SCREEN? y -= 2000; - this.strumTime = Math.round(strumTime); + + if (inCharter) + { + this.strumTime = strumTime; + rStrumTime = strumTime; + } + else + { + this.strumTime = strumTime; + rStrumTime = strumTime - (FlxG.save.data.offset + PlayState.songOffset); + #if sys + if (PlayState.isSM) + { + rStrumTime = Math.round(rStrumTime + Std.parseFloat(PlayState.sm.header.OFFSET)); + } + #end + } + if (this.strumTime < 0 ) this.strumTime = 0; @@ -62,84 +103,98 @@ class Note extends FlxSprite //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) + if (inCharter) { - case 'pixel': - loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels','week6'), true, 17, 17); + frames = Paths.getSparrowAtlas('NOTE_assets'); - animation.add('greenScroll', [6]); - animation.add('redScroll', [7]); - animation.add('blueScroll', [5]); - animation.add('purpleScroll', [4]); + for (i in 0...4) + { + animation.addByPrefix(dataColor[i] + 'Scroll', dataColor[i] + ' alone'); // Normal notes + animation.addByPrefix(dataColor[i] + 'hold', dataColor[i] + ' hold'); // Hold + animation.addByPrefix(dataColor[i] + 'holdend', dataColor[i] + ' tail'); // Tails + } - if (isSustainNote) + setGraphicSize(Std.int(width * 0.7)); + updateHitbox(); + if(FlxG.save.data.antialiasing) { - 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]); + antialiasing = true; } - - 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) + else { - 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'); + 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); + if (isSustainNote) + loadGraphic(Paths.image('weeb/pixelUI/arrowEnds', 'week6'), true, 7, 6); + + for (i in 0...4) + { + animation.add(dataColor[i] + 'Scroll', [i + 4]); // Normal notes + animation.add(dataColor[i] + 'hold', [i]); // Holds + animation.add(dataColor[i] + 'holdend', [i + 4]); // Tails + } + + setGraphicSize(Std.int(width * PlayState.daPixelZoom)); + updateHitbox(); + default: + frames = Paths.getSparrowAtlas('NOTE_assets'); + + for (i in 0...4) + { + animation.addByPrefix(dataColor[i] + 'Scroll', dataColor[i] + ' alone'); // Normal notes + animation.addByPrefix(dataColor[i] + 'hold', dataColor[i] + ' hold'); // Hold + animation.addByPrefix(dataColor[i] + 'holdend', dataColor[i] + ' tail'); // Tails + } + + setGraphicSize(Std.int(width * 0.7)); + updateHitbox(); + + if(FlxG.save.data.antialiasing) + { + antialiasing = true; + } + } } - // trace(prevNote); + x += swagWidth * noteData; + animation.play(dataColor[noteData] + 'Scroll'); + originColor = noteData; // The note's origin color will be checked by its sustain notes + if (FlxG.save.data.stepMania && !isSustainNote) + { + var strumCheck:Float = rStrumTime; + + // I give up on fluctuating bpms. something has to be subtracted from strumCheck to make them look right but idk what. + // I'd use the note's section's start time but neither the note's section nor its start time are accessible by themselves + //strumCheck -= ??? + + var ind:Int = Std.int(Math.round(strumCheck / (Conductor.stepCrochet / 2))); + + var col:Int = 0; + col = quantityColor[ind % 8]; // Set the color depending on the beats + + animation.play(dataColor[col] + 'Scroll'); + localAngle -= arrowAngles[col]; + localAngle += arrowAngles[noteData]; + originColor = col; + } + // 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 + // then what is this lol if (FlxG.save.data.downscroll && sustainNote) flipY = true; + var stepHeight = (0.45 * Conductor.stepCrochet * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? PlayState.SONG.speed : PlayStateChangeables.scrollSpeed, 2)); + if (isSustainNote && prevNote != null) { noteScore * 0.2; @@ -147,46 +202,30 @@ class Note extends FlxSprite 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'); - } + originColor = prevNote.originColor; + animation.play(dataColor[originColor] + 'holdend'); // This works both for normal colors and quantization colors updateHitbox(); x -= width / 2; - if (PlayState.curStage.startsWith('school')) + //if (noteTypeCheck == 'pixel') + // x += 30; + if (inCharter) 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.animation.play(dataColor[prevNote.originColor] + 'hold'); prevNote.updateHitbox(); + + prevNote.scale.y *= (stepHeight + 1) / prevNote.height; // + 1 so that there's no odd gaps as the notes scroll + prevNote.updateHitbox(); + prevNote.noteYOff = Math.round(-prevNote.offset.y); + // prevNote.setGraphicSize(); + + noteYOff = Math.round(-offset.y); } } } @@ -194,6 +233,15 @@ class Note extends FlxSprite override function update(elapsed:Float) { super.update(elapsed); + angle = modAngle + localAngle; + + if (!modifiedByLua) + { + if (!sustainActive) + { + alpha = 0.3; + } + } if (mustPress) { @@ -232,4 +280,4 @@ class Note extends FlxSprite alpha = 0.3; } } -} \ No newline at end of file +} diff --git a/source/OFLSprite.hx b/source/OFLSprite.hx new file mode 100644 index 0000000..abea3a0 --- /dev/null +++ b/source/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/OFLWaveform.hx b/source/OFLWaveform.hx new file mode 100644 index 0000000..46d1512 --- /dev/null +++ b/source/OFLWaveform.hx @@ -0,0 +1,30 @@ +import lime.media.AudioSource; +import lime.media.AudioBuffer; +import openfl.media.Sound; +import openfl.display.Graphics; +import openfl.display.Sprite; + +class OFLWaveform extends Sprite +{ + public var musicLength = 0; + public var _x = 0; + public var _y = 0; + + public var _sound:String; + + function new(x,y,musicLength, data:String) + { + super(); + + _x = x; + _y = y; + _sound = data; + this.musicLength = musicLength; + } + + public function drawWaveform() + { + var gfx:Graphics = graphics; + gfx.clear(); + } +} \ No newline at end of file diff --git a/source/Options.hx b/source/Options.hx index 4ed6a5f..0a7f8ef 100644 --- a/source/Options.hx +++ b/source/Options.hx @@ -119,6 +119,52 @@ class CpuStrums extends Option } +class GraphicLoading extends Option +{ + public function new(desc:String) + { + super(); + description = desc; + } + + public override function press():Bool + { + FlxG.save.data.cacheImages = !FlxG.save.data.cacheImages; + + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return FlxG.save.data.cacheImages ? "Preload Characters" : "Do not Preload Characters"; + } + +} + +class EditorRes extends Option +{ + public function new(desc:String) + { + super(); + description = desc; + } + + public override function press():Bool + { + FlxG.save.data.editor = !FlxG.save.data.editor; + + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return FlxG.save.data.editor ? "Show Editor Grid" : "Do not Show Editor Grid"; + } + +} + class DownscrollOption extends Option { public function new(desc:String) @@ -221,6 +267,26 @@ class DistractionsAndEffectsOption extends Option } } +class StepManiaOption extends Option +{ + public function new(desc:String) + { + super(); + description = desc; + } + public override function press():Bool + { + FlxG.save.data.stepMania = !FlxG.save.data.stepMania; + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return "Colors by quantization " + (!FlxG.save.data.stepMania ? "off" : "on"); + } +} + class ResetButtonOption extends Option { public function new(desc:String) @@ -261,6 +327,67 @@ class FlashingLightsOption extends Option } } +class AntialiasingOption extends Option +{ + public function new(desc:String) + { + super(); + description = desc; + } + public override function press():Bool + { + FlxG.save.data.antialiasing = !FlxG.save.data.antialiasing; + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return "Antialiasing " + (!FlxG.save.data.antialiasing ? "off" : "on"); + } +} + +class MissSoundsOption extends Option +{ + public function new(desc:String) + { + super(); + description = desc; + } + public override function press():Bool + { + FlxG.save.data.missSounds = !FlxG.save.data.missSounds; + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return "Miss Sounds " + (!FlxG.save.data.missSounds ? "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 { @@ -291,15 +418,15 @@ class Judgement extends Option FlxG.save.data.frames = Conductor.safeFrames; Conductor.recalculateTimings(); - return true; + return false; } override function getValue():String { return "Safe Frames: " + Conductor.safeFrames + - " - SIK: " + HelperFunctions.truncateFloat(22 * Conductor.timeScale, 0) + - "ms GD: " + HelperFunctions.truncateFloat(45 * Conductor.timeScale, 0) + + " - SIK: " + HelperFunctions.truncateFloat(45 * Conductor.timeScale, 0) + + "ms GD: " + HelperFunctions.truncateFloat(90 * Conductor.timeScale, 0) + "ms BD: " + HelperFunctions.truncateFloat(135 * Conductor.timeScale, 0) + - "ms SHT: " + HelperFunctions.truncateFloat(155 * Conductor.timeScale, 0) + + "ms SHT: " + HelperFunctions.truncateFloat(166 * Conductor.timeScale, 0) + "ms TOTAL: " + HelperFunctions.truncateFloat(Conductor.safeZoneOffset,0) + "ms"; } @@ -349,6 +476,7 @@ class ScoreScreen extends Option public override function press():Bool { FlxG.save.data.scoreScreen = !FlxG.save.data.scoreScreen; + display = updateDisplay(); return true; } @@ -482,6 +610,27 @@ class RainbowFPSOption extends Option } } +class Optimization extends Option +{ + public function new(desc:String) + { + super(); + description = desc; + } + + public override function press():Bool + { + FlxG.save.data.optimize = !FlxG.save.data.optimize; + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return "Optimization " + (FlxG.save.data.optimize ? "ON" : "OFF"); + } +} + class NPSDisplayOption extends Option { public function new(desc:String) @@ -655,3 +804,137 @@ class CamZoomOption extends Option return "Camera Zoom " + (!FlxG.save.data.camzoom ? "off" : "on"); } } + +class LockWeeksOption extends Option +{ + var confirm:Bool = false; + + public function new(desc:String) + { + super(); + description = desc; + } + public override function press():Bool + { + if(!confirm) + { + confirm = true; + display = updateDisplay(); + return true; + } + FlxG.save.data.weekUnlocked = 1; + StoryMenuState.weekUnlocked = [true, true]; + confirm = false; + trace('Weeks Locked'); + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return confirm ? "Confirm Story Reset" : "Reset Story Progress"; + } +} + +class ResetScoreOption extends Option +{ + var confirm:Bool = false; + + public function new(desc:String) + { + super(); + description = desc; + } + public override function press():Bool + { + if(!confirm) + { + confirm = true; + display = updateDisplay(); + return true; + } + FlxG.save.data.songScores = null; + for(key in Highscore.songScores.keys()) + { + Highscore.songScores[key] = 0; + } + FlxG.save.data.songCombos = null; + for(key in Highscore.songCombos.keys()) + { + Highscore.songCombos[key] = ''; + } + confirm = false; + trace('Highscores Wiped'); + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return confirm ? "Confirm Score Reset" : "Reset Score"; + } +} + +class ResetSettings extends Option +{ + var confirm:Bool = false; + + public function new(desc:String) + { + super(); + description = desc; + } + public override function press():Bool + { + if(!confirm) + { + confirm = true; + display = updateDisplay(); + return true; + } + FlxG.save.data.weekUnlocked = null; + FlxG.save.data.newInput = null; + FlxG.save.data.downscroll = null; + FlxG.save.data.antialiasing = null; + FlxG.save.data.missSounds = null; + FlxG.save.data.dfjk = null; + FlxG.save.data.accuracyDisplay = null; + FlxG.save.data.offset = null; + FlxG.save.data.songPosition = null; + FlxG.save.data.fps = null; + FlxG.save.data.changedHit = null; + FlxG.save.data.fpsRain = null; + FlxG.save.data.fpsCap = null; + FlxG.save.data.scrollSpeed = null; + FlxG.save.data.npsDisplay = null; + FlxG.save.data.frames = null; + FlxG.save.data.accuracyMod = null; + FlxG.save.data.watermark = null; + FlxG.save.data.ghost = null; + FlxG.save.data.distractions = null; + FlxG.save.data.stepMania = null; + FlxG.save.data.flashing = null; + FlxG.save.data.resetButton = null; + FlxG.save.data.botplay = null; + FlxG.save.data.cpuStrums = null; + FlxG.save.data.strumline = null; + FlxG.save.data.customStrumLine = null; + FlxG.save.data.camzoom = null; + FlxG.save.data.scoreScreen = null; + FlxG.save.data.inputShow = null; + FlxG.save.data.optimize = null; + FlxG.save.data.cacheImages = null; + FlxG.save.data.editor = null; + + KadeEngineData.initSave(); + confirm = false; + trace('All settings have been reset'); + display = updateDisplay(); + return true; + } + + private override function updateDisplay():String + { + return confirm ? "Confirm Settings Reset" : "Reset Settings"; + } +} diff --git a/source/OptionsMenu.hx b/source/OptionsMenu.hx index 28aa34b..efaef4e 100644 --- a/source/OptionsMenu.hx +++ b/source/OptionsMenu.hx @@ -1,5 +1,6 @@ package; +import flixel.input.gamepad.FlxGamepad; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import openfl.Lib; @@ -26,39 +27,50 @@ class OptionsMenu extends MusicBeatState 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)"), + new DownscrollOption("Toggle making the notes scroll down rather than up."), + new GhostTapOption("Toggle counting pressing a directional input when no arrow is there as a miss."), + new Judgement("Customize your Hit Timings. (LEFT or RIGHT)"), #if desktop - new FPSCapOption("Cap your FPS"), + new FPSCapOption("Change your FPS Cap."), #end - new ScrollSpeedOption("Change your scroll speed (1 = Chart dependent)"), + 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 CustomizeGameplay("Drag and drop gameplay modules to your prefered positions!") ]), new OptionCategory("Appearance", [ + new EditorRes("Not showing the editor grid will greatly increase editor performance"), 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 StepManiaOption("Sets the colors of the arrows depending on quantization instead of direction."), + new AccuracyOption("Display accuracy information on the info bar."), + new SongPositionOption("Show the song's current position as a scrolling bar."), + new NPSDisplayOption("Shows your current Notes Per Second on the info bar."), + new RainbowFPSOption("Make the FPS Counter flicker through rainbow colors."), + new CpuStrums("Toggle the CPU's strumline lighting up when it hits a note."), ]), 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 AntialiasingOption("Toggle antialiasing, improving graphics quality at a slight performance penalty."), + new MissSoundsOption("Toggle miss sounds playing when you don't hit a note."), + new ScoreScreen("Show the score screen after the end of a song"), + new ShowInput("Display every single input on the score screen."), + new Optimization("No characters or backgrounds. Just a usual rhythm game layout."), + new GraphicLoading("On startup, cache every character. Significantly decrease load times. (HIGH MEMORY)"), + new BotPlay("Showcase your charts and mods with autoplay.") + ]), + + new OptionCategory("Saves and Data", [ + #if desktop + new ReplayOption("View saved song replays."), + #end + new ResetScoreOption("Reset your score on all songs and weeks. This is irreversible!"), + new LockWeeksOption("Reset your story mode progress. This is irreversible!"), + new ResetSettings("Reset ALL your settings. This is irreversible!") ]) ]; @@ -80,7 +92,10 @@ class OptionsMenu extends MusicBeatState menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); menuBG.updateHitbox(); menuBG.screenCenter(); - menuBG.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + menuBG.antialiasing = true; + } add(menuBG); grpControls = new FlxTypedGroup(); @@ -142,9 +157,26 @@ class OptionsMenu extends MusicBeatState changeSelection(curSelected); } - if (controls.UP_P) + + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + if (gamepad != null) + { + if (gamepad.justPressed.DPAD_UP) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeSelection(-1); + } + if (gamepad.justPressed.DPAD_DOWN) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeSelection(1); + } + } + + if (FlxG.keys.justPressed.UP) changeSelection(-1); - if (controls.DOWN_P) + if (FlxG.keys.justPressed.DOWN) changeSelection(1); if (isCat) @@ -213,10 +245,8 @@ class OptionsMenu extends MusicBeatState 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); + grpControls.members[curSelected].reType(currentSelectedCat.getOptions()[curSelected].getDisplay()); + trace(currentSelectedCat.getOptions()[curSelected].getDisplay()); } } else @@ -235,7 +265,7 @@ class OptionsMenu extends MusicBeatState curSelected = 0; } - changeSelection(curSelected); + changeSelection(); } } FlxG.save.flush(); diff --git a/source/OutdatedSubState.hx b/source/OutdatedSubState.hx index f7015c4..c825c50 100644 --- a/source/OutdatedSubState.hx +++ b/source/OutdatedSubState.hx @@ -32,6 +32,10 @@ class OutdatedSubState extends MusicBeatState bg.scale.x *= 1.55; bg.scale.y *= 1.55; bg.screenCenter(); + if(FlxG.save.data.antialiasing) + { + bg.antialiasing = true; + } add(bg); var kadeLogo:FlxSprite = new FlxSprite(FlxG.width, 0).loadGraphic(Paths.image('KadeEngineLogo')); @@ -40,6 +44,10 @@ class OutdatedSubState extends MusicBeatState kadeLogo.x -= kadeLogo.frameHeight; kadeLogo.y -= 180; kadeLogo.alpha = 0.8; + if(FlxG.save.data.antialiasing) + { + kadeLogo.antialiasing = true; + } add(kadeLogo); var txt:FlxText = new FlxText(0, 0, FlxG.width, @@ -51,6 +59,13 @@ class OutdatedSubState extends MusicBeatState + "\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); + + if (MainMenuState.nightly != "") + txt.text = + "You are on\n" + + MainMenuState.kadeEngineVer + + "\nWhich is a PRE-RELEASE BUILD!" + + "\n\nReport all bugs to the author of the pre-release.\nSpace/Escape ignores this."; txt.setFormat("VCR OSD Mono", 32, FlxColor.fromRGB(200, 200, 200), CENTER); txt.borderColor = FlxColor.BLACK; @@ -84,10 +99,15 @@ class OutdatedSubState extends MusicBeatState override function update(elapsed:Float) { - if (controls.ACCEPT) + if (controls.ACCEPT && MainMenuState.nightly == "") { fancyOpenURL("https://kadedev.github.io/Kade-Engine/changelogs/changelog-" + needVer); } + else if (controls.ACCEPT) + { + leftState = true; + FlxG.switchState(new MainMenuState()); + } if (controls.BACK) { leftState = true; diff --git a/source/Paths.hx b/source/Paths.hx index 075adbd..8c8f184 100644 --- a/source/Paths.hx +++ b/source/Paths.hx @@ -1,5 +1,8 @@ package; +import openfl.utils.Assets; +import flixel.graphics.FlxGraphic; +import flixel.system.FlxAssets.FlxGraphicAsset; import flixel.FlxG; import flixel.graphics.frames.FlxAtlasFrames; import openfl.utils.AssetType; @@ -50,7 +53,7 @@ class Paths return 'assets/$file'; } - inline static public function file(file:String, type:AssetType = TEXT, ?library:String) + inline static public function file(file:String, ?library:String, type:AssetType = TEXT) { return getPath(file, type, library); } @@ -67,7 +70,7 @@ class Paths inline static public function txt(key:String, ?library:String) { - return getPath('data/$key.txt', TEXT, library); + return getPath('$key.txt', TEXT, library); } inline static public function xml(key:String, ?library:String) @@ -125,13 +128,48 @@ class Paths return 'assets/fonts/$key'; } - inline static public function getSparrowAtlas(key:String, ?library:String) + inline static public function getSparrowAtlas(key:String, ?library:String, ?isCharacter:Bool = false) { + var usecahce = FlxG.save.data.cacheImages; + #if !cpp + usecahce = false; + #end + if (isCharacter) + if (usecahce) + #if cpp + return FlxAtlasFrames.fromSparrow(imageCached(key), file('images/characters/$key.xml', library)); + #else + return null; + #end + else + return FlxAtlasFrames.fromSparrow(image('characters/$key', library), file('images/characters/$key.xml', library)); return FlxAtlasFrames.fromSparrow(image(key, library), file('images/$key.xml', library)); } - inline static public function getPackerAtlas(key:String, ?library:String) + #if cpp + inline static public function imageCached(key:String):FlxGraphic { + var data = Caching.bitmapData.get(key); + trace('finding ${key} - ${data.bitmap}'); + return data; + } + #end + + inline static public function getPackerAtlas(key:String, ?library:String, ?isCharacter:Bool = false) + { + var usecahce = FlxG.save.data.cacheImages; + #if !cpp + usecahce = false; + #end + if (isCharacter) + if (usecahce) + #if cpp + return FlxAtlasFrames.fromSpriteSheetPacker(imageCached(key), file('images/characters/$key.txt', library)); + #else + return null; + #end + else + return FlxAtlasFrames.fromSpriteSheetPacker(image('characters/$key'), file('images/characters/$key.txt', library)); return FlxAtlasFrames.fromSpriteSheetPacker(image(key, library), file('images/$key.txt', library)); } } diff --git a/source/PauseSubState.hx b/source/PauseSubState.hx index 08cfe98..747c7cb 100644 --- a/source/PauseSubState.hx +++ b/source/PauseSubState.hx @@ -1,5 +1,6 @@ package; +import flixel.input.gamepad.FlxGamepad; import openfl.Lib; #if windows import llua.Lua; @@ -59,7 +60,7 @@ class PauseSubState extends MusicBeatSubstate add(levelInfo); var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, "", 32); - levelDifficulty.text += CoolUtil.difficultyString(); + levelDifficulty.text += CoolUtil.difficultyFromInt(PlayState.storyDifficulty).toUpperCase(); levelDifficulty.scrollFactor.set(); levelDifficulty.setFormat(Paths.font('vcr.ttf'), 32); levelDifficulty.updateHitbox(); @@ -108,13 +109,22 @@ class PauseSubState extends MusicBeatSubstate 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 gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + var upPcontroller:Bool = false; + var downPcontroller:Bool = false; + var leftPcontroller:Bool = false; + var rightPcontroller:Bool = false; var oldOffset:Float = 0; + if (gamepad != null && KeyBinds.gamepad) + { + upPcontroller = gamepad.justPressed.DPAD_UP; + downPcontroller = gamepad.justPressed.DPAD_DOWN; + leftPcontroller = gamepad.justPressed.DPAD_LEFT; + rightPcontroller = gamepad.justPressed.DPAD_RIGHT; + } + // pre lowercasing the song name (update) var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase(); switch (songLowercase) { @@ -123,17 +133,23 @@ class PauseSubState extends MusicBeatSubstate } var songPath = 'assets/data/' + songLowercase + '/'; - if (upP) + #if sys + if (PlayState.isSM && !PlayState.isStoryMode) + songPath = PlayState.pathToSm; + #end + + if (controls.UP_P || upPcontroller) { changeSelection(-1); - }else if (downP) + } + else if (controls.DOWN_P || downPcontroller) { changeSelection(1); } #if cpp - else if (leftP) + else if (controls.LEFT_P || leftPcontroller) { oldOffset = PlayState.songOffset; PlayState.songOffset -= 1; @@ -160,7 +176,8 @@ class PauseSubState extends MusicBeatSubstate cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; offsetChanged = true; } - }else if (rightP) + } + else if (controls.RIGHT_P || rightPcontroller) { oldOffset = PlayState.songOffset; PlayState.songOffset += 1; @@ -188,7 +205,7 @@ class PauseSubState extends MusicBeatSubstate } #end - if (accepted) + if (controls.ACCEPT && !FlxG.keys.pressed.ALT) { var daSelected:String = menuItems[curSelected]; @@ -197,6 +214,7 @@ class PauseSubState extends MusicBeatSubstate case "Resume": close(); case "Restart Song": + PlayState.startTime = 0; if (PlayState.instance.useVideo) { GlobalVideo.get().stop(); @@ -205,6 +223,7 @@ class PauseSubState extends MusicBeatSubstate } FlxG.resetState(); case "Exit to menu": + PlayState.startTime = 0; if (PlayState.instance.useVideo) { GlobalVideo.get().stop(); @@ -228,7 +247,10 @@ class PauseSubState extends MusicBeatSubstate if (FlxG.save.data.fpsCap > 290) (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290); - FlxG.switchState(new MainMenuState()); + if (PlayState.isStoryMode) + FlxG.switchState(new StoryMenuState()); + else + FlxG.switchState(new FreeplayState()); } } @@ -249,6 +271,8 @@ class PauseSubState extends MusicBeatSubstate function changeSelection(change:Int = 0):Void { curSelected += change; + + FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); if (curSelected < 0) curSelected = menuItems.length - 1; @@ -272,4 +296,4 @@ class PauseSubState extends MusicBeatSubstate } } } -} \ No newline at end of file +} diff --git a/source/PlayState.hx b/source/PlayState.hx index 39e8b2b..04d16f1 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1,6 +1,22 @@ package; + +import Song.Event; +import openfl.media.Sound; +#if sys +import sys.io.File; +import smTools.SMFile; +#end +import openfl.ui.KeyLocation; +import openfl.events.Event; +import haxe.EnumTools; +import openfl.ui.Keyboard; +import openfl.events.KeyboardEvent; +import Replay.Ana; +import Replay.Analysis; +#if cpp import webm.WebmPlayer; +#end import flixel.input.keyboard.FlxKey; import haxe.Exception; import openfl.geom.Matrix; @@ -11,7 +27,6 @@ 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; @@ -54,7 +69,6 @@ import lime.utils.Assets; import openfl.display.BlendMode; import openfl.display.StageQuality; import openfl.filters.ShaderFilter; - #if windows import Discord.DiscordClient; #end @@ -87,6 +101,7 @@ class PlayState extends MusicBeatState public static var rep:Replay; public static var loadRep:Bool = false; + public static var inResults:Bool = false; public static var noteBools:Array = [false, false, false, false]; @@ -94,7 +109,7 @@ class PlayState extends MusicBeatState var songLength:Float = 0; var kadeEngineWatermark:FlxText; - + #if windows // Discord RPC variables var storyDifficultyText:String = ""; @@ -105,6 +120,12 @@ class PlayState extends MusicBeatState private var vocals:FlxSound; + public static var isSM:Bool = false; + #if sys + public static var sm:SMFile; + public static var pathToSm:String; + #end + public var originalX:Float; public static var dad:Character; @@ -112,9 +133,11 @@ class PlayState extends MusicBeatState 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; @@ -129,34 +152,47 @@ class PlayState extends MusicBeatState private var curSong:String = ""; private var gfSpeed:Int = 1; - public var health:Float = 1; //making public because sethealth doesnt work without it + + 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 iconP1:HealthIcon; // making these public again because i may be stupid + public var iconP2:HealthIcon; // what could go wrong? public var camHUD:FlxCamera; + public var camSustains:FlxCamera; + public var camNotes:FlxCamera; + private var camGame:FlxCamera; + public var cannotDie = false; public static var offsetTesting:Bool = false; + public var isSMFile:Bool = false; + var notesHitArray:Array = []; var currentFrames:Int = 0; + var idleToBeat:Bool = true; // change if bf and dad would idle to the beat of the song + var idleBeat:Int = 4; // how frequently bf and dad would play their idle animation(1 - every beat, 2 - every 2 beats and so on) public var dialogue:Array = ['dad:blah blah blah', 'bf:coolswag']; @@ -181,7 +217,9 @@ class PlayState extends MusicBeatState var wiggleShit:WiggleEffect = new WiggleEffect(); var talking:Bool = true; + public var songScore:Int = 0; + var songScoreDef:Int = 0; var scoreTxt:FlxText; var replayTxt:FlxText; @@ -193,43 +231,64 @@ class PlayState extends MusicBeatState public static var daPixelZoom:Float = 6; public static var theFunne:Bool = true; + var funneEffect:FlxSprite; var inCutscene:Bool = false; + var usedTimeTravel: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); } + // Animation common suffixes + private var dataSuffix:Array = ['LEFT', 'DOWN', 'UP', 'RIGHT']; + private var dataColor:Array = ['purple', 'blue', 'green', 'red']; + public static var startTime = 0.0; + + // API stuff + + public function addObject(object:FlxBasic) + { + add(object); + } + + public function removeObject(object:FlxBasic) + { + remove(object); + } override public function create() { + + FlxG.mouse.visible = false; instance = this; - + if (FlxG.save.data.fpsCap > 290) - (cast (Lib.current.getChildAt(0), Main)).setFPSCap(800); - + (cast(Lib.current.getChildAt(0), Main)).setFPSCap(800); + if (FlxG.sound.music != null) FlxG.sound.music.stop(); @@ -242,27 +301,35 @@ class PlayState extends MusicBeatState } misses = 0; + highestCombo = 0; repPresses = 0; repReleases = 0; - + inResults = false; PlayStateChangeables.useDownscroll = FlxG.save.data.downscroll; PlayStateChangeables.safeFrames = FlxG.save.data.frames; PlayStateChangeables.scrollSpeed = FlxG.save.data.scrollSpeed; PlayStateChangeables.botPlay = FlxG.save.data.botplay; - + PlayStateChangeables.Optimize = FlxG.save.data.optimize; // 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'; + switch (songLowercase) + { + case 'dad-battle': + songLowercase = 'dadbattle'; + case 'philly-nice': + songLowercase = 'philly'; } - + removedVideo = false; #if windows - executeModchart = FileSystem.exists(Paths.lua(songLowercase + "/modchart")); + executeModchart = FileSystem.exists(Paths.lua(songLowercase + "/modchart")); + if (isSM) + executeModchart = FileSystem.exists(pathToSm + "/modchart.lua"); + if (executeModchart) + PlayStateChangeables.Optimize = false; #end #if !cpp executeModchart = false; // FORCE disable for non cpp targets @@ -272,15 +339,7 @@ class PlayState extends MusicBeatState #if windows // Making difficulty text for Discord Rich Presence. - switch (storyDifficulty) - { - case 0: - storyDifficultyText = "Easy"; - case 1: - storyDifficultyText = "Normal"; - case 2: - storyDifficultyText = "Hard"; - } + storyDifficultyText = CoolUtil.difficultyFromInt(storyDifficulty); iconRPC = SONG.player2; @@ -309,17 +368,34 @@ class PlayState extends MusicBeatState 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); + 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; + camSustains = new FlxCamera(); + camSustains.bgColor.alpha = 0; + camNotes = new FlxCamera(); + camNotes.bgColor.alpha = 0; FlxG.cameras.reset(camGame); FlxG.cameras.add(camHUD); + FlxG.cameras.add(camSustains); + FlxG.cameras.add(camNotes); FlxCamera.defaultCameras = [camGame]; @@ -332,9 +408,51 @@ class PlayState extends MusicBeatState 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); + if (SONG.eventObjects == null) + { + SONG.eventObjects = [new Song.Event("Init BPM",0,SONG.bpm,"BPM Change")]; + } - //dialogue shit + + TimingStruct.clearTimings(); + + var convertedStuff:Array = []; + + var currentIndex = 0; + for (i in SONG.eventObjects) + { + var name = Reflect.field(i,"name"); + var type = Reflect.field(i,"type"); + var pos = Reflect.field(i,"position"); + var value = Reflect.field(i,"value"); + + if (type == "BPM Change") + { + var beat:Float = pos; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + currentIndex++; + } + convertedStuff.push(new Song.Event(name,pos,value,type)); + } + + SONG.eventObjects = convertedStuff; + + 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': @@ -355,315 +473,389 @@ class PlayState extends MusicBeatState "Only then I will even CONSIDER letting you\ndate my daughter!" ]; case 'senpai': - dialogue = CoolUtil.coolTextFile(Paths.txt('senpai/senpaiDialogue')); + dialogue = CoolUtil.coolTextFile(Paths.txt('data/senpai/senpaiDialogue')); case 'roses': - dialogue = CoolUtil.coolTextFile(Paths.txt('roses/rosesDialogue')); + dialogue = CoolUtil.coolTextFile(Paths.txt('data/roses/rosesDialogue')); case 'thorns': - dialogue = CoolUtil.coolTextFile(Paths.txt('thorns/thornsDialogue')); + dialogue = CoolUtil.coolTextFile(Paths.txt('data/thorns/thornsDialogue')); } - //defaults if no stage was found in chart + // 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) + if (SONG.stage == null) { - case 'halloween': + switch (storyWeek) { - 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': + case 2: + stageCheck = 'halloween'; + case 3: + stageCheck = 'philly'; + case 4: + stageCheck = 'limo'; + case 5: + if (songLowercase == 'winter-horrorland') { - 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); + stageCheck = 'mallEvil'; } - - for (i in 0...5) + 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; + } + + if (!PlayStateChangeables.Optimize) + { + 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'); + if(FlxG.save.data.antialiasing) + { + 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; + if(FlxG.save.data.antialiasing) + { + light.antialiasing = true; + } phillyCityLights.add(light); - } + } - var streetBehind:FlxSprite = new FlxSprite(-40, 50).loadGraphic(Paths.image('philly/behindTrain','week3')); - add(streetBehind); + 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) + 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'); + if(FlxG.save.data.antialiasing) + { + 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')); + if(FlxG.save.data.antialiasing) + { + 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); + if(FlxG.save.data.antialiasing) + { + 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')); + if(FlxG.save.data.antialiasing) + { + 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')); + if(FlxG.save.data.antialiasing) + { + 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); + if(FlxG.save.data.antialiasing) + { + 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; + if(FlxG.save.data.antialiasing) + { + 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); + if(FlxG.save.data.antialiasing) + { + 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')); + if(FlxG.save.data.antialiasing) + { + 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 overlayShit:FlxSprite = new FlxSprite(-500, -600).loadGraphic(Paths.image('limo/limoOverlay','week4')); - overlayShit.alpha = 0.5; - // add(overlayShit); + var evilTree:FlxSprite = new FlxSprite(300, -300).loadGraphic(Paths.image('christmas/evilTree', 'week5')); + if(FlxG.save.data.antialiasing) + { + evilTree.antialiasing = true; + } + evilTree.scrollFactor.set(0.2, 0.2); + add(evilTree); - // 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 evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow", 'week5')); + if(FlxG.save.data.antialiasing) + { + evilSnow.antialiasing = true; + } + add(evilSnow); } + case 'school': + { + curStage = 'school'; + // defaultCamZoom = 0.9; - 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 bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky', 'week6')); + bgSky.scrollFactor.set(0.1, 0.1); + add(bgSky); - 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); + var repositionShit = -200; - 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 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 fgSnow:FlxSprite = new FlxSprite(-600, 700).loadGraphic(Paths.image('christmas/fgSnow','week5')); - fgSnow.active = false; - fgSnow.antialiasing = true; - add(fgSnow); + var fgTrees:FlxSprite = new FlxSprite(repositionShit + 170, 130).loadGraphic(Paths.image('weeb/weebTreesBack', 'week6')); + fgTrees.scrollFactor.set(0.9, 0.9); + add(fgTrees); - 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 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 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 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 evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow",'week5')); - evilSnow.antialiasing = true; - add(evilSnow); - } - case 'school': - { - curStage = 'school'; + var widShit = Std.int(bgSky.width * 6); - // defaultCamZoom = 0.9; + 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); - var bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky','week6')); - bgSky.scrollFactor.set(0.1, 0.1); - add(bgSky); + fgTrees.updateHitbox(); + bgSky.updateHitbox(); + bgSchool.updateHitbox(); + bgStreet.updateHitbox(); + bgTrees.updateHitbox(); + treeLeaves.updateHitbox(); - var repositionShit = -200; + bgGirls = new BackgroundGirls(-100, 190); + bgGirls.scrollFactor.set(0.9, 0.9); - 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 (songLowercase == 'roses') { - if(FlxG.save.data.distractions){ + if (FlxG.save.data.distractions) + { bgGirls.getScared(); } } - bgGirls.setGraphicSize(Std.int(bgGirls.width * daPixelZoom)); - bgGirls.updateHitbox(); - if(FlxG.save.data.distractions){ - add(bgGirls); + bgGirls.setGraphicSize(Std.int(bgGirls.width * daPixelZoom)); + bgGirls.updateHitbox(); + if (FlxG.save.data.distractions) + { + add(bgGirls); + } } - } - case 'schoolEvil': - { - curStage = 'schoolEvil'; + case 'schoolEvil': + { + curStage = 'schoolEvil'; - var waveEffectBG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 3, 2); - var waveEffectFG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 5, 2); + if (!PlayStateChangeables.Optimize) + { + 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 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); + 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)); @@ -678,96 +870,86 @@ class PlayState extends MusicBeatState wiggleShit.waveAmplitude = 0.01; wiggleShit.waveFrequency = 60; wiggleShit.waveSpeed = 0.8; - */ + */ - // bg.shader = wiggleShit.shader; - // fg.shader = wiggleShit.shader; + // 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': - { + /* + 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); + */ + } + default: + { defaultCamZoom = 0.9; curStage = 'stage'; var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback')); - bg.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + 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; + if(FlxG.save.data.antialiasing) + { + 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; + if(FlxG.save.data.antialiasing) + { + 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 + // defaults if no gf was found in chart var gfCheck:String = 'gf'; - - if (SONG.gfVersion == null) { - switch(storyWeek) + + if (SONG.gfVersion == null) + { + switch (storyWeek) { - case 4: gfCheck = 'gf-car'; - case 5: gfCheck = 'gf-christmas'; - case 6: gfCheck = 'gf-pixel'; + case 4: + gfCheck = 'gf-car'; + case 5: + gfCheck = 'gf-christmas'; + case 6: + gfCheck = 'gf-pixel'; } - } else {gfCheck = SONG.gfVersion;} + } + else + { + gfCheck = SONG.gfVersion; + } var curGf:String = ''; switch (gfCheck) @@ -822,13 +1004,24 @@ class PlayState extends MusicBeatState dad.y += 360; camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); case 'spirit': + if (FlxG.save.data.distractions) + { + // trailArea.scrollFactor.set(); + if (!PlayStateChangeables.Optimize) + { + 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); + } + 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 @@ -837,7 +1030,8 @@ class PlayState extends MusicBeatState case 'limo': boyfriend.y -= 220; boyfriend.x += 260; - if(FlxG.save.data.distractions){ + if (FlxG.save.data.distractions) + { resetFastCar(); add(fastCar); } @@ -854,34 +1048,28 @@ class PlayState extends MusicBeatState 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); + if (!PlayStateChangeables.Optimize) + { + add(gf); - // Shitty layering but whatev it works LOL - if (curStage == 'limo') - add(limo); + // Shitty layering but whatev it works LOL + if (curStage == 'limo') + add(limo); + + add(dad); + add(boyfriend); + } - add(dad); - add(boyfriend); if (loadRep) { - FlxG.watch.addQuick('rep rpesses',repPresses); - FlxG.watch.addQuick('rep releases',repReleases); + FlxG.watch.addQuick('rep rpesses', repPresses); + FlxG.watch.addQuick('rep releases', repReleases); // FlxG.watch.addQuick('Queued',inputsQueued); PlayStateChangeables.useDownscroll = rep.replay.isDownscroll; @@ -900,10 +1088,10 @@ class PlayState extends MusicBeatState 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; @@ -913,6 +1101,9 @@ class PlayState extends MusicBeatState playerStrums = new FlxTypedGroup(); cpuStrums = new FlxTypedGroup(); + generateStaticArrows(0); + generateStaticArrows(1); + // startCountdown(); if (SONG.song == null) @@ -938,7 +1129,7 @@ class PlayState extends MusicBeatState add(camFollow); - FlxG.camera.follow(camFollow, LOCKON, 0.04 * (30 / (cast (Lib.current.getChildAt(0), Main)).getFPS())); + 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()); @@ -948,28 +1139,28 @@ class PlayState extends MusicBeatState 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) - 20,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]; - } + { + 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) @@ -986,8 +1177,13 @@ class PlayState extends MusicBeatState add(healthBar); // Add Kade Engine watermark - kadeEngineWatermark = new FlxText(4,healthBarBG.y + 50,0,SONG.song + " " + (storyDifficulty == 2 ? "Hard" : storyDifficulty == 1 ? "Normal" : "Easy") + (Main.watermarks ? " - KE " + MainMenuState.kadeEngineVer : ""), 16); - kadeEngineWatermark.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); + 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); @@ -1000,15 +1196,15 @@ class PlayState extends MusicBeatState originalX = scoreTxt.x; - scoreTxt.scrollFactor.set(); - - scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, FlxTextAlign.CENTER, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); + + 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 = 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(); @@ -1017,12 +1213,14 @@ class PlayState extends MusicBeatState 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 = 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); + if (PlayStateChangeables.botPlay && !loadRep) + add(botPlayState); iconP1 = new HealthIcon(SONG.player1, true); iconP1.y = healthBar.y - (iconP1.height / 2); @@ -1055,12 +1253,12 @@ class PlayState extends MusicBeatState // cameras = [FlxG.cameras.list[1]]; startingSong = true; - + trace('starting'); if (isStoryMode) { - switch (StringTools.replace(curSong," ", "-").toLowerCase()) + 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); @@ -1103,16 +1301,14 @@ class PlayState extends MusicBeatState } else { - switch (curSong.toLowerCase()) - { - default: - startCountdown(); - } + startCountdown(); } if (!loadRep) rep = new Replay("na"); + FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, handleInput); + FlxG.stage.addEventListener(KeyboardEvent.KEY_UP, releaseInput); super.create(); } @@ -1133,7 +1329,8 @@ class PlayState extends MusicBeatState senpaiEvil.updateHitbox(); senpaiEvil.screenCenter(); - if (StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'roses' || StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'thorns') + if (StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'roses' + || StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'thorns') { remove(black); @@ -1213,21 +1410,53 @@ class PlayState extends MusicBeatState { inCutscene = false; - generateStaticArrows(0); - generateStaticArrows(1); + appearStaticArrows(); + //generateStaticArrows(0); + //generateStaticArrows(1); + if (startTime != 0) + { + var toBeRemoved = []; + for(i in 0...unspawnNotes.length) + { + var dunceNote:Note = unspawnNotes[i]; + + if (dunceNote.strumTime - startTime <= 0) + toBeRemoved.push(dunceNote); + else if (dunceNote.strumTime - startTime < 3500) + { + notes.add(dunceNote); + + if (dunceNote.mustPress) + dunceNote.y = (playerStrums.members[Math.floor(Math.abs(dunceNote.noteData))].y + + 0.45 * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + 2)) - dunceNote.noteYOff; + else + dunceNote.y = (strumLineNotes.members[Math.floor(Math.abs(dunceNote.noteData))].y + + 0.45 * (startTime - dunceNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, + 2)) - dunceNote.noteYOff; + toBeRemoved.push(dunceNote); + } + } + + for(i in toBeRemoved) + unspawnNotes.remove(i); + } #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'; + switch (songLowercase) + { + case 'dad-battle': + songLowercase = 'dadbattle'; + case 'philly-nice': + songLowercase = 'philly'; } if (executeModchart) { luaModchart = ModchartState.createModchartState(); - luaModchart.executeState('start',[songLowercase]); + luaModchart.executeState('start', [songLowercase]); } #end @@ -1246,16 +1475,8 @@ class PlayState extends MusicBeatState 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' - ]); + 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 = ""; @@ -1264,8 +1485,10 @@ class PlayState extends MusicBeatState { if (value == curStage) { + trace(value + " - " + curStage); introAlts = introAssets.get(value); - altSuffix = '-pixel'; + if (curStage.contains('school')) + altSuffix = '-pixel'; } } @@ -1340,6 +1563,170 @@ class PlayState extends MusicBeatState var lastReportedPlayheadPosition:Int = 0; var songTime:Float = 0; + private function getKey(charCode:Int):String + { + for (key => value in FlxKey.fromStringMap) + { + if (charCode == value) + return key; + } + return null; + } + + var keys = [false, false, false, false]; + + private function releaseInput(evt:KeyboardEvent):Void // handles releases + { + @:privateAccess + var key = FlxKey.toStringMap.get(Keyboard.__convertKeyCode(evt.keyCode)); + + var binds:Array = [ + FlxG.save.data.leftBind, + FlxG.save.data.downBind, + FlxG.save.data.upBind, + FlxG.save.data.rightBind + ]; + + var data = -1; + + switch (evt.keyCode) // arrow keys + { + case 37: + data = 0; + case 40: + data = 1; + case 38: + data = 2; + case 39: + data = 3; + } + + for (i in 0...binds.length) // binds + { + if (binds[i].toLowerCase() == key.toLowerCase()) + data = i; + } + + if (data == -1) + return; + + keys[data] = false; + } + + private function handleInput(evt:KeyboardEvent):Void + { // this actually handles press inputs + + if (PlayStateChangeables.botPlay || loadRep || paused) + return; + + // first convert it from openfl to a flixel key code + // then use FlxKey to get the key's name based off of the FlxKey dictionary + // this makes it work for special characters + + @:privateAccess + var key = FlxKey.toStringMap.get(Keyboard.__convertKeyCode(evt.keyCode)); + + var binds:Array = [ + FlxG.save.data.leftBind, + FlxG.save.data.downBind, + FlxG.save.data.upBind, + FlxG.save.data.rightBind + ]; + + var data = -1; + + switch (evt.keyCode) // arrow keys + { + case 37: + data = 0; + case 40: + data = 1; + case 38: + data = 2; + case 39: + data = 3; + } + + for (i in 0...binds.length) // binds + { + if (binds[i].toLowerCase() == key.toLowerCase()) + data = i; + } + if (data == -1) + { + trace("couldn't find a keybind with the code " + key); + return; + } + if (keys[data]) + { + trace("ur already holding " + key); + return; + } + + keys[data] = true; + + var ana = new Ana(Conductor.songPosition, null, false, "miss", data); + + var dataNotes = []; + notes.forEachAlive(function(daNote:Note) + { + if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit && daNote.noteData == data) + dataNotes.push(daNote); + }); // Collect notes that can be hit + + dataNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime)); // sort by the earliest note + + if (dataNotes.length != 0) + { + var coolNote = null; + + for (i in dataNotes) + if (!i.isSustainNote) + { + coolNote = i; + break; + } + + if (coolNote == null) // Note is null, which means it's probably a sustain note. Update will handle this (HOPEFULLY???) + { + return; + } + + if (dataNotes.length > 1) // stacked notes or really close ones + { + for (i in 0...dataNotes.length) + { + if (i == 0) // skip the first note + continue; + + var note = dataNotes[i]; + + if (!note.isSustainNote && (note.strumTime - coolNote.strumTime) < 2) + { + trace('found a stacked/really close note ' + (note.strumTime - coolNote.strumTime)); + // just fuckin remove it since it's a stacked note and shouldn't be there + note.kill(); + notes.remove(note, true); + note.destroy(); + } + } + } + + goodNoteHit(coolNote); + var noteDiff:Float = -(coolNote.strumTime - Conductor.songPosition); + ana.hit = true; + ana.hitJudge = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000)); + ana.nearestNote = [coolNote.strumTime, coolNote.noteData, coolNote.sustainLength]; + } + else if (!FlxG.save.data.ghost && songStarted) + { + noteMiss(data, null); + ana.hit = false; + ana.hitJudge = "shit"; + ana.nearestNote = []; + health -= 0.10; + } + } var songStarted = false; @@ -1352,7 +1739,20 @@ class PlayState extends MusicBeatState if (!paused) { + #if sys + if (!isStoryMode && isSM) + { + trace("Loading " + pathToSm + "/" + sm.header.MUSIC); + var bytes = File.getBytes(pathToSm + "/" + sm.header.MUSIC); + var sound = new Sound(); + sound.loadCompressedDataFromByteArray(bytes.getData(), bytes.length); + FlxG.sound.playMusic(sound); + } + else + FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); + #else FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); + #end } FlxG.sound.music.onComplete = endSong; @@ -1369,22 +1769,25 @@ class PlayState extends MusicBeatState songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar')); if (PlayStateChangeables.useDownscroll) - songPosBG.y = FlxG.height * 0.9 + 45; + 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 = 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) - 20,songPosBG.y,0,SONG.song, 16); + 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.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); songName.scrollFactor.set(); add(songName); @@ -1392,26 +1795,49 @@ class PlayState extends MusicBeatState songPosBar.cameras = [camHUD]; songName.cameras = [camHUD]; } - + // Song check real quick - switch(curSong) + switch (curSong) { - case 'Bopeebo' | 'Philly Nice' | 'Blammed' | 'Cocoa' | 'Eggnog': allowedToHeadbang = true; - default: allowedToHeadbang = false; + 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); + DiscordClient.changePresence(detailsText + + " " + + SONG.song + + " (" + + storyDifficultyText + + ") " + + Ratings.GenerateLetterRank(accuracy), + "\nAcc: " + + HelperFunctions.truncateFloat(accuracy, 2) + + "% | Score: " + + songScore + + " | Misses: " + + misses, iconRPC); #end + + FlxG.sound.music.time = startTime; + vocals.time = startTime; + Conductor.songPosition = startTime; + startTime = 0; + + for(i in 0...unspawnNotes.length) + if (unspawnNotes[i].strumTime < startTime) + unspawnNotes.remove(unspawnNotes[i]); } var debugNum:Int = 0; - private function generateSong(dataPath:String):Void + public function generateSong(dataPath:String):Void { // FlxG.log.add(ChartParser.parse()); @@ -1420,10 +1846,17 @@ class PlayState extends MusicBeatState curSong = songData.song; + #if sys + if (SONG.needsVoices && !isSM) + vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song)); + else + vocals = new FlxSound(); + #else if (SONG.needsVoices) vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song)); else vocals = new FlxSound(); + #end trace('loaded vocals'); @@ -1441,33 +1874,45 @@ class PlayState extends MusicBeatState // 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'; - } + // 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 songPath = 'assets/data/' + songLowercase + '/'; + + #if sys + if (isSM && !isStoryMode) + songPath = pathToSm; + #end + + for (file in sys.FileSystem.readDirectory(songPath)) + { + var path = haxe.io.Path.join([songPath, file]); + if (!sys.FileSystem.isDirectory(path)) { - var path = haxe.io.Path.join([songPath, file]); - if(!sys.FileSystem.isDirectory(path)) + if (path.endsWith('.offset')) { - 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', ''); - } + 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); @@ -1493,6 +1938,10 @@ class PlayState extends MusicBeatState oldNote = null; var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote); + + if (!gottaHitNote && PlayStateChangeables.Optimize) + continue; + swagNote.sustainLength = songNotes[2]; swagNote.scrollFactor.set(0, 0); @@ -1501,6 +1950,11 @@ class PlayState extends MusicBeatState susLength = susLength / Conductor.stepCrochet; unspawnNotes.push(swagNote); + if (susLength > 0) + swagNote.isParent = true; + + var type = 0; + for (susNote in 0...Math.floor(susLength)) { oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)]; @@ -1515,6 +1969,11 @@ class PlayState extends MusicBeatState { sustainNote.x += FlxG.width / 2; // general offset } + + sustainNote.parent = swagNote; + swagNote.children.push(sustainNote); + sustainNote.spotInLine = type; + type++; } swagNote.mustPress = gottaHitNote; @@ -1523,9 +1982,6 @@ class PlayState extends MusicBeatState { swagNote.x += FlxG.width / 2; // general offset } - else - { - } } daBeats += 1; } @@ -1550,12 +2006,24 @@ class PlayState extends MusicBeatState // FlxG.log.add(i); var babyArrow:FlxSprite = new FlxSprite(0, strumLine.y); - //defaults if no noteStyle was found in chart + // 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;} + + if (PlayStateChangeables.Optimize && player == 0) + continue; + + if (SONG.noteStyle == null) + { + switch (storyWeek) + { + case 6: + noteTypeCheck = 'pixel'; + } + } + else + { + noteTypeCheck = SONG.noteStyle; + } switch (noteTypeCheck) { @@ -1593,83 +2061,37 @@ class PlayState extends MusicBeatState 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)) + + default: + babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets'); + for (j in 0...4) + { + babyArrow.animation.addByPrefix(dataColor[j], 'arrow' + dataSuffix[j]); + } + + var lowerDir:String = dataSuffix[i].toLowerCase(); + + babyArrow.animation.addByPrefix('static', 'arrow' + dataSuffix[i]); + babyArrow.animation.addByPrefix('pressed', lowerDir + ' press', 24, false); + babyArrow.animation.addByPrefix('confirm', lowerDir + ' confirm', 24, false); + + babyArrow.x += Note.swagWidth * i; + + if(FlxG.save.data.antialiasing) { - 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.antialiasing = true; } + babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7)); } babyArrow.updateHitbox(); babyArrow.scrollFactor.set(); + babyArrow.alpha = 0; if (!isStoryMode) { babyArrow.y -= 10; - babyArrow.alpha = 0; + //babyArrow.alpha = 0; FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)}); } @@ -1686,16 +2108,28 @@ class PlayState extends MusicBeatState babyArrow.animation.play('static'); babyArrow.x += 50; babyArrow.x += ((FlxG.width / 2) * player); - + + if (PlayStateChangeables.Optimize) + babyArrow.x -= 275; + cpuStrums.forEach(function(spr:FlxSprite) - { - spr.centerOffsets(); //CPU arrows start out slightly off-center + { + spr.centerOffsets(); // CPU arrows start out slightly off-center }); strumLineNotes.add(babyArrow); } } + private function appearStaticArrows():Void + { + strumLineNotes.forEach(function(babyArrow:FlxSprite) + { + if (isStoryMode) + babyArrow.alpha = 1; + }); + } + function tweenCamIn():Void { FlxTween.tween(FlxG.camera, {zoom: 1.3}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut}); @@ -1712,7 +2146,18 @@ class PlayState extends MusicBeatState } #if windows - DiscordClient.changePresence("PAUSED on " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "Acc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); + 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; @@ -1737,7 +2182,21 @@ class PlayState extends MusicBeatState #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); + DiscordClient.changePresence(detailsText + + " " + + SONG.song + + " (" + + storyDifficultyText + + ") " + + Ratings.GenerateLetterRank(accuracy), + "\nAcc: " + + HelperFunctions.truncateFloat(accuracy, 2) + + "% | Score: " + + songScore + + " | Misses: " + + misses, iconRPC, true, + songLength + - Conductor.songPosition); } else { @@ -1748,7 +2207,6 @@ class PlayState extends MusicBeatState super.closeSubState(); } - function resyncVocals():Void { @@ -1760,7 +2218,19 @@ class PlayState extends MusicBeatState vocals.play(); #if windows - DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); + DiscordClient.changePresence(detailsText + + " " + + SONG.song + + " (" + + storyDifficultyText + + ") " + + Ratings.GenerateLetterRank(accuracy), + "\nAcc: " + + HelperFunctions.truncateFloat(accuracy, 2) + + "% | Score: " + + songScore + + " | Misses: " + + misses, iconRPC); #end } @@ -1775,41 +2245,104 @@ class PlayState extends MusicBeatState public var stopUpdate = false; public var removedVideo = false; + public var currentBPM = 0; + + public var updateFrame = 0; + override public function update(elapsed:Float) { #if !debug perfectMode = false; #end + if (updateFrame == 4) + { + TimingStruct.clearTimings(); + + var currentIndex = 0; + for (i in SONG.eventObjects) + { + if (i.type == "BPM Change") + { + var beat:Float = i.position; + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,i.value,endBeat, 0); // offset in this case = start time since we don't have a offset + + if (currentIndex != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + currentIndex++; + } + } + updateFrame++; + } + else if (updateFrame != 5) + updateFrame++; + + + var timingSeg = TimingStruct.getTimingAtTimestamp(Conductor.songPosition); + + if (timingSeg != null) + { + + var timingSegBpm = timingSeg.bpm; + + if (timingSegBpm != Conductor.bpm) + { + trace("BPM CHANGE to " + timingSegBpm); + Conductor.changeBPM(timingSegBpm, false); + } + + } + + var newScroll = PlayStateChangeables.scrollSpeed; + + for(i in SONG.eventObjects) + { + switch(i.type) + { + case "Scroll Speed Change": + if (i.position < curDecimalBeat) + newScroll = i.value; + } + } + + PlayStateChangeables.scrollSpeed = newScroll; + 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 (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('songPos', Conductor.songPosition); luaModchart.setVar('hudZoom', camHUD.zoom); - luaModchart.setVar('cameraZoom',FlxG.camera.zoom); + luaModchart.setVar('curBeat', HelperFunctions.truncateFloat(curDecimalBeat,3)); + luaModchart.setVar('cameraZoom', FlxG.camera.zoom); luaModchart.executeState('update', [elapsed]); - for (i in luaWiggles) + for (key => value in luaModchart.luaWiggles) { trace('wiggle le gaming'); - i.update(elapsed); + value.update(elapsed); } /*for (i in 0...strumLineNotes.length) { @@ -1820,9 +2353,9 @@ class PlayState extends MusicBeatState }*/ FlxG.camera.angle = luaModchart.getVar('cameraAngle', 'float'); - camHUD.angle = luaModchart.getVar('camHudAngle','float'); + camHUD.angle = luaModchart.getVar('camHudAngle', 'float'); - if (luaModchart.getVar("showOnlyStrums",'bool')) + if (luaModchart.getVar("showOnlyStrums", 'bool')) { healthBarBG.visible = false; kadeEngineWatermark.visible = false; @@ -1841,8 +2374,8 @@ class PlayState extends MusicBeatState scoreTxt.visible = true; } - var p1 = luaModchart.getVar("strumLine1Visible",'bool'); - var p2 = luaModchart.getVar("strumLine2Visible",'bool'); + var p1 = luaModchart.getVar("strumLine1Visible", 'bool'); + var p2 = luaModchart.getVar("strumLine2Visible", 'bool'); for (i in 0...4) { @@ -1851,14 +2384,13 @@ class PlayState extends MusicBeatState 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; + var balls = notesHitArray.length - 1; while (balls >= 0) { var cock:Date = notesHitArray[balls]; @@ -1874,17 +2406,12 @@ class PlayState extends MusicBeatState } if (FlxG.keys.justPressed.NINE) - { - if (iconP1.animation.curAnim.name == 'bf-old') - iconP1.animation.play(SONG.player1); - else - iconP1.animation.play('bf-old'); - } + iconP1.swapOldIcon(); switch (curStage) { case 'philly': - if (trainMoving) + if (trainMoving && !PlayStateChangeables.Optimize) { trainFrameTiming += elapsed; @@ -1899,13 +2426,13 @@ class PlayState extends MusicBeatState super.update(elapsed); - scoreTxt.text = Ratings.CalculateRanking(songScore,songScoreDef,nps,maxNPS,accuracy); + 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) + if (controls.PAUSE && startedCountdown && canPause && !cannotDie) { persistentUpdate = false; persistentDraw = true; @@ -1924,17 +2451,22 @@ class PlayState extends MusicBeatState 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; - } + { + GlobalVideo.get().stop(); + remove(videoSprite); + #if sys + FlxG.stage.window.onFocusOut.remove(focusOut); + FlxG.stage.window.onFocusIn.remove(focusIn); + #end + removedVideo = true; + } + cannotDie = true; #if windows DiscordClient.changePresence("Chart Editor", null, null, true); #end FlxG.switchState(new ChartingState()); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleInput); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, releaseInput); #if windows if (luaModchart != null) { @@ -1974,18 +2506,20 @@ class PlayState extends MusicBeatState FlxG.switchState(new Charting()); */ #if debug - if (FlxG.keys.justPressed.EIGHT) + 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; - } + { + 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)); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleInput); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, releaseInput); #if windows if (luaModchart != null) { @@ -1998,6 +2532,8 @@ class PlayState extends MusicBeatState if (FlxG.keys.justPressed.ZERO) { FlxG.switchState(new AnimationDebug(SONG.player1)); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleInput); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, releaseInput); #if windows if (luaModchart != null) { @@ -2006,7 +2542,45 @@ class PlayState extends MusicBeatState } #end } + + if(FlxG.keys.justPressed.TWO) { //Go 10 seconds into the future, credit: Shadow Mario#9396 + if (!usedTimeTravel && Conductor.songPosition + 10000 < FlxG.sound.music.length) + { + usedTimeTravel = true; + FlxG.sound.music.pause(); + vocals.pause(); + Conductor.songPosition += 10000; + notes.forEachAlive(function(daNote:Note) + { + if(daNote.strumTime - 500 < Conductor.songPosition) { + daNote.active = false; + daNote.visible = false; + + daNote.kill(); + notes.remove(daNote, true); + daNote.destroy(); + } + }); + for (i in 0...unspawnNotes.length) { + var daNote:Note = unspawnNotes[0]; + if(daNote.strumTime - 500 >= Conductor.songPosition) { + break; + } + unspawnNotes.splice(unspawnNotes.indexOf(daNote), 1); + } + + FlxG.sound.music.time = Conductor.songPosition; + FlxG.sound.music.play(); + + vocals.time = Conductor.songPosition; + vocals.play(); + new FlxTimer().start(0.5, function(tmr:FlxTimer) + { + usedTimeTravel = false; + }); + } + } #end if (startingSong) @@ -2023,8 +2597,8 @@ class PlayState extends MusicBeatState // Conductor.songPosition = FlxG.sound.music.time; Conductor.songPosition += FlxG.elapsed * 1000; /*@:privateAccess - { - FlxG.sound.music._channel. + { + FlxG.sound.music._channel. }*/ songPositionBar = Conductor.songPosition; @@ -2049,104 +2623,116 @@ class PlayState extends MusicBeatState if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null) { // Make sure Girlfriend cheers only for certain songs - if(allowedToHeadbang) + 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') + 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) + 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) + // General duration of the song + if (curBeat < 250) { - if(curBeat % 16 == 8) + // Beats to skip or to stop GF from cheering + if (curBeat != 184 && curBeat != 216) { - // Just a garantee that it'll trigger just once - if(!triggeredAlready) + if (curBeat % 16 == 8) { - gf.playAnim('cheer'); - triggeredAlready = true; + // Just a garantee that it'll trigger just once + if (!triggeredAlready) + { + gf.playAnim('cheer'); + triggeredAlready = true; + } } - }else triggeredAlready = false; + else + triggeredAlready = false; + } } } - } case 'Bopeebo': - { - // Where it starts || where it ends - if(curBeat > 5 && curBeat < 130) { - if(curBeat % 8 == 7) + // Where it starts || where it ends + if (curBeat > 5 && curBeat < 130) { - if(!triggeredAlready) + if (curBeat % 8 == 7) { - gf.playAnim('cheer'); - triggeredAlready = true; + if (!triggeredAlready) + { + gf.playAnim('cheer'); + triggeredAlready = true; + } } - }else triggeredAlready = false; + else + triggeredAlready = false; + } } - } case 'Blammed': - { - if(curBeat > 30 && curBeat < 190) { - if(curBeat < 90 || curBeat > 128) + if (curBeat > 30 && curBeat < 190) { - if(curBeat % 4 == 2) + if (curBeat < 90 || curBeat > 128) { - if(!triggeredAlready) + if (curBeat % 4 == 2) { - gf.playAnim('cheer'); - triggeredAlready = true; + 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; } - }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); + 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) @@ -2169,18 +2755,12 @@ class PlayState extends MusicBeatState switch (dad.curCharacter) { - case 'mom': + case 'mom' | 'mom-car': camFollow.y = dad.getMidpoint().y; - case 'senpai': - camFollow.y = dad.getMidpoint().y - 430; - camFollow.x = dad.getMidpoint().x - 100; - case 'senpai-angry': + case 'senpai' | '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) @@ -2223,6 +2803,9 @@ class PlayState extends MusicBeatState camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95); } + FlxG.watch.addQuick("curBPM", Conductor.bpm); + FlxG.watch.addQuick("Closest Note", (unspawnNotes.length != 0 ? unspawnNotes[0].strumTime - Conductor.songPosition : "No note")); + FlxG.watch.addQuick("beatShit", curBeat); FlxG.watch.addQuick("stepShit", curStep); @@ -2256,48 +2839,75 @@ class PlayState extends MusicBeatState } } - if (health <= 0) + if (health <= 0 && !cannotDie) { - boyfriend.stunned = true; + if (!usedTimeTravel) + { + boyfriend.stunned = true; - persistentUpdate = false; - persistentDraw = false; - paused = true; + persistentUpdate = false; + persistentDraw = false; + paused = true; - vocals.stop(); - FlxG.sound.music.stop(); + vocals.stop(); + FlxG.sound.music.stop(); - openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + 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 + #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)); + // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + } + else + health = 1; } - if (FlxG.save.data.resetButton) + if (!inCutscene && FlxG.save.data.resetButton) { - if(FlxG.keys.justPressed.R) - { - boyfriend.stunned = true; + 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)); - } + 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) @@ -2306,6 +2916,10 @@ class PlayState extends MusicBeatState { var dunceNote:Note = unspawnNotes[0]; notes.add(dunceNote); + if (!dunceNote.isSustainNote) + dunceNote.cameras = [camNotes]; + else + dunceNote.cameras = [camSustains]; var index:Int = unspawnNotes.indexOf(dunceNote); unspawnNotes.splice(index, 1); @@ -2313,219 +2927,302 @@ class PlayState extends MusicBeatState } if (generatedMusic) + { + var holdArray:Array = [controls.LEFT, controls.DOWN, controls.UP, controls.RIGHT]; + + notes.forEachAlive(function(daNote:Note) { - 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; + } - // instead of doing stupid y > FlxG.height - // we be men and actually calculate the time :) - if (daNote.tooLate) + if (!daNote.modifiedByLua) + { + if (PlayStateChangeables.useDownscroll) { - daNote.active = false; - daNote.visible = false; - } - else - { - daNote.visible = true; - daNote.active = true; - } - - if (!daNote.modifiedByLua) + 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)) - daNote.noteYOff; + 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)) - daNote.noteYOff; + if (daNote.isSustainNote) { - if (PlayStateChangeables.useDownscroll) + // 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.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) + 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)) { - // 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; - } + // 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 - { - 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) + 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)) + daNote.noteYOff; + 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)) + daNote.noteYOff; + 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)) { - // im tired and lazy this sucks I know i'm dumb - if (findByTime(daNote.strumTime) != null) - totalNotesHit += 1; + // 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'; + } + + // Accessing the animation name directly to play it + var singData:Int = Std.int(Math.abs(daNote.noteData)); + dad.playAnim('sing' + dataSuffix[singData] + 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.modAngle = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].angle; + if (daNote.sustainActive) + daNote.alpha = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].alpha; + daNote.modAngle = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].angle; + } + 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.modAngle = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].angle; + if (daNote.sustainActive) + daNote.alpha = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].alpha; + daNote.modAngle = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].angle; + } + + if (daNote.isSustainNote) + { + daNote.x += daNote.width / 2 + 20; + if (PlayState.curStage.startsWith('school')) + daNote.x -= 11; + } + + // 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 + { + if (!daNote.isSustainNote) + health -= 0.10; + vocals.volume = 0; + if (theFunne && !daNote.isSustainNote) + noteMiss(daNote.noteData, daNote); + if (daNote.isParent) + { + health -= 0.20; // give a health punishment for failing a LN + trace("hold fell over at the start"); + for (i in daNote.children) + { + i.alpha = 0.3; + i.sustainActive = false; + } + } else { - health -= 0.075; - vocals.volume = 0; - if (theFunne) - noteMiss(daNote.noteData, daNote); + if (!daNote.wasGoodHit + && daNote.isSustainNote + && daNote.sustainActive + && daNote.spotInLine != daNote.parent.children.length) + { + health -= 0.20; // give a health punishment for failing a LN + trace("hold fell over at " + daNote.spotInLine); + for (i in daNote.parent.children) + { + i.alpha = 0.3; + i.sustainActive = false; + } + if (daNote.parent.wasGoodHit) + misses++; + updateAccuracy(); + } + } + } + } + else + { + if (!daNote.isSustainNote) + health -= 0.10; + vocals.volume = 0; + if (theFunne && !daNote.isSustainNote) + noteMiss(daNote.noteData, daNote); + + if (daNote.isParent) + { + health -= 0.20; // give a health punishment for failing a LN + trace("hold fell over at the start"); + for (i in daNote.children) + { + i.alpha = 0.3; + i.sustainActive = false; + trace(i.alpha); } } else { - health -= 0.075; - vocals.volume = 0; - if (theFunne) - noteMiss(daNote.noteData, daNote); + if (!daNote.wasGoodHit + && daNote.isSustainNote + && daNote.sustainActive + && daNote.spotInLine != daNote.parent.children.length) + { + health -= 0.20; // give a health punishment for failing a LN + trace("hold fell over at " + daNote.spotInLine); + for (i in daNote.parent.children) + { + i.alpha = 0.3; + i.sustainActive = false; + trace(i.alpha); + } + if (daNote.parent.wasGoodHit) + misses++; + updateAccuracy(); + } } } - - daNote.visible = false; - daNote.kill(); - notes.remove(daNote, true); } - - }); - } + + daNote.visible = false; + daNote.kill(); + notes.remove(daNote, true); + } + }); + } if (FlxG.save.data.cpuStrums) { @@ -2539,10 +3236,9 @@ class PlayState extends MusicBeatState }); } - if (!inCutscene) + if (!inCutscene && songStarted) keyShit(); - #if debug if (FlxG.keys.justPressed.ONE) endSong(); @@ -2551,19 +3247,21 @@ class PlayState extends MusicBeatState function endSong():Void { + FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleInput); + FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, releaseInput); if (useVideo) - { - GlobalVideo.get().stop(); - FlxG.stage.window.onFocusOut.remove(focusOut); - FlxG.stage.window.onFocusIn.remove(focusIn); - PlayState.instance.remove(PlayState.instance.videoSprite); - } + { + 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); + rep.SaveReplay(saveNotes, saveJudge, replayAna); else { PlayStateChangeables.botPlay = false; @@ -2572,7 +3270,7 @@ class PlayState extends MusicBeatState } if (FlxG.save.data.fpsCap > 290) - (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290); + (cast(Lib.current.getChildAt(0), Main)).setFPSCap(290); #if windows if (luaModchart != null) @@ -2592,9 +3290,12 @@ class PlayState extends MusicBeatState // 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'; + switch (songHighscore) + { + case 'Dad-Battle': + songHighscore = 'Dadbattle'; + case 'Philly-Nice': + songHighscore = 'Philly'; } #if !switch @@ -2628,11 +3329,18 @@ class PlayState extends MusicBeatState FlxG.sound.music.stop(); vocals.stop(); if (FlxG.save.data.scoreScreen) + { openSubState(new ResultsScreen()); + new FlxTimer().start(1, function(tmr:FlxTimer) + { + inResults = true; + }); + } else { FlxG.sound.playMusic(Paths.music('freakyMenu')); - FlxG.switchState(new MainMenuState()); + Conductor.changeBPM(102); + FlxG.switchState(new StoryMenuState()); } #if windows @@ -2643,26 +3351,24 @@ class PlayState extends MusicBeatState } #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(); + StoryMenuState.unlockNextWeek(storyWeek); } 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'; + switch (songFormat) + { + case 'Dad-Battle': + songFormat = 'Dadbattle'; + case 'Philly-Nice': + songFormat = 'Philly'; } var poop:String = Highscore.formatSong(songFormat, storyDifficulty); @@ -2685,7 +3391,6 @@ class PlayState extends MusicBeatState FlxTransitionableState.skipNextTransOut = true; prevCamFollow = camFollow; - PlayState.SONG = Song.loadFromJson(poop, PlayState.storyPlaylist[0]); FlxG.sound.music.stop(); @@ -2698,19 +3403,23 @@ class PlayState extends MusicBeatState paused = true; - FlxG.sound.music.stop(); vocals.stop(); - if (FlxG.save.data.scoreScreen) + if (FlxG.save.data.scoreScreen) + { openSubState(new ResultsScreen()); + new FlxTimer().start(1, function(tmr:FlxTimer) + { + inResults = true; + }); + } else - FlxG.switchState(new PlayState()); + FlxG.switchState(new FreeplayState()); } } } - var endingSong:Bool = false; var hits:Array = []; @@ -2720,73 +3429,70 @@ class PlayState extends MusicBeatState 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) { - 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; + case 'shit': + score = -300; + combo = 0; + misses++; + health -= 0.06; + ss = false; + shits++; + if (FlxG.save.data.accuracyMod == 0) + totalNotesHit -= 1; + case 'bad': + daRating = 'bad'; + score = 0; + health -= 0.03; + ss = false; + bads++; + if (FlxG.save.data.accuracyMod == 0) + totalNotesHit += 0.50; + case 'good': + daRating = 'good'; + score = 200; + ss = false; + goods++; + if (FlxG.save.data.accuracyMod == 0) + totalNotesHit += 0.75; + case 'sick': + if (health < 2) + health += 0.04; + if (FlxG.save.data.accuracyMod == 0) + totalNotesHit += 1; + sicks++; + } - if (FlxG.save.data.accuracyMod == 1) - totalNotesHit += wife; - var daRating = daNote.rating; + // trace('Wife accuracy loss: ' + wife + ' | Rating: ' + daRating + ' | Score: ' + score + ' | Weight: ' + (1 - wife)); - 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') - { - - + if (daRating != 'shit' || daRating != 'bad') + { songScore += Math.round(score); songScoreDef += Math.round(ConvertScore.convertScore(noteDiff)); - + /* if (combo > 60) daRating = 'sick'; else if (combo > 12) @@ -2794,21 +3500,21 @@ class PlayState extends MusicBeatState 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; @@ -2817,19 +3523,20 @@ class PlayState extends MusicBeatState 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 (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"); + currentTimingShown = new FlxText(0, 0, 0, "0ms"); timeShown = 0; - switch(daRating) + switch (daRating) { case 'shit' | 'bad': currentTimingShown.color = FlxColor.RED; @@ -2846,7 +3553,7 @@ class PlayState extends MusicBeatState if (msTiming >= 0.03 && offsetTesting) { - //Remove Outliers + // Remove Outliers hits.shift(); hits.shift(); hits.shift(); @@ -2857,19 +3564,18 @@ class PlayState extends MusicBeatState var total = 0.0; - for(i in hits) + for (i in hits) total += i; - - - offsetTest = HelperFunctions.truncateFloat(total / hits.length,2); + offsetTest = HelperFunctions.truncateFloat(total / hits.length, 2); } if (currentTimingShown.alpha != 1) currentTimingShown.alpha = 1; - if(!PlayStateChangeables.botPlay || loadRep) add(currentTimingShown); - + if (!PlayStateChangeables.botPlay || loadRep) + add(currentTimingShown); + var comboSpr:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'combo' + pixelShitPart2)); comboSpr.screenCenter(); comboSpr.x = rating.x; @@ -2882,34 +3588,41 @@ class PlayState extends MusicBeatState 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 (!PlayStateChangeables.botPlay || loadRep) + add(rating); + if (!curStage.startsWith('school')) { rating.setGraphicSize(Std.int(rating.width * 0.7)); - rating.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + rating.antialiasing = true; + } comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7)); - comboSpr.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + 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) @@ -2924,12 +3637,12 @@ class PlayState extends MusicBeatState else if (comboSplit.length == 2) seperatedScore.push(0); - for(i in 0...comboSplit.length) + for (i in 0...comboSplit.length) { var str:String = comboSplit[i]; seperatedScore.push(Std.parseInt(str)); } - + var daLoop:Int = 0; for (i in seperatedScore) { @@ -2941,7 +3654,10 @@ class PlayState extends MusicBeatState if (!curStage.startsWith('school')) { - numScore.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + numScore.antialiasing = true; + } numScore.setGraphicSize(Std.int(numScore.width * 0.5)); } else @@ -2949,13 +3665,13 @@ class PlayState extends MusicBeatState 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) { @@ -2963,17 +3679,17 @@ class PlayState extends MusicBeatState }, 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) @@ -2998,320 +3714,348 @@ class PlayState extends MusicBeatState }, 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; + + // THIS FUNCTION JUST FUCKS WIT HELD NOTES AND BOTPLAY/REPLAY (also gamepad shit) + + 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) { - return Math.abs(FlxMath.roundDecimal(value1, 1) - FlxMath.roundDecimal(value2, 1)) < unimportantDifference; + 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 upHold:Bool = false; - var downHold:Bool = false; - var rightHold:Bool = false; - var leftHold:Bool = false; + var anas:Array = [null, null, null, null]; - private function keyShit():Void // I've invested in emma stocks + 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) { - // 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) + if (daNote.isSustainNote && daNote.canBeHit && daNote.mustPress && holdArray[daNote.noteData] && daNote.sustainActive) { - holdArray = [false, false, false, false]; - pressArray = [false, false, false, false]; - releaseArray = [false, false, false, false]; - } - // 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); - }); + trace(daNote.sustainActive); + 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]) - { - if (directionList.contains(daNote.noteData)) - { - directionsAccounted[daNote.noteData] = true; - for (coolNote in possibleNotes) - { - if (coolNote.noteData == daNote.noteData && Math.abs(daNote.strumTime - coolNote.strumTime) < 10) - { // if it's the same note twice at < 10ms distance, just delete it - // EXCEPT u cant delete it in this loop cuz it fucks with the collection lol - dumbNotes.push(daNote); - break; - } - else if (coolNote.noteData == daNote.noteData && daNote.strumTime < coolNote.strumTime) - { // if daNote is earlier than existing note (coolNote), replace - possibleNotes.remove(coolNote); - possibleNotes.push(daNote); - break; - } - } - } - else - { - 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)); - - var dontCheck = false; + if ((KeyBinds.gamepad && !FlxG.keys.justPressed.ANY)) + { + // PRESSES, check for note hits + if (pressArray.contains(true) && generatedMusic) + { + boyfriend.holdTimer = 0; - for (i in 0...pressArray.length) - { - if (pressArray[i] && !directionList.contains(i)) - dontCheck = true; - } + 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 - if (perfectMode) - goodNoteHit(possibleNotes[0]); - else if (possibleNotes.length > 0 && !dontCheck) - { - 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; - goodNoteHit(coolNote); - } - } - } - else if (!FlxG.save.data.ghost) - { - for (shit in 0...pressArray.length) - if (pressArray[shit]) - noteMiss(shit, null); - } - - if(dontCheck && possibleNotes.length > 0 && FlxG.save.data.ghost && !PlayStateChangeables.botPlay) - { - if (mashViolations > 8) - { - trace('mash violations ' + mashViolations); - scoreTxt.color = FlxColor.RED; - noteMiss(0,null); - } - else - mashViolations++; - } - - } - notes.forEachAlive(function(daNote:Note) { - if(PlayStateChangeables.useDownscroll && daNote.y > strumLine.y || - !PlayStateChangeables.useDownscroll && daNote.y < strumLine.y) + if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit && !directionsAccounted[daNote.noteData]) { - // 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 (directionList.contains(daNote.noteData)) { - if(loadRep) + directionsAccounted[daNote.noteData] = true; + for (coolNote in possibleNotes) { - //trace('ReplayNote ' + tmpRepNote.strumtime + ' | ' + tmpRepNote.direction); - var n = findByTime(daNote.strumTime); - trace(n); - if(n != null) - { - goodNoteHit(daNote); - boyfriend.holdTimer = daNote.sustainLength; + if (coolNote.noteData == daNote.noteData && Math.abs(daNote.strumTime - coolNote.strumTime) < 10) + { // if it's the same note twice at < 10ms distance, just delete it + // EXCEPT u cant delete it in this loop cuz it fucks with the collection lol + dumbNotes.push(daNote); + break; + } + else if (coolNote.noteData == daNote.noteData && daNote.strumTime < coolNote.strumTime) + { // if daNote is earlier than existing note (coolNote), replace + possibleNotes.remove(coolNote); + possibleNotes.push(daNote); + break; } - }else { - goodNoteHit(daNote); - boyfriend.holdTimer = daNote.sustainLength; } } + else + { + 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)); + + var hit = [false,false,false,false]; + + 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] && !hit[coolNote.noteData]) + { + if (mashViolations != 0) + mashViolations--; + hit[coolNote.noteData] = true; + 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); + } + } + }; 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')) + if (boyfriend.animation.curAnim.name.startsWith('sing') && !boyfriend.animation.curAnim.name.endsWith('miss') && boyfriend.animation.curAnim.curFrame >= 10) boyfriend.playAnim('idle'); } - - playerStrums.forEach(function(spr:FlxSprite) + else if (!FlxG.save.data.ghost) { - 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')) + 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) { - spr.centerOffsets(); - spr.offset.x -= 13; - spr.offset.y -= 13; + // trace('ReplayNote ' + tmpRepNote.strumtime + ' | ' + tmpRepNote.direction); + var n = findByTime(daNote.strumTime); + trace(n); + if (n != null) + { + goodNoteHit(daNote); + boyfriend.holdTimer = daNote.sustainLength; + } } 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; + goodNoteHit(daNote); + boyfriend.holdTimer = daNote.sustainLength; } - return null; } - - 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 + }); + + 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.animation.curAnim.curFrame >= 10) + boyfriend.playAnim('idle'); + } + + playerStrums.forEach(function(spr:FlxSprite) + { + if (keys[spr.ID] && spr.animation.curAnim.name != 'confirm') + spr.animation.play('pressed'); + if (!keys[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 backgroundVideo(source:String) // for background videos - { - useVideo = true; - - FlxG.stage.window.onFocusOut.add(focusOut); - FlxG.stage.window.onFocusIn.add(focusIn); + 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; + } - 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); + public var fuckingVolume:Float = 1; + public var useVideo = false; - 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(); - } + 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 + { + #if cpp + 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(); + #end + } function noteMiss(direction:Int = 1, daNote:Note):Void { if (!boyfriend.stunned) { - health -= 0.04; + //health -= 0.2; if (combo > 5 && gf.animOffsets.exists('sad')) { gf.playAnim('sad'); @@ -3322,73 +4066,86 @@ class PlayState extends MusicBeatState if (daNote != null) { if (!loadRep) - saveNotes.push([daNote.strumTime,0,direction,166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166]); + { + 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"); } - else - if (!loadRep) - saveNotes.push([Conductor.songPosition,0,direction,166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166]); - //var noteDiff:Float = Math.abs(daNote.strumTime - Conductor.songPosition); - //var wife:Float = EtternaFunctions.wife3(noteDiff, FlxG.save.data.etternaMode ? 1 : 1.7); + // 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) + if (daNote != null) { - 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 (!daNote.isSustainNote) + songScore -= 10; } + else + songScore -= 10; + + if(FlxG.save.data.missSounds) + { + 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'); + } + + // Hole switch statement replaced with a single line :) + boyfriend.playAnim('sing' + dataSuffix[direction] + 'miss', 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); - } + { + // 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 { @@ -3406,19 +4163,19 @@ class PlayState extends MusicBeatState 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); + { + var noteDiff:Float = -(note.strumTime - Conductor.songPosition); - note.rating = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000)); + note.rating = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000)); - /* if (loadRep) + /* if (loadRep) { if (controlArray[note.noteData]) goodNoteHit(note, false); @@ -3429,13 +4186,13 @@ class PlayState extends MusicBeatState goodNoteHit(note, false); } } - } */ - - if (controlArray[note.noteData]) - { - goodNoteHit(note, (mashing > getKeyPresses(note))); - - /*if (mashing > getKeyPresses(note) && mashViolations <= 2) + }*/ + + if (controlArray[note.noteData]) + { + goodNoteHit(note, (mashing > getKeyPresses(note))); + + /*if (mashing > getKeyPresses(note) && mashViolations <= 2) { mashViolations++; @@ -3454,101 +4211,97 @@ class PlayState extends MusicBeatState mashing = 0; } else - goodNoteHit(note, false);*/ - - } + goodNoteHit(note, false); */ } + } - function goodNoteHit(note:Note, resetMashViolation = true):Void + 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) { - - if (mashing != 0) - mashing = 0; - - var noteDiff:Float = -(note.strumTime - Conductor.songPosition); - - if(loadRep) - noteDiff = findByTime(note.strumTime)[3]; - - 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); - } - - 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(); - } + 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; + 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.kill(); + notes.remove(note, true); + note.destroy(); + + updateAccuracy(); + } + } var fastCarCanDrive:Bool = true; function resetFastCar():Void { - if(FlxG.save.data.distractions){ + if (FlxG.save.data.distractions) + { fastCar.x = -12600; fastCar.y = FlxG.random.int(140, 250); fastCar.velocity.x = 0; @@ -3558,7 +4311,8 @@ class PlayState extends MusicBeatState function fastCarDrive() { - if(FlxG.save.data.distractions){ + 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; @@ -3579,7 +4333,8 @@ class PlayState extends MusicBeatState function trainStart():Void { - if(FlxG.save.data.distractions){ + if (FlxG.save.data.distractions) + { trainMoving = true; if (!trainSound.playing) trainSound.play(true); @@ -3590,36 +4345,37 @@ class PlayState extends MusicBeatState function updateTrainPos():Void { - if(FlxG.save.data.distractions){ + 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(); - } - } + { + 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){ + if (FlxG.save.data.distractions) + { gf.playAnim('hairFall'); phillyTrain.x = FlxG.width + 200; trainMoving = false; @@ -3656,8 +4412,8 @@ class PlayState extends MusicBeatState #if windows if (executeModchart && luaModchart != null) { - luaModchart.setVar('curStep',curStep); - luaModchart.executeState('stepHit',[curStep]); + luaModchart.setVar('curStep', curStep); + luaModchart.executeState('stepHit', [curStep]); } #end @@ -3669,9 +4425,22 @@ class PlayState extends MusicBeatState 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); + 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; @@ -3689,31 +4458,32 @@ class PlayState extends MusicBeatState #if windows if (executeModchart && luaModchart != null) { - luaModchart.setVar('curBeat',curBeat); - luaModchart.executeState('beatHit',[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 (curSong == 'Tutorial' && dad.curCharacter == 'gf') + { + if (SONG.notes[Math.floor(curStep / 16)].mustHitSection) + dad.dance(); + else + { + if (curBeat == 73 || curBeat % 4 == 0 || curBeat % 4 == 1) + dad.playAnim('danceLeft', true); + else + dad.playAnim('danceRight', true); + } } 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(); + if ((SONG.notes[Math.floor(curStep / 16)].mustHitSection || !dad.animation.curAnim.name.startsWith("sing")) && dad.curCharacter != 'gf') + if ((curBeat % idleBeat == 0 || !idleToBeat) || dad.curCharacter == "spooky") + dad.dance(idleToBeat); } // FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM); wiggleShit.update(Conductor.crochet); @@ -3726,18 +4496,17 @@ class PlayState extends MusicBeatState 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(); @@ -3746,11 +4515,15 @@ class PlayState extends MusicBeatState gf.dance(); } - if (!boyfriend.animation.curAnim.name.startsWith("sing")) + if (!boyfriend.animation.curAnim.name.startsWith("sing") && (curBeat % idleBeat == 0 || !idleToBeat)) { - boyfriend.playAnim('idle'); + boyfriend.playAnim('idle', idleToBeat); } - + + /*if (!dad.animation.curAnim.name.startsWith("sing")) + { + dad.dance(); + }*/ if (curBeat % 8 == 7 && curSong == 'Bopeebo') { @@ -3758,58 +4531,62 @@ class PlayState extends MusicBeatState } if (curBeat % 16 == 15 && SONG.song == 'Tutorial' && dad.curCharacter == 'gf' && curBeat > 16 && curBeat < 48) - { - boyfriend.playAnim('hey', true); - dad.playAnim('cheer', true); - } + { + boyfriend.playAnim('hey', true); + dad.playAnim('cheer', true); + } switch (curStage) { case 'school': - if(FlxG.save.data.distractions){ + if (FlxG.save.data.distractions) + { bgGirls.dance(); } case 'mall': - if(FlxG.save.data.distractions){ + 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){ + if (FlxG.save.data.distractions) + { grpLimoDancers.forEach(function(dancer:BackgroundDancer) - { - dancer.dance(); - }); - - if (FlxG.random.bool(10) && fastCarCanDrive) - fastCarDrive(); + { + dancer.dance(); + }); + + if (FlxG.random.bool(10) && fastCarCanDrive) + fastCarDrive(); } case "philly": - if(FlxG.save.data.distractions){ + 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){ + if (FlxG.save.data.distractions) + { trainCooldown = FlxG.random.int(-4, 0); trainStart(); } @@ -3818,7 +4595,8 @@ class PlayState extends MusicBeatState if (isHalloween && FlxG.random.bool(10) && curBeat > lightningStrikeBeat + lightningOffset) { - if(FlxG.save.data.distractions){ + if (FlxG.save.data.distractions) + { lightningStrikeShit(); } } diff --git a/source/PlayStateChangeables.hx b/source/PlayStateChangeables.hx index 8ee4995..17a430a 100644 --- a/source/PlayStateChangeables.hx +++ b/source/PlayStateChangeables.hx @@ -4,4 +4,5 @@ class PlayStateChangeables public static var safeFrames:Int; public static var scrollSpeed:Float; public static var botPlay:Bool; + public static var Optimize:Bool; } \ No newline at end of file diff --git a/source/Ratings.hx b/source/Ratings.hx index 92b0ee5..758f8bf 100644 --- a/source/Ratings.hx +++ b/source/Ratings.hx @@ -119,21 +119,21 @@ class Ratings public static function checkRating(ms:Float, ts:Float) { - var rating = "miss"; - if (ms < 166 * ts && ms > 135 * ts) + var rating = "sick"; + if (ms <= 166 * ts && ms >= 135 * ts) rating = "shit"; - if (ms > -166 * ts && ms < -135 * ts) - rating = "shit"; - if (ms < 135 * ts && ms > 90 * ts) + if (ms < 135 * ts && ms >= 90 * ts) rating = "bad"; - if (ms > -135 * ts && ms < -90 * ts) - rating = "bad"; - if (ms < 90 * ts && ms > 45 * ts) + if (ms < 90 * ts && ms >= 45 * ts) rating = "good"; - if (ms > -90 * ts && ms < -45 * ts) - rating = "good"; - if (ms < 45 * ts && ms > -45 * ts) + 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; } diff --git a/source/Replay.hx b/source/Replay.hx index 51fddf2..5d88f32 100644 --- a/source/Replay.hx +++ b/source/Replay.hx @@ -11,6 +11,31 @@ 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; @@ -18,9 +43,13 @@ typedef ReplayJSON = public var songName:String; public var songDiff:Int; public var songNotes:Array; + public var songJudgements:Array; public var noteSpeed:Float; + public var chartPath:String; public var isDownscroll:Bool; public var sf:Int; + public var sm:Bool; + public var ana:Analysis; } class Replay @@ -39,8 +68,12 @@ class Replay isDownscroll: false, songNotes: [], replayGameVer: version, + chartPath: "", + sm: false, timestamp: Date.now(), - sf: Conductor.safeFrames + sf: Conductor.safeFrames, + ana: new Analysis(), + songJudgements: [] }; } @@ -55,20 +88,30 @@ class Replay return rep; } - public function SaveReplay(notearray:Array) + public function SaveReplay(notearray:Array, judge:Array, ana:Analysis) { + #if sys + var chartPath = PlayState.isSM ? PlayState.pathToSm + "/converted.json" : ""; + #else + var chartPath = ""; + #end + var json = { "songName": PlayState.SONG.song, "songDiff": PlayState.storyDifficulty, + "chartPath": chartPath, + "sm": PlayState.isSM, + "timestamp": Date.now(), + "replayGameVer": version, + "sf": Conductor.safeFrames, "noteSpeed": (FlxG.save.data.scrollSpeed > 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed), "isDownscroll": FlxG.save.data.downscroll, "songNotes": notearray, - "timestamp": Date.now(), - "replayGameVer": version, - "sf": Conductor.safeFrames + "songJudgements": judge, + "ana": ana }; - var data:String = Json.stringify(json); + var data:String = Json.stringify(json, null, ""); var time = Date.now().getTime(); @@ -78,6 +121,8 @@ class Replay path = "replay-" + PlayState.SONG.song + "-time" + time + ".kadeReplay"; // for score screen shit LoadFromJSON(); + + replay.ana = ana; #end } diff --git a/source/ResultsScreen.hx b/source/ResultsScreen.hx index 2c8e258..be8371e 100644 --- a/source/ResultsScreen.hx +++ b/source/ResultsScreen.hx @@ -1,5 +1,10 @@ package; - +import haxe.Exception; +#if sys +import smTools.SMFile; +import sys.FileSystem; +import sys.io.File; +#end import openfl.geom.Matrix; import openfl.display.BitmapData; import flixel.system.FlxSound; @@ -35,7 +40,7 @@ class ResultsScreen extends FlxSubState public var anotherBackground:FlxSprite; public var graph:HitGraph; - public var graphSprite:FlxSprite; + public var graphSprite:OFLSprite; public var comboText:FlxText; public var contText:FlxText; @@ -54,9 +59,13 @@ class ResultsScreen extends FlxSubState 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))); + if (!PlayState.inResults) + { + music = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true); + music.volume = 0; + music.play(false, FlxG.random.int(0, Std.int(music.length / 2))); + FlxG.sound.list.add(music); + } background.alpha = 0; @@ -74,7 +83,7 @@ class ResultsScreen extends FlxSubState 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) + PlayState.shits}\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 = 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}\nScore: ${PlayState.instance.songScore}\nAccuracy: ${HelperFunctions.truncateFloat(PlayState.instance.accuracy,2)}%\n\n${Ratings.GenerateLetterRank(PlayState.instance.accuracy)}\n\n${!PlayState.loadRep ? "F1 - View replay\nF2 - Replay song" : ""} '); comboText.size = 28; comboText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1); @@ -82,7 +91,7 @@ class ResultsScreen extends FlxSubState comboText.scrollFactor.set(); add(comboText); - contText = new FlxText(FlxG.width - 475,FlxG.height + 50,0,'Press ENTER to continue.'); + contText = new FlxText(FlxG.width - 475,FlxG.height + 50,0,'Press ${KeyBinds.gamepad ? 'A' : 'ENTER'} to continue.'); contText.size = 28; contText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1); contText.color = FlxColor.WHITE; @@ -97,7 +106,7 @@ class ResultsScreen extends FlxSubState graph = new HitGraph(FlxG.width - 500,45,495,240); graph.alpha = 0; - graphSprite = new FlxSprite(FlxG.width - 510,45); + graphSprite = new OFLSprite(FlxG.width - 510,45,460,240,graph); graphSprite.scrollFactor.set(); graphSprite.alpha = 0; @@ -116,28 +125,31 @@ class ResultsScreen extends FlxSubState var mean:Float = 0; - for (i in PlayState.rep.replay.songNotes) + for (i in 0...PlayState.rep.replay.songNotes.length) { // 0 = time // 1 = length // 2 = type // 3 = diff - var diff = i[3]; - var judge = Ratings.CalculateRating(diff, Math.floor((PlayState.rep.replay.sf / 60) * 1000)); - mean += diff; - if (i[1] != -1) - graph.addToHistory(diff, judge); + 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; + if (diff != (166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166)) + mean += diff; + if (obj[1] != -1) + graph.addToHistory(diff, judge, obj3); } graph.update(); - graphSprite.makeGraphic(460,240,FlxColor.TRANSPARENT); - - graphSprite.pixels.draw(graph); - 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.difficultyString()}'); + 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; @@ -165,39 +177,46 @@ class ResultsScreen extends FlxSubState override function update(elapsed:Float) { - if (music.volume < 0.5) - music.volume += 0.01 * elapsed; + if (music != null && music.volume < 0.5) + music.volume += 0.01 * elapsed; - // render - if (frames != 2) - { - graphSprite.pixels.draw(graph); - frames++; - } // keybinds - if (FlxG.keys.justPressed.ENTER) + if (PlayerSettings.player1.controls.ACCEPT) { music.fadeOut(0.3); PlayState.loadRep = false; PlayState.rep = null; + 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(PlayState.instance.songScore), PlayState.storyDifficulty); + Highscore.saveCombo(songHighscore, Ratings.GenerateLetterRank(PlayState.instance.accuracy),PlayState.storyDifficulty); + #end + if (PlayState.isStoryMode) { FlxG.sound.playMusic(Paths.music('freakyMenu')); + Conductor.changeBPM(102); FlxG.switchState(new MainMenuState()); } else FlxG.switchState(new FreeplayState()); } - if (FlxG.keys.justPressed.F1) + if (FlxG.keys.justPressed.F1 && !PlayState.loadRep) { trace(PlayState.rep.path); PlayState.rep = Replay.LoadReplay(PlayState.rep.path); PlayState.loadRep = true; + PlayState.isSM = PlayState.rep.replay.sm; var songFormat = StringTools.replace(PlayState.rep.replay.songName, " ", "-"); switch (songFormat) { @@ -208,23 +227,76 @@ class ResultsScreen extends FlxSubState case 'philly-nice': songFormat = 'Philly'; } - var poop:String = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff); + 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(PlayState.instance.songScore), PlayState.storyDifficulty); + Highscore.saveCombo(songHighscore, Ratings.GenerateLetterRank(PlayState.instance.accuracy),PlayState.storyDifficulty); + #end + + #if sys + if (PlayState.rep.replay.sm) + if (!FileSystem.exists(StringTools.replace(PlayState.rep.replay.chartPath,"converted.json",""))) + { + Application.current.window.alert("The SM file in this replay does not exist!","SM Replays"); + return; + } + #end + + var poop = ""; + + #if sys + if (PlayState.isSM) + { + poop = File.getContent(PlayState.rep.replay.chartPath); + try + { + PlayState.sm = SMFile.loadFile(PlayState.pathToSm + "/" + StringTools.replace(PlayState.rep.replay.songName," ", "_") + ".sm"); + } + catch(e:Exception) + { + Application.current.window.alert("Make sure that the SM file is called " + PlayState.pathToSm + "/" + StringTools.replace(PlayState.rep.replay.songName," ", "_") + ".sm!\nAs I couldn't read it.","SM Replays"); + return; + } + } + else + poop = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff); + #else + poop = Highscore.formatSong(PlayState.rep.replay.songName, PlayState.rep.replay.songDiff); + #end music.fadeOut(0.3); - PlayState.SONG = Song.loadFromJson(poop, PlayState.rep.replay.songName); + if (PlayState.isSM) + PlayState.SONG = Song.loadFromJsonRAW(poop); + else + 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 ) + if (FlxG.keys.justPressed.F2 && !PlayState.loadRep) { PlayState.rep = null; PlayState.loadRep = false; + 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(PlayState.instance.songScore), PlayState.storyDifficulty); + Highscore.saveCombo(songHighscore, Ratings.GenerateLetterRank(PlayState.instance.accuracy),PlayState.storyDifficulty); + #end + var songFormat = StringTools.replace(PlayState.SONG.song, " ", "-"); switch (songFormat) { case 'Dad-Battle': songFormat = 'Dadbattle'; @@ -235,12 +307,12 @@ class ResultsScreen extends FlxSubState var poop:String = Highscore.formatSong(songFormat, PlayState.storyDifficulty); - music.fadeOut(0.3); + if (music != null) + 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()); } diff --git a/source/Section.hx b/source/Section.hx index f153da5..fcb574a 100644 --- a/source/Section.hx +++ b/source/Section.hx @@ -2,7 +2,9 @@ package; typedef SwagSection = { - var sectionNotes:Array; + var startTime:Float; + var endTime:Float; + var sectionNotes:Array>; var lengthInSteps:Int; var typeOfSection:Int; var mustHitSection:Bool; @@ -13,7 +15,9 @@ typedef SwagSection = class Section { - public var sectionNotes:Array = []; + public var startTime:Float = 0; + public var endTime:Float = 0; + public var sectionNotes:Array> = []; public var lengthInSteps:Int = 16; public var typeOfSection:Int = 0; diff --git a/source/SectionRender.hx b/source/SectionRender.hx new file mode 100644 index 0000000..67cafa8 --- /dev/null +++ b/source/SectionRender.hx @@ -0,0 +1,33 @@ +import flixel.FlxG; +import flixel.util.FlxColor; +import flixel.group.FlxGroup.FlxTypedGroup; +import Section.SwagSection; +import flixel.addons.display.FlxGridOverlay; +import flixel.FlxSprite; + +class SectionRender extends FlxSprite +{ + public var section:SwagSection; + public var icon:FlxSprite; + public var lastUpdated:Bool; + + public function new(x:Float,y:Float,GRID_SIZE:Int, ?Height:Int = 16) + { + super(x,y); + + makeGraphic(GRID_SIZE * 8, GRID_SIZE * Height,0xffe7e6e6); + + var h = GRID_SIZE; + if (Math.floor(h) != h) + h = GRID_SIZE; + + if (FlxG.save.data.editor) + FlxGridOverlay.overlay(this,GRID_SIZE, Std.int(h), GRID_SIZE * 8,GRID_SIZE * Height); + } + + + + override function update(elapsed) + { + } +} \ No newline at end of file diff --git a/source/ShaderShader.hx b/source/ShaderShader.hx new file mode 100644 index 0000000..fc19f21 --- /dev/null +++ b/source/ShaderShader.hx @@ -0,0 +1,41 @@ +import flixel.system.FlxAssets; + +class ShaderShader extends FlxShader +{ + @:glFragmentSource(' + #pragma header + uniform float fade; + + varying vec4 color; + varying vec2 textureCoord; + varying vec2 textureSize; + uniform sampler2D sampler0; + + float luma(vec3 color) { + return dot(color, vec3(0.299, 0.587, 0.114)); + } + + vec3 rgb(float r, float g, float b) { + return vec3(r/255.0,g/255.0,b/255.0); + } + + void main() + { + vec2 uv = textureCoord; + + vec3 col = texture2D( sampler0, uv ).rgb; + float bright=floor(luma(col+0.4)*4.0)/4.0; + + vec3 newcol; + if (bright<0.3) newcol = rgb(54.0,87.0,53.0); + else if (bright<0.6) newcol = rgb(128.0,128.0,0.0); + else newcol = rgb(157.0,187.0,97.0); + gl_FragColor = vec4( newcol*(fade)+col*(1.0-fade), 1.0 ) * color; + } + ') + + public function new() + { + super(); + } +} \ No newline at end of file diff --git a/source/Song.hx b/source/Song.hx index 5329079..e3e3055 100644 --- a/source/Song.hx +++ b/source/Song.hx @@ -7,10 +7,28 @@ import lime.utils.Assets; using StringTools; +class Event +{ + public var name:String; + public var position:Float; + public var value:Float; + public var type:String; + + public function new(name:String,pos:Float,value:Float,type:String) + { + this.name = name; + this.position = pos; + this.value = value; + this.type = type; + } +} + typedef SwagSong = { + var chartVersion:String; var song:String; var notes:Array; + var eventObjects:Array; var bpm:Float; var needsVoices:Bool; var speed:Float; @@ -25,10 +43,12 @@ typedef SwagSong = class Song { + public var chartVersion:String; public var song:String; public var notes:Array; public var bpm:Float; public var needsVoices:Bool = true; + public var eventObjects:Array; public var speed:Float = 1; public var player1:String = 'bf'; @@ -44,10 +64,19 @@ class Song this.bpm = bpm; } + public static function loadFromJsonRAW(rawJson:String) + { + while (!rawJson.endsWith("}")) + { + rawJson = rawJson.substr(0, rawJson.length - 1); + // LOL GOING THROUGH THE BULLSHIT TO CLEAN IDK WHATS STRANGE + } + + return parseJSONshit(rawJson); + } + public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong { - trace(jsonInput); - // pre lowercasing the folder name var folderLowercase = StringTools.replace(folder, " ", "-").toLowerCase(); switch (folderLowercase) { diff --git a/source/StoryMenuState.hx b/source/StoryMenuState.hx index 443b8e0..ce2d49d 100644 --- a/source/StoryMenuState.hx +++ b/source/StoryMenuState.hx @@ -1,5 +1,6 @@ package; +import flixel.input.gamepad.FlxGamepad; import flixel.FlxG; import flixel.FlxSprite; import flixel.addons.transition.FlxTransitionableState; @@ -23,18 +24,21 @@ 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'] - ]; + static function weekData():Array + { + return [ + ['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]; + public static var weekUnlocked:Array = []; var weekCharacters:Array = [ ['', 'bf', 'gf'], @@ -46,15 +50,7 @@ class StoryMenuState extends MusicBeatState ['senpai', 'bf', 'gf'] ]; - var weekNames:Array = [ - "", - "Daddy Dearest", - "Spooky Month", - "PICO", - "MOMMY MUST MURDER", - "RED SNOW", - "Hating Simulator ft. Moawling" - ]; + var weekNames:Array = CoolUtil.coolTextFile(Paths.txt('data/weekNames')); var txtWeekTitle:FlxText; @@ -72,8 +68,28 @@ class StoryMenuState extends MusicBeatState var leftArrow:FlxSprite; var rightArrow:FlxSprite; + function unlockWeeks():Array + { + var weeks:Array = []; + #if debug + for(i in 0...weekNames.length) + weeks.push(true); + return weeks; + #end + + weeks.push(true); + + for(i in 0...FlxG.save.data.weekUnlocked) + { + weeks.push(true); + } + return weeks; + } + override function create() { + weekUnlocked = unlockWeeks(); + #if windows // Updating Discord Rich Presence DiscordClient.changePresence("In the Story Mode Menu", null); @@ -85,7 +101,10 @@ class StoryMenuState extends MusicBeatState if (FlxG.sound.music != null) { if (!FlxG.sound.music.playing) + { FlxG.sound.playMusic(Paths.music('freakyMenu')); + Conductor.changeBPM(102); + } } persistentUpdate = persistentDraw = true; @@ -109,17 +128,17 @@ class StoryMenuState extends MusicBeatState grpWeekText = new FlxTypedGroup(); add(grpWeekText); + grpLocks = new FlxTypedGroup(); + add(grpLocks); + 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) + for (i in 0...weekData().length) { var weekThing:MenuItem = new MenuItem(0, yellowBG.y + yellowBG.height + 10, i); weekThing.y += ((weekThing.height + 20) * i); @@ -127,18 +146,25 @@ class StoryMenuState extends MusicBeatState grpWeekText.add(weekThing); weekThing.screenCenter(X); - weekThing.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + weekThing.antialiasing = true; + } // weekThing.updateHitbox(); // Needs an offset thingie if (!weekUnlocked[i]) { + trace('locking week ' + 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; + if(FlxG.save.data.antialiasing) + { + lock.antialiasing = true; + } grpLocks.add(lock); } } @@ -194,6 +220,19 @@ class StoryMenuState extends MusicBeatState updateText(); + + 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++; + } + trace("Line 165"); super.create(); @@ -222,12 +261,44 @@ class StoryMenuState extends MusicBeatState { if (!selectedWeek) { - if (controls.UP_P) + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + if (gamepad != null) + { + if (gamepad.justPressed.DPAD_UP) + { + changeWeek(-1); + } + if (gamepad.justPressed.DPAD_DOWN) + { + changeWeek(1); + } + + if (gamepad.pressed.DPAD_RIGHT) + rightArrow.animation.play('press') + else + rightArrow.animation.play('idle'); + if (gamepad.pressed.DPAD_LEFT) + leftArrow.animation.play('press'); + else + leftArrow.animation.play('idle'); + + if (gamepad.justPressed.DPAD_RIGHT) + { + changeDifficulty(1); + } + if (gamepad.justPressed.DPAD_LEFT) + { + changeDifficulty(-1); + } + } + + if (FlxG.keys.justPressed.UP) { changeWeek(-1); } - if (controls.DOWN_P) + if (FlxG.keys.justPressed.DOWN) { changeWeek(1); } @@ -261,6 +332,9 @@ class StoryMenuState extends MusicBeatState FlxG.switchState(new MainMenuState()); } + if (FlxG.sound.music != null) + Conductor.songPosition = FlxG.sound.music.time; + super.update(elapsed); } @@ -281,7 +355,7 @@ class StoryMenuState extends MusicBeatState stopspamming = true; } - PlayState.storyPlaylist = weekData[curWeek]; + PlayState.storyPlaylist = weekData()[curWeek]; PlayState.isStoryMode = true; selectedWeek = true; @@ -355,10 +429,10 @@ class StoryMenuState extends MusicBeatState { curWeek += change; - if (curWeek >= weekData.length) + if (curWeek >= weekData().length) curWeek = 0; if (curWeek < 0) - curWeek = weekData.length - 1; + curWeek = weekData().length - 1; var bullShit:Int = 0; @@ -384,7 +458,7 @@ class StoryMenuState extends MusicBeatState grpWeekCharacters.members[2].setCharacter(weekCharacters[curWeek][2]); txtTracklist.text = "Tracks\n"; - var stringThing:Array = weekData[curWeek]; + var stringThing:Array = weekData()[curWeek]; for (i in stringThing) txtTracklist.text += "\n" + i; @@ -400,4 +474,25 @@ class StoryMenuState extends MusicBeatState intendedScore = Highscore.getWeekScore(curWeek, curDifficulty); #end } + + public static function unlockNextWeek(week:Int):Void + { + if(week <= weekData().length - 1 && FlxG.save.data.weekUnlocked == week) + { + weekUnlocked.push(true); + trace('Week ' + week + ' beat (Week ' + (week + 1) + ' unlocked)'); + } + + FlxG.save.data.weekUnlocked = weekUnlocked.length - 1; + FlxG.save.flush(); + } + + override function beatHit() + { + super.beatHit(); + + grpWeekCharacters.members[0].bopHead(); + grpWeekCharacters.members[1].bopHead(); + grpWeekCharacters.members[2].bopHead(); + } } diff --git a/source/TimingStruct.hx b/source/TimingStruct.hx new file mode 100644 index 0000000..82128a3 --- /dev/null +++ b/source/TimingStruct.hx @@ -0,0 +1,55 @@ +import flixel.FlxG; + +class TimingStruct +{ + public static var AllTimings:Array = []; + + public var bpm:Float = 0; + + public var startBeat:Float = 0; + public var endBeat:Float = Math.POSITIVE_INFINITY; + public var startTime:Float = 0; + + public var length:Float = Math.POSITIVE_INFINITY; // in beats + + public static function clearTimings() + { + AllTimings = []; + } + + public static function addTiming(startBeat,bpm,endBeat:Float, offset:Float) + { + var pog = new TimingStruct(startBeat,bpm,endBeat, offset); + AllTimings.push(pog); + } + + public function new(startBeat,bpm,endBeat:Float, offset:Float) + { + this.bpm = bpm; + this.startBeat = startBeat; + if (endBeat != -1) + this.endBeat = endBeat; + startTime = offset; + } + + public static function getTimingAtTimestamp(msTime:Float):TimingStruct + { + for(i in AllTimings) + { + if (msTime >= i.startTime * 1000 && msTime < (i.startTime + i.length) * 1000) + return i; + } + trace('Apparently ' + msTime + ' is out of any segs'); + return null; + } + + public static function getTimingAtBeat(beat):TimingStruct + { + for(i in AllTimings) + { + if (i.startBeat <= beat && i.endBeat >= beat) + return i; + } + return null; + } +} \ No newline at end of file diff --git a/source/TitleState.hx b/source/TitleState.hx index 6b86eca..1a42555 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -1,5 +1,8 @@ package; +#if sys +import smTools.SMFile; +#end import flixel.FlxG; import flixel.FlxSprite; import flixel.FlxState; @@ -64,19 +67,24 @@ class TitleState extends MusicBeatState trace("Loaded " + openfl.Assets.getLibrary("default").assetsLoaded + " assets (DEFAULT)"); } + #if !cpp + + FlxG.save.bind('funkin', 'ninjamuffin99'); + PlayerSettings.init(); - #if windows - DiscordClient.initialize(); - - Application.current.onExit.add (function (exitCode) { - DiscordClient.shutdown(); - }); - + KadeEngineData.initSave(); + #end + + Highscore.load(); + + curWacky = FlxG.random.getObject(getIntroTextShit()); + trace('hello'); + // DEBUG BULLSHIT super.create(); @@ -88,35 +96,19 @@ class TitleState extends MusicBeatState 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 + #if !cpp new FlxTimer().start(1, function(tmr:FlxTimer) { startIntro(); }); + #else + startIntro(); + #end #end } @@ -127,34 +119,6 @@ class TitleState extends MusicBeatState 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); @@ -163,31 +127,30 @@ class TitleState extends MusicBeatState // bg.updateHitbox(); add(bg); - if(Main.watermarks) { - logoBl = new FlxSprite(-150, -100); + if (Main.watermarks) { + logoBl = new FlxSprite(-150, 1500); 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; } + if(FlxG.save.data.antialiasing) + { + logoBl.antialiasing = true; + } + logoBl.animation.addByPrefix('bump', 'logo bumpin', 24, false); + 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; + if(FlxG.save.data.antialiasing) + { + gfDance.antialiasing = true; + } add(gfDance); add(logoBl); @@ -195,7 +158,10 @@ class TitleState extends MusicBeatState titleText.frames = Paths.getSparrowAtlas('titleEnter'); titleText.animation.addByPrefix('idle', "Press Enter to Begin", 24); titleText.animation.addByPrefix('press', "ENTER PRESSED", 24); - titleText.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + titleText.antialiasing = true; + } titleText.animation.play('idle'); titleText.updateHitbox(); // titleText.screenCenter(X); @@ -203,7 +169,10 @@ class TitleState extends MusicBeatState var logo:FlxSprite = new FlxSprite().loadGraphic(Paths.image('logo')); logo.screenCenter(); - logo.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + logo.antialiasing = true; + } // add(logo); // FlxTween.tween(logoBl, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG}); @@ -229,7 +198,10 @@ class TitleState extends MusicBeatState ngSpr.setGraphicSize(Std.int(ngSpr.width * 0.8)); ngSpr.updateHitbox(); ngSpr.screenCenter(X); - ngSpr.antialiasing = true; + if(FlxG.save.data.antialiasing) + { + ngSpr.antialiasing = true; + } FlxTween.tween(credTextShit, {y: credTextShit.y + 20}, 2.9, {ease: FlxEase.quadInOut, type: PINGPONG}); @@ -237,15 +209,40 @@ class TitleState extends MusicBeatState if (initialized) skipIntro(); - else + else { + 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); initialized = true; + } // credGroup.add(credTextShit); } function getIntroTextShit():Array> { - var fullText:String = Assets.getText(Paths.txt('introText')); + var fullText:String = Assets.getText(Paths.txt('data/introText')); var firstArray:Array = fullText.split('\n'); var swagGoodArray:Array> = []; @@ -271,7 +268,7 @@ class TitleState extends MusicBeatState FlxG.fullscreen = !FlxG.fullscreen; } - var pressedEnter:Bool = FlxG.keys.justPressed.ENTER; + var pressedEnter:Bool = controls.ACCEPT; #if mobile for (touch in FlxG.touches.list) @@ -283,19 +280,6 @@ class TitleState extends MusicBeatState } #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 @@ -316,6 +300,7 @@ class TitleState extends MusicBeatState // FlxG.sound.music.stop(); MainMenuState.firstStart = true; + MainMenuState.finishedFunnyMove = false; new FlxTimer().start(2, function(tmr:FlxTimer) { @@ -328,7 +313,7 @@ class TitleState extends MusicBeatState { 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 == "") + if (!MainMenuState.kadeEngineVer.contains(returnedData[0].trim()) && !OutdatedSubState.leftState) { trace('outdated lmao! ' + returnedData[0] + ' != ' + MainMenuState.kadeEngineVer); OutdatedSubState.needVer = returnedData[0]; @@ -393,7 +378,7 @@ class TitleState extends MusicBeatState { super.beatHit(); - logoBl.animation.play('bump'); + logoBl.animation.play('bump', true); danceLeft = !danceLeft; if (danceLeft) @@ -405,6 +390,8 @@ class TitleState extends MusicBeatState switch (curBeat) { + case 0: + deleteCoolText(); case 1: createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']); // credTextShit.visible = true; @@ -473,6 +460,19 @@ class TitleState extends MusicBeatState FlxG.camera.flash(FlxColor.WHITE, 4); remove(credGroup); + + FlxTween.tween(logoBl,{y: -100}, 1.4, {ease: FlxEase.expoInOut}); + + logoBl.angle = -4; + + new FlxTimer().start(0.01, function(tmr:FlxTimer) + { + if(logoBl.angle == -4) + FlxTween.angle(logoBl, logoBl.angle, 4, 4, {ease: FlxEase.quartInOut}); + if (logoBl.angle == 4) + FlxTween.angle(logoBl, logoBl.angle, -4, 4, {ease: FlxEase.quartInOut}); + }, 0); + skippedIntro = true; } } diff --git a/source/smTools/SMFile.hx b/source/smTools/SMFile.hx new file mode 100644 index 0000000..bb9ab6b --- /dev/null +++ b/source/smTools/SMFile.hx @@ -0,0 +1,278 @@ +#if sys +package smTools; +import sys.io.File; +import haxe.Exception; +import lime.app.Application; +import haxe.Json; + +class SMFile +{ + public static function loadFile(path):SMFile + { + return new SMFile(File.getContent(path).split('\n')); + } + + private var _fileData:Array; + + public var isDouble:Bool = false; + + public var isValid:Bool = true; + + public var _readTime:Float = 0; + + public var header:SMHeader; + public var measures:Array; + + public function new(data:Array) + { + try + { + _fileData = data; + + // Gather header data + var headerData = ""; + var inc = 0; + while(!StringTools.contains(data[inc + 1],"//")) + { + headerData += data[inc]; + inc++; + // trace(data[inc]); + } + + header = new SMHeader(headerData.split(';')); + + if (!StringTools.contains(header.MUSIC,"ogg")) + { + Application.current.window.alert("The music MUST be an OGG File.","SM File loading (" + header.TITLE + ")"); + isValid = false; + return; + } + + // check if this is a valid file, it should be a dance double file. + inc += 3; // skip three lines down + if (!StringTools.contains(data[inc],"dance-double:") && !StringTools.contains(data[inc],"dance-single")) + { + Application.current.window.alert("The file you are loading is neither a Dance Double chart or a Dance Single chart","SM File loading (" + header.TITLE + ")"); + isValid = false; + return; + } + if (StringTools.contains(data[inc],"dance-double:")) + isDouble = true; + if (isDouble) + trace('this is dance double'); + + inc += 5; // skip 5 down to where da notes @ + + measures = []; + + var measure = ""; + + trace(data[inc - 1]); + + for (ii in inc...data.length) + { + var i = data[ii]; + if (StringTools.contains(i,",") || StringTools.contains(i,";")) + { + measures.push(new SMMeasure(measure.split('\n'))); + //trace(measures.length); + measure = ""; + continue; + } + measure += i + "\n"; + } + trace(measures.length + " Measures"); + } + catch(e:Exception) + { + Application.current.window.alert("Failure to load file.\n" + e,"SM File loading"); + } + } + + public function convertToFNF(saveTo:String):String + { + + // array's for helds + var heldNotes:Array>; + + + if (isDouble) // held storage lanes + heldNotes = [[],[],[],[],[],[],[],[]]; + else + heldNotes = [[],[],[],[]]; + + + // variables + + var measureIndex = 0; + var currentBeat:Float = 0; + var output = ""; + + // init a fnf song + + var song = { + song: header.TITLE, + notes: [], + eventObjects: [], + bpm: header.getBPM(0), + needsVoices: true, + player1: 'bf', + player2: 'gf', + gfVersion: 'gf', + noteStyle: 'normal', + stage: 'stage', + speed: 1.0, + validScore: false + }; + + // lets check if the sm loading was valid + + if (!isValid) + { + var json = { + "song": song + }; + + var data:String = Json.stringify(json,null," "); + File.saveContent(saveTo,data); + return data; + } + + // aight time to convert da measures + + trace("Converting measures"); + + for(measure in measures) + { + // private access since _measure is private + @:privateAccess + var lengthInRows = 192 / (measure._measure.length - 1); + + var rowIndex = 0; + + // section declaration + + var section = { + sectionNotes: [], + lengthInSteps: 16, + typeOfSection: 0, + startTime: 0.0, + endTime: 0.0, + mustHitSection: false, + bpm: header.getBPM(0), + changeBPM: false, + altAnim: false + }; + + // if it's not a double always set this to true + + if (!isDouble) + section.mustHitSection = true; + + @:privateAccess + for(i in 0...measure._measure.length - 1) + { + var noteRow = (measureIndex * 192) + (lengthInRows * rowIndex); + + var notes:Array = []; + + for(note in measure._measure[i].split('')) + { + //output += note; + notes.push(note); + } + + currentBeat = noteRow / 48; + + var seg = TimingStruct.getTimingAtBeat(currentBeat); + + var timeInSec:Float = (seg.startTime + ((currentBeat - seg.startBeat) / (seg.bpm/60))); + + var rowTime = timeInSec * 1000; + + //output += " - Row " + noteRow + " - Time: " + rowTime + " (" + timeInSec + ") - Beat: " + currentBeat + " - Current BPM: " + header.getBPM(currentBeat) + "\n"; + + var index = 0; + + for(i in notes) + { + // if its a mine lets skip (maybe add mines in the future??) + if (i == "M") + { + index++; + continue; + } + + // get the lane and note type + var lane = index; + var numba = Std.parseInt(i); + + // switch through the type and add the note + + switch(numba) + { + case 1: // normal + section.sectionNotes.push([rowTime,lane ,0]); + case 2: // held head + heldNotes[lane] = [rowTime,lane,0]; + case 3: // held tail + var data = heldNotes[lane]; + var timeDiff = rowTime - data[0]; + section.sectionNotes.push([data[0],lane,timeDiff]); + heldNotes[index] = []; + case 4: // roll head + heldNotes[lane] = [rowTime,lane,0]; + } + index++; + } + + + rowIndex++; + } + + // push the section + + song.notes.push(section); + + //output += ",\n"; + + measureIndex++; + } + + for (i in 0...song.notes.length) // loops through sections + { + var section = song.notes[i]; + + var currentBeat = 4 * i; + + var currentSeg = TimingStruct.getTimingAtBeat(currentBeat); + + var start:Float = (currentBeat - currentSeg.startBeat) / (currentSeg.bpm / 60); + + section.startTime = (currentSeg.startTime + start) * 1000; + + if (i != 0) + song.notes[i - 1].endTime = section.startTime; + section.endTime = Math.POSITIVE_INFINITY; + + } + + //File.saveContent("fuac" + header.TITLE,output); + + if (header.changeEvents.length != 0) + { + song.eventObjects = header.changeEvents; + } + + // save da song + + var json = { + "song": song + }; + + var data:String = Json.stringify(json,null," "); + File.saveContent(saveTo,data); + return data; + } +} +#end \ No newline at end of file diff --git a/source/smTools/SMHeader.hx b/source/smTools/SMHeader.hx new file mode 100644 index 0000000..80c61a5 --- /dev/null +++ b/source/smTools/SMHeader.hx @@ -0,0 +1,119 @@ +#if sys +package smTools; + +class SMHeader +{ + private var _header:Array; + + public var TITLE = ""; + public var SUBTITLE = ""; + public var ARTIST = ""; + public var GENRE = ""; + public var CREDIT = ""; + public var MUSIC = ""; + public var BANNER = ""; + public var BACKGROUND = ""; + public var CDTITLE = ""; + public var OFFSET = ""; + public var BPMS = ""; // time=bpm + + public var changeEvents:Array; + + public function new(headerData:Array) + { + _header = headerData; + + for (i in headerData) + { + readHeaderLine(i); + } + + trace(BPMS); + + MUSIC = StringTools.replace(MUSIC," ", "_"); + + changeEvents = []; + + getBPM(0,true); + } + + public function getBeatFromBPMIndex(index):Float + { + var bpmSplit = BPMS.split(','); + var beat = 0; + for(ii in 0...bpmSplit.length) + { + if (ii == index) + return Std.parseFloat(StringTools.replace(bpmSplit[ii].split('=')[0],",","")); + } + return 0.0; + } + + public function getBPM(beat:Float, printAllBpms:Bool = false) + { + var bpmSplit = BPMS.split(','); + if (printAllBpms) + { + TimingStruct.clearTimings(); + var currentIndex = 0; + for(i in bpmSplit) + { + var bpm:Float = Std.parseFloat(i.split('=')[1]); + var beat:Float = Std.parseFloat(StringTools.replace(i.split('=')[0],",","")); + + var endBeat:Float = Math.POSITIVE_INFINITY; + + TimingStruct.addTiming(beat,bpm,endBeat, -Std.parseFloat(OFFSET)); + + if (changeEvents.length != 0) + { + var data = TimingStruct.AllTimings[currentIndex - 1]; + data.endBeat = beat; + data.length = (data.endBeat - data.startBeat) / (data.bpm / 60); + TimingStruct.AllTimings[currentIndex].startTime = data.startTime + data.length; + } + + changeEvents.push(new Song.Event(HelperFunctions.truncateFloat(beat,3) + "SM",beat,bpm,"BPM Change")); + + if (bpmSplit.length == 1) + break; + currentIndex++; + } + + for(i in TimingStruct.AllTimings) + { + trace("BPM - " + i.bpm + " - " + i.startBeat); + } + + for(i in changeEvents) + { + trace("BPM - " + i.value + " - " + i.position); + } + + trace(changeEvents.length + " - BPM CHANGES"); + return 0.0; + } + var returningBPM = Std.parseFloat(bpmSplit[0].split('=')[1]); + for(i in bpmSplit) + { + var bpm:Float = Std.parseFloat(i.split('=')[1]); + var beatt:Float = Std.parseFloat(StringTools.replace(i.split('=')[0],",","")); + if (beatt <= beat) + returningBPM = bpm; + } + return returningBPM; + } + + function readHeaderLine(line:String) + { + var propName = line.split('#')[1].split(':')[0]; + var value = line.split(':')[1].split(';')[0]; + var prop = Reflect.getProperty(this,propName); + + if (prop != null) + { + Reflect.setProperty(this,propName,value); + } + } +} +#end \ No newline at end of file diff --git a/source/smTools/SMMeasure.hx b/source/smTools/SMMeasure.hx new file mode 100644 index 0000000..4519cbd --- /dev/null +++ b/source/smTools/SMMeasure.hx @@ -0,0 +1,29 @@ +#if sys +package smTools; + +class SMMeasure +{ + public var notes:Array; + + private var _measure:Array; + + public function new(measureData:Array) + { + _measure = measureData; + notes = []; + + // 0 = no note + // 1 = normal note + // 2 = head of sustain + // 3 = tail of sustain + + for(i in measureData) + { + for (ii in 0...i.length) + { + notes.push(new SMNote(i.split('')[ii],ii)); + } + } + } +} +#end \ No newline at end of file diff --git a/source/smTools/SMNote.hx b/source/smTools/SMNote.hx new file mode 100644 index 0000000..0a97f63 --- /dev/null +++ b/source/smTools/SMNote.hx @@ -0,0 +1,15 @@ +#if sys +package smTools; + +class SMNote +{ + public var data:String; + public var lane:Int; + + public function new(_data:String,_lane:Int) + { + data = _data; + lane = _lane; + } +} +#end \ No newline at end of file diff --git a/version.downloadMe b/version.downloadMe index b03f579..a061bd3 100644 --- a/version.downloadMe +++ b/version.downloadMe @@ -1,6 +1,8 @@ -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 +1.6; +- Full reworked charter +- BPM Changes & Scroll Speed Change Support +- StepMania File Format support +- Pre-loading for characters option +- New Main Menu Remix +- Difficulty Calculator +- Held note rework \ No newline at end of file