From 2c5bf43c5886860226fda720798d6aac9b4c4302 Mon Sep 17 00:00:00 2001 From: Marco Cawthorne Date: Mon, 2 Jan 2023 18:10:20 -0800 Subject: [PATCH] Fixed spectator inputs getting stuck and physics being run twice, due to the recent changes to SV_RunClientCommand. --- src/client/NSView.h | Bin 3361 -> 4794 bytes src/client/NSView.qc | 24 +++--- src/client/view.qc | 7 -- src/server/entry.qc | 21 +----- src/shared/NSClient.h | 12 +-- src/shared/NSClientPlayer.h | 1 + src/shared/NSClientPlayer.qc | 22 +++++- src/shared/NSClientSpectator.h | 4 +- src/shared/NSClientSpectator.qc | 130 ++++++++++++++++---------------- 9 files changed, 109 insertions(+), 112 deletions(-) diff --git a/src/client/NSView.h b/src/client/NSView.h index 9d3c26d37a50fc312ace43cb1032ff0b7a9bdd46..0f6b046f6cad0fa59caa73429288832f7e1d2edd 100644 GIT binary patch delta 1709 zcma)6L2DC16t+}avI(W2HCPazLff=938-i#m!d`KMZ}hhc(9Y~OER*VS!QOlO`-JQ zT@U#M{sW=6s^D4h7kKyX*^6&xlbT6OHK*+E``-J$?|m~L=8qRX&Q2cQfb}Mi5T0)B za7-)h0O+?~R~(yzchF`cj8H>^bx<*&C+JdbEV(ec5;(+m8{v(tgKUDKzgain8jOTc zu@o5G*>Er*l%yuW6f!s*0CYnkib{}!O+$kOG^8+$Qx(J!>!AXT%v6S7S)?V@5fY7| z9ie$Aj(VU_gjC9eBofMvbL^PtrSt+p3P*1^Ey(o`CO=P7@loyK_lYAp{d;1uy0QXW zXoxxqu|hjC#Mj1`R_TA8p6l=Dip#eA$v?|srP_a=E8PupUi(;TZaA^>ee-F$QQvaK zn;w)*>N4#EGgiNHmv+2TD*_BtEgV;I0bbxz6j>`ZA{Q+uI+ZFSTiZ$|t+su`6<`l_ z*8Xx(JoMT(B94MOr-D59gjAgS6sX6NI_xo860QQRLO@R@OSBLjW5Y0GCu`Zkx(s`( zFht2jflVcBXWUbsQ8h1VGchVnKBeflshyzR#>pYO#*CYdBRvfGhLqn-?_Uy`!dh_k znN|3R(Y%x!=KL3hkmUsUEiWFn;RuM z#LKlYDXgw#lo*62N6HV)aR!_*?|Ob_&8m8iCQ%~W%73BlF}jt9+nyyFg*`=GZhFv3 zBEw?}# zd55K0XUW1+GjcqAD*~kBIu>yEr+1wb3RNb=}!dNl|M_l=bCxiA#iYsj_SuMP< zwzX;3uH%>G;-2m3Nz7B3Eg(v8Ty5Y_b!(1!8dT7Tm diff --git a/src/client/NSView.qc b/src/client/NSView.qc index 3cea8b69..aa4e661c 100644 --- a/src/client/NSView.qc +++ b/src/client/NSView.qc @@ -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; diff --git a/src/client/view.qc b/src/client/view.qc index cacc3ed8..bbb87e3d 100644 --- a/src/client/view.qc +++ b/src/client/view.qc @@ -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(); diff --git a/src/server/entry.qc b/src/server/entry.qc index 90245843..a69834e1 100644 --- a/src/server/entry.qc +++ b/src/server/entry.qc @@ -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. diff --git a/src/shared/NSClient.h b/src/shared/NSClient.h index 1f29a36e..bcd8b3c0 100644 --- a/src/shared/NSClient.h +++ b/src/shared/NSClient.h @@ -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. */ diff --git a/src/shared/NSClientPlayer.h b/src/shared/NSClientPlayer.h index d0fe260a..16320eb3 100644 --- a/src/shared/NSClientPlayer.h +++ b/src/shared/NSClientPlayer.h @@ -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); diff --git a/src/shared/NSClientPlayer.qc b/src/shared/NSClientPlayer.qc index 6eacf64e..804904db 100644 --- a/src/shared/NSClientPlayer.qc +++ b/src/shared/NSClientPlayer.qc @@ -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 diff --git a/src/shared/NSClientSpectator.h b/src/shared/NSClientSpectator.h index 57eac7b0..178ea3a0 100644 --- a/src/shared/NSClientSpectator.h +++ b/src/shared/NSClientSpectator.h @@ -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); diff --git a/src/shared/NSClientSpectator.qc b/src/shared/NSClientSpectator.qc index 17a03d60..ef2d9a2f 100644 --- a/src/shared/NSClientSpectator.qc +++ b/src/shared/NSClientSpectator.qc @@ -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