FastCast Module - Projectile ricochet not colliding with player's character

What do you want to achieve?
I want the projectile to hit the player’s character if the projectile ricochets

What is the issue? / What solutions have you tried so far?
The projectile is not colliding the the player after it ricochets. I attempted updating the raycast parameter’s FilterDescendantsInstances table without the player’s character while the filter type is set to “Exclude” but it still does not collide.

When I switch the raycast filtertype to “Include” and set its FilterDescendantsInstances table with workspace children excluding the player’s character as an element, it collides with the player’s character.

Is there a way I can do this where I just use the “Exclude” raycast filter type?

Bullet Pierced Function:

	conTable.BulletPierced = caster.RayPierced:Connect(function (xActiveCast, result, velocity, bulletInstance)
		if (xActiveCast ~= activeCast) then return end
		if (result.Instance:GetAttribute("Reflect")) then
			-- Updating ray params
			local activeRayParams = activeCast.RayInfo.Parameters
			local rigIndex = table.find(activeRayParams.FilterDescendantsInstances, shooterRig)
			if (rigIndex) then
				local newTable = activeRayParams.FilterDescendantsInstances
				table.remove(newTable, rigIndex)
				activeCast.RayInfo.Parameters.FilterDescendantsInstances = newTable
			end
			
			-- Updating the velocity shoot towards the opposite direction (ricochet)
			activeCast:SetVelocity(velocity * -1)
		end
	end)

Entire Server script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")

local RE = ReplicatedStorage.RE

local FastCastLib = require(ServerScriptService.FastCastRedux)

local Casters = {}

local bulletTemplate = ServerScriptService.Bullet

local function getCaster (shooterRig)
	--[[
		* Gets the caster object with the given rig
		
		>shooterRig: Character of player who shot the projectile
	]]
	local ourCaster = nil
	-- Creaing a new caster if needed
	if (Casters[shooterRig] == nil) then
		Casters[shooterRig] = FastCastLib.new()
		local rigRemoveConsTable = {Disconnecting = false}
		function rigRemoveConsTable:Disconnect ()
			if (self.Disconnecting) then return end
			self.Disconnecting = true
			for _,x in pairs (self) do
				if (typeof(x) ~= "RBXScriptConnection") then continue end
				x:Disconnect()
			end
			Casters[shooterRig] = nil
			table.clear(self)
		end
		rigRemoveConsTable.AncestryChanged = shooterRig.AncestryChanged:Connect(function()
			if (shooterRig:IsDescendantOf(workspace)) then return end
			rigRemoveConsTable:Disconnect()
		end)
		rigRemoveConsTable.Destroying = shooterRig.Destroying:Connect(function ()
			rigRemoveConsTable:Disconnect()
		end) 
	end
	-- Getting & returning our caster
	ourCaster = Casters[shooterRig] 
	return ourCaster
end

local function getEverythingExceptRig (rig)
	--[[
		* Gets all workspace children except given 
			rig model
	]]
	local everything = workspace:GetChildren()
	local rigIndex = table.find(everything, rig)
	if (rigIndex) then
		table.remove(everything, rigIndex)
	end
	
	return everything
end

local function getRigFromCaster (casterObject)
	--[[
		**NOT USED**
	]]
	local rig = nil
	for xRig, rigCaster in pairs (Casters) do
		if (rigCaster == casterObject) then
			rig = xRig
			break
		end
	end
	return rig
end

local function createCasterBehavior (rig)
	--[[
		* Creates and returns the caster behavior for projectile
			with initial raycast params
		> rig: Character of player who shot the projectile 
	]]
	-- Creating the raycast parameters
	local rayParams = RaycastParams.new()
	rayParams.FilterType = Enum.RaycastFilterType.Exclude
	rayParams.FilterDescendantsInstances = {rig, workspace.Bullets}
	-- Creaing the caster behavior
	local castBehavior = FastCastLib.newBehavior()
	castBehavior.RaycastParams = rayParams
	castBehavior.CosmeticBulletTemplate = bulletTemplate
	castBehavior.CosmeticBulletContainer = workspace.Bullets
	castBehavior.AutoIgnoreContainer = false
	castBehavior.MaxDistance = 1000
	castBehavior.CanPierceFunction = function (cast, result, velocity)
		if (result.Instance:GetAttribute("Reflect")) then
			return true
		else
			return false
		end
	end
	
	return castBehavior
end

local function fireShot (shooterRig, originPoint, endPoint, castBehavior)
	--
	local ourBullet = nil
	
	-- Getting the caster
	local caster = getCaster(shooterRig)
	
	-- Getting direction & fire details
	local VELOCITY = 120
	local directionVector = (endPoint - originPoint).Unit 
	local currentBullet = nil
	local hit = false
	
	-- Firing & getting active cast
	local activeCast = caster:Fire(
		originPoint, 
		directionVector,
		VELOCITY,
		castBehavior
	)
	
	-- Events connection table
	local conTable = {}
	function conTable:Disconnect() 
		for _, x in pairs (conTable) do
			if (typeof(x) == "RBXScriptConnection") then x:Disconnect() end
		end
	end
	--_Bullet hit something event handling
	conTable.BulletHit = caster.RayHit:Connect(function (xActiveCast, result, velocity, bulletInstance)
		if (xActiveCast ~= activeCast) then return end
		if (currentBullet == nil) then currentBullet = bulletInstance end
		print(result.Instance)
		bulletInstance.CanCollide = true
		bulletInstance.Anchored = false
		conTable:Disconnect()
		hit = true
	end)
	--_Bullet pierced something event handling
	conTable.BulletPierced = caster.RayPierced:Connect(function (xActiveCast, result, velocity, bulletInstance)
		if (xActiveCast ~= activeCast) then return end
		if (result.Instance:GetAttribute("Reflect")) then
			-- Updating ray params
			local activeRayParams = activeCast.RayInfo.Parameters
			local rigIndex = table.find(activeRayParams.FilterDescendantsInstances, shooterRig)
			if (rigIndex) then
				local newTable = activeRayParams.FilterDescendantsInstances
				table.remove(newTable, rigIndex)
				activeCast.RayInfo.Parameters.FilterDescendantsInstances = newTable
			end
			
			-- Updating the velocity shoot towards the opposite direction (ricochet)
			activeCast:SetVelocity(velocity * -1)
		end
	end)
	--_Bullet length changed event handling
	conTable.LengthChanged = caster.LengthChanged:Connect(function (xActiveCast, lastPoint, rayDir, displacement, velocity, bulletInstance)
		if (xActiveCast ~= activeCast) then return end	
		if (bulletInstance == nil) then return end
		if (currentBullet == nil) then currentBullet = bulletInstance end
		
		local curPos = lastPoint + (rayDir * displacement) -- Getting its current position
		local offsetCFrame = CFrame.new(0, 0, (bulletInstance.Size.Z / 2)) -- Creaing a relative cframe offset that places the bullet behind its current position based on its size
		local curCFrame = CFrame.new(lastPoint, curPos)  * offsetCFrame -- Creaing final cframe for the bullet with the applied offset cframe
		bulletInstance.CFrame = curCFrame
	end)
	--_Terminating event handling
	conTable.Terminating = caster.CastTerminating:Connect(function (xActiveCast)
		if (xActiveCast ~= activeCast) then return end
		if (currentBullet) then 
			if (hit) then
				task.delay(2, function () currentBullet:Destroy() end)
			else
				currentBullet:Destroy()
			end
		end
	end)
end

local function onServerEvent (player, mousePos)
	-- Getting cast behavior
	local plrRig = player.Character
	local castBehavior = createCasterBehavior(plrRig)
	-- Firing shot
	local originalPoint = (plrRig.PrimaryPart.CFrame * CFrame.new(0, 0, -1)).Position 
	fireShot(plrRig, originalPoint, mousePos, castBehavior)
end


RE.OnServerEvent:Connect(onServerEvent)

RBLX PLACE: Fast Cast Issue - Roblox

1 Like

Adding a task.wait() line before changing the RayInfo.Parameters.FilterDescendantsInstances worked, and now the projectile is hitting the player’s character after it ricochets.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.