void F::MISC::MOVEMENT::AutoStrafe(CUserCmd* pCmd)
{
float sv_air_accelerate = I::Cvar->Find(FNV1A::Hash("sv_airaccelerate"))->value.fl;
if (!I::Engine->IsConnected() || !I::Engine->IsInGame())
return;
if (!SDK::LocalPawn)
return;
if (SDK::LocalPawn->GetWaterLevel() >= WL_WAIST)
return;
if (SDK::LocalPawn->GetFlags() & FL_ONGROUND)
return;
const int moveType = SDK::LocalPawn->GetMoveType();
if (moveType == 1794 || moveType == 2313)
return;
static uint64_t last_pressed = 0;
static uint64_t last_buttons = 0;
if (!C_GET(bool, Vars.bAutoStrafe))
return;
auto movement_services = SDK::LocalPawn->m_movement_services();
if (!movement_services)
return;
const auto current_buttons = pCmd->nButtons.nValue;
float yaw = normalize_yaw(I::Input->GetViewAngles().y);
auto check_button = [&](const uint64_t button) {
if (current_buttons & button && (!(last_buttons & button) ||
(button & IN_MOVELEFT && !(last_pressed & IN_MOVERIGHT)) ||
(button & IN_MOVERIGHT && !(last_pressed & IN_MOVELEFT)) ||
(button & IN_FORWARD && !(last_pressed & IN_BACK)) ||
(button & IN_BACK && !(last_pressed & IN_FORWARD)))) {
if (button & IN_MOVELEFT)
last_pressed &= ~IN_MOVERIGHT;
else if (button & IN_MOVERIGHT)
last_pressed &= ~IN_MOVELEFT;
else if (button & IN_FORWARD)
last_pressed &= ~IN_BACK;
else if (button & IN_BACK)
last_pressed &= ~IN_FORWARD;
last_pressed |= button;
}
else if (!(current_buttons & button))
last_pressed &= ~button;
};
check_button(IN_MOVELEFT);
check_button(IN_MOVERIGHT);
check_button(IN_FORWARD);
check_button(IN_BACK);
last_buttons = current_buttons;
float offset = 0.f;
if (last_pressed & IN_MOVELEFT)
offset += 90.f;
if (last_pressed & IN_MOVERIGHT)
offset -= 90.f;
if (last_pressed & IN_FORWARD)
offset *= 0.5f;
else if (last_pressed & IN_BACK)
offset = -offset * 0.5f + 180.f;
yaw += offset;
pCmd->csgoUserCmd.pBaseCmd->SetBits(EBaseCmdBits::BASE_BITS_FORWARDMOVE);
pCmd->csgoUserCmd.pBaseCmd->SetBits(EBaseCmdBits::BASE_BITS_LEFTMOVE);
pCmd->csgoUserCmd.pBaseCmd->flForwardMove = 0.f;
pCmd->csgoUserCmd.pBaseCmd->flSideMove = 0.f;
if (pCmd->csgoUserCmd.pBaseCmd->flForwardMove != 0 || pCmd->csgoUserCmd.pBaseCmd->flSideMove != 0)
return;
C_CSWeaponBase* pWeapon = SDK::LocalPawn->GetActiveWeapon();
if (!pWeapon)
return;
float flStamina = 100;
float flMaxSpeed = pWeapon->GetWeaponVData()->m_max_speed()[0];
if (flStamina > 0)
{
float flSpeedScale = std::clamp(1.0f - (flStamina / 100.f), 0.f, 1.f);
flMaxSpeed *= flSpeedScale * flSpeedScale;
}
const auto ticks = std::clamp(12 - pCmd->csgoUserCmd.pBaseCmd->subtickMovesField.nTotalSize, 0, 12);
const auto frame_time = 0.015625f / static_cast<float>(ticks);
const float flVelocityAngle = normalize_yaw(M_RAD2DEG(atan2f(SDK::LocalPawn->GetAbsVelocity().y, SDK::LocalPawn->GetAbsVelocity().x)));
const float flSpeed = SDK::LocalPawn->GetAbsVelocity().Length2D();
const float flIdeal = std::clamp(M_RAD2DEG(atan(fmax(15.f, 30.f - ((((flMaxSpeed * sv_air_accelerate)) * movement_services->m_surface_friction()) * frame_time)) / flSpeed)), 0.f, 90.f);
const float flVelocityDelta = normalize_yaw(yaw - flVelocityAngle);
auto RotateMovement = [](CBaseUserCmdPB* pBaseCmd, float flTargetYaw)
{
const float flRotation = M_DEG2RAD(pBaseCmd->pViewAngles->angValue.y - flTargetYaw);
const float flNewForwardMove = cos(flRotation) * pBaseCmd->flForwardMove - sin(flRotation) * pBaseCmd->flSideMove;
const float flNewSideMove = sin(flRotation) * pBaseCmd->flForwardMove + cos(flRotation) * pBaseCmd->flSideMove;
pBaseCmd->flForwardMove = std::clamp(flNewForwardMove, -1.f, 1.f);
pBaseCmd->flSideMove = std::clamp(flNewSideMove * -1.f, -1.f, 1.f);
};
if ((fabsf(flVelocityDelta) > 170.f && flSpeed > 80.f) || (flVelocityDelta > flIdeal && flSpeed > 80.f))
{
yaw = flIdeal + flVelocityAngle;
pCmd->csgoUserCmd.pBaseCmd->flSideMove = -1.f;
RotateMovement(pCmd->csgoUserCmd.pBaseCmd, normalize_yaw(yaw));
return;
}
static bool bSideSwitch = false;
bSideSwitch = !bSideSwitch;
if (-flIdeal <= flVelocityDelta || flSpeed <= 80.f) {
if (bSideSwitch) {
yaw = yaw - flIdeal;
pCmd->csgoUserCmd.pBaseCmd->flSideMove = -1.0f;
}
else {
yaw = flIdeal + yaw;
pCmd->csgoUserCmd.pBaseCmd->flSideMove = 1.0f;
}
}
else {
yaw = flVelocityAngle - flIdeal;
pCmd->csgoUserCmd.pBaseCmd->flSideMove = 1.0f;
}
RotateMovement(pCmd->csgoUserCmd.pBaseCmd, normalize_yaw(yaw));
}