naev 0.11.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"
13#include "pilot_cargo.h"
14
15#include "array.h"
16#include "economy.h"
17#include "gui.h"
18#include "log.h"
19
20/* Private common implementation */
21static int pilot_cargoAddInternal( Pilot* pilot, const Commodity* cargo,
22 int quantity, unsigned int id );
23
24/* ID Generators. */
25static unsigned int mission_cargo_id = 0;
36int pilot_cargoOwned( const Pilot* pilot, const Commodity* cargo )
37{
38 for (int i=0; i<array_size(pilot->commodities); i++)
39 if (!pilot->commodities[i].id &&
40 strcmp(cargo->name, pilot->commodities[i].commodity->name)==0)
41 return pilot->commodities[i].quantity;
42 return 0;
43}
44
51int pilot_cargoFree( const Pilot* p )
52{
53 return p->cargo_free;
54}
55
65int pilot_cargoMoveRaw( Pilot *dest, Pilot *src )
66{
67 /* Copy over. */
68 for (int i=array_size(src->commodities)-1; i>=0; i--) {
69 const PilotCommodity *pc = &src->commodities[i];
70 pilot_cargoAddRaw( dest, pc->commodity, pc->quantity, pc->id );
71 }
72 pilot_cargoRmAll( src, 1 );
73 /* Clean src. */
75 src->commodities = NULL;
76 return 0;
77}
78
88int pilot_cargoMove( Pilot* dest, Pilot* src )
89{
90 /* Check if it fits. */
91 if (pilot_cargoUsed(src) > pilot_cargoFree(dest)) {
92 WARN(_("Unable to copy cargo over from pilot '%s' to '%s'. Leaving cargo as is."), src->name, dest->name );
93 return -1;
94 }
95
96 return pilot_cargoMoveRaw( dest, src );
97}
98
107static int pilot_cargoAddInternal( Pilot* pilot, const Commodity* cargo,
108 int quantity, unsigned int id )
109{
110 PilotCommodity *pc;
111 int q = quantity;
112
113 /* If not mission cargo check to see if already exists. */
114 if (id == 0) {
115 for (int i=0; i<array_size(pilot->commodities); i++) {
116 pc = &pilot->commodities[i];
117 if (!pc->id && (pc->commodity == cargo)) {
118 pc->quantity += q;
119 return q;
120 }
121 }
122 }
123
124 /* Create the memory space. */
125 if (pilot->commodities == NULL)
127 pc = &array_grow( &pilot->commodities );
128 pc->commodity = cargo;
129 pc->id = id;
130 pc->quantity = q;
131
132 return q;
133}
134
145int pilot_cargoAddRaw( Pilot* pilot, const Commodity* cargo,
146 int quantity, unsigned int id )
147{
148 int q = pilot_cargoAddInternal( pilot, cargo, quantity, id );
149 pilot->cargo_free -= q;
150 pilot->mass_cargo += q;
151 pilot->solid.mass += pilot->stats.cargo_inertia * q;
152 pilot_updateMass( pilot );
153 gui_setGeneric( pilot );
154
155 return q;
156}
157
169int pilot_cargoAdd( Pilot* pilot, const Commodity* cargo,
170 int quantity, unsigned int id )
171{
172 /* Check to see how much to add. */
173 int freespace = pilot_cargoFree(pilot);
174 if (freespace < quantity) {
175 quantity = freespace;
176 if ((quantity==0) && (id==0))
177 return 0;
178 }
179
180 return pilot_cargoAddRaw( pilot, cargo, quantity, id );
181}
182
189int pilot_cargoUsed( const Pilot* p )
190{
191 int q = 0;
192 for (int i=0; i<array_size(p->commodities); i++)
193 q += p->commodities[i].quantity;
194 return q;
195}
196
204{
205 int q = 0;
206 for (int i=0; i<array_size(p->commodities); i++) {
207 const PilotCommodity *pc = &p->commodities[i];
208 if (pc->id > 0)
209 q += pc->quantity;
210 }
211
212 return q;
213}
214
220void pilot_cargoCalc( Pilot* pilot )
221{
222 pilot->mass_cargo = pilot_cargoUsed( pilot );
223 pilot->cargo_free = pilot->cap_cargo - pilot->mass_cargo;
224 pilot_updateMass( pilot );
225}
226
235unsigned int pilot_addMissionCargo( Pilot* pilot, const Commodity* cargo, int quantity )
236{
237 unsigned int id, max_id;
238
239 /* Get ID. */
240 id = ++mission_cargo_id;
241
242 /* Check for collisions with pilot and set ID generator to the max. */
243 max_id = 0;
244 for (int i=0; i<array_size(pilot->commodities); i++)
245 max_id = MAX( max_id, pilot->commodities[i].id );
246 if (max_id >= id)
247 id = mission_cargo_id = max_id+1;
248
249 /* Add the cargo. */
250 pilot_cargoAdd( pilot, cargo, quantity, id );
251
252 return id;
253}
254
263int pilot_rmMissionCargo( Pilot* pilot, unsigned int cargo_id, int jettison )
264{
265 int i;
266 /* check if pilot has it */
267 for (i=0; i<array_size(pilot->commodities); i++)
268 if (pilot->commodities[i].id == cargo_id)
269 break;
270 if (i >= array_size(pilot->commodities))
271 return 1; /* pilot doesn't have it */
272
273 if (jettison)
274 pilot_cargoJet( pilot, pilot->commodities[i].commodity,
275 pilot->commodities[i].quantity, 1 );
276
277 /* remove cargo */
278 pilot->cargo_free += pilot->commodities[i].quantity;
279 pilot->mass_cargo -= pilot->commodities[i].quantity;
280 pilot->solid.mass -= pilot->stats.cargo_inertia * pilot->commodities[i].quantity;
281 array_erase( &pilot->commodities, &pilot->commodities[i], &pilot->commodities[i+1] );
282 if (array_size(pilot->commodities) <= 0) {
283 array_free( pilot->commodities );
284 pilot->commodities = NULL;
285 }
286
287 /* Update mass. */
288 pilot_updateMass( pilot );
289 gui_setGeneric( pilot );
290
291 return 0;
292}
293
303int pilot_cargoRmRaw( Pilot* pilot, const Commodity* cargo, int quantity, int cleanup )
304{
305 /* Check if pilot has it */
306 int q = quantity;
307 for (int i=0; i<array_size(pilot->commodities); i++) {
308 if (pilot->commodities[i].commodity != cargo)
309 continue;
310
311 /* Must not be mission cargo unless cleaning up. */
312 if (!cleanup && (pilot->commodities[i].id != 0))
313 continue;
314
315 if (quantity >= pilot->commodities[i].quantity) {
316 q = pilot->commodities[i].quantity;
317
318 /* remove cargo */
319 array_erase( &pilot->commodities, &pilot->commodities[i], &pilot->commodities[i+1] );
320 if (array_size(pilot->commodities) <= 0) {
321 array_free( pilot->commodities );
322 pilot->commodities = NULL;
323 }
324 }
325 else
326 pilot->commodities[i].quantity -= q;
327 pilot->cargo_free += q;
328 pilot->mass_cargo -= q;
329 pilot->solid.mass -= pilot->stats.cargo_inertia * q;
330 pilot_updateMass( pilot );
331 /* This can call Lua code and be called during takeoff (pilot cleanup), causing
332 * the Lua code to be run with a half-assed pilot state crashing the game. */
333 if (!cleanup)
334 gui_setGeneric( pilot );
335 return q;
336 }
337 return 0; /* pilot didn't have it */
338}
339
347int pilot_cargoRmAll( Pilot* pilot, int cleanup )
348{
349 /* No commodities. */
350 if (pilot->commodities == NULL)
351 return 0;
352
353 /* Check if pilot has it */
354 int q = 0;
355 for (int i=array_size(pilot->commodities)-1; i>=0; i--) {
356 /* Must not be mission cargo unless cleaning up. */
357 if (!cleanup && (pilot->commodities[i].id != 0))
358 continue;
359
360 q += pilot->commodities[i].quantity;
361 array_erase( &pilot->commodities, &pilot->commodities[i], &pilot->commodities[i+1] );
362 }
363
364 if (array_size(pilot->commodities) <= 0) {
365 array_free( pilot->commodities );
366 pilot->commodities = NULL;
367 }
368
369 pilot->cargo_free += q;
370 pilot->mass_cargo -= q;
371 pilot->solid.mass -= pilot->stats.cargo_inertia * q;
372 pilot_updateMass( pilot );
373
374 /* If we're updating this ship's status, communicate the update to the GUI.
375 * Caution: it could make sense to communicate a deletion, but particularly in the middle of pilots_clean() that's unsafe. */
376 if (!cleanup)
377 gui_setGeneric( pilot );
378 return q;
379}
380
389int pilot_cargoRm( Pilot* pilot, const Commodity* cargo, int quantity )
390{
391 return pilot_cargoRmRaw( pilot, cargo, quantity, 0 );
392}
393
403int pilot_cargoJet( Pilot *p, const Commodity *cargo, int quantity, int simulate )
404{
405 int n;
406 double px,py, bvx, bvy;
407
408 if (!simulate)
409 quantity = pilot_cargoRmRaw( p, cargo, quantity, 0 );
410
411 n = MAX( 1, RNG((int)(quantity/10), (int)(quantity/5)) );
412 px = p->solid.pos.x;
413 py = p->solid.pos.y;
414 bvx = p->solid.vel.x;
415 bvy = p->solid.vel.y;
416 for (int i=0; i<n; i++) {
417 int effect = spfx_get("cargo");
418
419 /* Radial distribution gives much nicer results */
420 double r = RNGF()*25. - 12.5;
421 double a = 2. * M_PI * RNGF();
422 double vx = bvx + r*cos(a);
423 double vy = bvy + r*sin(a);
424
425 /* Add the cargo effect */
426 spfx_add( effect, px, py, vx, vy, SPFX_LAYER_BACK );
427 }
428
429 return quantity;
430}
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
void gui_setGeneric(const Pilot *pilot)
Calls trigger functions depending on who the pilot is.
Definition gui.c:1824
Header file with generic functions and naev-specifics.
#define MAX(x, y)
Definition naev.h:39
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:51
int pilot_cargoMove(Pilot *dest, Pilot *src)
Moves cargo from one pilot to another.
Definition pilot_cargo.c:88
int pilot_cargoMoveRaw(Pilot *dest, Pilot *src)
Moves cargo from one pilot to another without any checks.
Definition pilot_cargo.c:65
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:36
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:25
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:342
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:475
Represents a commodity.
Definition commodity.h:43
char * name
Definition commodity.h:44
Stores a pilot commodity.
Definition pilot.h:179
const Commodity * commodity
Definition pilot.h:180
unsigned int id
Definition pilot.h:182
The representation of an in-game pilot.
Definition pilot.h:217
ShipStats stats
Definition pilot.h:294
PilotCommodity * commodities
Definition pilot.h:326
double mass_cargo
Definition pilot.h:229
Solid solid
Definition pilot.h:227
char * name
Definition pilot.h:219
int cargo_free
Definition pilot.h:327
double cap_cargo
Definition pilot.h:239
double cargo_inertia
Definition shipstats.h:238
double mass
Definition physics.h:45