--legends:
--[s]: speed
--[d]: damper
--[t]: target
--[p]: position
--[v]: velocity


local SpeedSpring = Spring.spring.new()
SpeedSpring.s = 16
local SwaySpring = Spring.spring.new(0)
SwaySpring.s = 4
SwaySpring.d = 1
local SwaySpeed = Spring.spring.new(0)
SwaySpeed.s = 6
SwaySpeed.d = 1
SwaySpeed.t = 1
local DamageSpring = Spring.spring.new(Vector3.new())
DamageSpring.s = 20
DamageSpring.d = 0.75
local ImpactSpring = Spring.spring.new(Vector3.new())
ImpactSpring.s	= 15
ImpactSpring.d	= 1

local OffStates = {"Jumping", "PlatformStanding", "Ragdoll", "Seated", "FallingDown", "FreeFalling", "GettingUp", "Swimming", "Climbing"}
local OnStates = {"Running"}

local speed = 0
local distance = 0
local swayT = 0
local lastHealth = Humanoid.Health
local isFalling = false
local debounce = false

for _, state in pairs(OffStates) do
	Humanoid[state]:Connect(function()
		active = false
	end)
end

for _, state in pairs(OnStates) do
	Humanoid[state]:Connect(function(speed)
		active = (speed > 1)
	end)
end

local function GetHit(d)
  	local l = CFrame.new():VectorToObjectSpace(d)
  	DamageSpring:Accelerate(Vector3.new(l.Z, 0, -l.X) * 0.25)
	Thread:Wait(0.03)
	DamageSpring:Accelerate(Vector3.new(-l.Z, 0, 0) * 0.25)
end

local function HealthChanged(health)
	if lastHealth > health and lastHealth - health >= 5 then
		if Humanoid.Health ~= Humanoid.MaxHealth then
			local damageDealt = lastHealth - health
			Thread:Spawn(function()
				local dir = Vector3.new(0, 0, 0)
				if Humanoid:FindFirstChild("creator") then
					local killer = Humanoid.creator
					local killerChar = killer.Value.Character
					local killerHum = killerChar:FindFirstChildOfClass("Humanoid")
					local killerHRP = killerChar:FindFirstChild("HumanoidRootPart")
					if killerChar and killerHRP and killerHum and killerHum.Health > 0 then
						dir = (Camera.CFrame.p - killerHRP.Position).Unit
					else
						dir = (Camera.CFrame.p - HumanoidRootPart.Position).Unit
					end
				else
					dir = (Camera.CFrame.p - HumanoidRootPart.Position).Unit
				end
				GetHit((-damageDealt / 12 + 4.166666666666667) * dir)
			end)
		end
	end
	lastHealth = health
end

Humanoid.FreeFalling:Connect(function(falling)
	isFalling = falling
	if isFalling and not debounce then
		debounce = true
		local maxHeight, lowHeight = 0, math.huge
		while isFalling do
			local height = HumanoidRootPart.Position.Y
			if height > maxHeight then
				maxHeight = height
			end
			if height < lowHeight then
				lowHeight = height
			end
			Thread:Wait()
		end
		local fallHeight = maxHeight - lowHeight
		local impactHeight = fallHeight - GeneralSettings.LowestFallHeight
		if impactHeight > 0 then
			--local damage = impactHeight * (humanoid.MaxHealth / GeneralSettings.MaxFallHeight)
			--humanoid:TakeDamage(damage)
			ImpactSpring:Accelerate(Vector3.new(0, 0, math.random(-impactHeight, impactHeight) / 5))
		end
		debounce = false
	end
end)

RunService.RenderStepped:Connect(function(dt)
	if Character and HumanoidRootPart and Humanoid then
		local RelativeVelocity = CFrame.new().VectorToObjectSpace(HumanoidRootPart.CFrame, HumanoidRootPart.Velocity)
		SpeedSpring.t = (active and Humanoid.Health > 0) and (Vector3.new(1, 0, 1) * RelativeVelocity).Magnitude or 0
		speed = SpeedSpring.p
		distance = distance + dt * SpeedSpring.p
		swayT = swayT + dt * SwaySpeed.p
		if GeneralSettings.FpsCam then
			local CF = CFrame.new()
			CF = Camera.CoordinateFrame
		    local T = swayT
		    local S, D = 0.5 * speed, distance * 6.28318 / 4 * 3 / 4
		    local SS = SwaySpring.p
			local BobAngles = Math.FromAxisAngle(S * math.cos(D + 2) / 2048, S * math.cos(D / 2) / 2048, S * math.cos(D / 2 + 2) / 4096) * Math.FromAxisAngle(SS * math.cos(2 * T + 2) / 2048, SS * math.cos(2 * T / 2) / 2048, SS * math.cos(2 * T / 2 - 2) / 4096)
			local DamageAngles = Math.FromAxisAngle(DamageSpring.p)
			local ImpactAngles = Math.FromAxisAngle(ImpactSpring.p)
			if GeneralSettings.CamBobble then
				CF = CF * BobAngles
			end
			if GeneralSettings.CamHurt then
				CF = CF * DamageAngles
			end
			if GeneralSettings.CamImpact then
				CF = CF * ImpactAngles
			end
			Camera.CoordinateFrame = CF
		end
	end
end)

Humanoid.HealthChanged:Connect(HealthChanged)

Humanoid.Died:Connect(function()
	HealthChanged(20)
end)

HealthChanged(Humanoid.Health)