Thank you, NFITC1. I think we now have enough data to cover most functions. A provisional set of plugins can now be bandied about.
NEW PLUGINS
**********************************
* ALTERNATIVE HEADER WITH VARIABLE IQ *
**********************************
This is an alternative to the standard header. It uses LOCALVAR 0200 to determine intelligence.
The purpose of this is for enemies to get smarter and more efficient under certain circumstances. I'm sure we've all played games where one leader unit grants new abilities or better stats to his peers - or where a group will become more aggressive and vengeful on the death of certain allies. This header allows you to implement such behaviour.
12 2070
02 20a0
82
90
60 20
61 index of the 'dumb' attack
81
60 FF
34
00 0200 <- reads one byte from LOCALVAR 0200
43
70 ZZZZ <- address of the footer
To use this, you will need to set a default intelligence level in at least one of the active Pre-battle scripts for each formation. This should be a value from 0 to FF (one byte). This value over 255 will be the 'IQ' - the proportion of attacks that are 'smart'.
Establish this with the following code
10 0200
60 FF <- this is the default intel level, from 0h to FFh - 80h is about 'half' intelligence
90
To alter IQ on certain events, you will need to write counter scripts, or counter-death scripts. These will take the form of the above code for Pre-Battle scripts, but contain the 'new' intelligence level.
So, to make things clear, let's imagine a soldier and his two dogs
*Dog IQ = 2/3rds by default. 'Normal' attack is just the usual, but the 'smart' attack will be 'fang' (more potent), used against the weakest opp
*Soldier's counter-death script sets IQ to zero
*Dog now acts like a wild animal without a trainer
****************************
* THE TWO-STATUS CHECK PLUGIN *
****************************
This is very close to the code NFITC1 contributed. It looks for enemies with either two specified status conditions, or looks for enemies n one condition *or* another. By 'condition', I mean being either in or *out* of a status.
For instance, you can check for
* Opponents in both SLEEP and MINI
* Opponents both ASLEEP and NOT MINI'D
* Opponents either ASLEEP or MINI'D
* Opponents either ASLEEP or NOT MINI'D
This is useful when wanting to take heed of things like Resist or Reflect. It also allows you to compound effects, or limit difficulty by stopping monsters over-loading the party with nasty statuses. Want to cast debarrier on opponents with either protect or shell? Want to cast despell on enemies with regen but not slow? Fancy being able to haste allies in berserk but not confusion? This is the script to use.
<<OPTIONAL MP CHECKING SECTION START>>
02 2060
02 4140
80
61 INDEXOFATTACK
86
42
70 ADDRESS OF NEXTPLUGIN
<<OPTIONAL MP CHECKING SECTION END>>
12 0400
02 20A0
00 40XX
80
60 01
40
02 20A0
00 40YY
80
60 01
40
35
82
90
02 0400
70 ADDRESS OF NEXTPLUGIN
02 2070
02 0400
90
91
61 FFFF
90
Let's go over that again to explain how it works, and what you should change to make the plugin suit your purposes:
--optional MP checking section--
02 2060
02 4140
80
61 INDEXOFATTACK
86 <- checks if user has MP for the above attack
42
70 ADDRESS OF NEXT PLUGIN
--end of optional MP checking section--
12 0400
02 20A0 <- active opponents (2080 for allies)
00 40XX <- the first status to check, for instance, 4006 for confusion
80
60 01 <- are we looking for opponents who have the above status? If so, this should be 1. If we're looking for opponents who *don't*, then 0
40 <- create list of opponents with/without the status in question
02 20A0
00 40YY <- second status to check
80
60 01 <- again, 01 if we want opponents WITH the status, 00 if we want units WITHOUT the status.
40 <- we now have two lists: one of opps. with status X (in)active, and one of opps. with status Y (in)active. We're now going to compare them.
35 <- bitwise AND: creates a list of opps with both status X and status Y active. We use the opcode 36 instead if we're wanting an OR.
82 <- a random member of the resultant list (optional)
90 <- stores in 0400
02 0400 <- loads list from 0400
70 ADDRESS OF NEXT PLUGIN <- goes to next plugin if this list is empty
12 2070 <- tar address
02 0400 <- list data
90 <- uses list as target
91 <- POPS off default attack / prior set attacks
61 FFFF <- pushes data of new attack
***************************
* The Kamikaze / Darkside script *
***************************
This script has a monster look at its own HP, and use a certain attack if its HP is above or below a certain fraction. This is useful for darkside-like attacks/ souleater moves and blowup attacks. You don't want to use darkside (sacrifice a little HP for a powerful attack) when in low HP; nor do you want to explode when well-healed. So that's where this plugin comes in.
02 2060
02 4160
80
02 2060
02 4160
80
60 FF
33
60 X
32
42/43
70 ADDRESS OF NEXT PLUGIN
12 2070
02 20a0
82
90
91
61 INDEX OF ATTACK
Explained:
02 2060
02 4160
80 <-own HP
02 2060
02 4160
80
60 FF
33 <- own HP over 255
60 X <- this is our multiplier. This over 255 makes the fraction we're going to compare our HP with. 80h makes for half HP.
32
42/43 <- if HP below this fraction (42)/if HP above this fraction (43) ...then leave a TRUE on the stack
70 ADDRESS OF NEXT PLUGIN <- if there's a FALSE on the stack, go to next plugin
12 2070
02 20a0 <- so, random opponent
82
90
91
61 INDEX OF ATTACK
************************************************
* Use Attack A on LOCALVAR 0300 when LOCALVAR 0400 == 1 *
************************************************
This is a small script whose purpose may seem obscure at first. Basically, this allows for decisions to be set in counter scripts and the like. For instance, an ally might have a counter-death script that sets LVAR 0400 to 1 and puts the identity of its killer in LVAR0300. This script means that the downed monster's friends avenge its death.
Alternatively, a powerful fire attack might cause creatures to catch fire. A monster will, as a counter, flash, "The woods caught fire!" - from that point, attack A gets used, a fire-like attack called "Fire's outta control!". Think the Soulcage battle from FFIX.
You can replace the LocalVar 0300 with 20a0 (opponent list general) if you like. Here's the code:
00 0400
70 ADDRESS OF NEXT PLUGIN
12 2070
02 0300
(81)
90
91
61 INDEX OF ATTACK
So
00 0400
70 ADDRESS OF NEXT PLUGIN <- jumps if 0400 is FALSE
12 2070
02 0300 <- replace with 20a0 if you just want to target opponents as per usual
(81) <- optional: choose a random target of the above
90
91
61 INDEX OF ATTACK
***************************************
* ATTACK A on opp/ally with greatest/ least STAT *
***************************************
This is an attack that you may have seen a couple of times in vanilla FF7. It allows you to target the enemy with, say, the least HP or the greatest Magic stat; likewise you can target an ally with the highest Dex (taking advantage of haste, anyone?) or the lowest Defence (Barrier, for instance).
As always, this can be preceded with the 'MP checking section' seen elsewhere.
12 2070
02 20a0*
02 4100**
80
85***
82
90
91
61 INDEX OF ATTACK
With notes:
* Use 20a0 for opponents, 2080 for allies
** - This is the stat that you're interested in. Values include
HP - 4160
MP - 4140
MaxHP - 4180
MaxMP - 4150
STR - 4068
MAG - 4070
DEF - 4100
MDEF - 4110
DEX - 40a0
LUCK - 40a8
LEVEL - 4048
EVADE - 4078
MagEVADE - 4268
*** - 85 looks for the target with the smallest value of the stat we're interested in; 84 looks for the target with the largest.
I think that with these, we more or less have the basic plugins for just about every function. Now the issue is to refine what we have (if you want), mark up the typical values for 'address of next plugin' in each plugin, and maybe add a few specialist plugins for specific circumstances / consider writing counter and death scripts.