Hidden Ability Documentation - BluRosie/hg-engine GitHub Wiki

Hidden Ability Documentation

Usage In-Game

In include/config.h, there is a define for HIDDEN_ABILITIES_FLAG. By default, this is 2600, a free and unused flag in vanilla HG.

When set, this flag allows for the next Pokémon generated by scripts with the GivePokemon, WildBattleSp, GiveEgg, and GiveTogepiEgg script commands. It is immediately unset to prevent any unintended hidden abilities from appearing.

Additionally, for starters only, there is HIDDEN_ABILITIES_STARTERS_FLAG (by default 2601). This flag will give starters their hidden abilities when active. It is not unset, but it can be used as a normal story flag as it is not used for anything else later on.

Code Documentation

In vanilla HG, there are a number of fields in a Pokémon's data structure that are unused. For some reason, GF devs were thorough and made sure they were still accessible through the GetMonData and SetMonData functions. In substructure 2 of the BoxMonData structure, there is 18 bits at the end that go unused, a u8:2 and a u16, which are accessed through SetMonData parameter MON_DATA_RESERVED_113 and MON_DATA_RESERVED_114, respectively.

The least significant bit is taken from MON_DATA_RESERVED_113 and used as a second abilityslot flag of sorts to tell the engine when setting the ability that the hidden ability should be set. The hidden ability is generated in a new file that is placed in a028. This table is generated by data/HiddenAbilityTable.c. An empty entry of ABILITY_NONE will default to the two abilities defined in the personal structure in armips/data/mondata.s as well as default handling. The hidden ability bit takes precedence over the ability slot determination.

The way chosen to go about letting the player manipulate this is to use a script flag HIDDEN_ABILITIES_FLAG, configurable in include/config.h. By default, it is 2600, an initially free and unused flag. This is automatically unset when a Pokémon's hidden ability is set this way. This is done to prevent form changes and other code from inadvertently setting the hidden ability bit in battles and other such things. This script flag affects Pokémon given by scripts from GivePokemon, WildBattleSp, GiveEgg, and GiveTogepiEgg script commands.

For example, if I wanted to give myself an Alolan Sandshrew with its hidden ability Slush Rush and fight against a Shiny Galarian Darmanitan with its hidden ability Zen Mode, I could write a script such as:

DSPRE nomenclature:
...
SetFlag 2600
GivePokemon 27 10 0 1 0 0x800C
SetFlag 2600
WildBattleSp 0xA5D 10 1
...

pokeheartgold nomenclature:
...
setflag HIDDEN_ABILITIES_FLAG
give_mon SPECIES_SANDSHREW, 10, ITEM_NONE, 1, ABILITY_NONE, 0x800C
setflag HIDDEN_ABILITIES_FLAG
wild_battle (1 << 11) | SPECIES_DARMANITAN, 10, 1
...

For trainers, setting the abilityslot field to a value of 2 will give the Pokémon its hidden ability. This is recommended over using the ability override, as form changes that change abilities need to take the hidden ability bit into account.

In the event that you are looking to code access to the hidden ability in a PartyPokemon structure, the best way to access the hidden ability bit is:

u32 doesMonHaveHiddenAbility = GetMonData(partyPokemon, MON_DATA_RESERVED_113, NULL) & 1;

Because there is no separation between this bit and the rest of the bits in MON_DATA_RESERVED_113, the best way to set this bit would then be something like:

u16 dummy_p2_2 = GetMonData(partyPokemon, MON_DATA_RESERVED_113, NULL);
dummy_p2_2 |= 1;
SetMonData(partyPokemon, MON_DATA_RESERVED_113, &dummy_p2_2);

There are macros for this for both partyPokemon and boxPokemon:

u32 var = GET_MON_HIDDEN_ABILITY_BIT(mon);
SET_MON_HIDDEN_ABILTY_BIT(mon);
//and
u32 var = GET_BOX_MON_HIDDEN_ABILITY_BIT(mon);
SET_BOX_MON_HIDDEN_ABILTY_BIT(boxmon);

Hidden abilities are not currently passed through breeding subject to further research.