diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 328780f53a..b7a60dbbba 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1878,6 +1878,11 @@ .4byte \ptr .endm + .macro trytoapplymimicry battler:req, ptr:req + various \battler, VARIOUS_TRY_TO_APPLY_MIMICRY + .4byte \ptr + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6d6c1dae8b..79c6b7f792 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1908,6 +1908,23 @@ BattleScript_EffectPsychicTerrain: waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG, NULL call BattleScript_TerrainSeedLoop + jumpifabilitypresent ABILITY_MIMICRY, BattleScript_ApplyMimicry + goto BattleScript_MoveEnd + +BattleScript_ApplyMimicry:: + savetarget + setbyte gBattlerTarget, 0 +BattleScript_MimicryLoopIter: + copybyte sBATTLER, gBattlerTarget + trytoapplymimicry BS_TARGET, BattleScript_MimicryLoop_NextBattler + copybyte gBattlerAbility, sBATTLER + call BattleScript_AbilityPopUp + printstring STRINGID_BATTLERTYPECHANGEDTO + waitmessage B_WAIT_TIME_LONG +BattleScript_MimicryLoop_NextBattler: + addbyte gBattlerTarget, 0x1 + jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_MimicryLoopIter + restoretarget goto BattleScript_MoveEnd BattleScript_EffectTopsyTurvy: @@ -8002,6 +8019,12 @@ BattleScript_ColorChangeActivates:: waitmessage B_WAIT_TIME_LONG return +BattleScript_MimicryActivatesEnd3:: + call BattleScript_AbilityPopUp + printstring STRINGID_BATTLERTYPECHANGEDTO + waitmessage B_WAIT_TIME_LONG + end3 + BattleScript_ProteanActivates:: call BattleScript_AbilityPopUp printstring STRINGID_PKMNCHANGEDTYPE diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 12212ff94a..dc1e046b63 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -407,5 +407,7 @@ extern const u8 BattleScript_WanderingSpiritActivates[]; extern const u8 BattleScript_MirrorArmorReflect[]; extern const u8 BattleScript_GooeyActivates[]; extern const u8 BattleScript_PastelVeilActivates[]; +extern const u8 BattleScript_MimicryActivatesEnd3[]; +extern const u8 BattleScript_ApplyMimicry[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/battle_util.h b/include/battle_util.h index d0a9d8f87f..c799d9a58b 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -157,6 +157,9 @@ void DoBurmyFormChange(u32 monId); bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget); u16 GetUsedHeldItem(u8 battler); bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags); +void TryToApplyMimicry(u8 battlerId, bool8 various); +void TryToRevertMimicry(void); +void RestoreBattlerOriginalTypes(u8 battlerId); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 3b4495208f..50db280280 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -198,6 +198,7 @@ #define VARIOUS_JUMP_IF_WEATHER_AFFECTED 125 #define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 126 #define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 127 +#define VARIOUS_TRY_TO_APPLY_MIMICRY 128 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 3eb5dc9a44..74105f3bfe 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -601,8 +601,9 @@ #define STRINGID_SWAPPEDABILITIES 598 #define STRINGID_PASTELVEILPROTECTED 599 #define STRINGID_PASTELVEILENTERS 600 +#define STRINGID_BATTLERTYPECHANGEDTO 601 -#define BATTLESTRINGS_COUNT 601 +#define BATTLESTRINGS_COUNT 602 // The below IDs are all indexes into battle message tables, // used to determine which of a set of messages to print. diff --git a/src/battle_message.c b/src/battle_message.c index a1a24b3b13..60b7f5203d 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -727,9 +727,11 @@ static const u8 sText_AbilityAllowsOnlyMove[] = _("{B_ATK_ABILITY} allows the\nu static const u8 sText_SwappedAbilities[] = _("{B_DEF_NAME_WITH_PREFIX} swapped Abilities\nwith its target!"); static const u8 sText_PastelVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} is protected\nby a pastel veil!"); static const u8 sText_PastelVeilEnters[] = _("{B_DEF_NAME_WITH_PREFIX} was cured\nof its poisoning!"); +static const u8 sText_BattlerTypeChangedTo[] = _("{B_BUFF1}'s type\nchanged to {B_BUFF2}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_BATTLERTYPECHANGEDTO - 12] = sText_BattlerTypeChangedTo, [STRINGID_PASTELVEILENTERS - 12] = sText_PastelVeilEnters, [STRINGID_PASTELVEILPROTECTED -12] = sText_PastelVeilProtected, [STRINGID_SWAPPEDABILITIES - 12] = sText_SwappedAbilities, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ee9379d8d1..68992b8ec3 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -54,6 +54,7 @@ #include "constants/rgb.h" #include "data.h" #include "constants/party_menu.h" +#include "battle_util.h" extern struct MusicPlayerInfo gMPlayInfo_BGM; extern struct Evolution gEvolutionTable[][EVOS_PER_MON]; @@ -8858,6 +8859,7 @@ static void Cmd_various(void) break; } gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; // remove the terrain + TryToRevertMimicry(); // restore the types of Pokémon with Mimicry break; case VARIOUS_JUMP_IF_PRANKSTER_BLOCKED: if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gActiveBattler, TRUE)) @@ -9017,6 +9019,21 @@ static void Cmd_various(void) if (gBattleStruct->stickyWebUser != 0xFF) gBattlerAttacker = gBattleStruct->stickyWebUser; break; + case VARIOUS_TRY_TO_APPLY_MIMICRY: + { + bool8 isMimicryDone = FALSE; + + if (GetBattlerAbility(gActiveBattler) == ABILITY_MIMICRY) + { + TryToApplyMimicry(gActiveBattler, TRUE); + isMimicryDone = TRUE; + } + if (!isMimicryDone) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + else + gBattlescriptCurrInstr += 7; + return; + } } gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index f87e0a1341..5a9d47df98 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1894,6 +1894,57 @@ u8 GetImprisonedMovesCount(u8 battlerId, u16 move) return imprisonedMoves; } +void RestoreBattlerOriginalTypes(u8 battlerId) +{ + gBattleMons[battlerId].type1 = gBaseStats[gBattleMons[battlerId].species].type1; + gBattleMons[battlerId].type2 = gBaseStats[gBattleMons[battlerId].species].type2; +} + +void TryToApplyMimicry(u8 battlerId, bool8 various) +{ + u32 moveType, move; + + GET_MOVE_TYPE(move, moveType); + switch (gFieldStatuses) + { + case STATUS_FIELD_ELECTRIC_TERRAIN: + moveType = TYPE_ELECTRIC; + break; + case STATUS_FIELD_MISTY_TERRAIN: + moveType = TYPE_FAIRY; + break; + case STATUS_FIELD_GRASSY_TERRAIN: + moveType = TYPE_GRASS; + break; + case STATUS_FIELD_PSYCHIC_TERRAIN: + moveType = TYPE_PSYCHIC; + break; + default: + moveType = 0; + break; + } + + if (moveType != 0 && !IS_BATTLER_OF_TYPE(battlerId, moveType)) + { + SET_BATTLER_TYPE(battlerId, moveType); + PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battlerId, gBattlerPartyIndexes[battlerId]) + PREPARE_TYPE_BUFFER(gBattleTextBuff2, moveType); + if (!various) + BattleScriptPushCursorAndCallback(BattleScript_MimicryActivatesEnd3); + } +} + +void TryToRevertMimicry(void) +{ + s32 i; + + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (GetBattlerAbility(i) == ABILITY_MIMICRY) + RestoreBattlerOriginalTypes(i); + } +} + enum { ENDTURN_ORDER, @@ -2278,6 +2329,7 @@ u8 DoFieldEndTurnEffects(void) && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.electricTerrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); + TryToRevertMimicry(); BattleScriptExecute(BattleScript_ElectricTerrainEnds); effect++; } @@ -2288,6 +2340,7 @@ u8 DoFieldEndTurnEffects(void) && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.mistyTerrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN); + TryToRevertMimicry(); BattleScriptExecute(BattleScript_MistyTerrainEnds); effect++; } @@ -2298,8 +2351,10 @@ u8 DoFieldEndTurnEffects(void) { if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && (gFieldTimers.grassyTerrainTimer == 0 || --gFieldTimers.grassyTerrainTimer == 0)) + { gFieldStatuses &= ~(STATUS_FIELD_GRASSY_TERRAIN); - + TryToRevertMimicry(); + } BattleScriptExecute(BattleScript_GrassyTerrainHeals); effect++; } @@ -2310,6 +2365,7 @@ u8 DoFieldEndTurnEffects(void) && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.psychicTerrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_PSYCHIC_TERRAIN); + TryToRevertMimicry(); BattleScriptExecute(BattleScript_PsychicTerrainEnds); effect++; } @@ -4390,6 +4446,13 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move effect++; } break; + case ABILITY_MIMICRY: + if (gBattleMons[battler].hp != 0 && gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + { + TryToApplyMimicry(battler, FALSE); + effect++; + } + break; } break; case ABILITYEFFECT_ENDTURN: // 1