Rotating part based on another part's surface

Hello, i have a problem with my spit tool, whenever it shoots out a puddle part the puddle are not rotated correctly like what i expected, how can i make the puddle to rotate based on the part surface that it lands on?

local tool = script.Parent
local remote = tool.Splitted
local bullet = game.ServerStorage.cube

local fastcast = require(tool.FastCastRedux)
local mcchitbox = require(game.ReplicatedStorage.MuchachoHitbox)
local table = require(tool.FastCastRedux.Table)
local partcache = require(tool.PartCache)

local debris = game:GetService("Debris")
local tween = game:GetService("TweenService")

local hum = tool.Parent:FindFirstChild("Humanoid")

local CosmeticBulletsFolder = workspace:FindFirstChild("CosmeticBulletsFolder") or Instance.new("Folder", workspace)
CosmeticBulletsFolder.Name = "CosmeticBulletsFolder"

local bulletTemplate = Instance.new("Part")
bulletTemplate.Anchored = true
bulletTemplate.CanCollide = false
bulletTemplate.Shape = "Ball"
bulletTemplate.Size = Vector3.new(0.5,0.5,0.5)
bulletTemplate.Material = Enum.Material.Neon
bulletTemplate.Color = Color3.fromRGB(0, 170, 0)

local CosmeticPartProvider = partcache.new(bulletTemplate, 1, CosmeticBulletsFolder)

local caster = fastcast.new()

local castParams = RaycastParams.new()
castParams.FilterType = Enum.RaycastFilterType.Exclude
castParams.IgnoreWater = true

local castBehavior = fastcast.newBehavior()
castBehavior.RaycastParams = castParams
castBehavior.Acceleration = Vector3.new(0, -workspace.Gravity, 0)
castBehavior.AutoIgnoreContainer = false
castBehavior.CosmeticBulletProvider = CosmeticPartProvider 
castBehavior.CosmeticBulletContainer = CosmeticBulletsFolder
castBehavior.MaxDistance = 600

local poisonDuration = 10
local poisonInterval = 0.1
local poisonDamage = 0.3

local toolOwner = tool.Parent

local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude

function IsTeamMate(Player1, Player2)
	return (Player1 and Player2 and not Player1.Neutral and not Player2.Neutral and Player1.TeamColor == Player2.TeamColor)
end

function MakeParticleFX(position, normal)

	params.FilterDescendantsInstances = {tool.Parent}

	local attachment = Instance.new("Attachment")
	attachment.CFrame = CFrame.new(position, position + normal)
	attachment.Parent = workspace.Terrain
	local particle = script.poisonous:Clone()
	particle.Parent = attachment
	debris:AddItem(attachment, particle.Lifetime.Max)

	local puddle = Instance.new("Part")
	puddle.Shape = Enum.PartType.Cylinder
	puddle.Size = Vector3.new(0.05,20,20)
	puddle.Anchored = true
	puddle.CanCollide = false
	puddle.CastShadow = false
	puddle.Color = Color3.fromRGB(79, 255, 94)
	puddle.Material = Enum.Material.SmoothPlastic
	puddle.Parent = workspace

	puddle.CFrame = CFrame.lookAt(position, position + normal) * CFrame.Angles(math.rad(90), 0, 0)

	local puddlehitbox = mcchitbox.CreateHitbox()
	puddlehitbox.Size = Vector3.new(0.5,20,20)
	puddlehitbox.DetectionMode = "ConstantDetection"
	puddlehitbox.CFrame = puddle.CFrame
	puddlehitbox.OverlapParams = params

	local cantouch = false

	puddlehitbox.Touched:Connect(function(hit, human)
		if human == hum then return end
		if cantouch == false then
			local toolOwnerPlayer = game.Players:GetPlayerFromCharacter(toolOwner)
			local hitPlayer = game.Players:GetPlayerFromCharacter(hit.Parent)

			if IsTeamMate(toolOwnerPlayer, hitPlayer) then
				return 
			end

			cantouch = true
			human:TakeDamage(3)

			task.wait(0.5)
			cantouch = false

			local poisonStartTime = tick()
			local attach = Instance.new("Attachment")
			attach.Parent = hit.Parent:FindFirstChild("HumanoidRootPart")
			local poisonEffect = script.poisonous:Clone()
			poisonEffect.Parent = attach
			poisonEffect.Enabled = true

			debris:AddItem(attach, poisonDuration)

			while tick() - poisonStartTime < poisonDuration do
				if human.Health > 0 then
					human:TakeDamage(poisonDamage)
				else
					attach:Destroy()
					return
				end
				task.wait(poisonInterval)
			end
			attach:Destroy()
		end
	end)

	puddlehitbox:Start()
	task.wait(10)
	puddlehitbox:Stop()

	debris:AddItem(puddle, 5)

	particle.Enabled = true
	task.wait(0.05)
	particle.Enabled = false
end

function OnRayHit(cast, raycastResult, segmentVelocity, cosmeticBulletObject)
	local hitPart = raycastResult.Instance
	local hitPoint = raycastResult.Position
	local normal = raycastResult.Normal
	if hitPart ~= nil and hitPart.Parent ~= nil then 
		local humanoid = hitPart.Parent:FindFirstChildOfClass("Humanoid")
		if humanoid then
			humanoid:TakeDamage(0) 
		end
		
		
		MakeParticleFX(hitPoint, normal) 
	end
end

local function onEquipped()
	local character = tool.Parent
	local head = character:FindFirstChild("Head")

	if head then firePoint = Instance.new("Attachment")
		firePoint.Parent = head
		firePoint.Name = "firePoint"
		castParams.FilterDescendantsInstances = {character, CosmeticBulletsFolder}
	end
end

local db= false

remote.OnServerEvent:Connect(function(player, mousePosition)
	if db == false then
		db = true
		if firePoint then
		local origin = firePoint.WorldPosition
		local direction = (mousePosition - origin).Unit
		caster:Fire(origin, direction, 200, castBehavior)
		task.wait(1)
		db = false
		end
	end
end)

function OnRayTerminated(cast)
	local cosmeticBullet = cast.RayInfo.CosmeticBulletObject
	if cosmeticBullet ~= nil then
		if castBehavior.CosmeticBulletProvider ~= nil then
			castBehavior.CosmeticBulletProvider:ReturnPart(cosmeticBullet)
		else
			cosmeticBullet:Destroy()
		end
	end
end

caster.LengthChanged:Connect(function(cast, lastPoint, direction, length, velocity, bullet)
	if bullet then 
		local bulletLength = bullet.Size.Z/2
		local offset = CFrame.new(0, 0, -(length - bulletLength))
		bullet.CFrame = CFrame.lookAt(lastPoint, lastPoint + direction):ToWorldSpace(offset)
	end
end)

caster.RayHit:Connect(OnRayHit)
caster.CastTerminating:Connect(OnRayTerminated)

tool.Equipped:Connect(onEquipped)

Try typing “align bullet holes to surface” in the Search tool. It’s the same basic idea and there have been a few posts about this in the past.