Загрузка данных
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
--------------------------------------------------
-- SETTINGS
--------------------------------------------------
-- Walking
local WALK_BOB_AMOUNT = 0.035
local WALK_BOB_SPEED = 8
-- Sprint
local SPRINT_BOB_AMOUNT = 0.065
local SPRINT_BOB_SPEED = 12
-- Head tilt
local HEAD_TILT_AMOUNT = 1.2
-- Breathing
local BREATH_AMOUNT = 0.008
local BREATH_SPEED = 1.5
-- Landing
local 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_AMOUNT = 0.025
local LOW_HEALTH_SPEED = 5
-- Fatigue
local MAX_RUN_TIME = 12
local MAX_FATIGUE = 1
-- Smoothness
local EFFECT_SMOOTH = 10
--------------------------------------------------
-- VARIABLES
--------------------------------------------------
local character
local humanoid
local rootPart
local bobTime = 0
local impactTime = 0
local lowHealthTime = 0
local shake = 0
local runTime = 0
local fatigue = 0
local wasAirborne = false
local fallStartY = nil
local currentOffset = Vector3.zero
local currentRotation = Vector3.zero
local lastHealth = 100
--------------------------------------------------
-- CHARACTER SETUP
--------------------------------------------------
local function setupCharacter(char)
character = char
humanoid =
char:WaitForChild("Humanoid")
rootPart =
char:WaitForChild("HumanoidRootPart")
lastHealth = humanoid.Health
bobTime = 0
impactTime = 0
lowHealthTime = 0
shake = 0
runTime = 0
fatigue = 0
wasAirborne = false
fallStartY = nil
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)
--------------------------------------------------
-- CAMERA EFFECTS
--------------------------------------------------
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 = Vector3.new(
rootPart.AssemblyLinearVelocity.X,
0,
rootPart.AssemblyLinearVelocity.Z
)
local speed =
velocity.Magnitude
local moving =
speed > 1
--------------------------------------------------
-- 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
)
--------------------------------------------------
-- HEAVY LANDING
--------------------------------------------------
if fallDistance >= MIN_HEAVY_FALL then
local strength =
math.clamp(
(fallDistance - MIN_HEAVY_FALL)
/
(MAX_HEAVY_FALL - MIN_HEAVY_FALL),
0,
1
)
local landingStrength =
LANDING_SHAKE
+
strength
*
(
HEAVY_LANDING_SHAKE
- LANDING_SHAKE
)
shake =
math.max(
shake,
landingStrength
)
else
shake =
math.max(
shake,
LANDING_SHAKE
)
end
impactTime = 0
end
fallStartY = nil
end
wasAirborne = airborne
--------------------------------------------------
-- DETECT SPRINT
--------------------------------------------------
-- Works with the separate Sprint script.
-- Sprint normally changes WalkSpeed.
local isSprinting =
moving
and humanoid.WalkSpeed > 16
--------------------------------------------------
-- 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
--------------------------------------------------
-- BOB
--------------------------------------------------
local targetOffset =
Vector3.zero
local targetRotation =
Vector3.zero
if moving and not airborne then
local bobSpeed
local bobAmount
if isSprinting then
bobSpeed =
SPRINT_BOB_SPEED
bobAmount =
SPRINT_BOB_AMOUNT
*
(
1
+
fatigue * 0.35
)
else
bobSpeed =
WALK_BOB_SPEED
bobAmount =
WALK_BOB_AMOUNT
end
bobTime +=
deltaTime * bobSpeed
--------------------------------------------------
-- VERTICAL BOB
--------------------------------------------------
local vertical =
math.sin(
bobTime * 2
)
*
bobAmount
--------------------------------------------------
-- HORIZONTAL BOB
--------------------------------------------------
local horizontal =
math.cos(
bobTime
)
*
bobAmount
*
0.35
targetOffset =
Vector3.new(
horizontal,
vertical,
0
)
--------------------------------------------------
-- HEAD TILT
--------------------------------------------------
local tilt =
math.sin(
bobTime
)
*
HEAD_TILT_AMOUNT
targetRotation =
Vector3.new(
math.sin(bobTime * 2)
* 0.25,
0,
tilt
)
else
--------------------------------------------------
-- BREATHING
--------------------------------------------------
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 EFFECTS
--------------------------------------------------
local smooth =
math.clamp(
deltaTime
*
EFFECT_SMOOTH,
0,
1
)
currentOffset =
currentOffset:Lerp(
targetOffset,
smooth
)
currentRotation =
currentRotation:Lerp(
targetRotation,
smooth
)
--------------------------------------------------
-- DAMAGE / LANDING SHAKE
--------------------------------------------------
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_AMOUNT
*
danger
currentOffset +=
Vector3.new(
pulse * 0.5,
pulse,
0
)
currentRotation +=
Vector3.new(
0,
0,
math.rad(
pulse * 15
)
)
else
lowHealthTime = 0
end
--------------------------------------------------
-- APPLY OVER EXISTING CAMERA
--------------------------------------------------
-- IMPORTANT:
-- Your First Person script controls the camera.
-- This script only adds effects AFTER it.
camera.CFrame =
camera.CFrame
*
CFrame.new(
currentOffset
)
*
CFrame.Angles(
math.rad(
currentRotation.X
),
math.rad(
currentRotation.Y
),
math.rad(
currentRotation.Z
)
)
end
)