Idle is the action where Mario stands still, turning his head left to right while not moving.

Idle
Properties
Hex 0x0C400201
Action Flags Stationary, Idle, Allow First Person, Pause Exit
Action Group Stationary
ID 0x001
Transitions
Into stationary cancels: Water Plunge, Squished, Standing Death, Quicksand Death; other idle cancels: In Quicksand, Coughing, Panting; common idle cancels: Freefall, Shockwave Bounce, Hold Quicksand Jump Land, Quicksand Jump Land, Steep Jump, Jump, Begin Sliding, First Person Action, Walking, Punching, Start Crouching; non cancel: Shivering, Start Sleeping
Out of Waking Up, Shivering, Hold Idle, In Quicksand, Panting, Braking Stop, Butt Slide Stop, Hold Butt Slide Stop, Stop Crouching, Stop Crawling, Shockwave Bounce, Jump Land Stop, Double Jump Land Stop, Slideflip Land Stop, Freefall Land Stop, Backflip Land Stop, Lava Boost Land, Long Jump Land Stop (from cancel when INPUT_FIRST_PERSON), Hold Jump Land Stop, Hold Freefall Land Stop, Air Throw Land, Twirling Land, Ground Pound Land, First Person Action, Punching, Placing Down, Throwing, Heavy Throw, Stomach Slide Stop, Releasing Bowser, ("pole cancels": Holding Pole, Climbing Pole, Grab Pole Slow, Grab Pole Fast, Top of Pole Transition, Top of Pole), Ledge Climb Slow 1, Ledge Climb Slow 2, Ledge Climb Fast, Exit Land Save Dialog, Reading Npc Dialog, Reading Automatic Dialog, Reading Sign, Debug Free Move, Star Dance, Entering Star Door, Pushing Door, Pulling Door, Warp Door Spawn, Spawn Spin Landing, Spawn No Spin Landing, Teleport Fade In, Shocked, Squished, Putting On Cap, Head Stuck In Ground, Feet Stuck In Ground, Intro Cutscene, (some warps), (some level initializations), Decelerating, Hard Backward Ground Kb, Hard Forward Ground Kb, Backward Ground Kb, Forward Ground Kb, Soft Backward Ground Kb, Soft Forward Ground Kb, Ground Bonk, Death Exit Land, (when Mario initializes and is not less than or equal to 100 units below the water level)
Other
Animation 0x75 (standing against wall), 0xC3 (idle head left), 0xC4 (idle head right), 0xC5 (idle head center)
Related Actions
Related Panting, Standing Against Wall, Coughing, Shivering, Start Sleeping, Sleeping

Behavior

Certain things here are more explained on their individual pages. If something lacks detail, check the link for more information.

Before performing the action, stationary cancels are checked.

When performing the Idle action, the following happens:

  1. If Mario has sunk more than 30 units into quicksand, his action is set to in quicksand.
  2. If Mario is in poison gas AND he is not standing against the wall, his action is set to coughing.
  3. If Mario is not against a wall and has low health, his action is set to the panting action.
  4. check_common_idle_cancels
  5. If Mario's animation has just ended, his head has turned 10 times, and there is ground behind him (that is not an object)
    1. If Mario is in a cold environment, he starts to shiver, else he goes into the start sleeping action.
  6. If Mario is against a wall, Mario has his animation changed to be standing against the wall. Otherwise, Mario's animation is set depending on which way he is turning his head.
  7. stationary_ground_step

Stationary cancels

A variety of "cancels" are checked prior to actually performing any stationary action. These checks are as follows:[1]

  1. Water - If Mario's height is lower than 100 units below the water height:
    • The camera preset is updated.
    • Mario's forward velocity is divided by 4.
    • Mario's y velocity is divided by 2.
    • Mario's height is set to 100 units below the water height.
    • Mario's action is set to water plunge.
  2. Squish - If Mario is supposed to be squished:
    • The camera preset is updated.
    • Mario's action is set to squished.
  3. If the action is not the unused 0x0E action (always true) and Mario has less than 0x100 health:
    • The camera preset is updated.
    • Mario's action is changed to standing death.
  4. Potentially cancel to quicksand death (sinkingSpeed = 0.5)

The processing goes:

  1. Somehow, m->action is set to a stationary action.
  2. Right before executing the action, stationary cancels are checked.
  3. The action is executed.

Technically, m->action was set to the stationary action. So although the action doesn't really do anything, there is still a "transition" between such stationary action and Water Plunge, Squished, Standing Death, or Quicksand Death. So invariably, for all stationary actions, the infobox contains those 4 actions under "Transitions > Into" first (see top right of page if you don't know what I'm talking about).

quicksand death

Many actions call mario_update_quicksand. This function only cancels if Mario's action is set to Quicksand Death. This function has one argument, sinkingSpeed.

  • Nothing happens if Mario is riding on a shell (Riding Shell Ground, Riding Shell Jump, Riding Shell Fall)
  • If Mario's floor isn't quicksand, the quicksand depth is set to 0, and nothing happens.
  • Else:
    • If Mario's quicksand depth is less than 1.1, it is set to 1.1
    • Mario's quicksand depth is increased by sinkingSpeed
    • If Mario's floor type is SURFACE_SHALLOW_QUICKSAND, SURFACE_SHALLOW_MOVING_QUICKSAND, or (SURFACE_QUICKSAND or SURFACE_MOVING_QUICKSAND), then his quicksand depth is capped to at most 10, 25, and 60 units respectively.
    • If (Mario's floor type is SURFACE_DEEP_QUICKSAND or SURFACE_DEEP_MOVING_QUICKSAND, and his quicksand depth is at least 160) or (Mario's floor type is SURFACE_INSTANT_QUICKSAND or SURFACE_INSTANT_MOVING_QUICKSAND):

check_common_idle_cancels

Note: This is used only in Idle, Start Sleeping, Coughing, In Quicksand, and Panting.

  1. If Mario is on a steep cliff, he is pushed off (into freefall).
  2. If Mario is hit by a shockwave, his action is set to the shockwave bounce action.
  3. If A is pressed, his action is set to a jumping action:
    1. If Mario's quicksand depth is at least 11, then if Mario's holding an object, his action is set to Hold Quicksand Jump Land, else Quicksand Jump Land.
    2. If Mario's floor is steep, his action is set to Steep Jump, else Jump.
  4. If Mario is off the floor, Mario's action is set to freefall.
  5. If Mario is above a slide, he begins sliding.
  6. If Mario goes into first-person mode, his action is set to first person.
  7. If the joystick is held in a direction, Mario's action is set to walking.
  8. If B is pressed, Mario's action is set to punching.
  9. If Z is pressed, Mario's action is set to start crouching.[2]

stationary_ground_step

https://github.com/n64decomp/sm64/blob/66018e9f3caaa67399218971d61366cb3f7ba7d7/src/game/mario_step.c#L236

  1. Set Mario's forward velocity, velocity[0], velocity[2], slideVelocityX, and slideVelocityZ to 0.
  2. Let step_result = GROUND_STEP_NONE
  3. Call mario_update_moving_sand:[3]
    1. If Mario's floor type is {DEEP_MOVING, SHALLOW_MOVING, MOVING, or INSTANT_MOVING}_QUICKSAND:
      1. Change Mario's velocity[0] and velocity[2] based on the floor's "force" data.
      2. return TRUE
    2. else return FALSE
  4. Call mario_update_windy_ground:[4]
    1. If Mario's floor type is SURFACE_HORIZONTAL_WIND (like on the ship in Rainbow Ride):
      1. Change Mario's velocity[0] and velocity[2] as if the wind was pushing Mario, based on the floor's "force" data, the global timer, and Mario's facing angle.
      2. return TRUE
    2. else return FALSE
  5. If either step 3 or step 4 returned true, step_result = perform_ground_step():
    1. Loop 4 times: Do a quarterstep. The next intended position is Mario's position plus the de facto speed vector. Each time, set step_result to a (value).
      1. Let lowerWall be a wall within 30 units of (24 units above the next intended position). Wall push: Change the next intended position based on wall collisions.
      2. Let upperWall be a wall within 60 units of (50 units above the next intended position). Wall push: Change the next intended position based on wall collisions.
      3. Let floor be the (first) floor at the next intended position (TODO? this is complicated). It must be at least -78 units below Mario's y position.
      4. Let ceilingHeight be based on the position 80 units above the next intended position and the floor height.
      5. If the next intended position is OOB, exit loop (WALL)
      6. If Mario is riding a shell and the floor height is less than the water level (which is -11000 by default)
        1. Set floor height to water level
        2. Set floor to the global water surface pseudo floor (very slippery, flags: 0, room: 0, vertices: (0, 0, 0), (0, 0, 0), (0, 0, 0), normal vector: (0, 1, 0) i.e. up)[5]
        3. Set the floor's originOffset to floor height (a comment says this has no effect)
      7. If the floor is more than 100 units below Mario
        1. If Mario's height + 160 units is at least the ceiling height, exit loop (WALL)
        2. Set Mario's position to the next intended position, Mario's floor to the floor, and Mario's floor height to the floor height; exit loop (LEFT GROUND)
      8. If floor height + 160 units is at least the ceiling height, exit loop (WALL)
      9. Set Mario's position to the next intended position (but Mario's y position to the floor height), Mario's floor to the floor, and Mario's floor height to the floor height
      10. If the upperWall exists AND not(abs(atan2s(upperWall normal z, upperWall normal x) - Mario facing angle[1]) is between 0x2AAA and 0x5555), exit loop (WALL), else (WALL_CONTINUE)
      11. (NONE)
    2. Update Mario's "terrain sound addend", graphics position, and graphics angle.
    3. If step_result is (WALL_CONTINUE), set step_result to (WALL)
    4. Return step_result
  6. Else:
    1. Set Mario's y position to the floor height. This is the cause of many downwarps.
    2. Update Mario's graphics position and graphics angle.
  7. Return step_result

resolve_and_return_wall_collisions

A function that's called in the quarterstep code (see green text).

This function takes a Vec3s position, f32 yOffset, and f32 radius as arguments.

At times the position is modified, which in the case of stationary_ground_step, means changing the next intended position.

There's probably a better explanation, something something walls floors and ceilings.

https://github.com/n64decomp/sm64/blob/66018e9f3caaa67399218971d61366cb3f7ba7d7/src/game/mario.c#L521

  1. Let walls be an empty list (max 4 allocated entries)
  2. Inner function:
    1. Let x be (convert f32 to s16) position->x
    2. Let z be (convert f32 to s16) position->z
    3. If abs(x) or abs(z) is greater than or equal to LEVEL_BOUNDARY_MAX (i.e. 8192), return.
    4. A level consists of a 16x16 grid. These subgrids are called "cells" in the comments. An optimization is made filtering out surfaces not in the same cell as the position. When casting the position to an integer, round down. (This optimization is hopefully not important but just in case I'm typing this out).
    5. Check for walls belonging to objects and then walls that are part of level geometry.
    6. Code when checking one wall (there's actually a loop over the wall list):
      1. If radius > 200, set radius to 200.
      2. Let x be (f32) position->x, y be (f32) position->y + yOffset, z be (f32) position->z
      3. Let offset be (x*wallNormalX + y*wallNormalY + z*wallNormalZ + wallOriginOffset)
      4. Exclude walls where y is not in the range [wall.lowerY, wall.upperY]
      5. Exclude walls where offset is outside the range [-radius, radius]
      6. Exclude <insert complicated code>
      7. If this is the camera, ignore walls that have the SURFACE_FLAG_NO_CAM_COLLISION
      8. Else, ignore camera only surfaces and based on vanish cap, some other walls
      9. Add surfaceNormal.(x or z) * (radius - offset) to position->x and position->z. Since this function is called on each wall, multiple walls can do a push at the same time.
      10. If walls is not full (max 4 entries), add the wall being checked to walls.
  3. Return the last item in the list (which is NULL if no wall was found)

References