Adding a 'seizure' status to poison / linking statuses with AI

  • Thread starter Thread starter Bosola
  • Start date Start date
Status
Not open for further replies.
B

Bosola

Guest
As some of you may know, I've never been happy with the poison status in vanilla FFVII. 1/32 Max HP damage per turn just doesn't cut it in the endgame, when many monsters can be KOed in one or two hits anyway.

The usual solution is to add the 'dual drain' status to all poison-inflicting attacks and spells. This makes poison much more dangerous. But it has three main disadvantages:

1. Modifying *every* enemy and player attack is very time-consuming. And if you want to switch back, you have to be very thorough.
2. Just adding the status to poison attacks isn't enough - you now have to modify enemy status immunities (many creatures are vulnerable to the one status but not another). Again, this takes a lot of time.
3. You can't inflict your dual-drain status via added effect, because you can't give materia a dual-drain status affinity. Boo!

But do not despair! There is another way - to create an AI script that automatically gives poisoned creatures the dual-drain status, and removes it when they're cured. Here's the AI script:

Code: [Select]
Code:
12   000002   20E09012   002061   00019012   004002   000002   0020359002   004070   002E12   004010   401B8002   004000   4003809002   002061   80004570   004512   002002   002060   02329072   000E73
The idea is to put this into Vincent's preTurn-counter and general-counter scripts, then link other characters to Vincent's scripts with the preBattle code

Code: [Select]
Code:
60 077573
Now, poisoned characters and creatures will immediately take the Seizure status. The only potential bug is if a character has a counter ability, in which case, the seizure status will be delayed until another battle actor takes an action.

What if I want a disease status, rather than seizure / dual-drain?

Oh, that's simple. Use the code

Code: [Select]
Code:
12   000002   20E09012   002061   00019012   004002   000002   0020359002   004070   002E12   004010   42A98002   004000   4003809002   002061   80004570   004512   002002   002060   02329072   000E73
That should work just fine.

And if I want to link any statuses?

Then replace the values in the following:

Code: [Select]
Code:
12   000002   20E09012   002061   00019012   004002   000002   0020359002   004070   002E12   004010   ADDRESS OF STATUS TO ADD (E.G. DUAL-DRAIN)8002   004000   ADDRESS OF STATUS THAT TRIGGERS IT (E.G. POISON)809002   002061   80004570   004512   002002   002060   02329072   000E73
So if you wanted to give Flag:PhysicalImmune to anyone with Flag:Defending (so Defend blocks *all* non-magic damage), you'd substitute the values 4028 and 4025 respectively, etc. etc.

How is this script any different to older ones?

This isn't the first time this has been attempted (see https://www.ff7catalog.com/threads/7909/). The problem with those attempts is that they attempted to directly set allActors.dualDrain = allActors.poison by simply copying a word of one status mask to another, which the battle engine doesn't support. The result was typically a buggy script where all creatures would suffer dualDrain if *any* were poisoned. Not good. Instead, this script directly iterates through all battle actors and sets statuses individually.

How does it do that?

The idea is simple. We put the AllUnitsMask in a local variable, then we perform a bitwise AND on it with an iterator that's logically shifted to the left with every loop (by multiplying by two). That means that every loop, we get a unitmask that points to each actor in the battle. If the mask isn't empty, we copy the unit's poison status to its dual-drain status. We don't do that for units that don't exist, because that might invoke glitches (probably not, but better safe than sorry).

Here's an annotated AI script:

Code: [Select]
Code:
12   000002   20E090      Put a mask of all actors in LocalVar 000012   002061   000190      Start our iterator (LocalVar 0020) at 112   004002   0000   02   002035       Bitwise operation to cycle through bits in the LocalVar 0000, one at a time9002   004070   002E   If there's an active bit in the current position...12   004010   401B   80      Get the address of currentActor.dualDrain...02   004000   400380      And currentActor.poison...90      ... and finally make currentActor.dualDrain = currentActor.poison02   002061   80004570   0045   If the iterator is at 0x8000 (which means one 1 and fifteen 0s), exit12   002002   002060   023290      If not, double the iterator (which effectively applies a left shift) and go again72   000E   Loops73      End of script!
I've encountered a problem! Help!

...then post your issue here and I'll update the script if I can fix it.

Other than that, enjoy!
 
Last edited:
Status
Not open for further replies.
Back
Top