diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index ffe481086bec..cfdc2792b48c 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1366,6 +1366,12 @@ .byte \battler .endm + .macro trysetoctolock battler:req, failInstr:req + callnative BS_TrySetOctolock + .byte \battler + .4byte \failInstr + .endm + .macro setzeffect callnative BS_SetZEffect .endm @@ -2087,11 +2093,6 @@ .4byte \failInstr .endm - .macro setoctolock battler:req, failInstr:req - various \battler, VARIOUS_SET_OCTOLOCK - .4byte \failInstr - .endm - .macro cutonethirdhpraisestats failInstr:req various BS_ATTACKER, VARIOUS_CUT_1_3_HP_RAISE_STATS .4byte \failInstr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index ca6f73e908fd..01688c0dce45 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -446,33 +446,20 @@ BattleScript_EffectSyrupBomb:: call BattleScript_EffectHit_Ret seteffectwithchance tryfaintmon BS_TARGET + goto BattleScript_MoveEnd + +BattleScript_SyrupBombActivates:: printstring STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_SyrupBombEndTurn:: - setbyte sSTAT_ANIM_PLAYED, FALSE - copybyte sBATTLER, gBattlerTarget - jumpifholdeffect BS_TARGET, HOLD_EFFECT_CLEAR_AMULET, BattleScript_SyrupBombItemNoStatLoss - jumpifability BS_TARGET, ABILITY_CLEAR_BODY, BattleScript_SyrupBombAbilityNoStatLoss - jumpifability BS_TARGET, ABILITY_FULL_METAL_BODY, BattleScript_SyrupBombAbilityNoStatLoss - jumpifability BS_TARGET, ABILITY_WHITE_SMOKE, BattleScript_SyrupBombAbilityNoStatLoss - jumpifstat BS_TARGET, CMP_GREATER_THAN, BIT_SPEED, MIN_STAT_STAGE, BattleScript_SyrupBombLowerSpeed - goto BattleScript_SyrupBombEnd2 -BattleScript_SyrupBombLowerSpeed: playstatchangeanimation BS_ATTACKER, BIT_SPEED, STAT_CHANGE_NEGATIVE - setbyte sSTAT_ANIM_PLAYED, TRUE setstatchanger STAT_SPEED, 1, TRUE - statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_SyrupBombEnd2 - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_SyrupBombEnd2 + statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_SyrupBombTurnDmgEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG -BattleScript_SyrupBombItemNoStatLoss:: - call BattleScript_ItemNoStatLoss - goto BattleScript_SyrupBombEnd2 -BattleScript_SyrupBombAbilityNoStatLoss:: - call BattleScript_AbilityNoStatLoss -BattleScript_SyrupBombEnd2:: +BattleScript_SyrupBombTurnDmgEnd: end2 BattleScript_EffectMatchaGotcha:: @@ -1073,7 +1060,7 @@ BattleScript_EffectOctolock: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - setoctolock BS_TARGET, BattleScript_ButItFailed + trysetoctolock BS_TARGET, BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE @@ -1081,29 +1068,19 @@ BattleScript_EffectOctolock: goto BattleScript_MoveEnd BattleScript_OctolockEndTurn:: - setbyte sSTAT_ANIM_PLAYED, FALSE - jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_OctolockLowerDef - jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_OctolockTryLowerSpDef - goto BattleScript_OctolockEnd2 -BattleScript_OctolockLowerDef: - jumpifability BS_TARGET, ABILITY_BIG_PECKS, BattleScript_OctolockTryLowerSpDef playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE - setbyte sSTAT_ANIM_PLAYED, TRUE setstatchanger STAT_DEF, 1, TRUE - statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_OctolockTryLowerSpDef - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_OctolockTryLowerSpDef - printfromtable gStatUpStringIds + statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTryLowerSpDef +BattleScript_OctolockTryLowerDef: + printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_OctolockTryLowerSpDef: - jumpifbyte CMP_EQUAL, sSTAT_ANIM_PLAYED, TRUE, BattleScript_OctolockSkipSpDefAnim - playstatchangeanimation BS_ATTACKER, BIT_SPDEF, STAT_CHANGE_NEGATIVE -BattleScript_OctolockSkipSpDefAnim: setstatchanger STAT_SPDEF, 1, TRUE - statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_OctolockEnd2 - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_OctolockEnd2 - printfromtable gStatUpStringIds + statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctlockTurnDmgEnd +BattleScript_OctolockTurnDmgPrintMsg: + printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG -BattleScript_OctolockEnd2:: +BattleScript_OctlockTurnDmgEnd: end2 BattleScript_EffectPoltergeist: @@ -8578,13 +8555,6 @@ BattleScript_IntimidateLoop: jumpiftargetally BattleScript_IntimidateLoopIncrement jumpifabsent BS_TARGET, BattleScript_IntimidateLoopIncrement jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_IntimidateLoopIncrement - jumpifability BS_TARGET, ABILITY_HYPER_CUTTER, BattleScript_IntimidatePrevented -.if B_UPDATED_INTIMIDATE >= GEN_8 - jumpifability BS_TARGET, ABILITY_INNER_FOCUS, BattleScript_IntimidatePrevented - jumpifability BS_TARGET, ABILITY_SCRAPPY, BattleScript_IntimidatePrevented - jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_IntimidatePrevented - jumpifability BS_TARGET, ABILITY_OBLIVIOUS, BattleScript_IntimidatePrevented -.endif jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_IntimidateInReverse BattleScript_IntimidateEffect: copybyte sBATTLER, gBattlerAttacker @@ -8617,16 +8587,6 @@ BattleScript_IntimidateContrary_WontIncrease: printstring STRINGID_TARGETSTATWONTGOHIGHER goto BattleScript_IntimidateEffect_WaitString -BattleScript_IntimidatePrevented: - call BattleScript_AbilityPopUp - pause B_WAIT_TIME_LONG - setbyte gBattleCommunication STAT_ATK - stattextbuffer BS_TARGET - printstring STRINGID_STATWASNOTLOWERED - waitmessage B_WAIT_TIME_LONG - call BattleScript_TryAdrenalineOrb - goto BattleScript_IntimidateLoopIncrement - BattleScript_IntimidateInReverse: copybyte sBATTLER, gBattlerTarget call BattleScript_AbilityPopUpTarget @@ -8933,7 +8893,7 @@ BattleScript_AbilityNoStatLoss:: BattleScript_ItemNoStatLoss:: pause B_WAIT_TIME_SHORT - printstring STRINGID_STATWASNOTLOWERED + printstring STRINGID_CLEARAMULETWONTLOWERSTATS waitmessage B_WAIT_TIME_LONG return diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 3cfc9ace1606..bdcf1081b9d1 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -481,6 +481,7 @@ extern const u8 BattleScript_SelectingNotAllowedCurrentMove[]; extern const u8 BattleScript_SelectingNotAllowedCurrentMoveInPalace[]; extern const u8 BattleScript_SaltCureExtraDamage[]; extern const u8 BattleScript_SyrupBombEndTurn[]; +extern const u8 BattleScript_SyrupBombActivates[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 1775b9528e7d..087af0e30129 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -221,34 +221,33 @@ #define VARIOUS_TRY_TAR_SHOT 128 #define VARIOUS_CAN_TAR_SHOT_WORK 129 #define VARIOUS_CHECK_POLTERGEIST 130 -#define VARIOUS_SET_OCTOLOCK 131 -#define VARIOUS_CUT_1_3_HP_RAISE_STATS 132 -#define VARIOUS_TRY_END_NEUTRALIZING_GAS 133 -#define VARIOUS_JUMP_IF_UNDER_200 134 -#define VARIOUS_SET_SKY_DROP 135 -#define VARIOUS_CLEAR_SKY_DROP 136 -#define VARIOUS_SKY_DROP_YAWN 137 -#define VARIOUS_JUMP_IF_HOLD_EFFECT 138 -#define VARIOUS_CURE_CERTAIN_STATUSES 139 -#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 140 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 141 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 142 -#define VARIOUS_SAVE_BATTLER_ITEM 143 -#define VARIOUS_RESTORE_BATTLER_ITEM 144 -#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 145 -#define VARIOUS_SET_BEAK_BLAST 146 -#define VARIOUS_SWAP_SIDE_STATUSES 147 -#define VARIOUS_SWAP_STATS 148 -#define VARIOUS_TEATIME_INVUL 149 -#define VARIOUS_TEATIME_TARGETS 150 -#define VARIOUS_TRY_WIND_RIDER_POWER 151 -#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 152 -#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 153 -#define VARIOUS_STORE_HEALING_WISH 154 -#define VARIOUS_HIT_SWITCH_TARGET_FAILED 155 -#define VARIOUS_TRY_REVIVAL_BLESSING 156 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE 157 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION 158 +#define VARIOUS_CUT_1_3_HP_RAISE_STATS 131 +#define VARIOUS_TRY_END_NEUTRALIZING_GAS 132 +#define VARIOUS_JUMP_IF_UNDER_200 133 +#define VARIOUS_SET_SKY_DROP 134 +#define VARIOUS_CLEAR_SKY_DROP 135 +#define VARIOUS_SKY_DROP_YAWN 136 +#define VARIOUS_JUMP_IF_HOLD_EFFECT 137 +#define VARIOUS_CURE_CERTAIN_STATUSES 138 +#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 139 +#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 140 +#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 141 +#define VARIOUS_SAVE_BATTLER_ITEM 142 +#define VARIOUS_RESTORE_BATTLER_ITEM 143 +#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 144 +#define VARIOUS_SET_BEAK_BLAST 145 +#define VARIOUS_SWAP_SIDE_STATUSES 146 +#define VARIOUS_SWAP_STATS 147 +#define VARIOUS_TEATIME_INVUL 148 +#define VARIOUS_TEATIME_TARGETS 149 +#define VARIOUS_TRY_WIND_RIDER_POWER 150 +#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 151 +#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 152 +#define VARIOUS_STORE_HEALING_WISH 153 +#define VARIOUS_HIT_SWITCH_TARGET_FAILED 154 +#define VARIOUS_TRY_REVIVAL_BLESSING 155 +#define VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE 156 +#define VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION 157 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 1f5539dc6239..a9a6b7025b01 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -547,7 +547,7 @@ #define STRINGID_NOONEWILLBEABLETORUNAWAY 545 #define STRINGID_DESTINYKNOTACTIVATES 546 #define STRINGID_CLOAKEDINAFREEZINGLIGHT 547 -#define STRINGID_STATWASNOTLOWERED 548 +#define STRINGID_CLEARAMULETWONTLOWERSTATS 548 #define STRINGID_FERVENTWISHREACHED 549 #define STRINGID_AIRLOCKACTIVATES 550 #define STRINGID_PRESSUREENTERS 551 diff --git a/src/battle_message.c b/src/battle_message.c index 116a42d6bc7c..e6e87186b48a 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -702,7 +702,7 @@ static const u8 sText_PkmnAbsorbingPower[] = _("{B_ATK_NAME_WITH_PREFIX} is abso static const u8 sText_NoOneWillBeAbleToRun[] = _("No one will be able to run away\nduring the next turn!"); static const u8 sText_DestinyKnotActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} fell in love\nfrom the {B_LAST_ITEM}!"); static const u8 sText_CloakedInAFreezingLight[] = _("{B_ATK_NAME_WITH_PREFIX} became cloaked\nin a freezing light!"); -static const u8 sText_StatWasNotLowered[] = _("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1}\nwas not lowered!"); +static const u8 sText_ClearAmuletWontLowerStats[] = _("{B_DEF_NAME_WITH_PREFIX}'s {B_LAST_ITEM} prevents\nits stats from being lowered!"); static const u8 sText_AuraFlaredToLife[] = _("{B_DEF_NAME_WITH_PREFIX}'s aura flared to life!"); static const u8 sText_AirLockActivates[] = _("The effects of weather\ndisappeared."); static const u8 sText_PressureActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is exerting its\npressure!"); @@ -924,7 +924,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_ASANDSTORMKICKEDUP - BATTLESTRINGS_TABLE_START] = sText_ASandstormKickedUp, [STRINGID_BATTLERABILITYRAISEDSTAT - BATTLESTRINGS_TABLE_START] = sText_BattlerAbilityRaisedStat, [STRINGID_FETCHEDPOKEBALL - BATTLESTRINGS_TABLE_START] = sText_FetchedPokeBall, - [STRINGID_STATWASNOTLOWERED - BATTLESTRINGS_TABLE_START] = sText_StatWasNotLowered, + [STRINGID_CLEARAMULETWONTLOWERSTATS - BATTLESTRINGS_TABLE_START] = sText_ClearAmuletWontLowerStats, [STRINGID_CLOAKEDINAFREEZINGLIGHT - BATTLESTRINGS_TABLE_START] = sText_CloakedInAFreezingLight, [STRINGID_DESTINYKNOTACTIVATES - BATTLESTRINGS_TABLE_START] = sText_DestinyKnotActivates, [STRINGID_NOONEWILLBEABLETORUNAWAY - BATTLESTRINGS_TABLE_START] = sText_NoOneWillBeAbleToRun, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 82d184b88f1a..94352278dd2f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -354,6 +354,7 @@ static void TryUpdateRoundTurnOrder(void); static bool32 ChangeOrderTargetAfterAttacker(void); void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler); static void RemoveAllTerrains(void); +static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 isIntimidate); static void Cmd_attackcanceler(void); static void Cmd_accuracycheck(void); @@ -3637,15 +3638,12 @@ void SetMoveEffect(bool32 primary, u32 certain) break; case MOVE_EFFECT_SYRUP_BOMB: - if (gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB) - { - gBattlescriptCurrInstr++; - } - else + if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB)) { gStatuses4[gEffectBattler] |= STATUS4_SYRUP_BOMB; gDisableStructs[gBattlerTarget].syrupBombTimer = 3; - gBattlescriptCurrInstr++; + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_SyrupBombActivates; } break; } @@ -9547,7 +9545,7 @@ static void Cmd_various(void) { VARIOUS_ARGS(const u8 *failInstr); u16 move = gLastMoves[gBattlerTarget]; - if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || gBattleMoves[move].effect == EFFECT_RECHARGE + if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || gBattleMoves[move].effect == EFFECT_RECHARGE || gBattleMoves[move].instructBanned || gBattleMoves[move].twoTurnMove || IsDynamaxed(gBattlerTarget)) { gBattlescriptCurrInstr = cmd->failInstr; @@ -10351,22 +10349,6 @@ static void Cmd_various(void) } return; } - case VARIOUS_SET_OCTOLOCK: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gDisableStructs[battler].octolock) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gDisableStructs[battler].octolock = TRUE; - gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION; - gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } case VARIOUS_CHECK_POLTERGEIST: { VARIOUS_ARGS(const u8 *failInstr); @@ -11401,16 +11383,9 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr return STAT_CHANGE_DIDNT_WORK; } else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET - || battlerAbility == ABILITY_CLEAR_BODY - || battlerAbility == ABILITY_FULL_METAL_BODY - || battlerAbility == ABILITY_WHITE_SMOKE) - && (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE) + || CanAbilityPreventStatLoss(battlerAbility, GetBattlerAbility(gBattlerAttacker) == ABILITY_INTIMIDATE)) + && (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE) { - if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET) - { - RecordItemEffectBattle(battler, HOLD_EFFECT_CLEAR_AMULET); - } - if (flags == STAT_CHANGE_ALLOW_PTR) { if (gSpecialStatuses[battler].statLowered) @@ -11423,7 +11398,9 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr gBattleScripting.battler = battler; if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET) { + gLastUsedItem = gBattleMons[battler].item; gBattlescriptCurrInstr = BattleScript_ItemNoStatLoss; + RecordItemEffectBattle(battler, HOLD_EFFECT_CLEAR_AMULET); } else { @@ -15697,6 +15674,25 @@ static bool8 IsFinalStrikeEffect(u16 move) return FALSE; } +static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 byIntimidate) +{ + switch (abilityDef) + { + case ABILITY_CLEAR_BODY: + case ABILITY_FULL_METAL_BODY: + case ABILITY_WHITE_SMOKE: + return TRUE; + case ABILITY_INNER_FOCUS: + case ABILITY_SCRAPPY: + case ABILITY_OWN_TEMPO: + case ABILITY_OBLIVIOUS: + if (byIntimidate && (B_UPDATED_INTIMIDATE >= GEN_8)) + return TRUE; + break; + } + return FALSE; +} + void BS_CheckParentalBondCounter(void) { NATIVE_ARGS(u8 counter, const u8 *jumpInstr); @@ -16264,3 +16260,21 @@ void BS_TryReflectType(void) gBattlescriptCurrInstr = cmd->nextInstr; } } + +void BS_TrySetOctolock(void) +{ + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gDisableStructs[battler].octolock) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gDisableStructs[battler].octolock = TRUE; + gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION; + gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} diff --git a/src/battle_util.c b/src/battle_util.c index afef74b0f80f..ac8e7234a1d5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2735,12 +2735,7 @@ u8 DoBattlerEndTurnEffects(void) break; case ENDTURN_OCTOLOCK: { - u16 battlerAbility = GetBattlerAbility(battler); - if (gDisableStructs[battler].octolock - && !(GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_CLEAR_AMULET - || battlerAbility == ABILITY_CLEAR_BODY - || battlerAbility == ABILITY_FULL_METAL_BODY - || battlerAbility == ABILITY_WHITE_SMOKE)) + if (gDisableStructs[battler].octolock) { gBattlerTarget = battler; BattleScriptExecute(BattleScript_OctolockEndTurn); @@ -3037,19 +3032,11 @@ u8 DoBattlerEndTurnEffects(void) case ENDTURN_SYRUP_BOMB: if ((gStatuses4[battler] & STATUS4_SYRUP_BOMB) && (gBattleMons[battler].hp != 0)) { - gDisableStructs[battler].syrupBombTimer--; - if (gDisableStructs[battler].syrupBombTimer == 0) - { + if (gDisableStructs[battler].syrupBombTimer > 0 && --gDisableStructs[battler].syrupBombTimer == 0) gStatuses4[battler] &= ~STATUS4_SYRUP_BOMB; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SYRUP_BOMB); - gBattlescriptCurrInstr = BattleScript_WrapEnds; - } - else if (gDisableStructs[battler].syrupBombTimer != 0) - { - gBattlerTarget = battler; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SYRUP_BOMB); - gBattlescriptCurrInstr = BattleScript_SyrupBombEndTurn; - } + gBattlerTarget = battler; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SYRUP_BOMB); + gBattlescriptCurrInstr = BattleScript_SyrupBombEndTurn; BattleScriptExecute(gBattlescriptCurrInstr); effect++; } diff --git a/test/battle/ability/hyper_cutter.c b/test/battle/ability/hyper_cutter.c index ac942039bb48..8e5c0a40bae8 100644 --- a/test/battle/ability/hyper_cutter.c +++ b/test/battle/ability/hyper_cutter.c @@ -7,9 +7,9 @@ SINGLE_BATTLE_TEST("Hyper Cutter prevents intimidate") s16 turnTwoHit; GIVEN { - PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; - PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; - OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); } + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } } WHEN { TURN { MOVE(opponent, MOVE_TACKLE); } TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } @@ -19,17 +19,137 @@ SINGLE_BATTLE_TEST("Hyper Cutter prevents intimidate") ABILITY_POPUP(player, ABILITY_INTIMIDATE); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } ABILITY_POPUP(opponent, ABILITY_HYPER_CUTTER); - MESSAGE("Foe Krabby's Attack was not lowered!"); + MESSAGE("Foe Krabby's Hyper Cutter prevents Attack loss!"); HP_BAR(player, captureDamage: &turnTwoHit); } THEN { EXPECT_EQ(turnOneHit, turnTwoHit); } } -TO_DO_BATTLE_TEST("Hyper Cutter prevents Attack stage reduction from moves"); // Growl -TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent Attack stage reduction from moves used by the user"); // e.g. Superpower -TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent Attack reduction from burn"); -TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent receiving negative Attack stage changes from Baton Pass"); -TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent Topsy-Turvy"); -TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent Spectral Thief from resetting positive Attack stage changes"); -TO_DO_BATTLE_TEST("Hyper Cutter is ignored by Mold Breaker"); +SINGLE_BATTLE_TEST("Hyper Cutter prevents Attack stage reduction from moves") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } + } WHEN { + TURN { MOVE(player, MOVE_GROWL); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_HYPER_CUTTER); + MESSAGE("Foe Krabby's Hyper Cutter prevents Attack loss!"); + } +} + +SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Attack reduction from burn") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } + } WHEN { + TURN { MOVE(player, MOVE_WILL_O_WISP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WILL_O_WISP, player); + MESSAGE("Foe Krabby was burned!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Hyper Cutter is ignored by Mold Breaker") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN); + PLAYER(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); } + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } + } WHEN { + TURN { MOVE(player, MOVE_GROWL); } + } SCENE { + ABILITY_POPUP(player, ABILITY_MOLD_BREAKER); + MESSAGE("Pinsir breaks the mold!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, player); + MESSAGE("Foe Krabby's Attack fell!"); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_HYPER_CUTTER); + MESSAGE("Foe Krabby's Hyper Cutter prevents Attack loss!"); + } + } +} + +SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Attack stage reduction from moves used by the user") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SUPERPOWER].effect == EFFECT_SUPERPOWER); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUPERPOWER); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPERPOWER, opponent); + MESSAGE("Foe Krabby's Attack fell!"); + MESSAGE("Foe Krabby's Defense fell!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + } +} + +SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Topsy-Turvy") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2); + ASSUME(gBattleMoves[MOVE_TOPSY_TURVY].effect == EFFECT_TOPSY_TURVY); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } + } WHEN { + TURN { MOVE(opponent, MOVE_SWORDS_DANCE); MOVE(player, MOVE_TOPSY_TURVY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent); + MESSAGE("Foe Krabby's Attack sharply rose!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOPSY_TURVY, player); + MESSAGE("Foe Krabby's stat changes were all reversed!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 2); + } +} + +SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Spectral Thief from resetting positive Attack stage changes") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2); + ASSUME(gBattleMoves[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } + } WHEN { + TURN { MOVE(opponent, MOVE_SWORDS_DANCE); MOVE(player, MOVE_SPECTRAL_THIEF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent); + MESSAGE("Foe Krabby's Attack sharply rose!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, player); + MESSAGE("Wobbuffet stole the target's boosted stats!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent receiving negative Attack stage changes from Baton Pass") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN); + ASSUME(gBattleMoves[MOVE_BATON_PASS].effect == EFFECT_BATON_PASS); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } + } WHEN { + TURN { MOVE(player, MOVE_GROWL); + MOVE(opponent, MOVE_BATON_PASS); + SEND_OUT(opponent, 1); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BATON_PASS, opponent); + MESSAGE("2 sent out Krabby!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + } +} diff --git a/test/battle/ability/inner_focus.c b/test/battle/ability/inner_focus.c index 574c860a74f6..ecd71272cb9a 100644 --- a/test/battle/ability/inner_focus.c +++ b/test/battle/ability/inner_focus.c @@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Inner Focus prevents intimidate") ABILITY_POPUP(player, ABILITY_INTIMIDATE); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } ABILITY_POPUP(opponent, ABILITY_INNER_FOCUS); - MESSAGE("Foe Zubat's Attack was not lowered!"); + MESSAGE("Foe Zubat's Inner Focus prevents stat loss!"); HP_BAR(player, captureDamage: &turnTwoHit); } THEN { EXPECT_EQ(turnOneHit, turnTwoHit); diff --git a/test/battle/ability/oblivious.c b/test/battle/ability/oblivious.c index 51d27bb16976..b851256acc06 100644 --- a/test/battle/ability/oblivious.c +++ b/test/battle/ability/oblivious.c @@ -63,6 +63,6 @@ SINGLE_BATTLE_TEST("Oblivious prevents Intimidate") ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); ABILITY_POPUP(player, ABILITY_OBLIVIOUS); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } - MESSAGE("Slowpoke's Attack was not lowered!"); + MESSAGE("Slowpoke's Oblivious prevents stat loss!"); } } diff --git a/test/battle/ability/opportunist.c b/test/battle/ability/opportunist.c index f344bd026ff2..2f0c5c8c8401 100644 --- a/test/battle/ability/opportunist.c +++ b/test/battle/ability/opportunist.c @@ -69,7 +69,7 @@ DOUBLE_BATTLE_TEST("Opportunist raises Attack only once when partner has Intimid ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); MESSAGE("Mightyena's Intimidate cuts Foe Spinda's attack!"); } - + if ((abilityLeft == ABILITY_CONTRARY && abilityRight != ABILITY_CONTRARY) || (abilityLeft != ABILITY_CONTRARY && abilityRight == ABILITY_CONTRARY)) { ABILITY_POPUP(playerRight, ABILITY_OPPORTUNIST); @@ -82,7 +82,7 @@ DOUBLE_BATTLE_TEST("Opportunist raises Attack only once when partner has Intimid ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); MESSAGE("Wobbuffet's Attack sharply rose!"); } - + HP_BAR(playerLeft, captureDamage: &results[i].damageLeft); HP_BAR(playerRight, captureDamage: &results[i].damageRight); } THEN { diff --git a/test/battle/ability/own_tempo.c b/test/battle/ability/own_tempo.c index 4c6a3167f664..9babd52589c8 100644 --- a/test/battle/ability/own_tempo.c +++ b/test/battle/ability/own_tempo.c @@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Own Tempo prevents intimidate") ABILITY_POPUP(player, ABILITY_INTIMIDATE); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } ABILITY_POPUP(opponent, ABILITY_OWN_TEMPO); - MESSAGE("Foe Slowpoke's Attack was not lowered!"); + MESSAGE("Foe Slowpoke's Own Tempo prevents stat loss!"); HP_BAR(player, captureDamage: &turnTwoHit); } THEN { EXPECT_EQ(turnOneHit, turnTwoHit); diff --git a/test/battle/ability/scrappy.c b/test/battle/ability/scrappy.c index df4ededa4edc..22b6660b691b 100644 --- a/test/battle/ability/scrappy.c +++ b/test/battle/ability/scrappy.c @@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Scrappy prevents intimidate") ABILITY_POPUP(player, ABILITY_INTIMIDATE); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } ABILITY_POPUP(opponent, ABILITY_SCRAPPY); - MESSAGE("Foe Kangaskhan's Attack was not lowered!"); + MESSAGE("Foe Kangaskhan's Scrappy prevents stat loss!"); HP_BAR(player, captureDamage: &turnTwoHit); } THEN { EXPECT_EQ(turnOneHit, turnTwoHit); diff --git a/test/battle/damage_formula.c b/test/battle/damage_formula.c index 98aa197ca1de..a4b0a03f585d 100644 --- a/test/battle/damage_formula.c +++ b/test/battle/damage_formula.c @@ -76,3 +76,40 @@ SINGLE_BATTLE_TEST("Damage calculation matches Gen5+ (Muscle Band, crit)") EXPECT_EQ(expectedDamage, dmg); } } + +SINGLE_BATTLE_TEST("Damage calculation matches Gen5+ (Marshadow vs Mawile)") +{ + s16 dmg; + s16 expectedDamage; + PARAMETRIZE { expectedDamage = 145; } + PARAMETRIZE { expectedDamage = 144; } + PARAMETRIZE { expectedDamage = 142; } + PARAMETRIZE { expectedDamage = 141; } + PARAMETRIZE { expectedDamage = 139; } + PARAMETRIZE { expectedDamage = 138; } + PARAMETRIZE { expectedDamage = 136; } + PARAMETRIZE { expectedDamage = 135; } + PARAMETRIZE { expectedDamage = 133; } + PARAMETRIZE { expectedDamage = 132; } + PARAMETRIZE { expectedDamage = 130; } + PARAMETRIZE { expectedDamage = 129; } + PARAMETRIZE { expectedDamage = 127; } + PARAMETRIZE { expectedDamage = 126; } + PARAMETRIZE { expectedDamage = 124; } + PARAMETRIZE { expectedDamage = 123; } + GIVEN { + PLAYER(SPECIES_MARSHADOW) { Level(100); Attack(286); } + OPPONENT(SPECIES_MAWILE) { Level(100); Defense(226); HP(241); } + } WHEN { + TURN { + MOVE(player, MOVE_SPECTRAL_THIEF, WITH_RNG(RNG_DAMAGE_MODIFIER, i), criticalHit: FALSE); + } + } + SCENE{ + MESSAGE("Marshadow used SpectrlThief!"); + HP_BAR(opponent, captureDamage: &dmg); + } + THEN{ + EXPECT_EQ(expectedDamage, dmg); + } +} diff --git a/test/battle/hold_effect/clear_amulet.c b/test/battle/hold_effect/clear_amulet.c index 552dbd91e8d2..0073f706095e 100644 --- a/test/battle/hold_effect/clear_amulet.c +++ b/test/battle/hold_effect/clear_amulet.c @@ -21,8 +21,8 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents Intimidate") } SCENE { HP_BAR(player, captureDamage: &turnOneHit); ABILITY_POPUP(player, ABILITY_INTIMIDATE); - NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } - MESSAGE("Foe Wobbuffet's Attack was not lowered!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Foe Wobbuffet's Clear Amulet prevents its stats from being lowered!"); HP_BAR(player, captureDamage: &turnTwoHit); } THEN { EXPECT_EQ(turnOneHit, turnTwoHit); @@ -55,31 +55,8 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents stat reducing effects") } WHEN { TURN { MOVE(player, move); } } SCENE { - NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); } - switch (move) - { - case MOVE_GROWL: - MESSAGE("Foe Wobbuffet's Attack was not lowered!"); - break; - case MOVE_LEER: - MESSAGE("Foe Wobbuffet's Defense was not lowered!"); - break; - case MOVE_CONFIDE: - MESSAGE("Foe Wobbuffet's Sp. Atk was not lowered!"); - break; - case MOVE_FAKE_TEARS: - MESSAGE("Foe Wobbuffet's Sp. Def was not lowered!"); - break; - case MOVE_SCARY_FACE: - MESSAGE("Foe Wobbuffet's Speed was not lowered!"); - break; - case MOVE_SWEET_SCENT: - MESSAGE("Foe Wobbuffet's evasiveness was not lowered!"); - break; - case MOVE_SAND_ATTACK: - MESSAGE("Foe Wobbuffet's accuracy was not lowered!"); - break; - } + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Clear Amulet prevents its stats from being lowered!"); } } @@ -106,6 +83,9 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents secondary effects that reduce stats") } WHEN { TURN { MOVE(player, move); } } SCENE { - NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); } + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Clear Amulet prevents its stats from being lowered!"); + } } } diff --git a/test/battle/move_effect/octolock.c b/test/battle/move_effect/octolock.c new file mode 100644 index 000000000000..3cdc5f5602c3 --- /dev/null +++ b/test/battle/move_effect/octolock.c @@ -0,0 +1,133 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Octolock decreases Defense and Sp. Def by at the end of the turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_OCTOLOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); + MESSAGE("Foe Wobbuffet can no longer escape because of Octolock!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Defense fell!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + } +} + +SINGLE_BATTLE_TEST("Octolock reduction is prevented by Clear Body, White Smoke and Full Metal Body") +{ + u32 species; + u32 ability; + + PARAMETRIZE { species = SPECIES_BELDUM; ability = ABILITY_CLEAR_BODY; } + PARAMETRIZE { species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; } + PARAMETRIZE { species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_OCTOLOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + if (species == SPECIES_BELDUM) + { + MESSAGE("Foe Beldum can no longer escape because of Octolock!"); + ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY); + MESSAGE("Foe Beldum's Clear Body prevents stat loss!"); + NONE_OF { + MESSAGE("Foe Beldum's Defense fell!"); + MESSAGE("Foe Beldum's Sp. Def fell!"); + } + } + else if (species == SPECIES_TORKOAL) + { + MESSAGE("Foe Torkoal can no longer escape because of Octolock!"); + ABILITY_POPUP(opponent, ABILITY_WHITE_SMOKE); + MESSAGE("Foe Torkoal's White Smoke prevents stat loss!"); + NONE_OF { + MESSAGE("Foe Torkoal's Defense fell!"); + MESSAGE("Foe Torkoal's Sp. Def fell!"); + } + } + else if (species == SPECIES_SOLGALEO) + { + MESSAGE("Foe Solgaleo can no longer escape because of Octolock!"); + ABILITY_POPUP(opponent, ABILITY_FULL_METAL_BODY); + MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!"); + NONE_OF { + MESSAGE("Foe Solgaleo's Defense fell!"); + MESSAGE("Foe Solgaleo's Sp. Def fell!"); + } + } + } +} + +SINGLE_BATTLE_TEST("Octolock Defense reduction is prevented by Big Pecks") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_PIDGEY) { Ability(ABILITY_BIG_PECKS); } + } WHEN { + TURN { MOVE(player, MOVE_OCTOLOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); + MESSAGE("Foe Pidgey can no longer escape because of Octolock!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT MESSAGE("Foe Pidgey's Defense fell!"); + ABILITY_POPUP(opponent, ABILITY_BIG_PECKS); + MESSAGE("Foe Pidgey's Big Pecks prevents Defense loss!"); + MESSAGE("Foe Pidgey's Sp. Def fell!"); + } +} + +SINGLE_BATTLE_TEST("Octolock reduction is prevented by Clear Amulet") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); } + } WHEN { + TURN { MOVE(player, MOVE_OCTOLOCK); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); + MESSAGE("Foe Wobbuffet can no longer escape because of Octolock!"); + MESSAGE("Foe Wobbuffet's Clear Amulet prevents its stats from being lowered!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Defense fell!"); + MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + } + } +} + +SINGLE_BATTLE_TEST("Octolock will not decrease Defense and Sp. Def further then minus six") +{ + u8 j; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_OCTOLOCK); } + for (j = 0; j < 6; j++) + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); + for (j = 0; j < 5; j++) { + MESSAGE("Foe Wobbuffet's Defense fell!"); + MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + } + MESSAGE("Foe Wobbuffet's Defense won't go lower!"); + MESSAGE("Foe Wobbuffet's Sp. Def won't go lower!"); + NONE_OF { + MESSAGE("Foe Wobbuffet's Defense fell!"); + MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + } + } +} diff --git a/test/battle/move_effect/syrup_bomb.c b/test/battle/move_effect/syrup_bomb.c index 18b032f5cb82..10e2c40de173 100644 --- a/test/battle/move_effect/syrup_bomb.c +++ b/test/battle/move_effect/syrup_bomb.c @@ -3,14 +3,15 @@ SINGLE_BATTLE_TEST("Syrup Bomb covers the foe in sticky syrup for 3 turns") { + u8 j; + GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_SYRUP_BOMB); } - TURN {} - TURN {} - TURN {} + for (j = 0; j < 4; j++) + TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); HP_BAR(opponent); @@ -19,7 +20,32 @@ SINGLE_BATTLE_TEST("Syrup Bomb covers the foe in sticky syrup for 3 turns") MESSAGE("Foe Wobbuffet's Speed fell!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); MESSAGE("Foe Wobbuffet's Speed fell!"); - MESSAGE("Foe Wobbuffet was freed from Syrup Bomb!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Speed fell!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Speed fell!"); + } + } +} + +SINGLE_BATTLE_TEST("Sticky Syrup isn't applied again if the target is already covered") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SYRUP_BOMB); } + TURN { MOVE(player, MOVE_SYRUP_BOMB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); + HP_BAR(opponent); + MESSAGE("Foe Wobbuffet got covered in sticky syrup!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Speed fell!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); + HP_BAR(opponent); + NOT MESSAGE("Foe Wobbuffet got covered in sticky syrup!"); } } @@ -40,7 +66,7 @@ SINGLE_BATTLE_TEST("Syrup Bomb is prevented by Bulletproof") } } -SINGLE_BATTLE_TEST("Clear Body, White Smoke and Full Metal Body prevent Sticky Syrup speed reduction") +SINGLE_BATTLE_TEST("Sticky Syrup speed reduction is prevented by Clear Body, White Smoke or Full Metal Body") { u32 species; u32 ability; @@ -64,38 +90,71 @@ SINGLE_BATTLE_TEST("Clear Body, White Smoke and Full Metal Body prevent Sticky S MESSAGE("Foe Beldum got covered in sticky syrup!"); ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY); MESSAGE("Foe Beldum's Clear Body prevents stat loss!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Beldum's Speed fell!"); + } } else if (species == SPECIES_TORKOAL) { MESSAGE("Foe Torkoal got covered in sticky syrup!"); ABILITY_POPUP(opponent, ABILITY_WHITE_SMOKE); MESSAGE("Foe Torkoal's White Smoke prevents stat loss!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Torkoal's Speed fell!"); + } } else if (species == SPECIES_SOLGALEO) { MESSAGE("Foe Solgaleo got covered in sticky syrup!"); ABILITY_POPUP(opponent, ABILITY_FULL_METAL_BODY); MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Solgaleo's Speed fell!"); + } } + } +} + +SINGLE_BATTLE_TEST("Sticky Syrup speed reduction is prevented by Clear Amulet") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); } + } WHEN { + TURN { MOVE(player, MOVE_SYRUP_BOMB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); + HP_BAR(opponent); + MESSAGE("Foe Wobbuffet got covered in sticky syrup!"); + MESSAGE("Foe Wobbuffet's Clear Amulet prevents its stats from being lowered!"); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Beldum's Speed fell!"); + MESSAGE("Foe Wobbuffet's Speed fell!"); } } } -SINGLE_BATTLE_TEST("Clear Amulet prevents Sticky Syrup speed reduction") +SINGLE_BATTLE_TEST("Sticky syrup will not decrease speed further then minus six") { + u8 j; + GIVEN { PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); } + OPPONENT(SPECIES_WOBBUFFET); } WHEN { + for (j = 0; j < 3; j++) + TURN { MOVE(player, MOVE_SCARY_FACE); } TURN { MOVE(player, MOVE_SYRUP_BOMB); } + TURN {} } SCENE { + for (j = 0; j < 3; j++) { ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); } ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); HP_BAR(opponent); MESSAGE("Foe Wobbuffet got covered in sticky syrup!"); - MESSAGE("Foe Wobbuffet's Speed was not lowered!"); + MESSAGE("Foe Wobbuffet's Speed won't go lower!"); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); MESSAGE("Foe Wobbuffet's Speed fell!");