naev 0.12.5
nlua_pilot.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
12#include "naev.h"
14
15#include "nlua_pilot.h"
16
17#include "ai.h"
18#include "array.h"
19#include "camera.h"
20#include "damagetype.h"
21#include "escort.h"
22#include "gui.h"
23#include "land_outfits.h"
24#include "map.h"
25#include "nlua.h"
26#include "nlua_asteroid.h"
27#include "nlua_canvas.h"
28#include "nlua_colour.h"
29#include "nlua_commodity.h"
30#include "nlua_faction.h"
31#include "nlua_jump.h"
32#include "nlua_outfit.h"
33#include "nlua_pilotoutfit.h"
34#include "nlua_ship.h"
35#include "nlua_spob.h"
36#include "nlua_system.h"
37#include "nlua_tex.h"
38#include "nlua_vec2.h"
39#include "nluadef.h"
40#include "pilot.h"
41#include "pilot_heat.h"
42#include "player.h"
43#include "player_autonav.h"
44#include "rng.h"
45#include "space.h"
46#include "weapon.h"
47
48/*
49 * From ai.c
50 */
51extern Pilot *cur_pilot;
52
53/*
54 * Prototypes.
55 */
56static int pilotL_getFriendOrFoe( lua_State *L, int friend );
57static Task *pilotL_newtask( lua_State *L, Pilot *p, const char *task );
58static int outfit_compareActive( const void *slot1, const void *slot2 );
59static int pilotL_setFlagWrapper( lua_State *L, int flag );
60static int pilot_outfitAddSlot( Pilot *p, const Outfit *o, PilotOutfitSlot *s,
61 int bypass_cpu, int bypass_slot );
62static int luaL_checkweapset( lua_State *L, int idx );
63static PilotOutfitSlot *luaL_checkslot( lua_State *L, Pilot *p, int idx );
64
65/* Pilot metatable methods. */
66static int pilotL_add( lua_State *L );
67static int pilotL_clone( lua_State *L );
68static int pilotL_remove( lua_State *L );
69static int pilotL_explode( lua_State *L );
70static int pilotL_clear( lua_State *L );
71static int pilotL_clearSelect( lua_State *L );
72static int pilotL_canSpawn( lua_State *L );
73static int pilotL_toggleSpawn( lua_State *L );
74static int pilotL_getPilots( lua_State *L );
75static int pilotL_getAllies( lua_State *L );
76static int pilotL_getEnemies( lua_State *L );
77static int pilotL_getVisible( lua_State *L );
78static int pilotL_getInrange( lua_State *L );
79static int pilotL_eq( lua_State *L );
80static int pilotL_tostring( lua_State *L );
81static int pilotL_name( lua_State *L );
82static int pilotL_id( lua_State *L );
83static int pilotL_exists( lua_State *L );
84static int pilotL_target( lua_State *L );
85static int pilotL_setTarget( lua_State *L );
86static int pilotL_targetAsteroid( lua_State *L );
87static int pilotL_setTargetAsteroid( lua_State *L );
88static int pilotL_inrange( lua_State *L );
89static int pilotL_scandone( lua_State *L );
90static int pilotL_withPlayer( lua_State *L );
91static int pilotL_nav( lua_State *L );
92static int pilotL_navSpob( lua_State *L );
93static int pilotL_navJump( lua_State *L );
94static int pilotL_navJumpSet( lua_State *L );
95static int pilotL_autoweap( lua_State *L );
96static int pilotL_weapset( lua_State *L );
97static int pilotL_weapsetList( lua_State *L );
98static int pilotL_weapsetType( lua_State *L );
99static int pilotL_weapsetAdd( lua_State *L );
100static int pilotL_weapsetAddType( lua_State *L );
101static int pilotL_weapsetRm( lua_State *L );
102static int pilotL_weapsetCleanup( lua_State *L );
103static int pilotL_weapsetHeat( lua_State *L );
104static int pilotL_weapsetSetInrange( lua_State *L );
105static int pilotL_weapsetAmmo( lua_State *L );
106static int pilotL_weapsetAuto( lua_State *L );
107static int pilotL_actives( lua_State *L );
108static int pilotL_outfitsList( lua_State *L );
109static int pilotL_outfits( lua_State *L );
110static int pilotL_outfitsEquip( lua_State *L );
111static int pilotL_outfitGet( lua_State *L );
112static int pilotL_outfitToggle( lua_State *L );
113static int pilotL_outfitReady( lua_State *L );
114static int pilotL_rename( lua_State *L );
115static int pilotL_position( lua_State *L );
116static int pilotL_velocity( lua_State *L );
117static int pilotL_isStopped( lua_State *L );
118static int pilotL_dir( lua_State *L );
119static int pilotL_signature( lua_State *L );
120static int pilotL_temp( lua_State *L );
121static int pilotL_mass( lua_State *L );
122static int pilotL_accel( lua_State *L );
123static int pilotL_speed( lua_State *L );
124static int pilotL_speed_max( lua_State *L );
125static int pilotL_turn( lua_State *L );
126static int pilotL_faction( lua_State *L );
127static int pilotL_reputation( lua_State *L );
128static int pilotL_areEnemies( lua_State *L );
129static int pilotL_areAllies( lua_State *L );
130static int pilotL_spaceworthy( lua_State *L );
131static int pilotL_setPosition( lua_State *L );
132static int pilotL_setVelocity( lua_State *L );
133static int pilotL_setDir( lua_State *L );
134static int pilotL_broadcast( lua_State *L );
135static int pilotL_comm( lua_State *L );
136static int pilotL_setFaction( lua_State *L );
137static int pilotL_setHostile( lua_State *L );
138static int pilotL_setFriendly( lua_State *L );
139static int pilotL_setInvincible( lua_State *L );
140static int pilotL_setInvincPlayer( lua_State *L );
141static int pilotL_setHide( lua_State *L );
142static int pilotL_setInvisible( lua_State *L );
143static int pilotL_setNoRender( lua_State *L );
144static int pilotL_setVisplayer( lua_State *L );
145static int pilotL_setVisible( lua_State *L );
146static int pilotL_setHilight( lua_State *L );
147static int pilotL_setBribed( lua_State *L );
148static int pilotL_getColour( lua_State *L );
149static int pilotL_colourChar( lua_State *L );
150static int pilotL_getHostile( lua_State *L );
151static int pilotL_flags( lua_State *L );
152static int pilotL_hasIllegal( lua_State *L );
153static int pilotL_setActiveBoard( lua_State *L );
154static int pilotL_setNoDeath( lua_State *L );
155static int pilotL_disabled( lua_State *L );
156static int pilotL_disable( lua_State *L );
157static int pilotL_setDisable( lua_State *L );
158static int pilotL_cooldown( lua_State *L );
159static int pilotL_setCooldown( lua_State *L );
160static int pilotL_cooldownCycle( lua_State *L );
161static int pilotL_setNoJump( lua_State *L );
162static int pilotL_setNoLand( lua_State *L );
163static int pilotL_setNoClear( lua_State *L );
164static int pilotL_outfitAdd( lua_State *L );
165static int pilotL_outfitRm( lua_State *L );
166static int pilotL_outfitSlot( lua_State *L );
167static int pilotL_outfitAddSlot( lua_State *L );
168static int pilotL_outfitRmSlot( lua_State *L );
169static int pilotL_outfitAddIntrinsic( lua_State *L );
170static int pilotL_outfitRmIntrinsic( lua_State *L );
171static int pilotL_getFuel( lua_State *L );
172static int pilotL_setFuel( lua_State *L );
173static int pilotL_intrinsicReset( lua_State *L );
174static int pilotL_intrinsicSet( lua_State *L );
175static int pilotL_intrinsicGet( lua_State *L );
176static int pilotL_shippropReset( lua_State *L );
177static int pilotL_shippropSet( lua_State *L );
178static int pilotL_shippropGet( lua_State *L );
179static int pilotL_effectClear( lua_State *L );
180static int pilotL_effectAdd( lua_State *L );
181static int pilotL_effectRm( lua_State *L );
182static int pilotL_effectHas( lua_State *L );
183static int pilotL_effectGet( lua_State *L );
184static int pilotL_ai( lua_State *L );
185static int pilotL_changeAI( lua_State *L );
186static int pilotL_setTemp( lua_State *L );
187static int pilotL_setHealth( lua_State *L );
188static int pilotL_setHealthAbs( lua_State *L );
189static int pilotL_addHealth( lua_State *L );
190static int pilotL_setEnergy( lua_State *L );
191static int pilotL_addEnergy( lua_State *L );
192static int pilotL_fillAmmo( lua_State *L );
193static int pilotL_setNoBoard( lua_State *L );
194static int pilotL_setNoDisable( lua_State *L );
195static int pilotL_setSpeedLimit( lua_State *L );
196static int pilotL_getHealth( lua_State *L );
197static int pilotL_getArmour( lua_State *L );
198static int pilotL_getShield( lua_State *L );
199static int pilotL_getStress( lua_State *L );
200static int pilotL_getEnergy( lua_State *L );
201static int pilotL_getLockon( lua_State *L );
202static int pilotL_getStats( lua_State *L );
203static int pilotL_getShipStat( lua_State *L );
204static int pilotL_getDetectedDistance( lua_State *L );
205static int pilotL_cargoFree( lua_State *L );
206static int pilotL_cargoHas( lua_State *L );
207static int pilotL_cargoAdd( lua_State *L );
208static int pilotL_cargoRm( lua_State *L );
209static int pilotL_cargoJet( lua_State *L );
210static int pilotL_cargoList( lua_State *L );
211static int pilotL_credits( lua_State *L );
212static int pilotL_worth( lua_State *L );
213static int pilotL_ship( lua_State *L );
214static int pilotL_points( lua_State *L );
215static int pilotL_radius( lua_State *L );
216static int pilotL_idle( lua_State *L );
217static int pilotL_control( lua_State *L );
218static int pilotL_memory( lua_State *L );
219static int pilotL_shipmemory( lua_State *L );
220static int pilotL_ainame( lua_State *L );
221static int pilotL_task( lua_State *L );
222static int pilotL_taskname( lua_State *L );
223static int pilotL_taskstack( lua_State *L );
224static int pilotL_taskdata( lua_State *L );
225static int pilotL_taskclear( lua_State *L );
226static int pilotL_pushtask( lua_State *L );
227static int pilotL_poptask( lua_State *L );
228static int pilotL_refuel( lua_State *L );
229static int pilotL_moveto( lua_State *L );
230static int pilotL_face( lua_State *L );
231static int pilotL_brake( lua_State *L );
232static int pilotL_follow( lua_State *L );
233static int pilotL_attack( lua_State *L );
234static int pilotL_board( lua_State *L );
235static int pilotL_runaway( lua_State *L );
236static int pilotL_gather( lua_State *L );
237static int pilotL_canHyperspace( lua_State *L );
238static int pilotL_hyperspace( lua_State *L );
239static int pilotL_stealth( lua_State *L );
240static int pilotL_tryStealth( lua_State *L );
241static int pilotL_destealth( lua_State *L );
242static int pilotL_land( lua_State *L );
243static int pilotL_hailPlayer( lua_State *L );
244static int pilotL_msg( lua_State *L );
245static int pilotL_mothership( lua_State *L );
246static int pilotL_leader( lua_State *L );
247static int pilotL_setLeader( lua_State *L );
248static int pilotL_followers( lua_State *L );
249static int pilotL_hookClear( lua_State *L );
250static int pilotL_choosePoint( lua_State *L );
251static int pilotL_collisionTest( lua_State *L );
252static int pilotL_damage( lua_State *L );
253static int pilotL_kill( lua_State *L );
254static int pilotL_knockback( lua_State *L );
255static int pilotL_distress( lua_State *L );
256static int pilotL_calcStats( lua_State *L );
257static int pilotL_shipvarPeek( lua_State *L );
258static int pilotL_shipvarPush( lua_State *L );
259static int pilotL_shipvarPop( lua_State *L );
260static int pilotL_renderComm( lua_State *L );
261static int pilotL_render( lua_State *L );
262static int pilotL_renderTo( lua_State *L );
263
264static const luaL_Reg pilotL_methods[] = {
265 /* General. */
266 { "add", pilotL_add },
267 { "clone", pilotL_clone },
268 { "rm", pilotL_remove },
269 { "explode", pilotL_explode },
270 { "get", pilotL_getPilots },
271 { "getAllies", pilotL_getAllies },
272 { "getEnemies", pilotL_getEnemies },
273 { "getVisible", pilotL_getVisible },
274 { "getInrange", pilotL_getInrange },
275 { "__eq", pilotL_eq },
276 { "__tostring", pilotL_tostring },
277 /* Info. */
278 { "name", pilotL_name },
279 { "id", pilotL_id },
280 { "exists", pilotL_exists },
281 { "target", pilotL_target },
282 { "setTarget", pilotL_setTarget },
283 { "targetAsteroid", pilotL_targetAsteroid },
284 { "setTargetAsteroid", pilotL_setTargetAsteroid },
285 { "inrange", pilotL_inrange },
286 { "scandone", pilotL_scandone },
287 { "withPlayer", pilotL_withPlayer },
288 { "nav", pilotL_nav },
289 { "navSpob", pilotL_navSpob },
290 { "navJump", pilotL_navJump },
291 { "navJumpSet", pilotL_navJumpSet },
292 { "autoweap", pilotL_autoweap },
293 { "weapset", pilotL_weapset },
294 { "weapsetList", pilotL_weapsetList },
295 { "weapsetType", pilotL_weapsetType },
296 { "weapsetAdd", pilotL_weapsetAdd },
297 { "weapsetAddType", pilotL_weapsetAddType },
298 { "weapsetRm", pilotL_weapsetRm },
299 { "weapsetCleanup", pilotL_weapsetCleanup },
300 { "weapsetHeat", pilotL_weapsetHeat },
301 { "weapsetSetInrange", pilotL_weapsetSetInrange },
302 { "weapsetAmmo", pilotL_weapsetAmmo },
303 { "weapsetAuto", pilotL_weapsetAuto },
304 { "actives", pilotL_actives },
305 { "outfitsList", pilotL_outfitsList },
306 { "outfits", pilotL_outfits },
307 { "outfitsEquip", pilotL_outfitsEquip },
308 { "outfitGet", pilotL_outfitGet },
309 { "outfitToggle", pilotL_outfitToggle },
310 { "outfitReady", pilotL_outfitReady },
311 { "rename", pilotL_rename },
312 { "pos", pilotL_position },
313 { "vel", pilotL_velocity },
314 { "isStopped", pilotL_isStopped },
315 { "dir", pilotL_dir },
316 { "signature", pilotL_signature },
317 { "temp", pilotL_temp },
318 { "mass", pilotL_mass },
319 { "accel", pilotL_accel },
320 { "speed", pilotL_speed },
321 { "speedMax", pilotL_speed_max },
322 { "turn", pilotL_turn },
323 { "cooldown", pilotL_cooldown },
324 { "faction", pilotL_faction },
325 { "reputation", pilotL_reputation },
326 { "areEnemies", pilotL_areEnemies },
327 { "areAllies", pilotL_areAllies },
328 { "spaceworthy", pilotL_spaceworthy },
329 { "health", pilotL_getHealth },
330 { "armour", pilotL_getArmour },
331 { "shield", pilotL_getShield },
332 { "stress", pilotL_getStress },
333 { "energy", pilotL_getEnergy },
334 { "lockon", pilotL_getLockon },
335 { "stats", pilotL_getStats },
336 { "shipstat", pilotL_getShipStat },
337 { "detectedDistance", pilotL_getDetectedDistance },
338 { "colour", pilotL_getColour },
339 { "colourChar", pilotL_colourChar },
340 { "hostile", pilotL_getHostile },
341 { "flags", pilotL_flags },
342 { "hasIllegal", pilotL_hasIllegal },
343 /* System. */
344 { "clear", pilotL_clear },
345 { "clearSelect", pilotL_clearSelect },
346 { "canSpawn", pilotL_canSpawn },
347 { "toggleSpawn", pilotL_toggleSpawn },
348 /* Modify. */
349 { "ai", pilotL_ai },
350 { "changeAI", pilotL_changeAI },
351 { "setTemp", pilotL_setTemp },
352 { "setHealth", pilotL_setHealth },
353 { "setHealthAbs", pilotL_setHealthAbs },
354 { "addHealth", pilotL_addHealth },
355 { "setEnergy", pilotL_setEnergy },
356 { "addEnergy", pilotL_addEnergy },
357 { "fillAmmo", pilotL_fillAmmo },
358 { "setNoBoard", pilotL_setNoBoard },
359 { "setNoDisable", pilotL_setNoDisable },
360 { "setSpeedLimit", pilotL_setSpeedLimit },
361 { "setPos", pilotL_setPosition },
362 { "setVel", pilotL_setVelocity },
363 { "setDir", pilotL_setDir },
364 { "setFaction", pilotL_setFaction },
365 { "setHostile", pilotL_setHostile },
366 { "setFriendly", pilotL_setFriendly },
367 { "setInvincible", pilotL_setInvincible },
368 { "setInvincPlayer", pilotL_setInvincPlayer },
369 { "setHide", pilotL_setHide },
370 { "setInvisible", pilotL_setInvisible },
371 { "setNoRender", pilotL_setNoRender },
372 { "setVisplayer", pilotL_setVisplayer },
373 { "setVisible", pilotL_setVisible },
374 { "setHilight", pilotL_setHilight },
375 { "setBribed", pilotL_setBribed },
376 { "setActiveBoard", pilotL_setActiveBoard },
377 { "setNoDeath", pilotL_setNoDeath },
378 { "disabled", pilotL_disabled },
379 { "disable", pilotL_disable },
380 { "setDisable", pilotL_setDisable },
381 { "setCooldown", pilotL_setCooldown },
382 { "cooldownCycle", pilotL_cooldownCycle },
383 { "setNoJump", pilotL_setNoJump },
384 { "setNoLand", pilotL_setNoLand },
385 { "setNoClear", pilotL_setNoClear },
386 /* Talk. */
387 { "broadcast", pilotL_broadcast },
388 { "comm", pilotL_comm },
389 /* Outfits. */
390 { "outfitAdd", pilotL_outfitAdd },
391 { "outfitRm", pilotL_outfitRm },
392 { "outfitSlot", pilotL_outfitSlot },
393 { "outfitAddSlot", pilotL_outfitAddSlot },
394 { "outfitRmSlot", pilotL_outfitRmSlot },
395 { "outfitAddIntrinsic", pilotL_outfitAddIntrinsic },
396 { "outfitRmIntrinsic", pilotL_outfitRmIntrinsic },
397 { "fuel", pilotL_getFuel },
398 { "setFuel", pilotL_setFuel },
399 { "intrinsicReset", pilotL_intrinsicReset },
400 { "intrinsicSet", pilotL_intrinsicSet },
401 { "intrinsicGet", pilotL_intrinsicGet },
402 { "shippropReset", pilotL_shippropReset },
403 { "shippropSet", pilotL_shippropSet },
404 { "shippropGet", pilotL_shippropGet },
405 { "effectClear", pilotL_effectClear },
406 { "effectAdd", pilotL_effectAdd },
407 { "effectRm", pilotL_effectRm },
408 { "effects", pilotL_effectGet },
409 { "effectHas", pilotL_effectHas },
410 /* Ship. */
411 { "ship", pilotL_ship },
412 { "radius", pilotL_radius },
413 { "points", pilotL_points },
414 /* Cargo and moolah. */
415 { "cargoFree", pilotL_cargoFree },
416 { "cargoHas", pilotL_cargoHas },
417 { "cargoAdd", pilotL_cargoAdd },
418 { "cargoRm", pilotL_cargoRm },
419 { "cargoJet", pilotL_cargoJet },
420 { "cargoList", pilotL_cargoList },
421 { "credits", pilotL_credits },
422 { "worth", pilotL_worth },
423 /* Manual AI control. */
424 { "idle", pilotL_idle },
425 { "control", pilotL_control },
426 { "memory", pilotL_memory },
427 { "shipMemory", pilotL_shipmemory },
428 { "ainame", pilotL_ainame },
429 { "task", pilotL_task },
430 { "taskname", pilotL_taskname },
431 { "taskstack", pilotL_taskstack },
432 { "taskdata", pilotL_taskdata },
433 { "taskClear", pilotL_taskclear },
434 { "pushtask", pilotL_pushtask },
435 { "poptask", pilotL_poptask },
436 { "refuel", pilotL_refuel },
437 { "moveto", pilotL_moveto },
438 { "face", pilotL_face },
439 { "brake", pilotL_brake },
440 { "follow", pilotL_follow },
441 { "attack", pilotL_attack },
442 { "board", pilotL_board },
443 { "runaway", pilotL_runaway },
444 { "gather", pilotL_gather },
445 { "canHyperspace", pilotL_canHyperspace },
446 { "hyperspace", pilotL_hyperspace },
447 { "stealth", pilotL_stealth },
448 { "tryStealth", pilotL_tryStealth },
449 { "destealth", pilotL_destealth },
450 { "land", pilotL_land },
451 /* Misc. */
452 { "hailPlayer", pilotL_hailPlayer },
453 { "msg", pilotL_msg },
454 { "mothership", pilotL_mothership },
455 { "leader", pilotL_leader },
456 { "setLeader", pilotL_setLeader },
457 { "followers", pilotL_followers },
458 { "hookClear", pilotL_hookClear },
459 { "choosePoint", pilotL_choosePoint },
460 { "collisionTest", pilotL_collisionTest },
461 { "damage", pilotL_damage },
462 { "kill", pilotL_kill },
463 { "knockback", pilotL_knockback },
464 { "distress", pilotL_distress },
465 { "calcStats", pilotL_calcStats },
466 { "shipvarPeek", pilotL_shipvarPeek },
467 { "shipvarPush", pilotL_shipvarPush },
468 { "shipvarPop", pilotL_shipvarPop },
469 { "renderComm", pilotL_renderComm },
470 { "render", pilotL_render },
471 { "renderTo", pilotL_renderTo },
472 { 0, 0 },
473};
474
481int nlua_loadPilot( nlua_env env )
482{
483 nlua_register( env, PILOT_METATABLE, pilotL_methods, 1 );
484
485 /* Pilot always loads ship and asteroid. */
486 nlua_loadShip( env );
487 nlua_loadAsteroid( env );
488
489 return 0;
490}
491
495static int pilotL_setFlagWrapper( lua_State *L, int flag )
496{
497 int state;
498 Pilot *p = luaL_validpilot( L, 1 );
499
500 /* Get state. */
501 if ( lua_isnone( L, 2 ) )
502 state = 1;
503 else
504 state = lua_toboolean( L, 2 );
505
506 /* Set or remove the flag. */
507 if ( state )
508 pilot_setFlag( p, flag );
509 else
510 pilot_rmFlag( p, flag );
511
512 return 0;
513}
514
535LuaPilot lua_topilot( lua_State *L, int ind )
536{
537 return *( (LuaPilot *)lua_touserdata( L, ind ) );
538}
539
546LuaPilot luaL_checkpilot( lua_State *L, int ind )
547{
548 if ( lua_ispilot( L, ind ) )
549 return lua_topilot( L, ind );
550 luaL_typerror( L, ind, PILOT_METATABLE );
551 return 0;
552}
553
560Pilot *luaL_validpilot( lua_State *L, int ind )
561{
562 Pilot *p = pilot_get( luaL_checkpilot( L, ind ) );
563 if ( p == NULL ) {
564 NLUA_ERROR( L, _( "Pilot is invalid." ) );
565 return NULL;
566 }
567 return p;
568}
569
576LuaPilot *lua_pushpilot( lua_State *L, LuaPilot pilot )
577{
578 LuaPilot *p = (LuaPilot *)lua_newuserdata( L, sizeof( LuaPilot ) );
579 *p = pilot;
580 luaL_getmetatable( L, PILOT_METATABLE );
581 lua_setmetatable( L, -2 );
582 return p;
583}
584
591int lua_ispilot( lua_State *L, int ind )
592{
593 int ret;
594
595 if ( lua_getmetatable( L, ind ) == 0 )
596 return 0;
597 lua_getfield( L, LUA_REGISTRYINDEX, PILOT_METATABLE );
598
599 ret = 0;
600 if ( lua_rawequal( L, -1, -2 ) ) /* does it have the correct mt? */
601 ret = 1;
602
603 lua_pop( L, 2 ); /* remove both metatables */
604 return ret;
605}
606
618static int pilotL_choosePoint( lua_State *L )
619{
620 LuaFaction lf;
621 int ignore_rules, guerilla;
622 Spob *spob = NULL;
623 JumpPoint *jump = NULL;
624 vec2 vp;
625
626 /* Parameters. */
627 lf = luaL_validfaction( L, 1 );
628 ignore_rules = lua_toboolean( L, 2 );
629 guerilla = lua_toboolean( L, 3 );
630
631 pilot_choosePoint( &vp, &spob, &jump, lf, ignore_rules, guerilla );
632
633 if ( spob != NULL )
634 lua_pushspob( L, spob->id );
635 else if ( jump != NULL )
636 lua_pushsystem( L, jump->from->id );
637 else
638 lua_pushvector( L, vp );
639
640 return 1;
641}
642
683static int pilotL_add( lua_State *L )
684{
685 const Ship *ship;
686 const char *pilotname, *ai;
687 double a, r;
688 vec2 vv, vp, vn;
689 LuaFaction lf;
690 StarSystem *ss;
691 Spob *spob;
692 JumpPoint *jump;
693 PilotFlags flags;
694 int ignore_rules;
695 Pilot *p;
696
697 /* Default values. */
698 pilot_clearFlagsRaw( flags );
699 vectnull( &vn ); /* Need to determine angle. */
700 ss = NULL;
701 jump = NULL;
702 spob = NULL;
703 a = 0.;
704
705 /* Parse first argument - Ship Name */
706 ship = luaL_validship( L, 1 );
707 /* Get faction from string or number. */
708 lf = luaL_validfaction( L, 2 );
709 /* Get pilotname argument if provided. */
710 pilotname = luaL_optstring( L, 4, _( ship->name ) );
711
712 /* Handle position/origin argument. */
713 if ( lua_isvector( L, 3 ) ) {
714 vp = *lua_tovector( L, 3 );
715 a = RNGF() * 2. * M_PI;
716 vectnull( &vv );
717 } else if ( lua_issystem( L, 3 ) )
718 ss = system_getIndex( lua_tosystem( L, 3 ) );
719 else if ( lua_isjump( L, 3 ) )
720 ss = system_getIndex( lua_tojump( L, 3 )->destid );
721 else if ( lua_isspob( L, 3 ) ) {
722 spob = luaL_validspob( L, 3 );
723 pilot_setFlagRaw( flags, PILOT_TAKEOFF );
724 a = RNGF() * 2. * M_PI;
725 r = RNGF() * spob->radius;
726 vec2_cset( &vp, spob->pos.x + r * cos( a ), spob->pos.y + r * sin( a ) );
727 a = RNGF() * 2. * M_PI;
728 vectnull( &vv );
729 }
730 /* Random. */
731 else if ( lua_isnoneornil( L, 3 ) ) {
732 /* Check if we should ignore the strict rules. */
733 ignore_rules = 0;
734 if ( lua_isboolean( L, 3 ) && lua_toboolean( L, 3 ) )
735 ignore_rules = 1;
736
737 /* Choose the spawn point and act in consequence.*/
738 pilot_choosePoint( &vp, &spob, &jump, lf, ignore_rules, 0 );
739
740 if ( spob != NULL ) {
741 pilot_setFlagRaw( flags, PILOT_TAKEOFF );
742 a = RNGF() * 2. * M_PI;
743 r = RNGF() * spob->radius;
744 vec2_cset( &vp, spob->pos.x + r * cos( a ),
745 spob->pos.y + r * sin( a ) );
746 }
747 a = RNGF() * 2. * M_PI;
748 vectnull( &vv );
749 } else
750 NLUA_INVALID_PARAMETER( L, 3 );
751
752 /* Handle system. */
753 if ( ss != NULL ) {
754 for ( int i = 0; i < array_size( cur_system->jumps ); i++ ) {
755 if ( ( cur_system->jumps[i].target == ss ) &&
756 !jp_isFlag( cur_system->jumps[i].returnJump, JP_EXITONLY ) ) {
757 jump = cur_system->jumps[i].returnJump;
758 break;
759 }
760 }
761 if ( jump == NULL ) {
762 if ( array_size( cur_system->jumps ) > 0 ) {
763 NLUA_WARN(
764 L,
765 _( "Ship '%s' jumping in from non-adjacent system '%s' to "
766 "'%s'." ),
767 pilotname, ss->name, cur_system->name );
768 jump =
770 ->jumps[RNG_BASE( 0, array_size( cur_system->jumps ) - 1 )]
771 .returnJump;
772 } else
773 NLUA_WARN(
774 L,
775 _( "Ship '%s' attempting to jump in from '%s', but '%s' has "
776 "no jump points." ),
777 pilotname, ss->name, cur_system->name );
778 }
779 }
780
781 /* Parse final argument - table of optional parameters */
782 ai = NULL;
783 if ( lua_gettop( L ) >= 5 && !lua_isnil( L, 5 ) ) {
784 if ( !lua_istable( L, 5 ) )
785 return NLUA_ERROR(
786 L, _( "'parameters' should be a table of options or omitted!" ) );
787 lua_getfield( L, 5, "ai" );
788 ai = luaL_optstring( L, -1, NULL );
789 lua_pop( L, 1 );
790
791 lua_getfield( L, 5, "naked" );
792 if ( lua_toboolean( L, -1 ) )
793 pilot_setFlagRaw( flags, PILOT_NO_OUTFITS );
794 lua_pop( L, 1 );
795
796 lua_getfield( L, 5, "stealth" );
797 if ( lua_toboolean( L, -1 ) )
798 pilot_setFlagRaw( flags, PILOT_STEALTH );
799 lua_pop( L, 1 );
800 }
801
802 /* Set up velocities and such. */
803 if ( jump != NULL ) {
804 space_calcJumpInPos( cur_system, jump->from, &vp, &vv, &a, NULL );
805 pilot_setFlagRaw( flags, PILOT_HYP_END );
806 }
807
808 /* Make sure angle is valid. */
809 a = angle_clean( a );
810
811 /* Create the pilot. */
812 p = pilot_create( ship, pilotname, lf, ai, a, &vp, &vv, flags, 0, 0 );
813 lua_pushpilot( L, p->id );
814 if ( jump == NULL ) {
815 ai_newtask( L, p, "idle_wait", 0, 1 );
816 p->timer[0] = p->tcontrol;
817 }
818
819 /* TODO don't have space_calcJumpInPos called twice when stealth creating. */
820 if ( ( jump != NULL ) && pilot_isFlagRaw( flags, PILOT_STEALTH ) ) {
821 space_calcJumpInPos( cur_system, jump->from, &p->solid.pos, &p->solid.vel,
822 &p->solid.dir, p );
823 }
824 return 1;
825}
826
834static int pilotL_clone( lua_State *L )
835{
836 const Pilot *p = luaL_validpilot( L, 1 );
837 LuaPilot lp = pilot_clone( p );
838 lua_pushpilot( L, lp );
839 return 1;
840}
841
852static int pilotL_remove( lua_State *L )
853{
854 Pilot *p = pilot_get( luaL_checkpilot( L, 1 ) );
855 if ( p == NULL )
856 return 0;
857
858 /* Player is destroyed. */
859 if ( pilot_isPlayer( p ) )
861
862 /* Deletes the pilot. */
863 pilot_delete( p );
864
865 return 0;
866}
867
881static int pilotL_explode( lua_State *L )
882{
883 Pilot *p = luaL_validpilot( L, 1 );
884
885 /* Run exploded hook that can be cancelled. */
886 pilot_setFlag( p, PILOT_EXPLODED );
887 pilot_runHook( p, PILOT_HOOK_EXPLODED );
888 if ( !pilot_isFlag( p, PILOT_EXPLODED ) ) {
889 lua_pushboolean( L, 0 );
890 return 1;
891 }
892
893 /* Player is destroyed. */
894 if ( pilot_isPlayer( p ) )
896
897 /* Deletes the pilot. */
898 pilot_delete( p );
899
900 lua_pushboolean( L, 1 );
901 return 0;
902}
903
904static void clearSelect( Pilot *const *pilot_stack, int f )
905{
906 for ( int i = 0; i < array_size( pilot_stack ); i++ ) {
907 Pilot *pi = pilot_stack[i];
908 if ( pilot_isFlag( pi, PILOT_DELETE ) || pilot_isFlag( pi, PILOT_DEAD ) ||
909 pilot_isFlag( pi, PILOT_HIDE ) )
910 continue;
911 if ( pi->faction != f )
912 continue;
913 pilot_delete( pi );
914 }
915}
926static int pilotL_clearSelect( lua_State *L )
927{
928 Pilot *const *pilot_stack = pilot_getAll();
929 if ( lua_istable( L, 1 ) ) {
930 lua_pushnil( L );
931 while ( lua_next( L, 1 ) != 0 ) {
932 clearSelect( pilot_stack, luaL_validfaction( L, -1 ) );
933 lua_pop( L, 1 );
934 }
935 lua_pop( L, 1 );
936 } else
937 clearSelect( pilot_stack, luaL_validfaction( L, 1 ) );
938
939 return 0;
940}
941
953static int pilotL_clear( lua_State *L )
954{
955 (void)L;
956 pilots_clear();
957 weapon_clear();
958 return 0;
959}
960
967static int pilotL_canSpawn( lua_State *L )
968{
969 lua_pushboolean( L, space_spawn );
970 return 1;
971}
972
973static void toggleSpawn( int f, int b )
974{
975 /* Find the faction and set. */
976 for ( int i = 0; i < array_size( cur_system->presence ); i++ ) {
977 if ( cur_system->presence[i].faction != f )
978 continue;
979 cur_system->presence[i].disabled = b;
980 break;
981 }
982}
1001static int pilotL_toggleSpawn( lua_State *L )
1002{
1003 int b = !lua_toboolean( L, 2 );
1004
1005 /* Setting it directly. */
1006 if ( !lua_isnoneornil( L, 1 ) ) {
1007 if ( lua_istable( L, 1 ) ) {
1008 lua_pushnil( L );
1009 while ( lua_next( L, 1 ) != 0 ) {
1010 toggleSpawn( luaL_validfaction( L, -1 ), b );
1011 lua_pop( L, 1 );
1012 }
1013 lua_pop( L, 1 );
1014 } else if ( lua_isfaction( L, 1 ) || lua_isstring( L, 1 ) )
1015 toggleSpawn( luaL_validfaction( L, 1 ), b );
1016 else if ( lua_isboolean( L, 1 ) )
1017 space_spawn = lua_toboolean( L, 1 );
1018 else
1019 NLUA_INVALID_PARAMETER( L, 1 );
1020 }
1021 /* Toggling. */
1022 else
1023 space_spawn = b;
1024
1025 lua_pushboolean( L, space_spawn );
1026 return 1;
1027}
1028
1045static int pilotL_getPilots( lua_State *L )
1046{
1047 int d = lua_toboolean( L, 2 ); /* Whether or not to get disabled. */
1048 Pilot *const *pilot_stack = pilot_getAll();
1049
1050 /* Check for belonging to faction. */
1051 if ( lua_istable( L, 1 ) || lua_isfaction( L, 1 ) ) {
1052 int *factions;
1053 if ( lua_isfaction( L, 1 ) ) {
1054 factions = array_create( int );
1055 array_push_back( &factions, lua_tofaction( L, 1 ) );
1056 } else {
1057 /* Get table length and preallocate. */
1058 factions = array_create_size( int, lua_objlen( L, 1 ) );
1059 /* Load up the table. */
1060 lua_pushnil( L );
1061 while ( lua_next( L, 1 ) != 0 ) {
1062 if ( lua_isfaction( L, -1 ) )
1063 array_push_back( &factions, lua_tofaction( L, -1 ) );
1064 lua_pop( L, 1 );
1065 }
1066 lua_pop( L, 1 );
1067 }
1068
1069 /* Now put all the matching pilots in a table. */
1070 lua_newtable( L );
1071 int k = 1;
1072 for ( int i = 0; i < array_size( pilot_stack ); i++ ) {
1073 for ( int j = 0; j < array_size( factions ); j++ ) {
1074 if ( ( pilot_stack[i]->faction == factions[j] ) &&
1075 ( d || !pilot_isDisabled( pilot_stack[i] ) ) &&
1076 !pilot_isFlag( pilot_stack[i], PILOT_DELETE ) ) {
1077 lua_pushpilot( L, pilot_stack[i]->id ); /* value */
1078 lua_rawseti( L, -2, k++ ); /* table[key] = value */
1079 }
1080 }
1081 }
1082
1083 /* clean up. */
1084 array_free( factions );
1085 } else if ( ( lua_isnil( L, 1 ) ) || ( lua_gettop( L ) == 0 ) ) {
1086 /* Now put all the matching pilots in a table. */
1087 lua_newtable( L );
1088 int k = 1;
1089 for ( int i = 0; i < array_size( pilot_stack ); i++ ) {
1090 if ( ( d || !pilot_isDisabled( pilot_stack[i] ) ) &&
1091 !pilot_isFlag( pilot_stack[i], PILOT_DELETE ) ) {
1092 lua_pushpilot( L, pilot_stack[i]->id ); /* value */
1093 lua_rawseti( L, -2, k++ ); /* table[key] = value */
1094 }
1095 }
1096 } else
1097 NLUA_INVALID_PARAMETER( L, 1 );
1098
1099 return 1;
1100}
1101
1102static int getFriendOrFoeTest( const Pilot *p, const Pilot *plt, int friend,
1103 double dd, int inrange, int dis, int fighters,
1104 const vec2 *v, LuaFaction lf )
1105{
1106 /* Check if dead. */
1107 if ( pilot_isFlag( plt, PILOT_DELETE ) )
1108 return 0;
1109
1110 /* Ignore self. */
1111 if ( ( p != NULL ) && ( p->id == plt->id ) )
1112 return 0;
1113
1114 /* Ignore fighters unless specified. */
1115 if ( !fighters && pilot_isFlag( plt, PILOT_CARRIED ) )
1116 return 0;
1117
1118 /* Check distance if necessary. */
1119 if ( ( dd >= 0. ) && vec2_dist2( &plt->solid.pos, v ) > dd )
1120 return 0;
1121
1122 /* Check if disabled. */
1123 if ( dis && pilot_isDisabled( plt ) )
1124 return 0;
1125
1126 /* Check appropriate faction. */
1127 if ( friend ) {
1128 if ( p == NULL ) {
1129 if ( !areAllies( lf, plt->faction ) )
1130 return 0;
1131 } else {
1132 if ( !pilot_areAllies( p, plt ) )
1133 return 0;
1134 }
1135 } else {
1136 if ( p == NULL ) {
1137 if ( !areEnemies( lf, plt->faction ) )
1138 return 0;
1139 } else {
1140 if ( inrange ) {
1141 if ( !pilot_validEnemy( p, plt ) )
1142 return 0;
1143 } else {
1144 if ( !pilot_areEnemies( p, plt ) )
1145 return 0;
1146 }
1147 }
1148 }
1149
1150 /* Need extra check for friends. */
1151 if ( ( p != NULL ) && inrange && friend ) {
1152 if ( !pilot_inRangePilot( p, plt, NULL ) )
1153 return 0;
1154 }
1155
1156 return 1;
1157}
1158
1159/*
1160 * Helper to get nearby friends or foes.
1161 */
1162static int pilotL_getFriendOrFoe( lua_State *L, int friend )
1163{
1164 int k;
1165 double dd;
1166 const Pilot *p;
1167 double dist;
1168 int inrange, dis, fighters;
1169 const vec2 *v;
1170 Pilot *const *pilot_stack;
1171 LuaFaction lf;
1172
1173 /* Check if using faction. */
1174 lf = -1;
1175 if ( lua_isfaction( L, 1 ) )
1176 lf = lua_tofaction( L, 1 );
1177 else if ( lua_isstring( L, 1 ) )
1178 lf = luaL_validfaction( L, 1 );
1179 /* Faction case. */
1180 if ( lf >= 0 ) {
1181 dist = luaL_optnumber( L, 2, -1. );
1182 v = luaL_checkvector( L, 3 );
1183 inrange = 0;
1184 dis = lua_toboolean( L, 5 );
1185 fighters = lua_toboolean( L, 6 );
1186 p = NULL;
1187 }
1188 /* Pilot case. */
1189 else {
1190 p = luaL_validpilot( L, 1 );
1191 dist = luaL_optnumber( L, 2, -1. );
1192 v = luaL_optvector( L, 3, &p->solid.pos );
1193 inrange = !lua_toboolean( L, 4 );
1194 dis = lua_toboolean( L, 5 );
1195 fighters = lua_toboolean( L, 6 );
1196 }
1197
1198 if ( dist > 0. )
1199 dd = pow2( dist );
1200 else
1201 dd = -1.;
1202
1203 /* Now put all the matching pilots in a table. */
1205 lua_newtable( L );
1206 k = 1;
1207 if ( dist >= 0. && dist < INFINITY ) {
1208 int x, y, r;
1209 const IntList *qt;
1210 x = round( v->x );
1211 y = round( v->y );
1212 r = ceil( dist );
1213 qt = pilot_collideQuery( x - r, y - r, x + r, y + r );
1214 for ( int i = 0; i < il_size( qt ); i++ ) {
1215 const Pilot *plt = pilot_stack[il_get( qt, i, 0 )];
1216
1217 if ( getFriendOrFoeTest( p, plt, friend, dd, inrange, dis, fighters, v,
1218 lf ) ) {
1219 lua_pushpilot( L, plt->id ); /* value */
1220 lua_rawseti( L, -2, k++ ); /* table[key] = value */
1221 }
1222 }
1223 } else {
1224 for ( int i = 0; i < array_size( pilot_stack ); i++ ) {
1225 const Pilot *plt = pilot_stack[i];
1226
1227 if ( getFriendOrFoeTest( p, plt, friend, dd, inrange, dis, fighters, v,
1228 lf ) ) {
1229 lua_pushpilot( L, plt->id ); /* value */
1230 lua_rawseti( L, -2, k++ ); /* table[key] = value */
1231 }
1232 }
1233 }
1234 return 1;
1235}
1236
1259static int pilotL_getAllies( lua_State *L )
1260{
1261 return pilotL_getFriendOrFoe( L, 1 );
1262}
1263
1285static int pilotL_getEnemies( lua_State *L )
1286{
1287 return pilotL_getFriendOrFoe( L, 0 );
1288}
1289
1305static int pilotL_getVisible( lua_State *L )
1306{
1307 int k;
1308 const Pilot *p = luaL_validpilot( L, 1 );
1309 int dis = lua_toboolean( L, 2 );
1310 Pilot *const *pilot_stack;
1311
1312 /* Now put all the matching pilots in a table. */
1314 lua_newtable( L );
1315 k = 1;
1316 for ( int i = 0; i < array_size( pilot_stack ); i++ ) {
1317 /* Check if dead. */
1318 if ( pilot_isFlag( pilot_stack[i], PILOT_DELETE ) )
1319 continue;
1320 /* Check if disabled. */
1321 if ( dis && pilot_isDisabled( pilot_stack[i] ) )
1322 continue;
1323 /* Check visibilitiy. */
1324 if ( !pilot_validTarget( p, pilot_stack[i] ) )
1325 continue;
1326
1327 lua_pushpilot( L, pilot_stack[i]->id ); /* value */
1328 lua_rawseti( L, -2, k++ ); /* table[key] = value */
1329 }
1330
1331 return 1;
1332}
1333
1346static int pilotL_getInrange( lua_State *L )
1347{
1348 int k;
1349 const vec2 *v = luaL_checkvector( L, 1 );
1350 double d = luaL_checknumber( L, 2 );
1351 int dis = lua_toboolean( L, 3 );
1352 int x, y, r;
1353 const IntList *qt;
1354 Pilot *const *pilot_stack = pilot_getAll();
1355
1356 d = pow2( d ); /* Square it. */
1357
1358 /* Now put all the matching pilots in a table. */
1359 x = round( v->x );
1360 y = round( v->y );
1361 r = ceil( d );
1362 qt = pilot_collideQuery( x - r, y - r, x + r, y + r );
1363 lua_newtable( L );
1364 k = 1;
1365 for ( int i = 0; i < il_size( qt ); i++ ) {
1366 Pilot *p = pilot_stack[il_get( qt, i, 0 )];
1367
1368 /* Check if dead. */
1369 if ( pilot_isFlag( p, PILOT_DELETE ) )
1370 continue;
1371 /* Check if hidden. */
1372 if ( pilot_isFlag( p, PILOT_HIDE ) )
1373 continue;
1374 /* Check if disabled. */
1375 if ( dis && pilot_isDisabled( p ) )
1376 continue;
1377
1378 /* Must be in range. */
1379 if ( vec2_dist2( v, &p->solid.pos ) > d )
1380 continue;
1381
1382 lua_pushpilot( L, p->id ); /* value */
1383 lua_rawseti( L, -2, k++ ); /* table[key] = value */
1384 }
1385
1386 return 1;
1387}
1388
1399static int pilotL_eq( lua_State *L )
1400{
1401 LuaPilot p1 = luaL_checkpilot( L, 1 );
1402 LuaPilot p2 = luaL_checkpilot( L, 2 );
1403 lua_pushboolean( L, p1 == p2 );
1404 return 1;
1405}
1406
1417static int pilotL_tostring( lua_State *L )
1418{
1419 LuaPilot lp = luaL_checkpilot( L, 1 );
1420 const Pilot *p = pilot_get( lp );
1421 if ( p != NULL )
1422 lua_pushstring( L, p->name );
1423 else
1424 lua_pushstring( L, "(inexistent pilot)" );
1425 return 1;
1426}
1427
1437static int pilotL_name( lua_State *L )
1438{
1439 const Pilot *p = luaL_validpilot( L, 1 );
1440 lua_pushstring( L, p->name );
1441 return 1;
1442}
1443
1454static int pilotL_id( lua_State *L )
1455{
1456 const Pilot *p = luaL_validpilot( L, 1 );
1457 lua_pushnumber( L, p->id );
1458 return 1;
1459}
1460
1472static int pilotL_exists( lua_State *L )
1473{
1474 int exists;
1475 const Pilot *p = pilot_get( luaL_checkpilot( L, 1 ) );
1476
1477 /* Must still be kicking and alive. */
1478 if ( p == NULL )
1479 exists = 0;
1480 else if ( pilot_isFlag( p, PILOT_DEAD ) || pilot_isFlag( p, PILOT_HIDE ) )
1481 exists = 0;
1482 else
1483 exists = 1;
1484
1485 /* Check if the pilot exists. */
1486 lua_pushboolean( L, exists );
1487 return 1;
1488}
1489
1500static int pilotL_target( lua_State *L )
1501{
1502 Pilot *p = luaL_validpilot( L, 1 );
1503 /* Must be valid. */
1504 if ( pilot_getTarget( p ) == NULL )
1505 return 0;
1506 /* Push target. */
1507 lua_pushpilot( L, p->target );
1508 return 1;
1509}
1510
1518static int pilotL_setTarget( lua_State *L )
1519{
1520 unsigned int t;
1521 Pilot *p = luaL_validpilot( L, 1 );
1522 if ( lua_isnoneornil( L, 2 ) )
1523 t = p->id;
1524 else
1525 t = luaL_validpilot( L, 2 )->id;
1526 if ( pilot_isPlayer( p ) )
1527 player_targetSet( t );
1528 else
1529 pilot_setTarget( p, t );
1530 return 0;
1531}
1532
1543static int pilotL_targetAsteroid( lua_State *L )
1544{
1545 LuaAsteroid_t la;
1546 const Pilot *p = luaL_validpilot( L, 1 );
1547 if ( p->nav_asteroid < 0 )
1548 return 0;
1549
1550 la.parent = p->nav_anchor;
1551 la.id = p->nav_asteroid;
1552 lua_pushasteroid( L, la );
1553 return 1;
1554}
1555
1563static int pilotL_setTargetAsteroid( lua_State *L )
1564{
1565 Pilot *p = luaL_validpilot( L, 1 );
1566 const LuaAsteroid_t *la = luaL_checkasteroid( L, 2 );
1567
1568 /* Set the target asteroid. */
1569 p->nav_anchor = la->parent;
1570 p->nav_asteroid = la->id;
1571
1572 /* Untarget pilot. */
1573 p->target = p->id;
1574 p->ptarget = NULL;
1575
1576 return 0;
1577}
1578
1594static int pilotL_inrange( lua_State *L )
1595{
1596 /* Parse parameters. */
1597 const Pilot *p = luaL_validpilot( L, 1 );
1598 if ( lua_ispilot( L, 2 ) ) {
1599 const Pilot *t = luaL_validpilot( L, 2 );
1600
1601 /* Check if in range. */
1602 int ret = pilot_inRangePilot( p, t, NULL );
1603 if ( ret == 1 ) { /* In range. */
1604 lua_pushboolean( L, 1 );
1605 lua_pushboolean( L, 1 );
1606 } else if ( ret == 0 ) { /* Not in range. */
1607 lua_pushboolean( L, 0 );
1608 lua_pushboolean( L, 0 );
1609 } else { /* Detected fuzzy. */
1610 lua_pushboolean( L, 1 );
1611 lua_pushboolean( L, 0 );
1612 }
1613 return 2;
1614 } else if ( lua_isasteroid( L, 2 ) ) {
1615 const LuaAsteroid_t *la = luaL_checkasteroid( L, 2 );
1616
1617 /* Check if in range. */
1618 lua_pushboolean( L, pilot_inRangeAsteroid( p, la->id, la->parent ) );
1619 lua_pushboolean( L, 1 );
1620 return 2;
1621 } else {
1622 const vec2 *v = luaL_checkvector( L, 2 );
1623 lua_pushboolean( L, pilot_inRange( p, v->x, v->y ) );
1624 lua_pushboolean( L, 1 );
1625 return 2;
1626 }
1627}
1628
1635static int pilotL_scandone( lua_State *L )
1636{
1637 Pilot *p = luaL_validpilot( L, 1 );
1638 if ( pilot_isPlayer( p ) ) {
1639 const Pilot *t = pilot_getTarget( p );
1640 lua_pushboolean( L, pilot_isFlag( t, PILOT_PLAYER_SCANNED ) );
1641 } else
1642 lua_pushboolean( L, pilot_ewScanCheck( p ) );
1643 return 1;
1644}
1645
1653static int pilotL_withPlayer( lua_State *L )
1654{
1655 const Pilot *p = luaL_validpilot( L, 1 );
1656 lua_pushboolean( L, pilot_isWithPlayer( p ) );
1657 return 1;
1658}
1659
1670static int pilotL_nav( lua_State *L )
1671{
1672 const Pilot *p = luaL_validpilot( L, 1 );
1673 if ( p->target == 0 )
1674 return 0;
1675
1676 /* Get spob target. */
1677 if ( p->nav_spob < 0 )
1678 lua_pushnil( L );
1679 else
1680 lua_pushspob( L, cur_system->spobs[p->nav_spob]->id );
1681
1682 /* Get hyperspace target. */
1683 if ( p->nav_hyperspace < 0 )
1684 lua_pushnil( L );
1685 else {
1686 LuaSystem ls = cur_system->jumps[p->nav_hyperspace].targetid;
1687 lua_pushsystem( L, ls );
1688 }
1689
1690 return 2;
1691}
1692
1700static int pilotL_navSpob( lua_State *L )
1701{
1702 const Pilot *p = luaL_validpilot( L, 1 );
1703
1704 /* Get spob target. */
1705 if ( p->nav_spob < 0 )
1706 lua_pushnil( L );
1707 else
1708 lua_pushspob( L, cur_system->spobs[p->nav_spob]->id );
1709
1710 return 1;
1711}
1712
1720static int pilotL_navJump( lua_State *L )
1721{
1722 const Pilot *p = luaL_validpilot( L, 1 );
1723
1724 /* Get hyperspace target. */
1725 if ( p->nav_hyperspace < 0 )
1726 lua_pushnil( L );
1727 else {
1728 LuaJump lj;
1729 lj.srcid = cur_system->id;
1730 lj.destid = cur_system->jumps[p->nav_hyperspace].targetid;
1731 lua_pushjump( L, lj );
1732 }
1733
1734 return 1;
1735}
1736
1745static int pilotL_navJumpSet( lua_State *L )
1746{
1747 Pilot *p = luaL_validpilot( L, 1 );
1748 int jumpid = -1;
1749 if ( !lua_isnoneornil( L, 2 ) ) {
1750 const LuaJump *lj = luaL_checkjump( L, 2 );
1751 if ( cur_system->id != lj->srcid )
1752 return NLUA_ERROR(
1753 L, _( "Jump source system doesn't match current system!" ) );
1754 /* jumpid = jp - cur_system->jumps; */
1755 for ( int i = 0; i < array_size( cur_system->jumps ); i++ )
1756 if ( cur_system->jumps[i].targetid == lj->destid ) {
1757 jumpid = i;
1758 break;
1759 }
1760 if ( jumpid < 0 )
1761 return NLUA_ERROR( L, _( "Jump destination system not found!" ) );
1762 }
1763
1764 if ( pilot_isPlayer( p ) ) {
1765 player_targetHyperspaceSet( jumpid, 0 );
1766 if ( jumpid < 0 )
1767 map_select( NULL, 0 );
1768 else
1769 map_select( cur_system->jumps[jumpid].target, 0 );
1770 } else
1771 p->nav_hyperspace = jumpid;
1772
1773 return 0;
1774}
1775
1781static int weapsetItem( lua_State *L, int *k, Pilot *p,
1782 const PilotOutfitSlot *slot, const Pilot *target )
1783{
1784 const Damage *dmg;
1785 const Outfit *o = slot->outfit;
1786 int is_lau, is_fb;
1787
1788 /* Check if we should add. */
1789 if ( o == NULL )
1790 return 0;
1791 is_lau = outfit_isLauncher( o );
1792 is_fb = outfit_isFighterBay( o );
1793
1794 /* Must be valid weapon. */
1795 if ( !( outfit_isBolt( o ) || outfit_isBeam( o ) || is_lau || is_fb ) )
1796 return 0;
1797
1798 /* Set up new item. */
1799 lua_pushnumber( L, ++( *k ) );
1800
1801 /* We'll store the data in a table. */
1802 lua_newtable( L );
1803
1804 /* Outfit. */
1805 lua_pushstring( L, "outfit" );
1806 lua_pushoutfit( L, slot->outfit );
1807 lua_rawset( L, -3 );
1808
1809 /* Beams require special handling. */
1810 if ( outfit_isBeam( o ) ) {
1811 double delay, firemod, enermod;
1812 int has_beamid;
1813 pilot_getRateMod( &firemod, &enermod, p, slot->outfit );
1814
1815 /* When firing, cooldown is always zero. When recharging,
1816 * it's the usual 0-1 readiness value. */
1817 lua_pushstring( L, "cooldown" );
1818 has_beamid = ( slot->u.beamid > 0 );
1819 if ( has_beamid )
1820 lua_pushnumber( L, 0. );
1821 else {
1822 delay = ( slot->timer / outfit_delay( o ) ) * firemod;
1823 lua_pushnumber( L, CLAMP( 0., 1., 1. - delay ) );
1824 }
1825 lua_rawset( L, -3 );
1826
1827 /* When firing, slot->timer represents the remaining duration. */
1828 lua_pushstring( L, "charge" );
1829 if ( has_beamid )
1830 lua_pushnumber( L, CLAMP( 0., 1., slot->timer / o->u.bem.duration ) );
1831 else
1832 lua_pushnumber( L, CLAMP( 0., 1., 1. - delay ) );
1833 lua_rawset( L, -3 );
1834 } else {
1835 double delay, firemod, enermod;
1836 /* Set cooldown. */
1837 lua_pushstring( L, "cooldown" );
1838 pilot_getRateMod( &firemod, &enermod, p, slot->outfit );
1839 delay = outfit_delay( slot->outfit ) * firemod;
1840 if ( delay > 0. )
1841 lua_pushnumber( L, CLAMP( 0., 1., 1. - slot->timer / delay ) );
1842 else
1843 lua_pushnumber( L, 1. );
1844 lua_rawset( L, -3 );
1845 }
1846
1847 /* Ammo quantity absolute. */
1848 if ( is_lau || is_fb ) {
1849 lua_pushstring( L, "left" );
1850 lua_pushnumber( L, slot->u.ammo.quantity );
1851 lua_rawset( L, -3 );
1852
1853 /* Ammo quantity relative. */
1854 lua_pushstring( L, "left_p" );
1855 lua_pushnumber( L, (double)slot->u.ammo.quantity /
1856 (double)pilot_maxAmmoO( p, slot->outfit ) );
1857 lua_rawset( L, -3 );
1858 }
1859
1860 /* Launcher lockon. */
1861 if ( is_lau ) {
1862 double t = slot->u.ammo.lockon_timer;
1863 lua_pushstring( L, "lockon" );
1864 if ( t <= 0. )
1865 lua_pushnumber( L, 1. );
1866 else
1867 lua_pushnumber( L, 1. - ( t / slot->outfit->u.lau.lockon ) );
1868 lua_rawset( L, -3 );
1869
1870 /* Is in arc. */
1871 /* TODO this is broken right now. */
1872 lua_pushstring( L, "in_arc" );
1873 lua_pushboolean( L, slot->u.ammo.in_arc );
1874 lua_rawset( L, -3 );
1875 }
1876
1877 lua_pushstring( L, "active" );
1878 lua_pushboolean( L, slot->flags & PILOTOUTFIT_ISON );
1879 lua_rawset( L, -3 );
1880
1881 /* Temperature. */
1882 lua_pushstring( L, "heat" );
1883 lua_pushnumber( L, pilot_heatFirePercent( slot->heat_T ) );
1884 lua_rawset( L, -3 );
1885
1886 /* Type. */
1887 lua_pushstring( L, "type" );
1888 lua_pushstring( L, outfit_getType( slot->outfit ) );
1889 lua_rawset( L, -3 );
1890
1891 /* First weapon set. */
1892 lua_pushinteger( L, slot->weapset + 1 );
1893 lua_setfield( L, -2, "weapset" );
1894
1895 /* Damage type. */
1896 dmg = outfit_damage( slot->outfit );
1897 if ( dmg != NULL ) {
1898 lua_pushstring( L, "dtype" );
1899 lua_pushstring( L, dtype_damageTypeToStr( dmg->type ) );
1900 lua_rawset( L, -3 );
1901 }
1902
1903 /* Track. */
1904 if ( outfit_isBolt( slot->outfit ) ) {
1905 lua_pushstring( L, "track" );
1906 if ( target != NULL )
1907 lua_pushnumber(
1908 L, pilot_ewWeaponTrack( p, target, slot->outfit->u.blt.trackmin,
1909 slot->outfit->u.blt.trackmax ) );
1910 else
1911 lua_pushnumber( L, -1 );
1912 lua_rawset( L, -3 );
1913 }
1914
1915 /* Add to table. */
1916 lua_rawset( L, -3 );
1917 return 1;
1918}
1919
1929static int pilotL_autoweap( lua_State *L )
1930{
1931 Pilot *p = luaL_validpilot( L, 1 );
1932 lua_pushboolean( L, p->autoweap );
1933 return 1;
1934}
1935
1976static int pilotL_weapset( lua_State *L )
1977{
1978 Pilot *p, *target;
1979 int id, all;
1980
1981 /* Parse parameters. */
1982 id = 0;
1983 p = luaL_validpilot( L, 1 );
1984 if ( lua_gettop( L ) > 1 ) {
1985 id = luaL_checkinteger( L, 2 ) - 1;
1986 id = CLAMP( 0, PILOT_WEAPON_SETS, id );
1987 all = 0;
1988 } else
1989 all = 1;
1990
1991 /* Get target. */
1992 target = ( p->target != p->id ) ? pilot_get( p->target ) : NULL;
1993
1994 /* Push name. */
1995 lua_pushstring( L, pilot_weapSetName( p, id ) );
1996
1997 /* Push set. */
1998 lua_newtable( L );
1999 if ( all ) {
2000 int k = 0;
2001 for ( int i = 0; i < array_size( p->outfits ); i++ ) {
2002 const PilotOutfitSlot *slot = p->outfits[i];
2003 weapsetItem( L, &k, p, slot, target );
2004 }
2005 } else {
2006 int k = 0;
2007 const PilotWeaponSetOutfit *po_list = pilot_weapSetList( p, id );
2008 for ( int i = 0; i < array_size( po_list ); i++ ) {
2009 const PilotOutfitSlot *slot = p->outfits[po_list[i].slotid];
2010 weapsetItem( L, &k, p, slot, target );
2011 }
2012 }
2013
2014 return 2;
2015}
2016
2017static int luaL_checkweapset( lua_State *L, int idx )
2018{
2019 int ws = luaL_checkinteger( L, idx ) - 1;
2020 if ( ( ws < 0 ) || ( ws > 9 ) )
2021 return NLUA_ERROR( L, _( "Invalid weapon set '%d'!" ), idx );
2022 return ws;
2023}
2024
2025static PilotOutfitSlot *luaL_checkslot( lua_State *L, Pilot *p, int idx )
2026{
2027 if ( lua_isnumber( L, idx ) ) {
2028 const int slotid = lua_tointeger( L, idx );
2029 if ( ( slotid < 1 ) || ( slotid > array_size( p->outfits ) ) ) {
2030 NLUA_ERROR(
2031 L,
2032 _( "Pilot '%s' with ship '%s' does not have a slot with id '%d'!" ),
2033 p->name, _( p->ship->name ), slotid );
2034 return NULL;
2035 }
2036 /* We have to convert from "Lua IDs" to "C" ids by subtracting 1. */
2037 return p->outfits[slotid - 1];
2038 }
2039
2040 const char *slotname = luaL_checkstring( L, idx );
2041 PilotOutfitSlot *s = pilot_getSlotByName( p, slotname );
2042 if ( s == NULL ) {
2043 NLUA_WARN(
2044 L, _( "Pilot '%s' with ship '%s' does not have named slot '%s'!" ),
2045 p->name, _( p->ship->name ), slotname );
2046 return NULL;
2047 }
2048 return s;
2049}
2050
2060static int pilotL_weapsetList( lua_State *L )
2061{
2062 const Pilot *p = luaL_validpilot( L, 1 );
2063 int id = luaL_checkweapset( L, 2 );
2064 const PilotWeaponSet *ws = &p->weapon_sets[id];
2065
2066 lua_newtable( L );
2067 for ( int i = 0; i < array_size( ws->slots ); i++ ) {
2068 lua_pushinteger( L, ws->slots[i].slotid + 1 );
2069 lua_rawseti( L, -2, i + 1 );
2070 }
2071 return 1;
2072}
2073
2083static int pilotL_weapsetType( lua_State *L )
2084{
2085 Pilot *p = luaL_validpilot( L, 1 );
2086 int id = luaL_checkweapset( L, 2 );
2087 const char *type = luaL_checkstring( L, 3 );
2088 int typeid;
2089 if ( strcmp( type, "toggle" ) == 0 )
2090 typeid = WEAPSET_TYPE_TOGGLE;
2091 else if ( strcmp( type, "hold" ) == 0 )
2092 typeid = WEAPSET_TYPE_HOLD;
2093 else
2094 return NLUA_ERROR( L, _( "Invalid weapon set type '%s'!" ), type );
2095 pilot_weapSetType( p, id, typeid );
2096 return 0;
2097}
2098
2108static int pilotL_weapsetAdd( lua_State *L )
2109{
2110 Pilot *p = luaL_validpilot( L, 1 );
2111 int id = luaL_checkweapset( L, 2 );
2112 const PilotOutfitSlot *o = luaL_checkslot( L, p, 3 );
2113 pilot_weapSetAdd( p, id, o );
2114 return 0;
2115}
2116
2126static int pilotL_weapsetAddType( lua_State *L )
2127{
2128 Pilot *p = luaL_validpilot( L, 1 );
2129 int id = luaL_checkweapset( L, 2 );
2130 const char *type = luaL_checkstring( L, 3 );
2131 for ( int i = 0; i < array_size( p->outfits ); i++ ) {
2132 PilotOutfitSlot *pos = p->outfits[i];
2133 if ( pos->outfit == NULL )
2134 continue;
2135 if ( ( strcmp( pos->outfit->name, type ) == 0 ) ||
2136 ( strcmp( outfit_getType( pos->outfit ), type ) == 0 ) ||
2137 ( strcmp( outfit_getTypeBroad( pos->outfit ), type ) == 0 ) )
2138 pilot_weapSetAdd( p, id, pos );
2139 }
2140 return 0;
2141}
2142
2152static int pilotL_weapsetRm( lua_State *L )
2153{
2154 Pilot *p = luaL_validpilot( L, 1 );
2155 int id = luaL_checkweapset( L, 2 );
2156 const PilotOutfitSlot *o = luaL_checkslot( L, p, 3 );
2157 pilot_weapSetRm( p, id, o );
2158 return 0;
2159}
2160
2170static int pilotL_weapsetCleanup( lua_State *L )
2171{
2172 Pilot *p = luaL_validpilot( L, 1 );
2173 if ( lua_isnoneornil( L, 2 ) ) {
2174 for ( int i = 0; i < PILOT_WEAPON_SETS; i++ )
2175 pilot_weapSetCleanup( p, i );
2176 } else {
2177 int id = luaL_checkweapset( L, 2 );
2178 pilot_weapSetCleanup( p, id );
2179 }
2180 return 0;
2181}
2182
2205static int pilotL_weapsetHeat( lua_State *L )
2206{
2207 Pilot *p;
2208 PilotWeaponSetOutfit *po_list;
2209 int n, id, all;
2210 double heat, heat_mean, heat_peak, nweapons;
2211
2212 /* Defaults. */
2213 heat_mean = 0.;
2214 heat_peak = 0.;
2215 nweapons = 0;
2216
2217 /* Parse parameters. */
2218 id = 0;
2219 p = luaL_validpilot( L, 1 );
2220 if ( lua_gettop( L ) > 1 ) {
2221 id = luaL_checkinteger( L, 2 ) - 1;
2222 id = CLAMP( 0, PILOT_WEAPON_SETS, id );
2223 all = 0;
2224 } else
2225 all = 1;
2226
2227 /* Push set. */
2228 po_list = all ? NULL : pilot_weapSetList( p, id );
2229 n = all ? array_size( p->outfits ) : array_size( po_list );
2230
2231 /* Iterate over weapons. */
2232 for ( int i = 0; i < n; i++ ) {
2233 /* Get base look ups. */
2234 PilotOutfitSlot *slot =
2235 all ? p->outfits[i] : p->outfits[po_list[i].slotid];
2236 const Outfit *o = slot->outfit;
2237 if ( o == NULL )
2238 continue;
2239
2240 /* Must be weapon. */
2241 if ( outfit_isMod( o ) || outfit_isAfterburner( o ) )
2242 continue;
2243
2244 nweapons++;
2245 heat = pilot_heatFirePercent( slot->heat_T );
2246 heat_mean += heat;
2247 if ( heat > heat_peak )
2248 heat_peak = heat;
2249 }
2250
2251 /* Post-process. */
2252 if ( nweapons > 0 )
2253 heat_mean /= nweapons;
2254
2255 lua_pushnumber( L, heat_mean );
2256 lua_pushnumber( L, heat_peak );
2257
2258 return 2;
2259}
2260
2270static int pilotL_weapsetSetInrange( lua_State *L )
2271{
2272 Pilot *p = luaL_validpilot( L, 1 );
2273 int inrange = lua_toboolean( L, 3 );
2274 if ( lua_isnoneornil( L, 2 ) ) {
2275 for ( int i = 0; i < PILOT_WEAPON_SETS; i++ )
2276 pilot_weapSetInrange( p, i, inrange );
2277 } else {
2278 int id = luaL_checkweapset( L, 2 );
2279 pilot_weapSetInrange( p, id, inrange );
2280 }
2281 return 0;
2282}
2283
2294static int pilotL_weapsetAmmo( lua_State *L )
2295{
2296 Pilot *p = luaL_validpilot( L, 1 );
2297 int id = luaL_checkinteger( L, 2 );
2298 lua_pushnumber( L, pilot_weapSetAmmo( p, id ) );
2299 return 1;
2300}
2301
2308static int pilotL_weapsetAuto( lua_State *L )
2309{
2310 Pilot *p = luaL_validpilot( L, 1 );
2311 pilot_weaponAuto( p );
2312 return 0;
2313}
2314
2350static int pilotL_actives( lua_State *L )
2351{
2352 Pilot *p;
2353 int k, sort;
2354 PilotOutfitSlot **outfits;
2355 const char *str;
2356 double d;
2357
2358 /* Parse parameters. */
2359 p = luaL_validpilot( L, 1 );
2360 sort = lua_toboolean( L, 2 );
2361
2362 k = 0;
2363 lua_newtable( L );
2364
2365 if ( sort ) {
2366 outfits = array_copy( PilotOutfitSlot *, p->outfits );
2367 qsort( outfits, array_size( outfits ), sizeof( PilotOutfitSlot * ),
2369 } else
2370 outfits = p->outfits;
2371
2372 for ( int i = 0; i < array_size( outfits ); i++ ) {
2373 /* Get active outfits. */
2374 PilotOutfitSlot *pos = outfits[i];
2375 if ( pos->outfit == NULL )
2376 continue;
2377 if ( !( pos->flags & PILOTOUTFIT_ACTIVE ) )
2378 continue;
2379 if ( outfit_isWeapon( pos->outfit ) && ( pos->weapset < 2 ) )
2380 continue;
2381
2382 /* See if there's a same configuration that is lower. */
2383 int skip = 0;
2384 for ( int j = 0; j < i; j++ ) {
2385 PilotOutfitSlot *posj = outfits[j];
2386 if ( posj->outfit != pos->outfit )
2387 continue;
2388 if ( posj->weapset != pos->weapset )
2389 continue;
2390 skip = 1;
2391 break;
2392 }
2393 if ( skip )
2394 continue;
2395
2396 /* Set up for creation. */
2397 lua_pushnumber( L, ++k );
2398 lua_newtable( L );
2399
2400 /* Outfit. */
2401 lua_pushstring( L, "outfit" );
2402 lua_pushoutfit( L, pos->outfit );
2403 lua_rawset( L, -3 );
2404
2405 /* Type. */
2406 lua_pushstring( L, "type" );
2407 lua_pushstring( L, outfit_getType( pos->outfit ) );
2408 lua_rawset( L, -3 );
2409
2410 /* Heat. */
2411 lua_pushstring( L, "heat" );
2412 lua_pushnumber( L, 1. - pilot_heatEfficiencyMod(
2413 pos->heat_T, pos->outfit->overheat_min,
2414 pos->outfit->overheat_max ) );
2415 lua_rawset( L, -3 );
2416
2417 lua_pushstring( L, "active" );
2418 lua_pushboolean( L, pos->flags & PILOTOUTFIT_ISON );
2419 lua_rawset( L, -3 );
2420
2421 /* Find the first weapon set containing the outfit, if any. */
2422 if ( outfits[i]->weapset != -1 ) {
2423 lua_pushstring( L, "weapset" );
2424 lua_pushnumber( L, outfits[i]->weapset + 1 );
2425 lua_rawset( L, -3 );
2426 }
2427
2428 /* State and timer. */
2429 switch ( pos->state ) {
2430 case PILOT_OUTFIT_OFF:
2431 str = "off";
2432 break;
2433 case PILOT_OUTFIT_WARMUP:
2434 str = "warmup";
2435 if ( !outfit_isMod( pos->outfit ) ||
2436 pos->outfit->lua_env == LUA_NOREF )
2437 d = 1.; /* TODO add warmup stuff to normal active outfits (not sure
2438 if necessary though. */
2439 else
2440 d = pos->progress;
2441 lua_pushstring( L, "warmup" );
2442 lua_pushnumber( L, d );
2443 lua_rawset( L, -3 );
2444 break;
2445 case PILOT_OUTFIT_ON:
2446 str = "on";
2447 if ( !outfit_isMod( pos->outfit ) ||
2448 pos->outfit->lua_env == LUA_NOREF ) {
2449 d = outfit_duration( pos->outfit );
2450 if ( d == 0. )
2451 d = 1.;
2452 else if ( !isinf( pos->stimer ) )
2453 d = pos->stimer / d;
2454 } else
2455 d = pos->progress;
2456 lua_pushstring( L, "duration" );
2457 lua_pushnumber( L, d );
2458 lua_rawset( L, -3 );
2459 break;
2460 case PILOT_OUTFIT_COOLDOWN:
2461 str = "cooldown";
2462 if ( !outfit_isMod( pos->outfit ) ||
2463 pos->outfit->lua_env == LUA_NOREF ) {
2464 d = outfit_cooldown( pos->outfit );
2465 if ( d > 0. && !isinf( pos->stimer ) )
2466 d = pos->stimer / d;
2467 } else
2468 d = pos->progress;
2469 lua_pushstring( L, "cooldown" );
2470 lua_pushnumber( L, d );
2471 lua_rawset( L, -3 );
2472 break;
2473 default:
2474 str = "unknown";
2475 break;
2476 }
2477 lua_pushstring( L, "state" );
2478 lua_pushstring( L, str );
2479 lua_rawset( L, -3 );
2480
2481 /* Set table in table. */
2482 lua_rawset( L, -3 );
2483 }
2484
2485 /* Clean up. */
2486 if ( sort )
2487 array_free( outfits );
2488
2489 return 1;
2490}
2491
2495static int outfit_compareActive( const void *slot1, const void *slot2 )
2496{
2497 const PilotOutfitSlot *s1, *s2;
2498 s1 = *(const PilotOutfitSlot **)slot1;
2499 s2 = *(const PilotOutfitSlot **)slot2;
2500
2501 /* Put unassigned outfits at the end. */
2502 if ( ( s1->weapset < 0 ) && ( s2->weapset >= 0 ) )
2503 return -1;
2504 else if ( ( s1->weapset >= 0 ) && ( s2->weapset < 0 ) )
2505 return +1;
2506
2507 /* Compare weapon set indexes. */
2508 if ( s1->weapset < s2->weapset )
2509 return +1;
2510 else if ( s1->weapset > s2->weapset )
2511 return -1;
2512
2513 /* Compare positions within the outfit array. */
2514 if ( s1->id < s2->id )
2515 return +1;
2516 else if ( s1->id > s2->id )
2517 return -1;
2518
2519 return 0;
2520}
2521
2534static int pilotL_outfitsList( lua_State *L )
2535{
2536 int normal = 1;
2537 int intrinsics = 0;
2538 const Pilot *p = luaL_validpilot( L, 1 );
2539 const char *type = luaL_optstring( L, 2, NULL );
2540 int skip_locked = lua_toboolean( L, 3 );
2541 OutfitSlotType ost = OUTFIT_SLOT_NULL;
2542
2543 /* Get type. */
2544 if ( type != NULL ) {
2545 if ( strcmp( type, "all" ) == 0 )
2546 intrinsics = 1;
2547 else if ( strcmp( type, "structure" ) == 0 )
2548 ost = OUTFIT_SLOT_STRUCTURE;
2549 else if ( strcmp( type, "utility" ) == 0 )
2550 ost = OUTFIT_SLOT_UTILITY;
2551 else if ( strcmp( type, "weapon" ) == 0 )
2552 ost = OUTFIT_SLOT_WEAPON;
2553 else if ( strcmp( type, "intrinsic" ) == 0 ) {
2554 intrinsics = 1;
2555 normal = 0;
2556 } else
2557 return NLUA_ERROR( L, _( "Unknown slot type '%s'" ), type );
2558 }
2559
2560 lua_newtable( L );
2561 int j = 1;
2562 if ( normal ) {
2563 for ( int i = 0; i < array_size( p->outfits ); i++ ) {
2564 /* Get outfit. */
2565 if ( p->outfits[i]->outfit == NULL )
2566 continue;
2567
2568 /* Only match specific type. */
2569 if ( ( ost != OUTFIT_SLOT_NULL ) &&
2570 ( p->outfits[i]->outfit->slot.type != ost ) )
2571 continue;
2572
2573 /* Skip locked. */
2574 if ( skip_locked && p->outfits[i]->sslot->locked )
2575 continue;
2576
2577 /* Set the outfit. */
2578 lua_pushoutfit( L, p->outfits[i]->outfit );
2579 lua_rawseti( L, -2, j++ );
2580 }
2581 }
2582 if ( intrinsics ) {
2583 for ( int i = 0; i < array_size( p->outfit_intrinsic ); i++ ) {
2584 lua_pushoutfit( L, p->outfit_intrinsic[i].outfit );
2585 lua_rawseti( L, -2, j++ );
2586 }
2587 }
2588
2589 return 1;
2590}
2591
2602static int pilotL_outfits( lua_State *L )
2603{
2604 const Pilot *p = luaL_validpilot( L, 1 );
2605 lua_newtable( L );
2606 for ( int i = 0; i < array_size( p->outfits ); i++ ) {
2607 if ( p->outfits[i]->outfit == NULL )
2608 lua_pushboolean( L, 0 );
2609 else
2610 lua_pushoutfit( L, p->outfits[i]->outfit );
2611 lua_rawseti( L, -2, i + 1 );
2612 }
2613 return 1;
2614}
2615
2627static int pilotL_outfitsEquip( lua_State *L )
2628{
2629 Pilot *p = luaL_validpilot( L, 1 );
2630 int ret = 0;
2631 /* Process outputs. */
2632 for ( int i = 1;; i++ ) {
2633 const Outfit *o;
2634 PilotOutfitSlot *s;
2635
2636 lua_rawgeti( L, 2, i );
2637 if ( lua_isnil( L, -1 ) ) {
2638 lua_pop( L, 1 );
2639 break;
2640 }
2641
2642 if ( i > array_size( p->outfits ) ) {
2643 NLUA_WARN(
2644 L,
2645 _( "Trying to equip more outfits than slots available on pilot "
2646 "'%s'!" ),
2647 p->name );
2648 lua_pop( L, 1 );
2649 break;
2650 }
2651
2652 /* No outfit. */
2653 if ( !lua_toboolean( L, -1 ) )
2654 continue;
2655
2656 o = luaL_validoutfit( L, -1 );
2657 s = p->outfits[i - 1];
2658 ret |= pilot_outfitAddSlot( p, o, s, 1, 1 );
2659
2660 lua_pop( L, 1 );
2661 }
2662 lua_pushboolean( L, !ret );
2663 return 1;
2664}
2665
2674static int pilotL_outfitGet( lua_State *L )
2675{
2676 /* Parse parameters */
2677 const Pilot *p = luaL_validpilot( L, 1 );
2678 int id = luaL_checkinteger( L, 2 ) - 1;
2679 if ( id < 0 || id >= array_size( p->outfits ) )
2680 return NLUA_ERROR( L, _( "Pilot '%s' outfit ID '%d' is out of range!" ),
2681 p->name, id );
2682
2683 if ( p->outfits[id]->outfit != NULL )
2684 lua_pushoutfit( L, p->outfits[id]->outfit );
2685 else
2686 lua_pushnil( L );
2687 return 1;
2688}
2689
2690static int outfitToggle( lua_State *L, Pilot *p, int id, int activate )
2691{
2692 if ( id < 0 || id >= array_size( p->outfits ) )
2693 return NLUA_ERROR( L, _( "Pilot '%s' outfit ID '%d' is out of range!" ),
2694 p->name, id );
2695
2696 PilotOutfitSlot *po = p->outfits[id];
2697 const Outfit *o = po->outfit;
2698
2699 /* Ignore NULL outfits. */
2700 if ( o == NULL )
2701 return 0;
2702
2703 if ( ( activate && ( po->state != PILOT_OUTFIT_OFF ) ) ||
2704 ( !activate && ( po->state != PILOT_OUTFIT_ON ) ) )
2705 return 0;
2706
2707 int ret = po->flags & PILOTOUTFIT_ISON_TOGGLE;
2708 if ( activate ) {
2709 po->flags |= PILOTOUTFIT_ISON_TOGGLE;
2710 return ret;
2711 } else {
2712 po->flags &= PILOTOUTFIT_ISON_TOGGLE;
2713 return !ret;
2714 }
2715}
2726static int pilotL_outfitToggle( lua_State *L )
2727{
2728 Pilot *p = luaL_validpilot( L, 1 );
2729 int activate = lua_toboolean( L, 3 );
2730 int n;
2731
2732 /* Can't do a thing. */
2733 if ( ( pilot_isDisabled( p ) ) || ( pilot_isFlag( p, PILOT_COOLDOWN ) ) )
2734 return 0;
2735
2736 if ( lua_istable( L, 2 ) ) {
2737 n = 0;
2738 lua_pushnil( L );
2739 while ( lua_next( L, 1 ) != 0 ) {
2740 n += outfitToggle( L, p, luaL_checkinteger( L, -1 ) - 1, activate );
2741 lua_pop( L, 1 );
2742 }
2743 lua_pop( L, 1 );
2744 } else
2745 n = outfitToggle( L, p, luaL_checkinteger( L, 2 ) - 1, activate );
2746
2747 /* See if we have to do updates. */
2748 if ( n > 0 )
2750
2751 lua_pushboolean( L, n );
2752 return 1;
2753}
2754
2763static int pilotL_outfitReady( lua_State *L )
2764{
2765 /* Parse parameters */
2766 const Pilot *p = luaL_validpilot( L, 1 );
2767 int id = luaL_checkinteger( L, 2 ) - 1;
2768 if ( id < 0 || id >= array_size( p->outfits ) )
2769 return NLUA_ERROR( L, _( "Pilot '%s' outfit ID '%d' is out of range!" ),
2770 p->name, id );
2771
2772 if ( p->outfits[id]->outfit != NULL )
2773 lua_pushboolean( L, p->outfits[id]->state == PILOT_OUTFIT_OFF );
2774 else
2775 lua_pushboolean( L, 0 );
2776 return 1;
2777}
2778
2788static int pilotL_rename( lua_State *L )
2789{
2790 /* Parse parameters */
2791 Pilot *p = luaL_validpilot( L, 1 );
2792 const char *name = luaL_checkstring( L, 2 );
2793
2794 /* Change name. */
2795 free( p->name );
2796 p->name = strdup( name );
2797
2798 return 0;
2799}
2800
2810static int pilotL_position( lua_State *L )
2811{
2812 const Pilot *p = luaL_validpilot( L, 1 );
2813 lua_pushvector( L, p->solid.pos );
2814 return 1;
2815}
2816
2826static int pilotL_velocity( lua_State *L )
2827{
2828 const Pilot *p = luaL_validpilot( L, 1 );
2829 lua_pushvector( L, p->solid.vel );
2830 return 1;
2831}
2832
2842static int pilotL_isStopped( lua_State *L )
2843{
2844 const Pilot *p = luaL_validpilot( L, 1 );
2845 lua_pushboolean( L, ( VMOD( p->solid.vel ) < MIN_VEL_ERR ) );
2846 return 1;
2847}
2848
2858static int pilotL_signature( lua_State *L )
2859{
2860 const Pilot *p = luaL_validpilot( L, 1 );
2861 lua_pushnumber( L, p->ew_signature );
2862 return 1;
2863}
2864
2874static int pilotL_dir( lua_State *L )
2875{
2876 const Pilot *p = luaL_validpilot( L, 1 );
2877 lua_pushnumber( L, p->solid.dir );
2878 return 1;
2879}
2880
2890static int pilotL_temp( lua_State *L )
2891{
2892 const Pilot *p = luaL_validpilot( L, 1 );
2893 lua_pushnumber( L, p->heat_T );
2894 return 1;
2895}
2896
2906static int pilotL_mass( lua_State *L )
2907{
2908 const Pilot *p = luaL_validpilot( L, 1 );
2909 lua_pushnumber( L, p->solid.mass );
2910 return 1;
2911}
2912
2920static int pilotL_accel( lua_State *L )
2921{
2922 const Pilot *p = luaL_validpilot( L, 1 );
2923 lua_pushnumber( L, p->accel );
2924 return 1;
2925}
2926
2936static int pilotL_speed( lua_State *L )
2937{
2938 const Pilot *p = luaL_validpilot( L, 1 );
2939 lua_pushnumber( L, p->speed );
2940 return 1;
2941}
2942
2951static int pilotL_speed_max( lua_State *L )
2952{
2953 const Pilot *p = luaL_validpilot( L, 1 );
2954 lua_pushnumber( L, solid_maxspeed( &p->solid, p->speed, p->accel ) );
2955 return 1;
2956}
2957
2965static int pilotL_turn( lua_State *L )
2966{
2967 const Pilot *p = luaL_validpilot( L, 1 );
2968 lua_pushnumber( L, p->turn * 180. / M_PI ); /* TODO use radians. */
2969 return 1;
2970}
2971
2981static int pilotL_faction( lua_State *L )
2982{
2983 const Pilot *p = luaL_validpilot( L, 1 );
2984 lua_pushfaction( L, p->faction );
2985 return 1;
2986}
2987
2995static int pilotL_reputation( lua_State *L )
2996{
2997 const Pilot *p = luaL_validpilot( L, 1 );
2998 lua_pushnumber( L, system_getReputation( cur_system, p->faction ) );
2999 return 1;
3000}
3001
3010static int pilotL_areEnemies( lua_State *L )
3011{
3012 const Pilot *p = luaL_validpilot( L, 1 );
3013 const Pilot *t = luaL_validpilot( L, 2 );
3014 lua_pushboolean( L, pilot_areEnemies( p, t ) );
3015 return 1;
3016}
3017
3026static int pilotL_areAllies( lua_State *L )
3027{
3028 const Pilot *p = luaL_validpilot( L, 1 );
3029 const Pilot *t = luaL_validpilot( L, 2 );
3030 lua_pushboolean( L, pilot_areAllies( p, t ) );
3031 return 1;
3032}
3033
3046static int pilotL_spaceworthy( lua_State *L )
3047{
3048 char message[STRMAX_SHORT];
3049 const Pilot *p = luaL_validpilot( L, 1 );
3050 int worthy = !pilot_reportSpaceworthy( p, message, sizeof( message ) );
3051 lua_pushboolean( L, worthy );
3052 lua_pushstring( L, message );
3053 return 2;
3054}
3055
3065static int pilotL_setPosition( lua_State *L )
3066{
3067 /* Parse parameters */
3068 Pilot *p = luaL_validpilot( L, 1 );
3069 const vec2 *vec = luaL_checkvector( L, 2 );
3070
3071 /* Insert skip in trail. */
3072 pilot_sample_trails( p, 1 );
3073
3074 /* Warp pilot to new position. */
3075 p->solid.pos = *vec;
3076
3077 /* Update if necessary. */
3078 if ( pilot_isPlayer( p ) )
3079 cam_update( 0. );
3080
3081 return 0;
3082}
3083
3093static int pilotL_setVelocity( lua_State *L )
3094{
3095 /* Parse parameters */
3096 Pilot *p = luaL_validpilot( L, 1 );
3097 const vec2 *vec = luaL_checkvector( L, 2 );
3098
3099 /* Warp pilot to new position. */
3100 p->solid.vel = *vec;
3101 return 0;
3102}
3103
3115static int pilotL_setDir( lua_State *L )
3116{
3117 /* Parse parameters */
3118 Pilot *p = luaL_validpilot( L, 1 );
3119 double d = luaL_checknumber( L, 2 );
3120
3121 /* Set direction. */
3122 p->solid.dir = angle_clean( d );
3123
3124 return 0;
3125}
3126
3144static int pilotL_broadcast( lua_State *L )
3145{
3146 /* Parse parameters. */
3147 if ( lua_isstring( L, 1 ) ) {
3148 const char *s = luaL_checkstring( L, 1 );
3149 const char *msg = luaL_checkstring( L, 2 );
3150 const char *col = luaL_optstring( L, 3, NULL );
3151
3152 player_message( _( "#%cBroadcast %s>#0 \"%s\"" ),
3153 ( ( col == NULL ) ? 'N' : col[0] ), s, msg );
3154 if ( player.p )
3155 pilot_setCommMsg( player.p, msg );
3156 } else {
3157 Pilot *p = luaL_validpilot( L, 1 );
3158 const char *msg = luaL_checkstring( L, 2 );
3159 int ignore_int = lua_toboolean( L, 3 );
3160
3161 /* Broadcast message. */
3162 pilot_broadcast( p, msg, ignore_int );
3163 }
3164
3165 return 0;
3166}
3167
3193static int pilotL_comm( lua_State *L )
3194{
3195 if ( lua_isstring( L, 1 ) ) {
3196 const char *s;
3197 const char *msg, *col;
3198 int raw;
3199
3200 if ( player.p == NULL )
3201 return 0;
3202
3203 /* Parse parameters. */
3204 s = luaL_checkstring( L, 1 );
3205 if ( lua_isstring( L, 2 ) ) {
3206 msg = luaL_checkstring( L, 2 );
3207 col = luaL_optstring( L, 3, NULL );
3208 raw = lua_toboolean( L, 4 );
3209 } else {
3210 LuaPilot target = luaL_checkpilot( L, 2 );
3211 if ( target != player.p->id )
3212 return 0;
3213 msg = luaL_checkstring( L, 3 );
3214 col = luaL_optstring( L, 4, NULL );
3215 raw = lua_toboolean( L, 5 );
3216 }
3217
3218 /* Broadcast message. */
3219 if ( raw )
3220 player_message( _( "#%c%s>#0 %s" ), ( ( col == NULL ) ? 'N' : col[0] ),
3221 s, msg );
3222 else
3223 player_message( _( "#%cComm %s>#0 \"%s\"" ),
3224 ( ( col == NULL ) ? 'N' : col[0] ), s, msg );
3225 if ( player.p )
3226 pilot_setCommMsg( player.p, msg );
3227 } else {
3228 Pilot *p;
3229 LuaPilot target;
3230 const char *msg;
3231 int ignore_int, raw;
3232
3233 /* Parse parameters. */
3234 p = luaL_validpilot( L, 1 );
3235 if ( lua_isstring( L, 2 ) ) {
3236 target = 0;
3237 msg = luaL_checkstring( L, 2 );
3238 ignore_int = lua_toboolean( L, 3 );
3239 raw = lua_toboolean( L, 4 );
3240 } else {
3241 target = luaL_checkpilot( L, 2 );
3242 msg = luaL_checkstring( L, 3 );
3243 ignore_int = lua_toboolean( L, 4 );
3244 raw = lua_toboolean( L, 5 );
3245 }
3246
3247 if ( player.p == NULL )
3248 return 0;
3249
3250 if ( !ignore_int && !pilot_inRangePilot( player.p, p, NULL ) )
3251 return 0;
3252
3253 /* Broadcast message. */
3254 if ( target == 0 || target == PLAYER_ID ) {
3255 char c = pilot_getFactionColourChar( p );
3256 if ( raw )
3257 player_message( _( "#%c%s>#0 %s" ), c, p->name, msg );
3258 else
3259 player_message( _( "#%cComm %s>#0 \"%s\"" ), c, p->name, msg );
3260
3261 /* Set comm message. */
3262 pilot_setCommMsg( p, msg );
3263 }
3264 }
3265 return 0;
3266}
3267
3278static int pilotL_setFaction( lua_State *L )
3279{
3280 /* Parse parameters. */
3281 Pilot *p = luaL_validpilot( L, 1 );
3282 int fid = luaL_validfaction( L, 2 );
3283 /* Set the new faction. */
3284 p->faction = fid;
3285 return 0;
3286}
3287
3298static int pilotL_setHostile( lua_State *L )
3299{
3300 /* Get the pilot. */
3301 Pilot *p = luaL_validpilot( L, 1 );
3302 int state;
3303
3304 /* Get state. */
3305 if ( lua_isnone( L, 2 ) )
3306 state = 1;
3307 else
3308 state = lua_toboolean( L, 2 );
3309
3310 /* Set as hostile. */
3311 if ( state )
3312 pilot_setHostile( p );
3313 else
3314 pilot_rmHostile( p );
3315
3316 return 0;
3317}
3318
3329static int pilotL_setFriendly( lua_State *L )
3330{
3331 /* Get the pilot. */
3332 Pilot *p = luaL_validpilot( L, 1 );
3333 int state;
3334
3335 /* Get state. */
3336 if ( lua_isnone( L, 2 ) )
3337 state = 1;
3338 else
3339 state = lua_toboolean( L, 2 );
3340
3341 /* Remove hostile and mark as friendly. */
3342 if ( state )
3343 pilot_setFriendly( p );
3344 /* Remove friendly flag. */
3345 else
3346 pilot_rmFriendly( p );
3347
3348 return 0;
3349}
3350
3362static int pilotL_setInvincible( lua_State *L )
3363{
3364 return pilotL_setFlagWrapper( L, PILOT_INVINCIBLE );
3365}
3366
3379static int pilotL_setInvincPlayer( lua_State *L )
3380{
3381 return pilotL_setFlagWrapper( L, PILOT_INVINC_PLAYER );
3382}
3383
3398static int pilotL_setHide( lua_State *L )
3399{
3400 return pilotL_setFlagWrapper( L, PILOT_HIDE );
3401}
3402
3413static int pilotL_setInvisible( lua_State *L )
3414{
3415 return pilotL_setFlagWrapper( L, PILOT_INVISIBLE );
3416}
3417
3428static int pilotL_setNoRender( lua_State *L )
3429{
3430 return pilotL_setFlagWrapper( L, PILOT_NORENDER );
3431}
3432
3445static int pilotL_setVisplayer( lua_State *L )
3446{
3447 return pilotL_setFlagWrapper( L, PILOT_VISPLAYER );
3448}
3449
3461static int pilotL_setVisible( lua_State *L )
3462{
3463 return pilotL_setFlagWrapper( L, PILOT_VISIBLE );
3464}
3465
3478static int pilotL_setHilight( lua_State *L )
3479{
3480 return pilotL_setFlagWrapper( L, PILOT_HILIGHT );
3481}
3482
3492static int pilotL_setBribed( lua_State *L )
3493{
3494 return pilotL_setFlagWrapper( L, PILOT_BRIBED );
3495}
3496
3506static int pilotL_setActiveBoard( lua_State *L )
3507{
3508 return pilotL_setFlagWrapper( L, PILOT_BOARDABLE );
3509}
3510
3518static int pilotL_disabled( lua_State *L )
3519{
3520 const Pilot *p = luaL_validpilot( L, 1 );
3521 lua_pushboolean( L, pilot_isDisabled( p ) );
3522 return 1;
3523}
3524
3534static int pilotL_setNoDeath( lua_State *L )
3535{
3536 return pilotL_setFlagWrapper( L, PILOT_NODEATH );
3537}
3538
3539/* TODO remove in 0.13.0 */
3540static int pilotL_disable( lua_State *L )
3541{
3542 NLUA_DEPRECATED( L, "disable" );
3543 return pilotL_setDisable( L );
3544}
3545
3556static int pilotL_setDisable( lua_State *L )
3557{
3558 /* Get the pilot. */
3559 Pilot *p = luaL_validpilot( L, 1 );
3560 int permanent = !lua_toboolean( L, 2 );
3561
3562 /* Disable the pilot. */
3563 p->shield = 0.;
3564 p->stress = p->armour;
3565 pilot_updateDisable( p, 0 );
3566
3567 if ( permanent )
3568 pilot_setFlag( p, PILOT_DISABLED_PERM );
3569 else
3570 pilot_rmFlag( p, PILOT_DISABLED_PERM );
3571
3572 return 0;
3573}
3574
3585static int pilotL_cooldown( lua_State *L )
3586{
3587 const Pilot *p = luaL_validpilot( L, 1 );
3588 lua_pushboolean( L, pilot_isFlag( p, PILOT_COOLDOWN ) );
3589 lua_pushboolean( L, pilot_isFlag( p, PILOT_COOLDOWN_BRAKE ) );
3590 return 2;
3591}
3592
3602static int pilotL_setCooldown( lua_State *L )
3603{
3604 /* Get the pilot. */
3605 Pilot *p = luaL_validpilot( L, 1 );
3606 int state;
3607
3608 /* Get state. */
3609 if ( lua_isnone( L, 2 ) )
3610 state = 1;
3611 else
3612 state = lua_toboolean( L, 2 );
3613
3614 /* Set status. */
3615 if ( state )
3616 pilot_cooldown( p, 1 );
3617 else
3618 pilot_cooldownEnd( p, NULL );
3619
3620 return 0;
3621}
3622
3629static int pilotL_cooldownCycle( lua_State *L )
3630{
3631 Pilot *p = luaL_validpilot( L, 1 );
3632 pilot_cooldown( p, 0 );
3633 p->ctimer = -1.;
3634 pilot_rmFlag( p, PILOT_COOLDOWN_BRAKE ); /* Should allow triggering. */
3635 pilot_cooldownEnd( p, NULL );
3636 return 0;
3637}
3638
3648static int pilotL_setNoJump( lua_State *L )
3649{
3650 return pilotL_setFlagWrapper( L, PILOT_NOJUMP );
3651}
3652
3662static int pilotL_setNoLand( lua_State *L )
3663{
3664 return pilotL_setFlagWrapper( L, PILOT_NOLAND );
3665}
3666
3676static int pilotL_setNoClear( lua_State *L )
3677{
3678 return pilotL_setFlagWrapper( L, PILOT_NOCLEAR );
3679}
3680
3687 int bypass_cpu, int bypass_slot )
3688{
3689 int ret;
3690
3691 /* Must not have outfit (excluding default) already. */
3692 if ( ( s->outfit != NULL ) && ( s->outfit != s->sslot->data ) )
3693 return 0;
3694
3695 /* Only do a basic check. */
3696 if ( bypass_slot ) {
3697 if ( !outfit_fitsSlotType( o, &s->sslot->slot ) )
3698 return 0;
3699 } else if ( bypass_cpu ) {
3700 if ( !outfit_fitsSlot( o, &s->sslot->slot ) )
3701 return 0;
3702 }
3703 /* Full check. */
3704 else {
3705 /* Must fit slot. */
3706 if ( !outfit_fitsSlot( o, &s->sslot->slot ) )
3707 return 0;
3708
3709 /* Test if can add outfit. */
3710 ret = pilot_addOutfitTest( p, o, s, 0 );
3711 if ( ret )
3712 return -1;
3713 }
3714
3715 /* Add outfit - already tested. */
3716 ret = pilot_addOutfitRaw( p, o, s );
3717 if ( ret == 0 ) {
3718 pilot_outfitLInit( p, s );
3719
3720 /* Add ammo if needed. */
3721 pilot_addAmmo( p, s, pilot_maxAmmoO( p, o ) );
3722 }
3723
3724 /* Update GUI if necessary. */
3725 if ( pilot_isPlayer( p ) )
3726 gui_setShip();
3727
3728 return 1;
3729}
3730
3752static int pilotL_outfitAdd( lua_State *L )
3753{
3754 Pilot *p;
3755 const Outfit *o;
3756 int q, added, bypass_cpu, bypass_slot, slotid;
3757
3758 /* Get parameters. */
3759 p = luaL_validpilot( L, 1 );
3760 o = luaL_validoutfit( L, 2 );
3761 q = luaL_optinteger( L, 3, 1 );
3762 bypass_cpu = lua_toboolean( L, 4 );
3763 bypass_slot = lua_toboolean( L, 5 );
3764
3765 /* Add outfit. */
3766 added = 0;
3767 slotid = -1;
3768 for ( int i = 0; i < array_size( p->outfits ); i++ ) {
3769 int ret;
3770 PilotOutfitSlot *s = p->outfits[i];
3771
3772 /* Must still have to add outfit. */
3773 if ( q <= 0 )
3774 break;
3775
3776 /* Do tests and try to add. */
3777 ret = pilot_outfitAddSlot( p, o, s, bypass_cpu, bypass_slot );
3778 if ( ret < 0 )
3779 break;
3780 else if ( ret == 0 )
3781 continue;
3782
3783 /* We added an outfit. */
3784 q--;
3785 added++;
3786 if ( slotid < 0 )
3787 slotid = i;
3788 }
3789
3790 /* Update stats. */
3791 if ( added > 0 ) {
3792 pilot_calcStats( p );
3793
3794 /* Update the weapon sets. */
3795 if ( p->autoweap )
3796 pilot_weaponAuto( p );
3797
3798 /* Update equipment window if operating on the player's pilot. */
3799 if ( player.p != NULL && player.p == p )
3801
3802 /* Update GUI if necessary. */
3803 if ( pilot_isPlayer( p ) )
3804 gui_setShip();
3805 }
3806
3807 lua_pushnumber( L, added );
3808 if ( slotid < 0 )
3809 return 1;
3810 lua_pushinteger( L, slotid + 1 );
3811 return 2;
3812}
3813
3823static int pilotL_outfitSlot( lua_State *L )
3824{
3825 Pilot *p = luaL_validpilot( L, 1 );
3826 const PilotOutfitSlot *s = luaL_checkslot( L, p, 2 );
3827 if ( s == NULL )
3828 return 0;
3829 if ( s->outfit ) {
3830 lua_pushoutfit( L, s->outfit );
3831 return 1;
3832 }
3833 return 0;
3834}
3835
3852static int pilotL_outfitAddSlot( lua_State *L )
3853{
3854 Pilot *p;
3855 const Outfit *o;
3856 int ret, added, bypass_cpu, bypass_slot;
3857 PilotOutfitSlot *s;
3858
3859 /* Get parameters. */
3860 p = luaL_validpilot( L, 1 );
3861 o = luaL_validoutfit( L, 2 );
3862 s = luaL_checkslot( L, p, 3 );
3863 bypass_cpu = lua_toboolean( L, 4 );
3864 bypass_slot = lua_toboolean( L, 5 );
3865 if ( s == NULL )
3866 return 0;
3867
3868 /* Try to add. */
3869 ret = pilot_outfitAddSlot( p, o, s, bypass_cpu, bypass_slot );
3870 added = ( ret > 0 );
3871
3872 /* Update stats. */
3873 if ( added > 0 ) {
3874 pilot_calcStats( p );
3875
3876 /* Update the weapon sets. */
3877 if ( p->autoweap )
3878 pilot_weaponAuto( p );
3879
3880 /* Update equipment window if operating on the player's pilot. */
3881 if ( player.p != NULL && player.p == p )
3883
3884 /* Update GUI if necessary. */
3885 if ( pilot_isPlayer( p ) )
3886 gui_setShip();
3887 }
3888
3889 lua_pushboolean( L, added );
3890 return 1;
3891}
3892
3915static int pilotL_outfitRm( lua_State *L )
3916{
3917 Pilot *p;
3918 int q, removed, matched = 0;
3919
3920 /* Get parameters. */
3921 removed = 0;
3922 p = luaL_validpilot( L, 1 );
3923 q = luaL_optinteger( L, 3, 1 );
3924
3925 if ( lua_isstring( L, 2 ) ) {
3926 const char *outfit = luaL_checkstring( L, 2 );
3927
3928 /* If outfit is "all", we remove everything except cores and locked
3929 * outfits. */
3930 if ( strcmp( outfit, "all" ) == 0 ) {
3931 for ( int i = 0; i < array_size( p->outfits ); i++ ) {
3932 if ( p->outfits[i]->sslot->required )
3933 continue;
3934 if ( p->outfits[i]->sslot->locked )
3935 continue;
3936 pilot_rmOutfitRaw( p, p->outfits[i] );
3937 removed++;
3938 }
3939 pilot_calcStats( p ); /* Recalculate stats. */
3940 matched = 1;
3941 }
3942 /* If outfit is "cores", we remove cores only. */
3943 else if ( strcmp( outfit, "cores" ) == 0 ) {
3944 for ( int i = 0; i < array_size( p->outfits ); i++ ) {
3945 if ( !p->outfits[i]->sslot->required )
3946 continue;
3947 pilot_rmOutfitRaw( p, p->outfits[i] );
3948 removed++;
3949 }
3950 pilot_calcStats( p ); /* Recalculate stats. */
3951 matched = 1;
3952 }
3953 /* Remove intrinsic outfits. */
3954 else if ( strcmp( outfit, "intrinsic" ) == 0 ) {
3955 for ( int i = 0; i < array_size( p->outfit_intrinsic ); i++ ) {
3956 pilot_rmOutfitRaw( p, &p->outfit_intrinsic[i] );
3957 removed++;
3958 }
3959 array_erase( &p->outfit_intrinsic, array_begin( p->outfit_intrinsic ),
3960 array_end( p->outfit_intrinsic ) );
3961 pilot_calcStats( p ); /* Recalculate stats. */
3962 matched = 1;
3963 }
3964 /* Purpose fallthrough for if the outfit is passed as a string. */
3965 }
3966
3967 if ( !matched ) {
3968 const Outfit *o = luaL_validoutfit( L, 2 );
3969
3970 /* Remove the outfit outfit. */
3971 for ( int i = 0; i < array_size( p->outfits ); i++ ) {
3972 /* Must still need to remove. */
3973 if ( q <= 0 )
3974 break;
3975
3976 /* Not found. */
3977 if ( p->outfits[i]->outfit != o )
3978 continue;
3979
3980 /* Remove outfit. */
3981 pilot_rmOutfit( p, p->outfits[i] );
3982 q--;
3983 removed++;
3984 }
3985 }
3986
3987 /* Update equipment window if operating on the player's pilot. */
3988 if ( player.p != NULL && player.p == p && removed > 0 )
3990
3991 lua_pushnumber( L, removed );
3992 return 1;
3993}
3994
4009static int pilotL_outfitRmSlot( lua_State *L )
4010{
4011 /* Get parameters. */
4012 int ret;
4013 Pilot *p = luaL_validpilot( L, 1 );
4014 PilotOutfitSlot *s = luaL_checkslot( L, p, 2 );
4015 if ( s == NULL )
4016 return 0;
4017
4018 ret = !pilot_rmOutfitRaw( p, s );
4019 if ( ret ) {
4020 pilot_calcStats( p ); /* Recalculate stats. */
4021 /* Update equipment window if operating on the player's pilot. */
4022 if ( player.p != NULL && player.p == p )
4024 }
4025
4026 lua_pushboolean( L, ret );
4027 return 1;
4028}
4029
4042static int pilotL_outfitAddIntrinsic( lua_State *L )
4043{
4044 Pilot *p = luaL_validpilot( L, 1 );
4045 const Outfit *o = luaL_validoutfit( L, 2 );
4046 int ret = pilot_addOutfitIntrinsic( p, o );
4047 if ( ret == 0 )
4048 pilot_calcStats( p );
4049 lua_pushboolean( L, ret );
4050
4051 /* Update GUI if necessary. */
4052 if ( pilot_isPlayer( p ) )
4053 gui_setShip();
4054 return 1;
4055}
4056
4069static int pilotL_outfitRmIntrinsic( lua_State *L )
4070{
4071 Pilot *p = luaL_validpilot( L, 1 );
4072 const Outfit *o = luaL_validoutfit( L, 2 );
4073 lua_pushboolean( L, pilot_rmOutfitIntrinsic( p, o ) );
4074 return 1;
4075}
4076
4083static int pilotL_getFuel( lua_State *L )
4084{
4085 const Pilot *p = luaL_validpilot( L, 1 );
4086 lua_pushnumber( L, p->fuel );
4087 return 1;
4088}
4089
4101static int pilotL_setFuel( lua_State *L )
4102{
4103 Pilot *p = luaL_validpilot( L, 1 );
4104
4105 /* Get the parameter. */
4106 if ( lua_isboolean( L, 2 ) ) {
4107 if ( lua_toboolean( L, 2 ) )
4108 p->fuel = p->fuel_max;
4109 else
4110 p->fuel = 0;
4111 } else if ( lua_isnumber( L, 2 ) ) {
4112 p->fuel = CLAMP( 0, p->fuel_max, lua_tonumber( L, 2 ) );
4113 } else
4114 NLUA_INVALID_PARAMETER( L, 2 );
4115
4116 /* Return amount of fuel. */
4117 lua_pushnumber( L, p->fuel );
4118 return 1;
4119}
4120
4126static int pilotL_intrinsicReset( lua_State *L )
4127{
4128 Pilot *p = luaL_validpilot( L, 1 );
4129 ss_free( p->intrinsic_stats );
4130 p->intrinsic_stats = NULL;
4131 pilot_calcStats( p );
4132 return 0;
4133}
4134
4148static int pilotL_intrinsicSet( lua_State *L )
4149{
4150 Pilot *p = luaL_validpilot( L, 1 );
4151 const char *name;
4152 double value;
4153 int replace;
4154 /* Case individual parameter. */
4155 if ( !lua_istable( L, 2 ) ) {
4156 name = luaL_checkstring( L, 2 );
4157 value = luaL_checknumber( L, 3 );
4158 replace = lua_toboolean( L, 4 );
4159 p->intrinsic_stats = ss_statsSetList(
4160 p->intrinsic_stats, ss_typeFromName( name ), value, replace, 0 );
4161 pilot_calcStats( p );
4162 return 0;
4163 }
4164 replace = lua_toboolean( L, 4 );
4165 /* Case set of parameters. */
4166 lua_pushnil( L );
4167 while ( lua_next( L, 2 ) != 0 ) {
4168 name = luaL_checkstring( L, -2 );
4169 value = luaL_checknumber( L, -1 );
4170 p->intrinsic_stats = ss_statsSetList(
4171 p->intrinsic_stats, ss_typeFromName( name ), value, replace, 0 );
4172 lua_pop( L, 1 );
4173 }
4174 lua_pop( L, 1 );
4175 pilot_calcStats( p );
4176 return 0;
4177}
4178
4192static int pilotL_intrinsicGet( lua_State *L )
4193{
4194 const Pilot *p = luaL_validpilot( L, 1 );
4195 const char *name = luaL_optstring( L, 2, NULL );
4196 int internal = lua_toboolean( L, 3 );
4197 ShipStats ss;
4198 /* TODO get directly the stat from the list. */
4199 ss_statsInit( &ss );
4200 ss_statsMergeFromList( &ss, p->intrinsic_stats );
4201 ss_statsGetLua( L, &ss, name, internal );
4202 return 1;
4203}
4204
4210static int pilotL_shippropReset( lua_State *L )
4211{
4212 Pilot *p = luaL_validpilot( L, 1 );
4213 ss_free( p->ship_stats );
4214 p->ship_stats = NULL;
4215 pilot_calcStats( p );
4216 return 0;
4217}
4218
4230static int pilotL_shippropSet( lua_State *L )
4231{
4232 /* TODO merge with intrinsicSet */
4233 Pilot *p = luaL_validpilot( L, 1 );
4234 const char *name;
4235 double value;
4236
4237 if ( p->ship->lua_env == LUA_NOREF )
4238 return NLUA_ERROR( L,
4239 _( "Trying to set ship property of pilot '%s' flying "
4240 "ship '%s' with no ship Lua enabled!" ),
4241 p->name, p->ship->name );
4242
4243 /* Case individual parameter. */
4244 if ( !lua_istable( L, 2 ) ) {
4245 name = luaL_checkstring( L, 2 );
4246 value = luaL_checknumber( L, 3 );
4247 p->ship_stats =
4248 ss_statsSetList( p->ship_stats, ss_typeFromName( name ), value, 1, 0 );
4249 pilot_calcStats( p );
4250 return 0;
4251 }
4252 /* Case set of parameters. */
4253 lua_pushnil( L );
4254 while ( lua_next( L, 2 ) != 0 ) {
4255 name = luaL_checkstring( L, -2 );
4256 value = luaL_checknumber( L, -1 );
4257 p->ship_stats =
4258 ss_statsSetList( p->ship_stats, ss_typeFromName( name ), value, 1, 0 );
4259 lua_pop( L, 1 );
4260 }
4261 lua_pop( L, 1 );
4262 pilot_calcStats( p );
4263 return 0;
4264}
4265
4279static int pilotL_shippropGet( lua_State *L )
4280{
4281 const Pilot *p = luaL_validpilot( L, 1 );
4282 const char *name = luaL_optstring( L, 2, NULL );
4283 int internal = lua_toboolean( L, 3 );
4284 ShipStats ss;
4285 /* TODO get directly the stat from the list. */
4286 ss_statsInit( &ss );
4287 ss_statsMergeFromList( &ss, p->ship_stats );
4288 ss_statsGetLua( L, &ss, name, internal );
4289 return 1;
4290}
4291
4301static int pilotL_effectClear( lua_State *L )
4302{
4303 Pilot *p = luaL_validpilot( L, 1 );
4304 int keepdebuffs = lua_toboolean( L, 2 );
4305 int keepbuffs = lua_toboolean( L, 3 );
4306 int keepothers = lua_toboolean( L, 4 );
4307 if ( !keepdebuffs && !keepbuffs && !keepothers )
4308 effect_clear( &p->effects );
4309 else
4310 effect_clearSpecific( &p->effects, !keepdebuffs, !keepbuffs,
4311 !keepothers );
4312 pilot_calcStats( p );
4313 return 0;
4314}
4315
4327static int pilotL_effectAdd( lua_State *L )
4328{
4329 Pilot *p = luaL_validpilot( L, 1 );
4330 const char *effectname = luaL_checkstring( L, 2 );
4331 double duration = luaL_optnumber( L, 3, -1. );
4332 double scale = luaL_optnumber( L, 4, 1. );
4333 const EffectData *efx = effect_get( effectname );
4334 if ( efx != NULL ) {
4335 if ( !effect_add( &p->effects, efx, duration, scale, p->id ) )
4336 pilot_calcStats( p );
4337 lua_pushboolean( L, 1 );
4338 } else
4339 lua_pushboolean( L, 0 );
4340 return 1;
4341}
4342
4353static int pilotL_effectRm( lua_State *L )
4354{
4355 Pilot *p = luaL_validpilot( L, 1 );
4356 if ( lua_isnumber( L, 2 ) ) {
4357 int idx = lua_tointeger( L, 2 );
4358 if ( effect_rm( &p->effects, idx ) )
4359 pilot_calcStats( p );
4360 } else {
4361 const char *effectname = luaL_checkstring( L, 2 );
4362 int all = lua_toboolean( L, 3 );
4363 const EffectData *efx = effect_get( effectname );
4364 if ( efx != NULL ) {
4365 if ( effect_rmType( &p->effects, efx, all ) )
4366 pilot_calcStats( p );
4367 }
4368 }
4369 return 0;
4370}
4371
4379static int pilotL_effectHas( lua_State *L )
4380{
4381 const Pilot *p = luaL_validpilot( L, 1 );
4382 const char *effectname = luaL_checkstring( L, 2 );
4383 for ( int i = 0; i < array_size( p->effects ); i++ ) {
4384 const Effect *e = &p->effects[i];
4385 if ( strcmp( effectname, e->data->name ) != 0 )
4386 continue;
4387 lua_pushboolean( L, 1 );
4388 return 1;
4389 }
4390 lua_pushboolean( L, 0 );
4391 return 1;
4392}
4393
4402static int pilotL_effectGet( lua_State *L )
4403{
4404 const Pilot *p = luaL_validpilot( L, 1 );
4405 lua_newtable( L );
4406 for ( int i = 0; i < array_size( p->effects ); i++ ) {
4407 const Effect *e = &p->effects[i];
4408 lua_newtable( L );
4409
4410 lua_pushstring( L, e->data->name );
4411 lua_setfield( L, -2, "name" );
4412
4413 lua_pushnumber( L, e->timer );
4414 lua_setfield( L, -2, "timer" );
4415
4416 lua_pushnumber( L, e->timer );
4417 lua_setfield( L, -2, "strength" );
4418
4419 lua_pushnumber( L, e->data->duration );
4420 lua_setfield( L, -2, "duration" );
4421
4422 lua_pushtex( L, gl_dupTexture( e->data->icon ) );
4423 lua_setfield( L, -2, "icon" );
4424
4425 if ( e->data->flags & EFFECT_BUFF ) {
4426 lua_pushboolean( L, 1 );
4427 lua_setfield( L, -2, "buff" );
4428 }
4429
4430 if ( e->data->flags & EFFECT_DEBUFF ) {
4431 lua_pushboolean( L, 1 );
4432 lua_setfield( L, -2, "debuff" );
4433 }
4434
4435 lua_rawseti( L, -2, i + 1 );
4436 }
4437 return 1;
4438}
4439
4447static int pilotL_ai( lua_State *L )
4448{
4449 const Pilot *p = luaL_validpilot( L, 1 );
4450 if ( p->ai == NULL )
4451 return 0;
4452 lua_pushstring( L, p->ai->name );
4453 return 1;
4454}
4455
4465static int pilotL_changeAI( lua_State *L )
4466{
4467 int ret;
4468 /* Get parameters. */
4469 Pilot *p = luaL_validpilot( L, 1 );
4470 const char *str = luaL_checkstring( L, 2 );
4471
4472 /* Get rid of current AI. */
4473 ai_destroy( p );
4474
4475 /* Create the new AI. */
4476 ret = ai_pinit( p, str );
4477 lua_pushboolean( L, ret );
4478 return 1;
4479}
4480
4501static int pilotL_setTemp( lua_State *L )
4502{
4503 Pilot *p;
4504 int setOutfits = 1;
4505 double kelvins;
4506
4507 /* Handle parameters. */
4508 p = luaL_validpilot( L, 1 );
4509 kelvins = luaL_checknumber( L, 2 );
4510 setOutfits = !lua_toboolean( L, 3 );
4511
4512 /* Temperature must not go below base temp. */
4513 kelvins = MAX( kelvins, CONST_SPACE_STAR_TEMP );
4514
4515 /* Handle pilot ship. */
4516 p->heat_T = kelvins;
4517
4518 /* Handle pilot outfits (maybe). */
4519 if ( setOutfits )
4520 for ( int i = 0; i < array_size( p->outfits ); i++ )
4521 p->outfits[i]->heat_T = kelvins;
4522
4523 return 0;
4524}
4525
4545static int pilotL_setHealth( lua_State *L )
4546{
4547 Pilot *p;
4548 double a, s, st;
4549
4550 /* Handle parameters. */
4551 p = luaL_validpilot( L, 1 );
4552 a = luaL_optnumber( L, 2, 100. * p->armour / p->armour_max );
4553 s = luaL_optnumber( L, 3, 100. * p->shield / p->shield_max );
4554 st = luaL_optnumber( L, 4, 0. );
4555
4556 a /= 100.;
4557 s /= 100.;
4558 st /= 100.;
4559
4560 /* Set health. */
4561 p->armour = a * p->armour_max;
4562 p->shield = s * p->shield_max;
4563 p->stress = st * p->armour;
4564
4565 /* Clear death hooks if not dead. */
4566 if ( p->armour > 0. ) {
4567 pilot_rmFlag( p, PILOT_DISABLED );
4568 pilot_rmFlag( p, PILOT_DEAD );
4569 pilot_rmFlag( p, PILOT_DEATH_SOUND );
4570 pilot_rmFlag( p, PILOT_EXPLODED );
4571 pilot_rmFlag( p, PILOT_DELETE );
4572 if ( pilot_isPlayer( p ) )
4573 player_rmFlag( PLAYER_DESTROYED );
4574 }
4575 pilot_rmFlag( p, PILOT_DISABLED_PERM ); /* Remove permanent disable. */
4576
4577 /* Update disable status. */
4578 pilot_updateDisable( p, 0 );
4579
4580 return 0;
4581}
4582
4598static int pilotL_setHealthAbs( lua_State *L )
4599{
4600 Pilot *p;
4601 double a, s, st;
4602
4603 /* Handle parameters. */
4604 p = luaL_validpilot( L, 1 );
4605 a = luaL_optnumber( L, 2, p->armour );
4606 s = luaL_optnumber( L, 3, p->shield );
4607 st = luaL_optnumber( L, 4, p->stress );
4608
4609 /* Set health. */
4610 p->armour = CLAMP( 0., p->armour_max, a );
4611 p->shield = CLAMP( 0., p->shield_max, s );
4612 p->stress = CLAMP( 0., p->armour_max, st );
4613
4614 /* Clear death hooks if not dead. */
4615 if ( p->armour > 0. ) {
4616 pilot_rmFlag( p, PILOT_DISABLED );
4617 pilot_rmFlag( p, PILOT_DEAD );
4618 pilot_rmFlag( p, PILOT_DEATH_SOUND );
4619 pilot_rmFlag( p, PILOT_EXPLODED );
4620 pilot_rmFlag( p, PILOT_DELETE );
4621 if ( pilot_isPlayer( p ) )
4622 player_rmFlag( PLAYER_DESTROYED );
4623 }
4624 pilot_rmFlag( p, PILOT_DISABLED_PERM ); /* Remove permanent disable. */
4625
4626 /* Update disable status. */
4627 pilot_updateDisable( p, 0 );
4628
4629 return 0;
4630}
4631
4642static int pilotL_addHealth( lua_State *L )
4643{
4644 Pilot *p;
4645 double a, s;
4646
4647 /* Handle parameters. */
4648 p = luaL_validpilot( L, 1 );
4649 a = luaL_optnumber( L, 2, 0. );
4650 s = luaL_optnumber( L, 3, 0. );
4651
4652 /* Set health. */
4653 p->armour = CLAMP( 0., p->armour_max, p->armour + a );
4654 p->shield = CLAMP( 0., p->shield_max, p->shield + s );
4655
4656 /* Update disable status. */
4657 pilot_updateDisable( p, 0 );
4658
4659 return 0;
4660}
4661
4675static int pilotL_setEnergy( lua_State *L )
4676{
4677 /* Handle parameters. */
4678 Pilot *p = luaL_validpilot( L, 1 );
4679 double e = luaL_checknumber( L, 2 );
4680 int absolute = lua_toboolean( L, 3 );
4681
4682 if ( absolute )
4683 p->energy = CLAMP( 0., p->energy_max, e );
4684 else
4685 p->energy = ( e / 100. ) * p->energy_max;
4686
4687 return 0;
4688}
4689
4697static int pilotL_addEnergy( lua_State *L )
4698{
4699 /* Handle parameters. */
4700 Pilot *p = luaL_validpilot( L, 1 );
4701 double e = luaL_checknumber( L, 2 );
4702 p->energy = CLAMP( 0., p->energy_max, p->energy + e );
4703 return 0;
4704}
4705
4712static int pilotL_fillAmmo( lua_State *L )
4713{
4714 Pilot *p = luaL_validpilot( L, 1 );
4715 pilot_fillAmmo( p );
4716 return 0;
4717}
4718
4731static int pilotL_setNoBoard( lua_State *L )
4732{
4733 Pilot *p = luaL_validpilot( L, 1 );
4734 int disable;
4735 if ( lua_isnone( L, 2 ) )
4736 disable = 1;
4737 else
4738 disable = lua_toboolean( L, 2 );
4739
4740 /* See if should prevent boarding. */
4741 if ( disable )
4742 pilot_setFlag( p, PILOT_NOBOARD );
4743 else
4744 pilot_rmFlag( p, PILOT_NOBOARD );
4745
4746 return 0;
4747}
4748
4761static int pilotL_setNoDisable( lua_State *L )
4762{
4763 Pilot *p = luaL_validpilot( L, 1 );
4764 int nodisable;
4765 if ( lua_isnone( L, 2 ) )
4766 nodisable = 1;
4767 else
4768 nodisable = lua_toboolean( L, 2 );
4769
4770 /* See if should prevent disabling. */
4771 if ( nodisable )
4772 pilot_setFlag( p, PILOT_NODISABLE );
4773 else
4774 pilot_rmFlag( p, PILOT_NODISABLE );
4775
4776 return 0;
4777}
4778
4792static int pilotL_setSpeedLimit( lua_State *L )
4793{
4794 /* Handle parameters. */
4795 Pilot *p = luaL_validpilot( L, 1 );
4796 double s = luaL_checknumber( L, 2 );
4797
4798 /* Limit the speed */
4799 p->speed_limit = s;
4800 if ( s > 0. )
4801 pilot_setFlag( p, PILOT_HASSPEEDLIMIT );
4802 else
4803 pilot_rmFlag( p, PILOT_HASSPEEDLIMIT );
4804
4805 pilot_updateMass( p ); /* Updates the true speed limit. */
4806 return 0;
4807}
4808
4825static int pilotL_getHealth( lua_State *L )
4826{
4827 const Pilot *p = luaL_validpilot( L, 1 );
4828 int absolute = lua_toboolean( L, 2 );
4829 /* Return parameters. */
4830 if ( absolute ) {
4831 lua_pushnumber( L, p->armour );
4832 lua_pushnumber( L, p->shield );
4833 } else {
4834 lua_pushnumber(
4835 L, ( p->armour_max > 0. ) ? p->armour / p->armour_max * 100. : 0. );
4836 lua_pushnumber(
4837 L, ( p->shield_max > 0. ) ? p->shield / p->shield_max * 100. : 0. );
4838 }
4839 lua_pushnumber( L, MIN( 1., p->stress / p->armour ) * 100. );
4840 lua_pushboolean( L, pilot_isDisabled( p ) );
4841 return 4;
4842}
4843
4856static int pilotL_getArmour( lua_State *L )
4857{
4858 const Pilot *p = luaL_validpilot( L, 1 );
4859 int absolute = lua_toboolean( L, 2 );
4860 if ( absolute )
4861 lua_pushnumber( L, p->armour );
4862 else
4863 lua_pushnumber(
4864 L, ( p->armour_max > 0. ) ? p->armour / p->armour_max * 100. : 0. );
4865 return 1;
4866}
4867
4880static int pilotL_getShield( lua_State *L )
4881{
4882 const Pilot *p = luaL_validpilot( L, 1 );
4883 int absolute = lua_toboolean( L, 2 );
4884 if ( absolute )
4885 lua_pushnumber( L, p->shield );
4886 else
4887 lua_pushnumber(
4888 L, ( p->shield_max > 0. ) ? p->shield / p->shield_max * 100. : 0. );
4889 return 1;
4890}
4891
4904static int pilotL_getStress( lua_State *L )
4905{
4906 const Pilot *p = luaL_validpilot( L, 1 );
4907 int absolute = lua_toboolean( L, 2 );
4908 if ( absolute )
4909 lua_pushnumber( L, p->stress );
4910 else
4911 lua_pushnumber(
4912 L, ( p->armour > 0. ) ? MIN( 1., p->stress / p->armour ) * 100. : 0. );
4913 return 1;
4914}
4915
4927static int pilotL_getEnergy( lua_State *L )
4928{
4929 const Pilot *p = luaL_validpilot( L, 1 );
4930 int absolute = lua_toboolean( L, 2 );
4931 if ( absolute )
4932 lua_pushnumber( L, p->energy );
4933 else
4934 lua_pushnumber(
4935 L, ( p->energy_max > 0. ) ? p->energy / p->energy_max * 100. : 0. );
4936 return 1;
4937}
4938
4948static int pilotL_getLockon( lua_State *L )
4949{
4950 const Pilot *p = luaL_validpilot( L, 1 );
4951 lua_pushnumber( L, p->lockons );
4952 return 1;
4953}
4954
4955#define PUSH_DOUBLE( L, name, value ) \
4956 lua_pushstring( L, name ); \
4957 lua_pushnumber( L, value ); \
4958 lua_rawset( L, -3 )
4959#define PUSH_INT( L, name, value ) \
4960 lua_pushstring( L, name ); \
4961 lua_pushinteger( L, value ); \
4962 lua_rawset( L, -3 )
4996static int pilotL_getStats( lua_State *L )
4997{
4998 const Pilot *p = luaL_validpilot( L, 1 );
4999 /* Create table with information. */
5000 lua_newtable( L );
5001 /* Core. */
5002 PUSH_DOUBLE( L, "cpu", p->cpu );
5003 PUSH_INT( L, "cpu_max", p->cpu_max );
5004 PUSH_INT( L, "crew", (int)round( p->crew ) );
5005 PUSH_INT( L, "fuel", p->fuel );
5006 PUSH_INT( L, "fuel_max", p->fuel_max );
5007 PUSH_INT( L, "fuel_consumption", p->fuel_consumption );
5008 PUSH_DOUBLE( L, "mass", p->solid.mass );
5009 /* Movement. */
5010 PUSH_DOUBLE( L, "accel", p->accel );
5011 PUSH_DOUBLE( L, "speed", p->speed );
5012 PUSH_DOUBLE( L, "turn", p->turn * 180. / M_PI ); /* Convert back to grad. */
5013 PUSH_DOUBLE( L, "speed_max",
5014 solid_maxspeed( &p->solid, p->speed, p->accel ) );
5015 /* Health. */
5016 PUSH_DOUBLE( L, "absorb", p->dmg_absorb );
5017 PUSH_DOUBLE( L, "armour", p->armour_max );
5018 PUSH_DOUBLE( L, "shield", p->shield_max );
5019 PUSH_DOUBLE( L, "energy", p->energy_max );
5020 PUSH_DOUBLE( L, "armour_regen", p->armour_regen );
5021 PUSH_DOUBLE( L, "shield_regen", p->shield_regen );
5022 PUSH_DOUBLE( L, "energy_regen", p->energy_regen );
5023 /* Stats. */
5024 PUSH_DOUBLE( L, "ew_detection", p->ew_detection );
5025 PUSH_DOUBLE( L, "ew_signature", p->ew_signature );
5026 PUSH_DOUBLE( L, "ew_stealth", p->ew_stealth );
5027 PUSH_DOUBLE( L, "jump_delay",
5029 PUSH_INT( L, "jumps", pilot_getJumps( p ) );
5030
5031 return 1;
5032}
5033#undef PUSH_DOUBLE
5034#undef PUSH_INT
5035
5051static int pilotL_getShipStat( lua_State *L )
5052{
5053 const Pilot *p = luaL_validpilot( L, 1 );
5054 const char *str = luaL_optstring( L, 2, NULL );
5055 int internal = lua_toboolean( L, 3 );
5056 ss_statsGetLua( L, &p->stats, str, internal );
5057 return 1;
5058}
5059
5066static int pilotL_getDetectedDistance( lua_State *L )
5067{
5068 const Pilot *p = luaL_validpilot( L, 1 );
5069 if ( pilot_isFlag( p, PILOT_STEALTH ) )
5070 lua_pushnumber( L, p->ew_stealth );
5071 else
5072 lua_pushnumber( L, p->ew_detection );
5073 return 1;
5074}
5075
5083static int pilotL_cargoFree( lua_State *L )
5084{
5085 const Pilot *p = luaL_validpilot( L, 1 );
5086 lua_pushnumber( L, pilot_cargoFree( p ) );
5087 return 1;
5088}
5089
5101static int pilotL_cargoHas( lua_State *L )
5102{
5103 const Pilot *p = luaL_validpilot( L, 1 );
5104 const Commodity *cargo = luaL_validcommodity( L, 2 );
5105 int quantity = pilot_cargoOwned( p, cargo );
5106 lua_pushnumber( L, quantity );
5107 return 1;
5108}
5109
5123static int pilotL_cargoAdd( lua_State *L )
5124{
5125 /* Parse parameters. */
5126 Pilot *p = luaL_validpilot( L, 1 );
5127 const Commodity *cargo = luaL_validcommodity( L, 2 );
5128 int quantity = luaL_checknumber( L, 3 );
5129
5130 if ( quantity < 0 )
5131 return NLUA_ERROR( L, _( "Quantity must be positive for pilot.cargoAdd "
5132 "(if removing, use pilot.cargoRm)" ) );
5133
5134 /* Try to add the cargo. */
5135 quantity = pilot_cargoAdd( p, cargo, quantity, 0 );
5136 lua_pushnumber( L, quantity );
5137 return 1;
5138}
5139
5140static int pilotL_cargoRmHelper( lua_State *L, int jet )
5141{
5142 Pilot *p;
5143 int quantity;
5144 Commodity *cargo = NULL;
5145
5146 /* Parse parameters. */
5147 p = luaL_validpilot( L, 1 );
5148
5149 if ( lua_isstring( L, 2 ) ) {
5150 const char *str = lua_tostring( L, 2 );
5151
5152 /* Check for special strings. */
5153 if ( strcmp( str, "all" ) == 0 ) {
5154 quantity = pilot_cargoRmAll( p, 0 );
5155 lua_pushnumber( L, quantity );
5156 return 1;
5157 }
5158 }
5159
5160 /* No special string handling, just handle as a normal commodity. */
5161 cargo = luaL_validcommodity( L, 2 );
5162 quantity = luaL_checknumber( L, 3 );
5163
5164 if ( quantity < 0 )
5165 return NLUA_ERROR( L, _( "Quantity must be positive for pilot.cargoRm "
5166 "(if adding, use pilot.cargoAdd)" ) );
5167
5168 /* Try to remove the cargo. */
5169 if ( jet )
5170 quantity = pilot_cargoJet( p, cargo, quantity, 0 );
5171 else
5172 quantity = pilot_cargoRm( p, cargo, quantity );
5173
5174 lua_pushnumber( L, quantity );
5175 return 1;
5176}
5177
5194static int pilotL_cargoRm( lua_State *L )
5195{
5196 return pilotL_cargoRmHelper( L, 0 );
5197}
5198
5211static int pilotL_cargoJet( lua_State *L )
5212{
5213 return pilotL_cargoRmHelper( L, 1 );
5214}
5215
5235static int pilotL_cargoList( lua_State *L )
5236{
5237 const Pilot *p = luaL_validpilot( L, 1 );
5238 lua_newtable( L ); /* t */
5239 for ( int i = 0; i < array_size( p->commodities ); i++ ) {
5240 PilotCommodity *pc = &p->commodities[i];
5241
5242 /* Represents the cargo. */
5243 lua_newtable( L ); /* t, t */
5244
5245 lua_pushstring( L, "name" ); /* t, t, i */
5246 lua_pushstring( L, pc->commodity->name ); /* t, t, i, s */
5247 lua_rawset( L, -3 ); /* t, t */
5248
5249 lua_pushstring( L, "c" ); /* t, t, i */
5250 lua_pushcommodity( L, (Commodity *)pc->commodity ); /* t, t, i, s */
5251 lua_rawset( L, -3 ); /* t, t */
5252
5253 lua_pushstring( L, "q" ); /* t, t, i */
5254 lua_pushnumber( L, pc->quantity ); /* t, t, i, s */
5255 lua_rawset( L, -3 ); /* t, t */
5256
5257 lua_pushstring( L, "m" ); /* t, t, i */
5258 lua_pushboolean( L, pc->id ); /* t, t, i, s */
5259 lua_rawset( L, -3 ); /* t, t */
5260
5261 lua_rawseti( L, -2, i + 1 ); /* t */
5262 }
5263 return 1;
5264}
5265
5274static int pilotL_credits( lua_State *L )
5275{
5276 Pilot *p = luaL_validpilot( L, 1 );
5277 pilot_modCredits( p, luaL_optlong( L, 2, 0 ) );
5278 lua_pushnumber( L, p->credits );
5279 return 1;
5280}
5281
5291static int pilotL_worth( lua_State *L )
5292{
5293 const Pilot *p = luaL_validpilot( L, 1 );
5294 lua_pushnumber( L, pilot_worth( p, lua_toboolean( L, 2 ) ) );
5295 return 1;
5296}
5297
5308static int pilotL_getColour( lua_State *L )
5309{
5310 const Pilot *p = luaL_validpilot( L, 1 );
5311 const glColour *col = pilot_getColour( p );
5312 lua_pushcolour( L, *col );
5313 return 1;
5314}
5315
5325static int pilotL_colourChar( lua_State *L )
5326{
5327 const Pilot *p = luaL_validpilot( L, 1 );
5328 char str[2];
5329 str[0] = pilot_getFactionColourChar( p );
5330 str[1] = '\0';
5331 lua_pushstring( L, str );
5332 return 1;
5333}
5334
5344static int pilotL_getHostile( lua_State *L )
5345{
5346 const Pilot *p = luaL_validpilot( L, 1 );
5347 lua_pushboolean( L, pilot_isHostile( p ) );
5348 return 1;
5349}
5350
5354struct pL_flag {
5355 const char *name;
5356 int id;
5357};
5358static const struct pL_flag pL_flags[] = {
5359 { .name = "stealth", .id = PILOT_STEALTH },
5360 { .name = "refueling", .id = PILOT_REFUELING },
5361 { .name = "invisible", .id = PILOT_INVISIBLE },
5362 { .name = "disabled", .id = PILOT_DISABLED },
5363 { .name = "disabled_perm", .id = PILOT_DISABLED_PERM },
5364 { .name = "landing", .id = PILOT_LANDING },
5365 { .name = "takingoff", .id = PILOT_TAKEOFF },
5366 { .name = "jumpprep", .id = PILOT_HYP_PREP },
5367 { .name = "jumpingin", .id = PILOT_HYP_END },
5368 { .name = "jumpingout", .id = PILOT_HYPERSPACE },
5369 { .name = "manualcontrol", .id = PILOT_MANUAL_CONTROL },
5370 { .name = "carried", .id = PILOT_CARRIED },
5371 { .name = "hailing", .id = PILOT_HAILING },
5372 { .name = "bribed", .id = PILOT_BRIBED },
5373 { .name = "boardable", .id = PILOT_BOARDABLE },
5374 { .name = "nojump", .id = PILOT_NOJUMP },
5375 { .name = "noland", .id = PILOT_NOLAND },
5376 { .name = "nodeath", .id = PILOT_NODEATH },
5377 { .name = "nodisable", .id = PILOT_NODISABLE },
5378 { .name = "visible", .id = PILOT_VISIBLE },
5379 { .name = "visplayer", .id = PILOT_VISPLAYER },
5380 { .name = "hilight", .id = PILOT_HILIGHT },
5381 { .name = "norender", .id = PILOT_NORENDER },
5382 { .name = "hide", .id = PILOT_HIDE },
5383 { .name = "invincible", .id = PILOT_INVINCIBLE },
5384 { .name = "invinc_player", .id = PILOT_INVINC_PLAYER },
5385 { .name = "friendly", .id = PILOT_FRIENDLY },
5386 { .name = "hostile", .id = PILOT_HOSTILE },
5387 { .name = "combat", .id = PILOT_COMBAT },
5388 { NULL, -1 } };
5389
5423static int pilotL_flags( lua_State *L )
5424{
5425 const Pilot *p = luaL_validpilot( L, 1 );
5426 const char *name = luaL_optstring( L, 2, NULL );
5427
5428 if ( name != NULL ) {
5429 for ( int i = 0; pL_flags[i].name != NULL; i++ )
5430 if ( strcmp( pL_flags[i].name, name ) == 0 ) {
5431 lua_pushboolean( L, pilot_isFlag( p, pL_flags[i].id ) );
5432 return 1;
5433 }
5434#if DEBUGGING
5435 NLUA_WARN( L, _( "Tried to access unknown flag '%s' for pilot '%s'!" ),
5436 name, p->name );
5437#endif /* DEBUGGING */
5438 return 0;
5439 }
5440
5441 /* Create flag table. */
5442 lua_newtable( L );
5443 for ( int i = 0; pL_flags[i].name != NULL; i++ ) {
5444 lua_pushboolean( L, pilot_isFlag( p, pL_flags[i].id ) );
5445 lua_setfield( L, -2, pL_flags[i].name );
5446 }
5447 return 1;
5448}
5449
5457static int pilotL_hasIllegal( lua_State *L )
5458{
5459 const Pilot *p = luaL_validpilot( L, 1 );
5460 int f = luaL_validfaction( L, 2 );
5461 lua_pushboolean( L, pilot_hasIllegal( p, f ) );
5462 return 1;
5463}
5464
5474static int pilotL_ship( lua_State *L )
5475{
5476 const Pilot *p = luaL_validpilot( L, 1 );
5477 lua_pushship( L, p->ship );
5478 return 1;
5479}
5480
5488static int pilotL_radius( lua_State *L )
5489{
5490 const Pilot *p = luaL_validpilot( L, 1 );
5491 lua_pushnumber( L, PILOT_SIZE_APPROX * 0.5 * p->ship->size );
5492 return 1;
5493}
5494
5504static int pilotL_points( lua_State *L )
5505{
5506 const Pilot *p = luaL_validpilot( L, 1 );
5507 lua_pushinteger( L, p->ship->points );
5508 return 1;
5509}
5510
5520static int pilotL_idle( lua_State *L )
5521{
5522 const Pilot *p = luaL_validpilot( L, 1 );
5523 lua_pushboolean( L, p->task == 0 );
5524 return 1;
5525}
5526
5554static int pilotL_control( lua_State *L )
5555{
5556 Pilot *p;
5557 int enable, cleartasks;
5558
5559 /* Handle parameters. */
5560 p = luaL_validpilot( L, 1 );
5561 if ( lua_isnone( L, 2 ) )
5562 enable = 1;
5563 else
5564 enable = lua_toboolean( L, 2 );
5565 if ( lua_isnone( L, 3 ) )
5566 cleartasks = enable ^ pilot_isFlag( p, PILOT_MANUAL_CONTROL );
5567 else
5568 cleartasks = lua_toboolean( L, 3 );
5569
5570 if ( enable ) {
5571 int isp = pilot_isPlayer( p );
5572 if ( isp )
5574 NULL ); /* Has to be run before setting the flag. */
5575 pilot_setFlag( p, PILOT_MANUAL_CONTROL );
5576 if ( isp )
5577 ai_pinit( p, "player" );
5578 } else {
5579 pilot_rmFlag( p, PILOT_MANUAL_CONTROL );
5580 if ( pilot_isPlayer( p ) )
5581 ai_destroy( p );
5582 /* Note, we do not set p->ai to NULL, we just clear the tasks and memory.
5583 * This is because the player always has an ai named "player", which is
5584 * used for manual control among other things. Basically a pilot always
5585 * has to have an AI even if it's the player for things to work. */
5586 }
5587
5588 /* Clear task if changing state. */
5589 if ( cleartasks )
5590 pilotL_taskclear( L );
5591
5592 return 0;
5593}
5594
5606static int pilotL_memory( lua_State *L )
5607{
5608 const Pilot *p = luaL_validpilot( L, 1 );
5609 /* Set the pilot's memory. */
5610 if ( p->ai == NULL )
5611 return NLUA_ERROR( L, _( "Pilot '%s' does not have an AI!" ), p->name );
5612 lua_rawgeti( L, LUA_REGISTRYINDEX, p->lua_mem );
5613 return 1;
5614}
5615
5624static int pilotL_shipmemory( lua_State *L )
5625{
5626 Pilot *p = luaL_validpilot( L, 1 );
5627 /* Possible it's not initialized yet, so we do the dirty work here. */
5628 if ( p->lua_ship_mem == LUA_NOREF ) {
5629 lua_newtable( naevL ); /* mem */
5630 p->lua_ship_mem = luaL_ref( naevL, LUA_REGISTRYINDEX ); /* */
5631 }
5632 lua_rawgeti( L, LUA_REGISTRYINDEX, p->lua_ship_mem );
5633 return 1;
5634}
5635
5643static int pilotL_ainame( lua_State *L )
5644{
5645 const Pilot *p = luaL_validpilot( L, 1 );
5646 if ( p->ai == NULL )
5647 return 0;
5648 lua_pushstring( L, p->ai->name );
5649 return 1;
5650}
5651
5660static int pilotL_task( lua_State *L )
5661{
5662 Pilot *p = luaL_validpilot( L, 1 );
5663 Task *t = ai_curTask( p );
5664 if ( t ) {
5665 lua_pushstring( L, t->name );
5666 if ( t->dat != LUA_NOREF ) {
5667 lua_rawgeti( L, LUA_REGISTRYINDEX, t->dat );
5668 return 2;
5669 }
5670 return 1;
5671 }
5672 return 0;
5673}
5674
5684static int pilotL_taskname( lua_State *L )
5685{
5686 Pilot *p = luaL_validpilot( L, 1 );
5687 Task *t = ai_curTask( p );
5688 if ( t ) {
5689 lua_pushstring( L, t->name );
5690 if ( t->subtask != NULL ) {
5691 lua_pushstring( L, t->subtask->name );
5692 return 2;
5693 }
5694 return 1;
5695 }
5696 return 0;
5697}
5698
5705static int pilotL_taskstack( lua_State *L )
5706{
5707 Pilot *p = luaL_validpilot( L, 1 );
5708 int n;
5709
5710 lua_newtable( L );
5711 n = 1;
5712 for ( Task *t = p->task; t != NULL; t = t->next ) {
5713 if ( t->done )
5714 continue;
5715 lua_pushstring( L, t->name );
5716 lua_rawseti( L, -2, n++ );
5717 }
5718
5719 return 1;
5720}
5721
5729static int pilotL_taskdata( lua_State *L )
5730{
5731 Pilot *p = luaL_validpilot( L, 1 );
5732 Task *t = ai_curTask( p );
5733 if ( t && ( t->dat != LUA_NOREF ) ) {
5734 lua_rawgeti( L, LUA_REGISTRYINDEX, t->dat );
5735 return 1;
5736 }
5737 return 0;
5738}
5739
5748static int pilotL_taskclear( lua_State *L )
5749{
5750 Pilot *p = luaL_validpilot( L, 1 );
5751 ai_cleartasks( p );
5752 return 0;
5753}
5754
5765static int pilotL_pushtask( lua_State *L )
5766{
5767 Pilot *p = luaL_validpilot( L, 1 );
5768 const char *task = luaL_checkstring( L, 2 );
5769
5770 if ( pilot_isPlayer( p ) && !pilot_isFlag( p, PILOT_MANUAL_CONTROL ) )
5771 return 0;
5772
5773 Task *t = ai_newtask( L, p, task, 0, 1 );
5774 if ( !lua_isnoneornil( L, 3 ) ) {
5775 lua_pushvalue( L, 3 );
5776 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
5777 }
5778 return 0;
5779}
5780
5789static int pilotL_poptask( lua_State *L )
5790{
5791 Pilot *p = luaL_validpilot( L, 1 );
5792 Task *t = ai_curTask( p );
5793 /* Tasks must exist. */
5794 if ( t == NULL )
5795 return NLUA_ERROR(
5796 L, _( "Trying to pop task when there are no tasks on the stack." ) );
5797 t->done = 1;
5798 return 0;
5799}
5800
5809static int pilotL_refuel( lua_State *L )
5810{
5811 Pilot *p = luaL_validpilot( L, 1 );
5812 const Pilot *target = luaL_validpilot( L, 2 );
5813 double amount = luaL_optinteger( L, 3, 100 );
5814 pilot_rmFlag( p, PILOT_HYP_PREP );
5815 pilot_rmFlag( p, PILOT_HYP_BRAKE );
5816 pilot_rmFlag( p, PILOT_HYP_BEGIN );
5817 pilot_setFlag( p, PILOT_REFUELING );
5818 ai_refuel( p, target->id );
5819 p->refuel_amount = amount;
5820 return 0;
5821}
5822
5826static Task *pilotL_newtask( lua_State *L, Pilot *p, const char *task )
5827{
5828 Task *t;
5829
5830 /* Must be on manual control. */
5831 if ( !pilot_isFlag( p, PILOT_MANUAL_CONTROL ) ) {
5832 NLUA_ERROR( L, _( "Pilot '%s' is not on manual control." ), p->name );
5833 return NULL;
5834 }
5835
5836 /* Creates the new task. */
5837 t = ai_newtask( L, p, task, 0, 1 );
5838 if ( t == NULL ) {
5839 NLUA_ERROR( L, _( "Failed to create new task for pilot '%s'." ),
5840 p->name );
5841 return NULL;
5842 }
5843
5844 return t;
5845}
5846
5868static int pilotL_moveto( lua_State *L )
5869{
5870 Pilot *p;
5871 Task *t;
5872 vec2 *vec;
5873 int brake, compensate;
5874 const char *tsk;
5875
5876 /* Get parameters. */
5877 p = luaL_validpilot( L, 1 );
5878 vec = luaL_checkvector( L, 2 );
5879 if ( lua_isnone( L, 3 ) )
5880 brake = 1;
5881 else
5882 brake = lua_toboolean( L, 3 );
5883 if ( lua_isnone( L, 4 ) )
5884 compensate = 1;
5885 else
5886 compensate = lua_toboolean( L, 4 );
5887
5888 /* Set the task. */
5889 if ( brake ) {
5890 tsk = "moveto";
5891 } else {
5892 if ( compensate )
5893 tsk = "moveto_nobrake";
5894 else
5895 tsk = "moveto_nobrake_raw";
5896 }
5897 t = pilotL_newtask( L, p, tsk );
5898 lua_pushvector( L, *vec );
5899 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
5900
5901 return 0;
5902}
5903
5918static int pilotL_face( lua_State *L )
5919{
5920 Pilot *p, *pt;
5921 vec2 *vec;
5922 Task *t;
5923 int towards;
5924
5925 /* Get parameters. */
5926 pt = NULL;
5927 vec = NULL;
5928 p = luaL_validpilot( L, 1 );
5929 if ( lua_ispilot( L, 2 ) )
5930 pt = luaL_validpilot( L, 2 );
5931 else
5932 vec = luaL_checkvector( L, 2 );
5933 towards = lua_toboolean( L, 3 );
5934
5935 /* Set the task. */
5936 if ( towards )
5937 t = pilotL_newtask( L, p, "face_towards" );
5938 else
5939 t = pilotL_newtask( L, p, "face" );
5940 if ( pt != NULL ) {
5941 lua_pushpilot( L, pt->id );
5942 } else {
5943 lua_pushvector( L, *vec );
5944 }
5945 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
5946
5947 return 0;
5948}
5949
5959static int pilotL_brake( lua_State *L )
5960{
5961 Pilot *p = luaL_validpilot( L, 1 );
5962 pilotL_newtask( L, p, "brake" );
5963 return 0;
5964}
5965
5979static int pilotL_follow( lua_State *L )
5980{
5981 Pilot *p, *pt;
5982 Task *t;
5983 int accurate;
5984
5985 /* Get parameters. */
5986 p = luaL_validpilot( L, 1 );
5987 pt = luaL_validpilot( L, 2 );
5988 accurate = lua_toboolean( L, 3 );
5989
5990 /* Set the task. */
5991 if ( accurate == 0 )
5992 t = pilotL_newtask( L, p, "follow" );
5993 else
5994 t = pilotL_newtask( L, p, "follow_accurate" );
5995
5996 lua_pushpilot( L, pt->id );
5997 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
5998
5999 return 0;
6000}
6001
6016static int pilotL_attack( lua_State *L )
6017{
6018 Pilot *p;
6019 Task *t;
6020 unsigned int pid;
6021
6022 /* Get parameters. */
6023 p = luaL_validpilot( L, 1 );
6024 if ( !lua_isnoneornil( L, 2 ) ) {
6025 const Pilot *pt = luaL_validpilot( L, 2 );
6026 pid = pt->id;
6027 } else {
6028 pid = pilot_getNearestEnemy( p );
6029 if ( pid == 0 ) /* No enemy found. */
6030 return 0;
6031 }
6032
6033 /* Set the task. */
6034 t = pilotL_newtask( L, p, "attack_forced" );
6035 lua_pushpilot( L, pid );
6036 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6037
6038 return 0;
6039}
6040
6053static int pilotL_board( lua_State *L )
6054{
6055 Pilot *p, *pt;
6056 Task *t;
6057
6058 /* Get parameters. */
6059 p = luaL_validpilot( L, 1 );
6060 pt = luaL_validpilot( L, 2 );
6061
6062 /* Set the task. */
6063 t = pilotL_newtask( L, p, "board" );
6064 lua_pushpilot( L, pt->id );
6065 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6066
6067 return 0;
6068}
6069
6087static int pilotL_runaway( lua_State *L )
6088{
6089 /* Get parameters. */
6090 Pilot *p = luaL_validpilot( L, 1 );
6091 const Pilot *pt = luaL_validpilot( L, 2 );
6092
6093 /* Set the task depending on the last parameter. */
6094 if ( lua_isnoneornil( L, 3 ) ) {
6095 Task *t = pilotL_newtask( L, p, "runaway" );
6096 lua_pushpilot( L, pt->id );
6097 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6098 } else {
6099 if ( lua_isboolean( L, 3 ) ) {
6100 int nojump = lua_toboolean( L, 3 );
6101 Task *t =
6102 pilotL_newtask( L, p, ( nojump ) ? "runaway_nojump" : "runaway" );
6103 lua_pushpilot( L, pt->id );
6104 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6105 } else if ( lua_isjump( L, 3 ) ) {
6106 const LuaJump *lj = lua_tojump( L, 3 );
6107 Task *t = pilotL_newtask( L, p, "runaway_jump" );
6108 lua_newtable( L );
6109 lua_pushpilot( L, pt->id );
6110 lua_rawseti( L, -2, 1 );
6111 lua_pushjump( L, *lj );
6112 lua_rawseti( L, -2, 2 );
6113 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6114 } else if ( lua_isspob( L, 3 ) ) {
6115 LuaSpob lp = lua_tospob( L, 3 );
6116 Task *t = pilotL_newtask( L, p, "runaway_land" );
6117 lua_newtable( L );
6118 lua_pushpilot( L, pt->id );
6119 lua_rawseti( L, -2, 1 );
6120 lua_pushspob( L, lp );
6121 lua_rawseti( L, -2, 2 );
6122 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6123 } else
6124 NLUA_INVALID_PARAMETER( L, 3 );
6125 }
6126
6127 return 0;
6128}
6129
6137static int pilotL_gather( lua_State *L )
6138{
6139 Pilot *p = luaL_validpilot( L, 1 );
6140 Task *t = pilotL_newtask( L, p, "gather" );
6141 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6142 return 0;
6143}
6144
6153static int pilotL_canHyperspace( lua_State *L )
6154{
6155 const Pilot *p = luaL_validpilot( L, 1 );
6156 lua_pushboolean( L, space_canHyperspace( p ) );
6157 return 1;
6158}
6159
6173static int pilotL_hyperspace( lua_State *L )
6174{
6175 Pilot *p;
6176 Task *t;
6177 StarSystem *ss;
6178 JumpPoint *jp;
6179 LuaJump lj;
6180 int noshoot;
6181
6182 /* Get parameters. */
6183 p = luaL_validpilot( L, 1 );
6184 if ( lua_isjump( L, 2 ) )
6185 ss = system_getIndex( lua_tojump( L, 2 )->destid );
6186 else
6187 ss = ( lua_isnoneornil( L, 2 ) ) ? NULL : luaL_validsystem( L, 2 );
6188 noshoot = lua_toboolean( L, 3 );
6189
6190 /* Set the task. */
6191 if ( noshoot )
6192 t = pilotL_newtask( L, p, "hyperspace" );
6193 else
6194 t = pilotL_newtask( L, p, "hyperspace_shoot" );
6195
6196 if ( ss == NULL )
6197 return 0;
6198 /* Find the jump. */
6199 for ( int i = 0; i < array_size( cur_system->jumps ); i++ ) {
6200 jp = &cur_system->jumps[i];
6201 if ( jp->target != ss )
6202 continue;
6203 /* Found target. */
6204
6205 if ( jp_isFlag( jp, JP_EXITONLY ) )
6206 return NLUA_ERROR(
6207 L, _( "Pilot '%s' can't jump out exit only jump '%s'" ), p->name,
6208 ss->name );
6209
6210 /* Push jump. */
6211 lj.srcid = cur_system->id;
6212 lj.destid = jp->targetid;
6213 lua_pushjump( L, lj );
6214 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6215 return 0;
6216 }
6217 /* Not found. */
6218 return NLUA_ERROR( L,
6219 _( "System '%s' is not adjacent to current system '%s'" ),
6220 ss->name, cur_system->name );
6221}
6222
6232static int pilotL_stealth( lua_State *L )
6233{
6234 Pilot *p = luaL_validpilot( L, 1 );
6235 /* Set the task. */
6236 Task *t = pilotL_newtask( L, p, "stealth" );
6237 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6238 return 0;
6239}
6240
6248static int pilotL_tryStealth( lua_State *L )
6249{
6250 Pilot *p = luaL_validpilot( L, 1 );
6251 lua_pushboolean( L, pilot_stealth( p ) );
6252 return 1;
6253}
6254
6262static int pilotL_destealth( lua_State *L )
6263{
6264 Pilot *p = luaL_validpilot( L, 1 );
6265 pilot_destealth( p );
6266 return 0;
6267}
6268
6281static int pilotL_land( lua_State *L )
6282{
6283 Pilot *p;
6284 Task *t;
6285 Spob *pnt;
6286 int noshoot;
6287
6288 /* Get parameters. */
6289 p = luaL_validpilot( L, 1 );
6290 if ( lua_isnoneornil( L, 2 ) )
6291 pnt = NULL;
6292 else
6293 pnt = luaL_validspob( L, 2 );
6294 noshoot = lua_toboolean( L, 3 );
6295
6296 /* Set the task. */
6297 if ( noshoot )
6298 t = pilotL_newtask( L, p, "land" );
6299 else
6300 t = pilotL_newtask( L, p, "land_shoot" );
6301
6302 if ( pnt != NULL ) {
6303 int i;
6304 /* Find the spob. */
6305 for ( i = 0; i < array_size( cur_system->spobs ); i++ ) {
6306 if ( cur_system->spobs[i] == pnt ) {
6307 break;
6308 }
6309 }
6310 if ( i >= array_size( cur_system->spobs ) )
6311 return NLUA_ERROR( L, _( "Spob '%s' not found in system '%s'" ),
6312 pnt->name, cur_system->name );
6313
6314 p->nav_spob = i;
6315 if ( p->id == PLAYER_ID )
6316 gui_setNav();
6317
6318 lua_pushspob( L, pnt->id );
6319 t->dat = luaL_ref( L, LUA_REGISTRYINDEX );
6320 }
6321
6322 return 0;
6323}
6324
6337static int pilotL_hailPlayer( lua_State *L )
6338{
6339 Pilot *p;
6340 int enable;
6341
6342 /* Get parameters. */
6343 p = luaL_validpilot( L, 1 );
6344 if ( lua_isnone( L, 2 ) )
6345 enable = 1;
6346 else
6347 enable = lua_toboolean( L, 2 );
6348
6349 /* Set the flag. */
6350 if ( enable ) {
6351 /* Send message. */
6352 char c = pilot_getFactionColourChar( p );
6353 player_message( _( "#%c%s#0 is hailing you." ), c, p->name );
6354
6355 /* Set flag. */
6356 pilot_setFlag( p, PILOT_HAILING );
6358 } else
6359 pilot_rmFlag( p, PILOT_HAILING );
6360
6361 return 0;
6362}
6363
6376static int pilotL_msg( lua_State *L )
6377{
6378 Pilot *p;
6379 const char *type;
6380 unsigned int data;
6381
6382 if ( lua_isnoneornil( L, 1 ) )
6383 p = NULL;
6384 else
6385 p = luaL_validpilot( L, 1 );
6386 type = luaL_checkstring( L, 3 );
6387 data = lua_gettop( L ) > 3 ? 4 : 0;
6388
6389 if ( !lua_istable( L, 2 ) ) {
6390 const Pilot *receiver = luaL_validpilot( L, 2 );
6391 pilot_msg( p, receiver, type, data );
6392 } else {
6393 lua_pushnil( L );
6394 while ( lua_next( L, 2 ) != 0 ) {
6395 const Pilot *receiver = luaL_validpilot( L, -1 );
6396 pilot_msg( p, receiver, type, data );
6397 lua_pop( L, 1 );
6398 }
6399 lua_pop( L, 1 );
6400 }
6401
6402 return 0;
6403}
6404
6413static int pilotL_mothership( lua_State *L )
6414{
6415 const Pilot *p = luaL_validpilot( L, 1 );
6416 if ( p->dockpilot != 0 ) {
6417 const Pilot *l = pilot_get( p->dockpilot );
6418 if ( ( l == NULL ) || pilot_isFlag( l, PILOT_DEAD ) ) {
6419 lua_pushnil( L );
6420 } else
6421 lua_pushpilot( L, p->dockpilot );
6422 } else
6423 lua_pushnil( L );
6424 return 1;
6425}
6426
6434static int pilotL_leader( lua_State *L )
6435{
6436 Pilot *p = luaL_validpilot( L, 1 );
6437 if ( p->parent != 0 ) {
6438 const Pilot *l = pilot_get( p->parent );
6439 if ( ( l == NULL ) || pilot_isFlag( l, PILOT_DEAD ) ) {
6440 p->parent = 0; /* Clear parent for future calls. */
6441 lua_pushnil( L );
6442 } else
6443 lua_pushpilot( L, p->parent );
6444 } else
6445 lua_pushnil( L );
6446 return 1;
6447}
6448
6460static int pilotL_setLeader( lua_State *L )
6461{
6462 Pilot *p = luaL_validpilot( L, 1 );
6463 Pilot *prev_leader = pilot_get( p->parent );
6464
6465 /* Remove from previous leader's follower list */
6466 if ( prev_leader != NULL ) {
6467 int found = 0;
6468 for ( int i = 0; i < array_size( prev_leader->escorts ); i++ ) {
6469 const Escort_t *e = &prev_leader->escorts[i];
6470 if ( e->id != p->id )
6471 continue;
6472 if ( e->type != ESCORT_TYPE_MERCENARY )
6473 return NLUA_ERROR(
6474 L,
6475 _( "Trying to change the leader of pilot '%s' that is a "
6476 "deployed fighter or part of the player fleet!" ),
6477 p->name );
6478 escort_rmListIndex( prev_leader, i );
6479 found = 1;
6480 break;
6481 }
6482 if ( !found )
6483 NLUA_WARN( L, _( "Pilot '%s' not found in followers of '%s'" ),
6484 p->name, prev_leader->name );
6485 }
6486
6487 /* Just clear parent, will already be gone from parent escort list. */
6488 if ( lua_isnoneornil( L, 2 ) ) {
6489 p->parent = 0;
6490 } else {
6491 PilotOutfitSlot *dockslot;
6492 Pilot *leader = luaL_validpilot( L, 2 );
6493
6494 /* Don't allow setting a pilot's leader to themselves. */
6495 if ( p->id == leader->id )
6496 return NLUA_ERROR(
6497 L, _( "Trying to set pilot '%s' to be their own leader!" ),
6498 p->name );
6499
6500 if ( ( leader->parent != 0 ) && ( leader->parent != p->id ) ) {
6501 Pilot *leader_leader = pilot_get( leader->parent );
6502 if ( leader_leader != NULL )
6503 leader = leader_leader;
6504 }
6505
6506 p->parent = leader->id;
6507
6508 /* Reset dock slot */
6509 dockslot = pilot_getDockSlot( p );
6510 if ( dockslot != NULL ) {
6511 dockslot->u.ammo.deployed--;
6512 p->dockpilot = 0;
6513 p->dockslot = -1;
6514 }
6515
6516 /* TODO: Figure out escort type */
6517 escort_addList( leader, p->ship, ESCORT_TYPE_MERCENARY, p->id, 0 );
6518
6519 /* If the pilot has followers, they should be given the new leader as
6520 * well, and be added as escorts. */
6521 for ( int i = array_size( p->escorts ) - 1; i >= 0; i-- ) {
6522 const Escort_t *e = &p->escorts[i];
6523 /* We don't want to deal with fighter bays this way. */
6524 if ( e->type != ESCORT_TYPE_MERCENARY )
6525 continue;
6526 Pilot *pe = pilot_get( e->id );
6527 if ( pe == NULL ) {
6529 p, i ); /* MIght as well remove if they're not there. */
6530 continue;
6531 }
6532
6533 /* Setting an escort as leader, so we clear the leader of the escort.
6534 */
6535 if ( pe->id == p->parent ) {
6536 escort_rmListIndex( p, i );
6537 pe->parent = 0;
6538 continue;
6539 }
6540
6541 pe->parent = p->parent;
6542
6543 /* Add escort to parent. */
6544 escort_addList( leader, pe->ship, e->type, pe->id, 0 );
6545 escort_rmListIndex( p, i );
6546 }
6547 }
6548
6549 return 0;
6550}
6551
6561static int pilotL_followers( lua_State *L )
6562{
6563 const Pilot *p = luaL_validpilot( L, 1 );
6564 int ignorefighters = lua_toboolean( L, 2 );
6565 int idx = 1;
6566
6567 lua_newtable( L );
6568 for ( int i = 0; i < array_size( p->escorts ); i++ ) {
6569 /* Make sure the followers are valid. */
6570 const Pilot *pe = pilot_get( p->escorts[i].id );
6571 if ( ( pe == NULL ) || pilot_isFlag( pe, PILOT_DEAD ) ||
6572 pilot_isFlag( pe, PILOT_HIDE ) )
6573 continue;
6574
6575 if ( ignorefighters && pilot_isFlag( pe, PILOT_CARRIED ) )
6576 continue;
6577
6578 lua_pushpilot( L, p->escorts[i].id );
6579 lua_rawseti( L, -2, idx++ );
6580 }
6581
6582 return 1;
6583}
6584
6594static int pilotL_hookClear( lua_State *L )
6595{
6596 Pilot *p = luaL_validpilot( L, 1 );
6597 pilot_clearHooks( p );
6598 return 0;
6599}
6600
6601static const CollPolyView *getCollPoly( const Pilot *p )
6602{
6603 return poly_view( &p->ship->polygon, p->solid.dir );
6604}
6614static int pilotL_collisionTest( lua_State *L )
6615{
6616 vec2 crash;
6617 const Pilot *p = luaL_validpilot( L, 1 );
6618
6619 /* Asteroid treated separately. */
6620 if ( lua_isasteroid( L, 2 ) ) {
6621 Asteroid *a = luaL_validasteroid( L, 2 );
6622 CollPolyView rpoly;
6623 poly_rotate( &rpoly, &a->polygon->views[0], (float)a->ang );
6624 int ret = CollidePolygon( getCollPoly( p ), &p->solid.pos, &rpoly,
6625 &a->sol.pos, &crash );
6626 free( rpoly.x );
6627 free( rpoly.y );
6628 if ( !ret )
6629 return 0;
6630 lua_pushvector( L, crash );
6631 return 1;
6632 }
6633
6634 Pilot *t = luaL_validpilot( L, 2 );
6635
6636 /* Shouldn't be invincible. */
6637 if ( pilot_isFlag( t, PILOT_INVINCIBLE ) )
6638 return 0;
6639
6640 /* Shouldn't be landing or taking off. */
6641 if ( pilot_isFlag( t, PILOT_LANDING ) || pilot_isFlag( t, PILOT_TAKEOFF ) ||
6642 pilot_isFlag( t, PILOT_NONTARGETABLE ) )
6643 return 0;
6644
6645 /* Must be able to target. */
6646 if ( !pilot_canTarget( t ) )
6647 return 0;
6648
6649 int ret = CollidePolygon( getCollPoly( p ), &p->solid.pos, getCollPoly( t ),
6650 &t->solid.pos, &crash );
6651 if ( !ret )
6652 return 0;
6653
6654 lua_pushvector( L, crash );
6655 return 1;
6656}
6657
6670static int pilotL_damage( lua_State *L )
6671{
6672 Damage dmg;
6673 Pilot *p, *parent;
6674 double damage;
6675
6676 p = luaL_validpilot( L, 1 );
6677 dmg.damage = luaL_checknumber( L, 2 );
6678 dmg.disable = luaL_optnumber( L, 3, 0. );
6679 dmg.penetration = luaL_optnumber( L, 4, 0. ) / 100.;
6680 dmg.type = dtype_get( luaL_optstring( L, 5, "raw" ) );
6681 parent = ( lua_isnoneornil( L, 6 ) ) ? NULL : luaL_validpilot( L, 6 );
6682
6683 damage = pilot_hit( p, NULL, parent, &dmg, NULL, LUA_NOREF, 1 );
6684 if ( parent != NULL )
6685 weapon_hitAI( p, parent, damage );
6686
6687 lua_pushnumber( L, damage );
6688 return 1;
6689}
6690
6699static int pilotL_kill( lua_State *L )
6700{
6701 Pilot *p = luaL_validpilot( L, 1 );
6702 p->armour = -1.;
6703 pilot_dead( p, 0 );
6704 return 0;
6705}
6706
6725static int pilotL_knockback( lua_State *L )
6726{
6727 Pilot *p1 = luaL_validpilot( L, 1 );
6728 double m1 = p1->solid.mass;
6729 vec2 *v1 = &p1->solid.vel;
6730 vec2 *x1 = &p1->solid.pos;
6731 Pilot *p2;
6732 double m2;
6733 vec2 *v2;
6734 vec2 *x2;
6735 double e;
6736 if ( lua_ispilot( L, 2 ) ) {
6737 p2 = luaL_validpilot( L, 2 );
6738 m2 = p2->solid.mass;
6739 v2 = &p2->solid.vel;
6740 x2 = &p2->solid.pos;
6741 e = luaL_optnumber( L, 3, 1. );
6742 } else {
6743 p2 = NULL;
6744 m2 = luaL_checknumber( L, 2 );
6745 v2 = luaL_checkvector( L, 3 );
6746 x2 = luaL_optvector( L, 4, x1 );
6747 e = luaL_optnumber( L, 5, 1. );
6748 }
6749
6750 /* Pure inlastic case. */
6751 if ( e == 0. ) {
6752 double vx = ( m1 * v1->x + m2 * v2->x ) / ( m1 + m2 );
6753 double vy = ( m1 * v1->y + m2 * v2->y ) / ( m1 + m2 );
6754 vec2_cset( &p1->solid.vel, vx, vy );
6755 if ( p2 != NULL )
6756 vec2_cset( &p2->solid.vel, vx, vy );
6757 return 0.;
6758 }
6759
6760 /* Pure elastic. */
6761 double norm = pow2( x1->x - x2->x ) + pow2( x1->y - x2->y );
6762 double a1 = -e * ( 2. * m2 ) / ( m1 + m2 );
6763 if ( norm > 0. )
6764 a1 *= ( ( v1->x - v2->x ) * ( x1->x - x2->x ) +
6765 ( v1->y - v2->y ) * ( x1->y - x2->y ) ) /
6766 norm;
6767
6768 vec2_cadd( &p1->solid.vel, a1 * ( x1->x - x2->x ), a1 * ( x1->y - x2->y ) );
6769 if ( p2 != NULL ) {
6770 double a2 = -e * ( 2. * m1 ) / ( m2 + m1 );
6771 if ( norm > 0. )
6772 a2 *= ( ( v2->x - v1->x ) * ( x2->x - x1->x ) +
6773 ( v2->y - v1->y ) * ( x2->y - x1->y ) ) /
6774 norm;
6775 vec2_cadd( &p2->solid.vel, a2 * ( x2->x - x1->x ),
6776 a2 * ( x2->y - x1->y ) );
6777 }
6778
6779 /* Modulate. TODO this is probably totally wrong and needs fixing to be
6780 * physicaly correct. */
6781 if ( e != 1. ) {
6782 double vx = ( m1 * v1->x + m2 * v2->x ) / ( m1 + m2 );
6783 double vy = ( m1 * v1->y + m2 * v2->y ) / ( m1 + m2 );
6784 vec2_cset( &p1->solid.vel, e * v1->x + ( 1. - e ) * vx,
6785 e * v1->y + ( 1. - e ) * vy );
6786 if ( p2 != NULL )
6787 vec2_cset( &p2->solid.vel, e * v2->x + ( 1. - e ) * vx,
6788 e * v2->y + ( 1. - e ) * vy );
6789 }
6790
6791 return 0;
6792}
6793
6803static int pilotL_distress( lua_State *L )
6804{
6805 Pilot *p = luaL_validpilot( L, 1 );
6806 Pilot *attacker = luaL_validpilot( L, 2 );
6807 Pilot *const *pilot_stack = pilot_getAll();
6808
6809 /* Check if spob is in range. */
6810 for ( int i = 0; i < array_size( cur_system->spobs ); i++ ) {
6811 Spob *spb = cur_system->spobs[i];
6812 if ( spob_hasService( spb, SPOB_SERVICE_INHABITED ) &&
6813 pilot_inRangeSpob( p, i ) ) {
6814 spob_distress( spb, p, attacker );
6815 }
6816 }
6817
6818 /* Now we must check to see if a pilot is in range. */
6819 for ( int i = 0; i < array_size( pilot_stack ); i++ ) {
6820 Pilot *pi = pilot_stack[i];
6821
6822 /* Skip if unsuitable. */
6823 if ( ( pi->ai == NULL ) || ( pi->id == p->id ) ||
6824 ( pilot_isFlag( pi, PILOT_DEAD ) ) ||
6825 ( pilot_isFlag( pi, PILOT_DELETE ) ) )
6826 continue;
6827
6828 if ( !pilot_inRangePilot( p, pi, NULL ) ) {
6829 /*
6830 * If the pilots are within sensor range of each other, send the
6831 * distress signal, regardless of electronic warfare hide values.
6832 */
6833 double d = vec2_dist2( &p->solid.pos, &pi->solid.pos );
6834 if ( d > pilot_sensorRange() )
6835 continue;
6836 }
6837
6838 /* Send AI the distress signal. */
6839 ai_getDistress( pi, p, attacker );
6840 }
6841 return 0;
6842}
6843
6850static int pilotL_calcStats( lua_State *L )
6851{
6852 Pilot *p = luaL_validpilot( L, 1 );
6853 pilot_calcStats( p );
6854 return 0;
6855}
6856
6869static int pilotL_shipvarPeek( lua_State *L )
6870{
6871 const Pilot *p = luaL_validpilot( L, 1 );
6872 const char *str = luaL_checkstring( L, 2 );
6873 const lvar *var = lvar_get( p->shipvar, str );
6874 if ( var != NULL )
6875 return lvar_push( L, var );
6876 return 0;
6877}
6878
6887static int pilotL_shipvarPush( lua_State *L )
6888{
6889 Pilot *p = luaL_validpilot( L, 1 );
6890 const char *str = luaL_checkstring( L, 2 );
6891 lvar var = lvar_tovar( L, str, 3 );
6892 if ( p->shipvar == NULL )
6893 p->shipvar = array_create( lvar );
6894 lvar_addArray( &p->shipvar, &var, 1 );
6895 return 0;
6896}
6897
6905static int pilotL_shipvarPop( lua_State *L )
6906{
6907 Pilot *p = luaL_validpilot( L, 1 );
6908 const char *str = luaL_checkstring( L, 2 );
6909 lvar *var = lvar_get( p->shipvar, str );
6910 if ( var != NULL )
6911 lvar_rmArray( &p->shipvar, var );
6912 return 0;
6913}
6914
6918static int pilotL_renderComm( lua_State *L )
6919{
6920 const Pilot *p = luaL_validpilot( L, 1 );
6921 int size = luaL_optinteger( L, 2, 512 );
6922 glTexture *tex =
6923 ship_gfxComm( p->ship, size, p->tilt, p->solid.dir, &L_default );
6924 if ( tex == NULL ) {
6925 NLUA_WARN( L, _( "Unable to get ship comm graphic for '%s'." ),
6926 p->ship->name );
6927 return 0;
6928 }
6929 lua_pushtex( L, tex );
6930 return 1;
6931}
6932
6940static int pilotL_render( lua_State *L )
6941{
6942 LuaCanvas_t lc;
6943 int w, h;
6944 double eg;
6945 Pilot *p = luaL_validpilot( L, 1 );
6946
6947 /* TODO handle when effects make the ship render larger than it really is. */
6948 w = p->ship->size;
6949 h = p->ship->size;
6950 if ( canvas_new( &lc, w, h ) )
6951 return NLUA_ERROR( L, _( "Error setting up framebuffer!" ) );
6952
6953 /* The code path below is really buggy.
6954 * 1. engine_glow seems to scale 3D models improperly when interpolating, so
6955 * it's disabled.
6956 * 2. for some reason, have to pass real dimensions and not fbo dimensions.
6957 * TODO fix this shit. */
6958 eg = p->engine_glow;
6959 p->engine_glow = ( eg > 0.5 ) ? 1.0 : 0.0;
6960 pilot_renderFramebuffer( p, lc.fbo, gl_screen.rw, gl_screen.rh, NULL );
6961 p->engine_glow = eg;
6962
6963 lua_pushcanvas( L, lc );
6964 return 1;
6965}
6966
6976static int pilotL_renderTo( lua_State *L )
6977{
6978 Pilot *p = luaL_validpilot( L, 1 );
6979 LuaCanvas_t *lc = luaL_checkcanvas( L, 2 );
6980 int w, h;
6981 double eg;
6982
6983 /* TODO handle when effects make the ship render larger than it really is. */
6984 w = p->ship->size;
6985 h = p->ship->size;
6986 if ( ( lc->tex->w < w ) || ( lc->tex->h < h ) )
6987 NLUA_WARN(
6988 L,
6989 _( "Canvas is too small to fully render '%s': %.0f x %.0f < %d x %d" ),
6990 p->name, lc->tex->w, lc->tex->h, w, h );
6991
6992 /* The code path below is really buggy.
6993 * 1. engine_glow seems to scale 3D models improperly when interpolating, so
6994 * it's disabled.
6995 * 2. for some reason, have to pass real dimensions and not fbo dimensions.
6996 * TODO fix this shit. */
6997 eg = p->engine_glow;
6998 p->engine_glow = ( eg > 0.5 ) ? 1.0 : 0.0;
6999 pilot_renderFramebuffer( p, lc->fbo, gl_screen.rw, gl_screen.rh, NULL );
7000 p->engine_glow = eg;
7001
7002 lua_pushnumber( L, w );
7003 lua_pushnumber( L, h );
7004 return 2;
7005}
Task * ai_newtask(lua_State *L, Pilot *p, const char *func, int subtask, int pos)
Creates a new AI task.
Definition ai.c:1169
Task * ai_curTask(Pilot *pilot)
Gets the current running task.
Definition ai.c:385
void ai_refuel(Pilot *refueler, unsigned int target)
Has a pilot attempt to refuel the other.
Definition ai.c:1061
void ai_cleartasks(Pilot *p)
Clears the pilot's tasks.
Definition ai.c:548
void ai_getDistress(const Pilot *p, const Pilot *distressed, const Pilot *attacker)
Sends a distress signal to a pilot.
Definition ai.c:1094
void ai_destroy(Pilot *p)
Destroys the ai part of the pilot.
Definition ai.c:561
Pilot * cur_pilot
Definition ai.c:340
int ai_pinit(Pilot *p, const char *ai)
Initializes the pilot in the ai.
Definition ai.c:494
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:170
#define array_copy(basic_type, ptr_array)
Returns a shallow copy of the input array.
Definition array.h:230
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
Definition array.h:214
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
Definition array.h:102
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition array.h:148
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:179
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:134
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
Definition array.h:206
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
void cam_update(double dt)
Updates the camera.
Definition camera.c:232
void poly_rotate(CollPolyView *rpolygon, const CollPolyView *ipolygon, float theta)
Rotates a polygon.
Definition collision.c:385
int CollidePolygon(const CollPolyView *at, const vec2 *ap, const CollPolyView *bt, const vec2 *bp, vec2 *crash)
Checks whether or not two polygons collide. /!\ The function is not symmetric: the points of polygon ...
Definition collision.c:311
int dtype_get(const char *name)
Gets the id of a dtype based on name.
Definition damagetype.c:157
const char * dtype_damageTypeToStr(int type)
Gets the human readable string from damage type.
Definition damagetype.c:184
int effect_rmType(Effect **efxlist, const EffectData *efx, int all)
Removes an effect type from an effect list.
Definition effect.c:452
int effect_rm(Effect **efxlist, int idx)
Removes an effect from an effect list by index.
Definition effect.c:420
int effect_add(Effect **efxlist, const EffectData *efx, double duration, double strength, unsigned int parent)
Adds an effect to an effect list.
Definition effect.c:322
void effect_clearSpecific(Effect **efxlist, int debuffs, int buffs, int others)
Clears specific types of effects.
Definition effect.c:485
const EffectData * effect_get(const char *name)
Gets an effect by name.
Definition effect.c:265
void effect_clear(Effect **efxlist)
Clears an effect list, removing all active effects.
Definition effect.c:524
int escort_addList(Pilot *p, const Ship *ship, EscortType_t type, unsigned int id, int persist)
Adds an escort to the escort list of a pilot.
Definition escort.c:37
void escort_rmListIndex(Pilot *p, int i)
Remove from escorts list.
Definition escort.c:70
int areEnemies(int a, int b)
Checks whether two factions are enemies.
Definition faction.c:1450
int areAllies(int a, int b)
Checks whether two factions are allies or not.
Definition faction.c:1476
void gui_setShip(void)
Player just upgraded their ship or modified it.
Definition gui.c:1880
void gui_setNav(void)
Player just changed their nav computer target.
Definition gui.c:1864
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
Definition gui.c:353
void outfits_updateEquipmentOutfits(void)
Updates the outfitter and equipment outfit image arrays.
int lvar_addArray(lvar **arr, const lvar *new_var, int sort)
Adds a var to a var array.
Definition lvar.c:160
void lvar_rmArray(lvar **arr, lvar *rm_var)
Removes a var from a var array.
Definition lvar.c:187
lvar * lvar_get(const lvar *arr, const char *str)
Gets a lua var by name.
Definition lvar.c:41
lvar lvar_tovar(lua_State *L, const char *name, int idx)
Gets a lua variable from an index from a lua state.
Definition lvar.c:86
int lvar_push(lua_State *L, const lvar *v)
Pushes a lua var to a lua state.
Definition lvar.c:56
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:39
#define CLAMP(a, b, x)
Definition naev.h:41
#define pow2(x)
Definition naev.h:53
#define MAX(x, y)
Definition naev.h:37
lua_State * naevL
Definition nlua.c:54
int nlua_loadAsteroid(nlua_env env)
Loads the asteroid library.
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.
LuaAsteroid_t * lua_pushasteroid(lua_State *L, LuaAsteroid_t asteroid)
Pushes a asteroid on the stack.
Asteroid * luaL_validasteroid(lua_State *L, int ind)
Gets asteroid at index raising an error if type doesn't match.
glColour * lua_pushcolour(lua_State *L, glColour colour)
Pushes a colour on the stack.
Commodity ** lua_pushcommodity(lua_State *L, Commodity *commodity)
Pushes a commodity on the stack.
Commodity * luaL_validcommodity(lua_State *L, int ind)
Makes sure the commodity is valid or raises a Lua error.
LuaFaction * lua_pushfaction(lua_State *L, LuaFaction faction)
Pushes a faction on the stack.
LuaFaction luaL_validfaction(lua_State *L, int ind)
Gets faction (or faction name) at index, raising an error if type isn't a valid faction.
int lua_isfaction(lua_State *L, int ind)
Checks to see if ind is a faction.
LuaFaction lua_tofaction(lua_State *L, int ind)
Gets faction at index.
LuaJump * luaL_checkjump(lua_State *L, int ind)
Gets jump at index raising an error if isn't a jump.
Definition nlua_jump.c:106
LuaJump * lua_pushjump(lua_State *L, LuaJump jump)
Pushes a jump on the stack.
Definition nlua_jump.c:186
int lua_isjump(lua_State *L, int ind)
Checks to see if ind is a jump.
Definition nlua_jump.c:202
LuaJump * lua_tojump(lua_State *L, int ind)
This module allows you to handle the jumps from Lua.
Definition nlua_jump.c:95
const Outfit * luaL_validoutfit(lua_State *L, int ind)
Makes sure the outfit is valid or raises a Lua error.
const Outfit ** lua_pushoutfit(lua_State *L, const Outfit *outfit)
Pushes a outfit on the stack.
static int pilotL_setVisible(lua_State *L)
Marks the pilot as always visible for other pilots.
static int pilotL_weapsetAmmo(lua_State *L)
Gets the ammo left of a weapon set.
static int pilotL_setHealthAbs(lua_State *L)
Sets the health of a pilot in absolute value.
static int pilotL_intrinsicGet(lua_State *L)
Allows getting an intrinsic stats of a pilot, or gets all of them if name is not specified.
static int pilotL_getVisible(lua_State *L)
Gets visible pilots to a pilot.
static int pilotL_isStopped(lua_State *L)
Checks to see if a pilot is stopped.
static int pilotL_clone(lua_State *L)
Clones a pilot. It will share nearly all properties including outfits.
Definition nlua_pilot.c:834
static int pilotL_setHide(lua_State *L)
Sets the pilot's hide status.
static int pilotL_calcStats(lua_State *L)
Forces a recomputation of the pilots' stats.
static int pilotL_weapsetAddType(lua_State *L)
Adds an outfit to a pilot's weapon set.
static int pilotL_refuel(lua_State *L)
Tries to refuel a pilot.
static int pilotL_eq(lua_State *L)
Checks to see if pilot and p are the same.
static int pilotL_moveto(lua_State *L)
Makes the pilot move to a position.
static int pilotL_hailPlayer(lua_State *L)
Marks the pilot as hailing the player.
static int pilotL_setEnergy(lua_State *L)
Sets the energy of a pilot.
static int pilotL_setFriendly(lua_State *L)
Controls the pilot's friendliness towards the player.
static int pilotL_cargoJet(lua_State *L)
Tries to remove a cargo from a pilot's ship and jet it into space.
static int pilotL_outfitRm(lua_State *L)
Removes an outfit from a pilot.
static int pilotL_outfitRmIntrinsic(lua_State *L)
Removes an intrinsic outfit from the pilot.
static int pilotL_actives(lua_State *L)
Gets the active outfits and their states of the pilot.
static int pilotL_cargoFree(lua_State *L)
Gets the free cargo space the pilot has.
static int pilotL_weapsetRm(lua_State *L)
Removes an outfit from a pilot's weapon set.
static int pilotL_setNoLand(lua_State *L)
Enables or disables landing for a pilot.
static int pilotL_targetAsteroid(lua_State *L)
Gets the asteroid target of the pilot.
static int pilotL_setActiveBoard(lua_State *L)
Allows the pilot to be boarded when not disabled.
static int pilotL_brake(lua_State *L)
Makes the pilot brake.
static int pilotL_withPlayer(lua_State *L)
Checks to see if pilot is with player.
static int pilotL_canHyperspace(lua_State *L)
Checks to see if the pilot can currently hyperspace (as in has target jump and is in range).
static int pilotL_spaceworthy(lua_State *L)
Checks the pilot's spaceworthiness.
static int pilotL_render(lua_State *L)
Renders the pilot to a canvas.
static int pilotL_runaway(lua_State *L)
Makes the pilot runaway from another pilot.
static int pilotL_land(lua_State *L)
Tells the pilot to land.
static int pilotL_weapsetList(lua_State *L)
Get a list of all the outfits in a weapon set.
LuaPilot lua_topilot(lua_State *L, int ind)
Lua bindings to interact with pilots.
Definition nlua_pilot.c:535
static int pilotL_memory(lua_State *L)
Gets a pilots memory table.
LuaPilot * lua_pushpilot(lua_State *L, LuaPilot pilot)
Pushes a pilot on the stack.
Definition nlua_pilot.c:576
static int pilotL_choosePoint(lua_State *L)
Returns a suitable jumpin spot for a given pilot. Lua usage parameter: point = pilot....
Definition nlua_pilot.c:618
static int pilotL_setNoClear(lua_State *L)
Enables or disables making the the pilot exempt from pilot.clear().
static int pilotL_canSpawn(lua_State *L)
Returns if pilots can can spawn naturally in the current system.
Definition nlua_pilot.c:967
static int pilotL_setNoJump(lua_State *L)
Enables or disables a pilot's hyperspace engine.
static int pilotL_setLeader(lua_State *L)
Set a pilots leader.
static int pilotL_taskclear(lua_State *L)
Clears all the tasks of the pilot.
static int pilotL_nav(lua_State *L)
Gets the nav target of the pilot.
static int pilotL_credits(lua_State *L)
Handles the pilots credits.
static int pilotL_weapsetAuto(lua_State *L)
Makes the pilot's weapons get automatically set.
static int pilotL_taskdata(lua_State *L)
Gets the data of the task the pilot is currently doing.
static int pilotL_setInvisible(lua_State *L)
Sets the pilot's invisibility status.
static int pilotL_exists(lua_State *L)
Checks to see if pilot is still in the system and alive.
static int pilotL_disabled(lua_State *L)
Gets the disabled state of a pilot.
static int pilotL_hasIllegal(lua_State *L)
Checks to see if the pilot has illegal stuff to a faction.
static int pilotL_setTemp(lua_State *L)
Sets the temperature of a pilot.
static int pilotL_clearSelect(lua_State *L)
Removes all pilots belonging to a faction from the system.
Definition nlua_pilot.c:926
static int pilotL_outfitRmSlot(lua_State *L)
Removes an outfit from a pilot's named slot.
Pilot * luaL_validpilot(lua_State *L, int ind)
Makes sure the pilot is valid or raises a Lua error.
Definition nlua_pilot.c:560
static int pilotL_tostring(lua_State *L)
Gets the pilot's current (translated) name or notes it is inexistent.
static int pilotL_toggleSpawn(lua_State *L)
Disables or enables pilot spawning in the current system.
static int pilotL_getEnergy(lua_State *L)
Gets the pilot's energy.
static int pilotL_points(lua_State *L)
Gets the points the pilot costs.
static int pilotL_weapsetType(lua_State *L)
Sets the type of a weapon set for a pilot.
static int pilotL_getShield(lua_State *L)
Gets the pilot's shield.
static int pilotL_msg(lua_State *L)
Sends a message to another pilot.
static int pilotL_setBribed(lua_State *L)
Makes pilot act as if bribed by the player.
static int pilotL_cargoRm(lua_State *L)
Tries to remove cargo from the pilot's ship.
static int pilotL_knockback(lua_State *L)
Knocks back a pilot. It can either accept two pilots, or a pilot and an element represented by mass,...
static int pilotL_hookClear(lua_State *L)
Clears the pilot's hooks.
static int pilotL_setNoRender(lua_State *L)
Sets the pilot's norender status.
static int pilotL_taskname(lua_State *L)
Gets the name of the task the pilot is currently doing.
static int pilotL_intrinsicReset(lua_State *L)
Resets the intrinsic stats of a pilot.
static int pilotL_pushtask(lua_State *L)
Pushes a new task to the pilot's AI.
static int pilotL_mothership(lua_State *L)
Gets a pilots mothership (only exists for deployed pilots). Guaranteed to exist or will be nil.
static int pilotL_getHealth(lua_State *L)
Gets the pilot's health.
static int pilotL_cargoAdd(lua_State *L)
Tries to add cargo to the pilot's ship.
static int pilot_outfitAddSlot(Pilot *p, const Outfit *o, PilotOutfitSlot *s, int bypass_cpu, int bypass_slot)
Adds an outfit to a specific slot.
static int pilotL_damage(lua_State *L)
Damages a pilot.
static int pilotL_ai(lua_State *L)
Gets the pilot's AI.
static int pilotL_shippropGet(lua_State *L)
Allows getting an ship property stats of a pilot, or gets all of them if name is not specified.
static int pilotL_cooldownCycle(lua_State *L)
Makes the pilot do an instant full cooldown cycle.
static int pilotL_velocity(lua_State *L)
Gets the pilot's velocity.
static int pilotL_weapsetSetInrange(lua_State *L)
Sets whether a pilot's weapon set does inrange checks.
static int pilotL_reputation(lua_State *L)
Get the reputation the player has with the pilot's faction.
static int pilotL_comm(lua_State *L)
Sends a message to the target or player if no target is passed.
static int pilotL_tryStealth(lua_State *L)
Tries to make the pilot stealth.
static int pilotL_fillAmmo(lua_State *L)
Fills up the pilot's ammo.
static const luaL_Reg pilotL_methods[]
Definition nlua_pilot.c:264
static int pilotL_setHealth(lua_State *L)
Sets the health of a pilot.
static int pilotL_getInrange(lua_State *L)
Gets visible pilots to a pilot within a certain distance.
static int pilotL_changeAI(lua_State *L)
Changes the pilot's AI.
static int pilotL_setTarget(lua_State *L)
Sets the pilot target of the pilot.
static int pilotL_getEnemies(lua_State *L)
Gets hostile pilots to a pilot (or faction) within a certain distance.
static int pilotL_name(lua_State *L)
Gets the pilot's current (translated) name.
static int pilotL_getColour(lua_State *L)
Gets the pilot's colour based on hostility or friendliness to the player.
static int pilotL_scandone(lua_State *L)
Checks to see if a pilot is done scanning its target.
static Task * pilotL_newtask(lua_State *L, Pilot *p, const char *task)
Does a new task.
static int pilotL_shipvarPeek(lua_State *L)
Peeks at a ship variable.
static int pilotL_getShipStat(lua_State *L)
Gets a shipstat from a Pilot by name, or a table containing all the ship stats if not specified.
static int pilotL_setNoDisable(lua_State *L)
Sets the ability of the pilot to be disabled.
static int pilotL_colourChar(lua_State *L)
Gets the pilot's colour character based on hostility or friendliness to the player....
static int pilotL_cargoHas(lua_State *L)
Checks to see how many tonnes of a specific type of cargo the pilot has.
static int pilotL_setFuel(lua_State *L)
Sets the fuel of a pilot.
static int pilotL_stealth(lua_State *L)
Tells the pilot to try to stealth.
static int pilotL_navJump(lua_State *L)
Gets the nav jump target of the pilot.
static int pilotL_outfits(lua_State *L)
Gets a mapping of outfit slot IDs and outfits of a pilot.
static int pilotL_outfitSlot(lua_State *L)
Checks to see outfit a pilot has in a slot.
static int pilotL_outfitsList(lua_State *L)
Gets the outfits of a pilot.
static int pilotL_ainame(lua_State *L)
Gets the name of the task the pilot is currently doing.
static int outfit_compareActive(const void *slot1, const void *slot2)
qsort compare function for active outfits.
static int pilotL_shipvarPop(lua_State *L)
Pops a ship variable.
static int pilotL_setCooldown(lua_State *L)
Starts or stops a pilot's cooldown mode.
static int pilotL_face(lua_State *L)
Makes the pilot face a target.
static int pilotL_clear(lua_State *L)
Clears the current system of pilots. Used for epic battles and such.
Definition nlua_pilot.c:953
static int pilotL_shippropSet(lua_State *L)
Allows setting ship property stats of a pilot.
static int pilotL_rename(lua_State *L)
Changes the pilot's name.
static int pilotL_getStress(lua_State *L)
Gets the pilot's stress.
static int pilotL_mass(lua_State *L)
Gets the mass of a pilot.
static int pilotL_navSpob(lua_State *L)
Gets the nav spob target of the pilot.
static const struct pL_flag pL_flags[]
static int pilotL_collisionTest(lua_State *L)
Tests to see if two ships collide.
static int pilotL_setHostile(lua_State *L)
Controls the pilot's hostility towards the player.
static int pilotL_outfitsEquip(lua_State *L)
Equips a pilot with a set of outfits.
static int pilotL_getAllies(lua_State *L)
Gets friendly pilots to a pilot (or faction) within a certain distance.
static int pilotL_dir(lua_State *L)
Gets the pilot's direction.
static int pilotL_setPosition(lua_State *L)
Sets the pilot's position.
static int pilotL_attack(lua_State *L)
Makes the pilot attack another pilot.
static int pilotL_setFlagWrapper(lua_State *L, int flag)
Wrapper to simplify flag setting stuff.
Definition nlua_pilot.c:495
int nlua_loadPilot(nlua_env env)
Loads the pilot library.
Definition nlua_pilot.c:481
static int pilotL_getArmour(lua_State *L)
Gets the pilot's armour.
static int pilotL_setSpeedLimit(lua_State *L)
Limits the speed of a pilot.
static int pilotL_navJumpSet(lua_State *L)
Sets the hyperspace navigation target for the pilot.
static int pilotL_weapsetCleanup(lua_State *L)
Cleans up a weapon set. This removes all properties of the weapon set and resets it.
static int pilotL_control(lua_State *L)
Sets manual control of the pilot.
static int pilotL_followers(lua_State *L)
Get all of a pilots followers.
static int pilotL_autoweap(lua_State *L)
Gets if a pilot is using automatically set weapon sets.
static int pilotL_outfitToggle(lua_State *L)
Toggles an outfit.
static int pilotL_setNoBoard(lua_State *L)
Sets the ability to board the pilot.
static int pilotL_leader(lua_State *L)
Gets a pilots leader. Guaranteed to exist or will be nil.
static int pilotL_outfitGet(lua_State *L)
Gets a pilot's outfit by ID.
static int pilotL_temp(lua_State *L)
Gets the temperature of a pilot.
static int pilotL_getFuel(lua_State *L)
Gets the amount of fuel the pilot has.
static int pilotL_destealth(lua_State *L)
Tries to make the pilot stealth.
static int pilotL_effectHas(lua_State *L)
Checks to see if a player has an instance of an effect active. Lua function parameter: Pilot p Pilot ...
static int pilotL_weapsetHeat(lua_State *L)
Gets heat information for a weapon set.
static int pilotL_setHilight(lua_State *L)
Makes pilot stand out on radar and the likes.
static int pilotL_shipvarPush(lua_State *L)
Pushes a ship variable.
static int pilotL_areAllies(lua_State *L)
Checks to see if two pilots are allies.
static int pilotL_outfitAddIntrinsic(lua_State *L)
Adds an intrinsic outfit to the pilot.
static int pilotL_addHealth(lua_State *L)
Adds health to a pilot.
static int pilotL_getLockon(lua_State *L)
Gets the lockons on the pilot.
static int pilotL_radius(lua_State *L)
Gets the rough radius of the ship, useful for collision stuff.
static int pilotL_getDetectedDistance(lua_State *L)
Gets the distance that a pilot can be currently detect at.
static int pilotL_effectRm(lua_State *L)
Removes an effect from the pilot.
static int pilotL_setDisable(lua_State *L)
Disables a pilot.
static int pilotL_remove(lua_State *L)
Removes a pilot without explosions or anything.
Definition nlua_pilot.c:852
static int pilotL_intrinsicSet(lua_State *L)
Allows setting intrinsic stats of a pilot.
static int pilotL_kill(lua_State *L)
Kills a pilot.
static int pilotL_setFaction(lua_State *L)
Sets the pilot's faction.
static int pilotL_worth(lua_State *L)
Gets the worth of a pilot (total value of ship and outfits).
int lua_ispilot(lua_State *L, int ind)
Checks to see if ind is a pilot.
Definition nlua_pilot.c:591
static int pilotL_outfitReady(lua_State *L)
Sees if an outfit is ready to use.
static int pilotL_signature(lua_State *L)
Gets the pilot's signature.
static int pilotL_position(lua_State *L)
Gets the pilot's position.
static int pilotL_explode(lua_State *L)
Removes a pilot as if it exploded.
Definition nlua_pilot.c:881
static int pilotL_renderComm(lua_State *L)
Renders the pilot communication image.
static int pilotL_getStats(lua_State *L)
Gets stats of the pilot.
static int pilotL_poptask(lua_State *L)
Pops the current task from the pilot's AI.
static int pilotL_gather(lua_State *L)
Makes the pilot gather stuff.
static int pilotL_setInvincPlayer(lua_State *L)
Sets the pilot's invincibility status towards the player.
static int pilotL_cargoList(lua_State *L)
Lists the cargo the pilot has.
static int pilotL_setNoDeath(lua_State *L)
Makes it so the pilot never dies, stays at 1. armour.
static int pilotL_speed_max(lua_State *L)
Gets the maximum speed of a pilot.
static int pilotL_id(lua_State *L)
Gets the ID of the pilot. Guaranteed to be unique per pilot and not repeating over time (with the exc...
static int pilotL_getHostile(lua_State *L)
Returns whether the pilot is hostile to the player.
static int pilotL_board(lua_State *L)
Makes the pilot board another pilot.
static int pilotL_broadcast(lua_State *L)
Makes the pilot broadcast a message.
static int pilotL_cooldown(lua_State *L)
Gets a pilot's cooldown state.
static int pilotL_setDir(lua_State *L)
Sets the pilot's direction.
static int pilotL_weapsetAdd(lua_State *L)
Adds an outfit to a pilot's weapon set.
static int pilotL_accel(lua_State *L)
Gets the accel of a pilot.
static int pilotL_task(lua_State *L)
Gets the name and data of a pilot's current task.
static int pilotL_distress(lua_State *L)
Sends a distress single from the pilot.
static int pilotL_shipmemory(lua_State *L)
Gets a pilots ship memory table.
static int weapsetItem(lua_State *L, int *k, Pilot *p, const PilotOutfitSlot *slot, const Pilot *target)
Sets up an item in a weapon set.
static int pilotL_areEnemies(lua_State *L)
Checks to see if two pilots are enemies.
static int pilotL_setVelocity(lua_State *L)
Sets the pilot's velocity.
static int pilotL_taskstack(lua_State *L)
Gets the name of all the pilot's current tasks (not subtasks).
static int pilotL_inrange(lua_State *L)
Checks to see if a target pilot is in range of a pilot.
static int pilotL_setInvincible(lua_State *L)
Sets the pilot's invincibility status.
LuaPilot luaL_checkpilot(lua_State *L, int ind)
Gets pilot at index or raises error if there is no pilot at index.
Definition nlua_pilot.c:546
static int pilotL_outfitAdd(lua_State *L)
Adds an outfit to a pilot.
static int pilotL_follow(lua_State *L)
Makes the pilot follow another pilot.
static int pilotL_effectAdd(lua_State *L)
Adds an effect to a pilot.
static int pilotL_outfitAddSlot(lua_State *L)
Adds an outfit to a pilot by slot name.
static int pilotL_ship(lua_State *L)
Gets the pilot's ship.
static int pilotL_flags(lua_State *L)
Gets the pilot's flags.
static int pilotL_addEnergy(lua_State *L)
Adds (or subtracts) energy to a pilot.
static int pilotL_hyperspace(lua_State *L)
Tells the pilot to hyperspace.
static int pilotL_speed(lua_State *L)
Gets the speed of a pilot.
static int pilotL_getPilots(lua_State *L)
Gets the pilots available in the system by a certain criteria.
static int pilotL_setVisplayer(lua_State *L)
Marks the pilot as always visible for the player.
static int pilotL_effectGet(lua_State *L)
Gets the effects on a pilot.
static int pilotL_faction(lua_State *L)
Gets the pilot's faction.
static int pilotL_shippropReset(lua_State *L)
Resets the ship property stats of a pilot.
static int pilotL_setTargetAsteroid(lua_State *L)
Sets the pilot's asteroid target.
static int pilotL_renderTo(lua_State *L)
Renders the pilot to a canvas.
static int pilotL_target(lua_State *L)
Gets the pilot target of the pilot.
static int pilotL_weapset(lua_State *L)
Gets the weapset weapon of the pilot.
static int pilotL_idle(lua_State *L)
Checks to see if the pilot is idle.
static int pilotL_effectClear(lua_State *L)
Clears the effect on a pilot.
static int pilotL_add(lua_State *L)
Adds a ship with an AI and faction to the system (instead of a predefined fleet).
Definition nlua_pilot.c:683
static int pilotL_turn(lua_State *L)
Gets the turn of a pilot.
const Ship ** lua_pushship(lua_State *L, const Ship *ship)
Pushes a ship on the stack.
Definition nlua_ship.c:193
int nlua_loadShip(nlua_env env)
Loads the ship library.
Definition nlua_ship.c:117
const Ship * luaL_validship(lua_State *L, int ind)
Makes sure the ship is valid or raises a Lua error.
Definition nlua_ship.c:168
LuaSpob lua_tospob(lua_State *L, int ind)
This module allows you to handle the spobs from Lua.
Definition nlua_spob.c:152
LuaSpob * lua_pushspob(lua_State *L, LuaSpob spob)
Pushes a spob on the stack.
Definition nlua_spob.c:203
Spob * luaL_validspob(lua_State *L, int ind)
Gets a spob directly.
Definition nlua_spob.c:177
int lua_isspob(lua_State *L, int ind)
Checks to see if ind is a spob.
Definition nlua_spob.c:218
LuaSystem * lua_pushsystem(lua_State *L, LuaSystem sys)
Pushes a system on the stack.
StarSystem * luaL_validsystem(lua_State *L, int ind)
Gets system (or system name) at index raising an error if type doesn't match.
LuaSystem lua_tosystem(lua_State *L, int ind)
Lua system module.
int lua_issystem(lua_State *L, int ind)
Checks to see if ind is a system.
glTexture ** lua_pushtex(lua_State *L, glTexture *texture)
Pushes a texture on the stack.
Definition nlua_tex.c:129
int lua_isvector(lua_State *L, int ind)
Checks to see if ind is a vector.
Definition nlua_vec2.c:161
vec2 * luaL_checkvector(lua_State *L, int ind)
Gets vector at index making sure type is valid.
Definition nlua_vec2.c:130
vec2 * lua_tovector(lua_State *L, int ind)
Represents a 2D vector in Lua.
Definition nlua_vec2.c:119
vec2 * lua_pushvector(lua_State *L, vec2 vec)
Pushes a vector on the stack.
Definition nlua_vec2.c:145
double ntime_convertSeconds(ntime_t t)
Converts the time to seconds.
Definition ntime.c:158
glInfo gl_screen
Definition opengl.c:47
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
Definition opengl_tex.c:891
int outfit_isBeam(const Outfit *o)
Checks if outfit is a beam type weapon.
Definition outfit.c:639
int outfit_isLauncher(const Outfit *o)
Checks if outfit is a weapon launcher.
Definition outfit.c:649
int outfit_isWeapon(const Outfit *o)
Checks to see if an outfit is a weapon.
Definition outfit.c:603
const char * outfit_getTypeBroad(const Outfit *o)
Gets the outfit's broad type.
Definition outfit.c:1091
int outfit_fitsSlot(const Outfit *o, const OutfitSlot *s)
Checks to see if an outfit fits a slot.
Definition outfit.c:1180
int outfit_isFighterBay(const Outfit *o)
Checks if outfit is a fighter bay.
Definition outfit.c:701
int outfit_isAfterburner(const Outfit *o)
Checks if outfit is an afterburner.
Definition outfit.c:692
const char * outfit_getType(const Outfit *o)
Gets the outfit's specific type.
Definition outfit.c:1060
int outfit_isMod(const Outfit *o)
Checks if outfit is a ship modification.
Definition outfit.c:683
const Damage * outfit_damage(const Outfit *o)
Gets the outfit's damage.
Definition outfit.c:808
double outfit_duration(const Outfit *o)
Gets the outfit's duration.
Definition outfit.c:1030
double outfit_cooldown(const Outfit *o)
Gets the outfit's cooldown.
Definition outfit.c:1044
int outfit_isBolt(const Outfit *o)
Checks if outfit is bolt type weapon.
Definition outfit.c:629
double outfit_delay(const Outfit *o)
Gets the outfit's delay.
Definition outfit.c:834
int outfit_fitsSlotType(const Outfit *o, const OutfitSlot *s)
Checks to see if an outfit fits a slot type (ignoring size).
Definition outfit.c:1224
char pilot_getFactionColourChar(const Pilot *p)
Gets the faction colour char, works like faction_reputationColourChar but for a pilot.
Definition pilot.c:1121
void pilot_choosePoint(vec2 *vp, Spob **spob, JumpPoint **jump, int lf, int ignore_rules, int guerilla)
Finds a spawn point for a pilot.
Definition pilot.c:3784
int pilot_isHostile(const Pilot *p)
Checks to see if pilot is hostile to the player.
Definition pilot.c:699
void pilot_updateDisable(Pilot *p, unsigned int shooter)
Handles pilot disabling. Set or unset the disable status depending on health and stress values.
Definition pilot.c:1605
void pilot_cooldown(Pilot *p, int dochecks)
Begins active cooldown, reducing hull and outfit temperatures.
Definition pilot.c:918
void pilot_renderFramebuffer(Pilot *p, GLuint fbo, double fw, double fh, const Lighting *L)
Renders a pilot to a framebuffer.
Definition pilot.c:1849
void pilot_rmHostile(Pilot *p)
Unmarks a pilot as hostile to player.
Definition pilot.c:1277
int pilot_validEnemy(const Pilot *p, const Pilot *target)
Checks to see if a pilot is a valid enemy for another pilot.
Definition pilot.c:291
int pilot_areEnemies(const Pilot *p, const Pilot *target)
Like areEnemies but for pilots.
Definition pilot.c:763
void pilots_clear(void)
Clears all the pilots except the player and clear-exempt pilots.
Definition pilot.c:4137
Pilot * pilot_getTarget(Pilot *p)
Gets the target of a pilot using a fancy caching system.
Definition pilot.c:655
void pilot_msg(const Pilot *p, const Pilot *receiver, const char *type, unsigned int idx)
Sends a message.
Definition pilot.c:4531
void pilot_dead(Pilot *p, unsigned int killer)
Pilot is dead, now will slowly explode.
Definition pilot.c:1687
void pilot_cooldownEnd(Pilot *p, const char *reason)
Terminates active cooldown.
Definition pilot.c:986
credits_t pilot_modCredits(Pilot *p, credits_t amount)
Modifies the amount of credits the pilot has.
Definition pilot.c:3300
unsigned int pilot_getNearestEnemy(const Pilot *p)
Gets the nearest enemy to the pilot.
Definition pilot.c:331
void pilot_setFriendly(Pilot *p)
Marks pilot as friendly to player.
Definition pilot.c:1295
int pilot_validTarget(const Pilot *p, const Pilot *target)
Checks to see if a pilot is a valid target for another pilot.
Definition pilot.c:235
PilotOutfitSlot * pilot_getDockSlot(Pilot *p)
Gets the dock slot of the pilot.
Definition pilot.c:793
int pilot_hasIllegal(const Pilot *p, int faction)
Checks to see if the pilot has illegal stuf to a faction.
Definition pilot.c:4567
void pilot_setCommMsg(Pilot *p, const char *s)
Sets the overhead communication message of the pilot.
Definition pilot.c:1137
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:640
ntime_t pilot_hyperspaceDelay(const Pilot *p)
Calculates the hyperspace delay for a pilot.
Definition pilot.c:3243
void pilot_broadcast(Pilot *p, const char *msg, int ignore_int)
Has the pilot broadcast a message.
Definition pilot.c:1152
void pilot_setHostile(Pilot *p)
Marks pilot as hostile to player.
Definition pilot.c:1105
const glColour * pilot_getColour(const Pilot *p)
Gets a pilot's colour.
Definition pilot.c:1328
static Pilot ** pilot_stack
Definition pilot.c:51
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
Definition pilot.c:93
int pilot_canTarget(const Pilot *p)
Same as pilot_validTarget but without the range check.
Definition pilot.c:270
credits_t pilot_worth(const Pilot *p, int count_unique)
Gets the price or worth of a pilot in credits.
Definition pilot.c:4482
void pilot_rmFriendly(Pilot *p)
Unmarks a pilot as friendly to player.
Definition pilot.c:1306
int pilot_areAllies(const Pilot *p, const Pilot *target)
Like areAllies but for pilots.
Definition pilot.c:741
int pilot_getJumps(const Pilot *p)
Gets the amount of jumps the pilot has left.
Definition pilot.c:1317
void pilot_delete(Pilot *p)
Deletes a pilot.
Definition pilot.c:2965
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.
Definition pilot.c:1383
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.
Definition pilot.c:3557
void pilot_sample_trails(Pilot *p, int none)
Updates the given pilot's trail emissions.
Definition pilot.c:2846
void pilot_setTarget(Pilot *p, unsigned int id)
Sets the target of the pilot.
Definition pilot.c:1352
unsigned int pilot_clone(const Pilot *ref)
Clones an existing pilot.
Definition pilot.c:3646
int pilot_cargoRmAll(Pilot *pilot, int cleanup)
Gets rid of all cargo from pilot. Can remove mission cargo.
int pilot_cargoFree(const Pilot *p)
Gets the pilot's free cargo space.
Definition pilot_cargo.c:53
int pilot_cargoRm(Pilot *pilot, const Commodity *cargo, int quantity)
Tries to get rid of quantity cargo from pilot.
int pilot_cargoOwned(const Pilot *pilot, const Commodity *cargo)
Gets how many of the commodity a pilot has.
Definition pilot_cargo.c:38
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.
int pilot_cargoAdd(Pilot *pilot, const Commodity *cargo, int quantity, unsigned int id)
Tries to add quantity of cargo to pilot.
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
int pilot_ewScanCheck(const Pilot *p)
Checks to see if a scan is done.
Definition pilot_ew.c:74
int pilot_inRangeSpob(const Pilot *p, int target)
Check to see if a spob is in sensor range of the pilot.
Definition pilot_ew.c:293
void pilot_destealth(Pilot *p)
Destealths a pilot.
Definition pilot_ew.c:585
double pilot_ewWeaponTrack(const Pilot *p, const Pilot *t, double trackmin, double trackmax)
Calculates the weapon lead (1. is 100%, 0. is 0%)..
Definition pilot_ew.c:407
int pilot_inRangeAsteroid(const Pilot *p, int ast, int fie)
Check to see if an asteroid is in sensor range of the pilot.
Definition pilot_ew.c:324
double pilot_sensorRange(void)
Returns the default sensor range for the current system.
Definition pilot_ew.c:218
int pilot_inRange(const Pilot *p, double x, double y)
Check to see if a position is in range of the pilot.
Definition pilot_ew.c:231
int pilot_stealth(Pilot *p)
Stealths a pilot.
Definition pilot_ew.c:543
double pilot_heatEfficiencyMod(double T, double Tb, double Tc)
Returns a 0:1 modifier representing efficiency (1. being normal).
Definition pilot_heat.c:237
double pilot_heatFirePercent(double T)
Returns a 0:2 level of fire, 0:1 is the accuracy point, 1:2 is fire rate point.
Definition pilot_heat.c:298
void pilot_clearHooks(Pilot *p)
Clears the pilots hooks.
Definition pilot_hook.c:212
int pilot_runHook(Pilot *p, int hook_type)
Tries to run a pilot hook if he has it.
Definition pilot_hook.c:104
int pilot_rmOutfit(Pilot *pilot, PilotOutfitSlot *s)
Removes an outfit from the pilot.
void pilot_updateMass(Pilot *pilot)
Updates the pilot stats after mass change.
int pilot_maxAmmoO(const Pilot *p, const Outfit *o)
Gets the maximum available ammo for a pilot for a specific outfit.
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.
int pilot_rmOutfitRaw(Pilot *pilot, PilotOutfitSlot *s)
Removes an outfit from the pilot without doing any checks.
int pilot_outfitLInit(const Pilot *pilot, PilotOutfitSlot *po)
Runs the pilot's Lua outfits init script for an outfit.
PilotOutfitSlot * pilot_getSlotByName(Pilot *pilot, const char *name)
Gets the outfit slot by name.
int pilot_reportSpaceworthy(const Pilot *p, char *buf, int bufSize)
Pilot safety report - makes sure stats are safe.
int pilot_addOutfitTest(Pilot *pilot, const Outfit *outfit, const PilotOutfitSlot *s, int warn)
Tests to see if an outfit can be added.
int pilot_addOutfitRaw(Pilot *pilot, const Outfit *outfit, PilotOutfitSlot *s)
Adds an outfit to the pilot, ignoring CPU or other limits.
int pilot_rmOutfitIntrinsic(Pilot *pilot, const Outfit *outfit)
Removes an outfit from an intrinsic slot.
int pilot_addOutfitIntrinsic(Pilot *pilot, const Outfit *outfit)
Adds an outfit as an intrinsic slot.
void pilot_weapSetAdd(Pilot *p, int id, const PilotOutfitSlot *o)
Adds an outfit to a weapon set.
void pilot_getRateMod(double *rate_mod, double *energy_mod, const Pilot *p, const Outfit *o)
Gets applicable fire rate and energy modifications for a pilot's weapon.
void pilot_weapSetInrange(Pilot *p, int id, int inrange)
Changes the weapon set inrange property.
void pilot_weapSetCleanup(Pilot *p, int id)
Cleans up a weapon set.
void pilot_weapSetRm(Pilot *p, int id, const PilotOutfitSlot *o)
Removes a slot from a weapon set.
double pilot_weapSetAmmo(Pilot *p, int id)
Gets the ammo of the current pilot weapon set.
PilotWeaponSetOutfit * pilot_weapSetList(Pilot *p, int id)
Lists the items in a pilot weapon set.
void pilot_weapSetUpdateOutfitState(Pilot *p)
Updates the local state of all the pilot's outfits based on the weapon sets.
void pilot_weaponAuto(Pilot *p)
Tries to automatically set and create the pilot's weapon set.
const char * pilot_weapSetName(Pilot *p, int id)
Gets the name of a weapon set.
void pilot_weapSetType(Pilot *p, int id, WeaponSetType type)
Changes the weapon sets mode.
void player_hailStart(void)
Starts the hail sounds and aborts autoNav.
Definition player.c:2011
void player_targetSet(unsigned int id)
Sets the player's target.
Definition player.c:2230
void player_targetHyperspaceSet(int id, int nomsg)
Sets the player's hyperspace target.
Definition player.c:1905
Player_t player
Definition player.c:77
void player_destroyed(void)
Player blew up in a fireball.
Definition player.c:2698
void player_autonavAbort(const char *reason)
Aborts autonav.
static const double c[]
Definition rng.c:256
static const double d[]
Definition rng.c:263
glTexture * ship_gfxComm(const Ship *s, int size, double tilt, double dir, const Lighting *Lscene)
Loads the ship's comm graphic.
Definition ship.c:418
void ss_free(ShipStatList *ll)
Frees a list of ship stats.
Definition shipstats.c:934
int ss_statsMergeFromList(ShipStats *stats, const ShipStatList *list)
Updates a stat structure from a stat list.
Definition shipstats.c:666
int ss_statsGetLua(lua_State *L, const ShipStats *s, const char *name, int internal)
Gets a ship stat value by name and pushes it to Lua.
Definition shipstats.c:1116
ShipStatsType ss_typeFromName(const char *name)
Gets the type from the name.
Definition shipstats.c:725
int ss_statsInit(ShipStats *stats)
Initializes a stat structure.
Definition shipstats.c:490
void spob_distress(Spob *spb, const Pilot *p, const Pilot *attacker)
Spob is receiving distress from a pilot about an attacker.
Definition space.c:2081
int space_canHyperspace(const Pilot *p)
Checks to make sure if pilot is far enough away to hyperspace.
Definition space.c:494
double system_getReputation(const StarSystem *sys, int faction)
Gets the local reputation of the player in a system or returns 0.
Definition space.c:4502
StarSystem * system_getIndex(int id)
Get the system by its index.
Definition space.c:1038
int space_calcJumpInPos(const StarSystem *in, const StarSystem *out, vec2 *pos, vec2 *vel, double *dir, const Pilot *p)
Calculates the jump in pos for a pilot.
Definition space.c:556
StarSystem * cur_system
Definition space.c:110
int space_spawn
Definition space.c:122
Represents a single asteroid.
Definition asteroid.h:88
Represents a polygon used for collision detection.
Definition collision.h:13
float * x
Definition collision.h:14
float * y
Definition collision.h:15
Represents a commodity.
Definition commodity.h:57
char * name
Definition commodity.h:58
Core damage that an outfit does.
Definition outfit.h:168
int type
Definition outfit.h:169
double disable
Definition outfit.h:174
double penetration
Definition outfit.h:171
double damage
Definition outfit.h:173
Pilot ship effect data.
Definition effect.h:16
double duration
Definition effect.h:22
char * name
Definition effect.h:17
glTexture * icon
Definition effect.h:26
unsigned int flags
Definition effect.h:23
Pilot ship effect.
Definition effect.h:49
const EffectData * data
Definition effect.h:50
double timer
Definition effect.h:52
Stores an escort.
Definition pilot.h:252
unsigned int id
Definition pilot.h:255
EscortType_t type
Definition pilot.h:254
Wrapper to canvass.
Definition nlua_canvas.h:15
glTexture * tex
Definition nlua_canvas.h:17
Lua jump Wrapper.
Definition nlua_jump.h:14
int destid
Definition nlua_jump.h:16
int srcid
Definition nlua_jump.h:15
double duration
Definition outfit.h:218
double trackmin
Definition outfit.h:193
double trackmax
Definition outfit.h:194
A ship outfit, depends radically on the type.
Definition outfit.h:372
union Outfit::@264277167364127137334024361374356236341374052147 u
OutfitLauncherData lau
Definition outfit.h:456
OutfitBeamData bem
Definition outfit.h:455
OutfitBoltData blt
Definition outfit.h:454
double overheat_max
Definition outfit.h:404
nlua_env lua_env
Definition outfit.h:418
double overheat_min
Definition outfit.h:402
char * name
Definition outfit.h:373
Stores a pilot commodity.
Definition pilot.h:223
const Commodity * commodity
Definition pilot.h:224
unsigned int id
Definition pilot.h:226
double lockon_timer
Definition pilot.h:117
Stores an outfit the pilot has.
Definition pilot.h:145
unsigned int beamid
Definition pilot.h:172
PilotOutfitAmmo ammo
Definition pilot.h:174
double stimer
Definition pilot.h:161
double heat_T
Definition pilot.h:154
double progress
Definition pilot.h:165
PilotOutfitState state
Definition pilot.h:160
double timer
Definition pilot.h:162
ShipOutfitSlot * sslot
Definition pilot.h:151
const Outfit * outfit
Definition pilot.h:149
A pilot Weapon Set Outfit.
Definition pilot.h:187
A weapon set represents a set of weapons that have an action.
Definition pilot.h:207
PilotWeaponSetOutfit * slots
Definition pilot.h:210
The representation of an in-game pilot.
Definition pilot.h:263
AI_Profile * ai
Definition pilot.h:408
unsigned int id
Definition pilot.h:264
unsigned int parent
Definition pilot.h:390
const Ship * ship
Definition pilot.h:274
int faction
Definition pilot.h:269
Solid solid
Definition pilot.h:275
char * name
Definition pilot.h:265
Escort_t * escorts
Definition pilot.h:391
const Outfit * data
Definition ship.h:78
OutfitSlot slot
Definition ship.h:72
Represents ship statistics, properties ship can use.
Definition shipstats.h:229
Represents a space ship.
Definition ship.h:97
char * name
Definition ship.h:100
vec2 vel
Definition physics.h:48
double mass
Definition physics.h:45
vec2 pos
Definition physics.h:49
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:102
double radius
Definition space.h:110
char * name
Definition space.h:105
vec2 pos
Definition space.h:109
int id
Definition space.h:104
Basic AI task.
Definition ai.h:23
char * name
Definition ai.h:25
struct Task_ * subtask
Definition ai.h:29
struct Task_ * next
Definition ai.h:24
int done
Definition ai.h:27
int dat
Definition ai.h:31
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:43
double w
Definition opengl_tex.h:47
double h
Definition opengl_tex.h:48
Contains a mission variable.
Definition lvar.h:24
Small struct to handle flags.
const char * name
Definition msgcat.c:196
Represents a 2d vector.
Definition vec2.h:45
double y
Definition vec2.h:47
double x
Definition vec2.h:46
void weapon_clear(void)
Clears all the weapons, does NOT free the layers.
Definition weapon.c:2849
void weapon_hitAI(Pilot *p, const Pilot *shooter, double dmg)
Informs the AI if needed that it's been hit.
Definition weapon.c:1522