Run it
Copy the script and paste it into your executor.
.Gravity =
Config = {
VISUALIZE_FEET_HB = ,
VISUALIZE_COLLIDE_AND_SLIDE = ,
STEP_OFFSET = ,
MASS = ,
AIR_FRICTION = ,
FRICTION = ,
GRAVITY = ,
JUMP_VELOCITY = ,
GROUND_ACCEL = ,
GROUND_DECCEL = ,
AIR_ACCEL = ,
AIR_SPEED = ,
RUN_SPEED = ,
WALK_SPEED = ,
CROUCH_SPEED = ,
AIR_MAX_SPEED = ,
AIR_MAX_SPEED_FRIC = ,
AIR_MAX_SPEED_FRIC_DEC = ,
MIN_SLOPE_ANGLE = ,
MAX_SLOPE_ANGLE = ,
LEG_HEIGHT = +,
TORSO_TO_FEET = +,
FEET_HB_SIZE = .(,,),
TORSO_HB_SIZE = .(,,),
FOOT_OFFSET_AMOUNT =
}
RunService = :()
UserInputService = :()
ids = {
,
,
,
,
,
}
sounds = {}
_, i (ids)
sound = .()
sound.SoundId = i
sound.Volume =
sound.Parent = .Workspace
.(sounds, sound)
export Movement = {
Keys: {W: number, A: number, S: number, D: number, Space: number},
player: Player,
character: Model,
collider: Part,
vispart: Part?,
vis_coll_parts: {Part},
config: MovementConfig,
mover: LinearVelocity,
up_mover: LinearVelocity,
dt: number,
states: MovementStates,
}
export MovementConfig = {
VISUALIZE_FEET_HB: boolean,
VISUALIZE_COLLIDE_AND_SLIDE: boolean,
LEG_HEIGHT: number,
FEET_HB_SIZE: ,
TORSO_HB_SIZE: ,
MASS: number,
GRAVITY: number,
FRICTION: number,
AIR_FRICTION: number,
GROUND_ACCEL: number,
GROUND_DECCEL: number,
AIR_ACCEL: number,
RUN_SPEED: number,
WALK_SPEED: number,
CROUCH_SPEED: number,
AIR_SPEED: number,
AIR_MAX_SPEED: number,
AIR_MAX_SPEED_FRIC: number,
AIR_MAX_SPEED_FRIC_DEC: number,
JUMP_VELOCITY: number,
STEP_OFFSET: number,
TORSO_TO_FEET: number,
MIN_SLOPE_ANGLE: number,
MAX_SLOPE_ANGLE: number,
}
export MovementStates = {
grounded: boolean,
air_friction: number,
input_vec: number,
surfing: boolean,
jumping: boolean,
}
export Vec3Mod = {x: number, y: number, z: number, ToVector3: (Vec3Mod) -> }
Vec3Mod = {}
Vec3Mod.__index = Vec3Mod
Vec3Mod.(input: ?) : Vec3Mod
input = input .zero
({x = input.X, y = input.Y, z = input.Z}, Vec3Mod) :: Vec3Mod
Vec3Mod:()
.(self.x, self.y, self.z)
Movement: Movement = {}
Physics = {} :: Movement
Shared : Movement= {}
Trace : Movement= {}
Collisions = {} :: Movement
(result: RaycastResult, origin: , direction: )
position = result result.Position (origin + direction)
distance = (origin - position).Magnitude
p = .()
p.Anchored =
p.CanCollide =
p.Size = .(, , distance)
p.CFrame = .(origin, position)*.(, , -distance/)
p.Parent = .Temp
p
(moveVector: , normal: )
moveVector.Magnitude == normal.Magnitude ==
.zero
normal = normal.Unit
reflected = moveVector - * moveVector:(normal) * normal
parallel = moveVector + reflected
parallel.Magnitude ==
.zero
cropped = parallel.Unit:(moveVector.Unit) * parallel.Unit * moveVector.Magnitude
cropped
Collisions:(wishedSpeed: )
mod =
wishedSpeed.Magnitude ==
wishedSpeed
inputVec = self.states.input_vec
newSpeed = wishedSpeed
hrp = self.player.Character.HumanoidRootPart
params = Shared.(self)
wishedSpeed *=
dirAmnt = * (mod )
mainDirAmnt = * (mod )
isSticking =
normals = {}
stickingDirections = {}
ldd = {dir = , dist = }
partsAlreadyHit = {}
Config.VISUALIZE_COLLIDE_AND_SLIDE
_, v (self.vis_coll_parts)
v:()
lookVecs = {
.(, (-Config.TORSO_TO_FEET) + Config.STEP_OFFSET, ),
.(, , ),
.(, , )
}
_, v (lookVecs)
values = {}
hval = {}
currForDir
currSideDir
rayPos
(v) ==
rayPos = hrp.Position + v
rayPos = .(hrp.Position.X, hrp.Parent[v].CFrame.Position, hrp.Position.Z)
inputVec.X >
currForDir = hrp.CFrame.RightVector
.(values, currForDir)
.(hval, hrp.CFrame.LookVector * dirAmnt)
.(hval, -hrp.CFrame.LookVector * dirAmnt)
inputVec.X <
currForDir = -hrp.CFrame.RightVector
.(values, currForDir)
.(hval, hrp.CFrame.LookVector * dirAmnt)
.(hval, -hrp.CFrame.LookVector * dirAmnt)
inputVec.Z >
currSideDir = -hrp.CFrame.LookVector
.(values, currSideDir)
.(hval, hrp.CFrame.RightVector * dirAmnt)
.(hval, -hrp.CFrame.RightVector * dirAmnt)
inputVec.Z <
currSideDir = hrp.CFrame.LookVector
.(values, currSideDir)
.(hval, hrp.CFrame.RightVector * dirAmnt)
.(hval, -hrp.CFrame.RightVector * dirAmnt)
inputVec.Z == inputVec.X ==
values[] = wishedSpeed.Unit
.(hval, .(wishedSpeed.Unit).RightVector * dirAmnt)
.(hval, -.(wishedSpeed.Unit).RightVector * dirAmnt)
.(values, wishedSpeed.Unit * dirAmnt)
currForDir currSideDir
a, b (values)
values[a] = b * mainDirAmnt
.(values, (currForDir+currSideDir) * mainDirAmnt)
values[] *= mainDirAmnt
.(values, (values[] + hval[]).Unit * mainDirAmnt)
.(values, (values[] + hval[]).Unit * mainDirAmnt)
.(values, hval[])
.(values, hval[])
_, b (values)
b
Config.VISUALIZE_COLLIDE_AND_SLIDE
.(self.vis_coll_parts, (, rayPos, b))
result = :(rayPos, b, params)
result
( ldd.dir ldd.dist) (ldd.dist ldd.dist < result.Distance)
ldd.dir = b
ldd.dist = result.Distance
.(partsAlreadyHit, result.Instance)
.(partsAlreadyHit, result.Instance)
_v = newSpeed.Unit * result.Normal
_, c ({_v.X, _v.Y, _v.Z})
.(c) >
_v = c
(_v) == _v >
isSticking isSticking =
newSpeed = (newSpeed, result.Normal)
newSpeed -= result.Instance.Velocity
self.mover.PlaneVelocity = .(newSpeed.X, newSpeed.Z)
newSpeed, isSticking normals, isSticking stickingDirections, isSticking ldd.dir
export Trace = {
startPos: ,
endPos: ,
fraction: number,
startSolid: boolean,
hitPart: ,
hitPoint: ,
planeNormal: ,
distance: number
}
(self, cf, size)
Config.VISUALIZE_FEET_HB
self.vispart
self.vispart = .(, self.character)
self.vispart.CanCollide =
self.vispart.Anchored =
self.vispart.CFrame = cf
self.vispart.Size = size
Shared.(normal)
.(.(normal:(.yAxis)))
Shared:(dir): (boolean, boolean?, RaycastResult?, number?)
params = Shared.(self)
cf = .(self.collider.Position) - .(, self.collider.Size.Y/, )
size = Config.FEET_HB_SIZE
dir = dir .(,- * self.collider.Size.Y-Config.FOOT_OFFSET_AMOUNT,)
result = :(cf, size, dir, params)
(self, cf, size)
result
steepness = Shared.(result.Normal)
isSurfing = steepness >= Config.MIN_SLOPE_ANGLE steepness <= Config.MAX_SLOPE_ANGLE
isSurfing
, , result, steepness
, , result
Shared:()
collider = self.collider
camera = .CurrentCamera
rotationLook = collider.Position + camera.CoordinateFrame.lookVector
collider.CFrame = .(collider.Position, .(rotationLook.x, collider.Position.y, rotationLook.z))
collider.RotVelocity = .()
Shared:(groundNormal)
forward = self.Keys.W + -self.Keys.S
side = self.Keys.A + -self.Keys.D
groundNormal = groundNormal .(,,)
forward == side ==
self.states.input_vec = .zero
.zero
self.states.input_vec = .(-side, , -forward).Unit
forwardMove = groundNormal:(self.collider.CFrame.RightVector)
sideMove = groundNormal:(forwardMove)
(forwardMove * forward + sideMove * side).Unit
Shared:()
params = RaycastParams.()
params.FilterDescendantsInstances = {self.character, .CurrentCamera}
params.FilterType = .RaycastFilterType.Exclude
params.RespectCanCollide =
params.CollisionGroup =
params
Shared:(start: , scale: number, direction: )
.(
start.X + direction.X * scale,
start.Y + direction.Y * scale,
start.Z + direction.Z * scale
)
Trace: Movement = {}
numBumps =
maxClipPlanes =
_planes = {}
numToCoord = {, , }
(self, input, normal, output, overbounce)
newVelMod = Vec3Mod.(output)
Trace.(self, input, normal, newVelMod, overbounce)
newVelMod:()
Trace:(start: , destination: )
contactOffset =
longSide = .(contactOffset * contactOffset + contactOffset * contactOffset)
direction = (destination - start).Unit
maxDistance = (start - destination).Magnitude + longSide
result: Trace = {
startPos = start,
endPos = destination
}
_, _, hit = Shared.(self, direction*maxDistance)
hit
result.fraction = hit.Distance / maxDistance
result.hitPart = hit.Instance
result.hitPoint = hit.Position
result.planeNormal = hit.Normal
result.distance = hit.Distance
result.fraction =
result
Trace:(input: , normal: , output: Types.Vec3Mod, overbounce: number)
angle = normal.Y
blocked =
angle >
blocked = blocked
angle ==
blocked = blocked
backoff = input:(normal) * overbounce
i = , ,
ci = numToCoord[i]
change = normal[ci] * backoff
output[ci] = input[ci] - change
adjust = output:():(normal)
adjust <
output = output:()-(normal * adjust)
blocked
Trace:(velocity: , origin: )
self = self :: Movement
d
newVelocity = .zero
blocked =
numplanes =
originalVelocity = velocity
primalVelocity = velocity
allFraction =
timeLeft = self.dt
bumpcount = , numBumps,
velocity.Magnitude ==
endp = Shared.(self, origin, timeLeft, velocity)
trace = Trace.(self, origin, endp)
allFraction += trace.fraction
trace.fraction >
originalVelocity = velocity
numplanes =
trace.fraction ==
trace.planeNormal.Y > Config.MAX_SLOPE_ANGLE
blocked = blocked
trace.planeNormal.Y ==
blocked = blocked
timeLeft -= timeLeft * trace.fraction
numplanes >= maxClipPlanes
velocity = .zero
_planes[numplanes] = trace.planeNormal
numplanes+=
numplanes ==
_planes[].Y > Config.MAX_SLOPE_ANGLE
blocked
newVelocity = (self, originalVelocity, _planes[], newVelocity, )
velocity = newVelocity
originalVelocity = newVelocity
_i =
i = , numplanes-,
_i = i
newVelocity = (self, originalVelocity, _planes[i], newVelocity, )
_j =
j = , numplanes-,
_j = j
j ~= i velocity:(_planes[j]) <
_j == numplanes
_i ~= numplanes
numplanes ~=
velocity = .zero
dir = _planes[]:(_planes[]).Unit
d = dir:(velocity)
velocity = dir * d
d = velocity:(primalVelocity)
d <=
velocity = .zero
allFraction ==
velocity = .zero
velocity, blocked
(self: Movement, velocity: ):
vel = .(velocity.X, velocity.Z)
self.mover.PlaneVelocity = vel
vel
Physics:(groundNormal: )
wishDir = Shared.(self, groundNormal)
wishSpeed = wishDir.Magnitude * Config.RUN_SPEED
self.states.air_friction <=
Physics.(self)
sub = Config.AIR_MAX_SPEED_FRIC_DEC * self.dt *
curr = self.states.air_friction
fric = curr - sub
fric <
fric = curr + fric
Physics.(self, .(, fric/Config.FRICTION))
self.states.air_friction = .(, curr - sub)
Physics.(self, wishDir, wishSpeed)
Collisions.(self, .(self.mover.PlaneVelocity.X, , self.mover.PlaneVelocity.Y))
Shared.(groundNormal) <
curVel: = .(self.mover.PlaneVelocity.X, self.collider.Velocity.Y, self.mover.PlaneVelocity.Y)
forVel: = groundNormal:(.(,.(),).LookVector * curVel)
yVel: number =
forVel.Magnitude >
yVel = forVel.Unit.Y * curVel.Magnitude
self.collider.Velocity = .(curVel.X, yVel, curVel.Z)
Physics:(wishDir: , wishSpeed: number)
addSpeed
accelerationSpeed
currentSpeed
currentVelocity = .(self.mover.PlaneVelocity.X, , self.mover.PlaneVelocity.Y)
newVelocity = currentVelocity
currentSpeed = currentVelocity:(wishDir)
addSpeed = wishSpeed - currentSpeed
addSpeed <=
accelerationSpeed = .(Config.GROUND_ACCEL * self.dt * wishSpeed, addSpeed)
newVelocity += (accelerationSpeed * wishDir)
newVelocity = .(newVelocity.X, , newVelocity.Z)
newVelocity.Magnitude > (Config.RUN_SPEED)
newVelocity = newVelocity.Unit * .(newVelocity.Magnitude, (Config.RUN_SPEED))
(self, newVelocity)
Physics:(normal)
normal = .(,,)
vel = .(self.mover.PlaneVelocity.X, , self.mover.PlaneVelocity.Y)
wishDir = Shared.(self, normal)
wishSpeed = wishDir.Magnitude * Config.AIR_SPEED
currSpeed = vel.Magnitude
currSpeed > Config.AIR_MAX_SPEED
self.states.air_friction = Config.AIR_MAX_SPEED_FRIC
self.states.air_friction > self.states.surfing
Physics.(self, * self.states.air_friction, )
Physics.(self, wishDir, wishSpeed)
refVel = .(self.mover.PlaneVelocity.X, self.collider.Velocity.Y, self.mover.PlaneVelocity.Y)
(self, Trace.(self, refVel, self.collider.Position))
Physics:(wishDir: , wishSpeed: number)
currentSpeed
addSpeed
accelerationSpeed
currentVelocity = .(self.mover.PlaneVelocity.X, , self.mover.PlaneVelocity.Y)
currentSpeed = currentVelocity:(wishDir)
addSpeed = wishSpeed - currentSpeed
addSpeed <=
accelerationSpeed = .(Config.AIR_ACCEL * self.dt * wishSpeed, addSpeed)
newVelocity = currentVelocity + accelerationSpeed * wishDir
(self, newVelocity)
Physics:(modifier: number?, inAir: boolean?)
vel
inAir
vel = self.collider.Velocity
vel = .(self.mover.PlaneVelocity.X, , self.mover.PlaneVelocity.Y)
speed = vel.Magnitude
modifier = modifier
drop =
fric = inAir Config.AIR_FRICTION Config.FRICTION
decel = Config.GROUND_DECCEL
newSpeed
control
speed <=
vel
control = speed < decel decel speed
drop = control * fric * self.dt * modifier
(drop) ~= drop = drop.Magnitude
newSpeed = .(speed - drop, )
speed > newSpeed >
newSpeed /= speed
vel *= newSpeed
(self, vel)
inAir
nv = self.mover.VectorVelocity
()
Movement.Keys = {W = , S = , D = , A = , Space = }
Movement.player = .Players.LocalPlayer
Movement.character = Movement.player.Character Movement.player.CharacterAdded:()
Movement.collider = Movement.character:()
Movement.vispart =
Movement.vis_coll_parts = {}
Movement.config = Config
mover = .(, Movement.collider)
a0 = .(, Movement.collider)
a0.Name =
mover.Attachment0 = a0
mover.MaxForce =
mover.VelocityConstraintMode = .VelocityConstraintMode.Plane
mover.PrimaryTangentAxis = .(,,)
mover.SecondaryTangentAxis = .(,,)
Movement.mover = mover
Movement.states = {grounded = , air_friction = , input_vec = .zero, surfing = }
()
mod = Movement.config.GRAVITY * Movement.dt
Movement.collider.AssemblyLinearVelocity = .(
Movement.collider.AssemblyLinearVelocity.X,
Movement.collider.AssemblyLinearVelocity.Y - mod,
Movement.collider.AssemblyLinearVelocity.Z
)
()
Physics.(Movement)
vel = .(Movement.mover.PlaneVelocity.X, Movement.collider.AssemblyLinearVelocity.Y, Movement.mover.PlaneVelocity.Y)
vel = Trace.(Movement, vel, Movement.collider.CFrame.Position)
Movement.mover.PlaneVelocity = .(vel.X, vel.Z)
Movement.collider.AssemblyLinearVelocity = vel
(groundNormal: )
Physics.(Movement, groundNormal)
()
sounds[.(, #sounds)]:()
Movement.temp_jump_last = ()
Movement.states.jumping =
Movement.collider.AssemblyLinearVelocity = .(
Movement.collider.AssemblyLinearVelocity.X,
Movement.config.JUMP_VELOCITY,
Movement.collider.AssemblyLinearVelocity.Z
)
()
isGrounded, isSurfing, result = Shared.(Movement)
Movement.states.grounded = isGrounded
Movement.states.surfing = isSurfing
Movement.collider.AssemblyLinearVelocity.Y <
Movement.states.jumping =
Shared.(Movement)
Movement.states.jumping Movement.states.grounded
groundNormal =
isSurfing
groundNormal = result.Normal
Movement.collider.Velocity.Y >
(groundNormal)
()
Movement.Keys.Space >
()
()
(result.Normal)
(input: InputObject, gp: boolean)
input.KeyCode Movement.Keys[input.KeyCode.Name]
Movement.Keys[input.KeyCode.Name] =
(input: InputObject, gp: boolean)
input.KeyCode Movement.Keys[input.KeyCode.Name]
Movement.Keys[input.KeyCode.Name] =
(dt)
Movement.dt = dt
()
()
UserInputService.InputBegan:(InputBegan)
UserInputService.InputEnded:(InputEnded)
RunService.RenderStepped:(Update)its basically bhopping like half life 1