Welcome, reader, to Event Hacking for Dummies (Arch's third event tutorial)! Since you’re reading this, you obviously want to learn events (or clicked here by mistake looking for porn, but you’ve probably closed the window already if that was the case). This tutorial is designed to give you the tools you need to make fully-customized Fire Emblem chapters of your very own! Before we begin, here’s a list of tools you’re going to need:
A GBAFE ROM. (But if you didn't know that you should probably stop reading...)
Make sure you’ve got all of these readily accessible as you read through the tutorial. With that said, let the learning begin! But before that, a quick heads-up. Learning events should not be your first foray into the realm of FE hacking. I'm not going to explain basic ROM hacking terminology in this tutorial (I don't feel I should have to). If there's a term you come across that you don't understand, look it up or ask someone. I'm expecting that you've at least played with the Nightmare Modules a bit.
Vocabulary
Before we embark on our quest to use the Event Assembler, I'd like to go over some vocabulary. Some of this is basic hacking terminology, some of it is exclusive to the Event Assembler. I'd hope that the more basic terms are ones you're already familiar with, so I'm not going to go in-depth explaining things.
Variable: An integer with some value. Variables can be manually defined with words to make translation between what the game recognizes and what humans recognize easier (using one of the EA's features).
Parameter: A value selected by a user that modifies the code's effect. Parameters will always be variables.
CODE Parameter1 Parameter2 Parameter3
Pointer: Points to a data location in another part of the file. Pointers are found in GBA ROMs, as well as within event files themselves. Pointers within the event files are mostly handled through a labeling system (defined below). However, raw pointers may be used.
Label: Placed before a series of event codes as a reference-point for a pointer.
Label1:
CODE Parameter
CODE Parameter
ENDA
If Label1 is referred to in the event file, this code will be pointed to by the game.
Raw Code: The basic form of data written for the Event Assembler. This is raw code:
TEX1 0x0815
REMA
ENDA
Macro: A more user-friendly feature, which translates strings of raw code into easy-to-understand text. This is the above raw code with macros added:
Text(0815)
ENDA
Comment: A comment in the Event Assembler is denoted by two slash signs, '//'. The EA will ignore all text after // on a given line. You can also use /* and */ (the first starts a comment, the second ends it).
Text(0815) //Everything after this is ignored by the EA. I like cake more than pie, and the EA can't respond to the greatest debate mankind has ever known! BWAHAHAHAH!
MNCH /* Comment in-between code? Yesz! */ 0x05
Edited by Optimus OVERTROLL, 26 March 2011 - 03:31 PM.
The first step towards creating your fully-customized chapter is inserting a map. You need the map to do your events, get coordinates and such. I’ve never tried to do events without the chapter’s map, but I can’t imagine it’s any fun (you can try though, and tell me how much longer it takes).
What we’re going to need for this lesson is Nintenlord’s .MAR Inserter, and a .MAR file. “How do I get a .MAR file, Arch?”
Spoiler (Step 1: Get the .MAR File)
Open your map (should be a .FMP file) in Mappy, then click the “File” dropdown-menu and select the option “Export...” Put a check-mark in the box labeled “Map Array (?.MAR)” and click “Ok.” Your .MAR file has been created! Be sure to note the size of the map (X,Y), it's important for the next step.
Spoiler (Step 2: Insert the Map)
Open up Nintenlord's .MAR Inserter, it should look like this.
The first two are pretty self-explanatory. Pick your ROM and .MAR file. The coordinates you should have gotten from the map like I told you. Here's the catch though: take those coordinates and add one to them for your input. Finally we'll choose our offset, this is the location where the tool will write the map. If you're learning events and don't know what offsets are, I'd suggest you look it up or ask someone else (I mentioned before that I'm not explaining basics like offsets, this is your last warning of that).
Where to write your shiny new map? In FE7, there's a bunch of free space beginning at offset 00D00000. I personally like to write my maps in the 00DA0000 area (from offset DA0000 and onwards basically). However, you write the maps where you want. It's your ROM, organize it however you'd like.
Spoiler (Step 3: Tell the ROM where the map is)
Step 3 involves using Nightmare. Load your ROM in Nightmare and then find the FE# Event References.nmm module and open it. Here's what you should see:
The "Pointer" is going to point to the offset of our maps. My screenshot already has the Prologue Map pointing to 00DA0000 (notice that the first two 0s are replaced with 0x8, that's part of what pointers are). Once that's taken care of we need to open the Chapter Data Editor.nmm to edit the tileset that the game uses for your chapter.
Spoiler (Step 4: Specify the Tileset)
Step 4 is to edit the tileset (just in case you didn't read the spoiler tag's label). You'll see these four labels with drop-down menus:
Edit those to suit the tileset of your map. Once that's completed your map is officially ready to go!
Luckily for you, the basic event setup has already been made. There is a template in the EA download for FE7, but there are also templates for the other two GBAFE games.
Spoiler (FE7 Template)
//Made by markyjoe1990 of Youtube
//Modified by Nintenlord
#define DISABLE_TUTORIALS
#include EAstdlib.event
EventPointerTable(0x??,ThisChapter)
ORG 0x????????
ThisChapter:
POIN Turn_events
POIN Character_events
POIN Location_events
POIN Misc_events
POIN BallistaData BallistaData
POIN Bad Bad Bad Bad
POIN Good Good Good Good
POIN Opening_event Ending_event
Bad:
UNIT
Good:
UNIT
Turn_events:
TURN
Character_events:
CHAR
Location_events:
LOCA
Misc_events:
CauseGameOverIfLordDies
AFEV
Opening_event:
ENDA
Ending_event:
MNCH 0x??
STAL 1
_0x1
ENDA
BallistaData:
BLST
ALIGN 4
MESSAGE Events end at offset currentOffset
//The map for this chapter is at offset: ????????
Spoiler (FE6 Template)
//Made by markyjoe1990 of Youtube for FE7
//Modified by Nintenlord
//Modified further by Arch for FE6
#include EAstdlib.event
EventPointerTable(0x??,ThisChapter)
ORG 0x????????
ThisChapter:
POIN Turn_events
POIN Character_events
POIN Location_events
POIN Misc_events
POIN Bad Good
POIN Ending_event
Bad:
UNIT
Good:
UNIT
Turn_events:
TurnEventPlayer(0x00,Opening_event,1)
TURN
Character_events:
CHAR
Location_events:
LOCA
Misc_events:
CauseGameOverIfLordDies
AFEV
Opening_event:
ENDA
Ending_event:
MNCH 0x??
STAL 1
_0x1
ENDA
MESSAGE Events end at offset currentOffset
//The map for this chapter is at offset: ????????
Spoiler (FE8 Template)
//Made by Camtech075 of SerenesForest
#include EAstdlib.event
EventPointerTable(0x??,ThisChapter)
ORG 0x????????
ThisChapter:
POIN TurnBasedEvents
POIN CharacterBasedEvents
POIN LocationBasedEvents
POIN MiscBasedEvents
POIN Dunno Dunno Dunno
POIN Tutorial
POIN Ballista1 Ballista2
POIN Units1 Units1
POIN $0 $0 $0 $0 $0 $0
POIN BeginningScene EndingScene
TurnBasedEvents:
TURN
CharacterBasedEvents:
CHAR
LocationBasedEvents:
LOCA
MiscBasedEvents:
AFEV
Dunno:
//DO NOT TOUCH
CODE $00
Tutorial:
//DO NOT TOUCH
CODE $00
Ballista1:
BLST
Ballista2:
BLST
ALIGN 4
Units1:
UNIT
BeginningScene:
ENDA
EndingScene:
STAL 0x01
MNCH 0x__
ENDA
MESSAGE Events end at offset currentOffset
Pick whichever template you need for the game you're hacking.
However, just because the template is already made doesn't mean we aren't going over it! The first few lines are dominated by comments. For FE7, the first thing of significance is DISABLE_TUTORIALS, which, as you've hopefully guessed, disables FE7's tutorials. Next we have "#include EAstdlib.event," which tells the Event Assembler to include the Event Assembler Standard Library of macros and labels. I would highly suggest keeping this in your event files.
Now we delve into "EventPointerTable(0x??,ThisChapter)." This goes back to the FE# Event Refences Nightmare Module we learned about in the last chapter. In the folder where the Nightmare Module is, you'll find a file called "Pointers.txt." Let's say I'm doing my hack's Prologue Events, Pointers.txt says "0x06 Prologue Events." Therefore, I'll replace 0x?? with 0x06. I'll include the lists below for easy reference.
NOTE: This array of pointers references a lot of things. Object Sets, Tile Configurations, Map Palette, Tile Changes, Maps, and Events. The latter three are the only ones this tutorial will be covering.
Next thing on our template should be "ORG 0x????????." This is going to tell the Event Assembler where to write our events. 0x???????? should be replaced with an offset of your choosing. Note that I prefer to start my events at D80000, but it's up to you where your write events.
Below our ORG is a series of POINs. This is the pointer array, which is the beginning of each chapter's data. This array points to various parts of our chapter's events. The POINs vary between the three GBAFE games; but all three pointer arrays contain pointers to units, turn events, character events, location events, and miscellaneous events. That sounds like a good transition into talking about those parts of our events!
However, before we go on to making your events I'd like to cover one of the Event Assembler's handy features. In the last chapter I mentioned the Event Assembler Standard Library. The "EAstdlib" is a compilation of various macros and definitions. What are macros and definitions?
They're what allow me to turn code like this:
CHES 0x00 0x6C [2,4] 0x14
Into code like this:
Chest(Elixir,2,4)
The latter seems a lot simpler and easier to remember, right?
The EAstdlib comes bundled with every download of the Event Assembler. It contains a plethora of macros and definitions for you to use (I will be covering a lot of those macros in this tutorial). However, most people would like to make their own custom sets of definitions to match their hack. You can define Character IDs with your hack's character names, you can pretty much define anything. What's important is a definitions file. Notice in the template it has the line "#include EAstdlib.event"? Below that, in your own event files, you can put "#include yourdefinitions.txt" (obviously the file name is changeable) to tell the Event Assembler to read your own set of definitions!
Spoiler (Making Your Own Definitions File)
Make a new .txt file, name it whatever you desire.Open up your newly created text file, it is (hopefully) blank.
The to make the definitions we need to write the following code.
#define (name) (value)
The name is the word you want to define and the value is the value in hex. Here's a screenshot from my 'BSFE7_Definitions.txt' file (used for Elibian Nights).
Remember, the file can be named whatever you like so long as it matches the name in the "#include filename.txt" part of your events. Have fun defining! It makes the life of an event-crafter's life much much easier.
If your familiar with your game's respective Chapter Unit Editors, you'll have this down really quickly. 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.
Spoiler (FE7 & FE6 Units)
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. Now let's cover actually coding our units.
UNIT *Char ID* *Class ID* *Leader char* Level(#,side,autolevel?) [Loading position X, Loading position Y] [Starting position X, Starting position Y] [Item 1, Item 2, Item 3, Item 4] [AI 1, AI 2, AI 3, AI 4]]
A few things to cover.
Char ID and Class ID can be found in the EAstdlib, or in the Nightmare Modules txt files (just browse around, I'm sure you can find them on your own).
The "Leader Char" 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."
There are two sets of coordinates. The "loading" coordinates are where the unit first appears. The unit then moves to the "starting" coordinates. 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 though (not five, which is the maximum # of items holdable).
Values for AI can be found with Nightmare Modules. There are definitions for AI combos in the EAstdlib for FE7.
Here's an example of a batch of my units.
Knights:
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 Empty
Notice that I ended the list with "UNIT Empty." That tells the game to stop loading units, which is pretty important. Also notice the label above our group of units, "Knights." Those labels are used to refer to the unit group.
You can have as many groups of units as you like, there is no limit. There is a limit to how many units can be in one group, however. I've never recorded the limit (I've only hit it once), but I'd advise a maximum of 40 units per group (that should be more than enough for most circumstances).
Spoiler (FE8 Units)
The POIN arrays provide pointers to "Good" units. For chapters that do not use the preparations screen, those pointers are useless (but you should point to your allies anyways, just because it's a good habit). 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. However, FE6 and FE7 have a pointer to "Bad" units that appear in the map preview on the preparations screen. In FE8, any enemies loaded prior to the preparations screen will appear (that's a major space saver, trust me).
UNIT *Char ID* *Class ID* *Leader char* Level(#,side,autolevel?) [Loading position X, Loading position Y] *Flags* *Byte1* *Amount* *REinforcement DAta* [Item 1, Item 2, Item 3, Item 4] [AI 1, AI 2, AI 3, AI 4]
A few things to cover:
Char ID and Class ID can be found in the EAstdlib, or in the Nightmare Modules txt files (just browse around, I'm sure you can find them on your own).
The "Leader Char" 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."
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 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.
For Byte1, you will always use 0x00. It's unknown what this value does, but it doesn't appear to affect anything significant.
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 though (not five, which is the maximum # of items holdable).
Values for AI can be found with 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) (Rescuing character) (Delay before executing)
This is the format for our REDAs. You can have a series of REDA codes, making complex movements quite possible.
Here's an example of an FE8 unit.
Knights:
UNIT Forde Cavalier 0x00 Level(1,Ally,False) [9,8] DropItem 0x00 0x02 Forde_Move [SilverSword,0x00,0x00,0x00] [NoAI]
UNIT Empty
...
Forde_Move:
REDA [12,3] 0x5 0x00 0x20
REDA [10,4] 0x1 0x00 0x00
Notice that I ended the unit list (which, in this case, was just one unit) with "UNIT Empty." That tells the game to stop loading units, which is pretty important. Also notice the label above our group of units, "Knights." Those labels are used to refer to the unit group.
You can have as many groups of units as you like, there is no limit. There is a limit to how many units can be in one group, however. I've never recorded the limit (I've only hit it once), but I'd advise a maximum of 40 units per group (that should be more than enough for most circumstances).
Continuing to explore the POINs and what they reference to, let's turn our attention to Turn Events. Turn Events are, as the name implies, events that occur on specific turns.
Those are the only four codes that will go under the Turn Events section of your events.
The pointer will be the name of the event you want to occur on that turn.
For the 1st and 3rd codes, turn is the turn you want the event to occur on. This event will only occur on that turn, and will only occur once.
The 2nd and 4th codes listed allow for an event to recur multiple turns. startTurn is the turn the event begins to occur, endTurn is the turn the event ceases to occur (after endTurn the event will not occur again).
Simple to understand, right?
These codes, however, are introducing an important concept: the Event ID. The Event ID is the ID# of an event, the game checks to see if ID# has occurred or not. If an Event ID has already been triggered, it stops the game from triggering the same event twice. Event IDs 0x01 and 0x02 are used by the game, but any other value. There will be a lesson later on manipulating Event IDs, however this much information should suffice in the beginning stages of event hacking. For Turn Events, due to the way they're set up, (with the startTurn and endTurn) we don't need an Event ID to check whether the event has occurred to prevent it from reoccurring. For Turn Events you can simply use 0x00 for your Event ID. However, the Event ID will be important from this point forward.
NOTE: In the FE6 Template, Opening_event is not a POIN. The template instead specifies the opening event with a Turn Event. This is always done in FE6. For FE7 and FE8, this is done when chapters do not use the preparations screen.
Here's an example of Tale 1's Turn Events from Elibian Nights.
Notice that I ended the list with "TURN" (no parameters). That tells the game that the list has ended, and to stop reading for turn events (much like "UNIT Empty" does for units).
Spoiler (Note about Opening Events)
In all FE6 chapters, and in FE7/FE8 chapters that don't use the preparations screen, the Opening Event is specified as a turn event, like so:
TurnEventPlayer(0x00,Opening_event,1)
In FE7/FE8, chapters with the preparations screen will load events before the battle preparations. These events are specified in the POINs.
The next type of events we'll cover are called "Character Events." Now, I've personally just referred to them as "Talk" events.
Here are the three codes (only three!) that will go under you Character Events List.
CharacterEvent(eventID,pointer,char1,char2)
CharacterEvent(eventID,pointer,char1,char2,aftereventID) //Doesn't work in FE6
CharacterEventBothWays(eventID,pointer,char1,char2)
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).
CharacterEventBothWays is the exception, it automatically makes it so both characters specified have the 'Talk' command.
By adding the extra parameter to CharacterEvent (aftereventID), you can tell the game to not allow the 'Talk' command to appear until after a certain Event ID is triggered. Something to note though, let's say I want event 0x3A to trigger the 'Talk.' For aftereventID, instead of 0x3A I would just put 3A (just drop the 0x for this value).
These events are pretty simple to understand. Here's an example of one of my Character Event Lists.
Just like with the Turn_events list, we're ending our Character_events list with "CHAR" (no parameters).
Spoiler (Further Explanation of Event IDs (in case you're having trouble grasping the concept))
Notice that Character Events, unlike Turn Events, have actual values for the eventID. Consider the eventID to be like a switch with two positions: On and Off. When considering triggering an event, the game will refer to it's Event ID. If the switch is in the Off position (i.e. the event has already been triggered once), the event won't occur. If it's in the On position, you're clear. After an event has been activated the event ID's switch will go to the Off position.
Each event should have a different Event ID, unless you want only one of # events with the same ID to occur.
That should wrap things up quite nicely with Character Events!
By now we're hopefully getting a strong hold on the basics (Event IDs and pointers). So now let's cover Location Events. If you've been understanding the past two lessons, it shouldn't be too difficult (Location Events have the most codes to memorize though).
"nameofevent" works exactly the same as referencing a unit group with LOU1 (it's a pointer), it points to the data in the events that we need to trigger for this village event.
Here's an example for you.
Village(0x24,South_village,14,33)
In addition to villages, we also have houses which can be revisited.
As you should notice it follows the same basic setup as a village event. You can not include the nameofevent, which will result in it simply loading the event specified as the ending event. That would look like this:
Seize(event#,x-coordinate,y-coordinate)
Spoiler (Chests & Doors)
Another fun location event is a Treasure Chest. There are two different formats you can use for a chest event. A chest where you get an item or a chest where you get money.
Now, this one differs a bit. The pointer to the shop data will not be within the event file. And so, you have to use a pointer you make yourself to point to. For example I put my shop data at 0xD80000, my code would look like this.
Armory(0xD80000,x-coordinate,y-coordinate)
There are multiple types of shops in the game. For an item shop replace 'Armory' with 'Vendor', for a Secret Shop replace 'Armory' with 'SecretShop'.
However, there is (of course) a way to do this in the assembler.
SHLI (items)
You can have as many items as you want, put them hex values or defined variables. For example...
FE6 doesn't have a BallistaData POIN, nor does it have an array for Ballistae. 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
We've come to the fourth of our five major POIN arrays (each array being a list of events for the five types). Number four is quite easy, and quick to go over: Ballistae.
BLST [XX,YY] type
Coordinates should look quite familiar to you now. "Type" is the only new variable to us, and it's a variable exclusive to Ballistae.
0x34 = Normal Ballista
0x35 = Iron Ballista
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. Here's an example of my Ballistae array:
The ballistae will appear on your map and be fully-functional; however, Archers/Snipers won't automatically mount the ballista at the start of the map. Archers/Snipers will begin using the ballista you placed them on when the Enemy Phase begins for the first time.
Traps
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.
Since traps are so rarely used, it isn't necessary to read this portion of the tutorial until it is required for your hack (if it is even necessary at all).
Spoiler (Fire Traps)
FIRE [X,Y] 0x0 [1,1]
The coordinates are really the only thing a hacker needs to change. For the second pair of numbers, [1,1], [1,1] is the only value that works. The first number is the first tile from the coordinates that the trap affects, the second number is the last tile in a row that the trap hits. The second parameter is the trap's "type," but 0x0 is the only value ever used in the games.
Spoiler (Poison Gas Traps)
A poison gas trap in my hack, Elibian Nights.
GAST [X,Y] Direction [1,1]
Coordinates are the coordinates of the gas trap's tile. Direction is pretty self-explanatory, the direction the poison trap is pointed (values for direction are below). The second pair of numbers, [1,1], function just like the fire trap. [1,1] is the only value that works with this
Finally, the last of our POIN arrays! Misc. Events basically cover everything not covered in the last four arrays. The only tricky thing here is remembering what goes in this list!
The three most common Misc. Events are victory/loss conditions: Defeat All Enemies, Defeat Boss, and Cause Gameover If Lord Dies.
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 Event IDs 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 pointer EventIDofPreviousEvent
This is the "AFter EVent." It triggers an event directly after EventID __ has been triggered. "EventIDofPreviousEvent" is the event that our AFEV will follow. AFEVs have their own Event IDs, so infinite strings of AFEVs would be theoretically possible.
AREA EventID pointer [StartX,StartY] [EndX,EndY]
The last of our Misc. Events 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.
That wraps up our POIN Arrays! Now it's time to get into the nitty-gritty of event making.
Now we've got our arrays all worked out. The arrays tell the ROM where to look for our events, and how our events are triggered. Now it's time to actually code the events themselves. There is a lot to learn in the coming chapter, so be prepared.
Unit Loading & Manipulation
The first basic event I'll cover is loading units. Can't have a chapter without enemies and allies (and a few NPCs here and there), right?
LOU1 UnitPtr
The only parameter is a pointer to the unit data that you're trying to load. Let's provide an example, shall we?
Spoiler (Unit Loading Example)
Cornwell:
UNIT Raven Hero 0x00 Level(10,Ally,False) [3,1] [3,1] [Berveil,SteelAxe,Elixir] [NoAI]
UNIT Empty
.......
Opening_event:
LOU1 Cornwell
Once you've gotten units onto the map, there are a variety of things one can do with them. Moving units is important to constructing scenes:
MOVE Char [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.
In addition to this, one can add a 0x1 as a third parameter to force the unit to walk incredibly slowly.
Unit alliances are also manipulated through events.
TurnAlly(char)
TurnEnemy(char)
TurnNPC(char)
Macros work for FE7 and FE8. These are used for changing alliances in recruitment conversations (or anti-recruitment conversations where allies become enemies/NPCs).
Text
The next most-essential component of our chapters is text. I'm not going to go in-depth teaching actual text editing, this isn't the tutorial for that (besides, it's relatively simple anyways). Here are the codes you'll need to know for text.
Text(textpointer)
Text(textpointer,background)
These macros work for all three GBAFEs, and are in this tutorial because FE8 does some complicated stuff with even ordinary text. For beginners these macros should be enough. These macros load the text specified by "textpointer" and then clear the game's map of all mugs, text, and backgrounds.
Spoiler (Finding "textpointer)
If you're using FEditor for text editing, finding "textpointer" is quite simple.
You see the thing I circled in red, right? That's our textpointer. Here's an example referencing this conversation:
Now, the Text macros automatically fade to black when loading the background. This creates for a smooth transition. You can perform the fade-in and fade-out manually with relative ease.
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 looks sloppy to me, but you can experiment with what looks best to you (it's your game, not mine).
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, change the map entire. Now, when the chapter is loaded it can either go straight to the map or go to darkness. This is a simple option in the Chapter Data Editor.
Opening with "black" gives you the option to load another map (start the chapter on a scenic map), load units so that they're on the map initially, etc. Once you've finished whatever you want to do with the opening darkness, a simple no-parameter code will dispel it.
OOBB
Manipulating darkness is one of the 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 feel by using darkness to properly hide things.
Camera & Cursor Control
The camera is trained to automatically follow unit movement. It will focus on a moving unit as it moves.
CMOF //Turns off the camera's automatic follow.
CMON //Disables CMOF, turns the automatic follow back on.
The camera can be set to look at certain portions of the map quite easily, and this is commonly done.
CAM1 [XX,YY] //Focuses camera on tile XX,YY
CAM1 Char //Focuses camera on a certain character
And the final part of our exploration into camera & cursor control is...cursor control.
CURF [XX,YY] //Flash cursor on tile XX,YY
CURF Char //Flash cursor on specified character
Spoiler (FE8 Note on CURF)
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.
Music
Next to text and units, music is the third most important thing. It's also relatively simple to control.
MUS1 SongValue
This code simply starts playing the music. Not really much to explain. SongValues can be found here:
There are several simple codes to know when it comes to music.
MUEN Time
MUsic ENd, fades out your music. Does not work with FE8!
MUS2 SongValue
MURE Time //No "Time" variable for FE6
MUS2 plays a song, but remembers where the previous song left off. MURE returns to that previous song, exactly where it stopped.
MUSI //Make music quieter
MUNO //Reverses MUSI, making music normal after MUSI's usage.
The comments explain all. MUSI and MUNO are used for Villages/Houses mostly, quieting the map music for those specific types of events. I'm certain they have other uses though.
Items & Money
The final section of this lesson on basic event codes is giving items. These codes are useful for villages and 'Talk' events,
ITGC Char Item //Gives item to character.
ITGV Item //Gives item to current character, used for villages.
ITGM Item //Gives item to the main lord.
Giving money is also useful for these sorts of events.
MONE 0x00 Amount
ENDA
Once your event (village conversation, 'Talk' event, reinforcements, etc.) is over, you need to tell the game to stop reading for events. Just remember to end all of your events with the following code:
ENDA
Opening & Ending Events
One final note about the opening and ending events. These events are just like every other event in terms of how they're composed (they use the same codes I've taught in this lesson). But, a few notes about them anyways.
Opening events in chapters with the preparations screen will need to end with this code, instead of ENDA.
GotoPrepScreen
This naturally only applies to FE7 and FE8, since FE6 loads the preparations screen before any events can run.
Ending events will need to use the following code to load the save screen and force the game to go to the next chapter.
MNCH Chapter
The chapter is...well...the value of the chapter. You can find these values in the Chapter Data Editors for your respective version of GBAFE.
Before we proceed with more event codes, I'd like to make sure we have a firm understanding of what we've currently learned.
#define DISABLE_TUTORIALS
#include EAstdlib.event
EventPointerTable(0x0C,Pointers)
org 0xD80000
Pointers:
POIN Turn_events
POIN Character_events
POIN Location_events
POIN Misc_events
POIN BallistaData BallistaData
POIN Bad Bad Bad Bad
POIN Good Good Good Good
POIN Opening_event Ending_event
Bad:
UNIT Batta Brigand 0x00 Level(2,Enemy,False) [10,2] [10,2] [IronAxe,Vulnerary] [NoAI]
UNIT Empty
Good:
UNIT Eliwood EliwoodLord 0x00 Level(1,Ally,False) [4,2] [6,7] [Rapier,IronSword,Vulnerary] [NoAI]
UNIT Empty
Reinforcements:
UNIT 0x88 Brigand 0x00 Level(1,Enemy,False) [14,4] [13,4] [IronAxe] [NoAI]
UNIT 0x88 Brigand 0x00 Level(1,Enemy,False) [14,4] [15,4] [IronAxe] [NoAI]
UNIT 0x88 Brigand 0x00 Level(1,Enemy,False) [14,4] [14,3] [IronAxe] [NoAI]
UNIT 0x88 Brigand 0x00 Level(1,Enemy,False) [14,4] [14,5] [IronAxe] [NoAI]
UNIT Empty
Turn_events:
TurnEventPlayer(0x00,Opening_event,1) //Specified opening event since there is no prep. screen.
TurnEventEnemy(0x00,ReinforcementsCome,3)
TURN
Character_events:
CharacterEvent(0x06,Talk1,Eliwood,Batta)
CHAR
Location_events:
Village(0x07,Village1,7,10)
Armory(ShopData,8,12)
Seize(0x08,Ending_event,14,4)
LOCA
Misc_events:
CauseGameOverIfLordDies
AFEV
BallistaData:
BLST
ALIGN 4
Opening_event:
LOU1 Good
ENUN
OOBB //Allies are loaded before map is displayed.
STAL 0x20 //Stalls the game for ___ amount of time.
Text(0815)
CMOF //Stops camera from seeing enemy units load.
LOU1 Bad
CAM1 [13,18]
CURF Batta
Text(0816,0x02) //Loads text with background 0x02.
ENDA
Ending_event:
MNCH 0x01
ENDA
Village1:
MUSI
Text(0817,0x02)
ITGV IronSword
MUNO
ENDA
Talk1:
MUS2 TogetherWeRide
Text(0818)
MakeAlly(Batta)
MURE 5
ENDA
ReinforcementsCome:
LOU1 Reinforcements
ENUN
Text(0819)
ENDA
ShopData:
SHLI IronSword SlimSword
MESSAGE Events end at offset currentOffset
Just a heads up. The event assembler basics have (or, should have) been learned by now. The only thing really left is to teach individual codes and what they do. This chapter will cover event codes that you can trigger during the middle of a chapter that affect game-play.
Weather
Changing the weather mid-chapter via events is quite simple. Just use the following code:
WEA1 Weather
The variable "Weather" will be substituted with your desired effect.
All of these variables are defined in the EA Standard Library.
Fog is also similarly simple to control.
VCBF Vision //black fog
VCWF Vision //white fog
To cause fog, simply put a value higher than 0 for "Vision." To reverse inflicted fog, use the code again with 0 as your value for "Vision."
Controlling Enemy AI
You can change the AI of a unit in the middle of a chapter with
CHAI Character AI //Specific-character
CHAI [XX,YY] AI //For generic units
The AI commands are located in the unit making chapter.
You can also use coordinates to specify the character whose AI you wish to change. This is useful for changing the AI of generic enemies.
Tile Changes
Blazer receives all credit for this method, he invented it. You'll make your Tile Changes in another text file separate from your main events, and assemble that file separately.
Format
org 0xC9C9C8+(4*0x59) // - Pointer to tile map changes (change the 0x59)
POIN TileChanges // - puts a pointer to "event" TileChanges
org 0xCB1F00 // - where to place the data for tile changes
TileChanges: // - name of event Tilemap(TileChange#, Top Left X, Top Left Y, Length (# of tiles to right), Height (# of tiles down), TilePointer) // - (Insert as many as you need) CODE $FF // - Needed to end a list of tile changes, do not remove these 3 CODE things CODE $00 CODE $00
TilePointer: // - name of list of tiles to replace old tiles CODE 0x80 0x00 0x00 0x00 // - tiles to use (use the CODE to just insert hex, get the tile #s from reference tilesets or some other method)
You need to add this macro to a definitions file for everything to work properly. Also note that when doing Tile Changes with the EA everything in the Tilemap(...) NEEDS to be in hex. You can convert coordinates to hex with MS Calculator easily.
Things are pretty easy to understand. The TileChange# 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. 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.
When compiling your list of tile changes there is an extremely helpful resource, the Reference Tilesets (FE7 & FE8). Open these up and you'll see hexedecimal values on the top and left. Each tile is two bytes, the top value is the first byte and the left value is the second byte. These tilesets are extremely useful in getting those values (otherwise you have to endlessly count, and counting in hex is no fun). The other thing to know when compiling your lists is that the game handles the information in rows, not columns. What I mean by that is if you have a 2x3 tile change the first two tiles will be the first row, the next two tiles will be the second row and the last two tiles will be the third row.
Vertical Doors & Forcing Tile Changes
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 door code we'll use:
DOOR EventID Pointer [XX,YY] 0x10
The pointer to event is the biggest new thing. You're going to point to an event which triggers the map changes, like so.
DoorRemoval:
MAC1 TCN Status
ENDA
MAC1 forces a tile change. For the second parameter you use the TCN of the tile change you wish to force. For our "Status" variable, 0x00 causes tile changes and 0x08 reverses already triggered tile changes. For MAC1 you will almost always use 0x00.
At the end of the day you're just manually triggering the changes since the game doesn't recognize them due to how tile changes are triggered.
Like a lot of the more advanced tricks (like Vertical Doors in the previous chapter), this requires you to abandon your macros. I teach the macro because of FE8's irritating tendencies with text (and the desire for most things to be synchronized between all the GBAFE games), but the real code behind it is quite simple. The Text(value) macro can be substituted with the code:
TEX1 value
REMA
So, how do we switch a song mid-text? In FEditor, you're going to format the conversation, then split it into two text slots. For this example 0815 will have the first part, and 0816 will have the rest of the conversation. You don't have to reload portraits or anything, just split the text and remember which text slots you've used.
TEX1 0x0815 //The first half of the conversation, pre-music change
MUS1 TogetherWeRide //Changes the song
MORETEXT 0x0816 //Continues the conversation where it left off.
REMA
MORETEXT loads the specified text slot, while keeping the portraits from the previously loaded text.
There are several text codes left to cover.
TEX6 BubbleType [XX,YY] Text
The unique thing about TEX6 is the "BubbleType" 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, though). 0x1 displays the brown scroll bubble used for tutorial explanations and the like. For these two options, coordinates must be specified.
However, 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]
TEX8 loads text with a brown-box in the background, like so. It only works with FE7 and FE8.
This essentially covers the text codes available to all three GBAFE games. However, FE7 has several specific text codes that all have conditions written into them. This is a nice transition into the next chapter, so you may want to read it regardless of whether you mainly hack FE7 or not.
Spoiler (FE7's Specific Text Codes)
These text codes all have one thing in common, they all check to see whether a condition has been met. The outcome of the code (which text is displayed) is all based on whether the condition is met or not. This is the basic idea of condition events, which will be covered in the next chapter. These codes were probably created to simplify commonly used conditions with text, so I suppose we should be grateful that IS's coders got lazy.
TEXTIFEM Text1 Text2
Displays text based on the game's current mode. Text1 is the text shown in Eliwood's mode, and Text2 is for Hector's.
TEXTIFTACTF Text1 Text2
This code is based on the condition of the tactician's gender. Text1 is the text shown if the tactician is male, Text2 is female.
TEXTIFEVENTID EventID Text1 Text2
Checks to see whether the specified Event ID is triggered. Text1 is the text displayed if the Event ID was triggered, Text2 is shown if the Event ID was not triggered.
Something to note, with all three of these text codes you can add "MORE" to the beginning, it works like MORETEXT does with TEX1. For example:
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 [XX,YY]
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. So why is it called "ChapterID?" Well, 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.
Once the scene with your map is finished, if you need to load the chapter's map then use LOMA again with the correct ChapterID value.
Scripted Battles
For our FE6 and FE7 users, scripted battles are quite simple due to Nintenlord's EA Standard Library (which boasts macros for every scripted battle command one could need). However, FE8 does not yet have these macros. FE8 should probably get them soon, but until then FE8-users will have to deal with learning things the old-fashioned way (which isn't terribly harder).
Spoiler (FE6 & FE7 Scripted Battles)
Scripted battles are called with the FIGH code.
FIGH Attacker Defender FightData
Pretty simple, right? Now all you need is your list of commands for the FightData parameter (which is a pointer to elsewhere in the event file).
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:
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 CMDLs.
The CMDL command 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 CMDL list with "CMDL 0xFF 0xFF 0xFF 0xFF" as shown above.
For the value of the combatant, you can use 0x0 for the fighter on the left or 0x1 for the fighter on the right. For the HP value you can leave it 0x0 to do damage normally. If you input a value in hex that amount of damage will be dealt. For the action you have three options: 0x0 is hit, 0x1 is a critical hit, 0x2 is a missed attack. For special actions you will usually have it set to 0x0 for ordinary fights. These are the triggers we know about: 0x08 triggers Lethality, 0x40 triggers Sure Shot, 0x80 triggers Big Shield and 0xC0 triggers Pierce. Please note that Big Shield doesn't necessarily work.
Special thanks to Mage Knight 404 for his great documentation of FE8 fights.
Scripted Map Movement & Other Move Codes
My apologies to the FE8 users out there, but none of these codes currently work with FE8. The following section is for FE7 and FE6 only. Hopefully that will change sometime in the future.
MOVE Char 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?"
Naturally, Nintenlord's EA Standard Library has already simplified this process. Move data is composed of the MOMA command, and these are the available actions.
Spoiler (Movement Actions)
up //Moves the unit up. left //Moves the unit left. right //Moves the unit right. down //Moves the unit down. notice //Shows the exclamation mark of the moving unit's head. speed(newSpeed) //Changes speed. 0x0 for normal, 0x1 for slow. highlight(time) //Highlights the unit for "time" amount of time.
MoveData:
MOMA left left left left
MOMA speed(0x1) left left notice
MOMA speed (0x0)
MOMA right right up up
MOMA down down down
A sample of using "MoveData" for a semi-elaborate series of movement.
REPOS [X1,Y1] [X2,Y2] //Repositions Character based on set coordinates.
REPOS Char [XX,YY] //Repositions based on the character.
This code changes a unit's positioning on the map without "moving" them (a.k.a. they just arrive at their destination without any animations). Great for repositioning things during a fade-to-black, but I've never found much else to use it for.
MOVEMAINC [XX,YY]
Moves the character specified as the "main" character. This code is exclusive to FE7.
Conditions, my friends, are what separate the boys from the men, the girls from the women, 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 this code wouldn't work in the game, obviously. There's a bit more to conditions than just that. There are three major components writing conditions that we have to cover: the Condition ID, ELSE and ENIF.
First, the Condition ID. The Condition ID is somewhat like the Event ID, 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.
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.
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.
Now, let's go over the individual condition codes. There are five main codes that are commonly used while writing events.
IFCA ConditionID Char //If certain character is activating the event.
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 Char //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 ConditionID Char //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 Char //Reverse of IFCA for FE6. FE6 doesn't have IFCA.
These codes are less commonly used, and most of them are game-specific.
Guy getting a line at the beginning of Chapter 17, thanks to IFUF.
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.
ENIF 0x02
You may have noticed in the Lex Brave Axe event from the previous lesson, a new code called "ENUF." This code is one of two (ENUT and ENUF) that are used to manipulate Event IDs for desired effects. In the Lex event, using ENUT to refresh the Event ID makes it so that a random unit stepping on the tile doesn't make it so Lex can't trigger the event. Event IDs, as you should know, are automatically triggered when their corresponding event is triggered.
ENUF EventID
ENUT EventID
ENUF makes it so the Event ID is marked as "unused," and ENUT makes it so the Event ID is marked as "used" (even without triggering the connected event). As you know, once an Event ID is "used" the event cannot be re-activated manually. ENUF can undo this, even if an event was manually activated.
Now, an important fact to recognize is that we can manipulate any Event ID. We aren't restricted to only the Event IDs connected to events in a given chapter.
Event ID is difficult to teach, because everything beyond method is all up to an individual's creativity. ENUF, ENUT, and IFET form a powerful triumverate, with which complex strings of events can be written. What one does with this technique is entirely up to their minds, everyone can apply Event ID manipulation in a multitude of unique and different ways.
- Chapter on ASM Conditions (codes IFAT and IFAF), any knowledge is appreciated! - Final Chapter on cool special effects (Lightning, Earthquakes, CGs, etc.) - Conclusion
After this post, you're all free to make your own posts. Feedback on the tutorial, suggestions, and contributions are greatly appreciated. However, this is not the place for your event hacking questions.
Edited by Optimus OVERTROLL, 26 March 2011 - 03:33 PM.