View difference between Paste ID: aUYmEX8e and eryDCw9r
SHOW: | | - or go back to the newest paste.
1
-- services
2
3
local UserInputService	= game:GetService("UserInputService")
4
local CollectionService	= game:GetService("CollectionService")
5
local ReplicatedStorage	= game:GetService("ReplicatedStorage")
6
local RunService		= game:GetService("RunService")
7
local Workspace			= game:GetService("Workspace")
8
local Players			= game:GetService("Players")
9
10
-- constants
11
12
local CAMERA	= Workspace.CurrentCamera
13
local PLAYER	= Players.LocalPlayer
14
15
local SPACESHIP	= Workspace:WaitForChild("Spaceship")
16
17
local SQUADS	= ReplicatedStorage:WaitForChild("Squads")
18
local REMOTES	= ReplicatedStorage:WaitForChild("Remotes")
19
local EVENTS	= ReplicatedStorage:WaitForChild("Events")
20
local MODULES	= ReplicatedStorage:WaitForChild("Modules")
21
	local SPRING	= require(MODULES:WaitForChild("Spring"))
22
	local INPUT		= require(MODULES:WaitForChild("Input"))
23
24
local MIN_Y, MAX_Y	= -1.4, 1.4
25
local SENSITIVITY	= Vector2.new(1/250, 1/250)
26
local CENTER_OFFSET	= Vector3.new(0, 2, 0)
27
28
local GAMEPAD_DEAD	= 0.15
29
local GAMEPAD_SPEED	= 3
30
31
local IGNORE_SIZE	= 1
32
33
-- variables
34
35
local character, rootPart
36
local parts		= {}
37
38
local x, y		= 0, 0
39
local zoom		= 10
40
local height	= 1
41
local shoulder	= 3
42
43
local targetZoom	= 10
44
local zooming		= false
45
46
local recoil	= SPRING:Create(1, 100, 10, 2)
47
local shaker	= SPRING:Create(1, 100, 4, 3)
48
49
local mode		= "Default"
50
local flying	= false
51
52
local currentSquad, spectateChar
53
local killerChar
54
55
local modalStack	= 0
56
57
local flyShake	= 0
58
59
-- functions
60
61
local function Lerp(a, b, d) return a + (b - a) * d end
62
63
local function ZoomSensitivity()
64
	return (CAMERA.FieldOfView / 70)^2
65
end
66
67
local function GetSquad(player)
68
	for _, squad in pairs(SQUADS:GetChildren()) do
69
		if squad:FindFirstChild(player.Name) then
70
			return squad
71
		end
72
	end
73
end
74
75
local function CenterFromSubject(subject)
76
	if subject then
77
		if subject:IsA("Humanoid") then
78
			local rootPart	= subject.Parent:FindFirstChild("HumanoidRootPart")
79
			
80
			if rootPart then
81
				return rootPart.Position
82
			end
83
		elseif subject:IsA("BasePart") then
84
			return subject.Position
85
		elseif subject:IsA("Model") then
86
			if subject.PrimaryPart then
87
				return subject.PrimaryPart.Position
88
			end
89
		end
90
	end
91
	return Vector3.new()
92
end
93
		
94
local function HandleCharacter(newCharacter)
95
	if newCharacter then
96
		character	= nil
97
		
98
		parts	= {}
99
		for _, v in pairs(newCharacter:GetDescendants()) do
100
			if v:IsA("BasePart") then
101
				table.insert(parts, v)
102
			end
103
		end
104
		
105
		newCharacter.DescendantAdded:Connect(function(obj)
106
			if obj:IsA("BasePart") then
107
				table.insert(parts, obj)
108
			end
109
		end)
110
		
111
		newCharacter.DescendantRemoving:Connect(function(obj)
112
			if obj:IsA("BasePart") then
113
				for i, v in pairs(parts) do
114
					if v == obj then
115
						table.remove(parts, i)
116
						break
117
					end
118
				end
119
			end
120
		end)
121
		
122
		rootPart	= newCharacter:WaitForChild("HumanoidRootPart")
123
		character	= newCharacter
124
	end
125
end
126
127
local function GetIgnoreList()
128
	local ignore	= CollectionService:GetTagged("Ignore")
129
	
130
	if CAMERA.CameraSubject then
131
		if CAMERA.CameraSubject:IsA("Humanoid") then
132
			table.insert(ignore, CAMERA.CameraSubject.Parent)
133
		end
134
	end
135
	
136
	for _, player in pairs(Players:GetPlayers()) do
137
		if player.Character then
138
			table.insert(ignore, player.Character)
139
		end
140
	end
141
	
142
	return ignore
143
end
144
145
local function Raycast(ray)
146
	local success	= false
147
	local ignore	= GetIgnoreList()
148
	local hit, position, normal
149
	
150
	repeat
151
		hit, position, normal	= Workspace:FindPartOnRayWithIgnoreList(ray, ignore)
152
		
153
		if hit then
154
			if hit.CanCollide then
155
				if hit.Transparency >= 0.5 then
156
					table.insert(ignore, hit)
157
				elseif (hit.Size.X <= IGNORE_SIZE and hit.Size.Y <= IGNORE_SIZE)
158
					or (hit.Size.X <= IGNORE_SIZE and hit.Size.Z <= IGNORE_SIZE)
159
					or (hit.Size.Y <= IGNORE_SIZE and hit.Size.Z <= IGNORE_SIZE)
160
				then
161
					table.insert(ignore, hit)
162
				else
163
					success	= true
164
				end
165
			else
166
				table.insert(ignore, hit)
167
			end
168
		else
169
			success	= true
170
		end
171
	until success
172
	
173
	return hit, position, normal
174
end
175
176
local function GetSpectateChar()
177
	if not currentSquad then
178
		currentSquad	= GetSquad(PLAYER)
179
	end
180
	if currentSquad then
181
		for _, p in pairs(currentSquad:GetChildren()) do
182
			local player	= p.Value
183
			local char		= player.Character
184
			if char then
185
				local humanoid	= char:FindFirstChild("Humanoid")
186
				if humanoid and humanoid.Health > 0 then
187
					return char
188
				end
189
			end
190
		end
191
	end
192
end
193
194
local function Modal(action)
195
	if action == "Initialize" then
196
		modalStack	= 0
197
	elseif action == "Push" then
198
		modalStack	= modalStack + 1
199
	elseif action == "Pop" then
200
		modalStack	= modalStack - 1
201
	end
202
	
203
	UserInputService.MouseIconEnabled	= modalStack ~= 0
204
end
205
206
-- initiate
207
208
Modal("Initialize")
209
210
CAMERA.CameraType	= Enum.CameraType.Scriptable
211
212
HandleCharacter(PLAYER.Character)
213
214
RunService:BindToRenderStep("Camera", 4, function(deltaTime)
215
	UserInputService.MouseBehavior		= modalStack == 0 and Enum.MouseBehavior.LockCenter or Enum.MouseBehavior.Default
216
	
217
	for _, inputObject in pairs(UserInputService:GetGamepadState(Enum.UserInputType.Gamepad1)) do
218
		if inputObject.KeyCode == Enum.KeyCode.Thumbstick2 then
219
			local input	= inputObject.Position
220
			if input.Magnitude > GAMEPAD_DEAD then
221
				x	= (x - input.X * GAMEPAD_SPEED * deltaTime * ZoomSensitivity()) % (math.pi * 2)
222
				local invert	= UserSettings().GameSettings:GetCameraYInvertValue()
223
				y	= math.clamp(y + input.Y * GAMEPAD_SPEED * deltaTime * invert * ZoomSensitivity(), MIN_Y, MAX_Y)
224
			end
225
		end
226
	end
227
	
228
	if mode == "Default" then
229
		if character then
230
			CAMERA.FieldOfView	= Lerp(CAMERA.FieldOfView, 70 - (zooming and targetZoom or 0) + (flying and rootPart.Velocity.Magnitude / 10 or 0), math.min(deltaTime * 10, 1))
231
			
232
			local center	= rootPart.Position + CENTER_OFFSET
233
			local cframe	= CFrame.new(center) * CFrame.Angles(0, x, 0) * CFrame.Angles(y, 0, 0) * CFrame.new(shoulder, height, zoom - 10 * (1 - (CAMERA.FieldOfView / 70)))
234
			local rotation	= cframe - cframe.p
235
			
236
			local ray		= Ray.new(center, cframe.p - center)
237
			local hit, position, normal	= Raycast(ray)
238
			
239
			if hit then
240
				position	= position + normal * 0.2
241
			end
242
			
243
			local distance		= (center - position).Magnitude
244
			local transparency	= 0
245
			if distance < 5 then
246
				transparency	= (5 - distance) / 5
247
			end
248
			
249
			for _, v in pairs(parts) do
250
				v.LocalTransparencyModifier	= transparency
251
			end
252
			
253
			recoil:Update(deltaTime)
254
			shaker:Update(deltaTime)
255
			
256
			local offset	= Vector3.new(recoil.Position.X / 2, recoil.Position.Y, recoil.Position.Z) * (CAMERA.FieldOfView / 70)
257
			local offset2	= shaker.Position
258
			
259
			CAMERA.CFrame	= CFrame.new(position) * rotation * CFrame.new(offset + offset2) * CFrame.Angles(offset.Z / 20, -offset.X / 20, 0)
260
			
261
			if flying then
262
				flyShake	= flyShake + deltaTime * (rootPart.Velocity.Magnitude / 80)
263
				local x, y	= math.noise(flyShake, 0.3, 0.7), math.noise(0.3, flyShake, 0.7)
264
				
265
				CAMERA.CFrame	= CAMERA.CFrame * CFrame.Angles(x * 0.015, y * 0.015, 0)
266
			end
267
			
268
			CAMERA.Focus	= CAMERA.CFrame * CFrame.new(0, 0, -20)
269
		end
270
	elseif mode == "Spaceship" then
271
		CAMERA.FieldOfView	= Lerp(CAMERA.FieldOfView, 50, math.min(deltaTime * 10, 1))
272
		
273
		y	= math.min(y, 0.5)
274
		
275
		local center	= SPACESHIP.Position
276
		local cframe	= CFrame.new(center) * CFrame.Angles(0, x, 0) * CFrame.Angles(y, 0, 0) * CFrame.new(0, 0, 400)
277
		
278
		CAMERA.CFrame	= cframe
279
		CAMERA.Focus	= CFrame.new(center)
280
	elseif mode == "Spectate" then
281
		CAMERA.FieldOfView	= Lerp(CAMERA.FieldOfView, 70, math.min(deltaTime * 10, 1))
282
		
283
		if not spectateChar then
284
			spectateChar	= GetSpectateChar()
285
			
286
			if not spectateChar then
287
				for _, p in pairs(game.Players:GetPlayers()) do
288
					local char		= p.Character
289
					if char then
290
						local humanoid	= char:FindFirstChild("Humanoid")
291
						if humanoid and humanoid.Health > 0 then
292
							spectateChar	= char
293
							break
294
						end
295
					end
296
				end
297
			end
298
		end
299
		
300
		if killerChar then
301
			local humanoid	= killerChar:FindFirstChild("Humanoid")
302
			if humanoid and humanoid.Health > 0 then
303
				spectateChar	= killerChar
304
			else
305
				killerChar		= nil
306
				spectateChar	= nil
307
			end
308
		end
309
		
310
		if spectateChar then
311
			local root		= spectateChar:FindFirstChild("HumanoidRootPart")
312
			local humanoid	= spectateChar:FindFirstChildOfClass("Humanoid")
313
			
314
			if humanoid and humanoid.Health <= 0 then
315
				spectateChar	= nil
316
			elseif root then
317
				local head		= spectateChar.Head
318
				local angle		= 0--math.asin(head.CFrame.lookVector.Y)
319
				local position	= (root.CFrame * CFrame.Angles(angle, 0, 0) * CFrame.new(0, 6, 20)).p
320
				
321
				local ray			= Ray.new(root.Position, position - root.Position)
322
				local _, position	= Raycast(ray)--Workspace:FindPartOnRayWithIgnoreList(ray, {spectateChar, Workspace.Drops})
323
				
324
				local direction	= Vector3.new(root.CFrame.lookVector.X, 0, root.CFrame.lookVector.Z).Unit
325
				
326
				if spectateChar == killerChar then
327
					CAMERA.CFrame	= head.CFrame * CFrame.new(3, -0.1, -4) * CFrame.Angles(0, math.pi - math.pi / 4, 0)
328
				else
329
					CAMERA.CFrame	= CAMERA.CFrame:Lerp(CFrame.new(position, position + direction) * CFrame.Angles(angle, 0, 0), math.min(deltaTime * 10))
330
					CAMERA.Focus	= CAMERA.CFrame * CFrame.new(0, 0, -20)
331
				end
332
			end
333
		end
334
	end
335
end)
336
337
-- events
338
339
REMOTES.Camera.OnClientEvent:connect(function(action, ...)
340
	if action == "Mode" then
341
		mode	= ...
342
	elseif action == "KillChar" then
343
		killerChar	= ...
344
		wait(7)
345
		if GetSpectateChar() then
346
			killerChar		= nil
347
			spectateChar	= nil
348
		else
349
			if killerChar then
350
				spectateChar	= killerChar
351
				killerChar		= nil
352
			end
353
		end
354
	end
355
end)
356
357
script.Mode.Event:connect(function(m)
358
	mode	= m
359
end)
360
361
script.Flying.Event:connect(function(f)
362
	flying	= f
363
end)
364
365
EVENTS.Modal.Event:connect(Modal)
366
367
EVENTS.Zoom.Event:connect(function(target)
368
	targetZoom	= target and target or 10
369
end)
370
371
EVENTS.Recoil.Event:connect(function(r)
372
	recoil:Shove(r)
373
	EVENTS.Sway:Fire(-Vector3.new(r.X, r.Z, 0))
374
end)
375
376
EVENTS.Shake.Event:connect(function(s)
377
	shaker:Shove(s)
378
end)
379
380
INPUT.ActionBegan:connect(function(action, processed)
381
	if not processed then
382
		if action == "Aim" then
383
			zooming	= true
384
			EVENTS.Aim:Fire(zooming)
385
		elseif action == "AimToggle" then
386
			zooming	= not zooming
387
			EVENTS.Aim:Fire(zooming)
388
		end
389
	end
390
end)
391
392
INPUT.ActionEnded:connect(function(action, processed)
393
	if not processed then
394
		if action == "Aim" then
395
			zooming	= false
396
			EVENTS.Aim:Fire(zooming)
397
		end
398
	end
399
end)
400
401
UserInputService.InputChanged:connect(function(inputObject, processed)
402
	if not processed then
403
		if inputObject.UserInputType == Enum.UserInputType.MouseMovement then
404
			x	= (x - inputObject.Delta.X * SENSITIVITY.X * ZoomSensitivity()) % (math.pi * 2)
405
			y	= math.clamp(y - inputObject.Delta.Y * SENSITIVITY.Y * ZoomSensitivity(), MIN_Y, MAX_Y)
406
			
407
			EVENTS.Sway:Fire(Vector3.new(-inputObject.Delta.X, -inputObject.Delta.Y, 0))
408
		end
409
	end
410
end)
411
412
PLAYER.CharacterAdded:connect(HandleCharacter)