naev 0.11.5
ship.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <limits.h>
11#include "physfsrwops.h"
12#include "SDL_image.h"
13
14#include "naev.h"
17#include "ship.h"
18
19#include "array.h"
20#include "colour.h"
21#include "conf.h"
22#include "log.h"
23#include "ndata.h"
24#include "nfile.h"
25#include "nlua.h"
26#include "nlua_gfx.h"
27#include "nlua_camera.h"
28#include "nstring.h"
29#include "nxml.h"
30#include "shipstats.h"
31#include "slots.h"
32#include "toolkit.h"
33#include "threadpool.h"
34#include "unistd.h"
35
36#define XML_SHIP "ship"
38#define SHIP_ENGINE "_engine"
39#define SHIP_TARGET "_target"
40#define SHIP_COMM "_comm"
42#define VIEW_WIDTH 300
43#define VIEW_HEIGHT 300
45#define BUTTON_WIDTH 80
46#define BUTTON_HEIGHT 30
48#define STATS_DESC_MAX 512
53typedef struct ShipThreadData_ {
54 char *filename;
56 int ret;
58
59static Ship* ship_stack = NULL;
61/*
62 * Prototypes
63 */
64static int ship_loadGFX( Ship *temp, const char *buf, int sx, int sy, int engine );
65static int ship_loadPLG( Ship *temp, const char *buf, int size_hint );
66static int ship_parse( Ship *temp, const char *filename );
67static int ship_parseThread( void *ptr );
68static void ship_freeSlot( ShipOutfitSlot* s );
69
73static int ship_cmp( const void *p1, const void *p2 )
74{
75 const Ship *s1, *s2;
76 s1 = (const Ship*) p1;
77 s2 = (const Ship*) p2;
78 return strcmp( s1->name, s2->name );
79}
80
87const Ship* ship_get( const char* name )
88{
89 const Ship *s = ship_getW( name );
90 if (s==NULL)
91 WARN(_("Ship %s does not exist"), name);
92 return s;
93}
94
101const Ship* ship_getW( const char* name )
102{
103 const Ship s = {.name = (char*)name };
104 return bsearch( &s, ship_stack, array_size(ship_stack), sizeof(Ship), ship_cmp );
105}
106
110const char *ship_existsCase( const char* name )
111{
112 for (int i=0; i<array_size(ship_stack); i++)
113 if (strcasecmp(name,ship_stack[i].name)==0)
114 return ship_stack[i].name;
115 return NULL;
116}
117
121const Ship* ship_getAll (void)
122{
123 return ship_stack;
124}
125
129int ship_compareTech( const void *arg1, const void *arg2 )
130{
131 const Ship *s1, *s2;
132
133 /* Get ships. */
134 s1 = * (const Ship**) arg1;
135 s2 = * (const Ship**) arg2;
136
137 /* Compare requirements. */
138 if ((s1->condstr!=NULL) && (s2->condstr==NULL))
139 return -1;
140 else if ((s2->condstr!=NULL) && (s1->condstr==NULL))
141 return +1;
142
143 /* Compare class. */
144 if (s1->class < s2->class)
145 return +1;
146 else if (s1->class > s2->class)
147 return -1;
148
149 /* Compare price. */
150 if (s1->price < s2->price)
151 return +1;
152 else if (s1->price > s2->price)
153 return -1;
154
155 /* Same. */
156 return strcmp( s1->name, s2->name );
157}
158
165const char* ship_class( const Ship* s )
166{
167 return ship_classToString( s->class );
168}
169
176const char* ship_classDisplay( const Ship* s )
177{
178 if (s->class_display)
179 return s->class_display;
180 return ship_class( s );
181}
182
189const char *ship_classToString( ShipClass class )
190{
191 switch (class) {
192 case SHIP_CLASS_NULL:
193 return "NULL";
194 /* Civilian. */
195 case SHIP_CLASS_YACHT:
196 return N_("Yacht");
197 case SHIP_CLASS_COURIER:
198 return N_("Courier");
199 case SHIP_CLASS_FREIGHTER:
200 return N_("Freighter");
201 case SHIP_CLASS_ARMOURED_TRANSPORT:
202 return N_("Armoured Transport");
203 case SHIP_CLASS_BULK_FREIGHTER:
204 return N_("Bulk Freighter");
205 /* Military. */
206 case SHIP_CLASS_SCOUT:
207 return N_("Scout");
208 case SHIP_CLASS_INTERCEPTOR:
209 return N_("Interceptor");
210 case SHIP_CLASS_FIGHTER:
211 return N_("Fighter");
212 case SHIP_CLASS_BOMBER:
213 return N_("Bomber");
214 case SHIP_CLASS_CORVETTE:
215 return N_("Corvette");
216 case SHIP_CLASS_DESTROYER:
217 return N_("Destroyer");
218 case SHIP_CLASS_CRUISER:
219 return N_("Cruiser");
220 case SHIP_CLASS_BATTLESHIP:
221 return N_("Battleship");
222 case SHIP_CLASS_CARRIER:
223 return N_("Carrier");
224 /* Unknown. */
225 default:
226 return N_("Unknown");
227 }
228}
229
230#define STRTOSHIP( x, y ) if (strcmp(str,x)==0) return y
236ShipClass ship_classFromString( const char* str )
237{
238 if (str==NULL)
239 return SHIP_CLASS_NULL;
240 /* Civilian */
241 STRTOSHIP( "Yacht", SHIP_CLASS_YACHT );
242 STRTOSHIP( "Courier", SHIP_CLASS_COURIER );
243 STRTOSHIP( "Freighter", SHIP_CLASS_FREIGHTER );
244 STRTOSHIP( "Armoured Transport", SHIP_CLASS_ARMOURED_TRANSPORT );
245 STRTOSHIP( "Bulk Freighter", SHIP_CLASS_BULK_FREIGHTER );
246
247 /* Military */
248 STRTOSHIP( "Scout", SHIP_CLASS_SCOUT );
249 STRTOSHIP( "Interceptor", SHIP_CLASS_INTERCEPTOR );
250 STRTOSHIP( "Fighter", SHIP_CLASS_FIGHTER );
251 STRTOSHIP( "Bomber", SHIP_CLASS_BOMBER );
252 STRTOSHIP( "Corvette", SHIP_CLASS_CORVETTE );
253 STRTOSHIP( "Destroyer", SHIP_CLASS_DESTROYER );
254 STRTOSHIP( "Cruiser", SHIP_CLASS_CRUISER );
255 STRTOSHIP( "Battleship", SHIP_CLASS_BATTLESHIP);
256 STRTOSHIP( "Carrier", SHIP_CLASS_CARRIER );
257
258 /* Unknown */
259 return SHIP_CLASS_NULL;
260}
261#undef STRTOSHIP
262
266credits_t ship_basePrice( const Ship* s )
267{
268 return s->price;
269}
270
274credits_t ship_buyPrice( const Ship* s )
275{
276 /* Get base price. */
277 credits_t price = ship_basePrice(s);
278
279 for (int i=0; i<array_size(s->outfit_structure); i++) {
280 const Outfit *o = s->outfit_structure[i].data;
281 if (o != NULL)
282 price += o->price;
283 }
284 for (int i=0; i<array_size(s->outfit_utility); i++) {
285 const Outfit *o = s->outfit_utility[i].data;
286 if (o != NULL)
287 price += o->price;
288 }
289 for (int i=0; i<array_size(s->outfit_weapon); i++) {
290 const Outfit *o = s->outfit_weapon[i].data;
291 if (o != NULL)
292 price += o->price;
293 }
294
295 return price;
296}
297
304{
305 if (s->gfx_comm != NULL)
306 return gl_newImage( s->gfx_comm, 0 );
307 return NULL;
308}
309
316int ship_size( const Ship *s )
317{
318 switch (s->class) {
319 case SHIP_CLASS_YACHT:
320 case SHIP_CLASS_SCOUT:
321 case SHIP_CLASS_INTERCEPTOR:
322 return 1;
323
324 case SHIP_CLASS_COURIER:
325 case SHIP_CLASS_FIGHTER:
326 case SHIP_CLASS_BOMBER:
327 return 2;
328
329 case SHIP_CLASS_FREIGHTER:
330 case SHIP_CLASS_CORVETTE:
331 return 3;
332
333 case SHIP_CLASS_DESTROYER:
334 case SHIP_CLASS_ARMOURED_TRANSPORT:
335 return 4;
336
337 case SHIP_CLASS_BULK_FREIGHTER:
338 case SHIP_CLASS_CRUISER:
339 return 5;
340
341 case SHIP_CLASS_BATTLESHIP:
342 case SHIP_CLASS_CARRIER:
343 return 6;
344
345 default:
346 return -1;
347 }
348}
349
353static int ship_genTargetGFX( Ship *temp, SDL_Surface *surface, int sx, int sy )
354{
355 SDL_Surface *gfx, *gfx_store;
356 int x, y, sw, sh;
357 SDL_Rect rtemp, dstrect;
358 char buf[PATH_MAX];
359
360 /* Get sprite size. */
361 sw = temp->gfx_space->w / sx;
362 sh = temp->gfx_space->h / sy;
363
364 /* Create the surface. */
365 SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
366
367 /* create the temp POT surface */
368 gfx = SDL_CreateRGBSurface( 0, sw, sh,
369 surface->format->BytesPerPixel*8, RGBAMASK );
370 gfx_store = SDL_CreateRGBSurface( 0, SHIP_TARGET_W, SHIP_TARGET_H,
371 surface->format->BytesPerPixel*8, RGBAMASK );
372
373 if (gfx == NULL) {
374 WARN( _("Unable to create ship '%s' targeting surface."), temp->name );
375 return -1;
376 }
377
378 /* Copy over for target. */
379 gl_getSpriteFromDir( &x, &y, temp->gfx_space, M_PI* 5./4. );
380 rtemp.x = sw * x;
381 rtemp.y = sh * y;
382 rtemp.w = sw;
383 rtemp.h = sh;
384 dstrect.x = 0;
385 dstrect.y = 0;
386 dstrect.w = rtemp.w;
387 dstrect.h = rtemp.h;
388 SDL_BlitSurface( surface, &rtemp, gfx, &dstrect );
389
390 /* Copy over for store. */
391 dstrect.x = (SHIP_TARGET_W - sw) / 2;
392 dstrect.y = (SHIP_TARGET_H - sh) / 2;
393 dstrect.w = rtemp.w;
394 dstrect.h = rtemp.h;
395 SDL_BlitSurface( surface, &rtemp, gfx_store, &dstrect );
396
397 /* Load the store surface. */
398 snprintf( buf, sizeof(buf), "%s_gfx_store", temp->name );
399 temp->gfx_store = gl_loadImagePad( buf, gfx_store, OPENGL_TEX_VFLIP, SHIP_TARGET_W, SHIP_TARGET_H, 1, 1, 1 );
400
401 /* Load the surface. */
402 snprintf( buf, sizeof(buf), "%s_gfx_target", temp->name );
403 temp->gfx_target = gl_loadImagePad( buf, gfx, OPENGL_TEX_VFLIP, sw, sh, 1, 1, 1 );
404
405 return 0;
406}
407
416static int ship_loadSpaceImage( Ship *temp, char *str, int sx, int sy )
417{
418 SDL_RWops *rw;
419 SDL_Surface *surface;
420 int ret;
421
422 /* Load the space sprite. */
423 rw = PHYSFSRWOPS_openRead( str );
424 if (rw==NULL) {
425 WARN(_("Unable to open '%s' for reading!"), str);
426 return -1;
427 }
428 surface = IMG_Load_RW( rw, 0 );
429
430 /* Load the texture. */
431 if (temp->polygon != NULL)
432 temp->gfx_space = gl_loadImagePad( str, surface,
433 OPENGL_TEX_MIPMAPS | OPENGL_TEX_VFLIP,
434 surface->w, surface->h, sx, sy, 0 );
435 else
436 temp->gfx_space = gl_loadImagePadTrans( str, surface, rw,
437 OPENGL_TEX_MAPTRANS | OPENGL_TEX_MIPMAPS | OPENGL_TEX_VFLIP,
438 surface->w, surface->h, sx, sy, 0 );
439
440 /* Create the target graphic. */
441 ret = ship_genTargetGFX( temp, surface, sx, sy );
442 if (ret != 0)
443 return ret;
444
445 /* Free stuff. */
446 SDL_RWclose( rw );
447 SDL_FreeSurface( surface );
448
449 /* Calculate mount angle. */
450 temp->mangle = 2.*M_PI;
451 temp->mangle /= temp->gfx_space->sx * temp->gfx_space->sy;
452 return 0;
453}
454
463static int ship_loadEngineImage( Ship *temp, char *str, int sx, int sy )
464{
465 temp->gfx_engine = gl_newSprite( str, sx, sy, OPENGL_TEX_MIPMAPS );
466 return (temp->gfx_engine != NULL);
467}
468
478static int ship_loadGFX( Ship *temp, const char *buf, int sx, int sy, int engine )
479{
480 char str[PATH_MAX], *ext, *base, *delim;
481
482 /* Get base path. */
483 delim = strchr( buf, '_' );
484 base = delim==NULL ? strdup( buf ) : strndup( buf, delim-buf );
485
486 /* Load the 3d model */
487 snprintf(str, sizeof(str), SHIP_3DGFX_PATH"%s/%s/%s.obj", base, buf, buf);
488 if (PHYSFS_exists(str))
489 temp->gfx_3d = object_loadFromFile(str);
490
491 /* Load the space sprite. */
492 ext = ".webp";
493 snprintf( str, sizeof(str), SHIP_GFX_PATH"%s/%s%s", base, buf, ext );
494 if (!PHYSFS_exists(str)) {
495 ext = ".png";
496 snprintf( str, sizeof(str), SHIP_GFX_PATH"%s/%s%s", base, buf, ext );
497 }
498 ship_loadSpaceImage( temp, str, sx, sy );
499
500 /* Load the engine sprite .*/
501 if (engine) {
502 snprintf( str, sizeof(str), SHIP_GFX_PATH"%s/%s"SHIP_ENGINE"%s", base, buf, ext );
503 ship_loadEngineImage( temp, str, sx, sy );
504 if (temp->gfx_engine == NULL)
505 WARN(_("Ship '%s' does not have an engine sprite (%s)."), temp->name, str );
506 }
507
508 /* Get the comm graphic for future loading. */
509 if (temp->gfx_comm != NULL) {
510 WARN(_("Ship '%s' has doubly defined 'gfx_comm'!"),temp->name);
511 free(temp->gfx_comm);
512 }
513 SDL_asprintf( &temp->gfx_comm, SHIP_GFX_PATH"%s/%s"SHIP_COMM"%s", base, buf, ext );
514 free( base );
515
516 return 0;
517}
518
526static int ship_loadPLG( Ship *temp, const char *buf, int size_hint )
527{
528 char file[PATH_MAX];
529 xmlDocPtr doc;
530 xmlNodePtr node;
531
532 snprintf( file, sizeof(file), "%s%s.xml", SHIP_POLYGON_PATH, buf );
533
534 /* See if the file does exist. */
535 if (!PHYSFS_exists(file)) {
536 WARN(_("%s xml collision polygon does not exist!\n \
537 Please use the script 'polygon_from_sprite.py' if sprites are used,\n \
538 And 'polygonSTL.py' if 3D model is used in game.\n \
539 These files can be found in Naev's artwork repo."), file);
540 return 0;
541 }
542
543 /* Load the XML. */
544 doc = xml_parsePhysFS( file );
545 if (doc == NULL)
546 return 0;
547
548 node = doc->xmlChildrenNode; /* First polygon node */
549 if (node == NULL) {
550 xmlFreeDoc(doc);
551 WARN(_("Malformed %s file: does not contain elements"), file);
552 return 0;
553 }
554
555 do { /* load the polygon data */
556 if (xml_isNode(node,"polygons")) {
557 xmlNodePtr cur = node->children;
558 temp->polygon = array_create_size( CollPoly, size_hint );
559 do {
560 if (xml_isNode(cur,"polygon")) {
561 CollPoly *polygon = &array_grow( &temp->polygon );
562 LoadPolygon( polygon, cur );
563 }
564 } while (xml_nextNode(cur));
565 }
566 } while (xml_nextNode(node));
567
568 xmlFreeDoc(doc);
569 return 0;
570}
571
581static int ship_parseSlot( Ship *temp, ShipOutfitSlot *slot, OutfitSlotType type, xmlNodePtr node )
582{
583 OutfitSlotSize base_size;
584 char *buf;
585
586 /* Initialize. */
587 memset( slot, 0, sizeof(ShipOutfitSlot) );
588 /* Parse size. */
589 xmlr_attr_strd( node, "size", buf );
590 if (buf != NULL)
591 base_size = outfit_toSlotSize( buf );
592 else {
593 WARN(_("Ship '%s' has undefined slot size, setting to '%s'"),temp->name, "Small");
594 base_size = OUTFIT_SLOT_SIZE_LIGHT;
595 }
596 free(buf);
597
598 /* Get mount point for weapons. */
599 if (type == OUTFIT_SLOT_WEAPON) {
600 xmlr_attr_float( node, "x", slot->mount.x );
601 xmlr_attr_float( node, "y", slot->mount.y );
602 /* Since we measure in pixels, we have to modify it so it
603 * doesn't get corrected by the ortho correction. */
604 slot->mount.y *= M_SQRT2;
605 xmlr_attr_float( node, "h", slot->mount.h );
606 }
607
608 /* Parse property. */
609 xmlr_attr_strd( node, "prop", buf );
610 if (buf != NULL) {
611 slot->slot.spid = sp_get( buf );
612 slot->exclusive = sp_exclusive( slot->slot.spid );
613 slot->required = sp_required( slot->slot.spid );
614 slot->locked = sp_locked( slot->slot.spid );
615 free( buf );
616 }
617 //TODO: consider inserting those two parse blocks below inside the parse block above
618
619 /* Parse exclusive flag, default false. */
620 xmlr_attr_int_def( node, "exclusive", slot->exclusive, slot->exclusive );
621 /* TODO: decide if exclusive should even belong in ShipOutfitSlot,
622 * remove this hack, and fix slot->exclusive to slot->slot.exclusive
623 * in it's two previous occurrences, meaning three lines above and 12
624 * lines above */
625 /* hack */
626 slot->slot.exclusive = slot->exclusive;
627
628 /* Parse required flag, default false. */
629 xmlr_attr_int_def( node, "required", slot->required, slot->required );
630
631 /* Parse locked flag, default false. */
632 xmlr_attr_int_def( node, "locked", slot->locked, slot->locked );
633
634 /* Name if applicable. */
635 xmlr_attr_strd( node, "name", slot->name );
636
637 /* Parse default outfit. */
638 buf = xml_get(node);
639 if (buf != NULL) {
640 const Outfit *o = outfit_get( buf );
641 if (o == NULL)
642 WARN( _("Ship '%s' has default outfit '%s' which does not exist."), temp->name, buf );
643 slot->data = o;
644 }
645
646 /* Set stuff. */
647 slot->slot.size = base_size;
648 slot->slot.type = type;
649
650 /* Required slots need a default outfit. */
651 if (slot->required && (slot->data == NULL))
652 WARN(_("Ship '%s' has required slot without a default outfit."), temp->name);
653
654 return 0;
655}
656
664static int ship_parse( Ship *temp, const char *filename )
665{
666 xmlNodePtr parent, node;
667 xmlDocPtr doc;
668 int sx = 8, sy = 8;
669 char str[PATH_MAX];
670 int noengine;
671 ShipStatList *ll;
672 ShipTrailEmitter trail;
673
674 /* Load the XML. */
675 doc = xml_parsePhysFS( filename );
676 if (doc == NULL)
677 return -1;
678
679 parent = doc->xmlChildrenNode; /* First ship node */
680 if (parent == NULL) {
681 xmlFreeDoc(doc);
682 WARN(_("Malformed %s file: does not contain elements"), filename);
683 return -1;
684 }
685
686 /* Clear memory. */
687 memset( temp, 0, sizeof(Ship) );
688
689 /* Defaults. */
690 ss_statsInit( &temp->stats_array );
691 temp->dt_default = 1.;
692
693 /* Lua defaults. */
694 temp->lua_env = LUA_NOREF;
695 temp->lua_init = LUA_NOREF;
696 temp->lua_cleanup = LUA_NOREF;
697 temp->lua_update = LUA_NOREF;
698 temp->lua_dt = 0.1;
699 temp->lua_explode_init = LUA_NOREF;
700 temp->lua_explode_update = LUA_NOREF;
701
702 /* Get name. */
703 xmlr_attr_strd( parent, "name", temp->name );
704 if (temp->name == NULL)
705 WARN( _("Ship in %s has invalid or no name"), SHIP_DATA_PATH );
706
707 /* Default offsets for the engine. */
708 temp->trail_emitters = NULL;
709
710 /* Load the rest of the data. */
711 node = parent->xmlChildrenNode;
712 do { /* load all the data */
713
714 /* Only handle nodes. */
715 xml_onlyNodes(node);
716
717 if (xml_isNode(node,"class")) {
718 xmlr_attr_strd( node, "display", temp->class_display );
719 temp->class = ship_classFromString( xml_get(node) );
720 continue;
721 }
722 if (xml_isNode(node,"GFX")) {
723 /* Get base graphic name. */
724 char *buf = xml_get(node);
725 if (buf==NULL) {
726 WARN(_("Ship '%s': GFX element is NULL"), temp->name);
727 continue;
728 }
729
730 /* Get size. */
731 xmlr_attr_float_def(node, "size", temp->gfx_3d_scale, 1);
732 xmlr_attr_int_def( node, "sx", sx, 8 );
733 xmlr_attr_int_def( node, "sy", sy, 8 );
734
735 xmlr_attr_int(node, "noengine", noengine );
736
737 /* Load the polygon, run before graphics!. */
738 ship_loadPLG( temp, buf, sx*sy );
739
740 /* Load the graphics. */
741 ship_loadGFX( temp, buf, sx, sy, !noengine );
742
743 continue;
744 }
745
746 if (xml_isNode(node,"gfx_space")) {
747 char *plg;
748
749 /* Get path */
750 char *buf = xml_get(node);
751 if (buf==NULL) {
752 WARN(_("Ship '%s': gfx_space element is NULL"), temp->name);
753 continue;
754 }
755 snprintf( str, sizeof(str), GFX_PATH"%s", buf );
756
757 /* Get sprite size. */
758 xmlr_attr_int_def( node, "sx", sx, 8 );
759 xmlr_attr_int_def( node, "sy", sy, 8 );
760
761 /* Get polygon. */
762 xmlr_attr_strd( node, "polygon", plg );
763 if (plg)
764 ship_loadPLG( temp, plg, sx*sy );
765 free( plg );
766
767 /* Load the graphics. */
768 ship_loadSpaceImage( temp, str, sx, sy );
769
770 continue;
771 }
772
773 if (xml_isNode(node,"gfx_engine")) {
774 /* Get path */
775 char *buf = xml_get(node);
776 if (buf==NULL) {
777 WARN(_("Ship '%s': gfx_engine element is NULL"), temp->name);
778 continue;
779 }
780 snprintf( str, sizeof(str), GFX_PATH"%s", buf );
781
782 /* Get sprite size. */
783 xmlr_attr_int_def( node, "sx", sx, 8 );
784 xmlr_attr_int_def( node, "sy", sy, 8 );
785
786 /* Load the graphics. */
787 ship_loadEngineImage( temp, str, sx, sy );
788
789 continue;
790 }
791
792 if (xml_isNode(node,"gfx_comm")) {
793 /* Get path */
794 char *buf = xml_get(node);
795 if (buf==NULL) {
796 WARN(_("Ship '%s': gfx_comm element is NULL"), temp->name);
797 continue;
798 }
799 snprintf( str, sizeof(str), GFX_PATH"%s", buf );
800 if (temp->gfx_comm != NULL) {
801 WARN(_("Ship '%s' has doubly defined 'gfx_comm'!"),temp->name);
802 free(temp->gfx_comm);
803 }
804 temp->gfx_comm = strdup(str);
805 continue;
806 }
807 if (xml_isNode(node,"gfx_overlays")) {
808 xmlNodePtr cur = node->children;
810 do {
811 xml_onlyNodes(cur);
812 if (xml_isNode(cur,"gfx_overlay"))
814 xml_parseTexture( cur, OVERLAY_GFX_PATH"%s", 1, 1, OPENGL_TEX_MIPMAPS ) );
815 } while (xml_nextNode(cur));
816 continue;
817 }
818
819 if (xml_isNode(node,"sound")) {
820 xmlr_attr_float_def( node, "pitch", temp->engine_pitch, 1. );
821 temp->sound = sound_get( xml_get(node) );
822 continue;
823 }
824 xmlr_strd(node,"base_type",temp->base_type);
825 xmlr_float(node,"time_mod",temp->dt_default);
826 xmlr_long(node,"price",temp->price);
827 xmlr_strd(node,"license",temp->license);
828 xmlr_strd(node,"cond",temp->cond);
829 xmlr_strd(node,"condstr",temp->condstr);
830 xmlr_strd(node,"fabricator",temp->fabricator);
831 xmlr_strd(node,"description",temp->description);
832 xmlr_strd(node,"desc_extra",temp->desc_extra);
833 xmlr_int(node,"points",temp->points);
834 xmlr_int(node,"rarity",temp->rarity);
835 xmlr_strd(node,"lua",temp->lua_file);
836
837 if (xml_isNode(node,"flags")) {
838 xmlNodePtr cur = node->children;
839 do {
840 xml_onlyNodes(cur);
841 if (xml_isNode(cur,"noplayer")) {
842 ship_setFlag( temp, SHIP_NOPLAYER );
843 continue;
844 }
845 if (xml_isNode(cur,"noescort")) {
846 ship_setFlag( temp, SHIP_NOESCORT );
847 continue;
848 }
849 if (xml_isNode(cur,"unique")) {
850 ship_setFlag( temp, SHIP_UNIQUE );
851 continue;
852 }
853 WARN(_("Ship '%s' has unknown flags node '%s'."), temp->name, cur->name);
854 } while (xml_nextNode(cur));
855 continue;
856 }
857
858 if (xml_isNode(node,"trail_generator")) {
859 char *buf;
860 xmlr_attr_float( node, "x", trail.x_engine );
861 xmlr_attr_float( node, "y", trail.y_engine );
862 xmlr_attr_float( node, "h", trail.h_engine );
863 xmlr_attr_int_def( node, "always_under", trail.always_under, 0 );
864 if (temp->trail_emitters == NULL) {
866 }
867 buf = xml_get(node);
868 if (buf == NULL)
869 buf = "default";
870 trail.trail_spec = trailSpec_get( buf );
871 if (trail.trail_spec != NULL)
872 array_push_back( &temp->trail_emitters, trail );
873 continue;
874 }
875
876 if (xml_isNode(node,"movement")) {
877 xmlNodePtr cur = node->children;
878 do {
879 xml_onlyNodes(cur);
880 xmlr_float(cur,"accel",temp->accel);
881 xmlr_float(cur,"turn",temp->turn);
882 xmlr_float(cur,"speed",temp->speed);
883 /* All the xmlr_ stuff have continue cases. */
884 WARN(_("Ship '%s' has unknown movement node '%s'."), temp->name, cur->name);
885 } while (xml_nextNode(cur));
886 continue;
887 }
888 if (xml_isNode(node,"health")) {
889 xmlNodePtr cur = node->children;
890 do {
891 xml_onlyNodes(cur);
892 xmlr_float(cur,"absorb",temp->dmg_absorb);
893 xmlr_float(cur,"armour",temp->armour);
894 xmlr_float(cur,"armour_regen",temp->armour_regen);
895 xmlr_float(cur,"shield",temp->shield);
896 xmlr_float(cur,"shield_regen",temp->shield_regen);
897 xmlr_float(cur,"energy",temp->energy);
898 xmlr_float(cur,"energy_regen",temp->energy_regen);
899 /* All the xmlr_ stuff have continue cases. */
900 WARN(_("Ship '%s' has unknown health node '%s'."), temp->name, cur->name);
901 } while (xml_nextNode(cur));
902 continue;
903 }
904 if (xml_isNode(node,"characteristics")) {
905 xmlNodePtr cur = node->children;
906 do {
907 xml_onlyNodes(cur);
908 xmlr_int(cur,"crew",temp->crew);
909 xmlr_float(cur,"mass",temp->mass);
910 xmlr_float(cur,"cpu",temp->cpu);
911 xmlr_int(cur,"fuel",temp->fuel);
912 xmlr_int(cur,"fuel_consumption",temp->fuel_consumption);
913 xmlr_float(cur,"cargo",temp->cap_cargo);
914 /* All the xmlr_ stuff have continue cases. */
915 WARN(_("Ship '%s' has unknown characteristic node '%s'."), temp->name, cur->name);
916 } while (xml_nextNode(cur));
917 continue;
918 }
919 if (xml_isNode(node,"slots")) {
920 /* Allocate the space. */
924
925 /* Initialize the mounts. */
926 xmlNodePtr cur = node->children;
927 do {
928 xml_onlyNodes(cur);
929 if (xml_isNode(cur,"structure"))
930 ship_parseSlot( temp, &array_grow(&temp->outfit_structure), OUTFIT_SLOT_STRUCTURE, cur );
931 else if (xml_isNode(cur,"utility"))
932 ship_parseSlot( temp, &array_grow(&temp->outfit_utility), OUTFIT_SLOT_UTILITY, cur );
933 else if (xml_isNode(cur,"weapon"))
934 ship_parseSlot( temp, &array_grow(&temp->outfit_weapon), OUTFIT_SLOT_WEAPON, cur );
935 else if (xml_isNode(cur,"intrinsic")) {
936 const Outfit *o = outfit_get(xml_get(cur));
937 if (o==NULL) {
938 WARN(_("Ship '%s' has unknown intrinsic outfit '%s'"), temp->name, xml_get(cur));
939 continue;
940 }
941 if (temp->outfit_intrinsic==NULL)
942 temp->outfit_intrinsic = (Outfit const**) array_create( Outfit* );
944 }
945 else
946 WARN(_("Ship '%s' has unknown slot node '%s'."), temp->name, cur->name);
947 } while (xml_nextNode(cur));
950 array_shrink( &temp->outfit_weapon );
951 continue;
952 }
953
954 /* Parse ship stats. */
955 if (xml_isNode(node,"stats")) {
956 xmlNodePtr cur = node->children;
957 do {
958 xml_onlyNodes(cur);
959 ll = ss_listFromXML( cur );
960 if (ll != NULL) {
961 ll->next = temp->stats;
962 temp->stats = ll;
963 continue;
964 }
965 WARN(_("Ship '%s' has unknown stat '%s'."), temp->name, cur->name);
966 } while (xml_nextNode(cur));
967
968 /* Load array. */
969 ss_sort( &temp->stats );
970 ss_statsInit( &temp->stats_array );
971 ss_statsMergeFromList( &temp->stats_array, temp->stats );
972
973 /* Create description. */
974 if (temp->stats != NULL) {
975 int i;
976 temp->desc_stats = malloc( STATS_DESC_MAX );
977 i = ss_statsListDesc( temp->stats, temp->desc_stats, STATS_DESC_MAX, 0 );
978 if (i <= 0) {
979 free( temp->desc_stats );
980 temp->desc_stats = NULL;
981 }
982 }
983
984 continue;
985 }
986
987 /* Parse tags. */
988 if (xml_isNode(node, "tags")) {
989 xmlNodePtr cur = node->children;
990 temp->tags = array_create( char* );
991 do {
992 xml_onlyNodes(cur);
993 if (xml_isNode(cur, "tag")) {
994 char *tmp = xml_get(cur);
995 if (tmp != NULL)
996 array_push_back( &temp->tags, strdup(tmp) );
997 continue;
998 }
999 WARN(_("Ship '%s' has unknown node in tags '%s'."), temp->name, cur->name );
1000 } while (xml_nextNode(cur));
1001 continue;
1002 }
1003
1004 /* Used by on-valid and NSH utils, no in-game meaning. */
1005 if (xml_isNode(node,"mission"))
1006 continue;
1007
1008 DEBUG(_("Ship '%s' has unknown node '%s'."), temp->name, node->name);
1009 } while (xml_nextNode(node));
1010
1011 /* Post processing. */
1012 temp->dmg_absorb /= 100.;
1013 temp->turn *= M_PI / 180.; /* Convert to rad. */
1014
1015 /* Check license. */
1016 if (temp->license && !outfit_licenseExists(temp->license))
1017 WARN(_("Ship '%s' has inexistent license requirement '%s'!"), temp->name, temp->license);
1018
1019 /* Check polygon. */
1020 if (temp->polygon == NULL)
1021 WARN(_("Ship '%s' has no collision polygon!"), temp->name );
1022 else {
1023 /* Validity check: there must be 1 polygon per sprite. */
1024 if (array_size(temp->polygon) != sx*sy) {
1025 WARN(_("Ship '%s': the number of collision polygons is wrong.\n \
1026 npolygon = %i and sx*sy = %i"),
1027 temp->name, array_size(temp->polygon), sx*sy);
1028 }
1029 }
1030
1031 /* Ship XML validator */
1032#define MELEMENT(o,s) if (o) WARN( _("Ship '%s' missing '%s' element"), temp->name, s)
1033 MELEMENT(temp->name==NULL,"name");
1034 MELEMENT(temp->base_type==NULL,"base_type");
1035 MELEMENT((temp->gfx_space==NULL) || (temp->gfx_comm==NULL),"GFX");
1036 MELEMENT(temp->class==SHIP_CLASS_NULL,"class");
1037 MELEMENT(temp->points==0,"points");
1038 MELEMENT(temp->price==0,"price");
1039 MELEMENT(temp->dt_default<=0.,"time_mod");
1040 MELEMENT(temp->fabricator==NULL,"fabricator");
1041 MELEMENT(temp->description==NULL,"description");
1042 MELEMENT(temp->armour==0.,"armour");
1043 MELEMENT((temp->cond!=NULL) && (temp->condstr==NULL), "condstr");
1044 MELEMENT((temp->cond==NULL) && (temp->condstr!=NULL), "cond");
1045 /*MELEMENT(temp->accel==0.,"accel");
1046 MELEMENT(temp->turn==0.,"turn");
1047 MELEMENT(temp->speed==0.,"speed");
1048 MELEMENT(temp->shield==0.,"shield");
1049 MELEMENT(temp->shield_regen==0.,"shield_regen");
1050 MELEMENT(temp->energy==0.,"energy");
1051 MELEMENT(temp->energy_regen==0.,"energy_regen");
1052 MELEMENT(temp->fuel==0.,"fuel");*/
1053 MELEMENT(temp->crew==0,"crew");
1054 MELEMENT(temp->mass==0.,"mass");
1055 MELEMENT(temp->fuel_consumption==0,"fuel_consumption");
1056 /*MELEMENT(temp->cap_cargo==0,"cargo");
1057 MELEMENT(temp->cpu==0.,"cpu");*/
1058#undef MELEMENT
1059
1060 xmlFreeDoc(doc);
1061
1062 return 0;
1063}
1064
1068static int ship_parseThread( void *ptr )
1069{
1070 ShipThreadData *data = ptr;
1071 /* Load the ship. */
1072 data->ret = ship_parse( &data->ship, data->filename );
1073 /* Render if necessary. */
1075 gl_contextSet();
1077 gl_contextUnset();
1078 }
1079 return data->ret;
1080}
1081
1087int ships_load (void)
1088{
1089 char **ship_files;
1090 int nfiles;
1091 Uint32 time = SDL_GetTicks();
1092 ThreadQueue *tq = vpool_create();
1094
1095 /* Validity. */
1096 ss_check();
1097
1098 ship_files = ndata_listRecursive( SHIP_DATA_PATH );
1099 nfiles = array_size( ship_files );
1100
1101 /* Initialize stack if needed. */
1102 if (ship_stack == NULL)
1104
1105 /* First pass to find what ships we have to load. */
1106 for (int i=0; i<nfiles; i++) {
1107 if (ndata_matchExt( ship_files[i], "xml" )) {
1108 ShipThreadData *td = &array_grow( &shipdata );
1109 td->filename = ship_files[i];
1110 }
1111 else
1112 free( ship_files[i] );
1113 }
1114 array_free( ship_files );
1115
1116 /* Enqueue the jobs after the data array is done. */
1117 for (int i=0; i<array_size(shipdata); i++)
1118 vpool_enqueue( tq, ship_parseThread, &shipdata[i] );
1119
1120 /* Wait until done processing. */
1121 SDL_GL_MakeCurrent( gl_screen.window, NULL );
1122 vpool_wait( tq );
1123 SDL_GL_MakeCurrent( gl_screen.window, gl_screen.context );
1124
1125 /* Properly load the data. */
1126 for (int i=0; i<array_size(shipdata); i++) {
1127 ShipThreadData *td = &shipdata[i];
1128 if (!td->ret)
1130 free( td->filename );
1131 }
1132 array_free(shipdata);
1133
1134 /* Sort and done! */
1135 qsort( ship_stack, array_size(ship_stack), sizeof(Ship), ship_cmp );
1136
1137#if DEBUGGING
1138 /* Check to see if there are name collisions. */
1139 for (int i=1; i<array_size(ship_stack); i++)
1140 if (strcmp( ship_stack[i-1].name, ship_stack[i].name )==0)
1141 WARN(_("Duplicated ship name '%s' detected!"), ship_stack[i].name);
1142#endif /* DEBUGGING */
1143
1144 /* Shrink stack. */
1146
1147 /* Second pass to load Lua. */
1148 for (int i=0; i<array_size(ship_stack); i++) {
1149 Ship *s = &ship_stack[i];
1150 if (s->lua_file==NULL)
1151 continue;
1152
1153 nlua_env env;
1154 size_t sz;
1155 char *dat = ndata_read( s->lua_file, &sz );
1156 if (dat==NULL) {
1157 WARN(_("Ship '%s' failed to read Lua '%s'!"), s->name, s->lua_file );
1158 continue;
1159 }
1160
1161 env = nlua_newEnv();
1162 s->lua_env = env;
1163 /* TODO limit libraries here. */
1164 nlua_loadStandard( env );
1165 nlua_loadGFX( env );
1166 nlua_loadCamera( env );
1167
1168 /* Run code. */
1169 if (nlua_dobufenv( env, dat, sz, s->lua_file ) != 0) {
1170 WARN(_("Ship '%s' Lua error:\n%s"), s->name, lua_tostring(naevL,-1));
1171 lua_pop(naevL,1);
1172 nlua_freeEnv( s->lua_env );
1173 free( dat );
1174 s->lua_env = LUA_NOREF;
1175 continue;
1176 }
1177 free( dat );
1178
1179 /* Check functions as necessary. */
1180 nlua_getenv( naevL, env, "update_dt" );
1181 if (!lua_isnoneornil(naevL,-1))
1182 s->lua_dt = luaL_checknumber(naevL,-1);
1183 lua_pop(naevL,1);
1184 s->lua_init = nlua_refenvtype( env, "init", LUA_TFUNCTION );
1185 s->lua_cleanup = nlua_refenvtype( env, "cleanup", LUA_TFUNCTION );
1186 s->lua_update = nlua_refenvtype( env, "update", LUA_TFUNCTION );
1187 s->lua_explode_init = nlua_refenvtype( env, "explode_init", LUA_TFUNCTION );
1188 s->lua_explode_update = nlua_refenvtype( env, "explode_update", LUA_TFUNCTION );
1189 }
1190
1191 /* Debugging timings. */
1192 if (conf.devmode) {
1193 time = SDL_GetTicks() - time;
1194 DEBUG( n_( "Loaded %d Ship in %.3f s", "Loaded %d Ships in %.3f s", array_size(ship_stack) ), array_size(ship_stack), time/1000. );
1195 }
1196 else
1197 DEBUG( n_( "Loaded %d Ship", "Loaded %d Ships", array_size(ship_stack) ), array_size(ship_stack) );
1198
1199 return 0;
1200}
1201
1205void ships_free (void)
1206{
1207 for (int i=0; i < array_size(ship_stack); i++) {
1208 Ship *s = &ship_stack[i];
1209
1210 /* Free stored strings. */
1211 free(s->name);
1212 free(s->class_display);
1213 free(s->description);
1214 free(s->desc_extra);
1215 free(s->base_type);
1216 free(s->fabricator);
1217 free(s->license);
1218 free(s->cond);
1219 free(s->condstr);
1220 free(s->desc_stats);
1221
1222 /* Free outfits. */
1223 for (int j=0; j<array_size(s->outfit_structure); j++)
1224 ship_freeSlot( &s->outfit_structure[j] );
1225 for (int j=0; j<array_size(s->outfit_utility); j++)
1226 ship_freeSlot( &s->outfit_utility[j] );
1227 for (int j=0; j<array_size(s->outfit_weapon); j++)
1228 ship_freeSlot( &s->outfit_weapon[j] );
1233
1234 ss_free( s->stats );
1235
1236 /* Free graphics. */
1237 object_free(s->gfx_3d);
1242 free(s->gfx_comm);
1243 for (int j=0; j<array_size(s->gfx_overlays); j++)
1246
1247 /* Free collision polygons. */
1248 for (int j=0; j<array_size(s->polygon); j++)
1249 FreePolygon(&s->polygon[j]);
1250 array_free(s->polygon);
1251
1253
1254 /* Free tags. */
1255 for (int j=0; j<array_size(s->tags); j++)
1256 free(s->tags[j]);
1257 array_free(s->tags);
1258
1259 /* Free Lua. */
1260 nlua_freeEnv( s->lua_env );
1261 s->lua_env = LUA_NOREF;
1262 free(s->lua_file);
1263 }
1264
1266 ship_stack = NULL;
1267}
1268
1269static void ship_freeSlot( ShipOutfitSlot* s )
1270{
1271 outfit_freeSlot( &s->slot );
1272 free( s->name );
1273}
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_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
Definition array.h:102
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_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
Definition array.h:149
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:129
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
void LoadPolygon(CollPoly *polygon, xmlNodePtr node)
Loads a polygon from an xml node.
Definition collision.c:35
void naev_renderLoadscreen(void)
Renders the loadscreen if necessary.
Definition naev.c:597
int naev_shouldRenderLoadscreen(void)
Whether or not we want to render the loadscreen.
Definition naev.c:556
Header file with generic functions and naev-specifics.
#define PATH_MAX
Definition naev.h:50
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
Definition ndata.c:154
int ndata_matchExt(const char *path, const char *ext)
Sees if a file matches an extension.
Definition ndata.c:365
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
Definition ndata.c:231
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
Definition nlua.c:798
int nlua_refenvtype(nlua_env env, const char *name, int type)
Gets the reference of a global in a lua environment if it matches a type.
Definition nlua.c:920
int nlua_loadCamera(nlua_env env)
Loads the camera library.
Definition nlua_camera.c:49
int nlua_loadGFX(nlua_env env)
Loads the graphics library.
Definition nlua_gfx.c:98
char * strndup(const char *s, size_t n)
Return a pointer to a new string, which is a duplicate of the string s (or, if necessary,...
Definition nstring.c:67
glTexture * xml_parseTexture(xmlNodePtr node, const char *path, int defsx, int defsy, const unsigned int flags)
Parses a texture handling the sx and sy elements.
Definition nxml.c:29
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
Definition nxml.c:75
void object_free(Object *object)
Frees memory reserved for the object.
Definition object.c:354
Object * object_loadFromFile(const char *filename)
Loads object.
Definition object.c:221
glInfo gl_screen
Definition opengl.c:51
glTexture * gl_newSprite(const char *path, const int sx, const int sy, const unsigned int flags)
Loads the texture immediately, but also sets it as a sprite.
Definition opengl_tex.c:791
glTexture * gl_loadImagePad(const char *name, SDL_Surface *surface, unsigned int flags, int w, int h, int sx, int sy, int freesur)
Loads the already padded SDL_Surface to a glTexture.
Definition opengl_tex.c:543
glTexture * gl_loadImagePadTrans(const char *name, SDL_Surface *surface, SDL_RWops *rw, unsigned int flags, int w, int h, int sx, int sy, int freesur)
Wrapper for gl_loadImagePad that includes transparency mapping.
Definition opengl_tex.c:427
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
Definition opengl_tex.c:675
void gl_getSpriteFromDir(int *x, int *y, const glTexture *t, const double dir)
Sets x and y to be the appropriate sprite for glTexture using dir.
Definition opengl_tex.c:967
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition opengl_tex.c:862
const Outfit * outfit_get(const char *name)
Gets an outfit by name.
Definition outfit.c:166
OutfitSlotSize outfit_toSlotSize(const char *s)
Gets the outfit slot size from a human readable string.
Definition outfit.c:461
int outfit_licenseExists(const char *name)
Checks to see if a license exists.
Definition outfit.c:3057
void outfit_freeSlot(OutfitSlot *s)
Frees an outfit slot.
Definition outfit.c:1115
int ship_size(const Ship *s)
Gets the size of the ship.
Definition ship.c:316
ShipClass ship_classFromString(const char *str)
Gets the machine ship class identifier from a human readable string.
Definition ship.c:236
static int ship_parseSlot(Ship *temp, ShipOutfitSlot *slot, OutfitSlotType type, xmlNodePtr node)
Parses a slot for a ship.
Definition ship.c:581
static Ship * ship_stack
Definition ship.c:59
const char * ship_class(const Ship *s)
Gets the ship's class name in human readable form.
Definition ship.c:165
const char * ship_classDisplay(const Ship *s)
Gets the ship's display class in human readable form.
Definition ship.c:176
credits_t ship_basePrice(const Ship *s)
Gets the ship's base price (no outfits).
Definition ship.c:266
static int ship_parseThread(void *ptr)
Wrapper for threaded loading.
Definition ship.c:1068
credits_t ship_buyPrice(const Ship *s)
The ship buy price, includes default outfits.
Definition ship.c:274
const Ship * ship_getW(const char *name)
Gets a ship based on its name without warning.
Definition ship.c:101
#define SHIP_ENGINE
Definition ship.c:38
int ships_load(void)
Loads all the ships in the data files.
Definition ship.c:1087
static int ship_loadEngineImage(Ship *temp, char *str, int sx, int sy)
Loads the space graphics for a ship from an image.
Definition ship.c:463
static int ship_cmp(const void *p1, const void *p2)
Compares two ship pointers for qsort.
Definition ship.c:73
const Ship * ship_getAll(void)
Gets the array (array.h) of all ships.
Definition ship.c:121
static int ship_loadSpaceImage(Ship *temp, char *str, int sx, int sy)
Loads the space graphics for a ship from an image.
Definition ship.c:416
void ships_free(void)
Frees all the ships.
Definition ship.c:1205
static int ship_loadGFX(Ship *temp, const char *buf, int sx, int sy, int engine)
Loads the graphics for a ship.
Definition ship.c:478
int ship_compareTech(const void *arg1, const void *arg2)
Comparison function for qsort().
Definition ship.c:129
const char * ship_classToString(ShipClass class)
Gets the ship class name in human readable form.
Definition ship.c:189
#define STATS_DESC_MAX
Definition ship.c:48
#define SHIP_COMM
Definition ship.c:40
static int ship_parse(Ship *temp, const char *filename)
Extracts the in-game ship from an XML node.
Definition ship.c:664
glTexture * ship_loadCommGFX(const Ship *s)
Loads the ship's comm graphic.
Definition ship.c:303
static int ship_loadPLG(Ship *temp, const char *buf, int size_hint)
Loads the collision polygon for a ship.
Definition ship.c:526
const Ship * ship_get(const char *name)
Gets a ship based on its name.
Definition ship.c:87
static int ship_genTargetGFX(Ship *temp, SDL_Surface *surface, int sx, int sy)
Generates a target graphic for a ship.
Definition ship.c:353
const char * ship_existsCase(const char *name)
Checks to see if an ship exists matching name (case insensitive).
Definition ship.c:110
int ss_statsListDesc(const ShipStatList *ll, char *buf, int len, int newline)
Writes the ship statistics description.
Definition shipstats.c:780
void ss_free(ShipStatList *ll)
Frees a list of ship stats.
Definition shipstats.c:887
int ss_statsMergeFromList(ShipStats *stats, const ShipStatList *list)
Updates a stat structure from a stat list.
Definition shipstats.c:627
int ss_statsInit(ShipStats *stats)
Initializes a stat structure.
Definition shipstats.c:430
int ss_check(void)
Checks for validity.
Definition shipstats.c:414
ShipStatList * ss_listFromXML(xmlNodePtr node)
Creates a shipstat list element from an xml node.
Definition shipstats.c:292
int ss_sort(ShipStatList **ll)
Sorts the ship stats, useful if doing saving stuff.
Definition shipstats.c:381
int sp_locked(unsigned int spid)
Gets whether or not a slot property is locked.
Definition slots.c:199
unsigned int sp_get(const char *name)
Gets the id of a slot property.
Definition slots.c:133
int sp_required(unsigned int spid)
Gets whether or not a slot property is required.
Definition slots.c:179
int sp_exclusive(unsigned int spid)
Gets whether or not a slot property is exclusive.
Definition slots.c:189
int sound_get(const char *name)
Gets the buffer to sound of name.
Definition sound.c:756
const TrailSpec * trailSpec_get(const char *name)
Gets a trail spec by name.
Definition spfx.c:1283
Represents a polygon used for collision detection.
Definition collision.h:13
OutfitSlotSize size
Definition outfit.h:113
int exclusive
Definition outfit.h:111
unsigned int spid
Definition outfit.h:110
OutfitSlotType type
Definition outfit.h:112
A ship outfit, depends radically on the type.
Definition outfit.h:328
credits_t price
Definition outfit.h:347
int devmode
Definition conf.h:157
double x
Definition ship.h:62
double y
Definition ship.h:63
double h
Definition ship.h:64
Ship outfit slot.
Definition ship.h:70
int exclusive
Definition ship.h:73
int required
Definition ship.h:74
const Outfit * data
Definition ship.h:76
char * name
Definition ship.h:72
ShipMount mount
Definition ship.h:77
OutfitSlot slot
Definition ship.h:71
int locked
Definition ship.h:75
Represents relative ship statistics as a linked list.
Definition shipstats.h:167
struct ShipStatList_ * next
Definition shipstats.h:168
Structure for threaded loading.
Definition ship.c:53
char * filename
Definition ship.c:54
Ship ship
Definition ship.c:55
Ship trail emitter.
Definition ship.h:83
double y_engine
Definition ship.h:85
const TrailSpec * trail_spec
Definition ship.h:88
double h_engine
Definition ship.h:86
double x_engine
Definition ship.h:84
unsigned int always_under
Definition ship.h:87
Represents a space ship.
Definition ship.h:94
double shield_regen
Definition ship.h:130
double dt_default
Definition ship.h:124
double cap_cargo
Definition ship.h:123
char * desc_extra
Definition ship.h:110
glTexture * gfx_space
Definition ship.h:138
ShipStats stats_array
Definition ship.h:165
char * license
Definition ship.h:105
double gfx_3d_scale
Definition ship.h:137
char * name
Definition ship.h:95
int sound
Definition ship.h:150
int fuel
Definition ship.h:121
char * fabricator
Definition ship.h:108
char * description
Definition ship.h:109
int lua_init
Definition ship.h:174
char * base_type
Definition ship.h:96
char * lua_file
Definition ship.h:171
char * class_display
Definition ship.h:98
credits_t price
Definition ship.h:104
int lua_update
Definition ship.h:176
double energy_regen
Definition ship.h:132
double armour
Definition ship.h:127
int fuel_consumption
Definition ship.h:122
double lua_dt
Definition ship.h:173
double armour_regen
Definition ship.h:128
glTexture * gfx_target
Definition ship.h:140
CollPoly * polygon
Definition ship.h:147
int crew
Definition ship.h:118
ShipStatList * stats
Definition ship.h:164
double dmg_absorb
Definition ship.h:133
double engine_pitch
Definition ship.h:151
char * condstr
Definition ship.h:107
char * cond
Definition ship.h:106
int points
Definition ship.h:99
double cpu
Definition ship.h:120
double mangle
Definition ship.h:160
double speed
Definition ship.h:115
ShipOutfitSlot * outfit_utility
Definition ship.h:155
double turn
Definition ship.h:114
char * desc_stats
Definition ship.h:163
char ** tags
Definition ship.h:168
Outfit const ** outfit_intrinsic
Definition ship.h:157
int rarity
Definition ship.h:100
glTexture * gfx_engine
Definition ship.h:139
double accel
Definition ship.h:113
int lua_cleanup
Definition ship.h:175
ShipOutfitSlot * outfit_weapon
Definition ship.h:156
nlua_env lua_env
Definition ship.h:172
Object * gfx_3d
Definition ship.h:136
glTexture * gfx_store
Definition ship.h:141
double energy
Definition ship.h:131
char * gfx_comm
Definition ship.h:142
ShipTrailEmitter * trail_emitters
Definition ship.h:144
int lua_explode_init
Definition ship.h:177
glTexture ** gfx_overlays
Definition ship.h:143
double shield
Definition ship.h:129
ShipClass class
Definition ship.h:97
double mass
Definition ship.h:119
ShipOutfitSlot * outfit_structure
Definition ship.h:154
int lua_explode_update
Definition ship.h:178
SDL_Window * window
Definition opengl.h:68
SDL_GLContext context
Definition opengl.h:69
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:36
double w
Definition opengl_tex.h:40
double sx
Definition opengl_tex.h:44
double sy
Definition opengl_tex.h:45
double h
Definition opengl_tex.h:41