diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 135960c12..ec83a6c2d 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1760,6 +1760,10 @@ various BS_ABILITY_BATTLER, VARIOUS_DESTROY_ABILITY_POPUP .endm + .macro tryactivategrimneigh, battler:req + various \battler, VARIOUS_TRY_ACTIVATE_GRIM_NEIGH + .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 3eb1f5cbe..88e474373 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -4965,8 +4965,9 @@ BattleScript_FaintTarget:: tryactivatefellstinger BS_ATTACKER tryactivatesoulheart tryactivatereceiver BS_TARGET - tryactivatemoxie BS_ATTACKER + tryactivatemoxie BS_ATTACKER @ and chilling neigh, as one ice rider tryactivatebeastboost BS_ATTACKER + tryactivategrimneigh BS_ATTACKER @ and as one shadow rider trytrainerslidefirstdownmsg BS_TARGET return diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 2f52da319..e68278b1d 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -167,6 +167,7 @@ #define VARIOUS_PARALYZE_TYPE_IMMUNITY 100 #define VARIOUS_JUMP_IF_ABSENT 101 #define VARIOUS_DESTROY_ABILITY_POPUP 102 +#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 103 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 9348d67d5..10562bd98 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -558,8 +558,9 @@ #define STRINGID_AURABREAKENTERS 554 #define STRINGID_COMATOSEENTERS 555 #define STRINGID_SCREENCLEANERENTERS 556 +#define STRINGID_ASONEENTERS 557 -#define BATTLESTRINGS_COUNT 557 +#define BATTLESTRINGS_COUNT 558 //// multichoice message IDs // switch in ability message @@ -576,5 +577,6 @@ #define MULTI_SWITCHIN_AURABREAK 10 #define MULTI_SWITCHIN_COMATOSE 11 #define MULTI_SWITCHIN_SCREENCLEANER 12 +#define MULTI_SWITCHIN_ASONE 13 #endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H diff --git a/src/battle_message.c b/src/battle_message.c index 35ccc6e26..c629d3092 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -685,9 +685,11 @@ static const u8 sText_FairyAuraActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} static const u8 sText_AuraBreakActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} reversed all\nother POKéMON's auras!"); static const u8 sText_ComatoseActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is drowsing!"); static const u8 sText_ScreenCleanerActivates[] = _("All screens on the field were\ncleansed!"); +static const u8 sText_AsOneEnters[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} has two Abilities!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_ASONEENTERS - 12] = sText_AsOneEnters, [STRINGID_STATWASNOTLOWERED - 12] = sText_StatWasNotLowered, [STRINGID_CLOAKEDINAFREEZINGLIGHT - 12] = sText_CloakedInAFreezingLight, [STRINGID_DESTINYKNOTACTIVATES - 12] = sText_DestinyKnotActivates, @@ -1275,6 +1277,7 @@ const u16 gSwitchInAbilityStringIds[] = [MULTI_SWITCHIN_AURABREAK] = STRINGID_AURABREAKENTERS, [MULTI_SWITCHIN_COMATOSE] = STRINGID_COMATOSEENTERS, [MULTI_SWITCHIN_SCREENCLEANER] = STRINGID_SCREENCLEANERENTERS, + [MULTI_SWITCHIN_ASONE] = STRINGID_ASONEENTERS, }; const u16 gMissStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index bc427698e..0857b1c5e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7527,11 +7527,13 @@ static void Cmd_various(void) BtlController_EmitSetMonData(0, REQUEST_PP_DATA_BATTLE, 0, 5, data); MarkBattlerForControllerExec(gActiveBattler); break; - case VARIOUS_TRY_ACTIVATE_MOXIE: - if (GetBattlerAbility(gActiveBattler) == ABILITY_MOXIE - && HasAttackerFaintedTarget() - && !NoAliveMonsForEitherParty() - && gBattleMons[gBattlerAttacker].statStages[STAT_ATK] != 12) + case VARIOUS_TRY_ACTIVATE_MOXIE: // and chilling neigh + as one ice rider + if ((GetBattlerAbility(gActiveBattler) == ABILITY_MOXIE + || GetBattlerAbility(gActiveBattler) == ABILITY_CHILLING_NEIGH + || GetBattlerAbility(gActiveBattler) == ABILITY_AS_ONE_ICE_RIDER) + && HasAttackerFaintedTarget() + && !NoAliveMonsForEitherParty() + && gBattleMons[gBattlerAttacker].statStages[STAT_ATK] != 12) { gBattleMons[gBattlerAttacker].statStages[STAT_ATK]++; SET_STATCHANGER(STAT_ATK, 1, FALSE); @@ -7541,6 +7543,21 @@ static void Cmd_various(void) return; } break; + case VARIOUS_TRY_ACTIVATE_GRIM_NEIGH: // and as one shadow rider + if ((GetBattlerAbility(gActiveBattler) == ABILITY_GRIM_NEIGH + || GetBattlerAbility(gActiveBattler) == ABILITY_AS_ONE_SHADOW_RIDER) + && HasAttackerFaintedTarget() + && !NoAliveMonsForEitherParty() + && gBattleMons[gBattlerAttacker].statStages[STAT_SPATK] != 12) + { + gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]++; + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK); + BattleScriptPush(gBattlescriptCurrInstr + 3); + gBattlescriptCurrInstr = BattleScript_AttackerAbilityStatRaise; + return; + } + break; case VARIOUS_TRY_ACTIVATE_RECEIVER: // Partner gets fainted's ally ability gBattlerAbility = BATTLE_PARTNER(gActiveBattler); i = GetBattlerAbility(gBattlerAbility); diff --git a/src/battle_util.c b/src/battle_util.c index 397a011bb..f7804851c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -54,6 +54,7 @@ functions instead of at the top of the file with the other declarations. */ static bool32 TryRemoveScreens(u8 battler); +static bool32 IsUnnerveAbilityOnOpposingSide(u8 battlerId); extern const u8 *const gBattleScriptsForMoveEffects[]; extern const u8 *const gBattlescriptsForBallThrow[]; @@ -3701,6 +3702,16 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move effect++; } break; + case ABILITY_AS_ONE_ICE_RIDER: + case ABILITY_AS_ONE_SHADOW_RIDER: + if (!gSpecialStatuses[battler].switchInAbilityDone) + { + gBattleCommunication[MULTISTRING_CHOOSER] = MULTI_SWITCHIN_ASONE; + gSpecialStatuses[battler].switchInAbilityDone = 1; + BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg); + effect++; + } + break; case ABILITY_ANTICIPATION: if (!gSpecialStatuses[battler].switchInAbilityDone) { @@ -4986,7 +4997,7 @@ static bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId) if (gBattleMons[battlerId].hp == 0) return FALSE; // Unnerve prevents consumption of opponents' berries. - if (isBerry && IsAbilityOnOpposingSide(battlerId, ABILITY_UNNERVE)) + if (isBerry && IsUnnerveAbilityOnOpposingSide(battlerId)) return FALSE; if (gBattleMons[battlerId].hp <= gBattleMons[battlerId].maxHP / hpFraction) return TRUE; @@ -5100,7 +5111,7 @@ static u8 ItemHealHp(u32 battlerId, u32 itemId, bool32 end2, bool32 percentHeal) static bool32 UnnerveOn(u32 battlerId, u32 itemId) { - if (ItemId_GetPocket(itemId) == POCKET_BERRIES && IsAbilityOnOpposingSide(battlerId, ABILITY_UNNERVE)) + if (ItemId_GetPocket(itemId) == POCKET_BERRIES && IsUnnerveAbilityOnOpposingSide(battlerId)) return TRUE; return FALSE; } @@ -7871,3 +7882,12 @@ static bool32 TryRemoveScreens(u8 battler) return removed; } + +static bool32 IsUnnerveAbilityOnOpposingSide(u8 battlerId) +{ + if (IsAbilityOnOpposingSide(battlerId, ABILITY_UNNERVE) + || IsAbilityOnOpposingSide(battlerId, ABILITY_AS_ONE_ICE_RIDER) + || IsAbilityOnOpposingSide(battlerId, ABILITY_AS_ONE_SHADOW_RIDER)) + return TRUE; + return FALSE; +}