Retreat/Anti Recoil Help!

So I’m trying to make a Retreat Recoil, which basically moves your camera back to where a bullet spray started after you leave your mouse button. I’ve managed to make it…

https://gyazo.com/22dbc03a528cceccba9e6f409e0b8ee7

The above is the part which I have gotten right, I move the camera back to where the spray was started. However, there is a problem I cannot wrap my head around.

“What if player moves the mouse while spraying? How do I make it go back to Origin, but respective to how much the mouse was moved?”

local mod = {}
local Run = game:GetService("RunService")

local RecoilPattern = {
    --{AmmoCount, vertRec, RetreatRec, RecoilSpeed, SideRecoil}
	{1, 1.7, -.1, .7, 0.3, 1},
	{3, 2.7, -.1, 1, 0.3, 1}
}

function lerp(a, b, t) -- Gets a number between two points using an alpha
    return a * (1 - t) + (b * t)
end

local MouseDown = false
local Ox, Oy, Oz
local mouse = game.Players.LocalPlayer:GetMouse()

mouse.Button1Down:Connect(function()
    MouseDown = true
end)
mouse.Button1Up:Connect(function()
    MouseDown = false
end)

local Camera = workspace.CurrentCamera

function mod.ShootRecoil(curshot) --called by a localscript
	local moved = false
	local prevX,prevY,prevZ = 0,0,0
	local shooting = false

	game.Players.LocalPlayer:GetMouse().Move:Connect(function()
		moved = true
		prevX,prevY,prevZ = Camera.CFrame:ToEulerAnglesXYZ() --if camera moved, get the rotation of the camera. (not made use of yet.)
	end)

	if curshot == 1 then --if at first shot, set the rotation as the Origin.
		Ox,Oy,Oz = Camera.CFrame:ToEulerAnglesXYZ()
	end	

	for i, v in pairs(RecoilPattern) do
		if curshot <= v[1] then -- Found the current recoil we're at
			spawn(function() 
				local num = 0
				while math.abs(num - v[2]) > 0.01 do --actual positive Recoil
					shooting = true
					num = lerp(num, v[2], v[4])
					local rec = num / 10

					Camera.CFrame = Camera.CFrame * CFrame.Angles(math.rad(rec*v[6]), math.rad(rec * v[5]), 0)
					Run.RenderStepped:Wait()
				end
				while math.abs(num - v[3]) > 0.01 do --retreat Recoil after each bullet for effect.
					-- shooting = true
					num = lerp(num, v[3], v[4])
					local rec = num / 10
					Camera.CFrame = Camera.CFrame * CFrame.Angles(math.rad(rec*v[6]), math.rad(rec * v[5]), 0)
					Run.RenderStepped:Wait()
				end
				shooting = false
			end)

			spawn(function()
				wait(0.8) --when player cancels burst, the camera should go back to the point it started the burst at, but this origin can change.
				print(tostring(MouseDown),tostring(moved))
				while not MouseDown and not shooting and not moved do
					--Recoil Retreat Code Here (this is where I need help.)
					Camera.CFrame = Camera.CFrame:Lerp(CFrame.Angles(Ox,Oy,Oz),0.05) 

					wait()
				end	
			end)

			break
		end
	end
end

return mod

so above is module which I modified from a DevForum post. It results in the Clip I sent. Now, at the end, there is a while loop which actually moves the camera back to the origin. I’m not sure of how to use prevX,Y and Z (The rotation values of the camera which are updated when mouse is moved.) to get the rotation with respect to how much the mouse was moved.

So for example, if I start and upward Burst and then move rightwards, it should go downwards from where it is, and not back to the Origin, which is now at the left of where your camera is looking (where you started the burst)

Anyone got solutions?

EDIT: :sadge: no replies

I think one way you could do it is using part of Roblox’s camera system to mimic its behavior and edit the original CFrame accordingly.

I tested out this code as a local script under StarterPlayerScripts and it changed the originCFrame value, but I didn’t see if it copies the original roblox camera behavior via angle comparison, setting camera.CFrame to originCFrame, etc.

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

local player = Players.LocalPlayer
local camera = Workspace.CurrentCamera

local CameraModule = player.PlayerScripts:WaitForChild("PlayerModule").CameraModule

local CameraInput = require(CameraModule.CameraInput)
local BaseCamera = require(CameraModule.BaseCamera)

local originCFrame = camera.CFrame

local function startUpdatingOriginCFrame()
	RunService:BindToRenderStep("EditRecoilOrigin", Enum.RenderPriority.Camera.Value - 1, function(dt)
		local rotateInput = CameraInput.getRotation()
		originCFrame = BaseCamera:CalculateNewLookCFrameFromArg(originCFrame.LookVector, rotateInput)
		print(originCFrame) -- for testing
	end)
end

local function stopUpdatingOriginCFrame()
	RunService:UnbindFromRenderStep("EditRecoilOrigin")
end

startUpdatingOriginCFrame()

You might want to extract the angles like you were doing before, I’m not sure. Also, maybe BaseCamera:CalculateNewLookVectorFromArg would be better.

1 Like

I’m unable to find documentation on that function (EDIT: ahh its a module function xd). What does it do, and why would it make it better?

Note that I only need a way to find the relative CFrame rotation from the point where the mouse moved to where the spray started. I don’t really need to mess with the Camera Modules :slight_smile: just need math.

I tried subtracting the current camera after moving mouse with the cframe where the spray started, which didn’t work, so I thought there was different math needed.

1 Like

bumping. Still haven’t received help on this topic :frowning: