Jump to content

Reinforcements, conditionals and AI changing in FE8


Vennobennu
 Share

Recommended Posts

I've been poking around in the chapter events for FE8, and I've noticed something about how the game loads reinforcements. Those of you who hack FE8 may know of the strange and complex ways that it loads reinforcements, but from what I've found, reinforcement events only look complex - they're no more so than FE7 reinforcements in practice.

Let's use Chapter 8 as an example:
[spoiler=Chapter 8]On Turn 5, this event is triggered:

label18:
_SETVAL 0x2 0x88B7698
CALL label38
_0x0228 0x7
ENDA

Notice how the _SETVAL 0x2 command specifies a location of the ROM; this is the offset of the unit data of the reinforcements (Two mages and a thief in this case). These reinforcements do not appear in the disassembled chapter events, so yo'll have to edit them with Nightmare.

Anyway, continuing on, we call label38:

label38:
_0x1020 0x4
CALL label27
_0x0228 0x9
_LOAD_WHATEVER 0x1
ENUN
_0x0220 0x9
_0x1020 0x0
ENDA

[...]

label27:
_0x1020 0x1
_0x0220 0x2
_0x0320 0x8
_SETCONDITION 0x0 0xC 0x0
FADU 16
ENIF 0x0
_0x1020 0x0
ENDA

I am pretty sure that the LOAD_WHATEVER 0x1 command is loading units from the offset stored in Memory slot 2, i.e. the value defined from _SETVAL 0x2. It's a form of assembly, essentially.

The rest of the code looks opaque, but here's the deal: The majority of it is generic, and can be used for any reinforcement event in the game. Only a very few parts of it are different for different chapters or events, and even then only for special cases (such as when loading player units or triggering a convo during the event).
[spoiler=For example...]
A different reinforcement event in Chapter 8 goes like this:

label17:
_SETVAL 0x2 0x88B7648
CALL label38
_0x0228 0x7
ENDA

It is exactly the same as the previous event but for where it points to to load units from. They both call to label38 simply to save space.




Here's a slightly different case: In Chapter 10B, the game uses a single turn event to load two sets of reinforcements, one after another:

label24:
_SETVAL 0x2 0x88C30A0
CALL label39
_SETVAL 0x2 0x88C312C
CALL label66
_0x0228 0x7
ENDA

The first CALL is normal:

label39:
_0x1020 0x4
CALL label38
_0x0228 0x9
_LOAD_WHATEVER 0x1
ENUN
_0x0220 0x9
_0x1020 0x0
ENDA

label38:
_0x1020 0x1
_0x0220 0x2
_0x0320 0x8
_SETCONDITION 0x0 0xC 0x0
FADU 16
ENIF 0x0
_0x1020 0x0
ENDA

Notice how these events are identical to the ones used in Chapter 8.


But the second is a little different:

label66:
_0x1927
_SETCONDITION2 0x0 0xC 0x0
_0x1922
_SETCONDITION 0x0 0xC 0x0
CALL label39
ENIF 0x0
ENDA

It adds this bit of code to the usual reinforcement stuff. This, too, can be found unchanged in other chapters. This code is a check for Hard Mode; on Normal and Easy, the related reinforcement won't trigger.

Actual scenes, like Riev's monsters or Ewan's appearance in Chapter 13B, only need label39 or a simple _LOAD1.

I hope these notes will help anybody brave enough to work with FE8 events; in the future I may write on the different ways the game loads reinforcements consisting of player units that do and do not already exist in memory.

Edited by Vennobennu
Link to comment
Share on other sites

good work, i was hoping someone would do this

the more i learn about fe8 events the more i like them over fe7 events

someone should probably make these into macros so we don't have to continually copy paste what amounts to boilerplate code

Link to comment
Share on other sites

What exactly are you trying to show with Reinforcement events in FE8 exactly? That they all follow the same pattern and it can easily be copied? It looks like you're just overcomplicating the entire process.

In my FE8 hack, a typical reinforcment event would look like this:

TurnBasedEvents:
TurnEventPlayer(0x00,BeginningScene,0)
TurnEventEnemy(0x0D,ReinforceArm,8)
TurnEventEnemy(0x0E,ReinforceArm2,3)
TurnEventEnemy(0x0F,ReinforceArm3,5)
TurnEventEnemy(0x10,ReinforceArm3,7)
TurnEventEnemy(0x11,ReinforceArm2,9)
TurnEventEnemy(0x12,ReinforceArm3,11)
TurnEventEnemy(0x12,ReinforceArm3,4)
TurnEventEnemy(0x12,ReinforceArm3,6)
TURN
 
REIN4:
UNIT 0x75 0x09 0x45 Level(15,NPC,True) [8,19] 0b 0x00 0x01 28eREDA [0x1a,0x00,0x00,0x00] [0x00,0x2,0x0,0x00] //MK-I
UNIT 0x45 0x4e 0x00 Level(15,NPC,True) [9,19] 0b 0x00 0x01 29eREDA [0x10,0x00,0x00,0x00] [0x00,0x2,0x0,0x00] //Sol
UNIT Empty
 
 
ReinforceArm:
CAM2 [10,15]
LOU1 REIN4
MUS1 0x3c
FADI 10
Text(0x09eb)
FADU 10
REMA
CHAI 0x54
ENDA
 
 

or this

 
REIN2:
UNIT 0x77 0xa2 0x48 Level(6,Enemy,True) [14,0] 0b 0x00 0x01 24eREDA [0xb1,0x00,0x00,0x00] [0x00,0x0,0x0,0x00] //dog
UNIT 0x77 0xa2 0x48 Level(6,Enemy,True) [15,0] 0b 0x00 0x01 25eREDA [0xb1,0x00,0x00,0x00] [0x00,0x0,0x0,0x00]
UNIT Empty
 
 
ReinforceArm2:
CAM2 [4,13]
LOU1 REIN2
ENDA
Edited by Blademaster!
Link to comment
Share on other sites

CHAI doesn't work either, which is another part of FE8 events that sucks. What does 'CHAI 0x54' mean, anyway?

I mean, it'd be nice if I was wrong and there's an easy way; but the _LOAD 1/2/3 commands are used only during cutscenes, not during actual chapters. For instance, using the _LOAD commands during a chapter causes a fade to black.

On the positive side, I just found out that '_LOAD3 0x0 pointer' pointing at a UNIT list with just one unit in it will load your main lord with the position and allegiance data of the UNIT data at the pointer with their current inventory and stats, even if they're already on the map! I next tried it with a UNIT list with seven units in it, which restarted the game for...some reason.

Link to comment
Share on other sites

Umm I have the same question as Vennobennu, what exactly are you trying to do? I mean I normally bring in reinforcements like he said, though I change the LOU1 to _LOAD1....

I mean, it'd be nice if I was wrong and there's an easy way; but the _LOAD 1/2/3 commands are used only during cutscenes, not during actual chapters. For instance, using the _LOAD commands during a chapter causes a fade to black.

Woah really O_O- This has never happened to me... I think, what do you mean causes a chapter to fade to black? Because I always use _LOAD1 and the chapter plays fine...

Link to comment
Share on other sites

LOU1 doesn't work in FE8 anymore

Why? That sounds silly to take something that worked before and then make it not work (Please understand that the code I posted is years old).

Also, I don't really remember what CHAI 0x54 did. In fact, I don't think it should've done anything basedon the chapter I used that in. Might have been just something I left over on accident when I copied and pasted the code in.

Link to comment
Share on other sites

Woah really O_O- This has never happened to me... I think, what do you mean causes a chapter to fade to black? Because I always use _LOAD1 and the chapter plays fine...

Huh, that's strange. Whenever I try to use _LOAD1 or _LOAD2, the screen fades to black for a moment before going back to normal. And it doesn't automatically pan the camera over the reinforcements like the _LOAD_WHATEVER command does.

Could you share an event where you use _LOAD1 during a chapter? I'd like to see if I'm just making a mistake with my use of it.

Edited by Vennobennu
Link to comment
Share on other sites

I was going to make a post on this a while back when I was working on C6 for FEE3, but I'll just add what I think I know to what you found -- most of this is copied from a text file I made while testing these events.

1) Reinforcement events are almost always set like so (pretty much what you found):

labelA:
_SETVAL 0x2 0xMYPOINT (insert pointer of interest here)
CALL labelB

labelB:
_0x1020 0x4
CALL labelC
_0x0228 0x9
_LOAD_WHATEVER 0x1
ENUN
_0x0220 0x9
_0x1020 0x0
ENDA

labelC:
_0x1020 0x1
_0x0220 0x2
_0x0320 0x8
_SETCONDITION 0x0 0xC 0x0
FADU 16
ENIF 0x0
_0x1020 0x0
ENDA

2) _0x0228 0x7 before ENDA (or immediately after _LOAD1, VCWF, etc.) avoids that annoying black fade-in associated with most functions (LOAD, etc.)!

3) Not sure what first line does, but these lines always seem to be paired. Y is the text ID (from Feditor).
_SETVAL 0x2 0x2
_SETVAL 0x3 0xY

In this next code, 0xFFFF is whatever text ID is set up in the previous code -- i.e.Y from _SETVAL 0x3 0xY.

TEXTSHOW 0xFFFF
TEXTEND

Note that a few varieties of this exist.

4) The below is a character present condition; 0xZ is the condition ID and 0xY is the character ID -- 0x13 is Artur, 0x1 is Eirika (this is from Ch. 4 Lute recruitment), for example. Seems to go right to ENIF is marked as true.

_SETVAL 0x7 0xY
_SETCONDITION 0xZ 0xC 0x7

5) Similar to character present check in #4, but it is used for the AREA events, not villages. In other words, check to see if the character that proc'd the AREA event is the one you're checking for (think Eirika in Ch. 1 FE8 -- she must proc the AREA event for reinforcements to come). Considering what the OP found concerning SETVAL, may be the same thing as #4.

_SETVAL 0x2 0xY
_SETCONDITION 0x0 0xC 0x2

6) The below looks like the "is character dead?" condition; 0xY is the event ID and 0xZ is the condition ID.
_0x0322 0xY
_SETCONDITION 0xZ 0xC 0x0

7) The below looks like the "is this event ID unused?" condition; 0xY is the event ID and 0xZ is the condition ID.

_0x0321 0xY
_SETCONDITION 0xZ 0xC 0x0

8) _0x0221 0xY sets the event ID Y as unused! Note that it is _0x0221, while the conditional to check if an event is unused is _0x0321. This can't be a coincidence.

9) _0x0221 0xFFFF is similar to #8, but it's awesome in that it marks the event ID that was associated with the event as unused. I've manipulated this command for my reinforcements in Ch.6 (which should be shown in FEE3 soon), so I know that this works.

10) I don't yet know what marks an event ID as used. Maybe _0x0220 0xY? (Untested at this point) I NEED TO KNOW. GAH.

Edited by Kngt_Of_Titania
Link to comment
Share on other sites

Sorry didn't see this XD.

Well I inserted these events and I don't really notice a fade to black when it loads units.

#include EAstdlib.event

#include Definitions_SH.txt
EventPointerTable(0x07,ThisChapter)
ORG 0x00EF8820
ThisChapter:
POIN TurnBasedEvents
POIN CharacterBasedEvents
POIN LocationBasedEvents
POIN MiscBasedEvents
POIN Dunno Dunno Dunno
POIN Tutorial
POIN TrapData TrapData
POIN Allied Enemies
POIN $0 $0 $0 $0 $0 $0
POIN BeginningScene EndingScene
ALIGN 4
TurnBasedEvents:
TurnEventPlayer(0x0,BeginningScene,0)
TurnEventPlayer(0x0,Noa_Arrives,2)
TURN
Noa_Arrives:
_LOAD1 0x0 Others
ENUN
FlashCursor(3,0,60) //Flash Cursor on Noa
ENUN
Text(0x912) //Hey what's going on, why are Tyg and Garlan fighting.
REMA
ENDA
ALIGN 4
Allied:
UNIT Tyg Myrmidon 0x00 Level(1,Ally,False) [4,0] 0x00 0x00 0x00 0x00 [ironSword,SlimSword,0x0,0x0] NoAI
UNIT Garlan Fighter Tyg Level(1,Ally,False) [3,0] 0x00 0x00 0x00 0x00 [Hatchet,IronAxe,0x0,0x0] Defend
UNIT
Scene_Units:
UNIT Tyg Myrmidon 0x00 Level(1,Ally,False) [5,4] 0x00 0x00 0x00 0x00 [ironSword,SlimSword,0x0,0x0] NoAI
UNIT Garlan Fighter Tyg Level(1,Ally,False) [3,4] 0x00 0x00 0x00 0x00 [Hatchet,IronAxe,0x0,0x0] Defend
UNIT Noa Archer Tyg Level(1,Ally,False) [4,5] 0x00 0x00 0x00 0x00 [ironBow,ManiKatti,0x0,0x0] Defend
UNIT
Others:
UNIT Noa Archer Tyg Level(1,Ally,False) [3,0] 0x00 0x00 0x00 0x00 [ironBow,ManiKatti,0x0,0x0] Defend
UNIT
Civ_Unit:
UNIT 0x8E 0x6F 0x00 Level(3,NPC,True) [11,8] 0x00 0x00 0x00 0x00 [ironAxe,HandAxe,0x0,0x0] MoveGuard
UNIT
Enemy_Leader:
UNIT ONeill Brigand 0x00 Level(4,Enemy,False) [11,6] 0x00 0x00 0x00 0x00 [ironAxe,HandAxe,0x0,0x0] Defend
UNIT
ALIGN 4
Enemies:
UNIT 0x55 Brigand 0x00 Level(3,Enemy,True) [12,3] 0x00 0x00 0x00 0x00 [ironAxe,HandAxe,0x0,0x0] MoveGuard
UNIT 0x58 Brigand 0x00 Level(2,Enemy,True) [12,2] 0x00 0x00 0x00 0x00 [ironAxe,HandAxe,0x0,0x0] Wait2Turns
UNIT 0x59 Brigand 0x00 Level(1,Enemy,False) [13,2] 0x00 0x00 0x00 0x00 [ironAxe,HandAxe,0x0,0x0] NoAI
UNIT 0x61 Brigand 0x00 Level(1,Enemy,False) [12,1] 0x00 0x00 0x00 0x00 [ironAxe,HandAxe,0x0,0x0] Wait1Turn
UNIT 0x62 Brigand 0x00 Level(1,Enemy,False) [11,1] 0x00 0x00 0x00 0x00 [ironAxe,HandAxe,0x0,0x0] Wait2Turns
UNIT 0x63 Brigand 0x00 Level(1,Enemy,False) [10,1] 0x00 0x00 0x00 0x00 [ironAxe,HandAxe,0x0,0x0] NoAI
UNIT
ALIGN 4
CharacterBasedEvents:
CHAR
LocationBasedEvents:
LOCA
ALIGN 4
MiscBasedEvents:
DefeatAll(EndingScene)
AFEV
Dunno:
//DO NOT TOUCH
WORD $00
Tutorial:
//DO NOT TOUCH
WORD $00
TrapData:
ENDTRAP
ALIGN 4
ALIGN 4
BeginningScene:
FADI 0x20
LOMA 0x40
ENUN
_LOAD1 0x0 Scene_Units //loads guys at beginning
ENUN
Text(0x15,0x90D) //text
REMA
STAL 0x20
MOVE Tyg [14,3]
MOVE Garlan [13,3]
MOVE Noa [12,3]
ENUN
DISA Tyg
ENUN
MOVE Garlan [14,3]
MOVE Noa [13,3]
ENUN
DISA Garlan
ENUN
MOVE Noa [14,3]
ENUN
DISA Noa
ENUN
STAL 0x20
FADI 0x20
LOMA 0x00
ENUN
_LOAD1 0x0 Civ_Unit //Loads civilian
ENUN
REMA
STAL 0x20
FlashCursor(11,8,60) //Flash Cursor on him
ENUN
Text(0x18,0x90E) //text
REMA
MOVE 0x8E [9,9]
ENUN
DISA 0x8E //make civ leave
ENUN
STAL 0x30
_LOAD1 0x0 Allied //Load Tyg and Garlan
ENUN
FlashCursor(4,0,60) //Flash Cursor on Tyg
ENUN
Text(0x18,0x90F) //Text about how they have to go to the beach and back, Noa will catch up
REMA
MOVE Tyg [9,6]
MOVE Garlan [8,5] //Moves them Closer to the beach
ENUN
FADI 0x20
_LOAD1 0x0 Enemy_Leader
ENUN
Text(0x18,0x910) // Text about how they're almost there, then bandits show up
REMA
_LOAD1 0x0 Enemies
MOVE 0x55 [13,5]
MOVE 0x58 [13,8]
MOVE 0x59 [11,8]
MOVE 0x61 [6,0]
MOVE 0x62 [4,2]
MOVE 0x63 [6,4]
ENUN
Text(0x911) //We gotta fight them off
REMA
MOVE ONeill [12,3]
ENUN
ENDA
ALIGN 4
EndingScene:
FADI 0x20
Text(0x18,0x913)
REMA
MNC2(0x01)
ENDA
MESSAGE Events end at offset currentOffset
//The map for this offset is at 00EF86D0

Link to comment
Share on other sites

Well, you're using your _LOAD1 command as part of a scene, which I think is part of why it's working for you-LOAD1 is used during cutscenes in the vanilla game and obviously it doesn't cause fade-ins all the time, but when one tries to use it as its own thing as part of a TURN or AREA code, it does fade. Although, given what KoT just said about _0x0228 0x7, it seems that it is possible to use _LOAD1 anyhwere without problems.

...Which makes me wonder why reinforcements in this game use the _SETVAL method; it doesn't seem to offer any advantages over just using _LOAD1 and labels, at least from what I know of the codes. I do have some ideas as to why it is used:

1) _LOAD1 doesn't work consistently with TURN (and AREA?) triggers.

-PKL has told me that using _LOAD1 to load up reinforcements as a turn event during a chapter causes the reinforcements to either load with the other units at the beginning of the chapter, not load at all, or cause a game over.

2) _LOAD1 doesn't respect the 50 unit cap.

-Perhaps the unknown codes used in the vanilla reinforcement are checks against this and other potential issues.

Anyway, nice job KoT for that data on event commands! I think it will be a great help to anybody making an FE8 hack.

In other news, I think I've found out how to move a unit from a given set of coordinates, instead of by moving a character of a given character ID.

The important bit is this:

[spoiler=Chapter 1 Enemies Deploy]

_SETVAL 0x2 0x89EFC24
CALL label33
MOVE 0x46 [2,2]
_SETVAL 0xB 0x60001
_MOVE 0x18 0xFFFE [1,3]
_SETVAL 0xB 0x60003
_MOVE 0x18 0xFFFE [3,3]
_SETVAL 0xB 0x80001
_MOVE 0x18 0xFFFE [9,5]
_SETVAL 0xB 0x70002
_MOVE 0x18 0xFFFE [8,3]
_SETVAL 0xB 0x80003
_MOVE 0x18 0xFFFE [4,7]
_SETVAL 0xB 0x90002
_MOVE 0x18 0xFFFE [2,8]
ENUN
_0x0E22 0x3C

label33:
_0x1927
_SETCONDITION 0x0 0xC 0x0
_CALL_HELL
ENIF 0x0
ENDA

label33 is called frequently throughout the chapter, which is why it is seperated from the main stream of the beginning scene. I believe that the 0xFFFE may tell the game to load data from the memory slot last used.

In fact, you might be able to use this same method to change the AI of units at a given set of coords too; I'll post here if I can confirm it.

Link to comment
Share on other sites

I did use it as part of a TURN event, here when I load a character on turn 2:

ALIGN 4
TurnBasedEvents:
TurnEventPlayer(0x0,BeginningScene,0)
TurnEventPlayer(0x0,Noa_Arrives,2)
TURN
Noa_Arrives:
_LOAD1 0x0 Others
ENUN
FlashCursor(3,0,60) //Flash Cursor on Noa
ENUN
Text(0x912) //Hey what's going on, why are Tyg and Garlan fighting.
REMA
ENDA
Link to comment
Share on other sites

Huh. Well then I don't know what happened. Maybe having a text event afterwards makes it not fade in? That's the only difference I can find between this:

TurnBasedEvents:
TURN 0x0 label24 [5,0] 0x8
END_MAIN

label24:
_LOAD1 0x0 Extras
ENUN
ENDA

And your event.

Link to comment
Share on other sites

Huh. Well then I don't know what happened. Maybe having a text event afterwards makes it not fade in? That's the only difference I can find between this:

TurnBasedEvents:
TURN 0x0 label24 [5,0] 0x8
END_MAIN

label24:
_LOAD1 0x0 Extras
ENUN
ENDA

And your event.

I was thinking that it's possible that ENUN could be used in place of _0x0228 0x7 (I haven't tested this, it's just conjecture atm), based mainly on the fact that he uses it in locations similar to those I find _0x0228 0x7 needs to be placed as well as the distinct lack of ENUN in vanilla FE8 events that I noticed in certain routines; this may even suggest that _0x0228 0x7 and ENUN serve similar functions.

I don't have time right now (midterm tomorrow), but the theory would be easily tested.

Edited by Kngt_Of_Titania
Link to comment
Share on other sites

I can confirm that the command _0x0229 will mark an Event ID as used. Chapter 10A uses this command to force Marisa's aggro convo to only trigger on the enemy phase following a player unit triggering an AREA event, and for the Falcoknight and Ranger reinforcements to not occur until Marisa's recruitment event occurs.

Thanks to KoT's notes on _SETCONDITION, I've puzzled out an outline of how the game handles AI changes and conditionals:

//From Chapter 10A:

AREA 0x7 label36 [0,19] [19,30] //Aggro Marisa's group
TURN 0xE label25 [1,255] 0x8 //Convo when aggroing Marisa's group

label36:
_SETVAL 0x2 0x0 // Loads value 0x0 into memory slot 2
CALL label60
_0x0221 0xE //Mark Convo event as unused
_SETVAL 0xD 0x0 // Loads New AI? Into Memory Slot 0xD (Could write as _SETVAL 0xD 0x00000000)
_SETVAL 0x1 0x1D000D // Loads coordinates of unit to change (in y,x order) into memory slot 1
_SAVEFORBATTLE // Not sure what this does - it appears in many circumstances. Might change AI?
_SETVAL 0x1 0x1C000E
_SAVEFORBATTLE //Seems to require a value loaded to Memory Slot 1, though.
_SETVAL 0x1 0x1D000F
_SAVEFORBATTLE
_SETVAL 0x1 0x1C0010
_SAVEFORBATTLE
_SETVAL 0x1 0x1D0011
_SAVEFORBATTLE
_SETVAL 0x1 0x1E000E
_SAVEFORBATTLE
_SETVAL 0x1 0x1E0010
_SAVEFORBATTLE
_SETVAL 0x1 0x1E0012
_SAVEFORBATTLE
_SETVAL 0x2 0x1000000
CALL label61
_0x0228 0x7 // Prevents random fadein effects?
ENDA // Go back to parent event - since this event has no parents, this is the end.

label60:
_0x3325 0xFFFF
_SETCONDITION 0x0 0xC 0x2 // If the character ID of the triggering character does not match value loaded in Slot 2...
CALL label38 // Go to label38 - Never happens, as ID 0x0 is nonspecific?
ENIF 0x0 // If it does match, go back to label36
ENDA

label38:
_0x1929
_0x0620 0xC2
_0x0221 0xFFFF //Mark Event ID of event currently activated as unused - Which is our AREA event.
_0x0228 0x7
ENDB // Stop reading this event and its parents and go back to the normal game

label61:
ENIF 0x0
_0x0C44 0x1 0xD 0x0 //Some sort of conditional - not about character ID's?
_0x0620 0x21
_0x0722 0xB
_0x3921 0xFFFF //Perhaps this stuff is used to trigger every unit's AI change?
ELSE 0x0
ENIF 0x1
ENDA


I've figured out how to change the AI of units during chapters. It's actually pretty simple once you break it down into its essential components. Changing the AI of characters is straightforward. You just do this:

CauseAggro:
_SETVAL 0x1 0x1000000 //Loads new AI - Length of one word
_0x3920 0xE //Change AI of character 0xE to value loaded in Memory Slot 0x1
_SETVAL 0x1 0x10000
_0x3920 0x83 // The generic wyvern riders in this chapter use character ID 0x83
_0x0228 0x7 //Stop random fade-in
ENDA

The interesting thing is that _0x3920 will affect all units on the map with the given character ID. This code causes Cormag and his two subordinates to start chasing you even though _0x3920 is only executed twice.

For changing AI of units at given coordinates, it's a little bit complicated, but still easy to implement:

GuardsCharge:
_SETVAL 0x1 0xC0010 //Load value (coordinates YY00XX for us) 0x0C0010 into Memory Slot 1
_SAVEFORBATTLE //Store this value.
_SETVAL 0x1 0xE0010
_SAVEFORBATTLE
_SETVAL 0x1 0xD000F
_SAVEFORBATTLE
_SETVAL 0x2 0x1000000 // Loads new AI, word length - If AI Byte 1 is less than 10, drop the first 'digit'.
CALL AIChangeLoop
_0x0228 0x7
ENDA

AIChangeLoop: //This appears to be a simple loop: it will run until every unit listed has their AI changed.
ENIF 0x0 
_0x0C44 0x1 0xD 0x0 //Sets condition
_0x0620 0x21 //Loads unit at coords?
_0x0722 0xB
_0x3921 0xFFFF //Changes AI of unit currently loaded to value loaded at Memory Slot 0x2. You can use a single loop for multiple AI change events.
ELSE 0x0
ENIF 0x1
ENDA

So in summary:

  • Changing the AI of a character uses _0x3920.
  • Changing AI of a unit at a coordinate uses _0x3921.
  • Character AI changes are done individually; _0x3920 can work with a single input.
  • Coordinate AI changes are done all at once, and need a loop to function - _0x3921 doesn't work by itself.

So that's how you change AI. Pretty interesting, eh?

Edited by Vennobennu
Link to comment
Share on other sites

I've been looking into the units in skirmishes to see if it's possible to use the same randomization code for humans; the results are interesting and a little discouraging.

First, all random enemies in skirmishes have '101' in binary as their Flag. '1' will automatically give the unit an inventory based on their class; and what items that they get seem to be based on some pre-defined table (see this list of monster items).

But '100' (or 4) will slightly randomize their coordinates and class. It will keep them in the vicinity of their defined coordinates, though, and what classes they can randomly appear as is limited by their defined class - so, Bonewalkers and become Revenants or Bow Bonewalkers, but not Baels; Gargoyles can become Mogalls but not Deathgoyles or Tarvoses. You could say that there are categories of monsters, and a random monster can only become a class that's in it's own category.

Anyway, the classes of monsters in skirmishes are defined strangely. Instead of using their actual class ID's, random monsters use valueslike 0x1 to 0x14:

[spoiler=An example]

UNIT 0xAC 0x2 0x0 0x55 [19,4] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x3,0xC,0x0]
UNIT 0xBB 0x14 0x0 0x55 [21,18] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x0,0xC,0x0]
UNIT 0xB0 0x6 0x0 0x55 [4,13] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x3,0xC,0x0]
UNIT 0xAC 0x2 0x0 0x55 [18,3] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x3,0xC,0x0]
UNIT 0xBB 0x14 0x0 0x55 [20,19] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x12,0xC,0x0]
UNIT 0xBB 0x14 0x0 0x55 [22,4] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x3,0xC,0x0]
UNIT 0xBB 0x14 0x0 0x55 [22,6] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x0,0xC,0x0]
UNIT 0xBB 0x14 0x0 0x55 [21,5] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x3,0xC,0x0]
UNIT 0xB3 0x9 0x0 0x55 [3,4] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x12,0xC,0x0]
UNIT 0xAD 0x4 0x0 0x55 [16,14] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x3,0xC,0x0]
UNIT 0xAB 0x1 0x0 0x55 [18,14] 101b 0x0 0x0 0x0 [0x0,0x0,0x0,0x0] [0x0,0x3,0xC,0x0]

This makes me think that the class ID is being used as an index in a table, or a constant in a calculation that finds their class, or something to that effect.

What I've done to experiment with this is give monsters a flag of 1b, to stop their class from fluctuating, and tested various values for their class ID to see what happened.

[spoiler=Long]

1 - Revenant
2 - Bonewalker Melee
3 - Wight Bow
4 - Bonewalker Bow
5 - Wight Melee
6 - Bael
7 - Elder Bael
8 - Cyclops
9 - Mauthe Doog
A - Gwyllgi
B - Bael
C - Maelduin
D - Mogall
E - Mogall
F - Mogall
10 - Arch Mogall
11 - Arch Mogall
12 - Arch Mogall
13 - Gargoyle
14 - Gargoyle
15 - Deathgoyle
16 - Deathgoyle
17 - Gorgon
18 - Dracozombie
19 - Revenant
1A - Bael
1B - Cyclops 2
1C - Elder Bael 2
1D - Queen (No items)
1E - Bonewalker Bow (No items from here on in)
1F - Ranger
20 - Hero
21 - Boss Mercenary (Empty, Hangs game)
22 - Bonewalker (No items still)
23 - Mage Knight
24 - Wyvern Lord (Weird Map animation - incomplete?)
25 - Bonewalker Sword
26 - Summoner
27 - Bonewalker Bow
28 - Garbage Eph. Lord, Crashes game, wipes saves
29 - Garbage Eph. Lord (Doesn't crash)
2A - Garbage Eph. Lord
2B - Garbage, may mess up FoW
2C - Garbage, Invisible in FoW
2D - Tarvos (Has weapons again!)
2E - Arch Mogall
2F - Bonewalker Sword (No items)
30 - Mauthe Doog
31 - Archer in Ballista (No items again past here)
32 - Gorgon Egg (Can't select)
33 - Bonewalker Bow
34 - Knight (F)
35 - Mymridon (F)
36 - Archer
37 - Ephraim Lord
38 - Pupil (1)
39 - Bonewalker Bow
3A - Knight (F)
3B - Archer
3C - Bael
3D - Ephraim Lord
3E - Knight (F)
3F - Ranger (F)
40 - Knight (F)
41 - Ranger (F)
42 - Myrmidon (F)
43 - Sage (F)
44 - Bonewalker Sword
45 - Myrmidon (F)
46 - Fleet
47 - Bonewalker Sword
48 - Myrmidon (F)
49 - Bard
4A - Bonewalker Sword
4B - Archer

From this, I can say that while it's possible to have 'random humans', the human classes don't have any item lists corresponding to them, causing the 1b flag to do nothing. To make it possible, you'd have to find the item table - and that class lookup table - to give them such a list.

Link to comment
Share on other sites

FurryYeongsun's notes don't have any useful details in them, unfortunately.

But honestly, I think FE8 hacking is much easier than it was before, because now we have decent Event Assembler support, and progress has been made recently in uncovering the functionality of the unknown commands.

Since I have a compulsive need to put new information in every post I make, I will say that for basic reinforcement events, it seems like you can just get away with this:

[spoiler=Unit Loading]

Reinforce:
_SETVAL 0x2 (Reinforcements|0x8000000)//Creates a pointer to a unit label; must be done like this
_LOAD_WHATEVER 0x1
ENUN
_0x0228 0x7
ENDA

Reinforcements:
UNIT 0x80 WyvernRider 0x0 0x15 [5,0] 0b 0x0 0x2 Fly2 [0x17,0x0,0x0,0x0] [0x0,0x0,0x0,0x0]
UNIT 0x80 WyvernRider 0x0 0x15 [5,0] 0b 0x0 0x2 Fly3 [0x17,0x0,0x0,0x0] [0x0,0x0,0x0,0x0]
UNIT 0x80 WyvernLord 0x0 0x15 [5,0] 0b 0x0 0x2 Fly4 [0x18,0x0,0x0,0x0] [0x0,0x0,0x0,0x0]
UNIT 0x80 WyvernLord 0x0 0x15 [5,0] 0b 0x0 0x2 Fly5 [0x18,0x0,0x0,0x0] [0x0,0x0,0x0,0x0]
UNIT 0x80 WyvernRider 0x0 0x15 [5,0] 0b 0x0 0x1 Fly [0x17,0x0,0x0,0x0] [0x0,0x0,0x0,0x0]//Can't have >4 REDA's moving at the same time
UNIT

But, this was tested in a chapter with almost no other events, so who knows why the vanilla game loads reinforcements in the circuitous way it does. Perhaps it is set up so that one format can be used for all possible types of reinforcements, which seems a little space-ineffecient.

Edited by Vennobennu
Link to comment
Share on other sites

People have in the past encountered the problem where if a non-aggressive unit has its AI changed during a chapter to an aggressive one, it will not attack enemies that would not be in range under its old AI; hence the case of pursuing enemies that won't attack after moving. Well, there is a simple fix to this.

Setting a unit's initial AI Byte 4 to 0x20 (Stand Still) is what causes this behaviour. If you instead set AI Byte 1 to 0x03 (Stand Still, do not attack in Nightmare), the unit will properly respect any AI changes during the chapter. So, you would set the unit's initial AI in Event Assembler like so:

[0x3,0x3,0x9,0x0]

And then change it to an aggressive configuration with your event. I tested this in FE8, but I have no reason to believe that this method wouldn't work in FE7.

Edit: Oh yeah! If you want to make an AREA code only triggerable by player units (and you probably will), then make sure the area event goes like this:

[spoiler=Allegiance-Based Triggering]

GuardsCharge:
_SETVAL 0x2 0x0 //Loads 0x0, the ID of the player allegiance, into memory slot 2
CALL Surety //This sequence is the check for the unit's allegiance
_SETVAL 0x1 0x10000
_0x3920 0x80 //Change AI of all units with character ID 0x80
_0x0228 0x7
ENDA

Surety:
_0x3325 0xFFFF
_SETCONDITION 0x0 0xC 0x2 //Checks value loaded into memory slot 2; skip to ENIF 0x0 if they match
CALL Surety2
ENIF 0x0
ENDA

Surety2:
_0x1929
_0x0620 0xC2
_0x0221 0xFFFF //Sets the Event ID related to this event as unused?
_0x0228 0x7
ENDB //End all event execution, go back to main stream
Edited by Vennobennu
Link to comment
Share on other sites

Oh wow, this is quite the topic.

That AI change discovery is great, I had to reload all my units till now and it was a pain to come up with that kind of events, even if they actually worked.

Just a few notes.

6) The below looks like the "is character dead?" condition; 0xY is the event ID and 0xZ is the condition ID.
_0x0322 0xY
_SETCONDITION 0xZ 0xC 0x0

7) The below looks like the "is this event ID unused?" condition; 0xY is the event ID and 0xZ is the condition ID.

_0x0321 0xY
_SETCONDITION 0xZ 0xC 0x0

Actually it's the opposite. Invert the conditions order.

If it's ALIVE it does this

If it's DEAD it does that

//

If event ID is USED do this

if it's UNUSED do that.

example:

_0x0322 0xY
_SETCONDITION 0xZ 0xC 0x0
// Events that occur if Unit 0xY is alive
ELSE 0xW
ENIF 0xZ
// Events that occur if Unit 0xY is dead
ENIF 0xW

same thing for the other one.

Also:

_0x0221 0xFFFF considers the event ID associated to the event as unused

Actually that alone won't work.

It has to be:

_0x1929
_0x0620 0xC2
_0x0221 0xFFFF

And:

I was thinking that it's possible that ENUN could be used in place of _0x0228 0x7 (I haven't tested this, it's just conjecture atm), based mainly on the fact that he uses it in locations similar to those I find _0x0228 0x7

I'm 100% sure that ENUN can't be used in place of _0x0228 0x7. The latter is to end events, the first is to wait for any movement-type action to finish. They're quite different, and I'm sure that ENUN doesn't work like that since I've had it at the end of most of my codes before discovering _0x0228 0x7 (which I'm not always using anyway since I like that fade-in/out effect, it's kind of scenic).

Great topic anyway.

Edited by Alfred Kamon
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...