naev 0.12.5
player_autonav.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <time.h>
11
12#include "naev.h"
14
15#include "player_autonav.h"
16
17#include "ai.h"
18#include "map_overlay.h"
19#include "ndata.h"
20#include "nlua.h"
21#include "nlua_pilot.h"
22#include "nlua_spob.h"
23#include "nlua_vec2.h"
24#include "ntracing.h"
25#include "pause.h"
26#include "pilot.h"
27#include "pilot_ew.h"
28#include "player.h"
29#include "sound.h"
30#include "space.h"
31#include "toolkit.h"
32
33static nlua_env autonav_env = LUA_NOREF;
34static int func_system = LUA_NOREF;
35static int func_spob = LUA_NOREF;
36static int func_pilot = LUA_NOREF;
37static int func_board = LUA_NOREF;
38static int func_pos = LUA_NOREF;
39static int func_reset = LUA_NOREF;
40static int func_end = LUA_NOREF;
41static int func_abort = LUA_NOREF;
42static int func_think = LUA_NOREF;
43static int func_update = LUA_NOREF;
44static int func_enter = LUA_NOREF;
45
46/*
47 * Prototypes.
48 */
49static int player_autonavSetup( void );
50
55{
56 nlua_env env = nlua_newEnv( AUTONAV_PATH );
57 nlua_loadStandard( env );
58 nlua_loadAI( env );
59
60 size_t bufsize;
61 char *buf = ndata_read( AUTONAV_PATH, &bufsize );
62 if ( nlua_dobufenv( env, buf, bufsize, AUTONAV_PATH ) != 0 ) {
63 WARN( _( "Error loading file: %s\n"
64 "%s\n"
65 "Most likely Lua file has improper syntax, please check" ),
66 AUTONAV_PATH, lua_tostring( naevL, -1 ) );
67 free( buf );
68 return -1;
69 }
70 free( buf );
71 autonav_env = env;
72
73 func_system = nlua_refenvtype( env, "autonav_system", LUA_TFUNCTION );
74 func_spob = nlua_refenvtype( env, "autonav_spob", LUA_TFUNCTION );
75 func_pilot = nlua_refenvtype( env, "autonav_pilot", LUA_TFUNCTION );
76 func_board = nlua_refenvtype( env, "autonav_board", LUA_TFUNCTION );
77 func_pos = nlua_refenvtype( env, "autonav_pos", LUA_TFUNCTION );
78 func_reset = nlua_refenvtype( env, "autonav_reset", LUA_TFUNCTION );
79 func_end = nlua_refenvtype( env, "autonav_end", LUA_TFUNCTION );
80 func_abort = nlua_refenvtype( env, "autonav_abort", LUA_TFUNCTION );
81 func_think = nlua_refenvtype( env, "autonav_think", LUA_TFUNCTION );
82 func_update = nlua_refenvtype( env, "autonav_update", LUA_TFUNCTION );
83 func_enter = nlua_refenvtype( env, "autonav_enter", LUA_TFUNCTION );
84
85 return 0;
86}
87
95
100{
101 /* Not under manual control or disabled. */
102 if ( pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) ||
103 pilot_isDisabled( player.p ) )
104 return;
105
106 if ( ( player.p->nav_hyperspace == -1 ) && ( player.p->nav_spob == -1 ) )
107 return;
108 else if ( ( player.p->nav_spob != -1 ) && !player_getHypPreempt() ) {
109 player_autonavSpob( cur_system->spobs[player.p->nav_spob]->name, 0 );
110 return;
111 }
112
113 if ( player.p->fuel < player.p->fuel_consumption ) {
114 player_message( "#r%s#0", _( "Not enough fuel to jump for autonav." ) );
115 return;
116 }
117
118 if ( pilot_isFlag( player.p, PILOT_NOJUMP ) ) {
119 player_message( "#r%s#0", _( "Hyperspace drive is offline." ) );
120 return;
121 }
122
123 if ( player_autonavSetup() )
124 return;
125
126 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_system );
127 if ( nlua_pcall( autonav_env, 0, 0 ) ) {
128 WARN( "%s", lua_tostring( naevL, -1 ) );
129 lua_pop( naevL, 1 );
130 }
131 player.autonav = AUTONAV_JUMP;
132}
133
139static int player_autonavSetup( void )
140{
141 /* Not under manual control or disabled. */
142 if ( pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) ||
143 pilot_isDisabled( player.p ) )
144 return -1;
145
146 /* Autonav is mutually-exclusive with other autopilot methods. */
147 player_restoreControl( PINPUT_AUTONAV, NULL );
148 player_setFlag( PLAYER_AUTONAV );
149
150 return 0;
151}
152
153static int autonav_ending = 0;
158{
159 /* Don't allow recursive end chaining. */
160 if ( autonav_ending )
161 return;
162
163 autonav_ending = 1;
164 player_rmFlag( PLAYER_AUTONAV );
165 ovr_autonavClear();
167 player.speed_autonav = 1.;
168
169 /* End it. */
170 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_end );
171 if ( nlua_pcall( autonav_env, 0, 0 ) ) {
172 WARN( "%s", lua_tostring( naevL, -1 ) );
173 lua_pop( naevL, 1 );
174 }
175
176 autonav_ending = 0;
177}
178
182void player_autonavStartWindow( unsigned int wid, const char *str )
183{
184 (void)str;
187 window_destroy( wid );
188}
189
193void player_autonavPos( double x, double y )
194{
195 vec2 pos;
196
197 if ( player_autonavSetup() )
198 return;
199
200 vec2_cset( &pos, x, y );
201 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_pos );
202 lua_pushvector( naevL, pos );
203 if ( nlua_pcall( autonav_env, 1, 0 ) ) {
204 WARN( "%s", lua_tostring( naevL, -1 ) );
205 lua_pop( naevL, 1 );
206 }
207 player.autonav = AUTONAV_POS;
208}
209
213void player_autonavSpob( const char *name, int tryland )
214{
215 const Spob *spb;
216
217 if ( player_autonavSetup() )
218 return;
219
220 spb = spob_get( name );
221
222 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_spob );
223 lua_pushspob( naevL, spob_index( spb ) );
224 lua_pushboolean( naevL, tryland );
225 if ( nlua_pcall( autonav_env, 2, 0 ) ) {
226 WARN( "%s", lua_tostring( naevL, -1 ) );
227 lua_pop( naevL, 1 );
228 }
229 player.autonav = AUTONAV_SPOB;
230}
231
235void player_autonavPil( unsigned int p )
236{
237 const Pilot *pilot = pilot_get( p );
238 int inrange = pilot_inRangePilot( player.p, pilot, NULL );
239 if ( player_autonavSetup() || !inrange )
240 return;
241
242 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_pilot );
243 lua_pushpilot( naevL, p );
244 if ( nlua_pcall( autonav_env, 1, 0 ) ) {
245 WARN( "%s", lua_tostring( naevL, -1 ) );
246 lua_pop( naevL, 1 );
247 }
248 player.autonav = AUTONAV_PILOT;
249}
250
254void player_autonavBoard( unsigned int p )
255{
256 const Pilot *pilot = pilot_get( p );
257 int inrange = pilot_inRangePilot( player.p, pilot, NULL );
258 if ( player_autonavSetup() || !inrange )
259 return;
260
261 /* Detected fuzzy, can't board. */
262 if ( inrange != 1 ) {
264 return;
265 }
266
267 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_board );
268 lua_pushpilot( naevL, p );
269 if ( nlua_pcall( autonav_env, 1, 0 ) ) {
270 WARN( "%s", lua_tostring( naevL, -1 ) );
271 lua_pop( naevL, 1 );
272 }
273 player.autonav = AUTONAV_PILOT;
274}
275
281void player_autonavAbort( const char *reason )
282{
283 /* No point if player is beyond aborting. */
284 if ( ( player.p == NULL ) || pilot_isFlag( player.p, PILOT_HYPERSPACE ) )
285 return;
286
287 /* Not under autonav. */
288 if ( !player_isFlag( PLAYER_AUTONAV ) )
289 return;
290
291 /* Cooldown (handled later) may be script-initiated and we don't
292 * want to make it player-abortable while under manual control. */
293 if ( pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) )
294 return;
295
296 /* Run Lua function. */
297 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_abort );
298 if ( reason != NULL )
299 lua_pushstring( naevL, reason );
300 else
301 lua_pushnil( naevL );
302 if ( nlua_pcall( autonav_env, 1, 0 ) ) {
303 WARN( "%s", lua_tostring( naevL, -1 ) );
304 lua_pop( naevL, 1 );
305 }
306
307 /* Break possible hyperspacing. */
308 if ( pilot_isFlag( player.p, PILOT_HYP_PREP ) ) {
310 player_message( "#o%s#0", _( "Autonav: aborting hyperspace sequence." ) );
311 }
312}
313
319void player_autonavReset( double s )
320{
321 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_reset );
322 lua_pushnumber( naevL, s );
323 if ( nlua_pcall( autonav_env, 1, 0 ) ) {
324 WARN( "%s", lua_tostring( naevL, -1 ) );
325 lua_pop( naevL, 1 );
326 }
327}
328
335void player_thinkAutonav( Pilot *pplayer, double dt )
336{
337 AIMemory oldmem;
338
339 ai_thinkSetup( dt );
340 oldmem = ai_setPilot( pplayer ); /* Uses AI functionality. */
341 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_think );
342 lua_pushnumber( naevL, dt );
343 if ( nlua_pcall( autonav_env, 1, 0 ) ) {
344 WARN( "%s", lua_tostring( naevL, -1 ) );
345 lua_pop( naevL, 1 );
346 }
347 ai_unsetPilot( oldmem );
348 ai_thinkApply( pplayer );
349}
350
357void player_updateAutonav( double dt )
358{
359 const double dis_dead = 1.0; /* Time it takes to start ramping up. */
360 const double dis_mod = 2.0;
361 // const double dis_max = 5.0;
362 // const double dis_ramp = 3.0;
363
364 if ( paused || ( player.p == NULL ) ||
365 pilot_isFlag( player.p, PILOT_DEAD ) ||
366 player_isFlag( PLAYER_CINEMATICS ) )
367 return;
368
369 /* TODO maybe handle in autonav? */
370 /* We handle disabling here. */
371 if ( pilot_isFlag( player.p, PILOT_DISABLED ) ) {
372 static double tc_mod = 1.0;
373 /* It is somewhat like:
374 * /------------\ 4x
375 * / \
376 * -----/ \----- 1x
377 *
378 * <---><-><----------><-><--->
379 * 5 6 X 6 5 Real time
380 * 5 15 X 15 5 Game time
381 *
382 * For triangles we have to add the rectangle and triangle areas.
383 */
384 double tc_base = player_dt_default() * player.speed;
385 double dis_max = MAX( 5., player.p->dtimer / 10. );
386 double dis_ramp = ( dis_max - tc_base ) / dis_mod;
387
388 double time_left = player.p->dtimer - player.p->dtimer_accum;
389 /* Initial deadtime. */
390 if ( ( player.p->dtimer_accum < dis_dead ) || ( time_left < dis_dead ) )
391 tc_mod = tc_base;
392 else {
393 /* Ramp down. */
394 if ( time_left < dis_dead + ( dis_max - tc_base ) * dis_ramp / 2. +
395 tc_base * dis_ramp )
396 tc_mod = MAX( tc_base, tc_mod - dis_mod * dt );
397 /* Ramp up. */
398 else
399 tc_mod = MIN( dis_max, tc_mod + dis_mod * dt );
400 }
401 pause_setSpeed( tc_mod );
402 sound_setSpeed( tc_mod / player_dt_default() );
403 return;
404 }
405
406 /* Must be autonaving. */
407 if ( !player_isFlag( PLAYER_AUTONAV ) )
408 return;
409
410 NTracingZone( _ctx, 1 );
411
412 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_update );
413 lua_pushnumber( naevL, dt );
414 if ( nlua_pcall( autonav_env, 1, 0 ) ) {
415 WARN( "%s", lua_tostring( naevL, -1 ) );
416 lua_pop( naevL, 1 );
417 }
418
419 NTracingZoneEnd( _ctx );
420}
421
426{
427 /* Must be autonaving. */
428 if ( !player_isFlag( PLAYER_AUTONAV ) )
429 return;
430
431 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_enter );
432 if ( nlua_pcall( autonav_env, 0, 0 ) ) {
433 WARN( "%s", lua_tostring( naevL, -1 ) );
434 lua_pop( naevL, 1 );
435 }
436}
void ai_unsetPilot(AIMemory oldmem)
Finishes setting up a pilot.
Definition ai.c:428
void ai_thinkApply(Pilot *p)
Applies the result of thinking.
Definition ai.c:454
void ai_thinkSetup(double dt)
Sets up the pilot for thinking.
Definition ai.c:440
AIMemory ai_setPilot(Pilot *p)
Sets the pilot for further AI calls.
Definition ai.c:416
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
Definition gui.c:353
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:39
#define MAX(x, y)
Definition naev.h:37
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
Definition ndata.c:207
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
Definition nlua.c:914
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.
Definition nlua.c:1047
lua_State * naevL
Definition nlua.c:54
LuaPilot * lua_pushpilot(lua_State *L, LuaPilot pilot)
Pushes a pilot on the stack.
Definition nlua_pilot.c:576
LuaSpob * lua_pushspob(lua_State *L, LuaSpob spob)
Pushes a spob on the stack.
Definition nlua_spob.c:203
vec2 * lua_pushvector(lua_State *L, vec2 vec)
Pushes a vector on the stack.
Definition nlua_vec2.c:145
void pause_setSpeed(double mod)
Adjusts the game's dt modifier.
Definition pause.c:61
int paused
Definition pause.c:18
void pilot_hyperspaceAbort(Pilot *p)
Stops the pilot from hyperspacing.
Definition pilot.c:3140
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:640
int pilot_inRangePilot(const Pilot *p, const Pilot *target, double *dist2)
Check to see if a pilot is in sensor range of another.
Definition pilot_ew.c:256
void player_resetSpeed(void)
Resets the player speed stuff.
Definition player.c:1521
void player_hyperspacePreempt(int preempt)
Enables or disables jump points preempting spobs in autoface and target clearing.
Definition player.c:1980
double player_dt_default(void)
Returns the player's total default time delta based on time dilation stuff.
Definition player.c:2001
int player_getHypPreempt(void)
Returns whether the jump point target should preempt the spob target.
Definition player.c:1990
void player_restoreControl(int reason, const char *str)
Aborts autonav and other states that take control of the ship.
Definition player.c:1535
void player_accelOver(void)
Done accelerating.
Definition player.c:2220
Player_t player
Definition player.c:77
static int player_autonavSetup(void)
Prepares the player to enter autonav.
void player_autonavEnd(void)
Ends the autonav.
void player_autonavStartWindow(unsigned int wid, const char *str)
Starts autonav and closes the window.
void player_autonavPos(double x, double y)
Starts autonav with a local position destination.
int player_autonavInit(void)
Initialize the autonav code.
void player_autonavResetSpeed(void)
Resets the game speed.
void player_autonavStart(void)
Starts autonav.
void player_autonavReset(double s)
Resets the game speed without disabling autonav.
void player_autonavPil(unsigned int p)
Starts autonav with a pilot to follow.
static nlua_env autonav_env
void player_autonavBoard(unsigned int p)
Starts autonav with a pilot to board.
void player_autonavSpob(const char *name, int tryland)
Starts autonav with a spob destination.
void player_autonavEnter(void)
Signal to the autonav that a new system was entered.
void player_autonavAbort(const char *reason)
Aborts autonav.
void player_thinkAutonav(Pilot *pplayer, double dt)
Handles autonav thinking.
void player_updateAutonav(double dt)
Updates the player's autonav.
void sound_setSpeed(double s)
Sets the speed to play the sound at.
Definition sound.c:1158
Spob * spob_get(const char *spobname)
Gets a spob based on its name.
Definition space.c:1107
int spob_index(const Spob *p)
Gets the ID of a spob.
Definition space.c:1158
StarSystem * cur_system
Definition space.c:110
Represents a temporary pilot memory. For use with ai_setPilot and ai_unsetPilot.
Definition ai.h:59
The representation of an in-game pilot.
Definition pilot.h:263
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:102
Represents a 2d vector.
Definition vec2.h:45
void window_destroy(unsigned int wid)
Kills the window.
Definition toolkit.c:1039