All About Flags

Flags are one of the most commonly misunderstood things in CS modding, when really they aren't that difficult at all! This tutorial will teach you all you need to know in order to be a flag wizard and impress your friends and family.

What's a flag?

To start off with, in the regular course of CS modding you will come across a few different types of flags.

TSC flags are by far the most important to know, and will be the focus of this tutorial; Entity flags will be discussed in a seperate tutorial.
Each flag in cave story represents one 'bit' of data, and can have one of two values: on, or off. A flag that is on is said to be set, and a flag that is off is said to be unset. Setting and unsetting flags can be done as many times as you want, and there's no harm in setting a flag that's already set, or trying to unset a flag that wasn't set to begin with.
Although TSC allows you to use flag numbers up to 9999 (or more if you're sneaky!), only flags 0-7999 get saved in profile.dat and higher values may cause unexpected behaviour (more on that in the advanced section). Skipflags are even more limited, with only 0-127 being viable numbers; more than that and they'll be put into regular flag memory space, with <SK+0128 being the same as <FL+0000.
It's also recommended that you use flags greater than 10, because very low values may be designated as special "game flags" set by the engine that shouldn't be changed.

How do we use flags?

Flags are used to make the game world respond and change as the player progresses through the story. They can do this in one of two ways;

In Script

the most obvious use of flags is to control the flow of script. The <FL+ and <FL- commands turn the flags on and off, and the <FLJ command is used to go to a particular location in the script based on whether a flag is set. Consider the following example:

#0100
<KEY<FLJ0010:0101<FL+0010
<MSGHey, I haven't seen you around here before!<NOD<END

#0101
<MSGWelcome back!<NOD<END

Here we have a simple one-time script; the first time it is called (by interacting with an entity, let's say) we get the "I haven't seen you around here before!" message, because flag 0010 hasn't been set yet and so the FLJ doesn't trigger. However, as soon as that jump is missed, flag 0010 gets set so any subsequent calls to #0100 will go straight to #0101, giving the "Welcome back!" message.

With Entities

The other way of using flags is to associate them with entities. In the entity editor, every entity has a flag ID (or entity ID) that it uses when performing flag-related operations. Two special entity flags, "Appear when flagID set" and "Disappear when flagID set" are used with the flag at the time the map is loaded to determine whether or not the NPC should be loaded. Setting the entity's flag will have no effect until the map is reloaded, it should be noted.

If an entity has the "Disappear when flagID set" entity flag, then if it is killed or deleted the flag corresponding to its flag ID will be set automatically! This is the cause of much flag-related confusion for modders who don't know this.

These basic relationships can be added onto one another to build more complex conditions. For example, a chest is basically a one-time event that animates the chest to make it open, and then sets a flag so that every subsequent time the room is loaded the original chest entity isn't created and a different, open chest is made in its place. Numerous flags can be used to confirm a series of conditions to meet, and even simulate a rudimentary counter.

Tips

Advanced

As mentioned earlier, using flags above 7999 is generally a bad idea. There is no range checking, so if you use a value that is too large then it will happily set bits in parts of the memory that aren't for the flags, much like an out-of-bounds array. However, if you have a good knowledge of the memory layout you may be able to use this to your advantage to arbitrarily set some variables that would be otherwise inaccessible; in regular CS one that springs to mind is the "Show FPS" byte which should be relatively near to the flag memory. Each flag is one bit and there are eight bits in a byte, so the range of this command isn't very high. Using non-numerical characters in the TSC arguments significantly increases the range of accessible values, but the max is still probably only a few kilobytes of range.

If you are comfortable with binary, flags could be used to set up a "counter script" to simulate number variables with TSC. The amount of code and processing increases dramatically with the more bits you want to add, as every aspect has to be essentially "hard-coded" into the script. Still, it can be used for some neat things like timers or item counters.

Author: Noxid