FF7 AI question again...

  • Thread starter Thread starter Armorvil
  • Start date Start date
Status
Not open for further replies.
A

Armorvil

Guest
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 :)
 
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.
 
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]
Code:
Main attack = Claw on All.OpponentsIQ = 2/3Priority 1 = Explode on All.Opponent IF self.critical == 1Priority 2 = Deathblow on Random.All.Opponent.SleepPriority 3 = Deathblow on Random.All.Opponent.StopPriority 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...
 
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
 
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.
 
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 ?
 
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]
Code:
12  207002  20A000  40029060  01 (this is IN sleep status, the previous scripts assume they're NOT asleep. Just noticed that)408160  015070  XXXX <-- This will point to the 90 directly below829060  206092
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]
Code:
If (Random_WORD && 1)     TargetMask = RandomBit( ActiveTargets with Sleep )Else     TargetMask = ActiveTargets with SleepEnd If
 
Much appreciated ! Still, I gave sleep as an example, as I was thinking about a script which would also work with any magic.
 
Last edited:
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.
 
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 edited:
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 edited:
12 2070
02 2060
00 4002
80
60 00
40
82
90
60 20
60 [spell ID]
92
[/quote]
 
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 edited:
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
 
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!
 
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 ?
 
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 edited:
You have my gratitude  :D
I may edit this post later if another request comes to mind :)
 
Last edited:
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 edited:
- 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.
 
Status
Not open for further replies.
Back
Top