naev 0.10.4
shipstats.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 "shipstats.h"
14
15#include "log.h"
16#include "nstring.h"
17
21typedef enum StatDataType_ {
28
34typedef struct ShipStatsLookup_ {
35 /* Explicitly set. */
36 ShipStatsType type;
37 const char *name;
38 const char *display;
44 /* Self calculated. */
45 size_t offset;
47
48/* Flexible do everything macro. */
49#define ELEM( t, n, dsp, d , i) \
50 { .type=t, .name=#n, .display=dsp, .data=d, .inverted=i, .offset=offsetof( ShipStats, n ) }
51/* Standard types. */
52#define D__ELEM( t, n, dsp ) \
53 ELEM( t, n, dsp, SS_DATA_TYPE_DOUBLE, 0 )
54#define A__ELEM( t, n, dsp ) \
55 ELEM( t, n, dsp, SS_DATA_TYPE_DOUBLE_ABSOLUTE, 0 )
56#define P__ELEM( t, n, dsp ) \
57 ELEM( t, n, dsp, SS_DATA_TYPE_DOUBLE_ABSOLUTE_PERCENT, 0 )
58#define I__ELEM( t, n, dsp ) \
59 ELEM( t, n, dsp, SS_DATA_TYPE_INTEGER, 0 )
60#define B__ELEM( t, n, dsp ) \
61 ELEM( t, n, dsp, SS_DATA_TYPE_BOOLEAN, 0 )
62/* Inverted types. */
63#define DI_ELEM( t, n, dsp ) \
64 ELEM( t, n, dsp, SS_DATA_TYPE_DOUBLE, 1 )
65#define AI_ELEM( t, n, dsp ) \
66 ELEM( t, n, dsp, SS_DATA_TYPE_DOUBLE_ABSOLUTE, 1 )
67#define PI_ELEM( t, n, dsp ) \
68 ELEM( t, n, dsp, SS_DATA_TYPE_DOUBLE_ABSOLUTE_PERCENT, 1 )
69#define II_ELEM( t, n, dsp ) \
70 ELEM( t, n, dsp, SS_DATA_TYPE_INTEGER, 1 )
71#define BI_ELEM( t, n, dsp ) \
72 ELEM( t, n, dsp, SS_DATA_TYPE_BOOLEAN, 1 )
74#define N__ELEM( t ) \
75 { .type=t, .name=NULL, .display=NULL, .inverted=0, .offset=0 }
76
80static const ShipStatsLookup ss_lookup[] = {
81 /* Null element. */
82 N__ELEM( SS_TYPE_NIL ),
83
84 D__ELEM( SS_TYPE_D_SPEED_MOD, speed_mod, N_("Speed") ),
85 D__ELEM( SS_TYPE_D_TURN_MOD, turn_mod, N_("Turn") ),
86 D__ELEM( SS_TYPE_D_THRUST_MOD, thrust_mod, N_("Thrust") ),
87 D__ELEM( SS_TYPE_D_CARGO_MOD, cargo_mod, N_("Cargo Space") ),
88 D__ELEM( SS_TYPE_D_FUEL_MOD, fuel_mod, N_("Fuel Cpacity") ),
89 D__ELEM( SS_TYPE_D_ARMOUR_MOD, armour_mod, N_("Armour Strength") ),
90 D__ELEM( SS_TYPE_D_ARMOUR_REGEN_MOD, armour_regen_mod, N_("Armour Regeneration") ),
91 D__ELEM( SS_TYPE_D_SHIELD_MOD, shield_mod, N_("Shield Strength") ),
92 D__ELEM( SS_TYPE_D_SHIELD_REGEN_MOD, shield_regen_mod, N_("Shield Regeneration") ),
93 D__ELEM( SS_TYPE_D_ENERGY_MOD, energy_mod, N_("Energy Capacity") ),
94 D__ELEM( SS_TYPE_D_ENERGY_REGEN_MOD, energy_regen_mod, N_("Energy Regeneration") ),
95 D__ELEM( SS_TYPE_D_CPU_MOD, cpu_mod, N_("CPU Capacity") ),
96 DI_ELEM( SS_TYPE_D_COOLDOWN_MOD, cooldown_mod, N_("Ability Cooldown") ),
97
98 DI_ELEM( SS_TYPE_D_JUMP_DELAY, jump_delay, N_("Jump Time") ),
99 DI_ELEM( SS_TYPE_D_LAND_DELAY, land_delay, N_("Landing Time") ),
100 DI_ELEM( SS_TYPE_D_CARGO_INERTIA, cargo_inertia, N_("Cargo Inertia") ),
101
102 D__ELEM( SS_TYPE_D_EW_HIDE, ew_hide, N_("Concealment") ),
103 D__ELEM( SS_TYPE_D_EW_EVADE, ew_evade, N_("Evasion") ),
104 D__ELEM( SS_TYPE_D_EW_STEALTH, ew_stealth, N_("Stealth") ),
105 D__ELEM( SS_TYPE_D_EW_DETECT, ew_detect, N_("Detection") ),
106 D__ELEM( SS_TYPE_D_EW_TRACK, ew_track, N_("Tracking") ),
107 D__ELEM( SS_TYPE_D_EW_JUMPDETECT, ew_jump_detect, N_("Jump Detection") ),
108 DI_ELEM( SS_TYPE_D_EW_STEALTH_TIMER, ew_stealth_timer, N_("Stealth Discovered Speed") ),
109 DI_ELEM( SS_TYPE_D_EW_SCANNED_TIME, ew_scanned_time, N_("Scanned Speed") ),
110
111 D__ELEM( SS_TYPE_D_LAUNCH_RATE, launch_rate, N_("Fire Rate (Launcher)") ),
112 D__ELEM( SS_TYPE_D_LAUNCH_RANGE, launch_range, N_("Launch Range") ),
113 D__ELEM( SS_TYPE_D_LAUNCH_DAMAGE, launch_damage, N_("Damage (Launcher)") ),
114 D__ELEM( SS_TYPE_D_AMMO_CAPACITY, ammo_capacity, N_("Ammo Capacity") ),
115 DI_ELEM( SS_TYPE_D_LAUNCH_LOCKON, launch_lockon, N_("Launch Lock-on") ),
116 DI_ELEM( SS_TYPE_D_LAUNCH_CALIBRATION, launch_calibration, N_("Launch Calibration") ),
117 D__ELEM( SS_TYPE_D_LAUNCH_RELOAD, launch_reload, N_("Ammo Reload Rate") ),
118
119 D__ELEM( SS_TYPE_D_FBAY_DAMAGE, fbay_damage, N_("Fighter Damage") ),
120 D__ELEM( SS_TYPE_D_FBAY_HEALTH, fbay_health, N_("Fighter Health") ),
121 D__ELEM( SS_TYPE_D_FBAY_MOVEMENT, fbay_movement, N_("Fighter Movement") ),
122 D__ELEM( SS_TYPE_D_FBAY_CAPACITY, fbay_capacity, N_("Fighter Bay Capacity") ),
123 D__ELEM( SS_TYPE_D_FBAY_RATE, fbay_rate, N_("Fighter Bay Launch Rate") ),
124 D__ELEM( SS_TYPE_D_FBAY_RELOAD, fbay_reload, N_("Fighter Reload Rate") ),
125
126 DI_ELEM( SS_TYPE_D_FORWARD_HEAT, fwd_heat, N_("Heat (Cannon)") ),
127 D__ELEM( SS_TYPE_D_FORWARD_DAMAGE, fwd_damage, N_("Damage (Cannon)") ),
128 D__ELEM( SS_TYPE_D_FORWARD_FIRERATE, fwd_firerate, N_("Fire Rate (Cannon)") ),
129 DI_ELEM( SS_TYPE_D_FORWARD_ENERGY, fwd_energy, N_("Energy Usage (Cannon)") ),
130 D__ELEM( SS_TYPE_D_FORWARD_DAMAGE_AS_DISABLE,fwd_dam_as_dis,N_("Damage as Disable (Cannon)") ),
131
132 DI_ELEM( SS_TYPE_D_TURRET_HEAT, tur_heat, N_("Heat (Turret)") ),
133 D__ELEM( SS_TYPE_D_TURRET_DAMAGE, tur_damage, N_("Damage (Turret)") ),
134 D__ELEM( SS_TYPE_D_TURRET_TRACKING, tur_tracking, N_("Tracking (Turret)") ),
135 D__ELEM( SS_TYPE_D_TURRET_FIRERATE, tur_firerate, N_("Fire Rate (Turret)") ),
136 DI_ELEM( SS_TYPE_D_TURRET_ENERGY, tur_energy, N_("Energy Usage (Turret)") ),
137 D__ELEM( SS_TYPE_D_TURRET_DAMAGE_AS_DISABLE, tur_dam_as_dis,N_("Damage as Disable (Turret)") ),
138
139 D__ELEM( SS_TYPE_D_HEAT_DISSIPATION, heat_dissipation, N_("Heat Dissipation") ),
140 D__ELEM( SS_TYPE_D_STRESS_DISSIPATION, stress_dissipation, N_("Stress Dissipation") ),
141 D__ELEM( SS_TYPE_D_CREW, crew_mod, N_("Crew") ),
142 DI_ELEM( SS_TYPE_D_MASS, mass_mod, N_("Ship Mass") ),
143 D__ELEM( SS_TYPE_D_ENGINE_LIMIT_REL, engine_limit_rel, N_("Engine Mass Limit") ),
144 D__ELEM( SS_TYPE_D_LOOT_MOD, loot_mod, N_("Boarding Bonus") ),
145 DI_ELEM( SS_TYPE_D_TIME_MOD, time_mod, N_("Time Constant") ),
146 D__ELEM( SS_TYPE_D_TIME_SPEEDUP, time_speedup, N_("Action Speed") ),
147 DI_ELEM( SS_TYPE_D_COOLDOWN_TIME, cooldown_time, N_("Ship Cooldown Time") ),
148 D__ELEM( SS_TYPE_D_JUMP_DISTANCE, jump_distance, N_("Jump Distance") ),
149 DI_ELEM( SS_TYPE_D_JUMP_WARMUP, jump_warmup, N_("Jump Warmup") ),
150 D__ELEM( SS_TYPE_D_MINING_BONUS, mining_bonus, N_("Mining Bonus") ),
151
152 A__ELEM( SS_TYPE_A_THRUST, thrust, N_("kN/tonne Thrust") ),
153 A__ELEM( SS_TYPE_A_TURN, turn, N_("deg/s Turn Rate") ),
154 A__ELEM( SS_TYPE_A_SPEED, speed, N_("m/s Maximum Speed") ),
155 A__ELEM( SS_TYPE_A_ENERGY, energy, N_("MJ Energy Capacity") ),
156 A__ELEM( SS_TYPE_A_ENERGY_REGEN, energy_regen, N_("MW Energy Regeneration") ),
157 AI_ELEM( SS_TYPE_A_ENERGY_REGEN_MALUS, energy_regen_malus, N_("MW Energy Usage") ),
158 AI_ELEM( SS_TYPE_A_ENERGY_LOSS, energy_loss, N_("MW Energy Usage") ),
159 A__ELEM( SS_TYPE_A_SHIELD, shield, N_("MJ Shield Capacity") ),
160 A__ELEM( SS_TYPE_A_SHIELD_REGEN, shield_regen, N_("MW Shield Regeneration") ),
161 AI_ELEM( SS_TYPE_A_SHIELD_REGEN_MALUS, shield_regen_malus, N_("MW Shield Usage") ),
162 A__ELEM( SS_TYPE_A_ARMOUR, armour, N_("MJ Armour") ),
163 A__ELEM( SS_TYPE_A_ARMOUR_REGEN, armour_regen, N_("MW Armour Regeneration") ),
164 AI_ELEM( SS_TYPE_A_ARMOUR_REGEN_MALUS, armour_regen_malus, N_("MW Armour Damage") ),
165 A__ELEM( SS_TYPE_A_DAMAGE, damage, N_("MW Damage") ),
166 A__ELEM( SS_TYPE_A_DISABLE, disable, N_("MW Disable") ),
167
168 A__ELEM( SS_TYPE_A_CPU_MAX, cpu_max, N_("CPU Capacity") ),
169 A__ELEM( SS_TYPE_A_ENGINE_LIMIT, engine_limit, N_("Engine Mass Limit") ),
170 A__ELEM( SS_TYPE_A_FUEL_REGEN, fuel_regen, N_("Fuel Regeneration") ),
171 A__ELEM( SS_TYPE_A_ASTEROID_SCAN, asteroid_scan, N_("Asteroid Scanner Range") ),
172 A__ELEM( SS_TYPE_A_NEBULA_VISIBILITY, nebu_visibility, N_("Nebula Visibility") ),
173
174 P__ELEM( SS_TYPE_P_ABSORB, absorb, N_("Damage Absorption") ),
175
176 P__ELEM( SS_TYPE_P_NEBULA_ABSORB, nebu_absorb, N_("Nebula Resistance") ),
177 P__ELEM( SS_TYPE_P_JAMMING_CHANCE, jam_chance, N_("Missile jamming chance") ),
178
179 I__ELEM( SS_TYPE_I_FUEL, fuel, N_("units Fuel") ),
180 I__ELEM( SS_TYPE_I_CARGO, cargo, N_("tonnes Cargo Space") ),
181 I__ELEM( SS_TYPE_I_CREW, crew, N_("crew") ),
182
183 B__ELEM( SS_TYPE_B_HIDDEN_JUMP_DETECT, misc_hidden_jump_detect, N_("Hidden Jump Detection") ),
184 B__ELEM( SS_TYPE_B_INSTANT_JUMP, misc_instant_jump, N_("Instant Jump") ),
185 B__ELEM( SS_TYPE_B_REVERSE_THRUST, misc_reverse_thrust, N_("Reverse Thrusters") ),
186
187 /* Sentinel. */
188 N__ELEM( SS_TYPE_SENTINEL )
189};
190
191/*
192 * Prototypes.
193 */
194static const char* ss_printD_colour( double d, const ShipStatsLookup *sl );
195static const char* ss_printI_colour( int i, const ShipStatsLookup *sl );
196static int ss_printD( char *buf, int len, int newline, double d, const ShipStatsLookup *sl );
197static int ss_printA( char *buf, int len, int newline, double d, const ShipStatsLookup *sl );
198static int ss_printI( char *buf, int len, int newline, int i, const ShipStatsLookup *sl );
199static int ss_printB( char *buf, int len, int newline, int b, const ShipStatsLookup *sl );
200static double ss_statsGetInternal( const ShipStats *s, ShipStatsType type );
201static int ss_statsGetLuaInternal( lua_State *L, const ShipStats *s, ShipStatsType type, int internal );
202
209ShipStatList* ss_listFromXML( xmlNodePtr node )
210{
211 const ShipStatsLookup *sl;
212 ShipStatList *ll;
213 ShipStatsType type;
214
215 /* Try to get type. */
216 type = ss_typeFromName( (char*) node->name );
217 if (type == SS_TYPE_NIL)
218 return NULL;
219
220 /* Allocate. */
221 ll = malloc( sizeof(ShipStatList) );
222 ll->next = NULL;
223 ll->target = 0;
224 ll->type = type;
225
226 /* Set the data. */
227 sl = &ss_lookup[ type ];
228 switch (sl->data) {
231 ll->d.d = xml_getFloat(node) / 100.;
232 break;
233
235 ll->d.d = xml_getFloat(node);
236 break;
237
239 ll->d.i = !!xml_getInt(node);
240 break;
241
243 ll->d.i = xml_getInt(node);
244 break;
245 }
246
247 /* Sort them. */
248 ss_sort( &ll );
249
250 return ll;
251}
252
260int ss_listToXML( xmlTextWriterPtr writer, const ShipStatList *ll )
261{
262 for (const ShipStatList *l=ll; l!=NULL; l=l->next) {
263 const ShipStatsLookup *sl = &ss_lookup[ l->type ];
264 switch (sl->data) {
267 xmlw_elem( writer, sl->name, "%f", l->d.d * 100 );
268 break;
269
271 xmlw_elem( writer, sl->name, "%f", l->d.d );
272 break;
273
276 xmlw_elem( writer, sl->name, "%d", l->d.i );
277 break;
278 }
279 }
280 return 0;
281}
282
283static int shipstat_sort( const void *a, const void *b )
284{
285 const ShipStatList **la = (const ShipStatList**) a;
286 const ShipStatList **lb = (const ShipStatList**) b;
287 const ShipStatsLookup *sla = &ss_lookup[ (*la)->type ];
288 const ShipStatsLookup *slb = &ss_lookup[ (*lb)->type ];
289 return strcmp( sla->name, slb->name );
290}
291
299{
300 int n, i;
301 ShipStatList **arr;
302
303 /* Nothing to do. */
304 if (*ll==NULL)
305 return 0;
306
307 n = 0;
308 for (ShipStatList *l=*ll; l!=NULL; l=l->next)
309 n++;
310
311 arr = malloc( sizeof(ShipStatList*) * n );
312 i = 0;
313 for (ShipStatList *l=*ll; l!=NULL; l=l->next) {
314 arr[i] = l;
315 i++;
316 }
317 qsort( arr, n, sizeof(ShipStatList*), shipstat_sort );
318
319 *ll = arr[0];
320 for (i=1; i<n; i++)
321 arr[i-1]->next = arr[i];
322 arr[n-1]->next = NULL;
323 free( arr );
324 return 0;
325}
326
327
331int ss_check (void)
332{
333 for (ShipStatsType i=0; i<=SS_TYPE_SENTINEL; i++) {
334 if (ss_lookup[i].type != i) {
335 WARN(_("ss_lookup: %s should have id %d but has %d"),
336 ss_lookup[i].name, i, ss_lookup[i].type );
337 return -1;
338 }
339 }
340
341 return 0;
342}
343
348{
349 char *ptr;
350
351 /* Clear the memory. */
352 memset( stats, 0, sizeof(ShipStats) );
353
354 ptr = (char*) stats;
355 for (int i=0; i<SS_TYPE_SENTINEL; i++) {
356 const ShipStatsLookup *sl = &ss_lookup[ i ];
357
358 /* Only want valid names. */
359 if (sl->name == NULL)
360 continue;
361
362 /* Handle doubles. */
363 switch (sl->data) {
365 {
366 double *dbl;
367 char *fieldptr = &ptr[ sl->offset ];
368 memcpy(&dbl, &fieldptr, sizeof(double*));
369 *dbl = 1.0;
370 break;
371 }
372
373 /* No need to set, memset does the work. */
378 break;
379 }
380 }
381
382 return 0;
383}
384
391int ss_statsMerge( ShipStats *dest, const ShipStats *src )
392{
393 int *destint;
394 const int *srcint;
395 double *destdbl;
396 const double *srcdbl;
397 char *destptr;
398 const char *srcptr;
399
400 destptr = (char*) dest;
401 srcptr = (const char*) src;
402 for (int i=0; i<SS_TYPE_SENTINEL; i++) {
403 const ShipStatsLookup *sl = &ss_lookup[ i ];
404
405 /* Only want valid names. */
406 if (sl->name == NULL)
407 continue;
408
409 switch (sl->data) {
411 destdbl = (double*) &destptr[ sl->offset ];
412 srcdbl = (const double*) &srcptr[ sl->offset ];
413 *destdbl = (*destdbl) * (*srcdbl);
414 break;
415
418 destdbl = (double*) &destptr[ sl->offset ];
419 srcdbl = (const double*) &srcptr[ sl->offset ];
420 *destdbl = (*destdbl) + (*srcdbl);
421 break;
422
424 destint = (int*) &destptr[ sl->offset ];
425 srcint = (const int*) &srcptr[ sl->offset ];
426 *destint = (*destint) + (*srcint);
427 break;
428
430 destint = (int*) &destptr[ sl->offset ];
431 srcint = (const int*) &srcptr[ sl->offset ];
432 *destint = !!((*destint) + (*srcint));
433 break;
434 }
435 }
436
437 return 0;
438}
439
447int ss_statsModSingle( ShipStats *stats, const ShipStatList *list )
448{
449 char *ptr;
450 char *fieldptr;
451 double *dbl;
452 int *i;
453 const ShipStatsLookup *sl = &ss_lookup[ list->type ];
454
455 ptr = (char*) stats;
456 switch (sl->data) {
458 fieldptr = &ptr[ sl->offset ];
459 memcpy(&dbl, &fieldptr, sizeof(double*));
460 *dbl *= 1.0+list->d.d;
461 if (*dbl < 0.) /* Don't let the values go negative. */
462 *dbl = 0.;
463 break;
464
467 fieldptr = &ptr[ sl->offset ];
468 memcpy(&dbl, &fieldptr, sizeof(double*));
469 *dbl += list->d.d;
470 break;
471
473 fieldptr = &ptr[ sl->offset ];
474 memcpy(&i, &fieldptr, sizeof(int*));
475 *i += list->d.i;
476 break;
477
479 fieldptr = &ptr[ sl->offset ];
480 memcpy(&i, &fieldptr, sizeof(int*));
481 *i = 1; /* Can only set to true. */
482 break;
483 }
484
485 return 0;
486}
487
496int ss_statsModSingleScale( ShipStats *stats, const ShipStatList *list, double scale )
497{
498 char *ptr;
499 char *fieldptr;
500 double *dbl;
501 int *i;
502 const ShipStatsLookup *sl = &ss_lookup[ list->type ];
503
504 ptr = (char*) stats;
505 switch (sl->data) {
507 fieldptr = &ptr[ sl->offset ];
508 memcpy(&dbl, &fieldptr, sizeof(double*));
509 *dbl *= 1.0+list->d.d * scale;
510 if (*dbl < 0.) /* Don't let the values go negative. */
511 *dbl = 0.;
512 break;
513
516 fieldptr = &ptr[ sl->offset ];
517 memcpy(&dbl, &fieldptr, sizeof(double*));
518 *dbl += list->d.d * scale;
519 break;
520
522 fieldptr = &ptr[ sl->offset ];
523 memcpy(&i, &fieldptr, sizeof(int*));
524 *i += list->d.i * scale;
525 break;
526
528 fieldptr = &ptr[ sl->offset ];
529 memcpy(&i, &fieldptr, sizeof(int*));
530 *i = 1; /* Can only set to true. */
531 break;
532 }
533
534 return 0;
535}
536
544{
545 int ret = 0;
546 for (const ShipStatList *ll = list; ll != NULL; ll = ll->next)
547 ret |= ss_statsModSingle( stats, ll );
548 return ret;
549}
550
558int ss_statsModFromListScale( ShipStats *stats, const ShipStatList* list, double scale )
559{
560 int ret = 0;
561 for (const ShipStatList *ll = list; ll != NULL; ll = ll->next)
562 ret |= ss_statsModSingleScale( stats, ll, scale );
563 return ret;
564}
565
574const char* ss_nameFromType( ShipStatsType type )
575{
576 return ss_lookup[ type ].name;
577}
578
585size_t ss_offsetFromType( ShipStatsType type )
586{
587 return ss_lookup[ type ].offset;
588}
589
596ShipStatsType ss_typeFromName( const char *name )
597{
598 for (int i=0; i<SS_TYPE_SENTINEL; i++)
599 if ((ss_lookup[i].name != NULL) && (strcmp(name,ss_lookup[i].name)==0))
600 return ss_lookup[i].type;
601
602 WARN(_("ss_typeFromName: No ship stat matching '%s'"), name);
603 return SS_TYPE_NIL;
604}
605
609static const char* ss_printD_colour( double d, const ShipStatsLookup *sl )
610{
611 if (sl->inverted) {
612 if (d < 0.)
613 return "g";
614 return "r";
615 }
616
617 if (d > 0.)
618 return "g";
619 return "r";
620}
621
625static const char* ss_printI_colour( int i, const ShipStatsLookup *sl )
626{
627 if (sl->inverted) {
628 if (i < 0)
629 return "g";
630 return "r";
631 }
632
633 if (i > 0)
634 return "g";
635 return "r";
636}
637
641static int ss_printD( char *buf, int len, int newline, double d, const ShipStatsLookup *sl )
642{
643 if (FABS(d) < 1e-10)
644 return 0;
645 return scnprintf( buf, len, "%s#%s%+g%% %s#0",
646 (newline) ? "\n" : "",
647 ss_printD_colour( d, sl ),
648 d*100., _(sl->display) );
649}
650
654static int ss_printA( char *buf, int len, int newline, double d, const ShipStatsLookup *sl )
655{
656 if (FABS(d) < 1e-10)
657 return 0;
658 return scnprintf( buf, len, "%s#%s%+g %s#0",
659 (newline) ? "\n" : "",
660 ss_printD_colour( d, sl ),
661 d, _(sl->display) );
662}
663
667static int ss_printI( char *buf, int len, int newline, int i, const ShipStatsLookup *sl )
668{
669 if (i == 0)
670 return 0;
671 return scnprintf( buf, len, "%s#%s%+d %s#0",
672 (newline) ? "\n" : "",
673 ss_printI_colour( i, sl ),
674 i, _(sl->display) );
675}
676
680static int ss_printB( char *buf, int len, int newline, int b, const ShipStatsLookup *sl )
681{
682 if (!b)
683 return 0;
684 return scnprintf( buf, len, "%s#%s%s#0",
685 (newline) ? "\n" : "",
686 ss_printI_colour( b, sl ),
687 _(sl->display) );
688}
689
699int ss_statsListDesc( const ShipStatList *ll, char *buf, int len, int newline )
700{
701 int i, left, newl;
702 const ShipStatsLookup *sl;
703 i = 0;
704 newl = newline;
705 for ( ; ll != NULL; ll=ll->next) {
706 left = len-i;
707 if (left < 0)
708 break;
709 sl = &ss_lookup[ ll->type ];
710
711 switch (sl->data) {
714 i += ss_printD( &buf[i], left, newl, ll->d.d, sl );
715 break;
716
718 i += ss_printA( &buf[i], left, newl, ll->d.d, sl );
719 break;
720
722 i += ss_printI( &buf[i], left, newl, ll->d.i, sl );
723 break;
724
726 i += ss_printB( &buf[i], left, newl, ll->d.i, sl );
727 break;
728 }
729
730 newl = 1;
731 }
732 return i;
733}
734
744int ss_statsDesc( const ShipStats *s, char *buf, int len, int newline )
745{
746 int l, left;
747 char *ptr;
748 char *fieldptr;
749 double *dbl;
750 int *num;
751
752 l = 0;
753 ptr = (char*) s;
754 for (int i=0; i<SS_TYPE_SENTINEL; i++) {
755 const ShipStatsLookup *sl = &ss_lookup[ i ];
756
757 /* Only want valid names. */
758 if (sl->name == NULL)
759 continue;
760
761 /* Calculate offset left. */
762 left = len-l;
763 if (left < 0)
764 break;
765
766 switch (sl->data) {
768 fieldptr = &ptr[ sl->offset ];
769 memcpy(&dbl, &fieldptr, sizeof(double*));
770 l += ss_printD( &buf[l], left, (newline||(l!=0)), ((*dbl)-1.), sl );
771 break;
772
774 fieldptr = &ptr[ sl->offset ];
775 memcpy(&dbl, &fieldptr, sizeof(double*));
776 l += ss_printD( &buf[l], left, (newline||(l!=0)), (*dbl), sl );
777 break;
778
780 fieldptr = &ptr[ sl->offset ];
781 memcpy(&dbl, &fieldptr, sizeof(double*));
782 l += ss_printA( &buf[l], left, (newline||(l!=0)), (*dbl), sl );
783 break;
784
786 fieldptr = &ptr[ sl->offset ];
787 memcpy(&num, &fieldptr, sizeof(int*));
788 l += ss_printI( &buf[l], left, (newline||(l!=0)), (*num), sl );
789 break;
790
792 fieldptr = &ptr[ sl->offset ];
793 memcpy(&num, &fieldptr, sizeof(int*));
794 l += ss_printB( &buf[l], left, (newline||(l!=0)), (*num), sl );
795 break;
796 }
797 }
798
799 return l;
800}
801
808{
809 while (ll != NULL) {
810 ShipStatList *tmp = ll;
811 ll = ll->next;
812 free(tmp);
813 }
814}
815
819int ss_statsSet( ShipStats *s, const char *name, double value, int overwrite )
820{
821 const ShipStatsLookup *sl;
822 ShipStatsType type;
823 char *ptr;
824 double *destdbl;
825 int *destint;
826 double v;
827
828 type = ss_typeFromName( name );
829 if (type == SS_TYPE_NIL) {
830 WARN(_("Unknown ship stat type '%s'!"), name );
831 return -1;
832 }
833
834 sl = &ss_lookup[ type ];
835 ptr = (char*) s;
836 switch (sl->data) {
838 destdbl = (double*) &ptr[ sl->offset ];
839 v = 1.0 + value / 100.;
840 if (overwrite)
841 *destdbl = v;
842 else
843 *destdbl *= v;
844 break;
845
848 destdbl = (double*) &ptr[ sl->offset ];
849 if (overwrite)
850 *destdbl = value;
851 else
852 *destdbl += value;
853 break;
854
856 destint = (int*) &ptr[ sl->offset ];
857 if (overwrite)
858 *destint = (fabs(value) > 1e-5);
859 else
860 *destint |= (fabs(value) > 1e-5);
861 break;
862
864 destint = (int*) &ptr[ sl->offset ];
865 if (overwrite)
866 *destint = round(value);
867 else
868 *destint += round(value);
869 break;
870 }
871
872 return 0;
873}
874
875static double ss_statsGetInternal( const ShipStats *s, ShipStatsType type )
876{
877 const ShipStatsLookup *sl;
878 const char *ptr;
879 const double *destdbl;
880 const int *destint;
881
882 sl = &ss_lookup[ type ];
883 ptr = (const char*) s;
884 switch (sl->data) {
886 destdbl = (const double*) &ptr[ sl->offset ];
887 return 100.*((*destdbl) - 1.0);
888
890 destdbl = (const double*) &ptr[ sl->offset ];
891 return 100.*(*destdbl);
892
894 destdbl = (const double*) &ptr[ sl->offset ];
895 return *destdbl;
896
899 destint = (const int*) &ptr[ sl->offset ];
900 return *destint;
901 }
902 return 0.;
903}
904
905static int ss_statsGetLuaInternal( lua_State *L, const ShipStats *s, ShipStatsType type, int internal )
906{
907 const ShipStatsLookup *sl;
908 const char *ptr;
909 const double *destdbl;
910 const int *destint;
911
912 sl = &ss_lookup[ type ];
913 ptr = (const char*) s;
914 switch (sl->data) {
916 destdbl = (const double*) &ptr[ sl->offset ];
917 if (internal)
918 lua_pushnumber(L, *destdbl );
919 else
920 lua_pushnumber(L, 100.*((*destdbl) - 1.0) );
921 return 0;
922
924 destdbl = (const double*) &ptr[ sl->offset ];
925 if (internal)
926 lua_pushnumber(L, *destdbl );
927 else
928 lua_pushnumber(L, 100.*(*destdbl));
929 return 0;
930
932 destdbl = (const double*) &ptr[ sl->offset ];
933 lua_pushnumber(L, *destdbl);
934 return 0;
935
937 destint = (const int*) &ptr[ sl->offset ];
938 lua_pushboolean(L, *destint);
939 return 0;
940
942 destint = (const int*) &ptr[ sl->offset ];
943 lua_pushinteger(L, *destint);
944 return 0;
945 }
946 lua_pushnil(L);
947 return -1;
948}
949
953double ss_statsGet( const ShipStats *s, const char *name )
954{
955 ShipStatsType type = ss_typeFromName( name );
956 if (type == SS_TYPE_NIL) {
957 WARN(_("Unknown ship stat type '%s'!"), name );
958 return 0;
959 }
960
961 return ss_statsGetInternal( s, type );
962}
963
967int ss_statsGetLua( lua_State *L, const ShipStats *s, const char *name, int internal )
968{
969 ShipStatsType type;
970
971 if (name==NULL)
972 return ss_statsGetLuaTable( L, s, internal );
973
974 type = ss_typeFromName( name );
975 if (type == SS_TYPE_NIL) {
976 WARN(_("Unknown ship stat type '%s'!"), name );
977 return -1;
978 }
979
980 return ss_statsGetLuaInternal( L, s, type, internal );
981}
982
986int ss_statsGetLuaTable( lua_State *L, const ShipStats *s, int internal )
987{
988 lua_newtable(L);
989 for (int i=0; i<SS_TYPE_SENTINEL; i++) {
990 const ShipStatsLookup *sl = &ss_lookup[ i ];
991
992 /* Only want valid names. */
993 if (sl->name == NULL)
994 continue;
995
996 /* Push name and get value. */
997 lua_pushstring(L, sl->name);
998 ss_statsGetLuaInternal( L, s, i, internal );
999 lua_rawset( L, -3 );
1000 }
1001 return 0;
1002}
Header file with generic functions and naev-specifics.
#define FABS(x)
Definition: naev.h:37
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
Definition: nstring.c:178
static const double d[]
Definition: rng.c:273
int ss_statsListDesc(const ShipStatList *ll, char *buf, int len, int newline)
Writes the ship statistics description.
Definition: shipstats.c:699
void ss_free(ShipStatList *ll)
Frees a list of ship stats.
Definition: shipstats.c:807
static int ss_printD(char *buf, int len, int newline, double d, const ShipStatsLookup *sl)
Helper to print doubles.
Definition: shipstats.c:641
int ss_statsMerge(ShipStats *dest, const ShipStats *src)
Merges two different ship stats.
Definition: shipstats.c:391
int ss_statsModFromList(ShipStats *stats, const ShipStatList *list)
Updates a stat structure from a stat list.
Definition: shipstats.c:543
StatDataType
The data type.
Definition: shipstats.c:21
@ SS_DATA_TYPE_DOUBLE_ABSOLUTE_PERCENT
Definition: shipstats.c:24
@ SS_DATA_TYPE_DOUBLE_ABSOLUTE
Definition: shipstats.c:23
@ SS_DATA_TYPE_BOOLEAN
Definition: shipstats.c:26
@ SS_DATA_TYPE_INTEGER
Definition: shipstats.c:25
@ SS_DATA_TYPE_DOUBLE
Definition: shipstats.c:22
static int ss_printA(char *buf, int len, int newline, double d, const ShipStatsLookup *sl)
Helper to print absolute doubles.
Definition: shipstats.c:654
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:967
static const char * ss_printD_colour(double d, const ShipStatsLookup *sl)
Some colour coding for ship stats doubles.
Definition: shipstats.c:609
const char * ss_nameFromType(ShipStatsType type)
Gets the name from type.
Definition: shipstats.c:574
static int ss_printI(char *buf, int len, int newline, int i, const ShipStatsLookup *sl)
Helper to print integers.
Definition: shipstats.c:667
int ss_statsModSingle(ShipStats *stats, const ShipStatList *list)
Modifies a stat structure using a single element.
Definition: shipstats.c:447
#define N__ELEM(t)
Definition: shipstats.c:74
int ss_statsModSingleScale(ShipStats *stats, const ShipStatList *list, double scale)
Modifies a stat structure using a single element.
Definition: shipstats.c:496
int ss_statsDesc(const ShipStats *s, char *buf, int len, int newline)
Writes the ship statistics description.
Definition: shipstats.c:744
size_t ss_offsetFromType(ShipStatsType type)
Gets the offset from type.
Definition: shipstats.c:585
static const ShipStatsLookup ss_lookup[]
Definition: shipstats.c:80
ShipStatsType ss_typeFromName(const char *name)
Gets the type from the name.
Definition: shipstats.c:596
static int ss_printB(char *buf, int len, int newline, int b, const ShipStatsLookup *sl)
Helper to print booleans.
Definition: shipstats.c:680
static const char * ss_printI_colour(int i, const ShipStatsLookup *sl)
Some colour coding for ship stats integers.
Definition: shipstats.c:625
int ss_listToXML(xmlTextWriterPtr writer, const ShipStatList *ll)
Creatse a shipstat list element from an xml node.
Definition: shipstats.c:260
double ss_statsGet(const ShipStats *s, const char *name)
Gets a ship stat value by name.
Definition: shipstats.c:953
int ss_statsInit(ShipStats *stats)
Initializes a stat structure.
Definition: shipstats.c:347
int ss_statsSet(ShipStats *s, const char *name, double value, int overwrite)
Sets a ship stat by name.
Definition: shipstats.c:819
int ss_statsGetLuaTable(lua_State *L, const ShipStats *s, int internal)
Converts ship stats to a Lua table, which is pushed on the Lua stack.
Definition: shipstats.c:986
int ss_statsModFromListScale(ShipStats *stats, const ShipStatList *list, double scale)
Updates a stat structure from a stat list.
Definition: shipstats.c:558
int ss_check(void)
Checks for validity.
Definition: shipstats.c:331
ShipStatList * ss_listFromXML(xmlNodePtr node)
Creates a shipstat list element from an xml node.
Definition: shipstats.c:209
int ss_sort(ShipStatList **ll)
Sorts the ship stats, useful if doing saving stuff.
Definition: shipstats.c:298
Represents relative ship statistics as a linked list.
Definition: shipstats.h:167
double d
Definition: shipstats.h:173
ShipStatsType type
Definition: shipstats.h:171
struct ShipStatList_ * next
Definition: shipstats.h:168
Internal look up table for ship stats.
Definition: shipstats.c:34
const char * name
Definition: shipstats.c:37
const char * display
Definition: shipstats.c:38
ShipStatsType type
Definition: shipstats.c:36
StatDataType data
Definition: shipstats.c:39
size_t offset
Definition: shipstats.c:45
Represents ship statistics, properties ship can use.
Definition: shipstats.h:198