Users browsing this thread: 1 Guest(s)
Giving Everyone the Same Desperation Attack

#1
Posts: 614
Threads: 49
Thanks Received: 0
Thanks Given: 4
Joined: Feb 2017
Reputation: 25
Status
None
Hi there. I'm just about to implement B-Run's MMMMMagic 2.0 patch, and one of the thing I've noted is that it doesn't really do anything with desperation attacks. So if you went with the default plug-and-play patch, and had Terra do a desperation attack, she would do the Black Magic spell "Drain 2" instead (as this overwrites the slot $F0 for Riot Blade).

My solution for this is to have everyone share a single move, named "Desperation", in ability slot $F0. I think I know what to do, but I want to make sure I'm not overlooking anything. Here's the original code:
Code:
C2/15F8: B9 D8 3E     LDA $3ED8,Y    (Which character it is)
C2/15FB: C9 0C        CMP #$0C
C2/15FD: F0 05        BEQ $1604      (branch if Gogo)
C2/15FF: C9 0B        CMP #$0B
C2/1601: B0 0D        BCS $1610      (branch if Character 11 or above: Gau, Umaro, or
                                     special character.  none of these characters have DAs)
C2/1603: 1A           INC
C2/1604: 3A           DEC            (if it was Gogo, we decrement the DA by 1 to account
                                     for Gau -- who's before Gogo -- not having one)
C2/1605: 09 F0        ORA #$F0  
C2/1607: 85 B6        STA $B6        (add F0h to modified character #, then save as attack #)

I THINK I just have to NOP out the check for the character number, right? That should make it load ability $F0 for everyone, right? Is there anything I'm missing?

Code:
C2/15F8: EA EA EA
C2/15FB: EA EA        
C2/15FD: EA EA        
C2/15FF: EA EA        
C2/1601: EA EA        
C2/1603: EA          
C2/1604: EA          
C2/1605: 09 F0        ORA #$F0  
C2/1607: 85 B6        STA $B6        (add F0h to modified character #, then save as attack #)


Projects:
FFVI: Divergent Paths (Completed) - a complete storyline and gameplay hack of FF6 that adds Leo as a playable character
  Find
Quote  

#2
Posts: 175
Threads: 11
Thanks Received: 10
Thanks Given: 8
Joined: May 2013
Reputation: 13
Status
Well-Fed
You want to make that a LDA #$F0, not an ORA. Otherwise, at a glance, this should do what you want, yes!


Current Project: FF6: Tensei | Discord ID: TristanGrayse
  Find
Quote  

#3
Posts: 614
Threads: 49
Thanks Received: 0
Thanks Given: 4
Joined: Feb 2017
Reputation: 25
Status
None
I decided to expand this a bit. MMMMMagic leaves 3 unused abilities. My hack uses one of those as a replacement ability for "Health", so I have 2 slots remaining. I decided I wanted to do 2 tiers of desperation attack. I'm just having trouble with how to check one accumulator. Here's the logic of my hack in plain English:

1. Make sure the character is eligible for a Desperation Attack. This means:
    a. They're not a monster, but they are targeting a monster.
    b. They are in near fatal status.
    c. They have none of the following statuses: muddle, image, clear, zombie.
    d. They haven't already used a Desperation Attack this turn.
2. Do a Desperation Attack 1 in 16 times.
    a. If no characters are dead, do Desperation Lvl. 1 (Ability FA)
    b. If at least one character is dead, flip a coin. 50% of the time, upgrade to Desperation Lvl. 2 (Ability FB)

The problem is the section of code from C2/15F1-C2/15F5. Right now, the code checks for if the ATTACKER is dead (which would obviously never happen). How do I check to see if OTHER party members are dead?

Also, is there a way to do a multiplier times the number of dead party members? So, for example, if 1 party member is dead, you have a 33% (hex: $55) chance of DA Lvl2. If 2 are dead, 66% (hex: $AA). If 3 are dead, you will always do DA Lvl 2 (hex: $FF). This is my first real attempt at ASM, so any help is appreciated.

Here is the code I have so far.
Code:
(Fight - check for Desperation attack first)

C2/15C8: C0 08        CPY #$08
C2/15CA: B0 44        BCS $1610      (No Desperation Attack if attacker is a monster)
C2/15CC: B9 E5 3E     LDA $3EE5,Y
C2/15CF: 89 02        BIT #$02
C2/15D1: F0 3D        BEQ $1610      (No Desperation Attack if attacker is not near fatal)
C2/15D3: 89 24        BIT #$24
C2/15D5: D0 39        BNE $1610      (No Desperation Attack if attacker has Muddled or Image status)
C2/15D7: B9 E4 3E     LDA $3EE4,Y
C2/15DA: 89 12        BIT #$12    
C2/15DC: D0 2B        BNE $1610      (No Desperation Attack if attacker has Clear or Zombie status)
C2/15DE: A5 B9        LDA $B9
C2/15E0: F0 2E        BEQ $1610      (No Desperation Attack if target is not a monster)
C2/15E2: 20 5A 4B     JSR $4B5A      (Choose a random number between 0 and 255)
C2/15E5: C9 0F        CMP #$0F       (Is the number >15?) (15/16 chance of this being yes)
C2/15E7: D0 27        BNE $1610      (If so, branch to normal attack.)
C2/15E9: B9 18 30     LDA $3018,Y    
C2/15EC: 0C 2F 3F     TSB $3F2F      (Check if chraacter has used Desperation. If not, increment up one.)
C2/15EF: D0 20        BNE $1610      (If character has already used a Desperation, branch to normal attack)
C2/15F1: BD E4 3E     LDA $3EE4,X
C2/15F4: 89 C2        BIT #$C2       (Check for Dead, Zombie, or Petrify)
C2/15F6: F0 0B        BEQ $1603      (If no, branch to Desperation Lvl 1)
C2/15F8: 20 5A 4B     JSR $4B5A      (Choose a random number between 0 and 255)
C2/15FB: C9 80        CMP #$80       (Is the number between >128) (50% chance of this being yes)
C2/15FD: D0 04        BNE $1603      (If so, branch to Despeartion Lvl 1)
C2/15FF: A9 FB          LDA FB         (Queue Up Desperation Lvl 2 - Ability FB)
C2/1601: 80 02        BRA $1605         (and branch)
C2/1603: A9 FA        LDA FA         (Queue Up Desperation Lvl 1 - Ability FA)
C2/1605: 85 B6          STA $B6         (Save Attack #)
C2/1607: A9 10        LDA #$10
C2/1609: 14 B0        TRB $B0        (???  See functions C2/13D3 and C2/57C2 for usual
                                     purpose; dunno whether it does anything here.)
C2/160B: 4C 14 17     JMP $1714
C2/160E: EA EA        NOP


Projects:
FFVI: Divergent Paths (Completed) - a complete storyline and gameplay hack of FF6 that adds Leo as a playable character
  Find
Quote  

#4
Posts: 48
Threads: 7
Thanks Received: 0
Thanks Given: 0
Joined: Dec 2017
Reputation: 0
Status
None
The following line:

Code:
C2/15F1: BD E4 3E     LDA $3EE4,X

Actually loads the status of the attacker into A. According the this document: https://www.ff6hacking.com/wiki/doku.php...battle_ram , the values for all the current statuses of the characters are there:

Code:
$3EE4 Current Status 1
$3EE5 Current Status 2
$3EF8 Current Status 3
$3EF9 Current Status 4

But I don't know how are stored the values of the statuses for each character. (Why is there such a gap between CS1&2 and CS3&4? Even by accounting for 4 characters, there is still a few unexplained bytes! May somebody share a light please?)

But anyway, you will want to loop through these four values and check if a given character is dead. For every dead character, you add #$55 to an unused variable (since you have at most 3 dead characters, that value will at most be #$FF). Then, at C2/15FB, instead of comparing with #$80, you will compare with the content of that variable.

Or, instead, you may want to start that variable value at #$FF and substract #$55 for every alive character so that if you are alone, you will have the same percentage of getting a Lvl 2 desperation attack as if you were with 3 dead characters. But doing so will force to add a condition to check whether the alive character is the attacker, ignoring him if that is the case.
  Find
Quote  
[-] The following 1 user says Thank You to NPCnextdoor for this post:
  • PowerPanda (07-20-2018)

#5
Posts: 200
Threads: 1
Thanks Received: 10
Thanks Given: 0
Joined: Oct 2015
Reputation: 18
Status
None
those aren't just for characters, but for all 10 battle entities, including monsters.
Quote  
[-] The following 1 user says Thank You to assassin for this post:
  • NPCnextdoor (07-21-2018)

#6
Posts: 178
Threads: 2
Thanks Received: 23
Thanks Given: 4
Joined: Apr 2015
Reputation: 18
Status
None
You could try using $3A56. A bit gets set for each character with Wound, Petrify, or Zombie status. See C2/46A9.

There's also a subroutine at C2/520E which counts the number of bits set in the accumulator. You could use this to get your multiplier. For example:

Code:
LDA $3A56 ; bit mask for number of dead characters (use 8-bit A to get characters only)
JSR $520E ; count bits set in A

; now X holds the number of dead characters
; you can use this to adjust the probability of getting a lv.2 desperation attack

There's also $3A76, which is a count of the number of characters that are alive. See C2/4AB9.
  Find
Quote  
[-] The following 1 user says Thank You to Everything for this post:
  • PowerPanda (07-21-2018)

#7
Posts: 48
Threads: 7
Thanks Received: 0
Thanks Given: 0
Joined: Dec 2017
Reputation: 0
Status
None
Here is my attempt. The key word being "attempt". This wasn't tested. Wink

So, instead of LDA $3EE4,X at C2/15F1, you could JSR elsewhere in C2 (or JSL in another bank) and either plug in this additive subroutine:


Code:
DA  --  --  PHX          ;Put X into the stack, just in case that value is useful later in the code
9C  va  r1  STZ  var1    ;Store zero into var1
A2  00  --  LDX  #$00    ;Clear X

beginning_of_loop:
E0  08  --  CPX  #$08    ;Compare X with #$08
B0  0F  --  BCS  end     ;If X is greater or equal to #$08 (or is the battle entity an enemy?), skip to the end
BD  34  13  LDA  $1334,X ;Load into the accumulator the character current status #1
89  C2  --  BIT  #$C2    ;Bitwise AND between the accumulator and C2 (Does the character has status Death, Zombie or Petrify?)
F0  08  --  BEQ  adding_desperation_chance  ;If the character has none of these statuses, skip the addition part
A9  55  --  LDA  #$55    ;Load 1/3 of #$FF into the accumulator
6D  va  r1  ADC  var1    ;Add var1 to the accumulator
8D  va  r1  STA  var1    ;Store the accumulator into var1

adding_desperation_chance:
E8  --  --  INX        
E8  --  --  INX         ;Increase X by 2 in order to target the next battle entity current status #1
80  E9  --  BRA  beginning_of_loop

end:
FA  --  --  PLX         ;Pull stacked value back into X        
60  --  --  RTS         ;Return (user RTL if you changed bank)


Or this substractive subroutine:


Code:
8E  va  r1  STX  var1    ;Store X into var1, because we will need that value to check whether the character is the attacker
DA  --  --  PHX          ;Push X into the stack
A9  FF  --  LDA  #$FF    ;Load #$FF in the accumulator
8D  va  r2  STA  var2    ;Store #$FF into var2
A2  00  --  LDX  #$00    ;Clear X

beginning_of_loop:
E0  08  --  CPX  #$08    ;Compare X with #$08
B0  19  --  BCS  end     ;If X is greater or equal to #$08 (or is the battle entity an enemy?), skip to the end;
BD  34  13  LDA  $1334,X ;Load into the accumulator the character current status #1
89  C2  --  BIT  #$C2    ;Bitwise AND between the accumulator and C2 (Does the character has status Death, Zombie or Petrify?)
D0  0E  --  BNE  reducing_desperation_chance ;If the character has any of these statuses, skip the substraction part
EC  va  r1  CPX  var1    ;Compare X with var1
F0  09  --  BEQ  skip_reducing_desperation_chance ;If the current character is the attacker, skip the substraction part
38  --  --  SEC          ;Set the carry flag, in preparation of the substraction
AD  va  r2  LDA  var2    ;Load var2 into the accumulator
E9  55  --  SBC  #$55    ;Substract 1/3 of #$FF from the accumulator
8D  va  r2  STA  var2    ;Store the accumulator back into var2

reducing_desperation_chance:
E8  --  --  INX        
E8  --  --  INX          ;Increase X by 2 in order to target the next battle entity current status #1
80  E3  --  BRA  beginning_of_loop

end:
FA  --  --  PLX          ;Pull stacked value back into X
60  --  --  RTS          ;return (Use RTL if you changed bank)

(I changed some things around while writing this reply. I hope I adjusted the branchings correctly Tongue).

Because I don't know which memory addresses are available at that point in the battle, hence the names var1 and var2. Replace them at your convenience.

After that, you will need to change C2/15FB for CMP var1 (or var2, depending of the method used). Because this opcode will be using 3 bytes instead of 2, you will need to move the rest of the code (getting rid of one EA at the end). Make sure the branchings are recalculated accordingly.

EDIT: I forgot that this subroutine makes C2/15F4 and C2/15F6 useless, giving you space for CMP var1/2 without having to move everything around.
  Find
Quote  

#8
Posts: 614
Threads: 49
Thanks Received: 0
Thanks Given: 4
Joined: Feb 2017
Reputation: 25
Status
None
A couple of days ago, I realized that Gau's Leap had a check to miss if he was the only living character. That's exactly what I needed, so I was able to just copy/paste that check in. It is:

Code:
C2/3B78: AD 76 3A     LDA $3A76      (Number of present and living characters in party)
C2/3B7B: C9 02        CMP #$02
C2/3B7D: 90 11        BCC $3B90      (if less than 2, branch 11 bytes forward)

Using that as a template, I coded a working version of my Desperation Attack routine. It does all of the normal checks, minus the battle timer of 25 seconds. Then, it checks if the attacker is the sole remaining person standing in the party. If they are, they have a 1/6 chance of doing a Lvl 2 desperation attack. If there is more than one character still alive, there is a 1/12 chance of doing a Lvl 1 desperation attack. Here it is:

Code:
;XX = Spell address of Level 1 Desperation Attack
;YY = Spell address of Level 2 Desperation Attack

C2/15C8: C0 08        CPY #$08
C2/15CA: B0 44        BCS $1610      (No Desperation Attack if attacker is a monster)
C2/15CC: B9 E5 3E     LDA $3EE5,Y
C2/15CF: 89 02        BIT #$02
C2/15D1: F0 3D        BEQ $1610      (No Desperation Attack if attacker is not near fatal)
C2/15D3: 89 24        BIT #$24
C2/15D5: D0 39        BNE $1610      (No Desperation Attack if attacker has Muddled or Image status)
C2/15D7: B9 E4 3E     LDA $3EE4,Y
C2/15DA: 89 12        BIT #$12    
C2/15DC: D0 2B        BNE $1610      (No Desperation Attack if attacker has Clear or Zombie status)
C2/15DE: A5 B9        LDA $B9
C2/15E0: F0 2E        BEQ $1610      (No Desperation Attack if target is not a monster)
C2/15E2: B9 18 30     LDA $3018,Y    
C2/15E5: 0C 2F 3F     TSB $3F2F      (Check if chraacter has used Desperation. If not, increment up one.)
C2/15E8: D0 26        BNE $1610      (If character has already used a Desperation, branch to normal attack)
C2/15EA: AD 76 3A     LDA $3A76         (Check for # of living characters)
C2/15ED: C9 01        CMP #$01         (Is there only 1? In other words, is the attacker the only one standing?)      
C2/15EF: D0 0B        BNE $15FC      (If no, branch to Desperation Lvl 1)
C2/15F1: 20 5A 4B     JSR $4B5A      (Choose a random number between 0 and 255)
C2/15F4: 29 2A        CMP #$2A       (Is the number > 42?) (~1/6 chance of this being yes)
C2/15F6: B0 18        BCS $1610      (If yes, branch to normal attack.)
C2/15F8: A9 YY          LDA YY         (Queue Up Desperation Lvl 2)
C2/15FA: 80 09          BRA $1605         (and branch)
C2/15FC: 20 5A 4B     JSR $4B5A      (Choose a random number between 0 and 255)
C2/15FF: 29 15        CMP #$15       (Is the number > 21?) (~1/12 chance of this being yes)
C2/1561: B0 0D        BCS $1610      (If yes, branch to normal attack.)
C2/1563: A9 XX        LDA XX         (Queue Up Desperation Lvl 1)
C2/1605: 85 B6          STA $B6         (Save Attack #)
C2/1607: A9 10        LDA #$10
C2/1609: 14 B0        TRB $B0        
C2/160B: 4C 14 17     JMP $1714
C2/160E: EA EA        NOP
I am going to sit on this for a few days, then see if I can re-write it so that you don't ALWAYS get a Lvl2 if you're the only one standing.


Projects:
FFVI: Divergent Paths (Completed) - a complete storyline and gameplay hack of FF6 that adds Leo as a playable character
  Find
Quote  
[-] The following 1 user says Thank You to PowerPanda for this post:
  • madsiur (08-05-2018)

#9
Posts: 81
Threads: 12
Thanks Received: 0
Thanks Given: 0
Joined: Feb 2017
Reputation: 3
Status
Brave
Can you make it so that even characters like Gau and Umaro can do them, if they are given the fight command?
  Find
Quote  

#10
Posts: 614
Threads: 49
Thanks Received: 0
Thanks Given: 4
Joined: Feb 2017
Reputation: 25
Status
None
Timbo, that's the current state. There is no longer a check for characters. Even guest characters like Ghost will use this routine.

Note that I discovered a gross oversight in the routine. I write to the D.A. ram byte before I've confirmed that the attack is possible. I'll re-write sometime later today.

Okay, I was able to fix the code. I realized that I would need to duplicate the code for writing the character's D.A. bit if I were to move it to where it SHOULD be, which would mean expanding this routine beyond its current bounds. After testing several variations of desperation attacks, I've decided that I don't have a compelling reason to add a Lvl 2. Rather, I've changed the code so that there is a 1 in 16 chance for a Desperation Attack (like normal), but if the attacker is the last character standing, that probability jumps to 1 in 4. Here is the code that I will be using in my game. (Note, I'm also nopping out C2/453B so that near fatal triggers at 1/4th HP, not 1/8th.)

Code:
;(Fight - check for Desperation attack)

;Check for D.A. Eligibility
C2/15C8: C0 08        CPY #$08
C2/15CA: B0 44        BCS $1610      (No Desperation Attack if attacker is a monster)
C2/15CC: B9 E5 3E     LDA $3EE5,Y
C2/15CF: 89 02        BIT #$02
C2/15D1: F0 3D        BEQ $1610      (No Desperation Attack if attacker is not near fatal)
C2/15D3: 89 24        BIT #$24
C2/15D5: D0 39        BNE $1610      (No Desperation Attack if attacker has Muddled or Image status)
C2/15D7: B9 E4 3E     LDA $3EE4,Y
C2/15DA: 89 12        BIT #$12    
C2/15DC: D0 2B        BNE $1610      (No Desperation Attack if attacker has Clear or Zombie status)
C2/15DE: A5 B9        LDA $B9
C2/15E0: F0 2E        BEQ $1610      (No Desperation Attack if target is not a monster)

;Check Living characters
C2/15E2: AD 76 3A     LDA $3A76         (Check for # of living characters)
C2/15E5: C9 01        CMP #$01         (Is there only 1? In other words, is the attacker the only one standing?)      
C2/15E7: D0 09        BNE $15F2      (If no, branch to probability 1)

;Probability 2
C2/15E9: 20 5A 4B     JSR $4B5A      (Choose a random number between 0 and 255)
C2/15EC: 29 40        CMP #$40       (Is the number > 64?) (3/4 chance of this being yes)
C2/15EE: F0 20        BEQ $1610      (If yes, branch to normal attack.)
C2/15F0: 80 07          BRA $15F9         (Branch to Desperation)

;Probability 1
C2/15F2: 20 5A 4B     JSR $4B5A      (Choose a random number between 0 and 255)
C2/15F5: 29 10        CMP #$10       (Is the number > 16?) (15/16 chance of this being yes)
C2/15F7: F0 17        BEQ $1610      (If yes, branch to normal attack.)

;Queue up Desperation
C2/15F9: 0C 2F 3F     TSB $3F2F      (Check if chraacter has used Desperation. If not, increment up one.)
C2/15FC: D0 12        BNE $1610      (If character has already used a Desperation, branch to normal attack)
C2/15FE: A9 XX          LDA XX         (Queue Up Desperation)
C2/1600: 85 B6          STA $B6         (Save Attack #)
C2/1602: A9 10        LDA #$10
C2/1604: 14 B0        TRB $B0        
C2/1606: 4C 14 17     JMP $1714
C2/1609: EA EA EA       NOP
C2/160C: EA EA          NOP
C2/160E: EA EA          NOP

I also sketched out logic for a much more complex routine, that would choose between a weak and a strong D.A. with different probability based on how many living characters there were. The stats were:
4 living characters: 1 in 32 chance of D.A., no chance of D.A. Lvl 2
3 living characters: 1 in 16 chance of D.A., 10% chance of D.A. Lvl 2
2 living characters: 1 in 8 chance of D.A., 25% chance of D.A. Lvl 2
1 living character: 1 in 4 chance of D.A., 50% chance of D.A. Lvl 2

However, that routine took 27 bytes more than what I had, and I didn't want to jump to another part of C2 to accomplish it. Let me know if you're interested in including that in your hack. The logic obviously hasn't been tested yet. There is room in that logic to add in more levels of D.A. too.


Projects:
FFVI: Divergent Paths (Completed) - a complete storyline and gameplay hack of FF6 that adds Leo as a playable character
  Find
Quote  



Forum Jump:

Users browsing this thread: 1 Guest(s)


Theme by Madsiur2017Custom Graphics by JamesWhite