Author Topic: (FF7) Enemy AI: Referring to other enemies  (Read 3343 times)

Karifean

  • *
  • Posts: 65
    • View Profile
(FF7) Enemy AI: Referring to other enemies
« on: 2013-09-16 20:52:50 »
I seriously do not get how this works. As far as I can tell, there are two different lines that end up storing another enemy in a variable:

Code: [Select]
LocalVar:00XX <-  (AllyMask.EnemyID == ???)

and

LocalVar:00XX <-  (BitCount(Self.FormationNumber) == ActiveMask.FormationNumber)
LocalVar:00XX <-  (LocalVar:00XX.EnemyID == ???)

Both of them are used quite a bunch of times. The Rufus battle uses both; Rufus uses the top version, Dark Nation uses the bottom version. And yet, I can't quite see through it. Sometimes it randomly stops working, especially when using "manipulation" - as in changing the Self variable for a moment to have another enemy execute an attack. And what is does that line in the middle actually do?

To give a more concrete example, I have modified Dark Nation to use a custom skill (ID 03E9h/1001) on Rufus if it dies and Rufus is still alive. The following code comes into play:

Dark Nation's Pre-Battle Script:

Code: [Select]
0x000LocalVar:0020 <-  (BitCount(Self.FormationNumber) == ActiveMask.FormationNumber)
0x014LocalVar:0020 <-  (LocalVar:0020.EnemyID == 68)
0x022TargetMask <- AllyMask
0x029Perform("Reflect"[0011], EnemyAttack)
0x02FSCRIPT END

and Dark Nation's Death Counter Script, naturally:

Code: [Select]
0x000 If ( (LocalVar:0020.Status:Death == 0) )
0x000 {
0x00D TargetMask <- LocalVar:0020
0x014 Perform(1001, EnemyAttack)
0x01ASCRIPT END

And yet, Dark Nation did nothing. How come?

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: (FF7) Enemy AI: Referring to other enemies
« Reply #1 on: 2013-09-16 22:01:57 »
Don't use BitCount. It's a pretty stupid function, I think.

EDIT:
Turns out BitCount is only one function of code 83.

If the structure of the first pop is type 2X (a list) then
   Find first non-null value in list
   All values in list become first non-null value
Code: [Select]
Pre-83    Post-83
10        0
0         0
0         0
0         0
0         0
0*        0
0         0
1         0
0         0
0         0

* - Since Self.FormationNumber is the only valid value at the time, this is considered non-null

The the 40 code comes around:

Code: [Select]
List 1    List 2 (result of the ActiveMask.FormationNumber)
0         10
0         F1*
0         F1*
0         F1*
0         0
0         0
0         0
0         1
0         F1*
0         F1*

This means not present

The result is that the three enemies are "equal" and the value of the result is 70, which becomes the new Mask for list 1 and that gets pushed to the stack and written in LocalVar:0000.

Then the Enemy ID of each of these masks gets checked and the one with a value of 68 gets saved as the new mask and gets set to LocalVar:0000. Then you have your target mask of enemy 68. Pretty round-about way of doing this. It's just as easy to do
Code: [Select]
LocalVar:0000 <- ActiveMask.EnemyID == 68with the same result. 14 bytes vs 35. The caveat to this is that if there are multiple Rufuses, it would target all of them.

We can also see from this that "FormationNumber" is NOT FormationNumber or it would be numbered sequentially with Cloud being 0, Rufus being 4, and Dark Nation being 5. It's more like "Instance" as in, this is the 0th instance of Gagighandi, labeled Gagighandi A when Sensed, and 1st instance of Gagighandi, labeled Gagighandi B. For playable characters this is always 10h + CharacterID. That 1 toward the end? That's an invisible Helicopter actor that is....just there. It doesn't seem to serve any significance.
So Dark Nation is looking for all the zeroth instances of battle actors and then looking for the EnemyID within the results of that. If there were multiple Rufuses, it would only care about the first one.
« Last Edit: 2013-09-17 16:25:46 by NFITC1 »

Karifean

  • *
  • Posts: 65
    • View Profile
Re: (FF7) Enemy AI: Referring to other enemies
« Reply #2 on: 2013-09-17 17:16:16 »
So basically, use the BitCount(Self.FormationNumber) == ActiveMask.FormationNumber variant if there are multiple instances of one enemy and you want to refer to the first of them? Or... in the reverse case, there are multiple instances of your own enemy type, then only the first of you can successfully refer to the boss (the monsters in the Sample:H0512 fight do this)?

Edit: And one thing that would definitely help - can you refer to other instances of your own Enemy ID by using the ActiveMask.EnemyID method and then doing a bitwise AND with NOT Self? I haven't quite understood how exactly masks and lists work yet. Edit2: Okay, just found that Nibel Wolf does that so it should work.
« Last Edit: 2013-09-17 18:00:12 by Karifean »

nfitc1

  • *
  • Posts: 3011
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: (FF7) Enemy AI: Referring to other enemies
« Reply #3 on: 2013-09-17 17:57:13 »
So basically, use the BitCount(Self.FormationNumber) == ActiveMask.FormationNumber variant if there are multiple instances of one enemy and you want to refer to the first of them? Or... in the reverse case, there are multiple instances of your own enemy type, then only the first of you can successfully refer to the boss (the monsters in the Sample:H0512 fight do this)?

The first one.