On this page
  1. Related
  2. Games
  3. References
  4. Sources

Landing lag is the time a character spends in a landing animation after an air attack touches down. In Super Smash Bros. Melee, a trigger press shortly before landing divides an aerial’s landing lag, so long as the move’s script has turned the lag on1. Super Smash Bros. skips the air-landing status outright when Z was pressed within the last 10 counts2.

  • Press skips itSuper Smash Bros. (1999). Z within 10 counts before an air attack lands skips its air-landing status.2
  • Press reduces itSuper Smash Bros. Melee (2001). A trigger or Z press shortly before an aerial lands divides its landing lag.1

Games

GameYearHowNote
Super Smash Bros.1999Press skips itZ within 10 counts before an air attack lands skips its air-landing status
Super Smash Bros. Melee2001Press reduces ita trigger or Z press shortly before an aerial lands divides its landing lag
Every claim about this mechanic, by game (2)
Super Smash Bros. 1999In the US version of Super Smash Bros., when a fighter in an air attack lands, ftCommonAttackAirProcMap enters the move's air-landing status only when the motion's flag1 is nonzero and more than 10 counts have passed since Z was last pressed (tics_since_last_z: set to 0 on a Z press, counted up each update, and set to its maximum when the air attack starts, so a press before the attack doesn't count); otherwise it skips that status and enters Wait if the fighter's vertical speed is above −20, or the plain Landing status if not. Reading flag1 as the move's switch for landing lag is the atlas's.Code
Super Smash Bros. Melee 2001In the NTSC 1.02 version of Super Smash Bros. Melee, an aerial attack (statuses ftCo_MS_AttackAirN to ftCo_MS_AttackAirLw) that touches down calls ftCo_LandingAir_EnterWithLag from its collision routine ftCo_AttackAir_Coll, through ft_80082C74, which calls it when the unnamed ft_80081D0C returns true. If the move's command script has set cmd_vars[0], which entering the aerial clears, the fighter enters that aerial's LandingAir status with the fighter's landing-lag attribute for it (landingairn_lag and the four like it), and the animation plays at a rate of (ftAnim_8006F484 + 0.1) / lag, where ftAnim_8006F484 returns the animation's end frame. If the unnamed count x67F is below c_E4 at that moment, the lag is first divided by c_E8, truncated to a whole number, and raised to 1 if that's 0; c_E4 and c_E8 are p_ftCommonData fields from PlCo.dat, so the window and divisor aren't in the code. Fighter_procInput sets x67F to 0 on an update where the HSD_PAD_LR bit is newly pressed and otherwise adds 1, up to 255. That bit is on while L or R is held, while the analog trigger is past its deadzone, or while Z is held unless gm_GetDbPauseFlag(0) is true, and it's off while the unnamed gm_8016B0FC is true. Without cmd_vars[0], the fighter takes the basic landing (ftCo_Landing_Enter_Basic). Super Smash Bros. reads the same moment differently (ftCommonAttackAirProcMap): when the aerial's flag1 is clear or Z was pressed no more than 10 counts before (tics_since_last_z ≤ 10), it skips the aerial's landing lag outright, landing in Wait if the air speed is above −20 and in Landing otherwise, where Melee divides the lag.Code

References

  1. ^ abIn the NTSC 1.02 version of Super Smash Bros. Melee, an aerial attack (statuses ftCo_MS_AttackAirN to ftCo_MS_AttackAirLw) that touches down calls ftCo_LandingAir_EnterWithLag from its collision routine ftCo_AttackAir_Coll, through ft_80082C74, which calls it when the unnamed ft_80081D0C returns true. If the move's command script has set cmd_vars[0], which entering the aerial clears, the fighter enters that aerial's LandingAir status with the fighter's landing-lag attribute for it (landingairn_lag and the four like it), and the animation plays at a rate of (ftAnim_8006F484 + 0.1) / lag, where ftAnim_8006F484 returns the animation's end frame. If the unnamed count x67F is below c_E4 at that moment, the lag is first divided by c_E8, truncated to a whole number, and raised to 1 if that's 0; c_E4 and c_E8 are p_ftCommonData fields from PlCo.dat, so the window and divisor aren't in the code. Fighter_procInput sets x67F to 0 on an update where the HSD_PAD_LR bit is newly pressed and otherwise adds 1, up to 255. That bit is on while L or R is held, while the analog trigger is past its deadzone, or while Z is held unless gm_GetDbPauseFlag(0) is true, and it's off while the unnamed gm_8016B0FC is true. Without cmd_vars[0], the fighter takes the basic landing (ftCo_Landing_Enter_Basic). Super Smash Bros. reads the same moment differently (ftCommonAttackAirProcMap): when the aerial's flag1 is clear or Z was pressed no more than 10 counts before (tics_since_last_z ≤ 10), it skips the aerial's landing lag outright, landing in Wait if the air speed is above −20 and in Landing otherwise, where Melee divides the lag.Codedoldecomp/melee · VetriTheRetri/ssb-decomp-re
    How we know
    14void ftCo_LandingAir_EnterWithLag(Fighter_GObj* gobj)
    ⋮
    20    if (fp->cmd_vars[0]) {
    21        switch (fp->motion_id) {
    22        case ftCo_MS_AttackAirN:
    23            lag = fp->co_attrs.landingairn_lag;
    24            msid = ftCo_MS_LandingAirN;
    25            break;
    ⋮
    29            break;
    ⋮
    33            break;
    ⋮
    37            break;
    ⋮
    41            break;
    ⋮
    43        if (msid != ftCo_MS_None && fp->x67F < p_ftCommonData->xE4) {
    ⋮
    
    src/melee/ft/kinds/ftCommon/ftCo_LandingAir.c lines 14–56 at f0cdbb0 · upstream ↗
    59void ftCo_LandingAir_EnterWithMsidLag(Fighter_GObj* gobj, FtMotionId msid,
    60                                      float lag)
    ⋮
    64    Fighter_ChangeMotionState(gobj, msid, Ft_MF_None, 0, 1, 0, NULL);
    65    ftAnim_SetAnimRate(gobj, (ftAnim_8006F484(gobj) + 0.1f) / lag);
    
    src/melee/ft/kinds/ftCommon/ftCo_LandingAir.c lines 59–65 at f0cdbb0 · upstream ↗
    575float ftAnim_8006F484(Fighter_GObj* fighter_gobj)
    ⋮
    580        return lbGetJObjEndFrame(jobj);
    ⋮
    582    return lbGetJObjEndFrame(fp->x8AC_animSkeleton);
    
    src/melee/ft/ftanim.c lines 575–582 at f0cdbb0 · upstream ↗
    125void ftCo_AttackAir_EnterFromMsid(Fighter_GObj* gobj, FtMotionId msid)
    ⋮
    129    fp->cmd_vars[0] = 0;
    
    src/melee/ft/kinds/ftCommon/ftCo_AttackAir.c lines 125–129 at f0cdbb0 · upstream ↗
    189void ftCo_AttackAir_Coll(Fighter_GObj* gobj)
    ⋮
    191    ft_80082C74(gobj, ftCo_LandingAir_EnterWithLag);
    
    src/melee/ft/kinds/ftCommon/ftCo_AttackAir.c lines 189–191 at f0cdbb0 · upstream ↗
    850        // ftCo_MS_AttackAirN = 65
    ⋮
    857        ftCo_AttackAir_Coll,
    
    src/melee/ft/ftmotionstates.c lines 850–857 at f0cdbb0 · upstream ↗
    548void ft_80082C74(Fighter_GObj* gobj, HSD_GObjEvent cb)
    ⋮
    550    bool var_r0 = ft_80081D0C(gobj);
    551    PAD_STACK(8);
    552    if (var_r0) {
    553        cb(gobj);
    
    src/melee/ft/ft_081B.c lines 548–554 at f0cdbb0 · upstream ↗
    456void ftAction_80071820(Fighter_GObj* gobj, CommandInfo* cmd)
    ⋮
    460    switch (cmd->x8.u->set_cmd_var.idx) {
    461    case 0:
    462        fp->cmd_vars[0] = cmd->x8.u->set_cmd_var.value;
    
    src/melee/ft/ftaction.c lines 456–462 at f0cdbb0 · upstream ↗
    947    /* +0E8 fp+1F8 */ float landingairn_lag;
    948    /* +0EC fp+1FC */ float landingairf_lag;
    949    /* +0F0 fp+200 */ float landingairb_lag;
    950    /* +0F4 fp+204 */ float landingairhi_lag;
    951    /* +0F8 fp+208 */ float landingairlw_lag;
    
    src/melee/ft/types.h lines 947–951 at f0cdbb0 · upstream ↗
    1879            if (gm_8016B0FC()) {
    1880                fp->input.triggers[0] = 0.0f;
    1881                if (ftCo_IsCpuControlled(fp)) {
    1882                    fp->input.held_buttons[0] &= HSD_PAD_A | HSD_PAD_XY;
    1883                } else {
    1884                    fp->input.held_buttons[0] &= HSD_PAD_A;
    ⋮
    1886            } else {
    1887                if (fp->input.held_buttons[0] & (HSD_PAD_L | HSD_PAD_R)) {
    1888                    fp->input.held_buttons[0] |= HSD_PAD_LR;
    1889                    fp->input.triggers[0] = 1.0f;
    1890                } else if (fp->input.triggers[0]) {
    1891                    fp->input.held_buttons[0] |= HSD_PAD_LR;
    ⋮
    
    src/melee/ft/fighter.c lines 1879–1898 at f0cdbb0 · upstream ↗
    1866            if (fp->input.triggers[0] <=
    1867                p_ftCommonData->analog_shoulder_deadzone)
    ⋮
    1869                fp->input.triggers[0] = 0.0f;
    
    src/melee/ft/fighter.c lines 1866–1869 at f0cdbb0 · upstream ↗
    1759static void Fighter_procInput_Inner1(Fighter* fp)
    ⋮
    1764    temp0_loc_0 = (fp->input.held_buttons[0] &
    1765                   (fp->input.held_buttons[1] ^ fp->input.held_buttons[0]));
    
    src/melee/ft/fighter.c lines 1759–1765 at f0cdbb0 · upstream ↗
    1902            Fighter_procInput_Inner1(fp);
    
    src/melee/ft/fighter.c line 1902 at f0cdbb0 · upstream ↗
    2105            if (fp->input.pressed_buttons & HSD_PAD_LR) {
    2106                fp->x67F = 0;
    2107            } else if (fp->x67F < 255) {
    2108                fp->x67F++;
    
    src/melee/ft/fighter.c lines 2105–2109 at f0cdbb0 · upstream ↗
    53void ftCommonAttackAirProcMap(GObj *fighter_gobj)
    ⋮
    57    if (mpCommonCheckFighterLanding(fighter_gobj) != FALSE)
    ⋮
    59        if ((fp->motion_vars.flags.flag1 != 0) && (fp->tics_since_last_z > FTCOMMON_ATTACKAIR_SMOOTHLANDING_TICS_MAX))
    ⋮
    65                ftCommonLandingAirSetStatus(fighter_gobj);
    ⋮
    67            else ftCommonLandingAirNullSetStatus(fighter_gobj, F_PCT_TO_DEC(fp->motion_vars.flags.flag1));
    ⋮
    69        else if (fp->physics.vel_air.y > FTCOMMON_ATTACKAIR_SKIPLANDING_VEL_Y_MAX)
    ⋮
    71            ftCommonWaitSetStatus(fighter_gobj);
    ⋮
    73        else ftCommonLandingSetStatus(fighter_gobj);
    
    src/ft/ftcommon/ftcommonattackair.c lines 53–74 at 572a747 · upstream ↗
    361#define FTCOMMON_ATTACKAIR_SMOOTHLANDING_TICS_MAX 10
    362#define FTCOMMON_ATTACKAIR_SKIPLANDING_VEL_Y_MAX (-20.0F)
    
    src/ft/ftcommon.h lines 361–362 at 572a747 · upstream ↗
    1373    if (this_fp->tics_since_last_z < FTINPUT_ZTRIGLAST_TICS_MAX)
    ⋮
    1375        this_fp->tics_since_last_z++;
    ⋮
    1377    if (this_fp->input.pl.button_tap & this_fp->input.button_mask_z)
    ⋮
    1379        this_fp->tics_since_last_z = 0;
    
    src/ft/ftmain.c lines 1373–1380 at 572a747 · upstream ↗
    190                fp->motion_vars.flags.flag1 = 0;
    
    src/ft/ftcommon/ftcommonattackair.c line 190 at 572a747 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  2. ^ abIn the US version of Super Smash Bros., when a fighter in an air attack lands, ftCommonAttackAirProcMap enters the move's air-landing status only when the motion's flag1 is nonzero and more than 10 counts have passed since Z was last pressed (tics_since_last_z: set to 0 on a Z press, counted up each update, and set to its maximum when the air attack starts, so a press before the attack doesn't count); otherwise it skips that status and enters Wait if the fighter's vertical speed is above −20, or the plain Landing status if not. Reading flag1 as the move's switch for landing lag is the atlas's.CodeVetriTheRetri/ssb-decomp-rerevised
    How we know
    53void ftCommonAttackAirProcMap(GObj *fighter_gobj)
    ⋮
    59        if ((fp->motion_vars.flags.flag1 != 0) && (fp->tics_since_last_z > FTCOMMON_ATTACKAIR_SMOOTHLANDING_TICS_MAX))
    ⋮
    65                ftCommonLandingAirSetStatus(fighter_gobj);
    ⋮
    69        else if (fp->physics.vel_air.y > FTCOMMON_ATTACKAIR_SKIPLANDING_VEL_Y_MAX)
    ⋮
    71            ftCommonWaitSetStatus(fighter_gobj);
    ⋮
    73        else ftCommonLandingSetStatus(fighter_gobj);
    
    src/ft/ftcommon/ftcommonattackair.c lines 53–74 at 572a747 · upstream ↗
    361#define FTCOMMON_ATTACKAIR_SMOOTHLANDING_TICS_MAX 10
    362#define FTCOMMON_ATTACKAIR_SKIPLANDING_VEL_Y_MAX (-20.0F)
    
    src/ft/ftcommon.h lines 361–362 at 572a747 · upstream ↗
    1373    if (this_fp->tics_since_last_z < FTINPUT_ZTRIGLAST_TICS_MAX)
    ⋮
    1375        this_fp->tics_since_last_z++;
    ⋮
    1377    if (this_fp->input.pl.button_tap & this_fp->input.button_mask_z)
    ⋮
    1379        this_fp->tics_since_last_z = 0;
    
    src/ft/ftmain.c lines 1373–1380 at 572a747 · upstream ↗
    202                fp->tics_since_last_z = FTINPUT_ZTRIGLAST_TICS_MAX;
    
    src/ft/ftcommon/ftcommonattackair.c line 202 at 572a747 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-27.

    Revised after a check by a second AI model, 2026-10-27: Starting an air attack sets the Z counter to its maximum, so a press before the attack doesn't count.

    In the claim ledger

Sources

Code