FE Gun Kit Camera Sway

I want to change FE Gun Kit camera sway settings similliar to “Games Unite Testing Place”
robloxapp-20240323-2105479.wmv (1.0 MB)


local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid", 1)
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart", 1)
local LeftArm = Character:FindFirstChild("Left Arm") or Character:FindFirstChild("LeftHand")
local RightArm = Character:FindFirstChild("Right Arm") or Character:FindFirstChild("RightHand")
local Camera = Workspace.CurrentCamera

local Miscs = ReplicatedStorage:WaitForChild("Miscs")
local Modules = ReplicatedStorage:WaitForChild("Modules")

local Viewmodels = Miscs.Viewmodels

local Utilities = require(Modules.Utilities)
local Spring = Utilities.Spring
local Thread = Utilities.Thread
local Math = Utilities.Math

local ViewmodelStorage = Camera:FindFirstChild("ViewmodelStorage")
if not ViewmodelStorage then
	ViewmodelStorage = Instance.new("Folder")
	ViewmodelStorage.Name = "ViewmodelStorage"
	ViewmodelStorage.Parent = Camera
end

local GeneralSettings = {
	CanSway = true;
	CanBobble = true;
	CanBreathe = true;
	CanAim = true;
	CanRecoil = true;

	RecoilYRotMax = 16;
	RecoilZPosMax = 1;
	RecoilYPosMax = 0.5;
}

local OriginalAimSpeed = 15

--legends:
--[s]: speed
--[d]: damper
--[t]: target
--[p]: position
--[v]: velocity
local SpeedSpring = Spring.spring.new()
SpeedSpring.s = 16
local VelocitySpring = Spring.spring.new(Vector3.new())
VelocitySpring.s = 16
VelocitySpring.t = Vector3.new()
VelocitySpring.p = Vector3.new()
local AimSpring = Spring.spring.new()
AimSpring.s = OriginalAimSpeed
AimSpring.d = 0.9
AimSpring.t = 1
local SwaySpring = Spring.spring.new(Vector3.new())
SwaySpring.s = 10
SwaySpring.d = 0.55

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

local CurrentViewmodel
local CurrentIsAiming
local CurrentAimSteady
local CurrentViewmodelOffset
local CurrentFakeCamera
local OldCamCF
local Velocity = Vector3.new()
local Speed = 0
local Distance = 0
local RecoilPower = 0
local XAngle = 0
local YAngle = 0
local ZAngle = 0
local YPos = 0
local ZPos = 0
local RecoilCFrame = CFrame.new()
local CurrentAimCFrame = CFrame.new()
local RealAimCFrameTable
local AimCFrameStorage = {}
local OffStateConnections = {}
local OnStateConnections = {}

local HasAimPoints = false

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

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

local function ViewmodelBob(a, r, baseWalkSpeed)
	local a, r = a or 1, r or 1
	local d, s, v = Distance * 6.28318 * 1 / 2, Speed, -Velocity
	--if s < baseWalkSpeed then
	local w = Vector3.new(r * math.sin(d / 4 - 1) / 256 + r * (math.sin(d / 64) - r * v.Z / 4) / 512, r * math.cos(d / 128) / 128 - r * math.cos(d / 8) / 256, r * math.sin(d / 8) / 128 + r * v.X / 1024) * s / 20 * 6.28318
	return CFrame.new(r * math.cos(d / 8 - 1) * s / 196, 1.25 * a * math.sin(d / 4) * s / 512, 0) * Math.FromAxisAngle(w)
	--else
	--local w = Vector3.new((r * math.sin(d / 4 - 1) / 256 + r * (math.sin(d / 64) - r * v.Z / 4) / 512) * s / 20 * 6.28318, (r * math.cos(d / 128) / 128 - r * math.cos(d / 8) / 256) * s / 20 * 6.28318, r * math.sin(d / 8) / 128 * (5 * s - 56) / 20 * 6.28318 + r * v.X / 1024)
	--return CFrame.new(r * math.cos(d / 8 - 1) * (5 * s - 56) / 196, 1.25 * a * math.sin(d / 4) * s / 512, 0) * Math.FromAxisAngle(w)
	--end
end

local function ViewmodelBreath(a)
	local d, s = os.clock() * 2, 2 * (1.2 - a)
	return CFrame.new(math.cos(d / 8) * s / 128, -math.sin(d / 4) * s / 128, math.sin(d / 16) * s / 64)
end

local function SetTextureTransparency(part, transparency)
	local p = part:GetChildren()
	for i = 1, #p do
		local v = p[i]
		if v:IsA("Texture") or v:IsA("Decal") then
			v.LocalTransparencyModifier = transparency
		end
	end
end

local function IsFirstPerson()
	return (Camera.Focus.p - Camera.CoordinateFrame.p).Magnitude <= 1
end

local function GetTool()
	return Character:FindFirstChildOfClass("Tool")	
end

function ViewmodelHandler:RecoilViewmodel(value)
	RecoilPower = value
end

function ViewmodelHandler:SetAimEnabled(value, id, alignToAimPoint)
	if CurrentIsAiming then
		CurrentIsAiming.Value = alignToAimPoint and value or false
		if RealAimCFrameTable then
			CurrentAimCFrame = RealAimCFrameTable[id].AimCFrame
		end
	end
end

function ViewmodelHandler.SetUpViewmodel(viewmodelName)
	local Viewmodel
	if ViewmodelStorage:FindFirstChild("v_"..viewmodelName) then
		Viewmodel = ViewmodelStorage:FindFirstChild("v_"..viewmodelName)
	else
		Viewmodel = Viewmodels["v_"..viewmodelName]:Clone()
		local ArmSample = Viewmodels.VMArms:Clone()
		local RWeld = Instance.new("Motor6D")
		local LWeld = Instance.new("Motor6D")
		RWeld.Parent = ArmSample["Right Arm"]
		LWeld.Parent = ArmSample["Left Arm"]
		ArmSample.Parent = Viewmodel
		RWeld.Part0 = Viewmodel["Right Arm"]
		RWeld.Part1 = ArmSample["Right Arm"]
		LWeld.Part0 = Viewmodel["Left Arm"]
		LWeld.Part1 = ArmSample["Left Arm"]
		Viewmodel["Left Arm"].Transparency = 1
		Viewmodel["Right Arm"].Transparency = 1
	end
	if Viewmodel and Viewmodel.PrimaryPart then
		if Viewmodel:FindFirstChild("aimSpeed") then
			AimSpring.s = Viewmodel.aimSpeed.Value
		end
		if Viewmodel:FindFirstChild("AimPoints") then
			if #Viewmodel.AimPoints:GetChildren() > 0 then
				HasAimPoints = true
				local HasExistingTable = false
				local AimCFrameTable = {}
				for _, v in pairs(AimCFrameStorage) do
					if v.ViewmodelName == Viewmodel.Name then
						HasExistingTable = true
						AimCFrameTable = v.AimCFrameTable
						break
					end
				end
				if not HasExistingTable then
					for i, v in ipairs(Viewmodel.AimPoints:GetChildren()) do
						table.insert(AimCFrameTable, {
							Id = i,
							AimCFrame = Viewmodel.PrimaryPart.CFrame:ToObjectSpace(v.CFrame):Inverse()
						}) 
					end
					table.insert(AimCFrameStorage, {
						ViewmodelName = Viewmodel.Name,
						AimCFrameTable = AimCFrameTable
					}) 
				end
				RealAimCFrameTable = AimCFrameTable
				CurrentAimCFrame = RealAimCFrameTable[1].AimCFrame
			end		
		end
		CurrentIsAiming = Viewmodel:FindFirstChild("isAiming")
		CurrentAimSteady = Viewmodel:FindFirstChild("aimSteady")
		if Viewmodel:FindFirstChild("offset") then
			CurrentViewmodelOffset = require(Viewmodel.offset)
		end
		CurrentFakeCamera = Viewmodel:FindFirstChild("FakeCamera")
		for _, child in pairs(Viewmodel:GetDescendants()) do
			if child:IsA("Shirt") then
				child:Destroy()
			end
			if not IsFirstPerson() then
				if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
					if string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
						child.Enabled = false
					end
				end
				if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
					child.Visible = false
				end
				if child:IsA("BasePart") then
					child.LocalTransparencyModifier = 1
					SetTextureTransparency(child, 1)
				end
			else
				if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
					if string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
						child.Enabled = true
					end
				end
				if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
					child.Visible = true
				end
				if child:IsA("BasePart") then
					child.LocalTransparencyModifier = 0
					SetTextureTransparency(child, 0)
				end
			end
		end
		Thread:Spawn(function()
			local Loaded = Player:HasAppearanceLoaded()
			while not Loaded do
				Loaded = Player:HasAppearanceLoaded()
				RunService.RenderStepped:Wait()
			end
			local Shirt = Character:FindFirstChild("Shirt")
			local VMLeftArm = Viewmodel.VMArms:FindFirstChild("Left Arm")
			local VMRightArm = Viewmodel.VMArms:FindFirstChild("Right Arm")
			if Shirt then
				Shirt:Clone().Parent = Viewmodel
			end
			if VMLeftArm then
				VMLeftArm.Transparency = 0
				VMLeftArm.Color = LeftArm.Color
				VMLeftArm.Shirt.Texture = Shirt and Shirt.ShirtTemplate or ""
			end
			if VMRightArm then
				VMRightArm.Transparency = 0
				VMRightArm.Color = RightArm.Color
				VMRightArm.Shirt.Texture = Shirt and Shirt.ShirtTemplate or ""
			end
		end)
		Viewmodel.PrimaryPart.Anchored = true
		if Camera.CameraType == Enum.CameraType.Custom then
			Viewmodel.PrimaryPart.CFrame = (Camera.CoordinateFrame * CFrame.new(0, 0, (Camera.FieldOfView / 90 - 1) * 0.3)) * CurrentViewmodelOffset
		end
		Viewmodel.Parent = ViewmodelStorage
		CurrentViewmodel = Viewmodel
		return Viewmodel
	end
	return nil
end

local function RenderViewmodel()
	if CurrentViewmodel and CurrentViewmodel.PrimaryPart then
		if CurrentFakeCamera then
			if IsFirstPerson() then
				local NewCamCF = CurrentFakeCamera.CFrame:ToObjectSpace(CurrentViewmodel.PrimaryPart.CFrame)
				if OldCamCF then
					--Camera.CFrame = Camera.CFrame * NewCamCF:ToObjectSpace(NewCamCF)
					local _, _, Z = NewCamCF:ToOrientation()
					local X, Y, _ = NewCamCF:ToObjectSpace(OldCamCF):ToEulerAnglesXYZ()
					Camera.CFrame = Camera.CFrame * CFrame.Angles(X, Y, -Z)
				end
				OldCamCF = NewCamCF
				--else
				--Camera.CFrame = Camera.CFrame
			end		
		end	
		for _, child in pairs(CurrentViewmodel:GetDescendants()) do
			if not IsFirstPerson() then
				if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
					if string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
						child.Enabled = false
					end
				end
				if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
					child.Visible = false
				end
				if child:IsA("BasePart") then
					child.LocalTransparencyModifier = 1
					SetTextureTransparency(child, 1)
				end
			else				
				if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
					if string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
						if CurrentIsAiming and CurrentIsAiming.Value and CurrentViewmodel.hideWhenAim.Value then
							child.Enabled = false
						else
							child.Enabled = true
						end
					end
				end
				if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
					if CurrentIsAiming and CurrentIsAiming.Value and CurrentViewmodel.hideWhenAim.Value then
						child.Visible = false
					else
						child.Visible = true
					end
				end
				if child:IsA("UnionOperation") or child:IsA("MeshPart") or child:IsA("BasePart") then
					if CurrentIsAiming and CurrentIsAiming.Value and CurrentViewmodel.hideWhenAim.Value then
						child.LocalTransparencyModifier = 1
						SetTextureTransparency(child, 1)
					else
						child.LocalTransparencyModifier = 0
						SetTextureTransparency(child, 0)
					end
				end
			end
		end
		local Tool = GetTool()
		if Tool then
			for _, child in pairs(Tool:GetDescendants()) do
				if not IsFirstPerson() then
					if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
						if string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
							child.Enabled = true
						end
					end
					if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
						child.Visible = true
					end
					if child:IsA("BasePart") then
						child.LocalTransparencyModifier = 0
					end
					SetTextureTransparency(child, 0)
				else
					if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
						if string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
							child.Enabled = false
						end
					end
					if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
						child.Visible = false
					end
					if child:IsA("BasePart") then
						child.LocalTransparencyModifier = 1
					end
					SetTextureTransparency(child, 1)
				end
			end			
		end	
	end
end

function ViewmodelHandler:CullViewmodel(viewmodel)
	if viewmodel and viewmodel.PrimaryPart then
		if CurrentViewmodel == viewmodel then
			AimSpring.s = OriginalAimSpeed
			CurrentViewmodel = nil
			CurrentIsAiming = nil
			CurrentAimSteady = nil
			CurrentViewmodelOffset = nil
			CurrentFakeCamera = nil
			OldCamCF = nil
			RealAimCFrameTable = nil
			CurrentAimCFrame = CFrame.new()
			HasAimPoints = false
		end
		viewmodel.PrimaryPart.CFrame = CFrame.new(10e8, 10e8, 10e8) * CFrame.Angles(0, 0, 0)
	end
end

function ViewmodelHandler:DestroyViewmodel(viewmodel)
	if viewmodel then
		if CurrentViewmodel == viewmodel then
			AimSpring.s = OriginalAimSpeed
			CurrentViewmodel = nil
			CurrentIsAiming = nil
			CurrentAimSteady = nil
			CurrentViewmodelOffset = nil
			CurrentFakeCamera = nil
			OldCamCF = nil
			RealAimCFrameTable = nil
			CurrentAimCFrame = CFrame.new()
			HasAimPoints = false
		end
		viewmodel:Destroy()		
	end
end

Player.CharacterAdded:Connect(function(character)
	Character = character
	Humanoid = Character:WaitForChild("Humanoid", 1)
	HumanoidRootPart = Character:WaitForChild("HumanoidRootPart", 1)
	LeftArm = Character:FindFirstChild("Left Arm") or Character:FindFirstChild("LeftHand")
	RightArm = Character:FindFirstChild("Right Arm") or Character:FindFirstChild("RightHand")
	for i, v in pairs(OffStateConnections) do
		if v then
			v:Disconnect()
		end
		table.remove(OffStateConnections, i)
	end
	for i, v in pairs(OnStateConnections) do
		if v then
			v:Disconnect()
		end
		table.remove(OnStateConnections, i)
	end
	for _, state in pairs(OffStates) do
		table.insert(OffStateConnections, Humanoid[state]:Connect(function()
			active = false
		end))
	end
	for _, state in pairs(OnStates) do
		table.insert(OnStateConnections, Humanoid[state]:Connect(function(speed)
			active = (speed > 1)
		end))
	end
end)

RunService.RenderStepped:Connect(function(dt)
	if CurrentViewmodel and CurrentViewmodel.PrimaryPart and Character and Humanoid and HumanoidRootPart then		
		local MouseDelta = UserInputService:GetMouseDelta()
		RecoilPower = RecoilPower > 0.1 and Math.Lerp(RecoilPower, 0, dt * 11) or 0
		SwaySpring.t = Vector3.new(VelocitySpring.v.Z / 1024 / 32 + VelocitySpring.v.Y / 1024 / 16 + (MouseDelta.Y / 10) / 1024 * 3 / 2, VelocitySpring.v.X / 1024 / 32 + (MouseDelta.X / 10) / 1024 * 3 / 2, -(MouseDelta.X / 10) / 1024 * 3 / 2)
		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
		VelocitySpring.t = RelativeVelocity
		Speed = SpeedSpring.p
		Distance = Distance + dt * SpeedSpring.p
		Velocity = VelocitySpring.p
		YAngle = Math.Lerp(YAngle, GeneralSettings.RecoilYRotMax * RecoilPower, RecoilPower == 0 and dt * 7 or dt * 6) + Math.Lerp(XAngle, Math.Randomize(2) * RecoilPower, RecoilPower == 0 and dt * 7 or dt / 2)
		XAngle = Math.Lerp(XAngle, Math.Randomize(1.3) * RecoilPower, RecoilPower == 0 and dt * 7 or dt * 3)
		ZAngle = Math.Lerp(ZAngle, Math.Randomize(5) * RecoilPower, RecoilPower == 0 and dt * 7 or dt / 3)
		YPos = Math.Lerp(YPos, GeneralSettings.RecoilYPosMax * RecoilPower, RecoilPower == 0 and dt * 7 or dt * 0.4)
		ZPos = Math.Lerp(ZPos, GeneralSettings.RecoilZPosMax * RecoilPower, RecoilPower == 0 and dt * 7 or dt * 0.9)
		RecoilCFrame = CFrame.new(0, YPos, ZPos) * CFrame.Angles(math.rad(YAngle), XAngle, ZAngle)
		local CF = CFrame.new()
		CF = Camera.CoordinateFrame * CFrame.new(0, 0, (Camera.FieldOfView / 90 - 1) * 0.3)
		if CurrentIsAiming and CurrentAimSteady then
			if CurrentIsAiming.Value then
				MouseDelta = MouseDelta * 0.75
				AimSpring.t = CurrentAimSteady.aim.Value
			else
				AimSpring.t = CurrentAimSteady.noAim.Value
			end
		else
			AimSpring.t = 0
		end
		if GeneralSettings.CanSway then
			CF = CF * Math.FromAxisAngle(SwaySpring.v)
		end
		if GeneralSettings.CanBobble then
			CF = CF * ViewmodelBob(0.4 - 0.3 * AimSpring.p, 0.5 - 0.8 * AimSpring.p, Humanoid.WalkSpeed)
		end
		if GeneralSettings.CanBreathe then
			CF = CF * ViewmodelBreath(AimSpring.p)
		end
		if GeneralSettings.CanAim then
			if HasAimPoints then
				local AimCF = Math.Interpolator(CurrentAimCFrame)
				CF = CF * AimCF(AimSpring.p)
			end
		end
		if GeneralSettings.CanRecoil then
			CF = CF * RecoilCFrame
		end
		local Offset = CurrentViewmodelOffset or CFrame.new(0, 0, 0)
		local Offst = Math.Interpolator(Offset)
		CF = CF * Offst(1 - AimSpring.p)
		if Camera.CameraType == Enum.CameraType.Custom then
			local CamOffset = -Humanoid.CameraOffset
			CurrentViewmodel.PrimaryPart.CFrame = CF * CFrame.new(CamOffset.X * 0.5, CamOffset.Y * 0.5, CamOffset.Z * 0.5)
		end
		RenderViewmodel()
	end
end)

return ViewmodelHandler```
3 Likes