Edit: This tutorial is old and outdated. The new one is
here.
Yes, I made another tutorial - This one is by far the best of the previous ones I created however
Note: This tutorial was made for BullyMods.net and I'm too much of a lazy asshole to add new BB code
Welcome to Bully modding! Whether your new to modding, or just want some review this tutorial should be great for you! This tutorial will help you get started script modding.
Table of Contents:- 1: Intro/Concepts
- 2: Example
- 3: Example Explained
- 4: Variables
- 5: Algebra
- 6: Functions
- 7: Condition/Boolean
- 8: Control Flow
- 9: Ending
1 - IntroductionBefore jumping straight in, you'll need to know a few basic concepts that apply to all programming/scripting languages. Code is all executed in the order it appears, and will do exactly what you tell the program, in order from top to bottom. In LUA, you separate each statement with a linebreak. In some languages, your also required to add a semicolon to the end, this is optional, but a linebreak is required. In LUA (and a lot of other languages) the code will start in a function called 'main' (Functions will be covered later) and will start reading code from there.
Our LUA code will not be read by Bully directly as we right it. We will need to compile it. Compiling code transforms it from code that we can read, into code that our computer can read and run. We'll do this using a compiler.
It will be a lot easier to understand all these concepts if we look at an example, but first we will need to download a few tools.
LUA Editor: This can be any text editor, notepad,
notepad++ (my preference, it color codes code) or SWEGTA's
Ultimate Pasta (this will make creating code very easy and will require minimum knowledge of LUA, so this isn't suggested as it actually does most the work for you, if you use this anyway the tutorial here should still help you understand what is actually going on)
LUA Compiler: This is a command-line only tool, but should still be pretty easy for you after this tutorial.
DownloadIMG Editor: This will be essential for editing the archives that include the scripts so you can put your script in the game. There are 2 versions, each have their own tutorial and are fairly easy to use. One has a GUI, the other is a prompt, but has it's own shell. The first link is suggested for simplicity, but if your more skilled and need the best performance go for the 2nd one.
Ver. 1 -
Ver. 22 - Example ScriptIn this section, the goal will be to setup a basic script, run it, and then explain everything that we had done after it successfully runs.
First, copy the following code into your text/lua editor.
MissionSetup = function() --1
AreaTransitionXYZ(0,270,-110,6) --2
PlayerSetHealth(200) --3
PedSetWeapon(gPlayer,305,50) -- spud gun --4
end --5
--6
MissionCleanup = function() --7
end --8
--9
function main() --10
repeat --11
Wait(0) --12
until not Alive --13
end --14
Note: Any text after '--' is a comment, it is ignored and is not considered part of the code. In this example it was used to show line numbers to easily refer to them when we are explaining the example.
Then save the file with the file extension .lua (File extension is the stuff after the '.', it is usually 3 letters. EX: MyScript.lua)
Now you have a LUA script saved that will warp the player outside the dorm, give him 200 (max) health, and give him a spud gun. Now we need to compile it so it will actually be understood by Bully.
There are a few ways of compiling, but since there will be a larger section on compiling later on we will use the simplest one for now. Drag your saved LUA script over 'LuaC.exe' and it should produce a file called "LUAC.OUT" or something along those lines. Change the name to "ArcRace1.lur"
(Common Error: "Side by Side config is wrong" (or something like that) means that you do not have Visual Studio installed. Visual Studio is required for reasons discussed later on)
Now we have a compiled LUA script, your almost done!
Lastly, we'll need to put it into your Scripts archive. Using your IMG Editor, open Scripts.img (This is located in the 'Scripts' folder located in your Bully directory) and locate the file called "ArcRace1.lur" and delete it. We will be putting our custom ArcRace1.lur that we have compiled in there to replace it. Now when that script is activated, it will run our code instead of the code Rockstar had it run before. The IMG editor will NOT automatically delete it if you add another one inside the IMG archive, so be sure to delete the original first! Now that it is deleted, you guessed it, add the one we created. Now close the IMG editor and start the game.
We replaced "ArcRace1.lur", a script activated when the arcade machine is played in the Boy's Dorm. So to see our code take effect go and play the arcade machine in the boy's dorm. If the mod does not show up in-game at this point, you did something wrong and should figure it out before you continue.
3 - Example ExplainedWe will now go line-by-line discussing each line of code in the previous example. There are comments (text after --) that show the line number of each line so we can easily address each line of code. Remember, comments do not effect the performance of code at all.
1: This is a function declaration. It states the name of a function, (MissionSetup) and to make it read as a function we add " = function()". Everything in between the function declaration and the 'end' code is part of the function code.
2: This is a function call. A function call will run all the code contained in a function from the top of the function to the end of the function, then the code will return to executing/running right after the function call. In this case, we called the function "AreaTransitionXYZ" and supplied it with 4 parameters, (areacode,x coord,y coord,z coord). This will be explained in further detail in the function section of the tutorial. This function was not declared by us (the modders) as it is a function made by Rockstar in Bully. We can not see the source code of it at the moment, but modders do know a fair amount of functions and what they do.
3: This is also a function call, similar to the previous line.
4: Another function call...
5: This ends the function "MissionSetup"
6: Blank line, this does not effect the code in anyway, blank lines can be used to make the code simply look more appealing. Also the indents (2 spaces) by some code is also just for visual appeal. It is not required.
7: This is a function declaration of "MissionCleanup". The function does not have any code in it, so the 'end' code is immediately after it.
8: End of "MissionCleanup"
9: Blank line... already explained
10: This declares the main function. This is required for the code to run. It was previously said that when a script is launched, it starts at the main function. This is for the most part true, but actually for ArcRace1 (The script we are modding) or any other mission script, the first function called is MissionSetup, then it will go to main. When the main function is done the MissionCleanup function is called. Notice it is declared in a different way then the other 2 functions. This does not change the code's outcome, it is your choice to do "function <name>()" or "<name> = function()". They will have the same effect.
11: This is a repeat loop, it will repeatedly run the code between 'repeat' and 'until' until the condition after 'until' is met.
12: This is a function call to make the script wait for 0 milliseconds before it continues to execute. It does not make sense why we would need to make it wait for 0 ms, but if you try to create a repeat loop without a Wait function call (It can be any time, does not need to be 0ms) it will crash the script.
13: Continue to repeat the code until "not Alive". This will be further explained later.
14: End of the main function.
Some of the things explained above may still not make 100% sense. This is OK as long as you somewhat get it. Everything will be explained in the next few sections.
4- VariablesVariables are very useful. By now, you should know a little bit of how functions work. Not fully but enough to understand this: If we put PlayerSetHealth(200) in our code, the player will have 200 health. If we put PlayerSetHealth(164) he would have 164 health. This will be used to demonstrate how variables work. Look at this example... there are comments to explain the code. (Note: This won't do anything that you can see if you were to compile it. It is only for an example and no text is printed nor does it do anything noticeable besides change the players health a little bit. Also it contains an error for showing how NOT to do this)
function otherFunction() -- a function named "otherFunction"
PlayerSetHealth(cheese) -- cheese was a variable that equaled 170
PlayerSetHealth(170) -- the same effect as above, since cheese equals 170
PlayerSetHealth(donut) -- ERROR: donut was a local variable, local variables are only used in their own function
end -- the end of the function, when this is reached the code will continue to run from where this function was called.
function main() -- main function (code starts execution here)
PlayerSetHealth(200) -- Give the player 200 health
PlayerSetHealth(cheese) -- ERROR: this variable was not declared yet.
local donut = 140 -- a local variable named 'donut' that equals 140
cheese = 170 -- a global (not local) variable named 'cheese' that equals 170
otherFunction() -- call "otherFunction" (the code will execute all code in "otherFunction")
end
The comments should of explained a lot, but there is still a lot that you probably need cleared up. A variable is something that can be changed at anytime in the code, and can equal many things. A number (as it is here), a string of text, or a boolean value (true/false)
In this example, there are 2 variables. A local variable named "donut" and a global variable named "cheese". Since "donut" is local, it can ONLY be used in the function it was declared (created) in. Since "cheese" is global it can be used anywhere. (I personally usually use global variables as it is faster since you don't need to type 'local' plus it avoids confusion, but local variables still have their uses)
A variable can only be used AFTER it is declared (created). If it is used before it will mess up (This is shown in the example)
With variables, their value can be changed easily by doing the same way as declaring it. HOWEVER: If it is local, you do not specify 'local' again when changing it. Here is an example. (Cannot be ran, just like last one)
local x = 50 -- variable 'x' equals 50
x = 47 -- now it equals 47. NOT 50.
PlayerSetHealth(x) -- set health to 47
PlayerSetHealth(x + 5) -- set health to 52 (47 + 5)
x = 45 + 4 -- x equals 49
Simple enough right? This also showed math can be done on variables.
Also side-tip, a lot of modders call all variables 'locals' even when they are not local. I am not sure why, but if you hear 'locals' it often refers to 'variables'
Now what about those other data types?
String example:
cheese = "This is a variable named \"cheese\" and it is a string of text"
In the example, a variable named 'cheese' is declared and equals This is a variable named "cheese" and it is a string of text.
When declaring a string variable, it equals the text in between "s. The \ (backslash) is used in the example to type a " without it thinking that was the end of the string. If we did not do that, it'd think that the string equaled "This is a variable named " since " ends it.
And lastly, boolean. This is very simple. It's either true or false.
x = true
x = false
This is a variable named 'x' that has boolean values.
Oh wait, there is actually kind of one more data type. 'nil'
nil is NOTHING. Not even zero. It is just nothing, I can't really think of a good example but, 'nil' is no data or memory.
Tip: Variables ARE case-sensitive
5- AlgebraThis section is pretty basic. LUA can handle math operations. 5 of them.
+ : Addition.
- : Subtraction.
* : Multiplication
/ : Division
() : Everything in parenthesis will be evaluated first
Examples with variables:
x = 45 + 4 -- x equals 49
y = x - 5 -- y equals 44
z = y*2 -- z equals 88
a = z/4 -- a equals 22
6- FunctionsYou probably already have a good idea of how functions work at this point, but everything will be more formally discussed here.
<name> = function()
or
function <name>()
will declare a function.
and 'end' will end it. Example:
function cheese() -- start of "cheese"
end -- end of "cheese"
To call a function, you put it's name and "()"
EX: cheese()
When a function is called it will go to the start of a function, execute all the code, then when it reaches 'end' will return to where it was called.
A lot of functions for Bully are pre-made by Rockstar. EX: PlayerSetHealth(num)
You probably already knew everything above as review, but the following 2 topic are likely new to you.
Returning a value:
A function can optionally return a value. When a function returns a value. Example below:
getNum = function() -- getNum function
return 42 -- return the value 42
end
function main()
x = getNum() -- x equals 42 since the function "getNum" returns 42
end
Parameters:
A function can also optionally accept parameters, values passed into it. For example, in PlayerSetHealth(42) '42' is the parameter. Here is an example of how you can write and use parameters:
function cheese(x,y) -- the variables x and y are assigned values when the function is called. these are parameters
return (x*y) + 2 -- return 2 plus the product of x and y
end
function main()
a = 42
b = 7
x = cheese(a,b) -- x equals 296 (2 plus the product of a multiplied by y)
end
When a function with parameters is called, it needs to have the values of it's parameters in the () and separated by commas. In the example, the values of a and b (42 and 7) was passed into the function "cheese". "cheese" has parameters named x and y. Since the values 42 and 7 were passed in the function, x equals 42 and y equals 7 while the function runs. The function will run and return 42*7 + 2.
Functions can also return strings or boolean values.
7- Boolean ConditionsConditions will return a boolean value (true or false)
Conditions are needed for control flow statements (discussed in next section) and was also used in the repeat loop in section 2's example.
Let's first briefly explain the 'if' statement. This is it's syntax:
if <condition> then
-- code
end
the comment "code" is where you could put other code. The code there is only run if the condition is true. For example:
if true then
-- this code will run
end
if false then
-- this code will NOT run
end
But you do not only have to put true or false, you can also put conditions that will return a boolean value (true or false)
There are 6 condition operators.
> greater than
< less than
>= greater than or equal to
<= less than or equal to
== equal to (be careful not to put just 1 equal sign, that is a common mistake)
~= not equal to
also there is an operator ~ that will invert the boolean (true will be false, and false will be true)
Examples:
if 5 > 4 then
-- this code is ran since 5 is indeed greater than 4
end
if 5 < 3
-- this code will NOT run since (5 < 3) returns false as it is not true
end
if ~true then
-- NOT run, since ~ inverts true and makes it false (if it were ~false it WOULD run since it would then be true)
end
Lastly, there are 2 things called 'or' and 'and' which are pretty self explanitory.
Example:
if 5 > 4 and 4 == 5 then
-- code is not run since they are not both true
end
if 5 > 4 or 4 == 5 then
-- code is run since at least of them were true
end
8 - Control FlowNow we have control flow, you have already learned the 'if' statement. This is more things like that.
if:
if <condition> then
-- code will run if the condition returns true
end
else:
if <condition> then
-- code will run if the condition returns true
else
-- code will run instead if the condition was false
end
elseif:
if <condition> then
-- code will run if the condition returns true
elseif <condition> then
-- code will run if the original condition was false AND this new condition is true
elseif <condition> then
-- if both of the above 2 were false, and this 1 is true, this one will run
end
Those are the things related to 'if'
Now we have loops...
while <condition> do
--run this code if the condition is true, and until it is false
--somewhere in this loop the condition should be made false or it will never stop
end
do
-- code
while <condition> -- this type of loop is useful it you want it to run at least once
-- it will check the condition after running it at least once. then it will check it if was true, and run again if it is.
repeat
-- code here
until <condition>
-- fairly similar to the do-while loop. except it will run until the condition is TRUE instead of false.
Also there is something called "break"
When the code reaches a "break" it will end the loop, and continue to run code right after the loop. Even if the condition still says it should run.
There is also a 'for' loop but I forget how it works on LUA. I will add to this tutorial later.
9 - EndingHopefully you have learned a lot of LUA. However, you have not been taught many of Bully functions, only how LUA works.
Here are a few links to help you keep learning more LUA related to Bully.
Bully uses LUA version 5.0.2. Here is the official LUA documentation for 5.0:
LUA 5.0 Docc00ld0c26 (a fellow modder) LUA tutorial that covers a lot of Bully's functions instead of just LUA:
TutorialI also plan to myself make a topic/tutorial with all the Bully functions (or a lot of them at least) and their parameters, and what they return.
It is also pretty good to be friends with the other Bully modders to be able to get help from them.
XFire:
www.xfire.comMost of the modders use xfire. Here are some of the best Bully modders you can add.
DaBOSS54320: me
tuffjtags: AKA Rise To Honor, he is a pretty good modder but doesn't play Bully frequently as he used to.
c00ld0c26: An active modder.
SWEGTA: Another cool modder.