20#include "gatherable.h"
26#include "nlua_asteroid.h"
31typedef struct Debris_ {
53static int asteroid_creating = 0;
56static int asttype_cmp(
const void *p1,
const void *p2 );
59static int astgroup_cmp(
const void *p1,
const void *p2 );
78 int has_exclusion = 0;
91 for (
int j=0; j<ast->
nb; j++) {
97 if (a->state == ASTEROID_XX) {
100 a->state = ASTEROID_XX_TO_BG;
101 a->timer_max = a->timer = 1. + 3.*RNGF();
107 offx = ast->
pos.
x - a->pos.x;
108 offy = ast->
pos.
y - a->pos.y;
112 a->vel.x += ast->
thrust * dt * offx /
d;
113 a->vel.y += ast->
thrust * dt * offy /
d;
116 else if (has_exclusion) {
126 ex = a->pos.x - exc->
pos.
x;
127 ey = a->pos.y - exc->
pos.
y;
131 a->vel.x += ast->
thrust * dt * ex / ed;
132 a->vel.y += ast->
thrust * dt * ey / ed;
140 d = MOD(a->vel.x, a->vel.y);
148 a->pos.x += a->vel.x * dt;
149 a->pos.y += a->vel.y * dt;
152 a->ang += a->spin * dt;
156 if (a->state == ASTEROID_FG)
171 case ASTEROID_XX_TO_BG:
172 a->timer_max = a->timer = 1. + 3.*RNGF();
176 case ASTEROID_FG_TO_BG:
177 a->timer_max = a->timer = 10. + 20.*RNGF();
179 case ASTEROID_BG_TO_FG:
180 a->timer_max = a->timer = 90. + 30.*RNGF();
184 case ASTEROID_BG_TO_XX:
186 a->timer_max = a->timer = 10. + 20.*RNGF();
194 a->state = (a->state+1) % ASTEROID_STATE_MAX;
209 d->pos.x +=
d->vel.x * dt - dx;
210 d->pos.y +=
d->vel.y * dt - dy;
228 d->alpha =
MIN( 1.0,
d->alpha + 0.5 * dt );
230 d->alpha =
MAX( 0.0,
d->alpha - 0.5 * dt );
240 double density_max = 0.;
242 asteroid_creating = 1;
265 for (
int j=0; j<ast->
nb; j++) {
272 a->state = ASTEROID_FG;
274 a->state = ASTEROID_XB;
276 a->state = ASTEROID_BX;
278 a->state = ASTEROID_XX;
279 a->timer = a->timer_max = 30.*RNGF();
280 a->ang = RNGF() * M_PI * 2.;
283 density_max =
MAX( density_max, ast->
density );
292 ndebris = density_max * 100. * (SCREEN_W+2.*
DEBRIS_BUFFER * SCREEN_H+2.*
DEBRIS_BUFFER) / (RESOLUTION_W_MIN * RESOLUTION_H_MIN);
298 asteroid_creating = 0;
308 double mod, theta, wmax, r, r2;
327 if (asteroid_creating && outfield && (vec2_dist2( &ast->
pos, &field->
pos ) < r2)) {
328 ast->
state = ASTEROID_XX;
334 }
while (outfield && (attempts++ < 1000));
365 theta = RNGF()*2.*M_PI;
368 vec2_pset( &ast->
vel, mod, theta );
371 ast->
state = ASTEROID_XX;
373 ast->
ang = RNGF() * M_PI * 2.;
390 theta = RNGF()*2.*M_PI;
392 vec2_pset( &deb->
vel, mod, theta );
399 deb->
height = 0.8 + RNGF()*0.4;
401 deb->
ang = RNGF() * M_PI * 2.;
410 a->area = M_PI *
pow2(a->radius);
413 a->nb = floor( a->area / ASTEROID_REF_AREA * a->density );
416 a->margin =
pow2(a->maxspeed) / (4.*a->thrust) + 50.;
419 a->groupswtotal = 0.;
421 a->groupswtotal += a->groupsw[i];
432 char **asteroid_files, file[
PATH_MAX];
440 asteroid_files = PHYSFS_enumerateFiles( SPOB_GFX_SPACE_PATH
"asteroid/" );
443 for (
size_t i=0; asteroid_files[i]!=NULL; i++) {
444 snprintf( file,
sizeof(file),
"%s%s", SPOB_GFX_SPACE_PATH
"asteroid/", asteroid_files[i] );
448 PHYSFS_freeList( asteroid_files );
484 for (
int i=0; i<
array_size( asteroid_files ); i++) {
491 free( asteroid_files[i] );
505 for (
int i=0; i<
array_size( asteroid_files ); i++) {
512 free( asteroid_files[i] );
547 xmlNodePtr parent, node;
556 parent = doc->xmlChildrenNode;
557 if (!xml_isNode(parent,
"asteroid")) {
558 WARN( _(
"Malformed '%s' file: missing root element 'asteroid'"), file);
572 xmlr_attr_strd(parent,
"name",at->
name);
573 if (at->
name == NULL)
574 WARN(_(
"Asteroid '%s' has invalid or no name"), file);
576 node = parent->xmlChildrenNode;
582 xmlr_float( node,
"armour_min", at->
armour_min );
583 xmlr_float( node,
"armour_max", at->
armour_max );
584 xmlr_float( node,
"absorb", at->
absorb );
585 xmlr_float( node,
"damage", at->
damage );
586 xmlr_float( node,
"disable", at->
disable );
587 xmlr_float( node,
"penetration", at->
penetration );
588 xmlr_float( node,
"exp_radius", at->
exp_radius );
589 xmlr_float( node,
"alert_range", at->
alert_range );
591 if (xml_isNode(node,
"gfx")) {
596 else if (xml_isNode(node,
"commodity")) {
600 memset( &material, 0,
sizeof(material) );
602 xmlNodePtr cur = node->xmlChildrenNode;
606 xmlr_int( cur,
"quantity", material.
quantity );
607 xmlr_int( cur,
"rarity", material.
rarity );
609 if (xml_isNode(cur,
"name")) {
610 const char *str = xml_get(cur);
611 material.
material = commodity_get( str );
613 WARN(_(
"Asteroid Type '%s' has Commodity '%s' with no 'gfx_space'."),at->
name,str);
618 WARN(_(
"Asteroid Type '%s' has unknown node '%s'"), at->
name, cur->name);
619 }
while (xml_nextNode(cur));
621 if (namdef==0 || material.
quantity==0)
622 WARN(_(
"Asteroid Type '%s' has commodity that lacks name or quantity."), at->
name);
627 WARN(_(
"Asteroid Type '%s' has unknown node '%s'"), at->
name, node->name);
628 }
while (xml_nextNode(node));
639 WARN(_(
"Asteroid Type '%s' has armour_max below armour_min"), at->
name);
641#define MELEMENT(o,s) \
642if (o) WARN(_("Asteroid Type '%s' missing/invalid '%s' element"), at->name, s)
665 snprintf( file,
sizeof(file),
"%s%s.xml", ASTEROID_POLYGON_PATH, buf );
674 if (!PHYSFS_exists(file)) {
675 WARN(_(
"%s xml collision polygon does not exist!\n \
676 Please use the script 'polygon_from_sprite.py'\n \
677 This file can be found in Naev's artwork repo."), file);
686 node = doc->xmlChildrenNode;
689 WARN(_(
"Malformed %s file: does not contain elements"), file);
694 if (xml_isNode(node,
"polygons")) {
695 xmlNodePtr cur = node->children;
697 if (xml_isNode(cur,
"polygon")) {
700 }
while (xml_nextNode(cur));
702 }
while (xml_nextNode(node));
717 xmlNodePtr parent, node;
726 parent = doc->xmlChildrenNode;
727 if (!xml_isNode(parent,
"asteroid_group")) {
728 WARN( _(
"Malformed '%s' file: missing root element 'asteroid_group'"), file);
737 xmlr_attr_strd(parent,
"name",ag->
name);
738 if (ag->
name == NULL)
739 WARN(_(
"Asteroid '%s' has invalid or no name"), file);
741 node = parent->xmlChildrenNode;
746 if (xml_isNode(node,
"type")) {
748 xmlr_attr_float_def(node,
"weight", w, 1.);
755 WARN(_(
"Asteroid Type Group '%s' has unknown node '%s'"), ag->
name, node->name);
756 }
while (xml_nextNode(node));
795 for (
int j=0; j<ast->
nb; j++)
819 const glColour darkcol = cGrey20;
822 if (a->state == ASTEROID_XX)
825 progress = a->timer / a->timer_max;
827 case ASTEROID_XX_TO_BG:
835 case ASTEROID_BG_TO_FG:
836 col_blend( &col, &darkcol, &cWhite, progress );
841 case ASTEROID_FG_TO_BG:
842 col_blend( &col, &cWhite, &darkcol, progress );
844 case ASTEROID_BG_TO_XX:
860 col.a = a->scan_alpha;
880 const double scale = 0.5;
881 const glColour col = COL_ALPHA( cInert,
d->alpha );
966 if (vec2_dist2( p, &a->pos ) <=
pow2(a->radius))
994 WARN(_(
"Unknown Asteroid Type '%s'"),name);
1019 WARN(_(
"Unknown Asteroid Type Group '%s'"),name);
1037 a->armour -= darmour;
1065 at->
exp_radius, &dmg, NULL, EXPL_MODE_SHIP );
1068 snprintf(buf,
sizeof(buf),
"explosion%d", RNG(0,2));
1073 la.parent = a->parent;
1079 if (vec2_dist2( &p->solid->pos, &a->pos ) > rad2)
1087 if (max_rarity >= 0) {
1092 if (mat->
rarity > max_rarity)
1098 prob = 1./(double)ndrops;
1102 if (mat->
rarity > max_rarity)
1108 int nb = RNG(0, round((
double)mat->
quantity * mining_bonus));
1109 for (
int j=0; j<nb; j++) {
1113 pos.
x += (RNGF()*30.-15.);
1114 pos.
y += (RNGF()*30.-15.);
1115 vel.
x += (RNGF()*20.-10.);
1116 vel.
y += (RNGF()*20.-10.);
1129 a->state = ASTEROID_BG_TO_XX;
1130 a->timer_max = a->timer = 0.5;
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
#define array_resize(ptr_array, new_size)
Resizes the array to accomodate new_size elements.
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
void asteroids_render(void)
Renders the current systems' spobs.
static int astgroup_parse(AsteroidTypeGroup *ag, const char *file)
Parses an asteroid type group from a file.
void asteroids_computeInternals(AsteroidAnchor *a)
Updates internal alues of an asteroid field.
static Debris * debris_stack
static void asteroid_renderSingle(const Asteroid *a)
Renders an asteroid.
static AsteroidTypeGroup * asteroid_groups
static glTexture ** debris_gfx
void asteroids_free(void)
Cleans up the system.
void asteroid_hit(Asteroid *a, const Damage *dmg, int max_rarity, double mining_bonus)
Hits an asteroid.
const double DEBRIS_BUFFER
int asteroids_load(void)
Loads the asteroids.
static AsteroidType * asteroid_types
static void debris_renderSingle(const Debris *d, double cx, double cy)
Renders a debris.
static glTexture ** asteroid_gfx
AsteroidType * asttype_getName(const char *name)
Gets the ID of an asteroid type by name.
static int astgroup_cmp(const void *p1, const void *p2)
Compares two asteroid type groups.
const AsteroidTypeGroup * astgroup_getAll(void)
Gets all the asteroid type groups.
void asteroid_free(AsteroidAnchor *ast)
Frees an asteroid anchor.
AsteroidTypeGroup * astgroup_getName(const char *name)
Gets an asteroid type group by name.
static int asttype_cmp(const void *p1, const void *p2)
Compares two asteroid types.
static int asttype_parse(AsteroidType *at, const char *file)
Parses the XML of an asteroid type.
void asteroid_explode(Asteroid *a, int max_rarity, double mining_bonus)
Makes an asteroid explode.
static int asttype_load(void)
Loads the asteroids types.
static const double SCAN_FADE
static void debris_init(Debris *deb)
Initializes a debris.
void asteroids_init(void)
Initializes the system.
void asteroids_renderOverlay(void)
Renders the system overlay.
static int asteroid_init(Asteroid *ast, const AsteroidAnchor *field)
Initializes an asteroid.
const AsteroidType * asttype_getAll(void)
Gets all the asteroid types.
int asteroids_inField(const vec2 *p)
See if the position is in an asteroid field.
void asteroids_update(double dt)
Controls fleet spawning.
static int asteroid_loadPLG(AsteroidType *temp, const char *buf)
Loads the collision polygon for an asteroid type.
void cam_getDPos(double *dx, double *dy)
Gets the camera position differential (change in last frame).
void cam_getPos(double *x, double *y)
Gets the camera position.
void LoadPolygon(CollPoly *polygon, xmlNodePtr node)
Loads a polygon from an xml node.
void col_blend(glColour *blend, const glColour *fg, const glColour *bg, float alpha)
Blends two colours.
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.
int dtype_get(const char *name)
Gets the id of a dtype based on name.
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).
void gl_printRaw(const glFont *ft_font, double x, double y, const glColour *c, double outlineR, const char *text)
Prints text on screen.
void gatherable_free(void)
Frees all the gatherables.
int gatherable_init(const Commodity *com, vec2 pos, vec2 vel, double lifeleng, int qtt, unsigned int player_only)
Initializes a gatherable object.
void gatherable_render(void)
Renders all the gatherables.
Header file with generic functions and naev-specifics.
int ndata_matchExt(const char *path, const char *ext)
Sees if a file matches an extension.
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
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.
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
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.
void gl_freeTexture(glTexture *texture)
Frees a texture.
void pilot_msg(Pilot *p, Pilot *receiver, const char *type, unsigned int idx)
Sends a message.
static Pilot ** pilot_stack
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
void pilot_untargetAsteroid(int anchor, int asteroid)
Loops over pilot stack to remove an asteroid as target.
int sound_playPos(int sound, double px, double py, double vx, double vy)
Plays a sound based on position.
int sound_get(const char *name)
Gets the buffer to sound of name.
int space_isSimulation(void)
returns whether we're just simulating.
Represents an asteroid field anchor.
AsteroidTypeGroup ** groups
Represents an asteroid exclusion zone.
Represents a potential reward from the asteroid.
Represents a group of asteroids.
Represents a type of asteroid.
AsteroidReward * material
Represents a single asteroid.
const AsteroidType * type
Represents a polygon used for collision detection.
Core damage that an outfit does.
Represents a small asteroid debris rendered in the player frame.
The representation of an in-game pilot.
Abstraction for rendering sprite sheets.