79#include "gatherable.h"
84#include "nlua_asteroid.h"
85#include "nlua_pilot.h"
101#define ai_setFlag( f ) ( pilot_flags |= f )
102#define ai_isFlag( f ) ( pilot_flags & f )
104#define AI_DISTRESS ( 1 << 0 )
118static void ai_run( nlua_env env,
int nargs );
123static int ai_sort(
const void *p1,
const void *p2 );
171static int aiL_aim( lua_State *L );
172static int aiL_dir( lua_State *L );
350#define AI_STATUS_NORMAL 1
351#define AI_STATUS_CREATE 2
373 pointer->
next = NULL;
402 nlua_getenv(
naevL, env,
"mem" );
403 oldmem = luaL_ref(
naevL, LUA_REGISTRYINDEX );
406 nlua_setenv(
naevL, env,
"mem" );
431 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, oldmem.
mem );
432 nlua_setenv(
naevL, env,
"mem" );
433 luaL_unref(
naevL, LUA_REGISTRYINDEX, oldmem.
mem );
457 pilot_acc =
CLAMP( -PILOT_REVERSE_THRUST * p->stats.misc_reverse_thrust, 1.,
476static void ai_run( nlua_env env,
int nargs )
478 if (nlua_pcall( env, nargs, 0 )) {
479 WARN( _(
"Pilot '%s' ai '%s' error: %s" ),
cur_pilot->name,
499 strncpy( buf, ai,
sizeof( buf ) - 1 );
500 buf[
sizeof( buf ) - 1] =
'\0';
505 WARN( _(
"AI Profile '%s' not found, using dummy fallback." ), buf );
509 WARN( _(
"Dummy AI Profile not valid! Things are going to break." ) );
515 lua_newtable(
naevL );
519 lua_pushnil(
naevL );
520 while (lua_next(
naevL, -2 ) != 0) {
521 lua_pushvalue(
naevL, -2 );
522 lua_pushvalue(
naevL, -2 );
523 lua_remove(
naevL, -3 );
524 lua_settable(
naevL, -5 );
527 p->lua_mem = luaL_ref(
naevL, LUA_REGISTRYINDEX );
531 pilot_setFlag( p, PILOT_CREATED_AI );
538 p->tcontrol = RNGF() * p->ai->control_rate;
567 if (!pilot_isPlayer( p )) {
569 luaL_unref(
naevL, LUA_REGISTRYINDEX, p->lua_mem );
570 p->lua_mem = LUA_NOREF;
577static int ai_sort(
const void *p1,
const void *p2 )
581 return strcmp( ai1->
name, ai2->
name );
593 Uint32 time = SDL_GetTicks();
596 NTracingZone( _ctx, 1 );
599 files = PHYSFS_enumerateFiles( AI_PATH );
605 for (
size_t i = 0; files[i] != NULL; i++) {
613 snprintf( path,
sizeof( path ), AI_PATH
"%s", files[i] );
618 WARN( _(
"Error loading AI profile '%s'" ), path );
626 PHYSFS_freeList( files );
630 time = SDL_GetTicks() - time;
631 DEBUG( n_(
"Loaded %d AI Profile in %.3f s",
635 DEBUG( n_(
"Loaded %d AI Profile",
"Loaded %d AI Profiles",
646 NTracingZoneEnd( _ctx );
658 const char *filename = AI_EQUIP_PATH;
660 NTracingZone( _ctx, 1 );
671 if (nlua_dobufenv(
equip_env, buf, bufsize, filename ) != 0) {
672 WARN( _(
"Error loading file: %s\n"
674 "Most likely Lua file has improper syntax, please check" ),
675 filename, lua_tostring(
naevL, -1 ) );
676 NTracingZoneEnd( _ctx );
681 NTracingZoneEnd( _ctx );
686int nlua_loadAI( nlua_env env )
708 len = strlen( filename ) - strlen( AI_PATH ) - strlen(
".lua" );
709 prof->
name = malloc( len + 1 );
710 strncpy( prof->
name, &filename[strlen( AI_PATH )], len );
711 prof->
name[len] =
'\0';
714 env = nlua_newEnv( filename );
722 lua_pushboolean(
naevL, 1 );
723 nlua_setenv(
naevL, env,
"__ai" );
726 lua_newtable(
naevL );
727 lua_pushvalue(
naevL, -1 );
729 nlua_setenv(
naevL, env,
"mem" );
733 if (nlua_dobufenv( env, buf, bufsize, filename ) != 0) {
734 WARN( _(
"Error loading AI file: %s\n"
736 "Most likely Lua file has improper syntax, please check" ),
737 filename, lua_tostring(
naevL, -1 ) );
746 str = _(
"AI Profile '%s' is missing '%s' function!" );
749 WARN( str, filename,
"control" );
753 WARN( str, filename,
"control_manual" );
756 WARN( str, filename,
"refuel" );
759 WARN( str, filename,
"create" );
762 nlua_getenv(
naevL, env,
"control_rate" );
777 const AI_Profile ai = { .name = (
char *)name };
781 WARN( _(
"AI Profile '%s' not found in AI stack" ), name );
819 if (pilot->
ai == NULL)
822 NTracingZone( _ctx, 1 );
828 pilot_rmFlag( pilot, PILOT_SCANNING );
844 if ((
cur_pilot->tcontrol < 0. ) || ( t == NULL )) {
845 NTracingZoneName( _ctx_control,
"ai_think[control]", 1 );
847 double crate =
cur_pilot->ai->control_rate;
848 if (pilot_isFlag( pilot, PILOT_PLAYER ) ||
849 pilot_isFlag(
cur_pilot, PILOT_MANUAL_CONTROL )) {
850 lua_rawgeti(
naevL, LUA_REGISTRYINDEX,
855 lua_rawgeti(
naevL, LUA_REGISTRYINDEX,
cur_pilot->ai->ref_control );
860 cur_pilot->tcontrol = crate * ( 0.9 + 0.2 * RNGF() );
865 NTracingZoneEnd( _ctx_control );
870 NTracingZoneEnd( _ctx );
877 NTracingZoneName( _ctx_task,
"ai_think[task]", 1 );
881 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, t->
subtask->func );
884 if (data == LUA_NOREF)
887 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, t->
func );
891 if (data != LUA_NOREF) {
892 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, data );
898 if (pilot_isFlag(
cur_pilot, PILOT_MANUAL_CONTROL )) {
905 NTracingZoneEnd( _ctx_task );
921 NTracingZoneEnd( _ctx );
931 NTracingZone( _ctx, 1 );
934 if (( p->ai == NULL ) || ( p->ai->ref_create == LUA_NOREF ))
937 lua_rawgeti(
naevL, LUA_REGISTRYINDEX, p->ai->ref_create );
941 NTracingZoneEnd( _ctx );
957 hparam[0].
type = HOOK_PARAM_PILOT;
958 hparam[0].
u.
lp = attacker;
959 hparam[1].
type = HOOK_PARAM_NUMBER;
960 hparam[1].
u.
num = dmg;
963 pilot_runHookParam( attacked, PILOT_HOOK_ATTACKED, hparam, 2 );
966 if (attacked->
ai == NULL)
970 if (pilot_isFlag( attacked, PILOT_MANUAL_CONTROL ))
976 if (nlua_pcall(
cur_pilot->ai->env, 1, 0 )) {
977 WARN( _(
"Pilot '%s' ai '%s' -> 'attacked': %s" ),
cur_pilot->name,
995 if (pilot_isFlag( discovered, PILOT_MANUAL_CONTROL ))
999 if (discovered->
ai == NULL)
1006 if (lua_isnil(
naevL, -1 )) {
1007 lua_pop(
naevL, 1 );
1012 if (nlua_pcall(
cur_pilot->ai->env, 0, 0 )) {
1013 WARN( _(
"Pilot '%s' ai '%s' -> 'discovered': %s" ),
cur_pilot->name,
1015 lua_pop(
naevL, 1 );
1034 if (recipient->
ai == NULL)
1041 if (lua_isnil(
naevL, -1 )) {
1042 lua_pop(
naevL, 1 );
1047 if (nlua_pcall(
cur_pilot->ai->env, 0, 0 )) {
1048 WARN( _(
"Pilot '%s' ai '%s' -> 'hail': %s" ),
cur_pilot->name,
1050 lua_pop(
naevL, 1 );
1065 if (
cur_pilot->ai->ref_refuel == LUA_NOREF) {
1066 WARN( _(
"Pilot '%s' (ai '%s') is trying to refuel when no 'refuel' "
1067 "function is defined!" ),
1073 t = ncalloc( 1,
sizeof(
Task ) );
1074 t->
name = strdup(
"refuel" );
1075 lua_rawgeti(
naevL, LUA_REGISTRYINDEX,
cur_pilot->ai->ref_refuel );
1076 t->
func = luaL_ref(
naevL, LUA_REGISTRYINDEX );
1078 t->
dat = luaL_ref(
naevL, LUA_REGISTRYINDEX );
1095 const Pilot *attacker )
1098 if (pilot_isFlag( p, PILOT_MANUAL_CONTROL ))
1105 if (attacker != NULL)
1108 lua_pushnil(
naevL );
1109 pilot_msg( distressed, p,
"distress", -1 );
1110 lua_pop(
naevL, 1 );
1122 NTracingZone( _ctx, 1 );
1125 if (!pilot_isFlag( pilot, PILOT_CREATED_AI ))
1129 if (!pilot_isFlag( pilot, PILOT_NO_OUTFITS ) &&
1130 !pilot_isFlag( pilot, PILOT_NO_EQUIP ) &&
1133 char *func =
"equip_generic";
1139 nlua_getenv(
naevL, env, func );
1141 if (nlua_pcall( env, 1, 0 )) {
1142 WARN( _(
"Pilot '%s' equip '%s' -> '%s': %s" ), pilot->
name,
1143 pilot->
ai->
name, func, lua_tostring(
naevL, -1 ) );
1144 lua_pop(
naevL, 1 );
1152 if (pilot->
ai == NULL) {
1153 NTracingZoneEnd( _ctx );
1161 if (!pilot_isFlag( pilot, PILOT_CREATED_AI ))
1163 NTracingZoneEnd( _ctx );
1174 if (p->ai == NULL) {
1176 L, _(
"Trying to create new task for pilot '%s' that has no AI!" ),
1182 nlua_getenv( L, p->ai->env, func );
1183 luaL_checktype( L, -1, LUA_TFUNCTION );
1186 t = ncalloc( 1,
sizeof(
Task ) );
1187 t->
name = strdup( func );
1188 t->
func = luaL_ref( L, LUA_REGISTRYINDEX );
1193 if (( pos == 1 ) && ( p->task != NULL )) {
1194 for (pointer = p->task; pointer->next != NULL; pointer = pointer->next)
1204 if (curtask == NULL) {
1206 NLUA_ERROR( L, _(
"Trying to add subtask '%s' to non-existent task." ),
1212 if (( pos == 1 ) && ( curtask->
subtask != NULL )) {
1213 for (pointer = curtask->
subtask; pointer->next != NULL;
1214 pointer = pointer->next)
1233 if (t->
func != LUA_NOREF)
1234 luaL_unref(
naevL, LUA_REGISTRYINDEX, t->
func );
1236 if (t->
dat != LUA_NOREF)
1237 luaL_unref(
naevL, LUA_REGISTRYINDEX, t->
dat );
1246 if (t->
next != NULL) {
1261 const char *func = luaL_checkstring( L, 1 );
1264 !pilot_isFlag(
cur_pilot, PILOT_MANUAL_CONTROL ))
1270 NLUA_ERROR( L, _(
"Failed to create new task for pilot '%s'." ),
1276 if (lua_gettop( L ) > 1) {
1277 lua_pushvalue( L, 2 );
1278 t->
dat = luaL_ref( L, LUA_REGISTRYINDEX );
1289 if (t->
dat == LUA_NOREF)
1291 lua_rawgeti( L, LUA_REGISTRYINDEX, t->
dat );
1332 L, _(
"Trying to pop task when there are no tasks on the stack." ) );
1351 lua_pushstring( L, t->
name );
1397 L, _(
"Trying to pop task when there are no tasks on the stack." ) );
1399 return NLUA_ERROR( L,
1400 _(
"Trying to pop subtask when there are no subtasks "
1401 "for the task '%s'." ),
1422 if (( t != NULL ) && ( t->
subtask != NULL ))
1423 lua_pushstring( L, t->
subtask->name );
1440 if (( t == NULL ) || ( t->
subtask == NULL ))
1494 int candidate_id = -1;
1508 if (candidate_id == -1)
1537 NLUA_INVALID_PARAMETER( L, 1 );
1539 lua_pushnumber( L, vec2_dist( v, &
cur_pilot->solid.pos ) );
1564 NLUA_INVALID_PARAMETER( L, 1 );
1566 lua_pushnumber( L, vec2_dist2( v, &
cur_pilot->solid.pos ) );
1581 vec2 perp_motion_unit, offset_vect;
1582 int offset_distance;
1595 NLUA_INVALID_PARAMETER( L, 1 );
1597 vec2_cset( &offset_vect, VX( *v ) - VX(
cur_pilot->solid.pos ),
1598 VY( *v ) - VY(
cur_pilot->solid.pos ) );
1599 vec2_pset( &perp_motion_unit, 1, VANGLE(
cur_pilot->solid.vel ) + M_PI_2 );
1600 offset_distance = vec2_dot( &perp_motion_unit, &offset_vect );
1602 lua_pushnumber( L, offset_distance );
1624 if (lua_gettop( L ) > 0) {
1625 double time, dist, vel;
1630 vec2_cset( &vv, p->solid.vel.
x -
cur_pilot->solid.vel.x,
1631 p->solid.vel.y -
cur_pilot->solid.vel.y );
1637 vel =
MIN(
cur_pilot->speed - VMOD( p->solid.vel ), VMOD( vv ) );
1642 dist = vel * (flytime)-0.5 * (
cur_pilot->accel ) * time * time;
1643 lua_pushnumber( L, dist );
1644 lua_pushnumber( L, flytime );
1648 lua_pushnumber( L, dist );
1649 lua_pushnumber( L, flytime );
1664 lua_pushboolean( L, pilot_isWithPlayer( p ) &&
1665 pilot_isFlag(
cur_pilot, PILOT_BRIBED ) );
1677 lua_pushboolean( L,
cur_pilot->stats.misc_instant_jump );
1691 lua_pushboolean( L, ( VMOD(
cur_pilot->solid.vel ) >
1706 lua_pushboolean( L, ( VMOD(
cur_pilot->solid.vel ) < MIN_VEL_ERR ) );
1722 if (pilot_isWithPlayer( p )) {
1744 if (pilot_isWithPlayer( p )) {
1763 lua_pushboolean( L,
cur_pilot->lockons > 0 );
1776 lua_pushboolean( L,
cur_pilot->projectiles > 0 );
1804 double n = luaL_optnumber( L, 1, 1. );
1838 double k_diff, k_vel, diff, vx, vy, dx, dy;
1846 if (lua_toboolean( L, 2 ))
1854 }
else if (lua_isnumber( L, 1 )) {
1855 double d = lua_tonumber( L, 1 );
1856 diff = angle_diff(
cur_pilot->solid.dir,
d );
1860 lua_pushnumber( L,
ABS( diff ) );
1865 NLUA_INVALID_PARAMETER( L, 1 );
1868 vel = lua_toboolean( L, 3 );
1885 if (vel && ( dx || dy )) {
1887 double d = ( vx * dx + vy * dy ) / ( dx * dx + dy * dy );
1898 diff = angle_diff(
cur_pilot->solid.dir, atan2( dy, dx ) );
1904 lua_pushnumber( L,
ABS( diff ) );
1929 double d, diff, dist;
1935 const double k_goal = 1.;
1936 const double k_enemy = 6e6;
1947 }
else if (lua_isnumber( L, 1 )) {
1948 d = (double)lua_tonumber( L, 1 );
1952 NLUA_INVALID_PARAMETER( L, 1 );
1956 NLUA_INVALID_PARAMETER( L, 1 );
1959 vec2_csetmin( &F, 0., 0. );
1960 vec2_cset( &F1, tv->
x -
cur_pilot->solid.pos.x,
1962 dist = VMOD( F1 ) + 0.1;
1963 vec2_cset( &F1, F1.
x * k_goal / dist, F1.
y * k_goal / dist );
1972 pilot_collideQueryIL( &
ai_qtquery, x - r, y - r, x + r, y + r );
1973 for (
int i = 0; i < il_size( &
ai_qtquery ); i++) {
1980 if (p_i->
id == p->id)
1982 if (pilot_isDisabled( p_i ))
1988 if (dist <
pow2( 750. ))
1990 dist = sqrt( dist );
1996 double factor = k_enemy * k_mult / ( dist * dist * dist );
2003 vec2_cset( &F, F.x + F1.
x, F.y + F1.
y );
2006 diff = angle_diff(
cur_pilot->solid.dir, VANGLE( F ) );
2012 lua_pushnumber( L,
ABS( diff ) );
2029 double diff, mod, angle;
2041 diff = angle_diff(
cur_pilot->solid.dir, angle );
2044 lua_pushnumber( L,
ABS( diff ) );
2059 vec2 *vec, drift, reference_vector;
2061 double diff, heading_offset_azimuth, drift_radial, drift_azimuthal;
2071 NLUA_INVALID_PARAMETER( L, 1 );
2078 vec2_cset( &drift, VX( p->solid.vel ) - VX(
cur_pilot->solid.vel ),
2079 VY( p->solid.vel ) - VY(
cur_pilot->solid.vel ) );
2081 vec2_cset( &reference_vector,
2082 VX( p->solid.pos ) - VX(
cur_pilot->solid.pos ),
2083 VY( p->solid.pos ) - VY(
cur_pilot->solid.pos ) );
2086 vec2_cset( &drift, -VX(
cur_pilot->solid.vel ),
2089 vec2_cset( &reference_vector, VX( *vec ) - VX(
cur_pilot->solid.pos ),
2090 VY( *vec ) - VY(
cur_pilot->solid.pos ) );
2094 vec2_uv( &drift_radial, &drift_azimuthal, &drift, &reference_vector );
2095 heading_offset_azimuth =
2096 angle_diff(
cur_pilot->solid.dir, VANGLE( reference_vector ) );
2102 if (
FABS( heading_offset_azimuth ) < M_PI_2) {
2110 -copysign( 1. - 1. / (
FABS( drift_azimuthal / 200. ) + 1. ),
2113 diff = angle_diff( heading_offset_azimuth, speedmap );
2129 lua_pushnumber( L,
ABS( diff ) );
2150 vec2_cset( &tv, VX( p->solid.pos ), VY( p->solid.pos ) );
2151 diff = angle_diff(
cur_pilot->solid.dir, vec2_angle( &sv, &tv ) );
2154 diff = angle_diff(
cur_pilot->solid.dir,
2155 vec2_angle( &
cur_pilot->solid.pos, vec ) );
2157 NLUA_INVALID_PARAMETER( L, 1 );
2160 lua_pushnumber( L, diff );
2175 vec2 *vec, drift, reference_vector;
2177 double diff, heading_offset_azimuth, drift_radial, drift_azimuthal;
2187 NLUA_INVALID_PARAMETER( L, 1 );
2194 vec2_cset( &drift, VX( p->solid.vel ) - VX(
cur_pilot->solid.vel ),
2195 VY( p->solid.vel ) - VY(
cur_pilot->solid.vel ) );
2197 vec2_cset( &reference_vector,
2198 VX( p->solid.pos ) - VX(
cur_pilot->solid.pos ),
2199 VY( p->solid.pos ) - VY(
cur_pilot->solid.pos ) );
2202 vec2_cset( &drift, -VX(
cur_pilot->solid.vel ),
2205 vec2_cset( &reference_vector, VX( *vec ) - VX(
cur_pilot->solid.pos ),
2206 VY( *vec ) - VY(
cur_pilot->solid.pos ) );
2210 vec2_uv( &drift_radial, &drift_azimuthal, &drift, &reference_vector );
2211 heading_offset_azimuth =
2212 angle_diff(
cur_pilot->solid.dir, VANGLE( reference_vector ) );
2218 if (
FABS( heading_offset_azimuth ) < M_PI_2) {
2226 -copysign( 1. - 1. / (
FABS( drift_azimuthal / 200. ) + 1. ),
2229 diff = -angle_diff( heading_offset_azimuth, speedmap );
2238 diff = heading_offset_azimuth;
2242 lua_pushnumber( L, diff );
2257 lua_pushnumber( L, drift );
2271 double dir, accel, diff;
2272 int isstopped = pilot_isStopped(
cur_pilot );
2274 lua_toboolean( L, 1 ) *
cur_pilot->stats.misc_reverse_thrust;
2277 lua_pushboolean( L, 1 );
2283 accel = -PILOT_REVERSE_THRUST;
2285 dir = VANGLE(
cur_pilot->solid.vel ) + M_PI;
2289 diff = angle_diff(
cur_pilot->solid.dir, dir );
2291 if (
ABS( diff ) < MIN_DIR_ERR)
2295 lua_pushboolean( L, 0 );
2315 if (!spob_hasService(
cur_system->spobs[i], SPOB_SERVICE_INHABITED ))
2319 cur_system->spobs[i]->presence.faction ) ) &&
2356 if (!spob_hasService(
cur_system->spobs[i], SPOB_SERVICE_INHABITED ))
2360 cur_system->spobs[i]->presence.faction ) ) &&
2419 if (pilot_isFlag(
cur_pilot, PILOT_NOLAND ))
2423 only_friend = lua_toboolean( L, 1 );
2432 if (!spob_hasService( pnt, SPOB_SERVICE_LAND ))
2434 if (!spob_hasService( pnt, SPOB_SERVICE_INHABITED ))
2477 if (!lua_isnoneornil( L, 1 )) {
2488 return NLUA_ERROR( L, _(
"Spob '%s' not found in system '%s'" ),
2495 return NLUA_ERROR( L, _(
"Pilot '%s' (ai '%s') has no land target" ),
2503 !spob_hasService( spob, SPOB_SERVICE_LAND )) {
2504 lua_pushboolean( L, 0 );
2514 if (pilot_isFlag(
cur_pilot, PILOT_NOLAND )) {
2515 lua_pushboolean( L, 0 );
2521 lua_pushboolean( L, 0 );
2526 if (vec2_odist2( &
cur_pilot->solid.vel ) >
pow2( MAX_HYPERSPACE_VEL )) {
2527 lua_pushboolean( L, 0 );
2533 PILOT_LANDING_DELAY *
cur_pilot->ship->dt_default;
2535 pilot_setFlag(
cur_pilot, PILOT_LANDING );
2540 if (nlua_pcall( spob->
lua_env, 2, 0 )) {
2541 NLUA_WARN( L, _(
"Spob '%s' failed to run '%s':\n%s" ), spob->
name,
2542 "land", lua_tostring(
naevL, -1 ) );
2543 lua_pop(
naevL, 1 );
2547 hparam.
type = HOOK_PARAM_SPOB;
2548 hparam.
u.
la = spob->
id;
2550 pilot_runHookParam(
cur_pilot, PILOT_HOOK_LAND, &hparam, 1 );
2551 lua_pushboolean( L, 1 );
2567 if (!lua_isnoneornil( L, 1 )) {
2571 return NLUA_ERROR( L, _(
"Jump point must be in current system." ) );
2576 lua_pushnumber( L, canjump );
2589 const JumpPoint *jp;
2598 return NLUA_ERROR( L, _(
"Jump point must be in current system." ) );
2604 a = RNGF() * M_PI * 2.;
2605 rad = RNGF() * 0.5 * jp->radius;
2606 vec2_cadd( &vec, rad * cos( a ), rad * sin( a ) );
2625 const JumpPoint *jp;
2626 double mindist, dist;
2633 const JumpPoint *jiter = &
cur_system->jumps[i];
2637 if (jp_isFlag( jiter, JP_EXITONLY ))
2641 if (!useshidden && jp_isFlag( jiter, JP_HIDDEN ))
2649 dist = vec2_dist2( &
cur_pilot->solid.pos, &jiter->pos );
2650 if (dist < mindist) {
2659 lj.
destid = jp->targetid;
2693 if (( !useshidden && jp_isFlag( jiter, JP_HIDDEN ) ) ||
2694 jp_isFlag( jiter, JP_EXITONLY ))
2711 if (( !useshidden && jp_isFlag( jiter, JP_HIDDEN ) ) ||
2712 jp_isFlag( jiter, JP_EXITONLY ))
2721 NLUA_WARN( L, _(
"Pilot '%s' can't find jump to leave system!" ),
2729 lj.
destid = jumps[r]->targetid;
2778 if (lua_gettop( L ) > 1)
2779 absolute = lua_toboolean( L, 2 );
2785 vec2_cset( &vv, p->solid.vel.
x -
cur_pilot->solid.vel.x,
2786 p->solid.vel.y -
cur_pilot->solid.vel.y );
2788 vec2_cset( &vv, p->solid.vel.
x, p->solid.vel.y );
2790 vec2_cset( &pv, p->solid.pos.
x -
cur_pilot->solid.pos.x,
2791 p->solid.pos.y -
cur_pilot->solid.pos.y );
2792 dot = vec2_dot( &pv, &vv );
2793 mod =
MAX( VMOD( pv ), 1. );
2795 lua_pushnumber( L, dot / mod );
2816 vec2 point, cons, goal, pv;
2817 double radius, angle, Kp, Kd, angle2;
2818 const Pilot *p, *target;
2823 radius = luaL_optnumber( L, 2, 0. );
2824 angle = luaL_optnumber( L, 3, 0. );
2825 Kp = luaL_optnumber( L, 4, 10. );
2826 Kd = luaL_optnumber( L, 5, 20. );
2827 method = luaL_optstring( L, 6,
"velocity" );
2829 if (strcmp( method,
"absolute" ) == 0)
2831 else if (strcmp( method,
"keepangle" ) == 0) {
2832 vec2_cset( &pv, p->solid.pos.
x - target->
solid.
pos.
x,
2834 angle2 = VANGLE( pv );
2836 angle2 = angle + VANGLE( target->
solid.
vel );
2838 vec2_cset( &point, VX( target->
solid.
pos ) + radius * cos( angle2 ),
2839 VY( target->
solid.
pos ) + radius * sin( angle2 ) );
2843 ( point.
x - p->solid.pos.x ) * Kp +
2844 ( target->
solid.
vel.
x - p->solid.vel.x ) * Kd,
2845 ( point.
y - p->solid.pos.y ) * Kp +
2846 ( target->
solid.
vel.
y - p->solid.vel.y ) * Kd );
2848 vec2_cset( &goal, cons.
x + p->solid.pos.x, cons.
y + p->solid.pos.y );
2872 vec2 point, cons, goal, *pos, *vel;
2873 double radius, angle, Kp, Kd;
2878 radius = luaL_optnumber( L, 3, 0. );
2879 angle = luaL_optnumber( L, 4, 0. );
2880 Kp = luaL_optnumber( L, 5, 10. );
2881 Kd = luaL_optnumber( L, 6, 20. );
2883 vec2_cset( &point, pos->
x + radius * cos( angle ),
2884 pos->
y + radius * sin( angle ) );
2889 ( point.
x - p->solid.pos.x ) * Kp + ( vel->
x - p->solid.vel.x ) * Kd,
2890 ( point.
y - p->solid.pos.y ) * Kp + ( vel->
y - p->solid.vel.y ) * Kd );
2892 vec2_cset( &goal, cons.
x + p->solid.pos.x, cons.
y + p->solid.pos.y );
2910 if (VMOD(
cur_pilot->solid.vel ) < MIN_VEL_ERR)
2911 vec2_pset( &
cur_pilot->solid.vel, 0., 0. );
2938 if (lua_gettop( L ) > 0) {
2939 int i = lua_toboolean( L, 1 );
2941 pilot_setFlag(
cur_pilot, PILOT_COMBAT );
2943 pilot_rmFlag(
cur_pilot, PILOT_COMBAT );
2945 pilot_setFlag(
cur_pilot, PILOT_COMBAT );
2997 if (( lua_gettop( L ) < 1 ) || lua_isnil( L, 1 ))
3000 rad = lua_tonumber( L, 1 );
3005 lua_pushnumber( L, i );
3025 i = lua_tointeger( L, 1 );
3049 id = luaL_checkinteger( L, 1 ) - 1;
3051 if (lua_gettop( L ) > 1)
3052 type = lua_toboolean( L, 2 );
3072 lua_pushboolean( L,
cur_pilot->ncannons > 0 );
3084 lua_pushboolean( L,
cur_pilot->nturrets > 0 );
3096 lua_pushboolean( L,
cur_pilot->nfighterbays > 0 );
3108 lua_pushboolean( L,
cur_pilot->nafterburners > 0 );
3122 if (lua_isnoneornil( L, 1 )) {
3129 double range = luaL_checknumber( L, 1 );
3130 double r2 =
pow2( range );
3131 unsigned int tp = 0;
3139 pilot_collideQueryIL( &
ai_qtquery, x - r, y - r, x + r, y + r );
3140 for (
int i = 0; i < il_size( &
ai_qtquery ); i++) {
3144 if (vec2_dist2( &p->solid.pos, &
cur_pilot->solid.pos ) > r2)
3151 td = vec2_dist2( &p->solid.pos, &
cur_pilot->solid.pos );
3152 if (!tp || ( td <
d )) {
3170 if (pilot_isWithPlayer( p ))
3185 int id = luaL_checkinteger( L, 1 ) - 1;
3200 int id = luaL_checkinteger( L, 1 ) - 1;
3215 int id = luaL_checkinteger( L, 1 ) - 1;
3230 int id = luaL_checkinteger( L, 1 ) - 1;
3247 if (!pilot_isDisabled( p )) {
3248 lua_pushboolean( L, 0 );
3253 lua_pushboolean( L, !pilot_isFlag( p, PILOT_BOARDED ) );
3335 int n = luaL_checkint( L, 1 );
3337 cur_pilot->timer[n] = luaL_optnumber( L, 2, 0. );
3351 int n = luaL_checkint( L, 1 );
3352 lua_pushboolean( L,
cur_pilot->timer[n] <= 0. );
3364 cur_pilot->shoot_indicator = lua_toboolean( L, 1 );
3377 lua_pushboolean( L,
cur_pilot->shoot_indicator );
3389 if (lua_isstring( L, 1 ))
3391 lua_tostring( L, 1 ) );
3392 else if (lua_isnoneornil( L, 1 ))
3395 NLUA_INVALID_PARAMETER( L, 1 );
3434 cur_pilot->credits = luaL_checklong( L, 1 );
3447 lua_rawgeti( L, LUA_REGISTRYINDEX,
cur_pilot->messages );
3449 lua_rawseti( L, LUA_REGISTRYINDEX,
cur_pilot->messages );
3465 if (lua_gettop( L ) > 0)
3466 b = lua_toboolean( L, 1 );
3470 lua_pushboolean( L, 1 );
3488 cur_pilot->outfits[i]->flags &= ~PILOTOUTFIT_ISON_TOGGLE;
static int ai_setMemory(void)
Sets the cur_pilot's ai.
Task * ai_newtask(lua_State *L, Pilot *p, const char *func, int subtask, int pos)
Creates a new AI task.
void ai_unsetPilot(AIMemory oldmem)
Finishes setting up a pilot.
static nlua_env equip_env
void ai_thinkApply(Pilot *p)
Applies the result of thinking.
static AI_Profile * profiles
static IntList ai_qtquery
Task * ai_curTask(Pilot *pilot)
Gets the current running task.
void ai_refuel(Pilot *refueler, unsigned int target)
Has a pilot attempt to refuel the other.
static const luaL_Reg aiL_methods[]
static int ai_loadProfile(AI_Profile *prof, const char *filename)
Initializes an AI_Profile and adds it to the stack.
static void ai_create(Pilot *pilot)
Runs the create() function in the pilot.
void ai_cleartasks(Pilot *p)
Clears the pilot's tasks.
static int ai_tasktarget(lua_State *L, const Task *t)
Pushes a task target.
void ai_freetask(Task *t)
Frees an AI task.
void ai_think(Pilot *pilot, double dt, int dotask)
Heart of the AI, brains of the pilot.
void ai_thinkSetup(double dt)
Sets up the pilot for thinking.
void ai_getDistress(const Pilot *p, const Pilot *distressed, const Pilot *attacker)
Sends a distress signal to a pilot.
AIMemory ai_setPilot(Pilot *p)
Sets the pilot for further AI calls.
static Task * ai_createTask(lua_State *L, int subtask)
Creates a new task based on stack information.
static void ai_run(nlua_env env, int nargs)
Attempts to run a function.
static char aiL_distressmsg[STRMAX_SHORT]
void ai_attacked(Pilot *attacked, const unsigned int attacker, double dmg)
Triggers the attacked() function in the pilot's AI.
void ai_destroy(Pilot *p)
Destroys the ai part of the pilot.
void ai_hail(Pilot *recipient)
Triggers the hail() function in the pilot's AI.
void ai_discovered(Pilot *discovered)
Triggers the discovered() function in the pilot's AI.
void ai_exit(void)
Cleans up global AI.
static int ai_loadEquip(void)
Loads the equipment selector script.
void ai_init(Pilot *p)
Initializes the AI.
static void ai_taskGC(Pilot *pilot)
Runs the garbage collector on the pilot's tasks.
int ai_pinit(Pilot *p, const char *ai)
Initializes the pilot in the ai.
int ai_load(void)
Initializes the AI stuff which is basically Lua.
AI_Profile * ai_getProfile(const char *name)
Gets the AI_Profile by name.
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
int pilot_board(Pilot *p)
Has a pilot attempt to board another pilot.
nlua_env faction_getEquipper(int f)
Gets the equipper state associated to the faction scheduler.
int areEnemies(int a, int b)
Checks whether two factions are enemies.
int faction_usesHiddenJumps(int f)
Checks to see if a faction uses hidden jumps.
int areAllies(int a, int b)
Checks whether two factions are allies or not.
int gatherable_getPos(vec2 *pos, vec2 *vel, int id)
Returns the position and velocity of a gatherable.
int gatherable_getClosest(const vec2 *pos, double rad)
Gets the closest gatherable from a given position, within a given radius.
static int aiL_getweaprangemin(lua_State *L)
Gets the minimum range of a weapon set.
static int aiL_ismaxvel(lua_State *L)
Checks to see if pilot is at maximum velocity.
static int aiL_follow_accurate(lua_State *L)
Computes the point to face in order to follow another pilot using a PD controller.
static int aiL_face_accurate(lua_State *L)
Computes the point to face in order to follow a moving object.
static int aiL_relhp(lua_State *L)
Gets the relative health (total shields and armour) between the current pilot and the specified targe...
static int aiL_sethyptarget(lua_State *L)
Sets hyperspace target.
static int aiL_getspobfrompos(lua_State *L)
Get the nearest friendly spob to a given position.
static int aiL_getlandspob(lua_State *L)
Get a random friendly spob.
static int aiL_accel(lua_State *L)
Starts accelerating the pilot.
static int aiL_weapSet(lua_State *L)
Sets the active weapon set, fires another weapon set or activate an outfit.
static int aiL_poptask(lua_State *L)
Pops the current running task.
static int aiL_iface(lua_State *L)
Maintains an intercept pursuit course.
static int aiL_settarget(lua_State *L)
Sets the pilot's target.
static int aiL_nearhyptarget(lua_State *L)
Gets the nearest hyperspace target.
static int aiL_getrndspob(lua_State *L)
Get a random spob.
static int aiL_pilot(lua_State *L)
Gets the AI's pilot. Lua return parameter: Pilot The AI's pilot.
static int aiL_minbrakedist(lua_State *L)
Gets the minimum braking distance.
static int aiL_gatherablePos(lua_State *L)
Gets the pos and vel of a given gatherable.
static int aiL_relvel(lua_State *L)
Gets the relative velocity of a pilot.
static int aiL_haslockon(lua_State *L)
Checks to see if pilot has a missile lockon.
static int aiL_refuel(lua_State *L)
Attempts to refuel the pilot's target.
static int aiL_getdistance2(lua_State *L)
Gets the squared distance from the pointer.
static int aiL_getdistance(lua_State *L)
Gets the distance from the pointer.
static int aiL_instantJump(lua_State *L)
Checks to see if pilot can instant jump.
static int aiL_land(lua_State *L)
Lands on a spob.
static int aiL_isenemy(lua_State *L)
Checks to see if target is an enemy.
static int aiL_messages(lua_State *L)
Returns and clears the pilots message queue.
static int aiL_turn(lua_State *L)
Starts turning the pilot.
static int aiL_subtaskname(lua_State *L)
Gets the current subtask's name. Lua return parameter: string The current subtask name or nil if ther...
static int aiL_rndhyptarget(lua_State *L)
Gets a random hyperspace target.
static int aiL_dir(lua_State *L)
calculates the direction that the target is relative to the current pilot facing.
static int aiL_careful_face(lua_State *L)
Gives the direction to follow in order to reach the target while minimizating risk.
static int aiL_taskdata(lua_State *L)
Gets the pilot's task data. Lua return parameter: The pilot's task data or nil if there is no task da...
static int aiL_hasturrets(lua_State *L)
Does the pilot have turrets?
static int aiL_isally(lua_State *L)
Checks to see if target is an ally.
static int aiL_hyperspaceAbort(lua_State *L)
Has the AI abandon hyperspace if applicable.
static int aiL_relsize(lua_State *L)
Gets the relative size (ship mass) between the current pilot and the specified target.
static int aiL_aim(lua_State *L)
Aims at a pilot, trying to hit it rather than move to it.
static int aiL_credits(lua_State *L)
Sets the pilots credits. Only call in create().
static int aiL_reldps(lua_State *L)
Gets the relative damage output (total DPS) between the current pilot and the specified target.
static int aiL_canboard(lua_State *L)
Checks to see if pilot can board the target.
static int aiL_idir(lua_State *L)
Calculates angle between pilot facing and intercept-course to target.
static int aiL_getnearestpilot(lua_State *L)
gets the nearest pilot to the current pilot
static int aiL_hostile(lua_State *L)
Sets the enemy hostile (basically notifies of an impending attack).
static int aiL_hascannons(lua_State *L)
Does the pilot have cannons?
static int aiL_getBoss(lua_State *L)
Picks a pilot that will command the current pilot.
static int aiL_isbribed(lua_State *L)
Checks to see if target has bribed pilot.
static int aiL_getGatherable(lua_State *L)
Gets the closest gatherable within a radius.
static int aiL_taskname(lua_State *L)
Gets the current task's name. Lua return parameter: string The current task name or nil if there are ...
static int aiL_subtaskdata(lua_State *L)
Gets the pilot's subtask target. Lua return parameter: The pilot's target ship identifier or nil if n...
static int aiL_hasprojectile(lua_State *L)
Checks to see if pilot has a projectile after him.
static int aiL_getweapammo(lua_State *L)
Gets the ammo of a weapon.
static int aiL_drift_facing(lua_State *L)
Calculate the offset between the pilot's current direction of travel and the pilot's current facing.
static int aiL_shoot_indicator(lua_State *L)
Access the seeker shoot indicator (that is put to true each time a seeker is shot).
static int aiL_combat(lua_State *L)
Sets the combat flag.
static int aiL_distress(lua_State *L)
Sends a distress signal.
static int aiL_settimer(lua_State *L)
Sets a timer.
static int aiL_setasterotarget(lua_State *L)
Sets the pilot's asteroid target.
static int aiL_getweapspeed(lua_State *L)
Gets the speed of a weapon.
static int aiL_getrndpilot(lua_State *L)
Gets a random pilot in the system. Lua return parameter: Pilot|nil.
static int aiL_set_shoot_indicator(lua_State *L)
Set the seeker shoot indicator.
static int aiL_getenemy(lua_State *L)
Gets the nearest enemy.
static int aiL_stealth(lua_State *L)
Tries to stealth or destealth the pilot.
static int aiL_pushsubtask(lua_State *L)
Pushes a subtask onto the pilot's task's subtask list. Lua function parameter: string func Name of fu...
static int aiL_stop(lua_State *L)
Completely stops the pilot if it is below minimum vel error (no insta-stops).
static int aiL_getflybydistance(lua_State *L)
Gets the distance from the pointer perpendicular to the current pilot's flight vector.
static int aiL_canHyperspace(lua_State *L)
Gets whether or not the pilot can hyperspace.
static int aiL_popsubtask(lua_State *L)
Pops the current running task.
static int aiL_face(lua_State *L)
Faces the target.
static int aiL_timeup(lua_State *L)
Checks a timer.
static int aiL_pushtask(lua_State *L)
Pushes a task onto the pilot's task list. Lua function parameter: string func Name of function to cal...
static int aiL_scandone(lua_State *L)
Checks to see if pilot has finished scanning their target.
static int aiL_getweaprange(lua_State *L)
Gets the range of a weapon set.
static int aiL_dock(lua_State *L)
Docks the ship.
static int aiL_outfitOffAll(lua_State *L)
Tries to turn off all outfits.
static int aiL_hyperspace(lua_State *L)
Tries to enter hyperspace.
static int aiL_hasafterburner(lua_State *L)
Does the pilot have afterburners?
static int aiL_board(lua_State *L)
Attempts to board the pilot's target.
static int aiL_hasfighterbays(lua_State *L)
Does the pilot have fighter bays?
static int aiL_brake(lua_State *L)
Brakes the pilot.
static int aiL_getnearestspob(lua_State *L)
Get the nearest friendly spob to the pilot.
static int aiL_isstopped(lua_State *L)
Checks to see if pilot is stopped.
void naev_renderLoadscreen(void)
Renders the loadscreen if necessary.
Header file with generic functions and naev-specifics.
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
int ndata_matchExt(const char *path, const char *ext)
Sees if a file matches an extension.
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
int nlua_refenvtype(nlua_env env, const char *name, int type)
Gets the reference of a global in a lua environment if it matches a type.
int lua_isasteroid(lua_State *L, int ind)
Checks to see if ind is a asteroid.
LuaAsteroid_t * luaL_checkasteroid(lua_State *L, int ind)
Gets asteroid at index or raises error if there is no asteroid at index.
Asteroid * luaL_validasteroid(lua_State *L, int ind)
Gets asteroid at index raising an error if type doesn't match.
LuaJump * luaL_checkjump(lua_State *L, int ind)
Gets jump at index raising an error if isn't a jump.
LuaJump * lua_pushjump(lua_State *L, LuaJump jump)
Pushes a jump on the stack.
JumpPoint * luaL_validjump(lua_State *L, int ind)
Gets a jump directly.
LuaPilot * lua_pushpilot(lua_State *L, LuaPilot pilot)
Pushes a pilot on the stack.
Pilot * luaL_validpilot(lua_State *L, int ind)
Makes sure the pilot is valid or raises a Lua error.
int lua_ispilot(lua_State *L, int ind)
Checks to see if ind is a pilot.
LuaSpob * lua_pushspob(lua_State *L, LuaSpob spob)
Pushes a spob on the stack.
Spob * luaL_validspob(lua_State *L, int ind)
Gets a spob directly.
int lua_isvector(lua_State *L, int ind)
Checks to see if ind is a vector.
vec2 * luaL_checkvector(lua_State *L, int ind)
Gets vector at index making sure type is valid.
vec2 * lua_tovector(lua_State *L, int ind)
Represents a 2D vector in Lua.
vec2 * lua_pushvector(lua_State *L, vec2 vec)
Pushes a vector on the stack.
int pilot_isHostile(const Pilot *p)
Checks to see if pilot is hostile to the player.
int pilot_brakeCheckReverseThrusters(const Pilot *p)
See if the pilot wants to use their reverse thrusters to brake.
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.
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_setAccel(Pilot *p, double accel)
Sets the pilot's accel.
unsigned int pilot_getNearestEnemy(const Pilot *p)
Gets the nearest enemy to the pilot.
void pilot_hyperspaceAbort(Pilot *p)
Stops the pilot from hyperspacing.
void pilot_setTurn(Pilot *p, double turn)
Sets the pilot's turn.
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.
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.
static Pilot ** pilot_stack
void pilot_distress(Pilot *p, Pilot *attacker, const char *msg)
Has the pilot broadcast a distress signal.
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
int pilot_canTarget(const Pilot *p)
Same as pilot_validTarget but without the range check.
double pilot_aimAngle(Pilot *p, const vec2 *pos, const vec2 *vel)
Returns the angle for a pilot to aim at another pilot.
unsigned int pilot_getBoss(const Pilot *p)
Get the strongest ally in a given range.
void pilot_setTarget(Pilot *p, unsigned int id)
Sets the target of the pilot.
int pilot_inRangePilot(const Pilot *p, const Pilot *target, double *dist2)
Check to see if a pilot is in sensor range of another.
int pilot_ewScanCheck(const Pilot *p)
Checks to see if a scan is done.
void pilot_destealth(Pilot *p)
Destealths a pilot.
int pilot_stealth(Pilot *p)
Stealths a pilot.
int pilot_runHook(Pilot *p, int hook_type)
Tries to run a pilot hook if he has it.
void pilot_healLanded(Pilot *pilot)
Cures the pilot as if he was landed.
double pilot_weapSetRangeMin(Pilot *p, int id)
Gets the minimum range of the current pilot weapon set.
void pilot_weapSetAIClear(Pilot *p)
Useful function for AI, clears activeness of all weapon sets.
double pilot_weapSetSpeed(Pilot *p, int id)
Gets the speed of the current pilot weapon set.
double pilot_weapSetAmmo(Pilot *p, int id)
Gets the ammo of the current pilot weapon set.
void pilot_weapSetUpdateOutfitState(Pilot *p)
Updates the local state of all the pilot's outfits based on the weapon sets.
double pilot_weapSetRange(Pilot *p, int id)
Gets the range of the current pilot weapon set.
int pilot_weapSetPress(Pilot *p, int id, int type)
Handles a weapon set press.
int space_canHyperspace(const Pilot *p)
Checks to make sure if pilot is far enough away to hyperspace.
int spob_index(const Spob *p)
Gets the ID of a spob.
double system_getPresence(const StarSystem *sys, int faction)
Get the presence of a faction in a system.
int space_hyperspace(Pilot *p)
Tries to get the pilot into hyperspace.
Represents a temporary pilot memory. For use with ai_setPilot and ai_unsetPilot.
Represents a single asteroid.
The actual hook parameter.
union HookParam::@114305201244257020071001257133270030317263020235 u
The representation of an in-game pilot.
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...