Does anyone mind explaining how this script works?

Does anyone mind explaining how this script below works? It’s supposed to give character sparkles, (I got this script from wiki) I don’t understand how it all sort of connects to each other. When a player joins, idk which part of the script goes first and it just all seems confusing to me. I’m guessing the very bottom line is first, then onPlayerAdded but how does the for i, player line work and connects to the onPlayerAdded it’s all confusing to me so if anyone can give me like a step by step process on how this works it would solve my problem cuz i cant figure it out myself

local Players = game:GetService("Players")
 
local function onCharacterAdded(character)
	if not character:FindFirstChild("Sparkles") then
		local sparkles = Instance.new("Sparkles")
		sparkles.Parent = character:WaitForChild("Head")
	end
end
 
local function onPlayerAdded(player)
	if player.Character then
		onCharacterAdded(player.Character)
	end
	player.CharacterAdded:Connect(onCharacterAdded)
end

for i, player in pairs(Players:GetPlayers()) do
	onPlayerAdded(player)
end

Players.PlayerAdded:Connect(onPlayerAdded)
2 Likes

So when the players joins a event is called “Players.PlayerAdded:Connect(onPlayerAdded)” which then calls the function onPlayerAdded. In the onPlayerAdded function it checks if the players character has loaded in, if so calls the function onCharacterAdded, and if not it binds the function to the characteraddedevent so it will run when the character loads in. All the onCharacterAdded does is check if the player already has sparkles on them, “if not character:FindFirstChild(“Sparkles”) then” and if they don’t it makes a new sparkles object “Instance.new(“Sparkles”)” and parents it to the characters head.

3 Likes

I’m mainly confused by the “for i, player” part i don’t seem to understand how that even works that it passed a parameter to onPlayerAdded and yeah basically lol

2 Likes

05
Unless you are cloning the script in after the server has started this is useless

1 Like

Players:GetPlayers() returns an Array containing every Player in the server.
The for loop loops through that Array, naming the index i and the value player.
It then calls onPlayerAdded() with that player.

ty that narrows it down a bit lol

The for is in case there are already players in the game, because the PlayerAdded event does not count for players already in the game before it was declared.

2 Likes

If that doesn’t answer your question and you are asking what it actually does. lemme break it down.

‘I’ is the index, when using GetPlayers() or GetChildren() etc. this is primarily set to 1,2,3,4,5,6.
player is an object value for the player

Kinda standard for iterating through a table, no clue why its like that my best guess is because you are receiving ‘I’ and ‘player’ in pairs

This is very easy, this is just generating a simple table of all the players in the game.

This is just calling the PlayerAddedFunction and parsing the player as an argument so the function can modify it locally.

2 Likes
local function onPlayerAdded(player)
	if player.Character then
		onCharacterAdded(player.Character)
	end
	player.CharacterAdded:Connect(onCharacterAdded)
end

i dont understand the 5th lines purpose

If their Character already exists then it’ll fire call onCharacterAdded() since player.CharacterAdded would’ve already fired.

Then it connects CharacterAdded for any time they do spawn and call onCharacterAdded.

1 Like

pairs is standard for iterating through a dictionary. ipairs is standard for iterating through arrays (but is often ignored or not done due to lack of knowledge and/or the ugly performance from the old VM). GetPlayers returns an array. Use ipairs.

for key, value in pairs is a type of for loop - a generic for loop. The other type is a numeric for loop which uses for index = init, end, step. Reading material on for loops from the Lua PiL.

1 Like

Interesting, I always believed ipairs ignored nil values for some reason, however ive always just tended to avoid it.

It does, but so does pairs. If it’s nil, there’s nothing there, why would you need to iterate over it?

3 Likes

lets do it step by step:

This is getting the playersService(PlayersService is used when a player joins the game)

This is detecting when the players character(if you don’t know what character is, character is the person you see) is loaded. Local means that it only affects that ONE player, the word character inside the brackets is basically making the players character a variable(don’t worry if you don’t know what variables are, you’ll learn, it’s probably one of the most basic things on any scripting)

This will detect if the character has a child called, “Sparkles” as it’s child

This will make a sparkle

this will make the sparkles parent the head

the same thing as the last one, but when the player is loaded

detects if the player has a character

when the character is added, it makes the things in the brackets become one variable

if the character is added, then the variable from the last one could be references over the script

this is like a repeat, but it repeats exactly how much players there are

not sure

this is to end the script

Ok so you know that this script is adding sparkles to head, but how exactly is it being done?

The first thing I want you to get is how a function works, the code in your post contains two functions, and they are:

 
local function onCharacterAdded(character)
	if not character:FindFirstChild("Sparkles") then
		local sparkles = Instance.new("Sparkles")
		sparkles.Parent = character:WaitForChild("Head")
	end
end
 
local function onPlayerAdded(player)
	if player.Character then
		onCharacterAdded(player.Character)
	end
	player.CharacterAdded:Connect(onCharacterAdded)
end

So the code located with the functions onPlayerAdded and onCharacterAdded are only executed when we call that function. For example, in this line here:

for i, player in pairs(Players:GetPlayers()) do
	onPlayerAdded(player)--calling the onPlayerAdded function
end
--Also here:
Players.PlayerAdded:Connect(onPlayerAdded)
--[[

As you can see the onPlayerAdded function gets called each time a new player is added
You may be wondering how the player gets passed into the function, so the PlayerAdded
event is know as an script signal which is made by roblox, and when these
signals fires, some of them pass along data which is very useful. To find out about
these signals and the information they pass you must use the Devhub which contains
all the relevant info about each class and well all all of its various events(signals) and functions. Here is a link to the PlayerAdded event:

https://developer.roblox.com/en-us/api-reference/event/Players/PlayerAdded
]]--

To help you understand how this works Im going to show you another way in which this could
have been written:

game.Players.PlayerAdded:Connect(function(Player)
   print(Player.Name)
end)
--does the same thing as:
local function OnPlayerAdded(Player)
   print(Player.Name)
end
game.Players.PlayerAdded:Connect(OnPlayerAdded)
--so this line of code is just running the function each time a player is added

Ok so know lets explain each of the individual functions in greater detail:

local function onPlayerAdded(player)
       --[[
       ok so this function takes one argument 
       that represents the Player object,
       an argument refers to values
      that are declared or stated within the function header. 
       ]]--
	if player.Character then -- this line is checking if the player character is loaded in
       --if it is loaded in then we call the function
		onCharacterAdded(player.Character)
	end
   --[[
       if it is not loaded in then the script will wait until it loads 
       in before calling the onCharacter function,the CharacterAdded event
       is a signal of the Player class that fires when a player's character
       is added to the game. This must be done because
      some players may have a bad connection and thus there characters might take 
      sometime to load in. Also, on devhub it states that the CharacterAdded event
      passes as the character that is loaded in when the signal gets fired:
      here is a link to event:
      https://developer.roblox.com/en-us/api-reference/event/Player/CharacterAdded 
    --]]
	player.CharacterAdded:Connect(onCharacterAdded)
end

local function onCharacterAdded(character) 
     --this function takes a specific player's character as the argument
	if not character:FindFirstChild("Sparkles") then--this line is checking if the player does no have a child named Sparkles
    --if it does not we add the sparkles to the head
        local sparkles = Instance.new("Sparkles")
		sparkles.Parent = character:WaitForChild("Head")
	end
end

Ok so next lets go to the loop:

for i, player in pairs(Players:GetPlayers()) do
	onPlayerAdded(player)
end
--[[
This loop is basically going over all the players in the game
and calling the function OnPlayerAdded on each player so that
every player in game can get Sparkles added to their heads.

I think the reason we have to do this is because sometimes when
new servers are made players join before all the code gets executed, however I'm not sure
but this just ensures that the script gets every player.
]]--

Lastly and example of how this works when a new player joins:

  1. Player A joins, as such the PlayerAdded event in fired by roblox and this line will basically
    get fired:
game.Players.PlayerAdded:Connect(OnPlayerAdded)
  1. The OnPlayerAdded function will run

  2. The OnCharacterAdded function will fun and sparkles will get added to the player

2 Likes