naev 0.12.6
player_fleet.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
9#include "player_fleet.h"
10
11#include "array.h"
12#include "dialogue.h"
13#include "equipment.h"
14#include "escort.h"
15#include "land.h"
16#include "naev.h"
17#include "rng.h"
18
19/* Prototypes. */
20static int pfleet_cargoAddRaw( const Commodity *com, int q );
21
25void pfleet_update( void )
26{
27 const PlayerShip_t *pships = player_getShipStack();
28 player.fleet_used = player.p->ship->points;
29 for ( int i = 0; i < array_size( pships ); i++ ) {
30 const PlayerShip_t *ps = &pships[i];
31 if ( ps->deployed )
32 player.fleet_used += ps->p->ship->points;
33 }
34
35 /* Redistribute the cargo. */
37}
38
46int pfleet_toggleDeploy( PlayerShip_t *ps, int deploy )
47{
48 /* When undeploying we want to make sure cargo fits. */
49 if ( ps->deployed && !deploy ) {
50 int idx;
51 Pilot *p = ps->p;
52 int q = pilot_cargoUsed( p ); /* Amount we have to allocate. */
53 int f = pfleet_cargoFree() - pilot_cargoFree( p ); /* Real free amount. */
54 if ( f < q ) {
55 char buf_amount[ECON_MASS_STRLEN], buf_free[ECON_MASS_STRLEN],
56 buf_needed[ECON_MASS_STRLEN];
57 tonnes2str( buf_amount, q );
58 tonnes2str( buf_free, -f );
59 tonnes2str( buf_needed, q - f );
60 if ( !dialogue_YesNo(
61 _( "Not Enough Cargo Space" ),
62 _( "Your ship '%s' has %s of cargo but there is only %s of "
63 "free space in the rest of the fleet. Get rid of %s of "
64 "cargo to shrink your fleet?" ),
65 p->name, buf_amount, buf_free, buf_needed ) ) {
66 return -1;
67 }
68 }
69 /* Try to make room for the commodities. */
70 idx = -1;
71 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
72 const Escort_t *e = &player.p->escorts[i];
73 const Pilot *pe = pilot_get( e->id );
74 if ( pe == NULL )
75 continue;
76 if ( e->type != ESCORT_TYPE_FLEET )
77 continue;
78 if ( strcmp( pe->name, p->name ) == 0 ) {
79 idx = i;
80 break;
81 }
82 }
83 if ( idx < 0 ) {
84 WARN( _( "Player deployed ship '%s' not found in escort list!" ),
85 p->name );
86 ps->deployed = 0;
87 return -1;
88 } else
89 escort_rmListIndex( player.p, idx );
90
91 /* Try to add the cargo. */
92 for ( int i = 0; i < array_size( p->commodities ); i++ ) {
93 const PilotCommodity *pc = &p->commodities[i];
95 pilot_cargoRm( p, pc->commodity, pc->quantity );
96 }
97
98 /* Undeploy fighters. */
99 escort_clearDeployed( p, -1 );
100 }
101 ps->deployed = deploy;
102 if ( !ps->deployed ) {
103 pilot_stackRemove( ps->p );
104 pilot_free( ps->p );
105 } else
106 pfleet_deploy( ps );
108
109 /* Have to update GUI. */
110 equipment_updateShips( land_getWid( LAND_WINDOW_EQUIPMENT ), NULL );
111 return 0;
112}
113
123{
124 double a;
125 vec2 v;
126
127#if DEBUGGING
128 if ( !pilot_isSpaceworthy( ps->p ) ) {
129 WARN( _( "Trying to deploy fleet ship '%s' despite not being space "
130 "worthy!" ),
131 ps->p->name );
132 ps->deployed = 0;
133 return -1;
134 }
135#endif /* DEBUGGING */
136
137 /* Get the position. */
138 a = RNGF() * 2. * M_PI;
139 vec2_cset( &v, player.p->solid.pos.x + 50. * cos( a ),
140 player.p->solid.pos.y + 50. * sin( a ) );
141
142 /* Add the escort to the fleet. */
143 escort_createRef( player.p, ps->p, &v, NULL, a, ESCORT_TYPE_FLEET, 1, -1 );
144
145 /* Initialize. */
146 ai_pinit( ps->p, "escort" );
147 pilot_reset( ps->p );
148 pilot_setFlag( ps->p, PILOT_INVINC_PLAYER );
149 pilot_rmFlag( ps->p, PILOT_PLAYER );
150
151 /* AI only knows how to use auto weapon sets. */
152 pilot_weaponAuto( ps->p );
153
154 return 0;
155}
156
157static void shipCargo( PilotCommodity **pclist, Pilot *p, int remove )
158{
159 for ( int i = array_size( p->commodities ) - 1; i >= 0; i-- ) {
160 const PilotCommodity *pc = &p->commodities[i];
161 int q = pc->quantity;
162
163 /* Mission cargo gets added independently. */
164 if ( pc->id > 0 )
165 array_push_back( pclist, *pc );
166 else {
167 /* See if it can be added. */
168 int added = 0;
169 for ( int j = 0; j < array_size( *pclist ); j++ ) {
170 PilotCommodity *lc = &( *pclist )[j];
171
172 /* Ignore mission cargo. */
173 if ( lc->id > 0 )
174 continue;
175
176 /* Cargo must match. */
177 if ( pc->commodity != lc->commodity )
178 continue;
179
180 lc->quantity += q;
181 added = 1;
182 break;
183 }
184 if ( !added )
185 array_push_back( pclist, *pc );
186 }
187
188 /* Remove the cargo. TODO use pilot_cargoRm somehow. */
189 if ( remove )
190 array_erase( &p->commodities, &pc[0], &pc[1] );
191 }
192
193 /* Update cargo. */
194 if ( remove )
195 pilot_cargoCalc( p );
196}
197
198static int pc_cmp( const void *pa, const void *pb )
199{
200 const PilotCommodity *pca, *pcb;
201 pca = (const PilotCommodity *)pa;
202 pcb = (const PilotCommodity *)pb;
203 /* Prioritize mission cargo first. */
204 if ( ( pca->id > 0 ) && ( pcb->id == 0 ) )
205 return -1;
206 else if ( ( pca->id == 0 ) && ( pcb->id > 0 ) )
207 return +1;
208 /* Just do price at the end. */
209 return pcb->commodity->price - pca->commodity->price;
210}
211
216{
218
219 /* Add commodity if we want to. */
220 if ( pc_add != NULL )
221 array_push_back( &pclist, *pc_add );
222
223 /* First build up a list of all the potential cargo. */
224 shipCargo( &pclist, player.p, 1 );
225 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
226 const Escort_t *e = &player.p->escorts[i];
227 Pilot *pe = pilot_get( e->id );
228 if ( pe == NULL )
229 continue;
230 if ( e->type != ESCORT_TYPE_FLEET )
231 continue;
232 shipCargo( &pclist, pe, 1 );
233 }
234
235 /* Sort based on base price. */
236 qsort( pclist, array_size( pclist ), sizeof( PilotCommodity ), pc_cmp );
237
238 /* Re-add the cargo. */
239 for ( int i = 0; i < array_size( pclist ); i++ ) {
240 int q;
241 const PilotCommodity *pc = &pclist[i];
242
243 if ( pc->id > 0 )
244 q = pilot_cargoAddRaw( player.p, pc->commodity, pc->quantity, pc->id );
245 else {
246 q = pfleet_cargoAddRaw( pc->commodity, pc->quantity );
247 /* When landed, just stuff everything on the player's ship as they may
248 * not be ready for take-off yet. */
249 if ( landed && ( q < pc->quantity ) )
250 q += pilot_cargoAddRaw( player.p, pc->commodity, pc->quantity - q,
251 pc->id );
252 }
253#ifdef DEBUGGING
254 if ( q != pc->quantity )
255 WARN( _( "Failure to add cargo '%s' to player fleet. Only %d of %d "
256 "added." ),
257 pc->commodity->name, q, pc->quantity );
258#endif /* DEBUGGING */
259 (void)q;
260 }
261
262 array_free( pclist );
263}
264
272
279{
280 if ( player.p == NULL )
281 return 0;
282 int cargo_used = pilot_cargoUsed( player.p );
283 if ( player.fleet_capacity <= 0 )
284 return cargo_used;
285 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
286 const Escort_t *e = &player.p->escorts[i];
287 const Pilot *pe = pilot_get( e->id );
288 if ( pe == NULL )
289 continue;
290 if ( e->type != ESCORT_TYPE_FLEET )
291 continue;
292 cargo_used += pilot_cargoUsed( pe );
293 }
294 return cargo_used;
295}
296
303{
304 if ( player.p == NULL )
305 return 0;
306 int cargo_free = pilot_cargoFree( player.p );
307 if ( player.fleet_capacity <= 0 )
308 return cargo_free;
309 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
310 const Escort_t *e = &player.p->escorts[i];
311 const Pilot *pe = pilot_get( e->id );
312 if ( pe == NULL )
313 continue;
314 if ( e->type != ESCORT_TYPE_FLEET )
315 continue;
316 cargo_free += pilot_cargoFree( pe );
317 }
318 return cargo_free;
319}
320
325{
326 int misn_cargo = 0;
327 for ( int i = 0; i < array_size( player.p->commodities ); i++ ) {
328 PilotCommodity *pc = &player.p->commodities[i];
329 if ( !pc->id )
330 continue;
331 misn_cargo += pc->quantity;
332 }
333 /* Return minimum between free fleet space and minimum cargo space. */
334 return MIN( player.p->cap_cargo - misn_cargo, pfleet_cargoFree() );
335}
336
344{
345 if ( player.p == NULL )
346 return 0;
347 int amount = pilot_cargoOwned( player.p, com );
348 if ( player.fleet_capacity <= 0 )
349 return amount;
350 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
351 const Escort_t *e = &player.p->escorts[i];
352 const Pilot *pe = pilot_get( e->id );
353 if ( pe == NULL )
354 continue;
355 if ( e->type != ESCORT_TYPE_FLEET )
356 continue;
357 amount += pilot_cargoOwned( pe, com );
358 }
359 return amount;
360}
361
362static int pfleet_cargoAddRaw( const Commodity *com, int q )
363{
364 int added = pilot_cargoAdd( player.p, com, q, 0 );
365 if ( ( player.fleet_capacity <= 0 ) || ( q - added <= 0 ) )
366 return added;
367 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
368 const Escort_t *e = &player.p->escorts[i];
369 Pilot *pe = pilot_get( e->id );
370 if ( pe == NULL )
371 continue;
372 if ( e->type != ESCORT_TYPE_FLEET )
373 continue;
374 added += pilot_cargoAdd( pe, com, q - added, 0 );
375 if ( q - added <= 0 )
376 break;
377 }
378 return added;
379}
380
388int pfleet_cargoAdd( const Commodity *com, int q )
389{
390 if ( player.p == NULL )
391 return 0;
392 int amount = MIN( q, pfleet_cargoFree() );
394 memset( &pc, 0, sizeof( pc ) );
395 pc.commodity = com;
396 pc.quantity = amount;
398 return amount;
399}
400
408unsigned int pfleet_cargoMissionAdd( const Commodity *com, int q )
409{
410 if ( player.p == NULL )
411 return 0;
413 unsigned int id = pilot_genMissionCargoID( player.p );
414 memset( &pc, 0, sizeof( pc ) );
415 pc.commodity = com;
416 pc.quantity = q;
417 pc.id = id;
419 return id;
420}
421
430int pfleet_cargoRm( const Commodity *com, int q, int jet )
431{
432 int removed;
433 if ( player.p == NULL )
434 return 0;
435 if ( player.fleet_capacity <= 0 )
436 return pilot_cargoRm( player.p, com, q );
437 removed = 0;
438 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
439 const Escort_t *e = &player.p->escorts[i];
440 Pilot *pe = pilot_get( e->id );
441 if ( pe == NULL )
442 continue;
443 if ( e->type != ESCORT_TYPE_FLEET )
444 continue;
445
446 if ( jet )
447 removed += pilot_cargoJet( pe, com, q - removed, 0 );
448 else
449 removed += pilot_cargoRm( pe, com, q - removed );
450
451 if ( q - removed <= 0 )
452 break;
453 }
454 if ( q - removed > 0 ) {
455 if ( jet )
456 removed += pilot_cargoJet( player.p, com, q, 0 );
457 else
458 removed += pilot_cargoRm( player.p, com, q );
459 }
461 return removed;
462}
463
471{
473 shipCargo( &pclist, player.p, 0 );
474 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
475 const Escort_t *e = &player.p->escorts[i];
476 Pilot *pe = pilot_get( e->id );
477 if ( pe == NULL )
478 continue;
479 if ( e->type != ESCORT_TYPE_FLEET )
480 continue;
481 shipCargo( &pclist, pe, 0 );
482 }
483 return pclist;
484}
485
495{
497 int q = pilot_cargoOwned( player.p, com );
498 if ( q > 0 ) {
499 PFleetCargo fc = { .p = player.p, .q = q };
500 array_push_back( &plist, fc );
501 }
502 for ( int i = 0; i < array_size( player.p->escorts ); i++ ) {
503 const Escort_t *e = &player.p->escorts[i];
504 Pilot *pe = pilot_get( e->id );
505 if ( pe == NULL )
506 continue;
507 if ( e->type != ESCORT_TYPE_FLEET )
508 continue;
509 q = pilot_cargoOwned( pe, com );
510 if ( q > 0 ) {
511 PFleetCargo fc = { .p = pe, .q = q };
512 array_push_back( &plist, fc );
513 }
514 }
515 return plist;
516}
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_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_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
void tonnes2str(char *str, int tonnes)
Converts tonnes to a usable string for displaying.
Definition commodity.c:131
int dialogue_YesNo(const char *caption, const char *fmt,...)
Runs a dialogue with both yes and no options.
Definition dialogue.c:352
void equipment_updateShips(unsigned int wid, const char *str)
Updates the player's ship window.
Definition equipment.c:1992
int escort_clearDeployed(Pilot *p, int slot)
Clears deployed escorts of a pilot.
Definition escort.c:243
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:200
void escort_rmListIndex(Pilot *p, int i)
Remove from escorts list.
Definition escort.c:70
unsigned int land_getWid(int window)
Gets the WID of a window by type.
Definition land.c:1162
int landed
Definition land.c:78
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:39
void pilot_free(Pilot *p)
Frees and cleans up a pilot.
Definition pilot.c:3902
void pilot_stackRemove(Pilot *p)
Tries to remove a pilot from the stack.
Definition pilot.c:3992
void pilot_reset(Pilot *pilot)
Resets a pilot.
Definition pilot.c:3491
Pilot * pilot_get(unsigned int id)
Pulls a pilot out of the pilot_stack based on ID.
Definition pilot.c:640
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_cargoUsed(const Pilot *p)
Gets how much cargo ship has on board.
int pilot_cargoAddRaw(Pilot *pilot, const Commodity *cargo, int quantity, unsigned int id)
Adds cargo without checking the pilot's free space.
void pilot_cargoCalc(Pilot *pilot)
Calculates how much cargo ship has left and such.
int pilot_isSpaceworthy(const Pilot *p)
Pilot safety check - makes sure stats are safe.
void pilot_weaponAuto(Pilot *p)
Tries to automatically set and create the pilot's weapon set.
const PlayerShip_t * player_getShipStack(void)
Gets the array (array.h) of the player's ships.
Definition player.c:2804
Player_t player
Definition player.c:77
int pfleet_toggleDeploy(PlayerShip_t *ps, int deploy)
Toggles a player ship as deployed.
int pfleet_deploy(PlayerShip_t *ps)
Deploys a player's pilot.
PilotCommodity * pfleet_cargoList(void)
Gets a list of all the cargo in the fleet.
PFleetCargo * pfleet_cargoListShips(const Commodity *com)
Gets the list of ships that are carry a certain commodity in the player fleet and the amount they are...
unsigned int pfleet_cargoMissionAdd(const Commodity *com, int q)
Adds some mission cargo to the player's fleet.
int pfleet_cargoFree(void)
Gets the total amount of free cargo space in the player's fleet.
void pfleet_cargoRedistribute(void)
Redistributes the cargo in the player's fleet.
int pfleet_cargoOwned(const Commodity *com)
Gets the total amount of a commodity type owned by the player's fleet.
int pfleet_cargoAdd(const Commodity *com, int q)
Adds some cargo to the player's fleet.
int pfleet_cargoRm(const Commodity *com, int q, int jet)
Removes some cargo from the player's fleet.
int pfleet_cargoMissionFree(void)
Gets the free mission cargo space in the player's fleet.
int pfleet_cargoUsed(void)
Gets the total cargo space used by the player's fleet.
static void pfleet_cargoRedistributeInternal(PilotCommodity *pc_add)
Redistributes the cargo in the player's fleet.
void pfleet_update(void)
Updates the used fleet capacity of the player.
Represents a commodity.
Definition commodity.h:57
char * name
Definition commodity.h:58
double price
Definition commodity.h:67
Stores an escort.
Definition pilot.h:252
unsigned int id
Definition pilot.h:255
EscortType_t type
Definition pilot.h:254
Stores a pilot commodity.
Definition pilot.h:223
const Commodity * commodity
Definition pilot.h:224
unsigned int id
Definition pilot.h:226
The representation of an in-game pilot.
Definition pilot.h:263
const Ship * ship
Definition pilot.h:274
char * name
Definition pilot.h:265
Player ship.
Definition player.h:72
int deployed
Definition player.h:80
Pilot * p
Definition player.h:73
int points
Definition ship.h:110
Represents a 2d vector.
Definition vec2.h:45