Find Peril Most Unit (00198b04)

From Final Fantasy Hacktics Wiki
Jump to navigation Jump to search
Description:
Scores allied units based on their missing HP, status, distance, etc., then formulates a score for them.
Status Scores do not accumulate. The routine only checks for one.
The unit with the highest score gets returned to the routine.
Status Priority goes as: 
Dead > Dead w/ Reraise = Critical > Blood Suck > Petrify > Confuse > Frog > Low HP > Critical HP
It has two formulas, one for statused units and a "non-critical" formula.
This routine hard caps AI Range, or target acquisition, to 7. This is why the game ignores downed units across the map, for better or worse.
It also has a peril minimum, which is some explanation of why the AI seems averse to status curing at times.
Also note the AI will not even give the unit with the most usable abilities a peril score unless it has a status. 
This is actually good for the most part because statuses include Critical and Low HP (>50% HP).
This routine also accounts for Ramza (0x03 in the ENTD) and gives him a bonus score
Referenced In:
Protect Allies - Auto Battle (001984ec)
Save Fading Life - Auto Battle (00198df0)
Routines Used:
Check for Status
00198b04: 3c03801a lui r3,0x801a
00198b08: 8c630bbc lw r3,0x0bbc(r3)            Acting unit data
00198b0c: 3c02801a lui r2,0x801a
00198b10: 904201f2 lbu r2,0x01f2(r2)           Acting unit id
00198b14: 27bdffc8 addiu r29,r29,0xffc8
00198b18: afb40020 sw r20,0x0020(r29)
00198b1c: 3c14801a lui r20,0x801a
00198b20: 2694f3c4 addiu r20,r20,0xf3c4
00198b24: afbe0030 sw r30,0x0030(r29)
00198b28: 0000f021 addu r30,r0,r0
00198b2c: afb20018 sw r18,0x0018(r29)
00198b30: 00009021 addu r18,r0,r0
00198b34: afb7002c sw r23,0x002c(r29)
00198b38: 0000b821 addu r23,r0,r0
00198b3c: afbf0034 sw r31,0x0034(r29)
00198b40: afb60028 sw r22,0x0028(r29)
00198b44: afb50024 sw r21,0x0024(r29)
00198b48: afb3001c sw r19,0x001c(r29)
00198b4c: afb10014 sw r17,0x0014(r29)
00198b50: afb00010 sw r16,0x0010(r29)
00198b54: a06201b9 sb r2,0x01b9(r3)				Save Acting Unit ID
00198b58: 3c028019 lui r2,0x8019
00198b5c: 244208cc addiu r2,r2,0x08cc			Unit Data
00198b60: 00121900 sll r3,r18,0x04
00198b64: 2463182c addiu r3,r3,0x182c
00198b68: 02838821 addu r17,r20,r3
00198b6c: 92230007 lbu r3,0x0007(r17)           AI Target State
00198b70: 00000000 nop
00198b74: 30630010 andi r3,r3,0x0010
00198b78: 1460006a bne r3,r0,0x00198d24         <Unit++> if can't be targeted
00198b7c: 02e28021 addu r16,r23,r2				r16 = Current Unit Data Pointer
00198b80: 92220008 lbu r2,0x0008(r17)			Load Enemy Flag
00198b84: 00000000 nop
00198b88: 14400066 bne r2,r0,0x00198d24         <Unit++> if enemy
00198b8c: 00000000 nop
00198b90: 8e8417f8 lw r4,0x17f8(r20)            Acting unit data
00198b94: 0c0664db jal 0x0019936c				Calculate Distance Between Units
00198b98: 02002821 addu r5,r16,r0
00198b9c: 96060028 lhu r6,0x0028(r16)           r6 = Load Target Current HP
00198ba0: 9603002a lhu r3,0x002a(r16)           r3 = Load Target Max HP
00198ba4: 000631c0 sll r6,r6,0x07               HP * 80
00198ba8: 00c3001a div r6,r3                    (curHP * 80) / Max HP
00198bac: 00003012 mflo r6						r6 = ""
00198bb0: 02002021 addu r4,r16,r0				r4 = Current Unit Data Pointer
00198bb4: 34050002 ori r5,r0,0x0002				r5 = Dead Status
00198bb8: 340300ff ori r3,r0,0x00ff				r3 = 0xff
00198bbc: 00629823 subu r19,r3,r2				r19 = ff - Distance between Target and Caster (Closer distance = Higher score)
00198bc0: 92030005 lbu r3,0x0005(r16)			Load ENTD Flags
00198bc4: 34020080 ori r2,r0,0x0080
00198bc8: 30760003 andi r22,r3,0x0003           r22 = is unit Ramza?
<Dead?>
00198bcc: 0c066360 jal 0x00198d80				Check for Status
00198bd0: 0046a823 subu r21,r2,r6				r21 = 80 - curHP%
00198bd4: 10400006 beq r2,r0,0x00198bf0			<HP Recovery> if this unit is not dead
00198bd8: 00000000 nop
<Dead without reraise?>
00198bdc: 92220007 lbu r2,0x0007(r17)			Load AI Target State
00198be0: 00000000 nop
00198be4: 30420020 andi r2,r2,0x0020
00198be8: 14400033 bne r2,r0,0x00198cb8         <Status Checks> if dead without reraise
00198bec: 34030078 ori r3,r0,0x0078				Dead = Highest Status Priority
<HP Recovery?>
00198bf0: 8e820e34 lw r2,0x0e34(r20)             Acting unit decision data
00198bf4: 00000000 nop
00198bf8: 90420006 lbu r2,0x0006(r2) 			Load AI Targeting Flags            
00198bfc: 00000000 nop
00198c00: 30420002 andi r2,r2,0x0002
00198c04: 1040000b beq r2,r0,0x00198c34         <Blood Suck> if doesn't have HP recovery ability (Skip ReraiseDead and Critical)
00198c08: 02002021 addu r4,r16,r0				r4 = Current Unit Data Pointer
<Dead w/ Reraise?>
00198c0c: 92220007 lbu r2,0x0007(r17)			Load AI Target State
00198c10: 00000000 nop
00198c14: 30420040 andi r2,r2,0x0040
00198c18: 14400027 bne r2,r0,0x00198cb8         <Status Checks> if dead unit with reraise
00198c1c: 34030077 ori r3,r0,0x0077				Dead w/ reraise = 2nd highest?
<Critical?>
00198c20: 9202005a lbu r2,0x005a(r16)			Load Current Status 3
00198c24: 00000000 nop
00198c28: 30420001 andi r2,r2,0x0001
00198c2c: 14400022 bne r2,r0,0x00198cb8         <Status Checks> if critical
00198c30: 00000000 nop							Critical Unit = 2nd Highest
<Blood Suck?>
00198c34: 0c066360 jal 0x00198d80				Check for Status
00198c38: 3405000d ori r5,r0,0x000d				Check for Blood Suck
00198c3c: 1440001e bne r2,r0,0x00198cb8			<Status Checks> if unit has Blood Suck
00198c40: 34030076 ori r3,r0,0x0076				Blood Suck = 3rd Highest
<Petrify?>
00198c44: 02002021 addu r4,r16,r0
00198c48: 0c066360 jal 0x00198d80				Check for Status
00198c4c: 34050008 ori r5,r0,0x0008				Check for Petrify
00198c50: 14400019 bne r2,r0,0x00198cb8			<Status Checks> if unit is Petrified
00198c54: 34030075 ori r3,r0,0x0075				Petrify = 4th Highest
<Confused?>
00198c58: 02002021 addu r4,r16,r0
00198c5c: 0c066360 jal 0x00198d80				Check for Status
00198c60: 3405000b ori r5,r0,0x000b				Check for Confusion
00198c64: 14400014 bne r2,r0,0x00198cb8			<Status Checks> if unit is Confused
00198c68: 34030074 ori r3,r0,0x0074				Confusion = 5th Highest
<Frog?>
00198c6c: 02002021 addu r4,r16,r0
00198c70: 0c066360 jal 0x00198d80				Check for Status
00198c74: 34050016 ori r5,r0,0x0016				Check for Frog
00198c78: 10400003 beq r2,r0,0x00198c88			Branch if not Frog
00198c7c: 00000000 nop
00198c80: 0806632e j 0x00198cb8					<Status Checks>
00198c84: 34030073 ori r3,r0,0x0073				Frog = 6th Highest
<HP Recovery?>
00198c88: 8e820e34 lw r2,0x0e34(r20)			Load Current AI Pointer
00198c8c: 00000000 nop
00198c90: 90420006 lbu r2,0x0006(r2)			Load AI Target Flags
00198c94: 00000000 nop
00198c98: 30420002 andi r2,r2,0x0002
00198c9c: 10400006 beq r2,r0,0x00198cb8         <Status Checks> if doesn't have healing ability
00198ca0: 00001821 addu r3,r0,r0				No Priority if unit can heal itself (No low HP check)
<Low HP Unit?>
00198ca4: 92220007 lbu r2,0x0007(r17)			Load AI Target State
00198ca8: 00000000 nop
00198cac: 30420001 andi r2,r2,0x0001			Get Low HP Flag
00198cb0: 00021023 subu r2,r0,r2				-1 if Low HP Flag, else 0
00198cb4: 30430072 andi r3,r2,0x0072			Low HP = 72 (7th Lowest)
<Status Checks>
00198cb8: 1460000f bne r3,r0,0x00198cf8         <Peril Score B> if low HP unit
00198cbc: 00031600 sll r2,r3,0x18				Status Score * 1000000
<Most usable abilities?>
00198cc0: 92220006 lbu r2,0x0006(r17)			Load AI Target Flags
00198cc4: 00000000 nop
00198cc8: 30420004 andi r2,r2,0x0004
00198ccc: 14400015 bne r2,r0,0x00198d24          <Unit++> if unit has most usable abilities
00198cd0: 00000000 nop
<Acting Unit = Current Unit?>
00198cd4: 92820e2e lbu r2,0x0e2e(r20)			Load Acting Unit ID
00198cd8: 00000000 nop
00198cdc: 14520002 bne r2,r18,0x00198ce8		<Peril Score A> if Acting Unit and Current Unit are the same unit
00198ce0: 00161a00 sll r3,r22,0x08`				Ramza check * 100 = 300 (Ultimate Priority for AI)
00198ce4: 00009821 addu r19,r0,r0				Distance between targets is zero (same unit, duh)
<Peril Score A> (Non Statused Units)
(Missing HP% * 10000) + (Ramza Check * 100) + Close Distance)
00198ce8: 00151400 sll r2,r21,0x10				Missing HP% (80 - curHP%) * 10000
00198cec: 00431021 addu r2,r2,r3				Missing HP% + Ramza Check * 100
00198cf0: 08066343 j 0x00198d0c					
00198cf4: 00531821 addu r3,r2,r19				r3 = Missing HP% + Ramza Check + Distance
<Peril Score B> (Statused Unit)
(Missing HP% * 100) + (State Check * 1000000) + (Close Distance * 10000) + Ramza)
00198cf8: 00131c00 sll r3,r19,0x10				Close Distance * 10000
00198cfc: 00431021 addu r2,r2,r3				Close Distance + State Check * 1000000
00198d00: 00151a00 sll r3,r21,0x08				Missing HP% * 100
00198d04: 00431021 addu r2,r2,r3				Close Distance + State Check + Missing HP%
00198d08: 00561821 addu r3,r2,r22				Close Distance + State Check + Missing HP% + Ramza Check
<Highest Peril Check>
00198d0c: 03c3102a slt r2,r30,r3
00198d10: 10400004 beq r2,r0,0x00198d24			<Unit++> if this unit is not the current most unit in peril
00198d14: 00000000 nop
00198d18: 8e8217f8 lw r2,0x17f8(r20)			Load Acting Unit Data Pointer
00198d1c: 0060f021 addu r30,r3,r0				r30 = Highest Peril Score so far
00198d20: a05201b9 sb r18,0x01b9(r2)			Current Unit that needs to be saved the most
<Unit++>
00198d24: 26520001 addiu r18,r18,0x0001
00198d28: 2a420015 slti r2,r18,0x0015
00198d2c: 1440ff8a bne r2,r0,0x00198b58				Do for all units
00198d30: 26f701c0 addiu r23,r23,0x01c0
<Peril Minimum>
00198d34: 8e840e34 lw r4,0x0e34(r20)				Acting Unit's AI Decision Pointer
00198d38: 3c020200 lui r2,0x0200
00198d3c: 90830004 lbu r3,0x0004(r4)				Load Range
00198d40: 005e102a slt r2,r2,r30					Set if Highest Peril Score > 0x02000000
00198d44: 306300f7 andi r3,r3,0x00f7
00198d48: a0830004 sb r3,0x0004(r4)					Only look for units up to 7 range away
00198d4c: 8fbf0034 lw r31,0x0034(r29)
00198d50: 8fbe0030 lw r30,0x0030(r29)
00198d54: 8fb7002c lw r23,0x002c(r29)
00198d58: 8fb60028 lw r22,0x0028(r29)
00198d5c: 8fb50024 lw r21,0x0024(r29)
00198d60: 8fb40020 lw r20,0x0020(r29)
00198d64: 8fb3001c lw r19,0x001c(r29)
00198d68: 8fb20018 lw r18,0x0018(r29)
00198d6c: 8fb10014 lw r17,0x0014(r29)
00198d70: 8fb00010 lw r16,0x0010(r29)
00198d74: 27bd0038 addiu r29,r29,0x0038
00198d78: 03e00008 jr r31
00198d7c: 00000000 nop
Ideas to improve this routine:
Rearrange the status priorities, removing Dead w/ Reraise.
Remove the distance cap
(Ideal)Make it aware of the death countdown timer and prioritizing based on that.