diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 31a359a0ef..f33537bbb0 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1311,7 +1311,7 @@ callnative BS_CalcMetalBurstDmg .4byte \failInstr .endm - + .macro jumpifcantfling battler:req, jumpInstr:req callnative BS_JumpIfCantFling .byte \battler @@ -1361,6 +1361,11 @@ callnative BS_SetSnow .endm + .macro applysaltcure battler:req + callnative BS_ApplySaltCure + .byte \battler + .endm + .macro setzeffect callnative BS_SetZEffect .endm @@ -1381,7 +1386,7 @@ .byte \counter .4byte \ptr .endm - + .macro jumpifcantloseitem battler:req, ptr:req callnative BS_JumpIfCantLoseItem .byte \battler @@ -2322,3 +2327,9 @@ various 0, VARIOUS_TRY_REVIVAL_BLESSING .4byte \jumpInstr .endm + + @ Will jump to script pointer if the specified battler has or has not fainted. + .macro jumpiffainted battler:req, value:req, ptr:req + getbattlerfainted \battler + jumpifbyte CMP_EQUAL, gBattleCommunication, \value, \ptr + .endm diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 4997f56d2e..0b72e1cf98 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -948,6 +948,7 @@ gBattleAnims_General:: .4byte General_AffectionHangedOn @ B_ANIM_AFFECTION_HANGED_ON .4byte General_Snow @ B_ANIM_SNOW_CONTINUES .4byte General_UltraBurst @ B_ANIM_ULTRA_BURST + .4byte General_SaltCureDamage @ B_ANIM_SALT_CURE_DAMAGE .align 2 gBattleAnims_Special:: @@ -27135,6 +27136,9 @@ General_AffectionHangedOn_3Hearts: waitforvisualfinish end +General_SaltCureDamage:: + goto Status_Freeze + SnatchMoveTrySwapFromSubstitute: createvisualtask AnimTask_IsAttackerBehindSubstitute, 2 jumprettrue SnatchMoveSwapSubstituteForMon diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index cc69d3f787..cf3c953f1b 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -436,6 +436,32 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectCorrosiveGas @ EFFECT_CORROSIVE_GAS .4byte BattleScript_EffectHit @ EFFECT_POPULATION_BOMB .4byte BattleScript_EffectMortalSpin @ EFFECT_MORTAL_SPIN + .4byte BattleScript_EffectHit @ EFFECT_GIGATON_HAMMER + .4byte BattleScript_EffectSaltCure @ EFFECT_SALT_CURE + +BattleScript_EffectSaltCure: + call BattleScript_EffectHit_Ret + jumpiffainted BS_TARGET, TRUE, BattleScript_EffectSaltCure_End + applysaltcure BS_TARGET + printstring STRINGID_TARGETISBEINGSALTCURED + waitmessage B_WAIT_TIME_LONG +BattleScript_EffectSaltCure_End: + goto BattleScript_MoveEnd + +BattleScript_SaltCureExtraDamage:: + playanimation BS_TARGET, B_ANIM_SALT_CURE_DAMAGE, NULL + waitanimation + call BattleScript_HurtTarget_NoString + printstring STRINGID_TARGETISHURTBYSALTCURE + waitmessage B_WAIT_TIME_LONG + end2 + +BattleScript_HurtTarget_NoString: + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + tryfaintmon BS_TARGET + return BattleScript_EffectMortalSpin: call BattleScript_EffectHit_Ret @@ -6617,8 +6643,7 @@ BattleScript_PursuitDmgOnSwitchOut:: waitmessage B_WAIT_TIME_LONG tryfaintmon BS_TARGET moveendfromto MOVEEND_ABILITIES, MOVEEND_CHOICE_MOVE - getbattlerfainted BS_TARGET - jumpifbyte CMP_EQUAL, gBattleCommunication, FALSE, BattleScript_PursuitDmgOnSwitchOutRet + jumpiffainted BS_TARGET, FALSE, BattleScript_PursuitDmgOnSwitchOutRet setbyte sGIVEEXP_STATE, 0 getexp BS_TARGET BattleScript_PursuitDmgOnSwitchOutRet: @@ -7131,8 +7156,7 @@ BattleScript_GulpMissileGorging:: healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER - getbattlerfainted BS_ATTACKER - jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_GulpMissileNoSecondEffectGorging + jumpiffainted BS_ATTACKER, TRUE, BattleScript_GulpMissileNoSecondEffectGorging BattleScript_GulpMissileNoDmgGorging: handleformchange BS_TARGET, 0 playanimation BS_TARGET, B_ANIM_FORM_CHANGE @@ -7160,8 +7184,7 @@ BattleScript_GulpMissileGulping:: healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER - getbattlerfainted BS_ATTACKER - jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_GulpMissileNoSecondEffectGulping + jumpiffainted BS_ATTACKER, TRUE, BattleScript_GulpMissileNoSecondEffectGulping jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_CLEAR_AMULET, BattleScript_GulpMissileNoSecondEffectGulping jumpifability BS_ATTACKER, ABILITY_CLEAR_BODY, BattleScript_GulpMissileNoSecondEffectGulping jumpifability BS_ATTACKER, ABILITY_FULL_METAL_BODY, BattleScript_GulpMissileNoSecondEffectGulping @@ -7502,6 +7525,14 @@ BattleScript_SelectingNotAllowedMoveHealBlockInPalace:: printstring STRINGID_HEALBLOCKPREVENTSUSAGE goto BattleScript_SelectingUnusableMoveInPalace +BattleScript_SelectingNotAllowedCurrentMove:: + printselectionstring STRINGID_CURRENTMOVECANTSELECT + endselectionscript + +BattleScript_SelectingNotAllowedCurrentMoveInPalace:: + printstring STRINGID_CURRENTMOVECANTSELECT + goto BattleScript_SelectingUnusableMoveInPalace + BattleScript_WishComesTrue:: trywish 1, BattleScript_WishButFullHp playanimation BS_TARGET, B_ANIM_WISH_HEAL @@ -7875,8 +7906,7 @@ BattleScript_CottonDownActivates:: savetarget setbyte gBattlerTarget, 0 BattleScript_CottonDownLoop: - getbattlerfainted BS_TARGET - jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_CottonDownLoopIncrement + jumpiffainted BS_TARGET, TRUE, BattleScript_CottonDownLoopIncrement setstatchanger STAT_SPEED, 1, TRUE jumpifbyteequal gBattlerTarget, gEffectBattler, BattleScript_CottonDownLoopIncrement statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_CottonDownTargetSpeedCantGoLower diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 2a810e7fff..335aafb589 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -475,6 +475,9 @@ extern const u8 BattleScript_BerserkGeneRet[]; extern const u8 BattleScript_TargetFormChangeWithStringNoPopup[]; extern const u8 BattleScript_DefDown[]; extern const u8 BattleScript_UltraBurst[]; +extern const u8 BattleScript_SelectingNotAllowedCurrentMove[]; +extern const u8 BattleScript_SelectingNotAllowedCurrentMoveInPalace[]; +extern const u8 BattleScript_SaltCureExtraDamage[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; diff --git a/include/battle_util.h b/include/battle_util.h index 62394d85dc..36fb7a6e53 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -15,6 +15,7 @@ #define MOVE_LIMITATION_BELCH (1 << 11) #define MOVE_LIMITATION_THROAT_CHOP (1 << 12) #define MOVE_LIMITATION_STUFF_CHEEKS (1 << 13) +#define MOVE_LIMITATION_GIGATON_HAMMER (1 << 14) #define MOVE_LIMITATION_PLACEHOLDER (1 << 15) #define MOVE_LIMITATIONS_ALL 0xFFFF diff --git a/include/constants/battle.h b/include/constants/battle.h index d99eae919a..0f0d39db8d 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -187,6 +187,7 @@ #define STATUS4_MUD_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6 #define STATUS4_WATER_SPORT (1 << 3) // Only used if B_SPORT_TURNS < GEN_6 #define STATUS4_INFINITE_CONFUSION (1 << 4) // Used for Berserk Gene +#define STATUS4_SALT_CURE (1 << 5) #define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked. #define HITMARKER_SKIP_DMG_TRACK (1 << 5) diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index e70eba0fd7..9876652b65 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -549,6 +549,7 @@ #define B_ANIM_AFFECTION_HANGED_ON 35 #define B_ANIM_SNOW_CONTINUES 36 #define B_ANIM_ULTRA_BURST 37 +#define B_ANIM_SALT_CURE_DAMAGE 38 // special animations table (gBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index e91d45d3e1..72f54c4ec5 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -413,7 +413,9 @@ #define EFFECT_CORROSIVE_GAS 407 #define EFFECT_POPULATION_BOMB 408 #define EFFECT_MORTAL_SPIN 409 +#define EFFECT_GIGATON_HAMMER 410 +#define EFFECT_SALT_CURE 411 -#define NUM_BATTLE_MOVE_EFFECTS 410 +#define NUM_BATTLE_MOVE_EFFECTS 412 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index dabb7d337f..f7845d80bc 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -668,8 +668,11 @@ #define STRINGID_ULTRABURSTREACTING 666 #define STRINGID_ULTRABURSTCOMPLETED 667 #define STRINGID_TEAMGAINEDEXP 668 +#define STRINGID_CURRENTMOVECANTSELECT 669 +#define STRINGID_TARGETISBEINGSALTCURED 670 +#define STRINGID_TARGETISHURTBYSALTCURE 671 -#define BATTLESTRINGS_COUNT 669 +#define BATTLESTRINGS_COUNT 672 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 39f5dbe088..1805b2d9d8 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4958,6 +4958,10 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) || gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) score += 3; break; + case EFFECT_SALT_CURE: + if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_WATER) || IS_BATTLER_OF_TYPE(battlerDef, TYPE_STEEL)) + score += 2; + break; } // move effect checks return score; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 9bd9ef2f70..ed75fbad24 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2973,7 +2973,7 @@ bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility) u32 ShouldTryToFlinch(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u16 move) { if (((AI_DATA->abilities[battlerAtk] != ABILITY_MOLD_BREAKER && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS)) - || AI_GetHoldEffect(battlerDef) == HOLD_EFFECT_COVERT_CLOAK + || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER)) // Opponent goes first { @@ -3010,7 +3010,7 @@ bool32 ShouldFakeOut(u8 battlerAtk, u8 battlerDef, u16 move) if (!gDisableStructs[battlerAtk].isFirstTurn || AI_DATA->abilities[battlerAtk] == ABILITY_GORILLA_TACTICS || AI_DATA->holdEffects[battlerAtk] == HOLD_EFFECT_CHOICE_BAND - || AI_GetHoldEffect(battlerDef) == HOLD_EFFECT_COVERT_CLOAK + || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || (AI_DATA->abilities[battlerAtk] != ABILITY_MOLD_BREAKER && (AI_DATA->abilities[battlerDef] == ABILITY_SHIELD_DUST || AI_DATA->abilities[battlerDef] == ABILITY_INNER_FOCUS))) diff --git a/src/battle_message.c b/src/battle_message.c index 397cc213e2..a353c6b2de 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -804,9 +804,15 @@ static const u8 sText_PkmnItemMelted[] = _("{B_ATK_NAME_WITH_PREFIX} corroded\n{ static const u8 sText_UltraBurstReacting[] = _("Bright light is about to\nburst out of {B_ATK_NAME_WITH_PREFIX}!"); static const u8 sText_UltraBurstCompleted[] = _("{B_ATK_NAME_WITH_PREFIX} regained its\ntrue power through Ultra Burst!"); static const u8 sText_TeamGainedEXP[] = _("The rest of your team gained EXP.\nPoints thanks to the {B_LAST_ITEM}!\p"); +static const u8 sText_CurrentMoveCantSelect[] = _("{B_BUFF1} cannot be used!\p"); +static const u8 sText_TargetIsBeingSaltCured[] = _("{B_DEF_NAME_WITH_PREFIX} is being salt cured!"); +static const u8 sText_TargetIsHurtBySaltCure[] = _("{B_DEF_NAME_WITH_PREFIX} is hurt by {B_BUFF1}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_TARGETISHURTBYSALTCURE - BATTLESTRINGS_TABLE_START] = sText_TargetIsHurtBySaltCure, + [STRINGID_TARGETISBEINGSALTCURED - BATTLESTRINGS_TABLE_START] = sText_TargetIsBeingSaltCured, + [STRINGID_CURRENTMOVECANTSELECT - BATTLESTRINGS_TABLE_START] = sText_CurrentMoveCantSelect, [STRINGID_PKMNITEMMELTED - BATTLESTRINGS_TABLE_START] = sText_PkmnItemMelted, [STRINGID_MIRRORHERBCOPIED - BATTLESTRINGS_TABLE_START] = sText_MirrorHerbCopied, [STRINGID_THUNDERCAGETRAPPED - BATTLESTRINGS_TABLE_START] = sText_AtkTrappedDef, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5c779c3d13..1183d40520 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -16311,3 +16311,12 @@ void BS_JumpIfMotor(void) else gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_ApplySaltCure(void) +{ + NATIVE_ARGS(u8 battler); + + u8 battler = GetBattlerForBattleScript(cmd->battler); + gStatuses4[battler] |= STATUS4_SALT_CURE; + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index 5ce61373d6..b13e3cb293 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1749,6 +1749,22 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } + if (gBattleMoves[move].effect == EFFECT_GIGATON_HAMMER && move == gLastResultingMoves[battler]) + { + gCurrentMove = move; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gCurrentMove); + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) + { + gPalaceSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedCurrentMoveInPalace; + gProtectStructs[battler].palaceUnableToUseMove = TRUE; + } + else + { + gSelectionBattleScripts[battler] = BattleScript_SelectingNotAllowedCurrentMove; + limitations++; + } + } + gPotentialItemEffectBattler = battler; if (HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) { @@ -1885,6 +1901,8 @@ u8 CheckMoveLimitations(u8 battler, u8 unusableMoves, u16 check) // Gorilla Tactics else if (check & MOVE_LIMITATION_CHOICE_ITEM && GetBattlerAbility(battler) == ABILITY_GORILLA_TACTICS && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != gBattleMons[battler].moves[i]) unusableMoves |= gBitTable[i]; + else if (check & MOVE_LIMITATION_GIGATON_HAMMER && gBattleMoves[gBattleMons[battler].moves[i]].effect == EFFECT_GIGATON_HAMMER && gBattleMons[battler].moves[i] == gLastResultingMoves[battler]) + unusableMoves |= gBitTable[i]; } return unusableMoves; } @@ -2523,6 +2541,7 @@ enum ENDTURN_SLOW_START, ENDTURN_PLASMA_FISTS, ENDTURN_CUD_CHEW, + ENDTURN_SALT_CURE, ENDTURN_BATTLER_COUNT }; @@ -3086,6 +3105,22 @@ u8 DoBattlerEndTurnEffects(void) gDisableStructs[battler].cudChew = TRUE; gBattleStruct->turnEffectsTracker++; break; + case ENDTURN_SALT_CURE: + if (gStatuses4[battler] & STATUS4_SALT_CURE && gBattleMons[battler].hp != 0) + { + gBattlerTarget = battler; + if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_STEEL) || IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_WATER)) + gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP / 4; + else + gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SALT_CURE); + BattleScriptExecute(BattleScript_SaltCureExtraDamage); + effect++; + } + gBattleStruct->turnEffectsTracker++; + break; case ENDTURN_BATTLER_COUNT: // done gBattleStruct->turnEffectsTracker = 0; gBattleStruct->turnEffectsBattlerId++; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 75b89dccc6..00a8ee2c79 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10687,7 +10687,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, - .ballisticMove = B_UPDATED_MOVE_FLAGS < GEN_9, + .ballisticMove = TRUE, }, [MOVE_ANCHOR_SHOT] = @@ -13218,7 +13218,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_SALT_CURE] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_SALT_CURE + .effect = EFFECT_SALT_CURE, .power = 40, .type = TYPE_ROCK, .accuracy = 100, @@ -13639,7 +13639,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_GIGATON_HAMMER] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_GIGATON_HAMMER + .effect = EFFECT_GIGATON_HAMMER, .power = 160, .type = TYPE_STEEL, .accuracy = 100, diff --git a/test/battle/move_effect/gigaton_hammer.c b/test/battle/move_effect/gigaton_hammer.c new file mode 100644 index 0000000000..aaff50f752 --- /dev/null +++ b/test/battle/move_effect/gigaton_hammer.c @@ -0,0 +1,63 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_GIGATON_HAMMER].effect == EFFECT_GIGATON_HAMMER); +} + +SINGLE_BATTLE_TEST("Struggle will be used if slow Encore is used on Gigaton Hammer") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_ENCORE].effect == EFFECT_ENCORE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_GIGATON_HAMMER); MOVE(opponent, MOVE_ENCORE); } + TURN { FORCED_MOVE(player); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GIGATON_HAMMER, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, player); + } +} + +SINGLE_BATTLE_TEST("Gigaton Hammer strikes again if fast encore is used") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_ENCORE].effect == EFFECT_ENCORE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_GIGATON_HAMMER); } + TURN { MOVE(opponent, MOVE_ENCORE); FORCED_MOVE(player); } + TURN { FORCED_MOVE(player); } + TURN { FORCED_MOVE(player); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GIGATON_HAMMER, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GIGATON_HAMMER, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, player); + } +} + +SINGLE_BATTLE_TEST("Gigaton Hammer alternates with Struggle if it is the only usable move left") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_GIGATON_HAMMER, MOVE_NONE, MOVE_NONE, MOVE_NONE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_GIGATON_HAMMER); } + TURN { FORCED_MOVE(player); } + TURN { MOVE(player, MOVE_GIGATON_HAMMER); } + TURN { FORCED_MOVE(player); } + TURN { MOVE(player, MOVE_GIGATON_HAMMER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GIGATON_HAMMER, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GIGATON_HAMMER, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GIGATON_HAMMER, player); + } +} diff --git a/test/battle/move_effect/salt_cure.c b/test/battle/move_effect/salt_cure.c new file mode 100644 index 0000000000..fcf240631a --- /dev/null +++ b/test/battle/move_effect/salt_cure.c @@ -0,0 +1,72 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_SALT_CURE].effect == EFFECT_SALT_CURE); +} + +SINGLE_BATTLE_TEST("Salt Cure inflicts 1/8 of the target's maximum HP as damage per turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SALT_CURE); } + for (i = 0; i < 3; i++) + TURN {} + } SCENE { + s32 maxHP = GetMonData(&OPPONENT_PARTY[0], MON_DATA_MAX_HP); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SALT_CURE, player); + MESSAGE("Foe Wobbuffet is being salt cured!"); + for (i = 0; i < 4; i++) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SALT_CURE_DAMAGE, opponent); + HP_BAR(opponent, damage: maxHP / 8); + MESSAGE("Foe Wobbuffet is hurt by Salt Cure!"); + } + } +} + +SINGLE_BATTLE_TEST("Salt Cure inflicts 1/4 to Water/Steel types of their maximum HP as damage per turn") +{ + u32 species; + + PARAMETRIZE { species = SPECIES_LAPRAS; }; + PARAMETRIZE { species = SPECIES_JIRACHI; }; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species); + } WHEN { + TURN { MOVE(player, MOVE_SALT_CURE); } + TURN {} + } SCENE { + s32 maxHP = GetMonData(&OPPONENT_PARTY[0], MON_DATA_MAX_HP); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SALT_CURE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SALT_CURE_DAMAGE, opponent); + HP_BAR(opponent, damage: maxHP / 4); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SALT_CURE_DAMAGE, opponent); + HP_BAR(opponent, damage: maxHP / 4); + } +} + +SINGLE_BATTLE_TEST("Salt Cure is removed when the afflicted Pokémon is switched out") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_SALT_CURE); } + TURN { SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SALT_CURE, player); + MESSAGE("Foe Wobbuffet is being salt cured!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SALT_CURE_DAMAGE, opponent); + MESSAGE("Foe Wobbuffet is hurt by Salt Cure!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SALT_CURE_DAMAGE, opponent); + MESSAGE("Foe Wobbuffet is hurt by Salt Cure!"); + } + } +}