-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBhop.lua
388 lines (328 loc) · 10.2 KB
/
Bhop.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
--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()