Help with creating View-Punch style recoil

Hello,

Counter-Strike: Global Offensive features a recoil system in which firing makes the player’s camera slowly rise up and return to the original pitch. It’s a lot like the ViewPunch function, but ViewPunch doesn’t affect where the player is aiming. I can make the player’s EyeAngles aim upward, but it’s an immediate shift, and not gradual like the ViewPunch function.

I’ve been toying around with the use of CurTime( ) and Lerping, and I just feel like I’m over-complicating and misunderstanding everything, and have scrapped everything I’ve done so far.

I don’t expect anyone to code this for me, I just need the general gist of the approach I should be taking with whatever hooks needed.

The recoil impulse is relatively fairly instant, but you could set up a Lerp to execute in the Think function to execute the change over a short time.

Well, maybe what I’m looking for is a slow drift downwards back to where the player was looking before the jerk upwards.

your best bet is to set up 2 time variables: one where it goes up and another where it goes down
have it lerp up when the UP one is true and lerp down slowly when the down one is good. i don’t know how you could make it in any other fashion.


SWEP.Primary.Recoil = 1
SWEP.Primary.Delay = .125
SWEP.Primary.Automatic = true

function SWEP:CalculateRecoil( )
end

function SWEP:CanPrimaryAttack( )
    if self:GetNextPrimaryFire( CurTime() ) < CurTime( ) then
        return true
    else
        return false
    end
end

function SWEP:PrimaryAttack( )
    self:EmitSound( "buttons/blip1.wav" )
    self:ShootBullet( )
    
    if CLIENT then
        
        local ply       = LocalPlayer( )
        local plyEye    = ply:EyeAngles( )
        local plyAng    = Angle( plyEye.p, plyEye.y, plyEye.r )
        
        ply:SetEyeAngles( plyAng + Angle( -1 * self.Primary.Recoil, 0, 0 ) )
        self:CalculateRecoil( self.Primary.Recoil / 16, CurTime( ), .25 )
    end

    self:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
end

function SWEP:Think( )
    self:CalculateRecoil( )
end

if CLIENT then
    
    local toAng, toTime, toDuration = 0, 0, 0
    
    function SWEP:CalculateRecoil( power, time, duration )
        
        toAng       = power or toAng
        toTime      = time or toTime
        toDuration  = duration or toDuration
        
        local ply       = LocalPlayer( )
        local plyEye    = ply:EyeAngles( )
        local plyAng    = Angle( plyEye.p, plyEye.y, plyEye.r )
        
        local LerpFrac  = math.Clamp( ( toTime + toDuration - CurTime( ) ) / toDuration, 0, 1 )
        
        print( LerpFrac )
        
        ply:SetEyeAngles( plyAng + Angle( ( toAng * LerpFrac ), 0, 0 ) )
        
    end
end

function SWEP:SecondaryAttack( )
end

function SWEP:DrawHUD( )
end

This doesn’t work as intended, but this does work. It doesn’t return to the very specific position, though, but this is good enough.