Give me units to play with!
The standard UNIT command looks like this:
UNIT unitID jobID leader level [stX, stY] [endX, endY] [inventory] AI
Of course, to make things more confusing, these don’t actually go into scene data. It’s okay though, the game provides a default unit array (or “unit group”, as I may accidentally refer to it as) for you to put both “Good” (player) and “Bad” (enemy) units into! However, for our scene, let’s put units into a different array, because why not?
PlayerUnits:
UNIT Eliwood EliwoodLord 0x0 Level(5,Ally,false) [14, 12] [14, 12] [Rapier, Vulnerary] NoAI
UNIT Hector HectorLord Eliwood Level(5,Ally,false) [14, 8] [14, 8] [WolfBeil, Elixir] NoAI
UNIT Lyn LynLord Eliwood Level(5,Ally,false) [12, 9] [12, 9] [ManiKatti, Vulnerary] NoAI
UNIT
Whoa, whoa, slow down, a lot of things just happened. The first thing to note is my use of definitions (really a form of macro) to load “Eliwood” instead of “0x1”. On the same note, there’s an actual macro in the form of Level(5,Ally,false)
. This does what you’d expect; it loads a level 5 ally (it accepts “Ally”, “Enemy” and “NPC”), but what does false mean? The third parameter in Level macro is “autolevel”, it takes “true” or “false” (if you’ve played with Nightmare a bit, you should know what that means). Next up are the loading and final coordinates. What this means is that the unit will spawn at the first pair of coordinates and move to the second pair (where they’ll stay until they’re commanded to move again). While in this case it doesn’t matter, it’s useful to make units (say, enemies) seem like they’re all, say, leaving a building or something. Inventory is self-explanatory (it holds up to four items; supplying less than four is allowed). For AI, there are a series of AI definitions in EAstdlib, I’ve provided them for reference below.
//AI helpers
#ifdef _FE6_
#define NoAI [0x00,0x00,0x00,0x00]
#define AttackInRange [0x00,0x03,0x09,0x00]
#endif
#ifdef _FE7_
#define NoAI [0x00,0x00,0x00,0x00]
#define PursueWithoutHeed [0x00,0x02,0x02,0x00]
#define GuardTile [0x03,0x03,0x09,0x20]
#define Guard [0x00,0x03,0x00,0x20]
#define AttackInRange [0x00,0x03,0x09,0x00]
#define DestroyVillages [0x00,0x04,0x01,0x00]
#define HealUnits [0x0F,0x04,0x00,0x00]
#define StealFromUnits [0x10,0x05,0x09,0x00]
#define StealFromChests [0x06,0x05,0x09,0x00]
#define TalkToLord [0x06,0x0B,0x0A,0x00]
#define AttackWall [0x00,0x1B,0x01,0x00]
#define SeizeThrone [0x00,0x1E,0x00,0x00]
#endif
#ifdef _FE8_
#define NoAI [0x00,0x00,0x00,0x00]
#define SummonMonsters [0x14,0x03,0x09,0x00]
#endif
This should all be very familiar for those of you who’ve used the Chapter Unit Editors (or Army Editors, as some older versions are called); that’s good, because those modules are actually just editors for this data! Keep that in mind, because your chapter unit editors won’t work anymore after assembling these events.
The last thing to note about this group is that, similar to our TurnEvents array, we end with an empty UNIT.
Finally, the command to load units is LOU1
(followed by ENUN
, which means to wait until units stop moving); this would qualify as “something happening”, so that goes in your scene (opening scene, in this case). While we’re at it, let’s make and load some enemies. Here’s the whole file once we’re done with that, for reference:
// Template written by CT075, based off the original by markyjoe
#ifndef _FE7_
ERROR This file is meant for FE7!
#endif
#define DISABLE_TUTORIALS
#include "EAstdlib.event"
#include "FE7 Definitions.txt"
EventPointerTable(0x6, Pointers)
ORG offs
// The pointer array for the chapter
// Warning: Don't edit this!
Pointers:
POIN TurnEvents
POIN TalkEvents
POIN LocationEvents
POIN MovementEvents
POIN MapData MapData
POIN Bad Bad Bad Bad
POIN Good Good Good Good
POIN OpeningScene EndingScene
// Units
Bad:
UNIT Batta Brigand 0x0 Level(6,Enemy,false) [3, 16] [3, 16] [IronAxe] GuardTile
UNIT 0x88 Brigand Batta Level(6,Enemy,true) [8, 7] [8, 7] [IronAxe] AttackInRange
UNIT 0x88 Brigand Batta Level(6,Enemy,true) [2, 12] [2, 12] [SteelAxe] NoAI
UNIT 0x88 Brigand Batta Level(6,Enemy,true) [12, 3] [12, 3] [IronAxe] AttackInRange
UNIT 0x88 Brigand Batta Level(6,Enemy,true) [13, 14] [13, 14] [IronAxe] NoAI
UNIT 0x88 Brigand Batta Level(6,Enemy,true) [7, 17] [7, 17] [SteelAxe] AttackInRange
UNIT
Good:
UNIT
PlayerUnits:
UNIT Eliwood EliwoodLord 0x0 Level(5,Ally,false) [14, 12] [14, 12] [Rapier, Vulnerary] NoAI
UNIT Hector HectorLord Eliwood Level(5,Ally,false) [14, 8] [14, 8] [WolfBeil, Elixir] NoAI
UNIT Lyn LynLord Eliwood Level(5,Ally,false) [12, 9] [12, 9] [ManiKatti, Vulnerary] NoAI
UNIT
// Trigger arrays
TurnEvents:
TurnEventPlayer(0x0, OpeningScene, 1)
TURN
TalkEvents:
CHAR
LocationEvents:
LOCA
MovementEvents:
CauseGameOverIfLordDies
AFEV
MapData:
BLST
ALIGN 4
// Scene data
OpeningScene:
Text(0x2, 0x0813) // Load text at FEditor index 0x0813 with house background
REMA // Clear faces
LOU1 PlayerUnits Bad // Load all units
ENUN // Wait for unit movement to end
ENDA
EndingScene:
ENDA
MESSAGE events end at offset currentOffset
I’d recommend you glance at that for a bit to gain your bearings (although, if you’ve been following along, there shouldn’t be too many changes from the last step). Notice how, even though it’s empty, our POIN array still has Good
listed, and doesn’t have anything for PlayerUnits
. This is not a mistake and is very much intentional; you should never adjust the POIN array unless you know very well what you’re doing.