Paper Mario
Intelligent Systems' 2000 role-playing game for the Nintendo 64, read through the pmret/papermario decompilation.
On this page
The atlas reads Paper Mario through the pmret team’s decompilation, C that builds the US ROM and three others from one tree. Names and comments quoted here are theirs, and the claims cite the code the US build compiles. Nothing has been measured in the game yet.
Mario’s attacks are action commands. The Jump takes one press of A in the last 4 updates1 of its count, and a press before then voids the window; a good press bounces Mario into a second stomp, and a Dodge Master badge widens the window1. The hammer is held left through its charge and let go inside a window of 11 updates2 at its end, which doubles the basic hammer’s damage from 1 to 22.
On defense, a fresh press of A in the last 3 updates3 before an enemy’s hit is a guard, unless A was pressed in the 10 updates before those; it takes 1 from Mario’s damage and stops a partner’s3. Mario’s own damage is a subtraction: the move’s damage with its badges and charges, capped at 994, less the target’s defense4.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Action command | Timed press | the Jump takes one press of A in the last 4 updates of its count, and a good press earns a second stomp; a press before the window voids it |
| Action command | Hold and release | the hammer is held left and let go in an 11-update window at the end of a 51-update charge; a good release doubles the basic hammer's damage |
| Timed guard | Reduce · Mario | a fresh press of A in the 3 updates before a hit takes 1 off it, unless A was pressed in the 10 before those |
| Timed guard | Negate · partners | a partner's guard, read the same way, stops the hit's damage |
| Damage formula | Attack minus defense, no roll | Mario's damage, after badges and charges and a cap of 99, less the target's defense, floored at 0 |
Every claim about this game, by concept (4)
References
- ^ abIn the US version of Paper Mario, the jump action command (
action_command_jump) is one press of A timed to the stomp, and runs only once Mario has learned action commands (notAC_MODE_NOT_LEARNED). The basic Jump (EVS_UseMove_Basic, the script for menu level 0) computes the jump's length as(distance - 20) / 10.588 + 15from Mario to the target, gives that count toPlayerBasicJumpToGoal, and passes the same count to the command asprepareTime, at difficultyAC_DIFFICULTY_STANDARD(index 3 of 8). Each update the command countsprepareTimedown until it is no more than the window size,actionCmdTableJump[difficulty], which is 4 at standard in a table running 7 down to 0; it then sets the window timer to that size and counts it down to 0. A press of A whileprepareTimeis still counting setswrongButtonPressed, and the window then takes no press; the update in which the count reaches the window size runs that early-press test before falling through into the window, so a press there is early too, and a press counts only while the timer runs from 3 to 0, 4 updates at standard (computed), the last of the command's updates. When the partner isn't acting,adjust_action_command_difficultylowers the difficulty index by 3 for each Dodge Master badge equipped, clamped at 0, so one badge widens the window to 7 updates (computed). A good press makes the basic Jump's first stomp a nice hit, and the script then bounces Mario into a second stomp; each stomp passes a damage of 1. A missed press ends the move after the first.Codepmret/papermariorevisedHow we know
28Difficulty1D actionCmdTableJump = { 7, 6, 5, 4, 3, 2, 1, 0 };src/battle/action_cmd.c line 28 at 1104f1f · upstream ↗ 41enum ActionCommandDifficulty { 42 AC_DIFFICULTY_EASIEST, 43 AC_DIFFICULTY_VERY_EASY, 44 AC_DIFFICULTY_EASY, 45 AC_DIFFICULTY_STANDARD,
src/battle/action_cmd.h lines 41–45 at 1104f1f · upstream ↗ 101s32 adjust_action_command_difficulty(s32 difficultyLevel) { 102 if (!(gBattleStatus.flags1 & BS_FLAGS1_PARTNER_ACTING)) { 103 difficultyLevel -= is_ability_active(ABILITY_DODGE_MASTER) * 3; ⋮ 106 if (difficultyLevel < AC_DIFFICULTY_EASIEST) { 107 difficultyLevel = AC_DIFFICULTY_EASIEST;
src/battle/action_cmd.c lines 101–114 at 1104f1f · upstream ↗ 1578s32 is_ability_active(s32 ability) { ⋮ 1598 for (i = 0; i < ARRAY_COUNT(playerData->equippedBadges); i++) { ⋮ 1607 case ABILITY_DODGE_MASTER: 1608 if (badgeMoveID == MOVE_DODGE_MASTER) { 1609 ret++;
src/inventory.c lines 1578–1610 at 1104f1f · upstream ↗ 57 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) { 58 battleStatus->actionQuality = 0; 59 return ApiStatus_DONE2; ⋮ 63 acs->prepareTime = evt_get_variable(script, *args++); 64 acs->difficulty = evt_get_variable(script, *args++); 65 acs->difficulty = adjust_action_command_difficulty(acs->difficulty);
src/battle/action_cmd/jump.c lines 57–65 at 1104f1f · upstream ↗ 130 successWindow = battleStatus->actionCmdDifficultyTable[acs->difficulty]; ⋮ 135 if ((battleStatus->curButtonsPressed & BUTTON_A) && !acs->autoSucceed) { 136 acs->wrongButtonPressed = true; 137 battleStatus->actionResult = ACTION_RESULT_EARLY; ⋮ 140 if ((acs->prepareTime - successWindow) > 0) { 141 acs->prepareTime--; 142 break; ⋮ 145 acs->stateTimer = battleStatus->actionCmdDifficultyTable[acs->difficulty]; ⋮ 155 if (acs->stateTimer == 0) { 156 break; ⋮ 168 if (battleStatus->actionQuality < 0) { 169 if (((battleStatus->curButtonsPressed & BUTTON_A) && !acs->wrongButtonPressed) || acs->autoSucceed) { ⋮
src/battle/action_cmd/jump.c lines 130–188 at 1104f1f · upstream ↗ 75EvtScript N(EVS_JumpSupport_CalcJumpTime) = { ⋮ 85 Sub(LVar6, 20) 86 DivF(LVar6, Float(10.588)) 87 AddF(LVar6, 15) 88 Set(LVarA, LVar6)
src/battle/common/move/JumpSupport.inc.c lines 75–88 at 1104f1f · upstream ↗ 309EvtScript N(EVS_JumpSupport_ApproachAndJump) = { ⋮ 313 ExecWait(N(EVS_JumpSupport_CalcJumpTime)) 314 Call(action_command_jump_start, LVarA, AC_DIFFICULTY_STANDARD) ⋮ 318 Call(PlayerBasicJumpToGoal, LVarA, PLAYER_BASIC_JUMP_0)
src/battle/common/move/JumpSupport.inc.c lines 309–318 at 1104f1f · upstream ↗ 40 Call(GetMenuSelection, LVar0, LVar1, LVar2) 41 Switch(LVar1) 42 CaseEq(0) 43 ExecWait(N(EVS_UseMove_Basic))
src/battle/move/jump/attack.c lines 40–43 at 1104f1f · upstream ↗ 75 Call(GetPlayerActionQuality, LVar0) 76 Switch(LVar0) 77 CaseGt(false) ⋮ 79 Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_JUMP, 0, 0, 1, BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_NICE_HIT) 80 CaseDefault ⋮ 82 Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_JUMP, 0, 0, 1, BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_TRIGGER_EVENTS) 83 EndSwitch 84 Switch(LVar0) 85 CaseOrEq(HIT_RESULT_HIT) 86 CaseOrEq(HIT_RESULT_NO_DAMAGE) 87 // missed action command, end the script here 88 ExecWait(N(EVS_JumpSupport_G)) ⋮
src/battle/move/jump/attack.c lines 75–95 at 1104f1f · upstream ↗ 107 Call(action_command_jump_start, 24, AC_DIFFICULTY_STANDARD) ⋮ 110 Call(PlayerBasicJumpToGoal, 24, PLAYER_BASIC_JUMP_3) 111 Wait(1) ⋮ 113 Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_JUMP, 0, 0, 1, BS_FLAGS1_TRIGGER_EVENTS | BS_FLAGS1_NICE_HIT | BS_FLAGS1_NO_RATING)
src/battle/move/jump/attack.c lines 107–113 at 1104f1f · upstream ↗ 1545 battleStatus->curAttackElement = *args++; 1546 battleStatus->curAttackEventSuppression = *args++; 1547 battleStatus->curAttackStatus = *args++; 1548 battleStatus->curAttackDamage = evt_get_variable(script, *args++);
src/battle/dmg_player.c lines 1545–1548 at 1104f1f · upstream ↗ 1028 if (gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT)) { 1029 if (hitResult == HIT_RESULT_HIT) { 1030 hitResult = HIT_RESULT_NICE;
src/battle/dmg_player.c lines 1028–1031 at 1104f1f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abIn the US version of Paper Mario, the hammer action command (
action_command_hammer) is a hold and release of the stick to the left. When action commands are learned and the Berserker badge isn't equipped, the hammer script (outside the tutorial and auto-success) waits up to 45 updates for the stick to be held left, then starts the command with a duration of 51 (45 plus 6) atAC_DIFFICULTY_STANDARD, whose table valueactionCmdTableHammer[3]is 8 without a Dodge Master badge. The command's timer counts up from 0 each update. Its look-back count is the table value minus the updates left (duration - stateTimer) plus 3, at least 0: while it is 0, a stick not held left fails the command at once (ACTION_RESULT_EARLY), and once it is above 0 the command succeeds if any of that many latest entries of the held-button buffer has the stick not held left. That opens the release window at timer 41 and keeps it through timer 51, 11 updates (computed); the command marks ready (HES_TimingReadyand its sound) at timer 42, one update after the window opens (computed). A stick still held when the timer passes 51 fails. With the basic hammer, a success passes a damage of 2 and a failure 1 (comments in the script call them "good input dmg" and "bad input dmg").Codepmret/papermarioHow we know
29Difficulty1D actionCmdTableHammer = { 11, 10, 9, 8, 7, 6, 5, 4 };src/battle/action_cmd.c line 29 at 1104f1f · upstream ↗ 13API_CALLABLE(N(IsBerserkerEquipped)) { 14 script->varTable[0] = gBattleStatus.actionCommandMode; 15 script->varTable[1] = 15; ⋮ 17 if (is_ability_active(ABILITY_BERSERKER)) { 18 script->varTable[0] = AC_MODE_NOT_LEARNED;
src/battle/common/move/HammerSupport.inc.c lines 13–23 at 1104f1f · upstream ↗ 257 Call(N(IsBerserkerEquipped)) 258 IfNe(LVar0, false) ⋮ 264 Loop(45) 265 Wait(1) 266 Call(CheckButtonDown, BUTTON_STICK_LEFT, LVar0) 267 IfNe(LVar0, false) 268 BreakLoop ⋮ 273 Add(LVarD, 6) 274 Call(action_command_hammer_start, 0, LVarD, AC_DIFFICULTY_STANDARD)
src/battle/common/move/HammerSupport.inc.c lines 257–274 at 1104f1f · upstream ↗ 17 CaseEq(0) 18 Set(LVarD, 45)// action command duration 19 Set(LVarE, 1) // bad input dmg 20 Set(LVarF, 2) // good input dmg 21 ExecWait(N(EVS_UseMove_Impl))
src/battle/move/hammer/attack.c lines 17–21 at 1104f1f · upstream ↗ 95 Call(GetPlayerActionQuality, LVar0) 96 Switch(LVar0) 97 CaseGt(false) ⋮ 107 Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_SMASH, SUPPRESS_EVENTS_HAMMER, 0, LVarF, BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_TRIGGER_EVENTS | BS_FLAGS1_NICE_HIT) 108 CaseDefault ⋮ 118 Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_SMASH, SUPPRESS_EVENTS_HAMMER, 0, LVarE, BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_TRIGGER_EVENTS)
src/battle/move/hammer/attack.c lines 95–118 at 1104f1f · upstream ↗ 99 acs->prepareTime = evt_get_variable(script, *args++); 100 acs->duration = evt_get_variable(script, *args++); 101 acs->difficulty = evt_get_variable(script, *args++); 102 acs->difficulty = adjust_action_command_difficulty(acs->difficulty);
src/battle/action_cmd/hammer.c lines 99–102 at 1104f1f · upstream ↗ 207 if (acs->prepareTime != 0) { 208 acs->prepareTime--; 209 return; ⋮ 212 acs->stateTimer = 0; ⋮ 216 acs->state = AC_STATE_ACTIVE;
src/battle/action_cmd/hammer.c lines 207–216 at 1104f1f · upstream ↗ 256 if (acs->stateTimer == (-(inputWindow + 1) + acs->duration)) { 257 battleStatus->actionProgress = 3; 258 hud_element_set_script(acs->hudElemIDs[HIDX_WAIT], &HES_TimingReady);
src/battle/action_cmd/hammer.c lines 256–258 at 1104f1f · upstream ↗ 268 inputWindow = battleStatus->actionCmdDifficultyTable[acs->difficulty] - (acs->duration - acs->stateTimer) + 3; 269 if (inputWindow < 0) { 270 inputWindow = 0; ⋮ 273 // has the stick been release too early? 274 if (!(battleStatus->curButtonsDown & BUTTON_STICK_LEFT) 275 && inputWindow == 0 276 && acs->autoSucceed == 0 277 && battleStatus->actionCommandMode < AC_MODE_TUTORIAL 278 ) { 279 battleStatus->actionQuality = AC_QUALITY_FAILED; 280 battleStatus->actionResult = ACTION_RESULT_EARLY; ⋮ 287 bufferPos -= inputWindow; ⋮
src/battle/action_cmd/hammer.c lines 268–303 at 1104f1f · upstream ↗ 308 if (battleStatus->actionCommandMode < AC_MODE_TUTORIAL || acs->stateTimer != acs->duration) { 309 acs->stateTimer++; 310 if (acs->duration < acs->stateTimer) { 311 if (battleStatus->actionQuality == 0) { 312 battleStatus->actionQuality = AC_QUALITY_FAILED;
src/battle/action_cmd/hammer.c lines 308–313 at 1104f1f · upstream ↗ 292 battleStatus->pushInputBuffer[battleStatus->inputBufferPos] = battleStatus->curButtonsPressed; 293 battleStatus->holdInputBuffer[battleStatus->inputBufferPos] = battleStatus->curButtonsDown; ⋮ 295 battleStatus->inputBufferPos++; 296 if (battleStatus->inputBufferPos >= ARRAY_COUNT(battleStatus->pushInputBuffer)) { 297 battleStatus->inputBufferPos = 0;
src/battle/16C8E0.c lines 292–298 at 1104f1f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abIn the US version of Paper Mario, an enemy's hit on Mario is guarded when A was pressed shortly before it lands.
calc_enemy_damage_targetcallscheck_block_input(BUTTON_A)when Mario's debuff is none or one numbered at or afterSTATUS_KEY_POISON(so not dizzy, paralyzed, asleep, frozen, or stopped), he isn't stone, and the attack isn'tDAMAGE_TYPE_UNBLOCKABLE; with the Berserker badge,rand_int(1)decides instead. The check returns false before action commands are learned and in demo battles, and returns a guard with no press in the tutorial battle while the mode isAC_MODE_TUTORIAL_BLOCK. It guards if a fresh press of A is in the last 3 entries of the battle's pressed-button buffer, whichbtl_updatewrites once per battle update (5 entries with a Dodge Master badge, when the partner isn't acting), unless A was also pressed in the 10 entries before those. A guard takes 1 from Mario's damage, plus 1 for each Damage Dodge badge equipped. A guard by the partner, checked the same way when the partner isn't stone or knocked out, sets the damage to 0.Codepmret/papermariorevisedHow we know
551 if (battleStatus->actionCommandMode == AC_MODE_TUTORIAL_BLOCK && (battleStatus->flags1 & BS_FLAGS1_TUTORIAL_BATTLE)) { 552 battleStatus->blockResult = BLOCK_RESULT_SUCCESS; 553 return true;
src/battle/action_cmd.c lines 551–553 at 1104f1f · upstream ↗ 556 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED || (gGameStatusPtr->demoBattleFlags & DEMO_BTL_FLAG_ENABLED)) { 557 return false; ⋮ 567 block = false; 568 blockWindow = 3; 569 mashWindow = 10; ⋮ 571 if (!(gBattleStatus.flags1 & BS_FLAGS1_PARTNER_ACTING) && is_ability_active(ABILITY_DODGE_MASTER)) { 572 blockWindow = 5; ⋮ 575 // Pre-window mashing check 576 bufferPos = battleStatus->inputBufferPos; 577 bufferPos -= mashWindow + blockWindow; ⋮ 582 for (i = 0; i < mashWindow; i++) { ⋮ 587 if (battleStatus->pushInputBuffer[bufferPos] & buttonMask) { ⋮
src/battle/action_cmd.c lines 556–616 at 1104f1f · upstream ↗ 292 battleStatus->pushInputBuffer[battleStatus->inputBufferPos] = battleStatus->curButtonsPressed; 293 battleStatus->holdInputBuffer[battleStatus->inputBufferPos] = battleStatus->curButtonsDown; ⋮ 295 battleStatus->inputBufferPos++;
src/battle/16C8E0.c lines 292–295 at 1104f1f · upstream ↗ 231HitResult calc_enemy_damage_target(Actor* attacker) {src/battle/1A5830.c line 231 at 1104f1f · upstream ↗ 430 // apply damage mitigation from blocking ⋮ 432 switch (actorClass) { 433 case ACTOR_CLASS_PLAYER: ⋮ 435 if ((target->debuff == 0 || target->debuff >= STATUS_KEY_POISON) 436 && (target->stoneStatus == 0) 437 && !(battleStatus->curAttackElement & DAMAGE_TYPE_UNBLOCKABLE) 438 ) { ⋮ 441 if (player_team_is_ability_active(target, ABILITY_BERSERKER)) { 442 blocked = rand_int(1); 443 } else { 444 blocked = check_block_input(BUTTON_A); ⋮ 447 if (blocked) { ⋮
src/battle/1A5830.c lines 430–466 at 1104f1f · upstream ↗ 2808 STATUS_KEY_DIZZY = 0x00000004, 2809 STATUS_KEY_PARALYZE = 0x00000005, 2810 STATUS_KEY_SLEEP = 0x00000006, 2811 STATUS_KEY_FROZEN = 0x00000007, 2812 STATUS_KEY_STOP = 0x00000008, 2813 STATUS_KEY_POISON = 0x00000009,
include/enums.h lines 2808–2813 at 1104f1f · upstream ↗ 2870s32 player_team_is_ability_active(Actor* actor, s32 ability) { ⋮ 2875 case ACTOR_CLASS_PLAYER: 2876 if (!(gBattleStatus.flags2 & BS_FLAGS2_PEACH_BATTLE)) { 2877 hasAbility = is_ability_active(ability);
src/battle/190B20.c lines 2870–2878 at 1104f1f · upstream ↗ 1881 case ABILITY_DAMAGE_DODGE: 1882 if (badgeMoveID == MOVE_DAMAGE_DODGE) { 1883 ret++;
src/inventory.c lines 1881–1883 at 1104f1f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abIn the US version of Paper Mario,
calc_player_damage_enemyworks out Mario's damage to an enemy by subtraction. A forced immune hit (BS_FLAGS1_FORCE_IMMUNE_HIT) skips the calculation, and some hits return before it: an illusory, transparent, or buried target (buried unless the attack is a quake) is missed; a stone target takes nothing; a jump on a spiky top without Spike Shield, a contact attack on an explode-on-contact part, on a fiery part without Fire Shield or Ice Power, or on the alternate spiky flag without Spike Shield backfires; and a fire attack that sets off a part that explodes on fire returns before damage. Otherwise it starts from the move's damage (curAttackDamage, which the move script passes), adds Power Plus badges (count_power_plus), and adds or takes fixed amounts for Merlee, the jump and hammer charges, other badges, and statuses (L456-L535). A missed All or Nothing sets the damage to 0, and outside the Japanese build the defense too; a shrunk Mario's damage is halved, but stays at least 1; a blast on a part that explodes on ignition sets the damage to the target's HP and the defense to 0; andDAMAGE_TYPE_STATUS_ALWAYS_HITSsets both to 0. The total is capped at 99, and the target's defense is then subtracted:get_defense, plus the defense boost unless the attack ignores defense, plus 127 for a part flagged extreme defense, or 0 when the total is below 0. A result below 0 becomes 0, and a Power Bounce then adds its counter, keeping a hit above 0 at least 1. The function's onerand_intcall, theDAMAGE_TYPE_FEARscare-away test, runs after the damage is taken off the target's HP.Codepmret/papermariorevisedHow we know
240HitResult calc_player_damage_enemy(void) {src/battle/dmg_player.c line 240 at 1104f1f · upstream ↗ 292 if (gBattleStatus.flags1 & BS_FLAGS1_FORCE_IMMUNE_HIT) { 293 hitResult = HIT_RESULT_NO_DAMAGE; ⋮ 302 if (targetPart->eventFlags & ACTOR_EVENT_FLAG_ILLUSORY 303 || target->transparentStatus == STATUS_KEY_TRANSPARENT 304 || (targetPart->eventFlags & ACTOR_EVENT_FLAG_BURIED && !(battleStatus->curAttackElement & DAMAGE_TYPE_QUAKE)) 305 ) { 306 return HIT_RESULT_MISS; ⋮ 309 if (target->stoneStatus == STATUS_KEY_STONE) { ⋮ 314 return HIT_RESULT_NICE; ⋮ 325 if ((battleStatus->curAttackElement & DAMAGE_TYPE_JUMP) 326 && (targetPart->eventFlags & ACTOR_EVENT_FLAG_SPIKY_TOP) 327 && !player_team_is_ability_active(player, ABILITY_SPIKE_SHIELD)) ⋮
src/battle/dmg_player.c lines 292–380 at 1104f1f · upstream ↗ 443 targetDefense = get_defense(target, targetPart->defenseTable, battleStatus->curAttackElement); ⋮ 445 if (!(battleStatus->curAttackElement & DAMAGE_TYPE_IGNORE_DEFENSE)) { 446 targetDefense += target->defenseBoost; ⋮ 449 if (targetPart->eventFlags & ACTOR_EVENT_FLAG_EXTREME_DEFENSE) { 450 targetDefense += 127; ⋮ 453 currentAttackDamage = battleStatus->curAttackDamage; 454 currentAttackDamage += count_power_plus(battleStatus->curAttackElement); ⋮ 456 if (battleStatus->merleeAttackBoost > 0 ⋮ 458 ) { 459 currentAttackDamage += battleStatus->merleeAttackBoost;
src/battle/dmg_player.c lines 443–459 at 1104f1f · upstream ↗ 462 if (battleStatus->jumpCharge && battleStatus->curAttackElement & DAMAGE_TYPE_JUMP) { 463 currentAttackDamage += battleStatus->jumpCharge; ⋮ 467 if (battleStatus->hammerCharge && battleStatus->curAttackElement & (DAMAGE_TYPE_QUAKE_HAMMER | DAMAGE_TYPE_THROW | DAMAGE_TYPE_SMASH)) { 468 currentAttackDamage += battleStatus->hammerCharge; ⋮ 473 currentAttackDamage += 2; ⋮ 476 if (player_team_is_ability_active(player, ABILITY_BERSERKER)) { 477 currentAttackDamage += 2; ⋮ 480 if (player_team_is_ability_active(player, ABILITY_P_UP_D_DOWN)) { 481 currentAttackDamage++; ⋮ 484 if (player_team_is_ability_active(player, ABILITY_P_DOWN_D_UP)) { 485 currentAttackDamage--; ⋮ 488 if (battleStatus->turboChargeTurnsLeft != 0) { ⋮
src/battle/dmg_player.c lines 462–492 at 1104f1f · upstream ↗ 537 if (!(gBattleStatus.flags2 & BS_FLAGS2_IS_FIRST_STRIKE) 538 && player_team_is_ability_active(player, ABILITY_ALL_OR_NOTHING) 539 ) { 540 currentAttackDamage++; ⋮ 542 if (!(gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT))) { 543 missedAllOrNothing = true; 544 currentAttackDamage = 0; 545#if !VERSION_JP 546 targetDefense = 0; 547#endif ⋮ 555 if (player->debuff == STATUS_KEY_SHRINK) { 556 if (currentAttackDamage > 0) { ⋮
src/battle/dmg_player.c lines 536–576 at 1104f1f · upstream ↗ 578 if (currentAttackDamage > 99) { 579 currentAttackDamage = 99; ⋮ 582 if (currentAttackDamage < 0) { 583 targetDefense = 0; ⋮ 586 target->hpChangeCounter = 0; 587 currentAttackDamage -= targetDefense; ⋮ 589 if (currentAttackDamage < 0) { 590 currentAttackDamage = 0; ⋮ 593 if (battleStatus->curAttackElement & DAMAGE_TYPE_POWER_BOUNCE && currentAttackDamage > 0) { 594 currentAttackDamage += battleStatus->powerBounceCounter; ⋮ 596 if (currentAttackDamage < 1) { 597 currentAttackDamage = 1;
src/battle/dmg_player.c lines 578–598 at 1104f1f · upstream ↗ 630 target->curHP -= currentAttackDamage;src/battle/dmg_player.c line 630 at 1104f1f · upstream ↗ 672 if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS) { 673 if (battleStatus->curAttackElement & DAMAGE_TYPE_FEAR 674 && rand_int(99) < (target->actorBlueprint->escapeChance * battleStatus->statusChance) / 100
src/battle/dmg_player.c lines 672–674 at 1104f1f · upstream ↗ 1548 battleStatus->curAttackDamage = evt_get_variable(script, *args++);src/battle/dmg_player.c line 1548 at 1104f1f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
Sources
Code
- pmret and papermario contributors. 2026. “papermario: a decompilation of Paper Mario (pmret/papermario).” Commit 1104f1f. pmret/papermario @ 1104f1f · licence, all uses