naev 0.11.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"
15#include "player.h"
16
17#include "ai.h"
18#include "array.h"
19#include "board.h"
20#include "conf.h"
21#include "map.h"
22#include "pause.h"
23#include "pilot.h"
24#include "pilot_ew.h"
25#include "player.h"
26#include "map_overlay.h"
27#include "ndata.h"
28#include "nlua.h"
29#include "nlua_vec2.h"
30#include "nlua_pilot.h"
31#include "nlua_spob.h"
32#include "nlua_system.h"
33#include "sound.h"
34#include "space.h"
35#include "toolkit.h"
36
37static nlua_env autonav_env = LUA_NOREF;
38static int func_system = LUA_NOREF;
39static int func_spob = LUA_NOREF;
40static int func_pilot = LUA_NOREF;
41static int func_board = LUA_NOREF;
42static int func_pos = LUA_NOREF;
43static int func_reset = LUA_NOREF;
44static int func_end = LUA_NOREF;
45static int func_abort = LUA_NOREF;
46static int func_think = LUA_NOREF;
47static int func_update = LUA_NOREF;
48static int func_enter = LUA_NOREF;
49
50/*
51 * Prototypes.
52 */
53static int player_autonavSetup (void);
54
55int player_autonavInit (void)
56{
57 nlua_env env = nlua_newEnv();
58 nlua_loadStandard( env );
59 nlua_loadAI( env );
60
61 size_t bufsize;
62 char *buf = ndata_read( AUTONAV_PATH, &bufsize );
63 if (nlua_dobufenv(env, buf, bufsize, AUTONAV_PATH) != 0) {
64 WARN( _("Error loading file: %s\n"
65 "%s\n"
66 "Most likely Lua file has improper syntax, please check"),
67 AUTONAV_PATH, lua_tostring(naevL,-1));
68 free(buf);
69 return -1;
70 }
71 free(buf);
72 autonav_env = env;
73
74 func_system = nlua_refenvtype( env, "autonav_system", LUA_TFUNCTION );
75 func_spob = nlua_refenvtype( env, "autonav_spob", LUA_TFUNCTION );
76 func_pilot = nlua_refenvtype( env, "autonav_pilot", LUA_TFUNCTION );
77 func_board = nlua_refenvtype( env, "autonav_board", LUA_TFUNCTION );
78 func_pos = nlua_refenvtype( env, "autonav_pos", LUA_TFUNCTION );
79 func_reset = nlua_refenvtype( env, "autonav_reset", LUA_TFUNCTION );
80 func_end = nlua_refenvtype( env, "autonav_end", LUA_TFUNCTION );
81 func_abort = nlua_refenvtype( env, "autonav_abort", LUA_TFUNCTION );
82 func_think = nlua_refenvtype( env, "autonav_think", LUA_TFUNCTION );
83 func_update = nlua_refenvtype( env, "autonav_update", LUA_TFUNCTION );
84 func_enter = nlua_refenvtype( env, "autonav_enter", LUA_TFUNCTION );
85
86 return 0;
87}
88
96
101{
102 /* Not under manual control or disabled. */
103 if (pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) ||
104 pilot_isDisabled(player.p))
105 return;
106
107 if ((player.p->nav_hyperspace == -1) && (player.p->nav_spob== -1))
108 return;
109 else if ((player.p->nav_spob != -1) && !player_getHypPreempt()) {
110 player_autonavSpob( cur_system->spobs[ player.p->nav_spob ]->name, 0 );
111 return;
112 }
113
115 player_message("#r%s#0",_("Not enough fuel to jump for autonav."));
116 return;
117 }
118
119 if (pilot_isFlag( player.p, PILOT_NOJUMP)) {
120 player_message("#r%s#0",_("Hyperspace drive is offline."));
121 return;
122 }
123
125 return;
126
127 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_system );
128 if (nlua_pcall( autonav_env, 0, 0 )) {
129 WARN("%s",lua_tostring(naevL,-1));
130 lua_pop(naevL, 1);
131 }
132 player.autonav = AUTONAV_JUMP;
133}
134
140static int player_autonavSetup (void)
141{
142 /* Not under manual control or disabled. */
143 if (pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) ||
144 pilot_isDisabled(player.p))
145 return -1;
146
147 /* Autonav is mutually-exclusive with other autopilot methods. */
148 player_restoreControl( PINPUT_AUTONAV, NULL );
149 player_setFlag(PLAYER_AUTONAV);
150
151 return 0;
152}
153
154static int autonav_ending = 0;
159{
160 /* Don't allow recursive end chaining. */
161 if (autonav_ending)
162 return;
163
164 autonav_ending = 1;
165 player_rmFlag(PLAYER_AUTONAV);
166 ovr_autonavClear();
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
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
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}
232
236void player_autonavPil( unsigned int p )
237{
238 const Pilot *pilot = pilot_get( p );
239 int inrange = pilot_inRangePilot( player.p, pilot, NULL );
240 if (player_autonavSetup() || !inrange)
241 return;
242
243 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_pilot );
244 lua_pushpilot( naevL, p );
245 if (nlua_pcall( autonav_env, 1, 0 )) {
246 WARN("%s",lua_tostring(naevL,-1));
247 lua_pop(naevL, 1);
248 }
249 player.autonav = AUTONAV_PILOT;
250}
251
255void player_autonavBoard( unsigned int p )
256{
257 const Pilot *pilot = pilot_get( p );
258 int inrange = pilot_inRangePilot( player.p, pilot, NULL );
259 if (player_autonavSetup() || !inrange)
260 return;
261
262 /* Detected fuzzy, can't board. */
263 if (inrange!=1) {
265 return;
266 }
267
268 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_board );
269 lua_pushpilot( naevL, p );
270 if (nlua_pcall( autonav_env, 1, 0 )) {
271 WARN("%s",lua_tostring(naevL,-1));
272 lua_pop(naevL, 1);
273 }
274 player.autonav = AUTONAV_PILOT;
275}
276
282void player_autonavAbort( const char *reason )
283{
284 /* No point if player is beyond aborting. */
285 if ((player.p==NULL) || pilot_isFlag(player.p, PILOT_HYPERSPACE))
286 return;
287
288 /* Not under autonav. */
289 if (!player_isFlag(PLAYER_AUTONAV))
290 return;
291
292 /* Cooldown (handled later) may be script-initiated and we don't
293 * want to make it player-abortable while under manual control. */
294 if (pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ))
295 return;
296
297 /* Run Lua function. */
298 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_abort );
299 if (reason != NULL)
300 lua_pushstring( naevL, reason );
301 else
302 lua_pushnil( naevL );
303 if (nlua_pcall( autonav_env, 1, 0 )) {
304 WARN("%s",lua_tostring(naevL,-1));
305 lua_pop(naevL, 1);
306 }
307
308 /* Break possible hyperspacing. */
309 if (pilot_isFlag(player.p, PILOT_HYP_PREP)) {
311 player_message("#o%s#0",_("Autonav: aborting hyperspace sequence."));
312 }
313}
314
315void player_autonavReset( double s )
316{
317 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_reset );
318 lua_pushnumber( naevL, s );
319 if (nlua_pcall( autonav_env, 1, 0 )) {
320 WARN("%s",lua_tostring(naevL,-1));
321 lua_pop(naevL, 1);
322 }
323}
324
331void player_thinkAutonav( Pilot *pplayer, double dt )
332{
333 AIMemory oldmem;
334
335 ai_thinkSetup( dt );
336 oldmem = ai_setPilot( pplayer ); /* Uses AI functionality. */
337 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_think );
338 lua_pushnumber( naevL, dt );
339 if (nlua_pcall( autonav_env, 1, 0 )) {
340 WARN("%s",lua_tostring(naevL,-1));
341 lua_pop(naevL, 1);
342 }
343 ai_unsetPilot( oldmem );
344 ai_thinkApply( pplayer );
345}
346
352void player_updateAutonav( double dt )
353{
354 const double dis_dead = 1.0; /* Time it takes to start ramping up. */
355 const double dis_mod = 2.0;
356 //const double dis_max = 5.0;
357 //const double dis_ramp = 3.0;
358
359 if (paused || (player.p==NULL) ||
360 pilot_isFlag(player.p, PILOT_DEAD) ||
361 player_isFlag( PLAYER_CINEMATICS ))
362 return;
363
364 /* TODO maybe handle in autonav? */
365 /* We handle disabling here. */
366 if (pilot_isFlag(player.p, PILOT_DISABLED)) {
367 static double tc_mod = 1.0;
368 /* It is somewhat like:
369 * /------------\ 4x
370 * / \
371 * -----/ \----- 1x
372 *
373 * <---><-><----------><-><--->
374 * 5 6 X 6 5 Real time
375 * 5 15 X 15 5 Game time
376 *
377 * For triangles we have to add the rectangle and triangle areas.
378 */
379 double tc_base = player_dt_default() * player.speed;
380 double dis_max = MAX( 5., player.p->dtimer / 10. );
381 double dis_ramp = (dis_max-tc_base) / dis_mod;
382
383 double time_left = player.p->dtimer - player.p->dtimer_accum;
384 /* Initial deadtime. */
385 if ((player.p->dtimer_accum < dis_dead) || (time_left < dis_dead))
386 tc_mod = tc_base;
387 else {
388 /* Ramp down. */
389 if (time_left < dis_dead + (dis_max-tc_base)*dis_ramp/2. + tc_base*dis_ramp)
390 tc_mod = MAX( tc_base, tc_mod - dis_mod*dt );
391 /* Ramp up. */
392 else
393 tc_mod = MIN( dis_max, tc_mod + dis_mod*dt );
394 }
395 pause_setSpeed( tc_mod );
396 sound_setSpeed( tc_mod / player_dt_default() );
397 return;
398 }
399
400 /* Must be autonaving. */
401 if (!player_isFlag(PLAYER_AUTONAV))
402 return;
403
404 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_update );
405 lua_pushnumber( naevL, dt );
406 if (nlua_pcall( autonav_env, 1, 0 )) {
407 WARN("%s",lua_tostring(naevL,-1));
408 lua_pop(naevL, 1);
409 }
410}
411
412void player_autonavEnter (void)
413{
414 /* Must be autonaving. */
415 if (!player_isFlag(PLAYER_AUTONAV))
416 return;
417
418 lua_rawgeti( naevL, LUA_REGISTRYINDEX, func_enter );
419 if (nlua_pcall( autonav_env, 0, 0 )) {
420 WARN("%s",lua_tostring(naevL,-1));
421 lua_pop(naevL, 1);
422 }
423}
void ai_unsetPilot(AIMemory oldmem)
Finishes setting up a pilot.
Definition ai.c:426
void ai_thinkApply(Pilot *p)
Applies the result of thinking.
Definition ai.c:452
void ai_thinkSetup(double dt)
Sets up the pilot for thinking.
Definition ai.c:438
AIMemory ai_setPilot(Pilot *p)
Sets the pilot for further AI calls.
Definition ai.c:414
Provides macros to work with dynamic arrays.
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
Definition gui.c:335
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:40
#define MAX(x, y)
Definition naev.h:39
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
Definition ndata.c:154
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
Definition nlua.c:798
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:920
LuaPilot * lua_pushpilot(lua_State *L, LuaPilot pilot)
Pushes a pilot on the stack.
Definition nlua_pilot.c:563
LuaSpob * lua_pushspob(lua_State *L, LuaSpob spob)
Pushes a spob on the stack.
Definition nlua_spob.c:201
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:64
int paused
Definition pause.c:21
void pilot_hyperspaceAbort(Pilot *p)
Stops the pilot from hyperspacing.
Definition pilot.c:2857
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:620
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:244
void player_resetSpeed(void)
Resets the player speed stuff.
Definition player.c:1448
void player_hyperspacePreempt(int preempt)
Enables or disables jump points preempting spobs in autoface and target clearing.
Definition player.c:1893
double player_dt_default(void)
Returns the player's total default time delta based on time dilation stuff.
Definition player.c:1913
int player_getHypPreempt(void)
Returns whether the jump point target should preempt the spob target.
Definition player.c:1903
void player_restoreControl(int reason, const char *str)
Aborts autonav and other states that take control of the ship.
Definition player.c:1461
void player_accelOver(void)
Done accelerating.
Definition player.c:2127
Player_t player
Definition player.c:74
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.
void player_autonavResetSpeed(void)
Resets the game speed.
void player_autonavStart(void)
Starts 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_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:1152
Spob * spob_get(const char *spobname)
Gets a spob based on its name.
Definition space.c:1051
int spob_index(const Spob *p)
Gets the ID of a spob.
Definition space.c:1099
StarSystem * cur_system
Definition space.c:106
Represents a temporary pilot memory. For use with ai_setPilot and ai_unsetPilot.
Definition ai.h:58
The representation of an in-game pilot.
Definition pilot.h:217
double dtimer
Definition pilot.h:373
double dtimer_accum
Definition pilot.h:374
int nav_hyperspace
Definition pilot.h:345
double fuel
Definition pilot.h:260
double fuel_consumption
Definition pilot.h:261
int nav_spob
Definition pilot.h:344
Pilot * p
Definition player.h:101
int autonav
Definition player.h:107
double speed
Definition player.h:110
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:89
Represents a 2d vector.
Definition vec2.h:32
void window_destroy(unsigned int wid)
Kills the window.
Definition toolkit.c:1037