Tutorial:Intermediate guide to scripting

Welcome to Intermediate scripting! If you have not already, please check out the Beginner guide to scripting. This scripting tutorial will teach you about how to script at an intermediate level, firstly, as of course there are with all other scripting tutorials, there are -well- more than a few concepts you must have learned first - events, methods, tables, loops, "if" statements, "else" statements, and "elseif" statements.

Just a Quick Review
Here are some concepts you should know beforehand:


 * Variables: placeholders for data
 * Booleans: true/false statements
 * String Values: text values
 * Properties: attributes of an object
 * Functions: placeholders for code
 * Parent: The object directly above another object in the Explorer window
 * Child: The object directly below another object in the Explorer window

You should have Roblox Studio open for this, and you should also have a script open as well as your Explorer, Properties, and Output open.

If Statements
An if statement would run a piece of code if a condition is met. For example:

You can see that I am declaring a variable. Then, the script will come across the if statement. The script finds that Var is 1, so the condition is met, therefore it would print "condition met." Don't forget the end tags! Note that in an if statement == must be used. == is for comparing values and = is for declaring variables.

Relational Operators
If you aren't already familiar with relational operators, a relational operator is an operator that compares two numbers. As such, they can only be used on floats and int values. Here they are:


 * == (Equal to)
 * ~=(Not equal to)
 * < (Less than)
 * > (Greater than)
 * <= (Less than or equal to)
 * >= (Greater than or equal to)

So for example, some statements would be:

$$4<5$$

$$1=1$$

$$49>38$$

For reference, if you are confusing the greater than (>) and less than (<) symbols, I like to think of these symbols as an alligator mouth that "eats" the greater number.

Arithmetic Operators
If you have any knowledge of mathematics, you should know that numbers can be changed with operators. These are:


 * + (Add)
 * - (Subtract)
 * * (Multiply)
 * / (Divide)
 * % (Modulus)
 * ^ (Exponents)

So...

$$3+6=9$$

$$18*59=1062$$

$$89+21>102$$

If you are unclear with the last two operators, modulus returns the remainder when the two numbers are divided. So for example,

$$7/2=3.5$$

$$7%2=1$$

Because 7 is not perfectly divisible by 2, it leaves a remainder of 1. Therefore, 7 mod 2 is 1.

Exponents are just repeated multiplication.

$$5^3=5*5*5=125$$

So, 5^3 is just 5 multiplied by itself 3 times.

To perform an operation on a value, you must do an arithmetic operation with the value, as this example shows:

For added simplicity, these operations can be shortened, as this example shows:

Here is an example of an arithmetic operator that tests whether or not the player has enough money:

Here, it checks if the player owns $120 or more. If so, it would subtract it.

Logical Operators
A logical operator combines two operators together into one. These are:


 * and (checks if BOTH conditions are true)
 * or (checks if EITHER condition is true)
 * not (checks if the current state is the OPPOSITE of the condition)

The first if statement checks if the value is less than 30, but greater than 15. In other words, it checks if the value is between 15 and 30. The second if statement checks if the value is "cheese" or "pie", and the third checks if the value is not 12.

Truthy/Falsy Values
But what does this mean?

If there are no operators, the if statement checks if the value is truthy or falsy.

To be clear, a falsy value (also known as a falsey value), is a value that is either false or nil.

All other values are considered truthy values.

Most of the time, this is used to find if an instance exists. So, if I were to do this,

I will explain later on what FindFirstChild does later on, but basically, it finds the part named Head.

This script will check if its parent has a child named "Head". If it does, it prints.

Else, Elseif, and Nesting If Statements
You can also put one if statement inside another. This is called nesting an if statement.

The script will see that both conditions are met, so it prints. Remember, each, if statement needs its own end tag.

Placing else in the if statement will cause the script to run alternate code should the first condition not be met.

An elseif is basically just combining "else" with an if statement. If the first condition is not met, it will check if a second condition is met.

So, the system defines both variables, then has to decide whether Var1 is equal to 2. It is not, so it checks the other condition. It is met, so it prints out "condition 2 met." You can make if statements as crazy as you want, with as many elseifs and nested if statements as you want.

Service
A service is the anything of the highest hierarchal level in the Explorer window. Here they are:


 * Workspace: A service that holds all the parts and physical objects in the game.
 * Players: A service that manages all the players that enter the game.
 * Lighting: Manages the lighting effects, time of day, and the sun, moon and sky.
 * ReplicatedStorage: Service containing objects replicated to all clients
 * ServerScriptService: Service containing server scripts; scripts to be used for the whole game, ie: for leaderboards.
 * ServerStorage: Storage for objects to be used later.
 * StarterGui: Service containing ScreenGuis
 * StarterPack: Service containing tools
 * SoundService: Storage for audio
 * Chat: Manages chat
 * LocalizationService: Manages auto-translation

This is a lot to unpack, so focus on Workspace, as it is the most frequently used service, and the only one used in this tutorial. In the Advanced tutorial, we will start using StarterGui.

There are also two services you can manually add to the Explorer window: ReplicatedScriptService and Teams. To add them, open the View Tab > Command bar. Then, enter the following:

These services will then appear in your Explorer.

Of course, there are many other services hidden away from the Explorer window. To access them inside a script, you need to use the GetService function to get the service. For example:

Now, within the script, the service UserInputService will be contained inside the "UserInputService" variable.

Parameters
In the Beginners' tutorial, I explained what a function was: a placeholder for code. We can also allow a function to have an argument, or parameter (a value that needs to be entered in), for example:

When declaring a function, by putting a parameter in the brackets, the function then expects a value. Then, when you call the function, you then need to put a value in the brackets. In this case, the function expects a value for "stuff". When you call the function, by putting "Hello world!" in the brackets, you are defining "stuff" as the string "Hello world!" From there, you can use "stuff" as a variable inside the function.

Tuples
We can also do this:

The above script expects two parameters: stuff and morestuff. When calling the function, we define stuff as Hello and morestuff as world!.

You can have as many parameters as you want as long as you separate them with commas. When we use more than one argument, we call it a tuple.

Returning
Returning a value is a way for a function to output a value. A real-life example of this is Google returning results for your search.

Let's say I wanted to make a converter that would double the input number. Simply do this:

Here, the fourth line tells it to fire the function DoubleNumber. The function doubles 10 to make 20, and returns 20. This number is contained in the variable "Multiply." This variable can be used for the print statement in line 6.

Events
Events are basically special situations that can be programmed to cause a reaction. The most common one is Touched, that can be applied to Parts and Unions. Whenever something touches a part, it causes a function to be called.

Let's break this down.

"script.Parent" obviously refers to the part that was touched. Connect, as the name suggests, connects the event to the function. In other words, whenever the event occurs (when the part is touched by a part or player), the function fires.

Events also have built-in parameters. In the Touched event, its parameter is the person or thing that touched it.

In this case, you call the thing who touched the object "whotouched." So, when you trigger the event, it fires the function, and the function destroys the thing that triggered the event.

There are a plethora of other events, but for intermediate scripters, Touched will be the most important one.

Another way to fire an event is to do this:

This is a way to use less lines.

Instance
An instance is any object or property in the game. What if you want to create a script that creates a part? You COULD do this.

Here, I am creating a new instance. The first parameter,"Part" is the class name of the instance, or what type of object it is. So, I am creating a part. It also has a second parameter, for its parent.

However, this is a common bad practice. It's never a good idea to use the Parent parameter. This only makes the function slower.

Instead, define the parent in the next line.

What if we want to set properties? Simple. After the above code, type this:

The system already knows what Brick means. Just set the properties.

Built-In Functions
These are the functions that are set in the game, and no custom function can be declared with the name.

Destroy
This function effectively sets the object's parent to nil, removing it from the game. For example:

Clone
Makes a duplicate of the part, with all of the same properties, except the parent. You still need to define it in the next line.

ClearAllChildren
Destroys all of the object's children. As an example, if you were to use this on workspace, it would delete everything in the workspace.

FindFirstChild
If you are unsure of whether or not a variable or Instance exists, FindFirstChild will access the object if it exists; if not, then the script will still run, while if you simply try to access a nil value, the script would break.

To run code only if something exists, use an if statement to only run the code if the object in the FindFirstChild does not equal nil.

WaitForChild
Similar to FindFirstChild, but instead of returning a nil value if the object doesn't exist, it would yield, or wait.

Here, the script will wait for an instance named "Part", and will never continue on UNTIL it exists.

Wait
Delays a code a set number of seconds. Set the time in seconds as the parameter. If there is no parameter, by default it will wait 1 second. This also waits if there's no number in between the parenthesis, although for an extremely short period of time.

Tables
Tables, also known as arrays, are a type of variable in Lua that can be used to store multiple pieces of data in the same variable, for example:

Now you need to know that there are two main values of a table: i and v. i, or Index Position, is the position of the value in the table. In the above table, because "a" is the first number, its i value is 1. "b" is the 2nd value, so its i value is 2, and the i value of c is 3. v, or Value, is the piece of data itself.

So, if you want to find the v value given the i value, you would have to do this.

What this basically does is tells our script to access the second value in the table a. Now, say we wanted to print the last 2 values out of the following table: What we would do is this:

We can also assign values to individual spaces within a table:

This would print the text lol in our output, because the value of the second space in the table "a" was changed to "lol".

Loops
A loop is basically a chunk of code that executes repeatedly. Note that regardless of what type of loop you use, you MUST use a wait function (delay). This is because the system will run the code so infinitely fast that without a delay, the server will crash and stop responding.

While Loops
The most simple loop is a "while" loop, that basically acts like this:

Basically what this does is the script continually checks if a is still true every .1 seconds, and if a is still true then the code within the loop will execute again.

If you wanted a while loop to keep executing code unconditionally, you would do this:

For Loops
A second, more complicated loop is the "for" loop, which can repeat a set number of times, for example:

Basically what this does is it makes the script count from 1 to 6, executing the code each time. So, "Hello mom!" would be printed 6 times.

If you want to get fancy...

Adding the third part causes our for loop to count in 2's meaning our script will count from 2 to 6 in 2's, and run every time you can add 2 to 2 before it becomes 6.

We can also print i:

What this basically makes our script do is count from 1 to 6 and every single time it counts up 1, it prints whatever value it is at.

In Pairs Loops
This loop will require an understanding of tables, which you should have learned about above.

An in pairs loop is a loop that involves the values in a table.

What GetChildren does is that it returns an array containing all instance values inside each folder. Then, I renamed i to index and v to Part. Then, I told the script what table I wanted to use after "in pairs." Then, between half-second intervals, the script would count the number of parts as it destroys each part one by one.

What Does 'local' Mean?
In the Beginners' Tutorial, I mentioned that variables should have 'local' in front of it. Now that you've learned some important skills, I can explain what it means. To understand this, you need to understand blocks. You will notice that I asked that you indented code in if statements, functions and loops. The entire code is a block of code within itself, and any code inside loops, functions, and if statements are another block. You can see with the image on the right that there are four levels of blocks in that script.

So what does 'local' mean? Well, it means that the variable can only be accessed within that block. This keyword is similar to JavaScript. So if I were to use the following code:

The script would error, because the print statement is trying to access a variable that can only be accessed within the if statement.

You can see that on the second line, I have not given a value to var, therefore it is automatically set to nil. Then, the if statement will cause var to equal 1. It is no longer 'local' because the if statement is simply updating an already-existing variable.

Multi-Purpose Killing/Healing Brick (Difficulty: Medium-Hard)
Great! Now that we have our concepts down, let's get cracking. Say, we wanted a brick that removed Shedletsky's head whenever he stepped on it, but it would heal other players when they stepped on it. So, create a script and put it inside a brick using the explorer - Next, let's create our function that will be called by the Touched event and our value that will be assigned by the Touched event (to check if it's actually Shedletsky, of course!):

Great! We have the function touch with the argument shedletskycheck. Now we have to state what our function does. We want our function to first check for Shedletsky:

The script now checks for if whatever touched the brick's parent's name was Shedletsky. Now we must create a path leading from the touching brick to Shedletsky's head:

Now, let's say that something that WASN'T Shedletsky touched the brick. According to our script description, we must check if whatever that touched the brick that wasn't Shedletsky was even a player, then we must heal it. As such, we must find if the touching part's parent had a Humanoid in it. To do this, we must use a ;findFirstChild method (If you don't know what this is, see Beginner guide to scripting.)

Using the elseif statement, if the conditions for the previous "if" (Which is whoever touched the brick being Shedletsky") are not met, then the elseif statement checks the following condition (in this case, if the brick's parent actually even had a Humanoid in it, indicating whether or not whatever touched the brick was even a player), and then we ran a :findFirstChild method on the touching part's parent, and if it found a Humanoid in the touching part's parent, it returns ~= nil, however if it did not find one, it returns nil.

Now, we need to heal them:

This basically sets the value of their health to their maxhealth, effectively healing them to full capacity. Hooray! We almost have our script. Now all we have to do is add one "end" for every "function" and "if" we have, excluding "elseif"s.

We have one function and one if, excluding the "if" in "elseif", so we added two ends.

Lastly, we need to add the connection:

Hooray! Now if we run our script in Play Solo, if you rename a character Shedletsky, when it touches the brick, its head should be removed! However, if you damage yourself and you touch the brick, you should be healed back up to full health!

Extension: Extended Healing Effect
Now let's say that we didn't want our brick to heal other players up instantly, but instead it would heal them in 20's every 5 seconds 5 times. You guessed it: We're using "for" loops.

So we replaced the initial healing code with a "for" loop that counts from 1 to 5 (from 1 to 5 times), next we must add the healing code to make the Humanoid gain 20 extra health (I used a variable to define the humanoid in this case to shorten the code, however it's not necessary) and add the wait method that makes the script wait 5 seconds before adding more health:

So we added a wait statement that makes the script wait 5 seconds, then it - of course - found the Humanoid, and set its value to its original value plus 20. (A Variable's value is non-constant, it is whatever it was when its value was set. The variable does not continually update itself. Hence:

Would actually display 1, since at the time b was set to a, a was 1, however later on a was changed to 2, but since variables are non-constant, b remained 1.)

Now, lastly, we must end the loop with an "end":

If you did this correctly, when you step on the scripted block in Play Solo, if you're damaged, you should slowly be gaining Health (unless your name is Shedletsky.)

Extension: Disappearance Effect
Now, let's say we wanted our script to continually increase the transparency of Shedletsky's head every .1 second, and when his head's transparency reaches 1, ONLY THEN the script will remove Shedletsky's head. We're going to be using some more "for" loops. (I used a variable to define shedletsky's head's transparency, but you don't have to)

So we replaced the basic transparency setting code with a "for" loop that counted from 1 to 10 and defined shedletsky's head's transparency as the variable trans. Now, we must add the part where his transparency is increased:

So now this will increase the head's transparency by .1 10 times (a transparency value of 1 causes a brick to be fully invisible). Now we have to add the statement that makes the script wait .1 seconds between transparency increases:

Lastly, we add the end statement:

And the part that removes Shedletsky's head:

So now, when you run the script in Play Solo, if you name yourself Shedletsky, when you step on the brick your head should gradually disappear until you die.

Player Recording
So let's say at this point you wanted to record all the non-Shedletsky players that will step on this brick, for this we must use a table:

We've created a table with the content "one". This will help later on. Next, get the max number of our table by using the table.maxn method, which returns the highest space in the table:

Now, we must have our table insert the names of the recorded players using the table.insert method - table.insert(table,location,value):

What this does is it gets the highest place in the table, subtracts it by one, and inserts the name value there. We do this to make sure that the table will add in a new name in a new space. Now, let's make it print the entire table when it's touched using two methods: the tostring method and the table.concat method. The table.concat method basically takes all the values in a table and squishes them together. The tostring method converts any value (such as a table value) to a string value.

The VIP Door (Difficulty: Medium)
Now let's say you wanted a brick that only allows a certain person to pass through it but kills all others. Create a brick, firstly. Put a script in the brick, next, open its source. Firstly, we must create a function to be called by the Touched event and the value that will be defined by the Touched event:

So we have a function onTouch and an argument "vip". Next, we create an "if" statement to check if whatever touched the brick was a player named "Bob":

Our script now checks if the name of the parent of whatever touched the brick was Bob. Next, since we want our script to allow Bob to pass through, we set the value of the brick's cancollide to "false" for 1 second. The CanCollide property is the property that causes a brick to be solid.

Our script now, when touched by Bob, sets the brick's CanCollide to false, allowing Bob to pass through, and after 1 second - wait(1), it sets the brick's CanCollide to true, not letting others pass through. Now, we want Bob to know when the door is open, so we'll make the brick semitransparent while the brick's CanCollide is false:

Our script now, when touched by Bob, not only changes the value of the brick's CanCollide, but also makes it semitransparent so Bob knows when the door is open. After 1 second - wait(1), at the same time the CanCollide is set to true, the transparency is set to 0 so that Bob knows when the door is closed. Next, we add the part that checks if (hypothetically speaking) whatever that touched the block that WASN'T Bob was even a player.

So if the conditions for the first "if" statement (the toucher being Bob) aren't met, then it performs an additional check that indicates whether the toucher was even a player. Now, the fun part: Killing the player.

So our statement will now set the found Humanoid's health to zero. Lastly, let's close our "function" and or "if" (excluding our "elseif")

And lastly, let's create the connection statement (which makes everything happen:)

Congratulations! If your script worked, anyone named "Bob" should be able to pass through the door, but anyone that isn't Bob will be killed by the door! You can change "Bob" to the name of your liking once you're ready to implement this into your place!

That's it for the intermediate guide! Go to the advanced scripting guide to continue.