Skip to content

Fix #847: Reset faceanimtime during fast load to prevent stuck pain face#917

Open
adrian-andrzjewski wants to merge 2 commits into
Novum:masterfrom
adrian-andrzjewski:fix/847-fastload-face-animation
Open

Fix #847: Reset faceanimtime during fast load to prevent stuck pain face#917
adrian-andrzjewski wants to merge 2 commits into
Novum:masterfrom
adrian-andrzjewski:fix/847-fastload-face-animation

Conversation

@adrian-andrzjewski

Copy link
Copy Markdown
Contributor

Problem

When Fast Loading is enabled, saving during the 0.2s pain face animation window and then reloading causes the HUD face to get stuck in the pain state.

Root Cause

In view.c:302, when the player takes damage, cl.faceanimtime is set to cl.time + 0.2. During a fast load, cl.time is reset to the save time, but cl.faceanimtime was not reset. If the save occurred during the animation window (within 0.2s of taking damage), the condition cl.time <= cl.faceanimtime would remain true after loading, keeping the pain face visible.

Solution

Reset cl.faceanimtime to 0 during fast load, consistent with how other client state (dlights, beams, particles, blend effects) is already reset in the same code block.

Changes:

  • host_cmd.c: Added cl.faceanimtime = 0.0; to the fast load reset block
  • Misc/test_faceanimtime.c: Added unit tests validating the fix

Testing

  • Build: 0 warnings, 0 errors (MSVC x64 Release)
  • Unit tests: 9/9 passed
  • Verified the fix logic through test scenarios covering:
    • Save during animation window (bug case)
    • Save after animation expired (no bug)
    • Reset behavior validation

Expected Behavior

  • After fast loading, the HUD face should show the correct health-based expression
  • Pain face animation should not persist across fast loads
  • Normal (non-fast) loading behavior is unchanged

@sezero sezero left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patch from #916 has no place here.

@adrian-andrzjewski adrian-andrzjewski force-pushed the fix/847-fastload-face-animation branch from 1ddd51f to 8c74ad9 Compare June 17, 2026 08:24
@vsonnier

Copy link
Copy Markdown
Collaborator

@adrian-andrzjewski Thanks ! I also agree with @sezero , solving #916 has nothing to do here, please separate the issues.

I also don't care of unit or non-regression tests, please remove them it add maintainance without real benfit. This is just a game, already very stable, not a multi-million framework with consumer demands and money to back it up that would need some kind of non-regression garantees :)

@adrian-andrzjewski adrian-andrzjewski force-pushed the fix/847-fastload-face-animation branch from 8c74ad9 to 00ca365 Compare June 17, 2026 08:27
…ain face

When taking damage, cl.faceanimtime is set to cl.time + 0.2 to show
the pain face animation. During a fast load, cl.time is reset to the
save time, but cl.faceanimtime was not reset. This caused the pain
face to remain visible if the save was made during the 0.2s animation
window.

Fix: Reset cl.faceanimtime to 0 during fast load, consistent with
how other client state (dlights, beams, particles) is reset.
@sezero sezero requested review from vsonnier and removed request for sezero June 17, 2026 08:48

@sezero sezero left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In terms of relevant-only changes, this is good now.

In terms of functionality: Can't test myself now, @vsonnier should have a look.

@vsonnier

vsonnier commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Sorry @adrian-andrzjewski I've tested it, but it doesn't work.

Ex, tested on Bestiary using the method here : #920. While fast-reloading after being blown up by the mines, the face is still frozen in a pain state for a little while.

As another example using Quake Brutalist Jam III with the following save : s0.zip

  • Fire some shots with the pistol
  • Fall into the pit before you
  • Die
  • When fast-reloading, the pistol hud ammunition is broken for some time, and health icons pulse while the heath is not changing. Same story as the pain face, but using a custom HUD using CSQC.

Comment thread Quake/host_cmd.c
memset (cl_dlights, 0, sizeof (cl_dlights));
memset (cl_temp_entities, 0, sizeof (cl_temp_entities));
memset (cl_beams, 0, sizeof (cl_beams));
cl.faceanimtime = 0.0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't work, or is not enough... I also tried to add a cl.time = 0.0 reset following the same logic, to no avail.

…revent stuck pain face

The faceanimtime reset alone was insufficient because the server re-sends
a stale svc_damage on the next frame (from dmg_take/dmg_save restored by
the savefile). V_ParseDamage then overwrites faceanimtime using the old
cl.time (before svc_time resets it), causing the pain face to get stuck
until cl.time catches up -- potentially thousands of seconds.

Fix by zeroing dmg_take/dmg_save on the player entity (edict 1) in the
fastload cleanup block, preventing the stale damage message from being sent.

Also adds a test_faceanim console command for programmatic verification.
Usage: load a map, type 'test_faceanim run', observe PASS/FAIL.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants