Remote event problems - lua

I'm making a game using ROBLOX about the tank battle system of Dragon Quest Heroes Rocket Slime (although not using 100% GUI's)
Since I didn't know how to make ammo become locked onto a path in normal ROBLOX, I decided to use a gui to show the ammo "firing"
To do this, I have a remote event that fires a function inside the main script of the GUI system when ammo is loaded
cannon.Touched:connect(function(v)
if fireable[v.Name] and v.Parent == workspace then
event:FireAllClients("Left",v.Name)
v:Destroy()
end
end)
Then, the GUI gets the correct sprite for the ammo loaded and fires it out of the right tank (the first argument in the FireAllClients part)
This is one of the two if statements for firing ammo (the other one is literally the same except that it's for the right side tank)
local tank = tankFiring == "Left" and tank1 or tankFiring == "Right" and tank2
if tank == tank1 then
print("yo!")
script.Fire:Play()
local ammoFrame = sp.Ammo:Clone()
ammoFrame.Parent = tank
ammoFrame.Visible = true
ammoFrame.Position = UDim2.new(0,120,0,68)
playAnimation("Cannon Fire",UDim2.new(0,120,0,68-25),tank.Frame)
ammoFrame.Image = ammoTypes[type]["img"]
ammoFrame.Size = ammoTypes[type]["Size"]
repeat
wait(.1)
ammoFrame.Rotation = ammoTypes[type]["Rotatable"] == true and ammoFrame.Rotation + 15 or 0
ammoFrame.Position = ammoFrame.Position + UDim2.new(0,1,0,0)
until
tank2:FindFirstChild("Ammo") and isTouching(ammoFrame,tank2:GetChildren()[3]) or isTouching(ammoFrame,tank2) or ammoFrame == nil
if tank2:FindFirstChild("Ammo") and isTouching(ammoFrame,tank2:GetChildren()[3]) then
script.Collision:Play()
local lastAmmoPos = ammoFrame.Position
playAnimation("Explosion",lastAmmoPos-UDim2.new(0,15,0,25),tank.Frame)
ammoFrame:Destroy()
tank2:GetChildren()[3]:Destroy()
end
if isTouching(ammoFrame,tank2) then
script.Collision:Play()
ammoFrame:Destroy()
workspace["Tank2"].Health.Value = workspace["Tank2"].Health.Value - ammoTypes[type]["dmg"]
end
end
The problem with this, is that if a player joins AFTER the ammo has been shot, they will not see the ammo on the GUI
Is there anyway to fix this? I can't just FireAllClients again, since that'll just fire another piece of ammo for all the players.

Have a service that keeps track of what ammo is in what state. Then all clients first asks the servers of current ammo states when joining, and then subscribes to further changes.

Related

Other players can not see an object duplicate

I have this script that duplicates an object and teleports it to the player when the GUI button is pressed (You can think of GMod to make things easier). It is stored in a LocalScript inside the button and when you press it, but it's only visible for the player that clicked the button.
I'm not exactly sure how I would solve the problem or what the problem is, but I think it's because it's all stored into a LocalScript. I'm new to Lua and Roblox game development and I didn't really take any lessons on it, I'm just working from my memory and experience. Any and all suggestions are greatly appreciated. Also, if I need to give more information, please ask and I will provide it.
My script:
local player = game.Players.LocalPlayer
script.Parent.MouseButton1Click:Connect(function()
local rag = game.Lighting.ragdolls_presets["Wood Crate"]:Clone()
local X = player.Character.UpperTorso.Position.X
local Y = player.Character.UpperTorso.Position.Y + 10
local Z = player.Character.UpperTorso.Position.Z
rag.Parent = game.Workspace.ragdolls
local children = rag:GetChildren()
for i = 1, #children do
local child = children[i]
child.Position = Vector3.new(X,Y,Z)
end
end)
Thank you in advance!
When you clone something in a LocalScript, it only clones on the client side. Changes done on the client side never gets replicated to the server side, however all changes done on the server side would get replicated to all clients, which are the players.
So to fix this you'd need to use RemoteEvents, which is a way for the client to tell the server to do something.
So instead of doing this in a LocalScript
local player = game.Players.LocalPlayer
script.Parent.MouseButton1Click:Connect(function()
local rag = game.Lighting.ragdolls_presets["Wood Crate"]:Clone()
local X = player.Character.UpperTorso.Position.X
local Y = player.Character.UpperTorso.Position.Y + 10
local Z = player.Character.UpperTorso.Position.Z
rag.Parent = game.Workspace.ragdolls
local children = rag:GetChildren()
for i = 1, #children do
local child = children[i]
child.Position = Vector3.new(X,Y,Z)
end
end)
Put a new RemoteEvent in game.Replicated Storage, then:
This should be the LocalScript
local Event = game.ReplicatedStorage.RemoteEvent
script.Parent.MouseButton1Click:Connect(function()
Event:Fire()
end)
And this should be the ServerScript (or Script for short)
local Event = game.ReplicatedStorage.RemoteEvent
Event.OnServerEvent:Connect(function(player)
local rag = game.Lighting.ragdolls_presets["Wood Crate"]:Clone()
local X = player.Character.UpperTorso.Position.X
local Y = player.Character.UpperTorso.Position.Y + 10
local Z = player.Character.UpperTorso.Position.Z
rag.Parent = game.Workspace.ragdolls
local children = rag:GetChildren()
for i = 1, #children do
local child = children[i]
child.Position = Vector3.new(X,Y,Z)
end
end)
Also, it is very important to do server-side validation when using RemoteEvents, for example: instead of checking whether a player has enough money to spawn something in a LocalScript before the RemoteEvent is fired, it should be done in both LocalScript and the ServerScript. The cause for this is that players can change anything in their client side, so information from the client can NOT be trusted. Optionally you can also have time-outs in each side because, lets say a player has millions of money, he can keep executing the RemoteEvent hundreds of times in under a minute which can crash the server or cause extreme lag. So a 3 second - 1 minute time out is sometimes necessary
More information about Roblox's Client-Server Model: https://create.roblox.com/docs/scripting/networking/client-server-model
More information about Roblox RemoteEvents: https://create.roblox.com/docs/reference/engine/classes/RemoteEvent

Cloning Locally and not locally [Lua]

I've been trying to make a sword fight game on Roblox studio. I've made a shop Gui so you can click the text button to buy the sword. It works well, You click it checks your kills and if you have enough you get the weapon. In this case, it's 0 kills. But when you take out the sword you cant use it. I've done my research and I believe that's because it's been cloned locally and not globally. Is this the case and if so how do I fix it?
The script in the Text Button:
local player = game.Players.LocalPlayer
script.Parent.MouseButton1Click:Connect(function()
if player.leaderstats.Kills.Value >= 0 then
local clonar = game.ServerStorage.ClassicSword:Clone()
clonar.Parent = player.Backpack
end
end)
Thanks in advance!
When work needs to be performed on the server (as opposed to locally on the client), you can use RemoteEvents to communicate across the client-server boundary.
So first, you'll need to create a RemoteEvent in a shared location, like ReplicatedStorage.
Next, update your client-side LocalScript to fire the RemoteEvent :
local player = game.Players.LocalPlayer
local buyEvent = game.ReplicatedStorage.RemoteEvent
script.Parent.MouseButton1Click:Connect( function()
buyEvent:FireServer()
end)
Finally, you need to create a Script in the Workspace or ServerScriptService that listens for that RemoteEvent and performs the work of giving the player the item :
local buyEvent = game.ReplicatedStorage.RemoteEvent
buyEvent.OnServerEvent:Connect( function(player)
if player.leaderstats.Kills.Value >= 0 then
local clonar = game.ServerStorage.ClassicSword:Clone()
clonar.Parent = player.Backpack
end
end)

Why does my list clear/lose its contents? [ROBLOX]

local sounds = {
877986525;
2734549871;
}
local PrimaryQueue = {} -- Player Chosen Songs.
local SoundObj = workspace.MusicSystem
function PlaySoundAndWait(SoundId)
SoundObj.SoundId = "rbxassetid://"..SoundId
print("Loading Sound...")
repeat wait() until SoundObj.IsLoaded
print("Loaded")
SoundObj:Play()
repeat wait() until not SoundObj.Playing -- Wait till over.
end
local PlaySecondary = sounds
while wait(0.1) do
if #PrimaryQueue ~= 0 then
print("Play primary disregard current")
-- Play primary, disregard current.
PlaySoundAndWait(PrimaryQueue[1])
table.remove(PrimaryQueue,1) -- Remove from queue (played)
else
-- Refill Secondary Queue if empty.
if #PlaySecondary == 0 then
print("REFILL")
PlaySecondary = sounds
print(#sounds)
continue
end
print(PlaySecondary[1])
PlaySoundAndWait(PlaySecondary[1])
table.remove(PlaySecondary,1)
end
end
When I refer to "REFILL" I mean line 26 where the list is refreshed.
This script indefinitely checks if there's anything in the PrimaryQueue, if there is it plays that then removes it. If there's not it checks if the SecondaryQueue is empty, if so it refills it with "sounds". If it's not it plays the first sound then removes it.
As a result all of this should create a music system, but for some reason when refilling, the sound list reads as empty. Even though it shouldn't be and has only been assigned a value once.
Thank you.
You are doing table.remove(PlaySecondary, 1) which is equal to table.remove(sounds, 1) as they both point to the same table due to PlaySecondary = sounds, so it's coming back empty because you yourself removed all its elements previously!
I assume you wanted to create a copy of the table:
PlaySecondary = {unpack(sounds)}

How would I make a player invisible only to certain players?

Basically what I've done so far is add a boolValue to every player, and if that boolValue is set to true, they can see invisible people, if it is false, they can't. I am clueless about the code currently so I have no idea how to begin. I'm also changing the value of the Bool Value through a tool.
The key to making one player invisible only to certain players is the understanding that any changes made to the world in a LocalScript are only visible to that player. They are not replicated between other clients. So, if we can set up a system where LocalScripts can be told to turn a specific player invisible, that player will vanish from their screen and their screen only.
So if we had that system, Player Two could say, "Hey game server, could you let the people know to turn me invisible!". That message would go up to the server, the server would send it out to a bunch of different clients, and each client would make the change locally using their LocalScripts, and the player would effectively turn invisible on their screen.
So even though Player Two looks to be invisible to Players One and Three, to the game server, nothing is different or out of the ordinary, the changes are localized entirely to each player's version of the world.
One way to do this is to use a setup like this :
A Tool in StarterPack to allow players to control their visibility
A BoolValue inside that tool to hold onto the visiblity state
A LocalScript to control the tool's logic
A RemoteEvent in ReplicatedStorage
A Script in ServerScriptService to handle the event routing
In the LocalScript, you would have something like this :
local tool = script.Parent
local IsHidden = tool:WaitForChild("IsHidden", 5)
local TogglePlayerVisible = game.ReplicatedStorage.TogglePlayerVisible
local localPlayer = game.Players.LocalPlayer
-- debug
tool.Name = "Turn Invisible"
tool.RequiresHandle = false
IsHidden.Value = false
-- 1) When a player activates the tool, flip the BoolValue
tool.Activated:Connect(function()
IsHidden.Value = not IsHidden.Value
tool.Name = IsHidden.Value and "Become Visible" or "Turn Invisible"
end)
-- 2) When the BoolValue changes, tell the server about it
IsHidden.Changed:Connect(function(updatedValue)
TogglePlayerVisible:FireServer(updatedValue)
end)
-- 4) When the server tells us a player has used the tool, make that player invisible locally
TogglePlayerVisible.OnClientEvent:Connect(function(player, isHidden)
local invisible = 1.0
local visible = 0.0
-- if we are the one who sent it, only make us a little invisible
if (player.Name == localPlayer.Name) then
invisible = 0.7
end
-- loop over all of the parts in a player's Character Model and hide them
for _, part in ipairs(player.Character:GetDescendants()) do
local shouldTogglePart = true
-- handle exceptions
if not (part:IsA("BasePart") or part:IsA("Decal")) then
shouldTogglePart = false
elseif part.Name == "HumanoidRootPart" then
shouldTogglePart = false
end
-- hide or show all the parts and decals
if shouldTogglePart then
part.Transparency = isHidden and invisible or visible
end
end
end)
And in the Script, you would have something like this :
local TogglePlayerVisible = game.ReplicatedStorage.TogglePlayerVisible
-- 3) whenever a player triggers this event, send it out to all players
TogglePlayerVisible.OnServerEvent:Connect(function(player, isVisible)
TogglePlayerVisible:FireAllClients(player, isVisible)
end)
If you would like only specific players to not see a player, then you can modify step 3 so that instead of using TogglePlayerVisible:FireAllClients, you would specifically choose which players to send the message to using FireClient.

How do I make this code function correctly?

I want to make a sort of Lobby system in Roblox Studio where if you have 4 people on a part you get sent to another place. I tried to set up a system for it, but it didn't work; can you help me through this?
I've tried making it so it says .Value at the end.
local TeleportService = game:GetService("TeleportService")
player_amount = script.Parent.Parent.Parent.Player_Count
local placeID_1 = 4119652438
local function onPartTouch(otherPart)
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
player_amount.Value = player_amount.Value + 1
end
if player_amount == 4 then
TeleportService:Teleport(placeID_1, player)
end
end
script.Parent.Touched:Connect(onPartTouch)
I expected the output to be 0 then if one person steps on it, it would update the sign to say 1. But it only stays at 0.
This is not a viable solution as .Touched fires every frame the player touches a part, and only when they move. I suggest creating a hitbox, as I have done here

Resources