mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 07:12:07 +00:00
Detect if an autosave is loaded and advance world by 100 frames.
Autosaves are special. The are a byproduct of the level change process. When loaded they aren't respawning the player at it's last position, the player is relocated to func_playerstart. Since entities spawn at their start position, the player may end up in the wrong spot. One example is train.bsp -> base2.bsp. The platform spawns in upper position, the player in lower position. The platform comes down and crushes the player. Most of these cases work by luck when the client isn't paused during load, because the world advances a few frames before the player is spawned. Implement a better fix: Detect if an autosave is loaded (name is save0 or current) and treat it like a map change, advance the world by 100 frames. We cant use the `autosave` boolean, because it's in the game savefile. Fix suggested by @BjossiAlfreds, closes #711.
This commit is contained in:
parent
8f6a085434
commit
c9913eb538
4 changed files with 26 additions and 13 deletions
|
@ -217,7 +217,7 @@ void Master_Heartbeat(void);
|
||||||
void Master_Packet(void);
|
void Master_Packet(void);
|
||||||
|
|
||||||
void SV_InitGame(void);
|
void SV_InitGame(void);
|
||||||
void SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame);
|
void SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame, qboolean isautosave);
|
||||||
|
|
||||||
void SV_PrepWorldFrame(void);
|
void SV_PrepWorldFrame(void);
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,7 @@ SV_DemoMap_f(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SV_Map(true, Cmd_Argv(1), false);
|
SV_Map(true, Cmd_Argv(1), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -261,7 +261,7 @@ SV_GameMap_f(void)
|
||||||
|
|
||||||
|
|
||||||
/* start up the next map */
|
/* start up the next map */
|
||||||
SV_Map(false, map, false);
|
SV_Map(false, map, false, false);
|
||||||
|
|
||||||
/* archive server state */
|
/* archive server state */
|
||||||
Q_strlcpy(svs.mapcmd, map, sizeof(svs.mapcmd));
|
Q_strlcpy(svs.mapcmd, map, sizeof(svs.mapcmd));
|
||||||
|
|
|
@ -123,7 +123,7 @@ SV_CreateBaseline(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SV_CheckForSavegame(void)
|
SV_CheckForSavegame(qboolean isautosave)
|
||||||
{
|
{
|
||||||
char name[MAX_OSPATH];
|
char name[MAX_OSPATH];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
@ -155,7 +155,7 @@ SV_CheckForSavegame(void)
|
||||||
/* get configstrings and areaportals */
|
/* get configstrings and areaportals */
|
||||||
SV_ReadLevelFile();
|
SV_ReadLevelFile();
|
||||||
|
|
||||||
if (!sv.loadgame)
|
if (!sv.loadgame || (sv.loadgame && isautosave))
|
||||||
{
|
{
|
||||||
/* coming back to a level after being in a different
|
/* coming back to a level after being in a different
|
||||||
level, so run it for ten seconds */
|
level, so run it for ten seconds */
|
||||||
|
@ -179,7 +179,7 @@ SV_CheckForSavegame(void)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
SV_SpawnServer(char *server, char *spawnpoint, server_state_t serverstate,
|
SV_SpawnServer(char *server, char *spawnpoint, server_state_t serverstate,
|
||||||
qboolean attractloop, qboolean loadgame)
|
qboolean attractloop, qboolean loadgame, qboolean isautosave)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned checksum;
|
unsigned checksum;
|
||||||
|
@ -295,7 +295,7 @@ SV_SpawnServer(char *server, char *spawnpoint, server_state_t serverstate,
|
||||||
SV_CreateBaseline();
|
SV_CreateBaseline();
|
||||||
|
|
||||||
/* check for a savegame */
|
/* check for a savegame */
|
||||||
SV_CheckForSavegame();
|
SV_CheckForSavegame(isautosave);
|
||||||
|
|
||||||
/* set serverinfo variable */
|
/* set serverinfo variable */
|
||||||
Cvar_FullSet("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET);
|
Cvar_FullSet("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET);
|
||||||
|
@ -439,7 +439,7 @@ SV_InitGame(void)
|
||||||
* map tram.cin+jail_e3
|
* map tram.cin+jail_e3
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame)
|
SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame, qboolean isautosave)
|
||||||
{
|
{
|
||||||
char level[MAX_QPATH];
|
char level[MAX_QPATH];
|
||||||
char *ch;
|
char *ch;
|
||||||
|
@ -506,7 +506,7 @@ SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame)
|
||||||
SCR_BeginLoadingPlaque(); /* for local system */
|
SCR_BeginLoadingPlaque(); /* for local system */
|
||||||
#endif
|
#endif
|
||||||
SV_BroadcastCommand("changing\n");
|
SV_BroadcastCommand("changing\n");
|
||||||
SV_SpawnServer(level, spawnpoint, ss_cinematic, attractloop, loadgame);
|
SV_SpawnServer(level, spawnpoint, ss_cinematic, attractloop, loadgame, isautosave);
|
||||||
}
|
}
|
||||||
else if ((l > 4) && !strcmp(level + l - 4, ".dm2"))
|
else if ((l > 4) && !strcmp(level + l - 4, ".dm2"))
|
||||||
{
|
{
|
||||||
|
@ -514,7 +514,7 @@ SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame)
|
||||||
SCR_BeginLoadingPlaque(); /* for local system */
|
SCR_BeginLoadingPlaque(); /* for local system */
|
||||||
#endif
|
#endif
|
||||||
SV_BroadcastCommand("changing\n");
|
SV_BroadcastCommand("changing\n");
|
||||||
SV_SpawnServer(level, spawnpoint, ss_demo, attractloop, loadgame);
|
SV_SpawnServer(level, spawnpoint, ss_demo, attractloop, loadgame, isautosave);
|
||||||
}
|
}
|
||||||
else if ((l > 4) && !strcmp(level + l - 4, ".pcx"))
|
else if ((l > 4) && !strcmp(level + l - 4, ".pcx"))
|
||||||
{
|
{
|
||||||
|
@ -522,7 +522,7 @@ SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame)
|
||||||
SCR_BeginLoadingPlaque(); /* for local system */
|
SCR_BeginLoadingPlaque(); /* for local system */
|
||||||
#endif
|
#endif
|
||||||
SV_BroadcastCommand("changing\n");
|
SV_BroadcastCommand("changing\n");
|
||||||
SV_SpawnServer(level, spawnpoint, ss_pic, attractloop, loadgame);
|
SV_SpawnServer(level, spawnpoint, ss_pic, attractloop, loadgame, isautosave);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -531,7 +531,7 @@ SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame)
|
||||||
#endif
|
#endif
|
||||||
SV_BroadcastCommand("changing\n");
|
SV_BroadcastCommand("changing\n");
|
||||||
SV_SendClientMessages();
|
SV_SendClientMessages();
|
||||||
SV_SpawnServer(level, spawnpoint, ss_game, attractloop, loadgame);
|
SV_SpawnServer(level, spawnpoint, ss_game, attractloop, loadgame, isautosave);
|
||||||
Cbuf_CopyToDefer();
|
Cbuf_CopyToDefer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -417,6 +417,7 @@ SV_Loadgame_f(void)
|
||||||
char name[MAX_OSPATH];
|
char name[MAX_OSPATH];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *dir;
|
char *dir;
|
||||||
|
qboolean isautosave;
|
||||||
|
|
||||||
if (Cmd_Argc() != 2)
|
if (Cmd_Argc() != 2)
|
||||||
{
|
{
|
||||||
|
@ -444,6 +445,18 @@ SV_Loadgame_f(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Com_Printf("Savegame: %s\n", Cmd_Argv(1));
|
||||||
|
|
||||||
|
if (strcmp(Cmd_Argv(1), "save0") == 0 ||
|
||||||
|
strcmp(Cmd_Argv(1), "current") == 0)
|
||||||
|
{
|
||||||
|
isautosave = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isautosave = false;
|
||||||
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
SV_CopySaveGame(Cmd_Argv(1), "current");
|
SV_CopySaveGame(Cmd_Argv(1), "current");
|
||||||
|
@ -452,7 +465,7 @@ SV_Loadgame_f(void)
|
||||||
|
|
||||||
/* go to the map */
|
/* go to the map */
|
||||||
sv.state = ss_dead; /* don't save current level when changing */
|
sv.state = ss_dead; /* don't save current level when changing */
|
||||||
SV_Map(false, svs.mapcmd, true);
|
SV_Map(false, svs.mapcmd, true, isautosave);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in a new issue