naev 0.12.5
nlua_asteroid.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <lauxlib.h>
11
12#include "naev.h"
14
15#include "nlua_asteroid.h"
16
17#include "array.h"
18#include "nlua_commodity.h"
19#include "nlua_pilot.h"
20#include "nlua_vec2.h"
21#include "nluadef.h"
22#include "rng.h"
23#include "space.h"
24
25/* Asteroid methods. */
26static int asteroidL_eq( lua_State *L );
27static int asteroidL_tostring( lua_State *L );
28static int asteroidL_getAll( lua_State *L );
29static int asteroidL_get( lua_State *L );
30static int asteroidL_exists( lua_State *L );
31static int asteroidL_state( lua_State *L );
32static int asteroidL_setState( lua_State *L );
33static int asteroidL_field( lua_State *L );
34static int asteroidL_pos( lua_State *L );
35static int asteroidL_vel( lua_State *L );
36static int asteroidL_setPos( lua_State *L );
37static int asteroidL_setVel( lua_State *L );
38static int asteroidL_scanned( lua_State *L );
39static int asteroidL_timer( lua_State *L );
40static int asteroidL_setTimer( lua_State *L );
41static int asteroidL_armour( lua_State *L );
42static int asteroidL_setArmour( lua_State *L );
43static int asteroidL_alertRange( lua_State *L );
44static int asteroidL_materials( lua_State *L );
45
46static const luaL_Reg asteroidL_methods[] = {
47 { "__eq", asteroidL_eq },
48 { "__tostring", asteroidL_tostring },
49 { "getAll", asteroidL_getAll },
50 { "get", asteroidL_get },
51 { "exists", asteroidL_exists },
52 { "state", asteroidL_state },
53 { "setState", asteroidL_setState },
54 { "field", asteroidL_field },
55 { "pos", asteroidL_pos },
56 { "vel", asteroidL_vel },
57 { "setPos", asteroidL_setPos },
58 { "setVel", asteroidL_setVel },
59 { "scanned", asteroidL_scanned },
60 { "timer", asteroidL_timer },
61 { "setTimer", asteroidL_setTimer },
62 { "armour", asteroidL_armour },
63 { "setArmour", asteroidL_setArmour },
64 { "alertRange", asteroidL_alertRange },
65 { "materials", asteroidL_materials },
66 { 0, 0 } };
67
74int nlua_loadAsteroid( nlua_env env )
75{
76 nlua_register( env, ASTEROID_METATABLE, asteroidL_methods, 1 );
77 return 0;
78}
79
87LuaAsteroid_t *lua_toasteroid( lua_State *L, int ind )
88{
89 return (LuaAsteroid_t *)lua_touserdata( L, ind );
90}
91
99LuaAsteroid_t *luaL_checkasteroid( lua_State *L, int ind )
100{
101 if ( lua_isasteroid( L, ind ) )
102 return lua_toasteroid( L, ind );
103 luaL_typerror( L, ind, ASTEROID_METATABLE );
104 return NULL;
105}
106
113Asteroid *luaL_validasteroid( lua_State *L, int ind )
114{
115 Asteroid *a;
116 if ( lua_isasteroid( L, ind ) ) {
117 const LuaAsteroid_t *la = luaL_checkasteroid( L, ind );
118#if DEBUGGING
119 if ( ( la->parent < 0 ) ||
120 ( la->parent >= array_size( cur_system->asteroids ) ) ) {
121 NLUA_ERROR( L, _( "Asteroid field '%d' is out of range!" ),
122 la->parent );
123 return NULL;
124 }
125#endif /* DEBUGGING */
126 AsteroidAnchor *field = &cur_system->asteroids[la->parent];
127#if DEBUGGING
128 if ( ( la->id < 0 ) || ( la->id >= array_size( field->asteroids ) ) ) {
129 NLUA_ERROR( L, _( "Asteroid '%d' in field '%d' is out of range!" ),
130 la->id, la->parent );
131 return NULL;
132 }
133#endif /* DEBUGGING */
134 a = &field->asteroids[la->id];
135 } else {
136 luaL_typerror( L, ind, ASTEROID_METATABLE );
137 return NULL;
138 }
139
140 if ( a == NULL ) {
141 NLUA_ERROR( L, _( "Asteroid is invalid" ) );
142 return NULL;
143 }
144
145 return a;
146}
147
155{
156 LuaAsteroid_t *la =
157 (LuaAsteroid_t *)lua_newuserdata( L, sizeof( LuaAsteroid_t ) );
158 *la = asteroid;
159 luaL_getmetatable( L, ASTEROID_METATABLE );
160 lua_setmetatable( L, -2 );
161 return la;
162}
163
170int lua_isasteroid( lua_State *L, int ind )
171{
172 int ret;
173
174 if ( lua_getmetatable( L, ind ) == 0 )
175 return 0;
176 lua_getfield( L, LUA_REGISTRYINDEX, ASTEROID_METATABLE );
177
178 ret = 0;
179 if ( lua_rawequal( L, -1, -2 ) ) /* does it have the correct mt? */
180 ret = 1;
181
182 lua_pop( L, 2 ); /* remove both metatables */
183 return ret;
184}
185
200static int asteroidL_eq( lua_State *L )
201{
202 LuaAsteroid_t *a1 = luaL_checkasteroid( L, 1 );
203 LuaAsteroid_t *a2 = luaL_checkasteroid( L, 2 );
204 lua_pushboolean( L, ( memcmp( a1, a2, sizeof( LuaAsteroid_t ) ) == 0 ) );
205 return 1;
206}
207
219static int asteroidL_tostring( lua_State *L )
220{
221 char buf[STRMAX_SHORT];
222 const Asteroid *a = luaL_validasteroid( L, 1 );
223 snprintf( buf, sizeof( buf ), "Asteroid(%s)", a->type->name );
224 lua_pushstring( L, buf );
225 return 1;
226}
227
234static int asteroidL_getAll( lua_State *L )
235{
236 int n = 1;
237 lua_newtable( L );
238 for ( int i = 0; i < array_size( cur_system->asteroids ); i++ ) {
239 const AsteroidAnchor *ast = &cur_system->asteroids[i];
240 for ( int j = 0; j < array_size( ast->asteroids ); j++ ) {
241 const Asteroid *a = &ast->asteroids[j];
242 LuaAsteroid_t la = {
243 .parent = a->parent,
244 .id = a->id,
245 };
246
247 lua_pushasteroid( L, la );
248 lua_rawseti( L, -2, n++ );
249 }
250 }
251
252 return 1;
253}
254
265static int asteroidL_get( lua_State *L )
266{
267 LuaAsteroid_t la;
268 int field = -1;
269 const vec2 *pos = NULL;
270
271 /* No asteroids, so everything just returns nil. */
272 if ( array_size( cur_system->asteroids ) <= 0 )
273 return 0;
274
275 if ( lua_isvector( L, 1 ) )
276 pos = lua_tovector( L, 1 );
277
278 else if ( lua_ispilot( L, 1 ) )
279 pos = &luaL_validpilot( L, 1 )->solid.pos;
280
281 else if ( lua_isnoneornil( L, 1 ) ) {
282 int max_field = array_size( cur_system->asteroids ) - 1;
283 field = ( max_field < 0 ? max_field : RNG( 0, max_field ) );
284 } else if ( lua_isnumber( L, 1 ) ) {
285 field = luaL_checkinteger( L, 1 ) - 1;
286 if ( ( field < 0 ) || ( field >= array_size( cur_system->asteroids ) ) )
287 NLUA_INVALID_PARAMETER( L, 1 );
288 } else
289 NLUA_INVALID_PARAMETER( L, 1 );
290
291 /* Get random asteroid. */
292 if ( ( pos == NULL ) && ( field >= 0 ) ) {
293 /* Random asteroid. */
294 int nast = array_size( cur_system->asteroids[field].asteroids );
295 if ( nast <= 0 )
296 return 0;
297 int ast = RNG( 0, nast - 1 );
298 int bad_asteroid = 0;
299 Asteroid *a = &cur_system->asteroids[field].asteroids[ast];
300
301 if ( a->state != ASTEROID_FG ) {
302 int n = array_size( cur_system->asteroids[field].asteroids );
303 /* Switch to next index until we find a valid one, or until we come
304 * full-circle. */
305 bad_asteroid = 1;
306 for ( int i = 0; i < n; i++ ) {
307 ast = ( ast + 1 ) % n;
308 a = &cur_system->asteroids[field].asteroids[ast];
309 if ( a->state == ASTEROID_FG ) {
310 bad_asteroid = 0;
311 break;
312 }
313 }
314 }
315
316 if ( bad_asteroid )
317 return 0;
318
319 la.parent = field;
320 la.id = ast;
321 lua_pushasteroid( L, la );
322 return 1;
323 }
324
325 /* Try to find nearest asteroid. */
326 Asteroid *a_closest = NULL;
327 double dist2 = HUGE_VAL;
328 for ( int i = 0; i < array_size( cur_system->asteroids ); i++ ) {
329 AsteroidAnchor *ast = &cur_system->asteroids[i];
330 for ( int j = 0; j < array_size( ast->asteroids ); j++ ) {
331 double d2;
332 Asteroid *a = &ast->asteroids[j];
333
334 if ( a->state != ASTEROID_FG )
335 continue;
336
337 d2 = vec2_dist2( pos, &a->sol.pos );
338 if ( d2 > dist2 )
339 continue;
340
341 a_closest = a;
342 dist2 = d2;
343 }
344 }
345 if ( a_closest == NULL )
346 return 0;
347
348 /* Got an asteroid, ship it. */
349 la.parent = a_closest->parent;
350 la.id = a_closest->id;
351 lua_pushasteroid( L, la );
352 return 1;
353}
354
362static int asteroidL_exists( lua_State *L )
363{
364 if ( !lua_isasteroid( L, 1 ) ) {
365 lua_pushboolean( L, 0 );
366 return 1;
367 }
368
369 const LuaAsteroid_t *la = luaL_checkasteroid( L, 1 );
370 if ( ( la->parent < 0 ) ||
371 ( la->parent >= array_size( cur_system->asteroids ) ) ) {
372 lua_pushboolean( L, 0 );
373 return 1;
374 }
375
376 AsteroidAnchor *field = &cur_system->asteroids[la->parent];
377 if ( ( la->id < 0 ) || ( la->id >= array_size( field->asteroids ) ) ) {
378 lua_pushboolean( L, 0 );
379 return 1;
380 }
381
382 const Asteroid *a = &field->asteroids[la->id];
383 lua_pushboolean( L, ( a->state == ASTEROID_FG ) );
384 return 1;
385}
386
395static int asteroidL_state( lua_State *L )
396{
397 const Asteroid *ast = luaL_validasteroid( L, 1 );
398 const char *state = NULL;
399 switch ( ast->state ) {
400 case ASTEROID_FG:
401 state = "FG";
402 break;
403 case ASTEROID_XB:
404 state = "XB";
405 break;
406 case ASTEROID_BX:
407 state = "BX";
408 break;
409 case ASTEROID_XX_TO_BG:
410 state = "XX_TO_BG";
411 break;
412 case ASTEROID_FG_TO_BG:
413 state = "FG_TO_BG";
414 break;
415 case ASTEROID_BG_TO_FG:
416 state = "BG_TO_FG";
417 break;
418 case ASTEROID_BG_TO_XX:
419 state = "BG_TO_XX";
420 break;
421 case ASTEROID_XX:
422 state = "XX";
423 break;
424 }
425 lua_pushstring( L, state );
426 return 1;
427}
428
437static int asteroidL_setState( lua_State *L )
438{
439 Asteroid *ast = luaL_validasteroid( L, 1 );
440 const char *state = luaL_checkstring( L, 2 );
441 if ( strcmp( state, "FG" ) == 0 )
442 ast->state = ASTEROID_FG;
443 else if ( strcmp( state, "XB" ) == 0 )
444 ast->state = ASTEROID_XB;
445 else if ( strcmp( state, "BX" ) == 0 )
446 ast->state = ASTEROID_BX;
447 else if ( strcmp( state, "XX_TO_BG" ) == 0 )
448 ast->state = ASTEROID_XX_TO_BG;
449 else if ( strcmp( state, "FG_TO_BG" ) == 0 )
450 ast->state = ASTEROID_FG_TO_BG;
451 else if ( strcmp( state, "BG_TO_FG" ) == 0 )
452 ast->state = ASTEROID_BG_TO_FG;
453 else if ( strcmp( state, "BG_TO_XX" ) == 0 )
454 ast->state = ASTEROID_BG_TO_XX;
455 else if ( strcmp( state, "XX" ) == 0 )
456 ast->state = ASTEROID_XX;
457 else
458 NLUA_INVALID_PARAMETER( L, 2 );
459 return 0;
460}
461
470static int asteroidL_field( lua_State *L )
471{
472 const LuaAsteroid_t *la = luaL_checkasteroid( L, 1 );
473 lua_pushinteger( L, la->parent + 1 );
474 return 1;
475}
476
484static int asteroidL_pos( lua_State *L )
485{
486 const Asteroid *a = luaL_validasteroid( L, 1 );
487 lua_pushvector( L, a->sol.pos );
488 return 1;
489}
490
498static int asteroidL_vel( lua_State *L )
499{
500 const Asteroid *a = luaL_validasteroid( L, 1 );
501 lua_pushvector( L, a->sol.vel );
502 return 1;
503}
504
512static int asteroidL_setPos( lua_State *L )
513{
514 Asteroid *a = luaL_validasteroid( L, 1 );
515 const vec2 *v = luaL_checkvector( L, 2 );
516 a->sol.pos = *v;
517 return 0;
518}
519
527static int asteroidL_setVel( lua_State *L )
528{
529 Asteroid *a = luaL_validasteroid( L, 1 );
530 const vec2 *v = luaL_checkvector( L, 2 );
531 a->sol.vel = *v;
532 return 0;
533}
534
542static int asteroidL_scanned( lua_State *L )
543{
544 const Asteroid *a = luaL_validasteroid( L, 1 );
545 lua_pushboolean( L, a->scanned );
546 return 1;
547}
548
557static int asteroidL_timer( lua_State *L )
558{
559 const Asteroid *a = luaL_validasteroid( L, 1 );
560 lua_pushnumber( L, a->timer );
561 lua_pushnumber( L, a->timer_max );
562 return 2;
563}
564
572static int asteroidL_setTimer( lua_State *L )
573{
574 Asteroid *a = luaL_validasteroid( L, 1 );
575 a->timer = luaL_checknumber( L, 2 );
576 a->timer_max = MAX( a->timer_max, a->timer );
577 return 0;
578}
579
587static int asteroidL_armour( lua_State *L )
588{
589 const Asteroid *a = luaL_validasteroid( L, 1 );
590 lua_pushnumber( L, a->armour );
591 return 1;
592}
593
602static int asteroidL_setArmour( lua_State *L )
603{
604 Asteroid *a = luaL_validasteroid( L, 1 );
605 a->armour = luaL_checknumber( L, 2 );
606 if ( a->armour <= 0. )
607 asteroid_explode( a, -1, 0. );
608 return 0;
609}
610
618static int asteroidL_alertRange( lua_State *L )
619{
620 Asteroid *a = luaL_validasteroid( L, 1 );
621 lua_pushnumber( L, a->type->alert_range );
622 return 1;
623}
624
632static int asteroidL_materials( lua_State *L )
633{
634 Asteroid *a = luaL_validasteroid( L, 1 );
635 const AsteroidType *at = a->type;
636
637 lua_newtable( L );
638 for ( int i = 0; i < array_size( at->material ); i++ ) {
639 const AsteroidReward *mat = &at->material[i];
640 lua_newtable( L );
641
642 lua_pushcommodity( L, mat->material );
643 lua_setfield( L, -2, "commodity" );
644
645 lua_pushnumber( L, mat->quantity );
646 lua_setfield( L, -2, "quantity" );
647
648 lua_pushnumber( L, mat->rarity );
649 lua_setfield( L, -2, "rarity" );
650
651 lua_rawseti( L, -2, i + 1 );
652 }
653
654 return 1;
655}
Provides macros to work with dynamic arrays.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:179
void asteroid_explode(Asteroid *a, int max_rarity, double mining_bonus)
Makes an asteroid explode.
Definition asteroid.c:1209
Header file with generic functions and naev-specifics.
#define MAX(x, y)
Definition naev.h:37
static const luaL_Reg asteroidL_methods[]
static int asteroidL_state(lua_State *L)
Gets the state of an asteroid.
static int asteroidL_vel(lua_State *L)
Gets the velocity of an asteroid.
static int asteroidL_setState(lua_State *L)
Sets the state of an asteroid.
static int asteroidL_field(lua_State *L)
Gets the field the asteroid belongs to (useful for getting more asteroids from the same field).
static int asteroidL_scanned(lua_State *L)
Gets whether or not an asteroid got scanned.
static int asteroidL_exists(lua_State *L)
Checks to see if an asteroid exists.
static int asteroidL_materials(lua_State *L)
Gets the materials the asteroid can potentially drop.
static int asteroidL_setVel(lua_State *L)
Sets the velocity of an asteroid.
static int asteroidL_tostring(lua_State *L)
Gets the asteroid's current (translated) name or notes it is inexistent.
int nlua_loadAsteroid(nlua_env env)
Loads the asteroid library.
static int asteroidL_get(lua_State *L)
Gets an asteroid in the system.
static int asteroidL_alertRange(lua_State *L)
Gets the alert range of an asteroid.
static int asteroidL_setTimer(lua_State *L)
Sets the time left on the asteroid.
static int asteroidL_getAll(lua_State *L)
Gets all the asteroids in the system.
int lua_isasteroid(lua_State *L, int ind)
Checks to see if ind is a asteroid.
static int asteroidL_eq(lua_State *L)
Lua bindings to interact with asteroid.
LuaAsteroid_t * luaL_checkasteroid(lua_State *L, int ind)
Gets asteroid at index or raises error if there is no asteroid at index.
static int asteroidL_pos(lua_State *L)
Gets the position of an asteroid.
static int asteroidL_setPos(lua_State *L)
Sets the position of an asteroid.
static int asteroidL_setArmour(lua_State *L)
Sets the armour of the asteroid.
LuaAsteroid_t * lua_pushasteroid(lua_State *L, LuaAsteroid_t asteroid)
Pushes a asteroid on the stack.
Asteroid * luaL_validasteroid(lua_State *L, int ind)
Gets asteroid at index raising an error if type doesn't match.
LuaAsteroid_t * lua_toasteroid(lua_State *L, int ind)
Gets asteroid at index.
static int asteroidL_armour(lua_State *L)
Gets the armour (health) left on the asteroid.
static int asteroidL_timer(lua_State *L)
Gets the time left on the asteroid.
Commodity ** lua_pushcommodity(lua_State *L, Commodity *commodity)
Pushes a commodity on the stack.
Pilot * luaL_validpilot(lua_State *L, int ind)
Makes sure the pilot is valid or raises a Lua error.
Definition nlua_pilot.c:560
int lua_ispilot(lua_State *L, int ind)
Checks to see if ind is a pilot.
Definition nlua_pilot.c:591
int lua_isvector(lua_State *L, int ind)
Checks to see if ind is a vector.
Definition nlua_vec2.c:161
vec2 * luaL_checkvector(lua_State *L, int ind)
Gets vector at index making sure type is valid.
Definition nlua_vec2.c:130
vec2 * lua_tovector(lua_State *L, int ind)
Represents a 2D vector in Lua.
Definition nlua_vec2.c:119
vec2 * lua_pushvector(lua_State *L, vec2 vec)
Pushes a vector on the stack.
Definition nlua_vec2.c:145
StarSystem * cur_system
Definition space.c:110
Represents an asteroid field anchor.
Definition asteroid.h:111
Asteroid * asteroids
Definition asteroid.h:116
Represents a potential reward from the asteroid.
Definition asteroid.h:50
Commodity * material
Definition asteroid.h:51
Represents a type of asteroid.
Definition asteroid.h:59
AsteroidReward * material
Definition asteroid.h:64
Represents a single asteroid.
Definition asteroid.h:88
int id
Definition asteroid.h:90
int state
Definition asteroid.h:92
int parent
Definition asteroid.h:91
Solid solid
Definition pilot.h:275
vec2 pos
Definition physics.h:49
Represents a 2d vector.
Definition vec2.h:45