[Change] Improved outfit loading somewhat.

This commit is contained in:
Allanis 2014-01-21 20:07:29 +00:00
parent 20244a585d
commit 0c1f50a2ff
4 changed files with 62 additions and 37 deletions

View File

@ -18,6 +18,8 @@
#define OUTFIT_DATA "../dat/outfit.xml"
#define OUTFIT_GFX "../gfx/outfit/"
#define CHUNK_SIZE 64 /** Size to reallocate by. */
/* The Stack. */
static Outfit* outfit_stack = NULL;
static int outfit_nstack = 0;
@ -27,7 +29,7 @@ static DamageType outfit_strToDamageType(char* buf);
static OutfitType outfit_strToOutfitType(char* buf);
/* Parsing. */
static int outfit_parseDamage(DamageType* dtype, double* dmg, xmlNodePtr node);
static Outfit* outfit_parse(const xmlNodePtr parent);
static int outfit_parse(Outfit* tmp, const xmlNodePtr parent);
static void outfit_parseSBolt(Outfit* tmp, const xmlNodePtr parent);
static void outfit_parseSBeam(Outfit* tmp, const xmlNodePtr parent);
static void outfit_parseSLauncher(Outfit* tmp, const xmlNodePtr parent);
@ -368,12 +370,10 @@ int outfit_delay(const Outfit* o) {
}
/**
* @fn char* outfit_ammo(const Outfit* o)
*
* @brief Get the outfits ammo.
* @param o Outfit to get information from.
*/
char* outfit_ammo(const Outfit* o) {
Outfit* outfit_ammo(const Outfit* o) {
if(outfit_isLauncher(o)) return o->u.lau.ammo;
else if(outfit_isFighterBay(o)) return o->u.bay.ammo;
return NULL;
@ -671,12 +671,12 @@ static void outfit_parseSLauncher(Outfit* tmp, const xmlNodePtr parent) {
do {
/* Load the dataz. */
xmlr_int(node, "delay", tmp->u.lau.delay);
xmlr_strd(node, "ammo", tmp->u.lau.ammo);
xmlr_strd(node, "ammo", tmp->u.lau.ammo_name);
} while((node = node->next));
#define MELEMENT(o,s) if(o) WARN("Outfit '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->u.lau.ammo == NULL, "ammo");
MELEMENT(tmp->u.lau.delay==0, "delay");
MELEMENT(tmp->u.lau.ammo_name == NULL, "ammo");
MELEMENT(tmp->u.lau.delay==0, "delay");
#undef MELEMENT
}
@ -792,13 +792,13 @@ static void outfit_parseSFighterBay(Outfit* tmp, const xmlNodePtr parent) {
do {
xmlr_int(node, "delay", tmp->u.bay.delay);
xmlr_strd(node, "ammo", tmp->u.bay.ammo);
xmlr_strd(node, "ammo", tmp->u.bay.ammo_name);
} while(xml_nextNode(node));
#define MELEMENT(o,s) \
if(o) WARN("Outfit '%s' missing/invalid '"s"' element", tmp->name)
MELEMENT(tmp->u.bay.delay==0, "delay");
MELEMENT(tmp->u.bay.ammo==NULL, "ammo");
MELEMENT(tmp->u.bay.delay==0, "delay");
MELEMENT(tmp->u.bay.ammo_name==NULL, "ammo");
#undef MELEMENT
}
@ -857,12 +857,14 @@ static void outfit_parseSJammer(Outfit* tmp, const xmlNodePtr parent) {
}
/* Parse and return Outfits from parent node. */
static Outfit* outfit_parse(const xmlNodePtr parent) {
Outfit* tmp = CALLOC_L(Outfit);
static int outfit_parse(Outfit* tmp, const xmlNodePtr parent) {
xmlNodePtr cur, node;
char* prop;
char str[PATH_MAX] = "\0";
/* Clear data. */
memset(tmp, 0, sizeof(Outfit));
tmp->name = xml_nodeProp(parent, "name"); /* Already malloced. */
if(tmp->name == NULL) WARN("Outfit in "OUTFIT_DATA" has invalid or no name");
@ -934,16 +936,15 @@ static Outfit* outfit_parse(const xmlNodePtr parent) {
MELEMENT(tmp->description==NULL, "description");
#undef MELEMENT
return tmp;
return 0;
}
/* Load all the outfits into the outfit stack. */
int outfit_load(void) {
int i, mem;
uint32_t bufsize;
char* buf = pack_readfile(DATA, OUTFIT_DATA, &bufsize);
Outfit* tmp;
xmlNodePtr node;
xmlDocPtr doc = xmlParseMemory(buf, bufsize);
@ -959,15 +960,27 @@ int outfit_load(void) {
return -1;
}
/* First pass, load up ammunition. */
mem = 0;
do {
if(xml_isNode(node, XML_OUTFIT_TAG)) {
tmp = outfit_parse(node);
outfit_stack = realloc(outfit_stack, sizeof(Outfit)*(++outfit_nstack));
memmove(outfit_stack+outfit_nstack-1, tmp, sizeof(Outfit));
free(tmp);
outfit_nstack++;
if(outfit_nstack > mem) {
mem += CHUNK_SIZE;
outfit_stack = realloc(outfit_stack, sizeof(Outfit)*mem);
}
outfit_parse(&outfit_stack[outfit_nstack-1], node);
}
} while((node = node->next));
/* Second pass, set up ammunition relationships. */
for(i = 0; i < outfit_nstack; i++) {
if(outfit_isLauncher(&outfit_stack[i]))
outfit_stack[i].u.lau.ammo = outfit_get(outfit_stack[i].u.lau.ammo_name);
else if(outfit_isFighterBay(&outfit_stack[i]))
outfit_stack[i].u.bay.ammo = outfit_get(outfit_stack[i].u.bay.ammo_name);
}
xmlFreeDoc(doc);
free(buf);
@ -988,10 +1001,10 @@ void outfit_free(void) {
gl_freeTexture(outfit_gfx(&outfit_stack[i]));
/* Type specification. */
if(outfit_isLauncher(o) && o->u.lau.ammo)
free(o->u.lau.ammo);
if(outfit_isFighterBay(o) && o->u.bay.ammo)
free(o->u.bay.ammo);
if(outfit_isLauncher(o) && o->u.lau.ammo_name)
free(o->u.lau.ammo_name);
if(outfit_isFighterBay(o) && o->u.bay.ammo_name)
free(o->u.bay.ammo_name);
if(outfit_isFighter(o) && o->u.fig.ship)
free(o->u.fig.ship);

View File

@ -6,6 +6,8 @@
/* Property flags. */
#define OUTFIT_PROP_WEAP_SECONDARY (1<<0) /**< Is a secondary weapon? */
struct Outfit_;
/**
* @enum OutfitType
*
@ -107,7 +109,8 @@ typedef struct OutfitBeamData_ {
*/
typedef struct OutfitLauncherData_ {
unsigned int delay; /**< Delay between shots. */
char* ammo; /**< The ammo to use. */
char* ammo_name; /**< The ammo to use. */
struct Outfit_* ammo; /**< Ammo to use. */
} OutfitLauncherData;
/**
@ -179,8 +182,9 @@ typedef struct OutfitAfterburnerData_ {
* @brief Represents a fighter bay.
*/
typedef struct OutfitFighterBayData_ {
char* ammo; /**< Ships to use as ammo. */
double delay; /**< Delay between launches. */
char* ammo_name; /**< Ships to use as ammo. */
struct Outfit_* ammo; /**< Ships to use as ammo. */
double delay; /**< Delay between launches. */
} OutfitFighterBayData;
/**
@ -282,7 +286,7 @@ int outfit_spfx(const Outfit* o);
double outfit_damage(const Outfit* o);
DamageType outfit_damageType(const Outfit* o);
int outfit_delay(const Outfit* o);
char* outfit_ammo(const Outfit* o);
Outfit* outfit_ammo(const Outfit* o);
double outfit_energy(const Outfit* o);
double outfit_range(const Outfit* o);
double outfit_speed(const Outfit* o);

View File

@ -1,9 +1,17 @@
/**
* @file pause.c
*
* @brief Handles pausing and resuming the game.
*
* Main trick to pausing/unpausing is to allow things based on time
* to behave properly when the toolkit opens a window.
*
* @todo Should probably be eliminated by making everything use the dt system.
*/
#include "pilot.h"
#include "pause.h"
/* Main thing with pausing is to allow things based on time to */
/* work properly when the toolkit opens a window. */
int paused = 0; /* Are we paused. */
/* From pilot.c */

View File

@ -548,7 +548,7 @@ void pilot_setSecondary(Pilot* p, const char* secondary) {
*/
void pilot_setAmmo(Pilot* p) {
int i;
char* name;
Outfit* ammo;
/* Weapon must use ammo. */
if((p->secondary == NULL) || (outfit_ammo(p->secondary->outfit)==NULL)) {
@ -557,9 +557,9 @@ void pilot_setAmmo(Pilot* p) {
}
/* Find the ammo and set it. */
name = outfit_ammo(p->secondary->outfit);
ammo = outfit_ammo(p->secondary->outfit);
for(i = 0; i < p->noutfits; i++)
if(strcmp(p->outfits[i].outfit->name, name)==0) {
if(p->outfits[i].outfit == ammo) {
p->ammo = &p->outfits[i];
return;
}
@ -576,16 +576,16 @@ void pilot_setAmmo(Pilot* p) {
*/
int pilot_getAmmo(Pilot* p, Outfit* o) {
int i;
char* name;
Outfit* ammo;
/* Must be a launcher. */
if(!outfit_isLauncher(o))
return 0;
/* Try to find the ammo. */
name = o->u.lau.ammo;
ammo = o->u.lau.ammo;
for(i = 0; i < p->noutfits; i++)
if(strcmp(p->outfits[i].outfit->name, name)==0)
if(p->outfits[i].outfit == ammo)
return p->outfits[i].quantity;
/* Assume none. */
@ -632,7 +632,7 @@ int pilot_dock(Pilot* p, Pilot* target) {
/* Check to see if target has an available bay. */
for(i = 0; i < target->noutfits; i++) {
if(outfit_isFighterBay(target->outfits[i].outfit)) {
o = outfit_get(outfit_ammo(target->outfits[i].outfit));
o = outfit_ammo(target->outfits[i].outfit);
if(outfit_isFighter(o) &&
(strcmp(p->ship->name, o->u.fig.ship)==0))
break;