From a5f2b89e29fd4e81aa00c7c25d983cb679d58317 Mon Sep 17 00:00:00 2001 From: cawtds Date: Tue, 30 Apr 2024 20:02:18 +0200 Subject: [PATCH] updated up to Cmd_seteffectsecondary, Cmd_setgastroacid and Cmd_setstealthrock --- asm/macros/battle_script.inc | 46 +- charmap.txt | 1 + data/battle_scripts_1.s | 194 ++- include/battle.h | 43 +- include/battle_message.h | 1 - include/battle_script_commands.h | 9 + include/battle_scripts.h | 23 + include/battle_util.h | 27 +- include/constants/battle.h | 1 + include/constants/battle_script_commands.h | 2 + include/constants/battle_string_ids.h | 51 +- include/constants/form_change_types.h | 123 ++ include/constants/species.h | 1397 ++++++++--------- include/party_menu.h | 1 + include/pokemon.h | 5 + src/battle_message.c | 97 +- src/battle_script_commands.c | 1598 ++++++++++++++++---- src/battle_util.c | 444 +++++- src/data/pokemon/form_change_tables.h | 1073 +++++++------ src/party_menu.c | 14 +- src/pokemon.c | 177 +++ 21 files changed, 3751 insertions(+), 1576 deletions(-) create mode 100644 include/constants/form_change_types.h diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 76f45a11c..a781dea4f 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -92,7 +92,7 @@ .4byte \ptr .endm - .macro seteffectwithchance + .macro setadditionaleffects .byte 0x15 .endm @@ -1095,8 +1095,9 @@ .4byte \param0 .endm - .macro doubledamagedealtifdamaged + .macro setgastroacid failInstr:req .byte 0xd6 + .4byte \failInstr .endm .macro setyawn param0:req @@ -1123,9 +1124,9 @@ .4byte \param0 .endm - .macro trysetgrudge param0:req + .macro setstealthrock failInstr:req .byte 0xdc - .4byte \param0 + .4byte \failInstr .endm .macro weightdamagecalculation @@ -1307,13 +1308,13 @@ various \battler, VARIOUS_WAIT_FANFARE .endm + @ pokeemerald + .macro handleformchange battler:req, case:req various \battler, VARIOUS_HANDLE_FORM_CHANGE .byte \case .endm - @ pokeemerald - .macro playmoveanimation battler:req, move:req various \battler, VARIOUS_PLAY_MOVE_ANIMATION .2byte \move @@ -1334,10 +1335,26 @@ .byte \equal .endm - .macro jumpifnoholdeffect battler:req, holdEffect:req, jumpInstr:req - jumpifholdeffect \battler, \holdEffect, \jumpInstr, FALSE + .macro savetarget + various BS_TARGET, VARIOUS_SAVE_TARGET .endm + .macro restoretarget + various BS_TARGET, VARIOUS_RESTORE_TARGET + .endm + + .macro spectralthiefprintstats + various BS_ATTACKER, VARIOUS_SPECTRAL_THIEF + .endm + + .macro trytoclearprimalweather + various BS_ATTACKER, VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER + .endm + + .macro consumeberry battler:req, fromBattler:req + various \battler, VARIOUS_CONSUME_BERRY + .byte \fromBattler + .endm @ helpful macros .macro setstatchanger stat:req, stages:req, down:req @@ -1416,6 +1433,10 @@ jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, \flags, \jumpptr .endm + .macro jumpifnoholdeffect battler:req, holdEffect:req, jumpInstr:req + jumpifholdeffect \battler, \holdEffect, \jumpInstr, FALSE + .endm + @ callnative macros .macro itemrestorehp callnative BS_ItemRestoreHP @@ -1443,3 +1464,12 @@ printstring STRINGID_EMPTYSTRING3 waitmessage 1 .endm + + .macro tryrevertweatherform + callnative BS_TryRevertWeatherForm + .endm + + @ Used by effects that may proc Symbiosis but do not call removeitem. + .macro trysymbiosis + callnative BS_TrySymbiosis + .endm diff --git a/charmap.txt b/charmap.txt index b9d0ed9de..bc89fe0c5 100644 --- a/charmap.txt +++ b/charmap.txt @@ -406,6 +406,7 @@ B_DEF_PREFIX3 = FD 2D B_TRAINER2_LOSE_TEXT = FD 2E B_TRAINER2_WIN_TEXT = FD 2F B_BUFF3 = FD 30 +B_DEF_TEAM2 = FD 3B @ indicates the end of a town/city name (before " TOWN" or " CITY") NAME_END = FC 00 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8d0043f8b..ed0ebab98 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -268,7 +268,7 @@ BattleScript_HitFromAtkAnimation:: waitmessage B_WAIT_TIME_LONG resultmessage waitmessage B_WAIT_TIME_LONG - seteffectwithchance + setadditionaleffects tryfaintmon BS_TARGET BattleScript_MoveEnd:: moveendall @@ -514,6 +514,7 @@ BattleScript_StatUpEnd:: BattleScript_StatUp:: playanimation BS_EFFECT_BATTLER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 +BattleScript_StatUpMsg:: printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG return @@ -652,7 +653,7 @@ BattleScript_MultiHitPrintStrings:: printstring STRINGID_HITXTIMES waitmessage B_WAIT_TIME_LONG BattleScript_MultiHitEnd:: - seteffectwithchance + setadditionaleffects tryfaintmon BS_TARGET moveendcase MOVEEND_SYNCHRONIZE_TARGET moveendfrom MOVEEND_IMMUNITY_ABILITIES @@ -1431,7 +1432,7 @@ BattleScript_TripleKickPrintStrings:: printstring STRINGID_HITXTIMES waitmessage B_WAIT_TIME_LONG BattleScript_TripleKickEnd:: - seteffectwithchance + setadditionaleffects tryfaintmon BS_TARGET moveendfrom MOVEEND_UPDATE_LAST_MOVES end @@ -2412,7 +2413,7 @@ BattleScript_EffectRecycle:: goto BattleScript_MoveEnd BattleScript_EffectRevenge:: - doubledamagedealtifdamaged + setgastroacid BattleScript_CoreEnforcerRet goto BattleScript_EffectHit BattleScript_EffectBrickBreak:: @@ -2444,7 +2445,7 @@ BattleScript_BrickBreakDoHit:: waitmessage B_WAIT_TIME_LONG resultmessage waitmessage B_WAIT_TIME_LONG - seteffectwithchance + setadditionaleffects tryfaintmon BS_TARGET goto BattleScript_MoveEnd @@ -2533,7 +2534,7 @@ BattleScript_EffectGrudge:: attackcanceler attackstring ppreduce - trysetgrudge BattleScript_ButItFailed + setstealthrock BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNWANTSGRUDGE @@ -3591,6 +3592,25 @@ BattleScript_AtkDefDownAtkFail:: BattleScript_AtkDefDownDefFail:: return +BattleScript_DefSpDefDown:: + setbyte sSTAT_ANIM_PLAYED, FALSE + playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_CANT_PREVENT | STAT_CHANGE_NEGATIVE | STAT_CHANGE_MULTIPLE_STATS + playstatchangeanimation BS_ATTACKER, BIT_DEF, STAT_CHANGE_CANT_PREVENT | STAT_CHANGE_NEGATIVE + setstatchanger STAT_DEF, 1, TRUE + statbuffchange MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN | STAT_CHANGE_ALLOW_PTR, BattleScript_DefSpDefDownTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_DefSpDefDownTrySpDef + printfromtable gStatDownStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_DefSpDefDownTrySpDef:: + playstatchangeanimation BS_ATTACKER, BIT_SPDEF, STAT_CHANGE_CANT_PREVENT | STAT_CHANGE_NEGATIVE + setstatchanger STAT_SPDEF, 1, TRUE + statbuffchange MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN | STAT_CHANGE_ALLOW_PTR, BattleScript_DefSpDefDownRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_DefSpDefDownRet + printfromtable gStatDownStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_DefSpDefDownRet:: + return + BattleScript_KnockedOff:: playanimation BS_TARGET, B_ANIM_ITEM_KNOCKOFF printstring STRINGID_PKMNKNOCKEDOFF @@ -4580,3 +4600,165 @@ BattleScript_TargetFormChangeWithStringNoPopup:: printstring STRINGID_PKMNTRANSFORMED waitmessage B_WAIT_TIME_LONG return + +BattleScript_IceFaceNullsDamage:: + call BattleScript_TargetFormChangeWithString + return + +BattleScript_AffectionBasedEndurance:: +@ playanimation BS_TARGET, B_ANIM_AFFECTION_HANGED_ON @ TODO: Animation + printstring STRINGID_TARGETTOUGHEDITOUT + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_MoveEffectClearSmog:: + printstring STRINGID_RESETSTARGETSSTATLEVELS + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_MoveEffectFlameBurst:: + tryfaintmon BS_TARGET + copybyte sBATTLER, sSAVED_BATTLER + printstring STRINGID_BURSTINGFLAMESHIT + waitmessage B_WAIT_TIME_LONG + savetarget + copybyte gBattlerTarget, sSAVED_BATTLER + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + tryfaintmon BS_TARGET + restoretarget + goto BattleScript_MoveEnd + +BattleScript_HyperspaceFuryRemoveProtect:: + printstring STRINGID_BROKETHROUGHPROTECTION + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_MoveEffectFeint:: + printstring STRINGID_FELLFORFEINT + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_SpectralThiefSteal:: + printstring STRINGID_SPECTRALTHIEFSTEAL + waitmessage B_WAIT_TIME_LONG + setbyte sB_ANIM_ARG2, 0 + playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 + spectralthiefprintstats + return + +BattleScript_VCreateStatLoss:: + jumpifstat BS_ATTACKER, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_VCreateStatAnim + jumpifstat BS_ATTACKER, CMP_GREATER_THAN, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_VCreateStatAnim + jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MIN_STAT_STAGE, BattleScript_VCreateStatLossRet +BattleScript_VCreateStatAnim: + setbyte sSTAT_ANIM_PLAYED, FALSE + playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF | BIT_SPEED, STAT_CHANGE_NEGATIVE | STAT_CHANGE_CANT_PREVENT + setstatchanger STAT_DEF, 1, TRUE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_NOT_PROTECT_AFFECTED | MOVE_EFFECT_CERTAIN, BattleScript_VCreateTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateTrySpDef + printfromtable gStatDownStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_VCreateTrySpDef: + setstatchanger STAT_SPDEF, 1, TRUE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_NOT_PROTECT_AFFECTED | MOVE_EFFECT_CERTAIN, BattleScript_VCreateTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateTrySpeed + printfromtable gStatDownStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_VCreateTrySpeed: + setstatchanger STAT_SPEED, 1, TRUE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_NOT_PROTECT_AFFECTED | MOVE_EFFECT_CERTAIN, BattleScript_VCreateStatLossRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateStatLossRet + printfromtable gStatDownStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_VCreateStatLossRet: + return + +BattleScript_MoveEffectCoreEnforcer:: + setgastroacid BattleScript_CoreEnforcerRet + printstring STRINGID_PKMNSABILITYSUPPRESSED + waitmessage B_WAIT_TIME_LONG + trytoclearprimalweather + tryrevertweatherform + flushtextbox +BattleScript_CoreEnforcerRet: + return + +BattleScript_MoveEffectIncinerate:: + printstring STRINGID_INCINERATEBURN + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_MoveEffectBugBite:: + printstring STRINGID_BUGBITE + waitmessage B_WAIT_TIME_LONG + orword gHitMarker, HITMARKER_DISABLE_ANIMATION + setbyte sBERRY_OVERRIDE, 1 @ override the requirements for eating berries + savetarget + consumeberry BS_ATTACKER, FALSE + bicword gHitMarker, HITMARKER_DISABLE_ANIMATION + setbyte sBERRY_OVERRIDE, 0 + trysymbiosis + restoretarget + return + +BattleScript_BothCanNoLongerEscape:: + printstring STRINGID_BOTHCANNOLONGERESCAPE + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_RemoveFireType:: + printstring STRINGID_ATTACKERLOSTFIRETYPE + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_RemoveElectricType:: + printstring STRINGID_ATTACKERLOSTELECTRICTYPE + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_RemoveGenericType:: + printstring STRINGID_ATTACKERLOSTITSTYPE + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_StealthRockActivates:: + setstealthrock BattleScript_MoveEnd + printfromtable gDmgHazardsStringIds + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_SpikesActivates:: + trysetspikes BattleScript_MoveEnd + printfromtable gDmgHazardsStringIds + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_SyrupBombActivates:: + printstring STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_AromaVeilProtectsRet:: + pause B_WAIT_TIME_SHORT + call BattleScript_AbilityPopUp + printstring STRINGID_AROMAVEILPROTECTED + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_EffectPsychicNoise:: + printstring STRINGID_PKMNPREVENTEDFROMHEALING + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_SymbiosisActivates:: + call BattleScript_AbilityPopUp + printstring STRINGID_SYMBIOSISITEMPASS + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_NoItemSteal:: + pause B_WAIT_TIME_SHORT + printstring STRINGID_PKMNSXMADEYINEFFECTIVE + waitmessage B_WAIT_TIME_LONG + return diff --git a/include/battle.h b/include/battle.h index eaec4f2f6..8b6251f8e 100644 --- a/include/battle.h +++ b/include/battle.h @@ -4,6 +4,7 @@ #include #include "global.h" #include "constants/battle.h" +#include "constants/form_change_types.h" #include "constants/battle_script_commands.h" #include "battle_util.h" #include "battle_script_commands.h" @@ -352,6 +353,7 @@ struct SideTimer /*0x0B*/ u8 fieldB; // pokeemerald u8 retaliateTimer; + u8 stealthRockAmount; }; extern struct SideTimer gSideTimers[]; @@ -485,6 +487,12 @@ struct Illusion struct Pokemon *mon; }; +struct LostItem +{ + u16 originalItem:15; + u16 stolen:1; +}; + struct BattleStruct { u8 turnEffectsTracker; @@ -593,6 +601,17 @@ struct BattleStruct u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies. u8 enduredDamage; u16 changedSpecies[NUM_BATTLE_SIDES][PARTY_SIZE]; // For forms when multiple mons can change into the same pokemon. + u8 trainerSlideFirstCriticalHitMsgState:2; + u8 trainerSlideFirstSuperEffectiveHitMsgState:2; + u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects + u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit. + u16 moveEffect2; // For Knock Off + u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages + u8 stickySyrupdBy[MAX_BATTLERS_COUNT]; + u8 moneyMultiplierMove:1; + struct LostItem itemLost[PARTY_SIZE]; // Player's team that had items consumed or stolen (two bytes per party member) + u8 savedBattlerTarget; + u8 ateBerry[2]; // array id determined by side, each party pokemon as bit }; // size == 0x200 bytes extern struct BattleStruct *gBattleStruct; @@ -621,15 +640,29 @@ extern struct BattleStruct *gBattleStruct; #define BATTLER_MAX_HP(battlerId)(gBattleMons[battlerId].hp == gBattleMons[battlerId].maxHP) #define TARGET_TURN_DAMAGED ((gSpecialStatuses[gBattlerTarget].physicalDmg != 0 || gSpecialStatuses[gBattlerTarget].specialDmg != 0)) -#define IS_BATTLER_OF_TYPE(battlerId, type)((gBattleMons[battlerId].type1 == type || gBattleMons[battlerId].type2 == type)) -#define SET_BATTLER_TYPE(battlerId, type) \ -{ \ - gBattleMons[battlerId].type1 = type; \ - gBattleMons[battlerId].type2 = type; \ +#define IS_BATTLER_OF_TYPE(battlerId, type)((GetBattlerType(battlerId, 0) == type || GetBattlerType(battlerId, 1) == type || (GetBattlerType(battlerId, 2) != TYPE_MYSTERY && GetBattlerType(battlerId, 2) == type))) +#define SET_BATTLER_TYPE(battlerId, type) \ +{ \ + gBattleMons[battlerId].type1 = type; \ + gBattleMons[battlerId].type2 = type; \ + gBattleMons[battlerId].type3 = TYPE_MYSTERY; \ } +#define IS_BATTLER_PROTECTED(battlerId)(gProtectStructs[battlerId].protected \ + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD \ + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_QUICK_GUARD \ + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD \ + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_MAT_BLOCK \ + || gProtectStructs[battlerId].spikyShielded \ + || gProtectStructs[battlerId].kingsShielded \ + || gProtectStructs[battlerId].banefulBunkered \ + || gProtectStructs[battlerId].burningBulwarked \ + || gProtectStructs[battlerId].obstructed \ + || gProtectStructs[battlerId].silkTrapped) + #define GET_STAT_BUFF_ID(n)((n & 0xF)) // first four bits 0x1, 0x2, 0x4, 0x8 #define GET_STAT_BUFF_VALUE2(n)((n & 0xF0)) +#define GET_STAT_BUFF_VALUE_WITH_SIGN(n)((n & 0xF8)) #define GET_STAT_BUFF_VALUE(n)(((n >> 4) & 7)) // 0x10, 0x20, 0x40 #define STAT_BUFF_NEGATIVE 0x80 // 0x80, the sign bit diff --git a/include/battle_message.h b/include/battle_message.h index ffe8710d0..6733a49c1 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -233,7 +233,6 @@ extern const u8 *const gRefereeStringsTable[]; extern const u8 *const gStatNamesTable2[]; extern const u16 gMissStringIds[]; -extern const u16 gTrappingMoves[]; extern const u8 gText_Sleep[]; extern const u8 gText_Poison[]; diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index 624880895..d01cc451d 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -30,6 +30,15 @@ u32 GetHighestStatId(u32 battlerId); u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move); bool32 DoesDisguiseBlockMove(u32 battler, u32 move); +bool32 CanPoisonType(u8 battlerAttacker, u8 battlerTarget); +bool32 CanParalyzeType(u8 battlerAttacker, u8 battlerTarget); +bool32 NoAliveMonsForPlayer(void); +bool32 NoAliveMonsForEitherParty(void); +void StealTargetItem(u8 battlerStealer, u8 battlerItem); +u32 IsFlowerVeilProtected(u32 battler); +u32 IsLeafGuardProtected(u32 battler); +bool32 IsShieldsDownProtected(u32 battler); +u32 IsAbilityStatusProtected(u32 battler); extern void (* const gBattleScriptingCommandsTable[])(void); extern const struct StatFractions gAccuracyStageRatios[]; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 54fb54f8c..0c2922e0e 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -476,5 +476,28 @@ extern const u8 BattleScript_HangedOnMsg[]; extern const u8 BattleScript_PrintBerryReduceString[]; extern const u8 BattleScript_TargetFormChange[]; extern const u8 BattleScript_TargetFormChangeWithStringNoPopup[]; +extern const u8 BattleScript_IceFaceNullsDamage[]; +extern const u8 BattleScript_AffectionBasedEndurance[]; +extern const u8 BattleScript_DefSpDefDown[]; +extern const u8 BattleScript_MoveEffectClearSmog[]; +extern const u8 BattleScript_MoveEffectFlameBurst[]; +extern const u8 BattleScript_HyperspaceFuryRemoveProtect[]; +extern const u8 BattleScript_MoveEffectFeint[]; +extern const u8 BattleScript_SpectralThiefSteal[]; +extern const u8 BattleScript_VCreateStatLoss[]; +extern const u8 BattleScript_MoveEffectCoreEnforcer[]; +extern const u8 BattleScript_MoveEffectIncinerate[]; +extern const u8 BattleScript_MoveEffectBugBite[]; +extern const u8 BattleScript_BothCanNoLongerEscape[]; +extern const u8 BattleScript_RemoveFireType[]; +extern const u8 BattleScript_RemoveElectricType[]; +extern const u8 BattleScript_RemoveGenericType[]; +extern const u8 BattleScript_StealthRockActivates[]; +extern const u8 BattleScript_SpikesActivates[]; +extern const u8 BattleScript_SyrupBombActivates[]; +extern const u8 BattleScript_AromaVeilProtectsRet[]; +extern const u8 BattleScript_EffectPsychicNoise[]; +extern const u8 BattleScript_StatUpMsg[]; +extern const u8 BattleScript_SymbiosisActivates[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/battle_util.h b/include/battle_util.h index 66a0b77f6..1a5f83d15 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -39,12 +39,17 @@ #define ABILITY_ON_FIELD(abilityId)(AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, abilityId, 0, 0)) #define ABILITY_ON_FIELD2(abilityId)(AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, abilityId, 0, 0)) -// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try +/// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try #define ITEMEFFECT_ON_SWITCH_IN 0 #define ITEMEFFECT_NORMAL 1 #define ITEMEFFECT_DUMMY 2 // Unused, empty #define ITEMEFFECT_MOVE_END 3 -#define ITEMEFFECT_KINGSROCK_SHELLBELL 4 +#define ITEMEFFECT_KINGSROCK 4 +#define ITEMEFFECT_TARGET 5 +#define ITEMEFFECT_ORBS 6 +#define ITEMEFFECT_LIFEORB_SHELLBELL 7 +#define ITEMEFFECT_USE_LAST_ITEM 8 // move end effects for just the battler, not whole field +#define ITEMEFFECT_STATS_CHANGED 9 // For White Herb and Eject Pack #define WEATHER_HAS_EFFECT ((!AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, ABILITY_CLOUD_NINE, 0, 0) && !AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, ABILITY_AIR_LOCK, 0, 0))) #define WEATHER_HAS_EFFECT2 ((!AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_CLOUD_NINE, 0, 0) && !AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_AIR_LOCK, 0, 0))) @@ -103,7 +108,7 @@ void PressurePPLoseOnUsingImprison(u8 attacker); void PressurePPLoseOnUsingPerishSong(u8 attacker); void MarkBattlerForControllerExec(u8 battlerId); void MarkBattlerReceivedLinkData(u8 battlerId); -void CancelMultiTurnMoves(u8 battler); +const u8* CancelMultiTurnMoves(u32 battler); bool32 WasUnableToUseMove(u32 battler); void PrepareStringBattle(u16 stringId, u8 battler); void ResetSentPokesToOpponentValue(void); @@ -182,6 +187,22 @@ u32 GetBattlerHoldEffect(u32 battler, bool32 checkNegating); u32 GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating); u32 GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegating, bool32 checkAbility); void RecalcBattlerStats(u32 battler, struct Pokemon *mon); +bool32 TestIfSheerForceAffected(u32 battler, u16 move); +bool32 CanSleep(u32 battler); +bool32 CanBePoisoned(u32 battlerAttacker, u32 battlerTarget); +bool32 CanBeBurned(u32 battler); +bool32 CanBeParalyzed(u32 battler); +bool32 CanBeFrozen(u32 battler); +bool32 CanGetFrostbite(u32 battler); +bool32 CanBeConfused(u32 battler); +bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item); +void TrySaveExchangedItem(u32 battler, u16 stolenItem); +void RemoveBattlerType(u32 battler, u8 type); +bool32 IsBattlerMegaEvolved(u32 battler); +bool32 IsBattlerPrimalReverted(u32 battler); +bool32 IsBattlerUltraBursted(u32 battler); +u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method); +bool32 TryBattleFormChange(u32 battler, u16 method); // battle_ai_util.h bool32 IsHealingMove(u32 move); diff --git a/include/constants/battle.h b/include/constants/battle.h index af79bedc7..b5a12bbf8 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -66,6 +66,7 @@ #define BATTLE_TYPE_WILD_SCRIPTED (1 << 17) // Used in pokeemerald as BATTLE_TYPE_PALACE. #define BATTLE_TYPE_LEGENDARY_FRLG (1 << 18) // Used in pokeemerald as BATTLE_TYPE_ARENA. #define BATTLE_TYPE_TRAINER_TOWER (1 << 19) // Used in pokeemerald as BATTLE_TYPE_FACTORY. +#define BATTLE_TYPE_INGAME_PARTNER (1 << 20) #define IS_BATTLE_TYPE_GHOST_WITHOUT_SCOPE(flags) ((flags) & BATTLE_TYPE_GHOST && !((flags) & BATTLE_TYPE_GHOST_UNVEILED)) #define IS_BATTLE_TYPE_GHOST_WITH_SCOPE(flags) ((flags) & BATTLE_TYPE_GHOST && (flags) & BATTLE_TYPE_GHOST_UNVEILED) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index fbd4624e5..125da7e63 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -263,7 +263,9 @@ // Cmd_statbuffchange #define STAT_CHANGE_ALLOW_PTR (1 << 0) // If set, allow use of jumpptr. Set in every use of statbuffchange +#define STAT_CHANGE_MIRROR_ARMOR (1 << 1) // Stat change redirection caused by Mirror Armor ability. #define STAT_CHANGE_NOT_PROTECT_AFFECTED (1 << 5) +#define STAT_CHANGE_UPDATE_MOVE_EFFECT (1 << 6) // stat change flags for Cmd_playstatchangeanimation #define STAT_CHANGE_NEGATIVE (1 << 0) diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 641c53f37..1e6669ffb 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -411,8 +411,36 @@ #define STRINGID_ATTACKWEAKENEDBSTRONGWINDS 409 #define STRINGID_ENDUREDSTURDY 410 #define STRINGID_BERRYDMGREDUCES 411 +#define STRINGID_TARGETTOUGHEDITOUT 412 +#define STRINGID_TRAPPEDBYSWIRLINGMAGMA 413 +#define STRINGID_INFESTATION 414 +#define STRINGID_PKMNINSNAPTRAP 415 +#define STRINGID_THUNDERCAGETRAPPED 416 +#define STRINGID_RESETSTARGETSSTATLEVELS 417 +#define STRINGID_EXTREMESUNLIGHTFADED 418 +#define STRINGID_HEAVYRAINLIFTED 419 +#define STRINGID_STRONGWINDSDISSIPATED 420 +#define STRINGID_SYMBIOSISITEMPASS 421 +#define STRINGID_BURSTINGFLAMESHIT 422 +#define STRINGID_BROKETHROUGHPROTECTION 423 +#define STRINGID_FELLFORFEINT 424 +#define STRINGID_SPECTRALTHIEFSTEAL 425 +#define STRINGID_PKMNSABILITYSUPPRESSED 426 +#define STRINGID_INCINERATEBURN 427 +#define STRINGID_BUGBITE 428 +#define STRINGID_BOTHCANNOLONGERESCAPE 429 +#define STRINGID_ATTACKERLOSTFIRETYPE 430 +#define STRINGID_ATTACKERLOSTELECTRICTYPE 431 +#define STRINGID_ATTACKERLOSTITSTYPE 432 +#define STRINGID_STEALTHROCKDMG 433 +#define STRINGID_SHARPSTEELDMG 434 +#define STRINGID_POINTEDSTONESFLOAT 435 +#define STRINGID_SHARPSTEELFLOATS 436 +#define STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP 437 +#define STRINGID_AROMAVEILPROTECTED 438 +#define STRINGID_PKMNPREVENTEDFROMHEALING 439 -#define BATTLESTRINGS_COUNT 412 +#define BATTLESTRINGS_COUNT 440 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, @@ -621,6 +649,25 @@ #define B_MSG_FROSTBITE_HEALED 0 #define B_MSG_FROSTBITE_HEALED_BY_MOVE 1 -#define NUM_TRAPPING_MOVES 6 +// gWrappedStringIds +#define B_MSG_WRAPPED_BIND 0 +#define B_MSG_WRAPPED_WRAP 1 +#define B_MSG_WRAPPED_FIRE_SPIN 2 +#define B_MSG_WRAPPED_CLAMP 3 +#define B_MSG_WRAPPED_WHIRLPOOL 4 +#define B_MSG_WRAPPED_SAND_TOMB 5 +#define B_MSG_WRAPPED_MAGMA_STORM 6 +#define B_MSG_WRAPPED_INFESTATION 7 +#define B_MSG_WRAPPED_SNAP_TRAP 8 +#define B_MSG_WRAPPED_THUNDER_CAGE 9 +#define NUM_TRAPPING_MOVES 10 + +// gDmgHazardsStringIds +#define B_MSG_PKMNHURTBYSPIKES 0 +#define B_MSG_STEALTHROCKDMG 1 +#define B_MSG_SHARPSTEELDMG 2 +#define B_MSG_POINTEDSTONESFLOAT 3 +#define B_MSG_SPIKESSCATTERED 4 +#define B_MSG_SHARPSTEELFLOATS 5 #endif // GUARD_BATTLE_STRING_IDS_H diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h new file mode 100644 index 000000000..51325baf2 --- /dev/null +++ b/include/constants/form_change_types.h @@ -0,0 +1,123 @@ +#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 FUSION_TERMINATOR 0xFF +#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 +// param2: (optional) revert if specified ability is lost +#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 + +// Form change that activates when the mon has the defined item. +// If it's on the player's side, it also requires for the player to trigger it by pressing START before selecting a move. +// param1: item to hold. +#define FORM_CHANGE_BATTLE_ULTRA_BURST 16 + +// Form change that activates when the mon Dynamaxes (TODO: with Gigantamax factor). +// - No parameters +#define FORM_CHANGE_BATTLE_GIGANTAMAX 17 + +// Form change that activates at a certain time of day in the overworld automatically. +// param1: time of day to check. +// - DAY if Form change that activates in the daytime. +// - NIGHT if Form change that activates at nighttime. +#define FORM_CHANGE_TIME_OF_DAY 18 + +// Form change that depends on a multichoice (e.g. Rotom Catalog). +// param1: multichoice list (starting at 0). +#define FORM_CHANGE_ITEM_USE_MULTICHOICE 19 + +// Form change that activates when inflicted with a specific status +// param1: status +#define FORM_CHANGE_STATUS 20 + +#endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H diff --git a/include/constants/species.h b/include/constants/species.h index dd92a8c0e..07ebef6e1 100644 --- a/include/constants/species.h +++ b/include/constants/species.h @@ -419,7 +419,8 @@ #define SPECIES_BURMY_PLANT_CLOAK 412 #define SPECIES_WORMADAM SPECIES_WORMADAM_PLANT_CLOAK #define SPECIES_WORMADAM_PLANT_CLOAK 413 -#define SPECIES_MOTHIM 414 +#define SPECIES_MOTHIM SPECIES_MOTHIM_PLANT_CLOAK +#define SPECIES_MOTHIM_PLANT_CLOAK 414 #define SPECIES_COMBEE 415 #define SPECIES_VESPIQUEN 416 #define SPECIES_PACHIRISU 417 @@ -684,8 +685,10 @@ #define SPECIES_FLETCHLING 661 #define SPECIES_FLETCHINDER 662 #define SPECIES_TALONFLAME 663 -#define SPECIES_SCATTERBUG 664 -#define SPECIES_SPEWPA 665 +#define SPECIES_SCATTERBUG SPECIES_SCATTERBUG_ICY_SNOW +#define SPECIES_SCATTERBUG_ICY_SNOW 664 +#define SPECIES_SPEWPA SPECIES_SPEWPA_ICY_SNOW +#define SPECIES_SPEWPA_ICY_SNOW 665 #define SPECIES_VIVILLON SPECIES_VIVILLON_ICY_SNOW #define SPECIES_VIVILLON_ICY_SNOW 666 #define SPECIES_LITLEO 667 @@ -961,441 +964,329 @@ #define SPECIES_OVERQWIL 904 #define SPECIES_ENAMORUS SPECIES_ENAMORUS_INCARNATE #define SPECIES_ENAMORUS_INCARNATE 905 - -#define FORMS_START SPECIES_ENAMORUS_INCARNATE - -// Megas -#define SPECIES_VENUSAUR_MEGA FORMS_START + 1 -#define SPECIES_CHARIZARD_MEGA_X FORMS_START + 2 -#define SPECIES_CHARIZARD_MEGA_Y FORMS_START + 3 -#define SPECIES_BLASTOISE_MEGA FORMS_START + 4 -#define SPECIES_BEEDRILL_MEGA FORMS_START + 5 -#define SPECIES_PIDGEOT_MEGA FORMS_START + 6 -#define SPECIES_ALAKAZAM_MEGA FORMS_START + 7 -#define SPECIES_SLOWBRO_MEGA FORMS_START + 8 -#define SPECIES_GENGAR_MEGA FORMS_START + 9 -#define SPECIES_KANGASKHAN_MEGA FORMS_START + 10 -#define SPECIES_PINSIR_MEGA FORMS_START + 11 -#define SPECIES_GYARADOS_MEGA FORMS_START + 12 -#define SPECIES_AERODACTYL_MEGA FORMS_START + 13 -#define SPECIES_MEWTWO_MEGA_X FORMS_START + 14 -#define SPECIES_MEWTWO_MEGA_Y FORMS_START + 15 -#define SPECIES_AMPHAROS_MEGA FORMS_START + 16 -#define SPECIES_STEELIX_MEGA FORMS_START + 17 -#define SPECIES_SCIZOR_MEGA FORMS_START + 18 -#define SPECIES_HERACROSS_MEGA FORMS_START + 19 -#define SPECIES_HOUNDOOM_MEGA FORMS_START + 20 -#define SPECIES_TYRANITAR_MEGA FORMS_START + 21 -#define SPECIES_SCEPTILE_MEGA FORMS_START + 22 -#define SPECIES_BLAZIKEN_MEGA FORMS_START + 23 -#define SPECIES_SWAMPERT_MEGA FORMS_START + 24 -#define SPECIES_GARDEVOIR_MEGA FORMS_START + 25 -#define SPECIES_SABLEYE_MEGA FORMS_START + 26 -#define SPECIES_MAWILE_MEGA FORMS_START + 27 -#define SPECIES_AGGRON_MEGA FORMS_START + 28 -#define SPECIES_MEDICHAM_MEGA FORMS_START + 29 -#define SPECIES_MANECTRIC_MEGA FORMS_START + 30 -#define SPECIES_SHARPEDO_MEGA FORMS_START + 31 -#define SPECIES_CAMERUPT_MEGA FORMS_START + 32 -#define SPECIES_ALTARIA_MEGA FORMS_START + 33 -#define SPECIES_BANETTE_MEGA FORMS_START + 34 -#define SPECIES_ABSOL_MEGA FORMS_START + 35 -#define SPECIES_GLALIE_MEGA FORMS_START + 36 -#define SPECIES_SALAMENCE_MEGA FORMS_START + 37 -#define SPECIES_METAGROSS_MEGA FORMS_START + 38 -#define SPECIES_LATIAS_MEGA FORMS_START + 39 -#define SPECIES_LATIOS_MEGA FORMS_START + 40 -#define SPECIES_LOPUNNY_MEGA FORMS_START + 41 -#define SPECIES_GARCHOMP_MEGA FORMS_START + 42 -#define SPECIES_LUCARIO_MEGA FORMS_START + 43 -#define SPECIES_ABOMASNOW_MEGA FORMS_START + 44 -#define SPECIES_GALLADE_MEGA FORMS_START + 45 -#define SPECIES_AUDINO_MEGA FORMS_START + 46 -#define SPECIES_DIANCIE_MEGA FORMS_START + 47 - -// Special Mega + Primals -#define SPECIES_RAYQUAZA_MEGA FORMS_START + 48 -#define SPECIES_KYOGRE_PRIMAL FORMS_START + 49 -#define SPECIES_GROUDON_PRIMAL FORMS_START + 50 - -// Alolan Forms -#define SPECIES_RATTATA_ALOLAN FORMS_START + 51 -#define SPECIES_RATICATE_ALOLAN FORMS_START + 52 -#define SPECIES_RAICHU_ALOLAN FORMS_START + 53 -#define SPECIES_SANDSHREW_ALOLAN FORMS_START + 54 -#define SPECIES_SANDSLASH_ALOLAN FORMS_START + 55 -#define SPECIES_VULPIX_ALOLAN FORMS_START + 56 -#define SPECIES_NINETALES_ALOLAN FORMS_START + 57 -#define SPECIES_DIGLETT_ALOLAN FORMS_START + 58 -#define SPECIES_DUGTRIO_ALOLAN FORMS_START + 59 -#define SPECIES_MEOWTH_ALOLAN FORMS_START + 60 -#define SPECIES_PERSIAN_ALOLAN FORMS_START + 61 -#define SPECIES_GEODUDE_ALOLAN FORMS_START + 62 -#define SPECIES_GRAVELER_ALOLAN FORMS_START + 63 -#define SPECIES_GOLEM_ALOLAN FORMS_START + 64 -#define SPECIES_GRIMER_ALOLAN FORMS_START + 65 -#define SPECIES_MUK_ALOLAN FORMS_START + 66 -#define SPECIES_EXEGGUTOR_ALOLAN FORMS_START + 67 -#define SPECIES_MAROWAK_ALOLAN FORMS_START + 68 - -// Galarian Forms -#define SPECIES_MEOWTH_GALARIAN FORMS_START + 69 -#define SPECIES_PONYTA_GALARIAN FORMS_START + 70 -#define SPECIES_RAPIDASH_GALARIAN FORMS_START + 71 -#define SPECIES_SLOWPOKE_GALARIAN FORMS_START + 72 -#define SPECIES_SLOWBRO_GALARIAN FORMS_START + 73 -#define SPECIES_FARFETCHD_GALARIAN FORMS_START + 74 -#define SPECIES_WEEZING_GALARIAN FORMS_START + 75 -#define SPECIES_MR_MIME_GALARIAN FORMS_START + 76 -#define SPECIES_ARTICUNO_GALARIAN FORMS_START + 77 -#define SPECIES_ZAPDOS_GALARIAN FORMS_START + 78 -#define SPECIES_MOLTRES_GALARIAN FORMS_START + 79 -#define SPECIES_SLOWKING_GALARIAN FORMS_START + 80 -#define SPECIES_CORSOLA_GALARIAN FORMS_START + 81 -#define SPECIES_ZIGZAGOON_GALARIAN FORMS_START + 82 -#define SPECIES_LINOONE_GALARIAN FORMS_START + 83 -#define SPECIES_DARUMAKA_GALARIAN FORMS_START + 84 +#define SPECIES_VENUSAUR_MEGA 906 +#define SPECIES_CHARIZARD_MEGA_X 907 +#define SPECIES_CHARIZARD_MEGA_Y 908 +#define SPECIES_BLASTOISE_MEGA 909 +#define SPECIES_BEEDRILL_MEGA 910 +#define SPECIES_PIDGEOT_MEGA 911 +#define SPECIES_ALAKAZAM_MEGA 912 +#define SPECIES_SLOWBRO_MEGA 913 +#define SPECIES_GENGAR_MEGA 914 +#define SPECIES_KANGASKHAN_MEGA 915 +#define SPECIES_PINSIR_MEGA 916 +#define SPECIES_GYARADOS_MEGA 917 +#define SPECIES_AERODACTYL_MEGA 918 +#define SPECIES_MEWTWO_MEGA_X 919 +#define SPECIES_MEWTWO_MEGA_Y 920 +#define SPECIES_AMPHAROS_MEGA 921 +#define SPECIES_STEELIX_MEGA 922 +#define SPECIES_SCIZOR_MEGA 923 +#define SPECIES_HERACROSS_MEGA 924 +#define SPECIES_HOUNDOOM_MEGA 925 +#define SPECIES_TYRANITAR_MEGA 926 +#define SPECIES_SCEPTILE_MEGA 927 +#define SPECIES_BLAZIKEN_MEGA 928 +#define SPECIES_SWAMPERT_MEGA 929 +#define SPECIES_GARDEVOIR_MEGA 930 +#define SPECIES_SABLEYE_MEGA 931 +#define SPECIES_MAWILE_MEGA 932 +#define SPECIES_AGGRON_MEGA 933 +#define SPECIES_MEDICHAM_MEGA 934 +#define SPECIES_MANECTRIC_MEGA 935 +#define SPECIES_SHARPEDO_MEGA 936 +#define SPECIES_CAMERUPT_MEGA 937 +#define SPECIES_ALTARIA_MEGA 938 +#define SPECIES_BANETTE_MEGA 939 +#define SPECIES_ABSOL_MEGA 940 +#define SPECIES_GLALIE_MEGA 941 +#define SPECIES_SALAMENCE_MEGA 942 +#define SPECIES_METAGROSS_MEGA 943 +#define SPECIES_LATIAS_MEGA 944 +#define SPECIES_LATIOS_MEGA 945 +#define SPECIES_LOPUNNY_MEGA 946 +#define SPECIES_GARCHOMP_MEGA 947 +#define SPECIES_LUCARIO_MEGA 948 +#define SPECIES_ABOMASNOW_MEGA 949 +#define SPECIES_GALLADE_MEGA 950 +#define SPECIES_AUDINO_MEGA 951 +#define SPECIES_DIANCIE_MEGA 952 +#define SPECIES_RAYQUAZA_MEGA 953 +#define SPECIES_KYOGRE_PRIMAL 954 +#define SPECIES_GROUDON_PRIMAL 955 +#define SPECIES_RATTATA_ALOLAN 956 +#define SPECIES_RATICATE_ALOLAN 957 +#define SPECIES_RAICHU_ALOLAN 958 +#define SPECIES_SANDSHREW_ALOLAN 959 +#define SPECIES_SANDSLASH_ALOLAN 960 +#define SPECIES_VULPIX_ALOLAN 961 +#define SPECIES_NINETALES_ALOLAN 962 +#define SPECIES_DIGLETT_ALOLAN 963 +#define SPECIES_DUGTRIO_ALOLAN 964 +#define SPECIES_MEOWTH_ALOLAN 965 +#define SPECIES_PERSIAN_ALOLAN 966 +#define SPECIES_GEODUDE_ALOLAN 967 +#define SPECIES_GRAVELER_ALOLAN 968 +#define SPECIES_GOLEM_ALOLAN 969 +#define SPECIES_GRIMER_ALOLAN 970 +#define SPECIES_MUK_ALOLAN 971 +#define SPECIES_EXEGGUTOR_ALOLAN 972 +#define SPECIES_MAROWAK_ALOLAN 973 +#define SPECIES_MEOWTH_GALARIAN 974 +#define SPECIES_PONYTA_GALARIAN 975 +#define SPECIES_RAPIDASH_GALARIAN 976 +#define SPECIES_SLOWPOKE_GALARIAN 977 +#define SPECIES_SLOWBRO_GALARIAN 978 +#define SPECIES_FARFETCHD_GALARIAN 979 +#define SPECIES_WEEZING_GALARIAN 980 +#define SPECIES_MR_MIME_GALARIAN 981 +#define SPECIES_ARTICUNO_GALARIAN 982 +#define SPECIES_ZAPDOS_GALARIAN 983 +#define SPECIES_MOLTRES_GALARIAN 984 +#define SPECIES_SLOWKING_GALARIAN 985 +#define SPECIES_CORSOLA_GALARIAN 986 +#define SPECIES_ZIGZAGOON_GALARIAN 987 +#define SPECIES_LINOONE_GALARIAN 988 +#define SPECIES_DARUMAKA_GALARIAN 989 #define SPECIES_DARMANITAN_GALARIAN SPECIES_DARMANITAN_GALARIAN_STANDARD_MODE -#define SPECIES_DARMANITAN_GALARIAN_STANDARD_MODE FORMS_START + 85 -#define SPECIES_YAMASK_GALARIAN FORMS_START + 86 -#define SPECIES_STUNFISK_GALARIAN FORMS_START + 87 +#define SPECIES_DARMANITAN_GALARIAN_STANDARD_MODE 990 +#define SPECIES_YAMASK_GALARIAN 991 +#define SPECIES_STUNFISK_GALARIAN 992 //Hisuian Forms -#define SPECIES_GROWLITHE_HISUIAN FORMS_START + 88 -#define SPECIES_ARCANINE_HISUIAN FORMS_START + 89 -#define SPECIES_VOLTORB_HISUIAN FORMS_START + 90 -#define SPECIES_ELECTRODE_HISUIAN FORMS_START + 91 -#define SPECIES_TYPHLOSION_HISUIAN FORMS_START + 92 -#define SPECIES_QWILFISH_HISUIAN FORMS_START + 93 -#define SPECIES_SNEASEL_HISUIAN FORMS_START + 94 -#define SPECIES_SAMUROTT_HISUIAN FORMS_START + 95 -#define SPECIES_LILLIGANT_HISUIAN FORMS_START + 96 -#define SPECIES_ZORUA_HISUIAN FORMS_START + 97 -#define SPECIES_ZOROARK_HISUIAN FORMS_START + 98 -#define SPECIES_BRAVIARY_HISUIAN FORMS_START + 99 -#define SPECIES_SLIGGOO_HISUIAN FORMS_START + 100 -#define SPECIES_GOODRA_HISUIAN FORMS_START + 101 -#define SPECIES_AVALUGG_HISUIAN FORMS_START + 102 -#define SPECIES_DECIDUEYE_HISUIAN FORMS_START + 103 +#define SPECIES_GROWLITHE_HISUIAN 993 +#define SPECIES_ARCANINE_HISUIAN 994 +#define SPECIES_VOLTORB_HISUIAN 995 +#define SPECIES_ELECTRODE_HISUIAN 996 +#define SPECIES_TYPHLOSION_HISUIAN 997 +#define SPECIES_QWILFISH_HISUIAN 998 +#define SPECIES_SNEASEL_HISUIAN 999 +#define SPECIES_SAMUROTT_HISUIAN 1000 +#define SPECIES_LILLIGANT_HISUIAN 1001 +#define SPECIES_ZORUA_HISUIAN 1002 +#define SPECIES_ZOROARK_HISUIAN 1003 +#define SPECIES_BRAVIARY_HISUIAN 1004 +#define SPECIES_SLIGGOO_HISUIAN 1005 +#define SPECIES_GOODRA_HISUIAN 1006 +#define SPECIES_AVALUGG_HISUIAN 1007 +#define SPECIES_DECIDUEYE_HISUIAN 1008 // Misc Forms - -// Cosplay Pikachu -#define SPECIES_PIKACHU_COSPLAY FORMS_START + 104 -#define SPECIES_PIKACHU_ROCK_STAR FORMS_START + 105 -#define SPECIES_PIKACHU_BELLE FORMS_START + 106 -#define SPECIES_PIKACHU_POP_STAR FORMS_START + 107 -#define SPECIES_PIKACHU_PH_D FORMS_START + 108 -#define SPECIES_PIKACHU_LIBRE FORMS_START + 109 - -// Cap Pikachu -#define SPECIES_PIKACHU_ORIGINAL_CAP FORMS_START + 110 -#define SPECIES_PIKACHU_HOENN_CAP FORMS_START + 111 -#define SPECIES_PIKACHU_SINNOH_CAP FORMS_START + 112 -#define SPECIES_PIKACHU_UNOVA_CAP FORMS_START + 113 -#define SPECIES_PIKACHU_KALOS_CAP FORMS_START + 114 -#define SPECIES_PIKACHU_ALOLA_CAP FORMS_START + 115 -#define SPECIES_PIKACHU_PARTNER_CAP FORMS_START + 116 -#define SPECIES_PIKACHU_WORLD_CAP FORMS_START + 117 - -// Pichu -#define SPECIES_PICHU_SPIKY_EARED FORMS_START + 118 - -// Unown -#define SPECIES_UNOWN_B FORMS_START + 119 -#define SPECIES_UNOWN_C FORMS_START + 120 -#define SPECIES_UNOWN_D FORMS_START + 121 -#define SPECIES_UNOWN_E FORMS_START + 122 -#define SPECIES_UNOWN_F FORMS_START + 123 -#define SPECIES_UNOWN_G FORMS_START + 124 -#define SPECIES_UNOWN_H FORMS_START + 125 -#define SPECIES_UNOWN_I FORMS_START + 126 -#define SPECIES_UNOWN_J FORMS_START + 127 -#define SPECIES_UNOWN_K FORMS_START + 128 -#define SPECIES_UNOWN_L FORMS_START + 129 -#define SPECIES_UNOWN_M FORMS_START + 130 -#define SPECIES_UNOWN_N FORMS_START + 131 -#define SPECIES_UNOWN_O FORMS_START + 132 -#define SPECIES_UNOWN_P FORMS_START + 133 -#define SPECIES_UNOWN_Q FORMS_START + 134 -#define SPECIES_UNOWN_R FORMS_START + 135 -#define SPECIES_UNOWN_S FORMS_START + 136 -#define SPECIES_UNOWN_T FORMS_START + 137 -#define SPECIES_UNOWN_U FORMS_START + 138 -#define SPECIES_UNOWN_V FORMS_START + 139 -#define SPECIES_UNOWN_W FORMS_START + 140 -#define SPECIES_UNOWN_X FORMS_START + 141 -#define SPECIES_UNOWN_Y FORMS_START + 142 -#define SPECIES_UNOWN_Z FORMS_START + 143 -#define SPECIES_UNOWN_EMARK FORMS_START + 144 -#define SPECIES_UNOWN_QMARK FORMS_START + 145 - -// Castform -#define SPECIES_CASTFORM_SUNNY FORMS_START + 146 -#define SPECIES_CASTFORM_RAINY FORMS_START + 147 -#define SPECIES_CASTFORM_SNOWY FORMS_START + 148 - -// Deoxys -#define SPECIES_DEOXYS_ATTACK FORMS_START + 149 -#define SPECIES_DEOXYS_DEFENSE FORMS_START + 150 -#define SPECIES_DEOXYS_SPEED FORMS_START + 151 - -// Burmy -#define SPECIES_BURMY_SANDY_CLOAK FORMS_START + 152 -#define SPECIES_BURMY_TRASH_CLOAK FORMS_START + 153 - -// Wormadam -#define SPECIES_WORMADAM_SANDY_CLOAK FORMS_START + 154 -#define SPECIES_WORMADAM_TRASH_CLOAK FORMS_START + 155 - -// Cherrim -#define SPECIES_CHERRIM_SUNSHINE FORMS_START + 156 - -// Shellos -#define SPECIES_SHELLOS_EAST_SEA FORMS_START + 157 - -// Gastrodon -#define SPECIES_GASTRODON_EAST_SEA FORMS_START + 158 - -// Rotom -#define SPECIES_ROTOM_HEAT FORMS_START + 159 -#define SPECIES_ROTOM_WASH FORMS_START + 160 -#define SPECIES_ROTOM_FROST FORMS_START + 161 -#define SPECIES_ROTOM_FAN FORMS_START + 162 -#define SPECIES_ROTOM_MOW FORMS_START + 163 - -// Origin Forme -#define SPECIES_DIALGA_ORIGIN FORMS_START + 164 -#define SPECIES_PALKIA_ORIGIN FORMS_START + 165 -#define SPECIES_GIRATINA_ORIGIN FORMS_START + 166 - -// Shaymin -#define SPECIES_SHAYMIN_SKY FORMS_START + 167 - -// Arceus -#define SPECIES_ARCEUS_FIGHTING FORMS_START + 168 -#define SPECIES_ARCEUS_FLYING FORMS_START + 169 -#define SPECIES_ARCEUS_POISON FORMS_START + 170 -#define SPECIES_ARCEUS_GROUND FORMS_START + 171 -#define SPECIES_ARCEUS_ROCK FORMS_START + 172 -#define SPECIES_ARCEUS_BUG FORMS_START + 173 -#define SPECIES_ARCEUS_GHOST FORMS_START + 174 -#define SPECIES_ARCEUS_STEEL FORMS_START + 175 -#define SPECIES_ARCEUS_FIRE FORMS_START + 176 -#define SPECIES_ARCEUS_WATER FORMS_START + 177 -#define SPECIES_ARCEUS_GRASS FORMS_START + 178 -#define SPECIES_ARCEUS_ELECTRIC FORMS_START + 179 -#define SPECIES_ARCEUS_PSYCHIC FORMS_START + 180 -#define SPECIES_ARCEUS_ICE FORMS_START + 181 -#define SPECIES_ARCEUS_DRAGON FORMS_START + 182 -#define SPECIES_ARCEUS_DARK FORMS_START + 183 -#define SPECIES_ARCEUS_FAIRY FORMS_START + 184 - -// Basculin -#define SPECIES_BASCULIN_BLUE_STRIPED FORMS_START + 185 -#define SPECIES_BASCULIN_WHITE_STRIPED FORMS_START + 186 - -// Darmanitan -#define SPECIES_DARMANITAN_ZEN_MODE FORMS_START + 187 -#define SPECIES_DARMANITAN_GALARIAN_ZEN_MODE FORMS_START + 188 - -// Deerling -#define SPECIES_DEERLING_SUMMER FORMS_START + 189 -#define SPECIES_DEERLING_AUTUMN FORMS_START + 190 -#define SPECIES_DEERLING_WINTER FORMS_START + 191 - -// Sawsbuck -#define SPECIES_SAWSBUCK_SUMMER FORMS_START + 192 -#define SPECIES_SAWSBUCK_AUTUMN FORMS_START + 193 -#define SPECIES_SAWSBUCK_WINTER FORMS_START + 194 - -// Therian Forms -#define SPECIES_TORNADUS_THERIAN FORMS_START + 195 -#define SPECIES_THUNDURUS_THERIAN FORMS_START + 196 -#define SPECIES_LANDORUS_THERIAN FORMS_START + 197 -#define SPECIES_ENAMORUS_THERIAN FORMS_START + 198 - -// Kyurem -#define SPECIES_KYUREM_WHITE FORMS_START + 199 -#define SPECIES_KYUREM_BLACK FORMS_START + 200 - -// Keldeo -#define SPECIES_KELDEO_RESOLUTE FORMS_START + 201 - -// Meloetta -#define SPECIES_MELOETTA_PIROUETTE FORMS_START + 202 - -// Genesect -#define SPECIES_GENESECT_DOUSE_DRIVE FORMS_START + 203 -#define SPECIES_GENESECT_SHOCK_DRIVE FORMS_START + 204 -#define SPECIES_GENESECT_BURN_DRIVE FORMS_START + 205 -#define SPECIES_GENESECT_CHILL_DRIVE FORMS_START + 206 - -// Greninja -#define SPECIES_GRENINJA_BATTLE_BOND FORMS_START + 207 -#define SPECIES_GRENINJA_ASH FORMS_START + 208 - -// Vivillon -#define SPECIES_VIVILLON_POLAR FORMS_START + 209 -#define SPECIES_VIVILLON_TUNDRA FORMS_START + 210 -#define SPECIES_VIVILLON_CONTINENTAL FORMS_START + 211 -#define SPECIES_VIVILLON_GARDEN FORMS_START + 212 -#define SPECIES_VIVILLON_ELEGANT FORMS_START + 213 -#define SPECIES_VIVILLON_MEADOW FORMS_START + 214 -#define SPECIES_VIVILLON_MODERN FORMS_START + 215 -#define SPECIES_VIVILLON_MARINE FORMS_START + 216 -#define SPECIES_VIVILLON_ARCHIPELAGO FORMS_START + 217 -#define SPECIES_VIVILLON_HIGH_PLAINS FORMS_START + 218 -#define SPECIES_VIVILLON_SANDSTORM FORMS_START + 219 -#define SPECIES_VIVILLON_RIVER FORMS_START + 220 -#define SPECIES_VIVILLON_MONSOON FORMS_START + 221 -#define SPECIES_VIVILLON_SAVANNA FORMS_START + 222 -#define SPECIES_VIVILLON_SUN FORMS_START + 223 -#define SPECIES_VIVILLON_OCEAN FORMS_START + 224 -#define SPECIES_VIVILLON_JUNGLE FORMS_START + 225 -#define SPECIES_VIVILLON_FANCY FORMS_START + 226 -#define SPECIES_VIVILLON_POKE_BALL FORMS_START + 227 - -// Flabébé -#define SPECIES_FLABEBE_YELLOW_FLOWER FORMS_START + 228 -#define SPECIES_FLABEBE_ORANGE_FLOWER FORMS_START + 229 -#define SPECIES_FLABEBE_BLUE_FLOWER FORMS_START + 230 -#define SPECIES_FLABEBE_WHITE_FLOWER FORMS_START + 231 - -// Floette -#define SPECIES_FLOETTE_YELLOW_FLOWER FORMS_START + 232 -#define SPECIES_FLOETTE_ORANGE_FLOWER FORMS_START + 233 -#define SPECIES_FLOETTE_BLUE_FLOWER FORMS_START + 234 -#define SPECIES_FLOETTE_WHITE_FLOWER FORMS_START + 235 -#define SPECIES_FLOETTE_ETERNAL_FLOWER FORMS_START + 236 - -// Florges -#define SPECIES_FLORGES_YELLOW_FLOWER FORMS_START + 237 -#define SPECIES_FLORGES_ORANGE_FLOWER FORMS_START + 238 -#define SPECIES_FLORGES_BLUE_FLOWER FORMS_START + 239 -#define SPECIES_FLORGES_WHITE_FLOWER FORMS_START + 240 - -// Furfrou -#define SPECIES_FURFROU_HEART_TRIM FORMS_START + 241 -#define SPECIES_FURFROU_STAR_TRIM FORMS_START + 242 -#define SPECIES_FURFROU_DIAMOND_TRIM FORMS_START + 243 -#define SPECIES_FURFROU_DEBUTANTE_TRIM FORMS_START + 244 -#define SPECIES_FURFROU_MATRON_TRIM FORMS_START + 245 -#define SPECIES_FURFROU_DANDY_TRIM FORMS_START + 246 -#define SPECIES_FURFROU_LA_REINE_TRIM FORMS_START + 247 -#define SPECIES_FURFROU_KABUKI_TRIM FORMS_START + 248 -#define SPECIES_FURFROU_PHARAOH_TRIM FORMS_START + 249 - -// Meowstic -#define SPECIES_MEOWSTIC_FEMALE FORMS_START + 250 - -// Aegislash -#define SPECIES_AEGISLASH_BLADE FORMS_START + 251 - -// Pumpkaboo -#define SPECIES_PUMPKABOO_SMALL FORMS_START + 252 -#define SPECIES_PUMPKABOO_LARGE FORMS_START + 253 -#define SPECIES_PUMPKABOO_SUPER FORMS_START + 254 - -// Gourgeist -#define SPECIES_GOURGEIST_SMALL FORMS_START + 255 -#define SPECIES_GOURGEIST_LARGE FORMS_START + 256 -#define SPECIES_GOURGEIST_SUPER FORMS_START + 257 - -// Xerneas -#define SPECIES_XERNEAS_ACTIVE FORMS_START + 258 - -// Zygarde +#define SPECIES_PIKACHU_COSPLAY 1009 +#define SPECIES_PIKACHU_ROCK_STAR 1010 +#define SPECIES_PIKACHU_BELLE 1011 +#define SPECIES_PIKACHU_POP_STAR 1012 +#define SPECIES_PIKACHU_PH_D 1013 +#define SPECIES_PIKACHU_LIBRE 1014 +#define SPECIES_PIKACHU_ORIGINAL_CAP 1015 +#define SPECIES_PIKACHU_HOENN_CAP 1016 +#define SPECIES_PIKACHU_SINNOH_CAP 1017 +#define SPECIES_PIKACHU_UNOVA_CAP 1018 +#define SPECIES_PIKACHU_KALOS_CAP 1019 +#define SPECIES_PIKACHU_ALOLA_CAP 1020 +#define SPECIES_PIKACHU_PARTNER_CAP 1021 +#define SPECIES_PIKACHU_WORLD_CAP 1022 +#define SPECIES_PICHU_SPIKY_EARED 1023 +#define SPECIES_UNOWN_B 1024 +#define SPECIES_UNOWN_C 1025 +#define SPECIES_UNOWN_D 1026 +#define SPECIES_UNOWN_E 1027 +#define SPECIES_UNOWN_F 1028 +#define SPECIES_UNOWN_G 1029 +#define SPECIES_UNOWN_H 1030 +#define SPECIES_UNOWN_I 1031 +#define SPECIES_UNOWN_J 1032 +#define SPECIES_UNOWN_K 1033 +#define SPECIES_UNOWN_L 1034 +#define SPECIES_UNOWN_M 1035 +#define SPECIES_UNOWN_N 1036 +#define SPECIES_UNOWN_O 1037 +#define SPECIES_UNOWN_P 1038 +#define SPECIES_UNOWN_Q 1039 +#define SPECIES_UNOWN_R 1040 +#define SPECIES_UNOWN_S 1041 +#define SPECIES_UNOWN_T 1042 +#define SPECIES_UNOWN_U 1043 +#define SPECIES_UNOWN_V 1044 +#define SPECIES_UNOWN_W 1045 +#define SPECIES_UNOWN_X 1046 +#define SPECIES_UNOWN_Y 1047 +#define SPECIES_UNOWN_Z 1048 +#define SPECIES_UNOWN_EMARK 1049 +#define SPECIES_UNOWN_QMARK 1050 +#define SPECIES_CASTFORM_SUNNY 1051 +#define SPECIES_CASTFORM_RAINY 1052 +#define SPECIES_CASTFORM_SNOWY 1053 +#define SPECIES_DEOXYS_ATTACK 1054 +#define SPECIES_DEOXYS_DEFENSE 1055 +#define SPECIES_DEOXYS_SPEED 1056 +#define SPECIES_BURMY_SANDY_CLOAK 1057 +#define SPECIES_BURMY_TRASH_CLOAK 1058 +#define SPECIES_WORMADAM_SANDY_CLOAK 1059 +#define SPECIES_WORMADAM_TRASH_CLOAK 1060 +#define SPECIES_CHERRIM_SUNSHINE 1061 +#define SPECIES_SHELLOS_EAST_SEA 1062 +#define SPECIES_GASTRODON_EAST_SEA 1063 +#define SPECIES_ROTOM_HEAT 1064 +#define SPECIES_ROTOM_WASH 1065 +#define SPECIES_ROTOM_FROST 1066 +#define SPECIES_ROTOM_FAN 1067 +#define SPECIES_ROTOM_MOW 1068 +#define SPECIES_DIALGA_ORIGIN 1069 +#define SPECIES_PALKIA_ORIGIN 1070 +#define SPECIES_GIRATINA_ORIGIN 1071 +#define SPECIES_SHAYMIN_SKY 1072 +#define SPECIES_ARCEUS_FIGHTING 1073 +#define SPECIES_ARCEUS_FLYING 1074 +#define SPECIES_ARCEUS_POISON 1075 +#define SPECIES_ARCEUS_GROUND 1076 +#define SPECIES_ARCEUS_ROCK 1077 +#define SPECIES_ARCEUS_BUG 1078 +#define SPECIES_ARCEUS_GHOST 1079 +#define SPECIES_ARCEUS_STEEL 1080 +#define SPECIES_ARCEUS_FIRE 1081 +#define SPECIES_ARCEUS_WATER 1082 +#define SPECIES_ARCEUS_GRASS 1083 +#define SPECIES_ARCEUS_ELECTRIC 1084 +#define SPECIES_ARCEUS_PSYCHIC 1085 +#define SPECIES_ARCEUS_ICE 1086 +#define SPECIES_ARCEUS_DRAGON 1087 +#define SPECIES_ARCEUS_DARK 1088 +#define SPECIES_ARCEUS_FAIRY 1089 +#define SPECIES_BASCULIN_BLUE_STRIPED 1090 +#define SPECIES_BASCULIN_WHITE_STRIPED 1091 +#define SPECIES_DARMANITAN_ZEN_MODE 1092 +#define SPECIES_DARMANITAN_GALARIAN_ZEN_MODE 1093 +#define SPECIES_DEERLING_SUMMER 1094 +#define SPECIES_DEERLING_AUTUMN 1095 +#define SPECIES_DEERLING_WINTER 1096 +#define SPECIES_SAWSBUCK_SUMMER 1097 +#define SPECIES_SAWSBUCK_AUTUMN 1098 +#define SPECIES_SAWSBUCK_WINTER 1099 +#define SPECIES_TORNADUS_THERIAN 1100 +#define SPECIES_THUNDURUS_THERIAN 1101 +#define SPECIES_LANDORUS_THERIAN 1102 +#define SPECIES_ENAMORUS_THERIAN 1103 +#define SPECIES_KYUREM_WHITE 1104 +#define SPECIES_KYUREM_BLACK 1105 +#define SPECIES_KELDEO_RESOLUTE 1106 +#define SPECIES_MELOETTA_PIROUETTE 1107 +#define SPECIES_GENESECT_DOUSE_DRIVE 1108 +#define SPECIES_GENESECT_SHOCK_DRIVE 1109 +#define SPECIES_GENESECT_BURN_DRIVE 1110 +#define SPECIES_GENESECT_CHILL_DRIVE 1111 +#define SPECIES_GRENINJA_BATTLE_BOND 1112 +#define SPECIES_GRENINJA_ASH 1113 +#define SPECIES_VIVILLON_POLAR 1114 +#define SPECIES_VIVILLON_TUNDRA 1115 +#define SPECIES_VIVILLON_CONTINENTAL 1116 +#define SPECIES_VIVILLON_GARDEN 1117 +#define SPECIES_VIVILLON_ELEGANT 1118 +#define SPECIES_VIVILLON_MEADOW 1119 +#define SPECIES_VIVILLON_MODERN 1120 +#define SPECIES_VIVILLON_MARINE 1121 +#define SPECIES_VIVILLON_ARCHIPELAGO 1122 +#define SPECIES_VIVILLON_HIGH_PLAINS 1123 +#define SPECIES_VIVILLON_SANDSTORM 1124 +#define SPECIES_VIVILLON_RIVER 1125 +#define SPECIES_VIVILLON_MONSOON 1126 +#define SPECIES_VIVILLON_SAVANNA 1127 +#define SPECIES_VIVILLON_SUN 1128 +#define SPECIES_VIVILLON_OCEAN 1129 +#define SPECIES_VIVILLON_JUNGLE 1130 +#define SPECIES_VIVILLON_FANCY 1131 +#define SPECIES_VIVILLON_POKE_BALL 1132 +#define SPECIES_FLABEBE_YELLOW_FLOWER 1133 +#define SPECIES_FLABEBE_ORANGE_FLOWER 1134 +#define SPECIES_FLABEBE_BLUE_FLOWER 1135 +#define SPECIES_FLABEBE_WHITE_FLOWER 1136 +#define SPECIES_FLOETTE_YELLOW_FLOWER 1137 +#define SPECIES_FLOETTE_ORANGE_FLOWER 1138 +#define SPECIES_FLOETTE_BLUE_FLOWER 1139 +#define SPECIES_FLOETTE_WHITE_FLOWER 1140 +#define SPECIES_FLOETTE_ETERNAL_FLOWER 1141 +#define SPECIES_FLORGES_YELLOW_FLOWER 1142 +#define SPECIES_FLORGES_ORANGE_FLOWER 1143 +#define SPECIES_FLORGES_BLUE_FLOWER 1144 +#define SPECIES_FLORGES_WHITE_FLOWER 1145 +#define SPECIES_FURFROU_HEART_TRIM 1146 +#define SPECIES_FURFROU_STAR_TRIM 1147 +#define SPECIES_FURFROU_DIAMOND_TRIM 1148 +#define SPECIES_FURFROU_DEBUTANTE_TRIM 1149 +#define SPECIES_FURFROU_MATRON_TRIM 1150 +#define SPECIES_FURFROU_DANDY_TRIM 1151 +#define SPECIES_FURFROU_LA_REINE_TRIM 1152 +#define SPECIES_FURFROU_KABUKI_TRIM 1153 +#define SPECIES_FURFROU_PHARAOH_TRIM 1154 +#define SPECIES_MEOWSTIC_FEMALE 1155 +#define SPECIES_AEGISLASH_BLADE 1156 +#define SPECIES_PUMPKABOO_SMALL 1157 +#define SPECIES_PUMPKABOO_LARGE 1158 +#define SPECIES_PUMPKABOO_SUPER 1159 +#define SPECIES_GOURGEIST_SMALL 1160 +#define SPECIES_GOURGEIST_LARGE 1161 +#define SPECIES_GOURGEIST_SUPER 1162 +#define SPECIES_XERNEAS_ACTIVE 1163 #define SPECIES_ZYGARDE_10 SPECIES_ZYGARDE_10_AURA_BREAK -#define SPECIES_ZYGARDE_10_AURA_BREAK FORMS_START + 259 -#define SPECIES_ZYGARDE_10_POWER_CONSTRUCT FORMS_START + 260 -#define SPECIES_ZYGARDE_50_POWER_CONSTRUCT FORMS_START + 261 -#define SPECIES_ZYGARDE_COMPLETE FORMS_START + 262 - -// Hoopa -#define SPECIES_HOOPA_UNBOUND FORMS_START + 263 - -// Oricorio -#define SPECIES_ORICORIO_POM_POM FORMS_START + 264 -#define SPECIES_ORICORIO_PAU FORMS_START + 265 -#define SPECIES_ORICORIO_SENSU FORMS_START + 266 - -// Rockruff -#define SPECIES_ROCKRUFF_OWN_TEMPO FORMS_START + 267 - -// Lycanroc -#define SPECIES_LYCANROC_MIDNIGHT FORMS_START + 268 -#define SPECIES_LYCANROC_DUSK FORMS_START + 269 - -// Wishiwashi -#define SPECIES_WISHIWASHI_SCHOOL FORMS_START + 270 - -// Silvally -#define SPECIES_SILVALLY_FIGHTING FORMS_START + 271 -#define SPECIES_SILVALLY_FLYING FORMS_START + 272 -#define SPECIES_SILVALLY_POISON FORMS_START + 273 -#define SPECIES_SILVALLY_GROUND FORMS_START + 274 -#define SPECIES_SILVALLY_ROCK FORMS_START + 275 -#define SPECIES_SILVALLY_BUG FORMS_START + 276 -#define SPECIES_SILVALLY_GHOST FORMS_START + 277 -#define SPECIES_SILVALLY_STEEL FORMS_START + 278 -#define SPECIES_SILVALLY_FIRE FORMS_START + 279 -#define SPECIES_SILVALLY_WATER FORMS_START + 280 -#define SPECIES_SILVALLY_GRASS FORMS_START + 281 -#define SPECIES_SILVALLY_ELECTRIC FORMS_START + 282 -#define SPECIES_SILVALLY_PSYCHIC FORMS_START + 283 -#define SPECIES_SILVALLY_ICE FORMS_START + 284 -#define SPECIES_SILVALLY_DRAGON FORMS_START + 285 -#define SPECIES_SILVALLY_DARK FORMS_START + 286 -#define SPECIES_SILVALLY_FAIRY FORMS_START + 287 - -// Minior +#define SPECIES_ZYGARDE_10_AURA_BREAK 1164 +#define SPECIES_ZYGARDE_10_POWER_CONSTRUCT 1165 +#define SPECIES_ZYGARDE_50_POWER_CONSTRUCT 1166 +#define SPECIES_ZYGARDE_COMPLETE 1167 +#define SPECIES_HOOPA_UNBOUND 1168 +#define SPECIES_ORICORIO_POM_POM 1169 +#define SPECIES_ORICORIO_PAU 1170 +#define SPECIES_ORICORIO_SENSU 1171 +#define SPECIES_ROCKRUFF_OWN_TEMPO 1172 +#define SPECIES_LYCANROC_MIDNIGHT 1173 +#define SPECIES_LYCANROC_DUSK 1174 +#define SPECIES_WISHIWASHI_SCHOOL 1175 +#define SPECIES_SILVALLY_FIGHTING 1176 +#define SPECIES_SILVALLY_FLYING 1177 +#define SPECIES_SILVALLY_POISON 1178 +#define SPECIES_SILVALLY_GROUND 1179 +#define SPECIES_SILVALLY_ROCK 1180 +#define SPECIES_SILVALLY_BUG 1181 +#define SPECIES_SILVALLY_GHOST 1182 +#define SPECIES_SILVALLY_STEEL 1183 +#define SPECIES_SILVALLY_FIRE 1184 +#define SPECIES_SILVALLY_WATER 1185 +#define SPECIES_SILVALLY_GRASS 1186 +#define SPECIES_SILVALLY_ELECTRIC 1187 +#define SPECIES_SILVALLY_PSYCHIC 1188 +#define SPECIES_SILVALLY_ICE 1189 +#define SPECIES_SILVALLY_DRAGON 1190 +#define SPECIES_SILVALLY_DARK 1191 +#define SPECIES_SILVALLY_FAIRY 1192 #define SPECIES_MINIOR_ORANGE SPECIES_MINIOR_METEOR_ORANGE #define SPECIES_MINIOR_YELLOW SPECIES_MINIOR_METEOR_YELLOW #define SPECIES_MINIOR_GREEN SPECIES_MINIOR_METEOR_GREEN #define SPECIES_MINIOR_BLUE SPECIES_MINIOR_METEOR_BLUE #define SPECIES_MINIOR_INDIGO SPECIES_MINIOR_METEOR_INDIGO #define SPECIES_MINIOR_VIOLET SPECIES_MINIOR_METEOR_VIOLET -#define SPECIES_MINIOR_METEOR_ORANGE FORMS_START + 288 -#define SPECIES_MINIOR_METEOR_YELLOW FORMS_START + 289 -#define SPECIES_MINIOR_METEOR_GREEN FORMS_START + 290 -#define SPECIES_MINIOR_METEOR_BLUE FORMS_START + 291 -#define SPECIES_MINIOR_METEOR_INDIGO FORMS_START + 292 -#define SPECIES_MINIOR_METEOR_VIOLET FORMS_START + 293 +#define SPECIES_MINIOR_METEOR_ORANGE 1193 +#define SPECIES_MINIOR_METEOR_YELLOW 1194 +#define SPECIES_MINIOR_METEOR_GREEN 1195 +#define SPECIES_MINIOR_METEOR_BLUE 1196 +#define SPECIES_MINIOR_METEOR_INDIGO 1197 +#define SPECIES_MINIOR_METEOR_VIOLET 1198 #define SPECIES_MINIOR_CORE SPECIES_MINIOR_CORE_RED -#define SPECIES_MINIOR_CORE_RED FORMS_START + 294 -#define SPECIES_MINIOR_CORE_ORANGE FORMS_START + 295 -#define SPECIES_MINIOR_CORE_YELLOW FORMS_START + 296 -#define SPECIES_MINIOR_CORE_GREEN FORMS_START + 297 -#define SPECIES_MINIOR_CORE_BLUE FORMS_START + 298 -#define SPECIES_MINIOR_CORE_INDIGO FORMS_START + 299 -#define SPECIES_MINIOR_CORE_VIOLET FORMS_START + 300 - -// Mimikyu -#define SPECIES_MIMIKYU_BUSTED FORMS_START + 301 - -// Necrozma -#define SPECIES_NECROZMA_DUSK_MANE FORMS_START + 302 -#define SPECIES_NECROZMA_DAWN_WINGS FORMS_START + 303 -#define SPECIES_NECROZMA_ULTRA FORMS_START + 304 - -// Magearna -#define SPECIES_MAGEARNA_ORIGINAL_COLOR FORMS_START + 305 - -// Cramorant -#define SPECIES_CRAMORANT_GULPING FORMS_START + 306 -#define SPECIES_CRAMORANT_GORGING FORMS_START + 307 - -// Toxtricity -#define SPECIES_TOXTRICITY_LOW_KEY FORMS_START + 308 - -// Sinistea -#define SPECIES_SINISTEA_ANTIQUE FORMS_START + 309 - -// Polteageist -#define SPECIES_POLTEAGEIST_ANTIQUE FORMS_START + 310 - -// Alcremie +#define SPECIES_MINIOR_CORE_RED 1199 +#define SPECIES_MINIOR_CORE_ORANGE 1200 +#define SPECIES_MINIOR_CORE_YELLOW 1201 +#define SPECIES_MINIOR_CORE_GREEN 1202 +#define SPECIES_MINIOR_CORE_BLUE 1203 +#define SPECIES_MINIOR_CORE_INDIGO 1204 +#define SPECIES_MINIOR_CORE_VIOLET 1205 +#define SPECIES_MIMIKYU_BUSTED 1206 +#define SPECIES_NECROZMA_DUSK_MANE 1207 +#define SPECIES_NECROZMA_DAWN_WINGS 1208 +#define SPECIES_NECROZMA_ULTRA 1209 +#define SPECIES_MAGEARNA_ORIGINAL_COLOR 1210 +#define SPECIES_CRAMORANT_GULPING 1211 +#define SPECIES_CRAMORANT_GORGING 1212 +#define SPECIES_TOXTRICITY_LOW_KEY 1213 +#define SPECIES_SINISTEA_ANTIQUE 1214 +#define SPECIES_POLTEAGEIST_ANTIQUE 1215 #define SPECIES_ALCREMIE_RUBY_CREAM SPECIES_ALCREMIE_STRAWBERRY_RUBY_CREAM #define SPECIES_ALCREMIE_MATCHA_CREAM SPECIES_ALCREMIE_STRAWBERRY_MATCHA_CREAM #define SPECIES_ALCREMIE_MINT_CREAM SPECIES_ALCREMIE_STRAWBERRY_MINT_CREAM @@ -1404,375 +1295,343 @@ #define SPECIES_ALCREMIE_RUBY_SWIRL SPECIES_ALCREMIE_STRAWBERRY_RUBY_SWIRL #define SPECIES_ALCREMIE_CARAMEL_SWIRL SPECIES_ALCREMIE_STRAWBERRY_CARAMEL_SWIRL #define SPECIES_ALCREMIE_RAINBOW_SWIRL SPECIES_ALCREMIE_STRAWBERRY_RAINBOW_SWIRL -#define SPECIES_ALCREMIE_STRAWBERRY_RUBY_CREAM FORMS_START + 311 -#define SPECIES_ALCREMIE_STRAWBERRY_MATCHA_CREAM FORMS_START + 312 -#define SPECIES_ALCREMIE_STRAWBERRY_MINT_CREAM FORMS_START + 313 -#define SPECIES_ALCREMIE_STRAWBERRY_LEMON_CREAM FORMS_START + 314 -#define SPECIES_ALCREMIE_STRAWBERRY_SALTED_CREAM FORMS_START + 315 -#define SPECIES_ALCREMIE_STRAWBERRY_RUBY_SWIRL FORMS_START + 316 -#define SPECIES_ALCREMIE_STRAWBERRY_CARAMEL_SWIRL FORMS_START + 317 -#define SPECIES_ALCREMIE_STRAWBERRY_RAINBOW_SWIRL FORMS_START + 318 - -// Eiscue -#define SPECIES_EISCUE_NOICE_FACE FORMS_START + 319 - -// Indeedee -#define SPECIES_INDEEDEE_FEMALE FORMS_START + 320 - -// Morpeko -#define SPECIES_MORPEKO_HANGRY FORMS_START + 321 - -// Zacian -#define SPECIES_ZACIAN_CROWNED_SWORD FORMS_START + 322 - -// Zamazenta -#define SPECIES_ZAMAZENTA_CROWNED_SHIELD FORMS_START + 323 - -// Eternatus -#define SPECIES_ETERNATUS_ETERNAMAX FORMS_START + 324 - -// Urshifu -#define SPECIES_URSHIFU_RAPID_STRIKE_STYLE FORMS_START + 325 - -// Zarude -#define SPECIES_ZARUDE_DADA FORMS_START + 326 - -// Calyrex -#define SPECIES_CALYREX_ICE_RIDER FORMS_START + 327 -#define SPECIES_CALYREX_SHADOW_RIDER FORMS_START + 328 - -// Basculegion -#define SPECIES_BASCULEGION_FEMALE FORMS_START + 329 - -// More Alcremie +#define SPECIES_ALCREMIE_STRAWBERRY_RUBY_CREAM 1216 +#define SPECIES_ALCREMIE_STRAWBERRY_MATCHA_CREAM 1217 +#define SPECIES_ALCREMIE_STRAWBERRY_MINT_CREAM 1218 +#define SPECIES_ALCREMIE_STRAWBERRY_LEMON_CREAM 1219 +#define SPECIES_ALCREMIE_STRAWBERRY_SALTED_CREAM 1220 +#define SPECIES_ALCREMIE_STRAWBERRY_RUBY_SWIRL 1221 +#define SPECIES_ALCREMIE_STRAWBERRY_CARAMEL_SWIRL 1222 +#define SPECIES_ALCREMIE_STRAWBERRY_RAINBOW_SWIRL 1223 +#define SPECIES_EISCUE_NOICE_FACE 1224 +#define SPECIES_INDEEDEE_FEMALE 1225 +#define SPECIES_MORPEKO_HANGRY 1226 +#define SPECIES_ZACIAN_CROWNED_SWORD 1227 +#define SPECIES_ZAMAZENTA_CROWNED_SHIELD 1228 +#define SPECIES_ETERNATUS_ETERNAMAX 1229 +#define SPECIES_URSHIFU_RAPID_STRIKE_STYLE 1230 +#define SPECIES_ZARUDE_DADA 1231 +#define SPECIES_CALYREX_ICE_RIDER 1232 +#define SPECIES_CALYREX_SHADOW_RIDER 1233 +#define SPECIES_BASCULEGION_FEMALE 1234 #define SPECIES_ALCREMIE_BERRY SPECIES_ALCREMIE_BERRY_VANILLA_CREAM -#define SPECIES_ALCREMIE_BERRY_VANILLA_CREAM FORMS_START + 330 -#define SPECIES_ALCREMIE_BERRY_RUBY_CREAM FORMS_START + 331 -#define SPECIES_ALCREMIE_BERRY_MATCHA_CREAM FORMS_START + 332 -#define SPECIES_ALCREMIE_BERRY_MINT_CREAM FORMS_START + 333 -#define SPECIES_ALCREMIE_BERRY_LEMON_CREAM FORMS_START + 334 -#define SPECIES_ALCREMIE_BERRY_SALTED_CREAM FORMS_START + 335 -#define SPECIES_ALCREMIE_BERRY_RUBY_SWIRL FORMS_START + 336 -#define SPECIES_ALCREMIE_BERRY_CARAMEL_SWIRL FORMS_START + 337 -#define SPECIES_ALCREMIE_BERRY_RAINBOW_SWIRL FORMS_START + 338 +#define SPECIES_ALCREMIE_BERRY_VANILLA_CREAM 1235 +#define SPECIES_ALCREMIE_BERRY_RUBY_CREAM 1236 +#define SPECIES_ALCREMIE_BERRY_MATCHA_CREAM 1237 +#define SPECIES_ALCREMIE_BERRY_MINT_CREAM 1238 +#define SPECIES_ALCREMIE_BERRY_LEMON_CREAM 1239 +#define SPECIES_ALCREMIE_BERRY_SALTED_CREAM 1240 +#define SPECIES_ALCREMIE_BERRY_RUBY_SWIRL 1241 +#define SPECIES_ALCREMIE_BERRY_CARAMEL_SWIRL 1242 +#define SPECIES_ALCREMIE_BERRY_RAINBOW_SWIRL 1243 #define SPECIES_ALCREMIE_LOVE SPECIES_ALCREMIE_LOVE_VANILLA_CREAM -#define SPECIES_ALCREMIE_LOVE_VANILLA_CREAM FORMS_START + 339 -#define SPECIES_ALCREMIE_LOVE_RUBY_CREAM FORMS_START + 340 -#define SPECIES_ALCREMIE_LOVE_MATCHA_CREAM FORMS_START + 341 -#define SPECIES_ALCREMIE_LOVE_MINT_CREAM FORMS_START + 342 -#define SPECIES_ALCREMIE_LOVE_LEMON_CREAM FORMS_START + 343 -#define SPECIES_ALCREMIE_LOVE_SALTED_CREAM FORMS_START + 344 -#define SPECIES_ALCREMIE_LOVE_RUBY_SWIRL FORMS_START + 345 -#define SPECIES_ALCREMIE_LOVE_CARAMEL_SWIRL FORMS_START + 346 -#define SPECIES_ALCREMIE_LOVE_RAINBOW_SWIRL FORMS_START + 347 +#define SPECIES_ALCREMIE_LOVE_VANILLA_CREAM 1244 +#define SPECIES_ALCREMIE_LOVE_RUBY_CREAM 1245 +#define SPECIES_ALCREMIE_LOVE_MATCHA_CREAM 1246 +#define SPECIES_ALCREMIE_LOVE_MINT_CREAM 1247 +#define SPECIES_ALCREMIE_LOVE_LEMON_CREAM 1248 +#define SPECIES_ALCREMIE_LOVE_SALTED_CREAM 1249 +#define SPECIES_ALCREMIE_LOVE_RUBY_SWIRL 1250 +#define SPECIES_ALCREMIE_LOVE_CARAMEL_SWIRL 1251 +#define SPECIES_ALCREMIE_LOVE_RAINBOW_SWIRL 1252 #define SPECIES_ALCREMIE_STAR SPECIES_ALCREMIE_STAR_VANILLA_CREAM -#define SPECIES_ALCREMIE_STAR_VANILLA_CREAM FORMS_START + 348 -#define SPECIES_ALCREMIE_STAR_RUBY_CREAM FORMS_START + 349 -#define SPECIES_ALCREMIE_STAR_MATCHA_CREAM FORMS_START + 350 -#define SPECIES_ALCREMIE_STAR_MINT_CREAM FORMS_START + 351 -#define SPECIES_ALCREMIE_STAR_LEMON_CREAM FORMS_START + 352 -#define SPECIES_ALCREMIE_STAR_SALTED_CREAM FORMS_START + 353 -#define SPECIES_ALCREMIE_STAR_RUBY_SWIRL FORMS_START + 354 -#define SPECIES_ALCREMIE_STAR_CARAMEL_SWIRL FORMS_START + 355 -#define SPECIES_ALCREMIE_STAR_RAINBOW_SWIRL FORMS_START + 356 +#define SPECIES_ALCREMIE_STAR_VANILLA_CREAM 1253 +#define SPECIES_ALCREMIE_STAR_RUBY_CREAM 1254 +#define SPECIES_ALCREMIE_STAR_MATCHA_CREAM 1255 +#define SPECIES_ALCREMIE_STAR_MINT_CREAM 1256 +#define SPECIES_ALCREMIE_STAR_LEMON_CREAM 1257 +#define SPECIES_ALCREMIE_STAR_SALTED_CREAM 1258 +#define SPECIES_ALCREMIE_STAR_RUBY_SWIRL 1259 +#define SPECIES_ALCREMIE_STAR_CARAMEL_SWIRL 1260 +#define SPECIES_ALCREMIE_STAR_RAINBOW_SWIRL 1261 #define SPECIES_ALCREMIE_CLOVER SPECIES_ALCREMIE_CLOVER_VANILLA_CREAM -#define SPECIES_ALCREMIE_CLOVER_VANILLA_CREAM FORMS_START + 357 -#define SPECIES_ALCREMIE_CLOVER_RUBY_CREAM FORMS_START + 358 -#define SPECIES_ALCREMIE_CLOVER_MATCHA_CREAM FORMS_START + 359 -#define SPECIES_ALCREMIE_CLOVER_MINT_CREAM FORMS_START + 360 -#define SPECIES_ALCREMIE_CLOVER_LEMON_CREAM FORMS_START + 361 -#define SPECIES_ALCREMIE_CLOVER_SALTED_CREAM FORMS_START + 362 -#define SPECIES_ALCREMIE_CLOVER_RUBY_SWIRL FORMS_START + 363 -#define SPECIES_ALCREMIE_CLOVER_CARAMEL_SWIRL FORMS_START + 364 -#define SPECIES_ALCREMIE_CLOVER_RAINBOW_SWIRL FORMS_START + 365 +#define SPECIES_ALCREMIE_CLOVER_VANILLA_CREAM 1262 +#define SPECIES_ALCREMIE_CLOVER_RUBY_CREAM 1263 +#define SPECIES_ALCREMIE_CLOVER_MATCHA_CREAM 1264 +#define SPECIES_ALCREMIE_CLOVER_MINT_CREAM 1265 +#define SPECIES_ALCREMIE_CLOVER_LEMON_CREAM 1266 +#define SPECIES_ALCREMIE_CLOVER_SALTED_CREAM 1267 +#define SPECIES_ALCREMIE_CLOVER_RUBY_SWIRL 1268 +#define SPECIES_ALCREMIE_CLOVER_CARAMEL_SWIRL 1269 +#define SPECIES_ALCREMIE_CLOVER_RAINBOW_SWIRL 1270 #define SPECIES_ALCREMIE_FLOWER SPECIES_ALCREMIE_FLOWER_VANILLA_CREAM -#define SPECIES_ALCREMIE_FLOWER_VANILLA_CREAM FORMS_START + 366 -#define SPECIES_ALCREMIE_FLOWER_RUBY_CREAM FORMS_START + 367 -#define SPECIES_ALCREMIE_FLOWER_MATCHA_CREAM FORMS_START + 368 -#define SPECIES_ALCREMIE_FLOWER_MINT_CREAM FORMS_START + 369 -#define SPECIES_ALCREMIE_FLOWER_LEMON_CREAM FORMS_START + 370 -#define SPECIES_ALCREMIE_FLOWER_SALTED_CREAM FORMS_START + 371 -#define SPECIES_ALCREMIE_FLOWER_RUBY_SWIRL FORMS_START + 372 -#define SPECIES_ALCREMIE_FLOWER_CARAMEL_SWIRL FORMS_START + 373 -#define SPECIES_ALCREMIE_FLOWER_RAINBOW_SWIRL FORMS_START + 374 +#define SPECIES_ALCREMIE_FLOWER_VANILLA_CREAM 1271 +#define SPECIES_ALCREMIE_FLOWER_RUBY_CREAM 1272 +#define SPECIES_ALCREMIE_FLOWER_MATCHA_CREAM 1273 +#define SPECIES_ALCREMIE_FLOWER_MINT_CREAM 1274 +#define SPECIES_ALCREMIE_FLOWER_LEMON_CREAM 1275 +#define SPECIES_ALCREMIE_FLOWER_SALTED_CREAM 1276 +#define SPECIES_ALCREMIE_FLOWER_RUBY_SWIRL 1277 +#define SPECIES_ALCREMIE_FLOWER_CARAMEL_SWIRL 1278 +#define SPECIES_ALCREMIE_FLOWER_RAINBOW_SWIRL 1279 #define SPECIES_ALCREMIE_RIBBON SPECIES_ALCREMIE_RIBBON_VANILLA_CREAM -#define SPECIES_ALCREMIE_RIBBON_VANILLA_CREAM FORMS_START + 375 -#define SPECIES_ALCREMIE_RIBBON_RUBY_CREAM FORMS_START + 376 -#define SPECIES_ALCREMIE_RIBBON_MATCHA_CREAM FORMS_START + 377 -#define SPECIES_ALCREMIE_RIBBON_MINT_CREAM FORMS_START + 378 -#define SPECIES_ALCREMIE_RIBBON_LEMON_CREAM FORMS_START + 379 -#define SPECIES_ALCREMIE_RIBBON_SALTED_CREAM FORMS_START + 380 -#define SPECIES_ALCREMIE_RIBBON_RUBY_SWIRL FORMS_START + 381 -#define SPECIES_ALCREMIE_RIBBON_CARAMEL_SWIRL FORMS_START + 382 -#define SPECIES_ALCREMIE_RIBBON_RAINBOW_SWIRL FORMS_START + 383 +#define SPECIES_ALCREMIE_RIBBON_VANILLA_CREAM 1280 +#define SPECIES_ALCREMIE_RIBBON_RUBY_CREAM 1281 +#define SPECIES_ALCREMIE_RIBBON_MATCHA_CREAM 1282 +#define SPECIES_ALCREMIE_RIBBON_MINT_CREAM 1283 +#define SPECIES_ALCREMIE_RIBBON_LEMON_CREAM 1284 +#define SPECIES_ALCREMIE_RIBBON_SALTED_CREAM 1285 +#define SPECIES_ALCREMIE_RIBBON_RUBY_SWIRL 1286 +#define SPECIES_ALCREMIE_RIBBON_CARAMEL_SWIRL 1287 +#define SPECIES_ALCREMIE_RIBBON_RAINBOW_SWIRL 1288 #define GEN9_START SPECIES_ALCREMIE_RIBBON_RAINBOW_SWIRL -#define SPECIES_SPRIGATITO GEN9_START + 1 -#define SPECIES_FLORAGATO GEN9_START + 2 -#define SPECIES_MEOWSCARADA GEN9_START + 3 -#define SPECIES_FUECOCO GEN9_START + 4 -#define SPECIES_CROCALOR GEN9_START + 5 -#define SPECIES_SKELEDIRGE GEN9_START + 6 -#define SPECIES_QUAXLY GEN9_START + 7 -#define SPECIES_QUAXWELL GEN9_START + 8 -#define SPECIES_QUAQUAVAL GEN9_START + 9 -#define SPECIES_LECHONK GEN9_START + 10 +#define SPECIES_SPRIGATITO 1289 +#define SPECIES_FLORAGATO 1290 +#define SPECIES_MEOWSCARADA 1291 +#define SPECIES_FUECOCO 1292 +#define SPECIES_CROCALOR 1293 +#define SPECIES_SKELEDIRGE 1294 +#define SPECIES_QUAXLY 1295 +#define SPECIES_QUAXWELL 1296 +#define SPECIES_QUAQUAVAL 1297 +#define SPECIES_LECHONK 1298 #define SPECIES_OINKOLOGNE SPECIES_OINKOLOGNE_MALE -#define SPECIES_OINKOLOGNE_MALE GEN9_START + 11 -#define SPECIES_OINKOLOGNE_FEMALE GEN9_START + 12 -#define SPECIES_TAROUNTULA GEN9_START + 13 -#define SPECIES_SPIDOPS GEN9_START + 14 -#define SPECIES_NYMBLE GEN9_START + 15 -#define SPECIES_LOKIX GEN9_START + 16 -#define SPECIES_PAWMI GEN9_START + 17 -#define SPECIES_PAWMO GEN9_START + 18 -#define SPECIES_PAWMOT GEN9_START + 19 -#define SPECIES_TANDEMAUS GEN9_START + 20 +#define SPECIES_OINKOLOGNE_MALE 1299 +#define SPECIES_OINKOLOGNE_FEMALE 1300 +#define SPECIES_TAROUNTULA 1301 +#define SPECIES_SPIDOPS 1302 +#define SPECIES_NYMBLE 1303 +#define SPECIES_LOKIX 1304 +#define SPECIES_PAWMI 1305 +#define SPECIES_PAWMO 1306 +#define SPECIES_PAWMOT 1307 +#define SPECIES_TANDEMAUS 1308 #define SPECIES_MAUSHOLD SPECIES_MAUSHOLD_FAMILY_OF_THREE -#define SPECIES_MAUSHOLD_FAMILY_OF_THREE GEN9_START + 21 -#define SPECIES_MAUSHOLD_FAMILY_OF_FOUR GEN9_START + 22 -#define SPECIES_FIDOUGH GEN9_START + 23 -#define SPECIES_DACHSBUN GEN9_START + 24 -#define SPECIES_SMOLIV GEN9_START + 25 -#define SPECIES_DOLLIV GEN9_START + 26 -#define SPECIES_ARBOLIVA GEN9_START + 27 +#define SPECIES_MAUSHOLD_FAMILY_OF_THREE 1309 +#define SPECIES_MAUSHOLD_FAMILY_OF_FOUR 1310 +#define SPECIES_FIDOUGH 1311 +#define SPECIES_DACHSBUN 1312 +#define SPECIES_SMOLIV 1313 +#define SPECIES_DOLLIV 1314 +#define SPECIES_ARBOLIVA 1315 #define SPECIES_SQUAWKABILLY SPECIES_SQUAWKABILLY_GREEN_PLUMAGE -#define SPECIES_SQUAWKABILLY_GREEN_PLUMAGE GEN9_START + 28 -#define SPECIES_SQUAWKABILLY_BLUE_PLUMAGE GEN9_START + 29 -#define SPECIES_SQUAWKABILLY_YELLOW_PLUMAGE GEN9_START + 30 -#define SPECIES_SQUAWKABILLY_WHITE_PLUMAGE GEN9_START + 31 -#define SPECIES_NACLI GEN9_START + 32 -#define SPECIES_NACLSTACK GEN9_START + 33 -#define SPECIES_GARGANACL GEN9_START + 34 -#define SPECIES_CHARCADET GEN9_START + 35 -#define SPECIES_ARMAROUGE GEN9_START + 36 -#define SPECIES_CERULEDGE GEN9_START + 37 -#define SPECIES_TADBULB GEN9_START + 38 -#define SPECIES_BELLIBOLT GEN9_START + 39 -#define SPECIES_WATTREL GEN9_START + 40 -#define SPECIES_KILOWATTREL GEN9_START + 41 -#define SPECIES_MASCHIFF GEN9_START + 42 -#define SPECIES_MABOSSTIFF GEN9_START + 43 -#define SPECIES_SHROODLE GEN9_START + 44 -#define SPECIES_GRAFAIAI GEN9_START + 45 -#define SPECIES_BRAMBLIN GEN9_START + 46 -#define SPECIES_BRAMBLEGHAST GEN9_START + 47 -#define SPECIES_TOEDSCOOL GEN9_START + 48 -#define SPECIES_TOEDSCRUEL GEN9_START + 49 -#define SPECIES_KLAWF GEN9_START + 50 -#define SPECIES_CAPSAKID GEN9_START + 51 -#define SPECIES_SCOVILLAIN GEN9_START + 52 -#define SPECIES_RELLOR GEN9_START + 53 -#define SPECIES_RABSCA GEN9_START + 54 -#define SPECIES_FLITTLE GEN9_START + 55 -#define SPECIES_ESPATHRA GEN9_START + 56 -#define SPECIES_TINKATINK GEN9_START + 57 -#define SPECIES_TINKATUFF GEN9_START + 58 -#define SPECIES_TINKATON GEN9_START + 59 -#define SPECIES_WIGLETT GEN9_START + 60 -#define SPECIES_WUGTRIO GEN9_START + 61 -#define SPECIES_BOMBIRDIER GEN9_START + 62 -#define SPECIES_FINIZEN GEN9_START + 63 +#define SPECIES_SQUAWKABILLY_GREEN_PLUMAGE 1316 +#define SPECIES_SQUAWKABILLY_BLUE_PLUMAGE 1317 +#define SPECIES_SQUAWKABILLY_YELLOW_PLUMAGE 1318 +#define SPECIES_SQUAWKABILLY_WHITE_PLUMAGE 1319 +#define SPECIES_NACLI 1320 +#define SPECIES_NACLSTACK 1321 +#define SPECIES_GARGANACL 1322 +#define SPECIES_CHARCADET 1323 +#define SPECIES_ARMAROUGE 1324 +#define SPECIES_CERULEDGE 1325 +#define SPECIES_TADBULB 1326 +#define SPECIES_BELLIBOLT 1327 +#define SPECIES_WATTREL 1328 +#define SPECIES_KILOWATTREL 1329 +#define SPECIES_MASCHIFF 1330 +#define SPECIES_MABOSSTIFF 1331 +#define SPECIES_SHROODLE 1332 +#define SPECIES_GRAFAIAI 1333 +#define SPECIES_BRAMBLIN 1334 +#define SPECIES_BRAMBLEGHAST 1335 +#define SPECIES_TOEDSCOOL 1336 +#define SPECIES_TOEDSCRUEL 1337 +#define SPECIES_KLAWF 1338 +#define SPECIES_CAPSAKID 1339 +#define SPECIES_SCOVILLAIN 1340 +#define SPECIES_RELLOR 1341 +#define SPECIES_RABSCA 1342 +#define SPECIES_FLITTLE 1343 +#define SPECIES_ESPATHRA 1344 +#define SPECIES_TINKATINK 1345 +#define SPECIES_TINKATUFF 1346 +#define SPECIES_TINKATON 1347 +#define SPECIES_WIGLETT 1348 +#define SPECIES_WUGTRIO 1349 +#define SPECIES_BOMBIRDIER 1350 +#define SPECIES_FINIZEN 1351 #define SPECIES_PALAFIN SPECIES_PALAFIN_ZERO -#define SPECIES_PALAFIN_ZERO GEN9_START + 64 -#define SPECIES_PALAFIN_HERO GEN9_START + 65 -#define SPECIES_VAROOM GEN9_START + 66 -#define SPECIES_REVAVROOM GEN9_START + 67 -#define SPECIES_CYCLIZAR GEN9_START + 68 -#define SPECIES_ORTHWORM GEN9_START + 69 -#define SPECIES_GLIMMET GEN9_START + 70 -#define SPECIES_GLIMMORA GEN9_START + 71 -#define SPECIES_GREAVARD GEN9_START + 72 -#define SPECIES_HOUNDSTONE GEN9_START + 73 -#define SPECIES_FLAMIGO GEN9_START + 74 -#define SPECIES_CETODDLE GEN9_START + 75 -#define SPECIES_CETITAN GEN9_START + 76 -#define SPECIES_VELUZA GEN9_START + 77 -#define SPECIES_DONDOZO GEN9_START + 78 +#define SPECIES_PALAFIN_ZERO 1352 +#define SPECIES_PALAFIN_HERO 1353 +#define SPECIES_VAROOM 1354 +#define SPECIES_REVAVROOM 1355 +#define SPECIES_CYCLIZAR 1356 +#define SPECIES_ORTHWORM 1357 +#define SPECIES_GLIMMET 1358 +#define SPECIES_GLIMMORA 1359 +#define SPECIES_GREAVARD 1360 +#define SPECIES_HOUNDSTONE 1361 +#define SPECIES_FLAMIGO 1362 +#define SPECIES_CETODDLE 1363 +#define SPECIES_CETITAN 1364 +#define SPECIES_VELUZA 1365 +#define SPECIES_DONDOZO 1366 #define SPECIES_TATSUGIRI SPECIES_TATSUGIRI_CURLY -#define SPECIES_TATSUGIRI_CURLY GEN9_START + 79 -#define SPECIES_TATSUGIRI_DROOPY GEN9_START + 80 -#define SPECIES_TATSUGIRI_STRETCHY GEN9_START + 81 -#define SPECIES_ANNIHILAPE GEN9_START + 82 -#define SPECIES_CLODSIRE GEN9_START + 83 -#define SPECIES_FARIGIRAF GEN9_START + 84 +#define SPECIES_TATSUGIRI_CURLY 1367 +#define SPECIES_TATSUGIRI_DROOPY 1368 +#define SPECIES_TATSUGIRI_STRETCHY 1369 +#define SPECIES_ANNIHILAPE 1370 +#define SPECIES_CLODSIRE 1371 +#define SPECIES_FARIGIRAF 1372 #define SPECIES_DUDUNSPARCE SPECIES_DUDUNSPARCE_TWO_SEGMENT -#define SPECIES_DUDUNSPARCE_TWO_SEGMENT GEN9_START + 85 -#define SPECIES_DUDUNSPARCE_THREE_SEGMENT GEN9_START + 86 -#define SPECIES_KINGAMBIT GEN9_START + 87 -#define SPECIES_GREAT_TUSK GEN9_START + 88 -#define SPECIES_SCREAM_TAIL GEN9_START + 89 -#define SPECIES_BRUTE_BONNET GEN9_START + 90 -#define SPECIES_FLUTTER_MANE GEN9_START + 91 -#define SPECIES_SLITHER_WING GEN9_START + 92 -#define SPECIES_SANDY_SHOCKS GEN9_START + 93 -#define SPECIES_IRON_TREADS GEN9_START + 94 -#define SPECIES_IRON_BUNDLE GEN9_START + 95 -#define SPECIES_IRON_HANDS GEN9_START + 96 -#define SPECIES_IRON_JUGULIS GEN9_START + 97 -#define SPECIES_IRON_MOTH GEN9_START + 98 -#define SPECIES_IRON_THORNS GEN9_START + 99 -#define SPECIES_FRIGIBAX GEN9_START + 100 -#define SPECIES_ARCTIBAX GEN9_START + 101 -#define SPECIES_BAXCALIBUR GEN9_START + 102 +#define SPECIES_DUDUNSPARCE_TWO_SEGMENT 1373 +#define SPECIES_DUDUNSPARCE_THREE_SEGMENT 1374 +#define SPECIES_KINGAMBIT 1375 +#define SPECIES_GREAT_TUSK 1376 +#define SPECIES_SCREAM_TAIL 1377 +#define SPECIES_BRUTE_BONNET 1378 +#define SPECIES_FLUTTER_MANE 1379 +#define SPECIES_SLITHER_WING 1380 +#define SPECIES_SANDY_SHOCKS 1381 +#define SPECIES_IRON_TREADS 1382 +#define SPECIES_IRON_BUNDLE 1383 +#define SPECIES_IRON_HANDS 1384 +#define SPECIES_IRON_JUGULIS 1385 +#define SPECIES_IRON_MOTH 1386 +#define SPECIES_IRON_THORNS 1387 +#define SPECIES_FRIGIBAX 1388 +#define SPECIES_ARCTIBAX 1389 +#define SPECIES_BAXCALIBUR 1390 #define SPECIES_GIMMIGHOUL SPECIES_GIMMIGHOUL_CHEST -#define SPECIES_GIMMIGHOUL_CHEST GEN9_START + 103 -#define SPECIES_GIMMIGHOUL_ROAMING GEN9_START + 104 -#define SPECIES_GHOLDENGO GEN9_START + 105 -#define SPECIES_WO_CHIEN GEN9_START + 106 -#define SPECIES_CHIEN_PAO GEN9_START + 107 -#define SPECIES_TING_LU GEN9_START + 108 -#define SPECIES_CHI_YU GEN9_START + 109 -#define SPECIES_ROARING_MOON GEN9_START + 110 -#define SPECIES_IRON_VALIANT GEN9_START + 111 -#define SPECIES_KORAIDON GEN9_START + 112 -#define SPECIES_MIRAIDON GEN9_START + 113 +#define SPECIES_GIMMIGHOUL_CHEST 1391 +#define SPECIES_GIMMIGHOUL_ROAMING 1392 +#define SPECIES_GHOLDENGO 1393 +#define SPECIES_WO_CHIEN 1394 +#define SPECIES_CHIEN_PAO 1395 +#define SPECIES_TING_LU 1396 +#define SPECIES_CHI_YU 1397 +#define SPECIES_ROARING_MOON 1398 +#define SPECIES_IRON_VALIANT 1399 +#define SPECIES_KORAIDON 1400 +#define SPECIES_MIRAIDON 1401 // Paldean Forms -#define SPECIES_TAUROS_PALDEAN_COMBAT_BREED GEN9_START + 114 -#define SPECIES_TAUROS_PALDEAN_BLAZE_BREED GEN9_START + 115 -#define SPECIES_TAUROS_PALDEAN_AQUA_BREED GEN9_START + 116 -#define SPECIES_WOOPER_PALDEAN GEN9_START + 117 +#define SPECIES_TAUROS_PALDEAN_COMBAT_BREED 1402 +#define SPECIES_TAUROS_PALDEAN_BLAZE_BREED 1403 +#define SPECIES_TAUROS_PALDEAN_AQUA_BREED 1404 +#define SPECIES_WOOPER_PALDEAN 1405 // Scarlet and Violet 1.2.0 -#define SPECIES_WALKING_WAKE GEN9_START + 118 -#define SPECIES_IRON_LEAVES GEN9_START + 119 +#define SPECIES_WALKING_WAKE 1406 +#define SPECIES_IRON_LEAVES 1407 // Teal Mask -#define SPECIES_DIPPLIN GEN9_START + 120 +#define SPECIES_DIPPLIN 1408 #define SPECIES_POLTCHAGEIST SPECIES_POLTCHAGEIST_COUNTERFEIT -#define SPECIES_POLTCHAGEIST_COUNTERFEIT GEN9_START + 121 -#define SPECIES_POLTCHAGEIST_ARTISAN GEN9_START + 122 +#define SPECIES_POLTCHAGEIST_COUNTERFEIT 1409 +#define SPECIES_POLTCHAGEIST_ARTISAN 1410 #define SPECIES_SINISTCHA SPECIES_SINISTCHA_UNREMARKABLE -#define SPECIES_SINISTCHA_UNREMARKABLE GEN9_START + 123 -#define SPECIES_SINISTCHA_MASTERPIECE GEN9_START + 124 -#define SPECIES_OKIDOGI GEN9_START + 125 -#define SPECIES_MUNKIDORI GEN9_START + 126 -#define SPECIES_FEZANDIPITI GEN9_START + 127 +#define SPECIES_SINISTCHA_UNREMARKABLE 1411 +#define SPECIES_SINISTCHA_MASTERPIECE 1412 +#define SPECIES_OKIDOGI 1413 +#define SPECIES_MUNKIDORI 1414 +#define SPECIES_FEZANDIPITI 1415 #define SPECIES_OGERPON SPECIES_OGERPON_TEAL_MASK -#define SPECIES_OGERPON_TEAL_MASK GEN9_START + 128 -#define SPECIES_OGERPON_WELLSPRING_MASK GEN9_START + 129 -#define SPECIES_OGERPON_HEARTHFLAME_MASK GEN9_START + 130 -#define SPECIES_OGERPON_CORNERSTONE_MASK GEN9_START + 131 -#define SPECIES_OGERPON_TEAL_MASK_TERA GEN9_START + 132 -#define SPECIES_OGERPON_WELLSPRING_MASK_TERA GEN9_START + 133 -#define SPECIES_OGERPON_HEARTHFLAME_MASK_TERA GEN9_START + 134 -#define SPECIES_OGERPON_CORNERSTONE_MASK_TERA GEN9_START + 135 -#define SPECIES_URSALUNA_BLOODMOON GEN9_START + 136 +#define SPECIES_OGERPON_TEAL_MASK 1416 +#define SPECIES_OGERPON_WELLSPRING_MASK 1417 +#define SPECIES_OGERPON_HEARTHFLAME_MASK 1418 +#define SPECIES_OGERPON_CORNERSTONE_MASK 1419 +#define SPECIES_OGERPON_TEAL_MASK_TERA 1420 +#define SPECIES_OGERPON_WELLSPRING_MASK_TERA 1421 +#define SPECIES_OGERPON_HEARTHFLAME_MASK_TERA 1422 +#define SPECIES_OGERPON_CORNERSTONE_MASK_TERA 1423 +#define SPECIES_URSALUNA_BLOODMOON 1424 // Indigo Disk -#define SPECIES_1018 GEN9_START + 137 -#define SPECIES_1019 GEN9_START + 138 -#define SPECIES_1020 GEN9_START + 139 -#define SPECIES_1021 GEN9_START + 140 -#define SPECIES_1022 GEN9_START + 141 -#define SPECIES_1023 GEN9_START + 142 -#define SPECIES_1024 SPECIES_1024_FORM_1 -#define SPECIES_1024_FORM_1 GEN9_START + 143 -#define SPECIES_1024_FORM_2 GEN9_START + 144 -#define SPECIES_1024_FORM_3 GEN9_START + 145 -#define SPECIES_1025 GEN9_START + 146 +#define SPECIES_ARCHALUDON 1425 +#define SPECIES_HYDRAPPLE 1426 +#define SPECIES_GOUGING_FIRE 1427 +#define SPECIES_RAGING_BOLT 1428 +#define SPECIES_IRON_BOULDER 1429 +#define SPECIES_IRON_CROWN 1430 +#define SPECIES_TERAPAGOS SPECIES_TERAPAGOS_NORMAL +#define SPECIES_TERAPAGOS_NORMAL 1431 +#define SPECIES_TERAPAGOS_TERASTAL 1432 +#define SPECIES_TERAPAGOS_STELLAR 1433 +#define SPECIES_PECHARUNT 1434 +#define SPECIES_LUGIA_SHADOW 1435 +#define SPECIES_MOTHIM_SANDY_CLOAK 1436 +#define SPECIES_MOTHIM_TRASH_CLOAK 1437 +#define SPECIES_SCATTERBUG_POLAR 1438 +#define SPECIES_SCATTERBUG_TUNDRA 1439 +#define SPECIES_SCATTERBUG_CONTINENTAL 1440 +#define SPECIES_SCATTERBUG_GARDEN 1441 +#define SPECIES_SCATTERBUG_ELEGANT 1442 +#define SPECIES_SCATTERBUG_MEADOW 1443 +#define SPECIES_SCATTERBUG_MODERN 1444 +#define SPECIES_SCATTERBUG_MARINE 1445 +#define SPECIES_SCATTERBUG_ARCHIPELAGO 1446 +#define SPECIES_SCATTERBUG_HIGH_PLAINS 1447 +#define SPECIES_SCATTERBUG_SANDSTORM 1448 +#define SPECIES_SCATTERBUG_RIVER 1449 +#define SPECIES_SCATTERBUG_MONSOON 1450 +#define SPECIES_SCATTERBUG_SAVANNA 1451 +#define SPECIES_SCATTERBUG_SUN 1452 +#define SPECIES_SCATTERBUG_OCEAN 1453 +#define SPECIES_SCATTERBUG_JUNGLE 1454 +#define SPECIES_SCATTERBUG_FANCY 1455 +#define SPECIES_SCATTERBUG_POKE_BALL 1456 +#define SPECIES_SPEWPA_POLAR 1457 +#define SPECIES_SPEWPA_TUNDRA 1458 +#define SPECIES_SPEWPA_CONTINENTAL 1459 +#define SPECIES_SPEWPA_GARDEN 1460 +#define SPECIES_SPEWPA_ELEGANT 1461 +#define SPECIES_SPEWPA_MEADOW 1462 +#define SPECIES_SPEWPA_MODERN 1463 +#define SPECIES_SPEWPA_MARINE 1464 +#define SPECIES_SPEWPA_ARCHIPELAGO 1465 +#define SPECIES_SPEWPA_HIGH_PLAINS 1466 +#define SPECIES_SPEWPA_SANDSTORM 1467 +#define SPECIES_SPEWPA_RIVER 1468 +#define SPECIES_SPEWPA_MONSOON 1469 +#define SPECIES_SPEWPA_SAVANNA 1470 +#define SPECIES_SPEWPA_SUN 1471 +#define SPECIES_SPEWPA_OCEAN 1472 +#define SPECIES_SPEWPA_JUNGLE 1473 +#define SPECIES_SPEWPA_FANCY 1474 +#define SPECIES_SPEWPA_POKE_BALL 1475 +#define SPECIES_RATICATE_ALOLAN_TOTEM 1476 +#define SPECIES_GUMSHOOS_TOTEM 1477 +#define SPECIES_VIKAVOLT_TOTEM 1478 +#define SPECIES_LURANTIS_TOTEM 1479 +#define SPECIES_SALAZZLE_TOTEM 1480 +#define SPECIES_MIMIKYU_TOTEM SPECIES_MIMIKYU_TOTEM_DISGUISED +#define SPECIES_MIMIKYU_TOTEM_DISGUISED 1481 +#define SPECIES_KOMMO_O_TOTEM 1482 +#define SPECIES_MAROWAK_ALOLAN_TOTEM 1483 +#define SPECIES_RIBOMBEE_TOTEM 1484 +#define SPECIES_ARAQUANID_TOTEM 1485 +#define SPECIES_TOGEDEMARU_TOTEM 1486 +#define SPECIES_PIKACHU_PARTNER 1487 +#define SPECIES_EEVEE_PARTNER 1488 +#define SPECIES_VENUSAUR_GIGANTAMAX 1489 +#define SPECIES_BLASTOISE_GIGANTAMAX 1490 +#define SPECIES_CHARIZARD_GIGANTAMAX 1491 +#define SPECIES_BUTTERFREE_GIGANTAMAX 1492 +#define SPECIES_PIKACHU_GIGANTAMAX 1493 +#define SPECIES_MEOWTH_GIGANTAMAX 1494 +#define SPECIES_MACHAMP_GIGANTAMAX 1495 +#define SPECIES_GENGAR_GIGANTAMAX 1496 +#define SPECIES_KINGLER_GIGANTAMAX 1497 +#define SPECIES_LAPRAS_GIGANTAMAX 1498 +#define SPECIES_EEVEE_GIGANTAMAX 1499 +#define SPECIES_SNORLAX_GIGANTAMAX 1500 +#define SPECIES_GARBODOR_GIGANTAMAX 1501 +#define SPECIES_MELMETAL_GIGANTAMAX 1502 +#define SPECIES_RILLABOOM_GIGANTAMAX 1503 +#define SPECIES_CINDERACE_GIGANTAMAX 1504 +#define SPECIES_INTELEON_GIGANTAMAX 1505 +#define SPECIES_CORVIKNIGHT_GIGANTAMAX 1506 +#define SPECIES_ORBEETLE_GIGANTAMAX 1507 +#define SPECIES_DREDNAW_GIGANTAMAX 1508 +#define SPECIES_COALOSSAL_GIGANTAMAX 1509 +#define SPECIES_FLAPPLE_GIGANTAMAX 1510 +#define SPECIES_APPLETUN_GIGANTAMAX 1511 +#define SPECIES_SANDACONDA_GIGANTAMAX 1512 +#define SPECIES_TOXTRICITY_AMPED_GIGANTAMAX 1513 +#define SPECIES_TOXTRICITY_LOW_KEY_GIGANTAMAX 1514 +#define SPECIES_CENTISKORCH_GIGANTAMAX 1515 +#define SPECIES_HATTERENE_GIGANTAMAX 1516 +#define SPECIES_GRIMMSNARL_GIGANTAMAX 1517 +#define SPECIES_ALCREMIE_GIGANTAMAX 1518 +#define SPECIES_COPPERAJAH_GIGANTAMAX 1519 +#define SPECIES_DURALUDON_GIGANTAMAX 1520 +#define SPECIES_URSHIFU_SINGLE_STRIKE_STYLE_GIGANTAMAX 1521 +#define SPECIES_URSHIFU_RAPID_STRIKE_STYLE_GIGANTAMAX 1522 +#define SPECIES_MIMIKYU_TOTEM_BUSTED 1523 -#define PLACEHOLDER_START SPECIES_1025 -// XD: Gale of Darkness -#define SPECIES_LUGIA_SHADOW PLACEHOLDER_START + 1 -// Diamond & Pearl -#define SPECIES_MOTHIM_SANDY_CLOAK PLACEHOLDER_START + 2 -#define SPECIES_MOTHIM_TRASH_CLOAK PLACEHOLDER_START + 3 -// X & Y -#define SPECIES_SCATTERBUG_POLAR PLACEHOLDER_START + 4 -#define SPECIES_SCATTERBUG_TUNDRA PLACEHOLDER_START + 5 -#define SPECIES_SCATTERBUG_CONTINENTAL PLACEHOLDER_START + 6 -#define SPECIES_SCATTERBUG_GARDEN PLACEHOLDER_START + 7 -#define SPECIES_SCATTERBUG_ELEGANT PLACEHOLDER_START + 8 -#define SPECIES_SCATTERBUG_MEADOW PLACEHOLDER_START + 9 -#define SPECIES_SCATTERBUG_MODERN PLACEHOLDER_START + 10 -#define SPECIES_SCATTERBUG_MARINE PLACEHOLDER_START + 11 -#define SPECIES_SCATTERBUG_ARCHIPELAGO PLACEHOLDER_START + 12 -#define SPECIES_SCATTERBUG_HIGH_PLAINS PLACEHOLDER_START + 13 -#define SPECIES_SCATTERBUG_SANDSTORM PLACEHOLDER_START + 14 -#define SPECIES_SCATTERBUG_RIVER PLACEHOLDER_START + 15 -#define SPECIES_SCATTERBUG_MONSOON PLACEHOLDER_START + 16 -#define SPECIES_SCATTERBUG_SAVANNA PLACEHOLDER_START + 17 -#define SPECIES_SCATTERBUG_SUN PLACEHOLDER_START + 18 -#define SPECIES_SCATTERBUG_OCEAN PLACEHOLDER_START + 19 -#define SPECIES_SCATTERBUG_JUNGLE PLACEHOLDER_START + 20 -#define SPECIES_SCATTERBUG_FANCY PLACEHOLDER_START + 21 -#define SPECIES_SCATTERBUG_POKE_BALL PLACEHOLDER_START + 22 -#define SPECIES_SPEWPA_POLAR PLACEHOLDER_START + 23 -#define SPECIES_SPEWPA_TUNDRA PLACEHOLDER_START + 24 -#define SPECIES_SPEWPA_CONTINENTAL PLACEHOLDER_START + 25 -#define SPECIES_SPEWPA_GARDEN PLACEHOLDER_START + 26 -#define SPECIES_SPEWPA_ELEGANT PLACEHOLDER_START + 27 -#define SPECIES_SPEWPA_MEADOW PLACEHOLDER_START + 28 -#define SPECIES_SPEWPA_MODERN PLACEHOLDER_START + 29 -#define SPECIES_SPEWPA_MARINE PLACEHOLDER_START + 30 -#define SPECIES_SPEWPA_ARCHIPELAGO PLACEHOLDER_START + 31 -#define SPECIES_SPEWPA_HIGH_PLAINS PLACEHOLDER_START + 32 -#define SPECIES_SPEWPA_SANDSTORM PLACEHOLDER_START + 33 -#define SPECIES_SPEWPA_RIVER PLACEHOLDER_START + 34 -#define SPECIES_SPEWPA_MONSOON PLACEHOLDER_START + 35 -#define SPECIES_SPEWPA_SAVANNA PLACEHOLDER_START + 36 -#define SPECIES_SPEWPA_SUN PLACEHOLDER_START + 37 -#define SPECIES_SPEWPA_OCEAN PLACEHOLDER_START + 38 -#define SPECIES_SPEWPA_JUNGLE PLACEHOLDER_START + 39 -#define SPECIES_SPEWPA_FANCY PLACEHOLDER_START + 40 -#define SPECIES_SPEWPA_POKE_BALL PLACEHOLDER_START + 41 -// Sun & Moon -#define SPECIES_RATICATE_ALOLAN_TOTEM PLACEHOLDER_START + 42 -#define SPECIES_GUMSHOOS_TOTEM PLACEHOLDER_START + 43 -#define SPECIES_VIKAVOLT_TOTEM PLACEHOLDER_START + 44 -#define SPECIES_LURANTIS_TOTEM PLACEHOLDER_START + 45 -#define SPECIES_SALAZZLE_TOTEM PLACEHOLDER_START + 46 -#define SPECIES_MIMIKYU_TOTEM PLACEHOLDER_START + 47 -#define SPECIES_KOMMO_O_TOTEM PLACEHOLDER_START + 48 -// Ultra Sun & Ultra Moon -#define SPECIES_MAROWAK_ALOLAN_TOTEM PLACEHOLDER_START + 49 -#define SPECIES_RIBOMBEE_TOTEM PLACEHOLDER_START + 50 -#define SPECIES_ARAQUANID_TOTEM PLACEHOLDER_START + 51 -#define SPECIES_TOGEDEMARU_TOTEM PLACEHOLDER_START + 52 -// Let's Go Pikachu & Let's Go Eevee -#define SPECIES_PIKACHU_PARTNER PLACEHOLDER_START + 53 -#define SPECIES_EEVEE_PARTNER PLACEHOLDER_START + 54 +#define SPECIES_EGG SPECIES_MIMIKYU_TOTEM_BUSTED + 1 -#define GIGANTAMAX_START SPECIES_EEVEE_PARTNER - -// Gigantamax Forms -#define SPECIES_VENUSAUR_GIGANTAMAX GIGANTAMAX_START + 1 -#define SPECIES_BLASTOISE_GIGANTAMAX GIGANTAMAX_START + 2 -#define SPECIES_CHARIZARD_GIGANTAMAX GIGANTAMAX_START + 3 -#define SPECIES_BUTTERFREE_GIGANTAMAX GIGANTAMAX_START + 4 -#define SPECIES_PIKACHU_GIGANTAMAX GIGANTAMAX_START + 5 -#define SPECIES_MEOWTH_GIGANTAMAX GIGANTAMAX_START + 6 -#define SPECIES_MACHAMP_GIGANTAMAX GIGANTAMAX_START + 7 -#define SPECIES_GENGAR_GIGANTAMAX GIGANTAMAX_START + 8 -#define SPECIES_KINGLER_GIGANTAMAX GIGANTAMAX_START + 9 -#define SPECIES_LAPRAS_GIGANTAMAX GIGANTAMAX_START + 10 -#define SPECIES_EEVEE_GIGANTAMAX GIGANTAMAX_START + 11 -#define SPECIES_SNORLAX_GIGANTAMAX GIGANTAMAX_START + 12 -#define SPECIES_GARBODOR_GIGANTAMAX GIGANTAMAX_START + 13 -#define SPECIES_MELMETAL_GIGANTAMAX GIGANTAMAX_START + 14 -#define SPECIES_RILLABOOM_GIGANTAMAX GIGANTAMAX_START + 15 -#define SPECIES_CINDERACE_GIGANTAMAX GIGANTAMAX_START + 16 -#define SPECIES_INTELEON_GIGANTAMAX GIGANTAMAX_START + 17 -#define SPECIES_CORVIKNIGHT_GIGANTAMAX GIGANTAMAX_START + 18 -#define SPECIES_ORBEETLE_GIGANTAMAX GIGANTAMAX_START + 19 -#define SPECIES_DREDNAW_GIGANTAMAX GIGANTAMAX_START + 20 -#define SPECIES_COALOSSAL_GIGANTAMAX GIGANTAMAX_START + 21 -#define SPECIES_FLAPPLE_GIGANTAMAX GIGANTAMAX_START + 22 -#define SPECIES_APPLETUN_GIGANTAMAX GIGANTAMAX_START + 23 -#define SPECIES_SANDACONDA_GIGANTAMAX GIGANTAMAX_START + 24 -#define SPECIES_TOXTRICITY_AMPED_GIGANTAMAX GIGANTAMAX_START + 25 -#define SPECIES_TOXTRICITY_LOW_KEY_GIGANTAMAX GIGANTAMAX_START + 26 -#define SPECIES_CENTISKORCH_GIGANTAMAX GIGANTAMAX_START + 27 -#define SPECIES_HATTERENE_GIGANTAMAX GIGANTAMAX_START + 28 -#define SPECIES_GRIMMSNARL_GIGANTAMAX GIGANTAMAX_START + 29 -#define SPECIES_ALCREMIE_GIGANTAMAX GIGANTAMAX_START + 30 -#define SPECIES_COPPERAJAH_GIGANTAMAX GIGANTAMAX_START + 31 -#define SPECIES_DURALUDON_GIGANTAMAX GIGANTAMAX_START + 32 -#define SPECIES_URSHIFU_SINGLE_STRIKE_STYLE_GIGANTAMAX GIGANTAMAX_START + 33 -#define SPECIES_URSHIFU_RAPID_STRIKE_STYLE_GIGANTAMAX GIGANTAMAX_START + 34 - -#define SPECIES_EGG SPECIES_URSHIFU_RAPID_STRIKE_STYLE_GIGANTAMAX + 1 - -#define KANTO_SPECIES_END SPECIES_MEW +#define KANTO_SPECIES_END SPECIES_MEW // TODO: remove #define NUM_SPECIES SPECIES_EGG diff --git a/include/party_menu.h b/include/party_menu.h index fbc9d7236..dbc4603f8 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -62,6 +62,7 @@ void ItemUseCB_PPUp(u8 taskId, TaskFunc func); u16 ItemIdToBattleMoveId(u16 item); bool8 IsMoveHm(u16 move); bool8 MonKnowsMove(struct Pokemon *mon, u16 move); +bool8 BoxMonKnowsMove(struct BoxPokemon *boxMon, u16 move); void ItemUseCB_TMHM(u8 taskId, TaskFunc func); void ItemUseCB_RareCandy(u8 taskId, TaskFunc func); void ItemUseCB_SacredAsh(u8 taskId, TaskFunc func); diff --git a/include/pokemon.h b/include/pokemon.h index dd6b5e4cd..17357f671 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -791,6 +791,11 @@ struct MonSpritesGfxManager *CreateMonSpritesGfxManager(u8 battlePosition, u8 mo void DestroyMonSpritesGfxManager(void); u8 *MonSpritesGfxManager_GetSpritePtr(u8 bufferId); u16 GetFormSpeciesId(u16 speciesId, u8 formId); +u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId); +u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); +u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg); +bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method); +void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method); bool8 HealStatusConditions(struct Pokemon *mon, u32 healMask, u8 battleId); diff --git a/src/battle_message.c b/src/battle_message.c index 6b72c7a16..80dcd401e 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -541,6 +541,34 @@ static const u8 sText_GemActivates[] = _("{B_LAST_ITEM} strengthened\n{B_ATK_NAM static const u8 sText_AttackWeakenedByStrongWinds[] = _("The mysterious strong winds\nweakened the attack!"); static const u8 sText_EnduredViaSturdy[] = _("{B_DEF_NAME_WITH_PREFIX} endured\nthe hit using {B_DEF_ABILITY}!"); static const u8 sText_BerryDmgReducing[] = _("{B_LAST_ITEM} weakened the damage\nto {B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!"); +static const u8 sText_TrappedBySwirlingMagma[] =_("{B_DEF_NAME_WITH_PREFIX} became\ntrapped by swirling magma!"); +static const u8 sText_Infestation[] = _("{B_DEF_NAME_WITH_PREFIX} has been afflicted\nwith an infestation by {B_ATK_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnInSnapTrap[] = _("{B_DEF_NAME_WITH_PREFIX} got trapped\nby a snap trap!"); +static const u8 sText_AtkTrappedDef[] = _("{B_ATK_NAME_WITH_PREFIX} trapped\nthe {B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_ResetsTargetsStatLevels[] =_("{B_DEF_NAME_WITH_PREFIX}'s stat changes\nwere removed!"); +static const u8 sText_StrongWindsDissipated[] = _("The mysterious strong winds\nhave dissipated!{PAUSE 64}"); +static const u8 sText_ExtremeSunlightFaded[] = _("The extreme sunlight faded.{PAUSE 64}"); +static const u8 sText_HeavyRainLifted[] = _("The heavy rain has lifted!{PAUSE 64}"); +static const u8 sText_SymbiosisItemPass[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} passed its {B_LAST_ITEM}\nto {B_ATK_NAME_WITH_PREFIX} through {B_LAST_ABILITY}!"); +static const u8 sText_BurstingFlames[] = _("The bursting flames\nhit {B_SCR_ACTIVE_NAME_WITH_PREFIX}!"); +static const u8 sText_BrokeThroughProtection[] = _("It broke through\n{B_DEF_NAME_WITH_PREFIX}'s protection!"); +static const u8 sText_FellForFeint[] = _("{B_DEF_NAME_WITH_PREFIX} fell for\nthe feint!"); +static const u8 sText_SpectralThiefSteal[] = _("{B_ATK_NAME_WITH_PREFIX} stole the target's\nboosted stats!"); +static const u8 sText_PkmnsAbilitySuppressed[] = _("{B_DEF_NAME_WITH_PREFIX}'s ability\nwas suppressed!"); +static const u8 sText_IncinerateBurn[] = _("{B_EFF_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nwas burnt up!"); +static const u8 sText_BugBite[] = _("{B_ATK_NAME_WITH_PREFIX} stole and ate\n{B_EFF_NAME_WITH_PREFIX}'s {B_LAST_ITEM}!"); +static const u8 sText_BothCanNoLongerEscape[] = _("Neither Pokémon can run away!"); +static const u8 sText_AttackerLostFireType[] = _("{B_ATK_NAME_WITH_PREFIX} burned itself out!"); +static const u8 sText_AttackerLostElectricType[] = _("{B_ATK_NAME_WITH_PREFIX} used up all\nof its electricity!"); +static const u8 sText_AttackerLostItsType[] = _("{B_ATK_NAME_WITH_PREFIX} lost\nits {B_BUFF1} type!"); +static const u8 sText_StealthRockDmg[] = _("Pointed stones dug into\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}!"); +static const u8 sText_SharpSteelDmg[] = _("Sharp steel bit into {B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_PointedStonesFloat[] =_("Pointed stones float in the air\naround {B_DEF_TEAM2} team!"); +static const u8 sText_SharpSteelFloats[] = _("Sharp-pointed steel floats\naround {B_DEF_TEAM2} team!"); +static const u8 sText_TargetCoveredInStickyCandySyrup[] = _("{B_DEF_NAME_WITH_PREFIX} got covered\nin sticky syrup!"); +static const u8 sText_AromaVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} is protected\nby an aromatic veil!"); +static const u8 sText_PkmnPreventedFromHealing[] = _("{B_DEF_NAME_WITH_PREFIX} was prevented\nfrom healing!"); const u16 gTrainerUsedItemStringIds[] = @@ -952,6 +980,34 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT - BATTLESTRINGS_TABLE_ST [STRINGID_ATTACKWEAKENEDBSTRONGWINDS - BATTLESTRINGS_TABLE_START] = sText_AttackWeakenedByStrongWinds, [STRINGID_ENDUREDSTURDY - BATTLESTRINGS_TABLE_START] = sText_EnduredViaSturdy, [STRINGID_BERRYDMGREDUCES - BATTLESTRINGS_TABLE_START] = sText_BerryDmgReducing, + [STRINGID_TARGETTOUGHEDITOUT - BATTLESTRINGS_TABLE_START] = sText_TargetToughedItOut, + [STRINGID_TRAPPEDBYSWIRLINGMAGMA - BATTLESTRINGS_TABLE_START] = sText_TrappedBySwirlingMagma, + [STRINGID_INFESTATION - BATTLESTRINGS_TABLE_START] = sText_Infestation, + [STRINGID_PKMNINSNAPTRAP - BATTLESTRINGS_TABLE_START] = sText_PkmnInSnapTrap, + [STRINGID_THUNDERCAGETRAPPED - BATTLESTRINGS_TABLE_START] = sText_AtkTrappedDef, + [STRINGID_RESETSTARGETSSTATLEVELS - BATTLESTRINGS_TABLE_START] = sText_ResetsTargetsStatLevels, + [STRINGID_STRONGWINDSDISSIPATED - BATTLESTRINGS_TABLE_START] = sText_StrongWindsDissipated, + [STRINGID_EXTREMESUNLIGHTFADED - BATTLESTRINGS_TABLE_START] = sText_ExtremeSunlightFaded, + [STRINGID_HEAVYRAINLIFTED - BATTLESTRINGS_TABLE_START] = sText_HeavyRainLifted, + [STRINGID_SYMBIOSISITEMPASS - BATTLESTRINGS_TABLE_START] = sText_SymbiosisItemPass, + [STRINGID_BURSTINGFLAMESHIT - BATTLESTRINGS_TABLE_START] = sText_BurstingFlames, + [STRINGID_BROKETHROUGHPROTECTION - BATTLESTRINGS_TABLE_START] = sText_BrokeThroughProtection, + [STRINGID_FELLFORFEINT - BATTLESTRINGS_TABLE_START] = sText_FellForFeint, + [STRINGID_SPECTRALTHIEFSTEAL - BATTLESTRINGS_TABLE_START] = sText_SpectralThiefSteal, + [STRINGID_PKMNSABILITYSUPPRESSED - BATTLESTRINGS_TABLE_START] = sText_PkmnsAbilitySuppressed, + [STRINGID_INCINERATEBURN - BATTLESTRINGS_TABLE_START] = sText_IncinerateBurn, + [STRINGID_BUGBITE - BATTLESTRINGS_TABLE_START] = sText_BugBite, + [STRINGID_BOTHCANNOLONGERESCAPE - BATTLESTRINGS_TABLE_START] = sText_BothCanNoLongerEscape, + [STRINGID_ATTACKERLOSTFIRETYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostFireType, + [STRINGID_ATTACKERLOSTELECTRICTYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostElectricType, + [STRINGID_ATTACKERLOSTITSTYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostItsType, + [STRINGID_STEALTHROCKDMG - BATTLESTRINGS_TABLE_START] = sText_StealthRockDmg, + [STRINGID_SHARPSTEELDMG - BATTLESTRINGS_TABLE_START] = sText_SharpSteelDmg, + [STRINGID_POINTEDSTONESFLOAT - BATTLESTRINGS_TABLE_START] = sText_PointedStonesFloat, + [STRINGID_SHARPSTEELFLOATS - BATTLESTRINGS_TABLE_START] = sText_SharpSteelFloats, + [STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP - BATTLESTRINGS_TABLE_START] = sText_TargetCoveredInStickyCandySyrup, + [STRINGID_AROMAVEILPROTECTED - BATTLESTRINGS_TABLE_START] = sText_AromaVeilProtected, + [STRINGID_PKMNPREVENTEDFROMHEALING - BATTLESTRINGS_TABLE_START] = sText_PkmnPreventedFromHealing, }; const u16 gMagicCoatBounceStringIds[] = @@ -959,6 +1015,16 @@ const u16 gMagicCoatBounceStringIds[] = STRINGID_PKMNMOVEBOUNCED, STRINGID_PKMNMOVEBOUNCEDABILITY }; +const u16 gDmgHazardsStringIds[] = +{ + [B_MSG_PKMNHURTBYSPIKES] = STRINGID_PKMNHURTBYSPIKES, + [B_MSG_STEALTHROCKDMG] = STRINGID_STEALTHROCKDMG, + [B_MSG_SHARPSTEELDMG] = STRINGID_SHARPSTEELDMG, + [B_MSG_POINTEDSTONESFLOAT] = STRINGID_POINTEDSTONESFLOAT, + [B_MSG_SPIKESSCATTERED] = STRINGID_SPIKESSCATTERED, + [B_MSG_SHARPSTEELFLOATS] = STRINGID_SHARPSTEELFLOATS, +}; + const u16 gMissStringIds[] = { [B_MSG_MISSED] = STRINGID_ATTACKMISSED, @@ -1106,15 +1172,19 @@ const u16 gFirstTurnOfTwoStringIds[] = [B_MSG_TURN1_BOUNCE] = STRINGID_PKMNSPRANGUP }; -// Index copied from move's index in gTrappingMoves -const u16 gWrappedStringIds[] = +// Index copied from move's index in sTrappingMoves +const u16 gWrappedStringIds[NUM_TRAPPING_MOVES] = { - STRINGID_PKMNSQUEEZEDBYBIND, // MOVE_BIND - STRINGID_PKMNWRAPPEDBY, // MOVE_WRAP - STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_FIRE_SPIN - STRINGID_PKMNCLAMPED, // MOVE_CLAMP - STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_WHIRLPOOL - STRINGID_PKMNTRAPPEDBYSANDTOMB // MOVE_SAND_TOMB + [B_MSG_WRAPPED_BIND] = STRINGID_PKMNSQUEEZEDBYBIND, // MOVE_BIND + [B_MSG_WRAPPED_WRAP] = STRINGID_PKMNWRAPPEDBY, // MOVE_WRAP + [B_MSG_WRAPPED_FIRE_SPIN] = STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_FIRE_SPIN + [B_MSG_WRAPPED_CLAMP] = STRINGID_PKMNCLAMPED, // MOVE_CLAMP + [B_MSG_WRAPPED_WHIRLPOOL] = STRINGID_PKMNTRAPPEDINVORTEX, // MOVE_WHIRLPOOL + [B_MSG_WRAPPED_SAND_TOMB] = STRINGID_PKMNTRAPPEDBYSANDTOMB, // MOVE_SAND_TOMB + [B_MSG_WRAPPED_MAGMA_STORM] = STRINGID_TRAPPEDBYSWIRLINGMAGMA, // MOVE_MAGMA_STORM + [B_MSG_WRAPPED_INFESTATION] = STRINGID_INFESTATION, // MOVE_INFESTATION + [B_MSG_WRAPPED_SNAP_TRAP] = STRINGID_PKMNINSNAPTRAP, // MOVE_SNAP_TRAP + [B_MSG_WRAPPED_THUNDER_CAGE]= STRINGID_THUNDERCAGETRAPPED, // MOVE_THUNDER_CAGE }; const u16 gMistUsedStringIds[] = @@ -1340,17 +1410,6 @@ const u16 gDoubleBattleRecallStrings[1 << (MAX_BATTLERS_COUNT / 2)] = STRINGID_TRAINER1MON1AND2COMEBACK }; -const u16 gTrappingMoves[NUM_TRAPPING_MOVES + 1] = -{ - MOVE_BIND, - MOVE_WRAP, - MOVE_FIRE_SPIN, - MOVE_CLAMP, - MOVE_WHIRLPOOL, - MOVE_SAND_TOMB, - 0xFFFF // Never read -}; - const u8 gText_PkmnIsEvolving[] = _("What?\n{STR_VAR_1} is evolving!"); const u8 gText_CongratsPkmnEvolved[] = _("Congratulations! Your {STR_VAR_1}\nevolved into {STR_VAR_2}!{WAIT_SE}\p"); const u8 gText_PkmnStoppedEvolving[] = _("Huh? {STR_VAR_1}\nstopped evolving!\p"); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4c9e92404..e4109c2e4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -71,6 +71,24 @@ #define MEMBERS_8(a, b, c, d, e, f, g, h) a; b; c; d; e; f; g; h; + +static const u16 sTrappingMoves[NUM_TRAPPING_MOVES] = +{ + MOVE_BIND, + MOVE_WRAP, + MOVE_FIRE_SPIN, + MOVE_CLAMP, + MOVE_WHIRLPOOL, + MOVE_SAND_TOMB, + MOVE_MAGMA_STORM, + MOVE_INFESTATION, + MOVE_SNAP_TRAP, + MOVE_THUNDER_CAGE +}; + +#define STAT_CHANGE_WORKED 0 +#define STAT_CHANGE_DIDNT_WORK 1 + extern const u8 *const gBattleScriptsForMoveEffects[]; #define DEFENDER_IS_PROTECTED ((gProtectStructs[gBattlerTarget].protected) && (!gMovesInfo[gCurrentMove].ignoresProtect)) @@ -93,6 +111,10 @@ static void DrawLevelUpWindow2(void); static void PutMonIconOnLvlUpBanner(void); static void DrawLevelUpBannerText(void); static void SpriteCB_MonIconOnLvlUpBanner(struct Sprite* sprite); +static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent); +static bool8 IsFinalStrikeEffect(u16 move); +static void TryUpdateRoundTurnOrder(void); +static void BestowItem(u32 battlerAtk, u32 battlerDef); static void Cmd_attackcanceler(void); static void Cmd_accuracycheck(void); @@ -115,7 +137,7 @@ static void Cmd_printselectionstring(void); static void Cmd_waitmessage(void); static void Cmd_printfromtable(void); static void Cmd_printselectionstringfromtable(void); -static void Cmd_seteffectwithchance(void); +static void Cmd_setadditionaleffects(void); static void Cmd_seteffectprimary(void); static void Cmd_seteffectsecondary(void); static void Cmd_clearstatusfromeffect(void); @@ -308,13 +330,13 @@ static void Cmd_tryswapitems(void); static void Cmd_trycopyability(void); static void Cmd_trywish(void); static void Cmd_trysetroots(void); -static void Cmd_doubledamagedealtifdamaged(void); +static void Cmd_setgastroacid(void); static void Cmd_setyawn(void); static void Cmd_setdamagetohealthdifference(void); static void Cmd_scaledamagebyhealthratio(void); static void Cmd_tryswapabilities(void); static void Cmd_tryimprison(void); -static void Cmd_trysetgrudge(void); +static void Cmd_setstealthrock(void); static void Cmd_weightdamagecalculation(void); static void Cmd_assistattackselect(void); static void Cmd_trysetmagiccoat(void); @@ -346,30 +368,30 @@ static void Cmd_callnative(void); void (* const gBattleScriptingCommandsTable[])(void) = { - Cmd_attackcanceler, //0x0 // done - Cmd_accuracycheck, //0x1 // done - Cmd_attackstring, //0x2 // done - Cmd_ppreduce, //0x3 // done - Cmd_critcalc, //0x4 // done - Cmd_damagecalc, //0x5 // done - Cmd_typecalc, //0x6 // done - Cmd_adjustdamage, //0x7 // done - Cmd_multihitresultmessage, //0x8 // done - Cmd_attackanimation, //0x9 // done - Cmd_waitanimation, //0xA // done - Cmd_healthbarupdate, //0xB // done - Cmd_datahpupdate, //0xC // done - Cmd_critmessage, //0xD - Cmd_effectivenesssound, //0xE - Cmd_resultmessage, //0xF - Cmd_printstring, //0x10 - Cmd_printselectionstring, //0x11 - Cmd_waitmessage, //0x12 - Cmd_printfromtable, //0x13 - Cmd_printselectionstringfromtable, //0x14 - Cmd_seteffectwithchance, //0x15 - Cmd_seteffectprimary, //0x16 - Cmd_seteffectsecondary, //0x17 + Cmd_attackcanceler, //0x0 // done + Cmd_accuracycheck, //0x1 // done + Cmd_attackstring, //0x2 // done + Cmd_ppreduce, //0x3 // done + Cmd_critcalc, //0x4 // done + Cmd_damagecalc, //0x5 // done + Cmd_typecalc, //0x6 // done + Cmd_adjustdamage, //0x7 // done + Cmd_multihitresultmessage, //0x8 // done + Cmd_attackanimation, //0x9 // done + Cmd_waitanimation, //0xA // done + Cmd_healthbarupdate, //0xB // done + Cmd_datahpupdate, //0xC // done + Cmd_critmessage, //0xD // done + Cmd_effectivenesssound, //0xE // done + Cmd_resultmessage, //0xF // done + Cmd_printstring, //0x10 // done + Cmd_printselectionstring, //0x11 // done + Cmd_waitmessage, //0x12 // done + Cmd_printfromtable, //0x13 // done + Cmd_printselectionstringfromtable, //0x14 // done + Cmd_setadditionaleffects, //0x15 // done + Cmd_seteffectprimary, //0x16 // done + Cmd_seteffectsecondary, //0x17 // done Cmd_clearstatusfromeffect, //0x18 Cmd_tryfaintmon, //0x19 Cmd_dofaintanimation, //0x1A @@ -458,7 +480,7 @@ void (* const gBattleScriptingCommandsTable[])(void) = Cmd_resetsentmonsvalue, //0x6D Cmd_setatktoplayer0, //0x6E Cmd_makevisible, //0x6F - Cmd_recordability, //0x70 + Cmd_recordability, //0x70 // done Cmd_buffermovetolearn, //0x71 Cmd_jumpifplayerran, //0x72 Cmd_hpthresholds, //0x73 @@ -560,13 +582,13 @@ void (* const gBattleScriptingCommandsTable[])(void) = Cmd_trycopyability, //0xD3 Cmd_trywish, //0xD4 Cmd_trysetroots, //0xD5 - Cmd_doubledamagedealtifdamaged, //0xD6 + Cmd_setgastroacid, //0xD6 // done Cmd_setyawn, //0xD7 Cmd_setdamagetohealthdifference, //0xD8 Cmd_scaledamagebyhealthratio, //0xD9 Cmd_tryswapabilities, //0xDA Cmd_tryimprison, //0xDB - Cmd_trysetgrudge, //0xDC + Cmd_setstealthrock, //0xDC // done Cmd_weightdamagecalculation, //0xDD Cmd_assistattackselect, //0xDE Cmd_trysetmagiccoat, //0xDF @@ -765,18 +787,88 @@ static const u8 sFlailHpScaleToPowerTable[] = 48, 20 }; -static const u16 sNaturePowerMoves[] = +static const u16 sFinalStrikeOnlyEffects[] = { + MOVE_EFFECT_BUG_BITE, + MOVE_EFFECT_STEAL_ITEM, + MOVE_EFFECT_REMOVE_ARG_TYPE, + MOVE_EFFECT_SMACK_DOWN, + MOVE_EFFECT_REMOVE_STATUS, + MOVE_EFFECT_RECOIL_HP_25, + MOVE_EFFECT_PREVENT_ESCAPE, + MOVE_EFFECT_WRAP, +}; + +static const u16 sNaturePowerMoves[BATTLE_TERRAIN_COUNT] = +{ +#if B_NATURE_POWER_MOVES >= GEN_7 + [BATTLE_TERRAIN_GRASS] = MOVE_ENERGY_BALL, + [BATTLE_TERRAIN_LONG_GRASS] = MOVE_ENERGY_BALL, + [BATTLE_TERRAIN_SAND] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_WATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_POND] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_MOUNTAIN] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_CAVE] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_BUILDING] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_PLAIN] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_SNOW] = MOVE_ICE_BEAM, +#elif B_NATURE_POWER_MOVES == GEN_6 + [BATTLE_TERRAIN_GRASS] = MOVE_ENERGY_BALL, + [BATTLE_TERRAIN_LONG_GRASS] = MOVE_ENERGY_BALL, + [BATTLE_TERRAIN_SAND] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_WATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_POND] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_MOUNTAIN] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_CAVE] = MOVE_EARTH_POWER, + [BATTLE_TERRAIN_BUILDING] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_PLAIN] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_SNOW] = MOVE_FROST_BREATH, +#elif B_NATURE_POWER_MOVES == GEN_5 + [BATTLE_TERRAIN_GRASS] = MOVE_SEED_BOMB, + [BATTLE_TERRAIN_LONG_GRASS] = MOVE_SEED_BOMB, + [BATTLE_TERRAIN_SAND] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_WATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_POND] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_MOUNTAIN] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_CAVE] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_BUILDING] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_PLAIN] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_SNOW] = MOVE_BLIZZARD, +#elif B_NATURE_POWER_MOVES == GEN_4 + [BATTLE_TERRAIN_GRASS] = MOVE_SEED_BOMB, + [BATTLE_TERRAIN_LONG_GRASS] = MOVE_SEED_BOMB, + [BATTLE_TERRAIN_SAND] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_WATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_POND] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_MOUNTAIN] = MOVE_ROCK_SLIDE, + [BATTLE_TERRAIN_CAVE] = MOVE_ROCK_SLIDE, + [BATTLE_TERRAIN_BUILDING] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_PLAIN] = MOVE_EARTHQUAKE, + [BATTLE_TERRAIN_SNOW] = MOVE_BLIZZARD, +#else // Gen 1-3 [BATTLE_TERRAIN_GRASS] = MOVE_STUN_SPORE, [BATTLE_TERRAIN_LONG_GRASS] = MOVE_RAZOR_LEAF, [BATTLE_TERRAIN_SAND] = MOVE_EARTHQUAKE, - [BATTLE_TERRAIN_UNDERWATER] = MOVE_HYDRO_PUMP, [BATTLE_TERRAIN_WATER] = MOVE_SURF, [BATTLE_TERRAIN_POND] = MOVE_BUBBLE_BEAM, [BATTLE_TERRAIN_MOUNTAIN] = MOVE_ROCK_SLIDE, [BATTLE_TERRAIN_CAVE] = MOVE_SHADOW_BALL, [BATTLE_TERRAIN_BUILDING] = MOVE_SWIFT, - [BATTLE_TERRAIN_PLAIN] = MOVE_SWIFT + [BATTLE_TERRAIN_PLAIN] = MOVE_SWIFT, + [BATTLE_TERRAIN_SNOW] = MOVE_BLIZZARD, +#endif + [BATTLE_TERRAIN_UNDERWATER] = MOVE_HYDRO_PUMP, + [BATTLE_TERRAIN_SOARING] = MOVE_AIR_SLASH, + [BATTLE_TERRAIN_SKY_PILLAR] = MOVE_AIR_SLASH, + [BATTLE_TERRAIN_BURIAL_GROUND] = MOVE_SHADOW_BALL, + [BATTLE_TERRAIN_PUDDLE] = MOVE_MUD_BOMB, + [BATTLE_TERRAIN_MARSH] = MOVE_MUD_BOMB, + [BATTLE_TERRAIN_SWAMP] = MOVE_MUD_BOMB, + [BATTLE_TERRAIN_ICE] = MOVE_ICE_BEAM, + [BATTLE_TERRAIN_VOLCANO] = MOVE_LAVA_PLUME, + [BATTLE_TERRAIN_DISTORTION_WORLD] = MOVE_TRI_ATTACK, + [BATTLE_TERRAIN_SPACE] = MOVE_DRACO_METEOR, + [BATTLE_TERRAIN_ULTRA_SPACE] = MOVE_PSYSHOCK, }; // format: min. weight (hectograms), base power @@ -2379,34 +2471,43 @@ static void Cmd_datahpupdate(void) static void Cmd_critmessage(void) { + CMD_ARGS(); + if (gBattleControllerExecFlags == 0) { - if (gCritMultiplier == 2 && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + if (gIsCriticalHit == TRUE && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { PrepareStringBattle(STRINGID_CRITICALHIT, gBattlerAttacker); + + // Signal for the trainer slide-in system. + if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstCriticalHitMsgState != 2) + gBattleStruct->trainerSlideFirstCriticalHitMsgState = 1; + gBattleCommunication[MSG_DISPLAY] = 1; } - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = cmd->nextInstr; } } static void Cmd_effectivenesssound(void) { + CMD_ARGS(); + if (gBattleControllerExecFlags) return; gActiveBattler = gBattlerTarget; if (!(gMoveResultFlags & MOVE_RESULT_MISSED)) { - switch (gMoveResultFlags & (u8)(~MOVE_RESULT_MISSED)) + switch (gMoveResultFlags & ~MOVE_RESULT_MISSED) { case MOVE_RESULT_SUPER_EFFECTIVE: BtlController_EmitPlaySE(BUFFER_A, SE_SUPER_EFFECTIVE); - MarkBattlerForControllerExec(gActiveBattler); + MarkBattlerForControllerExec(gBattlerTarget); break; case MOVE_RESULT_NOT_VERY_EFFECTIVE: BtlController_EmitPlaySE(BUFFER_A, SE_NOT_EFFECTIVE); - MarkBattlerForControllerExec(gActiveBattler); + MarkBattlerForControllerExec(gBattlerTarget); break; case MOVE_RESULT_DOESNT_AFFECT_FOE: case MOVE_RESULT_FAILED: @@ -2415,51 +2516,76 @@ static void Cmd_effectivenesssound(void) case MOVE_RESULT_FOE_ENDURED: case MOVE_RESULT_ONE_HIT_KO: case MOVE_RESULT_FOE_HUNG_ON: + case MOVE_RESULT_STURDIED: default: if (gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE) { BtlController_EmitPlaySE(BUFFER_A, SE_SUPER_EFFECTIVE); - MarkBattlerForControllerExec(gActiveBattler); + MarkBattlerForControllerExec(gBattlerTarget); } else if (gMoveResultFlags & MOVE_RESULT_NOT_VERY_EFFECTIVE) { BtlController_EmitPlaySE(BUFFER_A, SE_NOT_EFFECTIVE); - MarkBattlerForControllerExec(gActiveBattler); + MarkBattlerForControllerExec(gBattlerTarget); } else if (!(gMoveResultFlags & (MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED))) { BtlController_EmitPlaySE(BUFFER_A, SE_EFFECTIVE); - MarkBattlerForControllerExec(gActiveBattler); + MarkBattlerForControllerExec(gBattlerTarget); } break; } } - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_resultmessage(void) { - u32 stringId = 0; + CMD_ARGS(); + u32 stringId = 0; if (gBattleControllerExecFlags) return; + // TODO: Convert this to a proper FORM_CHANGE type. + // Do Ice Face form change which was set up in Cmd_adjustdamage. + if (gBattleResources->flags->flags[gBattlerTarget] & RESOURCE_FLAG_ICE_FACE) + { + gBattleResources->flags->flags[gBattlerTarget] &= ~(RESOURCE_FLAG_ICE_FACE); + gBattleMons[gBattlerTarget].species = SPECIES_EISCUE_NOICE_FACE; + gBattleScripting.battler = gBattlerTarget; // For STRINGID_PKMNTRANSFORMED + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_IceFaceNullsDamage; + return; + } + if (gMoveResultFlags & MOVE_RESULT_MISSED && (!(gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE) || gBattleCommunication[MISS_TYPE] > B_MSG_AVOIDED_ATK)) { + // TODO: Ability Popup + // if (gBattleCommunication[MISS_TYPE] > B_MSG_AVOIDED_ATK) // Wonder Guard or Levitate - show the ability pop-up + // CreateAbilityPopUp(gBattlerTarget, gBattleMons[gBattlerTarget].ability, (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) != 0); stringId = gMissStringIds[gBattleCommunication[MISS_TYPE]]; gBattleCommunication[MSG_DISPLAY] = 1; } else { gBattleCommunication[MSG_DISPLAY] = 1; - switch (gMoveResultFlags & (u8)(~MOVE_RESULT_MISSED)) + switch (gMoveResultFlags & ~MOVE_RESULT_MISSED) { case MOVE_RESULT_SUPER_EFFECTIVE: - stringId = STRINGID_SUPEREFFECTIVE; + if (!gMultiHitCounter) // Don't print effectiveness on each hit in a multi hit attack + { + // Signal for the trainer slide-in system. + if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState != 2) + gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 1; + + stringId = STRINGID_SUPEREFFECTIVE; + } break; case MOVE_RESULT_NOT_VERY_EFFECTIVE: - stringId = STRINGID_NOTVERYEFFECTIVE; + if (!gMultiHitCounter) + stringId = STRINGID_NOTVERYEFFECTIVE; break; case MOVE_RESULT_ONE_HIT_KO: stringId = STRINGID_ONEHITKO; @@ -2478,7 +2604,7 @@ static void Cmd_resultmessage(void) gPotentialItemEffectBattler = gBattlerTarget; gMoveResultFlags &= ~(MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON); BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_FocusBandActivates; + gBattlescriptCurrInstr = BattleScript_HangedOnMsg; return; default: if (gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE) @@ -2494,6 +2620,14 @@ static void Cmd_resultmessage(void) gBattlescriptCurrInstr = BattleScript_OneHitKOMsg; return; } + else if (gMoveResultFlags & MOVE_RESULT_STURDIED) + { + gMoveResultFlags &= ~(MOVE_RESULT_STURDIED | MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON); + gSpecialStatuses[gBattlerTarget].sturdied = FALSE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SturdiedMsg; + return; + } else if (gMoveResultFlags & MOVE_RESULT_FOE_ENDURED) { gMoveResultFlags &= ~(MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON); @@ -2507,13 +2641,21 @@ static void Cmd_resultmessage(void) gPotentialItemEffectBattler = gBattlerTarget; gMoveResultFlags &= ~(MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON); BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_FocusBandActivates; + gBattlescriptCurrInstr = BattleScript_HangedOnMsg; return; } else if (gMoveResultFlags & MOVE_RESULT_FAILED) { stringId = STRINGID_BUTITFAILED; } + else if (B_AFFECTION_MECHANICS == TRUE && (gMoveResultFlags & MOVE_RESULT_FOE_ENDURED_AFFECTION)) + { + gSpecialStatuses[gBattlerTarget].affectionEndured = FALSE; + gMoveResultFlags &= ~MOVE_RESULT_FOE_ENDURED_AFFECTION; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AffectionBasedEndurance; + return; + } else { gBattleCommunication[MSG_DISPLAY] = 0; @@ -2524,7 +2666,16 @@ static void Cmd_resultmessage(void) if (stringId) PrepareStringBattle(stringId, gBattlerAttacker); - gBattlescriptCurrInstr++; + gBattlescriptCurrInstr = cmd->nextInstr; + + // Print berry reducing message after result message. + if (gSpecialStatuses[gBattlerTarget].berryReduced + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + { + gSpecialStatuses[gBattlerTarget].berryReduced = FALSE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_PrintBerryReduceString; + } } static void Cmd_printstring(void) @@ -2543,30 +2694,33 @@ static void Cmd_printstring(void) static void Cmd_printselectionstring(void) { + CMD_ARGS(u16 id); + gActiveBattler = gBattlerAttacker; + BtlController_EmitPrintSelectionString(BUFFER_A, cmd->id); + MarkBattlerForControllerExec(gBattlerAttacker); - BtlController_EmitPrintSelectionString(BUFFER_A, T2_READ_16(gBattlescriptCurrInstr + 1)); - MarkBattlerForControllerExec(gActiveBattler); - - gBattlescriptCurrInstr += 3; + gBattlescriptCurrInstr = cmd->nextInstr; gBattleCommunication[MSG_DISPLAY] = 1; } static void Cmd_waitmessage(void) { + CMD_ARGS(u16 time); + if (gBattleControllerExecFlags == 0) { if (!gBattleCommunication[MSG_DISPLAY]) { - gBattlescriptCurrInstr += 3; + gBattlescriptCurrInstr = cmd->nextInstr; } else { - u16 toWait = T2_READ_16(gBattlescriptCurrInstr + 1); + u16 toWait = cmd->time; if (++gPauseCounterBattle >= toWait) { gPauseCounterBattle = 0; - gBattlescriptCurrInstr += 3; + gBattlescriptCurrInstr = cmd->nextInstr; gBattleCommunication[MSG_DISPLAY] = 0; } } @@ -2575,61 +2729,138 @@ static void Cmd_waitmessage(void) static void Cmd_printfromtable(void) { + CMD_ARGS(const u16 *ptr); + if (gBattleControllerExecFlags == 0) { - const u16 *ptr = (const u16 *) T1_READ_PTR(gBattlescriptCurrInstr + 1); + const u16 *ptr = cmd->ptr; ptr += gBattleCommunication[MULTISTRING_CHOOSER]; + gBattlescriptCurrInstr = cmd->nextInstr; PrepareStringBattle(*ptr, gBattlerAttacker); - - gBattlescriptCurrInstr += 5; gBattleCommunication[MSG_DISPLAY] = 1; } } static void Cmd_printselectionstringfromtable(void) { + CMD_ARGS(const u16 *ptr); + if (gBattleControllerExecFlags == 0) { - const u16 *ptr = (const u16 *) T1_READ_PTR(gBattlescriptCurrInstr + 1); + const u16 *ptr = cmd->ptr; ptr += gBattleCommunication[MULTISTRING_CHOOSER]; gActiveBattler = gBattlerAttacker; BtlController_EmitPrintSelectionString(BUFFER_A, *ptr); - MarkBattlerForControllerExec(gActiveBattler); + MarkBattlerForControllerExec(gBattlerAttacker); - gBattlescriptCurrInstr += 5; + gBattlescriptCurrInstr = cmd->nextInstr; gBattleCommunication[MSG_DISPLAY] = 1; } } -u8 GetBattlerTurnOrderNum(u8 battlerId) +u8 GetBattlerTurnOrderNum(u8 battler) { s32 i; for (i = 0; i < gBattlersCount; i++) { - if (gBattlerByTurnOrder[i] == battlerId) + if (gBattlerByTurnOrder[i] == battler) break; } return i; } -// Called INCREMENT_RESET_RETURN in Emerald which adds "gBattleCommunication[MOVE_EFFECT_BYTE] = 0;" before the return. -#define INCREMENT_RETURN \ +static void CheckSetUnburden(u8 battler) +{ + if (GetBattlerAbility(battler) == ABILITY_UNBURDEN) + { + gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_UNBURDEN; + RecordAbilityBattle(battler, ABILITY_UNBURDEN); + } +} + +// battlerStealer steals the item of battlerItem +void StealTargetItem(u8 battlerStealer, u8 battlerItem) +{ + gLastUsedItem = gBattleMons[battlerItem].item; + gBattleMons[battlerItem].item = 0; + + RecordItemEffectBattle(battlerItem, 0); + RecordItemEffectBattle(battlerStealer, ItemId_GetHoldEffect(gLastUsedItem)); + gBattleMons[battlerStealer].item = gLastUsedItem; + + CheckSetUnburden(battlerItem); + gBattleResources->flags->flags[battlerStealer] &= ~RESOURCE_FLAG_UNBURDEN; + + gActiveBattler = battlerStealer; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gLastUsedItem), &gLastUsedItem); // set attacker item + MarkBattlerForControllerExec(battlerStealer); + + gActiveBattler = battlerItem; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[battlerItem].item); // remove target item + MarkBattlerForControllerExec(battlerItem); + + gBattleStruct->choicedMove[battlerItem] = 0; + + TrySaveExchangedItem(battlerItem, gLastUsedItem); +} + +#define INCREMENT_RESET_RETURN \ { \ gBattlescriptCurrInstr++; \ + gBattleScripting.moveEffect = 0; \ return; \ } -void SetMoveEffect(bool32 primary, u32 certain) +#define RESET_RETURN \ +{ \ + gBattleScripting.moveEffect = 0; \ + return; \ +} + +void SetMoveEffect(bool32 primary, bool32 certain) { + s32 i, affectsUser = 0; bool32 statusChanged = FALSE; - u32 affectsUser = 0; // 0x40 otherwise - bool32 noSunCanFreeze = TRUE; + bool32 mirrorArmorReflected = (GetBattlerAbility(gBattlerTarget) == ABILITY_MIRROR_ARMOR); + u32 flags = 0; + u16 battlerAbility; + bool8 activateAfterFaint = FALSE; + + // NULL move effect + if (gBattleScripting.moveEffect == 0) + return; + + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT + && gBattleMons[gBattlerTarget].hp != 0 + && IsFinalStrikeEffect(gBattleScripting.moveEffect)) + { + gBattlescriptCurrInstr++; + return; + } + + switch (gBattleScripting.moveEffect) // Set move effects which happen later on + { + case MOVE_EFFECT_KNOCK_OFF: + case MOVE_EFFECT_SMACK_DOWN: + case MOVE_EFFECT_REMOVE_STATUS: + case MOVE_EFFECT_STOCKPILE_WORE_OFF: + gBattleStruct->moveEffect2 = gBattleScripting.moveEffect; + gBattlescriptCurrInstr++; + return; + case MOVE_EFFECT_STEALTH_ROCK: + case MOVE_EFFECT_SPIKES: + case MOVE_EFFECT_PAYDAY: + case MOVE_EFFECT_STEAL_ITEM: + case MOVE_EFFECT_BUG_BITE: + activateAfterFaint = TRUE; + break; + } if (gBattleScripting.moveEffect & MOVE_EFFECT_AFFECTS_USER) { - gEffectBattler = gBattlerAttacker; // battlerId that effects get applied on + gEffectBattler = gBattlerAttacker; // battler that effects get applied on gBattleScripting.moveEffect &= ~MOVE_EFFECT_AFFECTS_USER; affectsUser = MOVE_EFFECT_AFFECTS_USER; gBattleScripting.battler = gBattlerTarget; // theoretically the attacker @@ -2639,60 +2870,73 @@ void SetMoveEffect(bool32 primary, u32 certain) gEffectBattler = gBattlerTarget; gBattleScripting.battler = gBattlerAttacker; } - if (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE && gBattleScripting.moveEffect != 1 - && GetBattlerSide(gEffectBattler) == B_SIDE_OPPONENT) - INCREMENT_RETURN - if (gBattleMons[gEffectBattler].ability == ABILITY_SHIELD_DUST && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) - && !primary && gBattleScripting.moveEffect <= 9) - INCREMENT_RETURN + battlerAbility = GetBattlerAbility(gEffectBattler); - if (gSideStatuses[GET_BATTLER_SIDE(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) - && !primary && gBattleScripting.moveEffect <= 7) - INCREMENT_RETURN + // Just in case this flag is still set + gBattleScripting.moveEffect &= ~MOVE_EFFECT_CERTAIN; - if (gBattleMons[gEffectBattler].hp == 0 - && gBattleScripting.moveEffect != MOVE_EFFECT_PAYDAY - && gBattleScripting.moveEffect != MOVE_EFFECT_STEAL_ITEM) - INCREMENT_RETURN - - if (gBattleMons[gEffectBattler].status2 & STATUS2_SUBSTITUTE && affectsUser != MOVE_EFFECT_AFFECTS_USER) - INCREMENT_RETURN - - if (gBattleScripting.moveEffect <= PRIMARY_STATUS_MOVE_EFFECT) + if (!primary && affectsUser != MOVE_EFFECT_AFFECTS_USER + && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) + && (battlerAbility == ABILITY_SHIELD_DUST || GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_COVERT_CLOAK)) { + if (battlerAbility == ABILITY_SHIELD_DUST) + RecordAbilityBattle(gEffectBattler, battlerAbility); + else + RecordItemEffectBattle(gEffectBattler, HOLD_EFFECT_COVERT_CLOAK); + INCREMENT_RESET_RETURN + } + + if (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) + && !primary && gBattleScripting.moveEffect <= MOVE_EFFECT_CONFUSION) + INCREMENT_RESET_RETURN + + if (!(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) + && TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove) + && !primary + && gBattleScripting.moveEffect != MOVE_EFFECT_CHARGING) + INCREMENT_RESET_RETURN + + if (gBattleMons[gEffectBattler].hp == 0 && !activateAfterFaint) + INCREMENT_RESET_RETURN + + if (DoesSubstituteBlockMove(gBattlerAttacker, gEffectBattler, gCurrentMove) && affectsUser != MOVE_EFFECT_AFFECTS_USER) + INCREMENT_RESET_RETURN + + if (gBattleScripting.moveEffect <= PRIMARY_STATUS_MOVE_EFFECT) // status change + { + const u8 *cancelMultiTurnMovesResult = NULL; switch (sStatusFlagsForMoveEffects[gBattleScripting.moveEffect]) { case STATUS1_SLEEP: // check active uproar - if (gBattleMons[gEffectBattler].ability != ABILITY_SOUNDPROOF) + if (battlerAbility != ABILITY_SOUNDPROOF || B_UPROAR_IGNORE_SOUNDPROOF >= GEN_5) { - for (gActiveBattler = 0; - gActiveBattler < gBattlersCount && !(gBattleMons[gActiveBattler].status2 & STATUS2_UPROAR); - gActiveBattler++) - {} + for (i = 0; i < gBattlersCount && !(gBattleMons[i].status2 & STATUS2_UPROAR); i++) + ; } else + { + i = gBattlersCount; gActiveBattler = gBattlersCount; + } - if (gBattleMons[gEffectBattler].status1) + if (i != gBattlersCount) break; - if (gActiveBattler != gBattlersCount) - break; - if (gBattleMons[gEffectBattler].ability == ABILITY_VITAL_SPIRIT) - break; - if (gBattleMons[gEffectBattler].ability == ABILITY_INSOMNIA) + if (!CanSleep(gEffectBattler)) break; - CancelMultiTurnMoves(gEffectBattler); + cancelMultiTurnMovesResult = CancelMultiTurnMoves(gEffectBattler); + if (cancelMultiTurnMovesResult) + gBattlescriptCurrInstr = cancelMultiTurnMovesResult; statusChanged = TRUE; break; case STATUS1_POISON: - if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY - && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) + if ((battlerAbility == ABILITY_IMMUNITY || battlerAbility == ABILITY_PASTEL_VEIL) + && (primary == TRUE || certain == TRUE)) { - gLastUsedAbility = ABILITY_IMMUNITY; - RecordAbilityBattle(gEffectBattler, ABILITY_IMMUNITY); + gLastUsedAbility = battlerAbility; + RecordAbilityBattle(gEffectBattler, battlerAbility); BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_PSNPrevention; @@ -2706,35 +2950,29 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_STATUS; } - return; + RESET_RETURN } - if ((IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON) || IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL)) + if (!CanPoisonType(gBattleScripting.battler, gEffectBattler) && (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) - && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) + && (primary == TRUE || certain == TRUE)) { BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_PSNPrevention; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STATUS_HAD_NO_EFFECT; - return; + RESET_RETURN } - if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON)) - break; - if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL)) - break; - if (gBattleMons[gEffectBattler].status1) - break; - if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY) + if (!CanBePoisoned(gBattleScripting.battler, gEffectBattler)) break; statusChanged = TRUE; break; case STATUS1_BURN: - if (gBattleMons[gEffectBattler].ability == ABILITY_WATER_VEIL - && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) + if ((battlerAbility == ABILITY_WATER_VEIL || battlerAbility == ABILITY_WATER_BUBBLE) + && (primary == TRUE || certain == TRUE)) { - gLastUsedAbility = ABILITY_WATER_VEIL; - RecordAbilityBattle(gEffectBattler, ABILITY_WATER_VEIL); + gLastUsedAbility = battlerAbility; + RecordAbilityBattle(gEffectBattler, battlerAbility); BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_BRNPrevention; @@ -2747,46 +2985,52 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_STATUS; } - return; + RESET_RETURN } if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE) && (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) - && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) + && (primary == TRUE || certain == TRUE)) { BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_BRNPrevention; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STATUS_HAD_NO_EFFECT; - return; + RESET_RETURN } - if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE)) - break; - if (gBattleMons[gEffectBattler].ability == ABILITY_WATER_VEIL) - break; - if (gBattleMons[gEffectBattler].status1) + + if (B_STATUS_TYPE_IMMUNITY == GEN_1) + { + u8 moveType = 0; + GET_MOVE_TYPE(gCurrentMove, moveType); + if (primary == FALSE && certain == FALSE && IS_BATTLER_OF_TYPE(gEffectBattler, moveType)) + break; + } + + if (!CanBeBurned(gEffectBattler)) break; statusChanged = TRUE; break; case STATUS1_FREEZE: - if (WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_SUN) - noSunCanFreeze = FALSE; - if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_ICE)) - break; - if (gBattleMons[gEffectBattler].status1) - break; - if (noSunCanFreeze == FALSE) - break; - if (gBattleMons[gEffectBattler].ability == ABILITY_MAGMA_ARMOR) + if (B_STATUS_TYPE_IMMUNITY == GEN_1) + { + u8 moveType = 0; + GET_MOVE_TYPE(gCurrentMove, moveType); + if (primary == FALSE && certain == FALSE && IS_BATTLER_OF_TYPE(gEffectBattler, moveType)) + break; + } + if (!CanBeFrozen(gEffectBattler)) break; - CancelMultiTurnMoves(gEffectBattler); + cancelMultiTurnMovesResult = CancelMultiTurnMoves(gEffectBattler); + if (cancelMultiTurnMovesResult) + gBattlescriptCurrInstr = cancelMultiTurnMovesResult; statusChanged = TRUE; break; case STATUS1_PARALYSIS: - if (gBattleMons[gEffectBattler].ability == ABILITY_LIMBER) + if (battlerAbility == ABILITY_LIMBER) { - if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN) + if (primary == TRUE || certain == TRUE) { gLastUsedAbility = ABILITY_LIMBER; RecordAbilityBattle(gEffectBattler, ABILITY_LIMBER); @@ -2803,21 +3047,41 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_STATUS; } - return; + RESET_RETURN } else break; } - if (gBattleMons[gEffectBattler].status1) + if (B_STATUS_TYPE_IMMUNITY == GEN_1) + { + u8 moveType = 0; + GET_MOVE_TYPE(gCurrentMove, moveType); + if (primary == FALSE && certain == FALSE && IS_BATTLER_OF_TYPE(gEffectBattler, moveType)) + break; + } + if (!CanParalyzeType(gBattleScripting.battler, gEffectBattler) + && (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) + && (primary == TRUE || certain == TRUE)) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_PRLZPrevention; + + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + RESET_RETURN + } + if (!CanParalyzeType(gBattleScripting.battler, gEffectBattler)) + break; + if (!CanBeParalyzed(gEffectBattler)) break; statusChanged = TRUE; break; case STATUS1_TOXIC_POISON: - if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) + if ((battlerAbility == ABILITY_IMMUNITY || battlerAbility == ABILITY_PASTEL_VEIL) + && (primary == TRUE || certain == TRUE)) { - gLastUsedAbility = ABILITY_IMMUNITY; - RecordAbilityBattle(gEffectBattler, ABILITY_IMMUNITY); + gLastUsedAbility = battlerAbility; + RecordAbilityBattle(gEffectBattler, battlerAbility); BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_PSNPrevention; @@ -2831,27 +3095,22 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_STATUS; } - return; + RESET_RETURN } - if ((IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON) || IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL)) + if (!CanPoisonType(gBattleScripting.battler, gEffectBattler) && (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) - && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) + && (primary == TRUE || certain == TRUE)) { BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_PSNPrevention; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STATUS_HAD_NO_EFFECT; - return; + RESET_RETURN } - if (gBattleMons[gEffectBattler].status1) { + if (gBattleMons[gEffectBattler].status1) break; - } - if (!IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON) && !IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL)) + if (CanBePoisoned(gBattleScripting.battler, gEffectBattler)) { - if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY) { - break; - } - // It's redundant, because at this point we know the status1 value is 0. gBattleMons[gEffectBattler].status1 &= ~STATUS1_TOXIC_POISON; gBattleMons[gEffectBattler].status1 &= ~STATUS1_POISON; @@ -2863,21 +3122,41 @@ void SetMoveEffect(bool32 primary, u32 certain) gMoveResultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE; } break; + case STATUS1_FROSTBITE: + if (B_STATUS_TYPE_IMMUNITY == GEN_1) + { + u8 moveType = 0; + GET_MOVE_TYPE(gCurrentMove, moveType); + if (primary == FALSE && certain == FALSE && IS_BATTLER_OF_TYPE(gEffectBattler, moveType)) + break; + } + if (!CanGetFrostbite(gEffectBattler)) + break; + + statusChanged = TRUE; + break; } if (statusChanged == TRUE) { BattleScriptPush(gBattlescriptCurrInstr + 1); if (sStatusFlagsForMoveEffects[gBattleScripting.moveEffect] == STATUS1_SLEEP) - gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN((Random() & 3) + 2); // 2-5 turns + { + if (B_SLEEP_TURNS >= GEN_5) + gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 1, 3)); + else + gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 2, 5)); + } else + { gBattleMons[gEffectBattler].status1 |= sStatusFlagsForMoveEffects[gBattleScripting.moveEffect]; + } gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; gActiveBattler = gEffectBattler; BtlController_EmitSetMonData(BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].status1), &gBattleMons[gEffectBattler].status1); - MarkBattlerForControllerExec(gActiveBattler); + MarkBattlerForControllerExec(gEffectBattler); if (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) { @@ -2896,14 +3175,16 @@ void SetMoveEffect(bool32 primary, u32 certain) || gBattleScripting.moveEffect == MOVE_EFFECT_PARALYSIS || gBattleScripting.moveEffect == MOVE_EFFECT_BURN) { - u16 *synchronizeEffect = &gBattleStruct->synchronizeMoveEffect; - *synchronizeEffect = gBattleScripting.moveEffect; + gBattleStruct->synchronizeMoveEffect = gBattleScripting.moveEffect; gHitMarker |= HITMARKER_SYNCHRONISE_EFFECT; } + return; } else if (statusChanged == FALSE) { + gBattleScripting.moveEffect = 0; gBattlescriptCurrInstr++; + return; } return; } @@ -2919,8 +3200,7 @@ void SetMoveEffect(bool32 primary, u32 certain) switch (gBattleScripting.moveEffect) { case MOVE_EFFECT_CONFUSION: - if (gBattleMons[gEffectBattler].ability == ABILITY_OWN_TEMPO - || gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION) + if (!CanBeConfused(gEffectBattler)) { gBattlescriptCurrInstr++; } @@ -2928,16 +3208,30 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleMons[gEffectBattler].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); // 2-5 turns - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; + // If the confusion is activating due to being released from Sky Drop, go to "confused due to fatigue" script. + // Otherwise, do normal confusion script. + if(gCurrentMove == MOVE_SKY_DROP) + { + gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattlerAttacker = gEffectBattler; + gBattlescriptCurrInstr = BattleScript_ThrashConfuses; + } + else + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; + } } break; case MOVE_EFFECT_FLINCH: - if (gBattleMons[gEffectBattler].ability == ABILITY_INNER_FOCUS) + if (battlerAbility == ABILITY_INNER_FOCUS) { - if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN) + // Inner Focus ALWAYS prevents flinching but only activates + // on a move that's supposed to flinch, like Fake Out + if (primary == TRUE || certain == TRUE) { gLastUsedAbility = ABILITY_INNER_FOCUS; + gBattlerAbility = gEffectBattler; RecordAbilityBattle(gEffectBattler, ABILITY_INNER_FOCUS); gBattlescriptCurrInstr = BattleScript_FlinchPrevention; } @@ -2946,10 +3240,10 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattlescriptCurrInstr++; } } - else + else if (GetBattlerTurnOrderNum(gEffectBattler) > gCurrentTurnActionNumber + /* && !IsDynamaxed(gEffectBattler) */) // TODO: Dynamax { - if (GetBattlerTurnOrderNum(gEffectBattler) > gCurrentTurnActionNumber) - gBattleMons[gEffectBattler].status2 |= sStatusFlagsForMoveEffects[gBattleScripting.moveEffect]; + gBattleMons[gEffectBattler].status2 |= sStatusFlagsForMoveEffects[gBattleScripting.moveEffect]; gBattlescriptCurrInstr++; } break; @@ -2958,7 +3252,7 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS; gLockedMoves[gEffectBattler] = gCurrentMove; - gBattleMons[gEffectBattler].status2 |= STATUS2_UPROAR_TURN((Random() & 3) + 2); // 2-5 turns + gBattleMons[gEffectBattler].status2 |= STATUS2_UPROAR_TURN(B_UPROAR_TURNS >= GEN_5 ? 3 : (Random() & 3) + 2); BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; @@ -2969,15 +3263,38 @@ void SetMoveEffect(bool32 primary, u32 certain) } break; case MOVE_EFFECT_PAYDAY: - if (GET_BATTLER_SIDE(gBattlerAttacker) == B_SIDE_PLAYER) + // Don't scatter coins on the second hit of Parental Bond + if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && gSpecialStatuses[gBattlerAttacker].parentalBondState!= PARENTAL_BOND_2ND_HIT) { u16 payday = gPaydayMoney; + u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); gPaydayMoney += (gBattleMons[gBattlerAttacker].level * 5); if (payday > gPaydayMoney) gPaydayMoney = 0xFFFF; + + // For a move that hits multiple targets (i.e. Make it Rain) + // we only want to print the message on the final hit + if (!((moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY) + && GetNextTarget(moveTarget, TRUE) != MAX_BATTLERS_COUNT)) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectPayDay; + } + else + gBattlescriptCurrInstr++; } - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; + else + { + gBattlescriptCurrInstr++; + } + break; + case MOVE_EFFECT_HAPPY_HOUR: + if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && !gBattleStruct->moneyMultiplierMove) + { + gBattleStruct->moneyMultiplier *= 2; + gBattleStruct->moneyMultiplierMove = 1; + } + gBattlescriptCurrInstr++; break; case MOVE_EFFECT_TRI_ATTACK: if (gBattleMons[gEffectBattler].status1) @@ -2986,14 +3303,20 @@ void SetMoveEffect(bool32 primary, u32 certain) } else { - gBattleScripting.moveEffect = Random() % 3 + 3; - SetMoveEffect(FALSE, 0); + static const u8 sTriAttackEffects[] = + { + MOVE_EFFECT_BURN, + MOVE_EFFECT_FREEZE_OR_FROSTBITE, + MOVE_EFFECT_PARALYSIS + }; + gBattleScripting.moveEffect = RandomElement(RNG_TRI_ATTACK, sTriAttackEffects); + SetMoveEffect(primary, certain); } break; case MOVE_EFFECT_CHARGING: gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS; gLockedMoves[gEffectBattler] = gCurrentMove; - gProtectStructs[gEffectBattler].chargingTurn = 1; + gProtectStructs[gEffectBattler].chargingTurn = TRUE; gBattlescriptCurrInstr++; break; case MOVE_EFFECT_WRAP: @@ -3009,30 +3332,19 @@ void SetMoveEffect(bool32 primary, u32 certain) else gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? (Random() % 2) + 4 : (Random() % 4) + 2; - *(gBattleStruct->wrappedMove + gEffectBattler * 2 + 0) = gCurrentMove; - *(gBattleStruct->wrappedMove + gEffectBattler * 2 + 1) = gCurrentMove >> 8; - *(gBattleStruct->wrappedBy + gEffectBattler) = gBattlerAttacker; + gBattleStruct->wrappedMove[gEffectBattler] = gCurrentMove; + gBattleStruct->wrappedBy[gEffectBattler] = gBattlerAttacker; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; - for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; ; gBattleCommunication[MULTISTRING_CHOOSER]++) + for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; gBattleCommunication[MULTISTRING_CHOOSER] < NUM_TRAPPING_MOVES; gBattleCommunication[MULTISTRING_CHOOSER]++) { - if (gBattleCommunication[MULTISTRING_CHOOSER] >= NUM_TRAPPING_MOVES - 1) - break; - if (gTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove) + if (sTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove) break; } } break; - case MOVE_EFFECT_RECOIL_25: // 25% recoil - gBattleMoveDamage = (gHpDealt) / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; - break; case MOVE_EFFECT_ATK_PLUS_1: case MOVE_EFFECT_DEF_PLUS_1: case MOVE_EFFECT_SPD_PLUS_1: @@ -3040,9 +3352,10 @@ void SetMoveEffect(bool32 primary, u32 certain) case MOVE_EFFECT_SP_DEF_PLUS_1: case MOVE_EFFECT_ACC_PLUS_1: case MOVE_EFFECT_EVS_PLUS_1: - if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1), + if (NoAliveMonsForEitherParty() + || ChangeStatBuffs(SET_STAT_BUFF_VALUE(1), gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_1 + 1, - affectsUser, 0)) + affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT, 0)) { gBattlescriptCurrInstr++; } @@ -3061,11 +3374,18 @@ void SetMoveEffect(bool32 primary, u32 certain) case MOVE_EFFECT_SP_DEF_MINUS_1: case MOVE_EFFECT_ACC_MINUS_1: case MOVE_EFFECT_EVS_MINUS_1: + flags = affectsUser; + if (mirrorArmorReflected) + flags |= (STAT_CHANGE_ALLOW_PTR * !affectsUser); + else + flags |= STAT_CHANGE_UPDATE_MOVE_EFFECT; + if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE, gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1, - affectsUser, 0)) + flags, gBattlescriptCurrInstr + 1)) { - gBattlescriptCurrInstr++; + if (!mirrorArmorReflected) + gBattlescriptCurrInstr++; } else { @@ -3082,9 +3402,10 @@ void SetMoveEffect(bool32 primary, u32 certain) case MOVE_EFFECT_SP_DEF_PLUS_2: case MOVE_EFFECT_ACC_PLUS_2: case MOVE_EFFECT_EVS_PLUS_2: - if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2), + if (NoAliveMonsForEitherParty() + || ChangeStatBuffs(SET_STAT_BUFF_VALUE(2), gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_2 + 1, - affectsUser, 0)) + affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT, 0)) { gBattlescriptCurrInstr++; } @@ -3103,11 +3424,15 @@ void SetMoveEffect(bool32 primary, u32 certain) case MOVE_EFFECT_SP_DEF_MINUS_2: case MOVE_EFFECT_ACC_MINUS_2: case MOVE_EFFECT_EVS_MINUS_2: + flags = affectsUser; + if (mirrorArmorReflected && !affectsUser) + flags |= STAT_CHANGE_ALLOW_PTR; if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE, gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1, - affectsUser, 0)) + flags | STAT_CHANGE_UPDATE_MOVE_EFFECT, gBattlescriptCurrInstr + 1)) { - gBattlescriptCurrInstr++; + if (!mirrorArmorReflected) + gBattlescriptCurrInstr++; } else { @@ -3129,7 +3454,7 @@ void SetMoveEffect(bool32 primary, u32 certain) break; case MOVE_EFFECT_STEAL_ITEM: { - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER) + if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item)) { gBattlescriptCurrInstr++; break; @@ -3155,38 +3480,27 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattlescriptCurrInstr++; } else if (gBattleMons[gBattlerTarget].item - && gBattleMons[gBattlerTarget].ability == ABILITY_STICKY_HOLD) + && GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) { - gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_NoItemSteal; + gLastUsedAbility = gBattleMons[gBattlerTarget].ability; RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); } else if (gBattleMons[gBattlerAttacker].item != ITEM_NONE - || gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY - || IS_ITEM_MAIL(gBattleMons[gBattlerTarget].item) + || gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY_E_READER || gBattleMons[gBattlerTarget].item == ITEM_NONE) { gBattlescriptCurrInstr++; } else { - u16 *changedItem = &gBattleStruct->changedItems[gBattlerAttacker]; - gLastUsedItem = *changedItem = gBattleMons[gBattlerTarget].item; - gBattleMons[gBattlerTarget].item = ITEM_NONE; - - gActiveBattler = gBattlerAttacker; - BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gLastUsedItem), &gLastUsedItem); - MarkBattlerForControllerExec(gBattlerAttacker); - - gActiveBattler = gBattlerTarget; - BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item); - MarkBattlerForControllerExec(gBattlerTarget); - + StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item + gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) + gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_ItemSteal; - - *(u8 *)((u8 *)(&gBattleStruct->choicedMove[gBattlerTarget]) + 0) = 0; - *(u8 *)((u8 *)(&gBattleStruct->choicedMove[gBattlerTarget]) + 1) = 0; } } break; @@ -3200,44 +3514,43 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattlescriptCurrInstr++; break; case MOVE_EFFECT_ALL_STATS_UP: - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_AllStatsUp; + if (!NoAliveMonsForEitherParty()) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_AllStatsUp; + } break; - case MOVE_EFFECT_RAPIDSPIN: + case MOVE_EFFECT_RAPID_SPIN: BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_RapidSpinAway; break; - case MOVE_EFFECT_REMOVE_PARALYSIS: // Smelling salts - if (!(gBattleMons[gBattlerTarget].status1 & STATUS1_PARALYSIS)) - { - gBattlescriptCurrInstr++; - } - else - { - gBattleMons[gBattlerTarget].status1 &= ~STATUS1_PARALYSIS; - - gActiveBattler = gBattlerTarget; - BtlController_EmitSetMonData(BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gActiveBattler].status1), &gBattleMons[gActiveBattler].status1); - MarkBattlerForControllerExec(gActiveBattler); - - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal; - } - break; case MOVE_EFFECT_ATK_DEF_DOWN: // SuperPower - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_AtkDefDown; + if (!NoAliveMonsForEitherParty()) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_AtkDefDown; + } break; - case MOVE_EFFECT_RECOIL_33: // Double Edge - gBattleMoveDamage = gHpDealt / 3; + case MOVE_EFFECT_DEF_SPDEF_DOWN: // Close Combat + if (!NoAliveMonsForEitherParty()) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_DefSpDefDown; + } + break; + case MOVE_EFFECT_RECOIL_HP_25: // Struggle + gBattleMoveDamage = (gBattleMons[gEffectBattler].maxHP) / 4; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; + if (GetBattlerAbility(gEffectBattler) == ABILITY_PARENTAL_BOND) + gBattleMoveDamage *= 2; BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; + gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; break; case MOVE_EFFECT_THRASH: - if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE) + // Petal Dance doesn't lock mons that copy the move with Dancer + if (gSpecialStatuses[gEffectBattler].dancerUsedMove) { gBattlescriptCurrInstr++; } @@ -3245,93 +3558,428 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS; gLockedMoves[gEffectBattler] = gCurrentMove; - gBattleMons[gEffectBattler].status2 |= STATUS2_LOCK_CONFUSE_TURN((Random() & 1) + 2); // thrash for 2-3 turns - } - break; - case MOVE_EFFECT_KNOCK_OFF: - if (gBattleMons[gEffectBattler].ability == ABILITY_STICKY_HOLD) - { - if (gBattleMons[gEffectBattler].item == ITEM_NONE) - { - gBattlescriptCurrInstr++; - } - else - { - gLastUsedAbility = ABILITY_STICKY_HOLD; - gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; - RecordAbilityBattle(gEffectBattler, ABILITY_STICKY_HOLD); - } - break; - } - if (gBattleMons[gEffectBattler].item) - { - side = GetBattlerSide(gEffectBattler); - - gLastUsedItem = gBattleMons[gEffectBattler].item; - gBattleMons[gEffectBattler].item = ITEM_NONE; - gWishFutureKnock.knockedOffMons[side] |= gBitTable[gBattlerPartyIndexes[gEffectBattler]]; - - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_KnockedOff; - - *(u8 *)((u8 *)(&gBattleStruct->choicedMove[gEffectBattler]) + 0) = 0; - *(u8 *)((u8 *)(&gBattleStruct->choicedMove[gEffectBattler]) + 1) = 0; - } - else - { - gBattlescriptCurrInstr++; + gBattleMons[gEffectBattler].status2 |= STATUS2_LOCK_CONFUSE_TURN(RandomUniform(RNG_RAMPAGE_TURNS, 2, 3)); } break; case MOVE_EFFECT_SP_ATK_TWO_DOWN: // Overheat + if (!NoAliveMonsForEitherParty()) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_SAtkDown2; + } + break; + case MOVE_EFFECT_CLEAR_SMOG: + for (i = 0; i < NUM_BATTLE_STATS; i++) + { + if (gBattleMons[gEffectBattler].statStages[i] != DEFAULT_STAT_STAGE) + break; + } + if ((gSpecialStatuses[gEffectBattler].physicalDmg || gSpecialStatuses[gEffectBattler].specialDmg) && i != NUM_BATTLE_STATS) + { + for (i = 0; i < NUM_BATTLE_STATS; i++) + gBattleMons[gEffectBattler].statStages[i] = DEFAULT_STAT_STAGE; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectClearSmog; + } + break; + case MOVE_EFFECT_FLAME_BURST: + if (IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)) + && !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_SEMI_INVULNERABLE) + && GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) != ABILITY_MAGIC_GUARD) + { + gBattleScripting.savedBattler = BATTLE_PARTNER(gBattlerTarget); + gBattleMoveDamage = gBattleMons[BATTLE_PARTNER(gBattlerTarget)].hp / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattlescriptCurrInstr = BattleScript_MoveEffectFlameBurst; + } + break; + case MOVE_EFFECT_FEINT: + if (IS_BATTLER_PROTECTED(gBattlerTarget)) + { + gProtectStructs[gBattlerTarget].protected = FALSE; + gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_WIDE_GUARD; + gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_QUICK_GUARD; + gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_CRAFTY_SHIELD; + gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_MAT_BLOCK; + gProtectStructs[gBattlerTarget].spikyShielded = FALSE; + gProtectStructs[gBattlerTarget].kingsShielded = FALSE; + gProtectStructs[gBattlerTarget].banefulBunkered = FALSE; + gProtectStructs[gBattlerTarget].obstructed = FALSE; + gProtectStructs[gBattlerTarget].silkTrapped = FALSE; + gProtectStructs[gBattlerAttacker].burningBulwarked = FALSE; + BattleScriptPush(gBattlescriptCurrInstr + 1); + if (gCurrentMove == MOVE_HYPERSPACE_FURY) + gBattlescriptCurrInstr = BattleScript_HyperspaceFuryRemoveProtect; + else + gBattlescriptCurrInstr = BattleScript_MoveEffectFeint; + } + break; + case MOVE_EFFECT_SPECTRAL_THIEF: + if (!NoAliveMonsForEitherParty()) + { + gBattleStruct->stolenStats[0] = 0; // Stats to steal. + gBattleScripting.animArg1 = 0; + for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) + { + if (gBattleMons[gBattlerTarget].statStages[i] > DEFAULT_STAT_STAGE && gBattleMons[gBattlerAttacker].statStages[i] != MAX_STAT_STAGE) + { + bool32 byTwo = FALSE; + + gBattleStruct->stolenStats[0] |= gBitTable[i]; + // Store by how many stages to raise the stat. + gBattleStruct->stolenStats[i] = gBattleMons[gBattlerTarget].statStages[i] - DEFAULT_STAT_STAGE; + while (gBattleMons[gBattlerAttacker].statStages[i] + gBattleStruct->stolenStats[i] > MAX_STAT_STAGE) + gBattleStruct->stolenStats[i]--; + gBattleMons[gBattlerTarget].statStages[i] = DEFAULT_STAT_STAGE; + + if (gBattleStruct->stolenStats[i] >= 2) + byTwo++; + + if (gBattleScripting.animArg1 == 0) + { + if (byTwo) + gBattleScripting.animArg1 = STAT_ANIM_PLUS2 + i; + else + gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + i; + } + else + { + if (byTwo) + gBattleScripting.animArg1 = STAT_ANIM_MULTIPLE_PLUS2; + else + gBattleScripting.animArg1 = STAT_ANIM_MULTIPLE_PLUS1; + } + } + } + + if (gBattleStruct->stolenStats[0] != 0) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_SpectralThiefSteal; + } + } + break; + case MOVE_EFFECT_V_CREATE: + if (!NoAliveMonsForEitherParty()) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_VCreateStatLoss; + } + break; + case MOVE_EFFECT_CORE_ENFORCER: + if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget) + && !NoAliveMonsForEitherParty()) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectCoreEnforcer; + } + break; + case MOVE_EFFECT_THROAT_CHOP: + gDisableStructs[gEffectBattler].throatChopTimer = 2; + gBattlescriptCurrInstr++; + break; + case MOVE_EFFECT_INCINERATE: + if ((gBattleMons[gEffectBattler].item >= FIRST_BERRY_INDEX && gBattleMons[gEffectBattler].item <= LAST_BERRY_INDEX) + || (B_INCINERATE_GEMS >= GEN_6 && GetBattlerHoldEffect(gEffectBattler, FALSE) == HOLD_EFFECT_GEMS)) + { + gLastUsedItem = gBattleMons[gEffectBattler].item; + gBattleMons[gEffectBattler].item = 0; + CheckSetUnburden(gEffectBattler); + + gActiveBattler = gEffectBattler; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].item), &gBattleMons[gEffectBattler].item); + MarkBattlerForControllerExec(gEffectBattler); + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectIncinerate; + } + break; + case MOVE_EFFECT_BUG_BITE: + if (ItemId_GetPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRY_POUCH + && battlerAbility != ABILITY_STICKY_HOLD) + { + // target loses their berry + gLastUsedItem = gBattleMons[gEffectBattler].item; + gBattleMons[gEffectBattler].item = 0; + CheckSetUnburden(gEffectBattler); + + gActiveBattler = gEffectBattler; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].item), &gBattleMons[gEffectBattler].item); + MarkBattlerForControllerExec(gEffectBattler); + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite; + } + break; + case MOVE_EFFECT_TRAP_BOTH: + if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION)) + { + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_BothCanNoLongerEscape; + } + if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION)) + gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; + + if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION)) + gDisableStructs[gBattlerAttacker].battlerPreventingEscape = gBattlerTarget; + + gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[gBattlerAttacker].status2 |= STATUS2_ESCAPE_PREVENTION; + break; + case MOVE_EFFECT_REMOVE_ARG_TYPE: + // This seems unnecessary but is done to make it work properly with Parental Bond BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_SAtkDown2; + switch (gMovesInfo[gCurrentMove].argument) + { + case TYPE_FIRE: // Burn Up + gBattlescriptCurrInstr = BattleScript_RemoveFireType; + break; + case TYPE_ELECTRIC: // Double Shot + gBattlescriptCurrInstr = BattleScript_RemoveElectricType; + break; + default: + gBattlescriptCurrInstr = BattleScript_RemoveGenericType; + break; + } + RemoveBattlerType(gEffectBattler, gMovesInfo[gCurrentMove].argument); + break; + case MOVE_EFFECT_ROUND: + TryUpdateRoundTurnOrder(); // If another Pokémon uses Round before the user this turn, the user will use Round directly after it + gBattlescriptCurrInstr++; + break; + case MOVE_EFFECT_DIRE_CLAW: + if (!gBattleMons[gEffectBattler].status1) + { + static const u8 sDireClawEffects[] = { MOVE_EFFECT_POISON, MOVE_EFFECT_PARALYSIS, MOVE_EFFECT_SLEEP }; + gBattleScripting.moveEffect = RandomElement(RNG_DIRE_CLAW, sDireClawEffects); + SetMoveEffect(primary, certain); + } + break; + case MOVE_EFFECT_STEALTH_ROCK: + if (!(gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_STEALTH_ROCK)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_StealthRockActivates; + } + break; + case MOVE_EFFECT_SPIKES: + if (gSideTimers[GetBattlerSide(gEffectBattler)].spikesAmount < 3) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED; + BattleScriptPush(gBattlescriptCurrInstr + 1); + + if (gBattleStruct->isSkyBattle) + gBattlescriptCurrInstr++; + else + gBattlescriptCurrInstr = BattleScript_SpikesActivates; + } + break; + case MOVE_EFFECT_SYRUP_BOMB: + if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB)) + { + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); + + gStatuses4[gEffectBattler] |= STATUS4_SYRUP_BOMB; + gDisableStructs[gEffectBattler].syrupBombTimer = 3; + gDisableStructs[gEffectBattler].syrupBombIsShiny = IsMonShiny(&party[gBattlerPartyIndexes[gBattlerAttacker]]); + gBattleStruct->stickySyrupdBy[gEffectBattler] = gBattlerAttacker; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_SyrupBombActivates; + } + break; + case MOVE_EFFECT_SECRET_POWER: + if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + { + switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + { + case STATUS_FIELD_MISTY_TERRAIN: + gBattleScripting.moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1; + break; + case STATUS_FIELD_GRASSY_TERRAIN: + gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP; + break; + case STATUS_FIELD_ELECTRIC_TERRAIN: + gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; + break; + case STATUS_FIELD_PSYCHIC_TERRAIN: + gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1; + break; + default: + gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; + break; + } + } + else + { + switch (gBattleTerrain) + { + case BATTLE_TERRAIN_GRASS: + gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON); + break; + case BATTLE_TERRAIN_UNDERWATER: + gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1); + break; + case BATTLE_TERRAIN_POND: + gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1); + break; + case BATTLE_TERRAIN_MOUNTAIN: + if (B_SECRET_POWER_EFFECT >= GEN_5) + gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1; + else if (B_SECRET_POWER_EFFECT >= GEN_4) + gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; + else + gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; + break; + case BATTLE_TERRAIN_PUDDLE: + gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1); + break; + case BATTLE_TERRAIN_LONG_GRASS: + gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP; + break; + case BATTLE_TERRAIN_SAND: + gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1; + break; + case BATTLE_TERRAIN_WATER: + gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; + break; + case BATTLE_TERRAIN_CAVE: + case BATTLE_TERRAIN_BURIAL_GROUND: + case BATTLE_TERRAIN_SPACE: + gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; + break; + case BATTLE_TERRAIN_SOARING: + case BATTLE_TERRAIN_SKY_PILLAR: + case BATTLE_TERRAIN_MARSH: + case BATTLE_TERRAIN_SWAMP: + gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1; + break; + case BATTLE_TERRAIN_SNOW: + case BATTLE_TERRAIN_ICE: + gBattleScripting.moveEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE; + break; + case BATTLE_TERRAIN_VOLCANO: + gBattleScripting.moveEffect = MOVE_EFFECT_BURN; + break; + case BATTLE_TERRAIN_ULTRA_SPACE: + gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_1; + break; + default: + gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; + break; + } + } + SetMoveEffect(primary, certain); + break; + case MOVE_EFFECT_PSYCHIC_NOISE: + battlerAbility = IsAbilityOnSide(gEffectBattler, ABILITY_AROMA_VEIL); + + if (battlerAbility) + { + gBattlerAbility = battlerAbility - 1; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_AromaVeilProtectsRet; + } + else if (!(gStatuses3[gEffectBattler] & STATUS3_HEAL_BLOCK)) + { + gStatuses3[gEffectBattler] |= STATUS3_HEAL_BLOCK; + gDisableStructs[gEffectBattler].healBlockTimer = 2; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_EffectPsychicNoise; + } break; } } } + + gBattleScripting.moveEffect = 0; } -static void Cmd_seteffectwithchance(void) +static bool32 CanApplyAdditionalEffect(const struct AdditionalEffect *additionalEffect) { - u32 percentChance; - - percentChance = CalcSecondaryEffectChance(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), gMovesInfo[gCurrentMove].additionalEffects); - // if (gBattleMons[gBattlerAttacker].ability == ABILITY_SERENE_GRACE) - // percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance * 2; - // else - // percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance; + // Self-targeting move effects only apply after the last mon has been hit + u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); + if (additionalEffect->self + && (moveTarget == MOVE_TARGET_BOTH || moveTarget == MOVE_TARGET_FOES_AND_ALLY) + && GetNextTarget(moveTarget, TRUE) != MAX_BATTLERS_COUNT) + return FALSE; - if (gBattleScripting.moveEffect & MOVE_EFFECT_CERTAIN - && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + // Certain move effects only apply if the target raised stats this turn (e.g. Burning Jealousy) + if (additionalEffect->onlyIfTargetRaisedStats && !gProtectStructs[gBattlerTarget].statRaised) + return FALSE; + + // Certain additional effects only apply on a two-turn move's charge turn + if (additionalEffect->onChargeTurnOnly != gProtectStructs[gBattlerAttacker].chargingTurn) + return FALSE; + + return TRUE; +} + +static void Cmd_setadditionaleffects(void) +{ + CMD_ARGS(); + + if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { - gBattleScripting.moveEffect &= ~MOVE_EFFECT_CERTAIN; - SetMoveEffect(FALSE, MOVE_EFFECT_CERTAIN); - } - else if (Random() % 100 <= percentChance - && gBattleScripting.moveEffect - && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) - { - if (percentChance >= 100) - SetMoveEffect(FALSE, MOVE_EFFECT_CERTAIN); + if (gMovesInfo[gCurrentMove].numAdditionalEffects > gBattleStruct->additionalEffectsCounter) + { + u32 percentChance; + const struct AdditionalEffect *additionalEffect = &gMovesInfo[gCurrentMove].additionalEffects[gBattleStruct->additionalEffectsCounter]; + const u8 *currentPtr = gBattlescriptCurrInstr; + + // Various checks for if this move effect can be applied this turn + if (CanApplyAdditionalEffect(additionalEffect)) + { + percentChance = CalcSecondaryEffectChance(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), additionalEffect); + + // Activate effect if it's primary (chance == 0) or if RNGesus says so + if ((percentChance == 0) || RandomPercentage(RNG_SECONDARY_EFFECT + gBattleStruct->additionalEffectsCounter, percentChance)) + { + gBattleScripting.moveEffect = additionalEffect->moveEffect | (MOVE_EFFECT_AFFECTS_USER * (additionalEffect->self)); + + SetMoveEffect( + percentChance == 0, // a primary effect + percentChance >= 100 // certain to happen + ); + } + } + + // Move script along if we haven't jumped elsewhere + if (gBattlescriptCurrInstr == currentPtr) + gBattlescriptCurrInstr = cmd->nextInstr; + + // Call setadditionaleffects again in the case of a move with multiple effects + gBattleStruct->additionalEffectsCounter++; + if (gMovesInfo[gCurrentMove].numAdditionalEffects > gBattleStruct->additionalEffectsCounter) + gBattleScripting.moveEffect = MOVE_EFFECT_CONTINUE; + else + gBattleScripting.moveEffect = gBattleStruct->additionalEffectsCounter = 0; + } else - SetMoveEffect(FALSE, 0); + { + gBattleScripting.moveEffect = 0; + gBattlescriptCurrInstr = cmd->nextInstr; + } } else { - gBattlescriptCurrInstr++; + gBattleScripting.moveEffect = 0; + gBattlescriptCurrInstr = cmd->nextInstr; } - gBattleScripting.moveEffect = 0; gBattleScripting.multihitMoveEffect = 0; } static void Cmd_seteffectprimary(void) { + CMD_ARGS(); + SetMoveEffect(TRUE, FALSE); } static void Cmd_seteffectsecondary(void) { + CMD_ARGS(); + SetMoveEffect(FALSE, FALSE); } @@ -4582,6 +5230,30 @@ static void Cmd_playstatchangeanimation(void) } } +#define SYMBIOSIS_CHECK(battler, ally) \ + GetBattlerAbility(ally) == ABILITY_SYMBIOSIS \ + && gBattleMons[battler].item == ITEM_NONE \ + && gBattleMons[ally].item != ITEM_NONE \ + && CanBattlerGetOrLoseItem(battler, gBattleMons[ally].item) \ + && CanBattlerGetOrLoseItem(ally, gBattleMons[ally].item) \ + && gBattleMons[battler].hp != 0 \ + && gBattleMons[ally].hp != 0 + +static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent) +{ + u32 i; + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (i != gBattlerAttacker + && !(excludeCurrent && i == gBattlerTarget) + && IsBattlerAlive(i) + && !(gBattleStruct->targetsDone[gBattlerAttacker] & gBitTable[i]) + && (GetBattlerSide(i) != GetBattlerSide(gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) + break; + } + return i; +} + static void Cmd_moveend(void) { s32 i; @@ -4709,7 +5381,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_KINGSROCK_SHELLBELL: // king's rock and shell bell - if (ItemBattleEffects(ITEMEFFECT_KINGSROCK_SHELLBELL, 0, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) effect = TRUE; gBattleScripting.moveendState++; break; @@ -6583,7 +7255,7 @@ static void Cmd_useitemonopponent(void) static void Cmd_various(void) { CMD_ARGS(u8 battler, u8 id); - u8 side; + u32 side, battler; s32 i; u32 monToCheck, status; u16 species; @@ -6591,6 +7263,7 @@ static void Cmd_various(void) struct Pokemon *mon; gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); + battler = gActiveBattler; switch (gBattlescriptCurrInstr[2]) { @@ -6779,7 +7452,6 @@ static void Cmd_various(void) case VARIOUS_HANDLE_FORM_CHANGE: { VARIOUS_ARGS(u8 case_); - u32 battler = gActiveBattler; if (GetBattlerSide(battler) == B_SIDE_OPPONENT) mon = &gEnemyParty[gBattlerPartyIndexes[battler]]; else @@ -6808,6 +7480,90 @@ static void Cmd_various(void) gBattlescriptCurrInstr = cmd->nextInstr; return; } + case VARIOUS_SAVE_TARGET: + { + VARIOUS_ARGS(); + gBattleStruct->savedBattlerTarget = gBattlerTarget; + break; + } + case VARIOUS_RESTORE_TARGET: + { + VARIOUS_ARGS(); + gBattlerTarget = gBattleStruct->savedBattlerTarget; + break; + } + case VARIOUS_SPECTRAL_THIEF: + { + VARIOUS_ARGS(); + // Raise stats + for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) + { + if (gBattleStruct->stolenStats[0] & gBitTable[i]) + { + gBattleStruct->stolenStats[0] &= ~(gBitTable[i]); + SET_STATCHANGER(i, gBattleStruct->stolenStats[i], FALSE); + if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), i, MOVE_EFFECT_CERTAIN | MOVE_EFFECT_AFFECTS_USER, NULL) == STAT_CHANGE_WORKED) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StatUpMsg; + return; + } + } + } + break; + } + case VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER: + { + bool8 shouldNotClear = FALSE; + + for (i = 0; i < gBattlersCount; i++) + { + u32 ability = GetBattlerAbility(i); + if (((ability == ABILITY_DESOLATE_LAND && gBattleWeather & B_WEATHER_SUN_PRIMAL) + || (ability == ABILITY_PRIMORDIAL_SEA && gBattleWeather & B_WEATHER_RAIN_PRIMAL) + || (ability == ABILITY_DELTA_STREAM && gBattleWeather & B_WEATHER_STRONG_WINDS)) + && IsBattlerAlive(i)) + shouldNotClear = TRUE; + } + if (gBattleWeather & B_WEATHER_SUN_PRIMAL && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_SUN_PRIMAL; + PrepareStringBattle(STRINGID_EXTREMESUNLIGHTFADED, battler); + gBattleCommunication[MSG_DISPLAY] = 1; + } + else if (gBattleWeather & B_WEATHER_RAIN_PRIMAL && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_RAIN_PRIMAL; + PrepareStringBattle(STRINGID_HEAVYRAINLIFTED, battler); + gBattleCommunication[MSG_DISPLAY] = 1; + } + else if (gBattleWeather & B_WEATHER_STRONG_WINDS && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_STRONG_WINDS; + PrepareStringBattle(STRINGID_STRONGWINDSDISSIPATED, battler); + gBattleCommunication[MSG_DISPLAY] = 1; + } + break; + } + case VARIOUS_CONSUME_BERRY: + { + VARIOUS_ARGS(bool8 fromBattler); + if (gBattleScripting.overrideBerryRequirements == 2) + { + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + + if (cmd->fromBattler) + gLastUsedItem = gBattleMons[battler].item; + + gBattleStruct->ateBerry[battler & BIT_SIDE] |= gBitTable[gBattlerPartyIndexes[battler]]; + gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID + if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler, FALSE)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } } gBattlescriptCurrInstr += 3; @@ -7246,9 +8002,6 @@ static void Cmd_negativedamage(void) gBattlescriptCurrInstr++; } -#define STAT_CHANGE_WORKED 0 -#define STAT_CHANGE_DIDNT_WORK 1 - static u8 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr) { bool32 certain = FALSE; @@ -9548,17 +10301,22 @@ static void Cmd_trysetroots(void) } } -static void Cmd_doubledamagedealtifdamaged(void) +static void Cmd_setgastroacid(void) { - if ((gProtectStructs[gBattlerAttacker].physicalDmg != 0 - && gProtectStructs[gBattlerAttacker].physicalBattlerId == gBattlerTarget) - || (gProtectStructs[gBattlerAttacker].specialDmg != 0 - && gProtectStructs[gBattlerAttacker].specialBattlerId == gBattlerTarget)) - { - gBattleScripting.dmgMultiplier = 2; - } + CMD_ARGS(const u8 *failInstr); - gBattlescriptCurrInstr++; + if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeSuppressed) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + + gStatuses3[gBattlerTarget] |= STATUS3_GASTRO_ACID; + gBattlescriptCurrInstr = cmd->nextInstr; + } } static void Cmd_setyawn(void) @@ -9663,16 +10421,20 @@ static void Cmd_tryimprison(void) } } -static void Cmd_trysetgrudge(void) +static void Cmd_setstealthrock(void) { - if (gStatuses3[gBattlerAttacker] & STATUS3_GRUDGE) + CMD_ARGS(const u8 *failInstr); + + u8 targetSide = GetBattlerSide(gBattlerTarget); + if (gSideStatuses[targetSide] & SIDE_STATUS_STEALTH_ROCK) { - gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = cmd->failInstr; } else { - gStatuses3[gBattlerAttacker] |= STATUS3_GRUDGE; - gBattlescriptCurrInstr += 5; + gSideStatuses[targetSide] |= SIDE_STATUS_STEALTH_ROCK; + gSideTimers[targetSide].stealthRockAmount = 1; + gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -10705,6 +11467,35 @@ bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler) return FALSE; } +u32 IsFlowerVeilProtected(u32 battler) +{ + if (IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) + return IsAbilityOnSide(battler, ABILITY_FLOWER_VEIL); + else + return 0; +} + +u32 IsLeafGuardProtected(u32 battler) +{ + if (IsBattlerWeatherAffected(battler, B_WEATHER_SUN)) + return GetBattlerAbility(battler) == ABILITY_LEAF_GUARD; + else + return 0; +} + +bool32 IsShieldsDownProtected(u32 battler) +{ + return (GetBattlerAbility(battler) == ABILITY_SHIELDS_DOWN + && GetFormIdFromFormSpeciesId(gBattleMons[battler].species) < GetFormIdFromFormSpeciesId(SPECIES_MINIOR_CORE_RED)); // Minior is not in core form +} + +u32 IsAbilityStatusProtected(u32 battler) +{ + return IsFlowerVeilProtected(battler) + || IsLeafGuardProtected(battler) + || IsShieldsDownProtected(battler); +} + u32 GetHighestStatId(u32 battler) { u32 i, highestId = STAT_ATK, highestStat = gBattleMons[battler].attack; @@ -10745,3 +11536,166 @@ bool32 DoesDisguiseBlockMove(u32 battler, u32 move) else return TRUE; } + +static bool8 IsFinalStrikeEffect(u16 move) +{ + u32 i; + u16 moveEffect = gMovesInfo[move].effect; + + for (i = 0; i < ARRAY_COUNT(sFinalStrikeOnlyEffects); i++) + { + if (moveEffect == sFinalStrikeOnlyEffects[i]) + return TRUE; + } + return FALSE; +} + +bool32 CanPoisonType(u8 battlerAttacker, u8 battlerTarget) +{ + return GetBattlerAbility(battlerAttacker) == ABILITY_CORROSION + || (!IS_BATTLER_OF_TYPE(battlerTarget, TYPE_STEEL) && !IS_BATTLER_OF_TYPE(battlerTarget, TYPE_POISON)); +} + +bool32 CanParalyzeType(u8 battlerAttacker, u8 battlerTarget) +{ + return !(B_PARALYZE_ELECTRIC >= GEN_6 && IS_BATTLER_OF_TYPE(battlerTarget, TYPE_ELECTRIC)); +} + +bool32 NoAliveMonsForPlayer(void) +{ + u32 i; + u32 maxI = PARTY_SIZE; + u32 HP_count = 0; + + if (B_MULTI_BATTLE_WHITEOUT < GEN_4 && gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)) + maxI = MULTI_PARTY_SIZE; + + // Get total HP for the player's party to determine if the player has lost + for (i = 0; i < maxI; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + { + HP_count += GetMonData(&gPlayerParty[i], MON_DATA_HP); + } + } + + return (HP_count == 0); +} + +static bool32 NoAliveMonsForOpponent(void) +{ + u32 i; + u32 HP_count = 0; + + // Get total HP for the enemy's party to determine if the player has won + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES) && !GetMonData(&gEnemyParty[i], MON_DATA_IS_EGG)) + { + HP_count += GetMonData(&gEnemyParty[i], MON_DATA_HP); + } + } + + return (HP_count == 0); +} + +bool32 NoAliveMonsForEitherParty(void) +{ + return (NoAliveMonsForPlayer() || NoAliveMonsForOpponent()); +} + +static void TryUpdateRoundTurnOrder(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + u32 i; + u32 j = 0; + u32 k = 0; + u32 currRounder = 0; + u8 roundUsers[3] = {0xFF, 0xFF, 0xFF}; + u8 nonRoundUsers[3] = {0xFF, 0xFF, 0xFF}; + for (i = 0; i < gBattlersCount; i++) + { + if (gBattlerByTurnOrder[i] == gBattlerAttacker) + { + currRounder = i + 1; // Current battler going after attacker + break; + } + } + + // Get battlers after us using round + for (i = currRounder; i < gBattlersCount; i++) + { + if (gChosenMoveByBattler[gBattlerByTurnOrder[i]] == MOVE_ROUND) + roundUsers[j++] = gBattlerByTurnOrder[i]; + else + nonRoundUsers[k++] = gBattlerByTurnOrder[i]; + } + + // update turn order for round users + for (i = 0; roundUsers[i] != 0xFF && i < 3; i++) + { + gBattlerByTurnOrder[currRounder] = roundUsers[i]; + gActionsByTurnOrder[currRounder] = gActionsByTurnOrder[roundUsers[i]]; + gProtectStructs[roundUsers[i]].quash = TRUE; // Make it so their turn order can't be changed again + currRounder++; + } + + // Update turn order for non-round users + for (i = 0; nonRoundUsers[i] != 0xFF && i < 3; i++) + { + gBattlerByTurnOrder[currRounder] = nonRoundUsers[i]; + gActionsByTurnOrder[currRounder] = gActionsByTurnOrder[nonRoundUsers[i]]; + currRounder++; + } + } +} + +void BS_TryRevertWeatherForm(void) +{ + NATIVE_ARGS(); + if (TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_WEATHER)) + { + gBattleScripting.battler = gBattlerTarget; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_TargetFormChangeWithStringNoPopup; + return; + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +// Used by Bestow and Symbiosis to take an item from one battler and give to another. +static void BestowItem(u32 battlerAtk, u32 battlerDef) +{ + gLastUsedItem = gBattleMons[battlerAtk].item; + + gBattleMons[battlerAtk].item = ITEM_NONE; + gActiveBattler = battlerAtk; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battlerAtk].item), &gBattleMons[battlerAtk].item); + MarkBattlerForControllerExec(battlerAtk); + CheckSetUnburden(battlerAtk); + + gBattleMons[battlerDef].item = gLastUsedItem; + gActiveBattler = battlerDef; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battlerDef].item), &gBattleMons[battlerDef].item); + MarkBattlerForControllerExec(battlerDef); + gBattleResources->flags->flags[battlerDef] &= ~RESOURCE_FLAG_UNBURDEN; +} + +void BS_TrySymbiosis(void) +{ + NATIVE_ARGS(); + //called by Bestow, Fling, and Bug Bite, which don't work with Cmd_removeitem. + u32 partner = BATTLE_PARTNER(gBattlerAttacker); + if (SYMBIOSIS_CHECK(gBattlerAttacker, partner)) + { + BestowItem(partner, gBattlerAttacker); + gLastUsedAbility = gBattleMons[partner].ability; + gBattleScripting.battler = gBattlerAbility = partner; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; + return; + } + + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index f0f2c9bff..287baeff5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -227,17 +227,87 @@ void MarkBattlerReceivedLinkData(u8 battlerId) gBattleControllerExecFlags &= ~((1 << 28) << battlerId); } -void CancelMultiTurnMoves(u8 battler) +const u8* CancelMultiTurnMoves(u32 battler) { - gBattleMons[battler].status2 &= ~STATUS2_MULTIPLETURNS; - gBattleMons[battler].status2 &= ~STATUS2_LOCK_CONFUSE; - gBattleMons[battler].status2 &= ~STATUS2_UPROAR; - gBattleMons[battler].status2 &= ~STATUS2_BIDE; + const u8 *result = NULL; + gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS); + gBattleMons[battler].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[battler].status2 &= ~(STATUS2_UPROAR); + gBattleMons[battler].status2 &= ~(STATUS2_BIDE); - gStatuses3[battler] &= ~STATUS3_SEMI_INVULNERABLE; + // Clear battler's semi-invulnerable bits if they are not held by Sky Drop. + if (!(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + gStatuses3[battler] &= ~(STATUS3_SEMI_INVULNERABLE); + + // Check to see if this Pokemon was in the middle of using Sky Drop. If so, release the target. + if (gBattleStruct->skyDropTargets[battler] != 0xFF && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + { + // Get the target's battler id + u8 otherSkyDropper = gBattleStruct->skyDropTargets[battler]; + + // Clears sky_dropped and on_air statuses + gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + + // Makes both attacker and target's sprites visible + gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; + gSprites[gBattlerSpriteIds[otherSkyDropper]].invisible = FALSE; + + // If target was sky dropped in the middle of Outrage/Thrash/Petal Dance, + // confuse them upon release and display "confused by fatigue" message & animation. + // Don't do this if this CancelMultiTurnMoves is caused by falling asleep via Yawn. + if (gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE && gBattleStruct->turnEffectsTracker != 24) + { + gBattleMons[otherSkyDropper].status2 &= ~(STATUS2_LOCK_CONFUSE); + + // If the target can be confused, confuse them. + // Don't use CanBeConfused, can cause issues in edge cases. + if (!(GetBattlerAbility(otherSkyDropper) == ABILITY_OWN_TEMPO + || gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION + || IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN))) + { + // Set confused status + gBattleMons[otherSkyDropper].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); + + // If this CancelMultiTurnMoves is occuring due to attackcanceller + if (gBattlescriptCurrInstr[0] == 0x0) + { + gBattleStruct->skyDropTargets[battler] = 0xFE; + } + // If this CancelMultiTurnMoves is occuring due to VARIOUS_GRAVITY_ON_AIRBORNE_MONS + // Reapplying STATUS3_SKY_DROPPED allows for avoiding unecessary messages when Gravity is applied to the target. + else if (gBattlescriptCurrInstr[0] == 0x76 && gBattlescriptCurrInstr[2] == 76) + { + gBattleStruct->skyDropTargets[battler] = 0xFE; + gStatuses3[otherSkyDropper] |= STATUS3_SKY_DROPPED; + } + // If this CancelMultiTurnMoves is occuring due to cancelmultiturnmoves script + else if (gBattlescriptCurrInstr[0] == 0x76 && gBattlescriptCurrInstr[2] == 0) + { + gBattlerAttacker = otherSkyDropper; + result = BattleScript_ThrashConfuses; + } + // If this CancelMultiTurnMoves is occuring due to receiving Sleep/Freeze status + else if (gBattleScripting.moveEffect <= PRIMARY_STATUS_MOVE_EFFECT) + { + gBattlerAttacker = otherSkyDropper; + BattleScriptPush(gBattlescriptCurrInstr + 1); + result = BattleScript_ThrashConfuses; + } + } + } + + // Clear skyDropTargets data, unless this CancelMultiTurnMoves is caused by Yawn, attackcanceler, or VARIOUS_GRAVITY_ON_AIRBORNE_MONS + if (!(gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE) && gBattleStruct->skyDropTargets[battler] < 4) + { + gBattleStruct->skyDropTargets[battler] = 0xFF; + gBattleStruct->skyDropTargets[otherSkyDropper] = 0xFF; + } + } gDisableStructs[battler].rolloutTimer = 0; gDisableStructs[battler].furyCutterCounter = 0; + + return result; } bool32 WasUnableToUseMove(u32 battler) @@ -3255,7 +3325,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } } break; - case ITEMEFFECT_KINGSROCK_SHELLBELL: + case ITEMEFFECT_KINGSROCK: if (gBattleMoveDamage) { switch (atkHoldEffect) @@ -6213,6 +6283,366 @@ void RecalcBattlerStats(u32 battler, struct Pokemon *mon) CopyMonAbilityAndTypesToBattleMon(battler, mon); } +bool32 TestIfSheerForceAffected(u32 battler, u16 move) +{ + return GetBattlerAbility(battler) == ABILITY_SHEER_FORCE && MoveIsAffectedBySheerForce(move); +} + +bool32 CanSleep(u32 battler) +{ + u16 ability = GetBattlerAbility(battler); + if (ability == ABILITY_INSOMNIA + || ability == ABILITY_VITAL_SPIRIT + || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD + || gBattleMons[battler].status1 & STATUS1_ANY + || IsAbilityOnSide(battler, ABILITY_SWEET_VEIL) + || IsAbilityStatusProtected(battler) + || IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + +bool32 CanBePoisoned(u32 battlerAttacker, u32 battlerTarget) +{ + u16 ability = GetBattlerAbility(battlerTarget); + + if (!(CanPoisonType(battlerAttacker, battlerTarget)) + || gSideStatuses[GetBattlerSide(battlerTarget)] & SIDE_STATUS_SAFEGUARD + || gBattleMons[battlerTarget].status1 & STATUS1_ANY + || ability == ABILITY_IMMUNITY + || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT + || IsAbilityOnSide(battlerTarget, ABILITY_PASTEL_VEIL) + || IsAbilityStatusProtected(battlerTarget) + || IsBattlerTerrainAffected(battlerTarget, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + +bool32 CanBeBurned(u32 battler) +{ + u16 ability = GetBattlerAbility(battler); + if (IS_BATTLER_OF_TYPE(battler, TYPE_FIRE) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD + || gBattleMons[battler].status1 & STATUS1_ANY + || ability == ABILITY_WATER_VEIL + || ability == ABILITY_WATER_BUBBLE + || ability == ABILITY_COMATOSE + || ability == ABILITY_THERMAL_EXCHANGE + || ability == ABILITY_PURIFYING_SALT + || IsAbilityStatusProtected(battler) + || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + +bool32 CanBeParalyzed(u32 battler) +{ + u16 ability = GetBattlerAbility(battler); + if ((B_PARALYZE_ELECTRIC >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC)) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD + || ability == ABILITY_LIMBER + || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT + || gBattleMons[battler].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battler) + || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + +bool32 CanBeFrozen(u32 battler) +{ + u16 ability = GetBattlerAbility(battler); + if (IS_BATTLER_OF_TYPE(battler, TYPE_ICE) + || IsBattlerWeatherAffected(battler, B_WEATHER_SUN) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD + || ability == ABILITY_MAGMA_ARMOR + || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT + || gBattleMons[battler].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battler) + || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + +bool32 CanGetFrostbite(u32 battler) +{ + u16 ability = GetBattlerAbility(battler); + if (IS_BATTLER_OF_TYPE(battler, TYPE_ICE) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD + || ability == ABILITY_MAGMA_ARMOR + || ability == ABILITY_COMATOSE + || ability == ABILITY_PURIFYING_SALT + || gBattleMons[battler].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battler) + || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + +bool32 CanBeConfused(u32 battler) +{ + if (GetBattlerAbility(battler) == ABILITY_OWN_TEMPO + || gBattleMons[battler].status2 & STATUS2_CONFUSION + || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + +bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item) +{ + u8 stealerSide = GetBattlerSide(battlerStealing); + + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER) + return FALSE; + + // Check if the battler trying to steal should be able to + if (stealerSide == B_SIDE_OPPONENT + && !(gBattleTypeFlags & + (BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_TRAINER_TOWER + | BATTLE_TYPE_LINK + | (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE ? BATTLE_TYPE_TRAINER : 0) + ))) + { + return FALSE; + } + else if (!(gBattleTypeFlags & + (BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_BATTLE_TOWER + | BATTLE_TYPE_LINK)) + && (gWishFutureKnock.knockedOffMons[stealerSide] & gBitTable[gBattlerPartyIndexes[battlerStealing]])) + { + return FALSE; + } + + if (!CanBattlerGetOrLoseItem(battlerItem, item) // Battler with item cannot have it stolen + ||!CanBattlerGetOrLoseItem(battlerStealing, item)) // Stealer cannot take the item + return FALSE; + + return TRUE; +} + +void TrySaveExchangedItem(u32 battler, u16 stolenItem) +{ + // Because BtlController_EmitSetMonData does SetMonData, we need to save the stolen item only if it matches the battler's original + // So, if the player steals an item during battle and has it stolen from it, it will not end the battle with it (naturally) + if (B_TRAINERS_KNOCK_OFF_ITEMS == FALSE) + return; + // If regular trainer battle and mon's original item matches what is being stolen, save it to be restored at end of battle + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER + && !(gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + && GetBattlerSide(battler) == B_SIDE_PLAYER + && stolenItem == gBattleStruct->itemLost[gBattlerPartyIndexes[battler]].originalItem) + gBattleStruct->itemLost[gBattlerPartyIndexes[battler]].stolen = TRUE; +} + +void RemoveBattlerType(u32 battler, u8 type) +{ + u32 i; + for (i = 0; i < 3; i++) + { + if (*(u8 *)(&gBattleMons[battler].type1 + i) == type) + *(u8 *)(&gBattleMons[battler].type1 + i) = TYPE_MYSTERY; + } +} + +// Returns SPECIES_NONE if no form change is possible +u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method) +{ + u32 i; + u16 targetSpecies = SPECIES_NONE; + u16 species = gBattleMons[battler].species; + const struct FormChange *formChanges = GetSpeciesFormChanges(species); + struct Pokemon *mon = &GetBattlerParty(battler)[gBattlerPartyIndexes[battler]]; + u16 heldItem; + + if (formChanges != NULL) + { + heldItem = gBattleMons[battler].item; + + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) + { + if (method == formChanges[i].method && species != formChanges[i].targetSpecies) + { + switch (method) + { + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_BATTLE_PRIMAL_REVERSION: + case FORM_CHANGE_BATTLE_ULTRA_BURST: + if (heldItem == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE: + if (gBattleMons[battler].moves[0] == formChanges[i].param1 + || gBattleMons[battler].moves[1] == formChanges[i].param1 + || gBattleMons[battler].moves[2] == formChanges[i].param1 + || gBattleMons[battler].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(battler)) + { + // We multiply by 100 to make sure that integer division doesn't mess with the health check. + u32 hpCheck = gBattleMons[battler].hp * 100 * 100 / gBattleMons[battler].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_GIGANTAMAX: + if (GetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR)) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_WEATHER: + // Check if there is a required ability and if the battler's ability does not match it + // or is suppressed. If so, revert to the no weather form. + if (formChanges[i].param2 + && GetBattlerAbility(battler) != formChanges[i].param2 + && formChanges[i].param1 == B_WEATHER_NONE) + { + targetSpecies = formChanges[i].targetSpecies; + } + // We need to revert the weather form if the field is under Air Lock, too. + else if (!WEATHER_HAS_EFFECT && formChanges[i].param1 == B_WEATHER_NONE) + { + targetSpecies = formChanges[i].targetSpecies; + } + // Otherwise, just check for a match between the weather and the form change table. + // Added a check for whether the weather is in effect to prevent end-of-turn soft locks with Cloud Nine / Air Lock + else if (((gBattleWeather & formChanges[i].param1) && WEATHER_HAS_EFFECT) + || (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(battler)) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_STATUS: + if (gBattleMons[battler].status1 & formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + } + } + } + } + + return targetSpecies; +} + +bool32 IsBattlerMegaEvolved(u32 battler) +{ + // While Transform does copy stats and visuals, it shouldn't be counted as true Mega Evolution. + if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + return FALSE; + return (gSpeciesInfo[gBattleMons[battler].species].isMegaEvolution); +} + +bool32 IsBattlerPrimalReverted(u32 battler) +{ + // While Transform does copy stats and visuals, it shouldn't be counted as true Primal Revesion. + if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + return FALSE; + return (gSpeciesInfo[gBattleMons[battler].species].isPrimalReversion); +} + +bool32 IsBattlerUltraBursted(u32 battler) +{ + // While Transform does copy stats and visuals, it shouldn't be counted as true Ultra Burst. + if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + return FALSE; + return (gSpeciesInfo[gBattleMons[battler].species].isUltraBurst); +} + +bool32 CanBattlerFormChange(u32 battler, u16 method) +{ + // Can't change form if transformed. + if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED + && B_TRANSFORM_FORM_CHANGES >= GEN_5) + return FALSE; + // Mega Evolved and Ultra Bursted Pokémon should always revert to normal upon fainting or ending the battle. + if ((IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler)) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + return TRUE; + else if (IsBattlerPrimalReverted(battler) && (method == FORM_CHANGE_END_BATTLE)) + return TRUE; + // TODO: Dynamax + // Gigantamaxed Pokemon should revert upon fainting, switching, or ending the battle. + /* else if (IsGigantamaxed(battler) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_BATTLE_SWITCH || method == FORM_CHANGE_END_BATTLE)) + return TRUE; */ + return DoesSpeciesHaveFormChangeMethod(gBattleMons[battler].species, method); +} + +bool32 TryBattleFormChange(u32 battler, u16 method) +{ + u8 monId = gBattlerPartyIndexes[battler]; + u8 side = GetBattlerSide(battler); + struct Pokemon *party = GetBattlerParty(battler); + u16 targetSpecies; + + if (!CanBattlerFormChange(battler, method)) + return FALSE; + + targetSpecies = GetBattleFormChangeTargetSpecies(battler, method); + if (targetSpecies == SPECIES_NONE) + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + if (targetSpecies != SPECIES_NONE) + { + // Saves the original species on the first form change. + if (gBattleStruct->changedSpecies[side][monId] == SPECIES_NONE) + gBattleStruct->changedSpecies[side][monId] = gBattleMons[battler].species; + + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + gBattleMons[battler].species = targetSpecies; + RecalcBattlerStats(battler, &party[monId]); + return TRUE; + } + else if (gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE) + { + bool32 restoreSpecies = FALSE; + + // Mega Evolved and Ultra Bursted 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(battler) || IsBattlerUltraBursted(battler)) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + // Unlike Megas, Primal Reversion isn't canceled on fainting. + else if (IsBattlerPrimalReverted(battler) && (method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + // Gigantamax Pokemon have their forms reverted after fainting, switching, or ending the battle. + else if (FALSE /* IsGigantamaxed(battler) */ && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_BATTLE_SWITCH || method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + if (restoreSpecies) + { + // Reverts the original species + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[side][monId]); + RecalcBattlerStats(battler, &party[monId]); + return TRUE; + } + } + + return FALSE; +} + // battle_ai_util.c diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 01154c024..5edd6f42b 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1,101 +1,135 @@ #if P_FAMILY_BULBASAUR static const struct FormChange sVenusaurFormChangeTable[] = { - {}, - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_VENUSAUR_MEGA, ITEM_VENUSAURITE}, +#endif +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_VENUSAUR_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_BULBASAUR #if P_FAMILY_CHARMANDER static const struct FormChange sCharizardFormChangeTable[] = { - {}, - {}, - {}, - {}, +#if P_MEGA_EVOLUTIONS + {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}, +#endif +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_CHARIZARD_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_CHARMANDER #if P_FAMILY_SQUIRTLE static const struct FormChange sBlastoiseFormChangeTable[] = { - {}, - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLASTOISE_MEGA, ITEM_BLASTOISINITE}, +#endif +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_BLASTOISE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SQUIRTLE #if P_FAMILY_CATERPIE static const struct FormChange sButterfreeFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_BUTTERFREE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_CATERPIE #if P_FAMILY_WEEDLE static const struct FormChange sBeedrillFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BEEDRILL_MEGA, ITEM_BEEDRILLITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_WEEDLE #if P_FAMILY_PIDGEY static const struct FormChange sPidgeotFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PIDGEOT_MEGA, ITEM_PIDGEOTITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_PIDGEY #if P_FAMILY_PIKACHU static const struct FormChange sPikachuFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_PIKACHU_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_PIKACHU #if P_FAMILY_MEOWTH static const struct FormChange sMeowthFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_MEOWTH_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MEOWTH #if P_FAMILY_ABRA static const struct FormChange sAlakazamFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALAKAZAM_MEGA, ITEM_ALAKAZITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ABRA #if P_FAMILY_MACHOP static const struct FormChange sMachampFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_MACHAMP_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MACHOP #if P_FAMILY_SLOWPOKE static const struct FormChange sSlowbroFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SLOWBRO_MEGA, ITEM_SLOWBRONITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SLOWPOKE #if P_FAMILY_GASTLY static const struct FormChange sGengarFormChangeTable[] = { - {}, - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GENGAR_MEGA, ITEM_GENGARITE}, +#endif +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_GENGAR_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_GASTLY #if P_FAMILY_ONIX #if P_GEN_2_CROSS_EVOS static const struct FormChange sSteelixFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_STEELIX_MEGA, ITEM_STEELIXITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_GEN_2_CROSS_EVOS #endif //P_FAMILY_ONIX @@ -103,461 +137,567 @@ static const struct FormChange sSteelixFormChangeTable[] = { #if P_FAMILY_KRABBY static const struct FormChange sKinglerFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_KINGLER_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_KRABBY #if P_FAMILY_KANGASKHAN static const struct FormChange sKangaskhanFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_KANGASKHAN_MEGA, ITEM_KANGASKHANITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_KANGASKHAN #if P_FAMILY_SCYTHER #if P_GEN_2_CROSS_EVOS static const struct FormChange sScizorFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCIZOR_MEGA, ITEM_SCIZORITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_GEN_2_CROSS_EVOS #endif //P_FAMILY_SCYTHER #if P_FAMILY_PINSIR static const struct FormChange sPinsirFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PINSIR_MEGA, ITEM_PINSIRITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_PINSIR #if P_FAMILY_MAGIKARP static const struct FormChange sGyaradosFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GYARADOS_MEGA, ITEM_GYARADOSITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MAGIKARP #if P_FAMILY_LAPRAS static const struct FormChange sLaprasFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_LAPRAS_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_LAPRAS #if P_FAMILY_EEVEE static const struct FormChange sEeveeFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_EEVEE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_EEVEE #if P_FAMILY_AERODACTYL static const struct FormChange sAerodactylFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AERODACTYL_MEGA, ITEM_AERODACTYLITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_AERODACTYL #if P_FAMILY_SNORLAX static const struct FormChange sSnorlaxFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_SNORLAX_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SNORLAX #if P_FAMILY_MEWTWO static const struct FormChange sMewtwoFormChangeTable[] = { - {}, - {}, - {}, +#if P_MEGA_EVOLUTIONS + {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}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MEWTWO #if P_FAMILY_MAREEP static const struct FormChange sAmpharosFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AMPHAROS_MEGA, ITEM_AMPHAROSITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MAREEP #if P_FAMILY_HERACROSS static const struct FormChange sHeracrossFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HERACROSS_MEGA, ITEM_HERACRONITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_HERACROSS #if P_FAMILY_HOUNDOUR static const struct FormChange sHoundoomFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HOUNDOOM_MEGA, ITEM_HOUNDOOMINITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_HOUNDOUR #if P_FAMILY_LARVITAR static const struct FormChange sTyranitarFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_TYRANITAR_MEGA, ITEM_TYRANITARITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_LARVITAR #if P_FAMILY_TREECKO static const struct FormChange sSceptileFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCEPTILE_MEGA, ITEM_SCEPTILITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_TREECKO #if P_FAMILY_TORCHIC static const struct FormChange sBlazikenFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLAZIKEN_MEGA, ITEM_BLAZIKENITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_TORCHIC #if P_FAMILY_MUDKIP static const struct FormChange sSwampertFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SWAMPERT_MEGA, ITEM_SWAMPERTITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MUDKIP #if P_FAMILY_RALTS static const struct FormChange sGardevoirFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARDEVOIR_MEGA, ITEM_GARDEVOIRITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #if P_GEN_4_CROSS_EVOS static const struct FormChange sGalladeFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GALLADE_MEGA, ITEM_GALLADITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_GEN_4_CROSS_EVOS #endif //P_FAMILY_RALTS #if P_FAMILY_SABLEYE static const struct FormChange sSableyeFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SABLEYE_MEGA, ITEM_SABLENITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SABLEYE #if P_FAMILY_MAWILE static const struct FormChange sMawileFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MAWILE_MEGA, ITEM_MAWILITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MAWILE #if P_FAMILY_ARON static const struct FormChange sAggronFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AGGRON_MEGA, ITEM_AGGRONITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ARON #if P_FAMILY_MEDITITE static const struct FormChange sMedichamFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEDICHAM_MEGA, ITEM_MEDICHAMITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MEDITITE #if P_FAMILY_ELECTRIKE static const struct FormChange sManectricFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MANECTRIC_MEGA, ITEM_MANECTITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ELECTRIKE #if P_FAMILY_CARVANHA static const struct FormChange sSharpedoFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SHARPEDO_MEGA, ITEM_SHARPEDONITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_CARVANHA #if P_FAMILY_NUMEL static const struct FormChange sCameruptFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CAMERUPT_MEGA, ITEM_CAMERUPTITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_NUMEL #if P_FAMILY_SWABLU static const struct FormChange sAltariaFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALTARIA_MEGA, ITEM_ALTARIANITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SWABLU #if P_FAMILY_SHUPPET static const struct FormChange sBanetteFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BANETTE_MEGA, ITEM_BANETTITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SHUPPET #if P_FAMILY_ABSOL static const struct FormChange sAbsolFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABSOL_MEGA, ITEM_ABSOLITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ABSOL #if P_FAMILY_SNORUNT static const struct FormChange sGlalieFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GLALIE_MEGA, ITEM_GLALITITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SNORUNT #if P_FAMILY_CASTFORM static const struct FormChange sCastformFormChangeTable[] = { #if B_WEATHER_FORMS >= GEN_5 - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_SUNNY, B_WEATHER_SUN, ABILITY_FORECAST}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_RAINY, B_WEATHER_RAIN, ABILITY_FORECAST}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_SNOWY, B_WEATHER_HAIL | B_WEATHER_SNOW, ABILITY_FORECAST}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_NORMAL, ~(B_WEATHER_SUN | B_WEATHER_RAIN | B_WEATHER_HAIL | B_WEATHER_SNOW), ABILITY_FORECAST}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_NORMAL, B_WEATHER_NONE, ABILITY_FORECAST}, #else - {}, - {}, - {}, - {}, - {}, + {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 | B_WEATHER_SNOW}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_NORMAL, ~(B_WEATHER_SUN | B_WEATHER_RAIN | B_WEATHER_HAIL | B_WEATHER_SNOW)}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_NORMAL, B_WEATHER_NONE}, #endif - {}, - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CASTFORM_NORMAL}, + {FORM_CHANGE_FAINT, SPECIES_CASTFORM_NORMAL}, + {FORM_CHANGE_END_BATTLE, SPECIES_CASTFORM_NORMAL}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_CASTFORM #if P_FAMILY_BAGON static const struct FormChange sSalamenceFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SALAMENCE_MEGA, ITEM_SALAMENCITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_BAGON #if P_FAMILY_BELDUM static const struct FormChange sMetagrossFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_METAGROSS_MEGA, ITEM_METAGROSSITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_BELDUM #if P_FAMILY_LATIAS static const struct FormChange sLatiasFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIAS_MEGA, ITEM_LATIASITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_LATIAS #if P_FAMILY_LATIOS static const struct FormChange sLatiosFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIOS_MEGA, ITEM_LATIOSITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_LATIOS #if P_FAMILY_KYOGRE static const struct FormChange sKyogreFormChangeTable[] = { - {}, - {}, +#if P_PRIMAL_REVERSIONS + {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_KYOGRE #if P_FAMILY_GROUDON static const struct FormChange sGroudonFormChangeTable[] = { - {}, - {}, +#if P_PRIMAL_REVERSIONS + {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_GROUDON_PRIMAL, ITEM_RED_ORB}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_GROUDON #if P_FAMILY_RAYQUAZA static const struct FormChange sRayquazaFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_RAYQUAZA +#if P_FAMILY_DEOXYS +static const struct FormChange sDeoxysNormalFormChangeTable[] = { + {FORM_CHANGE_ITEM_USE, SPECIES_DEOXYS_ATTACK, ITEM_METEORITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDeoxysAttackFormChangeTable[] = { + {FORM_CHANGE_ITEM_USE, SPECIES_DEOXYS_DEFENSE, ITEM_METEORITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDeoxysDefenseFormChangeTable[] = { + {FORM_CHANGE_ITEM_USE, SPECIES_DEOXYS_SPEED, ITEM_METEORITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDeoxysSpeedFormChangeTable[] = { + {FORM_CHANGE_ITEM_USE, SPECIES_DEOXYS_NORMAL, ITEM_METEORITE}, + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_DEOXYS + #if P_FAMILY_BURMY static const struct FormChange sBurmyFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_PLANT_CLOAK, BATTLE_TERRAIN_GRASS}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_PLANT_CLOAK, BATTLE_TERRAIN_LONG_GRASS}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_PLANT_CLOAK, BATTLE_TERRAIN_POND}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_PLANT_CLOAK, BATTLE_TERRAIN_MOUNTAIN}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_PLANT_CLOAK, 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}, }; #endif //P_FAMILY_BURMY #if P_FAMILY_CHERUBI static const struct FormChange sCherrimFormChangeTable[] = { #if B_WEATHER_FORMS >= GEN_5 - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_SUNSHINE, B_WEATHER_SUN, ABILITY_FLOWER_GIFT}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_OVERCAST, ~B_WEATHER_SUN, ABILITY_FLOWER_GIFT}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_OVERCAST, B_WEATHER_NONE, ABILITY_FLOWER_GIFT}, #else - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_SUNSHINE, B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_OVERCAST, ~B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_OVERCAST, B_WEATHER_NONE}, #endif - {}, - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CHERRIM_OVERCAST}, + {FORM_CHANGE_FAINT, SPECIES_CHERRIM_OVERCAST}, + {FORM_CHANGE_END_BATTLE, SPECIES_CHERRIM_OVERCAST}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_CHERUBI #if P_FAMILY_BUNEARY static const struct FormChange sLopunnyFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_BUNEARY #if P_FAMILY_GIBLE static const struct FormChange sGarchompFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARCHOMP_MEGA, ITEM_GARCHOMPITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_GIBLE #if P_FAMILY_RIOLU static const struct FormChange sLucarioFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LUCARIO_MEGA, ITEM_LUCARIONITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_RIOLU #if P_FAMILY_SNOVER static const struct FormChange sAbomasnowFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABOMASNOW_MEGA, ITEM_ABOMASITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SNOVER #if P_FAMILY_ROTOM static const struct FormChange sRotomFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ROTOM, ITEM_ROTOM_CATALOG, 0}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ROTOM_HEAT, ITEM_ROTOM_CATALOG, 1}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ROTOM_WASH, ITEM_ROTOM_CATALOG, 2}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ROTOM_FROST, ITEM_ROTOM_CATALOG, 3}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ROTOM_FAN, ITEM_ROTOM_CATALOG, 4}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ROTOM_MOW, ITEM_ROTOM_CATALOG, 5}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ROTOM #if P_FAMILY_DIALGA static const struct FormChange sDialgaFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_DIALGA, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_DIALGA_ORIGIN, ITEM_ADAMANT_CRYSTAL}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_DIALGA #if P_FAMILY_PALKIA static const struct FormChange sPalkiaFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_PALKIA, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_PALKIA_ORIGIN, ITEM_LUSTROUS_GLOBE}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_PALKIA #if P_FAMILY_GIRATINA static const struct FormChange sGiratinaFormChangeTable[] = { - {}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ALTERED, 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}, }; #endif //P_FAMILY_GIRATINA #if P_FAMILY_SHAYMIN static const struct FormChange sShayminFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA, DAY}, + {FORM_CHANGE_WITHDRAW, SPECIES_SHAYMIN_LAND}, + {FORM_CHANGE_TIME_OF_DAY, SPECIES_SHAYMIN_LAND, NIGHT}, + {FORM_CHANGE_STATUS, SPECIES_SHAYMIN_LAND, (STATUS1_FREEZE | STATUS1_FROSTBITE)}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SHAYMIN #if P_FAMILY_ARCEUS static const struct FormChange sArceusFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_NORMAL, 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 //P_FAMILY_ARCEUS #if P_FAMILY_AUDINO static const struct FormChange sAudinoFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AUDINO_MEGA, ITEM_AUDINITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_AUDINO #if P_FAMILY_DARUMAKA static const struct FormChange sDarmanitanFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_STANDARD_MODE, 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_STANDARD_MODE}, + {FORM_CHANGE_END_BATTLE, SPECIES_DARMANITAN_STANDARD_MODE}, + {FORM_CHANGE_TERMINATOR}, }; #if P_GALARIAN_FORMS static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_GALARIAN_STANDARD_MODE, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_GALARIAN_ZEN_MODE, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN_GALARIAN_STANDARD_MODE}, + {FORM_CHANGE_END_BATTLE, SPECIES_DARMANITAN_GALARIAN_STANDARD_MODE}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_GALARIAN_FORMS #endif //P_FAMILY_DARUMAKA @@ -565,510 +705,577 @@ static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { #if P_FAMILY_TRUBBISH static const struct FormChange sGarbodorFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_GARBODOR_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_TRUBBISH #if P_FAMILY_TORNADUS static const struct FormChange sTornadusFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS_INCARNATE, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_TORNADUS #if P_FAMILY_THUNDURUS static const struct FormChange sThundurusFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS_INCARNATE, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_THUNDURUS #if P_FAMILY_LANDORUS static const struct FormChange sLandorusFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS_INCARNATE, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_LANDORUS #if P_FAMILY_KYUREM static const struct Fusion sKyuremFusionTable[] = { - {}, - {}, - {}, + {0, ITEM_DNA_SPLICERS, SPECIES_KYUREM, SPECIES_RESHIRAM, SPECIES_KYUREM_WHITE}, + {0, ITEM_DNA_SPLICERS, SPECIES_KYUREM, SPECIES_ZEKROM, SPECIES_KYUREM_BLACK}, + {FUSION_TERMINATOR}, }; #endif //P_FAMILY_KYUREM #if P_FAMILY_KELDEO static const struct FormChange sKeldeoFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, + {FORM_CHANGE_MOVE, SPECIES_KELDEO_ORDINARY, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_KELDEO #if P_FAMILY_MELOETTA static const struct FormChange sMeloettaFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_FAINT, SPECIES_MELOETTA_ARIA}, + {FORM_CHANGE_END_BATTLE, SPECIES_MELOETTA_ARIA}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MELOETTA #if P_FAMILY_GENESECT static const struct FormChange sGenesectFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, - {}, + {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 //P_FAMILY_GENESECT #if P_FAMILY_FROAKIE static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_FAINT, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_END_BATTLE, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_FROAKIE #if P_FAMILY_HONEDGE static const struct FormChange sAegislashFormChangeTable[] = { - {}, - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH_SHIELD}, + {FORM_CHANGE_FAINT, SPECIES_AEGISLASH_SHIELD}, + {FORM_CHANGE_END_BATTLE, SPECIES_AEGISLASH_SHIELD}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_HONEDGE #if P_FAMILY_XERNEAS static const struct FormChange sXerneasFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_XERNEAS_ACTIVE}, + {FORM_CHANGE_END_BATTLE, SPECIES_XERNEAS_NEUTRAL}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_XERNEAS #if P_FAMILY_ZYGARDE static const struct FormChange sZygarde50AuraBreakFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ZYGARDE_10_AURA_BREAK, ITEM_ZYGARDE_CUBE, 0}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ZYGARDE_50_POWER_CONSTRUCT, ITEM_ZYGARDE_CUBE, 1}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZygarde10AuraBreakFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ZYGARDE_50_AURA_BREAK, ITEM_ZYGARDE_CUBE, 0}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ZYGARDE_10_POWER_CONSTRUCT, ITEM_ZYGARDE_CUBE, 1}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZygarde50PowerConstructFormChangeTable[] = { - {}, - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ZYGARDE_10_POWER_CONSTRUCT, ITEM_ZYGARDE_CUBE, 0}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ZYGARDE_50_AURA_BREAK, ITEM_ZYGARDE_CUBE, 1}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_ZYGARDE_COMPLETE, ABILITY_POWER_CONSTRUCT, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZygarde10PowerConstructFormChangeTable[] = { - {}, - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ZYGARDE_50_POWER_CONSTRUCT, ITEM_ZYGARDE_CUBE, 0}, + {FORM_CHANGE_ITEM_USE_MULTICHOICE, SPECIES_ZYGARDE_10_AURA_BREAK, ITEM_ZYGARDE_CUBE, 1}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_ZYGARDE_COMPLETE, ABILITY_POWER_CONSTRUCT, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZygardeCompleteFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_FAINT}, + {FORM_CHANGE_END_BATTLE}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ZYGARDE #if P_FAMILY_DIANCIE static const struct FormChange sDiancieFormChangeTable[] = { - {}, - {}, +#if P_MEGA_EVOLUTIONS + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DIANCIE_MEGA, ITEM_DIANCITE}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_DIANCIE #if P_FAMILY_HOOPA static const struct FormChange sHoopaFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA_CONFINED}, + {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA_CONFINED}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_HOOPA #if P_FAMILY_ORICORIO static const struct FormChange sOricorioFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_BAILE, 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}, }; #endif //P_FAMILY_ORICORIO #if P_FAMILY_WISHIWASHI 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_SOLO, ABILITY_SCHOOLING, HP_LOWER_EQ_THAN, 25}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI_SOLO}, + {FORM_CHANGE_FAINT, SPECIES_WISHIWASHI_SOLO}, + {FORM_CHANGE_END_BATTLE, SPECIES_WISHIWASHI_SOLO}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_WISHIWASHI #if P_FAMILY_TYPE_NULL static const struct FormChange sSilvallyFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_NORMAL, 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}, }; #endif //P_FAMILY_TYPE_NULL #if P_FAMILY_MINIOR static const struct FormChange sMiniorRedFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_RED, 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 //P_FAMILY_MINIOR #if P_FAMILY_MIMIKYU static const struct FormChange sMimikyuFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_FAINT, SPECIES_MIMIKYU_DISGUISED}, + {FORM_CHANGE_END_BATTLE, SPECIES_MIMIKYU_DISGUISED}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMimikyuTotemFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_MIMIKYU_TOTEM_DISGUISED}, + {FORM_CHANGE_END_BATTLE, SPECIES_MIMIKYU_TOTEM_DISGUISED}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MIMIKYU #if P_FAMILY_NECROZMA static const struct Fusion sNecrozmaFusionTable[] = { - {}, - {}, - {}, + {1, ITEM_N_SOLARIZER, SPECIES_NECROZMA, SPECIES_SOLGALEO, SPECIES_NECROZMA_DUSK_MANE, MOVE_SUNSTEEL_STRIKE, MOVE_CONFUSION}, + {2, ITEM_N_LUNARIZER, SPECIES_NECROZMA, SPECIES_LUNALA, SPECIES_NECROZMA_DAWN_WINGS, MOVE_MOONGEIST_BEAM, MOVE_CONFUSION}, + {FUSION_TERMINATOR}, }; static const struct FormChange sNecrozmaDuskManeFormChangeTable[] = { - {}, - {}, +#if P_ULTRA_BURST_FORMS + {FORM_CHANGE_BATTLE_ULTRA_BURST, SPECIES_NECROZMA_ULTRA, ITEM_ULTRANECROZIUM_Z}, +#endif + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sNecrozmaDawnWingsFormChangeTable[] = { - {}, - {}, +#if P_ULTRA_BURST_FORMS + {FORM_CHANGE_BATTLE_ULTRA_BURST, SPECIES_NECROZMA_ULTRA, ITEM_ULTRANECROZIUM_Z}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_NECROZMA #if P_FAMILY_MELTAN static const struct FormChange sMelmetalFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_MELMETAL_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MELTAN #if P_FAMILY_GROOKEY static const struct FormChange sRillaboomFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_RILLABOOM_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_GROOKEY #if P_FAMILY_SCORBUNNY static const struct FormChange sCinderaceFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_CINDERACE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SCORBUNNY #if P_FAMILY_SOBBLE static const struct FormChange sInteleonFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_INTELEON_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SOBBLE #if P_FAMILY_ROOKIDEE static const struct FormChange sCorviknightFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_CORVIKNIGHT_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ROOKIDEE #if P_FAMILY_BLIPBUG static const struct FormChange sOrbeetleFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_ORBEETLE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_BLIPBUG #if P_FAMILY_CHEWTLE static const struct FormChange sDrednawFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_DREDNAW_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_CHEWTLE #if P_FAMILY_ROLYCOLY static const struct FormChange sCoalossalFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_COALOSSAL_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ROLYCOLY #if P_FAMILY_APPLIN static const struct FormChange sFlappleFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_FLAPPLE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sAppletunFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_APPLETUN_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_APPLIN #if P_FAMILY_SILICOBRA static const struct FormChange sSandacondaFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_SANDACONDA_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SILICOBRA #if P_FAMILY_CRAMORANT 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}, }; #endif //P_FAMILY_CRAMORANT #if P_FAMILY_TOXEL static const struct FormChange sToxtricityAmpedFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_TOXTRICITY_AMPED_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sToxtricityLowKeyFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_TOXTRICITY_LOW_KEY_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_TOXEL #if P_FAMILY_SIZZLIPEDE static const struct FormChange sCentiskorchFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_CENTISKORCH_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_SIZZLIPEDE #if P_FAMILY_HATENNA static const struct FormChange sHattereneFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_HATTERENE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_HATENNA #if P_FAMILY_IMPIDIMP static const struct FormChange sGrimmsnarlFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_GRIMMSNARL_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_IMPIDIMP #if P_FAMILY_MILCERY static const struct FormChange sAlcremieFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_ALCREMIE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MILCERY #if P_FAMILY_EISCUE static const struct FormChange sEiscueFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_FAINT, SPECIES_EISCUE_ICE_FACE}, + {FORM_CHANGE_END_BATTLE, SPECIES_EISCUE_ICE_FACE}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_EISCUE #if P_FAMILY_MORPEKO static const struct FormChange sMorpekoFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_BATTLE_TURN_END, SPECIES_MORPEKO_HANGRY, ABILITY_HUNGER_SWITCH}, + {FORM_CHANGE_BATTLE_TURN_END, SPECIES_MORPEKO_FULL_BELLY, ABILITY_HUNGER_SWITCH}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO_FULL_BELLY}, + {FORM_CHANGE_FAINT, SPECIES_MORPEKO_FULL_BELLY}, + {FORM_CHANGE_END_BATTLE, SPECIES_MORPEKO_FULL_BELLY}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_MORPEKO #if P_FAMILY_CUFANT static const struct FormChange sCopperajahFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_COPPERAJAH_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_CUFANT #if P_FAMILY_DURALUDON static const struct FormChange sDuraludonFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_DURALUDON_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_DURALUDON #if P_FAMILY_ZACIAN static const struct FormChange sZacianFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, + {FORM_CHANGE_END_BATTLE, SPECIES_ZACIAN_HERO_OF_MANY_BATTLES, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ZACIAN #if P_FAMILY_ZAMAZENTA static const struct FormChange sZamazentaFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, + {FORM_CHANGE_END_BATTLE, SPECIES_ZAMAZENTA_HERO_OF_MANY_BATTLES, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ZAMAZENTA #if P_FAMILY_KUBFU static const struct FormChange sUrshifuSingleStrikeFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_URSHIFU_SINGLE_STRIKE_STYLE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sUrshifuRapidStrikeFormChangeTable[] = { - {}, - {}, +#if P_GIGANTAMAX_FORMS + {FORM_CHANGE_BATTLE_GIGANTAMAX, SPECIES_URSHIFU_RAPID_STRIKE_STYLE_GIGANTAMAX}, +#endif + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_KUBFU #if P_FAMILY_CALYREX static const struct Fusion sCalyrexFusionTable[] = { - {}, - {}, - {}, + {3, ITEM_REINS_OF_UNITY, SPECIES_CALYREX, SPECIES_GLASTRIER, SPECIES_CALYREX_ICE_RIDER, MOVE_GLACIAL_LANCE, MOVE_CONFUSION}, + {3, ITEM_REINS_OF_UNITY, SPECIES_CALYREX, SPECIES_SPECTRIER, SPECIES_CALYREX_SHADOW_RIDER, MOVE_ASTRAL_BARRAGE, MOVE_CONFUSION}, + {FUSION_TERMINATOR}, }; #endif //P_FAMILY_CALYREX #if P_FAMILY_ENAMORUS static const struct FormChange sEnamorusFormChangeTable[] = { - {}, - {}, - {}, + {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS_INCARNATE, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_ENAMORUS #if P_FAMILY_FINIZEN static const struct FormChange sPalafinZeroFormChangeTable[] = { - {}, - {}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_PALAFIN_HERO}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_FINIZEN #if P_FAMILY_OGERPON static const struct FormChange sOgerponFormChangeTable[] = { - {}, - {}, - {}, - {}, - {}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_OGERPON_TEAL_MASK, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_OGERPON_WELLSPRING_MASK, ITEM_WELLSPRING_MASK}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_OGERPON_HEARTHFLAME_MASK, ITEM_HEARTHFLAME_MASK}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_OGERPON_CORNERSTONE_MASK, ITEM_CORNERSTONE_MASK}, + {FORM_CHANGE_TERMINATOR}, }; #endif //P_FAMILY_OGERPON +#if P_FAMILY_TERAPAGOS +static const struct FormChange sTerapagosFormChangeTable[] = { + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_TERAPAGOS_TERASTAL}, //needs to be tied to the ability +#if P_TERA_FORMS + //{FORM_CHANGE_TERASTALLIZATION, SPECIES_TERAPAGOS_STELLAR}, +#endif + {FORM_CHANGE_END_BATTLE, SPECIES_TERAPAGOS_NORMAL}, + {FORM_CHANGE_TERMINATOR}, +}; +#endif //P_FAMILY_TERAPAGOS + #undef WHEN_LEARNED #undef WHEN_FORGOTTEN diff --git a/src/party_menu.c b/src/party_menu.c index 024aa8045..edd1cb200 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -5128,7 +5128,7 @@ bool8 MonKnowsMove(struct Pokemon *mon, u16 move) { u8 i; - for (i = 0; i < MAX_MON_MOVES; ++i) + for (i = 0; i < MAX_MON_MOVES; i++) { if (GetMonData(mon, MON_DATA_MOVE1 + i) == move) return TRUE; @@ -5136,6 +5136,18 @@ bool8 MonKnowsMove(struct Pokemon *mon, u16 move) return FALSE; } +bool8 BoxMonKnowsMove(struct BoxPokemon *boxMon, u16 move) +{ + u8 i; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (GetBoxMonData(boxMon, MON_DATA_MOVE1 + i) == move) + return TRUE; + } + return FALSE; +} + static void DisplayLearnMoveMessage(const u8 *str) { StringExpandPlaceholders(gStringVar4, str); diff --git a/src/pokemon.c b/src/pokemon.c index 247491e71..34e767972 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -30,6 +30,7 @@ #include "constants/items.h" #include "constants/item_effects.h" #include "constants/cries.h" +#include "constants/form_change_types.h" #include "constants/pokemon.h" #include "constants/abilities.h" #include "constants/moves.h" @@ -1673,6 +1674,17 @@ void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot) SetMonData(mon, MON_DATA_PP1 + slot, &gMovesInfo[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); + u16 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; @@ -6171,6 +6183,140 @@ u16 GetFormSpeciesId(u16 speciesId, u8 formId) return speciesId; } +u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId) +{ + u8 targetFormId = 0; + + if (GetSpeciesFormTable(formSpeciesId) != NULL) + { + for (targetFormId = 0; GetSpeciesFormTable(formSpeciesId)[targetFormId] != FORM_SPECIES_END; targetFormId++) + { + if (formSpeciesId == GetSpeciesFormTable(formSpeciesId)[targetFormId]) + break; + } + } + return targetFormId; +} + +u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg) +{ + return GetFormChangeTargetSpeciesBoxMon(&mon->box, method, arg); +} + +// Returns SPECIES_NONE if no form change is possible +u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg) +{ + u32 i; + u16 targetSpecies = SPECIES_NONE; + u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); + const struct FormChange *formChanges = GetSpeciesFormChanges(species); + u16 heldItem; + u32 ability; + + if (formChanges != NULL) + { + 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_TERMINATOR; i++) + { + if (method == formChanges[i].method && species != formChanges[i].targetSpecies) + { + switch (method) + { + 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_CHANGE_ITEM_USE: + if (arg == formChanges[i].param1) + { + // TODO: time + switch (formChanges[i].param2) + { + case DAY: + // if (GetTimeOfDay() != TIME_NIGHT) + // targetSpecies = formChanges[i].targetSpecies; + targetSpecies = SPECIES_NONE; + break; + case NIGHT: + // if (GetTimeOfDay() == TIME_NIGHT) + // targetSpecies = formChanges[i].targetSpecies; + targetSpecies = SPECIES_NONE; + break; + default: + targetSpecies = formChanges[i].targetSpecies; + break; + } + } + break; + case FORM_CHANGE_ITEM_USE_MULTICHOICE: + if (arg == formChanges[i].param1) + { + if (formChanges[i].param2 == gSpecialVar_Result) + targetSpecies = formChanges[i].targetSpecies; + } + break; + case FORM_CHANGE_MOVE: + if (BoxMonKnowsMove(boxMon, formChanges[i].param1) != formChanges[i].param2) + targetSpecies = formChanges[i].targetSpecies; + break; + 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: + case FORM_CHANGE_STATUS: + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_TIME_OF_DAY: + // TODO: time + // switch (formChanges[i].param1) + // { + // case DAY: + // if (GetTimeOfDay() != TIME_NIGHT) + // targetSpecies = formChanges[i].targetSpecies; + // break; + // case NIGHT: + // if (GetTimeOfDay() == TIME_NIGHT) + // targetSpecies = formChanges[i].targetSpecies; + // break; + // } + // break; + targetSpecies = SPECIES_NONE; + break; + } + } + } + } + + return targetSpecies; +} + +bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method) +{ + u32 i; + const struct FormChange *formChanges = GetSpeciesFormChanges(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; +} + u32 GetMonAffectionHearts(struct Pokemon *pokemon) { u32 friendship = GetMonData(pokemon, MON_DATA_FRIENDSHIP, NULL); @@ -6188,3 +6334,34 @@ u32 GetMonAffectionHearts(struct Pokemon *pokemon) return AFFECTION_NO_HEARTS; } + +void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method) +{ + int i, j; + u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); + const struct FormChange *formChanges = GetSpeciesFormChanges(species); + + if (formChanges == NULL + || (method != FORM_CHANGE_BEGIN_BATTLE && method != FORM_CHANGE_END_BATTLE)) + return; + + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) + { + 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; + + for (j = 0; j < MAX_MON_MOVES; j++) + { + u16 currMove = GetMonData(mon, MON_DATA_MOVE1 + j, NULL); + if (currMove == originalMove) + SetMonMoveSlot_KeepPP(mon, newMove, j); + } + break; + } + } +}