naev 0.12.5
pilot_cargo.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "naev.h"
12
13#include "pilot_cargo.h"
14
15#include "array.h"
16#include "commodity.h"
17#include "gui.h"
18#include "log.h"
19#include "rng.h"
20
21/* Private common implementation */
22static int pilot_cargoAddInternal( Pilot *pilot, const Commodity *cargo,
23 int quantity, unsigned int id );
24
25/* ID Generators. */
26static unsigned int mission_cargo_id =
27 0;
30
38int pilot_cargoOwned( const Pilot *pilot, const Commodity *cargo )
39{
40 for ( int i = 0; i < array_size( pilot->commodities ); i++ )
41 if ( !pilot->commodities[i].id &&
42 strcmp( cargo->name, pilot->commodities[i].commodity->name ) == 0 )
43 return pilot->commodities[i].quantity;
44 return 0;
45}
46
53int pilot_cargoFree( const Pilot *p )
54{
55 return p->cargo_free;
56}
57
68int pilot_cargoMoveRaw( Pilot *dest, Pilot *src )
69{
70 /* Copy over. */
71 for ( int i = array_size( src->commodities ) - 1; i >= 0; i-- ) {
72 const PilotCommodity *pc = &src->commodities[i];
73 pilot_cargoAddRaw( dest, pc->commodity, pc->quantity, pc->id );
74 }
75 pilot_cargoRmAll( src, 1 );
76 /* Clean src. */
77 array_free( src->commodities );
78 src->commodities = NULL;
79 return 0;
80}
81
92int pilot_cargoMove( Pilot *dest, Pilot *src )
93{
94 /* Check if it fits. */
95 if ( pilot_cargoUsed( src ) > pilot_cargoFree( dest ) ) {
96 WARN( _( "Unable to copy cargo over from pilot '%s' to '%s'. Leaving "
97 "cargo as is." ),
98 src->name, dest->name );
99 return -1;
100 }
101
102 return pilot_cargoMoveRaw( dest, src );
103}
104
113static int pilot_cargoAddInternal( Pilot *pilot, const Commodity *cargo,
114 int quantity, unsigned int id )
115{
116 PilotCommodity *pc;
117 int q = quantity;
118 if ( q < 0 ) {
119 if ( id == 0 )
120 return 0;
121
122 /* We'll warn and clamp to 0 for missions. */
123 WARN( "Trying to add mission cargo with negative quantity! (q=%d)", q );
124 q = 0;
125 }
126
127 /* If not mission cargo check to see if already exists. */
128 if ( id == 0 ) {
129 for ( int i = 0; i < array_size( pilot->commodities ); i++ ) {
130 pc = &pilot->commodities[i];
131 if ( !pc->id && ( pc->commodity == cargo ) ) {
132 pc->quantity += q;
133 return q;
134 }
135 }
136 }
137
138 /* Create the memory space. */
139 if ( pilot->commodities == NULL )
141 pc = &array_grow( &pilot->commodities );
142 pc->commodity = cargo;
143 pc->id = id;
144 pc->quantity = q;
145
146 return q;
147}
148
159int pilot_cargoAddRaw( Pilot *pilot, const Commodity *cargo, int quantity,
160 unsigned int id )
161{
162 int q = pilot_cargoAddInternal( pilot, cargo, quantity, id );
163 pilot->cargo_free -= q;
164 pilot->mass_cargo += q;
165 pilot->solid.mass += pilot->stats.cargo_inertia * q;
166 pilot_updateMass( pilot );
167 gui_setGeneric( pilot );
168 return q;
169}
170
183int pilot_cargoAdd( Pilot *pilot, const Commodity *cargo, int quantity,
184 unsigned int id )
185{
186 /* Check to see how much to add. */
187 int freespace = pilot_cargoFree( pilot );
188 if ( freespace < quantity ) {
189 quantity = freespace;
190 if ( ( quantity == 0 ) && ( id == 0 ) )
191 return 0;
192 }
193
194 return pilot_cargoAddRaw( pilot, cargo, quantity, id );
195}
196
203int pilot_cargoUsed( const Pilot *p )
204{
205 int q = 0;
206 for ( int i = 0; i < array_size( p->commodities ); i++ )
207 q += p->commodities[i].quantity;
208 return q;
209}
210
218{
219 int q = 0;
220 for ( int i = 0; i < array_size( p->commodities ); i++ ) {
221 const PilotCommodity *pc = &p->commodities[i];
222 if ( pc->id > 0 )
223 q += pc->quantity;
224 }
225
226 return q;
227}
228
234void pilot_cargoCalc( Pilot *pilot )
235{
236 pilot->mass_cargo = pilot_cargoUsed( pilot );
237 pilot->cargo_free = pilot->cap_cargo - pilot->mass_cargo;
238 pilot_updateMass( pilot );
239}
240
249unsigned int pilot_addMissionCargo( Pilot *pilot, const Commodity *cargo,
250 int quantity )
251{
252 unsigned int id = pilot_genMissionCargoID( pilot );
253 /* Add the cargo. */
254 pilot_cargoAdd( pilot, cargo, quantity, id );
255 return id;
256}
257
258unsigned int pilot_genMissionCargoID( Pilot *pilot )
259{
260 unsigned int id, max_id;
261
262 /* Get ID. */
263 id = ++mission_cargo_id;
264
265 /* Check for collisions with pilot and set ID generator to the max. */
266 max_id = 0;
267 for ( int i = 0; i < array_size( pilot->commodities ); i++ )
268 max_id = MAX( max_id, pilot->commodities[i].id );
269 if ( max_id >= id )
270 id = mission_cargo_id = max_id + 1;
271 return id;
272}
273
282int pilot_rmMissionCargo( Pilot *pilot, unsigned int cargo_id, int jettison )
283{
284 int i;
285 /* check if pilot has it */
286 for ( i = 0; i < array_size( pilot->commodities ); i++ )
287 if ( pilot->commodities[i].id == cargo_id )
288 break;
289 if ( i >= array_size( pilot->commodities ) )
290 return 1; /* pilot doesn't have it */
291
292 if ( jettison )
293 pilot_cargoJet( pilot, pilot->commodities[i].commodity,
294 pilot->commodities[i].quantity, 1 );
295
296 /* remove cargo */
297 pilot->cargo_free += pilot->commodities[i].quantity;
298 pilot->mass_cargo -= pilot->commodities[i].quantity;
299 pilot->solid.mass -=
300 pilot->stats.cargo_inertia * pilot->commodities[i].quantity;
301 array_erase( &pilot->commodities, &pilot->commodities[i],
302 &pilot->commodities[i + 1] );
303 if ( array_size( pilot->commodities ) <= 0 ) {
304 array_free( pilot->commodities );
305 pilot->commodities = NULL;
306 }
307
308 /* Update mass. */
309 pilot_updateMass( pilot );
310 gui_setGeneric( pilot );
311
312 return 0;
313}
314
325int pilot_cargoRmRaw( Pilot *pilot, const Commodity *cargo, int quantity,
326 int cleanup )
327{
328 /* Check if pilot has it */
329 int q = quantity;
330 for ( int i = 0; i < array_size( pilot->commodities ); i++ ) {
331 if ( pilot->commodities[i].commodity != cargo )
332 continue;
333
334 /* Must not be mission cargo unless cleaning up. */
335 if ( !cleanup && ( pilot->commodities[i].id != 0 ) )
336 continue;
337
338 if ( quantity >= pilot->commodities[i].quantity ) {
339 q = pilot->commodities[i].quantity;
340
341 /* remove cargo */
342 array_erase( &pilot->commodities, &pilot->commodities[i],
343 &pilot->commodities[i + 1] );
344 if ( array_size( pilot->commodities ) <= 0 ) {
345 array_free( pilot->commodities );
346 pilot->commodities = NULL;
347 }
348 } else
349 pilot->commodities[i].quantity -= q;
350 pilot->cargo_free += q;
351 pilot->mass_cargo -= q;
352 pilot->solid.mass -= pilot->stats.cargo_inertia * q;
353 pilot_updateMass( pilot );
354 /* This can call Lua code and be called during takeoff (pilot cleanup),
355 * causing the Lua code to be run with a half-assed pilot state crashing
356 * the game. */
357 if ( !cleanup )
358 gui_setGeneric( pilot );
359 return q;
360 }
361 return 0; /* pilot didn't have it */
362}
363
371int pilot_cargoRmAll( Pilot *pilot, int cleanup )
372{
373 /* No commodities. */
374 if ( pilot->commodities == NULL )
375 return 0;
376
377 /* Check if pilot has it */
378 int q = 0;
379 for ( int i = array_size( pilot->commodities ) - 1; i >= 0; i-- ) {
380 /* Must not be mission cargo unless cleaning up. */
381 if ( !cleanup && ( pilot->commodities[i].id != 0 ) )
382 continue;
383
384 q += pilot->commodities[i].quantity;
385 array_erase( &pilot->commodities, &pilot->commodities[i],
386 &pilot->commodities[i + 1] );
387 }
388
389 if ( array_size( pilot->commodities ) <= 0 ) {
390 array_free( pilot->commodities );
391 pilot->commodities = NULL;
392 }
393
394 pilot->cargo_free += q;
395 pilot->mass_cargo -= q;
396 pilot->solid.mass -= pilot->stats.cargo_inertia * q;
397 pilot_updateMass( pilot );
398
399 /* If we're updating this ship's status, communicate the update to the GUI.
400 * Caution: it could make sense to communicate a deletion, but particularly
401 * in the middle of pilots_clean() that's unsafe. */
402 if ( !cleanup )
403 gui_setGeneric( pilot );
404 return q;
405}
406
415int pilot_cargoRm( Pilot *pilot, const Commodity *cargo, int quantity )
416{
417 return pilot_cargoRmRaw( pilot, cargo, quantity, 0 );
418}
419
429int pilot_cargoJet( Pilot *p, const Commodity *cargo, int quantity,
430 int simulate )
431{
432 int n;
433 double px, py, bvx, bvy;
434
435 if ( !simulate )
436 quantity = pilot_cargoRmRaw( p, cargo, quantity, 0 );
437
438 n = MAX( 1, RNG( (int)( quantity / 10 ), (int)( quantity / 5 ) ) );
439 px = p->solid.pos.x;
440 py = p->solid.pos.y;
441 bvx = p->solid.vel.x;
442 bvy = p->solid.vel.y;
443 for ( int i = 0; i < n; i++ ) {
444 int effect = spfx_get( "cargo" );
445
446 /* Radial distribution gives much nicer results */
447 double r = RNGF() * 25. - 12.5;
448 double a = 2. * M_PI * RNGF();
449 double vx = bvx + r * cos( a );
450 double vy = bvy + r * sin( a );
451
452 /* Add the cargo effect */
453 spfx_add( effect, px, py, vx, vy, SPFX_LAYER_BACK );
454 }
455
456 return quantity;
457}
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_grow(ptr_array)
Increases the number of elements by one and returns the last element.
Definition array.h:122
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
void gui_setGeneric(const Pilot *pilot)
Calls trigger functions depending on who the pilot is.
Definition gui.c:1913
Header file with generic functions and naev-specifics.
#define MAX(x, y)
Definition naev.h:37
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_cargoMove(Pilot *dest, Pilot *src)
Moves cargo from one pilot to another.
Definition pilot_cargo.c:92
int pilot_cargoMoveRaw(Pilot *dest, Pilot *src)
Moves cargo from one pilot to another without any checks.
Definition pilot_cargo.c:68
unsigned int pilot_addMissionCargo(Pilot *pilot, const Commodity *cargo, int quantity)
Adds special mission cargo, can't sell it and such.
int pilot_cargoRm(Pilot *pilot, const Commodity *cargo, int quantity)
Tries to get rid of quantity cargo from pilot.
static int pilot_cargoAddInternal(Pilot *pilot, const Commodity *cargo, int quantity, unsigned int id)
Adds cargo to the pilot's "commodities" array only.
int pilot_cargoRmRaw(Pilot *pilot, const Commodity *cargo, int quantity, int cleanup)
Tries to get rid of quantity cargo from pilot. Can remove mission cargo.
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_cargoUsedMission(const Pilot *p)
Gets how much mission cargo ship has on board.
int pilot_rmMissionCargo(Pilot *pilot, unsigned int cargo_id, int jettison)
Removes special mission cargo based on id.
static unsigned int mission_cargo_id
Definition pilot_cargo.c:26
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.
void pilot_updateMass(Pilot *pilot)
Updates the pilot stats after mass change.
int spfx_get(const char *name)
Gets the id of an spfx based on name.
Definition spfx.c:355
void spfx_add(int effect, const double px, const double py, const double vx, const double vy, int layer)
Creates a new special effect.
Definition spfx.c:504
Represents a commodity.
Definition commodity.h:57
char * name
Definition commodity.h:58
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
ShipStats stats
Definition pilot.h:348
PilotCommodity * commodities
Definition pilot.h:383
double mass_cargo
Definition pilot.h:277
Solid solid
Definition pilot.h:275
char * name
Definition pilot.h:265
int cargo_free
Definition pilot.h:384
double cap_cargo
Definition pilot.h:288
double cargo_inertia
Definition shipstats.h:271
double mass
Definition physics.h:45