I released a project recently and have it open to a few people for testing. They have been telling me that they are able to use abilities that other players have unlocked, but not actually unlocked themselves. I went and decided to print who was activating the ability, and whos Backpack the script was located in (the players get the script cloned to their backpack when unlocking something) (output).
This is how things are set up in the starterpack. Once a player unlocks an ability they get a script pasted into NenLocal.
NenLocal:
local Player = game.Players.LocalPlayer local Char = workspace:WaitForChild(Player.Name) local Input = game:GetService("UserInputService") local Storage = game:GetService("ReplicatedStorage") local mouse = Player:GetMouse() if Char then Statistics = Player:WaitForChild("Stats") end function Down(inputObject, gameEvent) if Char and Statistics then if inputObject.KeyCode == Enum.KeyCode.E and gameEvent == false then Storage.Remotes.KoDown:FireServer() elseif inputObject.KeyCode == Enum.KeyCode.T and gameEvent == false then Storage.Remotes.EnDown:FireServer() elseif inputObject.KeyCode == Enum.KeyCode.Z and gameEvent == false then Storage.Remotes.HatsuZDown:FireServer(mouse.Hit) elseif inputObject.KeyCode == Enum.KeyCode.X and gameEvent == false then Storage.Remotes.HatsuXDown:FireServer(mouse.Hit) elseif inputObject.KeyCode == Enum.KeyCode.C and gameEvent == false then Storage.Remotes.HatsuCDown:FireServer(mouse.Hit) elseif inputObject.KeyCode == Enum.KeyCode.V and gameEvent == false then Storage.Remotes.HatsuVDown:FireServer(mouse.Hit) elseif inputObject.KeyCode == Enum.KeyCode.B and gameEvent == false then Storage.Remotes.HatsuBDown:FireServer(mouse.Hit) elseif inputObject.KeyCode == Enum.KeyCode.N and gameEvent == false then Storage.Remotes.HatsuNDown:FireServer(mouse.Hit) end end end function Up(inputObject, gameEvent) if Char and Statistics then if inputObject.KeyCode == Enum.KeyCode.E and gameEvent == false then Storage.Remotes.KoUp:FireServer() elseif inputObject.KeyCode == Enum.KeyCode.R and gameEvent == false then if Player.Status.Ren.Value == false then Storage.Remotes.Ren:FireServer() end if Player.Status.Ren.Value == true then Storage.Remotes.RenOff:FireServer() end elseif inputObject.KeyCode == Enum.KeyCode.F and gameEvent == false then if Player.Status.Zetsu.Value == false then Storage.Remotes.Zetsu:FireServer() end if Player.Status.Zetsu.Value == true then Storage.Remotes.ZetsuOff:FireServer() end elseif inputObject.KeyCode == Enum.KeyCode.T and gameEvent == false then Storage.Remotes.EnUp:FireServer() elseif inputObject.KeyCode == Enum.KeyCode.Z and gameEvent == false then Storage.Remotes.HatsuZUp:FireServer(mouse.Hit) elseif inputObject.KeyCode == Enum.KeyCode.X and gameEvent == false then Storage.Remotes.HatsuXUp:FireServer(mouse.Hit) elseif inputObject.KeyCode == Enum.KeyCode.C and gameEvent == false then Storage.Remotes.HatsuCUp:FireServer(mouse.Hit) elseif inputObject.KeyCode == Enum.KeyCode.V and gameEvent == false then Storage.Remotes.HatsuVUp:FireServer(mouse.Hit) end end end Input.InputBegan:Connect(Down) Input.InputEnded:Connect(Up)
Function that everyone is able to use when they cannot: (part of the script that gets pasted into NenLocal)
Storage.Remotes.KoDown.OnServerEvent:Connect(function(Player) print(""..Player.Name.."(Player activating)") print(""..script.Parent.Parent.Parent.Name.."(script location)") if Player.Status.Attacking.Value == false and KoCooldown == 0 and Player.Status.Zetsu.Value == false and Player.Stuns.ShortStun.Value == false and Player.Stuns.MedStun.Value == false and Player.Stuns.LongStun.Value == false and Player.Stuns.Crush.Value == false then local Animation = Player.Character.Humanoid:LoadAnimation(Storage.Animations.BasicNen.KoCharge) Animation:Play() Player.Status.Attacking.Value = true KoCooldown = 1 Ko = ServerStorage.Attacks.BasicNen.Ko:Clone() Ko.CFrame = Player.Character["Right Arm"].CFrame Ko2 = ServerStorage.Attacks.BasicNen.KoParticles:Clone() Ko2.Name = "Ko2" Ko2.CFrame = Player.Character["Right Arm"].CFrame local RHandWeld = Instance.new("Weld") RHandWeld.Parent = Ko RHandWeld.Part0 = RHandWeld.Parent RHandWeld.Part1 = Player.Character["Right Arm"] RHandWeld.C1 = CFrame.new(0, -0.6, 0) Ko.Parent = Player.Character.Bin local RHandWeld2 = Instance.new("Weld") RHandWeld2.Parent = Ko2 RHandWeld2.Part0 = RHandWeld2.Parent RHandWeld2.Part1 = Player.Character["Right Arm"] RHandWeld2.C1 = CFrame.new(0, -0.6, 0) Ko2.Parent = Player.Character.Bin local KoThing = Player.Stats.Aura.Value / 50 local tweenInfo = TweenInfo.new(0.8, Enum.EasingStyle.Quint, Enum.EasingDirection.Out, 0, false, 0) local tweenProp = {Size = Ko.Size + Vector3.new(1.4 + KoThing,1.4+ KoThing,1.4+ KoThing);} local tweenCreation = tweenService:Create(Ko, tweenInfo, tweenProp) tweenCreation:Play() end end)
Maybe it is because the RemoteEvents are stored in ReplicatedStorage in a folder?
Sorry if this seems like a dumb question, this is my first time setting up a game like this.
Thank you for reading
I think this is happening because you're a bit confused on how events work. I'm assuming that you think that because you (presumably) put the server script that handles the KOdown event under a player's character only they will be able to fire it. This is wrong. RemoteEvents are not per player! They are fired globally, regardless of who fired them or where they are being handled, which is what makes them so powerful. It's kind of like touch ID on an Iphone: anyone is able to push the button, but it's the phone's job to take their fingerprint and determine if they should actually be able to unlock the phone.
For example, take these three pieces of code:
Server Script (Located anywhere - even in a character) :
local event = workspace.RemoteEvent event.OnServerEvent:Connect(function(plr, input) print(plr.Name.. input) end)
Player1 Script:
local event = workspace.RemoteEvent event:FireServer("I'm player 1!")
Player2 Script:
local event = workspace.RemoteEvent wait(1) event:FireServer("I'm Player 2!")
In this case, the output will simply be
I'm player 1! I'm player 2!
regardless of the location of the server and client scripts. The point is, anyone can fire a remote event. It is the responsibility of your server script to decide who gets to actually run the code behind it!
If I only wanted say, player 1 to be able to print their message, I would need to modify the server script to this
local event = workspace.RemoteEvent event.OnServerEvent:Connect(function(plr, input) if plr.Name == player1 then print(plr.Name.. input) end end)
You don't have a check like this, which is why anyone can run the server code. Anyone can fire the KODown event once it is unlocked because you have no check to make sure that only the correct players can. The reason it isn't being fired before anyone unlocks it is that the code only gets bound to the event once the script gets placed into someone's character.
TLDR: Anybody can fire code behind a remoteevent once it is connected/bound to the event regardless of where any of the scripts are located. To fix this, add a check using an "if" statement that only allows certain players to actually run the code in the remoteevent.