diff --git a/src/llua_faction.c b/src/llua_faction.c new file mode 100644 index 0000000..8d57dd7 --- /dev/null +++ b/src/llua_faction.c @@ -0,0 +1,358 @@ +/** + * @file llua_faction.c + * + * @breif Handle the Lua faction bindings. + * + * These bindings control the faction. + */ + +#include "lauxlib.h" + +#include "log.h" +#include "lephisto.h" +#include "llua.h" +#include "lluadef.h" +#include "faction.h" +#include "llua_faction.h" + +static int factionL_createmetatable(lua_State* L, int readonly); + +/* Faction metatable methods. */ +static int factionL_eq(lua_State* L); +static int factionL_name(lua_State* L); +static int factionL_longname(lua_State* L); +static int factionL_areenemies(lua_State* L); +static int factionL_areallies(lua_State* L); +static int factionL_modplayer(lua_State* L); +static int factionL_modplayerraw(lua_State* L); +static int factionL_playerstanding(lua_State* L); +static const luaL_reg faction_methods[] = { + { "__eq", factionL_eq }, + { "name", factionL_name }, + { "longname", factionL_longname }, + { "areEnemeies", factionL_areenemies }, + { "areAllies", factionL_areallies }, + { "modPlayer", factionL_modplayer }, + { "modPlayerRaw", factionL_modplayerraw }, + { "playerStanding", factionL_playerstanding }, + { 0, 0 } +}; /**< Faction metatable methods. */ + +static const luaL_reg faction_methods_cond[] = { + { "__eq", factionL_eq }, + { "name", factionL_name }, + { "longname", factionL_longname }, + { "areEnemeies", factionL_areenemies }, + { "areAllies", factionL_areallies }, + { "playerStanding", factionL_playerstanding }, + { 0, 0 } +}; + +/* Global faction functions. */ +static int factionL_get(lua_State* L); +static const luaL_reg factionL_methods[] = { + { "get", faction_get }, + { 0, 0 } +}; + +/** + * @fn int lua_loadFaction(lua_State* L, int readonly) + * + * @brief Load the faction library. + * @param L State to load faction library into. + * @return 0 on success. + */ +int lua_loadFaction(lua_State* L, int readonly) { + /* Register the faction functions. */ + luaL_register(L, "faction", factionL_methods); + + /* Register the metatables. */ + factionL_createmetatable(L, readonly); + + return 0; +} + +/** + * @fn static int factionL_createmetatable(lua_State* L, int readonly) + * + * @brief Register the faction metatable. + * @param L Lua state to register metatable into. + * @param readonly Whether table should be readonly. + * @return 0 on success. + */ +static int factionL_createmetatable(lua_State* L, int readonly) { + /* Create metatable. */ + luaL_newmetatable(L, FACTION_METATABLE); + + /* Create the access table. */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + + /* Register the values. */ + luaL_register(L, NULL, (readonly) ? faction_methods_cond : faction_methods); + + return 0; /* No error. */ +} + +/** + * @defgroup FACTION Faction Lua bindings. + * + * @brief Lua bindings to deal with factions. + * + * Use with: + * @code + * faction.func(params) + * @endcode + * + * @{ + */ + +/** + * @fn static int factionL_get(lua_State* L) + * + * @brief faction get(string name) + * + * Get the faction based on its name. + * @param name Name of the faction to get. + * @return The faction matching name. + */ +static int factionL_get(lua_State* L) { + LuaFaction f; + char* name; + + if(lua_isstring(L, 1)) name = (char*) lua_tostring(L, 1); + else LLUA_INVALID_PARAMETER(); + + f.f = faction_get(name); + lua_pushfaction(L, f); + return 1; +} + +/** + * @} + */ + +/** + * @defgroup META_FACTION Faction Metatable. + * + * @brief The faction metatable is a way to represent a faction in Lua. + * + * It allows all sorts of operators making it much more natural to use. + * + * To call members of the metatable always use: + * + * @code + * faction:function(param) + * @endcode + * + * @{ + */ + +/** + * @fn LuaFaction* lua_tofaction(lua_State* L, int ind) + * + * @brief Get faction at index. + * @param L Lua state to get faction from. + * @param ind Index position to find the faction. + * @return Faction found at the index in the state. + */ +LuaFaction* lua_tofaction(lua_State* L, int ind) { + if(lua_isuserdata(L, ind)) { + return (LuaFaction*) lua_touserdata(L, ind); + } + + luaL_typerror(L, ind, FACTION_METATABLE); + return NULL; +} + +/** + * @fn LuaFaction* lua_pushfaction(lua_State* L, LuaFaction faction) + * + * @brief Pushes a faction on the stack. + * @param L lua state to push faction into. + * @param faction Faction to push. + * @return Newly pushed faction. + */ +LuaFaction* lua_pushfaction(lua_State* L, LuaFaction faction) { + LuaFaction* f; + f = (LuaFaction*) lua_newuserdata(L, sizeof(LuaFaction)); + *f = faction; + luaL_getmetatable(L, FACTION_METATABLE); + lua_setmetatable(L, -2); + return f; +} + +/** + * @fn int lua_isfaction(lua_State* L, int ind) + * + * @brief Check to see if ind is a faction. + * @param L Lua state to check. + * @param ind Index position to check. + * @return 1 if ind is a faction. + */ +int lua_isfaction(lua_State* L, int ind) { + int ret; + + if(lua_getmetatable(L, ind)==0) + return 0; + lua_getfield(L, LUA_REGISTRYINDEX, FACTION_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 factionL_eq(lua_State* L) + * + * @brief bool __eq(faction comp) + * + * __eq (equality) metamethod for factions. + * + * You can use the '=' operator within Lua to compare factions with this. + * @param comp faction to compare against. + * @return true if both factions are the same. + */ +static int factionL_eq(lua_State* L) { + LuaFaction* a, *b; + a = lua_tofaction(L, 1); + b = lua_tofaction(L, 2); + lua_pushboolean(L, a->f == b->f); + return 1; +} + +/** + * @fn static int factionL_name(lua_State* L) + * + * @brief string name(nil) + * + * Get the faction's name. + * @return The name of the faction. + */ +static int factionL_name(lua_State* L) { + LuaFaction* f; + f = lua_tofaction(L, 1); + lua_pushstring(L, faction_name(f->f)); + return 1; +} + +/** + * @fn static int factionL_longname(lua_State* L) + * + * @brief string longname(nil) + * + * Get the factions long name. + * @return The long name of the faction. + */ +static int factionL_longname(lua_State* L) { + LuaFaction* f; + f = lua_tofaction(L, 1); + lua_pushstring(L, faction_longname(f->f)); + return 1; +} + +/** + * @fn static int factionL_areenemeies(lua_State* L) + * + * @brief bool areenemies(faction f) + * + * Check to see if f is an enemy. + * @param f Faction to check if is an enemy. + * @return true if they are enemeies, false if they aren't. + */ +static int factionL_areenemies(lua_State* L) { + LuaFaction* f, *ff; + f = lua_tofaction(L, 1); + if(lua_isfaction(L, 2)) ff = lua_tofaction(L, 2); + else LLUA_INVALID_PARAMETER(); + + lua_pushboolean(L, areEnemies(f->f, ff->f)); + return 1; +} + +/** + * @fn static int factionL_areallies(lua_State* L) + * + * @brief bool areEnemies(faction f) + * + * Check to see if f is an enemy. + * @param f Faction to check if is an enemy. + * @return true if they are enemies, false if they aren't. + */ +static int factionL_areallies(lua_State* L) { + LuaFaction* f, *ff; + f = lua_tofaction(L, 1); + if(lua_isfaction(L, 2)) ff = lua_tofaction(L, 2); + else LLUA_INVALID_PARAMETER(); + + lua_pushboolean(L, areAllies(f->f, ff->f)); + return 1; +} + +/** + * @fn static int factionL_modplayer(lua_State* L) + * + * @brief modPlayer(number mod) + * + * Modifies the players standing with the faction. + * @param mod The modifier to modify faction by. + */ +static int factionL_modplayer(lua_State* L) { + LuaFaction* f; + int n; + f = lua_tofaction(L, 1); + + if(lua_isnumber(L, 2)) n = lua_tonumber(L, 2); + else LLUA_INVALID_PARAMETER(); + + faction_modPlayer(f->f, n); + return 0; +} + +/** + * @fn static int factionL_modplayerraw(lua_State* L) + * + * @brief modPlayerRaw(number mod) + * + * Modifies the players standing with the faction. + * + * Does not affect other faction standings. + * @param mod The modifier to modify faction by. + */ +static int factionL_modplayerraw(lua_State* L) { + LuaFaction* f; + int n; + f = lua_tofaction(L, 1); + + if(lua_isnumber(L, 2)) n = lua_tonumber(L, 2); + else LLUA_INVALID_PARAMETER(); + + faction_modPlayerRaw(f->f, n); + return 0; +} + +/** + * @fn static int factionL_playerstanding(lua_State* L) + * + * @brief number, string playerStanding(nil) + * + * Get the players standing with the faction. + * @return The value of the standing and the human readable string. + */ +static int factionL_playerstanding(lua_State* L) { + LuaFaction* f; + int n; + f = lua_tofaction(L, 1); + n = faction_getPlayer(f->f); + lua_pushnumber(L, n); + lua_pushstring(L, faction_getStanding(n)); + return 1; +} + +/** + * @} + */ + diff --git a/src/llua_faction.h b/src/llua_faction.h new file mode 100644 index 0000000..c537795 --- /dev/null +++ b/src/llua_faction.h @@ -0,0 +1,17 @@ +#pragma once + +#define FACTION_METATABLE "Faction" + +/* Lua wrappers. */ +typedef struct LuaFaction_s { + int f; +} LuaFaction; + +/* Load the space library. */ +int lua_loadFaction(lua_State* L, int readonly); + +/* Faction operations. */ +LuaFaction* lua_tofaction(lua_State* L, int ind); +LuaFaction* lua_pushfaction(lua_State* L, LuaFaction faction); +int lua_isfaction(lua_State* L, int ind); + diff --git a/src/llua_pilot.c b/src/llua_pilot.c index c753115..34fcd9c 100644 --- a/src/llua_pilot.c +++ b/src/llua_pilot.c @@ -8,8 +8,10 @@ #include "lauxlib.h" #include "lephisto.h" -#include "llua_space.h" +#include "llua.h" #include "lluadef.h" +#include "llua_space.h" +#include "llua_faction.h" #include "rng.h" #include "pilot.h" #include "player.h" @@ -518,19 +520,25 @@ static int pilotL_setFaction(lua_State* L) { LLUA_MIN_ARGS(2); Pilot* p; LuaPilot* lp; + LuaFaction* f; int fid; char* faction; /* Parse parameters. */ lp = lua_topilot(L, 1); - if(lua_isstring(L, 2)) + if(lua_isstring(L, 2)) { faction = (char*)lua_tostring(L,2); + fid = faction_get(faction); + } + else if(lua_isfaction(L, 2)) { + f = lua_tofaction(L, 2); + fid = f->f; + } else LLUA_INVALID_PARAMETER(); /* Get pilot/faction. */ p = pilot_get(lp->pilot); if(p == NULL) return 0; - fid = faction_get(faction); /* Set the new faction. */ p->faction = fid; diff --git a/src/llua_space.c b/src/llua_space.c index b4f4bcf..d6ed420 100644 --- a/src/llua_space.c +++ b/src/llua_space.c @@ -4,7 +4,9 @@ #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" @@ -203,6 +205,7 @@ static int planetL_get(lua_State* L) { char* rndplanet; LuaPlanet planet; LuaSystem sys; + LuaFaction* f; rndplanet = NULL; nplanets = 0; @@ -220,9 +223,9 @@ static int planetL_get(lua_State* L) { } /* Get a planet by faction */ - else if(lua_isnumber(L, 1)) { - i = lua_tonumber(L, 1); - planets = space_getFactionPlanet(&nplanets, &i, 1); + else if(lua_isfaction(L, 1)) { + f = lua_tofaction(L, 1); + planets = space_getFactionPlanet(&nplanets, &f->f, 1); } /* Get a planet by name. */ @@ -237,9 +240,9 @@ static int planetL_get(lua_State* L) { nfactions = (int)lua_gettop(L); factions = malloc(sizeof(int) * nfactions); i = 0; - while(lua_next(L, -2) != 0) { - factions[i++] = (int)lua_tonumber(L, -1); + f = lua_tofaction(L, -1); + factions[i++] = f->f; lua_pop(L,1); } @@ -292,8 +295,10 @@ static int planetL_name(lua_State* L) { /* Get the planets faction. */ static int planetL_faction(lua_State* L) { LuaPlanet* p; + LuaFaction f; p = lua_toplanet(L, 1); - lua_pushstring(L, faction_name(p->p->faction)); + f.f = p->p->faction; + lua_pushfaction(L, f); return 1; } diff --git a/src/misn_lua.c b/src/misn_lua.c index 08b2c10..6661c0b 100644 --- a/src/misn_lua.c +++ b/src/misn_lua.c @@ -9,6 +9,7 @@ #include "llua.h" #include "llua_space.h" #include "llua_pilot.h" +#include "llua_faction.h" #include "lluadef.h" #include "hook.h" #include "mission.h" @@ -187,6 +188,7 @@ int misn_loadLibs(lua_State* L) { lua_loadPilot(L, 0); lua_loadMusic(L, 0); lua_loadDiff(L, 0); + lua_loadFaction(L, 0); return 0; } @@ -443,6 +445,7 @@ static int misn_setMarker(lua_State* L) { static int misn_factions(lua_State* L) { int i; MissionData* dat; + LuaFaction f; dat = cur_mission->data; @@ -450,7 +453,8 @@ static int misn_factions(lua_State* L) { lua_newtable(L); for(i = 0; i < dat->avail.nfactions; i++) { lua_pushnumber(L, i+1); /* Index, starts with 1. */ - lua_pushnumber(L, dat->avail.factions[i]); /* Value. */ + f.f = dat->avail.factions[i]; + lua_pushfaction(L, f); /* Value. */ lua_rawset(L, -3); /* Store the value in the table. */ } return 1;