mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-27 10:05:41 -05:00
Merge branch 'feature/scripted-stages'
This commit is contained in:
commit
2d673e037a
130 changed files with 2397 additions and 1826 deletions
16
.vscode/launch.json
vendored
16
.vscode/launch.json
vendored
|
@ -2,18 +2,16 @@
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "HTML5 Debug",
|
// Launch in native/CPP
|
||||||
"type": "chrome",
|
|
||||||
"request": "launch",
|
|
||||||
"url": "http://127.0.0.1:3001",
|
|
||||||
"sourceMaps": true,
|
|
||||||
"webRoot": "${workspaceFolder}",
|
|
||||||
"preLaunchTask": "debug: html"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Lime",
|
"name": "Lime",
|
||||||
"type": "lime",
|
"type": "lime",
|
||||||
"request": "launch"
|
"request": "launch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Evaluate macros with debugging enabled
|
||||||
|
"name": "Haxe Eval",
|
||||||
|
"type": "haxe-eval",
|
||||||
|
"request": "launch"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
105
Project.xml
105
Project.xml
|
@ -2,7 +2,7 @@
|
||||||
<project>
|
<project>
|
||||||
<!-- _________________________ Application Settings _________________________ -->
|
<!-- _________________________ Application Settings _________________________ -->
|
||||||
|
|
||||||
<app title="Friday Night Funkin'" file="Funkin" packageName="com.funkin.fnf" package="com.funkin.fnf" main="Main" version="0.2.8" company="ninjamuffin99" />
|
<app title="Friday Night Funkin'" file="Funkin" packageName="com.funkin.fnf" package="com.funkin.fnf" main="Main" version="0.3.0" company="ninjamuffin99" />
|
||||||
|
|
||||||
<!--Switch Export with Unique ApplicationID and Icon-->
|
<!--Switch Export with Unique ApplicationID and Icon-->
|
||||||
<set name="APP_ID" value="0x0100f6c013bbc000" />
|
<set name="APP_ID" value="0x0100f6c013bbc000" />
|
||||||
|
@ -24,10 +24,10 @@
|
||||||
<window if="html5" resizable="true" />
|
<window if="html5" resizable="true" />
|
||||||
|
|
||||||
<!--Desktop-specific-->
|
<!--Desktop-specific-->
|
||||||
<window if="desktop" orientation="landscape" fullscreen="false" resizable="true" vsync="false"/>
|
<window if="desktop" orientation="landscape" fullscreen="false" resizable="true" vsync="false" />
|
||||||
|
|
||||||
<!--Mobile-specific-->
|
<!--Mobile-specific-->
|
||||||
<window if="mobile" orientation="landscape" fullscreen="true" width="0" height="0" resizable="false"/>
|
<window if="mobile" orientation="landscape" fullscreen="true" width="0" height="0" resizable="false" />
|
||||||
|
|
||||||
<!-- _____________________________ Path Settings ____________________________ -->
|
<!-- _____________________________ Path Settings ____________________________ -->
|
||||||
|
|
||||||
|
@ -37,11 +37,11 @@
|
||||||
|
|
||||||
<classpath name="source" />
|
<classpath name="source" />
|
||||||
|
|
||||||
<assets path="assets/preload" rename="assets" exclude="*.ogg" if="web"/>
|
<assets path="assets/preload" rename="assets" exclude="*.ogg" if="web" />
|
||||||
<assets path="assets/preload" rename="assets" exclude="*.mp3" unless="web"/>
|
<assets path="assets/preload" rename="assets" exclude="*.mp3" unless="web" />
|
||||||
|
|
||||||
<define name="PRELOAD_ALL" unless="web" />
|
<define name="PRELOAD_ALL" unless="web" />
|
||||||
<define name="NO_PRELOAD_ALL" unless="PRELOAD_ALL"/>
|
<define name="NO_PRELOAD_ALL" unless="PRELOAD_ALL" />
|
||||||
|
|
||||||
<section if="PRELOAD_ALL">
|
<section if="PRELOAD_ALL">
|
||||||
<library name="songs" preload="true" />
|
<library name="songs" preload="true" />
|
||||||
|
@ -72,43 +72,44 @@
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<assets path="assets/songs" library="songs" exclude="*.fla|*.ogg" if="web" />
|
<assets path="assets/songs" library="songs" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/songs" library="songs" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/songs" library="songs" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/shared" library="shared" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/shared" library="shared" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/shared" library="shared" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/shared" library="shared" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/tutorial" library="tutorial" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/week1" library="week1" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/week1" library="week1" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/week1" library="week1" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/week1" library="week1" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/week2" library="week2" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/week2" library="week2" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/week2" library="week2" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/week2" library="week2" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/week3" library="week3" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/week3" library="week3" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/week3" library="week3" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/week3" library="week3" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/week4" library="week4" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/week4" library="week4" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/week4" library="week4" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/week4" library="week4" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/week5" library="week5" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/week5" library="week5" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/week5" library="week5" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/week5" library="week5" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/week6" library="week6" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/week6" library="week6" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/week6" library="week6" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/week6" library="week6" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/week7" library="week7" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/week7" library="week7" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/week7" library="week7" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/week7" library="week7" exclude="*.fla|*.mp3" unless="web" />
|
||||||
<assets path="assets/week8" library="week8" exclude="*.fla|*.ogg" if="web"/>
|
<assets path="assets/week8" library="week8" exclude="*.fla|*.ogg" if="web" />
|
||||||
<assets path="assets/week8" library="week8" exclude="*.fla|*.mp3" unless="web"/>
|
<assets path="assets/week8" library="week8" exclude="*.fla|*.mp3" unless="web" />
|
||||||
|
|
||||||
<!-- <assets path='example_mods' rename='mods' embed='false'/> -->
|
<!-- <assets path='example_mods' rename='mods' embed='false'/> -->
|
||||||
|
|
||||||
<assets path='example_mods' rename='mods' embed='false' exclude="*.md"/>
|
<assets path='example_mods' rename='mods' embed='false' exclude="*.md" />
|
||||||
<assets path='art/readme.txt' rename='do NOT readme.txt' />
|
<assets path='art/readme.txt' rename='do NOT readme.txt' />
|
||||||
|
|
||||||
<assets path="CHANGELOG.md" rename='changelog.txt'/>
|
<assets path="CHANGELOG.md" rename='changelog.txt' />
|
||||||
|
|
||||||
<!-- NOTE FOR FUTURE SELF SINCE FONTS ARE ALWAYS FUCKY
|
<!-- NOTE FOR FUTURE SELF SINCE FONTS ARE ALWAYS FUCKY
|
||||||
TO FIX ONE OF THEM, I CONVERTED IT TO OTF. DUNNO IF YOU NEED TO
|
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!!!
|
THEN UHHH I USED THE NAME OF THE FONT WITH SETFORMAT() ON THE TEXT!!!
|
||||||
NOT USING A DIRECT THING TO THE ASSET!!!
|
NOT USING A DIRECT THING TO THE ASSET!!!
|
||||||
-->
|
-->
|
||||||
<assets path="assets/fonts" embed='true'/>
|
<assets path="assets/fonts" embed='true' />
|
||||||
<!-- _______________________________ Libraries ______________________________ -->
|
<!-- _______________________________ Libraries ______________________________ -->
|
||||||
|
|
||||||
|
<haxelib name="openfl" />
|
||||||
<haxelib name="flixel" />
|
<haxelib name="flixel" />
|
||||||
<haxedev set='webgl' />
|
<haxedev set='webgl' />
|
||||||
|
|
||||||
|
@ -119,14 +120,14 @@
|
||||||
<!--In case you want to use the ui package-->
|
<!--In case you want to use the ui package-->
|
||||||
<haxelib name="flixel-ui" />
|
<haxelib name="flixel-ui" />
|
||||||
<!--haxelib name="newgrounds" unless="switch"/> -->
|
<!--haxelib name="newgrounds" unless="switch"/> -->
|
||||||
<haxelib name="faxe" if='switch'/>
|
<haxelib name="faxe" if='switch' />
|
||||||
<haxelib name="polymod" if="desktop"/>
|
<haxelib name="polymod" />
|
||||||
<haxelib name="firetongue" />
|
<haxelib name="firetongue" />
|
||||||
|
|
||||||
<!-- <haxelib name="colyseus"/> -->
|
<!-- <haxelib name="colyseus"/> -->
|
||||||
<!-- <haxelib name="colyseus-websocket" /> -->
|
<!-- <haxelib name="colyseus-websocket" /> -->
|
||||||
<!-- <haxelib name="newgrounds"/> -->
|
<!-- <haxelib name="newgrounds"/> -->
|
||||||
<haxelib name="hxcpp-debug-server" if="desktop debug"/>
|
<haxelib name="hxcpp-debug-server" if="desktop debug" />
|
||||||
|
|
||||||
<!-- swf stufffff -->
|
<!-- swf stufffff -->
|
||||||
<!-- <haxelib name="swf"/> -->
|
<!-- <haxelib name="swf"/> -->
|
||||||
|
@ -138,7 +139,8 @@
|
||||||
<!-- https://github.com/ninjamuffin99/Flixel-Animate-Atlas-Player -->
|
<!-- https://github.com/ninjamuffin99/Flixel-Animate-Atlas-Player -->
|
||||||
|
|
||||||
|
|
||||||
<!--<haxelib name="discord_rpc" if="cpp"/> --> <!-- foesn't work with neko -->
|
<!--<haxelib name="discord_rpc" if="cpp"/> -->
|
||||||
|
<!-- foesn't work with neko -->
|
||||||
<!-- <haxelib name="hxcpp-debug-server" if="desktop"/> -->
|
<!-- <haxelib name="hxcpp-debug-server" if="desktop"/> -->
|
||||||
|
|
||||||
<!-- <haxelib name="markdown" /> -->
|
<!-- <haxelib name="markdown" /> -->
|
||||||
|
@ -179,30 +181,35 @@
|
||||||
<!--Enable this for Nape release builds for a serious peformance improvement-->
|
<!--Enable this for Nape release builds for a serious peformance improvement-->
|
||||||
<haxedef name="NAPE_RELEASE_BUILD" unless="debug" />
|
<haxedef name="NAPE_RELEASE_BUILD" unless="debug" />
|
||||||
|
|
||||||
|
<!-- _________________________________ Custom _______________________________ -->
|
||||||
|
|
||||||
|
<!-- Disable trace() calls in release builds to bump up performance. -->
|
||||||
<haxeflag name="--no-traces" unless="debug" />
|
<haxeflag name="--no-traces" unless="debug" />
|
||||||
<haxeflag name="--dce full" if="release" />
|
|
||||||
|
<!-- HScript relies heavily on Reflection, which means we can't use DCE. -->
|
||||||
|
<haxeflag name="-dce no" />
|
||||||
|
<haxeflag name="--macro" value="include('funkin')" />
|
||||||
|
|
||||||
|
<!-- Necessary to provide stack traces for HScript. -->
|
||||||
|
<haxedef name="hscriptPos" />
|
||||||
<haxedef name="HXCPP_CHECK_POINTER" />
|
<haxedef name="HXCPP_CHECK_POINTER" />
|
||||||
<haxedef name="HXCPP_STACK_LINE" />
|
<haxedef name="HXCPP_STACK_LINE" />
|
||||||
|
|
||||||
<!-- _________________________________ Custom _______________________________ -->
|
|
||||||
|
<!-- 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)-->
|
<!--Place custom nodes like icons here (higher priority to override the HaxeFlixel icon)-->
|
||||||
|
|
||||||
<icon path="art/icon16.png" size='16'/>
|
<icon path="art/icon16.png" size='16' />
|
||||||
<icon path="art/icon32.png" size='32'/>
|
<icon path="art/icon32.png" size='32' />
|
||||||
<icon path="art/icon64.png" size='64'/>
|
<icon path="art/icon64.png" size='64' />
|
||||||
<icon path="art/iconOG.png" />
|
<icon path="art/iconOG.png" />
|
||||||
|
|
||||||
<!--
|
|
||||||
aww yeah hackerman time, run a macro on the class rather than edit it
|
|
||||||
took me a while to get this working but turns out the classname comes SECOND
|
|
||||||
-->
|
|
||||||
<haxeflag name="--macro" value="addMetadata('@:build(util.macro.FlxMacro.buildFlxBasic())', 'flixel.FlxBasic')" />
|
|
||||||
|
|
||||||
<!-- <haxedef name="SKIP_TO_PLAYSTATE" if="debug" /> -->
|
<!-- <haxedef name="SKIP_TO_PLAYSTATE" if="debug" /> -->
|
||||||
|
|
||||||
<haxedef name="CAN_OPEN_LINKS" unless="switch"/>
|
<haxedef name="CAN_OPEN_LINKS" unless="switch" />
|
||||||
<haxedef name="CAN_CHEAT" if="switch debug"/>
|
<haxedef name="CAN_CHEAT" if="switch debug" />
|
||||||
|
|
||||||
<!-- Skip the Intro -->
|
<!-- Skip the Intro -->
|
||||||
<section if="debug">
|
<section if="debug">
|
||||||
|
@ -232,7 +239,7 @@
|
||||||
<!-- <prebuild haxe="trace('prebuilding');"/> -->
|
<!-- <prebuild haxe="trace('prebuilding');"/> -->
|
||||||
<!-- <postbuild haxe="art/Postbuild.hx"/> -->
|
<!-- <postbuild haxe="art/Postbuild.hx"/> -->
|
||||||
|
|
||||||
<config:ios allow-provisioning-updates="true" team-id=""/>
|
<config:ios allow-provisioning-updates="true" team-id="" />
|
||||||
|
|
||||||
<!-- Options for Polymod -->
|
<!-- Options for Polymod -->
|
||||||
<section if="polymod">
|
<section if="polymod">
|
||||||
|
@ -259,7 +266,7 @@
|
||||||
<section if='TOOLS'>
|
<section if='TOOLS'>
|
||||||
<!-- Compiles tool for old song conversion shit -->
|
<!-- Compiles tool for old song conversion shit -->
|
||||||
<!-- Assumes you use it on windows/desktop!!!! -->
|
<!-- Assumes you use it on windows/desktop!!!! -->
|
||||||
<postbuild command='haxe -main art/SongConverter.hx --cs export/songShit'/>
|
<postbuild command='haxe -main art/SongConverter.hx --cs export/songShit' />
|
||||||
<assets path='export/songShit/bin/SongConverter.exe' rename='SongConverter.exe' />
|
<assets path='export/songShit/bin/SongConverter.exe' rename='SongConverter.exe' />
|
||||||
|
|
||||||
<!-- <postbuild command='ren export/songShit/bin export/songShit/tools '/> -->
|
<!-- <postbuild command='ren export/songShit/bin export/songShit/tools '/> -->
|
||||||
|
|
BIN
example_mods/introMod/_polymod_icon.png
Normal file
BIN
example_mods/introMod/_polymod_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
8
example_mods/introMod/_polymod_meta.json
Normal file
8
example_mods/introMod/_polymod_meta.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"title": "Intro Mod",
|
||||||
|
"description": "An introductory mod.",
|
||||||
|
"author": "MasterEric",
|
||||||
|
"api_version": "0.1.0",
|
||||||
|
"mod_version": "1.0.0",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
}
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.3 MiB |
|
@ -1,64 +0,0 @@
|
||||||
package;
|
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
|
||||||
|
|
||||||
class BGSprite extends FlxSprite
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
Cool lil utility thing just so that it can easy do antialiasing and scrollfactor bullshit
|
|
||||||
*/
|
|
||||||
public var idleAnim:String;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NOTE: loadOldWay param is just for current backward compatibility! Will be moved later!
|
|
||||||
*/
|
|
||||||
public function new(image:String, x:Float = 0, y:Float = 0, parX:Float = 1, parY:Float = 1, ?daAnimations:Array<String>, ?loopingAnim:Bool = false,
|
|
||||||
?loadOldWay:Bool = true)
|
|
||||||
{
|
|
||||||
super(x, y);
|
|
||||||
|
|
||||||
if (loadOldWay)
|
|
||||||
{
|
|
||||||
if (daAnimations != null)
|
|
||||||
{
|
|
||||||
setupSparrow(image, daAnimations, loopingAnim);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
justLoadImage(image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollFactor.set(parX, parY);
|
|
||||||
antialiasing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setupSparrow(image:String, daAnimations:Array<String>, ?loopingAnim:Bool = false)
|
|
||||||
{
|
|
||||||
frames = Paths.getSparrowAtlas(image);
|
|
||||||
for (anims in daAnimations)
|
|
||||||
{
|
|
||||||
var daLoop:Bool = loopingAnim;
|
|
||||||
if (loopingAnim == null)
|
|
||||||
daLoop = false;
|
|
||||||
|
|
||||||
animation.addByPrefix(anims, anims, 24, daLoop);
|
|
||||||
animation.play(anims);
|
|
||||||
|
|
||||||
if (idleAnim == null)
|
|
||||||
idleAnim = anims;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function justLoadImage(image:String)
|
|
||||||
{
|
|
||||||
loadGraphic(Paths.image(image));
|
|
||||||
active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dance():Void
|
|
||||||
{
|
|
||||||
if (idleAnim != null)
|
|
||||||
animation.play(idleAnim);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package;
|
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
|
||||||
|
|
||||||
class BackgroundDancer extends FlxSprite
|
|
||||||
{
|
|
||||||
public function new(x:Float, y:Float)
|
|
||||||
{
|
|
||||||
super(x, y);
|
|
||||||
|
|
||||||
frames = Paths.getSparrowAtlas("limo/limoDancer");
|
|
||||||
animation.addByIndices('danceLeft', 'bg dancer sketch PINK', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
|
||||||
animation.addByIndices('danceRight', 'bg dancer sketch PINK', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
|
||||||
animation.play('danceLeft');
|
|
||||||
animation.finish();
|
|
||||||
antialiasing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var danceDir:Bool = false;
|
|
||||||
|
|
||||||
public function dance():Void
|
|
||||||
{
|
|
||||||
danceDir = !danceDir;
|
|
||||||
|
|
||||||
if (danceDir)
|
|
||||||
animation.play('danceRight', true);
|
|
||||||
else
|
|
||||||
animation.play('danceLeft', true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
package;
|
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
|
||||||
|
|
||||||
class BackgroundGirls extends FlxSprite
|
|
||||||
{
|
|
||||||
public function new(x:Float, y:Float)
|
|
||||||
{
|
|
||||||
super(x, y);
|
|
||||||
|
|
||||||
// BG fangirls dissuaded
|
|
||||||
frames = Paths.getSparrowAtlas('weeb/bgFreaks');
|
|
||||||
|
|
||||||
animation.addByIndices('danceLeft', 'BG girls group', CoolUtil.numberArray(14), "", 24, false);
|
|
||||||
animation.addByIndices('danceRight', 'BG girls group', CoolUtil.numberArray(30, 15), "", 24, false);
|
|
||||||
|
|
||||||
animation.play('danceLeft');
|
|
||||||
animation.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
var danceDir:Bool = false;
|
|
||||||
|
|
||||||
public function getScared():Void
|
|
||||||
{
|
|
||||||
animation.addByIndices('danceLeft', 'BG fangirls dissuaded', CoolUtil.numberArray(14), "", 24, false);
|
|
||||||
animation.addByIndices('danceRight', 'BG fangirls dissuaded', CoolUtil.numberArray(30, 15), "", 24, false);
|
|
||||||
dance();
|
|
||||||
animation.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dance():Void
|
|
||||||
{
|
|
||||||
danceDir = !danceDir;
|
|
||||||
|
|
||||||
if (danceDir)
|
|
||||||
animation.play('danceRight', true);
|
|
||||||
else
|
|
||||||
animation.play('danceLeft', true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,7 @@
|
||||||
package;
|
package;
|
||||||
|
|
||||||
|
import funkin.InitState;
|
||||||
|
import funkin.MemoryCounter;
|
||||||
import flixel.FlxGame;
|
import flixel.FlxGame;
|
||||||
import flixel.FlxState;
|
import flixel.FlxState;
|
||||||
import openfl.Lib;
|
import openfl.Lib;
|
||||||
|
@ -42,9 +44,9 @@ class Main extends Sprite
|
||||||
// A design similar to that of Minecraft resource packs would be intuitive.
|
// A design similar to that of Minecraft resource packs would be intuitive.
|
||||||
// 3. The interface should save (to the save file) and output an ordered array of mod IDs.
|
// 3. The interface should save (to the save file) and output an ordered array of mod IDs.
|
||||||
// 4. Replace the call to PolymodHandler.loadAllMods() with a call to PolymodHandler.loadModsById(ids:Array<String>).
|
// 4. Replace the call to PolymodHandler.loadAllMods() with a call to PolymodHandler.loadModsById(ids:Array<String>).
|
||||||
modding.PolymodHandler.loadAllMods();
|
funkin.modding.PolymodHandler.loadAllMods();
|
||||||
|
|
||||||
i18n.FireTongueHandler.init();
|
funkin.i18n.FireTongueHandler.init();
|
||||||
|
|
||||||
if (stage != null)
|
if (stage != null)
|
||||||
{
|
{
|
||||||
|
@ -98,9 +100,11 @@ class Main extends Sprite
|
||||||
#if debug
|
#if debug
|
||||||
fpsCounter = new FPS(10, 3, 0xFFFFFF);
|
fpsCounter = new FPS(10, 3, 0xFFFFFF);
|
||||||
addChild(fpsCounter);
|
addChild(fpsCounter);
|
||||||
|
#if !html5
|
||||||
memoryCounter = new MemoryCounter(10, 13, 0xFFFFFF);
|
memoryCounter = new MemoryCounter(10, 13, 0xFFFFFF);
|
||||||
addChild(memoryCounter);
|
addChild(memoryCounter);
|
||||||
#end
|
#end
|
||||||
|
#end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
video = new Video();
|
video = new Video();
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
package;
|
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
|
||||||
import haxe.display.Display.Package;
|
|
||||||
|
|
||||||
class TankmenBG extends FlxSprite
|
|
||||||
{
|
|
||||||
public static var animationNotes:Array<Dynamic> = [];
|
|
||||||
|
|
||||||
public var strumTime:Float = 0;
|
|
||||||
public var goingRight:Bool = false;
|
|
||||||
public var tankSpeed:Float = 0.7;
|
|
||||||
|
|
||||||
public var endingOffset:Float;
|
|
||||||
|
|
||||||
public function new(x:Float, y:Float, isGoingRight:Bool)
|
|
||||||
{
|
|
||||||
super(x, y);
|
|
||||||
|
|
||||||
// makeGraphic(200, 200);
|
|
||||||
|
|
||||||
frames = Paths.getSparrowAtlas('tankmanKilled1');
|
|
||||||
antialiasing = true;
|
|
||||||
animation.addByPrefix('run', 'tankman running', 24, true);
|
|
||||||
animation.addByPrefix('shot', 'John Shot ' + FlxG.random.int(1, 2), 24, false);
|
|
||||||
|
|
||||||
animation.play('run');
|
|
||||||
animation.curAnim.curFrame = FlxG.random.int(0, animation.curAnim.numFrames - 1);
|
|
||||||
|
|
||||||
updateHitbox();
|
|
||||||
|
|
||||||
setGraphicSize(Std.int(width * 0.8));
|
|
||||||
updateHitbox();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resetShit(x:Float, y:Float, isGoingRight:Bool)
|
|
||||||
{
|
|
||||||
setPosition(x, y);
|
|
||||||
goingRight = isGoingRight;
|
|
||||||
endingOffset = FlxG.random.float(50, 200);
|
|
||||||
tankSpeed = FlxG.random.float(0.6, 1);
|
|
||||||
|
|
||||||
if (goingRight)
|
|
||||||
flipX = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
override function update(elapsed:Float)
|
|
||||||
{
|
|
||||||
super.update(elapsed);
|
|
||||||
|
|
||||||
if (x >= FlxG.width * 1.2 || x <= FlxG.width * -0.5)
|
|
||||||
visible = false;
|
|
||||||
else
|
|
||||||
visible = true;
|
|
||||||
|
|
||||||
if (animation.curAnim.name == 'run')
|
|
||||||
{
|
|
||||||
var endDirection:Float = (FlxG.width * 0.74) + endingOffset;
|
|
||||||
|
|
||||||
if (goingRight)
|
|
||||||
{
|
|
||||||
endDirection = (FlxG.width * 0.02) - endingOffset;
|
|
||||||
|
|
||||||
x = (endDirection + (Conductor.songPosition - strumTime) * tankSpeed);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = (endDirection - (Conductor.songPosition - strumTime) * tankSpeed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Conductor.songPosition > strumTime)
|
|
||||||
{
|
|
||||||
// kill();
|
|
||||||
animation.play('shot');
|
|
||||||
|
|
||||||
if (goingRight)
|
|
||||||
{
|
|
||||||
offset.y = 200;
|
|
||||||
offset.x = 300;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (animation.curAnim.name == 'shot' && animation.curAnim.curFrame >= animation.curAnim.frames.length - 1)
|
|
||||||
{
|
|
||||||
kill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSubState;
|
import flixel.FlxSubState;
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Section.SwagSection;
|
import funkin.Note.NoteData;
|
||||||
|
import funkin.SongLoad.SwagSong;
|
||||||
|
import funkin.Section.SwagSection;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.animation.FlxBaseAnimation;
|
import flixel.animation.FlxBaseAnimation;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
||||||
import flixel.util.FlxSort;
|
import flixel.util.FlxSort;
|
||||||
import haxe.io.Path;
|
import haxe.io.Path;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
|
@ -19,7 +22,7 @@ class Character extends FlxSprite
|
||||||
|
|
||||||
public var holdTimer:Float = 0;
|
public var holdTimer:Float = 0;
|
||||||
|
|
||||||
public var animationNotes:Array<Dynamic> = [];
|
public var animationNotes:Array<NoteData> = [];
|
||||||
|
|
||||||
public function new(x:Float, y:Float, ?character:String = "bf", ?isPlayer:Bool = false)
|
public function new(x:Float, y:Float, ?character:String = "bf", ?isPlayer:Bool = false)
|
||||||
{
|
{
|
||||||
|
@ -267,6 +270,8 @@ class Character extends FlxSprite
|
||||||
quickAnimAdd('singLEFTmiss', 'BF NOTE LEFT MISS');
|
quickAnimAdd('singLEFTmiss', 'BF NOTE LEFT MISS');
|
||||||
quickAnimAdd('singRIGHTmiss', 'BF NOTE RIGHT MISS');
|
quickAnimAdd('singRIGHTmiss', 'BF NOTE RIGHT MISS');
|
||||||
quickAnimAdd('singDOWNmiss', 'BF NOTE DOWN MISS');
|
quickAnimAdd('singDOWNmiss', 'BF NOTE DOWN MISS');
|
||||||
|
quickAnimAdd('preAttack', 'bf pre attack');
|
||||||
|
quickAnimAdd('attack', 'boyfriend attack');
|
||||||
quickAnimAdd('hey', 'BF HEY');
|
quickAnimAdd('hey', 'BF HEY');
|
||||||
|
|
||||||
quickAnimAdd('firstDeath', "BF dies");
|
quickAnimAdd('firstDeath', "BF dies");
|
||||||
|
@ -582,27 +587,25 @@ class Character extends FlxSprite
|
||||||
|
|
||||||
public function loadMappedAnims()
|
public function loadMappedAnims()
|
||||||
{
|
{
|
||||||
var swagshit = SongLoad.loadFromJson('picospeaker', 'stress');
|
var swagshit:SwagSong = SongLoad.loadFromJson('stress', 'stress');
|
||||||
|
|
||||||
var notes = swagshit.extraNotes.get('picospeaker');
|
var notes:Array<SwagSection> = swagshit.noteMap.get('picospeaker');
|
||||||
|
|
||||||
for (section in notes)
|
for (section in notes)
|
||||||
{
|
{
|
||||||
for (idk in section.sectionNotes)
|
for (noteData in section.sectionNotes)
|
||||||
{
|
{
|
||||||
animationNotes.push(idk);
|
animationNotes.push(noteData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TankmenBG.animationNotes = animationNotes;
|
|
||||||
|
|
||||||
trace(animationNotes);
|
trace(animationNotes);
|
||||||
animationNotes.sort(sortAnims);
|
animationNotes.sort(sortAnims);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortAnims(val1:Array<Dynamic>, val2:Array<Dynamic>):Int
|
function sortAnims(val1:NoteData, val2:NoteData):Int
|
||||||
{
|
{
|
||||||
return FlxSort.byValues(FlxSort.ASCENDING, val1[0], val2[0]);
|
return FlxSort.byValues(FlxSort.ASCENDING, val1.strumTime, val2.strumTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
function quickAnimAdd(name:String, prefix:String)
|
function quickAnimAdd(name:String, prefix:String)
|
||||||
|
@ -657,13 +660,13 @@ class Character extends FlxSprite
|
||||||
// for pico??
|
// for pico??
|
||||||
if (animationNotes.length > 0)
|
if (animationNotes.length > 0)
|
||||||
{
|
{
|
||||||
if (Conductor.songPosition > animationNotes[0][0])
|
if (Conductor.songPosition > animationNotes[0].strumTime)
|
||||||
{
|
{
|
||||||
trace('played shoot anim' + animationNotes[0][1]);
|
trace('played shoot anim' + animationNotes[0].noteData);
|
||||||
|
|
||||||
var shootAnim:Int = 1;
|
var shootAnim:Int = 1;
|
||||||
|
|
||||||
if (animationNotes[0][1] >= 2)
|
if ((cast animationNotes[0].noteData) >= 2)
|
||||||
shootAnim = 3;
|
shootAnim = 3;
|
||||||
|
|
||||||
shootAnim += FlxG.random.int(0, 1);
|
shootAnim += FlxG.random.int(0, 1);
|
||||||
|
@ -689,6 +692,8 @@ class Character extends FlxSprite
|
||||||
*/
|
*/
|
||||||
public function dance()
|
public function dance()
|
||||||
{
|
{
|
||||||
|
if (animation == null)
|
||||||
|
return;
|
||||||
if (!debugMode)
|
if (!debugMode)
|
||||||
{
|
{
|
||||||
switch (curCharacter)
|
switch (curCharacter)
|
||||||
|
@ -723,6 +728,8 @@ class Character extends FlxSprite
|
||||||
|
|
||||||
public function playAnim(AnimName:String, Force:Bool = false, Reversed:Bool = false, Frame:Int = 0):Void
|
public function playAnim(AnimName:String, Force:Bool = false, Reversed:Bool = false, Frame:Int = 0):Void
|
||||||
{
|
{
|
||||||
|
if (animation == null)
|
||||||
|
return;
|
||||||
animation.play(AnimName, Force, Reversed, Frame);
|
animation.play(AnimName, Force, Reversed, Frame);
|
||||||
|
|
||||||
var daOffset = animOffsets.get(AnimName);
|
var daOffset = animOffsets.get(AnimName);
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import SongLoad.SwagSong;
|
import funkin.SongLoad.SwagSong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ...
|
* ...
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxObject;
|
import flixel.FlxObject;
|
||||||
import flixel.input.FlxInput;
|
import flixel.input.FlxInput;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxState;
|
import flixel.FlxState;
|
||||||
|
@ -15,7 +15,8 @@ import haxe.format.JsonParser;
|
||||||
import lime.math.Rectangle;
|
import lime.math.Rectangle;
|
||||||
import lime.utils.Assets;
|
import lime.utils.Assets;
|
||||||
import openfl.filters.ShaderFilter;
|
import openfl.filters.ShaderFilter;
|
||||||
import shaderslmfao.ScreenWipeShader;
|
import funkin.play.PlayState;
|
||||||
|
import funkin.shaderslmfao.ScreenWipeShader;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxState;
|
import flixel.FlxState;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.addons.text.FlxTypeText;
|
import flixel.addons.text.FlxTypeText;
|
||||||
|
@ -8,6 +8,7 @@ import flixel.input.FlxKeyManager;
|
||||||
import flixel.text.FlxText;
|
import flixel.text.FlxText;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Sys.sleep;
|
import Sys.sleep;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxCamera;
|
import flixel.FlxCamera;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxBasic;
|
import flixel.FlxBasic;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Controls.Control;
|
import funkin.Controls.Control;
|
||||||
import flash.text.TextField;
|
import flash.text.TextField;
|
||||||
import flixel.FlxCamera;
|
import flixel.FlxCamera;
|
||||||
import flixel.FlxGame;
|
import flixel.FlxGame;
|
||||||
|
@ -21,15 +21,16 @@ import flixel.tweens.FlxTween;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import flixel.util.FlxSpriteUtil;
|
import flixel.util.FlxSpriteUtil;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
import freeplayStuff.BGScrollingText;
|
import funkin.freeplayStuff.BGScrollingText;
|
||||||
import freeplayStuff.DJBoyfriend;
|
import funkin.freeplayStuff.DJBoyfriend;
|
||||||
import freeplayStuff.FreeplayScore;
|
import funkin.freeplayStuff.FreeplayScore;
|
||||||
import freeplayStuff.SongMenuItem;
|
import funkin.freeplayStuff.SongMenuItem;
|
||||||
import lime.app.Future;
|
import lime.app.Future;
|
||||||
import lime.utils.Assets;
|
import lime.utils.Assets;
|
||||||
import shaderslmfao.AngleMask;
|
import funkin.shaderslmfao.AngleMask;
|
||||||
import shaderslmfao.PureColor;
|
import funkin.shaderslmfao.PureColor;
|
||||||
import shaderslmfao.StrokeShader;
|
import funkin.shaderslmfao.StrokeShader;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ class FreeplayState extends MusicBeatSubstate
|
||||||
#if debug
|
#if debug
|
||||||
isDebug = true;
|
isDebug = true;
|
||||||
addSong('Test', 1, 'bf-pixel');
|
addSong('Test', 1, 'bf-pixel');
|
||||||
|
addSong('Pyro', 4, 'bf');
|
||||||
#end
|
#end
|
||||||
|
|
||||||
var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist'));
|
var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist'));
|
||||||
|
@ -517,10 +519,7 @@ class FreeplayState extends MusicBeatSubstate
|
||||||
if (controls.BACK)
|
if (controls.BACK)
|
||||||
{
|
{
|
||||||
FlxG.sound.play(Paths.sound('cancelMenu'));
|
FlxG.sound.play(Paths.sound('cancelMenu'));
|
||||||
|
FlxG.switchState(new MainMenuState());
|
||||||
close();
|
|
||||||
|
|
||||||
// FlxG.switchState(new MainMenuState());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accepted)
|
if (accepted)
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxObject;
|
import flixel.FlxObject;
|
||||||
import flixel.FlxSubState;
|
import flixel.FlxSubState;
|
||||||
|
@ -6,8 +6,9 @@ import flixel.math.FlxPoint;
|
||||||
import flixel.system.FlxSound;
|
import flixel.system.FlxSound;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
import haxe.display.Display.Package;
|
import haxe.display.Display;
|
||||||
import ui.PreferencesMenu;
|
import funkin.ui.PreferencesMenu;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
class GameOverSubstate extends MusicBeatSubstate
|
class GameOverSubstate extends MusicBeatSubstate
|
||||||
{
|
{
|
||||||
|
@ -24,7 +25,7 @@ class GameOverSubstate extends MusicBeatSubstate
|
||||||
gameOverMusic = new FlxSound();
|
gameOverMusic = new FlxSound();
|
||||||
FlxG.sound.list.add(gameOverMusic);
|
FlxG.sound.list.add(gameOverMusic);
|
||||||
|
|
||||||
var daStage = PlayState.curStage;
|
var daStage = PlayState.curStageId;
|
||||||
var daBf:String = '';
|
var daBf:String = '';
|
||||||
switch (daStage)
|
switch (daStage)
|
||||||
{
|
{
|
|
@ -1,7 +1,8 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
class GitarooPause extends MusicBeatState
|
class GitarooPause extends MusicBeatState
|
||||||
{
|
{
|
|
@ -1,7 +1,8 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import openfl.utils.Assets;
|
import openfl.utils.Assets;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
class Highscore
|
class Highscore
|
||||||
{
|
{
|
|
@ -1,7 +1,7 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
#if !(macro)
|
import funkin.play.stage.StageData;
|
||||||
import charting.ChartingState;
|
import funkin.charting.ChartingState;
|
||||||
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
|
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
|
||||||
import flixel.addons.transition.FlxTransitionableState;
|
import flixel.addons.transition.FlxTransitionableState;
|
||||||
import flixel.addons.transition.TransitionData;
|
import flixel.addons.transition.TransitionData;
|
||||||
|
@ -10,9 +10,11 @@ import flixel.math.FlxPoint;
|
||||||
import flixel.math.FlxRect;
|
import flixel.math.FlxRect;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import openfl.display.BitmapData;
|
import openfl.display.BitmapData;
|
||||||
import play.PicoFight;
|
import funkin.play.PicoFight;
|
||||||
import ui.PreferencesMenu;
|
import funkin.ui.PreferencesMenu;
|
||||||
import ui.stageBuildShit.StageBuilderState;
|
import funkin.ui.stageBuildShit.StageBuilderState;
|
||||||
|
import funkin.util.macro.MacroUtil;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
|
@ -29,12 +31,17 @@ import sys.io.File;
|
||||||
import sys.thread.Thread;
|
import sys.thread.Thread;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the game state using custom defines.
|
||||||
|
* Only used in Debug builds.
|
||||||
|
*/
|
||||||
class InitState extends FlxTransitionableState
|
class InitState extends FlxTransitionableState
|
||||||
{
|
{
|
||||||
override public function create():Void
|
override public function create():Void
|
||||||
{
|
{
|
||||||
|
trace('This is a debug build, loading InitState...');
|
||||||
#if android
|
#if android
|
||||||
FlxG.android.preventDefaultKeys = [FlxAndroidKey.BACK];
|
FlxG.android.preventDefaultKeys = [flixel.input.android.FlxAndroidKey.BACK];
|
||||||
#end
|
#end
|
||||||
#if newgrounds
|
#if newgrounds
|
||||||
NGio.init();
|
NGio.init();
|
||||||
|
@ -113,6 +120,8 @@ class InitState extends FlxTransitionableState
|
||||||
// FlxTransitionableState.skipNextTransOut = true;
|
// FlxTransitionableState.skipNextTransOut = true;
|
||||||
FlxTransitionableState.skipNextTransIn = true;
|
FlxTransitionableState.skipNextTransIn = true;
|
||||||
|
|
||||||
|
StageDataParser.loadStageCache();
|
||||||
|
|
||||||
#if song
|
#if song
|
||||||
var song = getSong();
|
var song = getSong();
|
||||||
|
|
||||||
|
@ -191,21 +200,12 @@ class InitState extends FlxTransitionableState
|
||||||
LoadingState.loadAndSwitchState(new PlayState());
|
LoadingState.loadAndSwitchState(new PlayState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#end
|
|
||||||
|
|
||||||
function getWeek()
|
function getWeek()
|
||||||
return Std.parseInt(getDefine("week"));
|
return Std.parseInt(MacroUtil.getDefine("week"));
|
||||||
|
|
||||||
function getSong()
|
function getSong()
|
||||||
return getDefine("song");
|
return MacroUtil.getDefine("song");
|
||||||
|
|
||||||
function getDif()
|
function getDif()
|
||||||
return Std.parseInt(getDefine("dif", "1"));
|
return Std.parseInt(MacroUtil.getDefine("dif", "1"));
|
||||||
|
|
||||||
macro function getDefine(key:String, defaultValue:String = null):haxe.macro.Expr
|
|
||||||
{
|
|
||||||
var value = haxe.macro.Context.definedValue(key);
|
|
||||||
if (value == null)
|
|
||||||
value = defaultValue;
|
|
||||||
return macro $v{value};
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Controls;
|
import funkin.Controls;
|
||||||
import flixel.input.gamepad.FlxGamepad;
|
import flixel.input.gamepad.FlxGamepad;
|
||||||
import flixel.input.gamepad.FlxGamepadInputID;
|
import flixel.input.gamepad.FlxGamepadInputID;
|
||||||
import flixel.input.keyboard.FlxKey;
|
import flixel.input.keyboard.FlxKey;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxState;
|
import flixel.FlxState;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxState;
|
import flixel.FlxState;
|
||||||
|
@ -12,6 +12,7 @@ import lime.utils.AssetLibrary;
|
||||||
import lime.utils.AssetManifest;
|
import lime.utils.AssetManifest;
|
||||||
import lime.utils.Assets as LimeAssets;
|
import lime.utils.Assets as LimeAssets;
|
||||||
import openfl.utils.Assets;
|
import openfl.utils.Assets;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
class LoadingState extends MusicBeatState
|
class LoadingState extends MusicBeatState
|
||||||
{
|
{
|
||||||
|
@ -186,8 +187,15 @@ class LoadingState extends MusicBeatState
|
||||||
}
|
}
|
||||||
|
|
||||||
static function getNextState(target:FlxState, stopMusic = false):FlxState
|
static function getNextState(target:FlxState, stopMusic = false):FlxState
|
||||||
|
{
|
||||||
|
if (PlayState.storyWeek == 0)
|
||||||
|
{
|
||||||
|
Paths.setCurrentLevel('tutorial');
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Paths.setCurrentLevel("week" + PlayState.storyWeek);
|
Paths.setCurrentLevel("week" + PlayState.storyWeek);
|
||||||
|
}
|
||||||
#if NO_PRELOAD_ALL
|
#if NO_PRELOAD_ALL
|
||||||
var loaded = isSoundLoaded(getSongPath())
|
var loaded = isSoundLoaded(getSongPath())
|
||||||
&& (!PlayState.SONG.needsVoices || isSoundLoaded(getVocalPath()))
|
&& (!PlayState.SONG.needsVoices || isSoundLoaded(getVocalPath()))
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import NGio;
|
import funkin.NGio;
|
||||||
import flixel.FlxObject;
|
import flixel.FlxObject;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxState;
|
import flixel.FlxState;
|
||||||
|
@ -17,12 +17,12 @@ import flixel.util.FlxColor;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
import lime.app.Application;
|
import lime.app.Application;
|
||||||
import openfl.filters.ShaderFilter;
|
import openfl.filters.ShaderFilter;
|
||||||
import shaderslmfao.ScreenWipeShader;
|
import funkin.shaderslmfao.ScreenWipeShader;
|
||||||
import ui.AtlasMenuList;
|
import funkin.ui.AtlasMenuList;
|
||||||
import ui.MenuList;
|
import funkin.ui.MenuList;
|
||||||
import ui.OptionsState;
|
import funkin.ui.OptionsState;
|
||||||
import ui.PreferencesMenu;
|
import funkin.ui.PreferencesMenu;
|
||||||
import ui.Prompt;
|
import funkin.ui.Prompt;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import Discord.DiscordClient;
|
||||||
#end
|
#end
|
||||||
#if newgrounds
|
#if newgrounds
|
||||||
import io.newgrounds.NG;
|
import io.newgrounds.NG;
|
||||||
import ui.NgPrompt;
|
import funkin.ui.NgPrompt;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
class MainMenuState extends MusicBeatState
|
class MainMenuState extends MusicBeatState
|
|
@ -1,3 +1,5 @@
|
||||||
|
package funkin;
|
||||||
|
|
||||||
import openfl.text.TextFormat;
|
import openfl.text.TextFormat;
|
||||||
import openfl.system.System;
|
import openfl.system.System;
|
||||||
import openfl.text.TextField;
|
import openfl.text.TextField;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Conductor.BPMChangeEvent;
|
import funkin.Conductor.BPMChangeEvent;
|
||||||
import flixel.FlxGame;
|
import flixel.FlxGame;
|
||||||
import flixel.addons.transition.FlxTransitionableState;
|
import flixel.addons.transition.FlxTransitionableState;
|
||||||
import flixel.addons.ui.FlxUIState;
|
import flixel.addons.ui.FlxUIState;
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Conductor.BPMChangeEvent;
|
import funkin.Conductor.BPMChangeEvent;
|
||||||
import flixel.FlxSubState;
|
import flixel.FlxSubState;
|
||||||
|
|
||||||
class MusicBeatSubstate extends FlxSubState
|
class MusicBeatSubstate extends FlxSubState
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
#if newgrounds
|
#if newgrounds
|
||||||
import flixel.util.FlxSignal;
|
import flixel.util.FlxSignal;
|
|
@ -1,19 +1,13 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
|
||||||
import flixel.math.FlxMath;
|
import flixel.math.FlxMath;
|
||||||
import flixel.util.FlxColor;
|
import funkin.shaderslmfao.ColorSwap;
|
||||||
import flixel.util.FlxTimer;
|
import funkin.ui.PreferencesMenu;
|
||||||
import shaderslmfao.ColorSwap;
|
import funkin.play.PlayState;
|
||||||
import ui.PreferencesMenu;
|
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
#if polymod
|
|
||||||
import polymod.format.ParseRules.TargetSignatureElement;
|
|
||||||
#end
|
|
||||||
|
|
||||||
class Note extends FlxSprite
|
class Note extends FlxSprite
|
||||||
{
|
{
|
||||||
public var data = new NoteData();
|
public var data = new NoteData();
|
||||||
|
@ -46,25 +40,37 @@ class Note extends FlxSprite
|
||||||
|
|
||||||
/** the lowercase name of the note, for anim control, i.e. left right up down */
|
/** the lowercase name of the note, for anim control, i.e. left right up down */
|
||||||
public var dirName(get, never):String;
|
public var dirName(get, never):String;
|
||||||
inline function get_dirName() return data.dirName;
|
|
||||||
|
inline function get_dirName()
|
||||||
|
return data.dirName;
|
||||||
|
|
||||||
/** the uppercase name of the note, for anim control, i.e. left right up down */
|
/** the uppercase name of the note, for anim control, i.e. left right up down */
|
||||||
public var dirNameUpper(get, never):String;
|
public var dirNameUpper(get, never):String;
|
||||||
inline function get_dirNameUpper() return data.dirNameUpper;
|
|
||||||
|
inline function get_dirNameUpper()
|
||||||
|
return data.dirNameUpper;
|
||||||
|
|
||||||
/** the lowercase name of the note's color, for anim control, i.e. purple blue green red */
|
/** the lowercase name of the note's color, for anim control, i.e. purple blue green red */
|
||||||
public var colorName(get, never):String;
|
public var colorName(get, never):String;
|
||||||
inline function get_colorName() return data.colorName;
|
|
||||||
|
inline function get_colorName()
|
||||||
|
return data.colorName;
|
||||||
|
|
||||||
/** the lowercase name of the note's color, for anim control, i.e. purple blue green red */
|
/** the lowercase name of the note's color, for anim control, i.e. purple blue green red */
|
||||||
public var colorNameUpper(get, never):String;
|
public var colorNameUpper(get, never):String;
|
||||||
inline function get_colorNameUpper() return data.colorNameUpper;
|
|
||||||
|
inline function get_colorNameUpper()
|
||||||
|
return data.colorNameUpper;
|
||||||
|
|
||||||
public var highStakes(get, never):Bool;
|
public var highStakes(get, never):Bool;
|
||||||
inline function get_highStakes() return data.highStakes;
|
|
||||||
|
inline function get_highStakes()
|
||||||
|
return data.highStakes;
|
||||||
|
|
||||||
public var lowStakes(get, never):Bool;
|
public var lowStakes(get, never):Bool;
|
||||||
inline function get_lowStakes() return data.lowStakes;
|
|
||||||
|
inline function get_lowStakes()
|
||||||
|
return data.lowStakes;
|
||||||
|
|
||||||
public static var swagWidth:Float = 160 * 0.7;
|
public static var swagWidth:Float = 160 * 0.7;
|
||||||
public static var PURP_NOTE:Int = 0;
|
public static var PURP_NOTE:Int = 0;
|
||||||
|
@ -103,8 +109,9 @@ class Note extends FlxSprite
|
||||||
|
|
||||||
data.noteData = noteData;
|
data.noteData = noteData;
|
||||||
|
|
||||||
var daStage:String = PlayState.curStage;
|
var daStage:String = PlayState.curStageId;
|
||||||
|
|
||||||
|
// TODO: Make this logic more generic
|
||||||
switch (daStage)
|
switch (daStage)
|
||||||
{
|
{
|
||||||
case 'school' | 'schoolEvil':
|
case 'school' | 'schoolEvil':
|
||||||
|
@ -187,7 +194,7 @@ class Note extends FlxSprite
|
||||||
|
|
||||||
x -= width / 2;
|
x -= width / 2;
|
||||||
|
|
||||||
if (PlayState.curStage.startsWith('school'))
|
if (PlayState.curStageId.startsWith('school'))
|
||||||
x += 30;
|
x += 30;
|
||||||
|
|
||||||
if (prevNote.isSustainNote)
|
if (prevNote.isSustainNote)
|
||||||
|
@ -276,68 +283,97 @@ typedef RawNoteData =
|
||||||
var noteData:NoteType;
|
var noteData:NoteType;
|
||||||
var sustainLength:Float;
|
var sustainLength:Float;
|
||||||
var altNote:Bool;
|
var altNote:Bool;
|
||||||
|
var noteKind:NoteKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
@:forward
|
@:forward
|
||||||
abstract NoteData(RawNoteData)
|
abstract NoteData(RawNoteData)
|
||||||
{
|
{
|
||||||
public function new (strumTime = 0.0, noteData:NoteType = 0, sustainLength = 0.0, altNote = false)
|
public function new(strumTime = 0.0, noteData:NoteType = 0, sustainLength = 0.0, altNote = false, noteKind = NORMAL)
|
||||||
{
|
{
|
||||||
this =
|
this = {
|
||||||
{ strumTime : strumTime
|
strumTime: strumTime,
|
||||||
, noteData : noteData
|
noteData: noteData,
|
||||||
, sustainLength : sustainLength
|
sustainLength: sustainLength,
|
||||||
, altNote : altNote
|
altNote: altNote,
|
||||||
|
noteKind: noteKind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var note(get, never):NoteType;
|
public var note(get, never):NoteType;
|
||||||
inline function get_note() return this.noteData.value;
|
|
||||||
|
inline function get_note()
|
||||||
|
return this.noteData.value;
|
||||||
|
|
||||||
public var int(get, never):Int;
|
public var int(get, never):Int;
|
||||||
inline function get_int() return this.noteData.int;
|
|
||||||
|
inline function get_int()
|
||||||
|
return this.noteData.int;
|
||||||
|
|
||||||
public var dir(get, never):NoteDir;
|
public var dir(get, never):NoteDir;
|
||||||
inline function get_dir() return this.noteData.value;
|
|
||||||
|
inline function get_dir()
|
||||||
|
return this.noteData.value;
|
||||||
|
|
||||||
public var dirName(get, never):String;
|
public var dirName(get, never):String;
|
||||||
inline function get_dirName() return dir.name;
|
|
||||||
|
inline function get_dirName()
|
||||||
|
return dir.name;
|
||||||
|
|
||||||
public var dirNameUpper(get, never):String;
|
public var dirNameUpper(get, never):String;
|
||||||
inline function get_dirNameUpper() return dir.nameUpper;
|
|
||||||
|
inline function get_dirNameUpper()
|
||||||
|
return dir.nameUpper;
|
||||||
|
|
||||||
public var color(get, never):NoteColor;
|
public var color(get, never):NoteColor;
|
||||||
inline function get_color() return this.noteData.value;
|
|
||||||
|
inline function get_color()
|
||||||
|
return this.noteData.value;
|
||||||
|
|
||||||
public var colorName(get, never):String;
|
public var colorName(get, never):String;
|
||||||
inline function get_colorName() return color.name;
|
|
||||||
|
inline function get_colorName()
|
||||||
|
return color.name;
|
||||||
|
|
||||||
public var colorNameUpper(get, never):String;
|
public var colorNameUpper(get, never):String;
|
||||||
inline function get_colorNameUpper() return color.nameUpper;
|
|
||||||
|
inline function get_colorNameUpper()
|
||||||
|
return color.nameUpper;
|
||||||
|
|
||||||
public var highStakes(get, never):Bool;
|
public var highStakes(get, never):Bool;
|
||||||
inline function get_highStakes() return this.noteData.highStakes;
|
|
||||||
|
inline function get_highStakes()
|
||||||
|
return this.noteData.highStakes;
|
||||||
|
|
||||||
public var lowStakes(get, never):Bool;
|
public var lowStakes(get, never):Bool;
|
||||||
inline function get_lowStakes() return this.noteData.lowStakes;
|
|
||||||
|
inline function get_lowStakes()
|
||||||
|
return this.noteData.lowStakes;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum abstract NoteType(Int) from Int to Int
|
enum abstract NoteType(Int) from Int to Int
|
||||||
{
|
{
|
||||||
// public var raw(get, never):Int;
|
// public var raw(get, never):Int;
|
||||||
// inline function get_raw() return this;
|
// inline function get_raw() return this;
|
||||||
|
|
||||||
public var int(get, never):Int;
|
public var int(get, never):Int;
|
||||||
inline function get_int() return this < 0 ? -this : this % 4;
|
|
||||||
|
inline function get_int()
|
||||||
|
return this < 0 ? -this : this % 4;
|
||||||
|
|
||||||
public var value(get, never):NoteType;
|
public var value(get, never):NoteType;
|
||||||
inline function get_value() return int;
|
|
||||||
|
inline function get_value()
|
||||||
|
return int;
|
||||||
|
|
||||||
public var highStakes(get, never):Bool;
|
public var highStakes(get, never):Bool;
|
||||||
inline function get_highStakes() return this > 3;
|
|
||||||
|
inline function get_highStakes()
|
||||||
|
return this > 3;
|
||||||
|
|
||||||
public var lowStakes(get, never):Bool;
|
public var lowStakes(get, never):Bool;
|
||||||
inline function get_lowStakes() return this < 0;
|
|
||||||
|
inline function get_lowStakes()
|
||||||
|
return this < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@:forward
|
@:forward
|
||||||
|
@ -347,30 +383,33 @@ enum abstract NoteDir(NoteType) from Int to Int from NoteType
|
||||||
var DOWN = 1;
|
var DOWN = 1;
|
||||||
var UP = 2;
|
var UP = 2;
|
||||||
var RIGHT = 3;
|
var RIGHT = 3;
|
||||||
|
|
||||||
var value(get, never):NoteDir;
|
var value(get, never):NoteDir;
|
||||||
inline function get_value() return this.value;
|
|
||||||
|
inline function get_value()
|
||||||
|
return this.value;
|
||||||
|
|
||||||
public var name(get, never):String;
|
public var name(get, never):String;
|
||||||
|
|
||||||
function get_name()
|
function get_name()
|
||||||
{
|
{
|
||||||
return switch(value)
|
return switch (value)
|
||||||
{
|
{
|
||||||
case LEFT : "left" ;
|
case LEFT: "left";
|
||||||
case DOWN : "down" ;
|
case DOWN: "down";
|
||||||
case UP : "up" ;
|
case UP: "up";
|
||||||
case RIGHT: "right";
|
case RIGHT: "right";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var nameUpper(get, never):String;
|
public var nameUpper(get, never):String;
|
||||||
|
|
||||||
function get_nameUpper()
|
function get_nameUpper()
|
||||||
{
|
{
|
||||||
return switch(value)
|
return switch (value)
|
||||||
{
|
{
|
||||||
case LEFT : "LEFT" ;
|
case LEFT: "LEFT";
|
||||||
case DOWN : "DOWN" ;
|
case DOWN: "DOWN";
|
||||||
case UP : "UP" ;
|
case UP: "UP";
|
||||||
case RIGHT: "RIGHT";
|
case RIGHT: "RIGHT";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,31 +422,44 @@ enum abstract NoteColor(NoteType) from Int to Int from NoteType
|
||||||
var BLUE = 1;
|
var BLUE = 1;
|
||||||
var GREEN = 2;
|
var GREEN = 2;
|
||||||
var RED = 3;
|
var RED = 3;
|
||||||
|
|
||||||
var value(get, never):NoteColor;
|
var value(get, never):NoteColor;
|
||||||
inline function get_value() return this.value;
|
|
||||||
|
inline function get_value()
|
||||||
|
return this.value;
|
||||||
|
|
||||||
public var name(get, never):String;
|
public var name(get, never):String;
|
||||||
|
|
||||||
function get_name()
|
function get_name()
|
||||||
{
|
{
|
||||||
return switch(value)
|
return switch (value)
|
||||||
{
|
{
|
||||||
case PURPLE: "purple";
|
case PURPLE: "purple";
|
||||||
case BLUE : "blue" ;
|
case BLUE: "blue";
|
||||||
case GREEN : "green" ;
|
case GREEN: "green";
|
||||||
case RED : "red" ;
|
case RED: "red";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public var nameUpper(get, never):String;
|
public var nameUpper(get, never):String;
|
||||||
|
|
||||||
function get_nameUpper()
|
function get_nameUpper()
|
||||||
{
|
{
|
||||||
return switch(value)
|
return switch (value)
|
||||||
{
|
{
|
||||||
case PURPLE: "PURPLE";
|
case PURPLE: "PURPLE";
|
||||||
case BLUE : "BLUE" ;
|
case BLUE: "BLUE";
|
||||||
case GREEN : "GREEN" ;
|
case GREEN: "GREEN";
|
||||||
case RED : "RED" ;
|
case RED: "RED";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum abstract NoteKind(String) from String to String
|
||||||
|
{
|
||||||
|
var NORMAL = "normal";
|
||||||
|
var PYRO_LIGHT = "pyro_light";
|
||||||
|
var PYRO_KICK = "pyro_kick";
|
||||||
|
var PYRO_TOSS = "pyro_toss";
|
||||||
|
var PYRO_COCK = "pyro_cock"; // lol
|
||||||
|
var PYRO_SHOOT = "pyro_shoot";
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import haxe.io.Path;
|
import haxe.io.Path;
|
||||||
|
@ -34,7 +34,8 @@ class NoteSplash extends FlxSprite
|
||||||
|
|
||||||
animation.play('note' + noteData + '-' + FlxG.random.int(0, 1), true);
|
animation.play('note' + noteData + '-' + FlxG.random.int(0, 1), true);
|
||||||
animation.curAnim.frameRate = 24 + FlxG.random.int(-2, 2);
|
animation.curAnim.frameRate = 24 + FlxG.random.int(-2, 2);
|
||||||
animation.finishCallback = function(name){
|
animation.finishCallback = function(name)
|
||||||
|
{
|
||||||
kill();
|
kill();
|
||||||
};
|
};
|
||||||
updateHitbox();
|
updateHitbox();
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
class Options
|
class Options
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxSubState;
|
import flixel.FlxSubState;
|
||||||
|
@ -6,6 +6,7 @@ import flixel.text.FlxText;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import lime.app.Application;
|
import lime.app.Application;
|
||||||
|
|
||||||
|
#if newgrounds
|
||||||
class OutdatedSubState extends MusicBeatState
|
class OutdatedSubState extends MusicBeatState
|
||||||
{
|
{
|
||||||
public static var leftState:Bool = false;
|
public static var leftState:Bool = false;
|
||||||
|
@ -42,3 +43,4 @@ class OutdatedSubState extends MusicBeatState
|
||||||
super.update(elapsed);
|
super.update(elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#end
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
||||||
import openfl.utils.AssetType;
|
import openfl.utils.AssetType;
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Controls.Control;
|
import funkin.Controls.Control;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxSubState;
|
import flixel.FlxSubState;
|
||||||
import flixel.addons.transition.FlxTransitionableState;
|
import flixel.addons.transition.FlxTransitionableState;
|
||||||
|
@ -11,6 +11,7 @@ import flixel.text.FlxText;
|
||||||
import flixel.tweens.FlxEase;
|
import flixel.tweens.FlxEase;
|
||||||
import flixel.tweens.FlxTween;
|
import flixel.tweens.FlxTween;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
class PauseSubState extends MusicBeatSubstate
|
class PauseSubState extends MusicBeatSubstate
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Controls;
|
import funkin.Controls;
|
||||||
import flixel.FlxCamera;
|
import flixel.FlxCamera;
|
||||||
import flixel.input.actions.FlxActionInput;
|
import flixel.input.actions.FlxActionInput;
|
||||||
import flixel.input.gamepad.FlxGamepad;
|
import flixel.input.gamepad.FlxGamepad;
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Note.NoteData;
|
import funkin.Note.NoteData;
|
||||||
|
|
||||||
typedef SwagSection =
|
typedef SwagSection =
|
||||||
{
|
{
|
|
@ -1,7 +1,7 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import Note.NoteData;
|
import funkin.Note.NoteData;
|
||||||
import Section.SwagSection;
|
import funkin.Section.SwagSection;
|
||||||
import haxe.Json;
|
import haxe.Json;
|
||||||
import haxe.format.JsonParser;
|
import haxe.format.JsonParser;
|
||||||
import lime.utils.Assets;
|
import lime.utils.Assets;
|
||||||
|
@ -48,7 +48,7 @@ class SongLoad
|
||||||
|
|
||||||
public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong
|
public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong
|
||||||
{
|
{
|
||||||
var rawJson = Assets.getText(Paths.json(folder.toLowerCase() + '/' + jsonInput.toLowerCase())).trim();
|
var rawJson = Assets.getText(Paths.json('songs/${folder.toLowerCase()}/${jsonInput.toLowerCase()}')).trim();
|
||||||
|
|
||||||
while (!rawJson.endsWith("}"))
|
while (!rawJson.endsWith("}"))
|
||||||
{
|
{
|
||||||
|
@ -174,6 +174,8 @@ class SongLoad
|
||||||
|
|
||||||
for (sectionIndex => section in noteStuff)
|
for (sectionIndex => section in noteStuff)
|
||||||
{
|
{
|
||||||
|
if (section == null || section.sectionNotes == null)
|
||||||
|
continue;
|
||||||
for (noteIndex => noteDataArray in section.sectionNotes)
|
for (noteIndex => noteDataArray in section.sectionNotes)
|
||||||
{
|
{
|
||||||
var arrayDipshit:Array<Dynamic> = cast noteDataArray; // crackhead
|
var arrayDipshit:Array<Dynamic> = cast noteDataArray; // crackhead
|
||||||
|
@ -188,6 +190,10 @@ class SongLoad
|
||||||
noteStuff[sectionIndex].sectionNotes[noteIndex].noteData = arrayDipshit[1];
|
noteStuff[sectionIndex].sectionNotes[noteIndex].noteData = arrayDipshit[1];
|
||||||
noteStuff[sectionIndex].sectionNotes[noteIndex].sustainLength = arrayDipshit[2];
|
noteStuff[sectionIndex].sectionNotes[noteIndex].sustainLength = arrayDipshit[2];
|
||||||
noteStuff[sectionIndex].sectionNotes[noteIndex].altNote = arrayDipshit[3];
|
noteStuff[sectionIndex].sectionNotes[noteIndex].altNote = arrayDipshit[3];
|
||||||
|
if (arrayDipshit.length >= 5)
|
||||||
|
{
|
||||||
|
noteStuff[sectionIndex].sectionNotes[noteIndex].noteKind = arrayDipshit[4];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (noteDataArray != null)
|
else if (noteDataArray != null)
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
#if discord_rpc
|
#if discord_rpc
|
||||||
import Discord.DiscordClient;
|
import Discord.DiscordClient;
|
||||||
|
@ -14,6 +14,7 @@ import flixel.tweens.FlxTween;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
import lime.net.curl.CURLCode;
|
import lime.net.curl.CURLCode;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ class StoryMenuState extends MusicBeatState
|
||||||
{
|
{
|
||||||
var scoreText:FlxText;
|
var scoreText:FlxText;
|
||||||
|
|
||||||
var weekData:Array<Dynamic> = [
|
var weekData:Array<Array<String>> = [
|
||||||
['Tutorial'],
|
['Tutorial'],
|
||||||
['Bopeebo', 'Fresh', 'Dadbattle'],
|
['Bopeebo', 'Fresh', 'Dadbattle'],
|
||||||
['Spookeez', 'South', "Monster"],
|
['Spookeez', 'South', "Monster"],
|
||||||
|
@ -430,11 +431,10 @@ class StoryMenuState extends MusicBeatState
|
||||||
// grpWeekCharacters.members[0].updateHitbox();
|
// grpWeekCharacters.members[0].updateHitbox();
|
||||||
}
|
}
|
||||||
|
|
||||||
var stringThing:Array<String> = weekData[curWeek];
|
var trackNames:Array<String> = weekData[curWeek];
|
||||||
|
for (i in trackNames)
|
||||||
for (i in stringThing)
|
|
||||||
{
|
{
|
||||||
txtTracklist.text += "\n" + i;
|
txtTracklist.text += '\n${i}';
|
||||||
}
|
}
|
||||||
|
|
||||||
txtTracklist.text = txtTracklist.text.toUpperCase();
|
txtTracklist.text = txtTracklist.text.toUpperCase();
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxCamera;
|
import flixel.FlxCamera;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.system.FlxSound;
|
import flixel.system.FlxSound;
|
|
@ -1,6 +1,6 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import audiovis.SpectogramSprite;
|
import funkin.audiovis.SpectogramSprite;
|
||||||
import flixel.FlxObject;
|
import flixel.FlxObject;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxState;
|
import flixel.FlxState;
|
||||||
|
@ -29,10 +29,10 @@ import openfl.events.NetStatusEvent;
|
||||||
import openfl.media.Video;
|
import openfl.media.Video;
|
||||||
import openfl.net.NetConnection;
|
import openfl.net.NetConnection;
|
||||||
import openfl.net.NetStream;
|
import openfl.net.NetStream;
|
||||||
import shaderslmfao.BuildingShaders;
|
import funkin.shaderslmfao.BuildingShaders;
|
||||||
import shaderslmfao.ColorSwap;
|
import funkin.shaderslmfao.ColorSwap;
|
||||||
import shaderslmfao.TitleOutline;
|
import funkin.shaderslmfao.TitleOutline;
|
||||||
import ui.PreferencesMenu;
|
import funkin.ui.PreferencesMenu;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
|
@ -351,17 +351,6 @@ class TitleState extends MusicBeatState
|
||||||
FlxG.switchState(new CutsceneAnimTestState());
|
FlxG.switchState(new CutsceneAnimTestState());
|
||||||
#end
|
#end
|
||||||
|
|
||||||
/*
|
|
||||||
if (FlxG.keys.justPressed.R)
|
|
||||||
{
|
|
||||||
#if polymod
|
|
||||||
polymod.Polymod.init({modRoot: "mods", dirs: ['introMod']});
|
|
||||||
trace('reinitialized');
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (FlxG.sound.music != null)
|
if (FlxG.sound.music != null)
|
||||||
Conductor.songPosition = FlxG.sound.music.time;
|
Conductor.songPosition = FlxG.sound.music.time;
|
||||||
if (FlxG.keys.justPressed.F)
|
if (FlxG.keys.justPressed.F)
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin;
|
||||||
|
|
||||||
import openfl.display.Sprite;
|
import openfl.display.Sprite;
|
||||||
import openfl.events.AsyncErrorEvent;
|
import openfl.events.AsyncErrorEvent;
|
|
@ -1,3 +1,5 @@
|
||||||
|
package funkin;
|
||||||
|
|
||||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||||
import flixel.system.FlxSound;
|
import flixel.system.FlxSound;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package animate;
|
package funkin.animate;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.FlxState;
|
import flixel.FlxState;
|
|
@ -1,7 +1,5 @@
|
||||||
package animate;
|
package funkin.animate;
|
||||||
|
|
||||||
// import animate.FlxSymbol.Parsed;
|
|
||||||
// import animate.FlxSymbol.Timeline;
|
|
||||||
import flixel.FlxCamera;
|
import flixel.FlxCamera;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
|
@ -1,10 +1,8 @@
|
||||||
package animate;
|
package funkin.animate;
|
||||||
|
|
||||||
// import animateAtlasPlayer.assets.AssetManager;
|
import funkin.animate.ParseAnimate.AnimJson;
|
||||||
// import animateAtlasPlayer.core.Animation;
|
import funkin.animate.ParseAnimate.Sprite;
|
||||||
import animate.ParseAnimate.AnimJson;
|
import funkin.animate.ParseAnimate.Spritemap;
|
||||||
import animate.ParseAnimate.Sprite;
|
|
||||||
import animate.ParseAnimate.Spritemap;
|
|
||||||
import flixel.FlxCamera;
|
import flixel.FlxCamera;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.FlxGraphic;
|
import flixel.graphics.FlxGraphic;
|
|
@ -1,12 +1,12 @@
|
||||||
package animate;
|
package funkin.animate;
|
||||||
|
|
||||||
import animate.ParseAnimate.AnimJson;
|
import funkin.animate.ParseAnimate.AnimJson;
|
||||||
import animate.ParseAnimate.Animation;
|
import funkin.animate.ParseAnimate.Animation;
|
||||||
import animate.ParseAnimate.Frame;
|
import funkin.animate.ParseAnimate.Frame;
|
||||||
import animate.ParseAnimate.Sprite;
|
import funkin.animate.ParseAnimate.Sprite;
|
||||||
import animate.ParseAnimate.Spritemap;
|
import funkin.animate.ParseAnimate.Spritemap;
|
||||||
import animate.ParseAnimate.SymbolDictionary;
|
import funkin.animate.ParseAnimate.SymbolDictionary;
|
||||||
import animate.ParseAnimate.Timeline;
|
import funkin.animate.ParseAnimate.Timeline;
|
||||||
import flixel.FlxCamera;
|
import flixel.FlxCamera;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
|
import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
|
|
@ -1,10 +1,9 @@
|
||||||
package animate;
|
package funkin.animate;
|
||||||
|
|
||||||
import haxe.format.JsonParser;
|
import haxe.format.JsonParser;
|
||||||
import openfl.Assets;
|
import openfl.Assets;
|
||||||
import openfl.geom.Matrix3D;
|
import openfl.geom.Matrix3D;
|
||||||
import openfl.geom.Matrix;
|
import openfl.geom.Matrix;
|
||||||
import sys.io.File;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generally designed / written in a way that can be easily taken out of FNF and used elsewhere
|
* Generally designed / written in a way that can be easily taken out of FNF and used elsewhere
|
|
@ -1,6 +1,6 @@
|
||||||
package animate;
|
package funkin.animate;
|
||||||
|
|
||||||
import animate.FlxSymbol.Frame;
|
import funkin.animate.ParseAnimate.Frame;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.input.mouse.FlxMouseEventManager;
|
import flixel.input.mouse.FlxMouseEventManager;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
|
@ -1,13 +1,13 @@
|
||||||
package audiovis;
|
package funkin.audiovis;
|
||||||
|
|
||||||
import audiovis.dsp.FFT;
|
import funkin.audiovis.dsp.FFT;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.addons.plugin.taskManager.FlxTask;
|
import flixel.addons.plugin.taskManager.FlxTask;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
||||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||||
import flixel.math.FlxMath;
|
import flixel.math.FlxMath;
|
||||||
import flixel.system.FlxSound;
|
import flixel.system.FlxSound;
|
||||||
import ui.PreferencesMenu.CheckboxThingie;
|
import funkin.ui.PreferencesMenu.CheckboxThingie;
|
||||||
|
|
||||||
using Lambda;
|
using Lambda;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package audiovis;
|
package funkin.audiovis;
|
||||||
|
|
||||||
import audiovis.VisShit.CurAudioInfo;
|
import funkin.audiovis.VisShit.CurAudioInfo;
|
||||||
import flixel.math.FlxMath;
|
import flixel.math.FlxMath;
|
||||||
import flixel.math.FlxPoint;
|
import flixel.math.FlxPoint;
|
||||||
import flixel.system.FlxSound;
|
import flixel.system.FlxSound;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import lime.utils.Int16Array;
|
import lime.utils.Int16Array;
|
||||||
import rendering.MeshRender;
|
import funkin.rendering.MeshRender;
|
||||||
|
|
||||||
class PolygonSpectogram extends MeshRender
|
class PolygonSpectogram extends MeshRender
|
||||||
{
|
{
|
|
@ -1,8 +1,8 @@
|
||||||
package audiovis;
|
package funkin.audiovis;
|
||||||
|
|
||||||
import audiovis.PolygonSpectogram.VISTYPE;
|
import funkin.audiovis.PolygonSpectogram.VISTYPE;
|
||||||
import audiovis.VisShit.CurAudioInfo;
|
import funkin.audiovis.VisShit.CurAudioInfo;
|
||||||
import audiovis.dsp.FFT;
|
import funkin.audiovis.dsp.FFT;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.group.FlxGroup;
|
import flixel.group.FlxGroup;
|
||||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
|
@ -1,6 +1,6 @@
|
||||||
package audiovis;
|
package funkin.audiovis;
|
||||||
|
|
||||||
import audiovis.dsp.FFT;
|
import funkin.audiovis.dsp.FFT;
|
||||||
import flixel.math.FlxMath;
|
import flixel.math.FlxMath;
|
||||||
import flixel.system.FlxSound;
|
import flixel.system.FlxSound;
|
||||||
import lime.utils.Int16Array;
|
import lime.utils.Int16Array;
|
|
@ -1,4 +1,4 @@
|
||||||
package audiovis.dsp;
|
package funkin.audiovis.dsp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Complex number representation.
|
Complex number representation.
|
|
@ -1,9 +1,9 @@
|
||||||
package audiovis.dsp;
|
package funkin.audiovis.dsp;
|
||||||
|
|
||||||
import audiovis.dsp.Complex;
|
import funkin.audiovis.dsp.Complex;
|
||||||
|
|
||||||
using audiovis.dsp.OffsetArray;
|
using funkin.audiovis.dsp.OffsetArray;
|
||||||
using audiovis.dsp.Signal;
|
using funkin.audiovis.dsp.Signal;
|
||||||
|
|
||||||
// these are only used for testing, down in FFT.main()
|
// these are only used for testing, down in FFT.main()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package audiovis.dsp;
|
package funkin.audiovis.dsp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A view into an Array with an indexing offset.
|
A view into an Array with an indexing offset.
|
|
@ -1,4 +1,4 @@
|
||||||
package audiovis.dsp;
|
package funkin.audiovis.dsp;
|
||||||
|
|
||||||
using Lambda;
|
using Lambda;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package charting;
|
package funkin.charting;
|
||||||
|
|
||||||
import Conductor.BPMChangeEvent;
|
import funkin.Conductor.BPMChangeEvent;
|
||||||
import Note.NoteData;
|
import funkin.Note.NoteData;
|
||||||
import Section.SwagSection;
|
import funkin.Section.SwagSection;
|
||||||
import SongLoad.SwagSong;
|
import funkin.SongLoad.SwagSong;
|
||||||
import audiovis.ABotVis;
|
import funkin.audiovis.ABotVis;
|
||||||
import audiovis.PolygonSpectogram;
|
import funkin.audiovis.PolygonSpectogram;
|
||||||
import audiovis.SpectogramSprite;
|
import funkin.audiovis.SpectogramSprite;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.addons.display.FlxGridOverlay;
|
import flixel.addons.display.FlxGridOverlay;
|
||||||
import flixel.addons.transition.FlxTransitionableState;
|
import flixel.addons.transition.FlxTransitionableState;
|
||||||
|
@ -29,7 +29,8 @@ import lime.utils.Assets;
|
||||||
import openfl.events.Event;
|
import openfl.events.Event;
|
||||||
import openfl.events.IOErrorEvent;
|
import openfl.events.IOErrorEvent;
|
||||||
import openfl.net.FileReference;
|
import openfl.net.FileReference;
|
||||||
import rendering.MeshRender;
|
import funkin.rendering.MeshRender;
|
||||||
|
import funkin.play.PlayState;
|
||||||
|
|
||||||
using Lambda;
|
using Lambda;
|
||||||
using StringTools;
|
using StringTools;
|
|
@ -1,4 +1,4 @@
|
||||||
package freeplayStuff;
|
package funkin.freeplayStuff;
|
||||||
|
|
||||||
import flixel.FlxObject;
|
import flixel.FlxObject;
|
||||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
|
@ -1,4 +1,4 @@
|
||||||
package freeplayStuff;
|
package funkin.freeplayStuff;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.util.FlxSignal;
|
import flixel.util.FlxSignal;
|
|
@ -1,4 +1,4 @@
|
||||||
package freeplayStuff;
|
package funkin.freeplayStuff;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||||
|
@ -11,6 +11,8 @@ class FreeplayScore extends FlxTypedSpriteGroup<ScoreNum>
|
||||||
|
|
||||||
function set_scoreShit(val):Int
|
function set_scoreShit(val):Int
|
||||||
{
|
{
|
||||||
|
if (group == null || group.members == null)
|
||||||
|
return val;
|
||||||
var loopNum:Int = group.members.length - 1;
|
var loopNum:Int = group.members.length - 1;
|
||||||
var dumbNumb = Std.parseInt(Std.string(val));
|
var dumbNumb = Std.parseInt(Std.string(val));
|
||||||
var prevNum:ScoreNum;
|
var prevNum:ScoreNum;
|
|
@ -1,4 +1,4 @@
|
||||||
package freeplayStuff;
|
package funkin.freeplayStuff;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.graphics.frames.FlxAtlasFrames;
|
import flixel.graphics.frames.FlxAtlasFrames;
|
|
@ -1,4 +1,4 @@
|
||||||
package i18n;
|
package funkin.i18n;
|
||||||
|
|
||||||
import firetongue.FireTongue;
|
import firetongue.FireTongue;
|
||||||
|
|
3
source/funkin/i18n/README.md
Normal file
3
source/funkin/i18n/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# i18n
|
||||||
|
|
||||||
|
This package contains functions used for internationalization (i18n).
|
|
@ -1,6 +1,6 @@
|
||||||
#if !macro
|
#if !macro
|
||||||
// Only import these when we aren't in a macro.
|
// Only import these when we aren't in a macro.
|
||||||
import Paths;
|
import funkin.Paths;
|
||||||
import flixel.FlxG; // This one in particular causes a compile error if you're using macros.
|
import flixel.FlxG; // This one in particular causes a compile error if you're using macros.
|
||||||
|
|
||||||
#end
|
#end
|
|
@ -1,4 +1,4 @@
|
||||||
package modding;
|
package funkin.modding;
|
||||||
|
|
||||||
import polymod.hscript.HScriptable;
|
import polymod.hscript.HScriptable;
|
||||||
|
|
71
source/funkin/modding/PolymodErrorHandler.hx
Normal file
71
source/funkin/modding/PolymodErrorHandler.hx
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package funkin.modding;
|
||||||
|
|
||||||
|
import polymod.Polymod;
|
||||||
|
|
||||||
|
class PolymodErrorHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Show a popup with the given text.
|
||||||
|
* This displays a system popup, it WILL interrupt the game.
|
||||||
|
* Make sure to only use this when it's important, like when there's a script error.
|
||||||
|
*
|
||||||
|
* @param name The name at the top of the popup.
|
||||||
|
* @param desc The body text of the popup.
|
||||||
|
*/
|
||||||
|
public static function showAlert(name:String, desc:String):Void
|
||||||
|
{
|
||||||
|
lime.app.Application.current.window.alert(desc, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function onPolymodError(error:PolymodError):Void
|
||||||
|
{
|
||||||
|
// Perform an action based on the error code.
|
||||||
|
switch (error.code)
|
||||||
|
{
|
||||||
|
case MOD_LOAD_PREPARE:
|
||||||
|
logInfo('[POLYMOD]: ${error.message}');
|
||||||
|
case MOD_LOAD_DONE:
|
||||||
|
logInfo('[POLYMOD]: ${error.message}');
|
||||||
|
case MISSING_ICON:
|
||||||
|
logWarn('[POLYMOD]: A mod is missing an icon. Please add one.');
|
||||||
|
case SCRIPT_PARSE_ERROR:
|
||||||
|
// A syntax error when parsing a script.
|
||||||
|
logError('[POLYMOD]: ${error.message}');
|
||||||
|
showAlert('Polymod Script Parsing Error', error.message);
|
||||||
|
case SCRIPT_EXCEPTION:
|
||||||
|
// A runtime error when running a script.
|
||||||
|
logError('[POLYMOD]: ${error.message}');
|
||||||
|
showAlert('Polymod Script Execution Error', error.message);
|
||||||
|
case SCRIPT_CLASS_NOT_FOUND:
|
||||||
|
// A scripted class tried to reference an unknown superclass.
|
||||||
|
logError('[POLYMOD]: ${error.message}');
|
||||||
|
showAlert('Polymod Script Parsing Error', error.message);
|
||||||
|
default:
|
||||||
|
// Log the message based on its severity.
|
||||||
|
switch (error.severity)
|
||||||
|
{
|
||||||
|
case NOTICE:
|
||||||
|
logInfo('[POLYMOD]: ${error.message}');
|
||||||
|
case WARNING:
|
||||||
|
logWarn('[POLYMOD]: ${error.message}');
|
||||||
|
case ERROR:
|
||||||
|
logError('[POLYMOD]: ${error.message}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function logInfo(message:String):Void
|
||||||
|
{
|
||||||
|
trace('[INFO ] ${message}');
|
||||||
|
}
|
||||||
|
|
||||||
|
static function logError(message:String):Void
|
||||||
|
{
|
||||||
|
trace('[ERROR] ${message}');
|
||||||
|
}
|
||||||
|
|
||||||
|
static function logWarn(message:String):Void
|
||||||
|
{
|
||||||
|
trace('[WARN ] ${message}');
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,11 @@
|
||||||
package modding;
|
package funkin.modding;
|
||||||
|
|
||||||
#if polymod
|
|
||||||
import polymod.Polymod.ModMetadata;
|
import polymod.Polymod.ModMetadata;
|
||||||
import polymod.Polymod;
|
import polymod.Polymod;
|
||||||
import polymod.backends.OpenFLBackend;
|
import polymod.backends.OpenFLBackend;
|
||||||
import polymod.backends.PolymodAssets.PolymodAssetType;
|
import polymod.backends.PolymodAssets.PolymodAssetType;
|
||||||
import polymod.format.ParseRules.LinesParseFormat;
|
import polymod.format.ParseRules.LinesParseFormat;
|
||||||
import polymod.format.ParseRules.TextFileFormat;
|
import polymod.format.ParseRules.TextFileFormat;
|
||||||
#end
|
|
||||||
|
|
||||||
class PolymodHandler
|
class PolymodHandler
|
||||||
{
|
{
|
||||||
|
@ -29,12 +27,8 @@ class PolymodHandler
|
||||||
*/
|
*/
|
||||||
public static function loadAllMods()
|
public static function loadAllMods()
|
||||||
{
|
{
|
||||||
#if polymod
|
|
||||||
trace("Initializing Polymod (using all mods)...");
|
trace("Initializing Polymod (using all mods)...");
|
||||||
loadModsById(getAllModIds());
|
loadModsById(getAllModIds());
|
||||||
#else
|
|
||||||
trace("Polymod not initialized; not supported on this platform.");
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,17 +37,12 @@ class PolymodHandler
|
||||||
public static function loadNoMods()
|
public static function loadNoMods()
|
||||||
{
|
{
|
||||||
// We still need to configure the debug print calls etc.
|
// We still need to configure the debug print calls etc.
|
||||||
#if polymod
|
|
||||||
trace("Initializing Polymod (using no mods)...");
|
trace("Initializing Polymod (using no mods)...");
|
||||||
loadModsById([]);
|
loadModsById([]);
|
||||||
#else
|
|
||||||
trace("Polymod not initialized; not supported on this platform.");
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function loadModsById(ids:Array<String>)
|
public static function loadModsById(ids:Array<String>)
|
||||||
{
|
{
|
||||||
#if polymod
|
|
||||||
if (ids.length == 0)
|
if (ids.length == 0)
|
||||||
{
|
{
|
||||||
trace('You attempted to load zero mods.');
|
trace('You attempted to load zero mods.');
|
||||||
|
@ -72,7 +61,7 @@ class PolymodHandler
|
||||||
// The current version of our API.
|
// The current version of our API.
|
||||||
apiVersion: API_VERSION,
|
apiVersion: API_VERSION,
|
||||||
// Call this function any time an error occurs.
|
// Call this function any time an error occurs.
|
||||||
errorCallback: onPolymodError,
|
errorCallback: PolymodErrorHandler.onPolymodError,
|
||||||
// Enforce semantic version patterns for each mod.
|
// Enforce semantic version patterns for each mod.
|
||||||
// modVersions: null,
|
// modVersions: null,
|
||||||
// A map telling Polymod what the asset type is for unfamiliar file extensions.
|
// A map telling Polymod what the asset type is for unfamiliar file extensions.
|
||||||
|
@ -85,6 +74,9 @@ class PolymodHandler
|
||||||
|
|
||||||
// Parsing rules for various data formats.
|
// Parsing rules for various data formats.
|
||||||
parseRules: buildParseRules(),
|
parseRules: buildParseRules(),
|
||||||
|
|
||||||
|
// Parse hxc files and register the scripted classes in them.
|
||||||
|
useScriptedClasses: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (loadedModList == null)
|
if (loadedModList == null)
|
||||||
|
@ -104,35 +96,38 @@ class PolymodHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
for (mod in loadedModList)
|
for (mod in loadedModList)
|
||||||
|
{
|
||||||
trace(' * ${mod.title} v${mod.modVersion} [${mod.id}]');
|
trace(' * ${mod.title} v${mod.modVersion} [${mod.id}]');
|
||||||
|
}
|
||||||
|
|
||||||
#if debug
|
#if debug
|
||||||
var fileList = Polymod.listModFiles("IMAGE");
|
var fileList = Polymod.listModFiles(PolymodAssetType.IMAGE);
|
||||||
trace('[POLYMOD] Installed mods have replaced ${fileList.length} images.');
|
trace('[POLYMOD] Installed mods have replaced ${fileList.length} images.');
|
||||||
for (item in fileList)
|
for (item in fileList)
|
||||||
trace(' * $item');
|
trace(' * $item');
|
||||||
|
|
||||||
fileList = Polymod.listModFiles("TEXT");
|
fileList = Polymod.listModFiles(PolymodAssetType.TEXT);
|
||||||
trace('[POLYMOD] Installed mods have replaced ${fileList.length} text files.');
|
trace('[POLYMOD] Installed mods have replaced ${fileList.length} text files.');
|
||||||
for (item in fileList)
|
for (item in fileList)
|
||||||
trace(' * $item');
|
trace(' * $item');
|
||||||
|
|
||||||
fileList = Polymod.listModFiles("MUSIC");
|
fileList = Polymod.listModFiles(PolymodAssetType.AUDIO_MUSIC);
|
||||||
trace('[POLYMOD] Installed mods have replaced ${fileList.length} music files.');
|
trace('[POLYMOD] Installed mods have replaced ${fileList.length} music files.');
|
||||||
for (item in fileList)
|
for (item in fileList)
|
||||||
trace(' * $item');
|
trace(' * $item');
|
||||||
|
|
||||||
fileList = Polymod.listModFiles("SOUND");
|
fileList = Polymod.listModFiles(PolymodAssetType.AUDIO_SOUND);
|
||||||
trace('[POLYMOD] Installed mods have replaced ${fileList.length} sound files.');
|
trace('[POLYMOD] Installed mods have replaced ${fileList.length} sound files.');
|
||||||
for (item in fileList)
|
for (item in fileList)
|
||||||
trace(' * $item');
|
trace(' * $item');
|
||||||
#end
|
|
||||||
#else
|
fileList = Polymod.listModFiles(PolymodAssetType.AUDIO_GENERIC);
|
||||||
trace("[POLYMOD] Mods are not supported on this platform.");
|
trace('[POLYMOD] Installed mods have replaced ${fileList.length} generic audio files.');
|
||||||
|
for (item in fileList)
|
||||||
|
trace(' * $item');
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
#if polymod
|
|
||||||
static function buildParseRules():polymod.format.ParseRules
|
static function buildParseRules():polymod.format.ParseRules
|
||||||
{
|
{
|
||||||
var output = polymod.format.ParseRules.getDefault();
|
var output = polymod.format.ParseRules.getDefault();
|
||||||
|
@ -140,6 +135,7 @@ class PolymodHandler
|
||||||
output.addType("txt", TextFileFormat.LINES);
|
output.addType("txt", TextFileFormat.LINES);
|
||||||
// Ensure script files have merge support.
|
// Ensure script files have merge support.
|
||||||
output.addType("hscript", TextFileFormat.PLAINTEXT);
|
output.addType("hscript", TextFileFormat.PLAINTEXT);
|
||||||
|
output.addType("hxs", TextFileFormat.PLAINTEXT);
|
||||||
|
|
||||||
// You can specify the format of a specific file, with file extension.
|
// You can specify the format of a specific file, with file extension.
|
||||||
// output.addFile("data/introText.txt", TextFileFormat.LINES)
|
// output.addFile("data/introText.txt", TextFileFormat.LINES)
|
||||||
|
@ -150,48 +146,18 @@ class PolymodHandler
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
assetLibraryPaths: [
|
assetLibraryPaths: [
|
||||||
"songs" => "./songs", "shared" => "./", "tutorial" => "./tutorial", "scripts" => "./scripts", "week1" => "./week1", "week2" => "./week2",
|
"songs" => "songs", "shared" => "", "tutorial" => "tutorial", "scripts" => "scripts", "week1" => "week1", "week2" => "week2",
|
||||||
"week3" => "./week3", "week4" => "./week4", "week5" => "./week5", "week6" => "./week6", "week7" => "./week7", "week8" => "./week8",
|
"week3" => "week3", "week4" => "week4", "week5" => "week5", "week6" => "week6", "week7" => "week7", "week8" => "week8",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static function onPolymodError(error:PolymodError):Void
|
public static function getAllMods():Array<ModMetadata>
|
||||||
{
|
{
|
||||||
// Perform an action based on the error code.
|
|
||||||
switch (error.code)
|
|
||||||
{
|
|
||||||
case MOD_LOAD_PREPARE:
|
|
||||||
trace('[POLYMOD] ${error.message}');
|
|
||||||
case MOD_LOAD_DONE:
|
|
||||||
trace('[POLYMOD] ${error.message}');
|
|
||||||
case MISSING_ICON:
|
|
||||||
trace('[POLYMOD] A mod is missing an icon. Please add one.');
|
|
||||||
default:
|
|
||||||
// Log the message based on its severity.
|
|
||||||
switch (error.severity)
|
|
||||||
{
|
|
||||||
case NOTICE:
|
|
||||||
trace('[POLYMOD] ${error.message}');
|
|
||||||
case WARNING:
|
|
||||||
trace('[POLYMOD] ${error.message}');
|
|
||||||
case ERROR:
|
|
||||||
trace('[POLYMOD] ${error.message}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
public static function getAllMods()
|
|
||||||
{
|
|
||||||
#if polymod
|
|
||||||
trace('Scanning the mods folder...');
|
trace('Scanning the mods folder...');
|
||||||
var modMetadata = Polymod.scan(MOD_FOLDER);
|
var modMetadata = Polymod.scan(MOD_FOLDER);
|
||||||
trace('Found ${modMetadata.length} mods when scanning.');
|
trace('Found ${modMetadata.length} mods when scanning.');
|
||||||
return modMetadata;
|
return modMetadata;
|
||||||
#else
|
|
||||||
return new Array<Dynamic>();
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAllModIds():Array<String>
|
public static function getAllModIds():Array<String>
|
5
source/funkin/modding/base/README.md
Normal file
5
source/funkin/modding/base/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# modding.base
|
||||||
|
|
||||||
|
This package is used to allow modders to create scripted classes which extend these base classes.
|
||||||
|
For example, one script can extend FlxSprite and another can call `ScriptedFlxSprite.init('ClassName')`.
|
||||||
|
Most of these scripted class stubs are not used by the game itself, so this package has been explicitly marked to be ignored by DCE.
|
10
source/funkin/modding/base/ScriptedFlxSprite.hx
Normal file
10
source/funkin/modding/base/ScriptedFlxSprite.hx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package funkin.modding.base;
|
||||||
|
|
||||||
|
import flixel.FlxSprite;
|
||||||
|
import funkin.modding.IHook;
|
||||||
|
|
||||||
|
@:hscriptClass
|
||||||
|
class ScriptedFlxSprite extends FlxSprite implements IHook
|
||||||
|
{
|
||||||
|
// No body needed for this class, it's magic ;)
|
||||||
|
}
|
10
source/funkin/modding/base/ScriptedFlxSpriteGroup.hx
Normal file
10
source/funkin/modding/base/ScriptedFlxSpriteGroup.hx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package funkin.modding.base;
|
||||||
|
|
||||||
|
import flixel.group.FlxSpriteGroup;
|
||||||
|
import funkin.modding.IHook;
|
||||||
|
|
||||||
|
@:hscriptClass
|
||||||
|
class ScriptedFlxSpriteGroup extends FlxSpriteGroup implements IHook
|
||||||
|
{
|
||||||
|
// No body needed for this class, it's magic ;)
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package play;
|
package funkin.play;
|
||||||
|
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package play;
|
package funkin.play;
|
||||||
|
|
||||||
import Note.NoteData;
|
import funkin.Note.NoteData;
|
||||||
import audiovis.PolygonSpectogram;
|
import funkin.audiovis.PolygonSpectogram;
|
||||||
import flixel.FlxObject;
|
import flixel.FlxObject;
|
||||||
import flixel.FlxSprite;
|
import flixel.FlxSprite;
|
||||||
import flixel.addons.effects.FlxTrail;
|
import flixel.addons.effects.FlxTrail;
|
File diff suppressed because it is too large
Load diff
9
source/funkin/play/character/Character.hx
Normal file
9
source/funkin/play/character/Character.hx
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package funkin.play.character;
|
||||||
|
|
||||||
|
enum CharacterType
|
||||||
|
{
|
||||||
|
BF;
|
||||||
|
GF;
|
||||||
|
DAD;
|
||||||
|
OTHER;
|
||||||
|
}
|
119
source/funkin/play/stage/Bopper.hx
Normal file
119
source/funkin/play/stage/Bopper.hx
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
package funkin.play.stage;
|
||||||
|
|
||||||
|
import flixel.FlxSprite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Bopper is a stage prop which plays a dance animation.
|
||||||
|
* Y'know, a thingie that bops. A bopper.
|
||||||
|
*/
|
||||||
|
class Bopper extends FlxSprite
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The bopper plays the dance animation once every `danceEvery` beats.
|
||||||
|
*/
|
||||||
|
public var danceEvery:Int = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the bopper should dance left and right.
|
||||||
|
* - If true, alternate playing `danceLeft` and `danceRight`.
|
||||||
|
* - If false, play `idle` every time.
|
||||||
|
*
|
||||||
|
* You can manually set this value, or you can leave it as `null` to determine it automatically.
|
||||||
|
*/
|
||||||
|
public var shouldAlternate:Null<Bool> = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this value to define an additional horizontal offset to this sprite's position.
|
||||||
|
*/
|
||||||
|
public var xOffset:Float = 0;
|
||||||
|
|
||||||
|
override function set_x(value:Float):Float
|
||||||
|
{
|
||||||
|
this.x = value + this.xOffset;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public var idleSuffix(default, set):String = "";
|
||||||
|
|
||||||
|
function set_idleSuffix(value:String):String
|
||||||
|
{
|
||||||
|
this.idleSuffix = value;
|
||||||
|
this.dance();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this value to define an additional vertical offset to this sprite's position.
|
||||||
|
*/
|
||||||
|
public var yOffset:Float = 0;
|
||||||
|
|
||||||
|
override function set_y(value:Float):Float
|
||||||
|
{
|
||||||
|
this.y = value + this.yOffset;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to play `danceRight` next iteration.
|
||||||
|
* Only used when `shouldAlternate` is true.
|
||||||
|
*/
|
||||||
|
var hasDanced:Bool = false;
|
||||||
|
|
||||||
|
public function new(danceEvery:Int = 1)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this.danceEvery = danceEvery;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_shouldAlternate():Void
|
||||||
|
{
|
||||||
|
if (this.animation.getByName('danceLeft') != null)
|
||||||
|
{
|
||||||
|
this.shouldAlternate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called once every beat of the song.
|
||||||
|
*/
|
||||||
|
public function onBeatHit(curBeat:Int):Void
|
||||||
|
{
|
||||||
|
if (curBeat % danceEvery == 0)
|
||||||
|
{
|
||||||
|
dance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called every `danceEvery` beats of the song.
|
||||||
|
*/
|
||||||
|
public function dance():Void
|
||||||
|
{
|
||||||
|
if (this.animation == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldAlternate == null)
|
||||||
|
{
|
||||||
|
update_shouldAlternate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldAlternate)
|
||||||
|
{
|
||||||
|
if (hasDanced)
|
||||||
|
{
|
||||||
|
this.animation.play('danceRight$idleSuffix');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.animation.play('danceLeft$idleSuffix');
|
||||||
|
}
|
||||||
|
hasDanced = !hasDanced;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.animation.play('idle$idleSuffix');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
source/funkin/play/stage/ScriptedBopper.hx
Normal file
10
source/funkin/play/stage/ScriptedBopper.hx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package funkin.play.stage;
|
||||||
|
|
||||||
|
import funkin.modding.IHook;
|
||||||
|
|
||||||
|
@:hscriptClass
|
||||||
|
@:keep
|
||||||
|
class ScriptedBopper extends Bopper implements IHook
|
||||||
|
{
|
||||||
|
// No body needed for this class, it's magic ;)
|
||||||
|
}
|
9
source/funkin/play/stage/ScriptedStage.hx
Normal file
9
source/funkin/play/stage/ScriptedStage.hx
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package funkin.play.stage;
|
||||||
|
|
||||||
|
import funkin.modding.IHook;
|
||||||
|
|
||||||
|
@:hscriptClass
|
||||||
|
class ScriptedStage extends Stage implements IHook
|
||||||
|
{
|
||||||
|
// No body needed for this class, it's magic ;)
|
||||||
|
}
|
402
source/funkin/play/stage/Stage.hx
Normal file
402
source/funkin/play/stage/Stage.hx
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
package funkin.play.stage;
|
||||||
|
|
||||||
|
import flixel.FlxSprite;
|
||||||
|
import flixel.group.FlxSpriteGroup;
|
||||||
|
import flixel.math.FlxPoint;
|
||||||
|
import flixel.util.FlxSort;
|
||||||
|
import funkin.modding.IHook;
|
||||||
|
import funkin.play.character.Character.CharacterType;
|
||||||
|
import funkin.play.stage.StageData.StageDataParser;
|
||||||
|
import funkin.util.SortUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Stage is a group of objects rendered in the PlayState.
|
||||||
|
*
|
||||||
|
* A Stage is comprised of one or more props, each of which is a FlxSprite.
|
||||||
|
*/
|
||||||
|
class Stage extends FlxSpriteGroup implements IHook
|
||||||
|
{
|
||||||
|
public final stageId:String;
|
||||||
|
public final stageName:String;
|
||||||
|
|
||||||
|
final _data:StageData;
|
||||||
|
|
||||||
|
public var camZoom:Float = 1.0;
|
||||||
|
|
||||||
|
var namedProps:Map<String, FlxSprite> = new Map<String, FlxSprite>();
|
||||||
|
var characters:Map<String, Character> = new Map<String, Character>();
|
||||||
|
var boppers:Array<Bopper> = new Array<Bopper>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Stage elements get initialized at the beginning of the game.
|
||||||
|
* They're used to cache the data needed to build the stage,
|
||||||
|
* then accessed and fleshed out when the stage needs to be built.
|
||||||
|
*
|
||||||
|
* @param stageId
|
||||||
|
*/
|
||||||
|
public function new(stageId:String)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.stageId = stageId;
|
||||||
|
_data = StageDataParser.parseStageData(this.stageId);
|
||||||
|
if (_data == null)
|
||||||
|
{
|
||||||
|
throw 'Could not find stage data for stageId: $stageId';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.stageName = _data.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default stage construction routine. Called when the stage is going to be played in.
|
||||||
|
* Instantiates each prop and adds it to the stage, while setting its parameters.
|
||||||
|
*/
|
||||||
|
public function buildStage()
|
||||||
|
{
|
||||||
|
trace('Building stage for display: ${this.stageId}');
|
||||||
|
|
||||||
|
this.camZoom = _data.cameraZoom;
|
||||||
|
// this.scrollFactor = new FlxPoint(1, 1);
|
||||||
|
|
||||||
|
for (dataProp in _data.props)
|
||||||
|
{
|
||||||
|
trace(' Placing prop: ${dataProp.name} (${dataProp.assetPath})');
|
||||||
|
|
||||||
|
var isAnimated = dataProp.animations.length > 0;
|
||||||
|
|
||||||
|
var propSprite:FlxSprite;
|
||||||
|
if (dataProp.danceEvery != 0)
|
||||||
|
{
|
||||||
|
propSprite = new Bopper(dataProp.danceEvery);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
propSprite = new FlxSprite();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAnimated)
|
||||||
|
{
|
||||||
|
// Initalize sprite frames.
|
||||||
|
switch (dataProp.animType)
|
||||||
|
{
|
||||||
|
case "packer":
|
||||||
|
propSprite.frames = Paths.getPackerAtlas(dataProp.assetPath);
|
||||||
|
default: // "sparrow"
|
||||||
|
propSprite.frames = Paths.getSparrowAtlas(dataProp.assetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Initalize static sprite.
|
||||||
|
propSprite.loadGraphic(Paths.image(dataProp.assetPath));
|
||||||
|
|
||||||
|
// Disables calls to update() for a performance boost.
|
||||||
|
propSprite.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propSprite.frames == null || propSprite.frames.numFrames == 0)
|
||||||
|
{
|
||||||
|
trace(' ERROR: Could not build texture for prop.');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Std.isOfType(dataProp.scale, Array))
|
||||||
|
{
|
||||||
|
propSprite.scale.set(dataProp.scale[0], dataProp.scale[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
propSprite.scale.set(dataProp.scale);
|
||||||
|
}
|
||||||
|
propSprite.updateHitbox();
|
||||||
|
|
||||||
|
propSprite.x = dataProp.position[0];
|
||||||
|
propSprite.y = dataProp.position[1];
|
||||||
|
|
||||||
|
// If pixel, disable antialiasing.
|
||||||
|
propSprite.antialiasing = !dataProp.isPixel;
|
||||||
|
|
||||||
|
propSprite.scrollFactor.x = dataProp.scroll[0];
|
||||||
|
propSprite.scrollFactor.y = dataProp.scroll[1];
|
||||||
|
|
||||||
|
propSprite.zIndex = dataProp.zIndex;
|
||||||
|
|
||||||
|
switch (dataProp.animType)
|
||||||
|
{
|
||||||
|
case "packer":
|
||||||
|
for (propAnim in dataProp.animations)
|
||||||
|
{
|
||||||
|
propSprite.animation.add(propAnim.name, propAnim.frameIndices);
|
||||||
|
}
|
||||||
|
default: // "sparrow"
|
||||||
|
for (propAnim in dataProp.animations)
|
||||||
|
{
|
||||||
|
if (propAnim.frameIndices.length == 0)
|
||||||
|
{
|
||||||
|
propSprite.animation.addByPrefix(propAnim.name, propAnim.prefix, propAnim.frameRate, propAnim.loop, propAnim.flipX,
|
||||||
|
propAnim.flipY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
propSprite.animation.addByIndices(propAnim.name, propAnim.prefix, propAnim.frameIndices, "", propAnim.frameRate, propAnim.loop,
|
||||||
|
propAnim.flipX, propAnim.flipY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataProp.startingAnimation != null)
|
||||||
|
{
|
||||||
|
propSprite.animation.play(dataProp.startingAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Std.isOfType(propSprite, Bopper))
|
||||||
|
{
|
||||||
|
addBopper(cast propSprite, dataProp.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addProp(propSprite, dataProp.name);
|
||||||
|
}
|
||||||
|
trace(' Prop placed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a sprite to the stage.
|
||||||
|
* @param prop The sprite to add.
|
||||||
|
* @param name (Optional) A unique name for the sprite.
|
||||||
|
* You can call `getNamedProp(name)` to retrieve it later.
|
||||||
|
*/
|
||||||
|
public function addProp(prop:FlxSprite, ?name:String = null)
|
||||||
|
{
|
||||||
|
if (name != null)
|
||||||
|
{
|
||||||
|
namedProps.set(name, prop);
|
||||||
|
}
|
||||||
|
this.add(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a sprite to the stage which animates to the beat of the song.
|
||||||
|
*/
|
||||||
|
public function addBopper(bopper:Bopper, ?name:String = null)
|
||||||
|
{
|
||||||
|
boppers.push(bopper);
|
||||||
|
this.addProp(bopper, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the stage, by redoing the render order of all props.
|
||||||
|
* It does this based on the `zIndex` of each prop.
|
||||||
|
*/
|
||||||
|
public function refresh()
|
||||||
|
{
|
||||||
|
sort(SortUtil.byZIndex, FlxSort.ASCENDING);
|
||||||
|
trace('Stage sorted by z-index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the stage and it's props (needs to be overridden with your own logic!)
|
||||||
|
*/
|
||||||
|
public function resetStage()
|
||||||
|
{
|
||||||
|
// Override me in your script to reset stage shit however you please!
|
||||||
|
// also note: maybe add some default behaviour to reset stage stuff?
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that should get called every frame.
|
||||||
|
*/
|
||||||
|
public function onUpdate(elapsed:Float):Void
|
||||||
|
{
|
||||||
|
// Override me in your scripted stage to perform custom behavior!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that gets called when the player hits a note.
|
||||||
|
*/
|
||||||
|
public function onNoteHit(note:Note):Void
|
||||||
|
{
|
||||||
|
// Override me in your scripted stage to perform custom behavior!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that gets called when the player hits a note.
|
||||||
|
*/
|
||||||
|
public function onNoteMiss(note:Note):Void
|
||||||
|
{
|
||||||
|
// Override me in your scripted stage to perform custom behavior!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the position and other properties of the soon-to-be child of this sprite group.
|
||||||
|
* Private helper to avoid duplicate code in `add()` and `insert()`.
|
||||||
|
*
|
||||||
|
* @param Sprite The sprite or sprite group that is about to be added or inserted into the group.
|
||||||
|
*/
|
||||||
|
override function preAdd(Sprite:FlxSprite):Void
|
||||||
|
{
|
||||||
|
var sprite:FlxSprite = cast Sprite;
|
||||||
|
sprite.x += x;
|
||||||
|
sprite.y += y;
|
||||||
|
sprite.alpha *= alpha;
|
||||||
|
// Don't override scroll factors.
|
||||||
|
// sprite.scrollFactor.copyFrom(scrollFactor);
|
||||||
|
sprite.cameras = _cameras; // _cameras instead of cameras because get_cameras() will not return null
|
||||||
|
|
||||||
|
if (clipRect != null)
|
||||||
|
clipRectTransform(sprite, clipRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that gets called once per step in the song.
|
||||||
|
* @param curStep The current step number.
|
||||||
|
*/
|
||||||
|
public function onStepHit(curStep:Int):Void
|
||||||
|
{
|
||||||
|
// Override me in your scripted stage to perform custom behavior!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that gets called once per beat in the song (once every four steps).
|
||||||
|
* @param curStep The current beat number.
|
||||||
|
*/
|
||||||
|
public function onBeatHit(curBeat:Int):Void
|
||||||
|
{
|
||||||
|
// Override me in your scripted stage to perform custom behavior!
|
||||||
|
// Make sure to call super.onBeatHit(curBeat) if you want to keep the boppers dancing.
|
||||||
|
|
||||||
|
for (bopper in boppers)
|
||||||
|
{
|
||||||
|
bopper.onBeatHit(curBeat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by the PlayState to add a character to the stage.
|
||||||
|
*/
|
||||||
|
public function addCharacter(character:Character, charType:CharacterType)
|
||||||
|
{
|
||||||
|
// Apply position and z-index.
|
||||||
|
switch (charType)
|
||||||
|
{
|
||||||
|
case BF:
|
||||||
|
this.characters.set("bf", character);
|
||||||
|
character.zIndex = _data.characters.bf.zIndex;
|
||||||
|
character.x = _data.characters.bf.position[0];
|
||||||
|
character.y = _data.characters.bf.position[1];
|
||||||
|
case GF:
|
||||||
|
this.characters.set("gf", character);
|
||||||
|
character.zIndex = _data.characters.gf.zIndex;
|
||||||
|
character.x = _data.characters.gf.position[0];
|
||||||
|
character.y = _data.characters.gf.position[1];
|
||||||
|
case DAD:
|
||||||
|
this.characters.set("dad", character);
|
||||||
|
character.zIndex = _data.characters.dad.zIndex;
|
||||||
|
character.x = _data.characters.dad.position[0];
|
||||||
|
character.y = _data.characters.dad.position[1];
|
||||||
|
default:
|
||||||
|
this.characters.set(character.curCharacter, character);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the character to the scene.
|
||||||
|
this.add(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a given character from the stage.
|
||||||
|
*/
|
||||||
|
public function getCharacter(id:String):Character
|
||||||
|
{
|
||||||
|
return this.characters.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBoyfriend():Character
|
||||||
|
{
|
||||||
|
return getCharacter('bf');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGirlfriend():Character
|
||||||
|
{
|
||||||
|
return getCharacter('gf');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDad():Character
|
||||||
|
{
|
||||||
|
return getCharacter('dad');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a specific prop by the name assigned in the JSON file.
|
||||||
|
* @param name The name of the prop to retrieve.
|
||||||
|
* @return The corresponding FlxSprite.
|
||||||
|
*/
|
||||||
|
public function getNamedProp(name:String):FlxSprite
|
||||||
|
{
|
||||||
|
return this.namedProps.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a list of all the asset paths required to load the stage.
|
||||||
|
* Override this in a scripted class to ensure that all necessary assets are loaded!
|
||||||
|
*
|
||||||
|
* @return An array of file names.
|
||||||
|
*/
|
||||||
|
public function fetchAssetPaths():Array<String>
|
||||||
|
{
|
||||||
|
var result:Array<String> = [];
|
||||||
|
for (dataProp in _data.props)
|
||||||
|
{
|
||||||
|
result.push(Paths.image(dataProp.assetPath));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform cleanup for when you are leaving the level.
|
||||||
|
*/
|
||||||
|
public override function kill()
|
||||||
|
{
|
||||||
|
super.kill();
|
||||||
|
|
||||||
|
for (prop in this.namedProps)
|
||||||
|
{
|
||||||
|
prop.destroy();
|
||||||
|
}
|
||||||
|
namedProps.clear();
|
||||||
|
|
||||||
|
for (char in this.characters)
|
||||||
|
{
|
||||||
|
char.destroy();
|
||||||
|
}
|
||||||
|
characters.clear();
|
||||||
|
|
||||||
|
for (bopper in boppers)
|
||||||
|
{
|
||||||
|
bopper.destroy();
|
||||||
|
}
|
||||||
|
boppers = [];
|
||||||
|
|
||||||
|
for (sprite in this.group)
|
||||||
|
{
|
||||||
|
sprite.destroy();
|
||||||
|
}
|
||||||
|
group.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform cleanup for when you are destroying the stage
|
||||||
|
* and removing all its data from cache.
|
||||||
|
*
|
||||||
|
* Call this ONLY when you are performing a hard cache clear.
|
||||||
|
*/
|
||||||
|
public override function destroy()
|
||||||
|
{
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
}
|
509
source/funkin/play/stage/StageData.hx
Normal file
509
source/funkin/play/stage/StageData.hx
Normal file
|
@ -0,0 +1,509 @@
|
||||||
|
package funkin.play.stage;
|
||||||
|
|
||||||
|
import openfl.Assets;
|
||||||
|
import funkin.util.assets.DataAssets;
|
||||||
|
import haxe.Json;
|
||||||
|
import flixel.util.typeLimit.OneOfTwo;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains utilities for loading and parsing stage data.
|
||||||
|
*/
|
||||||
|
class StageDataParser
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The current version string for the stage data format.
|
||||||
|
* Handle breaking changes by incrementing this value
|
||||||
|
* and adding migration to the `migrateStageData()` function.
|
||||||
|
*/
|
||||||
|
public static final STAGE_DATA_VERSION:String = "1.0";
|
||||||
|
|
||||||
|
static final stageCache:Map<String, Stage> = new Map<String, Stage>();
|
||||||
|
|
||||||
|
static final DEFAULT_STAGE_ID = 'UNKNOWN';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses and preloads the game's stage data and scripts when the game starts.
|
||||||
|
*
|
||||||
|
* If you want to force stages to be reloaded, you can just call this function again.
|
||||||
|
*/
|
||||||
|
public static function loadStageCache():Void
|
||||||
|
{
|
||||||
|
// Clear any stages that are cached if there were any.
|
||||||
|
clearStageCache();
|
||||||
|
trace("[STAGEDATA] Loading stage cache...");
|
||||||
|
|
||||||
|
//
|
||||||
|
// SCRIPTED STAGES
|
||||||
|
//
|
||||||
|
var scriptedStageClassNames:Array<String> = ScriptedStage.listScriptClasses();
|
||||||
|
trace(' Instantiating ${scriptedStageClassNames.length} scripted stages...');
|
||||||
|
for (stageCls in scriptedStageClassNames)
|
||||||
|
{
|
||||||
|
var stage:Stage = ScriptedStage.init(stageCls, DEFAULT_STAGE_ID);
|
||||||
|
if (stage != null)
|
||||||
|
{
|
||||||
|
trace(' Loaded scripted stage: ${stage.stageName}');
|
||||||
|
// Disable the rendering logic for stage until it's loaded.
|
||||||
|
// Note that kill() =/= destroy()
|
||||||
|
stage.kill();
|
||||||
|
|
||||||
|
// Then store it.
|
||||||
|
stageCache.set(stage.stageId, stage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trace(' Failed to instantiate scripted stage class: ${stageCls}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// UNSCRIPTED STAGES
|
||||||
|
//
|
||||||
|
var stageIdList:Array<String> = DataAssets.listDataFilesInPath('stages/');
|
||||||
|
var unscriptedStageIds:Array<String> = stageIdList.filter(function(stageId:String):Bool
|
||||||
|
{
|
||||||
|
return !stageCache.exists(stageId);
|
||||||
|
});
|
||||||
|
trace(' Instantiating ${unscriptedStageIds.length} non-scripted stages...');
|
||||||
|
for (stageId in unscriptedStageIds)
|
||||||
|
{
|
||||||
|
var stage:Stage;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stage = new Stage(stageId);
|
||||||
|
if (stage != null)
|
||||||
|
{
|
||||||
|
trace(' Loaded stage data: ${stage.stageName}');
|
||||||
|
stageCache.set(stageId, stage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
// Assume error was already logged.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trace(' Successfully loaded ${Lambda.count(stageCache)} stages.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fetchStage(stageId:String):Null<Stage>
|
||||||
|
{
|
||||||
|
if (stageCache.exists(stageId))
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] Successfully fetch stage: ${stageId}');
|
||||||
|
var stage:Stage = stageCache.get(stageId);
|
||||||
|
stage.revive();
|
||||||
|
return stage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] Failed to fetch stage, not found in cache: ${stageId}');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function clearStageCache():Void
|
||||||
|
{
|
||||||
|
if (stageCache != null)
|
||||||
|
{
|
||||||
|
for (stage in stageCache)
|
||||||
|
{
|
||||||
|
stage.destroy();
|
||||||
|
}
|
||||||
|
stageCache.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a stage's JSON file, parse its data, and return it.
|
||||||
|
*
|
||||||
|
* @param stageId The stage to load.
|
||||||
|
* @return The stage data, or null if validation failed.
|
||||||
|
*/
|
||||||
|
public static function parseStageData(stageId:String):Null<StageData>
|
||||||
|
{
|
||||||
|
var rawJson:String = loadStageFile(stageId);
|
||||||
|
|
||||||
|
var stageData:StageData = migrateStageData(rawJson, stageId);
|
||||||
|
|
||||||
|
return validateStageData(stageId, stageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function loadStageFile(stagePath:String):String
|
||||||
|
{
|
||||||
|
var stageFilePath:String = Paths.json('stages/${stagePath}');
|
||||||
|
var rawJson = Assets.getText(stageFilePath).trim();
|
||||||
|
|
||||||
|
while (!rawJson.endsWith("}"))
|
||||||
|
{
|
||||||
|
rawJson = rawJson.substr(0, rawJson.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function migrateStageData(rawJson:String, stageId:String)
|
||||||
|
{
|
||||||
|
// If you update the stage data format in a breaking way,
|
||||||
|
// handle migration here by checking the `version` value.
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stageData:StageData = cast Json.parse(rawJson);
|
||||||
|
return stageData;
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
trace(' Error parsing data for stage: ${stageId}');
|
||||||
|
trace(' ${e}');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final DEFAULT_NAME:String = "Untitled Stage";
|
||||||
|
static final DEFAULT_CAMERAZOOM:Float = 1.0;
|
||||||
|
static final DEFAULT_ZINDEX:Int = 0;
|
||||||
|
static final DEFAULT_DANCEEVERY:Int = 0;
|
||||||
|
static final DEFAULT_SCALE:Float = 1.0;
|
||||||
|
static final DEFAULT_ISPIXEL:Bool = false;
|
||||||
|
static final DEFAULT_POSITION:Array<Float> = [0, 0];
|
||||||
|
static final DEFAULT_SCROLL:Array<Float> = [0, 0];
|
||||||
|
static final DEFAULT_FRAMEINDICES:Array<Int> = [];
|
||||||
|
static final DEFAULT_ANIMTYPE:String = "sparrow";
|
||||||
|
|
||||||
|
static final DEFAULT_CHARACTER_DATA:StageDataCharacter = {
|
||||||
|
zIndex: DEFAULT_ZINDEX,
|
||||||
|
position: DEFAULT_POSITION,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set unspecified parameters to their defaults.
|
||||||
|
* If the parameter is mandatory, print an error message.
|
||||||
|
* @param id
|
||||||
|
* @param input
|
||||||
|
* @return The validated stage data
|
||||||
|
*/
|
||||||
|
static function validateStageData(id:String, input:StageData):Null<StageData>
|
||||||
|
{
|
||||||
|
if (input == null)
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] ERROR: Could not parse stage data for "${id}".');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.version != STAGE_DATA_VERSION)
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] ERROR: Could not load stage data for "$id": missing version');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.name == null)
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] WARN: Stage data for "$id" missing name');
|
||||||
|
input.name = DEFAULT_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.cameraZoom == null)
|
||||||
|
{
|
||||||
|
input.cameraZoom = DEFAULT_CAMERAZOOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.props == null || input.props.length == 0)
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] ERROR: Could not load stage data for "$id": missing props');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (inputProp in input.props)
|
||||||
|
{
|
||||||
|
// It's fine for inputProp.name to be null
|
||||||
|
|
||||||
|
if (inputProp.assetPath == null)
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] ERROR: Could not load stage data for "$id": missing assetPath for prop "${inputProp.name}"');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.position == null)
|
||||||
|
{
|
||||||
|
inputProp.position = DEFAULT_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.zIndex == null)
|
||||||
|
{
|
||||||
|
inputProp.zIndex = DEFAULT_ZINDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.isPixel == null)
|
||||||
|
{
|
||||||
|
inputProp.isPixel = DEFAULT_ISPIXEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.danceEvery == null)
|
||||||
|
{
|
||||||
|
inputProp.danceEvery = DEFAULT_DANCEEVERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.scale == null)
|
||||||
|
{
|
||||||
|
inputProp.scale = DEFAULT_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.animType == null)
|
||||||
|
{
|
||||||
|
inputProp.animType = DEFAULT_ANIMTYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Std.isOfType(inputProp.scale, Float))
|
||||||
|
{
|
||||||
|
inputProp.scale = [inputProp.scale, inputProp.scale];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.scroll == null)
|
||||||
|
{
|
||||||
|
inputProp.scroll = DEFAULT_SCROLL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Std.isOfType(inputProp.scroll, Float))
|
||||||
|
{
|
||||||
|
inputProp.scroll = [inputProp.scroll, inputProp.scroll];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.animations == null)
|
||||||
|
{
|
||||||
|
inputProp.animations = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputProp.animations.length == 0 && inputProp.startingAnimation != null)
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] ERROR: Could not load stage data for "$id": missing animations for prop "${inputProp.name}"');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (inputAnimation in inputProp.animations)
|
||||||
|
{
|
||||||
|
if (inputAnimation.name == null)
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] ERROR: Could not load stage data for "$id": missing animation name for prop "${inputProp.name}"');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputAnimation.frameRate == null)
|
||||||
|
{
|
||||||
|
inputAnimation.frameRate = 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputAnimation.frameIndices == null)
|
||||||
|
{
|
||||||
|
inputAnimation.frameIndices = DEFAULT_FRAMEINDICES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputAnimation.loop == null)
|
||||||
|
{
|
||||||
|
inputAnimation.loop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputAnimation.flipX == null)
|
||||||
|
{
|
||||||
|
inputAnimation.flipX = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputAnimation.flipY == null)
|
||||||
|
{
|
||||||
|
inputAnimation.flipY = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.characters == null)
|
||||||
|
{
|
||||||
|
trace('[STAGEDATA] ERROR: Could not load stage data for "$id": missing characters');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.characters.bf == null)
|
||||||
|
{
|
||||||
|
input.characters.bf = DEFAULT_CHARACTER_DATA;
|
||||||
|
}
|
||||||
|
if (input.characters.dad == null)
|
||||||
|
{
|
||||||
|
input.characters.dad = DEFAULT_CHARACTER_DATA;
|
||||||
|
}
|
||||||
|
if (input.characters.gf == null)
|
||||||
|
{
|
||||||
|
input.characters.gf = DEFAULT_CHARACTER_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (inputCharacter in [input.characters.bf, input.characters.dad, input.characters.gf])
|
||||||
|
{
|
||||||
|
if (inputCharacter.zIndex == null)
|
||||||
|
{
|
||||||
|
inputCharacter.zIndex = 0;
|
||||||
|
}
|
||||||
|
if (inputCharacter.position == null || inputCharacter.position.length != 2)
|
||||||
|
{
|
||||||
|
inputCharacter.position = [0, 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All good!
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef StageData =
|
||||||
|
{
|
||||||
|
// Uses semantic versioning.
|
||||||
|
var version:String;
|
||||||
|
var name:String;
|
||||||
|
var cameraZoom:Null<Float>;
|
||||||
|
var props:Array<StageDataProp>;
|
||||||
|
var characters:
|
||||||
|
{
|
||||||
|
bf:StageDataCharacter,
|
||||||
|
dad:StageDataCharacter,
|
||||||
|
gf:StageDataCharacter,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef StageDataProp =
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name of the prop for later lookup by scripts.
|
||||||
|
* Optional; if unspecified, the prop can't be referenced by scripts.
|
||||||
|
*/
|
||||||
|
var name:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The asset used to display the prop.
|
||||||
|
*/
|
||||||
|
var assetPath:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position of the prop as an [x, y] array of two floats.
|
||||||
|
*/
|
||||||
|
var position:Array<Float>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A number determining the stack order of the prop, relative to other props and the characters in the stage.
|
||||||
|
* Props with lower numbers render below those with higher numbers.
|
||||||
|
* This is just like CSS, it isn't hard.
|
||||||
|
* @default 0
|
||||||
|
*/
|
||||||
|
var zIndex:Null<Int>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to true, anti-aliasing will be forcibly disabled on the sprite.
|
||||||
|
* This prevents blurry images on pixel-art levels.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
var isPixel:Null<Bool>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Either the scale of the prop as a float, or the [w, h] scale as an array of two floats.
|
||||||
|
* Pro tip: On pixel-art levels, save the sprite small and set this value to 6 or so to save memory.
|
||||||
|
* @default 1
|
||||||
|
*/
|
||||||
|
var scale:OneOfTwo<Float, Array<Float>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If not zero, this prop will play an animation every X beats of the song.
|
||||||
|
* This requires animations to be defined. If `danceLeft` and `danceRight` are defined,
|
||||||
|
* they will alternated between, otherwise the `idle` animation will be used.
|
||||||
|
*
|
||||||
|
* @default 0
|
||||||
|
*/
|
||||||
|
var danceEvery:Null<Int>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How much the prop scrolls relative to the camera. Used to create a parallax effect.
|
||||||
|
* Represented as a float or as an [x, y] array of two floats.
|
||||||
|
* [1, 1] means the prop moves 1:1 with the camera.
|
||||||
|
* [0.5, 0.5] means the prop half as much as the camera.
|
||||||
|
* [0, 0] means the prop is not moved.
|
||||||
|
* @default [0, 0]
|
||||||
|
*/
|
||||||
|
var scroll:OneOfTwo<Float, Array<Float>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional array of animations which the prop can play.
|
||||||
|
* @default Prop has no animations.
|
||||||
|
*/
|
||||||
|
var animations:Array<StageDataPropAnimation>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If animations are used, this is the name of the animation to play first.
|
||||||
|
* @default Don't play an animation.
|
||||||
|
*/
|
||||||
|
var startingAnimation:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The animation type to use.
|
||||||
|
* Options: "sparrow", "packer"
|
||||||
|
* @default "sparrow"
|
||||||
|
*/
|
||||||
|
var animType:String;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef StageDataPropAnimation =
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name of the animation.
|
||||||
|
*/
|
||||||
|
var name:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The common beginning of image names in atlas for this animation's frames.
|
||||||
|
* For example, if the frames are named "test0001.png", "test0002.png", etc., use "test".
|
||||||
|
*/
|
||||||
|
var prefix:String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you want this animation to use only certain frames of an animation with a given prefix,
|
||||||
|
* select them here.
|
||||||
|
* @example [0, 1, 2, 3] (use only the first four frames)
|
||||||
|
* @default [] (all frames)
|
||||||
|
*/
|
||||||
|
var frameIndices:Array<Int>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The speed of the animation in frames per second.
|
||||||
|
* @default 24
|
||||||
|
*/
|
||||||
|
var frameRate:Null<Int>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the animation should loop.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
var loop:Null<Bool>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to flip the sprite horizontally while animating.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
var flipX:Null<Bool>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to flip the sprite vertically while animating.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
var flipY:Null<Bool>;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef StageDataCharacter =
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A number determining the stack order of the character, relative to props and other characters in the stage.
|
||||||
|
* Again, just like CSS.
|
||||||
|
* @default 0
|
||||||
|
*/
|
||||||
|
zIndex:Null<Int>,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The position to render the character at.
|
||||||
|
*/ position:Array<Float>
|
||||||
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
package rendering;
|
package funkin.rendering;
|
||||||
|
|
||||||
import flixel.FlxStrip;
|
import flixel.FlxStrip;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
|
@ -1,4 +1,4 @@
|
||||||
package shaderslmfao;
|
package funkin.shaderslmfao;
|
||||||
|
|
||||||
import flixel.system.FlxAssets.FlxShader;
|
import flixel.system.FlxAssets.FlxShader;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin.shaderslmfao;
|
||||||
|
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import openfl.display.ShaderParameter;
|
import openfl.display.ShaderParameter;
|
|
@ -1,4 +1,4 @@
|
||||||
package shaderslmfao;
|
package funkin.shaderslmfao;
|
||||||
|
|
||||||
import flixel.system.FlxAssets.FlxShader;
|
import flixel.system.FlxAssets.FlxShader;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package shaderslmfao;
|
package funkin.shaderslmfao;
|
||||||
|
|
||||||
import flixel.system.FlxAssets.FlxShader;
|
import flixel.system.FlxAssets.FlxShader;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
|
@ -1,4 +1,4 @@
|
||||||
package;
|
package funkin.shaderslmfao;
|
||||||
|
|
||||||
import flixel.system.FlxAssets.FlxShader;
|
import flixel.system.FlxAssets.FlxShader;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue