Another try to fix the problem of spurious aborts of cinematics.

Until this commit a cinematic was aborted as soon as any key were
marked down when finishing the user command and sending it to the
server. The whole logic to detect if a key is down is broken, for
example `vid_restart` may leave keys marked down that are in fact
up. And there's the possibility to inject fake key events from
nearly everywhere. I'm not really sure but I suspect that even the
server may be able to inject key events.

Therefore untangle the cinematic abort code from the user command
processing, it should depend only on real key strokes:

1. Introduce a new global variable `abort_cinamatic` and set it to
   `cls.realtime` as soon as a key down event is detected. The only
   exceptions are Escape and Shift, because opening the menu and
   toggeling the console should never abort a cinematic.
2. When starting a cinematic `abort_cinamatic` is set to INT_MAX,
   because it needs to be higher than the current `cls.realtime`.
3. When a cinematic is running, `cls.key_dest` is set to `key_game`
   (`key_menu` and `key_console` are ignored, keys send to the menu
   or the console should never abort a cinematic; `key_message`
   can / should never happen while a cinematic is running) and
   `abort_cinamatic` is less than `cls.realtime` the cinematic is
   aborted.

`abort_cinamatic` less than `cls.realtime` is necessary because the
client needs one frame to pop up the menu or toggle the console and set
the `cls.key_dest` accordingly. `abort_cinamatic == cls.realtime - 1`
is not possible because not every frame finishes a user command.

This closes #502.
This commit is contained in:
Yamagi 2020-02-17 17:56:54 +01:00
parent 9160af75d9
commit bb0fc01e38
4 changed files with 21 additions and 9 deletions

View file

@ -31,6 +31,7 @@
extern cvar_t *vid_renderer;
cvar_t *cin_force43;
int abort_cinematic;
typedef struct
{
@ -321,8 +322,7 @@ Huff1Decompress(cblock_t in)
int *hnodes, *hnodesbase;
/* get decompressed count */
count = in.data[0] +
(in.data[1] << 8) + (in.data[2] << 16) + (in.data[3] << 24);
count = in.data[0] + (in.data[1] << 8) + (in.data[2] << 16) + (in.data[3] << 24);
input = in.data + 4;
out_p = out.data = Z_Malloc(count);
@ -632,6 +632,7 @@ SCR_PlayCinematic(char *arg)
char name[MAX_OSPATH], *dot;
In_FlushQueue();
abort_cinematic = INT_MAX;
/* make sure background music is not playing */
OGG_Stop();

View file

@ -776,8 +776,7 @@ CL_SendCmd(void)
if (cls.state == ca_connected)
{
if (cls.netchan.message.cursize ||
(curtime - cls.netchan.last_sent > 1000))
if (cls.netchan.message.cursize || (curtime - cls.netchan.last_sent > 1000))
{
Netchan_Transmit(&cls.netchan, 0, buf.data);
}
@ -796,8 +795,9 @@ CL_SendCmd(void)
SZ_Init(&buf, data, sizeof(data));
if (cmd->buttons && (cl.cinematictime > 0) && !cl.attractloop &&
(cls.realtime - cl.cinematictime > 1000))
if ((cls.realtime > abort_cinematic) && (cl.cinematictime > 0) &&
!cl.attractloop && (cls.realtime - cl.cinematictime > 1000) &&
(cls.key_dest == key_game))
{
/* skip the rest of the cinematic */
SCR_FinishCinematic();

View file

@ -1118,6 +1118,12 @@ Key_Event(int key, qboolean down, qboolean special)
/* Track if key is down */
keydown[key] = down;
/* Evil hack against spurious cinematic aborts. */
if (down && (key != K_ESCAPE) && !keydown[K_SHIFT])
{
abort_cinematic = cls.realtime;
}
/* Ignore most autorepeats */
if (down)
{

View file

@ -261,11 +261,16 @@ typedef struct
extern client_static_t cls;
/*Evil hack against too many power screen and power
/* Evil hack against too many power screen and power
shield impact sounds. For example if the player
fires his shotgun onto a Brain. */
extern int num_power_sounds;
/* Even more evil hack against spurious cinematic
aborts caused by an unspeakable evil hack right
out of the deeps of hell... Aeh... KeyEvent(). */
extern int abort_cinematic;
/* cvars */
extern cvar_t *gl1_stereo_separation;
extern cvar_t *gl1_stereo_convergence;