Fixed spectator inputs getting stuck and physics being run twice, due to the recent changes to SV_RunClientCommand.

This commit is contained in:
Marco Cawthorne 2023-01-02 18:10:20 -08:00
parent 534b249ac4
commit 2c5bf43c58
Signed by: eukara
GPG Key ID: CE2032F0A2882A22
9 changed files with 109 additions and 112 deletions

Binary file not shown.

View File

@ -276,20 +276,22 @@ NSView::UpdateView(void)
/* after predraws we can act upon their new positions */
switch (GetViewMode()) {
case VIEWMODE_FPS:
cl.UpdateAliveCam();
if (Client_InIntermission()) {
cl.UpdateIntermissionCam();
} else {
if (Client_IsDead(pl)) {
SetAFOV(cvar("fov"));
SetSensitivity(1.0f);
pl.UpdateDeathcam();
} else {
print("alive\n");
SetAFOV(cvar("fov") * pl.viewzoom);
SetSensitivity(pl.viewzoom);
cl.UpdateAliveCam();
StairSmooth();
View_DrawViewModel();
}
}
StairSmooth();
SetAFOV(cvar("fov") * pl.viewzoom);
SetSensitivity(pl.viewzoom);
if (Client_IsDead(pl))
pl.UpdateDeathcam();
else
View_DrawViewModel();
break;
case VIEWMODE_THIRDPERSON:
break;

View File

@ -245,13 +245,6 @@ View_DrawViewModel(void)
Viewmodel_CalcBob();
Viewmodel_ApplyBob(m_eViewModel);
Viewmodel_ApplyBob(m_eViewModelL);
/* view roll */
if (pl.movetype == MOVETYPE_WALK) {
Camera_StrafeRoll(view_angles);
Camera_RunBob(view_angles);
setproperty(VF_ANGLES, view_angles + pl.punchangle);
}
} else {
m_eViewModelL.origin = pl.m_xrInputLeft.GetOrigin();
m_eViewModel.origin = pl.m_xrInputRight.GetOrigin();

View File

@ -248,30 +248,13 @@ void
SV_RunClientCommand(void)
{
NSClient cl = (NSClient)self;
cl.SharedInputFrame();
cl.ServerInputFrame();
if (self.classname != "player") {
return;
}
#ifdef BOT_INCLUDED
/* wait a few seconds, as we may not have been spawned yet */
if (clienttype(self) == CLIENTTYPE_BOT) {
((bot)self).RunAI();
}
#endif
if (!Plugin_RunClientCommand()) {
/* TODO */
}
/* the last thing that happens, so that the game can intercept
input globals beforehand */
if (self.classname == "player") {
player pl = (player)self;
pl.Physics_Run();
}
cl.SharedInputFrame();
cl.ServerInputFrame();
}
/** Any 'cmd' from the client get sent here and handled.

View File

@ -25,7 +25,7 @@ NSClient:NSNavAI
public:
void NSClient(void);
/** Called to deal with the final input handling of the client. */
/** Called within the class to deal with the final input handling of the client. */
virtual void ProcessInput(void);
/** Run once, every frame, before physics are run on the player. */
virtual void PreFrame(void);
@ -39,7 +39,7 @@ public:
virtual bool IsDead(void);
/** Returns if we're a player. That is a type of client that is built on top of NSClientPlayer. */
virtual bool IsPlayer(void);
/** Like ClientInputFrame and ServerInputFrame, but run on both client and server at the same time. It is run before ClientInputFrame and ServerInputFrame. */
/** Like ClientInputFrame and ServerInputFrame, but run on both client and server at the same time. It is run before ClientInputFrame and ServerInputFrame. When overriding, Make sure to call the super method to enable Nuclide to handle spectator controls properly. */
virtual void SharedInputFrame(void);
/* overrides */
@ -49,13 +49,13 @@ public:
/** Client: Called on the client to give a chance to override input_* variables before networking them takes place. */
virtual void ClientInputFrame(void);
/** Client: Called every single client frame when this client is alive */
/** Client: Called every single client frame when this client is alive. You are expected to manipulate the g_view global here, which is of type NSView. */
virtual void UpdateAliveCam(void);
/** Client: Called every single client frame when this client is dead */
/** Client: Called every single client frame when this client is dead. You are expected to manipulate the g_view global here, which is of type NSView. */
virtual void UpdateDeathcam(void);
/** Client: Called every single client frame during intermission */
/** Client: Called every single client frame during intermission. You are expected to manipulate the g_view global here, which is of type NSView. */
virtual void UpdateIntermissionCam(void);
/* overrides */
@ -63,7 +63,7 @@ public:
#endif
#ifdef SERVER
/** Server: This is where the input* variables arrive after sending them out from the client (see ClientInputFrame).*/
/** Server: This is where the input* variables arrive after sending them out from the client (see ClientInputFrame). This is also where we will instruct the server to run physics on the client. */
virtual void ServerInputFrame(void);
/** Set the value of an InfoKey. */

View File

@ -45,6 +45,7 @@ public:
virtual bool IsRealSpectator(void);
virtual bool IsDead(void);
virtual bool IsPlayer(void);
virtual void SharedInputFrame(void);
/** Empty & shared between Client and Server. This is run on every player, every frame, to update their animation cycle. */
virtual void UpdatePlayerAnimation(float);

View File

@ -21,6 +21,17 @@ NSClientPlayer::NSClientPlayer(void)
vehicle = __NULL__;
}
void
NSClientPlayer::SharedInputFrame(void)
{
/* if spectator, we want to make sure we call this */
if (!Client_InIntermission() && IsFakeSpectator()) {
NSClientSpectator::SharedInputFrame();
return;
}
}
bool
NSClientPlayer::IsRealSpectator(void)
{
@ -39,7 +50,7 @@ NSClientPlayer::IsDead(void)
bool
NSClientPlayer::IsPlayer(void)
{
return (false);
return (true);
}
bool
@ -279,6 +290,8 @@ void
NSClientPlayer::UpdateAliveCam(void)
{
g_view.SetCameraOrigin(GetEyePos());
Camera_RunBob(view_angles);
Camera_StrafeRoll(view_angles);
g_view.SetCameraAngle(view_angles);
if (vehicle) {
@ -551,7 +564,14 @@ NSClientPlayer::PredictPostFrame(void)
void
NSClientPlayer::ServerInputFrame(void)
{
#ifdef BOT_INCLUDED
/* wait a few seconds, as we may not have been spawned yet */
if (clienttype(this) == CLIENTTYPE_BOT) {
((bot)this).RunAI();
}
#endif
Physics_Run();
}
void

View File

@ -20,7 +20,8 @@ typedef enumflags
SPECFL_VELOCITY,
SPECFL_TARGET,
SPECFL_MODE,
SPECFL_FLAGS
SPECFL_FLAGS,
SPECFL_TYPE,
} NSClientSpectatorFlags_t;
typedef enum
@ -68,6 +69,7 @@ public:
virtual bool IsRealSpectator(void);
virtual bool IsDead(void);
virtual bool IsPlayer(void);
virtual void SharedInputFrame(void);
/** Call to spectate the next spectating target. */
virtual void InputNext(void);

View File

@ -64,6 +64,7 @@ NSClientSpectator::IsFakeSpectator(void)
void
NSClientSpectator::ProcessInput(void)
{
#ifdef SERVER
if (input_buttons & INPUT_BUTTON0) {
InputNext();
} else if (input_buttons & INPUT_BUTTON3) {
@ -73,9 +74,7 @@ NSClientSpectator::ProcessInput(void)
} else {
spec_flags &= ~SPECFLAG_BUTTON_RELEASED;
}
input_buttons = 0;
//crossprint(sprintf("%d %d %d\n", spec_ent, spec_mode, spec_flags));
#endif
}
void
@ -86,9 +85,23 @@ NSClientSpectator::WarpToTarget(void)
setorigin(this, b.origin);
}
void
NSClientSpectator::SharedInputFrame(void)
{
SetSize(g_vec_null, g_vec_null);
if (spec_mode == SPECMODE_FREE) {
SetSolid(SOLID_NOT);
SetMovetype(MOVETYPE_NOCLIP);
} else {
SetSolid(SOLID_NOT);
SetMovetype(MOVETYPE_NONE);
}
}
#ifdef SERVER
float
NSClientSpectator::SendEntity(entity ePVSent, float flChangedFlags)
NSClientSpectator::SendEntity(entity ePVSent, float flChanged)
{
if (this != ePVSent) {
return (0);
@ -99,28 +112,21 @@ NSClientSpectator::SendEntity(entity ePVSent, float flChangedFlags)
}
WriteByte(MSG_ENTITY, ENT_SPECTATOR);
WriteFloat(MSG_ENTITY, flChangedFlags);
WriteFloat(MSG_ENTITY, flChanged);
if (flChangedFlags & SPECFL_ORIGIN) {
WriteCoord(MSG_ENTITY, origin[0]);
WriteCoord(MSG_ENTITY, origin[1]);
WriteCoord(MSG_ENTITY, origin[2]);
}
SENDENTITY_COORD(origin[0], SPECFL_ORIGIN)
SENDENTITY_COORD(origin[1], SPECFL_ORIGIN)
SENDENTITY_COORD(origin[2], SPECFL_ORIGIN)
if (flChangedFlags & SPECFL_VELOCITY) {
WriteFloat(MSG_ENTITY, velocity[0]);
WriteFloat(MSG_ENTITY, velocity[1]);
WriteFloat(MSG_ENTITY, velocity[2]);
}
SENDENTITY_FLOAT(velocity[0], SPECFL_VELOCITY)
SENDENTITY_FLOAT(velocity[1], SPECFL_VELOCITY)
SENDENTITY_FLOAT(velocity[2], SPECFL_VELOCITY)
if (flChangedFlags & SPECFL_TARGET)
WriteByte(MSG_ENTITY, spec_ent);
if (flChangedFlags & SPECFL_MODE)
WriteByte(MSG_ENTITY, spec_mode);
if (flChangedFlags & SPECFL_FLAGS)
WriteByte(MSG_ENTITY, spec_flags);
SENDENTITY_BYTE(spec_ent, SPECFL_TARGET)
SENDENTITY_BYTE(spec_mode, SPECFL_MODE)
SENDENTITY_BYTE(spec_flags, SPECFL_FLAGS)
SENDENTITY_BYTE(movetype, SPECFL_TYPE)
SENDENTITY_BYTE(solid, SPECFL_TYPE)
return (1);
}
@ -128,7 +134,11 @@ NSClientSpectator::SendEntity(entity ePVSent, float flChangedFlags)
void
NSClientSpectator::ServerInputFrame(void)
{
runstandardplayerphysics(this);
if (spec_mode == SPECMODE_FREE) {
runstandardplayerphysics(this);
} else {
WarpToTarget();
}
/* since we are not using Physics_Run(), we have to call this manually */
ProcessInput();
@ -151,8 +161,9 @@ NSClientSpectator::ClientInputFrame(void)
}
void
NSClientSpectator::ReceiveEntity(float new, float fl)
NSClientSpectator::ReceiveEntity(float new, float flChanged)
{
if (spec_mode == SPECMODE_FREE)
if (new == FALSE) {
/* Go through all the physics code between the last received frame
* and the newest frame and keep the changes this time around instead
@ -181,27 +192,21 @@ NSClientSpectator::ReceiveEntity(float new, float fl)
/* seed for our prediction table */
sequence = servercommandframe;
if (fl & SPECFL_ORIGIN) {
origin[0] = readcoord();
origin[1] = readcoord();
origin[2] = readcoord();
}
READENTITY_COORD(origin[0], SPECFL_ORIGIN)
READENTITY_COORD(origin[1], SPECFL_ORIGIN)
READENTITY_COORD(origin[2], SPECFL_ORIGIN)
if (fl & SPECFL_VELOCITY) {
velocity[0] = readfloat();
velocity[1] = readfloat();
velocity[2] = readfloat();
}
READENTITY_FLOAT(velocity[0], SPECFL_VELOCITY)
READENTITY_FLOAT(velocity[1], SPECFL_VELOCITY)
READENTITY_FLOAT(velocity[2], SPECFL_VELOCITY)
if (fl & SPECFL_TARGET)
spec_ent = readbyte();
if (fl & SPECFL_MODE)
spec_mode = readbyte();
if (fl & SPECFL_FLAGS)
spec_flags = readbyte();
READENTITY_BYTE(spec_ent, SPECFL_TARGET)
READENTITY_BYTE(spec_mode, SPECFL_MODE)
READENTITY_BYTE(spec_flags, SPECFL_FLAGS)
READENTITY_BYTE(movetype, SPECFL_TYPE)
READENTITY_BYTE(solid, SPECFL_TYPE)
};
float
NSClientSpectator::predraw(void)
{
@ -216,6 +221,8 @@ NSClientSpectator::InputNext(void)
if (spec_flags & SPECFLAG_BUTTON_RELEASED)
return;
spec_flags |= SPECFLAG_BUTTON_RELEASED;
#if 0
float max_edict;
@ -264,7 +271,7 @@ NSClientSpectator::InputNext(void)
spec_ent = best;
#endif
spec_flags |= SPECFLAG_BUTTON_RELEASED;
WarpToTarget();
if (spec_mode == SPECMODE_FREE)
@ -276,6 +283,9 @@ NSClientSpectator::InputPrevious(void)
{
if (spec_flags & SPECFLAG_BUTTON_RELEASED)
return;
spec_flags |= SPECFLAG_BUTTON_RELEASED;
#if 0
float max_edict;
@ -327,7 +337,6 @@ NSClientSpectator::InputPrevious(void)
spec_ent = best;
#endif
spec_flags |= SPECFLAG_BUTTON_RELEASED;
WarpToTarget();
@ -341,6 +350,8 @@ NSClientSpectator::InputMode(void)
if (spec_flags & SPECFLAG_BUTTON_RELEASED)
return;
spec_flags |= SPECFLAG_BUTTON_RELEASED;
NSClient f;
#ifdef CLIENT
f = (NSClient)findfloat(world, ::entnum, spec_ent);
@ -356,8 +367,6 @@ NSClientSpectator::InputMode(void)
if (spec_mode > SPECMODE_FIRSTPERSON)
spec_mode = SPECMODE_FREE;
}
spec_flags |= SPECFLAG_BUTTON_RELEASED;
}
void
@ -436,26 +445,13 @@ NSClientSpectator::EvaluateEntity(void)
{
/* check for which values have changed in this frame
and announce to network said changes */
if (origin != origin_net)
SetSendFlags(SPECFL_ORIGIN);
if (velocity != velocity_net)
SetSendFlags(SPECFL_VELOCITY);
if (spec_ent != spec_ent_net)
SetSendFlags(SPECFL_TARGET);
if (spec_mode != spec_mode_net)
SetSendFlags(SPECFL_MODE);
if (spec_flags != spec_flags_net)
SetSendFlags(SPECFL_FLAGS);
SAVE_STATE(origin)
SAVE_STATE(velocity)
SAVE_STATE(spec_ent)
SAVE_STATE(spec_mode)
SAVE_STATE(spec_flags)
EVALUATE_FIELD(origin, SPECFL_ORIGIN)
EVALUATE_FIELD(velocity, SPECFL_VELOCITY)
EVALUATE_FIELD(spec_ent, SPECFL_TARGET)
EVALUATE_FIELD(spec_mode, SPECFL_MODE)
EVALUATE_FIELD(spec_flags, SPECFL_FLAGS)
EVALUATE_FIELD(movetype, SPECFL_TYPE)
EVALUATE_FIELD(solid, SPECFL_TYPE)
}
#endif