Advertisement
forsakenxn

bunny hop script

Nov 5th, 2024
2,319
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 25.49 KB | None | 0 0
  1. --- made by forsaken c:
  2.  
  3. workspace.Gravity = 100
  4.  
  5.  
  6. local Config = {
  7.  
  8.     --[[General]]
  9.     VISUALIZE_FEET_HB = false, -- Visualize Feet Hitbox
  10.     VISUALIZE_COLLIDE_AND_SLIDE = false,
  11.     STEP_OFFSET = 1.2,
  12.     MASS = 16,
  13.     AIR_FRICTION = 0.4,
  14.     FRICTION = 6,
  15.     GRAVITY = 10,
  16.     JUMP_VELOCITY = 30,
  17.  
  18.     --[[Accel/Deccel]]
  19.     GROUND_ACCEL = 14,
  20.     GROUND_DECCEL = 10,
  21.     AIR_ACCEL = 52,
  22.  
  23.     --[[General Speed]]
  24.     AIR_SPEED = 42,
  25.     RUN_SPEED = 32,
  26.     WALK_SPEED = 10,
  27.     CROUCH_SPEED = 10,
  28.  
  29.     --[[Advanced Speed]]
  30.     AIR_MAX_SPEED = 36.5,        -- The speed at which AIR_MAX_SPEED_FRIC is applied.
  31.     AIR_MAX_SPEED_FRIC = 3,      -- The initial friction applied at max speed
  32.     AIR_MAX_SPEED_FRIC_DEC = .5, -- Amount multiplied to current max speed friction per 1/60sec
  33.     MIN_SLOPE_ANGLE = 40,
  34.     MAX_SLOPE_ANGLE = 75,
  35.  
  36.     --[[Misc (Don't worry about these)]]
  37.     LEG_HEIGHT = 1.9+.3,
  38.     TORSO_TO_FEET = 3.1+1.9,
  39.     FEET_HB_SIZE = Vector3.new(1,0.1,1),
  40.     TORSO_HB_SIZE = Vector3.new(3,1,3),
  41.     FOOT_OFFSET_AMOUNT = 1.2
  42. }
  43.  
  44. local RunService = game:GetService("RunService")
  45. local UserInputService = game:GetService("UserInputService")
  46.  
  47. local ids = {
  48.     "rbxassetid://7338942417",
  49.     "rbxassetid://7338942345",
  50.     "rbxassetid://7338942259",
  51.     "rbxassetid://7338942180",
  52.     "rbxassetid://7338942417",
  53. }
  54. local sounds = {}
  55.  
  56. for _, i in ipairs(ids) do
  57.     local sound = Instance.new("Sound")
  58.     sound.SoundId = i
  59.     sound.Volume = 2
  60.     sound.Parent = game.Workspace  -- Or another appropriate parent
  61.     table.insert(sounds, sound)
  62. end
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69. export type Movement = {
  70.     Keys: {W: number, A: number, S: number, D: number, Space: number},
  71.  
  72.     player: Player,
  73.     character: Model,
  74.     collider: Part,
  75.     vispart: Part?,
  76.     vis_coll_parts: {Part},
  77.     config: MovementConfig,
  78.     mover: LinearVelocity,
  79.     up_mover: LinearVelocity,
  80.     dt: number,
  81.     states: MovementStates,
  82. }
  83.  
  84. export type MovementConfig = {
  85.     VISUALIZE_FEET_HB: boolean,
  86.     VISUALIZE_COLLIDE_AND_SLIDE: boolean,
  87.     LEG_HEIGHT: number,
  88.     FEET_HB_SIZE: Vector3,
  89.     TORSO_HB_SIZE: Vector3,
  90.  
  91.     MASS: number,
  92.     GRAVITY: number,
  93.     FRICTION: number,
  94.     AIR_FRICTION: number,
  95.  
  96.     GROUND_ACCEL: number,
  97.     GROUND_DECCEL: number,
  98.     AIR_ACCEL: number,
  99.  
  100.     RUN_SPEED: number,
  101.     WALK_SPEED: number,
  102.     CROUCH_SPEED: number,
  103.     AIR_SPEED: number,
  104.  
  105.     AIR_MAX_SPEED: number,
  106.     AIR_MAX_SPEED_FRIC: number,
  107.     AIR_MAX_SPEED_FRIC_DEC: number,
  108.  
  109.     JUMP_VELOCITY: number,
  110.  
  111.     STEP_OFFSET: number,
  112.     TORSO_TO_FEET: number,
  113.  
  114.     MIN_SLOPE_ANGLE: number,
  115.     MAX_SLOPE_ANGLE: number,
  116. }
  117.  
  118. export type MovementStates = {
  119.     grounded: boolean,
  120.     air_friction: number,
  121.     input_vec: number,
  122.     surfing: boolean,
  123.     jumping: boolean,
  124. }
  125.  
  126. export type Vec3Mod = {x: number, y: number, z: number, ToVector3: (Vec3Mod) -> Vector3}
  127. local Vec3Mod = {}
  128. Vec3Mod.__index = Vec3Mod
  129.  
  130. function Vec3Mod.new(input: Vector3?) : Vec3Mod
  131.     input = input or Vector3.zero
  132.     return setmetatable({x = input.X, y = input.Y, z = input.Z}, Vec3Mod) :: Vec3Mod
  133. end
  134.  
  135. function Vec3Mod:ToVector3()
  136.     return Vector3.new(self.x, self.y, self.z)
  137. end
  138.  
  139. local Movement: Movement = {}
  140. local Physics = {} :: Movement
  141. local Shared  : Movement= {}
  142. local Trace : Movement= {}
  143. local Collisions = {} :: Movement
  144.  
  145. local function visualizeRayResult(result: RaycastResult, origin: Vector3, direction: Vector3)
  146.     local position = result and result.Position or (origin + direction)
  147.     local distance = (origin - position).Magnitude
  148.     local p = Instance.new("Part")
  149.     p.Anchored = true
  150.     p.CanCollide = false
  151.     p.Size = Vector3.new(0.1, 0.1, distance)
  152.     p.CFrame = CFrame.lookAt(origin, position)*CFrame.new(0, 0, -distance/2)
  153.     p.Parent = workspace.Temp
  154.     return p
  155. end
  156.  
  157. local function flattenVectorAgainstWall(moveVector: Vector3, normal: Vector3)
  158.     -- if magnitudes are 0 then just nevermind
  159.     if moveVector.Magnitude == 0 and normal.Magnitude == 0 then
  160.         return Vector3.zero
  161.     end
  162.  
  163.     -- unit the normal (i its already normalized idk)
  164.     normal = normal.Unit
  165.  
  166.     -- reflect the vector
  167.     local reflected = moveVector - 2 * moveVector:Dot(normal) * normal
  168.     -- add the reflection to the move vector = vector parallel to wall
  169.     local parallel = moveVector + reflected
  170.  
  171.     -- if magnitude 0 NEVERMIND!!!
  172.     if parallel.Magnitude == 0 then
  173.         return Vector3.zero
  174.     end
  175.  
  176.     -- reduce the parallel vector to make sense idk HorseNuggetsXD did all this thank u
  177.     local cropped = parallel.Unit:Dot(moveVector.Unit) * parallel.Unit * moveVector.Magnitude
  178.     return cropped
  179. end
  180.  
  181. function Collisions:CollideAndSlide(wishedSpeed: Vector3)
  182.     local mod = 1
  183.  
  184.     if wishedSpeed.Magnitude == 0 then
  185.         return wishedSpeed
  186.     end
  187.  
  188.     -- get input vector
  189.     local inputVec = self.states.input_vec
  190.     local newSpeed = wishedSpeed
  191.     local hrp = self.player.Character.HumanoidRootPart
  192.  
  193.     -- raycast var
  194.     local params = Shared.GetMovementParams(self)
  195.  
  196.     -- wished speed modifier
  197.     wishedSpeed *= 2
  198.  
  199.     -- direction amount var
  200.     local dirAmnt = 1.375 * (mod or 1)
  201.     local mainDirAmnt = 1.55 * (mod or 1)
  202.  
  203.     -- stick var
  204.     local isSticking = false
  205.     local normals = {}
  206.     local stickingDirections = {}
  207.     local ldd = {dir = false, dist = false} -- lowest distance direction
  208.     local partsAlreadyHit = {}
  209.  
  210.     -- destroy sticking visualizations
  211.     if Config.VISUALIZE_COLLIDE_AND_SLIDE then
  212.         for _, v in pairs(self.vis_coll_parts) do
  213.             v:Destroy()
  214.         end
  215.     end
  216.  
  217.     local lookVecs = {
  218.         Vector3.new(0, (-Config.TORSO_TO_FEET) + Config.STEP_OFFSET, 0),
  219.         Vector3.new(0, 0, 0),
  220.         Vector3.new(0, 2, 0)
  221.     }
  222.  
  223.     for _, v in pairs(lookVecs) do
  224.         local values = {}
  225.         local hval = {}
  226.         local currForDir
  227.         local currSideDir
  228.         local rayPos
  229.  
  230.         if typeof(v) == "Vector3" then
  231.             rayPos = hrp.Position + v
  232.         else
  233.             rayPos = Vector3.new(hrp.Position.X, hrp.Parent[v].CFrame.Position, hrp.Position.Z)
  234.         end
  235.  
  236.         -- right, front, back
  237.         if inputVec.X > 0 then
  238.             currForDir = hrp.CFrame.RightVector
  239.             table.insert(values, currForDir)
  240.             table.insert(hval, hrp.CFrame.LookVector * dirAmnt)
  241.             table.insert(hval, -hrp.CFrame.LookVector * dirAmnt)
  242.             -- left, front, back
  243.         elseif inputVec.X < 0 then
  244.             currForDir = -hrp.CFrame.RightVector
  245.             table.insert(values, currForDir)
  246.             table.insert(hval, hrp.CFrame.LookVector * dirAmnt)
  247.             table.insert(hval, -hrp.CFrame.LookVector * dirAmnt)
  248.         end
  249.  
  250.         -- back, left, right
  251.         if inputVec.Z > 0 then
  252.             currSideDir = -hrp.CFrame.LookVector
  253.             table.insert(values, currSideDir)
  254.             table.insert(hval, hrp.CFrame.RightVector * dirAmnt)
  255.             table.insert(hval, -hrp.CFrame.RightVector * dirAmnt)
  256.             -- front, left, right
  257.         elseif inputVec.Z < 0 then
  258.             currSideDir = hrp.CFrame.LookVector
  259.             table.insert(values, currSideDir)
  260.             table.insert(hval, hrp.CFrame.RightVector * dirAmnt)
  261.             table.insert(hval, -hrp.CFrame.RightVector * dirAmnt)
  262.         end
  263.  
  264.  
  265.         if inputVec.Z == 0 and inputVec.X == 0 then
  266.             values[1] = wishedSpeed.Unit
  267.             table.insert(hval, CFrame.new(wishedSpeed.Unit).RightVector * dirAmnt)
  268.             table.insert(hval, -CFrame.new(wishedSpeed.Unit).RightVector * dirAmnt)
  269.         else
  270.             table.insert(values, wishedSpeed.Unit * dirAmnt)
  271.         end
  272.  
  273.         -- middle directions
  274.         if currForDir and currSideDir then
  275.             for a, b in pairs(values) do
  276.                 values[a] = b * mainDirAmnt
  277.             end
  278.             table.insert(values, (currForDir+currSideDir) * mainDirAmnt)
  279.         else
  280.             values[1] *= mainDirAmnt
  281.             table.insert(values, (values[1] + hval[1]).Unit * mainDirAmnt)
  282.             table.insert(values, (values[1] + hval[2]).Unit * mainDirAmnt)
  283.             table.insert(values, hval[1])
  284.             table.insert(values, hval[2])
  285.         end
  286.  
  287.         for _, b in pairs(values) do
  288.             if not b then continue end
  289.  
  290.             -- visualize ray using pos and direction
  291.             if Config.VISUALIZE_COLLIDE_AND_SLIDE then
  292.                 table.insert(self.vis_coll_parts, visualizeRayResult(false, rayPos, b))
  293.             end
  294.  
  295.             local result = workspace:Raycast(rayPos, b, params)
  296.             if not result then continue end
  297.  
  298.             if (not ldd.dir or not ldd.dist) or (ldd.dist and ldd.dist < result.Distance) then
  299.                 ldd.dir = b
  300.                 ldd.dist = result.Distance
  301.             end
  302.  
  303.             -- don't collide with the same part twice
  304.             if table.find(partsAlreadyHit, result.Instance) then continue end
  305.             table.insert(partsAlreadyHit, result.Instance)
  306.  
  307.             -- get the movement direction compared to the wall
  308.             local _v =  newSpeed.Unit * result.Normal
  309.  
  310.             -- find active coordinate of comparison
  311.             for _, c in pairs({_v.X, _v.Y, _v.Z}) do
  312.                 if math.abs(c) > 0 then
  313.                     _v = c
  314.                     break
  315.                 end
  316.             end
  317.  
  318.             -- if we are moving AWAY from the normal, (positive)
  319.             -- then do not flatten the vector.
  320.  
  321.             -- it's not necessary.
  322.             -- you will stick.
  323.             -- stick.
  324.  
  325.             if type(_v) == "number" and _v > 0 then
  326.                 continue
  327.             end
  328.  
  329.             if not isSticking then isSticking = true end
  330.             newSpeed = flattenVectorAgainstWall(newSpeed, result.Normal)
  331.             newSpeed -= result.Instance.Velocity
  332.  
  333.             self.mover.PlaneVelocity = Vector2.new(newSpeed.X, newSpeed.Z)
  334.             --self.collider.Velocity = Vector3.new(newSpeed.X, (self.collider.Velocity.Y), newSpeed.Z) -- anti sticking has to be applied on collider velocity as well (resolves head & in air collision)
  335.         end
  336.     end
  337.  
  338.     return newSpeed, isSticking and normals, isSticking and stickingDirections, isSticking and ldd.dir
  339. end
  340.  
  341.  
  342. export type Trace = {
  343.     startPos: Vector3,
  344.     endPos: Vector3,
  345.  
  346.  
  347.     fraction: number,
  348.     startSolid: boolean,
  349.     hitPart: Instance,
  350.     hitPoint: Vector3,
  351.     planeNormal: Vector3,
  352.     distance: number
  353. }
  354.  
  355. local function HandleVisualization(self, cf, size)
  356.     if not Config.VISUALIZE_FEET_HB then
  357.         return
  358.     end
  359.     if not self.vispart then
  360.         self.vispart = Instance.new("Part", self.character)
  361.         self.vispart.CanCollide = false
  362.         self.vispart.Anchored = true
  363.     end
  364.  
  365.     self.vispart.CFrame = cf
  366.     self.vispart.Size = size
  367. end
  368.  
  369. function Shared.GetAngle(normal)
  370.     return math.deg(math.acos(normal:Dot(Vector3.yAxis)))
  371. end
  372.  
  373. function Shared:IsGrounded(dir): (boolean, boolean?, RaycastResult?, number?)
  374.     local params = Shared.GetMovementParams(self)
  375.     local cf = CFrame.new(self.collider.Position) - Vector3.new(0, self.collider.Size.Y/2, 0)
  376.     local size = Config.FEET_HB_SIZE
  377.     dir = dir or Vector3.new(0,-1 * self.collider.Size.Y-Config.FOOT_OFFSET_AMOUNT,0)
  378.  
  379.     local result = workspace:Blockcast(cf, size, dir, params)
  380.  
  381.     HandleVisualization(self, cf, size)
  382.  
  383.     if not result then
  384.         return false
  385.     end
  386.  
  387.     local steepness = Shared.GetAngle(result.Normal)
  388.     local isSurfing = steepness >= Config.MIN_SLOPE_ANGLE and steepness <= Config.MAX_SLOPE_ANGLE
  389.     if isSurfing then
  390.         return false, true, result, steepness
  391.     end
  392.  
  393.     return true, false, result
  394. end
  395.  
  396. function Shared:RotateCharacter()
  397.     local collider = self.collider
  398.     local camera = workspace.CurrentCamera
  399.     local rotationLook = collider.Position + camera.CoordinateFrame.lookVector
  400.     collider.CFrame = CFrame.new(collider.Position, Vector3.new(rotationLook.x, collider.Position.y, rotationLook.z))
  401.     collider.RotVelocity = Vector3.new()
  402. end
  403.  
  404. function Shared:GetMovementDirection(groundNormal)
  405.     local forward = self.Keys.W + -self.Keys.S
  406.     local side = self.Keys.A + -self.Keys.D
  407.     groundNormal = groundNormal or Vector3.new(0,1,0)
  408.  
  409.     if forward == 0 and side == 0 then
  410.         self.states.input_vec = Vector3.zero
  411.         return Vector3.zero
  412.     else
  413.         self.states.input_vec = Vector3.new(-side, 0, -forward).Unit
  414.         local forwardMove = groundNormal:Cross(self.collider.CFrame.RightVector)
  415.         local sideMove = groundNormal:Cross(forwardMove)
  416.         return (forwardMove * forward + sideMove * side).Unit
  417.     end
  418. end
  419.  
  420. function Shared:GetMovementParams()
  421.     local params = RaycastParams.new()
  422.     params.FilterDescendantsInstances = {self.character, workspace.CurrentCamera}
  423.     params.FilterType = Enum.RaycastFilterType.Exclude
  424.     params.RespectCanCollide = false
  425.     params.CollisionGroup = "PlayerMovement"
  426.     return params
  427. end
  428.  
  429. function Shared:VectorMa(start: Vector3, scale: number, direction: Vector3)
  430.     return Vector3.new(
  431.         start.X + direction.X * scale,
  432.         start.Y + direction.Y * scale,
  433.         start.Z + direction.Z * scale
  434.     )
  435. end
  436.  
  437.  
  438. local Trace: Movement = {}
  439.  
  440. local numBumps = 1
  441. local maxClipPlanes = 5
  442. local _planes = {}
  443.  
  444. local numToCoord = {"X", "Y", "Z"}
  445.  
  446. local function ClipVelocity(self, input, normal, output, overbounce)
  447.     local newVelMod = Vec3Mod.new(output)
  448.     Trace.ClipVelocity(self, input, normal, newVelMod, overbounce)
  449.     return newVelMod:ToVector3()
  450. end
  451.  
  452. function Trace:TraceBox(start: Vector3, destination: Vector3)
  453.     local contactOffset = 0.1 -- idk what this is
  454.  
  455.     local longSide = math.sqrt(contactOffset * contactOffset + contactOffset * contactOffset)
  456.     local direction = (destination - start).Unit
  457.     local maxDistance = (start - destination).Magnitude + longSide
  458.  
  459.     local result: Trace = {
  460.         startPos = start,
  461.         endPos = destination
  462.     }
  463.  
  464.     local _, _, hit = Shared.IsGrounded(self, direction*maxDistance)
  465.     if hit then
  466.         result.fraction = hit.Distance / maxDistance
  467.         result.hitPart = hit.Instance
  468.         result.hitPoint = hit.Position
  469.         result.planeNormal = hit.Normal
  470.         result.distance = hit.Distance
  471.     else
  472.         result.fraction = 1
  473.     end
  474.  
  475.     return result
  476. end
  477.  
  478. function Trace:ClipVelocity(input: Vector3, normal: Vector3, output: Types.Vec3Mod, overbounce: number)
  479.     local angle = normal.Y
  480.     local blocked = 0x00     -- // Assume unblocked.
  481.  
  482.     if angle > 0 then -- // If the plane that is blocking us has a positive z component, then assume it's a floor.
  483.         blocked = blocked or 0x01
  484.     end
  485.  
  486.     if angle == 0 then -- // If the plane has no Z, it is vertical (wall/step)
  487.         blocked = blocked or 0x02
  488.     end
  489.  
  490.     -- // Determine how far along plane to slide based on incoming direction.
  491.     local backoff = input:Dot(normal) * overbounce
  492.  
  493.     --// iterate once to make sure we aren't still moving through the plane
  494.     for i = 1, 3, 1 do
  495.         local ci = numToCoord[i]
  496.         local change = normal[ci] * backoff
  497.         output[ci] = input[ci] - change
  498.     end
  499.  
  500.     local adjust = output:ToVector3():Dot(normal)
  501.     if adjust < 0 then
  502.         output = output:ToVector3()-(normal * adjust)
  503.     end
  504.  
  505.     -- Return blocking flags.
  506.     return blocked
  507. end
  508.  
  509. function Trace:Reflect(velocity: Vector3, origin: Vector3)
  510.  
  511.     self = self :: Movement
  512.  
  513.     local d
  514.     local newVelocity = Vector3.zero
  515.     local blocked = 0
  516.     local numplanes = 1
  517.     local originalVelocity = velocity
  518.     local primalVelocity = velocity
  519.  
  520.     local allFraction = 0
  521.     local timeLeft = self.dt
  522.  
  523.     for bumpcount = 1, numBumps, 1 do
  524.  
  525.         if velocity.Magnitude == 0 then
  526.             break
  527.         end
  528.  
  529.         -- Assume we can move all the way from the current origin to the
  530.         --  end point.
  531.         local endp = Shared.VectorMa(self, origin, timeLeft, velocity)
  532.         local trace = Trace.TraceBox(self, origin, endp)
  533.         allFraction += trace.fraction
  534.  
  535.         if trace.fraction > 0 then
  536.             -- actually covered some distance
  537.             originalVelocity = velocity
  538.             numplanes = 0
  539.         end
  540.  
  541.         -- If we covered the entire distance, we are done
  542.         --  and can return.
  543.         if trace.fraction == 1 then
  544.             break
  545.         end -- moved the entire distance
  546.  
  547.         -- If the plane we hit has a high z component in the normal, then
  548.         --  it's probably a floor
  549.         if trace.planeNormal.Y > Config.MAX_SLOPE_ANGLE then
  550.             blocked = blocked or 1
  551.         end
  552.  
  553.         -- If the plane has a zero z component in the normal, then it's a
  554.         --  step or wall
  555.         if trace.planeNormal.Y == 0 then
  556.             blocked = blocked or 2 -- step/wall
  557.         end
  558.  
  559.         -- Reduce amount of m_flFrameTime left by total time left * fraction
  560.         --  that we covered.
  561.         timeLeft -= timeLeft * trace.fraction
  562.  
  563.  
  564.         -- Did we run out of planes to clip against?
  565.         if numplanes >= maxClipPlanes then
  566.             -- this shouldn't really happen
  567.             --  Stop our movement if so.
  568.             velocity = Vector3.zero
  569.             break
  570.         end
  571.  
  572.         -- Set up next clipping plane
  573.         _planes[numplanes] = trace.planeNormal
  574.         numplanes+=1
  575.  
  576.         -- modify original_velocity so it parallels all of the clip planes
  577.         --
  578.  
  579.         -- reflect player velocity
  580.         -- Only give this a try for first impact plane because you can get yourself stuck in an acute corner by jumping in place
  581.         --  and pressing forward and nobody was really using this bounce/reflection feature anyway...
  582.         if numplanes == 2 then
  583.             if _planes[1].Y > Config.MAX_SLOPE_ANGLE then
  584.                 return blocked
  585.             else
  586.                 newVelocity = ClipVelocity(self, originalVelocity, _planes[1], newVelocity, 1)
  587.             end
  588.             velocity = newVelocity
  589.             originalVelocity = newVelocity
  590.         else
  591.             local _i = 0
  592.             for i = 1, numplanes-1, 1 do
  593.                 _i = i
  594.  
  595.                 newVelocity = ClipVelocity(self, originalVelocity, _planes[i], newVelocity, 1)
  596.  
  597.                 local _j = 0
  598.                 for j = 1, numplanes-1, 1 do
  599.                     _j = j
  600.                     if j ~= i and velocity:Dot(_planes[j]) < 0 then
  601.                         break
  602.                     end
  603.                 end
  604.  
  605.                 if _j == numplanes then
  606.                     break
  607.                 end
  608.             end
  609.  
  610.             if _i ~= numplanes then
  611.  
  612.             else
  613.                 if numplanes ~= 3 then
  614.                     velocity = Vector3.zero
  615.                     break
  616.                 end
  617.  
  618.                 local dir = _planes[1]:Cross(_planes[2]).Unit
  619.                 d = dir:Dot(velocity)
  620.                 velocity = dir * d
  621.             end
  622.         end
  623.  
  624.         d = velocity:Dot(primalVelocity)
  625.         if d <= 0 then
  626.             velocity = Vector3.zero
  627.             break
  628.         end
  629.  
  630.     end
  631.  
  632.     if allFraction == 0 then
  633.         velocity = Vector3.zero
  634.     end
  635.  
  636.     return velocity, blocked
  637. end
  638.  
  639.  
  640. local function ApplyMoverVelocity(self: Movement, velocity: Vector3): Vector2
  641.     local vel = Vector2.new(velocity.X, velocity.Z)
  642.     self.mover.PlaneVelocity = vel
  643.     return vel
  644. end
  645.  
  646. function Physics:ApplyGroundVelocity(groundNormal: Vector3)
  647.     local wishDir = Shared.GetMovementDirection(self, groundNormal)
  648.     local wishSpeed = wishDir.Magnitude * Config.RUN_SPEED
  649.  
  650.     -- normal friction
  651.     if self.states.air_friction <= 0 then
  652.         Physics.ApplyFriction(self)
  653.     else
  654.  
  655.         -- friction that is applied due to the player reaching max speed while bhopping
  656.         local sub = Config.AIR_MAX_SPEED_FRIC_DEC * self.dt * 60
  657.         local curr = self.states.air_friction
  658.         local fric = curr - sub
  659.         if fric < 0 then
  660.             fric = curr + fric
  661.         end
  662.  
  663.         Physics.ApplyFriction(self, math.max(1, fric/Config.FRICTION))
  664.         self.states.air_friction = math.max(0, curr - sub)
  665.     end
  666.  
  667.     Physics.ApplyGroundAcceleration(self, wishDir, wishSpeed)
  668.     Collisions.CollideAndSlide(self, Vector3.new(self.mover.PlaneVelocity.X, 0, self.mover.PlaneVelocity.Y))
  669.  
  670.     -- calculate & apply slope movement
  671.     if Shared.GetAngle(groundNormal) < 5 then
  672.         return
  673.     end
  674.  
  675.     local curVel: Vector3 = Vector3.new(self.mover.PlaneVelocity.X, self.collider.Velocity.Y, self.mover.PlaneVelocity.Y)
  676.     local forVel: Vector3 = groundNormal:Cross(CFrame.Angles(0,math.rad(90),0).LookVector * curVel)
  677.     local yVel: number = 0
  678.  
  679.     if forVel.Magnitude > 0 then
  680.         yVel = forVel.Unit.Y * curVel.Magnitude
  681.     end
  682.  
  683.     self.collider.Velocity = Vector3.new(curVel.X, yVel, curVel.Z)
  684. end
  685.  
  686. function Physics:ApplyGroundAcceleration(wishDir: Vector3, wishSpeed: number)
  687.     local addSpeed
  688.     local accelerationSpeed
  689.     local currentSpeed
  690.     local currentVelocity = Vector3.new(self.mover.PlaneVelocity.X, 0, self.mover.PlaneVelocity.Y)
  691.     local newVelocity = currentVelocity
  692.  
  693.     -- get current/add speed
  694.     currentSpeed = currentVelocity:Dot(wishDir)
  695.     addSpeed = wishSpeed - currentSpeed
  696.  
  697.     -- if we're not adding speed, dont do anything
  698.     if addSpeed <= 0 then return end
  699.  
  700.     -- get accelSpeed, cap at addSpeed
  701.     accelerationSpeed = math.min(Config.GROUND_ACCEL * self.dt * wishSpeed, addSpeed)
  702.  
  703.     -- you can't change the properties of a Vector3, so we do x, y, z
  704.     newVelocity += (accelerationSpeed * wishDir)
  705.     newVelocity = Vector3.new(newVelocity.X,  0, newVelocity.Z)
  706.  
  707.     -- clamp magnitude (max speed)
  708.     if newVelocity.Magnitude > (Config.RUN_SPEED) then
  709.         newVelocity = newVelocity.Unit * math.min(newVelocity.Magnitude, (Config.RUN_SPEED))
  710.     end
  711.  
  712.     -- apply acceleration
  713.     ApplyMoverVelocity(self, newVelocity)
  714. end
  715.  
  716. function Physics:ApplyAirVelocity(normal)
  717.     normal = Vector3.new(0,1,0)
  718.     local vel = Vector3.new(self.mover.PlaneVelocity.X, 0, self.mover.PlaneVelocity.Y)
  719.     local wishDir = Shared.GetMovementDirection(self, normal)
  720.     local wishSpeed = wishDir.Magnitude * Config.AIR_SPEED
  721.     local currSpeed = vel.Magnitude
  722.  
  723.     -- initiate extra friction for max speed
  724.     if currSpeed > Config.AIR_MAX_SPEED then
  725.         self.states.air_friction = Config.AIR_MAX_SPEED_FRIC
  726.     end
  727.  
  728.     -- apply extra friction if necessary
  729.     if self.states.air_friction > 0 and not self.states.surfing then
  730.         Physics.ApplyFriction(self, 0.01 * self.states.air_friction, false)
  731.     end
  732.  
  733.     Physics.ApplyAirAcceleration(self, wishDir, wishSpeed)
  734.  
  735.     local refVel = Vector3.new(self.mover.PlaneVelocity.X, self.collider.Velocity.Y, self.mover.PlaneVelocity.Y)
  736.     ApplyMoverVelocity(self, Trace.Reflect(self, refVel, self.collider.Position))
  737. end
  738.  
  739. function Physics:ApplyAirAcceleration(wishDir: Vector3, wishSpeed: number)
  740.     local currentSpeed
  741.     local addSpeed
  742.     local accelerationSpeed
  743.     local currentVelocity = Vector3.new(self.mover.PlaneVelocity.X, 0, self.mover.PlaneVelocity.Y)
  744.  
  745.     -- get current/add speed
  746.     currentSpeed = currentVelocity:Dot(wishDir)
  747.     addSpeed = wishSpeed - currentSpeed
  748.  
  749.     -- if we're not adding speed, dont do anything
  750.     if addSpeed <= 0 then return end
  751.  
  752.     -- get accelSpeed, cap at addSpeed
  753.     accelerationSpeed = math.min(Config.AIR_ACCEL * self.dt * wishSpeed, addSpeed)
  754.  
  755.     -- get new velocity
  756.     local newVelocity = currentVelocity + accelerationSpeed * wishDir
  757.  
  758.     -- apply acceleration
  759.     ApplyMoverVelocity(self, newVelocity)
  760. end
  761.  
  762. function Physics:ApplyFriction(modifier: number?, inAir: boolean?)
  763.     local vel
  764.     if inAir then
  765.         vel = self.collider.Velocity
  766.     else
  767.         vel = Vector3.new(self.mover.PlaneVelocity.X, 0, self.mover.PlaneVelocity.Y)
  768.     end
  769.  
  770.     local speed = vel.Magnitude
  771.     modifier = modifier or 1
  772.  
  773.     local drop = 0
  774.     local fric = inAir and Config.AIR_FRICTION or Config.FRICTION
  775.     local decel = Config.GROUND_DECCEL
  776.     local newSpeed
  777.     local control
  778.  
  779.     -- if we're not moving, don't apply friction
  780.     if speed <= 0 then
  781.         return vel
  782.     end
  783.  
  784.     -- ???
  785.     control = speed < decel and decel or speed
  786.     drop = control * fric * self.dt * modifier
  787.     if type(drop) ~= "number" then drop = drop.Magnitude end
  788.  
  789.     -- ????????????
  790.     newSpeed = math.max(speed - drop, 0)
  791.     if speed > 0 and newSpeed > 0 then
  792.         newSpeed /= speed
  793.     end
  794.  
  795.     vel *= newSpeed
  796.     ApplyMoverVelocity(self, vel)
  797.  
  798.     if inAir then
  799.         local nv = self.mover.VectorVelocity
  800.         --self.collider.Velocity = Vector3.new(nv.X, self.collider.Velocity.Y * newSpeed, nv.Z)
  801.     end
  802. end
  803.  
  804. local function Init()
  805.     Movement.Keys = {W = 0, S = 0, D = 0, A = 0, Space = 0}
  806.     Movement.player = game.Players.LocalPlayer
  807.     Movement.character = Movement.player.Character or Movement.player.CharacterAdded:Wait()
  808.     Movement.collider = Movement.character:WaitForChild("HumanoidRootPart")
  809.     Movement.vispart = false
  810.     Movement.vis_coll_parts = {}
  811.     Movement.config = Config
  812.  
  813.     local mover = Instance.new("LinearVelocity", Movement.collider)
  814.     local a0 = Instance.new("Attachment", Movement.collider)
  815.     a0.Name = "MovementAttachment"
  816.     mover.Attachment0 = a0
  817.     mover.MaxForce = 10000000
  818.     mover.VelocityConstraintMode = Enum.VelocityConstraintMode.Plane
  819.     mover.PrimaryTangentAxis = Vector3.new(1,0,0)
  820.     mover.SecondaryTangentAxis = Vector3.new(0,0,1)
  821.     Movement.mover = mover
  822.  
  823.     -- Will figure this out soon.
  824.     --[[local upMover = Instance.new("LinearVelocity", Movement.collider)
  825.     upMover.Attachment0 = Movement.collider:WaitForChild("MovementAttachment")
  826.     upMover.ForceLimitMode = Enum.ForceLimitMode.PerAxis
  827.     upMover.ForceLimitsEnabled = true
  828.     upMover.MaxAxesForce = Vector3.new(0, 100000, 0)
  829.     upMover.VelocityConstraintMode = Enum.VelocityConstraintMode.Vector
  830.     Movement.up_mover = upMover]]
  831.  
  832.     Movement.states = {grounded = false, air_friction = 0, input_vec = Vector3.zero, surfing = false}
  833. end
  834.  
  835. --
  836.  
  837. local function Gravity()
  838.     local mod = Movement.config.GRAVITY * Movement.dt
  839.     Movement.collider.AssemblyLinearVelocity = Vector3.new(
  840.         Movement.collider.AssemblyLinearVelocity.X,
  841.         Movement.collider.AssemblyLinearVelocity.Y - mod,
  842.         Movement.collider.AssemblyLinearVelocity.Z
  843.     )
  844. end
  845.  
  846. local function Air()
  847.     Physics.ApplyAirVelocity(Movement)
  848.     local vel = Vector3.new(Movement.mover.PlaneVelocity.X, Movement.collider.AssemblyLinearVelocity.Y, Movement.mover.PlaneVelocity.Y)
  849.     vel = Trace.Reflect(Movement, vel, Movement.collider.CFrame.Position)
  850.     Movement.mover.PlaneVelocity = Vector2.new(vel.X, vel.Z)
  851.     Movement.collider.AssemblyLinearVelocity = vel
  852. end
  853.  
  854. local function Ground(groundNormal: Vector3)
  855.     Physics.ApplyGroundVelocity(Movement, groundNormal)
  856. end
  857.  
  858. local function Jump()
  859.     sounds[math.random(1, #sounds)]:Play()
  860.     Movement.temp_jump_last = tick()
  861.     Movement.states.jumping = true
  862.     Movement.collider.AssemblyLinearVelocity = Vector3.new(
  863.         Movement.collider.AssemblyLinearVelocity.X,
  864.         Movement.config.JUMP_VELOCITY,
  865.         Movement.collider.AssemblyLinearVelocity.Z
  866.     )
  867. end
  868.  
  869. local function ProcessMovement()
  870.     local isGrounded, isSurfing, result = Shared.IsGrounded(Movement)
  871.     Movement.states.grounded = isGrounded or false
  872.     Movement.states.surfing = isSurfing or false
  873.  
  874.     if Movement.collider.AssemblyLinearVelocity.Y < 0 then
  875.         Movement.states.jumping = false
  876.  
  877.     end
  878.  
  879.     Shared.RotateCharacter(Movement)
  880.  
  881.     if Movement.states.jumping or not Movement.states.grounded then
  882.         local groundNormal = false
  883.         if isSurfing then
  884.             groundNormal = result.Normal
  885.             if Movement.collider.Velocity.Y > 0 then
  886.                 --Physics.ApplyFriction(Movement, false, true)
  887.             end
  888.         end
  889.  
  890.         Air(groundNormal)
  891.         Gravity()
  892.     elseif Movement.Keys.Space > 0 then
  893.         Jump()
  894.         Air()
  895.     else
  896.         Ground(result.Normal)
  897.     end
  898. end
  899.  
  900. --
  901.  
  902. local function InputBegan(input: InputObject, gp: boolean)
  903.     if input.KeyCode and Movement.Keys[input.KeyCode.Name] then
  904.         Movement.Keys[input.KeyCode.Name] = 1
  905.     end
  906. end
  907.  
  908. local function InputEnded(input: InputObject, gp: boolean)
  909.     if input.KeyCode and Movement.Keys[input.KeyCode.Name] then
  910.         Movement.Keys[input.KeyCode.Name] = 0
  911.     end
  912. end
  913.  
  914. local function Update(dt)
  915.     Movement.dt = dt
  916.     ProcessMovement()
  917. end
  918.  
  919. Init()
  920. UserInputService.InputBegan:Connect(InputBegan)
  921. UserInputService.InputEnded:Connect(InputEnded)
  922. RunService.RenderStepped:Connect(Update)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement