naev 0.11.5
escort.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "naev.h"
13#include "escort.h"
14
15#include "array.h"
16#include "dialogue.h"
17#include "hook.h"
18#include "log.h"
19#include "nlua.h"
20#include "nluadef.h"
21#include "nstring.h"
22#include "player.h"
23
24/*
25 * Prototypes.
26 */
27/* Static */
28static int escort_command( const Pilot *parent, const char *cmd, unsigned int index );
29
40int escort_addList( Pilot *p, const Ship *ship, EscortType_t type,
41 unsigned int id, int persist )
42{
43 Escort_t *escort;
44 if (p->escorts == NULL)
45 p->escorts = array_create( Escort_t );
46 escort = &array_grow( &p->escorts );
47 escort->ship = ship;
48 escort->type = type;
49 escort->id = id;
50 escort->persist= persist;
51
52 return 0;
53}
54
61{
62 array_free(p->escorts);
63 p->escorts = NULL;
64}
65
73void escort_rmListIndex( Pilot *p, int i )
74{
75 array_erase( &p->escorts, &p->escorts[i], &p->escorts[i+1] );
76}
77
85void escort_rmList( Pilot *p, unsigned int id )
86{
87 for (int i=0; i<array_size(p->escorts); i++) {
88 if (p->escorts[i].id == id) {
89 escort_rmListIndex( p, i );
90 break;
91 }
92 }
93}
94
108unsigned int escort_create( Pilot *p, const Ship *ship,
109 const vec2 *pos, const vec2 *vel, double dir,
110 EscortType_t type, int add, int dockslot )
111{
112 Pilot *pe;
113 PilotFlags f;
114 unsigned int parent;
115
116 /* Get important stuff. */
117 parent = p->id;
118
119 /* Set flags. */
120 pilot_clearFlagsRaw( f );
121 //pilot_setFlagRaw( f, PILOT_NOJUMP );
122 if (p->faction == FACTION_PLAYER) {
123 pilot_setFlagRaw( f, PILOT_PERSIST );
124 pilot_setFlagRaw( f, PILOT_NOCLEAR );
125 }
126 if (type == ESCORT_TYPE_BAY)
127 pilot_setFlagRaw( f, PILOT_CARRIED );
128
129 /* Create the pilot. */
130 pe = pilot_create( ship, NULL, p->faction, "escort", dir, pos, vel, f, parent, dockslot );
131 pe->parent = parent;
132
133 /* Make invincible to player. */
134 if (pe->parent == PLAYER_ID)
135 pilot_setFlag( pe, PILOT_INVINC_PLAYER );
136
137 /* Set some flags for consistent behaviour. */
138 if (pilot_isFlag(p, PILOT_HOSTILE))
139 pilot_setFlag( pe, PILOT_HOSTILE );
140 if (pilot_isFlag(p, PILOT_FRIENDLY))
141 pilot_setFlag( pe, PILOT_FRIENDLY );
142
143 /* Compute fighter bay bonuses. */
144 if (pilot_isFlagRaw( f, PILOT_CARRIED )) {
145 /* Damage. */
146 if (p->stats.fbay_damage != 1.) {
147 pe->intrinsic_stats = ss_statsSetList( pe->intrinsic_stats, SS_TYPE_D_LAUNCH_DAMAGE, p->stats.fbay_damage, 0, 1 );
148 pe->intrinsic_stats = ss_statsSetList( pe->intrinsic_stats, SS_TYPE_D_FORWARD_DAMAGE, p->stats.fbay_damage, 0, 1 );
149 pe->intrinsic_stats = ss_statsSetList( pe->intrinsic_stats, SS_TYPE_D_TURRET_DAMAGE, p->stats.fbay_damage, 0, 1 );
150 }
151 /* Health. */
152 if (p->stats.fbay_health != 1.) {;
153 pe->intrinsic_stats = ss_statsSetList( pe->intrinsic_stats, SS_TYPE_D_ARMOUR_MOD, p->stats.fbay_health, 0, 1 );
154 pe->intrinsic_stats = ss_statsSetList( pe->intrinsic_stats, SS_TYPE_D_SHIELD_MOD, p->stats.fbay_health, 0, 1 );
155 }
156 /* Movement. */
157 if (p->stats.fbay_movement != 1.) {;
158 pe->intrinsic_stats = ss_statsSetList( pe->intrinsic_stats, SS_TYPE_D_SPEED_MOD, p->stats.fbay_movement, 0, 1 );
159 pe->intrinsic_stats = ss_statsSetList( pe->intrinsic_stats, SS_TYPE_D_TURN_MOD, p->stats.fbay_movement, 0, 1 );
160 pe->intrinsic_stats = ss_statsSetList( pe->intrinsic_stats, SS_TYPE_D_ACCEL_MOD, p->stats.fbay_movement, 0, 1 );
161 }
162 /* Update stats. */
163 pilot_calcStats( pe );
164 }
165
166 /* Add to escort list. */
167 if (add != 0)
168 escort_addList( p, ship, type, pe->id, 1 );
169
170 return pe->id;
171}
172
186unsigned int escort_createRef( Pilot *p, Pilot *pe,
187 const vec2 *pos, const vec2 *vel, double dir,
188 EscortType_t type, int add, int dockslot )
189{
190 if (pilot_get( pe->id ) == NULL) /* Not on stack yet. */
191 pilot_addStack( pe ); /* Sets the ID, and resets internals. */
192 else
193 pilot_reset( pe ); /* Reset internals. */
194 pe->parent = p->id;
195
196 /* Make invincible to player. */
197 if (pe->parent == PLAYER_ID)
198 pilot_setFlag( pe, PILOT_INVINC_PLAYER );
199
200 /* Copy stuff over if necessary. */
201 if (pos != NULL)
202 memcpy( &pe->solid.pos, pos, sizeof(vec2) );
203 if (vel != NULL)
204 memcpy( &pe->solid.vel, vel, sizeof(vec2) );
205 pe->solid.dir = dir;
206
207 /* Set some flags for consistent behaviour. */
208 if (p->faction == FACTION_PLAYER) {
209 pilot_setFlag( pe, PILOT_PERSIST );
210 pilot_setFlag( pe, PILOT_NOCLEAR );
211 }
212 if (pilot_isFlag(p, PILOT_HOSTILE))
213 pilot_setFlag( pe, PILOT_HOSTILE );
214 if (pilot_isFlag(p, PILOT_FRIENDLY))
215 pilot_setFlag( pe, PILOT_FRIENDLY );
216
217 /* Add to escort list. */
218 if (add != 0)
219 escort_addList( p, pe->ship, type, pe->id, 1 );
220 pe->dockslot = dockslot;
221
222 return pe->id;
223}
224
229{
230 int q = 0;
231 /* Iterate backwards so we don't have to care about indices. */
232 for (int j=array_size(p->escorts)-1; j>=0; j--) {
233 Pilot *pe;
234 const Escort_t *e = &p->escorts[j];
235
236 /* Only try to dock fighters. */
237 if (e->type != ESCORT_TYPE_BAY)
238 continue;
239
240 pe = pilot_get( e->id );
241 if (pe==NULL)
242 continue;
243 /* Hack so it can dock. */
244 memcpy( &pe->solid.pos, &p->solid.pos, sizeof(vec2) );
245 memcpy( &pe->solid.vel, &p->solid.vel, sizeof(vec2) );
246 if (pilot_dock( pe, p ))
247 WARN(_("Pilot '%s' has escort '%s' docking error!"), p->name, pe->name);
248 else
249 q++;
250 }
251 return q;
252}
253
262static int escort_command( const Pilot *parent, const char *cmd, unsigned int idx )
263{
264 if (array_size(parent->escorts) == 0)
265 return 1;
266
267 for (int i=0; i<array_size(parent->escorts); i++) {
268 const Pilot *e = pilot_get( parent->escorts[i].id );
269 if (e == NULL) /* Most likely died. */
270 continue;
271
272 pilot_msg( parent, e, cmd, idx );
273 }
274
275 return 0;
276}
277
283int escorts_attack( Pilot *parent )
284{
285 int ret;
286 Pilot *t;
287
288 /* Avoid killing self. */
289 t = pilot_getTarget( parent );
290 if (t == NULL)
291 return 1;
292 if (t->faction == parent->faction)
293 return 1;
294
295 /* Send command. */
296 ret = 1;
297 if (parent->target != parent->id) {
298 lua_pushpilot(naevL, parent->target);
299 ret = escort_command( parent, "e_attack", -1 );
300 lua_pop(naevL, 1);
301 }
302 if ((ret == 0) && (parent == player.p)) {
303 const char *pltname;
304 if (pilot_inRangePilot( parent, t, NULL ) > 0)
305 pltname = t->name;
306 else
307 pltname = _("Unknown");
308
309 if (pilot_isFlag(t, PILOT_DISABLED))
310 player_message(_("#gEscorts: #0Destroying %s."), pltname);
311 else
312 player_message(_("#gEscorts: #0Engaging %s."), pltname);
313 }
314 return ret;
315}
316
322int escorts_hold( const Pilot *parent )
323{
324 int ret = escort_command( parent, "e_hold", 0 );
325 if ((ret == 0) && (parent == player.p))
326 player_message(_("#gEscorts: #0Holding formation."));
327 return ret;
328}
329
335int escorts_return( const Pilot *parent )
336{
337 int ret = escort_command( parent, "e_return", 0 );
338 if ((ret == 0) && (parent == player.p))
339 player_message(_("#gEscorts: #0Returning to ship."));
340 return ret;
341}
342
348int escorts_clear( const Pilot *parent )
349{
350 int ret = escort_command( parent, "e_clear", 0 );
351 if ((ret == 0) && (parent == player.p))
352 player_message(_("#gEscorts: #0Clearing orders."));
353 return ret;
354}
355
363{
364 const char *title, *caption;
365 char *choice;
366 int ret = 1;
367
368 /* "Attack My Target" order is omitted deliberately since e is your
369 * target, making "Attack My Target" a useless command. */
370 const char *opts[] = {
371 _("Hold Formation"),
372 _("Return To Ship"),
373 _("Clear Orders"),
374 _("Cancel")
375 };
376 const int nopts = 4;
377
378 /* Must not be NULL */
379 if (e == NULL)
380 return 1;
381
382 title = _("Escort Orders");
383 caption = _("Select the order to give to this escort.");
384
385 dialogue_makeChoice( title, caption, nopts );
386 for (int i=0; i<nopts; i++)
387 dialogue_addChoice( title, caption, opts[i] );
388
389 choice = dialogue_runChoice();
390 if (choice != NULL) {
391 if (strcmp(choice, opts[0]) == 0) { /* Hold position */
392 pilot_msg( player.p, e, "e_hold", 0 );
393 ret = 0;
394 }
395 else if (strcmp(choice, opts[1]) == 0) { /* Return to ship */
396 pilot_msg( player.p, e, "e_return", 0 );
397 ret = 0;
398 }
399 else if (strcmp(choice, opts[2]) == 0) { /* Clear orders */
400 pilot_msg( player.p, e, "e_clear", 0 );
401 ret = 0;
402 }
403 }
404 free( choice );
405 return ret;
406}
407
414int escorts_jump( const Pilot *parent, const JumpPoint *jp )
415{
416 int ret;
417 LuaJump lj;
418
419 lj.destid = jp->targetid;
420 lj.srcid = cur_system->id;
421
422 lua_pushjump( naevL, lj );
423 ret = escort_command( parent, "hyperspace", -1 );
424 lua_pop(naevL, 1);
425
426 if ((ret == 0) && (parent == player.p))
427 player_message(_("#gEscorts: #0Jumping."));
428 return ret;
429}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:158
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition array.h:140
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
Definition array.h:119
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
char * dialogue_runChoice(void)
Run the dialog and return the clicked string.
Definition dialogue.c:795
void dialogue_addChoice(const char *caption, const char *msg, const char *opt)
Add a choice to the dialog.
Definition dialogue.c:773
void dialogue_makeChoice(const char *caption, const char *msg, int opts)
Create the choice dialog. Need to add choices with below method.
Definition dialogue.c:751
void escort_rmList(Pilot *p, unsigned int id)
Remove from escorts list.
Definition escort.c:85
int escorts_hold(const Pilot *parent)
Have a pilot order its escorts to hold position.
Definition escort.c:322
static int escort_command(const Pilot *parent, const char *cmd, unsigned int index)
Runs an escort command on all of a pilot's escorts.
Definition escort.c:262
void escort_freeList(Pilot *p)
Remove all escorts from a pilot.
Definition escort.c:60
unsigned int escort_create(Pilot *p, const Ship *ship, const vec2 *pos, const vec2 *vel, double dir, EscortType_t type, int add, int dockslot)
Creates an escort.
Definition escort.c:108
unsigned int escort_createRef(Pilot *p, Pilot *pe, const vec2 *pos, const vec2 *vel, double dir, EscortType_t type, int add, int dockslot)
Creates an escort from a reference.
Definition escort.c:186
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:40
int escorts_return(const Pilot *parent)
Have a pilot order its escorts to dock.
Definition escort.c:335
void escort_rmListIndex(Pilot *p, int i)
Remove from escorts list.
Definition escort.c:73
int escort_playerCommand(const Pilot *e)
Open a dialog for the player to issue a command to an escort.
Definition escort.c:362
int escort_clearDeployed(Pilot *p)
Clears deployed escorts of a pilot.
Definition escort.c:228
int escorts_attack(Pilot *parent)
Have a pilot order its escorts to attack its target.
Definition escort.c:283
int escorts_jump(const Pilot *parent, const JumpPoint *jp)
Have a pilot order its escorts to jump.
Definition escort.c:414
int escorts_clear(const Pilot *parent)
Have a pilot order its escorts to clear orders.
Definition escort.c:348
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
Definition gui.c:335
Header file with generic functions and naev-specifics.
LuaJump * lua_pushjump(lua_State *L, LuaJump jump)
Pushes a jump on the stack.
Definition nlua_jump.c:185
LuaPilot * lua_pushpilot(lua_State *L, LuaPilot pilot)
Pushes a pilot on the stack.
Definition nlua_pilot.c:563
unsigned int pilot_addStack(Pilot *p)
Adds a pilot to the stack.
Definition pilot.c:3358
Pilot * pilot_getTarget(Pilot *p)
Gets the target of a pilot using a fancy caching system.
Definition pilot.c:634
void pilot_msg(const Pilot *p, const Pilot *receiver, const char *type, unsigned int idx)
Sends a message.
Definition pilot.c:4120
void pilot_reset(Pilot *pilot)
Resets a pilot.
Definition pilot.c:3185
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:620
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:3248
int pilot_inRangePilot(const Pilot *p, const Pilot *target, double *dist2)
Check to see if a pilot is in sensor range of another.
Definition pilot_ew.c:244
void pilot_calcStats(Pilot *pilot)
Recalculates the pilot's stats based on his outfits.
Player_t player
Definition player.c:74
StarSystem * cur_system
Definition space.c:106
Stores an escort.
Definition pilot.h:206
unsigned int id
Definition pilot.h:209
int persist
Definition pilot.h:211
EscortType_t type
Definition pilot.h:208
const Ship * ship
Definition pilot.h:207
Lua jump Wrapper.
Definition nlua_jump.h:14
int destid
Definition nlua_jump.h:16
int srcid
Definition nlua_jump.h:15
The representation of an in-game pilot.
Definition pilot.h:217
unsigned int id
Definition pilot.h:218
unsigned int parent
Definition pilot.h:333
const Ship * ship
Definition pilot.h:226
ShipStatList * intrinsic_stats
Definition pilot.h:293
int faction
Definition pilot.h:222
Solid solid
Definition pilot.h:227
char * name
Definition pilot.h:219
Escort_t * escorts
Definition pilot.h:334
unsigned int target
Definition pilot.h:342
int dockslot
Definition pilot.h:339
Pilot * p
Definition player.h:101
Represents a space ship.
Definition ship.h:94
vec2 vel
Definition physics.h:48
double dir
Definition physics.h:46
vec2 pos
Definition physics.h:49
Represents a 2d vector.
Definition vec2.h:32