Scripting for Dummies

News will be posted here by the CoDJumper team

Moderator: Core Staff

User avatar
Drofder2004
Core Staff
Core Staff
Posts: 13313
Joined: April 13th, 2005, 8:22 pm
Location: UK, London

Scripting for Dummies

Post by Drofder2004 » September 22nd, 2006, 1:40 am

Ok, this is my own guide for scripting, it is incomplete and lacks a lot of formatting (I will try and get round to that soon). It was written in 2.5 hours and contains a lot of basic and slightly advanced guides on several base topics. Some areas contain more detail than others depending on relevance and difficulty.

When I get more time, I will add to this guide. Once I have pretty much finished the majority of the guide I will provide several new scripts using several advanced functions.

This guide should be used as a small starting guide for people new to scripting, and reference for those who know some scripting. This will provide an insight into how script can improve the fun of maps, and hopefully will help answer questions for those who are stuck.

If you find any problems (be it wrong syntax, spelling or etc) then post.
If you want to request/criticise/compliments or whatever, again post.

Enjoy.

Contents
1. Getting Started
2. Using Variables
3. Maths & Operators
4. IFs, Loops & Logic
5. Creating Functions
6. Arrays
7. Switch
8. Notfiy / Endon / Waittill
9. Stock Function List (Incomplete)

1. Getting Started
This section will include serveral things you need to know before you start scripting.
All scripts are contained within simple text files that contain no formatting, so programs such as Word are not to be used. The file format used for scripts within the Call of Duty series is 'GSC' (.gsc). It is recommended you use a simple but effective editor for programming, such programs include Crimson Editor, Programmers Notepad and Editplus.

A few things you need to know before reading any further are a few common words used within scripting.
Variables: variables are data storage locations which are assigned a name. For example...

Code: Select all

intVar = 1;
floatVar = 0.5;
strVar = "Text";
boolVar = true;
The vairables are declared on the left, and assigned a piece of data such as an integer (whole number),
float (a number containing a decimal), string (text) or a boolean (true/false).

Entity: this is something that is used in maps which can be called in the script. Entities include players, guns,
objectives, script_models, etc.
They can be called using their relative targetname or classname which is defined in the map.

Functions: an action or procedure that can be called or threaded and can return a value. For example...

Code: Select all

funcMove()
{
self moveY(320, 3);
}
The function in the above code is called "funcMove", when called, it will perform the actions inside the brackets.

Arguement: these are required pieces of data that needs to be sent when requested from functions.
For example, if a function is shown as

Code: Select all

function(arg1, arg2)
The function is asking for two arguements to be sent to the function. An example of this in use...

Code: Select all

{
ent function(320, 5);
}

function(dis, time)
{
ent moveZ(dis, time);
}
As you can see, 'dis' is called and is given the value of 320, this can then be used as a variable called 'dis', ditto for time.

Calling/Threading: these are used with functions. A function can be called or they can be threaded.
If a function is threaded, then the function is performed while the script continues, whereas if a function is called, the script will wait until the function is completed before it continues. Examples...

Code: Select all

function(); // This is how to call a function
thread function(); // This is how to thread a function
Self: this is used inside functions when a function is called on an entity. Self is used instead of an entity.
For example... (You will see in this example that in the function, called function(), self is equal to 'ent' which was
decalred in a different function)

Code: Select all

{
ent = getent("ent","targetname");
ent function();
}

function()
{
self moveZ(150, 5);
}

2. Using Variables
Variables can be used in several ways, but in all cases they are used to store some data for the duration of the round. Variables come in different style, integer, floats, strings and booleans, there are also several different ways variables can be stored.
A simple variable is simply declared using

Code: Select all

<variable> = <data>;
This variable can be used in the current function and any function that it is called to (using arguements, explained in section 1)

Variables can be global (which can be used in all threads without needing to be called) by using the

Code: Select all

level.<variable> = <data>
or they can be assigned to entities individually

Code: Select all

<entity>.<variable> = <data>

3. Maths & Operators

Maths is used throughout scripting to get several results, be it distance from two objects or simply to calculate a simple equation.
For example, a variable can be given data from an equation.

Code: Select all

<variable> = 5 + 1;
The above example is pretty pointless, as you could just calculate it yourself and use the answer i.e.

Code: Select all

<variable> = 6;
But variables can be calculated using other variables, for example...

Code: Select all

<varAnswer> = <var1> + <var2>;
varAnswer will be equal to the value of var1 plus the value of var2.

There are several operators that can be used in maths...
+ :: Addition
- :: Subtraction
* :: Multiplication
/ :: Division
% :: Modulus
= :: Equals

There are also some more unknown operators such as...
++ :: Increment (+1)
-- :: Decrement (-1)
+= :: Incrementation (requires number)
-= :: Decrementation (requires number)

Example of these in use...

Code: Select all

var++; // This is the same as var + 1
var--; // This the same as var - 1
var+=int; // This is the same as var + int (where int is a number)
var-=int; // This is the same as var - int (where int is a number)
4. IFs, Loops & Logic
This section is to go into a little more detail of how to use statements such as If and different loops.
An 'If' statement is used to compare data and decide what is done after the data is compared.
To go into detail in this section, It is required you know of 'Logic' and the operators used to compare data.
So...

== :: Equal To
!= :: Not Equal To
! :: Negation (Not)
< :: Less than
> :: Greater than
<= :: Less or Equal to
>= :: Greater or Equal to
&& :: And
|| :: Or

Ok, now we have some operators, lets get started on the 'If' statement.
An 'If' statement, requires a minimum of one arguement and usually one operator.
Here are some examples...

Code: Select all

If(variable) // If variable is true
If(!variable) // If variable is not true
If(variable1 == variable2) // If variable1 is equal to variable2
If(variable1 != variable2) // If variable1 is not equal to variable2
If(integer1 < integer2) // If integer1 is less than integer2
If(integer1 > integer2) // If integer1 is greater than integer2
If(integer1 <= integer2) // If integer1 is less than or equal to integer2
If(integer1 >= integer2) // If integer1 is greater or equal to integer2
If((var1 == var2) && (var3 != var4)) // If var1 is equal to var2 AND var3 is not equal to var4
If((int1 > int2) || (var1 == var2)) // If int1 is greater than int2 OR var1 is equal to var2
To use an If statement to determine the movement of the script, you need to use the arguements to move the script in certain directions...

Code: Select all

If(var1 == var2)
{
	// If statement is true, do this code
}
// more code here
If the statement above is true, the code inside the curly brackets is processed, if it is not true, the code inside the brackets are skipped.
Whether or not the statement is true, the code outside of the brackets is going to be processed. If this is not what you want,
you need to use "Else" after the statement, for example...

Code: Select all

If(var1 == var2)
{
	// If true
}
Else
{
	// If False
}
You can also use an "Else If" in the statement. This is used in a scenario where you want to check multiple comparisons.

Code: Select all

if(var1 == var2)
{
	// If above arguement is true
}
Else if(var1 == var3)
{
	// If first arguement is false, but second is true.
}
Else
{
	// If all arguements are false
}
Thats the basics of If's, so let move to Loops.

Loops come in different forms...

While :: A while loop is a loop that keeps looping WHILE the arguement is true.
For :: A for loop is a loop that loops a set amount of times

To use a while loop, an arguement is needed "while(arguement);"
Often, this loop is used for infinite loops. An infinite loop is a loop that loops forever.
This is done using the arguement of 1 or true (1 is the integer of true)

Code: Select all

while(1)
while(true)
A while loop can also be used as a normal loop that loops while the arguement is true,
when the arguement becomes false the loop exits automatically.

Code: Select all

int = 0;

while(int < 10)
{
wait 1;
int++;
}
The above code will loop while 'int' is less than 10. The loop waits 1 second, and then the loop increments 'int'.
Once 'int' is not less than 10, the loop breaks.

The same applies for FOR loops.
An FOR loop requires 3 arguements.

Code: Select all

for(declare;while;do)
Declare is the section which declares a variable for the loop to use.
While is what determines when the loop breaks
Do is what the loop should do after each loop.

A common FOR loop looks like this...

Code: Select all

for(i=0;i<int;i++)
The above code is read, "'i' is equal to 0, while 'i' is less than 'int', add 1 to i.
Lets use the code, and replace int...

Code: Select all

for(i=0;i<10;i++)
{
wait 1;
}
This is the sequence of events...
- 'i' = 0
- loop check "while" (if i is less than 10, continue)
- perform code (wait 1;)
- increment 'i' (i++)
- 'i' = 1
- etc.

The FOR loop can also be used as an "infinite loop" using the "forever loop"

Code: Select all

for(;;)
The above will simply keep repeating the code until manual stopped.

The problem with infinite loops is they give an error if you do not allow the loop to take a breath.
infinite loops require a wait statement. If you get an "Infinite Loop" error, this is the reason.

That is about the loops, but to finish off, we need to know how to manually exit these loops. A common way to exit
an infinite loop is to use an IF statement to determine when to 'break' (break is the keyword used to exit a loop)
here is an example of an IF statement exiting an infinite loop...

Code: Select all

for(;;)
{
wait 1;
if(var1 == var2)
{
	break;
}
}
The above sequence simply goes...
- Wait 1
- check if statement...
+ if var1 is equal to var2, exit loop
+ else continue
- loop

5. Creating Functions
A custom function is a good way to use repeat sections of code more efficiently. For example, if you often use
the same sequence of code, you can template them into a custom function. Imagine this is your code...

Code: Select all

wait 1;
brush1 moveZ(320, 5);
brush1 waittill("movedone");
wait 1;
brush2 moveZ(540, 3);
brush2 waittill("movedone");
This can be simplified using a custom function, lets call this function "_moveEnt" (it is common practice to use an underscore as the first character of a function)

Code: Select all

_moveEnt(ent, dist, time)
As the above shows, we are going to need 3 arguements, ent (entity), dist (distance) and time.
Now lets look at the full code with custom function in use...

Code: Select all

{
_moveEnt(brush1, 320, 5);
_moveEnt(brush2, 540, 3);
}

_moveEnt(ent, dist, time)
{
wait 1;
ent moveZ(dist, time);
ent waittill("movedone");
}
As the above code shows, the custom function can simply be called using the required arguements, each time
it is called, the details are changed in the custom function and are processed. Once they are finished,
it goes back to the main function.

Functions can also return values, for example performaing mathmatical equations.
A new function to get 3D area...

Code: Select all

{
area = _areaEquation(2, 4, 6);
}

_areaEquation(a, b, c)
{
answer = (a * b) * c;
return answer;
}
Once the code calls the function '_areaEquation' the function works out the 'answer', 'answer' is the returned.
This declares a new variable (area). The variable area, is the answer that is returned by the function.

6. Arrays

Arrays are "multivariables". You can store several pieces of data within a single array. This can be integers, strings or pieces of data such as targetnames and etc.
Arrays are the answwer to having to use multiple variables or in mapping, you can use a single targetname.

Arrays are the key to more efficient scripts and maps. If your map contains lots of entities which do the exact same thing (such as moving platforms) then you should be using an array to manipulate them.

To create an array we simply type...

Code: Select all

arrayName = [];
Now we have an array, we need to add to this array, this would be a pretty advanced process if the IW developers had not built a function for us. The function can be accessed using...

Code: Select all

maps\mp\_utility::add_to_array(array, ent);
So, for example, we have an array called "arrayName" and what we want to add is a string in a variable named "arrayString", put that into the above code...

Code: Select all

maps\mp\_utility::add_to_array(arrayName, arrayString);
Now, a couple of things to remember about arrays is their size.
Whenever you see, <ent>.size the .size does not mean dimension, but "how many". So if an array contains 1 piece of data, the array.size is 1.
Another thing is calling the array. A piece of data is called from an array using the array number...
So, if we go back to the example, we have just put arrayString inside arrayName, so our arrayName.size = 1. To get that information back we use

Code: Select all

arrayName[0]
This is where it gets a little confusing. Your array size is always 1 bigger than you array, this is because your array starts at 0.
If you had 10 pieces of data in the array, the size would be ten but you would only be able to call [0]-[9].

A common use for the array is to thread a function to all of the players on the server. This can be done using an array with a for loop.
So, first off we must get our array, and instead of using the above method of defining an array and adding custom data, we use a builtin command.

Code: Select all

players = getEntArray("player", "classname");
So, our array has been defined as "players" or more accurately "players[]"
Inside "players[]" is every player on the server, and now all we need to do is use the array to thread a function to each player.
So, here we have a for loop to do such a thing.

Code: Select all

for(i=0;i<players.size;i++)
Thats our loop, 'i=0' (do not change this number, it is important). While 'i' is LESS than 'players.size' (remember, the size is always 1 bigger than the final number in the array), 'i++'.

Code: Select all

{
   players[i] thread function();
}
And that above simply threads the function to each person in the array. Remember, 'i' is a variable not a letter, so 'i' is substitued with the number of the loop.
The first loop, 'i' equals 0, so

Code: Select all

players[0] thread function();
The second loop, 'i' equals 1 and etc.
If the amount of players on the server is 10 then loop will loop while 'i' is less than the size of the array (10). This means the 'i' will equal 0,1,2...,9.

Arrays are a complicated part of scripting, but once you have them understood, they are one of the most useful things.

7. Switch

Switch is often used when there are multiple limited outcomes for a single variable.
The Switch function can often be replaced by lots of "If" and "Else If" statements, but Switch is more efficient when the variable being checked has a limited amount of outcomes.

How to use "Switch".
Switch can be quite hard to understand at first glance, but after using it, it will become easier.

Here is an example of how it is used. This is taken from the menu scripts, which handles the ingame menus, I have cut the code and also added the commented lines myself.

Code: Select all

self waittill("menuresponse", menu, response);

switch(response)
{
case "changeweapon":
	self closeMenu();
	self closeInGameMenu();
	if(self.pers["team"] == "allies")
		self openMenu(game["menu_weapon_allies"]);
	else if(self.pers["team"] == "axis")
		self openMenu(game["menu_weapon_axis"]);
	break;	

case "changeteam":
	self closeMenu();
	self closeInGameMenu();
	self openMenu(game["menu_team"]);
	break;

case "muteplayer":
	self closeMenu();
	self closeInGameMenu();
	self openMenu(game["menu_muteplayer"]);
	break;

case "callvote":
	self closeMenu();
	self closeInGameMenu();
	self openMenu(game["menu_callvote"]);
	break;
	
//default:
	// Add default here
	// break;		
}
The first part of the code is where the variable is defined. The game waits until a menu has been activated. The variables recieved are "menu" (the name of the menu activated) and "response" (what option was chosen from the menu). "Response" is the key variable for the 'Switch'.

After the variables have been defined, the Switch function is called. It then checks every "Case" (case is the term used for the possible outcomes of the variable) to find a match, if no match is found, the "Default" case is used. (If you do not have a Default case, the script will continue passed the 'Switch' function).
If a match is found, then the function will do ALL the events from that point onwards, which is why you MUST add "break;" at the end of every case, if the break is not existent, then all other case functions will run also.

To use the above example, I shall input my own values to show how the example works...

When I open the menu ingame, I choose the option "changeteam".
The code kicks in and the variable "response" becomes equal to "changeteam".
The switch statement will now look at every case for a positive match.
Once the match is found, everything after the case will happen;
- self closeMenu(); (Current menu closes)
- self closeInGameMenu(); (Close any other ingame menus)
- self openMenu(game["menu_team"]); (Will open the team menu).
- break; (The rest of the switch statement is ended and the code continues.

8. Notify / Endon / Waittill

These 3 functions can be used to do many things, they are often used to "end" a script/function from running, they can be used to stop a script running until another part of the code is ready for it to continue and it can be used in simple debugging (although, not the only way).

The functions are often used mainly on a player or the level. I will provide an example of each.

Code: Select all

level endon ("thread_restart");
and from any gametype script.

Code: Select all

self notify("killed_player");
If you use "player waittill" or "player endon", then using a "level notify" will not trigger any of the 2.
To use the functions is very easy. First you decide on what you want the function to be called on. If the action is going to happen to a specific player, then use "player" (although, this will need to change depending on how the player is being called, i.e. self, other, user, etc) or if you want the function to work for the entire script, use level.
Then you must decide which function to use. You need to choose, either "endon" or "waittill", they are both self explanatory, one will end when called, and the other will 'wait'.
Next you decide on a unique 'call' for the function. For exmaple...

Code: Select all

level endon("a_unique_call");
Now. when you want the 'endon' function to happen, you will use the 'Notify' function...

Code: Select all

level notify("a_unique_call");
Anything with the unique call will be activated, so, multiple 'endon' and 'waittill' functions can be placed around your script.
Here is a quick example of it in use in multiple threads in the DM gametype...

Code: Select all

spawnPlayer()
{
	self endon("disconnect");
	self notify("spawned");
	self notify("end_respawn");
	
	/*... Code Snipped ...*/
	
	self notify("spawned_player");
}

Callback_PlayerKilled(?, ?, ?, ?, ?, ?, ?, ?, ?)
{
	self endon("spawned");
	self notify("killed_player");
	
	attacker notify("update_playerhud_score");
}

spawnSpectator(origin, angles)
{
	self notify("spawned");
	self notify("end_respawn");
}
All the threads depend on those notifies being called.
Here is a quick easy demonstration...

Code: Select all

waiting_thread()
{
	level waittill("stop_waitting", user);
	iprintln("This thread has stopped waitting, because " + user.name + " touched the trigger");
}

trigger()
{
	trigger waittill("trigger", user);
	level notify("stop_waitting", user);
}
Last edited by Drofder2004 on August 3rd, 2007, 7:10 am, edited 5 times in total.
Image
Virgin Media 20Mb Broadband:
"Perfect for families going online at the same time, downloading movies, online gaming and more."
Borked internet since: 22-07-2010

User avatar
Soviet
Core Staff
Core Staff
Posts: 7762
Joined: April 23rd, 2005, 9:12 pm

Post by Soviet » September 22nd, 2006, 1:52 am

wow, gj drof, this should help a lot of people

User avatar
Drofder2004
Core Staff
Core Staff
Posts: 13313
Joined: April 13th, 2005, 8:22 pm
Location: UK, London

Post by Drofder2004 » September 26th, 2006, 12:40 am

Added Arrays and also some formatting. :)
Image
Virgin Media 20Mb Broadband:
"Perfect for families going online at the same time, downloading movies, online gaming and more."
Borked internet since: 22-07-2010

creator
CJ Worshipper
CJ Worshipper
Posts: 492
Joined: July 6th, 2006, 11:37 pm
Location: The Netherlands
Contact:

Post by creator » September 26th, 2006, 11:57 am

nice tut m8 :)
Cod 1 Mapper&Modder&Moddeler

User avatar
Gagarin
CJ Worshipper
CJ Worshipper
Posts: 256
Joined: November 2nd, 2005, 10:43 am
Location: Moscow, Russian Federation

Post by Gagarin » February 17th, 2007, 3:29 pm

Hm, i think passed more than half-year. Drof, may be u finish tutorial ? =)
Image
Image
Image

User avatar
Drofder2004
Core Staff
Core Staff
Posts: 13313
Joined: April 13th, 2005, 8:22 pm
Location: UK, London

Post by Drofder2004 » August 1st, 2007, 1:00 am

Bumped this to "Announcement" as scripting is getting a lot more attention lately, and thought this would provide a lot of the learners to get more info.

I shall finish this tutorial (and maybe add what I have learned in nearly a year) soon.
Image
Virgin Media 20Mb Broadband:
"Perfect for families going online at the same time, downloading movies, online gaming and more."
Borked internet since: 22-07-2010

User avatar
Marshall
CJ Spammer!
CJ Spammer!
Posts: 820
Joined: December 10th, 2005, 11:28 am
Location: UK

Post by Marshall » August 14th, 2007, 2:37 am

Nice, I've saved it

User avatar
Coontang
CJ G0D!
CJ G0D!
Posts: 1797
Joined: March 4th, 2007, 3:48 pm
Location: Painting by numbers

Post by Coontang » August 14th, 2007, 10:48 am

Go you, drof!
thought youd never finish... :wink:
Image
JDogg: 'I have a video of me pissing, wanna see?'

matt101harris
PC Team
PC Team
Posts: 2369
Joined: March 30th, 2008, 4:21 pm
Location: South England
Contact:

Re: Scripting for Dummies

Post by matt101harris » April 17th, 2009, 12:43 pm

well i am a dummie yes but i am 2 dumb 2 be botherd to read it all :D but wat i read of it i kinda understood :P but very nice mate :D someone has been VERY busy :D
PeЧĐuĐe@CoDJumper.com: put your cock away, you sick man
Matty@CoDJumper.com: hahaha
PeЧĐuĐe@CoDJumper.com: (while i whip mine out)
Matty@CoDJumper.com: lol
PeЧĐuĐe@CoDJumper.com: just kidding
PeЧĐuĐe@CoDJumper.com: ... i don't have one :(

_DanTheMan_
PC Team
PC Team
Posts: 294
Joined: September 6th, 2008, 2:14 am

Re: Scripting for Dummies

Post by _DanTheMan_ » April 17th, 2009, 4:45 pm

matt101harris wrote:well i am a dummie yes but i am 2 dumb 2 be botherd to read it all :D but wat i read of it i kinda understood :P but very nice mate :D someone has been VERY busy :D
Matty, check the date of the post. :P
Image

matt101harris
PC Team
PC Team
Posts: 2369
Joined: March 30th, 2008, 4:21 pm
Location: South England
Contact:

Re: Scripting for Dummies

Post by matt101harris » April 17th, 2009, 4:50 pm

no i new that i was just testing you... :lol: **good he fell for it**
PeЧĐuĐe@CoDJumper.com: put your cock away, you sick man
Matty@CoDJumper.com: hahaha
PeЧĐuĐe@CoDJumper.com: (while i whip mine out)
Matty@CoDJumper.com: lol
PeЧĐuĐe@CoDJumper.com: just kidding
PeЧĐuĐe@CoDJumper.com: ... i don't have one :(

User avatar
|Master|
CJ Worshipper
CJ Worshipper
Posts: 331
Joined: December 21st, 2009, 2:31 pm

Re: Scripting for Dummies

Post by |Master| » August 23rd, 2010, 9:25 am

Nice tut Drofder :P it will help a lot of people with script problems. Awesome!
Administrators: God, The Devil
Members: The People
Guests: Babies!


Image

User avatar
.:iSpawn:.
CJ Worshipper
CJ Worshipper
Posts: 422
Joined: December 17th, 2008, 4:58 pm

Re: Scripting for Dummies

Post by .:iSpawn:. » September 18th, 2010, 5:10 pm

Awesome Tut, cant wait to read through all of it.
Image

User avatar
Trckrcj
CJ Wannabe
CJ Wannabe
Posts: 21
Joined: September 28th, 2010, 6:54 pm

Re: Scripting for Dummies

Post by Trckrcj » October 4th, 2010, 7:24 pm

nice tutorial, the same as c javascript?
Delete plz

User avatar
Drofder2004
Core Staff
Core Staff
Posts: 13313
Joined: April 13th, 2005, 8:22 pm
Location: UK, London

Re: Scripting for Dummies

Post by Drofder2004 » October 4th, 2010, 9:40 pm

Trckrcj wrote:nice tutorial, the same as c javascript?
The coding is very similar to all formats.
Java and C/C++ being the most well known, but the code is actually a QuakeC variant which itself is obviosuly a C variant.

Most of the above can be used in many languages.
Image
Virgin Media 20Mb Broadband:
"Perfect for families going online at the same time, downloading movies, online gaming and more."
Borked internet since: 22-07-2010

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests