447 lines
10 KiB
C
447 lines
10 KiB
C
/**
|
|
* @file llua_space.c
|
|
*
|
|
* @brief Handle the Lua space bindings.
|
|
*
|
|
* These bindings control the planets and systems.
|
|
*/
|
|
|
|
#include "lauxlib.h"
|
|
#include "lephisto.h"
|
|
#include "llua_space.h"
|
|
#include "lluadef.h"
|
|
#include "rng.h"
|
|
#include "pilot.h"
|
|
#include "pilot.h"
|
|
#include "llua_pilot.h"
|
|
|
|
static int pilotL_createmetatable(lua_State* L);
|
|
/* Pilots. */
|
|
static int pilot_addFleet(lua_State* L);
|
|
static int pilot_clear(lua_State* L);
|
|
static int pilot_toggleSpawn(lua_State* L);
|
|
static const luaL_reg pilot_methods[] = {
|
|
{ "add", pilot_addFleet },
|
|
{ "clear", pilot_clear },
|
|
{ "toggleSpawn", pilot_toggleSpawn },
|
|
{ "clear", pilot_toggleSpawn },
|
|
{ 0, 0 }
|
|
}; /**< Pilot lua methods. */
|
|
|
|
static int pilotL_eq(lua_State* L);
|
|
static int pilotL_name(lua_State* L);
|
|
static int pilotL_rename(lua_State* L);
|
|
static int pilotL_position(lua_State* L);
|
|
static int pilotL_warp(lua_State* L);
|
|
static const luaL_reg pilotL_methods[] = {
|
|
{ "__eq", pilotL_eq },
|
|
{ "name", pilotL_name },
|
|
{ "rename", pilotL_rename },
|
|
{ "pos", pilotL_position },
|
|
{ "warp", pilotL_warp },
|
|
{ 0, 0 }
|
|
}; /**< Pilot metatable methods. */
|
|
|
|
/**
|
|
* @fn int lua_loadPilot(lua_State* L, int readonly)
|
|
*
|
|
* @brief Load the space library.
|
|
* @param L State to load space library into.
|
|
* @return 0 on success.
|
|
*/
|
|
int lua_loadPilot(lua_State* L, int readonly) {
|
|
if(readonly) /* Nothing is read only. */
|
|
return 0;
|
|
|
|
/* Register the functions. */
|
|
luaL_register(L, "pilot", pilot_methods);
|
|
|
|
/* Register the metatables. */
|
|
pilotL_createmetatable(L);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilotL_createmetatable(lua_State* L)
|
|
*
|
|
* @brief Registers the pilot metatable.
|
|
* @param L Lua state to register metatable in.
|
|
* @return 0 on success.
|
|
*/
|
|
static int pilotL_createmetatable(lua_State* L) {
|
|
/* Create the metatable. */
|
|
luaL_newmetatable(L, PILOT_METATABLE);
|
|
|
|
/* Create the access table. */
|
|
lua_pushvalue(L, -1);
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
/* Register the values. */
|
|
luaL_register(L, NULL, pilotL_methods);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @defgroup PILOT Pilot Lua bindings.
|
|
*
|
|
* @brief Lua bindings to interact with pilots.
|
|
*
|
|
* Functions should be called like:
|
|
*
|
|
* @code
|
|
* pilot.function(parameters)
|
|
* @endcode
|
|
*/
|
|
/**
|
|
* @defgroup META_PILOT Pilot Metatable
|
|
*
|
|
* @brief Represents a pilot in Lua.
|
|
*
|
|
* To call members of the metatable always use:
|
|
*
|
|
* @code
|
|
* pilot:function(param)
|
|
* @endcode
|
|
*/
|
|
|
|
/**
|
|
* @fn LuaPilot* lua_topilot(lua_State* L, int ind)
|
|
*
|
|
* @brief Get pilot at index.
|
|
* @param L Lua state to get pilot from.
|
|
* @param ind Index position to find the pilot.
|
|
* @return Pilot found at the index in the state.
|
|
*/
|
|
LuaPilot* lua_topilot(lua_State* L, int ind) {
|
|
if(lua_isuserdata(L, ind)) {
|
|
return (LuaPilot*)lua_touserdata(L, ind);
|
|
}
|
|
luaL_typerror(L, ind, PILOT_METATABLE);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @fn LuaPilot* lua_pushpilot(lua_State* L, LuaPilot pilot)
|
|
*
|
|
* @brief Push a pilot on the stack.
|
|
* @param L Lua state to push pilot into.
|
|
* @param pilot Pilot to push.
|
|
* @return Newly pushed pilot.
|
|
*/
|
|
LuaPilot* lua_pushpilot(lua_State* L, LuaPilot pilot) {
|
|
LuaPilot* p;
|
|
p = (LuaPilot*)lua_newuserdata(L, sizeof(LuaPilot));
|
|
*p = pilot;
|
|
luaL_getmetatable(L, PILOT_METATABLE);
|
|
lua_setmetatable(L, -2);
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @fn int lua_ispilot(lua_State* L, int ind)
|
|
*
|
|
* @brief Check to see if ind is a pilot.
|
|
* @param L Lua state to check.
|
|
* @param ind Index position to check.
|
|
* @return 1 if ind is a pilot.
|
|
*/
|
|
int lua_ispilot(lua_State* L, int ind) {
|
|
int ret;
|
|
|
|
if(lua_getmetatable(L, ind)==0)
|
|
return 0;
|
|
lua_getfield(L, LUA_REGISTRYINDEX, PILOT_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;
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilot_addFleet(lua_State* L)
|
|
* @ingroup PILOT
|
|
*
|
|
* @brief table add(string fleetname [, string ai, Vec2 pos ])
|
|
*
|
|
* Adds a fleet to the system.
|
|
* @param fleetname Name of the fleet to add.
|
|
* @param ai If set will override the standard fleet AI. "def" means use default.
|
|
* @param pos Position to create pilots around instead of choosing randomly.
|
|
* @return Table populated with all the identifiers of the pilots created.
|
|
*/
|
|
static int pilot_addFleet(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
Fleet* flt;
|
|
char* fltname, *fltai;
|
|
int i, j;
|
|
unsigned int p;
|
|
double a;
|
|
Vec2 vv, vp, vn;
|
|
FleetPilot* plt;
|
|
LuaPilot lp;
|
|
LuaVector* lv;
|
|
|
|
|
|
/* Parse first argument - Fleet name */
|
|
if(lua_isstring(L, 1)) fltname = (char*) lua_tostring(L, 1);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Parse second argument - Fleet IA override. */
|
|
if(lua_gettop(L) > 1) {
|
|
if(lua_isstring(L, 2)) {
|
|
fltai = (char*)lua_tostring(L, 2);
|
|
if(strcmp(fltai, "def")==0) /* Check if set to default. */
|
|
fltai = NULL;
|
|
}
|
|
else LLUA_INVALID_PARAMETER();
|
|
}
|
|
else fltai = NULL;
|
|
|
|
if(lua_gettop(L) > 2) {
|
|
if(lua_isvector(L,2))
|
|
lv = lua_tovector(L,2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
}
|
|
else lv = NULL;
|
|
|
|
/* Needed to determine angle. */
|
|
vectnull(&vn);
|
|
|
|
/* Pull the fleet. */
|
|
flt = fleet_get(fltname);
|
|
if(flt == NULL) {
|
|
LLUA_DEBUG("Fleet not found!");
|
|
return 0;
|
|
}
|
|
|
|
/* Use position passed if possible. */
|
|
if(lv != NULL)
|
|
vectcpy(&vp, &lv->vec);
|
|
else
|
|
vect_pset(&vp, RNG(MIN_HYPERSPACE_DIST*2, MIN_HYPERSPACE_DIST*3),
|
|
RNG(0,360)*M_PI/180.);
|
|
|
|
j = 0;
|
|
lua_newtable(L);
|
|
for(i = 0; i < flt->npilots; i++) {
|
|
plt = &flt->pilots[i];
|
|
|
|
if(RNG(0, 100) <= plt->chance) {
|
|
/* Fleet displacement. */
|
|
vect_cadd(&vp, RNG(75, 150) * (RNG(0,1) ? 1 : -1),
|
|
RNG(75, 150) * (RNG(0,1) ? 1 : -1));
|
|
|
|
/* Set velocity only if no position is set.. */
|
|
if(lv != NULL)
|
|
vectnull(&vv);
|
|
else { /* Enterting via hyperspace. */
|
|
a = vect_angle(&vp, &vn);
|
|
vect_pset(&vv, plt->ship->speed * 3., a);
|
|
}
|
|
|
|
/* Create the pilot. */
|
|
p = pilot_create(plt->ship,
|
|
plt->name,
|
|
flt->faction,
|
|
(fltai != NULL) ? /* Lua AI override. */
|
|
ai_getProfile(fltai) :
|
|
(plt->ai != NULL) ? /* Pilot AI override */
|
|
plt->ai : flt->ai,
|
|
a,
|
|
&vp,
|
|
&vv,
|
|
0);
|
|
|
|
/* We push each pilot created into a table and return it. */
|
|
lua_pushnumber(L, ++j); /* Index, starts with 1. */
|
|
lp.pilot = p;
|
|
lua_pushpilot(L, lp); /* value = LuaPilot */
|
|
lua_rawset(L, -3); /* Store the value in the table. */
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilot_clear(lua_State* L)
|
|
* @ingroup PILOT
|
|
*
|
|
* @brief clear(nil)
|
|
*
|
|
* Clears the current system of pilots. Used for epic battles and such.
|
|
*/
|
|
static int pilot_clear(lua_State* L) {
|
|
(void) L;
|
|
pilots_clean();
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilot_toggleSpawn(lua_State* L)
|
|
* @ingroup PILOT
|
|
*
|
|
* @brief bool togglespawn( [bool enable] )
|
|
*
|
|
* Disable or enable pilot spawning in the current system. If player jumps
|
|
* the spawn is enabled again automatically.
|
|
* @param enable true enables spawn, false disables it.
|
|
* @return The current spawn state.
|
|
*/
|
|
static int pilot_toggleSpawn(lua_State* L) {
|
|
/* Setting it directly. */
|
|
if((lua_gettop(L) > 0) && lua_isboolean(L, 1))
|
|
space_spawn = lua_toboolean(L, 1);
|
|
/* Toggling. */
|
|
else
|
|
space_spawn = !space_spawn;
|
|
|
|
lua_pushboolean(L, space_spawn);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilotL_eq(lua_State* L)
|
|
*
|
|
* @brief bool __eq(Pilot p)
|
|
*
|
|
* Check to see if pilot and p are the same.
|
|
* @param p Pilot to compare against.
|
|
* @return true if they are the same.
|
|
*/
|
|
static int pilotL_eq(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
LuaPilot* p1, *p2;
|
|
|
|
/* Get parameters. */
|
|
p1 = lua_topilot(L, 1);
|
|
if(lua_ispilot(L, 2))
|
|
p2 = lua_topilot(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Push result. */
|
|
lua_pushboolean(L, p1->pilot == p2->pilot);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilotL_name(lua_State* L)
|
|
* @ingroup META_PILOT
|
|
*
|
|
* @brief string name(nil)
|
|
*
|
|
* Get the pilots current name.
|
|
* @return The current name of the pilot.
|
|
*/
|
|
static int pilotL_name(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
LuaPilot* p1;
|
|
Pilot* p;
|
|
|
|
/* Parse parameters. */
|
|
p1 = lua_topilot(L, 1);
|
|
p = pilot_get(p1->pilot);
|
|
|
|
/* Pilot must exist. */
|
|
if(p == NULL) return 0;
|
|
|
|
/* Get name. */
|
|
lua_pushstring(L, p->name);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilotL_rename(lua_State* L)
|
|
*
|
|
* @brief rename(string name)
|
|
*
|
|
* Changes the pilots name.
|
|
* @param name Name to change to.
|
|
*/
|
|
static int pilotL_rename(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
LuaPilot* p1;
|
|
char* name;
|
|
Pilot* p;
|
|
|
|
/* Parse parameters. */
|
|
p1 = lua_topilot(L, 1);
|
|
p = pilot_get(p1->pilot);
|
|
if(lua_isstring(L, 2))
|
|
name = (char*)lua_tostring(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Pilot must exist. */
|
|
if(p == NULL) return 0;
|
|
|
|
/* Change name. */
|
|
if(p->name != NULL)
|
|
free(p->name);
|
|
p->name = strdup(name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilotL_position(lua_State* L)
|
|
*
|
|
* @brief Vec2 position( nil )
|
|
*
|
|
* Get the pilots position.
|
|
* @return The pilots current position.
|
|
*/
|
|
static int pilotL_position(lua_State* L) {
|
|
LLUA_MIN_ARGS(1);
|
|
LuaPilot* p1;
|
|
Pilot* p;
|
|
LuaVector v;
|
|
|
|
/* Parse parameters */
|
|
p1 = lua_topilot(L, 1);
|
|
p = pilot_get(p1->pilot);
|
|
|
|
/* Pilot must exist. */
|
|
if(p == NULL) return 0;
|
|
|
|
/* Push position. */
|
|
vectcpy(&v.vec, &p->solid->pos);
|
|
lua_pushvector(L, v);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* @fn static int pilotL_warp(lua_State* L)
|
|
* @ingroup META_PILOT
|
|
*
|
|
* @brief Vec2 position.
|
|
* @return The pilots current position.
|
|
*/
|
|
static int pilotL_warp(lua_State* L) {
|
|
LLUA_MIN_ARGS(2);
|
|
LuaPilot* p1;
|
|
Pilot* p;
|
|
LuaVector* v;
|
|
|
|
/* Parse parameters. */
|
|
p1 = lua_topilot(L, 1);
|
|
p = pilot_get(p1->pilot);
|
|
if(lua_isvector(L,2))
|
|
v = lua_tovector(L, 2);
|
|
else LLUA_INVALID_PARAMETER();
|
|
|
|
/* Pilot must exist. */
|
|
if(p == NULL) return 0;
|
|
|
|
/* Warp pilot to new position. */
|
|
vectcpy(&p->solid->pos, &v->vec);
|
|
vectnull(&p->solid->vel); /* Clear velocity otherwise it's a bit weird. */
|
|
return 0;
|
|
}
|
|
|