Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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()
- end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement