/** * @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 }, { "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 ]) * * Adds a fleet to the system. * @param fleetname Name of the fleet to add. * @param ai If set will override the standard fleet AI. * @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; /* 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) && lua_isstring(L, 2)) fltai = (char*)lua_tostring(L, 2); else fltai = NULL; /* Pull the fleet. */ flt = fleet_get(fltname); if(flt == NULL) { LLUA_DEBUG("Fleet not found!"); return 0; } /* This should probably be done better. */ vect_pset(&vp, RNG(MIN_HYPERSPACE_DIST, MIN_HYPERSPACE_DIST*1.5), RNG(0,360)*M_PI/180.); vectnull(&vn); 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)); a = vect_angle(&vp, &vn); vectnull(&vv); 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; }