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 );
77 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->sol.pos.x;
108 offy = ast->
pos.
y - a->sol.pos.y;
112 a->sol.vel.x += ast->
accel * dt * offx /
d;
113 a->sol.vel.y += ast->
accel * dt * offy /
d;
116 else if (has_exclusion) {
127 ey = a->sol.pos.y - exc->
pos.
y;
131 a->sol.vel.x += ast->
accel * dt * ex / ed;
132 a->sol.vel.y += ast->
accel * dt * ey / ed;
140 d = MOD(a->sol.vel.x, a->sol.vel.y);
149 a->sol.pre = a->sol.pos;
150 a->sol.pos.x += a->sol.vel.x * dt;
151 a->sol.pos.y += a->sol.vel.y * dt;
154 a->ang += a->spin * dt;
166 case ASTEROID_XX_TO_BG:
167 a->timer_max = a->timer = 1. + 3.*RNGF();
171 case ASTEROID_FG_TO_BG:
172 a->timer_max = a->timer = 10. + 20.*RNGF();
174 case ASTEROID_BG_TO_FG:
175 a->timer_max = a->timer = 90. + 30.*RNGF();
179 case ASTEROID_BG_TO_XX:
181 a->timer_max = a->timer = 10. + 20.*RNGF();
189 a->state = (a->state+1) % ASTEROID_STATE_MAX;
194 if (a->state == ASTEROID_FG)
201 if (a->state == ASTEROID_FG) {
202 int x, y, w2, h2, px, py;
203 x = round(a->sol.pos.x);
204 y = round(a->sol.pos.y);
205 px = round(a->sol.pre.x);
206 py = round(a->sol.pre.y);
207 w2 = ceil(a->gfx->sw*0.5);
208 h2 = ceil(a->gfx->sh*0.5);
209 qt_insert( &ast->
qt, j,
MIN(x,px)-w2,
MIN(y,py)-h2,
MAX(x,px)+w2,
MAX(y,py)+h2 );
224 d->pos.
x +=
d->vel.x * dt - dx;
225 d->pos.y +=
d->vel.y * dt - dy;
243 d->alpha =
MIN( 1.0,
d->alpha + 0.5 * dt );
245 d->alpha =
MAX( 0.0,
d->alpha - 0.5 * dt );
255 double density_max = 0.;
257 asteroid_creating = 1;
281 qt_destroy( &ast->
qt );
282 qx = round(ast->
pos.
x);
283 qy = round(ast->
pos.
y);
285 qt_create( &ast->
qt, qx-qr, qy-qr, qx+qr, qy+qr, 2, 5 );
290 for (
int j=0; j<ast->
nb; j++) {
297 a->state = ASTEROID_FG;
299 a->state = ASTEROID_XB;
301 a->state = ASTEROID_BX;
303 a->state = ASTEROID_XX;
304 a->timer = a->timer_max = 30.*RNGF();
305 a->ang = RNGF() * M_PI * 2.;
308 density_max =
MAX( density_max, ast->
density );
317 ndebris = density_max * 100. * (SCREEN_W+2.*
DEBRIS_BUFFER * SCREEN_H+2.*
DEBRIS_BUFFER) / (RESOLUTION_W_MIN * RESOLUTION_H_MIN);
323 asteroid_creating = 0;
333 double mod, theta, wmax, r;
344 n = sqrt(RNGF())*field->
radius;
345 a = RNGF() * 2. * M_PI;
347 vec2_cset( &pos, field->
pos.
x + n*cos(a), field->
pos.
y + n*sin(a) );
354 if (asteroid_creating && outfield) {
355 ast->
state = ASTEROID_XX;
361 }
while (outfield && (attempts++ < 1000));
392 theta = RNGF()*2.*M_PI;
397 ast->
state = ASTEROID_XX;
399 ast->
ang = RNGF() * M_PI * 2.;
403 vec2_pset( &vel, mod, theta );
405 solid_init( &ast->
sol, 1., theta, &pos, &vel, SOLID_UPDATE_EULER );
422 theta = RNGF()*2.*M_PI;
424 vec2_pset( &deb->
vel, mod, theta );
431 deb->
height = 0.8 + RNGF()*0.4;
433 deb->
ang = RNGF() * M_PI * 2.;
442 a->area = M_PI *
pow2(a->radius);
445 a->nb = floor( a->area / ASTEROID_REF_AREA * a->density );
448 a->margin =
pow2(a->maxspeed) / (4.*a->accel) + 50.;
451 a->groupswtotal = 0.;
453 a->groupswtotal += a->groupsw[i];
464 char **asteroid_files, file[
PATH_MAX];
472 asteroid_files = PHYSFS_enumerateFiles( SPOB_GFX_SPACE_PATH
"asteroid/" );
475 for (
size_t i=0; asteroid_files[i]!=NULL; i++) {
476 snprintf( file,
sizeof(file),
"%s%s", SPOB_GFX_SPACE_PATH
"asteroid/", asteroid_files[i] );
480 PHYSFS_freeList( asteroid_files );
516 for (
int i=0; i<
array_size( asteroid_files ); i++) {
523 free( asteroid_files[i] );
532 WARN(_(
"Asteroid Types with same name '%s'"),
asteroid_types[i].name);
537 for (
int i=0; i<
array_size( asteroid_files ); i++) {
544 free( asteroid_files[i] );
551 .name = strdup(at->
name),
566 WARN(_(
"Asteroid Type Groups with same name '%s'"),
asteroid_groups[i].name);
579 xmlNodePtr parent, node;
588 parent = doc->xmlChildrenNode;
589 if (!xml_isNode(parent,
"asteroid")) {
590 WARN( _(
"Malformed '%s' file: missing root element 'asteroid'"), file);
604 xmlr_attr_strd(parent,
"name",at->
name);
605 if (at->
name == NULL)
606 WARN(_(
"Asteroid '%s' has invalid or no name"), file);
608 node = parent->xmlChildrenNode;
614 xmlr_float( node,
"armour_min", at->
armour_min );
615 xmlr_float( node,
"armour_max", at->
armour_max );
616 xmlr_float( node,
"absorb", at->
absorb );
617 xmlr_float( node,
"damage", at->
damage );
618 xmlr_float( node,
"disable", at->
disable );
619 xmlr_float( node,
"penetration", at->
penetration );
620 xmlr_float( node,
"exp_radius", at->
exp_radius );
621 xmlr_float( node,
"alert_range", at->
alert_range );
623 if (xml_isNode(node,
"gfx")) {
628 else if (xml_isNode(node,
"commodity")) {
632 memset( &material, 0,
sizeof(material) );
634 xmlNodePtr cur = node->xmlChildrenNode;
638 xmlr_int( cur,
"quantity", material.
quantity );
639 xmlr_int( cur,
"rarity", material.
rarity );
641 if (xml_isNode(cur,
"name")) {
642 const char *str = xml_get(cur);
645 WARN(_(
"Asteroid Type '%s' has Commodity '%s' with no 'gfx_space'."),at->
name,str);
650 WARN(_(
"Asteroid Type '%s' has unknown node '%s'"), at->
name, cur->name);
651 }
while (xml_nextNode(cur));
653 if (namdef==0 || material.
quantity==0)
654 WARN(_(
"Asteroid Type '%s' has commodity that lacks name or quantity."), at->
name);
659 WARN(_(
"Asteroid Type '%s' has unknown node '%s'"), at->
name, node->name);
660 }
while (xml_nextNode(node));
671 WARN(_(
"Asteroid Type '%s' has armour_max below armour_min"), at->
name);
673#define MELEMENT(o,s) \
674if (o) WARN(_("Asteroid Type '%s' missing/invalid '%s' element"), at->name, s)
697 snprintf( file,
sizeof(file),
"%s%s.xml", ASTEROID_POLYGON_PATH, buf );
706 if (!PHYSFS_exists(file)) {
707 WARN(_(
"%s xml collision polygon does not exist!\n \
708 Please use the script 'polygon_from_sprite.py'\n \
709 This file can be found in Naev's artwork repo."), file);
718 node = doc->xmlChildrenNode;
721 WARN(_(
"Malformed %s file: does not contain elements"), file);
726 if (xml_isNode(node,
"polygons")) {
727 xmlNodePtr cur = node->children;
729 if (xml_isNode(cur,
"polygon")) {
732 }
while (xml_nextNode(cur));
734 }
while (xml_nextNode(node));
749 xmlNodePtr parent, node;
758 parent = doc->xmlChildrenNode;
759 if (!xml_isNode(parent,
"asteroid_group")) {
760 WARN( _(
"Malformed '%s' file: missing root element 'asteroid_group'"), file);
769 xmlr_attr_strd(parent,
"name",ag->
name);
770 if (ag->
name == NULL)
771 WARN(_(
"Asteroid '%s' has invalid or no name"), file);
773 node = parent->xmlChildrenNode;
778 if (xml_isNode(node,
"type")) {
780 xmlr_attr_float_def(node,
"weight", w, 1.);
787 WARN(_(
"Asteroid Type Group '%s' has unknown node '%s'"), ag->
name, node->name);
788 }
while (xml_nextNode(node));
833 if ((x < -r) || (x > SCREEN_W+r) ||
834 (y < -r) || (y > SCREEN_H+r))
838 for (
int j=0; j<ast->
nb; j++)
862 const glColour darkcol = cGrey20;
865 if (a->state == ASTEROID_XX)
868 progress = a->timer / a->timer_max;
870 case ASTEROID_XX_TO_BG:
878 case ASTEROID_BG_TO_FG:
879 col_blend( &col, &darkcol, &cWhite, progress );
884 case ASTEROID_FG_TO_BG:
885 col_blend( &col, &cWhite, &darkcol, progress );
887 case ASTEROID_BG_TO_XX:
903 col.a = a->scan_alpha;
923 const double scale = 0.5;
924 const glColour col = COL_ALPHA( cInert,
d->alpha );
937 qt_destroy( &ast->
qt );
967 FreePolygon( &at->
polygon[j] );
1009 if (vec2_dist2( p, &a->pos ) <=
pow2(a->radius))
1037 WARN(_(
"Unknown Asteroid Type '%s'"),name);
1062 WARN(_(
"Unknown Asteroid Type Group '%s'"),name);
1080 a->armour -= darmour;
1107 expl_explode( a->sol.pos.x, a->sol.pos.y, a->sol.vel.x, a->sol.vel.y,
1108 at->
exp_radius, &dmg, NULL, EXPL_MODE_SHIP );
1111 snprintf(buf,
sizeof(buf),
"explosion%d", RNG(0,2));
1116 la.parent = a->parent;
1122 if (vec2_dist2( &p->solid.pos, &a->sol.pos ) > rad2)
1130 if (max_rarity >= 0) {
1134 if (mat->
rarity > max_rarity)
1140 double prob = 1./(double)ndrops;
1144 if (mat->
rarity > max_rarity)
1150 int nb = RNG(0, round((
double)mat->
quantity * mining_bonus));
1151 for (
int j=0; j<nb; j++) {
1155 pos.
x += (RNGF()*30.-15.);
1156 pos.
y += (RNGF()*30.-15.);
1157 vel.
x += (RNGF()*20.-10.);
1158 vel.
y += (RNGF()*20.-10.);
1171 a->state = ASTEROID_BG_TO_XX;
1172 a->timer_max = a->timer = 0.5;
1177 qt_query( &anc->
qt, il, x1, y1, x2, y2 );
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.
double cam_getZoom(void)
Gets the camera zoom.
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.
Commodity * commodity_get(const char *name)
Gets a commodity by name.
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, const vec2 *pos, const 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(const Pilot *p, const 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.