[Change] Modulised fleet stuff.

This commit is contained in:
Allanis 2014-10-18 22:26:05 +01:00
parent 65e54c12fe
commit 1d53467491
8 changed files with 260 additions and 200 deletions

207
src/fleet.c Normal file
View File

@ -0,0 +1,207 @@
/**
* @file pilot.c
*
* @brief Handles the pilot stuff.
*/
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
#include "lxml.h"
#include "lephisto.h"
#include "log.h"
#include "weapon.h"
#include "ldata.h"
#include "spfx.h"
#include "rng.h"
#include "hook.h"
#include "map.h"
#include "explosion.h"
#include "escort.h"
#include "music.h"
#include "pilot.h"
#define XML_ID "Fleets" /**< XML document identifier. */
#define XML_FLEET "fleet" /**< XML individual fleet identifier. */
#define FLEET_DATA "../dat/fleet.xml" /**< Where to find fleet data. */
#define CHUNK_SIZE 32 /**< Size to allocate memory by. */
/* Stack of fleets. */
static Fleet* fleet_stack = NULL; /**< Fleet stack. */
static int nfleets = 0; /**< Number of fleets. */
/**
* @brief Grabs a fleet out of the stack.
* @param name Name of the fleet to match.
* @return The fleet mactching name or NULL if not found.
*/
Fleet* fleet_get(const char* name) {
int i;
for(i = 0; i < nfleets; i++)
if(strcmp(fleet_stack[i].name, name)==0)
return &fleet_stack[i];
WARN("Fleet '%s' not found in stack", name);
return NULL;
}
/**
* @brief Parses the fleet node.
* @param tmp Fleet to load.
* @param parent Parent xml node of the fleet in question.
* @return A newly allocated fleet loaded with data in parent node.
*/
static int fleet_parse(Fleet* tmp, const xmlNodePtr parent) {
xmlNodePtr cur, node;
FleetPilot* pilot;
char* c;
int mem;
node = parent->xmlChildrenNode;
/* Sane defaults and clean up. */
memset(tmp, 0, sizeof(Fleet));
tmp->faction = -1;
tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name"); /* Already mallocs. */
if(tmp->name == NULL) WARN("Fleet in "FLEET_DATA" has invalid or no name");
do { /* Load all the data. */
if(xml_isNode(node, "faction"))
tmp->faction = faction_get(xml_get(node));
else if(xml_isNode(node, "ai"))
tmp->ai = xml_getStrd(node);
else if(xml_isNode(node, "pilots")) {
cur = node->children;
mem = 0;
do {
if(xml_isNode(cur, "pilot")) {
/* See if must grow. */
tmp->npilots++;
if(tmp->npilots > mem) {
mem += CHUNK_SIZE;
tmp->pilots = realloc(tmp->pilots, mem * sizeof(FleetPilot));
}
pilot = &tmp->pilots[tmp->npilots-1];
/* Clear memory. */
memset(pilot, 0, sizeof(FleetPilot));
/* Check for name override. */
xmlr_attr(cur, "name", c);
pilot->name = c; /* No need to free since it will have later. */
/* Check for ai override. */
xmlr_attr(cur, "ai", pilot->ai);
/* Load pilots ship. */
pilot->ship = ship_get(xml_get(cur));
if(pilot->ship == NULL)
WARN("Pilot %s in Fleet %s has null ship", pilot->name, tmp->name);
/* Load chance. */
xmlr_attr(cur, "chance", c);
pilot->chance = atoi(c);
if(pilot->chance == 0)
WARN("Pilot %s in Fleet %s has 0%% chance of appearing",
pilot->name, tmp->name);
if(c != NULL)
free(c); /* Free the external malloc. */
}
} while(xml_nextNode(cur));
/* Resize to minimum. */
tmp->pilots = realloc(tmp->pilots, sizeof(FleetPilot)*tmp->npilots);
}
} while(xml_nextNode(node));
#define MELEMENT(o,s) \
if(o) WARN("Fleet '%s' missing '"s"' element", tmp->name)
/**< Hack to check for missing fields. */
MELEMENT(tmp->ai == NULL, "ai");
MELEMENT(tmp->faction == -1, "faction");
MELEMENT(tmp->pilots == NULL, "pilots");
#undef MELEMENT
return 0;
}
/**
* @brief Loads all the fleets.
* @return 0 on success.
*/
int fleet_load(void) {
int mem;
uint32_t bufsize;
char* buf = ldata_read(FLEET_DATA, &bufsize);
xmlNodePtr node;
xmlDocPtr doc = xmlParseMemory(buf, bufsize);
node = doc->xmlChildrenNode; /* Ships node. */
if(strcmp((char*)node->name, XML_ID)) {
ERR("Malformed "FLEET_DATA" file: missing root element '"XML_ID"'");
return -1;
}
node = node->xmlChildrenNode; /* First ship node. */
if(node == NULL) {
ERR("Malformed "FLEET_DATA" file: does not contain elements");
return -1;
}
mem = 0;
do {
if(xml_isNode(node, XML_FLEET)) {
/* See if memory must grow. */
nfleets++;
if(nfleets > mem) {
mem += CHUNK_SIZE;
fleet_stack = realloc(fleet_stack, sizeof(Fleet) * mem);
}
/* Load the fleet. */
fleet_parse(&fleet_stack[nfleets-1], node);
}
} while(xml_nextNode(node));
/* Shrink to minimum. */
fleet_stack = realloc(fleet_stack, sizeof(Fleet) * nfleets);
xmlFreeDoc(doc);
free(buf);
DEBUG("Loaded %d Fleets%s", nfleets, (nfleets == 1) ? "" : "s");
return 0;
}
/**
* @brief Cleans up by freeing all the fleet data.
*/
void fleet_free(void) {
int i,j;
if(fleet_stack != NULL) {
for(i = 0; i < nfleets; i++) {
for(j = 0; j < fleet_stack[i].npilots; j++) {
if(fleet_stack[i].pilots[j].name)
free(fleet_stack[i].pilots[j].name);
if(fleet_stack[i].pilots[j].ai)
free(fleet_stack[i].pilots[j].ai);
}
free(fleet_stack[i].name);
free(fleet_stack[i].pilots);
free(fleet_stack[i].ai);
}
free(fleet_stack);
fleet_stack = NULL;
}
nfleets = 0;
}

49
src/fleet.h Normal file
View File

@ -0,0 +1,49 @@
#pragma once
#include "pilot.h"
/**
* @struct FleetPilot
*
* @brief Represents a pilot in a fleet.
*
* @sa Fleet
* @sa Pilot
*/
typedef struct FleetPilot_ {
Ship* ship; /**< Ship the pilot is flying. */
char* name; /**< Used if they have a special name like uniques. */
int chance; /**< Chance of this pilot appearing in the fleet. */
char* ai; /**< ai different of fleets global ai. */
} FleetPilot;
/**
* @struct Fleet
*
* @brief Represenets a fleet.
*
* Fleets are used to create pilots, both from being in a system and from
* mission triggers.
*
* @sa FleetPilot
*/
typedef struct Fleet_ {
char* name; /**< Fleet name, used as the identifier. */
int faction; /**< Faction of the fleet. */
char* ai; /**< faction of the fleet. */
FleetPilot* pilots; /**< The pilots in the fleet. */
int npilots; /**< Total number of pilots. */
} Fleet;
/*
* Get fleet stuff.
*/
Fleet* fleet_get(const char* name);
/*
* Load / cleanup.
*/
int fleet_load(void);
void fleet_free(void);

View File

@ -31,6 +31,7 @@
#include "font.h"
#include "ship.h"
#include "pilot.h"
#include "fleet.h"
#include "player.h"
#include "input.h"
#include "joystick.h"

View File

@ -23,11 +23,6 @@
#include "music.h"
#include "pilot.h"
#define XML_ID "Fleets" /**< XML document identifier. */
#define XML_FLEET "fleet" /**< XML individual fleet identifier. */
#define FLEET_DATA "../dat/fleet.xml" /**< Where to find fleet data. */
#define PILOT_CHUNK 32 /**< Chunks to increment pilot_stack by. */
#define CHUNK_SIZE 32 /**< Size to allocate memory by. */
@ -48,10 +43,6 @@ extern double player_crating; /**< Players combat rating. */
extern void player_abortAutonav(char* reason);
extern int player_enemies;
/* Stack of fleets. */
static Fleet* fleet_stack = NULL; /** Fleet stack. */
static int nfleets = 0; /** Number of fleets. */
/* External. */
/* AI. */
extern AI_Profile* ai_pinit(Pilot* p, char* ai);
@ -73,7 +64,6 @@ static void pilot_hyperspace(Pilot* pilot);
void pilot_render(Pilot* pilot);
static void pilot_calcCargo(Pilot* pilot);
void pilot_free(Pilot* p); /* Externed in player.c */
static int fleet_parse(Fleet* tmp, const xmlNodePtr parent);
static void pilot_dead(Pilot* p);
static int pilot_setOutfitMounts(Pilot* p, PilotOutfit* po, int o, int q);
static void pilot_setSecondary(Pilot* p, Outfit* o);
@ -190,17 +180,6 @@ Pilot* pilot_get(const unsigned int id) {
return pilot_stack[m];
}
/* Grab a fleet out of the stack. */
Fleet* fleet_get(const char* name) {
int i;
for(i = 0; i < nfleets; i++)
if(strcmp(fleet_stack[i].name, name)==0)
return &fleet_stack[i];
WARN("Fleet '%s' not found in stack", name);
return NULL;
}
/**
* @brief Check to see if pilot is hostile to the player.
* @param p Player to see if is hostile.
@ -1987,144 +1966,3 @@ void pilots_render(void) {
}
}
/* Parse the fleet node. */
static int fleet_parse(Fleet* tmp, const xmlNodePtr parent) {
xmlNodePtr cur, node;
FleetPilot* pilot;
char* c;
int mem;
node = parent->xmlChildrenNode;
/* Sane defaults and clean up. */
memset(tmp, 0, sizeof(Fleet));
tmp->faction = -1;
tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name"); /* Already mallocs. */
if(tmp->name == NULL) WARN("Fleet in "FLEET_DATA" has invalid or no name");
do {
/* Load all the data. */
if(xml_isNode(node, "faction"))
tmp->faction = faction_get(xml_get(node));
else if(xml_isNode(node, "ai"))
tmp->ai = xml_getStrd(node);
else if(xml_isNode(node, "pilots")) {
cur = node->children;
mem = 0;
do {
if(xml_isNode(cur, "pilot")) {
/* See if we must grow. */
tmp->npilots++;
if(tmp->npilots > mem) {
mem += CHUNK_SIZE;
tmp->pilots = realloc(tmp->pilots, mem * sizeof(FleetPilot));
}
pilot = &tmp->pilots[tmp->npilots-1];
/* Clear memory. */
memset(pilot, 0, sizeof(FleetPilot));
/* Check for name override. */
xmlr_attr(cur, "name", c);
pilot->name = c; /* No need to free since it will have to later. */
/* Check for ai override. */
xmlr_attr(cur, "ai", pilot->ai);
/* Load pilots ship. */
pilot->ship = ship_get(xml_get(cur));
if(pilot->ship == NULL)
WARN("Pilot %s in Fleet %s has null ship", pilot->name, tmp->name);
/* Load chance. */
xmlr_attr(cur, "chance", c);
pilot->chance = atoi(c);
if(pilot->chance == 0)
WARN("Pilot %s in Fleet %s has 0%% chance of appearing",
pilot->name, tmp->name);
if(c != NULL)
free(c); /* Free the external malloc. */
}
} while(xml_nextNode(cur));
/* Resize to minimum. */
tmp->pilots = realloc(tmp->pilots, sizeof(FleetPilot)*tmp->npilots);
}
} while(xml_nextNode(node));
#define MELEMENT(o,s) if(o) WARN("Fleet '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->ai==NULL, "ai");
MELEMENT(tmp->faction==-1, "faction");
MELEMENT(tmp->pilots==NULL, "pilots");
#undef MELEMENT
return 0;
}
/* Load the fleets. */
int fleet_load(void) {
int mem;
uint32_t bufsize;
char* buf = ldata_read(FLEET_DATA, &bufsize);
xmlNodePtr node;
xmlDocPtr doc = xmlParseMemory(buf, bufsize);
node = doc->xmlChildrenNode; /* Ships node. */
if(strcmp((char*)node->name, XML_ID)) {
ERR("Malformed "FLEET_DATA" file: missing root element '"XML_ID"'");
return -1;
}
node = node->xmlChildrenNode; /* First ship node. */
if(node == NULL) {
ERR("Malformed "FLEET_DATA" file: does not contain elements");
return -1;
}
mem = 0;
do {
if(xml_isNode(node, XML_FLEET)) {
/* See if memory must grow. */
nfleets++;
if(nfleets > mem) {
mem += CHUNK_SIZE;
fleet_stack = realloc(fleet_stack, sizeof(Fleet)*mem);
}
/* Load the fleet. */
fleet_parse(&fleet_stack[nfleets-1], node);
}
} while(xml_nextNode(node));
/* Shrink to minimum. */
fleet_stack = realloc(fleet_stack, sizeof(Fleet)*nfleets);
xmlFreeDoc(doc);
free(buf);
DEBUG("Loaded %d fleet%s", nfleets, (nfleets==1) ? "" : "s");
return 0;
}
/* Free the fleets. */
void fleet_free(void) {
int i, j;
if(fleet_stack != NULL) {
for(i = 0; i < nfleets; i++) {
for(j = 0; j < fleet_stack[i].npilots; j++) {
if(fleet_stack[i].pilots[j].name)
free(fleet_stack[i].pilots[j].name);
if(fleet_stack[i].pilots[j].ai)
free(fleet_stack[i].pilots[j].ai);
}
free(fleet_stack[i].name);
free(fleet_stack[i].pilots);
free(fleet_stack[i].ai);
}
free(fleet_stack);
fleet_stack = NULL;
}
nfleets = 0;
}

View File

@ -195,41 +195,6 @@ typedef struct Pilot_ {
Task* task; /**< Current action. */
} Pilot;
/**
* @struct FleetPilot
*
* @brief Represents a pilot in a fleet.
*
* @sa Fleet
* @sa Pilot
*/
typedef struct FleetPilot_ {
Ship* ship; /**< Ship that the pilot is flying. */
char* name; /**< For special 'unique' names. */
int chance; /**< Chance of this pilot appearing in the fleet. */
char* ai; /**< Ai difference of fleet's global ai. */
} FleetPilot;
/**
* @struct Fleet
*
* @brief Represents a fleet.
*
* Fleets are used to create pilots, both from being in a system and from
* mission triggers.
*
* @sa FleetPilot
*/
typedef struct Fleet_ {
char* name; /**< Fleet name, used as an identifier. */
int faction; /**< Faction of the fleet. */
char* ai; /**< AI profile to use. */
FleetPilot* pilots; /**< The pilots in the fleet. */
int npilots; /**< Total number of pilots. */
} Fleet;
/* Grabing pilot crap. */
extern Pilot* player; /* The player. */
Pilot* pilot_get(unsigned int id);
@ -238,7 +203,6 @@ unsigned int pilot_getPrevID(const unsigned int id);
unsigned int pilot_getNearestEnemy(const Pilot* p);
unsigned int pilot_getNearestHostile(void); /* Only for the player. */
unsigned int pilot_getNearestPilot(const Pilot* p);
Fleet* fleet_get(const char* name);
int pilot_getJumps(const Pilot* p);
/* Misc. */
@ -297,8 +261,6 @@ void pilots_free(void);
void pilots_clean(void);
void pilots_cleanAll(void);
void pilot_free(Pilot* p);
int fleet_load(void);
void fleet_free(void);
void pilot_setHostile(Pilot* p);
void pilot_rmHostile(Pilot* p);

View File

@ -17,6 +17,7 @@
#include "nebulae.h"
#include "music.h"
#include "gui.h"
#include "fleet.h"
#include "space.h"
#define XML_PLANET_ID "Planets"

View File

@ -3,6 +3,7 @@
#include "opengl.h"
#include "economy.h"
#include "pilot.h"
#include "fleet.h"
#define MAX_HYPERSPACE_VEL 25 /**< Speed to brake to before jumping. */

View File

@ -16,6 +16,7 @@
#include "lxml.h"
#include "space.h"
#include "ldata.h"
#include "fleet.h"
#include "unidiff.h"
#define CHUNK_SIZE 32 /**< Size of chunk to allocate. */