Загрузка данных
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
-- CAMERA
local NORMAL_FOV = 70
local SPRINT_FOV = 78
local SPRINT_SPEED = 20
-- WALK BOB
local WALK_BOB_AMOUNT = 0.035
local RUN_BOB_AMOUNT = 0.065
local WALK_BOB_SPEED = 8
local RUN_BOB_SPEED = 12
-- BREATHING
local BREATH_AMOUNT = 0.008
local BREATH_SPEED = 1.5
-- LANDING
local NORMAL_LANDING_SHAKE = 0.12
local HEAVY_LANDING_SHAKE = 0.30
local MIN_HEAVY_FALL = 5
local MAX_HEAVY_FALL = 25
-- DAMAGE
local DAMAGE_SHAKE = 0.18
-- LOW HEALTH
local LOW_HEALTH_THRESHOLD = 0.35
local LOW_HEALTH_SHAKE = 0.025
local LOW_HEALTH_SPEED = 5
-- FATIGUE
local MAX_RUN_TIME = 12
local MAX_FATIGUE = 1
-- SMOOTHNESS
local EFFECT_SMOOTH = 10
local FOV_SMOOTH = 7
-- HEAD TILT
local HEAD_TILT_AMOUNT = 1.2
local character
local humanoid
local rootPart
local bobTime = 0
local lowHealthTime = 0
local impactTime = 0
local shake = 0
local fatigue = 0
local runTime = 0
local lastHealth = 100
local wasAirborne = false
local fallStartY = nil
local currentOffset = Vector3.zero
local currentRotation = Vector3.zero
local function setupCharacter(char)
character = char
humanoid = char:WaitForChild("Humanoid")
rootPart = char:WaitForChild("HumanoidRootPart")
lastHealth = humanoid.Health
wasAirborne = false
fallStartY = nil
bobTime = 0
lowHealthTime = 0
impactTime = 0
shake = 0
fatigue = 0
runTime = 0
currentOffset = Vector3.zero
currentRotation = Vector3.zero
humanoid.HealthChanged:Connect(function(health)
if health < lastHealth then
shake = math.max(shake, DAMAGE_SHAKE)
impactTime = 0
end
lastHealth = health
end)
end
if player.Character then
setupCharacter(player.Character)
end
player.CharacterAdded:Connect(setupCharacter)
RunService:BindToRenderStep(
"AdvancedCameraEffects",
Enum.RenderPriority.Camera.Value + 5,
function(deltaTime)
local camera = workspace.CurrentCamera
if not character or not humanoid or not rootPart then
return
end
if humanoid.Health <= 0 then
return
end
--------------------------------------------------
-- MOVEMENT
--------------------------------------------------
local velocity = rootPart.AssemblyLinearVelocity
local horizontalVelocity = Vector3.new(
velocity.X,
0,
velocity.Z
)
local speed = horizontalVelocity.Magnitude
local moving = humanoid.MoveDirection.Magnitude > 0.05
local isSprinting =
moving
and speed >= SPRINT_SPEED
--------------------------------------------------
-- HUMANOID STATE
--------------------------------------------------
local state = humanoid:GetState()
local airborne =
state == Enum.HumanoidStateType.Jumping
or state == Enum.HumanoidStateType.Freefall
--------------------------------------------------
-- FALL DETECTION
--------------------------------------------------
if airborne and not wasAirborne then
fallStartY = rootPart.Position.Y
end
if not airborne and wasAirborne then
if fallStartY then
local fallDistance =
math.max(
0,
fallStartY - rootPart.Position.Y
)
if fallDistance >= MIN_HEAVY_FALL then
local strength =
math.clamp(
(fallDistance - MIN_HEAVY_FALL)
/ (MAX_HEAVY_FALL - MIN_HEAVY_FALL),
0,
1
)
local landingStrength =
NORMAL_LANDING_SHAKE
+ strength
* (HEAVY_LANDING_SHAKE - NORMAL_LANDING_SHAKE)
shake = math.max(
shake,
landingStrength
)
impactTime = 0
else
shake = math.max(
shake,
NORMAL_LANDING_SHAKE
)
end
else
shake = math.max(
shake,
NORMAL_LANDING_SHAKE
)
end
fallStartY = nil
end
wasAirborne = airborne
--------------------------------------------------
-- FATIGUE
--------------------------------------------------
if isSprinting and not airborne then
runTime = math.min(
runTime + deltaTime,
MAX_RUN_TIME
)
fatigue =
math.clamp(
runTime / MAX_RUN_TIME,
0,
MAX_FATIGUE
)
else
runTime = math.max(
runTime - deltaTime * 2,
0
)
fatigue =
math.clamp(
runTime / MAX_RUN_TIME,
0,
MAX_FATIGUE
)
end
--------------------------------------------------
-- TARGET CAMERA EFFECT
--------------------------------------------------
local targetOffset = Vector3.zero
local targetRotation = Vector3.zero
if moving and not airborne then
local bobSpeed
local bobAmount
if isSprinting then
bobSpeed = RUN_BOB_SPEED
bobAmount =
RUN_BOB_AMOUNT
* (1 + fatigue * 0.35)
else
bobSpeed = WALK_BOB_SPEED
bobAmount = WALK_BOB_AMOUNT
end
bobTime += deltaTime * bobSpeed
local vertical =
math.sin(bobTime * 2)
* bobAmount
local horizontal =
math.cos(bobTime)
* bobAmount
* 0.35
targetOffset = Vector3.new(
horizontal,
vertical,
0
)
local headTilt =
math.sin(bobTime)
* HEAD_TILT_AMOUNT
targetRotation = Vector3.new(
math.sin(bobTime * 2) * 0.25,
0,
headTilt
)
else
bobTime += deltaTime * BREATH_SPEED
local breathing =
math.sin(bobTime)
* BREATH_AMOUNT
local fatigueBreathing =
1 + fatigue * 0.5
targetOffset = Vector3.new(
0,
breathing * fatigueBreathing,
0
)
targetRotation = Vector3.zero
end
--------------------------------------------------
-- SMOOTH EFFECT
--------------------------------------------------
local smooth =
math.clamp(
deltaTime * EFFECT_SMOOTH,
0,
1
)
currentOffset =
currentOffset:Lerp(
targetOffset,
smooth
)
currentRotation =
currentRotation:Lerp(
targetRotation,
smooth
)
--------------------------------------------------
-- DAMAGE / LANDING
--------------------------------------------------
if shake > 0 then
shake =
math.max(
shake - deltaTime * 1.8,
0
)
impactTime += deltaTime * 35
local shakeX =
math.sin(impactTime * 1.7)
* shake
local shakeY =
math.cos(impactTime * 2.3)
* shake
local shakeZ =
math.sin(impactTime * 2.8)
* shake
currentOffset += Vector3.new(
shakeX,
shakeY,
shakeZ
)
currentRotation += Vector3.new(
math.rad(shakeY * 30),
math.rad(shakeX * 20),
math.rad(shakeZ * 30)
)
end
--------------------------------------------------
-- LOW HEALTH
--------------------------------------------------
local healthRatio =
humanoid.Health
/ math.max(humanoid.MaxHealth, 1)
if healthRatio <= LOW_HEALTH_THRESHOLD then
local danger =
1
- math.clamp(
healthRatio / LOW_HEALTH_THRESHOLD,
0,
1
)
lowHealthTime +=
deltaTime
* LOW_HEALTH_SPEED
local pulse =
math.sin(lowHealthTime)
* LOW_HEALTH_SHAKE
* danger
currentOffset += Vector3.new(
pulse * 0.5,
pulse,
0
)
currentRotation += Vector3.new(
0,
0,
math.rad(pulse * 15)
)
else
lowHealthTime = 0
end
--------------------------------------------------
-- FOV
--------------------------------------------------
local targetFOV = NORMAL_FOV
if isSprinting and not airborne then
targetFOV = SPRINT_FOV
end
targetFOV -= fatigue * 2
camera.FieldOfView +=
(targetFOV - camera.FieldOfView)
* math.clamp(
deltaTime * FOV_SMOOTH,
0,
1
)
--------------------------------------------------
-- APPLY EFFECT WITHOUT MOVING CAMERA DIRECTION
--------------------------------------------------
camera.CFrame =
camera.CFrame
* CFrame.new(currentOffset)
* CFrame.Angles(
math.rad(currentRotation.X),
0,
math.rad(currentRotation.Z)
)
end
)