Merge branch 'rewrite/master' into bugfix/nene-pico-offsets

This commit is contained in:
Cameron Taylor 2024-08-27 14:40:56 -04:00
commit ce62c240fa
27 changed files with 1435 additions and 620 deletions

4
.gitattributes vendored
View file

@ -1 +1,3 @@
* text=auto eol=lf
* text=auto eol=lf
*.hxc linguist-language=Haxe
*.hxp linguist-language=Haxe

1
.github/labeler.yml vendored
View file

@ -1,7 +1,6 @@
# Add Documentation tag to PR's changing markdown files, or anyhting in the docs folder
Documentation:
- changed-files:
- any-glob-to-any-file:
- any-glob-to-any-file:
- docs/*
- '**/*.md'

30
.vscode/settings.json vendored
View file

@ -94,12 +94,12 @@
{
"label": "Windows / Debug",
"target": "windows",
"args": ["-debug", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Linux / Debug",
"target": "linux",
"args": ["-debug", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug",
@ -109,7 +109,7 @@
{
"label": "Windows / Debug (FlxAnimate Test)",
"target": "windows",
"args": ["-debug", "-DANIMATE", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DANIMATE", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug (FlxAnimate Test)",
@ -119,7 +119,7 @@
{
"label": "Windows / Debug (Straight to Freeplay)",
"target": "windows",
"args": ["-debug", "-DFREEPLAY", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DFREEPLAY", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug (Straight to Freeplay)",
@ -132,13 +132,13 @@
"args": [
"-debug",
"-DSONG=bopeebo -DDIFFICULTY=normal",
"-DFORCE_DEBUG_VERSION"
"-DFEATURE_DEBUG_FUNCTIONS"
]
},
{
"label": "Windows / Debug (Straight to Play - 2hot)",
"target": "windows",
"args": ["-debug", "-DSONG=2hot", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DSONG=2hot", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug (Straight to Play - Bopeebo Normal)",
@ -148,7 +148,7 @@
{
"label": "Windows / Debug (Conversation Test)",
"target": "windows",
"args": ["-debug", "-DDIALOGUE", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DDIALOGUE", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug (Conversation Test)",
@ -163,7 +163,7 @@
{
"label": "Windows / Debug (Straight to Chart Editor)",
"target": "windows",
"args": ["-debug", "-DCHARTING", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DCHARTING", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug (Straight to Chart Editor)",
@ -173,12 +173,12 @@
{
"label": "Windows / Debug (Straight to Animation Editor)",
"target": "windows",
"args": ["-debug", "-DANIMDEBUG", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DANIMDEBUG", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Windows / Debug (Debug hxCodec)",
"target": "windows",
"args": ["-debug", "-DHXC_LIBVLC_LOGGING", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DHXC_LIBVLC_LOGGING", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug (Straight to Animation Editor)",
@ -188,7 +188,7 @@
{
"label": "Windows / Debug (Latency Test)",
"target": "windows",
"args": ["-debug", "-DLATENCY", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DLATENCY", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HashLink / Debug (Latency Test)",
@ -198,7 +198,7 @@
{
"label": "Windows / Debug (Waveform Test)",
"target": "windows",
"args": ["-debug", "-DWAVEFORM", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DWAVEFORM", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "Windows / Release",
@ -218,17 +218,17 @@
{
"label": "HTML5 / Debug",
"target": "html5",
"args": ["-debug", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "HTML5 / Debug (Watch)",
"target": "html5",
"args": ["-debug", "-watch", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-watch", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "macOS / Debug",
"target": "mac",
"args": ["-debug", "-DFORCE_DEBUG_VERSION"]
"args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"]
},
{
"label": "macOS / Release",

View file

@ -4,6 +4,62 @@ All notable changes will be documented in this file.
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).
## [0.5.0] - 2024-08-??
### Added
- Added a new Character Select screen to switch between playable characters in Freeplay
- Modding isn't 100% there but we're working on it!
- Added Pico as a playable character! Unlock him by completing Weekend 1 (if you haven't already done that)
- The songs from Weekend 1 have moved; you must now switch to Pico in Freeplay to access them
- Added ## new Pico remixes! Access them by selecting Pico from in the Character Select screen
- Added 2 new Erect remixes! Access them by switching difficulty on the song
- Implemented support for a new Instrumental Selector in Freeplay
- Beating a Pico remix lets you use that instrumental when playing as Boyfriend
- Added the first batch of Erect Stages! These graphical overhauls of the original stages will be used when playing Erect remixes and Pico remixes
- Implemented support for scripted Note Kinds. You can use HScript define a different note style to display for these notes as well as custom behavior. (community feature by lemz1)
- Implemented a new Strumline Background option, to display a darkened background behind the strumline with your choice of opacity.
- Implemented support for Numeric and Selector options in the Options menu. (community feature by FlooferLand)
## Changed
- Girlfriend and Nene now perform previously unused animations when you achieve a large combo, or drop a large combo.
- The pixel character icons in the Freeplay menu now display an animation!
- Altered how Week 6 displays sprites to make things look more retro.
- Character offsets are now independent of the character's scale.
- This should resolve issues with offsets when porting characters from older mods.
- Pixel character offsets have been modified to compensate.
- Note style data can now specify custom combo count graphics, judgement graphics, countdown graphics, and countdown audio. (community feature by anysad)
- These were previously using hardcoded values based on whether the stage was `school` or `schoolEvil`.
- The `danceEvery` property of characters and stage props can now use values with a precision of `0.25`, to play their idle animation up to four times per beat.
- Reworked the JSON merging system in Polymod; you can now include JSONPatch files under `_merge` in your mod folder to add, modify, or remove values in a JSON without replacing it entirely!
- Cutscenes now automatically pause when tabbing out (community fix by AbnormalPoof)
- Characters will now respect the `danceEvery` property (community fix by gamerbross)
- The F5 function now reloads the current song's chart data from disc (community feature by gamerbross)
- Refactored the compilation guide and added common troubleshooting steps (community fix by Hundrec)
- Made several layout improvements and fixes to the Animation Offsets editor in the Debug menu (community fix by gamerbross)
- Fixed a bug where the Back sound would be not played when leaving the Story menu and Options menu (community fix by AppleHair)
- Animation offsets no longer directly modify the `x` and `y` position of props, which makes props work better with tweens (community fix by Sword352)
- The YEAH! events in Tutorial now use chart events rather than being hard-coded (community fix by anysad)
- The player's Score now displays commas in it (community fix by loggo)
## Fixed
- Fixed an issue where songs with no notes would crash on the Results screen.
- Fixed an issue where the old icon easter egg would not work properly on pixel levels.
- Fixed an issue where you could play notes during the Thorns cutscene.
- Fixed an issue where the Heart icon when favoriting a song in Freeplay would be malformed.
- Fixed an issue where Pico's death animation displays a faint blue background (community fix by doggogit)
- Fixed an issue where mod songs would not play a preview in the Freeplay menu (community fix by KarimAkra)
- Fixed an issue where the Memory Usage counter could overflow and display a negative number (community fix by KarimAkra)
- Fixed an issue where pressing the Chart Editor keybind while playtesting a chart would reset the chart editor (community fix by gamerbross)
- Fixed a crash bug when pressing F5 after seeing the sticker transition (community fix by gamerbross)
- Fixed an issue where the Story Mode menu couldn't be scrolled with a mouse (community fix by JVNpixels)
- Fixed an issue causing the song to majorly desync sometimes (community fix by Burgerballs)
- Fixed an issue where the Freeplay song preview would not respect the instrumental ID specified in the song metadata (community fix by AppleHair)
- Fixed an issue where Tankman's icon wouldn't display in the Chart Editor (community fix by hundrec)
- Fixed an issue where pausing the game during a camera zoom would zoom the pause menu. (community fix by gamerbros)
- Fixed an issue where certain UI elements would not flash at a consistent rate (community fix by cyn0x8)
- Fixed an issue where the game would not use the placeholder health icon as a fallback (community fix by gamerbross)
- Fixed an issue where the chart editor could get stuck creating a hold note when using Live Inputs (community fix by gamerbross)
- Fixed an issue where character graphics could not be placed in week folders (community fix by 7oltan)
- Fixed a crash issue when a Freeplay song has no `Normal` difficulty (community fix by Applehair and gamerbross)
- Fixed an issue in Story Mode where a song that isn't valid for the current variation could be selected (community fix by Applehair)
## [0.4.1] - 2024-06-12
### Added
- Pressing ESCAPE on the title screen on desktop now exits the game, allowing you to exit the game while in fullscreen on desktop

View file

@ -1,266 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://lime.openfl.org/project/1.0.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://lime.openfl.org/project/1.0.4 http://lime.openfl.org/xsd/project-1.0.4.xsd">
<!-- _________________________ Application Settings _________________________ -->
<app title="Friday Night Funkin'" file="Funkin" packageName="com.funkin.fnf" package="com.funkin.fnf" main="Main" version="0.5.0" company="ninjamuffin99" />
<!--Switch Export with Unique ApplicationID and Icon-->
<set name="APP_ID" value="0x0100f6c013bbc000" />
<!--
Define the OpenFL sprite which displays the preloader.
You can't replace the preloader's logic here, sadly, but you can extend it.
Basic preloading logic is done by `openfl.display.Preloader`.
-->
<app preloader="funkin.ui.transition.preload.FunkinPreloader" />
<!--Minimum without FLX_NO_GAMEPAD: 11.8, without FLX_NO_NATIVE_CURSOR: 11.2-->
<set name="SWF_VERSION" value="11.8" />
<!-- ____________________________ Window Settings ___________________________ -->
<!--These window settings apply to all targets-->
<window width="1280" height="720" fps="60" background="#000000" hardware="true" vsync="false" />
<!--HTML5-specific-->
<window if="html5" resizable="true" />
<!--Desktop-specific-->
<window if="desktop" orientation="landscape" fullscreen="false" resizable="true" vsync="false" />
<!--Mobile-specific-->
<window if="mobile" orientation="landscape" fullscreen="true" width="0" height="0" resizable="false" />
<!-- _____________________________ Path Settings ____________________________ -->
<set name="BUILD_DIR" value="export/debug" if="debug" />
<set name="BUILD_DIR" value="export/release" unless="debug" />
<set name="BUILD_DIR" value="export/32bit" if="32bit" />
<source path="source" />
<assets path="assets/preload" rename="assets" exclude="*.ogg|*.wav" if="web" />
<assets path="assets/preload" rename="assets" exclude="*.mp3|*.wav" unless="web" />
<define name="PRELOAD_ALL" unless="web" />
<define name="NO_PRELOAD_ALL" unless="PRELOAD_ALL" />
<section if="PRELOAD_ALL">
<library name="songs" preload="true" />
<library name="shared" preload="true" />
<library name="tutorial" preload="true" />
<library name="week1" preload="true" />
<library name="week2" preload="true" />
<library name="week3" preload="true" />
<library name="week4" preload="true" />
<library name="week5" preload="true" />
<library name="week6" preload="true" />
<library name="week7" preload="true" />
<library name="weekend1" preload="true" />
<library name="videos" preload="true" />
</section>
<section if="NO_PRELOAD_ALL">
<library name="songs" preload="false" />
<library name="shared" preload="false" />
<library name="tutorial" preload="false" />
<library name="week1" preload="false" />
<library name="week2" preload="false" />
<library name="week3" preload="false" />
<library name="week4" preload="false" />
<library name="week5" preload="false" />
<library name="week6" preload="false" />
<library name="week7" preload="false" />
<library name="weekend1" preload="false" />
<library name="videos" preload="false" />
</section>
<library name="art" preload="false" />
<assets path="assets/songs" library="songs" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/songs" library="songs" exclude="*.fla|*.mp3|*.wav" unless="web" />
<!-- Videos go in their own library because web never needs to preload them, they can just be streamed. -->
<assets path="assets/videos" library="videos" />
<assets path="assets/shared" library="shared" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/shared" library="shared" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/week1" library="week1" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/week1" library="week1" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/week2" library="week2" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/week2" library="week2" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/week3" library="week3" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/week3" library="week3" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/week4" library="week4" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/week4" library="week4" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/week5" library="week5" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/week5" library="week5" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/week6" library="week6" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/week6" library="week6" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/week7" library="week7" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/week7" library="week7" exclude="*.fla|*.mp3|*.wav" unless="web" />
<assets path="assets/weekend1" library="weekend1" exclude="*.fla|*.ogg|*.wav" if="web" />
<assets path="assets/weekend1" library="weekend1" exclude="*.fla|*.mp3|*.wav" unless="web" />
<!-- <assets path='example_mods' rename='mods' embed='false'/> -->
<!--
AUTOMATICALLY MOVING EXAMPLE MODS INTO THE BUILD CAUSES ISSUES
Currently, this line will add the mod files to the library manifest,
which causes issues if the mod is not enabled.
If we can exclude the `mods` folder from the manifest, we can re-enable this line.
<assets path='example_mods' rename='mods' embed='false' exclude="*.md" />
-->
<assets path="art/readme.txt" rename="do NOT readme.txt" library="art"/>
<assets path="CHANGELOG.md" rename="changelog.txt" library="art"/>
<!-- NOTE FOR FUTURE SELF SINCE FONTS ARE ALWAYS FUCKY
TO FIX ONE OF THEM, I CONVERTED IT TO OTF. DUNNO IF YOU NEED TO
THEN UHHH I USED THE NAME OF THE FONT WITH SETFORMAT() ON THE TEXT!!!
NOT USING A DIRECT THING TO THE ASSET!!!
-->
<assets path="assets/fonts" embed="true" />
<!-- If compiled via github actions, show debug version number. -->
<define name="FORCE_DEBUG_VERSION" if="GITHUB_BUILD" />
<define name="NO_REDIRECT_ASSETS_FOLDER" if="GITHUB_BUILD" />
<define name="TOUCH_HERE_TO_PLAY" if="web" />
<!-- _______________________________ Libraries ______________________________ -->
<haxelib name="lime" /> <!-- Game engine backend -->
<haxelib name="openfl" /> <!-- Game engine backend -->
<haxelib name="flixel" /> <!-- Game engine -->
<haxelib name="flixel-addons" /> <!-- Additional utilities for Flixel -->
<haxelib name="hscript" /> <!-- Scripting -->
<haxelib name="haxeui-core" /> <!-- UI framework -->
<haxelib name="haxeui-flixel" /> <!-- Integrate HaxeUI with Flixel -->
<haxelib name="flixel-text-input" /> <!-- Improved text field rendering for HaxeUI -->
<haxelib name="polymod" /> <!-- Modding framework -->
<haxelib name="flxanimate" /> <!-- Texture atlas rendering -->
<haxelib name="hxCodec" if="desktop" unless="hl" /> <!-- Video playback -->
<haxelib name="funkin.vis"/>
<haxelib name="grig.audio" />
<haxelib name="FlxPartialSound" /> <!-- Loading partial sound data -->
<haxelib name="json2object" /> <!-- JSON parsing -->
<haxelib name="thx.core" /> <!-- General utility library, "the lodash of Haxe" -->
<haxelib name="thx.semver" /> <!-- Version string handling -->
<haxelib name="hxcpp-debug-server" if="desktop debug" /> <!-- VSCode debug support -->
<!--Disable the Flixel core focus lost screen-->
<haxedef name="FLX_NO_FOCUS_LOST_SCREEN" />
<!--Disable the Flixel core debugger. Automatically gets set whenever you compile in release mode!-->
<haxedef name="FLX_NO_DEBUG" unless="debug || FORCE_DEBUG_VERSION" />
<!--Enable this for Nape release builds for a serious peformance improvement-->
<haxedef name="NAPE_RELEASE_BUILD" unless="debug" />
<!--
Hide deprecation warnings until they're fixed.
TODO: REMOVE THIS!!!!
<haxeflag name="-w" value="-WDeprecated" />
-->
<!-- Haxe 4.3.0+: Enable pretty syntax errors and stuff. -->
<haxedef name="message.reporting" value="pretty" />
<!-- _________________________________ Custom _______________________________ -->
<!-- Disable trace() calls in release builds to bump up performance.
<haxeflag name="- -no-traces" unless="debug" />-->
<!-- HScript relies heavily on Reflection, which means we can't use DCE. -->
<haxeflag name="-dce no" />
<!-- Ensure all Funkin' classes are available at runtime. -->
<haxeflag name="--macro" value="include('funkin')" />
<!-- Ensure all UI components are available at runtime. -->
<haxeflag name="--macro" value="include('haxe.ui.backend.flixel.components')" />
<haxeflag name="--macro" value="include('haxe.ui.containers.dialogs')" />
<haxeflag name="--macro" value="include('haxe.ui.containers.menus')" />
<haxeflag name="--macro" value="include('haxe.ui.containers.properties')" />
<haxeflag name="--macro" value="include('haxe.ui.core')" />
<haxeflag name="--macro" value="include('haxe.ui.components')" />
<haxeflag name="--macro" value="include('haxe.ui.containers')" />
<!--
Ensure additional class packages are available at runtime (some only really used by scripts).
Ignore packages we can't include.
-->
<haxeflag name="--macro" value="include('flixel', true, [ 'flixel.addons.editors.spine.*', 'flixel.addons.nape.*', 'flixel.system.macros.*' ])" />
<!-- Necessary to provide stack traces for HScript. -->
<haxedef name="hscriptPos" />
<haxedef name="safeMode"/>
<haxedef name="HXCPP_CHECK_POINTER" />
<haxedef name="HXCPP_STACK_LINE" />
<haxedef name="HXCPP_STACK_TRACE" />
<!-- This macro allows addition of new functionality to existing Flixel. -->
<haxeflag name="--macro" value="addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxBasic())', 'flixel.FlxBasic')" />
<!--Place custom nodes like icons here (higher priority to override the HaxeFlixel icon)-->
<icon path="art/icon16.png" size="16" />
<icon path="art/icon32.png" size="32" />
<icon path="art/icon64.png" size="64" />
<icon path="art/iconOG.png" />
<haxedef name="CAN_OPEN_LINKS" unless="switch" />
<haxedef name="CAN_CHEAT" if="switch debug" />
<!-- I don't remember what this is for. -->
<haxedef name="haxeui_no_mouse_reset" />
<!-- Clicking outside a dialog should deselect the current focused component. -->
<haxedef name="haxeui_focus_out_on_click" />
<!-- Required to use haxe.ui.backend.flixel.UIState with build macros. -->
<haxedef name="haxeui_dont_impose_base_class" />
<haxedef name="HARDCODED_CREDITS" />
<!-- Skip the Intro -->
<section if="debug">
<!-- Starts the game at the specified week, at the first song -->
<!-- <haxedef name="week" value="1" if="debug"/> -->
<!-- Starts the game at the specified song -->
<!-- <haxedef name="song" value="bopeebo" if="debug"/> -->
<!-- Difficulty, only used for week or song, defaults to 1 -->
<!-- <haxedef name="dif" value="2" if="debug"/> -->
</section>
<section if="newgrounds">
<!-- Enables Ng.core.verbose -->
<!-- <haxedef name="NG_VERBOSE" /> -->
<!-- Enables a NG debug session, so medals don't permently unlock -->
<!-- <haxedef name="NG_DEBUG" /> -->
<!-- pretends that the saved session Id was expired, forcing the reconnect prompt -->
<!-- <haxedef name="NG_FORCE_EXPIRED_SESSION" if="debug" /> -->
</section>
<!-- Uncomment this to wipe your input settings. -->
<!-- <haxedef name="CLEAR_INPUT_SAVE"/> -->
<section if="debug" unless="NO_REDIRECT_ASSETS_FOLDER || html5 || GITHUB_BUILD">
<!--
Use the parent assets folder rather than the exported one
No more will we accidentally undo our changes!
-->
<haxedef name="REDIRECT_ASSETS_FOLDER" />
</section>
<section>
<!--
This flag enables the popup/crashlog error handler.
However, it also messes with breakpoints on some platforms.
-->
<haxedef name="openfl-enable-handle-error" />
</section>
<!-- Run a script before and after building. -->
<prebuild haxe="source/Prebuild.hx"/> -->
<postbuild haxe="source/Postbuild.hx"/> -->
<!-- Enable this on platforms which do not support dropping files onto the window. -->
<haxedef name="FILE_DROP_UNSUPPORTED" if="mac" />
<section unless="FILE_DROP_UNSUPPORTED">
<haxedef name="FILE_DROP_SUPPORTED" />
</section>
<!-- Enable this on platforms which do not support the edsior views. -->
<haxedef name="CHART_EDITOR_UNSUPPORTED" if="web" />
<haxedef name="CHART_EDITOR_SUPPORTED" unless="web"/>
<!-- Options for Polymod -->
<section if="polymod">
<!-- Turns on additional debug logging. -->
<haxedef name="POLYMOD_DEBUG" value="true" if="debug" />
<!-- The file extension to use for script files. -->
<haxedef name="POLYMOD_SCRIPT_EXT" value=".hscript" />
<!-- Which asset library to use for scripts. -->
<haxedef name="POLYMOD_SCRIPT_LIBRARY" value="scripts" />
<!-- The base path from which scripts should be accessed. -->
<haxedef name="POLYMOD_ROOT_PATH" value="scripts/" />
<!-- Determines the subdirectory of the mod folder used for file appending. -->
<haxedef name="POLYMOD_APPEND_FOLDER" value="_append" />
<!-- Determines the subdirectory of the mod folder used for file merges. -->
<haxedef name="POLYMOD_MERGE_FOLDER" value="_merge" />
<!-- Determines the file in the mod folder used for metadata. -->
<haxedef name="POLYMOD_MOD_METADATA_FILE" value="_polymod_meta.json" />
<!-- Determines the file in the mod folder used for the icon. -->
<haxedef name="POLYMOD_MOD_ICON_FILE" value="_polymod_icon.png" />
</section>
</project>

View file

@ -1,5 +1,12 @@
{
"dependencies": [
{
"name": "FlxPartialSound",
"type": "git",
"dir": null,
"ref": "a1eab7b9bf507b87200a3341719054fe427f3b15",
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
},
{
"name": "discord_rpc",
"type": "git",
@ -32,7 +39,7 @@
"name": "flixel-ui",
"type": "git",
"dir": null,
"ref": "d0afed7293c71ffdb1184751317fc709b44c9056",
"ref": "27f1ba626f80a6282fa8a187115e79a4a2133dc2",
"url": "https://github.com/HaxeFlixel/flixel-ui"
},
{
@ -42,13 +49,6 @@
"ref": "768740a56b26aa0c072720e0d1236b94afe68e3e",
"url": "https://github.com/Dot-Stuff/flxanimate"
},
{
"name": "FlxPartialSound",
"type": "git",
"dir": null,
"ref": "a1eab7b9bf507b87200a3341719054fe427f3b15",
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
},
{
"name": "format",
"type": "haxelib",
@ -59,7 +59,9 @@
"type": "git",
"dir": null,
"ref": "22b1ce089dd924f15cdc4632397ef3504d464e90",
"url": "https://github.com/FunkinCrew/funkVis/"
"url": "https://github.com/FunkinCrew/funkVis"
},
{
"name": "grig.audio",
@ -89,8 +91,10 @@
},
{
"name": "hscript",
"type": "haxelib",
"version": "2.5.0"
"type": "git",
"dir": null,
"ref": "12785398e2f07082f05034cb580682e5671442a2",
"url": "https://github.com/FunkinCrew/hscript"
},
{
"name": "hxCodec",
@ -185,7 +189,7 @@
"name": "polymod",
"type": "git",
"dir": null,
"ref": "98945c6c7f5ecde01a32c4623d3515bf012a023a",
"ref": "96cfc5fa693b017e47f7cb13b765cc68698fa6b6",
"url": "https://github.com/larsiusprime/polymod"
},
{

1109
project.hxp Normal file

File diff suppressed because it is too large Load diff

View file

@ -113,7 +113,7 @@ class Main extends Sprite
addChild(game);
#if debug
#if FEATURE_DEBUG_FUNCTIONS
game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil());
#end

View file

@ -34,7 +34,7 @@ import funkin.util.CLIUtil;
import funkin.util.CLIUtil.CLIParams;
import funkin.util.TimerUtil;
import funkin.util.TrackerUtil;
#if discord_rpc
#if FEATURE_DISCORD_RPC
import Discord.DiscordClient;
#end
@ -123,7 +123,7 @@ class InitState extends FlxState
//
// DISCORD API SETUP
//
#if discord_rpc
#if FEATURE_DISCORD_RPC
DiscordClient.initialize();
Application.current.onExit.add(function(exitCode) {
@ -144,7 +144,7 @@ class InitState extends FlxState
// Plugins provide a useful interface for globally active Flixel objects,
// that receive update events regardless of the current state.
// TODO: Move scripted Module behavior to a Flixel plugin.
#if debug
#if FEATURE_DEBUG_FUNCTIONS
funkin.util.plugins.MemoryGCPlugin.initialize();
#end
funkin.util.plugins.EvacuateDebugPlugin.initialize();
@ -374,11 +374,16 @@ class InitState extends FlxState
//
// FLIXEL DEBUG SETUP
//
#if (debug || FORCE_DEBUG_VERSION)
// Make errors and warnings less annoying.
// Forcing this always since I have never been happy to have the debugger to pop up
#if FEATURE_DEBUG_FUNCTIONS
trace('Initializing Flixel debugger...');
#if !debug
// Make errors less annoying on release builds.
LogStyle.ERROR.openConsole = false;
LogStyle.ERROR.errorSound = null;
#end
// Make errors and warnings less annoying.
LogStyle.WARNING.openConsole = false;
LogStyle.WARNING.errorSound = null;

View file

@ -1,13 +1,13 @@
package funkin.api.discord;
import Sys.sleep;
#if discord_rpc
#if FEATURE_DISCORD_RPC
import discord_rpc.DiscordRpc;
#end
class DiscordClient
{
#if discord_rpc
#if FEATURE_DISCORD_RPC
public function new()
{
trace("Discord Client starting...");

View file

@ -24,7 +24,7 @@ class NGUnsafe
NG.core.calls.event.logEvent(event).send();
trace('should have logged: ' + event);
#else
#if debug
#if FEATURE_DEBUG_FUNCTIONS
trace('event:$event - not logged, missing NG.io lib');
#end
#end
@ -39,7 +39,7 @@ class NGUnsafe
if (!medal.unlocked) medal.sendUnlock();
}
#else
#if debug
#if FEATURE_DEBUG_FUNCTIONS
trace('medal:$id - not unlocked, missing NG.io lib');
#end
#end
@ -63,7 +63,7 @@ class NGUnsafe
}
}
#else
#if debug
#if FEATURE_DEBUG_FUNCTIONS
trace('Song:$song, Score:$score - not posted, missing NG.io lib');
#end
#end

View file

@ -239,7 +239,7 @@ class NGio
NG.core.calls.event.logEvent(event).send();
trace('should have logged: ' + event);
#else
#if debug
#if FEATURE_DEBUG_FUNCTIONS
trace('event:$event - not logged, missing NG.io lib');
#end
#end
@ -254,7 +254,7 @@ class NGio
if (!medal.unlocked) medal.sendUnlock();
}
#else
#if debug
#if FEATURE_DEBUG_FUNCTIONS
trace('medal:$id - not unlocked, missing NG.io lib');
#end
#end
@ -278,7 +278,7 @@ class NGio
}
}
#else
#if debug
#if FEATURE_DEBUG_FUNCTIONS
trace('Song:$song, Score:$score - not posted, missing NG.io lib');
#end
#end

View file

@ -93,9 +93,9 @@ typedef LevelPropData =
* The frequency to bop at, in beats.
* 1 = every beat, 2 = every other beat, etc.
* Supports up to 0.25 precision.
* @default 0.0
* @default 1.0
*/
@:default(0.0)
@:default(1.0)
@:optional
var danceEvery:Float;

View file

@ -21,7 +21,7 @@ class FlxAtlasSprite extends FlxAnimate
FrameRate: 24.0,
Reversed: false,
// ?OnComplete:Void -> Void,
ShowPivot: #if debug false #else false #end,
ShowPivot: false,
Antialiasing: true,
ScrollFactor: null,
// Offset: new FlxPoint(0, 0), // This is just FlxSprite.offset

View file

@ -356,9 +356,10 @@ class Controls extends FlxActionSet
public function check(name:Action, trigger:FlxInputState = JUST_PRESSED, gamepadOnly:Bool = false):Bool
{
#if debug
#if FEATURE_DEBUG_FUNCTIONS
if (!byName.exists(name)) throw 'Invalid name: $name';
#end
var action = byName[name];
if (gamepadOnly) return action.checkFiltered(trigger, GAMEPAD);
else
@ -367,7 +368,7 @@ class Controls extends FlxActionSet
public function getKeysForAction(name:Action):Array<FlxKey>
{
#if debug
#if FEATURE_DEBUG_FUNCTIONS
if (!byName.exists(name)) throw 'Invalid name: $name';
#end
@ -382,7 +383,7 @@ class Controls extends FlxActionSet
public function getButtonsForAction(name:Action):Array<FlxGamepadInputID>
{
#if debug
#if FEATURE_DEBUG_FUNCTIONS
if (!byName.exists(name)) throw 'Invalid name: $name';
#end

View file

@ -28,11 +28,10 @@ class PolymodHandler
{
/**
* The API version that mods should comply with.
* Format this with Semantic Versioning; <MAJOR>.<MINOR>.<PATCH>.
* Bug fixes increment the patch version, new features increment the minor version.
* Changes that break old mods increment the major version.
* Indicates which mods are compatible with this version of the game.
* Minor updates rarely impact mods but major versions often do.
*/
static final API_VERSION:String = '0.1.0';
static final API_VERSION:String = "0.5.0"; // Constants.VERSION;
/**
* Where relative to the executable that mods are located.
@ -178,7 +177,7 @@ class PolymodHandler
loadedModIds.push(mod.id);
}
#if debug
#if FEATURE_DEBUG_FUNCTIONS
var fileList:Array<String> = Polymod.listModFiles(PolymodAssetType.IMAGE);
trace('Installed mods have replaced ${fileList.length} images.');
for (item in fileList)
@ -258,8 +257,29 @@ class PolymodHandler
// Unserializerr.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages
Polymod.blacklistImport('Unserializer');
// `lime.system.CFFI`
// Can load and execute compiled binaries.
Polymod.blacklistImport('lime.system.CFFI');
// `lime.system.JNI`
// Can load and execute compiled binaries.
Polymod.blacklistImport('lime.system.JNI');
// `lime.system.System`
// System.load() can load malicious DLLs
Polymod.blacklistImport('lime.system.System');
// `lime.utils.Assets`
// Literally just has a private `resolveClass` function for some reason?
Polymod.blacklistImport('lime.utils.Assets');
Polymod.blacklistImport('openfl.utils.Assets');
// `openfl.desktop.NativeProcess`
// Can load native processes on the host operating system.
Polymod.blacklistImport('openfl.desktop.NativeProcess');
// `polymod.*`
// You can probably unblacklist a module
// Contains functions which may allow for un-blacklisting other modules.
for (cls in ClassMacro.listClassesInPackage('polymod'))
{
if (cls == null) continue;
@ -268,6 +288,7 @@ class PolymodHandler
}
// `sys.*`
// Access to system utilities such as the file system.
for (cls in ClassMacro.listClassesInPackage('sys'))
{
if (cls == null) continue;

View file

@ -430,7 +430,7 @@ class PauseSubState extends MusicBeatSubState
resume(this);
}
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
// to pause the game and get screenshots easy, press H on pause menu!
if (FlxG.keys.justPressed.H)
{

View file

@ -67,7 +67,7 @@ import lime.ui.Haptic;
import openfl.display.BitmapData;
import openfl.geom.Rectangle;
import openfl.Lib;
#if discord_rpc
#if FEATURE_DISCORD_RPC
import Discord.DiscordClient;
#end
@ -445,7 +445,7 @@ class PlayState extends MusicBeatSubState
*/
public var vocals:VoicesGroup;
#if discord_rpc
#if FEATURE_DISCORD_RPC
// Discord RPC variables
var storyDifficultyText:String = '';
var iconRPC:String = '';
@ -698,7 +698,7 @@ class PlayState extends MusicBeatSubState
initStrumlines();
initPopups();
#if discord_rpc
#if FEATURE_DISCORD_RPC
// Initialize Discord Rich Presence.
initDiscord();
#end
@ -738,7 +738,7 @@ class PlayState extends MusicBeatSubState
rightWatermarkText.cameras = [camHUD];
// Initialize some debug stuff.
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
// Display the version number (and git commit hash) in the bottom right corner.
this.rightWatermarkText.text = Constants.VERSION;
@ -977,7 +977,7 @@ class PlayState extends MusicBeatSubState
// boyfriendPos.put(); // TODO: Why is this here?
}
#if discord_rpc
#if FEATURE_DISCORD_RPC
DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
#end
}
@ -1036,7 +1036,7 @@ class PlayState extends MusicBeatSubState
// Disable updates, preventing animations in the background from playing.
persistentUpdate = false;
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
if (FlxG.keys.pressed.THREE)
{
// TODO: Change the key or delete this?
@ -1047,7 +1047,7 @@ class PlayState extends MusicBeatSubState
{
#end
persistentDraw = false;
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
}
#end
@ -1066,7 +1066,7 @@ class PlayState extends MusicBeatSubState
moveToGameOver();
}
#if discord_rpc
#if FEATURE_DISCORD_RPC
// Game Over doesn't get his own variable because it's only used here
DiscordClient.changePresence('Game Over - ' + detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
#end
@ -1179,9 +1179,9 @@ class PlayState extends MusicBeatSubState
}
/**
* Function called before opening a new substate.
* @param subState The substate to open.
*/
* Function called before opening a new substate.
* @param subState The substate to open.
*/
public override function openSubState(subState:FlxSubState):Void
{
// If there is a substate which requires the game to continue,
@ -1237,9 +1237,9 @@ class PlayState extends MusicBeatSubState
}
/**
* Function called before closing the current substate.
* @param subState
*/
* Function called before closing the current substate.
* @param subState
*/
public override function closeSubState():Void
{
if (Std.isOfType(subState, PauseSubState))
@ -1278,7 +1278,7 @@ class PlayState extends MusicBeatSubState
// Resume the countdown.
Countdown.resumeCountdown();
#if discord_rpc
#if FEATURE_DISCORD_RPC
if (startTimer.finished)
{
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true,
@ -1301,8 +1301,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Function called when the game window gains focus.
*/
* Function called when the game window gains focus.
*/
public override function onFocus():Void
{
if (VideoCutscene.isPlaying() && FlxG.autoPause && isGamePaused) VideoCutscene.pauseVideo();
@ -1311,7 +1311,7 @@ class PlayState extends MusicBeatSubState
VideoCutscene.resumeVideo();
#end
#if discord_rpc
#if FEATURE_DISCORD_RPC
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause)
{
if (Conductor.instance.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song
@ -1329,15 +1329,15 @@ class PlayState extends MusicBeatSubState
}
/**
* Function called when the game window loses focus.
*/
* Function called when the game window loses focus.
*/
public override function onFocusLost():Void
{
#if html5
if (FlxG.autoPause) VideoCutscene.pauseVideo();
#end
#if discord_rpc
#if FEATURE_DISCORD_RPC
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText,
currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
#end
@ -1346,8 +1346,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Call this by pressing F5 on a debug build.
*/
* Call this by pressing F5 on a debug build.
*/
override function reloadAssets():Void
{
funkin.modding.PolymodHandler.forceReloadAssets();
@ -1459,8 +1459,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Initializes the game and HUD cameras.
*/
* Initializes the game and HUD cameras.
*/
function initCameras():Void
{
camGame = new FunkinCamera('playStateCamGame');
@ -1484,8 +1484,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Initializes the health bar on the HUD.
*/
* Initializes the health bar on the HUD.
*/
function initHealthBar():Void
{
var healthBarYPos:Float = Preferences.downscroll ? FlxG.height * 0.1 : FlxG.height * 0.9;
@ -1516,8 +1516,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Generates the stage and all its props.
*/
* Generates the stage and all its props.
*/
function initStage():Void
{
loadStage(currentStageId);
@ -1537,10 +1537,10 @@ class PlayState extends MusicBeatSubState
}
/**
* Loads stage data from cache, assembles the props,
* and adds it to the state.
* @param id
*/
* Loads stage data from cache, assembles the props,
* and adds it to the state.
* @param id
*/
function loadStage(id:String):Void
{
currentStage = StageRegistry.instance.fetchEntry(id);
@ -1558,7 +1558,7 @@ class PlayState extends MusicBeatSubState
// Add the stage to the scene.
this.add(currentStage);
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
FlxG.console.registerObject('stage', currentStage);
#end
}
@ -1581,8 +1581,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Generates the character sprites and adds them to the stage.
*/
* Generates the character sprites and adds them to the stage.
*/
function initCharacters():Void
{
if (currentSong == null || currentChart == null)
@ -1661,7 +1661,7 @@ class PlayState extends MusicBeatSubState
{
currentStage.addCharacter(girlfriend, GF);
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
FlxG.console.registerObject('gf', girlfriend);
#end
}
@ -1670,7 +1670,7 @@ class PlayState extends MusicBeatSubState
{
currentStage.addCharacter(boyfriend, BF);
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
FlxG.console.registerObject('bf', boyfriend);
#end
}
@ -1681,7 +1681,7 @@ class PlayState extends MusicBeatSubState
// Camera starts at dad.
cameraFollowPoint.setPosition(dad.cameraFocusPoint.x, dad.cameraFocusPoint.y);
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
FlxG.console.registerObject('dad', dad);
#end
}
@ -1692,8 +1692,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Constructs the strumlines for each player.
*/
* Constructs the strumlines for each player.
*/
function initStrumlines():Void
{
var noteStyleId:String = currentChart.noteStyle;
@ -1725,8 +1725,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Configures the judgement and combo popups.
*/
* Configures the judgement and combo popups.
*/
function initPopups():Void
{
var noteStyleId:String = currentChart.noteStyle;
@ -1740,11 +1740,11 @@ class PlayState extends MusicBeatSubState
}
/**
* Initializes the Discord Rich Presence.
*/
* Initializes the Discord Rich Presence.
*/
function initDiscord():Void
{
#if discord_rpc
#if FEATURE_DISCORD_RPC
storyDifficultyText = difficultyString();
iconRPC = currentSong.player2;
@ -1775,9 +1775,9 @@ class PlayState extends MusicBeatSubState
}
/**
* Initializes the song (applying the chart, generating the notes, etc.)
* Should be done before the countdown starts.
*/
* Initializes the song (applying the chart, generating the notes, etc.)
* Should be done before the countdown starts.
*/
function generateSong():Void
{
if (currentChart == null)
@ -1808,8 +1808,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Read note data from the chart and generate the notes.
*/
* Read note data from the chart and generate the notes.
*/
function regenNoteData(startTime:Float = 0):Void
{
Highscore.tallies.combo = 0;
@ -1862,10 +1862,10 @@ class PlayState extends MusicBeatSubState
}
/**
* Prepares to start the countdown.
* Ends any running cutscenes, creates the strumlines, and starts the countdown.
* This is public so that scripts can call it.
*/
* Prepares to start the countdown.
* Ends any running cutscenes, creates the strumlines, and starts the countdown.
* This is public so that scripts can call it.
*/
public function startCountdown():Void
{
// If Countdown.performCountdown returns false, then the countdown was canceled by a script.
@ -1879,9 +1879,9 @@ class PlayState extends MusicBeatSubState
}
/**
* Displays a dialogue cutscene with the given ID.
* This is used by song scripts to display dialogue.
*/
* Displays a dialogue cutscene with the given ID.
* This is used by song scripts to display dialogue.
*/
public function startConversation(conversationId:String):Void
{
isInCutscene = true;
@ -1901,8 +1901,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Handler function called when a conversation ends.
*/
* Handler function called when a conversation ends.
*/
function onConversationComplete():Void
{
isInCutscene = false;
@ -1921,8 +1921,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Starts playing the song after the countdown has completed.
*/
* Starts playing the song after the countdown has completed.
*/
function startSong():Void
{
startingSong = false;
@ -1957,7 +1957,7 @@ class PlayState extends MusicBeatSubState
vocals.pitch = playbackRate;
resyncVocals();
#if discord_rpc
#if FEATURE_DISCORD_RPC
// Updating Discord Rich Presence (with Time Left)
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true, currentSongLengthMs);
#end
@ -1972,8 +1972,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Resyncronize the vocal tracks if they have become offset from the instrumental.
*/
* Resyncronize the vocal tracks if they have become offset from the instrumental.
*/
function resyncVocals():Void
{
if (vocals == null) return;
@ -1992,8 +1992,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Updates the position and contents of the score display.
*/
* Updates the position and contents of the score display.
*/
function updateScoreText():Void
{
// TODO: Add functionality for modules to update the score text.
@ -2010,8 +2010,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Updates the values of the health bar.
*/
* Updates the values of the health bar.
*/
function updateHealthBar():Void
{
if (isBotPlayMode)
@ -2025,8 +2025,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Callback executed when one of the note keys is pressed.
*/
* Callback executed when one of the note keys is pressed.
*/
function onKeyPress(event:PreciseInputEvent):Void
{
if (isGamePaused) return;
@ -2036,8 +2036,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Callback executed when one of the note keys is released.
*/
* Callback executed when one of the note keys is released.
*/
function onKeyRelease(event:PreciseInputEvent):Void
{
if (isGamePaused) return;
@ -2047,8 +2047,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Handles opponent note hits and player note misses.
*/
* Handles opponent note hits and player note misses.
*/
function processNotes(elapsed:Float):Void
{
if (playerStrumline?.notes?.members == null || opponentStrumline?.notes?.members == null) return;
@ -2266,8 +2266,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Spitting out the input for ravy 🙇!!
*/
* Spitting out the input for ravy 🙇!!
*/
var inputSpitter:Array<ScoreInput> = [];
function handleSkippedNotes():Void
@ -2291,9 +2291,9 @@ class PlayState extends MusicBeatSubState
}
/**
* PreciseInputEvents are put into a queue between update() calls,
* and then processed here.
*/
* PreciseInputEvents are put into a queue between update() calls,
* and then processed here.
*/
function processInputQueue():Void
{
if (inputPressQueue.length + inputReleaseQueue.length == 0) return;
@ -2435,9 +2435,9 @@ class PlayState extends MusicBeatSubState
}
/**
* Called when a note leaves the screen and is considered missed by the player.
* @param note
*/
* Called when a note leaves the screen and is considered missed by the player.
* @param note
*/
function onNoteMiss(note:NoteSprite, playSound:Bool = false, healthChange:Float):Void
{
// If we are here, we already CALLED the onNoteMiss script hook!
@ -2493,13 +2493,13 @@ class PlayState extends MusicBeatSubState
}
/**
* Called when a player presses a key with no note present.
* Scripts can modify the amount of health/score lost, whether player animations or sounds are used,
* or even cancel the event entirely.
*
* @param direction
* @param hasPossibleNotes
*/
* Called when a player presses a key with no note present.
* Scripts can modify the amount of health/score lost, whether player animations or sounds are used,
* or even cancel the event entirely.
*
* @param direction
* @param hasPossibleNotes
*/
function ghostNoteMiss(direction:NoteDirection, hasPossibleNotes:Bool = true):Void
{
var event:GhostMissNoteScriptEvent = new GhostMissNoteScriptEvent(direction, // Direction missed in.
@ -2548,11 +2548,11 @@ class PlayState extends MusicBeatSubState
}
/**
* Debug keys. Disabled while in cutscenes.
*/
* Debug keys. Disabled while in cutscenes.
*/
function debugKeyShit():Void
{
#if CHART_EDITOR_SUPPORTED
#if FEATURE_CHART_EDITOR
// Open the stage editor overlaying the current state.
if (controls.DEBUG_STAGE)
{
@ -2582,7 +2582,7 @@ class PlayState extends MusicBeatSubState
}
#end
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
// H: Hide the HUD.
if (FlxG.keys.justPressed.H) camHUD.visible = !camHUD.visible;
@ -2599,7 +2599,7 @@ class PlayState extends MusicBeatSubState
// 9: Toggle the old icon.
if (FlxG.keys.justPressed.NINE) iconP1.toggleOldIcon();
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
// PAGEUP: Skip forward two sections.
// SHIFT+PAGEUP: Skip forward twenty sections.
if (FlxG.keys.justPressed.PAGEUP) changeSection(FlxG.keys.pressed.SHIFT ? 20 : 2);
@ -2612,8 +2612,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Handles applying health, score, and ratings.
*/
* Handles applying health, score, and ratings.
*/
function applyScore(score:Int, daRating:String, healthChange:Float, isComboBreak:Bool)
{
switch (daRating)
@ -2645,8 +2645,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Handles rating popups when a note is hit.
*/
* Handles rating popups when a note is hit.
*/
function popUpScore(daRating:String, ?combo:Int):Void
{
if (daRating == 'miss')
@ -2703,10 +2703,10 @@ class PlayState extends MusicBeatSubState
}
/**
* Handle keyboard inputs during cutscenes.
* This includes advancing conversations and skipping videos.
* @param elapsed Time elapsed since last game update.
*/
* Handle keyboard inputs during cutscenes.
* This includes advancing conversations and skipping videos.
* @param elapsed Time elapsed since last game update.
*/
function handleCutsceneKeys(elapsed:Float):Void
{
if (isGamePaused) return;
@ -2750,20 +2750,20 @@ class PlayState extends MusicBeatSubState
}
/**
* Handle logic for actually skipping a video cutscene after it has been held.
*/
* Handle logic for actually skipping a video cutscene after it has been held.
*/
function skipVideoCutscene():Void
{
VideoCutscene.finishVideo();
}
/**
* End the song. Handle saving high scores and transitioning to the results screen.
*
* Broadcasts an `onSongEnd` event, which can be cancelled to prevent the song from ending (for a cutscene or something).
* Remember to call `endSong` again when the song should actually end!
* @param rightGoddamnNow If true, don't play the fancy animation where you zoom onto Girlfriend. Used after a cutscene.
*/
* End the song. Handle saving high scores and transitioning to the results screen.
*
* Broadcasts an `onSongEnd` event, which can be cancelled to prevent the song from ending (for a cutscene or something).
* Remember to call `endSong` again when the song should actually end!
* @param rightGoddamnNow If true, don't play the fancy animation where you zoom onto Girlfriend. Used after a cutscene.
*/
public function endSong(rightGoddamnNow:Bool = false):Void
{
if (FlxG.sound.music != null) FlxG.sound.music.volume = 0;
@ -2978,8 +2978,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Perform necessary cleanup before leaving the PlayState.
*/
* Perform necessary cleanup before leaving the PlayState.
*/
function performCleanup():Void
{
// If the camera is being tweened, stop it.
@ -3037,8 +3037,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Play the camera zoom animation and then move to the results screen once it's done.
*/
* Play the camera zoom animation and then move to the results screen once it's done.
*/
function zoomIntoResultsScreen(isNewHighscore:Bool, ?prevScoreData:SaveScoreData):Void
{
trace('WENT TO RESULTS SCREEN!');
@ -3102,17 +3102,17 @@ class PlayState extends MusicBeatSubState
// Zoom over to the Results screen.
// TODO: Re-enable this.
/*
FlxTween.tween(FlxG.camera, {zoom: 1200}, 1.1,
{
ease: FlxEase.expoIn,
});
*/
FlxTween.tween(FlxG.camera, {zoom: 1200}, 1.1,
{
ease: FlxEase.expoIn,
});
*/
});
}
/**
* Move to the results screen right goddamn now.
*/
* Move to the results screen right goddamn now.
*/
function moveToResultsScreen(isNewHighscore:Bool, ?prevScoreData:SaveScoreData):Void
{
persistentUpdate = false;
@ -3152,8 +3152,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Pauses music and vocals easily.
*/
* Pauses music and vocals easily.
*/
public function pauseMusic():Void
{
if (FlxG.sound.music != null) FlxG.sound.music.pause();
@ -3161,8 +3161,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Resets the camera's zoom level and focus point.
*/
* Resets the camera's zoom level and focus point.
*/
public function resetCamera(?resetZoom:Bool = true, ?cancelTweens:Bool = true):Void
{
// Cancel camera tweens if any are active.
@ -3184,8 +3184,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Sets the camera follow point's position and tweens the camera there.
*/
* Sets the camera follow point's position and tweens the camera there.
*/
public function tweenCameraToPosition(?x:Float, ?y:Float, ?duration:Float, ?ease:Null<Float->Float>):Void
{
cameraFollowPoint.setPosition(x, y);
@ -3193,8 +3193,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Disables camera following and tweens the camera to the follow point manually.
*/
* Disables camera following and tweens the camera to the follow point manually.
*/
public function tweenCameraToFollowPoint(?duration:Float, ?ease:Null<Float->Float>):Void
{
// Cancel the current tween if it's active.
@ -3231,8 +3231,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Tweens the camera zoom to the desired amount.
*/
* Tweens the camera zoom to the desired amount.
*/
public function tweenCameraZoom(?zoom:Float, ?duration:Float, ?direct:Bool, ?ease:Null<Float->Float>):Void
{
// Cancel the current tween if it's active.
@ -3263,8 +3263,8 @@ class PlayState extends MusicBeatSubState
}
/**
* Cancel all active camera tweens simultaneously.
*/
* Cancel all active camera tweens simultaneously.
*/
public function cancelAllCameraTweens()
{
cancelCameraFollowTween();
@ -3274,8 +3274,8 @@ class PlayState extends MusicBeatSubState
var prevScrollTargets:Array<Dynamic> = []; // used to snap scroll speed when things go unruely
/**
* The magical function that shall tween the scroll speed.
*/
* The magical function that shall tween the scroll speed.
*/
public function tweenScrollSpeed(?speed:Float, ?duration:Float, ?ease:Null<Float->Float>, strumlines:Array<String>):Void
{
// Cancel the current tween if it's active.
@ -3325,12 +3325,12 @@ class PlayState extends MusicBeatSubState
scrollSpeedTweens = [];
}
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
/**
* Jumps forward or backward a number of sections in the song.
* Accounts for BPM changes, does not prevent death from skipped notes.
* @param sections The number of sections to jump, negative to go backwards.
*/
* Jumps forward or backward a number of sections in the song.
* Accounts for BPM changes, does not prevent death from skipped notes.
* @param sections The number of sections to jump, negative to go backwards.
*/
function changeSection(sections:Int):Void
{
// FlxG.sound.music.pause();

View file

@ -386,7 +386,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
{
if (character == null) return;
#if debug
#if FEATURE_DEBUG_FUNCTIONS
// Temporary marker that shows where the character's location is relative to.
// Should display at the stage position of the character (before any offsets).
// TODO: Make this a toggle? It's useful to turn on from time to time.
@ -451,7 +451,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
character.cameraFocusPoint.x += stageCharData.cameraOffsets[0];
character.cameraFocusPoint.y += stageCharData.cameraOffsets[1];
#if debug
#if FEATURE_DEBUG_FUNCTIONS
// Draw the debug icon at the character's feet.
if (charType == BF || charType == DAD)
{
@ -468,7 +468,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
ScriptEventDispatcher.callEvent(character, new ScriptEvent(ADDED, false));
#if debug
#if FEATURE_DEBUG_FUNCTIONS
debugIconGroup.add(debugIcon);
debugIconGroup.add(debugIcon2);
#end
@ -769,39 +769,15 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
* A function that gets called once per step in the song.
* @param curStep The current step number.
*/
public function onStepHit(event:SongTimeScriptEvent):Void
{
// Override me in your scripted stage to perform custom behavior!
// Make sure to call super.onStepHit(event) if you want to keep the boppers dancing.
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onStepHit(event:SongTimeScriptEvent):Void {}
/**
* A function that gets called once per beat in the song (once every four steps).
* @param curStep The current beat number.
*/
public function onBeatHit(event:SongTimeScriptEvent):Void
{
// Override me in your scripted stage to perform custom behavior!
// Make sure to call super.onBeatHit(event) if you want to keep the boppers dancing.
public function onBeatHit(event:SongTimeScriptEvent):Void {}
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onUpdate(event:UpdateScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onUpdate(event:UpdateScriptEvent) {}
public override function kill()
{
@ -883,129 +859,41 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
public function onScriptEvent(event:ScriptEvent)
{
// Ensure all custom events get broadcast to the elements of the stage.
// If we do it here, we don't have to add a handler to EACH script event function.
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onPause(event:PauseScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onPause(event:PauseScriptEvent) {}
public function onResume(event:ScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onResume(event:ScriptEvent) {}
public function onSongStart(event:ScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onSongStart(event:ScriptEvent) {}
public function onSongEnd(event:ScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onSongEnd(event:ScriptEvent) {}
public function onGameOver(event:ScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onGameOver(event:ScriptEvent) {}
public function onCountdownStart(event:CountdownScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onCountdownStart(event:CountdownScriptEvent) {}
public function onCountdownStep(event:CountdownScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onCountdownStep(event:CountdownScriptEvent) {}
public function onCountdownEnd(event:CountdownScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onCountdownEnd(event:CountdownScriptEvent) {}
public function onNoteIncoming(event:NoteScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onNoteIncoming(event:NoteScriptEvent) {}
public function onNoteHit(event:HitNoteScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onNoteHit(event:HitNoteScriptEvent) {}
public function onNoteMiss(event:NoteScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onNoteMiss(event:NoteScriptEvent) {}
public function onSongEvent(event:SongEventScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onSongEvent(event:SongEventScriptEvent) {}
public function onNoteGhostMiss(event:GhostMissNoteScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onNoteGhostMiss(event:GhostMissNoteScriptEvent) {}
public function onSongLoaded(event:SongLoadScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onSongLoaded(event:SongLoadScriptEvent) {}
public function onSongRetry(event:ScriptEvent)
{
for (bopper in boppers)
{
ScriptEventDispatcher.callEvent(bopper, event);
}
}
public function onSongRetry(event:ScriptEvent) {}
}

View file

@ -54,7 +54,7 @@ class DebugMenuSubState extends MusicBeatSubState
// Create each menu item.
// Call onMenuChange when the first item is created to move the camera .
#if CHART_EDITOR_SUPPORTED
#if FEATURE_CHART_EDITOR
onMenuChange(createItem("CHART EDITOR", openChartEditor));
#end
// createItem("Input Offset Testing", openInputOffsetTesting);

View file

@ -3327,7 +3327,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
handleTestKeybinds();
handleHelpKeybinds();
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
handleQuickWatch();
#end

View file

@ -148,7 +148,7 @@ class FreeplayDJ extends FlxAtlasSprite
// I shit myself.
}
#if debug
#if FEATURE_DEBUG_FUNCTIONS
if (FlxG.keys.pressed.CONTROL)
{
if (FlxG.keys.justPressed.LEFT)

View file

@ -291,14 +291,14 @@ class FreeplayState extends MusicBeatSubState
stickerSubState.degenStickers();
}
#if discord_rpc
#if FEATURE_DISCORD_RPC
// Updating Discord Rich Presence
DiscordClient.changePresence('In the Menus', null);
#end
var isDebug:Bool = false;
#if debug
#if FEATURE_DEBUG_FUNCTIONS
isDebug = true;
#end
@ -871,7 +871,7 @@ class FreeplayState extends MusicBeatSubState
return str.songName.toLowerCase().startsWith(songFilter.filterData ?? '');
});
case ALL:
// no filter!
// no filter!
case FAVORITE:
songsToFilter = songsToFilter.filter(str -> {
if (str == null) return true; // Random
@ -1198,7 +1198,7 @@ class FreeplayState extends MusicBeatSubState
{
super.update(elapsed);
#if debug
#if FEATURE_DEBUG_FUNCTIONS
if (FlxG.keys.justPressed.T)
{
rankAnimStart(fromResultsParams ??
@ -1772,7 +1772,7 @@ class FreeplayState extends MusicBeatSubState
var targetInstId:String = baseInstrumentalId;
// TODO: Make this a UI element.
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL)
{
targetInstId = altInstrumentalIds[0];
@ -1833,7 +1833,7 @@ class FreeplayState extends MusicBeatSubState
practiceMode: false,
minimalMode: false,
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
botPlayMode: FlxG.keys.pressed.SHIFT,
#else
botPlayMode: false,
@ -1942,7 +1942,7 @@ class FreeplayState extends MusicBeatSubState
var instSuffix:String = baseInstrumentalId;
// TODO: Make this a UI element.
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL)
{
instSuffix = altInstrumentalIds[0];

View file

@ -27,7 +27,7 @@ import funkin.ui.title.TitleState;
import funkin.ui.story.StoryMenuState;
import funkin.ui.Prompt;
import funkin.util.WindowUtil;
#if discord_rpc
#if FEATURE_DISCORD_RPC
import Discord.DiscordClient;
#end
#if newgrounds
@ -54,7 +54,7 @@ class MainMenuState extends MusicBeatState
override function create():Void
{
#if discord_rpc
#if FEATURE_DISCORD_RPC
// Updating Discord Rich Presence
DiscordClient.changePresence("In the Menus", null);
#end
@ -344,7 +344,7 @@ class MainMenuState extends MusicBeatState
}
}
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
// Open the debug menu, defaults to ` / ~
if (controls.DEBUG_MENU)
{

View file

@ -216,7 +216,7 @@ class StoryMenuState extends MusicBeatState
changeLevel();
refresh();
#if discord_rpc
#if FEATURE_DISCORD_RPC
// Updating Discord Rich Presence
DiscordClient.changePresence('In the Menus', null);
#end

View file

@ -174,7 +174,7 @@ class LoadingState extends MusicBeatSubState
FlxG.watch.addQuick('percentage?', callbacks.numRemaining / callbacks.length);
}
#if debug
#if FEATURE_DEBUG_FUNCTIONS
if (FlxG.keys.justPressed.SPACE) trace('fired: ' + callbacks.getFired() + ' unfired:' + callbacks.getUnfired());
#end
}

View file

@ -41,9 +41,9 @@ class Constants
* A suffix to add to the game version.
* Add a suffix to prototype builds and remove it for releases.
*/
public static final VERSION_SUFFIX:String = #if (DEBUG || FORCE_DEBUG_VERSION) ' PROTOTYPE' #else '' #end;
public static final VERSION_SUFFIX:String = #if FEATURE_DEBUG_FUNCTIONS ' PROTOTYPE' #else '' #end;
#if (debug || FORCE_DEBUG_VERSION)
#if FEATURE_DEBUG_FUNCTIONS
static function get_VERSION():String
{
return 'v${Application.current.meta.get('version')} (${GIT_BRANCH} : ${GIT_HASH}${GIT_HAS_LOCAL_CHANGES ? ' : MODIFIED' : ''})' + VERSION_SUFFIX;
@ -384,11 +384,7 @@ class Constants
* 1 = The preloader waits for 1 second before moving to the next step.
* The progress bare is automatically rescaled to match.
*/
#if debug
public static final PRELOADER_MIN_STAGE_TIME:Float = 0.0;
#else
public static final PRELOADER_MIN_STAGE_TIME:Float = 0.1;
#end
/**
* HEALTH VALUES