diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index d5a410168..f10c1e364 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -311,6 +311,7 @@ #define EVOS_PER_MON 10 // Form change types +#define FORM_CHANGE_END 0 #define FORM_ITEM_HOLD 1 #define FORM_ITEM_USE 2 #define FORM_MOVE 3 diff --git a/include/pokemon.h b/include/pokemon.h index cd45d56c0..3fe9c66df 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -440,5 +440,5 @@ void sub_806F47C(u8 id); u8 *sub_806F4F8(u8 id, u8 arg1); u16 GetFormSpeciesId(u16 speciesId, u8 formId); u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId); - +u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); #endif // GUARD_POKEMON_H diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index 3ec9952cf..777b174a4 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -1,4 +1,4 @@ -const struct FormChange *gFormChangeTablePointers[POKEMON_SLOTS_NUMBER] = +const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = { [SPECIES_GIRATINA] = sGiratinaFormChangeTable, [SPECIES_SHAYMIN] = sShayminFormChangeTable, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index a5bba1cb6..dd5e1e7b0 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -22,26 +22,25 @@ FORM_WITHDRAW: no parameters */ -#define FORM_CHANGE_END 0 #define WHEN_LEARNED FALSE #define WHEN_FORGOTTEN TRUE -const struct FormChange sGiratinaFormChangeTable[] = { +static const struct FormChange sGiratinaFormChangeTable[] = { {FORM_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB}, {FORM_CHANGE_END}, }; -const struct FormChange sShayminFormChangeTable[] = { +static const struct FormChange sShayminFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA}, {FORM_CHANGE_END}, }; -const struct FormChange sShayminSkyFormChangeTable[] = { +static const struct FormChange sShayminSkyFormChangeTable[] = { {FORM_WITHDRAW, SPECIES_SHAYMIN}, {FORM_CHANGE_END}, }; -const struct FormChange sArceusFormChangeTable[] = { +static const struct FormChange sArceusFormChangeTable[] = { {FORM_ITEM_HOLD, SPECIES_ARCEUS, ITEM_NONE, ABILITY_MULTITYPE}, {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIST_PLATE, ABILITY_MULTITYPE}, {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIGHTINIUM_Z, ABILITY_MULTITYPE}, @@ -80,47 +79,47 @@ const struct FormChange sArceusFormChangeTable[] = { {FORM_CHANGE_END}, }; -const struct FormChange sTornadusFormChangeTable[] = { +static const struct FormChange sTornadusFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; -const struct FormChange sTornadusTherianFormChangeTable[] = { +static const struct FormChange sTornadusTherianFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; -const struct FormChange sThundurusFormChangeTable[] = { +static const struct FormChange sThundurusFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; -const struct FormChange sThundurusTherianFormChangeTable[] = { +static const struct FormChange sThundurusTherianFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; -const struct FormChange sLandorusFormChangeTable[] = { +static const struct FormChange sLandorusFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; -const struct FormChange sLandorusTherianFormChangeTable[] = { +static const struct FormChange sLandorusTherianFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, {FORM_CHANGE_END}, }; -const struct FormChange sKeldeoFormChangeTable[] = { +static const struct FormChange sKeldeoFormChangeTable[] = { {FORM_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, {FORM_CHANGE_END}, }; -const struct FormChange sKeldeoResoluteFormChangeTable[] = { +static const struct FormChange sKeldeoResoluteFormChangeTable[] = { {FORM_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, {FORM_CHANGE_END}, }; -const struct FormChange sGenesectFormChangeTable[] = { +static const struct FormChange sGenesectFormChangeTable[] = { {FORM_ITEM_HOLD, SPECIES_GENESECT, ITEM_NONE}, {FORM_ITEM_HOLD, SPECIES_GENESECT_DOUSE_DRIVE, ITEM_DOUSE_DRIVE}, {FORM_ITEM_HOLD, SPECIES_GENESECT_SHOCK_DRIVE, ITEM_SHOCK_DRIVE}, @@ -128,17 +127,17 @@ const struct FormChange sGenesectFormChangeTable[] = { {FORM_ITEM_HOLD, SPECIES_GENESECT_CHILL_DRIVE, ITEM_CHILL_DRIVE}, }; -const struct FormChange sHoopaFormChangeTable[] = { +static const struct FormChange sHoopaFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, {FORM_CHANGE_END}, }; -const struct FormChange sHoopaUnboundFormChangeTable[] = { +static const struct FormChange sHoopaUnboundFormChangeTable[] = { {FORM_WITHDRAW, SPECIES_HOOPA}, {FORM_CHANGE_END}, }; -const struct FormChange sOricorioFormChangeTable[] = { +static const struct FormChange sOricorioFormChangeTable[] = { {FORM_ITEM_USE, SPECIES_ORICORIO, ITEM_RED_NECTAR}, {FORM_ITEM_USE, SPECIES_ORICORIO_POM_POM, ITEM_YELLOW_NECTAR}, {FORM_ITEM_USE, SPECIES_ORICORIO_PAU, ITEM_PINK_NECTAR}, @@ -146,7 +145,7 @@ const struct FormChange sOricorioFormChangeTable[] = { {FORM_CHANGE_END}, }; -const struct FormChange sSilvallyFormChangeTable[] = { +static const struct FormChange sSilvallyFormChangeTable[] = { {FORM_ITEM_HOLD, SPECIES_SILVALLY, ITEM_NONE, ABILITY_RKS_SYSTEM}, {FORM_ITEM_HOLD, SPECIES_SILVALLY_BUG, ITEM_BUG_MEMORY, ABILITY_RKS_SYSTEM}, {FORM_ITEM_HOLD, SPECIES_SILVALLY_DARK, ITEM_DARK_MEMORY, ABILITY_RKS_SYSTEM}, @@ -167,6 +166,5 @@ const struct FormChange sSilvallyFormChangeTable[] = { {FORM_ITEM_HOLD, SPECIES_SILVALLY_WATER, ITEM_WATER_MEMORY, ABILITY_RKS_SYSTEM}, }; -#undef FORM_CHANGE_END #undef WHEN_LEARNED #undef WHEN_FORGOTTEN diff --git a/src/pokemon.c b/src/pokemon.c index ec84c05c2..fcb94204a 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -1847,8 +1847,9 @@ const s8 gNatureStatTable[NUM_NATURES][NUM_NATURE_STATS] = #include "data/pokemon/evolution.h" #include "data/pokemon/level_up_learnset_pointers.h" #include "data/pokemon/form_species_tables.h" -#include "data/pokemon/form_change_tables.h" #include "data/pokemon/form_species_table_pointers.h" +#include "data/pokemon/form_change_tables.h" +#include "data/pokemon/form_change_table_pointers.h" // SPECIES_NONE are ignored in the following two tables, so decrement before accessing these arrays to get the right result @@ -7880,3 +7881,38 @@ u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId) } return targetFormId; } + +// returns SPECIES_NONE if no form change is possible +u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg) +{ + u32 i; + u16 targetSpecies = SPECIES_NONE; + u16 originalSpecies = GetMonData(mon, MON_DATA_SPECIES, NULL); + const struct FormChange *formChanges = gFormChangeTablePointers[originalSpecies]; + if (formChanges == NULL) + return SPECIES_NONE; + + for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) { + if (method == formChanges[i].method) { + u32 ability = GetAbilityBySpecies(originalSpecies, GetMonData(mon, MON_DATA_ABILITY_NUM, NULL)); + switch (method) + { + case FORM_ITEM_HOLD: + if (GetMonData(mon, MON_DATA_HELD_ITEM, NULL) == formChanges[i].param1 && (ability == formChanges[i].param2 || formChanges[i].param2 == ABILITY_NONE)) + break; + case FORM_ITEM_USE: + if (arg == formChanges[i].param1 && (ability == formChanges[i].param2 || formChanges[i].param2 == ABILITY_NONE)) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_MOVE: + if (MonKnowsMove(mon, formChanges[i].param1) != formChanges[i].param2) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_WITHDRAW: + targetSpecies = formChanges[i].targetSpecies; + break; + } + } + } + return originalSpecies != targetSpecies ? targetSpecies : SPECIES_NONE; +}