diff --git a/src/outfit.c b/src/outfit.c index b089dea..a261e4b 100644 --- a/src/outfit.c +++ b/src/outfit.c @@ -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); diff --git a/src/outfit.h b/src/outfit.h index d9b1267..b6ea718 100644 --- a/src/outfit.h +++ b/src/outfit.h @@ -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); diff --git a/src/pause.c b/src/pause.c index 240fff5..c46020b 100644 --- a/src/pause.c +++ b/src/pause.c @@ -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 */ diff --git a/src/pilot.c b/src/pilot.c index 635af8d..f4806ab 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -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;