diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 61276158b9..5fc78df332 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -348,6 +348,13 @@ #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 +#define FORM_WITHDRAW 4 + // Evolution 'modes,' for GetEvolutionTargetSpecies #define EVO_MODE_NORMAL 0 #define EVO_MODE_TRADE 1 diff --git a/include/constants/pokemon_config.h b/include/constants/pokemon_config.h index a14ac688a9..c6e6a269f7 100644 --- a/include/constants/pokemon_config.h +++ b/include/constants/pokemon_config.h @@ -95,6 +95,78 @@ #define ITEM_RAZOR_FANG ITEM_NONE #define ITEM_RAZOR_CLAW ITEM_NONE #define ITEM_OVAL_STONE ITEM_NONE -#endif + +//FORM_ITEM_HOLD +#define ITEM_GRISEOUS_ORB ITEM_NONE +#define ITEM_DRACO_PLATE ITEM_NONE +#define ITEM_DREAD_PLATE ITEM_NONE +#define ITEM_EARTH_PLATE ITEM_NONE +#define ITEM_FIST_PLATE ITEM_NONE +#define ITEM_FLAME_PLATE ITEM_NONE +#define ITEM_ICICLE_PLATE ITEM_NONE +#define ITEM_INSECT_PLATE ITEM_NONE +#define ITEM_IRON_PLATE ITEM_NONE +#define ITEM_MEADOW_PLATE ITEM_NONE +#define ITEM_MIND_PLATE ITEM_NONE +#define ITEM_PIXIE_PLATE ITEM_NONE +#define ITEM_SKY_PLATE ITEM_NONE +#define ITEM_SPLASH_PLATE ITEM_NONE +#define ITEM_SPOOKY_PLATE ITEM_NONE +#define ITEM_STONE_PLATE ITEM_NONE +#define ITEM_TOXIC_PLATE ITEM_NONE +#define ITEM_ZAP_PLATE ITEM_NONE +#define ITEM_FIGHTINIUM_Z ITEM_NONE +#define ITEM_FLYINIUM_Z ITEM_NONE +#define ITEM_POISONIUM_Z ITEM_NONE +#define ITEM_GROUNDIUM_Z ITEM_NONE +#define ITEM_ROCKIUM_Z ITEM_NONE +#define ITEM_BUGINIUM_Z ITEM_NONE +#define ITEM_GHOSTIUM_Z ITEM_NONE +#define ITEM_STEELIUM_Z ITEM_NONE +#define ITEM_FIRIUM_Z ITEM_NONE +#define ITEM_WATERIUM_Z ITEM_NONE +#define ITEM_GRASSIUM_Z ITEM_NONE +#define ITEM_ELECTRIUM_Z ITEM_NONE +#define ITEM_PSYCHIUM_Z ITEM_NONE +#define ITEM_ICIUM_Z ITEM_NONE +#define ITEM_DRAGONIUM_Z ITEM_NONE +#define ITEM_DARKINIUM_Z ITEM_NONE +#define ITEM_FAIRIUM_Z ITEM_NONE +#define ITEM_DOUSE_DRIVE ITEM_NONE +#define ITEM_SHOCK_DRIVE ITEM_NONE +#define ITEM_BURN_DRIVE ITEM_NONE +#define ITEM_CHILL_DRIVE ITEM_NONE +#define ITEM_BUG_MEMORY ITEM_NONE +#define ITEM_DARK_MEMORY ITEM_NONE +#define ITEM_DRAGON_MEMORY ITEM_NONE +#define ITEM_ELECTRIC_MEMORY ITEM_NONE +#define ITEM_FAIRY_MEMORY ITEM_NONE +#define ITEM_FIGHTING_MEMORY ITEM_NONE +#define ITEM_FIRE_MEMORY ITEM_NONE +#define ITEM_FLYING_MEMORY ITEM_NONE +#define ITEM_GHOST_MEMORY ITEM_NONE +#define ITEM_GRASS_MEMORY ITEM_NONE +#define ITEM_GROUND_MEMORY ITEM_NONE +#define ITEM_ICE_MEMORY ITEM_NONE +#define ITEM_POISON_MEMORY ITEM_NONE +#define ITEM_PSYCHIC_MEMORY ITEM_NONE +#define ITEM_ROCK_MEMORY ITEM_NONE +#define ITEM_STEEL_MEMORY ITEM_NONE +#define ITEM_WATER_MEMORY ITEM_NONE + +//FORM_ITEM_USE +#define ITEM_GRACIDEA ITEM_NONE +// #define ITEM_REVEAL_GLASS ITEM_NONE +// #define ITEM_PRISON_BOTTLE ITEM_NONE +#define ITEM_RED_NECTAR ITEM_NONE +#define ITEM_YELLOW_NECTAR ITEM_NONE +#define ITEM_PINK_NECTAR ITEM_NONE +#define ITEM_PURPLE_NECTAR ITEM_NONE +#endif // ITEM_EXPANSION + +#ifndef BATTLE_ENGINE +#define ABILITY_MULTITYPE ABILITY_NONE +#define ABILITY_RKS_SYSTEM ABILITY_NONE +#endif // BATTLE_ENGINE #endif // GUARD_CONSTANTS_POKEMON_CONFIG_H diff --git a/include/item_use.h b/include/item_use.h index f577f8d464..3bc3c2226b 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -23,6 +23,8 @@ void ItemUseOutOfBattle_BlackWhiteFlute(u8); void ItemUseOutOfBattle_EvolutionStone(u8); void ItemUseOutOfBattle_Berry(u8); void ItemUseOutOfBattle_EnigmaBerry(u8); +void ItemUseOutOfBattle_FormChange(u8); +void ItemUseOutOfBattle_FormChange_ConsumedOnUse(u8); void ItemUseOutOfBattle_CannotUse(u8); void ItemUseInBattle_PokeBall(u8); void ItemUseInBattle_StatIncrease(u8); diff --git a/include/party_menu.h b/include/party_menu.h index 7f51d08c9f..75fe7b9583 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -59,6 +59,8 @@ void ItemUseCB_TMHM(u8 taskId, TaskFunc task); void ItemUseCB_RareCandy(u8 taskId, TaskFunc task); void ItemUseCB_SacredAsh(u8 taskId, TaskFunc task); void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task); +void ItemUseCB_FormChange(u8 taskId, TaskFunc task); +void ItemUseCB_FormChange_ConsumedOnUse(u8 taskId, TaskFunc task); u8 GetItemEffectType(u16 item); void CB2_PartyMenuFromStartMenu(void); void CB2_ChooseMonToGiveItem(void); diff --git a/include/pokemon.h b/include/pokemon.h index d87a72ddd7..6a13f7432d 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -243,6 +243,13 @@ struct Evolution u16 targetSpecies; }; +struct FormChange { + u16 method; + u16 targetSpecies; + u16 param1; + u16 param2; +}; + #define NUM_UNOWN_FORMS 28 #define GET_UNOWN_LETTER(personality) (( \ @@ -431,5 +438,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 new file mode 100644 index 0000000000..777b174a4e --- /dev/null +++ b/src/data/pokemon/form_change_table_pointers.h @@ -0,0 +1,61 @@ +const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = +{ + [SPECIES_GIRATINA] = sGiratinaFormChangeTable, + [SPECIES_SHAYMIN] = sShayminFormChangeTable, + [SPECIES_SHAYMIN_SKY] = sShayminSkyFormChangeTable, + [SPECIES_ARCEUS] = sArceusFormChangeTable, + [SPECIES_ARCEUS_FIGHTING] = sArceusFormChangeTable, + [SPECIES_ARCEUS_FLYING] = sArceusFormChangeTable, + [SPECIES_ARCEUS_POISON] = sArceusFormChangeTable, + [SPECIES_ARCEUS_ROCK] = sArceusFormChangeTable, + [SPECIES_ARCEUS_GROUND] = sArceusFormChangeTable, + [SPECIES_ARCEUS_BUG] = sArceusFormChangeTable, + [SPECIES_ARCEUS_GHOST] = sArceusFormChangeTable, + [SPECIES_ARCEUS_STEEL] = sArceusFormChangeTable, + [SPECIES_ARCEUS_FIRE] = sArceusFormChangeTable, + [SPECIES_ARCEUS_WATER] = sArceusFormChangeTable, + [SPECIES_ARCEUS_GRASS] = sArceusFormChangeTable, + [SPECIES_ARCEUS_ELECTRIC] = sArceusFormChangeTable, + [SPECIES_ARCEUS_PSYCHIC] = sArceusFormChangeTable, + [SPECIES_ARCEUS_ICE] = sArceusFormChangeTable, + [SPECIES_ARCEUS_DRAGON] = sArceusFormChangeTable, + [SPECIES_ARCEUS_DARK] = sArceusFormChangeTable, + [SPECIES_ARCEUS_FAIRY] = sArceusFormChangeTable, + [SPECIES_TORNADUS] = sTornadusFormChangeTable, + [SPECIES_TORNADUS_THERIAN] = sTornadusTherianFormChangeTable, + [SPECIES_THUNDURUS] = sThundurusFormChangeTable, + [SPECIES_THUNDURUS_THERIAN] = sThundurusTherianFormChangeTable, + [SPECIES_LANDORUS] = sLandorusFormChangeTable, + [SPECIES_LANDORUS_THERIAN] = sLandorusTherianFormChangeTable, + [SPECIES_KELDEO] = sKeldeoFormChangeTable, + [SPECIES_KELDEO_RESOLUTE] = sKeldeoResoluteFormChangeTable, + [SPECIES_GENESECT] = sGenesectFormChangeTable, + [SPECIES_GENESECT_DOUSE_DRIVE] = sGenesectFormChangeTable, + [SPECIES_GENESECT_SHOCK_DRIVE] = sGenesectFormChangeTable, + [SPECIES_GENESECT_BURN_DRIVE] = sGenesectFormChangeTable, + [SPECIES_GENESECT_CHILL_DRIVE] = sGenesectFormChangeTable, + [SPECIES_HOOPA] = sHoopaFormChangeTable, + [SPECIES_HOOPA_UNBOUND] = sHoopaUnboundFormChangeTable, + [SPECIES_ORICORIO] = sOricorioFormChangeTable, + [SPECIES_ORICORIO_POM_POM] = sOricorioFormChangeTable, + [SPECIES_ORICORIO_PAU] = sOricorioFormChangeTable, + [SPECIES_ORICORIO_SENSU] = sOricorioFormChangeTable, + [SPECIES_SILVALLY] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_BUG] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_DARK] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_DRAGON] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_ELECTRIC] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_FAIRY] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_FIGHTING] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_FIRE] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_FLYING] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_GHOST] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_GRASS] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_GROUND] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_ICE] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_POISON] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_PSYCHIC] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_ROCK] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_STEEL] = sSilvallyFormChangeTable, + [SPECIES_SILVALLY_WATER] = sSilvallyFormChangeTable, +}; diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h new file mode 100644 index 0000000000..737a05ee87 --- /dev/null +++ b/src/data/pokemon/form_change_tables.h @@ -0,0 +1,169 @@ +/* +FORM_ITEM_USE: + Changes any pokemon with a matching base species (even if + it is a form) to the target species. + param1 = item to use + param1 = ability to check for (none means any) + +FORM_ITEM_HOLD: + param1 = item to hold + param2 = ability to check for (none means any) + +FORM_MOVE: + param1 = move to check for + param2 = true if form change activates when move is forgotten, + false if form change activates when move is learned + +FORM_WITHDRAW: + Form change activates when the Pokemon is withdrawn from the PC or Daycare. + no parameters +*/ + +#define WHEN_LEARNED FALSE +#define WHEN_FORGOTTEN TRUE + +static const struct FormChange sGiratinaFormChangeTable[] = { + {FORM_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sShayminFormChangeTable[] = { + {FORM_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sShayminSkyFormChangeTable[] = { + {FORM_WITHDRAW, SPECIES_SHAYMIN}, + {FORM_CHANGE_END}, +}; + +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}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_SKY_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_FLYINIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_TOXIC_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_POISONIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_STONE_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_ROCKIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_EARTH_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_GROUNDIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_INSECT_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_BUGINIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_SPOOKY_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_GHOSTIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_IRON_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_STEELIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FLAME_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FIRIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_SPLASH_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_WATERIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_MEADOW_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_GRASSIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ZAP_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ELECTRIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_MIND_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_PSYCHIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICICLE_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRACO_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRAGONIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DREAD_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DARKINIUM_Z, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_PIXIE_PLATE, ABILITY_MULTITYPE}, + {FORM_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_FAIRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sTornadusFormChangeTable[] = { + // {FORM_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sTornadusTherianFormChangeTable[] = { + // {FORM_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sThundurusFormChangeTable[] = { + // {FORM_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sThundurusTherianFormChangeTable[] = { + // {FORM_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sLandorusFormChangeTable[] = { + // {FORM_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sLandorusTherianFormChangeTable[] = { + // {FORM_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sKeldeoFormChangeTable[] = { + {FORM_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sKeldeoResoluteFormChangeTable[] = { + {FORM_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, + {FORM_CHANGE_END}, +}; + +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}, + {FORM_ITEM_HOLD, SPECIES_GENESECT_BURN_DRIVE, ITEM_BURN_DRIVE}, + {FORM_ITEM_HOLD, SPECIES_GENESECT_CHILL_DRIVE, ITEM_CHILL_DRIVE}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sHoopaFormChangeTable[] = { + // {FORM_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, + {FORM_CHANGE_END}, +}; + +static const struct FormChange sHoopaUnboundFormChangeTable[] = { + {FORM_WITHDRAW, SPECIES_HOOPA}, + {FORM_CHANGE_END}, +}; + +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}, + {FORM_ITEM_USE, SPECIES_ORICORIO_SENSU, ITEM_PURPLE_NECTAR}, + {FORM_CHANGE_END}, +}; + +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}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_DRAGON, ITEM_DRAGON_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_ELECTRIC, ITEM_ELECTRIC_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_FIGHTING, ITEM_FIGHTING_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_FIRE, ITEM_FIRE_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_FLYING, ITEM_FLYING_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_GHOST, ITEM_GHOST_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_GRASS, ITEM_GRASS_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_GROUND, ITEM_GROUND_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_ICE, ITEM_ICE_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_POISON, ITEM_POISON_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_PSYCHIC, ITEM_PSYCHIC_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_ROCK, ITEM_ROCK_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_STEEL, ITEM_STEEL_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_ITEM_HOLD, SPECIES_SILVALLY_WATER, ITEM_WATER_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_END}, +}; + +#undef WHEN_LEARNED +#undef WHEN_FORGOTTEN diff --git a/src/daycare.c b/src/daycare.c index 6a17150490..ecf4730472 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -245,6 +245,7 @@ static void ApplyDaycareExperience(struct Pokemon *mon) static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon) { u16 species; + u16 newSpecies; u32 experience; struct Pokemon pokemon; @@ -252,6 +253,13 @@ static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon) species = GetBoxMonData(&daycareMon->mon, MON_DATA_SPECIES); BoxMonToMon(&daycareMon->mon, &pokemon); + newSpecies = GetFormChangeTargetSpecies(&pokemon, FORM_WITHDRAW, 0); + if (newSpecies != SPECIES_NONE) { + SetMonData(&pokemon, MON_DATA_SPECIES, &newSpecies); + CalculateMonStats(&pokemon); + species = newSpecies; + } + if (GetMonData(&pokemon, MON_DATA_LEVEL) != MAX_LEVEL) { experience = GetMonData(&pokemon, MON_DATA_EXP) + daycareMon->steps; diff --git a/src/item_use.c b/src/item_use.c index 4b4c6e1b9d..bcbe321a28 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -1118,6 +1118,20 @@ void ItemUseInBattle_EnigmaBerry(u8 taskId) } } +void ItemUseOutOfBattle_FormChange(u8 taskId) +{ + gItemUseCB = ItemUseCB_FormChange; + gTasks[taskId].data[0] = FALSE; + SetUpItemUseCallback(taskId); +} + +void ItemUseOutOfBattle_FormChange_ConsumedOnUse(u8 taskId) +{ + gItemUseCB = ItemUseCB_FormChange_ConsumedOnUse; + gTasks[taskId].data[0] = TRUE; + SetUpItemUseCallback(taskId); +} + void ItemUseOutOfBattle_CannotUse(u8 taskId) { DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); diff --git a/src/party_menu.c b/src/party_menu.c index 4bbb147d8b..861776394b 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -409,6 +409,8 @@ static bool8 SetUpFieldMove_Dive(void); #include "data/pokemon/tutor_learnsets.h" #include "data/party_menu.h" +static const u8 ChangedForm[] = _("{STR_VAR_1} changed Forme!{PAUSE_UNTIL_PRESS}"); + // code static void InitPartyMenu(u8 menuType, u8 layout, u8 partyAction, bool8 keepCursorPos, u8 messageId, TaskFunc task, MainCallback callback) { @@ -5165,6 +5167,51 @@ void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task) } } +bool32 TryItemUseFormChange(u8 taskId, TaskFunc task) +{ + struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; + u16 species = GetMonData(mon, MON_DATA_SPECIES); + u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_ITEM_USE, gSpecialVar_ItemId); + if (targetSpecies != SPECIES_NONE) + { + gPartyMenuUseExitCallback = TRUE; + PlaySE(SE_USE_ITEM); + PlayCry2(targetSpecies, 0, 0x7D, 0xA); + SetMonData(mon, MON_DATA_SPECIES, &targetSpecies); + FreeAndDestroyMonIconSprite(&gSprites[sPartyMenuBoxes[gPartyMenu.slotId].monSpriteId]); + CreatePartyMonIconSpriteParameterized(targetSpecies, GetMonData(mon, MON_DATA_PERSONALITY, NULL), &sPartyMenuBoxes[gPartyMenu.slotId], 0); + CalculateMonStats(mon); + GetMonNickname(mon, gStringVar1); + StringExpandPlaceholders(gStringVar4, ChangedForm); + DisplayPartyMenuMessage(gStringVar4, FALSE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = task; + return TRUE; + } + else + { + gPartyMenuUseExitCallback = FALSE; + PlaySE(SE_SELECT); + DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = task; + return FALSE; + } +} + +void ItemUseCB_FormChange(u8 taskId, TaskFunc task) +{ + TryItemUseFormChange(taskId, task); +} + +void ItemUseCB_FormChange_ConsumedOnUse(u8 taskId, TaskFunc task) +{ + if (TryItemUseFormChange(taskId, task)) + { + RemoveBagItem(gSpecialVar_ItemId, 1); + } +} + u8 GetItemEffectType(u16 item) { const u8 *itemEffect; diff --git a/src/pokemon.c b/src/pokemon.c index 06d5b79159..c5bb10d70c 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -1850,6 +1850,8 @@ const s8 gNatureStatTable[NUM_NATURES][NUM_NATURE_STATS] = #include "data/pokemon/level_up_learnset_pointers.h" #include "data/pokemon/form_species_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 @@ -8046,3 +8048,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; + default: + targetSpecies = formChanges[i].targetSpecies; + break; + } + } + } + return originalSpecies != targetSpecies ? targetSpecies : SPECIES_NONE; +}