Super Smash Bros. Melee
HAL Laboratory's 2001 platform fighter for the GameCube, read through the doldecomp decompilation of NTSC 1.02.
On this page
The atlas reads Super Smash Bros. Melee through the doldecomp decompilation, C that compiles to the NTSC 1.02 release’s own code. Names and comments quoted here are theirs. Most of the game’s tuning isn’t in that code: it’s read from the disc file PlCo.dat, so the claims here give the shape of each rule with its constants named by their offset in that file. Nothing has been measured in the game yet.
The knockback formula has the same terms as Super Smash Bros.’s, but the fighter’s weight attribute now divides the launch where the earlier game multiplied by it1. Hitstun is the knockback times a value from the disc, and after a hit at an angle in a set range, a falling fighter can end it with an air jump or up special2. How fast the shield wears while held, and how much a hit takes from it, both depend on how far the analog trigger is pressed3. A trigger press shortly before an aerial lands divides its landing lag, where Super Smash Bros. skipped the lag on a Z press4.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Knockback | Percent-scaled | Super Smash Bros.'s formula with its constants moved to a data file, and the weight dividing the launch rather than multiplying it |
| Hitstun | From knockback | the knockback times a data-file value, as a whole count of at least 1; an air jump or up special can end it early after a hit at an angle in a set range |
| Blocking | Guard meter | a shield whose wear while held and damage from hits both depend on how far the analog trigger is pressed |
| Landing lag | Press reduces it | a trigger or Z press shortly before an aerial lands divides its landing lag |
Every claim about this game, by concept (4)
References
- ^In the NTSC 1.02 version of Super Smash Bros. Melee,
ftColl_80079AB0computes a hit's knockback as capped at c_108. Every c is an unnamed field ofp_ftCommonData, whichFighter_LoadCommonDataloads from the disc file PlCo.dat, so the constants aren't in the code. Here d is the target'sx1830_percentplusx1838_percentTemp, or, while the unnamed flagx2225_b7is set, c_6D4 (c_6D8 ifstamina_dead) plusx1838_percentTemp; n is the hit capsule'sunk_count; w is the target'sweightattribute times c_F4; g and b are the capsule's unnamedx24andx2C; r isgm_8016B248(), the match rules'x30, which the VS setup in gm_1601.c sets to 0.1 × the rules'damage_ratio; and A and D arePlayer_GetAttackRatiofor the attacker andPlayer_GetDefenseRatiofor the target. A capsule whose unnamedx28(k) isn't 0 uses c_118·c_110 + c_114·c_118·k in place of the percent term. The terms sit where Super Smash Bros.'s 0.1, 0.05, 1.4, 18, and its set-knockback 10 and cap 2500 do (ssb64/knockback), and the atlas reads g as the growth and b as the base by that position. Where Super Smash Bros. multiplies by its weight attribute, Melee's weight term equals c_F8 / (1 + w) (computed), so the weight divides. Of the hits a fighter logs in one update,ftColl_8007A06Ckeeps the largest knockback and writes it tokb_applied;ftCo_Damage_CalcKnockbackthen multiplies it bykb_squat_mulinftCo_MS_SquatorftCo_MS_SquatWait, bykb_ice_mulinftCo_MS_DamageIce, and bykb_smashcharge_mulwhile a smash attack charges, rescales it withftCo_CalcYScaledKnockbackwhen the fighter's vertical scale isn't 1, subtracts the larger ofarmor0andarmor1(plusmetal_armorfor a metal fighter), and raises it tokb_minif it falls below.Codedoldecomp/melee · VetriTheRetri/ssb-decomp-reHow we know
2061static inline s32 ftColl_GetDamageCount(Fighter* fp, ftCommonData* ftd) ⋮ 2063 if (fp->x2225_b7) { 2064 if (fp->stamina_dead) { 2065 return ftd->x6D8; ⋮ 2067 return ftd->x6D4; ⋮ 2069 return (s32) fp->dmg.x1830_percent;
src/melee/ft/ftcoll.c lines 2061–2069 at f0cdbb0 · upstream ↗ 2075#define KNOCKBACK(defense, attack, arg3, one, ftd, hit, w, inner) \ 2076 ((defense) * \ 2077 ((attack) * \ 2078 ((arg3) * ((0.01F * (hit)->x24 * \ 2079 ((ftd)->x11C * \ 2080 (((ftd)->xF8 - (((w) * (ftd)->xF8) / ((one) + (w)))) * \ 2081 (inner)) + \ 2082 (ftd)->x120)) + \ 2083 (hit)->x2C)))) ⋮ 2091 float w = weight; 2092 w *= ftd->xF4; ⋮ 2094 if (hit->x28 != 0) { ⋮
src/melee/ft/ftcoll.c lines 2075–2118 at f0cdbb0 · upstream ↗ 2120float ftColl_80079C70(Fighter* fp, Fighter* attacker, HitCapsule* hit, 2121 int unk_count) ⋮ 2123 ftCo_DatAttrs* co = &fp->co_attrs; 2124 return ftColl_80079AB0(fp, hit, unk_count, gm_8016B248(), 2125 Player_GetAttackRatio(attacker->player_idx), 2126 Player_GetDefenseRatio(fp->player_idx), co->weight);
src/melee/ft/ftcoll.c lines 2120–2126 at f0cdbb0 · upstream ↗ 37 /* +8 */ u32 unk_count; ⋮ 42 /* +24 */ u32 x24; 43 /* +28 */ u32 x28; 44 /* +2C */ u32 x2C;
src/melee/lb/types.h lines 37–44 at f0cdbb0 · upstream ↗ 918 /* +088 fp+198 */ float weight;src/melee/ft/types.h line 918 at f0cdbb0 · upstream ↗ 182 lbArchive_LoadSymbols("PlCo.dat", &data, "ftLoadCommonData", 0); ⋮ 188 p_ftCommonData = data->common; // p_ftCommonData
src/melee/ft/fighter.c lines 182–189 at f0cdbb0 · upstream ↗ 263f32 gm_8016B248(void) ⋮ 265 return gm_GetStartMeleeRules()->x30;
src/melee/gm/gmvs.c lines 263–266 at f0cdbb0 · upstream ↗ 3810 vs_data->start.rules.x30 = 0.1f * rules->damage_ratio;src/melee/gm/gm_1601.c line 3810 at f0cdbb0 · upstream ↗ 2253 kb = ftColl_80079C70(fp, attacker_fp, hit, unk_count);src/melee/ft/ftcoll.c line 2253 at f0cdbb0 · upstream ↗ 2298 if (kb > best_kb.v) { ⋮ 2306 best_kb.v = kb; 2307 best_idx = i;
src/melee/ft/ftcoll.c lines 2298–2307 at f0cdbb0 · upstream ↗ 2194struct DmgResult { 2195 /* 0x00 */ float dir; 2196 /* 0x04 */ int angle; 2197 /* 0x08 */ int hurt_height; 2198 /* 0x0C */ float kb;
src/melee/ft/ftcoll.c lines 2194–2198 at f0cdbb0 · upstream ↗ 2389 out->kb = best_kb.v;src/melee/ft/ftcoll.c line 2389 at f0cdbb0 · upstream ↗ 2452 ftColl_8007A06C(gobj, &fp->dmg.facing_dir_1, dmg_log0, dmg_log0_idx, 1);src/melee/ft/ftcoll.c line 2452 at f0cdbb0 · upstream ↗ 1660 /* fp+1844 */ float facing_dir_1; 1661 /* fp+1848 */ int x1848_kb_angle; 1662 /* fp+184C */ int x184c_damaged_hurtbox; 1663 /* fp+1850 */ float kb_applied;
src/melee/ft/types.h lines 1660–1663 at f0cdbb0 · upstream ↗ 2852 forceAppliedOnHit = fp->dmg.kb_applied; ⋮ 2859 ftCo_Damage_CalcKnockback(fp);
src/melee/ft/fighter.c lines 2852–2859 at f0cdbb0 · upstream ↗ 118void ftCo_Damage_CalcKnockback(Fighter* fp) ⋮ 120 if (!fp->dmg.kb_applied) { 121 return; ⋮ 123 if (fp->motion_id == ftCo_MS_Squat || fp->motion_id == ftCo_MS_SquatWait) { 124 fp->dmg.kb_applied *= p_ftCommonData->kb_squat_mul; ⋮ 126 if (fp->motion_id == ftCo_MS_DamageIce) { 127 fp->dmg.kb_applied *= p_ftCommonData->kb_ice_mul; ⋮ 129 if (fp->smash_attrs.state == SmashState_Charging) { 130 fp->dmg.kb_applied *= p_ftCommonData->kb_smashcharge_mul; ⋮ 132 if (fp->x34_scale.y != 1) { 133 fp->dmg.kb_applied = ftCo_CalcYScaledKnockback( 134 fp->dmg.kb_applied, fp->x34_scale.y, Fighter_804D6524->x0); ⋮
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 118–146 at f0cdbb0 · upstream ↗ 1451f32 ftParamGetCommonKnockback(s32 percent_damage, s32 recent_damage, s32 hit_damage, s32 knockback_weight, s32 knockback_scale, s32 knockback_base, f32 weight, s32 attack_handicap, s32 defend_handicap) ⋮ 1457 knockback = ( ( ( ( ( ( 1 + ( 10.0F * knockback_weight * 0.05F ) ) * weight * 1.4F ) + 18.0F ) * ( knockback_scale * 0.01F ) ) + knockback_base ) * ( gSCManagerBattleState->damage_ratio * 0.01F ) * dFTCommonDataHandicapTable[attack_handicap - 1][0] ) * dFTCommonDataHandicapTable[defend_handicap - 1][1]; ⋮ 1463 knockback = ( ( ( ( ( ( ( damage_add * 0.1F ) + ( damage_add * hit_damage * 0.05F ) ) * weight * 1.4F ) + 18.0F ) * ( knockback_scale * 0.01F ) ) + knockback_base ) * ( gSCManagerBattleState->damage_ratio * 0.01F ) * dFTCommonDataHandicapTable[attack_handicap - 1][0] ) * dFTCommonDataHandicapTable[defend_handicap - 1][1]; ⋮ 1465 if (knockback >= 2500.0F) ⋮ 1467 knockback = 2500.0F;
src/ft/ftparam.c lines 1451–1468 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 NTSC 1.02 version of Super Smash Bros. Melee,
ftCo_8008DCE0, the routine that puts a hit fighter into a Damage status, sets the unnamed countmv.co.damage.x0to the knockback (kb_applied) timesp_ftCommonData->x154, a value from the disc file PlCo.dat, truncated to a whole number, and to 1 if that comes to 0. It also sets the flagx221C_b6, whichftLib_IsInHitstunreturns. Where Super Smash Bros. divides the knockback by 1.875 (ssb64/hitstun), Melee multiplies it by a value the code doesn't hold. The animation routines of the Damage statuses (75 to 86) and the DamageFly statuses (87 to 90) take 1 off the count while it's above 0 (ftCo_8008F744) and clear the flag once it's 0 or below; the status ends when its animation has run out with the flag clear. While the flag is set, their interrupt routines run onlydoIasa, as the decompilers name it, in place of the wait, fall, or hammer checks, so the fighter can't act, with one exception: after a hit whose angleftColl_8007AC68accepts (betweenunk_kb_angle_minandunk_kb_angle_max), once an unnamed countdown from c_7F0 runs out, an airborne fighter moving down can leave through an air up special (ftCo_800D69C4) or an air jump (ftCo_800CB8E0), which the atlas reads as the meteor cancel. A jump pressed in hitstun otherwise only records the count left. While the flag is set an airborne fighter gets gravity andaerial_friction(ft_80084EEC) in place of fast-fall and drift (ft_80084DB0). A change of motion state clears the flag unless the new state is entered withFt_MF_SkipHitStun. The DamageFlyRoll status's own routines aren't read here.Codedoldecomp/melee · VetriTheRetri/ssb-decomp-rerevisedHow we know
263void ftCo_8008DCE0(Fighter_GObj* gobj, int arg1, float facing_dir)src/melee/ft/kinds/ftCommon/ftCo_Damage.c line 263 at f0cdbb0 · upstream ↗ 282 float kb_applied = fp->dmg.kb_applied; ⋮ 287 scaled_kb_154 = kb_applied * p_ftCommonData->x154; 288 fp->mv.co.damage.x0 = (int) scaled_kb_154; 289 if (!fp->mv.co.damage.x0) { 290 fp->mv.co.damage.x0 = 1;
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 282–291 at f0cdbb0 · upstream ↗ 61int ftCo_803C5520[2][4][3] = { ⋮ 63 { 81, 78, 75 }, 64 { 82, 79, 76 }, 65 { 83, 80, 77 }, 66 { 89, 88, 87 }, ⋮ 69 { 84, 84, 84 }, 70 { 85, 85, 85 }, 71 { 86, 86, 86 }, 72 { 89, 88, 87 },
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 60–73 at f0cdbb0 · upstream ↗ 405 Fighter_ChangeMotionState(gobj, msid, 0x40U, 0, 1, 0, NULL);src/melee/ft/kinds/ftCommon/ftCo_Damage.c line 405 at f0cdbb0 · upstream ↗ 423 fp->x221C_b6 = true;src/melee/ft/kinds/ftCommon/ftCo_Damage.c line 423 at f0cdbb0 · upstream ↗ 665bool ftLib_IsInHitstun(HSD_GObj* gobj) ⋮ 667 Fighter* fp = GET_FIGHTER(gobj); 668 return fp->x221C_b6;
src/melee/ft/ftlib.c lines 665–669 at f0cdbb0 · upstream ↗ 843void ftCo_8008F744(Fighter_GObj* gobj) ⋮ 845 Fighter* fp = GET_FIGHTER(gobj); 846 if (fp->mv.co.damage.x0 > 0) { 847 fp->mv.co.damage.x0 -= 1; ⋮ 849 if (fp->x221C_b6) { 850 if (fp->mv.co.damage.x0 <= 0) { 851 fp->x221C_b6 = false;
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 843–852 at f0cdbb0 · upstream ↗ 872void ftCo_Damage_Anim(Fighter_GObj* gobj) ⋮ 874 Fighter* fp = GET_FIGHTER(gobj); 875 ftCo_8008F744(gobj); 876 if (!ftAnim_IsFramesRemaining(gobj) && !fp->x221C_b6) {
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 872–876 at f0cdbb0 · upstream ↗ 890bool doIasa(Fighter_GObj* gobj) ⋮ 892 Fighter* fp = gobj->user_data; 893 if (fp->mv.co.damage.x1A) { 894 if (fp->mv.co.damage.x1B) { 895 --fp->mv.co.damage.x1B; ⋮ 897 if (!fp->mv.co.damage.x1B && fp->ground_or_air == GA_Air && 898 fp->x8c_kb_vel.y < 0 && 899 (ftCo_800D69C4(gobj) || ftCo_800CB8E0(gobj))) ⋮ 905 return true; ⋮ 909 if (ftCo_Jump_GetInput(gobj)) { 910 fp->mv.co.damage.x14 = fp->mv.co.damage.x0; 911 return true; ⋮
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 890–914 at f0cdbb0 · upstream ↗ 916void ftCo_Damage_IASA(Fighter_GObj* gobj) ⋮ 918 Fighter* fp = gobj->user_data; 919 if (!fp->x221C_b6) { 920 if (ftCo_800C5240(gobj)) { 921 if (fp->ground_or_air == GA_Air) { 922 ftCo_HammerFall_IASA(gobj); 923 } else { 924 ftCo_HammerWait_IASA(gobj); ⋮ 926 } else { ⋮ 932 if (fp->ground_or_air == GA_Air) { 933 ftCo_Fall_IASA_Inner(gobj); 934 } else { ⋮
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 916–941 at f0cdbb0 · upstream ↗ 79float ftCo_Damage_CalcAngle(Fighter* fp, float f) ⋮ 81 if (fp->dmg.x1848_kb_angle != 361) { 82 if (ftColl_8007AC68(fp->dmg.x1848_kb_angle)) { 83 fp->mv.co.damage.x1A = 1; 84 fp->mv.co.damage.x1B = p_ftCommonData->x7F0;
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 79–85 at f0cdbb0 · upstream ↗ 312 fp->mv.co.damage.x1A = 0; 313 fp->mv.co.damage.x14 = 0; 314 kb_angle = ftCo_Damage_CalcAngle(fp, kb_applied);
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 312–314 at f0cdbb0 · upstream ↗ 2481bool ftColl_8007AC68(u32 kb_angle) ⋮ 2483 if (kb_angle != 361 && p_ftCommonData->unk_kb_angle_min <= kb_angle && 2484 kb_angle <= p_ftCommonData->unk_kb_angle_max) ⋮ 2486 return true; ⋮ 2488 return false;
src/melee/ft/ftcoll.c lines 2481–2489 at f0cdbb0 · upstream ↗ 103bool ftCo_800D69C4(Fighter_GObj* gobj) ⋮ 110 ftData_SpecialAirHi[fp->kind](gobj); 111 return true;
src/melee/ft/kinds/ftCommon/ftCo_Attack100.c lines 103–111 at f0cdbb0 · upstream ↗ 73bool ftCo_800CB8E0(Fighter_GObj* gobj) ⋮ 83 return ftCo_JumpAerial_CheckInput(gobj, true);
src/melee/ft/kinds/ftCommon/ftCo_JumpAerial.c lines 73–83 at f0cdbb0 · upstream ↗ 943void ftCo_Damage_Phys(Fighter_GObj* gobj) ⋮ 945 Fighter* fp = gobj->user_data; 946 if (fp->ground_or_air == GA_Air) { 947 if (!fp->x221C_b6) { 948 ft_80084DB0(gobj); 949 } else { 950 ft_80084EEC(gobj);
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 943–951 at f0cdbb0 · upstream ↗ 34void ft_80084EEC(Fighter_GObj* gobj) ⋮ 39 ftCommon_Fall(fp, co_attrs->gravity, co_attrs->terminal_velocity); 40 ftCommon_CalcSelfAccel_Deaccel(fp, co_attrs->aerial_friction);
src/melee/ft/ft_084E.c lines 34–41 at f0cdbb0 · upstream ↗ 1371void ft_80084DB0(Fighter_GObj* gobj) ⋮ 1376 ftCommon_CheckFallFast(fp); 1377 if (fp->fall_fast) { 1378 ftCommon_FallFast(fp); ⋮ 1382 ftCommon_CalcSelfAccel_Drift(fp);
src/melee/ft/ft_081B.c lines 1371–1382 at f0cdbb0 · upstream ↗ 1032void ftCo_DamageFly_Anim(Fighter_GObj* gobj) ⋮ 1036 ftCo_8008F744(gobj); 1037 if (!ftAnim_IsFramesRemaining(gobj) && !fp->x221C_b6) { ⋮ 1044void ftCo_DamageFly_IASA(Fighter_GObj* gobj) ⋮ 1046 if (!GET_FIGHTER(gobj)->x221C_b6) { 1047 ftCo_DamageFall_IASA(gobj); 1048 } else { 1049 RETURN_IF(doIasa(gobj));
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 1032–1050 at f0cdbb0 · upstream ↗ 1062static void inlineE0(Fighter_GObj* gobj) ⋮ 1064 Fighter* fp = GET_FIGHTER(gobj); 1065 if (!fp->x221C_b6) { 1066 ft_80084DB0(gobj); 1067 } else { 1068 ft_80084EEC(gobj);
src/melee/ft/kinds/ftCommon/ftCo_Damage.c lines 1062–1070 at f0cdbb0 · upstream ↗ 960 // ftCo_MS_DamageHi1 = 75 961 ftCo_SM_DamageHi1, 962 ftCo_MF_Damage, 963 FtMoveId_Default << 24, 964 ftCo_Damage_Anim, 965 ftCo_Damage_IASA, 966 ftCo_Damage_Phys,
src/melee/ft/ftmotionstates.c lines 960–966 at f0cdbb0 · upstream ↗ 1092 // ftCo_MS_DamageFlyHi = 87 ⋮ 1096 ftCo_DamageFly_Anim, 1097 ftCo_DamageFly_IASA, 1098 ftCo_DamageFly_Phys,
src/melee/ft/ftmotionstates.c lines 1092–1098 at f0cdbb0 · upstream ↗ 1035 if (((flags & Ft_MF_SkipHitStun) == 0) && (fp->x221C_b6 != 0U)) { 1036 fp->x221C_b6 = 0;
src/melee/ft/fighter.c lines 1035–1037 at f0cdbb0 · upstream ↗ 1505f32 ftParamGetHitStun(f32 knockback) ⋮ 1507 return knockback / 1.875F;
src/ft/ftparam.c lines 1505–1508 at 572a747 · 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.
- ^In the NTSC 1.02 version of Super Smash Bros. Melee, a fighter's
shield_healthis a float that starts atx260_startShieldHealth. Each timeFighter_procCollResolveruns for a fighter that isn't asleep (is_sleeping), a fighter whose unnamed flagx221A_b7is clear regains c_27C, up to the start value. That flag is set when the guard statuses switch on the shield's collision (ftColl_8007B1B8), and the atlas reads it as "shield up". While it's set, the fighter instead loses c_284 × s × (1 − (l·(c_2E0 − c_2DC) + c_2DC)) + c_288, where s isx19A0_shieldDamageTaken, each shield hit's damage plus its unnamedx34(a fighter's hit counts only while the flagx221C_b2, set on enteringftCo_MS_GuardReflect, is clear), and l islightshield_amount. Below 0, the health is set tox280_unkShieldHealth, and on the hit path the shield break (ftCo_80098B20, which entersftCo_MS_ShieldBreakFly) starts only in the branch taken when the fighter has no knockback to apply (kb_appliedis 0), the unnamedx18a0is 0, and a shield hit is recorded (x19A4). While the fighter holds the shield, the animation routines offtCo_MS_GuardOnandftCo_MS_GuardcallftCo_800925A4, which, whilex221B_b0is set, sets l from the analog trigger past its deadzone, (trigger − deadzone) / (1 − deadzone), keeping the old value when that's negative, and takes c_278 × (l·(c_2F0 − c_2EC) + c_2EC) off the health; below 0 it sets the health to 0 and starts the shield break. Every c is a field ofp_ftCommonData, from the disc file PlCo.dat, so the numbers aren't in the code. Where Super Smash Bros. counts whole points from a fixed 55 and resets to 30, with no say for how hard the button is pressed (ssb64/shield), Melee's wear while held and its damage from hits both depend on l.Codedoldecomp/melee · VetriTheRetri/ssb-decomp-rerevisedHow we know
420 fp->shield_health = p_ftCommonData->x260_startShieldHealth;src/melee/ft/fighter.c line 420 at f0cdbb0 · upstream ↗ 1741 /* fp+1998 */ float shield_health; 1742 /* fp+199C */ float lightshield_amount; 1743 /* fp+19A0 */ s32 x19A0_shieldDamageTaken;
src/melee/ft/types.h lines 1741–1743 at f0cdbb0 · upstream ↗ 2806void Fighter_procCollResolve(Fighter_GObj* gobj) ⋮ 2816 if (!fp->is_sleeping) { 2817 if (!fp->x221A_b7) { 2818 if (fp->shield_health < p_ftCommonData->x260_startShieldHealth) { 2819 fp->shield_health += p_ftCommonData->x27C; 2820 if (fp->shield_health > p_ftCommonData->x260_startShieldHealth) ⋮ 2822 fp->shield_health = p_ftCommonData->x260_startShieldHealth; ⋮ 2827 if (fp->x221A_b7) { 2828 fp->shield_health -= 2829 (p_ftCommonData->x284 * 2830 ((fp->x19A0_shieldDamageTaken) * 2831 (1.0f - ((fp->lightshield_amount * ⋮
src/melee/ft/fighter.c lines 2806–2842 at f0cdbb0 · upstream ↗ 2853 if (forceAppliedOnHit) {src/melee/ft/fighter.c line 2853 at f0cdbb0 · upstream ↗ 2907 } else if (fp->dmg.x18a0) { ⋮ 2910 } else if (fp->x19A4) { 2911 if (bool3) { 2912 ftCo_80098B20(gobj);
src/melee/ft/fighter.c lines 2907–2912 at f0cdbb0 · upstream ↗ 21void ftCo_80098B20(Fighter_GObj* gobj) ⋮ 25 Fighter_ChangeMotionState(gobj, ftCo_MS_ShieldBreakFly, Ft_MF_Unk06, 0, 1,
src/melee/ft/kinds/ftCommon/ftCo_ShieldBreakFly.c lines 21–26 at f0cdbb0 · upstream ↗ 301 if (!fp1->x221C_b2) { 302 int tmp_dmg = int_dmg + hit0->x34; 303 PAD_STACK(4); 304 fp1->x19A0_shieldDamageTaken += tmp_dmg < 0 ? 0 : tmp_dmg;
src/melee/ft/ftcoll.c lines 301–304 at f0cdbb0 · upstream ↗ 763 int total = dmg + hurt->x34; ⋮ 770 fp->x19A0_shieldDamageTaken += clamped_total;
src/melee/ft/ftcoll.c lines 763–770 at f0cdbb0 · upstream ↗ 899void ftCo_8009388C(HSD_GObj* gobj) ⋮ 902 Fighter_ChangeMotionState(gobj, ftCo_MS_GuardReflect, ⋮ 910 fp->x221C_b2 = true;
src/melee/ft/kinds/ftCommon/ftCo_Guard.c lines 899–910 at f0cdbb0 · upstream ↗ 507void ftCo_80092908(Fighter_GObj* gobj) ⋮ 510 Fighter_ChangeMotionState(gobj, ftCo_MS_Guard, Ft_MF_SkipAnim, 0, 1, 0, ⋮ 523 ftColl_8007B1B8(gobj, (ShieldDesc*) &absorb, ftCo_80092E50); 524 fp2->x221A_b7 = true;
src/melee/ft/kinds/ftCommon/ftCo_Guard.c lines 507–526 at f0cdbb0 · upstream ↗ 2651void ftColl_8007B1B8(Fighter_GObj* gobj, ShieldDesc* shield, HSD_GObjEvent cb) ⋮ 2653 Fighter* fp = GET_FIGHTER(gobj); 2654 fp->x221B.x221B_b0 = true;
src/melee/ft/ftcoll.c lines 2651–2654 at f0cdbb0 · upstream ↗ 400bool ftCo_800925A4(HSD_GObj* gobj) ⋮ 404 if (fp->x221B.x221B_b0) { 405 fp->mv.co.guard.x2C = fp->lightshield_amount; ⋮ 407 fp->lightshield_amount = 408 (fp->input.triggers[0] - 409 p_ftCommonData->analog_shoulder_deadzone) / 410 (1 - p_ftCommonData->analog_shoulder_deadzone) < ⋮ 412 ? fp->mv.co.guard.x2C 413 : (fp->input.triggers[0] - 414 p_ftCommonData->analog_shoulder_deadzone) / 415 (1 - p_ftCommonData->analog_shoulder_deadzone); ⋮ 417 fp->shield_health -= p_ftCommonData->x278 * ⋮
src/melee/ft/kinds/ftCommon/ftCo_Guard.c lines 400–427 at f0cdbb0 · upstream ↗ 440void ftCo_GuardOn_Anim(Fighter_GObj* gobj) ⋮ 442 Fighter* fp = gobj->user_data; 443 fp->mv.co.guard.x0 += 1; 444 if (ftCo_800925A4(gobj) == 0) {
src/melee/ft/kinds/ftCommon/ftCo_Guard.c lines 440–444 at f0cdbb0 · upstream ↗ 530void ftCo_Guard_Anim(Fighter_GObj* gobj) ⋮ 535 if (!ftCo_800925A4(gobj)) {
src/melee/ft/kinds/ftCommon/ftCo_Guard.c lines 530–535 at f0cdbb0 · upstream ↗ 2093 // ftCo_MS_GuardOn = 178 ⋮ 2097 ftCo_GuardOn_Anim, ⋮ 2104 // ftCo_MS_Guard = 179 ⋮ 2108 ftCo_Guard_Anim,
src/melee/ft/ftmotionstates.c lines 2093–2108 at f0cdbb0 · upstream ↗ 431 fp->shield_health = (fp->fkind == nFTKindYoshi) ? 55 : 55;src/ft/ftmanager.c line 431 at 572a747 · upstream ↗ 3837 if (!(fp->is_shield) && (fp->shield_health < 55)) ⋮ 3848 fp->shield_health -= fp->shield_damage_total; ⋮ 3850 if (fp->shield_health <= 0) ⋮ 3852 fp->shield_health = (fp->fkind == nFTKindYoshi) ? 30 : 30;
src/ft/ftmain.c lines 3837–3854 at 572a747 · 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.
- ^In the NTSC 1.02 version of Super Smash Bros. Melee, an aerial attack (statuses
ftCo_MS_AttackAirNtoftCo_MS_AttackAirLw) that touches down callsftCo_LandingAir_EnterWithLagfrom its collision routineftCo_AttackAir_Coll, throughft_80082C74, which calls it when the unnamedft_80081D0Creturns true. If the move's command script has setcmd_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_lagand the four like it), and the animation plays at a rate of (ftAnim_8006F484+ 0.1) / lag, whereftAnim_8006F484returns the animation's end frame. If the unnamed countx67Fis 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 arep_ftCommonDatafields from PlCo.dat, so the window and divisor aren't in the code.Fighter_procInputsetsx67Fto 0 on an update where theHSD_PAD_LRbit 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 unlessgm_GetDbPauseFlag(0)is true, and it's off while the unnamedgm_8016B0FCis true. Withoutcmd_vars[0], the fighter takes the basic landing (ftCo_Landing_Enter_Basic). Super Smash Bros. reads the same moment differently (ftCommonAttackAirProcMap): when the aerial'sflag1is 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-reHow 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.
Sources
Code
- doldecomp. 2026. “melee: a decompilation of Super Smash Bros. Melee (doldecomp/melee).” Commit f0cdbb0. doldecomp/melee @ f0cdbb0 · licence, all uses
- VetriTheRetri. 2026. “ssb-decomp-re: a decompilation of Super Smash Bros. (VetriTheRetri/ssb-decomp-re).” Commit 572a747. VetriTheRetri/ssb-decomp-re @ 572a747 · licence, all uses