Dispos Enemy AI - DivineDragonFanClub/Lythos GitHub Wiki
AI Flags
public DisposData.AIFlags
{
NotActivateByAttacked = 1,
Dummy = 2,
ZeroAttack = 4,
Heal = 8,
Break = 16,
Chain = 32,
EquipShortAfterLongRange = 64,
MoveBreak = 128,
EngageAttackOnce = 256
}Flags
public DisposData.Flags
{
Normal = 1;
Hard = 2;
Lunatic = 4;
Create = 8;
Leader = 16;
NotMove = 32;
Edge = 64;
Pos = 128;
Must = 256;
Fix = 512;
Guest = 1024;
MaskSortie = 896;
MaskDifficulty = 7;
}Directions
public DisposData.Directions
{
None = 0;
Up = 1; // ⇑
UpperRight = 2; // ⇗
Right = 3; // ⇒
LowerRight = 4; // ⇘
Down = 5; // ⇓
LowerLeft = 6; // ⇙
Left = 7; // ⇐
UpperLeft = 8; // ⇖
}States - See Engage Attack Rampage
public DisposData.State
{
Normal = 0;
Rampage = 1;
Keep = -1;
}AI for each enemy unit is determined both in dispos and by scripts. Fire Emblem Engage has a modular approach to AI, meaning the enemy AI consists of up to 4 components, as seen in dispos: Action, Mind, Attack, and Move.

Any AI sequence can be put into any of these fields, but usually Action determines when the unit "activates," and Mind, Attack, Move determines what the unit does. Usually, attack is battling or using staves, move is moving + waiting, and mind is other actions. What each of the AI sequences do is defined in AI.xml.

Each AI sequence is a list of commands. In the case of action commands (with code 3), the game will simply iterate though them in order and select the first action that can be performed. This is how each unit decides what to do each turn.
Active: Determines if the command is for active units, inactive units, or both. For actions, 0 is active, -1 is both, -2 is inactive.
Code: Determines which type of command it is. Actions have code 3, and are ususally of most interest to edit.

Mind: Determines which specific command it is. Further down is a table of each.
StrValue0 and StrValue1: Parameters for the command. Arguments can be passed directly, but values V_0, V_1, V_2, and V_3 are often used so that arguments can be passed from fields in dispos such as AI_AttackVal. Most commands don't use the parameters, and their purpose varies.
Trans: Unknown, but actions don't use them.
For instance, take "AI_AT_Attack" shown above, a very common AI sequence for regular enemies in the game. Action commands 41, 72, 0, 71, 74 are HE_MiddleLow, MI_GuardBattleScore, AT_Default, MI_Guard, MI_GuardNoMove respectively. Thus, each turn will have the following procedure to decide what this unit will do each turn once it's active:
First it's HE_MiddleLow. This means checking if it's appropriate to heal. If so, heal, otherwise move on to the next command which is MI_GuardBattleScore. This means checking if it's possible to chain guard and if it's smarter than attacking. If so, chain guard, otherwise move on to the next command, AT_Default. This one just checks if it's possible to attack an enemy. If not, move on to MI_Guard. Check if it's possible to chain guard an ally at all. If not, do nothing.
Note that the MI_GuardNoMove command in this example is only to be attempted if the unit is inactive due to Active="-2", and the final command with Code="0" just signifies the end of the sequence. Also, this sequence, "AI_AT_Attack", is used by a wide variety of units, most of which cannot chain guard.
Here's what each Mind value means for Code="3". Keep in mind the descriptions may be inaccurate, as this is just my conclusions from staring at disassembly code for a couple of hours.
| Name | ID | Description |
|---|---|---|
| AT_Default | 0 | Attack an enemy |
| AT_MiddleLow | 1 | Attack an enemy if m_Think is not AttackHigh |
| AT_Low | 2 | Attack an enemy if m_Think is not AttackHigh or AttackMiddle |
| AT_Hero | 3 | Attack the protag |
| AT_Person | 4 | Attack a specific Pid |
| AT_ExcludePerson | 5 | Attack an enemy other than a specific Pid |
| AT_ExcludeBand | 6 | Attack an enemy not in a specific group |
| AT_Job | 7 | Attack an enemy with a specific class |
| AT_JobNearestPosition | 8 | Attack the closest enemy with a specific class |
| AT_Force | 9 | Attack an enemy on a specific side |
| AT_PriorItem | 10 | Attack an enemy with a specific weapon |
| AT_CrossfireEnd | 11 | n/a |
| AT_Breath | 12 | Attack an enemy with a breath attack if m_Think is not AttackLongRange |
| AT_BreathMiddleLow | 13 | Attack an enemy with a breath attack if m_Think is not AttackLongRange or AttackHigh |
| AT_ExcludePerson2 | 14 | Attack an enemy other than two specific Pids |
| RD_Heal | 20 | Heal an ally |
| RD_Warp | 21 | Warp an ally towards an enemy |
| RD_WarpFarZ | 22 | Warp an ally in the Z-direction |
| RD_Rescue | 23 | Rescue the most powerful ally |
| RD_MagicShield | 24 | Use reflect on allies |
| IR_Default | 30 | Use disruptive rod on an enemy |
| IR_HighMagic | 31 | Use disruptive rod on an enemy with high magic |
| IR_LowMagic | 32 | Use disruptive rod on an enemy with low magic |
| IR_Person | 33 | Use disruptive rod on a specific Pid |
| IR_ExcludePerson | 34 | Use disruptive rod on an enemy other than a specific Pid |
| IR_Weapon | 35 | Use disruptive rod on an enemy with a specific weapon type |
| IR_Frequency | 36 | Use disruptive rod on an enemy |
| HE_Default | 40 | Use healing item or move toward heal tile |
| HE_MiddleLow | 41 | Use healing item or move toward heal tile if m_Think is not AttackHigh |
| HE_NearingHero | 42 | Use healing item next to protag |
| EG_Attack | 50 | Use engage attack on an enemy |
| EG_Dance | 51 | Use dance engage attack on allies. Within Engage Attack SID, the item's name in EquipIids must start with IID_女神の舞...IID_女神の舞... must have its Kind 7 aka must be a staff.IID_女神の舞... must have RangeTarget Flag enabled.IID_女神の舞... must have its UseType 15. |
| EG_Vision | 52 | Create illusory doubles |
| EG_Pierce | 53 | Use engage attack on allies as if it pierces (like override) |
| EG_Bless | 54 | Use divine blessing on an ally |
| EG_BlessPerson | 55 | Use divine blessing on a specific Pid |
| EG_Wait | 56 | Use an enemy phase engage attack if hp >= 50% |
| EG_Summon | 57 | Use summon hero if hp >= 50% |
| EG_Overlap | 58 | Use AOE engage attack |
| MI_Talk | 60 | Talk to someone |
| MI_Treasure | 61 | Open a treasure box |
| MI_Village | 62 | Visit a house |
| MI_Escape | 63 | Escape the map |
| MI_EscapeSlow | 64 | Escape the map using less move |
| MI_BreakDown | 65 | Unknown |
| MI_Dance | 66 | Dance for an ally |
| MI_TerrainDestroy | 68 | Destroy some breakable terrain |
| MI_Torch | 70 | Extinguish a torch |
| MI_Guard | 71 | Chain guard next to an ally |
| MI_GuardBattleScore | 72 | Chain guard next to an ally if there's no good attack available |
| MI_GuardPerson | 73 | Chain guard next to a specific Pid |
| MI_GuardNoMove | 74 | Chain guard without moving if next to ally |
| MV_Return | 80 | Move toward own spawnpoint |
| MV_Idle | 81 | Wait or use healing item without moving |
| MV_AttackRange | 82 | Move to get an attackable enemy within range |
| MV_AttackRangeSide | 83 | MV_AttackRange, but with an unknown attackFlag |
| MV_AttackRangeExcludePerson | 84 | MV_AttackRange, but ignoring a specific Pid |
| MV_AttackRangeIgnore | 85 | MV_AttackRange, but with an unknown moveFlag |
| MV_WeakRange | 86 | MV_AttackRange, but with another unknown attackFlag |
| MV_WeakRangeSide | 87 | Combination of MV_AttackRangeSide and MV_WeakRange |
| MV_HealRange | 88 | Move to get a healable ally within range |
| MV_Hero | 89 | Move toward protag |
| MV_Person | 90 | Move toward a specific Pid |
| MV_Position | 91 | Move toward a pecific coordinate |
| MV_Force | 92 | Move toward a unit on a specific side |
| MV_ForceExcludePerson | 93 | MV_Force, but ignoring a specific Pid |
| MV_Treasure | 94 | Move toward closest treasure box |
| MV_Village | 95 | Move toward closest village |
| MV_Escape | 96 | Move toward escape |
| MV_NearestFriend | 97 | Move toward closest ally |
| MV_TerrainDestroy | 98 | Move toward closest breakable terrain |
| MV_Retreat | 99 | Move to the safest available spot |
| MV_BreakDown | 100 | Unknown |
| MV_Terrain | 101 | Move toward a specific Tid |
| MV_Rewarp | 108 | Rewarp toward an attackable enemy |
| MV_AttackRangeExcludePerson2 | 109 | MV_AttackRange, but ignoring two specific Pids |
| CS_Battle | 110 | Attack an enemy with a battle command skill (like echo or advance) |
| CS_Overlap | 111 | Use Dragon Vein [Cavalry] on enemies |
| CS_OverlapNoEnemy | 112 | Use Dragon Vein [Cavalry] on enemies if none are attackable |
| CS_FullBullet | 113 | Use let fly on specific coordinate using a specific Iid |
| CS_Decoy | 114 | Use assign decoy on an ally if you can't kill all enemies nearby |
| CS_Enchant | 115 | Enchant allies with any item |
| CS_EnchantHeal | 116 | Enchant allies with a healing item |
| CS_Strategy | 117 | Use gambit command skill appropriately |
| CS_Trimasteries | 118 | Use combat art command skill |
| CS_Contract | 119 | Use contract on ally |
| CS_Yell | 120 | Use rally spectrum on allies if no enemies are attackable |
| CS_Gaze | 121 | Use piercing glare on a specific coordinate |
| VS_Plan | -1 | Unselectable. Set m_VsThink to AttackLow if dance engage attack is available |
| VS_EG_Engage | -2 | Engage |
| VS_EG_Attack | -3 | Use engage attack appropriately |
| VS_AT_MiddleLow | -4 | Attack an enemy if m_Think is not AttackHigh |
| VS_GodSkill | -5 | Use any sync/engage command skill appropriately |
| VS_MI_Dance | -6 | Dance for an ally |
| VS_MI_Guard | -7 | Chain guard next to an ally |
| VS_MI_FireCannon | -8 | Attack an enemy with an artillery |
| VS_MI_TerrainDestroy | -9 | Destroy some breakable terrain |
| VS_CS_Enchant | -10 | Enchant allies with any item |
| VS_CS_EnchantHeal | -11 | Enchant allies with a healing item |
| VS_CS_FullBullet | -12 | Use let fly on an enemy |
<Param Group="AI_AT_ALittle_Secret_AI" Active="" Code="" Mind="" StrValue0="" StrValue1="" Trans="" />
<Param Group="" Active="0" Code="3" Mind="-3" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="-10" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="118" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="110" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="117" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="12" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="0" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="-8" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="-12" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="52" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="24" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="66" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="119" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="120" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="114" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="-5" StrValue0="1" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="-5" StrValue0="0" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="30" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="20" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="21" StrValue0="1" StrValue1="1" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="23" StrValue0="1" StrValue1="1" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="71" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="41" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="108" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="86" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="82" StrValue0="V_Max" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="3" Mind="88" StrValue0="V_Max" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="-2" Code="3" Mind="74" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
<Param Group="" Active="0" Code="0" Mind="0" StrValue0="V_Default" StrValue1="V_Default" Trans="-128" />
Lines within Details are from here but slightly edited. They're created when program randomizes & exports files. Don't use as it as a randomizer, it's old. Use Draconic Vibe Crystal: Runtime Randomizer + More instead.
Copy paste the lines into the AI section in Astra. Then, in a Chapter Dispos, have at least one AI Attack Name be AI_AT_ALittle_Secret_AI to try it out.
With this knowledge we can now design our own AI sequences, and possibly even cram as much functionality as possible into one. The sequence shown above will make units attempt to use engage attacks, command skills, regular attacks, artillery, dancing, enchanting, offensive staves, healing staves, warp, rescue, chain guarding, healing items, rewarp, and also takes care of how they will move if they don't do any of those things. Great as a general-purpose enemy AI, if you need that for some reason...
Thanks to Nifyr for writing most of this page!