20#include "difficulty.h"
39#include "threadpool.h"
47#define LOAD_HEIGHT 530
49#define BUTTON_WIDTH 120
50#define BUTTON_HEIGHT 30
52typedef struct player_saves_s {
60static int old_saves_detected = 0, player_warned = 0;
61static char *selected_player = NULL;
76extern int var_load( xmlNodePtr parent );
90static void load_menu_delete(
unsigned int wdw,
const char *str );
94static void load_snapshot_menu_onClose(
unsigned int wid,
const char *str );
99static void move_old_save(
const char *path,
const char *fname,
const char *ext,
100 const char *new_name );
105static int load_enumerateCallbackPlayer(
void *data,
const char *origdir,
107static int load_compatibilityTest(
const nsave_t *ns );
108static const char *load_compatibilityString(
const nsave_t *ns );
113static int load_sortCompareName(
const void *p1,
const void *p2 );
116static void load_freeSave(
nsave_t *ns );
126 xmlNodePtr root, parent;
131 WARN( _(
"Unable to parse save path '%s'." ), save->
path );
134 root = doc->xmlChildrenNode;
135 if ( root == NULL ) {
136 WARN( _(
"Unable to get child node of save '%s'." ), save->
path );
142 parent = root->xmlChildrenNode;
144 xml_onlyNodes( parent );
147 if ( xml_isNode( parent,
"version" ) ) {
148 xmlNodePtr node = parent->xmlChildrenNode;
150 xmlr_strd( node,
"naev", save->
version );
151 xmlr_strd( node,
"data", save->
data );
152 }
while ( xml_nextNode( node ) );
156 else if ( xml_isNode( parent,
"player" ) ) {
158 xmlr_attr_strd( parent,
"name", save->
player_name );
160 xmlNodePtr node = parent->xmlChildrenNode;
162 xml_onlyNodes( node );
165 xmlr_strd( node,
"location", save->
spob );
166 xmlr_ulong( node,
"credits", save->
credits );
167 xmlr_strd( node,
"chapter", save->
chapter );
168 xmlr_strd( node,
"difficulty", save->
difficulty );
171 if ( xml_isNode( node,
"time" ) ) {
172 int cycles, periods, seconds;
173 xmlNodePtr cur = node->xmlChildrenNode;
174 cycles = periods = seconds = 0;
176 xmlr_int( cur,
"SCU", cycles );
177 xmlr_int( cur,
"STP", periods );
178 xmlr_int( cur,
"STU", seconds );
179 }
while ( xml_nextNode( cur ) );
185 if ( xml_isNode( node,
"ship" ) ) {
186 xmlr_attr_strd( node,
"name", save->
shipname );
187 xmlr_attr_strd( node,
"model", save->
shipmodel );
190 }
while ( xml_nextNode( node ) );
192 }
else if ( xml_isNode( parent,
"plugins" ) ) {
195 xmlNodePtr node = parent->xmlChildrenNode;
197 xml_onlyNodes( node );
199 if ( xml_isNode( node,
"plugin" ) ) {
200 const char *name = xml_get( node );
204 WARN( _(
"Save '%s' has unnamed plugin node!" ), save->
path );
206 }
while ( xml_nextNode( node ) );
209 }
while ( xml_nextNode( parent ) );
223static int load_loadThread(
void *ptr )
235 ThreadQueue *tq = vpool_create();
247 for (
int j = 0; j <
array_size( ps->saves ); j++ ) {
249 vpool_enqueue( tq, load_loadThread, ns );
258 for (
int j =
array_size( ps->saves ) - 1; j >= 0; j-- ) {
259 const nsave_t *ns = &ps->saves[j];
260 if ( ns->
ret != 0 ) {
262 free( ns->save_name );
263 array_erase( &ps->saves, &ps->saves[j], &ps->saves[j + 1] );
266 if ( ps->name == NULL )
269 if ( ps->name == NULL )
288 if ( strcmp( ps->name, ps[-1].name ) != 0 )
292 for (
int j = 0; j <
array_size( ps->saves ); j++ ) {
293 const nsave_t *ns = &ps->saves[j];
299 load_sortCompareName );
300 for (
int j =
array_size( ps[-1].saves ) - 1; j > 0; j-- ) {
301 nsave_t *ns = &ps[-1].saves[j];
302 if ( strcmp( ns->save_name, ns[-1].save_name ) != 0 )
326static int load_enumerateCallbackPlayer(
void *data,
const char *origdir,
335 size_t name_len = strlen( fname );
336 if ( name_len < 4 || strcmp( &fname[name_len - 3],
".ns" ) )
337 return PHYSFS_ENUM_OK;
339 dir_len = strlen( origdir );
341 fmt = dir_len && origdir[dir_len - 1] ==
'/' ?
"%s%s" :
"%s/%s";
342 SDL_asprintf( &path, fmt, origdir, fname );
343 if ( !PHYSFS_stat( path, &stat ) ) {
344 WARN( _(
"PhysicsFS: Cannot stat %s: %s" ), path,
345 _( PHYSFS_getErrorByCode( PHYSFS_getLastErrorCode() ) ) );
347 }
else if ( stat.filetype == PHYSFS_FILETYPE_REGULAR ) {
350 memset( &ns, 0,
sizeof( ns ) );
352 ns.save_name = strdup( fname );
353 ns.save_name[strlen( ns.save_name ) - 3] =
'\0';
359 return PHYSFS_ENUM_OK;
369 char *path, *backup_path;
371 size_t dir_len, name_len;
374 dir_len = strlen( origdir );
375 name_len = strlen( fname );
377 fmt = dir_len && origdir[dir_len - 1] ==
'/' ?
"%s%s" :
"%s/%s";
378 SDL_asprintf( &path, fmt, origdir, fname );
379 if ( !PHYSFS_stat( path, &stat ) )
380 WARN( _(
"PhysicsFS: Cannot stat %s: %s" ), path,
381 _( PHYSFS_getErrorByCode( PHYSFS_getLastErrorCode() ) ) );
383 else if ( stat.filetype == PHYSFS_FILETYPE_REGULAR ) {
384 if ( ( name_len < 4 || strcmp( &fname[name_len - 3],
".ns" ) ) &&
386 strcmp( &fname[name_len - 10],
".ns.backup" ) ) ) {
388 return PHYSFS_ENUM_OK;
390 if ( !PHYSFS_exists(
"saves-pre-0.10.0" ) )
391 PHYSFS_mkdir(
"saves-pre-0.10.0" );
392 SDL_asprintf( &backup_path,
"saves-pre-0.10.0/%s", fname );
394 old_saves_detected = 1;
398 }
else if ( stat.filetype == PHYSFS_FILETYPE_DIRECTORY ) {
402 PHYSFS_enumerate( path, load_enumerateCallbackPlayer, &psave );
407 return PHYSFS_ENUM_OK;
410static int load_compatibilityTest(
const nsave_t *ns )
412 char buf[STRMAX], buf2[STRMAX];
417 case SAVE_COMPATIBILITY_NAEV_VERSION:
419 _(
"Save game version mismatch" ),
420 _(
"Save game '%s' version does not match Naev version:\n"
421 " Save version: #r%s#0\n"
422 " Naev version: %s\n"
423 "Are you sure you want to load this game? It may lose data." ),
428 case SAVE_COMPATIBILITY_PLUGINS:
432 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"%s%s",
433 ( l > 0 ) ? p_(
"plugins",
", " ) :
"#r",
435 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"#0" );
439 l +=
scnprintf( &buf2[l],
sizeof( buf2 ) - l,
"%s%s",
440 ( l > 0 ) ? p_(
"plugins",
", " ) :
"",
443 _(
"Save game plugin mismatch" ),
444 _(
"Save game '%s' plugins do not match loaded plugins:\n"
445 " Save plugins: %s\n"
446 " Naev plugins: %s\n"
447 "Are you sure you want to load this game? It may lose data." ),
452 case SAVE_COMPATIBILITY_OK:
459static const char *load_compatibilityString(
const nsave_t *ns )
462 case SAVE_COMPATIBILITY_NAEV_VERSION:
463 return _(
"version mismatch" );
465 case SAVE_COMPATIBILITY_PLUGINS:
466 return _(
"plugins mismatch" );
468 case SAVE_COMPATIBILITY_OK:
469 return _(
"compatible" );
493 if (
ABS( diff ) >= 2 )
494 return SAVE_COMPATIBILITY_NAEV_VERSION;
498 return SAVE_COMPATIBILITY_PLUGINS;
501 return SAVE_COMPATIBILITY_OK;
512 return strcmp( ps1->name, ps2->name );
526static int load_sortCompareName(
const void *p1,
const void *p2 )
531 ret = strcmp( ns1->save_name, ns2->save_name );
572 return strcmp( ns1->save_name, ns2->save_name );
575static void load_freeSave(
nsave_t *ns )
580 free( ns->save_name );
600 for (
int j = 0; j <
array_size( ps->saves ); j++ ) {
601 load_freeSave( &ps->saves[j] );
619 if ( strcmp(
load_saves[i].name, name ) == 0 )
635 wid =
window_create(
"wdwLoadGameMenu", _(
"Load Pilot" ), -1, -1,
644 names = malloc(
sizeof(
char * ) * n );
645 for (
int i = 0; i < n; i++ ) {
648 char buf[STRMAX_SHORT];
650 load_compatibilityString( ns ) );
651 names[i] = strdup( buf );
654 if ( selected_player != NULL && !strcmp( names[i], selected_player ) )
660 names = malloc(
sizeof(
char *) );
661 names[0] = strdup( _(
"None" ) );
684 _(
"Delete" ), load_menu_delete, SDLK_d );
686 if ( old_saves_detected && !player_warned ) {
687 char buf[STRMAX_SHORT];
688 snprintf( buf,
sizeof( buf ),
"%s%s",
689 PHYSFS_getRealDir(
"saves-pre-0.10.0" ),
"saves-pre-0.10.0" );
690 dialogue_alert( _(
"Naev has detected saves in pre-0.10.0 format, and "
691 "has automatically migrated them to the new format. "
692 "Old saves have been backed up at '%s'." ),
698static void load_snapshot_menu_onClose(
unsigned int wid,
const char *str )
720 if ( strcmp(
load_saves[i].name, name ) == 0 ) {
726 WARN( _(
"Player '%s' not found in list of saves!" ), name );
732 free( selected_player );
736 wid =
window_create(
"wdwLoadSnapshotMenu", _(
"Load Snapshot" ), -1, -1,
741 data = malloc(
sizeof(
int ) );
749 names = malloc(
sizeof(
char * ) * n );
750 for (
int i = 0; i < n; i++ ) {
753 char buf[STRMAX_SHORT];
754 scnprintf( buf,
sizeof( buf ), _(
"%s (#r%s#0)" ), ns->save_name,
755 load_compatibilityString( ns ) );
756 names[i] = strdup( buf );
758 names[i] = strdup( ns->save_name );
763 names = malloc(
sizeof(
char *) );
764 names[0] = strdup( _(
"None" ) );
790 window_disableButton( wid,
"btnSave" );
792 int can_save =
landed && !player_isFlag( PLAYER_NOSAVE );
794 window_disableButton( wid,
"btnSave" );
806 int pos = toolkit_getListPos( wdw,
"lstNames" );
820 _(
"Save game" ), 1, 60, _(
"Please give the new snapshot a name:" ) );
821 if ( save_name == NULL )
824 snprintf( path,
sizeof( path ),
"saves/%s/%s.ns",
player.name, save_name );
825 if ( PHYSFS_exists( path ) ) {
828 _(
"You already have a snapshot named '%s'. Overwrite?" ), save_name );
837 _(
"Failed to save the game! You should exit and check the log to see "
838 "what happened and then file a bug report!" ) );
877 char buf[STRMAX_SHORT], credits[ECON_CRED_STRLEN], date[64],
878 difficulty[STRMAX_SHORT];
883 snprintf( difficulty,
sizeof( difficulty ), _(
"%s (options)" ),
886 snprintf( difficulty,
sizeof( difficulty ), _(
"%s (this save)" ),
891 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"#n%s", _(
"Name:" ) );
893 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Version:" ) );
894 if ( ns->
compatible == SAVE_COMPATIBILITY_NAEV_VERSION )
898 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Difficulty:" ) );
899 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#0 %s", difficulty );
900 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Date:" ) );
901 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#0 %s", date );
902 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Chapter:" ) );
904 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Space Object:" ) );
905 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#0 %s", _( ns->
spob ) );
906 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Credits:" ) );
907 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#0 %s", credits );
908 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Ship Name:" ) );
910 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Ship Model:" ) );
914 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#n%s", _(
"Plugins:" ) );
916 scnprintf( &buf[l],
sizeof( buf ) - l,
"\n#0 #%c%s#0",
920 &buf[l],
sizeof( buf ) - l, p_(
"plugins list",
", #%c%s#0" ),
924 window_modifyText( wid,
"txtPilot", buf );
934static void move_old_save(
const char *path,
const char *fname,
const char *ext,
935 const char *new_name )
937 size_t name_len = strlen( fname );
938 size_t ext_len = strlen( ext );
939 if ( name_len >= ext_len + 1 &&
940 !strcmp( &fname[name_len - ext_len], ext ) ) {
942 char *dirname = strdup( fname );
943 dirname[name_len - ext_len] =
'\0';
944 SDL_asprintf( &new_path,
"saves/%s", dirname );
945 if ( !PHYSFS_exists( new_path ) )
946 PHYSFS_mkdir( new_path );
948 SDL_asprintf( &new_path,
"saves/%s/%s", dirname, new_name );
950 if ( PHYSFS_exists( new_path ) ) {
953 SDL_asprintf( &bkp_path,
"%s.bkp", new_path );
954 while ( PHYSFS_exists( bkp_path ) && ( tries++ < 10 ) ) {
956 SDL_asprintf( &bkp_bkp_path,
"%s.bkp", bkp_path );
958 bkp_path = bkp_bkp_path;
965 if ( !PHYSFS_delete( path ) )
988 pos = toolkit_getListPos( wid,
"lstNames" );
990 if ( selected_player != NULL )
991 free( selected_player );
992 selected_player = strdup(
load_saves[pos].name );
1013 pos = toolkit_getListPos( wid,
"lstSaves" );
1032 pos = toolkit_getListPos( wid,
"lstNames" );
1040 if ( load_compatibilityTest( ns ) )
1072 pos = toolkit_getListPos( wid,
"lstSaves" );
1075 if ( load_compatibilityTest( &
load_player->saves[pos] ) )
1098static void load_menu_delete(
unsigned int wdw,
const char *str )
1105 pos = toolkit_getListPos( wid,
"lstNames" );
1111 _(
"Permanently Delete?" ),
1112 _(
"Are you sure you want to permanently delete the "
1113 "character '%s'?\n#rThis action is irreversible!#0" ),
1119 for (
int i = 0; i < n; i++ )
1120 if ( !PHYSFS_delete(
load_saves[pos].saves[i].path ) )
1123 snprintf( path,
sizeof( path ),
"saves/%s",
load_saves[pos].name );
1124 if ( !PHYSFS_delete( path ) )
1143 unsigned int wid =
window_get(
"wdwLoadSnapshotMenu" );
1148 pos = toolkit_getListPos( wid,
"lstSaves" );
1151 _(
"Are you sure you want to permanently delete the "
1152 "snapshot '%s'?\n#rThis action is irreversible!#0" ),
1157 if ( !PHYSFS_delete(
load_player->saves[pos].path ) )
1165 snprintf( path,
sizeof( path ),
"saves/%s",
load_player->name );
1166 if ( !PHYSFS_delete( path ) )
1185static void load_compatSlots(
void )
1194 sships = malloc( nships *
sizeof(
char * ) );
1195 tships = malloc( nships *
sizeof(
glTexture * ) );
1198 for (
int i = -1; i < nships; i++ ) {
1212 if ( sslot->
data != NULL )
1220 for (
int i = 0; i < nships; i++ )
1238 if ( !PHYSFS_exists( file ) ) {
1247 node = doc->xmlChildrenNode;
1262 WARN( _(
"Saved game '%s' invalid!" ), file );
1275 const char *file = ns->
path;
1276 const char *version = ns->
version;
1279 if ( !PHYSFS_exists( file ) ) {
1285 char buf[STRMAX_SHORT];
1286 size_t l = snprintf( buf,
sizeof( buf ),
"Loading save '%s'", file );
1287 NTracingMessage( buf, l );
1294 data = malloc(
sizeof(
const char *) * 2 );
1299 if ( (
player.p == NULL ) ||
1300 player_isFlag( PLAYER_DESTROYED ) )
1305 SDL_memset( &event, 0,
sizeof( event ) );
1307 SDL_PushEvent( &event );
1323 int misn_failed = 0, evt_failed = 0;
1324 const char **sdata = data;
1325 const char *file = sdata[0];
1326 const char *version = sdata[1];
1334 node = doc->xmlChildrenNode;
1341 render_postprocessCleanup();
1363 strdup( ( version != NULL ) ? version :
naev_version( 0 ) );
1366 if ( version_diff <= -2 ) {
1367 WARN( _(
"Old version detected. Sanitizing ships for slots" ) );
1412 if ( misn_failed || evt_failed ) {
1415 const char **misn_failed_str = mission_loadFailed();
1417 &buf[l],
sizeof( buf ) - l,
1418 _(
"Saved game '%s' failed to load some missions/events properly!" ),
1420 if ( misn_failed ) {
1421 l +=
scnprintf( &buf[l],
sizeof( buf ) - l,
1422 _(
"\nIn particular, the following missions have "
1423 "failed to load and been removed:" ) );
1424 for (
int i = 0; i <
array_size( misn_failed_str ); i++ )
1425 l +=
scnprintf( &buf[l],
sizeof( buf ) - l, _(
"\n #r%s#0" ),
1426 misn_failed_str[i] );
1429 &buf[l],
sizeof( buf ) - l,
1430 _(
"\nNote that, in general, you should be able to find the "
1431 "missions/events again and start them without penalty." ) );
1455 snprintf( buf,
sizeof( buf ),
"%s/%s", PHYSFS_getWriteDir(), filename );
1456 return xmlParseFile( buf );
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
void credits2str(char *str, credits_t credits, int decimals)
Converts credits to a usable string for displaying.
void dialogue_alert(const char *fmt,...)
Displays an alert popup with only an ok button and a message.
char * dialogue_input(const char *title, int min, int max, const char *fmt,...)
Creates a dialogue that allows the player to write a message.
void dialogue_alertRaw(const char *msg)
Displays an alert popup with only an ok button and a message.
int dialogue_YesNo(const char *caption, const char *fmt,...)
Runs a dialogue with both yes and no options.
int economy_init(void)
Initializes the economy.
void event_checkValidity(void)
Checks the event validity and cleans up after them.
void events_trigger(EventTrigger_t trigger)
Runs all the events matching a trigger.
const char * gui_pick(void)
Determines which GUI should be used.
int gui_load(const char *name)
Attempts to load the actual GUI.
void gui_setShip(void)
Player just upgraded their ship or modified it.
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
void gui_setCargo(void)
Player just changed their cargo.
void hook_clear(void)
Clears the hooks.
unsigned int hook_addFunc(int(*func)(void *), void *data, const char *stack)
Adds a function hook to be run.
void land(Spob *p, int load)
Opens up all the land dialogue stuff.
static void load_menu_update(unsigned int wid, const char *str)
Updates the load menu.
static int load_load(nsave_t *save)
Loads an individual save.
int load_game(const nsave_t *ns)
Actually loads a new game based on save structure.
int news_loadArticles(xmlNodePtr parent)
Loads the player's active articles from a save, initilizes news.
static void load_menu_close(unsigned int wdw, const char *str)
Closes the load game menu.
static void load_menu_load(unsigned int wdw, const char *str)
Loads a new game.
static int has_plugin(const char *plugin)
Checks to see if has a plugin.
int diff_load(xmlNodePtr parent)
Loads the diffs.
int events_loadActive(xmlNodePtr parent)
Loads the player's active events from a save.
static int load_gameInternalHook(void *data)
Loads a game. Meant to be run in a function hook.
int economy_sysLoad(xmlNodePtr parent)
Loads player's economy properties from an XML node.
int hook_load(xmlNodePtr parent)
Loads hooks for a player.
static int load_sortCompare(const void *p1, const void *p2)
qsort compare function for files.
int var_load(xmlNodePtr parent)
Loads the vars from XML file.
static SaveCompatibility load_compatibility(const nsave_t *ns)
Checks to see if a save is compatible with current Naev.
static void move_old_save(const char *path, const char *fname, const char *ext, const char *new_name)
Moves old Naev saves to subdirectories.
void load_loadSnapshotMenu(const char *name, int disablesave)
Opens the load snapshot menu.
int load_refresh(void)
Loads or refreshes saved games for the player.
static void display_save_info(unsigned int wid, const nsave_t *ns)
Displays Naev save info.
static void load_snapshot_menu_save(unsigned int wdw, const char *str)
Creates new custom snapshot.
static int load_enumerateCallback(void *data, const char *origdir, const char *fname)
The PHYSFS_EnumerateCallback for load_refresh.
static void load_menu_snapshots(unsigned int wdw, const char *str)
Opens the load snapshot menu.
void load_loadGameMenu(void)
Opens the load game menu.
static player_saves_t * load_saves
static void load_snapshot_menu_load(unsigned int wdw, const char *str)
Loads a new game.
void load_free(void)
Frees loaded save stuff.
const nsave_t * load_getList(const char *name)
Gets the array (array.h) of loaded saves.
static player_saves_t * load_player
static void load_snapshot_menu_delete(unsigned int wdw, const char *str)
Deletes an old game.
int pfaction_load(xmlNodePtr parent)
Loads the player's faction standings.
static void load_snapshot_menu_close(unsigned int wdw, const char *str)
Closes the load snapshot menu.
Spob * player_load(xmlNodePtr parent)
Loads the player stuff.
static xmlDocPtr load_xml_parsePhysFS(const char *filename)
Temporary (hopefully) wrapper around xml_parsePhysFS in support of gzipped XML (like ....
int load_gameDiff(const char *file)
Loads the diffs from game file.
static void load_snapshot_menu_update(unsigned int wid, const char *str)
Updates the load snapshot menu.
static int load_sortComparePlayersName(const void *p1, const void *p2)
qsort compare function for files.
static int load_sortComparePlayers(const void *p1, const void *p2)
qsort compare function for files.
int missions_loadActive(xmlNodePtr parent)
Loads the player's active missions from a save.
int missions_loadCommodity(xmlNodePtr parent)
Loads the player's special mission commodities.
int naev_versionCompare(const char *version)
Compares the version against the current naev version.
Header file with generic functions and naev-specifics.
const char * naev_version(int long_version)
Returns the version in a human readable string.
int ndata_copyIfExists(const char *file1, const char *file2)
Copy a file, if it exists.
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
ntime_t ntime_create(int scu, int stp, int stu)
Creates a time structure.
void ntime_prettyBuf(char *str, int max, ntime_t t, int d)
Gets the time in a pretty human readable format filling a preset buffer.
void pilot_calcStats(Pilot *pilot)
Recalculates the pilot's stats based on his outfits.
int pilot_rmOutfitRaw(Pilot *pilot, PilotOutfitSlot *s)
Removes an outfit from the pilot without doing any checks.
int pilot_addOutfitRaw(Pilot *pilot, const Outfit *outfit, PilotOutfitSlot *s)
Adds an outfit to the pilot, ignoring CPU or other limits.
int player_nships(void)
Gets the amount of ships player has in storage.
int player_ships(char **sships, glTexture **tships)
Returns a buffer with all the player's ships names.
int player_addOutfit(const Outfit *o, int quantity)
Adds an outfit to the player outfit stack.
void player_cleanup(void)
Cleans up player stuff like player_stack.
int player_addEscorts(void)
Adds the player's escorts.
Pilot * player_getShip(const char *shipname)
Gets a specific ship.
const char * plugin_name(const plugin_t *plg)
Tries to tget the name of a plugin.
static plugin_t * plugins
const plugin_t * plugin_list(void)
Returns the list of all the plugins.
int save_all_with_name(const char *name)
Saves the current game.
void shiplog_new(void)
Set up the shiplog.
int shiplog_load(xmlNodePtr parent)
Loads the logfiile.
int space_playerLoad(xmlNodePtr parent, const char *version)
Loads player's space properties from an XML node.
const char * start_chapter(void)
Gets the player's starting chapter.
const char * start_gui(void)
Gets the module's starting ship was acquired.
The representation of an in-game pilot.
PilotOutfitSlot ** outfits
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Abstraction for rendering sprite sheets.
SaveCompatibility compatible
void unidiff_universeDefer(int enable)
Sets whether or not to defer universe change stuff.