so i did do a patrt of it, now teher is two raycasts, one for client and one for server, i just took the position, size and the color to the server and made a part, how would i make the whole thing serversided?
client script:
local Debris = game:GetService("Debris")
local LaserGun = script.Parent
local Tip = LaserGun:WaitForChild("Tip")
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
local Player = game.Players.LocalPlayer
local Character = Player.Character
local GunDamage = 30
equipped = false
shooting = false
local connection
LaserGun.Parent.Equipped:Connect(function(Mouse)
equipped = true
connection = Mouse.Button1Down:Connect(function()
shooting = true
while shooting and equipped do
local Laser = Ray.new(Tip.CFrame.p, (Mouse.Hit.p - Tip.CFrame.p).unit * 300)
local HitPart, HitPosition = game.Workspace:FindPartOnRay(Laser, Character, false, true)
LaserGun.Position += LaserGun.CFrame.RightVector * 0.1;
local LaserBeam = Instance.new("Part", game.Workspace)
LaserBeam.BrickColor = BrickColor.new("New Yeller")
LaserBeam.FormFactor = "Custom"
LaserBeam.Material = "Plastic"
LaserBeam.Transparency = 0.25
LaserBeam.Anchored = true
LaserBeam.CanCollide = false
local LaserDistance = (Tip.CFrame.p - HitPosition).Magnitude
LaserBeam.Size = Vector3.new(0.3, 0.3, LaserDistance)
LaserBeam.CFrame = CFrame.new(Tip.CFrame.p, HitPosition) * CFrame.new(0, 0, -LaserDistance/2)
wait(0.1)
LaserGun.Position += LaserGun.CFrame.RightVector * -0.1;
Debris:AddItem(LaserBeam, 0.1)
ray:FireServer(LaserBeam.Size,LaserBeam.CFrame,LaserBeam.BrickColor)
if HitPart then
local HitHumanoid = HitPart.Parent:FindFirstChild("Humanoid")
if not HitHumanoid then
HitHumanoid = HitPart.Parent.Parent:FindFirstChild("Humanoid")
end
if HitHumanoid and HitHumanoid ~= script.Parent.Parent.Parent.Humanoid then
HitHumanoid:TakeDamage(GunDamage)
end
end
wait(0.1)
end
end)
end)
LaserGun.Parent.Unequipped:Connect(function(Mouse)
equipped = false
end)
Player.Mouse.Button1Up:Connect(function()
shooting = false
connection:Disconnect()
end)
server script:
wait()
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
ray.OnServerEvent:Connect(function(plr,size,position,color)
local LaserBeam = Instance.new("Part", game.Workspace)
LaserBeam.Anchored = true
LaserBeam.Size = size
LaserBeam.CFrame = position
LaserBeam.BrickColor = color
LaserBeam.Transparency = 0.5
wait(0.1)
LaserBeam:Destroy()
end)
I don’t see a raycast on the server side. Ultimately, you need to do a raycast on the server, where the client sends the server the laser tool’s position as well as the mouse hit position, and the server creates its own ray and performs its own :FindPartOnRay from that ray. Creating a client-sided laser beam from a client-sided raycast is fine, except the local client will see two laser beams, one from the client and one eventually created by the server. Either you need to not create the beam on the client (not good for immediate feedback) or you need to have the server FireAllClients() with a different RemoteEvent that tells everyone to draw a laser beam whilst also passing the player who shot. That way, the shooting player can compare it’s player name to the shooting player name from the FireAllClients() event, and it won’t create a laser beam if the two player names are equal.
The “if Hitpart” section of the code needs to be on the server. It won’t even work on the client side, as the client doesn’t have the ability to invoke the TakeDamage() method on Humanoids other than the local humanoid.
Remember that a cheating client could send a bogus position. It would be ideal to only pass the part the client thinks it hit. Then the server can do its own ray cast based on where it knows the player’s tool position to be in the direction of the part the client claims it hit. If that part is indeed hit, then you know the client isn’t performing a “shoot-through-walls” hack, for example.
local Debris = game:GetService("Debris")
local LaserGun = script.Parent
local Tip = LaserGun:WaitForChild("Tip")
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
local Player = game.Players.LocalPlayer
local Character = Player.Character
local GunDamage = 30
equipped = false
shooting = false
local connection
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
LaserGun.Parent.Equipped:Connect(function(Mouse)
equipped = true
connection = Mouse.Button1Down:Connect(function()
shooting = true
while shooting and equipped do
LaserGun.Position += LaserGun.CFrame.RightVector * 0.1;
ray:FireServer(script.Parent.Tip.CFrame.Position, Mouse.Hit.Position)
wait(0.1)
LaserGun.Position += LaserGun.CFrame.RightVector * -0.1;
end
end)
end)
LaserGun.Parent.Unequipped:Connect(function(Mouse)
equipped = false
end)
Player.Mouse.Button1Up:Connect(function()
shooting = false
connection:Disconnect()
end)
Nice work so far keep it up! I’d like to offer a little bit of advice to clean up your variables and separate it a bit more from that beefy function of yours.
oh ye oops lemme delete that rn, i am trying to modify a youtuber’s script, it works…ish, the bullet hole is stacking on top of eachother, trying to make an if statement for that rn
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
ray.OnServerEvent:Connect(function(Player, FromP, ToP)
local RayCast = Ray.new(FromP,(ToP-FromP).unit*100)
local Part,Position,Normal = game.Workspace:FindPartOnRay(RayCast,Player.Character, false,true)
local Dist = (ToP-FromP).magnitude
if not Dist then Dist = 300 end
local Lazer = Instance.new("Part")
Lazer.Parent = game.Workspace
Lazer.Anchored = true
Lazer.CanCollide = false
Lazer.Size = Vector3.new(0.5,0.5,Dist)
Lazer.CFrame = CFrame.new(FromP,Position)*CFrame.new(0,0,-Dist/2)
local Hole = game.ReplicatedStorage.Hole:Clone()
Hole.Parent = Part.Parent
if ToP.Name ~= Hole then
Hole.Position = ToP
Hole.CFrame = CFrame.new(Hole.Position, Hole.Position+Normal)
local Weld = Instance.new("Weld")
Weld.Part0 = Part
Weld.Part1 = Hole
Weld.C0 = Part.CFrame:Inverse()
Weld.C1 = Hole.CFrame:Inverse()
Weld.Parent = Hole
game.Debris:AddItem(Lazer,0.2)
end
if Part and Part.Parent:FindFirstChild("Humanoid") then
Part.Parent.Humanoid:TakeDamage(30)
end
game.Debris:AddItem(Hole,10)
end)
well i kinda learn while editing, i have to know what each part does for me to change it, or else i can’t edit at all, im just bad at putting stuff together so i learn by breaking apart other people’s finished product to fit my needs
You haven’t done the raycast on the server side yet. That is critical to do, or else the client can change what it sends on the “Ray” event to whatever it wants, and the server has no idea if it should damage the HitPart’s humanoid or not.
Remember that the localscripts you make can be completely changed to anything that a hacker wants it to be. The only thing hackers can’t change are server-side scripts. It’s ok for the client to do its own ray cast, but the server must double-check and validate what the client sends.
For example, the client is sending the “Tip” part to the server, and the server blindly believes that it has received the tip of the shooter’s gun. A hacker won’t send the tip of their gun. They will change the localscript to send a part that’s right next to the HitPart on the player they want to damage. The server will then blindly cast a ray from the fake Tip part to the HitPart, see that it’s close and isn’t blocked by anything, and it will incorrectly damage an innocent player that could be 5000 studs away from the hacker.
You get the plr object on the server side when the Ray event fires. Use that player object to get its character object, then the tool object from the character, then the tip from the tool.
--do this in the server script inside the ray server event
local serverTip = plr.Character.Tool.Tip --I don't know what your Tool is named here
local shooterTipPosition = serverTip.Position
local serverLaserRay = Ray.new(shooterTipPosition, (HitPosition - shooterTipPosition).unit * 300)
local serverHitPart, serverHitPosition = game.Workspace:FindPartOnRay(serverLaserRay, plr.Character, false, true)
if HitPart ~= serverHitPart then
print("Either " , plr.Name, " is a cheater or a big lagger!")
return
end