Put the client into pause mode when loading save games.

This prevenits the worlds from advancing during client connect. The
player won't get attacked by monsters or hurt by the environment. Note
that in baseq2 there're still 4 world frames processed by the game and
100 world frames if the player enters a level that he or she already
visited. Both aren't a big problem, 4 world frames are hardly enough
for monsters starting to attack and in most levels the starting area
can't be reached by monsters and is free from environmental effects.

Pause mode is only entered for local servers and only in single player
mode. This should prevent problems with coop and deathmatch games.

The behaviour can be controlled by `cl_loadpaused`:
* `0`: Do not enter pause mode, Vanilla Quake I behaviour.
* `1`: Enter pause mode at load and leave it at first regular server
       frame.
* `2`: Enter pause mode at load, never leave it. The player must leave
       it by hand.

This was requested in issue #417.
This commit is contained in:
Yamagi Burmeister 2019-09-03 08:34:57 +02:00
parent 81a36bb3ad
commit fc5c2788a1
5 changed files with 59 additions and 0 deletions

View file

@ -63,6 +63,13 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
If *cl_async* is set to `0` *vid_maxfps* is the same as *cl_maxfps*,
use *cl_maxfps* to set the framerate.
* **cl_loadpaused**: If set to `1` (the default) the client is put into
pause mode during single player savegame load. This prevents monsters
and the environment from hurting the player while the client is still
connecting. If set to `2` the client stays in pause mode after
loading. If set to `0` pause mode is never entered, this is the
Vanilla Quake II behaviour.
* **cl_showfps**: Shows the framecounter. Set to `2` for more and to
`3` for even more informations.

View file

@ -56,6 +56,7 @@ cvar_t *cl_showmiss;
cvar_t *cl_showclamp;
cvar_t *cl_paused;
cvar_t *cl_loadpaused;
cvar_t *lookstrafe;
cvar_t *sensitivity;
@ -97,6 +98,11 @@ entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
fires his shotgun onto a Brain. */
int num_power_sounds;
/* Used to communicate if we entered paused mode
during server connect or if we were already in
it. */
qboolean paused_at_load;
extern cvar_t *allow_download;
extern cvar_t *allow_download_players;
extern cvar_t *allow_download_models;
@ -524,6 +530,7 @@ CL_InitLocal(void)
cl_showclamp = Cvar_Get("showclamp", "0", 0);
cl_timeout = Cvar_Get("cl_timeout", "120", 0);
cl_paused = Cvar_Get("paused", "0", 0);
cl_loadpaused = Cvar_Get("cl_loadpaused", "1", CVAR_ARCHIVE);
gl1_stereo = Cvar_Get( "gl1_stereo", "0", CVAR_ARCHIVE );
gl1_stereo_separation = Cvar_Get( "gl1_stereo_separation", "1", CVAR_ARCHIVE );

View file

@ -617,6 +617,40 @@ CL_ConnectionlessPacket(void)
}
}
/* Put client into pause mode when connecting to a local server.
This prevents the world from being forwarded while the client
is connecting, loading assets, etc. It's not 100%, there're
still 4 world frames (for baseq2) processed in the game and
100 frames by the server if the player enters a level that he
or she already visited. In practise both shouldn't be a big
problem. 4 frames are hardly enough for monsters staring to
attack and in most levels the starting area in unreachable by
monsters and free from environmental effects.
Com_Serverstate() returns > 1 if the server is local, otherwise
0. If it's a local server, maxclients aus either 0 (for single
player), or 2 to 8 (coop and deathmatch) if we're reaching this
code. For remote servers it's always 1. So this should trigger
only if it's a local single player server.
Since the player can load savegames from a paused state (e.g.
through the console) we'll need to communicate if we entered
paused mode (and it should left as soon as the player joined
the server) or if it was already there.
Last but not least this can be disabled by cl_loadpaused 0. */
if (Com_ServerState() || (Cvar_VariableValue("maxclients") <= 1))
{
if (cl_loadpaused->value)
{
if (!cl_paused->value)
{
paused_at_load = true;
Cvar_Set("paused", "1");
}
}
}
MSG_WriteChar(&cls.netchan.message, clc_stringcmd);
MSG_WriteString(&cls.netchan.message, "new");
cls.state = ca_connected;

View file

@ -798,6 +798,14 @@ CL_ParseFrame(void)
}
cl.sound_prepped = true;
if (paused_at_load)
{
if (cl_loadpaused->value == 1)
{
Cvar_Set("paused", "0");
}
}
}
/* fire entity events */

View file

@ -297,6 +297,7 @@ extern cvar_t *m_side;
extern cvar_t *freelook;
extern cvar_t *cl_lightlevel;
extern cvar_t *cl_paused;
extern cvar_t *cl_loadpaused;
extern cvar_t *cl_timedemo;
extern cvar_t *cl_vwep;
extern cvar_t *horplus;
@ -321,6 +322,8 @@ extern entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
extern netadr_t net_from;
extern sizebuf_t net_message;
extern qboolean paused_at_load;
void DrawString (int x, int y, char *s);
void DrawStringScaled(int x, int y, char *s, float factor);
void DrawAltString (int x, int y, char *s); /* toggle high bit */