967 lines
21 KiB
C
967 lines
21 KiB
C
#include "lauxlib.h"
|
|
|
|
#include "log.h"
|
|
#include "lephisto.h"
|
|
#include "rng.h"
|
|
#include "land.h"
|
|
#include "llua.h"
|
|
#include "lluadef.h"
|
|
#include "llua_faction.h"
|
|
#include "map.h"
|
|
#include "llua_space.h"
|
|
|
|
static int planetL_createmetatable(lua_State* L);
|
|
static int systemL_createmetatable(lua_State* L);
|
|
static int vectorL_createmetatable(lua_State* L);
|
|
|
|
/* Space. */
|
|
static int planetL_get(lua_State* L);
|
|
static int systemL_get(lua_State* L);
|
|
static const luaL_reg space_methods[] = {
|
|
{ "getPlanet", planetL_get },
|
|
{ "getSystem", systemL_get },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
/* Planet metatable methods. */
|
|
static int planetL_eq(lua_State* L);
|
|
static int planetL_name(lua_State* L);
|
|
static int planetL_faction(lua_State* L);
|
|
static int planetL_class(lua_State* L);
|
|
static int planetL_services(lua_State* L);
|
|
static int planetL_position(lua_State* L);
|
|
static const luaL_reg planet_methods[] = {
|
|
{ "__eq", planetL_eq },
|
|
{ "__tostring", planetL_name },
|
|
{ "name", planetL_name },
|
|
{ "faction", planetL_faction },
|
|
{ "class", planetL_class },
|
|
{ "services", planetL_services },
|
|
{ "pos", planetL_position },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
/* System metatable methods. */
|
|
static int systemL_eq(lua_State* L);
|
|
static int systemL_name(lua_State* L);
|
|
static int systemL_faction(lua_State* L);
|
|
static int systemL_jumpdistance(lua_State* L);
|
|
static const luaL_reg system_methods[] = {
|
|
{ "__eq", systemL_eq },
|
|
{ "__tostring", systemL_name },
|
|
{ "name", systemL_name },
|
|
{ "faction", systemL_faction },
|
|
{ "jumpDist", systemL_jumpdistance },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
/* Vector metatable methods. */
|
|
static int vectorL_new(lua_State* L);
|
|
static int vectorL_add(lua_State* L);
|
|
static int vectorL_sub(lua_State* L);
|
|
static int vectorL_mul(lua_State* L);
|
|
static int vectorL_div(lua_State* L);
|
|
static int vectorL_get(lua_State* L);
|
|
static int vectorL_set(lua_State* L);
|
|
static int vectorL_distance(lua_State* L);
|
|
static int vectorL_mod(lua_State* L);
|
|
static const luaL_reg vector_methods[] = {
|
|
{ "new", vectorL_new },
|
|
{ "__add", vectorL_add },
|
|
{ "add", vectorL_add },
|
|
{ "__sub", vectorL_sub },
|
|
{ "sub", vectorL_sub },
|
|
{ "__mul", vectorL_mul },
|
|
{ "__div", vectorL_div },
|
|
{ "get", vectorL_get },
|
|
{ "set", vectorL_set },
|
|
{ "dist", vectorL_distance },
|
|
{ "mod", vectorL_mod },
|
|
{ 0, 0 }
|
|
}; /**< Vector metatable methods. */
|
|
|
|
/**
|
|
* @brief Load the space library.
|
|
* @param L State to load space library into.
|
|
* @return 0 on success.
|
|
*/
|
|
int lua_loadSpace(lua_State* L, int readonly) {
|
|
(void)readonly; /* Only read only atm. */
|
|
|
|
/* Register the functions. */
|
|
luaL_register(L, "space", space_methods);
|
|
|
|
/* Register the metatables. */
|
|
planetL_createmetatable(L);
|
|
systemL_createmetatable(L);
|
|
lua_loadVector(L);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Loads the vector metatable.
|
|
* @param L State to load the vector metatable into.
|
|
* @return 0 on success.
|
|
*/
|
|
int lua_loadVector(lua_State* L) {
|
|
vectorL_createmetatable(L);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Registers the planet metatable.
|
|
* @param L Lua state to register metatable in.
|
|
* @return 0 on success.
|
|
*/
|
|
static int planetL_createmetatable(lua_State* L) {
|
|
/* Create the metatable. */
|
|
luaL_newmetatable(L, PLANET_METATABLE);
|
|
|
|
/* Create the access table. */
|
|
lua_pushvalue(L, -1);
|
|
lua_setfield(L, -2,"__index");
|
|
|
|
/* Register the values. */
|
|
luaL_register(L, NULL, planet_methods);
|
|
|
|
/* Clean up. */
|
|
lua_pop(L, 1);
|
|
|
|
return 0; /* No error. */
|
|
}
|
|
|
|
/**
|
|
* @brief Register the system metatable.
|
|
* @param L Lua state to register metatable in.
|
|
* @param 0 on success.
|
|
*/
|
|
static int systemL_createmetatable(lua_State* L) {
|
|
/* Create the metatable. */
|
|
luaL_newmetatable(L, SYSTEM_METATABLE);
|
|
|
|
/* Create the access table. */
|
|
lua_pushvalue(L, -1);
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
/* Register the values. */
|
|
luaL_register(L, NULL, system_methods);
|
|
|
|
/* Clean up. */
|
|
lua_pop(L, 1);
|
|
|
|
return 0; /* No error. */
|
|
}
|
|
|
|
/**
|
|
* @brief Registers the vector metatable.
|
|
* @param L Lua state to register metatable in.
|
|
* @return 0 on success.
|
|
*/
|
|
static int vectorL_createmetatable(lua_State* L) {
|
|
/* Create the metatable. */
|
|
luaL_newmetatable(L, VECTOR_METATABLE);
|
|
|
|
/* Create the access table. */
|
|
lua_pushvalue(L, -1);
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
/* Register the values. */
|
|
luaL_register(L, NULL, vector_methods);
|
|
|
|
/* Clean up. */
|
|
lua_pop(L, 1);
|
|
|
|
return 0; /* No error. */
|
|
}
|
|
|
|
/**
|
|
* @defgroup SPACE Space Lua Bindings.
|
|
*
|
|
* @brief Contains Lua bindings for manipulating the space itself.
|
|
*/
|
|
/**
|
|
* @defgroup META_PLANET Planet metatable
|
|
*
|
|
* @brief The planet metatable is a way to represent a planet in Lua.
|
|
*
|
|
* It allows all sorts of operators making it much more natural to use.
|
|
*
|
|
* To call Members of the metatable always use:
|
|
* @code
|
|
* planet:function(param)
|
|
* @endcode
|
|
*/
|
|
|
|
/**
|
|
* @brief Get planet at index.
|
|
* @param L Lua state to get planet from.
|
|
* @param ind Index position to find the planet.
|
|
* @return Planet found at the index in the state.
|
|
*/
|
|
LuaPlanet* lua_toplanet(lua_State* L, int ind) {
|
|
if(lua_isuserdata(L, ind)) {
|
|
return (LuaPlanet*) lua_touserdata(L, ind);
|
|
}
|
|
|
|
luaL_typerror(L, ind, PLANET_METATABLE);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @brief Pushes a planet on the stack.
|
|
* @param L Lua state to push planet into.
|
|
* @param planet Planet to push.
|
|
* @return Newly pushed planet.
|
|
*/
|
|
LuaPlanet* lua_pushplanet(lua_State* L, LuaPlanet planet) {
|
|
LuaPlanet* p;
|
|
p = (LuaPlanet*) lua_newuserdata(L, sizeof(LuaPlanet));
|
|
*p = planet;
|
|
luaL_getmetatable(L, PLANET_METATABLE);
|
|
lua_setmetatable(L, -2);
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief Check to see if ind is a planet.
|
|
* @param L Lua state to check.
|
|
* @param ind Index at position to check.
|
|
* @return 1 if ind is a planet.
|
|
*/
|
|
int lua_isplanet(lua_State* L, int ind) {
|
|
int ret;
|
|
|
|
if(lua_getmetatable(L, ind)==0)
|
|
return 0;
|
|
lua_getfield(L, LUA_REGISTRYINDEX, PLANET_METATABLE);
|
|
|
|
ret = 0;
|
|
if(lua_rawequal(L, -1, -2)) /* Does it have the correct mt? */
|
|
ret = 1;
|
|
|
|
lua_pop(L, 2); /* Remove both metatables. */
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @ingroup SPACE
|
|
*
|
|
* @brief planet, system getPlanet([param])
|
|
*
|
|
* Get a planet.
|
|
*
|
|
* Possible values of param:
|
|
* -- nil : Get the current landed planet or nil if there is none.
|
|
* -- number : Get a random planet belonging to faction matching the number.
|
|
* -- string : Get the planet by name.
|
|
* -- table : Get random planet belonging to any of the factions in the table.
|
|
*
|
|
* @param param See description.
|
|
* @return Returns the planet and the system it belongs to.
|
|
*/
|
|
static int planetL_get(lua_State* L) {
|
|
int i;
|
|
int* factions;
|
|
int nfactions;
|
|
char** planets;
|
|
int nplanets;
|
|
char* rndplanet;
|
|
LuaPlanet planet;
|
|
LuaSystem sys;
|
|
LuaFaction* f;
|
|
|
|
rndplanet = NULL;
|
|
nplanets = 0;
|
|
|
|
/* Get the landed planet. */
|
|
if(lua_gettop(L) == 0) {
|
|
if(land_planet != NULL) {
|
|
planet.p = land_planet;
|
|
lua_pushplanet(L, planet);
|
|
sys.s = system_get(planet_getSystem(land_planet->name));
|
|
lua_pushsystem(L, sys);
|
|
return 2;
|
|
}
|
|
return 0; /* Not landed. */
|
|
}
|
|
|
|
/* Get a planet by faction */
|
|
else if(lua_isfaction(L, 1)) {
|
|
f = lua_tofaction(L, 1);
|
|
planets = space_getFactionPlanet(&nplanets, &f->f, 1);
|
|
}
|
|
|
|
/* Get a planet by name. */
|
|
else if(lua_isstring(L, 1)) {
|
|
rndplanet = (char*) lua_tostring(L, 1);
|
|
}
|
|
|
|
/* Get a planet from faction list. */
|
|
else if(lua_istable(L, 1)) {
|
|
/* Get table length and preallocate. */
|
|
nfactions = (int) lua_objlen(L, 1);
|
|
factions = malloc(sizeof(int) * nfactions);
|
|
/* Load up the table. */
|
|
lua_pushnil(L);
|
|
i = 0;
|
|
while(lua_next(L, -2) != 0) {
|
|
f = lua_tofaction(L, -1);
|
|
factions[i++] = f->f;
|
|
lua_pop(L,1);
|
|
}
|
|
|
|
/* Get the planets. */
|
|
planets = space_getFactionPlanet(&nplanets, factions, nfactions);
|
|
free(factions);
|
|
}
|
|
else LLUA_INVALID_PARAMETER(); /* Bad parameter. */
|
|
|
|
/* No suitable planet found. */
|
|
if((rndplanet == NULL) && (nplanets == 0)) {
|
|
free(planets);
|
|
return 0;
|
|
}
|
|
|
|
/* Pick random planet. */
|
|
else if(rndplanet == NULL) {
|
|
rndplanet = planets[RNG(0, nplanets-1)];
|
|
free(planets);
|
|
}
|
|
|
|
/* Push the planet. */
|
|
planet.p = planet_get(rndplanet); /* The real planet. */
|
|
lua_pushplanet(L, planet);
|
|
sys.s = system_get(planet_getSystem(rndplanet));
|
|
lua_pushsystem(L, sys);
|
|
return 2;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_PLANET
|
|
*
|
|
* @brief bool __eq(planet comp)
|
|
*
|
|
* __eq (equality) metamethod for planets.
|
|
*
|
|
* You can use the '=' operator within Lua to compare planets with this.
|
|
* @param comp planet to compare against.
|
|
* @return true if both planets are the same.
|
|
*/
|
|
static int planetL_eq(lua_State* L) {
|
|
LuaPlanet* a, *b;
|
|
a = lua_toplanet(L, 1);
|
|
b = lua_toplanet(L, 2);
|
|
if(a->p == b->p)
|
|
lua_pushboolean(L, 1);
|
|
else
|
|
lua_pushboolean(L, 0);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_PLANET
|
|
*
|
|
* @brief string name(nil)
|
|
*
|
|
* Get the planets name.
|
|
* @return The name of the planet.
|
|
*/
|
|
static int planetL_name(lua_State* L) {
|
|
LuaPlanet* p;
|
|
p = lua_toplanet(L, 1);
|
|
lua_pushstring(L, p->p->name);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_PLANET
|
|
*
|
|
* @brief number faction(nil)
|
|
*
|
|
* Get the planets faction.
|
|
* @return The planets faction.
|
|
*/
|
|
static int planetL_faction(lua_State* L) {
|
|
LuaPlanet* p;
|
|
LuaFaction f;
|
|
p = lua_toplanet(L, 1);
|
|
f.f = p->p->faction;
|
|
lua_pushfaction(L, f);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_PLANET
|
|
*
|
|
* @brief string class(nil)
|
|
*
|
|
* Get the planets class.
|
|
* @return The class of the planet in one char identifier.
|
|
*/
|
|
static int planetL_class(lua_State* L) {
|
|
char buf[2];
|
|
LuaPlanet* p;
|
|
p = lua_toplanet(L, 1);
|
|
buf[0] = planet_getClass(p->p);
|
|
buf[1] = '\0';
|
|
lua_pushstring(L, buf);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_PLANET
|
|
*
|
|
* @brief Number services(nil)
|
|
*
|
|
* Get planet services.
|
|
* @return The services the planet has it stored bitwise.
|
|
*/
|
|
static int planetL_services(lua_State* L) {
|
|
LuaPlanet* p;
|
|
p = lua_toplanet(L, 1);
|
|
lua_pushnumber(L, p->p->services);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_PLANET
|
|
*
|
|
* @brief Vec2 pos(nil)
|
|
*
|
|
* Get the position of the planet in the system.
|
|
* @return The position of the planet in the system.
|
|
*/
|
|
static int planetL_position(lua_State* L) {
|
|
LuaPlanet* p;
|
|
LuaVector v;
|
|
p = lua_toplanet(L, 1);
|
|
vectcpy(&v.vec, &p->p->pos);
|
|
lua_pushvector(L, v);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @defgroup META_SYSTEM System Metatable.
|
|
*
|
|
* @brief Represents a system in Lua.
|
|
*
|
|
* To call members of the metatable always use:
|
|
* @code
|
|
* system:function(param)
|
|
* @endcode
|
|
*/
|
|
|
|
/**
|
|
* @brief Get system at index.
|
|
* @param L Lus state to get system from.
|
|
* @param ind Index position of system.
|
|
* @return The LuaSystem at ind.
|
|
*/
|
|
LuaSystem* lua_tosystem(lua_State* L, int ind) {
|
|
if(lua_isuserdata(L, ind)) {
|
|
return (LuaSystem*) lua_touserdata(L,ind);
|
|
}
|
|
luaL_typerror(L, ind, SYSTEM_METATABLE);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @brief Pushes a system on the stack.
|
|
* @param L Lua state to push system onto.
|
|
* @param sys System to push.
|
|
* @return System just pushed.
|
|
*/
|
|
LuaSystem* lua_pushsystem(lua_State* L, LuaSystem sys) {
|
|
LuaSystem* s;
|
|
s = (LuaSystem*) lua_newuserdata(L, sizeof(LuaSystem));
|
|
*s = sys;
|
|
luaL_getmetatable(L, SYSTEM_METATABLE);
|
|
lua_setmetatable(L, -2);
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* @brief Check to see if ind is a system.
|
|
* @param L Lua state to check.
|
|
* @param ind Index position to check.
|
|
* @return 1 if there is a system at index position.
|
|
*/
|
|
int lua_issystem(lua_State* L, int ind) {
|
|
int ret;
|
|
|
|
if(lua_getmetatable(L, ind)==0)
|
|
return 0;
|
|
lua_getfield(L, LUA_REGISTRYINDEX, SYSTEM_METATABLE);
|
|
|
|
ret = 0;
|
|
if(lua_rawequal(L, -1, -2)) /* Does it have the correct mt? */
|
|
ret = 1;
|
|
|
|
lua_pop(L, 2); /* Remove both metatables. */
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @ingroup SPACE
|
|
*
|
|
* @brief system getSystem([param])
|
|
*
|
|
* Get a system.
|
|
*
|
|
* Behaves differently depending on what you pass as param:
|
|
* -- nil : Get the current system.
|
|
* -- string : Get the system by name.
|
|
* -- planet : Get the system by planet.
|
|
*
|
|
* @param param Read description for details.
|
|
* @return System metatable matching param.
|
|
*/
|
|
static int systemL_get(lua_State* L) {
|
|
LuaSystem sys;
|
|
LuaPlanet* p;
|
|
|
|
/* Get the current system with no parameters. */
|
|
if(lua_gettop(L) == 0) {
|
|
sys.s = cur_system;
|
|
}
|
|
/* Passing a string (systemname) */
|
|
else if(lua_isstring(L, 1)) {
|
|
sys.s = system_get((char*)lua_tostring(L, 1));
|
|
}
|
|
/* Passing a planet */
|
|
else if(lua_isplanet(L, 1)) {
|
|
p = lua_toplanet(L, 1);
|
|
sys.s = system_get(planet_getSystem(p->p->name));
|
|
}
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Return the system. */
|
|
lua_pushsystem(L, sys);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_SYSTEM
|
|
*
|
|
* @brief bool __eq(system comp)
|
|
*
|
|
* Check systems for equality.
|
|
*
|
|
* Allows you to use the '=' operator in Lua with systems.
|
|
* @param comp System to compare against.
|
|
* @return true if both systems are the same.
|
|
*/
|
|
static int systemL_eq(lua_State* L) {
|
|
LuaSystem* a, *b;
|
|
a = lua_tosystem(L, 1);
|
|
b = lua_tosystem(L, 2);
|
|
if(a->s == b->s)
|
|
lua_pushboolean(L, 1);
|
|
else
|
|
lua_pushboolean(L, 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_SYSTEM
|
|
*
|
|
* @brief string name(nil)
|
|
*
|
|
* Return the systems name.
|
|
* @return The name of the system.
|
|
*/
|
|
static int systemL_name(lua_State* L) {
|
|
LuaSystem* sys;
|
|
sys = lua_tosystem(L, 1);
|
|
lua_pushstring(L, sys->s->name);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_SYSTEM
|
|
*
|
|
* @brief table faction(nil)
|
|
*
|
|
* Get system factions.
|
|
*
|
|
* @code
|
|
* foo = space.faction("foo")
|
|
* if foo["bar"] then
|
|
* print("faction 'bar' found")
|
|
* end
|
|
* @endcode
|
|
* @return A table containing all the factions in the system.
|
|
*/
|
|
static int systemL_faction(lua_State* L) {
|
|
int i;
|
|
LuaSystem* sys;
|
|
sys = lua_tosystem(L, 1);
|
|
|
|
/* Return result in table. */
|
|
lua_newtable(L);
|
|
for(i = 0; i < sys->s->nplanets; i++) {
|
|
if(sys->s->planets[i]->faction > 0) { /* Faction must be valid. */
|
|
lua_pushboolean(L, 1); /* Value. */
|
|
lua_setfield(L, -2, faction_name(sys->s->planets[i]->faction)); /* Key. */
|
|
/* Allows syntax foo = space.faction("foo"); if foo["bar"] then ... end */
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_SYSTEM
|
|
*
|
|
* @brief number jumpDist([param])
|
|
*
|
|
* Get jump distance from current system, or to another.
|
|
*
|
|
* Does different things depending on the parameter type:
|
|
* -- nil : Get distance from current system.
|
|
* -- string : Get distance from system matching name.
|
|
* -- system : Get distance from system.
|
|
*
|
|
* @param param See description.
|
|
* @return Number of jumps to system.
|
|
*/
|
|
static int systemL_jumpdistance(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
LuaSystem* sys;
|
|
StarSystem** s;
|
|
int jumps;
|
|
char* start, *goal;
|
|
|
|
sys = lua_tosystem(L, 1);
|
|
start = sys->s->name;
|
|
|
|
if((lua_gettop(L) > 1) && lua_isstring(L, 2))
|
|
goal = (char*)lua_tostring(L, 2);
|
|
else
|
|
goal = cur_system->name;
|
|
|
|
s = map_getJumpPath(&jumps, start, goal, 1);
|
|
free(s);
|
|
|
|
lua_pushnumber(L, jumps);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @defgroup META_VECTOR Vector Metatable
|
|
*
|
|
* @brief Represents a 2d vector in Lua.
|
|
*
|
|
* To call members of the metatable always use:
|
|
* @code
|
|
* vector:function(param)
|
|
* @endcode
|
|
*/
|
|
|
|
/**
|
|
* @fn LuaVector* lua_tovector(lua_State* L, int ind)
|
|
*
|
|
* @brief Gets vector at index.
|
|
* @param L Lua state to get vector from.
|
|
* @param ind Index position of vector.
|
|
* @return The LuaVector at ind.
|
|
*/
|
|
LuaVector* lua_tovector(lua_State* L, int ind) {
|
|
if(lua_isuserdata(L, ind)) {
|
|
return (LuaVector*)lua_touserdata(L, ind);
|
|
}
|
|
|
|
luaL_typerror(L, ind, VECTOR_METATABLE);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @fn LuaVector* lua_pushvector(lua_State* L, LuaVector vec)
|
|
*
|
|
* @brief Pushes a vector on the stack.
|
|
* @param L Lua state to push vector onto.
|
|
* @param sys Vector to push.
|
|
* @return Vector just pushed.
|
|
*/
|
|
LuaVector* lua_pushvector(lua_State* L, LuaVector vec) {
|
|
LuaVector* v;
|
|
v = (LuaVector*) lua_newuserdata(L, sizeof(LuaVector));
|
|
*v = vec;
|
|
luaL_getmetatable(L, VECTOR_METATABLE);
|
|
lua_setmetatable(L, -2);
|
|
return v;
|
|
}
|
|
|
|
/**
|
|
* @fn int lua_isvector(lua_State* L, int ind)
|
|
*
|
|
* @brief Check to see if ind is a vector.
|
|
* @param L lua state to check.
|
|
* @param ind Index position to check.
|
|
* @return 1 if there is a vector at index position.
|
|
*/
|
|
int lua_isvector(lua_State* L, int ind) {
|
|
int ret;
|
|
|
|
if(lua_getmetatable(L, ind)==0)
|
|
return 0;
|
|
lua_getfield(L, LUA_REGISTRYINDEX, VECTOR_METATABLE);
|
|
|
|
ret = 0;
|
|
if(lua_rawequal(L, -1, -2)) /* Does it have the correct mt? */
|
|
ret = 1;
|
|
|
|
lua_pop(L, 2); /* Remove both metatables. */
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_VECTOR
|
|
*
|
|
* @brief Vec2 new([number x, number y])
|
|
*
|
|
* Creates a new vector.
|
|
* @param x if set, the X value for the new vector.
|
|
* @param y if set, the Y value for the new vector.
|
|
* @return The new vector.
|
|
*/
|
|
static int vectorL_new(lua_State* L) {
|
|
LuaVector v;
|
|
double x, y;
|
|
|
|
if((lua_gettop(L) > 1) && lua_isnumber(L,1) && lua_isnumber(L,2)) {
|
|
x = lua_tonumber(L,1);
|
|
y = lua_tonumber(L,2);
|
|
} else {
|
|
x = 0.;
|
|
y = 0.;
|
|
}
|
|
|
|
vect_cset(&v.vec, x, y);
|
|
lua_pushvector(L, v);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_VECTOR
|
|
*
|
|
* @brief __add(Vec2 vector)
|
|
*
|
|
* __add(number x, number y)
|
|
*
|
|
* Adds two vectors or a vector and some cartesian coords.
|
|
*/
|
|
static int vectorL_add(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
LuaVector* v1, *v2;
|
|
double x, y;
|
|
|
|
/* Get self. */
|
|
v1 = lua_tovector(L, 1);
|
|
|
|
/* Get rest of parameters. */
|
|
v2 = NULL;
|
|
if(lua_isvector(L, 2)) {
|
|
v2 = lua_tovector(L, 2);
|
|
x = v2->vec.x;
|
|
y = v2->vec.y;
|
|
}
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Actually add it. */
|
|
vect_cadd(&v1->vec, x, y);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_VECTOR
|
|
*
|
|
* @brief Subtracts a vector and some cartesian coords.
|
|
* @luaparam x X coordinate to subtract.
|
|
* @luaparam y Y coordinate to subtract.
|
|
*
|
|
* @luafunc __sub(vector)
|
|
* @brief Subtracts two vectors.
|
|
* @luaparam x
|
|
* @luafunc __sub(x, y)
|
|
*/
|
|
static int vectorL_sub(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
LuaVector* v1, *v2;
|
|
double x, y;
|
|
|
|
/* Get self. */
|
|
v1 = lua_tovector(L,1);
|
|
|
|
/* Get rest of parameters. */
|
|
v2 = NULL;
|
|
if(lua_isvector(L, 2)) {
|
|
v2 = lua_tovector(L, 2);
|
|
x = v2->vec.x;
|
|
y = v2->vec.y;
|
|
}
|
|
else if((lua_gettop(L) > 2) && lua_isnumber(L, 2) && lua_isnumber(L, 3)) {
|
|
x = lua_tonumber(L, 2);
|
|
y = lua_tonumber(L, 3);
|
|
}
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Actually add it. */
|
|
vect_cadd(&v1->vec, -x, -y);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_VECTOR
|
|
*
|
|
* @brief Multiplies a vector by a number.
|
|
* @luaparam mod Amount to multiply by.
|
|
* @luafunc __mul(mod)
|
|
*/
|
|
static int vectorL_mul(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
LuaVector* v1;
|
|
double mod;
|
|
|
|
/* Get self. */
|
|
v1 = lua_tovector(L,1);
|
|
|
|
/* Get rest of parameters. */
|
|
if(lua_isnumber(L, 2))
|
|
mod = lua_tonumber(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Actually add it. */
|
|
vect_cadd(&v1->vec, v1->vec.x * mod, v1->vec.x * mod);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_VECTOR
|
|
*
|
|
* @brief Divides a vector by a number.
|
|
* @luaparam mod Amount to divide by.
|
|
* @luafunc __div(mod)
|
|
*/
|
|
static int vectorL_div(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
LuaVector* v1;
|
|
double mod;
|
|
|
|
/* Get self. */
|
|
v1 = lua_tovector(L,1);
|
|
|
|
/* Get rest of parameters. */
|
|
if(lua_isnumber(L, 2))
|
|
mod = lua_tonumber(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Actually add it. */
|
|
vect_cadd(&v1->vec, v1->vec.x / mod, v1->vec.x / mod);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_VECTOR
|
|
*
|
|
* @brief Get the cartesian positions of the vector.
|
|
* @return X and Y position of the vector.
|
|
*
|
|
* @luafunc get()
|
|
*/
|
|
static int vectorL_get(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
LuaVector* v1;
|
|
|
|
/* Get self. */
|
|
v1 = lua_tovector(L,1);
|
|
|
|
/* Push the vector. */
|
|
lua_pushnumber(L, v1->vec.x);
|
|
lua_pushnumber(L, v1->vec.y);
|
|
return 2;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the vector by cartesian coordinates.
|
|
* @luaparam x X coordinate to set.
|
|
* @luaparam y Y coordinate to set.
|
|
*
|
|
* @luafunc set(x, y)
|
|
*/
|
|
static int vectorL_set(lua_State* L) {
|
|
LLUA_MIN_ARGS(3);
|
|
LuaVector* v1;
|
|
double x, y;
|
|
|
|
/* Get self */
|
|
v1 = lua_tovector(L, 1);
|
|
|
|
/* Get parameters. */
|
|
if(lua_isnumber(L,2))
|
|
x = lua_tonumber(L,2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
if(lua_isnumber(L, 3))
|
|
y = lua_tonumber(L, 3);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
vect_cset(&v1->vec, x, y);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_VECTOR
|
|
*
|
|
* @brief Get the distance from the Vec2.
|
|
* @param vector Vector to get distance from, uses origin(0,0) if not set.
|
|
* @return The distance calculated.
|
|
*
|
|
* @luafunc dist(vector)
|
|
*/
|
|
static int vectorL_distance(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
LuaVector* v1, *v2;
|
|
double dist;
|
|
|
|
/* Get self. */
|
|
v1 = lua_tovector(L, 1);
|
|
|
|
/* Get rest of parameters. */
|
|
v2 = NULL;
|
|
if(lua_gettop(L) > 1) {
|
|
if(lua_isvector(L,2))
|
|
v2 = lua_tovector(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
}
|
|
|
|
/* Get distance. */
|
|
if(v2 == NULL)
|
|
dist = vect_odist(&v1->vec);
|
|
else
|
|
dist = vect_dist(&v1->vec, &v2->vec);
|
|
|
|
/* Return the distance. */
|
|
lua_pushnumber(L, dist);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @ingroup META_VECTOR.
|
|
*
|
|
* @brief Gets the modulus of the vector.
|
|
* @return The modulus of the vector.
|
|
* @luafunc mod()
|
|
*/
|
|
static int vectorL_mod(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
LuaVector* v;
|
|
|
|
v = lua_tovector(L, 1);
|
|
lua_pushnumber(L, VMOD(v->vec));
|
|
return 1;
|
|
}
|
|
|