1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-06-08 17:42:05 +00:00
Aquaria/Aquaria/ScriptInterface.cpp
fgenesis 8472718fb7 Major include refactor; changes to pretty much everything
This untangles some of the gigantic kitchen sink headers
in an attempt to split things into smaller files.
Also don't include gl.h, glext.h, windows.h,
and other such nonsense *everywhere*.

Lots of cleanups on the way too. More dead/unused code removal.

Remove incrFlag(), decrFlag() Lua functions.
2016-07-09 04:18:40 +02:00

11943 lines
243 KiB
C++

#/*
Copyright (C) 2007, 2010 - Bit-Blot
This file is part of Aquaria.
Aquaria is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "SDL.h"
#include "ScriptInterface.h"
#include "../BBGE/ScriptObject.h"
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#include "ReadXML.h"
#include "DSQ.h"
#include "Game.h"
#include "Avatar.h"
#include "ScriptedEntity.h"
#include "Shot.h"
#include "Entity.h"
#include "Web.h"
#include "GridRender.h"
#include "AfterEffect.h"
#include "PathFinding.h"
#include <algorithm>
#include "Gradient.h"
#include "InGameMenu.h"
#include "GasCloud.h"
#include "Ingredient.h"
#include "Beam.h"
#include "Hair.h"
#include "Spore.h"
#include "../BBGE/MathFunctions.h"
// Define this to 1 to check types of pointers passed to functions,
// and warn if a type mismatch is detected. In this case,
// the pointer is treated as NULL, to avoid crashing or undefined behavior.
// Note: There are a few functions that depend on this (isObject and related).
// They will still work as expected when this is disabled.
#define CHECK_POINTER_TYPES 1
// If true, send all sort of script errors to errorLog instead of debugLog.
// On win32/OSX, this pops up message boxes which help to locate errors easily,
// but can be annoying for regular gameplay.
bool loudScriptErrors = false;
// Set this to true to complain whenever a script tries to
// get or set a global variable.
bool complainOnGlobalVar = false;
// Set this to true to complain whenever a script tries to get an undefined
// thread-local variable.
bool complainOnUndefLocal = false;
// Set to true to make 'os' and 'io' Lua tables accessible
bool allowUnsafeFunctions = false;
// List of all interface functions called by C++ code, terminated by NULL.
static const char * const interfaceFunctions[] = {
"action",
"activate",
"animationKey",
"castSong",
"canShotHit",
"cookFailure",
"damage",
"deathNotify",
"dieEaten",
"dieNormal",
"enterState",
"entityDied",
"exitState",
"exitTimer",
"getIngredientEffectString",
"hitEntity",
"hitSurface",
"init",
"lightFlare",
"msg",
"postInit",
"preUpdate",
"shiftWorlds",
"shotHitEntity",
"song",
"songNote",
"songNoteDone",
"sporesDropped",
"update",
"useIngredient",
"useTreasure",
NULL
};
//============================================================================================
// R U L E S F O R W R I T I N G S C R I P T S
//============================================================================================
//
// All scripts in Aquaria run as separate threads in the same Lua state.
// This means that scripts must follow certain rules to avoid interfering
// with each other:
//
// -- DON'T use global variables (or functions). Use file-scope or
// instance locals instead.
//
// Since every script runs in the same Lua state and thus shares the
// same global environment, global variables set in one script affect
// every other script. Something as innocuous-looking as "hits = 10"
// would set a "hits" variable in _every_ script -- overwriting any
// value that another script might have already set!
//
// For constant values and functions (which are in effect constant
// values), you can use Lua's "local" keyword to declare the value as
// local to the script file which declares it. Any functions defined
// later in the file will then be able to access those local values as
// function upvalues, thus avoiding touching the global environment.
// (However, remember to define the constants or functions _before_
// you use them!)
//
// For variables, a file-scope local won't work, because a script's
// functions are shared across all instances of that script -- for
// example, every active jellyfish entity calls the same "update"
// function. If you used file-scope locals, then you'd have no way to
// separate one instance's data from another. Instead, the Aquaria
// script engine provides a Lua table specific to each script instance,
// into which instance-local variables can be stored. This table is
// loaded into the global variable "v" when any script function is
// called from the game, so functions can store variables in this table
// without worrying that another instance of the script will clobber
// them.
//
// The instance-local table is also available to code in the script
// outside any functions, which is executed when the script is loaded.
// In this case, the values in the table are used as defaults and
// copied into the instance-local table of each new instance of the
// script.
//
// If you use any include files, be aware that file-scope locals in the
// include files can only be used inside those files, since they would
// be out of scope in the calling file. To export constants or
// functions to the calling file, you'll have to use instance locals
// instead. (As an exception, if you have constants which you know are
// unique across all scripts, you can define them as globals. Aquaria
// itself defines a number of global constants for use in scripts --
// see the "SCRIPT CONSTANTS" section toward the bottom of this file.)
//
// -- DO define instance functions in the global namespace.
//
// As an exception to the rule above, interface functions such as
// init() or update() _should_ be defined in the global namespace.
// For example:
//
// local function doUpdateStuff(dt)
// -- Some update stuff.
// end
// function update(dt)
// doUpdateStuff(dt)
// -- Other update stuff.
// end
//
// The script engine will take care of ensuring that different scripts'
// functions don't interfere with each other.
//
// -- DON'T call interface functions from within a script.
//
// Interface functions, such as init() and update(), are treated
// specially by the script engine, and attempting to call them from
// other script functions will fail. If you need to perform the same
// processing from two or more different interface functions, define
// a local function with the necessary code and call it from the
// interface functions.
//
// It _is_ possible, though not recommended, to have a local function
// with the same name as an interface function. For example, if you
// write a script containing:
//
// local function activate(me)
// -- Do something.
// end
//
// then you can call activate() from other functions without problems.
// The local function, activate() in this case, will naturally not be
// visible to the script engine. (This is discouraged because someone
// reading the code may be confused at seeing what looks like an
// interface function defined locally.)
//
// -- DON'T call any functions from the outermost (file) scope of an
// instanced script file.
//
// "Instanced" script files are those for which multiple instances may
// be created, i.e. entity or node scripts. For these, the script
// itself is executed only once, when it is loaded; any statements
// outside function definitions will be executed at this time, but not
// when a new script instance is created. For example, if you try to
// call a function such as math.random() to set a different value for
// each instance, you'll instead end up with the same value for every
// instance. In cases like this, the variable should be set in the
// script's init() function, not at file scope.
//
// Likewise, any functions which have side effects or otherwise modify
// program state should not be called from file scope. Call them from
// init() instead.
//
// -- DON'T declare non-constant Lua tables at file scope in instanced
// scripts.
//
// One non-obvious result of the above restrictions is that tables
// intended to be modified by the script cannot be declared at file
// scope, even as instance variables. The reason for this is that
// table variables in Lua are actually pointers; the Lua statement
// "v.table = {}" is functionally the same as "v.table = newtable()",
// where the hypothetical newtable() function allocates and returns a
// pointer to a table object, and thus falls under the restriction
// that functions must not be called at file scope. Table variables
// in instanced scripts must therefore be initialized in the init()
// function, even if you're only setting the variable to an empty
// table.
//
// In summary:
//
// -- Never use global variables or functions, except interface functions.
// -- Constants and local functions should be defined with "local":
// local MY_CONSTANT = 42
// local function getMyConstant() return MY_CONSTANT end
// -- Variables should be stored in the "v" table:
// function update(dt) v.timer = v.timer + dt end
// -- Variables (except table variables) can have default values set when
// the script is loaded:
// v.countdown = 5
// function update(dt) v.countdown = v.countdown - dt end
// -- Non-constant tables must be initialized in init(), even if the
// variable is always set to the same thing (such as an empty table).
// -- Never call interface functions from other functions.
// -- Always perform instance-specific setup in init(), not at file scope.
//
// ====================
// Compatibility notes:
// ====================
//
// Due to the use of an instance variable table (the "v" global), scripts
// written for this version of Aquaria will _not_ work with commercial
// releases (at least through version 1.1.3) of the game; likewise, the
// scripts from those commercial releases, and mods written to target
// those releases, will not work with this engine.
//
// The latter problem is unfortunately an unsolvable one, in any practical
// sense. Since the original engine created a new Lua state for each
// script, scripts could create and modify global variables with impunity.
// The mere act of loading such a script could wreak havoc on the single
// Lua state used in the current engine, and attempting to work around
// this would require at least the implementation of a custom Lua parser
// to analyze and/or alter each script before it was passed to the Lua
// interpreter.
//
// However, the former problem -- of writing scripts for this version of
// the engine which also work on earlier versions -- can be solved with
// a few extra lines of code at the top of each script. Since the new
// engine initializes the "v" global before each call to a script,
// including when the script is first loaded, scripts can check for the
// existence of this variable and assign an empty table to it if needed,
// such as with this line:
//
// if not v then v = {} end
//
// Additionally, the current engine provides built-in constants which
// were formerly loaded from external files. To differentiate between
// this and other versions of the engine, the script interface exports a
// constant named AQUARIA_VERSION, generated directly from the program
// version (shown on the title screen) as:
// major*10000 + minor*100 + revision
// For example, in version 1.1.3, AQUARIA_VERSION == 10103. In earlier
// versions of the engine, the value of this constant will be nil, which
// can be used as a trigger to load the constant definition file from
// that version:
//
// if not AQUARIA_VERSION then dofile("scripts/entities/entityinclude.lua") end
//
// Note that scripts should _not_ rely on AQUARIA_VERSION for the v = {}
// assignment. The code "if not AQUARIA_VERSION then v = {} end" would
// work correctly in a top-level script, but if executed from a script
// used as an include file, the table created in the include file would
// overwrite any existing table created by the file's caller.
//
//============================================================================================
// S C R I P T C O M M A N D S
//============================================================================================
static void scriptError(const std::string& msg)
{
if(loudScriptErrors)
errorLog(msg);
else
debugLog(msg);
}
static inline void luaPushPointer(lua_State *L, void *ptr)
{
// All the scripts do this:
// x = getFirstEntity()
// while x =~ 0 do x = getNextEntity() end
// The problem is this is now a pointer ("light user data"), so in
// Lua, it's never equal to 0 (or nil!), even if it's NULL.
// So we push an actual zero when we get a NULL to keep the existing
// scripts happy. --ryan.
if (ptr != NULL)
lua_pushlightuserdata(L, ptr);
else
lua_pushnumber(L, 0);
}
static std::string luaFormatStackInfo(lua_State *L, int level = 1)
{
lua_Debug ar;
std::ostringstream os;
if (lua_getstack(L, level, &ar) && lua_getinfo(L, "Sln", &ar))
{
os << ar.short_src << ":" << ar.currentline
<< " ([" << ar.what << "] " << ar.namewhat << " " << (ar.name ? ar.name : "(?)") << ")";
}
else
{
os << "???:0";
}
return os.str();
}
static void scriptDebug(lua_State *L, const std::string& msg)
{
debugLog(luaFormatStackInfo(L) + ": " + msg);
}
static void scriptError(lua_State *L, const std::string& msg)
{
lua_Debug dummy;
std::ostringstream os;
os << msg;
for (int level = 0; lua_getstack(L, level, &dummy); ++level)
os << '\n' << luaFormatStackInfo(L, level);
scriptError(os.str());
}
#if CHECK_POINTER_TYPES
// Not intended to be called.
// Because wild typecasting expects X::_objtype to reside at the same relative
// memory location, be sure this is the case before running into undefined behavior later.
// - The C++ standard allows offsetof() only on POD-types. Oh well, it probably works anyways.
// If it does not compile for some reason, comment it out, hope for the best, and go ahead.
#if !(defined(__GNUC__) && __GNUC__ <= 2)
static void compile_time_assertions()
{
#define oo(cls) offsetof(cls, _objtype)
compile_assert(oo(Path) == oo(RenderObject));
compile_assert(oo(Path) == oo(Entity));
compile_assert(oo(Path) == oo(Ingredient));
compile_assert(oo(Path) == oo(CollideEntity));
compile_assert(oo(Path) == oo(ScriptedEntity));
compile_assert(oo(Path) == oo(Beam));
compile_assert(oo(Path) == oo(Shot));
compile_assert(oo(Path) == oo(Web));
compile_assert(oo(Path) == oo(Bone));
compile_assert(oo(Path) == oo(PauseQuad));
compile_assert(oo(Path) == oo(Quad));
compile_assert(oo(Path) == oo(Avatar));
compile_assert(oo(Path) == oo(BaseText));
compile_assert(oo(Path) == oo(PauseQuad));
compile_assert(oo(Path) == oo(ParticleEffect));
#undef oo
}
#endif
template <typename T>
static void ensureType(lua_State *L, T *& ptr, ScriptObjectType ty)
{
if (ptr)
{
ScriptObject *so = (ScriptObject*)(ptr);
if (!so->isType(ty))
{
std::ostringstream os;
os << "WARNING: script passed wrong pointer to function (expected type: "
<< ScriptObject::getTypeString(ty) << "; got: "
<< so->getTypeString() << ')';
scriptError(L, os.str());
ptr = NULL; // note that the pointer is passed by reference
}
}
}
# define ENSURE_TYPE(ptr, ty) ensureType(L, (ptr), (ty))
# define typecheckOnly(func) func
#else
# define ENSURE_TYPE(ptr, ty)
# define typecheckOnly(func)
#endif
static inline
RenderObject *robj(lua_State *L, int slot = 1)
{
RenderObject *r = (RenderObject*)lua_touserdata(L, slot);
ENSURE_TYPE(r, SCO_RENDEROBJECT);
if (!r)
scriptDebug(L, "RenderObject invalid pointer.");
return r;
}
static inline
ScriptedEntity *scriptedEntity(lua_State *L, int slot = 1)
{
ScriptedEntity *se = (ScriptedEntity*)lua_touserdata(L, slot);
ENSURE_TYPE(se, SCO_SCRIPTED_ENTITY);
if (!se)
scriptDebug(L, "ScriptedEntity invalid pointer.");
return se;
}
static inline
CollideEntity *collideEntity(lua_State *L, int slot = 1)
{
CollideEntity *ce = (CollideEntity*)lua_touserdata(L, slot);
ENSURE_TYPE(ce, SCO_COLLIDE_ENTITY);
if (!ce)
scriptDebug(L, "CollideEntity invalid pointer.");
return ce ;
}
static inline
Beam *beam(lua_State *L, int slot = 1)
{
Beam *b = (Beam*)lua_touserdata(L, slot);
ENSURE_TYPE(b, SCO_BEAM);
if (!b)
scriptDebug(L, "Beam invalid pointer.");
return b;
}
static inline
std::string getString(lua_State *L, int slot = 1)
{
std::string sr;
if (lua_isstring(L, slot))
{
sr = lua_tostring(L, slot);
}
return sr;
}
static inline
const char *getCString(lua_State *L, int slot = 1)
{
return lua_isstring(L, slot) ? lua_tostring(L, slot) : NULL;
}
static inline
Shot *getShot(lua_State *L, int slot = 1)
{
Shot *shot = (Shot*)lua_touserdata(L, slot);
ENSURE_TYPE(shot, SCO_SHOT);
if (!shot)
scriptDebug(L, "Shot invalid pointer.");
return shot;
}
static inline
Web *getWeb(lua_State *L, int slot = 1)
{
Web *web = (Web*)lua_touserdata(L, slot);
ENSURE_TYPE(web, SCO_WEB);
if (!web)
scriptDebug(L, "Web invalid pointer.");
return web;
}
static inline
Ingredient *getIng(lua_State *L, int slot = 1)
{
Ingredient *ing = (Ingredient*)lua_touserdata(L, slot);
ENSURE_TYPE(ing, SCO_INGREDIENT);
if (!ing)
scriptDebug(L, "Ingredient invalid pointer.");
return ing;
}
static inline
bool getBool(lua_State *L, int slot = 1)
{
if (lua_isnumber(L, slot))
{
return bool(lua_tonumber(L, slot));
}
else if (lua_islightuserdata(L, slot))
{
return (lua_touserdata(L, slot) != NULL);
}
else if (lua_isboolean(L, slot))
{
return lua_toboolean(L, slot);
}
return false;
}
static inline
Entity *entity(lua_State *L, int slot = 1)
{
Entity *ent = (Entity*)lua_touserdata(L, slot);
ENSURE_TYPE(ent, SCO_ENTITY);
if (!ent)
{
scriptDebug(L, "Entity Invalid Pointer");
}
return ent;
}
static inline
Vector getVector(lua_State *L, int slot = 1)
{
Vector v(lua_tonumber(L, slot), lua_tonumber(L, slot+1));
return v;
}
static inline
Bone *bone(lua_State *L, int slot = 1)
{
Bone *b = (Bone*)lua_touserdata(L, slot);
ENSURE_TYPE(b, SCO_BONE);
if (!b)
{
scriptDebug(L, "Bone Invalid Pointer");
}
return b;
}
static inline
Path *pathFromName(lua_State *L, int slot = 1)
{
std::string s = getString(L, slot);
stringToLower(s);
Path *p = dsq->game->getPathByName(s);
if (!p)
{
debugLog("Could not find path [" + s + "]");
}
return p;
}
static inline
Path *path(lua_State *L, int slot = 1)
{
Path *p = (Path*)lua_touserdata(L, slot);
ENSURE_TYPE(p, SCO_PATH);
return p;
}
static inline
Quad *getQuad(lua_State *L, int slot = 1)
{
Quad *q = (Quad*)lua_touserdata(L, slot);
ENSURE_TYPE(q, SCO_QUAD);
if (!q)
scriptDebug(L, "Invalid Quad");
return q;
}
static inline
BaseText *getText(lua_State *L, int slot = 1)
{
BaseText *q = (BaseText*)lua_touserdata(L, slot);
ENSURE_TYPE(q, SCO_TEXT);
if (!q)
scriptDebug(L, "Invalid Text");
return q;
}
static inline
Shader *getShader(lua_State *L, int slot = 1)
{
Shader *q = (Shader*)lua_touserdata(L, slot);
ENSURE_TYPE(q, SCO_SHADER);
if (!q)
scriptDebug(L, "Invalid Shader");
return q;
}
static SkeletalSprite *getSkeletalSprite(Entity *e)
{
return e ? &e->skeletalSprite : NULL;
}
static inline
ParticleEffect *getParticle(lua_State *L, int slot = 1)
{
ParticleEffect *q = (ParticleEffect*)lua_touserdata(L, slot);
ENSURE_TYPE(q, SCO_PARTICLE_EFFECT);
if (!q)
scriptDebug(L, "Invalid Particle Effect");
return q;
}
static bool looksLikeGlobal(const char *s)
{
for( ; *s; ++s)
if( !((*s >= 'A' && *s <= 'Z') || *s == '_' || (*s >= '0' && *s <= '9')) ) // accept any uppercase, number, and _ char
return false;
return true;
}
inline float interpolateVec1(lua_State *L, InterpolatedVector& vec, int argOffs)
{
return vec.interpolateTo(
lua_tonumber (L, argOffs ), // value
lua_tonumber (L, argOffs+1), // time
lua_tointeger(L, argOffs+2), // loopType
getBool (L, argOffs+3), // pingPong
getBool (L, argOffs+4)); // ease
}
inline float interpolateVec1z(lua_State *L, InterpolatedVector& vec, int argOffs)
{
return vec.interpolateTo(
Vector(0.0f, 0.0f, lua_tonumber (L, argOffs )), // value, last component
lua_tonumber (L, argOffs+1), // time
lua_tointeger(L, argOffs+2), // loopType
getBool (L, argOffs+3), // pingPong
getBool (L, argOffs+4)); // ease
}
inline float interpolateVec2(lua_State *L, InterpolatedVector& vec, int argOffs)
{
return vec.interpolateTo(
Vector(lua_tonumber (L, argOffs ), // x value
lua_tonumber (L, argOffs+1)), // y value
lua_tonumber (L, argOffs+2), // time
lua_tointeger(L, argOffs+3), // loopType
getBool(L, argOffs+4), // pingPong
getBool(L, argOffs+5)); // ease
}
inline float interpolateVec3(lua_State *L, InterpolatedVector& vec, int argOffs)
{
return vec.interpolateTo(
Vector(lua_tonumber (L, argOffs ), // x value
lua_tonumber (L, argOffs+1), // y value
lua_tonumber (L, argOffs+2)), // z value
lua_tonumber (L, argOffs+3), // time
lua_tointeger(L, argOffs+4), // loopType
getBool(L, argOffs+5), // pingPong
getBool(L, argOffs+6)); // ease
}
static void safePath(lua_State *L, const std::string& path)
{
// invalid characters for file/path names.
// Filter out \ as well, it'd work on on win32 only, so it's not supposed to be used.
size_t invchr = path.find_first_of("\\\":*?<>|");
if(invchr != std::string::npos)
{
lua_pushfstring(L, "Invalid char in path/file name: %c", path[invchr]);
lua_error(L);
}
// Block attempts to access files outside of the "safe area"
if(path.length())
{
if(path[0] == '/')
{
if(!(dsq->mod.isActive() && path.substr(0, dsq->mod.getBaseModPath().length()) == dsq->mod.getBaseModPath()))
{
lua_pushliteral(L, "Absolute paths are not allowed");
lua_error(L);
}
}
if(path.find("../") != std::string::npos)
{
lua_pushliteral(L, "Accessing parent is not allowed");
lua_error(L);
}
}
}
//----------------------------------//
#define luaFunc(func) static int l_##func(lua_State *L)
#define luaReturnBool(bool) do {lua_pushboolean(L, (bool)); return 1;} while(0)
#define luaReturnInt(num) do {lua_pushinteger(L, (num)); return 1;} while(0)
#define luaReturnNum(num) do {lua_pushnumber(L, (num)); return 1;} while(0)
#define luaReturnPtr(ptr) do {luaPushPointer(L, (ptr)); return 1;} while(0)
#define luaReturnStr(str) do {lua_pushstring(L, (str)); return 1;} while(0)
#define luaReturnVec2(x,y) do {lua_pushnumber(L, (x)); lua_pushnumber(L, (y)); return 2;} while(0)
#define luaReturnVec3(x,y,z) do {lua_pushnumber(L, (x)); lua_pushnumber(L, (y)); lua_pushnumber(L, (z)); return 3;} while(0)
#define luaReturnVec4(x,y,z,w) do {lua_pushnumber(L, (x)); lua_pushnumber(L, (y)); lua_pushnumber(L, (z)); lua_pushnumber(L, (w)); return 4;} while(0)
#define luaReturnNil() return 0;
// Set the global "v" to the instance's local variable table. Must be
// called when starting a script.
static void fixupLocalVars(lua_State *L)
{
lua_getglobal(L, "_threadvars");
lua_pushlightuserdata(L, L);
lua_gettable(L, -2);
lua_remove(L, -2);
lua_setglobal(L, "v");
}
luaFunc(indexWarnGlobal)
{
lua_pushvalue(L, -1);
lua_rawget(L, -3);
lua_remove(L, -3);
if (lua_isnil(L, -1))
{
// Don't warn on "v" or known interface functions.
lua_pushvalue(L, -2);
const char *varname = lua_tostring(L, -1);
bool doWarn = (strcmp(varname, "v") != 0);
for (unsigned int i = 0; doWarn && interfaceFunctions[i] != NULL; i++)
{
doWarn = (strcmp(varname, interfaceFunctions[i]) != 0);
}
if (doWarn)
{
std::string s = "WARNING: script tried to get/call undefined global variable ";
s += varname;
scriptError(L, s);
}
lua_pop(L, 1);
}
lua_remove(L, -2);
return 1;
}
luaFunc(newindexWarnGlobal)
{
// Don't warn on "v" or known interface functions.
lua_pushvalue(L, -2);
const char *varname = lua_tostring(L, -1);
bool doWarn = (strcmp(varname, "v") != 0) && !looksLikeGlobal(varname);
for (unsigned int i = 0; doWarn && interfaceFunctions[i] != NULL; i++)
{
doWarn = (strcmp(varname, interfaceFunctions[i]) != 0);
}
if (doWarn)
{
std::ostringstream os;
os << "WARNING: script set global "
<< lua_typename(L, lua_type(L, -2))
<< " " << varname;
scriptError(L, os.str());
}
lua_pop(L, 1);
// Do the set anyway.
lua_rawset(L, -3);
lua_pop(L, 1);
return 0;
}
luaFunc(indexWarnInstance)
{
lua_pushvalue(L, -1);
lua_rawget(L, -3);
lua_remove(L, -3);
if (lua_isnil(L, -1))
{
std::ostringstream os;
os << "WARNING: script tried to get/call undefined instance variable "
<< getString(L, -2);
scriptError(L, os.str());
}
lua_remove(L, -2);
return 1;
}
luaFunc(panicHandler)
{
std::string err = luaFormatStackInfo(L) + ": Lua PANIC: " + getString(L, -1);
exit_error(err);
return 0;
}
static bool findFile_helper(const char *rawname, std::string &fname)
{
if (!rawname)
return false;
if (dsq->mod.isActive())
{
fname = dsq->mod.getPath();
if(fname[fname.length() - 1] != '/')
fname += '/';
fname += rawname;
fname = localisePath(fname, dsq->mod.getPath());
fname = adjustFilenameCase(fname);
if (exists(fname))
return true;
}
fname = localisePath(rawname);
fname = adjustFilenameCase(fname);
return exists(fname);
}
static int loadFile_helper(lua_State *L, const char *fn)
{
#ifdef BBGE_BUILD_VFS
unsigned long size = 0;
const char *data = readFile(fn, &size);
if (!data)
{
lua_pushfstring(L, "cannot open %s", fn);
return LUA_ERRFILE;
}
else
{
int result = luaL_loadbuffer(L, data, size, fn);
delete [] data;
return result;
}
#else
return luaL_loadfile(L, fn);
#endif
}
luaFunc(dofile_caseinsensitive)
{
// This is Lua's dofile(), with some tweaks. --ryan.
std::string fname;
findFile_helper(luaL_checkstring(L, 1), fname);
int n = lua_gettop(L);
if (loadFile_helper(L, fname.c_str()) != 0)
lua_error(L);
lua_call(L, 0, LUA_MULTRET);
return lua_gettop(L) - n;
}
luaFunc(loadfile_caseinsensitive)
{
// This is Lua's loadfile(), with some tweaks. --FG.
std::string fname;
findFile_helper(luaL_checkstring(L, 1), fname);
if (loadFile_helper(L, fname.c_str()) == 0) /* OK? */
return 1;
else
{
lua_pushnil(L);
lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */
}
}
luaFunc(fileExists)
{
const std::string s = getString(L);
safePath(L, s);
std::string res;
bool there = findFile_helper(s.c_str(), res);
lua_pushboolean(L, there);
lua_pushstring(L, res.c_str());
return 2;
}
luaFunc(getModName)
{
luaReturnStr(dsq->mod.isActive() ? dsq->mod.getName().c_str() : "");
}
luaFunc(getModPath)
{
std::string path;
if (dsq->mod.isActive())
{
path = dsq->mod.getPath();
if(path[path.length() - 1] != '/')
path += '/';
}
luaReturnStr(path.c_str());
}
luaFunc(getInterfaceFunctionNames)
{
lua_newtable(L);
for(unsigned i = 0; interfaceFunctions[i]; ++i)
{
lua_pushstring(L, interfaceFunctions[i]);
lua_rawseti(L, -2, i+1);
}
return 1;
}
// ----- RenderObject common functions -----
#define forwardCall(func) l_##func(L)
#define MakeTypeCheckFunc(fname, ty) luaFunc(fname) \
{ ScriptObject *r = (ScriptObject*)lua_touserdata(L, 1); luaReturnBool(r ? r->isType(ty) : false); }
MakeTypeCheckFunc(isNode, SCO_PATH);
MakeTypeCheckFunc(isObject, SCO_RENDEROBJECT);
MakeTypeCheckFunc(isEntity, SCO_ENTITY)
MakeTypeCheckFunc(isScriptedEntity, SCO_SCRIPTED_ENTITY)
MakeTypeCheckFunc(isBone, SCO_BONE)
MakeTypeCheckFunc(isShot, SCO_SHOT)
MakeTypeCheckFunc(isWeb, SCO_WEB)
MakeTypeCheckFunc(isIng, SCO_INGREDIENT)
MakeTypeCheckFunc(isBeam, SCO_BEAM)
MakeTypeCheckFunc(isText, SCO_TEXT)
MakeTypeCheckFunc(isShader, SCO_SHADER)
MakeTypeCheckFunc(isParticleEffect, SCO_PARTICLE_EFFECT)
#undef MakeTypeCheckFunc
// special, because it would return true on almost everything that is RenderObject based.
// Instead, return true only for stuff created with createQuad()
luaFunc(isQuad)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->isExactType(ScriptObjectType(SCO_RENDEROBJECT | SCO_QUAD)) : false);
}
luaFunc(obj_setPosition)
{
RenderObject *r = robj(L);
if (r)
{
r->position.stop();
interpolateVec2(L, r->position, 2);
}
luaReturnNil();
}
luaFunc(obj_scale)
{
RenderObject *r = robj(L);
if (r)
{
r->scale.stop();
interpolateVec2(L, r->scale, 2);
}
luaReturnNil();
}
luaFunc(obj_getScale)
{
RenderObject *r = robj(L);
Vector s;
if (r)
s = r->scale;
luaReturnVec2(s.x, s.y);
}
luaFunc(obj_alpha)
{
RenderObject *r = robj(L);
if (r)
{
r->alpha.stop();
interpolateVec1(L, r->alpha, 2);
}
luaReturnNil();
}
luaFunc(obj_alphaMod)
{
RenderObject *r = robj(L);
if (r)
r->alphaMod = lua_tonumber(L, 2);
luaReturnNil()
}
luaFunc(obj_getAlphaMod)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->alphaMod : 0.0f);
}
luaFunc(obj_getAlpha)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->alpha.x : 0.0f);
}
luaFunc(obj_color)
{
RenderObject *r = robj(L);
if (r)
{
r->color.stop();
interpolateVec3(L, r->color, 2);
}
luaReturnNil();
}
luaFunc(obj_getColor)
{
RenderObject *r = robj(L);
Vector c;
if(r)
c = r->color;
luaReturnVec3(c.x, c.y, c.z);
}
luaFunc(obj_rotate)
{
RenderObject *r = robj(L);
if (r)
{
r->rotation.stop();
interpolateVec1z(L, r->rotation, 2);
}
luaReturnNil();
}
luaFunc(obj_rotateOffset)
{
RenderObject *r = robj(L);
if (r)
{
r->rotationOffset.stop();
interpolateVec1z(L, r->rotationOffset, 2);
}
luaReturnNil();
}
luaFunc(obj_getRotation)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->rotation.z : 0.0f);
}
luaFunc(obj_getRotationOffset)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->rotationOffset.z : 0.0f);
}
luaFunc(obj_offset)
{
RenderObject *r = robj(L);
if (r)
{
r->offset.stop();
interpolateVec2(L, r->offset, 2);
}
luaReturnNil();
}
luaFunc(obj_internalOffset)
{
RenderObject *r = robj(L);
if (r)
{
r->internalOffset.stop();
interpolateVec2(L, r->internalOffset, 2);
}
luaReturnNil();
}
luaFunc(obj_getInternalOffset)
{
RenderObject *r = robj(L);
Vector io;
if (r)
io = r->internalOffset;
luaReturnVec2(io.x, io.y);
}
luaFunc(obj_getPosition)
{
float x=0,y=0;
RenderObject *r = robj(L);
if (r)
{
x = r->position.x;
y = r->position.y;
}
luaReturnVec2(x, y);
}
luaFunc(obj_getOffset)
{
float x=0,y=0;
RenderObject *r = robj(L);
if (r)
{
x = r->offset.x;
y = r->offset.y;
}
luaReturnVec2(x, y);
}
luaFunc(obj_x)
{
RenderObject *r = robj(L);
float x = 0;
if (r)
x = r->position.x;
luaReturnNum(x);
}
luaFunc(obj_y)
{
RenderObject *r = robj(L);
float y = 0;
if (r)
y = r->position.y;
luaReturnNum(y);
}
luaFunc(obj_setBlendType)
{
RenderObject *r = robj(L);
if (r)
r->setBlendType(lua_tointeger(L, 2));
luaReturnNil();
}
luaFunc(obj_getBlendType)
{
RenderObject *r = robj(L);
luaReturnInt(r ? r->blendType : 0);
}
luaFunc(obj_setTexture)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->setTexture(getString(L, 2)) : false);
}
luaFunc(obj_getTexture)
{
RenderObject *r = robj(L);
if (r && r->texture)
luaReturnStr(r->texture->name.c_str());
luaReturnStr("");
}
luaFunc(obj_delete)
{
RenderObject *r = robj(L);
if (r)
{
float time = lua_tonumber(L, 2);
if (time == 0)
{
r->safeKill();
}
else
{
r->fadeAlphaWithLife = true;
r->setLife(1);
r->setDecayRate(1.0f/time);
}
}
luaReturnNil();
}
luaFunc(obj_setLife)
{
RenderObject *r = robj(L);
if (r)
r->setLife(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(obj_getLife)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->life : 0.0f);
}
luaFunc(obj_setDecayRate)
{
RenderObject *r = robj(L);
if (r)
r->setDecayRate(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(obj_addDeathNotify)
{
RenderObject *r = robj(L);
RenderObject *which = robj(L, 2);
if (r && which)
r->addDeathNotify(which);
luaReturnNil();
}
luaFunc(obj_addChild)
{
RenderObject *r = robj(L);
RenderObject *which = robj(L, 2);
bool takeOwnership = getBool(L, 3);
bool front = getBool(L, 4);
if (r && which)
{
if (takeOwnership)
{
// HACK: this is ugly, but necessary to prevent double-deletion
// anyways, dangerous; addChild() may fail, causing a small memory leak (and an error message)
dsq->getState(dsq->game->name)->removeRenderObjectFromList(which);
which->setStateDataObject(NULL);
core->removeRenderObject(which, Core::DO_NOT_DESTROY_RENDER_OBJECT);
r->addChild(which, PM_POINTER, RBP_NONE, front ? CHILD_FRONT : CHILD_BACK);
}
else
r->addChild(which, PM_STATIC);
}
luaReturnNil();
}
luaFunc(obj_getChild)
{
RenderObject *r = robj(L);
size_t idx = lua_tointeger(L, 2);
luaReturnPtr(r && idx < r->children.size() ? r->children[idx] : NULL);
}
luaFunc(obj_removeChild)
{
RenderObject *r = robj(L);
RenderObject *which = robj(L, 2);
if(r && which)
r->removeChild(which);
luaReturnNil();
}
luaFunc(obj_removeChildIdx)
{
RenderObject *r = robj(L);
size_t idx = lua_tointeger(L, 2);
if(r && idx < r->children.size())
r->removeChild(r->children[idx]);
luaReturnNil();
}
luaFunc(obj_removeAllChildren)
{
RenderObject *r = robj(L);
bool del = getBool(L, 2);
if(r)
{
if(del)
for(RenderObject::Children::iterator it = r->children.begin(); it != r->children.end(); ++it)
(*it)->safeKill();
r->children.clear();
}
luaReturnNil();
}
luaFunc(obj_getNumChildren)
{
RenderObject *r = robj(L);
luaReturnInt(r ? (int)r->children.size() : 0);
}
luaFunc(obj_setRenderBeforeParent)
{
RenderObject *r = robj(L);
if (r)
r->renderBeforeParent = getBool(L, 2);
luaReturnNil();
}
luaFunc(obj_isRenderBeforeParent)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->renderBeforeParent : false);
}
// Not so pretty: Because RenderObject has a `velocity' vector,
// and Entity has `vel' ADDITIONALLY, we need to use
// extra functions to manage RenderObject's velocities.
// Different names were chosen to allow avoid name clashing. -- FG
luaFunc(obj_setInternalVel)
{
RenderObject *r = robj(L);
if (r)
{
r->velocity.stop();
interpolateVec2(L, r->velocity, 2);
}
luaReturnNil();
}
luaFunc(obj_setInternalVelLen)
{
RenderObject *r = robj(L);
if (r)
{
r->velocity.stop();
r->velocity.setLength2D(lua_tonumber(L, 2));
}
luaReturnNil();
}
luaFunc(obj_getInternalVelLen)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->velocity.getLength2D() : 0.0f);
}
luaFunc(obj_getInternalVel)
{
Vector v;
RenderObject *r = robj(L);
if (r)
v = r->velocity;
luaReturnVec2(v.x, v.y);
}
luaFunc(obj_ivelx)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->velocity.x : 0.0f);
}
luaFunc(obj_ively)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->velocity.y : 0.0f);
}
luaFunc(obj_addInternalVel)
{
RenderObject *r = robj(L);
if (r)
r->velocity += Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(obj_isInternalVelIn)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->velocity.isLength2DIn(lua_tonumber(L, 2)) : false);
}
luaFunc(obj_setGravity)
{
RenderObject *r = robj(L);
if (r)
{
r->gravity.stop();
interpolateVec2(L, r->gravity, 2);
}
luaReturnNil();
}
luaFunc(obj_getGravity)
{
Vector v;
RenderObject *r = robj(L);
if (r)
v = r->gravity;
luaReturnVec2(v.x, v.y);
}
luaFunc(obj_getCollideRadius)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->collideRadius : 0);
}
luaFunc(obj_setCollideRadius)
{
RenderObject *r = robj(L);
if (r)
r->collideRadius = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(obj_getNormal)
{
Vector v(0, 1);
RenderObject *r = robj(L);
if (r)
v = r->getForward();
luaReturnVec2(v.x, v.y);
}
luaFunc(obj_getVectorToObj)
{
RenderObject *r1 = robj(L);
RenderObject *r2 = robj(L, 2);
if (r1 && r2)
{
Vector diff = r2->position - r1->position;
luaReturnVec2(diff.x, diff.y);
}
else
{
luaReturnVec2(0, 0);
}
}
luaFunc(obj_stopInterpolating)
{
RenderObject *r = robj(L);
if (r)
r->position.stop();
luaReturnNil();
}
luaFunc(obj_isInterpolating)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->position.isInterpolating() : false);
}
luaFunc(obj_followCamera)
{
RenderObject *r = robj(L);
if (r)
r->followCamera = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(obj_update)
{
RenderObject *r = robj(L);
if (r)
r->update(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(obj_getWorldPosition)
{
RenderObject *b = robj(L);
float x = 0, y = 0;
if (b)
{
Vector v = b->getWorldCollidePosition(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)));
x = v.x;
y = v.y;
}
luaReturnVec2(x, y);
}
luaFunc(obj_getWorldRotation)
{
RenderObject *r = robj(L);
luaReturnNum(r ? r->getWorldRotation() : 0.0f);
}
luaFunc(obj_getWorldPositionAndRotation)
{
RenderObject *r = robj(L);
if (r)
{
Vector v = r->getWorldPositionAndRotation();
luaReturnVec3(v.x, v.y, v.z);
}
luaReturnVec3(0.0f, 0.0f, 0.0f);
}
luaFunc(obj_moveToFront)
{
RenderObject *r = robj(L);
if (r)
r->moveToFront();
luaReturnNil();
}
luaFunc(obj_moveToBack)
{
RenderObject *r = robj(L);
if (r)
r->moveToBack();
luaReturnNil();
}
luaFunc(obj_setLayer)
{
RenderObject *r = robj(L);
if (r)
core->switchRenderObjectLayer(r, lua_tointeger(L, 2));
luaReturnNil();
}
luaFunc(obj_getLayer)
{
RenderObject *r = robj(L);
luaReturnInt(r ? r->layer : 0);
}
luaFunc(obj_setRenderPass)
{
RenderObject *r = robj(L);
int pass = lua_tointeger(L, 2);
if (r)
r->setRenderPass(pass);
luaReturnNil();
}
luaFunc(obj_setOverrideRenderPass)
{
RenderObject *r = robj(L);
int pass = lua_tointeger(L, 2);
if (r)
r->setOverrideRenderPass(pass);
luaReturnNil();
}
luaFunc(obj_fh)
{
RenderObject *r = robj(L);
if (r)
r->flipHorizontal();
luaReturnNil();
}
luaFunc(obj_fhTo)
{
RenderObject *r = robj(L);
bool b = getBool(L);
if (r)
r->fhTo(b);
luaReturnNil();
}
luaFunc(obj_fv)
{
RenderObject *r = robj(L);
if (r)
r->flipVertical();
luaReturnNil();
}
luaFunc(obj_isfh)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->isfh() : false);
}
luaFunc(obj_isfv)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->isfv() : false);
}
luaFunc(obj_isfhr)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->isfhr() : false);
}
luaFunc(obj_isfvr)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->isfvr() : false);
}
luaFunc(obj_damageFlash)
{
RenderObject *r = robj(L);
int type = lua_tointeger(L, 2);
if (r)
{
Vector toColor = Vector(1, 0.1, 0.1);
if (type == 1)
toColor = Vector(1, 1, 0.1);
r->color = Vector(1,1,1);
r->color.interpolateTo(toColor, 0.1, 5, 1);
}
luaReturnNil();
}
luaFunc(obj_setCull)
{
RenderObject *r = robj(L);
if (r)
r->cull = getBool(L, 2);
luaReturnNil();
}
luaFunc(obj_setCullRadius)
{
RenderObject *r = robj(L);
if (r)
r->setOverrideCullRadius(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(obj_isScaling)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->scale.isInterpolating() : false);
}
luaFunc(obj_isRotating)
{
RenderObject *r = robj(L);
luaReturnBool(r ? r->rotation.isInterpolating() : false);
}
luaFunc(obj_setUpdateCull)
{
RenderObject *r = robj(L);;
if (r)
r->updateCull = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(obj_getUpdateCull)
{
RenderObject *r = robj(L);;
luaReturnNum(r ? r->updateCull : 0.0f);
}
luaFunc(obj_setPositionX)
{
RenderObject *r = robj(L);
if (r)
r->position.x = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(obj_setPositionY)
{
RenderObject *r = robj(L);
if (r)
r->position.y = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(obj_enableMotionBlur)
{
RenderObject *r = robj(L);
if (r)
r->enableMotionBlur(10, 2);
luaReturnNil();
}
luaFunc(obj_disableMotionBlur)
{
RenderObject *r = robj(L);
if (r)
r->disableMotionBlur();
luaReturnNil();
}
luaFunc(obj_collideCircleVsLine)
{
RenderObject *r = robj(L);
float x1, y1, x2, y2, sz;
x1 = lua_tonumber(L, 2);
y1 = lua_tonumber(L, 3);
x2 = lua_tonumber(L, 4);
y2 = lua_tonumber(L, 5);
sz = lua_tonumber(L, 6);
bool v = false;
if (r)
v = dsq->game->collideCircleVsLine(r, Vector(x1, y1), Vector(x2, y2), sz);
luaReturnBool(v);
}
luaFunc(obj_collideCircleVsLineAngle)
{
RenderObject *r = robj(L);
float angle = lua_tonumber(L, 2);
float start=lua_tonumber(L, 3), end=lua_tonumber(L, 4), radius=lua_tonumber(L, 5);
float x=lua_tonumber(L, 6);
float y=lua_tonumber(L, 7);
bool v = false;
if (r)
v = dsq->game->collideCircleVsLineAngle(r, angle, start, end, radius, Vector(x,y));
luaReturnBool(v);
}
luaFunc(obj_fadeAlphaWithLife)
{
RenderObject *r = robj(L);
if (r)
r->fadeAlphaWithLife = getBool(L, 2);
luaReturnNil();
}
luaFunc(obj_getWorldScale)
{
RenderObject *r = robj(L);
Vector s;
if (r)
s = r->getRealScale();
luaReturnVec2(s.x, s.y);
}
luaFunc(obj_getParent)
{
RenderObject *r = robj(L);
luaReturnPtr(r ? r->getParent() : NULL);
}
// ----- end RenderObject common functions -----
// ----- Quad common functions -----
luaFunc(quad_isVisible)
{
Quad *q = getQuad(L);
luaReturnBool(q ? q->renderQuad : false);
}
luaFunc(quad_setVisible)
{
Quad *q = getQuad(L);
if (q)
q->renderQuad = getBool(L, 2);
luaReturnNil();
}
luaFunc(quad_getWidth)
{
Quad *q = getQuad(L);
luaReturnNum(q ? q->width : 0.0f);
}
luaFunc(quad_getHeight)
{
Quad *q = getQuad(L);
luaReturnNum(q ? q->height : 0.0f);
}
luaFunc(quad_setWidth)
{
Quad *q = getQuad(L);
if (q)
q->setWidth(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(quad_setHeight)
{
Quad *q = getQuad(L);
if (q)
q->setHeight(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(quad_setSegs)
{
Quad *b = getQuad(L);
if (b)
b->setSegs(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6), lua_tonumber(L, 7), lua_tonumber(L, 8), getBool(L, 9));
luaReturnNil();
}
luaFunc(quad_setRepeatTexture)
{
Quad *b = getQuad(L);
if (b)
b->repeatTextureToFill(getBool(L, 2));
luaReturnNil();
}
luaFunc(quad_setRepeatScale)
{
Quad *b = getQuad(L);
if (b)
b->repeatToFillScale = Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(quad_isRepeatTexture)
{
Quad *b = getQuad(L);
luaReturnBool(b ? b->isRepeatingTextureToFill() : false);
}
luaFunc(quad_setTexOffset)
{
Quad *b = getQuad(L);
if (b)
b->texOff = Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(quad_getTexOffset)
{
Quad *b = getQuad(L);
Vector v;
if (b)
v = b->texOff;
luaReturnVec2(v.x, v.y);
}
luaFunc(quad_setRenderBorder)
{
Quad *b = getQuad(L);
if (b)
b->renderBorder = getBool(L, 2);
luaReturnNil();
}
luaFunc(quad_isRenderBorder)
{
Quad *b = getQuad(L);
luaReturnBool(b ? b->renderBorder : false);
}
luaFunc(quad_setRenderCenter)
{
Quad *b = getQuad(L);
if (b)
b->renderCenter = getBool(L, 2);
luaReturnNil();
}
luaFunc(quad_isRenderCenter)
{
Quad *b = getQuad(L);
luaReturnBool(b ? b->renderCenter : false);
}
luaFunc(quad_borderAlpha)
{
Quad *b = getQuad(L);
if (b)
b->borderAlpha = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(quad_getBorderAlpha)
{
Quad *b = getQuad(L);
luaReturnNum(b ? b->borderAlpha : 0.0f);
}
// --- standard set/get functions for each type, wrapping RenderObject functions ---
#define MK_FUNC(base, getter, prefix, suffix) \
luaFunc(prefix##_##suffix) \
{ \
typecheckOnly(getter(L)); \
return forwardCall(base##_##suffix); \
}
#define MK_ALIAS(prefix, suffix, alias) // not yet used here. defined to avoid warnings
#define RO_FUNC(getter, prefix, suffix) MK_FUNC(obj, getter, prefix, suffix)
#define Q_FUNC(getter, prefix, suffix) MK_FUNC(quad, getter, prefix, suffix)
#define MAKE_ROBJ_FUNCS(getter, prefix) \
RO_FUNC(getter, prefix, setPosition ) \
RO_FUNC(getter, prefix, scale ) \
RO_FUNC(getter, prefix, getScale ) \
RO_FUNC(getter, prefix, isScaling ) \
RO_FUNC(getter, prefix, alpha ) \
RO_FUNC(getter, prefix, alphaMod ) \
RO_FUNC(getter, prefix, getAlpha ) \
RO_FUNC(getter, prefix, getAlphaMod ) \
RO_FUNC(getter, prefix, color ) \
RO_FUNC(getter, prefix, getColor ) \
RO_FUNC(getter, prefix, rotate ) \
RO_FUNC(getter, prefix, rotateOffset ) \
RO_FUNC(getter, prefix, getRotation ) \
RO_FUNC(getter, prefix, getRotationOffset) \
RO_FUNC(getter, prefix, isRotating ) \
RO_FUNC(getter, prefix, offset ) \
RO_FUNC(getter, prefix, getOffset ) \
RO_FUNC(getter, prefix, internalOffset ) \
RO_FUNC(getter, prefix, getInternalOffset) \
RO_FUNC(getter, prefix, getPosition ) \
RO_FUNC(getter, prefix, getTexture ) \
RO_FUNC(getter, prefix, x ) \
RO_FUNC(getter, prefix, y ) \
RO_FUNC(getter, prefix, setBlendType ) \
RO_FUNC(getter, prefix, getBlendType ) \
RO_FUNC(getter, prefix, setTexture ) \
RO_FUNC(getter, prefix, delete ) \
RO_FUNC(getter, prefix, getLife ) \
RO_FUNC(getter, prefix, setLife ) \
RO_FUNC(getter, prefix, setDecayRate ) \
RO_FUNC(getter, prefix, addDeathNotify ) \
RO_FUNC(getter, prefix, setInternalVel ) \
RO_FUNC(getter, prefix, setInternalVelLen) \
RO_FUNC(getter, prefix, getInternalVel ) \
RO_FUNC(getter, prefix, ivelx ) \
RO_FUNC(getter, prefix, ively ) \
RO_FUNC(getter, prefix, addInternalVel ) \
RO_FUNC(getter, prefix, isInternalVelIn) \
RO_FUNC(getter, prefix, getInternalVelLen) \
RO_FUNC(getter, prefix, setGravity ) \
RO_FUNC(getter, prefix, getGravity ) \
RO_FUNC(getter, prefix, getCollideRadius) \
RO_FUNC(getter, prefix, setCollideRadius) \
RO_FUNC(getter, prefix, getNormal ) \
RO_FUNC(getter, prefix, stopInterpolating)\
RO_FUNC(getter, prefix, isInterpolating)\
RO_FUNC(getter, prefix, followCamera ) \
RO_FUNC(getter, prefix, update ) \
RO_FUNC(getter, prefix, getWorldPosition) \
RO_FUNC(getter, prefix, getWorldRotation) \
RO_FUNC(getter, prefix, getWorldPositionAndRotation)\
RO_FUNC(getter, prefix, moveToFront ) \
RO_FUNC(getter, prefix, moveToBack ) \
RO_FUNC(getter, prefix, setLayer ) \
RO_FUNC(getter, prefix, getLayer ) \
RO_FUNC(getter, prefix, setRenderBeforeParent) \
RO_FUNC(getter, prefix, isRenderBeforeParent) \
RO_FUNC(getter, prefix, addChild ) \
RO_FUNC(getter, prefix, getChild ) \
RO_FUNC(getter, prefix, removeChild ) \
RO_FUNC(getter, prefix, removeChildIdx ) \
RO_FUNC(getter, prefix, removeAllChildren) \
RO_FUNC(getter, prefix, getNumChildren ) \
RO_FUNC(getter, prefix, fh ) \
RO_FUNC(getter, prefix, fv ) \
RO_FUNC(getter, prefix, fhTo ) \
RO_FUNC(getter, prefix, isfh ) \
RO_FUNC(getter, prefix, isfv ) \
RO_FUNC(getter, prefix, isfhr ) \
RO_FUNC(getter, prefix, isfvr ) \
RO_FUNC(getter, prefix, damageFlash ) \
RO_FUNC(getter, prefix, setCull ) \
RO_FUNC(getter, prefix, setCullRadius ) \
RO_FUNC(getter, prefix, setUpdateCull ) \
RO_FUNC(getter, prefix, getUpdateCull ) \
RO_FUNC(getter, prefix, setRenderPass ) \
RO_FUNC(getter, prefix, setOverrideRenderPass ) \
RO_FUNC(getter, prefix, setPositionX ) \
RO_FUNC(getter, prefix, setPositionY ) \
RO_FUNC(getter, prefix, enableMotionBlur ) \
RO_FUNC(getter, prefix, disableMotionBlur ) \
RO_FUNC(getter, prefix, collideCircleVsLine) \
RO_FUNC(getter, prefix, collideCircleVsLineAngle) \
RO_FUNC(getter, prefix, getVectorToObj ) \
RO_FUNC(getter, prefix, fadeAlphaWithLife ) \
RO_FUNC(getter, prefix, getWorldScale ) \
RO_FUNC(getter, prefix, getParent ) \
MK_ALIAS(prefix, fh, flipHorizontal ) \
MK_ALIAS(prefix, fv, flipVertical )
#define MAKE_QUAD_FUNCS(getter, prefix) \
MAKE_ROBJ_FUNCS(getter, prefix) \
Q_FUNC(getter, prefix, setVisible ) \
Q_FUNC(getter, prefix, isVisible ) \
Q_FUNC(getter, prefix, setWidth ) \
Q_FUNC(getter, prefix, setHeight ) \
Q_FUNC(getter, prefix, getWidth ) \
Q_FUNC(getter, prefix, getHeight ) \
Q_FUNC(getter, prefix, setSegs ) \
Q_FUNC(getter, prefix, setRepeatTexture) \
Q_FUNC(getter, prefix, isRepeatTexture ) \
Q_FUNC(getter, prefix, setRepeatScale ) \
Q_FUNC(getter, prefix, setRenderBorder ) \
Q_FUNC(getter, prefix, isRenderBorder ) \
Q_FUNC(getter, prefix, setRenderCenter ) \
Q_FUNC(getter, prefix, isRenderCenter ) \
Q_FUNC(getter, prefix, borderAlpha ) \
Q_FUNC(getter, prefix, getBorderAlpha ) \
Q_FUNC(getter, prefix, setTexOffset ) \
Q_FUNC(getter, prefix, getTexOffset )
// This should reflect the internal class hierarchy,
// e.g. a Beam is a Quad, so it can use quad_* functions
#define EXPAND_FUNC_PROTOTYPES \
MAKE_QUAD_FUNCS(entity, entity) \
MAKE_QUAD_FUNCS(bone, bone ) \
MAKE_QUAD_FUNCS(getShot, shot ) \
MAKE_QUAD_FUNCS(beam, beam ) \
MAKE_ROBJ_FUNCS(getQuad, quad ) \
MAKE_ROBJ_FUNCS(getWeb, web ) \
MAKE_ROBJ_FUNCS(getText, text ) \
MAKE_ROBJ_FUNCS(getParticle, pe )
// first time, create them. (There is a second use of this further down, with different MK_* macros)
EXPAND_FUNC_PROTOTYPES
luaFunc(debugBreak)
{
debugLog("DEBUG BREAK");
triggerBreakpoint();
luaReturnNil();
}
luaFunc(setIgnoreAction)
{
dsq->game->setIgnoreAction((AquariaActions)lua_tointeger(L, 1), getBool(L, 2));
luaReturnNil();
}
luaFunc(isIgnoreAction)
{
luaReturnBool(dsq->game->isIgnoreAction((AquariaActions)lua_tointeger(L, 1)));
}
luaFunc(sendAction)
{
AquariaActions ac = (AquariaActions)lua_tointeger(L, 1);
int state = lua_tointeger(L, 2);
int mask = lua_tointeger(L, 3);
int source = lua_tointeger(L, 4);
if(!mask)
mask = -1;
if(mask & 1)
dsq->game->action(ac, state, source);
if((mask & 2) && dsq->game->avatar)
dsq->game->avatar->action(ac, state, source);
luaReturnNil();
}
luaFunc(randRange)
{
int n1 = lua_tointeger(L, 1);
int n2 = lua_tointeger(L, 2);
int spread = n2-n1;
int r = rand()%spread;
r += n1;
luaReturnNum(r);
}
luaFunc(upgradeHealth)
{
dsq->continuity.upgradeHealth();
luaReturnNil();
}
luaFunc(shakeCamera)
{
dsq->shakeCamera(lua_tonumber(L,1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(rumble)
{
dsq->rumble(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(changeForm)
{
dsq->game->avatar->changeForm((FormType)lua_tointeger(L, 1));
luaReturnNil();
}
luaFunc(getWaterLevel)
{
luaReturnNum(dsq->game->getWaterLevel());
}
luaFunc(setPoison)
{
dsq->continuity.setPoison(lua_tonumber(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(cureAllStatus)
{
dsq->continuity.cureAllStatus();
luaReturnNil();
}
luaFunc(setMusicToPlay)
{
if (lua_isstring(L, 1))
dsq->game->setMusicToPlay(getString(L, 1));
luaReturnNil();
}
luaFunc(setActivePet)
{
Entity *e = dsq->game->setActivePet(lua_tonumber(L, 1));
luaReturnPtr(e);
}
luaFunc(setWaterLevel)
{
interpolateVec1(L, dsq->game->waterLevel, 1);
luaReturnNum(dsq->game->waterLevel.x);
}
luaFunc(getForm)
{
luaReturnNum(dsq->continuity.form);
}
luaFunc(isForm)
{
FormType form = FormType(lua_tointeger(L, 1));
bool v = (form == dsq->continuity.form);
luaReturnBool(v);
}
luaFunc(learnFormUpgrade)
{
dsq->continuity.learnFormUpgrade((FormUpgradeType)lua_tointeger(L, 1));
luaReturnNil();
}
luaFunc(hasLi)
{
luaReturnBool(dsq->continuity.hasLi());
}
luaFunc(hasFormUpgrade)
{
luaReturnBool(dsq->continuity.hasFormUpgrade((FormUpgradeType)lua_tointeger(L, 1)));
}
// This used to be castSong(), but that name is already taken by an interface function. -- FG
luaFunc(singSong)
{
dsq->continuity.castSong(lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(isStory)
{
luaReturnBool(dsq->continuity.isStory(lua_tonumber(L, 1)));
}
luaFunc(getNoteVector)
{
int note = lua_tointeger(L, 1);
float mag = lua_tonumber(L, 2);
Vector v = dsq->getNoteVector(note, mag);
luaReturnVec2(v.x, v.y);
}
luaFunc(getNoteColor)
{
int note = lua_tointeger(L, 1);
Vector v = dsq->getNoteColor(note);
luaReturnVec3(v.x, v.y, v.z);
}
luaFunc(getRandNote)
{
luaReturnNum(dsq->getRandNote());
}
luaFunc(getStory)
{
luaReturnNum(dsq->continuity.getStory());
}
luaFunc(foundLostMemory)
{
int num = 0;
if (dsq->continuity.getFlag(FLAG_SECRET01)) num++;
if (dsq->continuity.getFlag(FLAG_SECRET02)) num++;
if (dsq->continuity.getFlag(FLAG_SECRET03)) num++;
int sbank = 800+(num-1);
dsq->game->setControlHint(dsq->continuity.stringBank.get(sbank), 0, 0, 0, 4, "13/face");
dsq->sound->playSfx("memory-found");
luaReturnNil();
}
luaFunc(setStory)
{
dsq->continuity.setStory(lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(confirm)
{
std::string s1 = getString(L, 1);
std::string s2 = getString(L, 2);
bool b = dsq->confirm(s1, s2);
luaReturnBool(b);
}
luaFunc(createWeb)
{
Web *web = new Web();
dsq->game->addRenderObject(web, LR_PARTICLES);
luaReturnPtr(web);
}
// spore has base entity
luaFunc(createSpore)
{
Vector pos(lua_tonumber(L, 1), lua_tonumber(L, 2));
if (Spore::isPositionClear(pos))
{
Spore *spore = new Spore(pos);
dsq->game->addRenderObject(spore, LR_ENTITIES);
luaReturnPtr(spore);
}
else
luaReturnPtr(NULL);
}
luaFunc(web_addPoint)
{
Web *w = getWeb(L);
float x = lua_tonumber(L, 2);
float y = lua_tonumber(L, 3);
int r = 0;
if (w)
{
r = w->addPoint(Vector(x,y));
}
luaReturnInt(r);
}
luaFunc(web_setPoint)
{
Web *w = getWeb(L);
int pt = lua_tointeger(L, 2);
float x = lua_tonumber(L, 3);
float y = lua_tonumber(L, 4);
if (w)
{
w->setPoint(pt, Vector(x, y));
}
luaReturnInt(pt);
}
luaFunc(web_getNumPoints)
{
Web *web = getWeb(L);
int num = 0;
if (web)
{
num = web->getNumPoints();
}
luaReturnInt(num);
}
luaFunc(getFirstShot)
{
luaReturnPtr(Shot::getFirstShot());
}
luaFunc(getNextShot)
{
luaReturnPtr(Shot::getNextShot());
}
luaFunc(shot_getName)
{
Shot *s = getShot(L);
luaReturnStr(s ? s->getName() : "");
}
luaFunc(shot_setOut)
{
Shot *shot = getShot(L);
float outness = lua_tonumber(L, 2);
if (shot && shot->firer)
{
Vector adjust = shot->velocity;
adjust.setLength2D(outness);
shot->position += adjust;
}
luaReturnNil();
}
luaFunc(shot_setAimVector)
{
Shot *shot = getShot(L);
float ax = lua_tonumber(L, 2);
float ay = lua_tonumber(L, 3);
if (shot)
{
shot->setAimVector(Vector(ax, ay));
}
luaReturnNil();
}
luaFunc(shot_getEffectTime)
{
if (lua_isstring(L, 1))
{
ShotData *data = Shot::getShotData(lua_tostring(L, 1));
luaReturnNum(data ? data->effectTime : 0.0f);
}
Shot *shot = getShot(L);
luaReturnNum((shot && shot->shotData) ? shot->shotData->effectTime : 0.0f);
}
luaFunc(shot_isIgnoreShield)
{
if (lua_isstring(L, 1))
{
ShotData *data = Shot::getShotData(lua_tostring(L, 1));
luaReturnBool(data ? data->ignoreShield : false);
}
Shot *shot = getShot(L);
luaReturnBool((shot && shot->shotData) ? shot->shotData->ignoreShield : false);
}
luaFunc(shot_getFirer)
{
Shot *shot = getShot(L);
luaReturnPtr(shot ? shot->firer : NULL);
}
luaFunc(shot_setFirer)
{
Shot *shot = getShot(L);
if(shot)
{
Entity *e = lua_isuserdata(L, 2) ? entity(L, 2) : NULL;
shot->firer = e;
}
luaReturnNil();
}
luaFunc(shot_setTarget)
{
Shot *shot = getShot(L);
if(shot)
{
Entity *e = lua_isuserdata(L, 2) ? entity(L, 2) : NULL;
shot->setTarget(e);
}
luaReturnNil();
}
luaFunc(shot_getTarget)
{
Shot *shot = getShot(L);
luaReturnPtr(shot ? shot->target : NULL);
}
luaFunc(shot_setExtraDamage)
{
Shot *shot = getShot(L);
if(shot)
shot->extraDamage = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(shot_getExtraDamage)
{
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->extraDamage : 0.0f);
}
luaFunc(shot_getDamage)
{
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->getDamage() : 0.0f);
}
luaFunc(shot_getDamageType)
{
if (lua_isstring(L, 1))
{
ShotData *data = Shot::getShotData(lua_tostring(L, 1));
luaReturnInt(data ? data->damageType : 0);
}
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->getDamageType() : DT_NONE);
}
luaFunc(shot_getMaxSpeed)
{
if (lua_isstring(L, 1))
{
ShotData *data = Shot::getShotData(lua_tostring(L, 1));
luaReturnNum(data ? data->maxSpeed : 0.0f);
}
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->maxSpeed : 0.0f);
}
luaFunc(shot_setMaxSpeed)
{
Shot *shot = getShot(L);
if (shot)
shot->maxSpeed = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(shot_getHomingness)
{
if (lua_isstring(L, 1))
{
ShotData *data = Shot::getShotData(lua_tostring(L, 1));
luaReturnNum(data ? data->homing : 0.0f);
}
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->homingness : 0.0f);
}
luaFunc(shot_setHomingness)
{
Shot *shot = getShot(L);
if (shot)
shot->homingness = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(shot_getLifeTime)
{
if (lua_isstring(L, 1))
{
ShotData *data = Shot::getShotData(lua_tostring(L, 1));
luaReturnNum(data ? data->lifeTime : 0.0f);
}
Shot *shot = getShot(L);
luaReturnNum(shot ? shot->lifeTime : 0.0f);
}
luaFunc(shot_setLifeTime)
{
Shot *shot = getShot(L);
if (shot)
shot->lifeTime = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(shot_setDamageType)
{
Shot *shot = getShot(L);
if (shot)
shot->damageType = (DamageType)lua_tointeger(L, 2);
luaReturnNil();
}
luaFunc(shot_setCheckDamageTarget)
{
Shot *shot = getShot(L);
if (shot)
shot->checkDamageTarget = getBool(L, 2);
luaReturnNil();
}
luaFunc(shot_isCheckDamageTarget)
{
if (lua_isstring(L, 1))
{
ShotData *data = Shot::getShotData(lua_tostring(L, 1));
luaReturnBool(data ? data->checkDamageTarget : false);
}
Shot *shot = getShot(L);
luaReturnBool(shot ? shot->checkDamageTarget : false);
}
luaFunc(shot_setTrailPrt)
{
Shot *shot = getShot(L);
if (shot)
shot->setParticleEffect(getString(L, 2));
luaReturnNil();
}
luaFunc(shot_setTargetPoint)
{
Shot *shot = getShot(L);
if (shot)
shot->setTargetPoint(lua_tointeger(L, 2));
luaReturnNil();
}
luaFunc(shot_getTargetPoint)
{
Shot *shot = getShot(L);
luaReturnInt(shot ? shot->targetPt : 0);
}
luaFunc(shot_canHitEntity)
{
Shot *shot = getShot(L);
Entity *e = entity(L, 2);
bool hit = false;
if(shot && e && shot->isActive() && dsq->game->isEntityCollideWithShot(e, shot))
{
DamageData d;
d.attacker = shot->firer;
d.damage = shot->getDamage();
d.damageType = shot->getDamageType();
d.shot = shot;
hit = e->canShotHit(d);
}
luaReturnBool(hit);
}
typedef std::pair<Shot*, float> ShotDistancePair;
static std::vector<ShotDistancePair> filteredShots(20);
static int filteredShotIdx = 0;
static bool _shotDistanceCmp(const ShotDistancePair& a, const ShotDistancePair& b)
{
return a.second < b.second;
}
static bool _shotDistanceEq(const ShotDistancePair& a, const ShotDistancePair& b)
{
return a.first == b.first;
}
static size_t _shotFilter(lua_State *L)
{
const Vector p(lua_tonumber(L, 1), lua_tonumber(L, 2));
const float radius = lua_tonumber(L, 3);
const DamageType dt = lua_isnumber(L, 5) ? (DamageType)lua_tointeger(L, 5) : DT_NONE;
const float sqrRadius = radius * radius;
float distsq;
const bool skipRadiusCheck = radius <= 0;
size_t added = 0;
for(Shot::Shots::iterator it = Shot::shots.begin(); it != Shot::shots.end(); ++it)
{
Shot *s = *it;
if (s->isActive() && s->life >= 1.0f)
{
if (dt == DT_NONE || s->getDamageType() == dt)
{
if (skipRadiusCheck || (distsq = (s->position - p).getSquaredLength2D()) <= sqrRadius)
{
filteredShots.push_back(std::make_pair(s, distsq));
++added;
}
}
}
}
if(added)
{
std::sort(filteredShots.begin(), filteredShots.end(), _shotDistanceCmp);
std::vector<ShotDistancePair>::iterator newend = std::unique(filteredShots.begin(), filteredShots.end(), _shotDistanceEq);
filteredShots.resize(std::distance(filteredShots.begin(), newend));
}
// Add terminator if there is none
if(filteredShots.size() && filteredShots.back().first)
filteredShots.push_back(std::make_pair((Shot*)NULL, 0.0f)); // terminator
filteredShotIdx = 0; // Reset getNextFilteredShot() iteration index
return added;
}
luaFunc(filterNearestShots)
{
filteredShots.clear();
luaReturnInt(_shotFilter(L));
}
luaFunc(filterNearestShotsAdd)
{
// Remove terminator if there is one
if(filteredShots.size() && !filteredShots.back().first)
filteredShots.pop_back();
luaReturnInt(_shotFilter(L));
}
luaFunc(getNextFilteredShot)
{
ShotDistancePair sp = filteredShots[filteredShotIdx];
if (sp.first)
++filteredShotIdx;
luaPushPointer(L, sp.first);
lua_pushnumber(L, sp.second);
return 2;
}
luaFunc(entity_setVel)
{
Entity *e = entity(L);
if (e)
e->vel = Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(entity_setVelLen)
{
Entity *e = entity(L);
if (e)
e->vel.setLength2D(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(entity_getVelLen)
{
Entity *e = entity(L);
luaReturnNum(e ? e->vel.getLength2D() : 0.0f);
}
luaFunc(entity_getVel)
{
Vector v;
Entity *e = entity(L);
if (e)
v = e->vel;
luaReturnVec2(v.x, v.y);
}
luaFunc(entity_velx)
{
Entity *e = entity(L);
luaReturnNum(e ? e->vel.x : 0.0f);
}
luaFunc(entity_vely)
{
Entity *e = entity(L);
luaReturnNum(e ? e->vel.y : 0.0f);
}
luaFunc(entity_addVel)
{
Entity *e = entity(L);
if (e)
e->vel += Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(entity_addRandomVel)
{
Entity *e = entity(L);
float len = lua_tonumber(L, 2);
Vector add;
if (e && len)
{
int angle = int(rand()%360);
float a = MathFunctions::toRadians(angle);
add.x = sinf(a);
add.y = cosf(a);
add.setLength2D(len);
e->vel += add;
}
luaReturnVec2(add.x, add.y);
}
luaFunc(entity_isVelIn)
{
Entity *e = entity(L);
luaReturnBool(e ? e->vel.isLength2DIn(lua_tonumber(L, 2)) : false);
}
luaFunc(entity_clearVel)
{
Entity *e = entity(L);
if (e)
e->vel = Vector(0,0,0);
luaReturnNil();
}
// end extra Entity::vel functions
luaFunc(entity_getPushVec)
{
Entity *e = entity(L);
Vector v;
if (e)
v = e->getPushVec();
luaReturnVec2(v.x, v.y);
}
luaFunc(entity_addIgnoreShotDamageType)
{
Entity *e = entity(L);
if (e)
{
e->addIgnoreShotDamageType((DamageType)lua_tointeger(L, 2));
}
luaReturnNil();
}
luaFunc(entity_warpLastPosition)
{
Entity *e = entity(L);
if (e)
{
e->warpLastPosition();
}
luaReturnNil();
}
luaFunc(entity_velTowards)
{
Entity *e = entity(L);
float x = lua_tonumber(L, 2);
float y = lua_tonumber(L, 3);
float velLen = lua_tonumber(L, 4);
float range = lua_tonumber(L, 5);
if (e)
{
Vector pos(x,y);
if (range==0 || ((pos - e->position).getLength2D() < range))
{
Vector add = pos - e->position;
add.setLength2D(velLen);
e->vel2 += add;
}
}
luaReturnNil();
}
luaFunc(entity_getBoneLockEntity)
{
Entity *e = entity(L);
Entity *ent = NULL;
if (e)
{
BoneLock *b = e->getBoneLock();
ent = b->entity;
}
luaReturnPtr(ent);
}
luaFunc(entity_getBoneLockData)
{
Entity *e = entity(L);
if (!e)
luaReturnNil();
BoneLock b = *e->getBoneLock(); // always safe to deref
lua_pushboolean(L, b.on);
luaPushPointer(L, b.bone);
lua_pushnumber(L, b.origRot);
lua_pushnumber(L, b.wallNormal.x);
lua_pushnumber(L, b.wallNormal.y);
lua_pushnumber(L, b.localOffset.x);
lua_pushnumber(L, b.localOffset.y);
return 7;
}
luaFunc(entity_ensureLimit)
{
Entity *e = entity(L);
dsq->game->ensureLimit(e, lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(entity_setRidingPosition)
{
Entity *e = entity(L);
if (e)
e->setRidingPosition(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)));
luaReturnNil();
}
luaFunc(entity_setRidingData)
{
Entity *e = entity(L);
if (e)
e->setRidingData(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), lua_tonumber(L, 4), getBool(L, 5));
luaReturnNil();
}
luaFunc(entity_getRidingPosition)
{
Entity *e = entity(L);
Vector v;
if (e)
v = e->getRidingPosition();
luaReturnVec2(v.x, v.y);
}
luaFunc(entity_getRidingRotation)
{
Entity *e = entity(L);
luaReturnNum(e ? e->getRidingRotation() : 0.0f);
}
luaFunc(entity_getRidingFlip)
{
Entity *e = entity(L);
luaReturnBool(e && e->getRidingFlip());
}
luaFunc(entity_setBoneLock)
{
Entity *e = entity(L);
bool ret = false;
if (e)
{
BoneLock bl;
if (lua_isuserdata(L, 2))
{
Entity *e2 = entity(L, 2);
Bone *b = 0;
if (lua_isuserdata(L, 3))
b = bone(L, 3);
bl.entity = e2;
bl.bone = b;
bl.on = true;
bl.collisionMaskIndex = dsq->game->lastCollideMaskIndex;
}
ret = e->setBoneLock(bl);
}
luaReturnBool(ret);
}
luaFunc(entity_setIngredient)
{
Entity *e = entity(L);
if (e)
{
e->setIngredientData(getString(L,2));
}
luaReturnNil();
}
luaFunc(entity_setSegsMaxDist)
{
ScriptedEntity *se = scriptedEntity(L);
if (se)
se->setMaxDist(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(entity_setBounceType)
{
Entity *e = entity(L);
int v = lua_tointeger(L, 2);
if (e)
{
e->setBounceType((BounceType)v);
}
luaReturnNum(v);
}
luaFunc(user_set_demo_intro)
{
#ifndef AQUARIA_DEMO
dsq->user.demo.intro = lua_tointeger(L, 1);
#endif
luaReturnNil();
}
luaFunc(user_save)
{
dsq->user.save();
luaReturnNil();
}
luaFunc(entity_setAutoSkeletalUpdate)
{
ScriptedEntity *e = scriptedEntity(L);
bool v = getBool(L, 2);
if (e)
e->setAutoSkeletalUpdate(v);
luaReturnBool(v);
}
luaFunc(entity_getBounceType)
{
Entity *e = entity(L);
BounceType bt=BOUNCE_SIMPLE;
if (e)
{
bt = (BounceType)e->getBounceType();
}
luaReturnInt((int)bt);
}
luaFunc(entity_setDieTimer)
{
Entity *e = entity(L);
if (e)
{
e->setDieTimer(lua_tonumber(L, 2));
}
luaReturnNil();
}
luaFunc(entity_setLookAtPoint)
{
Entity *e = entity(L);
if (e)
{
e->lookAtPoint = Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
}
luaReturnNil();
}
luaFunc(entity_getLookAtPoint)
{
Entity *e = entity(L);
Vector pos;
if (e)
{
pos = e->getLookAtPoint();
}
luaReturnVec2(pos.x, pos.y);
}
luaFunc(entity_setRiding)
{
Entity *e = entity(L);
Entity *e2 = 0;
if (lua_touserdata(L, 2) != NULL)
e2 = entity(L, 2);
if (e)
{
e->setRiding(e2);
}
luaReturnNil();
}
luaFunc(entity_getHealthPerc)
{
Entity *e = entity(L);
float p = 0;
if (e)
{
p = e->getHealthPerc();
}
luaReturnNum(p);
}
luaFunc(entity_getRiding)
{
Entity *e = entity(L);
Entity *ret = 0;
if (e)
ret = e->getRiding();
luaReturnPtr(ret);
}
luaFunc(entity_setTargetPriority)
{
Entity *e = entity(L);
if (e)
{
e->targetPriority = lua_tonumber(L, 2);
}
luaReturnNil();
}
luaFunc(entity_getTargetPriority)
{
Entity *e = entity(L);
luaReturnInt(e ? e->targetPriority : 0);
}
luaFunc(isQuitFlag)
{
luaReturnBool(dsq->isQuitFlag());
}
luaFunc(isDeveloperKeys)
{
luaReturnBool(dsq->isDeveloperKeys());
}
luaFunc(isDemo)
{
#ifdef AQUARIA_DEMO
luaReturnBool(true);
#else
luaReturnBool(false);
#endif
}
luaFunc(isWithin)
{
Vector v1 = getVector(L, 1);
Vector v2 = getVector(L, 3);
float dist = lua_tonumber(L, 5);
Vector d = v2-v1;
bool v = false;
if (d.isLength2DIn(dist))
{
v = true;
}
luaReturnBool(v);
}
luaFunc(toggleDamageSprite)
{
dsq->game->toggleDamageSprite(getBool(L));
luaReturnNil();
}
luaFunc(toggleCursor)
{
dsq->toggleCursor(getBool(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(toggleBlackBars)
{
dsq->toggleBlackBars(getBool(L, 1));
luaReturnNil();
}
luaFunc(setBlackBarsColor)
{
Vector c(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3));
dsq->setBlackBarsColor(c);
luaReturnNil();
}
luaFunc(toggleLiCombat)
{
dsq->continuity.toggleLiCombat(getBool(L));
luaReturnNil();
}
luaFunc(getNoteName)
{
luaReturnStr(dsq->game->getNoteName(lua_tonumber(L, 1), getString(L, 2)).c_str());
}
luaFunc(getWorldType)
{
luaReturnNum((int)dsq->continuity.getWorldType());
}
luaFunc(setWorldType)
{
WorldType wt = (WorldType)lua_tointeger(L, 1);
bool trans = getBool(L, 2);
dsq->continuity.applyWorldEffects(wt, trans, 1); // last arg is not used
luaReturnNil();
}
luaFunc(isWorldPaused)
{
luaReturnBool(dsq->game->isWorldPaused());
}
luaFunc(setWorldPaused)
{
dsq->game->setWorldPaused(getBool(L, 1));
luaReturnNil();
}
luaFunc(getNearestNodeByType)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
int type = lua_tointeger(L, 3);
luaReturnPtr(dsq->game->getNearestPath(Vector(x,y), (PathType)type));
}
luaFunc(fadeOutMusic)
{
dsq->sound->fadeMusic(SFT_OUT, lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(getNode)
{
luaReturnPtr(pathFromName(L));
}
luaFunc(getNodeToActivate)
{
luaReturnPtr(dsq->game->avatar->pathToActivate);
}
luaFunc(setNodeToActivate)
{
dsq->game->avatar->pathToActivate = path(L, 1);
luaReturnNil();
}
luaFunc(getEntityToActivate)
{
luaReturnPtr(dsq->game->avatar->entityToActivate);
}
luaFunc(setEntityToActivate)
{
dsq->game->avatar->entityToActivate = entity(L, 1);
luaReturnNil();
}
luaFunc(hasThingToActivate)
{
luaReturnBool(dsq->game->avatar->hasThingToActivate());
}
luaFunc(setActivation)
{
dsq->game->activation = getBool(L, 1);
luaReturnNil();
}
luaFunc(debugLog)
{
const char *s = lua_tostring(L, 1);
if(s)
debugLog(s);
luaReturnStr(s);
}
luaFunc(errorLog)
{
const char *s = lua_tostring(L, 1);
if(s)
errorLog(s);
luaReturnStr(s);
}
luaFunc(reconstructGrid)
{
dsq->game->reconstructGrid(true);
luaReturnNil();
}
luaFunc(reconstructEntityGrid)
{
dsq->game->reconstructEntityGrid();
luaReturnNil();
}
luaFunc(dilateGrid)
{
unsigned int radius = lua_tointeger(L, 1);
ObsType test = (ObsType)lua_tointeger(L, 2);
ObsType set = (ObsType)lua_tointeger(L, 3);
ObsType allowOverwrite = (ObsType)lua_tointeger(L, 4);
dsq->game->dilateGrid(radius, test, set, allowOverwrite);
luaReturnNil();
}
luaFunc(entity_setCanLeaveWater)
{
Entity *e = entity(L);
bool v = getBool(L, 2);
if (e)
{
e->setCanLeaveWater(v);
}
luaReturnNil();
}
luaFunc(entity_setSegmentTexture)
{
ScriptedEntity *e = scriptedEntity(L);
if (e)
{
RenderObject *ro = e->getSegment(lua_tonumber(L, 2));
if (ro)
{
ro->setTexture(getString(L, 3));
}
}
luaReturnNil();
}
luaFunc(entity_findNearestEntityOfType)
{
Entity *e = entity(L);
Entity *nearest = 0;
if (e)
{
EntityType et = (EntityType)lua_tointeger(L, 2);
int maxRange = lua_tointeger(L, 3);
float smallestDist = HUGE_VALF;
Entity *closest = 0;
FOR_ENTITIES(i)
{
Entity *ee = *i;
if (ee != e)
{
float dist = (ee->position - e->position).getSquaredLength2D();
if (ee->health > 0 && !ee->isEntityDead() && ee->getEntityType() == et && dist < smallestDist)
{
smallestDist = dist;
closest = ee;
}
}
}
if (maxRange == 0 || smallestDist <= sqr(maxRange))
{
nearest = closest;
}
}
luaReturnPtr(nearest);
}
luaFunc(createShot)
{
Entity *e = entity(L,2);
Entity *t = 0;
if (lua_touserdata(L, 3) != NULL)
t = entity(L,3);
Shot *s = 0;
Vector pos, aim;
pos.x = lua_tonumber(L, 4);
pos.y = lua_tonumber(L, 5);
aim.x = lua_tonumber(L, 6);
aim.y = lua_tonumber(L, 7);
s = dsq->game->fireShot(getString(L, 1), e, t, pos, aim);
luaReturnPtr(s);
}
luaFunc(isSkippingCutscene)
{
luaReturnBool(dsq->isSkippingCutscene());
}
// deprecated, use entity_playSfx
luaFunc(entity_sound)
{
Entity *e = entity(L);
if (e && !dsq->isSkippingCutscene())
{
float freq = lua_tonumber(L, 3);
// HACK: most old scripts still use a freq value of ~1000 as normal pitch.
// Pitch values this high produce a barely audible click only,
// so a cheap hack like this fixes it without changing older scripts. -- FG
if (freq >= 100)
freq *= 0.001f;
e->sound(getString(L, 2), freq, lua_tonumber(L, 4));
}
luaReturnNil();
}
luaFunc(entity_playSfx)
{
Entity *e = entity(L);
void *h = NULL;
if (e && !dsq->isSkippingCutscene())
{
PlaySfx sfx;
sfx.name = getString(L, 2);
sfx.freq = lua_tonumber(L, 3);
sfx.vol = lua_tonumber(L, 4);
if(sfx.vol <= 0)
sfx.vol = 1;
sfx.loops = lua_tonumber(L, 5);
float fadeOut = lua_tonumber(L, 6);
sfx.maxdist = lua_tonumber(L, 7);
sfx.relative = false;
sfx.positional = true;
Vector pos = e->position + e->offset;
sfx.x = pos.x;
sfx.y = pos.y;
h = core->sound->playSfx(sfx);
if (fadeOut != 0)
{
sound->fadeSfx(h, SFT_OUT, fadeOut);
}
e->linkSound(h);
e->updateSoundPosition();
}
luaReturnPtr(h);
}
luaFunc(entity_setStopSoundsOnDeath)
{
Entity *e = entity(L);
if (e)
e->setStopSoundsOnDeath(getBool(L, 2));
luaReturnNil();
}
luaFunc(entity_setSpiritFreeze)
{
Entity *e = entity(L);
if (e)
{
e->setSpiritFreeze(getBool(L,2));
}
luaReturnNil();
}
luaFunc(entity_setPauseFreeze)
{
Entity *e = entity(L);
if (e)
{
e->setPauseFreeze(getBool(L,2));
}
luaReturnNil();
}
luaFunc(node_setSpiritFreeze)
{
Path *e = path(L);
if (e)
e->spiritFreeze = getBool(L,2);
luaReturnNil();
}
luaFunc(node_setPauseFreeze)
{
Path *e = path(L);
if (e)
e->pauseFreeze = getBool(L,2);
luaReturnNil();
}
luaFunc(entity_setFillGrid)
{
Entity *e = entity(L);
bool b = getBool(L,2);
if (e)
{
e->fillGridFromQuad = b;
}
luaReturnNil();
}
luaFunc(entity_isFillGrid)
{
Entity *e = entity(L);
luaReturnBool(e ? e->fillGridFromQuad : false);
}
luaFunc(entity_getAimVector)
{
Entity *e = entity(L);
Vector aim;
float adjust = lua_tonumber(L, 2);
float len = lua_tonumber(L, 3);
bool flip = getBool(L, 4);
if (e)
{
float a = e->rotation.z;
if (!flip)
a += adjust;
else
{
if (e->isfh())
{
a -= adjust;
}
else
{
a += adjust;
}
}
a = MathFunctions::toRadians(a);
aim = Vector(sinf(a)*len, cosf(a)*len);
}
luaReturnVec2(aim.x, aim.y);
}
luaFunc(entity_getVectorToEntity)
{
typecheckOnly(entity(L));
typecheckOnly(entity(L, 2));
return forwardCall(obj_getVectorToObj);
}
luaFunc(entity_setDropChance)
{
Entity *e = entity(L);
if (e)
{
e->dropChance = lua_tonumber(L, 2);
float amount = lua_tonumber(L, 3);
ScriptedEntity *se = dynamic_cast<ScriptedEntity*>(e);
if (se && amount)
{
se->manaBallAmount = amount;
}
}
luaReturnNil();
}
luaFunc(entity_warpToNode)
{
Entity *e = entity(L);
Path *p = path(L, 2);
if (e && p)
{
e->position.stopPath();
e->position = p->nodes[0].position;
e->rotateToVec(Vector(0,-1), 0.1);
}
luaReturnNil();
}
luaFunc(entity_stopPull)
{
Entity *e = entity(L);
if (e)
e->stopPull();
luaReturnNil();
}
luaFunc(entity_moveToNode)
{
Entity *e = entity(L);
Path *p = path(L, 2);
float time = 0;
if (e && p)
{
float speed = dsq->continuity.getSpeedType(lua_tointeger(L, 3));
time = e->moveToPos(p->nodes[0].position, speed, lua_tointeger(L, 4), 0);
}
luaReturnNum(time);
}
luaFunc(entity_swimToNode)
{
Entity *e = entity(L);
Path *p = path(L, 2);
float time = 0;
if (e && p)
{
float speed = dsq->continuity.getSpeedType(lua_tointeger(L, 3));
time = e->moveToPos(p->nodes[0].position, speed, lua_tointeger(L, 4), 1);
}
luaReturnNum(time);
}
luaFunc(entity_swimToPosition)
{
Entity *e = entity(L);
float time = 0;
if (e)
{
float speed = dsq->continuity.getSpeedType(lua_tointeger(L, 4));
time = e->moveToPos(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), speed, lua_tointeger(L, 5), 1);
}
luaReturnNum(time);
}
luaFunc(entity_moveToNodeSpeed)
{
Entity *e = entity(L);
Path *p = path(L, 2);
float time = 0;
if (e && p)
time = e->moveToPos(p->nodes[0].position, lua_tonumber(L, 3), lua_tointeger(L, 4), 0);
luaReturnNum(time);
}
luaFunc(entity_swimToNodeSpeed)
{
Entity *e = entity(L);
Path *p = path(L, 2);
float time = 0;
if (e && p)
time = e->moveToPos(p->nodes[0].position, lua_tonumber(L, 3), lua_tointeger(L, 4), 1);
luaReturnNum(time);
}
luaFunc(entity_swimToPositionSpeed)
{
Entity *e = entity(L);
float time = 0;
if (e)
time = e->moveToPos(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), lua_tonumber(L, 4), lua_tointeger(L, 5), 1);
luaReturnNum(time);
}
luaFunc(avatar_setCanDie)
{
dsq->game->avatar->canDie = getBool(L, 1);
luaReturnNil();
}
// not naming this avatar_* because it rather belongs into the UI category...
luaFunc(setCanActivate)
{
dsq->game->avatar->setCanActivateStuff(getBool(L, 1));
luaReturnNil();
}
luaFunc(setSeeMapMode)
{
dsq->game->avatar->setSeeMapMode((SeeMapMode)lua_tointeger(L, 1));
luaReturnNil();
}
luaFunc(avatar_setCanBurst)
{
dsq->game->avatar->setCanBurst(getBool(L, 1));
luaReturnNil();
}
luaFunc(avatar_canBurst)
{
luaReturnBool(dsq->game->avatar->canBurst());
}
luaFunc(avatar_setCanLockToWall)
{
dsq->game->avatar->setCanLockToWall(getBool(L, 1));
luaReturnNil();
}
luaFunc(avatar_canLockToWall)
{
luaReturnBool(dsq->game->avatar->canLockToWall());
}
luaFunc(avatar_setCanSwimAgainstCurrents)
{
dsq->game->avatar->setCanSwimAgainstCurrents(getBool(L, 1));
luaReturnNil();
}
luaFunc(avatar_canSwimAgainstCurrents)
{
luaReturnBool(dsq->game->avatar->canSwimAgainstCurrents());
}
luaFunc(avatar_setCanCollideWithShots)
{
dsq->game->avatar->setCollideWithShots(getBool(L, 1));
luaReturnNil();
}
luaFunc(avatar_canCollideWithShots)
{
luaReturnBool(dsq->game->avatar->canCollideWithShots());
}
luaFunc(avatar_setCollisionAvoidanceData)
{
dsq->game->avatar->setCollisionAvoidanceData(lua_tointeger(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(avatar_toggleCape)
{
dsq->game->avatar->toggleCape(getBool(L,1));
luaReturnNil();
}
luaFunc(avatar_setBlockSinging)
{
bool b = getBool(L);
dsq->game->avatar->setBlockSinging(b);
luaReturnNil();
}
luaFunc(avatar_isBlockSinging)
{
luaReturnBool(dsq->game->avatar->isBlockSinging());
}
luaFunc(avatar_setBlockBackflip)
{
dsq->game->avatar->blockBackFlip = getBool(L);
luaReturnNil();
}
luaFunc(avatar_isBlockBackflip)
{
dsq->game->avatar->blockBackFlip = getBool(L);
luaReturnNil();
}
luaFunc(avatar_fallOffWall)
{
dsq->game->avatar->fallOffWall();
luaReturnNil();
}
luaFunc(avatar_isBursting)
{
luaReturnBool(dsq->game->avatar->bursting);
}
luaFunc(avatar_isLockable)
{
luaReturnBool(dsq->game->avatar->isLockable());
}
luaFunc(avatar_isRolling)
{
luaReturnBool(dsq->game->avatar->isRolling());
}
luaFunc(avatar_isSwimming)
{
luaReturnBool(dsq->game->avatar->isSwimming());
}
luaFunc(avatar_isOnWall)
{
bool v = dsq->game->avatar->state.lockedToWall;
luaReturnBool(v);
}
luaFunc(avatar_isShieldActive)
{
bool v = (dsq->game->avatar->activeAura == AURA_SHIELD);
luaReturnBool(v);
}
luaFunc(avatar_setShieldActive)
{
bool on = getBool(L, 1);
if (on)
dsq->game->avatar->activateAura(AURA_SHIELD);
else
dsq->game->avatar->stopAura();
luaReturnNil();
}
luaFunc(avatar_getStillTimer)
{
luaReturnNum(dsq->game->avatar->stillTimer.getValue());
}
luaFunc(avatar_getRollDirection)
{
int v = 0;
if (dsq->game->avatar->isRolling())
v = dsq->game->avatar->rollDir;
luaReturnNum(v);
}
luaFunc(avatar_getSpellCharge)
{
luaReturnNum(dsq->game->avatar->state.spellCharge);
}
luaFunc(avatar_setSpeedMult)
{
dsq->continuity.setSpeedMultiplier(lua_tonumber(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(avatar_setSpeedMult2)
{
dsq->continuity.speedMult2 = lua_tonumber(L, 1);
luaReturnNil();
}
luaFunc(avatar_getSpeedMult)
{
luaReturnNum(dsq->continuity.speedMult);
}
luaFunc(avatar_getSpeedMult2)
{
luaReturnNum(dsq->continuity.speedMult2);
}
luaFunc(jumpState)
{
dsq->enqueueJumpState(getString(L, 1), getBool(L, 2));
luaReturnNil();
}
luaFunc(goToTitle)
{
dsq->title();
luaReturnNil();
}
luaFunc(getEnqueuedState)
{
luaReturnStr(dsq->getEnqueuedJumpState().c_str());
}
luaFunc(learnSong)
{
dsq->continuity.learnSong(lua_tointeger(L, 1));
luaReturnNil();
}
luaFunc(unlearnSong)
{
dsq->continuity.unlearnSong(lua_tointeger(L, 1));
luaReturnNil();
}
luaFunc(showInGameMenu)
{
dsq->game->getInGameMenu()->show(getBool(L, 1), getBool(L, 2), (MenuPage)lua_tointeger(L, 3));
luaReturnNil();
}
luaFunc(hideInGameMenu)
{
bool skipEffect = getBool(L, 1);
bool cancel = getBool(L, 2);
dsq->game->getInGameMenu()->hide(!skipEffect, cancel);
luaReturnNil();
}
luaFunc(showImage)
{
dsq->game->showImage(getString(L));
luaReturnNil();
}
luaFunc(hideImage)
{
dsq->game->hideImage();
luaReturnNil();
}
luaFunc(hasSong)
{
bool b = dsq->continuity.hasSong(lua_tointeger(L, 1));
luaReturnBool(b);
}
luaFunc(loadSound)
{
void *handle = core->sound->loadLocalSound(getString(L, 1));
luaReturnPtr(handle);
}
luaFunc(loadMap)
{
std::string s = getString(L, 1);
std::string n = getString(L, 2);
if (!s.empty())
{
if (!n.empty())
{
if (dsq->game->avatar)
dsq->game->avatar->disableInput();
dsq->game->warpToSceneNode(s, n);
}
else
{
if (dsq->game->avatar)
dsq->game->avatar->disableInput();
dsq->game->transitionToScene(s);
}
}
luaReturnNil();
}
luaFunc(entity_followPath)
{
Entity *e = entity(L);
float time = 0;
if (e)
{
Path *p = path(L, 2);
int speedType = lua_tointeger(L, 3);
int dir = lua_tointeger(L, 4);
float speed = dsq->continuity.getSpeedType(speedType);
time = e->followPath(p, speed, dir);
}
luaReturnNum(time);
}
luaFunc(entity_followPathSpeed)
{
Entity *e = entity(L);
float time = 0;
if (e)
{
Path *p = path(L, 2);
float speed = lua_tonumber(L, 3);
int dir = lua_tointeger(L, 4);
time = e->followPath(p, speed, dir);
}
luaReturnNum(time);
}
luaFunc(spawnIngredient)
{
int times = lua_tointeger(L, 4);
if (times == 0) times = 1;
bool out = getBool(L, 5);
Entity *e = dsq->game->spawnIngredient(getString(L, 1), Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), times, out);
luaReturnPtr(e);
}
luaFunc(getNearestIngredient)
{
Ingredient *i = dsq->game->getNearestIngredient(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)), lua_tonumber(L, 3));
luaReturnPtr(i);
}
luaFunc(spawnAllIngredients)
{
dsq->spawnAllIngredients(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)));
luaReturnNil();
}
luaFunc(spawnParticleEffect)
{
float t = lua_tonumber(L, 4);
// having t and rot reversed compared to the DSQ function is intentional
float rot = lua_tonumber(L, 5);
int layer = lua_tointeger(L, 6);
if (!layer)
layer = LR_PARTICLES;
float follow = lua_tonumber(L, 7);
ParticleEffect *pe = dsq->spawnParticleEffect(getString(L, 1), Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)),
rot, t, layer, follow);
luaReturnPtr(pe);
}
luaFunc(setNumSuckPositions)
{
particleManager->setNumSuckPositions(lua_tointeger(L, 1));
luaReturnNil();
}
luaFunc(setSuckPosition)
{
particleManager->setSuckPosition(lua_tointeger(L, 1), Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)));
luaReturnNil();
}
luaFunc(getSuckPosition)
{
Vector *v = particleManager->getSuckPosition(lua_tointeger(L, 1));
if(v)
luaReturnVec2(v->x, v->y);
luaReturnVec2(0.0f, 0.0f);
}
luaFunc(bone_showFrame)
{
Bone *b = bone(L);
if (b)
b->showFrame(lua_tointeger(L, 2));
luaReturnNil();
}
luaFunc(bone_setSegmentOffset)
{
Bone *b = bone(L);
if (b)
b->segmentOffset = Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(bone_setSegmentProps)
{
Bone *b = bone(L);
if (b)
{
b->setSegmentProps(lua_tonumber(L, 2), lua_tonumber(L, 3), getBool(L, 4));
}
luaReturnNil();
}
luaFunc(bone_setSegmentChainHead)
{
Bone *b = bone(L);
if (b)
{
if (getBool(L, 2))
b->segmentChain = 1;
else
b->segmentChain = 0;
}
luaReturnNil();
}
luaFunc(bone_addSegment)
{
Bone *b = bone(L);
Bone *b2 = bone(L, 2);
if (b && b2)
b->addSegment(b2);
luaReturnNil();
}
luaFunc(bone_setAnimated)
{
Bone *b = bone(L);
if (b)
{
b->setAnimated(lua_tointeger(L, 2));
}
luaReturnNil();
}
luaFunc(bone_lookAtEntity)
{
Bone *b = bone(L);
Entity *e = entity(L, 2);
if (b && e)
{
Vector pos = e->position;
if (e->getEntityType() == ET_AVATAR)
{
pos = e->skeletalSprite.getBoneByIdx(1)->getWorldPosition();
}
b->lookAt(pos, lua_tonumber(L, 3), lua_tonumber(L, 4),lua_tonumber(L, 5), lua_tonumber(L, 6));
}
luaReturnNil();
}
luaFunc(bone_lookAtPosition)
{
Bone *b = bone(L);
if (b)
{
b->lookAt(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6), lua_tonumber(L, 7));
}
luaReturnNil();
}
luaFunc(entity_resetTimer)
{
ScriptedEntity *se = scriptedEntity(L);
if (se)
se->resetTimer(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(entity_stopFollowingPath)
{
Entity *e = entity(L);
if (e)
{
if (e->isFollowingPath())
{
e->stopFollowingPath();
}
}
luaReturnNil();
}
luaFunc(entity_slowToStopPath)
{
Entity *e = entity(L);
if (e)
{
if (e->isFollowingPath())
{
debugLog("calling slow to stop path");
e->slowToStopPath(lua_tonumber(L, 2));
}
else
{
debugLog("wasn't following path");
}
}
luaReturnNil();
}
luaFunc(entity_stopTimer)
{
ScriptedEntity *se = scriptedEntity(L);
if (se)
se->stopTimer();
luaReturnNil();
}
luaFunc(entity_createEntity)
{
Entity *e = entity(L);
Entity *ret = NULL;
if (e)
ret = dsq->game->createEntity(dsq->getEntityTypeIndexByName(getString(L, 2)), 0, e->position, 0, false, "", ET_ENEMY, true);
luaReturnPtr(ret);
}
luaFunc(entity_checkSplash)
{
Entity *e = entity(L);
bool ret = false;
float x = lua_tonumber(L, 2);
float y = lua_tonumber(L, 3);
if (e)
ret = e->checkSplash(Vector(x,y));
luaReturnBool(ret);
}
luaFunc(entity_isInCurrent)
{
Entity *e = entity(L);
luaReturnBool(e ? e->isInCurrent() : false);
}
luaFunc(entity_isUnderWater)
{
Entity *e = entity(L);
bool b = false;
if (e)
{
b = e->isUnderWater(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)));
}
luaReturnBool(b);
}
luaFunc(entity_isBeingPulled)
{
Entity *e = entity(L);
bool v= false;
if (e)
v = (dsq->game->avatar->pullTarget == e);
luaReturnBool(v);
}
luaFunc(avatar_setPullTarget)
{
Entity *e = 0;
if (lua_isuserdata(L, 1))
e = entity(L, 1);
if (dsq->game->avatar->pullTarget != 0)
dsq->game->avatar->pullTarget->stopPull();
dsq->game->avatar->pullTarget = e;
if (e)
e->startPull();
luaReturnNil();
}
luaFunc(entity_isDead)
{
Entity *e = entity(L);
bool v= false;
if (e)
{
v = e->isEntityDead();
}
luaReturnBool(v);
}
luaFunc(getLastCollidePosition)
{
luaReturnVec2(dsq->game->lastCollidePosition.x, dsq->game->lastCollidePosition.y);
}
luaFunc(getLastCollideTileType)
{
luaReturnInt(dsq->game->lastCollideTileType);
}
luaFunc(collideCircleWithGrid)
{
bool c = dsq->game->collideCircleWithGrid(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)), lua_tonumber(L, 3));
luaReturnBool(c);
}
luaFunc(entity_isNearGround)
{
Entity *e = entity(L);
bool value = false;
if (e)
{
int sampleArea = lua_tointeger(L, 2);
Vector v = dsq->game->getWallNormal(e->position, sampleArea);
if (!v.isZero())
{
if (v.y < 0 && fabsf(v.x) < 0.6f)
{
value = true;
}
}
}
luaReturnBool(value);
}
luaFunc(entity_isHit)
{
Entity *e = entity(L);
bool v = false;
if (e)
v = e->isHit();
luaReturnBool(v);
}
luaFunc(entity_waitForPath)
{
Entity *e = entity(L);
while (e && e->isFollowingPath())
{
core->run(FRAME_TIME);
}
luaReturnNil();
}
luaFunc(quitNestedMain)
{
core->quitNestedMain();
luaReturnNil();
}
luaFunc(isNestedMain)
{
luaReturnBool(core->isNested());
}
luaFunc(entity_watchForPath)
{
dsq->game->avatar->disableInput();
Entity *e = entity(L);
while (e && e->isFollowingPath())
{
core->run(FRAME_TIME);
}
dsq->game->avatar->enableInput();
luaReturnNil();
}
luaFunc(watchForVoice)
{
int quit = lua_tointeger(L, 1);
while (dsq->sound->isPlayingVoice())
{
dsq->watch(FRAME_TIME, quit);
if (quit && dsq->isQuitFlag())
{
dsq->sound->stopVoice();
break;
}
}
luaReturnNil();
}
luaFunc(entity_isSlowingToStopPath)
{
Entity *e = entity(L);
bool v = false;
if (e)
{
v = e->isSlowingToStopPath();
}
luaReturnBool(v);
}
luaFunc(entity_resumePath)
{
Entity *e = entity(L);
if (e)
{
e->position.resumePath();
}
luaReturnNil();
}
luaFunc(entity_isAnimating)
{
Entity *e = entity(L);
bool v= false;
if (e)
{
v = e->skeletalSprite.isAnimating(lua_tonumber(L, 2));
}
luaReturnBool(v);
}
luaFunc(entity_getAnimationName)
{
Entity *e = entity(L);
const char *ret = "";
int layer = lua_tointeger(L, 2);
if (e)
{
if (Animation *anim = e->skeletalSprite.getCurrentAnimation(layer))
{
ret = anim->name.c_str();
}
}
luaReturnStr(ret);
}
luaFunc(entity_getAnimationLength)
{
Entity *e = entity(L);
float ret=0;
if (e)
{
Animation *anim = 0;
if (lua_isstring(L, 2))
anim = e->skeletalSprite.getAnimation(lua_tostring(L, 2));
else
{
int layer = lua_tointeger(L, 2);
anim = e->skeletalSprite.getCurrentAnimation(layer);
}
if (anim)
ret = anim->getAnimationLength();
}
luaReturnNum(ret);
}
luaFunc(entity_hasAnimation)
{
Entity *e = entity(L);
Animation *anim = e->skeletalSprite.getAnimation(getString(L, 2));
luaReturnBool(anim != NULL);
}
luaFunc(entity_isFollowingPath)
{
Entity *e = entity(L);
if (e)
luaReturnBool(e->isFollowingPath());
else
luaReturnBool(false);
}
luaFunc(entity_toggleBone)
{
Entity *e = entity(L);
Bone *b = bone(L, 2);
if (e && b)
{
e->skeletalSprite.toggleBone(e->skeletalSprite.getBoneIdx(b), lua_tonumber(L, 3));
}
luaReturnNil();
}
luaFunc(entity_setEntityType)
{
Entity *e = entity(L);
if (e)
e->setEntityType(EntityType(lua_tointeger(L, 2)));
luaReturnNil();
}
luaFunc(entity_getEntityType)
{
Entity *e = entity(L);
if (e)
luaReturnInt(int(e->getEntityType()));
else
luaReturnInt(0);
}
luaFunc(cam_snap)
{
dsq->game->snapCam();
luaReturnNil();
}
luaFunc(cam_toNode)
{
Path *p = path(L);
if (p)
{
dsq->game->setCameraFollow(&p->nodes[0].position);
}
luaReturnNil();
}
luaFunc(cam_toEntity)
{
if (lua_touserdata(L, 1) == NULL)
{
Vector *pos = 0;
dsq->game->setCameraFollow(pos);
}
else
{
Entity *e = entity(L);
if (e)
{
dsq->game->setCameraFollowEntity(e);
}
}
luaReturnNil();
}
luaFunc(cam_setPosition)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
float time = lua_tonumber(L, 3);
int loopType = lua_tointeger(L, 4);
bool pingPong = getBool(L, 5);
bool ease = getBool(L, 6);
Vector p(x,y);
dsq->game->cameraInterp.stop();
dsq->game->cameraInterp.interpolateTo(p, time, loopType, pingPong, ease);
dsq->cameraPos = dsq->game->getCameraPositionFor(dsq->game->cameraInterp);
luaReturnNil();
}
luaFunc(entity_spawnParticlesFromCollisionMask)
{
Entity *e = entity(L);
if (e)
{
int intv = lua_tointeger(L, 3);
if (intv <= 0)
intv = 1;
e->spawnParticlesFromCollisionMask(getString(L, 2), intv);
}
luaReturnNil();
}
luaFunc(entity_initEmitter)
{
ScriptedEntity *se = scriptedEntity(L);
int e = lua_tointeger(L, 2);
std::string pfile = getString(L, 3);
if (se)
{
se->initEmitter(e, pfile);
}
luaReturnNil();
}
luaFunc(entity_startEmitter)
{
ScriptedEntity *se = scriptedEntity(L);
int e = lua_tointeger(L, 2);
if (se)
{
se->startEmitter(e);
}
luaReturnNil();
}
luaFunc(entity_stopEmitter)
{
ScriptedEntity *se = scriptedEntity(L);
int e = lua_tointeger(L, 2);
if (se)
{
se->stopEmitter(e);
}
luaReturnNil();
}
luaFunc(entity_getEmitter)
{
ScriptedEntity *se = scriptedEntity(L);
luaReturnPtr(se ? se->getEmitter(lua_tointeger(L, 2)) : NULL);
}
luaFunc(entity_getNumEmitters)
{
ScriptedEntity *se = scriptedEntity(L);
luaReturnInt(se ? se->getNumEmitters() : 0);
}
luaFunc(entity_initStrands)
{
ScriptedEntity *e = scriptedEntity(L);
if (e)
{
e->initStrands(lua_tonumber(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5), Vector(lua_tonumber(L, 6), lua_tonumber(L, 7), lua_tonumber(L, 8)));
}
luaReturnNil();
}
luaFunc(entity_initSkeletal)
{
Entity *e = entity(L);
if (e)
{
e->renderQuad = false;
e->setWidthHeight(128, 128);
e->skeletalSprite.loadSkeletal(getString(L, 2));
const char *s = lua_tostring(L, 3);
if (s && *s)
e->skeletalSprite.loadSkin(s);
}
luaReturnNil();
}
luaFunc(entity_loadSkin)
{
Entity *e = entity(L);
if (e && e->skeletalSprite.isLoaded())
{
const char *s = lua_tostring(L, 2);
if (s && *s)
e->skeletalSprite.loadSkin(s);
}
luaReturnNil();
}
luaFunc(entity_getSkeletalName)
{
Entity *e = entity(L);
const char *s = "";
if (e && e->skeletalSprite.isLoaded())
s = e->skeletalSprite.filenameLoaded.c_str();
luaReturnStr(s);
}
luaFunc(entity_hasSkeletal)
{
Entity *e = entity(L);
luaReturnBool(e && e->skeletalSprite.isLoaded());
}
luaFunc(entity_getNumAnimLayers)
{
Entity *e = entity(L);
luaReturnInt(e ? e->skeletalSprite.getNumAnimLayers() : 0);
}
luaFunc(entity_idle)
{
Entity *e = entity(L);
if (e)
{
e->idle();
}
luaReturnNil();
}
luaFunc(entity_stopAllAnimations)
{
Entity *e = entity(L);
if (e)
e->skeletalSprite.stopAllAnimations();
luaReturnNil();
}
luaFunc(entity_setAnimLayerTimeMult)
{
Entity *e = entity(L);
int layer = 0;
float t = 0;
if (e)
{
layer = lua_tointeger(L, 2);
t = lua_tonumber(L, 3);
AnimationLayer *l = e->skeletalSprite.getAnimationLayer(layer);
if (l)
{
interpolateVec1(L, l->timeMultiplier, 3);
}
}
luaReturnNum(t);
}
luaFunc(entity_getAnimLayerTimeMult)
{
Entity *e = entity(L);
float t = 0;
if (e)
{
AnimationLayer *l = e->skeletalSprite.getAnimationLayer(lua_tointeger(L, 2));
if (l)
{
t = l->timeMultiplier.x;
}
}
luaReturnNum(t);
}
luaFunc(entity_animate)
{
SkeletalSprite *skel = getSkeletalSprite(entity(L));
float ret = 0;
if (skel)
{
float transition = lua_tonumber(L, 5);
if (transition == -1)
transition = 0;
else if (transition == 0)
transition = 0.2;
ret = skel->transitionAnimate(getString(L, 2), transition, lua_tointeger(L, 3), lua_tointeger(L, 4));
}
luaReturnNum(ret);
}
luaFunc(entity_stopAnimation)
{
SkeletalSprite *skel = getSkeletalSprite(entity(L));
if (skel)
{
AnimationLayer *animlayer = skel->getAnimationLayer(lua_tointeger(L, 2));
if (animlayer)
animlayer->stopAnimation();
}
luaReturnNil();
}
luaFunc(entity_getAnimationLoop)
{
int loop = 0;
SkeletalSprite *skel = getSkeletalSprite(entity(L));
if (skel)
{
AnimationLayer *animlayer = skel->getAnimationLayer(lua_tointeger(L, 2));
if (animlayer)
loop = animlayer->loop ? animlayer->loop : animlayer->enqueuedAnimationLoop;
}
luaReturnInt(loop);
}
// entity, x, y, time, ease, relative
luaFunc(entity_move)
{
Entity *e = entity(L);
bool ease = lua_tointeger(L, 5);
Vector p(lua_tonumber(L, 2), lua_tonumber(L, 3));
if (getBool(L, 6))
p = e->position + p;
e->position.interpolateTo(p, lua_tonumber(L, 4), 0, 0, getBool(L, 5));
luaReturnNil();
}
luaFunc(spawnManaBall)
{
Vector p;
p.x = lua_tonumber(L, 1);
p.y = lua_tonumber(L, 2);
float amount = lua_tonumber(L, 3);
dsq->game->spawnManaBall(p, amount);
luaReturnNil();
}
luaFunc(spawnAroundEntity)
{
Entity *e = entity(L);
int num = lua_tointeger(L, 2);
float radius = lua_tonumber(L, 3);
std::string entType = getString(L, 4);
std::string name = getString(L, 5);
int idx = dsq->game->getIdxForEntityType(entType);
if (e)
{
Vector pos = e->position;
for (int i = 0; i < num; i++)
{
float angle = i*((2*PI)/float(num));
e = dsq->game->createEntity(idx, 0, pos + Vector(sinf(angle)*radius, cosf(angle)*radius), 0, false, name);
}
}
luaReturnNil();
}
luaFunc(createBeam)
{
int x = lua_tointeger(L, 1);
int y = lua_tointeger(L, 2);
float a = lua_tonumber(L, 3);
int l = lua_tointeger(L, 4);
Beam *b = new Beam(Vector(x,y), a);
if (l == 1)
dsq->game->addRenderObject(b, LR_PARTICLES);
else
dsq->game->addRenderObject(b, LR_ENTITIES_MINUS2);
luaReturnPtr(b);
}
luaFunc(beam_setDamage)
{
Beam *b = beam(L);
if (b)
{
b->setDamage(lua_tonumber(L, 2));
}
luaReturnNil();
}
luaFunc(beam_setDamageType)
{
Beam *b = beam(L);
if (b)
{
b->damageData.damageType = (DamageType)lua_tointeger(L, 2);
}
luaReturnNil();
}
luaFunc(beam_setBeamWidth)
{
Beam *b = beam(L);
if (b)
{
b->setBeamWidth(lua_tonumber(L, 2));
}
luaReturnNil();
}
luaFunc(beam_setAngle)
{
Beam *b = beam(L);
if (b)
{
b->angle = lua_tonumber(L, 2);
b->trace();
}
luaReturnNil();
}
luaFunc(beam_setFirer)
{
Beam *b = beam(L);
if (b)
b->setFirer(entity(L, 2));
luaReturnNil();
}
// Note the additional trace() call
luaFunc(beam_setPosition_override)
{
Beam *b = beam(L);
if (b)
{
forwardCall(obj_setPosition);
b->trace();
}
luaReturnNil();
}
luaFunc(beam_getEndPos)
{
Beam *b = beam(L);
Vector v;
if (b)
v = b->endPos;
luaReturnVec2(v.x, v.y);
}
luaFunc(getStringBank)
{
luaReturnStr(dsq->continuity.stringBank.get(lua_tointeger(L, 1)).c_str());
}
luaFunc(isPlat)
{
int plat = lua_tointeger(L, 1);
bool v = false;
#ifdef BBGE_BUILD_WINDOWS
v = (plat == 0);
#elif BBGE_BUILD_MACOSX
v = (plat == 1);
#elif BBGE_BUILD_UNIX
v = (plat == 2);
#endif
luaReturnBool(v);
}
luaFunc(createEntity)
{
std::string type = getString(L, 1);
std::string name;
if (lua_isstring(L, 2))
name = lua_tostring(L, 2);
int x = lua_tointeger(L, 3);
int y = lua_tointeger(L, 4);
Entity *e = 0;
e = dsq->game->createEntity(type, 0, Vector(x, y), 0, false, name, ET_ENEMY, true);
luaReturnPtr(e);
}
luaFunc(savePoint)
{
Path *p = path(L);
Vector position;
if (p)
{
position = p->nodes[0].position;
}
dsq->doSavePoint(position);
luaReturnNil();
}
luaFunc(saveMenu)
{
dsq->doSaveSlotMenu(SSM_SAVE);
luaReturnNil();
}
luaFunc(setSceneDisplayNameInSave)
{
dsq->game->sceneDisplayName = getString(L);
luaReturnNil();
}
luaFunc(pause)
{
dsq->game->togglePause(1);
luaReturnNil();
}
luaFunc(unpause)
{
dsq->game->togglePause(0);
luaReturnNil();
}
luaFunc(isPaused)
{
luaReturnBool(dsq->game->isPaused());
}
luaFunc(isInGameMenu)
{
luaReturnBool(dsq->game->isInGameMenu());
}
luaFunc(isInEditor)
{
luaReturnBool(dsq->game->isSceneEditorActive());
}
luaFunc(clearControlHint)
{
dsq->game->clearControlHint();
luaReturnNil();
}
luaFunc(setSceneColor)
{
interpolateVec3(L, dsq->game->sceneColor3, 1);
luaReturnNil();
}
luaFunc(getSceneColor)
{
const Vector& c = dsq->game->sceneColor3;
luaReturnVec3(c.x, c.y, c.z);
}
luaFunc(setSceneColor2)
{
interpolateVec3(L, dsq->game->sceneColor2, 1);
luaReturnNil();
}
luaFunc(getSceneColor2)
{
const Vector& c = dsq->game->sceneColor2;
luaReturnVec3(c.x, c.y, c.z);
}
luaFunc(setCameraLerpDelay)
{
dsq->game->cameraLerpDelay = lua_tonumber(L, 1);
luaReturnNil();
}
luaFunc(setControlHint)
{
std::string str = getString(L, 1);
bool left = getBool(L, 2);
bool right = getBool(L, 3);
bool middle = getBool(L, 4);
float t = lua_tonumber(L, 5);
std::string s;
if (lua_isstring(L, 6))
s = lua_tostring(L, 6);
int songType = lua_tointeger(L, 7);
float scale = lua_tonumber(L, 8);
if (scale == 0)
scale = 1;
dsq->game->setControlHint(str, left, right, middle, t, s, false, songType, scale);
luaReturnNil();
}
luaFunc(setCanChangeForm)
{
dsq->game->avatar->canChangeForm = getBool(L);
luaReturnNil();
}
luaFunc(setInvincibleOnNested)
{
dsq->game->invincibleOnNested = getBool(L);
luaReturnNil();
}
luaFunc(setCanWarp)
{
dsq->game->avatar->canWarp = getBool(L);
luaReturnNil();
}
luaFunc(entity_generateCollisionMask)
{
Entity *e = entity(L);
float num = lua_tonumber(L, 2);
if (e)
{
e->generateCollisionMask(num);
}
luaReturnNil();
}
luaFunc(entity_damage)
{
Entity *e = entity(L);
bool didDamage = false;
if (e)
{
DamageData d;
d.attacker = lua_isuserdata(L, 2) ? entity(L, 2) : NULL;
d.damage = lua_tonumber(L, 3);
d.damageType = (DamageType)lua_tointeger(L, 4);
d.effectTime = lua_tonumber(L, 5);
d.useTimer = !getBool(L, 6);
d.shot = lua_isuserdata(L, 7) ? getShot(L, 7) : NULL;
d.hitPos = Vector(lua_tonumber(L, 8), lua_tonumber(L, 9));
didDamage = e->damage(d);
}
luaReturnBool(didDamage);
}
// must be called in init
luaFunc(entity_setEntityLayer)
{
ScriptedEntity *e = scriptedEntity(L);
int l = lua_tointeger(L, 2);
if (e)
{
e->setEntityLayer(l);
}
luaReturnNil();
}
// Note that this overrides the generic obj_setRenderPass function for entities.
// (It's registered as "entity_setRenderPass" to Lua)
luaFunc(entity_setRenderPass_override)
{
Entity *e = entity(L);
int pass = lua_tointeger(L, 2);
if (e)
e->setOverrideRenderPass(pass);
luaReturnNil();
}
// intended to be used for setting max health and refilling it all
luaFunc(entity_setHealth)
{
Entity *e = entity(L, 1);
if (e)
e->health = e->maxHealth = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(entity_setCurrentHealth)
{
Entity *e = entity(L, 1);
if (e)
e->health = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(entity_setMaxHealth)
{
Entity *e = entity(L, 1);
if (e)
e->maxHealth = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(entity_changeHealth)
{
Entity *e = entity(L, 1);
if (e)
e->health += lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(entity_heal)
{
Entity *e = entity(L);
if (e)
e->heal(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(entity_revive)
{
Entity *e = entity(L);
if (e)
e->revive(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(screenFadeCapture)
{
dsq->screenTransition->capture();
luaReturnNil();
}
luaFunc(screenFadeTransition)
{
dsq->screenTransition->transition(lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(screenFadeGo)
{
dsq->screenTransition->go(lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(isEscapeKey)
{
bool isDown = dsq->game->isActing(ACTION_ESC);
luaReturnBool(isDown);
}
luaFunc(isLeftMouse)
{
bool isDown = core->mouse.buttons.left || (dsq->game->avatar && dsq->game->avatar->pollAction(ACTION_PRIMARY));
luaReturnBool(isDown);
}
luaFunc(isRightMouse)
{
bool isDown = core->mouse.buttons.right || (dsq->game->avatar && dsq->game->avatar->pollAction(ACTION_SECONDARY));
luaReturnBool(isDown);
}
luaFunc(setTimerTextAlpha)
{
dsq->game->setTimerTextAlpha(lua_tonumber(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(setTimerText)
{
dsq->game->setTimerText(lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(getWallNormal)
{
float x,y;
x = lua_tonumber(L, 1);
y = lua_tonumber(L, 2);
int range = lua_tointeger(L, 3);
int obs = lua_tointeger(L, 4);
if (range == 0)
range = 5;
if (!obs)
obs = OT_BLOCKING;
Vector n = dsq->game->getWallNormal(Vector(x, y), range, NULL, obs);
luaReturnVec2(n.x, n.y);
}
luaFunc(setFlag)
{
dsq->continuity.setFlag(lua_tointeger(L, 1), lua_tointeger(L, 2));
luaReturnNil();
}
luaFunc(getFlag)
{
int v = 0;
v = dsq->continuity.getFlag(lua_tointeger(L, 1));
luaReturnNum(v);
}
luaFunc(getStringFlag)
{
luaReturnStr(dsq->continuity.getStringFlag(getString(L, 1)).c_str());
}
luaFunc(node_setEmitter)
{
Path *p = path(L);
if(p)
p->setEmitter(getString(L, 2));
luaReturnPtr(p->emitter);
}
luaFunc(node_getEmitter)
{
Path *p = path(L);
luaReturnPtr(p ? p->emitter : NULL);
}
luaFunc(node_setActive)
{
Path *p = path(L);
bool v = getBool(L, 2);
if (p)
{
p->active = v;
if(p->emitter)
{
if(v)
p->emitter->start();
else
p->emitter->stop();
}
}
luaReturnNil();
}
luaFunc(node_isActive)
{
Path *p = path(L);
luaReturnBool(p ? p->active : false);
}
luaFunc(node_setCursorActivation)
{
Path *p = path(L);
bool v = getBool(L, 2);
if (p)
{
p->cursorActivation = v;
}
luaReturnNil();
}
luaFunc(node_setActivationRange)
{
Path *p = path(L);
if(p)
p->activationRange = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(node_setCatchActions)
{
Path *p = path(L);
bool v = getBool(L, 2);
if (p)
{
p->catchActions = v;
}
luaReturnNil();
}
luaFunc(node_isEntityInRange)
{
Path *p = path(L);
Entity *e = entity(L,2);
float range = lua_tonumber(L, 3);
bool v = false;
if (p && e)
{
if ((p->nodes[0].position - e->position).isLength2DIn(range))
{
v = true;
}
}
luaReturnBool(v);
}
luaFunc(node_isEntityPast)
{
Path *p = path(L);
bool past = false;
if (p && !p->nodes.empty())
{
PathNode *n = &p->nodes[0];
Entity *e = entity(L, 2);
if (e)
{
bool checkY = getBool(L, 3);
int dir = lua_tointeger(L, 4);
float range = lua_tonumber(L, 5);
if (!checkY)
{
if (e->position.x > n->position.x-range && e->position.x < n->position.x+range)
{
if (!dir)
{
if (e->position.y < n->position.y)
past = true;
}
else
{
if (e->position.y > n->position.y)
past = true;
}
}
}
else
{
if (e->position.y > n->position.y-range && e->position.y < n->position.y+range)
{
if (!dir)
{
if (e->position.x < n->position.x)
past = true;
}
else
{
if (e->position.x > n->position.x)
past = true;
}
}
}
}
}
luaReturnBool(past);
}
luaFunc(node_x)
{
Path *p = path(L);
float v = 0;
if (p)
{
v = p->nodes[0].position.x;
}
luaReturnNum(v);
}
luaFunc(node_y)
{
Path *p = path(L);
float v = 0;
if (p)
{
v = p->nodes[0].position.y;
}
luaReturnNum(v);
}
luaFunc(entity_isName)
{
Entity *e = entity(L);
std::string s = getString(L, 2);
bool ret = false;
if (e)
{
ret = (nocasecmp(s,e->name)==0);
}
luaReturnBool(ret);
}
luaFunc(entity_getName)
{
Entity *e = entity(L);
const char *s = "";
if (e)
{
s = e->name.c_str();
}
luaReturnStr(s);
}
luaFunc(node_getContent)
{
Path *p = path(L);
const char *s = "";
if (p)
{
s = p->content.c_str();
}
luaReturnStr(s);
}
luaFunc(node_getAmount)
{
Path *p = path(L);
float a = 0;
if (p)
{
a = p->amount;
}
luaReturnNum(a);
}
luaFunc(node_getSize)
{
Path *p = path(L);
int w=0,h=0;
if (p)
{
w = p->rect.getWidth();
h = p->rect.getHeight();
}
luaReturnVec2(w, h);
}
luaFunc(node_getName)
{
Path *p = path(L);
const char *s = "";
if (p)
{
s = p->name.c_str();
}
luaReturnStr(s);
}
luaFunc(node_getLabel)
{
Path *p = path(L);
const char *s = "";
if (p)
{
s = p->label.c_str();
}
luaReturnStr(s);
}
luaFunc(node_getPathPosition)
{
Path *p = path(L);
int idx = lua_tointeger(L, 2);
float x=0,y=0;
if (p)
{
PathNode *node = p->getPathNode(idx);
if (node)
{
x = node->position.x;
y = node->position.y;
}
}
luaReturnVec2(x, y);
}
luaFunc(node_getPosition)
{
Path *p = path(L);
float x=0,y=0;
if (p)
{
PathNode *node = &p->nodes[0];
x = node->position.x;
y = node->position.y;
}
luaReturnVec2(x, y);
}
luaFunc(node_setPosition)
{
Path *p = path(L);
float x=0,y=0;
if (p)
{
x = lua_tonumber(L, 2);
y = lua_tonumber(L, 3);
PathNode *node = &p->nodes[0];
node->position = Vector(x, y);
}
luaReturnNil();
}
luaFunc(node_getShape)
{
Path *p = path(L);
luaReturnInt(p ? p->pathShape : 0);
}
luaFunc(registerSporeDrop)
{
float x, y;
int t=0;
x = lua_tonumber(L, 1);
y = lua_tonumber(L, 2);
t = lua_tointeger(L, 3);
dsq->game->registerSporeDrop(Vector(x,y), t);
luaReturnNil();
}
luaFunc(setStringFlag)
{
std::string n = getString(L, 1);
std::string v = getString(L, 2);
dsq->continuity.setStringFlag(n, v);
luaReturnNil();
}
luaFunc(centerText)
{
dsq->centerText(getString(L, 1));
luaReturnNil();
}
luaFunc(msg)
{
dsq->screenMessage(getString(L, 1));
luaReturnNil();
}
luaFunc(chance)
{
int r = rand()%100;
int c = lua_tointeger(L, 1);
if (c == 0)
luaReturnBool(false);
else
{
if (r <= c || c==100)
luaReturnBool(true);
else
luaReturnBool(false);
}
}
luaFunc(entity_handleShotCollisions)
{
Entity *e = entity(L);
if (e)
{
dsq->game->handleShotCollisions(e);
}
luaReturnNil();
}
luaFunc(entity_handleShotCollisionsSkeletal)
{
Entity *e = entity(L);
if (e)
{
dsq->game->handleShotCollisionsSkeletal(e);
}
luaReturnNil();
}
luaFunc(entity_handleShotCollisionsHair)
{
Entity *e = entity(L);
if (e)
{
dsq->game->handleShotCollisionsHair(e, lua_tointeger(L, 2), lua_tonumber(L, 3));
}
luaReturnNil();
}
luaFunc(entity_collideSkeletalVsCircle)
{
Entity *e = entity(L);
RenderObject *e2 = robj(L,2);
Bone *b = 0;
if (e && e2)
{
b = dsq->game->collideSkeletalVsCircle(e,e2);
}
luaReturnPtr(b);
}
luaFunc(entity_collideSkeletalVsCirclePos)
{
Entity *e = entity(L);
Bone *b = 0;
if (e)
{
b = dsq->game->collideSkeletalVsCircle(e, Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), lua_tonumber(L, 4));
}
luaReturnPtr(b);
}
luaFunc(entity_collideSkeletalVsLine)
{
Entity *e = entity(L);
int x1, y1, x2, y2, sz;
x1 = lua_tonumber(L, 2);
y1 = lua_tonumber(L, 3);
x2 = lua_tonumber(L, 4);
y2 = lua_tonumber(L, 5);
sz = lua_tonumber(L, 6);
Bone *b = 0;
if (e)
{
b = dsq->game->collideSkeletalVsLine(e, Vector(x1, y1), Vector(x2, y2), sz);
}
luaReturnPtr(b);
}
luaFunc(entity_collideHairVsCircle)
{
Entity *e = entity(L);
Entity *e2 = entity(L, 2);
bool col=false;
if (e && e2)
{
int num = lua_tointeger(L, 3);
// perc: percent of hairWidth to use as collide radius
float perc = lua_tonumber(L, 4);
int colSegment;
col = dsq->game->collideHairVsCircle(e, num, e2->position, e2->collideRadius, perc, &colSegment);
if(col)
{
lua_pushboolean(L, true);
lua_pushinteger(L, colSegment);
return 2;
}
}
luaReturnBool(false);
}
luaFunc(entity_collideSkeletalVsCircleForListByName)
{
Entity *e = entity(L);
std::string name;
if (lua_isstring(L, 2))
name = lua_tostring(L, 2);
if (e && !name.empty())
{
FOR_ENTITIES(i)
{
Entity *e2 = *i;
if (e2->life == 1 && e2->name == name)
{
Bone *b = dsq->game->collideSkeletalVsCircle(e, e2);
if (b)
{
DamageData d;
d.attacker = e2;
d.bone = b;
e->damage(d);
}
}
}
}
luaReturnNil();
}
luaFunc(entity_debugText)
{
Entity *e = entity(L);
const char *txt = lua_tostring(L, 2);
if (e && txt)
{
BitmapText *f = new BitmapText(&dsq->smallFont);
f->setText(txt);
f->position = e->position;
core->getTopStateData()->addRenderObject(f, LR_DEBUG_TEXT);
f->setLife(5);
f->setDecayRate(1);
f->fadeAlphaWithLife=1;
}
luaReturnNil();
}
luaFunc(entity_getHealth)
{
Entity *e = entity(L);
luaReturnNum(e ? e->health : 0);
}
luaFunc(entity_getMaxHealth)
{
Entity *e = entity(L);
luaReturnNum(e ? e->maxHealth : 0);
}
luaFunc(entity_initSegments)
{
ScriptedEntity *se = scriptedEntity(L);
if (se)
se->initSegments(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), getString(L, 5), getString(L, 6), lua_tointeger(L, 7), lua_tointeger(L, 8), lua_tonumber(L, 9), lua_tointeger(L, 10));
luaReturnNil();
}
luaFunc(entity_warpSegments)
{
ScriptedEntity *se = scriptedEntity(L);
if (se)
se->warpSegments();
luaReturnNil()
}
luaFunc(avatar_incrLeaches)
{
dsq->game->avatar->leaches++;
luaReturnNil();
}
luaFunc(avatar_decrLeaches)
{
// Not checking for underflow here because this allows some neat tricks.
dsq->game->avatar->leaches--;
luaReturnNil();
}
luaFunc(entity_rotateToVel)
{
Entity *e = entity(L);
if (e)
{
if (!e->vel.isZero())
{
e->rotateToVec(e->vel, lua_tonumber(L, 2), lua_tointeger(L, 3));
}
}
luaReturnNil();
}
luaFunc(entity_rotateToEntity)
{
Entity *e = entity(L);
Entity *e2 = entity(L, 2);
if (e && e2)
{
Vector vec = e2->position - e->position;
if (!vec.isZero())
{
e->rotateToVec(vec, lua_tonumber(L, 3), lua_tointeger(L, 4));
}
}
luaReturnNil();
}
luaFunc(entity_rotateToVec)
{
Entity *e = entity(L);
Vector vec(lua_tonumber(L, 2), lua_tonumber(L, 3));
if (e)
{
if (!vec.isZero())
{
e->rotateToVec(vec, lua_tonumber(L, 4), lua_tointeger(L, 5));
}
}
luaReturnNil();
}
luaFunc(entity_updateSkeletal)
{
Entity *e = entity(L);
if (e)
{
bool oldIgnore = e->skeletalSprite.ignoreUpdate;
e->skeletalSprite.ignoreUpdate = false;
e->skeletalSprite.update(lua_tonumber(L, 2));
e->skeletalSprite.ignoreUpdate = oldIgnore;
}
luaReturnNil();
}
luaFunc(entity_msg)
{
Entity *e = entity(L);
if (e)
{
// pass everything on the stack except the entity pointer
int res = e->messageVariadic(L, lua_gettop(L) - 1);
if (res >= 0)
return res;
}
luaReturnNil();
}
luaFunc(node_msg)
{
Path *p = path(L);
if (p)
{
// pass everything on the stack except the entity pointer
int res = p->messageVariadic(L, lua_gettop(L) - 1);
if (res >= 0)
return res;
}
luaReturnNil();
}
luaFunc(entity_updateCurrents)
{
Entity *e = entity(L);
luaReturnBool(e ? e->updateCurrents(lua_tonumber(L, 2)) : false);
}
luaFunc(entity_updateLocalWarpAreas)
{
Entity *e = entity(L);
luaReturnBool(e ? e->updateLocalWarpAreas(getBool(L, 2)) : false);
}
luaFunc(entity_updateMovement)
{
ScriptedEntity *e = scriptedEntity(L);
if (e)
e->updateMovement(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(entity_applySurfaceNormalForce)
{
Entity *e = entity(L);
if (e)
{
Vector v;
if (!e->ridingOnEntity)
{
v = dsq->game->getWallNormal(e->position, 8);
}
else
{
v = e->position - e->ridingOnEntity->position;
e->ridingOnEntity = 0;
}
v.setLength2D(lua_tointeger(L, 2));
e->vel += v;
}
luaReturnNil();
}
luaFunc(entity_doElementInteraction)
{
Entity *e = entity(L);
if (e)
{
float mult = lua_tonumber(L, 2);
float touchWidth = lua_tonumber(L, 3);
if (!touchWidth)
touchWidth = 16;
ElementUpdateList& elems = dsq->game->elementInteractionList;
for (ElementUpdateList::iterator it = elems.begin(); it != elems.end(); ++it)
{
(*it)->doInteraction(e, mult, touchWidth);
}
}
luaReturnNil();
}
luaFunc(avatar_setElementEffectMult)
{
dsq->game->avatar->elementEffectMult = lua_tonumber(L, 1);
luaReturnNil();
}
luaFunc(flingMonkey)
{
Entity *e = entity(L);
dsq->continuity.flingMonkey(e);
luaReturnNil();
}
luaFunc(entity_getDistanceToTarget)
{
Entity *e = entity(L);
float dist = 0;
if (e)
{
Entity *t = e->getTargetEntity();
if (t)
{
dist = (t->position - e->position).getLength2D();
}
}
luaReturnNum(dist);
}
luaFunc(entity_getDistanceToPoint)
{
Entity *e = entity(L);
float dist = 0;
if (e)
{
Vector p(lua_tonumber(L, 2), lua_tonumber(L, 3));
dist = (p - e->position).getLength2D();
}
luaReturnNum(dist);
}
luaFunc(entity_watchEntity)
{
Entity *e = entity(L);
Entity *e2 = 0;
if (lua_touserdata(L, 2) != NULL)
e2 = entity(L, 2);
if (e)
{
e->watchEntity(e2);
}
luaReturnNil();
}
luaFunc(setNaijaHeadTexture)
{
Avatar *a = dsq->game->avatar;
if (a)
{
a->setHeadTexture(getString(L, 1), lua_tonumber(L, 2));
}
luaReturnNil();
}
luaFunc(entity_flipToSame)
{
Entity *e = entity(L);
Entity *e2 = entity(L, 2);
if (e && e2)
{
if ((e->isfh() && !e2->isfh())
|| (!e->isfh() && e2->isfh()))
{
e->flipHorizontal();
}
}
luaReturnNil();
}
luaFunc(entity_flipToEntity)
{
Entity *e = entity(L);
Entity *e2 = entity(L, 2);
if (e && e2)
{
e->flipToTarget(e2->position);
}
luaReturnNil();
}
luaFunc(entity_flipToNode)
{
Entity *e = entity(L);
Path *p = path(L, 2);
PathNode *n = &p->nodes[0];
if (e && n)
{
e->flipToTarget(n->position);
}
luaReturnNil();
}
luaFunc(entity_flipToVel)
{
Entity *e = entity(L);
if (e)
{
e->flipToVel();
}
luaReturnNil();
}
luaFunc(node_isEntityIn)
{
Path *p = path(L,1);
Entity *e = entity(L,2);
bool v = false;
if (e && p)
{
if (!p->nodes.empty())
{
v = p->isCoordinateInside(e->position);
//(e->position - p->nodes[0].position);
}
}
luaReturnBool(v);
}
luaFunc(node_isPositionIn)
{
Path *p = path(L,1);
float x = lua_tonumber(L, 2);
float y = lua_tonumber(L, 3);
bool v = false;
if (p)
{
if (!p->nodes.empty())
{
v = p->rect.isCoordinateInside(Vector(x,y) - p->nodes[0].position);
}
}
luaReturnBool(v);
}
luaFunc(entity_isInDarkness)
{
Entity *e = entity(L);
bool d = false;
if (e)
{
d = e->isInDarkness();
}
luaReturnBool(d);
}
luaFunc(entity_isInRect)
{
Entity *e = entity(L);
bool v= false;
float x1, y1, x2, y2;
x1 = lua_tonumber(L, 2);
y1 = lua_tonumber(L, 3);
x2 = lua_tonumber(L, 4);
y2 = lua_tonumber(L, 5);
if (e)
{
if (e->position.x > x1 && e->position.x < x2)
{
if (e->position.y > y1 && e->position.y < y2)
{
v = true;
}
}
}
luaReturnBool(v);
}
luaFunc(createQuad)
{
PauseQuad *q = new PauseQuad();
q->setTexture(getString(L, 1));
int layer = lua_tointeger(L, 2);
if (layer == 13)
layer = 13;
else
layer = (LR_PARTICLES+1) - LR_ELEMENTS1;
dsq->game->addRenderObject(q, LR_ELEMENTS1+(layer-1));
q->moveToFront();
luaReturnPtr(q);
}
luaFunc(quad_setPauseLevel)
{
Quad *q = getQuad(L);
ENSURE_TYPE(q, SCO_PAUSEQUAD);
if (q)
((PauseQuad*)q)->pauseLevel = lua_tointeger(L, 2);
luaReturnNil();
}
luaFunc(setupEntity)
{
ScriptedEntity *se = scriptedEntity(L);
if (se)
{
std::string tex;
if (lua_isstring(L, 2))
{
tex = lua_tostring(L, 2);
}
se->setupEntity(tex, lua_tonumber(L, 3));
}
luaReturnNil();
}
luaFunc(setupBasicEntity)
{
ScriptedEntity *se = scriptedEntity(L);
//-- texture, health, manaballamount, exp, money, collideRadius, initState
if (se)
se->setupBasicEntity(getString(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5), lua_tointeger(L, 6), lua_tointeger(L, 7), lua_tointeger(L, 8), lua_tointeger(L, 9), lua_tointeger(L, 10), lua_tointeger(L, 11), lua_tointeger(L, 12), lua_tointeger(L, 13), lua_tointeger(L, 14));
luaReturnNil();
}
luaFunc(entity_setBeautyFlip)
{
Entity *e = entity(L);
if (e)
{
e->beautyFlip = getBool(L, 2);
}
luaReturnNil();
}
luaFunc(setInvincible)
{
dsq->game->invinciblity = getBool(L, 1);
luaReturnBool(dsq->game->invinciblity);
}
luaFunc(entity_setInvincible)
{
Entity *e = entity(L);
if (e)
{
e->setInvincible(getBool(L, 2));
}
luaReturnNil();
}
luaFunc(entity_setDeathSound)
{
Entity *e = entity(L);
if (e)
{
e->deathSound = getString(L, 2);
}
luaReturnNil();
}
luaFunc(entity_setDeathParticleEffect)
{
ScriptedEntity *se = scriptedEntity(L);
if (se)
{
se->deathParticleEffect = getString(L, 2);
}
luaReturnNil();
}
luaFunc(entity_setNaijaReaction)
{
Entity *e = entity(L);
std::string s;
if (lua_isstring(L, 2))
s = lua_tostring(L, 2);
if (e)
{
e->naijaReaction = s;
}
luaReturnNil();
}
luaFunc(entity_setName)
{
Entity *e = entity(L);
std::string s;
if (lua_isstring(L, 2))
s = lua_tostring(L, 2);
if (e)
{
debugLog("setting entity name to: " + s);
e->setName(s);
}
luaReturnNil();
}
luaFunc(entity_pathBurst)
{
Entity *e = entity(L);
bool v = false;
if (e)
v = e->pathBurst(lua_tointeger(L, 2));
luaReturnBool(v);
}
luaFunc(entity_moveTowardsAngle)
{
Entity *e = entity(L);
if (e)
e->moveTowardsAngle(lua_tointeger(L, 2), lua_tonumber(L, 3), lua_tointeger(L, 4));
luaReturnNil();
}
luaFunc(entity_moveAroundAngle)
{
Entity *e = entity(L);
if (e)
e->moveTowardsAngle(lua_tointeger(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4));
luaReturnNil();
}
luaFunc(entity_moveTowards)
{
Entity *e = entity(L);
if (e)
e->moveTowards(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), lua_tonumber(L, 4), lua_tonumber(L, 5));
luaReturnNil();
}
luaFunc(entity_moveAround)
{
Entity *e = entity(L);
if (e)
e->moveAround(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6));
luaReturnNil();
}
luaFunc(entity_addVel2)
{
Entity *e = entity(L);
if (e)
e->vel2 += Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(entity_setVel2)
{
Entity *e = entity(L);
if (e)
{
e->vel2 = Vector(lua_tonumber(L, 2), lua_tonumber(L, 3));
}
luaReturnNil();
}
luaFunc(entity_getVel2Len)
{
Entity *e = entity(L);
luaReturnNum(e ? e->vel2.getLength2D() : 0.0f);
}
luaFunc(entity_setVel2Len)
{
Entity *e = entity(L);
if(e)
e->vel2.setLength2D(lua_tonumber(L, 2));
luaReturnNil();
};
luaFunc(entity_getVel2)
{
Entity *e = entity(L);
Vector vel2;
if(e)
vel2 = e->vel2;
luaReturnVec2(vel2.x, vel2.y);
}
luaFunc(entity_isValidTarget)
{
Entity *e = entity(L);
Entity *e2 = 0;
if (lua_tonumber(L, 2)!=0)
e2 = entity(L);
bool b = false;
if (e)
b = dsq->game->isValidTarget(e, e2);
luaReturnBool(b);
}
luaFunc(entity_clearVel2)
{
Entity *e = entity(L);
if (e)
e->vel2 = Vector(0,0,0);
luaReturnNil();
}
luaFunc(getScreenCenter)
{
luaReturnVec2(core->screenCenter.x, core->screenCenter.y);
}
luaFunc(entity_isState)
{
Entity *e = entity(L);
bool v=false;
if (e)
{
v = (e->getState() == lua_tointeger(L, 2));
}
luaReturnBool(v);
}
luaFunc(entity_getState)
{
Entity *e = entity(L);
int state = 0;
if (e)
state = e->getState();
luaReturnNum(state);
}
luaFunc(entity_getEnqueuedState)
{
Entity *e = entity(L);
int state = 0;
if (e)
state = e->getEnqueuedState();
luaReturnNum(state);
}
luaFunc(entity_getPrevState)
{
Entity *e = entity(L);
int state = 0;
if (e)
state = e->getPrevState();
luaReturnNum(state);
}
luaFunc(entity_setTarget)
{
Entity *e = entity(L);
Entity *t = 0;
if (lua_touserdata(L, 2) != NULL)
{
t = entity(L, 2);
}
if (e)
{
e->setTargetEntity(t);
}
luaReturnNil();
}
luaFunc(entity_setBounce)
{
CollideEntity *e = collideEntity(L);
if (e)
e->bounceAmount = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(avatar_isSinging)
{
bool b = dsq->game->avatar->isSinging();
luaReturnBool(b);
}
luaFunc(avatar_isTouchHit)
{
//avatar_canBeTouchHit
bool b = !(dsq->game->avatar->bursting && dsq->continuity.form == FORM_BEAST);
luaReturnBool(b);
}
luaFunc(avatar_clampPosition)
{
dsq->game->avatar->clampPosition();
luaReturnNil();
}
luaFunc(entity_setMaxSpeed)
{
Entity *e = entity(L);
if (e)
e->setMaxSpeed(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(entity_getMaxSpeed)
{
Entity *e = entity(L);
int v = 0;
if (e)
v = e->getMaxSpeed();
luaReturnNum(v);
}
luaFunc(entity_setMaxSpeedLerp)
{
Entity *e = entity(L);
if (e)
interpolateVec1(L, e->maxSpeedLerp, 2);
luaReturnNil();
}
luaFunc(entity_getMaxSpeedLerp)
{
Entity *e = entity(L);
luaReturnNum(e ? e->maxSpeedLerp.x : 0.0f);
}
// note: this is a weaker setState than perform
// this is so that things can override it
// for example getting PUSH-ed (Force) or FROZEN (bubbled)
luaFunc(entity_setState)
{
Entity *me = entity(L);
if (me)
{
int state = lua_tointeger(L, 2);
float time = lua_tonumber(L, 3);
if (time == 0)
time = -1;
bool force = getBool(L, 4);
me->setState(state, time, force);
}
luaReturnNil();
}
luaFunc(entity_getBoneByIdx)
{
Entity *e = entity(L);
Bone *b = 0;
if (e)
{
int n = 0;
if (lua_isnumber(L, 2))
{
n = lua_tointeger(L, 2);
b = e->skeletalSprite.getBoneByIdx(n);
}
}
luaReturnPtr(b);
}
luaFunc(entity_getBoneByName)
{
Entity *e = entity(L);
luaReturnPtr(e ? e->skeletalSprite.getBoneByName(getString(L, 2)) : NULL);
}
luaFunc(entity_getBoneByInternalId)
{
Entity *e = entity(L);
size_t i = lua_tointeger(L, 2);
luaReturnPtr((e && i < e->skeletalSprite.bones.size()) ? e->skeletalSprite.bones[i] : NULL);
}
luaFunc(entity_getNumBones)
{
Entity *e = entity(L);
luaReturnInt(e ? (int)e->skeletalSprite.bones.size() : 0);
}
luaFunc(bone_getIndex)
{
Bone *b = bone(L);
int idx = -1;
if (b)
idx = b->boneIdx;
luaReturnNum(idx);
}
luaFunc(bone_getName)
{
const char *n = "";
Bone *b = bone(L);
if (b)
{
n = b->name.c_str();
}
luaReturnStr(n);
}
luaFunc(bone_isName)
{
Bone *b = bone(L);
bool v = false;
const char *s = lua_tostring(L, 2);
if (b && s)
{
v = b->name == s;
}
luaReturnBool(v);
}
luaFunc(overrideZoom)
{
dsq->game->overrideZoom(lua_tonumber(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(getZoom)
{
luaReturnNum(dsq->globalScale.x);
}
luaFunc(disableOverrideZoom)
{
dsq->game->toggleOverrideZoom(false);
luaReturnNil();
}
luaFunc(setMaxLookDistance)
{
dsq->game->maxLookDistance = lua_tonumber(L, 1);
luaReturnNil();
}
// dt, range, mod
luaFunc(entity_doSpellAvoidance)
{
Entity *e = entity(L);
if (e)
e->doSpellAvoidance(lua_tonumber(L, 2), lua_tointeger(L, 3), lua_tonumber(L, 4));
luaReturnNil();
}
// dt, range, mod, ignore
luaFunc(entity_doEntityAvoidance)
{
Entity *e = entity(L);
if (e)
e->doEntityAvoidance(lua_tonumber(L, 2), lua_tointeger(L, 3), lua_tonumber(L, 4), e->getTargetEntity());
luaReturnNil();
}
// doCollisionAvoidance(me, dt, search, mod)
luaFunc(entity_doCollisionAvoidance)
{
Entity *e = entity(L);
bool ret = false;
bool useVel2 = getBool(L, 6);
bool onlyVP = getBool(L, 7);
int ignoreObs = lua_tointeger(L, 8);
if (e)
{
if (useVel2)
ret = e->doCollisionAvoidance(lua_tonumber(L, 2), lua_tointeger(L, 3), lua_tonumber(L, 4), &e->vel2, lua_tonumber(L, 5), ignoreObs, onlyVP);
else
ret = e->doCollisionAvoidance(lua_tonumber(L, 2), lua_tointeger(L, 3), lua_tonumber(L, 4), 0, lua_tonumber(L, 5), ignoreObs);
}
luaReturnBool(ret);
}
luaFunc(setOverrideMusic)
{
dsq->game->overrideMusic = getString(L, 1);
luaReturnNil();
}
luaFunc(setOverrideVoiceFader)
{
dsq->sound->setOverrideVoiceFader(lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(setGameSpeed)
{
dsq->gameSpeed.stop();
dsq->gameSpeed.stopPath();
interpolateVec1(L, dsq->gameSpeed, 1);
luaReturnNil();
}
luaFunc(bedEffects)
{
dsq->overlay->alpha.interpolateTo(1, 2);
dsq->sound->fadeMusic(SFT_OUT, 1);
core->run(1);
// music goes here
dsq->sound->fadeMusic(SFT_CROSS, 1);
dsq->sound->playMusic("Sleep");
core->run(6);
Vector bedPosition(lua_tointeger(L, 1), lua_tointeger(L, 2));
if (bedPosition.x == 0 && bedPosition.y == 0)
{
bedPosition = dsq->game->avatar->position;
}
dsq->game->positionToAvatar = bedPosition;
dsq->game->transitionToScene(dsq->game->sceneName);
luaReturnNil();
}
luaFunc(entity_setDeathScene)
{
Entity *e = entity(L);
if (e)
{
e->setDeathScene(getBool(L, 2));
}
luaReturnNil();
}
luaFunc(entity_isDeathScene)
{
Entity *e = entity(L);
luaReturnBool(e ? e->isDeathScene() : false);
}
luaFunc(entity_setCurrentTarget)
{
Entity *e = entity(L);
if (e)
e->currentEntityTarget = lua_tointeger(L, 2);
luaReturnNil();
}
luaFunc(entityFollowEntity)
{
Entity *e = dsq->getEntityByName(getString(L, 1));
if (e)
{
e->followEntity = dsq->getEntityByName(getString(L, 2));
}
luaReturnNil();
}
luaFunc(entity_isFollowingEntity)
{
Entity *e = entity(L);
bool v = false;
if (e)
v = e->followEntity != 0;
luaReturnBool(v);
}
luaFunc(entity_followEntity)
{
Entity *e1 = entity(L);
Entity *e2 = 0;
if (lua_touserdata(L, 2) != NULL)
{
e2 = entity(L, 2);
}
if (e1)
{
e1->followEntity = e2;
e1->followPos = lua_tointeger(L, 3);
}
luaReturnNil();
}
luaFunc(toggleInput)
{
bool v = getBool(L, 1);
if (v)
dsq->game->avatar->enableInput();
else
dsq->game->avatar->disableInput();
luaReturnNil();
}
luaFunc(warpAvatar)
{
dsq->game->positionToAvatar = Vector(lua_tointeger(L, 2),lua_tointeger(L, 3));
dsq->game->transitionToScene(getString(L, 1));
luaReturnNil();
}
luaFunc(warpNaijaToSceneNode)
{
std::string scene = getString(L, 1);
std::string node = getString(L, 2);
std::string flip = getString(L, 3);
if (!scene.empty() && !node.empty())
{
dsq->game->toNode = node;
stringToLower(flip);
if (flip == "l")
dsq->game->toFlip = 0;
if (flip == "r")
dsq->game->toFlip = 1;
dsq->game->transitionToScene(scene);
}
luaReturnNil();
}
luaFunc(entity_setDamageTarget)
{
Entity *e = entity(L);
if (e)
{
e->setDamageTarget((DamageType)lua_tointeger(L, 2), getBool(L, 3));
}
luaReturnNil();
}
luaFunc(entity_setAllDamageTargets)
{
Entity *e = entity(L);
if (e)
{
e->setAllDamageTargets(getBool(L, 2));
}
luaReturnNil();
}
luaFunc(entity_isDamageTarget)
{
Entity *e = entity(L);
bool v=false;
if (e)
{
v = e->isDamageTarget((DamageType)lua_tointeger(L, 2));
}
luaReturnBool(v);
}
luaFunc(entity_setTargetRange)
{
Entity *e = entity(L);
if (e)
{
e->targetRange = lua_tonumber(L, 2);
}
luaReturnNil();
}
luaFunc(entity_getTargetRange)
{
Entity *e = entity(L);
luaReturnInt(e ? e->getTargetRange() : 0);
}
luaFunc(entity_clearTargetPoints)
{
Entity *e = entity(L);
if (e)
e->clearTargetPoints();
luaReturnNil();
}
luaFunc(entity_addTargetPoint)
{
Entity *e = entity(L);
if (e)
e->addTargetPoint(Vector(lua_tonumber(L,2), lua_tonumber(L, 3)));
luaReturnNil();
}
luaFunc(entity_getTargetPoint)
{
Entity *e = entity(L);
int idx = lua_tointeger(L, 2);
Vector v;
if (e)
{
v = e->getTargetPoint(idx);
}
luaReturnVec2(v.x, v.y);
}
luaFunc(entity_getRandomTargetPoint)
{
Entity *e = entity(L);
Vector v;
int idx = 0;
if (e)
{
idx = e->getRandomTargetPoint();
}
luaReturnNum(idx);
}
luaFunc(entity_getNumTargetPoints)
{
Entity *e = entity(L);
luaReturnInt(e ? e->getNumTargetPoints() : 0);
}
luaFunc(playVisualEffect)
{
Entity *target = NULL;
if(lua_isuserdata(L, 4))
target = entity(L, 4);
dsq->playVisualEffect(lua_tonumber(L, 1), Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), target);
luaReturnNil();
}
luaFunc(playNoEffect)
{
dsq->playNoEffect();
luaReturnNil();
}
luaFunc(createShockEffect)
{
if (core->afterEffectManager)
{
core->afterEffectManager->addEffect(new ShockEffect(
Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)), // position
Vector(lua_tonumber(L, 3), lua_tonumber(L, 4)), // original position
lua_tonumber(L, 5), // amplitude
lua_tonumber(L, 6), // amplitude decay
lua_tonumber(L, 7), // frequency
lua_tonumber(L, 8), // wave length
lua_tonumber(L, 9))); // time multiplier
}
luaReturnNil();
}
luaFunc(emote)
{
int emote = lua_tointeger(L, 1);
dsq->emote.playSfx(emote);
luaReturnNil();
}
luaFunc(playSfx)
{
PlaySfx sfx;
sfx.name = getString(L, 1);
sfx.freq = lua_tonumber(L, 2);
sfx.vol = lua_tonumber(L, 3);
if (sfx.vol <= 0)
sfx.vol = 1;
sfx.loops = lua_tointeger(L, 4);
if(lua_isnumber(L, 5) && lua_isnumber(L, 6))
{
sfx.x = lua_tonumber(L, 5);
sfx.y = lua_tonumber(L, 6);
sfx.positional = true;
}
sfx.maxdist = lua_tonumber(L, 7);
if(lua_isnoneornil(L, 8))
sfx.relative = (sfx.x == 0 && sfx.y == 0);
else
sfx.relative = getBool(L, 8);
void *handle = NULL;
if (!dsq->isSkippingCutscene())
{
handle = core->sound->playSfx(sfx);
}
luaReturnPtr(handle);
}
luaFunc(fadeSfx)
{
void *header = lua_touserdata(L, 1);
float ft = lua_tonumber(L, 2);
core->sound->fadeSfx(header, SFT_OUT, ft);
luaReturnPtr(header);
}
luaFunc(resetTimer)
{
dsq->resetTimer();
luaReturnNil();
}
luaFunc(stopMusic)
{
dsq->sound->stopMusic();
luaReturnNil();
}
luaFunc(playMusic)
{
float crossfadeTime = 0.8;
dsq->sound->playMusic(getString(L, 1), SLT_LOOP, SFT_CROSS, crossfadeTime);
luaReturnNil();
}
luaFunc(playMusicStraight)
{
dsq->sound->setMusicFader(1,0);
dsq->sound->playMusic(getString(L, 1), SLT_LOOP, SFT_IN, 0.5);
luaReturnNil();
}
luaFunc(playMusicOnce)
{
float crossfadeTime = 0.8;
dsq->sound->playMusic(getString(L, 1), SLT_NONE, SFT_CROSS, crossfadeTime);
luaReturnNil();
}
luaFunc(addInfluence)
{
ParticleInfluence pinf;
pinf.pos.x = lua_tonumber(L, 1);
pinf.pos.y = lua_tonumber(L, 2);
pinf.size = lua_tonumber(L, 3);
pinf.spd = lua_tonumber(L, 4);
pinf.pull = getBool(L, 5);
dsq->particleManager->addInfluence(pinf);
luaReturnNil();
}
luaFunc(updateMusic)
{
dsq->game->updateMusic();
luaReturnNil();
}
luaFunc(entity_grabTarget)
{
Entity *e = entity(L);
if (e)
e->attachEntity(e->getTargetEntity(), Vector(lua_tointeger(L, 2), lua_tointeger(L, 3)));
luaReturnNil();
}
luaFunc(entity_clampToHit)
{
Entity *e = entity(L);
if (e)
e->clampToHit();
luaReturnNil();
}
luaFunc(entity_clampToSurface)
{
Entity *e = entity(L);
bool ret = e && e->clampToSurface(lua_tonumber(L, 2));
luaReturnBool(ret);
}
luaFunc(entity_checkSurface)
{
Entity *e = entity(L);
bool c = false;
if (e)
{
c = e->checkSurface(lua_tonumber(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4));
}
luaReturnBool(c);
}
luaFunc(entity_switchSurfaceDirection)
{
ScriptedEntity *e = scriptedEntity(L);
if (!e)
luaReturnNil();
int n = -1;
if (lua_isnumber(L, 2))
{
n = lua_tonumber(L, 2);
}
if (e->isv(EV_SWITCHCLAMP, 1))
{
Vector oldPos = e->position;
if (e->isNearObstruction(0))
{
Vector n = dsq->game->getWallNormal(e->position);
if (!n.isZero())
{
do
{
e->position += n * 2;
}
while(e->isNearObstruction(0));
}
}
Vector usePos = e->position;
e->position = oldPos;
e->clampToSurface(0, usePos);
}
if (n == -1)
{
if (e->surfaceMoveDir)
e->surfaceMoveDir = 0;
else
e->surfaceMoveDir = 1;
}
else
{
e->surfaceMoveDir = n;
}
luaReturnNil();
}
luaFunc(entity_adjustPositionBySurfaceNormal)
{
ScriptedEntity *e = scriptedEntity(L);
if (e && !e->ridingOnEntity)
{
Vector v = dsq->game->getWallNormal(e->position);
if (v.x != 0 || v.y != 0)
{
v.setLength2D(lua_tonumber(L, 2));
e->position += v;
}
e->setv(EV_CRAWLING, 0);
}
luaReturnNil();
}
// HACK: move functionality inside entity class
luaFunc(entity_moveAlongSurface)
{
ScriptedEntity *e = scriptedEntity(L);
if (e && e->isv(EV_CLAMPING,0))
{
e->lastPosition = e->position;
{
Vector v;
if (e->ridingOnEntity)
{
v = (e->position - e->ridingOnEntity->position);
v.normalize2D();
}
else
v = dsq->game->getWallNormal(e->position);
int outFromWall = e->getv(EV_WALLOUT);
bool invisibleIn = e->isSittingOnInvisibleIn();
if (invisibleIn)
outFromWall -= TILE_SIZE;
float t = 0.1;
e->offset.interpolateTo(v*outFromWall, t);
float dt = lua_tonumber(L, 2);
float speed = lua_tonumber(L, 3);
Vector mov;
if (e->surfaceMoveDir==1)
mov = Vector(v.y, -v.x);
else
mov = Vector(-v.y, v.x);
e->position += mov * speed * dt;
if (e->ridingOnEntity)
e->ridingOnEntityOffset = e->position - e->ridingOnEntity->position;
e->vel = 0;
}
}
luaReturnNil();
}
luaFunc(entity_rotateToSurfaceNormal)
{
Entity *e = entity(L);
float t = lua_tonumber(L, 2);
int n = lua_tointeger(L, 3);
float rot = lua_tonumber(L, 4);
if (e)
{
e->rotateToSurfaceNormal(t, n, rot);
}
luaReturnNil();
}
luaFunc(entity_releaseTarget)
{
Entity *e = entity(L);
if (e)
e->detachEntity(e->getTargetEntity());
luaReturnNil();
}
luaFunc(esetv)
{
Entity *e = entity(L);
EV ev = (EV)lua_tointeger(L, 2);
int n = lua_tointeger(L, 3);
if (e)
e->setv(ev, n);
luaReturnNum(n);
}
luaFunc(egetv)
{
Entity *e = entity(L);
EV ev = (EV)lua_tointeger(L, 2);
int v = 0;
if (e)
v = e->getv(ev);
luaReturnNum(v);
}
luaFunc(esetvf)
{
Entity *e = entity(L);
EV ev = (EV)lua_tointeger(L, 2);
float n = lua_tonumber(L, 3);
if (e)
e->setvf(ev, n);
luaReturnNum(n);
}
luaFunc(egetvf)
{
Entity *e = entity(L);
float vf = 0;
if (e)
{
EV ev = (EV)lua_tointeger(L, 2);
vf = e->getvf(ev);
}
luaReturnNum(vf);
}
luaFunc(eisv)
{
Entity *e = entity(L);
EV ev = (EV)lua_tointeger(L, 2);
int n = lua_tointeger(L, 3);
bool b = 0;
if (e)
b = e->isv(ev, n);
luaReturnBool(b);
}
luaFunc(vector_normalize)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
Vector v(x,y);
v.normalize2D();
luaReturnVec2(v.x, v.y);
}
luaFunc(vector_getLength)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
Vector v(x,y);
float len = v.getLength2D();
luaReturnNum(len);
}
luaFunc(vector_setLength)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
Vector v(x,y);
v.setLength2D(lua_tonumber(L, 3));
luaReturnVec2(v.x, v.y);
}
luaFunc(vector_dot)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
float x2 = lua_tonumber(L, 3);
float y2 = lua_tonumber(L, 4);
Vector v(x,y);
Vector v2(x2,y2);
luaReturnNum(v.dot2D(v2));
}
luaFunc(vector_cap)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
Vector v(x,y);
v.capLength2D(lua_tonumber(L, 3));
luaReturnVec2(v.x, v.y);
}
luaFunc(vector_isLength2DIn)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
Vector v(x,y);
bool ret = v.isLength2DIn(lua_tonumber(L, 3));
luaReturnBool(ret);
}
luaFunc(entity_push)
{
Entity *e = entity(L);
if (e)
{
e->push(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6));
}
luaReturnNil();
}
luaFunc(entity_pushTarget)
{
Entity *e = entity(L);
if (e)
{
Entity *target = e->getTargetEntity();
if (target)
{
Vector diff = target->position - e->position;
diff.setLength2D(lua_tointeger(L, 2));
target->vel += diff;
}
}
luaReturnNil();
}
luaFunc(entity_getPushDamage)
{
Entity *e = entity(L);
luaReturnNum(e ? e->getPushDamage() : 0.0f);
}
luaFunc(watch)
{
float t = lua_tonumber(L, 1);
int quit = lua_tointeger(L, 2);
dsq->watch(t, quit);
luaReturnNil();
}
luaFunc(wait)
{
core->run(lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(warpNaijaToEntity)
{
Entity *e = dsq->getEntityByName(getString(L, 1));
if (e)
{
dsq->overlay->alpha.interpolateTo(1, 1);
core->run(1);
Vector offset(lua_tointeger(L, 2), lua_tointeger(L, 3));
dsq->game->avatar->position = e->position + offset;
dsq->overlay->alpha.interpolateTo(0, 1);
core->run(1);
}
luaReturnNil();
}
luaFunc(getTimer)
{
float n = lua_tonumber(L, 1);
if (n == 0)
n = 1;
luaReturnNum(dsq->game->getTimer(n));
}
luaFunc(getHalfTimer)
{
float n = lua_tonumber(L, 1);
if (n == 0)
n = 1;
luaReturnNum(dsq->game->getHalfTimer(n));
}
luaFunc(getOldDT)
{
luaReturnNum(core->get_old_dt());
}
luaFunc(getDT)
{
luaReturnNum(core->get_current_dt());
}
luaFunc(getFPS)
{
luaReturnInt(core->fps);
}
luaFunc(isNested)
{
luaReturnBool(core->isNested());
}
luaFunc(getNumberOfEntitiesNamed)
{
std::string s = getString(L);
int c = dsq->game->getNumberOfEntitiesNamed(s);
luaReturnNum(c);
}
luaFunc(entity_pullEntities)
{
Entity *e = entity(L);
if (e)
{
Vector pos(lua_tonumber(L, 2), lua_tonumber(L, 3));
float range = lua_tonumber(L, 4);
float len = lua_tonumber(L, 5);
float dt = lua_tonumber(L, 6);
FOR_ENTITIES(i)
{
Entity *ent = *i;
if (ent != e && (e->getEntityType() == ET_ENEMY || e->getEntityType() == ET_AVATAR) && e->isUnderWater())
{
Vector diff = ent->position - pos;
if (diff.isLength2DIn(range))
{
Vector pull = pos - ent->position;
pull.setLength2D(float(len) * dt);
ent->vel2 += pull;
}
}
}
}
luaReturnNil();
}
// Note that this overrides the generic obj_delete function for entities.
// (It's registered as "entity_delete" to Lua)
// There is at least one known case where this is necessary:
// Avatar::pullTarget does a life check to drop the pointer;
// If it's instantly deleted, this will cause a crash.
luaFunc(entity_delete_override)
{
Entity *e = entity(L);
if (e)
{
float time = lua_tonumber(L, 2);
if (time == 0)
{
e->alpha = 0;
e->setLife(0);
e->setDecayRate(1);
}
else
{
e->fadeAlphaWithLife = true;
e->setLife(1);
e->setDecayRate(1.0f/time);
}
}
luaReturnNil();
}
luaFunc(entity_isRidingOnEntity)
{
Entity *e = entity(L);
if (e)
luaReturnPtr(e->ridingOnEntity);
else
luaReturnPtr(NULL);
}
luaFunc(entity_isProperty)
{
Entity *e = entity(L);
bool v = false;
if (e)
{
v = e->isEntityProperty((EntityProperty)lua_tointeger(L, 2));
}
luaReturnBool(v);
}
luaFunc(entity_setProperty)
{
Entity *e = entity(L);
if (e)
{
e->setEntityProperty((EntityProperty)lua_tointeger(L, 2), getBool(L, 3));
}
luaReturnNil();
}
luaFunc(entity_setActivation)
{
ScriptedEntity *e = scriptedEntity(L);
if (e)
{
int type = lua_tointeger(L, 2);
// cursor radius
float activationRadius = lua_tonumber(L, 3);
float range = lua_tonumber(L, 4);
e->activationType = (Entity::ActivationType)type;
e->activationRange = range;
e->activationRadius = activationRadius;
}
luaReturnNil();
}
luaFunc(entity_setActivationType)
{
Entity *e = entity(L);
if (e)
e->activationType = (Entity::ActivationType)lua_tointeger(L, 2);
luaReturnNil();
}
luaFunc(entity_hasTarget)
{
Entity *e = entity(L);
if (e)
luaReturnBool(e->hasTarget(e->currentEntityTarget));
else
luaReturnBool(false);
}
luaFunc(entity_hurtTarget)
{
Entity *e = entity(L);
if (e && e->getTargetEntity())
{
DamageData d;
d.attacker = e;
d.damage = lua_tointeger(L, 2);
e->getTargetEntity(e->currentEntityTarget)->damage(d);
}
luaReturnNil();
}
// radius dmg speed pushtime
luaFunc(entity_touchAvatarDamage)
{
Entity *e = entity(L);
bool v = false;
if (e)
{
v = e->touchAvatarDamage(lua_tonumber(L, 2), lua_tonumber(L, 3), Vector(-1,-1,-1), lua_tonumber(L, 4), lua_tonumber(L, 5), Vector(lua_tonumber(L, 6), lua_tonumber(L, 7)));
}
luaReturnBool(v);
}
luaFunc(entity_getDistanceToEntity)
{
Entity *e = entity(L);
Entity *e2 = entity(L, 2);
float d = 0;
if (e && e2)
{
Vector diff = e->position - e2->position;
d = diff.getLength2D();
}
luaReturnNum(d);
}
luaFunc(entity_isEntityInside)
{
Entity *e = entity(L);
luaReturnBool(e ? e->isEntityInside() : false);
}
// entity_istargetInRange
luaFunc(entity_isTargetInRange)
{
Entity *e = entity(L);
if (e)
luaReturnBool(e->isTargetInRange(lua_tointeger(L, 2), e->currentEntityTarget));
else
luaReturnBool(false);
}
luaFunc(randAngle360)
{
luaReturnNum(randAngle360());
}
luaFunc(randVector)
{
float num = lua_tonumber(L, 1);
if (num == 0)
num = 1;
Vector v = randVector(num);
luaReturnVec2(v.x, v.y);
}
luaFunc(getNaija)
{
luaReturnPtr(dsq->game->avatar);
}
luaFunc(getLi)
{
luaReturnPtr(dsq->game->li);
}
luaFunc(setLi)
{
dsq->game->li = entity(L);
luaReturnNil();
}
luaFunc(entity_isPositionInRange)
{
Entity *e = entity(L);
bool v = false;
int x, y;
x = lua_tonumber(L, 2);
y = lua_tonumber(L, 3);
if (e)
{
if ((e->position - Vector(x,y)).isLength2DIn(lua_tonumber(L, 4)))
{
v = true;
}
}
luaReturnBool(v);
}
luaFunc(entity_isEntityInRange)
{
Entity *e1 = entity(L);
Entity *e2 = entity(L, 2);
bool v= false;
if (e1 && e2)
{
//v = ((e2->position - e1->position).getSquaredLength2D() < sqr(lua_tonumber(L, 3)));
v = (e2->position - e1->position).isLength2DIn(lua_tonumber(L, 3));
}
luaReturnBool(v);
}
//entity_moveTowardsTarget(spd, dt)
luaFunc(entity_moveTowardsTarget)
{
Entity *e = entity(L);
if (e)
{
e->moveTowardsTarget(lua_tonumber(L, 2), lua_tonumber(L, 3), e->currentEntityTarget);
}
luaReturnNil();
}
// entity dt speed dir
luaFunc(entity_moveAroundTarget)
{
Entity *e = entity(L);
if (e)
e->moveAroundTarget(lua_tonumber(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), e->currentEntityTarget);
// do stuff
luaReturnNil();
}
luaFunc(entity_rotateToTarget)
{
Entity *e = entity(L);
if (e)
{
Entity *t = e->getTargetEntity(e->currentEntityTarget);
if (t)
{
Vector v = t->position - e->position;
e->rotateToVec(v, lua_tonumber(L, 2), lua_tointeger(L, 3));
}
}
luaReturnNil();
}
luaFunc(entity_partWidthHeight)
{
ScriptedEntity *e = scriptedEntity(L);
Quad *r = (Quad*)e->partMap[getString(L, 2)];
if (r)
{
int w = lua_tointeger(L, 3);
int h = lua_tointeger(L, 4);
r->setWidthHeight(w, h);
}
luaReturnNil();
}
luaFunc(entity_partSetSegs)
{
ScriptedEntity *e = scriptedEntity(L);
Quad *r = (Quad*)e->partMap[getString(L, 2)];
if (r)
{
r->setSegs(lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6), lua_tonumber(L, 7), lua_tonumber(L, 8), lua_tonumber(L, 9), lua_tointeger(L, 10));
}
luaReturnNil();
}
luaFunc(entity_getID)
{
Entity *e = entity(L);
luaReturnNum(e ? e->getID() : 0);
}
luaFunc(getEntityByID)
{
debugLog("Calling getEntityByID");
int v = lua_tointeger(L, 1);
Entity *found = 0;
if (v)
{
std::ostringstream os;
os << "searching for entity with id: " << v;
debugLog(os.str());
FOR_ENTITIES(i)
{
Entity *e = *i;
if (e->getID() == v)
{
found = e;
break;
}
}
if (!found)
{
std::ostringstream os;
os << "entity with id: " << v << " not found!";
debugLog(os.str());
}
else
{
std::ostringstream os;
os << "Found: " << found->name;
debugLog(os.str());
}
}
else
{
debugLog("entity ID was 0");
}
luaReturnPtr(found);
}
luaFunc(node_activate)
{
Path *p = path(L);
Entity *e = 0;
if (lua_touserdata(L, 2) != NULL)
e = entity(L, 2);
if (p)
{
p->activate(e);
}
luaReturnNil();
}
luaFunc(node_setElementsInLayerActive)
{
Path *p = path(L);
if (p)
{
int l = lua_tointeger(L, 2);
bool v = getBool(L, 3);
for (Element *e = dsq->getFirstElementOnLayer(l); e; e = e->bgLayerNext)
{
if (e && p->isCoordinateInside(e->position))
{
e->setElementActive(v);
}
}
}
luaReturnNil();
}
luaFunc(node_getNumEntitiesIn)
{
Path *p = path(L);
std::string name;
if (lua_isstring(L, 2))
{
name = lua_tostring(L, 2);
}
int c = 0;
if (p && !p->nodes.empty())
{
FOR_ENTITIES(i)
{
Entity *e = *i;
if (name.empty() || (nocasecmp(e->name, name)==0))
{
if (p->isCoordinateInside(e->position))
{
c++;
}
}
}
}
luaReturnNum(c);
}
luaFunc(node_getNearestEntity)
{
Path *p = path(L);
Entity *closest=0;
if (p && !p->nodes.empty())
{
Vector pos = p->nodes[0].position;
std::string name;
Entity *ignore = 0;
if (lua_isstring(L, 2))
name = lua_tostring(L, 2);
if (lua_isuserdata(L, 3))
ignore = entity(L, 3);
float smallestDist = HUGE_VALF;
FOR_ENTITIES(i)
{
Entity *e = *i;
if (e != ignore && e->isPresent() && e->isNormalLayer())
{
if (name.empty() || (nocasecmp(e->name, name)==0))
{
float dist = (pos - e->position).getSquaredLength2D();
if (dist < smallestDist)
{
smallestDist = dist;
closest = e;
}
}
}
}
}
luaReturnPtr(closest);
}
luaFunc(node_getNearestNode)
{
Path *p = path(L);
Path *closest = 0;
if (p && !p->nodes.empty())
{
std::string name;
if (lua_isstring(L, 2))
name = lua_tostring(L, 2);
Path *ignore = path(L, 3);
closest = dsq->game->getNearestPath(p->nodes[0].position, name, ignore);
}
luaReturnPtr(closest);
}
luaFunc(entity_getNearestBoneToPosition)
{
Entity *me = entity(L);
Vector p(lua_tonumber(L, 2), lua_tonumber(L, 3));
float smallestDist = HUGE_VALF;
Bone *closest = 0;
if (me)
{
for (int i = 0; i < me->skeletalSprite.bones.size(); i++)
{
Bone *b = me->skeletalSprite.bones[i];
float dist = (b->getWorldPosition() - p).getSquaredLength2D();
if (dist < smallestDist)
{
smallestDist = dist;
closest = b;
}
}
}
luaReturnPtr(closest);
}
luaFunc(entity_getNearestNode)
{
Entity *me = entity(L);
Path *closest = 0;
if (me)
{
std::string name;
if (lua_isstring(L, 2))
name = lua_tostring(L, 2);
Path *ignore = path(L, 3);
closest = dsq->game->getNearestPath(me->position, name, ignore);
}
luaReturnPtr(closest);
}
luaFunc(ing_hasIET)
{
Ingredient *i = getIng(L, 1);
bool has = i && i->hasIET((IngredientEffectType)lua_tointeger(L, 2));
luaReturnBool(has);
}
luaFunc(ing_getIngredientName)
{
Ingredient *i = getIng(L, 1);
IngredientData *data = i ? i->getIngredientData() : 0;
luaReturnStr(data ? data->name.c_str() : "");
}
luaFunc(entity_getNearestEntity)
{
Entity *me = entity(L);
if (!me)
luaReturnPtr(0);
const char *name = 0;
if (lua_isstring(L, 2))
{
name = lua_tostring(L, 2);
if (!*name)
name = NULL;
}
bool nameCheck = true;
if (name && (name[0] == '!' || name[0] == '~'))
{
name++;
nameCheck = false;
}
float range = lua_tonumber(L, 3);
EntityType type = ET_NOTYPE;
if (lua_isnumber(L, 4))
type = (EntityType)lua_tointeger(L, 4);
DamageType damageTarget = DT_NONE;
if (lua_isnumber(L, 5))
damageTarget = (DamageType)lua_tointeger(L, 5);
Entity *closest = 0;
Entity *ignore = 0;
if (lua_isuserdata(L, 6))
ignore = entity(L, 6);
float smallestDist = range ? sqr(range) : HUGE_VALF;
FOR_ENTITIES(i)
{
Entity *e = *i;
if (e != me && e != ignore && e->isPresent() && e->isNormalLayer())
{
if (type == ET_NOTYPE || e->getEntityType() == type)
{
if (damageTarget == DT_NONE || e->isDamageTarget((DamageType)damageTarget))
{
if (!name || ((nocasecmp(e->name, name)==0) == nameCheck))
{
float dist = (me->position - e->position).getSquaredLength2D();
if (dist < smallestDist)
{
smallestDist = dist;
closest = e;
}
}
}
}
}
}
luaReturnPtr(closest);
}
luaFunc(getNearestEntity)
{
Vector p(lua_tonumber(L, 1), lua_tonumber(L, 2));
int radius = lua_tointeger(L, 3);
Entity *ignore = lua_isuserdata(L, 4) ? entity(L, 4) : NULL;
EntityType et = lua_isnumber(L, 5) ? (EntityType)lua_tointeger(L, 5) : ET_NOTYPE;
DamageType dt = lua_isnumber(L, 6) ? (DamageType)lua_tointeger(L, 6) : DT_NONE;
int lrStart = lua_isnumber(L, 7) ? lua_tointeger(L, 7) : -1;
int lrEnd = lua_isnumber(L, 8) ? lua_tointeger(L, 8) : -1;
Entity *target = dsq->game->getNearestEntity(p, radius, ignore, ET_ENEMY, dt, lrStart, lrEnd);
luaReturnPtr(target);
}
luaFunc(findWall)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
int dirx = lua_tointeger(L, 3);
int diry = lua_tointeger(L, 4);
if (dirx == 0 && diry == 0){ debugLog("dirx && diry are zero!"); luaReturnNum(0); }
TileVector t(Vector(x, y));
while (!dsq->game->isObstructed(t))
{
t.x += dirx;
t.y += diry;
}
Vector v = t.worldVector();
int wall = 0;
if (diry != 0) wall = v.y;
if (dirx != 0) wall = v.x;
luaReturnNum(wall);
}
luaFunc(toggleVersionLabel)
{
bool on = getBool(L, 1);
dsq->toggleVersionLabel(on);
luaReturnBool(on);
}
luaFunc(setVersionLabelText)
{
dsq->setVersionLabelText();
luaReturnNil();
}
luaFunc(setCutscene)
{
dsq->setCutscene(getBool(L, 1), getBool(L, 2));
luaReturnNil();
}
luaFunc(isInCutscene)
{
luaReturnBool(dsq->isInCutscene());
}
luaFunc(toggleSteam)
{
bool on = getBool(L, 1);
for (Path *p = dsq->game->getFirstPathOfType(PATH_STEAM); p; p = p->nextOfType)
{
p->setActive(on);
}
luaReturnBool(on);
}
luaFunc(getFirstEntity)
{
luaReturnPtr(dsq->getFirstEntity());
}
luaFunc(getNextEntity)
{
luaReturnPtr(dsq->getNextEntity());
}
typedef std::pair<Entity*, float> EntityDistancePair;
static std::vector<EntityDistancePair> filteredEntities(20);
static int filteredEntityIdx = 0;
static bool _entityDistanceCmp(const EntityDistancePair& a, const EntityDistancePair& b)
{
return a.second < b.second;
}
static bool _entityDistanceEq(const EntityDistancePair& a, const EntityDistancePair& b)
{
return a.first == b.first;
}
static size_t _entityFilter(lua_State *L)
{
const Vector p(lua_tonumber(L, 1), lua_tonumber(L, 2));
const float radius = lua_tonumber(L, 3);
const Entity *ignore = lua_isuserdata(L, 4) ? entity(L, 4) : NULL;
const EntityType et = lua_isnumber(L, 5) ? (EntityType)lua_tointeger(L, 5) : ET_NOTYPE;
const DamageType dt = lua_isnumber(L, 6) ? (DamageType)lua_tointeger(L, 6) : DT_NONE;
const int lrStart = lua_isnumber(L, 7) ? lua_tointeger(L, 7) : -1;
const int lrEnd = lua_isnumber(L, 8) ? lua_tointeger(L, 8) : -1;
const float sqrRadius = radius * radius;
float distsq;
const bool skipLayerCheck = lrStart == -1 || lrEnd == -1;
const bool skipRadiusCheck = radius <= 0;
size_t added = 0;
FOR_ENTITIES(i)
{
Entity *e = *i;
distsq = (e->position - p).getSquaredLength2D();
if (skipRadiusCheck || distsq <= sqrRadius)
{
if (e != ignore && e->isPresent())
{
if (skipLayerCheck || (e->layer >= lrStart && e->layer <= lrEnd))
{
if (et == ET_NOTYPE || e->getEntityType() == et)
{
if (dt == DT_NONE || e->isDamageTarget(dt))
{
filteredEntities.push_back(std::make_pair(e, distsq));
++added;
}
}
}
}
}
}
if(added)
{
std::sort(filteredEntities.begin(), filteredEntities.end(), _entityDistanceCmp);
std::vector<EntityDistancePair>::iterator newend = std::unique(filteredEntities.begin(), filteredEntities.end(), _entityDistanceEq);
filteredEntities.resize(std::distance(filteredEntities.begin(), newend));
}
// Add terminator if there is none
if(filteredEntities.size() && filteredEntities.back().first)
filteredEntities.push_back(std::make_pair((Entity*)NULL, 0.0f)); // terminator
filteredEntityIdx = 0; // Reset getNextFilteredEntity() iteration index
return added;
}
luaFunc(filterNearestEntities)
{
filteredEntities.clear();
luaReturnInt(_entityFilter(L));
}
luaFunc(filterNearestEntitiesAdd)
{
// Remove terminator if there is one
if(filteredEntities.size() && !filteredEntities.back().first)
filteredEntities.pop_back();
luaReturnInt(_entityFilter(L));
}
luaFunc(getNextFilteredEntity)
{
EntityDistancePair ep = filteredEntities[filteredEntityIdx];
if (ep.first)
++filteredEntityIdx;
luaPushPointer(L, ep.first);
lua_pushnumber(L, ep.second);
return 2;
}
luaFunc(getEntity)
{
Entity *ent = 0;
// THIS WAS IMPORTANT: this was for getting entity by NUMBER IN LIST used for looping through all entities in script
if (lua_isnumber(L, 1))
{
//HACK: FIX:
// this has been disabled due to switching to list based entities
}
else if (lua_isstring(L, 1))
{
std::string s = lua_tostring(L, 1);
ent = dsq->getEntityByName(s);
}
luaReturnPtr(ent);
}
luaFunc(entity_partAlpha)
{
ScriptedEntity *e = scriptedEntity(L);
if (e)
{
RenderObject *r = e->partMap[getString(L, 2)];
if (r)
{
float start = lua_tonumber(L, 3);
if (start != -1)
r->alpha = start;
interpolateVec1(L, r->alpha, 4);
}
}
luaReturnNil();
}
luaFunc(entity_partBlendType)
{
ScriptedEntity *e = scriptedEntity(L);
if (e)
e->partMap[getString(L, 2)]->setBlendType(lua_tointeger(L, 3));
luaReturnNil();
}
luaFunc(entity_partRotate)
{
ScriptedEntity *e = scriptedEntity(L);
if (e)
{
RenderObject *r = e->partMap[getString(L, 2)];
if (r)
interpolateVec1z(L, r->rotation, 3);
}
luaReturnNil();
}
luaFunc(entity_getStateTime)
{
Entity *e = entity(L);
float t = 0;
if (e)
t = e->getStateTime();
luaReturnNum(t);
}
luaFunc(entity_setStateTime)
{
Entity *e = entity(L);
float t = lua_tonumber(L, 2);
if (e)
e->setStateTime(t);
luaReturnNum(t);
}
luaFunc(entity_offsetUpdate)
{
Entity *e = entity(L);
if (e)
{
float uc = e->updateCull;
e->updateCull = -1;
float t = float(rand()%10000)/1000.0f;
e->update(t);
e->updateCull = uc;
}
luaReturnNil();
}
// not to be confused with obj_setLayer or entity_setEntityLayer!!
luaFunc(entity_switchLayer)
{
Entity *e = entity(L);
if (e)
{
int lcode = lua_tointeger(L, 2);
int toLayer = LR_ENTITIES;
toLayer = dsq->getEntityLayerToLayer(lcode);
if (e->getEntityType() == ET_AVATAR)
toLayer = LR_ENTITIES;
core->switchRenderObjectLayer(e, toLayer);
}
luaReturnNil();
}
// entity numSegments segmentLength width texture
luaFunc(entity_initHair)
{
Entity *se = entity(L);
if (se)
{
se->initHair(lua_tonumber(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4), getString(L, 5));
}
luaReturnNil();
}
luaFunc(entity_getHair)
{
Entity *e = entity(L);
luaReturnPtr(e ? e->hair : NULL);
}
luaFunc(entity_clearHair)
{
Entity *e = entity(L);
if (e && e->hair)
{
e->hair->safeKill();
e->hair = 0;
}
luaReturnNil();
}
luaFunc(entity_getHairPosition)
{
Entity *se = entity(L);
float x=0;
float y=0;
int idx = lua_tointeger(L, 2);
if (se && se->hair)
{
HairNode *h = se->hair->getHairNode(idx);
if (h)
{
x = h->position.x;
y = h->position.y;
}
}
luaReturnVec2(x, y);
}
// entity x y z
luaFunc(entity_setHairHeadPosition)
{
Entity *se = entity(L);
if (se)
{
se->setHairHeadPosition(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)));
}
luaReturnNil();
}
luaFunc(entity_updateHair)
{
Entity *se = entity(L);
if (se)
{
se->updateHair(lua_tonumber(L, 2));
}
luaReturnNil();
}
// entity x y dt
luaFunc(entity_exertHairForce)
{
ScriptedEntity *se = scriptedEntity(L);
if (se)
{
if (se->hair)
se->hair->exertForce(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), lua_tonumber(L, 4), lua_tonumber(L, 5));
}
luaReturnNil();
}
luaFunc(entity_initPart)
{
std::string partName(getString(L, 2));
std::string partTex(getString(L, 3));
Vector partPosition(lua_tonumber(L, 4), lua_tonumber(L, 5));
bool renderAfter = getBool(L, 6);
bool partFlipH = getBool(L, 7);
bool partFlipV = getBool(L,8);
Vector offsetInterpolateTo(lua_tonumber(L, 9), lua_tonumber(L, 10));
float offsetInterpolateTime = lua_tonumber(L, 11);
ScriptedEntity *e = scriptedEntity(L);
if (e)
{
Quad *q = new Quad;
q->setTexture(partTex);
q->renderBeforeParent = !renderAfter;
q->position = partPosition;
if (offsetInterpolateTo.x != 0 || offsetInterpolateTo.y != 0)
q->offset.interpolateTo(offsetInterpolateTo, offsetInterpolateTime, -1, 1, 1);
if (partFlipH)
q->flipHorizontal();
if (partFlipV)
q->flipVertical();
e->addChild(q, PM_POINTER);
e->registerNewPart(q, partName);
}
luaReturnNil();
}
luaFunc(entity_findTarget)
{
Entity *e = entity(L);
if (e)
e->findTarget(lua_tointeger(L, 2), lua_tointeger(L, 3), e->currentEntityTarget);
luaReturnNil();
}
luaFunc(entity_doFriction)
{
Entity *e = entity(L);
if (e)
{
e->doFriction(lua_tonumber(L, 2), lua_tonumber(L, 3));
}
luaReturnNil();
}
luaFunc(entity_doGlint)
{
Entity *e = entity(L);
if (e)
e->doGlint(e->position, Vector(2,2), getString(L,2), (RenderObject::BlendTypes)lua_tointeger(L, 3));
luaReturnNil();
}
luaFunc(entity_getTarget)
{
Entity *e = entity(L);
Entity *retEnt = NULL;
if (e)
{
retEnt = e->getTargetEntity(lua_tonumber(L, 2));
}
luaReturnPtr(retEnt);
}
luaFunc(entity_getTargetPositionX)
{
Entity *e = entity(L);
luaReturnInt(e ? e->getTargetEntity()->position.x : 0);
}
luaFunc(entity_getTargetPositionY)
{
Entity *e = entity(L);
luaReturnNum(e ? e->getTargetEntity()->position.y : 0);
}
luaFunc(entity_isNearObstruction)
{
Entity *e = entity(L);
int sz = lua_tointeger(L, 2);
int type = lua_tointeger(L, 3);
bool v = false;
if (e)
{
v = e->isNearObstruction(sz, type);
}
luaReturnBool(v);
}
luaFunc(entity_isInvincible)
{
Entity *e = entity(L);
bool v = false;
if (e)
{
v = e->isInvincible();
}
luaReturnBool(v);
}
luaFunc(entity_setEatType)
{
Entity *e = entity(L);
int et = lua_tointeger(L, 2);
if (e)
e->setEatType((EatType)et, getString(L, 3));
luaReturnInt(et);
}
luaFunc(getMapName)
{
luaReturnStr(dsq->game->sceneName.c_str());
}
luaFunc(isMapName)
{
std::string s1 = dsq->game->sceneName;
std::string s2 = getString(L, 1);
stringToUpper(s1);
stringToUpper(s2);
bool ret = (s1 == s2);
luaReturnBool(ret);
}
luaFunc(mapNameContains)
{
std::string s = dsq->game->sceneName;
stringToLower(s);
bool b = (s.find(getString(L, 1)) != std::string::npos);
luaReturnBool(b);
}
luaFunc(entity_fireGas)
{
Entity *e = entity(L);
if (e)
{
int radius = lua_tointeger(L, 2);
float life = lua_tonumber(L, 3);
float damage = lua_tonumber(L, 4);
std::string gfx = getString(L, 5);
float colorx = lua_tonumber(L, 6);
float colory = lua_tonumber(L, 7);
float colorz = lua_tonumber(L, 8);
float offx = lua_tonumber(L, 9);
float offy = lua_tonumber(L, 10);
float poisonTime = lua_tonumber(L, 11);
GasCloud *c = new GasCloud(e, e->position + Vector(offx, offy), gfx, Vector(colorx, colory, colorz), radius, life, damage, false, poisonTime);
core->getTopStateData()->addRenderObject(c, LR_PARTICLES);
}
luaReturnNil();
}
luaFunc(isInputEnabled)
{
luaReturnBool(dsq->game->avatar->isInputEnabled());
}
luaFunc(enableInput)
{
dsq->game->avatar->enableInput();
luaReturnNil();
}
luaFunc(disableInput)
{
dsq->game->avatar->disableInput();
luaReturnNil();
}
luaFunc(getInputMode)
{
luaReturnInt(dsq->inputMode);
}
luaFunc(getJoystickAxisLeft)
{
Vector v;// = core->joystick.position;
assert(false); // FIXME
luaReturnVec2(v.x, v.y);
}
luaFunc(getJoystickAxisRight)
{
Vector v;// = core->joystick.rightStick;
assert(false); // FIXME
luaReturnVec2(v.x, v.y);
}
luaFunc(quit)
{
#ifdef AQUARIA_DEMO
dsq->nag(NAG_QUIT);
#else
dsq->quit();
#endif
luaReturnNil();
}
luaFunc(doModSelect)
{
dsq->doModSelect();
luaReturnNil();
}
luaFunc(doLoadMenu)
{
dsq->doLoadMenu();
luaReturnNil();
}
luaFunc(resetContinuity)
{
dsq->continuity.reset();
luaReturnNil();
}
luaFunc(toWindowFromWorld)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
x = x - core->screenCenter.x;
y = y - core->screenCenter.y;
x *= core->globalScale.x;
y *= core->globalScale.x;
x = 400+x;
y = 300+y;
luaReturnVec2(x, y);
}
luaFunc(setMousePos)
{
core->setMousePosition(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)));
luaReturnNil();
}
luaFunc(getMousePos)
{
luaReturnVec2(core->mouse.position.x, core->mouse.position.y);
}
luaFunc(getMouseWorldPos)
{
Vector v = dsq->getGameCursorPosition();
luaReturnVec2(v.x, v.y);
}
luaFunc(getMouseWheelChange)
{
luaReturnNum(core->mouse.scrollWheelChange);
}
luaFunc(setMouseConstraintCircle)
{
core->setMouseConstraintCircle(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(setMouseConstraint)
{
core->setMouseConstraint(getBool(L, 1));
luaReturnNil();
}
luaFunc(fade)
{
dsq->overlay->color.interpolateTo(Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)), lua_tonumber(L, 6));
dsq->overlay->alpha.interpolateTo(lua_tonumber(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(fade2)
{
dsq->overlay2->color.interpolateTo(Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)), lua_tonumber(L, 6));
dsq->overlay2->alpha.interpolateTo(lua_tonumber(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(fade3)
{
dsq->overlay3->color.interpolateTo(Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)), lua_tonumber(L, 6));
dsq->overlay3->alpha.interpolateTo(lua_tonumber(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(vision)
{
dsq->vision(getString(L, 1), lua_tonumber(L, 2), getBool(L, 3));
luaReturnNil();
}
luaFunc(musicVolume)
{
dsq->sound->setMusicFader(lua_tonumber(L, 1), lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(voice)
{
float vmod = lua_tonumber(L, 2);
if (vmod == 0)
vmod = -1;
else if (vmod == -1)
vmod = 0;
dsq->voice(getString(L, 1), vmod);
luaReturnNil();
}
luaFunc(voiceOnce)
{
dsq->voiceOnce(getString(L, 1));
luaReturnNil();
}
luaFunc(voiceInterupt)
{
dsq->voiceInterupt(getString(L, 1));
luaReturnNil();
}
luaFunc(stopVoice)
{
dsq->stopVoice();
luaReturnNil();
}
luaFunc(stopAllSfx)
{
dsq->sound->stopAllSfx();
luaReturnNil();
}
luaFunc(stopAllVoice)
{
dsq->sound->stopAllVoice();
luaReturnNil();
}
luaFunc(fadeIn)
{
dsq->overlay->alpha.interpolateTo(0, lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(fadeOut)
{
dsq->overlay->color = 0;
dsq->overlay->alpha.interpolateTo(1, lua_tonumber(L, 1));
luaReturnNil();
}
luaFunc(entity_setWeight)
{
CollideEntity *e = collideEntity(L);
if (e)
e->weight = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(entity_getWeight)
{
CollideEntity *e = collideEntity(L);
luaReturnNum(e ? e->weight : 0.0f);
}
luaFunc(pickupGem)
{
dsq->continuity.pickupGem(getString(L), !getBool(L, 2));
luaReturnInt(dsq->continuity.gems.size() - 1);
}
luaFunc(setGemPosition)
{
int gemId = lua_tointeger(L, 1);
std::string mapname = getString(L, 4);
if(mapname.empty())
mapname = dsq->game->sceneName;
Vector pos(lua_tonumber(L, 2), lua_tonumber(L, 3));
bool result = false;
WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(mapname);
if(tile)
{
pos = dsq->game->worldMapRender->getWorldToTile(tile, pos, true, true);
if(gemId >= 0 && gemId < dsq->continuity.gems.size())
{
Continuity::Gems::iterator it = dsq->continuity.gems.begin();
std::advance(it, gemId);
GemData& gem = *it;
gem.pos = pos;
gem.mapName = mapname;
result = true;
}
else
{
debugLog("setGemPosition: invalid index");
}
}
else
{
debugLog("setGemPosition: Map tile does not exist: " + mapname);
}
luaReturnBool(result);
}
luaFunc(setGemName)
{
int gemId = lua_tointeger(L, 1);
bool result = false;
if(gemId >= 0 && gemId < dsq->continuity.gems.size())
{
Continuity::Gems::iterator it = dsq->continuity.gems.begin();
std::advance(it, gemId);
GemData& gem = *it;
gem.name = getString(L, 2);
result = true;
}
else
debugLog("setGemName: invalid index");
luaReturnBool(result);
}
luaFunc(setGemBlink)
{
int gemId = lua_tointeger(L, 1);
bool result = false;
if(gemId >= 0 && gemId < dsq->continuity.gems.size())
{
Continuity::Gems::iterator it = dsq->continuity.gems.begin();
std::advance(it, gemId);
GemData& gem = *it;
gem.blink = getBool(L, 2);
result = true;
}
else
debugLog("setGemBlink: invalid index");
luaReturnBool(result);
}
luaFunc(removeGem)
{
int gemId = lua_tointeger(L, 1);
if(gemId >= 0 && gemId < dsq->continuity.gems.size())
{
Continuity::Gems::iterator it = dsq->continuity.gems.begin();
std::advance(it, gemId);
dsq->continuity.removeGemData(&(*it));
if(dsq->game->worldMapRender->isOn())
dsq->game->worldMapRender->fixGems();
}
luaReturnNil();
}
luaFunc(beaconEffect)
{
int index = lua_tointeger(L, 1);
BeaconData *b = dsq->continuity.getBeaconByIndex(index);
float p1 = 0.7f;
float p2 = 1.0f - p1;
dsq->clickRingEffect(dsq->game->miniMapRender->getWorldPosition(), 0, (b->color*p1) + Vector(p2, p2, p2), 1);
dsq->clickRingEffect(dsq->game->miniMapRender->getWorldPosition(), 1, (b->color*p1) + Vector(p2, p2, p2), 1);
dsq->sound->playSfx("ping");
luaReturnNil();
}
luaFunc(setBeacon)
{
int index = lua_tointeger(L, 1);
bool v = getBool(L, 2);
Vector pos;
pos.x = lua_tonumber(L, 3);
pos.y = lua_tonumber(L, 4);
Vector color;
color.x = lua_tonumber(L, 5);
color.y = lua_tonumber(L, 6);
color.z = lua_tonumber(L, 7);
dsq->continuity.setBeacon(index, v, pos, color);
luaReturnNil();
}
luaFunc(getBeacon)
{
int index = lua_tointeger(L, 1);
bool v = false;
if (dsq->continuity.getBeaconByIndex(index))
{
v = true;
}
luaReturnBool(v);
}
luaFunc(getCostume)
{
luaReturnStr(dsq->continuity.costume.c_str());
}
luaFunc(setCostume)
{
dsq->continuity.setCostume(getString(L));
luaReturnNil();
}
luaFunc(setLayerRenderPass)
{
int layer = lua_tointeger(L, 1);
int startPass = lua_tointeger(L, 2);
int endPass = lua_tointeger(L, 3);
if(layer >= 0 && layer < core->renderObjectLayers.size())
{
core->renderObjectLayers[layer].startPass = startPass;
core->renderObjectLayers[layer].endPass = endPass;
}
luaReturnNil();
}
luaFunc(setElementLayerVisible)
{
int l = lua_tointeger(L, 1);
bool v = getBool(L, 2);
dsq->game->setElementLayerVisible(l, v);
luaReturnNil();
}
luaFunc(isElementLayerVisible)
{
luaReturnBool(dsq->game->isElementLayerVisible(lua_tonumber(L, 1)));
}
luaFunc(isStreamingVoice)
{
bool v = dsq->sound->isPlayingVoice();
luaReturnBool(v);
}
luaFunc(isObstructed)
{
int obs = lua_tointeger(L, 3);
luaReturnBool(dsq->game->isObstructed(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2))), obs ? obs : -1));
}
luaFunc(isObstructedRaw)
{
int obs = lua_tointeger(L, 3);
luaReturnBool(dsq->game->isObstructedRaw(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2))), obs));
}
luaFunc(getObstruction)
{
luaReturnInt(dsq->game->getGrid(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)))));
}
luaFunc(getGridRaw)
{
luaReturnInt(dsq->game->getGridRaw(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)))));
}
luaFunc(isObstructedBlock)
{
float x = lua_tonumber(L, 1);
float y = lua_tonumber(L, 2);
int span = lua_tointeger(L, 3);
TileVector t(Vector(x,y));
bool obs = false;
for (int xx = t.x-span; xx <= t.x+span; xx++)
{
for (int yy = t.y-span; yy <= t.y+span; yy++)
{
if (dsq->game->isObstructed(TileVector(xx, yy)))
{
obs = true;
break;
}
}
}
luaReturnBool(obs);
}
luaFunc(node_getFlag)
{
Path *p = path(L);
int v = 0;
if (p)
{
v = dsq->continuity.getPathFlag(p);
}
luaReturnNum(v);
}
luaFunc(node_isFlag)
{
Path *p = path(L);
int c = lua_tointeger(L, 2);
bool ret = false;
if (p)
{
ret = (c == dsq->continuity.getPathFlag(p));
}
luaReturnBool(ret);
}
luaFunc(node_setFlag)
{
Path *p = path(L);
int v = lua_tointeger(L, 2);
if (p)
{
dsq->continuity.setPathFlag(p, v);
}
luaReturnNum(v);
}
luaFunc(entity_isFlag)
{
Entity *e = entity(L);
int v = lua_tointeger(L, 2);
bool b = false;
if (e)
{
b = (dsq->continuity.getEntityFlag(dsq->game->sceneName, e->getID())==v);
}
luaReturnBool(b);
}
luaFunc(entity_setFlag)
{
Entity *e = entity(L);
int v = lua_tointeger(L, 2);
if (e)
{
dsq->continuity.setEntityFlag(dsq->game->sceneName, e->getID(), v);
}
luaReturnNil();
}
luaFunc(entity_setPoison)
{
Entity *e = entity(L);
if(e)
e->setPoison(lua_tonumber(L, 2), lua_tonumber(L, 3));
luaReturnNil();
}
luaFunc(entity_getPoison)
{
Entity *e = entity(L);
luaReturnNum(e ? e->getPoison() : 0.0f);
}
luaFunc(entity_getFlag)
{
Entity *e = entity(L);
int ret = 0;
if (e)
{
ret = dsq->continuity.getEntityFlag(dsq->game->sceneName, e->getID());
}
luaReturnNum(ret);
}
luaFunc(isFlag)
{
int v = 0;
bool f = false;
if (lua_isnumber(L, 1))
{
v = dsq->continuity.getFlag(lua_tointeger(L, 1));
f = (v == lua_tointeger(L, 2));
}
else
{
v = dsq->continuity.getFlag(getString(L, 1));
f = (v == lua_tointeger(L, 2));
}
luaReturnBool(f);
}
luaFunc(avatar_updatePosition)
{
dsq->game->avatar->updatePosition();
luaReturnNil();
}
luaFunc(avatar_toggleMovement)
{
dsq->game->avatar->toggleMovement(getBool(L));
luaReturnNil();
}
luaFunc(clearShots)
{
Shot::killAllShots();
luaReturnNil();
}
luaFunc(clearHelp)
{
float t = 0.4;
RenderObjectLayer *rl = &core->renderObjectLayers[LR_HELP];
RenderObject *ro = rl->getFirst();
while (ro)
{
ro->setLife(t);
ro->setDecayRate(1);
ro->alpha.stopPath();
ro->alpha.interpolateTo(0,t-0.01f);
ro = rl->getNext();
}
luaReturnNil();
}
luaFunc(setLiPower)
{
float m = lua_tonumber(L, 1);
float t = lua_tonumber(L, 2);
dsq->continuity.setLiPower(m, t);
luaReturnNil();
}
luaFunc(getLiPower)
{
luaReturnNum(dsq->continuity.liPower);
}
luaFunc(getPetPower)
{
luaReturnNum(dsq->continuity.petPower);
}
luaFunc(appendUserDataPath)
{
std::string path = getString(L, 1);
if (!dsq->getUserDataFolder().empty())
path = dsq->getUserDataFolder() + "/" + path;
luaReturnStr(path.c_str());
}
luaFunc(getScreenVirtualOff)
{
luaReturnVec2(core->getVirtualOffX(), core->getVirtualOffY());
}
luaFunc(getScreenSize)
{
luaReturnVec2(core->width, core->height);
}
luaFunc(getScreenVirtualSize)
{
luaReturnVec2(core->getVirtualWidth(), core->getVirtualHeight());
}
luaFunc(isMiniMapCursorOkay)
{
luaReturnBool(dsq->isMiniMapCursorOkay());
}
luaFunc(isShuttingDownGameState)
{
luaReturnBool(dsq->game->isShuttingDownGameState());
}
static void _fillPathfindTables(lua_State *L, VectorPath& path, int xs_idx, int ys_idx)
{
const unsigned num = path.getNumPathNodes();
if(lua_istable(L, xs_idx))
lua_pushvalue(L, xs_idx);
else
lua_createtable(L, num, 0);
if(lua_istable(L, ys_idx))
lua_pushvalue(L, ys_idx);
else
lua_createtable(L, num, 0);
// [..., xs, yx]
for(unsigned i = 0; i < num; ++i)
{
const VectorPathNode *n = path.getPathNode(i);
lua_pushnumber(L, n->value.x); // [..., xs, ys, x]
lua_rawseti(L, -3, i+1); // [..., xs, ys]
lua_pushnumber(L, n->value.y); // [..., xs, ys, y]
lua_rawseti(L, -2, i+1); // [..., xs, ys]
}
// terminate tables
lua_pushnil(L); // [..., xs, ys, nil]
lua_rawseti(L, -3, num+1); // [..., xs, ys]
lua_pushnil(L); // [..., xs, ys, nil]
lua_rawseti(L, -2, num+1); // [..., xs, ys]
}
static int _pathfindDelete(lua_State *L)
{
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
PathFinding::deleteFindPath(state);
return 0;
}
// startx, starty, endx, endy [, step, xtab, ytab, obsMask]
luaFunc(findPath)
{
VectorPath path;
Vector start(lua_tonumber(L, 1), lua_tonumber(L, 2));
Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4));
ObsType obs = ObsType(lua_tointeger(L, 8));
if(!PathFinding::generatePathSimple(path, start, end, lua_tointeger(L, 5), obs))
luaReturnBool(false);
const unsigned num = path.getNumPathNodes();
lua_pushinteger(L, num);
_fillPathfindTables(L, path, 6, 7);
return 3; // found path?, x positions, y positions
}
luaFunc(createFindPath)
{
PathFinding::State **statep = (PathFinding::State**)lua_newuserdata(L, sizeof(void*));
*statep = PathFinding::initFindPath();
luaL_getmetatable(L, "pathfinder");
lua_setmetatable(L, -2);
return 1;
}
luaFunc(findPathBegin)
{
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
Vector start(lua_tonumber(L, 2), lua_tonumber(L, 3));
Vector end(lua_tonumber(L, 4), lua_tonumber(L, 5));
ObsType obs = ObsType(lua_tointeger(L, 6));
PathFinding::beginFindPath(state, start, end, obs);
luaReturnNil();
}
luaFunc(findPathUpdate)
{
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
int limit = lua_tointeger(L, 2);
bool done = PathFinding::updateFindPath(state, limit);
luaReturnBool(done);
}
luaFunc(findPathFinish)
{
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
VectorPath path;
bool found = PathFinding::finishFindPath(state, path, lua_tointeger(L, 2));
if(!found)
luaReturnBool(false);
lua_pushinteger(L, (int)path.getNumPathNodes());
_fillPathfindTables(L, path, 3, 4);
return 3;
}
luaFunc(findPathGetStats)
{
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
unsigned stepsDone, nodesExpanded;
PathFinding::getStats(state, stepsDone, nodesExpanded);
lua_pushinteger(L, stepsDone);
lua_pushinteger(L, nodesExpanded);
return 2;
}
luaFunc(findPathFreeMemory)
{
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
PathFinding::purgeFindPath(state);
luaReturnNil();
}
luaFunc(castLine)
{
Vector v(lua_tonumber(L, 1), lua_tonumber(L, 2));
Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4));
int tiletype = lua_tointeger(L, 5);
if(!tiletype)
tiletype = OT_BLOCKING;
bool invert = getBool(L, 6);
Vector step = end - v;
int steps = step.getLength2D() / TILE_SIZE;
step.setLength2D(TILE_SIZE);
if(!invert)
{
for(int i = 0; i < steps; ++i)
{
if(dsq->game->getGridRaw(TileVector(v)) & tiletype)
{
lua_pushinteger(L, dsq->game->getGrid(TileVector(v)));
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 3;
}
v += step;
}
}
else
{
for(int i = 0; i < steps; ++i)
{
if(!(dsq->game->getGridRaw(TileVector(v)) & tiletype))
{
lua_pushinteger(L, dsq->game->getGrid(TileVector(v)));
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 3;
}
v += step;
}
}
lua_pushboolean(L, false);
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 3;
}
luaFunc(getUserInputString)
{
luaReturnStr(dsq->getUserInputString(getString(L, 1), getString(L, 2), true).c_str());
}
luaFunc(getMaxCameraValues)
{
luaReturnVec4(dsq->game->cameraMin.x, dsq->game->cameraMin.y, dsq->game->cameraMax.x, dsq->game->cameraMax.y);
}
luaFunc(inv_isFull)
{
IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1));
bool full = false;
if(data)
full = dsq->continuity.isIngredientFull(data);
luaReturnBool(full);
}
luaFunc(inv_getMaxAmount)
{
IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1));
luaReturnInt(data ? data->maxAmount : 0);
}
luaFunc(inv_getAmount)
{
IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1));
luaReturnInt(data ? data->amount : 0);
}
luaFunc(inv_add)
{
IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1));
if(data)
dsq->continuity.pickupIngredient(data, lua_tointeger(L, 2), false, false);
luaReturnNil();
}
luaFunc(inv_getGfx)
{
luaReturnStr(dsq->continuity.getIngredientGfx(getString(L, 1)).c_str());
}
luaFunc(inv_remove)
{
IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1));
if(data && data->amount > 0)
{
data->amount--;
dsq->continuity.removeEmptyIngredients();
if(dsq->game->isInGameMenu())
dsq->game->getInGameMenu()->refreshFoodSlots(true);
}
luaReturnNil();
}
luaFunc(inv_getType)
{
IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1));
luaReturnInt(data ? data->type : 0);
}
luaFunc(inv_getDisplayName)
{
IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1));
luaReturnStr(data ? data->displayName.c_str() : "");
}
luaFunc(inv_pickupEffect)
{
IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1));
if(data)
dsq->game->pickupIngredientEffects(data);
luaReturnNil();
}
luaFunc(inv_getNumItems)
{
luaReturnInt(dsq->continuity.getIngredientHeldSize());
}
luaFunc(inv_getItemName)
{
IngredientData *data = dsq->continuity.getIngredientHeldByIndex(lua_tointeger(L, 1));
luaReturnStr(data ? data->name.c_str() : "");
}
luaFunc(getIngredientDataSize)
{
luaReturnInt(dsq->continuity.getIngredientDataSize());
}
luaFunc(getIngredientDataName)
{
IngredientData *data = dsq->continuity.getIngredientDataByIndex(lua_tointeger(L, 1));
luaReturnStr(data ? data->name.c_str() : "");
}
luaFunc(learnRecipe)
{
std::string name = getString(L, 1);
bool show = getBool(L, 2);
dsq->continuity.learnRecipe(name, show);
luaReturnNil();
}
luaFunc(setBGGradient)
{
if(!dsq->game->grad)
dsq->game->createGradient();
Vector c1(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tonumber(L, 3));
Vector c2(lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6));
if(getBool(L, 7))
dsq->game->grad->makeHorizontal(c1, c2);
else
dsq->game->grad->makeVertical(c1, c2);
luaReturnNil();
}
luaFunc(createDebugText)
{
DebugFont *txt = new DebugFont(lua_tointeger(L, 2), getString(L, 1));
txt->position = Vector(lua_tonumber(L, 3), lua_tonumber(L, 4));
dsq->game->addRenderObject(txt, LR_DEBUG_TEXT);
luaReturnPtr(txt);
}
luaFunc(createBitmapText)
{
BmpFont *font = &dsq->smallFont;
BitmapText *txt = new BitmapText(font);
txt->setText(getString(L, 1));
txt->setFontSize(lua_tointeger(L, 2));
txt->position = Vector(lua_tonumber(L, 3), lua_tonumber(L, 4));
dsq->game->addRenderObject(txt, LR_HUD);
luaReturnPtr(txt);
}
static int createArialText(lua_State *L, TTFFont *font)
{
TTFText *txt = new TTFText(font);
txt->setText(getString(L, 1));
//txt->setFontSize(lua_tointeger(L, 2)); // not supported; param is ignored for API compat with the create*Text functions
txt->position = Vector(lua_tonumber(L, 3), lua_tonumber(L, 4));
dsq->game->addRenderObject(txt, LR_HUD);
luaReturnPtr(txt);
}
luaFunc(createArialTextBig)
{
return createArialText(L, &dsq->fontArialBig);
}
luaFunc(createArialTextSmall)
{
return createArialText(L, &dsq->fontArialSmall);
}
luaFunc(text_setText)
{
BaseText *txt = getText(L);
if (txt)
txt->setText(getString(L, 2));
luaReturnNil();
}
luaFunc(text_setFontSize)
{
BaseText *txt = getText(L);
if (txt)
txt->setFontSize(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(text_setWidth)
{
BaseText *txt = getText(L);
if (txt)
txt->setWidth(lua_tonumber(L, 2));
luaReturnNil();
}
luaFunc(text_setAlign)
{
BaseText *txt = getText(L);
if (txt)
txt->setAlign((Align)lua_tointeger(L, 2));
luaReturnNil();
}
luaFunc(text_getHeight)
{
BaseText *txt = getText(L);
luaReturnNum(txt ? txt->getHeight() : 0.0f);
}
luaFunc(text_getLineHeight)
{
BaseText *txt = getText(L);
luaReturnNum(txt ? txt->getLineHeight() : 0.0f);
}
luaFunc(text_getNumLines)
{
BaseText *txt = getText(L);
luaReturnInt(txt ? txt->getNumLines() : 0);
}
luaFunc(text_getStringWidth)
{
BaseText *txt = getText(L);
luaReturnNum(txt ? txt->getStringWidth(getString(L, 2)) : 0.0f);
}
luaFunc(text_getActualWidth)
{
BaseText *txt = getText(L);
luaReturnNum(txt ? txt->getActualWidth() : 0.0f);
}
luaFunc(loadShader)
{
int handle = 0;
const char *vertRaw = getCString(L, 1);
const char *fragRaw = getCString(L, 2);
std::string vert, frag;
if(vertRaw)
findFile_helper(vertRaw, vert);
if(fragRaw)
findFile_helper(fragRaw, frag);
if(core->afterEffectManager)
handle = core->afterEffectManager->loadShaderFile(vert.c_str(), frag.c_str());
luaReturnInt(handle);
}
luaFunc(createShader)
{
int handle = 0;
if(core->afterEffectManager)
handle = core->afterEffectManager->loadShaderSrc(getCString(L, 1), getCString(L, 2));
luaReturnInt(handle);
}
luaFunc(shader_setAsAfterEffect)
{
int handle = lua_tointeger(L, 1);
int pos = lua_tointeger(L, 2);
bool done = false;
if(core->afterEffectManager)
done = core->afterEffectManager->setShaderPipelinePos(handle, pos);
luaReturnBool(done);
}
luaFunc(shader_setNumAfterEffects)
{
if(core->afterEffectManager)
core->afterEffectManager->setShaderPipelineSize(lua_tointeger(L, 1));
luaReturnNil();
}
luaFunc(shader_setInt)
{
if(core->afterEffectManager)
{
Shader *sh = core->afterEffectManager->getShaderPtr(lua_tointeger(L, 1));
const char *name = getCString(L, 2);
if(sh && name)
sh->setInt(name, lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5), lua_tointeger(L, 6));
}
luaReturnNil();
}
luaFunc(shader_setFloat)
{
if(core->afterEffectManager)
{
Shader *sh = core->afterEffectManager->getShaderPtr(lua_tointeger(L, 1));
const char *name = getCString(L, 2);
if(sh && name)
sh->setFloat(name, lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6));
}
luaReturnNil();
}
luaFunc(shader_delete)
{
if(core->afterEffectManager)
core->afterEffectManager->deleteShader(lua_tointeger(L, 1));
luaReturnNil();
}
luaFunc(pe_start)
{
ParticleEffect *pe = getParticle(L);
if (pe)
pe->start();
luaReturnNil();
}
luaFunc(pe_stop)
{
ParticleEffect *pe = getParticle(L);
if (pe)
pe->stop();
luaReturnNil();
}
luaFunc(pe_isRunning)
{
ParticleEffect *pe = getParticle(L);
luaReturnBool(pe && pe->isRunning());
}
luaFunc(getPerformanceCounter)
{
#ifdef BBGE_BUILD_SDL2
luaReturnNum((lua_Number)SDL_GetPerformanceCounter());
#else
luaReturnNum((lua_Number)SDL_GetTicks());
#endif
}
luaFunc(getPerformanceFreq)
{
#ifdef BBGE_BUILD_SDL2
luaReturnNum((lua_Number)SDL_GetPerformanceFrequency());
#else
luaReturnNum((lua_Number)1000);
#endif
}
// ---------- Minimap related ------------------
luaFunc(getMinimapRender)
{
luaReturnPtr(dsq->game->miniMapRender);
}
luaFunc(minimap_setWaterBitTex)
{
luaReturnBool(MiniMapRender::setWaterBitTex(getString(L)));
}
luaFunc(minimap_setTopTex)
{
luaReturnBool(MiniMapRender::setTopTex(getString(L)));
}
luaFunc(minimap_setBottomTex)
{
luaReturnBool(MiniMapRender::setBottomTex(getString(L)));
}
luaFunc(minimap_setAvatarIconTex)
{
luaReturnBool(MiniMapRender::setAvatarTex(getString(L)));
}
luaFunc(minimap_setHealthBarTex)
{
luaReturnBool(MiniMapRender::setAvatarTex(getString(L)));
}
luaFunc(minimap_setMaxHealthMarkerTex)
{
luaReturnBool(MiniMapRender::setMaxHealthMarkerTex(getString(L)));
}
template<typename T>
int mmicon_delete(lua_State *L, T *obj)
{
delete obj->minimapIcon;
obj->minimapIcon = NULL;
luaReturnNil();
}
template<typename T>
int mmicon_tex(lua_State *L, T *obj)
{
if(!obj)
luaReturnNil();
MinimapIcon *ico = obj->ensureMinimapIcon();
bool good = ico->setTexture(getString(L, 2));
luaReturnBool(good);
}
template<typename T>
int mmicon_size(lua_State *L, T *obj)
{
if(!obj)
luaReturnNil();
luaReturnNum(interpolateVec2(L, obj->ensureMinimapIcon()->size, 2));
}
template<typename T>
int mmicon_color(lua_State *L, T *obj)
{
if(!obj)
luaReturnNil();
luaReturnNum(interpolateVec3(L, obj->ensureMinimapIcon()->color, 2));
}
template<typename T>
int mmicon_alpha(lua_State *L, T *obj)
{
if(!obj)
luaReturnNil();
luaReturnNum(interpolateVec1(L, obj->ensureMinimapIcon()->alpha, 2));
}
template<typename T>
int mmicon_scaleWithDistance(lua_State *L, T *obj)
{
if(!obj)
luaReturnNil();
obj->ensureMinimapIcon()->scaleWithDistance = getBool(L, 2);
luaReturnNil();
}
template<typename T>
int mmicon_throb(lua_State *L, T *obj)
{
if(!obj)
luaReturnNil();
obj->ensureMinimapIcon()->throbMult = lua_tonumber(L, 2);
luaReturnNil();
}
luaFunc(entity_mmicon_delete) { return mmicon_delete(L, entity(L)); }
luaFunc(entity_mmicon_tex) { return mmicon_tex(L, entity(L)); }
luaFunc(entity_mmicon_size) { return mmicon_size(L, entity(L)); }
luaFunc(entity_mmicon_color) { return mmicon_color(L, entity(L)); }
luaFunc(entity_mmicon_alpha) { return mmicon_alpha(L, entity(L)); }
luaFunc(entity_mmicon_scaleWithDistance) { return mmicon_scaleWithDistance(L, entity(L)); }
luaFunc(entity_mmicon_throb) { return mmicon_throb(L, entity(L)); }
luaFunc(node_mmicon_delete) { return mmicon_delete(L, path(L)); }
luaFunc(node_mmicon_tex) { return mmicon_tex(L, path(L)); }
luaFunc(node_mmicon_size) { return mmicon_size(L, path(L)); }
luaFunc(node_mmicon_color) { return mmicon_color(L, path(L)); }
luaFunc(node_mmicon_alpha) { return mmicon_alpha(L, path(L)); }
luaFunc(node_mmicon_scaleWithDistance) { return mmicon_scaleWithDistance(L, path(L)); }
luaFunc(node_mmicon_throb) { return mmicon_throb(L, path(L)); }
class LuaXMLConverter : public tinyxml2::XMLVisitor
{
public:
LuaXMLConverter(lua_State *lua) : L(lua) {}
virtual ~LuaXMLConverter() {}
virtual bool VisitEnter( const tinyxml2::XMLDocument& /*doc*/ )
{
lua_newtable(L);
indexes.push_back(0);
return true;
}
virtual bool VisitExit( const tinyxml2::XMLDocument& /*doc*/ )
{
indexes.pop_back();
assert(indexes.empty());
// Leave the root table on the stack
return true;
}
virtual bool VisitEnter( const tinyxml2::XMLElement& element, const tinyxml2::XMLAttribute *a)
{
lua_newtable(L);
indexes.push_back(0);
if(a)
{
lua_newtable(L);
for( ; a; a = a->Next())
{
lua_pushstring(L, a->Value());
lua_setfield(L, -2, a->Name());
}
lua_setfield(L, -2, "attr");
}
if(const char *name = element.Value())
{
lua_pushstring(L, name);
lua_setfield(L, -2, "name");
}
if(const char *text = element.GetText())
{
lua_pushstring(L, text);
lua_setfield(L, -2, "text");
}
return true;
}
virtual bool VisitExit( const tinyxml2::XMLElement& /*element*/ )
{
indexes.pop_back();
lua_rawseti(L, -2, ++indexes.back());
return true;
}
protected:
std::vector<unsigned> indexes;
lua_State * const L;
};
luaFunc(loadXMLTable)
{
const std::string s = getString(L);
safePath(L, s);
std::string fn;
if(!findFile_helper(s.c_str(), fn))
luaReturnNil();
tinyxml2::XMLDocument xml;
tinyxml2::XMLError err = readXML(fn, xml);
if(err != tinyxml2::XML_NO_ERROR)
{
lua_pushboolean(L, false);
lua_pushinteger(L, err);
return 2;
}
LuaXMLConverter cvt(L);
xml.Accept(&cvt);
return 1;
}
//--------------------------------------------------------------------------------------------
#define luaRegister(func) {#func, l_##func}
static const struct {
const char *name;
lua_CFunction func;
} luaFunctionTable[] = {
// override Lua's standard dofile() and loadfile(), so we can handle filename case issues.
{"dofile", l_dofile_caseinsensitive},
{"loadfile", l_loadfile_caseinsensitive},
luaRegister(fileExists),
luaRegister(getModName),
luaRegister(getModPath),
luaRegister(getInterfaceFunctionNames),
luaRegister(debugBreak),
luaRegister(setIgnoreAction),
luaRegister(isIgnoreAction),
luaRegister(sendAction),
luaRegister(rumble),
luaRegister(shakeCamera),
luaRegister(upgradeHealth),
luaRegister(cureAllStatus),
luaRegister(setPoison),
luaRegister(setMusicToPlay),
luaRegister(confirm),
luaRegister(randRange),
luaRegister(flingMonkey),
luaRegister(setLiPower),
luaRegister(getLiPower),
luaRegister(getPetPower),
luaRegister(getTimer),
luaRegister(getHalfTimer),
luaRegister(getOldDT),
luaRegister(getDT),
luaRegister(getFPS),
luaRegister(setCostume),
luaRegister(getCostume),
luaRegister(getNoteName),
luaRegister(getWorldType),
luaRegister(setWorldType),
luaRegister(setWorldPaused),
luaRegister(isWorldPaused),
luaRegister(getWaterLevel),
luaRegister(setWaterLevel),
luaRegister(createQuad),
luaRegister(quad_setPauseLevel),
luaRegister(setupEntity),
luaRegister(setActivePet),
luaRegister(reconstructGrid),
luaRegister(reconstructEntityGrid),
luaRegister(dilateGrid),
luaRegister(ing_hasIET),
luaRegister(ing_getIngredientName),
luaRegister(esetv),
luaRegister(esetvf),
luaRegister(egetv),
luaRegister(egetvf),
luaRegister(eisv),
luaRegister(entity_addIgnoreShotDamageType),
luaRegister(entity_ensureLimit),
luaRegister(entity_getBoneLockEntity),
luaRegister(entity_getBoneLockData),
luaRegister(entity_setRidingPosition),
luaRegister(entity_setRidingData),
luaRegister(entity_getRidingPosition),
luaRegister(entity_getRidingRotation),
luaRegister(entity_getRidingFlip),
luaRegister(entity_setBoneLock),
luaRegister(entity_setIngredient),
luaRegister(entity_setDeathScene),
luaRegister(entity_isDeathScene),
luaRegister(entity_setBeautyFlip),
luaRegister(entity_setInvincible),
luaRegister(setInvincible),
luaRegister(entity_setLookAtPoint),
luaRegister(entity_getLookAtPoint),
luaRegister(entity_setDieTimer),
luaRegister(entity_setAutoSkeletalUpdate),
luaRegister(entity_updateSkeletal),
luaRegister(entity_setBounceType),
luaRegister(entity_getHealthPerc),
luaRegister(entity_getBounceType),
luaRegister(entity_setRiding),
luaRegister(entity_getRiding),
luaRegister(entity_setNaijaReaction),
luaRegister(entity_setEatType),
luaRegister(entity_setSpiritFreeze),
luaRegister(entity_setPauseFreeze),
luaRegister(node_setSpiritFreeze),
luaRegister(node_setPauseFreeze),
luaRegister(entity_setCanLeaveWater),
luaRegister(entity_pullEntities),
luaRegister(entity_setEntityLayer),
luaRegister(entity_clearTargetPoints),
luaRegister(entity_addTargetPoint),
luaRegister(entity_setCullRadius),
luaRegister(entity_switchLayer),
luaRegister(entity_debugText),
luaRegister(avatar_setCanDie),
luaRegister(setCanActivate),
luaRegister(setSeeMapMode),
luaRegister(avatar_toggleCape),
luaRegister(avatar_setPullTarget),
luaRegister(avatar_setCanLockToWall),
luaRegister(avatar_canLockToWall),
luaRegister(avatar_setCanBurst),
luaRegister(avatar_canBurst),
luaRegister(avatar_setCanSwimAgainstCurrents),
luaRegister(avatar_canSwimAgainstCurrents),
luaRegister(avatar_setCanCollideWithShots),
luaRegister(avatar_canCollideWithShots),
luaRegister(avatar_setCollisionAvoidanceData),
luaRegister(avatar_clampPosition),
luaRegister(avatar_updatePosition),
luaRegister(pause),
luaRegister(unpause),
luaRegister(isPaused),
luaRegister(isInGameMenu),
luaRegister(isInEditor),
luaRegister(vector_normalize),
luaRegister(vector_setLength),
luaRegister(vector_getLength),
luaRegister(vector_dot),
luaRegister(vector_isLength2DIn),
luaRegister(vector_cap),
luaRegister(entity_setDeathParticleEffect),
luaRegister(entity_setDeathSound),
luaRegister(entity_setDamageTarget),
luaRegister(entity_setAllDamageTargets),
luaRegister(entity_isDamageTarget),
luaRegister(entity_isValidTarget),
luaRegister(entity_isUnderWater),
luaRegister(entity_checkSplash),
luaRegister(entity_isInCurrent),
luaRegister(entity_getRandomTargetPoint),
luaRegister(entity_getTargetPoint),
luaRegister(entity_getNumTargetPoints),
luaRegister(entity_setTargetRange),
luaRegister(entity_getTargetRange),
luaRegister(bone_addSegment),
luaRegister(bone_setSegmentOffset),
luaRegister(bone_setSegmentProps),
luaRegister(bone_setSegmentChainHead),
luaRegister(bone_setAnimated),
luaRegister(bone_showFrame),
luaRegister(bone_lookAtEntity),
luaRegister(bone_lookAtPosition),
luaRegister(entity_partSetSegs),
luaRegister(entity_adjustPositionBySurfaceNormal),
luaRegister(entity_applySurfaceNormalForce),
luaRegister(entity_doElementInteraction),
luaRegister(avatar_setElementEffectMult),
luaRegister(createBeam),
luaRegister(beam_setAngle),
luaRegister(beam_setDamage),
luaRegister(beam_setBeamWidth),
luaRegister(beam_setFirer),
luaRegister(beam_setDamageType),
luaRegister(beam_getEndPos),
luaRegister(getStringBank),
luaRegister(isPlat),
luaRegister(createEntity),
luaRegister(entity_setWeight),
luaRegister(entity_getWeight),
luaRegister(entity_setActivationType),
luaRegister(isQuitFlag),
luaRegister(isDeveloperKeys),
luaRegister(isDemo),
luaRegister(isInputEnabled),
luaRegister(disableInput),
luaRegister(getInputMode),
luaRegister(getJoystickAxisLeft),
luaRegister(getJoystickAxisRight),
luaRegister(setMousePos),
luaRegister(getMousePos),
luaRegister(getMouseWorldPos),
luaRegister(getMouseWheelChange),
luaRegister(setMouseConstraintCircle),
luaRegister(setMouseConstraint),
luaRegister(resetContinuity),
luaRegister(quit),
luaRegister(doModSelect),
luaRegister(doLoadMenu),
luaRegister(enableInput),
luaRegister(fade),
luaRegister(fade2),
luaRegister(fade3),
luaRegister(getMapName),
luaRegister(isMapName),
luaRegister(mapNameContains),
luaRegister(entity_getAimVector),
luaRegister(entity_getVectorToEntity),
luaRegister(entity_getDistanceToTarget),
luaRegister(entity_getDistanceToPoint),
luaRegister(entity_move),
luaRegister(entity_getID),
luaRegister(getEntityByID),
luaRegister(entity_setBounce),
luaRegister(entity_setActivation),
luaRegister(entity_rotateToEntity),
luaRegister(entity_fireGas),
luaRegister(entity_rotateToTarget),
luaRegister(entity_switchSurfaceDirection),
luaRegister(entity_moveAlongSurface),
luaRegister(entity_rotateToSurfaceNormal),
luaRegister(entity_clampToSurface),
luaRegister(entity_checkSurface),
luaRegister(entity_clampToHit),
luaRegister(entity_grabTarget),
luaRegister(entity_releaseTarget),
luaRegister(entity_getStateTime),
luaRegister(entity_setStateTime),
luaRegister(entity_doFriction),
luaRegister(entity_partWidthHeight),
luaRegister(entity_partBlendType),
luaRegister(entity_partRotate),
luaRegister(entity_partAlpha),
luaRegister(entity_getHealth),
luaRegister(entity_getMaxHealth),
luaRegister(entity_pushTarget),
luaRegister(entity_getPushDamage),
luaRegister(entity_msg),
luaRegister(node_msg),
luaRegister(entity_updateMovement),
luaRegister(entity_updateCurrents),
luaRegister(entity_updateLocalWarpAreas),
luaRegister(entity_getTargetPositionX),
luaRegister(entity_getTargetPositionY),
luaRegister(avatar_incrLeaches),
luaRegister(avatar_decrLeaches),
luaRegister(entity_rotateToVel),
luaRegister(entity_rotateToVec),
luaRegister(entity_setSegsMaxDist),
luaRegister(entity_offsetUpdate),
luaRegister(entity_createEntity),
luaRegister(entity_resetTimer),
luaRegister(entity_stopTimer),
luaRegister(entity_stopPull),
luaRegister(entity_setTargetPriority),
luaRegister(entity_getTargetPriority),
luaRegister(entity_setEntityType),
luaRegister(entity_getEntityType),
luaRegister(entity_setSegmentTexture),
luaRegister(entity_spawnParticlesFromCollisionMask),
luaRegister(entity_initEmitter),
luaRegister(entity_startEmitter),
luaRegister(entity_stopEmitter),
luaRegister(entity_getEmitter),
luaRegister(entity_getNumEmitters),
luaRegister(entity_initPart),
luaRegister(entity_initSegments),
luaRegister(entity_warpSegments),
luaRegister(entity_initSkeletal),
luaRegister(entity_loadSkin),
luaRegister(entity_hasSkeletal),
luaRegister(entity_getNumAnimLayers),
luaRegister(entity_getSkeletalName),
luaRegister(entity_initStrands),
luaRegister(entity_hurtTarget),
luaRegister(entity_doSpellAvoidance),
luaRegister(entity_doEntityAvoidance),
luaRegister(entity_rotate),
luaRegister(entity_doGlint),
luaRegister(entity_findTarget),
luaRegister(entity_hasTarget),
luaRegister(entity_isInRect),
luaRegister(entity_isInDarkness),
luaRegister(entity_isRidingOnEntity),
luaRegister(entity_isBeingPulled),
luaRegister(entity_isNearObstruction),
luaRegister(entity_isDead),
luaRegister(entity_isTargetInRange),
luaRegister(entity_getDistanceToEntity),
luaRegister(entity_isEntityInside),
luaRegister(entity_isInvincible),
luaRegister(entity_isNearGround),
luaRegister(entity_moveTowardsTarget),
luaRegister(entity_moveAroundTarget),
luaRegister(entity_moveTowardsAngle),
luaRegister(entity_moveAroundAngle),
luaRegister(entity_moveTowards),
luaRegister(entity_moveAround),
luaRegister(entity_setMaxSpeed),
luaRegister(entity_getMaxSpeed),
luaRegister(entity_setMaxSpeedLerp),
luaRegister(entity_getMaxSpeedLerp),
luaRegister(entity_setState),
luaRegister(entity_getState),
luaRegister(entity_getEnqueuedState),
luaRegister(entity_getPrevState),
luaRegister(entity_doCollisionAvoidance),
luaRegister(entity_animate),
luaRegister(entity_setAnimLayerTimeMult),
luaRegister(entity_getAnimLayerTimeMult),
luaRegister(entity_stopAnimation),
luaRegister(entity_getAnimationLoop),
luaRegister(entity_setCurrentTarget),
luaRegister(entity_stopInterpolating),
luaRegister(entity_followPath),
luaRegister(entity_followPathSpeed),
luaRegister(entity_isFollowingPath),
luaRegister(entity_followEntity),
luaRegister(entity_sound),
luaRegister(entity_playSfx),
luaRegister(registerSporeDrop),
luaRegister(spawnIngredient),
luaRegister(spawnAllIngredients),
luaRegister(spawnParticleEffect),
luaRegister(spawnManaBall),
luaRegister(isEscapeKey),
luaRegister(resetTimer),
luaRegister(addInfluence),
luaRegister(setSuckPosition),
luaRegister(setSuckPosition),
luaRegister(setNumSuckPositions),
luaRegister(setupBasicEntity),
luaRegister(playMusic),
luaRegister(playMusicStraight),
luaRegister(stopMusic),
luaRegister(user_set_demo_intro),
luaRegister(user_save),
luaRegister(playMusicOnce),
luaRegister(playSfx),
luaRegister(fadeSfx),
luaRegister(emote),
luaRegister(playVisualEffect),
luaRegister(playNoEffect),
luaRegister(createShockEffect),
luaRegister(setOverrideMusic),
luaRegister(setOverrideVoiceFader),
luaRegister(setGameSpeed),
luaRegister(warpAvatar),
luaRegister(warpNaijaToSceneNode),
luaRegister(toWindowFromWorld),
luaRegister(toggleDamageSprite),
luaRegister(toggleLiCombat),
luaRegister(toggleCursor),
luaRegister(toggleBlackBars),
luaRegister(setBlackBarsColor),
luaRegister(entityFollowEntity),
luaRegister(bedEffects),
luaRegister(warpNaijaToEntity),
luaRegister(setNaijaHeadTexture),
luaRegister(setFlag),
luaRegister(getFlag),
luaRegister(setStringFlag),
luaRegister(getStringFlag),
luaRegister(learnSong),
luaRegister(unlearnSong),
luaRegister(hasSong),
luaRegister(hasLi),
luaRegister(setCanWarp),
luaRegister(setCanChangeForm),
luaRegister(setInvincibleOnNested),
luaRegister(setControlHint),
luaRegister(setCameraLerpDelay),
luaRegister(screenFadeGo),
luaRegister(screenFadeTransition),
luaRegister(screenFadeCapture),
luaRegister(clearControlHint),
luaRegister(savePoint),
luaRegister(saveMenu),
luaRegister(setSceneDisplayNameInSave),
luaRegister(wait),
luaRegister(watch),
luaRegister(quitNestedMain),
luaRegister(isNestedMain),
luaRegister(msg),
luaRegister(centerText),
luaRegister(watchForVoice),
luaRegister(setLayerRenderPass),
luaRegister(setElementLayerVisible),
luaRegister(isElementLayerVisible),
luaRegister(isWithin),
luaRegister(pickupGem),
luaRegister(setGemPosition),
luaRegister(setGemName),
luaRegister(setGemBlink),
luaRegister(removeGem),
luaRegister(setBeacon),
luaRegister(getBeacon),
luaRegister(beaconEffect),
luaRegister(chance),
luaRegister(goToTitle),
luaRegister(jumpState),
luaRegister(getEnqueuedState),
luaRegister(fadeIn),
luaRegister(fadeOut),
luaRegister(vision),
luaRegister(musicVolume),
luaRegister(voice),
luaRegister(voiceOnce),
luaRegister(voiceInterupt),
luaRegister(stopVoice),
luaRegister(stopAllVoice),
luaRegister(stopAllSfx),
luaRegister(fadeOutMusic),
luaRegister(isStreamingVoice),
luaRegister(changeForm),
luaRegister(getForm),
luaRegister(isForm),
luaRegister(learnFormUpgrade),
luaRegister(hasFormUpgrade),
luaRegister(singSong),
luaRegister(isObstructed),
luaRegister(isObstructedRaw),
luaRegister(isObstructedBlock),
luaRegister(getObstruction),
luaRegister(getGridRaw),
luaRegister(findPath),
luaRegister(createFindPath),
luaRegister(findPathBegin),
luaRegister(findPathUpdate),
luaRegister(findPathFinish),
luaRegister(findPathGetStats),
luaRegister(findPathFreeMemory),
luaRegister(castLine),
luaRegister(getUserInputString),
luaRegister(getMaxCameraValues),
luaRegister(isFlag),
luaRegister(entity_isFlag),
luaRegister(entity_setFlag),
luaRegister(entity_getFlag),
luaRegister(node_isFlag),
luaRegister(node_setFlag),
luaRegister(node_getFlag),
luaRegister(avatar_getStillTimer),
luaRegister(avatar_getSpellCharge),
luaRegister(avatar_isSinging),
luaRegister(avatar_isTouchHit),
luaRegister(avatar_isBursting),
luaRegister(avatar_isLockable),
luaRegister(avatar_isRolling),
luaRegister(avatar_isSwimming),
luaRegister(avatar_isOnWall),
luaRegister(avatar_isShieldActive),
luaRegister(avatar_setShieldActive),
luaRegister(avatar_getRollDirection),
luaRegister(avatar_fallOffWall),
luaRegister(avatar_setBlockSinging),
luaRegister(avatar_isBlockSinging),
luaRegister(avatar_setBlockBackflip),
luaRegister(avatar_isBlockBackflip),
luaRegister(avatar_setSpeedMult),
luaRegister(avatar_setSpeedMult2),
luaRegister(avatar_getSpeedMult),
luaRegister(avatar_getSpeedMult2),
luaRegister(avatar_toggleMovement),
luaRegister(showInGameMenu),
luaRegister(hideInGameMenu),
luaRegister(showImage),
luaRegister(hideImage),
luaRegister(clearHelp),
luaRegister(clearShots),
luaRegister(getEntity),
luaRegister(getFirstEntity),
luaRegister(getNextEntity),
luaRegister(filterNearestEntities),
luaRegister(filterNearestEntitiesAdd),
luaRegister(getNextFilteredEntity),
luaRegister(setStory),
luaRegister(getStory),
luaRegister(getNoteColor),
luaRegister(getNoteVector),
luaRegister(getRandNote),
luaRegister(foundLostMemory),
luaRegister(isStory),
luaRegister(entity_damage),
luaRegister(entity_heal),
luaRegister(getNearestIngredient),
luaRegister(getNearestNodeByType),
luaRegister(getNode),
luaRegister(getNodeToActivate),
luaRegister(setNodeToActivate),
luaRegister(getEntityToActivate),
luaRegister(setEntityToActivate),
luaRegister(hasThingToActivate),
luaRegister(setActivation),
luaRegister(entity_warpToNode),
luaRegister(entity_moveToNode),
luaRegister(entity_moveToNodeSpeed),
luaRegister(cam_toNode),
luaRegister(cam_snap),
luaRegister(cam_toEntity),
luaRegister(cam_setPosition),
luaRegister(entity_flipToEntity),
luaRegister(entity_flipToSame),
luaRegister(entity_flipToNode),
luaRegister(entity_flipToVel),
luaRegister(entity_swimToNode),
luaRegister(entity_swimToNodeSpeed),
luaRegister(entity_swimToPosition),
luaRegister(entity_swimToPositionSpeed),
luaRegister(createShot),
luaRegister(entity_isHit),
luaRegister(createWeb),
luaRegister(web_addPoint),
luaRegister(web_setPoint),
luaRegister(web_getNumPoints),
luaRegister(createSpore),
luaRegister(getFirstShot),
luaRegister(getNextShot),
luaRegister(shot_setAimVector),
luaRegister(shot_setOut),
luaRegister(shot_getEffectTime),
luaRegister(shot_isIgnoreShield),
luaRegister(shot_setFirer),
luaRegister(shot_getFirer),
luaRegister(shot_setTarget),
luaRegister(shot_getTarget),
luaRegister(shot_setExtraDamage),
luaRegister(shot_getExtraDamage),
luaRegister(shot_getDamage),
luaRegister(shot_getDamageType),
luaRegister(shot_getName),
luaRegister(shot_getMaxSpeed),
luaRegister(shot_setMaxSpeed),
luaRegister(shot_getHomingness),
luaRegister(shot_setHomingness),
luaRegister(shot_getLifeTime),
luaRegister(shot_setLifeTime),
luaRegister(shot_setDamageType),
luaRegister(shot_setCheckDamageTarget),
luaRegister(shot_isCheckDamageTarget),
luaRegister(shot_setTrailPrt),
luaRegister(shot_setTargetPoint),
luaRegister(shot_getTargetPoint),
luaRegister(shot_canHitEntity),
luaRegister(filterNearestShots),
luaRegister(filterNearestShotsAdd),
luaRegister(getNextFilteredShot),
luaRegister(entity_pathBurst),
luaRegister(entity_handleShotCollisions),
luaRegister(entity_handleShotCollisionsSkeletal),
luaRegister(entity_handleShotCollisionsHair),
luaRegister(entity_collideSkeletalVsCircle),
luaRegister(entity_collideSkeletalVsCirclePos),
luaRegister(entity_collideSkeletalVsLine),
luaRegister(entity_collideSkeletalVsCircleForListByName),
luaRegister(entity_collideCircleVsLine),
luaRegister(entity_collideCircleVsLineAngle),
luaRegister(entity_collideHairVsCircle),
luaRegister(entity_setDropChance),
luaRegister(entity_waitForPath),
luaRegister(entity_watchForPath),
luaRegister(entity_revive),
luaRegister(entity_getTarget),
luaRegister(entity_isState),
luaRegister(entity_setProperty),
luaRegister(entity_isProperty),
luaRegister(entity_initHair),
luaRegister(entity_getHairPosition),
luaRegister(entity_getHair),
luaRegister(entity_clearHair),
luaRegister(entity_setHairHeadPosition),
luaRegister(entity_updateHair),
luaRegister(entity_exertHairForce),
luaRegister(entity_setName),
luaRegister(getNumberOfEntitiesNamed),
luaRegister(isNested),
luaRegister(isSkippingCutscene),
luaRegister(entity_idle),
luaRegister(entity_stopAllAnimations),
luaRegister(entity_getBoneByIdx),
luaRegister(entity_getBoneByName),
luaRegister(entity_getBoneByInternalId),
luaRegister(entity_getNumBones),
luaRegister(toggleInput),
luaRegister(entity_setTarget),
luaRegister(getScreenCenter),
luaRegister(debugLog),
luaRegister(errorLog),
luaRegister(loadMap),
luaRegister(loadSound),
luaRegister(node_activate),
luaRegister(node_getName),
luaRegister(node_getLabel),
luaRegister(node_getPathPosition),
luaRegister(node_getPosition),
luaRegister(node_setPosition),
luaRegister(node_getContent),
luaRegister(node_getAmount),
luaRegister(node_getSize),
luaRegister(node_getShape),
luaRegister(toggleSteam),
luaRegister(toggleVersionLabel),
luaRegister(setVersionLabelText),
luaRegister(appendUserDataPath),
luaRegister(setCutscene),
luaRegister(isInCutscene),
luaRegister(node_getNumEntitiesIn),
luaRegister(entity_getName),
luaRegister(entity_isName),
luaRegister(node_setActivationRange),
luaRegister(node_setCursorActivation),
luaRegister(node_setCatchActions),
luaRegister(node_setElementsInLayerActive),
luaRegister(entity_setHealth),
luaRegister(entity_setCurrentHealth),
luaRegister(entity_setMaxHealth),
luaRegister(entity_changeHealth),
luaRegister(node_setActive),
luaRegister(node_isActive),
luaRegister(node_setEmitter),
luaRegister(node_getEmitter),
luaRegister(setSceneColor),
luaRegister(getSceneColor),
luaRegister(setSceneColor2),
luaRegister(getSceneColor2),
luaRegister(entity_watchEntity),
luaRegister(entity_isEntityInRange),
luaRegister(entity_isPositionInRange),
luaRegister(entity_stopFollowingPath),
luaRegister(entity_slowToStopPath),
luaRegister(entity_isSlowingToStopPath),
luaRegister(entity_findNearestEntityOfType),
luaRegister(entity_isFollowingEntity),
luaRegister(entity_resumePath),
luaRegister(entity_generateCollisionMask),
luaRegister(entity_isAnimating),
luaRegister(entity_getAnimationName),
luaRegister(entity_getAnimationLength),
luaRegister(entity_hasAnimation),
luaRegister(entity_setCull),
luaRegister(entity_setFillGrid),
luaRegister(entity_isFillGrid),
luaRegister(entity_push),
luaRegister(entity_alpha),
luaRegister(findWall),
luaRegister(overrideZoom),
luaRegister(disableOverrideZoom),
luaRegister(getZoom),
luaRegister(setMaxLookDistance),
luaRegister(spawnAroundEntity),
luaRegister(entity_toggleBone),
luaRegister(bone_getName),
luaRegister(bone_isName),
luaRegister(bone_getIndex),
luaRegister(node_x),
luaRegister(node_y),
luaRegister(node_isEntityPast),
luaRegister(node_isEntityInRange),
luaRegister(node_isPositionIn),
luaRegister(entity_warpLastPosition),
luaRegister(entity_setVel),
luaRegister(entity_setVelLen),
luaRegister(entity_getVelLen),
luaRegister(entity_getVel),
luaRegister(entity_velx),
luaRegister(entity_vely),
luaRegister(entity_addVel),
luaRegister(entity_addRandomVel),
luaRegister(entity_isVelIn),
luaRegister(entity_clearVel),
luaRegister(entity_velTowards),
luaRegister(entity_setVel2),
luaRegister(entity_setVel2Len),
luaRegister(entity_getVel2Len),
luaRegister(entity_addVel2),
luaRegister(entity_getVel2),
luaRegister(entity_clearVel2),
luaRegister(entity_getPushVec),
luaRegister(updateMusic),
luaRegister(entity_touchAvatarDamage),
luaRegister(getNaija),
luaRegister(getLi),
luaRegister(setLi),
luaRegister(randAngle360),
luaRegister(randVector),
luaRegister(entity_getNearestEntity),
luaRegister(entity_getNearestBoneToPosition),
luaRegister(getNearestEntity),
luaRegister(entity_getNearestNode),
luaRegister(entity_setPoison),
luaRegister(entity_getPoison),
luaRegister(node_getNearestEntity),
luaRegister(node_getNearestNode),
luaRegister(node_isEntityIn),
luaRegister(isLeftMouse),
luaRegister(isRightMouse),
luaRegister(setTimerTextAlpha),
luaRegister(setTimerText),
luaRegister(getWallNormal),
luaRegister(getLastCollidePosition),
luaRegister(getLastCollideTileType),
luaRegister(collideCircleWithGrid),
luaRegister(getScreenVirtualOff),
luaRegister(getScreenSize),
luaRegister(getScreenVirtualSize),
luaRegister(isMiniMapCursorOkay),
luaRegister(isShuttingDownGameState),
luaRegister(setBGGradient),
luaRegister(inv_isFull),
luaRegister(inv_getMaxAmount),
luaRegister(inv_getAmount),
luaRegister(inv_add),
luaRegister(inv_getGfx),
luaRegister(inv_remove),
luaRegister(inv_getType),
luaRegister(inv_getDisplayName),
luaRegister(inv_pickupEffect),
luaRegister(inv_getNumItems),
luaRegister(inv_getItemName),
luaRegister(learnRecipe),
luaRegister(getIngredientDataSize),
luaRegister(getIngredientDataName),
luaRegister(createDebugText),
luaRegister(createBitmapText),
luaRegister(createArialTextBig),
luaRegister(createArialTextSmall),
luaRegister(text_setText),
luaRegister(text_setFontSize),
luaRegister(text_setWidth),
luaRegister(text_setAlign),
luaRegister(text_getHeight),
luaRegister(text_getStringWidth),
luaRegister(text_getActualWidth),
luaRegister(text_getLineHeight),
luaRegister(text_getNumLines),
luaRegister(loadShader),
luaRegister(createShader),
luaRegister(shader_setAsAfterEffect),
luaRegister(shader_setNumAfterEffects),
luaRegister(shader_setFloat),
luaRegister(shader_setInt),
luaRegister(shader_delete),
luaRegister(pe_start),
luaRegister(pe_stop),
luaRegister(pe_isRunning),
luaRegister(isQuad),
luaRegister(isNode),
luaRegister(isObject),
luaRegister(isEntity),
luaRegister(isScriptedEntity),
luaRegister(isBone),
luaRegister(isShot),
luaRegister(isWeb),
luaRegister(isIng),
luaRegister(isBeam),
luaRegister(isText),
luaRegister(isShader),
luaRegister(isParticleEffect),
luaRegister(getPerformanceCounter),
luaRegister(getPerformanceFreq),
luaRegister(getMinimapRender),
luaRegister(minimap_setWaterBitTex),
luaRegister(minimap_setTopTex),
luaRegister(minimap_setBottomTex),
luaRegister(minimap_setAvatarIconTex),
luaRegister(minimap_setHealthBarTex),
luaRegister(entity_mmicon_delete),
luaRegister(entity_mmicon_tex),
luaRegister(entity_mmicon_size),
luaRegister(entity_mmicon_color),
luaRegister(entity_mmicon_alpha),
luaRegister(entity_mmicon_scaleWithDistance),
luaRegister(entity_mmicon_throb),
luaRegister(node_mmicon_delete),
luaRegister(node_mmicon_tex),
luaRegister(node_mmicon_size),
luaRegister(node_mmicon_color),
luaRegister(node_mmicon_alpha),
luaRegister(node_mmicon_scaleWithDistance),
luaRegister(node_mmicon_throb),
luaRegister(loadXMLTable),
#undef MK_FUNC
#undef MK_ALIAS
#define MK_FUNC(base, getter, prefix, suffix) luaRegister(prefix##_##suffix),
#define MK_STR(s) #s
#define MK_ALIAS(prefix, suffix, alias) {MK_STR(prefix)"_"MK_STR(alias), l_##prefix##_##suffix},
EXPAND_FUNC_PROTOTYPES
// obj_* are not in the define above
MAKE_ROBJ_FUNCS(_, obj)
// same for quad_* base functions
MAKE_QUAD_FUNCS(_, quad)
// -- overrides / special cases--
{"bone_getPosition", l_bone_getWorldPosition},
{ "entity_delete", l_entity_delete_override },
{ "entity_setRenderPass", l_entity_setRenderPass_override },
{ "beam_setPosition", l_beam_setPosition_override },
// -- deprecated/compatibility related functions below here --
{"entity_incrTargetLeaches", l_avatar_incrLeaches},
{"entity_decrTargetLeaches", l_avatar_decrLeaches},
{"entity_soundFreq", l_entity_sound},
{"entity_interpolateTo", l_entity_setPosition},
{"entity_isFlippedHorizontal", l_entity_isfh},
{"entity_isFlippedVertical", l_entity_isfv},
{"entity_rotateTo", l_entity_rotate},
{"entity_setColor", l_entity_color},
{"entity_setInternalOffset", l_entity_internalOffset},
{"getIngredientGfx", l_inv_getGfx},
{"bone_setColor", l_bone_color},
{"node_setEffectOn", l_node_setActive},
{"node_isEffectOn", l_node_isActive},
};
//============================================================================================
// S C R I P T C O N S T A N T S
//============================================================================================
#define luaConstant(name) {#name, name}
#define luaConstantFromClass(name,class) {#name, class::name}
static const struct {
const char *name;
lua_Number value;
} luaConstantTable[] = {
{"AQUARIA_VERSION", VERSION_MAJOR*10000 + VERSION_MINOR*100 + VERSION_REVISION},
// emotes
luaConstant(EMOTE_NAIJAEVILLAUGH),
luaConstant(EMOTE_NAIJAGIGGLE),
luaConstant(EMOTE_NAIJALAUGH),
luaConstant(EMOTE_NAIJASADSIGH),
luaConstant(EMOTE_NAIJASIGH),
luaConstant(EMOTE_NAIJAWOW),
luaConstant(EMOTE_NAIJAUGH),
luaConstant(EMOTE_NAIJALOW),
luaConstant(EMOTE_NAIJALI),
{"EMOTE_NAIJAEW", 9}, // FIXME: unused
// Li expressions
{"EXPRESSION_NORMAL", 0},
{"EXPRESSION_ANGRY", 1},
{"EXPRESSION_HAPPY", 2},
{"EXPRESSION_HURT", 3},
{"EXPRESSION_LAUGH", 4},
{"EXPRESSION_SURPRISE", 5},
luaConstantFromClass(OVERRIDE_NONE, RenderObject),
//actions
luaConstant(ACTION_MENULEFT),
luaConstant(ACTION_MENURIGHT),
luaConstant(ACTION_MENUUP),
luaConstant(ACTION_MENUDOWN),
{"WATCH_QUIT", 1},
{"BEACON_HOMECAVE", 1},
{"BEACON_ENERGYTEMPLE", 2},
{"BEACON_MITHALAS", 3},
{"BEACON_FOREST", 4},
{"BEACON_LI", 5},
{"BEACON_SUNTEMPLE", 6},
{"BEACON_SONGCAVE", 7},
{"PLAT_WIN", 0},
{"PLAT_MAC", 1},
{"PLAT_LNX", 2},
// ingredient effect types
luaConstant(IET_NONE),
luaConstant(IET_HP),
luaConstant(IET_DEFENSE),
luaConstant(IET_SPEED),
luaConstant(IET_RANDOM),
luaConstant(IET_MAXHP),
luaConstant(IET_INVINCIBLE),
luaConstant(IET_TRIP),
luaConstant(IET_REGEN),
luaConstant(IET_LI),
luaConstant(IET_FISHPOISON),
luaConstant(IET_BITE),
luaConstant(IET_EAT),
luaConstant(IET_LIGHT),
luaConstant(IET_YUM),
luaConstant(IET_PETPOWER),
luaConstant(IET_WEB),
luaConstant(IET_ENERGY),
luaConstant(IET_POISON),
luaConstant(IET_BLIND),
luaConstant(IET_ALLSTATUS),
luaConstant(IET_MAX),
// menu pages
luaConstant(MENUPAGE_NONE),
luaConstant(MENUPAGE_SONGS),
luaConstant(MENUPAGE_FOOD),
luaConstant(MENUPAGE_TREASURES),
luaConstant(MENUPAGE_PETS),
// Entity States
luaConstantFromClass(STATE_DEAD, Entity),
luaConstantFromClass(STATE_IDLE, Entity),
luaConstantFromClass(STATE_PUSH, Entity),
luaConstantFromClass(STATE_PUSHDELAY, Entity),
luaConstantFromClass(STATE_PLANTED, Entity),
luaConstantFromClass(STATE_PULLED, Entity),
luaConstantFromClass(STATE_FOLLOWNAIJA, Entity),
luaConstantFromClass(STATE_DEATHSCENE, Entity),
luaConstantFromClass(STATE_ATTACK, Entity),
luaConstantFromClass(STATE_CHARGE0, Entity),
luaConstantFromClass(STATE_CHARGE1, Entity),
luaConstantFromClass(STATE_CHARGE2, Entity),
luaConstantFromClass(STATE_CHARGE3, Entity),
luaConstantFromClass(STATE_WAIT, Entity),
luaConstantFromClass(STATE_HUG, Entity),
luaConstantFromClass(STATE_EATING, Entity),
luaConstantFromClass(STATE_FOLLOW, Entity),
luaConstantFromClass(STATE_TITLE, Entity),
// Remainder are script-specific, not used by C++ code
{"STATE_HATCH", 25},
{"STATE_CARRIED", 26},
{"STATE_HOSTILE", 100},
{"STATE_CLOSE", 200},
{"STATE_OPEN", 201},
{"STATE_CLOSED", 202},
{"STATE_OPENED", 203},
{"STATE_CHARGED", 300},
{"STATE_INHOLDER", 301},
{"STATE_DISABLED", 302},
{"STATE_FLICKER", 303},
{"STATE_ACTIVE", 304},
{"STATE_USED", 305},
{"STATE_BLOATED", 306},
{"STATE_DELAY", 307},
{"STATE_DONE", 309},
{"STATE_RAGE", 310},
{"STATE_CALM", 311},
{"STATE_DESCEND", 312},
{"STATE_SING", 313},
{"STATE_TRANSFORM", 314},
{"STATE_GROW", 315},
{"STATE_MATING", 316},
{"STATE_SHRINK", 317},
{"STATE_MOVE", 319},
{"STATE_TRANSITION", 320},
{"STATE_TRANSITION2", 321},
{"STATE_TRAPPEDINCREATOR", 322},
{"STATE_GRAB", 323},
{"STATE_FIGURE", 324},
{"STATE_CUTSCENE", 325},
{"STATE_WAITFORCUTSCENE", 326},
{"STATE_FIRE", 327},
{"STATE_FIRING", 328},
{"STATE_PREP", 329},
{"STATE_INTRO", 330},
{"STATE_PUPPET", 331},
{"STATE_COLLECT", 400},
{"STATE_COLLECTED", 401},
{"STATE_COLLECTEDINHOUSE", 402},
//{"STATE_ATTACK"}, 500},
{"STATE_STEP", 501},
{"STATE_AWAKEN", 502},
{"STATE_WEAK", 600},
{"STATE_BREAK", 601},
{"STATE_BROKEN", 602},
{"STATE_PULSE", 700},
{"STATE_ON", 701},
{"STATE_OFF", 702},
{"STATE_SEED", 703},
{"STATE_PLANTED", 704},
{"STATE_SK_RED", 705},
{"STATE_SK_GREEN", 706},
{"STATE_SK_BLUE", 707},
{"STATE_SK_YELLOW", 708},
{"STATE_WAITFORKISS", 710},
{"STATE_KISS", 711},
{"STATE_START", 712},
{"STATE_RACE", 714},
{"STATE_RESTART", 715},
{"STATE_APPEAR", 716},
{"STATE_MOVETOWEED", 2000},
{"STATE_PULLWEED", 2001},
{"STATE_DONEWEED", 2002},
{"ORIENT_NONE", -1},
{"ORIENT_LEFT", 0},
{"ORIENT_RIGHT", 1},
{"ORIENT_UP", 2},
{"ORIENT_DOWN", 3},
{"ORIENT_HORIZONTAL", 4},
{"ORIENT_VERTICAL", 5},
// for entity_isNearObstruction
luaConstant(OBSCHECK_RANGE),
luaConstant(OBSCHECK_4DIR),
luaConstant(OBSCHECK_DOWN),
luaConstant(OBSCHECK_8DIR),
luaConstant(EV_WALLOUT),
luaConstant(EV_WALLTRANS),
luaConstant(EV_CLAMPING),
luaConstant(EV_SWITCHCLAMP),
luaConstant(EV_CLAMPTRANSF),
luaConstant(EV_MOVEMENT),
luaConstant(EV_COLLIDE),
luaConstant(EV_TOUCHDMG),
luaConstant(EV_FRICTION),
luaConstant(EV_LOOKAT),
luaConstant(EV_CRAWLING),
luaConstant(EV_ENTITYDIED),
luaConstant(EV_TYPEID),
luaConstant(EV_COLLIDELEVEL),
luaConstant(EV_BONELOCKED),
luaConstant(EV_FLIPTOPATH),
luaConstant(EV_NOINPUTNOVEL),
luaConstant(EV_VINEPUSH),
luaConstant(EV_BEASTBURST),
luaConstant(EV_MINIMAP),
luaConstant(EV_SOULSCREAMRADIUS),
luaConstant(EV_WEBSLOW),
luaConstant(EV_NOAVOID),
luaConstant(EV_MAX),
{"EVT_NONE", 0},
{"EVT_THERMALVENT", 1},
{"EVT_GLOBEJELLY", 2},
{"EVT_CELLWHITE", 3},
{"EVT_CELLRED", 4},
{"EVT_PET", 5},
{"EVT_DARKLISHOT", 6},
{"EVT_ROCK", 7},
{"EVT_FORESTGODVINE", 8},
{"EVT_CONTAINER", 9},
{"EVT_PISTOLSHRIMP", 10},
{"EVT_GATEWAYMUTANT", 11},
// PATH/node types
luaConstant(PATH_NONE),
luaConstant(PATH_CURRENT),
luaConstant(PATH_STEAM),
luaConstant(PATH_LI),
luaConstant(PATH_SAVEPOINT),
luaConstant(PATH_WARP),
luaConstant(PATH_SPIRITPORTAL),
luaConstant(PATH_BGSFXLOOP),
luaConstant(PATH_RADARHIDE),
luaConstant(PATH_COOK),
luaConstant(PATH_WATERBUBBLE),
luaConstant(PATH_GEM),
luaConstant(PATH_SETING),
luaConstant(PATH_SETENT),
// Entity Types
luaConstant(ET_AVATAR),
luaConstant(ET_ENEMY),
luaConstant(ET_PET),
luaConstant(ET_FLOCK),
luaConstant(ET_NEUTRAL),
luaConstant(ET_INGREDIENT),
luaConstant(EP_SOLID),
luaConstant(EP_MOVABLE),
luaConstant(EP_BATTERY),
luaConstant(EP_BLOCKER),
// ACTIVATION TYPES
{"AT_NONE", -1},
{"AT_NORMAL", 0},
{"AT_CLICK", 0},
{"AT_RANGE", 1},
luaConstant(WT_NORMAL),
luaConstant(WT_SPIRIT),
{"SPEED_NORMAL", 0},
{"SPEED_SLOW", 1},
{"SPEED_FAST", 2},
{"SPEED_VERYFAST", 3},
{"SPEED_MODSLOW", 4},
{"SPEED_VERYSLOW", 5},
{"SPEED_FAST2", 6},
{"SPEED_LITOCAVE", 7},
luaConstant(BOUNCE_NONE),
luaConstant(BOUNCE_SIMPLE),
luaConstant(BOUNCE_REAL),
{"LOOP_INFINITE", -1},
{"LOOP_INF", -1},
{"LAYER_BODY", 0},
{"LAYER_UPPERBODY", 1},
{"LAYER_HEAD", 2},
{"LAYER_OVERRIDE", 3},
luaConstant(SONG_NONE),
luaConstant(SONG_HEAL),
luaConstant(SONG_ENERGYFORM),
luaConstant(SONG_SONGDOOR1),
luaConstant(SONG_SPIRITFORM),
luaConstant(SONG_BIND),
{"SONG_PULL", SONG_BIND},
luaConstant(SONG_NATUREFORM),
luaConstant(SONG_BEASTFORM),
luaConstant(SONG_SHIELDAURA),
{"SONG_SHIELD", SONG_SHIELDAURA},
luaConstant(SONG_SONGDOOR2),
luaConstant(SONG_DUALFORM),
luaConstant(SONG_FISHFORM),
luaConstant(SONG_SUNFORM),
{"SONG_LIGHTFORM", SONG_SUNFORM},
luaConstant(SONG_LI),
luaConstant(SONG_TIME),
luaConstant(SONG_LANCE),
luaConstant(SONG_MAP),
luaConstant(SONG_ANIMA),
luaConstant(SONG_MAX),
luaConstantFromClass(BLEND_DEFAULT, RenderObject),
luaConstantFromClass(BLEND_ADD, RenderObject),
{"BLEND_ADDITIVE", RenderObject::BLEND_ADD},
luaConstantFromClass(BLEND_SUB, RenderObject),
luaConstantFromClass(BLEND_MULT, RenderObject),
{"ENDING_NAIJACAVE", 10},
{"ENDING_NAIJACAVEDONE", 11},
{"ENDING_SECRETCAVE", 12},
{"ENDING_MAINAREA", 13},
{"ENDING_DONE", 14},
{"FLAG_SONGCAVECRYSTAL", 20},
{"FLAG_TEIRA", 50},
{"FLAG_SHARAN", 51},
{"FLAG_DRASK", 52},
{"FLAG_VEDHA", 53},
{"FLAG_ENERGYTEMPLE01DOOR", 100},
{"FLAG_ENERGYDOOR02", 101},
{"FLAG_ENERGYSLOT01", 102},
{"FLAG_ENERGYSLOT02", 103},
{"FLAG_ENERGYSLOT_MAINAREA", 104},
{"FLAG_MAINAREA_ENERGYTEMPLE_ROCK", 105},
{"FLAG_ENERGYSLOT_FIRST", 106},
{"FLAG_ENERGYDOOR03", 107},
{"FLAG_ENERGYGODENCOUNTER", 108},
{"FLAG_ENERGYBOSSDEAD", 109},
{"FLAG_MAINAREA_ETENTER2", 110},
{"FLAG_SUNTEMPLE_WATERLEVEL", 111},
{"FLAG_SUNTEMPLE_LIGHTCRYSTAL", 112},
{"FLAG_SUNKENCITY_PUZZLE", 113},
{"FLAG_SUNKENCITY_BOSS", 114},
{"FLAG_MITHALAS_THRONEROOM", 115},
{"FLAG_BOSS_MITHALA", 116},
{"FLAG_BOSS_FOREST", 117},
{"FLAG_FISHCAVE", 118},
{"FLAG_VISION_VEIL", 119},
{"FLAG_MITHALAS_PRIESTS", 120},
{"FLAG_FIRSTTRANSTURTLE", 121},
{"FLAG_13PROGRESSION", 122},
{"FLAG_FINAL", 123},
{"FLAG_SPIRIT_ERULIAN", 124},
{"FLAG_SPIRIT_KROTITE", 125},
{"FLAG_SPIRIT_DRASK", 126},
{"FLAG_SPIRIT_DRUNIAD", 127},
{"FLAG_BOSS_SUNWORM", 128},
{"FLAG_WHALELAMPPUZZLE", 129},
{"FLAG_TRANSTURTLE_VEIL01", 130},
{"FLAG_TRANSTURTLE_OPENWATER06", 131},
{"FLAG_TRANSTURTLE_FOREST04", 132},
{"FLAG_TRANSTURTLE_OPENWATER03", 133},
{"FLAG_TRANSTURTLE_FOREST05", 134},
{"FLAG_TRANSTURTLE_MAINAREA", 135},
{"FLAG_TRANSTURTLE_SEAHORSE", 136},
{"FLAG_TRANSTURTLE_VEIL02", 137},
{"FLAG_TRANSTURTLE_ABYSS03", 138},
{"FLAG_TRANSTURTLE_FINALBOSS", 139},
{"FLAG_NAIJA_SWIM", 200},
{"FLAG_NAIJA_MINIMAP", 201},
{"FLAG_NAIJA_SPEEDBOOST", 202},
{"FLAG_NAIJA_MEMORYCRYSTAL", 203},
{"FLAG_NAIJA_SINGING", 204},
{"FLAG_NAIJA_LEAVESVEDHA", 205},
{"FLAG_NAIJA_SONGDOOR", 206},
{"FLAG_NAIJA_ENTERVEDHACAVE", 207},
{"FLAG_NAIJA_INTERACT", 208},
{"FLAG_NAIJA_ENTERSONGCAVE", 209},
{"FLAG_NAIJA_ENERGYFORMSHOT", 210},
{"FLAG_NAIJA_ENERGYFORMCHARGE", 211},
{"FLAG_NAIJA_RETURNTONORMALFORM", 212},
{"FLAG_NAIJA_ENERGYBARRIER", 213},
{"FLAG_NAIJA_SOLIDENERGYBARRIER", 214},
{"FLAG_NAIJA_ENTERENERGYTEMPLE", 215},
{"FLAG_NAIJA_OPENWATERS", 216},
{"FLAG_NAIJA_SINGING", 217},
{"FLAG_NAIJA_INGAMEMENU", 218},
{"FLAG_NAIJA_SINGINGHINT", 219},
{"FLAG_NAIJA_LOOK", 220},
{"FLAG_HINT_MINIMAP", 221},
{"FLAG_HINT_HEALTHPLANT", 222},
{"FLAG_HINT_SLEEP", 223},
{"FLAG_HINT_COLLECTIBLE", 224},
{"FLAG_HINT_IGFDEMO", 225},
{"FLAG_HINT_BEASTFORM1", 226},
{"FLAG_HINT_BEASTFORM2", 227},
{"FLAG_HINT_LISONG", 228},
{"FLAG_HINT_ENERGYTARGET", 229},
{"FLAG_HINT_NATUREFORMABILITY", 230},
{"FLAG_HINT_LICOMBAT", 231},
{"FLAG_HINT_COOKING", 232},
{"FLAG_NAIJA_FIRSTVINE", 233},
luaConstant(FLAG_SECRET01),
luaConstant(FLAG_SECRET02),
luaConstant(FLAG_SECRET03),
{"FLAG_DEEPWHALE", 237},
{"FLAG_OMPO", 238},
{"FLAG_HINT_SINGBULB", 239},
{"FLAG_ENDING", 240},
{"FLAG_NAIJA_BINDSHELL", 241},
{"FLAG_NAIJA_BINDROCK", 242},
{"FLAG_HINT_ROLLGEAR", 243},
{"FLAG_FIRSTHEALTHUPGRADE", 244},
{"FLAG_MAINAREA_TRANSTURTLE_ROCK", 245},
{"FLAG_SKIPSECRETCHECK", 246},
{"FLAG_SEAHORSEBESTTIME", 247},
{"FLAG_SEAHORSETIMETOBEAT", 248},
{"FLAG_HINT_BINDMERMEN", 249},
{"FLAG_CREATORVOICE", 250},
{"FLAG_HINT_DUALFORMCHANGE", 251},
{"FLAG_HINT_DUALFORMCHARGE", 252},
{"FLAG_HINT_HEALTHUPGRADE", 253},
{"FLAG_VISION_ENERGYTEMPLE", 300},
luaConstant(FLAG_COLLECTIBLE_START),
{"FLAG_COLLECTIBLE_SONGCAVE", 500},
{"FLAG_COLLECTIBLE_ENERGYTEMPLE", 501},
{"FLAG_COLLECTIBLE_ENERGYSTATUE", 502},
{"FLAG_COLLECTIBLE_ENERGYBOSS", 503},
{"FLAG_COLLECTIBLE_NAIJACAVE", 504},
{"FLAG_COLLECTIBLE_CRABCOSTUME", 505},
{"FLAG_COLLECTIBLE_JELLYPLANT", 506},
{"FLAG_COLLECTIBLE_MITHALASPOT", 507},
{"FLAG_COLLECTIBLE_SEAHORSECOSTUME", 508},
{"FLAG_COLLECTIBLE_CHEST", 509},
{"FLAG_COLLECTIBLE_BANNER", 510},
{"FLAG_COLLECTIBLE_MITHALADOLL", 511},
{"FLAG_COLLECTIBLE_WALKERBABY", 512},
{"FLAG_COLLECTIBLE_SEEDBAG", 513},
{"FLAG_COLLECTIBLE_ARNASSISTATUE", 514},
{"FLAG_COLLECTIBLE_GEAR", 515},
{"FLAG_COLLECTIBLE_SUNKEY", 516},
{"FLAG_COLLECTIBLE_URCHINCOSTUME", 517},
{"FLAG_COLLECTIBLE_TEENCOSTUME", 518},
{"FLAG_COLLECTIBLE_MUTANTCOSTUME", 519},
{"FLAG_COLLECTIBLE_JELLYCOSTUME", 520},
{"FLAG_COLLECTIBLE_MITHALANCOSTUME", 521},
{"FLAG_COLLECTIBLE_ANEMONESEED", 522},
{"FLAG_COLLECTIBLE_BIOSEED", 523},
{"FLAG_COLLECTIBLE_TURTLEEGG", 524},
{"FLAG_COLLECTIBLE_SKULL", 525},
{"FLAG_COLLECTIBLE_TRIDENTHEAD", 526},
{"FLAG_COLLECTIBLE_SPORESEED", 527},
{"FLAG_COLLECTIBLE_UPSIDEDOWNSEED", 528},
{"FLAG_COLLECTIBLE_STONEHEAD", 529},
{"FLAG_COLLECTIBLE_STARFISH", 530},
{"FLAG_COLLECTIBLE_BLACKPEARL", 531},
luaConstant(FLAG_COLLECTIBLE_END),
luaConstant(FLAG_PET_ACTIVE),
luaConstant(FLAG_PET_NAMESTART),
{"FLAG_PET_NAUTILUS", 601},
{"FLAG_PET_DUMBO", 602},
{"FLAG_PET_BLASTER", 603},
{"FLAG_PET_PIRANHA", 604},
luaConstant(FLAG_UPGRADE_WOK),
// does the player have access to 3 slots all the time?
{"FLAG_COLLECTIBLE_NAUTILUSPRIME", 630},
{"FLAG_COLLECTIBLE_DUMBOEGG", 631},
{"FLAG_COLLECTIBLE_BLASTEREGG", 632},
{"FLAG_COLLECTIBLE_PIRANHAEGG", 633},
{"FLAG_ENTER_HOMEWATERS", 650},
{"FLAG_ENTER_SONGCAVE", 651},
{"FLAG_ENTER_ENERGYTEMPLE", 652},
{"FLAG_ENTER_OPENWATERS", 653},
{"FLAG_ENTER_HOMECAVE", 654},
{"FLAG_ENTER_FOREST", 655},
{"FLAG_ENTER_VEIL", 656},
{"FLAG_ENTER_MITHALAS", 657},
{"FLAG_ENTER_MERMOGCAVE", 658},
{"FLAG_ENTER_MITHALAS", 659},
{"FLAG_ENTER_SUNTEMPLE", 660},
{"FLAG_ENTER_ABYSS", 661},
{"FLAG_ENTER_SUNKENCITY", 662},
{"FLAG_ENTER_FORESTSPRITECAVE", 663},
{"FLAG_ENTER_FISHCAVE", 664},
{"FLAG_ENTER_MITHALASCATHEDRAL", 665},
{"FLAG_ENTER_TURTLECAVE", 666},
{"FLAG_ENTER_FROZENVEIL", 667},
{"FLAG_ENTER_ICECAVE", 668},
{"FLAG_ENTER_SEAHORSE", 669},
{"FLAG_MINIBOSS_START", 700},
{"FLAG_MINIBOSS_NAUTILUSPRIME", 700},
{"FLAG_MINIBOSS_KINGJELLY", 701},
{"FLAG_MINIBOSS_MERGOG", 702},
{"FLAG_MINIBOSS_CRAB", 703},
{"FLAG_MINIBOSS_OCTOMUN", 704},
{"FLAG_MINIBOSS_MANTISSHRIMP", 705},
{"FLAG_MINIBOSS_PRIESTS", 706},
{"FLAG_MINIBOSS_END", 720},
{"FLAG_MAMATURTLE_RESCUE1", 750},
{"FLAG_MAMATURTLE_RESCUE2", 751},
{"FLAG_MAMATURTLE_RESCUE3", 752},
{"FLAG_SONGDOOR1", 800},
luaConstant(FLAG_SEALOAFANNOYANCE),
{"FLAG_SEAL_KING", 900},
{"FLAG_SEAL_QUEEN", 901},
{"FLAG_SEAL_PRINCE", 902},
{"FLAG_HEALTHUPGRADES", 950},
{"FLAG_HEALTHUPGRADES_END", 960},
luaConstant(FLAG_LI),
luaConstant(FLAG_LICOMBAT),
luaConstant(MAX_FLAGS),
{"ALPHA_NEARZERO", 0.001},
{"SUNKENCITY_START", 0},
{"SUNKENCITY_CLIMBDOWN", 1},
{"SUNKENCITY_RUNAWAY", 2},
{"SUNKENCITY_INHOLE", 3},
{"SUNKENCITY_GF", 4},
{"SUNKENCITY_BULLIES", 5},
{"SUNKENCITY_ANIMA", 6},
{"SUNKENCITY_BOSSWAIT", 7},
{"SUNKENCITY_CLAY1", 8},
{"SUNKENCITY_CLAY2", 9},
{"SUNKENCITY_CLAY3", 10},
{"SUNKENCITY_CLAY4", 11},
{"SUNKENCITY_CLAY5", 12},
{"SUNKENCITY_CLAY6", 13},
{"SUNKENCITY_CLAYDONE", 14},
{"SUNKENCITY_BOSSFIGHT", 15},
{"SUNKENCITY_BOSSDONE", 16},
{"SUNKENCITY_FINALTONGUE", 17},
{"FINAL_START", 0},
{"FINAL_SOMETHING", 1},
{"FINAL_FREEDLI", 2},
luaConstantFromClass(ANIM_NONE, Bone),
luaConstantFromClass(ANIM_POS, Bone),
luaConstantFromClass(ANIM_ROT, Bone),
luaConstantFromClass(ANIM_ALL, Bone),
luaConstant(FORM_NORMAL),
luaConstant(FORM_ENERGY),
luaConstant(FORM_BEAST),
luaConstant(FORM_NATURE),
luaConstant(FORM_SPIRIT),
luaConstant(FORM_DUAL),
luaConstant(FORM_FISH),
luaConstant(FORM_SUN),
{"FORM_LIGHT", FORM_SUN},
luaConstant(FORM_MAX),
luaConstant(VFX_SHOCK),
luaConstant(VFX_RIPPLE),
luaConstant(EAT_NONE),
luaConstant(EAT_DEFAULT),
luaConstant(EAT_FILE),
luaConstant(EAT_MAX),
luaConstant(DT_NONE),
luaConstant(DT_ENEMY),
luaConstant(DT_ENEMY_ENERGYBLAST),
luaConstant(DT_ENEMY_SHOCK),
luaConstant(DT_ENEMY_BITE),
luaConstant(DT_ENEMY_TRAP),
luaConstant(DT_ENEMY_WEB),
luaConstant(DT_ENEMY_BEAM),
luaConstant(DT_ENEMY_GAS),
luaConstant(DT_ENEMY_INK),
luaConstant(DT_ENEMY_POISON),
luaConstant(DT_ENEMY_ACTIVEPOISON),
luaConstant(DT_ENEMY_CREATOR),
luaConstant(DT_ENEMY_MANTISBOMB),
luaConstant(DT_ENEMY_MAX),
{"DT_ENEMY_END", DT_ENEMY_MAX},
luaConstant(DT_AVATAR),
luaConstant(DT_AVATAR_ENERGYBLAST),
luaConstant(DT_AVATAR_SHOCK),
luaConstant(DT_AVATAR_BITE),
luaConstant(DT_AVATAR_VOMIT),
luaConstant(DT_AVATAR_ACID),
luaConstant(DT_AVATAR_SPORECHILD),
luaConstant(DT_AVATAR_LIZAP),
luaConstant(DT_AVATAR_NATURE),
luaConstant(DT_AVATAR_ENERGYROLL),
luaConstant(DT_AVATAR_VINE),
luaConstant(DT_AVATAR_EAT),
luaConstant(DT_AVATAR_EAT_BASICSHOT),
luaConstant(DT_AVATAR_EAT_MAX),
luaConstant(DT_AVATAR_LANCEATTACH),
luaConstant(DT_AVATAR_LANCE),
luaConstant(DT_AVATAR_CREATORSHOT),
luaConstant(DT_AVATAR_DUALFORMLI),
luaConstant(DT_AVATAR_DUALFORMNAIJA),
luaConstant(DT_AVATAR_BUBBLE),
luaConstant(DT_AVATAR_SEED),
luaConstant(DT_AVATAR_PET),
luaConstant(DT_AVATAR_PETNAUTILUS),
luaConstant(DT_AVATAR_PETBITE),
luaConstant(DT_AVATAR_MAX),
{"DT_AVATAR_END", DT_AVATAR_MAX},
luaConstant(DT_TOUCH),
luaConstant(DT_CRUSH),
luaConstant(DT_SPIKES),
luaConstant(DT_STEAM),
luaConstant(DT_WALLHURT),
luaConstant(FRAME_TIME),
luaConstant(FORMUPGRADE_ENERGY1),
luaConstant(FORMUPGRADE_ENERGY2),
luaConstant(FORMUPGRADE_BEAST),
luaConstant(TILE_SIZE),
luaConstant(INPUT_MOUSE),
luaConstant(INPUT_JOYSTICK),
luaConstant(INPUT_KEYBOARD),
luaConstant(ANIMLAYER_FLOURISH),
luaConstant(ANIMLAYER_OVERRIDE),
luaConstant(ANIMLAYER_ARMOVERRIDE),
luaConstant(ANIMLAYER_UPPERBODYIDLE),
luaConstant(ANIMLAYER_HEADOVERRIDE),
luaConstant(OT_EMPTY),
luaConstant(OT_BLACK),
luaConstant(OT_BLACKINVIS),
luaConstant(OT_INVISIBLE),
luaConstant(OT_INVISIBLEIN),
luaConstant(OT_HURT),
luaConstant(OT_INVISIBLEENT),
luaConstant(OT_USER1),
luaConstant(OT_USER2),
luaConstant(OT_MASK_BLACK),
luaConstant(OT_BLOCKING),
luaConstant(OT_USER_MASK),
luaConstant(OT_OUTOFBOUNDS),
luaConstant(SEE_MAP_NEVER),
luaConstant(SEE_MAP_DEFAULT),
luaConstant(SEE_MAP_ALWAYS),
luaConstant(ALIGN_CENTER),
luaConstant(ALIGN_LEFT),
luaConstant(PATHSHAPE_RECT),
luaConstant(PATHSHAPE_CIRCLE),
};
//============================================================================================
// F U N C T I O N S
//============================================================================================
ScriptInterface::ScriptInterface()
: baseState(NULL), _sballoc(8, 128)
{
}
void ScriptInterface::init()
{
bool devmode = dsq->isDeveloperKeys();
// Everything on in dev mode, everything off otherwise.
loudScriptErrors = devmode;
complainOnGlobalVar = devmode;
complainOnUndefLocal = devmode;
allowUnsafeFunctions = dsq->user.system.allowDangerousScriptFunctions;
if (!baseState)
baseState = createLuaVM();
}
void ScriptInterface::reset()
{
shutdown();
init();
}
void *ScriptInterface::the_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
{
ScriptInterface *this_ = (ScriptInterface*)ud;
return this_->_sballoc.Alloc(ptr, nsize, osize);
}
lua_State *ScriptInterface::createLuaVM()
{
lua_State *state = lua_newstate(the_alloc, this); /* opens Lua */
luaL_openlibs(state);
if(!allowUnsafeFunctions)
{
lua_pushnil(state);
lua_setglobal(state, "os");
lua_pushnil(state);
lua_setglobal(state, "io");
lua_pushnil(state);
lua_setglobal(state, "package");
}
// Set up various tables for state management:
// -- Interface function tables for each script file.
lua_newtable(state);
lua_setglobal(state, "_scriptfuncs");
// -- Number of users (active threads) for each script file.
lua_newtable(state);
lua_setglobal(state, "_scriptusers");
// -- Initial instance-local tables for each script file.
lua_newtable(state);
lua_setglobal(state, "_scriptvars");
// -- Instance-local variable tables for each thread.
lua_newtable(state);
lua_setglobal(state, "_threadvars");
// -- Active threads (so they aren't garbage-collected).
lua_newtable(state);
lua_setglobal(state, "_threadtable");
// Register all custom functions and constants.
for (unsigned int i = 0; i < sizeof(luaFunctionTable)/sizeof(*luaFunctionTable); i++)
{
lua_register(state, luaFunctionTable[i].name, luaFunctionTable[i].func);
}
for (unsigned int i = 0; i < sizeof(luaConstantTable)/sizeof(*luaConstantTable); i++)
{
lua_pushnumber(state, luaConstantTable[i].value);
lua_setglobal(state, luaConstantTable[i].name);
}
// Add hooks to monitor global get/set operations if requested.
if (complainOnGlobalVar)
{
if (!lua_getmetatable(state, LUA_GLOBALSINDEX))
lua_newtable(state);
lua_pushcfunction(state, l_indexWarnGlobal);
lua_setfield(state, -2, "__index");
lua_pushcfunction(state, l_newindexWarnGlobal);
lua_setfield(state, -2, "__newindex");
lua_setmetatable(state, LUA_GLOBALSINDEX);
}
// In case a script errors outside of any protected environment, report and exit.
lua_atpanic(state, l_panicHandler);
// Register Lua classes
luaL_newmetatable(state, "pathfinder");
lua_pushliteral(state, "__gc");
lua_pushcfunction(state, _pathfindDelete);
lua_settable(state, -3);
lua_pop(state, 1);
// All done, return the new state.
return state;
}
void ScriptInterface::destroyLuaVM(lua_State *state)
{
if (state)
lua_close(state);
}
// Initial value for the instance-local table should be on the stack of
// the base Lua state; it will be popped when this function returns.
lua_State *ScriptInterface::createLuaThread(const std::string &file)
{
lua_State *thread = lua_newthread(baseState);
if (!thread)
{
lua_pop(baseState, 1);
return NULL;
}
// Save the thread object in a Lua table to prevent it from being
// garbage-collected.
lua_getglobal(baseState, "_threadtable");
lua_pushlightuserdata(baseState, thread);
lua_pushvalue(baseState, -3); // -3 = thread
lua_rawset(baseState, -3); // -3 = _threadtable
lua_pop(baseState, 2);
// Set up the instance-local variable table for this thread, copying
// the contents of the initial-value table.
lua_newtable(baseState);
lua_pushnil(baseState);
while (lua_next(baseState, -3))
{
// We need to save a copy of the key for the next iteration.
lua_pushvalue(baseState, -2);
lua_insert(baseState, -2);
lua_settable(baseState, -4);
}
lua_remove(baseState, -2); // We no longer need the original table.
if (complainOnUndefLocal)
{
if (!lua_getmetatable(baseState, -1))
lua_newtable(baseState);
lua_pushcfunction(baseState, l_indexWarnInstance);
lua_setfield(baseState, -2, "__index");
lua_setmetatable(baseState, -2);
}
lua_getglobal(baseState, "_threadvars");
lua_pushlightuserdata(baseState, thread);
lua_pushvalue(baseState, -3); // -3 = instance-local table
lua_rawset(baseState, -3); // -3 = _threadvars
lua_pop(baseState, 2);
// Update the usage count for this script.
lua_getglobal(baseState, "_scriptusers");
lua_getfield(baseState, -1, file.c_str());
const int users = lua_tointeger(baseState, -1) + 1;
lua_pop(baseState, 1);
lua_pushinteger(baseState, users);
lua_setfield(baseState, -2, file.c_str());
lua_pop(baseState, 1);
return thread;
}
// Returns the number of remaining users of this script.
int ScriptInterface::destroyLuaThread(const std::string &file, lua_State *thread)
{
// Threads are not explicitly closed; instead, we delete the thread
// resources from the state-global tables, thus allowing them to be
// garbage-collected. collectGarbage() can be called at a convenient
// time to forcibly free all dead thread resources.
lua_getglobal(baseState, "_threadtable");
lua_pushlightuserdata(baseState, thread);
lua_pushnil(baseState);
lua_rawset(baseState, -3);
lua_pop(baseState, 1);
lua_getglobal(baseState, "_threadvars");
lua_pushlightuserdata(baseState, thread);
lua_pushnil(baseState);
lua_rawset(baseState, -3);
lua_pop(baseState, 1);
lua_getglobal(baseState, "_scriptusers");
lua_getfield(baseState, -1, file.c_str());
const int users = lua_tointeger(baseState, -1) - 1;
lua_pop(baseState, 1);
if (users > 0)
lua_pushinteger(baseState, users);
else
lua_pushnil(baseState);
lua_setfield(baseState, -2, file.c_str());
lua_pop(baseState, 1);
return users;
}
void ScriptInterface::collectGarbage()
{
lua_gc(baseState, LUA_GCCOLLECT, 0);
}
int ScriptInterface::gcGetStats()
{
return lua_gc(baseState, LUA_GCCOUNT, 0);
}
void ScriptInterface::shutdown()
{
destroyLuaVM(baseState);
baseState = NULL;
}
Script *ScriptInterface::openScript(const std::string &file, bool ignoremissing /* = false */)
{
std::string realFile = localisePathInternalModpath(file);
realFile = adjustFilenameCase(realFile);
bool loadedScript = false;
lua_getglobal(baseState, "_scriptvars");
lua_getfield(baseState, -1, realFile.c_str());
lua_remove(baseState, -2);
if (!lua_istable(baseState, -1))
{
// We must not have loaded the script yet, so load it.
loadedScript = true;
// Clear out the (presumably nil) getfield() result from the stack.
lua_pop(baseState, 1);
// Create a new variable table for the initial run of the script.
// This will become the initial instance-local variable table for
// all instances of this script.
lua_newtable(baseState);
if (complainOnUndefLocal)
{
if (!lua_getmetatable(baseState, -1))
lua_newtable(baseState);
lua_pushcfunction(baseState, l_indexWarnInstance);
lua_setfield(baseState, -2, "__index");
lua_setmetatable(baseState, -2);
}
// Save the current value of the "v" global, so we can restore it
// after we run the script. (We do this here and in Script::call()
// so that nested Lua calls don't disrupt the caller's instance
// variable table.)
lua_getglobal(baseState, "v");
// Load the file itself. This leaves the Lua chunk on the stack.
int result = loadFile_helper(baseState, realFile.c_str());
if (result != 0)
{
if(result != LUA_ERRFILE || (result == LUA_ERRFILE && !ignoremissing))
scriptError("Error loading script [" + realFile + "]: " + lua_tostring(baseState, -1));
lua_pop(baseState, 2);
return NULL;
}
// Do the initial run of the script, popping the Lua chunk.
lua_getglobal(baseState, "_threadvars");
lua_pushlightuserdata(baseState, baseState);
lua_pushvalue(baseState, -5);
lua_settable(baseState, -3);
lua_pop(baseState, 1);
fixupLocalVars(baseState);
result = lua_pcall(baseState, 0, 0, 0);
lua_getglobal(baseState, "_threadvars");
lua_pushlightuserdata(baseState, baseState);
lua_pushnil(baseState);
lua_settable(baseState, -3);
lua_pop(baseState, 1);
if (result != 0)
{
scriptError("Error doing initial run of script [" + realFile + "]: " + lua_tostring(baseState, -1));
lua_pop(baseState, 2);
return NULL;
}
// Restore the old value of the "v" global.
lua_setglobal(baseState, "v");
// Store the instance-local table in the _scriptvars table.
lua_getglobal(baseState, "_scriptvars");
lua_pushvalue(baseState, -2);
lua_setfield(baseState, -2, realFile.c_str());
lua_pop(baseState, 1);
// Generate an interface function table for the script, and
// clear out the functions from the global environment.
lua_getglobal(baseState, "_scriptfuncs");
lua_newtable(baseState);
for (unsigned int i = 0; interfaceFunctions[i] != NULL; i++)
{
const char *funcName = interfaceFunctions[i];
lua_getglobal(baseState, funcName);
if (!lua_isnil(baseState, -1))
{
lua_setfield(baseState, -2, funcName);
lua_pushnil(baseState);
lua_setglobal(baseState, funcName);
}
else
{
lua_pop(baseState, 1);
}
}
lua_setfield(baseState, -2, realFile.c_str());
lua_pop(baseState, 1);
// Leave the instance-local table on the stack for createLuaThread().
}
lua_State *thread = createLuaThread(realFile.c_str());
if (!thread)
{
scriptError("Unable to create new thread for script [" + realFile + "]");
if (loadedScript)
{
lua_getglobal(baseState, "_scriptfuncs");
lua_pushnil(baseState);
lua_setfield(baseState, -2, realFile.c_str());
lua_pop(baseState, 1);
lua_getglobal(baseState, "_scriptvars");
lua_pushnil(baseState);
lua_setfield(baseState, -2, realFile.c_str());
lua_pop(baseState, 1);
}
return NULL;
}
return new Script(thread, realFile);
}
void ScriptInterface::closeScript(Script *script)
{
const char *file = script->getFile().c_str();
int users = destroyLuaThread(file, script->getLuaState());
// If this was the last instance of this script, unload the script itself.
if (users <= 0)
{
lua_getglobal(baseState, "_scriptfuncs");
lua_pushnil(baseState);
lua_setfield(baseState, -2, file);
lua_pop(baseState, 1);
lua_getglobal(baseState, "_scriptvars");
lua_pushnil(baseState);
lua_setfield(baseState, -2, file);
lua_pop(baseState, 1);
}
delete script;
}
bool ScriptInterface::runScriptNum(const std::string &file, const std::string &func, int num)
{
std::string realFile = file;
if (file.find('/')==std::string::npos)
realFile = "scripts/" + file + ".lua";
Script *script = openScript(realFile);
if (!script)
return false;
if (!script->call(func.c_str(), num))
{
debugLog(script->getLastError());
debugLog("(error calling func: " + func + " in script: " + file + ")");
closeScript(script);
return false;
}
closeScript(script);
return true;
}
bool ScriptInterface::runScript(const std::string &file, const std::string &func, bool ignoremissing /* = false */)
{
std::string realFile = file;
if (file.find('/')==std::string::npos)
realFile = "scripts/" + file + ".lua";
Script *script = openScript(realFile, ignoremissing);
if (!script)
return false;
if (!func.empty() && !script->call(func.c_str()))
{
debugLog(script->getLastError());
debugLog("(error calling func: " + func + " in script: " + file + ")");
closeScript(script);
return false;
}
closeScript(script);
return true;
}
//-------------------------------------------------------------------------
void Script::lookupFunc(const char *name)
{
lua_getglobal(L, "_scriptfuncs"); // [_scriptfuncs]
lua_getfield(L, -1, file.c_str()); // [_scriptfuncs, tab]
lua_remove(L, -2); // [tab]
lua_getfield(L, -1, name); // [tab, f]
lua_remove(L, -2); // [f]
}
bool Script::doCall(int nparams, int nrets)
{
// Push the current value of the "v" global onto the Lua stack,
// so we can restore the current script's instance variable table
// before returning.
lua_getglobal(L, "v"); // [f, ..., v]
lua_insert(L, -(nparams+2)); // [v, f, ...]
fixupLocalVars(L);
int vpos = lua_gettop(L) - (nparams+1);
bool result;
if (lua_pcall(L, nparams, nrets, 0) == 0) // [v, ...]
{
result = true;
}
else
{
lastError = lua_tostring(L, -1);
lastError += " [";
lastError += luaFormatStackInfo(L);
lastError += "]";
lua_pop(L, 1);
result = false;
}
if (nrets != 0)
{
lua_pushvalue(L, vpos); // [v, ..., v]
lua_remove(L, vpos); // [..., v]
}
lua_setglobal(L, "v"); // [...]
return result;
}
bool Script::call(const char *name)
{
lookupFunc(name);
return doCall(0);
}
bool Script::call(const char *name, float param1)
{
lookupFunc(name);
lua_pushnumber(L, param1);
return doCall(1);
}
bool Script::call(const char *name, void *param1)
{
lookupFunc(name);
luaPushPointer(L, param1);
return doCall(1);
}
bool Script::call(const char *name, void *param1, float param2)
{
lookupFunc(name);
luaPushPointer(L, param1);
lua_pushnumber(L, param2);
return doCall(2);
}
bool Script::call(const char *name, void *param1, void *param2)
{
lookupFunc(name);
luaPushPointer(L, param1);
luaPushPointer(L, param2);
return doCall(2);
}
bool Script::call(const char *name, void *param1, float param2, float param3)
{
lookupFunc(name);
luaPushPointer(L, param1);
lua_pushnumber(L, param2);
lua_pushnumber(L, param3);
return doCall(3);
}
bool Script::call(const char *name, void *param1, float param2, float param3, bool *ret1)
{
lookupFunc(name);
luaPushPointer(L, param1);
lua_pushnumber(L, param2);
lua_pushnumber(L, param3);
if (!doCall(3, 1))
return false;
*ret1 = lua_toboolean(L, -1);
lua_pop(L, 1);
return true;
}
bool Script::call(const char *name, void *param1, int param2, int param3, int param4, bool *ret1)
{
lookupFunc(name);
luaPushPointer(L, param1);
lua_pushinteger(L, param2);
lua_pushinteger(L, param3);
lua_pushinteger(L, param4);
if (!doCall(4, 1))
return false;
*ret1 = lua_toboolean(L, -1);
lua_pop(L, 1);
return true;
}
bool Script::call(const char *name, void *param1, const char *param2, float param3)
{
lookupFunc(name);
luaPushPointer(L, param1);
lua_pushstring(L, param2);
lua_pushnumber(L, param3);
return doCall(3);
}
bool Script::call(const char *name, void *param1, const char *param2, void *param3)
{
lookupFunc(name);
luaPushPointer(L, param1);
lua_pushstring(L, param2);
luaPushPointer(L, param3);
return doCall(3);
}
bool Script::call(const char *name, void *param1, void *param2, void *param3)
{
lookupFunc(name);
luaPushPointer(L, param1);
luaPushPointer(L, param2);
luaPushPointer(L, param3);
return doCall(3);
}
bool Script::call(const char *name, void *param1, float param2, float param3, float param4)
{
lookupFunc(name);
luaPushPointer(L, param1);
lua_pushnumber(L, param2);
lua_pushnumber(L, param3);
lua_pushnumber(L, param4);
return doCall(4);
}
bool Script::call(const char *name, void *param1, void *param2, void *param3, void *param4)
{
lookupFunc(name);
luaPushPointer(L, param1);
luaPushPointer(L, param2);
luaPushPointer(L, param3);
luaPushPointer(L, param4);
return doCall(4);
}
bool Script::call(const char *name, void *param1, void *param2, void *param3, float param4, float param5, float param6, float param7, void *param8, bool *ret1)
{
lookupFunc(name);
luaPushPointer(L, param1);
luaPushPointer(L, param2);
luaPushPointer(L, param3);
lua_pushnumber(L, param4);
lua_pushnumber(L, param5);
lua_pushnumber(L, param6);
lua_pushnumber(L, param7);
luaPushPointer(L, param8);
if (!doCall(8, 1))
return false;
*ret1 = lua_toboolean(L, -1);
lua_pop(L, 1);
return true;
}
bool Script::call(const char *name, const char *param, bool *ret)
{
lookupFunc(name);
lua_pushstring(L, param);
if (!doCall(1, 1))
return false;
*ret = lua_toboolean(L, -1);
lua_pop(L, 1);
return true;
}
bool Script::call(const char *name, const char *param, std::string *ret)
{
lookupFunc(name);
lua_pushstring(L, param);
if (!doCall(1, 1))
return false;
*ret = getString(L, -1);
lua_pop(L, 1);
return true;
}
bool Script::call(const char *name, const char *param1, const char *param2, const char *param3, std::string *ret)
{
lookupFunc(name);
lua_pushstring(L, param1);
lua_pushstring(L, param2);
lua_pushstring(L, param3);
if (!doCall(3, 1))
return false;
*ret = getString(L, -1);
lua_pop(L, 1);
return true;
}
int Script::callVariadic(const char *name, lua_State *fromL, int nparams, void *param)
{
int oldtop = lua_gettop(L);
lookupFunc(name);
luaPushPointer(L, param);
// If both stacks are the same, we already pushed 2 more entries to the stack.
int pos = (L == fromL) ? -(nparams+2) : -nparams;
for (int i = 0; i < nparams; ++i)
lua_pushvalue(fromL, pos);
// Move them to the other stack. Ignored if L == fromL.
lua_xmove(fromL, L, nparams);
// Do the call
if (!doCall(nparams + 1, LUA_MULTRET))
return -1;
nparams = lua_gettop(L) - oldtop;
lua_xmove(L, fromL, nparams);
return nparams;
}