Bhop (Universal)
Key RequiredUniversal Patched

Bhop (Universal)

Universal Scriptviralviral 15.7K views 136 executesUpdated Jan 16, 2022
1.7/ 5(3 votes)
1233% Positive
Lua Script•388 lines (10393 chars)
--script by Novik#5516 feel free to edit



local mv = {}
local player
local character
local collider
local camera
local input
local collider
local playerGrounded
local playerVelocity
local jumping
local moveInputSum
local dt = 1/60
local partYRatio
local partZRatio
local cameraYaw
local cameraLook
local movementPosition
local movementVelocity
local gravityForce

local airAccelerate
local airMaxSpeed --only limits projection of velocity onto acceleration
local groundAccelerate
local groundMaxVelocity --only limits projection of velocity onto acceleration
local friction
local playerTorsoToGround
local movementStickDistance
local jumpVelocity
local movementPositionForce
local movementVelocityForce
local maxMovementPitch
local rayYLength
local movementPositionD
local movementPositionP
local movementVelocityP
local gravity



function mv.init(Player, Camera, Input)
	player = Player
	character = player.Character
	collider = character.Torso
	camera = Camera
	input = Input
	playerVelocity = 0
	playerGrounded = false
	moveInputSum = {
	["forward"] = 0,
	["side"] 	= 0 --left is positive
	}
	
	airAccelerate 			= 5000
	airMaxSpeed 			= 20
	groundAccelerate 		= 25
	groundMaxVelocity 		= 400
	friction			 	= 10
	playerTorsoToGround 	= 3
	movementStickDistance 	= 0.5
	jumpVelocity 			= 80
	movementPositionForce	= 400000
	movementVelocityForce	= 3000000
	maxMovementPitch		= 0.6
	rayYLength				= playerTorsoToGround + movementStickDistance
	movementPositionD		= 125
	movementPositionP		= 14000
	movementVelocityP		= 15000
	gravity					= 0.4
	
end

function mv.initBodyMovers()
	movementPosition = Instance.new("BodyPosition", collider)
	movementPosition.Name = "movementPosition"
	movementPosition.D = movementPositionD
	movementPosition.P = movementPositionP
	movementPosition.maxForce = Vector3.new()
	movementPosition.position = Vector3.new()
	
	movementVelocity = Instance.new("BodyVelocity", collider)
	movementVelocity.Name = "movementVelocity"
	movementVelocity.P = movementVelocityP
	movementVelocity.maxForce = Vector3.new()
	movementVelocity.velocity = Vector3.new()
	
	gravityForce = Instance.new("BodyForce", collider)
	gravityForce.Name = "gravityForce"
	gravityForce.force = Vector3.new(0, (1-gravity)*196.2, 0) * getCharacterMass()
end

function mv.update(deltaTime)
	dt = deltaTime
	updateMoveInputSum()
	cameraYaw = getYaw()
	cameraLook = cameraYaw.lookVector	
	if cameraLook == nil then
		return
	end
	local hitPart, hitPosition, hitNormal, yRatio, zRatio = findCollisionRay()
	partYRatio = yRatio
	partZRatio = zRatio
	
	playerGrounded = hitPart ~= nil and true or false
	playerVelocity = collider.Velocity - Vector3.new(0, collider.Velocity.y, 0)
	if playerGrounded and (input["Space"] or jumping) then
		jumping = true
	else
		jumping = false
	end
	
	setCharacterRotation()
	if jumping then
		jump()
		print(math.random())
	elseif playerGrounded then
		run(hitPosition)
	else
		air()		
	end
	
end

function updateMoveInputSum()
	moveInputSum["forward"] = input["W"] == true and 1 or 0
	moveInputSum["forward"] = input["S"] == true and moveInputSum["forward"] - 1 or moveInputSum["forward"]
	moveInputSum["side"] = input["A"] == true and 1 or 0
	moveInputSum["side"] = input["D"] == true and moveInputSum["side"] - 1 or moveInputSum["side"]
end

function findCollisionRay()
	local torsoCFrame = character.Torso.CFrame
	local ignoreList = {character, camera}
	local rays = {
		Ray.new(character.Torso.Position, Vector3.new(0, -rayYLength, 0)),
		Ray.new((torsoCFrame * CFrame.new(-0.8,0,0)).p, Vector3.new(0, -rayYLength, 0)),
		Ray.new((torsoCFrame * CFrame.new(0.8,0,0)).p, Vector3.new(0, -rayYLength, 0)),
		Ray.new((torsoCFrame * CFrame.new(0,0,0.8)).p, Vector3.new(0, -rayYLength, 0)),
		Ray.new((torsoCFrame * CFrame.new(0,0,-0.8)).p, Vector3.new(0, -rayYLength, 0))
	}
	local rayReturns  = {}
	
	local i
	for i = 1, #rays do
		local part, position, normal = game.Workspace:FindPartOnRayWithIgnoreList(rays[i],ignoreList)
		if part == nil then
			position = Vector3.new(0,-3000000,0)
		end
		if i == 1 then
			table.insert(rayReturns, {part, position, normal})
		else
			local yPos = position.y
			if yPos <= rayReturns[#rayReturns][2].y then
				table.insert(rayReturns, {part, position, normal})
			else 
				local j
				for j = 1, #rayReturns do
					if yPos >= rayReturns[j][2].y then
						table.insert(rayReturns, j, {part, position, normal})
					end
				end
			end
		end
	end
	
	i = 1
	local yRatio, zRatio = getPartYRatio(rayReturns[i][3])
	while magnitude2D(yRatio, zRatio) > maxMovementPitch and i<#rayReturns do
		i = i + 1
		if rayReturns[i][1] then
			yRatio, zRatio = getPartYRatio(rayReturns[i][3])
		end
	end
	
	return rayReturns[i][1], rayReturns[i][2], rayReturns[i][3], yRatio, zRatio
end

function setCharacterRotation()
	local rotationLook = collider.Position + camera.CoordinateFrame.lookVector
	collider.CFrame = CFrame.new(collider.Position, Vector3.new(rotationLook.x, collider.Position.y, rotationLook.z))
	collider.RotVelocity = Vector3.new()
end

function jump()
	collider.Velocity = Vector3.new(collider.Velocity.x, jumpVelocity, collider.Velocity.z)
	air()
end

function air()
	movementPosition.maxForce = Vector3.new()
	movementVelocity.velocity = getMovementVelocity(collider.Velocity, airAccelerate, airMaxSpeed)
	movementVelocity.maxForce = getMovementVelocityAirForce()
end

function run(hitPosition)
	local playerSpeed = collider.Velocity.magnitude
	local mVelocity = collider.Velocity
	
	if playerSpeed ~= 0 then
		local drop = playerSpeed * friction * dt;
		mVelocity = mVelocity * math.max(playerSpeed - drop, 0) / playerSpeed;
	end
	
	movementPosition.position = hitPosition + Vector3.new(0,playerTorsoToGround,0)
	movementPosition.maxForce = Vector3.new(0,movementPositionForce,0)
	movementVelocity.velocity = getMovementVelocity(mVelocity, groundAccelerate, groundMaxVelocity)
	local VelocityForce = getMovementVelocityForce()
	movementVelocity.maxForce = VelocityForce
	movementVelocity.P = movementVelocityP
end

function getMovementVelocity(prevVelocity, accelerate, maxVelocity)
	local accelForward = cameraLook * moveInputSum["forward"]
	local accelSide = (cameraYaw * CFrame.Angles(0,math.rad(90),0)).lookVector * moveInputSum["side"];
	local accelDir = (accelForward+accelSide).unit;
	if moveInputSum["forward"] == 0 and moveInputSum["side"] == 0 then --avoids divide 0 errors
		accelDir = Vector3.new(0,0,0);
	end
	
	local projVel =  prevVelocity:Dot(accelDir);
	local accelVel = accelerate * dt;
	
	if (projVel + accelVel > maxVelocity) then
		accelVel = math.max(maxVelocity - projVel, 0);
	end
	
	return prevVelocity + accelDir * accelVel;
end

function getMovementVelocityForce()

	return Vector3.new(movementVelocityForce,0,movementVelocityForce)
end

function getMovementVelocityAirForce()
	local accelForward = cameraLook * moveInputSum["forward"];
	local accelSide = (cameraYaw * CFrame.Angles(0,math.rad(90),0)).lookVector * moveInputSum["side"]
	local accelDir = (accelForward+accelSide).unit
	if moveInputSum["forward"] == 0 and moveInputSum["side"] == 0 then
		accelDir = Vector3.new(0,0,0);
	end
	
	local xp = math.abs(accelDir.x)
	local zp = math.abs(accelDir.z)
	
	return Vector3.new(movementVelocityForce*xp,0,movementVelocityForce*zp)
end

function getPartYRatio(normal)
	local partYawVector = Vector3.new(-normal.x, 0, -normal.z)
	if partYawVector.magnitude == 0 then
		return 0,0
	else
		local partPitch = math.atan2(partYawVector.magnitude,normal.y)/(math.pi/2)
		local vector = Vector3.new(cameraLook.x, 0, cameraLook.z)*partPitch
		return vector:Dot(partYawVector), -partYawVector:Cross(vector).y
	end	
end

function getYaw() --returns CFrame
	return camera.CoordinateFrame*CFrame.Angles(-getPitch(),0,0)
end

function getPitch() --returns number
	return math.pi/2 - math.acos(camera.CoordinateFrame.lookVector:Dot(Vector3.new(0,1,0)))
end

function getCharacterMass()
	return character.Torso:GetMass() + character.Head:GetMass()
end

function magnitude2D(x,z)
	return math.sqrt(x*x+z*z)
end

--note: this only works with filtering enabled

local player = game.Players.LocalPlayer
local camera = game.Workspace.CurrentCamera
local UserInputService = game:GetService("UserInputService")

local prevUpdateTime = nil
local updateDT = 1/60
local inputKeys = {
	["W"] = false,
	["S"] = false,
	["A"] = false,
	["D"] = false,
	["Space"] = false,
	["LMB"] = false,
	["RMB"] = false
}

function main()
	-- character spawning bs
	if player:FindFirstChild("customCharacterSpawned") == nil then
		local newval = Instance.new("BoolValue", player);
		newval.Name = "customCharacterSpawned";
		newval.Value = false;
	end
	
	if not player.customCharacterSpawned.Value then
		player.customCharacterSpawned.Value = true;
		return;
	end
	
	player.Character:WaitForChild("Humanoid");
	--remove hats for physics sake
	huckFats();
	spawn(function()
		while player.Character do
			wait(1)
			huckFats();
		end
	end)
	
	--init movement
	mv.init(player, camera, inputKeys);
	mv.initBodyMovers();
	
	--display poop

	
	--connect input
	UserInputService.InputBegan:connect(onInput);
	UserInputService.InputEnded:connect(onInput);
	
	--connect updateloop
	game:GetService("RunService"):BindToRenderStep("updateLoop", 1, updateLoop);
	
	--rip
	player.Character.Humanoid.Died:connect(onDeath)
end

function updateLoop()
	setDeltaTime();
	mv.update(updateDT);
end

function huckFats()
	for _,v in pairs (player.Character:GetChildren()) do
		if v:IsA("Hat") then
			v:Destroy()
		end
	end
end

function setDeltaTime() --seconds
	local UpdateTime = tick() 
	if prevUpdateTime ~= nil then
		updateDT = (UpdateTime - prevUpdateTime)
	else
		updateDT = 1/60
	end
	prevUpdateTime = UpdateTime
end

function onInput(input, gameProcessedEvent)
	local inputState
	--print(input.KeyCode)
	if input.UserInputState == Enum.UserInputState.Begin then
		inputState = true
	elseif input.UserInputState == Enum.UserInputState.End then
		inputState = false
	else
		return
	end 
	
	if input.UserInputType == Enum.UserInputType.Keyboard then
		local key = input.KeyCode.Name
		if inputKeys[key] ~= nil then
			inputKeys[key] = inputState
		end
	elseif input.UserInputType == Enum.UserInputType.MouseButton1 then --LMB down
		inputKeys.LMB = inputState
	elseif input.UserInputType == Enum.UserInputType.MouseButton2 then --RMB down
		inputKeys.RMB = inputState
	end
end

function onDeath()
	player.customCharacterSpawned = false
end

main()

Features & Information

Bhop at mach 5
#Bhop

Community Comments (2)

AdriaD2103AdriaD2103Jan 16, 2022(edited)

Patched

CandyLeanCandyLeanJan 17, 2022(edited)

dam this **** got patched, been looking for a while for a bhop script tho

More Scripts for Universal Scripts