Calculate Physical Target

From Final Fantasy Hacktics Wiki
Jump to navigation Jump to search
BATTLE.BIN : Calculate Physical? Target  - rename ? Seek Nearest Unit Fulfilling r4 conditions
-----------------------------------------------------------------------------------------
Parameters : r4 = Preset Value determines condition of research

Returns : r2 = ID of Nearest Unit Fulfilling conditions (see notes)
          r2 = Acting unit ID if there's no eligible target
-----------------------------------------------------------------------------------------
00199124: 27bdffc8 addiu r29,r29,-0x0038    |
00199128: afb40020 sw r20,0x0020(r29)       |
0019912c: 0080a021 addu r20,r4,r0           |r20 = Preset Value
00199130: afb7002c sw r23,0x002c(r29)       |
00199134: 3c177fff lui r23,0x7fff           |
00199138: afbe0030 sw r30,0x0030(r29)       |
0019913c: 3c1e801a lui r30,0x801a           |
00199140: 93de01f2 lbu r30,0x01f2(r30)      |Load Acting Unit ID
00199144: 36f7ffff ori r23,r23,0xffff       |Forces Distance to Max Value - Will be used to track the nearest unit of interest
00199148: afb20018 sw r18,0x0018(r29)       |
0019914c: 00009021 addu r18,r0,r0           |Reset Unit Counter
00199150: afb50024 sw r21,0x0024(r29)       |
00199154: 3c15801a lui r21,0x801a           |
00199158: 26b5f3c4 addiu r21,r21,-0x0c3c    |r21 = Start of AI Data Pointer 8019f3c4
0019915c: afb3001c sw r19,0x001c(r29)       |
00199160: 02a09821 addu r19,r21,r0          |r19 = Start of AI Data Pointer  (used as offset in the loop)
00199164: afb60028 sw r22,0x0028(r29)       |
00199168: 0000b021 addu r22,r0,r0           |Offset for Battle stats (+0x1c0 each iteration)
0019916c: afbf0034 sw r31,0x0034(r29)       |
00199170: afb10014 sw r17,0x0014(r29)       |
00199174: afb00010 sw r16,0x0010(r29)       |
00199178: 3c028019 lui r2,0x8019            @LOOP - through all units
0019917c: 244208cc addiu r2,r2,0x08cc           |
00199180: 02c28821 addu r17,r22,r2              |r17 = This iteration Unit Data Pointer +0x01c0 each iteration
00199184: 00121100 sll r2,r18,0x04              |Unit Offset in AI decision data
00199188: 2442182c addiu r2,r2,0x182c           |
0019918c: 02a28021 addu r16,r21,r2              |r16 = This iteration Unit's AI Decision Data 8019f3c4 + 0x182c + Unit offset
00199190: 34020005 ori r2,r0,0x0005             |r2 = 5
00199194: 16820006 bne r20,r2,0x001991b0        #If Preset Value = 0x05 (Unit with less than 35% HP (Player team only ?))
00199198: 00000000 nop                              |
0019919c: 92220058 lbu r2,0x0058(r17)               |Load Unit Current Statuses 1
001991a0: 00000000 nop                              |
001991a4: 30420040 andi r2,r2,0x0040                |
001991a8: 14400054 bne r2,r0,0x001992fc             #Branch to next Unit If This Unit is a Crystal
001991ac: 00000000 nop                                  |
001991b0: 0c065b3a jal 0x00196ce8               |-->Check if Unit can be Targeted (Cryst/Trea/Mount/Trans) Returns r2 = 0x00 if OK
001991b4: 02402021 addu r4,r18,r0               |r4 = Unit Counter
001991b8: 14400059 bne r2,r0,0x00199320         #If Unit can be Targeted by AI /Else branch to  next Unit
001991bc: 00000000 nop                              |
001991c0: 92220059 lbu r2,0x0059(r17)               |Load This Unit Current Statuses 2
001991c4: 00000000 nop                              |
001991c8: 30420080 andi r2,r2,0x0080                |
001991cc: 14400054 bne r2,r0,0x00199320             #Branch to next Unit If This Unit is Petrified
001991d0: 34020004 ori r2,r0,0x0004                     |
001991d4: 12820006 beq r20,r2,0x001991f0            #If Preset Value is not 0x04 - Ignore Deads
001991d8: 2e820006 sltiu r2,r20,0x0006                  |
001991dc: 92220058 lbu r2,0x0058(r17)                   |Load this Unit Current Statuses 1
001991e0: 00000000 nop                                  |
001991e4: 30420020 andi r2,r2,0x0020                    |check [Dead]
001991e8: 1440004d bne r2,r0,0x00199320                 #Branch to next Unit If This Unit is Dead
001991ec: 2e820006 sltiu r2,r20,0x0006                      |
001991f0: 10400042 beq r2,r0,0x001992fc             #If preset Value < 6 /Else branch directly to  Check nearest unit section
001991f4: 00141080 sll r2,r20,0x02                      |Preset Value * 4 (word offset)
001991f8: 3c068019 lui r6,0x8019                        |
001991fc: 24c63d98 addiu r6,r6,0x3d98                   |80193d98 / 0x80193d98
00199200: 00461021 addu r2,r2,r6                        |80193d98 + Preset Value Offset
00199204: 8c420000 lw r2,0x0000(r2)                     |Load Code Pointer (see notes)
00199208: 00000000 nop                                  |
0019920c: 00400008 jr r2                                >>Jump to dedicated Section
00199210: 00000000 nop                                  |

0x05 Section : Find the nearest Healer
00199214: 92020008 lbu r2,0x0008(r16)               |Load this Unit Enemy Flag AI decision data
00199218: 00000000 nop                              |
0019921c: 14400040 bne r2,r0,0x00199320             #If This iteration Unit do not have the enemy flag
00199220: 00000000 nop                                  |
00199224: 92020006 lbu r2,0x0006(r16)                   |Load this Unit AI decision byte 0x06
00199228: 00000000 nop                                  |
0019922c: 30420002 andi r2,r2,0x0002                    |check [HP recovery for Ally]
00199230: 14400032 bne r2,r0,0x001992fc                 #If this unit is not a healer / If Unit is a Healer branch to Check nearest unit section
00199234: 00000000 nop                                      |
00199238: 080664c9 j 0x00199324                             >>Jump to next Unit
0019923c: 26730001 addiu r19,r19,0x0001                     |AI Data Pointer +1

0x01 Section :  Seek Nearest Active enemy unit not at melee range
00199240: 92620c8d lbu r2,0x0c8d(r19)               |Load This unit Targetable Flag Take in consideration ? 
00199244: 00000000 nop                              |
00199248: 10400035 beq r2,r0,0x00199320             #Branch to next Unit If This Unit is not Targetable
0019924c: 00000000 nop                                  |
00199250: 0c066632 jal 0x001998c8                   |-->AI_Check_Options_-_Stop/Don%27t_Act/Sleep/Chicken/Charm  r2 = 0x00 if all statuses are possible (= Unit is active ?)
00199254: 02402021 addu r4,r18,r0                   |r4 = Unit Counter
00199258: 14400031 bne r2,r0,0x00199320             #If All tested statuses infliction is an option / Else branch to  next Unit
0019925c: 00000000 nop                                  |
00199260: 8ea417f8 lw r4,0x17f8(r21)                    |Load Acting Unit's Data Pointer
00199264: 0c0664db jal 0x0019936c                       |-->Calculate Distance Between Units Returns r2 with distance
00199268: 02202821 addu r5,r17,r0                       |This iteration Unit Data Pointer
0019926c: 28420002 slti r2,r2,0x0002                    |Check if unit is at melee range
00199270: 10400022 beq r2,r0,0x001992fc                 #If Target is at melee range #Else go to find nearest unit fullfiling condition
00199274: 26a40e30 addiu r4,r21,0x0e30                      |r4 = Acting Unit's Coordinate Pointer
00199278: 0c066dac jal 0x0019b6b0                           |-->Calculate Height Difference Between Units returns r2 = (Target Height - Actor Height)
0019927c: 02202821 addu r5,r17,r0                           |r5 = Current Unit's Data Pointer
00199280: 080664bd j 0x001992f4                             >>Jump with r2 - Unit will be ignored if r2 = 0x01
00199284: 2842fffe slti r2,r2,-0x0002                       |0x1 if Acting unit is at least 2 tiles above Target  Melee range test ? From above only ?

0x02 Section : Seek Nearest Enemy
00199288: 92020008 lbu r2,0x0008(r16)               |Load this Unit Enemy Flag AI decision data
0019928c: 00000000 nop                              |
00199290: 1440001a bne r2,r0,0x001992fc             #If Unit is an enemy : Branch to Check nearest unit section
00199294: 00000000 nop                                  |
00199298: 080664c9 j 0x00199324                     >>Else : jump to  next Unit Iteration 
0019929c: 26730001 addiu r19,r19,0x0001             |AI Data Pointer +1

0x04 Section : Seek Nearest enemy  (not Counted as KO nor Death sentenced)
001992a0: 92020008 lbu r2,0x0008(r16)               |Load this Unit Enemy Flag AI decision data
001992a4: 00000000 nop                              |
001992a8: 1040001d beq r2,r0,0x00199320             #If This Unit is an Enemy / Else branch to  next Unit
001992ac: 00000000 nop                                  |
001992b0: 92020007 lbu r2,0x0007(r16)                   |Load AI Targeting Flags
001992b4: 00000000 nop                                  |
001992b8: 30420020 andi r2,r2,0x0020                    |Check [Dead without reraise]
001992bc: 14400018 bne r2,r0,0x00199320                 #If Unit is not dead for good / Else ignore this dead unit and go to  next Unit 
001992c0: 00000000 nop                                      |
001992c4: 92620c8d lbu r2,0x0c8d(r19)                       |Load this unit Current Targetable Flag
001992c8: 00000000 nop                                      |
001992cc: 10400014 beq r2,r0,0x00199320                     #If Unit is Targetable  /Else ignore it and go to  next Unit 
001992d0: 00000000 nop                                          |
001992d4: 92020004 lbu r2,0x0004(r16)                           |Load This Unit ENTD behavior flag
001992d8: 00000000 nop                                          |
001992dc: 30420080 andi r2,r2,0x0080                            |Check [0x80] - Performing or Charging ? Maybe not counted as KO (dead petrified Death sentence)
001992e0: 1040000f beq r2,r0,0x00199320                         #If Flag [0x80] is off : ignore this unit, else go to 0x00 section (blood suck)
001992e4: 00000000 nop                                              |

0x00 Section : Nearest Unit without Blood Suck / End of 0x04
001992e8: 92220059 lbu r2,0x0059(r17)               |Load Current Unit's Statuses 2
001992ec: 00000000 nop                              |
001992f0: 30420004 andi r2,r2,0x0004                |check [Blood Suck]

0x00 - Blood suck check / 0x01 - Height difference check
001992f4: 1440000a bne r2,r0,0x00199320             #Ignore Unit with Blood Suck (count as KO) / Or Adjacent Unit 2 tiles (or more) below Attacker
001992f8: 00000000 nop                                  |

 Check Distance and Save Nearest Unit / Section 0x03
001992fc: 8ea417f8 lw r4,0x17f8(r21)                |Load Acting Unit's Data Pointer
00199300: 0c0664db jal 0x0019936c                   |-->Calculate Distance Between Units Returns r2 with distance
00199304: 02202821 addu r5,r17,r0                   |r5 = Current Unit's Data Pointer
00199308: 00401821 addu r3,r2,r0                    |r3 = Distance
0019930c: 0077102a slt r2,r3,r23                    |Check This unit distance Vs Minimum distance found
00199310: 10400003 beq r2,r0,0x00199320             #If This unit is the nearest (so far)
00199314: 00000000 nop                                  |
00199318: 0060b821 addu r23,r3,r0                       |Update lowest distance
0019931c: 0240f021 addu r30,r18,r0                      |Keep Nearest Unit ID in r30

End of Loop
00199320: 26730001 addiu r19,r19,0x0001         |AI Data Pointer + 1 (Unit offset in AI data)
00199324: 26520001 addiu r18,r18,0x0001         |Unit Counter +1
00199328: 2a420015 slti r2,r18,0x0015           |Check counter Vs Limit
0019932c: 1440ff92 bne r2,r0,0x00199178     Λ Loop while counter < 0x15
00199330: 26d601c0 addiu r22,r22,0x01c0         |Unit data pointer + offset  (0x1c0 each iteration)
00199334: 03c01021 addu r2,r30,r0           |r2 = Chosen Unit ID
00199338: 8fbf0034 lw r31,0x0034(r29)       END
0019933c: 8fbe0030 lw r30,0x0030(r29)
00199340: 8fb7002c lw r23,0x002c(r29)
00199344: 8fb60028 lw r22,0x0028(r29)
00199348: 8fb50024 lw r21,0x0024(r29)
0019934c: 8fb40020 lw r20,0x0020(r29)
00199350: 8fb3001c lw r19,0x001c(r29)
00199354: 8fb20018 lw r18,0x0018(r29)
00199358: 8fb10014 lw r17,0x0014(r29)
0019935c: 8fb00010 lw r16,0x0010(r29)
00199360: 27bd0038 addiu r29,r29,0x0038
00199364: 03e00008 jr r31
00199368: 00000000 nop

Notes

Mechanics
Loop through all unit, scanning AI decision data and status data:
  Always ignore petrified units
  Ignore untargetable units
  Condition of research depends on Preset Value (r4):
   - 0x01 : Returns Nearest Active Enemy ? (Enemy that could take Stop, Don't Act, Sleep, Chicken and Charm)
   - 0x02 : Returns Nearest Enemy
   - 0x03 : Nearest Unit
   - 0x04 : Returns Nearest Enemy not counted as KO
   - 0x00 : Nearest Unit without bloodsuck
   - 0x05 : Returns Nearest Ally with healing skillset   
  
Address pointers
Offset is based on Preset Value (Parameter r4)
Offset - Address  - Jump Address
---------------------------------
 0x00  | 80193d98 | 801992e8 
 0x01  | 00193d9c | 80199240 
 0x02  | 00193da0 | 80199288 
 0x03  | 00193da4 | 801992fc 
 0x04  | 00193da8 | 801992a0 
 0x05  | 00193dac | 80199214 

Return Locations

BATTLE.BIN
001948e0: Set_AI_flags_for_target_consideration r4 = 0x04 / 0x05
00197280: Set_chosen_ability/target_for_AI_status r4 = 0x00
00197488: Set_chosen_ability/target_for_AI_status r4 = 0x03
001974a0: Set_chosen_ability/target_for_AI_status r4 = 0x02
00198148: Fight_for_Life_-_Auto_Battle_(00197ff4) r4 = 0x04
00198ed8: 00198e60_-_00199058 r4 = 0x05
0019acbc: Some_Map_calculations_-_height_diff.,_coordinates r4 = 0x01
0019acd0: Some_Map_calculations_-_height_diff.,_coordinates r4 = 0x02