local v={}v.__index=v local f=Vector3.new local N=math.noise v.CameraShakeState={FadingIn=0,FadingOut=1;Sustained=2,Inactive=3}function v.new(N,D,i,u)if i==nil then i=0 end if u==nil then u=0 end assert(type(N)=="\110\117\109\098\101\114","\077\097\103\110\105\116\117\100\101 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")assert(type(D)=="\110\117\109\098\101\114","\082\111\117\103\104\110\101\115\115 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")assert(type(i)=="\110\117\109\098\101\114","\070\097\100\101\073\110\084\105\109\101 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")assert(type(u)=="\110\117\109\098\101\114","\070\097\100\101\079\117\116\084\105\109\101 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")local V=setmetatable({Magnitude=N,Roughness=D,PositionInfluence=f(),RotationInfluence=f(),DeleteOnInactive=true;roughMod=1;magnMod=1,fadeOutDuration=u,fadeInDuration=i,sustain=i>0,currentFadeTime=i>0 and 0 or 1,tick=(Random.new()):NextNumber(-100,100);_camShakeInstance=true},v)return V end function v.UpdateShake(D,v)local i=D.tick local u=D.currentFadeTime local V=f(N(i,0)*.5,N(0,i)*.5,N(i,i)*.5)if D.fadeInDuration>0 and D.sustain then if u<1 then u=u+v/D.fadeInDuration elseif D.fadeOutDuration>0 then D.sustain=false end end if not D.sustain then u=u-v/D.fadeOutDuration end if D.sustain then D.tick=i+(v*D.Roughness)*D.roughMod else D.tick=i+((v*D.Roughness)*D.roughMod)*u end D.currentFadeTime=u return((V*D.Magnitude)*D.magnMod)*u end function v.StartFadeOut(f,v)if v==0 then f.currentFadeTime=0 end f.fadeOutDuration=v f.fadeInDuration=0 f.sustain=false end function v.StartFadeIn(f,v)if v==0 then f.currentFadeTime=1 end f.fadeInDuration=v or f.fadeInDuration f.fadeOutDuration=0 f.sustain=true end function v.GetScaleRoughness(v)return v.roughMod end function v.SetScaleRoughness(f,v)f.roughMod=v end function v.GetScaleMagnitude(v)return v.magnMod end function v.SetScaleMagnitude(f,v)f.magnMod=v end function v.GetNormalizedFadeTime(v)return v.currentFadeTime end function v.IsShaking(v)return v.currentFadeTime>0 or v.sustain end function v.IsFadingOut(v)return not v.sustain and v.currentFadeTime>0 end function v.IsFadingIn(v)return v.currentFadeTime<1 and(v.sustain and v.fadeInDuration>0)end function v.GetState(f)if f:IsFadingIn()then return v.CameraShakeState.FadingIn elseif f:IsFadingOut()then return v.CameraShakeState.FadingOut elseif f:IsShaking()then return v.CameraShakeState.Sustained else return v.CameraShakeState.Inactive end end return v
--[[
	
	cameraShakeInstance = CameraShakeInstance.new(magnitude, roughness, fadeInTime, fadeOutTime)
	
--]]

local CameraShakeInstance = {}
CameraShakeInstance.__index = CameraShakeInstance

local V3 = Vector3.new
local NOISE = math.noise

CameraShakeInstance.CameraShakeState = {
	FadingIn = 0,
	FadingOut = 1,
	Sustained = 2,
	Inactive = 3,
}

function CameraShakeInstance.new(magnitude, roughness, fadeInTime, fadeOutTime)
	if fadeInTime == nil then
		fadeInTime = 0
	end
	if fadeOutTime == nil then
		fadeOutTime = 0
	end

	assert(type(magnitude) == "number", "Magnitude must be a number")
	assert(type(roughness) == "number", "Roughness must be a number")
	assert(type(fadeInTime) == "number", "FadeInTime must be a number")
	assert(type(fadeOutTime) == "number", "FadeOutTime must be a number")

	local self = setmetatable({
		Magnitude = magnitude,
		Roughness = roughness,
		PositionInfluence = V3(),
		RotationInfluence = V3(),
		DeleteOnInactive = true,
		roughMod = 1,
		magnMod = 1,
		fadeOutDuration = fadeOutTime,
		fadeInDuration = fadeInTime,
		sustain = (fadeInTime > 0),
		currentFadeTime = (fadeInTime > 0 and 0 or 1),
		tick = Random.new():NextNumber(-100, 100),
		_camShakeInstance = true,
	}, CameraShakeInstance)

	return self
end

function CameraShakeInstance:UpdateShake(dt)
	local _tick = self.tick
	local currentFadeTime = self.currentFadeTime

	local offset = V3(NOISE(_tick, 0) * 0.5, NOISE(0, _tick) * 0.5, NOISE(_tick, _tick) * 0.5)

	if self.fadeInDuration > 0 and self.sustain then
		if currentFadeTime < 1 then
			currentFadeTime = currentFadeTime + (dt / self.fadeInDuration)
		elseif self.fadeOutDuration > 0 then
			self.sustain = false
		end
	end

	if not self.sustain then
		currentFadeTime = currentFadeTime - (dt / self.fadeOutDuration)
	end

	if self.sustain then
		self.tick = _tick + (dt * self.Roughness * self.roughMod)
	else
		self.tick = _tick + (dt * self.Roughness * self.roughMod * currentFadeTime)
	end

	self.currentFadeTime = currentFadeTime

	return offset * self.Magnitude * self.magnMod * currentFadeTime
end

function CameraShakeInstance:StartFadeOut(fadeOutTime)
	if fadeOutTime == 0 then
		self.currentFadeTime = 0
	end
	self.fadeOutDuration = fadeOutTime
	self.fadeInDuration = 0
	self.sustain = false
end

function CameraShakeInstance:StartFadeIn(fadeInTime)
	if fadeInTime == 0 then
		self.currentFadeTime = 1
	end
	self.fadeInDuration = fadeInTime or self.fadeInDuration
	self.fadeOutDuration = 0
	self.sustain = true
end

function CameraShakeInstance:GetScaleRoughness()
	return self.roughMod
end

function CameraShakeInstance:SetScaleRoughness(v)
	self.roughMod = v
end

function CameraShakeInstance:GetScaleMagnitude()
	return self.magnMod
end

function CameraShakeInstance:SetScaleMagnitude(v)
	self.magnMod = v
end

function CameraShakeInstance:GetNormalizedFadeTime()
	return self.currentFadeTime
end

function CameraShakeInstance:IsShaking()
	return (self.currentFadeTime > 0 or self.sustain)
end

function CameraShakeInstance:IsFadingOut()
	return ((not self.sustain) and self.currentFadeTime > 0)
end

function CameraShakeInstance:IsFadingIn()
	return (self.currentFadeTime < 1 and self.sustain and self.fadeInDuration > 0)
end

function CameraShakeInstance:GetState()
	if self:IsFadingIn() then
		return CameraShakeInstance.CameraShakeState.FadingIn
	elseif self:IsFadingOut() then
		return CameraShakeInstance.CameraShakeState.FadingOut
	elseif self:IsShaking() then
		return CameraShakeInstance.CameraShakeState.Sustained
	else
		return CameraShakeInstance.CameraShakeState.Inactive
	end
end

return CameraShakeInstance
