Facepunch / garrysmod-issues

Garry's Mod issue tracker
142 stars 56 forks source link

Poseparameters implented inside a sequence do not work properly on viewmodels #3698

Open Kinyom opened 5 years ago

Kinyom commented 5 years ago

I'm currently attempting to create Left 4 Dead SWEPs; the original Turtle Rock Studios .smd files and .qcs were recently released, so they can be compiled properly for Garry's Mod and such. I'm compiling the M16/Rifle from that game.

Here's the .qc I'm using; I haven't edited it in any major way from the original besides the commented-out lines that were just me testing things.

The key thing here is this:

$sequence idle {
    ta_rifle_run_trans_run ta_rifle_run_trans_idle ta_rifle_run_trans_run 
     blendwidth 3 blend move_x 1 -1 loop
     //idle_actual loop
    addlayer look_poses
    //addlayer run_anims
    activity ACT_VM_IDLE 1
    }

In Left 4 Dead, as your character runs, the gun shifts its animation from its standard idle into a "running" animation where it bobs around and stuff. This is handled through poseparameters. If I use the compiled model (no matter whether it's compiled for GMod, L4D2, or the SDK 2013 multiplayer base) in my viewmodel, however, this does not work properly. I've attempted to set these clientside in my weapon's Think function, PostOpaqueRenderables, ViewModelDrawn, PostDrawViewModel, PreDrawViewModel, etc., and I've double-checked my interpolation methods to make sure they don't give any bogus values. However, the running animations do not work correctly. When interpolating into the poseparameter (going from 0, in the idle state, to 1, into the full running animation), initially they'll work fine, however as more time passes the interpolation/points between reaching the full animation will become choppier and choppier, and this gets reset whenever I send a sequence (for example, shooting the gun resets this choppiness). If I do it shared in my weapon's code, the choppiness gets even worse.

Here's my current approach - taking after how Garry does it in the gm_button entity code - where I set it in Think. The values at play here are move_x specifically; the ver_aims poseparameter doesn't change how this all works.

function SWEP:UpdatePoses( vm )
    local delta = FrameTime()
    local speed = self.Owner:GetVelocity():Length2D()
    speed = speed/self.Owner:GetWalkSpeed()
    speed = math.min( speed, 1.0 )

    self.m_runTrans = Lerp( delta / 0.5, self.m_runTrans, speed )

    local frac = math.min( (self.Owner:EyeAngles().x + self.Owner:GetPunchAngle().x + self.m_gravPunch.x)/89.0, 1.0 )
    if (self.Owner:IsFlagSet( FL_ANIMDUCKING ) or not self.Owner:OnGround()) then
        frac = -math.abs( frac )
    end
    self.m_verTrans = Lerp( delta / 0.25, self.m_verTrans, frac )

    vm:SetPoseParameter( "ver_aims", self.m_verTrans )
    vm:InvalidateBoneCache()

    vm:SetPoseParameter( "move_x", self.m_runTrans )
    vm:InvalidateBoneCache()
end

function SWEP:Think()
    if (CLIENT) then
        self:UpdatePoses( self.Owner:GetViewModel() )
    end
end

What I also want to say is that, if the run_anims code in the .qc is uncommented, then everything works perfectly fine, but the running animation is slowed down to play at the same FPS as the idle, which obviously isn't what I want. Not too sure why that works, but setting the poseparameters up in the .qc the other way doesn't; this works perfectly fine in Left 4 Dead; I'll also say that the ver_aims poseparameter works perfectly.

I'll see if I can get a video to show of this.

xDShot commented 5 years ago

For me, vm:SetPoseParameter() doesn't work on view model although I did almost the same as in your code.

Kinyom commented 5 years ago

Here, I recorded a video.

xDShot commented 5 years ago

nwm, I was stupid enough so I forgot to play needed animation with pose param.

Kinyom commented 4 years ago

Any updates on this? This is still an issue, and prevents viewmodels from having blend sequences that last more than one frame.

TotallyMehis commented 3 years ago

For the record and for anybody else struggling with this issue:

The problem is caused by interpolation here: https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/client/c_baseviewmodel.cpp#L157-L193

The code makes sure the client's viewmodel animation is in sync with the server's. Changing the pose parameters changes the cycle rate and that has side-effects on this code, which causes the weird sped-up / choppy animations.

As a workaround, you can disable this cycle extrapolation for idle animations (as they don't really need to be 100% in sync) and update the idle animations manually with FrameAdvance. Or, it might be possible to make the pose parameter animation and the actual sequence length the same, so there is no change in the cycle rate.

Chances are, this won't be fixed as it might affect old addons. You'll have to hack around it.