diff --git a/.gitignore b/.gitignore index bb87919..7f9f795 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ *bin/Lephisto *bin/mksprite *bin/data +*bin/test.xml *pack *core screenshots/*.png diff --git a/src/menu.c b/src/menu.c index b441341..152a336 100644 --- a/src/menu.c +++ b/src/menu.c @@ -11,6 +11,7 @@ #include "plasmaf.h" #include "mission.h" #include "ltime.h" +#include "save.h" #include "menu.h" #define MAIN_WIDTH 130 @@ -41,6 +42,7 @@ int menu_open = 0; // Main menu. static void menu_main_close(void); +static void menu_main_load(char* str); static void menu_main_new(char* str); // Small menu. static void menu_small_close(char* str); @@ -76,7 +78,7 @@ void menu_main(void) { wid = window_create("Main Menu", -1, -1, MAIN_WIDTH, MAIN_HEIGHT); window_addButton(wid, 20, 20 + (BUTTON_HEIGHT+20)*3, BUTTON_WIDTH, BUTTON_HEIGHT, - "btnLoad", "Load Game", NULL); + "btnLoad", "Load Game", menu_main_load); window_addButton(wid, 20, 20 + (BUTTON_HEIGHT+20)*2, BUTTON_WIDTH, BUTTON_HEIGHT, "btnNew", "New Game", menu_main_new); @@ -98,6 +100,13 @@ static void menu_main_close(void) { menu_Close(MENU_MAIN); } +static void menu_main_load(char* str) { + (void)str; + + menu_main_close(); + load_game("text.xml"); +} + static void menu_main_new(char* str) { (void)str; diff --git a/src/pilot.c b/src/pilot.c index 4fe3217..f1a14f9 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -746,6 +746,8 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, int faction, AI_Profile* ai, const double dir, const Vec2* pos, const Vec2* vel, const int flags) { + ShipOutfit* so; + if(flags & PILOT_PLAYER) // Player is ID 0 pilot->id = PLAYER_ID; else @@ -773,17 +775,19 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, int faction, pilot->secondary = NULL; pilot->ammo = NULL; pilot->afterburner = NULL; - ShipOutfit* so; - if(ship->outfit) { - pilot->noutfits = 0; - for(so = ship->outfit; so; so = so->next) { - pilot->outfits = realloc(pilot->outfits, (pilot->noutfits+1)*sizeof(PilotOutfit)); - pilot->outfits[pilot->noutfits].outfit = so->data; - pilot->outfits[pilot->noutfits].quantity = so->quantity; - pilot->outfits[pilot->noutfits].timer = 0; - (pilot->noutfits)++; - if(outfit_isTurret(so->data)) // Used to speed up AI a bit. - pilot_setFlag(pilot, PILOT_HASTURRET); + pilot->noutfits = 0; + if(!(flags & PILOT_NO_OUTFITS)) { + if(ship->outfit) { + pilot->noutfits = 0; + for(so = ship->outfit; so; so = so->next) { + pilot->outfits = realloc(pilot->outfits, (pilot->noutfits+1)*sizeof(PilotOutfit)); + pilot->outfits[pilot->noutfits].outfit = so->data; + pilot->outfits[pilot->noutfits].quantity = so->quantity; + pilot->outfits[pilot->noutfits].timer = 0; + (pilot->noutfits)++; + if(outfit_isTurret(so->data)) // Used to speed up AI a bit. + pilot_setFlag(pilot, PILOT_HASTURRET); + } } } @@ -809,8 +813,11 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, int faction, pilot->think = player_think; // Players don't need to thing! :P pilot->render = NULL; // Render will be called from player_think pilot_setFlag(pilot, PILOT_PLAYER); // It's a player! - player = pilot; - gui_load(pilot->ship->gui); // Load the GUI. + // Bit of a hack. + if(!(flags & PILOT_EMPTY)) { + player = pilot; + gui_load(pilot->ship->gui); // Load the GUI. + } } else { pilot->think = ai_think; pilot->render = pilot_render; @@ -861,6 +868,15 @@ unsigned int pilot_create(Ship* ship, char* name, int faction, return dyn->id; } +Pilot* pilot_createEmpty(Ship* ship, char* name, + int faction, AI_Profile* ai, const int flags) { + + Pilot* dyn; + dyn = MALLOC_L(Pilot*); + pilot_init(dyn, ship, name, faction, ai, 0., NULL, NULL, flags | PILOT_EMPTY); + return dyn; +} + // Copy src pilot to dest. Pilot* pilot_copy(Pilot* src) { Pilot* dest = malloc(sizeof(Pilot)); diff --git a/src/pilot.h b/src/pilot.h index 05f6276..aa89d93 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -30,7 +30,9 @@ #define pilot_rmFlag(p,f) (p->flags ^= (f)) // Creation. #define PILOT_PLAYER (1<<0) // Pilot is a player. -#define PILOT_HASTURRET (1<<20) // Pilit has turrets. +#define PILOT_HASTURRET (1<<20) // Pilot has turrets. +#define PILOT_NO_OUTFITS (1<<21) // Do not create the pilot with outfits. +#define PILOT_EMPTY (1<<22) // Do not add pilot to stack. // Dynamic. #define PILOT_HOSTILE (1<<1) // Pilot is hostile to the player. #define PILOT_COMBAT (1<<2) // Pilot is engaged in combat. @@ -168,6 +170,9 @@ unsigned int pilot_create(Ship* ship, char* name, int faction, AI_Profile* ai, const double dir, const Vec2* pos, const Vec2* vel, const int flags); +Pilot* pilot_createEmpty(Ship* ship, char* name, + int faction, AI_Profile* ai, const int flags); + Pilot* pilot_copy(Pilot* src); // Init/Cleanup. diff --git a/src/player.c b/src/player.c index c40d1a7..3e661cf 100644 --- a/src/player.c +++ b/src/player.c @@ -139,6 +139,9 @@ 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 int player_saveShip(xmlTextWriterPtr writer, Pilot* ship, char* loc); +static int player_parse(xmlNodePtr parent); +static int player_parseDone(xmlNodePtr parent); +static int player_parseShip(xmlNodePtr parent, int is_player); // Externed. void player_dead(void); void player_destroyed(void); @@ -146,20 +149,16 @@ int player_save(xmlTextWriterPtr writer); // Prompt player name. void player_new(void) { - int i; // Let's not seg fault due to a lack of environment. player_setFlag(PLAYER_DESTROYED); vectnull(&player_cam); gl_bindCamera(&player_cam); - for(i = 0; i < msg_max; i++) - memset(msg_stack[i].str, '\0', MSG_SIZE_MAX); - // Cleanup player stuff if we'll be re-creating. player_cleanup(); - // Cleanup stacks. var_cleanup(); + missions_cleanup(); player_name = dialogue_input("Player Name", 3, 20, "Please tell me your name:"); @@ -323,6 +322,10 @@ void player_cleanup(void) { // Cleanup name. if(player_name) free(player_name); + // Cleanup messages. + for(i = 0; i < msg_max; i++) + memset(msg_stack[i].str, '\0', MSG_SIZE_MAX); + // Clean up the stack. if(player_stack) { for(i = 0; i < player_nstack; i++) { @@ -1441,7 +1444,9 @@ int player_save(xmlTextWriterPtr writer) { xmlw_elem(writer, "rating", "%d", player_crating); xmlw_elem(writer, "scred", "%d", player->credits); + xmlw_elem(writer, "time", "%d", ltime_get()); + xmlw_elem(writer, "location", land_planet->name); player_saveShip(writer, player, NULL); // Current ship. xmlw_startElem(writer, "ships"); @@ -1465,8 +1470,8 @@ static int player_saveShip(xmlTextWriterPtr writer, Pilot* ship, char* loc) { xmlw_startElem(writer, "ship"); xmlw_attr(writer, "name", ship->name); + xmlw_attr(writer, "model", ship->ship->name); - xmlw_elem(writer, "shipname", ship->ship->name); if(loc != NULL) xmlw_elem(writer, "location", loc); // Save the outfits. @@ -1499,3 +1504,155 @@ static int player_saveShip(xmlTextWriterPtr writer, Pilot* ship, char* loc) { return 0; } +int player_load(xmlNodePtr parent) { + xmlNodePtr node; + + // Some cleanup. + player_cleanup(); + var_cleanup(); + missions_cleanup(); + + node = parent->xmlChildrenNode; + + do { + if(xml_isNode(node, "player")) + player_parse(node); + else if(xml_isNode(node, "missions_done")) + player_parseDone(node); + } while(xml_nextNode(node)); + + return 0; +} + +static int player_parse(xmlNodePtr parent) { + unsigned int player_time; + char* planet; + Planet* pnt; + int sw, sh; + xmlNodePtr node, cur; + + node = parent->xmlChildrenNode; + + xmlr_attr(parent, "name", player_name); + + do { + // Global stuff. + xmlr_int(node, "rating", player_crating); + xmlr_int(node, "credits", player_credits); + xmlr_long(node, "time", player_time); + xmlr_str(node, "location", planet); + + if(xml_isNode(node, "ship")) + player_parseShip(node, 1); + + if(xml_isNode(node, "ships")) { + cur = node->xmlChildrenNode; + do { + if(xml_isNode(cur, "ship")) + player_parseShip(cur, 0); + } while(xml_nextNode(cur)); + } + } while(xml_nextNode(node)); + + // Set global thingies. + player->credits = player_credits; + ltime_set(player_time); + + // Set player in system. + pnt = planet_get(planet); + sw = pnt->gfx_space->sw; + sh = pnt->gfx_space->sh; + player_warp(pnt->pos.x + RNG(-sw/2, sw/2), + pnt->pos.y + RNG(-sh/2, sh/2)); + player->solid->dir = RNG(0, 359) * M_PI/180.; + gl_bindCamera(&player->solid->pos); + + // Initialize the system. + space_init(planet_getSystem(planet)); + + return 0; +} + +static int player_parseDone(xmlNodePtr parent) { + xmlNodePtr node; + + node = parent->xmlChildrenNode; + + do { + + } while(xml_nextNode(node)); + + return 0; +} + +static int player_parseShip(xmlNodePtr parent, int is_player) { + char* name, *model, *loc, *q, *id; + int i, n; + Pilot* ship; + xmlNodePtr node, cur; + + xmlr_attr(parent, "name", name); + xmlr_attr(parent, "model", model); + + // Player is currently on this ship. + if(is_player) { + pilot_create(ship_get(model), name, faction_get("Player"), NULL, 0., NULL, + NULL, PILOT_PLAYER | PILOT_NO_OUTFITS); + ship = player; + } else + ship = pilot_createEmpty(ship_get(model), name, faction_get("Player"), NULL, + PILOT_PLAYER | PILOT_NO_OUTFITS); + + free(name); + free(model); + + node = parent->xmlChildrenNode; + + do { + if(!is_player) xmlr_str(node, "location", loc); + + if(xml_isNode(node, "outfits")) { + cur = node->xmlChildrenNode; + do { + // Load each outfit. + if(xml_isNode(cur, "outfits")) { + xmlr_attr(cur, "quantity", q); + n = atoi(q); + free(q); + // Add the outfit. + pilot_addOutfit(ship, outfit_get(xml_get(cur)), n); + } + } while(xml_nextNode(cur)); + } + if(xml_isNode(node, "commodities")) { + cur = node->xmlChildrenNode; + do { + if(xml_isNode(cur, "commodity")) { + xmlr_attr(cur, "quantity", q); + xmlr_attr(cur, "id", id); + n = atoi(q); + if(id == NULL) i = 0; + else i = atoi(id); + free(q); + if(id != NULL) free(id); + + // Actually add the cargo with id hack. + pilot_addCargo(ship, commodity_get(xml_get(cur)), n); + if(i != 0) ship->commodities[ship->ncommodities-1].id = i; + } + } while(xml_nextNode(node)); + } + } while(xml_nextNode(node)); + + // Add it to the stack if it's not what the player is in. + if(!is_player) { + player_stack = realloc(player_stack, sizeof(Pilot*)*(player_nstack+1)); + player_stack[player_nstack] = pilot_copy(player); + player_lstack = realloc(player_lstack, sizeof(char*)*(player_nstack+1)); + player_lstack[player_nstack] = strdup(loc); + player_nstack++; + } + + return 0; +} + diff --git a/src/save.c b/src/save.c index 93ac4de..fb75cbc 100644 --- a/src/save.c +++ b/src/save.c @@ -7,6 +7,7 @@ extern int player_save(xmlTextWriterPtr writer); extern int missions_save(xmlTextWriterPtr writer); extern int var_save(xmlTextWriterPtr writer); // misn var. +extern int player_load(xmlNodePtr parent); // Static. static int save_data(xmlTextWriterPtr writer); @@ -19,6 +20,7 @@ static int save_data(xmlTextWriterPtr writer) { return 0; } +// Save the current game. int save_all(void) { char* file; xmlDocPtr doc; @@ -46,7 +48,22 @@ int save_all(void) { file = "test.xml"; xmlFreeTextWriter(writer); - //xmlSaveFileEnc(file, doc, "UTF-8"); + xmlSaveFileEnc(file, doc, "UTF-8"); + xmlFreeDoc(doc); + + return 0; +} + +// Load a new game. +int load_game(char* file) { + xmlNodePtr node; + xmlDocPtr doc; + + doc = xmlParseFile(file); + node = doc->xmlChildrenNode; // Base node. + + player_load(node); + xmlFreeDoc(doc); return 0; diff --git a/src/save.h b/src/save.h index 5a4d80d..c35a0af 100644 --- a/src/save.h +++ b/src/save.h @@ -1,4 +1,5 @@ #pragma once int save_all(void); +int load_game(char* file); diff --git a/src/space.c b/src/space.c index 3b6df35..5fa3ba3 100644 --- a/src/space.c +++ b/src/space.c @@ -70,7 +70,7 @@ static int mstars = 0; // Memory stars are taking. // Intern. static StarSystem* system_get(const char* sysname); -static Planet* planet_get(const char* name); +static Planet* planet_pull(const char* name); static void space_addFleet(Fleet* fleet); static StarSystem* system_parse(const xmlNodePtr parent); static void system_parseJumps(const xmlNodePtr parent); @@ -478,6 +478,22 @@ char* planet_getSystem(char* planetname) { return NULL; } +// Get a planet based on it's name. +Planet* planet_get(char* planetname) { + int i; + char* sys; + StarSystem* system; + + sys = planet_getSystem(planetname); + system = system_get(sys); + + for(i = 0; i < system->nplanets; i++) + if(strcmp(planetname, system->planets[i].name)==0) + return &system->planets[i]; + DEBUG("Planet '%s' not found in the universe", planetname); + return NULL; +} + // Basically used for spawning fleets. void space_update(const double dt) { unsigned int t; @@ -583,7 +599,7 @@ void space_init(const char* sysname) { } // Load the planets of name 'name'. -static Planet* planet_get(const char* name) { +static Planet* planet_pull(const char* name) { int i; Planet* tmp = NULL; @@ -792,8 +808,7 @@ static StarSystem* system_parse(const xmlNodePtr parent) { if(xml_isNode(cur, "planet")) { // Add planet to system. nplanets++; // Increase planet counter. - planet = planet_get(xml_get(cur)); - planet = planet_get((const char*)cur->children->content); + planet = planet_pull(xml_get(cur)); tmp->planets = realloc(tmp->planets, sizeof(Planet)*(++tmp->nplanets)); memcpy(tmp->planets+(tmp->nplanets-1), planet, sizeof(Planet)); diff --git a/src/space.h b/src/space.h index 7460e26..8e119a0 100644 --- a/src/space.h +++ b/src/space.h @@ -100,6 +100,7 @@ void space_exit(void); // Planet stuff. char* planet_getSystem(char* planetname); +Planet* planet_get(char* planetname); // Render. void space_render(double dt); diff --git a/src/xml.h b/src/xml.h index dda3e05..d33a78d 100644 --- a/src/xml.h +++ b/src/xml.h @@ -19,15 +19,23 @@ // Get the property s of node n. This mallocs. #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)) // Reader crap. #define xmlr_int(n,s,i) \ - if(xml_isNode(n,s)) { i = xml_getInt(n); continue; } + if(xml_isNode(n,s)) { i = xml_getInt(n); continue; } +#define xmlr_long(n,s,l) \ + if(xml_isNode(n,s)) { l = xml_getLong(n); continue; } #define xmlr_float(n,s,f) \ - if(xml_isNode(n,s)) { f = xml_getFloat(n); continue; } + if(xml_isNode(n,s)) { f = xml_getFloat(n); continue; } +#define xmlr_str(n,s,str) \ + if(xml_isNode(n,s)) { str = xml_get(n); continue; } +#define xmlr_attr(n,s,a) \ + a = xml_nodeProp(n,s) // Writer crap.