local o={}o.__index=o o.CameraShakeState={FadingIn=0,FadingOut=1,Sustained=2,Inactive=3}function o.new(V,u,K,G)assert(type(V)=="\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(u)=="\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(K)=="\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(G)=="\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 A=setmetatable({},o)A.Magnitude=V A.Roughness=u A.PositionInfluence=Vector3.new(.15,.15,.15)A.RotationInfluence=Vector3.new(1,1,1)A.DeleteOnInactive=true A.roughMod=1 A.magnMod=1 A.fadeOutDuration=G A.fadeInDuration=K A.sustain=K>0 A.currentFadeTime=K>0 and 0 or 1 A.tick=(Random.new()):NextNumber(-100,100)A._camShakeInstance=true return A end function o.UpdateShake(V,o)local u=V.tick local K=V.currentFadeTime local G=Vector3.new(math.noise(u,0)*.5,math.noise(0,u)*.5,math.noise(u,u)*.5)if V.fadeInDuration>0 and V.sustain then if K<1 then K=K+o/V.fadeInDuration elseif V.fadeOutDuration>0 then V.sustain=false end end if not V.sustain then K=K-o/V.fadeOutDuration end if V.sustain then V.tick=u+(o*V.Roughness)*V.roughMod else V.tick=u+((o*V.Roughness)*V.roughMod)*K end V.currentFadeTime=K return((G*V.Magnitude)*V.magnMod)*K end function o.StartFadeOut(V,o)if o==0 then V.currentFadeTime=0 end V.fadeOutDuration=o V.fadeInDuration=0 V.sustain=false end function o.StartFadeIn(V,o)if o==0 then V.currentFadeTime=1 end V.fadeInDuration=o or V.fadeInDuration V.fadeOutDuration=0 V.sustain=true end function o.GetScaleRoughness(o)return o.roughMod end function o.SetScaleRoughness(V,o)V.roughMod=o end function o.GetScaleMagnitude(o)return o.magnMod end function o.SetScaleMagnitude(V,o)V.magnMod=o end function o.GetNormalizedFadeTime(o)return o.currentFadeTime end function o.IsShaking(o)return o.currentFadeTime>0 or o.sustain end function o.IsFadingOut(o)return not o.sustain and o.currentFadeTime>0 end function o.IsFadingIn(o)return o.currentFadeTime<1 and(o.sustain and o.fadeInDuration>0)end function o.GetState(V)if V:IsFadingIn()then return o.CameraShakeState.FadingIn elseif V:IsFadingOut()then return o.CameraShakeState.FadingOut elseif V:IsShaking()then return o.CameraShakeState.Sustained else return o.CameraShakeState.Inactive end end function o.destroy(o)o.Magnitude=nil o.Roughness=nil o.PositionInfluence=nil o.RotationInfluence=nil o.DeleteOnInactive=nil o.roughMod=nil o.magnMod=nil o.fadeOutDuration=nil o.fadeInDuration=nil o.sustain=nil o.currentFadeTime=nil o.tick=nil o._camShakeInstance=nil end return o
--[[
	cameraShakeInstance = CameraShakeInstance.new(magnitude, roughness, fadeInTime, fadeOutTime)
--]]

local CameraShakeInstance = {}
CameraShakeInstance.__index = CameraShakeInstance

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

function CameraShakeInstance.new(magnitude, roughness, fadeInTime, fadeOutTime)	
	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({}, CameraShakeInstance)
	
	self.Magnitude = magnitude
	self.Roughness = roughness
	self.PositionInfluence = Vector3.new(0.15, 0.15, 0.15)
	self.RotationInfluence = Vector3.new(1, 1, 1)
	self.DeleteOnInactive = true
	self.roughMod = 1
	self.magnMod = 1
	self.fadeOutDuration = fadeOutTime
	self.fadeInDuration = fadeInTime
	self.sustain = (fadeInTime > 0)
	self.currentFadeTime = (fadeInTime > 0 and 0 or 1)
	self.tick = Random.new():NextNumber(-100, 100)
	self._camShakeInstance = true
	
	return self
	
end

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

	local offset = Vector3.new(
		math.noise(_tick, 0) * 0.5,
		math.noise(0, _tick) * 0.5,
		math.noise(_tick, _tick) * 0.5
	)

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

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

	if self.sustain then
		self.tick = _tick + (deltaTime * self.Roughness * self.roughMod)
	else
		self.tick = _tick + (deltaTime * 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(scale)
	self.roughMod = scale
end

function CameraShakeInstance:GetScaleMagnitude()
	return self.magnMod
end

function CameraShakeInstance:SetScaleMagnitude(scale)
	self.magnMod = scale
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

function CameraShakeInstance:destroy()
	-- Set all properties to nil or default values
	self.Magnitude = nil
	self.Roughness = nil
	self.PositionInfluence = nil
	self.RotationInfluence = nil
	self.DeleteOnInactive = nil
	self.roughMod = nil
	self.magnMod = nil
	self.fadeOutDuration = nil
	self.fadeInDuration = nil
	self.sustain = nil
	self.currentFadeTime = nil
	self.tick = nil
	self._camShakeInstance = nil
end

return CameraShakeInstance
