This is a guide intended for the beginner who doesn't know any C syntax or CoD syntax. If you know basic C, you don't need most of this guide. Choose a topic below or start at the first topic. This is in no way, shape, or form a complete guide to CoD Syntax. I will do my best but there are so many aspects of it that it takes a while to think of it all and think of a way to explain it logically.
Scripts are saved as .gsc and .csc. The major difference between the two is that GSC is run 'server-side' (on the host pc) and CSC is run on the 'client-side' (on connected players and the host, each separate). The syntax between the two is the same but practice and utility functions are slightly different. This tutorial will focus on GSC scripting. There are also menu scripts (.menu) which will be covered in a later tutorial.
All scripts must have '#include' statements which include basic functionality and include utility functions needed to define what you script. If you don't include these basic files, your script will get a "unknown function" error at runtime. Runtime is what you load your map and scripts are compiled.
While I'm on the subject of runtime errors, I want to go over how to see errors. CoD has a console, which can be accessed using the ~ key (to the left of the 1 key on a US keyboard). If you cannot access the console, go into Options>Game Options and enable the console. The console lets you do lots of things, but right now I'm only going to focus on debug features. Pressing Shift+~ will bring the console into fullscreen view, which is what shows us more info about errors than the pop-up windows do (line numbers, file name, etc). Look for red text that has a relevant error to you. Obviously "error: missing texture" isn't going to help you or affect your scripts.
When you can't see enough info about your error, sometimes it is useful to enter 'developer 1' (without quotes) into the console and press enter. Then boot your map again. You will see more info about the error.
Note : Enabling developer 1 will most likely prevent your map from booting. If you fix an error, make sure to turn developer 1 back to developer 0 before attempting to boot your map again.
CoD GSC has a basic syntax that must be followed to have working scripts. If you get an error such as "Bad Syntax: blah" it means you made a syntax error. developer 1 and a full console view will tell you a line number to start looking near, and in some cases, there will be an * below the line under a certain character where the bad syntax starts. See Beginning for more info on debugging.
Logic statements
: if(), else if(), else(), while(), for(), function_declaration(), or similar.
Strings
: information that is not variable. Strings are surrounded by double quotes.
/# and #/ are encapsulating tags used to create code blocks which only run when the game was booted with developer1 and developer_script 1 before the map was loaded. Setting the variables to 1 after the map has loaded will not allow the script to run because it is removed from the code in RAM during the map loading period if those dvars are not both set to 1.
Here are some examples. Don't worry if they don't make sense yet because I haven't explained them. Just remember to come back here for reference.
Example of comment and strings syntax:
Example of array syntax:
Example of function syntax:
Example of logic statement syntax:
Variables store info. Yes, it's really that simple. Variables can store strings, numbers, objects, arrays, etc. The list goes on.
Variables must be defined before you can use them. Undefined variables (variables that have never been declared or have a value of "undefined") will cause errors if not handled correctly.
You declare a variable with the = operator. You create a new value 'on the
left' of the operator and assign an existing or new value 'on the right' of
the operator.
Example:
Variables can be accessed an infinite amount of times
within the function they were declared
, and
their value does not change until you reassign it
.
If you wish to access one variable from multiple functions, there are two
approaches. You have to either pass that variable into the function, or you
have to declare that variable as 'global'. The CoD syntax for a global
variable is to store said variable inside the 'level' variable using the dot
operator.
Dot Operator : A variable within a variable (inception!).
Example of passing a variable:
Example of globalizing a variable:
I'm sure at this point you've seen 'self' used as a variable in almost every script you've read. What is self? What is its purpose? Well little Timmy, self refers to whatever object a function has been called on. For instance,
Arrays are a very useful form of variable. Like a variable, they store information. However, arrays are a special type of variable that can store multiple pieces of information that can be 'indexed'. You will learn to love arrays, and they will bring your line counts down immensely.
Note : CoD and C start counting from ZERO, not ONE. So if you want to count to 15, you count to 14.
I'll start off with an example of a block of code that uses an array, and then the same block of code without using an array. I will throw a lot of code in there but just focus on the point, which is line count and syntax.
Without arrays:
There are a few key points to go over with strings.
Concatenation : Joining two strings together to form one line of text.
Example:
getSubStr(string, start, end) : CoD utility function which allows you to 'cut' the beginning of a string off and turn it into a new string. end is an optional arguement
int(string) : CoD utility function which allows you to convert a string to an integer value for math purposes. There is no str().
Example:
Math is very straightforward in GSC. If you know any other programming languages, or if you passed basic math, this should be very easy to understand. If you failed basic math, shame on you.
Operators
: + - * / < <= => > ++ -- = == += -=
+
Addition
-
Subtraction
*
Multiplication
/
Division
<
Less-than
<=
Less-than or equal to
=>
Greater-than or equal to
>
Greater-than
++
Increment by +1
--
Decrement by -1
=
Equals or Assignment
==
Is-Equal-To
+=
Increment by
-=
Decrement by
Examples:
Function : A codeblock of logic and/or tasks.
Functions have the following syntax:
A function can either complete tasks (with no end statement) or complete logic
(with an end statement).
End Statement : return, continue, break.
return : When code runs into this end statement, it will return to the function that called the current function and continue logic from there. If a variable is passed with the return, it will return that value to the variable that the current function was called on.
continue : This statement can only be used within a loop. When the code runs into this end statement, it will skip the remaining code in the loop and start again from the beginning of the current loop. Think of this keyword as a "restart" ability for loops.
break : This statement can only be used within a loop. When the code runs into this end statement, it will break from the current loop, which will continue by executing any remaining code after the loop.
If you're confused about the difference between continue and break, test them out and make your own conclusions.
Example of a return statement with a passing variable:
The BEST WAY TO LEARN how to use functions efficiently and intelligently is to look at existing ones! See how others conquered the issues you face. The beauty of programming is that there are almost always 100 different ways to code the same thing! Experiment with how short you can make your functions and still have them accomplish your goals. Don't be satisfied with a 300 line function that could be written in 34 lines.
The key points of calling functions are 1)thread or no? 2) arguments? 3) calling to other files.
1)
To thread, or not to thread? That seems to be the question on everyone's mind.
To an experienced scripter its a pretty fundamental aspect of calling
functions, but to the newbie it may seem like guessing on thread/not thread
will fix their non-working functions. DON'T GUESS! I'm here to tell you when
to use the all-important 'thread'.
The easiest way to explain (at least for me) is through a visual aid. Imagine
yourself weaving a rope together. You have 3+ strands of thin pieces of rope
and you weave them together to make one thicker, stronger piece of rope. When
you wound up that rope, you had 3 different strands all being woven at the
same time, right? Well, when you 'thread' a function, it's just like threading
together a rope. Threading a function causes it to be run in the
background
while the function continues to run without waiting for the function to finish
or return a value first. If you don't thread a function, the flow of execution
will
halt
at the function call and wait for the called function to finish before
executing any code after the call.
For example, if you call a function in your mapname.gsc before
maps_zombiemode::main() is called, it will prevent zombiemode from ever
starting (i.e. your zombies will not spawn, etc). If you
thread
that function, it will allow zombiemode to initialize without waiting for your
function to finish.
2) Arguments are variables or absolutes that you pass to a function for processing ( Example ). Arguments can be optional or required.
3) You can use functions that are in other files without #including them at the top of your script. The way you do this is as follows:*
They work just like normal functions (for example, you can still assign a variable's value to a function outside of the current script using that same format.
Loops are your second best friend (right up there with arrays). They allow you
to repeat logic until something changes (or indefinitely). Again, the best way
to show their importance is with visual examples.
Say I want to have a door that waits until the player walks up to it before it
opens.
You can also have while() loops that will end once a certain thing is true or
false. For instance:
For() loops can also be indefinite, but that is not their primary use. This
for() loop provides the same functionality as it did above with while():
The primary function of for() loops is to loop through an array using an
'index'.
Index:
A string or numerical value that corresponds to a value inside an array. An
index is the same as the 'key' in a keys-and-values dictionary (if you want to
think of it that way). Although strings can also be used, only numbers are
supported for using in a for() loop through indexes. There are other ways to
loop through an array of strings using getArrayKeys() which we will not
discuss right now.
A great visual example of the power of for loops can be found way back up in
the
Variables
section. The syntax for a for() index loop is as follows, where 'variable'
contains a numerical value from 0 to the size of the array:
This loop will run the same code over and over for each item stored in the array, starting at whatever number you specify and ending at whatever number you specify. In the above example, the loop starts with array 0 and goes to the highest index in the array.
There are a number of CoD-specific utility functions that you will find useful. They can ALL be found here https://ugx-mods.com/script and here https://zeroy.com/script . There are also other functions that Treyarch wrote for CoD5 and IW wrote for CoD4 that can be found in the raw/maps folder of your CoD5/CoD4 installation. The most used utility function is probably the getEnt() function, which is explained below:
So you want to move that purple box 10ft in the air and then make it disappear? Wow, that's really stupid, man. Why would you want to do that? Did you seriously just spend 45 minutes reading this entire page to accomplish that?
Just kidding! On with the actual info:
Acquiring entities is easy. You use getEnt(value, key) to get one ent (and there must only be one of that name!) and getEntArray(value,key) to get a group of ents with the same name. Most of the time, your key will be "targetname" and your value will be whatever you assigned it in Radiant, although you can acquire ents using other key/value pairs as well (but the question is why bother). To acquire any ent, it MUST BE SET AS A SCRIPT_MODEL (XMODEL) OR SCRIPT_BRUSHMODEL (BRUSH) IN ORDER TO BE SEEN BY SCRIPT. Read that sentence like 5 times. Maybe 10. Seriously. It's REALLY important that you understand that and that you don't forget it.
To be continued.
Have questions? Suggestions? Comments? Parts to point out where I screwed up?
Let us know or contribute your change! :)