Mechanic · combat · role-playing game
Action command
A button input timed inside a turn-based attack that raises its effect when it lands in a window.
On this page
An action command asks for a timed input during a turn-based attack, and a good one strengthens it. In Paper Mario the Jump takes one press of A in the last 4 updates1 of its count, and a good press earns a second stomp1; the hammer is held left and let go inside a window of 11 updates2 at the end of its charge, which doubles its damage2.
- Timed pressPaper Mario (2000). 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.1
- Hold and releasePaper Mario (2000). 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.2
Games
| Game | Year | How | Note |
|---|---|---|---|
| Paper Mario | 2000 | 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 |
| Paper Mario | 2000 | 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 |
Every claim about this mechanic, by game (2)
References
- ^ abcIn 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.
- ^ abcIn 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.
Sources
Code
- pmret and papermario contributors. 2026. “papermario: a decompilation of Paper Mario (pmret/papermario).” Commit 1104f1f. pmret/papermario @ 1104f1f · licence, all uses