diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index ec73fd6b2..be20f6809 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5174,7 +5174,7 @@ BattleScript_MoveWeatherChange:: waitanimation printfromtable gMoveWeatherChangeStringIds waitmessage B_WAIT_TIME_LONG - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities goto BattleScript_MoveEnd BattleScript_EffectSunnyDay:: @@ -6878,7 +6878,7 @@ BattleScript_OverworldWeatherStarts:: printfromtable gWeatherStartsStringIds waitmessage B_WAIT_TIME_LONG playanimation_var BS_ATTACKER, sB_ANIM_ARG1 - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_OverworldTerrain:: @@ -7874,14 +7874,13 @@ BattleScript_MegaEvolution:: printstring STRINGID_EMPTYSTRING3 trytrainerslidemegaevolutionmsg BS_ATTACKER printstring STRINGID_MEGAEVOREACTING -BattleScript_MegaEvolutionAfeterString: +BattleScript_MegaEvolutionAfterString: waitmessage B_WAIT_TIME_LONG setbyte gIsCriticalHit, 0 handlemegaevo BS_ATTACKER, 0 - handlemegaevo BS_ATTACKER, 1 playanimation BS_ATTACKER, B_ANIM_MEGA_EVOLUTION waitanimation - handlemegaevo BS_ATTACKER, 2 + handlemegaevo BS_ATTACKER, 1 printstring STRINGID_MEGAEVOEVOLVED waitmessage B_WAIT_TIME_LONG switchinabilities BS_ATTACKER @@ -7891,7 +7890,7 @@ BattleScript_WishMegaEvolution:: printstring STRINGID_EMPTYSTRING3 trytrainerslidemegaevolutionmsg BS_ATTACKER printstring STRINGID_FERVENTWISHREACHED - goto BattleScript_MegaEvolutionAfeterString + goto BattleScript_MegaEvolutionAfterString BattleScript_PrimalReversion:: printstring STRINGID_EMPTYSTRING3 @@ -7940,6 +7939,7 @@ BattleScript_AttackerFormChangeEnd3:: BattleScript_AttackerFormChangeEnd3NoPopup:: call BattleScript_AttackerFormChangeNoPopup + end3 BattleScript_AttackerFormChangeMoveEffect:: waitmessage 1 @@ -8434,7 +8434,7 @@ BattleScript_DrizzleActivates:: printstring STRINGID_PKMNMADEITRAIN waitstate playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_AbilityRaisesDefenderStat:: @@ -8596,7 +8596,7 @@ BattleScript_SandstreamActivates:: printstring STRINGID_PKMNSXWHIPPEDUPSANDSTORM waitstate playanimation BS_BATTLER_0, B_ANIM_SANDSTORM_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_SandSpitActivates:: @@ -8605,7 +8605,7 @@ BattleScript_SandSpitActivates:: printstring STRINGID_ASANDSTORMKICKEDUP waitstate playanimation BS_BATTLER_0, B_ANIM_SANDSTORM_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities return BattleScript_ShedSkinActivates:: @@ -8615,37 +8615,15 @@ BattleScript_ShedSkinActivates:: updatestatusicon BS_ATTACKER end3 -BattleScript_WeatherFormChanges:: - setbyte sBATTLER, 0 -BattleScript_WeatherFormChangesLoop:: - tryweatherformdatachange - activateweatherchangeabilities BS_SCRIPTING - addbyte sBATTLER, 1 - jumpifbytenotequal sBATTLER, gBattlersCount, BattleScript_WeatherFormChangesLoop - return - -BattleScript_WeatherFormChange:: - call BattleScript_DoWeatherFormChange - end3 - -BattleScript_DoWeatherFormChange:: - copybyte gBattlerAbility, sBATTLER -.if B_WEATHER_FORMS >= GEN_5 - jumpifspecies BS_SCRIPTING, SPECIES_CASTFORM, BattleScript_DoWeatherFormChange_ForecastCheck -BattleScript_DoWeatherFormChange_FlowerGiftCheck: - jumpifability BS_SCRIPTING, ABILITY_FLOWER_GIFT, BattleScript_DoWeatherFormChange_PopUp - goto BattleScript_DoWeatherFormChange_AfterPopUp -.endif -BattleScript_DoWeatherFormChange_ForecastCheck: - jumpifability BS_SCRIPTING, ABILITY_FORECAST, BattleScript_DoWeatherFormChange_PopUp - goto BattleScript_DoWeatherFormChange_AfterPopUp -BattleScript_DoWeatherFormChange_PopUp: - call BattleScript_AbilityPopUp -BattleScript_DoWeatherFormChange_AfterPopUp: - doweatherformchangeanimation - waitstate - printstring STRINGID_PKMNTRANSFORMED - waitmessage B_WAIT_TIME_LONG +BattleScript_ActivateWeatherAbilities: + copybyte sBATTLER, gBattlerAttacker + setbyte gBattlerAttacker, 0 +BattleScript_ActivateWeatherAbilities_Loop: + activateweatherchangeabilities BS_ATTACKER +BattleScript_ActivateWeatherAbilities_Increment: + addbyte gBattlerAttacker, 1 + jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateWeatherAbilities_Loop + copybyte gBattlerAttacker, sBATTLER return BattleScript_TryAdrenalineOrb: @@ -8740,7 +8718,7 @@ BattleScript_DroughtActivates:: printstring STRINGID_PKMNSXINTENSIFIEDSUN waitstate playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_DesolateLandActivates:: @@ -8749,7 +8727,7 @@ BattleScript_DesolateLandActivates:: printstring STRINGID_EXTREMELYHARSHSUNLIGHT waitstate playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_DesolateLandEvaporatesWaterTypeMoves:: @@ -8769,7 +8747,7 @@ BattleScript_PrimordialSeaActivates:: printstring STRINGID_HEAVYRAIN waitstate playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_PrimordialSeaFizzlesOutFireTypeMoves:: @@ -8846,7 +8824,7 @@ BattleScript_SnowWarningActivates:: printstring STRINGID_SNOWWARNINGHAIL waitstate playanimation BS_BATTLER_0, B_ANIM_HAIL_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_ActivateTerrainEffects: @@ -10009,7 +9987,7 @@ BattleScript_AnnounceAirLockCloudNine:: call BattleScript_AbilityPopUp printstring STRINGID_AIRLOCKACTIVATES waitmessage B_WAIT_TIME_LONG - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_QuickClawActivation:: diff --git a/include/battle.h b/include/battle.h index c7265ed2a..4ba3cba6e 100644 --- a/include/battle.h +++ b/include/battle.h @@ -3,6 +3,7 @@ // should they be included here or included individually by every file? #include "constants/battle.h" +#include "constants/form_change_types.h" #include "battle_main.h" #include "battle_message.h" #include "battle_util.h" @@ -477,13 +478,7 @@ struct LinkBattlerHeader struct MegaEvolutionData { u8 toEvolve; // As flags using gBitTable. - u8 evolvedPartyIds[2]; // As flags using gBitTable; bool8 alreadyEvolved[4]; // Array id is used for mon position. - u16 evolvedSpecies[MAX_BATTLERS_COUNT]; - u16 playerEvolvedSpecies; - u8 primalRevertedPartyIds[2]; // As flags using gBitTable; - u16 primalRevertedSpecies[MAX_BATTLERS_COUNT]; - u16 playerPrimalRevertedSpecies; u8 battlerId; bool8 playerSelect; u8 triggerSpriteId; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 876e2d343..51773df8d 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -149,9 +149,6 @@ extern const u8 BattleScript_TraceActivatesEnd3[]; extern const u8 BattleScript_RainDishActivates[]; extern const u8 BattleScript_SandstreamActivates[]; extern const u8 BattleScript_ShedSkinActivates[]; -extern const u8 BattleScript_WeatherFormChanges[]; -extern const u8 BattleScript_WeatherFormChangesLoop[]; -extern const u8 BattleScript_WeatherFormChange[]; extern const u8 BattleScript_IntimidateActivates[]; extern const u8 BattleScript_DroughtActivates[]; extern const u8 BattleScript_TookAttack[]; diff --git a/include/battle_util.h b/include/battle_util.h index a57aca5f6..0ad287c53 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -173,12 +173,11 @@ u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilit u16 GetTypeModifier(u8 atkType, u8 defType); s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId); s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp); -u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId); -u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId); -u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4); bool32 CanMegaEvolve(u8 battlerId); -void UndoMegaEvolution(u32 monId); -void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut); +bool32 IsBattlerMegaEvolved(u8 battlerId); +bool32 IsBattlerPrimalReverted(u8 battlerId); +u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method); +bool32 TryBattleFormChange(u8 battlerId, u16 method); bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId); u32 GetIllusionMonSpecies(u32 battlerId); @@ -206,13 +205,15 @@ void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind); bool32 TryRoomService(u8 battlerId); void BufferStatChange(u8 battlerId, u8 statId, u8 stringId); -void DoBurmyFormChange(u32 monId); bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget); u16 GetUsedHeldItem(u8 battler); bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags); u32 GetBattlerMoveTargetType(u8 battlerId, u16 move); bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move); bool8 IsMoveAffectedByParentalBond(u16 move, u8 battlerId); +void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon); +void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon); +void RecalcBattlerStats(u32 battler, struct Pokemon *mon); // Ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); bool32 IsRolePlayBannedAbility(u16 ability); diff --git a/include/config/battle.h b/include/config/battle.h index b9d3926b0..d1d4fc52f 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -99,6 +99,7 @@ // Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon. #define B_DEFOG_CLEARS_TERRAIN GEN_LATEST // In Gen8+, Defog also clears active Terrain. #define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp. Defense stats. Once Spit Up / Swallow is used, these stat changes are lost. +#define B_TRANSFORM_FORM_CHANGES GEN_LATEST // In Gen5+, Transformed Pokemon cannot change forms. // Ability settings #define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters. diff --git a/include/config/item.h b/include/config/item.h index 09008d0f2..88cfeeb7c 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -2,13 +2,14 @@ #define GUARD_CONFIG_ITEM_H // Item config -#define I_SHINY_CHARM_REROLLS 3 // Amount of re-rolls if the player has the Shiny Charm. Set to 0 to disable Shiny Charm's effects. -#define I_KEY_FOSSILS GEN_LATEST // In Gen4+, all Gen 3 fossils became regular items. -#define I_KEY_ESCAPE_ROPE GEN_LATEST // In Gen8, Escape Rope became a Key Item. Keep in mind, this will make it free to buy in marts. -#define I_HEALTH_RECOVERY GEN_LATEST // In Gen7+, certain healing items recover a different amount of HP than they used to. -#define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP. -#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8+, the Vitamins no longer have a cap of 100 EV per stat. -#define I_BERRY_EV_JUMP GEN_LATEST // In Gen4 only, EV-lowering Berries lower a stat's EV to 100 if it is above 100. +#define I_SHINY_CHARM_REROLLS 3 // Amount of re-rolls if the player has the Shiny Charm. Set to 0 to disable Shiny Charm's effects. +#define I_KEY_FOSSILS GEN_LATEST // In Gen4+, all Gen 3 fossils became regular items. +#define I_KEY_ESCAPE_ROPE GEN_LATEST // In Gen8, Escape Rope became a Key Item. Keep in mind, this will make it free to buy in marts. +#define I_HEALTH_RECOVERY GEN_LATEST // In Gen7+, certain healing items recover a different amount of HP than they used to. +#define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP. +#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8+, the Vitamins no longer have a cap of 100 EV per stat. +#define I_BERRY_EV_JUMP GEN_LATEST // In Gen4 only, EV-lowering Berries lower a stat's EV to 100 if it is above 100. +#define I_GRISEOUS_ORB_FORM_CHANGE GEN_LATEST // In Gen9+, the Griseous Orb no longer changes Giratina's form when held. // TM config #define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1. diff --git a/include/constants/battle.h b/include/constants/battle.h index f0130e58f..a37f0c6d5 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -270,6 +270,7 @@ #define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) // Battle Weather flags +#define B_WEATHER_NONE 0 #define B_WEATHER_RAIN_TEMPORARY (1 << 0) #define B_WEATHER_RAIN_DOWNPOUR (1 << 1) // unused #define B_WEATHER_RAIN_PERMANENT (1 << 2) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index a769ce30d..2be15be58 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -335,10 +335,9 @@ #define MOVEEND_PICKPOCKET 30 #define MOVEEND_DANCER 31 #define MOVEEND_EMERGENCY_EXIT 32 -#define MOVEEND_WEATHER_FORM 33 -#define MOVEEND_SYMBIOSIS 34 -#define MOVEEND_CLEAR_BITS 35 -#define MOVEEND_COUNT 36 +#define MOVEEND_SYMBIOSIS 33 +#define MOVEEND_CLEAR_BITS 34 +#define MOVEEND_COUNT 35 // switch cases #define B_SWITCH_NORMAL 0 diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h new file mode 100644 index 000000000..651bcf788 --- /dev/null +++ b/include/constants/form_change_types.h @@ -0,0 +1,98 @@ +#ifndef GUARD_CONSTANTS_FORM_CHANGE_TYPES_H +#define GUARD_CONSTANTS_FORM_CHANGE_TYPES_H + +// FORM_CHANGE_BATTLE_HP_PERCENT param2 arguments +#define HP_HIGHER_THAN 1 +#define HP_LOWER_EQ_THAN 2 +// FORM_CHANGE_MOVE param2 Arguments +#define WHEN_LEARNED 0 +#define WHEN_FORGOTTEN 1 +// FORM_CHANGE_ITEM_USE param2 Arguments +#define DAY 1 +#define NIGHT 2 + +#define FORM_CHANGE_TERMINATOR 0 + +// Form change that activates when the specified item is given to or taken from the selected Pokémon. +// param1: item to hold. +// param2: ability to check for, optional. +#define FORM_CHANGE_ITEM_HOLD 1 + +// Form change that activates when the item is used on the selected Pokémon. +// param1: item to use +// param2: time of day to check, optional. +// - DAY if Form change that activates in the daytime. +// - NIGHT if Form change that activates at nighttime. +#define FORM_CHANGE_ITEM_USE 2 + +// TODO: Form change that activates when the Pokémon learns or forgets the move. +// param1: move to check for +// param2: +// - WHEN_LEARNED if Form change that activates when move is forgotten +// - WHEN_FORGOTTEN if Form change that activates when move is learned +#define FORM_CHANGE_MOVE 3 + +// Form change that activates when the Pokémon is withdrawn from the PC or Daycare. +// Daycare withdraw done, PC withdraw TODO. +// - No parameters. +#define FORM_CHANGE_WITHDRAW 4 + +// Form change that activates when the Pokémon faints, either in battle or in the overworld by poison. +// If species is not specified and it's on the player's side, it will try to use the value +// saved in gBattleStruct->changedSpecies from a previous form change. +// - No parameters. +#define FORM_CHANGE_FAINT 5 + +// Form change that activates when the Pokémon is sent out at the beginning of a battle +// param1: item to hold, optional +// param2: a move that will be replaced, optional +// param3: a new move to replace it with, optional +#define FORM_CHANGE_BEGIN_BATTLE 6 + +// Form change that activates at the end of a battle. If species is not specified and it's on the player's side, it will try to use the value saved in gBattleStruct->changedSpecies from a previous form change. +// param1: item to hold, optional +// param2: a move that will be replaced, optional +// param3: a new move to replace it with, optional +#define FORM_CHANGE_END_BATTLE 7 + +// Form change that activates at the end of a battle based on the terrain if it participated in the battle and hasn't fainted. Takes priority over FORM_CHANGE_END_BATTLE. +// param1: battle terrain to check. +#define FORM_CHANGE_END_BATTLE_TERRAIN 8 + +// Form change that activates when the Pokémon is switched out in battle. +// - No parameters. +#define FORM_CHANGE_BATTLE_SWITCH 9 + +// Form change that activates when the Pokémon's HP % passes a certain threshold. +// param1: Ability to check. +// param2: HP comparer +// - HP_HIGHER_THAN if the form triggers when the current HP is higher than the specified threshold. +// - HP_LOWER_EQ_THAN if the form triggers when the current HP is lower or equal than the specified threshold. +// param3: HP percentage threshold. +#define FORM_CHANGE_BATTLE_HP_PERCENT 10 + +// Form change that activates when the mon has the defined item. +// If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. +// param1: item to hold. +#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM 11 + +// Form change that activates when the mon has the defined move. +// If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. +// param1: move to have. +#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE 12 + +// Form change that activates automatically when entering battle with the specified item. +// If the item is a Red Orb, it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to the Alpha symbol. +// The battle indicator icon is based on the species, with Primal Groudon's as Omega and otherwise being Alpha. +// param1: item to hold. +#define FORM_CHANGE_BATTLE_PRIMAL_REVERSION 13 + +// Form change that activates when a specific weather is set during battle. +// param1: weather to check +#define FORM_CHANGE_BATTLE_WEATHER 14 + +// Form change that activates automatically when the turn ends. +// param1: ability to check. +#define FORM_CHANGE_BATTLE_TURN_END 15 + +#endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index ddf879854..ff2a44dc9 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -273,9 +273,6 @@ #define F_SUMMARY_SCREEN_FLIP_SPRITE 0x80 // Evolution types -#define EVO_MEGA_EVOLUTION 0xffff // Not an actual evolution, used to temporarily mega evolve in battle. -#define EVO_MOVE_MEGA_EVOLUTION 0xfffe // Mega Evolution that checks for a move instead of held item. -#define EVO_PRIMAL_REVERSION 0xfffd // Not an actual evolution, used to undergo primal reversion in battle. #define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220 #define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220 #define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220 @@ -326,15 +323,6 @@ #define EVO_MODE_BATTLE_SPECIAL 4 #define EVO_MODE_OVERWORLD_SPECIAL 5 -// 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 -#define FORM_BATTLE_BEGIN 5 -#define FORM_BATTLE_END 6 - #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 #define MON_PIC_SIZE (MON_PIC_WIDTH * MON_PIC_HEIGHT / 2) @@ -362,13 +350,14 @@ #define SPECIES_FLAG_LEGENDARY (1 << 0) #define SPECIES_FLAG_MYTHICAL (1 << 1) #define SPECIES_FLAG_MEGA_EVOLUTION (1 << 2) -#define SPECIES_FLAG_ULTRA_BEAST (1 << 3) -#define SPECIES_FLAG_ALOLAN_FORM (1 << 4) -#define SPECIES_FLAG_GALARIAN_FORM (1 << 5) -#define SPECIES_FLAG_HISUIAN_FORM (1 << 6) -#define SPECIES_FLAG_GENDER_DIFFERENCE (1 << 7) -#define SPECIES_FLAG_ALL_PERFECT_IVS (1 << 8) -#define SPECIES_FLAG_CANNOT_BE_TRADED (1 << 9) +#define SPECIES_FLAG_PRIMAL_REVERSION (1 << 3) +#define SPECIES_FLAG_ULTRA_BEAST (1 << 4) +#define SPECIES_FLAG_ALOLAN_FORM (1 << 5) +#define SPECIES_FLAG_GALARIAN_FORM (1 << 6) +#define SPECIES_FLAG_HISUIAN_FORM (1 << 7) +#define SPECIES_FLAG_GENDER_DIFFERENCE (1 << 8) +#define SPECIES_FLAG_ALL_PERFECT_IVS (1 << 9) +#define SPECIES_FLAG_CANNOT_BE_TRADED (1 << 10) #define LEGENDARY_PERFECT_IV_COUNT 3 diff --git a/include/pokemon.h b/include/pokemon.h index 581677cae..b3ba009be 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -414,6 +414,7 @@ extern const u16 gUnionRoomFacilityClasses[]; extern const struct SpriteTemplate gBattlerSpriteTemplates[]; extern const s8 gNatureStatTable[][5]; extern const u16 *const gFormSpeciesIdTables[NUM_SPECIES]; +extern const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES]; extern const u32 sExpCandyExperienceTable[]; void ZeroBoxMonData(struct BoxPokemon *boxMon); @@ -565,10 +566,12 @@ u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum); u16 GetFormSpeciesId(u16 speciesId, u8 formId); u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId); u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); -u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *mon, u16 method, u32 arg); +u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg); +bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method); u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); bool32 ShouldShowFemaleDifferences(u16 species, u32 personality); -void TryToSetBattleFormChangeMoves(struct Pokemon *mon); +bool32 TryFormChange(u32 monId, u32 side, u16 method); +void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method); u32 GetMonFriendshipScore(struct Pokemon *pokemon); void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 6c60705d5..cadcb55f1 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3081,12 +3081,8 @@ static bool32 IsPinchBerryItemEffect(u16 holdEffect) case HOLD_EFFECT_SP_DEFENSE_UP: case HOLD_EFFECT_CRITICAL_UP: case HOLD_EFFECT_RANDOM_STAT_UP: - #ifdef HOLD_EFFECT_CUSTAP_BERRY case HOLD_EFFECT_CUSTAP_BERRY: - #endif - #ifdef HOLD_EFFECT_MICLE_BERRY case HOLD_EFFECT_MICLE_BERRY: - #endif return TRUE; } @@ -3861,7 +3857,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_KINGS_SHIELD: - #if (defined SPECIES_AEGISLASH && defined SPECIES_AEGISLASH_BLADE) if (AI_DATA->abilities[battlerAtk] == ABILITY_STANCE_CHANGE //Special logic for Aegislash && gBattleMons[battlerAtk].species == SPECIES_AEGISLASH_BLADE && !IsBattlerIncapacitated(battlerDef, AI_DATA->abilities[battlerDef])) @@ -3869,7 +3864,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 3; break; } - #endif //fallthrough default: // protect ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); @@ -4538,7 +4532,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 3; break; case EFFECT_RELIC_SONG: - #if (defined SPECIES_MELOETTA && defined SPECIES_MELOETTA_PIROUETTE) if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) // Don't try to change form if it's transformed. { if (gBattleMons[battlerAtk].species == SPECIES_MELOETTA && gBattleMons[battlerDef].defense < gBattleMons[battlerDef].spDefense) @@ -4546,7 +4539,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) else if (gBattleMons[battlerAtk].species == SPECIES_MELOETTA_PIROUETTE && gBattleMons[battlerDef].spDefense < gBattleMons[battlerDef].defense) score += 3; // Change to Aria if can do more damage } - #endif break; case EFFECT_ELECTRIC_TERRAIN: case EFFECT_MISTY_TERRAIN: diff --git a/src/battle_interface.c b/src/battle_interface.c index bbe61a372..9c380d4a4 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -980,8 +980,7 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) u8 battler = gSprites[healthboxSpriteId].hMain_Battler; // Don't print Lv char if mon is mega evolved or primal reverted. - if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]] - || gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]) + if (IsBattlerMegaEvolved(battler) || IsBattlerPrimalReverted(battler)) { objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); xPos = 5 * (3 - (objVram - (text + 2))) - 1; @@ -1503,22 +1502,16 @@ static bool32 MegaIndicator_ShouldBeInvisible(u32 battlerId, u32 indicatorType) u32 side = GetBattlerSide(battlerId); if (indicatorType == INDICATOR_MEGA) { - if (gBattleStruct->mega.evolvedPartyIds[side] & gBitTable[gBattlerPartyIndexes[battlerId]]) + if (IsBattlerMegaEvolved(battlerId)) return FALSE; } else { - if (indicatorType == INDICATOR_ALPHA) - { - if (gBattleMons[battlerId].species != SPECIES_KYOGRE_PRIMAL) - return TRUE; - } - else if (indicatorType == INDICATOR_OMEGA) - { - if (gBattleMons[battlerId].species != SPECIES_GROUDON_PRIMAL) - return TRUE; - } - if (gBattleStruct->mega.primalRevertedPartyIds[side] & gBitTable[gBattlerPartyIndexes[battlerId]]) + if (indicatorType == INDICATOR_ALPHA && gBattleMons[battlerId].species != SPECIES_KYOGRE_PRIMAL) + return TRUE; + else if (indicatorType == INDICATOR_OMEGA && gBattleMons[battlerId].species != SPECIES_GROUDON_PRIMAL) + return TRUE; + if (IsBattlerPrimalReverted(battlerId)) return FALSE; } return TRUE; diff --git a/src/battle_main.c b/src/battle_main.c index 2faeb84f2..e59653f31 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -607,21 +607,9 @@ static void CB2_InitBattleInternal(void) for (i = 0; i < PARTY_SIZE; i++) { // Player's side - targetSpecies = GetFormChangeTargetSpecies(&gPlayerParty[i], FORM_BATTLE_BEGIN, 0); - if (targetSpecies != SPECIES_NONE) - { - SetMonData(&gPlayerParty[i], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&gPlayerParty[i]); - TryToSetBattleFormChangeMoves(&gPlayerParty[i]); - } + TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BEGIN_BATTLE); // Opponent's side - targetSpecies = GetFormChangeTargetSpecies(&gEnemyParty[i], FORM_BATTLE_BEGIN, 0); - if (targetSpecies != SPECIES_NONE) - { - SetMonData(&gEnemyParty[i], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&gEnemyParty[i]); - TryToSetBattleFormChangeMoves(&gEnemyParty[i]); - } + TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BEGIN_BATTLE); } gBattleCommunication[MULTIUSE_STATE] = 0; @@ -3411,9 +3399,7 @@ void FaintClearSetData(void) gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; Ai_UpdateFaintData(gActiveBattler); - UndoFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FALSE); - if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) - UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); + TryBattleFormChange(gActiveBattler, FORM_CHANGE_FAINT); gBattleStruct->overwrittenAbilities[gActiveBattler] = ABILITY_NONE; @@ -3845,24 +3831,6 @@ static void TryDoEventsBeforeFirstTurn(void) } memset(gTotemBoosts, 0, sizeof(gTotemBoosts)); // erase all totem boosts just to be safe - // Primal Reversion - for (i = 0; i < gBattlersCount; i++) - { - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB) - { - for (j = 0; j < EVOS_PER_MON; j++) - { - if (gEvolutionTable[gBattleMons[i].species][j].targetSpecies != SPECIES_NONE - && gEvolutionTable[gBattleMons[i].species][j].method == EVO_PRIMAL_REVERSION) - { - gBattlerAttacker = i; - BattleScriptExecute(BattleScript_PrimalReversion); - return; - } - } - } - } - // Check neutralizing gas if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0) return; @@ -3871,6 +3839,14 @@ static void TryDoEventsBeforeFirstTurn(void) while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount) { gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->switchInAbilitiesCounter++]; + + // Primal Reversion + if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_PRIMAL_ORB + && GetBattleFormChangeTargetSpecies(gBattlerAttacker, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE) + { + BattleScriptExecute(BattleScript_PrimalReversion); + return; + } if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0) return; } @@ -5054,7 +5030,7 @@ static void CheckMegaEvolutionBeforeTurn(void) gBattleStruct->mega.toEvolve &= ~(gBitTable[gActiveBattler]); gLastUsedItem = gBattleMons[gActiveBattler].item; - if (GetWishMegaEvolutionSpecies(GetMonData(mon, MON_DATA_SPECIES), GetMonData(mon, MON_DATA_MOVE1), GetMonData(mon, MON_DATA_MOVE2), GetMonData(mon, MON_DATA_MOVE3), GetMonData(mon, MON_DATA_MOVE4))) + if (GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) BattleScriptExecute(BattleScript_WishMegaEvolution); else BattleScriptExecute(BattleScript_MegaEvolution); @@ -5410,21 +5386,31 @@ static void HandleEndTurn_FinishBattle(void) #endif for (i = 0; i < PARTY_SIZE; i++) { - UndoMegaEvolution(i); - UndoFormChange(i, B_SIDE_PLAYER, FALSE); - DoBurmyFormChange(i); - } - #if B_RECALCULATE_STATS >= GEN_5 - // Recalculate the stats of every party member before the end - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG) - { + bool8 changedForm = FALSE; + + // Appeared in battle and didn't faint + if ((gBattleStruct->appearedInBattle & gBitTable[i]) && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0) + changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE_TERRAIN); + + if (!changedForm) + changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE); + + // Clear original species field + gBattleStruct->changedSpecies[i] = SPECIES_NONE; + + #if B_RECALCULATE_STATS >= GEN_5 + // Recalculate the stats of every party member before the end + if (!changedForm) CalculateMonStats(&gPlayerParty[i]); - } + #endif + } + // Clear battle mon species to avoid a bug on the next battle that causes + // healthboxes loading incorrectly due to it trying to create a Mega Indicator + // if the previous battler would've had it. + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + gBattleMons[i].species = SPECIES_NONE; } - #endif gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions; gCB2_AfterEvolution = BattleMainCB2; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a56130748..aead0fe3c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4480,15 +4480,7 @@ static void Cmd_getexp(void) if (battlerId != 0xFF) { - gBattleMons[battlerId].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL); - gBattleMons[battlerId].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HP); - gBattleMons[battlerId].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MAX_HP); - gBattleMons[battlerId].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_ATK); - gBattleMons[battlerId].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_DEF); - gBattleMons[battlerId].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); - gBattleMons[battlerId].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPATK); - gBattleMons[battlerId].spDefense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPDEF); - + CopyMonLevelAndBaseStatsToBattleMon(battlerId, &gPlayerParty[gBattleStruct->expGetterMonId]); if (gStatuses3[battlerId] & STATUS3_POWER_TRICK) SWAP(gBattleMons[battlerId].attack, gBattleMons[battlerId].defense, temp); } @@ -6273,28 +6265,6 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_WEATHER_FORM: - for (i = 0; i < MAX_BATTLERS_COUNT; i++) - { - switch (gBattleMons[i].species) - { - case SPECIES_CASTFORM: - case SPECIES_CASTFORM_RAINY: - case SPECIES_CASTFORM_SNOWY: - case SPECIES_CASTFORM_SUNNY: - case SPECIES_CHERRIM: - case SPECIES_CHERRIM_SUNSHINE: - effect = TryWeatherFormChange(i); - if (effect) - { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - gBattleScripting.battler = i; - gBattleStruct->formToChangeInto = effect - 1; - } - } - } - gBattleScripting.moveendState++; - break; case MOVEEND_SYMBIOSIS: for (i = 0; i < gBattlersCount; i++) { @@ -8614,22 +8584,6 @@ u32 IsAbilityStatusProtected(u32 battler) || IsShieldsDownProtected(battler); } -static void RecalcBattlerStats(u32 battler, struct Pokemon *mon) -{ - CalculateMonStats(mon); - gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL); - gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP); - gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP); - gBattleMons[battler].attack = GetMonData(mon, MON_DATA_ATK); - gBattleMons[battler].defense = GetMonData(mon, MON_DATA_DEF); - gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED); - gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK); - gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF); - gBattleMons[battler].ability = GetMonAbility(mon); - gBattleMons[battler].type1 = gSpeciesInfo[gBattleMons[battler].species].types[0]; - gBattleMons[battler].type2 = gSpeciesInfo[gBattleMons[battler].species].types[1]; -} - u32 GetHighestStatId(u32 battlerId) { u32 i, highestId = STAT_ATK, highestStat = gBattleMons[battlerId].attack; @@ -8792,62 +8746,27 @@ static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega) // Change species. if (caseId == 0) { - u16 newSpecies; if (isMega) { - gBattleStruct->mega.evolvedSpecies[battlerId] = gBattleMons[battlerId].species; - if (position == B_POSITION_PLAYER_LEFT - || (position == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)))) - { - gBattleStruct->mega.playerEvolvedSpecies = gBattleStruct->mega.evolvedSpecies[battlerId]; - } - //Checks regular Mega Evolution - newSpecies = GetMegaEvolutionSpecies(gBattleStruct->mega.evolvedSpecies[battlerId], gBattleMons[battlerId].item); - //Checks Wish Mega Evolution - if (newSpecies == SPECIES_NONE) - { - newSpecies = GetWishMegaEvolutionSpecies(gBattleStruct->mega.evolvedSpecies[battlerId], - gBattleMons[battlerId].moves[0], gBattleMons[battlerId].moves[1], gBattleMons[battlerId].moves[2], gBattleMons[battlerId].moves[3]); - } + if (!TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM)) + TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE); } else - { - gBattleStruct->mega.primalRevertedSpecies[battlerId] = gBattleMons[battlerId].species; - if (position == B_POSITION_PLAYER_LEFT - || (position == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)))) - { - gBattleStruct->mega.playerPrimalRevertedSpecies = gBattleStruct->mega.primalRevertedSpecies[battlerId]; - } - // Checks Primal Reversion. - newSpecies = GetPrimalReversionSpecies(gBattleStruct->mega.primalRevertedSpecies[battlerId], gBattleMons[battlerId].item); - } + TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_PRIMAL_REVERSION); - gBattleMons[battlerId].species = newSpecies; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battlerId].species); BtlController_EmitSetMonData(BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[battlerId]], sizeof(gBattleMons[battlerId].species), &gBattleMons[battlerId].species); MarkBattlerForControllerExec(battlerId); } - // Change stats. - else if (caseId == 1) - { - RecalcBattlerStats(battlerId, mon); - if (isMega) - { - gBattleStruct->mega.alreadyEvolved[position] = TRUE; - gBattleStruct->mega.evolvedPartyIds[side] |= gBitTable[gBattlerPartyIndexes[battlerId]]; - } - else - { - gBattleStruct->mega.primalRevertedPartyIds[side] |= gBitTable[gBattlerPartyIndexes[battlerId]]; - } - } // Update healthbox and elevation and play cry. else { UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId], mon, HEALTHBOX_ALL); if (side == B_SIDE_OPPONENT) SetBattlerShadowSpriteCallback(battlerId, gBattleMons[battlerId].species); + if (isMega) + gBattleStruct->mega.alreadyEvolved[position] = TRUE; } } @@ -10751,15 +10670,7 @@ static void Cmd_various(void) case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL: { VARIOUS_ARGS(const u8 *jumpInstr); - bool8 canDoPrimalReversion = FALSE; - - for (i = 0; i < EVOS_PER_MON; i++) - { - if (gEvolutionTable[gBattleMons[gActiveBattler].species][i].method == EVO_PRIMAL_REVERSION - && gEvolutionTable[gBattleMons[gActiveBattler].species][i].param == gBattleMons[gActiveBattler].item) - canDoPrimalReversion = TRUE; - } - if (!canDoPrimalReversion) + if (GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) == SPECIES_NONE) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -15237,15 +15148,7 @@ static void Cmd_tryweatherformdatachange(void) { CMD_ARGS(); - u8 form; - - gBattlescriptCurrInstr = cmd->nextInstr; - form = TryWeatherFormChange(gBattleScripting.battler); - if (form) - { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - *(&gBattleStruct->formToChangeInto) = form - 1; - } + // removed in favor of new form system } // Water and Mud Sport @@ -15732,7 +15635,7 @@ static void Cmd_handleballthrow(void) { BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS); MarkBattlerForControllerExec(gActiveBattler); - UndoFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FALSE); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); @@ -15786,7 +15689,7 @@ static void Cmd_handleballthrow(void) if (IsCriticalCapture()) gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - UndoFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FALSE); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); diff --git a/src/battle_util.c b/src/battle_util.c index bf332e64d..99fa85ab2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -542,7 +542,7 @@ void HandleAction_Switch(void) if (gBattleResults.playerSwitchesCounter < 255) gBattleResults.playerSwitchesCounter++; - UndoFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), TRUE); + TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_SWITCH); } void HandleAction_UseItem(void) @@ -2487,8 +2487,16 @@ u8 DoFieldEndTurnEffects(void) gBattleStruct->turnCountersTracker++; break; case ENDTURN_WEATHER_FORM: - AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, 0, 0, 0, 0); - gBattleStruct->turnCountersTracker++; + for (i = 0; i < gBattlersCount; i++) + { + if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0)) + { + effect++; + break; + } + } + if (effect == 0) + gBattleStruct->turnCountersTracker++; break; case ENDTURN_STATUS_HEAL: for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) @@ -4115,51 +4123,6 @@ static bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag, u8 *timer) return FALSE; } -static bool32 ShouldChangeFormHpBased(u32 battler) -{ - // Ability, form >, form <=, hp divided - static const u16 forms[][4] = - { - {ABILITY_ZEN_MODE, SPECIES_DARMANITAN, SPECIES_DARMANITAN_ZEN_MODE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_BLUE, SPECIES_MINIOR_CORE_BLUE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_GREEN, SPECIES_MINIOR_CORE_GREEN, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_INDIGO, SPECIES_MINIOR_CORE_INDIGO, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_ORANGE, SPECIES_MINIOR_CORE_ORANGE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW, 2}, - {ABILITY_SCHOOLING, SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, 4}, - {ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GORGING, 2}, - {ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GULPING, 1}, - {ABILITY_ZEN_MODE, SPECIES_DARMANITAN_GALARIAN, SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, 2}, - }; - u32 i; - u16 battlerAbility = GetBattlerAbility(battler); - - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) - return FALSE; - - for (i = 0; i < ARRAY_COUNT(forms); i++) - { - if (battlerAbility == forms[i][0]) - { - if (gBattleMons[battler].species == forms[i][2] - && gBattleMons[battler].hp > gBattleMons[battler].maxHP / forms[i][3]) - { - gBattleMons[battler].species = forms[i][1]; - return TRUE; - } - if (gBattleMons[battler].species == forms[i][1] - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / forms[i][3]) - { - gBattleMons[battler].species = forms[i][2]; - return TRUE; - } - } - } - return FALSE; -} - static u8 ForewarnChooseMove(u32 battler) { struct Forewarn { @@ -4712,8 +4675,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_SCHOOLING: if (gBattleMons[battler].level < 20) break; + // Fallthrough + case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: - if (ShouldChangeFormHpBased(battler)) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); effect++; @@ -4984,17 +4949,12 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_SCHOOLING: if (gBattleMons[battler].level < 20) break; + // Fallthrough case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: - if ((effect = ShouldChangeFormHpBased(battler))) - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); - break; case ABILITY_POWER_CONSTRUCT: - if ((gBattleMons[battler].species == SPECIES_ZYGARDE || gBattleMons[battler].species == SPECIES_ZYGARDE_10) - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 2) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; - gBattleMons[battler].species = SPECIES_ZYGARDE_COMPLETE; BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); effect++; } @@ -5014,18 +4974,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_HUNGER_SWITCH: - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) { - if (gBattleMons[battler].species == SPECIES_MORPEKO) - { - gBattleMons[battler].species = SPECIES_MORPEKO_HANGRY; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); - } - else if (gBattleMons[battler].species == SPECIES_MORPEKO_HANGRY) - { - gBattleMons[battler].species = SPECIES_MORPEKO; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); - } + BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); effect++; } break; @@ -5709,7 +5660,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move { if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { @@ -5723,7 +5673,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } else if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { @@ -5846,7 +5795,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move break; case ABILITY_GULP_MISSILE: if (((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) - && (effect = ShouldChangeFormHpBased(gBattlerAttacker))) + && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerFormChange; @@ -6125,11 +6074,11 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move #else TRY_WEATHER_FORM: #endif - effect = TryWeatherFormChange(battler); - if (effect != 0) + if ((IsBattlerWeatherAffected(battler, gBattleWeather) || gBattleWeather == B_WEATHER_NONE) + && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_WEATHER)) { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - *(&gBattleStruct->formToChangeInto) = effect - 1; + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); + effect++; } break; case ABILITY_ICE_FACE: @@ -9349,10 +9298,7 @@ static bool32 CanEvolve(u32 species) for (i = 0; i < EVOS_PER_MON; i++) { - if (gEvolutionTable[species][i].method - && gEvolutionTable[species][i].method != EVO_MEGA_EVOLUTION - && gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION - && gEvolutionTable[species][i].method != EVO_PRIMAL_REVERSION) + if (gEvolutionTable[species][i].method) return TRUE; } return FALSE; @@ -10016,46 +9962,27 @@ bool32 IsPartnerMonFromSameTrainer(u8 battlerId) return TRUE; } -u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId) +bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) { u32 i; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; - for (i = 0; i < EVOS_PER_MON; i++) + if (formChanges != NULL) { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_MEGA_EVOLUTION - && gEvolutionTable[preEvoSpecies][i].param == heldItemId) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; - } - return SPECIES_NONE; -} - -u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId) -{ - u32 i; - - for (i = 0; i < EVOS_PER_MON; i++) - { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_PRIMAL_REVERSION - && gEvolutionTable[preEvoSpecies][i].param == heldItemId) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; - } - return SPECIES_NONE; -} - -u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4) -{ - u32 i, par; - - for (i = 0; i < EVOS_PER_MON; i++) - { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_MOVE_MEGA_EVOLUTION) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { - par = gEvolutionTable[preEvoSpecies][i].param; - if (par == moveId1 || par == moveId2 || par == moveId3 || par == moveId4) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; + switch (formChanges[i].method) + { + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_BATTLE_PRIMAL_REVERSION: + case FORM_CHANGE_ITEM_HOLD: + if (formChanges[i].param1 == heldItemId) + return TRUE; + break; + } } } - return SPECIES_NONE; + return FALSE; } bool32 CanMegaEvolve(u8 battlerId) @@ -10098,7 +10025,7 @@ bool32 CanMegaEvolve(u8 battlerId) itemId = GetMonData(mon, MON_DATA_HELD_ITEM); // Check if there is an entry in the evolution table for regular Mega Evolution. - if (GetMegaEvolutionSpecies(species, itemId) != SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE) { #if DEBUG_BATTLE_MENU == TRUE if (gBattleStruct->debugHoldEffects[battlerId]) @@ -10116,85 +10043,162 @@ bool32 CanMegaEvolve(u8 battlerId) } // Check if there is an entry in the evolution table for Wish Mega Evolution. - if (GetWishMegaEvolutionSpecies(species, GetMonData(mon, MON_DATA_MOVE1), GetMonData(mon, MON_DATA_MOVE2), GetMonData(mon, MON_DATA_MOVE3), GetMonData(mon, MON_DATA_MOVE4))) + if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) return TRUE; // No checks passed, the mon CAN'T mega evolve. return FALSE; } -void UndoMegaEvolution(u32 monId) +bool32 IsBattlerMegaEvolved(u8 battlerId) { - u16 baseSpecies = GET_BASE_SPECIES_ID(GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES)); - - if (gBattleStruct->mega.evolvedPartyIds[B_SIDE_PLAYER] & gBitTable[monId]) - { - gBattleStruct->mega.evolvedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]); - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &baseSpecies); - CalculateMonStats(&gPlayerParty[monId]); - } - else if (gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] & gBitTable[monId]) - { - gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]); - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &baseSpecies); - CalculateMonStats(&gPlayerParty[monId]); - } - // While not exactly a mega evolution, Zygarde follows the same rules. - else if (GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, NULL) == SPECIES_ZYGARDE_COMPLETE) - { - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); - gBattleStruct->changedSpecies[monId] = 0; - CalculateMonStats(&gPlayerParty[monId]); - } + // While Transform does copy stats and visuals, it shouldn't be counted as true Mega Evolution. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + return FALSE; + return (gSpeciesInfo[gBattleMons[battlerId].species].flags & SPECIES_FLAG_MEGA_EVOLUTION); } -void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) +bool32 IsBattlerPrimalReverted(u8 battlerId) { - u32 i, currSpecies, targetSpecies; - struct Pokemon *party = GetSideParty(side); - static const u16 species[][3] = - { - // Changed Form ID Default Form ID Should change on switch - {SPECIES_EISCUE_NOICE_FACE, SPECIES_EISCUE, TRUE}, - {SPECIES_MIMIKYU_BUSTED, SPECIES_MIMIKYU, FALSE}, - {SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND, FALSE}, - {SPECIES_MELOETTA_PIROUETTE, SPECIES_MELOETTA, FALSE}, - {SPECIES_AEGISLASH_BLADE, SPECIES_AEGISLASH, TRUE}, - {SPECIES_DARMANITAN_ZEN_MODE, SPECIES_DARMANITAN, TRUE}, - {SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED, TRUE}, - {SPECIES_MINIOR_METEOR_BLUE, SPECIES_MINIOR_CORE_BLUE, TRUE}, - {SPECIES_MINIOR_METEOR_GREEN, SPECIES_MINIOR_CORE_GREEN, TRUE}, - {SPECIES_MINIOR_METEOR_INDIGO, SPECIES_MINIOR_CORE_INDIGO, TRUE}, - {SPECIES_MINIOR_METEOR_ORANGE, SPECIES_MINIOR_CORE_ORANGE, TRUE}, - {SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET, TRUE}, - {SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW, TRUE}, - {SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, TRUE}, - {SPECIES_CRAMORANT_GORGING, SPECIES_CRAMORANT, TRUE}, - {SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT, TRUE}, - {SPECIES_MORPEKO_HANGRY, SPECIES_MORPEKO, TRUE}, - {SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, SPECIES_DARMANITAN_GALARIAN, TRUE}, - }; + // While Transform does copy stats and visuals, it shouldn't be counted as true Primal Revesion. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + return FALSE; + return (gSpeciesInfo[gBattleMons[battlerId].species].flags & SPECIES_FLAG_PRIMAL_REVERSION); +} - currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); - for (i = 0; i < ARRAY_COUNT(species); i++) +// Returns SPECIES_NONE if no form change is possible +u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) +{ + u32 i, j; + u16 targetSpecies = SPECIES_NONE; + u16 species = gBattleMons[battlerId].species; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; + u16 heldItem; + u32 ability; + + if (formChanges != NULL) { - if (currSpecies == species[i][0] && (!isSwitchingOut || species[i][2] == TRUE)) + heldItem = gBattleMons[battlerId].item; + ability = GetBattlerAbility(battlerId); + + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { - SetMonData(&party[monId], MON_DATA_SPECIES, &species[i][1]); - CalculateMonStats(&party[monId]); - break; + if (method == formChanges[i].method && species != formChanges[i].targetSpecies) + { + switch (method) + { + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_BATTLE_PRIMAL_REVERSION: + if (heldItem == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE: + if (gBattleMons[battlerId].moves[0] == formChanges[i].param1 + || gBattleMons[battlerId].moves[1] == formChanges[i].param1 + || gBattleMons[battlerId].moves[2] == formChanges[i].param1 + || gBattleMons[battlerId].moves[3] == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_SWITCH: + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_HP_PERCENT: + if (formChanges[i].param1 == GetBattlerAbility(battlerId)) + { + // We multiply by 100 to make sure that integer division doesn't mess with the health check. + u32 hpCheck = gBattleMons[battlerId].hp * 100 * 100 / gBattleMons[battlerId].maxHP; + switch(formChanges[i].param2) + { + case HP_HIGHER_THAN: + if (hpCheck > formChanges[i].param3 * 100) + targetSpecies = formChanges[i].targetSpecies; + break; + case HP_LOWER_EQ_THAN: + if (hpCheck <= formChanges[i].param3 * 100) + targetSpecies = formChanges[i].targetSpecies; + break; + } + } + break; + case FORM_CHANGE_BATTLE_WEATHER: + if (gBattleWeather & formChanges[i].param1 + || (gBattleWeather == B_WEATHER_NONE && formChanges[i].param1 == B_WEATHER_NONE)) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_TURN_END: + if (formChanges[i].param1 == GetBattlerAbility(battlerId)) + targetSpecies = formChanges[i].targetSpecies; + break; + } + } } } - if (!isSwitchingOut) + + return targetSpecies; +} + +bool32 CanBattlerFormChange(u8 battlerId, u16 method) +{ + // Can't change form if transformed. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED + && B_TRANSFORM_FORM_CHANGES >= GEN_5) + return FALSE; + // Mega Evolved Pokémon should always revert to normal upon fainting or ending the battle. + if (IsBattlerMegaEvolved(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + return TRUE; + else if (IsBattlerPrimalReverted(battlerId) && (method == FORM_CHANGE_END_BATTLE)) + return TRUE; + return DoesSpeciesHaveFormChangeMethod(gBattleMons[battlerId].species, method); +} + +bool32 TryBattleFormChange(u8 battlerId, u16 method) +{ + u8 monId = gBattlerPartyIndexes[battlerId]; + u8 side = GET_BATTLER_SIDE(battlerId); + struct Pokemon *party = GetBattlerParty(battlerId); + u16 targetSpecies; + + if (!CanBattlerFormChange(battlerId, method)) + return FALSE; + + targetSpecies = GetBattleFormChangeTargetSpecies(battlerId, method); + if (targetSpecies == SPECIES_NONE) + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + if (targetSpecies != SPECIES_NONE) { - targetSpecies = GetFormChangeTargetSpecies(&party[monId], FORM_BATTLE_END, 0); - if (targetSpecies != SPECIES_NONE) + // Saves the original species on the first form change for the player. + if (side == B_SIDE_PLAYER && gBattleStruct->changedSpecies[monId] == SPECIES_NONE) + gBattleStruct->changedSpecies[monId] = gBattleMons[battlerId].species; + + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + gBattleMons[battlerId].species = targetSpecies; + RecalcBattlerStats(battlerId, &party[monId]); + return TRUE; + } + else if (gBattleStruct->changedSpecies[monId] != SPECIES_NONE) + { + bool8 restoreSpecies = FALSE; + + // Mega Evolved Pokémon should always revert to normal upon fainting or ending the battle, so no need to add it to the form change tables. + if (IsBattlerMegaEvolved(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + // Unlike Megas, Primal Reversion isn't canceled on fainting. + else if (IsBattlerPrimalReverted(battlerId) && (method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + if (restoreSpecies) { - SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&party[monId]); - TryToSetBattleFormChangeMoves(&party[monId]); + // Reverts the original species + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); + RecalcBattlerStats(battlerId, &party[monId]); + return TRUE; } } + + return FALSE; } bool32 DoBattlersShareType(u32 battler1, u32 battler2) @@ -10225,24 +10229,10 @@ bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId) // Mail can be stolen now if (itemId == ITEM_ENIGMA_BERRY_E_READER) return FALSE; - // Primal Reversion inducing items cannot be lost if pokemon's base species can undergo primal reversion with it. - else if (holdEffect == HOLD_EFFECT_PRIMAL_ORB && (GetPrimalReversionSpecies(GET_BASE_SPECIES_ID(species), itemId) != SPECIES_NONE)) + else if (DoesSpeciesUseHoldItemToChangeForm(species, itemId)) return FALSE; - // Mega stone cannot be lost if pokemon's base species can mega evolve with it. - else if (holdEffect == HOLD_EFFECT_MEGA_STONE && (GetMegaEvolutionSpecies(GET_BASE_SPECIES_ID(species), itemId) != SPECIES_NONE)) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_GIRATINA && itemId == ITEM_GRISEOUS_ORB) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_GENESECT && holdEffect == HOLD_EFFECT_DRIVE) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_SILVALLY && holdEffect == HOLD_EFFECT_MEMORY) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_ARCEUS && holdEffect == HOLD_EFFECT_PLATE) - return FALSE; -#ifdef HOLD_EFFECT_Z_CRYSTAL else if (holdEffect == HOLD_EFFECT_Z_CRYSTAL) return FALSE; -#endif else return TRUE; } @@ -10753,46 +10743,6 @@ bool32 TryRoomService(u8 battlerId) } } -void DoBurmyFormChange(u32 monId) -{ - u16 newSpecies, currSpecies; - struct Pokemon *party = gPlayerParty; - - currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); - - if ((GET_BASE_SPECIES_ID(currSpecies) == SPECIES_BURMY) - && (gBattleStruct->appearedInBattle & gBitTable[monId]) // Burmy appeared in battle - && GetMonData(&party[monId], MON_DATA_HP, NULL) != 0) // Burmy isn't fainted - { - switch (gBattleTerrain) - { - case BATTLE_TERRAIN_GRASS: - case BATTLE_TERRAIN_LONG_GRASS: - case BATTLE_TERRAIN_POND: - case BATTLE_TERRAIN_MOUNTAIN: - case BATTLE_TERRAIN_PLAIN: - newSpecies = SPECIES_BURMY; - break; - case BATTLE_TERRAIN_CAVE: - case BATTLE_TERRAIN_SAND: - newSpecies = SPECIES_BURMY_SANDY_CLOAK; - break; - case BATTLE_TERRAIN_BUILDING: - newSpecies = SPECIES_BURMY_TRASH_CLOAK; - break; - default: // Don't change form if last battle was water-related - newSpecies = SPECIES_NONE; - break; - } - - if (newSpecies != SPECIES_NONE) - { - SetMonData(&party[monId], MON_DATA_SPECIES, &newSpecies); - CalculateMonStats(&party[monId]); - } - } -} - bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget) { #if B_PRANKSTER_DARK_TYPES >= GEN_7 @@ -10886,6 +10836,33 @@ static void SetRandomMultiHitCounter() } } +void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon) +{ + gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL); + gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP); + gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP); + gBattleMons[battler].attack = GetMonData(mon, MON_DATA_ATK); + gBattleMons[battler].defense = GetMonData(mon, MON_DATA_DEF); + gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED); + gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK); + gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF); +} + +void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon) +{ + gBattleMons[battler].ability = GetMonAbility(mon); + gBattleMons[battler].type1 = gSpeciesInfo[gBattleMons[battler].species].types[0]; + gBattleMons[battler].type2 = gSpeciesInfo[gBattleMons[battler].species].types[1]; + gBattleMons[battler].type3 = TYPE_MYSTERY; +} + +void RecalcBattlerStats(u32 battler, struct Pokemon *mon) +{ + CalculateMonStats(mon); + CopyMonLevelAndBaseStatsToBattleMon(battler, mon); + CopyMonAbilityAndTypesToBattleMon(battler, mon); +} + void RemoveConfusionStatus(u8 battlerId) { gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; diff --git a/src/data/items.h b/src/data/items.h index 67c5b477f..1831f11d0 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -3125,7 +3125,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3139,7 +3138,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3153,7 +3151,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3167,7 +3164,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -9092,7 +9088,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_REVEAL_GLASS] = @@ -9104,7 +9099,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_DNA_SPLICERS] = @@ -9114,9 +9108,8 @@ const struct Item gItems[] = .price = 0, .description = sDNASplicersDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_ZYGARDE_CUBE] = @@ -9140,7 +9133,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_N_SOLARIZER] = @@ -9150,9 +9142,8 @@ const struct Item gItems[] = .price = 0, .description = sNSolarizerDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_N_LUNARIZER] = @@ -9162,9 +9153,8 @@ const struct Item gItems[] = .price = 0, .description = sNLunarizerDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_REINS_OF_UNITY] = @@ -9174,9 +9164,8 @@ const struct Item gItems[] = .price = 0, .description = sReinsOfUnityDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, // Battle Mechanic Key Items diff --git a/src/data/pokemon/evolution.h b/src/data/pokemon/evolution.h index f22214817..86ef6dbe5 100644 --- a/src/data/pokemon/evolution.h +++ b/src/data/pokemon/evolution.h @@ -2,22 +2,16 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = { [SPECIES_BULBASAUR] = {{EVO_LEVEL, 16, SPECIES_IVYSAUR}}, [SPECIES_IVYSAUR] = {{EVO_LEVEL, 32, SPECIES_VENUSAUR}}, - [SPECIES_VENUSAUR] = {{EVO_MEGA_EVOLUTION, ITEM_VENUSAURITE, SPECIES_VENUSAUR_MEGA}}, [SPECIES_CHARMANDER] = {{EVO_LEVEL, 16, SPECIES_CHARMELEON}}, [SPECIES_CHARMELEON] = {{EVO_LEVEL, 36, SPECIES_CHARIZARD}}, - [SPECIES_CHARIZARD] = {{EVO_MEGA_EVOLUTION, ITEM_CHARIZARDITE_X, SPECIES_CHARIZARD_MEGA_X}, - {EVO_MEGA_EVOLUTION, ITEM_CHARIZARDITE_Y, SPECIES_CHARIZARD_MEGA_Y}}, [SPECIES_SQUIRTLE] = {{EVO_LEVEL, 16, SPECIES_WARTORTLE}}, [SPECIES_WARTORTLE] = {{EVO_LEVEL, 36, SPECIES_BLASTOISE}}, - [SPECIES_BLASTOISE] = {{EVO_MEGA_EVOLUTION, ITEM_BLASTOISINITE, SPECIES_BLASTOISE_MEGA}}, [SPECIES_CATERPIE] = {{EVO_LEVEL, 7, SPECIES_METAPOD}}, [SPECIES_METAPOD] = {{EVO_LEVEL, 10, SPECIES_BUTTERFREE}}, [SPECIES_WEEDLE] = {{EVO_LEVEL, 7, SPECIES_KAKUNA}}, [SPECIES_KAKUNA] = {{EVO_LEVEL, 10, SPECIES_BEEDRILL}}, - [SPECIES_BEEDRILL] = {{EVO_MEGA_EVOLUTION, ITEM_BEEDRILLITE, SPECIES_BEEDRILL_MEGA}}, [SPECIES_PIDGEY] = {{EVO_LEVEL, 18, SPECIES_PIDGEOTTO}}, [SPECIES_PIDGEOTTO] = {{EVO_LEVEL, 36, SPECIES_PIDGEOT}}, - [SPECIES_PIDGEOT] = {{EVO_MEGA_EVOLUTION, ITEM_PIDGEOTITE, SPECIES_PIDGEOT_MEGA}}, [SPECIES_RATTATA] = {{EVO_LEVEL, 20, SPECIES_RATICATE}}, [SPECIES_SPEAROW] = {{EVO_LEVEL, 20, SPECIES_FEAROW}}, [SPECIES_EKANS] = {{EVO_LEVEL, 22, SPECIES_ARBOK}}, @@ -49,7 +43,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_ABRA] = {{EVO_LEVEL, 16, SPECIES_KADABRA}}, [SPECIES_KADABRA] = {{EVO_TRADE, 0, SPECIES_ALAKAZAM}, {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_ALAKAZAM}}, - [SPECIES_ALAKAZAM] = {{EVO_MEGA_EVOLUTION, ITEM_ALAKAZITE, SPECIES_ALAKAZAM_MEGA}}, [SPECIES_MACHOP] = {{EVO_LEVEL, 28, SPECIES_MACHOKE}}, [SPECIES_MACHOKE] = {{EVO_TRADE, 0, SPECIES_MACHAMP}, {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_MACHAMP}}, @@ -62,7 +55,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_PONYTA] = {{EVO_LEVEL, 40, SPECIES_RAPIDASH}}, [SPECIES_SLOWPOKE] = {{EVO_LEVEL, 37, SPECIES_SLOWBRO}, {EVO_TRADE_ITEM, ITEM_KINGS_ROCK, SPECIES_SLOWKING}}, - [SPECIES_SLOWBRO] = {{EVO_MEGA_EVOLUTION, ITEM_SLOWBRONITE, SPECIES_SLOWBRO_MEGA}}, [SPECIES_MAGNEMITE] = {{EVO_LEVEL, 30, SPECIES_MAGNETON}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_MAGNETON] = {{EVO_MAPSEC, MAPSEC_NEW_MAUVILLE, SPECIES_MAGNEZONE}, @@ -75,7 +67,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_GASTLY] = {{EVO_LEVEL, 25, SPECIES_HAUNTER}}, [SPECIES_HAUNTER] = {{EVO_TRADE, 0, SPECIES_GENGAR}, {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GENGAR}}, - [SPECIES_GENGAR] = {{EVO_MEGA_EVOLUTION, ITEM_GENGARITE, SPECIES_GENGAR_MEGA}}, [SPECIES_ONIX] = {{EVO_TRADE_ITEM, ITEM_METAL_COAT, SPECIES_STEELIX}}, [SPECIES_DROWZEE] = {{EVO_LEVEL, 26, SPECIES_HYPNO}}, [SPECIES_KRABBY] = {{EVO_LEVEL, 28, SPECIES_KINGLER}}, @@ -96,7 +87,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_TANGELA] = {{EVO_MOVE, MOVE_ANCIENT_POWER, SPECIES_TANGROWTH}}, #endif - [SPECIES_KANGASKHAN] = {{EVO_MEGA_EVOLUTION, ITEM_KANGASKHANITE, SPECIES_KANGASKHAN_MEGA}}, [SPECIES_HORSEA] = {{EVO_LEVEL, 32, SPECIES_SEADRA}}, [SPECIES_SEADRA] = {{EVO_TRADE_ITEM, ITEM_DRAGON_SCALE, SPECIES_KINGDRA}}, [SPECIES_GOLDEEN] = {{EVO_LEVEL, 33, SPECIES_SEAKING}}, @@ -107,9 +97,7 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_ELECTABUZZ] = {{EVO_TRADE_ITEM, ITEM_ELECTIRIZER, SPECIES_ELECTIVIRE}}, [SPECIES_MAGMAR] = {{EVO_TRADE_ITEM, ITEM_MAGMARIZER, SPECIES_MAGMORTAR}}, #endif - [SPECIES_PINSIR] = {{EVO_MEGA_EVOLUTION, ITEM_PINSIRITE, SPECIES_PINSIR_MEGA}}, [SPECIES_MAGIKARP] = {{EVO_LEVEL, 20, SPECIES_GYARADOS}}, - [SPECIES_GYARADOS] = {{EVO_MEGA_EVOLUTION, ITEM_GYARADOSITE, SPECIES_GYARADOS_MEGA}}, [SPECIES_EEVEE] = {{EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_JOLTEON}, {EVO_ITEM, ITEM_WATER_STONE, SPECIES_VAPOREON}, {EVO_ITEM, ITEM_FIRE_STONE, SPECIES_FLAREON}, @@ -128,11 +116,8 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_PORYGON] = {{EVO_TRADE_ITEM, ITEM_UPGRADE, SPECIES_PORYGON2}}, [SPECIES_OMANYTE] = {{EVO_LEVEL, 40, SPECIES_OMASTAR}}, [SPECIES_KABUTO] = {{EVO_LEVEL, 40, SPECIES_KABUTOPS}}, - [SPECIES_AERODACTYL] = {{EVO_MEGA_EVOLUTION, ITEM_AERODACTYLITE, SPECIES_AERODACTYL_MEGA}}, [SPECIES_DRATINI] = {{EVO_LEVEL, 30, SPECIES_DRAGONAIR}}, [SPECIES_DRAGONAIR] = {{EVO_LEVEL, 55, SPECIES_DRAGONITE}}, - [SPECIES_MEWTWO] = {{EVO_MEGA_EVOLUTION, ITEM_MEWTWONITE_X, SPECIES_MEWTWO_MEGA_X}, - {EVO_MEGA_EVOLUTION, ITEM_MEWTWONITE_Y, SPECIES_MEWTWO_MEGA_Y}}, [SPECIES_CHIKORITA] = {{EVO_LEVEL, 16, SPECIES_BAYLEEF}}, [SPECIES_BAYLEEF] = {{EVO_LEVEL, 32, SPECIES_MEGANIUM}}, [SPECIES_CYNDAQUIL] = {{EVO_LEVEL, 14, SPECIES_QUILAVA}}, @@ -154,7 +139,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_NATU] = {{EVO_LEVEL, 25, SPECIES_XATU}}, [SPECIES_MAREEP] = {{EVO_LEVEL, 15, SPECIES_FLAAFFY}}, [SPECIES_FLAAFFY] = {{EVO_LEVEL, 30, SPECIES_AMPHAROS}}, - [SPECIES_AMPHAROS] = {{EVO_MEGA_EVOLUTION, ITEM_AMPHAROSITE, SPECIES_AMPHAROS_MEGA}}, [SPECIES_MARILL] = {{EVO_LEVEL, 18, SPECIES_AZUMARILL}}, [SPECIES_HOPPIP] = {{EVO_LEVEL, 18, SPECIES_SKIPLOOM}}, [SPECIES_SKIPLOOM] = {{EVO_LEVEL, 27, SPECIES_JUMPLUFF}}, @@ -172,10 +156,7 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_GLIGAR] = {{EVO_ITEM_HOLD_NIGHT, ITEM_RAZOR_FANG, SPECIES_GLISCOR}}, #endif - [SPECIES_STEELIX] = {{EVO_MEGA_EVOLUTION, ITEM_STEELIXITE, SPECIES_STEELIX_MEGA}}, [SPECIES_SNUBBULL] = {{EVO_LEVEL, 23, SPECIES_GRANBULL}}, - [SPECIES_SCIZOR] = {{EVO_MEGA_EVOLUTION, ITEM_SCIZORITE, SPECIES_SCIZOR_MEGA}}, - [SPECIES_HERACROSS] = {{EVO_MEGA_EVOLUTION, ITEM_HERACRONITE, SPECIES_HERACROSS_MEGA}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_SNEASEL] = {{EVO_ITEM_HOLD_NIGHT, ITEM_RAZOR_CLAW, SPECIES_WEAVILE}}, #endif @@ -187,7 +168,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #endif [SPECIES_REMORAID] = {{EVO_LEVEL, 25, SPECIES_OCTILLERY}}, [SPECIES_HOUNDOUR] = {{EVO_LEVEL, 24, SPECIES_HOUNDOOM}}, - [SPECIES_HOUNDOOM] = {{EVO_MEGA_EVOLUTION, ITEM_HOUNDOOMINITE, SPECIES_HOUNDOOM_MEGA}}, [SPECIES_PHANPY] = {{EVO_LEVEL, 25, SPECIES_DONPHAN}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_PORYGON2] = {{EVO_TRADE_ITEM, ITEM_DUBIOUS_DISC, SPECIES_PORYGON_Z}}, @@ -200,16 +180,12 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_MAGBY] = {{EVO_LEVEL, 30, SPECIES_MAGMAR}}, [SPECIES_LARVITAR] = {{EVO_LEVEL, 30, SPECIES_PUPITAR}}, [SPECIES_PUPITAR] = {{EVO_LEVEL, 55, SPECIES_TYRANITAR}}, - [SPECIES_TYRANITAR] = {{EVO_MEGA_EVOLUTION, ITEM_TYRANITARITE, SPECIES_TYRANITAR_MEGA}}, [SPECIES_TREECKO] = {{EVO_LEVEL, 16, SPECIES_GROVYLE}}, [SPECIES_GROVYLE] = {{EVO_LEVEL, 36, SPECIES_SCEPTILE}}, - [SPECIES_SCEPTILE] = {{EVO_MEGA_EVOLUTION, ITEM_SCEPTILITE, SPECIES_SCEPTILE_MEGA}}, [SPECIES_TORCHIC] = {{EVO_LEVEL, 16, SPECIES_COMBUSKEN}}, [SPECIES_COMBUSKEN] = {{EVO_LEVEL, 36, SPECIES_BLAZIKEN}}, - [SPECIES_BLAZIKEN] = {{EVO_MEGA_EVOLUTION, ITEM_BLAZIKENITE, SPECIES_BLAZIKEN_MEGA}}, [SPECIES_MUDKIP] = {{EVO_LEVEL, 16, SPECIES_MARSHTOMP}}, [SPECIES_MARSHTOMP] = {{EVO_LEVEL, 36, SPECIES_SWAMPERT}}, - [SPECIES_SWAMPERT] = {{EVO_MEGA_EVOLUTION, ITEM_SWAMPERTITE, SPECIES_SWAMPERT_MEGA}}, [SPECIES_POOCHYENA] = {{EVO_LEVEL, 18, SPECIES_MIGHTYENA}}, [SPECIES_ZIGZAGOON] = {{EVO_LEVEL, 20, SPECIES_LINOONE}}, [SPECIES_WURMPLE] = {{EVO_LEVEL_SILCOON, 7, SPECIES_SILCOON}, @@ -232,20 +208,16 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_NOSEPASS] = {{EVO_MAPSEC, MAPSEC_NEW_MAUVILLE, SPECIES_PROBOPASS}}, #endif - [SPECIES_SABLEYE] = {{EVO_MEGA_EVOLUTION, ITEM_SABLENITE, SPECIES_SABLEYE_MEGA}}, [SPECIES_BARBOACH] = {{EVO_LEVEL, 30, SPECIES_WHISCASH}}, [SPECIES_CORPHISH] = {{EVO_LEVEL, 30, SPECIES_CRAWDAUNT}}, [SPECIES_FEEBAS] = {{EVO_BEAUTY, 170, SPECIES_MILOTIC}, {EVO_TRADE_ITEM, ITEM_PRISM_SCALE, SPECIES_MILOTIC}}, [SPECIES_CARVANHA] = {{EVO_LEVEL, 30, SPECIES_SHARPEDO}}, - [SPECIES_SHARPEDO] = {{EVO_MEGA_EVOLUTION, ITEM_SHARPEDONITE, SPECIES_SHARPEDO_MEGA}}, [SPECIES_TRAPINCH] = {{EVO_LEVEL, 35, SPECIES_VIBRAVA}}, [SPECIES_VIBRAVA] = {{EVO_LEVEL, 45, SPECIES_FLYGON}}, [SPECIES_MAKUHITA] = {{EVO_LEVEL, 24, SPECIES_HARIYAMA}}, [SPECIES_ELECTRIKE] = {{EVO_LEVEL, 26, SPECIES_MANECTRIC}}, - [SPECIES_MANECTRIC] = {{EVO_MEGA_EVOLUTION, ITEM_MANECTITE, SPECIES_MANECTRIC_MEGA}}, [SPECIES_NUMEL] = {{EVO_LEVEL, 33, SPECIES_CAMERUPT}}, - [SPECIES_CAMERUPT] = {{EVO_MEGA_EVOLUTION, ITEM_CAMERUPTITE, SPECIES_CAMERUPT_MEGA}}, [SPECIES_SPHEAL] = {{EVO_LEVEL, 32, SPECIES_SEALEO}}, [SPECIES_SEALEO] = {{EVO_LEVEL, 44, SPECIES_WALREIN}}, [SPECIES_CACNEA] = {{EVO_LEVEL, 32, SPECIES_CACTURNE}}, @@ -254,14 +226,10 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_ITEM_FEMALE, ITEM_DAWN_STONE, SPECIES_FROSLASS} #endif }, - [SPECIES_GLALIE] = {{EVO_MEGA_EVOLUTION, ITEM_GLALITITE, SPECIES_GLALIE_MEGA}}, [SPECIES_AZURILL] = {{EVO_FRIENDSHIP, 0, SPECIES_MARILL}}, [SPECIES_SPOINK] = {{EVO_LEVEL, 32, SPECIES_GRUMPIG}}, - [SPECIES_MAWILE] = {{EVO_MEGA_EVOLUTION, ITEM_MAWILITE, SPECIES_MAWILE_MEGA}}, [SPECIES_MEDITITE] = {{EVO_LEVEL, 37, SPECIES_MEDICHAM}}, - [SPECIES_MEDICHAM] = {{EVO_MEGA_EVOLUTION, ITEM_MEDICHAMITE, SPECIES_MEDICHAM_MEGA}}, [SPECIES_SWABLU] = {{EVO_LEVEL, 35, SPECIES_ALTARIA}}, - [SPECIES_ALTARIA] = {{EVO_MEGA_EVOLUTION, ITEM_ALTARIANITE, SPECIES_ALTARIA_MEGA}}, [SPECIES_WYNAUT] = {{EVO_LEVEL, 15, SPECIES_WOBBUFFET}}, [SPECIES_DUSKULL] = {{EVO_LEVEL, 37, SPECIES_DUSCLOPS}}, #if P_GEN_4_POKEMON == TRUE @@ -275,12 +243,9 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_LOUDRED] = {{EVO_LEVEL, 40, SPECIES_EXPLOUD}}, [SPECIES_CLAMPERL] = {{EVO_TRADE_ITEM, ITEM_DEEP_SEA_TOOTH, SPECIES_HUNTAIL}, {EVO_TRADE_ITEM, ITEM_DEEP_SEA_SCALE, SPECIES_GOREBYSS}}, - [SPECIES_ABSOL] = {{EVO_MEGA_EVOLUTION, ITEM_ABSOLITE, SPECIES_ABSOL_MEGA}}, [SPECIES_SHUPPET] = {{EVO_LEVEL, 37, SPECIES_BANETTE}}, - [SPECIES_BANETTE] = {{EVO_MEGA_EVOLUTION, ITEM_BANETTITE, SPECIES_BANETTE_MEGA}}, [SPECIES_ARON] = {{EVO_LEVEL, 32, SPECIES_LAIRON}}, [SPECIES_LAIRON] = {{EVO_LEVEL, 42, SPECIES_AGGRON}}, - [SPECIES_AGGRON] = {{EVO_MEGA_EVOLUTION, ITEM_AGGRONITE, SPECIES_AGGRON_MEGA}}, [SPECIES_LILEEP] = {{EVO_LEVEL, 40, SPECIES_CRADILY}}, [SPECIES_ANORITH] = {{EVO_LEVEL, 40, SPECIES_ARMALDO}}, [SPECIES_RALTS] = {{EVO_LEVEL, 20, SPECIES_KIRLIA}}, @@ -289,19 +254,10 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_ITEM_MALE, ITEM_DAWN_STONE, SPECIES_GALLADE} #endif }, - [SPECIES_GARDEVOIR] = {{EVO_MEGA_EVOLUTION, ITEM_GARDEVOIRITE, SPECIES_GARDEVOIR_MEGA}}, [SPECIES_BAGON] = {{EVO_LEVEL, 30, SPECIES_SHELGON}}, [SPECIES_SHELGON] = {{EVO_LEVEL, 50, SPECIES_SALAMENCE}}, - [SPECIES_SALAMENCE] = {{EVO_MEGA_EVOLUTION, ITEM_SALAMENCITE, SPECIES_SALAMENCE_MEGA}}, [SPECIES_BELDUM] = {{EVO_LEVEL, 20, SPECIES_METANG}}, [SPECIES_METANG] = {{EVO_LEVEL, 45, SPECIES_METAGROSS}}, - [SPECIES_METAGROSS] = {{EVO_MEGA_EVOLUTION, ITEM_METAGROSSITE, SPECIES_METAGROSS_MEGA}}, - [SPECIES_LATIAS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIASITE, SPECIES_LATIAS_MEGA}}, - [SPECIES_LATIOS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIOSITE, SPECIES_LATIOS_MEGA}}, - [SPECIES_KYOGRE] = {{EVO_PRIMAL_REVERSION, ITEM_BLUE_ORB, SPECIES_KYOGRE_PRIMAL}}, - [SPECIES_GROUDON] = {{EVO_PRIMAL_REVERSION, ITEM_RED_ORB, SPECIES_GROUDON_PRIMAL}}, - [SPECIES_RAYQUAZA] = {{EVO_MOVE_MEGA_EVOLUTION, MOVE_DRAGON_ASCENT, SPECIES_RAYQUAZA_MEGA}}, - #if P_GEN_4_POKEMON == TRUE // Gens 4-7 [SPECIES_TURTWIG] = {{EVO_LEVEL, 18, SPECIES_GROTLE}}, @@ -327,7 +283,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_SHELLOS] = {{EVO_LEVEL, 30, SPECIES_GASTRODON}}, [SPECIES_DRIFLOON] = {{EVO_LEVEL, 28, SPECIES_DRIFBLIM}}, [SPECIES_BUNEARY] = {{EVO_FRIENDSHIP, 0, SPECIES_LOPUNNY}}, - [SPECIES_LOPUNNY] = {{EVO_MEGA_EVOLUTION, ITEM_LOPUNNITE, SPECIES_LOPUNNY_MEGA}}, [SPECIES_GLAMEOW] = {{EVO_LEVEL, 38, SPECIES_PURUGLY}}, [SPECIES_CHINGLING] = {{EVO_FRIENDSHIP_NIGHT, 0, SPECIES_CHIMECHO}}, [SPECIES_STUNKY] = {{EVO_LEVEL, 34, SPECIES_SKUNTANK}}, @@ -337,18 +292,14 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_HAPPINY] = {{EVO_ITEM_HOLD_DAY, ITEM_OVAL_STONE, SPECIES_CHANSEY}}, [SPECIES_GIBLE] = {{EVO_LEVEL, 24, SPECIES_GABITE}}, [SPECIES_GABITE] = {{EVO_LEVEL, 48, SPECIES_GARCHOMP}}, - [SPECIES_GARCHOMP] = {{EVO_MEGA_EVOLUTION, ITEM_GARCHOMPITE, SPECIES_GARCHOMP_MEGA}}, [SPECIES_MUNCHLAX] = {{EVO_FRIENDSHIP, 0, SPECIES_SNORLAX}}, [SPECIES_RIOLU] = {{EVO_FRIENDSHIP_DAY, 0, SPECIES_LUCARIO}}, - [SPECIES_LUCARIO] = {{EVO_MEGA_EVOLUTION, ITEM_LUCARIONITE, SPECIES_LUCARIO_MEGA}}, [SPECIES_HIPPOPOTAS] = {{EVO_LEVEL, 34, SPECIES_HIPPOWDON}}, [SPECIES_SKORUPI] = {{EVO_LEVEL, 40, SPECIES_DRAPION}}, [SPECIES_CROAGUNK] = {{EVO_LEVEL, 37, SPECIES_TOXICROAK}}, [SPECIES_FINNEON] = {{EVO_LEVEL, 31, SPECIES_LUMINEON}}, [SPECIES_MANTYKE] = {{EVO_SPECIFIC_MON_IN_PARTY, SPECIES_REMORAID, SPECIES_MANTINE}}, [SPECIES_SNOVER] = {{EVO_LEVEL, 40, SPECIES_ABOMASNOW}}, - [SPECIES_ABOMASNOW] = {{EVO_MEGA_EVOLUTION, ITEM_ABOMASITE, SPECIES_ABOMASNOW_MEGA}}, - [SPECIES_GALLADE] = {{EVO_MEGA_EVOLUTION, ITEM_GALLADITE, SPECIES_GALLADE_MEGA}}, #endif #if P_GEN_5_POKEMON == TRUE [SPECIES_SNIVY] = {{EVO_LEVEL, 17, SPECIES_SERVINE}}, @@ -373,7 +324,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GIGALITH}}, [SPECIES_WOOBAT] = {{EVO_FRIENDSHIP, 0, SPECIES_SWOOBAT}}, [SPECIES_DRILBUR] = {{EVO_LEVEL, 31, SPECIES_EXCADRILL}}, - [SPECIES_AUDINO] = {{EVO_MEGA_EVOLUTION, ITEM_AUDINITE, SPECIES_AUDINO_MEGA}}, [SPECIES_TIMBURR] = {{EVO_LEVEL, 25, SPECIES_GURDURR}}, [SPECIES_GURDURR] = {{EVO_TRADE, 0, SPECIES_CONKELDURR}, {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_CONKELDURR}}, @@ -467,7 +417,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GOURGEIST}}, [SPECIES_BERGMITE] = {{EVO_LEVEL, 37, SPECIES_AVALUGG}}, [SPECIES_NOIBAT] = {{EVO_LEVEL, 48, SPECIES_NOIVERN}}, - [SPECIES_DIANCIE] = {{EVO_MEGA_EVOLUTION, ITEM_DIANCITE, SPECIES_DIANCIE_MEGA}}, #endif #if P_GEN_7_POKEMON == TRUE [SPECIES_ROWLET] = {{EVO_LEVEL, 17, SPECIES_DARTRIX}}, diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index 62afeb2e0..daeaa9cbb 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -1,6 +1,107 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = { + [SPECIES_VENUSAUR] = sVenusaurFormChangeTable, + [SPECIES_VENUSAUR_MEGA] = sVenusaurFormChangeTable, + [SPECIES_CHARIZARD] = sCharizardFormChangeTable, + [SPECIES_CHARIZARD_MEGA_X] = sCharizardFormChangeTable, + [SPECIES_CHARIZARD_MEGA_Y] = sCharizardFormChangeTable, + [SPECIES_BLASTOISE] = sBlastoiseFormChangeTable, + [SPECIES_BLASTOISE_MEGA] = sBlastoiseFormChangeTable, + [SPECIES_BEEDRILL] = sBeedrillFormChangeTable, + [SPECIES_BEEDRILL_MEGA] = sBeedrillFormChangeTable, + [SPECIES_PIDGEOT] = sPidgeotFormChangeTable, + [SPECIES_PIDGEOT_MEGA] = sPidgeotFormChangeTable, + [SPECIES_ALAKAZAM] = sAlakazamFormChangeTable, + [SPECIES_ALAKAZAM_MEGA] = sAlakazamFormChangeTable, + [SPECIES_SLOWBRO] = sSlowbroFormChangeTable, + [SPECIES_SLOWBRO_MEGA] = sSlowbroFormChangeTable, + [SPECIES_GENGAR] = sGengarFormChangeTable, + [SPECIES_GENGAR_MEGA] = sGengarFormChangeTable, + [SPECIES_KANGASKHAN] = sKangaskhanFormChangeTable, + [SPECIES_KANGASKHAN_MEGA] = sKangaskhanFormChangeTable, + [SPECIES_PINSIR] = sPinsirFormChangeTable, + [SPECIES_PINSIR_MEGA] = sPinsirFormChangeTable, + [SPECIES_GYARADOS] = sGyaradosFormChangeTable, + [SPECIES_GYARADOS_MEGA] = sGyaradosFormChangeTable, + [SPECIES_AERODACTYL] = sAerodactylFormChangeTable, + [SPECIES_AERODACTYL_MEGA] = sAerodactylFormChangeTable, + [SPECIES_MEWTWO] = sMewtwoFormChangeTable, + [SPECIES_MEWTWO_MEGA_X] = sMewtwoFormChangeTable, + [SPECIES_MEWTWO_MEGA_Y] = sMewtwoFormChangeTable, + [SPECIES_AMPHAROS] = sAmpharosFormChangeTable, + [SPECIES_AMPHAROS_MEGA] = sAmpharosFormChangeTable, + [SPECIES_STEELIX] = sSteelixFormChangeTable, + [SPECIES_STEELIX_MEGA] = sSteelixFormChangeTable, + [SPECIES_SCIZOR] = sScizorFormChangeTable, + [SPECIES_SCIZOR_MEGA] = sScizorFormChangeTable, + [SPECIES_HERACROSS] = sHeracrossFormChangeTable, + [SPECIES_HERACROSS_MEGA] = sHeracrossFormChangeTable, + [SPECIES_HOUNDOOM] = sHoundoomFormChangeTable, + [SPECIES_HOUNDOOM_MEGA] = sHoundoomFormChangeTable, + [SPECIES_TYRANITAR] = sTyranitarFormChangeTable, + [SPECIES_TYRANITAR_MEGA] = sTyranitarFormChangeTable, + [SPECIES_SCEPTILE] = sSceptileFormChangeTable, + [SPECIES_SCEPTILE_MEGA] = sSceptileFormChangeTable, + [SPECIES_BLAZIKEN] = sBlazikenFormChangeTable, + [SPECIES_BLAZIKEN_MEGA] = sBlazikenFormChangeTable, + [SPECIES_SWAMPERT] = sSwampertFormChangeTable, + [SPECIES_SWAMPERT_MEGA] = sSwampertFormChangeTable, + [SPECIES_SABLEYE] = sSableyeFormChangeTable, + [SPECIES_SABLEYE_MEGA] = sSableyeFormChangeTable, + [SPECIES_SHARPEDO] = sSharpedoFormChangeTable, + [SPECIES_SHARPEDO_MEGA] = sSharpedoFormChangeTable, + [SPECIES_MANECTRIC] = sManectricFormChangeTable, + [SPECIES_MANECTRIC_MEGA] = sManectricFormChangeTable, + [SPECIES_CAMERUPT] = sCameruptFormChangeTable, + [SPECIES_CAMERUPT_MEGA] = sCameruptFormChangeTable, + [SPECIES_GLALIE] = sGlalieFormChangeTable, + [SPECIES_GLALIE_MEGA] = sGlalieFormChangeTable, + [SPECIES_MAWILE] = sMawileFormChangeTable, + [SPECIES_MAWILE_MEGA] = sMawileFormChangeTable, + [SPECIES_MEDICHAM] = sMedichamFormChangeTable, + [SPECIES_MEDICHAM_MEGA] = sMedichamFormChangeTable, + [SPECIES_ALTARIA] = sAltariaFormChangeTable, + [SPECIES_ALTARIA_MEGA] = sAltariaFormChangeTable, + [SPECIES_ABSOL] = sAbsolFormChangeTable, + [SPECIES_ABSOL_MEGA] = sAbsolFormChangeTable, + [SPECIES_CASTFORM] = sCastformFormChangeTable, + [SPECIES_CASTFORM_SUNNY] = sCastformFormChangeTable, + [SPECIES_CASTFORM_RAINY] = sCastformFormChangeTable, + [SPECIES_CASTFORM_SNOWY] = sCastformFormChangeTable, + [SPECIES_BANETTE] = sBanetteFormChangeTable, + [SPECIES_BANETTE_MEGA] = sBanetteFormChangeTable, + [SPECIES_AGGRON] = sAggronFormChangeTable, + [SPECIES_AGGRON_MEGA] = sAggronFormChangeTable, + [SPECIES_GARDEVOIR] = sGardevoirFormChangeTable, + [SPECIES_GARDEVOIR_MEGA] = sGardevoirFormChangeTable, + [SPECIES_SALAMENCE] = sSalamenceFormChangeTable, + [SPECIES_SALAMENCE_MEGA] = sSalamenceFormChangeTable, + [SPECIES_METAGROSS] = sMetagrossFormChangeTable, + [SPECIES_METAGROSS_MEGA] = sMetagrossFormChangeTable, + [SPECIES_LATIAS] = sLatiasFormChangeTable, + [SPECIES_LATIAS_MEGA] = sLatiasFormChangeTable, + [SPECIES_LATIOS] = sLatiosFormChangeTable, + [SPECIES_LATIOS_MEGA] = sLatiosFormChangeTable, + [SPECIES_KYOGRE] = sKyogreFormChangeTable, + [SPECIES_KYOGRE_PRIMAL] = sKyogreFormChangeTable, + [SPECIES_GROUDON] = sGroudonFormChangeTable, + [SPECIES_GROUDON_PRIMAL] = sGroudonFormChangeTable, + [SPECIES_RAYQUAZA] = sRayquazaFormChangeTable, + [SPECIES_RAYQUAZA_MEGA] = sRayquazaFormChangeTable, #if P_GEN_4_POKEMON == TRUE + [SPECIES_BURMY] = sBurmyFormChangeTable, + [SPECIES_BURMY_SANDY_CLOAK] = sBurmyFormChangeTable, + [SPECIES_BURMY_TRASH_CLOAK] = sBurmyFormChangeTable, + [SPECIES_LOPUNNY] = sLopunnyFormChangeTable, + [SPECIES_LOPUNNY_MEGA] = sLopunnyFormChangeTable, + [SPECIES_GARCHOMP] = sGarchompFormChangeTable, + [SPECIES_GARCHOMP_MEGA] = sGarchompFormChangeTable, + [SPECIES_LUCARIO] = sLucarioFormChangeTable, + [SPECIES_LUCARIO_MEGA] = sLucarioFormChangeTable, + [SPECIES_ABOMASNOW] = sAbomasnowFormChangeTable, + [SPECIES_ABOMASNOW_MEGA] = sAbomasnowFormChangeTable, + [SPECIES_GALLADE] = sGalladeFormChangeTable, + [SPECIES_GALLADE_MEGA] = sGalladeFormChangeTable, [SPECIES_DIALGA] = sDialgaFormChangeTable, [SPECIES_DIALGA_ORIGIN] = sDialgaFormChangeTable, [SPECIES_PALKIA] = sPalkiaFormChangeTable, @@ -29,6 +130,12 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_ARCEUS_FAIRY] = sArceusFormChangeTable, #endif #if P_GEN_5_POKEMON == TRUE + [SPECIES_AUDINO] = sAudinoFormChangeTable, + [SPECIES_AUDINO_MEGA] = sAudinoFormChangeTable, + [SPECIES_DARMANITAN] = sDarmanitanFormChangeTable, + [SPECIES_DARMANITAN_ZEN_MODE] = sDarmanitanFormChangeTable, + [SPECIES_DARMANITAN_GALARIAN] = sDarmanitanGalarianFormChangeTable, + [SPECIES_DARMANITAN_ZEN_MODE_GALARIAN] = sDarmanitanGalarianFormChangeTable, [SPECIES_TORNADUS] = sTornadusFormChangeTable, [SPECIES_TORNADUS_THERIAN] = sTornadusFormChangeTable, [SPECIES_THUNDURUS] = sThundurusFormChangeTable, @@ -37,6 +144,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_LANDORUS_THERIAN] = sLandorusFormChangeTable, [SPECIES_KELDEO] = sKeldeoFormChangeTable, [SPECIES_KELDEO_RESOLUTE] = sKeldeoFormChangeTable, + [SPECIES_MELOETTA] = sMeloettaFormChangeTable, + [SPECIES_MELOETTA_PIROUETTE] = sMeloettaFormChangeTable, [SPECIES_GENESECT] = sGenesectFormChangeTable, [SPECIES_GENESECT_DOUSE_DRIVE] = sGenesectFormChangeTable, [SPECIES_GENESECT_SHOCK_DRIVE] = sGenesectFormChangeTable, @@ -44,8 +153,17 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_GENESECT_CHILL_DRIVE] = sGenesectFormChangeTable, #endif #if P_GEN_6_POKEMON == TRUE + [SPECIES_GRENINJA_BATTLE_BOND] = sGreninjaBattleBondFormChangeTable, + [SPECIES_GRENINJA_ASH] = sGreninjaBattleBondFormChangeTable, + [SPECIES_AEGISLASH] = sAegislashFormChangeTable, + [SPECIES_AEGISLASH_BLADE] = sAegislashFormChangeTable, [SPECIES_XERNEAS] = sXerneasFormChangeTable, [SPECIES_XERNEAS_ACTIVE] = sXerneasFormChangeTable, + [SPECIES_ZYGARDE_10_POWER_CONSTRUCT] = sZygardePowerConstructFormChangeTable, + [SPECIES_ZYGARDE_50_POWER_CONSTRUCT] = sZygardePowerConstructFormChangeTable, + [SPECIES_ZYGARDE_COMPLETE] = sZygardePowerConstructFormChangeTable, + [SPECIES_DIANCIE] = sDiancieFormChangeTable, + [SPECIES_DIANCIE_MEGA] = sDiancieFormChangeTable, [SPECIES_HOOPA] = sHoopaFormChangeTable, [SPECIES_HOOPA_UNBOUND] = sHoopaFormChangeTable, #endif @@ -54,6 +172,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_ORICORIO_POM_POM] = sOricorioFormChangeTable, [SPECIES_ORICORIO_PAU] = sOricorioFormChangeTable, [SPECIES_ORICORIO_SENSU] = sOricorioFormChangeTable, + [SPECIES_WISHIWASHI] = sWishiwashiFormChangeTable, + [SPECIES_WISHIWASHI_SCHOOL] = sWishiwashiFormChangeTable, [SPECIES_SILVALLY] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_BUG] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_DARK] = sSilvallyFormChangeTable, @@ -72,8 +192,31 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_SILVALLY_ROCK] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_STEEL] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_WATER] = sSilvallyFormChangeTable, + [SPECIES_MIMIKYU] = sMimikyuFormChangeTable, + [SPECIES_MIMIKYU_BUSTED] = sMimikyuFormChangeTable, + [SPECIES_MINIOR] = sMiniorRedFormChangeTable, + [SPECIES_MINIOR_CORE_RED] = sMiniorRedFormChangeTable, + [SPECIES_MINIOR_METEOR_BLUE] = sMiniorBlueFormChangeTable, + [SPECIES_MINIOR_CORE_BLUE] = sMiniorBlueFormChangeTable, + [SPECIES_MINIOR_METEOR_GREEN] = sMiniorGreenFormChangeTable, + [SPECIES_MINIOR_CORE_GREEN] = sMiniorGreenFormChangeTable, + [SPECIES_MINIOR_METEOR_INDIGO] = sMiniorIndigoFormChangeTable, + [SPECIES_MINIOR_CORE_INDIGO] = sMiniorIndigoFormChangeTable, + [SPECIES_MINIOR_METEOR_ORANGE] = sMiniorOrangeFormChangeTable, + [SPECIES_MINIOR_CORE_ORANGE] = sMiniorOrangeFormChangeTable, + [SPECIES_MINIOR_METEOR_VIOLET] = sMiniorVioletFormChangeTable, + [SPECIES_MINIOR_CORE_VIOLET] = sMiniorVioletFormChangeTable, + [SPECIES_MINIOR_METEOR_YELLOW] = sMiniorYellowFormChangeTable, + [SPECIES_MINIOR_CORE_YELLOW] = sMiniorYellowFormChangeTable, #endif #if P_GEN_8_POKEMON == TRUE + [SPECIES_CRAMORANT] = sCramorantFormChangeTable, + [SPECIES_CRAMORANT_GULPING] = sCramorantFormChangeTable, + [SPECIES_CRAMORANT_GORGING] = sCramorantFormChangeTable, + [SPECIES_EISCUE] = sEiscueFormChangeTable, + [SPECIES_EISCUE_NOICE_FACE] = sEiscueFormChangeTable, + [SPECIES_MORPEKO] = sMorpekoFormChangeTable, + [SPECIES_MORPEKO_HANGRY] = sMorpekoFormChangeTable, [SPECIES_ZACIAN] = sZacianFormChangeTable, [SPECIES_ZACIAN_CROWNED_SWORD] = sZacianFormChangeTable, [SPECIES_ZAMAZENTA] = sZamazentaFormChangeTable, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 723bda4b2..c4ade7b9a 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1,211 +1,582 @@ -/* -FORM_ITEM_HOLD: - Form change activates when the specified item is given to or taken from the selected Pokémon. - Alternatively, form change activates when the specified item is is given to or taken from - the selected Pokémon that has a particular ability. - param1 = item to hold - param2 = ability to check for, optional +static const struct FormChange sVenusaurFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_VENUSAUR_MEGA, ITEM_VENUSAURITE}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_ITEM_USE: - Form change activates when the item is used on the selected Pokémon. - param1 = item to use - param2 = DAY if form change activates in the daytime, optional - NIGHT if form change activates at nighttime, optional +static const struct FormChange sCharizardFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_X, ITEM_CHARIZARDITE_X}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_Y, ITEM_CHARIZARDITE_Y}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_MOVE: - Form change activates when the Pokémon learns or forgets the move. - param1 = move to check for - param2 = WHEN_LEARNED if form change activates when move is forgotten - WHEN_FORGOTTEN if form change activates when move is learned +static const struct FormChange sBlastoiseFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLASTOISE_MEGA, ITEM_BLASTOISINITE}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_WITHDRAW: - Form change activates when the Pokémon is withdrawn from the PC or Daycare. - no parameters +static const struct FormChange sBeedrillFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BEEDRILL_MEGA, ITEM_BEEDRILLITE}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_BATTLE_BEGIN: - Form change activates when the Pokémon is sent out at the beginning of a battle - param1 = item to hold, optional - param2 = a move that will be replaced, optional - param3 = a new move to replace it with, optional +static const struct FormChange sPidgeotFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PIDGEOT_MEGA, ITEM_PIDGEOTITE}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_BATTLE_END: - Form change activates at the end of a battle - param1 = item to hold, optional - param2 = a move that will be replaced, optional - param3 = a new move to replace it with, optional -*/ +static const struct FormChange sAlakazamFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALAKAZAM_MEGA, ITEM_ALAKAZITE}, + {FORM_CHANGE_TERMINATOR}, +}; -// FORM_MOVE param2 Arguments -#define WHEN_LEARNED 0 -#define WHEN_FORGOTTEN 1 +static const struct FormChange sSlowbroFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SLOWBRO_MEGA, ITEM_SLOWBRONITE}, + {FORM_CHANGE_TERMINATOR}, +}; -// FORM_ITEM_USE param2 Arguments -#define DAY 1 -#define NIGHT 2 +static const struct FormChange sGengarFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GENGAR_MEGA, ITEM_GENGARITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sKangaskhanFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_KANGASKHAN_MEGA, ITEM_KANGASKHANITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sPinsirFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PINSIR_MEGA, ITEM_PINSIRITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGyaradosFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GYARADOS_MEGA, ITEM_GYARADOSITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAerodactylFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AERODACTYL_MEGA, ITEM_AERODACTYLITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMewtwoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_X, ITEM_MEWTWONITE_X}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_Y, ITEM_MEWTWONITE_Y}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAmpharosFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AMPHAROS_MEGA, ITEM_AMPHAROSITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSteelixFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_STEELIX_MEGA, ITEM_STEELIXITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sScizorFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCIZOR_MEGA, ITEM_SCIZORITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sHeracrossFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HERACROSS_MEGA, ITEM_HERACRONITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sHoundoomFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HOUNDOOM_MEGA, ITEM_HOUNDOOMINITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sTyranitarFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_TYRANITAR_MEGA, ITEM_TYRANITARITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSceptileFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCEPTILE_MEGA, ITEM_SCEPTILITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sBlazikenFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLAZIKEN_MEGA, ITEM_BLAZIKENITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSwampertFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SWAMPERT_MEGA, ITEM_SWAMPERTITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSableyeFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SABLEYE_MEGA, ITEM_SABLENITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSharpedoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SHARPEDO_MEGA, ITEM_SHARPEDONITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sManectricFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MANECTRIC_MEGA, ITEM_MANECTITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sCameruptFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CAMERUPT_MEGA, ITEM_CAMERUPTITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGlalieFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GLALIE_MEGA, ITEM_GLALITITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMawileFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MAWILE_MEGA, ITEM_MAWILITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMedichamFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEDICHAM_MEGA, ITEM_MEDICHAMITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAltariaFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALTARIA_MEGA, ITEM_ALTARIANITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAbsolFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABSOL_MEGA, ITEM_ABSOLITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sCastformFormChangeTable[] = { + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_SUNNY, B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_RAINY, B_WEATHER_RAIN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_SNOWY, B_WEATHER_HAIL}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM, ~(B_WEATHER_SUN | B_WEATHER_RAIN | B_WEATHER_HAIL)}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM, B_WEATHER_NONE}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CASTFORM}, + {FORM_CHANGE_FAINT, SPECIES_CASTFORM}, + {FORM_CHANGE_END_BATTLE, SPECIES_CASTFORM}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sBanetteFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BANETTE_MEGA, ITEM_BANETTITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAggronFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AGGRON_MEGA, ITEM_AGGRONITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGardevoirFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARDEVOIR_MEGA, ITEM_GARDEVOIRITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSalamenceFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SALAMENCE_MEGA, ITEM_SALAMENCITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMetagrossFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_METAGROSS_MEGA, ITEM_METAGROSSITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sLatiasFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIAS_MEGA, ITEM_LATIASITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sLatiosFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIOS_MEGA, ITEM_LATIOSITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sKyogreFormChangeTable[] = { + {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGroudonFormChangeTable[] = { + {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_GROUDON_PRIMAL, ITEM_RED_ORB}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sRayquazaFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, + {FORM_CHANGE_TERMINATOR}, +}; #if P_GEN_4_POKEMON == TRUE +static const struct FormChange sBurmyFormChangeTable[] = { + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_GRASS}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_LONG_GRASS}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_POND}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_MOUNTAIN}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_PLAIN}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_SANDY_CLOAK, BATTLE_TERRAIN_CAVE}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_SANDY_CLOAK, BATTLE_TERRAIN_SAND}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_TRASH_CLOAK, BATTLE_TERRAIN_BUILDING}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sCherrimFormChangeTable[] = { + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_SUNSHINE, B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM, ~B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM, B_WEATHER_NONE}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CHERRIM}, + {FORM_CHANGE_FAINT, SPECIES_CHERRIM}, + {FORM_CHANGE_END_BATTLE, SPECIES_CHERRIM}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sLopunnyFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGarchompFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARCHOMP_MEGA, ITEM_GARCHOMPITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sLucarioFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LUCARIO_MEGA, ITEM_LUCARIONITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAbomasnowFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABOMASNOW_MEGA, ITEM_ABOMASITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGalladeFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GALLADE_MEGA, ITEM_GALLADITE}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sDialgaFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_DIALGA, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_DIALGA_ORIGIN, ITEM_ADAMANT_CRYSTAL}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_DIALGA, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_DIALGA_ORIGIN, ITEM_ADAMANT_CRYSTAL}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sPalkiaFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_PALKIA, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_PALKIA_ORIGIN, ITEM_LUSTROUS_GLOBE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_PALKIA, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_PALKIA_ORIGIN, ITEM_LUSTROUS_GLOBE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGiratinaFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_CORE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, +#if I_GRISEOUS_ORB_FORM_CHANGE < GEN_9 + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB}, +#endif + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_CORE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sShayminFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA, DAY}, - // {FORM_WITHDRAW, SPECIES_SHAYMIN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA, DAY}, + // {FORM_CHANGE_WITHDRAW, SPECIES_SHAYMIN}, + {FORM_CHANGE_TERMINATOR}, }; 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}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS, ITEM_NONE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIST_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIGHTINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_SKY_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_FLYINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_TOXIC_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_POISONIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_STONE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_ROCKIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_EARTH_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_GROUNDIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_INSECT_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_BUGINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_SPOOKY_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_GHOSTIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_IRON_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_STEELIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FLAME_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FIRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_SPLASH_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_WATERIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_MEADOW_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_GRASSIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ZAP_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ELECTRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_MIND_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_PSYCHIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICICLE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRACO_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRAGONIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DREAD_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DARKINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_PIXIE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_FAIRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_5_POKEMON == TRUE +static const struct FormChange sAudinoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AUDINO_MEGA, ITEM_AUDINITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDarmanitanFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_ZEN_MODE, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN}, + {FORM_CHANGE_END_BATTLE, SPECIES_DARMANITAN}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_GALARIAN, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_END_BATTLE, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMeloettaFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_MELOETTA}, + {FORM_CHANGE_END_BATTLE, SPECIES_MELOETTA}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sTornadusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sThundurusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLandorusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sKeldeoFormChangeTable[] = { - // {FORM_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, - // {FORM_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, - {FORM_CHANGE_END}, + // {FORM_CHANGE_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, + // {FORM_CHANGE_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, + {FORM_CHANGE_TERMINATOR}, }; 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}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_DOUSE_DRIVE, ITEM_DOUSE_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_SHOCK_DRIVE, ITEM_SHOCK_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_BURN_DRIVE, ITEM_BURN_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_CHILL_DRIVE, ITEM_CHILL_DRIVE}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_6_POKEMON == TRUE +static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_END_BATTLE, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAegislashFormChangeTable[] = { + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH}, + {FORM_CHANGE_FAINT, SPECIES_AEGISLASH}, + {FORM_CHANGE_END_BATTLE, SPECIES_AEGISLASH}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sXerneasFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_XERNEAS_ACTIVE}, - {FORM_BATTLE_END, SPECIES_XERNEAS, }, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_XERNEAS_ACTIVE}, + {FORM_CHANGE_END_BATTLE, SPECIES_XERNEAS, }, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sZygardePowerConstructFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_ZYGARDE_COMPLETE, ABILITY_POWER_CONSTRUCT, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT}, + {FORM_CHANGE_END_BATTLE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDiancieFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DIANCIE_MEGA, ITEM_DIANCITE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sHoopaFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, - // {FORM_WITHDRAW, SPECIES_HOOPA}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, + {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_7_POKEMON == TRUE 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}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO, ITEM_RED_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_POM_POM, ITEM_YELLOW_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_PAU, ITEM_PINK_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_SENSU, ITEM_PURPLE_NECTAR}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sWishiwashiFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_WISHIWASHI_SCHOOL, ABILITY_SCHOOLING, HP_HIGHER_THAN, 25}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_WISHIWASHI, ABILITY_SCHOOLING, HP_LOWER_EQ_THAN, 25}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI}, + {FORM_CHANGE_FAINT, SPECIES_WISHIWASHI}, + {FORM_CHANGE_END_BATTLE, SPECIES_WISHIWASHI}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSilvallyFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_SILVALLY, ITEM_NONE, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FIGHTING, ITEM_FIGHTING_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FLYING, ITEM_FLYING_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_POISON, ITEM_POISON_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GROUND, ITEM_GROUND_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ROCK, ITEM_ROCK_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_BUG, ITEM_BUG_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GHOST, ITEM_GHOST_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_STEEL, ITEM_STEEL_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FIRE, ITEM_FIRE_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_WATER, ITEM_WATER_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GRASS, ITEM_GRASS_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ELECTRIC, ITEM_ELECTRIC_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_PSYCHIC, ITEM_PSYCHIC_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ICE, ITEM_ICE_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_DRAGON, ITEM_DRAGON_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_DARK, ITEM_DARK_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY, ITEM_NONE, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FIGHTING, ITEM_FIGHTING_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FLYING, ITEM_FLYING_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_POISON, ITEM_POISON_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GROUND, ITEM_GROUND_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ROCK, ITEM_ROCK_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_BUG, ITEM_BUG_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GHOST, ITEM_GHOST_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_STEEL, ITEM_STEEL_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FIRE, ITEM_FIRE_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_WATER, ITEM_WATER_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GRASS, ITEM_GRASS_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ELECTRIC, ITEM_ELECTRIC_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_PSYCHIC, ITEM_PSYCHIC_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ICE, ITEM_ICE_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_DRAGON, ITEM_DRAGON_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_DARK, ITEM_DARK_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMimikyuFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_MIMIKYU}, + {FORM_CHANGE_END_BATTLE, SPECIES_MIMIKYU}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMiniorRedFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_RED, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorBlueFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_BLUE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_BLUE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorGreenFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_GREEN, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_GREEN, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorIndigoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_INDIGO, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_INDIGO, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorOrangeFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_ORANGE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_ORANGE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorVioletFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_VIOLET, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_VIOLET, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorYellowFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_YELLOW, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_YELLOW, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_8_POKEMON == TRUE +static const struct FormChange sCramorantFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GULPING, ABILITY_GULP_MISSILE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GORGING, ABILITY_GULP_MISSILE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, + {FORM_CHANGE_FAINT, SPECIES_CRAMORANT}, + {FORM_CHANGE_END_BATTLE, SPECIES_CRAMORANT}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sEiscueFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_EISCUE}, + {FORM_CHANGE_END_BATTLE, SPECIES_EISCUE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMorpekoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_TURN_END, SPECIES_MORPEKO_HANGRY, ABILITY_HUNGER_SWITCH}, + {FORM_CHANGE_BATTLE_TURN_END, SPECIES_MORPEKO , ABILITY_HUNGER_SWITCH}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO}, + {FORM_CHANGE_FAINT, SPECIES_MORPEKO}, + {FORM_CHANGE_END_BATTLE, SPECIES_MORPEKO}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sZacianFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, - {FORM_BATTLE_END, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, + {FORM_CHANGE_END_BATTLE, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZamazentaFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, - {FORM_BATTLE_END, SPECIES_ZAMAZENTA, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, + {FORM_CHANGE_END_BATTLE, SPECIES_ZAMAZENTA, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sEnamorusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_ENAMORUS, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_ENAMORUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; #endif diff --git a/src/data/pokemon/species_info.h b/src/data/pokemon/species_info.h index 7b60f1b1a..6e99e6f34 100644 --- a/src/data/pokemon/species_info.h +++ b/src/data/pokemon/species_info.h @@ -22202,7 +22202,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_PRIMORDIAL_SEA, ABILITY_PRIMORDIAL_SEA}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, - .flags = SPECIES_FLAG_LEGENDARY, + .flags = SPECIES_FLAG_LEGENDARY | SPECIES_FLAG_PRIMAL_REVERSION, }, [SPECIES_GROUDON_PRIMAL] = @@ -22225,7 +22225,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_DESOLATE_LAND, ABILITY_DESOLATE_LAND}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_LEGENDARY, + .flags = SPECIES_FLAG_LEGENDARY | SPECIES_FLAG_PRIMAL_REVERSION, }, [SPECIES_RATTATA_ALOLAN] = diff --git a/src/daycare.c b/src/daycare.c index 803c0cacf..077ef499a 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -20,6 +20,7 @@ #include "list_menu.h" #include "overworld.h" #include "item.h" +#include "constants/form_change_types.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/region_map_sections.h" @@ -255,8 +256,9 @@ 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) { + newSpecies = GetFormChangeTargetSpecies(&pokemon, FORM_CHANGE_WITHDRAW, 0); + if (newSpecies != SPECIES_NONE) + { SetMonData(&pokemon, MON_DATA_SPECIES, &newSpecies); CalculateMonStats(&pokemon); species = newSpecies; diff --git a/src/field_poison.c b/src/field_poison.c index da162e413..202be30e2 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -15,6 +15,7 @@ #include "task.h" #include "trainer_hill.h" #include "constants/field_poison.h" +#include "constants/form_change_types.h" #include "constants/party_menu.h" static bool32 IsMonValidSpecies(struct Pokemon *pokemon) @@ -135,10 +136,14 @@ s32 DoPoisonFieldEffect(void) hp = GetMonData(pokemon, MON_DATA_HP); #if OW_POISON_DAMAGE < GEN_4 if (hp == 0 || --hp == 0) + { + TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_FAINT); + numFainted++; + } #else if (hp == 1 || --hp == 1) - #endif numFainted++; + #endif SetMonData(pokemon, MON_DATA_HP, &hp); numPoisoned++; diff --git a/src/party_menu.c b/src/party_menu.c index 3e0d04764..ca0794ad2 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -66,6 +66,7 @@ #include "constants/battle.h" #include "constants/battle_frontier.h" #include "constants/field_effects.h" +#include "constants/form_change_types.h" #include "constants/item_effects.h" #include "constants/items.h" #include "constants/moves.h" @@ -5731,7 +5732,7 @@ static void Task_TryItemUseFormChange(u8 taskId) bool32 TryItemUseFormChange(u8 taskId, TaskFunc task) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; - u16 targetSpecies = GetFormChangeTargetSpecies(mon, ItemId_GetSecondaryId(gSpecialVar_ItemId), gSpecialVar_ItemId); + u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_USE, gSpecialVar_ItemId); if (targetSpecies != SPECIES_NONE) { @@ -5766,7 +5767,7 @@ void ItemUseCB_FormChange_ConsumedOnUse(u8 taskId, TaskFunc task) } void TryItemHoldFormChange(struct Pokemon *mon) { - u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_ITEM_HOLD, 0); + u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { PlayCry_NormalNoDucking(targetSpecies, 0, CRY_VOLUME_RS, CRY_VOLUME_RS); diff --git a/src/pokemon.c b/src/pokemon.c index e82cb98c3..2cdaf453f 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -42,6 +42,7 @@ #include "constants/battle_frontier.h" #include "constants/battle_move_effects.h" #include "constants/battle_script_commands.h" +#include "constants/form_change_types.h" #include "constants/hold_effects.h" #include "constants/item_effects.h" #include "constants/items.h" @@ -4138,13 +4139,14 @@ void CalculateMonStats(struct Pokemon *mon) { if (currentHP == 0 && oldMaxHP == 0) currentHP = newMaxHP; - else if (currentHP != 0) { - // BUG: currentHP is unintentionally able to become <= 0 after the instruction below. This causes the pomeg berry glitch. - currentHP += newMaxHP - oldMaxHP; - #ifdef BUGFIX + else if (currentHP != 0) + { + if (newMaxHP > oldMaxHP) + currentHP += newMaxHP - oldMaxHP; if (currentHP <= 0) currentHP = 1; - #endif + if (currentHP > newMaxHP) + currentHP = newMaxHP; } else return; @@ -4235,6 +4237,17 @@ void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot) SetMonData(mon, MON_DATA_PP1 + slot, &gBattleMoves[move].pp); } +static void SetMonMoveSlot_KeepPP(struct Pokemon *mon, u16 move, u8 slot) +{ + u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); + u8 currPP = GetMonData(mon, MON_DATA_PP1 + slot, NULL); + u8 newPP = CalculatePPWithBonus(move, ppBonuses, slot); + u8 finalPP = min(currPP, newPP); + + SetMonData(mon, MON_DATA_MOVE1 + slot, &move); + SetMonData(mon, MON_DATA_PP1 + slot, &finalPP); +} + void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot) { mon->moves[slot] = move; @@ -8311,18 +8324,18 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 heldItem = GetBoxMonData(boxMon, MON_DATA_HELD_ITEM, NULL); ability = GetAbilityBySpecies(species, GetBoxMonData(boxMon, MON_DATA_ABILITY_NUM, NULL)); - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { if (method == formChanges[i].method && species != formChanges[i].targetSpecies) { switch (method) { - case FORM_ITEM_HOLD: + case FORM_CHANGE_ITEM_HOLD: if ((heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) && (ability == formChanges[i].param2 || formChanges[i].param2 == ABILITY_NONE)) targetSpecies = formChanges[i].targetSpecies; break; - case FORM_ITEM_USE: + case FORM_CHANGE_ITEM_USE: if (arg == formChanges[i].param1) { switch (formChanges[i].param2) @@ -8343,14 +8356,23 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 } } break; - case FORM_MOVE: + case FORM_CHANGE_MOVE: if (BoxMonKnowsMove(boxMon, formChanges[i].param1) != formChanges[i].param2) targetSpecies = formChanges[i].targetSpecies; break; - case FORM_BATTLE_BEGIN: - case FORM_BATTLE_END: + case FORM_CHANGE_BEGIN_BATTLE: + case FORM_CHANGE_END_BATTLE: if (heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_END_BATTLE_TERRAIN: + if (gBattleTerrain == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_WITHDRAW: + case FORM_CHANGE_FAINT: + targetSpecies = formChanges[i].targetSpecies; + break; } } } @@ -8359,6 +8381,23 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 return targetSpecies; } +bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method) +{ + u32 i, j; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; + + if (formChanges != NULL) + { + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) + { + if (method == formChanges[i].method && species != formChanges[i].targetSpecies) + return TRUE; + } + } + + return FALSE; +} + u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove) { u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); @@ -8441,20 +8480,47 @@ bool32 ShouldShowFemaleDifferences(u16 species, u32 personality) return (gSpeciesInfo[species].flags & SPECIES_FLAG_GENDER_DIFFERENCE) && GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE; } -void TryToSetBattleFormChangeMoves(struct Pokemon *mon) +bool32 TryFormChange(u32 monId, u32 side, u16 method) +{ + struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + u16 targetSpecies; + + if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG, 0) == SPECIES_NONE + || GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG, 0) == SPECIES_EGG) + return FALSE; + + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + + if (targetSpecies == SPECIES_NONE && gBattleStruct != NULL) + targetSpecies = gBattleStruct->changedSpecies[monId]; + + if (targetSpecies != SPECIES_NONE) + { + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + CalculateMonStats(&party[monId]); + return TRUE; + } + + return FALSE; +} + +void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method) { int i, j; u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); const struct FormChange *formChanges = gFormChangeTablePointers[species]; - u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); - if (formChanges == NULL) + if (formChanges == NULL + || (method != FORM_CHANGE_BEGIN_BATTLE && method != FORM_CHANGE_END_BATTLE)) return; - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { - if ((formChanges[i].method == FORM_BATTLE_BEGIN || formChanges[i].method == FORM_BATTLE_END) - && formChanges[i].param2 && formChanges[i].param3 && formChanges[i].targetSpecies == species) + if (formChanges[i].method == method + && formChanges[i].param2 + && formChanges[i].param3 + && formChanges[i].targetSpecies != species) { u16 originalMove = formChanges[i].param2; u16 newMove = formChanges[i].param3; @@ -8462,20 +8528,9 @@ void TryToSetBattleFormChangeMoves(struct Pokemon *mon) for (j = 0; j < MAX_MON_MOVES; j++) { u16 currMove = GetMonData(mon, MON_DATA_MOVE1 + j, NULL); - u8 totalPp = gBattleMoves[currMove].pp; // Get current move's max PP - u8 currPp = GetMonData(mon, MON_DATA_PP1 + j, NULL); // Get current move's remaining PP - u8 diffPp = totalPp - currPp; // Current move's PP difference - u8 finalPp = gBattleMoves[newMove].pp - diffPp; // Apply the PP difference to the new move - if (currMove == originalMove) - { - if (finalPp > gBattleMoves[newMove].pp) - finalPp = 0; - SetMonMoveSlot(mon, newMove, j); - SetMonData(mon, MON_DATA_PP1 + j, &finalPp); - } + SetMonMoveSlot_KeepPP(mon, newMove, j); } - SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); break; } } diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index 7d9f71f55..1224a7dbe 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -36,6 +36,7 @@ #include "trig.h" #include "walda_phrase.h" #include "window.h" +#include "constants/form_change_types.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/rgb.h" @@ -6893,7 +6894,7 @@ static void ReshowDisplayMon(void) void SetMonFormPSS(struct BoxPokemon *boxMon) { - u16 targetSpecies = GetFormChangeTargetSpeciesBoxMon(boxMon, FORM_ITEM_HOLD, 0); + u16 targetSpecies = GetFormChangeTargetSpeciesBoxMon(boxMon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { SetBoxMonData(boxMon, MON_DATA_SPECIES, &targetSpecies); diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index 15d5b2e5d..34f75ef8e 100755 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -72,7 +72,7 @@ u8 ScriptGiveMon(u16 species, u8 level, u16 item, u32 unused1, u32 unused2, u8 u SetMonData(&mon, MON_DATA_HELD_ITEM, heldItem); // In case a mon with a form changing item is given. Eg: SPECIES_ARCEUS with ITEM_SPLASH_PLATE will transform into SPECIES_ARCEUS_WATER upon gifted. - targetSpecies = GetFormChangeTargetSpecies(&mon, FORM_ITEM_HOLD, 0); + targetSpecies = GetFormChangeTargetSpecies(&mon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { SetMonData(&mon, MON_DATA_SPECIES, &targetSpecies); diff --git a/test/ability_hunger_switch.c b/test/ability_hunger_switch.c new file mode 100644 index 000000000..9250ae85a --- /dev/null +++ b/test/ability_hunger_switch.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the turn") +{ + u16 species; + PARAMETRIZE { species = SPECIES_MORPEKO; } + PARAMETRIZE { species = SPECIES_MORPEKO_HANGRY; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(species) { Speed(2); }; + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }; + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + MESSAGE("Morpeko used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + if (species == SPECIES_MORPEKO) + EXPECT_EQ(player->species, SPECIES_MORPEKO_HANGRY); + else + EXPECT_EQ(player->species, SPECIES_MORPEKO); + } +} diff --git a/test/ability_schooling.c b/test/ability_schooling.c new file mode 100644 index 000000000..03a5303f0 --- /dev/null +++ b/test/ability_schooling.c @@ -0,0 +1,111 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is 25-percent or less at the end of the turn") +{ + u16 level; + PARAMETRIZE { level = 19; } + PARAMETRIZE { level = 20; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SUPER_FANG); } + } SCENE { + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Super Fang!"); + HP_BAR(player); + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + } THEN { + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is over 25-percent before the first turn") +{ + u16 level; + bool32 overQuarterHP; + PARAMETRIZE { level = 19; overQuarterHP = FALSE; } + PARAMETRIZE { level = 20; overQuarterHP = FALSE; } + PARAMETRIZE { level = 19; overQuarterHP = TRUE; } + PARAMETRIZE { level = 20; overQuarterHP = TRUE; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / (overQuarterHP ? 2 : 4)); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + if (level >= 20 && overQuarterHP) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + if (level >= 20 && overQuarterHP) + EXPECT_EQ(player->species, SPECIES_WISHIWASHI_SCHOOL); + else + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is healed above 25-percent") +{ + u16 level; + PARAMETRIZE { level = 19; } + PARAMETRIZE { level = 20; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 4); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_HEAL_PULSE); } + } SCENE { + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Heal Pulse!"); + HP_BAR(player); + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + } THEN { + if (level >= 20) + EXPECT_EQ(player->species, SPECIES_WISHIWASHI_SCHOOL); + else + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} diff --git a/test/ability_zen_mode.c b/test/ability_zen_mode.c new file mode 100644 index 000000000..f18f6d659 --- /dev/null +++ b/test/ability_zen_mode.c @@ -0,0 +1,93 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is half or less at the end of the turn") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP((GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2) + 1); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Tackle!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + ASSUME(player->hp <= player->maxHP / 2); + EXPECT_EQ(player->species, zenSpecies); + } +} + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is half or less before the first turn") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + EXPECT_LE(player->hp, player->maxHP / 2); + EXPECT_EQ(player->species, zenSpecies); + } +} + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is healed above half") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_HEAL_PULSE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Heal Pulse!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + EXPECT_GT(player->hp, player->maxHP / 2); + EXPECT_EQ(player->species, standardSpecies); + } +} diff --git a/test/form_change.c b/test/form_change.c new file mode 100644 index 000000000..74ba2b75f --- /dev/null +++ b/test/form_change.c @@ -0,0 +1,119 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Xerneas changes into Active Form upon battle start") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_XERNEAS); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + EXPECT_EQ(player->species, SPECIES_XERNEAS_ACTIVE); + } +} + +SINGLE_BATTLE_TEST("Zacian changes into its Crowned Form when holding the Rusted Sword upon battle start") +{ + u16 item; + PARAMETRIZE { item = ITEM_NONE; } + PARAMETRIZE { item = ITEM_RUSTED_SWORD; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZACIAN) { Item(item); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + if (item == ITEM_NONE) + EXPECT_EQ(player->species, SPECIES_ZACIAN); + else + EXPECT_EQ(player->species, SPECIES_ZACIAN_CROWNED_SWORD); + } +} + +SINGLE_BATTLE_TEST("Zacian's Iron Head becomes Behemoth Blade upon form change") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZACIAN) { Item(ITEM_RUSTED_SWORD); Moves(MOVE_IRON_HEAD, MOVE_CELEBRATE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + ASSUME(player->species == SPECIES_ZACIAN_CROWNED_SWORD); // Assumes form change worked. + EXPECT_EQ(player->moves[0], MOVE_BEHEMOTH_BLADE); + } +} + +SINGLE_BATTLE_TEST("Zamazenta changes into its Crowned Form when holding the Rusted Shield upon battle start") +{ + u16 item; + PARAMETRIZE { item = ITEM_NONE; } + PARAMETRIZE { item = ITEM_RUSTED_SHIELD; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZAMAZENTA) { Item(item); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + if (item == ITEM_NONE) + EXPECT_EQ(player->species, SPECIES_ZAMAZENTA); + else + EXPECT_EQ(player->species, SPECIES_ZAMAZENTA_CROWNED_SHIELD); + } +} + +SINGLE_BATTLE_TEST("Zamazenta's Iron Head becomes Behemoth Bash upon form change") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZAMAZENTA) { Item(ITEM_RUSTED_SHIELD); Moves(MOVE_IRON_HEAD, MOVE_CELEBRATE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + ASSUME(player->species == SPECIES_ZAMAZENTA_CROWNED_SHIELD); // Assumes form change worked. + EXPECT_EQ(player->moves[0], MOVE_BEHEMOTH_BASH); + } +} + +SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon switching out") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_AEGISLASH); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } + } SCENE { + ABILITY_POPUP(player, ABILITY_STANCE_CHANGE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Aegislash used Tackle!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_AEGISLASH); + } +} + +SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_AEGISLASH) { HP(1); }; + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_GUST); SEND_OUT(player, 1);} + } SCENE { + MESSAGE("Foe Wobbuffet used Gust!"); + MESSAGE("Aegislash fainted!"); + } THEN { + EXPECT_EQ(GetMonData(&PLAYER_PARTY[0], MON_DATA_SPECIES), SPECIES_AEGISLASH); + } +} diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 365120f13..9f3b9a5f8 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1082,9 +1082,12 @@ void Ability_(u32 sourceLine, u32 ability) void Level_(u32 sourceLine, u32 level) { // TODO: Preserve any explicitly-set stats. + u32 species = GetMonData(DATA.currentMon, MON_DATA_SPECIES); INVALID_IF(!DATA.currentMon, "Level outside of PLAYER/OPPONENT"); INVALID_IF(level == 0 || level > MAX_LEVEL, "Illegal level: %d", level); SetMonData(DATA.currentMon, MON_DATA_LEVEL, &level); + SetMonData(DATA.currentMon, MON_DATA_EXP, &gExperienceTables[gSpeciesInfo[species].growthRate][level]); + CalculateMonStats(DATA.currentMon); } void MaxHP_(u32 sourceLine, u32 maxHP)