Communication between predicted hooks (PrimaryAttack and Move)
5 replies, posted
So say I wanted to make a gun that blasted you backwards when you shot it. The naive approach would be to set the players velocity in PrimaryAttack. It's kinda shitty when you consistently have 100+ ping though. I know I should be setting the movedata velocity in Move, but I can't figure out how to communicate between the two hooks properly. I'm guessing it's something a little more complicated than just a local variable?
Well, when I wanted to do that, in primary attack I set my own target position (shared) and then inside a Move hook I lerp the position while predicting and I set the origin with velocity
local ang = mv:GetMoveAngles()
local pos = mv:GetOrigin()
local vel = dir:Forward() * 4
--
-- Add the velocity to the position ( this is the movement )
--
vel = vel + dir:Right() * mv:GetSideSpeed() * speed * 50
if (IsFirstTimePredicted()) then
--
-- Set our target calculation only when it's predicted ( Happens once and it's always true in server, while doing interpolated frames is false )
--
ply._movetarget = pos + vel
end
--
-- Since we don't need any interpolation in server, we just use ply._moveTarget
-- Otherwise we lerp origin to movetarget (or pos so we don't cause a STUTTER effect when we null it)
--
pos = SERVER and ply._movetarget
or LerpVector(FrameTime(), pos, ply._movetarget or pos)
mv:SetVelocity( vel )
mv:SetOrigin( pos )
So you're basically faking the initial movement to avoid prediction errors?
He's interpolating between the command's calculated position and the predicted position on the client to compensate for lagtime between the server and client. Prediction already does this (somewhat) if you set everything shared in predicted hooks.
This code will cause prediction errors if the client repredicts a previous command since your _movetarget variable isn't reversed during prediction. For example, say command #4 (a new usercmd that has not been predicted) goes through the movement process on the client and calls the Move hook. As a result, your _movetarget variable is now setup for command #4's predicted position. Now say a prediction error occurs with command #3 (a previous command that has been predicted before) after receiving a net update from the server - the client will now go back and predict command #3 again even though command #4 has already started its prediction process. Your _movetarget variable will now be too far ahead in time causing an incorrect position to be used for an old command.
DTVars/NetworkVars and NWVars overcome this problem by caching their values before user commands are initially ran, then restore them when prediction starts. You'll can emulate the same behaviour with normal variables by storing the movetarget by its associated command number - if prediction occurs, you can look up the previously calculated movetarget for that specific command number without overwriting another command's movetarget.
You still require to call IsFirstTimePredicted otherwise you will end up having stuttering and jumping forward since your client will be much ahead than server
You're right with everything else, although I do some dirty distance verifications and then I nullify _movetarget, anyway this code ONLY runs while _movetarget is valid, I'm not really sure what do you really mean with the commands, it's not supposed that IsFirstTimePredicted runs first and then the interpolations? In weapons atleast, but I always tried to make the right calculations in the predicted frame on PrimaryAttack for example
Prediction is a bitch, most likely based in velocity aspects, got awful reminds about me creating a grapplehook and having to replicate a shadow in ClientSide and the apply force was the problem within prediction, so I had to kinky fake physics
I ended up checking mv:KeyDown, wep:GetNextPrimaryFire, and wep:Clip1 to figure out whenever the weapon was firing. It seems kinda hacky, but it's pretty solid.
Sorry, you need to Log In to post a reply to this thread.