Lephisto/src/ship.c
2013-02-02 06:15:51 +00:00

154 lines
4.6 KiB
C

#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;
}