How to calculate damage fall off for weapons!

Hello! This is my first post here, so any feedback or criticism is welcome.

I decided to share what I had discovered because there aren’t many lessons on how to perform damage fall off, which is why I’m writing this post.

So first we have to set some variables such as minimal and maximal damage and distance, it should look something like this

local MinDamage = 10
local MaxDamage = 30
local MinDistance = 20
local MaxDistance = 40

Alright, now let’s insert a function to get our damage. First, we need to get the distance between the player who shot and the player who was hit. Most guns (if not all) use raycasting for weapons, so let’s write that down.

--//Preparing raycast
local raycastParams = RaycastParams.new() 

--//we add the player who shot character into a blacklist so the raycast can ignore them
racastParams.FilterDescendantsInstances = {player.Character} 
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	
--//Getting raycastResult

--So in the first paramater we set the starting position, it can be almost anything as long as it's in the workspace. Now the second one we can get the distance  by getting the shooter's starting position and the mouse hit position. Using mouse.Hit.Position and then multiply it with a given range
local raycastResult = workspace:Raycast(player.Character.HumanoidRootPart.Position, (mousePos - player.Character.HumanoidRootPart.Position) * 500, raycastParams)

--//If the raycast hit something
if raycastResult then

	local model = hitpart:FindFirstAncestorOfClass("Model")

	if model and model:FindFirstChild("Humanoid") 
	
		--//We send the distance to the damage function
		local gottenDamage = GetDamage(raycastResult.Distance)
	end
end

Alright great! Now we just need to add 2 functions: one to calculate the damage and one to get our linear interpolation. But hold on, what is linear interpolation and why do we need it? In simple terms, it’s a way to get the in-between damage. For example, if the distance between the shooter and the target is equal to or below the minimal distance, we will apply the maximum damage; if it is equal to or higher than the maximum distance, we will apply the minimal damage. It’s the in-between we need to calculate to get the correct damage Here’s an example from the phantom forces weapon wiki, so let’s start it off by getting a normalization of the distance by using this: (Distance - Minimal distance) / (Max distance - Minimal distance). So for example, if it goes like this: (25 - 20) / (40 - 20), then it will equal 0.25, and we can use this normalized number on the “GetDamage” function. So let’s write these functions:

function GetLinearInterpolation(distance)	
		
	--//If distance is lower or equals the minimal distance
	if distance <= MinDistance then
		return 0
	end
	
	--//If distance is higher or equals the max distance
	if distance >= MaxDistance then
		return 1
	end
	
	--//If the distance is in-between
	if distance > MinDistance and distance < MaxDistance then
		return (distance - MinDistance) / (MaxDistance - MinDistance)
	end
end


function GetDamage(Distance)
	
	--//Getting the damage linear fall off
	local n = GetLinearInterpolation(Distance)
		
	return n * MinDamage + (1 - n) * MaxDamage --// N is the normalized distance that we just got.
end

Alright, so this function is made up of two sides; the left side of the function will return how much minimal damage it will deal, while the right one gets the maximum damage it will deal. Then we add them together, which will give us our final damage value. For example, if the distance between the shooter and the target is 27, it should look like this: 0.37 * 10 + (1 - 0.37 * 30) = 51.87. Another example is if the shooter is within close range: 0 * 10 + (1 - 0) * 30 = 30, the left side will be nullified while the right will have to multiply by 1 giving us our max damage. And now, the final part is just to apply the damage, which is pretty simple.

model.Humanoid.Health -= GottenDamage

I hope this helps you make damage fall off system for your gun. A huge shout out to Marblr on youtube, his video helped me on this topic tremendously Here’s the video if you want to take a look

Take care and stay safe.

26 Likes

You can use math.clamp instead of the GetLinearInterpolation function
math.clamp((Distance - MinDistance) / (MaxDistance - MinDistance),0,1)