Skip to content

Commit

Permalink
Client: Add +use slowdown auto-detection (#247)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmp64 committed Oct 6, 2024
1 parent c674cb0 commit bda2f0c
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/game/client/cdll_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ int CL_DLLEXPORT HUD_VidInit(void)
gHUD.VidInit();
g_StudioRenderer.InitOnConnect();
PM_ResetBHopDetection();
PM_ResetUseSlowDownDetection();
CResults::Get().Stop();
GetClientVoiceMgr()->VidInit();

Expand Down
14 changes: 4 additions & 10 deletions src/game/client/hud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,11 @@ static Color s_DefaultColorCodeColors[10] = {
const Color NoTeamColor::Orange = Color(255, 178, 0, 255);
const Color NoTeamColor::White = Color(216, 216, 216, 255);

CON_COMMAND(bhop_reset, "Resets BHop auto-detection if it was detected incorrectly")
CON_COMMAND(pm_reset, "Resets player movement settings if they were detected incorrectly")
{
if (gHUD.GetBHopCapState() != EBHopCap::AutoDetect)
{
ConPrintf("BHop auto-detection is disabled, nothing was done.\n");
}
else
{
PM_ResetBHopDetection();
ConPrintf("BHop auto-detection reset.\n");
}
PM_ResetBHopDetection();
PM_ResetUseSlowDownDetection();
ConPrintf("Player movement settings reset.\n");
}

// inputw32.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/hud_redraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ extern ConVar zoom_sensitivity_ratio;
ConVar hud_colortext("hud_colortext", "1", FCVAR_BHL_ARCHIVE);
ConVar hud_takesshots("hud_takesshots", "0", FCVAR_ARCHIVE, "Whether or not to automatically take screenshots at the end of a round");
ConVar default_fov("default_fov", "90", FCVAR_ARCHIVE | FCVAR_BHL_ARCHIVE, "Default horizontal field of view");
ConVar cl_useslowdown("cl_useslowdown", "1", FCVAR_BHL_ARCHIVE, "Slowdown behavior on +USE. 0 - Old. 1 - New");
ConVar cl_useslowdown("cl_useslowdown", "2", FCVAR_BHL_ARCHIVE, "Slowdown behavior on +USE. 0 - Old. 1 - New. 2 - Auto-detect.");

// Think
void CHud::Think(void)
Expand Down
121 changes: 117 additions & 4 deletions src/pm_shared/pm_shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,19 +173,46 @@ EUseSlowDownType PM_GetUseSlowDownType()

void PM_SetUseSlowDownType(EUseSlowDownType value)
{
#ifdef CLIENT_DLL
if (s_nUseSlowDownType != EUseSlowDownType::AutoDetect && value == EUseSlowDownType::AutoDetect)
PM_ResetUseSlowDownDetection();
#endif

s_nUseSlowDownType = value;
}

#ifdef CLIENT_DLL

static constexpr float BHOP_DETECT_DELAY = 0.3f;
static constexpr float USE_SLOWDOWN_DETECT_MIN = 0.25f;
static constexpr float USE_SLOWDOWN_DETECT_MAX = 0.4f;

enum class EUseSlowDownDetectionState
{
None,

//! speed < USE_SLOWDOWN_DETECT_MIN * maxSpeed
LowSpeed,

//! USE_SLOWDOWN_DETECT_MIN * maxSpeed <= speed < USE_SLOWDOWN_DETECT_MAX * maxSpeed
MidSpeed,

//! speed >= USE_SLOWDOWN_DETECT_MAX * maxSpeed
HighSpeed,

//! Successfully detected the server mode.
Done,
};

static int s_iOnGround;
static int s_iWaterlevel;
static int s_iMoveType;
static EBHopCap s_iBHopState = EBHopCap::Enabled;
static float s_flBHopCheckTime = 0.0f;

static EUseSlowDownDetectionState s_nUseSlowDownDetectionState = EUseSlowDownDetectionState::None;
static int s_iUseSlowDownCount = 0;

int PM_GetOnGround()
{
return s_iOnGround;
Expand Down Expand Up @@ -222,6 +249,12 @@ void PM_ResetBHopDetection()
}
}

void PM_ResetUseSlowDownDetection()
{
s_nUseSlowDownDetectionState = EUseSlowDownDetectionState::None;
s_iUseSlowDownCount = 0;
}

#else

int PM_GetBHopCapEnabled()
Expand All @@ -236,6 +269,27 @@ void PM_SetBHopCapEnabled(int state)

#endif

static EUseSlowDownType PM_GetActualUseSlowDownType()
{
#ifdef CLIENT_DLL
if (s_nUseSlowDownType == EUseSlowDownType::AutoDetect)
{
if (s_nUseSlowDownDetectionState == EUseSlowDownDetectionState::Done)
{
// Detected that the server uses Old method
return EUseSlowDownType::Old;
}
else
{
// Not yet detected or the server uses New
return EUseSlowDownType::New;
}
}
#endif

return s_nUseSlowDownType;
}

void PM_SwapTextures(int i, int j)
{
char chTemp;
Expand Down Expand Up @@ -3005,7 +3059,7 @@ void PM_CheckParamters(void)
//
// JoshA: Moved this to CheckParamters rather than working on the velocity,
// as otherwise it affects every integration step incorrectly.
if (s_nUseSlowDownType == EUseSlowDownType::New && (pmove->onground != -1) && (pmove->cmd.buttons & IN_USE))
if (PM_GetActualUseSlowDownType() == EUseSlowDownType::New && (pmove->onground != -1) && (pmove->cmd.buttons & IN_USE))
{
pmove->maxspeed *= 1.0f / 3.0f;
}
Expand Down Expand Up @@ -3185,11 +3239,70 @@ void PM_PlayerMove(qboolean server)
}
}

// Slow down, I'm pulling it! (a box maybe) but only when I'm standing on ground
if (s_nUseSlowDownType == EUseSlowDownType::Old && (pmove->onground != -1) && (pmove->cmd.buttons & IN_USE))
if ((pmove->onground != -1) && (pmove->cmd.buttons & IN_USE))
{
VectorScale(pmove->velocity, 0.3, pmove->velocity);
if (PM_GetActualUseSlowDownType() == EUseSlowDownType::Old)
{
// Slow down, I'm pulling it! (a box maybe) but only when I'm standing on ground
VectorScale(pmove->velocity, 0.3, pmove->velocity);
}
#ifdef CLIENT_DLL
else if (s_nUseSlowDownType == EUseSlowDownType::AutoDetect &&
s_nUseSlowDownDetectionState != EUseSlowDownDetectionState::Done)
{
if (pmove->cmd.buttons & (IN_FORWARD | IN_FORWARD | IN_MOVELEFT | IN_MOVERIGHT) &&
pmove->velocity.Length2DSqr() >= 25.0f)
{
// We're moving in some direction. Try to auto-detect server's +use slowdown type
EUseSlowDownDetectionState oldState = s_nUseSlowDownDetectionState;
EUseSlowDownDetectionState newState = EUseSlowDownDetectionState::None;
float speed = pmove->velocity.Length2D();

if (speed >= USE_SLOWDOWN_DETECT_MAX * pmove->maxspeed)
newState = EUseSlowDownDetectionState::HighSpeed;
else if (speed >= USE_SLOWDOWN_DETECT_MIN * pmove->maxspeed)
newState = EUseSlowDownDetectionState::MidSpeed;
else
newState = EUseSlowDownDetectionState::LowSpeed;

if (oldState == EUseSlowDownDetectionState::HighSpeed && newState == EUseSlowDownDetectionState::LowSpeed)
{
// Sudden slow down. This occurs when the client re-synchronizes with the server.
s_iUseSlowDownCount++;
}
else if (oldState == EUseSlowDownDetectionState::LowSpeed && newState == EUseSlowDownDetectionState::HighSpeed)
{
// Sudden speed up. Something went wrong.
PM_ResetUseSlowDownDetection();
}

if (s_iUseSlowDownCount >= 5)
{
// Slow down has happened a few times. Assume the server uses the old method.
PM_ResetUseSlowDownDetection();
pmove->Con_Printf("Setting +use slowdown to Old to match the server\n");
s_nUseSlowDownDetectionState = EUseSlowDownDetectionState::Done;
}
else
{
s_nUseSlowDownDetectionState = newState;
}
}
else
{
// Reset auto-detection
PM_ResetUseSlowDownDetection();
}
}
#endif
}
#ifdef CLIENT_DLL
else if (s_nUseSlowDownDetectionState != EUseSlowDownDetectionState::Done)
{
// Reset auto-detection
PM_ResetUseSlowDownDetection();
}
#endif

// Handle movement
switch (pmove->movetype)
Expand Down
11 changes: 11 additions & 0 deletions src/pm_shared/pm_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,18 @@ enum class EUseSlowDownType
//! Player slowly slows down if +use is held down.
New,

#ifdef CLIENT_DLL
//! Detect automatically.
AutoDetect,
#endif

#ifdef CLIENT_DLL
_Min = Old,
_Max = AutoDetect,
#else
_Min = Old,
_Max = New,
#endif
};

void PM_Init(struct playermove_s *ppmove);
Expand Down Expand Up @@ -59,6 +69,7 @@ int PM_GetMoveType();
EBHopCap PM_GetBHopCapState();
void PM_SetBHopCapState(EBHopCap state);
void PM_ResetBHopDetection();
void PM_ResetUseSlowDownDetection();
#else
int PM_GetBHopCapEnabled();
void PM_SetBHopCapEnabled(int state);
Expand Down

0 comments on commit bda2f0c

Please sign in to comment.