diff --git a/source/core/d_net.cpp b/source/core/d_net.cpp index e1d4d8939..6fbd27d90 100644 --- a/source/core/d_net.cpp +++ b/source/core/d_net.cpp @@ -1037,6 +1037,7 @@ void NetUpdate (void) float uvel = 0; float avel = 0; float horz = 0; + float roll = 0; for (tic = 0; tic < ticdup; ++tic) { @@ -1046,6 +1047,7 @@ void NetUpdate (void) uvel += localcmds[modp].ucmd.uvel; avel += localcmds[modp].ucmd.avel; horz += localcmds[modp].ucmd.horz; + roll += localcmds[modp].ucmd.roll; } svel /= ticdup; @@ -1053,6 +1055,7 @@ void NetUpdate (void) uvel /= ticdup; avel /= ticdup; horz /= ticdup; + roll /= ticdup; for (tic = 0; tic < ticdup; ++tic) { @@ -1062,6 +1065,7 @@ void NetUpdate (void) localcmds[modp].ucmd.uvel = uvel; localcmds[modp].ucmd.avel = avel; localcmds[modp].ucmd.horz = horz; + localcmds[modp].ucmd.roll = roll; } Net_NewMakeTic (); diff --git a/source/core/d_protocol.cpp b/source/core/d_protocol.cpp index 15525471e..ba8d64f5d 100644 --- a/source/core/d_protocol.cpp +++ b/source/core/d_protocol.cpp @@ -169,6 +169,8 @@ int UnpackUserCmd (InputPacket *ucmd, const InputPacket *basis, uint8_t **stream ucmd->svel = ReadFloat(stream); if (flags & UCMDF_UPMOVE) ucmd->uvel = ReadFloat(stream); + if (flags & UCMDF_ROLL) + ucmd->roll = ReadFloat(stream); } return int(*stream - start); @@ -220,6 +222,11 @@ int PackUserCmd (const InputPacket *ucmd, const InputPacket *basis, uint8_t **st flags |= UCMDF_UPMOVE; WriteFloat (ucmd->uvel, stream); } + if (ucmd->roll != basis->roll) + { + flags |= UCMDF_ROLL; + WriteFloat (ucmd->roll, stream); + } // Write the packing bits WriteByte (flags, &temp); @@ -248,6 +255,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, InputPacket &cmd, Inpu ("fvel", cmd.fvel) ("svel", cmd.svel) ("uvel", cmd.uvel) + ("roll", cmd.roll) .EndObject(); } return arc; @@ -262,7 +270,8 @@ int WriteUserCmdMessage (InputPacket *ucmd, const InputPacket *basis, uint8_t ** ucmd->avel != 0 || ucmd->fvel != 0 || ucmd->svel != 0 || - ucmd->uvel != 0) + ucmd->uvel != 0 || + ucmd->roll != 0) { WriteByte (DEM_USERCMD, stream); return PackUserCmd (ucmd, basis, stream) + 1; @@ -274,7 +283,8 @@ int WriteUserCmdMessage (InputPacket *ucmd, const InputPacket *basis, uint8_t ** ucmd->avel != basis->avel || ucmd->fvel != basis->fvel || ucmd->svel != basis->svel || - ucmd->uvel != basis->uvel) + ucmd->uvel != basis->uvel || + ucmd->roll != basis->roll) { WriteByte (DEM_USERCMD, stream); return PackUserCmd (ucmd, basis, stream) + 1; diff --git a/source/core/gameinput.cpp b/source/core/gameinput.cpp index 615299d8c..c9bc3bbb1 100644 --- a/source/core/gameinput.cpp +++ b/source/core/gameinput.cpp @@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //--------------------------------------------------------------------------- +EXTERN_CVAR(Int, vr_mode) CVAR(Float, m_pitch, 1.f, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) CVAR(Float, m_yaw, 1.f, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) CVAR(Float, m_forward, 1.f, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) @@ -183,6 +184,7 @@ void GameInput::processMovement(PlayerAngles* const plrAngles, const float scale if (scaleAdjust < 1) { plrAngles->CameraAngles.Yaw += DAngle::fromDeg(thisInput.avel); + plrAngles->CameraAngles.Roll += DAngle::fromDeg(thisInput.roll); plrAngles->CameraAngles.Pitch += DAngle::fromDeg(thisInput.horz); } } @@ -248,6 +250,7 @@ void GameInput::processVehicle(PlayerAngles* const plrAngles, const float scaleA if (scaleAdjust < 1) { plrAngles->CameraAngles.Yaw += DAngle::fromDeg(thisInput.avel); + plrAngles->CameraAngles.Roll += DAngle::fromDeg(thisInput.roll); plrAngles->CameraAngles.Pitch += DAngle::fromDeg(thisInput.horz); } } @@ -543,39 +546,48 @@ void PlayerAngles::doViewYaw(InputPacket* const input) // //--------------------------------------------------------------------------- -void PlayerAngles::doViewTilting(InputPacket* const pInput, const DVector2& nVelVect, const double nMaxVel, const bool bUnderwater) +void PlayerAngles::doRollInput(InputPacket* const input, const DVector2& nVelVect, const double nMaxVel, const bool bUnderwater) { - // Scale/attenuate tilting based on player actions. - const auto rollAmp = cl_viewtiltscale / (bUnderwater + 1); - const auto runScale = 1. / (!(pInput->actions & SB_RUN) + 1); - const auto strafeScale = !!pInput->svel + 1; + // Allow viewtilting if we're not in a VR mode. + if (!vr_mode) + { + // Scale/attenuate tilting based on player actions. + const auto rollAmp = cl_viewtiltscale / (bUnderwater + 1); + const auto runScale = 1. / (!(input->actions & SB_RUN) + 1); + const auto strafeScale = !!input->svel + 1; - if (cl_viewtilting == 1) - { - // Console-like yaw rolling. Adjustment == ~(90/32) for keyboard turning. Clamp is 1.5x this value. - const auto rollAdj = DAngle::fromDeg(pInput->avel * ROLL_TILTAVELSCALE * rollAmp); - const auto rollMax = DAngle::fromDeg((90. / 32. * 1.5) * cl_viewtiltscale); - scaletozero(pActor->spr.Angles.Roll, ROLL_TILTRETURN); - pActor->spr.Angles.Roll = clamp(pActor->spr.Angles.Roll + rollAdj, -rollMax, rollMax); - } - else if (cl_viewtilting == 2) - { - // Quake-like strafe rolling. Adjustment == (90/48) for running keyboard strafe. - const auto rollAdj = StrafeVel * strafeScale * rollAmp; - const auto rollMax = nMaxVel * runScale * cl_viewtiltscale; - pActor->spr.Angles.Roll = DAngle::fromDeg(clamp(rollAdj, -rollMax, rollMax) * (1.875 / nMaxVel)); - } - else if (cl_viewtilting == 3) - { - // Movement rolling from player's velocity. Adjustment == (90/48) for running keyboard strafe. - const auto rollAdj = nVelVect.Rotated(-pActor->spr.Angles.Yaw).Y * strafeScale * rollAmp; - const auto rollMax = nMaxVel * runScale * cl_viewtiltscale; - pActor->spr.Angles.Roll = DAngle::fromDeg(clamp(rollAdj, -rollMax, rollMax) * (1.875 / nMaxVel)); + if (cl_viewtilting == 1) + { + // Console-like yaw rolling. Adjustment == ~(90/32) for keyboard turning. Clamp is 1.5x this value. + const auto rollAdj = DAngle::fromDeg(input->avel * ROLL_TILTAVELSCALE * rollAmp); + const auto rollMax = DAngle::fromDeg((90. / 32. * 1.5) * cl_viewtiltscale); + scaletozero(pActor->spr.Angles.Roll, ROLL_TILTRETURN); + pActor->spr.Angles.Roll = clamp(pActor->spr.Angles.Roll + rollAdj, -rollMax, rollMax); + } + else if (cl_viewtilting == 2) + { + // Quake-like strafe rolling. Adjustment == (90/48) for running keyboard strafe. + const auto rollAdj = StrafeVel * strafeScale * rollAmp; + const auto rollMax = nMaxVel * runScale * cl_viewtiltscale; + pActor->spr.Angles.Roll = DAngle::fromDeg(clamp(rollAdj, -rollMax, rollMax) * (1.875 / nMaxVel)); + } + else if (cl_viewtilting == 3) + { + // Movement rolling from player's velocity. Adjustment == (90/48) for running keyboard strafe. + const auto rollAdj = nVelVect.Rotated(-pActor->spr.Angles.Yaw).Y * strafeScale * rollAmp; + const auto rollMax = nMaxVel * runScale * cl_viewtiltscale; + pActor->spr.Angles.Roll = DAngle::fromDeg(clamp(rollAdj, -rollMax, rollMax) * (1.875 / nMaxVel)); + } + else + { + // Always reset roll if we're not tilting at all. + pActor->spr.Angles.Roll = nullAngle; + } } else { - // Always reset roll if we're not tilting at all. - pActor->spr.Angles.Roll = nullAngle; + // Add player's device input. + pActor->spr.Angles.Roll += DAngle::fromDeg(input->roll * SyncInput()); } } diff --git a/source/core/gameinput.h b/source/core/gameinput.h index e9a6c785e..e2416ad3c 100644 --- a/source/core/gameinput.h +++ b/source/core/gameinput.h @@ -93,7 +93,7 @@ struct PlayerAngles void doYawInput(InputPacket* const input); void doViewPitch(const bool canslopetilt, const bool climbing = false); void doViewYaw(InputPacket* const input); - void doViewTilting(InputPacket* const pInput, const DVector2& nVelVect, const double nMaxVel, const bool bUnderwater); + void doRollInput(InputPacket* const input, const DVector2& nVelVect, const double nMaxVel, const bool bUnderwater); // General methods. void initialize(DCoreActor* const actor, const DAngle viewyaw = nullAngle) diff --git a/source/core/packet.h b/source/core/packet.h index 76d9e3a4b..346b7afe4 100644 --- a/source/core/packet.h +++ b/source/core/packet.h @@ -75,6 +75,7 @@ struct InputPacket float uvel; float avel; float horz; + float roll; ESyncBits actions; diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index 22c6ef72c..78ff4da6b 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -1578,7 +1578,7 @@ void ProcessInput(PLAYER* pPlayer) pPlayer->Angles.doYawInput(pInput); constexpr auto maxVel = (36211. / 3000.); - pPlayer->Angles.doViewTilting(pInput, actor->vel.XY(), maxVel, pPlayer->posture == kPostureSwim); + pPlayer->Angles.doRollInput(pInput, actor->vel.XY(), maxVel, pPlayer->posture == kPostureSwim); if (!(pInput->actions & SB_JUMP)) pPlayer->cantJump = 0; diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index 33568b221..330c0e048 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -1828,7 +1828,7 @@ void processinput_d(int snum) } } - p->Angles.doViewTilting(&p->sync, p->vel.XY(), maxVel, (psectlotag == 1) || (psectlotag == 2)); + p->Angles.doRollInput(&p->sync, p->vel.XY(), maxVel, (psectlotag == 1) || (psectlotag == 2)); HORIZONLY: diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index 3444ed2d9..a04d61b70 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -2693,7 +2693,7 @@ void processinput_r(int snum) } } - p->Angles.doViewTilting(&p->sync, p->vel.XY(), maxVel, (psectlotag == 1) || (psectlotag == 2)); + p->Angles.doRollInput(&p->sync, p->vel.XY(), maxVel, (psectlotag == 1) || (psectlotag == 2)); HORIZONLY: diff --git a/source/games/exhumed/src/player.cpp b/source/games/exhumed/src/player.cpp index 4bcd14703..0fc9efab4 100644 --- a/source/games/exhumed/src/player.cpp +++ b/source/games/exhumed/src/player.cpp @@ -1569,7 +1569,7 @@ static void doPlayerCameraEffects(Player* const pPlayer, const double nDestVertP doPlayerVertPanning(pPlayer, nDestVertPan * cl_slopetilting); // Roll tilting effect, either console or Quake-style. - pPlayer->Angles.doViewTilting(&pPlayer->input, pPlayerActor->vel.XY(), maxVel, nUnderwater); + pPlayer->Angles.doRollInput(&pPlayer->input, pPlayerActor->vel.XY(), maxVel, nUnderwater); // Update Z bobbing. if (cl_viewbob) diff --git a/source/games/sw/src/player.cpp b/source/games/sw/src/player.cpp index 82a27b604..074be9be5 100644 --- a/source/games/sw/src/player.cpp +++ b/source/games/sw/src/player.cpp @@ -2075,7 +2075,7 @@ void DoPlayerMove(PLAYER* pp) actor->vel.X = pp->vect.Length(); constexpr auto maxVel = (380401538. / 36022361.); - pp->Angles.doViewTilting(&pp->input, pp->vect, maxVel, pp->Flags & (PF_SWIMMING|PF_DIVING)); + pp->Angles.doRollInput(&pp->input, pp->vect, maxVel, pp->Flags & (PF_SWIMMING|PF_DIVING)); if (pp->Flags & (PF_CLIP_CHEAT)) {