25#include "damagetype.h"
30#include "nlua_outfit.h"
31#include "nlua_pilot.h"
45typedef struct WeaponCollision_ {
60typedef struct WeaponHit_ {
82static int qt_init = 0;
94 const vec2 *vel,
double dir,
double time );
97 const vec2 *vel,
double dir,
double time );
99 double dir,
double swivel );
101 double dir,
const vec2 *pos,
const vec2 *vel,
102 const Pilot *parent,
double time,
int aim );
104 double dir,
const vec2 *pos,
const vec2 *vel,
105 const Pilot *parent,
double time,
int aim );
107 double T,
double dir,
const vec2 *pos,
109 const Target *target,
double time,
int aim );
111 double dvx,
double dvy,
double pxv,
112 double vmin,
double acc,
double *tt );
130 double cradius,
vec2 crash[2] );
135void weapon_minimap(
double res,
double w,
double h,
const RadarShape shape,
182 w1 = (
const Weapon *)ptr1;
183 w2 = (
const Weapon *)ptr2;
184 return w1->
id - w2->
id;
192 const Weapon wid = { .id =
id };
195 if ( ( w == NULL ) || weapon_isFlag( w, WEAPON_FLAG_DESTROYED ) )
206 NTracingZone( _ctx, 1 );
214 NTracingZoneEnd( _ctx );
232 NTracingZone( _ctx, 1 );
238 if ( shape == RADAR_CIRCLE )
261 if ( shape == RADAR_RECT && (
ABS( x ) > w / 2. ||
ABS( y ) > h / 2. ) )
263 if ( shape == RADAR_CIRCLE && ( ( ( x ) * ( x ) + ( y ) * ( y ) ) > rc ) )
267 isplayer = ( ( wp->
target.type == TARGET_PILOT ) &&
268 ( wp->
target.u.id == PLAYER_ID ) );
270 ( wp->
faction == FACTION_PLAYER ) )
306 glUseProgram( shaders.points.program );
307 glEnableVertexAttribArray( shaders.points.vertex );
308 glEnableVertexAttribArray( shaders.points.vertex_colour );
309 gl_uniformMat4( shaders.points.projection, &gl_view_matrix );
313 offset *
sizeof( GLfloat ), 4, GL_FLOAT, 0 );
314 glDrawArrays( GL_POINTS, 0, p );
315 glDisableVertexAttribArray( shaders.points.vertex );
316 glDisableVertexAttribArray( shaders.points.vertex_colour );
321 NTracingZoneEnd( _ctx );
329 w->solid.accel = accel;
337 w->solid.dir_vel = turn;
350 double turn_max, jc, speed_mod;
352 if ( w->target.type != TARGET_PILOT )
366 switch ( w->status ) {
367 case WEAPON_STATUS_LOCKING:
369 if ( w->timer2 >= 0. )
372 w->status = WEAPON_STATUS_OK;
376 case WEAPON_STATUS_OK:
377 jc = p->stats.jam_chance - w->outfit->u.lau.resist;
380 double d = vec2_dist( &p->solid.pos, &w->solid.pos );
381 if (
d < w->r * p->ew_signature ) {
386 w->status = WEAPON_STATUS_JAMMED;
387 }
else if ( r < 0.6 ) {
388 w->status = WEAPON_STATUS_JAMMED;
390 ( ( RNGF() > 0.5 ) ? -1.0 : 1.0 ) );
391 }
else if ( r < 0.8 ) {
392 w->status = WEAPON_STATUS_JAMMED;
396 w->status = WEAPON_STATUS_JAMMED_SLOWED;
397 w->falloff = RNGF() * 0.5;
401 w->status = WEAPON_STATUS_UNJAMMED;
406 case WEAPON_STATUS_JAMMED_SLOWED:
407 case WEAPON_STATUS_UNJAMMED:
408 turn_max = w->outfit->u.lau.turn * w->turn_mod;
409 if ( w->status == WEAPON_STATUS_JAMMED_SLOWED )
410 turn_max *= w->falloff;
413 if ( w->outfit->u.lau.ai == AMMO_AI_SMART ) {
418 vec2_csetmin( &v, p->solid.pos.x - w->solid.pos.x,
419 p->solid.pos.y - w->solid.pos.y );
421 vec2_odist2( &p->solid.vel ) - vec2_odist2( &w->solid.vel );
422 const double b = vec2_dot( &p->solid.vel, &v );
423 const double c = vec2_odist2( &v );
430 const double b2_ac = b * b - a *
c;
432 t = ( -b - sqrt( b2_ac ) ) / a;
443 ANGLE( v.x + t * p->solid.vel.x, v.y + t * p->solid.vel.y );
444 const double diff = angle_diff( w->solid.dir, angle );
449 double diff = angle_diff( w->solid.dir,
450 vec2_angle( &w->solid.pos, &p->solid.pos ) );
452 w,
CLAMP( -turn_max, turn_max,
453 10 * diff * w->outfit->u.lau.turn * w->turn_mod ) );
457 case WEAPON_STATUS_JAMMED:
462 WARN( _(
"Unknown weapon status for '%s'" ), w->outfit->name );
467 speed_mod = w->speed_mod;
468 speed_mod *= ( w->status == WEAPON_STATUS_JAMMED_SLOWED ) ? w->falloff : 1.;
472 MIN( speed_mod * w->outfit->u.lau.speed_max,
473 w->real_vel + w->outfit->u.lau.accel * w->accel_mod * dt );
474 vec2_pset( &w->solid.vel, w->real_vel, w->solid.dir );
493 unsigned int turn_off;
504 rate = p->stats.fwd_firerate;
506 rate = p->stats.tur_firerate;
507 dt *= p->stats.time_speedup * rate *
508 p->stats.weapon_firerate;
511 mod = ( w->outfit->type == OUTFIT_TYPE_BEAM ) ? p->stats.fwd_energy
512 : p->stats.tur_energy;
513 p->energy -= mod * dt * w->outfit->u.bem.energy * p->stats.weapon_energy;
515 if ( p->energy < 0. ) {
524 switch ( w->target.type ) {
528 case TARGET_ASTEROID: {
530 &
cur_system->asteroids[w->target.u.ast.anchor];
531 ast = &field->
asteroids[w->target.u.ast.asteroid];
542 if ( vec2_dist( &p->solid.pos, &t->
solid.
pos ) <=
547 if ( vec2_dist( &p->solid.pos, &ast->
sol.
pos ) <=
560 w->solid.pos.x = p->solid.pos.x + v.x;
561 w->solid.pos.y = p->solid.pos.y + v.y;
564 switch ( w->outfit->type ) {
565 case OUTFIT_TYPE_BEAM:
566 if ( w->outfit->u.bem.swivel > 0. )
569 &p->solid.vel, p->solid.dir, 0. );
571 w->solid.dir = p->solid.dir;
574 case OUTFIT_TYPE_TURRET_BEAM:
575 if ( !weapon_isFlag( w, WEAPON_FLAG_AIM ) && pilot_isPlayer( p ) &&
579 diff = angle_diff( w->solid.dir,
580 vec2_angle( &w->solid.pos, &tv ) );
585 else if ( t == NULL ) {
587 diff = angle_diff( w->solid.dir,
588 vec2_angle( &w->solid.pos, &ast->
sol.
pos ) );
590 diff = angle_diff( w->solid.dir, p->solid.dir );
592 diff = angle_diff( w->solid.dir,
593 vec2_angle( &w->solid.pos, &t->
solid.
pos ) );
596 p->stats.time_speedup *
597 CLAMP( -w->outfit->u.bem.turn, w->outfit->u.bem.turn,
598 10. * diff * w->outfit->u.bem.turn ) );
611 NTracingZone( _ctx, 1 );
619 if ( !weapon_isFlag( w, WEAPON_FLAG_DESTROYED ) )
628 int x, y, px, py, w2, h2;
632 if ( !weapon_isFlag( w, WEAPON_FLAG_HITTABLE ) )
636 if ( gfx->
tex != NULL )
642 x = round( w->solid.pos.x );
643 y = round( w->solid.pos.y );
644 px = round( w->solid.pre.x );
645 py = round( w->solid.pre.y );
646 w2 = ceil( range * 0.5 );
647 h2 = ceil( range * 0.5 );
649 MAX( x, px ) + w2,
MAX( y, py ) + h2 );
652 NTracingZoneEnd( _ctx );
660 NTracingZone( _ctx, 1 );
667 if ( weapon_isFlag( w, WEAPON_FLAG_DESTROYED ) )
671 switch ( w->outfit->type ) {
674 case OUTFIT_TYPE_LAUNCHER:
675 case OUTFIT_TYPE_TURRET_LAUNCHER:
681 case OUTFIT_TYPE_BOLT:
682 case OUTFIT_TYPE_TURRET_BOLT:
684 if ( w->timer < 0. ) {
687 }
else if ( w->timer < w->falloff )
688 w->strength = w->timer / w->falloff * w->strength_base;
692 case OUTFIT_TYPE_BEAM:
693 case OUTFIT_TYPE_TURRET_BEAM: {
700 if ( w->mount->outfit->type == OUTFIT_TYPE_BEAM )
701 rate = p->stats.fwd_firerate;
703 rate = p->stats.tur_firerate;
705 dt * p->stats.time_speedup * rate *
706 p->stats.weapon_firerate;
711 if ( w->timer < 0. ) {
720 if ( w->timer2 < -1. )
724 WARN( _(
"Weapon of type '%s' has no update implemented yet!" ),
730 if ( !weapon_isFlag( w, WEAPON_FLAG_DESTROYED ) )
734 NTracingZoneEnd( _ctx );
744 NTracingZone( _ctx, 1 );
749 if ( !weapon_isFlag( w, WEAPON_FLAG_DESTROYED ) )
753 NTracingZoneEnd( _ctx );
764 NTracingZone( _ctx, 1 );
768 if ( w->layer == layer )
772 NTracingZoneEnd( _ctx );
775static void weapon_renderBeam(
Weapon *w,
double dt )
779 double range = w->outfit->u.bem.range * w->range_mod;
785 glUseProgram( shaders.beam.program );
793 projection = gl_view_matrix;
794 mat4_translate_xy( &projection, x, y );
796 mat4_scale_xy( &projection, range * z, w->outfit->u.bem.width * z );
797 mat4_translate_xy( &projection, 0., -0.5 );
800 glEnableVertexAttribArray( shaders.beam.vertex );
805 gl_uniformMat4( shaders.beam.projection, &projection );
806 gl_uniformColour( shaders.beam.colour, &w->outfit->u.bem.colour );
807 glUniform2f( shaders.beam.dimensions, range, w->outfit->u.bem.width );
808 glUniform1f( shaders.beam.dt, w->anim );
809 glUniform1f( shaders.beam.r, w->r );
812 if ( gl_has( OPENGL_SUBROUTINES ) )
813 glUniformSubroutinesuiv( GL_FRAGMENT_SHADER, 1,
814 &w->outfit->u.bem.shader );
817 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
820 glDisableVertexAttribArray( shaders.beam.vertex );
837 glColour col,
c = { .r = 1., .g = 1., .b = 1. };
840 if ( weapon_isFlag( w, WEAPON_FLAG_DESTROYED ) )
843 switch ( w->outfit->type ) {
845 case OUTFIT_TYPE_LAUNCHER:
846 case OUTFIT_TYPE_TURRET_LAUNCHER:
847 if ( w->status == WEAPON_STATUS_LOCKING ) {
851 r = w->outfit->u.lau.gfx.size * z * 0.75;
853 st = 1. - w->timer2 / w->paramf;
857 glUseProgram( shaders.iflockon.program );
858 glUniform1f( shaders.iflockon.paramf,
st );
862 case OUTFIT_TYPE_BOLT:
863 case OUTFIT_TYPE_TURRET_BOLT:
867 c.a =
MIN( 1., w->strength );
870 if ( gfx->
tex != NULL ) {
874 w->solid.pos.x, w->solid.pos.y, w->
sx,
890 if ( ( x < -r ) || ( x > SCREEN_W + r ) || ( y < -r ) ||
891 ( y > SCREEN_H + r ) )
894 mat4 projection = gl_view_matrix;
895 mat4_translate_xy( &projection, x, y );
897 mat4_scale_xy( &projection, r, r );
901 glUniform1f( gfx->
u_r, w->r );
902 glUniform1f( gfx->
u_time, w->life - w->timer );
903 glUniform1f( gfx->
u_fade,
MIN( 1., w->strength ) );
904 gl_uniformMat4( gfx->
projection, &projection );
906 glEnableVertexAttribArray( gfx->
vertex );
910 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
912 glDisableVertexAttribArray( gfx->
vertex );
919 case OUTFIT_TYPE_BEAM:
920 case OUTFIT_TYPE_TURRET_BEAM:
921 weapon_renderBeam( w, dt );
925 WARN( _(
"Weapon of type '%s' has no render implemented yet!" ),
941 if ( pilot_isFlag( p, PILOT_INVINCIBLE ) )
945 if ( pilot_isFlag( p, PILOT_HIDE ) )
949 if ( pilot_isFlag( p, PILOT_LANDING ) || pilot_isFlag( p, PILOT_TAKEOFF ) )
953 if ( pilot_isFlag( p, PILOT_DEAD ) )
957 if ( ( w->faction == FACTION_PLAYER ) &&
958 pilot_isFlag( p, PILOT_INVINC_PLAYER ) )
962 if ( ( w->target.type == TARGET_PILOT ) && ( w->target.u.id == p->id ) )
966 if ( p->faction == w->faction )
970 if ( w->faction == FACTION_PLAYER ) {
982 if ( p->faction == FACTION_PLAYER ) {
984 if ( parent != NULL ) {
1013 const glTexture *ctex,
int csx,
int csy,
1015 double cradius,
vec2 crash[2] )
1017 NTracingZone( _ctx, 1 );
1021 const vec2 *wpos, *cpos;
1025 wpos = &w->solid.pos;
1035 double vx1 = w->solid.pre.x - w->solid.pos.x;
1036 double vy1 = w->solid.pre.y - w->solid.pos.y;
1037 double vx2 = csol->
pre.
x - csol->
pos.
x;
1038 double vy2 = csol->
pre.
y - csol->
pos.
y;
1039 double b = vx1 - vx2;
1040 double d = vy1 - vy2;
1043 if ( ( fabs( b ) > DOUBLE_TOL ) || ( fabs(
d ) > DOUBLE_TOL ) ) {
1044 double a = w->solid.pos.x - csol->
pos.
x;
1045 double c = w->solid.pos.y - csol->
pos.
y;
1046 double t =
CLAMP( 0., 1., -( a * b +
c *
d ) / ( b * b +
d *
d ) );
1048 wipos.
x = w->solid.pos.x + t * vx1;
1049 wipos.
y = w->solid.pos.y + t * vy1;
1050 cipos.
x = csol->
pos.
x + t * vx2;
1051 cipos.
y = csol->
pos.
y + t * vy2;
1061 double s1x = csol->
pos.
x;
1062 double s1y = csol->
pos.
y;
1063 double e1x = csol->
pre.
x;
1064 double e1y = csol->
pre.
y;
1065 double s2x = w->solid.pos.x;
1066 double s2y = w->solid.pos.y;
1067 double e2x = w->solid.pos.x + cos( w->solid.dir ) * wc->
beamrange;
1068 double e2y = w->solid.pos.y + sin( w->solid.dir ) * wc->
beamrange;
1072 ( e2y - s2y ) * ( e1x - s1x ) - ( e2x - s2x ) * ( e1y - s1y );
1075 if ( fabs( u_b ) > DOUBLE_TOL ) {
1077 ( e2x - s2x ) * ( s1y - s2y ) - ( e2y - s2y ) * ( s1x - s2x );
1080 double ua =
CLAMP( 0., 1., ua_t / u_b );
1083 cipos.
x = s1x + ua * ( e1x - s1x );
1084 cipos.
y = s1y + ua * ( e1y - s1y );
1091 if ( cpol != NULL ) {
1093 cpol, cpos, crash );
1094 }
else if ( ctex != NULL ) {
1096 ctex, csx, csy, cpos, crash );
1098 const vec2 endpoint = { .x = e2x, .y = e2y };
1103 NTracingZoneEnd( _ctx );
1110 ( e1x - s1x ) * ( s1y - s2y ) - ( e1y - s1y ) * ( s1x - s2x );
1111 double ub =
CLAMP( 0., 1., ub_t / u_b );
1112 wipos.
x = s2x + ub * ( e2x - s2x );
1113 wipos.
y = s2y + ub * ( e2y - s2y );
1119 double vx1 = s1x - s2x;
1120 double vy1 = s1y - s2y;
1121 double vx2 = e2x - s2x;
1122 double vy2 = e2y - s2y;
1123 double t = ( vx1 * vx2 + vy1 * vy2 ) / (
pow2( vx2 ) +
pow2( vy2 ) );
1124 t =
CLAMP( 0., 1., t );
1125 wipos.
x = s2x + t * vx2;
1126 wipos.
y = s2y + t * vy2;
1135 if ( cpol != NULL ) {
1140 else if ( ( wc->
gfx != NULL ) && ( wc->
gfx->
tex != NULL ) )
1148 else if ( ctex != NULL ) {
1154 else if ( ( wc->
gfx != NULL ) && ( wc->
gfx->
tex != NULL ) )
1169 else if ( ( wc->
gfx != NULL ) && ( wc->
gfx->
tex != NULL ) )
1177 NTracingZoneEnd( _ctx );
1199 int x, y, w2, h2, px, py;
1201 if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_COLLISION_OVERRIDE ) ) {
1207 if ( wc.
gfx->
tex != NULL ) {
1209 if ( plg != NULL ) {
1211 wc.
polyview = poly_view( plg, w->solid.dir );
1226 x = round( w->solid.pos.x );
1227 y = round( w->solid.pos.y );
1228 px = x + round( w->solid.pre.x );
1229 py = y + round( w->solid.pre.y );
1230 w2 = ceil( wc.
range * 0.5 );
1231 h2 = ceil( wc.
range * 0.5 );
1232 x1 =
MIN( x, px ) - w2;
1233 y1 =
MIN( y, py ) - h2;
1234 x2 =
MAX( x, px ) + w2;
1235 y2 =
MAX( y, py ) + h2;
1241 if ( w->outfit->type == OUTFIT_TYPE_BEAM ) {
1242 w->dam_mod = p->stats.fwd_damage * p->stats.weapon_damage;
1243 w->dam_as_dis_mod = p->stats.fwd_dam_as_dis - 1.;
1244 w->range_mod = p->stats.fwd_range * p->stats.weapon_range;
1246 w->dam_mod = p->stats.tur_damage * p->stats.weapon_damage;
1247 w->dam_as_dis_mod = p->stats.tur_dam_as_dis - 1.;
1248 w->range_mod = p->stats.tur_range * p->stats.weapon_range;
1250 w->dam_as_dis_mod =
CLAMP( 0., 1., w->dam_as_dis_mod );
1255 wc.
range = w->outfit->u.bem.width * 0.5;
1257 w->outfit->u.bem.range * w->range_mod;
1260 x1 = round( w->solid.pos.x );
1261 y1 = round( w->solid.pos.y );
1262 x2 = x1 + ceil( wc.
beamrange * cos( w->solid.dir ) );
1263 y2 = y1 + ceil( wc.
beamrange * sin( w->solid.dir ) );
1277 if ( !outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_MISS_SHIPS ) ) {
1284 if ( pilot_isFlag( p, PILOT_DELETE ) )
1288 if ( w->parent == p->id )
1293 int isjammed = ( ( w->status == WEAPON_STATUS_JAMMED ) ||
1294 ( w->status == WEAPON_STATUS_JAMMED_SLOWED ) );
1295 if ( !isjammed && ( w->target.type == TARGET_PILOT ) &&
1296 ( p->id != w->target.u.id ) )
1301 if ( weapon_isFlag( w, WEAPON_FLAG_ONLYHITTARGET ) ) {
1302 if ( ( w->target.type == TARGET_PILOT ) &&
1303 ( p->id != w->target.u.id ) )
1313 &wc, p->ship->gfx_space, p->tsx, p->tsy, &p->solid,
1314 poly_view( &p->ship->polygon, p->solid.dir ), 0., crash ) )
1318 hit.type = TARGET_PILOT;
1333 if ( !outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_MISS_ASTEROIDS ) ) {
1340 if ( vec2_dist2( &w->solid.pos, &ast->
pos ) >
1352 if ( a->state != ASTEROID_FG )
1357 poly_rotate( &rpoly, &a->polygon->views[0], (
float)a->ang );
1371 hit.type = TARGET_ASTEROID;
1385 if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_POINTDEFENSE ) ) {
1398 if ( wchit.
gfx->
tex != NULL ) {
1417 hit.type = TARGET_WEAPON;
1438 double odir = w->solid.dir;
1441 if ( w->think != NULL )
1442 ( *w->think )( w, dt );
1445 ( *w->solid.update )( &w->solid, dt );
1448 if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_SPIN ) ) {
1451 if ( w->anim < 0. ) {
1458 if ( w->sprite >= tex->
sx * tex->
sy )
1461 w->sx = w->sprite % (int)tex->
sx;
1462 w->sy = w->sprite / (int)tex->
sx;
1464 }
else if ( fabs( odir - w->solid.dir ) > DOUBLE_TOL ) {
1466 if ( ( gfx != NULL ) && ( gfx->
tex != NULL ) )
1472 sound_updatePos( w->voice, w->solid.pos.x, w->solid.pos.y, w->solid.vel.x,
1476 if ( w->trail != NULL )
1485 double a, dx, dy, ax, ay;
1496 dx = w->outfit->u.lau.trail_x_offset * ca;
1497 dy = w->outfit->u.lau.trail_x_offset * sa;
1498 ax = w->solid.accel * -ca;
1499 ay = w->solid.accel * -sa;
1502 if ( ( w->outfit->u.lau.ai == AMMO_AI_UNGUIDED ) ||
1503 w->solid.vel.x * w->solid.vel.x + w->solid.vel.y * w->solid.vel.y + 1. <
1504 w->solid.speed_max * w->solid.speed_max )
1505 mode = MODE_AFTERBURN;
1506 else if ( w->solid.dir_vel != 0. )
1512 w->solid.pos.y + dy * M_SQRT1_2, 0., ax, ay, mode, 0 );
1525 if ( shooter == NULL )
1533 if ( pilot_isDisabled( p ) )
1537 if ( pilot_isFlag( p, PILOT_DELETE ) || pilot_isFlag( p, PILOT_DEAD ) ||
1538 pilot_isFlag( p, PILOT_HIDE ) )
1542 if ( shooter->
faction == FACTION_PLAYER ) {
1545 if ( p->faction == FACTION_PLAYER )
1549 p->player_damage += dmg / ( p->shield_max + p->armour_max );
1552 if ( ( p->player_damage > PILOT_HOSTILE_THRESHOLD ) ||
1553 ( shooter->
target == p->id ) ) {
1574 const vec2 *center )
1576 int x, y, r, x1, y1, x2, y2;
1577 double vx, vy, nvel;
1591 vx = vy = nvel = 0.;
1594 x = round( center->
x );
1595 y = round( center->
y );
1603 if ( !outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_MISS_SHIPS ) ) {
1612 if ( pilot_isFlag( p, PILOT_DELETE ) )
1615 if ( !outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_FRIENDLYFIRE ) ) {
1617 if ( w->parent == p->id )
1627 &wc, p->ship->gfx_space, p->tsx, p->tsy, &p->solid,
1628 poly_view( &p->ship->polygon, p->solid.dir ), 0., crash ) )
1633 pilot_hit( p, &w->solid, parent, dmg, w->outfit, w->lua_mem, 1 );
1637 vx += p->solid.vel.x;
1638 vy += p->solid.vel.y;
1644 if ( !outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_MISS_ASTEROIDS ) ) {
1645 double mining_bonus =
1652 if ( vec2_dist2( &w->solid.pos, &ast->
pos ) >
1662 if ( a->state != ASTEROID_FG )
1667 poly_rotate( &rpoly, &a->polygon->views[0], (
float)a->ang );
1690 if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_POINTDEFENSE ) ) {
1703 if ( wchit.
gfx->
tex != NULL ) {
1735 vx = w->solid.vel.x;
1736 vy = w->solid.vel.y;
1739 vy, SPFX_LAYER_FRONT );
1751 double damage, radius;
1757 damage = w->dam_mod * w->strength * odmg->
damage;
1759 dmg.
damage =
MAX( 0., damage * ( 1. - w->dam_as_dis_mod ) );
1763 damage * w->dam_as_dis_mod );
1768 w->voice =
sound_playPos( s, w->solid.pos.x, w->solid.pos.y,
1769 w->solid.vel.x, w->solid.vel.y );
1772 if ( radius > 0. ) {
1778 if ( hit->type == TARGET_PILOT ) {
1779 Pilot *ptarget = hit->u.plt;
1784 double realdmg =
pilot_hit( ptarget, &w->
solid, parent, &dmg, w->outfit,
1790 if ( ptarget->
shield > 0. )
1797 pilot_isPlayer( ptarget ) ? SPFX_LAYER_FRONT
1798 : SPFX_LAYER_MIDDLE );
1799 }
else if ( hit->type == TARGET_ASTEROID ) {
1802 double mining_bonus =
1806 VY( ast->
sol.
vel ), SPFX_LAYER_BACK );
1808 }
else if ( hit->type == TARGET_WEAPON ) {
1809 Weapon *wpn = hit->u.wpn;
1813 ( wpn->
layer == WEAPON_LAYER_FG ) ? SPFX_LAYER_FRONT
1814 : SPFX_LAYER_MIDDLE );
1832 if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_BLOWUP_ARMOUR ) )
1835 else if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_BLOWUP_SHIELD ) )
1841 spfx_add( spfx, w->solid.pos.x, w->solid.pos.y, w->solid.vel.x,
1843 ( w->layer == WEAPON_LAYER_FG ) ? SPFX_LAYER_FRONT
1844 : SPFX_LAYER_MIDDLE );
1848 w->voice =
sound_playPos( s, w->solid.pos.x, w->solid.pos.y,
1849 w->solid.vel.x, w->solid.vel.y );
1853 if ( w->outfit->lua_onmiss != LUA_NOREF ) {
1856 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, w->lua_mem );
1857 nlua_setenv(
naevL, w->outfit->lua_env,
"mem" );
1860 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, w->outfit->lua_onmiss );
1865 if ( nlua_pcall( w->outfit->lua_env, 4, 0 ) ) {
1866 WARN( _(
"Outfit '%s' -> '%s':\n%s" ), w->outfit->name,
"onmiss",
1867 lua_tostring(
naevL, -1 ) );
1868 lua_pop(
naevL, 1 );
1873 if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_MISS_EXPLODE ) ) {
1874 double damage, radius;
1880 damage = w->dam_mod * w->strength * odmg->
damage;
1882 dmg.
damage =
MAX( 0., damage * ( 1. - w->dam_as_dis_mod ) );
1886 damage * w->dam_as_dis_mod );
1904 double damage_armour;
1909 w->armour -= damage_armour + dmg->
disable;
1912 if ( w->armour > 0. )
1920 if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_BLOWUP_ARMOUR ) )
1923 else if ( outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_BLOWUP_SHIELD ) )
1927 spfx_add( spfx, w->solid.pos.x, w->solid.pos.y, w->solid.vel.x,
1929 ( w->layer == WEAPON_LAYER_FG ) ? SPFX_LAYER_FRONT
1930 : SPFX_LAYER_MIDDLE );
1934 w->voice =
sound_playPos( s, w->solid.pos.x, w->solid.pos.y,
1935 w->solid.vel.x, w->solid.vel.y );
1949 double damage, firerate, mod;
1956 if ( w->outfit->type == OUTFIT_TYPE_TURRET_BEAM )
1962 damage = odmg->
damage * mod;
1963 dmg.
damage =
MAX( 0., damage * ( 1. - w->dam_as_dis_mod ) );
1968 if ( hit->type == TARGET_PILOT ) {
1969 Pilot *p = hit->u.plt;
1973 pilot_hit( p, &w->solid, parent, &dmg, w->outfit, w->lua_mem, 1 );
1976 if ( w->timer2 <= 0. ) {
1979 WeaponLayer spfx_layer = ( w->layer == WEAPON_LAYER_FG )
1981 : SPFX_LAYER_MIDDLE;
1984 if ( p->shield > 0. )
1990 spfx_add( spfx, hit->pos[0].
x, hit->pos[0].
y, VX( p->solid.vel ),
1991 VY( p->solid.vel ), spfx_layer );
1992 spfx_add( spfx, hit->pos[1].
x, hit->pos[1].
y, VX( p->solid.vel ),
1993 VY( p->solid.vel ), spfx_layer );
2000 }
else if ( hit->type == TARGET_ASTEROID ) {
2002 double mining_bonus =
2007 if ( w->timer2 <= 0. ) {
2011 spfx_add( spfx, hit->pos[0].
x, hit->pos[0].
y, VX( a->sol.vel ),
2012 VY( a->sol.vel ), SPFX_LAYER_MIDDLE );
2013 spfx_add( spfx, hit->pos[1].
x, hit->pos[1].
y, VX( a->sol.vel ),
2014 VY( a->sol.vel ), SPFX_LAYER_MIDDLE );
2017 }
else if ( hit->type == TARGET_WEAPON ) {
2018 Weapon *wpn = hit->u.wpn;
2022 if ( w->timer2 <= 0. ) {
2025 WeaponLayer spfx_layer = ( w->layer == WEAPON_LAYER_FG )
2027 : SPFX_LAYER_MIDDLE;
2031 VY( wpn->
solid.
vel ), spfx_layer );
2033 VY( wpn->
solid.
vel ), spfx_layer );
2052 const vec2 *pos,
const vec2 *vel,
double dir,
double time )
2056 else if ( ( o->
type == OUTFIT_TYPE_LAUNCHER ) && ( o->
u.
lau.
ai > 0 ) ) {
2058 const vec2 *target_pos;
2059 double x, y, ang, off;
2060 switch ( target->type ) {
2061 case TARGET_PILOT: {
2063 if ( pilot_target == NULL )
2065 target_pos = &pilot_target->
solid.
pos;
2068 case TARGET_ASTEROID: {
2070 &
cur_system->asteroids[target->u.ast.anchor];
2072 target_pos = &ast->
sol.
pos;
2075 case TARGET_WEAPON: {
2077 if ( wtarget == NULL )
2086 x = target_pos->
x - pos->
x;
2087 y = target_pos->
y - pos->
y;
2088 ang = ANGLE( x, y );
2089 off = angle_diff( ang, dir );
2097 double off = angle_diff( rdir, dir );
2098 if (
FABS( off ) <= swivel )
2109 const vec2 *vel,
double dir,
double time )
2111 const Pilot *pilot_target = NULL;
2112 const vec2 *target_pos, *target_vel;
2113 double rx, ry, x, y, t, lead, rdir;
2115 switch ( target->type ) {
2117 pilot_target =
pilot_get( target->u.id );
2118 if ( pilot_target == NULL )
2120 target_pos = &pilot_target->
solid.
pos;
2121 target_vel = &pilot_target->
solid.
vel;
2124 case TARGET_ASTEROID: {
2126 &
cur_system->asteroids[target->u.ast.anchor];
2128 target_pos = &ast->
sol.
pos;
2129 target_vel = &ast->
sol.
vel;
2132 case TARGET_WEAPON: {
2134 if ( wtarget == NULL )
2146 rx = target_pos->
x - pos->
x;
2147 ry = target_pos->
y - pos->
y;
2155 double t_parent = t;
2161 x = ( target_pos->
x + target_vel->
x * t ) - ( pos->
x + vel->
x * t_parent );
2162 y = ( target_pos->
y + target_vel->
y * t ) - ( pos->
y + vel->
y * t_parent );
2165 if ( pilot_target != NULL ) {
2170 x = lead * x + ( 1. - lead ) * rx;
2171 y = lead * y + ( 1. - lead ) * ry;
2174 rdir = ANGLE( x, y );
2182 double tt, ddir, acc, pxv, ang, dvx, dvy;
2186 dvx = lead * ( target_vel->
x - vel->
x );
2187 dvy = lead * ( target_vel->
y - vel->
y );
2192 pxv = rx * dvy - ry * dvx;
2196 if ( fabs( ang + M_PI ) < fabs( ang ) )
2198 else if ( fabs( ang - M_PI ) < fabs( ang ) )
2200 ddir = -ang / 1000.;
2206 if ( fabs( ang ) > DOUBLE_TOL ) {
2209 for (
int i = 0; i < niter; i++ ) {
2214 pxv, vmin, acc, &tt );
2219 if ( tt < 0. || fabs(
d ) < 5. )
2224 rdir = rdir -
d / dtdd;
2246 const vec2 *vel,
double dir,
double time )
2259 off = angle_diff( rdir, dir );
2260 if (
FABS( off ) > swivel ) {
2262 rdir = dir - swivel;
2264 rdir = dir + swivel;
2279 double dir,
double swivel )
2281 double rx, ry, rdir, off;
2283 rx = target_pos->
x - pos->
x;
2284 ry = target_pos->
y - pos->
y;
2285 rdir = ANGLE( rx, ry );
2288 off = angle_diff( rdir, dir );
2289 if (
FABS( off ) > swivel ) {
2291 rdir = dir - swivel;
2293 rdir = dir + swivel;
2313 double dvx,
double dvy,
double pxv,
2314 double vmin,
double acc,
double *tt )
2316 double l, dxv, dxp, ct,
st,
d;
2323 dxv = ct * dvy -
st * dvx;
2324 dxp = ct * ry -
st * rx;
2331 d = .5 * acc * ( *tt ) * ( *tt ) +
2352 double dir,
const vec2 *pos,
const vec2 *vel,
2353 const Pilot *parent,
double time,
int aim )
2356 double mass, rdir, acc, m;
2379 if ( outfit->
type == OUTFIT_TYPE_TURRET_BOLT ) {
2392 w->dam_as_dis_mod =
CLAMP( 0., 1., w->dam_as_dis_mod );
2395 rdir += RNG_2SIGMA() * acc;
2396 rdir = angle_clean( rdir );
2404 vec2_cadd( &v, m * cos( rdir ), m * sin( rdir ) );
2407 solid_init( &w->solid, mass, rdir, pos, &v, SOLID_UPDATE_EULER );
2408 w->voice =
sound_playPos( w->outfit->u.blt.sound, w->solid.pos.x,
2409 w->solid.pos.y, w->solid.vel.x, w->solid.vel.y );
2413 if ( gfx->
tex != NULL )
2432 double dir,
const vec2 *pos,
const vec2 *vel,
2433 const Pilot *parent,
double time,
int aim )
2437 double mass, rdir, m;
2456 rdir = angle_clean( rdir );
2469 vec2_cadd( &v, m * cos( rdir ), m * sin( rdir ) );
2470 w->real_vel = VMOD( v );
2473 mass = w->outfit->u.lau.ammo_mass;
2476 solid_init( &w->solid, mass, rdir, pos, &v, SOLID_UPDATE_EULER );
2477 if ( w->outfit->u.lau.accel > 0. ) {
2481 w->solid.speed_max = w->outfit->u.lau.speed_max * w->speed_mod;
2482 if ( w->outfit->u.lau.speed > 0. )
2483 w->solid.speed_max = -1;
2487 if ( w->outfit->u.lau.armour > 0. ) {
2488 w->armour = w->outfit->u.lau.armour;
2489 weapon_setFlag( w, WEAPON_FLAG_HITTABLE );
2493 if ( w->outfit->u.lau.ai != AMMO_AI_UNGUIDED ) {
2496 w->status = ( w->timer2 > 0. ) ? WEAPON_STATUS_LOCKING : WEAPON_STATUS_OK;
2502 if ( w->target.type == TARGET_PILOT ) {
2504 if ( pilot_target != NULL )
2508 w->status = WEAPON_STATUS_OK;
2511 w->voice =
sound_playPos( w->outfit->u.lau.sound, w->solid.pos.x,
2512 w->solid.pos.y, w->solid.vel.x, w->solid.vel.y );
2516 if ( gfx->
tex != NULL )
2521 if ( w->outfit->u.lau.trail_spec != NULL )
2543 double T,
double dir,
const vec2 *pos,
2545 const Target *target,
double time,
int aim )
2549 ( ( ref == NULL ) && ( po != NULL ) ) ? po->
outfit : ref;
2552 memset( w, 0,
sizeof(
Weapon ) );
2554 w->layer = ( parent->
id == PLAYER_ID ) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG;
2563 w->parent = parent->
id;
2564 memcpy( &w->target, target,
sizeof(
Target ) );
2565 w->lua_mem = LUA_NOREF;
2566 if ( po != NULL && po->
lua_mem != LUA_NOREF ) {
2568 w->lua_mem = luaL_ref(
naevL, LUA_REGISTRYINDEX );
2572 w->strength_base = 1.;
2575 if ( outfit_isProp( outfit, OUTFIT_PROP_WEAP_ONLYHITTARGET ) )
2576 weapon_setFlag( w, WEAPON_FLAG_ONLYHITTARGET );
2580 ( w->target.type == TARGET_PILOT ) ) {
2582 if ( pilot_target != NULL )
2586 switch ( outfit->
type ) {
2589 case OUTFIT_TYPE_BOLT:
2590 case OUTFIT_TYPE_TURRET_BOLT:
2595 case OUTFIT_TYPE_BEAM:
2596 case OUTFIT_TYPE_TURRET_BEAM:
2598 if ( outfit->
type == OUTFIT_TYPE_TURRET_BEAM ) {
2603 weapon_setFlag( w, WEAPON_FLAG_AIM );
2604 switch ( w->target.type ) {
2609 if ( w->parent != w->target.u.id ) {
2611 rdir = vec2_angle( pos, &pilot_target->
solid.
pos );
2615 case TARGET_ASTEROID:
2616 field = &
cur_system->asteroids[w->target.u.ast.anchor];
2617 ast = &field->
asteroids[w->target.u.ast.asteroid];
2618 rdir = vec2_angle( pos, &ast->
sol.
pos );
2623 if ( wtarget != NULL )
2624 rdir = vec2_angle( pos, &wtarget->
solid.
pos );
2630 rdir = vec2_angle( pos, &tv );
2633 rdir = angle_clean( rdir );
2636 solid_init( &w->solid, mass, rdir, pos, vel, SOLID_UPDATE_EULER );
2640 sound_playPos( w->outfit->u.bem.sound, w->solid.pos.x, w->solid.pos.y,
2641 w->solid.vel.x, w->solid.vel.y );
2643 if ( outfit->
type == OUTFIT_TYPE_BEAM ) {
2652 w->dam_as_dis_mod =
CLAMP( 0., 1., w->dam_as_dis_mod );
2657 case OUTFIT_TYPE_LAUNCHER:
2658 case OUTFIT_TYPE_TURRET_LAUNCHER:
2664 WARN( _(
"Weapon of type '%s' has no create implemented yet!" ),
2666 solid_init( &w->solid, 1., dir, pos, vel, SOLID_UPDATE_EULER );
2691 const Target *target,
double time,
int aim )
2699 WARN( _(
"Trying to create a Weapon from a non-Weapon type Outfit" ) );
2705 weapon_create( w, po, ref, T, dir, pos, vel, parent, target, time, aim );
2717 switch ( t->type ) {
2720 case TARGET_PILOT: {
2726 case TARGET_WEAPON: {
2732 case TARGET_ASTEROID: {
2757 const Target *target,
int aim )
2762 WARN( _(
"Trying to create a Beam Weapon from a non-beam outfit." ) );
2767 weapon_create( w, po, NULL, 0., dir, pos, vel, parent, target, 0., aim );
2783 WARN( _(
"Trying to remove beam with ID 0!" ) );
2791 if ( w->id == beam ) {
2806 weapon_setFlag( w, WEAPON_FLAG_DESTROYED );
2819 sound_playPos( w->outfit->u.bem.sound_off, w->solid.pos.x, w->solid.pos.y,
2820 w->solid.vel.x, w->solid.vel.y );
2821 }
else if ( w->target.type == TARGET_PILOT ) {
2825 if ( pilot_target != NULL ) {
2839 luaL_unref(
naevL, LUA_REGISTRYINDEX, w->lua_mem );
2842 memset( w, 0,
sizeof(
Weapon ) );
2851 NTracingZone( _ctx, 1 );
2864 NTracingZoneEnd( _ctx );
2889const IntList *weapon_collideQuery(
int x1,
int y1,
int x2,
int y2 )
2895void weapon_collideQueryIL(
IntList *il,
int x1,
int y1,
int x2,
int y2 )
void ai_attacked(Pilot *attacked, const unsigned int attacker, double dmg)
Triggers the attacked() function in the pilot's AI.
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_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_begin(array)
Returns a pointer to the beginning of the reserved memory space.
#define array_reserved(array)
Returns number of elements reserved.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
void asteroid_hit(Asteroid *a, const Damage *dmg, int max_rarity, double mining_bonus)
Hits an asteroid.
double cam_getZoom(void)
Gets the camera zoom.
int CollideCircleCircle(const vec2 *p1, double r1, const vec2 *p2, double r2, vec2 crash[2])
Computes the collision between two circles.
int CollideSpritePolygon(const CollPolyView *at, const vec2 *ap, const glTexture *bt, int bsx, int bsy, const vec2 *bp, vec2 *crash)
Checks whether or not a sprite collides with a polygon.
void poly_rotate(CollPolyView *rpolygon, const CollPolyView *ipolygon, float theta)
Rotates a polygon.
int CollideLineCircle(const vec2 *p1, const vec2 *p2, const vec2 *cc, double cr, vec2 crash[2])
Checks to see if a line collides with a circle.
int CollideLineSprite(const vec2 *ap, double ad, double al, const glTexture *bt, const int bsx, const int bsy, const vec2 *bp, vec2 crash[2])
Checks to see if a line collides with a sprite.
int CollideCircleSprite(const vec2 *ap, double ar, const glTexture *bt, const int bsx, const int bsy, const vec2 *bp, vec2 *crash)
Checks whether or not a sprite collides with a polygon.
int CollideCirclePolygon(const vec2 *ap, double ar, const CollPolyView *bt, const vec2 *bp, vec2 crash[2])
Checks to see if a circle collides with a polygon.
int CollideLinePolygon(const vec2 *ap, double ad, double al, const CollPolyView *bt, const vec2 *bp, vec2 crash[2])
Checks to see if a line collides with a polygon.
int CollideSprite(const glTexture *at, const int asx, const int asy, const vec2 *ap, const glTexture *bt, const int bsx, const int bsy, const vec2 *bp, vec2 *crash)
Checks whether or not two sprites collide.
int CollidePolygon(const CollPolyView *at, const vec2 *ap, const CollPolyView *bt, const vec2 *bp, vec2 *crash)
Checks whether or not two polygons collide. /!\ The function is not symmetric: the points of polygon ...
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 areEnemies(int a, int b)
Checks whether two factions are enemies.
void mat4_rotate2d(mat4 *m, double angle)
Rotates an angle, in radians, around the z axis.
Header file with generic functions and naev-specifics.
const Outfit ** lua_pushoutfit(lua_State *L, const Outfit *outfit)
Pushes a outfit on the stack.
LuaPilot * lua_pushpilot(lua_State *L, LuaPilot pilot)
Pushes a pilot on the stack.
vec2 * lua_pushvector(lua_State *L, vec2 vec)
Pushes a vector on the stack.
void gl_renderShader(double x, double y, double w, double h, double r, const SimpleShader *shd, const glColour *c, int center)
Renders a simple shader.
void gl_gameToScreenCoords(double *nx, double *ny, double bx, double by)
Converts in-game coordinates to screen coordinates.
void gl_renderSpriteInterpolate(const glTexture *sa, const glTexture *sb, double inter, double bx, double by, int sx, int sy, const glColour *c)
Blits a sprite interpolating, position is relative to the player.
void gl_renderSprite(const glTexture *sprite, double bx, double by, int sx, int sy, const glColour *c)
Blits a sprite, position is relative to the player.
void gl_screenToGameCoords(double *nx, double *ny, int bx, int by)
Converts screen coordinates to in-game coordinates.
void gl_getSpriteFromDir(int *x, int *y, int sx, int sy, double dir)
Sets x and y to be the appropriate sprite for glTexture using dir.
void gl_vboDestroy(gl_vbo *vbo)
Destroys a VBO.
gl_vbo * gl_vboCreateStream(GLsizei size, const void *data)
Creates a stream vbo.
void gl_vboActivateAttribOffset(gl_vbo *vbo, GLuint index, GLuint offset, GLint size, GLenum type, GLsizei stride)
Activates a VBO's offset.
void gl_vboData(gl_vbo *vbo, GLsizei size, const void *data)
Reloads new data or grows the size of the vbo.
void gl_vboSubData(gl_vbo *vbo, GLint offset, GLsizei size, const void *data)
Loads some data into the VBO.
double outfit_trackmin(const Outfit *o)
Gets the outfit's minimal tracking.
int outfit_isBeam(const Outfit *o)
Checks if outfit is a beam type weapon.
int outfit_soundHit(const Outfit *o)
Gets the outfit's hit sound.
int outfit_isLauncher(const Outfit *o)
Checks if outfit is a weapon launcher.
int outfit_isSeeker(const Outfit *o)
Checks if outfit is a seeking weapon.
int outfit_miningRarity(const Outfit *o)
Gets the maximum rarity the outfit can mine up to.
double outfit_radius(const Outfit *o)
Gets the outfit's explosion radius.
int outfit_spfxShield(const Outfit *o)
Gets the outfit's sound effect.
int outfit_isTurret(const Outfit *o)
Checks if outfit is a turret class weapon.
const CollPoly * outfit_plg(const Outfit *o)
Gets the outfit's collision polygon.
const OutfitGFX * outfit_gfx(const Outfit *o)
Gets the outfit's graphic effect.
double outfit_spin(const Outfit *o)
Gets the outfit's animation spin.
double outfit_trackmax(const Outfit *o)
Gets the outfit's minimal tracking.
int outfit_spfxArmour(const Outfit *o)
Gets the outfit's sound effect.
const Damage * outfit_damage(const Outfit *o)
Gets the outfit's damage.
double outfit_swivel(const Outfit *o)
Gets the swivel of an outfit.
int outfit_isBolt(const Outfit *o)
Checks if outfit is bolt type weapon.
int pilot_isHostile(const Pilot *p)
Checks to see if pilot is hostile to the player.
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
void pilot_setHostile(Pilot *p)
Marks pilot as hostile to player.
static Pilot ** pilot_stack
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
double pilot_hit(Pilot *p, const Solid *w, const Pilot *pshooter, const Damage *dmg, const Outfit *outfit, int lua_mem, int reset)
Damages the pilot.
double pilot_ewWeaponTrack(const Pilot *p, const Pilot *t, double trackmin, double trackmax)
Calculates the weapon lead (1. is 100%, 0. is 0%)..
int pilot_inRange(const Pilot *p, double x, double y)
Check to see if a position is in range of the pilot.
double pilot_heatAccuracyMod(double T)
Returns a 0:1 modifier representing accuracy (0. being normal).
void pilot_heatAddSlotTime(const Pilot *p, PilotOutfitSlot *o, double dt)
Adds heat to an outfit slot over a period of time.
int pilot_getMount(const Pilot *p, const PilotOutfitSlot *w, vec2 *v)
Gets the mount position of a pilot.
void pilot_stopBeam(const Pilot *p, PilotOutfitSlot *w)
Stops a beam outfit and sets delay as appropriate.
double pilot_weapFlyTime(const Outfit *o, const Pilot *parent, const vec2 *pos, const vec2 *vel)
Computes an estimation of ammo flying time.
int sound_playPos(int sound, double px, double py, double vx, double vy)
Plays a sound based on position.
void sound_stop(int voice)
Stops a voice from playing.
int sound_updatePos(int voice, double px, double py, double vx, double vy)
Updates the position of a voice.
int space_needsEffects(void)
returns whether or not we're simulating with effects.
void spfx_trail_sample(Trail_spfx *trail, double x, double y, double z, double dx, double dy, TrailMode mode, int force)
Makes a trail grow.
void spfx_trail_remove(Trail_spfx *trail)
Removes a trail.
void spfx_add(int effect, const double px, const double py, const double vx, const double vy, int layer)
Creates a new special effect.
Trail_spfx * spfx_trail_create(const TrailSpec *spec)
Initalizes a trail.
Represents an asteroid field anchor.
Represents a single asteroid.
Represents a polygon used for collision detection.
Core damage that an outfit does.
A ship outfit, depends radically on the type.
union Outfit::@052125200133344144252153256241104103242010347340 u
Stores an outfit the pilot has.
The representation of an in-game pilot.
double launch_calibration
Represents a solid in the game.
Represents a weapon target.
Struct useful for generalization of weapno collisions.
const CollPolyView * polyview
Represents a weapon hitting something.
In-game representation of a weapon.
Abstraction for rendering sprite sheets.
static void weapon_hitBeam(Weapon *w, const WeaponHit *hit, double dt)
A beam weapon hit something.
void weapons_update(double dt)
Updates all the weapons.
static void weapon_updateVBO(void)
Checks to see if we have to update the VBO size.
double weapon_targetFlyTime(const Outfit *o, const Pilot *p, const Target *t)
Gets the fly time for a weapon target.
static void weapon_sample_trail(Weapon *w)
Updates the animated trail for a weapon.
unsigned int beam_start(PilotOutfitSlot *po, double dir, const vec2 *pos, const vec2 *vel, const Pilot *parent, const Target *target, int aim)
Starts a beam weapon.
static int weapon_checkCanHit(const Weapon *w, const Pilot *p)
Checks to see if the weapon can hit the pilot.
static unsigned int weapon_idgen
Weapon * weapon_add(PilotOutfitSlot *po, const Outfit *ref, double dir, const vec2 *pos, const vec2 *vel, const Pilot *parent, const Target *target, double time, int aim)
Creates a new weapon.
static void weapon_destroy(Weapon *w)
Destroys a weapon.
static gl_vbo * weapon_vbo
static void weapon_render(Weapon *w, double dt)
Renders an individual weapon.
static double weapon_computeTimes(double rdir, double rx, double ry, double dvx, double dvy, double pxv, double vmin, double acc, double *tt)
Computes precisely interception times for propelled weapons (rockets).
static double weapon_aimTurretStatic(const vec2 *target_pos, const vec2 *pos, double dir, double swivel)
Gets the aim position of a turret weapon.
static void weapon_createBolt(Weapon *w, const Outfit *outfit, double T, double dir, const vec2 *pos, const vec2 *vel, const Pilot *parent, double time, int aim)
Creates the bolt specific properties of a weapon.
Weapon * weapon_getID(unsigned int id)
Gets a weapon by ID.
static double weapon_aimTurretAngle(const Outfit *outfit, const Pilot *parent, const Target *target, const vec2 *pos, const vec2 *vel, double dir, double time)
Gets the aim direction of a turret weapon.
static void weapon_hit(Weapon *w, const WeaponHit *hit)
A bolt/launcher weapon hit something.
static void weapon_updateCollide(Weapon *w, double dt)
Updates an individual weapon.
static void weapon_setTurn(Weapon *w, double turn)
Sets the weapon's turn.
static IntList weapon_qtquery
static void weapon_setAccel(Weapon *w, double accel)
Sets the weapon's accel.
void weapons_updatePurge(void)
Purges unnecessary weapons.
void weapon_clear(void)
Clears all the weapons, does NOT free the layers.
static void weapon_createAmmo(Weapon *w, const Outfit *outfit, double T, double dir, const vec2 *pos, const vec2 *vel, const Pilot *parent, double time, int aim)
Creates the ammo specific properties of a weapon.
static void weapon_damage(Weapon *w, const Damage *dmg)
Applies damage to a weapon.
void weapons_updateCollide(double dt)
Handles weapon collisions.
static void weapon_update(Weapon *w, double dt)
Updates an individual weapon.
static Quadtree weapon_quadtree
void weapon_hitAI(Pilot *p, const Pilot *shooter, double dmg)
Informs the AI if needed that it's been hit.
static GLfloat * weapon_vboData
int weapon_inArc(const Outfit *o, const Pilot *parent, const Target *target, const vec2 *pos, const vec2 *vel, double dir, double time)
Gets the aim position of a turret weapon.
void weapon_minimap(double res, double w, double h, const RadarShape shape, double alpha)
Draws the minimap weapons (used in player.c).
static void weapon_hitExplode(Weapon *w, const Damage *dmg, double radius, const vec2 *center)
A weapon hit something and decided to explode.
Weapon * weapon_getStack(void)
Gets the weapon stack. Do not manipulate directly.
static double weapon_aimTurret(const Outfit *outfit, const Pilot *parent, const Target *target, const vec2 *pos, const vec2 *vel, double dir, double time)
Gets the aim position of a turret weapon.
static void weapon_free(Weapon *w)
Frees the weapon.
static void weapon_miss(Weapon *w)
Weapon missed and is due to be destroyed.
void weapon_exit(void)
Destroys all the weapons and frees it all.
static int weapon_cmp(const void *ptr1, const void *ptr2)
Compare id (for use with bsearch)
static void think_beam(Weapon *w, double dt)
The pseudo-ai of the beam weapons.
static int weapon_testCollision(const WeaponCollision *wc, const glTexture *ctex, int csx, int csy, const Solid *csol, const CollPolyView *cpol, double cradius, vec2 crash[2])
Tests to see if a weapon collides with a ship.
static IntList weapon_qtexp
void weapons_render(const WeaponLayer layer, double dt)
Renders all the weapons in a layer.
void weapon_init(void)
Initializes the weapon stuff.
static size_t weapon_vboSize
static Weapon * weapon_stack
static void think_seeker(Weapon *w, double dt)
The AI of seeker missiles.
static int weapon_create(Weapon *w, PilotOutfitSlot *po, const Outfit *ref, double T, double dir, const vec2 *pos, const vec2 *vel, const Pilot *parent, const Target *target, double time, int aim)
Creates a new weapon.
void weapon_newSystem(void)
Sets up collision stuff for a new system.
void beam_end(unsigned int beam)
Ends a beam weapon.