--[=[
	Calculates the current shake vector. This should be continuously
	called inside a loop, such as `RunService.Heartbeat`. Alternatively,
	`OnSignal` or `BindToRenderStep` can be used to automatically call
	this function.

	Returns a tuple of three values:
	1. `position: Vector3` - Position shake offset
	2. `rotation: Vector3` - Rotation shake offset
	3. `completed: boolean` - Flag indicating if the shake is finished

	```lua
	local hb
	hb = RunService.Heartbeat:Connect(function()
		local offsetPosition, offsetRotation, isDone = shake:Update()
		if isDone then
			hb:Disconnect()
		end
		-- Use `offsetPosition` and `offsetRotation` here
	end)
	```
]=]

function Shake:Update(): (Vector3, Vector3, boolean)

	local done = false

	local now = self.TimeFunction()
	local dur = now - self._startTime

	local noiseInput = ((now + self._timeOffset) / self.Frequency) % 1000000

	local multiplierFadeIn = 1
	local multiplierFadeOut = 1
	if dur < self.FadeInTime then
		multiplierFadeIn = dur / self.FadeInTime
	end
	if not self.Sustain and dur > self.FadeInTime + self.SustainTime then
		multiplierFadeOut = 1 - (dur - self.FadeInTime - self.SustainTime) / self.FadeOutTime
		if (not self.Sustain) and dur >= self.FadeInTime + self.SustainTime + self.FadeOutTime then
			done = true
		end
	end

	local offset = Vector3.new(
		math.noise(noiseInput, 0) / 2,
		math.noise(0, noiseInput) / 2,
		math.noise(noiseInput, noiseInput) / 2
	) * self.Amplitude * math.min(multiplierFadeIn, multiplierFadeOut)

	if done then
		self:Stop()
	end

	return self.PositionInfluence * offset, self.RotationInfluence * offset, done

end

