Setting velocity in Think() ?

I’m making a jetpack, which sets the player’s velocity when holding WASD and spacebar.

It works fine on servers with 66 tickrate. When I tried it on 20 tickrate, it became extremely weak and could barely lift the player. And in single player, it became extremely overpowered.

I figured it’s because Think() executes once every tick serverside, so I tried making a tick multiplier variable. so for example, on 33 tickrate, the multiplier would be 2 since Think() is only called 33 times per second instead of 66.
It works well to scale the fuel consumption and recharge rate, but completely f*cks up velocity calculations and overpowers them.

(to undo the TickMultiplier calculation, it’s possible to just set the tm variable to 1)


function ITEM:Think(ply, modifications)
	if (SERVER) then
		local tm = 66.6	/ engine.TickInterval()                               --gets (T)ick (M)ultiplier to adjust velocity calculations and fuel consumption.
	
		if ply:KeyDown(IN_JUMP) then
			ply.Jetpackfuel = math.max(0, ply.Jetpackfuel - 1*tm)
			local i = math.floor( math.min(10,-0.1+ply.Jetpackfuel) / 10 )	-- returns -1 at 0 fuel,    0 below 10 fuel,    and 1 above 10 fuel.
			if i ~= -1 then
				ply:SetVelocity( ply:GetUp() * tm * ( 17 + i*10 )         +         ply:GetForward()*tm*(10 + i*7)*( (ply:KeyDown(IN_FORWARD) and 1 or 0)-(ply:KeyDown(IN_BACK) and 1 or 0) )        +          ply:GetRight()*tm*(10 + i*7)*( (ply:KeyDown(IN_MOVERIGHT) and 1 or 0)-(ply:KeyDown(IN_MOVELEFT) and 1 or 0) )               -ply:GetVelocity()*Vector(3,3,2+i)*0.01*tm )
			end
		else
			ply:SetVelocity( -ply:GetVelocity()*Vector(0,0,1)*0.01*tm )
		end


		if(ply.Jetpackfuel < 100) then
			ply.Jetpackfuel = ply.Jetpackfuel + 0.25*tm
		end
	end
end

So how do I solve setting velocity of items on different tickrates?

cant you use CurTime()? like lastTime = CurTime(), if CurTime() + 0.1 (0.1 seconds) > CurTime() then it hasn’t gone a 0.1 seconds, then it should apply the same everywhere I think?

Don’t divide the tickinterval by anything, simply multiply the velocity by engine.TickInterval() and then some multiplier and it should be fine. You need to imagine what the maths is doing:

Higher server tick = Think is being run more often, which means we need to decrease the velocity applied
As the server tick gets higher, TickInterval gets lowered.
But if you do 1/TickInterval, you reverse it, a higher servertick suddenly increases your “tm” variable.
So use an unalterned version of the TickInterval.

@Donkie
sorry, I pasted an old script. I meant to actually calculate TM by:
66.6 / engine.TickInterval()
which gets a correct multiplier for different tickrates.

But with that calculation, the velocity got extremely overpowered on lower ticks.
velocity doesn’t seem to actually be half on 33 tick compared to 66 tick. It’s just slightly lower.

The only way I’ve managed to make the jetpack stable on different tickrates is by setting the player’s gravity to a negative value to boost upwards, but that doesn’t fix sideways movement speed.

Edit:
I think I know why velocity doesn’t scale correctly:

ENTITY:Think()



20 tick = 1/20 = 0.05
66 tick = 1/66 = 0.01515
100 tick = 1/100 = 0.01

By your maths:
20 tick -> 66/0.05 -> Multiplier: 1320
66 tick -> 66/0.01515 -> Multiplier: 4356
100 tick -> 66/0.01 -> Multiplier: 6600


You actually increase the multiplier as the tickrate increases, which is wrong, the multiplier should reduce.
This is physics, most physics engines uses http://en.wikipedia.org/wiki/Euler_method to compute theire physics. The “Step Size” in this case is the TickInterval.

lol my bad, another stupid typo, I made this thread too soon after waking up.

In the actually tested code, tm was:
66.6 / ( 1 / TickInterval() )
which does scale it correctly.

but my tired brain mixed up 1/x and x/1, and thought:
“herp derp, 1/x is the same as x”, so I changed it to 66.6/TickInterval() in the code i posted here xD…

But yeah, even with the tm variable scaling correctly (which I checked with print™ while testing), scaling velocity depending on tick does not work as expected.

That is atleast the correct way, but I’m still not sure about you dividing the tickinterval like that, I want you to try it without dividing and then adding a multiplier instead, because that is how it should be done.

ply:SetVelocity( -ply:GetVelocity()Vector(0,0,1)<somemul>*engine.TickInterval() )

The last problem which is also a big one is that this isn’t predicted. Source engine goes back and forth in time in order to give players a smooth experience, with this code, you don’t take account for that timetraveling.
Its a lot more complicated, but on a laggy server this will be the only right solution.

mathematically speaking, mult * TickInterval() should scale it exactly the same as div / (1 / TickInterval()).

on 66 tickrate, TickInterval() should be somewhere around 0.015, so:

66.6 / (1 / 0.015) = 0.999
66.6 * 0.015 = 0.999

looking at them though, multiplying it seems more efficient, so I’ll change to that for optimization reasons. But the calculation will return the exact same value, so doesn’t make a difference in the jetpack’s functionality.

I think this more has to do with how the game handles physics?
It seems to be done seperately from the actual tick, like… physics isn’t 2 times slower on servers with 33 tickrate.
So I’m guessing multiplying velocity by 2 on 33 tick servers doesn’t work as expected. But I’ve confirmed this type of calculation it to work when changing variables over time, like how fast the jetpack fuel depletes and recharges.

Edit:
Hmm… I don’t need it to be 100% accurate, so I don’t think I’ll bother with the game movement thingy, since it’s a bit too complicated for me until i get better at lua.
I actually don’t need it to work for other tickrates, since my server always uses 66.
But I want to make it usable for other server owners as well, in case I decide to share my modified pointshop when it’s done.

Edit 2:
I tried making a new variable, vm (velocity modifier), which does the following calculation:



local tm = 66.66 * TickInterval()		--actual tick multiplier
local vm = 0.8 + tm*0.2			--experimental velocity modifier

so basically, it uses a base multiplier of 0.8, and 20% of the tick multiplier, and I tried using it to scale all velocity calculations.

I just did it as a random test, but the jetpack works very similarly on both 66 and 20 tick now.
I realise it’s a very bad solution, but it’s the closest I’ve come so far.