[FE7/FE6] Arch's Guide to Chapter Construction

Chapter 2: The Event Arrays

The POIN array tells the chapter what’s what, our event arrays list all of our triggerable events.

TurnEvents

http://i.imgur.com/2lE0tNo.png

We’ll start with a quick explanation of the TURN code.

TURN eventID SceneLabel [startTurn,endTurn] phase 0x00

This is the TURN code, which triggers events based on the turn count and phase. Turn events don’t usually have an event ID assigned, since their scope is naturally limited by the turn count. However, event IDs can be useful for turn events that involve additional conditions within the scene’s code (more on this later).

The first question is: are you using the prep screen or not? Although you specify the OpeningScene in the POIN array, this only applies to chapters with the preparations screen enabled. Without the prep screen, you’ll have to specify the opening event in the turn event array.

The “SceneLabel” will be the label designating our OpeningScene. For startTurn, we want 01; endTurn will be 00 (this is the default value for events that only happen once). For phase, we’ll use 0x00 (before player phase). That code should look something like this:

TurnEvents:
TURN 0x00 OpeningScene [01,00] 0x00 0x00
END_MAIN

For chapters with the prep screen, the OpeningScene is designated to play before the screen comes up. This requires a special code to end the scene. While any other scene uses the ENDA code to signify that the scene is ending (thus telling the game to stop reading for more code), an OpeningScene with a preparations screen needs to end with the ENDB code.

It’s also worth noting that for the opening scene example we used 0x00 for our phase value (since it was the first event to trigger, it needed to occur before the player phase). However, you can run an event before any phase. 0x8 will run the event before the enemy phase, and 0x4 will run before the NPC phase.

Note: In the FE6 Template, OpeningScene is not a POIN like FE7 and FE8. The template instead specifies the opening event with a Turn Event. This is always done in FE6, regardless of whether there’s a prep screen. However, all events will occur after the preparations screen, unlike FE7 and FE8 where the OpeningScene occurs before the preparations. If you wanted to use an FE6-style OpeningScene after the prep screen, you could use a combination of the TURN designation and the POIN array, which would simply point to a blank OpeningScene with only ENDB.

TalkEvents

Sometimes called “Character Events.”

CHAR eventID SceneLabel char1 char2 0xXX00YY
  • char1 is the character who initiates the conversation (the one who gets the ‘Talk’ command).
  • char2 is the one who receives the conversation (no ‘Talk’ command).

In order to have a reciprocal conversation (where both units get the ‘Talk’ command), you’ll need to list the event twice, like so:

TalkEvents:
CHAR 0x0E NinianNatalie Ninian Natalie 0x110003
CHAR 0x0E NinianNatalie Natalie Ninian 0x110003
END_MAIN

You’ll also notice how I filled in that last parameter. This makes it so that the ‘talk’ command won’t appear until after eventID 0x11 has been triggered. It’s a built in condition; if you aren’t using that, simply use 0x000000.

Note for FE6: You guys don’t have that last parameter. Sorry.

LocationEvents

http://i.imgur.com/SIfexyl.png

Normally, I’m trying to teach the raw code over macros. If you learn the raw version, the macros will come naturally. This, however, is an area where the macros really help, since the LOCA events are distinguished by one byte and it can be burdensome to remember which one to use.

LocationEvents:
Village(eventID,SceneLabel,X,Y)
House(0x00,SceneLabel,X,Y)
Seize(X,Y) //This will automatically load EndingScene
Seize(eventID,SceneLabel,X,Y) //This can be used for multiple-seize chapters ala FE4. 
Chest(item,X,Y)
ChestMoney(amount,X,Y)
Door(X,Y)
Armory(ShopList,X,Y)
Vendor(ShopList,X,Y)
SecretShop(ShopList,X,Y)
END_MAIN

There’s the list of codes. They’re all quite straightforward. For houses, we don’t use an eventID (that allows them to be retriggered for the revisiting effect). For shops, you can write the ShopList in your events:

Armory(ShopData,4,5)
...
ShopData:
SHLI IronSword IronLance IronAxe IronBow Fire

Using that SHLI code as demonstrated above.

MiscEvents

We’ve come to the fourth of our five major POIN arrays. MiscEvents basically cover else (aside from ballistae and traps). The only tricky thing here is remembering what goes in this list.

The three most common MiscEvents are victory/loss conditions: Defeat All Enemies, Defeat Boss, and Cause Gameover If Lord Dies.

MiscEvents:
DefeatAll(EndingScene)
DefeatBoss(EndingScene)
CauseGameOverIfLordDies
END_MAIN

These two codes work for all 3 GBAFE games (including FE6, even though FE6 only had Seize missions in its main game). If your CauseGameOverIfLordDies or DefeatBoss aren’t working, it’s logical to check the eventIDs triggered by the character-in-question’s death event. In the Death Quote Editor for your respective GBAFE, boss deaths should trigger Event ID 0x02, and lord deaths should trigger 0x65. There are only two other events that go under the Misc. Events array.

AFEV eventID SceneLabel eventIDofPreviousEvent

This is the “AFter EVent.” It triggers an event directly after a specified eventID has been triggered. “EventIDofPreviousEvent” is the event that our AFEV will follow. AFEVs have their own Event IDs, so incredibly long strings of AFEVs would be theoretically possible.

You can also put AFEVs under TurnEvents so that they’ll only be checked when a phase ends.

AREA eventID SceneLabel [StartX,StartY] [EndX,EndY]

The last of our MiscEvents is the AREA event. It’s quite simple, an event is triggered when any unit steps within the specified tiles. StartX/Y and EndX/Y create a rectangular area for the event to be triggered. Everything between the two points you specified (in that rectangular shape) will trigger the event the AREA points to, regardless of a unit’s affiliation.

TerrainEvents

http://i.imgur.com/J6rqTiK.png

Last and probably least, we have TerrainEvents to cover.

Note for FE6: 6 doesn’t have a TerrainEvents POIN, nor does it have an array for them. FE6 handles the placement of Ballistae through mapping. Certain tiles (made unique by the existence of a letter embedded into the grass) make Ballistae appear on those tiles.
K = Killer Ballista
I = Iron Ballista
L = Normal Ballista

BLST [X,Y] type

Fairly simple. For type, 0x34 = Normal Ballista, 0x35 = Iron Ballista, and 0x36 = Killer Ballista.

Another small note for our Ballistae array: you need to re-align everything after it. These events have the annoying property of not being divisible by four, and they leave everything after them in the event file in shambles. An ALIGN 4 is included in the template I provided, but I thought I’d mention it regardless.

Traps also go under the BallistaData POIN Array. What exactly is a trap? Well, think of FE7’s chapter where Hector gets Armads. Remember the tiles that spat poison at your units? That’s what is called a “trap.” Our knowledge of traps and setting them up with the EA is limited. FE6 doesn’t have a BallistaData POIN Array, so I assume traps are linked to a certain tile like Ballistae. FE8’s traps are also unknown, so the following information is currently only for FE7.

TrapData:
FIRE [X,Y] 0x0 [1,1]
GAST [X,Y] direction [1,1]
ENDTRAP

For the fire trap, essentially all you need to change is the coordinates. For both codes, that second set of numbers will always be [1,1] (that’s the only value that works). You also need to set the gas trap’s direction: 0x0 Left, 0x1 Right, 0x2 Down, 0x3 Up.

For documentation on additional trap types, please refer to @Gryz’s documentation in this topic.

1 Like

Chapter 3: Handling Units

If your familiar with your game’s respective Chapter Unit Editors, you’ll have this down really quickly (it’s the same format). Units in FE6 and FE7 are written exactly the same, whereas FE8 does things mildly differently. I’m going to split the lesson into two parts, click the spoiler tag that corresponds to your version of GBAFE.

The POIN arrays provide pointers to “Bad” units, and “Good” units. Now, let me take a moment to explain those pointers. For chapters that do not use the preparations screen, those pointers are useless (but you should point to your allies and enemies anyways, just because). In chapters with the preparations screen, the number of units pointed to by the “Good” pointer equals the number of units selectable in the preparations screen. The “Bad” units are the enemies seen when you preview the map and the enemies that will be on the map when the chapter begins (if you want NPCs at the start a prep screen chapter, put them in that same group). Now let’s cover actually coding our units.

UNIT characterID clasID leader Level(#,side,autolevel?)  [X1,Y1] [X2,Y2] [Item 1,Item 2,Item 3,Item 4] AI
  • characterID and classID can be found in the EAstdlib, or in the Nightmare Modules’ character editor (don’t forget that you can define your own names!)
  • The “leader” is the character that the auto-cursor goes on, and the character that appears as the Army Commander in the Status screen. The character that is the leader should have 0x00 as his value for that byte.
  • The level part included works with the Event Assembler. Level(10,Ally,False) tells the EA I want a Level 10 Ally with no autolevel. To use autolevel, type the word “True.” Possible values for side are “Ally” “Enemy” or “NPC.” Autolevel will also give the unit the weapon rank to use the highest leveled weapons in their inventory of each type (in addition to the stat increases).
  • There are two sets of coordinates. The first set, “loading” coordinates, are where the unit first appears. The unit then moves to the second set of “starting” coordinates upon loading. If you don’t want a unit to move, simply make these two sets of coordinates the same.
  • Items are pretty self-explanatory, you can only specify four (not five, which is the maximum # of items holdable).
  • AI values are defined variables in the EA Standard Library. In FE7, you have the options of: NoAI, PursueWithoutHeed, GuardTile, Guard, AttackInRange, DestroyVillages, HealUnits, StealFromChests, StealFromUnits, TalkToLord, AttackWall, and SeizeThrone. You can use the raw values yourself (listed in Nightmare’s Chapter Unit Editors folder) by bracketing the four bytes: NoAI = [0x00,0x00,0x00,0x00], for example.

Here’s a sample from the Elibian Nights source:

ElibeanKnights:
UNIT Rebecca Sniper_F Eliwood Level(5,Ally,False) [8,12] [10,5] [SilverBow,Longbow,Vulnerary] NoAI
UNIT Lowen Paladin Eliwood Level(6,Ally,False) [8,12] [13,7] [SilverAxe,Javelin] NoAI
UNIT Harken Hero Eliwood Level(8,Ally,False) [8,12] [14,5] [SilverSword,BraveSword,SteelAxe,Vulnerary] NoAI
UNIT

The UNIT code with no parameters tells the game to stop reading for units to load. Instead of loading all of the units in one batch, you can break them up for more polish on the loading effects. You can have as many groups of units as you like, there is no limit. However, there is a limit to how many units can be in one group. I never actually wrote it down (I’ve only hit it once), but try to keep it under 40 (that should be more than enough for most circumstances if you’re breaking them up properly).

1 Like

Chapter 4: Scene Construction (pt. 1)

Now that we’ve worked our way through the intricacies of the event structure, here comes the fun part: filling in the rest. To do that, we’re going to have to learn some basic event codes.

The Darkness is your Ally

The first step to mastering events is knowing how to use the fade-ins and cover of darkness properly.

In the Chapter Data Editor (towards the bottom), you’ll see this option. If you’re writing over Lyn’s Prologue, it’ll already be set to fade to black. You can choose to have it go straight to the map (it’ll always start at the top-left corner).

Personally, I always use fade to black. Even for scenes that start on the map, since you can use the darkness to change the camera position if you want the scene to start at a specific area, and you can preload the units before starting the scene. When you have fade to black on, you’ll need to use a special code to end the covering black effect.

OOBB

Yup. That’s it. If you’re opening your chapter with a dialogue sequence, you don’t even need OOBB because loading a background will also end the black out effect.

FADI time //Fade-in with black
FADU time //Fade-out with black
FAWI time //Fade-in with white
FAWU time //Fade-out with white

Time is our only parameter here. I recommend 10 for normally-timed fades, and 5 for slower-fades. Anything above 10 tends to look choppy to me. Play around with the values to get the effect you want (you can have a fast fade in and slow fade out, etc).

While the map is faded in, absolutely nothing will appear on-screen. You can take advantage of this to load units so that it appears that they were already on the map, shift to a cutscene map, load conversation backgrounds, and more.

Manipulating darkness is one of the best ways to give your events that extra level of “polish.” Play with it; it may seem somewhat trivial (I thought it was for some time), but you can be surprised how good your events can look by using darkness to properly hide things.

Basic Text

The next most-essential component of our chapters is text. I’m not going to go in-depth teaching actual text editing, there’s another tutorial for that. Here are the codes you’ll need to know for text.

We will need to add a few more codes to our repertoire, however.

FADI 10 //obligatory fades
BACG backgroundID //displays the background
FADU 10
TEX1 textID //displays the text
REMA //clears the screen

You can, of course, load text without a background. The portraits just display over the map. We’ve got three new codes here, all of which are pretty straightforward.

To find your textID, simply open up FEditor:

That bit that’s highlighted there? That’s your textID. For the backgrounds, you can find those lists for FE6, FE7, and FE8. So, let’s go back and fill in the blanks from the above code.

FADI 10 //obligatory fades
BACG 0x00 //displays the Lyn tent background
FADU 10
TEX1 0x815  //displays the text at input index 0815
REMA //clears the screen

Let the Music Play!

Another one of the absolutely basic staples.

MUSC songID //plays the specified song

You can find lists of songs in your respective Chapter Data Editor folder. In previous versions of EA the code was formerly “MUS1”, but has since been changed to “MUSC”.

MUEN time

This code ends the current song playing, fading it out based on the time specified.

The chapter data editor gives you the option of specifying a song to play at the very beginning of the chapter. Personally, I’ll often just use a MUS1 at the top of my OpeningScene (I like having things contained to my event.txt whenever possible, but it’s a matter of personal preference).

Camera & Cursor Controls

The camera is trained to automatically follow unit movement. It will focus on a moving unit as it moves. This can be useful at times, but sometimes you’ll want to keep the camera static to hide a new unit that’s about to enter the scene, to keep the focus on a commander as his army sorties, etc.

CMOF //Turns off the camera's automatic follow.
CMON //Disables CMOF, turns the automatic follow back on.

You can also force the camera to focus on a particular coordinate or character.

CAM1 [XX,YY] //Focuses camera on tile XX,YY
CAM1 characterID //Focuses camera on a certain character

And also you can force the cursor to flash.

CURF [XX,YY] //Flash cursor on tile XX,YY
CURF characterID //Flash cursor on specified character

It’s all fairly basic stuff, non?

Loading & Moving Units

Of course, all the scene codes in the world won’t build a chapter without any units. There’s certainly more to cover, even with just these four topics, but we’ll come back to the more advanced scene constructions later in the tutorial.

Now that we’ve got a handle on creating units from the previous chapter, we’ve got to start getting them onto the map. In order to accomplish that, we’ll need to use this event code:

LOU1 UnitGroup

The only parameter is a pointer to the unit data that you’re trying to load. Let’s provide an example, shall we?

Cornwell:
UNIT Raven Hero 0x00 Level(10,Ally,False) [3,1] [3,1] [Berveil,SteelAxe,Elixir] [NoAI]
UNIT
.......
OpeningScene:
MUSC 0x0034 //Plays music 0x0034
LOU1 Cornwell
ENUN
CAM1 Raven //Puts the camera on Raven before we see the map
BACG 0x10 //Sets the Background to 0x01, which displays without a FADU thanks to the 'fade to black'
TEX1 0x0820 //Displays text at index 0820
REMA //Wipes the screen of backgrounds, portraits and text.
ENDA

And there Raven will be after the REMA, his unit on the map with the camera centered on him.

You’ll notice that the unit I loaded simply stays in place. When you have loaded units moving to their starting coordinates, you’ll want to follow your LOU1 with another code:

LOU1 Cornwell
ENUN //Tells game to stop reading events until all units in position

Once you’ve gotten units onto the map, you’re free to move them around as you wish. Keep in mind that you can pre-program a movement when you load a unit by having different load/start coordinates.

MOVE characterID [XX,YY] //Moves character to specified coordinates.
MOVE [X1,Y1] [X2,Y2] //Moves character on the first set of coordinates to the tile specified by the second set of coordinates. Used to move generics.

You can also add a third parameter to adjust the unit’s speed.

Wrap-Up (pt. 1)

One more basic code to cover before we move on (because there’s nowhere really good to stick it):

STAL time

This will, as the name implies, stall the reading of events for a set amount of time.

Before we move on, you can study this sample OpeningScene I’ve constructed with everything we’ve got here.

OpeningScene:
MUSC 0x0023 //plays "The Kingdom of Bern"
CAM1 [11,10] //sets the camera to center on those coordinates
OOBB //ends the fade to black effect
STAL 20 //stalls
CURF [12,7] //cursor flash on that coordinate
MUEN 5 //ends the music
FADI 10 //fade in
BACG 0x15 //loads "Castle Hall" background
FADU 10 //fade out
TEX1 0x815 //displays that text
REMA //clears screen & returns to map
LOU1 Good //loads units under the "Good" label
ENUN //waits for units to finish loading before continuing events
ENDA
1 Like

Chapter 5: Scene Construction (pt. 2)

Now that we’ve gone through the basic event structure, we get to learn alllllll of the scenes and codes.

Villages & Houses

Villages are primarily used for three things: recruitments, items, and money. At least the ones with red roofs, that is (damn brown roof villages just offer dialogue).

One important thing to note, the game actually quiets the map music when visiting a village or a house using these codes:

MUSI //Make music quieter
MUNO //Reverses MUSI, making music normal after MUSI's usage.

So, let’s start off with that first one: recruitment.

VillageRecruit:
MUSI //The music gets quieter in a village scene
FADI 10
BACG 0x02 //Loads village with a garden background
FADU 10
TEX1 0x815
REMA
LOU1 Recruit //Loads our new recruit
ENUN //Just use these for good measure
MUNO //Undoes the music quieting effect
ENDA

This is pretty much the basic outline for your village events. What changes what happens after the REMA. For this one, we’re doing LOU1 to reference this unit group.

Recruit:
UNIT Wil Archer 0x00 Level(3,Ally,False) [3,2] [3,3] [IronBow,Vulnerary] NoAI
UNIT

And huzzah, Wil joins the party! You’ll want your village recruits to move down a tile, since otherwise they’ll be loaded on the same tile as your visiting unit.

Then, of course, we need our items and our money.

ITGV item //Gives item to the active character (the one visiting)
MONE 0x00 amount //Get money!

For houses, we’ll be following a similar routine.

House1:
MUSI //The music gets quieter for house scenes too
FADI 10
BACG 0x01 //Loads house with a fireplace background
FADU 10
TEX1 0x81A
REMA
MUNO //Undoes the music quieting effect
ENDA

Characters Talks

Since these events interrupt the map, we’ll be using a special music code:

MUSS songID //changes song while remembering leave-off point for last song playing
MURE time //fades back to map music

Otherwise the map music will reset to the beginning after each talk. Using MUSS (formerly “MUS2” in previous EA versions) in conjunction with MURE will play a song and then return to the previous background music at the same point that the original song left off. Again, one of those polish things.

With TalkEvents, you’ll want to use another variant of the item code:

ITGC charID itemID //Gives item to specified character.

TalkEvents can be used for a variety of purposes, the most prominent among them is for recruitment conversations (that’s largely what GBAFE uses the function for). For that, we’ll need I’m sure you’ve already guessed it to learn a new code:

CUSI unitID alliance

This code changes the unit’s alliance. $00 turns into an ally, $A7 becomes an enemy, and $47 becomes an NPC.

So, now let’s make a demonstration of a recruitment conversation:

RecruitTalk:
MUSS 0x42 //Plays "Together, We Ride!"
TEX1 0x817
REMA
CUSI Navarre $00 //Navarre joins the party!
MURE 0x05 //Shifts back to map music
ENDA

Some pretty simple beans there, right?

Enemy Reinforcements

Reinforcements are spawned through TurnEvents. When they load depends on the phase you choose (you can select to load them on the enemy phase for the dreaded ambush spawn, or be nice and load them before the player phase). But basically, the actual scene is quite simple:

Reinforcements:
LOU1 UnitGroup
ENUN
ENDA

For ambush spawns, you’ll want to throw in a MUS1 code with the enemy phase music at the start of the scene.

You can also use the CMOF code before the LOU1 if you want to be extra devilish (that way, the camera won’t automatically show the reinforcements load).

Other Mid-Chapter Effects

Using TurnEvents for weather changes is fairly common, you’ll use this code:

WEA1 weather

The weather values are defined in the standard library, you’ll have your choice of: Clear, Rain, Snow, SnowStorm, BlueBackground, Flames, SandStorm, Clouds.

Amidst the standard weather affairs, you’ll notice some other effects. Clouds is used in FE6 as a background for St. Elimine’s tower (only displays behind certain tiles). Same with BlueBackground, while Flames will put a burning animation at the bottom of the screen that follows with the camera (used in lava caves).

Fog is also fairly simple to call up.

VCBF vision //black fog
VCWF vision //white fog

vision will change the tile distance units can see. To reverse the inflicted fog, use the code again with 0x00 as your value for vision.

You can also change the AI for units mid-chapter with these commands:

CHAI characterID AI //Specific-character
CHAI [X,Y] AI //For generic units

At least, it would seem that way. CHAI does something funky with the AI; changing a GuardTile unit to free roaming AI gives you a unit that won’t attack, for instance. Which may or may not be useful to you, but the combinations of AI and their results aren’t that well documented.

It appears to goof when there’s a value other than 0x00 in the fourth byte of the AI combo.

You can set AttackInRange as the initial AI and CHAI to PursueWithoutHeed if you want them to go from standing still to becoming aggressive. Obviously, the units will still attack if you get in their range, but this gives some sort of “stand still” to “move and attack” effect.

It’s also possible to change the phase music mid-chapter simply by triggering eventID 0x04 (either through ENUT or assigning it to the event that triggers the change). The chapter data editor lists the secondary phase music.

Ending Scenes

Often for ending scenes, you’ll want to clear the map of all active units (for seize missions especially, you’ll just have the lord walking in place on the gate). Luckily, we have a little macro for that.

UnitClear

UnitClear will, as the name implies, wipe the map clean of all units for EndingScene purposes (or transitions between cutscene maps, which will be covered in Chapter 7). Just stick this in your personal definitions file.

At the end of your EndingScene, you’ll need to use this code to tell the game it’s time to go to the next chapter.

MNCH chapterID

That chapterID will be the value in your Chapter Data Editor (Chapter 11E, for instance, will be 0x0C).

1 Like

Chapter 6: Scene Construction (pt. 3)

Did you think you’d learned alllllll of the codes? Think again!

More Text Controls

MORETEXT textID

This allows you to load another textID while preserving the current portraits in use. It becomes more significant once you learn conditions, for conversations where a segment depends on whether a character is alive, whether an event was completed, etc.

It’s also possible to run events mid-conversation, by using the [LoadOverworldFaces] code in FEditor’s text editor to specify the pause point, this tells the game to read events until a certain stop code is used.

TEX1 0x815
MUSC 0x30 //game changes the music mid-song
SCRO //our certain stop code
REMA

The game will continue reading events after the SCRO once told to (either by another [LoadOverworldFaces] tag, you can have multiple SCROs, or the end of the text). This is useful for changing music mid-dialogue, moving units, etc.

Beyond those two, we have a few more codes to cover.

TEX6 bubble [XX,YY] textID
_ASM0x42 0x83181 //This is like REMA for TEX6, note that REMA doesn't work, that's why we have this.

The unique thing about TEX6 is the “bubble” parameter. There are four options generally used for this value. 0x0 displays text in a speech bubble on the map, it’s just a standard speech bubble with text that you can place anywhere on the screen (it has no tail pointing to a speaker since no speaker mug appears). 0x1 displays the brown scroll bubble used for tutorial explanations and the like. For these two options, coordinates must be specified.

0x4 and 0x5 display the same backgrounds (0x4 speech bubble and 0x5 brown scroll) but automatically center them with the coordinates [0,0].

TEX8 text [XX,YY]
RETB //This is REMA's equivalent for TEX8.

TEX8 loads text with a brown-box in the background, like so. It only works with FE7 and FE8. In the .games this text box was displayed in the top right corner to designate location. But, as shown above, you really can use it for anything.

Scripted Movement & Other MOVE Codes

By adding another parameter to our MOVE code, we can have scripted movements.

MOVE charID MoveData
MOVE [X,Y] MoveData

Moves a character based on their specified “MoveData” (which is a pointer to the specifics of how you want the character to move). Naturally, GBAFE forces characters while moving to take the shortest route. If you’d like to move a character across a specific path, for whatever reason, this is how you do that. How exactly do we construct our “MoveData?”

MoveData:
MOMA left left left left
MOMA speed(0x1) left left notice
MOMA speed(0x0)
MOMA right right up up
MOMA down down down
MOMA highlight(0x2)

This demonstrates all of the defined actions that you can assign. notice puts the exclamation mark above the unit’s head, the directionals are all pretty self explanatory, speed adjusts the unit’s movement speed, and highlight has the unit move in place for the specified amount of time.

There are still a few more codes to learn.

REPOS [X1,Y1] [X2,Y2] //Repositions character without movement based on set coordinates.
REPOS charID [X,Y] //Repositions based on the character.
MOVEMAINC [X,Y] //Moves main character, FE7 only.
MOVENEXTTO [X,Y] charID //The name explains it perfectly.
MOVENEXTTO charID charToMoveNextTo

Scripted Fight Sequences

Scripted battles are called with the FIGH code.

FIGH attacker defender FightData [Byte1,Byte2,Byte3,Byte4]

Pretty simple, right? Other than the bytes. For most scripted battles, you can just use $00000000 in lieu of the brackets. The bytes give special effects.

Byte1: By using an itemID, you can force the equip of a weapon. Sets “100 hit – dmg – crit” for ally, “-- hit – dmg – crit” for Other Ally/NPC/Enemy. You can use this to force a healing staff onto a unit for scripted healing scenes, for example, or to unleash the legendary story weapon in an epic scripted battle.

Byte2: Weapon durability remaining+1. Only if Byte1 has a value. Putting any value here other than 0x00 will cause Byte1 to be active… and show a non-existent sword item if Byte1 is “0x00”.

Byte3: “WTF” to quote @shadowofchaos, who wrote up the explanation for these bytes.

Byte4: Anything other than 0x00 will cause the fight to go to “non-controlled” mode, as if you actually attacked with the attacker on a turn, and the stats are factored in if they will double…and critical, depending on the RNG.

Now all you need is your list of commands for the FightData parameter (which is a pointer to elsewhere in the event file).

AttackerHit(damage,lastAttack)
DefenderHit(damage,lastAttack)
AttackerNoDamage(lastAttack)
DefenderNoDamage(lastAttack)
AttackerCritical(damage,lastAttack)
DefenderCritical(damage,lastAttack)
AttackerMiss(lastAttack)
DefenderMiss(lastAttack)
AttackerPoison(damage,lastAttack)
DefenderPoison(damage,lastAttack)
AttackerHurtItself(damage,lastAttack)
BLDT //This will end the fight scene

Loading Other Maps

Sometimes, scenes in the openings and endings of chapters occur on maps that aren’t the chapter’s map. This is done with a simple event code, LOMA.

LOMA chapterID [X,Y]

LOMA’s coordinates are actually a built-in CAM1 (which is quite handy). LOMA stands for LOad MAp, and (as you’ve probably guessed) it loads a specified map. The first parameter, chapterID, specifies the map to be loaded. We’ve already used this value for our MNCH code. LOMA loads maps based on the chapter they’re associated with. Let’s say I wanted to load Chapter 7’s map (for some reason). The map value in the Chapter Data Editor is 0x26, but that’s useless to LOMA. To load Ch7’s map, we’d use 0x07 for our chapterID.

Back when I introduced MNCH, I also shared a macro for the ClearAllUnits code. That’ll be useful here, too.

After you’re finished with the map, for an OpeningScene you’ll want to LOMA back to the main chapter.

Protip: The native GBAFE engine doesn’t allow you to change the goal text mid-chapter. If you’re looking for that effect, simply LOMA mid-chapter to a copy of the chapter with different values for the goal text. Since it’s the same map, the units will stay in place and the chapter will carry on as though nothing happened, so long as you’ve got the same events and everything specified. This will undo any tile changes, although you can manually retrigger them yourself.

Loading CGs

CGs will require some new codes, of course. The fades work like any other (FADI/FADU for black, FAWI/FAWU for white, in case you forgot).

SHCG cgID

This is the code to show CGs, which works similarly to the BACG code. Your cgID, of course, can be found in the CG Editor. We’ve also got a special text code for text bubbles over CGs.

TEXTCG textID 0x1
MORETEXTCG textID 0x1 //Because why not?

And some various transitioning codes to top it all off:

FROMBGTOCG cgID 0x2 //Fades in the CG; also works going from CG to another CG
FROMCGTOBG background 0x2
FROMCGTOMAP [X,Y] //The coordinates act as a built-in CAM1, like LOMA 

You can insert your own custom CGs with one of FEditor’s hidden little tools.

Unit Controls

To wrap up our code dump, I’ve got two final ones for ya.

UNCM charID condition //Applies unit condition
UNCR charID condition //Reverses unit condition

0x01 = Invisible
0x02 = Greyed out
0x04 = Not in the status menu or unit data
0x10 = Rescuing
0x20 = Is being rescued
0x800 = In ballista

After a scripted fight, for instance, the attacker greys out automatically. To get his color back, you’ll need a UNCR.

FIGH Gandolf Midir Fight $00000000
KILL Midir
UNCR Gandolf 0x02

One of the more useful conditions is 0x04, which can be used to remove members of your party and force them back in. In the Elibian Nights source for Karel’s Tale, UNCR is used to essentially revive Karel after a forced loss/kill in his series of boss battles. Others have used this condition for temporarily removing party members, and even pulling of FE8’s Ch5x-esque chapters that shift parties entirely by UNCMing all of the units. They can be UNCR’d much later (as necessary), bringing them back into the party.

Chapter 7: Tile Changes

A lot of this revision for the tutorial is just copy/pasting, reorganize, update. This section, however, needed a total revamp. It used to be that I taught people to assemble tile changes from a second text file (which is how I did it, until I realized you could just put them both in the same file).

First off, if you use Tiled, stop reading this and go read this instead.

For the rest of us, we’re doin’ this the hard way. I’ve gone ahead and modified the standard template to merge in tile changes. It’s incredibly simple to implement into your event files.

#define DISABLE_TUTORIALS
#include EAstdlib.event

EventPointerTable(EventTableID,Pointers)
EventPointerTable(TileChangeID,TileChanges) //This will write the tile changes to the Event Reference Array.


ORG StartOffset
Pointers:
POIN TurnEvents 
POIN TalkEvents 
POIN LocationEvents 
POIN MiscEvents
POIN TrapDataEM TrapDataHM
POIN BadENM BadEHM BadHNM BadHHM
POIN Good Good Good Good
POIN OpeningScene EndingScene

BadENM:
BadEHM:
BadHNM:
BadHHM:
UNIT

Good:
UNIT

TurnEvents:
OpeningTurnEvent(OpeningScene)
END_MAIN

TalkEvents:
END_MAIN

LocationEvents:
END_MAIN

MiscEvents:
CauseGameOverIfLordDies
END_MAIN


OpeningScene:
ENDA

EndingScene:
MoveToChapter(NextChapter)


TrapDataEM:
TrapDataHM:
ENDTRAP

MESSAGE Events end at offset currentOffset

TileChanges: //Now we just add our tile change list.
TileMapEnd

MESSAGE Tile changes end at offset currentOffset
//The map for this chapter is at offset: ????????

Now we’ve got to fill out that tile change list.

TileMap(tilechangeID,X1,Y1,L1,L2,TilePointer)

Things are pretty easy to understand. The tilechangeID works like an eventID, just for tile changes. Start at 0x00 for your first item and work your way downward. X1 is the top-left X value, Y1 is the top Y value (for destroyed villages, your coordinates won’t be the same as your events - the event specifies the gate, but the tile change has to start at the top left corner of the 3x3 village).

L1 is the length of the tile change on the X-axis. L2 is the length of the tile change on the Y-axis. TilePointer points to the list of tile changes.

So, now we have to list the tile changes. For this, we’ll need the reference tilesets.

We’ll do the basic village tile changes to demonstrate. In the FE7 folder of that archive, I’ve opened up 1C1D1E1F.png, the standard Fields tileset. Using the rows and columns as a guide, we’re going to write out our tile changes.

For the closed village gate, you’ll see that it’s in row 0E column 28 (for the skinny road tile, the wide road is at row 00 column 28).

SHORT 0x0E28

That simple. It’s just a matter of using the reference and writing it down. Then just fill out the TileMap macro for the list and you’re golden.

TileChanges:     
TileMap(0x00,14,12,1,1,VillageGate)
TileMap(0x01,13,10,3,3,VillageDestroyed)
TileMapEnd

VillageGate:
SHORT 0x0E28

VillageDestroyed:
SHORT 0x0E1C
SHORT 0x0E20
SHORT 0x0E24
SHORT 0x0E9C
SHORT 0x0EA0
SHORT 0x0EA4
SHORT 0x0F9C
SHORT 0x0FA0
SHORT 0x0F24

Manual Tile Changes

Tile changes generally trigger automatically: the game just knows. One such example where this is necessary are vertical doors. Ordinary horizontal doors will trigger a tile change automatically. Tile changes are generally handled by the game, but there are a few times when we need to force things (vertical doors, roof removal, etc.). Vertical doors require you to abandon the macro you’ve been using for doors up until now. You have to trigger the tile changes for the vertical door manually.

Here is the code we’ll use to do just that.

MAC1 tilechangeID status

For the status parameter, you’ll use 0x00 to force a tile change and 0x08 to reverse it. Here’s what our code should look like:

DOOR 0x00 DoorRemoval [X,Y] 0x10 //Using this instead of the macro to point to a scene
.....
DoorRemoval:
MAC1 0x03 0x00 //Triggers tile change 0x03
ENDA
1 Like

Chapter 8: Conditional Logic

Conditions, my friends, are what separate the boys from the men, the girls from the women (because fuck the patriarchy), and the good event hackers from the run-of-the-mill average ones. Now it is entirely possible to make chapters without events (I’ve done so), but conditions allow for the creation of unique chapters. Tale 1x of my hack, Elibian Nights, was created using a complex string of conditions and event ID manipulation (the chapter’s goal was to rebuild three villages). Conditions allow us to have village conversations happen with specific characters, gaiden chapters to be given conditions, and a plethora of other effects.

Before we dive into learning the codes, I’d like to talk briefly about what I call “condition logic.” Conditions with events can be hard to grasp for some, and easy for others. It all depends on the individual’s degree of logic. To get everyone up to par (or at least attempt to do so), I’ll go over condition logic. Let’s say a parent makes a deal with their child. “If you clean your room, I’ll buy you Fire Emblem DS.” The condition is that the child’s room is cleaned, and there are two possible outcomes. Outcome #1: The child’s room is cleaned and the child gets Fire Emblem DS. Outcome #2: The child’s room is not cleaned and the child does not receive Fire Emblem DS. This is how conditions work in GBAFE, there is a condition set and two possible outcomes (the condition is met or the condition is not met).

Let’s translate the above example into GBAFE events. Theoretically, the room being cleaned triggers an Event ID 0x25.

IfEventIDTriggered 0x25
Kid gets Fire Emblem DS
IfConditionIsNotMet
Nothing Happens

Now, there’s a bit more to conditions than just that. There are three major components writing conditions that we have to cover: the conditionID, ELSE and ENIF.

First, the conditionID. The conditionID is somewhat like the eventID, it identifies a certain condition. No two conditions should share an ID. Condition IDs start at 0x01, and go onward to 0xFF (though I doubt you’ll need 255 conditions in one chapter). Let’s rewrite our kid’s situation with Condition IDs. We can also change “Kid gets Fire Emblem DS” to ITGC Kid FireEmblemDS.

IfEventIDTriggered 0x01 0x25
ITGC Kid FireEmblemDS
IfConditionIsNotMet
//Nothing Happens

The second piece of information we need to cover is the “ELSE” code. ELSE signals the game to read for information about what to do if the condition is not met. Having conditions without ELSE is possible if you only want one outcome, ELSE is the second outcome (what happens when Kid doesn’t clean his room). “IfConditionIsNotMet” from the fake code above is essentially ELSE. Note that ELSE uses a different Condition ID than the original condition.

IfEventIDTriggered 0x01 0x25
ITGC Kid FireEmblemDS
ELSE 0x02
//Nothing Happens

Now, how does the game know when to stop reading for the results of a condition? It doesn’t, you have to specify the end with the ENIF code. ENIF ends the results of a condition, and it’s only parameter is the Condition ID that it ends.

IfEventIDTriggered 0x01 0x25
ITGC Kid FireEmblemDS
ELSE 0x02
ENIF 0x01
//Nothing Happens
ENIF 0x02
1 Like

Chapter 9: Writing Conditions

Now, let’s go over the individual condition codes. There are five main codes that are commonly used while writing events.

IFCA 0x00 conditionID charID //If certain character is activating the event. That 0x00 is a dead byte.
IFTU conditionID turn# //If specified turn has not yet passed.
IFET conditionID eventID //If specified Event ID was triggered.
IFYN conditionID //If yes was chosen in the previous Yes/No prompt.
IFCD conditionID charID //If specified character is dead.

These condition codes can be applied to any situation at any time in your events. IFCA can be used in a village to check for a certain visitor, IFTU can be used to set up gaiden conditions, etc. These five are the most commonly used event codes, but there are a few other codes available to hackers.

IFUF 0x00 conditionID charID //If specified character is on the map.
IFEF conditionID eventID //If specified Event ID was not triggered. Reverse of IFET.
IFHM conditionID //If game is in Hector's mode. FE7 only.
IFEM conditionID //If game is in Eliwood's mode. FE7 only.
IFTT conditionID //If game is in Tutorial mode. FE7 only.
IFCNA conditionID charID //Reverse of IFCA for FE6. FE6 doesn't have IFCA.

These codes are less commonly used, and most of them are game-specific.

Guy gets a line at the beginning of Chapter 17, thanks to IFUF to check whether he’s fielded.

Here is an example of a condition-based AREA event from FE4A, the event where Lex obtains his Brave Axe in Chapter 1.

LexBraveAxe:
IFCA 0x01 Lex //If activating character is Lex.
MUSI
TEX1 0x0815
REMA
ITGC Lex BraveAxe
MUNO
ELSE 0x02 //If activating character is NOT Lex.
ENIF 0x01
ENUF 0x24 //Makes it so the event ID for this event is "unused," so Lex can activate the event if someone else steps on the tile.
ENIF 0x02
ENDA
1 Like

Chapter 10: eventID Manipulation

Notice that Lex’s Brave Axe event from the previous chapter we used the ENUF code, which I introduced way back in Chapter 3.

ENUT eventID //sets eventID as "triggered"
ENUF eventID //sets eventID as "not triggered"

These two codes are used to manipulate Event IDs for desired effects. In the Lex event, using ENUF to refresh the eventID makes it so that a random unit stepping on the tile doesn’t make it so Lex can’t trigger the event. eventIDs, as you should know, are automatically triggered when their corresponding event is triggered.

Important to note, we can manipulate any eventID, even ones that aren’t attached to a specific event. Essentially, we have a fine collection of unused switches at our disposal. Even with just a simple on/off switch, coupled with the IFET and IFEF condition codes, you can create some pretty incredible things.

As a sample, here’s something I wrote for the Death or Glory hack. Originally in Ch1, you got a Game Over for killing any of the civilian soldier units. This code tweaks that instead to scale the fund reward at the end of the chapter according to how many civilian casualties there were.

MiscEvents:
AFEV 0x12 CountingCode 0x06
AFEV

EndingScene:
IFEF 0x09 0x37 //No soldiers dead
MONE 0x01 5000
ENIF 0x09
IFET 0x0A 0x38 //One soldier dead
MONE 0x01 4375 //How much is a soldier's life worth? 5000/8 is 625G a pop
ENIF 0x0A
IFET 0x0B 0x39 //Two
MONE 0x01 3750
ENIF 0x0B
IFET 0x0C 0x3A //Three
MONE 0x01 3125
ENIF 0x0C
IFET 0x0D 0x3B //Four
MONE 0x01 2500
ENIF 0x0D
IFET 0x0E 0x3C //Five
MONE 0x01 1875
ENIF 0x0E
IFET 0x0F 0x3D //Six
MONE 0x01 1250
ENIF 0x0F
IFET 0x10 0x3E //Seven
MONE 0x01 625
ENIF 0x10
//No money for all the soldiers killed.
MNCH 0x02
ENDA
    
CountingCode: //This is what we'll run for the death quote
IFET 0x28 0x3E //All the soldiers dead
ENUF 0x3E
ENUT 0x3F
ENIF 0x28
IFET 0x27 0x3D //Seventh soldier dead
ENUF 0x3D
ENUT 0x3E
ENIF 0x27
IFET 0x26 0x3C //Sixth soldier dead
ENUF 0x3C
ENUT 0x3D
ENIF 0x26
IFET 0x25 0x3B //Fifth soldier dead
ENUF 0x3B
ENUT 0x3C
ENIF 0x25
IFET 0x24 0x3A //Fourth soldier dead
ENUF 0x3A
ENUT 0x3B
ENIF 0x24
IFET 0x23 0x39 //Third soldier dead
ENUF 0x39
ENUT 0x3A
ENIF 0x23
IFET 0x22 0x38 //Second soldier dead triggered
ENUF 0x38 //set to not trigger
ENUT 0x39 //trigger it
ENIF 0x22
IFEF 0x21 0x37 //First soldier dead not triggered
ENUT 0x38 //trigger it
ENUT 0x37
ENIF 0x21
ENUF 0x06 //Use 0x06 for the eventID of the death quote.
ENUF 0x12
ENDA

It’s just a simple counting system using eventIDs, which I’ve used for things like the a chapter goal for defeating a certain amount of enemies.

What it comes down to is ingenuity. Elibian Nights itself isn’t terribly riddled with code additions, yet it created things like an Achievements system just by manipulating eventIDs.

The achievements system in particular took full advantage of the engine’s permanent eventIDs, which are remembered from chapter-to-chapter. When an eventID beyond 0x65 is triggered, the game remembers that it was triggered, unlike ordinary eventIDs which are reset with each new chapter.

So have fun! Be creative! Even a fairly limited toolset can be powerful in the hands of a crafty coder. Above everything else, that’s my secret ingredient: a little imagination goes a long way.

1 Like

Chapter 11: ASM Conditions

And we come back to conditions again. If you thought what we covered before was the end of things; well, you were wrong. Fire Emblem has quite a few “ASM-based” conditions. Now, before your brain turns off because “ASM OMG TOO HAAAAARRRRDDDD,” for the non-ASM-challenged among us, yes this can be used to make your own custom conditions. However, you don’t have to know any ASM to work with these, they work just like ordinary conditions.

IFAT conditionID ASMRoutine //If ASM condition is TRUE.
IFAF conditionID ASMRoutine //If ASM condition is FALSE.

Those are the two codes you need to know. They just check the ASM routine, and the routine comes back with either a ‘yes’ or ‘no’ for whether the condition has been met. That’s where the real power is, and those of you with ASM knowledge (or who have generous friends with ASM knowledge), you an create custom conditions.

Here’s a list of pointers we’ve documented from FE7:

0x7D2B1 //If the unit is lucky, used for desert items.
0x7A2F1 //If it's the player phase.
0x7D3F9 //If player has X gold (X specified by player, default is 20000).

I’ve got some documentation on the pay-to-recruit events.

And, as a little treat for the class (for making it through 10 chapters of this bullshit), I’m also going to share some custom conditions with you.

@CT075 made these for a chapter in Elibian Nights, which I used for reinforcement events.

EveryTwoTurns:
00 B5 01 20 03 49 09 88 01 40 00 29 00 D0 00 20 00 BD 00 00 08 BC 02 02 00

EveryFourTurns:
00 B5 01 20 03 49 09 88 03 22 11 40 00 29 00 D0 00 20 00 BD 08 BC 02 02 00

EverySixTurns:
00 B5 01 20 03 49 09 88 07 22 11 40 00 29 00 D0 00 20 00 BD 08 BC 02 02 00

Just copy/paste these into free space, and for your ASMRoutine remember to use the offset+1. You can find the source for that here. This is the code in action:

HorseReinforcements:
IFAF 0x03 0xDE0181 //Every four turns, the code was pasted at DE0180
LOU1 Whorses2
ELSE 0x04
ENIF 0x03
IFAF 0x05 0xDE0161 //Every two turns
LOU1 Whorses
ENUN
ENIF 0x05
ENIF 0x04
ENDA
....
Whorses:
UNIT 0x7E Paladin 0x00 Level(8,Enemy,True) [3,29] [3,29] [SilverLance] NoAI
UNIT

Whorses2:
UNIT 0x6B GreatKnight 0x00 Level(8,Enemy,True) [3,29] [3,29] [SteelBlade] NoAI
UNIT

Every two turns a Paladin will be loaded, except every four turns it’ll load a Great Knight instead. These were useful in constructing a chapter with endless reinforcements to vary the loading without a TurnEvent list a mile long for all the different reinforcements.

The chapter I made was essentially a forced loss for the player, whose ending event was triggered by an ASM condition Markyjoe created. It’s sort of the opposite of the DefeatAll enemies effect, triggering the ending when all allies are defeated.

ASME 0x00 SceneLabel ASMRoutine

In my MiscEvents, this was used (triggers an event based on the ASM condition being met).

AllDefeated:
00 21 00 22 09 48 40 58 00 28 0C D0 08 48 40 5C FF 28 04 D0 07 48 40 5C 00 28 02 D1 01 22 48 31 F0 E7 00 20 70 47 10 1C 70 47 00 00 50 BD 02 02 60 BD 02 02 63 BD 02 02

You can get your hands on the source here.

Finally, we have another condition @Nintenlord made for me based on the tactician’s gender. I use it to change the gender of the My Unit character for the Tale Select in Elibian Nights.

IfTactFemale:    
00 B5 06 48 00 F0 08 F8 00 06 00 28 01 D1 01 20 00 E0 00 20 02 BC 08 47 00 47 00 00 C9 A3 07 08

These are just a few examples of the power that ASM conditions can unleash.

@Agro’s notes: I strongly suggest you check out this thread as some more custom assembly conditions are being written and released.

1 Like

Chapter 12: ASMC Effects

This is like the part in chemistry class where the teachers busts out some kickass color pyrotechnics and shows you how raw the periodic table can be.

In fact, “raw” might be the perfect word for this, now that I think of it. This is some raw ASM, plain and simple. Except for the simple part.

Okay, I brought pyrotechnics too. ASM pyrotechnics, which are triggered by this:

ASMC 0x7BBE5

This plays the fire ring animation from the Chapter 20 (Hector’s mode) cutscene with the first dragon coming out of the game and disintegrating. It plays this cool fire animation, then highlights a red glow at a fixed offset (that’s the only downside to this, since it can look out-of-place, but otherwise it’s a cool little effect).

But, in terms of events, it is quite plain. Just a quick ASMC code and the pointer to your routine. In need of a quick earthquake?

ASMC 0x7D645 //This'll get it started
ASMC 0x7D689 //And this'll stop it

And you can just STAL inbetween for however long you’d like.

Unfortunately we don’t have all of these ASMCs well-documented. @CT075’s notes are a good place to start. We should really try to fix that someday…

Nevertheless, I’ll show off some cool tricks and leave the rest to you!

This one handily enough already has a macro.

QuintessenceEffect

By calling the offset of a spell animation, you can play it on the map (it’d be great if some ASM-minded people clipped out certain parts - they can be a little wacky with multiple effects and the battle screen floor cuts).

You’ve also got a quick sword slash animation at your disposal.

FADI 16
HIDEMAP
ASMC 0xECB1
STAL 0
BACG 0x5B
STAL 20
SOUN swordsfxID
ASMC 0x7D8ED
FADU 8
SHOWMAP
REMA
2 Likes

Chapter 13: World Map Events

A quick shout-out to my friend Mariobro, who wrote the original tutorial for this. It was referenced heavily.

Well, here goes nothing. I can’t say I’ve had much experience with world map events, but hopefully I still can teach you how to do them. It isn’t terrible complex at all, just a lot of unique codes to know.

#include EAstdlib.event

WorldMapPointerTable(0x??,WorldMapEvents)

ORG 0x??????

WorldMapEvents:
ENDA

MESSAGE World map events end at currentOffset

This is basically what the world map events structure looks like. You can do them in a separate .txt file, or incorporate it into your main events file (much in the way we incorporated tile changes back when learning those). Like so:

#define DISABLE_TUTORIALS
#include EAstdlib.event

EventPointerTable(EventTableID,Pointers)
WorldMapPointerTable(WorldMapID,WorldMapEvents) //Add this here to auto-write the pointer


ORG StartOffset
Pointers:
POIN TurnEvents 
POIN TalkEvents 
POIN LocationEvents 
POIN MiscEvents
POIN TrapDataEM TrapDataHM
POIN BadENM BadEHM BadHNM BadHHM
POIN Good Good Good Good
POIN OpeningScene EndingScene

BadENM:
BadEHM:
BadHNM:
BadHHM:
UNIT

Good:
UNIT

TurnEvents:
OpeningTurnEvent(OpeningScene)
END_MAIN

TalkEvents:
END_MAIN

LocationEvents:
END_MAIN

MiscEvents:
CauseGameOverIfLordDies
END_MAIN


OpeningScene:
ENDA

EndingScene:
MoveToChapter(NextChapter)


TrapDataEM:
TrapDataHM:
ENDTRAP

MESSAGE Events end at offset currentOffset

WorldMapEvents: //Now we just have to write the damn thing.
ENDA

MESSAGE World map events end at offset currentOffset
//The map for this chapter is at offset: ????????

World map events are defined in a separate array from what we’ve been using thus far (our event reference array). Instead, you’ll need to brush off the World Map Event References.nmm. Your worldmapID will be found there.

Now it’s time to actually learn the codes. One thing to keep in mind: the world map event engine is actually not quite stable. Errors can happen through seemingly correct uses of code, randomly. For example, a portrait can get palette swapped if you didn’t use a long enough STAL code before loading after switching the map background. The solution is generally more STALs if you’re encountering a bizarre error like that (rather unscientific, I know).

StartWorldMap(map, X, Y, loadWay)

Defined map values: FullWorldMap, LyciaBernSacaeMap, NabataDesertMap

Let’s start off by starting off! You’ll need to use this macro to kick off the world map events.

The coordinates only matter for the LyciaBernSacaeMap, where they’ll serve to determine exact location (it’s kinda wonky, yeah). For the other two, the coordinates will just be 0,0. Ensure that the co-ordinates of the camera location are always a multiple of 8–otherwise you’ll get an odd effect whenever you use the FADETOWM code (discussed later).

You can get those coordinate values here. Next, we’ll need our loadWay value.

0x00 Doesn't Load, No music
0x1C Theatrical Shutter (faster?)
0x5C Theatrical Shutter (seems slow, more dramatic)
0x64 Fade in, No music
0x76 Fade in

Basic Codes

Now we can get into the weeds of world map event making. First, we’ll need some text.

TEXTWM textID

If you’ll recall what I taught you about changing music mid-dialogue (if you can remember as far back as Chapter 7), using the [LoadOverworldFaces] text command tells the game to read for events until it hits the next SCRO code. There are a few other text codes for world map events:

TEXTBOXTOTOP
TEXTBOXTOBOTTOM
REMOVETEXTBOX

All three of them should require no explanation.

HIGHLIGHT area

Defined area values: LyciaArea, IliaArea, EtruriaArea, WesternIslesArea, BernArea, SacaeArea, NabataDesertArea, DreadIsleArea, AreaNearPherae

This is the highlight command from the opening world map event that runs through all the countries. It makes the select country area grow (hardcoded to take those shapes, I’m afraid).

FADETOWM [X,Y] map 0x00 0x00

This is used to transition to another world map. It’ll fade right in. Once again, make sure that your co-ordinates are multiples of 8 to avoid any weird camera effects.

_0xC1 [X,Y] Speed 0x00

This command will pan the camera across the world map to location X,Y. Speed can be any value between 0x01 and 0x04. Exceeding 0x04 will cause the camera to glitch.

RIPPLE [X,Y]

Another simple code for the ripple effect.

_0xCA

This code will stop a ripple effect.

Now we’ll start getting into the more interesting stuff. Once you’re finished, you’ll simply use this macro followed by an ENDA:

EndWorldMap

Objects

This is where things start to get a bit more interesting.

PLACEDOT objectID [X,Y] palette

Defined palette values: RedDot, BlueDot, HoleDot, DarkBlueDullDot, DarkBlueNoBorderDot

Notice the objectID; think of it as akin to the eventIDs and conditionIDs we’ve already learned about, just for world map objects. Portrait object IDs sprite object IDs and dot IDs appear to be separate, so you can load a portrait into ID 0x03 and a sprite into 0x03 at the same time if you like, as well as a dot with ID 0x03.

Beyond just the dot, we can also load map sprites.

PUTSPRITE objectID [X,Y] classID properties 0x00 0x00 0x00

Defined property values: AllySprite, FastSprite, EnemySprite, NPCSprite, GraySprite, CameraFollowSprite

Additionally, you can combine any of those properties by doing this, for example:

AllySprite|FastSprite|CameraFollowSprite

To move a sprite, you’ll simply use another PUTSPRITE code with the same objectID with different coordinates (the last three parameters will all be 0x00). It shall move.

If there’s a way to load a sprite, there has to be a way to remove it.

REMSPRITE objectID time
_ASM0x42 0xB2FB1 //Use this after REMSPRITE because

Often when you want to remove a sprite you’ll also want it to fade to black. This is done via a similar command, and is placed BEFORE a REMSPRITE command.

_0xC2 Allegiance 0x58
Allegiance: 0x1C for ally sprites, 0x1D for enemy sprites, and 0x1E for NPC sprites

The _0xC2 command has a direct effect on ALL sprites of that palette, meaning that any other sprites of that allegiance will also turn black.

After you have used a _0xC2 command you’ll want to turn the palette back to normal, otherwise when you load another map sprite it will be black. To do that, use this command:

_0xC3 Allegiance 0x0

Where allegiance is the same parameter as you saw previously.

Finally, we can also load portraits to the world map cinematics.

SHOWPORTRAIT objectID portraitID position loadWay delay

Defined loadWays: PortraitFacesLeft, PortraitMoveLeft, PortraitMoveRight, PortraitFacesRight

The position is the X-axis coordinate only. You can combine these parameters in the same way you can combine map sprite parameters with a | between each parameter. The delay parameter gives us a built in STAL code. Note that if you have a ripple effect playing out, then you MUST use the command _0xCA to stop it before loading portraits, or else the fade-in effect of the portraits will be ruined.

@Agro’s notes: The “delay” parameter doesn’t seem to be a delay parameter at all. In fact, it always seems to be 0 for vanilla world map events, so you can leave it at 0 if you like.

REMOVEPORTRAIT objectID loadWay delay

The standard removal code. loadWay values are the same as SHOWPORTRAIT’s, just remember to use the same objectID as when you loaded the mugshot.

1 Like

Epilogue

And that’s a wrap for the fourth edition of my tutorial. It’s quite long, I know, but hopefully it does the job of teaching events well enough. Take what is useful to you, leave the rest.

As always, you can reply to this topic with any feedback or corrections for the tutorial.

1 Like

I would suggest putting this bit of trivia along with the Event ID that triggers music change in this section:

So I don’t have to search for it every time I forget.

Mind that in FE8 it’s different.
A huge number of event IDs is used by world map events.
I don’t have all of them documented unfortunately, but I’m pretty sure that events from 0x40 aren’t safe.

Warping in enemies. How do I do it?

EAstdlib Macro and Command List:

I take it the second command is for generics/pointer to unit data for many enemies? (What’s with the X,Y then – do I have to warp in one unit at a time, and what do the X and Y in the UNIT data do then…?)

I’m currently working on updating the tutorial to match the changes in EA 10.0. If there’s anything else that’d be helpful to add or anything that you notice is outdated, just give me a heads up and I’ll address it.

1 Like

Here are the leftover tidbits that I had on FE8 (I figured that with the new tutorial being written that I would take them out of mine in order to make the tut shorter):

FE8 Units

While FE6 and FE7 use pointers for “Bad” units to put enemies on prep screen maps, in FE8, any enemies loaded prior to the preparations screen will appear (that’s a major space saver, trust me).

UNIT characterID classID leader Level(#,side,autolevel?)  [X,Y] flags 0x00 amount REinforcementDAta [Item 1,Item 2,Item 3,Item 4] AI
  • characterID and classID can be found in the EAstdlib, or in the Nightmare Modules’ character editor (don’t forget that you can define names yourself!).
  • The “leader” is the character that the auto-cursor goes on, and the character that appears as the Army Commander in the Status screen. The character that is the leader should have 0x00 as his value for that byte.
  • The level part included works with the Event Assembler. Level(10,Ally,False) tells the EA I want a Level 10 Ally with no autolevel. To use autolevel, type the word “True.” Possible value for side are “Ally” “Enemy” or “NPC.”
  • Unlike FE7 & FE6, there is only one set of coordinates. These are the coordinates your unit appear on when loaded.
  • For flags, we only know of two values (both defined by the EAstdlib). “MonsterTemplate” makes the unit function like a unit in the Tower/Ruins. “DropItem” makes the last item drop-able upon death.
  • amount is the…amount of REDA’s (REinforcement DAtas) the unit has. This will make more sense when REDAs are explained in a bit.
  • The pointer to a unit’s REDA’s.
  • Items are pretty self-explanatory, you can only specify four (not five, which is the maximum # of items holdable).
  • Values for AI can be found with the Chapter Unit Editor Nightmare Modules. There are definitions for AI combos in the EAstdlib for FE7.

So, let’s go over REDAs. In FE7 & FE6 you specify two coordinates. Coordinates for a unit to load on and then a second set that the unit instantly moves to upon loading. FE8 handles this very differently.

REDA [X,Y] Speed Rescuer Delay

You can have a series of REDA codes, making specific complex movements quite possible. These also enable units to rescue one another; when not rescuing, however, the Rescuer parameter should be 0x00. Speed handles the unit’s movement speed, and Delay is just, ya know, putting a delay before the movement is executed.

Here’s an example:

MagvellianKnights:
UNIT Forde Cavalier 0x00 Level(1,Ally,False)  [9,8] DropItem 0x00 0x02 FordeMove [SilverSword,0x00,0x00,0x00] NoAI
UNIT
.....
FordeMoves:
REDA [12,3] 0x5 0x00 0x20
REDA [10,4] 0x1 0x00 0x00

Scripted Fight Sequences: FE8

Fights work somewhat differently than FE7. The FIG1 command triggers a fight, it does not contain a pointer to a fight command. Instead you specify what happens in the fight directly before the FIG1 command. Here’s an example:

CMDS
NormalDamage(CombatantNumber,damage)
NormalDamage(CombatantNumber,damage)
EndBattle
FIG1 Attacker Defender

FIG1 starts the fight with animations on. Alternatively you can use FIG2 for map battles (everything else between the two codes is the same).

CMDS begins the listing for the fight commands. Always have it before your list of battle actions.

NormalDamage(combatant,damage)
CriticalHit(combatant,damage)
MissedAttack(combatant,damage)
Silencer(combatant,damage)
SureShot(combatant,damage)
Pierce(combatant,damage)
BigShield(combatant)
EndBattle

Each battle action triggers one attack, the code I used above has only two attacks. Theoretically you can have many more attacks for a death-match of sorts. Be sure to end your action list with “EndBattle” as shown above.

For the value of the combatant, you can use 0 for the fighter on the left or 1 for the fighter on the right. For the HP value you can leave it as 0 to do damage normally. If you input any other numeric value, that is the damage that will be dealt by the attack. Big Shield’s effect does not automatically apply, so you need to trigger the animation, then have the following attack by the opponent deal severely reduced damage. Since 0 tells the game to apply damage normally, doing 1 damage would be the only way to semi-replicate the effect.

Special thanks to Mage Knight 404 for his great documentation of FE8 fights, and to @CT075 for the creation of the FE8 fight macros.

Cursor Flash

Note for FE8: The CURF command doesn’t exist in FE8. This macro was created for FE8-users to give them an easy-to-use cursor command.

FlashCursor(X,Y,time)
FlashCursor(char,time)

time can be set to anything, but 60 is equivalent to FE7/FE6’s automatically-timed cursor.

1 Like