modcharts

This commit is contained in:
KadeDev 2021-04-15 11:09:46 -07:00
parent e92d286405
commit fec5fa33c2
10 changed files with 959 additions and 31 deletions

0
Error Normal file
View File

View File

@ -1,4 +1,4 @@
# Kade Engine Lua Mod Chart Documentation Kade Engine Lua Mod Chart Documentation
In the latest version of Kade Engine we introduced Mod Charts. Mod Charts are a way of changing gameplay without hard coded values, this is achieved by using the Lua Scripting language to create script files that run during runtime. In the latest version of Kade Engine we introduced Mod Charts. Mod Charts are a way of changing gameplay without hard coded values, this is achieved by using the Lua Scripting language to create script files that run during runtime.
@ -20,10 +20,10 @@ end
function update (elapsed) -- example https://twitter.com/KadeDeveloper/status/1382178179184422918 function update (elapsed) -- example https://twitter.com/KadeDeveloper/status/1382178179184422918
local currentBeat = (songPos / 1000)*(bpm/60) local currentBeat = (songPos / 1000)*(bpm/60)
for i=0,7 do for i=0,7 do
_G['strum'..i..'X'] = _G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi) setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i)
_G['strum'..i..'Y'] = _G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi) setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i)
end end
end end
function beatHit (beat) function beatHit (beat)
@ -31,7 +31,7 @@ function beatHit (beat)
end end
function stepHit (step) function stepHit (step)
-- do nothing -- do nothing
end end
print("Mod Chart script loaded :)") print("Mod Chart script loaded :)")
@ -41,9 +41,9 @@ Spinning Receptor Example
```lua ```lua
function update (elapsed) function update (elapsed)
for i=0,7 do for i=0,7 do
_G['strum'..i..'Angle'] = _G['strum'..i..'Angle'] + 15 setActorAngle(getActorAngle(i) + 15, i)
end end
end end
``` ```
@ -62,13 +62,15 @@ function update (elapsed)
if curStep >= 352 and curStep < 400 then if curStep >= 352 and curStep < 400 then
local currentBeat = (songPos / 1000)*(bpm/60) local currentBeat = (songPos / 1000)*(bpm/60)
for i=0,7 do for i=0,7 do
_G['strum'..i..'X'] = _G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi) setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i)
_G['strum'..i..'Y'] = _G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi) setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i)
end end
else else
_G['strum'..i..'X'] = _G['defaultStrum'..i..'X'] for i=0,7 do
_G['strum'..i..'Y'] = _G['defaultStrum'..i..'Y'] setActorX(_G['defaultStrum'..i..'X'],i)
end setActorX(_G['defaultStrum'..i..'Y'],i)
end
end
end end
``` ```
@ -77,10 +79,20 @@ Showing/Hiding receptors/the hud
```lua ```lua
function start (song) function start (song)
showOnlyStrums = true -- remove all hud elements besides notes and strums showOnlyStrums = true -- remove all hud elements besides notes and strums
_G['strumLine1Visible'] = false -- remove the first line of strums (the ai notes) for i=0,3 do -- fade out the first 4 receptors (the ai receptors)
tweenFadeIn(i,0,0.6)
end
end end
``` ```
Looping through all of the rendered notes
```lua
for i = 0, getRenderedNotes() do -- sets all of the rendered notes to 0 0 on the x and y axsis
setRenderedNotePos(0,0,i)
end
```
### Available Hooks ### Available Hooks
@ -105,8 +117,6 @@ Kade Engine provides a list of global variables to be used in the lua scripting
| bpm | Float | The current BPM of the song | | bpm | Float | The current BPM of the song |
| fpsCap | Int | The current FPS Cap (set by the player) | | fpsCap | Int | The current FPS Cap (set by the player) |
| downscroll | Bool | Whether the player is in downscroll or not | | downscroll | Bool | Whether the player is in downscroll or not |
| hudZoom | Float | The amount of zoom the Hud should be zoomed in/out |
| cameraZoom | Float | The amount of zoom the Main Camera should be zoomed in/out |
| cameraAngle | Float | The angle that the Main Camera should be rotated | | cameraAngle | Float | The angle that the Main Camera should be rotated |
| camHudAngle | Float | The angle that the Hud should be rotated | | camHudAngle | Float | The angle that the Hud should be rotated |
| followXOffset | Float | The x offset to be added when the camera moves between a character | | followXOffset | Float | The x offset to be added when the camera moves between a character |
@ -114,10 +124,227 @@ Kade Engine provides a list of global variables to be used in the lua scripting
| showOnlyStrums | Bool | Whether to show the Hud and Strums or only the Strums | | showOnlyStrums | Bool | Whether to show the Hud and Strums or only the Strums |
| strumLine1Visible | Bool | Whether to show the first strum line or not | | strumLine1Visible | Bool | Whether to show the first strum line or not |
| strumLine2Visible | Bool | Whether to show the secondstrum line or not | | strumLine2Visible | Bool | Whether to show the secondstrum line or not |
| strum0-7X | Float | (0-7 is strum0,strum1,strum2,etc) get/set the X coordinate for the strum |
| strum0-7Y | Float | (0-7 is strum0,strum1,strum2,etc) get/set the Y coordinate for the strum |
| strum0-7Angle | Float | (0-7 is strum0,strum1,strum2,etc) get/set the Angle for the strum |
| defaultStrum0-7X | Float | (0-7 is strum0,strum1,strum2,etc) get the default X coordinate for the strum | | defaultStrum0-7X | Float | (0-7 is strum0,strum1,strum2,etc) get the default X coordinate for the strum |
| defaultStrum0-7Y | Float | (0-7 is strum0,strum1,strum2,etc) get the default Y coordinate for the strum | | defaultStrum0-7Y | Float | (0-7 is strum0,strum1,strum2,etc) get the default Y coordinate for the strum |
| defaultStrum0-7Angle | Float | (0-7 is strum0,strum1,strum2,etc) get the default Angle for the strum | | defaultStrum0-7Angle | Float | (0-7 is strum0,strum1,strum2,etc) get the default Angle for the strum |
| screenWidth | Int | The width of the current gamespace |
| screenHeight | Int | The height of the current gamespace |
| hudWidth | Int | The width of the hud |
| hudHeight | Int | The height of the hud |
## Functions
Kade Engine exposes a lot of functions that let you modify elements in the game field.
To get started every sprite has an id, and there are some id's that are accessible without creating one.
These premade id's are the following:
| Sprite Id | Value |
| :--------: | :--------------------------------------: |
| 0-7 | Represents Receptor 0-7 |
| boyfriend | Represents the Boyfriend Actor (player1) |
| dad | Represents the Dad Actor (player2) |
| girlfriend | Represents the Girlfriend Actor |
### Sprites
##### makeSprite(string SpritePath,string SpriteId,bool DrawBehind)
Creates a sprite out of the specified image, returns the id you gave it.
*Note: Sprite Path is normally the FILE NAME so if you have a file name of Image it'll go to assets/data/songName/Image.png so don't include the extension*
### Hud/Camera
##### setHudPosition(int x, int y)
Set's the game hud's position in space.
##### getHudX()
Returns the hud's x position
##### getHudY()
Returns the hud's y position
##### setCamPosition(int x, int y)
Set's the current camera's position in space
##### getCamX()
Returns the current camera's x position
##### getCamY()
Returns the current camera's y position
##### setCamZoom(int zoomAmount)
Set's the current camera's zoom
##### setHudZoom(int zoomAmount)
Set's the hud's zoom
### Actor's
##### getRenderedNotes()
Returns the amount of rendered notes.
##### getRenderedNoteX(int id)
Return's the x position of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteY(int id)
Return's the y position of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteScaleX(int id)
Return's the scale x of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteScaleY(int id)
Return's the scale y of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteAlpha(int id)
Return's the alpha of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### setRenderedNotePos(int x, int y, int id)
Set's the position of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### setRenderedNoteAlpha(float alpha, int id)
Set's the alpha of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### setRenderedNoteScale(float scale, int id)
Set's the scale of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### setRenderedNoteScaleX(float scale, int id)
Set's the scale x of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### setRenderedNoteScaleY(float scale, int id)
Set's the scale y of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### getActorX(string/int id)
Returns the x position for the sprite id
##### getActorY(string/int id)
Returns the y position for the sprite id
##### getActorScaleX(string/int id)
Returns the scale x for the sprite id
##### getActorScaleY(string/int id)
Returns the scale y for the sprite id
##### getActorAlpha(string/int id)
Returns the alpha for the sprite id
##### getActorAngle(string/int id)
Returns the angle for the sprite id
##### setActorX(int x, string/int id)
Set's the x position for the sprite id
##### setActorY(int y, string/int id)
Set's the y position for the sprite id
##### setActorAlpha(float alpha, string/int id)
Set's the alpha for the sprite id
##### setActorAngle(int alpha, string/int id)
Set's the angle for the sprite id
##### setActorScale(float scale, string/int id)
Set's the scale for the sprite id
##### setActorScaleX(float x, string/int id)
Set's the scale x for the sprite id
##### setActorScaleY(float y, string/int id)
Set's the scale y for the sprite id
##### getActorWidth(string/int id)
Returns the width for the sprite id
##### getActorHeight(string/int id)
Returns the height for the sprite id
### Tweens
*Note, On Complete functions are based by the function name (and they also well get called when the tween completes)*
##### tweenPos(string/int id, int toX, int toY, float time, string onComplete)
Smoothly tween into a x and y position
##### tweenPosXAngle(string/int id, int toX, float toAngle, float time, string onComplete)
Smoothly tween into a x position and angle
##### tweenPosYAngle(string/int id, int toY, float toAngle, float time, string onComplete)
Smoothly tween into a y position and angle
##### tweenAngle(string/int id, float toAngle, float time, string onComplete)
Smoothly tween into a angle
##### tweenFadeIn(string/int id, float toAlpha, float time, string onComplete)
Smoothly fade in to an alpha
##### tweenFadeOut(string/int id, float toAlpha, float time, string onComplete)
Smoothly fade out to an alpha

View File

@ -2,7 +2,7 @@
<project> <project>
<!-- _________________________ Application Settings _________________________ --> <!-- _________________________ Application Settings _________________________ -->
<app title="Friday Night Funkin' Kade Engine" file="KadeEngine" packageName="com.ninjamuffin99.funkin" package="com.ninjamuffin99.funkin" main="Main" version="0.2.7.1" company="ninjamuffin99" /> <app title="Friday Night Funkin' Kade Engine" file="Kade Engine" packageName="com.ninjamuffin99.funkin" package="com.ninjamuffin99.funkin" main="Main" version="0.2.7.1" 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" />
@ -117,6 +117,8 @@
<haxelib name="faxe" if='switch'/> <haxelib name="faxe" if='switch'/>
<haxelib name="polymod"/> <haxelib name="polymod"/>
<haxelib name="discord_rpc" if="windows"/> <haxelib name="discord_rpc" if="windows"/>
<haxelib name="linc_luajit"/>
<!-- <haxelib name="hxcpp-debug-server" if="desktop"/> --> <!-- <haxelib name="hxcpp-debug-server" if="desktop"/> -->
<!-- <haxelib name="markdown" /> --> <!-- <haxelib name="markdown" /> -->

View File

@ -82,6 +82,9 @@ class ChartingState extends MusicBeatState
var gridBlackLine:FlxSprite; var gridBlackLine:FlxSprite;
var vocals:FlxSound; var vocals:FlxSound;
var player2:Character = new Character(0,0, "dad");
var player1:Boyfriend = new Boyfriend(0,0, "bf");
var leftIcon:HealthIcon; var leftIcon:HealthIcon;
var rightIcon:HealthIcon; var rightIcon:HealthIcon;
@ -365,6 +368,18 @@ class ChartingState extends MusicBeatState
tab_group_note.add(applyLength); tab_group_note.add(applyLength);
UI_box.addGroup(tab_group_note); UI_box.addGroup(tab_group_note);
/*player2 = new Character(0,gridBG.y, _song.player2);
player1 = new Boyfriend(player2.width * 0.2,gridBG.y + player2.height, _song.player1);
player1.y = player1.y - player1.height;
player2.setGraphicSize(Std.int(player2.width * 0.2));
player1.setGraphicSize(Std.int(player1.width * 0.2));
UI_box.add(player1);
UI_box.add(player2);*/
} }
function loadSong(daSong:String):Void function loadSong(daSong:String):Void
@ -559,6 +574,77 @@ class ChartingState extends MusicBeatState
strumLine.y = getYfromStrum((Conductor.songPosition - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps)); strumLine.y = getYfromStrum((Conductor.songPosition - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps));
/*curRenderedNotes.forEach(function(note:Note) {
if (strumLine.overlaps(note) && strumLine.y == note.y) // yandere dev type shit
{
if (_song.notes[curSection].mustHitSection)
{
trace('must hit ' + Math.abs(note.noteData));
if (note.noteData < 4)
{
switch (Math.abs(note.noteData))
{
case 2:
player1.playAnim('singUP', true);
case 3:
player1.playAnim('singRIGHT', true);
case 1:
player1.playAnim('singDOWN', true);
case 0:
player1.playAnim('singLEFT', true);
}
}
if (note.noteData >= 4)
{
switch (note.noteData)
{
case 6:
player2.playAnim('singUP', true);
case 7:
player2.playAnim('singRIGHT', true);
case 5:
player2.playAnim('singDOWN', true);
case 4:
player2.playAnim('singLEFT', true);
}
}
}
else
{
trace('hit ' + Math.abs(note.noteData));
if (note.noteData < 4)
{
switch (Math.abs(note.noteData))
{
case 2:
player2.playAnim('singUP', true);
case 3:
player2.playAnim('singRIGHT', true);
case 1:
player2.playAnim('singDOWN', true);
case 0:
player2.playAnim('singLEFT', true);
}
}
if (note.noteData >= 4)
{
switch (note.noteData)
{
case 6:
player1.playAnim('singUP', true);
case 7:
player1.playAnim('singRIGHT', true);
case 5:
player1.playAnim('singDOWN', true);
case 4:
player1.playAnim('singLEFT', true);
}
}
}
}
});*/
if (curBeat % 4 == 0 && curStep >= 16 * (curSection + 1)) if (curBeat % 4 == 0 && curStep >= 16 * (curSection + 1))
{ {
trace(curStep); trace(curStep);
@ -783,6 +869,18 @@ class ChartingState extends MusicBeatState
updateGrid(); updateGrid();
} }
override function beatHit()
{
trace('beat');
super.beatHit();
if (!player2.animation.curAnim.name.startsWith("sing"))
{
player2.playAnim('idle');
}
player1.dance();
}
function recalculateSteps():Int function recalculateSteps():Int
{ {
var lastChange:BPMChangeEvent = { var lastChange:BPMChangeEvent = {

View File

@ -29,6 +29,9 @@ class Main extends Sprite
public static function main():Void public static function main():Void
{ {
// quick checks
Lib.current.addChild(new Main()); Lib.current.addChild(new Main());
} }
@ -82,6 +85,7 @@ class Main extends Sprite
fpsCounter = new FPS(10, 3, 0xFFFFFF); fpsCounter = new FPS(10, 3, 0xFFFFFF);
addChild(fpsCounter); addChild(fpsCounter);
toggleFPS(FlxG.save.data.fps); toggleFPS(FlxG.save.data.fps);
#end #end
} }

View File

@ -1,5 +1,6 @@
package; package;
import flixel.addons.effects.FlxSkewedSprite;
import flixel.FlxG; import flixel.FlxG;
import flixel.FlxSprite; import flixel.FlxSprite;
import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxAtlasFrames;
@ -11,7 +12,7 @@ import polymod.format.ParseRules.TargetSignatureElement;
using StringTools; using StringTools;
class Note extends FlxSprite class Note extends FlxSkewedSprite
{ {
public var strumTime:Float = 0; public var strumTime:Float = 0;
@ -21,7 +22,7 @@ class Note extends FlxSprite
public var tooLate:Bool = false; public var tooLate:Bool = false;
public var wasGoodHit:Bool = false; public var wasGoodHit:Bool = false;
public var prevNote:Note; public var prevNote:Note;
public var modifiedByLua:Bool = false;
public var sustainLength:Float = 0; public var sustainLength:Float = 0;
public var isSustainNote:Bool = false; public var isSustainNote:Bool = false;
@ -172,7 +173,7 @@ class Note extends FlxSprite
prevNote.animation.play('redhold'); prevNote.animation.play('redhold');
} }
prevNote.scale.y *= Conductor.stepCrochet / 100 * 1.8 * FlxG.save.data.scrollSpeed; prevNote.scale.y *= Conductor.stepCrochet / 50 * 1.5 * FlxG.save.data.scrollSpeed;
prevNote.updateHitbox(); prevNote.updateHitbox();
// prevNote.setGraphicSize(); // prevNote.setGraphicSize();
} }

View File

@ -55,6 +55,16 @@ class Paths
return getPath(file, type, library); return getPath(file, type, library);
} }
inline static public function lua(key:String,?library:String)
{
return getPath('data/$key.lua', TEXT, library);
}
inline static public function luaImage(key:String, ?library:String)
{
return getPath('data/$key.png', IMAGE, library);
}
inline static public function txt(key:String, ?library:String) inline static public function txt(key:String, ?library:String)
{ {
return getPath('data/$key.txt', TEXT, library); return getPath('data/$key.txt', TEXT, library);

View File

@ -1,5 +1,6 @@
package; package;
import llua.Lua;
import Controls.Control; import Controls.Control;
import flixel.FlxG; import flixel.FlxG;
import flixel.FlxSprite; import flixel.FlxSprite;
@ -179,6 +180,11 @@ class PauseSubState extends MusicBeatSubstate
FlxG.resetState(); FlxG.resetState();
case "Exit to menu": case "Exit to menu":
PlayState.loadRep = false; PlayState.loadRep = false;
if (PlayState.lua != null)
{
Lua.close(PlayState.lua);
PlayState.lua = null;
}
if (PlayState.offsetTesting) if (PlayState.offsetTesting)
{ {
PlayState.offsetTesting = false; PlayState.offsetTesting = false;

View File

@ -1,5 +1,20 @@
package; package;
import openfl.geom.Matrix;
import openfl.display.BitmapData;
import openfl.utils.AssetType;
import lime.graphics.Image;
import flixel.graphics.FlxGraphic;
import openfl.utils.AssetManifest;
import openfl.utils.AssetLibrary;
import flixel.system.FlxAssets;
import llua.Convert;
import llua.Lua;
import llua.State;
import llua.LuaL;
import lime.app.Application;
import lime.media.AudioContext;
import lime.media.AudioManager;
import openfl.Lib; import openfl.Lib;
import Section.SwagSection; import Section.SwagSection;
import Song.SwagSong; import Song.SwagSong;
@ -43,6 +58,7 @@ import openfl.filters.ShaderFilter;
#if desktop #if desktop
import Discord.DiscordClient; import Discord.DiscordClient;
import Sys; import Sys;
import sys.FileSystem;
#end #end
using StringTools; using StringTools;
@ -72,6 +88,7 @@ class PlayState extends MusicBeatState
var halloweenLevel:Bool = false; var halloweenLevel:Bool = false;
var songLength:Float = 0; var songLength:Float = 0;
var kadeEngineWatermark:FlxText;
#if windows #if windows
// Discord RPC variables // Discord RPC variables
@ -129,7 +146,6 @@ class PlayState extends MusicBeatState
public static var offsetTesting:Bool = false; public static var offsetTesting:Bool = false;
var notesHitArray:Array<Date> = []; var notesHitArray:Array<Date> = [];
var currentFrames:Int = 0; var currentFrames:Int = 0;
@ -184,6 +200,8 @@ class PlayState extends MusicBeatState
// Per song additive offset // Per song additive offset
public static var songOffset:Float = 0; public static var songOffset:Float = 0;
private var executeModchart = false;
override public function create() override public function create()
{ {
@ -200,6 +218,15 @@ class PlayState extends MusicBeatState
repPresses = 0; repPresses = 0;
repReleases = 0; repReleases = 0;
#if sys
executeModchart = FileSystem.exists(Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart"));
#end
#if !cpp
executeModchart = false; // FORCE disable for non cpp targets
#end
trace('Mod chart: ' + executeModchart + " - " + Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart"));
#if windows #if windows
// Making difficulty text for Discord Rich Presence. // Making difficulty text for Discord Rich Presence.
switch (storyDifficulty) switch (storyDifficulty)
@ -823,7 +850,7 @@ class PlayState extends MusicBeatState
add(healthBar); add(healthBar);
// Add Kade Engine watermark // Add Kade Engine watermark
var kadeEngineWatermark = new FlxText(4,healthBarBG.y + 50,0,SONG.song + " " + (storyDifficulty == 2 ? "Hard" : storyDifficulty == 1 ? "Normal" : "Easy") + (Main.watermarks ? " - KE " + MainMenuState.kadeEngineVer : ""), 16); kadeEngineWatermark = new FlxText(4,healthBarBG.y + 50,0,SONG.song + " " + (storyDifficulty == 2 ? "Hard" : storyDifficulty == 1 ? "Normal" : "Easy") + (Main.watermarks ? " - KE " + MainMenuState.kadeEngineVer : ""), 16);
kadeEngineWatermark.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK); kadeEngineWatermark.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
kadeEngineWatermark.scrollFactor.set(); kadeEngineWatermark.scrollFactor.set();
add(kadeEngineWatermark); add(kadeEngineWatermark);
@ -1140,6 +1167,198 @@ class PlayState extends MusicBeatState
var lastReportedPlayheadPosition:Int = 0; var lastReportedPlayheadPosition:Int = 0;
var songTime:Float = 0; var songTime:Float = 0;
// LUA SHIT
public static var lua:State = null;
function callLua(func_name : String, args : Array<Dynamic>, ?type : String) : Dynamic
{
var result : Any = null;
Lua.getglobal(lua, func_name);
for( arg in args ) {
Convert.toLua(lua, arg);
}
result = Lua.pcall(lua, args.length, 1, 0);
if( result == null) {
return null;
} else {
return convert(result, type);
}
}
function getType(l, type):Any
{
return switch Lua.type(l,type) {
case t if (t == Lua.LUA_TNIL): null;
case t if (t == Lua.LUA_TNUMBER): Lua.tonumber(l, type);
case t if (t == Lua.LUA_TSTRING): (Lua.tostring(l, type):String);
case t if (t == Lua.LUA_TBOOLEAN): Lua.toboolean(l, type);
case t: throw 'you don goofed up. lua type error ($t)';
}
}
function getReturnValues(l) {
var lua_v:Int;
var v:Any = null;
while((lua_v = Lua.gettop(l)) != 0) {
var type:String = getType(l,lua_v);
v = convert(lua_v, type);
Lua.pop(l, 1);
}
return v;
}
private function convert(v : Any, type : String) : Dynamic { // I didn't write this lol
if( Std.is(v, String) && type != null ) {
var v : String = v;
if( type.substr(0, 4) == 'array' ) {
if( type.substr(4) == 'float' ) {
var array : Array<String> = v.split(',');
var array2 : Array<Float> = new Array();
for( vars in array ) {
array2.push(Std.parseFloat(vars));
}
return array2;
} else if( type.substr(4) == 'int' ) {
var array : Array<String> = v.split(',');
var array2 : Array<Int> = new Array();
for( vars in array ) {
array2.push(Std.parseInt(vars));
}
return array2;
} else {
var array : Array<String> = v.split(',');
return array;
}
} else if( type == 'float' ) {
return Std.parseFloat(v);
} else if( type == 'int' ) {
return Std.parseInt(v);
} else if( type == 'bool' ) {
if( v == 'true' ) {
return true;
} else {
return false;
}
} else {
return v;
}
} else {
return v;
}
}
function getLuaErrorMessage(l) {
var v:String = Lua.tostring(l, -1);
Lua.pop(l, 1);
return v;
}
public function setVar(var_name : String, object : Dynamic){
// trace('setting variable ' + var_name + ' to ' + object);
Lua.pushnumber(lua,object);
Lua.setglobal(lua, var_name);
}
public function getVar(var_name : String, type : String) : Dynamic {
var result : Any = null;
// trace('getting variable ' + var_name + ' with a type of ' + type);
Lua.getglobal(lua, var_name);
result = Convert.fromLua(lua,-1);
Lua.pop(lua,1);
if( result == null ) {
return null;
} else {
var result = convert(result, type);
//trace(var_name + ' result: ' + result);
return result;
}
}
function getActorByName(id:String):Dynamic
{
// pre defined names
switch(id)
{
case 'boyfriend':
return boyfriend;
case 'girlfriend':
return gf;
case 'dad':
return dad;
}
// lua objects or what ever
if (luaSprites.get(id) == null)
return strumLineNotes.members[Std.parseInt(id)];
return luaSprites.get(id);
}
public static var luaSprites:Map<String,FlxSprite> = [];
function makeLuaSprite(spritePath:String,toBeCalled:String, drawBehind:Bool)
{
#if sys
var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + PlayState.SONG.song.toLowerCase() + '/' + spritePath + ".png");
var sprite:FlxSprite = new FlxSprite(0,0);
var imgWidth:Float = FlxG.width / data.width;
var imgHeight:Float = FlxG.height / data.height;
var scale:Float = imgWidth <= imgHeight ? imgWidth : imgHeight;
// Cap the scale at x1
if (scale > 1)
{
scale = 1;
}
sprite.makeGraphic(Std.int(data.width * scale),Std.int(data.width * scale),FlxColor.TRANSPARENT);
var data2:BitmapData = sprite.pixels.clone();
var matrix:Matrix = new Matrix();
matrix.identity();
matrix.scale(scale, scale);
data2.fillRect(data2.rect, FlxColor.TRANSPARENT);
data2.draw(data, matrix, null, null, null, true);
sprite.pixels = data2;
luaSprites.set(toBeCalled,sprite);
// and I quote:
// shitty layering but it works!
if (drawBehind)
{
remove(gf);
remove(boyfriend);
remove(dad);
}
add(sprite);
if (drawBehind)
{
add(gf);
add(boyfriend);
add(dad);
}
#end
return toBeCalled;
}
// LUA SHIT
function startSong():Void function startSong():Void
{ {
startingSong = false; startingSong = false;
@ -1148,8 +1367,257 @@ class PlayState extends MusicBeatState
lastReportedPlayheadPosition = 0; lastReportedPlayheadPosition = 0;
if (!paused) if (!paused)
{
FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false); FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 1, false);
}
if (executeModchart) // dude I hate lua (jkjkjkjk)
{
trace('opening a lua state (because we are cool :))');
lua = LuaL.newstate();
LuaL.openlibs(lua);
trace("Lua version: " + Lua.version());
trace("LuaJIT version: " + Lua.versionJIT());
Lua.init_callbacks(lua);
var result = LuaL.dofile(lua, Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart")); // execute le file
if (result != 0)
trace('COMPILE ERROR\n' + getLuaErrorMessage(lua));
// get some fukin globals up in here bois
setVar("bpm", Conductor.bpm);
setVar("fpsCap", FlxG.save.data.fpsCap);
setVar("downscroll", FlxG.save.data.downscroll);
setVar("curStep", 0);
setVar("curBeat", 0);
setVar("hudZoom", camHUD.zoom);
setVar("cameraZoom", FlxG.camera.zoom);
setVar("cameraAngle", FlxG.camera.angle);
setVar("camHudAngle", camHUD.angle);
setVar("followXOffset",0);
setVar("followYOffset",0);
setVar("showOnlyStrums", false);
setVar("strumLine1Visible", true);
setVar("strumLine2Visible", true);
setVar("screenWidth",FlxG.width);
setVar("screenHeight",FlxG.height);
setVar("hudWidth", camHUD.width);
setVar("hudHeight", camHUD.height);
// callbacks
// sprites
trace(Lua_helper.add_callback(lua,"makeSprite", makeLuaSprite));
Lua_helper.add_callback(lua,"destroySprite", function(id:String) {
var sprite = luaSprites.get(id);
if (sprite == null)
return false;
remove(sprite);
return true;
});
// hud/camera
trace(Lua_helper.add_callback(lua,"setHudPosition", function (x:Int, y:Int) {
camHUD.x = x;
camHUD.y = y;
}));
trace(Lua_helper.add_callback(lua,"getHudX", function () {
return camHUD.x;
}));
trace(Lua_helper.add_callback(lua,"getHudY", function () {
return camHUD.y;
}));
trace(Lua_helper.add_callback(lua,"setCamPosition", function (x:Int, y:Int) {
FlxG.camera.x = x;
FlxG.camera.y = y;
}));
trace(Lua_helper.add_callback(lua,"getCameraX", function () {
return FlxG.camera.x;
}));
trace(Lua_helper.add_callback(lua,"getCameraY", function () {
return FlxG.camera.y;
}));
trace(Lua_helper.add_callback(lua,"setCamZoom", function(zoomAmount:Int) {
FlxG.camera.zoom = zoomAmount;
}));
trace(Lua_helper.add_callback(lua,"setHudZoom", function(zoomAmount:Int) {
camHUD.zoom = zoomAmount;
}));
// actors
trace(Lua_helper.add_callback(lua,"getRenderedNotes", function() {
return notes.length;
}));
trace(Lua_helper.add_callback(lua,"getRenderedNoteX", function(id:Int) {
return notes.members[id].x;
}));
trace(Lua_helper.add_callback(lua,"getRenderedNoteY", function(id:Int) {
return notes.members[id].y;
}));
trace(Lua_helper.add_callback(lua,"getRenderedNoteScaleX", function(id:Int) {
return notes.members[id].scale.x;
}));
trace(Lua_helper.add_callback(lua,"getRenderedNoteScaleY", function(id:Int) {
return notes.members[id].scale.y;
}));
trace(Lua_helper.add_callback(lua,"getRenderedNoteAlpha", function(id:Int) {
return notes.members[id].alpha;
}));
trace(Lua_helper.add_callback(lua,"setRenderedNotePos", function(x:Int,y:Int, id:Int) {
notes.members[id].modifiedByLua = true;
notes.members[id].x = x;
notes.members[id].y = y;
}));
trace(Lua_helper.add_callback(lua,"setRenderedNoteAlpha", function(alpha:Float, id:Int) {
notes.members[id].modifiedByLua = true;
notes.members[id].alpha = alpha;
}));
trace(Lua_helper.add_callback(lua,"setRenderedNoteScale", function(scale:Float, id:Int) {
notes.members[id].modifiedByLua = true;
notes.members[id].setGraphicSize(Std.int(notes.members[id].width * scale));
}));
trace(Lua_helper.add_callback(lua,"setRenderedNoteScaleX", function(scale:Float, id:Int) {
notes.members[id].modifiedByLua = true;
notes.members[id].scale.x = scale;
}));
trace(Lua_helper.add_callback(lua,"setRenderedNoteScaleY", function(scale:Float, id:Int) {
notes.members[id].modifiedByLua = true;
notes.members[id].scale.y = scale;
}));
trace(Lua_helper.add_callback(lua,"setActorX", function(x:Int,id:String) {
getActorByName(id).x = x;
}));
trace(Lua_helper.add_callback(lua,"setActorAlpha", function(alpha:Int,id:String) {
getActorByName(id).alpha = alpha;
}));
trace(Lua_helper.add_callback(lua,"setActorY", function(y:Int,id:String) {
getActorByName(id).y = y;
}));
trace(Lua_helper.add_callback(lua,"setActorAngle", function(angle:Int,id:String) {
getActorByName(id).angle = angle;
}));
trace(Lua_helper.add_callback(lua,"setActorScale", function(scale:Float,id:String) {
getActorByName(id).setGraphicSize(Std.int(getActorByName(id).width * scale));
}));
trace(Lua_helper.add_callback(lua,"setActorScaleX", function(scale:Float,id:String) {
getActorByName(id).scale.x = scale;
}));
trace(Lua_helper.add_callback(lua,"setActorScaleY", function(scale:Float,id:String) {
getActorByName(id).scale.y = scale;
}));
trace(Lua_helper.add_callback(lua,"getActorWidth", function (id:String) {
return getActorByName(id).width;
}));
trace(Lua_helper.add_callback(lua,"getActorHeight", function (id:String) {
return getActorByName(id).height;
}));
trace(Lua_helper.add_callback(lua,"getActorAlpha", function(id:String) {
return getActorByName(id).alpha;
}));
trace(Lua_helper.add_callback(lua,"getActorAngle", function(id:String) {
return getActorByName(id).angle;
}));
trace(Lua_helper.add_callback(lua,"getActorX", function (id:String) {
return getActorByName(id).x;
}));
trace(Lua_helper.add_callback(lua,"getActorY", function (id:String) {
return getActorByName(id).y;
}));
trace(Lua_helper.add_callback(lua,"getActorScaleX", function (id:String) {
return getActorByName(id).scale.x;
}));
trace(Lua_helper.add_callback(lua,"getActorScaleY", function (id:String) {
return getActorByName(id).scale.y;
}));
// tweens
Lua_helper.add_callback(lua,"tweenPos", function(id:String, toX:Int, toY:Int, time:Float, onComplete:String) {
FlxTween.tween(getActorByName(id), {x: toX, y: toY}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
});
Lua_helper.add_callback(lua,"tweenPosXAngle", function(id:String, toX:Int, toAngle:Float, time:Float, onComplete:String) {
FlxTween.tween(getActorByName(id), {x: toX, angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
});
Lua_helper.add_callback(lua,"tweenPosYAngle", function(id:String, toY:Int, toAngle:Float, time:Float, onComplete:String) {
FlxTween.tween(getActorByName(id), {y: toY, angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
});
Lua_helper.add_callback(lua,"tweenAngle", function(id:String, toAngle:Int, time:Float, onComplete:String) {
FlxTween.tween(getActorByName(id), {angle: toAngle}, time, {ease: FlxEase.cubeIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
});
Lua_helper.add_callback(lua,"tweenFadeIn", function(id:String, toAlpha:Int, time:Float, onComplete:String) {
FlxTween.tween(getActorByName(id), {alpha: toAlpha}, time, {ease: FlxEase.circIn, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
});
Lua_helper.add_callback(lua,"tweenFadeOut", function(id:String, toAlpha:Int, time:Float, onComplete:String) {
FlxTween.tween(getActorByName(id), {alpha: toAlpha}, time, {ease: FlxEase.circOut, onComplete: function(flxTween:FlxTween) { if (onComplete != '' && onComplete != null) {callLua(onComplete,[id]);}}});
});
for (i in 0...strumLineNotes.length) {
var member = strumLineNotes.members[i];
trace(strumLineNotes.members[i].x + " " + strumLineNotes.members[i].y + " " + strumLineNotes.members[i].angle + " | strum" + i);
//setVar("strum" + i + "X", Math.floor(member.x));
setVar("defaultStrum" + i + "X", Math.floor(member.x));
//setVar("strum" + i + "Y", Math.floor(member.y));
setVar("defaultStrum" + i + "Y", Math.floor(member.y));
//setVar("strum" + i + "Angle", Math.floor(member.angle));
setVar("defaultStrum" + i + "Angle", Math.floor(member.angle));
trace("Adding strum" + i);
}
trace('calling start function');
trace('return: ' + Lua.tostring(lua,callLua('start', [PlayState.SONG.song])));
}
FlxG.sound.music.onComplete = endSong; FlxG.sound.music.onComplete = endSong;
vocals.play(); vocals.play();
@ -1249,7 +1717,6 @@ class PlayState extends MusicBeatState
} }
} }
#end #end
var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped
for (section in noteData) for (section in noteData)
{ {
@ -1604,6 +2071,53 @@ class PlayState extends MusicBeatState
perfectMode = false; perfectMode = false;
#end #end
if (executeModchart && lua != null)
{
setVar('songPos',Conductor.songPosition);
setVar('hudZoom', camHUD.zoom);
setVar('cameraZoom',FlxG.camera.zoom);
callLua('update', [elapsed]);
/*for (i in 0...strumLineNotes.length) {
var member = strumLineNotes.members[i];
member.x = getVar("strum" + i + "X", "float");
member.y = getVar("strum" + i + "Y", "float");
member.angle = getVar("strum" + i + "Angle", "float");
}*/
FlxG.camera.angle = getVar('cameraAngle', 'float');
camHUD.angle = getVar('camHudAngle','float');
if (getVar("showOnlyStrums",'bool'))
{
healthBarBG.visible = false;
kadeEngineWatermark.visible = false;
healthBar.visible = false;
iconP1.visible = false;
iconP2.visible = false;
scoreTxt.visible = false;
}
else
{
healthBarBG.visible = true;
kadeEngineWatermark.visible = true;
healthBar.visible = true;
iconP1.visible = true;
iconP2.visible = true;
scoreTxt.visible = true;
}
var p1 = getVar("strumLine1Visible",'bool');
var p2 = getVar("strumLine2Visible",'bool');
for (i in 0...4)
{
strumLineNotes.members[i].visible = p1;
if (i <= playerStrums.length)
playerStrums.members[i].visible = p2;
}
}
if (currentFrames == FlxG.save.data.fpsCap) if (currentFrames == FlxG.save.data.fpsCap)
{ {
for(i in 0...notesHitArray.length) for(i in 0...notesHitArray.length)
@ -1683,6 +2197,11 @@ class PlayState extends MusicBeatState
DiscordClient.changePresence("Chart Editor", null, null, true); DiscordClient.changePresence("Chart Editor", null, null, true);
#end #end
FlxG.switchState(new ChartingState()); FlxG.switchState(new ChartingState());
if (lua != null)
{
Lua.close(lua);
lua = null;
}
} }
// FlxG.watch.addQuick('VOL', vocals.amplitudeLeft); // FlxG.watch.addQuick('VOL', vocals.amplitudeLeft);
@ -1717,7 +2236,15 @@ class PlayState extends MusicBeatState
#if debug #if debug
if (FlxG.keys.justPressed.EIGHT) if (FlxG.keys.justPressed.EIGHT)
{
FlxG.switchState(new AnimationDebug(SONG.player2)); FlxG.switchState(new AnimationDebug(SONG.player2));
if (lua != null)
{
Lua.close(lua);
lua = null;
}
}
#end #end
if (startingSong) if (startingSong)
@ -1857,7 +2384,7 @@ class PlayState extends MusicBeatState
if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection) if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection)
{ {
camFollow.setPosition(dad.getMidpoint().x + 150, dad.getMidpoint().y - 100); camFollow.setPosition(dad.getMidpoint().x + 150 + (lua != null ? getVar("followXOffset", "float") : 0), dad.getMidpoint().y - 100 + (lua != null ? getVar("followYOffset", "float") : 0));
// camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210); // camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210);
switch (dad.curCharacter) switch (dad.curCharacter)
@ -1883,7 +2410,7 @@ class PlayState extends MusicBeatState
if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100) if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100)
{ {
camFollow.setPosition(boyfriend.getMidpoint().x - 100, boyfriend.getMidpoint().y - 100); camFollow.setPosition(boyfriend.getMidpoint().x - 100 + (lua != null ? getVar("followXOffset", "float") : 0), boyfriend.getMidpoint().y - 100 + (lua != null ? getVar("followYOffset", "float") : 0));
switch (curStage) switch (curStage)
{ {
@ -2003,7 +2530,7 @@ class PlayState extends MusicBeatState
{ {
if (SONG.song != 'Tutorial') if (SONG.song != 'Tutorial')
camZooming = true; camZooming = true;
var altAnim:String = ""; var altAnim:String = "";
if (SONG.notes[Math.floor(curStep / 16)] != null) if (SONG.notes[Math.floor(curStep / 16)] != null)
@ -2029,6 +2556,8 @@ class PlayState extends MusicBeatState
if (SONG.needsVoices) if (SONG.needsVoices)
vocals.volume = 1; vocals.volume = 1;
daNote.active = false;
daNote.kill(); daNote.kill();
notes.remove(daNote, true); notes.remove(daNote, true);
daNote.destroy(); daNote.destroy();
@ -2038,6 +2567,29 @@ class PlayState extends MusicBeatState
daNote.y = (strumLine.y - (Conductor.songPosition - daNote.strumTime) * (-0.45 * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2))); daNote.y = (strumLine.y - (Conductor.songPosition - daNote.strumTime) * (-0.45 * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)));
else else
daNote.y = (strumLine.y - (Conductor.songPosition - daNote.strumTime) * (0.45 * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2))); daNote.y = (strumLine.y - (Conductor.songPosition - daNote.strumTime) * (0.45 * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2)));
if (daNote.mustPress && !daNote.modifiedByLua)
{
daNote.visible = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].visible;
daNote.x = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].x;
if (!daNote.isSustainNote)
daNote.angle = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].angle;
daNote.alpha = playerStrums.members[Math.floor(Math.abs(daNote.noteData))].alpha;
}
else if (!daNote.wasGoodHit && !daNote.modifiedByLua)
{
daNote.visible = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].visible;
daNote.x = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].x;
if (!daNote.isSustainNote)
daNote.angle = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].angle;
daNote.alpha = strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].alpha;
}
if (daNote.isSustainNote)
daNote.x += daNote.width / 2 + 7;
//trace(daNote.y); //trace(daNote.y);
// WIP interpolation shit? Need to fix the pause issue // WIP interpolation shit? Need to fix the pause issue
// daNote.y = (strumLine.y - (songTime - daNote.strumTime) * (0.45 * PlayState.SONG.speed)); // daNote.y = (strumLine.y - (songTime - daNote.strumTime) * (0.45 * PlayState.SONG.speed));
@ -2084,6 +2636,12 @@ class PlayState extends MusicBeatState
if (!loadRep) if (!loadRep)
rep.SaveReplay(); rep.SaveReplay();
if (executeModchart)
{
Lua.close(lua);
lua = null;
}
canPause = false; canPause = false;
FlxG.sound.music.volume = 0; FlxG.sound.music.volume = 0;
vocals.volume = 0; vocals.volume = 0;
@ -2118,6 +2676,12 @@ class PlayState extends MusicBeatState
FlxG.switchState(new StoryMenuState()); FlxG.switchState(new StoryMenuState());
if (lua != null)
{
Lua.close(lua);
lua = null;
}
// if () // if ()
StoryMenuState.weekUnlocked[Std.int(Math.min(storyWeek + 1, StoryMenuState.weekUnlocked.length - 1))] = true; StoryMenuState.weekUnlocked[Std.int(Math.min(storyWeek + 1, StoryMenuState.weekUnlocked.length - 1))] = true;
@ -3136,6 +3700,12 @@ class PlayState extends MusicBeatState
resyncVocals(); resyncVocals();
} }
if (executeModchart && lua != null)
{
setVar('curStep',curStep);
callLua('stepHit',[curStep]);
}
if (dad.curCharacter == 'spooky' && curStep % 4 == 2) if (dad.curCharacter == 'spooky' && curStep % 4 == 2)
{ {
// dad.dance(); // dad.dance();
@ -3167,6 +3737,12 @@ class PlayState extends MusicBeatState
notes.sort(FlxSort.byY, FlxSort.DESCENDING); notes.sort(FlxSort.byY, FlxSort.DESCENDING);
} }
if (executeModchart && lua != null)
{
setVar('curBeat',curBeat);
callLua('beatHit',[curBeat]);
}
if (SONG.notes[Math.floor(curStep / 16)] != null) if (SONG.notes[Math.floor(curStep / 16)] != null)
{ {
if (SONG.notes[Math.floor(curStep / 16)].changeBPM) if (SONG.notes[Math.floor(curStep / 16)].changeBPM)

View File

@ -59,6 +59,10 @@ class TitleState extends MusicBeatState
sys.FileSystem.createDirectory(Sys.getCwd() + "/assets/replays"); sys.FileSystem.createDirectory(Sys.getCwd() + "/assets/replays");
#end #end
@:privateAccess
{
trace("Loaded " + openfl.Assets.getLibrary("default").assetsLoaded + " assets (DEFAULT)");
}
PlayerSettings.init(); PlayerSettings.init();