#include <string.h> #include "libxml/xmlreader.h" #include "log.h" #include "ship.h" #define MAX_PATH_NAME 20 // Maximum size of the path. #define XML_NODE_START 1 #define XML_NODE_TEXT 3 #define XML_NODE_CLOSE 15 #define XML_NODE_CDATA 4 #define XML_ID "Ships" // XML section identifier. #define XML_SHIP "ship" #define SHIP_DATA "../dat/ship.xml" #define SHIP_GFX "../gfx/ship/" static Ship* ship_stack = NULL; static int ships; // Get a ship based on it's name. Ship* get_ship(const char* name) { Ship* tmp = ship_stack; int i; for(i = 0; i < ships; i++) if(strcmp((tmp+i)->name, name)==0) break; return tmp+1; } Ship* ship_parse(xmlNodePtr node) { xmlNodePtr cur; Ship* tmp = CALLOC_L(Ship); char str[MAX_PATH_NAME] = "\0"; tmp->name = (char*)xmlGetProp(node, (xmlChar*)"name"); node = node->xmlChildrenNode; while((node = node->next)) { if(strcmp((char*)node->name, "GFX")==0) { cur = node->children; if(strcmp((char*)cur->name, "text")==0) { snprintf(str, strlen((char*)cur->content)+sizeof(SHIP_GFX), SHIP_GFX"%s", (char*)cur->content); tmp->gfx_ship = gl_newSprite(str, 6, 6); } } else if(strcmp((char*)node->name, "class")==0) { cur = node->children; if(strcmp((char*)cur->name, "text")==0) tmp->class = atoi((char*)cur->content); } else if(strcmp((char*)node->name, "movement")==0) { cur = node->children; while((cur = cur->next)) { if(strcmp((char*)cur->name, "thrust")==0) tmp->thrust = atoi((char*)cur->children->content); else if(strcmp((char*)cur->name, "turn")==0) tmp->turn = atoi((char*)cur->children->content); else if(strcmp((char*)cur->name, "speed")==0) tmp->speed = atoi((char*)cur->children->content); } } else if(strcmp((char*)node->name, "health")==0) { cur = node->children; while((cur = cur->next)) { if(strcmp((char*)cur->name, "armor")==0) tmp->armor = (FP)atoi((char*)cur->children->content); else if(strcmp((char*)cur->name, "shield")==0) tmp->shield = (FP)atoi((char*)cur->children->content); else if(strcmp((char*)cur->name, "energy")==0) tmp->energy = (FP)atoi((char*)cur->children->content); else if(strcmp((char*)cur->name, "armor_regen")==0) tmp->armor_regen = (FP)(atoi((char*)cur->children->content))/60.0; else if(strcmp((char*)cur->name, "shield_regen")==0) tmp->shield_regen = (FP)(atoi((char*)cur->children->content))/60.0; else if(strcmp((char*)cur->name, "energy_regen")==0) tmp->energy_regen = (FP)(atoi((char*)cur->children->content))/60.0; } } else if(strcmp((char*)node->name, "characteristics")==0) { cur = node->children; while((cur = cur->next)) { if(strcmp((char*)cur->name, "crew")==0) tmp->crew = atoi((char*)cur->children->content); else if(strcmp((char*)cur->name, "mass")==0) tmp->mass = (FP)atoi((char*)cur->children->content); else if(strcmp((char*)cur->name, "cap_weapon")==0) tmp->cap_weapon = atoi((char*)cur->children->content); else if(strcmp((char*)cur->name, "cap_cargo")==0) tmp->cap_cargo = atoi((char*)cur->children->content); } } } tmp->thrust *= tmp->mass; // Helps keep number sane. DEBUG("Loaded ship '%s'", tmp->name); return tmp; } int ships_load(void) { xmlTextReaderPtr reader; xmlNodePtr node; Ship* tmp = NULL; if((reader = xmlNewTextReaderFilename(SHIP_DATA)) == NULL) { WARN("XML error reading " SHIP_DATA); return -1; } // Get to the start of the "ships" section. while(xmlTextReaderRead(reader)==1) { if(xmlTextReaderNodeType(reader)==XML_NODE_START && strcmp((char*)xmlTextReaderConstName(reader), XML_ID) == 0) break; } xmlTextReaderRead(reader); // At ships node. while(xmlTextReaderRead(reader)==1) { if(xmlTextReaderNodeType(reader)==XML_NODE_START && strcmp((char*)xmlTextReaderConstName(reader), XML_SHIP)==0) { node = xmlTextReaderCurrentNode(reader); // Node to process. if(ship_stack == NULL) { ship_stack = tmp = ship_parse(node); ships = 1; } else { tmp = ship_parse(node); ship_stack = realloc(ship_stack, sizeof(Ship)*(++ships)); memcpy(ship_stack+ships-1, tmp, sizeof(Ship)); free(tmp); } } } xmlFreeTextReader(reader); return 0; } void ships_free(void) { int i; for(i = 0; i < ships; i++) { if((ship_stack+i)->name) free((ship_stack+i)->name); gl_freeTexture((ship_stack+i)->gfx_ship); } free(ship_stack); ship_stack = NULL; }