diff --git a/dat/gui.xml b/dat/gui.xml index caa6791..ed34522 100644 --- a/dat/gui.xml +++ b/dat/gui.xml @@ -8,6 +8,7 @@ <shield w="98" h="8" x="52" y="201" /> <armour w="98" h="8" x="52" y="212" /> <energy w="98" h="8" x="52" y="223" /> + <fuel w="0" h="0" x="0" y="0" /> </health> <weapon x="40" y="239" w="112" h="42" /> <target> diff --git a/src/colour.c b/src/colour.c index 74d3a0c..bbcb401 100644 --- a/src/colour.c +++ b/src/colour.c @@ -47,4 +47,5 @@ glColour cRadar_weap = { .r = 0.8, .g = 0.2, .b = 0.2, .a = 1. }; /**< Weapon glColour cShield = { .r = 0.2, .g = 0.2, .b = 0.8, .a = 1. }; /**< Shield bar colour. */ glColour cArmour = { .r = 0.5, .g = 0.5, .b = 0.5, .a = 1. }; /**< Armour bar colour. */ glColour cEnergy = { .r = 0.2, .g = 0.8, .b = 0.2, .a = 1. }; /**< Energy bar colour. */ +glColour cFuel = { .r = 0.8, .g = 0.2, .b = 0.8, .a = 1. }; /**< Fuel bar colour. */ diff --git a/src/colour.h b/src/colour.h index 5f2ca31..bf65bfe 100644 --- a/src/colour.h +++ b/src/colour.h @@ -56,4 +56,5 @@ extern glColour cRadar_weap; extern glColour cShield; extern glColour cArmour; extern glColour cEnergy; +extern glColour cFuel; diff --git a/src/economy.c b/src/economy.c index d85bf59..ff75dba 100644 --- a/src/economy.c +++ b/src/economy.c @@ -64,14 +64,10 @@ static Commodity* commodity_parse(xmlNodePtr parent) { node = parent->xmlChildrenNode; do { - if(xml_isNode(node, "description")) - tmp->description = strdup(xml_get(node)); - else if(xml_isNode(node, "high")) - tmp->high = xml_getInt(node); - else if(xml_isNode(node, "medium")) - tmp->medium = xml_getInt(node); - else if(xml_isNode(node, "low")) - tmp->low = xml_getInt(node); + xmlr_strd(node, "description", tmp->description); + xmlr_strd(node, "high", tmp->high); + xmlr_strd(node, "medium", tmp->medium); + xmlr_strd(node, "low", tmp->low); } while((node = node->next)); #if 0 /* Let's kill this for now. */ #define MELEMENT(o,s)if(o)WARN("Commodity '%s' missing '"s"' element",tmp->name) diff --git a/src/lephisto.c b/src/lephisto.c index ac7fabf..2b656bb 100644 --- a/src/lephisto.c +++ b/src/lephisto.c @@ -71,9 +71,9 @@ static unsigned int time = 0; /**< Used to calculate FPS and movement, in pa static char version[VERSION_LEN]; /**< Contains version. */ static glTexture* loading; /**< Loading screen. */ -/* Just some default crap. */ +/* Some defaults. */ char* data = NULL; /**< Path to datafile. */ -char dataname[DATA_NAME_LEN] = ""; /**< Name of data file. */ +char* dataname = NULL; /**< Name of data file. */ int nosound = 0; /**< Disable sound when loaded. */ int show_fps = 1; /**< Shows fps - default true. */ int max_fps = 0; /**< Default FPS limit, 0 is no limit. */ @@ -640,10 +640,7 @@ static void data_name(void) { return; } do { - if(xml_isNode(node, "name")) { - strncpy(dataname, xml_get(node), DATA_NAME_LEN); - dataname[DATA_NAME_LEN-1] = '\0'; - } + xmlr_strd(node, "name", dataname); } while(xml_nextNode(node)); xmlFreeDoc(doc); @@ -656,10 +653,14 @@ static void data_name(void) { * @brief Set the window caption. */ static void window_caption(void) { - char tmp[DATA_NAME_LEN+10]; + size_t len; + char* tmp; - snprintf(tmp, DATA_NAME_LEN+10, APPNAME" - %s", dataname); + len = strlen(dataname) + strlen(APPNAME); + tmp = malloc(sizeof(char)*len); + snprintf(tmp, len, APPNAME" - %s", dataname); SDL_WM_SetCaption(tmp, NULL); + free(tmp); } static char human_version[50]; /**< Stores human readable version string. */ diff --git a/src/lephisto.h b/src/lephisto.h index 89b65ab..34e6f76 100644 --- a/src/lephisto.h +++ b/src/lephisto.h @@ -26,8 +26,7 @@ #endif extern char* data; /**< Modifiable datafile. */ #define DATA data /**< Standard data file to use. */ -#define DATA_NAME_LEN 32 /**< Max length of data name. */ -extern char dataname[DATA_NAME_LEN]; /**< Datafile name. */ +extern char *dataname; /**< Datafile name. */ /* Max filename path. */ #ifndef PATH_MAX diff --git a/src/misn_lua.c b/src/misn_lua.c index c12dcd5..44707d2 100644 --- a/src/misn_lua.c +++ b/src/misn_lua.c @@ -362,15 +362,15 @@ int var_load(xmlNodePtr parent) { var.type = MISN_VAR_NIL; else if(strcmp(str, "num")==0) { var.type = MISN_VAR_NUM; - var.d.num = atoi(xml_get(cur)); + var.d.num = xml_getFloat(cur); } else if(strcmp(str, "bool")==0) { var.type = MISN_VAR_BOOL; - var.d.b = atoi(xml_get(cur)); + var.d.b = xml_getInt(cur); } else if(strcmp(str, "str")==0) { var.type = MISN_VAR_STR; - var.d.str = atoi(xml_get(cur)); + var.d.str = xml_getStrd(cur); } else { /* Supeh error checking. */ WARN("Unknown var type '%s'", str); diff --git a/src/pilot.c b/src/pilot.c index 06acbce..1289844 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -1691,7 +1691,7 @@ static Fleet* fleet_parse(const xmlNodePtr parent) { if(xml_isNode(node, "faction")) tmp->faction = faction_get(xml_get(node)); else if(xml_isNode(node, "ai")) - tmp->ai = strdup(xml_get(node)); + tmp->ai = xml_getStrd(node); else if(xml_isNode(node, "pilots")) { cur = node->children; do { diff --git a/src/player.c b/src/player.c index 558ad4d..99cb905 100644 --- a/src/player.c +++ b/src/player.c @@ -143,17 +143,31 @@ typedef struct GUI_ { glTexture* gfx_frame; /**< Frame of the GUI. */ glTexture* gfx_targetPilot, *gfx_targetPlanet; /**< Graphics used to target planets. */ - Radar radar; /**< The radar. */ - Rect nav; /**< Navigation computer. */ - Rect shield; /**< Shield bar. */ - Rect armour; /**< Armour bar. */ - Rect energy; /**< Energy bar. */ - Rect weapon; /**< Weapon targeting system. */ - Rect target_health; /**< Target health. */ - Rect target_name; /**< Name of the target. */ - Rect target_faction; /**< Faction of the target. */ - Rect misc; /**< Misc stuff: credits, cargo.. */ - Rect msg; /**< Where messages go. */ + /* Rects. */ + + /* Radar. */ + Radar radar; /**< The radar. */ + /* Navigation. */ + Rect nav; /**< Navigation computer. */ + /* Health. */ + Rect shield; /**< Shield bar. */ + glTexture* gfx_shield; /**< Shield bar texture if applicable. */ + Rect armour; /**< Armour bar. */ + glTexture* gfx_armour; /**M Armour bar texture if applicable. */ + Rect energy; /**< Energy bar. */ + glTexture* gfx_energy; /**< Energy bar texture if applicable. */ + Rect fuel; /**< Fuel bar. */ + glTexture* gfx_fuel; /**< Fuel bar texture if applicable. */ + /* Weapon. */ + Rect weapon; /**< Weapon targeting system. */ + /* Targetting. */ + Rect target_health; /**< Target health. */ + Rect target_name; /**< Name of the target. */ + Rect target_faction; /**< Faction of the target. */ + /* Misc. */ + Rect misc; /**< Misc stuff: credits, cargo.. */ + /* Messages. */ + Rect msg; /**< Where messages go. */ /* Positions. */ Vec2 frame; /**< Global frame position. */ @@ -200,11 +214,14 @@ static void player_newShipMake(char* name); /* Sound. */ static void player_initSound(void); /* Gui. */ +static void rect_parseParam(const xmlNodePtr parent, char* name, double* param); static void rect_parse(const xmlNodePtr parent, double* x, double* y, double* w, double* h); static int gui_parse(const xmlNodePtr parent, const char* name); static void gui_renderPilot(const Pilot* p); -static void gui_renderBar(const glColour* c, const Rect* r, const double w); +static void gui_renderHealth(const glColour* c, const Rect* r, + const glTexture* tex, const double w); +static void gui_cleanup(void); /* Save/Load. */ static int player_saveShip(xmlTextWriterPtr writer, Pilot* ship, char* loc); static int player_parse(xmlNodePtr parent); @@ -337,8 +354,7 @@ static int player_newMake(void) { tmp = cur->children; do { /* System name. @todo Chance based on percentage. */ - if(xml_isNode(tmp, "name")) - sysname = strdup(xml_get(tmp)); + xmlr_strd(tmp, "name", sysname); /* Position. */ xmlr_float(tmp, "x", x); xmlr_float(tmp, "y", y); @@ -358,7 +374,7 @@ static int player_newMake(void) { WARN("start.xml already contains a mission node!"); continue; } - player_mission = strdup(xml_get(cur)); + player_mission = xml_getStrd(cur); } } while((cur = cur->next)); } @@ -983,9 +999,10 @@ void player_renderGUI(void) { } /* Health */ - gui_renderBar(&cShield, &gui.shield, player->shield / player->shield_max); - gui_renderBar(&cArmour, &gui.armour, player->armour / player->armour_max); - gui_renderBar(&cEnergy, &gui.energy, player->energy / player->energy_max); + gui_renderHealth(&cShield, &gui.shield, &gui.gfx_shield, player->shield / player->shield_max); + gui_renderHealth(&cArmour, &gui.armour, &gui.gfx_armour, player->armour / player->armour_max); + gui_renderHealth(&cEnergy, &gui.energy, &gui.gfx_energy, player->energy / player->energy_max); + gui_renderHealth(&cFuel, &gui.fuel, &gui.gfx_fuel, player->fuel / player->fuel_max); /* Weapon. */ if(player->secondary == NULL) { @@ -1222,21 +1239,59 @@ static void gui_renderPilot(const Pilot* p) { glEnd(); } -/* Render a bar. */ -static void gui_renderBar(const glColour* c, const Rect* r, const double w) { - int x, y, sx, sy; +/** + * @brief Render a health bar. + */ +static void gui_renderHealth(const glColour* c, const Rect* r, const glTexture* tex, + const double w) { + + double x, y, sx, sy, tx, ty; - glBegin(GL_QUADS); + /* Set colour. */ COLOUR(*c); - x = r->x - SCREEN_W/2.; - y = r->y - SCREEN_H/2.; - sx = w * r->w; - sy = r->h; - glVertex2d(x, y); - glVertex2d(x+sx, y); - glVertex2d(x+sx, y-sy); - glVertex2d(x, y-sy); - glEnd(); + + /* Just create a bar. */ + if(tex == NULL) { + /* Set the position values. */ + x = r->x - SCREEN_W/2.; + y = r->y - SCREEN_H/2.; + sx = w * r->w; + sy = r->h; + + glBegin(GL_QUADS); + glVertex2d(x, y); + glVertex2d(x+sx, y); + glVertex2d(x+sx, y-sy); + glVertex2d(x, y-sy); + glEnd(); + } else { /* Render the texture. */ + /* Set the position values. */ + x = r->x - SCREEN_W/2.; + y = r->y - SCREEN_H/2. + tex->sh; + sx = w * tex->sw; + sy = tex->sh; + tx = tex->sw / tex->rw; + ty = tex->sh / tex->rh; + + /* Draw the image. */ + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex->texture); + glBegin(GL_QUADS); + COLOUR(*c); + glTexCoord2d(0., ty); + glVertex2d(x, y); + + glTexCoord2d(w*tx, ty); + glVertex2d(x + sx, y); + + glTexCoord2d(w*tx, 0.); + glVertex2d(x+sx, y - sy); + + glTexCoord2d(0., 0.); + glVertex2d(x, y - sy); + glEnd(); + glDisable(GL_TEXTURE_2D); + } } /** @@ -1247,9 +1302,7 @@ static void gui_renderBar(const glColour* c, const Rect* r, const double w) { */ int gui_init(void) { /* Set graphics to NULL. */ - gui.gfx_frame = NULL; - gui.gfx_targetPilot = NULL; - gui.gfx_targetPlanet = NULL; + memset(&gui, 0, sizeof(GUI)); /* -- Radar. */ gui.radar.res = RADAR_RES_DEFAULT; @@ -1364,6 +1417,9 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { xmlNodePtr cur, node; char* tmp, buf[PATH_MAX]; + /* Clean up. */ + gui_cleanup(); + /* Gfx. */ /* Set a property and not a node because it must be loaded first. */ tmp = xml_nodeProp(parent, "gfx"); @@ -1375,15 +1431,12 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { /* Frame. */ snprintf(buf, PATH_MAX, GUI_GFX"%s.png", tmp); - if(gui.gfx_frame) gl_freeTexture(gui.gfx_frame); /* Free if needed. */ gui.gfx_frame = gl_newImage(buf); /* Pilot. */ snprintf(buf, PATH_MAX, GUI_GFX"%s_pilot.png", tmp); - if(gui.gfx_targetPilot) gl_freeTexture(gui.gfx_targetPilot); /* Free if needed. */ gui.gfx_targetPilot = gl_newSprite(buf, 2, 2); /* Planet. */ snprintf(buf, PATH_MAX, GUI_GFX"%s_planet.png", tmp); - if(gui.gfx_targetPlanet) gl_freeTexture(gui.gfx_targetPlanet); /* Free if needed. */ gui.gfx_targetPlanet = gl_newSprite(buf, 2, 2); free(tmp); @@ -1430,20 +1483,34 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { if(xml_isNode(cur, "shield")) { rect_parse(cur, &gui.shield.x, &gui.shield.y, &gui.shield.w, &gui.shield.h); + tmp = xml_get(cur); + if(tmp != NULL) + gui.gfx_shield = gl_newImage(tmp); RELATIVIZE(gui.shield); } if(xml_isNode(cur, "armour")) { rect_parse(cur, &gui.armour.x, &gui.armour.y, &gui.armour.w, &gui.armour.h); + if(tmp != NULL) + gui.gfx_armour = gl_newImage(tmp); RELATIVIZE(gui.armour); } if(xml_isNode(cur, "energy")) { rect_parse(cur, &gui.energy.x, &gui.energy.y, &gui.energy.w, &gui.energy.h); + if(tmp != NULL) + gui.gfx_energy = gl_newImage(tmp); RELATIVIZE(gui.energy); } + if(xml_isNode(cur, "fuel")) { + rect_parse(cur, &gui.fuel.x, &gui.fuel.y, + &gui.fuel.w, &gui.fuel.h); + if(tmp != NULL) + gui.gfx_fuel = gl_newImage(tmp); + RELATIVIZE(gui.fuel); + } } while((cur = cur->next)); } /* Secondary weapon. */ @@ -1494,15 +1561,49 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { #undef RELATIVIZE /** - * @fn void gui_free(void) - * + * @brief Clean up the GUI. + */ +static void gui_cleanup(void) { + /* Free textures. */ + if(gui.gfx_frame != NULL) { + gl_freeTexture(gui.gfx_frame); + gui.gfx_frame = NULL; + } + if(gui.gfx_targetPilot != NULL) { + gl_freeTexture(gui.gfx_targetPilot); + gui.gfx_targetPilot = NULL; + } + if(gui.gfx_targetPlanet != NULL) { + gl_freeTexture(gui.gfx_targetPlanet); + gui.gfx_targetPlanet = NULL; + } + /* Health textures. */ + if(gui.gfx_shield != NULL) { + gl_freeTexture(gui.gfx_shield); + gui.gfx_shield = NULL; + } + if(gui.gfx_armour != NULL) { + gl_freeTexture(gui.gfx_armour); + gui.gfx_armour = NULL; + } + if(gui.gfx_energy != NULL) { + gl_freeTexture(gui.gfx_energy); + gui.gfx_energy = NULL; + } + if(gui.gfx_fuel != NULL) { + gl_freeTexture(gui.gfx_fuel); + gui.gfx_fuel = NULL; + } +} + +/** * @brief Free the GUI. */ void gui_free(void) { - if(gui.gfx_frame) gl_freeTexture(gui.gfx_frame); - if(gui.gfx_targetPilot) gl_freeTexture(gui.gfx_targetPilot); - if(gui.gfx_targetPlanet) gl_freeTexture(gui.gfx_targetPlanet); + /* Clean up gui. */ + gui_cleanup(); + /* Free messages. */ free(msg_stack); } diff --git a/src/ship.c b/src/ship.c index 77c1b08..4001c4e 100644 --- a/src/ship.c +++ b/src/ship.c @@ -239,13 +239,13 @@ static Ship* ship_parse(xmlNodePtr parent) { if(xml_isNode(node,"GFX")) { /* Load the base graphic. */ - snprintf(str, strlen(xml_get(node)) + + snprintf(str, strlen(xml_raw(node)) + sizeof(SHIP_GFX) + sizeof(SHIP_EXT), SHIP_GFX"%s"SHIP_EXT, xml_get(node)); tmp->gfx_space = gl_newSprite(str, 6, 6); /* Load the comm graphic. */ - snprintf(str, strlen(xml_get(node))+ + snprintf(str, strlen(xml_raw(node))+ sizeof(SHIP_GFX)+sizeof(SHIP_COMM)+sizeof(SHIP_EXT), SHIP_GFX"%s"SHIP_COMM SHIP_EXT, xml_get(node)); tmp->gfx_comm = gl_newImage(str); @@ -259,7 +259,7 @@ static Ship* ship_parse(xmlNodePtr parent) { tmp->gfx_target = gl_newImage(str); free(stmp); } else { /* Load standard target graphic. */ - snprintf(str, strlen(xml_get(node)) + + snprintf(str, strlen(xml_raw(node)) + sizeof(SHIP_GFX)+sizeof(SHIP_TARGET)+sizeof(SHIP_EXT), SHIP_GFX"%s"SHIP_TARGET SHIP_EXT, xml_get(node)); tmp->gfx_target = gl_newImage(str); diff --git a/src/space.c b/src/space.c index 8417a7d..d22b5ce 100644 --- a/src/space.c +++ b/src/space.c @@ -686,7 +686,7 @@ static int planet_parse(Planet* planet, const xmlNodePtr parent) { planet->gfx_space = gl_newImage(str); } else if(xml_isNode(cur, "exterior")) { /* Load land gfx. */ - len = strlen(xml_get(cur)) + sizeof(PLANET_GFX_EXTERIOR); + len = strlen(xml_raw(cur)) + sizeof(PLANET_GFX_EXTERIOR); planet->gfx_exterior = malloc(len); snprintf(planet->gfx_exterior, len, PLANET_GFX_EXTERIOR"%s", xml_get(cur)); } @@ -715,9 +715,9 @@ static int planet_parse(Planet* planet, const xmlNodePtr parent) { planet->faction = faction_get(xml_get(cur)); } else if(xml_isNode(cur, "description")) - planet->description = strdup(xml_get(cur)); + planet->description = xml_getStrd(cur); else if(xml_isNode(cur, "bar")) - planet->bar_description = strdup(xml_get(cur)); + planet->bar_description = xml_getStrd(cur); else if(xml_isNode(cur, "services")) { flags |= FLAG_SERVICESET; planet->services = xml_getInt(cur); /* Flags gotten by data. */ @@ -1072,7 +1072,7 @@ static void system_parseJumps(const xmlNodePtr parent) { do { if(xml_isNode(cur, "jump")) { for(i = 0; i < systems_nstack; i++) - if(strcmp(systems_stack[i].name, xml_get(cur))==0) { + if(strcmp(systems_stack[i].name, xml_raw(cur))==0) { sys->njumps++; sys->jumps = realloc(sys->jumps, sys->njumps*sizeof(int)); sys->jumps[sys->njumps-1] = i; diff --git a/src/xml.h b/src/xml.h index ddd9628..5c5452d 100644 --- a/src/xml.h +++ b/src/xml.h @@ -21,10 +21,12 @@ #define xml_nodeProp(n,s) (char*)xmlGetProp(n, (xmlChar*)s) /* Get data different ways. */ -#define xml_get(n) ((char*)(n)->children->content) -#define xml_getInt(n) (atoi((char*)(n)->children->content)) -#define xml_getLong(n) (atoi((char*)(n)->children->content)) -#define xml_getFloat(n) (atof((char*)(n)->children->content)) +#define xml_raw(n) ((char*)(n)->children->content) +#define xml_get(n) (((n)->children == NULL) ? NULL : (char*)(n)->children->content) +#define xml_getInt(n) ((xml_get(n) == NULL) ? 0 : atoi(xml_raw(n))) +#define xml_getLong(n) ((xml_get(n) == NULL) ? 0 : atol(xml_raw(n))) +#define xml_getFloat(n) ((xml_get(n) == NULL) ? 0. : atof(xml_raw(n))) +#define xml_getStrd(n) ((xml_get(n) == NULL) ? NULL : strdup(xml_raw(n))) /* Reader crap. */ #define xmlr_int(n,s,i) \ @@ -36,7 +38,7 @@ #define xmlr_str(n,s,str) \ if(xml_isNode(n,s)) { str = xml_get(n); continue; } #define xmlr_strd(n,s,str) \ - if(xml_isNode(n,s)) { str = strdup(xml_get(n)); continue; } + if(xml_isNode(n,s)) { str = ((xml_get(n) == NULL) ? NULL : strdup(xml_raw(n))); continue; } #define xmlr_attr(n,s,a) \ a = xml_nodeProp(n,s)