Fandom

ROBLOX Wikia

Intermediate Guide to Scripting

12,577pages on
this wiki
Add New Page
Comments0 Share

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 - variables, functions, events, methods, tables, loops, "if" statements, "else" statements, and "elseif" statements.

Intermediate Scripting: Concepts

You should have ROBLOX Studio open for this, and you should also have a script open as well as your output open.

Variables

Variables (this term may seem familiar to you if you've learned algebra) are data spaces which you can assign certain values to - to assign a value to a variable, first state the variable, which we will say, in this case, is a. Of course, you could name a variable anything as long as you use the variable properly:

a

Now, in order to state we want to assign a value to a variable, use the equals sign:

a =

Lastly, let's say we want to assign the value 1 to a , so let's put 1 at the end of the equals sign. (As stated in the Newbie tutorials, if we want to assign a TEXT value to a variable, we must put the text at the end of the equals sign IN DOUBLE QUOTES.)

a = 1

Congratulations! Your script will now tell Lua to define a as 1! For an example of how to use a variable, if you've written the aforementioned script, then add this line to it:

print(a+a)

This basically tells our script to print into the output whatever a + a equals. Now, since a = 1, Lua will interpret a + a as 1+1, so in your output we should get 2 once we run the script.

Functions

Functions are essentially variables that store code instead of number or text values. Assigning code to a function is a little different from assigning values to variables, firstly, write this line in a script

function lol()

This tells us that we are defining a FUNCTION that is called lol. Next, add another line that tells the script to do something, which is, in this case, to print lol:

print("lol")

Now, in order to tell our script where the code we're assigning to our function is ending, we must write "end".

end

Now, we've created a function. Now to activate our function, all we have to do is this:

lol()

So now you should have

function lol()
   print("lol")
end
 
lol()

If you ran the script and wrote everything correctly, you should get the word "lol" in the output.

We can also allow a function to have an argument (a value that needs to be entered in), for example:

function write(stuff)
   print(stuff)
end
 
write("Hello world!")

Basically, we told our script to define "stuff" as whatever will be written in that space when the function is activated. In this case, I activated the function with the words "Hello world!" in that specific space, so the function defines "stuff" as "Hello world!", and then the code causes stuff, which is actually "Hello world!" to be printed, so you should get Hello world! inside your output once you run the script.

We can also do this:

function write(stuff, morestuff)
   print(stuff)
   print(morestuff)
end
 
write("Hello","world!")

Events

Events are basically special "fire" values that are built into the game, and basically whenever something happens in-game, if it coincides with an event, then that specific event is "fired" off, and any functions that are connected to it are activated, so as an example, put a script inside a brick using the explorer (to open, see TUTORIAL: The Disappearing Brick) and use this as the source:

function onTouch()
   print("i was touched D=")
end
 
script.Parent.Touched:connect(onTouch)

Basically what this last line does is it connects the brick's "Touched" event to the function onTouch. So when the brick is touched, its "Touched" event is fired, and because of the Touched event's connection to the function onTouch, the onTouch function is activated in turn. So once you touched this brick, the text i was touched D= should appear in the output.

Certain events also output certain values, in this case the Touched event, apart from having a basic "Fired" value, will also have a "WhoTouched" value. We can find this like so:

function onTouch(whotouched)
   whotouched:Destroy()
end
 
script.Parent.Touched:connect(onTouch)

Basically what this does is the Touched event will apply the whotouched value to the one within the function's parentheses, so that when the function is called, the whotouched value (which represents whatever part touched the brick) will be removed, so essentially, if the brick touches something/vice versa, that "something" will be deleted.

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

Methods

Methods are basically commands made by the ROBLOX Devs that are built into the ROBLOX game engine and can be called in a script to make scripters' lives easier, and the print command is one example of this. Other commands include clone, which is used like so (assuming there is a brick named Part in the workspace):

b = game.Workspace.Part:clone()
b.Parent = game.Workspace

Basically what this tells our script to do is to clone our part, and then put the part into the Workspace. Another command is Destroy, which is used like so (also assuming there is a part named Part in the workspace):

game.Workspace.Part:Destroy()

This, obviously, completely destroys the Part in the workspace, and prevents it from ever being used again without errors.

Tables

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

a = {f,i,g}

Now, in order to get the value i out of the table called "a", you must do this:

a[2]

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:

a = {"three thousand","nine hundred","and one"}

What we would do is this:

print(a[2])
print(a[3])

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

a[2] = "lol"
print(a[2])

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 until a certain condition is met. The most simple loop is a "while" loop, that basically acts like this:

a = true
while a = true do
wait(0.1)
print("I can swing my sword")
end

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.

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

for i = 2,6 do
wait(0.1)
print("Hello mom!")
end

Basically what this does is it makes the script count from 2 to 6, which makes the code between the for loop and the end run 4 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.

for i = 2,6,2 do
wait(0.1)
print("Hello dad!")
end

We can also print i:

for i = 1,6 do
wait(0.1)
print(i)
end

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.

Our next loop is the repeat loop, basically this loop repeats a certain line of code until a condition is met, for example:

a = 1
repeat a = a + 1 print("lol") until a == 10

What our script here does is add 1 to an until a is 10. Each time it adds 1, it prints "lol". The reason, as you may have noticed, this loop does not have to end with an end is because you instead close it with an until that will stop the loop on its own once certain conditions are met. Repeat loops are currently very buggy, it's not recommended to use them in scripting. The use of double equals is very important, using one equals sign tells our script to only assign values to a variable, however using double equals tells our script to check a value.

"if" Statements

"If" statements are statements that cause the script to check for a certain value. You must end "if" statements with an "end" to show where your activated code stops. For example:

if script.Name == "Bob" then
script:remove()
end

Basically what this does is tell our script to check if its name is Bob. If the script's name is Bob, then it will remove itself. If the script's name is NOT Bob, then it won't remove itself.

"else" Statements

"else" statements are statements that you can add to the end of an "if" statement - any code after an "else" statement before the "end" will be activated if the conditions in the "if" statement are not met. For example:

if script.Name == "Bob" then
print("My name is Bob.")
else
print("My name is not Bob.")
end

In this case, because of our else statement, if the script's name is NOT Bob, then the script does not simply do nothing. It will also print My name is not Bob in the output.

"elseif" Statements

"elseif" statements are statements that check for additional conditions if the ones in the "if" condition are not met:

if script.Name == "Bob" then
print("My name is Bob.")
elseif script.Name == "Duncan" then
print("My name is Duncan.")
end

Basically what the script does is it first checks if its name is Bob. If its name is Bob, it will print "My name is Bob." If its name is not Bob, it then checks if its name is Duncan. If its name is Duncan, then it will print "My name is Duncan." If its name is neither Duncan nor Bob, then it will not do anything.

END NOTE: EVERY "IF", "FUNCTION", AND LOOP (excluding repeat) IN YOUR SCRIPT MUST BE CLOSED BY AN "END". "ELSEIFS" DO NOT HAVE TO BE CLOSED.

Intermediate Scripting: Examples

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!):

function touch(shedletskycheck)

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:

function touch(shedletskycheck) 
if shedletskycheck.Parent.Name == "Shedletsky" then

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:

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
shedletskycheck.Parent.Head:remove()

--We navigated from shedletskycheck to its Parent, which is the Shedletsky model itself, then we found the Head within the Shedletsky model.

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 Beginners Guide to Scripting.)

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then

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:

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstchild("Humanoid") ~= nil then
shedletskycheck.Parent.Humanoid.Health = shedletsky.Parent.Humanoid.MaxHealth

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.

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
shedletskycheck.Parent.Humanoid.Health = shedletsky.Parent.Humanoid.MaxHealth
end
end

We have one function and one if, excluding the "if" in "elseif", so we added two ends. Lastly, we need to add the connection:

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
shedletskycheck.Parent.Humanoid.Health = shedletsky.Parent.Humanoid.MaxHealth
end
end
script.Parent.Touched:connect(touch)

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.

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
end
end
script.Parent.Touched:connect(touch)

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:

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
wait(5)
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
script.Parent.Touched:connect(touch)

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:

a = 1
b = a
wait(1)
a = 2
print(b)

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":

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
wait(5)
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
end 
script.Parent.Touched:connect(touch)

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)

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
end 
script.Parent.Touched:connect(touch)

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:

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
trans = trans + 0.1
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
end 
script.Parent.Touched:connect(touch)

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:

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
wait(0.1)
trans = trans + 0.1
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
end 
script.Parent.Touched:connect(touch)

Lastly, we add the end statement:

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
wait(0.1)
trans = trans + 0.1
end
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
end
script.Parent.Touched:connect(touch)

And the part that removes Shedletsky's head:

function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
wait(0.1)
trans = trans + 0.1
end
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
end
script.Parent.Touched:connect(touch)

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:

t = {one}
function touch(shedletskycheck)
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
wait(0.1)
trans = trans + 0.1
end
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
end
script.Parent.Touched:connect(touch)

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:

t = {one}
function touch(shedletskycheck)
maxn = table.maxn(t)
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
wait(0.1)
trans = trans + 0.1
end
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
end
end
script.Parent.Touched:connect(touch)

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

t = {one}
function touch(shedletskycheck)
maxn = table.maxn(t)
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
wait(0.1)
trans = trans + 0.1
end
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
table.insert(t,(maxn - 1),shedletskycheck.Parent.Name)
end
end
script.Parent.Touched:connect(touch)

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.

t = {one}
function touch(shedletskycheck)
maxn = table.maxn(t)
print(tostring(table.concat(t,' ')))
if shedletskycheck.Parent.Name == "Shedletsky" then
trans = shedletskycheck.Parent.Head.Transparency
for i = 1,10 do
wait(0.1)
trans = trans + 0.1
end
shedletskycheck.Parent.Head:remove()
elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
for i = 1,5 do
b = shedletskycheck.Parent:findFirstChild("Humanoid")
b.Health = b.Health + 20
end
table.insert(t,(maxn - 1),shedletskycheck.Parent.Name)
end
end
script.Parent.Touched:connect(touch)

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:

function onTouch(vip)

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":

function onTouch(vip)
if vip.Parent.Name == "Bob" then

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.

function onTouch(vip)
if vip.Parent.Name == "Bob" then
script.Parent.CanCollide = false
wait(1)
script.Parent.CanCollide = true

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:

function onTouch(vip)
if vip.Parent.Name == "Bob" then
script.Parent.Transparency = 0.5
script.Parent.CanCollide = false
wait(1)
script.Parent.Transparency = 0
script.Parent.CanCollide = true

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.

function onTouch(vip)
if vip.Parent.Name == "Bob" then
script.Parent.Transparency = 0.5
script.Parent.CanCollide = false
wait(1)
script.Parent.Transparency = 0
script.Parent.CanCollide = true
elseif vip.Parent:findFirstChild("Humanoid") ~= nil then

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.

function onTouch(vip)
if vip.Parent.Name == "Bob" then
script.Parent.Transparency = 0.5
script.Parent.CanCollide = false
wait(1)
script.Parent.Transparency = 0
script.Parent.CanCollide = true
elseif vip.Parent:findFirstChild("Humanoid") ~= nil then
vip.Parent.Humanoid.Health = 0

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")

function onTouch(vip)
if vip.Parent.Name == "Bob" then
script.Parent.Transparency = 0.5
script.Parent.CanCollide = false
wait(1)
script.Parent.Transparency = 0
script.Parent.CanCollide = true
elseif vip.Parent:findFirstChild("Humanoid") ~= nil then
vip.Parent.Humanoid.Health = 0
end
end

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

function onTouch(vip)
if vip.Parent.Name == "Bob" then
script.Parent.Transparency = 0.5
script.Parent.CanCollide = false
wait(1)
script.Parent.Transparency = 0
script.Parent.CanCollide = true
elseif vip.Parent:findFirstChild("Humanoid") ~= nil then
vip.Parent.Humanoid.Health = 0
end
end
script.Parent.Touched:connect(onTouch)

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!

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.