1 /*
2  * See Licensing and Copyright notice in naev.h
3  */
4 
5 /**
6  * @file nlua_faction.c
7  *
8  * @brief Handles the Lua faction bindings.
9  *
10  * These bindings control the factions.
11  */
12 
13 #include "nlua_faction.h"
14 
15 #include "naev.h"
16 
17 #include <lauxlib.h>
18 
19 #include "log.h"
20 #include "nluadef.h"
21 #include "nlua_tex.h"
22 #include "nlua_col.h"
23 #include "faction.h"
24 
25 
26 /* Faction metatable methods */
27 static int factionL_get( lua_State *L );
28 static int factionL_eq( lua_State *L );
29 static int factionL_name( lua_State *L );
30 static int factionL_longname( lua_State *L );
31 static int factionL_areenemies( lua_State *L );
32 static int factionL_areallies( lua_State *L );
33 static int factionL_modplayer( lua_State *L );
34 static int factionL_modplayersingle( lua_State *L );
35 static int factionL_modplayerraw( lua_State *L );
36 static int factionL_setplayerstanding( lua_State *L );
37 static int factionL_playerstanding( lua_State *L );
38 static int factionL_enemies( lua_State *L );
39 static int factionL_allies( lua_State *L );
40 static int factionL_logoSmall( lua_State *L );
41 static int factionL_logoTiny( lua_State *L );
42 static int factionL_colour( lua_State *L );
43 static int factionL_isknown( lua_State *L );
44 static int factionL_setknown( lua_State *L );
45 static const luaL_reg faction_methods[] = {
46    { "get", factionL_get },
47    { "__eq", factionL_eq },
48    { "__tostring", factionL_name },
49    { "name", factionL_name },
50    { "longname", factionL_longname },
51    { "areEnemies", factionL_areenemies },
52    { "areAllies", factionL_areallies },
53    { "modPlayer", factionL_modplayer },
54    { "modPlayerSingle", factionL_modplayersingle },
55    { "modPlayerRaw", factionL_modplayerraw },
56    { "setPlayerStanding", factionL_setplayerstanding },
57    { "playerStanding", factionL_playerstanding },
58    { "enemies", factionL_enemies },
59    { "allies", factionL_allies },
60    { "logoSmall", factionL_logoSmall },
61    { "logoTiny", factionL_logoTiny },
62    { "colour", factionL_colour },
63    { "known", factionL_isknown },
64    { "setKnown", factionL_setknown },
65    {0,0}
66 }; /**< Faction metatable methods. */
67 
68 
69 /**
70  * @brief Loads the faction library.
71  *
72  *    @param env Environment to load faction library into.
73  *    @return 0 on success.
74  */
nlua_loadFaction(nlua_env env)75 int nlua_loadFaction( nlua_env env )
76 {
77    nlua_register(env, FACTION_METATABLE, faction_methods, 1);
78    return 0; /* No error */
79 }
80 
81 
82 /**
83  * @brief Lua bindings to deal with factions.
84  *
85  * Use like:
86  * @code
87  * f = faction.get( "Empire" )
88  * if f:playerStanding() < 0 then
89  *    -- player is hostile to "Empire"
90  * end
91  * @endcode
92  *
93  * @luamod faction
94  */
95 /**
96  * @brief Gets the faction based on its name.
97  *
98  * @usage f = faction.get( "Empire" )
99  *
100  *    @luatparam string name Name of the faction to get.
101  *    @luatreturn Faction The faction matching name.
102  * @luafunc get( name )
103  */
factionL_get(lua_State * L)104 static int factionL_get( lua_State *L )
105 {
106    LuaFaction f;
107    const char *name;
108 
109    name = luaL_checkstring(L,1);
110    f = faction_get(name);
111    if (f < 0) {
112       NLUA_ERROR(L,"Faction '%s' not found in stack.", name );
113       return 0;
114    }
115    lua_pushfaction(L,f);
116    return 1;
117 }
118 
119 
120 /**
121  * @brief Gets faction at index.
122  *
123  *    @param L Lua state to get faction from.
124  *    @param ind Index position to find the faction.
125  *    @return Faction found at the index in the state.
126  */
lua_tofaction(lua_State * L,int ind)127 LuaFaction lua_tofaction( lua_State *L, int ind )
128 {
129    return *((LuaFaction*) lua_touserdata(L,ind));
130 }
131 
132 
133 /**
134  * @brief Gets faction (or faction name) at index, raising an error if type isn't a valid faction.
135  *
136  *    @param L Lua state to get faction from.
137  *    @param ind Index position to find the faction.
138  *    @return Faction found at the index in the state.
139  */
luaL_validfaction(lua_State * L,int ind)140 LuaFaction luaL_validfaction( lua_State *L, int ind )
141 {
142    int id;
143 
144    if (lua_isfaction(L,ind))
145       id = lua_tofaction(L,ind);
146    else if (lua_isstring(L,ind))
147       id = faction_get( lua_tostring(L, ind) );
148    else {
149       luaL_typerror(L, ind, FACTION_METATABLE);
150       return 0;
151    }
152 
153    if (id == -1)
154       NLUA_ERROR(L,"Faction '%s' not found in stack.", lua_tostring(L,ind) );
155 
156    return id;
157 }
158 
159 
160 /**
161  * @brief Pushes a faction on the stack.
162  *
163  *    @param L Lua state to push faction into.
164  *    @param faction Faction to push.
165  *    @return Newly pushed faction.
166  */
lua_pushfaction(lua_State * L,LuaFaction faction)167 LuaFaction* lua_pushfaction( lua_State *L, LuaFaction faction )
168 {
169    LuaFaction *f;
170    f = (LuaFaction*) lua_newuserdata(L, sizeof(LuaFaction));
171    *f = faction;
172    luaL_getmetatable(L, FACTION_METATABLE);
173    lua_setmetatable(L, -2);
174    return f;
175 }
176 /**
177  * @brief Checks to see if ind is a faction.
178  *
179  *    @param L Lua state to check.
180  *    @param ind Index position to check.
181  *    @return 1 if ind is a faction.
182  */
lua_isfaction(lua_State * L,int ind)183 int lua_isfaction( lua_State *L, int ind )
184 {
185    int ret;
186 
187    if (lua_getmetatable(L,ind)==0)
188       return 0;
189    lua_getfield(L, LUA_REGISTRYINDEX, FACTION_METATABLE);
190 
191    ret = 0;
192    if (lua_rawequal(L, -1, -2))  /* does it have the correct mt? */
193       ret = 1;
194 
195    lua_pop(L, 2);  /* remove both metatables */
196    return ret;
197 }
198 
199 /**
200  * @brief __eq (equality) metamethod for factions.
201  *
202  * You can use the '==' operator within Lua to compare factions with this.
203  *
204  * @usage if f == faction.get( "Dvaered" ) then
205  *
206  *    @luatparam Faction f Faction comparing.
207  *    @luatparam Faction comp faction to compare against.
208  *    @luatreturn boolean true if both factions are the same.
209  * @luafunc __eq( f, comp )
210  */
factionL_eq(lua_State * L)211 static int factionL_eq( lua_State *L )
212 {
213    int a, b;
214    a = luaL_validfaction(L,1);
215    b = luaL_validfaction(L,2);
216    lua_pushboolean(L, a == b);
217    return 1;
218 }
219 
220 /**
221  * @brief Gets the faction's name.
222  *
223  * @usage name = f:name()
224  *
225  *    @luatparam Faction f The faction to get the name of.
226  *    @luatreturn string The name of the faction.
227  * @luafunc name( f )
228  */
factionL_name(lua_State * L)229 static int factionL_name( lua_State *L )
230 {
231    int f;
232    f = luaL_validfaction(L,1);
233    lua_pushstring(L, faction_name(f));
234    return 1;
235 }
236 
237 /**
238  * @brief Gets the faction's long name.
239  *
240  * @usage longname = f:longname()
241  *    @luatparam Faction f Faction to get long name of.
242  *    @luatreturn string The long name of the faction.
243  * @luafunc longname( f )
244  */
factionL_longname(lua_State * L)245 static int factionL_longname( lua_State *L )
246 {
247    int f;
248    f = luaL_validfaction(L,1);
249    lua_pushstring(L, faction_longname(f));
250    return 1;
251 }
252 
253 /**
254  * @brief Checks to see if f is an enemy of e.
255  *
256  * @usage if f:areEnemies( faction.get( "Dvaered" ) ) then
257  *
258  *    @luatparam Faction f Faction to check against.
259  *    @luatparam Faction e Faction to check if is an enemy.
260  *    @luatreturn string true if they are enemies, false if they aren't.
261  * @luafunc areEnemies( f, e )
262  */
factionL_areenemies(lua_State * L)263 static int factionL_areenemies( lua_State *L )
264 {
265    int f, ff;
266    f  = luaL_validfaction(L,1);
267    ff = luaL_validfaction(L,2);
268 
269    lua_pushboolean(L, areEnemies( f, ff ));
270    return 1;
271 }
272 
273 /**
274  * @brief Checks to see if f is an ally of a.
275  *
276  * @usage if f:areAllies( faction.get( "Pirate" ) ) then
277  *
278  *    @luatparam Faction f Faction to check against.
279  *    @luatparam faction a Faction to check if is an enemy.
280  *    @luatreturn boolean true if they are enemies, false if they aren't.
281  * @luafunc areAllies( f, a )
282  */
factionL_areallies(lua_State * L)283 static int factionL_areallies( lua_State *L )
284 {
285    int f, ff;
286    f  = luaL_validfaction(L,1);
287    ff = luaL_validfaction(L,2);
288 
289    lua_pushboolean(L, areAllies( f, ff ));
290    return 1;
291 }
292 
293 /**
294  * @brief Modifies the player's standing with the faction.
295  *
296  * Also modifies standing with allies and enemies of the faction.
297  *
298  * @usage f:modPlayer( -5 ) -- Lowers faction by 5
299  *
300  *    @luatparam Faction f Faction to modify player's standing with.
301  *    @luatparam number mod The modifier to modify faction by.
302  * @luafunc modPlayer( f, mod )
303  */
factionL_modplayer(lua_State * L)304 static int factionL_modplayer( lua_State *L )
305 {
306    int f;
307    double n;
308 
309    NLUA_CHECKRW(L);
310 
311    f = luaL_validfaction(L,1);
312    n = luaL_checknumber(L,2);
313    faction_modPlayer( f, n, "script" );
314 
315    return 0;
316 }
317 
318 /**
319  * @brief Modifies the player's standing with the faction.
320  *
321  * Does not affect other faction standings.
322  *
323  * @usage f:modPlayerSingle( 10 )
324  *
325  *    @luatparam Faction f Faction to modify player's standing with.
326  *    @luatparam number mod The modifier to modify faction by.
327  * @luafunc modPlayerSingle( f, mod )
328  */
factionL_modplayersingle(lua_State * L)329 static int factionL_modplayersingle( lua_State *L )
330 {
331    int f;
332    double n;
333 
334    NLUA_CHECKRW(L);
335 
336    f = luaL_validfaction(L,1);
337    n = luaL_checknumber(L,2);
338    faction_modPlayerSingle( f, n, "script" );
339 
340    return 0;
341 }
342 
343 /**
344  * @brief Modifies the player's standing with the faction.
345  *
346  * Does not affect other faction standings and is not processed by the faction
347  *  Lua script, so it indicates exactly the amount to be changed.
348  *
349  * @usage f:modPlayerRaw( 10 )
350  *
351  *    @luatparam Faction f Faction to modify player's standing with.
352  *    @luatparam number mod The modifier to modify faction by.
353  * @luafunc modPlayerRaw( f, mod )
354  */
factionL_modplayerraw(lua_State * L)355 static int factionL_modplayerraw( lua_State *L )
356 {
357    int f;
358    double n;
359 
360    NLUA_CHECKRW(L);
361 
362    f = luaL_validfaction(L,1);
363    n = luaL_checknumber(L,2);
364    faction_modPlayerRaw( f, n );
365 
366    return 0;
367 }
368 
369 /**
370  * @brief Sets the player's standing with the faction.
371  *
372  * @usage f:setPlayerStanding(70) -- Make player an ally
373  *
374  *    @luatparam Faction f Faction to set the player's standing for.
375  *    @luatparam number value Value to set the player's standing to (from -100 to 100).
376  * @luafunc setPlayerStanding( f, value )
377  */
factionL_setplayerstanding(lua_State * L)378 static int factionL_setplayerstanding( lua_State *L )
379 {
380    int f;
381    double n;
382 
383    NLUA_CHECKRW(L);
384 
385    f = luaL_validfaction( L, 1 );
386    n = luaL_checknumber( L, 2 );
387    faction_setPlayer( f, n );
388 
389    return 0;
390 }
391 
392 /**
393  * @brief Gets the player's standing with the faction.
394  *
395  * @usage if f:playerStanding() > 70 then -- Player is an ally
396  *
397  *    @luatparam Faction f Faction to get player's standing with.
398  *    @luatreturn number The value of the standing and the human readable string.
399  * @luafunc playerStanding( f )
400  */
factionL_playerstanding(lua_State * L)401 static int factionL_playerstanding( lua_State *L )
402 {
403    int f;
404    double n;
405 
406    f = luaL_validfaction( L, 1 );
407    n = faction_getPlayer( f );
408 
409    lua_pushnumber( L, n );
410    lua_pushstring( L, faction_getStandingText( f ) );
411 
412    return 2;
413 }
414 
415 /**
416  * @brief Gets the enemies of the faction.
417  *
418  * @usage for k,v in pairs(f:enemies()) do -- Iterates over enemies
419  *
420  *    @luatparam Faction f Faction to get enemies of.
421  *    @luatreturn {Faction,...} A table containing the enemies of the faction.
422  * @luafunc enemies( f )
423  */
factionL_enemies(lua_State * L)424 static int factionL_enemies( lua_State *L )
425 {
426    int i, n, f;
427    int *factions;
428 
429    f = luaL_validfaction(L,1);
430 
431    /* Push the enemies in a table. */
432    lua_newtable(L);
433    factions = faction_getEnemies( f, &n );
434    for (i=0; i<n; i++) {
435       lua_pushnumber(L, i+1); /* key */
436       lua_pushfaction(L, factions[i]); /* value */
437       lua_rawset(L, -3);
438    }
439 
440    return 1;
441 }
442 
443 /**
444  * @brief Gets the allies of the faction.
445  *
446  * @usage for k,v in pairs(f:allies()) do -- Iterate over faction allies
447  *
448  *    @luatparam Faction f Faction to get allies of.
449  *    @luatreturn {Faction,...} A table containing the allies of the faction.
450  * @luafunc allies( f )
451  */
factionL_allies(lua_State * L)452 static int factionL_allies( lua_State *L )
453 {
454    int i, n, f;
455    int *factions;
456 
457    f = luaL_validfaction(L,1);
458 
459    /* Push the enemies in a table. */
460    lua_newtable(L);
461    factions = faction_getAllies( f, &n );
462    for (i=0; i<n; i++) {
463       lua_pushnumber(L, i+1); /* key */
464       lua_pushfaction(L, factions[i]); /* value */
465       lua_rawset(L, -3);
466    }
467 
468    return 1;
469 }
470 
471 
472 /**
473  * @brief Gets the small faction logo which is 64x64 or smaller.
474  *
475  *    @luatparam Faction f Faction to get logo from.
476  *    @luatreturn Tex The small faction logo or nil if not applicable.
477  * @luafunc logoSmall( f )
478  */
factionL_logoSmall(lua_State * L)479 static int factionL_logoSmall( lua_State *L )
480 {
481    int lf;
482    glTexture *tex;
483    lf = luaL_validfaction(L,1);
484    tex = faction_logoSmall( lf );
485    if (tex == NULL)
486       return 0;
487    lua_pushtex( L, gl_dupTexture( tex ) );
488    return 1;
489 }
490 
491 
492 /**
493  * @brief Gets the tiny faction logo which is 24x24 or smaller.
494  *
495  *    @luatparam Faction f Faction to get logo from.
496  *    @luatreturn Tex The tiny faction logo or nil if not applicable.
497  * @luafunc logoTiny( f )
498  */
factionL_logoTiny(lua_State * L)499 static int factionL_logoTiny( lua_State *L )
500 {
501    int lf;
502    glTexture *tex;
503    lf = luaL_validfaction(L,1);
504    tex = faction_logoTiny( lf );
505    if (tex == NULL)
506       return 0;
507    lua_pushtex( L, gl_dupTexture( tex ) );
508    return 1;
509 }
510 
511 
512 /**
513  * @brief Gets the faction colour.
514  *
515  *    @luatparam Faction f Faction to get colour from.
516  *    @luatreturn Colour|nil The faction colour or nil if not applicable.
517  * @luafunc colour( f )
518  */
factionL_colour(lua_State * L)519 static int factionL_colour( lua_State *L )
520 {
521    int lf;
522    const glColour *col;
523    lf = luaL_validfaction(L,1);
524    col = faction_getColour(lf);
525    if (col == NULL)
526       return 0;
527    lua_pushcolour( L, *col );
528    return 1;
529 }
530 
531 
532 /**
533  * @brief Checks to see if a faction is known by the player.
534  *
535  * @usage b = f:known()
536  *
537  *    @luatparam Faction f Faction to check if the player knows.
538  *    @luatreturn boolean true if the player knows the faction.
539  * @luafunc known( f )
540  */
factionL_isknown(lua_State * L)541 static int factionL_isknown( lua_State *L )
542 {
543    int fac = luaL_validfaction(L, 1);
544    lua_pushboolean(L, faction_isKnown(fac));
545    return 1;
546 }
547 
548 
549 /**
550  * @brief Sets a faction's known state.
551  *
552  * @usage f:setKnown( false ) -- Makes faction unknown.
553  *    @luatparam Faction f Faction to set known.
554  *    @luatparam[opt=false] boolean b Whether or not to set as known.
555  * @luafunc setKnown( f, b )
556  */
factionL_setknown(lua_State * L)557 static int factionL_setknown( lua_State *L )
558 {
559    int b, fac;
560 
561    NLUA_CHECKRW(L);
562 
563    fac = luaL_validfaction(L, 1);
564    b   = lua_toboolean(L, 2);
565 
566    faction_setKnown( fac, b );
567 
568    return 0;
569 }
570 
571