-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Ability Switcher via special
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:
In data\specials.inc
:
def_special CountPartyAliveNonEggMons
def_special TryPrepareSecondApproachingTrainer
def_special RemoveRecordsWindow
def_special CloseDeptStoreElevatorWindow
def_special TrySetBattleTowerLinkType
+ def_special SwitchMonAbility
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!