• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

Completed Throw Hitstun Bug Fix

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
423
Sycorax Sycorax Interesting glitch...

Using the Community Symbols Map, I think I can see exactly where it’s happening--but I don’t know enough about the hard-working blrl @ 80390dfc of “wP_RunObjectFrameFunctions” to know why it’s happening.

The culprit appears to be “8006a360 ac_PlayerThinkAgain” -- which gets called (as part of a loop involving the blrl instruction at the above address) each frame for each player entity. It does a whole slew of things both known and unknown--including handling animation interrupts, updating hitstun/damage, and updating action state frames.

It updates action state frames with a call to “8006eba4 ac_AS_AnimationFrameUpdate&More” which is simply a collection of calls to the following 4 functions:
  • 8006e9b4 $?_relatedTo_AS_Frames <-- Action State frame count updates here
  • 80073240 $!_SAevent_Parse_Player <-- Subaction Event frame count updates here
  • 800707b0 $?_relatedTo_AS_Frames_2 (unknown function)
  • 800db500 $?_relatedTo_AS_Frames_3 (unknown function)

By following the action state transition (via breakpoint at 800693ac ActionStateChange) we can see the P2 transition into frame 0 of DamageFlyTop as a part of the damage/hitstun update (@ 8008e25c)

This update is a part of the normal playerThinkAgain routine, so further along it hits the frame update and increments to frame 1, like normal. The playerThinkAgain function finishes and returns to the objectFrameFunctions loop, where it should (to my knowledge) proceed to the next frame before running playerThinkAgain another time for this player.

Instead--for player 2/2--the loop seems to iterate with playerThinkAgain and call it 2 times in a row. This is what appears to be causing the frame to increment up to frame 2.

---

Without knowing more about why this happens, I’m not sure how to safely go about changing this behavior. The only idea I have would possibly have unknown effects on frame updates by conditionally skipping the first call in that AnimationFrameUpdate function with an "update flag" somehow fashioned for each player.

Anyone familiar with any of these functions, or got any ideas/insights?
 

Sycorax

Smash Ace
Joined
Jul 7, 2014
Messages
502
Location
Atlanta, GA
Sycorax Sycorax Interesting glitch...

Using the Community Symbols Map, I think I can see exactly where it’s happening--but I don’t know enough about the hard-working blrl @ 80390dfc of “wP_RunObjectFrameFunctions” to know why it’s happening.

The culprit appears to be “8006a360 ac_PlayerThinkAgain” -- which gets called (as part of a loop involving the blrl instruction at the above address) each frame for each player entity. It does a whole slew of things both known and unknown--including handling animation interrupts, updating hitstun/damage, and updating action state frames.

It updates action state frames with a call to “8006eba4 ac_AS_AnimationFrameUpdate&More” which is simply a collection of calls to the following 4 functions:
  • 8006e9b4 $?_relatedTo_AS_Frames <-- Action State frame count updates here
  • 80073240 $!_SAevent_Parse_Player <-- Subaction Event frame count updates here
  • 800707b0 $?_relatedTo_AS_Frames_2 (unknown function)
  • 800db500 $?_relatedTo_AS_Frames_3 (unknown function)

By following the action state transition (via breakpoint at 800693ac ActionStateChange) we can see the P2 transition into frame 0 of DamageFlyTop as a part of the damage/hitstun update (@ 8008e25c)

This update is a part of the normal playerThinkAgain routine, so further along it hits the frame update and increments to frame 1, like normal. The playerThinkAgain function finishes and returns to the objectFrameFunctions loop, where it should (to my knowledge) proceed to the next frame before running playerThinkAgain another time for this player.

Instead--for player 2/2--the loop seems to iterate with playerThinkAgain and call it 2 times in a row. This is what appears to be causing the frame to increment up to frame 2.

---

Without knowing more about why this happens, I’m not sure how to safely go about changing this behavior. The only idea I have would possibly have unknown effects on frame updates by conditionally skipping the first call in that AnimationFrameUpdate function with an "update flag" somehow fashioned for each player.

Anyone familiar with any of these functions, or got any ideas/insights?
I have no idea what any of that means :080: but I eagerly await other people's responses :039:
 

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
Sycorax Sycorax
This update is a part of the normal playerThinkAgain routine, so further along it hits the frame update and increments to frame 1, like normal. The playerThinkAgain function finishes and returns to the objectFrameFunctions loop, where it should (to my knowledge) proceed to the next frame before running playerThinkAgain another time for this player.
It's running the PlayerThinkAgain function "again" for this player, because when the thrown player's action state changes, code execution is in the middle of the PlayerThinkAgain for the player doing the throwing. So then PlayerThinkAgain gets ran for the next player in line, and their frame gets updated again.
Code:
Throw Bug Fix v2 (1.02) [Achilles]
C208E250 0000000D
38C00000 8118002C
80E818C4 8928000C
7C093800 41800050
80E80010 2C0700EF
41800044 2C0700F3
4181003C 3CE03F80
90E20000 C0820000
C0A82340 FC84282A
D0882340 3CE08006
60E793AC 7CE803A6
4E800021 3CE08008
60E7E260 7CE803A6
4E800020 00000000
Code:
ASM
inject @ 8008e250

li r6,0 # default code line
lwz r8,0x2c(r24) # load internal offset for thrown player
lwz r7, 0x18c4(r8) # load slot of last damage source
lbz r9,0xc(r8) # load thrown player's port
cmpw r9,r7 # skip if thrown player's port is less than thrower's
blt- DEFAULT
lwz r7,0x10(r8) # load action state of thrown player
cmpwi r7,0xef # is player in ThrownF/B/Hi/Lw/LwWomen
blt- DEFAULT
cmpwi r7,0xf3
bgt- DEFAULT
lis r7,0x3f80 # load 1.0 into floating point register
stw r7,0(r2)
lfs f4,0(r2)
lfs f5,0x2340(r8) # load frames of hitstun left for thrown player
fadd    f4,f4,f5 # add 1 frame of hitstun
stfs f4,0x2340(r8) # store new frames of hitstun left for thrown player

lis r7,0x8006
ori r7,r7,0x93ac # branch to ActionStateChange
mtlr r7
blrl
lis r7,0x8008
ori r7,r7,0xe260 # continue with code execution, skipping the AnimationUpdate function
mtlr r7
blr

DEFAULT:
Thoroughly untested aside from this picture. Yellow on the right is frames of hitstun left.
Capture.PNG
 
Last edited:

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
423
It's running the PlayerThinkAgain function "again" for this player, because when the thrown player's action state changes, code execution is in the middle of the PlayerThinkAgain for the player doing the throwing. So then PlayerThinkAgain gets ran for the next player in line, and their frame gets updated again.
Oh, lol. I completely missed that I was looking at the function twice from 2 different player contexts. That makes a LOT more sense. Nice work~

I just tested your code briefly with p1 and p2, and p2 now functions correctly. P1 however seems to skip the animation update, causing the new state to start at frame 0--recreating the priority.

I believe this is because r24 and r29 come from the same player entity--so the comparison doesn't appear to consider the throwing player as intended.

Here are sample internal player data offsets during breakpoints at the end of the playerThinkAgain routine (containing the action state change) and the following global frame tick:
 
Last edited:

Achilles1515

Smash Master
Joined
Jun 18, 2007
Messages
3,211
Location
Cincinnati / Columbus OH
Oh, lol. I completely missed that I was looking at the function twice from 2 different player contexts. That makes a LOT more sense. Nice work~

I just tested your code briefly with p1 and p2, and p2 now functions correctly. P1 however seems to skip the animation update, causing the new state to start at frame 0--recreating the priority.

I believe this is because r24 and r29 come from the same player entity--so the comparison doesn't appear to consider the throwing player as intended.

Here are sample internal player data offsets during breakpoints at the end of the playerThinkAgain routine (containing the action state change) and the following global frame tick:
Thanks for pointing that out. I glossed over r29 and made assumptions about it. Try the updated code in my above post.
 

Punkline

Dr. Frankenstack
Premium
Joined
May 15, 2015
Messages
423
Thanks for pointing that out. I glossed over r29 and made assumptions about it. Try the updated code in my above post.
Both players are looking good now!

This glitch and your code are very informative.

I took a closer look last night at the reason for the strange player context of that action state change, and it appears to be part of the animation interrupt for the thrower--changing the state of the thrown player (like you said.)

I feel like a similarly placed action state change might also be responsible for the "soulstunner/soulbreaker" mewtwo grab glitch--which can be reproduced by unnaturally interrupting any throw from any character before releasing the "thrown" player.

Edit - this seems like it may be the case. They're both animation interrupts that (asynchronously) apply new states to 2 players instead of just the owner of the interrupt:
 
Last edited:

DRGN

Technowizard
Moderator
Premium
Joined
Aug 20, 2005
Messages
2,175
Location
Sacramento, CA
Neat.

Looks like a nice little detail to add to MCM's default library. I'll include a link to here in the description as well.
 

The Cape

Smash Master
Joined
May 16, 2004
Messages
4,478
Location
Carlisle, PA
So I was playing with this and it appears the Ganondorf's UpB when grabbing grounded opponents glitches. I plan to test more with it, but I think it's this code.

More tests have determined it is this code when using a lower input for characters. I looked at the Looping hitboxes in Debug and it appears to skip certain time frames on that. I have manipulated the duration of time the move holds the opponent and the timing of the loops, as well as the damage and KB of the looping attacks, but no luck.

It appears to be the holding loop against grounded opponents only
 
Last edited:

The Cape

Smash Master
Joined
May 16, 2004
Messages
4,478
Location
Carlisle, PA
So I found that by adding a hitbox that does no damage and launches the opponent into the air fixes the issue. The problem with this is it does not deal well with shields, nor can it be steadily repeated. This makes me think that the opponent being on the ground (into the looping hitboxes) is the issue.

Tried swapping out the animation with the airborne one as well, but that does nothing. It appears to matter for the opponent being on stage or in the air only.


Thought with this change as well. Is it possible to make grabs colliding clank or just negating each other?
 
Last edited:

The Cape

Smash Master
Joined
May 16, 2004
Messages
4,478
Location
Carlisle, PA
It wont let me edit my post above, but this issue appears to be known and with the code for removing grab infinites.
 
Top Bottom