22#include "damagetype.h"
32#include "nlua_outfit.h"
33#include "nlua_pilotoutfit.h"
37#include "pilot_ship.h"
39#include "player_autonav.h"
44#define PILOT_SIZE_MIN 128
56static int qt_init = 0;
59static int qt_max_elem = 2;
60static int qt_depth = 5;
73 int faction,
const double dir,
const vec2 *pos,
74 const vec2 *vel,
const PilotFlags flags,
75 unsigned int dockpilot,
int dockslot );
88static void pilot_addQuadtree(
const Pilot *p,
int i );
101static int pilot_cmp(
const void *ptr1,
const void *ptr2 )
103 const Pilot *p1, *p2;
104 p1 = *( (
const Pilot **)ptr1 );
105 p2 = *( (
const Pilot **)ptr2 );
106 return p1->
id - p2->
id;
117 const Pilot pid = { .id =
id };
118 const Pilot *pidptr = &pid;
213 else if ( mode == 1 ) {
273 if ( pilot_isFlag( p, PILOT_DELETE ) || pilot_isFlag( p, PILOT_DEAD ) )
277 if ( pilot_isFlag( p, PILOT_HIDE ) || pilot_isFlag( p, PILOT_INVISIBLE ) )
296 if ( pilot_isDisabled( target ) )
300 if ( pilot_isFlag( target, PILOT_INVINCIBLE ) )
304 if ( pilot_isFlag( target, PILOT_LANDING ) ||
305 pilot_isFlag( target, PILOT_TAKEOFF ) ||
306 pilot_isFlag( target, PILOT_NONTARGETABLE ) )
343 td = vec2_dist2( &
pilot_stack[i]->solid.pos, &p->solid.pos );
344 if ( !tp || ( td <
d ) ) {
362 double target_mass_UB )
373 if (
pilot_stack[i]->solid.mass < target_mass_LB ||
378 td = vec2_dist2( &
pilot_stack[i]->solid.pos, &p->solid.pos );
379 if ( !tp || ( td <
d ) ) {
402 double health_factor,
403 double damage_factor,
404 double range_factor )
407 double current_heuristic_value = 10e3;
417 temp = range_factor * vec2_dist2( &target->
solid.
pos, &p->solid.pos ) +
422 if ( ( tp == 0 ) || ( temp < current_heuristic_value ) ) {
423 current_heuristic_value = temp;
453 double relpower, ppower;
463 double dx, dy, td, curpower;
479 p->solid.pos.x - 2 * p->solid.vel.x;
481 p->solid.pos.y - 2 * p->solid.vel.y;
482 td = sqrt(
pow2( dx ) +
pow2( dy ) );
497 if ( ppower >= curpower )
500 if ( relpower < curpower ) {
531 if ( !disabled && pilot_isPlayer( p ) &&
536 if ( !disabled && pilot_isDisabled(
pilot_stack[i] ) )
546 if ( ( ( *tp == NULL ) || ( td <
d ) ) ) {
565 double y,
int disabled )
588 double a = ang + M_PI;
600 if ( !disabled && pilot_isPlayer( p ) &&
605 if ( !disabled && pilot_isDisabled(
pilot_stack[i] ) )
620 ta = atan2( p->solid.pos.y -
pilot_stack[i]->solid.pos.y,
622 if (
ABS( angle_diff( ang, ta ) ) <
ABS( angle_diff( ang, a ) ) ) {
642 const Pilot pid = { .id =
id };
643 const Pilot *pidptr = &pid;
647 if ( ( pp == NULL ) || ( pilot_isFlag( *pp, PILOT_DELETE ) ) )
660 if ( p->target == p->id )
666 if ( pilot_isFlag( t, PILOT_DELETE ) ) {
682 p->solid.accel = p->accel * accel;
690 p->solid.dir_vel = p->turn * turn;
702 ( pilot_isFlag( p, PILOT_HOSTILE ) ||
703 areEnemiesSystem( FACTION_PLAYER, p->faction,
cur_system ) ) )
730 if ( pilot_isFlag( p, PILOT_FRIENDLY ) ||
731 ( areAlliesSystem( FACTION_PLAYER, p->faction,
cur_system ) &&
732 !pilot_isFlag( p, PILOT_HOSTILE ) ) )
743 if ( pilot_isWithPlayer( p ) ) {
746 else if ( pilot_isFlag( target, PILOT_HOSTILE ) )
748 }
else if ( pilot_isWithPlayer( target ) ) {
751 else if ( pilot_isFlag( p, PILOT_HOSTILE ) )
765 if ( pilot_isWithPlayer( p ) ) {
768 else if ( pilot_isFlag( target, PILOT_FRIENDLY ) )
770 else if ( pilot_isFlag( target, PILOT_BRIBED ) )
773 if ( pilot_isWithPlayer( target ) ) {
776 else if ( pilot_isFlag( p, PILOT_FRIENDLY ) )
778 else if ( pilot_isFlag( p, PILOT_BRIBED ) )
795 if ( ( p->dockpilot != 0 ) && ( p->dockslot != -1 ) ) {
797 if ( dockpilot != NULL )
798 return dockpilot->
outfits[p->dockslot];
805const IntList *pilot_collideQuery(
int x1,
int y1,
int x2,
int y2 )
811void pilot_collideQueryIL(
IntList *il,
int x1,
int y1,
int x2,
int y2 )
829 double diff = angle_diff( p->solid.dir, dir );
830 double turn =
CLAMP( -1., 1., diff / ( p->turn * dt ) );
840 if ( p->stats.misc_reverse_thrust ) {
841 double diff, btime, ftime, vel, t;
842 vel =
MIN( VMOD( p->solid.vel ), p->speed );
846 diff = angle_diff( p->solid.dir, VANGLE( p->solid.vel ) + M_PI );
847 btime =
ABS( diff ) / p->turn + t;
850 diff = angle_diff( p->solid.dir, VANGLE( p->solid.vel ) );
851 ftime =
ABS( diff ) / p->turn + t / PILOT_REVERSE_THRUST;
864 double vel =
MIN(
MIN( VMOD( p->solid.vel ), p->speed ),
865 solid_maxspeed( &p->solid, p->speed, p->accel ) );
866 double accel = p->accel;
867 double t = vel / accel;
869 t /= PILOT_REVERSE_THRUST;
871 return vel * ( t + dt ) -
872 0.5 * PILOT_REVERSE_THRUST * accel *
pow2( t - dt );
875 *flytime = t + M_PI / p->turn + dt;
876 return vel * ( *flytime ) - 0.5 * accel *
pow2( t - dt );
888 double dir, accel, diff;
889 int isstopped = pilot_isStopped( p );
895 dir = VANGLE( p->solid.vel );
897 -
MIN( PILOT_REVERSE_THRUST, VMOD( p->solid.vel ) / ( p->accel * dt ) );
899 dir = VANGLE( p->solid.vel ) + M_PI;
900 accel =
MIN( 1., VMOD( p->solid.vel ) / ( p->accel * dt ) );
904 if (
ABS( diff ) < MIN_DIR_ERR )
920 double heat_capacity, heat_mean;
923 if ( dochecks && !pilot_isStopped( p ) ) {
924 pilot_setFlag( p, PILOT_BRAKING );
925 pilot_setFlag( p, PILOT_COOLDOWN_BRAKE );
928 pilot_rmFlag( p, PILOT_BRAKING );
929 pilot_rmFlag( p, PILOT_COOLDOWN_BRAKE );
932 if ( p->id == PLAYER_ID )
940 pilotoutfit_modified = 0;
945 heat_capacity = p->heat_C;
946 heat_mean = p->heat_T * p->heat_C;
947 for (
int i = 0; i <
array_size( p->outfits ); i++ ) {
950 heat_capacity += p->outfits[i]->heat_C;
955 heat_mean =
MAX( heat_mean, CONST_SPACE_STAR_TEMP );
957 heat_mean /= heat_capacity;
970 ( 5. + sqrt( p->base_mass ) / 2. ) *
971 ( 1. + pow(
MAX( heat_mean / CONST_SPACE_STAR_TEMP - 1., 0. ), 1.25 ) );
972 p->ctimer = p->cdelay * p->stats.cooldown_time;
973 p->heat_start = p->heat_T;
974 pilot_setFlag( p, PILOT_COOLDOWN );
988 if ( pilot_isFlag( p, PILOT_COOLDOWN_BRAKE ) ) {
989 pilot_rmFlag( p, PILOT_COOLDOWN_BRAKE );
994 if ( p->id == PLAYER_ID ) {
995 if ( p->ctimer < 0. )
998 if ( reason != NULL )
1006 pilot_rmFlag( p, PILOT_COOLDOWN );
1009 if ( p->ctimer < 0. ) {
1029 vec2 tv, approach_vector, relative_location, orthoradial_vector;
1032 double radial_speed;
1033 double orthoradial_speed;
1036 dist = vec2_dist( &p->solid.pos, pos );
1054 vec2_cset( &approach_vector, VX( p->solid.vel ) - VX( *vel ),
1055 VY( p->solid.vel ) - VY( *vel ) );
1056 vec2_cset( &relative_location, VX( *pos ) - VX( p->solid.pos ),
1057 VY( *pos ) - VY( p->solid.pos ) );
1058 vec2_cset( &orthoradial_vector, VY( p->solid.pos ) - VY( *pos ),
1059 VX( *pos ) - VX( p->solid.pos ) );
1061 radial_speed = vec2_dot( &approach_vector, &relative_location );
1062 radial_speed = radial_speed / VMOD( relative_location );
1064 orthoradial_speed = vec2_dot( &approach_vector, &orthoradial_vector );
1065 orthoradial_speed = orthoradial_speed / VMOD( relative_location );
1071 if ( ( ( speed * speed -
1072 VMOD( approach_vector ) * VMOD( approach_vector ) ) != 0 ) &&
1073 ( speed * speed - orthoradial_speed * orthoradial_speed ) > 0 )
1075 ( sqrt( speed * speed - orthoradial_speed * orthoradial_speed ) -
1077 ( speed * speed - VMOD( approach_vector ) * VMOD( approach_vector ) );
1084 ( sqrt( speed * speed - orthoradial_speed * orthoradial_speed ) +
1086 ( speed * speed - VMOD( approach_vector ) * VMOD( approach_vector ) );
1093 x = pos->
x + vel->
x * t - ( p->solid.pos.x + p->solid.vel.x * t );
1094 y = pos->
y + vel->
y * t - ( p->solid.pos.y + p->solid.vel.y * t );
1095 vec2_cset( &tv, x, y );
1097 return VANGLE( tv );
1108 if ( pilot_isWithPlayer( p ) )
1110 pilot_setFlag( p, PILOT_HOSTILE );
1112 pilot_rmFlag( p, PILOT_BRIBED );
1123 if ( pilot_isDisabled( p ) )
1129 else if ( pilot_isFlag( p, PILOT_BRIBED ) )
1131 return faction_reputationColourCharSystem( p->faction,
cur_system );
1139 free( p->comm_msg );
1140 p->comm_msg = strdup( s );
1186 if ( ( msg != NULL ) && ( msg[0] !=
'\0' ) )
1190 if ( attacker == NULL )
1199 if ( !pilot_isFlag( p, PILOT_DISTRESSED ) ) {
1203 if ( spob_hasService( spb, SPOB_SERVICE_INHABITED ) &&
1218 if ( ( pi->
ai == NULL ) || ( pi->
id == p->id ) ||
1219 ( pilot_isFlag( pi, PILOT_DEAD ) ) ||
1220 ( pilot_isFlag( pi, PILOT_DELETE ) ) )
1228 d = vec2_dist2( &p->solid.pos, &pi->
solid.
pos );
1237 if ( !pilot_isFlag( p, PILOT_DISTRESSED ) &&
1243 if ( !pilot_isFlag( p, PILOT_DISTRESSED ) ) {
1246 if ( r && ( attacker != NULL ) && ( pilot_isWithPlayer( attacker ) ) ) {
1247 if ( p->ai == NULL )
1248 WARN( _(
"Pilot '%s' does not have an AI!" ), p->name );
1251 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, p->lua_mem );
1252 lua_getfield(
naevL, -1,
"distress_hit" );
1253 if ( lua_isnil(
naevL, -1 ) )
1254 hit =
MAX( 0., pow( p->ship->points, 0.37 ) - 2. );
1255 else if ( lua_isnumber(
naevL, -1 ) )
1256 hit = lua_tonumber(
naevL, -1 );
1258 WARN( _(
"Pilot '%s' has non-number mem.distress_hit!" ),
1262 lua_pop(
naevL, 2 );
1268 pilot_setFlag( p, PILOT_DISTRESSED );
1282 if ( pilot_isFlag( p, PILOT_HOSTILE ) )
1283 pilot_rmFlag( p, PILOT_HOSTILE );
1286 if (
areEnemies( FACTION_PLAYER, p->faction ) )
1287 pilot_setFlag( p, PILOT_BRIBED );
1298 pilot_setFlag( p, PILOT_FRIENDLY );
1308 pilot_rmFlag( p, PILOT_FRIENDLY );
1319 return p->fuel / p->fuel_consumption;
1330 const glColour *col;
1334 else if ( pilot_isDisabled( p ) || pilot_isFlag( p, PILOT_DEAD ) )
1355 if ( p->target ==
id )
1367 p->nav_asteroid = -1;
1388 double damage_shield, damage_armour, disable, knockback, dam_mod, ddmg, ddis,
1389 absorb, dmod, start;
1390 double tdshield, tdarmour;
1393 if ( pilot_isFlag( p, PILOT_INVINCIBLE ) || pilot_isFlag( p, PILOT_HIDE ) ||
1394 ( ( pshooter != NULL ) && pilot_isWithPlayer( pshooter ) &&
1395 pilot_isFlag( p, PILOT_INVINC_PLAYER ) ) )
1402 shooter = ( pshooter == NULL ) ? 0 : pshooter->
id;
1414 if ( !pilot_isFlag( p, PILOT_DEAD ) && ( p->dtimer_accum > 0. ) )
1415 p->dtimer_accum -=
MIN( pow( disable, 0.8 ), p->dtimer_accum );
1419 if ( pilot_isFlag( p, PILOT_NODISABLE ) ) {
1420 damage_armour += disable * absorb;
1430 if ( p->shield - damage_shield > 0. ) {
1432 ddmg = damage_shield;
1433 p->shield -= damage_shield;
1434 dam_mod = damage_shield / p->shield_max;
1448 ( 0.5 + ( 0.5 - ( ( start + p->shield ) / p->shield_max ) / 4. ) );
1452 tdshield = damage_shield;
1457 else if ( p->shield > 0. ) {
1459 dmod = ( 1. - p->shield / damage_shield );
1460 ddmg = p->shield + dmod * damage_armour;
1461 tdshield = p->shield;
1465 ddis = disable * ( 1. - dmod ) *
1466 ( 0.5 + ( 0.5 - ( start / p->shield_max / 4. ) ) );
1471 tdarmour = dmod * damage_armour;
1472 p->armour -= tdarmour;
1473 p->stress += dmod * disable;
1474 dam_mod = ( damage_shield + damage_armour ) /
1475 ( ( p->shield_max + p->armour_max ) / 2. );
1479 p->stimer = 5. * p->stats.shielddown_mod;
1486 else if ( p->armour > 0. ) {
1487 ddmg = damage_armour;
1490 p->armour -= damage_armour;
1496 p->stimer = 5. * p->stats.shielddown_mod;
1505 if ( ( p->armour <= 0. ) && pilot_isFlag( p, PILOT_NODEATH ) ) {
1511 if ( pilot_isFlag( p, PILOT_DISABLED_PERM ) )
1512 p->stress = p->armour;
1515 if ( p->shield <= 0. ) {
1516 if ( p->id == PLAYER_ID ) {
1517 double spfx_mod = tdarmour / p->armour_max;
1524 if ( p->id == PLAYER_ID ) {
1525 player.dmg_taken_shield += tdshield;
1526 player.dmg_taken_armour += tdarmour;
1527 player.ps.dmg_taken_shield += tdshield;
1528 player.ps.dmg_taken_armour += tdarmour;
1531 else if ( ( pshooter != NULL ) && pilot_isWithPlayer( pshooter ) ) {
1532 player.dmg_done_shield += tdshield;
1533 player.dmg_done_armour += tdarmour;
1534 player.ps.dmg_done_shield += tdshield;
1535 player.ps.dmg_done_armour += tdarmour;
1544 ( w->vel.x * ( dam_mod / 9. + w->mass / p->solid.mass / 6. ) ),
1546 ( w->vel.y * ( dam_mod / 9. + w->mass / p->solid.mass / 6. ) ) );
1549 if ( ( outfit != NULL ) && ( outfit->
lua_onimpact != LUA_NOREF ) ) {
1550 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, lua_mem );
1560 if ( nlua_pcall( outfit->
lua_env, 5, 0 ) ) {
1561 WARN( _(
"Pilot '%s''s outfit '%s' -> '%s':\n%s" ), p->name,
1562 outfit->
name,
"onimpact", lua_tostring(
naevL, -1 ) );
1563 lua_pop(
naevL, 1 );
1575 if ( p->armour <= 0. ) {
1578 if ( !pilot_isFlag( p, PILOT_DEAD ) ) {
1582 if ( ( p->armour <= 0. ) && ( pshooter != NULL ) &&
1583 pilot_isWithPlayer( pshooter ) ) {
1589 player.ships_destroyed[p->ship->class]++;
1590 player.ps.ships_destroyed[p->ship->class]++;
1607 if ( ( !pilot_isFlag( p, PILOT_DISABLED ) ) &&
1608 ( !pilot_isFlag( p, PILOT_NODISABLE ) || ( p->armour <= 0. ) ) &&
1609 ( p->armour <= p->stress ) ) {
1613 if ( pilot_isFlag( p, PILOT_COOLDOWN ) )
1617 pilot_rmFlag( p, PILOT_COOLDOWN_BRAKE );
1618 pilot_rmFlag( p, PILOT_BRAKING );
1619 pilot_rmFlag( p, PILOT_STEALTH );
1622 pilot_rmFlag( p, PILOT_HYP_PREP );
1623 pilot_rmFlag( p, PILOT_HYP_BEGIN );
1624 pilot_rmFlag( p, PILOT_HYP_BRAKE );
1625 pilot_rmFlag( p, PILOT_HYPERSPACE );
1628 if ( p->presence > 0 ) {
1637 p->dtimer = 8. * pow( p->solid.mass, 1. / 3. );
1638 p->dtimer_accum = 0.;
1641 pilotoutfit_modified = 0;
1645 pilot_setFlag( p, PILOT_DISABLED );
1646 if ( pilot_isPlayer( p ) )
1650 if ( shooter > 0 ) {
1651 hparam.
type = HOOK_PARAM_PILOT;
1652 hparam.
u.
lp = shooter;
1654 hparam.
type = HOOK_PARAM_NIL;
1656 pilot_runHookParam( p, PILOT_HOOK_DISABLE, &hparam,
1658 }
else if ( pilot_isFlag( p, PILOT_DISABLED ) &&
1661 pilot_rmFlag( p, PILOT_DISABLED );
1663 p, PILOT_DISABLED_PERM );
1664 pilot_rmFlag( p, PILOT_BOARDING );
1667 p->dtimer_accum = 0.;
1673 if ( pilot_isPlayer( p ) ) {
1676 _(
"You have recovered control of your ship!" ) );
1691 if ( pilot_isFlag( p, PILOT_DEAD ) )
1695 if ( p->id == PLAYER_ID ) {
1696 pilot_setFlag( p, PILOT_DISABLED );
1700 p->ptimer =
MIN( 1. + sqrt( p->armour_max * p->shield_max ) / 650.,
1701 3 + pow( p->armour_max * p->shield_max, 0.4 ) / 500 );
1705 pilot_rmFlag( p, PILOT_HYP_PREP );
1706 pilot_rmFlag( p, PILOT_HYP_BEGIN );
1707 pilot_rmFlag( p, PILOT_HYP_BRAKE );
1708 pilot_rmFlag( p, PILOT_HYPERSPACE );
1714 for (
int i = 0; i <
array_size( p->outfits ); i++ ) {
1716 po->
state = PILOT_OUTFIT_OFF;
1717 po->
flags &= ~( PILOTOUTFIT_DYNAMIC_FLAGS | PILOTOUTFIT_ISON );
1723 hparam.
type = HOOK_PARAM_PILOT;
1724 hparam.
u.
lp = killer;
1726 hparam.
type = HOOK_PARAM_NIL;
1727 pilot_runHookParam( p, PILOT_HOOK_DEATH, &hparam, 1 );
1730 if ( p->armour > 0. )
1733 if ( p->parent == PLAYER_ID )
1734 player_message( _(
"#rShip under command '%s' was destroyed!#0" ),
1737 pilot_setFlag( p, PILOT_DEAD );
1743 for (
int i = 0; i <
array_size( p->escorts ); i++ ) {
1746 if ( ( pe == NULL ) || pilot_isFlag( pe, PILOT_DEAD ) ||
1747 pilot_isFlag( pe, PILOT_HIDE ) )
1750 if ( !pilot_isFlag( pe, PILOT_CARRIED ) )
1754 pilot_setFlag( pe, PILOT_CARRIER_DIED );
1768 const Pilot *parent )
1776 rad2 = radius * radius;
1781 qr = ceil( radius );
1782 qt = pilot_collideQuery( qx - qr, qy - qr, qx + qr, qy + qr );
1783 for (
int i = 0; i < il_size( qt ); i++ ) {
1785 double rx, ry, dist;
1788 rx = p->solid.pos.x - x;
1789 ry = p->solid.pos.y - y;
1792 dist -=
pow2( p->ship->size );
1793 dist =
MAX( 0, dist );
1800 ddmg.
damage = dmg->
damage * ( 1. - sqrt( dist / rad2 ) );
1808 pilot_hit( p, &s, parent, &ddmg, NULL, LUA_NOREF, 1 );
1811 if ( p->id == PILOT_PLAYER )
1828 glColour
c = { 1., 1., 1., 1. };
1831 if ( !pilot_isPlayer( p ) && pilot_isFlag( p, PILOT_STEALTH ) )
1835 p->tilt, p->r, p->tsx, p->tsy, &
c, L );
1853 double timeleft, elapsed;
1860 p->solid.pos.y - h / 2. );
1863 for (
int i = 0; i <
array_size( p->effects ); i++ ) {
1865 const Effect *eiter = &p->effects[i];
1866 if ( eiter->
data->program == 0 )
1871 timeleft = e->
timer;
1873 }
else if ( eiter->
data == e->
data ) {
1884 mat4 projection, tex_mat;
1888 if ( ed->
flags & EFFECT_VERTEX ) {
1889 double s = ceil( 2.0 * p->ship->size /
gl_screen.scale );
1890 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.fbo[2] );
1891 glEnable( GL_SCISSOR_TEST );
1892 glScissor( 0, 0, s, s );
1893 glClear( GL_COLOR_BUFFER_BIT );
1894 glDisable( GL_SCISSOR_TEST );
1901 glBindFramebuffer( GL_FRAMEBUFFER, fbo );
1903 glClear( GL_COLOR_BUFFER_BIT );
1905 glUseProgram( ed->program );
1908 if ( ed->
img != NULL ) {
1909 glActiveTexture( GL_TEXTURE1 );
1910 glBindTexture( GL_TEXTURE_2D, ed->
img->
texture );
1911 glUniform1i( ed->u_img, 1 );
1914 glActiveTexture( GL_TEXTURE0 );
1915 glBindTexture( GL_TEXTURE_2D,
gl_screen.fbo_tex[2] );
1916 glUniform1i( ed->u_tex, 0 );
1918 glEnableVertexAttribArray( ed->vertex );
1921 projection =
mat4_ortho( 0., fw, 0, fh, -1., 1. );
1923 gl_uniformMat4( ed->projection, &projection );
1928 gl_uniformMat4( ed->tex_mat, &tex_mat );
1930 glUniform3f( ed->dimensions, SCREEN_W, SCREEN_H, 1. );
1931 glUniform1f( ed->u_timer, timeleft );
1932 glUniform1f( ed->u_elapsed, elapsed );
1933 glUniform1f( ed->u_r, e->
r );
1934 glUniform1f( ed->u_dir, p->solid.dir );
1937 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1940 if ( ed->
img != NULL ) {
1941 glActiveTexture( GL_TEXTURE1 );
1942 glBindTexture( GL_TEXTURE_2D, 0 );
1943 glActiveTexture( GL_TEXTURE0 );
1947 glDisableVertexAttribArray( ed->vertex );
1949 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.current_fbo );
1960 double scale, x, y, w, h, z;
1961 double timeleft, elapsed;
1964 glColour
c = { .r = 1., .g = 1., .b = 1., .a = 1. };
1967 if ( pilot_isFlag( p, PILOT_NORENDER ) )
1975 p->solid.pos.y - h / 2. );
1978 if ( ( x < -w ) || ( x > SCREEN_W + w ) || ( y < -h ) ||
1979 ( y > SCREEN_H + h ) )
1984 if ( pilot_isFlag( p, PILOT_LANDING ) )
1985 scale =
CLAMP( 0., 1., p->ptimer / p->landing_delay );
1986 else if ( pilot_isFlag( p, PILOT_TAKEOFF ) )
1987 scale =
CLAMP( 0., 1., 1. - p->ptimer / p->landing_delay );
1992 for (
int i = 0; i <
array_size( p->effects ); i++ ) {
1994 Effect *eiter = &p->effects[i];
1995 if ( eiter->
data->program == 0 )
2000 timeleft = e->
timer;
2002 }
else if ( eiter->
data == e->
data ) {
2009 if ( !pilot_isPlayer( p ) && pilot_isFlag( p, PILOT_STEALTH ) )
2014 if ( p->ship->gfx_3d != NULL ) {
2020 gl_renderTextureDepthRaw(
2022 x + ( 1. - scale ) * z * w * 0.5,
2023 y + ( 1. - scale ) * z * h * 0.5, w * scale * z, h * scale * z,
2028 p->ship->gfx_space, p->ship->gfx_engine, 1. - p->engine_glow,
2029 p->solid.pos.x, p->solid.pos.y, scale, scale, p->tsx, p->tsy,
2035 mat4 projection, tex_mat;
2039 if ( ed->
flags & EFFECT_VERTEX ) {
2040 double s = ceil( 2.0 * p->ship->size /
gl_screen.scale );
2041 glBindFramebuffer( GL_FRAMEBUFFER,
gl_screen.fbo[2] );
2042 glEnable( GL_SCISSOR_TEST );
2043 glScissor( 0, 0, s, s );
2044 glClear( GL_COLOR_BUFFER_BIT );
2045 glDisable( GL_SCISSOR_TEST );
2055 gl_screen.fbo_depth_tex[2], 0, x + ( 1. - scale ) * z * w * 0.5,
2056 y + ( 1. - scale ) * z * h * 0.5, w * scale * z, h * scale * z, 0,
2060 glUseProgram( ed->program );
2063 if ( ed->
img != NULL ) {
2064 glActiveTexture( GL_TEXTURE1 );
2065 glBindTexture( GL_TEXTURE_2D, ed->
img->
texture );
2066 glUniform1i( ed->u_img, 1 );
2069 glActiveTexture( GL_TEXTURE0 );
2070 glBindTexture( GL_TEXTURE_2D,
gl_screen.fbo_tex[2] );
2071 glUniform1i( ed->u_tex, 0 );
2073 glEnableVertexAttribArray( ed->vertex );
2077 projection = gl_view_matrix;
2078 mat4_translate_scale_xy( &projection, x + ( 1. - scale ) * z * w * 0.5,
2079 y + ( 1. - scale ) * z * h * 0.5,
2080 scale * z * w, scale * z * h );
2081 gl_uniformMat4( ed->projection, &projection );
2086 gl_uniformMat4( ed->tex_mat, &tex_mat );
2088 glUniform3f( ed->dimensions, SCREEN_W, SCREEN_H,
cam_getZoom() );
2089 glUniform1f( ed->u_timer, timeleft );
2090 glUniform1f( ed->u_elapsed, elapsed );
2091 glUniform1f( ed->u_r, e->
r );
2092 glUniform1f( ed->u_dir, p->solid.dir );
2095 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
2098 if ( ed->
img != NULL ) {
2099 glActiveTexture( GL_TEXTURE1 );
2100 glBindTexture( GL_TEXTURE_2D, 0 );
2101 glActiveTexture( GL_TEXTURE0 );
2105 glDisableVertexAttribArray( ed->vertex );
2111 glEnable( GL_DEPTH_TEST );
2112 glDepthMask( GL_FALSE );
2114 for (
int i = 0, g = 0; g <
array_size( p->ship->trail_emitters ); g++ ) {
2116 if ( p->trail[i]->ontop )
2122 glDepthMask( GL_TRUE );
2123 glDisable( GL_DEPTH_TEST );
2127 if ( inbounds && ( p->ship->gfx_3d != NULL ) ) {
2129 y + ( 1. - scale ) * z * h * 0.5, w * scale * z,
2131 glClear( GL_DEPTH_BUFFER_BIT );
2137 if ( inbounds && debug_isFlag( DEBUG_MARK_COLLISION ) ) {
2138 static gl_vbo *poly_vbo = NULL;
2140 const CollPolyView *poly = poly_view( &p->ship->polygon, p->solid.dir );
2142 MIN(
sizeof( data ) / (
sizeof( GLfloat ) * 2 ), (
size_t)poly->
npt );
2143 size_t ndata = n *
sizeof( GLfloat ) * 2;
2144 mat4 projection = gl_view_matrix;
2147 for (
size_t i = 0; i < n; i++ ) {
2148 data[i * 2 + 0] = poly->
x[i];
2149 data[i * 2 + 1] = poly->
y[i];
2153 if ( poly_vbo == NULL )
2159 glUseProgram( shaders.lines.program );
2160 glEnableVertexAttribArray( shaders.lines.vertex );
2166 mat4_translate_scale_xy( &projection, x, y, z, z );
2167 gl_uniformMat4( shaders.lines.projection, &projection );
2170 gl_uniformColour( shaders.lines.colour, &cWhite );
2173 glDrawArrays( GL_LINE_LOOP, 0, n );
2176 glDisableVertexAttribArray( shaders.lines.vertex );
2183 if ( inbounds && debug_isFlag( DEBUG_MARK_EMITTER ) ) {
2184 double dircos, dirsin;
2186 int use_3d = ship_isFlag( p->ship, SHIP_3DTRAILS );
2192 dircos = cos( p->solid.dir );
2193 dirsin = sin( p->solid.dir );
2197 for (
int i = 0; i <
array_size( p->ship->trail_emitters ); i++ ) {
2208 v.x = trail->
pos.v[0] * dircos - trail->
pos.v[1] * dirsin;
2209 v.y = trail->
pos.v[0] * dirsin + trail->
pos.v[1] * dircos +
2220 p->solid.pos.y + v.y );
2241 if ( pilot_isFlag( p, PILOT_NORENDER ) )
2247 playerdead = ( player_isFlag( PLAYER_DESTROYED ) || (
player.p == NULL ) );
2250 if ( !playerdead && pilot_isFlag( p, PILOT_HAILING ) ) {
2252 if ( ico_hail != NULL ) {
2253 int sx = (int)ico_hail->
sx;
2258 p->solid.pos.x + PILOT_SIZE_APPROX * sw / 2. + ico_hail->
sw / 4.,
2259 p->solid.pos.y + PILOT_SIZE_APPROX * sh / 2. + ico_hail->
sh / 4.,
2260 p->hail_pos % sx, p->hail_pos / sx, NULL );
2265 if ( p->comm_msg != NULL ) {
2266 double x, y, dx, dy;
2272 glColour
c = { 1., 1., 1., 1. };
2279 dx = x - p->comm_msgWidth / 2.;
2280 dy = y + PILOT_SIZE_APPROX * sh / 2.;
2291 if ( conf.healthbars && !playerdead && !pilot_isPlayer( p ) &&
2292 !pilot_isFlag( p, PILOT_DEAD ) && !pilot_isDisabled( p ) &&
2293 ( pilot_isFlag( p, PILOT_COMBAT ) || ( p->shield < p->shield_max ) ) ) {
2303 if ( ( x < -w ) || ( x > SCREEN_W + w ) || ( y < -h ) ||
2304 ( y > SCREEN_H + h ) )
2307 w = PILOT_SIZE_APPROX * sw;
2308 h = PILOT_SIZE_APPROX * sh / 3.;
2310 glUseProgram( shaders.healthbar.program );
2311 glUniform2f( shaders.healthbar.dimensions, 5., h );
2312 glUniform1f( shaders.healthbar.paramf,
2313 ( p->armour + p->shield ) /
2314 ( p->armour_max + p->shield_max ) );
2315 gl_uniformColour( shaders.healthbar.paramv,
2316 ( p->shield > 0. ) ? &cShield : &cArmour );
2332 double a, px, py, vx, vy, Q;
2340 cooling = pilot_isFlag( pilot, PILOT_COOLDOWN );
2349 if ( pilot->
ctimer < 0. ) {
2355 if ( pilot->
stimer <= 0. )
2357 for (
int i = 0; i < MAX_AI_TIMERS; i++ )
2358 if ( pilot->
timer[i] > 0. )
2359 pilot->
timer[i] -= dt;
2367 if ( pilot_isFlag( pilot, PILOT_HAILING ) ) {
2369 if ( ico_hail != NULL ) {
2372 sx = (int)ico_hail->
sx;
2373 sy = (int)ico_hail->
sy;
2374 if ( pilot->
htimer < 0. ) {
2382 pilotoutfit_modified = 0;
2390 if ( pos->
outfit == NULL )
2392 if ( !( pos->
flags & PILOTOUTFIT_ACTIVE ) )
2396 if ( pos->
timer > 0. )
2405 double ammo_threshold, reload_time;
2427 if ( pos->
rtimer < reload_time )
2434 while ( ( pos->
rtimer >= reload_time ) &&
2436 pos->
rtimer -= reload_time;
2444 if ( pos->
stimer >= 0. ) {
2446 if ( pos->
stimer < 0. ) {
2447 if ( pos->
state == PILOT_OUTFIT_ON ) {
2450 }
else if ( pos->
state == PILOT_OUTFIT_COOLDOWN ) {
2451 pos->
state = PILOT_OUTFIT_OFF;
2475 if ( !pilot_isFlag( pilot,
2476 PILOT_DISABLED ) ) {
2477 double stress_falloff =
2484 }
else if ( !pilot_isFlag(
2486 PILOT_DISABLED_PERM ) ) {
2503 pilot_hit( pilot, NULL, NULL, &dmg, NULL, LUA_NOREF, 0 );
2507 if ( pilot_isFlag( pilot, PILOT_TAKEOFF ) ) {
2508 if ( pilot->
ptimer < 0. ) {
2509 pilot_rmFlag( pilot, PILOT_TAKEOFF );
2510 if ( pilot_isFlag( pilot, PILOT_PLAYER ) ) {
2511 pilot_setFlag( pilot, PILOT_NONTARGETABLE );
2512 pilot->
itimer = PILOT_PLAYER_NONTARGETABLE_TAKEOFF_DELAY;
2516 }
else if ( pilot_isFlag( pilot, PILOT_LANDING ) ) {
2517 if ( pilot->
ptimer < 0. ) {
2518 if ( pilot_isPlayer( pilot ) ) {
2519 player_setFlag( PLAYER_HOOK_LAND );
2527 else if ( pilot_isFlag( pilot, PILOT_DEAD ) ) {
2534 if ( !pilot_isFlag( pilot, PILOT_DEATH_SOUND ) &&
2535 ( pilot->
ptimer < 0.050 ) ) {
2539 snprintf( buf,
sizeof( buf ),
"explosion%d", RNG( 0, 2 ) );
2544 pilot_setFlag( pilot, PILOT_DEATH_SOUND );
2547 else if ( !pilot_isFlag( pilot, PILOT_EXPLODED ) &&
2548 ( pilot->
ptimer < 0.200 ) ) {
2555 MAX( 0., 2. * ( a * ( 1. + sqrt( pilot->
fuel + 1. ) / 28. ) ) );
2560 pilot->
ship->
size / 2. / PILOT_SIZE_APPROX + a, &dmg,
2561 NULL, EXPL_MODE_SHIP );
2565 pilot_setFlag( pilot, PILOT_EXPLODED );
2569 if ( pilot_isFlag( pilot, PILOT_EXPLODED ) ) {
2577 else if ( pilot->
timer[1] <= 0. ) {
2584 a = RNGF() * 2. * M_PI;
2586 cos( a ) * RNGF() * pilot->
ship->
size / 2.;
2588 sin( a ) * RNGF() * pilot->
ship->
size / 2.;
2593 l = ( pilot->
id == PLAYER_ID ) ? SPFX_LAYER_FRONT
2594 : SPFX_LAYER_MIDDLE;
2602 if ( pilot_isFlag( pilot, PILOT_DEAD ) && ( pilot->
ptimer < 0. ) ) {
2603 if ( pilot->
id == PLAYER_ID )
2609 }
else if ( pilot_isFlag( pilot, PILOT_NONTARGETABLE ) ) {
2611 if ( pilot->
itimer < 0. )
2612 pilot_rmFlag( pilot, PILOT_NONTARGETABLE );
2613 }
else if ( pilot->
armour <= 0. ) {
2614 if ( pilot_isFlag( pilot, PILOT_NODEATH ) )
2621 if ( pilot_isFlag( pilot, PILOT_BRAKING ) ) {
2623 if ( pilot_isFlag( pilot, PILOT_COOLDOWN_BRAKE ) )
2631 if ( VMOD( pilot->
solid.
vel ) < 1e-1 ) {
2633 pilot_rmFlag( pilot, PILOT_BRAKING );
2640 if ( !pilot_isDisabled( pilot ) ) {
2649 if ( pilot->
stimer <= 0. ) {
2651 if ( pilot->
sbonus > 0. )
2670 else if ( pilot->
energy < 0. ) {
2681 if ( pilot_isFlag( pilot, PILOT_DELETE ) )
2686 if ( ( nchg > 0 ) || pilotoutfit_modified )
2690 if ( pilot_isDisabled( pilot ) || cooling ) {
2714 while ( pilot->
otimer >= PILOT_OUTFIT_LUA_UPDATE_DT ) {
2716 if ( pilot_isFlag( pilot, PILOT_DELETE ) )
2719 pilot->
otimer -= PILOT_OUTFIT_LUA_UPDATE_DT;
2731 if ( pilot_isFlag( pilot, PILOT_REFUELBOARDING ) )
2735 if ( pilot_isFlag( pilot, PILOT_BOARDING ) ) {
2736 if ( target == NULL )
2737 pilot_rmFlag( pilot, PILOT_BOARDING );
2743 if ( pilot->
ptimer < 0. )
2751 if ( !pilot_isFlag( pilot, PILOT_HYPERSPACE ) ) {
2754 if ( pilot_isFlag( pilot, PILOT_AFTERBURNER ) ) {
2772 if ( pilot->
id == PLAYER_ID )
2801 const double tilt_max = M_PI / 8.;
2802 const double tilt_mod = tilt_max * 8.;
2803 const double tilt_threshold = 0.05;
2811 }
else if ( pilot->
tilt > 0. ) {
2812 pilot->
tilt -= pilot->
turn / tilt_mod * dt;
2814 }
else if ( pilot->
tilt < 0. ) {
2815 pilot->
tilt += pilot->
turn / tilt_mod * dt;
2830 while ( pilot->
otimer >= PILOT_OUTFIT_LUA_UPDATE_DT ) {
2832 if ( pilot_isFlag( pilot, PILOT_DELETE ) )
2835 pilot->
otimer -= PILOT_OUTFIT_LUA_UPDATE_DT;
2848 double d2, cx, cy, dircos, dirsin;
2858 if ( p->trail == NULL )
2863 d2 =
pow2( cx - p->solid.pos.x ) +
pow2( cy - p->solid.pos.y );
2864 if ( d2 >
pow2(
MAX( SCREEN_W, SCREEN_H ) / conf.zoom_far * 2. ) )
2871 if ( pilot_isFlag( p, PILOT_HYPERSPACE ) ||
2872 pilot_isFlag( p, PILOT_HYP_END ) )
2873 mode = MODE_JUMPING;
2874 else if ( pilot_isFlag( p, PILOT_AFTERBURNER ) )
2875 mode = MODE_AFTERBURN;
2876 else if ( p->solid.accel > 0.2 )
2882 use_3d = ship_isFlag( p->ship, SHIP_3DTRAILS );
2887 dircos = cos( p->solid.dir );
2888 dirsin = sin( p->solid.dir );
2891 for (
int i = 0, g = 0; g <
array_size( p->ship->trail_emitters ); g++ ) {
2893 double dx, dy, dz, amod, ax, ay, scale;
2906 dz /= p->ship->size * 0.5;
2907 p->trail[i]->ontop = 1;
2909 p->trail[i]->ontop = 0;
2910 if ( !( trail->
flags & SHIP_TRAIL_ALWAYS_UNDER ) && ( dirsin > 0 ) ) {
2913 ( trail_front( p->trail[i] ).x - p->solid.pos.x ) * dircos +
2914 ( trail_front( p->trail[i] ).y - p->solid.pos.y ) * dirsin;
2916 p->trail[i]->ontop = ( prod < 0 );
2920 dx = trail->
pos.v[0] * dircos - trail->
pos.v[1] * dirsin;
2921 dy = trail->
pos.v[0] * dirsin + trail->
pos.v[1] * dircos +
2928 if ( pilot_isFlag( p, PILOT_LANDING ) )
2929 scale =
CLAMP( 0., 1., p->ptimer / p->landing_delay );
2930 else if ( pilot_isFlag( p, PILOT_TAKEOFF ) )
2931 scale =
CLAMP( 0., 1., 1. - p->ptimer / p->landing_delay );
2938 amod = p->solid.accel * p->engine_glow;
2939 ax = amod * -dircos;
2940 ay = amod * -dirsin;
2944 p->solid.pos.y + dy, dz, ax, ay, mode,
2945 mode == MODE_NONE );
2955 return !p->ship->trail_emitters[generator].trail_spec->nebula ||
2957 ( sys_isFlag(
cur_system, SYSTEM_NEBULATRAIL ) );
2970 if ( pilot_isFlag( p, PILOT_DELETE ) )
2981 if ( p->parent != 0 ) {
2983 if ( leader != NULL )
2988 if ( p->presence > 0 ) {
2995 if ( dockslot != NULL ) {
3002 pilot_setFlag( p, PILOT_DELETE );
3019 if ( pilot_isFlag( p, PILOT_HYPERSPACE ) ) {
3022 if ( ( p->id == PLAYER_ID ) &&
3024 ( p->timer[0] == -1. ) ) {
3030 if ( p->ptimer < 0. ) {
3031 pilot_setFlag( p, PILOT_HYP_END );
3033 if ( p->id == PLAYER_ID )
3034 player_setFlag( PLAYER_HOOK_HYPER );
3036 hparam.
type = HOOK_PARAM_JUMP;
3041 pilot_runHookParam( p, PILOT_HOOK_JUMP, &hparam, 1 );
3052 else if ( pilot_isFlag( p, PILOT_HYP_BEGIN ) ) {
3059 if ( pilot_isPlayer( p ) )
3060 if ( !player_isFlag( PLAYER_AUTONAV ) )
3063 _(
"Strayed too far from jump point: jump aborted." ) );
3064 }
else if ( pilot_isFlag( p, PILOT_AFTERBURNER ) ) {
3067 if ( pilot_isPlayer( p ) )
3068 if ( !player_isFlag( PLAYER_AUTONAV ) )
3070 _(
"Afterburner active: jump aborted." ) );
3072 if ( p->ptimer < 0. ) {
3073 p->ptimer = HYPERSPACE_FLY_DELAY * p->stats.jump_delay;
3074 pilot_setFlag( p, PILOT_HYPERSPACE );
3075 if ( p->id == PLAYER_ID )
3087 if ( pilot_isPlayer( p ) )
3088 if ( !player_isFlag( PLAYER_AUTONAV ) )
3091 _(
"Strayed too far from jump point: jump aborted." ) );
3094 if ( !p->stats.misc_instant_jump &&
3095 !pilot_isFlag( p, PILOT_HYP_BRAKE ) && !pilot_isStopped( p ) )
3100 pilot_setFlag( p, PILOT_HYP_BRAKE );
3104 sys =
cur_system->jumps[p->nav_hyperspace].target;
3109 if (
ABS( diff ) < MIN_DIR_ERR ) {
3110 if ( jp_isFlag( &
cur_system->jumps[p->nav_hyperspace],
3112 WARN( _(
"Pilot '%s' trying to jump through exit-only jump "
3113 "from '%s' to '%s'" ),
3117 p->ptimer = HYPERSPACE_ENGINE_DELAY * p->stats.jump_warmup *
3118 !p->stats.misc_instant_jump;
3119 pilot_setFlag( p, PILOT_HYP_BEGIN );
3121 if ( ( p->id == PLAYER_ID ) && !p->stats.misc_instant_jump )
3129 if ( pilot_isPlayer( p ) )
3142 if ( pilot_isFlag( p, PILOT_HYPERSPACE ) )
3145 if ( pilot_isFlag( p, PILOT_HYP_BEGIN ) ) {
3147 if ( p->id == PLAYER_ID ) {
3152 pilot_rmFlag( p, PILOT_HYP_BEGIN );
3153 pilot_rmFlag( p, PILOT_HYP_BRAKE );
3154 pilot_rmFlag( p, PILOT_HYP_PREP );
3157 for (
int i = 0; i <
array_size( p->escorts ); i++ ) {
3161 pilot_msg( p, e,
"hyperspace_abort", 0 );
3174 if ( target == NULL ) {
3175 pilot_rmFlag( p, PILOT_REFUELING );
3180 if ( vec2_dist( &p->solid.pos, &target->
solid.
pos ) >
3181 target->
ship->
size * PILOT_SIZE_APPROX )
3183 else if ( vec2_dist2( &p->solid.vel, &target->
solid.
vel ) >
3184 pow2( MAX_HYPERSPACE_VEL ) )
3188 pilot_setFlag( p, PILOT_REFUELBOARDING );
3189 p->ptimer = PILOT_REFUEL_TIME;
3198 p->solid.update( &p->solid, dt );
3215 if ( target == NULL ) {
3216 pilot_rmFlag( p, PILOT_REFUELBOARDING );
3217 pilot_rmFlag( p, PILOT_REFUELING );
3225 if ( p->ptimer < 0. ) {
3227 double amount =
MIN( p->fuel, p->refuel_amount );
3230 target->
fuel += amount;
3232 pilot_rmFlag( p, PILOT_REFUELBOARDING );
3233 pilot_rmFlag( p, PILOT_REFUELING );
3245 int stu = (int)( NT_PERIOD_SECONDS * p->stats.jump_delay );
3258 if ( (
pilot_stack[i]->nav_asteroid == asteroid ) &&
3272 for (
int i = 0; i <
array_size( p->outfits ); i++ ) {
3273 if ( p->outfits[i]->outfit == o )
3290 return ( amount <= p->credits );
3303 if ( CREDITS_MAX - p->credits <= amount )
3304 p->credits = CREDITS_MAX;
3306 p->credits += amount;
3307 }
else if ( amount < 0 ) {
3318 if ( ( amount <= CREDITS_MIN ) || (
ABS( amount ) >= p->credits ) )
3321 p->credits += amount;
3341 int faction,
double dir,
const vec2 *pos,
3342 const vec2 *vel,
const PilotFlags flags,
3343 unsigned int dockpilot,
int dockslot )
3360 pilot->
parent = dockpilot;
3365 pilot->
name = strdup( ( name == NULL ) ? _( ship->
name ) : name );
3373 solid_init( &pilot->
solid, ship->
mass, dir, pos, vel, SOLID_UPDATE_RK4 );
3386 for (
int i = 0; i < 3; i++ ) {
3387 *pilot_list_ptr[i] =
3389 for (
int j = 0; j <
array_size( ship_list[i] ); j++ ) {
3393 slot->
sslot = &ship_list[i][j];
3397 if ( ( !pilot_isFlagRaw( flags, PILOT_NO_OUTFITS ) ||
3406 if ( !pilot_isFlagRaw( flags, PILOT_NO_OUTFITS ) ) {
3437 if ( dslot != NULL )
3442 if ( !pilot_isFlagRaw( flags, PILOT_NO_OUTFITS ) ) {
3443 char message[STRMAX_SHORT];
3447 DEBUG( _(
"Pilot '%s' failed safety check: %s" ), pilot->
name,
3451 DEBUG( _(
" [%d] %s" ), i,
3459 pilot_copyFlagsRaw( pilot->
flags, flags );
3476 if ( pilot_isFlagRaw( flags, PILOT_TAKEOFF ) ) {
3482 lua_newtable(
naevL );
3494 for (
int i = PILOT_NOCLEAR + 1; i < PILOT_FLAGS_MAX; i++ )
3495 pilot->
flags[i] = 0;
3537 int n =
array_size( p->ship->trail_emitters );
3538 if ( p->trail == NULL )
3541 for (
int g = 0; g < n; g++ )
3558 const char *ai,
const double dir,
const vec2 *pos,
3559 const vec2 *vel,
const PilotFlags flags,
3560 unsigned int dockpilot,
int dockslot )
3565 WARN( _(
"Unable to allocate memory" ) );
3569 NTracingZone( _ctx, 1 );
3573 memset( p, 0,
sizeof(
Pilot ) );
3580 if ( pilot_isFlagRaw(
3581 flags, PILOT_PLAYER ) ) {
3591 pilot_init( p, ship, name, faction, dir, pos, vel, flags, dockpilot,
3613 NTracingZoneEnd( _ctx );
3631 if ( dyn == NULL ) {
3632 WARN( _(
"Unable to allocate memory" ) );
3635 memset( dyn, 0,
sizeof(
Pilot ) );
3636 pilot_init( dyn, ship, name, faction, 0., NULL, NULL, flags, 0, 0 );
3651 pilot_clearFlagsRaw( &pf );
3652 pilot_setFlagRaw( pf, PILOT_NO_OUTFITS );
3655 dyn = nmalloc(
sizeof(
Pilot ) );
3656 if ( dyn == NULL ) {
3657 WARN( _(
"Unable to allocate memory" ) );
3664 memset( dyn, 0,
sizeof(
Pilot ) );
3669 &ref->solid.pos, &ref->solid.vel, pf, 0, 0 );
3672 for (
int i = 0; i <
array_size( ref->outfits ); i++ )
3673 if ( ref->outfits[i]->outfit != NULL )
3675 for (
int i = 0; i <
array_size( ref->outfit_intrinsic ); i++ )
3693 pilot_setFlag( p, PILOT_NOFREE );
3710 WARN( _(
"Duplicate pilots on stack!" ) );
3724 for (
int j = 0; j <
array_size( p->trail ); j++ )
3750 after->
id = PLAYER_ID;
3768 pilot_setFlag( after, PILOT_PLAYER );
3769 pilot_setFlag( after, PILOT_NOFREE );
3785 int ignore_rules,
int guerilla )
3788 JumpPoint **validJumpPoints;
3799 if ( spob_hasService( pnt, SPOB_SERVICE_INHABITED ) &&
3813 const JumpPoint *jmp = &
cur_system->jumps[i];
3814 JumpPoint *target = jmp->returnJump;
3819 if ( jp_isFlag( target, JP_EXITONLY ) )
3822 if ( ignore_rules ) {
3828 if ( jp_isFlag( jmp, JP_HIDDEN ) && !guerilla )
3839 for (
int j = 0; j <
array_size( fact ); j++ )
3850 vec2_pset( vp, 1.5 *
cur_system->radius, RNGF() * 2 * M_PI );
3854 if ( jp_isFlag( jp->returnJump, JP_EXITONLY ) )
3857 if ( jp_isFlag( jp, JP_HIDDEN ) )
3863 if ( !guerilla &&
array_size( validJumpPoints ) <= 0 ) {
3866 if ( jp_isFlag( jp->returnJump, JP_EXITONLY ) )
3872 WARN( _(
"Creating pilot in system with no jumps nor spobs to take "
3880 double chance =
array_size( validJumpPoints );
3881 chance = chance / ( chance +
array_size( ind ) );
3884 if ( ( RNGF() <= chance ) && ( validJumpPoints != NULL ) )
3886 validJumpPoints[RNG_BASE( 0,
array_size( validJumpPoints ) - 1 )];
3904 NTracingZone( _ctx, 1 );
3916 for (
int i = 0; i <
array_size( p->trail ); i++ )
3922 if ( pilot_isFlag( p, PILOT_NOFREE ) ) {
3924 NTracingZoneEnd( _ctx );
3933 ss_free( p->intrinsic_stats );
3940 for (
int i = 0; i <
array_size( p->outfits ); i++ ) {
3941 ss_free( p->outfits[i]->lua_stats );
3963 free( p->comm_msg );
3966 luaL_unref(
naevL, p->messages, LUA_REGISTRYINDEX );
3969 memset( p, 0,
sizeof(
Pilot ) );
3974 NTracingZoneEnd( _ctx );
3997 WARN( _(
"Trying to remove non-existent pilot '%s' from stack!" ),
4039 free(
player.ps.acquired );
4054 int persist_count = 0;
4055 NTracingZone( _ctx, 1 );
4061 if ( p ==
player.p && ( persist && pilot_isFlag( p, PILOT_PERSIST ) ) )
4072 if ( !pilot_isFlag(
pilot_stack[i], PILOT_DELETE ) &&
4074 ( persist && pilot_isFlag(
pilot_stack[i], PILOT_PERSIST ) ) ) ) {
4085 for (
int g = 0; g <
array_size( p->trail ); g++ )
4109 NTracingZoneEnd( _ctx );
4120 NTracingZone( _ctx, 1 );
4128 qt_create( &
pilot_quadtree, -r, -r, r, r, qt_max_elem, qt_depth );
4131 NTracingZoneEnd( _ctx );
4151 if (
player.p != NULL ) {
4152 player_rmPlayerShip( &
player.ps );
4160static void pilot_addQuadtree(
const Pilot *p,
int i )
4162 int x, y, w2, h2, px, py;
4163 x = round( p->solid.pos.x );
4164 y = round( p->solid.pos.y );
4165 px = round( p->solid.pre.x );
4166 py = round( p->solid.pre.y );
4167 w2 = ceil( p->ship->size * 0.5 );
4168 h2 = ceil( p->ship->size * 0.5 );
4170 MAX( x, px ) + w2,
MAX( y, py ) + h2 );
4178 NTracingZone( _ctx, 1 );
4188 if ( pilot_isFlag( p, PILOT_DELETE ) )
4198 if ( pilot_isFlag( p, PILOT_DELETE ) )
4202 if ( pilot_isFlag( p, PILOT_HIDE ) )
4205 pilot_addQuadtree( p, i );
4208 NTracingZoneEnd( _ctx );
4218 NTracingZone( _ctx, 1 );
4226 if ( pilot_isFlag( p, PILOT_HIDE ) )
4230 if ( pilot_isDisabled( p ) )
4232 if ( pilot_isFlag( p, PILOT_DEAD ) || pilot_isFlag( p, PILOT_DELETE ) )
4241 if ( pilot_isFlag( p, PILOT_HYP_PREP ) ) {
4242 if ( !pilot_isFlag( p, PILOT_HYPERSPACE ) )
4247 else if ( pilot_isFlag( p, PILOT_HYP_END ) ) {
4248 if ( ( VMOD( p->solid.vel ) <
4249 2 * solid_maxspeed( &p->solid, p->speed, p->accel ) ) &&
4250 ( p->ptimer < 0. ) )
4251 pilot_rmFlag( p, PILOT_HYP_END );
4254 else if ( !pilot_isFlag( p, PILOT_BOARDING ) &&
4255 !pilot_isFlag( p, PILOT_REFUELBOARDING ) &&
4257 !pilot_isFlag( p, PILOT_LANDING ) &&
4258 !pilot_isFlag( p, PILOT_TAKEOFF ) &&
4260 !pilot_isFlag( p, PILOT_HYP_END ) ) {
4261 if ( pilot_isFlag( p, PILOT_PLAYER ) )
4273 if ( pilot_isFlag( p, PILOT_DELETE ) )
4277 if ( pilot_isFlag( p, PILOT_HIDE ) )
4281 if ( pilot_isFlag( p, PILOT_PLAYER ) )
4287 NTracingZoneEnd( _ctx );
4295 NTracingZone( _ctx, 1 );
4301 if ( pilot_isFlag( p, PILOT_HIDE ) || pilot_isFlag( p, PILOT_DELETE ) )
4304 if ( !pilot_isFlag( p, PILOT_PLAYER ) )
4308 NTracingZoneEnd( _ctx );
4316 NTracingZone( _ctx, 1 );
4322 if ( pilot_isFlag( p, PILOT_HIDE ) || pilot_isFlag( p, PILOT_DELETE ) )
4325 if ( !pilot_isFlag( p, PILOT_PLAYER ) )
4329 NTracingZoneEnd( _ctx );
4347 for (
int i = 0; i < MAX_AI_TIMERS; i++ )
4348 pilot->
timer[i] = 0.;
4366 return ( 1. - 1. / ( 1. + ( (
double)
cur_pilot->solid.mass /
4367 (
double)p->solid.mass ) ) );
4379 double shots, dps = 0., eps = 0.;
4380 for (
int i = 0; i <
array_size( p->outfits ); i++ ) {
4382 double mod_energy, mod_damage, mod_shots;
4383 const Outfit *o = p->outfits[i]->outfit;
4386 switch ( o->
type ) {
4387 case OUTFIT_TYPE_BOLT:
4388 mod_energy = p->stats.fwd_energy;
4389 mod_damage = p->stats.fwd_damage;
4390 mod_shots = 1. / p->stats.fwd_firerate * (double)o->
u.
blt.
shots;
4392 case OUTFIT_TYPE_TURRET_BOLT:
4393 mod_energy = p->stats.tur_energy;
4394 mod_damage = p->stats.tur_damage;
4395 mod_shots = 1. / p->stats.tur_firerate * (double)o->
u.
blt.
shots;
4397 case OUTFIT_TYPE_LAUNCHER:
4398 case OUTFIT_TYPE_TURRET_LAUNCHER:
4400 mod_damage = p->stats.launch_damage;
4401 mod_shots = 1. / p->stats.launch_rate * (double)o->
u.
lau.
shots;
4403 case OUTFIT_TYPE_BEAM:
4404 case OUTFIT_TYPE_TURRET_BEAM:
4406 if ( o->
type == OUTFIT_TYPE_BEAM ) {
4407 mod_energy = p->stats.fwd_energy;
4408 mod_damage = p->stats.fwd_damage;
4409 mod_shots = 1. / p->stats.fwd_firerate;
4411 mod_energy = p->stats.tur_energy;
4412 mod_damage = p->stats.tur_damage;
4413 mod_shots = 1. / p->stats.tur_firerate;
4416 mod_shots = shots / ( shots + mod_shots *
outfit_delay( o ) );
4427 dps += shots * mod_damage * dmg->
damage;
4447 double DPSaccum_target, DPSaccum_pilot;
4452 if ( ( DPSaccum_target > DOUBLE_TOL ) && ( DPSaccum_pilot > DOUBLE_TOL ) )
4453 return DPSaccum_pilot / ( DPSaccum_target + DPSaccum_pilot );
4454 else if ( DPSaccum_pilot > 0. )
4471 double p_hp = p->armour_max + p->shield_max;
4472 return c_hp / ( p_hp + c_hp );
4486 for (
int i = 0; i <
array_size( p->outfits ); i++ ) {
4487 if ( p->outfits[i]->outfit == NULL )
4490 if ( !count_unique &&
4491 outfit_isProp( p->outfits[i]->outfit, OUTFIT_PROP_UNIQUE ) )
4493 price += p->outfits[i]->outfit->price;
4509 mat4 H = { .m = { { -1., 0., 0., 0. },
4512 { 0., 0., 0., 1. } } };
4513 if ( fabs( p->tilt ) > DOUBLE_TOL ) {
4518 mat4_rotate( &H, -p->solid.dir + M_PI_2, 0.0, 1.0, 0.0 );
4535 lua_pushvalue(
naevL, idx );
4537 lua_pushnil(
naevL );
4539 lua_newtable(
naevL );
4543 lua_rawseti(
naevL, -2, 1 );
4546 lua_pushstring(
naevL, type );
4547 lua_rawseti(
naevL, -2, 2 );
4549 lua_pushvalue(
naevL, -2 );
4550 lua_rawseti(
naevL, -2, 3 );
4552 lua_rawgeti(
naevL, LUA_REGISTRYINDEX,
4554 lua_pushvalue(
naevL, -2 );
4555 lua_rawseti(
naevL, -2,
4556 lua_objlen(
naevL, -2 ) + 1 );
4557 lua_pop(
naevL, 3 );
4570 for (
int i = 0; i <
array_size( p->commodities ); i++ ) {
4571 const Commodity *
c = p->commodities[i].commodity;
4576 for (
int i = 0; i <
array_size( p->outfits ); i++ ) {
4577 const Outfit *o = p->outfits[i]->outfit;
4594 qt_max_elem = max_elem;
void ai_cleartasks(Pilot *p)
Clears the pilot's tasks.
void ai_think(Pilot *pilot, double dt, int dotask)
Heart of the AI, brains of the pilot.
void ai_getDistress(const Pilot *p, const Pilot *distressed, const Pilot *attacker)
Sends a distress signal to a pilot.
void ai_destroy(Pilot *p)
Destroys the ai part of the pilot.
void ai_init(Pilot *p)
Initializes the AI.
int ai_pinit(Pilot *p, const char *ai)
Initializes the pilot in the 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_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
#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 pilot_boardComplete(Pilot *p)
Finishes the boarding.
void cam_getPos(double *x, double *y)
Gets the camera position.
double cam_getZoom(void)
Gets the camera zoom.
int commodity_checkIllegal(const Commodity *com, int faction)
Checks to see if a commodity is illegal to a faction.
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 debris_add(double mass, double r, double px, double py, double vx, double vy)
Creates a cloud of debris.
void effect_cleanup(Effect *efxlist)
Cleans up an effect list freeing it.
int effect_update(Effect **efxlist, double dt)
Updates an effect list.
void escort_rmList(Pilot *p, unsigned int id)
Remove from escorts list.
void escort_freeList(Pilot *p)
Remove all escorts from a pilot.
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).
const char * faction_default_ai(int f)
Gets the name of the default AI profile for the faction's pilots.
const int * faction_getEnemies(int f)
Gets the list of enemies of a faction.
int areEnemies(int a, int b)
Checks whether two factions are enemies.
double faction_hit(int f, const StarSystem *sys, double mod, const char *source, int single)
Handles a faction hit against a faction and how to apply it.
void gl_printRaw(const glFont *ft_font, double x, double y, const glColour *c, double outlineR, const char *text)
Prints text on screen.
int gl_printWidthRaw(const glFont *ft_font, const char *text)
Gets the width that it would take to print some text.
glTexture * gui_hailIcon(void)
Gets the hail icon texture.
int gui_onScreenPilot(double *rx, double *ry, const Pilot *pilot)
Takes a pilot and returns whether it's on screen, plus its relative position.
void gui_cooldownEnd(void)
Notifies GUI scripts that the player broke out of cooldown.
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
void lvar_freeArray(lvar *arr)
Frees a variable array.
mat4 mat4_identity(void)
Creates an identity matrix.
void mat4_rotate(mat4 *m, double angle, double x, double y, double z)
Multiplies the given matrix by a rotation. (Follows the right-hand rule.)
void mat4_mul_vec(vec3 *out, const mat4 *m, const vec3 *v)
Multiplies a matrix with a vector (out = m * v);.
void mat4_scale(mat4 *m, double x, double y, double z)
Scales a homogeneous transformation matrix.
mat4 mat4_ortho(double left, double right, double bottom, double top, double nearVal, double farVal)
Creates an orthographic projection matrix.
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.
ntime_t ntime_create(int scu, int stp, int stu)
Creates a time structure.
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_renderRect(double x, double y, double w, double h, const glColour *c)
Renders a rectangle.
void gl_gameToScreenCoords(double *nx, double *ny, double bx, double by)
Converts in-game coordinates to screen coordinates.
void gl_unclipRect(void)
Clears the 2d clipping planes.
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_renderCross(double x, double y, double r, const glColour *c)
Renders a cross at a given position.
void gl_renderSpriteInterpolateScale(const glTexture *sa, const glTexture *sb, double inter, double bx, double by, double scalew, double scaleh, int sx, int sy, const glColour *c)
Blits a sprite interpolating, position is relative to the player.
void gl_clipRect(int x, int y, int w, int h)
Sets up 2d clipping planes around a rectangle.
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.
gl_vbo * gl_vboCreateDynamic(GLsizei size, const void *data)
Creates a dynamic 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.
int outfit_isLauncher(const Outfit *o)
Checks if outfit is a weapon launcher.
int outfit_checkIllegal(const Outfit *o, int fct)
Checks illegality of an outfit to a faction.
int outfit_isFighterBay(const Outfit *o)
Checks if outfit is a fighter bay.
const Damage * outfit_damage(const Outfit *o)
Gets the outfit's damage.
double outfit_energy(const Outfit *o)
Gets the outfit's energy usage.
double outfit_delay(const Outfit *o)
Gets the outfit's delay.
char pilot_getFactionColourChar(const Pilot *p)
Gets the faction colour char, works like faction_reputationColourChar but for a pilot.
void pilot_free(Pilot *p)
Frees and cleans up a pilot.
void pilot_stackRemove(Pilot *p)
Tries to remove a pilot from the stack.
static void pilot_hyperspace(Pilot *pilot, double dt)
Handles pilot's hyperspace states.
unsigned int pilot_getNearestEnemy_size(const Pilot *p, double target_mass_LB, double target_mass_UB)
Gets the nearest enemy to the pilot closest to the pilot whose mass is between LB and UB.
static int pilot_trail_generated(Pilot *p, int generator)
Return true if the given trail_emitters index has a corresponding generated trail.
void pilot_choosePoint(vec2 *vp, Spob **spob, JumpPoint **jump, int lf, int ignore_rules, int guerilla)
Finds a spawn point for a pilot.
int pilot_isHostile(const Pilot *p)
Checks to see if pilot is hostile to the player.
void pilot_updateDisable(Pilot *p, unsigned int shooter)
Handles pilot disabling. Set or unset the disable status depending on health and stress values.
void pilot_cooldown(Pilot *p, int dochecks)
Begins active cooldown, reducing hull and outfit temperatures.
static IntList pilot_qtquery
int pilot_brakeCheckReverseThrusters(const Pilot *p)
See if the pilot wants to use their reverse thrusters to brake.
void pilot_renderFramebuffer(Pilot *p, GLuint fbo, double fw, double fh, const Lighting *L)
Renders a pilot to a framebuffer.
void pilot_rmHostile(Pilot *p)
Unmarks a pilot as hostile to player.
unsigned int pilot_addStack(Pilot *p)
Adds a pilot to the stack.
void pilots_updatePurge(void)
Purges pilots set for deletion.
void pilot_quadtreeParams(int max_elem, int depth)
Sets the quad tree parameters. Can have significant impact on performance.
double pilot_relhp(const Pilot *cur_pilot, const Pilot *p)
Gets the relative hp(combined shields and armour) between the current pilot and the specified target.
int pilot_validEnemy(const Pilot *p, const Pilot *target)
Checks to see if a pilot is a valid enemy for another pilot.
double pilot_relsize(const Pilot *cur_pilot, const Pilot *p)
Gets the relative size(shipmass) between the current pilot and the specified target.
int pilot_areEnemies(const Pilot *p, const Pilot *target)
Like areEnemies but for pilots.
void pilots_clear(void)
Clears all the pilots except the player and clear-exempt pilots.
static const double pilot_commFade
unsigned int pilot_getNearestPilot(const Pilot *p)
Get the nearest pilot to a pilot.
void pilots_clean(int persist)
Cleans up the pilot stack - leaves the player.
Pilot * pilot_getTarget(Pilot *p)
Gets the target of a pilot using a fancy caching system.
Pilot * pilot_createEmpty(const Ship *ship, const char *name, int faction, PilotFlags flags)
Creates a pilot without adding it to the stack.
double pilot_face(Pilot *p, double dir, double dt)
Tries to turn the pilot to face dir.
mat4 pilot_local_transform(const Pilot *p)
Gets the local transformation matrix of a pilot.
double pilot_getNearestPos(const Pilot *p, unsigned int *tp, double x, double y, int disabled)
Get the nearest pilot to a pilot from a certain position.
void pilot_clearTimers(Pilot *pilot)
Clears the pilot's timers.
double pilot_reldps(const Pilot *cur_pilot, const Pilot *p)
Gets the relative damage output(total DPS) between the current pilot and the specified target.
void pilot_msg(const Pilot *p, const Pilot *receiver, const char *type, unsigned int idx)
Sends a message.
void pilot_dead(Pilot *p, unsigned int killer)
Pilot is dead, now will slowly explode.
static int pilot_cmp(const void *ptr1, const void *ptr2)
Compare id (for use with bsearch)
Pilot * pilot_setPlayer(Pilot *after)
Replaces the player's pilot with an alternate ship with the same ID.
static void pilot_refuel(Pilot *p, double dt)
Has the pilot refuel its target.
void pilot_renderOverlay(Pilot *p)
Renders the pilot overlay.
void pilot_setAccel(Pilot *p, double accel)
Sets the pilot's accel.
static void pilot_erase(Pilot *p)
Destroys pilot from stack.
void pilot_cooldownEnd(Pilot *p, const char *reason)
Terminates active cooldown.
static void pilot_init(Pilot *dest, const Ship *ship, const char *name, int faction, const double dir, const vec2 *pos, const vec2 *vel, const PilotFlags flags, unsigned int dockpilot, int dockslot)
Initialize pilot.
static const double pilot_commTimeout
credits_t pilot_modCredits(Pilot *p, credits_t amount)
Modifies the amount of credits the pilot has.
unsigned int pilot_getNearestEnemy(const Pilot *p)
Gets the nearest enemy to the pilot.
void pilot_setFriendly(Pilot *p)
Marks pilot as friendly to player.
void pilot_hyperspaceAbort(Pilot *p)
Stops the pilot from hyperspacing.
void pilot_setTurn(Pilot *p, double turn)
Sets the pilot's turn.
int pilot_validTarget(const Pilot *p, const Pilot *target)
Checks to see if a pilot is a valid target for another pilot.
void pilot_explode(double x, double y, double radius, const Damage *dmg, const Pilot *parent)
Makes the pilot explosion.
void pilot_reset(Pilot *pilot)
Resets a pilot.
int pilot_isFriendly(const Pilot *p)
Checks to see if pilot is friendly to the player.
int pilot_refuelStart(Pilot *p)
Attempts to start refueling the pilot's target.
void pilots_renderOverlay(void)
Renders all the pilots overlays.
int pilot_isNeutral(const Pilot *p)
Checks to see if pilot is neutral to the player.
PilotOutfitSlot * pilot_getDockSlot(Pilot *p)
Gets the dock slot of the pilot.
void pilots_init(void)
Initializes pilot stuff.
int pilot_hasIllegal(const Pilot *p, int faction)
Checks to see if the pilot has illegal stuf to a faction.
void pilot_setCommMsg(Pilot *p, const char *s)
Sets the overhead communication message of the pilot.
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
ntime_t pilot_hyperspaceDelay(const Pilot *p)
Calculates the hyperspace delay for a pilot.
void pilot_broadcast(Pilot *p, const char *msg, int ignore_int)
Has the pilot broadcast a message.
double pilot_minbrakedist(const Pilot *p, double dt, double *flytime)
Gets the minimum braking distance for the pilot.
void pilot_setHostile(Pilot *p)
Marks pilot as hostile to player.
double pilot_getNearestPosPilot(const Pilot *p, Pilot **tp, double x, double y, int disabled)
Get the nearest pilot to a pilot from a certain position.
void pilot_dpseps(const Pilot *p, double *pdps, double *peps)
Calculates the dps and eps of a pilot.
const glColour * pilot_getColour(const Pilot *p)
Gets a pilot's colour.
static Pilot ** pilot_stack
void pilot_distress(Pilot *p, Pilot *attacker, const char *msg)
Has the pilot broadcast a distress signal.
void pilot_render(Pilot *p)
Renders the pilot.
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
int pilot_canTarget(const Pilot *p)
Same as pilot_validTarget but without the range check.
credits_t pilot_worth(const Pilot *p, int count_unique)
Gets the price or worth of a pilot in credits.
unsigned int pilot_getNearestEnemy_heuristic(const Pilot *p, double mass_factor, double health_factor, double damage_factor, double range_factor)
Gets the nearest enemy to the pilot closest to the pilot whose mass is between LB and UB.
static unsigned int pilot_id
double pilot_aimAngle(Pilot *p, const vec2 *pos, const vec2 *vel)
Returns the angle for a pilot to aim at another pilot.
void pilots_newSystem(void)
Updates pilot state which depends on the system (sensor range, nebula trails...)
unsigned int pilot_getNextID(unsigned int id, int mode)
Gets the next pilot based on id.
void pilot_rmFriendly(Pilot *p)
Unmarks a pilot as friendly to player.
void pilots_render(void)
Renders all the pilots.
int pilot_areAllies(const Pilot *p, const Pilot *target)
Like areAllies but for pilots.
int pilot_validTargetRange(const Pilot *p, const Pilot *target, int *inrange)
Checks to see if a pilot is a valid target for another pilot while storing the result of pilot_inRang...
double pilot_getNearestAng(const Pilot *p, unsigned int *tp, double ang, int disabled)
Get the pilot closest to an angle extending from another pilot.
void pilot_untargetAsteroid(int anchor, int asteroid)
Loops over pilot stack to remove an asteroid as target.
int pilot_getJumps(const Pilot *p)
Gets the amount of jumps the pilot has left.
void pilot_delete(Pilot *p)
Deletes a pilot.
void pilots_update(double dt)
Updates all the pilots.
void pilots_cleanAll(void)
Even cleans up the player.
void pilot_clearTrails(Pilot *p)
Resets the trails for a pilot.
unsigned int pilot_getBoss(const Pilot *p)
Get the strongest ally in a given range.
static void pilot_init_trails(Pilot *p)
Initialize pilot's trails according to the ship type and current system characteristics.
void pilots_free(void)
Frees the pilot stack.
static Quadtree pilot_quadtree
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.
static int pilot_getStackPos(unsigned int id)
Gets the pilot's position in the stack.
void pilot_update(Pilot *pilot, double dt)
Updates the pilot.
Pilot * pilot_create(const Ship *ship, const char *name, int faction, const char *ai, const double dir, const vec2 *pos, const vec2 *vel, const PilotFlags flags, unsigned int dockpilot, int dockslot)
Creates a new pilot.
static void pilot_renderFramebufferBase(Pilot *p, GLuint fbo, double fw, double fh, const Lighting *L)
Renders a pilot to a framebuffer without effects.
unsigned int pilot_getPrevID(unsigned int id, int mode)
Gets the previous pilot based on ID.
int pilot_numOutfit(const Pilot *p, const Outfit *o)
Checks to see how many of an outfit a pilot has.
static void pilot_updateSolid(Pilot *p, double dt)
Updates the pilot solid.
void pilot_sample_trails(Pilot *p, int none)
Updates the given pilot's trail emissions.
int pilot_hasCredits(const Pilot *p, credits_t amount)
Checks to see if the pilot has at least a certain amount of credits.
int pilot_brake(Pilot *p, double dt)
Causes the pilot to turn around and brake.
void pilot_setTarget(Pilot *p, unsigned int id)
Sets the target of the pilot.
unsigned int pilot_clone(const Pilot *ref)
Clones an existing pilot.
int pilot_cargoRmAll(Pilot *pilot, int cleanup)
Gets rid of all cargo from pilot. Can remove mission cargo.
int pilot_cargoJet(Pilot *p, const Commodity *cargo, int quantity, int simulate)
Tries to get rid of quantity cargo from pilot, jetting it into space.
void pilot_ewUpdateStealth(Pilot *p, double dt)
Updates the stealth mode and checks to see if it is getting broken.
int pilot_inRangePilot(const Pilot *p, const Pilot *target, double *dist2)
Check to see if a pilot is in sensor range of another.
void pilot_ewUpdateDynamic(Pilot *p, double dt)
Updates the pilot's dynamic electronic warfare properties.
int pilot_inRangeSpob(const Pilot *p, int target)
Check to see if a spob is in sensor range of the pilot.
void pilot_updateSensorRange(void)
Updates the system's base sensor range.
void pilot_ewScanStart(Pilot *p)
Initializes the scan timer for a pilot.
double pilot_sensorRange(void)
Returns the default sensor range for the current system.
double pilot_heatEfficiencyMod(double T, double Tb, double Tc)
Returns a 0:1 modifier representing efficiency (1. being normal).
void pilot_heatUpdateCooldown(Pilot *p)
Overrides the usual heat model during active cooldown.
double pilot_heatFireRateMod(double T)
Returns a 0:1 modifier representing fire rate (1. being normal).
void pilot_heatReset(Pilot *p)
Resets a pilot's heat.
void pilot_heatUpdateShip(Pilot *p, double Q_cond, double dt)
Heats the pilot's ship.
double pilot_heatUpdateSlot(const Pilot *p, PilotOutfitSlot *o, double dt)
Heats the pilot's slot.
void pilot_heatAddSlotTime(const Pilot *p, PilotOutfitSlot *o, double dt)
Adds heat to an outfit slot over a period of time.
void pilots_clearGlobalHooks(void)
Removes all the pilot global hooks.
void pilot_clearHooks(Pilot *p)
Clears the pilots hooks.
void pilot_freeGlobalHooks(void)
Clears global pilot hooks.
int pilot_runHook(Pilot *p, int hook_type)
Tries to run a pilot hook if he has it.
void pilot_lockUpdateSlot(Pilot *p, PilotOutfitSlot *o, Pilot *t, Target *wt, double *a, double dt)
Updates the lockons on the pilot's launchers.
int pilot_addOutfitIntrinsicRaw(Pilot *pilot, const Outfit *outfit)
Adds an outfit as an intrinsic slot.
void pilot_outfitLCooldown(Pilot *pilot, int done, int success, double timer)
Handle cooldown hooks for outfits.
void pilot_outfitLOutfofenergy(Pilot *pilot)
Handles when the pilot runs out of energy.
void pilot_healLanded(Pilot *pilot)
Cures the pilot as if he was landed.
void pilot_calcStats(Pilot *pilot)
Recalculates the pilot's stats based on his outfits.
void pilot_fillAmmo(Pilot *pilot)
Fills pilot's ammo completely.
int pilot_addAmmo(Pilot *pilot, PilotOutfitSlot *s, int quantity)
Adds some ammo to the pilot stock.
void pilot_lockClear(Pilot *p)
Clears pilot's missile lockon timers.
void pilot_outfitLCleanup(Pilot *pilot)
Handle cleanup hooks for outfits.
int pilot_reportSpaceworthy(const Pilot *p, char *buf, int bufSize)
Pilot safety report - makes sure stats are safe.
void pilot_outfitLUpdate(Pilot *pilot, double dt)
Runs the pilot's Lua outfits update script.
int pilot_addOutfitRaw(Pilot *pilot, const Outfit *outfit, PilotOutfitSlot *s)
Adds an outfit to the pilot, ignoring CPU or other limits.
int pilot_addOutfitIntrinsic(Pilot *pilot, const Outfit *outfit)
Adds an outfit as an intrinsic slot.
void pilot_outfitLOnhit(Pilot *pilot, double armour, double shield, unsigned int attacker)
Runs the pilot's Lua outfits onhit script.
void pilot_outfitLInitAll(Pilot *pilot)
Runs the pilot's Lua outfits init script.
int pilot_shipLInit(Pilot *p)
Initializes the pilot ship Lua.
int pilot_shipLExplodeUpdate(Pilot *p, double dt)
Updates the pilot explosion Lua stuff.
int pilot_shipLUpdate(Pilot *p, double dt)
Updates the pilot Lua stuff.
int pilot_shipLCleanup(Pilot *p)
Cleans up the pilot ship Lua.
int pilot_shipLExplodeInit(Pilot *p)
Initializes the pilot explosion stuff.
void pilot_afterburnOver(Pilot *p)
Deactivates the afterburner.
void pilot_weapSetAIClear(Pilot *p)
Useful function for AI, clears activeness of all weapon sets.
Pilot * pilot_weaponTarget(Pilot *p, Target *wt)
Gets the weapon target of a pilot.
void pilot_weapSetUpdate(Pilot *p)
Updates the pilot's weapon sets.
int pilot_outfitOffAll(Pilot *p)
Disables all active outfits for a pilot.
double pilot_weapSetSpeed(Pilot *p, int id)
Gets the speed of the current pilot weapon set.
int pilot_outfitOff(Pilot *p, PilotOutfitSlot *o, int natural)
Disables a given active outfit.
void pilot_weapSetUpdateOutfitState(Pilot *p)
Updates the local state of all the pilot's outfits based on the weapon sets.
void pilot_weapSetFree(Pilot *p)
Frees a pilot's weapon sets.
void player_updateSpecific(Pilot *pplayer, const double dt)
Does a player specific update.
void player_dead(void)
Player got pwned.
void player_soundPlay(int sound, int once)
Plays a sound at the player.
void player_update(Pilot *pplayer, const double dt)
Player update function.
void player_soundStop(void)
Stops playing player sounds.
void player_think(Pilot *pplayer, const double dt)
Basically uses keyboard input instead of AI input. Used in pilot.c.
void player_destroyed(void)
Player blew up in a fireball.
void player_autonavResetSpeed(void)
Resets the game speed.
credits_t ship_basePrice(const Ship *s)
Gets the ship's base price (no outfits).
void ship_renderFramebuffer(const Ship *s, GLuint fbo, double fw, double fh, double dir, double engine_glow, double tilt, double r, int sx, int sy, const glColour *c, const Lighting *L)
Renders a ship to a framebuffer.
int ship_gfxLoad(Ship *s)
Loads the graphics for a ship if necessary.
void ss_free(ShipStatList *ll)
Frees a list of ship stats.
double sound_getLength(int sound)
Gets the length of the sound buffer.
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.
void spob_distress(Spob *spb, const Pilot *p, const Pilot *attacker)
Spob is receiving distress from a pilot about an attacker.
void system_rmCurrentPresence(StarSystem *sys, int faction, double amount)
Removes active presence.
int space_canHyperspace(const Pilot *p)
Checks to make sure if pilot is far enough away to hyperspace.
double system_getPresence(const StarSystem *sys, int faction)
Get the presence of a faction in a system.
int space_needsEffects(void)
returns whether or not we're simulating with effects.
int space_isSimulation(void)
returns whether we're just simulating.
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_shake(double mod)
Increases the current rumble level.
int spfx_get(const char *name)
Gets the id of an spfx based on name.
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.
void spfx_damage(double mod)
Increases the current damage level.
Trail_spfx * spfx_trail_create(const TrailSpec *spec)
Initalizes a trail.
void spfx_trail_draw(const Trail_spfx *trail)
Draws a trail on screen.
Represents a polygon used for collision detection.
Core damage that an outfit does.
The actual hook parameter.
union HookParam::@325330313164266255110350307176363262300250041145 u
A ship outfit, depends radically on the type.
union Outfit::@052125200133344144252153256241104103242010347340 u
OutfitAfterburnerData afb
const Commodity * commodity
Stores an outfit the pilot has.
The representation of an in-game pilot.
PilotCommodity * commodities
PilotOutfitSlot * outfit_structure
PilotOutfitSlot ** outfits
PilotOutfitSlot * outfit_utility
PilotOutfitSlot * outfit_intrinsic
double timer[MAX_AI_TIMERS]
unsigned int shoot_indicator
PilotOutfitSlot * afterburner
PilotOutfitSlot * outfit_weapon
double stress_dissipation
const TrailSpec * trail_spec
ShipOutfitSlot * outfit_utility
Outfit const ** outfit_intrinsic
ShipOutfitSlot * outfit_weapon
ShipOutfitSlot * outfit_structure
Represents a solid in the game.
void(* update)(struct Solid_ *, double)
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Represents a weapon target.
A trail generated by a ship or an ammo.
Abstraction for rendering sprite sheets.