naev 0.12.6
asteroid.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "physfs.h"
11
12#include "naev.h"
14
15#include "asteroid.h"
16
17#include "array.h"
18#include "camera.h"
19#include "conf.h"
20#include "damagetype.h"
21#include "explosion.h"
22#include "font.h"
23#include "gatherable.h"
24#include "ndata.h"
25#include "nlua_asteroid.h"
26#include "ntracing.h"
27#include "nxml.h"
28#include "opengl.h"
29#include "player.h"
30#include "rng.h"
31#include "sound.h"
32#include "space.h"
33
37typedef struct Debris_ {
38 const glTexture *gfx;
41 double ang;
42 double height;
43 double alpha;
44} Debris;
45
46const double DEBRIS_BUFFER =
47 1000.;
48
49static const double SCAN_FADE =
50 10.;
51
53 NULL;
54static glTexture **debris_gfx = NULL;
55static double asteroid_dt =
56 0.;
57
58/*
59 * Useful data for asteroids.
60 */
62 NULL;
64 NULL;
66 NULL;
67static int asteroid_creating = 0;
68
69/* Prototypes. */
70static int asttype_cmp( const void *p1, const void *p2 );
71static int asttype_parse( AsteroidType *at, const char *file );
72static int asteroid_loadPLG( AsteroidType *temp, const char *buf );
73static int astgroup_cmp( const void *p1, const void *p2 );
74static int astgroup_parse( AsteroidTypeGroup *ag, const char *file );
75static int asttype_load( void );
76
77static int asteroid_updateSingle( Asteroid *a );
78static void asteroid_renderSingle( const Asteroid *a );
79static void debris_renderSingle( const Debris *d, double cx, double cy );
80static void debris_init( Debris *deb );
81static int asteroid_init( Asteroid *ast, const AsteroidAnchor *field );
82
83static int asteroid_updateSingle( Asteroid *a )
84{
85 const AsteroidAnchor *ast = &cur_system->asteroids[a->parent];
86 double dt = asteroid_dt;
87 double offx, offy, d;
88 int forced;
89 int setvel = 0;
90
91 /* Push back towards center. */
92 offx = ast->pos.x - a->sol.pos.x;
93 offy = ast->pos.y - a->sol.pos.y;
94 d = pow2( offx ) + pow2( offy );
95 if ( d >= pow2( ast->radius ) ) {
96 d = sqrt( d );
97 a->sol.vel.x += ast->accel * dt * offx / d;
98 a->sol.vel.y += ast->accel * dt * offy / d;
99 setvel = 1;
100 } else if ( ast->has_exclusion ) {
101 /* Push away from exclusion areas. */
102 for ( int k = 0; k < array_size( cur_system->astexclude ); k++ ) {
103 AsteroidExclusion *exc = &cur_system->astexclude[k];
104 double ex, ey, ed;
105
106 /* Ignore exclusion zones that shouldn't affect. */
107 if ( !exc->affects )
108 continue;
109
110 ex = a->sol.pos.x - exc->pos.x;
111 ey = a->sol.pos.y - exc->pos.y;
112 ed = pow2( ex ) + pow2( ey );
113 if ( ed <= pow2( exc->radius ) ) {
114 ed = sqrt( ed );
115 a->sol.vel.x += ast->accel * dt * ex / ed;
116 a->sol.vel.y += ast->accel * dt * ey / ed;
117 setvel = 1;
118 }
119 }
120 }
121
122 if ( setvel ) {
123 /* Enforce max speed. */
124 double speed = MOD( a->sol.vel.x, a->sol.vel.y );
125 if ( speed > ast->maxspeed ) {
126 a->sol.vel.x *= ast->maxspeed / speed;
127 a->sol.vel.y *= ast->maxspeed / speed;
128 }
129 }
130
131 /* Update position. */
132 /* TODO use physics.c */
133 a->sol.pre = a->sol.pos;
134 a->sol.pos.x += a->sol.vel.x * dt;
135 a->sol.pos.y += a->sol.vel.y * dt;
136
137 /* Update angle. */
138 a->ang += a->spin * dt;
139
140 /* igure out state change if applicable. */
141 forced = a->timer < 0.; /* Forced by Lua or whatever. */
142 a->timer -= dt;
143 if ( a->timer < 0. ) {
144 switch ( a->state ) {
145 /* Transition states. */
146 case ASTEROID_FG:
147 /* Don't go away if player is close. */
148 if ( !forced && ( player.p != NULL ) &&
149 ( ( vec2_dist2( &player.p->solid.pos, &a->sol.pos ) <
150 pow2( 1500. ) ) ||
151 ( ( player.p->nav_anchor == a->parent ) &&
152 ( player.p->nav_asteroid == a->id ) ) ) )
153 a->state =
154 ASTEROID_FG - 1; /* So it gets turned back into ASTEROID_FG. */
155 else
156 /* This should be thread safe as a single pilot can only target a
157 * single asteroid. */
158 pilot_untargetAsteroid( a->parent, a->id );
159 FALLTHROUGH;
160 case ASTEROID_XB:
161 case ASTEROID_BX:
162 case ASTEROID_XX_TO_BG:
163 a->timer_max = a->timer = 1. + 3. * RNGF();
164 break;
165
166 /* Longer states. */
167 case ASTEROID_FG_TO_BG:
168 a->timer_max = a->timer = 10. + 20. * RNGF();
169 break;
170 case ASTEROID_BG_TO_FG:
171 a->timer_max = a->timer = 90. + 30. * RNGF();
172 break;
173
174 /* Special case needs to respawn. */
175 case ASTEROID_BG_TO_XX:
176 asteroid_init( a, ast );
177 a->timer_max = a->timer = 10. + 20. * RNGF();
178 break;
179
180 case ASTEROID_XX:
181 /* Do nothing. */
182 break;
183 }
184 /* States should be in proper order. */
185 a->state = ( a->state + 1 ) % ASTEROID_STATE_MAX;
186 }
187
188 /* Update scanned state if necessary. */
189 if ( a->scanned ) {
190 if ( a->state == ASTEROID_FG )
191 a->scan_alpha = MIN( a->scan_alpha + SCAN_FADE * dt, 1. );
192 else
193 a->scan_alpha = MAX( a->scan_alpha - SCAN_FADE * dt, 0. );
194 }
195 return 0;
196}
197
203void asteroids_update( double dt )
204{
205 NTracingZone( _ctx, 1 );
206
207 /* Asteroids/Debris update */
208 for ( int i = 0; i < array_size( cur_system->asteroids ); i++ ) {
209 AsteroidAnchor *ast = &cur_system->asteroids[i];
210 ast->has_exclusion = 0;
211
212 for ( int k = 0; k < array_size( cur_system->astexclude ); k++ ) {
213 AsteroidExclusion *exc = &cur_system->astexclude[k];
214 if ( vec2_dist2( &ast->pos, &exc->pos ) <
215 pow2( ast->radius + exc->radius ) ) {
216 exc->affects = 1;
217 ast->has_exclusion = 1;
218 } else
219 exc->affects = 0;
220 }
221
222 /* Now just thread it and zoom. */
223 asteroid_dt = dt;
224 for ( int j = 0; j < array_size( ast->asteroids ); j++ ) {
225 Asteroid *a = &ast->asteroids[j];
226 /* Skip inexistent asteroids. */
227 if ( a->state == ASTEROID_XX ) {
228 a->timer -= dt;
229 if ( a->timer < 0. ) {
230 a->state = ASTEROID_XX_TO_BG;
231 a->timer_max = a->timer = 1. + 3. * RNGF();
232 }
233 continue;
234 }
235 asteroid_updateSingle( a );
236 }
237
238 /* Do quadtree stuff. Can't be threaded. */
239 qt_clear( &ast->qt );
240 for ( int j = 0; j < array_size( ast->asteroids ); j++ ) {
241 const Asteroid *a = &ast->asteroids[j];
242 /* Add to quadtree if in foreground. */
243 if ( a->state == ASTEROID_FG ) {
244 int x, y, w2, h2, px, py;
245 x = round( a->sol.pos.x );
246 y = round( a->sol.pos.y );
247 px = round( a->sol.pre.x );
248 py = round( a->sol.pre.y );
249 w2 = ceil( a->gfx->sw * 0.5 );
250 h2 = ceil( a->gfx->sh * 0.5 );
251 qt_insert( &ast->qt, j, MIN( x, px ) - w2, MIN( y, py ) - h2,
252 MAX( x, px ) + w2, MAX( y, py ) + h2 );
253 }
254 }
255 }
256
257 /* Only have to update stuff if not simulating. */
258 if ( !space_isSimulation() ) {
259 double dx, dy;
260 cam_getDPos( &dx, &dy );
261
262 for ( int j = 0; j < array_size( debris_stack ); j++ ) {
263 Debris *d = &debris_stack[j];
264 int infield;
265 vec2 v;
266
267 d->pos.x += d->vel.x * dt - dx;
268 d->pos.y += d->vel.y * dt - dy;
269
270 /* Check boundaries */
271 if ( d->pos.x > SCREEN_W + DEBRIS_BUFFER )
272 d->pos.x -= SCREEN_W + 2. * DEBRIS_BUFFER;
273 else if ( d->pos.y > SCREEN_H + DEBRIS_BUFFER )
274 d->pos.y -= SCREEN_H + 2. * DEBRIS_BUFFER;
275 else if ( d->pos.x < -DEBRIS_BUFFER )
276 d->pos.x += SCREEN_W + 2. * DEBRIS_BUFFER;
277 else if ( d->pos.y < -DEBRIS_BUFFER )
278 d->pos.y += SCREEN_H + 2. * DEBRIS_BUFFER;
279
280 /* Set alpha based on position. */
281 /* TODO there seems to be some offset mistake or something going on
282 * here, not too big of an issue though. */
283 gl_screenToGameCoords( &v.x, &v.y, d->pos.x, d->pos.y );
284 infield = asteroids_inField( &v );
285 if ( infield >= 0 )
286 d->alpha = MIN( 1.0, d->alpha + 0.5 * dt );
287 else
288 d->alpha = MAX( 0.0, d->alpha - 0.5 * dt );
289 }
290 }
291
292 NTracingZoneEnd( _ctx );
293}
294
298void asteroids_init( void )
299{
300 double density_max = 0.;
301 int ndebris;
302 asteroid_creating = 1;
303
304 NTracingZone( _ctx, 1 );
305
306 if ( debris_gfx == NULL )
310
311 /* Set up asteroids. */
312 for ( int i = 0; i < array_size( cur_system->asteroids ); i++ ) {
313 AsteroidAnchor *ast = &cur_system->asteroids[i];
314 int qx, qy, qr;
315 ast->id = i;
316
317 /* Add graphics to debris. */
318 for ( int j = 0; j < array_size( ast->groups ); j++ ) {
319 AsteroidTypeGroup *ag = ast->groups[j];
320 for ( int k = 0; k < array_size( ag->types ); k++ ) {
321 AsteroidType *at = ag->types[k];
322 for ( int x = 0; x < array_size( at->gfxs ); x++ )
324 }
325 }
326
327 /* Build quadtree. */
328 if ( ast->qt_init )
329 qt_destroy( &ast->qt );
330 qx = round( ast->pos.x );
331 qy = round( ast->pos.y );
332 qr = ceil( ast->radius );
333 qt_create( &ast->qt, qx - qr, qy - qr, qx + qr, qy + qr, 2, 5 );
334 ast->qt_init = 1;
335
336 /* Add the asteroids to the anchor */
338 array_end( ast->asteroids ) );
339 if ( array_size( ast->groups ) > 0 ) {
340 for ( int j = 0; j < ast->nmax; j++ ) {
341 double r = RNGF();
342 Asteroid a;
343 if ( asteroid_init( &a, ast ) ) {
344 continue;
345 }
346 a.id = array_size( ast->asteroids );
347 if ( r > 0.6 )
348 a.state = ASTEROID_FG;
349 else if ( r > 0.8 )
350 a.state = ASTEROID_XB;
351 else if ( r > 0.9 )
352 a.state = ASTEROID_BX;
353 else
354 a.state = ASTEROID_XX;
355 a.timer = a.timer_max = 30. * RNGF();
356 a.ang = RNGF() * M_PI * 2.;
357 /* Push into array. */
358 array_push_back( &ast->asteroids, a );
359 }
360 } else {
361 if ( ast->label != NULL )
362 WARN( _( "Asteroid field '%s' in system '%s' has no asteroid types "
363 "defined!" ),
364 ast->label, cur_system->name );
365 else
366 WARN( _( "Asteroid field with no label in system '%s' has no "
367 "asteroid types defined!" ),
368 cur_system->name );
369 }
370
371 density_max = MAX( density_max, ast->density );
372 }
373
374 /* Add the debris to the anchor */
375 if ( debris_stack == NULL )
377
378 /* We compute a fixed amount and scale depending on how big the screen is
379 * compared the reference (minimum resolution). */
380 ndebris = density_max * 100. *
381 ( SCREEN_W + 2. * DEBRIS_BUFFER * SCREEN_H + 2. * DEBRIS_BUFFER ) /
382 ( RESOLUTION_W_MIN * RESOLUTION_H_MIN );
383 array_resize( &debris_stack, ndebris );
384
385 for ( int j = 0; j < array_size( debris_stack ); j++ )
387
388 asteroid_creating = 0;
389
390 NTracingZoneEnd( _ctx );
391}
392
398static int asteroid_init( Asteroid *ast, const AsteroidAnchor *field )
399{
400 double mod, theta, wmax, r;
401 AsteroidType *at = NULL;
402 int outfield, id;
403 int attempts = 0;
404 vec2 pos, vel;
405
406 ast->parent = field->id;
407 ast->scanned = 0;
408
409 do {
410 double n, a;
411 n = sqrt( RNGF() ) * field->radius;
412 a = RNGF() * 2. * M_PI;
413 /* Try to keep density uniform using cartesian coordinates. */
414 vec2_cset( &pos, field->pos.x + n * cos( a ),
415 field->pos.y + n * sin( a ) );
416
417 /* Check if out of the field. */
418 outfield = ( asteroids_inField( &pos ) < 0 );
419
420 /* If this is the first time and it's spawned outside the field,
421 * we get rid of it so that density remains roughly consistent. */
422 if ( asteroid_creating && outfield ) {
423 ast->state = ASTEROID_XX;
424 ast->timer_max = ast->timer = HUGE_VAL; /* Don't reappear. */
425 /* TODO probably do a more proper solution removing total number of
426 * asteroids. */
427 return -1;
428 }
429
430 } while ( outfield && ( attempts++ < 1000 ) );
431
432 /* Randomly init the type of asteroid */
433 r = field->groupswtotal * RNGF();
434 wmax = 0.;
435 for ( int i = 0; i < array_size( field->groups ); i++ ) {
436 wmax += field->groupsw[i];
437 if ( r > wmax )
438 continue;
439 AsteroidTypeGroup *grp = field->groups[i];
440 double wi = 0.;
441 r = grp->wtotal * RNGF();
442 for ( int j = 0; j < array_size( grp->types ); j++ ) {
443 wi += grp->weights[j];
444 if ( r > wi )
445 continue;
446 at = grp->types[j];
447 break;
448 }
449 break;
450 }
451
452 /* Randomly init the gfx ID, and associated polygon */
453 id = RNG( 0, array_size( at->gfxs ) - 1 );
454 ast->gfx = at->gfxs[id];
455 ast->polygon = &at->polygon[id];
456
457 ast->type = at;
458 ast->armour = at->armour_min + RNGF() * ( at->armour_max - at->armour_min );
459
460 /* And a random velocity/spin */
461 theta = RNGF() * 2. * M_PI;
462 ast->spin = ( 1 - 2 * RNGF() ) * field->maxspin;
463 mod = RNGF() * field->maxspeed;
464
465 /* Fade in stuff. */
466 ast->state = ASTEROID_XX;
467 ast->timer_max = ast->timer = -1.;
468 ast->ang = RNGF() * M_PI * 2.;
469
470 /* Set up the solid. */
471 // vec2_cset( &pos, x, y );
472 vec2_pset( &vel, mod, theta );
473 /* TODO set a proper mass. */
474 solid_init( &ast->sol, 1., theta, &pos, &vel, SOLID_UPDATE_EULER );
475
476 return 0;
477}
478
483static void debris_init( Debris *deb )
484{
485 double theta, mod;
486 /* Position */
487 deb->pos.x = -DEBRIS_BUFFER + RNGF() * ( SCREEN_W + 2. * DEBRIS_BUFFER );
488 deb->pos.y = -DEBRIS_BUFFER + RNGF() * ( SCREEN_H + 2. * DEBRIS_BUFFER );
489
490 /* And a random velocity */
491 theta = RNGF() * 2. * M_PI;
492 mod = RNGF() * 20.;
493 vec2_pset( &deb->vel, mod, theta );
494
495 /* Randomly init the gfx ID */
496 // deb->gfx = asteroid_gfx[ RNG(0,(int)array_size(asteroid_gfx)-1) ];
497 deb->gfx = debris_gfx[RNG( 0, (int)array_size( debris_gfx ) - 1 )];
498
499 /* Random height vs player. */
500 deb->height = 0.8 + RNGF() * 0.4;
501 deb->alpha = 0.;
502 deb->ang = RNGF() * M_PI * 2.;
503}
504
509{
510 /* Calculate area */
511 a->area = M_PI * pow2( a->radius );
512
513 /* Compute number of asteroids */
514 a->nmax = floor( a->area / ASTEROID_REF_AREA * a->density );
515 if ( a->asteroids == NULL )
516 a->asteroids = array_create_size( Asteroid, a->nmax );
517
518 /* Computed from your standard physics equations (with a bit of margin). */
519 a->margin = pow2( a->maxspeed ) / ( 4. * a->accel ) + 50.;
520
521 /* Compute weight total. */
522 a->groupswtotal = 0.;
523 for ( int i = 0; i < array_size( a->groupsw ); i++ )
524 a->groupswtotal += a->groupsw[i];
525}
526
532int asteroids_load( void )
533{
534 char **asteroid_files;
535
536 /* Load asteroid types. */
537 asttype_load();
538
539 /* Load asteroid graphics. */
540 asteroid_files = PHYSFS_enumerateFiles( SPOB_GFX_SPACE_PATH "asteroid/" );
542
543 for ( size_t i = 0; asteroid_files[i] != NULL; i++ ) {
544 char file[PATH_MAX];
545 snprintf( file, sizeof( file ), "%s%s", SPOB_GFX_SPACE_PATH "asteroid/",
546 asteroid_files[i] );
547 array_push_back( &asteroid_gfx, gl_newImage( file, OPENGL_TEX_MIPMAPS ) );
548 }
549
550 PHYSFS_freeList( asteroid_files );
551 return 0;
552}
553
557static int asttype_cmp( const void *p1, const void *p2 )
558{
559 const AsteroidType *at1, *at2;
560 at1 = (const AsteroidType *)p1;
561 at2 = (const AsteroidType *)p2;
562 return strcmp( at1->name, at2->name );
563}
564
568static int astgroup_cmp( const void *p1, const void *p2 )
569{
570 const AsteroidTypeGroup *at1, *at2;
571 at1 = (const AsteroidTypeGroup *)p1;
572 at2 = (const AsteroidTypeGroup *)p2;
573 return strcmp( at1->name, at2->name );
574}
575
581static int asttype_load( void )
582{
583 char **asteroid_files = ndata_listRecursive( ASTEROID_TYPES_DATA_PATH );
585
586 for ( int i = 0; i < array_size( asteroid_files ); i++ ) {
587 if ( ndata_matchExt( asteroid_files[i], "xml" ) ) {
588 AsteroidType at;
589 int ret = asttype_parse( &at, asteroid_files[i] );
590 if ( ret == 0 )
592 }
593 free( asteroid_files[i] );
594 }
595 array_free( asteroid_files );
598 asttype_cmp );
599
600 /* Check for name collisions. */
601 for ( int i = 0; i < array_size( asteroid_types ) - 1; i++ )
602 if ( strcmp( asteroid_types[i].name, asteroid_types[i + 1].name ) == 0 )
603 WARN( _( "Asteroid Types with same name '%s'" ),
604 asteroid_types[i].name );
605
606 /* Load the asteroid groups from XML definitions. */
608 asteroid_files = ndata_listRecursive( ASTEROID_GROUPS_DATA_PATH );
609 for ( int i = 0; i < array_size( asteroid_files ); i++ ) {
610 if ( ndata_matchExt( asteroid_files[i], "xml" ) ) {
612 int ret = astgroup_parse( &atg, asteroid_files[i] );
613 if ( ret == 0 )
615 }
616 free( asteroid_files[i] );
617 }
618 array_free( asteroid_files );
619 /* Add asteroid types as individual groups. */
620 for ( int i = 0; i < array_size( asteroid_types ); i++ ) {
622 AsteroidTypeGroup grp = { .name = strdup( at->name ),
623 .types = array_create( AsteroidType *),
624 .weights = array_create( double ),
625 .wtotal = 1. };
626 array_push_back( &grp.types, at );
627 array_push_back( &grp.weights, 1. );
629 }
632 sizeof( AsteroidTypeGroup ), astgroup_cmp );
633
634 /* Check for name collisions. */
635 for ( int i = 0; i < array_size( asteroid_groups ) - 1; i++ )
636 if ( strcmp( asteroid_groups[i].name, asteroid_groups[i + 1].name ) == 0 )
637 WARN( _( "Asteroid Type Groups with same name '%s'" ),
638 asteroid_groups[i].name );
639
640 return 0;
641}
642
649static int asttype_parse( AsteroidType *at, const char *file )
650{
651 xmlNodePtr parent, node;
652 xmlDocPtr doc;
653
654 /* Load the data. */
655 doc = xml_parsePhysFS( file );
656 if ( doc == NULL )
657 return -1;
658
659 /* Get the root node. */
660 parent = doc->xmlChildrenNode;
661 if ( !xml_isNode( parent, "asteroid" ) ) {
662 WARN( _( "Malformed '%s' file: missing root element 'asteroid'" ), file );
663 return -1;
664 }
665
666 /* Set up the element. */
667 memset( at, 0, sizeof( AsteroidType ) );
668 at->gfxs = array_create( glTexture *);
671 at->damage = 100;
672 at->penetration = 100.;
673 at->exp_radius = 50.;
674 at->alert_range = 7000.;
675
676 xmlr_attr_strd( parent, "name", at->name );
677 if ( at->name == NULL )
678 WARN( _( "Asteroid '%s' has invalid or no name" ), file );
679
680 node = parent->xmlChildrenNode;
681 do {
682 /* Only handle nodes. */
683 xml_onlyNodes( node );
684
685 xmlr_strd( node, "scanned", at->scanned_msg );
686 xmlr_float( node, "armour_min", at->armour_min );
687 xmlr_float( node, "armour_max", at->armour_max );
688 xmlr_float( node, "absorb", at->absorb );
689 xmlr_float( node, "damage", at->damage );
690 xmlr_float( node, "disable", at->disable );
691 xmlr_float( node, "penetration", at->penetration );
692 xmlr_float( node, "exp_radius", at->exp_radius );
693 xmlr_float( node, "alert_range", at->alert_range );
694
695 if ( xml_isNode( node, "gfx" ) ) {
697 &at->gfxs,
698 xml_parseTexture( node, SPOB_GFX_SPACE_PATH "asteroid/%s", 1, 1,
699 OPENGL_TEX_MAPTRANS | OPENGL_TEX_MIPMAPS ) );
700 asteroid_loadPLG( at, xml_get( node ) );
701 continue;
702 } else if ( xml_isNode( node, "commodity" ) ) {
703 /* Check that name and quantity are defined. */
704 int namdef = 0;
705 AsteroidReward material;
706 memset( &material, 0, sizeof( material ) );
707
708 xmlNodePtr cur = node->xmlChildrenNode;
709 do {
710 xml_onlyNodes( cur );
711
712 xmlr_int( cur, "quantity", material.quantity );
713 xmlr_int( cur, "rarity", material.rarity );
714
715 if ( xml_isNode( cur, "name" ) ) {
716 const char *str = xml_get( cur );
717 material.material = commodity_get( str );
718 if ( material.material->gfx_space == NULL )
719 WARN( _( "Asteroid Type '%s' has Commodity '%s' with no "
720 "'gfx_space'." ),
721 at->name, str );
722 namdef = 1;
723 continue;
724 }
725
726 WARN( _( "Asteroid Type '%s' has unknown node '%s'" ), at->name,
727 cur->name );
728 } while ( xml_nextNode( cur ) );
729
730 if ( namdef == 0 || material.quantity == 0 )
731 WARN( _( "Asteroid Type '%s' has commodity that lacks name or "
732 "quantity." ),
733 at->name );
734
735 array_push_back( &at->material, material );
736 continue;
737 }
738 WARN( _( "Asteroid Type '%s' has unknown node '%s'" ), at->name,
739 node->name );
740 } while ( xml_nextNode( node ) );
741
742 /* Clean up. */
743 xmlFreeDoc( doc );
744
745 /* Some post-process. */
746 at->absorb = CLAMP( 0., 1., at->absorb / 100. );
747 at->penetration = CLAMP( 0., 1., at->penetration / 100. );
748
749 /* Checks. */
750 if ( at->armour_max < at->armour_min )
751 WARN( _( "Asteroid Type '%s' has armour_max below armour_min" ),
752 at->name );
753
754#define MELEMENT( o, s ) \
755 if ( o ) \
756 WARN( _( "Asteroid Type '%s' missing/invalid '%s' element" ), at->name, \
757 s )
758 MELEMENT( at->scanned_msg == NULL, "scanned" );
759 MELEMENT( array_size( at->gfxs ) == 0, "gfx" );
760 MELEMENT( at->armour_min <= 0., "armour_min" );
761 MELEMENT( at->armour_max <= 0., "armour_max" );
762#undef MELEMENT
763
764 return 0;
765}
766
773static int asteroid_loadPLG( AsteroidType *temp, const char *buf )
774{
775 char file[PATH_MAX];
776 xmlDocPtr doc;
777 xmlNodePtr node;
778
779 snprintf( file, sizeof( file ), "%s%s.xml", ASTEROID_POLYGON_PATH, buf );
780
781 /* See if the file does exist. */
782 if ( !PHYSFS_exists( file ) ) {
783 WARN( _( "%s xml collision polygon does not exist!\n \
784 Please use the script 'polygon_from_sprite.py'\n \
785 This file can be found in Naev's artwork repo." ),
786 file );
787 return 0;
788 }
789
790 /* Load the XML. */
791 doc = xml_parsePhysFS( file );
792 if ( doc == NULL )
793 return 0;
794
795 node = doc->xmlChildrenNode; /* First polygon node */
796 if ( node == NULL ) {
797 xmlFreeDoc( doc );
798 WARN( _( "Malformed %s file: does not contain elements" ), file );
799 return 0;
800 }
801
802 do { /* load the polygon data */
803 if ( xml_isNode( node, "polygons" ) ) {
804 CollPoly plg;
805 poly_load( &plg, node, file );
806 array_push_back( &temp->polygon, plg );
807 }
808 } while ( xml_nextNode( node ) );
809
810 xmlFreeDoc( doc );
811 return 0;
812}
813
821static int astgroup_parse( AsteroidTypeGroup *ag, const char *file )
822{
823 xmlNodePtr parent, node;
824 xmlDocPtr doc;
825
826 /* Load the data. */
827 doc = xml_parsePhysFS( file );
828 if ( doc == NULL )
829 return -1;
830
831 /* Get the root node. */
832 parent = doc->xmlChildrenNode;
833 if ( !xml_isNode( parent, "asteroid_group" ) ) {
834 WARN( _( "Malformed '%s' file: missing root element 'asteroid_group'" ),
835 file );
836 return -1;
837 }
838
839 /* Set up the element. */
840 memset( ag, 0, sizeof( AsteroidTypeGroup ) );
842 ag->weights = array_create( double );
843
844 xmlr_attr_strd( parent, "name", ag->name );
845 if ( ag->name == NULL )
846 WARN( _( "Asteroid '%s' has invalid or no name" ), file );
847
848 node = parent->xmlChildrenNode;
849 do {
850 /* Only handle nodes. */
851 xml_onlyNodes( node );
852
853 if ( xml_isNode( node, "type" ) ) {
854 double w;
855 xmlr_attr_float_def( node, "weight", w, 1. );
856 AsteroidType *at = asttype_getName( xml_get( node ) );
857 array_push_back( &ag->types, at );
858 array_push_back( &ag->weights, w );
859 ag->wtotal += w;
860 continue;
861 }
862 WARN( _( "Asteroid Type Group '%s' has unknown node '%s'" ), ag->name,
863 node->name );
864 } while ( xml_nextNode( node ) );
865
866 /* Clean up. */
867 xmlFreeDoc( doc );
868
869 return 0;
870}
871
876{
877 double cx, cy;
878 cam_getPos( &cx, &cy );
879 cx -= SCREEN_W / 2.;
880 cy -= SCREEN_H / 2.;
881
882 NTracingZone( _ctx, 1 );
883
884 /* Render the debris. */
885 for ( int j = 0; j < array_size( debris_stack ); j++ ) {
886 const Debris *d = &debris_stack[j];
887 if ( d->height > 1. )
888 debris_renderSingle( d, cx, cy );
889 }
890
891 NTracingZoneEnd( _ctx );
892}
893
898{
899 double cx, cy, z;
900 cam_getPos( &cx, &cy );
901 z = cam_getZoom();
902 cx -= SCREEN_W / 2.;
903 cy -= SCREEN_H / 2.;
904
905 NTracingZone( _ctx, 1 );
906
907 /* Render the asteroids & debris. */
908 for ( int i = 0; i < array_size( cur_system->asteroids ); i++ ) {
909 const AsteroidAnchor *ast = &cur_system->asteroids[i];
910 double x, y, r;
911
912 /* See if the asteroid field is in range, if not skip. */
913 gl_gameToScreenCoords( &x, &y, ast->pos.x, ast->pos.y );
914 r = ast->radius * z;
915 if ( ( x < -r ) || ( x > SCREEN_W + r ) || ( y < -r ) ||
916 ( y > SCREEN_H + r ) )
917 continue;
918
919 /* Render all asteroids. */
920 for ( int j = 0; j < array_size( ast->asteroids ); j++ )
922 }
923
924 /* Render the debris. */
925 for ( int j = 0; j < array_size( debris_stack ); j++ ) {
926 const Debris *d = &debris_stack[j];
927 if ( d->height <= 1. )
928 debris_renderSingle( d, cx, cy );
929 }
930
931 /* Render gatherable stuff. */
933
934 NTracingZoneEnd( _ctx );
935}
936
940static void asteroid_renderSingle( const Asteroid *a )
941{
942 double nx, ny;
943 const AsteroidType *at;
944 glColour col;
945 double progress;
946 const glColour darkcol = cGrey20;
947
948 /* Skip invisible asteroids */
949 if ( a->state == ASTEROID_XX )
950 return;
951
952 progress = a->timer / a->timer_max;
953 switch ( a->state ) {
954 case ASTEROID_XX_TO_BG:
955 col = darkcol;
956 col.a = 1. - progress;
957 break;
958 case ASTEROID_XB:
959 case ASTEROID_BX:
960 col = darkcol;
961 break;
962 case ASTEROID_BG_TO_FG:
963 col_blend( &col, &darkcol, &cWhite, progress );
964 break;
965 case ASTEROID_FG:
966 col = cWhite;
967 break;
968 case ASTEROID_FG_TO_BG:
969 col_blend( &col, &cWhite, &darkcol, progress );
970 break;
971 case ASTEROID_BG_TO_XX:
972 col = darkcol;
973 col.a = progress;
974 break;
975
976 default:
977 break;
978 }
979
980 at = a->type;
981 gl_renderSpriteRotate( a->gfx, a->sol.pos.x, a->sol.pos.y, a->ang, 0, 0,
982 &col );
983
984 /* Add the commodities if scanned. */
985 if ( !a->scanned )
986 return;
987 col = cFontWhite;
988 col.a = a->scan_alpha;
989 gl_gameToScreenCoords( &nx, &ny, a->sol.pos.x, a->sol.pos.y );
990 gl_printRaw( &gl_smallFont, nx + a->gfx->sw / 2, ny - gl_smallFont.h / 2,
991 &col, -1., _( at->scanned_msg ) );
992 /*
993 for (int i=0; i<array_size(at->material); i++) {
994 AsteroidReward *mat = &at->material[i];
995 Commodity *com = mat->material;
996 if (com->gfx_space!=NULL)
997 gl_renderSprite( com->gfx_space, a->pos.x, a->pos.y-10.*i, 0, 0, NULL
998 ); snprintf(c, sizeof(c), "x%i", mat->quantity); gl_printRaw( &gl_smallFont,
999 nx+10, ny-5-10.*i, &cFontWhite, -1., c );
1000 }
1001 */
1002}
1003
1007static void debris_renderSingle( const Debris *d, double cx, double cy )
1008{
1009 const double scale = 0.5;
1010 const glColour col = COL_ALPHA( cInert, d->alpha );
1011
1012 gl_renderSpriteScaleRotate( d->gfx, d->pos.x + cx, d->pos.y + cy, scale,
1013 scale, d->ang, 0, 0, &col );
1014}
1015
1020{
1021 memset( ast, 0, sizeof( AsteroidAnchor ) );
1022 ast->density = ASTEROID_DEFAULT_DENSITY;
1024 ast->groupsw = array_create( double );
1025 ast->radius = ASTEROID_DEFAULT_RADIUS;
1026 ast->maxspeed = ASTEROID_DEFAULT_MAXSPEED;
1027 ast->maxspin = ASTEROID_DEFAULT_MAXSPIN;
1028 ast->accel = ASTEROID_DEFAULT_ACCEL;
1029}
1030
1037{
1038 if ( ast->qt_init )
1039 qt_destroy( &ast->qt );
1040 free( ast->label );
1041 array_free( ast->asteroids );
1042 array_free( ast->groups );
1043 array_free( ast->groupsw );
1044}
1045
1052{
1053 free( exc->label );
1054}
1055
1059void asteroids_free( void )
1060{
1061 /* Free asteroid graphics. */
1062 for ( int i = 0; i < array_size( asteroid_gfx ); i++ )
1066
1067 /* Free the asteroid types. */
1068 for ( int i = 0; i < array_size( asteroid_types ); i++ ) {
1069 AsteroidType *at = &asteroid_types[i];
1070 free( at->name );
1071 free( at->scanned_msg );
1072 array_free( at->material );
1073 for ( int j = 0; j < array_size( at->gfxs ); j++ )
1074 gl_freeTexture( at->gfxs[j] );
1075 array_free( at->gfxs );
1076
1077 /* Free collision polygons. */
1078 for ( int j = 0; j < array_size( at->polygon ); j++ )
1079 poly_free( &at->polygon[j] );
1080 array_free( at->polygon );
1081 }
1083 asteroid_types = NULL;
1084
1085 /* Free the asteroid groups. */
1086 for ( int i = 0; i < array_size( asteroid_groups ); i++ ) {
1088 free( ag->name );
1089 array_free( ag->types );
1090 array_free( ag->weights );
1091 }
1093 asteroid_groups = NULL;
1094
1095 /* Clean up debris. */
1097 debris_stack = NULL;
1098
1099 /* Free the gatherable stack. */
1101}
1102
1110{
1111 /* Always return -1 if in an exclusion zone */
1112 for ( int i = 0; i < array_size( cur_system->astexclude ); i++ ) {
1113 AsteroidExclusion *e = &cur_system->astexclude[i];
1114 if ( vec2_dist2( p, &e->pos ) <= pow2( e->radius ) )
1115 return -1;
1116 }
1117
1118 /* Check if in asteroid field */
1119 for ( int i = 0; i < array_size( cur_system->asteroids ); i++ ) {
1120 AsteroidAnchor *a = &cur_system->asteroids[i];
1121 if ( vec2_dist2( p, &a->pos ) <= pow2( a->radius ) )
1122 return i;
1123 }
1124
1125 return -1;
1126}
1127
1134{
1135 return asteroid_types;
1136}
1137
1144AsteroidType *asttype_getName( const char *name )
1145{
1146 const AsteroidType q = { .name = (char *)name };
1148 sizeof( AsteroidType ), asttype_cmp );
1149 if ( at == NULL )
1150 WARN( _( "Unknown Asteroid Type '%s'" ), name );
1151 return at;
1152}
1153
1160{
1161 return asteroid_groups;
1162}
1163
1171{
1172 const AsteroidTypeGroup q = { .name = (char *)name };
1173 AsteroidTypeGroup *ag =
1175 sizeof( AsteroidTypeGroup ), astgroup_cmp );
1176 if ( ag == NULL )
1177 WARN( _( "Unknown Asteroid Type Group '%s'" ), name );
1178 return ag;
1179}
1180
1189void asteroid_hit( Asteroid *a, const Damage *dmg, int max_rarity,
1190 double mining_bonus )
1191{
1192 double darmour;
1193 double absorb = 1. - CLAMP( 0., 1., a->type->absorb - dmg->penetration );
1194 dtype_calcDamage( NULL, &darmour, absorb, NULL, dmg, NULL );
1195
1196 a->armour -= darmour;
1197 if ( a->armour <= 0 )
1198 asteroid_explode( a, max_rarity, mining_bonus );
1199}
1200
1209void asteroid_explode( Asteroid *a, int max_rarity, double mining_bonus )
1210{
1211 Damage dmg;
1212 char buf[16];
1213 double rad2;
1214 LuaAsteroid_t la;
1215 const AsteroidType *at = a->type;
1216 const AsteroidAnchor *field = &cur_system->asteroids[a->parent];
1217 Pilot *const *pilot_stack = pilot_getAll();
1218
1219 /* Manage the explosion */
1220 dmg.type = dtype_get( "explosion_splash" );
1221 dmg.damage = at->damage;
1222 dmg.penetration = at->penetration; /* Full penetration. */
1223 dmg.disable = 0.;
1224 expl_explode( a->sol.pos.x, a->sol.pos.y, a->sol.vel.x, a->sol.vel.y,
1225 at->exp_radius, &dmg, NULL, EXPL_MODE_SHIP );
1226
1227 /* Play random explosion sound. */
1228 snprintf( buf, sizeof( buf ), "explosion%d", RNG( 0, 2 ) );
1229 sound_playPos( sound_get( buf ), a->sol.pos.x, a->sol.pos.y, a->sol.vel.x,
1230 a->sol.vel.y );
1231
1232 /* Alert nearby pilots. */
1233 rad2 = pow2( at->alert_range );
1234 la.parent = a->parent;
1235 la.id = a->id;
1236 lua_pushasteroid( naevL, la );
1237 for ( int i = 0; i < array_size( pilot_stack ); i++ ) {
1238 Pilot *p = pilot_stack[i];
1239
1240 if ( vec2_dist2( &p->solid.pos, &a->sol.pos ) > rad2 )
1241 continue;
1242
1243 pilot_msg( NULL, p, "asteroid", -1 );
1244 }
1245 lua_pop( naevL, 1 );
1246
1247 /* Release commodity rewards. */
1248 if ( max_rarity >= 0 ) {
1249 int ndrops = 0;
1250 for ( int i = 0; i < array_size( at->material ); i++ ) {
1251 const AsteroidReward *mat = &at->material[i];
1252 if ( mat->rarity > max_rarity )
1253 continue;
1254 ndrops++;
1255 }
1256 if ( ndrops > 0 ) {
1257 double r = RNGF();
1258 double prob = 1. / (double)ndrops;
1259 double accum = 0.;
1260 for ( int i = 0; i < array_size( at->material ); i++ ) {
1261 const AsteroidReward *mat = &at->material[i];
1262 if ( mat->rarity > max_rarity )
1263 continue;
1264 accum += prob;
1265 if ( r > accum )
1266 continue;
1267
1268 int nb = RNG( 0, round( (double)mat->quantity * mining_bonus ) );
1269 for ( int j = 0; j < nb; j++ ) {
1270 vec2 pos, vel;
1271 pos = a->sol.pos;
1272 vel = a->sol.vel;
1273 pos.x += ( RNGF() * 30. - 15. );
1274 pos.y += ( RNGF() * 30. - 15. );
1275 vel.x += ( RNGF() * 20. - 10. );
1276 vel.y += ( RNGF() * 20. - 10. );
1277 gatherable_init( mat->material, &pos, &vel, -1., RNG( 1, 5 ),
1278 0 );
1279 }
1280 break;
1281 }
1282 }
1283 }
1284
1285 /* Remove the asteroid target to any pilot. */
1286 pilot_untargetAsteroid( a->parent, a->id );
1287
1288 /* Make it respawn elsewhere */
1289 asteroid_init( a, field );
1290 a->state = ASTEROID_BG_TO_XX;
1291 a->timer_max = a->timer = 0.5;
1292}
1293
1294void asteroid_collideQueryIL( AsteroidAnchor *anc, IntList *il, int x1, int y1,
1295 int x2, int y2 )
1296{
1297 qt_query( &anc->qt, il, x1, y1, x2, y2 );
1298}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:170
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
Definition array.h:214
#define array_resize(ptr_array, new_size)
Resizes the array to accomodate new_size elements.
Definition array.h:113
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
Definition array.h:102
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition array.h:148
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:179
#define array_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
Definition array.h:160
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:134
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
Definition array.h:206
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
void asteroids_render(void)
Renders the current systems' spobs.
Definition asteroid.c:897
static int astgroup_parse(AsteroidTypeGroup *ag, const char *file)
Parses an asteroid type group from a file.
Definition asteroid.c:821
void asteroids_computeInternals(AsteroidAnchor *a)
Updates internal alues of an asteroid field.
Definition asteroid.c:508
static Debris * debris_stack
Definition asteroid.c:52
static void asteroid_renderSingle(const Asteroid *a)
Renders an asteroid.
Definition asteroid.c:940
static AsteroidTypeGroup * asteroid_groups
Definition asteroid.c:63
static glTexture ** debris_gfx
Definition asteroid.c:54
void asteroids_free(void)
Cleans up the system.
Definition asteroid.c:1059
void asteroid_hit(Asteroid *a, const Damage *dmg, int max_rarity, double mining_bonus)
Hits an asteroid.
Definition asteroid.c:1189
int asteroids_load(void)
Loads the asteroids.
Definition asteroid.c:532
void asteroid_freeAnchor(AsteroidAnchor *ast)
Frees an asteroid anchor.
Definition asteroid.c:1036
static AsteroidType * asteroid_types
Definition asteroid.c:61
static void debris_renderSingle(const Debris *d, double cx, double cy)
Renders a debris.
Definition asteroid.c:1007
static glTexture ** asteroid_gfx
Definition asteroid.c:65
AsteroidType * asttype_getName(const char *name)
Gets the ID of an asteroid type by name.
Definition asteroid.c:1144
static int astgroup_cmp(const void *p1, const void *p2)
Compares two asteroid type groups.
Definition asteroid.c:568
const AsteroidTypeGroup * astgroup_getAll(void)
Gets all the asteroid type groups.
Definition asteroid.c:1159
AsteroidTypeGroup * astgroup_getName(const char *name)
Gets an asteroid type group by name.
Definition asteroid.c:1170
static int asttype_cmp(const void *p1, const void *p2)
Compares two asteroid types.
Definition asteroid.c:557
static int asttype_parse(AsteroidType *at, const char *file)
Parses the XML of an asteroid type.
Definition asteroid.c:649
void asteroid_explode(Asteroid *a, int max_rarity, double mining_bonus)
Makes an asteroid explode.
Definition asteroid.c:1209
static int asttype_load(void)
Loads the asteroids types.
Definition asteroid.c:581
static const double SCAN_FADE
Definition asteroid.c:49
static double asteroid_dt
Definition asteroid.c:55
static void debris_init(Debris *deb)
Initializes a debris.
Definition asteroid.c:483
void asteroids_init(void)
Initializes the system.
Definition asteroid.c:298
void asteroids_renderOverlay(void)
Renders the system overlay.
Definition asteroid.c:875
static int asteroid_init(Asteroid *ast, const AsteroidAnchor *field)
Initializes an asteroid.
Definition asteroid.c:398
void asteroid_initAnchor(AsteroidAnchor *ast)
Initializes an asteroid anchor.
Definition asteroid.c:1019
void asteroid_freeExclude(AsteroidExclusion *exc)
Frees an asteroid exclusion.
Definition asteroid.c:1051
const AsteroidType * asttype_getAll(void)
Gets all the asteroid types.
Definition asteroid.c:1133
int asteroids_inField(const vec2 *p)
See if the position is in an asteroid field.
Definition asteroid.c:1109
void asteroids_update(double dt)
Controls fleet spawning.
Definition asteroid.c:203
static int asteroid_loadPLG(AsteroidType *temp, const char *buf)
Loads the collision polygon for an asteroid type.
Definition asteroid.c:773
void cam_getDPos(double *dx, double *dy)
Gets the camera position differential (change in last frame).
Definition camera.c:131
void cam_getPos(double *x, double *y)
Gets the camera position.
Definition camera.c:122
double cam_getZoom(void)
Gets the camera zoom.
Definition camera.c:101
void poly_load(CollPoly *polygon, xmlNodePtr base, const char *name)
Loads a polygon from an xml node.
Definition collision.c:37
void col_blend(glColour *blend, const glColour *fg, const glColour *bg, float alpha)
Blends two colours.
Definition colour.c:206
Commodity * commodity_get(const char *name)
Gets a commodity by name.
Definition commodity.c:151
void dtype_calcDamage(double *dshield, double *darmour, double absorb, double *knockback, const Damage *dmg, const ShipStats *s)
Gives the real shield damage, armour damage and knockback modifier.
Definition damagetype.c:275
int dtype_get(const char *name)
Gets the id of a dtype based on name.
Definition damagetype.c:157
void expl_explode(double x, double y, double vx, double vy, double radius, const Damage *dmg, const Pilot *parent, int mode)
Does explosion in a radius (damage and graphics).
Definition explosion.c:42
glFont gl_smallFont
Definition font.c:159
void gl_printRaw(const glFont *ft_font, double x, double y, const glColour *c, double outlineR, const char *text)
Prints text on screen.
Definition font.c:646
void gatherable_free(void)
Frees all the gatherables.
Definition gatherable.c:147
int gatherable_init(const Commodity *com, const vec2 *pos, const vec2 *vel, double lifeleng, int qtt, unsigned int player_only)
Initializes a gatherable object.
Definition gatherable.c:68
void gatherable_render(void)
Renders all the gatherables.
Definition gatherable.c:156
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:39
#define CLAMP(a, b, x)
Definition naev.h:41
#define pow2(x)
Definition naev.h:53
#define MAX(x, y)
Definition naev.h:37
#define PATH_MAX
Definition naev.h:57
int ndata_matchExt(const char *path, const char *ext)
Sees if a file matches an extension.
Definition ndata.c:420
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
Definition ndata.c:286
lua_State * naevL
Definition nlua.c:54
LuaAsteroid_t * lua_pushasteroid(lua_State *L, LuaAsteroid_t asteroid)
Pushes a asteroid on the stack.
glTexture * xml_parseTexture(xmlNodePtr node, const char *path, int defsx, int defsy, const unsigned int flags)
Parses a texture handling the sx and sy elements.
Definition nxml.c:25
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
Definition nxml.c:70
void gl_gameToScreenCoords(double *nx, double *ny, double bx, double by)
Converts in-game coordinates to screen coordinates.
void gl_renderSpriteScaleRotate(const glTexture *sprite, double bx, double by, double scalew, double scaleh, double angle, int sx, int sy, const glColour *c)
Blits a sprite, position is relative to the player with scaling and rotation.
void gl_screenToGameCoords(double *nx, double *ny, int bx, int by)
Converts screen coordinates to in-game coordinates.
void gl_renderSpriteRotate(const glTexture *sprite, double bx, double by, double angle, int sx, int sy, const glColour *c)
Blits a sprite, position is relative to the player with rotation.
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
Definition opengl_tex.c:587
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition opengl_tex.c:835
void pilot_msg(const Pilot *p, const Pilot *receiver, const char *type, unsigned int idx)
Sends a message.
Definition pilot.c:4531
static Pilot ** pilot_stack
Definition pilot.c:51
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
Definition pilot.c:93
void pilot_untargetAsteroid(int anchor, int asteroid)
Loops over pilot stack to remove an asteroid as target.
Definition pilot.c:3255
Player_t player
Definition player.c:77
static const double d[]
Definition rng.c:263
int sound_playPos(int sound, double px, double py, double vx, double vy)
Plays a sound based on position.
Definition sound.c:832
int sound_get(const char *name)
Gets the buffer to sound of name.
Definition sound.c:761
StarSystem * cur_system
Definition space.c:110
#define DEBRIS_BUFFER
Definition space.c:71
int space_isSimulation(void)
returns whether we're just simulating.
Definition space.c:1601
Represents an asteroid field anchor.
Definition asteroid.h:111
Quadtree qt
Definition asteroid.h:128
double radius
Definition asteroid.h:118
double density
Definition asteroid.h:115
double maxspin
Definition asteroid.h:124
double * groupsw
Definition asteroid.h:121
double maxspeed
Definition asteroid.h:123
Asteroid * asteroids
Definition asteroid.h:116
double groupswtotal
Definition asteroid.h:122
AsteroidTypeGroup ** groups
Definition asteroid.h:120
Represents an asteroid exclusion zone.
Definition asteroid.h:136
Represents a potential reward from the asteroid.
Definition asteroid.h:50
Commodity * material
Definition asteroid.h:51
Represents a group of asteroids.
Definition asteroid.h:78
double * weights
Definition asteroid.h:81
AsteroidType ** types
Definition asteroid.h:80
Represents a type of asteroid.
Definition asteroid.h:59
double exp_radius
Definition asteroid.h:71
double penetration
Definition asteroid.h:70
double alert_range
Definition asteroid.h:72
double armour_max
Definition asteroid.h:66
CollPoly * polygon
Definition asteroid.h:63
double armour_min
Definition asteroid.h:65
double damage
Definition asteroid.h:68
char * name
Definition asteroid.h:60
AsteroidReward * material
Definition asteroid.h:64
double absorb
Definition asteroid.h:67
char * scanned_msg
Definition asteroid.h:61
double disable
Definition asteroid.h:69
glTexture ** gfxs
Definition asteroid.h:62
Represents a single asteroid.
Definition asteroid.h:88
CollPoly * polygon
Definition asteroid.h:95
int id
Definition asteroid.h:90
double timer
Definition asteroid.h:102
int state
Definition asteroid.h:92
double timer_max
Definition asteroid.h:103
int parent
Definition asteroid.h:91
double armour
Definition asteroid.h:96
const glTexture * gfx
Definition asteroid.h:94
Solid sol
Definition asteroid.h:98
int scanned
Definition asteroid.h:105
const AsteroidType * type
Definition asteroid.h:93
double ang
Definition asteroid.h:99
double spin
Definition asteroid.h:100
glTexture * gfx_space
Definition commodity.h:69
Core damage that an outfit does.
Definition outfit.h:168
int type
Definition outfit.h:169
double disable
Definition outfit.h:174
double penetration
Definition outfit.h:171
double damage
Definition outfit.h:173
Represents a small asteroid debris rendered in the player frame.
Definition asteroid.c:37
vec2 pos
Definition asteroid.c:39
double height
Definition asteroid.c:42
double ang
Definition asteroid.c:41
vec2 vel
Definition asteroid.c:40
const glTexture * gfx
Definition asteroid.c:38
double alpha
Definition asteroid.c:43
The representation of an in-game pilot.
Definition pilot.h:263
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:43
Represents a 2d vector.
Definition vec2.h:45
double y
Definition vec2.h:47
double x
Definition vec2.h:46