So i have a gun system that works 99% of the time. I am using quentys cframe spring module for movement and stuff. however this wierd bug happens
from the actual players camera you see it in first person but this is a good screenshot for refrence. here is the camera movement code if you wanted to see it.
camera movement below
local part = game.Workspace.M1Grand
local camera = workspace.CurrentCamera
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local CamPart = game.Workspace.M1Grand
local Spring = require(script:WaitForChild("Spring"))
local Count = 0
local ZEROVECTOR =Vector3.new()
local viewmodelSpring = Spring.new(ZEROVECTOR)
local ZoomingIn = false
local ZoomingOut = false
viewmodelSpring.Damper = 0.7 --1 is perfect dampening
local Mouse = game.Players.LocalPlayer:GetMouse()
Zoomed = false
Mouse.TargetFilter = game.Workspace.M1Grand
local function clampMagnitude(vector, maxMagnitude)
return (vector.Magnitude > maxMagnitude and (vector.Unit * maxMagnitude) or vector)
end
local deltaSensitivity = 1 -- increases force from mouse delta
--if negative force goes in opposite direction
local previousGoalCFrame = CFrame.new()
Mouse.Button2Down:Connect(function()
CanFire = true
--game.Workspace.M1Grand.CamPart2.CFrame = game.Workspace.M1Grand.CamPart3.CFrame
script.Parent.CrossHair.Top:TweenPosition(UDim2.new(.5, 0, 0.49, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.05)
script.Parent.CrossHair.Bottom:TweenPosition(UDim2.new(.5, 0, 0.51, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.05)
script.Parent.CrossHair.Left:TweenPosition(UDim2.new(.49, 0, 0.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.05)
script.Parent.CrossHair.Right:TweenPosition(UDim2.new(.51, 0, 0.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.05)
script.Parent.Zoomed.Value = 1
ZoomingIn = true
ZoomingOut = false
deltaSensitivity = 0.4
if Count > 0 then
local Count2 = Count
Count = 50 - Count2
end
end)
Mouse.Button2Up:Connect(function()
deltaSensitivity = 1
CanFire = true
script.Parent.CrossHair.Top:TweenPosition(UDim2.new(.5, 0, 0.35, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.05)
script.Parent.CrossHair.Bottom:TweenPosition(UDim2.new(.5, 0, 0.65, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.05)
script.Parent.CrossHair.Left:TweenPosition(UDim2.new(.425, 0, 0.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.05)
script.Parent.CrossHair.Right:TweenPosition(UDim2.new(.575, 0, 0.5, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.05)
--game.Workspace.M1Grand.CamPart2.CFrame = game.Workspace.M1Grand.CamPart.CFrame
script.Parent.Zoomed.Value = 0
ZoomingIn = false
ZoomingOut = true
if Count > 0 then
local Count2 = Count
Count = 50 - Count2
end
end)
RunService.RenderStepped:Connect(function(step)
if script.Parent.Zoomed.Value == 1 then
Zoomed = true
else
Zoomed = false
end
if ZoomingIn == true then
if ZoomingOut == false then
if Count < 20 then
--game.Workspace.CurrentCamera.FieldOfView = game.Workspace.CurrentCamera.FieldOfView - 0.7
CamPart.CamPart2.CFrame = CamPart.CamPart2.CFrame:Lerp(CamPart.CamPart.CFrame, Count / 20)
--wait()
--CamPart.CamPart2.CFrame = CamPart.CamPart2.CFrame:Lerp(CamPart.CamPart.CFrame, 1)
--script.Parent.Offset.Value = 1.5
Count = Count + 1
else
script.Parent.Offset.Value = 1
CamPart.CamPart2.CFrame = CamPart.CamPart2.CFrame:Lerp(CamPart.CamPart.CFrame, 1)
ZoomingIn = false
ZoomingOut = false
Count = 0
end
end
end
if ZoomingIn == false then
if ZoomingOut == true then
if Count < 20 then
--game.Workspace.CurrentCamera.FieldOfView = game.Workspace.CurrentCamera.FieldOfView - 0.7
CamPart.CamPart2.CFrame = CamPart.CamPart2.CFrame:Lerp(CamPart.CamPart3.CFrame, Count / 20)
--wait()
--CamPart.CamPart2.CFrame = CamPart.CamPart2.CFrame:Lerp(CamPart.CamPart.CFrame, 1)
--script.Parent.Offset.Value = 1.5
Count = Count + 1
else
script.Parent.Offset.Value = 1
CamPart.CamPart2.CFrame = CamPart.CamPart2.CFrame:Lerp(CamPart.CamPart3.CFrame, 1)
ZoomingIn = false
ZoomingOut = false
Count = 0
end
end
end
if Zoomed then
if ZoomingIn == false then
if ZoomingOut == false then
--game.Workspace.M1Grand.ProjectorSight2.BillboardGui.ClippingFrame.Reticle.ImageTransparency = 1
--game.Workspace.ProjectorSight.CFrame = game.Workspace.CurrentCamera.CFrame * CFrame.new(0, 0, -1)
--game.Workspace.ProjectorSight.BillboardGui.ClippingFrame.Reticle.ImageTransparency = 0
end
end
UserInputService.MouseDeltaSensitivity = 0.2
viewmodelSpring.Speed = 20
local cameraOffset = CFrame.new(0, 0, -script.Parent.Offset.Value)
local goalCFrame = camera.CFrame*cameraOffset
part:SetPrimaryPartCFrame(goalCFrame)
--Spring stuff
local differenceCF = previousGoalCFrame:ToObjectSpace(goalCFrame)
local axis, angle = differenceCF:ToAxisAngle()
local angularDisplacement = axis*angle
previousGoalCFrame = goalCFrame
local springForce = angularDisplacement*deltaSensitivity
viewmodelSpring:Impulse(springForce)
local partSpringOffset = viewmodelSpring.Position
local axis = partSpringOffset.Unit
local angle = partSpringOffset.Magnitude
--clamp the angle don't want it to speen 360 degrees unless you want it to
--velocity goes wild though
--angle = math.deg(angle)
--local maxAngle = 45 --degrees
--angle = math.clamp(angle,0,45)
-- angle = math.rad(angle)
part:SetPrimaryPartCFrame(part.CamPart2.CFrame * CFrame.fromAxisAngle(axis,angle))
--part.CFrame *= CFrame.fromAxisAngle(axis,angle)
else
--game.Workspace.M1Grand.ProjectorSight2.BillboardGui.ClippingFrame.Reticle.ImageTransparency = 0
--game.Workspace.ProjectorSight.BillboardGui.ClippingFrame.Reticle.ImageTransparency = 1
UserInputService.MouseDeltaSensitivity = 1
viewmodelSpring.Speed = 16
local cameraOffset = CFrame.new(0, 0, -script.Parent.Offset.Value)
local goalCFrame = camera.CFrame*cameraOffset
part:SetPrimaryPartCFrame(goalCFrame)
--Spring stuff
local differenceCF = previousGoalCFrame:ToObjectSpace(goalCFrame)
local axis, angle = differenceCF:ToAxisAngle()
local angularDisplacement = axis*angle
previousGoalCFrame = goalCFrame
local springForce = angularDisplacement*deltaSensitivity
viewmodelSpring:Impulse(springForce)
local partSpringOffset = viewmodelSpring.Position
local axis = partSpringOffset.Unit
local angle = partSpringOffset.Magnitude
--clamp the angle don't want it to speen 360 degrees unless you want it to
--velocity goes wild though
--angle = math.deg(angle)
--local maxAngle = 45 --degrees
--angle = math.clamp(angle,0,45)
-- angle = math.rad(angle)
part:SetPrimaryPartCFrame(part.CamPart2.CFrame * CFrame.fromAxisAngle(axis,angle))
--part.CFrame *= CFrame.fromAxisAngle(axis,angle)
end
end)
spring module below
--[[
class Spring
Description:
A physical model of a spring, useful in many applications. Properties only evaluate
upon index making this model good for lazy applications
API:
Spring = Spring.new(number position)
Creates a new spring in 1D
Spring = Spring.new(Vector3 position)
Creates a new spring in 3D
Spring.Position
Returns the current position
Spring.Velocity
Returns the current velocity
Spring.Target
Returns the target
Spring.Damper
Returns the damper
Spring.Speed
Returns the speed
Spring.Target = number/Vector3
Sets the target
Spring.Position = number/Vector3
Sets the position
Spring.Velocity = number/Vector3
Sets the velocity
Spring.Damper = number [0, 1]
Sets the spring damper, defaults to 1
Spring.Speed = number [0, infinity)
Sets the spring speed, defaults to 1
Spring:TimeSkip(number DeltaTime)
Instantly skips the spring forwards by that amount of now
Spring:Impulse(number/Vector3 velocity)
Impulses the spring, increasing velocity by the amount given
]]
local Spring = {}
--- Creates a new spring
-- @param initial A number or Vector3 (anything with * number and addition/subtraction defined)
function Spring.new(initial)
local target = initial or 0
return setmetatable({
_time0 = tick();
_position0 = target;
_velocity0 = 0*target;
_target = target;
_damper = 1;
_speed = 1;
}, Spring)
end
--- Impulse the spring with a change in velocity
-- @param velocity The velocity to impulse with
function Spring:Impulse(velocity)
self.Velocity = self.Velocity + velocity
end
--- Skip forwards in now
-- @param delta now to skip forwards
function Spring:TimeSkip(delta)
local now = tick()
local position, velocity = self:_positionVelocity(now+delta)
self._position0 = position
self._velocity0 = velocity
self._time0 = now
end
function Spring:__index(index)
if Spring[index] then
return Spring[index]
elseif index == "Value" or index == "Position" or index == "p" then
local position, _ = self:_positionVelocity(tick())
return position
elseif index == "Velocity" or index == "v" then
local _, velocity = self:_positionVelocity(tick())
return velocity
elseif index == "Target" or index == "t" then
return self._target
elseif index == "Damper" or index == "d" then
return self._damper
elseif index == "Speed" or index == "s" then
return self._speed
else
error(("%q is not a valid member of Spring"):format(tostring(index)), 2)
end
end
function Spring:__newindex(index, value)
local now = tick()
if index == "Value" or index == "Position" or index == "p" then
local _, velocity = self:_positionVelocity(now)
self._position0 = value
self._velocity0 = velocity
elseif index == "Velocity" or index == "v" then
local position, _ = self:_positionVelocity(now)
self._position0 = position
self._velocity0 = value
elseif index == "Target" or index == "t" then
local position, velocity = self:_positionVelocity(now)
self._position0 = position
self._velocity0 = velocity
self._target = value
elseif index == "Damper" or index == "d" then
local position, velocity = self:_positionVelocity(now)
self._position0 = position
self._velocity0 = velocity
self._damper = math.clamp(value, 0, 1)
elseif index == "Speed" or index == "s" then
local position, velocity = self:_positionVelocity(now)
self._position0 = position
self._velocity0 = velocity
self._speed = value < 0 and 0 or value
else
error(("%q is not a valid member of Spring"):format(tostring(index)), 2)
end
self._time0 = now
end
function Spring:_positionVelocity(now)
local p0 = self._position0
local v0 = self._velocity0
local p1 = self._target
local d = self._damper
local s = self._speed
local t = s*(now - self._time0)
local d2 = d*d
local h, si, co
if d2 < 1 then
h = math.sqrt(1 - d2)
local ep = math.exp(-d*t)/h
co, si = ep*math.cos(h*t), ep*math.sin(h*t)
elseif d2 == 1 then
h = 1
local ep = math.exp(-d*t)/h
co, si = ep, ep*t
else
h = math.sqrt(d2 - 1)
local u = math.exp((-d + h)*t)/(2*h)
local v = math.exp((-d - h)*t)/(2*h)
co, si = u + v, u - v
end
local a0 = h*co + d*si
local a1 = 1 - (h*co + d*si)
local a2 = si/s
local b0 = -s*si
local b1 = s*si
local b2 = h*co - d*si
return
a0*p0 + a1*p1 + a2*v0,
b0*p0 + b1*p1 + b2*v0
end
return Spring
heres the layout of the scripts