data/claims/paper-mario.yamlPaper 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 rangesThe 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 rangesThe 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 rangesAfter 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 itThe 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