Author Topic: FF7 AI question again...  (Read 12768 times)

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
FF7 AI question again...
« on: 2011-04-25 11:04:42 »
Anyone knows which byte(s) to change to make an enemy multi-target a magic spell (like Fire, Sleep, Dispel, ...) instead of single target ? I hope it is as simple as changing one or two bytes, but when I compared Safer Sephiroth's AI (IIRC the guy multi-targets DeSpell) with another monster that single-targets (almost all of them =\), their scripts were so different it wasn't funny.

Any help would be appreciated :)

nfitc1

  • *
  • Posts: 3008
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: FF7 AI question again...
« Reply #1 on: 2011-04-25 12:15:10 »
The enemies' target data is 2070 I believe. This has to be set before they perform an attack. Usually most enemies start out by just loading the "AllActiveOpponents" address of 20A0. You'll see a lot of

12  2070
02  20A0
90

That's target all opponents whose "targetable" flag is set.

To target just one character, you'll often see this:

12  2070
02  20A0
82  <--- I think it's this. Replace this with whatever "RandomBit" is
90

That'll choose a random character from the list of active ones and set it as the target.

I believe Reno has some scripts dealing with individual formation slots and Rude has some dealing with specific characters (he's not supposed to hit Tifa unless she's the only one) if you want more examples.

Bosola

  • Fire hazard!
  • *
  • Posts: 1749
    • View Profile
    • My YouTube Channel
Re: FF7 AI question again...
« Reply #2 on: 2011-04-25 13:29:21 »
You know, really, I need to update Welder so that modders needn't even ask these questions.

The biggest problem with Welder, though, is that it's an excel spreadsheet that needs to work properly with Excel 2003, Excel 2007+ and Open Office calc, each of which handles the sheet in annoyingly different ways.

Maybe I should bite the bullet and create a proper script generator. You'd hand it a text file with a configuration, like

Code: [Select]
Main attack = Claw on All.Opponents
IQ = 2/3
Priority 1 = Explode on All.Opponent IF self.critical == 1
Priority 2 = Deathblow on Random.All.Opponent.Sleep
Priority 3 = Deathblow on Random.All.Opponent.Stop
Priority 4 = Sleep on Random.All.Opponent.notSleep +checkMP

Then it'd just generate the code, or even better, just insert it right into the SCENE.BIN

But that's a looong way off. Maybe in the meanwhile I should just clean up the welder stuff I've got and document it better...

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #3 on: 2011-04-25 13:53:11 »
Thanks for the reply, NFITC1 :)

Here is a random script of an enemy that single-targets a spell :

12 2070
02 20A0
00 4002
80
60 00
40
82
90
60 20
60 [spell ID]
92

Does that mean I just need to replace 82h? You wouldn't happen to know the byte I'd need to enter, would you?... ...In any case, I'll take a look at those examples, thanks ^^

@Bosola: something like that would be awesome :D

nfitc1

  • *
  • Posts: 3008
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: FF7 AI question again...
« Reply #4 on: 2011-04-25 14:44:39 »
Thanks for the reply, NFITC1 :)

Here is a random script of an enemy that single-targets a spell :

12 2070
02 20A0
00 4002
80
60 00
40
82
90
60 20
60 [spell ID]
92

Does that mean I just need to replace 82h? You wouldn't happen to know the byte I'd need to enter, would you?... ...In any case, I'll take a look at those examples, thanks ^^

@Bosola: something like that would be awesome :D

That's performing an action on a random active opponent with the Sleep status (Eligor does something like that). If you replace the 82 then it can target all enemies. You can insert a NOP if you want, but not just any old value can be a NOP. If you give it an opcode it doesn't recognize it might throw an error or a memory leak might happen. Safe values for NOPs include 2Xh, BXh, CXh, DXh, EXh, FXh. For standardization purposes, we'll call 20h the NOP. So change that script to

12 2070
02 20A0
00 4002
80
60 00
40
20
90
60 20
60 [spell ID]
92

and then it targets all active opponents with the sleep status. Be advised that PrC will let you do this, but won't be able to disassemble that code. I'll be changing that for the next version.

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #5 on: 2011-04-25 15:02:42 »
Awesome, thank you very much ! :D

And now that I think about it, I'd hate to abuse your kindness, but do you know what the script would be if I wanted this enemy to only have a 50% chance to target all party members ? IE, making it use Sleep on a single target half the time ?

nfitc1

  • *
  • Posts: 3008
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: FF7 AI question again...
« Reply #6 on: 2011-04-25 16:15:02 »
Awesome, thank you very much ! :D

And now that I think about it, I'd hate to abuse your kindness, but do you know what the script would be if I wanted this enemy to only have a 50% chance to target all party members ? IE, making it use Sleep on a single target half the time ?

Let me think this through real quick

Code: [Select]
12  2070
02  20A0
00  4002
90
60  01 (this is IN sleep status, the previous scripts assume they're NOT asleep. Just noticed that)
40
81
60  01
50
70  XXXX <-- This will point to the 90 directly below
82
90
60  20
60
92

That's an ASM optimized code and will not disassemble correctly AT ALL. It basically skips the RandomBit function if some random (WORD AND 1) == 0. That's a 50/50 chance of either getting a random target or not. I'll try to give a pseudo-disassembly of this, but it won't assemble back into that code:

Code: [Select]
If (Random_WORD && 1)
     TargetMask = RandomBit( ActiveTargets with Sleep )
Else
     TargetMask = ActiveTargets with Sleep
End If

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #7 on: 2011-04-25 16:49:21 »
Much appreciated ! Still, I gave sleep as an example, as I was thinking about a script which would also work with any magic.
« Last Edit: 2011-04-25 18:26:45 by Armorvil »

nfitc1

  • *
  • Posts: 3008
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: FF7 AI question again...
« Reply #8 on: 2011-04-25 18:25:46 »
81
60  01
50
70  XXXX <-- This will point to the 90 directly below
82
90

is the block you really want to pay attention to then. Put that after whatever condition you want to test for and this is your "randomly target one or all" block.

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #9 on: 2011-04-25 18:50:59 »
Ha, thanks a lot, but I actually don't want a condition. I just want an enemy to cast its spell on 1 target or all targets randomly (with a 50% chance for each). The battle mechanics in FFVI already do that, since for example, the SlamDancer, when alone (and without a targeting command to specify this behavior), casts Fire2, Ice2 or Bolt2 either on the whole team, or on a single party member.

I was wondering if there was a simple way to do that in FFVII (in other words, without having to insert dozens of bytes). My guess is it should be possible by calling a random value (0 or 1, think dice-roll), and if 0 comes up -> make the enemy targets 1 ally, and if 1 comes up -> make the enemy target all allies. But I suppose this solution would require kind of a long script...

I wish one could make FFVII read the AI language used in FFVI. True, it is more restrictive, but paradoxally, its simplicity would allow most modders to achieve what they want a lot faster and with less hassle. I love that, for example, if you enter the command "use Fire" for an enemy in FFVI, it will automatically follow this 50% rule - and it's only when you enter a specific target command just above, that it will use Fire on a particular ally, a random ally, or all allies (among other targeting possibilities). Sorry for bringing up FFVI again :P
« Last Edit: 2011-04-25 19:02:30 by Armorvil »

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #10 on: 2011-04-27 15:13:38 »
Another question if I may.
In this example, how do you make this enemy target itself instead of the party ?


12 2070
02 20A0
00 4002
80
60 00
40
82
90
60 20
60 [spell ID]
92
« Last Edit: 2011-04-27 15:22:13 by Armorvil »

Bosola

  • Fire hazard!
  • *
  • Posts: 1749
    • View Profile
    • My YouTube Channel
Re: FF7 AI question again...
« Reply #11 on: 2011-04-27 15:39:16 »


12 2070
02 2060
00 4002
80
60 00
40
82
90
60 20
60 [spell ID]
92
[/quote]

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #12 on: 2011-04-27 15:46:18 »
Thank you very much Bosola ; you & NFITC1 are human-shaped Gods that descended from the heavens to help mankind in its FF7 modding effort :D

EDIT:

And what if I wanted to make this monster target the entire monster team ?
« Last Edit: 2011-04-27 15:55:16 by Armorvil »

nfitc1

  • *
  • Posts: 3008
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: FF7 AI question again...
« Reply #13 on: 2011-04-27 15:59:54 »

12 2070
02 2060
00 4002
80
60 00
40
82
90
60 20
60 [spell ID]
92

That makes no sense in context. Since 2060 will only have one active bit there's no reason to get a random active bit later. If you want it to target a random ally (possibly itself) then

12 2070
02 2080
00 4002
80
60 00
40
82
90
60 20
60 [spell ID]
92

would do that just fine. This script still suggests that the targets won't be asleep. Remove the

00 4002
80
60 00
40

to target indiscriminately

Bosola

  • Fire hazard!
  • *
  • Posts: 1749
    • View Profile
    • My YouTube Channel
Re: FF7 AI question again...
« Reply #14 on: 2011-04-27 17:24:34 »
That makes no sense in context. Since 2060 will only have one active bit there's no reason to get a random active bit later. If you want it to target a random ally (possibly itself) then

YOUR FACE makes no sense in context!

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #15 on: 2011-04-27 19:21:29 »
Now now, don't fight  ;D

And -subsidiary question- what kind of script would you write, to make this monster target the entire monster team ?

Bosola

  • Fire hazard!
  • *
  • Posts: 1749
    • View Profile
    • My YouTube Channel
Re: FF7 AI question again...
« Reply #16 on: 2011-04-27 20:13:19 »
For a creature that targets all allies (inc. self) with an attack, use

12 2070
02 2080
90
60 20
61 attack id (two bytes)
92

For a creature that targets a random ally, but not itself, with an attack, use

12 2070
02 2060 ; this is self
37 ; bitwise not, eg we've pushed 'everything not self'
02 2080 ; all allies
35 ; a bitwise and, so we've pushed 'things which are not self but are allies'
82
90
60 20
61 attack ID (two bytes)
« Last Edit: 2011-04-27 21:37:04 by Bosola »

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #17 on: 2011-04-27 21:21:18 »
You have my gratitude  :D
I may edit this post later if another request comes to mind :)
« Last Edit: 2011-04-28 16:53:31 by Armorvil »

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #18 on: 2011-05-04 08:32:35 »
New question. I'm a little annoyed that the Seizure / Dual status has no visuals when enemies are under this status, so I've been thinking of a way to let the player know that it worked.

There is the possibility of mixing Dual & Dual Drain with Blind. Since Blind doesn't work on enemies, I could make it so its graphical effect becomes Dual's. Only drawback is, when this particular magic would be used against characters, characters would also lose accuracy because of Blind...

The other option is to make use of AI, so a message at the top of the screen tells you that it worked. I would have to insert this code in every enemy's AI, or maybe I could insert it in the characters' AI to gain space. And of course, I don't know how to create such a code... ...I guess something like :

- If [target] is inflicted with Dual + Dual Drain,
- Displays message "Seizure connects !"

would work. I know the 93 opcode can display messages, it is with the first line I'd need help with.
« Last Edit: 2011-05-04 08:58:43 by Armorvil »

Vgr

  • Global moderator
  • *
  • Posts: 2163
  • If it quacks like a duck, it must be a duck
    • View Profile
Re: FF7 AI question again...
« Reply #19 on: 2011-05-05 09:45:50 »
- If {VAR:LastTargetName} has Dual/Dual Drain status;
- Display string : "Seizure connects"

or, with the Blind effect, this in character's AI, General Counter :

- If Blind is active on character, set [some flag] to 1
- If Dual/Dual Drain and Blind are active, deactivate Blind if [the same flag] is 0

I don't know either how to do that, but people like Bosola or Gjoerulv could help.

nfitc1

  • *
  • Posts: 3008
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: FF7 AI question again...
« Reply #20 on: 2011-05-05 13:25:29 »
New question. I'm a little annoyed that the Seizure / Dual status has no visuals when enemies are under this status, so I've been thinking of a way to let the player know that it worked.

There is the possibility of mixing Dual & Dual Drain with Blind. Since Blind doesn't work on enemies, I could make it so its graphical effect becomes Dual's. Only drawback is, when this particular magic would be used against characters, characters would also lose accuracy because of Blind...

The other option is to make use of AI, so a message at the top of the screen tells you that it worked. I would have to insert this code in every enemy's AI, or maybe I could insert it in the characters' AI to gain space. And of course, I don't know how to create such a code... ...I guess something like :

- If [target] is inflicted with Dual + Dual Drain,
- Displays message "Seizure connects !"

would work. I know the 93 opcode can display messages, it is with the first line I'd need help with.

For a playable character, put this on each one's General Counter:
Code: [Select]
02  2060
00  4013
80              ; they have the "Dual" status
02  2060
00  401B
80              ; they have the "DualDrain" status
50              ; they have both statuses
70  XXXX
12  2060
11  4080
80
60  YY          ; I don't know the value for this.
90              ; This would change their idle animation loop. You can change it to the "shock damage" animation, but it might not loop. It WOULD make them look like they're having seizures though and not make it look like they're blind.
93  "<Char> started convulsing"
60  22
60  00
92              ; double-check this with Hojo's Pre-battle and Death scripts. He's got some odd command index that pauses action while a string is being displayed. This is optional, of course
....     <-- 70 points here

You could do a similar thing on the enemy, but instead of changing their idle animation (most enemies only have one damage animation) you could inflict blind:

12  2060
10  401A
80
60  01
90

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #21 on: 2011-05-05 17:19:06 »
Thank you very much for taking the time to think about the code and to share the info :)

Still, I'm confused. I don't really need a code to change the player-characters' behavior when they're hit with Seizure (they already kneel and anyone with half a brain would notice their HP being drained away). Only the enemies'. I was hoping a code that checks for the enemies' status could be implemented in the party members' AI, but chances are it's not possible (oh yeah, and now that I think about it, is there a way to make use of the Formations' AI ? Because right now, if you try to edit them in any version of PrC, it crashes (it not really crashes, since you can edit the AI and leave the menu, but you won't be able to go back into the Fomation's AI menu afterwards)). End of parenthesis.

Back to the subject at hand. Actually, forget about Blind & animations. I just want a script that tells you that Seizure connects if the enemy is under the status (with a message at the top of the screen). It doesn't even have to be enemy-specific ; if I use the Seizure magic on a Cokatrice and the message "Enemy started convulsing" displays (thanks for the wording, by the way :D), anyone with half a brain should know that it is the Cokatrice that is now under Seizure ^^

Taking a look at your code, would adding this script under all non-Seizure-immuned enemies' General Counter scripts work ?

Code: [Select]
02  2060
00  4013
80              ; they have the "Dual" status
02  2060
00  401B
80              ; they have the "DualDrain" status
50              ; they have both statuses
70  XXXX
93  "The enemy started convulsing"

Small question though : what is the XXXX refering to ? Is it an address ? The enemy's ID ?...

(also, fun fact in the game mechanics : it looks like enemies that have less than ~40 HP are immune to Dual+Dual Drain, even if you didn't make them immune. In my mod, the MP enemies had 32 HP and didn't take damage from seizure. When I increased their HP to 40, the status worked  and decreased their HP to 8 (weird that the status wore off before it killed them, even though I already knew Dual has a limited duration. The Dual status sure lasts long enough to kill Cloud at full health, with any amount of HP... ...It may be because Regen isn't as effective on enemies as it is on characters, and since Dual is an inversed Regen...) 8-))

EDIT:

Nah, I just tried the above code in General Counter without the 70 XXXX part, and it doesn't work : the message "The enemy starts convulsing" always displays as a counter-attack, no matter what I hit it with (sword attack, Bolt, etc.). Perhaps the 70 XXXX would fix this, but I have no idea which values to insert instead of the XXXX.

EDIT 2:

I figured it out by myself :D. It's a JMP command, of course. Makes sense. So I just had to enter the address to jump to when the conditions aren't met (0031), and the message stops popping up when Seizure doesn't connect. I'm glad that I'm not entirely clueless with AI stuff. Thanks again NFITC1, now it works perfectly :D
« Last Edit: 2011-05-05 19:15:09 by Armorvil »

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: FF7 AI question again...
« Reply #22 on: 2011-05-05 19:18:43 »
Proof in video ^^

It's the first video I make with my ipod, and -promise- the last time that I record a video vertically. That was a bad idea.

EDIT:

Oh crap, I just realized something. This JMP command is bad, since it will be different for every enemy in the game. I thought I'd just have to copy/paste the code to all the enemies in all the scenes... ...Tedious and time-consuming of course (I already did it with the enemies that die when they have 0 MP, so I'm not afraid of that), but not as much as also having to enter the hundreds of different JMP addresses ! :o Now I'm scared that this project will forever take my sanity away.

Isn't there a way to make such a code work for all enemies, without having to copy-paste it to all the enemies AND edit the JMP addresses ? Please, tell me there is way... ... ...If not, well, I'll just have to get to work. Tell the guys up there that they'll need more than that to make me quit ! :P

EDIT 2:

Mmm... ...Maybe I don't need to update the JMP address for each enemy after all : about those that already have a General Counter script, can I just paste my code at address 0x000, insert 90h at the end of the seizure code to separate it from the other counter scripts, and make the JMP opcode target said 90h ?
« Last Edit: 2011-05-05 20:07:13 by Armorvil »

Vgr

  • Global moderator
  • *
  • Posts: 2163
  • If it quacks like a duck, it must be a duck
    • View Profile
Re: FF7 AI question again...
« Reply #23 on: 2011-05-05 21:51:24 »
Do you want Fraps, AV?

sl1982

  • Administrator
  • *
  • Posts: 3764
  • GUI Master :P
    • View Profile
Re: FF7 AI question again...
« Reply #24 on: 2011-05-05 22:18:34 »