FIRST PERSON FINAL
Key RequiredUniversal

FIRST PERSON FINAL

Universal ScriptRip_xxj2Rip_xxj2 106 views 2.1K executesUpdated Jul 12, 2026
Unrated
00
Lua Script•592 lines (20635 chars)
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local Lighting = game:GetService("Lighting")
local SoundService = game:GetService("SoundService")

local player = Players.LocalPlayer
local camera = workspace.CurrentCamera

local FOV = 120
local LOOK_SPEED = 0.010
local SMOOTHING = 0.25

-- Jitter / Screen Shake Configuration
local JITTER_INTENSITY = 0.02 
local JITTER_SPEED = 25       

local yaw = 0
local pitch = 0
local smoothYaw = 0
local smoothPitch = 0
local lastYaw = 0
local lastPitch = 0

local bob = 0
local rotatingTouch = nil
local renderConnection

local lastMoveState = false
local isDead = false
local deathCamCFrame = nil

-- Connections
local inputBeganConnection
local inputChangedConnection
local inputEndedConnection
local diedConnection
local healthChangedConnection
local toolConnection

-- Sprint Settings
local WALK_SPEED = 16
local SPRINT_SPEED = 26
local MAX_STAMINA = 30 -- 30 seconds of sprinting
local stamina = MAX_STAMINA
local isSprinting = false
local staminaRechargeDelay = 2 -- Cooldown before recharge starts

-- Day/Night Cycle Configuration
local DAY_SPEED = 0.05 -- Adjust how fast time moves (higher = faster)

-- --- ATMOSPHERIC, DARKER NIGHT, SHADOWS & GLOSS CONFIGURATION ---
Lighting.GlobalShadows = true           -- Force shadow maps on
Lighting.ShadowSoftness = 0.15          -- Crisper, sharper shadow profiles
Lighting.EnvironmentSpecularScale = 0.85 -- High glossiness for realistic surface shine
Lighting.EnvironmentDiffuseScale = 0.15  -- Low matte diffuse to keep the ambient night dark

local blurEffect = Lighting:FindFirstChild("CameraBlur") or Instance.new("BlurEffect")
blurEffect.Name = "CameraBlur"
blurEffect.Size = 0
blurEffect.Parent = Lighting

local bloomEffect = Lighting:FindFirstChild("CameraBloom") or Instance.new("BloomEffect")
bloomEffect.Name = "CameraBloom"
bloomEffect.Intensity = 1.2
bloomEffect.Size = 24
bloomEffect.Threshold = 0.8
bloomEffect.Parent = Lighting

local colorCorrection = Lighting:FindFirstChild("CameraColor") or Instance.new("ColorCorrectionEffect")
colorCorrection.Name = "CameraColor"
colorCorrection.Saturation = 0
colorCorrection.Parent = Lighting

-- --- AUDIO ENGINE SETUP ---
local function createSound(name, id, volume)
	local sound = SoundService:FindFirstChild(name)
	if not sound then
		sound = Instance.new("Sound")
		sound.Name = name
		sound.SoundId = "rbxassetid://" .. id
		sound.Volume = volume or 0.5
		sound.Parent = SoundService
	end
	return sound
end

-- Sound Asset Registry (Standard global audio IDs)
local soundPunch = createSound("PunchSound", "9114223171", 0.6)
local soundGore = createSound("GoreSound", "9114222881", 0.7)
local soundStepGrass = createSound("StepGrass", "9114222075", 0.3)
local soundStepMetal = createSound("StepMetal", "9114221194", 0.4)
local soundStepDefault = createSound("StepDefault", "9114221655", 0.3)

-- --- UI CREATOR HELPER ---
local function createGameUI()
	local pGui = player:WaitForChild("PlayerGui")
	
	local oldUI = pGui:FindFirstChild("GameInterfaceGui")
	if oldUI then oldUI:Destroy() end
	
	local screenGui = Instance.new("ScreenGui")
	screenGui.Name = "GameInterfaceGui"
	screenGui.ResetOnSpawn = false
	screenGui.Parent = pGui
	
	-- FLASH LIGHT BUTTON (Top Left)
	local flashButton = Instance.new("TextButton")
	flashButton.Name = "FlashlightButton"
	flashButton.Size = UDim2.new(0, 120, 0, 45)
	flashButton.Position = UDim2.new(0, 20, 0, 20)
	flashButton.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
	flashButton.TextColor3 = Color3.fromRGB(255, 255, 255)
	flashButton.Font = Enum.Font.SourceSansBold
	flashButton.TextSize = 18
	flashButton.Text = "Flashlight: OFF"
	flashButton.Parent = screenGui
	Instance.new("UICorner", flashButton).CornerRadius = UDim.new(0, 8)
	
	-- SPRINT BUTTON (Top Right)
	local sprintButton = Instance.new("TextButton")
	sprintButton.Name = "SprintButton"
	sprintButton.Size = UDim2.new(0, 120, 0, 45)
	sprintButton.Position = UDim2.new(1, -140, 0, 20)
	sprintButton.BackgroundColor3 = Color3.fromRGB(30, 80, 30)
	sprintButton.TextColor3 = Color3.fromRGB(255, 255, 255)
	sprintButton.Font = Enum.Font.SourceSansBold
	sprintButton.TextSize = 18
	sprintButton.Text = "SPRINT"
	sprintButton.Parent = screenGui
	Instance.new("UICorner", sprintButton).CornerRadius = UDim.new(0, 8)
	
	-- HEALTH & STAMINA HUD (Bottom Left)
	local hudFrame = Instance.new("Frame")
	hudFrame.Name = "HUDFrame"
	hudFrame.Size = UDim2.new(0, 250, 0, 90)
	hudFrame.Position = UDim2.new(0, 20, 1, -110)
	hudFrame.BackgroundTransparency = 1
	hudFrame.Parent = screenGui
	
	-- Health Background Bar
	local healthBg = Instance.new("Frame")
	healthBg.Name = "HealthBg"
	healthBg.Size = UDim2.new(1, 0, 0, 25)
	healthBg.Position = UDim2.new(0, 0, 0, 10)
	healthBg.BackgroundColor3 = Color3.fromRGB(50, 10, 10)
	healthBg.Parent = hudFrame
	Instance.new("UICorner", healthBg).CornerRadius = UDim.new(0, 4)
	
	local healthBar = Instance.new("Frame")
	healthBar.Name = "Bar"
	healthBar.Size = UDim2.new(1, 0, 1, 0)
	healthBar.BackgroundColor3 = Color3.fromRGB(200, 30, 30)
	healthBar.Parent = healthBg
	Instance.new("UICorner", healthBar).CornerRadius = UDim.new(0, 4)
	
	local healthLabel = Instance.new("TextLabel")
	healthLabel.Size = UDim2.new(1, 0, 1, 0)
	healthLabel.BackgroundTransparency = 1
	healthLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
	healthLabel.Font = Enum.Font.SourceSansBold
	healthLabel.TextSize = 14
	healthLabel.Text = "HEALTH: 100%"
	healthLabel.Parent = healthBg
	
	-- Stamina Background Bar
	local staminaBg = Instance.new("Frame")
	staminaBg.Name = "StaminaBg"
	staminaBg.Size = UDim2.new(1, 0, 0, 25)
	staminaBg.Position = UDim2.new(0, 0, 0, 45)
	staminaBg.BackgroundColor3 = Color3.fromRGB(10, 40, 10)
	staminaBg.Parent = hudFrame
	Instance.new("UICorner", staminaBg).CornerRadius = UDim.new(0, 4)
	
	local staminaBar = Instance.new("Frame")
	staminaBar.Name = "Bar"
	staminaBar.Size = UDim2.new(1, 0, 1, 0)
	staminaBar.BackgroundColor3 = Color3.fromRGB(30, 180, 30)
	staminaBar.Parent = staminaBg
	Instance.new("UICorner", staminaBar).CornerRadius = UDim.new(0, 4)
	
	local staminaLabel = Instance.new("TextLabel")
	staminaLabel.Size = UDim2.new(1, 0, 1, 0)
	staminaLabel.BackgroundTransparency = 1
	staminaLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
	staminaLabel.Font = Enum.Font.SourceSansBold
	staminaLabel.TextSize = 14
	staminaLabel.Text = "STAMINA: 100%"
	staminaLabel.Parent = staminaBg
	
	return screenGui
end

local function createRealisticGameOverUI()
	local pGui = player:WaitForChild("PlayerGui")
	
	local oldUI = pGui:FindFirstChild("GameOverGui")
	if oldUI then oldUI:Destroy() end
	
	local screenGui = Instance.new("ScreenGui")
	screenGui.Name = "GameOverGui"
	screenGui.ResetOnSpawn = false
	
	-- Dark Vignette/Overlay background
	local background = Instance.new("Frame")
	background.Size = UDim2.new(1, 0, 1, 0)
	background.BackgroundColor3 = Color3.new(0, 0, 0)
	background.BackgroundTransparency = 1
	background.Parent = screenGui
	
	local textLabel = Instance.new("TextLabel")
	textLabel.Size = UDim2.new(1, 0, 1, 0)
	textLabel.BackgroundTransparency = 1
	textLabel.Text = "GAME OVER"
	textLabel.TextColor3 = Color3.new(0.5, 0, 0) -- Muted crimson red
	textLabel.Font = Enum.Font.SourceSansBold
	textLabel.TextSize = 72
	textLabel.TextTransparency = 1
	textLabel.Parent = screenGui
	
	screenGui.Parent = pGui
	return screenGui, background, textLabel
end

-- --- CHARACTER SETUP ENGINE ---
local function setupCharacter(character)
	task.wait(1.5)
	
	isDead = false
	deathCamCFrame = nil
	colorCorrection.Saturation = 0 -- Reset to normal colors
	stamina = MAX_STAMINA
	isSprinting = false

	if inputBeganConnection then inputBeganConnection:Disconnect() end
	if inputChangedConnection then inputChangedConnection:Disconnect() end
	if inputEndedConnection then inputEndedConnection:Disconnect() end
	if diedConnection then diedConnection:Disconnect() end
	if healthChangedConnection then healthChangedConnection:Disconnect() end
	if toolConnection then toolConnection:Disconnect() end

	local humanoid = character:WaitForChild("Humanoid")
	local root = character:WaitForChild("HumanoidRootPart")
	local head = character:WaitForChild("Head")

	humanoid.WalkSpeed = WALK_SPEED

	-- Setup Game HUD
	local hudGui = createGameUI()
	local hudFrame = hudGui:WaitForChild("HUDFrame")
	local healthBar = hudFrame.HealthBg.Bar
	local healthLabel = hudFrame.HealthBg.TextLabel
	local staminaBar = hudFrame.StaminaBg.Bar
	local staminaLabel = hudFrame.StaminaBg.TextLabel
	local flashButton = hudGui:WaitForChild("FlashlightButton")
	local sprintButton = hudGui:WaitForChild("SprintButton")

	-- Camera-locked Flashlight Setup (Fixed with Attachment)
	local flashlightAttachment = workspace.Terrain:FindFirstChild("FlashlightAttachment") or Instance.new("Attachment")
	flashlightAttachment.Name = "FlashlightAttachment"
	flashlightAttachment.Parent = workspace.Terrain

	local flashlight = flashlightAttachment:FindFirstChild("CameraFlashlight") or Instance.new("SpotLight")
	flashlight.Name = "CameraFlashlight"
	flashlight.Brightness = 12 -- High brightness to emphasize specular gloss highlights
	flashlight.Range = 90
	flashlight.Angle = 50
	flashlight.Enabled = false
	flashlight.Parent = flashlightAttachment

	flashButton.MouseButton1Click:Connect(function()
		if isDead then return end
		flashlight.Enabled = not flashlight.Enabled
		flashButton.Text = flashlight.Enabled and "Flashlight: ON" or "Flashlight: OFF"
		flashButton.BackgroundColor3 = flashlight.Enabled and Color3.fromRGB(100, 100, 30) or Color3.fromRGB(40, 40, 40)
	end)

	-- Sprint Button Multi-input Bindings
	sprintButton.MouseButton1Down:Connect(function() isSprinting = true end)
	sprintButton.MouseButton1Up:Connect(function() isSprinting = false end)

	-- Health System Hook
	local function updateHealthHUD()
		local healthPercent = math.clamp(humanoid.Health / humanoid.MaxHealth, 0, 1)
		TweenService:Create(healthBar, TweenInfo.new(0.2), {Size = UDim2.new(healthPercent, 0, 1, 0)}):Play()
		healthLabel.Text = "HEALTH: " .. math.floor(healthPercent * 100) .. "%"
	end
	updateHealthHUD()
	healthChangedConnection = humanoid:GetPropertyChangedSignal("Health"):Connect(updateHealthHUD)

	-- --- COMBAT AND ENEMY ELIMINATION DETECTION ---
	local function trackCombatInteractions(tool)
		if tool:IsA("Tool") then
			toolConnection = tool.Activated:Connect(function()
				soundPunch:Play()
				
				-- Raycast out from camera look vector to verify targets
				local rayParam = RaycastParams.new()
				rayParam.FilterDescendantsInstances = {character}
				rayParam.FilterType = Enum.RaycastFilterType.Exclude
				
				local hitResult = workspace:Raycast(head.Position, camera.CFrame.LookVector * 6, rayParam)
				if hitResult and hitResult.Instance then
					local enemyModel = hitResult.Instance:FindAncestorOfClass("Model")
					if enemyModel then
						local enemyHumanoid = enemyModel:FindFirstChildOfClass("Humanoid")
						if enemyHumanoid and enemyHumanoid.Health > 0 then
							task.delay(0.1, function()
								if enemyHumanoid.Health <= 0 then
									soundGore:Play()
								end
							end)
						end
					end
				end
			end)
		end
	end
	character.ChildAdded:Connect(trackCombatInteractions)
	for _, child in ipairs(character:GetChildren()) do trackCombatInteractions(child) end

	local repairing = false

	task.delay(2, function()
		if character.Parent and not isDead then
			player.CameraMode = Enum.CameraMode.LockFirstPerson
			camera.CameraType = Enum.CameraType.Scriptable
			camera.FieldOfView = FOV
		end
	end)

	camera:GetPropertyChangedSignal("CameraType"):Connect(function()
		if repairing or isDead then return end
		if camera.CameraType ~= Enum.CameraType.Scriptable then
			repairing = true
			task.delay(2, function()
				if character.Parent and not isDead then
					player.CameraMode = Enum.CameraMode.LockFirstPerson
					camera.CameraType = Enum.CameraType.Scriptable
					camera.FieldOfView = FOV
				end
				repairing = false
			end)
		end
	end)

	player.CameraMode = Enum.CameraMode.LockFirstPerson
	camera.CameraType = Enum.CameraType.Scriptable
	camera.FieldOfView = FOV
	humanoid.AutoRotate = false

	-- Realistic Game Over Sequence
	diedConnection = humanoid.Died:Connect(function()
		isDead = true
		hudGui:Destroy()
		flashlight.Enabled = false
		
		-- Freeze the camera's rotation context in world space right where they fell
		local lastCamCFrame = camera.CFrame
		-- Drop the height to simulate hitting the deck, tilt it sideways slightly
		deathCamCFrame = CFrame.new(lastCamCFrame.Position - Vector3.new(0, 3.5, 0)) * CFrame.Angles(0, 0, math.rad(45))
		
		local ui, bg, label = createRealisticGameOverUI()
		
		-- Dramatic Post-Processing and UI Fade In
		TweenService:Create(colorCorrection, TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Saturation = -1}):Play() -- Desaturate entirely
		TweenService:Create(blurEffect, TweenInfo.new(3), {Size = 20}):Play() -- Heavy blur eye strain
		TweenService:Create(bg, TweenInfo.new(2), {BackgroundTransparency = 0.2}):Play() -- Fade to near pitch black
		TweenService:Create(label, TweenInfo.new(3, Enum.EasingStyle.Sine, Enum.EasingDirection.In), {TextTransparency = 0}):Play()
		
		local respawnConn
		respawnConn = player.CharacterAdded:Connect(function()
			-- Smoothly clean up and restore vision settings upon respawn
			TweenService:Create(colorCorrection, TweenInfo.new(1), {Saturation = 0}):Play()
			TweenService:Create(blurEffect, TweenInfo.new(1), {Size = 0}):Play()
			TweenService:Create(bg, TweenInfo.new(0.5), {BackgroundTransparency = 1}):Play()
			TweenService:Create(label, TweenInfo.new(0.5), {TextTransparency = 1}):Play()
			
			task.delay(0.5, function() ui:Destroy() end)
			respawnConn:Disconnect()
		end)
	end)

	-- Input System
	inputBeganConnection = UserInputService.InputBegan:Connect(function(input, processed)
		if isDead then return end
		if input.UserInputType == Enum.UserInputType.Touch and not processed then
			if input.Position.X > camera.ViewportSize.X * 0.5 then
				rotatingTouch = input
			end
		end
		
		-- Sprint Activation (Left Shift)
		if input.KeyCode == Enum.KeyCode.LeftShift then
			isSprinting = true
		end
	end)

	inputChangedConnection = UserInputService.InputChanged:Connect(function(input)
		if isDead then return end
		local delta = Vector2.new(input.Delta.X, input.Delta.Y)

		if input.UserInputType == Enum.UserInputType.MouseMovement then
			yaw -= delta.X * LOOK_SPEED
			pitch -= delta.Y * LOOK_SPEED
		elseif input.UserInputType == Enum.UserInputType.Touch then
			if input == rotatingTouch then
				yaw -= delta.X * LOOK_SPEED
				pitch -= delta.Y * LOOK_SPEED
			end
		end
		pitch = math.clamp(pitch, -1.4, 1.4)
	end)

	inputEndedConnection = UserInputService.InputEnded:Connect(function(input)
		if input == rotatingTouch then
			rotatingTouch = nil
		end
		
		-- Sprint Deactivation
		if input.KeyCode == Enum.KeyCode.LeftShift then
			isSprinting = false
		end
	end)

	-- Visibility Updates
	local function updateVisibility()
		for _, obj in ipairs(character:GetDescendants()) do
			local isInTool = obj:FindFirstAncestorOfClass("Tool") ~= nil

			if obj:IsA("BasePart") then
				local n = obj.Name
				local visible =
					n == "Left Arm" or n == "Right Arm" or
					n == "Left Leg" or n == "Right Leg" or
					n == "LeftHand" or n == "RightHand" or
					n == "LeftLowerArm" or n == "RightLowerArm" or
					n == "LeftUpperArm" or n == "RightUpperArm" or
					n == "LeftFoot" or n == "RightFoot" or
					n == "LeftLowerLeg" or n == "RightLowerLeg" or
					n == "LeftUpperLeg" or n == "RightUpperLeg" or
					n == "Torso" or n == "UpperTorso" or n == "LowerTorso"

				obj.LocalTransparencyModifier = (isInTool or visible) and 0 or 1
			end
		end

		head.LocalTransparencyModifier = 1
		if head:FindFirstChild("FaceFrontAttachment") then
			for _, face in ipairs(head:GetChildren()) do
				if face:IsA("Decal") then face.Transparency = 1 end
			end
		end
	end

	if renderConnection then
		renderConnection:Disconnect()
	end

	local lastSprintTime = 0
	local lastStepTime = 0

	-- --- RENDER LOOP RUNTIME ---
	renderConnection = RunService.RenderStepped:Connect(function(dt)
		if not character.Parent then return end

		updateVisibility()

		-- Dynamic Day/Mid-day/Evening/Night Cycle Processing 
		local currentMinutes = Lighting:GetMinutesAfterMidnight()
		local nextMinutes = currentMinutes + (dt * DAY_SPEED * 60)
		Lighting:SetMinutesAfterMidnight(nextMinutes)

		-- Dynamic Ambient Atmospheric Changes based on clock time
		local timeInHours = nextMinutes / 60
		if timeInHours > 18 or timeInHours < 6 then
			-- Pitch black environment baseline settings
			Lighting.Ambient = Color3.fromRGB(4, 4, 8)
			Lighting.OutdoorAmbient = Color3.fromRGB(0, 0, 4)
			Lighting.Brightness = 0.02
		else
			-- Standard Day presets
			Lighting.Ambient = Color3.fromRGB(120, 120, 120)
			Lighting.OutdoorAmbient = Color3.fromRGB(140, 140, 140)
			Lighting.Brightness = 2
		end

		-- Handle the camera if dead
		if isDead and deathCamCFrame then
			camera.CFrame = camera.CFrame:Lerp(deathCamCFrame, dt * 4)
			camera.FieldOfView = FOV
			return
		end

		local isMoving = humanoid.MoveDirection.Magnitude > 0.05

		-- Stamina Management Loop
		if isSprinting and isMoving and stamina > 0 then
			stamina = math.clamp(stamina - dt, 0, MAX_STAMINA)
			humanoid.WalkSpeed = SPRINT_SPEED
			lastSprintTime = os.clock()
		else
			humanoid.WalkSpeed = WALK_SPEED
			if os.clock() - lastSprintTime >= staminaRechargeDelay then
				stamina = math.clamp(stamina + dt, 0, MAX_STAMINA)
			end
		end

		-- Update Stamina HUD UI
		local staminaPercent = stamina / MAX_STAMINA
		staminaBar.Size = UDim2.new(staminaPercent, 0, 1, 0)
		staminaLabel.Text = "STAMINA: " .. math.floor(staminaPercent * 100) .. "%"

		-- --- MATERIAL DYNAMIC FOOTSTEPS ---
		if isMoving and humanoid.FloorMaterial ~= Enum.Material.Air then
			local stepInterval = (humanoid.WalkSpeed == SPRINT_SPEED) and 0.32 or 0.52
			if os.clock() - lastStepTime >= stepInterval then
				lastStepTime = os.clock()
				
				local floorMat = humanoid.FloorMaterial
				if floorMat == Enum.Material.Grass or floorMat == Enum.Material.LeafyGrass then
					soundStepGrass:Play()
				elseif floorMat == Enum.Material.Metal or floorMat == Enum.Material.CorrodedMetal or floorMat == Enum.Material.DiamondPlate then
					soundStepMetal:Play()
				else
					soundStepDefault:Play()
				end
			end
		end

		if isMoving ~= lastMoveState then
			lastMoveState = isMoving
			if isMoving then
				UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
			else
				UserInputService.MouseBehavior = Enum.MouseBehavior.Default
			end
		end

		-- Dynamic Bob speed variation depending on sprint speed
		if isMoving then
			local _, cameraYaw, _ = camera.CFrame:ToOrientation()
			root.CFrame = CFrame.new(root.Position) * CFrame.Angles(0, cameraYaw, 0)
			
			local bobVelocity = (humanoid.WalkSpeed == SPRINT_SPEED) and 18 or 12
			bob += dt * bobVelocity
		else
			bob = 0
		end

		local currentBobAmount = (humanoid.WalkSpeed == SPRINT_SPEED) and 0.14 or 0.08
		local bobOffset = math.sin(bob) * currentBobAmount

		smoothYaw = smoothYaw + (yaw - smoothYaw) * SMOOTHING
		smoothPitch = smoothPitch + (pitch - smoothPitch) * SMOOTHING

		-- Calculate Motion Blur
		local yawDelta = math.abs(smoothYaw - lastYaw)
		local pitchDelta = math.abs(smoothPitch - lastPitch)
		local totalDelta = (yawDelta + pitchDelta) / dt
		blurEffect.Size = math.clamp(totalDelta * 0.5, 0, 24)
		
		lastYaw = smoothYaw
		lastPitch = smoothPitch

		-- Calculate Camera Jitter
		local currentTime = os.clock() * JITTER_SPEED
		local jitterX = math.noise(currentTime, 0, 0) * JITTER_INTENSITY
		local jitterY = math.noise(0, currentTime, 0) * JITTER_INTENSITY
		local jitterZ = math.noise(0, 0, currentTime) * JITTER_INTENSITY
		local jitterCFrame = CFrame.new(jitterX, jitterY, jitterZ)

		-- FIXED CAMERA STRAPPED TO HEAD (Ignores Torso adjustments entirely)
		local camPos = head.Position + Vector3.new(0, bobOffset, 0)
		local camRot = CFrame.Angles(0, smoothYaw, 0) * CFrame.Angles(smoothPitch, 0, 0)

		camera.CFrame = CFrame.new(camPos) * camRot * jitterCFrame
		camera.FieldOfView = FOV

		-- Lock Flashlight strictly to Camera Coordinate Matrix (Fixed via Attachment)
		if flashlight.Enabled and flashlightAttachment then
			flashlightAttachment.WorldCFrame = camera.CFrame
		end
	end)
end

if player.Character then
	setupCharacter(player.Character)
end

player.CharacterAdded:Connect(setupCharacter)

Features & Information

Most op first person script

Community Comments (0)

No comments yet for this script.

More Scripts for Universal Scripts