Sword Pogo mechanic behaving weirdly

I’m trying to make a Sword Pogo mechanic for my Movement shooter game, but its behaving weirdly and I don’t know how to fix it.

My previous code worked fairly well, but when I was moving forward and I trying to pogo in the ground while falling, my horizontal speed would get resetted. I made it so that horizontal and vertical speeds was separated so there was the option for one of them to be preserved, but it still didn’t worked and “dotxz” was -1 when going forward, but 1 when backwards, which I don’t know why, but I think its due to the fact that you can’t fully look down so when going backwards you’re actually aiming a bit forward.

Another problem also appears which if I am trying to pogo out of a wall while aiming diagonally and falling, I go up but I don’t get sended away, but this doesn’t happen when I have upwards momentum.

As I said, I have tried to separate horizontal momentum from vertical, but it just caused more problems and made me more confused. I tried to switch some values but it still didn’t worked

Video on where I don’t get launched away from pogoing diagonally and where I start to pogo forward and backwards:

robloxapp-20241224-1651425.wmv (2.2 MB)

You can’t see it on the video but when I start to pogo forward, it says that dotxz is -1, meaning that my speed gets set, but when I start to go backwards it says that dotxz is 1, so my speed gets added. Also, yes, the horizontal speed IS getting resetted, its just not very apparent because I wasn’t moving very fast, but when you are you gonna notice it instantly

Also, here’s the full code (note that its a local script)

local player = game:GetService("Players").LocalPlayer
local UIS = game:GetService("UserInputService")
local debris = game:GetService("Debris")
local db = true

UIS.InputBegan:Connect(function(inp,gpe)
	--print("A")

	if not gpe and inp.KeyCode == Enum.KeyCode.F then
		--print("B")

		if db == true then --Checks if not on cooldown
			db = false

			--print("C")

			local origin = workspace.Camera.CFrame.Position
			local dir = workspace.Camera.CFrame.LookVector*10
			local params = RaycastParams.new()
			local hitted = {}
			local phum = player.Character:FindFirstChildWhichIsA("Humanoid")
			

			params.FilterType = Enum.RaycastFilterType.Exclude
			params.FilterDescendantsInstances = {player.Character}

			local raycast = workspace:Raycast(origin,dir,params)

			local hitbox = workspace:GetPartBoundsInBox(workspace.Camera.CFrame+dir,Vector3.new(5,5,10))

			if raycast and phum.FloorMaterial == Enum.Material.Air then --Sees if the raycast hitted anything and if the player is on the air
				--print("Pogo")

				local vel = player.Character.PrimaryPart.AssemblyLinearVelocity

				local xz = Vector3.new(vel.X,0,vel.Z)
				local dirxz = Vector3.new(dir.X,0,dir.Z)
				
				local y = Vector3.new(0,vel.Y,0)
				local diry = Vector3.new(0,dir.Y,0)

				local dotxz = xz.Unit:Dot(-dirxz.Unit)
				local doty = y.Unit:Dot(-diry.Unit)
				
				local alv = player.Character.PrimaryPart.AssemblyLinearVelocity

				print(dotxz.."xz")
				print(doty.."y")

				--If the player is moving along the pogo velocity it adds to the speed
				--If the player is moving the opposite direction of the pogo velocity, it sets the speed

				--It is coded with XZ being separate of Y so that horizontal and vertical momentum can be preserved

				if dotxz >= 0 then
					player.Character.PrimaryPart.AssemblyLinearVelocity += Vector3.new(-dir.X*3.5,0,-dir.Z*3.5)
				else
					player.Character.PrimaryPart.AssemblyLinearVelocity = Vector3.new(-dir.X*7,alv.Y,-dir.Z*7)
				end
				
				if doty >= 0 then
					player.Character.PrimaryPart.AssemblyLinearVelocity += Vector3.new(0,-dir.Y*3.5,0)
				else
					player.Character.PrimaryPart.AssemblyLinearVelocity = Vector3.new(alv.X,-dir.Y*7,alv.Z)
				end
			end

			for i,obj in hitbox do
				local humanoid = obj.Parent:FindFirstChildWhichIsA("Humanoid")
				
				if humanoid and not game.Players:GetPlayerFromCharacter(obj.Parent) then
					if not hitted[obj.Parent] and obj.Parent.Name ~= "Armss" then
						hitted[obj.Parent] = obj.Parent
						game.ReplicatedStorage.Damage:FireServer(humanoid,20)
					end
				end

				if obj.Name == "PH" then --Checks if it has a parry hitbox
					local inv = Instance.new("ForceField",player.Character)

					local hittt = workspace:Raycast(origin,dir*50,params)

					if hittt then
						hittt = hittt.Position
					else
						hittt = origin+workspace.Camera.CFrame.LookVector*500
					end

					inv.Visible = false

					debris:AddItem(inv,0.1)

					print("parry")

					game.ReplicatedStorage.Parry:FireServer(obj,hittt)

					break
				end
			end

			task.wait(1)
			db = true
		end
	end
end)

So… does anyone know a fix to this?

Nevermind, I have found a solution

Here’s the code if you’re curious:

if raycast and phum.FloorMaterial == Enum.Material.Air then --Sees if the raycast hitted anything and if the player is on the air
	--print("Pogo")

	local vel = player.Character.PrimaryPart.AssemblyLinearVelocity

	local xz = Vector3.new(vel.X,0,vel.Z)
	local dirxz = Vector3.new(dir.X,0,dir.Z)
				
	local y = Vector3.new(0,vel.Y,0)
	local diry = Vector3.new(0,dir.Y,0)

	local dotxz = xz.Magnitude > 0 and xz.Unit:Dot(-dirxz.Unit) or 0
	local doty = y.Magnitude > 0 and y.Unit:Dot(-diry.Unit) or 0
				
	local alv = player.Character.PrimaryPart.AssemblyLinearVelocity

	print(dotxz.."xz")
	print(doty.."y")

	--If the player is moving along the pogo velocity it adds to the speed
	--If the player is moving the opposite direction of the pogo velocity, it sets the speed

	--It is coded with XZ being separate of Y so that horizontal and vertical momentum can be preserved

	if math.round(workspace.CurrentCamera.CFrame.LookVector.Y) == 1 then
		--I can't make the camera look straight down so my code naturally works
		--It returns dotxz as 1 because you can't look less than 81 degrees down
		--So I instead just checked if the player is looking down enough (~78 degrees down is enough to trigger this)
					
		dotxz = 1
	end

	if dotxz >= 0 then
		player.Character.PrimaryPart.AssemblyLinearVelocity += Vector3.new(-dir.X*7,0,-dir.Z*7)
	else
		player.Character.PrimaryPart.AssemblyLinearVelocity = Vector3.new(-dir.X*7,alv.Y,-dir.Z*7)
	end
				
	alv = player.Character.PrimaryPart.AssemblyLinearVelocity --Updates the alv so that the next change doesn't use the old one and thus resets horizontal movement

	if doty >= 0 then
		player.Character.PrimaryPart.AssemblyLinearVelocity += Vector3.new(0,-dir.Y*3.5,0)
	else
		player.Character.PrimaryPart.AssemblyLinearVelocity = Vector3.new(alv.X,-dir.Y*7,alv.Z)
	end
end

Basically I just made it so that if the player is looking 78 degrees down dotxz turns to 1 so horizontal movement is preserved and I updated the value used for the player assembly linear velocity so that of the doty part calculations it doesn’t use the old value and cancel the horizontal velocity

There’s two problems with this solution though:

  1. If the player gets launched really fast towards a wall diagonally and he somehow manages to pogo up out of the wall, horizontal movement will be set and vertical will be preserved, and since vertical speed is way higher than horizontal, it will seem like the player got send to jesus (i.e launched up really fast)

  2. Since you don’t have to look straight down to trigger the dotxz = 1, and you can’t really look 100% down anyways, you could dash along a big wall and just look straight down and both get horizontal and vertical speed preserved and increased (so you could just build up speed), and while you could replicate this even if this wasn’t the case by aiming on a precise angle, its way easier to do this way

But let’s be honest, those are not really bugs are they? If anything they just make my movement game cooler (saying its a intended game mechanic treatment)