diff --git a/Quake/host.c b/Quake/host.c index aa4ce42c..c72d6f92 100644 --- a/Quake/host.c +++ b/Quake/host.c @@ -657,6 +657,39 @@ void Host_ServerFrame (void) // send all messages to the clients SV_SendClientMessages (); + + // autosave + qboolean autosaveAllowed = (!deathmatch.value && + !coop.value && + !sv.paused && + sv.active && + !cl.intermission && + svs.maxclients == 1 && + sv_player->v.deadflag == DEAD_NO); + if (autosaveAllowed) + { + static double oldhealth = 0; + static double lastautosave = 0; + + // Reset the last autosave time if it is out of bounds (i.e. we changed maps) + if (lastautosave > sv.time) + { + lastautosave = 0; + } + + // Only autosave when health is picked up + if ((sv.time - lastautosave) > 30.0 + && (sv_player->v.health > oldhealth)) + { + char command[MAX_QPATH + 10]; + sprintf(command, "save auto_%s", sv.name); + + Cmd_ExecuteString (command, src_command); + lastautosave = sv.time; + } + + oldhealth = sv_player->v.health; + } } /* diff --git a/Quake/host_cmd.c b/Quake/host_cmd.c index cb1ec9a9..51398bbd 100644 --- a/Quake/host_cmd.c +++ b/Quake/host_cmd.c @@ -33,8 +33,14 @@ extern int com_nummissionpacks; //johnfitz int current_skill; +char lastsavename[MAX_QPATH]; // autosave +char lastsavemapname[MAX_QPATH]; // autosave + void Mod_Print (void); +static qboolean _autoloadIfPossible(); +static void _resetAutoload(); + /* ================== Host_Quit_f @@ -837,6 +843,8 @@ void Host_Map_f (void) key_dest = key_game; // remove console or menu SCR_BeginLoadingPlaque (); + _resetAutoload(); // autosave + svs.serverflags = 0; // haven't completed an episode yet q_strlcpy (name, Cmd_Argv(1), sizeof(name)); // remove (any) trailing ".bsp" from mapname S.A. @@ -894,9 +902,52 @@ void Host_Changelevel_f (void) key_dest = key_game; // remove console or menu SV_SaveSpawnparms (); q_strlcpy (level, Cmd_Argv(1), sizeof(level)); + fprintf(stderr, "Host_Changelevel_f '%s'\n", level); + _resetAutoload(); // autosave SV_SpawnServer (level); } +static qboolean _autoloadIfPossible() +{ + if (!deathmatch.value && + !coop.value && + sv.active && + !cl.intermission && + svs.maxclients == 1) + { + if (0 == strcmp(sv.name, lastsavemapname)) + { + char command[MAX_QPATH + 5]; + sprintf(command, "load %s", lastsavename); + + Cmd_ExecuteString (command, src_command); + return true; + } + } + return false; +} + +static void _resetAutoload() +{ + lastsavemapname[0] = '\0'; // autosave - we are explicitly restarting the level, so don't autoload + lastsavename[0] = '\0'; +} + +/* +================== +Host_Autoload_f + +Automatically loads either the +================== +*/ +void Host_Autoload_f (void) +{ + if (!_autoloadIfPossible()) + { + Host_Restart_f(); + } +} + /* ================== Host_Restart_f @@ -915,6 +966,18 @@ void Host_Restart_f (void) return; q_strlcpy (mapname, sv.name, sizeof(mapname)); // must copy out, because it gets cleared // in sv_spawnserver + + if (sv_player->v.deadflag != DEAD_NO) // autosave + { + // If we are dead, attempt to autoload + if (_autoloadIfPossible()) + { + return; + } + } + + _resetAutoload(); + SV_SpawnServer (mapname); } @@ -1046,6 +1109,9 @@ void Host_Savegame_f (void) } } + strcpy(lastsavename, Cmd_Argv(1)); // autosave + strcpy(lastsavemapname, sv.name); // autosave + q_snprintf (name, sizeof(name), "%s/%s", com_gamedir, Cmd_Argv(1)); COM_DefaultExtension (name, ".sav", sizeof(name)); @@ -2297,6 +2363,7 @@ void Host_InitCommands (void) Cmd_AddCommand ("load", Host_Loadgame_f); Cmd_AddCommand ("save", Host_Savegame_f); Cmd_AddCommand ("give", Host_Give_f); + Cmd_AddCommand ("autoload", Host_Autoload_f); //autosave Cmd_AddCommand ("startdemos", Host_Startdemos_f); Cmd_AddCommand ("demos", Host_Demos_f);