Users browsing this thread: 11 Guest(s)
Breakable Tools - Need Help
(07-07-2021, 05:46 PM)Bropedio Wrote: Edit: On second thought, this will definitely not work out of the box for DP, since it uses BNW's "free turn" handling on successful steal. But the code could be tweaked pretty easily to adjust back to vanilla.
It looks like...
Code:
JSR $3CB8 ; free-turn + load unique bit
EDIT: Oh I'm wrong, I've misunderstood something fundamental about how Bropedio's code handles the inventory replacement. This will take more study.
07-07-2021, 09:24 PM
(This post was last modified: 07-07-2021, 11:18 PM by PowerPanda.)
Okay, I've had a chance to look at my "Steal Twice" code, and I remember what I did. Don't feel bad for not understanding it. Even Assassin had to look at it 3 different times to figure out what it was actually doing.
From what I understand, the PHY/PLY has to do with the enemy counterattacking correctly. The problem with where it was placed in the original code is that it blows away the INY at C2/39E0 for which item you're targeting (common or rare). This doesn't matter in vanilla, because 1 successful steal blanks out both slots. However, by moving the PLY to AFTER the "LDA #$FF/STA $3308,Y", the INY from the item slot targeting is retained, and the function to empty that slot simply targets whichever slot you actually stole from.
The only catch was that if you successfully stole, but the slot you were targeting was empty, Y got pushed, but never pulled. Because of that, I put a 2nd PLY at C2/3A00. All other branches to the "Fail to steal" jump to C2/3A01, but that specific case needed a PLY first.
I'll take a look at Bropedia's code in about an hour.
Looked at Bropedia's code, and added it to my rom. Now I need to figure out how to call it from both branches (The item broke, or the item didn't break).
The item breaking is easy, because it's an exact copy of the Metamorph code.
What I don't know iis how to fit this into the No_Break branch:
On this branch, XBA never happened. I also don't know what the 4 bytes exclusive to the "no_break" section do.
Oh, one last note: Subtraction, I reverted to a 1 in 32 chance (AND #$1F instead of my bugged AND #$2A).
From what I understand, the PHY/PLY has to do with the enemy counterattacking correctly. The problem with where it was placed in the original code is that it blows away the INY at C2/39E0 for which item you're targeting (common or rare). This doesn't matter in vanilla, because 1 successful steal blanks out both slots. However, by moving the PLY to AFTER the "LDA #$FF/STA $3308,Y", the INY from the item slot targeting is retained, and the function to empty that slot simply targets whichever slot you actually stole from.
The only catch was that if you successfully stole, but the slot you were targeting was empty, Y got pushed, but never pulled. Because of that, I put a 2nd PLY at C2/3A00. All other branches to the "Fail to steal" jump to C2/3A01, but that specific case needed a PLY first.
Code:
Steal function
C2/399E: A3 05 LDA $05,S (Attacker)
C2/39A0: AA TAX
C2/39A1: A9 01 LDA #$01
C2/39A3: 8D 01 34 STA $3401 (=1) (Sets message to "Doesn't have anything!")
C2/39A6: E0 08 CPX #$08 (Check if attacker is monster)
C2/39A8: B0 5F BCS $3A09 (Branch if monster)
C2/39AA: C2 20 REP #$20 (Set 16-bit accumulator)
C2/39AC: B9 08 33 LDA $3308,Y (Target's stolen items)
C2/39AF: 1A INC
C2/39B0: E2 21 SEP #$21 (Set 8-bit Accumulator AND Carry Flag)
C2/39B2: F0 4D BEQ $3A01 (Fail to steal if no items)
C2/39B4: EE 01 34 INC $3401 (now = 2) (Sets message to "Couldn't steal!!")
C2/39B7: BD 18 3B LDA $3B18,X (Attacker's Level)
C2/39BA: 69 32 ADC #$32 (adding 51, since Carry Flag was set)
C2/39BC: B0 1A BCS $39D8 (Automatically steal if level >= 205)
C2/39BE: F9 18 3B SBC $3B18,Y (Subtract Target's Level, along with an extra 1 because
Carry Flag is unset at this point. Don't worry; this
cancels out with the extra 1 from C2/39BA.)
(StealValue = [attacker level + 51] - [target lvl + 1]
= Attacker level + 50 - Target level )
C2/39C1: 90 3E BCC $3A01 (Fail to steal if StealValue < 0)
C2/39C3: 30 13 BMI $39D8 (Automatically steal if StealValue >= 128)
C2/39C5: 85 EE STA $EE (save StealValue)
C2/39C7: BD 45 3C LDA $3C45,X
C2/39CA: 4A LSR
C2/39CB: 90 02 BCC $39CF (Branch if no sneak ring)
C2/39CD: 06 EE ASL $EE (Double value)
C2/39CF: A9 64 LDA #$64
C2/39D1: 20 65 4B JSR $4B65 (Random: 0 to 99)
C2/39D4: C5 EE CMP $EE
C2/39D6: B0 29 BCS $3A01 (Fail to steal if the random number >= StealValue)
C2/39D8: 5A PHY
C2/39D9: 20 5A 4B JSR $4B5A (Random: 0 to 255)
C2/39DC: C9 20 CMP #$20
C2/39DE: 90 01 BCC $39E1 (branch 1/8 of the time, so Rare steal slot
will be checked)
C2/39E0: C8 INY (Check the 2nd [Common] slot 7/8 of the time)
C2/39E1: B9 08 33 LDA $3308,Y (Target's stolen item)
*C2/39E4: EA NOP (This is not where we restore Y, as that will blow away our item slot targeting)
C2/39E5: C9 FF CMP #$FF (If no item)
*C2/39E7: F0 17 BEQ $3A00 (Restore Y and the fail to steal)
C2/39E9: 8D 35 2F STA $2F35 (save Item stolen for message purposes in
parameter 1, bottom byte)
C2/39EC: 9D F4 32 STA $32F4,X (Store in "Acquired item")
C2/39EF: BD 18 30 LDA $3018,X
C2/39F2: 0C 8C 3A TSB $3A8C (flag character to have any applicable item in
$32F4,X added to inventory when turn is over.)
C2/39F5: A9 FF LDA #$FF
C2/39F7: 99 08 33 STA $3308,Y (Set to no item to steal)
*C2/39FA: EE 01 34 INC $3401 (now = 3) (Sets message to "Stole #whatever ")
*C2/39FD: 7A PLY (HERE is where we restore Y, now that we no longer need to hold onto our item slot)
*C2/39FE: 60 RTS
*C2/39FF: EA NOP (No function; simply 1 left-over byte)
Restore Y for Counterattack
*C2/3A00: 7A PLY (Restore Y and continue on to fail to steal)
Fail to steal
C2/3A01: E2 20 SEP #$20
C2/3A03: A9 00 LDA #$00
C2/3A05: 99 48 3D STA $3D48,Y (save Fight as command for counterattack purposes)
C2/3A08: 60 RTS
I'll take a look at Bropedia's code in about an hour.
Looked at Bropedia's code, and added it to my rom. Now I need to figure out how to call it from both branches (The item broke, or the item didn't break).
The item breaking is easy, because it's an exact copy of the Metamorph code.
Code:
***ORIGINAL***
STA $32F4,X ; null item index to add to inventory. This means the item will stay deducted from your inventory.
LDA $3018,X
BRA check_break_end
(...)
check_break_end
TSB $3A8C ; flag character to have any applicable item in $32F4,X added back to inventory when turn is over.
***CHANGED TO FIT WITH BROPEDIA'S CODE***
XBA ; store item in B (in this case $FF, Empty)
LDA $3018,X ; character's unique bit
BRA check_break_end
(...)
check_break_end
JSR SaveItem ; save new item to buffer
What I don't know iis how to fit this into the No_Break branch:
Code:
no_break:
LDA #$10
TSB $B1 ; set flag to re-add item to inventory at the end of the character's turn
check_break_end:
TSB $3A8C ; !!THIS LINE WAS CHANGED ABOVE TO "JSR SaveItem"!!
PLP
PLA
SBC #$A2 ; carry was clear, so subtract 163
STA $B6 ; save unique Tool index. 0 = NoiseBlaster, 1 = Bio Blaster, etc.
RTS
On this branch, XBA never happened. I also don't know what the 4 bytes exclusive to the "no_break" section do.
Oh, one last note: Subtraction, I reverted to a 1 in 32 chance (AND #$1F instead of my bugged AND #$2A).
Projects:
FFVI: Divergent Paths (Completed) - a complete storyline and gameplay hack of FF6 that adds Leo as a playable character
Here's a breakdown of all the code that I believe needs to be changed from the Divergent Paths 1.0 release. I would've included all of the tool breakage code too, but there's an origin address missing in the first post so I don't know where all those command comparisons are taking place.
Essentially, you need to first make sure you've applied ALL of Bropedio's fix, so that Metamorph--which Kappa uses--and Steal/Mug--which Locke uses--are also fixed and don't contribute to the problem [Note the small tweak, the Steal fix is identical to the Metamorph fix in the above code]. THEN, we change the no_break branch to rev up the same restore situation that the break branch does, but with the original item ID in A instead of #$FF. We do this by taking the second variable on the stack, because it was the second-to-last to be placed in the stack [at the very start of your tool breakage subroutine]. This variable was the original item ID, before any multiplication or shuffling took place.
I tried it up to 14 with tool usage and it appears to work. I urge you to test it more thoroughly. Bropedio's code did all the heavy lifting here, all I did was restore the original tool ID before running it (kinda like that earlier fix I proposed, but with the vanilla bug now corrected).
EDIT: IMPORTANT! Make sure you also fix the item buffer length in C1, or the original bug will still be a problem! Added as the first line in the code block because it is by far the most essential.
EDIT: CAUTION! If you took the block of code before 7-8-2021, you need to take it again. I made a mistake in the assembly... wrote "TBA" instead of "XBA", xKas ignored it, and the code worked as intended. When I corrected my 'error', it started ADDING tools to the menu. This implied my earlier approach was not using Bropedio's buffer fix properly, so I ran through the code again and found that the four bytes that were bothering you were indeed a source of problems (they were telling the item to be added twice). So I removed them and now it seems to be working.
Code:
$C112D5: [Fix Item return buffer]
HEX
E0 50 00
CODE MEANING
CPX #$0050 ; The game only clears #$40 for item buffer, but it expects #$50 [Bropedio]
$C20A2B:
HEX
20 60 65
CODE MEANING
JSR ReturnReserve
$C239EC: [Steal Fix]
HEX
EB BD 18 30 20 4B 65 EA EA
CODE MEANING
XBA ; store acquired item in B
LDA $3018,X ; character's unique bit
JSR SaveItem ; save new item to buffer
NOP #2
$C23A7C: [Metamorph Fix]
HEX
EB BD 18 30 20 4B 65 EA EA
CODE MEANING
XBA ; store acquired item in B
LDA $3018,X ; character's unique bit
JSR SaveItem ; save new item to buffer
NOP #2
$C26490: [Breakable Tools]
HEX
C9 09 F0 06 C9 01 F0 02 C9 08 60 48 08 20 63 2B C2 10 AA BF 12 50 D8 10 1E 20 5A 4B 29 1F D0 17 A9 08 2C BB 3E D0 10 A9 44 8D 01 34 E2 10 BB A9 FF EB BD 18 30 80 09 E2 10 BB A3 02 EB BD 18 30 20 4B 65 28 68 E9 A2 85 B6 60
CODE MEANING
check_command_c2:
CMP #$09
BEQ check_command_c2_end
CMP #$01
BEQ check_command_c2_end
CMP #$08
check_command_c2_end:
RTS
check_break:
PHA
PHP
JSR $2B63 ; Multiply A by 30, size of item data block
REP #$10 ; Set 16-bit X and Y
TAX
LDA $D85012,X ; equipment spell byte. Bit 7: 1 = remove from inventory upon usage, 0 = nope
BPL no_break ; if the flag is not set, this tool never breaks
JSR $4B5A
AND #$1F ; 1/32 chance of breaking
BNE no_break
LDA #$08
BIT $3EBB ; Check bit 4 of $3EBB (loaded from 1DD0 at the beginning of battle).
BNE no_break ; If set, tools can't be broken (set via event with B8 3B. Clear with B9 3B)
LDA #$44 ; "Orge Nix broke!" dialog. Works for most tools but gets clobbered by the Air Anchor "Move and you're dust!"
STA $3401
SEP #$10 ; Set 8-bit X and Y
TYX
LDA #$FF
XBA ; Put it into B because we're in 8-bit mode. This acts like a free scratch variable
LDA $3018,X
BRA check_break_end
no_break:
SEP #$10 ; Set 8-bit X and Y
TYX
LDA $02,S ; Load the second item off the stack. In this instance, it's a copy of the A we pushed, the tool's original item ID.
XBA ; Put it into B because we're in 8-bit mode. This acts like a free scratch variable
LDA $3018,X ; character's unique bit
check_break_end:
JSR SaveItem ; save new item to buffer [This ensures if there's an old item waiting, like a reusable rod, it gets saved]
PLP
PLA
SBC #$A2 ; carry was clear, so subtract 163
STA $B6 ; save unique Tool index. 0 = NoiseBlaster, 1 = Bio Blaster, etc.
RTS
$C2654B: [Save Item & Return Reserve]
HEX
0C 8C 3A BD F4 32 48 EB 9D F4 32 DA 20 C7 62 FA 68 9D F4 32 60 BD 18 30 0C 8C 3A BD 19 32 60
CODE MEANING
SaveItem: ; 21 bytes
TSB $3A8C ; set character's reserve item to be added
LDA $32F4,X ; load current reserve item
PHA ; save reserve item on stack
XBA ; get new item in A
STA $32F4,X ; store new item in reserve byte
PHX ; save X
JSR $62C7 ; add reserve to obtained-items buffer
PLX ; restore X
PLA ; restore previous reserve item
STA $32F4,X ; store in reserve item byte again
RTS
ReturnReserve: ; 10 bytes
LDA $3018,X ; character's unique bit
TSB $3A8C ; return reserve to inventory at turn end
LDA $3219,X ; ATB top byte (vanilla code)
RTS
I tried it up to 14 with tool usage and it appears to work. I urge you to test it more thoroughly. Bropedio's code did all the heavy lifting here, all I did was restore the original tool ID before running it (kinda like that earlier fix I proposed, but with the vanilla bug now corrected).
EDIT: IMPORTANT! Make sure you also fix the item buffer length in C1, or the original bug will still be a problem! Added as the first line in the code block because it is by far the most essential.
EDIT: CAUTION! If you took the block of code before 7-8-2021, you need to take it again. I made a mistake in the assembly... wrote "TBA" instead of "XBA", xKas ignored it, and the code worked as intended. When I corrected my 'error', it started ADDING tools to the menu. This implied my earlier approach was not using Bropedio's buffer fix properly, so I ran through the code again and found that the four bytes that were bothering you were indeed a source of problems (they were telling the item to be added twice). So I removed them and now it seems to be working.
07-08-2021, 08:21 AM
(07-07-2021, 04:10 PM)PowerPanda Wrote: So, instead of using the Multi-Steal Fix, I'm using Assassin's "Recapture the Glory", which treats each steal attempt with dual weapons as a separate attempt, with each one getting weapon special effects, counter-effects, etc. Because of my changes to Steal, plus the way Recapture the Glory handles things, I actually didn't (previously) see a need for the Multi-Steal fix. I am still hesitant to change the Steal special effect itself, since it is working exactly as I want it to.
Looking at Assassin's notes on Recapture the Glory, it doesn't seem like it does anything to prevent issues arising from multiple steal attempts. So I just performed a test where I mugged 2 Hi-Potions from a Lunaris, and it only gave me one of them. Suppose the steal options were instead Elixir vs Hi-Ether, it would be possible to clobber one with the other depending on which you snagged first.
This could also come up with an Offering+Thief Knife or Offering+Thief Glove combo, if you succeed on a steal attempt against more than one target. This would probably be more likely to come up than the Rare+Common combo, since you can just get the Common more than once with a higher degree of success.
07-08-2021, 11:14 AM
IT IS WORKING. I REPEAT, IT IS WORKING.
The only oddity is that the Tool gets added back to the inventory before the character uses it; so you can "predict" breakage by checking the item menu with another character. However, that is such a small thing compared to the other issue that I'm comfortable releasing it as-is.
C-Dude and Bropedia, thank you. And thanks also to Subtraction for writing the code in the first place, and Gi Nattak for helping me figure out what was going on. I'm feeling the community love this morning.
The only oddity is that the Tool gets added back to the inventory before the character uses it; so you can "predict" breakage by checking the item menu with another character. However, that is such a small thing compared to the other issue that I'm comfortable releasing it as-is.
C-Dude and Bropedia, thank you. And thanks also to Subtraction for writing the code in the first place, and Gi Nattak for helping me figure out what was going on. I'm feeling the community love this morning.
Projects:
FFVI: Divergent Paths (Completed) - a complete storyline and gameplay hack of FF6 that adds Leo as a playable character
07-08-2021, 02:16 PM
(07-08-2021, 08:21 AM)SirNewtonFig Wrote: Looking at Assassin's notes on Recapture the Glory, it doesn't seem like it does anything to prevent issues arising from multiple steal attempts. So I just performed a test where I mugged 2 Hi-Potions from a Lunaris, and it only gave me one of them. Suppose the steal options were instead Elixir vs Hi-Ether, it would be possible to clobber one with the other depending on which you snagged first.
This could also come up with an Offering+Thief Knife or Offering+Thief Glove combo, if you succeed on a steal attempt against more than one target. This would probably be more likely to come up than the Rare+Common combo, since you can just get the Common more than once with a higher degree of success.
Just to follow up on this, I tried this same test with C-Dude's fixes applied, and it worked perfectly – both Hi-Potions were acquired as expected. Onward!
07-08-2021, 05:31 PM
(07-08-2021, 02:16 PM)SirNewtonFig Wrote: Just to follow up on this, I tried this same test with C-Dude's fixes applied, and it worked perfectly – both Hi-Potions were acquired as expected. Onward!
Bropedio's fix. (All I did was integrate Bropedio's fix into Subtraction's Tool Breakage).
Bropedio's fix is a from-scratch Multisteal fix, which works with Recapture the Glory because of how it hooks into the game. I should really look into applying both to my game too... if only I hadn't eaten so much C2 space with extra ending names.
« Next Oldest | Next Newest »
Users browsing this thread: 11 Guest(s)