Claim set · data/claims/paper-mario.yaml

Paper Mario (the pmret/papermario decompilation)

Game: Paper Mario.

In 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 (not AC_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 + 15 from Mario to the target, gives that count to PlayerBasicJumpToGoal, and passes the same count to the command as prepareTime, at difficulty AC_DIFFICULTY_STANDARD (index 3 of 8). Each update the command counts prepareTime down 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 while prepareTime is still counting sets wrongButtonPressed, 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_difficulty lowers 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. paper-mario/jump-command

About: Paper Mario Action command

Value: 4 updates in which a press counts (computed from the table value 4 at standard difficulty)

Codepapermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd.c#L28Difficulty1D actionCmdTableJump = { 7, 6, 5, 4, 3, 2, 1, 0 };papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd.h#L41-L45enum ActionCommandDifficulty { AC_DIFFICULTY_EASIEST, AC_DIFFICULTY_VERY_EASY, AC_DIFFICULTY_EASY, AC_DIFFICULTY_STANDARD,papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd.c#L101-L114s32 adjust_action_command_difficulty(s32 difficultyLevel) { if (!(gBattleStatus.flags1 & BS_FLAGS1_PARTNER_ACTING)) { difficultyLevel -= is_ability_active(ABILITY_DODGE_MASTER) * 3; } … if (difficultyLevel < AC_DIFFICULTY_EASIEST) { difficultyLevel = AC_DIFFICULTY_EASIEST;papermario: a decompilation of Paper Mario (pmret/papermario) · src/inventory.c#L1578-L1610s32 is_ability_active(s32 ability) { … for (i = 0; i < ARRAY_COUNT(playerData->equippedBadges); i++) { … case ABILITY_DODGE_MASTER: if (badgeMoveID == MOVE_DODGE_MASTER) { ret++;papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd/jump.c#L57-L65if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) { battleStatus->actionQuality = 0; return ApiStatus_DONE2; } … acs->prepareTime = evt_get_variable(script, *args++); acs->difficulty = evt_get_variable(script, *args++); acs->difficulty = adjust_action_command_difficulty(acs->difficulty);papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd/jump.c#L130-L188successWindow = battleStatus->actionCmdDifficultyTable[acs->difficulty]; … if ((battleStatus->curButtonsPressed & BUTTON_A) && !acs->autoSucceed) { acs->wrongButtonPressed = true; battleStatus->actionResult = ACTION_RESULT_EARLY; } … if ((acs->prepareTime - successWindow) > 0) { acs->prepareTime--; break; } acs->stateTimer = battleStatus->actionCmdDifficultyTable[acs->difficulty]; …papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/common/move/JumpSupport.inc.c#L75-L88EvtScript N(EVS_JumpSupport_CalcJumpTime) = { … Sub(LVar6, 20) DivF(LVar6, Float(10.588)) AddF(LVar6, 15) Set(LVarA, LVar6)papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/common/move/JumpSupport.inc.c#L309-L318EvtScript N(EVS_JumpSupport_ApproachAndJump) = { … ExecWait(N(EVS_JumpSupport_CalcJumpTime)) Call(action_command_jump_start, LVarA, AC_DIFFICULTY_STANDARD) … Call(PlayerBasicJumpToGoal, LVarA, PLAYER_BASIC_JUMP_0)papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/move/jump/attack.c#L40-L43Call(GetMenuSelection, LVar0, LVar1, LVar2) Switch(LVar1) CaseEq(0) ExecWait(N(EVS_UseMove_Basic))papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/move/jump/attack.c#L75-L95Call(GetPlayerActionQuality, LVar0) Switch(LVar0) CaseGt(false) … Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_JUMP, 0, 0, 1, BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_NICE_HIT) CaseDefault … Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_JUMP, 0, 0, 1, BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_TRIGGER_EVENTS) EndSwitch Switch(LVar0) CaseOrEq(HIT_RESULT_HIT) CaseOrEq(HIT_RESULT_NO_DAMAGE) …papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/move/jump/attack.c#L107-L113Call(action_command_jump_start, 24, AC_DIFFICULTY_STANDARD) … Call(PlayerBasicJumpToGoal, 24, PLAYER_BASIC_JUMP_3) Wait(1) … Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_JUMP, 0, 0, 1, BS_FLAGS1_TRIGGER_EVENTS | BS_FLAGS1_NICE_HIT | BS_FLAGS1_NO_RATING)papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L1545-L1548battleStatus->curAttackElement = *args++; battleStatus->curAttackEventSuppression = *args++; battleStatus->curAttackStatus = *args++; battleStatus->curAttackDamage = evt_get_variable(script, *args++);papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L1028-L1031if (gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT)) { if (hitResult == HIT_RESULT_HIT) { hitResult = HIT_RESULT_NICE; }Checked by claude, 2026-10-22 — read the jump command's init, start, and update whole; the difficulty tables and adjust_action_command_difficulty; is_ability_active's loop and Dodge Master case (it counts equipped badges); the jump-time script and ApproachAndJump; the basic Jump script from its menu switch through the second stomp; PlayerDamageEnemy's argument order and its NICE_HIT flag (L1566-L1569); and the end of calc_player_damage_enemy, which turns a hit into a nice hit under that flag. The window count was traced by hand and corrected after audit; START runs its early-press test before its prepareTime test, so in the update that falls through into ACTIVE (timer 4) a press has already set wrongButtonPressed, and only timers 3 to 0 score. No VERSION_ conditional in the cited ranges

The command and the jump's motion are separate (a worker and a script), so "the last updates of the jump" is the atlas's reading of the two counts starting together; no probe has timed them. Super and Ultra Jump use the same command with other jump-time formulas and damages of 2 and 3.

Cited by: Action command, Paper Mario

In 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) at AC_DIFFICULTY_STANDARD, whose table value actionCmdTableHammer[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_TimingReady and 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"). paper-mario/hammer-command

About: Paper Mario Action command

Value: 11 updates in which a release counts (computed for the basic hammer at standard difficulty)

Codepapermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd.c#L29Difficulty1D actionCmdTableHammer = { 11, 10, 9, 8, 7, 6, 5, 4 };papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/common/move/HammerSupport.inc.c#L13-L23API_CALLABLE(N(IsBerserkerEquipped)) { script->varTable[0] = gBattleStatus.actionCommandMode; script->varTable[1] = 15; if (is_ability_active(ABILITY_BERSERKER)) { script->varTable[0] = AC_MODE_NOT_LEARNED;papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/common/move/HammerSupport.inc.c#L257-L274Call(N(IsBerserkerEquipped)) IfNe(LVar0, false) … Loop(45) Wait(1) Call(CheckButtonDown, BUTTON_STICK_LEFT, LVar0) IfNe(LVar0, false) BreakLoop … Add(LVarD, 6) Call(action_command_hammer_start, 0, LVarD, AC_DIFFICULTY_STANDARD)papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/move/hammer/attack.c#L17-L21CaseEq(0) Set(LVarD, 45)// action command duration Set(LVarE, 1) // bad input dmg Set(LVarF, 2) // good input dmg ExecWait(N(EVS_UseMove_Impl))papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/move/hammer/attack.c#L95-L118Call(GetPlayerActionQuality, LVar0) Switch(LVar0) CaseGt(false) … Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_SMASH, SUPPRESS_EVENTS_HAMMER, 0, LVarF, BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_TRIGGER_EVENTS | BS_FLAGS1_NICE_HIT) CaseDefault … Call(PlayerDamageEnemy, LVar0, DAMAGE_TYPE_SMASH, SUPPRESS_EVENTS_HAMMER, 0, LVarE, BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_TRIGGER_EVENTS)papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd/hammer.c#L99-L102acs->prepareTime = evt_get_variable(script, *args++); acs->duration = evt_get_variable(script, *args++); acs->difficulty = evt_get_variable(script, *args++); acs->difficulty = adjust_action_command_difficulty(acs->difficulty);papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd/hammer.c#L207-L216if (acs->prepareTime != 0) { acs->prepareTime--; return; } acs->stateTimer = 0; … acs->state = AC_STATE_ACTIVE;papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd/hammer.c#L256-L258if (acs->stateTimer == (-(inputWindow + 1) + acs->duration)) { battleStatus->actionProgress = 3; hud_element_set_script(acs->hudElemIDs[HIDX_WAIT], &HES_TimingReady);papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd/hammer.c#L268-L303inputWindow = battleStatus->actionCmdDifficultyTable[acs->difficulty] - (acs->duration - acs->stateTimer) + 3; if (inputWindow < 0) { inputWindow = 0; } // has the stick been release too early? if (!(battleStatus->curButtonsDown & BUTTON_STICK_LEFT) && inputWindow == 0 && acs->autoSucceed == 0 && battleStatus->actionCommandMode < AC_MODE_TUTORIAL ) { battleStatus->actionQuality = AC_QUALITY_FAILED; battleStatus->actionResult = ACTION_RESULT_EARLY; …papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd/hammer.c#L308-L313if (battleStatus->actionCommandMode < AC_MODE_TUTORIAL || acs->stateTimer != acs->duration) { acs->stateTimer++; if (acs->duration < acs->stateTimer) { if (battleStatus->actionQuality == 0) { battleStatus->actionQuality = AC_QUALITY_FAILED; }papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/16C8E0.c#L292-L298battleStatus->pushInputBuffer[battleStatus->inputBufferPos] = battleStatus->curButtonsPressed; battleStatus->holdInputBuffer[battleStatus->inputBufferPos] = battleStatus->curButtonsDown; battleStatus->inputBufferPos++; if (battleStatus->inputBufferPos >= ARRAY_COUNT(battleStatus->pushInputBuffer)) { battleStatus->inputBufferPos = 0;Checked by claude, 2026-10-22 — read the hammer command's start and update whole, the basic hammer's EVS_UseMove values and EVS_UseMove_Impl through both PlayerDamageEnemy calls, HammerSupport's EVS_UseBasicHammer through the command start, and btl_update's buffer write. Window traced by hand with duration 51 and table value 8 (no Dodge Master), look-back = timer - 40, zero through timer 40; the ready test is timer == 51 - 9. prepareTime is 0, so START falls through to ACTIVE on its first update. No VERSION_ conditional in the cited ranges

The look-back reads the buffer entries btl_update wrote most recently; whether the current update's entry is among them depends on btl_update running before the command's worker in a frame, which the atlas hasn't traced. With Berserker equipped, IsBerserkerEquipped reports AC_MODE_NOT_LEARNED and the script takes the branch that starts the command and waits a fixed time. Dodge Master would lower the difficulty index here too (adjust_action_command_difficulty), lengthening the window.

Cited by: Action command, Paper Mario

In 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_target calls check_block_input(BUTTON_A) when Mario's debuff is none or one numbered at or after STATUS_KEY_POISON (so not dizzy, paralyzed, asleep, frozen, or stopped), he isn't stone, and the attack isn't DAMAGE_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 is AC_MODE_TUTORIAL_BLOCK. It guards if a fresh press of A is in the last 3 entries of the battle's pressed-button buffer, which btl_update writes 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. paper-mario/guard

About: Paper Mario Timed guard

Value: 3 entries of the pressed-button buffer, one per battle update (5 with Dodge Master)

Codepapermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd.c#L551-L553if (battleStatus->actionCommandMode == AC_MODE_TUTORIAL_BLOCK && (battleStatus->flags1 & BS_FLAGS1_TUTORIAL_BATTLE)) { battleStatus->blockResult = BLOCK_RESULT_SUCCESS; return true;papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/action_cmd.c#L556-L616if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED || (gGameStatusPtr->demoBattleFlags & DEMO_BTL_FLAG_ENABLED)) { return false; } … block = false; blockWindow = 3; mashWindow = 10; if (!(gBattleStatus.flags1 & BS_FLAGS1_PARTNER_ACTING) && is_ability_active(ABILITY_DODGE_MASTER)) { blockWindow = 5; } // Pre-window mashing check bufferPos = battleStatus->inputBufferPos; …papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/16C8E0.c#L292-L295battleStatus->pushInputBuffer[battleStatus->inputBufferPos] = battleStatus->curButtonsPressed; battleStatus->holdInputBuffer[battleStatus->inputBufferPos] = battleStatus->curButtonsDown; battleStatus->inputBufferPos++;papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/1A5830.c#L231HitResult calc_enemy_damage_target(Actor* attacker) {papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/1A5830.c#L430-L466// apply damage mitigation from blocking switch (actorClass) { case ACTOR_CLASS_PLAYER: … if ((target->debuff == 0 || target->debuff >= STATUS_KEY_POISON) && (target->stoneStatus == 0) && !(battleStatus->curAttackElement & DAMAGE_TYPE_UNBLOCKABLE) ) { … if (player_team_is_ability_active(target, ABILITY_BERSERKER)) { blocked = rand_int(1); } else { …papermario: a decompilation of Paper Mario (pmret/papermario) · include/enums.h#L2808-L2813STATUS_KEY_DIZZY = 0x00000004, STATUS_KEY_PARALYZE = 0x00000005, STATUS_KEY_SLEEP = 0x00000006, STATUS_KEY_FROZEN = 0x00000007, STATUS_KEY_STOP = 0x00000008, STATUS_KEY_POISON = 0x00000009,papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/190B20.c#L2870-L2878s32 player_team_is_ability_active(Actor* actor, s32 ability) { … case ACTOR_CLASS_PLAYER: if (!(gBattleStatus.flags2 & BS_FLAGS2_PEACH_BATTLE)) { hasAbility = is_ability_active(ability);papermario: a decompilation of Paper Mario (pmret/papermario) · src/inventory.c#L1881-L1883case ABILITY_DAMAGE_DODGE: if (badgeMoveID == MOVE_DAMAGE_DODGE) { ret++;Checked by claude, 2026-10-22 — read check_block_input whole (its two buffer loops, the mash override, and the buffer clear after a guard), the blocking switch in calc_enemy_damage_target for both actor classes, the status enum's order, player_team_is_ability_active, is_ability_active's loop and Damage Dodge case (it counts equipped badges), and btl_update's buffer write. The 3 and 10 entries are positions inputBufferPos - 3 to - 1 and - 13 to - 4. No VERSION_ conditional in the cited ranges

After a guard, check_block_input clears the 13 entries it read, which a code comment says lets it be "called in quick succession" for multi-hit attacks. The atlas found no second, tighter guard window in the battle code it fetched; the Superguard is a later game's. The damage that a guard reduces is computed earlier in the same function and isn't traced here.

Cited by: Paper Mario, Timed guard

In the US version of Paper Mario, calc_player_damage_enemy works 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; and DAMAGE_TYPE_STATUS_ALWAYS_HITS sets 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 one rand_int call, the DAMAGE_TYPE_FEAR scare-away test, runs after the damage is taken off the target's HP. paper-mario/damage-defense

About: Paper Mario Damage formula

Value: 99 cap on attack damage before defense

Codepapermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L240HitResult calc_player_damage_enemy(void) {papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L292-L380if (gBattleStatus.flags1 & BS_FLAGS1_FORCE_IMMUNE_HIT) { hitResult = HIT_RESULT_NO_DAMAGE; … if (targetPart->eventFlags & ACTOR_EVENT_FLAG_ILLUSORY || target->transparentStatus == STATUS_KEY_TRANSPARENT || (targetPart->eventFlags & ACTOR_EVENT_FLAG_BURIED && !(battleStatus->curAttackElement & DAMAGE_TYPE_QUAKE)) ) { return HIT_RESULT_MISS; } if (target->stoneStatus == STATUS_KEY_STONE) { … if ((battleStatus->curAttackElement & DAMAGE_TYPE_JUMP) …papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L443-L459targetDefense = get_defense(target, targetPart->defenseTable, battleStatus->curAttackElement); if (!(battleStatus->curAttackElement & DAMAGE_TYPE_IGNORE_DEFENSE)) { targetDefense += target->defenseBoost; } if (targetPart->eventFlags & ACTOR_EVENT_FLAG_EXTREME_DEFENSE) { targetDefense += 127; } currentAttackDamage = battleStatus->curAttackDamage; currentAttackDamage += count_power_plus(battleStatus->curAttackElement); if (battleStatus->merleeAttackBoost > 0 … currentAttackDamage += battleStatus->merleeAttackBoost;papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L462-L492if (battleStatus->jumpCharge && battleStatus->curAttackElement & DAMAGE_TYPE_JUMP) { currentAttackDamage += battleStatus->jumpCharge; … if (battleStatus->hammerCharge && battleStatus->curAttackElement & (DAMAGE_TYPE_QUAKE_HAMMER | DAMAGE_TYPE_THROW | DAMAGE_TYPE_SMASH)) { currentAttackDamage += battleStatus->hammerCharge; … if (player_team_is_ability_active(player, ABILITY_BERSERKER)) { currentAttackDamage += 2; … if (player_team_is_ability_active(player, ABILITY_P_UP_D_DOWN)) { currentAttackDamage++; … …papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L536-L576if (!(gBattleStatus.flags2 & BS_FLAGS2_IS_FIRST_STRIKE) && player_team_is_ability_active(player, ABILITY_ALL_OR_NOTHING) ) { currentAttackDamage++; if (!(gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT))) { missedAllOrNothing = true; currentAttackDamage = 0; #if !VERSION_JP targetDefense = 0; #endif … if (player->debuff == STATUS_KEY_SHRINK) { …papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L578-L598if (currentAttackDamage > 99) { currentAttackDamage = 99; } if (currentAttackDamage < 0) { targetDefense = 0; } target->hpChangeCounter = 0; currentAttackDamage -= targetDefense; if (currentAttackDamage < 0) { currentAttackDamage = 0; } if (battleStatus->curAttackElement & DAMAGE_TYPE_POWER_BOUNCE && currentAttackDamage > 0) { …papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L630target->curHP -= currentAttackDamage;papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L672-L674if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS) { if (battleStatus->curAttackElement & DAMAGE_TYPE_FEAR && rand_int(99) < (target->actorBlueprint->escapeChance * battleStatus->statusChance) / 100papermario: a decompilation of Paper Mario (pmret/papermario) · src/battle/dmg_player.c#L1548battleStatus->curAttackDamage = evt_get_variable(script, *args++);Checked by claude, 2026-10-22 — read calc_player_damage_enemy from the forced-immune test through the scare-away test (L292-L691, the else that holds the calculation closes at L691) and searched the whole function (L240-L1050) for rand_int, finding only L674. Revised after audit to name the early returns, the cases that zero the defense, the shrink halving, and Power Bounce. The VERSION_JP conditional at L544-L546 is quoted as the code has it

The damage comes off the target's HP (L630) only when the part isn't damage-immune or immune to the attack's element, the target doesn't take no damage, and this isn't the tutorial battle (L625-L629). The HP Drain badges (L494-L520) and Power and Mega Rush (L522-L534) are among the fixed adjustments the statement doesn't list one by one.

Cited by: Damage formula, Paper Mario