[FFVII] Enemy AI Script questions

  • Thread starter Thread starter DynamixDJ
  • Start date Start date
Status
Not open for further replies.
D

DynamixDJ

Guest
Hi Y'all! I'm currently working on the Enemy Module of my walkthrough, and I've decided that I want to break the AI script down for myself, instead of just blindly following the work the TFergusson has done in his Enemy Mechanics FAQ (the Eligor caused me quite a few problems).

Anyway, this is a fun project, and this webpage from the qhuimm wiki is the thing that I needed to fill in the blanks. I have had a few queries along the way though, so I've decided to ask them here.

1st Question:

Code: [Select]
Code:
If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )
Is this a check to see if ALL Players are in the front row, or if ANY of the Players are in the front row?

I had assumed it was ALL Players when I was looking at the script for MP/Guard Hound/Mono Drive/Grunt. All of these enemies uses AI script that's supposed to look at which row the player is in to choose their Attacks accordingly, but the script is illogical.

I've tried to work out what their patterns were supposed to be. Take the MP as an example, here is the opening setup for the AI Script:

Code: [Select]
Code:
0x000LovalVar:PlayerRow <- 00x006LovalVar:EnemyRow <- 00x00CLovalVar:SelfRow <- 00x012 If ( (BattleAddr(&AllEnemies).BattleAddr(&Row) == 0) )0x012 {0x01F LovalVar:EnemyRow <- LovalVar:EnemyRow AND 10x029 If ( (BattleAddr(&AllEnemies).BattleAddr(&Row) == 1) )0x029 {0x036 LovalVar:EnemyRow <- LovalVar:EnemyRow AND 20x040 If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x040 {0x04D LovalVar:PlayerRow <- LovalVar:PlayerRow AND 10x057 If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x057 {0x064 LovalVar:PlayerRow <- LovalVar:PlayerRow AND 20x06E If ( (BattleAddr(&Self).BattleAddr(&Row) == 0) )0x06E {0x07B LovalVar:SelfRow <- 00x081 }0x081 Else0x081 {0x084 LovalVar:SelfRow <- 1
So, seeing as TF has reported that flaws in the script prevent it from targetting th Players wors correctly, I wanted to see if I could fix the error, which is the AND function returning 0 for every check. If you swap the AND X functions with  <- X, then it would make sense to me. If All Players are in the front row; LovalVar:PlayerRow <- 1, and if All Players are in the Back Row, then LovalVar:PlayerRow <- 2, and if the Player Row values are mixed, then it stays as 0. That works.

The thing is, I've just started looking at the Grashtrike, and the first line reads:

Code: [Select]
Code:
If ( ( (BattleAddr(&AllPlayers).BattleAddr(&SlowStatus) == 0)
I had assumed that this meant that it was performing Silk ONLY if all players do not have Slow, however, after testing I can see that this actually means that it will perform Silk if ANY Player does not have Slow.

So, how does that translate to the MP? If at least one player is in the front, the var gets set to 1, and if any player is in the back, the var gets set to 2... that would mean that it can never be 0, and would bypass some of the script....

Here is the MP's full AI script for reference:

Code: [Select]
Code:
MAIN:0x000LovalVar:PlayerRow <- 00x006LovalVar:EnemyRow <- 00x00CLovalVar:SelfRow <- 00x012 If ( (BattleAddr(&AllEnemies).BattleAddr(&Row) == 0) )0x012 {0x01F LovalVar:EnemyRow <- LovalVar:EnemyRow AND 10x029 If ( (BattleAddr(&AllEnemies).BattleAddr(&Row) == 1) )0x029 {0x036 LovalVar:EnemyRow <- LovalVar:EnemyRow AND 20x040 If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x040 {0x04D LovalVar:PlayerRow <- LovalVar:PlayerRow AND 10x057 If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x057 {0x064 LovalVar:PlayerRow <- LovalVar:PlayerRow AND 20x06E If ( (BattleAddr(&Self).BattleAddr(&Row) == 0) )0x06E {0x07B LovalVar:SelfRow <- 00x081 }0x081 Else0x081 {0x084 LovalVar:SelfRow <- 10x08A If (Not  (LovalVar:SelfRow) )0x08A {0x091  If (LovalVar:PlayerRow == 1)0x091  {0x099  LocalVar:Random <- 40x09F   If (Not  (Random MOD LocalVar:Random) )0x09F   {0x0A8    If ( (LovalVar:PlayerRow AND 2 == 2) )0x0A8    {0x0B4    BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x0C3    }0x0C3    Else0x0C3    {0x0C6    BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x0CE   LocalVar:EnemyAttack <- 272 (Machine Gun)0x0D5   }0x0D5   Else0x0D5   {0x0D8    If ( (LovalVar:PlayerRow AND 1 == 1) )0x0D8    {0x0E4    BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x0F3    }0x0F3    Else0x0F3    {0x0F6    BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x0FE   LocalVar:EnemyAttack <- 273 (Tonfa)0x105  }0x105  Else0x105  {0x108   }0x108   Else0x108   {0x10B    If (LovalVar:PlayerRow == 2)0x10B    {0x110   LocalVar:Random <- 80x116    If (Not  (Random MOD LocalVar:Random) )0x116    {0x11F     If ( (LovalVar:PlayerRow AND 1 == 1) )0x11F     {0x12B     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x13A     }0x13A     Else0x13A     {0x13D     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x145    LocalVar:EnemyAttack <- 273 (Tonfa)0x14C    }0x14C    Else0x14C    {0x14F     If ( (LovalVar:PlayerRow AND 2 == 2) )0x14F     {0x15B     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x16A     }0x16A     Else0x16A     {0x16D     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x175    LocalVar:EnemyAttack <- 272 (Machine Gun)0x17C   }0x17C   Else0x17C   {0x17F    }0x17F    Else0x17F    {0x182   LocalVar:Random <- 20x188    If (Not  (Random MOD LocalVar:Random) )0x188    {0x191     If ( (LovalVar:PlayerRow AND 2 == 2) )0x191     {0x19D     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x1AC     }0x1AC     Else0x1AC     {0x1AF     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x1B7    LocalVar:EnemyAttack <- 272 (Machine Gun)0x1BE    }0x1BE    Else0x1BE    {0x1C1     If ( (LovalVar:PlayerRow AND 1 == 1) )0x1C1     {0x1CD     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x1DC     }0x1DC     Else0x1DC     {0x1DF     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x1E7    LocalVar:EnemyAttack <- 273 (Tonfa)0x1EE   }0x1EE   Else0x1EE   {0x1F1 POP(LovalVar:PlayerRow)0x1F2 }0x1F2 Else0x1F2 {0x1F5  If (LovalVar:PlayerRow == 1)0x1F5  {0x1FD  LocalVar:Random <- 40x203   If (Not  (Random MOD LocalVar:Random) )0x203   {0x20C    If ( (LovalVar:PlayerRow AND 1 == 1) )0x20C    {0x218    BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x227    }0x227    Else0x227    {0x22A    BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x232   LocalVar:EnemyAttack <- 273 (Tonfa)0x239   }0x239   Else0x239   {0x23C    If ( (LovalVar:PlayerRow AND 2 == 2) )0x23C    {0x248    BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x257    }0x257    Else0x257    {0x25A    BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x262   LocalVar:EnemyAttack <- 272 (Machine Gun)0x269  }0x269  Else0x269  {0x26C   }0x26C   Else0x26C   {0x26F    If (LovalVar:PlayerRow == 2)0x26F    {0x274   LocalVar:Random <- 80x27A    If (Not  (Random MOD LocalVar:Random) )0x27A    {0x283     If ( (LovalVar:PlayerRow AND 1 == 1) )0x283     {0x28F     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x29E     }0x29E     Else0x29E     {0x2A1     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x2A9    LocalVar:EnemyAttack <- 273 (Tonfa)0x2B0    }0x2B0    Else0x2B0    {0x2B3     If ( (LovalVar:PlayerRow AND 2 == 2) )0x2B3     {0x2BF     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x2CE     }0x2CE     Else0x2CE     {0x2D1     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x2D9    LocalVar:EnemyAttack <- 272 (Machine Gun)0x2E0   }0x2E0   Else0x2E0   {0x2E3    }0x2E3    Else0x2E3    {0x2E6   LocalVar:Random <- 60x2EC    If (Not  (Random MOD LocalVar:Random) )0x2EC    {0x2F5     If ( (LovalVar:PlayerRow AND 1 == 1) )0x2F5     {0x301     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x310     }0x310     Else0x310     {0x313     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x31B    LocalVar:EnemyAttack <- 273 (Tonfa)0x322    }0x322    Else0x322    {0x325     If ( (LovalVar:PlayerRow AND 2 == 2) )0x325     {0x331     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x340     }0x340     Else0x340     {0x343     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x34B    LocalVar:EnemyAttack <- 272 (Machine Gun)0x352   }0x352   Else0x352   {0x355 POP(LovalVar:PlayerRow)0x356Perform(LocalVar:EnemyAttack, EnemyAttack)0x35CSCRIPT END
Here's how I have deciphered that, assuming that the AND functions are actually PUSH functions, and that the check in question is looking for ALL players in Front/Back Row (as opposed to any player):


Code: [Select]
Code:
/----------------------------------------------------------------------------\|   BATTLE PLAN: (Unused)                                                    ||                                                                            ||  If All Players are in Back Row: 1/4 Chance use Machine Gun on Rnd Target  ||                                  3/4 Chance use <Tonfa> on Rnd Target      ||                                                                            ||  If All Players are in Front Row: 1/8 Chance use <Tonfa> on Rnd Target     ||                                   7/8 Chance use Machine Gun on Rnd Target ||                                                                            ||  If the Players Rows are mixed:                                            ||   If MP is in the Front Row: 1/2 Chance use Machine Gun on Rnd Target      ||                              1/2 Chance use <Tonfa> on Rnd Target          ||                                                                            ||   If MP is in the Back Row:  1/6 Chance use <Tonfa> on Rnd Target          ||                              5/6 Chance use Machine Gun on Rnd Target      |\----------------------------------------------------------------------------/

I'm not 100% sure this is correct now. If anyone could clarify for me how the MP's correct AI script is supposed to work, that would be great!
 
Last edited:
The first question I'd have is where you're getting the text version of these scripts from? I'm assuming these are probably disassembled from ProudClod. The word of caution there is to worry about the lesser known opcodes that have a higher chance of inaccuracies, although i don't know if any of these lesser known opcodes are used for MP, not only lesser known opcodes but also special cases that maybe weren't considered.  It's possible that some of these outputs could have errors, but NFITC would be the one to comment on how confident he is with the accuracy of that output.

It also looks like there are several layers of IFs, but I don't see any closing brackets, which is important because that will determine whether they are nested or sequential.
 
I'm first disassembling it via Proud Clod, then using the Find-All > Replace-All feature in my .txt editor to assign the argument values to the variable mapping as you see. This is where I'm getting the info for the mapping:

http://wiki.ffrtt.ru/index.php/FF7/Battle/Battle_Scenes/Battle_AI_Addresses

Here is a list of variables that I've been working with, I'm adding to the list as and when I need to:

Code: [Select]
Code:
BattleAddr(&2050) = BattleAddr(&ActiveActors)BattleAddr(&2060) = BattleAddr(&Self)BattleAddr(&2070) = BattleAddr(&TargetSelected)BattleAddr(&2080) = BattleAddr(&AllEnemies)BattleAddr(&2090) = BattleAddr(&ActiveEnemies)BattleAddr(&20A0) = BattleAddr(&AllPlayers)BattleAddr(&20B0) = BattleAddr(&ActivePlayers)BattleAddr(&4000) = BattleAddr(&DeathStatus)BattleAddr(&4001) = BattleAddr(&NearDeathStatus)BattleAddr(&4002) = BattleAddr(&SleepStatus)BattleAddr(&4003) = BattleAddr(&PoisonStatus)BattleAddr(&4004) = BattleAddr(&SadnessStatus)BattleAddr(&4005) = BattleAddr(&FuryStatus)BattleAddr(&4006) = BattleAddr(&ConfusionStatus)BattleAddr(&4007) = BattleAddr(&SilenceStatus)BattleAddr(&4008) = BattleAddr(&HasteStatus)BattleAddr(&4009) = BattleAddr(&SlowStatus)BattleAddr(&400A) = BattleAddr(&StopStatus)BattleAddr(&400B) = BattleAddr(&FrogStatus)BattleAddr(&400C) = BattleAddr(&SmallStatus)BattleAddr(&400D) = BattleAddr(&SlowNumbStatus)BattleAddr(&400E) = BattleAddr(&PetrifyStatus)BattleAddr(&400F) = BattleAddr(&RegenStatus)BattleAddr(&4010) = BattleAddr(&BarrierStatus)BattleAddr(&4011) = BattleAddr(&MBarrierStatus)BattleAddr(&4012) = BattleAddr(&ReflectStatus)BattleAddr(&4013) = BattleAddr(&DualStatus)BattleAddr(&4014) = BattleAddr(&ShieldStatus)BattleAddr(&4015) = BattleAddr(&DSentenceStatus)BattleAddr(&4016) = BattleAddr(&ManipulateStatus)BattleAddr(&4017) = BattleAddr(&BerserkStatus)BattleAddr(&4018) = BattleAddr(&PeerlessStatus)BattleAddr(&4019) = BattleAddr(&ParalyzedStatus)BattleAddr(&401A) = BattleAddr(&DarknessStatus)BattleAddr(&401B) = BattleAddr(&DualDrainStatus)BattleAddr(&401C) = BattleAddr(&DeathForceStatus)BattleAddr(&401D) = BattleAddr(&ResistStatus)BattleAddr(&401E) = BattleAddr(&LuckyGirlStatus)BattleAddr(&401F) = BattleAddr(&ImprisonedStatus)BattleAddr(&4026) = BattleAddr(&Row)BattleAddr(&4060) = BattleAddr(&PlayerID)BattleAddr(&4080) = BattleAddr(&IdleAnimID)BattleAddr(&4088) = BattleAddr(&DamagedAnimID)BattleAddr(&40D0) = BattleAddr(&LastAttacker)BattleAddr(&4100) = BattleAddr(&Def)BattleAddr(&4110) = BattleAddr(&MDef)BattleAddr(&4140) = BattleAddr(&CurrentMP)BattleAddr(&4150) = BattleAddr(&MaxMP)BattleAddr(&4160) = BattleAddr(&CurrentHP)BattleAddr(&4180) = BattleAddr(&MaxHP)
 
BattleAddr(&4020)
BattleAddr(&4022)
BattleAddr(&4023)
BattleAddr(&4024)

What do these do? They can be found after the Action 0138 Escape is performed, which is used by Prowler, Bandit and Vice:


Code: [Select]
Code:
BattleAddr(&TargetSelected) <- BattleAddr(&Self)Perform("Escape"[0138], EnemyAttack)BattleAddr(&Self).BattleAddr(&4020) <- 0BattleAddr(&Self).BattleAddr(&4023) <- 0BattleAddr(&Self).BattleAddr(&4022) <- 0BattleAddr(&Self).BattleAddr(&4024) <- 0
Edit - Same vars are found on the Hell House [2C] (1st Form). I guess this has something to do with stat transfers when an enemy leaves the battle

Double edit - Perhaps.... Exp, Gil, AP and....... ???? - Another edit - Nope, AP is 0x42BO, Gil is 0x42C0, and EXP is 0x42E0. The mystery remains...

Another edit - OK, I have a suspicion that they could be setting the main enemy battle flags:

BattleAddr(&4020) = 0x0001 OFF = Invisible
BattleAddr(&4021) = 0x0002 OFF = Groups the enemies together during a PINCER ATTACK.
BattleAddr(&4022) = 0x0004 OFF = ???? (Bad Rap Sample and Poodler Sample only)
BattleAddr(&4023) = 0x0008 OFF = Non-Targetable
BattleAddr(&4024) =  0x0010 OFF = Disables Main AI Script

This would fit, seeing as the four variables that are used are 4020 4022 4023 & 4024, meaning the 0x0002 flag (4021) wouldn't be set during the instances in which an enemy removes itself from battle, as it wouldn't need to. Edit - the quimm wiki's description for 4021 is "Ally of current actor", which could fit....

Bear in mind that with the Hell House and Aero Combatant are turning the same vars ON for the subsequent enemy that takes it's place:

Aero Combatant (1st form):
Code: [Select]
Code:
PRE-BATTLE:0x000LocalVar:TransformID <-  (BitCount(BattleAddr(&Self).BattleAddr(&PlayerID)) == BattleAddr(&ActiveActors).BattleAddr(&PlayerID)) 0x014LocalVar:TransformID <-  (LocalVar:TransformID.BattleAddr(&4120) == 47) 0x022SCRIPT ENDMAIN:0x000BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x008 If (Not  (Random MOD 3) )0x008 {0x010 Perform("Kick"[0158], EnemyAttack)0x016 }0x016 Else0x016 {0x019 Perform("Propeller"[0159], EnemyAttack)0x01FSCRIPT ENDGENERAL COUNTER:0x000 If (Not  (Random MOD 2) )0x000 {0x008 BattleAddr(&TargetSelected) <- BattleAddr(&Self)0x00F Perform([011F], EnemyAttack)0x015 BattleAddr(&Self).BattleAddr(&4020) <- 00x01F BattleAddr(&Self).BattleAddr(&4023) <- 00x029 LocalVar:TransformID.BattleAddr(&4020) <- 10x033 LocalVar:TransformID.BattleAddr(&4023) <- 10x03D LocalVar:TransformID.BattleAddr(&4022) <- 10x047 LocalVar:TransformID.BattleAddr(&4024) <- 10x051 TransferStatus(BattleAddr(&Self), LocalVar:TransformID)0x058 BattleAddr(&Self).BattleAddr(&4020) <- 00x062 BattleAddr(&Self).BattleAddr(&4023) <- 00x06C BattleAddr(&Self).BattleAddr(&4022) <- 00x076 BattleAddr(&Self).BattleAddr(&4024) <- 00x080SCRIPT ENDDEATH COUNTER:0x000LocalVar:TransformID.BattleAddr(&4020) <- 00x00ALocalVar:TransformID.BattleAddr(&4023) <- 00x014LocalVar:TransformID.BattleAddr(&4022) <- 00x01ELocalVar:TransformID.BattleAddr(&4024) <- 00x028SCRIPT END
I can't see anywhere else in the script that handles enabling of the AI script/visibility/targetability of the new enemy.

On a side note, that 0x0004 Enemy Battle Flag that I'm unsure of could be disabling battle rewards, seeing as Bad Rap Sample and Poodler Sample do not give any rewards....
 
Last edited:
Oh this is the thread for me. :D

Regarding to the (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) conundrum. This, as you noticed, translates to if there are NO players in the back row. This has to do with the data type that is returned by the AllPlayers address. It's a 2X type variable meaning it returns a list (of 3 in this case) values with the state of each player. When that is masked by row, it changes those 3 values to each players' row values. In this case, if ANY of them are zero then the condition passes. That's just the nature of the 2X variable type and conditional checks. I wish there were a non-ugly way to indicate that in the AI editor.

Now to the 4022 variable, I believe this unsetting this value indicates the enemy does not need to be defeated in order for the battle to end. I think some set pieces set this in their init scripts. Check the helicopter in the Rufus battle and the truck and tiny bronco in the Palmer battle. Just going by memory here, but I'm pretty sure they unset the 4022 flag. A few bosses do as well IIRC. Check Mystery Ninja Custom 7 script and Diamond Weapon's Death script.
 
Ah, so it's not "All players in the Front row", it's  "No Players in the Back Row", which is the same thing when it comes to rows. With the Slow check, it's not as I initially thought "All Players without Slow", but rather "No Player with Slow". This fits, thanks!

In regards to 4023 and 4024, I'm 99% certain that I'm correct in thinking that 4023 is Actor's Targetability, and 4024 is Actor's AI Script enabled/disabled, after having dissected Reno:Turks I and his Pyramids.

If I'm right in thinking that, then that would mean that 4020 - 4024 does indeed reflect the Actor's Battle Flags as mentioned. And, if I'm right about that. then that means that you have solved the mystery of 0x0004 Enemy Battle Flag; as mentioned, Poodler Sample and Bad Rap sample are the only enemies in the game that go into the fight with this flag disabled. Your description of the actor needeing to be defetaed for the Battle to end fits perfectly, not just with the P/BR Sample, but also with the instances in which I've witnessed the 4023 flag be enabled/disabled via the AI script.

I'm going to jot down 4023 as you've described, and I'm gonna keep going through each enemy sequentially keeping my eyes open for consistency, but I'm fairly happy the shoe fits. Thanks!

I must say, this is quite a fun project to do, seeing as I don't think anyone has worked with the AI sctipt down in the way I currently am, which is to try to break each enemy's "Battle Plan" down into something the layman can understand. TF did a fantastic job, but I'm trying to do one better.

Take the Eligor, for example. I've converted this:

Code: [Select]
Code:
40 - [28] EligorLocalVar:0000 = LocalVar:OpenAttackLocalVar:0020 = LocalVar:StageLocalVar:0040 = LocalVar:1stChrLocalVar:0060 = LocalVar:2ndChrLocalVar:0080 = LovalVar:3rdChrBattleAddr(&2060) = BattleAddr(&Self)BattleAddr(&2070) = BattleAddr(&TargetSelected)BattleAddr(&20A0) = BattleAddr(&AllPlayers)BattleAddr(&4000) = BattleAddr(&DeathStatus)BattleAddr(&4002) = BattleAddr(&SleepStatus)BattleAddr(&4007) = BattleAddr(&SilenceStatus)BattleAddr(&4026) = BattleAddr(&Row)BattleAddr(&4140) = BattleAddr(&CurrentMP)BattleAddr(&4160) = BattleAddr(&CurrentHP)BattleAddr(&4180) = BattleAddr(&MaxHP)MAIN:0x000 If (Not  (LocalVar:OpenAttack) )0x000 {0x007  If (Random MOD 3 == 0)0x007  {0x010   If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Silence [000D])) )0x010   {0x01E   BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x02D   Perform("Silence"[000D], EnemyAttack)0x032   }0x032   Else0x032   {0x035    If (Not  (LocalVar:Stage) )0x035    {0x03C     If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x03C     {0x049     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x058     }0x058     Else0x058     {0x05B     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x063    Perform("Sword Attack"[014A], EnemyAttack)0x069    }0x069    Else0x069    {0x06C    LocalVar:1stChr <- FlagBit(0)0x073    LocalVar:2ndChr <- FlagBit(1)0x07A    LovalVar:3rdChr <- FlagBit(2)0x081     If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x081     {0x08E     BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x095     Perform("Mono Laser"[014B], EnemyAttack)0x09B     If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x09B     {0x0A8     BattleAddr(&TargetSelected) <- LocalVar:1stChr0x0AF     Perform("Mono Laser"[014B], EnemyAttack)0x0B5     If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x0B5     {0x0C2     BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x0C9     Perform("Mono Laser"[014B], EnemyAttack)0x0CF  }0x0CF  Else0x0CF  {0x0D2   }0x0D2   Else0x0D2   {0x0D5    If (Random MOD 3 == 1)0x0D5    {0x0DA    If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Sleepel [000B])) )0x0DA    {0x0E8    BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x0F7    Perform("Sleepel"[000B], EnemyAttack)0x0FC    }0x0FC    Else0x0FC    {0x0FF     If (Not  (LocalVar:Stage) )0x0FF     {0x106      If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x106      {0x113      BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x122      }0x122      Else0x122      {0x125      BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x12D     Perform("Sword Attack"[014A], EnemyAttack)0x133     }0x133     Else0x133     {0x136     LocalVar:1stChr <- FlagBit(0)0x13D     LocalVar:2ndChr <- FlagBit(1)0x144     LovalVar:3rdChr <- FlagBit(2)0x14B      If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x14B      {0x158      BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x15F      Perform("Mono Laser"[014B], EnemyAttack)0x165      If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x165      {0x172      BattleAddr(&TargetSelected) <- LocalVar:1stChr0x179      Perform("Mono Laser"[014B], EnemyAttack)0x17F      If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x17F      {0x18C      BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x193      Perform("Mono Laser"[014B], EnemyAttack)0x199   }0x199   Else0x199   {0x19C    }0x19C    Else0x19C    {0x19F   }0x19F   Else0x19F   {0x1A2 POP(Random MOD 3)0x1A3 LocalVar:OpenAttack <- 10x1A9 }0x1A9 Else0x1A9 {0x1AC  If (Not  (LocalVar:Stage) )0x1AC  {0x1B3   If (Random MOD 12 == 0)0x1B3   {0x1BC   }0x1BC   Else0x1BC   {0x1BF    If (Random MOD 12 == 1)0x1BF    {0x1C4    If ( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x1C4    {0x1D1     If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Silence [000D])) )0x1D1     {0x1DF     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x1EE     Perform("Silence"[000D], EnemyAttack)0x1F3     }0x1F3     Else0x1F3     {0x1F6      If (Not  (LocalVar:Stage) )0x1F6      {0x1FD       If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x1FD       {0x20A       BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x219       }0x219       Else0x219       {0x21C       BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x224      Perform("Sword Attack"[014A], EnemyAttack)0x22A      }0x22A      Else0x22A      {0x22D      LocalVar:1stChr <- FlagBit(0)0x234      LocalVar:2ndChr <- FlagBit(1)0x23B      LovalVar:3rdChr <- FlagBit(2)0x242       If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x242       {0x24F       BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x256       Perform("Mono Laser"[014B], EnemyAttack)0x25C       If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x25C       {0x269       BattleAddr(&TargetSelected) <- LocalVar:1stChr0x270       Perform("Mono Laser"[014B], EnemyAttack)0x276       If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x276       {0x283       BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x28A       Perform("Mono Laser"[014B], EnemyAttack)0x290    }0x290    Else0x290    {0x293     If ( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x293     {0x2A0      If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Sleepel [000B])) )0x2A0      {0x2AE      BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x2BD      Perform("Sleepel"[000B], EnemyAttack)0x2C2      }0x2C2      Else0x2C2      {0x2C5       If (Not  (LocalVar:Stage) )0x2C5       {0x2CC        If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x2CC        {0x2D9        BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x2E8        }0x2E8        Else0x2E8        {0x2EB        BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x2F3       Perform("Sword Attack"[014A], EnemyAttack)0x2F9       }0x2F9       Else0x2F9       {0x2FC       LocalVar:1stChr <- FlagBit(0)0x303       LocalVar:2ndChr <- FlagBit(1)0x30A       LovalVar:3rdChr <- FlagBit(2)0x311        If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x311        {0x31E        BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x325        Perform("Mono Laser"[014B], EnemyAttack)0x32B        If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x32B        {0x338        BattleAddr(&TargetSelected) <- LocalVar:1stChr0x33F        Perform("Mono Laser"[014B], EnemyAttack)0x345        If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x345        {0x352        BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x359        Perform("Mono Laser"[014B], EnemyAttack)0x35F     }0x35F     Else0x35F     {0x362      If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x362      {0x36F      BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x37E      }0x37E      Else0x37E      {0x381      BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x389     Perform("Sword Attack"[014A], EnemyAttack)0x38F   }0x38F   Else0x38F   {0x392    }0x392    Else0x392    {0x395     If (Random MOD 12 == 2)0x395     {0x39A    }0x39A    Else0x39A    {0x39D     If (Random MOD 12 == 3)0x39D     {0x3A2     If ( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x3A2     {0x3AF      If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Sleepel [000B])) )0x3AF      {0x3BD      BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x3CC      Perform("Sleepel"[000B], EnemyAttack)0x3D1      }0x3D1      Else0x3D1      {0x3D4       If (Not  (LocalVar:Stage) )0x3D4       {0x3DB        If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x3DB        {0x3E8        BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x3F7        }0x3F7        Else0x3F7        {0x3FA        BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x402       Perform("Sword Attack"[014A], EnemyAttack)0x408       }0x408       Else0x408       {0x40B       LocalVar:1stChr <- FlagBit(0)0x412       LocalVar:2ndChr <- FlagBit(1)0x419       LovalVar:3rdChr <- FlagBit(2)0x420        If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x420        {0x42D        BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x434        Perform("Mono Laser"[014B], EnemyAttack)0x43A        If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x43A        {0x447        BattleAddr(&TargetSelected) <- LocalVar:1stChr0x44E        Perform("Mono Laser"[014B], EnemyAttack)0x454        If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x454        {0x461        BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x468        Perform("Mono Laser"[014B], EnemyAttack)0x46E     }0x46E     Else0x46E     {0x471      If ( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x471      {0x47E       If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Silence [000D])) )0x47E       {0x48C       BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x49B       Perform("Silence"[000D], EnemyAttack)0x4A0       }0x4A0       Else0x4A0       {0x4A3        If (Not  (LocalVar:Stage) )0x4A3        {0x4AA         If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x4AA         {0x4B7         BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x4C6         }0x4C6         Else0x4C6         {0x4C9         BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x4D1        Perform("Sword Attack"[014A], EnemyAttack)0x4D7        }0x4D7        Else0x4D7        {0x4DA        LocalVar:1stChr <- FlagBit(0)0x4E1        LocalVar:2ndChr <- FlagBit(1)0x4E8        LovalVar:3rdChr <- FlagBit(2)0x4EF         If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x4EF         {0x4FC         BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x503         Perform("Mono Laser"[014B], EnemyAttack)0x509         If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x509         {0x516         BattleAddr(&TargetSelected) <- LocalVar:1stChr0x51D         Perform("Mono Laser"[014B], EnemyAttack)0x523         If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x523         {0x530         BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x537         Perform("Mono Laser"[014B], EnemyAttack)0x53D      }0x53D      Else0x53D      {0x540       If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x540       {0x54D       BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x55C       }0x55C       Else0x55C       {0x55F       BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x567      Perform("Sword Attack"[014A], EnemyAttack)0x56D    }0x56D    Else0x56D    {0x570     }0x570     Else0x570     {0x573      If (Random MOD 12 == 4)0x573      {0x578     }0x578     Else0x578     {0x57B      If (Random MOD 12 == 5)0x57B      {0x580     }0x580     Else0x580     {0x583      If (Random MOD 12 == 6)0x583      {0x588     }0x588     Else0x588     {0x58B      If (Random MOD 12 == 7)0x58B      {0x590      If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x590      {0x59D      BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 1) )0x5AC      }0x5AC      Else0x5AC      {0x5AF      BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x5B7     Perform("Mono Laser"[014B], EnemyAttack)0x5BD     }0x5BD     Else0x5BD     {0x5C0      }0x5C0      Else0x5C0      {0x5C3      If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x5C3      {0x5D0      BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x5DF      }0x5DF      Else0x5DF      {0x5E2      BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x5EA     Perform("Sword Attack"[014A], EnemyAttack)0x5F0     }0x5F0     Else0x5F0     {0x5F3  POP(Random MOD 12)0x5F4  }0x5F4  Else0x5F4  {0x5F7   If (Random MOD 5 == 0)0x5F7   {0x600    If ( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x600    {0x60D     If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Silence [000D])) )0x60D     {0x61B     BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x62A     Perform("Silence"[000D], EnemyAttack)0x62F     }0x62F     Else0x62F     {0x632      If (Not  (LocalVar:Stage) )0x632      {0x639       If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x639       {0x646       BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x655       }0x655       Else0x655       {0x658       BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x660      Perform("Sword Attack"[014A], EnemyAttack)0x666      }0x666      Else0x666      {0x669      LocalVar:1stChr <- FlagBit(0)0x670      LocalVar:2ndChr <- FlagBit(1)0x677      LovalVar:3rdChr <- FlagBit(2)0x67E       If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x67E       {0x68B       BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x692       Perform("Mono Laser"[014B], EnemyAttack)0x698       If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x698       {0x6A5       BattleAddr(&TargetSelected) <- LocalVar:1stChr0x6AC       Perform("Mono Laser"[014B], EnemyAttack)0x6B2       If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x6B2       {0x6BF       BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x6C6       Perform("Mono Laser"[014B], EnemyAttack)0x6CC    }0x6CC    Else0x6CC    {0x6CF     If ( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x6CF     {0x6DC      If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Sleepel [000B])) )0x6DC      {0x6EA      BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x6F9      Perform("Sleepel"[000B], EnemyAttack)0x6FE      }0x6FE      Else0x6FE      {0x701       If (Not  (LocalVar:Stage) )0x701       {0x708        If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x708        {0x715        BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x724        }0x724        Else0x724        {0x727        BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x72F       Perform("Sword Attack"[014A], EnemyAttack)0x735       }0x735       Else0x735       {0x738       LocalVar:1stChr <- FlagBit(0)0x73F       LocalVar:2ndChr <- FlagBit(1)0x746       LovalVar:3rdChr <- FlagBit(2)0x74D        If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x74D        {0x75A        BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x761        Perform("Mono Laser"[014B], EnemyAttack)0x767        If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x767        {0x774        BattleAddr(&TargetSelected) <- LocalVar:1stChr0x77B        Perform("Mono Laser"[014B], EnemyAttack)0x781        If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x781        {0x78E        BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x795        Perform("Mono Laser"[014B], EnemyAttack)0x79B     }0x79B     Else0x79B     {0x79E     LocalVar:1stChr <- FlagBit(0)0x7A5     LocalVar:2ndChr <- FlagBit(1)0x7AC     LovalVar:3rdChr <- FlagBit(2)0x7B3      If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x7B3      {0x7C0      BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x7C7      Perform("Mono Laser"[014B], EnemyAttack)0x7CD      If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x7CD      {0x7DA      BattleAddr(&TargetSelected) <- LocalVar:1stChr0x7E1      Perform("Mono Laser"[014B], EnemyAttack)0x7E7      If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x7E7      {0x7F4      BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x7FB      Perform("Mono Laser"[014B], EnemyAttack)0x801   }0x801   Else0x801   {0x804    }0x804    Else0x804    {0x807     If (Random MOD 5 == 1)0x807     {0x80C     If ( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x80C     {0x819      If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Sleepel [000B])) )0x819      {0x827      BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SleepStatus) == 0) )0x836      Perform("Sleepel"[000B], EnemyAttack)0x83B      }0x83B      Else0x83B      {0x83E       If (Not  (LocalVar:Stage) )0x83E       {0x845        If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x845        {0x852        BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x861        }0x861        Else0x861        {0x864        BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x86C       Perform("Sword Attack"[014A], EnemyAttack)0x872       }0x872       Else0x872       {0x875       LocalVar:1stChr <- FlagBit(0)0x87C       LocalVar:2ndChr <- FlagBit(1)0x883       LovalVar:3rdChr <- FlagBit(2)0x88A        If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x88A        {0x897        BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x89E        Perform("Mono Laser"[014B], EnemyAttack)0x8A4        If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x8A4        {0x8B1        BattleAddr(&TargetSelected) <- LocalVar:1stChr0x8B8        Perform("Mono Laser"[014B], EnemyAttack)0x8BE        If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x8BE        {0x8CB        BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x8D2        Perform("Mono Laser"[014B], EnemyAttack)0x8D8     }0x8D8     Else0x8D8     {0x8DB      If ( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x8DB      {0x8E8       If ( (BattleAddr(&Self).BattleAddr(&CurrentMP) >= MPCost(Silence [000D])) )0x8E8       {0x8F6       BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&SilenceStatus) == 0) )0x905       Perform("Silence"[000D], EnemyAttack)0x90A       }0x90A       Else0x90A       {0x90D        If (Not  (LocalVar:Stage) )0x90D        {0x914         If ( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x914         {0x921         BattleAddr(&TargetSelected) <- RandomBit( (BattleAddr(&AllPlayers).BattleAddr(&Row) == 0) )0x930         }0x930         Else0x930         {0x933         BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x93B        Perform("Sword Attack"[014A], EnemyAttack)0x941        }0x941        Else0x941        {0x944        LocalVar:1stChr <- FlagBit(0)0x94B        LocalVar:2ndChr <- FlagBit(1)0x952        LovalVar:3rdChr <- FlagBit(2)0x959         If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x959         {0x966         BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x96D         Perform("Mono Laser"[014B], EnemyAttack)0x973         If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x973         {0x980         BattleAddr(&TargetSelected) <- LocalVar:1stChr0x987         Perform("Mono Laser"[014B], EnemyAttack)0x98D         If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x98D         {0x99A         BattleAddr(&TargetSelected) <- LovalVar:3rdChr0x9A1         Perform("Mono Laser"[014B], EnemyAttack)0x9A7      }0x9A7      Else0x9A7      {0x9AA      LocalVar:1stChr <- FlagBit(0)0x9B1      LocalVar:2ndChr <- FlagBit(1)0x9B8      LovalVar:3rdChr <- FlagBit(2)0x9BF       If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0x9BF       {0x9CC       BattleAddr(&TargetSelected) <- LocalVar:2ndChr0x9D3       Perform("Mono Laser"[014B], EnemyAttack)0x9D9       If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0x9D9       {0x9E6       BattleAddr(&TargetSelected) <- LocalVar:1stChr0x9ED       Perform("Mono Laser"[014B], EnemyAttack)0x9F3       If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0x9F3       {0xA00       BattleAddr(&TargetSelected) <- LovalVar:3rdChr0xA07       Perform("Mono Laser"[014B], EnemyAttack)0xA0D    }0xA0D    Else0xA0D    {0xA10     }0xA10     Else0xA10     {0xA13    LocalVar:1stChr <- FlagBit(0)0xA1A    LocalVar:2ndChr <- FlagBit(1)0xA21    LovalVar:3rdChr <- FlagBit(2)0xA28     If ( (LocalVar:2ndChr.BattleAddr(&DeathStatus) == 0) )0xA28     {0xA35     BattleAddr(&TargetSelected) <- LocalVar:2ndChr0xA3C     Perform("Mono Laser"[014B], EnemyAttack)0xA42     If ( (LocalVar:1stChr.BattleAddr(&DeathStatus) == 0) )0xA42     {0xA4F     BattleAddr(&TargetSelected) <- LocalVar:1stChr0xA56     Perform("Mono Laser"[014B], EnemyAttack)0xA5C     If ( (LovalVar:3rdChr.BattleAddr(&DeathStatus) == 0) )0xA5C     {0xA69     BattleAddr(&TargetSelected) <- LovalVar:3rdChr0xA70     Perform("Mono Laser"[014B], EnemyAttack)0xA76    }0xA76    Else0xA76    {0xA79  POP(Random MOD 5)0xA7ASCRIPT ENDGENERAL COUNTER:0x000 If ( (BattleAddr(&Self).BattleAddr(&CurrentHP) <= BattleAddr(&Self).BattleAddr(&MaxHP) / 2) )0x000 {0x015 LocalVar:Stage <- 10x01B }0x01B Else0x01B {0x01E LocalVar:Stage <- 00x024SCRIPT END
Into this:

Code: [Select]
Code:
/----------------------------------------------------------------------------\|   BATTLE PLAN:                                                             ||                                                                            ||  Opening AttacK: 1/3 Chance use Silence on Rnd Target without Silence;     ||                       If Eligor's MP < 24:                                 ||                        Eligor's HP  > 50%: Use Phase 1 Attack              ||                        Eligor's HP <= 50%: Use Phase 2 Attack              ||                                                                            ||                  1/3 Chance use Sleepel on Rnd Target without Sleep,       ||                        If Eligor's MP < 8:                                 ||                         Eligor's HP  > 50%: Use Phase 1 Attack             ||                         Eligor's HP <= 50%: Use Phase 2 Attack             ||                                                                            ||                  1/3 Chance skip a turn                                    ||                                                                            ||                                                                            ||  Phase 1 Attack: Use <Sword Attack> on Rnd Target in Front Row; If All     ||                   Targets are in Back Row, select Rnd Target               ||                                                                            ||  Phase 2 Attack: Use Mono Laser on 2nd Target; If 2nd Target has Death, do ||                   nothing                                                  ||                  Use Mono Laser on 1st Target; If 1st Target has Death, do ||                   nothing (Follow-Up Attack)                               ||                  Use Mono Laser on 3rd Target; If 3rd Target has Death, do ||                   nothing (Follow-Up Attack)                               ||                                                                            ||                                                                            ||  Phase 1: (Repeats)                                                        ||                                                                            ||   Eligor's HP > 50%:                                                       ||                                                                            ||    1/6 Chance: Use Silence on Rnd Target without Silence; If Eligor's      ||                 MP < 24, use Phase 1 Attack                                ||                                                                            ||                If All Targets have Silence, use Sleepel on Rnd Target; If  ||                 Eligor's MP < 8, use Phase 1 Attack                        ||                                                                            ||                If All Targets have Sleep, use Phase 1 Attack               ||                                                                            ||    1/6 Chance: Use Sleepel on Rnd Target without Sleep; If Eligor's        ||                 MP < 8, use Phase 1 Attack                                 ||                                                                            ||                If All Targets have Sleep, use Silence on Rnd Target; If    ||                 Eligor's MP < 24, use Phase 1 Attack                       ||                                                                            ||                If All Targets have Silence, use Phase 1 Attack             ||                                                                            ||    2/6 Chance: Use Mono Laser on Rnd Target in Back Row; If All Targets    ||                 are in Front Row, select Rnd Target                        ||                                                                            ||    2/6 Chance: Use Phase 1 Attack                                          ||                                                                            ||                                                                            ||  Phase 2: (Repeats)                                                        ||                                                                            ||   Eligor's HP <= 50%:                                                      ||                                                                            ||    1/5 Chance: Use Silence on Rnd Target without Silence; If Eligor's      ||                 MP < 24, use Phase 2 Attack                                ||                                                                            ||                If All Targets have Silence, use Sleepel on Rnd Target; If  ||                 Eligor's MP < 8, use Phase 2 Attack                        ||                                                                            ||                If All Targets have Sleep, use Phase 2 Attack               ||                                                                            ||    1/5 Chance: Use Sleepel on Rnd Target without Sleep; If Eligor's        ||                 MP < 8, use Phase 2 Attack                                 ||                                                                            ||                If All Targets have Sleep, use Silence on Rnd Target; If    ||                 Eligor's MP < 24, use Phase 2 Attack                       ||                                                                            ||                If All Targets have Silence, use Phase 2 Attack             ||                                                                            ||    3/5 Chance: Use Phase 2 Attack                                          |\----------------------------------------------------------------------------/
Once I'm done I'm gonna upload each individual enemy to Paste Bin. I'm also gonna C+P the raw AI Script as opcodes+arguments, so that when the time finally comes to writing my own AI script I'll be able to take snippets from each enemy to build my own custom script. It's a really fun project! I'm sure I'll be back  soon with my next question :)

On a side note NFI, do you use Discord much? I've sent you a PM in the past but you never got...
 
Last edited:
Eligor made me rage quit. I understand what it was doing, but he got WAY more of a detailed script than he needed. It's main script is longer and convoluted than Ruby Weapon's; And HE controls his tentacles!

You have the 4020, 4021, 4023 and 4024 addresses correct to my notes. I haven't tested 4022 very much. It's used in 59 different enemies (none of which are the Hojo samples. Not sure where you get that they are) and they are typically enemies that have multiple parts and are controlling certain parts. Some exceptions are enemies like Chocobos (which is why I think this flag is "not necessary to defeat to win").

I used to check Discord a lot. I haven't been on lately due to lack of time. I'll give it a check now though. I did get that PM, but I didn't have anything constructive to add. I'm almost daily checking this site though.
 
Last edited:
The reason I know that Hojo's samples use that flag is that I spotted it when working on my Enemy Formation Charts.

Look at offset 0x0C in the Battle Formation Data.These four bytes only consider the last 5 bits, and these 5 bits are what the 4020 - 4024 addresses pull.
0x01 I think isn't the Actor's visibility, but rather its "presence" in the battle. 0x02 is more accurately "Enemy grouping during a pincer attack" 0 = group one, and 1= group two (or the other way round, I can't remember). 0x04 is unknown, but you've allocated that as "Indicates if Actor needs to die for Battle to end".

The only Formation to use the "FFE3" Battle Formation Flag (Non-Targetable, Main AI script disabled and 0x04 OFF) is formation 358h, specifically the BR Sample and P Sample enemies. These are the only two enemies in the game that enter the battle with the 0x04 flag off; all other instances of that flag being toggled occur via in-battle AI script.
 
Last edited:
When you mention enemies with multiple limbs, are you sure that you're not confusing it wih the 0x0010 offset of the Battle Setup formate? I remember we discussed before about the fact that bit 1 was a bit of a mystery to me, and I recall you saying then that that flag has something to do with enemies with multiple limbs. In fact, I made a list of enemies which have this flag ON for the pre-battle setup flag ([FF], [FB], [EF], [F3], [EB] & [E3]):

 - Ghirofelgo / Chain
 - Mirage
 - Dorky Face
 - Jersey
 - Ying, Yang, Ying/Yang
 - Ancient Dragon
 - Schizo Left / Schizo Right
 - Guardian (+ Guardian Left and Guardian Right)
 - Carry Armour / Left Arm / Right Arm
 - Proud Clod / Jamar Armour
 - Helletic Hojo / Right Arm / Left Arm
 - Mover
 - Jenova Synthesis
 - Bizarro Sephiroth
 - Roulette Cannon / Pedestal
 - Diamond Weapon
 - Ruby Weapon / Right + left Tentacle
 - Emerald Weapon / Leg / Eye

Anyway, I don't think this is the same as the 4022 address. We see the Vice and Hell House use 4022, and they don't have multiple limbs
 
Last edited:
Ack! I was only looking at the AI. I know those flags pull into the 402X memory region, but I always forget to look in form data.

I didn't say multiple limbs, I said multiple parts. This includes Hell House as it essentially has two "parts". One being the thing you initially encounter and the other being the possessed thing after the initial house thing is defeated.
 
Ah, my bad. I'm only assuming that 4022 is pulling the 0x04 flag in the enemy battle setup, but I could be wrong.

Anyway, in regards to the Setup Flag used (0x0010 offset in the Battle Setup Format), I still have Bit1 0x02 jotted down as ?'s, it would be good to give it a clear description as to what that flag does. I recall you saying it has something do with the animations when an enemy does have multiple limbs (not parts; I get what you're saying now about the other flag). Or, if an enemy interacts with another enemy during one of their animations (like the Movers).

A concise explanation to this flag would be really useful :). It's the 2 bytes that's usually set to FFFD to indicate a normal battle (0x02 OFF), or FFED to indicate Pre-Emp disabled.
 
I'm not going to say I'm lazy, but can you provide a link to where I discussed that. :P I'm not doubting that I said this, but I probably said other things around that and the context would make more sense to me and be able to explain it.
 
Haha lol. I know it's somewhere in the PMs that we've sent each other, or possibly in a topic I posted a few years back (I'm not saying I'm lazy either.......)

Anyway, just a quickie regarding the MP again, we can see that the script doesn't work properly, I'm compiling a list of errors for DLPB and I would like to offer working fixes.

The fix that I have suggested for the MP (and if this works then the same thing can be applied to the Grunt/Guard Hound/Mono Drive also):

change:

Code: [Select]
Code:
0x040 If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 0) )0x040 {0x04D LovalVar:PlayerRow <- LovalVar:PlayerRow AND 10x057 If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 1) )0x057 {0x064 LovalVar:PlayerRow <- LovalVar:PlayerRow AND 20x06E If ( (BattleAddr(&Self).BattleAddr(&FrontRow) == 0) )
TO:

Code: [Select]
Code:
0x040 If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 0) )0x040 {0x04D LovalVar:PlayerRow <- LovalVar:PlayerRow <- 10x057 If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 1) )0x057 {0x064 LovalVar:PlayerRow <- LovalVar:PlayerRow <- 20x06E If ( (BattleAddr(&Self).BattleAddr(&FrontRow) == 0) )
This should fix the subsequent AND checks to make it work properly... I think. NFI?

Edit - actually, thinking on it, it could be a fun exercise just to tidy up the whole script, it'll put everything I've learned to the test. It's obvious that the opening bombing mission was a "trial and error" task for the coders, they probably had a cool off period after the demo was finished to restructure the way they compile the script (Enemy AI and field script; why on earth are they using [2][0] $GM to signify that the Restore Materia has been obtained haha lol??)

I'll have a go at that once I've escaped Midgar, which I honestly thought I would have done by now lol
 
Last edited:
Once you enter Midgar, you never leave.

Though...no. those changes don't make sense. I'm guessing you meant this:
Code: [Select]
Code:
0x040 If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 0) )0x040 {0x04D LocalVar:PlayerRow <- 10x057 If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 1) )0x057 {0x064 LocalVar:PlayerRow <- 20x06E If ( (BattleAddr(&Self).BattleAddr(&FrontRow) == 0) )
THAT would make sense. :)
I just took a look at it and at first glance the vanilla script is totally stupid. Trying to AND a value that you just set to 0 will always result in 0. However, maybe they intended this. It appears that the intended function is if all playable characters are in the back row then prioritize the machine gun action.

There is a 1:4 chance of Tonfa in the event that the LocalVar:PlayerRow = 1
There is a 1:8 chance of Tonfa if LocalVar:PlayerRow = 2
However, since neither of those are possible, it defaults to a 1:6 chance of a Tonfa

This idea probably got scrapped since both Machine Gun and Tonfa are long range attacks and their damage output is not reduced due to target's row. Rather than remove the code that would allow for this chance behavior, it is simply mitigated by not allowing it to logically happen. Then, should the need arise in the future to change it back, it's a simple fix. A SIMPLER fix is to change the initial assignment at position 0x004 to be a 3. Then these values will be correctly AND'd and produce a non-zero result. The script is still stupid for other reasons (obvious copy-pasted code blocks) but it has more function again. If I wanted to take the time I could make a much cleaner code. I'm just not sure it's worth it on such a simple enemy. Although it might provide some good practice for other scripts... I might change my mind if I find myself bored later. Actually, it is CERTAINLY not worth it because the entire script is based around the possibility that Tonfa is a short range action. Since it's not there is no need for 90% of the script. It can be as simple as
Code: [Select]
Code:
If (Not (Random MOD 6)){   LocalVar:0080 <- 272 (Machine Gun)} Else {   LocalVar:0080 <- 273 (Tonfa)}TargetMask <- RandomBit( AllOpponentMask )Perform(LocalVar:0080, EnemyAttack)SCRIPT END
That is literally all it needs to be. This prioritizes Tonfa (since it's a more damaging action) at a 5:6 ratio.
 
Last edited:
Though...no. those changes don't make sense. I'm guessing you meant this:
Code: [Select]
0x040   If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 0) )
0x040   {
0x04D   LocalVar:PlayerRow <- 1
0x057   If ( (BattleAddr(&AllPlayers).BattleAddr(&FrontRow) == 1) )
0x057   {
0x064   LocalVar:PlayerRow <- 2
0x06E   If ( (BattleAddr(&Self).BattleAddr(&FrontRow) == 0) )
THAT would make sense. :)
Yes, indeed, that's exactly what I meant lol.

I agree that it looks quite a lot like they had left this script in as it was to give them the option to invoke the Front/Back row behaviour at a later date, or they decided that it wasn't needed so they simply overwrote it. I didn't clock that changing the initial value of LocalVar:0020 from 0 to 3 would also neatly fix the issue, kudos (kind of annoyed I didn't see that myself :))

In your custom script you've missed out the part that does work, which is the check to see if the MP is in the Front Row or back row, and we do see an instance on the Sector 8 Bridge with MP's in the back row. Here is how (I think) it should look:

Code: [Select]
Code:
MAIN:     LovalVar:SelfRow <- 0      If ( (BattleAddr(&Self).BattleAddr(&Row) == 0) )      {      LovalVar:SelfRow <- 0      }      Else      {      LovalVar:SelfRow <- 1      If (Not  (LovalVar:SelfRow) )      {       LocalVar:Random <- 2        If (Not  (Random MOD LocalVar:Random) )        {         BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))        LocalVar:EnemyAttack <- 272 (Machine Gun)        }        Else        {         BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))        LocalVar:EnemyAttack <- 273 (Tonfa)      }      Else      {       LocalVar:Random <- 6        If (Not  (Random MOD LocalVar:Random) )        {         BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))        LocalVar:EnemyAttack <- 273 (Tonfa)        }        Else        {         BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))        LocalVar:EnemyAttack <- 272 (Machine Gun)       }       Else       {      POP(LovalVar:SelfROw)     Perform(LocalVar:EnemyAttack, EnemyAttack)     SCRIPT END
As mentioned, this weirdness in the script occurs in the first four enemies 10h - 13h, and all of them can have their script completely simplified in a similar way.
 
Last edited:
Remind me again what happens to enemies that take double damage from Statuses (Sword Dance, Soldier:3rd, Corvette take double from Confusion; Palmer takes double from Sleep).

I know that they would take double damage from Added Effect+Confusion on your weapon, but does it also mean that the Confusion/Sleep infliction chance would now be 100%?
 
Man the Warning Board + Machine Gun + Laser Cannon are cheesing me off.

I don't get what's going on at 0x130 here with the Machine Gun:

Code: [Select]
Code:
PRE-BATTLE:0x000LocalVar:WarningBoard <-  (BitCount(BattleAddr(&Self).BattleAddr(&PlayerID)) == BattleAddr(&ActiveActors).BattleAddr(&PlayerID)) 0x014LocalVar:WarningBoard <-  (LocalVar:WarningBoard.BattleAddr(&SelfID) == 50) 0x022LocalVar:LaserCannon <-  (BitCount(BattleAddr(&Self).BattleAddr(&PlayerID)) == BattleAddr(&ActiveActors).BattleAddr(&PlayerID)) 0x036LocalVar:LaserCannon <-  (LocalVar:LaserCannon.BattleAddr(&SelfID) == 52) 0x044SCRIPT ENDMAIN:0x000LocalVar:SelfActive <- 00x006 If (LocalVar:WarningBoard.BattleAddr(&SelfActive))0x006 {0x010 LocalVar:SelfActive <- LocalVar:SelfActive OR 10x01A If (BattleAddr(&Self).BattleAddr(&SelfActive))0x01A {0x024 LocalVar:SelfActive <- LocalVar:SelfActive OR 20x02E If (LocalVar:LaserCannon.BattleAddr(&SelfActive))0x02E {0x038 LocalVar:SelfActive <- LocalVar:SelfActive OR 40x042 If ( (BattleAddr(&Self).BattleAddr(&AllyAngry) == 1) )0x042 {0x04F  If (LocalVar:SelfActive == 1)0x04F  {0x057   If ( (BattleAddr(&Self).BattleAddr(&Angry) == 0) )0x057   {0x064    If ( (BattleAddr(&AllPlayers).BattleAddr(&ParalyzedStatus) == 0) )0x064    {0x071     If (Not  (Random MOD 2) )0x071     {0x079     BattleAddr(&Self).BattleAddr(&SelfActive) <- 10x083     BattleAddr(&Self).BattleAddr(&Targetable) <- 10x08D     BattleAddr(&TargetSelected) <- BattleAddr(&Self)0x094     Perform("Appear"[014F], EnemyAttack)0x09A     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x0A2     Perform("Machine Gun"[0110], EnemyAttack)0x0A8    }0x0A8    Else0x0A8    {0x0AB     If (Random MOD 4)0x0AB     {0x0B2     BattleAddr(&Self).BattleAddr(&SelfActive) <- 10x0BC     BattleAddr(&Self).BattleAddr(&Targetable) <- 10x0C6     BattleAddr(&TargetSelected) <- BattleAddr(&Self)0x0CD     Perform("Appear"[014F], EnemyAttack)0x0D3     BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x0DB     Perform("Machine Gun"[0110], EnemyAttack)0x0E1   }0x0E1   Else0x0E1   {0x0E4   BattleAddr(&Self).BattleAddr(&SelfActive) <- 10x0EE   BattleAddr(&Self).BattleAddr(&Targetable) <- 10x0F8   BattleAddr(&TargetSelected) <- BattleAddr(&Self)0x0FF   Perform("Appear"[014F], EnemyAttack)0x105   BattleAddr(&Self).BattleAddr(&Angry) <- 00x10F    If (Not  (Random MOD 2) )0x10F    {0x117    BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x11F    Perform("Machine Gun"[0110], EnemyAttack)0x125  }0x125  Else0x125  {0x128   }0x128   Else0x128   {0x12B    If (LocalVar:SelfActive == 3)0x12B    {0x130    If ( (LocalVar:LaserCannon.BattleAddr(&DeathStatus) == 0) )0x130    {0x13D     If (Random MOD 4 == 0)0x13D     {0x146     BattleAddr(&TargetSelected) <- BattleAddr(&Self)0x14D     Perform("Vanish"[014E], EnemyAttack)0x153     BattleAddr(&Self).BattleAddr(&SelfActive) <- 00x15D     BattleAddr(&Self).BattleAddr(&Targetable) <- 00x167     LocalVar:LaserCannon.BattleAddr(&Angry) <- 10x171     }0x171     Else0x171     {0x174      }0x174      Else0x174      {0x177       If (Random MOD 4 == 1)0x177       {0x17C      BattleAddr(&TargetSelected) <- BattleAddr(&Self)0x183      Perform("Vanish"[014E], EnemyAttack)0x189      BattleAddr(&Self).BattleAddr(&SelfActive) <- 00x193      BattleAddr(&Self).BattleAddr(&Targetable) <- 00x19D      }0x19D      Else0x19D      {0x1A0       }0x1A0       Else0x1A0       {0x1A3      BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x1AB      Perform("Machine Gun"[0110], EnemyAttack)0x1B1      }0x1B1      Else0x1B1      {0x1B4    POP(Random MOD 4)0x1B5    }0x1B5    Else0x1B5    {0x1B8    BattleAddr(&TargetSelected) <- RandomBit(BattleAddr(&AllPlayers))0x1C0    Perform("Machine Gun"[0110], EnemyAttack)0x1C6   }0x1C6   Else0x1C6   {0x1C9    }0x1C9    Else0x1C9    {0x1CC     If (LocalVar:SelfActive == 5)0x1CC     {0x1D1    }0x1D1    Else0x1D1    {0x1D4   }0x1D4   Else0x1D4   {0x1D7 POP(LocalVar:SelfActive)0x1D8SCRIPT END
It's checking to see if Laser Cannon doesn't have the Death Status, which it always will pass seeing as the Machine Gun cannot spawn in if you've killed the Laser Cannon.

Am I missing something, or is the check at 0x130 always going to pass, meaning that use of Machine Gun at 0x1B5 will never occur?
 
Last edited:
OK, I think I understand it now. It's a flaw in the scripting, there should be a Death Counter.

When you kill either the Mchn Gun or Lsr Can, there is no script to toggle the 4020 "SelfActive" var from 1 to 0 (like we see when one of the counterparts disappears). Because of this, once you've killed the Laser Cannon, the next time the Machine Gun's script runs, the check at 0x02E passes and the final value that is returned is always 5, which bypasses all of the scripts and acts as though the Laser Cannon was still alive.

I think this is an error. When you kill either the MG or LC another enemy will not spawn in, and the Warning Board will just sit there till you kill it. It seems to me as though the Laser Cannon should have spawned in again once you kill the Machine Gun and vice-versa (unless the other one has been killed obv).

If you add a Death Counter script for the MG and LC that looks like this, I think that will solve the problem:

Code: [Select]
Code:
DEATH COUNTER:0x000BattleAddr(&Self).BattleAddr(&SelfActive) <- 00x0OASCRIPT ENDor:DEATH COUNTER:0x000BattleAddr(&2060).BattleAddr(&4020) <- 00x0OASCRIPT END
Thing is, this flag may automatically get set to 0 upon playing the normal Death script for an enemy, in which case I don't know what's going on...
 
Last edited:
YES! The last two hours haven't been wasted :) :)

My first bit of AI script editing was a success. It took me a while, Pr Cl didn't like it when I tried to copy and paste and delete large chunks of AI script, but I finally got the script I wanted which was this:
Code: [Select]
Code:
12 206010 40208060 0090
This is the death counter script that I've added for the Machine Gun and Laser Cannon, which disassembles to:

Code: [Select]
Code:
0x000: PUSH (2060) Type (12)0x003: PUSH (4020) Type (10)0x006: MASK0x007: PUSH (00) Type (01)0x009: STRA0x00A: END0x000BattleAddr(&2060).BattleAddr(&4020) <- 00x00ASCRIPT END
I know it doesn't look like much, but I'm only a beginner lol. Anyway, after trying to mess around with Steam and getting it to not delete my save, then working out which bloody scene.bin the Steam version pulls from, I finally managed to battle the Warning Board, and that script did exactly what I had intended it to do.

It has flagged the killed enemy as non-active. So, let's say I've killed the Machine Gun; normally the MG will still be flagged as active, so when the LC takes it turn it does nothing and does not spawn in. With the added Death Counter script the MG is now flagged as non-active, so the LC re-spawns in like it was supposed to.

Again, I'm only assuming that it was supposed to respawn in givent the fact that both the MG and LC have redundant script that searches for the Death status of its counterpart. And I've fixed it :) Now I can move on :)

One for DLPB
 
Last edited:
Status
Not open for further replies.
Back
Top