We will be using Debris to remove the bullet after 2 seconds instead of wait(). Debris removes the part after 2 seconds if they still exists, and does not error if the part no longer exists.
TweenService will be used to move the bullet forward, although there are other methods, such as BodyMovers and Hitscan. We take the direction the HumanoidRootPart is facing, and tween the bullet 100 studs that way. The X axis and Z axis might need to be swapped.
To deal damage, we can use :TakeDamage() on the humanoid.
As I did not test this, you might encounter errors, or if you need further explanation, feel free to ask.
local ServerStorage = game:GetService('ServerStorage')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local TweenService = game:GetService('TweenService')
local Debris = game:GetService('Debris')
ReplicatedStorage.Remotes.WaterBullet.OnServerEvent:Connect(function(player)
local humanoidRootPartCFrame = player.Character.HumanoidRootPart
local bullet = ServerStorage.WaterBullet:Clone()
bullet.CFrame = humanoidRootPartCFrame
bullet.Parent = workspace
TweenService:Create(bullet, TweenInfo.new(0.1), {Position = Vector3.new(humanoidRootPartCFrame.LookVector * 100, bullet.Position.Y, bullet.Position.Z)}):Play()
bullet.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild('Humanoid')
if humanoid and hit.Parent.Name ~= player.Name then
bullet:Destroy()
humanoid:TakeDamage(10)
end
end)
Debris:AddItem(bullet, 2)
end)