local m={}m.__index=m local O=Vector3.new local n=math.noise m.CameraShakeState={FadingIn=0;FadingOut=1;Sustained=2,Inactive=3}function m.new(n,P,g,x)if g==nil then g=0 end if x==nil then x=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(P)=="\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(g)=="\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(x)=="\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 L=setmetatable({Magnitude=n;Roughness=P,PositionInfluence=O();RotationInfluence=O();DeleteOnInactive=true;roughMod=1,magnMod=1;fadeOutDuration=x;fadeInDuration=g;sustain=g>0;currentFadeTime=g>0 and 0 or 1,tick=(Random.new()):NextNumber(-100,100),_camShakeInstance=true},m)return L end function m.UpdateShake(P,m)local g=P.tick local x=P.currentFadeTime local L=O(n(g,0)*.5,n(0,g)*.5,n(g,g)*.5)if P.fadeInDuration>0 and P.sustain then if x<1 then x=x+m/P.fadeInDuration elseif P.fadeOutDuration>0 then P.sustain=false end end if not P.sustain then x=x-m/P.fadeOutDuration end if P.sustain then P.tick=g+(m*P.Roughness)*P.roughMod else P.tick=g+((m*P.Roughness)*P.roughMod)*x end P.currentFadeTime=x return((L*P.Magnitude)*P.magnMod)*x end function m.StartFadeOut(O,m)if m==0 then O.currentFadeTime=0 end O.fadeOutDuration=m O.fadeInDuration=0 O.sustain=false end function m.StartFadeIn(O,m)if m==0 then O.currentFadeTime=1 end O.fadeInDuration=m or O.fadeInDuration O.fadeOutDuration=0 O.sustain=true end function m.GetScaleRoughness(m)return m.roughMod end function m.SetScaleRoughness(O,m)O.roughMod=m end function m.GetScaleMagnitude(m)return m.magnMod end function m.SetScaleMagnitude(O,m)O.magnMod=m end function m.GetNormalizedFadeTime(m)return m.currentFadeTime end function m.IsShaking(m)return m.currentFadeTime>0 or m.sustain end function m.IsFadingOut(m)return not m.sustain and m.currentFadeTime>0 end function m.IsFadingIn(m)return m.currentFadeTime<1 and(m.sustain and m.fadeInDuration>0)end function m.GetState(O)if O:IsFadingIn()then return m.CameraShakeState.FadingIn elseif O:IsFadingOut()then return m.CameraShakeState.FadingOut elseif O:IsShaking()then return m.CameraShakeState.Sustained else return m.CameraShakeState.Inactive end end return m




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
