Загрузка данных
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Lighting = game:GetService("Lighting")
-- ================= НАСТРОЙКИ =================
local Settings = {
-- Позиция камеры
CameraHeight = -0.25, -- высота: больше = выше, меньше = ниже
CameraBack = -1.5, -- вперёд/назад: минус = вперёд, плюс = назад
CameraSide = 0, -- влево/вправо: минус = влево, плюс = вправо
-- FOV (максимум в Roblox = 120)
IdleFOV = 90, -- когда стоишь
WalkFOV = 100, -- при ходьбе
SprintFOV = 120, -- при беге
FOVSmoothing = 6, -- плавность смены FOV (больше = быстрее)
-- Движение
WalkSpeed = 16,
SprintSpeed = 26,
SprintKey = Enum.KeyCode.LeftShift, -- бег
ToggleCameraKey = Enum.KeyCode.F, -- выход из / вход в режим камеры
-- Покачивание при ходьбе и беге
BobEnabled = true,
BobVertical = 0.28,
BobHorizontal = 0.2,
BobSpeed = 0.45,
BobRoll = 0.035,
BobPitch = 0.025,
SprintBobMultiplier = 1.8,
BobSmoothing = 10,
-- Покачивание в покое (дыхание)
IdleEnabled = true,
IdleVertical = 0.03,
IdleHorizontal = 0.015,
IdleRotation = 0.004,
IdleSpeed = 1.1,
-- Усталость от долгого бега
FatigueEnabled = true,
BlurAfter = 30, -- через сколько секунд бега появляется размытие
BlurDuration = 10, -- сколько оно длится
BlurMaxSize = 8,
DimAfter = 60, -- через сколько секунд бега появляется затемнение
DimDuration = 30, -- сколько оно длится
DimBrightness = -0.2,
DimSaturation = -0.35,
-- Третье лицо (после нажатия F)
ThirdPersonMinZoom = 10,
ThirdPersonMaxZoom = 400,
-- Видимость тела
ViewAccessories = false,
ViewModels = false,
HeadLocalTransparency = 1,
HiddenParts = { "UpperTorso", "LeftUpperArm", "RightUpperArm" },
}
-- =============================================
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
local character, humanoid, root
local firstPerson = true
local sprinting = false
local bobTime = 0
local idleTime = 0
local bobOffset = Vector3.zero
local moveAlpha = 0
local locked = {}
-- Эффекты усталости
for _, name in ipairs({ "FatigueBlur", "FatigueDim" }) do
local old = Lighting:FindFirstChild(name)
if old then old:Destroy() end
end
local blur = Instance.new("BlurEffect")
blur.Name = "FatigueBlur"
blur.Size = 0
blur.Parent = Lighting
local dim = Instance.new("ColorCorrectionEffect")
dim.Name = "FatigueDim"
dim.Parent = Lighting
local sprintTime = 0
local blurT = nil
local dimT = nil
local blurFired = false
local function envelope(t, duration, fadeIn, fadeOut)
return math.clamp(t / fadeIn, 0, 1) * math.clamp((duration - t) / fadeOut, 0, 1)
end
local function resetFatigue()
sprintTime = 0
blurT = nil
dimT = nil
blurFired = false
blur.Size = 0
dim.Brightness = 0
dim.Saturation = 0
end
local function classify(part)
if not part:IsA("BasePart") or not character then return nil end
if part.Name == "Head" and part.Parent == character then
return Settings.HeadLocalTransparency
end
if part:FindFirstAncestorOfClass("Accessory") then
return Settings.ViewAccessories and 0 or nil
end
if part.Parent == character then
if table.find(Settings.HiddenParts, part.Name) then
return 1
end
return 0
end
if part:FindFirstAncestorOfClass("Model") ~= character and Settings.ViewModels then
return 0
end
return nil
end
local function register(part)
local value = classify(part)
if value ~= nil then
locked[part] = value
end
end
local function applyMode()
if not humanoid then return end
if firstPerson then
player.CameraMode = Enum.CameraMode.LockFirstPerson
player.CameraMinZoomDistance = 0.5
player.CameraMaxZoomDistance = 0.5
else
player.CameraMode = Enum.CameraMode.Classic
player.CameraMinZoomDistance = Settings.ThirdPersonMinZoom
player.CameraMaxZoomDistance = Settings.ThirdPersonMaxZoom
humanoid.CameraOffset = Vector3.zero
camera.FieldOfView = 70
for part in pairs(locked) do
part.LocalTransparencyModifier = 0
end
end
end
local function setupCharacter(char)
character = char
humanoid = char:WaitForChild("Humanoid")
root = char:WaitForChild("HumanoidRootPart")
locked = {}
sprinting = false
bobTime = 0
bobOffset = Vector3.zero
moveAlpha = 0
resetFatigue()
humanoid.WalkSpeed = Settings.WalkSpeed
for _, d in ipairs(char:GetDescendants()) do
register(d)
end
char.DescendantAdded:Connect(register)
char.DescendantRemoving:Connect(function(d)
locked[d] = nil
end)
applyMode()
end
-- Бег и переключение камеры
UserInputService.InputBegan:Connect(function(input, processed)
if processed or not humanoid then return end
if input.KeyCode == Settings.SprintKey then
sprinting = true
humanoid.WalkSpeed = Settings.SprintSpeed
elseif input.KeyCode == Settings.ToggleCameraKey then
firstPerson = not firstPerson
applyMode()
end
end)
UserInputService.InputEnded:Connect(function(input)
if input.KeyCode == Settings.SprintKey and humanoid then
sprinting = false
humanoid.WalkSpeed = Settings.WalkSpeed
end
end)
-- Усталость
RunService.Heartbeat:Connect(function(dt)
if not Settings.FatigueEnabled or not root or not humanoid then return end
local speed = (root.AssemblyLinearVelocity * Vector3.new(1, 0, 1)).Magnitude
local running = sprinting and speed > 10 and humanoid.Health > 0
if running then
sprintTime += dt
if sprintTime >= Settings.BlurAfter and not blurFired then
blurFired = true
blurT = 0
end
if sprintTime >= Settings.DimAfter then
dimT = 0
sprintTime = 0
blurFired = false
end
else
sprintTime = math.max(0, sprintTime - dt * 2)
if sprintTime < Settings.BlurAfter then
blurFired = false
end
end
if blurT then
blurT += dt
if blurT >= Settings.BlurDuration then
blurT = nil
blur.Size = 0
else
blur.Size = Settings.BlurMaxSize * envelope(blurT, Settings.BlurDuration, 1.5, 3)
end
end
if dimT then
dimT += dt
if dimT >= Settings.DimDuration then
dimT = nil
dim.Brightness = 0
dim.Saturation = 0
else
local e = envelope(dimT, Settings.DimDuration, 3, 6)
dim.Brightness = Settings.DimBrightness * e
dim.Saturation = Settings.DimSaturation * e
end
end
end)
-- Камера каждый кадр
RunService:BindToRenderStep("FirstPersonBody", Enum.RenderPriority.Camera.Value + 1, function(dt)
if not humanoid or not root or humanoid.Health <= 0 or not firstPerson then return end
for part, value in pairs(locked) do
part.LocalTransparencyModifier = value
end
local speed = (root.AssemblyLinearVelocity * Vector3.new(1, 0, 1)).Magnitude
local onGround = humanoid.FloorMaterial ~= Enum.Material.Air
local moving = onGround and speed > 1 and humanoid.MoveDirection.Magnitude > 0
moveAlpha += ((moving and 1 or 0) - moveAlpha) * math.clamp(dt * 8, 0, 1)
local mult = sprinting and Settings.SprintBobMultiplier or 1
local walkOffset = Vector3.zero
local roll, pitch = 0, 0
if Settings.BobEnabled and moving then
bobTime += dt * speed * Settings.BobSpeed
end
if Settings.BobEnabled then
walkOffset = Vector3.new(
math.sin(bobTime) * Settings.BobHorizontal * mult,
math.abs(math.sin(bobTime)) * Settings.BobVertical * mult - Settings.BobVertical * mult * 0.5,
0
) * moveAlpha
roll = math.sin(bobTime) * Settings.BobRoll * mult * moveAlpha
pitch = math.sin(bobTime * 2) * Settings.BobPitch * mult * moveAlpha
end
local idleOffset = Vector3.zero
local idleRoll, idlePitch = 0, 0
if Settings.IdleEnabled then
idleTime += dt * Settings.IdleSpeed
local idleAlpha = 1 - moveAlpha
idleOffset = Vector3.new(
math.sin(idleTime * 0.6) * Settings.IdleHorizontal,
math.sin(idleTime) * Settings.IdleVertical,
0
) * idleAlpha
idleRoll = math.sin(idleTime * 0.7) * Settings.IdleRotation * idleAlpha
idlePitch = math.sin(idleTime * 0.9 + 1) * Settings.IdleRotation * idleAlpha
end
local base = Vector3.new(Settings.CameraSide, Settings.CameraHeight, Settings.CameraBack)
local target = walkOffset + idleOffset
bobOffset = bobOffset:Lerp(target, math.clamp(dt * Settings.BobSmoothing, 0, 1))
humanoid.CameraOffset = base + bobOffset
camera.CFrame = camera.CFrame * CFrame.Angles(pitch + idlePitch, 0, roll + idleRoll)
-- FOV: стоишь / идёшь / бежишь
local targetFov = Settings.IdleFOV
if moving then
targetFov = sprinting and Settings.SprintFOV or Settings.WalkFOV
end
targetFov = math.clamp(targetFov, 1, 120)
camera.FieldOfView += (targetFov - camera.FieldOfView) * math.clamp(dt * Settings.FOVSmoothing, 0, 1)
end)
-- Камера не липнет к сиденьям
camera:GetPropertyChangedSignal("CameraSubject"):Connect(function()
if humanoid and camera.CameraSubject and camera.CameraSubject:IsA("VehicleSeat") then
camera.CameraSubject = humanoid
end
end)
player.CharacterAdded:Connect(setupCharacter)
if player.Character then
setupCharacter(player.Character)
end