26#define XML_TECH_ID "Techs"
27#define XML_TECH_TAG "tech"
32typedef enum tech_item_type_e {
43typedef struct tech_item_s {
68static tech_group_t *tech_groups = NULL;
82static tech_item_t *tech_addItemOutfit( tech_group_t *grp,
const char *name );
86static tech_item_t *tech_addItemTechInternal( tech_group_t *tech,
90 const tech_group_t *ptr );
94 const tech_group_t *tech );
96static int tech_cmp(
const void *p1,
const void *p2 )
98 const tech_group_t *t1 = p1;
99 const tech_group_t *t2 = p2;
100 return strcmp( t1->name, t2->name );
109 Uint32 time = SDL_GetTicks();
118 for (
int i = 0; i <
array_size( tech_files ); i++ ) {
127 tech.filename = strdup( tech_files[i] );
131 free( tech_files[i] );
137 qsort( tech_groups,
array_size( tech_groups ),
sizeof( tech_group_t ),
142 for (
int i = 0; i < s; i++ )
147 if ( conf.devmode ) {
148 DEBUG( n_(
"Loaded %d tech group in %.3f s",
149 "Loaded %d tech groups in %.3f s", s ),
150 s, ( SDL_GetTicks() - time ) / 1000. );
152 DEBUG( n_(
"Loaded %d tech group",
"Loaded %d tech groups", s ), s );
165 for (
int i = 0; i < s; i++ )
178 free( grp->filename );
198 tech_group_t *tech = calloc( 1,
sizeof( tech_group_t ) );
220 switch ( item->
type ) {
228 return tech_groups[item->
u.
grp].name;
248 xmlw_startElem( writer,
"tech" );
252 for (
int i = 0; i < s; i++ )
255 xmlw_endElem( writer );
270 parent = doc->xmlChildrenNode;
271 if ( parent == NULL ) {
272 WARN( _(
"Malformed '%s' file: does not contain elements" ), file );
277 memset( tech, 0,
sizeof( tech_group_t ) );
280 xmlr_attr_strd( parent,
"name", tech->name );
281 if ( tech->name == NULL ) {
282 WARN( _(
"tech node does not have 'name' attribute" ) );
297 xmlNodePtr node = parent->xmlChildrenNode;
299 xml_onlyNodes( node );
300 if ( xml_isNode( node,
"item" ) ) {
305 name = xml_get( node );
306 if ( name == NULL ) {
307 WARN( _(
"Tech group '%s' has an item without a value." ),
313 xmlr_attr_strd( node,
"type", buf );
315 itm = tech_addItemTechInternal( tech, name );
316 }
else if ( strcmp( buf,
"group" ) == 0 ) {
318 WARN( _(
"Group item '%s' not found in tech group '%s'." ), name,
320 }
else if ( strcmp( buf,
"outfit" ) == 0 ) {
321 itm = tech_addItemOutfit( tech, name );
322 WARN( _(
"Outfit item '%s' not found in tech group '%s'." ), name,
324 }
else if ( strcmp( buf,
"ship" ) == 0 ) {
326 WARN( _(
"Ship item '%s' not found in tech group '%s'." ), name,
328 }
else if ( strcmp( buf,
"commodity" ) == 0 ) {
331 WARN( _(
"Commodity item '%s' not found in tech group '%s'." ),
335 xmlr_attr_float_def( node,
"chance", itm->
chance, -1. );
339 WARN( _(
"Tech group '%s' has unknown node '%s'." ), tech->name,
341 }
while ( xml_nextNode( node ) );
352 const char *file = tech->filename;
357 parent = doc->xmlChildrenNode;
358 if ( parent == NULL ) {
359 WARN( _(
"Malformed '%s' file: does not contain elements" ), file );
376 if ( grp->items == NULL )
383static tech_item_t *tech_addItemOutfit( tech_group_t *grp,
const char *name )
452 WARN( _(
"Trying to add item '%s' to non-existent tech '%s'." ), value,
458 tech = &tech_groups[id];
463 ret = tech_addItemOutfit( tech, value );
469 WARN( _(
"Generic item '%s' not found in tech group '%s'" ), value,
482 return ( tech_addItemTechInternal( tech, value ) != NULL );
485static tech_item_t *tech_addItemTechInternal( tech_group_t *tech,
491 ret = tech_addItemOutfit( tech, value );
497 WARN( _(
"Generic item '%s' not found in tech group" ), value );
510 for (
int i = 0; i < s; i++ ) {
512 if ( strcmp( buf, value ) == 0 ) {
513 array_erase( &tech->items, &tech->items[i], &tech->items[i + 1] );
518 WARN( _(
"Item '%s' not found in tech group" ), value );
533 WARN( _(
"Trying to remove item '%s' to non-existent tech '%s'." ), value,
539 tech = &tech_groups[id];
543 for (
int i = 0; i < s; i++ ) {
545 if ( strcmp( buf, value ) == 0 ) {
546 array_erase( &tech->items, &tech->items[i], &tech->items[i + 1] );
551 WARN( _(
"Item '%s' not found in tech group '%s'" ), value, name );
560 const tech_group_t q = { .name = (
char *)name };
561 const tech_group_t *t = bsearch( &q, tech_groups,
array_size( tech_groups ),
562 sizeof( tech_group_t ), tech_cmp );
565 return t - tech_groups;
572 const tech_group_t *ptr )
612 memset( grp, 0,
sizeof( tech_group_t ) );
615 for (
int i = 0; i < num; i++ )
624 const tech_group_t *tech )
630 for (
int i = 0; i < size; i++ ) {
635 if ( item->
type != type )
640 for (
int j = 0; j <
array_size( items ); j++ ) {
641 if ( items[j] == item->
u.
ptr ) {
650 if ( ( item->
chance > 0. ) && ( RNGF() < item->
chance ) )
660 for (
int i = 0; i < size; i++ ) {
685 for (
int i = 0; i < s; i++ ) {
687 if ( strcmp( buf, item ) == 0 )
693static int tech_hasItemInternal(
const tech_group_t *tech,
699 for (
int i = 0; i < s; i++ ) {
703 switch ( item->
type ) {
722 if ( tech_hasItemInternal( &tech_groups[itemi->
u.
grp], item ) )
725 if ( tech_hasItemInternal( itemi->
u.
grpptr, item ) )
745 return tech_hasItemInternal( tech, &item );
761 return tech_hasItemInternal( tech, &item );
777 return tech_hasItemInternal( tech, &item );
803 names = malloc(
sizeof(
char *) * s );
805 for (
int i = 0; i < s; i++ )
823 names = malloc(
sizeof(
char *) * s );
825 for (
int i = 0; i < s; i++ )
826 names[i] = strdup( tech_groups[i].name );
983 for (
int i = 0; i <
array_size( to ); i++ ) {
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
int commodity_compareTech(const void *commodity1, const void *commodity2)
Function meant for use with C89, C99 algorithm qsort().
Commodity * commodity_getW(const char *name)
Gets a commodity by name without warning.
int ndata_matchExt(const char *path, const char *ext)
Sees if a file matches an extension.
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
int outfit_compareTech(const void *outfit1, const void *outfit2)
Function meant for use with C89, C99 algorithm qsort().
const Outfit * outfit_getW(const char *name)
Gets an outfit by name without warning on no-find.
const Ship * ship_getW(const char *name)
Gets a ship based on its name without warning.
int ship_compareTech(const void *arg1, const void *arg2)
Comparison function for qsort().
A ship outfit, depends radically on the type.
Group of tech items, basic unit of the tech trees.
Item contained in a tech group.
const tech_group_t * grpptr
union tech_item_t::@052232320132052006256273131130205035030043136237 u
static char * tech_getItemName(tech_item_t *item)
Gets an item's name.
static tech_item_t * tech_addItemCommodity(tech_group_t *grp, const char *name)
Loads a group item pertaining to a outfit.
void tech_free(void)
Cleans up after the tech stuff.
Ship ** tech_getShipArray(tech_group_t **tech, int num)
Gets the ships from an array of techs.
int tech_load(void)
Loads the tech information.
Commodity ** tech_getCommodity(const tech_group_t *tech)
Gets all of the ships associated to a tech group.
int tech_checkOutfit(const tech_group_t *tech, const Outfit *o)
Checks to see if there is an outfit in the tech group.
int tech_groupWrite(xmlTextWriterPtr writer, tech_group_t *grp)
Writes a group in an xml node.
static int tech_parseFile(tech_group_t *tech, const char *file)
Parses an XML tech node.
static void tech_createMetaGroup(tech_group_t *grp, tech_group_t **tech, int num)
Creates a meta-tech group pointing only to other groups.
int tech_hasShip(const tech_group_t *tech, const Ship *ship)
Checks to see whether a tech group contains a ship.
int tech_rmItemTech(tech_group_t *tech, const char *value)
Removes an item from a tech.
int tech_hasCommodity(const tech_group_t *tech, const Commodity *comm)
Checks to see whether a tech group contains a commodity.
tech_group_t * tech_groupCreate(void)
Creates a tech group.
static int tech_addItemGroupPointer(tech_group_t *grp, const tech_group_t *ptr)
Adds a group pointer to a group.
int tech_getItemCount(const tech_group_t *tech)
Gets the number of techs within a given group.
int tech_rmItem(const char *name, const char *value)
Removes a tech item.
tech_item_type_t
Different tech types.
@ TECH_TYPE_GROUP_POINTER
static void tech_freeGroup(tech_group_t *grp)
Cleans up a tech group.
static int tech_parseXMLData(tech_group_t *tech, xmlNodePtr parent)
Parses an XML tech node.
int tech_hasItem(const tech_group_t *tech, const char *item)
Checks whether a given tech group has the specified item.
tech_group_t * tech_groupCreateXML(xmlNodePtr node)
Creates a tech group from an XML node.
static int tech_getID(const char *name)
Gets the ID of a tech.
void tech_groupDestroy(tech_group_t *grp)
Frees a tech group.
static void ** tech_addGroupItem(void **items, tech_item_type_t type, const tech_group_t *tech)
Recursive function for creating an array of commodities from a tech group.
static tech_item_t * tech_itemGrow(tech_group_t *grp)
Adds an item to a tech.
Commodity ** tech_getCommodityArray(tech_group_t **tech, int num)
Gets the ships from an array of techs.
Ship ** tech_getShip(const tech_group_t *tech)
Gets all of the ships associated to a tech group.
int tech_addItemTech(tech_group_t *tech, const char *value)
Adds an item to a tech.
int tech_addItem(const char *name, const char *value)
Adds an item to a tech.
Outfit ** tech_getOutfitArray(tech_group_t **tech, int num)
Gets the outfits from an array of techs.
Outfit ** tech_getOutfit(const tech_group_t *tech)
Gets all of the outfits associated to a tech group.
static int tech_parseFileData(tech_group_t *tech)
Parses an XML tech node.
char ** tech_getItemNames(const tech_group_t *tech, int *n)
Gets the names of all techs within a given group.
int tech_hasOutfit(const tech_group_t *tech, const Outfit *outfit)
Checks to see whether a tech group contains a outfit.
static tech_item_t * tech_addItemShip(tech_group_t *grp, const char *name)
Loads a group item pertaining to a outfit.
static tech_item_t * tech_addItemGroup(tech_group_t *grp, const char *name)
Loads a group item pertaining to a group.
char ** tech_getAllItemNames(int *n)
Gets the names of all techs.