• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
April 16, 2024, 07:08:05 pm

News:

Use of ePSXe before 2.0 is highly discouraged. Mednafen, RetroArch, and Duckstation are recommended for playing/testing, pSX is recommended for debugging.


Viewing attack preview causes ability action to occur

Started by stuminator, October 19, 2021, 06:54:45 pm

stuminator

October 19, 2021, 06:54:45 pm Last Edit: October 20, 2021, 05:05:45 pm by stuminator
I have a couple formulas I'm working on where simply viewing the attack preview window causes the changes to actually occur, even if you back out before confirming that you want to execute the ability. 

Here is one I'm having an issue with:

00188f90: addiu r29,r29,0xffe8
00188f94: sw r31,0x0010(r29)
00188f98: jal 0x 00185e30 #  Loads SP and X
00188f9c: nop
00188fa0: jal 0x 001885f8 #  Zodiac Calculation
00188fa4: nop
00188fa8: jal 0x 0018659c #  Loads SP + X as X
00188fac: nop
00188fb0: jal 0x 00187510 #  Total Accuracy Check
00188fb4: nop
00188fb8: lui r3,0x8019
00188fbc: lw r2,0x2d90(r3)
00188fc0: nop
00188fc4: lbu r2,0x0000(r2)
00188fc8: nop
00188fcc: beq r2,r0,0x00189038 #  branch if attack fails
00188fd0: nop
00188fd4: jal 0x0002230c #  r3=random number
00188fd8: nop
00188fdc: lui r2,0x8019
00188fe0: ori r5,r0,0x0008 #  r5=8
00188fe4: divu r3,r5 #  divide random number by 8
00188fe8: lw r4,0x2d98(r2) #  load target's data pointer
00188fec: lw r1,0x2d90(r2)
00188ff0: ori r5,r0,0x0001 #  r5=1
00188ff4: mfhi r6 #  r6=remainder (random from 0...7)
00188ff8: lbu r7,0x006d(r4) #  load target's absorb element
00188ffc: lbu r8,0x006e(r4) #  load target's null element
00189000: lbu r9,0x006f(r4) #  load target's halve element
00189004: lbu r10,0x0070(r4) #  load target's weak element
00189008: sllv r6,r5,r6 #  shift 1 left by the remainder
0018900c: xori r11,r6,0xff #  r11=bit flip of r6
00189010: and r7,r7,r11 #  remove element from absorb elements
00189014: and r8,r8,r11 #  remove element from null elements
00189018: and r9,r9,r11 #  remove element from halve elements
0018901c: or r10,r10,r6 #  add element to weak elements
00189020: sb r7,0x006d(r4) #  store new absorb elements
00189024: sb r8,0x006e(r4) #  store new null elements
00189028: sb r9,0x006f(r4) #  store new halve elements
0018902c: sb r10,0x0070(r4) #  store new weak elements
00189030: sb r5,0x0000(r1) #  store as hit?
00189034: sb r5,0x0025(r1) # store as pseudo status?
00189038: lw r31,0x0010(r29)
0018903c: addiu r29,r29,0x0018
00189040: jr r31
00189044: nop

This is basically Edgar's debilitator tool from FFVI, which causes the target to be weak to a random element.  The code begins with a copy/paste of formula 3F (Mustadio's snipe), then most everything from 00188fd4 on down are the element roll and changes.  I'm clearly missing something I need since simply running the attack preview and backing out does make the target weak to a random element.  Also, if you follow through and confirm the attack, it doesn't yield any XP or JP like normal (but does add an additional weakness on top of the attack preview.) 

Anyone know what I'm missing on this?
  • Modding version: PSX
  • Discord username: stuminator

Glain

Well, the issue is that you're directly affecting stats in the formula code, and the formula code is run during the attack preview.  You'll want to check for the preview by doing something like this:

lui r8, 0x8019
lbu r8, -0x0a04(r8)
li  r9, 2
beq r8, r9, skip

Also, I just want to point out a trick that can help out here... since you're taking the remainder of a division by a power of 2, you can just take the binary digits after that number and zero out the rest with a simple binary AND.
(Much like how doing modulus 100 on a base 10 number is the same as just taking the last two digits)

andi r6, r3, 0x07    # modulus division by 8

Edit:  As for not gaining EXP or JP, the action probably isn't flagged as doing anything (HP/MP damage, healing, or status infliction) and so the game doesn't see the action as anything that had an effect.
  • Modding version: Other/Unknown

nitwit

Quote from: Glain on October 19, 2021, 09:41:06 pmEdit:  As for not gaining EXP or JP, the action probably isn't flagged as doing anything (HP/MP damage, healing, or status infliction) and so the game doesn't see the action as anything that had an effect.
Flagged as in the skill flags, or flagged as in the "save as pseudo status effect" stuff you see in Golem, Quick, and Marlboro Spore?

Glain

I'm referring to the current action data set by the formula code (not the ability data).  See the way r16 is manipulated in this routine, and then passed to the earned experience routine.
  • Modding version: Other/Unknown

stuminator

Quote from: Glain on October 19, 2021, 09:41:06 pmWell, the issue is that you're directly affecting stats in the formula code, and the formula code is run during the attack preview.  You'll want to check for the preview by doing something like this:

lui r8, 0x8019
lbu r8, -0x0a04(r8)
li  r9, 2
beq r8, r9, skip

Ah, much appreciated.  I had noticed the offset -0x0a04 pop up a few times in other routines or formulas but didn't understand what it was doing.  Formula is now working as intended. 


Quote from: Glain on October 19, 2021, 09:41:06 pmAlso, I just want to point out a trick that can help out here... since you're taking the remainder of a division by a power of 2, you can just take the binary digits after that number and zero out the rest with a simple binary AND.
(Much like how doing modulus 100 on a base 10 number is the same as just taking the last two digits)

andi r6, r3, 0x07    # modulus division by 8

This is definitely an easier way to get random number if the range is a power of 2.


Quote from: Glain on October 19, 2021, 09:41:06 pmEdit:  As for not gaining EXP or JP, the action probably isn't flagged as doing anything (HP/MP damage, healing, or status infliction) and so the game doesn't see the action as anything that had an effect.

Still trying to get the XP/JP thing to work on this.  I thought flagging it as a pseudo status effect would do the job.  At least everything else related to the formula is working properly.

BTW, why do some formulas work ok without the check for "is it only an attack preview"?  Take a simple one like formula 45 (Target max HP - current HP):

00186e78: 3c028019 lui r2,0x8019
00186e7c: 8c422d98 lw r2,0x2d98(r2)
00186e80: 3c058019 lui r5,0x8019
00186e84: 8ca52d90 lw r5,0x2d90(r5)
00186e88: 9443002a lhu r3,0x002a(r2)
00186e8c: 94440028 lhu r4,0x0028(r2)
00186e90: 34020080 ori r2,r0,0x0080
00186e94: a0a20025 sb r2,0x0025(r5)      Set as HP Damage
00186e98: 00641823 subu r3,r3,r4      Damage is Target maxHP - curHP
00186e9c: 03e00008 jr r31
00186ea0: a4a30004 sh r3,0x0004(r5)      Store Damage

This is the entire routine, no jumps or branches. 
  • Modding version: PSX
  • Discord username: stuminator

Glain

The important difference with that code is that a variable is being set on the action as opposed to the unit.  Setting HP Damage on the action will cause the preview to show the damage, and the damage will take effect if and when the action is executed (and hits).

If that code was loading the unit HP, subtracting the damage from it, and saving the HP back, then the unit HP would decrease every time the preview was shown.

In your code from earlier, you're directly changing the unit's elemental weakness stats, as opposed to setting a variable on the action that would take effect later. (You might also have an issue with the newfound weakness disappearing in the event that the unit's elemental weakness values are recalculated, say, when a piece of equipment on the unit is stolen/broken/equip changed out)
  • Modding version: Other/Unknown

stuminator

As Glain predicted it might, a change in the unit's equipment does cause the weakness to disappear.  From what I could tell, any change to a unit's equipment causes elemental affinities to be reset to what is determined by the unit's job, then any additional modifications due to equipment are applied.  Not too surprising, since changing elemental affinities mid-battle (outside of what is caused by equipment) is something that was never intended to be included originally.

Quote from: Glain on October 20, 2021, 06:41:49 pmThe important difference with that code is that a variable is being set on the action as opposed to the unit.  Setting HP Damage on the action will cause the preview to show the damage, and the damage will take effect if and when the action is executed (and hits).

Makes perfect sense, now I see the difference here.  Since there are a limited number of action types the game recognizes, coding an action not originally intended will need the "only a preview" check to work properly.
  • Modding version: PSX
  • Discord username: stuminator