[FE7] The Official AI Documentation Thread

Can you also check the priority of mounting a ballista and dismounting a used up ballista? If my guess is right, dismounting the ballista should come after staves, but before steal, and mounting a ballista will have be below attack, only if they can’t reach an enemy this turn. I think. Just from cursory examination of the code and making guesses as to what some things do.

I’ve got a question about movement AI/aggression AI and I’m hoping one of you guys who have tested this more thoroughly will be able to answer or even test it out for me as I’m on borrowed time to meet the deadline for FEE3 and probably won’t make it.

I want to have a chapter set up such that a band of wyvern knights are patrolled the edges of a map. If everything goes accordingly, the wyvern knights will cycle between 0x13-0x16 for movement AI (with adjusted coordinates) such that they move in this cyclic fashion. The boss should ONLY move and attack if three characters are in range, otherwise he will continue to fly around the map. The generic wyverns will simply be set to follow the boss. An AFEV will change the group’s AI such that after the boss’s battle quote they will target anyone.

I’m not sure how to go about this, but I’m certain that it can be done. My current plan is to have this setup for the boss:

AI Byte 1: Do not attack [all player characters except Henrick, Damion, Bronwyn]
AI Byte 2: Turn 1/2 - move to top right corner, Turn 3/4 - move to top left corner, Turn 5/6 - move to bottom left corner (and so on and so forth; using CHAI on a turn event)
AI Byte 3: Recovery of some amount
AI Byte 4: Nothing

However, I want the boss to prioritise attacking Henrick/Damion/Bronwyn over moving to the specified coordinates. Will this set-up do that for me or will the boss move towards those coordinates before attacking?

… sorry I got nothing. I was thinking of throwing together a demo (of the very first custom FE7 AI) of an enemy moving around in a square…

But sorry, we’re just not advanced enough for that first AI yet :frowning: .

All good, @Venno just tested it out for me and it looks like enemies with a Move to Coordinate AI will attack player units before they move to their designated place (hooray!). So it looks like I’m all good.

BTW, it appears that AI2 is more of a “backup” AI, or something, like, it’s done when AI1 doesn’t return something satisfactory. I think. It’s just my gut feeling from looking at routines and making new Ai1s. I could be wrong. But I know for sure it’s not “aggression” and “movement”.

2 Likes

I’m a bein’ flexin’ my hackin’ muscles.

5 Likes

sweeeeeeeeeeet

are you jesus

Jesus Christ: ROM Hacking Superstar!

1 Like

btw, mind adding this to the wiki-post of mega-decumentation?

Pre-ballista:
Staves and steal definitely have higher priority than mount. Units won’t mount ballista if there are no enemies in ballista range. It looks like attack and mount+attack have equal priority. During the targeting process, the unit analyzes in-range enemies with both the ballista and weapons in inventory.

In the ballista:
The unit can use staves but won’t steal. Ballista units normally don’t move, but the ballista can move when using staves.

Post-ballista:
Unit will dismount if there is no more ammo and the unit isn’t going to use a staff. The dismount turn is kind of strange, the unit can either attack without moving or move without attacking. The unit can’t steal until 1 turn after dismounting.

There’s an issue with ballista in the targeting process…
For the expected value calculation at 08039040, the ballista’s might and hit aren’t included in the damage and hit values.

Something else I stumbled across…
08038B9A : TP for ballista targets apparently gets compared here instead of 080386F0

1 Like

Just as an addendum…it turns out a Shade/Provoke mechanic would be very easily implementable in the current engine; the routine at $08039138 loops through some fixed locations in ROM (pointers at $8B970C8) and compares each byte there with the target’s class ID; the function returns the loop counter upon finding a match with this ID or going through 0x9 entries (each entry is terminated by a 0x0 byte).

By default the list it looks at is filled up with zeroes, so this function always returns 0x9. Then the game multiplies TP_modifier[0x3] by TP_modifier[0x8+return value], and adds that (max value of 20 by default) to the total TP for that target.

In the unmodified ROM this always ends up being 0x0; but by modifying the TP modifier struct and the list that checks for class bytes, one could make it so that certain classes have a higher or lower priority than normal.

More TP routines:
$0803916C - multiplies the current turn number by TP_modifier[0x4], and adds the result to the total TP.

$08039184 - If the target has no weapon it can use, add 10 to the total TP. Otherwise, calculate the target’s projected damage from a counter (accounting for hit%) and multiply by TP_modifier[0x5].

If penalty > 0x28 (50), set to 0x28. Subtract penalty from the total TP so far.

$0803921C - Multiply (20-Attacker’s HP after a successful counter) by TP_modifier[0x7]. Subtract this return value from the total TP so far.

The remaining routines that modify TP are at $080391E4 (calcs a penalty) and $08039094 (calcs a bonus) - they seem to have something to do with map data, and the attacker’s allegiance.

2 Likes
08037928 F7EBFFC2 bl      #0x80238B0

This is the allegiance check. It take two characters’ deployment numbers in r0 and r1 and returns true if they ARE on the same side. This is what makes Other units friendly(the stat of their 0x80 bit is the same as players) and hypothetically, player 4 units are allied with enemies.

… also, we can totally jack this in Blazing Renaissance to make 3 way fights.

edit: funfact - we can’t process -mag/2 range weapons! idk if the player/engine still can, but the enemy is certainly incapable.

3 Likes

Would we be able to make some sort of assembly hack to change this such that it is enabled/disabled for certain chapters? :smiley:

Easily :wink:

@Agro, @Brendor. I literally changed 1 bit (made a 0x80 into 0xC0) to make it treat all factions like its own team. I’m unloading a demo to youtube shortly.

And, I realllly need help here. What does the memory at 0x202E3E4 and 0x202E3E8 store? @CT075, @Venno? Can you help me track down what writes to it and what data that is?

1 Like

Try setting a break on read and see what you get

0x0202E3D8 - X and Y size of map, used for bounding the cursor, stored here as two halfwords

It’s a bit past that.

0x0202E3E0 - Points to pointers detailed below (except for first) (not in order)
E4 -> pointer to terrain, E8 -> pointer to fog
0x0202E3F8 - Row pointers for unit map (byte per tile with value == byte at +0x0B in unit struct)

–Hextator’s doc

Newest tech demo.

2 Likes

Wait. That stuff about map data in memory isn’t matching up with what I am seeing?

0202E3DC (row pointers at 0202E400) : Location of units

0202E3E0 (row pointers at 0202EBB8) : Terrain data

0202E3E4 (row pointers at 03000448) : Movement range of selected unit
Numbers indicate amount of movement points needed to reach space from starting position. FF = cannot enter space

0202E3E8 (row pointers at 03000C00) : Related to attack/staff range of selected unit

When unit is selected: Numbers decrease as distance from unit increases. 00 = appears to be space outside of attack range. Numbers are higher when the unit has a 1-2 range weapon in inventory compared to when the unit only has 1 range weapons.

After unit moves and the attack/staff option is available: 01 = spaces that be targeted (highlighted red/green)

0202E3EC (row pointers at 0202F370) : Shaded tiles for fog-of-war and magic sealing
00 = Shaded. Greater than 00 = Clear

0202E3F0 (row pointers at 0202FB28) : Hidden fog-of-war enemies and mines
00 = None, 01 = Hidden “enemy” (display “!” and stop movement if player unit tries to enter), 02 = Mine

0202E3F4 (row pointers at 020302E0) : ???
Player Phase: Data changes whenever the movement arrow path has to be altered due to moving cursor over enemies or certain terrain.
Enemy Phase: ???