Problem with movement system based on Quake

I am currently trying to make a custom movement system using a BodyVelocity. I used this article as a reference. I’m pretty sure I implemented everything correctly, but air strafing and some other movement tricks don’t work. In theory, I should be able to replicate the air strafing in the video in the article, but I can’t. I have also watched this Youtube video on the subject, and my code still seems correct, but I can’t perform any of the tricks in the video, like wall-running or zigzagging. I’ve also tried looking into the original code itself, but I couldn’t really understand anything.

Here is the place file:
movement test.rbxl (54.1 KB)

The movement script is in StarterCharacterScripts. I have also visualized the wishDir (blue) and the player’s velocity (green). Can somebody show me what I have done wrong in the script/what I have missed/what I need to implement?

Movement code if you're too lazy to download the file
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local character = script.Parent
local humanoid : Humanoid = character:WaitForChild("Humanoid")
local humanoidRootPart : BasePart = character:WaitForChild("HumanoidRootPart")

local camera = workspace.CurrentCamera
camera.FieldOfView = 90

local BodyVelocity = Instance.new("BodyVelocity")
BodyVelocity.MaxForce = Vector3.new(1,0,1) * 2e4
BodyVelocity.Parent = humanoidRootPart

-- constants
local sv_ground_accelerate = 400
local sv_air_accelerate = 0
local sv_max_velocity_ground = 500
local sv_max_velocity_air = 1500
local sv_friction = 10

-- check if player is airborne
local function PlayerIsInAir()
	return humanoid.FloorMaterial == Enum.Material.Air
end

-- http://adrianb.io/2015/02/14/bunnyhop.html

local function Accelerate(accelDir : Vector3, prevVelocity :Vector3, accelerate, maxVelocity, deltaTime)
	local projVel = prevVelocity:Dot(accelDir) -- vector projection of prev velocity onto accelDir
	local accelVel = accelerate * deltaTime -- accelerated velocity in direction of movement
	
	-- if necessary, truncate the accelerated velocity so the vector projection does not exceed max velocity
	if (projVel + accelVel) > maxVelocity then
		accelVel = maxVelocity - projVel
	end
	
	return prevVelocity + accelDir * accelVel;
end

local function ApplyFriction(prevVelocity : Vector3, deltaTime)
	local speed = prevVelocity.Magnitude
	if speed ~= 0 then -- to avoid divide by 0 errors
		local drop = speed * sv_friction * deltaTime
		prevVelocity *= math.max(speed - drop, 0) / speed -- scale the velocity based on friction
	end
	
	return prevVelocity
end

local function MoveGround(accelDir : Vector3, prevVelocity : Vector3, deltaTime)
	prevVelocity = ApplyFriction(prevVelocity, deltaTime)
	
	return Accelerate(accelDir, prevVelocity, sv_ground_accelerate, sv_max_velocity_ground, deltaTime);
end

local function MoveAir(accelDir : Vector3, prevVelocity : Vector3, deltaTime)
	return Accelerate(accelDir, prevVelocity, sv_air_accelerate, sv_max_velocity_air, deltaTime);
end

local function UpdateVelocity(deltaTime)
	local accelDir = humanoid.MoveDirection
	local prevVelocity = humanoidRootPart.AssemblyLinearVelocity
	local humanoidState = humanoid:GetState()
	
	if PlayerIsInAir() then
		BodyVelocity.Velocity = MoveAir(accelDir, prevVelocity, deltaTime)
	else
		BodyVelocity.Velocity = MoveGround(accelDir, prevVelocity, deltaTime)
	end
end

RunService.RenderStepped:Connect(UpdateVelocity)

This is the code I used, I think the problem was that the velocity calculation was a bit off. Use it as a learning tool.
local player = game.Players.LocalPlayer
local char = player.Character
local torso = char:WaitForChild(“Torso”)

local function getMoveVector()
local moveVector = Vector3.new()
local input_x = player:GetMouse().X
local input_y = player:GetMouse().Y
moveVector = moveVector + Vector3.new(input_x, 0, input_y)
return moveVector.unit * 5
end

local function getWishDir()
local wishDir = Vector3.new()

local wishVel = getMoveVector()

local wishDirc = Vector3.new(wishVel.x, 0, wishVel.z)
-- Remove y component
wishDirc = wishDirc.unit * 5

return wishDirc

end

local function getVelocity()
local wishDir = getWishDir()
local wishVel = wishDir

local currentVel = torso.Velocity
local vel = Vector3.new()
vel = vel + wishVel
vel = vel - currentVel
vel = vel * 10

return vel

end

local function onInputBegan(input, processed)
if input.KeyCode == Enum.KeyCode.W then
torso.BodyVelocity.Velocity = torso.BodyVelocity.Velocity + getVelocity()
end
end

player.InputBegan:Connect(onInputBegan)

This code doesn’t really have the functionality I want. The problem with this code is that it just keeps on multiplying the velocity, so you get some really fast uncontrollable speeds.

What are you getting angry for? I just pointed out the flaw in your code.

The behavior of it is kinda weird. I had to make some adjustments because the code came with errors as well.

Well you see what the problem is and you are a competent coder so you will know what to do to fix it. Its clear that is multiplying at a crazy rate so stop it from doing that.

Why should I be the one to fix your code? Why did you give me broken code in the first place? I want to focus on what’s wrong with my code in this post.