diff --git a/ISSUES-WITH-ISSUES.md b/ISSUES-WITH-ISSUES.md new file mode 100644 index 0000000..f93ec30 --- /dev/null +++ b/ISSUES-WITH-ISSUES.md @@ -0,0 +1,22 @@ +# Addressing Various Topics Related to Issues &/Or Discussions + +Read this before making an issue. It pretty much just tells you what and what not to complain about. +## Issues + +### What should go in an issue? +An issue should adhere to one of the two templates, Bug Report or Enhancement. (You can also create from blank but meh) + +An issue should NOT be related to any problems in forks or mods of Kade Engine. + +What the individual issue templates are for is self-explanatory, but please ACTUALLY use them. Don't just leave them blank and put all or partial info in the title. + + +## Discussions + +### What should go in a discussion? +Discussions should be related to mods or forks of Kade Engine, as well as topics related to building the game from source. + +> issues are for suggestions/bugs with kade engine itself, not with forks/mods of it. + + +This whole thing was made by Prokube's head and a comment by daniel11420. diff --git a/Modding.md b/Modding.md deleted file mode 100644 index 4b52fd8..0000000 --- a/Modding.md +++ /dev/null @@ -1,13 +0,0 @@ -# RIGHT NOW THE MODS FOLDER DOES NOT WORK ENTIRELY JUST YET!!! -## THIS IS WORK IN PROGRESS!!! - -# QUICK AND DIRTY MOD GUIDE - -With the 0.2.6 update, I added a bit of a slightly nicer mod support backend. - -It's POLYMOD, which is made by Lars Doucet: https://github.com/larsiusprime/polymod - -You may have noticed that there's a new folder in the assets. MODS. Within it you will see 2 files. modList.txt, and a folder called introMod. -modList.txt will load any folder into the game. Put the folder you want to load into a new line in modList.txt, and reboot the game. - -Now you may be wondering, what do I put in the folder? Well later down it'll get a bit more complicated, especially as I'll make the IN-GAME mod loader nicer. \ No newline at end of file diff --git a/Project.xml b/Project.xml index c9a144e..f537d99 100644 --- a/Project.xml +++ b/Project.xml @@ -94,7 +94,7 @@ - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/songs/dadbattle/Inst.mp3 b/assets/songs/dad battle/Inst.mp3 similarity index 100% rename from assets/songs/dadbattle/Inst.mp3 rename to assets/songs/dad battle/Inst.mp3 diff --git a/assets/songs/dadbattle/Inst.ogg b/assets/songs/dad battle/Inst.ogg similarity index 100% rename from assets/songs/dadbattle/Inst.ogg rename to assets/songs/dad battle/Inst.ogg diff --git a/assets/songs/dadbattle/Voices.mp3 b/assets/songs/dad battle/Voices.mp3 similarity index 100% rename from assets/songs/dadbattle/Voices.mp3 rename to assets/songs/dad battle/Voices.mp3 diff --git a/assets/songs/dadbattle/Voices.ogg b/assets/songs/dad battle/Voices.ogg similarity index 100% rename from assets/songs/dadbattle/Voices.ogg rename to assets/songs/dad battle/Voices.ogg diff --git a/assets/songs/philly/Inst.mp3 b/assets/songs/philly nice/Inst.mp3 similarity index 100% rename from assets/songs/philly/Inst.mp3 rename to assets/songs/philly nice/Inst.mp3 diff --git a/assets/songs/philly/Inst.ogg b/assets/songs/philly nice/Inst.ogg similarity index 100% rename from assets/songs/philly/Inst.ogg rename to assets/songs/philly nice/Inst.ogg diff --git a/assets/songs/philly/Voices.mp3 b/assets/songs/philly nice/Voices.mp3 similarity index 100% rename from assets/songs/philly/Voices.mp3 rename to assets/songs/philly nice/Voices.mp3 diff --git a/assets/songs/philly/Voices.ogg b/assets/songs/philly nice/Voices.ogg similarity index 100% rename from assets/songs/philly/Voices.ogg rename to assets/songs/philly nice/Voices.ogg diff --git a/assets/songs/satin-panties/Inst.mp3 b/assets/songs/satin panties/Inst.mp3 similarity index 100% rename from assets/songs/satin-panties/Inst.mp3 rename to assets/songs/satin panties/Inst.mp3 diff --git a/assets/songs/satin-panties/Inst.ogg b/assets/songs/satin panties/Inst.ogg similarity index 100% rename from assets/songs/satin-panties/Inst.ogg rename to assets/songs/satin panties/Inst.ogg diff --git a/assets/songs/satin-panties/Voices.mp3 b/assets/songs/satin panties/Voices.mp3 similarity index 100% rename from assets/songs/satin-panties/Voices.mp3 rename to assets/songs/satin panties/Voices.mp3 diff --git a/assets/songs/satin-panties/Voices.ogg b/assets/songs/satin panties/Voices.ogg similarity index 100% rename from assets/songs/satin-panties/Voices.ogg rename to assets/songs/satin panties/Voices.ogg diff --git a/assets/songs/winter-horrorland/Inst.mp3 b/assets/songs/winter horrorland/Inst.mp3 similarity index 100% rename from assets/songs/winter-horrorland/Inst.mp3 rename to assets/songs/winter horrorland/Inst.mp3 diff --git a/assets/songs/winter-horrorland/Inst.ogg b/assets/songs/winter horrorland/Inst.ogg similarity index 100% rename from assets/songs/winter-horrorland/Inst.ogg rename to assets/songs/winter horrorland/Inst.ogg diff --git a/assets/songs/winter-horrorland/Voices.mp3 b/assets/songs/winter horrorland/Voices.mp3 similarity index 100% rename from assets/songs/winter-horrorland/Voices.mp3 rename to assets/songs/winter horrorland/Voices.mp3 diff --git a/assets/songs/winter-horrorland/Voices.ogg b/assets/songs/winter horrorland/Voices.ogg similarity index 100% rename from assets/songs/winter-horrorland/Voices.ogg rename to assets/songs/winter horrorland/Voices.ogg diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index 3d0ec4d..0000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -funkin.me \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..ecfe66a --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,7 @@ +theme: jekyll-theme-minimal +title: "Kade Engine" +description: "Kade Engine is a mod for Friday Night Funkin', including a full engine rework, replays, and more." +show_downloads: true +replace_index_with: "https://cors-thing.puyo.workers.dev/master/" +logo: "https://github.com/KadeDev/Kade-Engine/raw/master/KadeEngineLogo.png" +url: "https://KadeDev.github.io/Kade-Engine/" diff --git a/docs/_includes/header.html b/docs/_includes/header.html new file mode 100644 index 0000000..b5765cd --- /dev/null +++ b/docs/_includes/header.html @@ -0,0 +1,34 @@ + +
+

+ Changelogs + Building + Modcharts + Guides +
  +


+

+
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html new file mode 100644 index 0000000..d46a7c9 --- /dev/null +++ b/docs/_layouts/default.html @@ -0,0 +1,93 @@ + + + + + + + {{page.title}} - Kade Engine + +{% seo %} + + + + +
+
+

{{ site.title | default: site.github.repository_name }}

+ + {% if site.logo %} + Logo + {% endif %} + +

{{ site.description | default: site.github.project_tagline }}

+ + {% if site.github.is_project_page %} +

View the Project on GitHub {{ site.github.repository_nwo }}

+ {% endif %} + + {% if site.github.is_user_page %} +

View My GitHub Profile

+ {% endif %} + + {% if site.show_downloads %} +

+ Source code +

+

+

+ Binaries
+ Download the Latest release
+ Download a Windows development build
+ Download a Linux development build
+ Play in your Web Browser +

+ {% endif %} +
+
+ {% include header.html %} + {% if page.url == "/" %} + + {% else %} + {{ content }} + {% endif %} + +
+ +
+ + {% if page.url == "/" %} + + + {% endif %} + {% if site.google_analytics %} + + {% endif %} + + diff --git a/BUILDING.md b/docs/building.md similarity index 87% rename from BUILDING.md rename to docs/building.md index 554e3d1..ea1e885 100644 --- a/BUILDING.md +++ b/docs/building.md @@ -1,6 +1,6 @@ # Building Friday Night Funkin': Kade Engine -**Please note** that these instructions are for compiling/building the game. If you just want to play Kade Engine, **play in your browser or download a build instead**: **[play in browser](https://funkin.puyo.xyz) ⋅ [latest stable release](https://github.com/KadeDev/Kade-Engine/releases/latest) ⋅ [latest development build (windows)](https://ci.appveyor.com/project/KadeDev/kade-engine-windows/build/artifacts) ⋅ [latest development build (linux)](https://ci.appveyor.com/project/daniel11420/kade-engine-linux/build/artifacts)**. If you want to build the game yourself, continue reading. +**Please note** that these instructions are for compiling/building the game. If you just want to play Kade Engine, **play in your browser or download a build instead**: **[play in browser](https://funkin.puyo.xyz) ⋅ [latest stable release](https://github.com/KadeDev/Kade-Engine/releases/latest) ⋅ [latest development build (windows)](https://ci.appveyor.com/project/KadeDev/kade-engine-windows/build/artifacts) ⋅ [latest development build (macOS)](https://ci.appveyor.com/project/daniel11420/kade-engine-macos/build/artifacts) ⋅ [latest development build (linux)](https://ci.appveyor.com/project/daniel11420/kade-engine-linux/build/artifacts)**. If you want to build the game yourself, continue reading. **Also note**: you should be familiar with the commandline. If not, read this [quick guide by ninjamuffin](https://ninjamuffin99.newgrounds.com/news/post/1090480). @@ -28,6 +28,7 @@ - `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` + ### 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 @@ -57,10 +58,11 @@ Since you already installed `git` in a previous step, we'll use it to clone the 2. `git clone https://github.com/KadeDev/Kade-Engine.git` 3. `cd` into the source code: `cd Kade-Engine` 4. (optional) If you want to build a specific version of Kade Engine, you can use `git checkout` to switch to it (i.e. `git checkout 1.4-KE`) (remember that versions 1.4 and older cannot build to Linux or HTML5) - - You should **not** do this if you are planning to contribute, as you should always be developing on the latest version. +- You should **not** do this if you are planning to contribute, as you should always be developing on the latest version. + ## Building Finally, we are ready to build. -- Run `lime build `, replacing `` with the platform you want to build to (`windows`, `linux`, `html5`) (i.e. `lime build windows`) +- Run `lime build `, replacing `` with the platform you want to build to (`windows`, `mac`, `linux`, `html5`) (i.e. `lime build windows`) - The build will be in `Kade-Engine/export//bin`, with `` being the target you built to in the previous step. (i.e. `Kade-Engine/export/windows/bin`) - - Only the `bin` folder is necessary to run the game. The other ones in `export/` are not. +- Only the `bin` folder is necessary to run the game. The other ones in `export/` are not. diff --git a/CHANGELOG.md b/docs/changelogs/changelog-pre.md similarity index 98% rename from CHANGELOG.md rename to docs/changelogs/changelog-pre.md index 859ccc3..83b611c 100644 --- a/CHANGELOG.md +++ b/docs/changelogs/changelog-pre.md @@ -1,5 +1,5 @@ -# Changelog -All notable changes will be documented in this file. +# Changelog for 1.4.2 and before +Changelogs from before the current changelog system existed. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/docs/changelogs/changelog-template.md b/docs/changelogs/changelog-template.md new file mode 100644 index 0000000..acf810d --- /dev/null +++ b/docs/changelogs/changelog-template.md @@ -0,0 +1,24 @@ +# Latest changelog/Changelog for 1.0.0 + +Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`. + +### Additions +- New thing without issue +- [#1](https://github.com/KadeDev/Kade-Engine/issues/1): New thing with issue +- [#1](https://github.com/KadeDev/Kade-Engine/issues/1) ([PR #1](https://github.com/KadeDev/Kade-Engine/pulls/1)): New thing with issue and pull request +- [PR #1](https://github.com/KadeDev/Kade-Engine/pulls/1): New thing with pull request but no issue +- 💖 [PR #1](https://github.com/KadeDev/Kade-Engine/pulls/1): New thing with pull request but no issue and it's going in the short changelog + +### Changes +- Use same templates as additions +- Changes also includes stuff getting removed (as that happens less often so include it with changes) + +### Bugfixes +- Use same templates as additions +- This is for when bugs get fixed. This should, like, always have an issue link, most of the time (if it has one) + +## Links +[GitHub Release](https://github.com/KadeDev/Kade-Engine/releases/tag/1.4.2) · [Last Windows CI build]() · [Last macOS CI build]() · [Last Linux CI build]() + +// Only include links section after it is no longer "latest changelog" +// "Last x CI build" links should link to a specific build, the last one for the version diff --git a/docs/changelogs/index.md b/docs/changelogs/index.md new file mode 100644 index 0000000..30d502f --- /dev/null +++ b/docs/changelogs/index.md @@ -0,0 +1,4 @@ +# Changelogs + +- [Latest](latest) (Contains changes that are not in a release yet) +- [1.4.2 and before](changelog-pre) diff --git a/docs/changelogs/latest.md b/docs/changelogs/latest.md new file mode 100644 index 0000000..6db0b2d --- /dev/null +++ b/docs/changelogs/latest.md @@ -0,0 +1,39 @@ +# Latest changelog + +Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`. + +### Additions +- [PR #307](https://github.com/KadeDev/Kade-Engine/pulls/307): Fix freeplay lag, add freeplay background changes, and add icons updating in charting state +- Updated to Week 7 input with anti mash +- 💖 Added toggle for ghost tapping +- 💖 [PR #328](https://github.com/KadeDev/Kade-Engine/pulls/328) and [PR #331](https://github.com/KadeDev/Kade-Engine/pulls/331): Distractions toggle +- [PR #341](https://github.com/KadeDev/Kade-Engine/pull/341): Update heads in realtime in charting state +- 💖 [PR #362](https://github.com/KadeDev/Kade-Engine/pull/362): Officially support macOS (and add macOS requirements to docs) +- Set up macOS CI builds +- [PR #373](https://github.com/KadeDev/Kade-Engine/pull/373): Add tweens to modcharts +- [PR #367](https://github.com/KadeDev/Kade-Engine/pull/367): Add labels to charting state +- [PR #374](https://github.com/KadeDev/Kade-Engine/pull/374): Add more icon sizes +- 💖 [PR #385](https://github.com/KadeDev/Kade-Engine/pull/385): Autoplay +- (maybe 💖) [#353](https://github.com/KadeDev/Kade-Engine/issues/353) ([PR #400](https://github.com/KadeDev/Kade-Engine/pulls/400)): Clap assist for syncing charts +- [PR #413](https://github.com/KadeDev/Kade-Engine/pulls/413): Option to disable flashing lights in menus +- [PR #428](https://github.com/KadeDev/Kade-Engine/pulls/428): Move documentation to GitHub Pages + new changelog system +- [PR #431](https://github.com/KadeDev/Kade-Engine/pull/431): Add Max NPS counter + +### Changes +- Tutorial is now a modchart instead of being hardcoded +- [PR #332](https://github.com/KadeDev/Kade-Engine/pull/332): Move the beatbox in Fresh to the vocal track +- [PR #334](https://github.com/KadeDev/Kade-Engine/pull/334): Unhardcode GF Version, stages, and noteskins and make them loaded from chart +- [PR #291](https://github.com/KadeDev/Kade-Engine/pull/291): Make it so you can compile with 4.0.x +- 💖 [PR #440](https://github.com/KadeDev/Kade-Engine/pull/440): Change how replays work + store scroll speed and direction in replays + +### Bugfixes +- [PR #289](https://github.com/KadeDev/Kade-Engine/pulls/289): Player 2 now plays idle animation properly when camera zooms in +- (maybe 💖) [PR #314](https://github.com/KadeDev/Kade-Engine/pulls/314): Fix note trails +- [PR #330](https://github.com/KadeDev/Kade-Engine/pull/330): Fix spelling errors in options +- [#329](https://github.com/KadeDev/Kade-Engine/issues/329) ([PR #341](https://github.com/KadeDev/Kade-Engine/pull/341)): Fix crash when changing characters in charting state on web +- [PR #341](https://github.com/KadeDev/Kade-Engine/pull/341): Fix html5 crash (when building), fix layering issues in charting state, fix charting state crashes in html5 +- [PR #376](https://github.com/KadeDev/Kade-Engine/pull/376): Fix must hit sections +- [#368](https://github.com/KadeDev/Kade-Engine/issues/368) ([PR #392](https://github.com/KadeDev/Kade-Engine/pull/392)): Fix enemy idle animations not playing before first note +- [PR #399](https://github.com/KadeDev/Kade-Engine/pulls/399): Fix downscroll typo +- [PR #431](https://github.com/KadeDev/Kade-Engine/pull/431): Fix NPS counter +- [#404](https://github.com/KadeDev/Kade-Engine/issues/404) ([PR #446](https://github.com/KadeDev/Kade-Engine/pull/446)): Fix bug where Alt Animation in charting state doesn't stay checked after going to another section then back diff --git a/docs/guides/index.md b/docs/guides/index.md new file mode 100644 index 0000000..a1b30c6 --- /dev/null +++ b/docs/guides/index.md @@ -0,0 +1,10 @@ +# Guides +[Creating A Custom Week](https://kadedev.github.io/Kade-Engine/guides/weeks) + +### Contributing +If you'd like to write a guide, you can make a [pull request](https://github.com/KadeDev/Kade-Engine/pulls). Make sure you put the guide in `docs/guides/` and that it's written in Markdown. + +Guides that need to be written: +- How to use the charting state/chart editor +- How to make custom dialogue (like Week 6) +- How to make custom characters diff --git a/docs/guides/weeks.md b/docs/guides/weeks.md new file mode 100644 index 0000000..90b89ca --- /dev/null +++ b/docs/guides/weeks.md @@ -0,0 +1,158 @@ +# Creating A Custom Week + +## Requirements +1. The ability to compile Kade Engine from the source code. All information related to building Kade Engine is listed [here.](https://kadedev.github.io/Kade-Engine/building) +2. A text editor. Some form of IDE that can support Haxe is recommended, such as Visual Studio Code. + +--- +### Step 1. Navigation +Navigate to your Kade Engine source code. In the `source` folder, look for `StoryMenuState.hx`. Open it in your text editor. + +### Step 2. Songlist + +Scroll down to Line 26, or Search (Windows/Linux: `Ctrl+F`, Mac: `Cmd+F`) for "weekData". You should find an Array that looks like this: + +--- + +```haxe +var weekData:Array = [ + + ['Tutorial'], + + ['Bopeebo', 'Fresh', 'Dadbattle'], + + ['Spookeez', 'South', "Monster"], + + ['Pico', 'Philly', "Blammed"], + + ['Satin-Panties', "High", "Milf"], + + ['Cocoa', 'Eggnog', 'Winter-Horrorland'], + + ['Senpai', 'Roses', 'Thorns'] + +]; +``` + +--- + +Copy `['Senpai', 'Roses', 'Thorns']` into an empty line below it, and change the song names to the song names you want to use. +Don't forget to add a comma at the end of the previous Week, and you have your songlist for the week completed! + +Example +--- + +--- + +```haxe +var weekData:Array = [ + + ['Tutorial'], + + ['Bopeebo', 'Fresh', 'Dadbattle'], + + ['Spookeez', 'South', "Monster"], + + ['Pico', 'Philly', "Blammed"], + + ['Satin-Panties', "High", "Milf"], + + ['Cocoa', 'Eggnog', 'Winter-Horrorland'], + + ['Senpai', 'Roses', 'Thorns'], + + ['Ugh', 'Guns', 'Stress'] + +]; +``` + +--- + +### Step 3. Week Characters +Directly below the songlist should be an Array titled `weekCharacters`. This array tells the game what characters to display in the top yellow bar when a certain week is selected. +It's not very useful unless you followed the Characters guide (will link to it once it's actually done). If you have, though, you can insert the name of your character into the first pair of quotes in a new "week". Example: + +Example +--- + +--- + +```haxe +var weekCharacters:Array = [ + + ['', 'bf', 'gf'], + + ['dad', 'bf', 'gf'], + + ['spooky', 'bf', 'gf'], + + ['pico', 'bf', 'gf'], + + ['mom', 'bf', 'gf'], + + ['parents-christmas', 'bf', 'gf'], + + ['senpai', 'bf', 'gf'], + + ['tankman', 'bf', 'gf'] + + ]; +``` + +--- + +### 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. + +Example +--- + +--- +```haxe +var weekNames:Array = [ + + "How to Funk", + + "Daddy dearest", + + "Spooky Month", + + "PICO", + + "Mommy Must Murder", + + "Red Snow", + + "Hating Simulator ft. Moawlings", + + "Tankman" + +]; +``` + +--- + + Now, compile the game, and if all goes correctly, the Story Mode menu shouldn't crash your game. If you make your way to the bottom of the list, there's your custom week! Except... its displaying as a HaxeFlixel Logo? + +### 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. + +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) + + +### Conclusion + +If you followed all of the steps correctly, you have successfully created a new week in the Story Mode. diff --git a/docs/img/skin-funkin-cardbordtoast.jpg b/docs/img/skin-funkin-cardbordtoast.jpg deleted file mode 100644 index dd0e96e..0000000 Binary files a/docs/img/skin-funkin-cardbordtoast.jpg and /dev/null differ diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 11137c6..0000000 --- a/docs/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - Friday Night Funkin' - - - - - - - - - -
-
- - - Friday Night Funkin - -
-

Friday Night Funkin' - Rhythm game extraordinaire

- - -
-
- -
-
- - -
-

Friday Night Funkin' is a dope ass rhythm game.

-

It is made by ninjamuffin99 (programmer), PhantomArcade (animator), evilsk8r (artist), - and Kawaisprite (musician) originally for Ludum Dare 47.

-
- - - - - -
- - \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..3fa1626 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,3 @@ +# Readme + +Index is automatically replaced with README by the layout. So, this file does nothing. diff --git a/ModCharts.md b/docs/modchart.md similarity index 87% rename from ModCharts.md rename to docs/modchart.md index 4f9f40e..a8bdfbe 100644 --- a/ModCharts.md +++ b/docs/modchart.md @@ -1,16 +1,12 @@ -# Kade Engine Lua Mod Chart Documentation +# Lua Modcharts In the 1.4.2 release of Kade Engine, we introduced Mod Charts. Mod Charts are a way of changing gameplay without hard coded values. This is achieved by using the Lua Scripting language to create script files that run during runtime. -All files **are located in** `assets/data/song/` +Song data is located in `assets/data//`, so the Lua file containing your scripts should be located at exactly `assets/data//modchart.lua`. (replace with the name of the song. for example, `assets/data/milf/` for milf) -Modchart Lua File should be in `assets/data/song/modchart.lua` **exactly** +If the file doesn't exist, Lua code won't be ran. -Lua code will only be ran if that file exists. - - - -### Examples +## Examples Full Example @@ -22,10 +18,10 @@ end function update (elapsed) -- example https://twitter.com/KadeDeveloper/status/1382178179184422918 local currentBeat = (songPos / 1000)*(bpm/60) - for i=0,7 do - setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i) - setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i) - end + for i=0,7 do + setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i) + setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i) + end end function beatHit (beat) @@ -43,9 +39,9 @@ Spinning Receptor Example ```lua function update (elapsed) - for i=0,7 do - setActorAngle(getActorAngle(i) + 15, i) - end + for i=0,7 do + setActorAngle(getActorAngle(i) + 15, i) + end end ``` @@ -68,11 +64,11 @@ function update (elapsed) setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i) end else - for i=0,7 do - setActorX(_G['defaultStrum'..i..'X'],i) - setActorY(_G['defaultStrum'..i..'Y'],i) - end - end + for i=0,7 do + setActorX(_G['defaultStrum'..i..'X'],i) + setActorY(_G['defaultStrum'..i..'Y'],i) + end + end end ``` @@ -90,23 +86,23 @@ end Looping through all of the rendered notes ```lua - for i = 0, getRenderedNotes() do -- sets all of the rendered notes to 0 0 on the x and y axsis - setRenderedNotePos(0,0,i) - end +for i = 0, getRenderedNotes() do -- sets all of the rendered notes to 0 0 on the x and y axsis + setRenderedNotePos(0,0,i) +end ``` Centering BF's Side ```lua - function setDefault(id) - _G['defaultStrum'..id..'X'] = getActorX(id) - end +function setDefault(id) + _G['defaultStrum'..id..'X'] = getActorX(id) +end - -- put this somewhere in a function +-- put this somewhere in a function - for i = 4, 7 do -- go to the center - tweenPosXAngle(i, _G['defaultStrum'..i..'X'] - 275,getActorAngle(i) + 360, 0.6, 'setDefault') - end +for i = 4, 7 do -- go to the center + tweenPosXAngle(i, _G['defaultStrum'..i..'X'] - 275,getActorAngle(i) + 360, 0.6, 'setDefault') +end ``` @@ -116,10 +112,10 @@ Current calls to functions include, | Name | Arguments | Description | | :-----: | :------------: | :----------------------------------------------------------: | -| start | Song Name | Get's called when the song starts | -| update | Elapsed frames | Get's called every frame (after the song starts) | -| stepHit | Current Step | Get's called when ever a step hits (steps are in between beats, aka 4 steps are in a beat) | -| beatHit | Current Beat | Get's called when ever a beat hits | +| start | Song Name | Gets called when the song starts | +| update | Elapsed frames | Gets called every frame (after the song starts) | +| stepHit | Current Step | Gets called when ever a step hits (steps are in between beats, aka 4 steps are in a beat) | +| beatHit | Current Beat | Gets called when ever a beat hits | @@ -175,13 +171,13 @@ These premade id's are the following: Creates a sprite out of the specified image, returns the id you gave it. -*Note: Sprite Path is normally the FILE NAME so if you have a file name of Image it'll go to assets/data/songName/Image.png so don't include the extension* +*Note: Sprite Path is normally the FILE NAME so if your file is named `Image` it'll go to assets/data/songName/Image.png so don't include the extension* ### Hud/Camera ##### setHudPosition(int x, int y) -Set's the game hud's position in space. +Sets the game hud's position in space. ##### getHudX() diff --git a/docs/styles.css b/docs/styles.css deleted file mode 100644 index 5ee1062..0000000 --- a/docs/styles.css +++ /dev/null @@ -1,97 +0,0 @@ -.coolBox { - background: #1a1a1aCC; - margin: 40px 4vw; - padding: 25px; - font-size: 120%; - border-radius: 10px; -} - -#wrapper -{ - padding: 20px; - margin: auto; -} - -marquee { - margin: auto; - text-align: center; - display: inline-block; -} - -h1 { - text-align: center; -} - -body { - background-image: url('img/skin-funkin-cardbordtoast.jpg'); - background-repeat: no-repeat; - background-attachment: fixed; - background-size: cover; - color:white; - background-color: #000; - font-family: Arial, Helvetica, sans-serif; - -} - -a { color:inherit; - text-decoration: none;} - - -.hovertext a{ - color:white; - text-shadow: 0px 0px #00000077; - transition: color 1s, text-shadow 1s; -} - -.hovertext a:hover -{ - text-shadow: 2px 2px #00000077; - color: #ffb50e; -} - -.linktext { - text-align: center; - display:block; - font-size: 130%; - padding-bottom: 10px; -} - -.linktext a { - font-weight: bold; -} - -.linktext a:hover { - border-radius: 5px; -} - -#itch a:hover -{ - color: #fa5c5c; -} -#twitter a:hover -{ - color: #00acee; -} - - -#coolervidwrapper { - padding-left: min(12em, 75%); - padding-right: min(12em, 75%); - min-width: 30%; -} - -.videoWrapper { - position: relative; - padding-bottom: 56.25%; /* 16:9 */ - height: 0; - - max-block-size: 1400px; -} -.videoWrapper iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - -} diff --git a/source/Alphabet.hx b/source/Alphabet.hx index 6f7e711..c16de50 100644 --- a/source/Alphabet.hx +++ b/source/Alphabet.hx @@ -238,7 +238,7 @@ class AlphaCharacter extends FlxSprite public static var numbers:String = "1234567890"; - public static var symbols:String = "|~#$%()*+-:;<=>@[]^_.,'!?"; + public static var symbols:String = "|~#$%()*+-:;<=>@[]^_.,'!? "; public var row:Int = 0; @@ -302,6 +302,48 @@ class AlphaCharacter extends FlxSprite case "!": animation.addByPrefix(letter, 'exclamation point', 24); animation.play(letter); + case '_': + animation.addByPrefix(letter, '_', 24); + animation.play(letter); + y += 50; + case "#": + animation.addByPrefix(letter, '#', 24); + animation.play(letter); + case "$": + animation.addByPrefix(letter, '$', 24); + animation.play(letter); + case "%": + animation.addByPrefix(letter, '%', 24); + animation.play(letter); + case "&": + animation.addByPrefix(letter, '&', 24); + animation.play(letter); + case "(": + animation.addByPrefix(letter, '(', 24); + animation.play(letter); + case ")": + animation.addByPrefix(letter, ')', 24); + animation.play(letter); + case "+": + animation.addByPrefix(letter, '+', 24); + animation.play(letter); + case "-": + animation.addByPrefix(letter, '-', 24); + animation.play(letter); + case '"': + animation.addByPrefix(letter, '"', 24); + animation.play(letter); + y -= 0; + case '@': + animation.addByPrefix(letter, '@', 24); + animation.play(letter); + case "^": + animation.addByPrefix(letter, '^', 24); + animation.play(letter); + y -= 0; + case ' ': + animation.addByPrefix(letter, 'space', 24); + animation.play(letter); } updateHitbox(); diff --git a/source/ChartingState.hx b/source/ChartingState.hx index 7d11cd2..105d2a1 100644 --- a/source/ChartingState.hx +++ b/source/ChartingState.hx @@ -55,7 +55,7 @@ class ChartingState extends MusicBeatState var bpmTxt:FlxText; var strumLine:FlxSprite; - var curSong:String = 'Dadbattle'; + var curSong:String = 'Dad Battle'; var amountSteps:Int = 0; var bullshitUI:FlxGroup; var writingNotesText:FlxText; @@ -515,7 +515,7 @@ class ChartingState extends MusicBeatState case 'Change BPM': _song.notes[curSection].changeBPM = check.checked; FlxG.log.add('changed bpm shit'); - case "Alt Animation": + case "Alternate Animation": _song.notes[curSection].altAnim = check.checked; } } @@ -670,8 +670,8 @@ class ChartingState extends MusicBeatState else FlxG.sound.play(Paths.sound('SNAP')); } }); - } - }); + } + }); /*curRenderedNotes.forEach(function(note:Note) { if (strumLine.overlaps(note) && strumLine.y == note.y) // yandere dev type shit @@ -1390,4 +1390,4 @@ class ChartingState extends MusicBeatState _file = null; FlxG.log.error("Problem saving Level data"); } -} \ No newline at end of file +} diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index 59ecc70..53af317 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -149,7 +149,7 @@ class FreeplayState extends MusicBeatState public function addWeek(songs:Array, weekNum:Int, ?songCharacters:Array) { if (songCharacters == null) - songCharacters = ['bf']; + songCharacters = ['dad']; var num:Int = 0; for (song in songs) diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 4957316..63e3c0e 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -1,239 +1,254 @@ -package; - -import Controls.KeyboardScheme; -import flixel.FlxG; -import flixel.FlxObject; -import flixel.FlxSprite; -import flixel.effects.FlxFlicker; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.text.FlxText; -import flixel.tweens.FlxEase; -import flixel.tweens.FlxTween; -import flixel.util.FlxColor; -import io.newgrounds.NG; -import lime.app.Application; - -#if windows -import Discord.DiscordClient; -#end - -using StringTools; - -class MainMenuState extends MusicBeatState -{ - var curSelected:Int = 0; - - var menuItems:FlxTypedGroup; - - #if !switch - var optionShit:Array = ['story mode', 'freeplay', 'donate', 'options']; - #else - var optionShit:Array = ['story mode', 'freeplay']; - #end - - var newGaming:FlxText; - var newGaming2:FlxText; - var newInput:Bool = true; - - public static var nightly:String = ""; - - public static var kadeEngineVer:String = "1.4.2" + nightly; - public static var gameVer:String = "0.2.7.1"; - - var magenta:FlxSprite; - var camFollow:FlxObject; - - override function create() - { - #if windows - // Updating Discord Rich Presence - DiscordClient.changePresence("In the Menus", null); - #end - - if (!FlxG.sound.music.playing) - { - FlxG.sound.playMusic(Paths.music('freakyMenu')); - } - - persistentUpdate = persistentDraw = true; - - var bg:FlxSprite = new FlxSprite(-80).loadGraphic(Paths.image('menuBG')); - bg.scrollFactor.x = 0; - bg.scrollFactor.y = 0.15; - bg.setGraphicSize(Std.int(bg.width * 1.1)); - bg.updateHitbox(); - bg.screenCenter(); - bg.antialiasing = true; - add(bg); - - camFollow = new FlxObject(0, 0, 1, 1); - add(camFollow); - - magenta = new FlxSprite(-80).loadGraphic(Paths.image('menuDesat')); - magenta.scrollFactor.x = 0; - magenta.scrollFactor.y = 0.18; - magenta.setGraphicSize(Std.int(magenta.width * 1.1)); - magenta.updateHitbox(); - magenta.screenCenter(); - magenta.visible = false; - magenta.antialiasing = true; - magenta.color = 0xFFfd719b; - add(magenta); - // magenta.scrollFactor.set(); - - menuItems = new FlxTypedGroup(); - add(menuItems); - - var tex = Paths.getSparrowAtlas('FNF_main_menu_assets'); - - for (i in 0...optionShit.length) - { - var menuItem:FlxSprite = new FlxSprite(0, 60 + (i * 160)); - menuItem.frames = tex; - menuItem.animation.addByPrefix('idle', optionShit[i] + " basic", 24); - menuItem.animation.addByPrefix('selected', optionShit[i] + " white", 24); - menuItem.animation.play('idle'); - menuItem.ID = i; - menuItem.screenCenter(X); - menuItems.add(menuItem); - menuItem.scrollFactor.set(); - menuItem.antialiasing = true; - } - - FlxG.camera.follow(camFollow, null, 0.60 * (60 / FlxG.save.data.fpsCap)); - - var versionShit:FlxText = new FlxText(5, FlxG.height - 18, 0, gameVer + (Main.watermarks ? " FNF - " + kadeEngineVer + " Kade Engine" : ""), 12); - versionShit.scrollFactor.set(); - versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - add(versionShit); - - // NG.core.calls.event.logEvent('swag').send(); - - - if (FlxG.save.data.dfjk) - controls.setKeyboardScheme(KeyboardScheme.Solo, true); - else - controls.setKeyboardScheme(KeyboardScheme.Duo(true), true); - - changeItem(); - - super.create(); - } - - var selectedSomethin:Bool = false; - - override function update(elapsed:Float) - { - if (FlxG.sound.music.volume < 0.8) - { - FlxG.sound.music.volume += 0.5 * FlxG.elapsed; - } - - if (!selectedSomethin) - { - if (controls.UP_P) - { - FlxG.sound.play(Paths.sound('scrollMenu')); - changeItem(-1); - } - - if (controls.DOWN_P) - { - FlxG.sound.play(Paths.sound('scrollMenu')); - changeItem(1); - } - - if (controls.BACK) - { - FlxG.switchState(new TitleState()); - } - - if (controls.ACCEPT) - { - if (optionShit[curSelected] == 'donate') - { - #if linux - Sys.command('/usr/bin/xdg-open', ["https://ninja-muffin24.itch.io/funkin", "&"]); - #else - FlxG.openURL('https://ninja-muffin24.itch.io/funkin'); - #end - } - else - { - selectedSomethin = true; - FlxG.sound.play(Paths.sound('confirmMenu')); - - if(FlxG.save.data.flashing){ - FlxFlicker.flicker(magenta, 1.1, 0.15, false); - } - - menuItems.forEach(function(spr:FlxSprite) - { - if (curSelected != spr.ID) - { - FlxTween.tween(spr, {alpha: 0}, 1.3, { - ease: FlxEase.quadOut, - onComplete: function(twn:FlxTween) - { - spr.kill(); - } - }); - } - else - { - FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker) - { - var daChoice:String = optionShit[curSelected]; - - switch (daChoice) - { - case 'story mode': - FlxG.switchState(new StoryMenuState()); - trace("Story Menu Selected"); - case 'freeplay': - FlxG.switchState(new FreeplayState()); - - trace("Freeplay Menu Selected"); - - case 'options': - FlxG.switchState(new OptionsMenu()); - } - }); - } - }); - } - } - } - - super.update(elapsed); - - menuItems.forEach(function(spr:FlxSprite) - { - spr.screenCenter(X); - }); - } - - function changeItem(huh:Int = 0) - { - curSelected += huh; - - if (curSelected >= menuItems.length) - curSelected = 0; - if (curSelected < 0) - curSelected = menuItems.length - 1; - - menuItems.forEach(function(spr:FlxSprite) - { - spr.animation.play('idle'); - - if (spr.ID == curSelected) - { - spr.animation.play('selected'); - camFollow.setPosition(spr.getGraphicMidpoint().x, spr.getGraphicMidpoint().y); - } - - spr.updateHitbox(); - }); - } -} +package; + +import Controls.KeyboardScheme; +import flixel.FlxG; +import flixel.FlxObject; +import flixel.FlxSprite; +import flixel.effects.FlxFlicker; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxTimer; +import io.newgrounds.NG; +import lime.app.Application; + +#if windows +import Discord.DiscordClient; +#end + +using StringTools; + +class MainMenuState extends MusicBeatState +{ + var curSelected:Int = 0; + + var menuItems:FlxTypedGroup; + + #if !switch + var optionShit:Array = ['story mode', 'freeplay', 'donate', 'options']; + #else + var optionShit:Array = ['story mode', 'freeplay']; + #end + + var newGaming:FlxText; + var newGaming2:FlxText; + var newInput:Bool = true; + + public static var nightly:String = ""; + + public static var kadeEngineVer:String = "1.4.2" + nightly; + public static var gameVer:String = "0.2.7.1"; + + var magenta:FlxSprite; + var camFollow:FlxObject; + + override function create() + { + #if windows + // Updating Discord Rich Presence + DiscordClient.changePresence("In the Menus", null); + #end + + if (!FlxG.sound.music.playing) + { + FlxG.sound.playMusic(Paths.music('freakyMenu')); + } + + persistentUpdate = persistentDraw = true; + + var bg:FlxSprite = new FlxSprite(-80).loadGraphic(Paths.image('menuBG')); + bg.scrollFactor.x = 0; + bg.scrollFactor.y = 0.15; + bg.setGraphicSize(Std.int(bg.width * 1.1)); + bg.updateHitbox(); + bg.screenCenter(); + bg.antialiasing = true; + add(bg); + + camFollow = new FlxObject(0, 0, 1, 1); + add(camFollow); + + magenta = new FlxSprite(-80).loadGraphic(Paths.image('menuDesat')); + magenta.scrollFactor.x = 0; + magenta.scrollFactor.y = 0.18; + magenta.setGraphicSize(Std.int(magenta.width * 1.1)); + magenta.updateHitbox(); + magenta.screenCenter(); + magenta.visible = false; + magenta.antialiasing = true; + magenta.color = 0xFFfd719b; + add(magenta); + // magenta.scrollFactor.set(); + + menuItems = new FlxTypedGroup(); + add(menuItems); + + var tex = Paths.getSparrowAtlas('FNF_main_menu_assets'); + + for (i in 0...optionShit.length) + { + var menuItem:FlxSprite = new FlxSprite(0, 60 + (i * 160)); + menuItem.frames = tex; + menuItem.animation.addByPrefix('idle', optionShit[i] + " basic", 24); + menuItem.animation.addByPrefix('selected', optionShit[i] + " white", 24); + menuItem.animation.play('idle'); + menuItem.ID = i; + menuItem.screenCenter(X); + menuItems.add(menuItem); + menuItem.scrollFactor.set(); + menuItem.antialiasing = true; + } + + FlxG.camera.follow(camFollow, null, 0.60 * (60 / FlxG.save.data.fpsCap)); + + var versionShit:FlxText = new FlxText(5, FlxG.height - 18, 0, gameVer + (Main.watermarks ? " FNF - " + kadeEngineVer + " Kade Engine" : ""), 12); + versionShit.scrollFactor.set(); + versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + add(versionShit); + + // NG.core.calls.event.logEvent('swag').send(); + + + if (FlxG.save.data.dfjk) + controls.setKeyboardScheme(KeyboardScheme.Solo, true); + else + controls.setKeyboardScheme(KeyboardScheme.Duo(true), true); + + changeItem(); + + super.create(); + } + + var selectedSomethin:Bool = false; + + override function update(elapsed:Float) + { + if (FlxG.sound.music.volume < 0.8) + { + FlxG.sound.music.volume += 0.5 * FlxG.elapsed; + } + + if (!selectedSomethin) + { + if (controls.UP_P) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeItem(-1); + } + + if (controls.DOWN_P) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + changeItem(1); + } + + if (controls.BACK) + { + FlxG.switchState(new TitleState()); + } + + if (controls.ACCEPT) + { + if (optionShit[curSelected] == 'donate') + { + #if linux + Sys.command('/usr/bin/xdg-open', ["https://www.kickstarter.com/projects/funkin/friday-night-funkin-the-full-ass-game", "&"]); + #else + FlxG.openURL('https://www.kickstarter.com/projects/funkin/friday-night-funkin-the-full-ass-game'); + #end + } + else + { + selectedSomethin = true; + FlxG.sound.play(Paths.sound('confirmMenu')); + + if (FlxG.save.data.flashing) + FlxFlicker.flicker(magenta, 1.1, 0.15, false); + + menuItems.forEach(function(spr:FlxSprite) + { + if (curSelected != spr.ID) + { + FlxTween.tween(spr, {alpha: 0}, 1.3, { + ease: FlxEase.quadOut, + onComplete: function(twn:FlxTween) + { + spr.kill(); + } + }); + } + else + { + if (FlxG.save.data.flashing) + { + FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker) + { + goToState(); + }); + } + else + { + new FlxTimer().start(1, function(tmr:FlxTimer) + { + goToState(); + }); + } + } + }); + } + } + } + + super.update(elapsed); + + menuItems.forEach(function(spr:FlxSprite) + { + spr.screenCenter(X); + }); + } + + function goToState() + { + var daChoice:String = optionShit[curSelected]; + + switch (daChoice) + { + case 'story mode': + FlxG.switchState(new StoryMenuState()); + trace("Story Menu Selected"); + case 'freeplay': + FlxG.switchState(new FreeplayState()); + + trace("Freeplay Menu Selected"); + + case 'options': + FlxG.switchState(new OptionsMenu()); + } + } + + function changeItem(huh:Int = 0) + { + curSelected += huh; + + if (curSelected >= menuItems.length) + curSelected = 0; + if (curSelected < 0) + curSelected = menuItems.length - 1; + + menuItems.forEach(function(spr:FlxSprite) + { + spr.animation.play('idle'); + + if (spr.ID == curSelected) + { + spr.animation.play('selected'); + camFollow.setPosition(spr.getGraphicMidpoint().x, spr.getGraphicMidpoint().y); + } + + spr.updateHitbox(); + }); + } +} \ No newline at end of file diff --git a/source/MenuItem.hx b/source/MenuItem.hx index 6d08a95..5f8304b 100644 --- a/source/MenuItem.hx +++ b/source/MenuItem.hx @@ -37,14 +37,13 @@ class MenuItem extends FlxSpriteGroup { super.update(elapsed); y = FlxMath.lerp(y, (targetY * 120) + 480, 0.17 * (60 / FlxG.save.data.fpsCap)); - if(FlxG.save.data.flashing){ - if (isFlashing) - flashingInt += 1; + + if (isFlashing) + flashingInt += 1; - if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) - week.color = 0xFF33ffff; - else - week.color = FlxColor.WHITE; - } + if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) + week.color = 0xFF33ffff; + else if (FlxG.save.data.flashing) + week.color = FlxColor.WHITE; } } diff --git a/source/OutdatedSubState.hx b/source/OutdatedSubState.hx index 07a5064..5aeba3b 100644 --- a/source/OutdatedSubState.hx +++ b/source/OutdatedSubState.hx @@ -1,45 +1,98 @@ -package; - -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.FlxSubState; -import flixel.text.FlxText; -import flixel.util.FlxColor; -import lime.app.Application; - -class OutdatedSubState extends MusicBeatState -{ - public static var leftState:Bool = false; - - public static var needVer:String = "IDFK LOL"; - - override function create() - { - super.create(); - var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); - add(bg); - var txt:FlxText = new FlxText(0, 0, FlxG.width, - "Kade Engine is Outdated!\n" - + MainMenuState.kadeEngineVer - + " is your current version\nwhile the most recent version is " + needVer - + "!\nPress Space to go to the github or ESCAPE to ignore this!!", - 32); - txt.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, CENTER); - txt.screenCenter(); - add(txt); - } - - override function update(elapsed:Float) - { - if (controls.ACCEPT) - { - FlxG.openURL("https://github.com/KadeDev/Kade-Engine/releases/latest"); - } - if (controls.BACK) - { - leftState = true; - FlxG.switchState(new MainMenuState()); - } - super.update(elapsed); - } -} +package; + +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.FlxSubState; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxTimer; +import lime.app.Application; + +class OutdatedSubState extends MusicBeatState +{ + public static var leftState:Bool = false; + + public static var needVer:String = "IDFK LOL"; + public static var currChanges:String = "dk"; + + private var bgColors:Array = [ + '#314d7f', + '#4e7093', + '#70526e', + '#594465' + ]; + private var colorRotation:Int = 1; + + override function create() + { + super.create(); + var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('week54prototype', 'shared')); + bg.scale.x *= 1.55; + bg.scale.y *= 1.55; + bg.screenCenter(); + add(bg); + + var kadeLogo:FlxSprite = new FlxSprite(FlxG.width, 0).loadGraphic(Paths.image('KadeEngineLogo')); + kadeLogo.scale.y = 0.3; + kadeLogo.scale.x = 0.3; + kadeLogo.x -= kadeLogo.frameHeight; + kadeLogo.y -= 180; + kadeLogo.alpha = 0.8; + add(kadeLogo); + + var txt:FlxText = new FlxText(0, 0, FlxG.width, + "Your Kade Engine is outdated!\nYou are on " + + MainMenuState.kadeEngineVer + + "\nwhile the most recent version is " + needVer + "." + + "\n\nWhat's new:\n\n" + + currChanges + + "\n& more changes and bugfixes in the full changelog" + + "\n\nPress Space to view the full changelog and update\nor ESCAPE to ignore this", + 32); + + txt.setFormat("VCR OSD Mono", 32, FlxColor.fromRGB(200, 200, 200), CENTER); + txt.borderColor = FlxColor.BLACK; + txt.borderSize = 3; + txt.borderStyle = FlxTextBorderStyle.OUTLINE; + txt.screenCenter(); + add(txt); + + FlxTween.color(bg, 2, bg.color, FlxColor.fromString(bgColors[colorRotation])); + FlxTween.angle(kadeLogo, kadeLogo.angle, -10, 2, {ease: FlxEase.quartInOut}); + + new FlxTimer().start(2, function(tmr:FlxTimer) + { + FlxTween.color(bg, 2, bg.color, FlxColor.fromString(bgColors[colorRotation])); + if(colorRotation < (bgColors.length - 1)) colorRotation++; + else colorRotation = 0; + }, 0); + + new FlxTimer().start(2, function(tmr:FlxTimer) + { + if(kadeLogo.angle == -10) FlxTween.angle(kadeLogo, kadeLogo.angle, 10, 2, {ease: FlxEase.quartInOut}); + else FlxTween.angle(kadeLogo, kadeLogo.angle, -10, 2, {ease: FlxEase.quartInOut}); + }, 0); + + new FlxTimer().start(0.8, function(tmr:FlxTimer) + { + if(kadeLogo.alpha == 0.8) FlxTween.tween(kadeLogo, {alpha: 1}, 0.8, {ease: FlxEase.quartInOut}); + else FlxTween.tween(kadeLogo, {alpha: 0.8}, 0.8, {ease: FlxEase.quartInOut}); + }, 0); + } + + override function update(elapsed:Float) + { + if (controls.ACCEPT) + { + FlxG.openURL("https://kadedev.github.io/Kade-Engine/changelogs/changelog-" + needVer); + } + if (controls.BACK) + { + leftState = true; + FlxG.switchState(new MainMenuState()); + } + super.update(elapsed); + } +} diff --git a/source/PauseSubState.hx b/source/PauseSubState.hx index affb540..e59e72b 100644 --- a/source/PauseSubState.hx +++ b/source/PauseSubState.hx @@ -1,239 +1,246 @@ -package; - -import openfl.Lib; -#if windows -import llua.Lua; -#end -import Controls.Control; -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.FlxSubState; -import flixel.addons.transition.FlxTransitionableState; -import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.input.keyboard.FlxKey; -import flixel.system.FlxSound; -import flixel.text.FlxText; -import flixel.tweens.FlxEase; -import flixel.tweens.FlxTween; -import flixel.util.FlxColor; - -class PauseSubState extends MusicBeatSubstate -{ - var grpMenuShit:FlxTypedGroup; - - var menuItems:Array = ['Resume', 'Restart Song', 'Exit to menu']; - var curSelected:Int = 0; - - var pauseMusic:FlxSound; - var perSongOffset:FlxText; - - var offsetChanged:Bool = false; - - public function new(x:Float, y:Float) - { - super(); - - pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true); - pauseMusic.volume = 0; - pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2))); - - FlxG.sound.list.add(pauseMusic); - - var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); - bg.alpha = 0; - bg.scrollFactor.set(); - add(bg); - - var levelInfo:FlxText = new FlxText(20, 15, 0, "", 32); - levelInfo.text += PlayState.SONG.song; - levelInfo.scrollFactor.set(); - levelInfo.setFormat(Paths.font("vcr.ttf"), 32); - levelInfo.updateHitbox(); - add(levelInfo); - - var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, "", 32); - levelDifficulty.text += CoolUtil.difficultyString(); - levelDifficulty.scrollFactor.set(); - levelDifficulty.setFormat(Paths.font('vcr.ttf'), 32); - levelDifficulty.updateHitbox(); - add(levelDifficulty); - - levelDifficulty.alpha = 0; - levelInfo.alpha = 0; - - levelInfo.x = FlxG.width - (levelInfo.width + 20); - levelDifficulty.x = FlxG.width - (levelDifficulty.width + 20); - - FlxTween.tween(bg, {alpha: 0.6}, 0.4, {ease: FlxEase.quartInOut}); - FlxTween.tween(levelInfo, {alpha: 1, y: 20}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.3}); - FlxTween.tween(levelDifficulty, {alpha: 1, y: levelDifficulty.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.5}); - - grpMenuShit = new FlxTypedGroup(); - add(grpMenuShit); - perSongOffset = new FlxText(5, FlxG.height - 18, 0, "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.', 12); - perSongOffset.scrollFactor.set(); - perSongOffset.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - - #if cpp - add(perSongOffset); - #end - - for (i in 0...menuItems.length) - { - var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false); - songText.isMenuItem = true; - songText.targetY = i; - grpMenuShit.add(songText); - } - - changeSelection(); - - cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; - } - - override function update(elapsed:Float) - { - if (pauseMusic.volume < 0.5) - pauseMusic.volume += 0.01 * elapsed; - - super.update(elapsed); - - var upP = controls.UP_P; - var downP = controls.DOWN_P; - var leftP = controls.LEFT_P; - var rightP = controls.RIGHT_P; - var accepted = controls.ACCEPT; - var oldOffset:Float = 0; - var songPath = 'assets/data/' + PlayState.SONG.song.toLowerCase() + '/'; - - if (upP) - { - changeSelection(-1); - - }else if (downP) - { - changeSelection(1); - } - - #if cpp - else if (leftP) - { - oldOffset = PlayState.songOffset; - PlayState.songOffset -= 1; - sys.FileSystem.rename(songPath + oldOffset + '.offset', songPath + PlayState.songOffset + '.offset'); - perSongOffset.text = "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.'; - - // Prevent loop from happening every single time the offset changes - if(!offsetChanged) - { - grpMenuShit.clear(); - - menuItems = ['Restart Song', 'Exit to menu']; - - for (i in 0...menuItems.length) - { - var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false); - songText.isMenuItem = true; - songText.targetY = i; - grpMenuShit.add(songText); - } - - changeSelection(); - - cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; - offsetChanged = true; - } - }else if (rightP) - { - oldOffset = PlayState.songOffset; - PlayState.songOffset += 1; - sys.FileSystem.rename(songPath + oldOffset + '.offset', songPath + PlayState.songOffset + '.offset'); - perSongOffset.text = "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.'; - if(!offsetChanged) - { - grpMenuShit.clear(); - - menuItems = ['Restart Song', 'Exit to menu']; - - for (i in 0...menuItems.length) - { - var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false); - songText.isMenuItem = true; - songText.targetY = i; - grpMenuShit.add(songText); - } - - changeSelection(); - - cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; - offsetChanged = true; - } - } - #end - - if (accepted) - { - var daSelected:String = menuItems[curSelected]; - - switch (daSelected) - { - case "Resume": - close(); - case "Restart Song": - FlxG.resetState(); - case "Exit to menu": - PlayState.loadRep = false; - #if windows - if (PlayState.luaModchart != null) - { - PlayState.luaModchart.die(); - PlayState.luaModchart = null; - } - #end - if (FlxG.save.data.fpsCap > 290) - (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290); - FlxG.switchState(new MainMenuState()); - } - } - - if (FlxG.keys.justPressed.J) - { - // for reference later! - // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null); - } - } - - override function destroy() - { - pauseMusic.destroy(); - - super.destroy(); - } - - function changeSelection(change:Int = 0):Void - { - curSelected += change; - - if (curSelected < 0) - curSelected = menuItems.length - 1; - if (curSelected >= menuItems.length) - curSelected = 0; - - var bullShit:Int = 0; - - for (item in grpMenuShit.members) - { - item.targetY = bullShit - curSelected; - bullShit++; - - item.alpha = 0.6; - // item.setGraphicSize(Std.int(item.width * 0.8)); - - if (item.targetY == 0) - { - item.alpha = 1; - // item.setGraphicSize(Std.int(item.width)); - } - } - } -} +package; + +import openfl.Lib; +#if windows +import llua.Lua; +#end +import Controls.Control; +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.FlxSubState; +import flixel.addons.transition.FlxTransitionableState; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.input.keyboard.FlxKey; +import flixel.system.FlxSound; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; + +class PauseSubState extends MusicBeatSubstate +{ + var grpMenuShit:FlxTypedGroup; + + var menuItems:Array = ['Resume', 'Restart Song', 'Exit to menu']; + var curSelected:Int = 0; + + var pauseMusic:FlxSound; + var perSongOffset:FlxText; + + var offsetChanged:Bool = false; + + public function new(x:Float, y:Float) + { + super(); + + pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true); + pauseMusic.volume = 0; + pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2))); + + FlxG.sound.list.add(pauseMusic); + + var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); + bg.alpha = 0; + bg.scrollFactor.set(); + add(bg); + + var levelInfo:FlxText = new FlxText(20, 15, 0, "", 32); + levelInfo.text += PlayState.SONG.song; + levelInfo.scrollFactor.set(); + levelInfo.setFormat(Paths.font("vcr.ttf"), 32); + levelInfo.updateHitbox(); + add(levelInfo); + + var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, "", 32); + levelDifficulty.text += CoolUtil.difficultyString(); + levelDifficulty.scrollFactor.set(); + levelDifficulty.setFormat(Paths.font('vcr.ttf'), 32); + levelDifficulty.updateHitbox(); + add(levelDifficulty); + + levelDifficulty.alpha = 0; + levelInfo.alpha = 0; + + levelInfo.x = FlxG.width - (levelInfo.width + 20); + levelDifficulty.x = FlxG.width - (levelDifficulty.width + 20); + + FlxTween.tween(bg, {alpha: 0.6}, 0.4, {ease: FlxEase.quartInOut}); + FlxTween.tween(levelInfo, {alpha: 1, y: 20}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.3}); + FlxTween.tween(levelDifficulty, {alpha: 1, y: levelDifficulty.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.5}); + + grpMenuShit = new FlxTypedGroup(); + add(grpMenuShit); + perSongOffset = new FlxText(5, FlxG.height - 18, 0, "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.', 12); + perSongOffset.scrollFactor.set(); + perSongOffset.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + + #if cpp + add(perSongOffset); + #end + + for (i in 0...menuItems.length) + { + var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false); + songText.isMenuItem = true; + songText.targetY = i; + grpMenuShit.add(songText); + } + + changeSelection(); + + cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + } + + override function update(elapsed:Float) + { + if (pauseMusic.volume < 0.5) + pauseMusic.volume += 0.01 * elapsed; + + super.update(elapsed); + + var upP = controls.UP_P; + var downP = controls.DOWN_P; + var leftP = controls.LEFT_P; + var rightP = controls.RIGHT_P; + var accepted = controls.ACCEPT; + var oldOffset:Float = 0; + var songPath = 'assets/data/' + PlayState.SONG.song.toLowerCase() + '/'; + + if (upP) + { + changeSelection(-1); + + }else if (downP) + { + changeSelection(1); + } + + #if cpp + else if (leftP) + { + oldOffset = PlayState.songOffset; + PlayState.songOffset -= 1; + sys.FileSystem.rename(songPath + oldOffset + '.offset', songPath + PlayState.songOffset + '.offset'); + perSongOffset.text = "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.'; + + // Prevent loop from happening every single time the offset changes + if(!offsetChanged) + { + grpMenuShit.clear(); + + menuItems = ['Restart Song', 'Exit to menu']; + + for (i in 0...menuItems.length) + { + var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false); + songText.isMenuItem = true; + songText.targetY = i; + grpMenuShit.add(songText); + } + + changeSelection(); + + cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + offsetChanged = true; + } + }else if (rightP) + { + oldOffset = PlayState.songOffset; + PlayState.songOffset += 1; + sys.FileSystem.rename(songPath + oldOffset + '.offset', songPath + PlayState.songOffset + '.offset'); + perSongOffset.text = "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.'; + if(!offsetChanged) + { + grpMenuShit.clear(); + + menuItems = ['Restart Song', 'Exit to menu']; + + for (i in 0...menuItems.length) + { + var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false); + songText.isMenuItem = true; + songText.targetY = i; + grpMenuShit.add(songText); + } + + changeSelection(); + + cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + offsetChanged = true; + } + } + #end + + if (accepted) + { + var daSelected:String = menuItems[curSelected]; + + switch (daSelected) + { + case "Resume": + close(); + case "Restart Song": + FlxG.resetState(); + case "Exit to menu": + if(PlayState.loadRep) + { + FlxG.save.data.botplay = false; + FlxG.save.data.scrollSpeed = 1; + FlxG.save.data.downscroll = false; + } + PlayState.loadRep = false; + #if windows + if (PlayState.luaModchart != null) + { + PlayState.luaModchart.die(); + PlayState.luaModchart = null; + } + #end + if (FlxG.save.data.fpsCap > 290) + (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290); + + FlxG.switchState(new MainMenuState()); + } + } + + if (FlxG.keys.justPressed.J) + { + // for reference later! + // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null); + } + } + + override function destroy() + { + pauseMusic.destroy(); + + super.destroy(); + } + + function changeSelection(change:Int = 0):Void + { + curSelected += change; + + if (curSelected < 0) + curSelected = menuItems.length - 1; + if (curSelected >= menuItems.length) + curSelected = 0; + + var bullShit:Int = 0; + + for (item in grpMenuShit.members) + { + item.targetY = bullShit - curSelected; + bullShit++; + + item.alpha = 0.6; + // item.setGraphicSize(Std.int(item.width * 0.8)); + + if (item.targetY == 0) + { + item.alpha = 1; + // item.setGraphicSize(Std.int(item.width)); + } + } + } +} \ No newline at end of file diff --git a/source/PlayState.hx b/source/PlayState.hx index 2539f71..9058186 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1,3395 +1,3419 @@ -package; - -import haxe.Exception; -import openfl.geom.Matrix; -import openfl.display.BitmapData; -import openfl.utils.AssetType; -import lime.graphics.Image; -import flixel.graphics.FlxGraphic; -import openfl.utils.AssetManifest; -import openfl.utils.AssetLibrary; -import flixel.system.FlxAssets; - -import lime.app.Application; -import lime.media.AudioContext; -import lime.media.AudioManager; -import openfl.Lib; -import Section.SwagSection; -import Song.SwagSong; -import WiggleEffect.WiggleEffectType; -import flixel.FlxBasic; -import flixel.FlxCamera; -import flixel.FlxG; -import flixel.FlxGame; -import flixel.FlxObject; -import flixel.FlxSprite; -import flixel.FlxState; -import flixel.FlxSubState; -import flixel.addons.display.FlxGridOverlay; -import flixel.addons.effects.FlxTrail; -import flixel.addons.effects.FlxTrailArea; -import flixel.addons.effects.chainable.FlxEffectSprite; -import flixel.addons.effects.chainable.FlxWaveEffect; -import flixel.addons.transition.FlxTransitionableState; -import flixel.graphics.atlas.FlxAtlas; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.math.FlxMath; -import flixel.math.FlxPoint; -import flixel.math.FlxRect; -import flixel.system.FlxSound; -import flixel.text.FlxText; -import flixel.tweens.FlxEase; -import flixel.tweens.FlxTween; -import flixel.ui.FlxBar; -import flixel.util.FlxCollision; -import flixel.util.FlxColor; -import flixel.util.FlxSort; -import flixel.util.FlxStringUtil; -import flixel.util.FlxTimer; -import haxe.Json; -import lime.utils.Assets; -import openfl.display.BlendMode; -import openfl.display.StageQuality; -import openfl.filters.ShaderFilter; - -#if windows -import Discord.DiscordClient; -#end -#if windows -import Sys; -import sys.FileSystem; -#end - -using StringTools; - -class PlayState extends MusicBeatState -{ - public static var instance:PlayState = null; - - public static var curStage:String = ''; - public static var SONG:SwagSong; - public static var isStoryMode:Bool = false; - public static var storyWeek:Int = 0; - public static var storyPlaylist:Array = []; - public static var storyDifficulty:Int = 1; - public static var weekSong:Int = 0; - public static var shits:Int = 0; - public static var bads:Int = 0; - public static var goods:Int = 0; - public static var sicks:Int = 0; - - public static var songPosBG:FlxSprite; - public static var songPosBar:FlxBar; - - public static var rep:Replay; - public static var loadRep:Bool = false; - - public static var noteBools:Array = [false, false, false, false]; - - var halloweenLevel:Bool = false; - - var songLength:Float = 0; - var kadeEngineWatermark:FlxText; - - #if windows - // Discord RPC variables - var storyDifficultyText:String = ""; - var iconRPC:String = ""; - var detailsText:String = ""; - var detailsPausedText:String = ""; - #end - - private var vocals:FlxSound; - - public static var dad:Character; - public static var gf:Character; - public static var boyfriend:Boyfriend; - - public var notes:FlxTypedGroup; - private var unspawnNotes:Array = []; - - public var strumLine:FlxSprite; - private var curSection:Int = 0; - - private var camFollow:FlxObject; - - private static var prevCamFollow:FlxObject; - - public static var strumLineNotes:FlxTypedGroup = null; - public static var playerStrums:FlxTypedGroup = null; - - private var camZooming:Bool = false; - private var curSong:String = ""; - - private var gfSpeed:Int = 1; - private var health:Float = 1; - private var combo:Int = 0; - public static var misses:Int = 0; - private 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; - - private var iconP1:HealthIcon; - private var iconP2:HealthIcon; - public var camHUD:FlxCamera; - private var camGame:FlxCamera; - - public static var offsetTesting:Bool = false; - - var notesHitArray:Array = []; - var currentFrames:Int = 0; - - public var dialogue:Array = ['dad:blah blah blah', 'bf:coolswag']; - - var halloweenBG:FlxSprite; - var isHalloween:Bool = false; - - var phillyCityLights:FlxTypedGroup; - var phillyTrain:FlxSprite; - var trainSound:FlxSound; - - var limo:FlxSprite; - var grpLimoDancers:FlxTypedGroup; - var fastCar:FlxSprite; - var songName:FlxText; - var upperBoppers:FlxSprite; - var bottomBoppers:FlxSprite; - var santa:FlxSprite; - - var fc:Bool = true; - - var bgGirls:BackgroundGirls; - var wiggleShit:WiggleEffect = new WiggleEffect(); - - var talking:Bool = true; - var songScore:Int = 0; - var songScoreDef:Int = 0; - var scoreTxt:FlxText; - var replayTxt:FlxText; - - public static var campaignScore:Int = 0; - - var defaultCamZoom:Float = 1.05; - - public static var daPixelZoom:Float = 6; - - public static var theFunne:Bool = true; - var funneEffect:FlxSprite; - var inCutscene:Bool = false; - public static var repPresses:Int = 0; - public static var repReleases:Int = 0; - - public static var timeCurrently:Float = 0; - public static var timeCurrentlyR:Float = 0; - - // Will fire once to prevent debug spam messages and broken animations - private var triggeredAlready:Bool = false; - - // Will decide if she's even allowed to headbang at all depending on the song - private var allowedToHeadbang:Bool = false; - // Per song additive offset - public static var songOffset:Float = 0; - // BotPlay text - private var botPlayState:FlxText; - - private var executeModchart = false; - - // API stuff - - public function addObject(object:FlxBasic) { add(object); } - public function removeObject(object:FlxBasic) { remove(object); } - - - override public function create() - { - instance = this; - - if (FlxG.save.data.fpsCap > 290) - (cast (Lib.current.getChildAt(0), Main)).setFPSCap(800); - - if (FlxG.sound.music != null) - FlxG.sound.music.stop(); - - sicks = 0; - bads = 0; - shits = 0; - goods = 0; - - misses = 0; - - repPresses = 0; - repReleases = 0; - - #if windows - executeModchart = FileSystem.exists(Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart")); - #end - #if !cpp - executeModchart = false; // FORCE disable for non cpp targets - #end - - trace('Mod chart: ' + executeModchart + " - " + Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart")); - - #if windows - // Making difficulty text for Discord Rich Presence. - switch (storyDifficulty) - { - case 0: - storyDifficultyText = "Easy"; - case 1: - storyDifficultyText = "Normal"; - case 2: - storyDifficultyText = "Hard"; - } - - iconRPC = SONG.player2; - - // To avoid having duplicate images in Discord assets - switch (iconRPC) - { - case 'senpai-angry': - iconRPC = 'senpai'; - case 'monster-christmas': - iconRPC = 'monster'; - case 'mom-car': - iconRPC = 'mom'; - } - - // String that contains the mode defined here so it isn't necessary to call changePresence for each mode - if (isStoryMode) - { - detailsText = "Story Mode: Week " + storyWeek; - } - else - { - detailsText = "Freeplay"; - } - - // String for when the game is paused - detailsPausedText = "Paused - " + detailsText; - - // Updating Discord Rich Presence. - DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); - #end - - - // var gameCam:FlxCamera = FlxG.camera; - camGame = new FlxCamera(); - camHUD = new FlxCamera(); - camHUD.bgColor.alpha = 0; - - FlxG.cameras.reset(camGame); - FlxG.cameras.add(camHUD); - - FlxCamera.defaultCameras = [camGame]; - - persistentUpdate = true; - persistentDraw = true; - - if (SONG == null) - SONG = Song.loadFromJson('tutorial'); - - Conductor.mapBPMChanges(SONG); - Conductor.changeBPM(SONG.bpm); - - trace('INFORMATION ABOUT WHAT U PLAYIN WIT:\nFRAMES: ' + Conductor.safeFrames + '\nZONE: ' + Conductor.safeZoneOffset + '\nTS: ' + Conductor.timeScale + '\nBotPlay : ' + FlxG.save.data.botplay); - - switch (SONG.song.toLowerCase()) - { - case 'tutorial': - dialogue = ["Hey you're pretty cute.", 'Use the arrow keys to keep up \nwith me singing.']; - case 'bopeebo': - dialogue = [ - 'HEY!', - "You think you can just sing\nwith my daughter like that?", - "If you want to date her...", - "You're going to have to go \nthrough ME first!" - ]; - case 'fresh': - dialogue = ["Not too shabby boy.", ""]; - case 'dadbattle': - dialogue = [ - "gah you think you're hot stuff?", - "If you can beat me here...", - "Only then I will even CONSIDER letting you\ndate my daughter!" - ]; - case 'senpai': - dialogue = CoolUtil.coolTextFile(Paths.txt('senpai/senpaiDialogue')); - case 'roses': - dialogue = CoolUtil.coolTextFile(Paths.txt('roses/rosesDialogue')); - case 'thorns': - dialogue = CoolUtil.coolTextFile(Paths.txt('thorns/thornsDialogue')); - } - - switch(SONG.stage) - { - case 'halloween': - { - curStage = 'spooky'; - halloweenLevel = true; - - var hallowTex = Paths.getSparrowAtlas('halloween_bg','week2'); - - halloweenBG = new FlxSprite(-200, -100); - halloweenBG.frames = hallowTex; - halloweenBG.animation.addByPrefix('idle', 'halloweem bg0'); - halloweenBG.animation.addByPrefix('lightning', 'halloweem bg lightning strike', 24, false); - halloweenBG.animation.play('idle'); - halloweenBG.antialiasing = true; - add(halloweenBG); - - isHalloween = true; - } - case 'philly': - { - curStage = 'philly'; - - var bg:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image('philly/sky', 'week3')); - bg.scrollFactor.set(0.1, 0.1); - add(bg); - - var city:FlxSprite = new FlxSprite(-10).loadGraphic(Paths.image('philly/city', 'week3')); - city.scrollFactor.set(0.3, 0.3); - city.setGraphicSize(Std.int(city.width * 0.85)); - city.updateHitbox(); - add(city); - - phillyCityLights = new FlxTypedGroup(); - if(FlxG.save.data.distractions){ - add(phillyCityLights); - } - - for (i in 0...5) - { - var light:FlxSprite = new FlxSprite(city.x).loadGraphic(Paths.image('philly/win' + i, 'week3')); - light.scrollFactor.set(0.3, 0.3); - light.visible = false; - light.setGraphicSize(Std.int(light.width * 0.85)); - light.updateHitbox(); - light.antialiasing = true; - phillyCityLights.add(light); - } - - var streetBehind:FlxSprite = new FlxSprite(-40, 50).loadGraphic(Paths.image('philly/behindTrain','week3')); - add(streetBehind); - - phillyTrain = new FlxSprite(2000, 360).loadGraphic(Paths.image('philly/train','week3')); - if(FlxG.save.data.distractions){ - add(phillyTrain); - } - - trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes','week3')); - FlxG.sound.list.add(trainSound); - - // var cityLights:FlxSprite = new FlxSprite().loadGraphic(AssetPaths.win0.png); - - var street:FlxSprite = new FlxSprite(-40, streetBehind.y).loadGraphic(Paths.image('philly/street','week3')); - add(street); - } - case 'limo': - { - curStage = 'limo'; - defaultCamZoom = 0.90; - - var skyBG:FlxSprite = new FlxSprite(-120, -50).loadGraphic(Paths.image('limo/limoSunset','week4')); - skyBG.scrollFactor.set(0.1, 0.1); - add(skyBG); - - var bgLimo:FlxSprite = new FlxSprite(-200, 480); - bgLimo.frames = Paths.getSparrowAtlas('limo/bgLimo','week4'); - bgLimo.animation.addByPrefix('drive', "background limo pink", 24); - bgLimo.animation.play('drive'); - bgLimo.scrollFactor.set(0.4, 0.4); - add(bgLimo); - if(FlxG.save.data.distractions){ - grpLimoDancers = new FlxTypedGroup(); - add(grpLimoDancers); - - for (i in 0...5) - { - var dancer:BackgroundDancer = new BackgroundDancer((370 * i) + 130, bgLimo.y - 400); - dancer.scrollFactor.set(0.4, 0.4); - grpLimoDancers.add(dancer); - } - } - - var overlayShit:FlxSprite = new FlxSprite(-500, -600).loadGraphic(Paths.image('limo/limoOverlay','week4')); - overlayShit.alpha = 0.5; - // add(overlayShit); - - // var shaderBullshit = new BlendModeEffect(new OverlayShader(), FlxColor.RED); - - // FlxG.camera.setFilters([new ShaderFilter(cast shaderBullshit.shader)]); - - // overlayShit.shader = shaderBullshit; - - var limoTex = Paths.getSparrowAtlas('limo/limoDrive','week4'); - - limo = new FlxSprite(-120, 550); - limo.frames = limoTex; - limo.animation.addByPrefix('drive', "Limo stage", 24); - limo.animation.play('drive'); - limo.antialiasing = true; - - fastCar = new FlxSprite(-300, 160).loadGraphic(Paths.image('limo/fastCarLol','week4')); - // add(limo); - } - case 'mall': - { - curStage = 'mall'; - - defaultCamZoom = 0.80; - - var bg:FlxSprite = new FlxSprite(-1000, -500).loadGraphic(Paths.image('christmas/bgWalls','week5')); - bg.antialiasing = true; - bg.scrollFactor.set(0.2, 0.2); - bg.active = false; - bg.setGraphicSize(Std.int(bg.width * 0.8)); - bg.updateHitbox(); - add(bg); - - upperBoppers = new FlxSprite(-240, -90); - upperBoppers.frames = Paths.getSparrowAtlas('christmas/upperBop','week5'); - upperBoppers.animation.addByPrefix('bop', "Upper Crowd Bob", 24, false); - upperBoppers.antialiasing = true; - upperBoppers.scrollFactor.set(0.33, 0.33); - upperBoppers.setGraphicSize(Std.int(upperBoppers.width * 0.85)); - upperBoppers.updateHitbox(); - if(FlxG.save.data.distractions){ - add(upperBoppers); - } - - - var bgEscalator:FlxSprite = new FlxSprite(-1100, -600).loadGraphic(Paths.image('christmas/bgEscalator','week5')); - bgEscalator.antialiasing = true; - bgEscalator.scrollFactor.set(0.3, 0.3); - bgEscalator.active = false; - bgEscalator.setGraphicSize(Std.int(bgEscalator.width * 0.9)); - bgEscalator.updateHitbox(); - add(bgEscalator); - - var tree:FlxSprite = new FlxSprite(370, -250).loadGraphic(Paths.image('christmas/christmasTree','week5')); - tree.antialiasing = true; - tree.scrollFactor.set(0.40, 0.40); - add(tree); - - bottomBoppers = new FlxSprite(-300, 140); - bottomBoppers.frames = Paths.getSparrowAtlas('christmas/bottomBop','week5'); - bottomBoppers.animation.addByPrefix('bop', 'Bottom Level Boppers', 24, false); - bottomBoppers.antialiasing = true; - bottomBoppers.scrollFactor.set(0.9, 0.9); - bottomBoppers.setGraphicSize(Std.int(bottomBoppers.width * 1)); - bottomBoppers.updateHitbox(); - if(FlxG.save.data.distractions){ - add(bottomBoppers); - } - - - var fgSnow:FlxSprite = new FlxSprite(-600, 700).loadGraphic(Paths.image('christmas/fgSnow','week5')); - fgSnow.active = false; - fgSnow.antialiasing = true; - add(fgSnow); - - santa = new FlxSprite(-840, 150); - santa.frames = Paths.getSparrowAtlas('christmas/santa','week5'); - santa.animation.addByPrefix('idle', 'santa idle in fear', 24, false); - santa.antialiasing = true; - if(FlxG.save.data.distractions){ - add(santa); - } - } - case 'mallEvil': - { - curStage = 'mallEvil'; - var bg:FlxSprite = new FlxSprite(-400, -500).loadGraphic(Paths.image('christmas/evilBG','week5')); - bg.antialiasing = true; - bg.scrollFactor.set(0.2, 0.2); - bg.active = false; - bg.setGraphicSize(Std.int(bg.width * 0.8)); - bg.updateHitbox(); - add(bg); - - var evilTree:FlxSprite = new FlxSprite(300, -300).loadGraphic(Paths.image('christmas/evilTree','week5')); - evilTree.antialiasing = true; - evilTree.scrollFactor.set(0.2, 0.2); - add(evilTree); - - var evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow",'week5')); - evilSnow.antialiasing = true; - add(evilSnow); - } - case 'school': - { - curStage = 'school'; - - // defaultCamZoom = 0.9; - - var bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky','week6')); - bgSky.scrollFactor.set(0.1, 0.1); - add(bgSky); - - var repositionShit = -200; - - var bgSchool:FlxSprite = new FlxSprite(repositionShit, 0).loadGraphic(Paths.image('weeb/weebSchool','week6')); - bgSchool.scrollFactor.set(0.6, 0.90); - add(bgSchool); - - var bgStreet:FlxSprite = new FlxSprite(repositionShit).loadGraphic(Paths.image('weeb/weebStreet','week6')); - bgStreet.scrollFactor.set(0.95, 0.95); - add(bgStreet); - - var fgTrees:FlxSprite = new FlxSprite(repositionShit + 170, 130).loadGraphic(Paths.image('weeb/weebTreesBack','week6')); - fgTrees.scrollFactor.set(0.9, 0.9); - add(fgTrees); - - var bgTrees:FlxSprite = new FlxSprite(repositionShit - 380, -800); - var treetex = Paths.getPackerAtlas('weeb/weebTrees','week6'); - bgTrees.frames = treetex; - bgTrees.animation.add('treeLoop', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 12); - bgTrees.animation.play('treeLoop'); - bgTrees.scrollFactor.set(0.85, 0.85); - add(bgTrees); - - var treeLeaves:FlxSprite = new FlxSprite(repositionShit, -40); - treeLeaves.frames = Paths.getSparrowAtlas('weeb/petals','week6'); - treeLeaves.animation.addByPrefix('leaves', 'PETALS ALL', 24, true); - treeLeaves.animation.play('leaves'); - treeLeaves.scrollFactor.set(0.85, 0.85); - add(treeLeaves); - - var widShit = Std.int(bgSky.width * 6); - - bgSky.setGraphicSize(widShit); - bgSchool.setGraphicSize(widShit); - bgStreet.setGraphicSize(widShit); - bgTrees.setGraphicSize(Std.int(widShit * 1.4)); - fgTrees.setGraphicSize(Std.int(widShit * 0.8)); - treeLeaves.setGraphicSize(widShit); - - fgTrees.updateHitbox(); - bgSky.updateHitbox(); - bgSchool.updateHitbox(); - bgStreet.updateHitbox(); - bgTrees.updateHitbox(); - treeLeaves.updateHitbox(); - - bgGirls = new BackgroundGirls(-100, 190); - bgGirls.scrollFactor.set(0.9, 0.9); - - if (SONG.song.toLowerCase() == 'roses') - { - if(FlxG.save.data.distractions){ - bgGirls.getScared(); - } - } - - bgGirls.setGraphicSize(Std.int(bgGirls.width * daPixelZoom)); - bgGirls.updateHitbox(); - if(FlxG.save.data.distractions){ - add(bgGirls); - } - } - case 'schoolEvil': - { - curStage = 'schoolEvil'; - - var waveEffectBG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 3, 2); - var waveEffectFG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 5, 2); - - var posX = 400; - var posY = 200; - - var bg:FlxSprite = new FlxSprite(posX, posY); - bg.frames = Paths.getSparrowAtlas('weeb/animatedEvilSchool','week6'); - bg.animation.addByPrefix('idle', 'background 2', 24); - bg.animation.play('idle'); - bg.scrollFactor.set(0.8, 0.9); - bg.scale.set(6, 6); - add(bg); - - /* - var bg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolBG')); - bg.scale.set(6, 6); - // bg.setGraphicSize(Std.int(bg.width * 6)); - // bg.updateHitbox(); - add(bg); - var fg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolFG')); - fg.scale.set(6, 6); - // fg.setGraphicSize(Std.int(fg.width * 6)); - // fg.updateHitbox(); - add(fg); - wiggleShit.effectType = WiggleEffectType.DREAMY; - wiggleShit.waveAmplitude = 0.01; - wiggleShit.waveFrequency = 60; - wiggleShit.waveSpeed = 0.8; - */ - - // bg.shader = wiggleShit.shader; - // fg.shader = wiggleShit.shader; - - /* - var waveSprite = new FlxEffectSprite(bg, [waveEffectBG]); - var waveSpriteFG = new FlxEffectSprite(fg, [waveEffectFG]); - // Using scale since setGraphicSize() doesnt work??? - waveSprite.scale.set(6, 6); - waveSpriteFG.scale.set(6, 6); - waveSprite.setPosition(posX, posY); - waveSpriteFG.setPosition(posX, posY); - waveSprite.scrollFactor.set(0.7, 0.8); - waveSpriteFG.scrollFactor.set(0.9, 0.8); - // waveSprite.setGraphicSize(Std.int(waveSprite.width * 6)); - // waveSprite.updateHitbox(); - // waveSpriteFG.setGraphicSize(Std.int(fg.width * 6)); - // waveSpriteFG.updateHitbox(); - add(waveSprite); - add(waveSpriteFG); - */ - } - case 'stage': - { - defaultCamZoom = 0.9; - curStage = 'stage'; - var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback')); - bg.antialiasing = true; - bg.scrollFactor.set(0.9, 0.9); - bg.active = false; - add(bg); - - var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront')); - stageFront.setGraphicSize(Std.int(stageFront.width * 1.1)); - stageFront.updateHitbox(); - stageFront.antialiasing = true; - stageFront.scrollFactor.set(0.9, 0.9); - stageFront.active = false; - add(stageFront); - - var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains')); - stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9)); - stageCurtains.updateHitbox(); - stageCurtains.antialiasing = true; - stageCurtains.scrollFactor.set(1.3, 1.3); - stageCurtains.active = false; - - add(stageCurtains); - } - default: - { - defaultCamZoom = 0.9; - curStage = 'stage'; - var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback')); - bg.antialiasing = true; - bg.scrollFactor.set(0.9, 0.9); - bg.active = false; - add(bg); - - var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront')); - stageFront.setGraphicSize(Std.int(stageFront.width * 1.1)); - stageFront.updateHitbox(); - stageFront.antialiasing = true; - stageFront.scrollFactor.set(0.9, 0.9); - stageFront.active = false; - add(stageFront); - - var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains')); - stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9)); - stageCurtains.updateHitbox(); - stageCurtains.antialiasing = true; - stageCurtains.scrollFactor.set(1.3, 1.3); - stageCurtains.active = false; - - add(stageCurtains); - } - } - var gfVersion:String = 'gf'; - - switch (SONG.gfVersion) - { - case 'gf-car': - gfVersion = 'gf-car'; - case 'gf-christmas': - gfVersion = 'gf-christmas'; - case 'gf-pixel': - gfVersion = 'gf-pixel'; - case 'gf': - gfVersion = 'gf'; - default: - gfVersion = 'gf'; - } - - gf = new Character(400, 130, gfVersion); - gf.scrollFactor.set(0.95, 0.95); - - dad = new Character(100, 100, SONG.player2); - - var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x, dad.getGraphicMidpoint().y); - - switch (SONG.player2) - { - case 'gf': - dad.setPosition(gf.x, gf.y); - gf.visible = false; - if (isStoryMode) - { - camPos.x += 600; - tweenCamIn(); - } - - case "spooky": - dad.y += 200; - case "monster": - dad.y += 100; - case 'monster-christmas': - dad.y += 130; - case 'dad': - camPos.x += 400; - case 'pico': - camPos.x += 600; - dad.y += 300; - case 'parents-christmas': - dad.x -= 500; - case 'senpai': - dad.x += 150; - dad.y += 360; - camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); - case 'senpai-angry': - dad.x += 150; - dad.y += 360; - camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); - case 'spirit': - dad.x -= 150; - dad.y += 100; - camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); - } - - - - boyfriend = new Boyfriend(770, 450, SONG.player1); - - // REPOSITIONING PER STAGE - switch (curStage) - { - case 'limo': - boyfriend.y -= 220; - boyfriend.x += 260; - if(FlxG.save.data.distractions){ - resetFastCar(); - add(fastCar); - } - - case 'mall': - boyfriend.x += 200; - - case 'mallEvil': - boyfriend.x += 320; - dad.y -= 80; - case 'school': - boyfriend.x += 200; - boyfriend.y += 220; - gf.x += 180; - gf.y += 300; - case 'schoolEvil': - if(FlxG.save.data.distractions){ - // trailArea.scrollFactor.set(); - var evilTrail = new FlxTrail(dad, null, 4, 24, 0.3, 0.069); - // evilTrail.changeValuesEnabled(false, false, false, false); - // evilTrail.changeGraphic() - add(evilTrail); - // evilTrail.scrollFactor.set(1.1, 1.1); - } - - - boyfriend.x += 200; - boyfriend.y += 220; - gf.x += 180; - gf.y += 300; - } - - add(gf); - - // Shitty layering but whatev it works LOL - if (curStage == 'limo') - add(limo); - - add(dad); - add(boyfriend); - - var doof:DialogueBox = new DialogueBox(false, dialogue); - // doof.x += 70; - // doof.y = FlxG.height * 0.5; - doof.scrollFactor.set(); - doof.finishThing = startCountdown; - - Conductor.songPosition = -5000; - - - strumLine = new FlxSprite(0, 50).makeGraphic(FlxG.width, 10); - strumLine.scrollFactor.set(); - - if (FlxG.save.data.downscroll) - strumLine.y = FlxG.height - 165; - - strumLineNotes = new FlxTypedGroup(); - add(strumLineNotes); - - playerStrums = new FlxTypedGroup(); - - // startCountdown(); - - generateSong(SONG.song); - - // add(strumLine); - - camFollow = new FlxObject(0, 0, 1, 1); - - camFollow.setPosition(camPos.x, camPos.y); - - if (prevCamFollow != null) - { - camFollow = prevCamFollow; - prevCamFollow = null; - } - - add(camFollow); - - FlxG.camera.follow(camFollow, LOCKON, 0.04 * (30 / (cast (Lib.current.getChildAt(0), Main)).getFPS())); - // FlxG.camera.setScrollBounds(0, FlxG.width, 0, FlxG.height); - FlxG.camera.zoom = defaultCamZoom; - FlxG.camera.focusOn(camFollow.getPosition()); - - FlxG.worldBounds.set(0, 0, FlxG.width, FlxG.height); - - FlxG.fixedTimestep = false; - - if (FlxG.save.data.songPosition) // I dont wanna talk about this code :( - { - songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar')); - if (FlxG.save.data.downscroll) - 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 (FlxG.save.data.downscroll) - 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 (FlxG.save.data.downscroll) - healthBarBG.y = 50; - healthBarBG.screenCenter(X); - healthBarBG.scrollFactor.set(); - add(healthBarBG); - - healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this, - 'health', 0, 2); - healthBar.scrollFactor.set(); - healthBar.createFilledBar(0xFFFF0000, 0xFF66FF33); - // healthBar - add(healthBar); - - // Add Kade Engine watermark - kadeEngineWatermark = new FlxText(4,healthBarBG.y + 50,0,SONG.song + " " + (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.scrollFactor.set(); - add(kadeEngineWatermark); - - if (FlxG.save.data.downscroll) - kadeEngineWatermark.y = FlxG.height * 0.9 + 45; - - scoreTxt = new FlxText(FlxG.width / 2 - 235, healthBarBG.y + 50, 0, "", 20); - if (!FlxG.save.data.accuracyDisplay) - scoreTxt.x = healthBarBG.x + healthBarBG.width / 2; - scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); - scoreTxt.scrollFactor.set(); - if (offsetTesting) - scoreTxt.x += 300; - if(FlxG.save.data.botplay) scoreTxt.x = FlxG.width / 2 - 20; - add(scoreTxt); - - replayTxt = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (FlxG.save.data.downscroll ? 100 : -100), 0, "REPLAY", 20); - replayTxt.setFormat(Paths.font("vcr.ttf"), 42, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); - replayTxt.scrollFactor.set(); - if (loadRep) - { - add(replayTxt); - } - // Literally copy-paste of the above, fu - botPlayState = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (FlxG.save.data.downscroll ? 100 : -100), 0, "BOTPLAY", 20); - botPlayState.setFormat(Paths.font("vcr.ttf"), 42, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); - botPlayState.scrollFactor.set(); - - if(FlxG.save.data.botplay) add(botPlayState); - - iconP1 = new HealthIcon(SONG.player1, true); - iconP1.y = healthBar.y - (iconP1.height / 2); - add(iconP1); - - iconP2 = new HealthIcon(SONG.player2, false); - iconP2.y = healthBar.y - (iconP2.height / 2); - add(iconP2); - - strumLineNotes.cameras = [camHUD]; - notes.cameras = [camHUD]; - healthBar.cameras = [camHUD]; - healthBarBG.cameras = [camHUD]; - iconP1.cameras = [camHUD]; - iconP2.cameras = [camHUD]; - scoreTxt.cameras = [camHUD]; - doof.cameras = [camHUD]; - if (FlxG.save.data.songPosition) - { - songPosBG.cameras = [camHUD]; - songPosBar.cameras = [camHUD]; - } - kadeEngineWatermark.cameras = [camHUD]; - if (loadRep) - replayTxt.cameras = [camHUD]; - - // if (SONG.song == 'South') - // FlxG.camera.alpha = 0.7; - // UI_camera.zoom = 1; - - // cameras = [FlxG.cameras.list[1]]; - startingSong = true; - - if (isStoryMode) - { - switch (curSong.toLowerCase()) - { - case "winter-horrorland": - var blackScreen:FlxSprite = new FlxSprite(0, 0).makeGraphic(Std.int(FlxG.width * 2), Std.int(FlxG.height * 2), FlxColor.BLACK); - add(blackScreen); - blackScreen.scrollFactor.set(); - camHUD.visible = false; - - new FlxTimer().start(0.1, function(tmr:FlxTimer) - { - remove(blackScreen); - FlxG.sound.play(Paths.sound('Lights_Turn_On')); - camFollow.y = -2050; - camFollow.x += 200; - FlxG.camera.focusOn(camFollow.getPosition()); - FlxG.camera.zoom = 1.5; - - new FlxTimer().start(0.8, function(tmr:FlxTimer) - { - camHUD.visible = true; - remove(blackScreen); - FlxTween.tween(FlxG.camera, {zoom: defaultCamZoom}, 2.5, { - ease: FlxEase.quadInOut, - onComplete: function(twn:FlxTween) - { - startCountdown(); - } - }); - }); - }); - case 'senpai': - schoolIntro(doof); - case 'roses': - FlxG.sound.play(Paths.sound('ANGRY')); - schoolIntro(doof); - case 'thorns': - schoolIntro(doof); - default: - startCountdown(); - } - } - else - { - switch (curSong.toLowerCase()) - { - default: - startCountdown(); - } - } - - if (!loadRep) - rep = new Replay("na"); - - super.create(); - } - - function schoolIntro(?dialogueBox:DialogueBox):Void - { - var black:FlxSprite = new FlxSprite(-100, -100).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK); - black.scrollFactor.set(); - add(black); - - var red:FlxSprite = new FlxSprite(-100, -100).makeGraphic(FlxG.width * 2, FlxG.height * 2, 0xFFff1b31); - red.scrollFactor.set(); - - var senpaiEvil:FlxSprite = new FlxSprite(); - senpaiEvil.frames = Paths.getSparrowAtlas('weeb/senpaiCrazy'); - senpaiEvil.animation.addByPrefix('idle', 'Senpai Pre Explosion', 24, false); - senpaiEvil.setGraphicSize(Std.int(senpaiEvil.width * 6)); - senpaiEvil.scrollFactor.set(); - senpaiEvil.updateHitbox(); - senpaiEvil.screenCenter(); - - if (SONG.song.toLowerCase() == 'roses' || SONG.song.toLowerCase() == 'thorns') - { - remove(black); - - if (SONG.song.toLowerCase() == 'thorns') - { - add(red); - } - } - - new FlxTimer().start(0.3, function(tmr:FlxTimer) - { - black.alpha -= 0.15; - - if (black.alpha > 0) - { - tmr.reset(0.3); - } - else - { - if (dialogueBox != null) - { - inCutscene = true; - - if (SONG.song.toLowerCase() == 'thorns') - { - add(senpaiEvil); - senpaiEvil.alpha = 0; - new FlxTimer().start(0.3, function(swagTimer:FlxTimer) - { - senpaiEvil.alpha += 0.15; - if (senpaiEvil.alpha < 1) - { - swagTimer.reset(); - } - else - { - senpaiEvil.animation.play('idle'); - FlxG.sound.play(Paths.sound('Senpai_Dies'), 1, false, null, true, function() - { - remove(senpaiEvil); - remove(red); - FlxG.camera.fade(FlxColor.WHITE, 0.01, true, function() - { - add(dialogueBox); - }, true); - }); - new FlxTimer().start(3.2, function(deadTime:FlxTimer) - { - FlxG.camera.fade(FlxColor.WHITE, 1.6, false); - }); - } - }); - } - else - { - add(dialogueBox); - } - } - else - startCountdown(); - - remove(black); - } - }); - } - - var startTimer:FlxTimer; - var perfectMode:Bool = false; - - var luaWiggles:Array = []; - - #if windows - public static var luaModchart:ModchartState = null; - #end - - function startCountdown():Void - { - inCutscene = false; - - generateStaticArrows(0); - generateStaticArrows(1); - - - #if windows - if (executeModchart) - { - luaModchart = ModchartState.createModchartState(); - luaModchart.executeState('start',[PlayState.SONG.song]); - } - #end - - talking = false; - startedCountdown = true; - Conductor.songPosition = 0; - Conductor.songPosition -= Conductor.crochet * 5; - - var swagCounter:Int = 0; - - startTimer = new FlxTimer().start(Conductor.crochet / 1000, function(tmr:FlxTimer) - { - dad.dance(); - gf.dance(); - boyfriend.playAnim('idle'); - - var introAssets:Map> = new Map>(); - introAssets.set('default', ['ready', "set", "go"]); - introAssets.set('school', [ - 'weeb/pixelUI/ready-pixel', - 'weeb/pixelUI/set-pixel', - 'weeb/pixelUI/date-pixel' - ]); - introAssets.set('schoolEvil', [ - 'weeb/pixelUI/ready-pixel', - 'weeb/pixelUI/set-pixel', - 'weeb/pixelUI/date-pixel' - ]); - - var introAlts:Array = introAssets.get('default'); - var altSuffix:String = ""; - - for (value in introAssets.keys()) - { - if (value == curStage) - { - introAlts = introAssets.get(value); - altSuffix = '-pixel'; - } - } - - switch (swagCounter) - - { - case 0: - FlxG.sound.play(Paths.sound('intro3' + altSuffix), 0.6); - case 1: - var ready:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[0])); - ready.scrollFactor.set(); - ready.updateHitbox(); - - if (curStage.startsWith('school')) - ready.setGraphicSize(Std.int(ready.width * daPixelZoom)); - - ready.screenCenter(); - add(ready); - FlxTween.tween(ready, {y: ready.y += 100, alpha: 0}, Conductor.crochet / 1000, { - ease: FlxEase.cubeInOut, - onComplete: function(twn:FlxTween) - { - ready.destroy(); - } - }); - FlxG.sound.play(Paths.sound('intro2' + altSuffix), 0.6); - case 2: - var set:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[1])); - set.scrollFactor.set(); - - if (curStage.startsWith('school')) - set.setGraphicSize(Std.int(set.width * daPixelZoom)); - - set.screenCenter(); - add(set); - FlxTween.tween(set, {y: set.y += 100, alpha: 0}, Conductor.crochet / 1000, { - ease: FlxEase.cubeInOut, - onComplete: function(twn:FlxTween) - { - set.destroy(); - } - }); - FlxG.sound.play(Paths.sound('intro1' + altSuffix), 0.6); - case 3: - var go:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[2])); - go.scrollFactor.set(); - - if (curStage.startsWith('school')) - go.setGraphicSize(Std.int(go.width * daPixelZoom)); - - go.updateHitbox(); - - go.screenCenter(); - add(go); - FlxTween.tween(go, {y: go.y += 100, alpha: 0}, Conductor.crochet / 1000, { - ease: FlxEase.cubeInOut, - onComplete: function(twn:FlxTween) - { - go.destroy(); - } - }); - FlxG.sound.play(Paths.sound('introGo' + altSuffix), 0.6); - case 4: - } - - swagCounter += 1; - // generateSong('fresh'); - }, 5); - } - - var previousFrameTime:Int = 0; - var lastReportedPlayheadPosition:Int = 0; - var songTime:Float = 0; - - - var songStarted = false; - - function startSong():Void - { - startingSong = false; - songStarted = true; - previousFrameTime = FlxG.game.ticks; - lastReportedPlayheadPosition = 0; - - if (!paused) - { - FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); - } - - FlxG.sound.music.onComplete = endSong; - vocals.play(); - - // Song duration in a float, useful for the time left feature - songLength = FlxG.sound.music.length; - - if (FlxG.save.data.songPosition) - { - remove(songPosBG); - remove(songPosBar); - remove(songName); - - songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar')); - if (FlxG.save.data.downscroll) - songPosBG.y = FlxG.height * 0.9 + 45; - songPosBG.screenCenter(X); - songPosBG.scrollFactor.set(); - add(songPosBG); - - songPosBar = new FlxBar(songPosBG.x + 4, songPosBG.y + 4, LEFT_TO_RIGHT, Std.int(songPosBG.width - 8), Std.int(songPosBG.height - 8), this, - 'songPositionBar', 0, songLength - 1000); - songPosBar.numDivisions = 1000; - songPosBar.scrollFactor.set(); - songPosBar.createFilledBar(FlxColor.GRAY, FlxColor.LIME); - add(songPosBar); - - var songName = new FlxText(songPosBG.x + (songPosBG.width / 2) - 20,songPosBG.y,0,SONG.song, 16); - if (FlxG.save.data.downscroll) - songName.y -= 3; - songName.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); - songName.scrollFactor.set(); - add(songName); - - songPosBG.cameras = [camHUD]; - songPosBar.cameras = [camHUD]; - songName.cameras = [camHUD]; - } - - // Song check real quick - switch(curSong) - { - case 'Bopeebo' | 'Philly' | 'Blammed' | 'Cocoa' | 'Eggnog': allowedToHeadbang = true; - default: allowedToHeadbang = false; - } - - #if windows - // Updating Discord Rich Presence (with Time Left) - DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); - #end - } - - var debugNum:Int = 0; - - private function generateSong(dataPath:String):Void - { - // FlxG.log.add(ChartParser.parse()); - - var songData = SONG; - Conductor.changeBPM(songData.bpm); - - curSong = songData.song; - - if (SONG.needsVoices) - vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song)); - else - vocals = new FlxSound(); - - FlxG.sound.list.add(vocals); - - notes = new FlxTypedGroup(); - add(notes); - - var noteData:Array; - - // NEW SHIT - noteData = songData.notes; - - var playerCounter:Int = 0; - - // Per song offset check - #if windows - var songPath = 'assets/data/' + PlayState.SONG.song.toLowerCase() + '/'; - for(file in sys.FileSystem.readDirectory(songPath)) - { - var path = haxe.io.Path.join([songPath, file]); - if(!sys.FileSystem.isDirectory(path)) - { - if(path.endsWith('.offset')) - { - trace('Found offset file: ' + path); - songOffset = Std.parseFloat(file.substring(0, file.indexOf('.off'))); - break; - }else { - trace('Offset file not found. Creating one @: ' + songPath); - sys.io.File.saveContent(songPath + songOffset + '.offset', ''); - } - } - } - #end - var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped - for (section in noteData) - { - var coolSection:Int = Std.int(section.lengthInSteps / 4); - - for (songNotes in section.sectionNotes) - { - var daStrumTime:Float = songNotes[0] + FlxG.save.data.offset + songOffset; - if (daStrumTime < 0) - daStrumTime = 0; - var daNoteData:Int = Std.int(songNotes[1] % 4); - - var gottaHitNote:Bool = section.mustHitSection; - - if (songNotes[1] > 3) - { - gottaHitNote = !section.mustHitSection; - } - - var oldNote:Note; - if (unspawnNotes.length > 0) - oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)]; - else - oldNote = null; - - var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote); - swagNote.sustainLength = songNotes[2]; - swagNote.scrollFactor.set(0, 0); - - var susLength:Float = swagNote.sustainLength; - - susLength = susLength / Conductor.stepCrochet; - unspawnNotes.push(swagNote); - - for (susNote in 0...Math.floor(susLength)) - { - oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)]; - - var sustainNote:Note = new Note(daStrumTime + (Conductor.stepCrochet * susNote) + Conductor.stepCrochet, daNoteData, oldNote, true); - sustainNote.scrollFactor.set(); - unspawnNotes.push(sustainNote); - - sustainNote.mustPress = gottaHitNote; - - if (sustainNote.mustPress) - { - sustainNote.x += FlxG.width / 2; // general offset - } - } - - swagNote.mustPress = gottaHitNote; - - if (swagNote.mustPress) - { - swagNote.x += FlxG.width / 2; // general offset - } - else - { - } - } - daBeats += 1; - } - - // trace(unspawnNotes.length); - // playerCounter += 1; - - unspawnNotes.sort(sortByShit); - - generatedMusic = true; - } - - function sortByShit(Obj1:Note, Obj2:Note):Int - { - return FlxSort.byValues(FlxSort.ASCENDING, Obj1.strumTime, Obj2.strumTime); - } - - private function generateStaticArrows(player:Int):Void - { - for (i in 0...4) - { - // FlxG.log.add(i); - var babyArrow:FlxSprite = new FlxSprite(0, strumLine.y); - - switch (SONG.noteStyle) - { - case 'pixel': - babyArrow.loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17); - babyArrow.animation.add('green', [6]); - babyArrow.animation.add('red', [7]); - babyArrow.animation.add('blue', [5]); - babyArrow.animation.add('purplel', [4]); - - babyArrow.setGraphicSize(Std.int(babyArrow.width * daPixelZoom)); - babyArrow.updateHitbox(); - babyArrow.antialiasing = false; - - switch (Math.abs(i)) - { - case 0: - babyArrow.x += Note.swagWidth * 0; - babyArrow.animation.add('static', [0]); - babyArrow.animation.add('pressed', [4, 8], 12, false); - babyArrow.animation.add('confirm', [12, 16], 24, false); - case 1: - babyArrow.x += Note.swagWidth * 1; - babyArrow.animation.add('static', [1]); - babyArrow.animation.add('pressed', [5, 9], 12, false); - babyArrow.animation.add('confirm', [13, 17], 24, false); - case 2: - babyArrow.x += Note.swagWidth * 2; - babyArrow.animation.add('static', [2]); - babyArrow.animation.add('pressed', [6, 10], 12, false); - babyArrow.animation.add('confirm', [14, 18], 12, false); - case 3: - babyArrow.x += Note.swagWidth * 3; - babyArrow.animation.add('static', [3]); - babyArrow.animation.add('pressed', [7, 11], 12, false); - babyArrow.animation.add('confirm', [15, 19], 24, false); - } - - case 'normal': - babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets'); - babyArrow.animation.addByPrefix('green', 'arrowUP'); - babyArrow.animation.addByPrefix('blue', 'arrowDOWN'); - babyArrow.animation.addByPrefix('purple', 'arrowLEFT'); - babyArrow.animation.addByPrefix('red', 'arrowRIGHT'); - - babyArrow.antialiasing = true; - babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7)); - - switch (Math.abs(i)) - { - case 0: - babyArrow.x += Note.swagWidth * 0; - babyArrow.animation.addByPrefix('static', 'arrowLEFT'); - babyArrow.animation.addByPrefix('pressed', 'left press', 24, false); - babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false); - case 1: - babyArrow.x += Note.swagWidth * 1; - babyArrow.animation.addByPrefix('static', 'arrowDOWN'); - babyArrow.animation.addByPrefix('pressed', 'down press', 24, false); - babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false); - case 2: - babyArrow.x += Note.swagWidth * 2; - babyArrow.animation.addByPrefix('static', 'arrowUP'); - babyArrow.animation.addByPrefix('pressed', 'up press', 24, false); - babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false); - case 3: - babyArrow.x += Note.swagWidth * 3; - babyArrow.animation.addByPrefix('static', 'arrowRIGHT'); - babyArrow.animation.addByPrefix('pressed', 'right press', 24, false); - babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false); - } - - default: - babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets'); - babyArrow.animation.addByPrefix('green', 'arrowUP'); - babyArrow.animation.addByPrefix('blue', 'arrowDOWN'); - babyArrow.animation.addByPrefix('purple', 'arrowLEFT'); - babyArrow.animation.addByPrefix('red', 'arrowRIGHT'); - - babyArrow.antialiasing = true; - babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7)); - - switch (Math.abs(i)) - { - case 0: - babyArrow.x += Note.swagWidth * 0; - babyArrow.animation.addByPrefix('static', 'arrowLEFT'); - babyArrow.animation.addByPrefix('pressed', 'left press', 24, false); - babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false); - case 1: - babyArrow.x += Note.swagWidth * 1; - babyArrow.animation.addByPrefix('static', 'arrowDOWN'); - babyArrow.animation.addByPrefix('pressed', 'down press', 24, false); - babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false); - case 2: - babyArrow.x += Note.swagWidth * 2; - babyArrow.animation.addByPrefix('static', 'arrowUP'); - babyArrow.animation.addByPrefix('pressed', 'up press', 24, false); - babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false); - case 3: - babyArrow.x += Note.swagWidth * 3; - babyArrow.animation.addByPrefix('static', 'arrowRIGHT'); - babyArrow.animation.addByPrefix('pressed', 'right press', 24, false); - babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false); - } - } - - babyArrow.updateHitbox(); - babyArrow.scrollFactor.set(); - - if (!isStoryMode) - { - babyArrow.y -= 10; - babyArrow.alpha = 0; - FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)}); - } - - babyArrow.ID = i; - - if (player == 1) - { - playerStrums.add(babyArrow); - } - - babyArrow.animation.play('static'); - babyArrow.x += 50; - babyArrow.x += ((FlxG.width / 2) * player); - - strumLineNotes.add(babyArrow); - } - } - - function tweenCamIn():Void - { - FlxTween.tween(FlxG.camera, {zoom: 1.3}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut}); - } - - override function openSubState(SubState:FlxSubState) - { - if (paused) - { - if (FlxG.sound.music != null) - { - FlxG.sound.music.pause(); - vocals.pause(); - } - - #if windows - DiscordClient.changePresence("PAUSED on " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "Acc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); - #end - if (!startTimer.finished) - startTimer.active = false; - } - - super.openSubState(SubState); - } - - override function closeSubState() - { - if (paused) - { - if (FlxG.sound.music != null && !startingSong) - { - resyncVocals(); - } - - if (!startTimer.finished) - startTimer.active = true; - paused = false; - - #if windows - if (startTimer.finished) - { - DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses, iconRPC, true, songLength - Conductor.songPosition); - } - else - { - DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), iconRPC); - } - #end - } - - super.closeSubState(); - } - - - function resyncVocals():Void - { - vocals.pause(); - - FlxG.sound.music.play(); - Conductor.songPosition = FlxG.sound.music.time; - vocals.time = Conductor.songPosition; - vocals.play(); - - #if windows - DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); - #end - } - - private var paused:Bool = false; - var startedCountdown:Bool = false; - var canPause:Bool = true; - - public static var songRate = 1.5; - - override public function update(elapsed:Float) - { - #if !debug - perfectMode = false; - #end - - if (FlxG.save.data.botplay && FlxG.keys.justPressed.ONE) - camHUD.visible = !camHUD.visible; - - #if windows - if (executeModchart && luaModchart != null && songStarted) - { - luaModchart.setVar('songPos',Conductor.songPosition); - luaModchart.setVar('hudZoom', camHUD.zoom); - luaModchart.setVar('cameraZoom',FlxG.camera.zoom); - luaModchart.executeState('update', [elapsed]); - - for (i in luaWiggles) - { - trace('wiggle le gaming'); - i.update(elapsed); - } - - /*for (i in 0...strumLineNotes.length) { - var member = strumLineNotes.members[i]; - member.x = luaModchart.getVar("strum" + i + "X", "float"); - member.y = luaModchart.getVar("strum" + i + "Y", "float"); - member.angle = luaModchart.getVar("strum" + i + "Angle", "float"); - }*/ - - FlxG.camera.angle = luaModchart.getVar('cameraAngle', 'float'); - camHUD.angle = luaModchart.getVar('camHudAngle','float'); - - if (luaModchart.getVar("showOnlyStrums",'bool')) - { - healthBarBG.visible = false; - kadeEngineWatermark.visible = false; - healthBar.visible = false; - iconP1.visible = false; - iconP2.visible = false; - scoreTxt.visible = false; - } - else - { - healthBarBG.visible = true; - kadeEngineWatermark.visible = true; - healthBar.visible = true; - iconP1.visible = true; - iconP2.visible = true; - scoreTxt.visible = true; - } - - var p1 = luaModchart.getVar("strumLine1Visible",'bool'); - var p2 = luaModchart.getVar("strumLine2Visible",'bool'); - - for (i in 0...4) - { - strumLineNotes.members[i].visible = p1; - if (i <= playerStrums.length) - playerStrums.members[i].visible = p2; - } - } - - #end - - if (currentFrames == FlxG.save.data.fpsCap) - { - for(i in 0...notesHitArray.length) - { - var cock:Date = notesHitArray[i]; - if (cock != null) - if (cock.getTime() + 2000 < Date.now().getTime()) - notesHitArray.remove(cock); - } - nps = Math.floor(notesHitArray.length / 2); - currentFrames = 0; - } - else - currentFrames++; - - if (FlxG.keys.justPressed.NINE) - { - if (iconP1.animation.curAnim.name == 'bf-old') - iconP1.animation.play(SONG.player1); - else - iconP1.animation.play('bf-old'); - } - - switch (curStage) - { - case 'philly': - if (trainMoving) - { - trainFrameTiming += elapsed; - - if (trainFrameTiming >= 1 / 24) - { - updateTrainPos(); - trainFrameTiming = 0; - } - } - // phillyCityLights.members[curLight].alpha -= (Conductor.crochet / 1000) * FlxG.elapsed; - } - - super.update(elapsed); - - scoreTxt.text = Ratings.CalculateRanking(songScore,songScoreDef,nps,accuracy); - if (FlxG.keys.justPressed.ENTER && startedCountdown && canPause) - { - persistentUpdate = false; - persistentDraw = true; - paused = true; - - // 1 / 1000 chance for Gitaroo Man easter egg - if (FlxG.random.bool(0.1)) - { - // gitaroo man easter egg - FlxG.switchState(new GitarooPause()); - } - else - openSubState(new PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); - } - - if (FlxG.keys.justPressed.SEVEN) - { - #if windows - DiscordClient.changePresence("Chart Editor", null, null, true); - #end - FlxG.switchState(new ChartingState()); - #if windows - if (luaModchart != null) - { - luaModchart.die(); - luaModchart = null; - } - #end - } - - // FlxG.watch.addQuick('VOL', vocals.amplitudeLeft); - // FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight); - - iconP1.setGraphicSize(Std.int(FlxMath.lerp(150, iconP1.width, 0.50))); - iconP2.setGraphicSize(Std.int(FlxMath.lerp(150, iconP2.width, 0.50))); - - iconP1.updateHitbox(); - iconP2.updateHitbox(); - - var iconOffset:Int = 26; - - iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01) - iconOffset); - iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01)) - (iconP2.width - iconOffset); - - if (health > 2) - health = 2; - - if (healthBar.percent < 20) - iconP1.animation.curAnim.curFrame = 1; - else - iconP1.animation.curAnim.curFrame = 0; - - if (healthBar.percent > 80) - iconP2.animation.curAnim.curFrame = 1; - else - iconP2.animation.curAnim.curFrame = 0; - - /* if (FlxG.keys.justPressed.NINE) - FlxG.switchState(new Charting()); */ - - #if debug - if (FlxG.keys.justPressed.EIGHT) - { - FlxG.switchState(new AnimationDebug(SONG.player2)); - #if windows - if (luaModchart != null) - { - luaModchart.die(); - luaModchart = null; - } - #end - } - - #end - - if (startingSong) - { - if (startedCountdown) - { - Conductor.songPosition += FlxG.elapsed * 1000; - if (Conductor.songPosition >= 0) - startSong(); - } - } - else - { - // Conductor.songPosition = FlxG.sound.music.time; - Conductor.songPosition += FlxG.elapsed * 1000; - /*@:privateAccess - { - FlxG.sound.music._channel. - }*/ - songPositionBar = Conductor.songPosition; - - if (!paused) - { - songTime += FlxG.game.ticks - previousFrameTime; - previousFrameTime = FlxG.game.ticks; - - // Interpolation type beat - if (Conductor.lastSongPos != Conductor.songPosition) - { - songTime = (songTime + Conductor.songPosition) / 2; - Conductor.lastSongPos = Conductor.songPosition; - // Conductor.songPosition += FlxG.elapsed * 1000; - // trace('MISSED FRAME'); - } - } - - // Conductor.lastSongPos = FlxG.sound.music.time; - } - - if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null) - { - // Make sure Girlfriend cheers only for certain songs - if(allowedToHeadbang) - { - // Don't animate GF if something else is already animating her (eg. train passing) - if(gf.animation.curAnim.name == 'danceLeft' || gf.animation.curAnim.name == 'danceRight' || gf.animation.curAnim.name == 'idle') - { - // Per song treatment since some songs will only have the 'Hey' at certain times - switch(curSong) - { - case 'Philly': - { - // General duration of the song - if(curBeat < 250) - { - // Beats to skip or to stop GF from cheering - if(curBeat != 184 && curBeat != 216) - { - if(curBeat % 16 == 8) - { - // Just a garantee that it'll trigger just once - if(!triggeredAlready) - { - gf.playAnim('cheer'); - triggeredAlready = true; - } - }else triggeredAlready = false; - } - } - } - case 'Bopeebo': - { - // Where it starts || where it ends - if(curBeat > 5 && curBeat < 130) - { - if(curBeat % 8 == 7) - { - if(!triggeredAlready) - { - gf.playAnim('cheer'); - triggeredAlready = true; - } - }else triggeredAlready = false; - } - } - case 'Blammed': - { - if(curBeat > 30 && curBeat < 190) - { - if(curBeat < 90 || curBeat > 128) - { - if(curBeat % 4 == 2) - { - if(!triggeredAlready) - { - gf.playAnim('cheer'); - triggeredAlready = true; - } - }else triggeredAlready = false; - } - } - } - case 'Cocoa': - { - if(curBeat < 170) - { - if(curBeat < 65 || curBeat > 130 && curBeat < 145) - { - if(curBeat % 16 == 15) - { - if(!triggeredAlready) - { - gf.playAnim('cheer'); - triggeredAlready = true; - } - }else triggeredAlready = false; - } - } - } - case 'Eggnog': - { - if(curBeat > 10 && curBeat != 111 && curBeat < 220) - { - if(curBeat % 8 == 7) - { - if(!triggeredAlready) - { - gf.playAnim('cheer'); - triggeredAlready = true; - } - }else triggeredAlready = false; - } - } - } - } - } - - #if windows - if (luaModchart != null) - luaModchart.setVar("mustHit",PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection); - #end - - if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection) - { - var offsetX = 0; - var offsetY = 0; - #if windows - if (luaModchart != null) - { - offsetX = luaModchart.getVar("followXOffset", "float"); - offsetY = luaModchart.getVar("followYOffset", "float"); - } - #end - camFollow.setPosition(dad.getMidpoint().x + 150 + offsetX, dad.getMidpoint().y - 100 + offsetY); - #if windows - if (luaModchart != null) - luaModchart.executeState('playerTwoTurn', []); - #end - // camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210); - - switch (dad.curCharacter) - { - case 'mom': - camFollow.y = dad.getMidpoint().y; - case 'senpai': - camFollow.y = dad.getMidpoint().y - 430; - camFollow.x = dad.getMidpoint().x - 100; - case 'senpai-angry': - camFollow.y = dad.getMidpoint().y - 430; - camFollow.x = dad.getMidpoint().x - 100; - } - - if (dad.curCharacter == 'mom') - vocals.volume = 1; - } - - if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100) - { - var offsetX = 0; - var offsetY = 0; - #if windows - if (luaModchart != null) - { - offsetX = luaModchart.getVar("followXOffset", "float"); - offsetY = luaModchart.getVar("followYOffset", "float"); - } - #end - camFollow.setPosition(boyfriend.getMidpoint().x - 100 + offsetX, boyfriend.getMidpoint().y - 100 + offsetY); - - #if windows - if (luaModchart != null) - luaModchart.executeState('playerOneTurn', []); - #end - - switch (curStage) - { - case 'limo': - camFollow.x = boyfriend.getMidpoint().x - 300; - case 'mall': - camFollow.y = boyfriend.getMidpoint().y - 200; - case 'school': - camFollow.x = boyfriend.getMidpoint().x - 200; - camFollow.y = boyfriend.getMidpoint().y - 200; - case 'schoolEvil': - camFollow.x = boyfriend.getMidpoint().x - 200; - camFollow.y = boyfriend.getMidpoint().y - 200; - } - } - } - - if (camZooming) - { - FlxG.camera.zoom = FlxMath.lerp(defaultCamZoom, FlxG.camera.zoom, 0.95); - camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95); - } - - FlxG.watch.addQuick("beatShit", curBeat); - FlxG.watch.addQuick("stepShit", curStep); - if (loadRep) // rep debug - { - FlxG.watch.addQuick('rep rpesses',repPresses); - FlxG.watch.addQuick('rep releases',repReleases); - // FlxG.watch.addQuick('Queued',inputsQueued); - } - - if (curSong == 'Fresh') - { - switch (curBeat) - { - case 16: - camZooming = true; - gfSpeed = 2; - case 48: - gfSpeed = 1; - case 80: - gfSpeed = 2; - case 112: - gfSpeed = 1; - case 163: - // FlxG.sound.music.stop(); - // FlxG.switchState(new TitleState()); - } - } - - if (curSong == 'Bopeebo') - { - switch (curBeat) - { - case 128, 129, 130: - vocals.volume = 0; - // FlxG.sound.music.stop(); - // FlxG.switchState(new PlayState()); - } - } - - if (health <= 0) - { - boyfriend.stunned = true; - - persistentUpdate = false; - persistentDraw = false; - paused = true; - - vocals.stop(); - FlxG.sound.music.stop(); - - openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); - - #if windows - // Game Over doesn't get his own variable because it's only used here - DiscordClient.changePresence("GAME OVER -- " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy),"\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); - #end - - // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); - } - - if (unspawnNotes[0] != null) - { - if (unspawnNotes[0].strumTime - Conductor.songPosition < 3500) - { - var dunceNote:Note = unspawnNotes[0]; - notes.add(dunceNote); - - var index:Int = unspawnNotes.indexOf(dunceNote); - unspawnNotes.splice(index, 1); - } - } - - if (generatedMusic) - { - notes.forEachAlive(function(daNote:Note) - { - - // instead of doing stupid y > FlxG.height - // we be men and actually calculate the time :) - if (daNote.tooLate) - { - daNote.active = false; - daNote.visible = false; - } - else - { - daNote.visible = true; - daNote.active = true; - } - - if (!daNote.modifiedByLua) - { - if (FlxG.save.data.downscroll) - { - if (daNote.mustPress) - daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)); - else - daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)); - if(daNote.isSustainNote) - { - // Remember = minus makes notes go up, plus makes them go down - if(daNote.animation.curAnim.name.endsWith('end') && daNote.prevNote != null) - daNote.y += daNote.prevNote.height; - else - daNote.y += daNote.height / 2; - - // If not in botplay, only clip sustain notes when properly hit, botplay gets to clip it everytime - if(!FlxG.save.data.botplay) - { - if((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit && !daNote.canBeHit) && daNote.y - daNote.offset.y * daNote.scale.y + daNote.height >= (strumLine.y + Note.swagWidth / 2)) - { - // Clip to strumline - var swagRect = new FlxRect(0, 0, daNote.frameWidth * 2, daNote.frameHeight * 2); - swagRect.height = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y; - swagRect.y = daNote.frameHeight - swagRect.height; - - daNote.clipRect = swagRect; - } - }else { - var swagRect = new FlxRect(0, 0, daNote.frameWidth * 2, daNote.frameHeight * 2); - swagRect.height = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y; - swagRect.y = daNote.frameHeight - swagRect.height; - - daNote.clipRect = swagRect; - } - } - }else - { - if (daNote.mustPress) - daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)); - else - daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)); - if(daNote.isSustainNote) - { - daNote.y -= daNote.height / 2; - - if(!FlxG.save.data.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 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 && !FlxG.save.data.downscroll || daNote.mustPress && daNote.tooLate && FlxG.save.data.downscroll) && daNote.mustPress) - { - if (daNote.isSustainNote && daNote.wasGoodHit) - { - daNote.kill(); - notes.remove(daNote, true); - daNote.destroy(); - } - else - { - health -= 0.075; - vocals.volume = 0; - if (theFunne) - noteMiss(daNote.noteData, daNote); - } - - daNote.active = false; - daNote.visible = false; - - daNote.kill(); - notes.remove(daNote, true); - daNote.destroy(); - } - }); - } - - - if (!inCutscene) - keyShit(); - - - #if debug - if (FlxG.keys.justPressed.ONE) - endSong(); - #end - } - - function endSong():Void - { - if (!loadRep) - rep.SaveReplay(); - - if (FlxG.save.data.fpsCap > 290) - (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290); - - #if windows - if (luaModchart != null) - { - luaModchart.die(); - luaModchart = null; - } - #end - - canPause = false; - FlxG.sound.music.volume = 0; - vocals.volume = 0; - if (SONG.validScore) - { - #if !switch - Highscore.saveScore(SONG.song, Math.round(songScore), storyDifficulty); - #end - } - - if (offsetTesting) - { - FlxG.sound.playMusic(Paths.music('freakyMenu')); - offsetTesting = false; - LoadingState.loadAndSwitchState(new OptionsMenu()); - FlxG.save.data.offset = offsetTest; - } - else - { - if (isStoryMode) - { - campaignScore += Math.round(songScore); - - storyPlaylist.remove(storyPlaylist[0]); - - if (storyPlaylist.length <= 0) - { - FlxG.sound.playMusic(Paths.music('freakyMenu')); - - transIn = FlxTransitionableState.defaultTransIn; - transOut = FlxTransitionableState.defaultTransOut; - - FlxG.switchState(new StoryMenuState()); - - #if windows - if (luaModchart != null) - { - luaModchart.die(); - luaModchart = null; - } - #end - - // if () - StoryMenuState.weekUnlocked[Std.int(Math.min(storyWeek + 1, StoryMenuState.weekUnlocked.length - 1))] = true; - - if (SONG.validScore) - { - NGio.unlockMedal(60961); - Highscore.saveWeekScore(storyWeek, campaignScore, storyDifficulty); - } - - FlxG.save.data.weekUnlocked = StoryMenuState.weekUnlocked; - FlxG.save.flush(); - } - else - { - var difficulty:String = ""; - - if (storyDifficulty == 0) - difficulty = '-easy'; - - if (storyDifficulty == 2) - difficulty = '-hard'; - - trace('LOADING NEXT SONG'); - trace(PlayState.storyPlaylist[0].toLowerCase() + difficulty); - - if (SONG.song.toLowerCase() == 'eggnog') - { - var blackShit:FlxSprite = new FlxSprite(-FlxG.width * FlxG.camera.zoom, - -FlxG.height * FlxG.camera.zoom).makeGraphic(FlxG.width * 3, FlxG.height * 3, FlxColor.BLACK); - blackShit.scrollFactor.set(); - add(blackShit); - camHUD.visible = false; - - FlxG.sound.play(Paths.sound('Lights_Shut_off')); - } - - FlxTransitionableState.skipNextTransIn = true; - FlxTransitionableState.skipNextTransOut = true; - prevCamFollow = camFollow; - - PlayState.SONG = Song.loadFromJson(PlayState.storyPlaylist[0].toLowerCase() + difficulty, PlayState.storyPlaylist[0]); - FlxG.sound.music.stop(); - - LoadingState.loadAndSwitchState(new PlayState()); - } - } - else - { - trace('WENT BACK TO FREEPLAY??'); - FlxG.switchState(new FreeplayState()); - } - } - } - - - var endingSong:Bool = false; - - var hits:Array = []; - var offsetTest:Float = 0; - - var timeShown = 0; - var currentTimingShown:FlxText = null; - - private function popUpScore(daNote:Note):Void - { - var noteDiff:Float = Math.abs(Conductor.songPosition - daNote.strumTime); - var wife:Float = EtternaFunctions.wife3(noteDiff, Conductor.timeScale); - // boyfriend.playAnim('hey'); - vocals.volume = 1; - - var placement:String = Std.string(combo); - - var coolText:FlxText = new FlxText(0, 0, 0, placement, 32); - coolText.screenCenter(); - coolText.x = FlxG.width * 0.55; - coolText.y -= 350; - coolText.cameras = [camHUD]; - // - - var rating:FlxSprite = new FlxSprite(); - var score:Float = 350; - - if (FlxG.save.data.accuracyMod == 1) - totalNotesHit += wife; - - var daRating = daNote.rating; - - switch(daRating) - { - case 'shit': - score = -300; - combo = 0; - misses++; - health -= 0.2; - ss = false; - shits++; - if (FlxG.save.data.accuracyMod == 0) - totalNotesHit += 0.25; - case 'bad': - daRating = 'bad'; - score = 0; - health -= 0.06; - ss = false; - bads++; - if (FlxG.save.data.accuracyMod == 0) - totalNotesHit += 0.50; - case 'good': - daRating = 'good'; - score = 200; - ss = false; - goods++; - if (health < 2) - health += 0.04; - if (FlxG.save.data.accuracyMod == 0) - totalNotesHit += 0.75; - case 'sick': - if (health < 2) - health += 0.1; - if (FlxG.save.data.accuracyMod == 0) - totalNotesHit += 1; - sicks++; - } - - // trace('Wife accuracy loss: ' + wife + ' | Rating: ' + daRating + ' | Score: ' + score + ' | Weight: ' + (1 - wife)); - - if (daRating != 'shit' || daRating != 'bad') - { - - - songScore += Math.round(score); - songScoreDef += Math.round(ConvertScore.convertScore(noteDiff)); - - /* if (combo > 60) - daRating = 'sick'; - else if (combo > 12) - daRating = 'good' - else if (combo > 4) - daRating = 'bad'; - */ - - var pixelShitPart1:String = ""; - var pixelShitPart2:String = ''; - - if (curStage.startsWith('school')) - { - pixelShitPart1 = 'weeb/pixelUI/'; - pixelShitPart2 = '-pixel'; - } - - rating.loadGraphic(Paths.image(pixelShitPart1 + daRating + pixelShitPart2)); - rating.screenCenter(); - rating.y -= 50; - rating.x = coolText.x - 125; - - if (FlxG.save.data.changedHit) - { - rating.x = FlxG.save.data.changedHitX; - rating.y = FlxG.save.data.changedHitY; - } - rating.acceleration.y = 550; - rating.velocity.y -= FlxG.random.int(140, 175); - rating.velocity.x -= FlxG.random.int(0, 10); - - var msTiming = HelperFunctions.truncateFloat(noteDiff, 3); - if(FlxG.save.data.botplay) msTiming = 0; - - if (currentTimingShown != null) - remove(currentTimingShown); - - currentTimingShown = new FlxText(0,0,0,"0ms"); - timeShown = 0; - switch(daRating) - { - case 'shit' | 'bad': - currentTimingShown.color = FlxColor.RED; - case 'good': - currentTimingShown.color = FlxColor.GREEN; - case 'sick': - currentTimingShown.color = FlxColor.CYAN; - } - currentTimingShown.borderStyle = OUTLINE; - currentTimingShown.borderSize = 1; - currentTimingShown.borderColor = FlxColor.BLACK; - currentTimingShown.text = msTiming + "ms"; - currentTimingShown.size = 20; - - if (msTiming >= 0.03 && offsetTesting) - { - //Remove Outliers - hits.shift(); - hits.shift(); - hits.shift(); - hits.pop(); - hits.pop(); - hits.pop(); - hits.push(msTiming); - - var total = 0.0; - - for(i in hits) - total += i; - - - - offsetTest = HelperFunctions.truncateFloat(total / hits.length,2); - } - - if (currentTimingShown.alpha != 1) - currentTimingShown.alpha = 1; - - if(!FlxG.save.data.botplay) add(currentTimingShown); - - var comboSpr:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'combo' + pixelShitPart2)); - comboSpr.screenCenter(); - comboSpr.x = rating.x; - comboSpr.y = rating.y + 100; - comboSpr.acceleration.y = 600; - comboSpr.velocity.y -= 150; - - currentTimingShown.screenCenter(); - currentTimingShown.x = comboSpr.x + 100; - currentTimingShown.y = rating.y + 100; - currentTimingShown.acceleration.y = 600; - currentTimingShown.velocity.y -= 150; - - comboSpr.velocity.x += FlxG.random.int(1, 10); - currentTimingShown.velocity.x += comboSpr.velocity.x; - if(!FlxG.save.data.botplay) add(rating); - - if (!curStage.startsWith('school')) - { - rating.setGraphicSize(Std.int(rating.width * 0.7)); - rating.antialiasing = true; - comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7)); - comboSpr.antialiasing = true; - } - else - { - rating.setGraphicSize(Std.int(rating.width * daPixelZoom * 0.7)); - comboSpr.setGraphicSize(Std.int(comboSpr.width * daPixelZoom * 0.7)); - } - - currentTimingShown.updateHitbox(); - comboSpr.updateHitbox(); - rating.updateHitbox(); - - currentTimingShown.cameras = [camHUD]; - comboSpr.cameras = [camHUD]; - rating.cameras = [camHUD]; - - var seperatedScore:Array = []; - - var comboSplit:Array = (combo + "").split(''); - - if (comboSplit.length == 2) - seperatedScore.push(0); // make sure theres a 0 in front or it looks weird lol! - - for(i in 0...comboSplit.length) - { - var str:String = comboSplit[i]; - seperatedScore.push(Std.parseInt(str)); - } - - var daLoop:Int = 0; - for (i in seperatedScore) - { - var numScore:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'num' + Std.int(i) + pixelShitPart2)); - numScore.screenCenter(); - numScore.x = rating.x + (43 * daLoop) - 50; - numScore.y = rating.y + 100; - numScore.cameras = [camHUD]; - - if (!curStage.startsWith('school')) - { - numScore.antialiasing = true; - numScore.setGraphicSize(Std.int(numScore.width * 0.5)); - } - else - { - numScore.setGraphicSize(Std.int(numScore.width * daPixelZoom)); - } - numScore.updateHitbox(); - - numScore.acceleration.y = FlxG.random.int(200, 300); - numScore.velocity.y -= FlxG.random.int(140, 160); - numScore.velocity.x = FlxG.random.float(-5, 5); - - if (combo >= 10 || combo == 0) - add(numScore); - - FlxTween.tween(numScore, {alpha: 0}, 0.2, { - onComplete: function(tween:FlxTween) - { - numScore.destroy(); - }, - startDelay: Conductor.crochet * 0.002 - }); - - daLoop++; - } - /* - trace(combo); - trace(seperatedScore); - */ - - coolText.text = Std.string(seperatedScore); - // add(coolText); - - FlxTween.tween(rating, {alpha: 0}, 0.2, { - startDelay: Conductor.crochet * 0.001, - onUpdate: function(tween:FlxTween) - { - if (currentTimingShown != null) - currentTimingShown.alpha -= 0.02; - timeShown++; - } - }); - - FlxTween.tween(comboSpr, {alpha: 0}, 0.2, { - onComplete: function(tween:FlxTween) - { - coolText.destroy(); - comboSpr.destroy(); - if (currentTimingShown != null && timeShown >= 20) - { - remove(currentTimingShown); - currentTimingShown = null; - } - rating.destroy(); - }, - startDelay: Conductor.crochet * 0.001 - }); - - curSection += 1; - } - } - - public function NearlyEquals(value1:Float, value2:Float, unimportantDifference:Float = 10):Bool - { - return Math.abs(FlxMath.roundDecimal(value1, 1) - FlxMath.roundDecimal(value2, 1)) < unimportantDifference; - } - - var upHold:Bool = false; - var downHold:Bool = false; - var rightHold:Bool = false; - var leftHold:Bool = false; - - private function keyShit():Void // I've invested in emma stocks - { - // control arrays, order L D R U - var holdArray:Array = [controls.LEFT, controls.DOWN, controls.UP, controls.RIGHT]; - var pressArray:Array = [ - controls.LEFT_P, - controls.DOWN_P, - controls.UP_P, - controls.RIGHT_P - ]; - var releaseArray:Array = [ - controls.LEFT_R, - controls.DOWN_R, - controls.UP_R, - controls.RIGHT_R - ]; - - // Prevent player input if botplay is on - if(FlxG.save.data.botplay) - { - 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); - }); - } - - // 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 - - notes.forEachAlive(function(daNote:Note) - { - if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit) - { - if (directionList.contains(daNote.noteData)) - { - 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; - - for (i in 0...pressArray.length) - { - if (pressArray[i] && !directionList.contains(i)) - dontCheck = true; - } - - 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 && !FlxG.save.data.botplay) - { - if (mashViolations > 4) - { - trace('mash violations ' + mashViolations); - scoreTxt.color = FlxColor.RED; - noteMiss(0,null); - } - else - mashViolations++; - } - - } - - notes.forEachAlive(function(daNote:Note) - { - if(FlxG.save.data.downscroll && daNote.y > strumLine.y || - !FlxG.save.data.downscroll && daNote.y < strumLine.y) - { - // Force good note hit regardless if it's too late to hit it or not as a fail safe - if(FlxG.save.data.botplay && daNote.canBeHit && daNote.mustPress || - FlxG.save.data.botplay && daNote.tooLate && daNote.mustPress) - { - goodNoteHit(daNote); - boyfriend.holdTimer = daNote.sustainLength; - } - } - }); - if (boyfriend.holdTimer > Conductor.stepCrochet * 4 * 0.001 && !holdArray.contains(true)) - { - if (boyfriend.animation.curAnim.name.startsWith('sing') && !boyfriend.animation.curAnim.name.endsWith('miss')) - boyfriend.playAnim('idle'); - } - - playerStrums.forEach(function(spr:FlxSprite) - { - if (pressArray[spr.ID] && spr.animation.curAnim.name != 'confirm') - spr.animation.play('pressed'); - if (!holdArray[spr.ID]) - spr.animation.play('static'); - - if (spr.animation.curAnim.name == 'confirm' && !curStage.startsWith('school')) - { - spr.centerOffsets(); - spr.offset.x -= 13; - spr.offset.y -= 13; - } - else - spr.centerOffsets(); - }); - } - - function noteMiss(direction:Int = 1, daNote:Note):Void - { - if (!boyfriend.stunned) - { - health -= 0.04; - if (combo > 5 && gf.animOffsets.exists('sad')) - { - gf.playAnim('sad'); - } - combo = 0; - misses++; - - //var noteDiff:Float = Math.abs(daNote.strumTime - Conductor.songPosition); - //var wife:Float = EtternaFunctions.wife3(noteDiff, FlxG.save.data.etternaMode ? 1 : 1.7); - - if (FlxG.save.data.accuracyMod == 1) - totalNotesHit -= 1; - - songScore -= 10; - - FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2)); - // FlxG.sound.play(Paths.sound('missnote1'), 1, false); - // FlxG.log.add('played imss note'); - - switch (direction) - { - case 0: - boyfriend.playAnim('singLEFTmiss', true); - case 1: - boyfriend.playAnim('singDOWNmiss', true); - case 2: - boyfriend.playAnim('singUPmiss', true); - case 3: - boyfriend.playAnim('singRIGHTmiss', true); - } - - #if windows - if (luaModchart != null) - luaModchart.executeState('playerOneMiss', [direction, Conductor.songPosition]); - #end - - - updateAccuracy(); - } - } - - /*function badNoteCheck() - { - // just double pasting this shit cuz fuk u - // REDO THIS SYSTEM! - var upP = controls.UP_P; - var rightP = controls.RIGHT_P; - var downP = controls.DOWN_P; - var leftP = controls.LEFT_P; - - if (leftP) - noteMiss(0); - if (upP) - noteMiss(2); - if (rightP) - noteMiss(3); - if (downP) - noteMiss(1); - updateAccuracy(); - } - */ - function updateAccuracy() - { - totalPlayed += 1; - accuracy = Math.max(0,totalNotesHit / totalPlayed * 100); - accuracyDefault = Math.max(0, totalNotesHitDefault / totalPlayed * 100); - } - - - function getKeyPresses(note:Note):Int - { - var possibleNotes:Array = []; // copypasted but you already know that - - notes.forEachAlive(function(daNote:Note) - { - if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate) - { - possibleNotes.push(daNote); - possibleNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime)); - } - }); - if (possibleNotes.length == 1) - return possibleNotes.length + 1; - return possibleNotes.length; - } - - var mashing:Int = 0; - var mashViolations:Int = 0; - - var etternaModeScore:Int = 0; - - function noteCheck(controlArray:Array, note:Note):Void // sorry lol - { - var noteDiff:Float = Math.abs(note.strumTime - Conductor.songPosition); - - note.rating = Ratings.CalculateRating(noteDiff); - - if (loadRep) - { - if (controlArray[note.noteData]) - goodNoteHit(note, false); - else if (rep.replay.keyPresses.length > repPresses && !controlArray[note.noteData]) - { - if (NearlyEquals(note.strumTime,rep.replay.keyPresses[repPresses].time, 4)) - { - goodNoteHit(note, false); - } - } - } - else if (controlArray[note.noteData]) - { - - goodNoteHit(note, (mashing > getKeyPresses(note))); - - /*if (mashing > getKeyPresses(note) && mashViolations <= 2) - { - mashViolations++; - - goodNoteHit(note, (mashing > getKeyPresses(note))); - } - else if (mashViolations > 2) - { - // this is bad but fuck you - playerStrums.members[0].animation.play('static'); - playerStrums.members[1].animation.play('static'); - playerStrums.members[2].animation.play('static'); - playerStrums.members[3].animation.play('static'); - health -= 0.4; - trace('mash ' + mashing); - if (mashing != 0) - mashing = 0; - } - else - goodNoteHit(note, false);*/ - - } - } - - var nps:Int = 0; - - function goodNoteHit(note:Note, resetMashViolation = true):Void - { - - if (mashing != 0) - mashing = 0; - - var noteDiff:Float = Math.abs(note.strumTime - Conductor.songPosition); - - note.rating = Ratings.CalculateRating(noteDiff); - - if (!note.isSustainNote) - notesHitArray.push(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) - playerStrums.forEach(function(spr:FlxSprite) - { - if (Math.abs(note.noteData) == spr.ID) - { - spr.animation.play('confirm', true); - } - }); - - note.wasGoodHit = true; - vocals.volume = 1; - - note.kill(); - notes.remove(note, true); - note.destroy(); - - updateAccuracy(); - } - } - - - var fastCarCanDrive:Bool = true; - - function resetFastCar():Void - { - if(FlxG.save.data.distractions){ - fastCar.x = -12600; - fastCar.y = FlxG.random.int(140, 250); - fastCar.velocity.x = 0; - fastCarCanDrive = true; - } - } - - function fastCarDrive() - { - if(FlxG.save.data.distractions){ - FlxG.sound.play(Paths.soundRandom('carPass', 0, 1), 0.7); - - fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; - fastCarCanDrive = false; - new FlxTimer().start(2, function(tmr:FlxTimer) - { - resetFastCar(); - }); - } - } - - var trainMoving:Bool = false; - var trainFrameTiming:Float = 0; - - var trainCars:Int = 8; - var trainFinishing:Bool = false; - var trainCooldown:Int = 0; - - function trainStart():Void - { - if(FlxG.save.data.distractions){ - trainMoving = true; - if (!trainSound.playing) - trainSound.play(true); - } - } - - var startedMoving:Bool = false; - - function updateTrainPos():Void - { - if(FlxG.save.data.distractions){ - if (trainSound.time >= 4700) - { - startedMoving = true; - gf.playAnim('hairBlow'); - } - - if (startedMoving) - { - phillyTrain.x -= 400; - - if (phillyTrain.x < -2000 && !trainFinishing) - { - phillyTrain.x = -1150; - trainCars -= 1; - - if (trainCars <= 0) - trainFinishing = true; - } - - if (phillyTrain.x < -4000 && trainFinishing) - trainReset(); - } - } - - } - - function trainReset():Void - { - if(FlxG.save.data.distractions){ - gf.playAnim('hairFall'); - phillyTrain.x = FlxG.width + 200; - trainMoving = false; - // trainSound.stop(); - // trainSound.time = 0; - trainCars = 8; - trainFinishing = false; - startedMoving = false; - } - } - - function lightningStrikeShit():Void - { - FlxG.sound.play(Paths.soundRandom('thunder_', 1, 2)); - halloweenBG.animation.play('lightning'); - - lightningStrikeBeat = curBeat; - lightningOffset = FlxG.random.int(8, 24); - - boyfriend.playAnim('scared', true); - gf.playAnim('scared', true); - } - - override function stepHit() - { - super.stepHit(); - if (FlxG.sound.music.time > Conductor.songPosition + 20 || FlxG.sound.music.time < Conductor.songPosition - 20) - { - resyncVocals(); - } - - #if windows - if (executeModchart && luaModchart != null) - { - luaModchart.setVar('curStep',curStep); - luaModchart.executeState('stepHit',[curStep]); - } - #end - - if (dad.curCharacter == 'spooky' && curStep % 4 == 2) - { - // dad.dance(); - } - - - // yes this updates every step. - // yes this is bad - // but i'm doing it to update misses and accuracy - #if windows - // Song duration in a float, useful for the time left feature - songLength = FlxG.sound.music.length; - - // Updating Discord Rich Presence (with Time Left) - DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "Acc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC,true, songLength - Conductor.songPosition); - #end - - } - - var lightningStrikeBeat:Int = 0; - var lightningOffset:Int = 8; - - override function beatHit() - { - super.beatHit(); - - if (generatedMusic) - { - notes.sort(FlxSort.byY, (FlxG.save.data.downscroll ? FlxSort.ASCENDING : FlxSort.DESCENDING)); - } - - #if windows - if (executeModchart && luaModchart != null) - { - luaModchart.setVar('curBeat',curBeat); - luaModchart.executeState('beatHit',[curBeat]); - } - #end - - 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 - - // Commented out until a reason to bring this back arises in the future - /* if (SONG.notes[Math.floor(curStep / 16)].mustHitSection) - dad.dance(); */ - /* no because this is kinda dumb - if(dad.animation.curAnim.name.startsWith('sing')) - if(dad.animation.finished) - dad.dance(); - else - dad.dance(); - */ - } - // FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM); - wiggleShit.update(Conductor.crochet); - - // HARDCODING FOR MILF ZOOMS! - if (curSong.toLowerCase() == 'milf' && curBeat >= 168 && curBeat < 200 && camZooming && FlxG.camera.zoom < 1.35) - { - FlxG.camera.zoom += 0.015; - camHUD.zoom += 0.03; - } - - if (camZooming && FlxG.camera.zoom < 1.35 && curBeat % 4 == 0) - { - FlxG.camera.zoom += 0.015; - camHUD.zoom += 0.03; - } - - iconP1.setGraphicSize(Std.int(iconP1.width + 30)); - iconP2.setGraphicSize(Std.int(iconP2.width + 30)); - - iconP1.updateHitbox(); - iconP2.updateHitbox(); - - if (curBeat % gfSpeed == 0) - { - gf.dance(); - } - - if (!boyfriend.animation.curAnim.name.startsWith("sing")) - { - boyfriend.playAnim('idle'); - } - - if (!dad.animation.curAnim.name.startsWith("sing")) - { - dad.dance(); - } - - if (curBeat % 8 == 7 && curSong == 'Bopeebo') - { - boyfriend.playAnim('hey', true); - } - - if (curBeat % 16 == 15 && SONG.song == 'Tutorial' && dad.curCharacter == 'gf' && curBeat > 16 && curBeat < 48) - { - boyfriend.playAnim('hey', true); - dad.playAnim('cheer', true); - } - - switch (curStage) - { - case 'school': - if(FlxG.save.data.distractions){ - bgGirls.dance(); - } - - case 'mall': - if(FlxG.save.data.distractions){ - upperBoppers.animation.play('bop', true); - bottomBoppers.animation.play('bop', true); - santa.animation.play('idle', true); - } - - case 'limo': - if(FlxG.save.data.distractions){ - grpLimoDancers.forEach(function(dancer:BackgroundDancer) - { - dancer.dance(); - }); - - if (FlxG.random.bool(10) && fastCarCanDrive) - fastCarDrive(); - } - case "philly": - if(FlxG.save.data.distractions){ - if (!trainMoving) - trainCooldown += 1; - - if (curBeat % 4 == 0) - { - phillyCityLights.forEach(function(light:FlxSprite) - { - light.visible = false; - }); - - curLight = FlxG.random.int(0, phillyCityLights.length - 1); - - phillyCityLights.members[curLight].visible = true; - // phillyCityLights.members[curLight].alpha = 1; - } - - } - - if (curBeat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8) - { - if(FlxG.save.data.distractions){ - trainCooldown = FlxG.random.int(-4, 0); - trainStart(); - } - } - } - - if (isHalloween && FlxG.random.bool(10) && curBeat > lightningStrikeBeat + lightningOffset) - { - if(FlxG.save.data.distractions){ - lightningStrikeShit(); - } - } - } - - var curLight:Int = 0; -} +package; + +import haxe.Exception; +import openfl.geom.Matrix; +import openfl.display.BitmapData; +import openfl.utils.AssetType; +import lime.graphics.Image; +import flixel.graphics.FlxGraphic; +import openfl.utils.AssetManifest; +import openfl.utils.AssetLibrary; +import flixel.system.FlxAssets; + +import lime.app.Application; +import lime.media.AudioContext; +import lime.media.AudioManager; +import openfl.Lib; +import Section.SwagSection; +import Song.SwagSong; +import WiggleEffect.WiggleEffectType; +import flixel.FlxBasic; +import flixel.FlxCamera; +import flixel.FlxG; +import flixel.FlxGame; +import flixel.FlxObject; +import flixel.FlxSprite; +import flixel.FlxState; +import flixel.FlxSubState; +import flixel.addons.display.FlxGridOverlay; +import flixel.addons.effects.FlxTrail; +import flixel.addons.effects.FlxTrailArea; +import flixel.addons.effects.chainable.FlxEffectSprite; +import flixel.addons.effects.chainable.FlxWaveEffect; +import flixel.addons.transition.FlxTransitionableState; +import flixel.graphics.atlas.FlxAtlas; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.math.FlxMath; +import flixel.math.FlxPoint; +import flixel.math.FlxRect; +import flixel.system.FlxSound; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.ui.FlxBar; +import flixel.util.FlxCollision; +import flixel.util.FlxColor; +import flixel.util.FlxSort; +import flixel.util.FlxStringUtil; +import flixel.util.FlxTimer; +import haxe.Json; +import lime.utils.Assets; +import openfl.display.BlendMode; +import openfl.display.StageQuality; +import openfl.filters.ShaderFilter; + +#if windows +import Discord.DiscordClient; +#end +#if windows +import Sys; +import sys.FileSystem; +#end + +using StringTools; + +class PlayState extends MusicBeatState +{ + public static var instance:PlayState = null; + + public static var curStage:String = ''; + public static var SONG:SwagSong; + public static var isStoryMode:Bool = false; + public static var storyWeek:Int = 0; + public static var storyPlaylist:Array = []; + public static var storyDifficulty:Int = 1; + public static var weekSong:Int = 0; + public static var shits:Int = 0; + public static var bads:Int = 0; + public static var goods:Int = 0; + public static var sicks:Int = 0; + + public static var songPosBG:FlxSprite; + public static var songPosBar:FlxBar; + + public static var rep:Replay; + public static var loadRep:Bool = false; + + public static var noteBools:Array = [false, false, false, false]; + + var halloweenLevel:Bool = false; + + var songLength:Float = 0; + var kadeEngineWatermark:FlxText; + + #if windows + // Discord RPC variables + var storyDifficultyText:String = ""; + var iconRPC:String = ""; + var detailsText:String = ""; + var detailsPausedText:String = ""; + #end + + private var vocals:FlxSound; + + public static var dad:Character; + public static var gf:Character; + public static var boyfriend:Boyfriend; + + public var notes:FlxTypedGroup; + private var unspawnNotes:Array = []; + + public var strumLine:FlxSprite; + private var curSection:Int = 0; + + private var camFollow:FlxObject; + + private static var prevCamFollow:FlxObject; + + public static var strumLineNotes:FlxTypedGroup = null; + public static var playerStrums:FlxTypedGroup = null; + + private var camZooming:Bool = false; + private var curSong:String = ""; + + private var gfSpeed:Int = 1; + private var health:Float = 1; + private var combo:Int = 0; + public static var misses:Int = 0; + private 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; + + private var iconP1:HealthIcon; + private var iconP2:HealthIcon; + public var camHUD:FlxCamera; + private var camGame:FlxCamera; + + public static var offsetTesting:Bool = false; + + var notesHitArray:Array = []; + var currentFrames:Int = 0; + + public var dialogue:Array = ['dad:blah blah blah', 'bf:coolswag']; + + var halloweenBG:FlxSprite; + var isHalloween:Bool = false; + + var phillyCityLights:FlxTypedGroup; + var phillyTrain:FlxSprite; + var trainSound:FlxSound; + + var limo:FlxSprite; + var grpLimoDancers:FlxTypedGroup; + var fastCar:FlxSprite; + var songName:FlxText; + var upperBoppers:FlxSprite; + var bottomBoppers:FlxSprite; + var santa:FlxSprite; + + var fc:Bool = true; + + var bgGirls:BackgroundGirls; + var wiggleShit:WiggleEffect = new WiggleEffect(); + + var talking:Bool = true; + var songScore:Int = 0; + var songScoreDef:Int = 0; + var scoreTxt:FlxText; + var replayTxt:FlxText; + + public static var campaignScore:Int = 0; + + var defaultCamZoom:Float = 1.05; + + public static var daPixelZoom:Float = 6; + + public static var theFunne:Bool = true; + var funneEffect:FlxSprite; + var inCutscene:Bool = false; + public static var repPresses:Int = 0; + public static var repReleases:Int = 0; + + public static var timeCurrently:Float = 0; + public static var timeCurrentlyR:Float = 0; + + // Will fire once to prevent debug spam messages and broken animations + private var triggeredAlready:Bool = false; + + // Will decide if she's even allowed to headbang at all depending on the song + private var allowedToHeadbang:Bool = false; + // Per song additive offset + public static var songOffset:Float = 0; + // BotPlay text + private var botPlayState:FlxText; + // Replay shit + private var saveNotes:Array = []; + + private var executeModchart = false; + + // API stuff + + public function addObject(object:FlxBasic) { add(object); } + public function removeObject(object:FlxBasic) { remove(object); } + + + override public function create() + { + instance = this; + + if (FlxG.save.data.fpsCap > 290) + (cast (Lib.current.getChildAt(0), Main)).setFPSCap(800); + + if (FlxG.sound.music != null) + FlxG.sound.music.stop(); + + sicks = 0; + bads = 0; + shits = 0; + goods = 0; + + misses = 0; + + repPresses = 0; + repReleases = 0; + + #if windows + executeModchart = FileSystem.exists(Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart")); + #end + #if !cpp + executeModchart = false; // FORCE disable for non cpp targets + #end + + trace('Mod chart: ' + executeModchart + " - " + Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart")); + + #if windows + // Making difficulty text for Discord Rich Presence. + switch (storyDifficulty) + { + case 0: + storyDifficultyText = "Easy"; + case 1: + storyDifficultyText = "Normal"; + case 2: + storyDifficultyText = "Hard"; + } + + iconRPC = SONG.player2; + + // To avoid having duplicate images in Discord assets + switch (iconRPC) + { + case 'senpai-angry': + iconRPC = 'senpai'; + case 'monster-christmas': + iconRPC = 'monster'; + case 'mom-car': + iconRPC = 'mom'; + } + + // String that contains the mode defined here so it isn't necessary to call changePresence for each mode + if (isStoryMode) + { + detailsText = "Story Mode: Week " + storyWeek; + } + else + { + detailsText = "Freeplay"; + } + + // String for when the game is paused + detailsPausedText = "Paused - " + detailsText; + + // Updating Discord Rich Presence. + DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); + #end + + + // var gameCam:FlxCamera = FlxG.camera; + camGame = new FlxCamera(); + camHUD = new FlxCamera(); + camHUD.bgColor.alpha = 0; + + FlxG.cameras.reset(camGame); + FlxG.cameras.add(camHUD); + + FlxCamera.defaultCameras = [camGame]; + + persistentUpdate = true; + persistentDraw = true; + + if (SONG == null) + SONG = Song.loadFromJson('tutorial'); + + Conductor.mapBPMChanges(SONG); + Conductor.changeBPM(SONG.bpm); + + trace('INFORMATION ABOUT WHAT U PLAYIN WIT:\nFRAMES: ' + Conductor.safeFrames + '\nZONE: ' + Conductor.safeZoneOffset + '\nTS: ' + Conductor.timeScale + '\nBotPlay : ' + FlxG.save.data.botplay); + + + + //dialogue shit + switch (SONG.song.toLowerCase()) + { + case 'tutorial': + dialogue = ["Hey you're pretty cute.", 'Use the arrow keys to keep up \nwith me singing.']; + case 'bopeebo': + dialogue = [ + 'HEY!', + "You think you can just sing\nwith my daughter like that?", + "If you want to date her...", + "You're going to have to go \nthrough ME first!" + ]; + case 'fresh': + dialogue = ["Not too shabby boy.", ""]; + case 'dad battle': + dialogue = [ + "gah you think you're hot stuff?", + "If you can beat me here...", + "Only then I will even CONSIDER letting you\ndate my daughter!" + ]; + case 'senpai': + dialogue = CoolUtil.coolTextFile(Paths.txt('senpai/senpaiDialogue')); + case 'roses': + dialogue = CoolUtil.coolTextFile(Paths.txt('roses/rosesDialogue')); + case 'thorns': + dialogue = CoolUtil.coolTextFile(Paths.txt('thorns/thornsDialogue')); + } + + switch(SONG.stage) + { + case 'halloween': + { + curStage = 'spooky'; + halloweenLevel = true; + + var hallowTex = Paths.getSparrowAtlas('halloween_bg','week2'); + + halloweenBG = new FlxSprite(-200, -100); + halloweenBG.frames = hallowTex; + halloweenBG.animation.addByPrefix('idle', 'halloweem bg0'); + halloweenBG.animation.addByPrefix('lightning', 'halloweem bg lightning strike', 24, false); + halloweenBG.animation.play('idle'); + halloweenBG.antialiasing = true; + add(halloweenBG); + + isHalloween = true; + } + case 'philly': + { + curStage = 'philly'; + + var bg:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image('philly/sky', 'week3')); + bg.scrollFactor.set(0.1, 0.1); + add(bg); + + var city:FlxSprite = new FlxSprite(-10).loadGraphic(Paths.image('philly/city', 'week3')); + city.scrollFactor.set(0.3, 0.3); + city.setGraphicSize(Std.int(city.width * 0.85)); + city.updateHitbox(); + add(city); + + phillyCityLights = new FlxTypedGroup(); + if(FlxG.save.data.distractions){ + add(phillyCityLights); + } + + for (i in 0...5) + { + var light:FlxSprite = new FlxSprite(city.x).loadGraphic(Paths.image('philly/win' + i, 'week3')); + light.scrollFactor.set(0.3, 0.3); + light.visible = false; + light.setGraphicSize(Std.int(light.width * 0.85)); + light.updateHitbox(); + light.antialiasing = true; + phillyCityLights.add(light); + } + + var streetBehind:FlxSprite = new FlxSprite(-40, 50).loadGraphic(Paths.image('philly/behindTrain','week3')); + add(streetBehind); + + phillyTrain = new FlxSprite(2000, 360).loadGraphic(Paths.image('philly/train','week3')); + if(FlxG.save.data.distractions){ + add(phillyTrain); + } + + trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes','week3')); + FlxG.sound.list.add(trainSound); + + // var cityLights:FlxSprite = new FlxSprite().loadGraphic(AssetPaths.win0.png); + + var street:FlxSprite = new FlxSprite(-40, streetBehind.y).loadGraphic(Paths.image('philly/street','week3')); + add(street); + } + case 'limo': + { + curStage = 'limo'; + defaultCamZoom = 0.90; + + var skyBG:FlxSprite = new FlxSprite(-120, -50).loadGraphic(Paths.image('limo/limoSunset','week4')); + skyBG.scrollFactor.set(0.1, 0.1); + add(skyBG); + + var bgLimo:FlxSprite = new FlxSprite(-200, 480); + bgLimo.frames = Paths.getSparrowAtlas('limo/bgLimo','week4'); + bgLimo.animation.addByPrefix('drive', "background limo pink", 24); + bgLimo.animation.play('drive'); + bgLimo.scrollFactor.set(0.4, 0.4); + add(bgLimo); + if(FlxG.save.data.distractions){ + grpLimoDancers = new FlxTypedGroup(); + add(grpLimoDancers); + + for (i in 0...5) + { + var dancer:BackgroundDancer = new BackgroundDancer((370 * i) + 130, bgLimo.y - 400); + dancer.scrollFactor.set(0.4, 0.4); + grpLimoDancers.add(dancer); + } + } + + var overlayShit:FlxSprite = new FlxSprite(-500, -600).loadGraphic(Paths.image('limo/limoOverlay','week4')); + overlayShit.alpha = 0.5; + // add(overlayShit); + + // var shaderBullshit = new BlendModeEffect(new OverlayShader(), FlxColor.RED); + + // FlxG.camera.setFilters([new ShaderFilter(cast shaderBullshit.shader)]); + + // overlayShit.shader = shaderBullshit; + + var limoTex = Paths.getSparrowAtlas('limo/limoDrive','week4'); + + limo = new FlxSprite(-120, 550); + limo.frames = limoTex; + limo.animation.addByPrefix('drive', "Limo stage", 24); + limo.animation.play('drive'); + limo.antialiasing = true; + + fastCar = new FlxSprite(-300, 160).loadGraphic(Paths.image('limo/fastCarLol','week4')); + // add(limo); + } + case 'mall': + { + curStage = 'mall'; + + defaultCamZoom = 0.80; + + var bg:FlxSprite = new FlxSprite(-1000, -500).loadGraphic(Paths.image('christmas/bgWalls','week5')); + bg.antialiasing = true; + bg.scrollFactor.set(0.2, 0.2); + bg.active = false; + bg.setGraphicSize(Std.int(bg.width * 0.8)); + bg.updateHitbox(); + add(bg); + + upperBoppers = new FlxSprite(-240, -90); + upperBoppers.frames = Paths.getSparrowAtlas('christmas/upperBop','week5'); + upperBoppers.animation.addByPrefix('bop', "Upper Crowd Bob", 24, false); + upperBoppers.antialiasing = true; + upperBoppers.scrollFactor.set(0.33, 0.33); + upperBoppers.setGraphicSize(Std.int(upperBoppers.width * 0.85)); + upperBoppers.updateHitbox(); + if(FlxG.save.data.distractions){ + add(upperBoppers); + } + + + var bgEscalator:FlxSprite = new FlxSprite(-1100, -600).loadGraphic(Paths.image('christmas/bgEscalator','week5')); + bgEscalator.antialiasing = true; + bgEscalator.scrollFactor.set(0.3, 0.3); + bgEscalator.active = false; + bgEscalator.setGraphicSize(Std.int(bgEscalator.width * 0.9)); + bgEscalator.updateHitbox(); + add(bgEscalator); + + var tree:FlxSprite = new FlxSprite(370, -250).loadGraphic(Paths.image('christmas/christmasTree','week5')); + tree.antialiasing = true; + tree.scrollFactor.set(0.40, 0.40); + add(tree); + + bottomBoppers = new FlxSprite(-300, 140); + bottomBoppers.frames = Paths.getSparrowAtlas('christmas/bottomBop','week5'); + bottomBoppers.animation.addByPrefix('bop', 'Bottom Level Boppers', 24, false); + bottomBoppers.antialiasing = true; + bottomBoppers.scrollFactor.set(0.9, 0.9); + bottomBoppers.setGraphicSize(Std.int(bottomBoppers.width * 1)); + bottomBoppers.updateHitbox(); + if(FlxG.save.data.distractions){ + add(bottomBoppers); + } + + + var fgSnow:FlxSprite = new FlxSprite(-600, 700).loadGraphic(Paths.image('christmas/fgSnow','week5')); + fgSnow.active = false; + fgSnow.antialiasing = true; + add(fgSnow); + + santa = new FlxSprite(-840, 150); + santa.frames = Paths.getSparrowAtlas('christmas/santa','week5'); + santa.animation.addByPrefix('idle', 'santa idle in fear', 24, false); + santa.antialiasing = true; + if(FlxG.save.data.distractions){ + add(santa); + } + } + case 'mallEvil': + { + curStage = 'mallEvil'; + var bg:FlxSprite = new FlxSprite(-400, -500).loadGraphic(Paths.image('christmas/evilBG','week5')); + bg.antialiasing = true; + bg.scrollFactor.set(0.2, 0.2); + bg.active = false; + bg.setGraphicSize(Std.int(bg.width * 0.8)); + bg.updateHitbox(); + add(bg); + + var evilTree:FlxSprite = new FlxSprite(300, -300).loadGraphic(Paths.image('christmas/evilTree','week5')); + evilTree.antialiasing = true; + evilTree.scrollFactor.set(0.2, 0.2); + add(evilTree); + + var evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow",'week5')); + evilSnow.antialiasing = true; + add(evilSnow); + } + case 'school': + { + curStage = 'school'; + + // defaultCamZoom = 0.9; + + var bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky','week6')); + bgSky.scrollFactor.set(0.1, 0.1); + add(bgSky); + + var repositionShit = -200; + + var bgSchool:FlxSprite = new FlxSprite(repositionShit, 0).loadGraphic(Paths.image('weeb/weebSchool','week6')); + bgSchool.scrollFactor.set(0.6, 0.90); + add(bgSchool); + + var bgStreet:FlxSprite = new FlxSprite(repositionShit).loadGraphic(Paths.image('weeb/weebStreet','week6')); + bgStreet.scrollFactor.set(0.95, 0.95); + add(bgStreet); + + var fgTrees:FlxSprite = new FlxSprite(repositionShit + 170, 130).loadGraphic(Paths.image('weeb/weebTreesBack','week6')); + fgTrees.scrollFactor.set(0.9, 0.9); + add(fgTrees); + + var bgTrees:FlxSprite = new FlxSprite(repositionShit - 380, -800); + var treetex = Paths.getPackerAtlas('weeb/weebTrees','week6'); + bgTrees.frames = treetex; + bgTrees.animation.add('treeLoop', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 12); + bgTrees.animation.play('treeLoop'); + bgTrees.scrollFactor.set(0.85, 0.85); + add(bgTrees); + + var treeLeaves:FlxSprite = new FlxSprite(repositionShit, -40); + treeLeaves.frames = Paths.getSparrowAtlas('weeb/petals','week6'); + treeLeaves.animation.addByPrefix('leaves', 'PETALS ALL', 24, true); + treeLeaves.animation.play('leaves'); + treeLeaves.scrollFactor.set(0.85, 0.85); + add(treeLeaves); + + var widShit = Std.int(bgSky.width * 6); + + bgSky.setGraphicSize(widShit); + bgSchool.setGraphicSize(widShit); + bgStreet.setGraphicSize(widShit); + bgTrees.setGraphicSize(Std.int(widShit * 1.4)); + fgTrees.setGraphicSize(Std.int(widShit * 0.8)); + treeLeaves.setGraphicSize(widShit); + + fgTrees.updateHitbox(); + bgSky.updateHitbox(); + bgSchool.updateHitbox(); + bgStreet.updateHitbox(); + bgTrees.updateHitbox(); + treeLeaves.updateHitbox(); + + bgGirls = new BackgroundGirls(-100, 190); + bgGirls.scrollFactor.set(0.9, 0.9); + + if (SONG.song.toLowerCase() == 'roses') + { + if(FlxG.save.data.distractions){ + bgGirls.getScared(); + } + } + + bgGirls.setGraphicSize(Std.int(bgGirls.width * daPixelZoom)); + bgGirls.updateHitbox(); + if(FlxG.save.data.distractions){ + add(bgGirls); + } + } + case 'schoolEvil': + { + curStage = 'schoolEvil'; + + var waveEffectBG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 3, 2); + var waveEffectFG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 5, 2); + + var posX = 400; + var posY = 200; + + var bg:FlxSprite = new FlxSprite(posX, posY); + bg.frames = Paths.getSparrowAtlas('weeb/animatedEvilSchool','week6'); + bg.animation.addByPrefix('idle', 'background 2', 24); + bg.animation.play('idle'); + bg.scrollFactor.set(0.8, 0.9); + bg.scale.set(6, 6); + add(bg); + + /* + var bg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolBG')); + bg.scale.set(6, 6); + // bg.setGraphicSize(Std.int(bg.width * 6)); + // bg.updateHitbox(); + add(bg); + var fg:FlxSprite = new FlxSprite(posX, posY).loadGraphic(Paths.image('weeb/evilSchoolFG')); + fg.scale.set(6, 6); + // fg.setGraphicSize(Std.int(fg.width * 6)); + // fg.updateHitbox(); + add(fg); + wiggleShit.effectType = WiggleEffectType.DREAMY; + wiggleShit.waveAmplitude = 0.01; + wiggleShit.waveFrequency = 60; + wiggleShit.waveSpeed = 0.8; + */ + + // bg.shader = wiggleShit.shader; + // fg.shader = wiggleShit.shader; + + /* + var waveSprite = new FlxEffectSprite(bg, [waveEffectBG]); + var waveSpriteFG = new FlxEffectSprite(fg, [waveEffectFG]); + // Using scale since setGraphicSize() doesnt work??? + waveSprite.scale.set(6, 6); + waveSpriteFG.scale.set(6, 6); + waveSprite.setPosition(posX, posY); + waveSpriteFG.setPosition(posX, posY); + waveSprite.scrollFactor.set(0.7, 0.8); + waveSpriteFG.scrollFactor.set(0.9, 0.8); + // waveSprite.setGraphicSize(Std.int(waveSprite.width * 6)); + // waveSprite.updateHitbox(); + // waveSpriteFG.setGraphicSize(Std.int(fg.width * 6)); + // waveSpriteFG.updateHitbox(); + add(waveSprite); + add(waveSpriteFG); + */ + } + case 'stage': + { + defaultCamZoom = 0.9; + curStage = 'stage'; + var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback')); + bg.antialiasing = true; + bg.scrollFactor.set(0.9, 0.9); + bg.active = false; + add(bg); + + var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront')); + stageFront.setGraphicSize(Std.int(stageFront.width * 1.1)); + stageFront.updateHitbox(); + stageFront.antialiasing = true; + stageFront.scrollFactor.set(0.9, 0.9); + stageFront.active = false; + add(stageFront); + + var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains')); + stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9)); + stageCurtains.updateHitbox(); + stageCurtains.antialiasing = true; + stageCurtains.scrollFactor.set(1.3, 1.3); + stageCurtains.active = false; + + add(stageCurtains); + } + default: + { + defaultCamZoom = 0.9; + curStage = 'stage'; + var bg:FlxSprite = new FlxSprite(-600, -200).loadGraphic(Paths.image('stageback')); + bg.antialiasing = true; + bg.scrollFactor.set(0.9, 0.9); + bg.active = false; + add(bg); + + var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront')); + stageFront.setGraphicSize(Std.int(stageFront.width * 1.1)); + stageFront.updateHitbox(); + stageFront.antialiasing = true; + stageFront.scrollFactor.set(0.9, 0.9); + stageFront.active = false; + add(stageFront); + + var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains')); + stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9)); + stageCurtains.updateHitbox(); + stageCurtains.antialiasing = true; + stageCurtains.scrollFactor.set(1.3, 1.3); + stageCurtains.active = false; + + add(stageCurtains); + } + } + var gfVersion:String = 'gf'; + + switch (SONG.gfVersion) + { + case 'gf-car': + gfVersion = 'gf-car'; + case 'gf-christmas': + gfVersion = 'gf-christmas'; + case 'gf-pixel': + gfVersion = 'gf-pixel'; + case 'gf': + gfVersion = 'gf'; + default: + gfVersion = 'gf'; + } + + gf = new Character(400, 130, gfVersion); + gf.scrollFactor.set(0.95, 0.95); + + dad = new Character(100, 100, SONG.player2); + + var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x, dad.getGraphicMidpoint().y); + + switch (SONG.player2) + { + case 'gf': + dad.setPosition(gf.x, gf.y); + gf.visible = false; + if (isStoryMode) + { + camPos.x += 600; + tweenCamIn(); + } + + case "spooky": + dad.y += 200; + case "monster": + dad.y += 100; + case 'monster-christmas': + dad.y += 130; + case 'dad': + camPos.x += 400; + case 'pico': + camPos.x += 600; + dad.y += 300; + case 'parents-christmas': + dad.x -= 500; + case 'senpai': + dad.x += 150; + dad.y += 360; + camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); + case 'senpai-angry': + dad.x += 150; + dad.y += 360; + camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); + case 'spirit': + dad.x -= 150; + dad.y += 100; + camPos.set(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y); + } + + + + boyfriend = new Boyfriend(770, 450, SONG.player1); + + // REPOSITIONING PER STAGE + switch (curStage) + { + case 'limo': + boyfriend.y -= 220; + boyfriend.x += 260; + if(FlxG.save.data.distractions){ + resetFastCar(); + add(fastCar); + } + + case 'mall': + boyfriend.x += 200; + + case 'mallEvil': + boyfriend.x += 320; + dad.y -= 80; + case 'school': + boyfriend.x += 200; + boyfriend.y += 220; + gf.x += 180; + gf.y += 300; + case 'schoolEvil': + if(FlxG.save.data.distractions){ + // trailArea.scrollFactor.set(); + var evilTrail = new FlxTrail(dad, null, 4, 24, 0.3, 0.069); + // evilTrail.changeValuesEnabled(false, false, false, false); + // evilTrail.changeGraphic() + add(evilTrail); + // evilTrail.scrollFactor.set(1.1, 1.1); + } + + + boyfriend.x += 200; + boyfriend.y += 220; + gf.x += 180; + gf.y += 300; + } + + add(gf); + + // Shitty layering but whatev it works LOL + if (curStage == 'limo') + add(limo); + + add(dad); + add(boyfriend); + if (loadRep) + { + FlxG.watch.addQuick('rep rpesses',repPresses); + FlxG.watch.addQuick('rep releases',repReleases); + + FlxG.save.data.botplay = true; + FlxG.save.data.scrollSpeed = rep.replay.noteSpeed; + FlxG.save.data.downscroll = rep.replay.isDownscroll; + // FlxG.watch.addQuick('Queued',inputsQueued); + } + + var doof:DialogueBox = new DialogueBox(false, dialogue); + // doof.x += 70; + // doof.y = FlxG.height * 0.5; + doof.scrollFactor.set(); + doof.finishThing = startCountdown; + + Conductor.songPosition = -5000; + + strumLine = new FlxSprite(0, 50).makeGraphic(FlxG.width, 10); + strumLine.scrollFactor.set(); + + if (FlxG.save.data.downscroll) + strumLine.y = FlxG.height - 165; + + strumLineNotes = new FlxTypedGroup(); + add(strumLineNotes); + + playerStrums = new FlxTypedGroup(); + + // startCountdown(); + + generateSong(SONG.song); + + // add(strumLine); + + camFollow = new FlxObject(0, 0, 1, 1); + + camFollow.setPosition(camPos.x, camPos.y); + + if (prevCamFollow != null) + { + camFollow = prevCamFollow; + prevCamFollow = null; + } + + add(camFollow); + + FlxG.camera.follow(camFollow, LOCKON, 0.04 * (30 / (cast (Lib.current.getChildAt(0), Main)).getFPS())); + // FlxG.camera.setScrollBounds(0, FlxG.width, 0, FlxG.height); + FlxG.camera.zoom = defaultCamZoom; + FlxG.camera.focusOn(camFollow.getPosition()); + + FlxG.worldBounds.set(0, 0, FlxG.width, FlxG.height); + + FlxG.fixedTimestep = false; + + if (FlxG.save.data.songPosition) // I dont wanna talk about this code :( + { + songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar')); + if (FlxG.save.data.downscroll) + 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 (FlxG.save.data.downscroll) + 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 (FlxG.save.data.downscroll) + healthBarBG.y = 50; + healthBarBG.screenCenter(X); + healthBarBG.scrollFactor.set(); + add(healthBarBG); + + healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this, + 'health', 0, 2); + healthBar.scrollFactor.set(); + healthBar.createFilledBar(0xFFFF0000, 0xFF66FF33); + // healthBar + add(healthBar); + + // Add Kade Engine watermark + kadeEngineWatermark = new FlxText(4,healthBarBG.y + 50,0,SONG.song + " " + (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.scrollFactor.set(); + add(kadeEngineWatermark); + + if (FlxG.save.data.downscroll) + kadeEngineWatermark.y = FlxG.height * 0.9 + 45; + + scoreTxt = new FlxText(FlxG.width / 2 - 235, healthBarBG.y + 50, 0, "", 20); + if (!FlxG.save.data.accuracyDisplay) + scoreTxt.x = healthBarBG.x + healthBarBG.width / 2; + scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); + scoreTxt.scrollFactor.set(); + if (offsetTesting) + scoreTxt.x += 300; + if(FlxG.save.data.botplay) scoreTxt.x = FlxG.width / 2 - 20; + add(scoreTxt); + + replayTxt = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (FlxG.save.data.downscroll ? 100 : -100), 0, "REPLAY", 20); + replayTxt.setFormat(Paths.font("vcr.ttf"), 42, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); + replayTxt.scrollFactor.set(); + if (loadRep) + { + add(replayTxt); + } + // Literally copy-paste of the above, fu + botPlayState = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (FlxG.save.data.downscroll ? 100 : -100), 0, "BOTPLAY", 20); + botPlayState.setFormat(Paths.font("vcr.ttf"), 42, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); + botPlayState.scrollFactor.set(); + + if(FlxG.save.data.botplay && !loadRep) add(botPlayState); + + iconP1 = new HealthIcon(SONG.player1, true); + iconP1.y = healthBar.y - (iconP1.height / 2); + add(iconP1); + + iconP2 = new HealthIcon(SONG.player2, false); + iconP2.y = healthBar.y - (iconP2.height / 2); + add(iconP2); + + strumLineNotes.cameras = [camHUD]; + notes.cameras = [camHUD]; + healthBar.cameras = [camHUD]; + healthBarBG.cameras = [camHUD]; + iconP1.cameras = [camHUD]; + iconP2.cameras = [camHUD]; + scoreTxt.cameras = [camHUD]; + doof.cameras = [camHUD]; + if (FlxG.save.data.songPosition) + { + songPosBG.cameras = [camHUD]; + songPosBar.cameras = [camHUD]; + } + kadeEngineWatermark.cameras = [camHUD]; + if (loadRep) + replayTxt.cameras = [camHUD]; + + // if (SONG.song == 'South') + // FlxG.camera.alpha = 0.7; + // UI_camera.zoom = 1; + + // cameras = [FlxG.cameras.list[1]]; + startingSong = true; + + if (isStoryMode) + { + switch (curSong.toLowerCase()) + { + case "winter-horrorland": + var blackScreen:FlxSprite = new FlxSprite(0, 0).makeGraphic(Std.int(FlxG.width * 2), Std.int(FlxG.height * 2), FlxColor.BLACK); + add(blackScreen); + blackScreen.scrollFactor.set(); + camHUD.visible = false; + + new FlxTimer().start(0.1, function(tmr:FlxTimer) + { + remove(blackScreen); + FlxG.sound.play(Paths.sound('Lights_Turn_On')); + camFollow.y = -2050; + camFollow.x += 200; + FlxG.camera.focusOn(camFollow.getPosition()); + FlxG.camera.zoom = 1.5; + + new FlxTimer().start(0.8, function(tmr:FlxTimer) + { + camHUD.visible = true; + remove(blackScreen); + FlxTween.tween(FlxG.camera, {zoom: defaultCamZoom}, 2.5, { + ease: FlxEase.quadInOut, + onComplete: function(twn:FlxTween) + { + startCountdown(); + } + }); + }); + }); + case 'senpai': + schoolIntro(doof); + case 'roses': + FlxG.sound.play(Paths.sound('ANGRY')); + schoolIntro(doof); + case 'thorns': + schoolIntro(doof); + default: + startCountdown(); + } + } + else + { + switch (curSong.toLowerCase()) + { + default: + startCountdown(); + } + } + + if (!loadRep) + rep = new Replay("na"); + + super.create(); + } + + function schoolIntro(?dialogueBox:DialogueBox):Void + { + var black:FlxSprite = new FlxSprite(-100, -100).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK); + black.scrollFactor.set(); + add(black); + + var red:FlxSprite = new FlxSprite(-100, -100).makeGraphic(FlxG.width * 2, FlxG.height * 2, 0xFFff1b31); + red.scrollFactor.set(); + + var senpaiEvil:FlxSprite = new FlxSprite(); + senpaiEvil.frames = Paths.getSparrowAtlas('weeb/senpaiCrazy'); + senpaiEvil.animation.addByPrefix('idle', 'Senpai Pre Explosion', 24, false); + senpaiEvil.setGraphicSize(Std.int(senpaiEvil.width * 6)); + senpaiEvil.scrollFactor.set(); + senpaiEvil.updateHitbox(); + senpaiEvil.screenCenter(); + + if (SONG.song.toLowerCase() == 'roses' || SONG.song.toLowerCase() == 'thorns') + { + remove(black); + + if (SONG.song.toLowerCase() == 'thorns') + { + add(red); + } + } + + new FlxTimer().start(0.3, function(tmr:FlxTimer) + { + black.alpha -= 0.15; + + if (black.alpha > 0) + { + tmr.reset(0.3); + } + else + { + if (dialogueBox != null) + { + inCutscene = true; + + if (SONG.song.toLowerCase() == 'thorns') + { + add(senpaiEvil); + senpaiEvil.alpha = 0; + new FlxTimer().start(0.3, function(swagTimer:FlxTimer) + { + senpaiEvil.alpha += 0.15; + if (senpaiEvil.alpha < 1) + { + swagTimer.reset(); + } + else + { + senpaiEvil.animation.play('idle'); + FlxG.sound.play(Paths.sound('Senpai_Dies'), 1, false, null, true, function() + { + remove(senpaiEvil); + remove(red); + FlxG.camera.fade(FlxColor.WHITE, 0.01, true, function() + { + add(dialogueBox); + }, true); + }); + new FlxTimer().start(3.2, function(deadTime:FlxTimer) + { + FlxG.camera.fade(FlxColor.WHITE, 1.6, false); + }); + } + }); + } + else + { + add(dialogueBox); + } + } + else + startCountdown(); + + remove(black); + } + }); + } + + var startTimer:FlxTimer; + var perfectMode:Bool = false; + + var luaWiggles:Array = []; + + #if windows + public static var luaModchart:ModchartState = null; + #end + + function startCountdown():Void + { + inCutscene = false; + + generateStaticArrows(0); + generateStaticArrows(1); + + + #if windows + if (executeModchart) + { + luaModchart = ModchartState.createModchartState(); + luaModchart.executeState('start',[PlayState.SONG.song]); + } + #end + + talking = false; + startedCountdown = true; + Conductor.songPosition = 0; + Conductor.songPosition -= Conductor.crochet * 5; + + var swagCounter:Int = 0; + + startTimer = new FlxTimer().start(Conductor.crochet / 1000, function(tmr:FlxTimer) + { + dad.dance(); + gf.dance(); + boyfriend.playAnim('idle'); + + var introAssets:Map> = new Map>(); + introAssets.set('default', ['ready', "set", "go"]); + introAssets.set('school', [ + 'weeb/pixelUI/ready-pixel', + 'weeb/pixelUI/set-pixel', + 'weeb/pixelUI/date-pixel' + ]); + introAssets.set('schoolEvil', [ + 'weeb/pixelUI/ready-pixel', + 'weeb/pixelUI/set-pixel', + 'weeb/pixelUI/date-pixel' + ]); + + var introAlts:Array = introAssets.get('default'); + var altSuffix:String = ""; + + for (value in introAssets.keys()) + { + if (value == curStage) + { + introAlts = introAssets.get(value); + altSuffix = '-pixel'; + } + } + + switch (swagCounter) + + { + case 0: + FlxG.sound.play(Paths.sound('intro3' + altSuffix), 0.6); + case 1: + var ready:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[0])); + ready.scrollFactor.set(); + ready.updateHitbox(); + + if (curStage.startsWith('school')) + ready.setGraphicSize(Std.int(ready.width * daPixelZoom)); + + ready.screenCenter(); + add(ready); + FlxTween.tween(ready, {y: ready.y += 100, alpha: 0}, Conductor.crochet / 1000, { + ease: FlxEase.cubeInOut, + onComplete: function(twn:FlxTween) + { + ready.destroy(); + } + }); + FlxG.sound.play(Paths.sound('intro2' + altSuffix), 0.6); + case 2: + var set:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[1])); + set.scrollFactor.set(); + + if (curStage.startsWith('school')) + set.setGraphicSize(Std.int(set.width * daPixelZoom)); + + set.screenCenter(); + add(set); + FlxTween.tween(set, {y: set.y += 100, alpha: 0}, Conductor.crochet / 1000, { + ease: FlxEase.cubeInOut, + onComplete: function(twn:FlxTween) + { + set.destroy(); + } + }); + FlxG.sound.play(Paths.sound('intro1' + altSuffix), 0.6); + case 3: + var go:FlxSprite = new FlxSprite().loadGraphic(Paths.image(introAlts[2])); + go.scrollFactor.set(); + + if (curStage.startsWith('school')) + go.setGraphicSize(Std.int(go.width * daPixelZoom)); + + go.updateHitbox(); + + go.screenCenter(); + add(go); + FlxTween.tween(go, {y: go.y += 100, alpha: 0}, Conductor.crochet / 1000, { + ease: FlxEase.cubeInOut, + onComplete: function(twn:FlxTween) + { + go.destroy(); + } + }); + FlxG.sound.play(Paths.sound('introGo' + altSuffix), 0.6); + case 4: + } + + swagCounter += 1; + // generateSong('fresh'); + }, 5); + } + + var previousFrameTime:Int = 0; + var lastReportedPlayheadPosition:Int = 0; + var songTime:Float = 0; + + + var songStarted = false; + + function startSong():Void + { + startingSong = false; + songStarted = true; + previousFrameTime = FlxG.game.ticks; + lastReportedPlayheadPosition = 0; + + if (!paused) + { + FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); + } + + FlxG.sound.music.onComplete = endSong; + vocals.play(); + + // Song duration in a float, useful for the time left feature + songLength = FlxG.sound.music.length; + + if (FlxG.save.data.songPosition) + { + remove(songPosBG); + remove(songPosBar); + remove(songName); + + songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar')); + if (FlxG.save.data.downscroll) + songPosBG.y = FlxG.height * 0.9 + 45; + songPosBG.screenCenter(X); + songPosBG.scrollFactor.set(); + add(songPosBG); + + songPosBar = new FlxBar(songPosBG.x + 4, songPosBG.y + 4, LEFT_TO_RIGHT, Std.int(songPosBG.width - 8), Std.int(songPosBG.height - 8), this, + 'songPositionBar', 0, songLength - 1000); + songPosBar.numDivisions = 1000; + songPosBar.scrollFactor.set(); + songPosBar.createFilledBar(FlxColor.GRAY, FlxColor.LIME); + add(songPosBar); + + var songName = new FlxText(songPosBG.x + (songPosBG.width / 2) - 20,songPosBG.y,0,SONG.song, 16); + if (FlxG.save.data.downscroll) + songName.y -= 3; + songName.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); + songName.scrollFactor.set(); + add(songName); + + songPosBG.cameras = [camHUD]; + songPosBar.cameras = [camHUD]; + songName.cameras = [camHUD]; + } + + // Song check real quick + switch(curSong) + { + case 'Bopeebo' | 'Philly' | 'Blammed' | 'Cocoa' | 'Eggnog': allowedToHeadbang = true; + default: allowedToHeadbang = false; + } + + #if windows + // Updating Discord Rich Presence (with Time Left) + DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); + #end + } + + var debugNum:Int = 0; + + private function generateSong(dataPath:String):Void + { + // FlxG.log.add(ChartParser.parse()); + + var songData = SONG; + Conductor.changeBPM(songData.bpm); + + curSong = songData.song; + + if (SONG.needsVoices) + vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song)); + else + vocals = new FlxSound(); + + FlxG.sound.list.add(vocals); + + notes = new FlxTypedGroup(); + add(notes); + + var noteData:Array; + + // NEW SHIT + noteData = songData.notes; + + var playerCounter:Int = 0; + + // Per song offset check + #if windows + var songPath = 'assets/data/' + PlayState.SONG.song.toLowerCase() + '/'; + for(file in sys.FileSystem.readDirectory(songPath)) + { + var path = haxe.io.Path.join([songPath, file]); + if(!sys.FileSystem.isDirectory(path)) + { + if(path.endsWith('.offset')) + { + trace('Found offset file: ' + path); + songOffset = Std.parseFloat(file.substring(0, file.indexOf('.off'))); + break; + }else { + trace('Offset file not found. Creating one @: ' + songPath); + sys.io.File.saveContent(songPath + songOffset + '.offset', ''); + } + } + } + #end + var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped + for (section in noteData) + { + var coolSection:Int = Std.int(section.lengthInSteps / 4); + + for (songNotes in section.sectionNotes) + { + var daStrumTime:Float = songNotes[0] + FlxG.save.data.offset + songOffset; + if (daStrumTime < 0) + daStrumTime = 0; + var daNoteData:Int = Std.int(songNotes[1] % 4); + + var gottaHitNote:Bool = section.mustHitSection; + + if (songNotes[1] > 3) + { + gottaHitNote = !section.mustHitSection; + } + + var oldNote:Note; + if (unspawnNotes.length > 0) + oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)]; + else + oldNote = null; + + var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote); + swagNote.sustainLength = songNotes[2]; + swagNote.scrollFactor.set(0, 0); + + var susLength:Float = swagNote.sustainLength; + + susLength = susLength / Conductor.stepCrochet; + unspawnNotes.push(swagNote); + + for (susNote in 0...Math.floor(susLength)) + { + oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)]; + + var sustainNote:Note = new Note(daStrumTime + (Conductor.stepCrochet * susNote) + Conductor.stepCrochet, daNoteData, oldNote, true); + sustainNote.scrollFactor.set(); + unspawnNotes.push(sustainNote); + + sustainNote.mustPress = gottaHitNote; + + if (sustainNote.mustPress) + { + sustainNote.x += FlxG.width / 2; // general offset + } + } + + swagNote.mustPress = gottaHitNote; + + if (swagNote.mustPress) + { + swagNote.x += FlxG.width / 2; // general offset + } + else + { + } + } + daBeats += 1; + } + + // trace(unspawnNotes.length); + // playerCounter += 1; + + unspawnNotes.sort(sortByShit); + + generatedMusic = true; + } + + function sortByShit(Obj1:Note, Obj2:Note):Int + { + return FlxSort.byValues(FlxSort.ASCENDING, Obj1.strumTime, Obj2.strumTime); + } + + private function generateStaticArrows(player:Int):Void + { + for (i in 0...4) + { + // FlxG.log.add(i); + var babyArrow:FlxSprite = new FlxSprite(0, strumLine.y); + + switch (SONG.noteStyle) + { + case 'pixel': + babyArrow.loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17); + babyArrow.animation.add('green', [6]); + babyArrow.animation.add('red', [7]); + babyArrow.animation.add('blue', [5]); + babyArrow.animation.add('purplel', [4]); + + babyArrow.setGraphicSize(Std.int(babyArrow.width * daPixelZoom)); + babyArrow.updateHitbox(); + babyArrow.antialiasing = false; + + switch (Math.abs(i)) + { + case 0: + babyArrow.x += Note.swagWidth * 0; + babyArrow.animation.add('static', [0]); + babyArrow.animation.add('pressed', [4, 8], 12, false); + babyArrow.animation.add('confirm', [12, 16], 24, false); + case 1: + babyArrow.x += Note.swagWidth * 1; + babyArrow.animation.add('static', [1]); + babyArrow.animation.add('pressed', [5, 9], 12, false); + babyArrow.animation.add('confirm', [13, 17], 24, false); + case 2: + babyArrow.x += Note.swagWidth * 2; + babyArrow.animation.add('static', [2]); + babyArrow.animation.add('pressed', [6, 10], 12, false); + babyArrow.animation.add('confirm', [14, 18], 12, false); + case 3: + babyArrow.x += Note.swagWidth * 3; + babyArrow.animation.add('static', [3]); + babyArrow.animation.add('pressed', [7, 11], 12, false); + babyArrow.animation.add('confirm', [15, 19], 24, false); + } + + case 'normal': + babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets'); + babyArrow.animation.addByPrefix('green', 'arrowUP'); + babyArrow.animation.addByPrefix('blue', 'arrowDOWN'); + babyArrow.animation.addByPrefix('purple', 'arrowLEFT'); + babyArrow.animation.addByPrefix('red', 'arrowRIGHT'); + + babyArrow.antialiasing = true; + babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7)); + + switch (Math.abs(i)) + { + case 0: + babyArrow.x += Note.swagWidth * 0; + babyArrow.animation.addByPrefix('static', 'arrowLEFT'); + babyArrow.animation.addByPrefix('pressed', 'left press', 24, false); + babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false); + case 1: + babyArrow.x += Note.swagWidth * 1; + babyArrow.animation.addByPrefix('static', 'arrowDOWN'); + babyArrow.animation.addByPrefix('pressed', 'down press', 24, false); + babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false); + case 2: + babyArrow.x += Note.swagWidth * 2; + babyArrow.animation.addByPrefix('static', 'arrowUP'); + babyArrow.animation.addByPrefix('pressed', 'up press', 24, false); + babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false); + case 3: + babyArrow.x += Note.swagWidth * 3; + babyArrow.animation.addByPrefix('static', 'arrowRIGHT'); + babyArrow.animation.addByPrefix('pressed', 'right press', 24, false); + babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false); + } + + default: + babyArrow.frames = Paths.getSparrowAtlas('NOTE_assets'); + babyArrow.animation.addByPrefix('green', 'arrowUP'); + babyArrow.animation.addByPrefix('blue', 'arrowDOWN'); + babyArrow.animation.addByPrefix('purple', 'arrowLEFT'); + babyArrow.animation.addByPrefix('red', 'arrowRIGHT'); + + babyArrow.antialiasing = true; + babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7)); + + switch (Math.abs(i)) + { + case 0: + babyArrow.x += Note.swagWidth * 0; + babyArrow.animation.addByPrefix('static', 'arrowLEFT'); + babyArrow.animation.addByPrefix('pressed', 'left press', 24, false); + babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false); + case 1: + babyArrow.x += Note.swagWidth * 1; + babyArrow.animation.addByPrefix('static', 'arrowDOWN'); + babyArrow.animation.addByPrefix('pressed', 'down press', 24, false); + babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false); + case 2: + babyArrow.x += Note.swagWidth * 2; + babyArrow.animation.addByPrefix('static', 'arrowUP'); + babyArrow.animation.addByPrefix('pressed', 'up press', 24, false); + babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false); + case 3: + babyArrow.x += Note.swagWidth * 3; + babyArrow.animation.addByPrefix('static', 'arrowRIGHT'); + babyArrow.animation.addByPrefix('pressed', 'right press', 24, false); + babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false); + } + } + + babyArrow.updateHitbox(); + babyArrow.scrollFactor.set(); + + if (!isStoryMode) + { + babyArrow.y -= 10; + babyArrow.alpha = 0; + FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)}); + } + + babyArrow.ID = i; + + if (player == 1) + { + playerStrums.add(babyArrow); + } + + babyArrow.animation.play('static'); + babyArrow.x += 50; + babyArrow.x += ((FlxG.width / 2) * player); + + strumLineNotes.add(babyArrow); + } + } + + function tweenCamIn():Void + { + FlxTween.tween(FlxG.camera, {zoom: 1.3}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut}); + } + + override function openSubState(SubState:FlxSubState) + { + if (paused) + { + if (FlxG.sound.music != null) + { + FlxG.sound.music.pause(); + vocals.pause(); + } + + #if windows + DiscordClient.changePresence("PAUSED on " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "Acc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); + #end + if (!startTimer.finished) + startTimer.active = false; + } + + super.openSubState(SubState); + } + + override function closeSubState() + { + if (paused) + { + if (FlxG.sound.music != null && !startingSong) + { + resyncVocals(); + } + + if (!startTimer.finished) + startTimer.active = true; + paused = false; + + #if windows + if (startTimer.finished) + { + DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses, iconRPC, true, songLength - Conductor.songPosition); + } + else + { + DiscordClient.changePresence(detailsText, SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), iconRPC); + } + #end + } + + super.closeSubState(); + } + + + function resyncVocals():Void + { + vocals.pause(); + + FlxG.sound.music.play(); + Conductor.songPosition = FlxG.sound.music.time; + vocals.time = Conductor.songPosition; + vocals.play(); + + #if windows + DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); + #end + } + + private var paused:Bool = false; + var startedCountdown:Bool = false; + var canPause:Bool = true; + var nps:Int = 0; + var maxNPS:Int = 0; + + public static var songRate = 1.5; + + override public function update(elapsed:Float) + { + #if !debug + perfectMode = false; + #end + + if (FlxG.save.data.botplay && FlxG.keys.justPressed.ONE) + camHUD.visible = !camHUD.visible; + + #if windows + if (executeModchart && luaModchart != null && songStarted) + { + luaModchart.setVar('songPos',Conductor.songPosition); + luaModchart.setVar('hudZoom', camHUD.zoom); + luaModchart.setVar('cameraZoom',FlxG.camera.zoom); + luaModchart.executeState('update', [elapsed]); + + for (i in luaWiggles) + { + trace('wiggle le gaming'); + i.update(elapsed); + } + + /*for (i in 0...strumLineNotes.length) { + var member = strumLineNotes.members[i]; + member.x = luaModchart.getVar("strum" + i + "X", "float"); + member.y = luaModchart.getVar("strum" + i + "Y", "float"); + member.angle = luaModchart.getVar("strum" + i + "Angle", "float"); + }*/ + + FlxG.camera.angle = luaModchart.getVar('cameraAngle', 'float'); + camHUD.angle = luaModchart.getVar('camHudAngle','float'); + + if (luaModchart.getVar("showOnlyStrums",'bool')) + { + healthBarBG.visible = false; + kadeEngineWatermark.visible = false; + healthBar.visible = false; + iconP1.visible = false; + iconP2.visible = false; + scoreTxt.visible = false; + } + else + { + healthBarBG.visible = true; + kadeEngineWatermark.visible = true; + healthBar.visible = true; + iconP1.visible = true; + iconP2.visible = true; + scoreTxt.visible = true; + } + + var p1 = luaModchart.getVar("strumLine1Visible",'bool'); + var p2 = luaModchart.getVar("strumLine2Visible",'bool'); + + for (i in 0...4) + { + strumLineNotes.members[i].visible = p1; + if (i <= playerStrums.length) + playerStrums.members[i].visible = p2; + } + } + + #end + + // reverse iterate to remove oldest notes first and not invalidate the iteration + // stop iteration as soon as a note is not removed + // all notes should be kept in the correct order and this is optimal, safe to do every frame/update + { + var balls = notesHitArray.length-1; + while (balls >= 0) + { + var cock:Date = notesHitArray[balls]; + if (cock != null && cock.getTime() + 1000 < Date.now().getTime()) + notesHitArray.remove(cock); + else + balls = 0; + balls--; + } + nps = notesHitArray.length; + if (nps > maxNPS) + maxNPS = nps; + } + + if (FlxG.keys.justPressed.NINE) + { + if (iconP1.animation.curAnim.name == 'bf-old') + iconP1.animation.play(SONG.player1); + else + iconP1.animation.play('bf-old'); + } + + switch (curStage) + { + case 'philly': + if (trainMoving) + { + trainFrameTiming += elapsed; + + if (trainFrameTiming >= 1 / 24) + { + updateTrainPos(); + trainFrameTiming = 0; + } + } + // phillyCityLights.members[curLight].alpha -= (Conductor.crochet / 1000) * FlxG.elapsed; + } + + super.update(elapsed); + + scoreTxt.text = Ratings.CalculateRanking(songScore,songScoreDef,nps,maxNPS,accuracy); + if (FlxG.keys.justPressed.ENTER && startedCountdown && canPause) + { + persistentUpdate = false; + persistentDraw = true; + paused = true; + + // 1 / 1000 chance for Gitaroo Man easter egg + if (FlxG.random.bool(0.1)) + { + // gitaroo man easter egg + FlxG.switchState(new GitarooPause()); + } + else + openSubState(new PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + } + + if (FlxG.keys.justPressed.SEVEN) + { + #if windows + DiscordClient.changePresence("Chart Editor", null, null, true); + #end + FlxG.switchState(new ChartingState()); + #if windows + if (luaModchart != null) + { + luaModchart.die(); + luaModchart = null; + } + #end + } + + // FlxG.watch.addQuick('VOL', vocals.amplitudeLeft); + // FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight); + + iconP1.setGraphicSize(Std.int(FlxMath.lerp(150, iconP1.width, 0.50))); + iconP2.setGraphicSize(Std.int(FlxMath.lerp(150, iconP2.width, 0.50))); + + iconP1.updateHitbox(); + iconP2.updateHitbox(); + + var iconOffset:Int = 26; + + iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01) - iconOffset); + iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01)) - (iconP2.width - iconOffset); + + if (health > 2) + health = 2; + + if (healthBar.percent < 20) + iconP1.animation.curAnim.curFrame = 1; + else + iconP1.animation.curAnim.curFrame = 0; + + if (healthBar.percent > 80) + iconP2.animation.curAnim.curFrame = 1; + else + iconP2.animation.curAnim.curFrame = 0; + + /* if (FlxG.keys.justPressed.NINE) + FlxG.switchState(new Charting()); */ + + #if debug + if (FlxG.keys.justPressed.EIGHT) + { + FlxG.switchState(new AnimationDebug(SONG.player2)); + #if windows + if (luaModchart != null) + { + luaModchart.die(); + luaModchart = null; + } + #end + } + + #end + + if (startingSong) + { + if (startedCountdown) + { + Conductor.songPosition += FlxG.elapsed * 1000; + if (Conductor.songPosition >= 0) + startSong(); + } + } + else + { + // Conductor.songPosition = FlxG.sound.music.time; + Conductor.songPosition += FlxG.elapsed * 1000; + /*@:privateAccess + { + FlxG.sound.music._channel. + }*/ + songPositionBar = Conductor.songPosition; + + if (!paused) + { + songTime += FlxG.game.ticks - previousFrameTime; + previousFrameTime = FlxG.game.ticks; + + // Interpolation type beat + if (Conductor.lastSongPos != Conductor.songPosition) + { + songTime = (songTime + Conductor.songPosition) / 2; + Conductor.lastSongPos = Conductor.songPosition; + // Conductor.songPosition += FlxG.elapsed * 1000; + // trace('MISSED FRAME'); + } + } + + // Conductor.lastSongPos = FlxG.sound.music.time; + } + + if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null) + { + // Make sure Girlfriend cheers only for certain songs + if(allowedToHeadbang) + { + // Don't animate GF if something else is already animating her (eg. train passing) + if(gf.animation.curAnim.name == 'danceLeft' || gf.animation.curAnim.name == 'danceRight' || gf.animation.curAnim.name == 'idle') + { + // Per song treatment since some songs will only have the 'Hey' at certain times + switch(curSong) + { + case 'Philly': + { + // General duration of the song + if(curBeat < 250) + { + // Beats to skip or to stop GF from cheering + if(curBeat != 184 && curBeat != 216) + { + if(curBeat % 16 == 8) + { + // Just a garantee that it'll trigger just once + if(!triggeredAlready) + { + gf.playAnim('cheer'); + triggeredAlready = true; + } + }else triggeredAlready = false; + } + } + } + case 'Bopeebo': + { + // Where it starts || where it ends + if(curBeat > 5 && curBeat < 130) + { + if(curBeat % 8 == 7) + { + if(!triggeredAlready) + { + gf.playAnim('cheer'); + triggeredAlready = true; + } + }else triggeredAlready = false; + } + } + case 'Blammed': + { + if(curBeat > 30 && curBeat < 190) + { + if(curBeat < 90 || curBeat > 128) + { + if(curBeat % 4 == 2) + { + if(!triggeredAlready) + { + gf.playAnim('cheer'); + triggeredAlready = true; + } + }else triggeredAlready = false; + } + } + } + case 'Cocoa': + { + if(curBeat < 170) + { + if(curBeat < 65 || curBeat > 130 && curBeat < 145) + { + if(curBeat % 16 == 15) + { + if(!triggeredAlready) + { + gf.playAnim('cheer'); + triggeredAlready = true; + } + }else triggeredAlready = false; + } + } + } + case 'Eggnog': + { + if(curBeat > 10 && curBeat != 111 && curBeat < 220) + { + if(curBeat % 8 == 7) + { + if(!triggeredAlready) + { + gf.playAnim('cheer'); + triggeredAlready = true; + } + }else triggeredAlready = false; + } + } + } + } + } + + #if windows + if (luaModchart != null) + luaModchart.setVar("mustHit",PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection); + #end + + if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection) + { + var offsetX = 0; + var offsetY = 0; + #if windows + if (luaModchart != null) + { + offsetX = luaModchart.getVar("followXOffset", "float"); + offsetY = luaModchart.getVar("followYOffset", "float"); + } + #end + camFollow.setPosition(dad.getMidpoint().x + 150 + offsetX, dad.getMidpoint().y - 100 + offsetY); + #if windows + if (luaModchart != null) + luaModchart.executeState('playerTwoTurn', []); + #end + // camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210); + + switch (dad.curCharacter) + { + case 'mom': + camFollow.y = dad.getMidpoint().y; + case 'senpai': + camFollow.y = dad.getMidpoint().y - 430; + camFollow.x = dad.getMidpoint().x - 100; + case 'senpai-angry': + camFollow.y = dad.getMidpoint().y - 430; + camFollow.x = dad.getMidpoint().x - 100; + } + + if (dad.curCharacter == 'mom') + vocals.volume = 1; + } + + if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100) + { + var offsetX = 0; + var offsetY = 0; + #if windows + if (luaModchart != null) + { + offsetX = luaModchart.getVar("followXOffset", "float"); + offsetY = luaModchart.getVar("followYOffset", "float"); + } + #end + camFollow.setPosition(boyfriend.getMidpoint().x - 100 + offsetX, boyfriend.getMidpoint().y - 100 + offsetY); + + #if windows + if (luaModchart != null) + luaModchart.executeState('playerOneTurn', []); + #end + + switch (curStage) + { + case 'limo': + camFollow.x = boyfriend.getMidpoint().x - 300; + case 'mall': + camFollow.y = boyfriend.getMidpoint().y - 200; + case 'school': + camFollow.x = boyfriend.getMidpoint().x - 200; + camFollow.y = boyfriend.getMidpoint().y - 200; + case 'schoolEvil': + camFollow.x = boyfriend.getMidpoint().x - 200; + camFollow.y = boyfriend.getMidpoint().y - 200; + } + } + } + + if (camZooming) + { + FlxG.camera.zoom = FlxMath.lerp(defaultCamZoom, FlxG.camera.zoom, 0.95); + camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95); + } + + FlxG.watch.addQuick("beatShit", curBeat); + FlxG.watch.addQuick("stepShit", curStep); + + if (curSong == 'Fresh') + { + switch (curBeat) + { + case 16: + camZooming = true; + gfSpeed = 2; + case 48: + gfSpeed = 1; + case 80: + gfSpeed = 2; + case 112: + gfSpeed = 1; + case 163: + // FlxG.sound.music.stop(); + // FlxG.switchState(new TitleState()); + } + } + + if (curSong == 'Bopeebo') + { + switch (curBeat) + { + case 128, 129, 130: + vocals.volume = 0; + // FlxG.sound.music.stop(); + // FlxG.switchState(new PlayState()); + } + } + + if (health <= 0) + { + boyfriend.stunned = true; + + persistentUpdate = false; + persistentDraw = false; + paused = true; + + vocals.stop(); + FlxG.sound.music.stop(); + + openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + + #if windows + // Game Over doesn't get his own variable because it's only used here + DiscordClient.changePresence("GAME OVER -- " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy),"\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC); + #end + + // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + } + + if (unspawnNotes[0] != null) + { + if (unspawnNotes[0].strumTime - Conductor.songPosition < 3500) + { + var dunceNote:Note = unspawnNotes[0]; + notes.add(dunceNote); + + var index:Int = unspawnNotes.indexOf(dunceNote); + unspawnNotes.splice(index, 1); + } + } + + if (generatedMusic) + { + notes.forEachAlive(function(daNote:Note) + { + + // instead of doing stupid y > FlxG.height + // we be men and actually calculate the time :) + if (daNote.tooLate) + { + daNote.active = false; + daNote.visible = false; + } + else + { + daNote.visible = true; + daNote.active = true; + } + + if (!daNote.modifiedByLua) + { + if (FlxG.save.data.downscroll) + { + if (daNote.mustPress) + daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)); + else + daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)); + if(daNote.isSustainNote) + { + // Remember = minus makes notes go up, plus makes them go down + if(daNote.animation.curAnim.name.endsWith('end') && daNote.prevNote != null) + daNote.y += daNote.prevNote.height; + else + daNote.y += daNote.height / 2; + + // If not in botplay, only clip sustain notes when properly hit, botplay gets to clip it everytime + if(!FlxG.save.data.botplay) + { + if((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit && !daNote.canBeHit) && daNote.y - daNote.offset.y * daNote.scale.y + daNote.height >= (strumLine.y + Note.swagWidth / 2)) + { + // Clip to strumline + var swagRect = new FlxRect(0, 0, daNote.frameWidth * 2, daNote.frameHeight * 2); + swagRect.height = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y; + swagRect.y = daNote.frameHeight - swagRect.height; + + daNote.clipRect = swagRect; + } + }else { + var swagRect = new FlxRect(0, 0, daNote.frameWidth * 2, daNote.frameHeight * 2); + swagRect.height = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + Note.swagWidth / 2 - daNote.y) / daNote.scale.y; + swagRect.y = daNote.frameHeight - swagRect.height; + + daNote.clipRect = swagRect; + } + } + }else + { + if (daNote.mustPress) + daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)); + else + daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)); + if(daNote.isSustainNote) + { + daNote.y -= daNote.height / 2; + + if(!FlxG.save.data.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 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 && !FlxG.save.data.downscroll || daNote.mustPress && daNote.tooLate && FlxG.save.data.downscroll) && daNote.mustPress) + { + if (daNote.isSustainNote && daNote.wasGoodHit) + { + daNote.kill(); + notes.remove(daNote, true); + daNote.destroy(); + } + else + { + health -= 0.075; + vocals.volume = 0; + if (theFunne) + noteMiss(daNote.noteData, daNote); + } + + daNote.active = false; + daNote.visible = false; + + daNote.kill(); + notes.remove(daNote, true); + daNote.destroy(); + } + }); + } + + + if (!inCutscene) + keyShit(); + + + #if debug + if (FlxG.keys.justPressed.ONE) + endSong(); + #end + } + + function endSong():Void + { + if (!loadRep) + rep.SaveReplay(saveNotes); + else + { + FlxG.save.data.botplay = false; + FlxG.save.data.scrollSpeed = 1; + FlxG.save.data.downscroll = false; + } + + if (FlxG.save.data.fpsCap > 290) + (cast (Lib.current.getChildAt(0), Main)).setFPSCap(290); + + #if windows + if (luaModchart != null) + { + luaModchart.die(); + luaModchart = null; + } + #end + + canPause = false; + FlxG.sound.music.volume = 0; + vocals.volume = 0; + if (SONG.validScore) + { + #if !switch + Highscore.saveScore(SONG.song, Math.round(songScore), storyDifficulty); + #end + } + + if (offsetTesting) + { + FlxG.sound.playMusic(Paths.music('freakyMenu')); + offsetTesting = false; + LoadingState.loadAndSwitchState(new OptionsMenu()); + FlxG.save.data.offset = offsetTest; + } + else + { + if (isStoryMode) + { + campaignScore += Math.round(songScore); + + storyPlaylist.remove(storyPlaylist[0]); + + if (storyPlaylist.length <= 0) + { + FlxG.sound.playMusic(Paths.music('freakyMenu')); + + transIn = FlxTransitionableState.defaultTransIn; + transOut = FlxTransitionableState.defaultTransOut; + + FlxG.switchState(new StoryMenuState()); + + #if windows + if (luaModchart != null) + { + luaModchart.die(); + luaModchart = null; + } + #end + + // if () + StoryMenuState.weekUnlocked[Std.int(Math.min(storyWeek + 1, StoryMenuState.weekUnlocked.length - 1))] = true; + + if (SONG.validScore) + { + NGio.unlockMedal(60961); + Highscore.saveWeekScore(storyWeek, campaignScore, storyDifficulty); + } + + FlxG.save.data.weekUnlocked = StoryMenuState.weekUnlocked; + FlxG.save.flush(); + } + else + { + var difficulty:String = ""; + + if (storyDifficulty == 0) + difficulty = '-easy'; + + if (storyDifficulty == 2) + difficulty = '-hard'; + + trace('LOADING NEXT SONG'); + trace(PlayState.storyPlaylist[0].toLowerCase() + difficulty); + + if (SONG.song.toLowerCase() == 'eggnog') + { + var blackShit:FlxSprite = new FlxSprite(-FlxG.width * FlxG.camera.zoom, + -FlxG.height * FlxG.camera.zoom).makeGraphic(FlxG.width * 3, FlxG.height * 3, FlxColor.BLACK); + blackShit.scrollFactor.set(); + add(blackShit); + camHUD.visible = false; + + FlxG.sound.play(Paths.sound('Lights_Shut_off')); + } + + FlxTransitionableState.skipNextTransIn = true; + FlxTransitionableState.skipNextTransOut = true; + prevCamFollow = camFollow; + + PlayState.SONG = Song.loadFromJson(PlayState.storyPlaylist[0].toLowerCase() + difficulty, PlayState.storyPlaylist[0]); + FlxG.sound.music.stop(); + + LoadingState.loadAndSwitchState(new PlayState()); + } + } + else + { + trace('WENT BACK TO FREEPLAY??'); + FlxG.switchState(new FreeplayState()); + } + } + } + + + var endingSong:Bool = false; + + var hits:Array = []; + var offsetTest:Float = 0; + + var timeShown = 0; + var currentTimingShown:FlxText = null; + + private function popUpScore(daNote:Note):Void + { + var noteDiff:Float = Math.abs(Conductor.songPosition - daNote.strumTime); + var wife:Float = EtternaFunctions.wife3(noteDiff, Conductor.timeScale); + // boyfriend.playAnim('hey'); + vocals.volume = 1; + + var placement:String = Std.string(combo); + + var coolText:FlxText = new FlxText(0, 0, 0, placement, 32); + coolText.screenCenter(); + coolText.x = FlxG.width * 0.55; + coolText.y -= 350; + coolText.cameras = [camHUD]; + // + + var rating:FlxSprite = new FlxSprite(); + var score:Float = 350; + + if (FlxG.save.data.accuracyMod == 1) + totalNotesHit += wife; + + var daRating = daNote.rating; + + switch(daRating) + { + case 'shit': + score = -300; + combo = 0; + misses++; + health -= 0.2; + ss = false; + shits++; + if (FlxG.save.data.accuracyMod == 0) + totalNotesHit += 0.25; + case 'bad': + daRating = 'bad'; + score = 0; + health -= 0.06; + ss = false; + bads++; + if (FlxG.save.data.accuracyMod == 0) + totalNotesHit += 0.50; + case 'good': + daRating = 'good'; + score = 200; + ss = false; + goods++; + if (health < 2) + health += 0.04; + if (FlxG.save.data.accuracyMod == 0) + totalNotesHit += 0.75; + case 'sick': + if (health < 2) + health += 0.1; + if (FlxG.save.data.accuracyMod == 0) + totalNotesHit += 1; + sicks++; + } + + // trace('Wife accuracy loss: ' + wife + ' | Rating: ' + daRating + ' | Score: ' + score + ' | Weight: ' + (1 - wife)); + + if (daRating != 'shit' || daRating != 'bad') + { + + + songScore += Math.round(score); + songScoreDef += Math.round(ConvertScore.convertScore(noteDiff)); + + /* if (combo > 60) + daRating = 'sick'; + else if (combo > 12) + daRating = 'good' + else if (combo > 4) + daRating = 'bad'; + */ + + var pixelShitPart1:String = ""; + var pixelShitPart2:String = ''; + + if (curStage.startsWith('school')) + { + pixelShitPart1 = 'weeb/pixelUI/'; + pixelShitPart2 = '-pixel'; + } + + rating.loadGraphic(Paths.image(pixelShitPart1 + daRating + pixelShitPart2)); + rating.screenCenter(); + rating.y -= 50; + rating.x = coolText.x - 125; + + if (FlxG.save.data.changedHit) + { + rating.x = FlxG.save.data.changedHitX; + rating.y = FlxG.save.data.changedHitY; + } + rating.acceleration.y = 550; + rating.velocity.y -= FlxG.random.int(140, 175); + rating.velocity.x -= FlxG.random.int(0, 10); + + var msTiming = HelperFunctions.truncateFloat(noteDiff, 3); + if(FlxG.save.data.botplay) msTiming = 0; + + if (currentTimingShown != null) + remove(currentTimingShown); + + currentTimingShown = new FlxText(0,0,0,"0ms"); + timeShown = 0; + switch(daRating) + { + case 'shit' | 'bad': + currentTimingShown.color = FlxColor.RED; + case 'good': + currentTimingShown.color = FlxColor.GREEN; + case 'sick': + currentTimingShown.color = FlxColor.CYAN; + } + currentTimingShown.borderStyle = OUTLINE; + currentTimingShown.borderSize = 1; + currentTimingShown.borderColor = FlxColor.BLACK; + currentTimingShown.text = msTiming + "ms"; + currentTimingShown.size = 20; + + if (msTiming >= 0.03 && offsetTesting) + { + //Remove Outliers + hits.shift(); + hits.shift(); + hits.shift(); + hits.pop(); + hits.pop(); + hits.pop(); + hits.push(msTiming); + + var total = 0.0; + + for(i in hits) + total += i; + + + + offsetTest = HelperFunctions.truncateFloat(total / hits.length,2); + } + + if (currentTimingShown.alpha != 1) + currentTimingShown.alpha = 1; + + if(!FlxG.save.data.botplay) add(currentTimingShown); + + var comboSpr:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'combo' + pixelShitPart2)); + comboSpr.screenCenter(); + comboSpr.x = rating.x; + comboSpr.y = rating.y + 100; + comboSpr.acceleration.y = 600; + comboSpr.velocity.y -= 150; + + currentTimingShown.screenCenter(); + currentTimingShown.x = comboSpr.x + 100; + currentTimingShown.y = rating.y + 100; + currentTimingShown.acceleration.y = 600; + currentTimingShown.velocity.y -= 150; + + comboSpr.velocity.x += FlxG.random.int(1, 10); + currentTimingShown.velocity.x += comboSpr.velocity.x; + if(!FlxG.save.data.botplay) add(rating); + + if (!curStage.startsWith('school')) + { + rating.setGraphicSize(Std.int(rating.width * 0.7)); + rating.antialiasing = true; + comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7)); + comboSpr.antialiasing = true; + } + else + { + rating.setGraphicSize(Std.int(rating.width * daPixelZoom * 0.7)); + comboSpr.setGraphicSize(Std.int(comboSpr.width * daPixelZoom * 0.7)); + } + + currentTimingShown.updateHitbox(); + comboSpr.updateHitbox(); + rating.updateHitbox(); + + currentTimingShown.cameras = [camHUD]; + comboSpr.cameras = [camHUD]; + rating.cameras = [camHUD]; + + var seperatedScore:Array = []; + + var comboSplit:Array = (combo + "").split(''); + + if (comboSplit.length == 2) + seperatedScore.push(0); // make sure theres a 0 in front or it looks weird lol! + + for(i in 0...comboSplit.length) + { + var str:String = comboSplit[i]; + seperatedScore.push(Std.parseInt(str)); + } + + var daLoop:Int = 0; + for (i in seperatedScore) + { + var numScore:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'num' + Std.int(i) + pixelShitPart2)); + numScore.screenCenter(); + numScore.x = rating.x + (43 * daLoop) - 50; + numScore.y = rating.y + 100; + numScore.cameras = [camHUD]; + + if (!curStage.startsWith('school')) + { + numScore.antialiasing = true; + numScore.setGraphicSize(Std.int(numScore.width * 0.5)); + } + else + { + numScore.setGraphicSize(Std.int(numScore.width * daPixelZoom)); + } + numScore.updateHitbox(); + + numScore.acceleration.y = FlxG.random.int(200, 300); + numScore.velocity.y -= FlxG.random.int(140, 160); + numScore.velocity.x = FlxG.random.float(-5, 5); + + if (combo >= 10 || combo == 0) + add(numScore); + + FlxTween.tween(numScore, {alpha: 0}, 0.2, { + onComplete: function(tween:FlxTween) + { + numScore.destroy(); + }, + startDelay: Conductor.crochet * 0.002 + }); + + daLoop++; + } + /* + trace(combo); + trace(seperatedScore); + */ + + coolText.text = Std.string(seperatedScore); + // add(coolText); + + FlxTween.tween(rating, {alpha: 0}, 0.2, { + startDelay: Conductor.crochet * 0.001, + onUpdate: function(tween:FlxTween) + { + if (currentTimingShown != null) + currentTimingShown.alpha -= 0.02; + timeShown++; + } + }); + + FlxTween.tween(comboSpr, {alpha: 0}, 0.2, { + onComplete: function(tween:FlxTween) + { + coolText.destroy(); + comboSpr.destroy(); + if (currentTimingShown != null && timeShown >= 20) + { + remove(currentTimingShown); + currentTimingShown = null; + } + rating.destroy(); + }, + startDelay: Conductor.crochet * 0.001 + }); + + curSection += 1; + } + } + + public function NearlyEquals(value1:Float, value2:Float, unimportantDifference:Float = 10):Bool + { + return Math.abs(FlxMath.roundDecimal(value1, 1) - FlxMath.roundDecimal(value2, 1)) < unimportantDifference; + } + + var upHold:Bool = false; + var downHold:Bool = false; + var rightHold:Bool = false; + var leftHold:Bool = false; + + private function keyShit():Void // I've invested in emma stocks + { + // control arrays, order L D R U + var holdArray:Array = [controls.LEFT, controls.DOWN, controls.UP, controls.RIGHT]; + var pressArray:Array = [ + controls.LEFT_P, + controls.DOWN_P, + controls.UP_P, + controls.RIGHT_P + ]; + var releaseArray:Array = [ + controls.LEFT_R, + controls.DOWN_R, + controls.UP_R, + controls.RIGHT_R + ]; + + // Prevent player input if botplay is on + if(FlxG.save.data.botplay) + { + 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); + }); + } + + // 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 + + notes.forEachAlive(function(daNote:Note) + { + if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit) + { + if (directionList.contains(daNote.noteData)) + { + 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; + + for (i in 0...pressArray.length) + { + if (pressArray[i] && !directionList.contains(i)) + dontCheck = true; + } + + 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 && !FlxG.save.data.botplay) + { + if (mashViolations > 4) + { + trace('mash violations ' + mashViolations); + scoreTxt.color = FlxColor.RED; + noteMiss(0,null); + } + else + mashViolations++; + } + + } + + notes.forEachAlive(function(daNote:Note) + { + if(FlxG.save.data.downscroll && daNote.y > strumLine.y || + !FlxG.save.data.downscroll && daNote.y < strumLine.y) + { + // Force good note hit regardless if it's too late to hit it or not as a fail safe + if(FlxG.save.data.botplay && daNote.canBeHit && daNote.mustPress || + FlxG.save.data.botplay && daNote.tooLate && daNote.mustPress) + { + if(loadRep) + { + //trace('ReplayNote ' + tmpRepNote.strumtime + ' | ' + tmpRepNote.direction); + if(rep.replay.songNotes.contains(HelperFunctions.truncateFloat(daNote.strumTime, 2))) + { + goodNoteHit(daNote); + boyfriend.holdTimer = daNote.sustainLength; + } + }else { + goodNoteHit(daNote); + boyfriend.holdTimer = daNote.sustainLength; + } + } + } + }); + + if (boyfriend.holdTimer > Conductor.stepCrochet * 4 * 0.001 && (!holdArray.contains(true) || FlxG.save.data.botplay)) + { + if (boyfriend.animation.curAnim.name.startsWith('sing') && !boyfriend.animation.curAnim.name.endsWith('miss')) + boyfriend.playAnim('idle'); + } + + playerStrums.forEach(function(spr:FlxSprite) + { + if (pressArray[spr.ID] && spr.animation.curAnim.name != 'confirm') + spr.animation.play('pressed'); + if (!holdArray[spr.ID]) + spr.animation.play('static'); + + if (spr.animation.curAnim.name == 'confirm' && !curStage.startsWith('school')) + { + spr.centerOffsets(); + spr.offset.x -= 13; + spr.offset.y -= 13; + } + else + spr.centerOffsets(); + }); + } + + function noteMiss(direction:Int = 1, daNote:Note):Void + { + if (!boyfriend.stunned) + { + health -= 0.04; + if (combo > 5 && gf.animOffsets.exists('sad')) + { + gf.playAnim('sad'); + } + combo = 0; + misses++; + + //var noteDiff:Float = Math.abs(daNote.strumTime - Conductor.songPosition); + //var wife:Float = EtternaFunctions.wife3(noteDiff, FlxG.save.data.etternaMode ? 1 : 1.7); + + if (FlxG.save.data.accuracyMod == 1) + totalNotesHit -= 1; + + songScore -= 10; + + FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2)); + // FlxG.sound.play(Paths.sound('missnote1'), 1, false); + // FlxG.log.add('played imss note'); + + switch (direction) + { + case 0: + boyfriend.playAnim('singLEFTmiss', true); + case 1: + boyfriend.playAnim('singDOWNmiss', true); + case 2: + boyfriend.playAnim('singUPmiss', true); + case 3: + boyfriend.playAnim('singRIGHTmiss', true); + } + + #if windows + if (luaModchart != null) + luaModchart.executeState('playerOneMiss', [direction, Conductor.songPosition]); + #end + + + updateAccuracy(); + } + } + + /*function badNoteCheck() + { + // just double pasting this shit cuz fuk u + // REDO THIS SYSTEM! + var upP = controls.UP_P; + var rightP = controls.RIGHT_P; + var downP = controls.DOWN_P; + var leftP = controls.LEFT_P; + + if (leftP) + noteMiss(0); + if (upP) + noteMiss(2); + if (rightP) + noteMiss(3); + if (downP) + noteMiss(1); + updateAccuracy(); + } + */ + function updateAccuracy() + { + totalPlayed += 1; + accuracy = Math.max(0,totalNotesHit / totalPlayed * 100); + accuracyDefault = Math.max(0, totalNotesHitDefault / totalPlayed * 100); + } + + + function getKeyPresses(note:Note):Int + { + var possibleNotes:Array = []; // copypasted but you already know that + + notes.forEachAlive(function(daNote:Note) + { + if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate) + { + possibleNotes.push(daNote); + possibleNotes.sort((a, b) -> Std.int(a.strumTime - b.strumTime)); + } + }); + if (possibleNotes.length == 1) + return possibleNotes.length + 1; + return possibleNotes.length; + } + + var mashing:Int = 0; + var mashViolations:Int = 0; + + var etternaModeScore:Int = 0; + + function noteCheck(controlArray:Array, note:Note):Void // sorry lol + { + var noteDiff:Float = Math.abs(note.strumTime - Conductor.songPosition); + + note.rating = Ratings.CalculateRating(noteDiff); + + /* if (loadRep) + { + if (controlArray[note.noteData]) + goodNoteHit(note, false); + else if (rep.replay.keyPresses.length > repPresses && !controlArray[note.noteData]) + { + if (NearlyEquals(note.strumTime,rep.replay.keyPresses[repPresses].time, 4)) + { + goodNoteHit(note, false); + } + } + } */ + + if (controlArray[note.noteData]) + { + goodNoteHit(note, (mashing > getKeyPresses(note))); + + /*if (mashing > getKeyPresses(note) && mashViolations <= 2) + { + mashViolations++; + + goodNoteHit(note, (mashing > getKeyPresses(note))); + } + else if (mashViolations > 2) + { + // this is bad but fuck you + playerStrums.members[0].animation.play('static'); + playerStrums.members[1].animation.play('static'); + playerStrums.members[2].animation.play('static'); + playerStrums.members[3].animation.play('static'); + health -= 0.4; + trace('mash ' + mashing); + if (mashing != 0) + mashing = 0; + } + else + goodNoteHit(note, false);*/ + + } + } + + function goodNoteHit(note:Note, resetMashViolation = true):Void + { + + if (mashing != 0) + mashing = 0; + + var noteDiff:Float = Math.abs(note.strumTime - Conductor.songPosition); + + note.rating = Ratings.CalculateRating(noteDiff); + + // 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) + saveNotes.push(HelperFunctions.truncateFloat(note.strumTime, 2)); + + playerStrums.forEach(function(spr:FlxSprite) + { + if (Math.abs(note.noteData) == spr.ID) + { + spr.animation.play('confirm', true); + } + }); + + note.wasGoodHit = true; + vocals.volume = 1; + + note.kill(); + notes.remove(note, true); + note.destroy(); + + updateAccuracy(); + } + } + + + var fastCarCanDrive:Bool = true; + + function resetFastCar():Void + { + if(FlxG.save.data.distractions){ + fastCar.x = -12600; + fastCar.y = FlxG.random.int(140, 250); + fastCar.velocity.x = 0; + fastCarCanDrive = true; + } + } + + function fastCarDrive() + { + if(FlxG.save.data.distractions){ + FlxG.sound.play(Paths.soundRandom('carPass', 0, 1), 0.7); + + fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3; + fastCarCanDrive = false; + new FlxTimer().start(2, function(tmr:FlxTimer) + { + resetFastCar(); + }); + } + } + + var trainMoving:Bool = false; + var trainFrameTiming:Float = 0; + + var trainCars:Int = 8; + var trainFinishing:Bool = false; + var trainCooldown:Int = 0; + + function trainStart():Void + { + if(FlxG.save.data.distractions){ + trainMoving = true; + if (!trainSound.playing) + trainSound.play(true); + } + } + + var startedMoving:Bool = false; + + function updateTrainPos():Void + { + if(FlxG.save.data.distractions){ + if (trainSound.time >= 4700) + { + startedMoving = true; + gf.playAnim('hairBlow'); + } + + if (startedMoving) + { + phillyTrain.x -= 400; + + if (phillyTrain.x < -2000 && !trainFinishing) + { + phillyTrain.x = -1150; + trainCars -= 1; + + if (trainCars <= 0) + trainFinishing = true; + } + + if (phillyTrain.x < -4000 && trainFinishing) + trainReset(); + } + } + + } + + function trainReset():Void + { + if(FlxG.save.data.distractions){ + gf.playAnim('hairFall'); + phillyTrain.x = FlxG.width + 200; + trainMoving = false; + // trainSound.stop(); + // trainSound.time = 0; + trainCars = 8; + trainFinishing = false; + startedMoving = false; + } + } + + function lightningStrikeShit():Void + { + FlxG.sound.play(Paths.soundRandom('thunder_', 1, 2)); + halloweenBG.animation.play('lightning'); + + lightningStrikeBeat = curBeat; + lightningOffset = FlxG.random.int(8, 24); + + boyfriend.playAnim('scared', true); + gf.playAnim('scared', true); + } + + override function stepHit() + { + super.stepHit(); + if (FlxG.sound.music.time > Conductor.songPosition + 20 || FlxG.sound.music.time < Conductor.songPosition - 20) + { + resyncVocals(); + } + + #if windows + if (executeModchart && luaModchart != null) + { + luaModchart.setVar('curStep',curStep); + luaModchart.executeState('stepHit',[curStep]); + } + #end + + if (dad.curCharacter == 'spooky' && curStep % 4 == 2) + { + // dad.dance(); + } + + + // yes this updates every step. + // yes this is bad + // but i'm doing it to update misses and accuracy + #if windows + // Song duration in a float, useful for the time left feature + songLength = FlxG.sound.music.length; + + // Updating Discord Rich Presence (with Time Left) + DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "Acc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC,true, songLength - Conductor.songPosition); + #end + + } + + var lightningStrikeBeat:Int = 0; + var lightningOffset:Int = 8; + + override function beatHit() + { + super.beatHit(); + + if (generatedMusic) + { + notes.sort(FlxSort.byY, (FlxG.save.data.downscroll ? FlxSort.ASCENDING : FlxSort.DESCENDING)); + } + + #if windows + if (executeModchart && luaModchart != null) + { + luaModchart.setVar('curBeat',curBeat); + luaModchart.executeState('beatHit',[curBeat]); + } + #end + + 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.dance(); + } + // FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM); + wiggleShit.update(Conductor.crochet); + + // HARDCODING FOR MILF ZOOMS! + if (curSong.toLowerCase() == 'milf' && curBeat >= 168 && curBeat < 200 && camZooming && FlxG.camera.zoom < 1.35) + { + FlxG.camera.zoom += 0.015; + camHUD.zoom += 0.03; + } + + if (camZooming && FlxG.camera.zoom < 1.35 && curBeat % 4 == 0) + { + FlxG.camera.zoom += 0.015; + camHUD.zoom += 0.03; + } + + iconP1.setGraphicSize(Std.int(iconP1.width + 30)); + iconP2.setGraphicSize(Std.int(iconP2.width + 30)); + + iconP1.updateHitbox(); + iconP2.updateHitbox(); + + if (curBeat % gfSpeed == 0) + { + gf.dance(); + } + + if (!boyfriend.animation.curAnim.name.startsWith("sing")) + { + boyfriend.playAnim('idle'); + } + + if (!dad.animation.curAnim.name.startsWith("sing")) + { + dad.dance(); + } + + if (curBeat % 8 == 7 && curSong == 'Bopeebo') + { + boyfriend.playAnim('hey', true); + } + + if (curBeat % 16 == 15 && SONG.song == 'Tutorial' && dad.curCharacter == 'gf' && curBeat > 16 && curBeat < 48) + { + boyfriend.playAnim('hey', true); + dad.playAnim('cheer', true); + } + + switch (curStage) + { + case 'school': + if(FlxG.save.data.distractions){ + bgGirls.dance(); + } + + case 'mall': + if(FlxG.save.data.distractions){ + upperBoppers.animation.play('bop', true); + bottomBoppers.animation.play('bop', true); + santa.animation.play('idle', true); + } + + case 'limo': + if(FlxG.save.data.distractions){ + grpLimoDancers.forEach(function(dancer:BackgroundDancer) + { + dancer.dance(); + }); + + if (FlxG.random.bool(10) && fastCarCanDrive) + fastCarDrive(); + } + case "philly": + if(FlxG.save.data.distractions){ + if (!trainMoving) + trainCooldown += 1; + + if (curBeat % 4 == 0) + { + phillyCityLights.forEach(function(light:FlxSprite) + { + light.visible = false; + }); + + curLight = FlxG.random.int(0, phillyCityLights.length - 1); + + phillyCityLights.members[curLight].visible = true; + // phillyCityLights.members[curLight].alpha = 1; + } + + } + + if (curBeat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8) + { + if(FlxG.save.data.distractions){ + trainCooldown = FlxG.random.int(-4, 0); + trainStart(); + } + } + } + + if (isHalloween && FlxG.random.bool(10) && curBeat > lightningStrikeBeat + lightningOffset) + { + if(FlxG.save.data.distractions){ + lightningStrikeShit(); + } + } + } + + var curLight:Int = 0; +} diff --git a/source/Ratings.hx b/source/Ratings.hx index a8e5ccf..615d3ba 100644 --- a/source/Ratings.hx +++ b/source/Ratings.hx @@ -129,10 +129,10 @@ class Ratings return "sick"; } - public static function CalculateRanking(score:Int,scoreDef:Int,nps:Int,accuracy:Float):String + public static function CalculateRanking(score:Int,scoreDef:Int,nps:Int,maxNPS:Int,accuracy:Float):String { return - (FlxG.save.data.npsDisplay ? "NPS: " + nps + (!FlxG.save.data.botplay ? " | " : "") : "") + (!FlxG.save.data.botplay ? // NPS Toggle + (FlxG.save.data.npsDisplay ? "NPS: " + nps + " (Max " + maxNPS + ")" + (!FlxG.save.data.botplay ? " | " : "") : "") + (!FlxG.save.data.botplay ? // NPS Toggle "Score:" + (Conductor.safeFrames != 10 ? score + " (" + scoreDef + ")" : "" + score) + // Score " | Combo Breaks:" + PlayState.misses + // Misses/Combo Breaks " | Accuracy:" + (FlxG.save.data.botplay ? "N/A" : HelperFunctions.truncateFloat(accuracy, 2) + " %") + // Accuracy diff --git a/source/Replay.hx b/source/Replay.hx index 3bf37a0..bf43d77 100644 --- a/source/Replay.hx +++ b/source/Replay.hx @@ -1,101 +1,91 @@ -#if sys -import sys.io.File; -#end -import Controls.Control; -import flixel.FlxG; -import openfl.events.IOErrorEvent; -import openfl.events.Event; -import openfl.net.FileReference; -import lime.utils.Assets; -import haxe.Json; -import flixel.input.keyboard.FlxKey; -import openfl.utils.Dictionary; - -typedef KeyPress = -{ - public var time:Float; - public var key:String; -} - -typedef KeyRelease = -{ - public var time:Float; - public var key:String; -} - -typedef ReplayJSON = -{ - public var replayGameVer:String; - public var timestamp:Date; - public var songName:String; - public var songDiff:Int; - public var keyPresses:Array; - public var keyReleases:Array; -} - -class Replay -{ - public static var version:String = "1.0"; // replay file version - - public var path:String = ""; - public var replay:ReplayJSON; - public function new(path:String) - { - this.path = path; - replay = { - songName: "Tutorial", - songDiff: 1, - keyPresses: [], - keyReleases: [], - replayGameVer: version, - timestamp: Date.now() - }; - } - - public static function LoadReplay(path:String):Replay - { - var rep:Replay = new Replay(path); - - rep.LoadFromJSON(); - - trace('basic replay data:\nSong Name: ' + rep.replay.songName + '\nSong Diff: ' + rep.replay.songDiff + '\nKeys Length: ' + rep.replay.keyPresses.length); - - return rep; - } - - public function SaveReplay() - { - var json = { - "songName": PlayState.SONG.song.toLowerCase(), - "songDiff": PlayState.storyDifficulty, - "keyPresses": replay.keyPresses, - "keyReleases": replay.keyReleases, - "timestamp": Date.now(), - "replayGameVer": version - }; - - var data:String = Json.stringify(json); - - #if sys - File.saveContent("assets/replays/replay-" + PlayState.SONG.song + "-time" + Date.now().getTime() + ".kadeReplay", data); - #end - } - - - public function LoadFromJSON() - { - #if sys - trace('loading ' + Sys.getCwd() + 'assets/replays/' + path + ' replay...'); - try - { - var repl:ReplayJSON = cast Json.parse(File.getContent(Sys.getCwd() + "assets/replays/" + path)); - replay = repl; - } - catch(e) - { - trace('failed!\n' + e.message); - } - #end - } - -} +#if sys +import sys.io.File; +#end +import Controls.Control; +import flixel.FlxG; +import openfl.events.IOErrorEvent; +import openfl.events.Event; +import openfl.net.FileReference; +import lime.utils.Assets; +import haxe.Json; +import flixel.input.keyboard.FlxKey; +import openfl.utils.Dictionary; + +typedef ReplayJSON = +{ + public var replayGameVer:String; + public var timestamp:Date; + public var songName:String; + public var songDiff:Int; + public var songNotes:Array; + public var noteSpeed:Float; + public var isDownscroll:Bool; +} + +class Replay +{ + public static var version:String = "1.0"; // replay file version + + public var path:String = ""; + public var replay:ReplayJSON; + public function new(path:String) + { + this.path = path; + replay = { + songName: "Tutorial", + songDiff: 1, + noteSpeed: 1.5, + isDownscroll: false, + songNotes: [], + replayGameVer: version, + timestamp: Date.now() + }; + } + + public static function LoadReplay(path:String):Replay + { + var rep:Replay = new Replay(path); + + rep.LoadFromJSON(); + + trace('basic replay data:\nSong Name: ' + rep.replay.songName + '\nSong Diff: ' + rep.replay.songDiff + '\nNotes Length: ' + rep.replay.songNotes.length); + + return rep; + } + + public function SaveReplay(notearray:Array) + { + var json = { + "songName": PlayState.SONG.song.toLowerCase(), + "songDiff": PlayState.storyDifficulty, + "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 + }; + + var data:String = Json.stringify(json); + + #if sys + File.saveContent("assets/replays/replay-" + PlayState.SONG.song + "-time" + Date.now().getTime() + ".kadeReplay", data); + #end + } + + public function LoadFromJSON() + { + #if sys + trace('loading ' + Sys.getCwd() + 'assets/replays/' + path + ' replay...'); + try + { + var repl:ReplayJSON = cast Json.parse(File.getContent(Sys.getCwd() + "assets/replays/" + path)); + replay = repl; + } + catch(e) + { + trace('failed!\n' + e.message); + } + #end + } + +} diff --git a/source/StoryMenuState.hx b/source/StoryMenuState.hx index 9fccd52..9dbafc8 100644 --- a/source/StoryMenuState.hx +++ b/source/StoryMenuState.hx @@ -25,11 +25,11 @@ class StoryMenuState extends MusicBeatState var weekData:Array = [ ['Tutorial'], - ['Bopeebo', 'Fresh', 'Dadbattle'], + ['Bopeebo', 'Fresh', 'Dad Battle'], ['Spookeez', 'South', "Monster"], - ['Pico', 'Philly', "Blammed"], - ['Satin-Panties', "High", "Milf"], - ['Cocoa', 'Eggnog', 'Winter-Horrorland'], + ['Pico', 'Philly Nice', "Blammed"], + ['Satin Panties', "High", "Milf"], + ['Cocoa', 'Eggnog', 'Winter Horrorland'], ['Senpai', 'Roses', 'Thorns'] ]; var curDifficulty:Int = 1; @@ -47,7 +47,7 @@ class StoryMenuState extends MusicBeatState ]; var weekNames:Array = [ - "How to Funk", + "", "Daddy Dearest", "Spooky Month", "PICO", diff --git a/source/TitleState.hx b/source/TitleState.hx index a0b0658..213d816 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -1,463 +1,467 @@ -package; - -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.FlxState; -import flixel.addons.display.FlxGridOverlay; -import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond; -import flixel.addons.transition.FlxTransitionableState; -import flixel.addons.transition.TransitionData; -import flixel.graphics.FlxGraphic; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.group.FlxGroup; -import flixel.input.gamepad.FlxGamepad; -import flixel.math.FlxPoint; -import flixel.math.FlxRect; -import flixel.system.FlxSound; -import flixel.system.ui.FlxSoundTray; -import flixel.text.FlxText; -import flixel.tweens.FlxEase; -import flixel.tweens.FlxTween; -import flixel.util.FlxColor; -import flixel.util.FlxTimer; -import io.newgrounds.NG; -import lime.app.Application; -import openfl.Assets; - -#if windows -import Discord.DiscordClient; -#end - -#if cpp -import sys.thread.Thread; -#end - -using StringTools; - -class TitleState extends MusicBeatState -{ - static var initialized:Bool = false; - - var blackScreen:FlxSprite; - var credGroup:FlxGroup; - var credTextShit:Alphabet; - var textGroup:FlxGroup; - var ngSpr:FlxSprite; - - var curWacky:Array = []; - - var wackyImage:FlxSprite; - - override public function create():Void - { - #if polymod - polymod.Polymod.init({modRoot: "mods", dirs: ['introMod']}); - #end - - #if sys - if (!sys.FileSystem.exists(Sys.getCwd() + "/assets/replays")) - sys.FileSystem.createDirectory(Sys.getCwd() + "/assets/replays"); - #end - - @:privateAccess - { - trace("Loaded " + openfl.Assets.getLibrary("default").assetsLoaded + " assets (DEFAULT)"); - } - - PlayerSettings.init(); - - #if windows - DiscordClient.initialize(); - - Application.current.onExit.add (function (exitCode) { - DiscordClient.shutdown(); - }); - - #end - - curWacky = FlxG.random.getObject(getIntroTextShit()); - - // DEBUG BULLSHIT - - super.create(); - - // NGio.noLogin(APIStuff.API); - - #if ng - var ng:NGio = new NGio(APIStuff.API, APIStuff.EncKey); - trace('NEWGROUNDS LOL'); - #end - - FlxG.save.bind('funkin', 'ninjamuffin99'); - - KadeEngineData.initSave(); - - Highscore.load(); - - if (FlxG.save.data.weekUnlocked != null) - { - // FIX LATER!!! - // WEEK UNLOCK PROGRESSION!! - // StoryMenuState.weekUnlocked = FlxG.save.data.weekUnlocked; - - if (StoryMenuState.weekUnlocked.length < 4) - StoryMenuState.weekUnlocked.insert(0, true); - - // QUICK PATCH OOPS! - if (!StoryMenuState.weekUnlocked[0]) - StoryMenuState.weekUnlocked[0] = true; - } - - #if FREEPLAY - FlxG.switchState(new FreeplayState()); - #elseif CHARTING - FlxG.switchState(new ChartingState()); - #else - new FlxTimer().start(1, function(tmr:FlxTimer) - { - startIntro(); - }); - #end - } - - var logoBl:FlxSprite; - var gfDance:FlxSprite; - var danceLeft:Bool = false; - var titleText:FlxSprite; - - function startIntro() - { - if (!initialized) - { - var diamond:FlxGraphic = FlxGraphic.fromClass(GraphicTransTileDiamond); - diamond.persist = true; - diamond.destroyOnNoUse = false; - - FlxTransitionableState.defaultTransIn = new TransitionData(FADE, FlxColor.BLACK, 1, new FlxPoint(0, -1), {asset: diamond, width: 32, height: 32}, - new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4)); - FlxTransitionableState.defaultTransOut = new TransitionData(FADE, FlxColor.BLACK, 0.7, new FlxPoint(0, 1), - {asset: diamond, width: 32, height: 32}, new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4)); - - transIn = FlxTransitionableState.defaultTransIn; - transOut = FlxTransitionableState.defaultTransOut; - - // HAD TO MODIFY SOME BACKEND SHIT - // IF THIS PR IS HERE IF ITS ACCEPTED UR GOOD TO GO - // https://github.com/HaxeFlixel/flixel-addons/pull/348 - - // var music:FlxSound = new FlxSound(); - // music.loadStream(Paths.music('freakyMenu')); - // FlxG.sound.list.add(music); - // music.play(); - FlxG.sound.playMusic(Paths.music('freakyMenu'), 0); - - FlxG.sound.music.fadeIn(4, 0, 0.7); - } - - Conductor.changeBPM(102); - persistentUpdate = true; - - var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); - // bg.antialiasing = true; - // bg.setGraphicSize(Std.int(bg.width * 0.6)); - // bg.updateHitbox(); - add(bg); - - logoBl = new FlxSprite(-150, -100); - logoBl.frames = Paths.getSparrowAtlas('logoBumpin'); - logoBl.antialiasing = true; - logoBl.animation.addByPrefix('bump', 'logo bumpin', 24); - logoBl.animation.play('bump'); - logoBl.updateHitbox(); - // logoBl.screenCenter(); - // logoBl.color = FlxColor.BLACK; - - gfDance = new FlxSprite(FlxG.width * 0.4, FlxG.height * 0.07); - gfDance.frames = Paths.getSparrowAtlas('gfDanceTitle'); - gfDance.animation.addByIndices('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false); - gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false); - gfDance.antialiasing = true; - add(gfDance); - add(logoBl); - - titleText = new FlxSprite(100, FlxG.height * 0.8); - titleText.frames = Paths.getSparrowAtlas('titleEnter'); - titleText.animation.addByPrefix('idle', "Press Enter to Begin", 24); - titleText.animation.addByPrefix('press', "ENTER PRESSED", 24); - titleText.antialiasing = true; - titleText.animation.play('idle'); - titleText.updateHitbox(); - // titleText.screenCenter(X); - add(titleText); - - var logo:FlxSprite = new FlxSprite().loadGraphic(Paths.image('logo')); - logo.screenCenter(); - logo.antialiasing = true; - // add(logo); - - // FlxTween.tween(logoBl, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG}); - // FlxTween.tween(logo, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG, startDelay: 0.1}); - - credGroup = new FlxGroup(); - add(credGroup); - textGroup = new FlxGroup(); - - blackScreen = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); - credGroup.add(blackScreen); - - credTextShit = new Alphabet(0, 0, "ninjamuffin99\nPhantomArcade\nkawaisprite\nevilsk8er", true); - credTextShit.screenCenter(); - - // credTextShit.alignment = CENTER; - - credTextShit.visible = false; - - ngSpr = new FlxSprite(0, FlxG.height * 0.52).loadGraphic(Paths.image('newgrounds_logo')); - add(ngSpr); - ngSpr.visible = false; - ngSpr.setGraphicSize(Std.int(ngSpr.width * 0.8)); - ngSpr.updateHitbox(); - ngSpr.screenCenter(X); - ngSpr.antialiasing = true; - - FlxTween.tween(credTextShit, {y: credTextShit.y + 20}, 2.9, {ease: FlxEase.quadInOut, type: PINGPONG}); - - FlxG.mouse.visible = false; - - if (initialized) - skipIntro(); - else - initialized = true; - - // credGroup.add(credTextShit); - } - - function getIntroTextShit():Array> - { - var fullText:String = Assets.getText(Paths.txt('introText')); - - var firstArray:Array = fullText.split('\n'); - var swagGoodArray:Array> = []; - - for (i in firstArray) - { - swagGoodArray.push(i.split('--')); - } - - return swagGoodArray; - } - - var transitioning:Bool = false; - - override function update(elapsed:Float) - { - if (FlxG.sound.music != null) - Conductor.songPosition = FlxG.sound.music.time; - // FlxG.watch.addQuick('amp', FlxG.sound.music.amplitude); - - if (FlxG.keys.justPressed.F) - { - FlxG.fullscreen = !FlxG.fullscreen; - } - - var pressedEnter:Bool = FlxG.keys.justPressed.ENTER; - - #if mobile - for (touch in FlxG.touches.list) - { - if (touch.justPressed) - { - pressedEnter = true; - } - } - #end - - var gamepad:FlxGamepad = FlxG.gamepads.lastActive; - - if (gamepad != null) - { - if (gamepad.justPressed.START) - pressedEnter = true; - - #if switch - if (gamepad.justPressed.B) - pressedEnter = true; - #end - } - - if (pressedEnter && !transitioning && skippedIntro) - { - #if !switch - NGio.unlockMedal(60960); - - // If it's Friday according to da clock - if (Date.now().getDay() == 5) - NGio.unlockMedal(61034); - #end - - titleText.animation.play('press'); - - FlxG.camera.flash(FlxColor.WHITE, 1); - FlxG.sound.play(Paths.sound('confirmMenu'), 0.7); - - transitioning = true; - // FlxG.sound.music.stop(); - - new FlxTimer().start(2, function(tmr:FlxTimer) - { - - // Get current version of Kade Engine - - var http = new haxe.Http("https://raw.githubusercontent.com/KadeDev/Kade-Engine/master/version.downloadMe"); - - http.onData = function (data:String) { - - if (!MainMenuState.kadeEngineVer.contains(data.trim()) && !OutdatedSubState.leftState && MainMenuState.nightly == "") - { - trace('outdated lmao! ' + data.trim() + ' != ' + MainMenuState.kadeEngineVer); - OutdatedSubState.needVer = data; - FlxG.switchState(new OutdatedSubState()); - } - else - { - FlxG.switchState(new MainMenuState()); - } - } - - http.onError = function (error) { - trace('error: $error'); - FlxG.switchState(new MainMenuState()); // fail but we go anyway - } - - http.request(); - - }); - // FlxG.sound.play(Paths.music('titleShoot'), 0.7); - } - - if (pressedEnter && !skippedIntro && initialized) - { - skipIntro(); - } - - super.update(elapsed); - } - - function createCoolText(textArray:Array) - { - for (i in 0...textArray.length) - { - var money:Alphabet = new Alphabet(0, 0, textArray[i], true, false); - money.screenCenter(X); - money.y += (i * 60) + 200; - credGroup.add(money); - textGroup.add(money); - } - } - - function addMoreText(text:String) - { - var coolText:Alphabet = new Alphabet(0, 0, text, true, false); - coolText.screenCenter(X); - coolText.y += (textGroup.length * 60) + 200; - credGroup.add(coolText); - textGroup.add(coolText); - } - - function deleteCoolText() - { - while (textGroup.members.length > 0) - { - credGroup.remove(textGroup.members[0], true); - textGroup.remove(textGroup.members[0], true); - } - } - - override function beatHit() - { - super.beatHit(); - - logoBl.animation.play('bump'); - danceLeft = !danceLeft; - - if (danceLeft) - gfDance.animation.play('danceRight'); - else - gfDance.animation.play('danceLeft'); - - FlxG.log.add(curBeat); - - switch (curBeat) - { - case 1: - createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']); - // credTextShit.visible = true; - case 3: - addMoreText('present'); - // credTextShit.text += '\npresent...'; - // credTextShit.addText(); - case 4: - deleteCoolText(); - // credTextShit.visible = false; - // credTextShit.text = 'In association \nwith'; - // credTextShit.screenCenter(); - case 5: - if (Main.watermarks) - createCoolText(['Kade Engine', 'by']); - else - createCoolText(['In Partnership', 'with']); - case 7: - if (Main.watermarks) - addMoreText('KadeDeveloper'); - else - { - addMoreText('Newgrounds'); - ngSpr.visible = true; - } - // credTextShit.text += '\nNewgrounds'; - case 8: - deleteCoolText(); - ngSpr.visible = false; - // credTextShit.visible = false; - - // credTextShit.text = 'Shoutouts Tom Fulp'; - // credTextShit.screenCenter(); - case 9: - createCoolText([curWacky[0]]); - // credTextShit.visible = true; - case 11: - addMoreText(curWacky[1]); - // credTextShit.text += '\nlmao'; - case 12: - deleteCoolText(); - // credTextShit.visible = false; - // credTextShit.text = "Friday"; - // credTextShit.screenCenter(); - case 13: - addMoreText('Friday'); - // credTextShit.visible = true; - case 14: - addMoreText('Night'); - // credTextShit.text += '\nNight'; - case 15: - addMoreText('Funkin'); // credTextShit.text += '\nFunkin'; - - case 16: - skipIntro(); - } - } - - var skippedIntro:Bool = false; - - function skipIntro():Void - { - if (!skippedIntro) - { - remove(ngSpr); - - FlxG.camera.flash(FlxColor.WHITE, 4); - remove(credGroup); - skippedIntro = true; - } - } -} +package; + +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.FlxState; +import flixel.addons.display.FlxGridOverlay; +import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond; +import flixel.addons.transition.FlxTransitionableState; +import flixel.addons.transition.TransitionData; +import flixel.graphics.FlxGraphic; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.group.FlxGroup; +import flixel.input.gamepad.FlxGamepad; +import flixel.math.FlxPoint; +import flixel.math.FlxRect; +import flixel.system.FlxSound; +import flixel.system.ui.FlxSoundTray; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxTimer; +import io.newgrounds.NG; +import lime.app.Application; +import openfl.Assets; + +#if windows +import Discord.DiscordClient; +#end + +#if cpp +import sys.thread.Thread; +#end + +using StringTools; + +class TitleState extends MusicBeatState +{ + static var initialized:Bool = false; + + var blackScreen:FlxSprite; + var credGroup:FlxGroup; + var credTextShit:Alphabet; + var textGroup:FlxGroup; + var ngSpr:FlxSprite; + + var curWacky:Array = []; + + var wackyImage:FlxSprite; + + override public function create():Void + { + #if polymod + polymod.Polymod.init({modRoot: "mods", dirs: ['introMod']}); + #end + + #if sys + if (!sys.FileSystem.exists(Sys.getCwd() + "/assets/replays")) + sys.FileSystem.createDirectory(Sys.getCwd() + "/assets/replays"); + #end + + @:privateAccess + { + trace("Loaded " + openfl.Assets.getLibrary("default").assetsLoaded + " assets (DEFAULT)"); + } + + PlayerSettings.init(); + + #if windows + DiscordClient.initialize(); + + Application.current.onExit.add (function (exitCode) { + DiscordClient.shutdown(); + }); + + #end + + curWacky = FlxG.random.getObject(getIntroTextShit()); + + // DEBUG BULLSHIT + + super.create(); + + // NGio.noLogin(APIStuff.API); + + #if ng + var ng:NGio = new NGio(APIStuff.API, APIStuff.EncKey); + trace('NEWGROUNDS LOL'); + #end + + FlxG.save.bind('funkin', 'ninjamuffin99'); + + KadeEngineData.initSave(); + + Highscore.load(); + + if (FlxG.save.data.weekUnlocked != null) + { + // FIX LATER!!! + // WEEK UNLOCK PROGRESSION!! + // StoryMenuState.weekUnlocked = FlxG.save.data.weekUnlocked; + + if (StoryMenuState.weekUnlocked.length < 4) + StoryMenuState.weekUnlocked.insert(0, true); + + // QUICK PATCH OOPS! + if (!StoryMenuState.weekUnlocked[0]) + StoryMenuState.weekUnlocked[0] = true; + } + + #if FREEPLAY + FlxG.switchState(new FreeplayState()); + #elseif CHARTING + FlxG.switchState(new ChartingState()); + #else + new FlxTimer().start(1, function(tmr:FlxTimer) + { + startIntro(); + }); + #end + } + + var logoBl:FlxSprite; + var gfDance:FlxSprite; + var danceLeft:Bool = false; + var titleText:FlxSprite; + + function startIntro() + { + if (!initialized) + { + var diamond:FlxGraphic = FlxGraphic.fromClass(GraphicTransTileDiamond); + diamond.persist = true; + diamond.destroyOnNoUse = false; + + FlxTransitionableState.defaultTransIn = new TransitionData(FADE, FlxColor.BLACK, 1, new FlxPoint(0, -1), {asset: diamond, width: 32, height: 32}, + new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4)); + FlxTransitionableState.defaultTransOut = new TransitionData(FADE, FlxColor.BLACK, 0.7, new FlxPoint(0, 1), + {asset: diamond, width: 32, height: 32}, new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4)); + + transIn = FlxTransitionableState.defaultTransIn; + transOut = FlxTransitionableState.defaultTransOut; + + // HAD TO MODIFY SOME BACKEND SHIT + // IF THIS PR IS HERE IF ITS ACCEPTED UR GOOD TO GO + // https://github.com/HaxeFlixel/flixel-addons/pull/348 + + // var music:FlxSound = new FlxSound(); + // music.loadStream(Paths.music('freakyMenu')); + // FlxG.sound.list.add(music); + // music.play(); + FlxG.sound.playMusic(Paths.music('freakyMenu'), 0); + + FlxG.sound.music.fadeIn(4, 0, 0.7); + } + + Conductor.changeBPM(102); + persistentUpdate = true; + + var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); + // bg.antialiasing = true; + // bg.setGraphicSize(Std.int(bg.width * 0.6)); + // bg.updateHitbox(); + add(bg); + + logoBl = new FlxSprite(-150, -100); + logoBl.frames = Paths.getSparrowAtlas('logoBumpin'); + logoBl.antialiasing = true; + logoBl.animation.addByPrefix('bump', 'logo bumpin', 24); + logoBl.animation.play('bump'); + logoBl.updateHitbox(); + // logoBl.screenCenter(); + // logoBl.color = FlxColor.BLACK; + + gfDance = new FlxSprite(FlxG.width * 0.4, FlxG.height * 0.07); + gfDance.frames = Paths.getSparrowAtlas('gfDanceTitle'); + gfDance.animation.addByIndices('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false); + gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false); + gfDance.antialiasing = true; + add(gfDance); + add(logoBl); + + titleText = new FlxSprite(100, FlxG.height * 0.8); + titleText.frames = Paths.getSparrowAtlas('titleEnter'); + titleText.animation.addByPrefix('idle', "Press Enter to Begin", 24); + titleText.animation.addByPrefix('press', "ENTER PRESSED", 24); + titleText.antialiasing = true; + titleText.animation.play('idle'); + titleText.updateHitbox(); + // titleText.screenCenter(X); + add(titleText); + + var logo:FlxSprite = new FlxSprite().loadGraphic(Paths.image('logo')); + logo.screenCenter(); + logo.antialiasing = true; + // add(logo); + + // FlxTween.tween(logoBl, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG}); + // FlxTween.tween(logo, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG, startDelay: 0.1}); + + credGroup = new FlxGroup(); + add(credGroup); + textGroup = new FlxGroup(); + + blackScreen = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); + credGroup.add(blackScreen); + + credTextShit = new Alphabet(0, 0, "ninjamuffin99\nPhantomArcade\nkawaisprite\nevilsk8er", true); + credTextShit.screenCenter(); + + // credTextShit.alignment = CENTER; + + credTextShit.visible = false; + + ngSpr = new FlxSprite(0, FlxG.height * 0.52).loadGraphic(Paths.image('newgrounds_logo')); + add(ngSpr); + ngSpr.visible = false; + ngSpr.setGraphicSize(Std.int(ngSpr.width * 0.8)); + ngSpr.updateHitbox(); + ngSpr.screenCenter(X); + ngSpr.antialiasing = true; + + FlxTween.tween(credTextShit, {y: credTextShit.y + 20}, 2.9, {ease: FlxEase.quadInOut, type: PINGPONG}); + + FlxG.mouse.visible = false; + + if (initialized) + skipIntro(); + else + initialized = true; + + // credGroup.add(credTextShit); + } + + function getIntroTextShit():Array> + { + var fullText:String = Assets.getText(Paths.txt('introText')); + + var firstArray:Array = fullText.split('\n'); + var swagGoodArray:Array> = []; + + for (i in firstArray) + { + swagGoodArray.push(i.split('--')); + } + + return swagGoodArray; + } + + var transitioning:Bool = false; + + override function update(elapsed:Float) + { + if (FlxG.sound.music != null) + Conductor.songPosition = FlxG.sound.music.time; + // FlxG.watch.addQuick('amp', FlxG.sound.music.amplitude); + + if (FlxG.keys.justPressed.F) + { + FlxG.fullscreen = !FlxG.fullscreen; + } + + var pressedEnter:Bool = FlxG.keys.justPressed.ENTER; + + #if mobile + for (touch in FlxG.touches.list) + { + if (touch.justPressed) + { + pressedEnter = true; + } + } + #end + + var gamepad:FlxGamepad = FlxG.gamepads.lastActive; + + if (gamepad != null) + { + if (gamepad.justPressed.START) + pressedEnter = true; + + #if switch + if (gamepad.justPressed.B) + pressedEnter = true; + #end + } + + if (pressedEnter && !transitioning && skippedIntro) + { + #if !switch + NGio.unlockMedal(60960); + + // If it's Friday according to da clock + if (Date.now().getDay() == 5) + NGio.unlockMedal(61034); + #end + + if (FlxG.save.data.flashing) + titleText.animation.play('press'); + + FlxG.camera.flash(FlxColor.WHITE, 1); + FlxG.sound.play(Paths.sound('confirmMenu'), 0.7); + + transitioning = true; + // FlxG.sound.music.stop(); + + new FlxTimer().start(2, function(tmr:FlxTimer) + { + // Get current version of Kade Engine + + //var http = new haxe.Http("https://raw.githubusercontent.com/KadeDev/Kade-Engine/master/version.downloadMe"); + var http = new haxe.Http("https://raw.githubusercontent.com/KadeDev/Kade-Engine/patchnotes/version.downloadMe"); + var returnedData:Array = []; + + http.onData = function (data:String) + { + returnedData[0] = data.substring(0, data.indexOf(';')); + returnedData[1] = data.substring(data.indexOf('-'), data.length); + if (!MainMenuState.kadeEngineVer.contains(returnedData[0].trim()) && !OutdatedSubState.leftState && MainMenuState.nightly == "") + { + trace('outdated lmao! ' + returnedData[0] + ' != ' + MainMenuState.kadeEngineVer); + OutdatedSubState.needVer = returnedData[0]; + OutdatedSubState.currChanges = returnedData[1]; + FlxG.switchState(new OutdatedSubState()); + } + else + { + FlxG.switchState(new MainMenuState()); + } + } + + http.onError = function (error) { + trace('error: $error'); + FlxG.switchState(new MainMenuState()); // fail but we go anyway + } + + http.request(); + }); + // FlxG.sound.play(Paths.music('titleShoot'), 0.7); + } + + if (pressedEnter && !skippedIntro && initialized) + { + skipIntro(); + } + + super.update(elapsed); + } + + function createCoolText(textArray:Array) + { + for (i in 0...textArray.length) + { + var money:Alphabet = new Alphabet(0, 0, textArray[i], true, false); + money.screenCenter(X); + money.y += (i * 60) + 200; + credGroup.add(money); + textGroup.add(money); + } + } + + function addMoreText(text:String) + { + var coolText:Alphabet = new Alphabet(0, 0, text, true, false); + coolText.screenCenter(X); + coolText.y += (textGroup.length * 60) + 200; + credGroup.add(coolText); + textGroup.add(coolText); + } + + function deleteCoolText() + { + while (textGroup.members.length > 0) + { + credGroup.remove(textGroup.members[0], true); + textGroup.remove(textGroup.members[0], true); + } + } + + override function beatHit() + { + super.beatHit(); + + logoBl.animation.play('bump'); + danceLeft = !danceLeft; + + if (danceLeft) + gfDance.animation.play('danceRight'); + else + gfDance.animation.play('danceLeft'); + + FlxG.log.add(curBeat); + + switch (curBeat) + { + case 1: + createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']); + // credTextShit.visible = true; + case 3: + addMoreText('present'); + // credTextShit.text += '\npresent...'; + // credTextShit.addText(); + case 4: + deleteCoolText(); + // credTextShit.visible = false; + // credTextShit.text = 'In association \nwith'; + // credTextShit.screenCenter(); + case 5: + if (Main.watermarks) + createCoolText(['Kade Engine', 'by']); + else + createCoolText(['In Partnership', 'with']); + case 7: + if (Main.watermarks) + addMoreText('KadeDeveloper'); + else + { + addMoreText('Newgrounds'); + ngSpr.visible = true; + } + // credTextShit.text += '\nNewgrounds'; + case 8: + deleteCoolText(); + ngSpr.visible = false; + // credTextShit.visible = false; + + // credTextShit.text = 'Shoutouts Tom Fulp'; + // credTextShit.screenCenter(); + case 9: + createCoolText([curWacky[0]]); + // credTextShit.visible = true; + case 11: + addMoreText(curWacky[1]); + // credTextShit.text += '\nlmao'; + case 12: + deleteCoolText(); + // credTextShit.visible = false; + // credTextShit.text = "Friday"; + // credTextShit.screenCenter(); + case 13: + addMoreText('Friday'); + // credTextShit.visible = true; + case 14: + addMoreText('Night'); + // credTextShit.text += '\nNight'; + case 15: + addMoreText('Funkin'); // credTextShit.text += '\nFunkin'; + + case 16: + skipIntro(); + } + } + + var skippedIntro:Bool = false; + + function skipIntro():Void + { + if (!skippedIntro) + { + remove(ngSpr); + + FlxG.camera.flash(FlxColor.WHITE, 4); + remove(credGroup); + skippedIntro = true; + } + } +}