29#include "nlua_pilot.h"
31#include "nlua_outfit.h"
42typedef struct WeaponCollision_ {
55typedef struct WeaponHit_ {
86 const Target *target,
const vec2 *pos,
const vec2 *vel,
double dir,
double time );
88 const Target *target,
const vec2 *pos,
const vec2 *vel,
double dir,
double time );
91 double dir,
const vec2* pos,
const vec2* vel,
const Pilot* parent,
double time,
int aim );
93 double dir,
const vec2* pos,
const vec2* vel,
const Pilot* parent,
double time,
int aim );
95 double T,
double dir,
const vec2* pos,
const vec2* vel,
96 const Pilot* parent,
const Target *target,
double time,
int aim );
97static double weapon_computeTimes(
double rdir,
double rx,
double ry,
double dvx,
double dvy,
double pxv,
98 double vmin,
double acc,
double *tt );
114 int csx,
int csy,
const Solid *csol,
const CollPoly *cpol,
double cradius,
vec2 crash[2] );
120 double h,
const RadarShape shape,
double alpha );
166 w1 = (
const Weapon*) ptr1;
167 w2 = (
const Weapon*) ptr2;
168 return w1->
id - w2->
id;
176 const Weapon wid = { .id =
id };
178 if ((w==NULL) || weapon_isFlag(w,WEAPON_FLAG_DESTROYED))
205 double h,
const RadarShape shape,
double alpha )
214 if (shape==RADAR_CIRCLE)
237 if (shape==RADAR_RECT && (
ABS(x)>w/2. ||
ABS(y)>h/2.))
239 if (shape==RADAR_CIRCLE && (((x)*(x)+(y)*(y)) > rc))
243 isplayer = ((wp->
target.type==TARGET_PILOT) && (wp->
target.u.id==PLAYER_ID));
280 glUseProgram(shaders.points.program);
281 glEnableVertexAttribArray(shaders.points.vertex);
282 glEnableVertexAttribArray(shaders.points.vertex_colour);
283 gl_uniformMat4(shaders.points.projection, &gl_view_matrix);
286 glDrawArrays( GL_POINTS, 0, p );
287 glDisableVertexAttribArray(shaders.points.vertex);
288 glDisableVertexAttribArray(shaders.points.vertex_colour);
299 w->solid.accel = accel;
307 w->solid.dir_vel = turn;
320 double turn_max, jc, speed_mod;
322 if (w->target.type != TARGET_PILOT)
336 case WEAPON_STATUS_LOCKING:
341 w->status = WEAPON_STATUS_OK;
345 case WEAPON_STATUS_OK:
346 jc = p->stats.jam_chance - w->outfit->u.lau.resist;
349 double d = vec2_dist( &p->solid.pos, &w->solid.pos );
350 if (
d < w->r * p->ew_signature) {
355 w->status = WEAPON_STATUS_JAMMED;
358 w->status = WEAPON_STATUS_JAMMED;
359 weapon_setTurn( w, w->outfit->u.lau.turn * ((RNGF()>0.5)?-1.0:1.0) );
362 w->status = WEAPON_STATUS_JAMMED;
367 w->status = WEAPON_STATUS_JAMMED_SLOWED;
368 w->falloff = RNGF()*0.5;
373 w->status = WEAPON_STATUS_UNJAMMED;
378 case WEAPON_STATUS_JAMMED_SLOWED:
379 case WEAPON_STATUS_UNJAMMED:
380 turn_max = w->outfit->u.lau.turn;
383 if (w->outfit->u.lau.ai == AMMO_AI_SMART) {
388 vec2_csetmin( &v, p->solid.pos.x - w->solid.pos.x,
389 p->solid.pos.y - w->solid.pos.y );
391#define QUADRATURE(ref, v) ((v).x * (-(ref).y) + (v).y * (ref).x)
392 if (vec2_dot(&v, &w->solid.vel) < 0) {
397 if (QUADRATURE(w->solid.vel, v) > 0)
404 vec2_csetmin( &r_vel, p->solid.vel.x - w->solid.vel.x,
405 p->solid.vel.y - w->solid.vel.y);
406 if (vec2_dot(&r_vel, &w->solid.vel) > 0) {
411 if (QUADRATURE(w->solid.vel, p->solid.vel) > 0)
422 if (QUADRATURE(r_vel, v) < 0)
432 double diff = angle_diff(w->solid.dir,
433 vec2_angle(&w->solid.pos, &p->solid.pos));
435 10 * diff * w->outfit->u.lau.turn ));
439 case WEAPON_STATUS_JAMMED:
444 WARN(_(
"Unknown weapon status for '%s'"), w->outfit->name);
449 speed_mod = (w->status==WEAPON_STATUS_JAMMED_SLOWED) ? w->falloff : 1.;
452 w->real_vel =
MIN( speed_mod * w->outfit->u.lau.speed_max, w->real_vel + w->outfit->u.lau.accel*dt );
453 vec2_pset( &w->solid.vel, w->real_vel, w->solid.dir );
472 unsigned int turn_off;
481 dt *= p->stats.time_speedup;
484 mod = (w->outfit->type == OUTFIT_TYPE_BEAM) ? p->stats.fwd_energy : p->stats.tur_energy;
485 p->energy -= mod * dt*w->outfit->u.bem.energy;
487 if (p->energy < 0.) {
496 switch (w->target.type) {
500 case TARGET_ASTEROID:
503 ast = &field->
asteroids[ w->target.u.ast.asteroid ];
539 w->solid.pos.x = p->solid.pos.x + v.x;
540 w->solid.pos.y = p->solid.pos.y + v.y;
543 switch (w->outfit->type) {
544 case OUTFIT_TYPE_BEAM:
545 if (w->outfit->u.bem.swivel > 0.)
546 w->solid.dir =
weapon_aimTurret( w->outfit, p, &w->target, &w->solid.pos, &p->solid.vel, p->solid.dir, 0. );
548 w->solid.dir = p->solid.dir;
551 case OUTFIT_TYPE_TURRET_BEAM:
552 if (!weapon_isFlag(w,WEAPON_FLAG_AIM) && pilot_isPlayer(p) && (SDL_ShowCursor(SDL_QUERY)==SDL_ENABLE)) {
555 diff = angle_diff(w->solid.dir,
556 vec2_angle( &w->solid.pos, &tv ) );
561 else if (t == NULL) {
563 diff = angle_diff(w->solid.dir,
564 vec2_angle( &w->solid.pos, &ast->
sol.
pos ));
567 diff = angle_diff(w->solid.dir, p->solid.dir);
570 diff = angle_diff(w->solid.dir,
571 vec2_angle(&w->solid.pos, &t->
solid.
pos));
573 weapon_setTurn( w, p->stats.time_speedup*
CLAMP( -w->outfit->u.bem.turn, w->outfit->u.bem.turn,
574 10. * diff * w->outfit->u.bem.turn ));
593 if (!weapon_isFlag(w,WEAPON_FLAG_DESTROYED))
602 int x,y, px,py, w2,h2;
606 if (!weapon_isFlag(w,WEAPON_FLAG_HITTABLE))
610 if (gfx->
tex != NULL)
616 x = round(w->solid.pos.x);
617 y = round(w->solid.pos.y);
618 px = round(w->solid.pre.x);
619 py = round(w->solid.pre.y);
620 w2 = ceil(range * 0.5);
621 h2 = ceil(range * 0.5);
635 if (weapon_isFlag(w, WEAPON_FLAG_DESTROYED))
639 switch (w->outfit->type) {
642 case OUTFIT_TYPE_LAUNCHER:
643 case OUTFIT_TYPE_TURRET_LAUNCHER:
649 case OUTFIT_TYPE_BOLT:
650 case OUTFIT_TYPE_TURRET_BOLT:
656 else if (w->timer < w->falloff)
657 w->strength = w->timer / w->falloff * w->strength_base;
661 case OUTFIT_TYPE_BEAM:
662 case OUTFIT_TYPE_TURRET_BEAM:
666 if (w->timer < 0. || (w->outfit->u.bem.min_duration > 0. &&
667 w->mount->stimer < 0.)) {
680 WARN(_(
"Weapon of type '%s' has no update implemented yet!"),
686 if (!weapon_isFlag(w, WEAPON_FLAG_DESTROYED))
701 if (!weapon_isFlag(w, WEAPON_FLAG_DESTROYED))
721static void weapon_renderBeam(
Weapon* w,
double dt )
730 glUseProgram(shaders.beam.program);
738 projection = gl_view_matrix;
741 mat4_scale( &projection, w->outfit->u.bem.range*z,w->outfit->u.bem.width * z, 1. );
745 glEnableVertexAttribArray( shaders.beam.vertex );
750 gl_uniformMat4(shaders.beam.projection, &projection);
751 gl_uniformColour(shaders.beam.colour, &w->outfit->u.bem.colour);
752 glUniform2f(shaders.beam.dimensions, w->outfit->u.bem.range, w->outfit->u.bem.width);
753 glUniform1f(shaders.beam.dt, w->anim);
754 glUniform1f(shaders.beam.r, w->r);
757 if (gl_has( OPENGL_SUBROUTINES ))
758 glUniformSubroutinesuiv( GL_FRAGMENT_SHADER, 1, &w->outfit->u.bem.shader );
761 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
764 glDisableVertexAttribArray( shaders.beam.vertex );
781 glColour col,
c = { .r=1., .g=1., .b=1. };
784 if (weapon_isFlag(w,WEAPON_FLAG_DESTROYED))
787 switch (w->outfit->type) {
789 case OUTFIT_TYPE_LAUNCHER:
790 case OUTFIT_TYPE_TURRET_LAUNCHER:
791 if (w->status == WEAPON_STATUS_LOCKING) {
795 r = w->outfit->u.lau.gfx.size * z * 0.75;
797 st = 1. - w->timer2 / w->paramf;
801 glUseProgram( shaders.iflockon.program );
802 glUniform1f( shaders.iflockon.paramf,
st );
806 case OUTFIT_TYPE_BOLT:
807 case OUTFIT_TYPE_TURRET_BOLT:
811 c.a =
MIN( 1., w->strength );
814 if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_SPIN)) {
817 if (gfx->
tex != NULL) {
827 if (w->sprite >= tex->
sx*tex->
sy)
834 w->solid.pos.x, w->solid.pos.y,
835 w->sprite % (
int)tex->
sx, w->sprite / (
int)tex->
sx, &
c );
838 w->sprite % (
int)tex->
sx, w->sprite / (
int)tex->
sx, &
c );
844 if (gfx->
tex != NULL) {
849 w->solid.pos.x, w->solid.pos.y, w->
sx, w->sy, &
c );
864 if ((x < -r) || (x > SCREEN_W+r) ||
865 (y < -r) || (y > SCREEN_H+r))
868 mat4 projection = gl_view_matrix;
875 glUniform1f( gfx->
u_r, w->r );
876 glUniform1f( gfx->
u_time, w->life-w->timer );
877 glUniform1f( gfx->
u_fade,
MIN( 1., w->strength ) );
878 gl_uniformMat4( gfx->
projection, &projection );
880 glEnableVertexAttribArray( gfx->
vertex );
883 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
885 glDisableVertexAttribArray(gfx->
vertex);
893 case OUTFIT_TYPE_BEAM:
894 case OUTFIT_TYPE_TURRET_BEAM:
895 weapon_renderBeam(w, dt);
899 WARN(_(
"Weapon of type '%s' has no render implemented yet!"),
915 if (pilot_isFlag(p, PILOT_INVINCIBLE))
919 if (pilot_isFlag(p, PILOT_HIDE))
923 if (pilot_isFlag(p, PILOT_LANDING) ||
924 pilot_isFlag(p, PILOT_TAKEOFF))
928 if (pilot_isFlag(p, PILOT_DEAD))
932 if ((w->faction == FACTION_PLAYER) &&
933 pilot_isFlag(p, PILOT_INVINC_PLAYER))
937 if ((w->target.type==TARGET_PILOT) && (w->target.u.id==p->id))
941 if (p->faction == w->faction)
945 if (w->faction == FACTION_PLAYER) {
957 if (p->faction == FACTION_PLAYER) {
959 if (parent != NULL) {
986 int csx,
int csy,
const Solid *csol,
const CollPoly *cpol,
double cradius,
vec2 crash[2] )
990 const vec2 *wpos, *cpos;
993 wpos = &w->solid.pos;
1003 double vx1 = w->solid.pre.x - w->solid.pos.x;
1004 double vy1 = w->solid.pre.y - w->solid.pos.y;
1005 double vx2 = csol->
pre.
x - csol->
pos.
x;
1006 double vy2 = csol->
pre.
y - csol->
pos.
y;
1007 double b = vx1 - vx2;
1008 double d = vy1 - vy2;
1011 if ((fabs(b)>1e-5) || (fabs(
d)>1e-5)) {
1012 double a = w->solid.pos.x - csol->
pos.
x;
1013 double c = w->solid.pos.y - csol->
pos.
y;
1014 double t =
CLAMP( 0., 1., -(a*b+
c*
d) / (b*b+
d*
d) );
1016 wipos.
x = w->solid.pos.x + t*vx1;
1017 wipos.
y = w->solid.pos.y + t*vy1;
1018 cipos.
x = csol->
pos.
x + t*vx2;
1019 cipos.
y = csol->
pos.
y + t*vy2;
1029 double s1x = csol->
pos.
x;
1030 double s1y = csol->
pos.
y;
1031 double e1x = csol->
pre.
x;
1032 double e1y = csol->
pre.
y;
1033 double s2x = w->solid.pos.x;
1034 double s2y = w->solid.pos.y;
1035 double e2x = w->solid.pos.x + cos(w->solid.dir) * wc->
beamrange;
1036 double e2y = w->solid.pos.y + sin(w->solid.dir) * wc->
beamrange;
1039 double u_b = (e2y - s2y) * (e1x - s1x) - (e2x - s2x) * (e1y - s1y);
1042 if (fabs(u_b) > 1e-5) {
1043 double ua_t = (e2x - s2x) * (s1y - s2y) - (e2y - s2y) * (s1x - s2x);
1046 double ua =
CLAMP( 0., 1., ua_t / u_b );
1049 cipos.
x = s1x + ua * (e1x-s1x);
1050 cipos.
y = s1y + ua * (e1y-s1y);
1059 int k = ctex->
sx * csy + csx;
1063 else if (ctex!=NULL) {
1065 wc->
beamrange, ctex, csx, csy, cpos, crash);
1068 const vec2 endpoint = { .x=e2x, .y=e2y };
1075 double ub_t = (e1x - s1x) * (s1y - s2y) - (e1y - s1y) * (s1x - s2x);
1076 double ub =
CLAMP( 0., 1., ub_t / u_b );
1077 wipos.
x = s2x + ub * (e2x-s2x);
1078 wipos.
y = s2y + ub * (e2y-s2y);
1083 double vx1 = s1x-s2x;
1084 double vy1 = s1y-s2y;
1085 double vx2 = e2x-s2x;
1086 double vy2 = e2y-s2y;
1087 double t = (vx1*vx2 + vy1*vy2) / (
pow2(vx2)+
pow2(vy2));
1088 t =
CLAMP( 0., 1., t );
1089 wipos.
x = s2x + t * vx2;
1090 wipos.
y = s2y + t * vy2;
1100 int k = ctex->
sx * csy + csx;
1105 else if ((wc->
gfx!=NULL) && (wc->
gfx->
tex != NULL))
1112 else if (ctex != NULL) {
1117 else if ((wc->
gfx!=NULL) && (wc->
gfx->
tex!=NULL))
1119 ctex, csx, csy, cpos, crash );
1130 else if ((wc->
gfx!=NULL) && (wc->
gfx->
tex!=NULL))
1156 int x, y, w2, h2, px, py;
1158 if (wc.
gfx->
tex != NULL) {
1163 n = wc.
gfx->
tex->
sx * w->sy + w->sx;
1177 x = round(w->solid.pos.x);
1178 y = round(w->solid.pos.y);
1179 px = x+round(w->solid.pre.x);
1180 py = y+round(w->solid.pre.y);
1181 w2 = ceil(wc.
range * 0.5);
1182 h2 = ceil(wc.
range * 0.5);
1193 if (w->outfit->type == OUTFIT_TYPE_BEAM) {
1194 w->dam_mod = p->stats.fwd_damage;
1195 w->dam_as_dis_mod = p->stats.fwd_dam_as_dis-1.;
1198 w->dam_mod = p->stats.tur_damage;
1199 w->dam_as_dis_mod = p->stats.tur_dam_as_dis-1.;
1201 w->dam_as_dis_mod =
CLAMP( 0., 1., w->dam_as_dis_mod );
1205 wc.
range = w->outfit->u.bem.width*0.5;
1209 x1 = round(w->solid.pos.x);
1210 y1 = round(w->solid.pos.y);
1211 x2 = x1 + ceil( w->outfit->u.bem.range * cos(w->solid.dir) );
1212 y2 = y1 + ceil( w->outfit->u.bem.range * sin(w->solid.dir) );
1226 if (!outfit_isProp(w->outfit,OUTFIT_PROP_WEAP_MISS_SHIPS)) {
1233 if (pilot_isFlag(p, PILOT_DELETE))
1237 if (w->parent==p->id)
1241 if (weapon_isSmart(w)) {
1242 int isjammed = ((w->status == WEAPON_STATUS_JAMMED) || (w->status == WEAPON_STATUS_JAMMED_SLOWED));
1243 if (!isjammed && (w->target.type==TARGET_PILOT) && (p->id != w->target.u.id))
1248 if (weapon_isFlag(w,WEAPON_FLAG_ONLYHITTARGET)) {
1249 if ((w->target.type==TARGET_PILOT) && (p->id != w->target.u.id))
1259 &p->solid, p->ship->polygon, 0., crash ))
1263 hit.type = TARGET_PILOT;
1278 if (!outfit_isProp(w->outfit,OUTFIT_PROP_WEAP_MISS_ASTEROIDS)) {
1284 if (vec2_dist2( &w->solid.pos, &ast->
pos ) >
1295 if (a->state != ASTEROID_FG)
1298 if (a->polygon->npt!=0) {
1313 hit.type = TARGET_ASTEROID;
1327 if (outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_POINTDEFENSE )) {
1340 if (wchit.
gfx->
tex != NULL) {
1356 hit.type = TARGET_WEAPON;
1379 (*w->think)( w, dt );
1382 (*w->solid.update)( &w->solid, dt );
1386 w->solid.vel.x, w->solid.vel.y);
1389 if (w->trail != NULL)
1406 dx = w->outfit->u.lau.trail_x_offset * cos(a);
1407 dy = w->outfit->u.lau.trail_x_offset * sin(a);
1410 if ((w->outfit->u.lau.ai == AMMO_AI_UNGUIDED) ||
1411 w->solid.vel.x*w->solid.vel.x + w->solid.vel.y*w->solid.vel.y + 1.
1412 < w->solid.speed_max*w->solid.speed_max)
1413 mode = MODE_AFTERBURN;
1414 else if (w->solid.dir_vel != 0.)
1419 spfx_trail_sample( w->trail, w->solid.pos.x + dx, w->solid.pos.y + dy*M_SQRT1_2, mode, 0 );
1432 if (shooter == NULL)
1440 if (pilot_isDisabled(p))
1444 if (pilot_isFlag(p, PILOT_DELETE) || pilot_isFlag(p, PILOT_DEAD) || pilot_isFlag( p, PILOT_HIDE ))
1448 if (shooter->
faction == FACTION_PLAYER) {
1450 p->player_damage += dmg / (p->shield_max + p->armour_max);
1453 if ((p->player_damage > PILOT_HOSTILE_THRESHOLD) ||
1454 (shooter->
target==p->id)) {
1474 int x, y, r, x1, y1, x2, y2;
1487 x = round(w->solid.pos.x);
1488 y = round(w->solid.pos.y);
1496 if (!outfit_isProp(w->outfit,OUTFIT_PROP_WEAP_MISS_SHIPS)) {
1505 if (pilot_isFlag(p, PILOT_DELETE))
1508 if (!outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_FRIENDLYFIRE )) {
1510 if (w->parent == p->id)
1520 &p->solid, p->ship->polygon, 0., crash ))
1524 damage =
pilot_hit( p, &w->solid, parent, dmg, w->outfit, w->lua_mem, 1 );
1531 if (!outfit_isProp(w->outfit,OUTFIT_PROP_WEAP_MISS_ASTEROIDS)) {
1538 if (vec2_dist2( &w->solid.pos, &ast->
pos ) >
1548 if (a->state != ASTEROID_FG)
1551 if (a->polygon->npt!=0) {
1571 if (outfit_isProp( w->outfit, OUTFIT_PROP_WEAP_POINTDEFENSE )) {
1580 if (wchit.
gfx->
tex != NULL) {
1585 n = wchit.
gfx->
tex->
sx * w->sy + w->sx;
1617 double damage, radius;
1623 damage = w->dam_mod * w->strength * odmg->
damage;
1625 dmg.
damage =
MAX( 0., damage * (1.-w->dam_as_dis_mod) );
1628 dmg.
disable =
MAX( 0., w->dam_mod * w->strength * odmg->
disable + damage * w->dam_as_dis_mod );
1634 w->solid.pos.x, w->solid.pos.y,
1635 w->solid.vel.x, w->solid.vel.y );
1644 if (hit->type==TARGET_PILOT) {
1645 Pilot *ptarget = hit->u.plt;
1650 double realdmg =
pilot_hit( ptarget, &w->
solid, parent, &dmg, w->outfit, w->lua_mem, 1 );
1655 if (ptarget->
shield > 0.)
1662 pilot_isPlayer(ptarget) ? SPFX_LAYER_FRONT : SPFX_LAYER_MIDDLE );
1664 else if (hit->type==TARGET_ASTEROID) {
1673 else if (hit->type==TARGET_WEAPON) {
1674 Weapon *wpn = hit->u.wpn;
1678 (wpn->
layer==WEAPON_LAYER_FG) ? SPFX_LAYER_FRONT : SPFX_LAYER_MIDDLE );
1696 if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_ARMOUR))
1699 else if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_BLOWUP_SHIELD))
1705 spfx_add( spfx, w->solid.pos.x, w->solid.pos.y,
1706 w->solid.vel.x, w->solid.vel.y,
1707 (w->layer==WEAPON_LAYER_FG) ? SPFX_LAYER_FRONT : SPFX_LAYER_MIDDLE );
1719 if (w->outfit->lua_onmiss != LUA_NOREF) {
1722 lua_rawgeti(naevL, LUA_REGISTRYINDEX, w->lua_mem);
1723 nlua_setenv(naevL, w->outfit->lua_env,
"mem");
1726 lua_rawgeti(naevL, LUA_REGISTRYINDEX, w->outfit->lua_onmiss);
1731 if (nlua_pcall( w->outfit->lua_env, 4, 0 )) {
1732 WARN( _(
"Outfit '%s' -> '%s':\n%s"), w->outfit->name,
"onmiss", lua_tostring(naevL,-1) );
1738 if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_MISS_EXPLODE)) {
1739 double damage, radius;
1745 damage = w->dam_mod * w->strength * odmg->
damage;
1747 dmg.
damage =
MAX( 0., damage * (1.-w->dam_as_dis_mod) );
1750 dmg.
disable =
MAX( 0., w->dam_mod * w->strength * odmg->
disable + damage * w->dam_as_dis_mod );
1768 double damage_armour;
1769 double absorb = 1. -
CLAMP( 0., 1., w->outfit->u.lau.dmg_absorb - dmg->
penetration );
1772 w->armour -= damage_armour + dmg->
disable;
1792 double damage, firerate, mod;
1799 if (w->outfit->type == OUTFIT_TYPE_TURRET_BEAM)
1804 damage = odmg->
damage * mod;
1805 dmg.
damage =
MAX( 0., damage * (1.-w->dam_as_dis_mod) );
1810 if (hit->type==TARGET_PILOT) {
1811 Pilot *p = hit->u.plt;
1814 double realdmg =
pilot_hit( p, &w->solid, parent, &dmg, w->outfit, w->lua_mem, 1 );
1817 if (w->timer2 <= 0.) {
1820 WeaponLayer spfx_layer = (w->layer==WEAPON_LAYER_FG) ? SPFX_LAYER_FRONT : SPFX_LAYER_MIDDLE;
1829 spfx_add( spfx, hit->pos[0].
x, hit->pos[0].
y,
1830 VX(p->solid.vel), VY(p->solid.vel), spfx_layer );
1831 spfx_add( spfx, hit->pos[1].
x, hit->pos[1].
y,
1832 VX(p->solid.vel), VY(p->solid.vel), spfx_layer );
1839 else if (hit->type==TARGET_ASTEROID) {
1845 if (w->timer2 <= 0.) {
1849 spfx_add( spfx, hit->pos[0].
x, hit->pos[0].
y,
1850 VX(a->sol.vel), VY(a->sol.vel), SPFX_LAYER_MIDDLE );
1851 spfx_add( spfx, hit->pos[1].
x, hit->pos[1].
y,
1852 VX(a->sol.vel), VY(a->sol.vel), SPFX_LAYER_MIDDLE );
1856 else if (hit->type==TARGET_WEAPON) {
1857 Weapon *wpn = hit->u.wpn;
1861 if (w->timer2 <= 0.) {
1864 WeaponLayer spfx_layer = (w->layer==WEAPON_LAYER_FG) ? SPFX_LAYER_FRONT : SPFX_LAYER_MIDDLE;
1867 spfx_add( spfx, hit->pos[0].
x, hit->pos[0].
y,
1869 spfx_add( spfx, hit->pos[1].
x, hit->pos[1].
y,
1892 else if ((o->
type==OUTFIT_TYPE_LAUNCHER) && (o->
u.
lau.
ai > 0)) {
1894 const vec2 *target_pos;
1895 double x, y, ang, off;
1896 switch (target->type) {
1900 if (pilot_target==NULL)
1902 target_pos = &pilot_target->
solid.
pos;
1906 case TARGET_ASTEROID:
1910 target_pos = &ast->
sol.
pos;
1927 x = target_pos->
x - pos->
x;
1928 y = target_pos->
y - pos->
y;
1929 ang = ANGLE( x, y );
1930 off = angle_diff( ang, dir );
1938 double off = angle_diff( rdir, dir );
1939 if (
FABS(off) <= swivel)
1949 const Target *target,
const vec2 *pos,
const vec2 *vel,
double dir,
double time )
1951 const Pilot *pilot_target = NULL;
1952 const vec2 *target_pos, *target_vel;
1953 double rx, ry, x, y, t, lead, rdir;
1955 switch (target->type) {
1957 pilot_target =
pilot_get( target->u.id );
1958 if (pilot_target==NULL)
1960 target_pos = &pilot_target->
solid.
pos;
1961 target_vel = &pilot_target->
solid.
vel;
1964 case TARGET_ASTEROID:
1968 target_pos = &ast->
sol.
pos;
1969 target_vel = &ast->
sol.
vel;
1989 rx = target_pos->
x - pos->
x;
1990 ry = target_pos->
y - pos->
y;
1997 double t_parent = t;
2003 x = (target_pos->
x + target_vel->
x*t) - (pos->
x + vel->
x*t_parent);
2004 y = (target_pos->
y + target_vel->
y*t) - (pos->
y + vel->
y*t_parent);
2007 if (pilot_target != NULL) {
2012 x = lead * x + (1.-lead) * rx;
2013 y = lead * y + (1.-lead) * ry;
2025 double tt, ddir, acc, pxv, ang, dvx, dvy;
2029 dvx = lead * (target_vel->
x - vel->
x);
2030 dvy = lead * (target_vel->
y - vel->
y);
2034 pxv = rx*dvy - ry*dvx;
2035 ang = atan2( pxv, rx*dvx+ry*dvy );
2036 if (fabs(ang + M_PI) < fabs(ang))
2038 else if (fabs(ang - M_PI) < fabs(ang))
2046 if (fabs(ang) > 1e-7) {
2048 for (
int i=0; i<niter; i++) {
2056 if (tt < 0. || fabs(
d) < 5.)
2060 rdir = rdir -
d/dtdd;
2081 const Target *target,
const vec2 *pos,
const vec2 *vel,
double dir,
double time )
2094 off = angle_diff( rdir, dir );
2095 if (
FABS(off) > swivel) {
2097 rdir = dir - swivel;
2099 rdir = dir + swivel;
2115 double rx, ry, rdir, off;
2117 rx = target_pos->
x - pos->
x;
2118 ry = target_pos->
y - pos->
y;
2119 rdir = ANGLE(rx,ry);
2122 off = angle_diff( rdir, dir );
2123 if (
FABS(off) > swivel) {
2125 rdir = dir - swivel;
2127 rdir = dir + swivel;
2147 double vmin,
double acc,
double *tt )
2149 double l, dxv, dxp, ct,
st,
d;
2152 ct = cos(rdir);
st = sin(rdir);
2155 dxv = ct*dvy -
st*dvx;
2156 dxp = ct*ry -
st*rx;
2161 d = .5*acc*(*tt)*(*tt) + vmin*(*tt);
2180 double dir,
const vec2* pos,
const vec2* vel,
const Pilot* parent,
double time,
int aim )
2183 double mass, rdir, acc, m;
2189 if (pilot_isPlayer(parent) && (SDL_ShowCursor(SDL_QUERY)==SDL_ENABLE)) {
2206 if (outfit->
type == OUTFIT_TYPE_TURRET_BOLT) {
2217 w->dam_as_dis_mod =
CLAMP( 0., 1., w->dam_as_dis_mod );
2220 rdir += RNG_2SIGMA() * acc;
2223 else if (rdir >= 2.*M_PI)
2231 vec2_cadd( &v, m*cos(rdir), m*sin(rdir));
2234 solid_init( &w->solid, mass, rdir, pos, &v, SOLID_UPDATE_EULER );
2236 w->solid.pos.x, w->solid.pos.y,
2237 w->solid.vel.x, w->solid.vel.y );
2241 if (gfx->
tex != NULL)
2259 double dir,
const vec2* pos,
const vec2* vel,
const Pilot* parent,
double time,
int aim )
2263 double mass, rdir, m;
2269 if (pilot_isPlayer(parent) && (SDL_ShowCursor(SDL_QUERY)==SDL_ENABLE)) {
2285 while (rdir >= 2.*M_PI)
2296 vec2_cadd( &v, m * cos(rdir), m * sin(rdir) );
2297 w->real_vel = VMOD(v);
2300 mass = w->outfit->u.lau.ammo_mass;
2302 solid_init( &w->solid, mass, rdir, pos, &v, SOLID_UPDATE_EULER );
2303 if (w->outfit->u.lau.accel > 0.) {
2306 w->solid.speed_max = w->outfit->u.lau.speed_max;
2307 if (w->outfit->u.lau.speed > 0.)
2308 w->solid.speed_max = -1;
2312 if (w->outfit->u.lau.armour > 0.) {
2313 w->armour = w->outfit->u.lau.armour;
2314 weapon_setFlag( w, WEAPON_FLAG_HITTABLE );
2318 if (w->outfit->u.lau.ai != AMMO_AI_UNGUIDED) {
2321 w->status = (w->timer2 > 0.) ? WEAPON_STATUS_LOCKING : WEAPON_STATUS_OK;
2327 if (w->target.type == TARGET_PILOT) {
2329 if (pilot_target != NULL)
2334 w->status = WEAPON_STATUS_OK;
2338 w->solid.pos.x, w->solid.pos.y,
2339 w->solid.vel.x, w->solid.vel.y );
2343 if (gfx->
tex != NULL)
2347 if (w->outfit->u.lau.trail_spec != NULL)
2368 double T,
double dir,
const vec2* pos,
const vec2* vel,
2369 const Pilot* parent,
const Target *target,
double time,
int aim )
2372 const Outfit *outfit = ((ref==NULL) && (po!=NULL)) ? po->
outfit : ref;
2375 memset( w, 0,
sizeof(
Weapon) );
2377 w->layer = (parent->
id==PLAYER_ID) ? WEAPON_LAYER_FG : WEAPON_LAYER_BG;
2380 w->dam_as_dis_mod = 0.;
2382 w->parent = parent->
id;
2383 memcpy( &w->target, target,
sizeof(
Target) );
2384 w->lua_mem = LUA_NOREF;
2385 if (po != NULL && po->
lua_mem != LUA_NOREF) {
2386 lua_rawgeti(naevL, LUA_REGISTRYINDEX, po->
lua_mem);
2387 w->lua_mem = luaL_ref( naevL, LUA_REGISTRYINDEX );
2391 w->strength_base = 1.;
2394 if (outfit_isProp(outfit,OUTFIT_PROP_WEAP_ONLYHITTARGET))
2395 weapon_setFlag(w,WEAPON_FLAG_ONLYHITTARGET);
2398 if (!(
outfit_isBeam(w->outfit)) && (w->target.type==TARGET_PILOT)) {
2400 if (pilot_target != NULL)
2404 switch (outfit->
type) {
2407 case OUTFIT_TYPE_BOLT:
2408 case OUTFIT_TYPE_TURRET_BOLT:
2413 case OUTFIT_TYPE_BEAM:
2414 case OUTFIT_TYPE_TURRET_BEAM:
2416 if (outfit->
type==OUTFIT_TYPE_TURRET_BEAM) {
2421 weapon_setFlag(w, WEAPON_FLAG_AIM);
2422 switch (w->target.type) {
2427 if (w->parent != w->target.u.id) {
2429 rdir = vec2_angle(pos, &pilot_target->
solid.
pos);
2433 case TARGET_ASTEROID:
2435 ast = &field->
asteroids[ w->target.u.ast.asteroid ];
2436 rdir = vec2_angle(pos, &ast->
sol.
pos);
2441 if (wtarget != NULL)
2442 rdir = vec2_angle( pos, &wtarget->
solid.
pos );
2446 else if (pilot_isPlayer(parent) && (SDL_ShowCursor(SDL_QUERY)==SDL_ENABLE)) {
2449 rdir = vec2_angle( pos, &tv );
2455 else if (rdir >= 2.*M_PI)
2459 solid_init( &w->solid, mass, rdir, pos, vel, SOLID_UPDATE_EULER );
2463 w->solid.pos.x, w->solid.pos.y,
2464 w->solid.vel.x, w->solid.vel.y );
2466 if (outfit->
type == OUTFIT_TYPE_BEAM) {
2474 w->dam_as_dis_mod =
CLAMP( 0., 1., w->dam_as_dis_mod );
2479 case OUTFIT_TYPE_LAUNCHER:
2480 case OUTFIT_TYPE_TURRET_LAUNCHER:
2486 WARN(_(
"Weapon of type '%s' has no create implemented yet!"),
2488 solid_init( &w->solid, 1., dir, pos, vel, SOLID_UPDATE_EULER );
2512 double dir,
const vec2* pos,
const vec2* vel,
2513 const Pilot *parent,
const Target *target,
double time,
int aim )
2522 ERR(_(
"Trying to create a Weapon from a non-Weapon type Outfit"));
2528 weapon_create( w, po, ref, T, dir, pos, vel, parent, target, time, aim );
2559 case TARGET_ASTEROID:
2585 double dir,
const vec2* pos,
const vec2* vel,
2586 const Pilot *parent,
const Target *target,
int aim )
2591 ERR(_(
"Trying to create a Beam Weapon from a non-beam outfit."));
2596 weapon_create( w, po, NULL, 0., dir, pos, vel, parent, target, 0., aim );
2612 WARN(_(
"Trying to remove beam with ID 0!"));
2620 if (w->id == beam) {
2635 weapon_setFlag( w, WEAPON_FLAG_DESTROYED );
2649 w->solid.pos.x, w->solid.pos.y,
2650 w->solid.vel.x, w->solid.vel.y );
2652 else if (w->target.type==TARGET_PILOT) {
2656 if (pilot_target != NULL) {
2670 luaL_unref( naevL, LUA_REGISTRYINDEX, w->lua_mem );
2673 memset(w, 0,
sizeof(
Weapon));
2715const IntList *weapon_collideQuery(
int x1,
int y1,
int x2,
int y2 )
2721void 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.
void RotatePolygon(CollPoly *rpolygon, CollPoly *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 CollideLinePolygon(const vec2 *ap, double ad, double al, const CollPoly *bt, const vec2 *bp, vec2 crash[2])
Checks to see if a line collides with a polygon.
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 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 CollideCirclePolygon(const vec2 *ap, double ar, const CollPoly *bt, const vec2 *bp, vec2 crash[2])
Checks to see if a circle collides with a polygon.
int CollideSpritePolygon(const CollPoly *at, const vec2 *ap, 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 CollidePolygon(const CollPoly *at, const vec2 *ap, const CollPoly *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_translate(mat4 *m, double x, double y, double z)
Translates a homogenous transformation matrix.
void mat4_scale(mat4 *m, double x, double y, double z)
Scales a homogeneous transformation matrix.
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, const glTexture *t, const 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, 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.
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.
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 int weapon_testCollision(const WeaponCollision *wc, const glTexture *ctex, int csx, int csy, const Solid *csol, const CollPoly *cpol, double cradius, vec2 crash[2])
Tests to see if a weapon collides with a ship.
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).
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 void weapon_hitExplode(Weapon *w, const Damage *dmg, double radius)
A weapon hit something and decided to explode.
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.