Skip to content

Ability Switcher via special

Scyrous edited this page Aug 19, 2024 · 2 revisions

This scripting special lets you switch between a Pokémon's two ability slots. For instance, a Steelix with Sturdy will have Rock Head after using this special - and vice versa. If the second slot is ABILITY_NONE, meaning the Pokémon has no alternative ability, the special will do nothing. This also holds true for the handful of Pokémon who have two identical abilities (this happens when their pre-evolved form does have two different abilities). Keep in mind that forcefully replacing a Pokémon's ability with this method will cause a PID mismatch, which is relevant if you care about having ''legal'' Pokémon and/or compatibility with other games.

The Pokémon is meant to be selected in a script with special ChoosePartyMon. The resulting species is then stored in gSpecialVar_0x8004, at which point you'd use special SwitchMonAbility to change its ability.

Alternatively, you can use something like GetLeadMonIndex() to automatically select the first Pokémon in your party, if you prefer.

Example:

Sturdy Rock Head


1. Define special

In data\specials.inc:

     def_special CountPartyAliveNonEggMons
     def_special TryPrepareSecondApproachingTrainer
     def_special RemoveRecordsWindow
     def_special CloseDeptStoreElevatorWindow
     def_special TrySetBattleTowerLinkType
+    def_special SwitchMonAbility

2. Add special

Since our special references ABILITY_NONE at one point, we need to include the relevant header file.

In src\field_specials.c:

 #include "constants/battle_frontier.h"
 #include "constants/weather.h"
 #include "constants/metatile_labels.h"
 #include "palette.h"
+#include "constants/abilities.h"

Add this function at the end of the file:

void SwitchMonAbility(void)
{
    u16 species = GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPECIES, NULL);
    u8 currentAbilityNum = GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_ABILITY_NUM, NULL);

    if (gSpeciesInfo[species].abilities[1] != 0 && gSpeciesInfo[species].abilities[0] != gSpeciesInfo[species].abilities[1])
    {
        u8 newAbilityNum = !currentAbilityNum;
        SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_ABILITY_NUM, &newAbilityNum);
    }
}

In short: we first retrieve the selected Pokémon's species and current ability using GetMonData. We then check if the second ability is not ABILITY_NONE and if it differs from the first ability. If both conditions are true, we switch the ability by setting newAbilityNum to the opposite of currentAbilityNum and update the Pokémon's ability using SetMonData.

And that's it!

Clone this wiki locally