Merge branch 'master' of git://github.com/BTAxis/naev into testmission
[naev.git] / src / nlua_system.c
blob1f1985c0392fcd857ce0b5929138e747a359558f
1 /*
2 * See Licensing and Copyright notice in naev.h
3 */
5 /**
6 * @file nlua_system.c
8 * @brief Lua system module.
9 */
11 #include "nlua_system.h"
13 #include "naev.h"
15 #include "lauxlib.h"
17 #include "nlua.h"
18 #include "nluadef.h"
19 #include "nlua_faction.h"
20 #include "nlua_vec2.h"
21 #include "nlua_planet.h"
22 #include "log.h"
23 #include "rng.h"
24 #include "land.h"
25 #include "map.h"
28 /* System metatable methods */
29 static int systemL_cur( lua_State *L );
30 static int systemL_get( lua_State *L );
31 static int systemL_eq( lua_State *L );
32 static int systemL_name( lua_State *L );
33 static int systemL_faction( lua_State *L );
34 static int systemL_nebula( lua_State *L );
35 static int systemL_jumpdistance( lua_State *L );
36 static int systemL_adjacent( lua_State *L );
37 static int systemL_hasPresence( lua_State *L );
38 static int systemL_planets( lua_State *L );
39 static int systemL_security( lua_State *L );
40 static const luaL_reg system_methods[] = {
41 { "cur", systemL_cur },
42 { "get", systemL_get },
43 { "__eq", systemL_eq },
44 { "__tostring", systemL_name },
45 { "name", systemL_name },
46 { "faction", systemL_faction },
47 { "nebula", systemL_nebula },
48 { "jumpDist", systemL_jumpdistance },
49 { "adjacentSystems", systemL_adjacent },
50 { "hasPresence", systemL_hasPresence },
51 { "planets", systemL_planets },
52 { "security", systemL_security },
53 {0,0}
54 }; /**< System metatable methods. */
57 /**
58 * @brief Loads the system library.
60 * @param L State to load system library into.
61 * @param readonly Load read only functions?
62 * @return 0 on success.
64 int nlua_loadSystem( lua_State *L, int readonly )
66 (void)readonly; /* only read only atm */
68 /* Create the metatable */
69 luaL_newmetatable(L, SYSTEM_METATABLE);
71 /* Create the access table */
72 lua_pushvalue(L,-1);
73 lua_setfield(L,-2,"__index");
75 /* Register the values */
76 luaL_register(L, NULL, system_methods);
78 /* Clean up. */
79 lua_setfield(L, LUA_GLOBALSINDEX, SYSTEM_METATABLE);
81 return 0; /* No error */
85 /**
86 * @brief Lua system module.
88 * This module allows you to use the Star Systems from Lua.
90 * Typical example would be something like:
91 * @code
92 * cur = system.get() -- Gets current system
93 * sys = system.get( "Gamma Polaris" )
94 * @endcode
96 * @luamod system
98 /**
99 * @brief Gets system at index.
101 * @param L Lua state to get system from.
102 * @param ind Index position of system.
103 * @return The LuaSystem at ind.
105 LuaSystem* lua_tosystem( lua_State *L, int ind )
107 return (LuaSystem*) lua_touserdata(L,ind);
110 * @brief Gets system at index raising an error if type doesn't match.
112 * @param L Lua state to get system from.
113 * @param ind Index position of system.
114 * @return The LuaSystem at ind.
116 LuaSystem* luaL_checksystem( lua_State *L, int ind )
118 if (lua_issystem(L,ind))
119 return lua_tosystem(L,ind);
120 luaL_typerror(L, ind, SYSTEM_METATABLE);
121 return NULL;
125 * @brief Pushes a system on the stack.
127 * @param L Lua state to push system onto.
128 * @param sys System to push.
129 * @return System just pushed.
131 LuaSystem* lua_pushsystem( lua_State *L, LuaSystem sys )
133 LuaSystem *s;
134 s = (LuaSystem*) lua_newuserdata(L, sizeof(LuaSystem));
135 *s = sys;
136 luaL_getmetatable(L, SYSTEM_METATABLE);
137 lua_setmetatable(L, -2);
138 return s;
142 * @brief Checks to see if ind is a system.
144 * @param L Lua state to check.
145 * @param ind Index position to check.
146 * @return 1 if there is a system at index position.
148 int lua_issystem( lua_State *L, int ind )
150 int ret;
152 if (lua_getmetatable(L,ind)==0)
153 return 0;
154 lua_getfield(L, LUA_REGISTRYINDEX, SYSTEM_METATABLE);
156 ret = 0;
157 if (lua_rawequal(L, -1, -2)) /* does it have the correct mt? */
158 ret = 1;
160 lua_pop(L, 2); /* remove both metatables */
161 return ret;
166 * @brief Gets the current system.
168 * @usage sys = system.cur() -- Gets the current system
170 * @luareturn Current system.
171 * @luafunc cur()
173 static int systemL_cur( lua_State *L )
175 LuaSystem sys;
176 sys.s = cur_system;
177 lua_pushsystem(L,sys);
178 return 1;
183 * @brief Gets a system.
185 * Behaves differently depending on what you pass as param:
186 * - nil : -OBSOLETE- Gets the current system. Use system.cur() instead.
187 * - string : Gets the system by name.
188 * - planet : Gets the system by planet.
190 * @usage sys = system.get( p ) -- Gets system where planet 'p' is located.
191 * @usage sys = system.get( "Gamma Polaris" ) -- Gets the system by name.
193 * @luaparam param Read description for details.
194 * @luareturn System metatable matching param.
195 * @luafunc get( param )
197 static int systemL_get( lua_State *L )
199 LuaSystem sys;
200 LuaPlanet *p;
202 /* Get current system with no parameters */
203 if (lua_gettop(L) == 0) {
204 sys.s = cur_system;
206 /* Passing a string (systemname) */
207 else if (lua_isstring(L,1)) {
208 sys.s = system_get( lua_tostring(L,1) );
210 /* Passing a planet */
211 else if (lua_isplanet(L,1)) {
212 p = lua_toplanet(L,1);
213 sys.s = system_get( planet_getSystem( p->p->name ) );
215 else NLUA_INVALID_PARAMETER();
217 /* Error checking. */
218 if(sys.s == NULL) {
219 NLUA_ERROR(L, "No matching systems found.");
220 return 0;
223 /* return the system */
224 lua_pushsystem(L,sys);
225 return 1;
229 * @brief Check systems for equality.
231 * Allows you to use the '=' operator in Lua with systems.
233 * @usage if sys == system.get( "Draygar" ) then -- Do something
235 * @luaparam s System comparing.
236 * @luaparam comp System to compare against.
237 * @luareturn true if both systems are the same.
238 * @luafunc __eq( s, comp )
240 static int systemL_eq( lua_State *L )
242 LuaSystem *a, *b;
243 a = luaL_checksystem(L,1);
244 b = luaL_checksystem(L,2);
245 if (a->s == b->s)
246 lua_pushboolean(L,1);
247 else
248 lua_pushboolean(L,0);
249 return 1;
253 * @brief Returns the system's name.
255 * @usage name = sys:name()
257 * @luaparam s System to get name of.
258 * @luareturn The name of the system.
259 * @luafunc name( s )
261 static int systemL_name( lua_State *L )
263 LuaSystem *sys;
264 sys = luaL_checksystem(L,1);
265 lua_pushstring(L,sys->s->name);
266 return 1;
270 * @brief Gets system factions.
272 * @code
273 * sys = system.get() -- Get current system
274 * facts = sys:faction() -- Get factions
275 * if facts["Empire"] then
276 * -- Do something since there is at least one Empire planet in the system
277 * end
278 * @endcode
280 * @luaparam s System to get the factions of.
281 * @luareturn A table containing all the factions in the system.
282 * @luafunc faction( s )
284 static int systemL_faction( lua_State *L )
286 int i;
287 LuaSystem *sys;
288 sys = luaL_checksystem(L,1);
290 /* Return result in table */
291 lua_newtable(L);
292 for (i=0; i<sys->s->nplanets; i++) {
293 if (sys->s->planets[i]->faction > 0) { /* Faction must be valid */
294 lua_pushboolean(L,1); /* value */
295 lua_setfield(L,-2,faction_name(sys->s->planets[i]->faction)); /* key */
296 /* allows syntax foo = space.faction("foo"); if foo["bar"] then ... end */
299 return 1;
305 * @brief Gets the system's nebula parameters.
307 * @usage density, volatility = sys:nebula()
309 * @luaparam s System to get nebula parameters from.
310 * @luareturn The density and volatility of the system.
311 * @luafunc nebula( s )
313 static int systemL_nebula( lua_State *L )
315 LuaSystem *sys;
316 sys = luaL_checksystem(L,1);
318 /* Push the density and volatility. */
319 lua_pushnumber(L, sys->s->nebu_density);
320 lua_pushnumber(L, sys->s->nebu_volatility);
322 return 2;
327 * @brief Gets jump distance from current system, or to another.
329 * Does different things depending on the parameter type:
330 * - nil : Gets distance from current system.
331 * - string : Gets distance from system matching name.
332 * - system : Gets distance from system
334 * @usage d = sys:jumpDist() -- Distance from current system.
335 * @usage d = sys:jumpDist( "Draygar" ) -- Distance from system Draygar.
336 * @usage d = sys:jumpDist( another_sys ) -- Distance from system another_sys.
338 * @luaparam param See description.
339 * @luareturn Number of jumps to system.
340 * @luafunc jumpDist( param )
342 static int systemL_jumpdistance( lua_State *L )
344 LuaSystem *sys, *sysp;
345 StarSystem **s;
346 int jumps;
347 const char *start, *goal;
349 sys = luaL_checksystem(L,1);
350 start = sys->s->name;
352 if (lua_gettop(L) > 1) {
353 if (lua_isstring(L,2))
354 goal = lua_tostring(L,2);
355 else if (lua_issystem(L,2)) {
356 sysp = lua_tosystem(L,2);
357 goal = sysp->s->name;
359 else NLUA_INVALID_PARAMETER();
361 else
362 goal = cur_system->name;
364 s = map_getJumpPath( &jumps, start, goal, 1, NULL );
365 free(s);
367 lua_pushnumber(L,jumps);
368 return 1;
373 * @brief Gets all the ajacent systems to a system.
375 * @usage for k,v in pairs( sys:adjacentSystems() ) do -- Iterate over adjacent systems.
377 * @luaparam s System to get adjacent systems of.
378 * @luareturn A table with all the adjacent systems.
379 * @luafunc adjacentSystems( s )
381 static int systemL_adjacent( lua_State *L )
383 int i;
384 LuaSystem *sys, sysp;
386 sys = luaL_checksystem(L,1);
388 /* Push all adjacent systems. */
389 lua_newtable(L);
390 for (i=0; i<sys->s->njumps; i++) {
391 sysp.s = system_getIndex( sys->s->jumps[i] );
392 lua_pushnumber(L,i+1); /* key */
393 lua_pushsystem(L,sysp); /* value */
394 lua_rawset(L,-3);
397 return 1;
402 * @brief Checks to see if a faction has presence in a system.
404 * This checks to see if the faction has a possibility of having any ships at all
405 * be randomly generated in the system.
407 * @usage if sys:hasPresence( "Empire" ) then -- Checks to see if Empire has ships in the system
408 * @usage if sys:hasPresence( faction.get("Pirate") ) then -- Checks to see if the Pirate has ships in the system
410 * @luaparam s System to check to see if has presence of a certain faction.
411 * @luaparam f Faction or name of faction to check to see if has presence in the system.
412 * @luareturn true If faction has presence in the system, false otherwise.
413 * @luafunc hasPresence( s, f )
415 static int systemL_hasPresence( lua_State *L )
417 LuaSystem *sys;
418 LuaFaction *lf;
419 int fct;
420 int i, found;
422 sys = luaL_checksystem(L,1);
424 /* Get the second parameter. */
425 if (lua_isstring(L,2)) {
426 fct = faction_get( lua_tostring(L,2) );
428 else if (lua_isfaction(L,2)) {
429 lf = lua_tofaction(L,2);
430 fct = lf->f;
432 else NLUA_INVALID_PARAMETER();
434 /* Try to find a fleet of the faction. */
435 found = 0;
436 for (i=0; i<sys->s->nfleets; i++) {
437 if (sys->s->fleets[i].fleet->faction == fct) {
438 found = 1;
439 break;
443 lua_pushboolean(L, found);
444 return 1;
449 * @brief Gets the planets in a system.
451 * @usage for k,v in pairs( sys:planets() ) do -- Iterate over planets in system
452 * @usage if #sys:planets() > 0then -- System has planets
454 * @luaparam s System to get planets of
455 * @luareturn A table with all the planets
456 * @luafunc planets( s )
458 static int systemL_planets( lua_State *L )
460 int i;
461 LuaSystem *sys;
462 LuaPlanet p;
464 sys = luaL_checksystem(L,1);
466 /* Push all planets. */
467 lua_newtable(L);
468 for (i=0; i<sys->s->nplanets; i++) {
469 p.p = sys->s->planets[i];
470 lua_pushnumber(L,i+1); /* key */
471 lua_pushplanet(L,p); /* value */
472 lua_rawset(L,-3);
475 return 1;
480 * @brief Gets the security level in a system.
482 * @usage sec = sys:security()
484 * @luaparam s System to get security level of.
485 * @luareturn The security level in sys (in % -> 25 = 25%).
486 * @luafunc security( s )
488 static int systemL_security( lua_State *L )
490 LuaSystem *sys;
492 sys = luaL_checksystem(L,1);
494 lua_pushnumber(L, sys->s->security * 100. );
495 return 1;