There are a few mechanics involved with FE8 events that are necessary to understand how conditionals work.
Although Event Assembler has its own version of labels, what we’re interested in here is the version used in the events themselves. There are two event codes to know here, and they’re very simple; LABEL and GOTO.
LABEL is very important, despite doing nothing on its own. Putting
LABEL labelNumber where
labelNumber is any integer will mark that position in your event. Again, this does nothing on its own, but that’s where its friend GOTO comes in.
GOTO can be used to jump to any LABEL you set. Just by using
GOTO labelNumber you’ll jump to the first instance of
LABEL with the same
labelNumber occurring after the start of the current event. On its own, this may sound pretty useless; always jumping to a point. Well, what if we could GOTO only if specific conditions are met? Hold that thought, there’s one more mechanic we need to go over.
Checks are event codes that can get different information about the state of the game and return them for use in events. There’s a whole lot of these, so let’s go over what all of them are and what they do.
All of these return their result in memory slot 0xC!
CHECK_MODE Checks current game mode; 0x1 for prologue, 0x2 for Eirika, 0x3 for Ephraim CHECK_HARD Checks for hard mode; returns true (1) if hard mode, false (0) if not CHECK_TURNS Checks turn count; returns current turn number CHECK_ENEMIES Checks number of enemies; returns total number of enemies on the map CHECK_OTHERS Checks number of NPCs; returns total number of NPCs on the map CHECK_SKIRMISH Checks if you're in a skirmish or dungeon; returns true or false CHECK_TUTORIAL Checks if you're in easy mode; returns true or false CHECK_MONEY Checks your gold balance; returns amount of gold you have CHECK_EVENTID Checks the current event's ID; returns the ID associated with the currently running event CHECK_CHAPTER_NUMBER Checks chapter number; returns number associated with current map CHECK_ACTIVE Checks active character; returns active character's ID
Arguments: Something you can always do with the checks that want a character ID is use
0xFFFF to use the active character instead of a specific character.
CHECK_EVENTID eventID takes any event ID; returns true or false based on whether or not the given ID is set CHECK_EVBIT takes any evbit; returns true or false based on whether or not the given evbit is set CHECK_EXISTS character check if unit exists; returns true or false CHECK_ALIVE character checks if unit is alive; returns true or false CHECK_DEPLOYED character checks deployment status; returns true or false CHECK_ACTIVEID character checks if active character matches given character; returns true or false CHECK_ALLEGIANCE character checks unit's allegiance; returns allegiance CHECK_COORDS character checks unit's current position; returns coordinates CHECK_CLASS character checks unit's current class; returns class ID CHECK_LUCK character checks unit's luck stat; returns luck stat CHECK_AT [x,y] checks at given coordinates for a unit; returns character ID if there is a character at coordinates CHECK_INAREA character [x1,y1] [x2,y2] checks within a rectangular area for a unit, top left corner is (x1,y1) and bottom right corner is (x2,y2); returns true or false based on whether the given character is in the given area
Once again, these seem pretty useless on their own. What’s the point of getting this information in a memory slot? What can we do with it? That’s where conditionals come in.
Conditionals are special versions of GOTO that only GOTO a LABEL if certain conditions are met based on values in memory slots (you can use SVAL to put any value you want in a memory slot!). Once again there’s a number of these, but the vast majority of the time you’ll only need 2 of them: BEQ and BNE.
BranchType labelNumber memorySlot memorySlot is the format for all conditional codes; the first argument is the label if conditions are met, and then you specify two memory slots to compare the values in. Let’s go over an example of how you would use it in practice.
Let’s say we’ve got a village, but we only want to get an item from it if a certain character (let’s say, Joshua) is visiting. Our event could look something like this:
CHECK_ACTIVEID 0x20 BNE 1 0 0xC TEXTSTART TEXTSHOW 0x903 TEXTEND REMA CALL $591F40 SMOV 0x3 0xC GIVEITEMTO 0xFFFF GOTO 2 LABEL 1 TEXTSTART TEXTSHOW 0x904 TEXTEND LABEL 2 EVBIT_T 0x7 ENDA
Well, that’s a bit confusing. Let’s trim it down a little, make it a bit easier to understand, and throw parts into some definitions and macros:
CHECK_ACTIVE SVAL 1 Joshua BNE 1 1 0xC Text(JoshuaHouse) GiveItem(Shamshir,0xFFFF) GOTO 2 LABEL 1 Text(GenericHouse) LABEL 2 NoFade ENDA
You’ll notice we changed up the beginning a bit, from one code to two.
CHECK_ACTIVEID is a self-contained version of the first three codes that returns true or false to memory slot 0xC instead of doing a GOTO directly. Either way works, as there’s any number of ways to do a conditional for one situation!
If we break down our conditional further, we can simplify it to this template:
CHECK_information SVAL 1 comparison BNE 1 1 0xC //successful result GOTO 2 LABEL 1 //unsuccessful result LABEL 2 NoFade ENDA
Of course, you don’t always have to check for the values in each memory slot to be either the same or different. There’s a number of different checks you can use:
BEQ labelNumber memorySlot memorySlot *B*ranch to label if values are *EQ*ual BNE labelNumber memorySlot memorySlot *B*ranch to label if values are *N*ot *E*qual BGE labelNumber memorySlot memorySlot *B*ranch to label if first slot value is *G*reater than or *E*qual to second slot value BGT labelNumber memorySlot memorySlot *B*ranch to label if first slot value is *G*reater *T*han second slot value BLE labelNumber memorySlot memorySlot *B*ranch to label if first slot value is *L*ess than or *E*qual to second slot value BLT labelNumber memorySlot memorySlot *B*ranch to label if first slot value is *L*ess *T*han second slot value
Something to keep in mind with your conditionals is that memory slot 0 always contains 0, and you can’t set it to any other value. You can use this to your advantage, as we did in our initial example event, to compare your true/false check results against 0 instead of storing a value to compare against.
(Thanks to @2WB for proofreading this for me!)