image

Most people know that the Eye Gouge has the potential to un-mask an opponent, but I wanted to know how the game determines whether the mask gets ripped off or not.

The relevant function starts at 80147E34 in RAM.  This function is run near the end of a repeating move: when the Defender’s Wakeup Timer goes to 4 (i.e., just before they’re about to escape from the repeating move), this function executes. 

First the game checks whether the move has the ‘unmask’ attribute (for all practical purposes, there is only one move in the game that has this attribute: the Eye Gouge).

(These code blocks come from Freem’s excellent decomp GitHub):
/* 1424E4 80147E34 8E2402F0 */  lw    $a0, 0x2f0($s1) # get move damage pointer
/* 1424E8 80147E38 8C82001C */  lw    $v0, 0x1c($a0)
/* 1424EC 80147E3C 30424000 */  andi  $v0, $v0, 0x4000 // check if move can unmask
/* 1424F0 80147E40 10400027 */  beqz  $v0, .L3_80147EE0
/* 1424F4 80147E44 3C030800 */   lui   $v1, 0x800  // value used for masked wrestlers

If the answer is ‘yes’, next, the game checks whether the Defender (i.e., the person on the receiving end of the Eye Gouge) has a mask or not.  This is set in the wrestler’s parameters: just giving a mask to a wrestler in Edit mode is not enough to change the relevant parameter.

# check for mask
/* 1424F8 80147E48 8E0202C4 */  lw    $v0, 0x2c4($s0) # get pointer to unpacked params
/* 1424FC 80147E4C 8C420030 */  lw    $v0, 0x30($v0)
/* 142500 80147E50 00431024 */  and   $v0, $v0, $v1  // checking if wrestler has a mask
/* 142504 80147E54 10400022 */  beqz  $v0, .L3_80147EE0
/* 142508 80147E58 00000000 */   nop   

Assuming the answer is ‘yes’, the game checks the Defender’s status to determine whether the Defender has already been unmasked.

# check “mask ripped” flag 1
/* 14250C 80147E5C 92020075 */  lbu   $v0, 0x75($s0)
/* 142510 80147E60 30420001 */  andi  $v0, $v0, 1  // checking wrestler status: are they already unmasked?
/* 142514 80147E64 1440001E */  bnez  $v0, .L3_80147EE0
/* 142518 80147E68 00000000 */   nop   

Assuming they haven’t been unmasked yet, the game checks the Limb Stamina of the Defender’s Head: this needs to be at zero for there to be a chance of an unmasking.

/* 14252C 80147E7C 8082000C */  lb    $v0, 0xc($a0) // checking what Limb the move damages
/* 142530 80147E80 00021080 */  sll   $v0, $v0, 2 
/* 142534 80147E84 00501021 */  addu  $v0, $v0, $s0
/* 142538 80147E88 C44002A4 */  lwc1  $f0, 0x2a4($v0)  // loading Limb Stamina of that limb (head)
/* 14253C 80147E8C 44801000 */  mtc1  $zero, $f2 
/* 142540 80147E90 44801800 */  mtc1  $zero, $f3
/* 142544 80147E94 46000021 */  cvt.d.s $f0, $f0
/* 142548 80147E98 4622003E */  c.le.d $f0, $f2  // Checking if zero is less than current Limb Stamina
/* 14254C 80147E9C 00000000 */  nop   
/* 142550 80147EA0 00000000 */  nop   
/* 142554 80147EA4 4500000E */  bc1f  .L3_80147EE0
/* 142558 80147EA8 34620400 */   ori   $v0, $v1, 0x400 //adding 0x400 to P2’s status

If Head Stamina is at zero, the game performs a Random Number Generator “dice roll”.  The chances of success are “1 in x”, with x being calculated as follows:

x = (P2 Current Health divided by 10 (round down)) + (P2 Spirit divided by 10 (round)) + 1

For example, let’s say that P2’s Head Limb Stamina is 0, their Current Health is 45 and their Spirit is 38%.  

x = (45/10)+(38/10)+1
x = 4 + 3 + 1
x = 8

The chances of an unmasking in this example are 1 in 8 (or 12.5%).

The game only performs this RNG dice roll once per Eye Gouge: if you fail, you need to apply the Eye Gouge again to perform another dice roll.