444 lines
12 KiB
Haxe
444 lines
12 KiB
Haxe
package;
|
|
|
|
import openfl.display.BitmapData;
|
|
#if linc_luajit
|
|
import llua.Lua;
|
|
import llua.LuaL;
|
|
import llua.State;
|
|
import llua.Convert;
|
|
#end
|
|
|
|
//import animateatlas.AtlasFrameMaker;
|
|
import flixel.FlxG;
|
|
import flixel.addons.effects.FlxTrail;
|
|
import flixel.input.keyboard.FlxKey;
|
|
import flixel.tweens.FlxTween;
|
|
import flixel.tweens.FlxEase;
|
|
import flixel.text.FlxText;
|
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
|
import flixel.math.FlxPoint;
|
|
import flixel.system.FlxSound;
|
|
import flixel.util.FlxTimer;
|
|
import flixel.FlxSprite;
|
|
import flixel.FlxCamera;
|
|
import flixel.util.FlxColor;
|
|
import flixel.FlxBasic;
|
|
import flixel.FlxObject;
|
|
import flixel.FlxSprite;
|
|
import openfl.Lib;
|
|
import openfl.display.BlendMode;
|
|
import openfl.filters.BitmapFilter;
|
|
import openfl.utils.Assets;
|
|
import flixel.math.FlxMath;
|
|
import flixel.util.FlxSave;
|
|
import flixel.addons.transition.FlxTransitionableState;
|
|
import flixel.system.FlxAssets.FlxShader;
|
|
|
|
#if (!flash && sys)
|
|
import flixel.addons.display.FlxRuntimeShader;
|
|
#end
|
|
|
|
#if sys
|
|
import sys.FileSystem;
|
|
import sys.io.File;
|
|
#end
|
|
|
|
import Type.ValueType;
|
|
import Controls;
|
|
//import DialogueBoxPsych;
|
|
|
|
#if hscript
|
|
import hscript.Parser;
|
|
import hscript.Interp;
|
|
import hscript.Expr;
|
|
#end
|
|
|
|
import ui.PreferencesMenu;
|
|
|
|
#if desktop
|
|
import Discord;
|
|
#end
|
|
|
|
#if hxCodec
|
|
import hxcodec.VideoHandler;
|
|
#end
|
|
|
|
using StringTools;
|
|
|
|
class LuaHandler {
|
|
public static var Function_Stop:Dynamic = "##NEKO2LUA_FUNCTIONSTOP";
|
|
public static var Function_Continue:Dynamic = "##NEKO2LUA_FUNCTIONCONTINUE";
|
|
public static var Function_StopLua:Dynamic = "##NEKO2LUA_FUNCTIONSTOPLUA";
|
|
|
|
#if linc_luajit
|
|
public var lua:State = null;
|
|
#end
|
|
public var closed:Bool = false;
|
|
public var scriptName:String = '';
|
|
|
|
#if hscript
|
|
public static var hscript:HScript = null;
|
|
#end
|
|
|
|
public function new(luafile:String)
|
|
{
|
|
var lua:State = LuaL.newstate();
|
|
LuaL.openlibs(lua);
|
|
//trace("Lua version: " + Lua.version());
|
|
//trace("LuaJIT version: " + Lua.versionJIT());
|
|
|
|
LuaL.dofile(lua, luafile);
|
|
|
|
try{
|
|
var result:Dynamic = LuaL.dofile(lua, luafile);
|
|
var resultStr:String = Lua.tostring(lua, result);
|
|
if(resultStr != null && result != 0) {
|
|
trace('Error on lua script! ' + resultStr);
|
|
#if windows
|
|
lime.app.Application.current.window.alert(resultStr, 'Error on lua script!');
|
|
#else
|
|
luaTrace('Error loading lua script: "$luafile"\n' + resultStr, true, false, FlxColor.RED);
|
|
#end
|
|
lua = null;
|
|
return;
|
|
}
|
|
} catch(e:Dynamic) {
|
|
trace(e);
|
|
return;
|
|
}
|
|
scriptName = luafile;
|
|
hscript = new HScript();
|
|
trace('lua file loaded succesfully:' + luafile);
|
|
|
|
#if linc_luajit
|
|
Lua_helper.add_callback(lua, "setLuaValue", function(variable:String, value:Dynamic) {
|
|
PlayState.instance.variables.set(variable,value);
|
|
});
|
|
|
|
Lua_helper.add_callback(lua, "getLuaValue", function(variable:String) {
|
|
return PlayState.instance.variables.get(variable);
|
|
});
|
|
|
|
Lua_helper.add_callback(lua, "setInstanceValue", function(variable:String, value:Dynamic) {
|
|
Reflect.setField(PlayState.instance, variable, value);
|
|
});
|
|
|
|
Lua_helper.add_callback(lua, "getInstanceValue", function(variable:String) {
|
|
return Reflect.field(PlayState.instance, variable);
|
|
});
|
|
|
|
Lua_helper.add_callback(lua, "runHaxeCode", function(codeToRun:String) {
|
|
var retVal:Dynamic = null;
|
|
|
|
#if hscript
|
|
hscript = new HScript();
|
|
try {
|
|
retVal = hscript.execute(codeToRun);
|
|
}
|
|
catch (e:Dynamic) {
|
|
luaTrace(scriptName + ":" + lastCalledFunction + " - " + e, false,false, FlxColor.RED);
|
|
}
|
|
#else
|
|
luaTrace("runHaxeCode: HScript isn't supported on this platform!", false, false, FlxColor.RED);
|
|
#end
|
|
|
|
if(retVal != null && !isOfTypes(retVal, [Bool, Int, Float, String, Array])) retVal = null;
|
|
return retVal;
|
|
});
|
|
|
|
|
|
Lua_helper.add_callback(lua, "debugPrint", function(text1:Dynamic = '', text2:Dynamic = '', text3:Dynamic = '', text4:Dynamic = '', text5:Dynamic = '') {
|
|
if (text1 == null) text1 = '';
|
|
if (text2 == null) text2 = '';
|
|
if (text3 == null) text3 = '';
|
|
if (text4 == null) text4 = '';
|
|
if (text5 == null) text5 = '';
|
|
luaTrace('' + text1 + text2 + text3 + text4 + text5, true, false);
|
|
});
|
|
|
|
Lua_helper.add_callback(lua, "close", function() {
|
|
closed = true;
|
|
return closed;
|
|
});
|
|
|
|
Lua_helper.add_callback(lua, "changePresence", function(details:String, state:Null<String>, ?smallImageKey:String, ?hasStartTimestamp:Bool, ?endTimestamp:Float) {
|
|
#if desktop
|
|
DiscordClient.changePresence(details, state, smallImageKey, hasStartTimestamp, endTimestamp);
|
|
#end
|
|
});
|
|
|
|
Lua_helper.add_callback(lua, "playCutscene", function (name:String, atEndOfSong:Bool = false) {
|
|
#if hxCodec
|
|
PlayState.instance.inCutscene = true;
|
|
FlxG.sound.music.stop();
|
|
|
|
var video:VideoHandler = new VideoHandler();
|
|
video.finishCallback = function()
|
|
{
|
|
PlayState.instance.inCutscene = false;
|
|
if (atEndOfSong)
|
|
{
|
|
if (PlayState.storyPlaylist.length <= 0)
|
|
FlxG.switchState(new StoryMenuState());
|
|
else
|
|
{
|
|
PlayState.SONG = Song.loadFromJson(PlayState.storyPlaylist[0].toLowerCase());
|
|
FlxG.switchState(new PlayState());
|
|
}
|
|
}
|
|
else
|
|
FlxTween.tween(FlxG.camera, {zoom: PlayState.defaultCamZoom}, (Conductor.crochet / 1000) * 5, {ease: FlxEase.quadInOut});
|
|
PlayState.instance.startCountdown();
|
|
PlayState.instance.cameraMovement();
|
|
}
|
|
video.playVideo(Paths.video(name).replace("videos:",""));
|
|
#else
|
|
PlayState.instance.inCutscene = true;
|
|
var vid:FlxVideo = new FlxVideo(name);
|
|
vid.finishCallback = function()
|
|
{
|
|
FlxTween.tween(FlxG.camera, {zoom: PlayState.defaultCamZoom}, (Conductor.crochet / 1000) * 5, {ease: FlxEase.quadInOut});
|
|
PlayState.instance.startCountdown();
|
|
PlayState.instance.cameraMovement();
|
|
PlayState.instance.inCutscene = false;
|
|
};
|
|
#end
|
|
});
|
|
#end
|
|
}
|
|
|
|
var lastCalledFunction:String = '';
|
|
public function call(func:String, args:Array<Dynamic>):Dynamic {
|
|
#if linc_luajit
|
|
if(closed) return Function_Continue;
|
|
|
|
lastCalledFunction = func;
|
|
try {
|
|
if(lua == null) return Function_Continue;
|
|
|
|
Lua.getglobal(lua, func);
|
|
var type:Int = Lua.type(lua, -1);
|
|
|
|
if (type != Lua.LUA_TFUNCTION) {
|
|
if (type > Lua.LUA_TNIL)
|
|
luaTrace("ERROR (" + func + "): attempt to call a " + typeToString(type) + " value", false, false, FlxColor.RED);
|
|
|
|
Lua.pop(lua, 1);
|
|
return Function_Continue;
|
|
}
|
|
|
|
for (arg in args) Convert.toLua(lua, arg);
|
|
var status:Int = Lua.pcall(lua, args.length, 1, 0);
|
|
|
|
// Checks if it's not successful, then show a error.
|
|
if (status != Lua.LUA_OK) {
|
|
var error:String = getErrorMessage(status);
|
|
luaTrace("ERROR (" + func + "): " + error, false, false, FlxColor.RED);
|
|
return Function_Continue;
|
|
}
|
|
|
|
// If successful, pass and then return the result.
|
|
var result:Dynamic = cast Convert.fromLua(lua, -1);
|
|
if (result == null) result = Function_Continue;
|
|
|
|
Lua.pop(lua, 1);
|
|
return result;
|
|
}
|
|
catch (e:Dynamic) {
|
|
trace(e);
|
|
}
|
|
#end
|
|
return Function_Continue;
|
|
}
|
|
|
|
public static function isOfTypes(value:Any, types:Array<Dynamic>)
|
|
{
|
|
for (type in types)
|
|
{
|
|
if(Std.isOfType(value, type)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function typeToString(type:Int):String {
|
|
#if linc_luajit
|
|
switch(type) {
|
|
case Lua.LUA_TBOOLEAN: return "boolean";
|
|
case Lua.LUA_TNUMBER: return "number";
|
|
case Lua.LUA_TSTRING: return "string";
|
|
case Lua.LUA_TTABLE: return "table";
|
|
case Lua.LUA_TFUNCTION: return "function";
|
|
}
|
|
if (type <= Lua.LUA_TNIL) return "nil";
|
|
#end
|
|
return "unknown";
|
|
}
|
|
|
|
function getErrorMessage(status:Int):String {
|
|
#if linc_luajit
|
|
var v:String = Lua.tostring(lua, -1);
|
|
Lua.pop(lua, 1);
|
|
|
|
if (v != null) v = v.trim();
|
|
if (v == null || v == "") {
|
|
switch(status) {
|
|
case Lua.LUA_ERRRUN: return "Runtime Error";
|
|
case Lua.LUA_ERRMEM: return "Memory Allocation Error";
|
|
case Lua.LUA_ERRERR: return "Critical Error";
|
|
}
|
|
return "Unknown Error";
|
|
}
|
|
|
|
return v;
|
|
#end
|
|
return null;
|
|
}
|
|
|
|
public function set(variable:String, data:Dynamic) {
|
|
#if linc_luajit
|
|
if(lua == null) {
|
|
return;
|
|
}
|
|
|
|
Convert.toLua(lua, data);
|
|
Lua.setglobal(lua, variable);
|
|
#end
|
|
}
|
|
|
|
public function stop() {
|
|
#if linc_luajit
|
|
if(lua == null) {
|
|
return;
|
|
}
|
|
|
|
Lua.close(lua);
|
|
lua = null;
|
|
#end
|
|
}
|
|
|
|
public function luaTrace(text:String, ignoreCheck:Bool = false, deprecated:Bool = false, color:FlxColor = FlxColor.WHITE) {
|
|
#if linc_luajit
|
|
if(ignoreCheck || getBool('luaDebugMode')) {
|
|
if(deprecated && !getBool('luaDeprecatedWarnings')) {
|
|
return;
|
|
}
|
|
PlayState.instance.addTextToDebug(text, color);
|
|
trace(text);
|
|
}
|
|
#end
|
|
}
|
|
|
|
#if linc_luajit
|
|
public function getBool(variable:String) {
|
|
var result:String = null;
|
|
Lua.getglobal(lua, variable);
|
|
result = Convert.fromLua(lua, -1);
|
|
Lua.pop(lua, 1);
|
|
|
|
if(result == null) {
|
|
return false;
|
|
}
|
|
return (result == 'true');
|
|
}
|
|
#end
|
|
}
|
|
|
|
class DebugLuaText extends FlxText
|
|
{
|
|
private var disableTime:Float = 6;
|
|
public var parentGroup:FlxTypedGroup<DebugLuaText>;
|
|
public function new(text:String, parentGroup:FlxTypedGroup<DebugLuaText>, color:FlxColor) {
|
|
this.parentGroup = parentGroup;
|
|
super(10, 10, 0, text, 16);
|
|
setFormat(Paths.font("vcr.ttf"), 16, color, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
|
scrollFactor.set();
|
|
borderSize = 1;
|
|
}
|
|
|
|
override function update(elapsed:Float) {
|
|
super.update(elapsed);
|
|
disableTime -= elapsed;
|
|
if(disableTime < 0) disableTime = 0;
|
|
if(disableTime < 1) alpha = disableTime;
|
|
}
|
|
}
|
|
|
|
class ModchartSprite extends FlxSprite
|
|
{
|
|
public var wasAdded:Bool = false;
|
|
public var animOffsets:Map<String, Array<Float>> = new Map<String, Array<Float>>();
|
|
//public var isInFront:Bool = false;
|
|
|
|
public function new(?x:Float = 0, ?y:Float = 0)
|
|
{
|
|
super(x, y);
|
|
antialiasing = PreferencesMenu.getPref('antialiasing');
|
|
}
|
|
}
|
|
|
|
#if hscript
|
|
class HScript
|
|
{
|
|
public static var parser:Parser = new Parser();
|
|
public var interp:Interp;
|
|
|
|
public var variables(get, never):Map<String, Dynamic>;
|
|
|
|
public function get_variables()
|
|
{
|
|
return interp.variables;
|
|
}
|
|
|
|
public function new()
|
|
{
|
|
interp = new Interp();
|
|
interp.variables.set('FlxG', FlxG);
|
|
interp.variables.set('FlxSprite', FlxSprite);
|
|
interp.variables.set('FlxCamera', FlxCamera);
|
|
interp.variables.set('FlxTimer', FlxTimer);
|
|
interp.variables.set('FlxTween', FlxTween);
|
|
interp.variables.set('FlxEase', FlxEase);
|
|
interp.variables.set('PlayState', PlayState);
|
|
interp.variables.set('game', PlayState.instance);
|
|
interp.variables.set('Paths', Paths);
|
|
interp.variables.set('Conductor', Conductor);
|
|
interp.variables.set('Preference', Preference);
|
|
interp.variables.set('Character', Character);
|
|
interp.variables.set('Alphabet', Alphabet);
|
|
//interp.variables.set('CustomSubstate', CustomSubstate);
|
|
#if (!flash && sys)
|
|
interp.variables.set('FlxRuntimeShader', FlxRuntimeShader);
|
|
#end
|
|
interp.variables.set('ShaderFilter', openfl.filters.ShaderFilter);
|
|
interp.variables.set('StringTools', StringTools);
|
|
|
|
interp.variables.set('setVar', function(name:String, value:Dynamic)
|
|
{
|
|
PlayState.instance.variables.set(name, value);
|
|
});
|
|
interp.variables.set('getVar', function(name:String)
|
|
{
|
|
var result:Dynamic = null;
|
|
if(PlayState.instance.variables.exists(name)) result = PlayState.instance.variables.get(name);
|
|
return result;
|
|
});
|
|
interp.variables.set('removeVar', function(name:String)
|
|
{
|
|
if(PlayState.instance.variables.exists(name))
|
|
{
|
|
PlayState.instance.variables.remove(name);
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
public function execute(codeToRun:String):Dynamic
|
|
{
|
|
@:privateAccess
|
|
HScript.parser.line = 1;
|
|
HScript.parser.allowTypes = true;
|
|
return interp.execute(HScript.parser.parseString(codeToRun));
|
|
}
|
|
}
|
|
#end |