Variables (or symbols) are like storage places with a name. Values are stored in variables. These values can be numbers or text. All variables should be declared in the symbols section. A symbol declaration tells JK to reserve memory for the value that the variable will be given in the code section. With most variables, you can assign an initial value when you declare the variable.
An integer is a whole number - a number without a fractional portion. You'll use integers more than anything else when writing cogs. A typical declaration looks like this:
int is short for integer. With every variable that you define, the variable's type will come first. Next is the variable's name - in this case, yourInt. In this declaration, the integer is given an initial value of 1. You can also add arguments after the declaration which tell JK how to use the variable (covered that later on this page).
Floating point numbers, or floats, are numbers with a fractional portion. They're called floats because the point is said to "float" between digits.
JK has two floating point types: float and flex. Apparently, both types are exactly the same. Float is the standard programming term, but flex is more commonly used in Cog. Their declarations look like this:
float yourFloat=1.1 flex yourFlex=1.2
Floats are most often used to store physics variables like speed, mass, and vector axes.
Templates are defined by giving the template's name as it's listed in its JKL file. Template variables are usually used to get a reference to a specific template since you won't normally refer to a template by name in the code section. A declaration looks like this:
A template contains an integer value. This integer is the template's number in its JKL's listing. For the static.jkl, there is an offset number that's added to the list number.
Vectors are special variables that store three floating point numbers. Vectors do not accept an initial value in the symbols section but you can pass a value to them from a JKL. Their declaration looks like this:
A vector's value can be expressed in several different ways, but when passing a value from a JKL, you'll use the form (x/y/z).
File variables are used to get a reference to a resource file. They are declared like this:
ai yourAI=example.ai material yourMat=example.mat sound yourSound=example.wav keyframe yourKey=example.key model yourModel=example.3do
JK will look for these files in their respective resource subfolders. All of these variable types contain integer values. This value will be the number of the resource in its JKL's list for that file type. In some cases, JK will add a resource that's not already in the JKL's list.
Cog variables can't be assigned to .cog files because more than one copy of a cog can be loaded in the same level. Referring to a cog file wouldn't let you talk to the right cog. Cog variables hold an integer value which is normally passed from a JKL. This number will be the target cog's number in the JKL's list. And each instance of the cog in the level will have a different number in the list. The declaration looks like:
Messages are declared in the symbols section to tell JK what events the cog is listening for. Messages aren't used in the code section like other variables. Their declaration looks like this:
Message variables must be given message names.
A thing declaration looks like this:
Things have integer values - the number of the thing in the thing list. You can give them initial values just like integers, but it's not that helpful from the cog itself. A thing that's already placed in the level should be left open for the level's JKL to define.
Surface variables contain the integer number of surfaces in the JKL's list. Their declaration looks like this:
Surfaces should be left open for the level to define.
A sector is a group of surfaces that form a room. Level geometry is created by adjoining (combining) sectors. Like surfaces, sectors are integers containing the value of a sector in the JKL's list. Their declarations look like:
Sectors should be left open for the level to define.
A string is a sequence of characters (i.e., letters, numbers, etc). Strings are written inside of double quotes. For example:
"this is a string."
Cog doesn't really have a string symbol type, but in the code section you can assign a variable to a string value, and it will keep the value.
Level cogs receive their events from things that the level defines for them. Let's say our cog's symbols looks like this:
symbols thing myThing message created end
And the cog's listing in the level JKL looks like this:
Section: cogs World cogs 10 #Num Script Symbol values 0: yourCog.cog 18 end
The value of 18 is being passed to the variable myThing. So when the level finishes loading, myThing will have a value of 18. This is how the level defines variables.
When the level passes a thing, sector, or surface value to one of its cogs, it associates the cog with that object. In our example above, yourCog will receive the created message from myThing.
If you don't want to define a variable in the JKL, or you do but don't want to receive its events, you'll need to add symbol extensions after your variable.
After a variable's declaration, you can add arguments that tell JK how to use the variable. These arguments will be refered to as symbol extensions in this reference. These extensions are desc, local, mask, linkid, and nolink.
Desc serves only to add commenting to a variable. A typical use would look like:
thing myThing desc=this_is_my_thing
JK won't complain either way, but it's considered bad syntax to have spaces or special characters in the description.
Local is the most common extension used in cog. This extension tells JK that the variable will not be given a value by the JKL. For example, let's say your symbols looks like this:
symbols thing myThing int myVar local thing myOtherThing message created end
And your JKL looks like this:
Section: cogs World cogs 10 #Num Script Symbol values 0: yourCog.cog 18 20 end
myThing will be given a value of 18, and myOtherThing will be given the value of 20. Because myVar had the local extension, JK skipped over it when it assigned the JKL's values.
Mask is used to limit the events that the cog receives from a thing. All events have source and a sender. The source is the thing that caused the event. And the sender is the thing that the event happened to. When the event happens to the sender, it will send a message out to its cogs telling them what's happened. The message includes the thing that caused the event - the source.
Mask Flags are used to block messages that have irrelevant sources. Let's say you want your cog to listen for the touched event of a thing so that your cog can do something when the thing is shot. If the thing is touched by the player, you don't want him to do anything. Instead of adding extra code to your cog to make sure the source of the touched event is a laser, you can use mask flags to block out events caused by players.
For this example, the declaration would look like:
thing myThing mask=0x8
Flags have not been covered yet, so it's ok if 0x8 makes no sense. The 0x8 flag tells JK that only the cog will only receive messages of events that were caused by a weapon. If we wanted the reverse - if we wanted only events caused by the player and nothing else, the flag would be 0x400. If we wanted both players and weapons, the flag would be 0x408.
There are default masks for things, sectors, and surfaces. These are explained in the symbols documentation. By using the mask extension, you are overriding this default. To receive all the messages that a thing sends, use a flag of 0xfff.
Linkid is used to make a group out of a bunch of symbols so that it's easier to refer to them in the code section. A declaration looks like:
thing myThing linkid=1 thing myOtherThing linkid=1
Then in the code section, you'd be able to refer to all the objects that have a linkid of 1 instead of having to write the variable name of every one of the objects in your group. Nolink is used when you want to define a thing in the JKL, but you don't want to listen to any of its events. Its declaration looks like:
thing myThing nolink
These symbol extensions are only useful in level cogs. However, it's considered proper syntax to add local to all of a class or inventory cog's variables. This is a way of telling the reader that all of the variables are being defined within the cog.
In all of the examples with variables, names like oneWordTwoWord and redFishBlueFish are used. The first character is lowercase to show that it's a variable - and the beginning of every other word in the name is capitalized to make it easier to read. This method of writing variable names is often called camel-hump notation.
Another common method is to use underscores: one_word_two_word and red_fish_blue_fish. Camel-hump notation may be better for you because the underscores the make you type out more characters, and you get more typos trying to shift-hit the underscore key.
A constant is a variable that's given a value in the symbols section and never changed in the code section. To make it clear that a constant shouldn't have its value changed, many programmers use all capital letters: ONEWORDTWOWORD and REDFISHBLUEFISH. This is a good rule to follow, but it can be an eyesore.
Keywords, symbol types, and symbol extensions are most often written with lowercase letters. Some programmers prefer to capitalize the first letter or all of the letters, but it's probably not worth your time for keywords that you'll use in most of your cogs.
You should always have your variables declared in the symbols section, not doing this is considered sloppy coding. But this doesn't mean undeclared variables won't work. JK is nice enough to recognize that a variable hasn't been declared, so it will declare the variable when it finds an assignment for it in the code section. JK will also convert a variable's type to the type of the value it's assigned to - something you should never let it do.
|Previous: Cog Structure||Up: How To Cog||Next: Cog Code|