Fix follow mode switching and PVS during pause
Three issues fixed: 1. ClientThink called ClientThink_real during demo playback, which ran server-side PmoveSingle and overwrote the client-owned ps.origin. Now ClientThink returns early in demo mode after updating pers.cmd (for button access). 2. Buttons never reached the server while paused: SV_UserMove discards usercmds with duplicate serverTime (line 1421). During pause, all usercmds have frozen serverTime. Fix: always process the last usercmd in the packet during demo playback. 3. Spectator button handling in G_RunFrame demo mode processes MOUSE1 (attack) to cycle follow targets via Cmd_FollowCycle_f. Removed debug print. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c4dca5f950
commit
2ce4aa88f2
3 changed files with 23 additions and 1 deletions
|
|
@ -1034,6 +1034,12 @@ void ClientThink( int clientNum ) {
|
||||||
// phone jack if they don't get any for a while
|
// phone jack if they don't get any for a while
|
||||||
ent->client->lastCmdTime = level.time;
|
ent->client->lastCmdTime = level.time;
|
||||||
|
|
||||||
|
// demo playback: don't run ClientThink_real — cgame owns
|
||||||
|
// the camera movement, G_RunFrame handles buttons and PVS origin
|
||||||
|
if ( g_svDemoPlaying.integer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !(ent->r.svFlags & SVF_BOT) && !g_synchronousClients.integer ) {
|
if ( !(ent->r.svFlags & SVF_BOT) && !g_synchronousClients.integer ) {
|
||||||
ClientThink_real( ent );
|
ClientThink_real( ent );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1761,6 +1761,17 @@ int start, end;
|
||||||
VectorCopy( cl->pers.cmd.origin, e->s.pos.trBase );
|
VectorCopy( cl->pers.cmd.origin, e->s.pos.trBase );
|
||||||
VectorCopy( cl->pers.cmd.origin, e->r.currentOrigin );
|
VectorCopy( cl->pers.cmd.origin, e->r.currentOrigin );
|
||||||
}
|
}
|
||||||
|
// process spectator buttons for follow mode switching
|
||||||
|
// (pers.cmd is updated by ClientThink which still runs)
|
||||||
|
{
|
||||||
|
int oldButtons = cl->buttons;
|
||||||
|
cl->oldbuttons = cl->buttons;
|
||||||
|
cl->buttons = cl->pers.cmd.buttons;
|
||||||
|
// attack cycles follow targets
|
||||||
|
if ( ( cl->buttons & BUTTON_ATTACK ) && !( oldButtons & BUTTON_ATTACK ) ) {
|
||||||
|
Cmd_FollowCycle_f( e, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
specEnt = e;
|
specEnt = e;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1419,7 +1419,12 @@ static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) {
|
||||||
// don't execute if this is an old cmd which is already executed
|
// don't execute if this is an old cmd which is already executed
|
||||||
// these old cmds are included when cl_packetdup > 0
|
// these old cmds are included when cl_packetdup > 0
|
||||||
if ( cmds[i].serverTime <= cl->lastUsercmd.serverTime ) {
|
if ( cmds[i].serverTime <= cl->lastUsercmd.serverTime ) {
|
||||||
continue;
|
// demo playback: still process the LAST cmd even with duplicate
|
||||||
|
// serverTime (paused = frozen time, all cmds have same time).
|
||||||
|
// Need buttons and origin from fresh usercmds.
|
||||||
|
if ( !SVD_IsPlaying() || i != cmdCount - 1 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SV_ClientThink (cl, &cmds[ i ]);
|
SV_ClientThink (cl, &cmds[ i ]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue