# Make Phantom-Forces-esqe Recoil Patterns

Ive been trying to create FPS recoil for a while now, but i cant seem to replicate the recoil of games like phantom forces or entry point

recoil from games like phantom forces or other major fps games look like this:

notice how the gun’s spread is contained in a small area?

heres my lates attempt to create recoil (i havent bothered constraining it yet because this attempt simply isnt worth the time)

the main problem here is that the gun jumps to a higher “layer”, caused by the gun firing before it has fallen back.

visual representation of what i mean

i have a simplified version my my script here:
``````local curshot = 0
local drift = Vector3.new()

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

function ShootRecoil()
curshot += 1
local RecoilStats = WeaponStats[Viewmodel.ItemName]['RecoilPattern'][1]
if curshot > RecoilStats[1] then RecoilStats = WeaponStats[Viewmodel.ItemName]['RecoilPattern'][2] end

local ticks = 0
local VertDrift = math.random(80,120)/100
local HoriDrift = (1 - math.random(0,1) * 2) * math.random(90,110)/100

local rp = RecoilStats[2] --rp stands for 'recoilpattern'
while ticks <= rp['h'] * 2 * RecoilStats[3] * VertDrift do
local dt = RunService.Heartbeat:Wait()

local lastrecoil = (rp['a'] * (ticks - rp['h'])^2 + rp['k'])/2
ticks += dt
local recoil = (rp['a'] * (math.min(ticks, rp['h'] * 2) - rp['h'])^2 + rp['k'])/2

local x,y,z = (recoil - lastrecoil), (rp['k'] * (RecoilStats[4])/2) * HoriDrift * dt * 60, 0

end
end)
end

local FireViewmodelLoop = true
FireLoop = coroutine.wrap(function()
while FireViewmodelLoop do
local dt = RunService.Heartbeat:Wait()
if MouseButton1Down then
if not automatic then
MouseButton1Down = false
end

--RECOIL--
ShootRecoil()
Viewmodel:PlayAnim('Fire')
----

else
curshot = 0
end
end
end)
FireLoop()
``````

does anybody have an idea of how to acomplish this? i havent seen a devforum post that achieves what ive been looking for.

I imagine you’re asking for wanting your spread to be concentrated in a circular area, something like this correct?

If so, here’s a good post by a user that translates the mathematical formula behind this into code;