/* ================== SV_GameMap_f Saves the state of the map just being exited and goes to a new map. If the initial character of the map string is '*', the next map is in a new unit, so the current savegame directory is cleared of map files. Example: *inter.cin+jail Clears the archived maps, plays the inter.cin cinematic, then goes to map jail.bsp. ================== */ void SV_GameMap_f (void) { char *map; int i; client_t *cl; qboolean *savedInuse; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: gamemap <map>\n"); return; } Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1)); FS_CreatePath (va("%s/save/current/", FS_Gamedir())); // check for clearing the current savegame map = Cmd_Argv(1); if (map[0] == '*') { // wipe all the *.sav files SV_WipeSavegame ("current"); } else { // save the map just exited if (sv.state == ss_game) { // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells savedInuse = malloc(maxclients->value * sizeof(qboolean)); for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) { savedInuse[i] = cl->edict->inuse; cl->edict->inuse = false; } SV_WriteLevelFile (); // we must restore these for clients to transfer over correctly for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) cl->edict->inuse = savedInuse[i]; free (savedInuse); } } // start up the next map SV_Map (false, Cmd_Argv(1), false ); // archive server state strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1); // copy off the level to the autosave slot if (!dedicated->value) { SV_WriteServerFile (true); SV_CopySaveGame ("current", "save0"); } }
void SV_Savegame_f(void) { char *dir; if (sv.state != ss_game) { Com_Printf("You must be in a game to save.\n"); return; } if (Cmd_Argc() != 2) { Com_Printf("USAGE: savegame <directory>\n"); return; } if (Cvar_VariableValue("deathmatch")) { Com_Printf("Can't savegame in a deathmatch\n"); return; } if (!strcmp(Cmd_Argv(1), "current")) { Com_Printf("Can't save to 'current'\n"); return; } if ((maxclients->value == 1) && (svs.clients[0].edict->client->ps.stats[STAT_HEALTH] <= 0)) { Com_Printf("\nCan't savegame while dead!\n"); return; } dir = Cmd_Argv(1); if (strstr(dir, "..") || strstr(dir, "/") || strstr(dir, "\\")) { Com_Printf("Bad savedir.\n"); } Com_Printf("Saving game...\n"); /* archive current level, including all client edicts. when the level is reloaded, they will be shells awaiting a connecting client */ SV_WriteLevelFile(); /* save server state */ SV_WriteServerFile(false); /* copy it off */ SV_CopySaveGame("current", dir); Com_Printf("Done.\n"); }
void SV_Savegame_f(void) { char *dir; if (sv.state != ss_game) { Com_Printf("You must be in a game to save.\n"); return; } /* * Knightmare- fs_gamedir may be getting messed up, causing it to * occasinally save in the root dir, */ /* thus leading to a hang on game loads, so we reset it here. */ if (!fs_gamedir[0]) { if (fs_gamedirvar->string[0]) Com_sprintf(fs_gamedir, sizeof(fs_gamedir), "%s/%s", fs_basedir->string, fs_gamedirvar->string); } if (Cmd_Argc() != 2) { Com_Printf("USAGE: savegame <directory>\n"); return; } if (Cvar_VariableValue("deathmatch")) { Com_Printf("Can't savegame in a deathmatch\n"); return; } if (!strcmp(Cmd_Argv(1), "current")) { Com_Printf("Can't save to 'current'\n"); return; } if (maxclients->value == 1 && svs.clients[0].edict->client->ps.stats[STAT_HEALTH] <= 0) { Com_Printf("\nCan't savegame while dead!\n"); return; } dir = Cmd_Argv(1); if (strstr(dir, "..") || strstr(dir, "/") || strstr(dir, "\\")) { Com_Printf("Bad savedir.\n"); } Com_Printf("Saving game...\n", dir); /* archive current level, including all client edicts. */ /* when the level is reloaded, they will be shells awaiting */ /* a connecting client */ SV_WriteLevelFile(); /* save server state */ SV_WriteServerFile(false); /* copy it off */ SV_CopySaveGame("current", dir); Com_Printf("Done.\n"); }
/* ================== SV_GameMap_f Saves the state of the map just being exited and goes to a new map. If the initial character of the map string is '*', the next map is in a new unit, so the current savegame directory is cleared of map files. Example: *inter.cin+jail Clears the archived maps, plays the inter.cin cinematic, then goes to map jail.bsp. ================== */ static void SV_GameMap_f (void) { char *map, expanded[MAX_QPATH], tMap[MAX_QPATH]; int i; client_t *cl; //qboolean *savedInuse; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: gamemap <map>\n"); return; } Q_strncpyz(tMap, Cmd_Argv(1), sizeof(tMap)); map = tMap; Com_DPrintf("SV_GameMap(%s)\n", map); FS_CreatePath (va("%s/save/current/", FS_Gamedir())); // check for clearing the current savegame if (map[0] == '*') { // wipe all the *.sav files SV_WipeSavegame("current"); } else { // save the map just exited if (!strchr(map, '.') && !strchr(map, '$')) { Com_sprintf (expanded, sizeof(expanded), "maps/%s.bsp", map); if (FS_LoadFile (expanded, NULL) == -1) { Com_Printf ("Can't find %s\n", expanded); return; } } if (sv.state == ss_game) { qboolean savedInuse[MAX_CLIENTS]; // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells //savedInuse = malloc(maxclients->integer * sizeof(qboolean)); for (i=0,cl=svs.clients ; i<maxclients->integer; i++,cl++) { savedInuse[i] = cl->edict->inuse; cl->edict->inuse = false; } SV_WriteLevelFile (); // we must restore these for clients to transfer over correctly for (i=0,cl=svs.clients ; i<maxclients->integer; i++,cl++) cl->edict->inuse = savedInuse[i]; //free (savedInuse); } } // start up the next map SV_Map (false, map, false ); // archive server state Q_strncpyz (svs.mapcmd, map, sizeof(svs.mapcmd)); // copy off the level to the autosave slot if (!dedicated->integer && !Cvar_VariableIntValue("deathmatch")) { SV_WriteServerFile(true); SV_CopySaveGame("current", "save0"); } }
void SV_Savegame_f (void) { char *dir; if (sv.state != ss_game) { Com_Printf ("You must be in a game to save.\n"); return; } // Knightmare- fs_gamedir may be getting messed up, causing it to occasinally save in the root dir, // thus leading to a hang on game loads, so we reset it here. if (!fs_gamedir[0]) { if (fs_gamedirvar->string[0]) Com_sprintf (fs_gamedir, sizeof(fs_gamedir), "%s/%s", fs_basedir->string, fs_gamedirvar->string); } if (Cmd_Argc() != 2) { Com_Printf ("USAGE: savegame <directory>\n"); return; } if (Cvar_VariableValue("deathmatch")) { Com_Printf ("Can't savegame in a deathmatch\n"); return; } if (!strcmp (Cmd_Argv(1), "current")) { Com_Printf ("Can't save to 'current'\n"); return; } // Knightmare- grab screen for quicksave if ( !dedicated->value && (!strcmp(Cmd_Argv(1), "quick") || !strcmp(Cmd_Argv(1), "quik")) ) R_GrabScreen(); if (maxclients->value == 1 && svs.clients[0].edict->client->ps.stats[STAT_HEALTH] <= 0) { Com_Printf ("\nCan't savegame while dead!\n"); return; } dir = Cmd_Argv(1); if (strstr (dir, "..") || strstr (dir, "/") || strstr (dir, "\\") ) { Com_Printf ("Bad savedir.\n"); } Com_Printf (S_COLOR_CYAN"Saving game \"%s\"...\n", dir); // archive current level, including all client edicts. // when the level is reloaded, they will be shells awaiting // a connecting client SV_WriteLevelFile (); // save server state SV_WriteServerFile (false); // take screenshot SV_WriteScreenshot (); // copy it off SV_CopySaveGame ("current", dir); Com_Printf (S_COLOR_CYAN"Done.\n"); }
/* ================== SV_GameMap_f Saves the state of the map just being exited and goes to a new map. If the initial character of the map string is '*', the next map is in a new unit, so the current savegame directory is cleared of map files. Example: *inter.cin+jail Clears the archived maps, plays the inter.cin cinematic, then goes to map jail.bsp. ================== */ void SV_GameMap_f (void) { char *map; int32_t i, l; client_t *cl; qboolean *savedInuse; if (Cmd_Argc() != 2) { Com_Printf ("USAGE: gamemap <map>\n"); return; } Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1)); FS_CreatePath (va("%s/save/current/", FS_Gamedir())); // check for clearing the current savegame map = Cmd_Argv(1); if (map[0] == '*') { // wipe all the *.sav files SV_WipeSavegame ("current"); } else { // save the map just exited if (sv.state == ss_game) { // clear all the client inuse flags before saving so that // when the level is re-entered, the clients will spawn // at spawn points instead of occupying body shells savedInuse = (qboolean*)Z_TagMalloc(maxclients->value * sizeof(qboolean), TAG_SERVER); for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) { savedInuse[i] = cl->edict->inuse; cl->edict->inuse = false; } SV_WriteLevelFile (); // we must restore these for clients to transfer over correctly for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++) cl->edict->inuse = savedInuse[i]; Z_Free (savedInuse); } } // start up the next map SV_Map (false, Cmd_Argv(1), false ); // archive server state strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1); // copy off the level to the autosave slot // Knightmare- don't do this in deathmatch or for cinematics l = strlen(map); //l = strcspn(map, "+"); if (!dedicated->value && !Cvar_VariableValue("deathmatch") && Q_strcasecmp (map+l-4, ".cin") && Q_strcasecmp (map+l-4, ".roq") && Q_strcasecmp (map+l-4, ".pcx")) { SV_WriteServerFile (true); SV_CopySaveGame ("current", "vrsave00"); } }