From 6ed8ab771b4ff629e1ed15f10854f649c26cd42b Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 13 Oct 2023 14:08:44 +0200 Subject: [PATCH 01/12] Fix Syrup Bomb and change Octolock --- data/battle_scripts_1.s | 51 +++++---------- src/battle_script_commands.c | 8 +-- src/battle_util.c | 13 +--- test/battle/damage_formula.c | 37 +++++++++++ test/battle/move_effect/octolock.c | 97 ++++++++++++++++++++++++++++ test/battle/move_effect/syrup_bomb.c | 7 +- 6 files changed, 158 insertions(+), 55 deletions(-) create mode 100644 test/battle/move_effect/octolock.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 183e7796bb..7f323dbd8b 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -452,28 +452,15 @@ BattleScript_EffectSyrupBomb:: goto BattleScript_MoveEnd 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 +BattleScript_SyrupBombTurnDmgPrintMsg: + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 3, BattleScript_SyrupBombTurnDmgEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, 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:: @@ -1079,29 +1066,23 @@ 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_OctolockTryLowerDef +BattleScript_OctolockTryLowerDef: + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 3, BattleScript_OctolockTryLowerSpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_OctolockTryLowerSpDef + 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_OctolockTurnDmgPrintMsg +BattleScript_OctolockTurnDmgPrintMsg: + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 3, BattleScript_OctlockTurnDmgEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_OctlockTurnDmgEnd + printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG -BattleScript_OctolockEnd2:: +BattleScript_OctlockTurnDmgEnd: end2 BattleScript_EffectPoltergeist: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index cc365dbf82..b415f25d52 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3010,7 +3010,7 @@ void SetMoveEffect(bool32 primary, u32 certain) 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]; @@ -11406,11 +11406,6 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr || battlerAbility == ABILITY_WHITE_SMOKE) && (!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) @@ -11424,6 +11419,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET) { gBattlescriptCurrInstr = BattleScript_ItemNoStatLoss; + RecordItemEffectBattle(battler, HOLD_EFFECT_CLEAR_AMULET); } else { diff --git a/src/battle_util.c b/src/battle_util.c index a619b505e4..32bbf7f7e0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2793,11 +2793,7 @@ u8 DoBattlerEndTurnEffects(void) 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); @@ -3094,9 +3090,6 @@ u8 DoBattlerEndTurnEffects(void) case ENDTURN_SYRUP_BOMB: if ((gStatuses4[battler] & STATUS4_SYRUP_BOMB) && (gBattleMons[battler].hp != 0)) { - u16 battlerAbility = GetBattlerAbility(battler); - u32 battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE); - gDisableStructs[battler].syrupBombTimer--; if (gDisableStructs[battler].syrupBombTimer == 0) { @@ -5760,7 +5753,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITYEFFECT_OPPORTUNIST: /* Similar to ABILITYEFFECT_IMMUNITY in that it loops through all battlers. * Is called after ABILITYEFFECT_ON_SWITCHIN to copy any boosts - * from switch in abilities e.g. intrepid sword, as + * from switch in abilities e.g. intrepid sword, as */ for (battler = 0; battler < gBattlersCount; battler++) { @@ -5836,7 +5829,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect = 4; break; } - + if (effect != 0) { switch (effect) diff --git a/test/battle/damage_formula.c b/test/battle/damage_formula.c index 98aa197ca1..a4b0a03f58 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/move_effect/octolock.c b/test/battle/move_effect/octolock.c new file mode 100644 index 0000000000..f3249dd5ce --- /dev/null +++ b/test/battle/move_effect/octolock.c @@ -0,0 +1,97 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Octolock") +{ + 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 2") +{ + 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!"); + NOT MESSAGE("Foe Beldum's Defense fell!"); + NOT 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!"); + NOT MESSAGE("Foe Torkoal's Defense fell!"); + NOT 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!"); + NOT MESSAGE("Foe Solgaleo's Defense fell!"); + NOT MESSAGE("Foe Solgaleo's Sp. Def fell!"); + } + } +} + +SINGLE_BATTLE_TEST("Octolock 3") +{ + 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 stat loss!"); + MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + } +} + +SINGLE_BATTLE_TEST("Octolock 4") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); } + } WHEN { + TURN { MOVE(player, MOVE_OCTOLOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); + MESSAGE("Foe Wobbuffet can no longer escape because of Octolock!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT MESSAGE("Foe Wobbuffet's Defense fell!"); + NOT 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 ae689b3629..08a3af95f9 100644 --- a/test/battle/move_effect/syrup_bomb.c +++ b/test/battle/move_effect/syrup_bomb.c @@ -32,9 +32,9 @@ SINGLE_BATTLE_TEST("Syrup Bomb is prevented by Bulletproof") TURN { MOVE(player, MOVE_SYRUP_BOMB); } } SCENE { ABILITY_POPUP(opponent, ABILITY_BULLETPROOF); - MESSAGE("Foe Chespin's Bulletproof blocks Syrup Bomb!"); NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); NOT HP_BAR(opponent); + MESSAGE("Foe Chespin's Bulletproof blocks Syrup Bomb!"); } } @@ -57,6 +57,7 @@ SINGLE_BATTLE_TEST("Clear Body, White Smoke and Full Metal Body prevent Sticky S } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); if (species == SPECIES_BELDUM) { MESSAGE("Foe Beldum got covered in sticky syrup!"); @@ -75,8 +76,6 @@ SINGLE_BATTLE_TEST("Clear Body, White Smoke and Full Metal Body prevent Sticky S ABILITY_POPUP(opponent, ABILITY_FULL_METAL_BODY); MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!"); } - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - NOT MESSAGE("Foe Beldum's Speed fell!"); } } @@ -91,8 +90,8 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents Sticky Syrup speed reduction") 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!"); NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); NOT MESSAGE("Foe Wobbuffet's Speed fell!"); + MESSAGE("Foe Wobbuffet's Speed was not lowered!"); } } From 91b6722322727e2cc14b711176ba9c03b5bb2f71 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 18 Oct 2023 20:25:34 +0200 Subject: [PATCH 02/12] Octolock, more tests --- asm/macros/battle_script.inc | 11 ++-- data/battle_scripts_1.s | 21 +++---- include/battle_scripts.h | 1 + include/constants/battle_script_commands.h | 55 +++++++++-------- include/constants/battle_string_ids.h | 2 +- src/battle_message.c | 5 +- src/battle_script_commands.c | 44 +++++++------- src/battle_util.c | 16 ++--- test/battle/hold_effect/clear_amulet.c | 34 ++--------- test/battle/move_effect/octolock.c | 37 ++++++++++-- test/battle/move_effect/syrup_bomb.c | 68 +++++++++++++++++++--- 11 files changed, 169 insertions(+), 125 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 866831c462..9bff248651 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1366,6 +1366,12 @@ .byte \battler .endm + .macro setoctolock battler:req, failInstr:req + callnative BS_Octolock + .byte \battler + .4byte \failInstr + .endm + .macro setzeffect callnative BS_SetZEffect .endm @@ -2044,11 +2050,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 7f323dbd8b..08d70e4e04 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -437,7 +437,6 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectMortalSpin @ EFFECT_MORTAL_SPIN .4byte BattleScript_EffectHit @ EFFECT_GIGATON_HAMMER .4byte BattleScript_EffectSaltCure @ EFFECT_SALT_CURE - .4byte BattleScript_EffectMatchaGotcha @ EFFECT_MATCHA_GOTCHA .4byte BattleScript_EffectSyrupBomb @ EFFECT_SYRUP_BOMB .4byte BattleScript_EffectHit @ EFFECT_IVY_CUDGEL @@ -447,17 +446,17 @@ 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:: playstatchangeanimation BS_ATTACKER, BIT_SPEED, STAT_CHANGE_NEGATIVE setstatchanger STAT_SPEED, 1, TRUE statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_SyrupBombTurnDmgEnd -BattleScript_SyrupBombTurnDmgPrintMsg: - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 3, BattleScript_SyrupBombTurnDmgEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_SyrupBombTurnDmgEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_SyrupBombTurnDmgEnd: @@ -1068,18 +1067,14 @@ BattleScript_EffectOctolock: BattleScript_OctolockEndTurn:: playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE setstatchanger STAT_DEF, 1, TRUE - statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTryLowerDef + statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTryLowerSpDef BattleScript_OctolockTryLowerDef: - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 3, BattleScript_OctolockTryLowerSpDef - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_OctolockTryLowerSpDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_OctolockTryLowerSpDef: setstatchanger STAT_SPDEF, 1, TRUE - statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTurnDmgPrintMsg + statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctlockTurnDmgEnd BattleScript_OctolockTurnDmgPrintMsg: - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 3, BattleScript_OctlockTurnDmgEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_OctlockTurnDmgEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_OctlockTurnDmgEnd: @@ -8597,7 +8592,7 @@ BattleScript_IntimidatePrevented: pause B_WAIT_TIME_LONG setbyte gBattleCommunication STAT_ATK stattextbuffer BS_TARGET - printstring STRINGID_STATWASNOTLOWERED + printstring STRINGID_PKMNPREVENTSSTATLOSSWITH waitmessage B_WAIT_TIME_LONG call BattleScript_TryAdrenalineOrb goto BattleScript_IntimidateLoopIncrement @@ -8908,7 +8903,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 c2a73d01fd..807f228f35 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -480,6 +480,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 1775b9528e..087af0e301 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 54b7a4437c..6998502d1f 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 3b5402b97f..a0139f315f 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!"); @@ -812,7 +812,6 @@ static const u8 sText_TargetCoveredInStickyCandySyrup[] = _("{B_DEF_NAME_WITH_PR const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { - [STRINGID_OPPORTUNISTCOPIED - BATTLESTRINGS_TABLE_START] = sText_OpportunistCopied, [STRINGID_TARGETISHURTBYSALTCURE - BATTLESTRINGS_TABLE_START] = sText_TargetIsHurtBySaltCure, [STRINGID_TARGETISBEINGSALTCURED - BATTLESTRINGS_TABLE_START] = sText_TargetIsBeingSaltCured, [STRINGID_CURRENTMOVECANTSELECT - BATTLESTRINGS_TABLE_START] = sText_CurrentMoveCantSelect, @@ -899,7 +898,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 b415f25d52..0f3217d40d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3645,15 +3645,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; } @@ -10354,22 +10351,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); @@ -11418,6 +11399,7 @@ 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); } @@ -16260,3 +16242,21 @@ void BS_JumpIfTerrainAffected(void) else gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_Octolock(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; + } +} \ No newline at end of file diff --git a/src/battle_util.c b/src/battle_util.c index 32bbf7f7e0..b7b8dd089d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3090,19 +3090,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/hold_effect/clear_amulet.c b/test/battle/hold_effect/clear_amulet.c index 39e6c22a69..fd695f06b5 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,7 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents secondary effects that reduce stats") } WHEN { TURN { MOVE(player, MOVE_ROCK_SMASH); } } SCENE { - NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); } + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT 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 index f3249dd5ce..2f70db39cf 100644 --- a/test/battle/move_effect/octolock.c +++ b/test/battle/move_effect/octolock.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Octolock") +SINGLE_BATTLE_TEST("Octolock decreases Defense and Sp. Def by at the end of the turn") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -18,7 +18,7 @@ SINGLE_BATTLE_TEST("Octolock") } } -SINGLE_BATTLE_TEST("Octolock 2") +SINGLE_BATTLE_TEST("Octolock reduction is prevented by Clear Body, White Smoke and Full Metal Body") { u32 species; u32 ability; @@ -62,7 +62,7 @@ SINGLE_BATTLE_TEST("Octolock 2") } } -SINGLE_BATTLE_TEST("Octolock 3") +SINGLE_BATTLE_TEST("Octolock Defense reduction is prevented by Big Pecks") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -75,23 +75,48 @@ SINGLE_BATTLE_TEST("Octolock 3") 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 stat loss!"); - MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + MESSAGE("Foe Pidgey's Big Pecks prevents Defense loss!"); + MESSAGE("Foe Pidgey's Sp. Def fell!"); } } -SINGLE_BATTLE_TEST("Octolock 4") +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!"); NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); NOT MESSAGE("Foe Wobbuffet's Defense fell!"); NOT 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!"); + NOT MESSAGE("Foe Wobbuffet's Defense fell!"); + NOT 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 08a3af95f9..7c3808def8 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,30 @@ 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!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT MESSAGE("Foe Wobbuffet's Speed fell!"); + } +} + +SINGLE_BATTLE_TEST("Target will be not covered in sticky syrup again if it is currently 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!"); } } @@ -32,9 +56,9 @@ SINGLE_BATTLE_TEST("Syrup Bomb is prevented by Bulletproof") TURN { MOVE(player, MOVE_SYRUP_BOMB); } } SCENE { ABILITY_POPUP(opponent, ABILITY_BULLETPROOF); + MESSAGE("Foe Chespin's Bulletproof blocks Syrup Bomb!"); NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); NOT HP_BAR(opponent); - MESSAGE("Foe Chespin's Bulletproof blocks Syrup Bomb!"); } } @@ -63,23 +87,29 @@ 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!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT 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!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT 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!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT MESSAGE("Foe Solgaleo's Speed fell!"); } } } -SINGLE_BATTLE_TEST("Clear Amulet prevents Sticky Syrup speed reduction") +SINGLE_BATTLE_TEST("Sticky Syrup speed reduction is prevented by Clear Amulet") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -90,8 +120,32 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents Sticky Syrup speed reduction") 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!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT MESSAGE("Foe Wobbuffet's Speed fell!"); + } +} + +SINGLE_BATTLE_TEST("Sticky syrup will not decrease speed further then minus six") +{ + u8 j; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + 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 won't go lower!"); NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); NOT MESSAGE("Foe Wobbuffet's Speed fell!"); - MESSAGE("Foe Wobbuffet's Speed was not lowered!"); } } From 354f84be21e90cd6468e05524cb6159ed8e54651 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 18 Oct 2023 22:14:49 +0200 Subject: [PATCH 03/12] intim changes --- data/battle_scripts_1.s | 17 ----------------- src/battle_message.c | 1 + src/battle_script_commands.c | 10 ++++++++-- test/battle/ability/hyper_cutter.c | 2 +- test/battle/ability/inner_focus.c | 2 +- test/battle/ability/oblivious.c | 2 +- test/battle/ability/opportunist.c | 4 ++-- test/battle/ability/own_tempo.c | 2 +- test/battle/ability/scrappy.c | 2 +- 9 files changed, 16 insertions(+), 26 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 08d70e4e04..8c2389054c 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8548,13 +8548,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 @@ -8587,16 +8580,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_PKMNPREVENTSSTATLOSSWITH - waitmessage B_WAIT_TIME_LONG - call BattleScript_TryAdrenalineOrb - goto BattleScript_IntimidateLoopIncrement - BattleScript_IntimidateInReverse: copybyte sBATTLER, gBattlerTarget call BattleScript_AbilityPopUpTarget diff --git a/src/battle_message.c b/src/battle_message.c index a0139f315f..0b58caaf34 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -812,6 +812,7 @@ static const u8 sText_TargetCoveredInStickyCandySyrup[] = _("{B_DEF_NAME_WITH_PR const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_OPPORTUNISTCOPIED - BATTLESTRINGS_TABLE_START] = sText_OpportunistCopied, [STRINGID_TARGETISHURTBYSALTCURE - BATTLESTRINGS_TABLE_START] = sText_TargetIsHurtBySaltCure, [STRINGID_TARGETISBEINGSALTCURED - BATTLESTRINGS_TABLE_START] = sText_TargetIsBeingSaltCured, [STRINGID_CURRENTMOVECANTSELECT - BATTLESTRINGS_TABLE_START] = sText_CurrentMoveCantSelect, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0f3217d40d..d4d0fcf21a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11384,7 +11384,13 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET || battlerAbility == ABILITY_CLEAR_BODY || battlerAbility == ABILITY_FULL_METAL_BODY - || battlerAbility == ABILITY_WHITE_SMOKE) + || battlerAbility == ABILITY_WHITE_SMOKE + || (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK)) + || ((B_UPDATED_INTIMIDATE >= GEN_8) && statId == STAT_ATK + && (battlerAbility == ABILITY_INNER_FOCUS + || battlerAbility == ABILITY_SCRAPPY + || battlerAbility == ABILITY_OWN_TEMPO + || battlerAbility == ABILITY_OBLIVIOUS)) && (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE) { if (flags == STAT_CHANGE_ALLOW_PTR) @@ -16259,4 +16265,4 @@ void BS_Octolock(void) gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; } -} \ No newline at end of file +} diff --git a/test/battle/ability/hyper_cutter.c b/test/battle/ability/hyper_cutter.c index ac942039bb..4155cc5a12 100644 --- a/test/battle/ability/hyper_cutter.c +++ b/test/battle/ability/hyper_cutter.c @@ -19,7 +19,7 @@ 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 stat loss!"); HP_BAR(player, captureDamage: &turnTwoHit); } THEN { EXPECT_EQ(turnOneHit, turnTwoHit); diff --git a/test/battle/ability/inner_focus.c b/test/battle/ability/inner_focus.c index 574c860a74..ecd71272cb 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 51d27bb169..b851256acc 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 f344bd026f..2f0c5c8c84 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 4c6a3167f6..9babd52589 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 df4ededa4e..22b6660b69 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); From 876341105bcf003e6cdc309830f1289ef3f6ef64 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 19 Oct 2023 11:32:58 +0200 Subject: [PATCH 04/12] parantheses --- src/battle_script_commands.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d4d0fcf21a..19879ba9b3 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11381,16 +11381,15 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr gBattlescriptCurrInstr = BattleScript_ButItFailed; return STAT_CHANGE_DIDNT_WORK; } - else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET + else if (((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET || battlerAbility == ABILITY_CLEAR_BODY || battlerAbility == ABILITY_FULL_METAL_BODY - || battlerAbility == ABILITY_WHITE_SMOKE - || (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK)) + || battlerAbility == ABILITY_WHITE_SMOKE) || ((B_UPDATED_INTIMIDATE >= GEN_8) && statId == STAT_ATK && (battlerAbility == ABILITY_INNER_FOCUS || battlerAbility == ABILITY_SCRAPPY || battlerAbility == ABILITY_OWN_TEMPO - || battlerAbility == ABILITY_OBLIVIOUS)) + || battlerAbility == ABILITY_OBLIVIOUS))) && (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE) { if (flags == STAT_CHANGE_ALLOW_PTR) From 535768838f142f9a8ba53dc1a13db3652e5c1c10 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 19 Oct 2023 21:28:27 +0200 Subject: [PATCH 05/12] Hyper Cutter tests --- test/battle/ability/hyper_cutter.c | 116 ++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 9 deletions(-) diff --git a/test/battle/ability/hyper_cutter.c b/test/battle/ability/hyper_cutter.c index cde108e4c3..10be6fa725 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); } @@ -26,10 +26,108 @@ SINGLE_BATTLE_TEST("Hyper Cutter prevents intimidate") } } -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"); +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!"); + NOT ABILITY_POPUP(opponent, ABILITY_HYPER_CUTTER); + NOT 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("xx 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); + } +} + 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"); From f3580aa3f56005917aed8ed350b76d9078069777 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 19 Oct 2023 21:31:04 +0200 Subject: [PATCH 06/12] tabs --- data/battle_scripts_1.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index cfb2d03cc9..a279a8f0bc 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -456,7 +456,7 @@ BattleScript_SyrupBombActivates:: BattleScript_SyrupBombEndTurn:: playstatchangeanimation BS_ATTACKER, BIT_SPEED, STAT_CHANGE_NEGATIVE setstatchanger STAT_SPEED, 1, TRUE - statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_SyrupBombTurnDmgEnd + statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_SyrupBombTurnDmgEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_SyrupBombTurnDmgEnd: @@ -1067,13 +1067,13 @@ BattleScript_EffectOctolock: BattleScript_OctolockEndTurn:: playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE setstatchanger STAT_DEF, 1, TRUE - statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTryLowerSpDef + statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTryLowerSpDef BattleScript_OctolockTryLowerDef: printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_OctolockTryLowerSpDef: setstatchanger STAT_SPDEF, 1, TRUE - statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctlockTurnDmgEnd + statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctlockTurnDmgEnd BattleScript_OctolockTurnDmgPrintMsg: printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG From ab6c5bafe9e47651b9cae2ece93c1c4a06ee16b6 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 20 Oct 2023 12:29:55 +0200 Subject: [PATCH 07/12] New function to check ability stat loss --- src/battle_script_commands.c | 31 ++++++++++++++++++++++--------- src/battle_util.c | 1 - 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index da647034a5..0cdb99e932 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -355,6 +355,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); @@ -11390,15 +11391,8 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr gBattlescriptCurrInstr = BattleScript_ButItFailed; 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) - || ((B_UPDATED_INTIMIDATE >= GEN_8) && statId == STAT_ATK - && (battlerAbility == ABILITY_INNER_FOCUS - || battlerAbility == ABILITY_SCRAPPY - || battlerAbility == ABILITY_OWN_TEMPO - || battlerAbility == ABILITY_OBLIVIOUS))) + else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET + || CanAbilityPreventStatLoss(battlerAbility, GetBattlerAbility(gBattlerAttacker) == ABILITY_INTIMIDATE)) && (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE) { if (flags == STAT_CHANGE_ALLOW_PTR) @@ -15703,6 +15697,25 @@ static bool8 IsFinalStrikeEffect(u16 move) return FALSE; } +static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 isIntimidate) +{ + 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 (isIntimidate && (B_UPDATED_INTIMIDATE >= GEN_8)) + return TRUE; + break; + } + return FALSE; +} + void BS_CheckParentalBondCounter(void) { NATIVE_ARGS(u8 counter, const u8 *jumpInstr); diff --git a/src/battle_util.c b/src/battle_util.c index 12dcb256a3..d0bb6e8c3c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2792,7 +2792,6 @@ u8 DoBattlerEndTurnEffects(void) break; case ENDTURN_OCTOLOCK: { - u16 battlerAbility = GetBattlerAbility(battler); if (gDisableStructs[battler].octolock) { gBattlerTarget = battler; From 6daea655e56c74feebe9bdea6c0493e1eeccb7d4 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 20 Oct 2023 12:33:56 +0200 Subject: [PATCH 08/12] fix line alignment --- src/battle_script_commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0cdb99e932..8e5db2fd6e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11392,8 +11392,8 @@ 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 - || CanAbilityPreventStatLoss(battlerAbility, GetBattlerAbility(gBattlerAttacker) == ABILITY_INTIMIDATE)) - && (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE) + || CanAbilityPreventStatLoss(battlerAbility, GetBattlerAbility(gBattlerAttacker) == ABILITY_INTIMIDATE)) + && (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE) { if (flags == STAT_CHANGE_ALLOW_PTR) { From 123fd45d8ecd1fd108fa64e9d0d364a8409c7702 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 20 Oct 2023 18:53:49 +0200 Subject: [PATCH 09/12] last hyper cutter test --- test/battle/ability/hyper_cutter.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/battle/ability/hyper_cutter.c b/test/battle/ability/hyper_cutter.c index 10be6fa725..16b1635060 100644 --- a/test/battle/ability/hyper_cutter.c +++ b/test/battle/ability/hyper_cutter.c @@ -111,7 +111,7 @@ SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Topsy-Turvy") } } -SINGLE_BATTLE_TEST("xx Hyper Cutter doesn't prevent Spectral Thief from resetting positive Attack stage changes") +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); @@ -130,4 +130,24 @@ SINGLE_BATTLE_TEST("xx Hyper Cutter doesn't prevent Spectral Thief from resettin } } -TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent receiving negative Attack stage changes from Baton Pass"); +SINGLE_BATTLE_TEST("xx 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); + } +} \ No newline at end of file From 783ec0e957af43b96a893d82a796120f229a3518 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 20 Oct 2023 22:51:30 +0200 Subject: [PATCH 10/12] fixes tests --- test/battle/ability/hyper_cutter.c | 4 ++-- test/battle/move_effect/octolock.c | 3 ++- test/battle/move_effect/syrup_bomb.c | 5 ++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/battle/ability/hyper_cutter.c b/test/battle/ability/hyper_cutter.c index 16b1635060..f040907626 100644 --- a/test/battle/ability/hyper_cutter.c +++ b/test/battle/ability/hyper_cutter.c @@ -130,7 +130,7 @@ SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Spectral Thief from resetting p } } -SINGLE_BATTLE_TEST("xx Hyper Cutter doesn't prevent receiving negative Attack stage changes from Baton Pass") +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); @@ -150,4 +150,4 @@ SINGLE_BATTLE_TEST("xx Hyper Cutter doesn't prevent receiving negative Attack st } THEN { EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); } -} \ No newline at end of file +} diff --git a/test/battle/move_effect/octolock.c b/test/battle/move_effect/octolock.c index 2f70db39cf..4b0b1dbf4d 100644 --- a/test/battle/move_effect/octolock.c +++ b/test/battle/move_effect/octolock.c @@ -111,9 +111,10 @@ SINGLE_BATTLE_TEST("Octolock will not decrease Defense and Sp. Def further then TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); - for (j = 0; j < 5; j++) + 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!"); NOT MESSAGE("Foe Wobbuffet's Defense fell!"); diff --git a/test/battle/move_effect/syrup_bomb.c b/test/battle/move_effect/syrup_bomb.c index 7c3808def8..fc55fa0163 100644 --- a/test/battle/move_effect/syrup_bomb.c +++ b/test/battle/move_effect/syrup_bomb.c @@ -98,7 +98,7 @@ SINGLE_BATTLE_TEST("Clear Body, White Smoke and Full Metal Body prevent Sticky S NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); NOT MESSAGE("Foe Torkoal's Speed fell!"); } - else if (species == SPECIES_SOLGALEO) + else { MESSAGE("Foe Solgaleo got covered in sticky syrup!"); ABILITY_POPUP(opponent, ABILITY_FULL_METAL_BODY); @@ -139,8 +139,7 @@ SINGLE_BATTLE_TEST("Sticky syrup will not decrease speed further then minus six" TURN { MOVE(player, MOVE_SYRUP_BOMB); } TURN {} } SCENE { - for (j = 0; j < 3; j++) - ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + 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!"); From bf56ea8a8bdc17ecc4382351b59726af9b0deee6 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 22 Oct 2023 19:46:31 +0200 Subject: [PATCH 11/12] apply suggestions --- asm/macros/battle_script.inc | 4 ++-- data/battle_scripts_1.s | 2 +- src/battle_script_commands.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9bff248651..e5d8fc58c8 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1366,8 +1366,8 @@ .byte \battler .endm - .macro setoctolock battler:req, failInstr:req - callnative BS_Octolock + .macro trysetoctolock battler:req, failInstr:req + callnative BS_TrySetOctolock .byte \battler .4byte \failInstr .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a279a8f0bc..bc0a7a7fa3 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1057,7 +1057,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 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8e5db2fd6e..088546991e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -15697,7 +15697,7 @@ static bool8 IsFinalStrikeEffect(u16 move) return FALSE; } -static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 isIntimidate) +static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 byIntimidate) { switch (abilityDef) { @@ -15709,7 +15709,7 @@ static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 isIntimidate) case ABILITY_SCRAPPY: case ABILITY_OWN_TEMPO: case ABILITY_OBLIVIOUS: - if (isIntimidate && (B_UPDATED_INTIMIDATE >= GEN_8)) + if (byIntimidate && (B_UPDATED_INTIMIDATE >= GEN_8)) return TRUE; break; } @@ -16238,7 +16238,7 @@ void BS_JumpIfTerrainAffected(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_Octolock(void) +void BS_TrySetOctolock(void) { NATIVE_ARGS(u8 battler, const u8 *failInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); From 25a57d48d962b00fde758949a49e2f7f82f1105b Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 25 Oct 2023 10:18:59 +0200 Subject: [PATCH 12/12] fixes tests --- test/battle/ability/hyper_cutter.c | 6 +++-- test/battle/hold_effect/clear_amulet.c | 6 +++-- test/battle/move_effect/octolock.c | 32 +++++++++++++++++--------- test/battle/move_effect/syrup_bomb.c | 30 ++++++++++++++++-------- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/test/battle/ability/hyper_cutter.c b/test/battle/ability/hyper_cutter.c index f040907626..8e5c0a40ba 100644 --- a/test/battle/ability/hyper_cutter.c +++ b/test/battle/ability/hyper_cutter.c @@ -69,8 +69,10 @@ SINGLE_BATTLE_TEST("Hyper Cutter is ignored by Mold Breaker") MESSAGE("Pinsir breaks the mold!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, player); MESSAGE("Foe Krabby's Attack fell!"); - NOT ABILITY_POPUP(opponent, ABILITY_HYPER_CUTTER); - NOT MESSAGE("Foe Krabby's Hyper Cutter prevents Attack loss!"); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_HYPER_CUTTER); + MESSAGE("Foe Krabby's Hyper Cutter prevents Attack loss!"); + } } } diff --git a/test/battle/hold_effect/clear_amulet.c b/test/battle/hold_effect/clear_amulet.c index c924f79912..0073f70609 100644 --- a/test/battle/hold_effect/clear_amulet.c +++ b/test/battle/hold_effect/clear_amulet.c @@ -83,7 +83,9 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents secondary effects that reduce stats") } WHEN { TURN { MOVE(player, move); } } SCENE { - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - NOT 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 Clear Amulet prevents its stats from being lowered!"); + } } } diff --git a/test/battle/move_effect/octolock.c b/test/battle/move_effect/octolock.c index 4b0b1dbf4d..3cdc5f5602 100644 --- a/test/battle/move_effect/octolock.c +++ b/test/battle/move_effect/octolock.c @@ -40,24 +40,30 @@ SINGLE_BATTLE_TEST("Octolock reduction is prevented by Clear Body, White Smoke a 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!"); - NOT MESSAGE("Foe Beldum's Defense fell!"); - NOT MESSAGE("Foe Beldum's Sp. Def fell!"); + 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!"); - NOT MESSAGE("Foe Torkoal's Defense fell!"); - NOT MESSAGE("Foe Torkoal's Sp. Def fell!"); + 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!"); - NOT MESSAGE("Foe Solgaleo's Defense fell!"); - NOT MESSAGE("Foe Solgaleo's Sp. Def fell!"); + NONE_OF { + MESSAGE("Foe Solgaleo's Defense fell!"); + MESSAGE("Foe Solgaleo's Sp. Def fell!"); + } } } } @@ -92,9 +98,11 @@ SINGLE_BATTLE_TEST("Octolock reduction is prevented by Clear Amulet") 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!"); - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - NOT MESSAGE("Foe Wobbuffet's Defense fell!"); - NOT MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Defense fell!"); + MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + } } } @@ -117,7 +125,9 @@ SINGLE_BATTLE_TEST("Octolock will not decrease Defense and Sp. Def further then } MESSAGE("Foe Wobbuffet's Defense won't go lower!"); MESSAGE("Foe Wobbuffet's Sp. Def won't go lower!"); - NOT MESSAGE("Foe Wobbuffet's Defense fell!"); - NOT MESSAGE("Foe Wobbuffet's Sp. Def fell!"); + 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 232f922f84..10e2c40de1 100644 --- a/test/battle/move_effect/syrup_bomb.c +++ b/test/battle/move_effect/syrup_bomb.c @@ -22,12 +22,14 @@ 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!"); - NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - NOT 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("Target will be not covered in sticky syrup again if it is currently covered") +SINGLE_BATTLE_TEST("Sticky Syrup isn't applied again if the target is already covered") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -64,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; @@ -88,27 +90,35 @@ 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 Beldum's Speed fell!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Solgaleo's Speed fell!"); + } } } } -SINGLE_BATTLE_TEST("Clear Amulet prevents Sticky Syrup speed reduction") +SINGLE_BATTLE_TEST("Sticky Syrup speed reduction is prevented by Clear Amulet") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -119,7 +129,7 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents Sticky Syrup speed reduction") 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 Clear Amulet prevents its stats from being lowered!"); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); MESSAGE("Foe Wobbuffet's Speed fell!");