#include /* remove() */ #include "lephisto.h" #include "log.h" #include "xml.h" #include "player.h" #include "toolkit.h" #include "dialogue.h" #include "menu.h" #include "lfile.h" #include "hook.h" #include "save.h" #define LOAD_WIDTH 400 #define LOAD_HEIGHT 300 #define BUTTON_WIDTH 50 #define BUTTON_HEIGHT 30 /* Externs. */ extern int player_save(xmlTextWriterPtr writer); /* A lot of stuff. */ extern int player_load(xmlNodePtr parent); extern int missions_saveActive(xmlTextWriterPtr writer); /* Active missions. */ extern int missions_loadActive(xmlNodePtr parent); extern int var_save(xmlTextWriterPtr writer); /* misn var. */ extern int var_load(xmlNodePtr parent); extern int pfaction_save(xmlTextWriterPtr writer); /* Faction data. */ extern int pfaction_load(xmlNodePtr parent); extern int hook_save(xmlTextWriterPtr writer); /* Hooks. */ extern int hook_load(xmlNodePtr parent); extern int space_sysSave(xmlTextWriterPtr writer); /* Space stuff. */ extern int space_sysLoad(xmlNodePtr parent); extern int diff_save(xmlTextWriterPtr writer); extern int diff_load(xmlNodePtr parent); extern void menu_main_close(void); /* Static. */ static int save_data(xmlTextWriterPtr writer); static void load_menu_close(unsigned int wdw, char* str); static void load_menu_load(unsigned int wdw, char* str); static void load_menu_delete(unsigned wdw, char* str); static int load_game(char* file); /* Save all the game data. */ static int save_data(xmlTextWriterPtr writer) { /* The data itself. */ if(diff_save(writer) < 0) return -1; /* Must save first or can get cleared. */ if(player_save(writer) < 0) return -1; if(missions_saveActive(writer) < 0) return -1; if(var_save(writer) < 0) return -1; if(pfaction_save(writer) < 0) return -1; if(hook_save(writer) < 0) return -1; if(space_sysSave(writer) < 0) return -1; return 0; } /* Save the current game. */ int save_all(void) { char file[PATH_MAX]; xmlDocPtr doc; xmlTextWriterPtr writer; writer = xmlNewTextWriterDoc(&doc, 0); if(writer == NULL) { ERR("testXmlwriterDoc: Error creating the xml writer."); return -1; } xmlw_start(writer); xmlw_startElem(writer, "lephisto_save"); /* Save the version or something.. */ xmlw_startElem(writer, "version"); xmlw_elem(writer, "lephisto", "%d.%d.%d", VMAJOR, VMINOR, VREV); xmlw_elem(writer, "data", dataname); xmlw_endElem(writer); /* Version. */ if(save_data(writer) < 0) { ERR("Trying to save game data"); xmlFreeTextWriter(writer); xmlFreeDoc(doc); return -1; } xmlw_endElem(writer); /* lephisto_save. */ xmlw_done(writer); if(lfile_dirMakeExist("%ssaves", lfile_basePath()) < 0) { WARN("Aborting save..."); xmlFreeTextWriter(writer); xmlFreeDoc(doc); return -1; } snprintf(file, PATH_MAX, "%ssaves/%s.ls", lfile_basePath(), player_name); /* Critical section, if crashes, the players save game gets screwed!!! * HAHAHAHAHA!!!!! -- NOT! */ xmlFreeTextWriter(writer); xmlSaveFileEnc(file, doc, "UTF-8"); xmlFreeDoc(doc); return 0; } /* Open the load game menu. */ void load_game_menu(void) { unsigned int wid; char** files; int lfiles, i, len; /* Window. */ wid = window_create("Load Game", -1, -1, LOAD_WIDTH, LOAD_HEIGHT); /* Load the saves. */ files = lfile_readDir(&lfiles, "%ssaves", lfile_basePath()); for(i = 0; i < lfiles; i++) { len = strlen(files[i]); /* No save extension. */ if((len < 6) || strcmp(&files[i][len-3], ".ls")) { free(files[i]); memmove(&files[i], &files[i+1], sizeof(char*) * (lfiles-i-1)); lfiles--; i--; } else /* Remove the extension. */ files[i][len-3] = '\0'; } /* Again.. What if there is no files? */ if(files == NULL) { files = malloc(sizeof(char*)); files[0] = strdup("None"); lfiles = 1; } window_addList(wid, 20, -50, LOAD_WIDTH-BUTTON_WIDTH-50, LOAD_HEIGHT-90, "lstSaves", files, lfiles, 0, NULL); /* Buttons. */ window_addButton(wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnBack", "Back", load_menu_close); window_addButton(wid, -20, 30 + BUTTON_HEIGHT, BUTTON_WIDTH, BUTTON_HEIGHT, "btnLoad", "Load", load_menu_load); window_addButton(wid, -20, 20+2*(10+BUTTON_HEIGHT), BUTTON_WIDTH, BUTTON_HEIGHT, "btnDelete", "Del", load_menu_delete); /* Default action. */ window_setAccept(wid, load_menu_load); } static void load_menu_close(unsigned int wdw, char* str) { (void)str; window_destroy(wdw); } static void load_menu_load(unsigned int wdw, char* str) { (void)str; char* save, path[PATH_MAX]; int wid; wid = window_get("Load Game"); save = toolkit_getList(wid, "lstSaves"); if(strcmp(save, "None")==0) return; snprintf(path, PATH_MAX, "%ssaves/%s.ls", lfile_basePath(), save); /* Close menus before loading for proper rendering. */ load_menu_close(wdw, NULL); menu_main_close(); load_game(path); } static void load_menu_delete(unsigned int wdw, char* str) { (void)str; char* save, path[PATH_MAX]; int wid; wid = window_get("Load Game"); save = toolkit_getList(wid, "lstSaves"); if(strcmp(save, "None") == 0) return; if(dialogue_YesNo("Permanently Delete?", "Are you sure you want to permanently delete '%s'?", save) == 0) return; snprintf(path, PATH_MAX, "%ssaves/%s.ls", lfile_basePath(), save); remove(path); /* Remove is more portable and will call unlink on Linux. */ /* Need to reload the menu. */ load_menu_close(wdw, NULL); load_game_menu(); } /* Load a new game. */ static int load_game(char* file) { xmlNodePtr node; xmlDocPtr doc; doc = xmlParseFile(file); node = doc->xmlChildrenNode; /* Base node. */ if(node == NULL) { WARN("Savegame '%s' invalid!", file); return -1; } diff_load(node); /* Must load first to work properly. */ player_load(node); var_load(node); missions_loadActive(node); pfaction_load(node); hook_load(node); space_sysLoad(node); /* Need to run takeoff hooks since player just "took off". */ hooks_run("takeoff"); hooks_run("enter"); xmlFreeDoc(doc); xmlCleanupParser(); return 0; }