Break between weapon + beam

Hello, why is there a break between the weapon and the beam? Sometimes the beam is not visible.
Sometimes it does not create the beam and parent it to workspace.

https://gyazo.com/7d7aef54751807fcb498570cbe788823

Client:

local plr = game:GetService("Players").LocalPlayer
local mouse = plr:GetMouse()

local rs = game:GetService("ReplicatedStorage")

local pressing = false

local ColorAmmo = script.ColorAmmo
local DamageAmmo = script.DamageAmmo

local function handleAction()
	pressing = true
	local char = plr.Character
	local possibleARI = char:FindFirstChild("ARI")
	while true do 
		local isEquipped = rs.Events.Items.GetARIEquipped:InvokeServer()
		if isEquipped then
			local isReloading = rs.Events.Items.GetARIReloading:InvokeServer()
			if not isReloading then
				if pressing then 
					rs.Events.Items.ARIShoot:FireServer(pressing)
					rs.Events.Items.Shoot:FireServer("ARI", mouse.Hit.p, DamageAmmo.Value, ColorAmmo.Value)
					task.wait(0.1)
				end
			end
		end
	end
end

mouse.Button1Down:Connect(handleAction)
mouse.Button1Up:Connect(function()
	pressing = false
end)

Server :

local rs = game:GetService("ReplicatedStorage")
local event = rs.Events.Items.Shoot

event.OnServerEvent:Connect(function(plr, nameGun, mousepos, degat, color)
	local char = plr.Character
	local gun = char:FindFirstChild(nameGun)

	if gun then 
		local cp = gun:FindFirstChild("ShootPos").CFrame.p
		local ray = Ray.new(cp, (mousepos - cp).unit * 300)
		local part, position = workspace:FindPartOnRay(ray, char, false, true)

		local beam = Instance.new("Part", workspace)
		beam.BrickColor = color
		beam.FormFactor = "Custom"
		beam.Transparency = 0.8
		beam.Anchored = true
		beam.Locked = true
		beam.CanCollide = false

		local distance = (cp - position).magnitude
		beam.Size = Vector3.new(0.04, 0.04, distance)
		beam.CFrame = CFrame.new(cp, position) * CFrame.new(0, 0, -distance / 2)

		game:GetService("Debris"):AddItem(beam, 0.1)

		if part then
			local humanoid = part.Parent:FindFirstChild("Humanoid")

			if not humanoid then
				humanoid = part.Parent.Parent:FindFirstChild("Humanoid")
			end

			if humanoid then
				humanoid:TakeDamage(degat)
			end
		end
	end
end)
2 Likes

Using InvokeServer means that it will expect the function to callback on the client, meaning that it will wait for the connection between the client and the server before moving. I would highly suggest not checking if the weapon is reloading from the server each shot as it is yielding the code in the meantime. I would use a RemoteEvent to instead track that information and also simply track it from the client. That way you have a sanity check while also a more accurate method to read important information such as a weapon reload.

Regarding making bullets in the workspace, I also believe rather than make the bullets inside of workspace, you should make the bullets inside of the player’s client and when the event is sent to the server, have the server send the event to all other clients. Bullets should not need to appear on the server for any reason.

If I understood :

  • I should change shoot bullets event, to fire all clients and no fire server.
  • I should check if it’s reloading on server (in the shoot bullets event and no in the localscript with Invoke).

Am I right ?

1 Like

Not exactly.

Use the client to determine whether or not the player needs to reload. In the client side, you should have a reload value which when the reload function would fire, changes the reload variable. You can use a RemoteEvent instead of a RemoteFunction and FireServer instead of InvokeServer to send the reload information to the server for sanity checking purposes or data gathering purposes.
Referring to this line: “local isReloading = rs.Events.Items.GetARIReloading:InvokeServer()”

When you fire the bullet, you do fire it to the server. The server should fire back all other clients. These are fine:
rs.Events.Items.ARIShoot:FireServer(pressing)
rs.Events.Items.Shoot:FireServer(“ARI”, mouse.Hit.p, DamageAmmo.Value, ColorAmmo.Value)

When it does fire to the server, the server should instead FireClient to each other player, creating the bullet on each other individual client.

1 Like

Can you show me an example plz :frowning: ?

1 Like
local plr = game:GetService("Players").LocalPlayer
local mouse = plr:GetMouse()
local isReloading = false

local rs = game:GetService("ReplicatedStorage")

local pressing = false

local ColorAmmo = script.ColorAmmo
local DamageAmmo = script.DamageAmmo

local function CreateBullet(a, pos, dmg, col, origplr)
    local char = origplr.Character
    local gun = char:FindFirstChild(nameGun)
    local cp = gun:FindFirstChild("ShootPos").CFrame.p
    local ray = Ray.new(cp, (pos - cp).unit * 300)
	local part, position = workspace:FindPartOnRay(ray, char, false, true)
							
	local beam = Instance.new("Part", workspace)
	beam.BrickColor = col
	beam.FormFactor = "Custom"
	beam.Transparency = 0.8
	beam.Anchored = true
	beam.Locked = true
	beam.CanCollide = false
							
	local distance = (cp - position).magnitude
	beam.Size = Vector3.new(0.04, 0.04, distance)
	beam.CFrame = CFrame.new(cp, position) * CFrame.new(0, 0, -distance / 2)
end

local function handleAction()
	pressing = true
	local char = plr.Character
	local possibleARI = char:FindFirstChild("ARI")
	while true do 
		local isEquipped = rs.Events.Items.GetARIEquipped:InvokeServer()
		if isEquipped then
			if not isReloading then
				if pressing then 
					rs.Events.Items.ARIShoot:FireServer(pressing)
					rs.Events.Items.Shoot:FireServer("ARI", mouse.Hit.p, DamageAmmo.Value, ColorAmmo.Value)
                   CreateBullet("ARI", mouse.Hit.p, DamageAmmo.Value, ColorAmmo.Value, plr)
					task.wait(0.1)
				end
			end
		end
	end
end

rs.Events.Items.Shoot.OnClientEvent:Connect(function(rename, repos, redmg, reammo, replr)
CreateBullet(rename, repos, redmg, reammo, replr)
end)

mouse.Button1Down:Connect(handleAction)
mouse.Button1Up:Connect(function()
	pressing = false
end)
local rs = game:GetService("ReplicatedStorage")
local event = rs.Events.Items.Shoot

event.OnServerEvent:Connect(function(plr, nameGun, mousepos, degat, color)
	local char = plr.Character
	local gun = char:FindFirstChild(nameGun)

	if gun then 
		if part then
			local humanoid = part.Parent:FindFirstChild("Humanoid")
            
            for _,p in pairs(game.Players:GetPlayers()) do
                if p ~= plr then
                    event:FireClient(p, nameGun, mousepos, degat, color, plr)
                end
            end

			if not humanoid then
				humanoid = part.Parent.Parent:FindFirstChild("Humanoid")
			end

			if humanoid then
				humanoid:TakeDamage(degat)
			end
		end
	end
end)
2 Likes

something like that

im never attempting to code using the dev forum again that was tedious >.<

Didn’t have any way to check errors either so let me know how it goes.

2 Likes

In your code how do I get part in server side ?

1 Like

I can add a script in the bullet to detect if it touched a humanoid for example.

Sometimes the ray is not correctly on my mouse + no damage on characters.
And btw there is still the problem when I move.

local plr = game:GetService("Players").LocalPlayer
local mouse = plr:GetMouse()
local isReloading = false

local rs = game:GetService("ReplicatedStorage")

local pressing = false

local ColorAmmo = script.ColorAmmo
local DamageAmmo = script.DamageAmmo

local function CreateBullet(nameGun, pos, dmg, col, origplr)
	local char = origplr.Character
	local gun = char:FindFirstChild(nameGun)
	local cp = gun:FindFirstChild("ShootPos").CFrame.p
	local ray = Ray.new(cp, (pos - cp).unit * 300)
	local part, position = workspace:FindPartOnRay(ray, char, false, true)
	
	local scriptBeam = script.Parent.ScriptBeam_ARI:Clone()
	local beam = Instance.new("Part", workspace)
	scriptBeam.Parent = beam
	beam.BrickColor = col
	beam.FormFactor = "Custom"
	beam.Material = Enum.Material.Neon
	beam.Transparency = 0.8
	beam.Anchored = true
	beam.Locked = true
	beam.CanCollide = false

	local distance = (gun:FindFirstChild("ShootPos").CFrame.p - position).magnitude
	beam.Size = Vector3.new(0.04, 0.04, distance)
	beam.CFrame = CFrame.new(cp, position) * CFrame.new(0, 0, -distance / 2)
	
	game:GetService("Debris"):AddItem(beam, 0.005)
end

local function handleAction()
	pressing = true
	local char = plr.Character
	local possibleARI = char:FindFirstChild("ARI")
	while true do 
		local isEquipped = rs.Events.Items.GetARIEquipped:InvokeServer()
		if isEquipped then
			if not isReloading then
				if pressing then 
					rs.Events.Items.ARIShoot:FireServer(pressing) -- Animation
					rs.Events.Items.Shoot:FireServer("ARI", mouse.Hit.p, DamageAmmo.Value, ColorAmmo.Value)
					CreateBullet("ARI", mouse.Hit.p, DamageAmmo.Value, ColorAmmo.Value, plr)
					task.wait(0.1)
				end
			end
		end
	end
end

rs.Events.Items.Shoot.OnClientEvent:Connect(function(rename, repos, redmg, reammo, replr)
	CreateBullet(rename, repos, redmg, reammo, replr)
end)

mouse.Button1Down:Connect(handleAction)
mouse.Button1Up:Connect(function()
	pressing = false
end)

ScriptBeam_ARI :

script.Parent.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
		local humanoid = hit.Parent:FindFirstChild("Humanoid")  
		humanoid:TakeDamage(script.Parent.ShootARI.DamageAmmo)
		script.Parent:Destroy()
	end
end)

Server :

local rs = game:GetService("ReplicatedStorage")
local event = rs.Events.Items.Shoot

event.OnServerEvent:Connect(function(plr, gunName, posMouse, dmg, color)
	event:FireAllClients(gunName, posMouse, dmg, color, plr)
end)

Unless the beam is a constant ongoing beam, I wouldn’t recommend using the touchedevent for it. In fact, I wouldn’t recommend using the touchedevent for it even if that is the case; you’d be better off detecting all players on the ray from the client and just as reliably send that information to the server.

You don’t want to make the beam in the server at all. I didn’t see ScriptBeam there but if it IS an ongoing beam (which doesn’t seem possible considering it disappears at half a frame) but if there was you’d want to make a few changes.

Just take out scriptBeam entirely otherwise.

On the server you’ll want it to fire all other clients, not all clients. You want the client to have their version first.

I did not understand…
Example :frowning: ?

I have to for each all player from Players and check if it’s not, I fire this client ?

In other words, just remove ScriptBeam entirely. The script for it and the reference to it. You don’t need ScriptBeam.

Do not use
event:FireAllClients(gunName, posMouse, dmg, color, plr)

Use
for _,p in pairs(game.Players:GetPlayers()) do
if p ~= plr then
event:FireClient(p, nameGun, mousepos, degat, color, plr)
end
end

1 Like

The second part I understood but how I do damages then ?

local rs = game:GetService("ReplicatedStorage")
local event = rs.Events.Items.Shoot

event.OnServerEvent:Connect(function(plr, gunName, posMouse, dmg, color)
	for _,p in pairs(game.Players:GetPlayers()) do
		if p ~= plr then
			event:FireClient(p, gunName, posMouse, dmg, color, plr)
		end
	end
end)

The part below it is what does the damage.

if not humanoid then
	humanoid = part.Parent.Parent:FindFirstChild("Humanoid")
end

if humanoid then
	humanoid:TakeDamage(degat)
end

??? What are you talking about ? What “part below” ?

the server

local rs = game:GetService("ReplicatedStorage")
local event = rs.Events.Items.Shoot

event.OnServerEvent:Connect(function(plr, nameGun, mousepos, degat, color)
	local char = plr.Character
	local gun = char:FindFirstChild(nameGun)

	if gun then 
		if part then
			local humanoid = part.Parent:FindFirstChild("Humanoid")
            
            for _,p in pairs(game.Players:GetPlayers()) do
                if p ~= plr then
                    event:FireClient(p, nameGun, mousepos, degat, color, plr)
                end
            end

			if not humanoid then
				humanoid = part.Parent.Parent:FindFirstChild("Humanoid")
			end

			if humanoid then
				humanoid:TakeDamage(degat)
			end
		end
	end
end)

There is not “part” in your function, it’s undefined.