diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index ffa1176890..f661ad9dc2 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2384,10 +2384,6 @@ manipulatedamage DMG_CURR_ATTACKER_HP .endm - .macro dmg_1_2_attackerhp - manipulatedamage DMG_1_2_ATTACKER_HP - .endm - .macro jumpifflowerveil jumpInstr:req jumpifnottype BS_TARGET, TYPE_GRASS, 1f jumpifability BS_TARGET_SIDE, ABILITY_FLOWER_VEIL, \jumpInstr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6e11cbcaa8..7887a0da85 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -320,6 +320,7 @@ BattleScript_EffectSaltCure:: call BattleScript_EffectHit_Ret tryfaintmon BS_TARGET jumpiffainted BS_TARGET, TRUE, BattleScript_EffectSaltCure_End + jumpifsubstituteblocks BattleScript_EffectSaltCure_End applysaltcure BS_TARGET printstring STRINGID_TARGETISBEINGSALTCURED waitmessage B_WAIT_TIME_LONG @@ -579,36 +580,6 @@ BattleScript_EffectShellTrap:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectMaxHp50Recoil:: - attackcanceler - attackstring - ppreduce - accuracycheck BattleScript_SteelBeamMiss, ACC_CURR_MOVE - call BattleScript_EffectHit_RetFromCritCalc - jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_SteelBeamAfterSelfDamage - call BattleScript_SteelBeamSelfDamage -BattleScript_SteelBeamAfterSelfDamage:: - waitstate - tryfaintmon BS_ATTACKER - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd -BattleScript_SteelBeamMiss:: - pause B_WAIT_TIME_SHORT - effectivenesssound - resultmessage - waitmessage B_WAIT_TIME_LONG - jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_MoveEnd - bichalfword gMoveResultFlags, MOVE_RESULT_MISSED - call BattleScript_SteelBeamSelfDamage - orhalfword gMoveResultFlags, MOVE_RESULT_MISSED - goto BattleScript_SteelBeamAfterSelfDamage - -BattleScript_SteelBeamSelfDamage:: - dmg_1_2_attackerhp - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER - return - BattleScript_EffectCourtChange:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE @@ -3000,84 +2971,26 @@ BattleScript_AbsorbHealBlock:: tryfaintmon BS_TARGET goto BattleScript_MoveEnd -BattleScript_EffectExplosion_AnimDmgRet: - jumpifbyte CMP_NO_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_MISSED, BattleScript_ExplosionAnimRet - call BattleScript_PreserveMissedBitDoMoveAnim - goto BattleScript_ExplosionDmgRet -BattleScript_ExplosionAnimRet: - attackanimation - waitanimation -BattleScript_ExplosionDmgRet: - movevaluescleanup - critcalc - damagecalc - adjustdamage - accuracycheck BattleScript_ExplosionMissedRet, ACC_CURR_MOVE - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG - tryfaintmon BS_TARGET -BattleScript_ExplosionAnimEndRet_Return: - return -BattleScript_ExplosionMissedRet: - effectivenesssound - resultmessage - waitmessage B_WAIT_TIME_LONG - goto BattleScript_ExplosionAnimEndRet_Return - BattleScript_EffectExplosion:: attackcanceler attackstring ppreduce -@ Below jumps to BattleScript_DampStopsExplosion if it fails (only way it can) tryexplosion - waitstate -BattleScript_EffectExplosion_AnimDmgFaintAttacker: - call BattleScript_EffectExplosion_AnimDmgRet - moveendall setatkhptozero - tryfaintmon BS_ATTACKER - end - -BattleScript_EffectMindBlown:: - attackcanceler - attackstring - ppreduce - jumpifbyte CMP_GREATER_THAN, sB_ANIM_TARGETS_HIT, 0, BattleScript_EffectMindBlown_NoHpLoss - jumpifabilitypresent ABILITY_DAMP, BattleScript_MindBlownDamp - jumpifmorethanhalfHP BS_ATTACKER, BattleScript_EffectMindBlown_HpDown - setbyte sMULTIHIT_EFFECT, 0 @ Note to faint the attacker - instanthpdrop BS_ATTACKER waitstate - goto BattleScript_EffectExplosion_AnimDmgFaintAttacker -BattleScript_EffectMindBlown_NoHpLoss: - jumpifbyte CMP_EQUAL, sMULTIHIT_EFFECT, 0, BattleScript_EffectExplosion_AnimDmgFaintAttacker - goto BattleScript_EffectMindBlown_AnimDmgNoFaint -BattleScript_MindBlownDamp: - copybyte gBattlerTarget, gBattlerAbility - goto BattleScript_DampStopsExplosion -BattleScript_EffectMindBlown_HpDown: - setbyte sMULTIHIT_EFFECT, 1 @ Note to not faint the attacker - jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_EffectMindBlown_AnimDmgNoFaint - dmg_1_2_attackerhp + jumpiffainted BS_TARGET, TRUE, BattleScript_MoveEnd + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc + +BattleScript_FaintAttackerForExplosion:: + tryfaintmon BS_ATTACKER + return + +BattleScript_MaxHp50Recoil:: + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER - waitstate -BattleScript_EffectMindBlown_AnimDmgNoFaint: - call BattleScript_EffectExplosion_AnimDmgRet - goto BattleScript_MoveEnd - -BattleScript_PreserveMissedBitDoMoveAnim: - bichalfword gMoveResultFlags, MOVE_RESULT_MISSED - attackanimation - waitanimation - orhalfword gMoveResultFlags, MOVE_RESULT_MISSED + tryfaintmon BS_ATTACKER return BattleScript_EffectDreamEater:: @@ -7658,6 +7571,15 @@ BattleScript_AbilityPopUp: sethword sABILITY_OVERWRITE, 0 return +BattleScript_AbilityPopUpScripting: + .if B_ABILITY_POP_UP == TRUE + showabilitypopup BS_SCRIPTING + pause 40 + .endif + recordability BS_SCRIPTING + sethword sABILITY_OVERWRITE, 0 + return + BattleScript_SpeedBoostActivates:: statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_SpeedBoostActivatesEnd call BattleScript_AbilityPopUp @@ -8191,7 +8113,7 @@ BattleScript_SturdyPreventsOHKO:: BattleScript_DampStopsExplosion:: pause B_WAIT_TIME_SHORT - call BattleScript_AbilityPopUpTarget + call BattleScript_AbilityPopUpScripting printstring STRINGID_PKMNPREVENTSUSAGE pause B_WAIT_TIME_LONG moveendto MOVEEND_NEXT_TARGET diff --git a/graphics/pokemon/basculin/blue_striped/anim_front.png b/graphics/pokemon/basculin/blue_striped/anim_front.png new file mode 100644 index 0000000000..4b333a0ca8 Binary files /dev/null and b/graphics/pokemon/basculin/blue_striped/anim_front.png differ diff --git a/graphics/pokemon/basculin/blue_striped/front.png b/graphics/pokemon/basculin/blue_striped/front.png deleted file mode 100644 index cd6e6cda1b..0000000000 Binary files a/graphics/pokemon/basculin/blue_striped/front.png and /dev/null differ diff --git a/graphics/pokemon/basculin/white_striped/anim_front.png b/graphics/pokemon/basculin/white_striped/anim_front.png new file mode 100644 index 0000000000..ed4c680347 Binary files /dev/null and b/graphics/pokemon/basculin/white_striped/anim_front.png differ diff --git a/graphics/pokemon/basculin/white_striped/front.png b/graphics/pokemon/basculin/white_striped/front.png deleted file mode 100644 index f16202e149..0000000000 Binary files a/graphics/pokemon/basculin/white_striped/front.png and /dev/null differ diff --git a/graphics/pokemon/iron_bundle/back.png b/graphics/pokemon/iron_bundle/back.png index 1635738474..2b75da09fd 100644 Binary files a/graphics/pokemon/iron_bundle/back.png and b/graphics/pokemon/iron_bundle/back.png differ diff --git a/graphics/pokemon/iron_hands/back.png b/graphics/pokemon/iron_hands/back.png index b7702eb316..c7024a786a 100644 Binary files a/graphics/pokemon/iron_hands/back.png and b/graphics/pokemon/iron_hands/back.png differ diff --git a/graphics/pokemon/keldeo/resolute/anim_front.png b/graphics/pokemon/keldeo/resolute/anim_front.png new file mode 100644 index 0000000000..c2611bde2f Binary files /dev/null and b/graphics/pokemon/keldeo/resolute/anim_front.png differ diff --git a/graphics/pokemon/keldeo/resolute/front.png b/graphics/pokemon/keldeo/resolute/front.png deleted file mode 100644 index 8e83b810a7..0000000000 Binary files a/graphics/pokemon/keldeo/resolute/front.png and /dev/null differ diff --git a/graphics/pokemon/meloetta/pirouette/anim_front.png b/graphics/pokemon/meloetta/pirouette/anim_front.png new file mode 100644 index 0000000000..ec378790d8 Binary files /dev/null and b/graphics/pokemon/meloetta/pirouette/anim_front.png differ diff --git a/graphics/pokemon/meloetta/pirouette/front.png b/graphics/pokemon/meloetta/pirouette/front.png deleted file mode 100644 index a3b532860b..0000000000 Binary files a/graphics/pokemon/meloetta/pirouette/front.png and /dev/null differ diff --git a/graphics/pokemon/mewtwo/mega_y/back.png b/graphics/pokemon/mewtwo/mega_y/back.png index d908b50511..9fa999a2ab 100644 Binary files a/graphics/pokemon/mewtwo/mega_y/back.png and b/graphics/pokemon/mewtwo/mega_y/back.png differ diff --git a/graphics/pokemon/xerneas/anim_front.png b/graphics/pokemon/xerneas/anim_front.png new file mode 100644 index 0000000000..fdfda5f137 Binary files /dev/null and b/graphics/pokemon/xerneas/anim_front.png differ diff --git a/graphics/pokemon/xerneas/front.png b/graphics/pokemon/xerneas/front.png deleted file mode 100644 index 85a22af42b..0000000000 Binary files a/graphics/pokemon/xerneas/front.png and /dev/null differ diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 2b9fc4ca0a..2e27b5e935 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -154,6 +154,8 @@ extern const u8 BattleScript_MoveEffectPayDay[]; extern const u8 BattleScript_MoveEffectWrap[]; extern const u8 BattleScript_MoveEffectConfusion[]; extern const u8 BattleScript_MoveEffectRecoil[]; +extern const u8 BattleScript_FaintAttackerForExplosion[]; +extern const u8 BattleScript_MaxHp50Recoil[]; extern const u8 BattleScript_DoRecoil33[]; extern const u8 BattleScript_Recoil33End[]; extern const u8 BattleScript_ItemSteal[]; @@ -782,7 +784,6 @@ extern const u8 BattleScript_EffectLaserFocus[]; extern const u8 BattleScript_EffectMagneticFlux[]; extern const u8 BattleScript_EffectGearUp[]; extern const u8 BattleScript_EffectStrengthSap[]; -extern const u8 BattleScript_EffectMindBlown[]; extern const u8 BattleScript_EffectPurify[]; extern const u8 BattleScript_FailIfNotArgType[]; extern const u8 BattleScript_EffectShoreUp[]; @@ -814,7 +815,6 @@ extern const u8 BattleScript_EffectClangorousSoul[]; extern const u8 BattleScript_EffectSkyDrop[]; extern const u8 BattleScript_EffectMeteorBeam[]; extern const u8 BattleScript_EffectCourtChange[]; -extern const u8 BattleScript_EffectMaxHp50Recoil[]; extern const u8 BattleScript_EffectExtremeEvoboost[]; extern const u8 BattleScript_EffectHitSetRemoveTerrain[]; extern const u8 BattleScript_EffectDarkVoid[]; diff --git a/include/battle_util.h b/include/battle_util.h index 27ecb26e82..ff8bc7e5d2 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -91,6 +91,7 @@ enum CANCELLER_POWDER_MOVE, CANCELLER_POWDER_STATUS, CANCELLER_THROAT_CHOP, + CANCELLER_EXPLODING_DAMP, CANCELLER_MULTIHIT_MOVES, CANCELLER_Z_MOVES, CANCELLER_END, diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index abb1a9ab0f..a86471b5d9 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -275,7 +275,6 @@ enum { EFFECT_MAGNETIC_FLUX, EFFECT_GEAR_UP, EFFECT_STRENGTH_SAP, - EFFECT_MIND_BLOWN, EFFECT_PURIFY, EFFECT_FAIL_IF_NOT_ARG_TYPE, EFFECT_SHORE_UP, @@ -318,6 +317,7 @@ enum { EFFECT_BEAK_BLAST, EFFECT_COURT_CHANGE, EFFECT_MAX_HP_50_RECOIL, + EFFECT_MIND_BLOWN, // Same as EFFECT_MAX_HP_50_RECOIL but is cancelled by Damp EFFECT_EXTREME_EVOBOOST, EFFECT_HIT_SET_REMOVE_TERRAIN, EFFECT_DARK_VOID, diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index ef8803ce42..7228954f21 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -246,8 +246,7 @@ #define DMG_FULL_ATTACKER_HP 4 #define DMG_CURR_ATTACKER_HP 5 #define DMG_BIG_ROOT 6 -#define DMG_1_2_ATTACKER_HP 7 -#define DMG_RECOIL_FROM_IMMUNE 8 // Used to calculate recoil for the Gen 4 version of Jump Kick +#define DMG_RECOIL_FROM_IMMUNE 7 // Used to calculate recoil for the Gen 4 version of Jump Kick // Cmd_jumpifcantswitch #define SWITCH_IGNORE_ESCAPE_PREVENTION (1 << 7) diff --git a/sound/cry_tables.inc b/sound/cry_tables.inc index c98e0ec746..13cb51f53c 100644 --- a/sound/cry_tables.inc +++ b/sound/cry_tables.inc @@ -1786,7 +1786,7 @@ gCryTable:: .endif @ P_FAMILY_CRABRAWLER .if P_FAMILY_ORICORIO == TRUE cry Cry_OricorioBaile - cry Cry_OricorioPomPom + cry_uncomp Cry_OricorioPomPom @ Cannot be heard unless we use cry_uncomp here. cry Cry_OricorioPau cry Cry_OricorioSensu .endif @ P_FAMILY_ORICORIO @@ -4212,7 +4212,7 @@ gCryTable_Reverse:: .endif @ P_FAMILY_CRABRAWLER .if P_FAMILY_ORICORIO == TRUE cry_reverse Cry_OricorioBaile - cry_reverse Cry_OricorioPomPom + cry_reverse_uncomp Cry_OricorioPomPom @ Cannot be heard unless we use cry_reverse_uncomp here. cry_reverse Cry_OricorioPau cry_reverse Cry_OricorioSensu .endif @ P_FAMILY_ORICORIO diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 6201ceffe5..68b9b1d2f9 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1437,6 +1437,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); else if (aiData->abilities[battlerDef] == ABILITY_SUCTION_CUPS) ADJUST_SCORE(-10); + else if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); break; case EFFECT_TOXIC_THREAD: if (!ShouldLowerStat(battlerDef, aiData->abilities[battlerDef], STAT_SPEED)) @@ -1468,6 +1470,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) return 0; if (!ShouldTryOHKO(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move)) ADJUST_SCORE(-10); + else if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); break; case EFFECT_MIST: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_MIST @@ -1505,7 +1509,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-3); break; case EFFECT_DISABLE: - if (gDisableStructs[battlerDef].disableTimer == 0 + if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); + else if (gDisableStructs[battlerDef].disableTimer == 0 && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { @@ -1525,7 +1531,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_ENCORE: - if (gDisableStructs[battlerDef].encoreTimer == 0 + if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); + else if (gDisableStructs[battlerDef].encoreTimer == 0 && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { @@ -1739,7 +1747,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_TORMENT: - if (gBattleMons[battlerDef].status2 & STATUS2_TORMENT + if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); + else if (gBattleMons[battlerDef].status2 & STATUS2_TORMENT || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { ADJUST_SCORE(-10); @@ -1942,6 +1952,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_DESTINY_BOND: if (gBattleMons[battlerDef].status2 & STATUS2_DESTINY_BOND) ADJUST_SCORE(-10); + else if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); break; case EFFECT_HEAL_BELL: if (!AnyPartyMemberStatused(battlerAtk, gMovesInfo[move].soundMove) || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) @@ -2138,6 +2150,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeSwapped || aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) ADJUST_SCORE(-10); + else if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); break; case EFFECT_WORRY_SEED: if (aiData->abilities[battlerDef] == ABILITY_INSOMNIA @@ -2156,6 +2170,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeOverwritten || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ABILITY_SHIELD) ADJUST_SCORE(-10); + else if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); break; case EFFECT_SIMPLE_BEAM: if (aiData->abilities[battlerDef] == ABILITY_SIMPLE @@ -2482,6 +2498,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(-10); } + else if (IsDynamaxed(battlerDef)) + ADJUST_SCORE(-10); else if (isDoubleBattle) { if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) @@ -3360,7 +3378,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (gBattleMons[battlerDef].statStages[STAT_EVASION] < 7 || aiData->abilities[battlerAtk] == ABILITY_NO_GUARD) ADJUST_SCORE(-2); break; - case EFFECT_BIDE: + case EFFECT_BIDE: if (aiData->hpPercents[battlerAtk] < 90) ADJUST_SCORE(-2); // Should be either removed or turned into increasing score case EFFECT_ACUPRESSURE: @@ -3381,7 +3399,10 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle); break; case EFFECT_ROAR: - if ((gMovesInfo[move].soundMove && aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF) || aiData->abilities[battlerDef] == ABILITY_SUCTION_CUPS) + if ((gMovesInfo[move].soundMove && aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF) + || aiData->abilities[battlerDef] == ABILITY_SUCTION_CUPS) + break; + else if (IsDynamaxed(battlerDef)) break; score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle); break; @@ -3466,7 +3487,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_OHKO: - if (gStatuses3[battlerAtk] & STATUS3_ALWAYS_HITS) + if (IsDynamaxed(battlerDef)) + break; + else if (gStatuses3[battlerAtk] & STATUS3_ALWAYS_HITS) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_MEAN_LOOK: @@ -3561,7 +3584,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_DISABLE: - if (gDisableStructs[battlerDef].disableTimer == 0 + if (IsDynamaxed(battlerDef)) + break; + else if (gDisableStructs[battlerDef].disableTimer == 0 && (gLastMoves[battlerDef] != MOVE_NONE) && (gLastMoves[battlerDef] != 0xFFFF) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) @@ -3572,7 +3597,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_ENCORE: - if (gDisableStructs[battlerDef].encoreTimer == 0 + if (IsDynamaxed(battlerDef)) + break; + else if (gDisableStructs[battlerDef].encoreTimer == 0 && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && (gBattleMoveEffects[gMovesInfo[gLastMoves[battlerDef]].effect].encourageEncore)) ADJUST_SCORE(BEST_EFFECT); @@ -3589,7 +3616,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_DESTINY_BOND: - if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER && CanTargetFaintAi(battlerDef, battlerAtk)) + if (IsDynamaxed(battlerDef)) + break; + else if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER && CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SPITE: @@ -4035,7 +4064,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_SKILL_SWAP: - if (gAbilitiesInfo[aiData->abilities[battlerDef]].aiRating > gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating) + if (IsDynamaxed(battlerDef)) + break; + else if (gAbilitiesInfo[aiData->abilities[battlerDef]].aiRating > gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_WORRY_SEED: @@ -4045,7 +4076,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_ENTRAINMENT: - if ((IsAbilityOfRating(aiData->abilities[battlerDef], 5) || gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 0) + if (IsDynamaxed(battlerDef)) + break; + else if ((IsAbilityOfRating(aiData->abilities[battlerDef], 5) || gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 0) && (aiData->abilities[battlerDef] != aiData->abilities[battlerAtk] && !(gStatuses3[battlerDef] & STATUS3_GASTRO_ACID))) ADJUST_SCORE(DECENT_EFFECT); break; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index ec628a6e68..aa73a7f3e7 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -751,8 +751,8 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s switch (gMovesInfo[move].effect) { - case EFFECT_MIND_BLOWN: case EFFECT_MAX_HP_50_RECOIL: + case EFFECT_MIND_BLOWN: return TRUE; case EFFECT_RECOIL_IF_MISS: if (AI_IsDamagedByRecoil(battlerAtk)) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a47f313f94..5b6d72fb51 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1273,7 +1273,7 @@ static void Cmd_attackcanceler(void) gCurrentActionFuncId = B_ACTION_FINISHED; return; } - if (!IsBattlerAlive(gBattlerAttacker) && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) + if (!IsBattlerAlive(gBattlerAttacker) && gMovesInfo[gCurrentMove].effect != EFFECT_EXPLOSION && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) { gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattlescriptCurrInstr = BattleScript_MoveEnd; @@ -5410,6 +5410,7 @@ static void Cmd_moveend(void) u16 *choicedMoveAtk = NULL; u32 endMode, endState; u32 originallyUsedMove; + u8 currBattler, liveBattlerCount; if (gChosenMove == MOVE_UNAVAILABLE) originallyUsedMove = MOVE_NONE; @@ -5562,18 +5563,38 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_RECOIL: - if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && IsBattlerAlive(gBattlerAttacker) - && gBattleScripting.savedDmg != 0) // Some checks may be redundant alongside this one + if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) { - if (gMovesInfo[gCurrentMove].recoil > 0) - { - gBattleMoveDamage = max(1, gBattleScripting.savedDmg * max(1, gMovesInfo[gCurrentMove].recoil) / 100); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; - effect = TRUE; - } + gBattleScripting.moveendState++; + break; + } + else if (gMovesInfo[gCurrentMove].recoil > 0 + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && IsBattlerAlive(gBattlerAttacker) + && gBattleScripting.savedDmg != 0) // Some checks may be redundant alongside this one + { + gBattleMoveDamage = max(1, gBattleScripting.savedDmg * max(1, gMovesInfo[gCurrentMove].recoil) / 100); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; + effect = TRUE; + } + else if (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION && !IsAbilityOnField(ABILITY_DAMP)) + { + gBattleMoveDamage = 0; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FaintAttackerForExplosion; + effect = TRUE; + } + else if ((gMovesInfo[gCurrentMove].effect == EFFECT_MAX_HP_50_RECOIL + || gMovesInfo[gCurrentMove].effect == EFFECT_MIND_BLOWN) + && IsBattlerAlive(gBattlerAttacker) + && !(gMoveResultFlags & MOVE_RESULT_FAILED) + && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MaxHp50Recoil; + effect = TRUE; } gBattleScripting.moveendState++; break; @@ -5654,7 +5675,10 @@ static void Cmd_moveend(void) switch (gBattleStruct->moveEffect2) { case MOVE_EFFECT_KNOCK_OFF: - effect = TryKnockOffBattleScript(gBattlerTarget); + if (!DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + { + effect = TryKnockOffBattleScript(gBattlerTarget); + } break; case MOVE_EFFECT_STOCKPILE_WORE_OFF: if (gDisableStructs[gBattlerAttacker].stockpileCounter != 0) @@ -5666,7 +5690,9 @@ static void Cmd_moveend(void) } break; case MOVE_EFFECT_SMACK_DOWN: - if (!IsBattlerGrounded(gBattlerTarget) && IsBattlerAlive(gBattlerTarget)) + if (!IsBattlerGrounded(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN; gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR); @@ -5676,7 +5702,9 @@ static void Cmd_moveend(void) } break; case MOVE_EFFECT_REMOVE_STATUS: // Smelling salts, Wake-Up Slap, Sparkling Aria - if ((gBattleMons[gBattlerTarget].status1 & gMovesInfo[gCurrentMove].argument) && IsBattlerAlive(gBattlerTarget)) + if ((gBattleMons[gBattlerTarget].status1 & gMovesInfo[gCurrentMove].argument) + && IsBattlerAlive(gBattlerTarget) + && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { gBattleMons[gBattlerTarget].status1 &= ~(gMovesInfo[gCurrentMove].argument); @@ -5693,8 +5721,28 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_TargetWokeUp; break; case STATUS1_BURN: - gBattlescriptCurrInstr = BattleScript_TargetBurnHeal; - break; + // Checks to see if Sparkling Aria should cure a Shield Dust pokemon + if (gBattleMons[gBattlerTarget].ability == ABILITY_SHIELD_DUST || gBattleMons[gBattlerTarget].item == ITEM_COVERT_CLOAK) + { + liveBattlerCount = 0; + for (currBattler = 0; currBattler < gBattlersCount; currBattler++) + { + if (gBattleMons[currBattler].hp != 0) + { + liveBattlerCount++; + } + } + if (liveBattlerCount > 2) + { + gBattlescriptCurrInstr = BattleScript_TargetBurnHeal; + } + break; + } + else + { + gBattlescriptCurrInstr = BattleScript_TargetBurnHeal; + break; + } } } break; // MOVE_EFFECT_REMOVE_STATUS @@ -5918,7 +5966,11 @@ static void Cmd_moveend(void) gBattleScripting.moveendState = 0; MoveValuesCleanUp(); gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect; - BattleScriptPush(GET_MOVE_BATTLESCRIPT(gCurrentMove)); + + if (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION) + BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); // Edge case for Explosion not changing targets + else + BattleScriptPush(GET_MOVE_BATTLESCRIPT(gCurrentMove)); gBattlescriptCurrInstr = BattleScript_FlushMessageBox; return; } @@ -7215,22 +7267,10 @@ static void Cmd_switchineffects(void) gDisableStructs[battler].truantSwitchInHack = 0; - // Don't activate switch-in abilities if the opposing field is empty. - // This could happen when a mon uses explosion and causes everyone to faint. - if ((battlerAbility == ABILITY_INTIMIDATE || battlerAbility == ABILITY_SUPERSWEET_SYRUP || battlerAbility == ABILITY_DOWNLOAD) - && !IsBattlerAlive(BATTLE_OPPOSITE(battler)) - && !IsBattlerAlive(BATTLE_PARTNER(BATTLE_OPPOSITE(battler)))) - { - if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE)) - return; - } - else - { - if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE)) - return; - else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0)) - return; - } + if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE)) + return; + else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0)) + return; gDisableStructs[battler].stickyWebDone = FALSE; gDisableStructs[battler].spikesDone = FALSE; @@ -10993,19 +11033,9 @@ static void Cmd_tryexplosion(void) { CMD_ARGS(); - u32 dampBattler; if (gBattleControllerExecFlags) return; - if ((dampBattler = IsAbilityOnField(ABILITY_DAMP))) - { - // Failed, a battler has Damp - gLastUsedAbility = ABILITY_DAMP; - gBattlerTarget = --dampBattler; - gBattlescriptCurrInstr = BattleScript_DampStopsExplosion; - return; - } - gBattleMoveDamage = gBattleMons[gBattlerAttacker].hp; BtlController_EmitHealthBarUpdate(gBattlerAttacker, BUFFER_A, INSTANT_HP_BAR_DROP); MarkBattlerForControllerExec(gBattlerAttacker); @@ -11250,9 +11280,6 @@ static void Cmd_manipulatedamage(void) case DMG_BIG_ROOT: gBattleMoveDamage = GetDrainedBigRootHp(gBattlerAttacker, gBattleMoveDamage); break; - case DMG_1_2_ATTACKER_HP: - gBattleMoveDamage = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP - break; case DMG_RECOIL_FROM_IMMUNE: gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerTarget) / 2; break; diff --git a/src/battle_util.c b/src/battle_util.c index aa4f405d84..67f36e80ef 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3583,6 +3583,20 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) } gBattleStruct->atkCancellerTracker++; break; + case CANCELLER_EXPLODING_DAMP: + { + u32 dampBattler = IsAbilityOnField(ABILITY_DAMP); + if (dampBattler && (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION + || gMovesInfo[gCurrentMove].effect == EFFECT_MIND_BLOWN)) + { + gBattleScripting.battler = dampBattler - 1; + gBattlescriptCurrInstr = BattleScript_DampStopsExplosion; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + effect = 1; + } + gBattleStruct->atkCancellerTracker++; + break; + } case CANCELLER_MULTIHIT_MOVES: if (gMovesInfo[gCurrentMove].effect == EFFECT_MULTI_HIT) { @@ -8713,8 +8727,11 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3 break; case EFFECT_DOUBLE_POWER_ON_ARG_STATUS: // Comatose targets treated as if asleep - if ((gBattleMons[battlerDef].status1 | (STATUS1_SLEEP * (abilityDef == ABILITY_COMATOSE))) & gMovesInfo[move].argument) + if ((gBattleMons[battlerDef].status1 | (STATUS1_SLEEP * (abilityDef == ABILITY_COMATOSE))) & gMovesInfo[move].argument + && !((gMovesInfo[move].additionalEffects->moveEffect == MOVE_EFFECT_REMOVE_STATUS) && DoesSubstituteBlockMove(battlerAtk, battlerDef, move))) + { basePower *= 2; + } break; case EFFECT_VARY_POWER_BASED_ON_HP: basePower = gMovesInfo[move].argument * gBattleMons[battlerDef].hp / gBattleMons[battlerDef].maxHP; diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index 29acfc4630..966d4d0dea 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -1766,12 +1766,6 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, - [EFFECT_MIND_BLOWN] = - { - .battleScript = BattleScript_EffectMindBlown, - .battleTvScore = 0, // TODO: Assign points - }, - [EFFECT_PURIFY] = { .battleScript = BattleScript_EffectPurify, @@ -2029,7 +2023,13 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_MAX_HP_50_RECOIL] = { - .battleScript = BattleScript_EffectMaxHp50Recoil, + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, + + [EFFECT_MIND_BLOWN] = + { + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h index f15a9b5c2d..ef0755e9be 100644 --- a/src/data/graphics/pokemon.h +++ b/src/data/graphics/pokemon.h @@ -7278,14 +7278,14 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar const u8 gMonFootprint_Basculin[] = INCBIN_U8("graphics/pokemon/basculin/footprint.1bpp"); #endif //P_FOOTPRINTS - const u32 gMonFrontPic_BasculinBlueStriped[] = INCBIN_U32("graphics/pokemon/basculin/blue_striped/front.4bpp.lz"); + const u32 gMonFrontPic_BasculinBlueStriped[] = INCBIN_U32("graphics/pokemon/basculin/blue_striped/anim_front.4bpp.lz"); const u32 gMonPalette_BasculinBlueStriped[] = INCBIN_U32("graphics/pokemon/basculin/blue_striped/normal.gbapal.lz"); const u32 gMonBackPic_BasculinBlueStriped[] = INCBIN_U32("graphics/pokemon/basculin/blue_striped/back.4bpp.lz"); const u32 gMonShinyPalette_BasculinBlueStriped[] = INCBIN_U32("graphics/pokemon/basculin/blue_striped/shiny.gbapal.lz"); const u8 gMonIcon_BasculinBlueStriped[] = INCBIN_U8("graphics/pokemon/basculin/blue_striped/icon.4bpp"); #if P_HISUIAN_FORMS - const u32 gMonFrontPic_BasculinWhiteStriped[] = INCBIN_U32("graphics/pokemon/basculin/white_striped/front.4bpp.lz"); + const u32 gMonFrontPic_BasculinWhiteStriped[] = INCBIN_U32("graphics/pokemon/basculin/white_striped/anim_front.4bpp.lz"); const u32 gMonPalette_BasculinWhiteStriped[] = INCBIN_U32("graphics/pokemon/basculin/white_striped/normal.gbapal.lz"); const u32 gMonBackPic_BasculinWhiteStriped[] = INCBIN_U32("graphics/pokemon/basculin/white_striped/back.4bpp.lz"); const u32 gMonShinyPalette_BasculinWhiteStriped[] = INCBIN_U32("graphics/pokemon/basculin/white_striped/shiny.gbapal.lz"); @@ -8472,7 +8472,7 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar const u8 gMonFootprint_Keldeo[] = INCBIN_U8("graphics/pokemon/keldeo/footprint.1bpp"); #endif //P_FOOTPRINTS - const u32 gMonFrontPic_KeldeoResolute[] = INCBIN_U32("graphics/pokemon/keldeo/resolute/front.4bpp.lz"); + const u32 gMonFrontPic_KeldeoResolute[] = INCBIN_U32("graphics/pokemon/keldeo/resolute/anim_front.4bpp.lz"); const u32 gMonPalette_KeldeoResolute[] = INCBIN_U32("graphics/pokemon/keldeo/resolute/normal.gbapal.lz"); const u32 gMonBackPic_KeldeoResolute[] = INCBIN_U32("graphics/pokemon/keldeo/resolute/back.4bpp.lz"); const u32 gMonShinyPalette_KeldeoResolute[] = INCBIN_U32("graphics/pokemon/keldeo/resolute/shiny.gbapal.lz"); @@ -8489,7 +8489,7 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar const u8 gMonFootprint_Meloetta[] = INCBIN_U8("graphics/pokemon/meloetta/footprint.1bpp"); #endif //P_FOOTPRINTS - const u32 gMonFrontPic_MeloettaPirouette[] = INCBIN_U32("graphics/pokemon/meloetta/pirouette/front.4bpp.lz"); + const u32 gMonFrontPic_MeloettaPirouette[] = INCBIN_U32("graphics/pokemon/meloetta/pirouette/anim_front.4bpp.lz"); const u32 gMonPalette_MeloettaPirouette[] = INCBIN_U32("graphics/pokemon/meloetta/pirouette/normal.gbapal.lz"); const u32 gMonBackPic_MeloettaPirouette[] = INCBIN_U32("graphics/pokemon/meloetta/pirouette/back.4bpp.lz"); const u32 gMonShinyPalette_MeloettaPirouette[] = INCBIN_U32("graphics/pokemon/meloetta/pirouette/shiny.gbapal.lz"); @@ -9458,7 +9458,7 @@ const u8 gMonFootprint_QuestionMark[] = INCBIN_U8("graphics/pokemon/question_mar #endif //P_FAMILY_NOIBAT #if P_FAMILY_XERNEAS - const u32 gMonFrontPic_XerneasNeutral[] = INCBIN_U32("graphics/pokemon/xerneas/front.4bpp.lz"); + const u32 gMonFrontPic_XerneasNeutral[] = INCBIN_U32("graphics/pokemon/xerneas/anim_front.4bpp.lz"); const u32 gMonPalette_XerneasNeutral[] = INCBIN_U32("graphics/pokemon/xerneas/normal.gbapal.lz"); const u32 gMonBackPic_XerneasNeutral[] = INCBIN_U32("graphics/pokemon/xerneas/back.4bpp.lz"); const u32 gMonShinyPalette_XerneasNeutral[] = INCBIN_U32("graphics/pokemon/xerneas/shiny.gbapal.lz"); diff --git a/src/data/pokemon/species_info/gen_5_families.h b/src/data/pokemon/species_info/gen_5_families.h index 2d4a0abeb0..99197cfa0d 100644 --- a/src/data/pokemon/species_info/gen_5_families.h +++ b/src/data/pokemon/species_info/gen_5_families.h @@ -10207,7 +10207,7 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = .frontPicSize = MON_COORDS_SIZE(64, 64), .frontPicYOffset = 2, .frontAnimFrames = sAnims_KeldeoResolute, - .frontAnimId = ANIM_V_STRETCH, + .frontAnimId = ANIM_V_JUMPS_H_JUMPS, .backPic = gMonBackPic_KeldeoResolute, .backPicSize = MON_COORDS_SIZE(64, 64), .backPicYOffset = 3, @@ -10328,7 +10328,7 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = .trainerScale = 256, .trainerOffset = 0, .frontPic = gMonFrontPic_MeloettaPirouette, - .frontPicSize = MON_COORDS_SIZE(40, 64), + .frontPicSize = MON_COORDS_SIZE(64, 64), .frontPicYOffset = 2, .frontAnimFrames = sAnims_MeloettaPirouette, .frontAnimId = ANIM_H_SLIDE_SLOW, diff --git a/src/data/pokemon/species_info/gen_9_families.h b/src/data/pokemon/species_info/gen_9_families.h index 33097c3ef6..eb35606516 100644 --- a/src/data/pokemon/species_info/gen_9_families.h +++ b/src/data/pokemon/species_info/gen_9_families.h @@ -6189,7 +6189,7 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = //.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, .backPic = gMonBackPic_Munkidori, .backPicSize = MON_COORDS_SIZE(64, 64), - .backPicYOffset = 0, + .backPicYOffset = 2, //.backAnimId = BACK_ANIM_NONE, .palette = gMonPalette_Munkidori, .shinyPalette = gMonShinyPalette_Munkidori, diff --git a/test/battle/ability/shield_dust.c b/test/battle/ability/shield_dust.c index 8c655a22aa..24eb53a117 100644 --- a/test/battle/ability/shield_dust.c +++ b/test/battle/ability/shield_dust.c @@ -121,19 +121,44 @@ SINGLE_BATTLE_TEST("Shield Dust does not block self-targeting effects, primary o } } -DOUBLE_BATTLE_TEST("Shield Dust does not block Sparkling Aria in doubles") +DOUBLE_BATTLE_TEST("Shield Dust does or does not block Sparkling Aria depending on number of targets hit") { - KNOWN_FAILING; + u32 moveToUse; + PARAMETRIZE { moveToUse = MOVE_FINAL_GAMBIT; } + PARAMETRIZE { moveToUse = MOVE_TACKLE; } GIVEN { - PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_VIVILLON) { Ability(ABILITY_SHIELD_DUST); Status1(STATUS1_BURN); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(playerLeft, MOVE_SPARKLING_ARIA); } + TURN { MOVE(playerRight, moveToUse, target: opponentRight); MOVE(playerLeft, MOVE_SPARKLING_ARIA); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SPARKLING_ARIA, playerLeft); - MESSAGE("Foe Vivillion's burn was healed."); - STATUS_ICON(opponentLeft, burn: TRUE); + if (moveToUse == MOVE_TACKLE) { + MESSAGE("Foe Vivillon's burn was healed."); + STATUS_ICON(opponentLeft, none: TRUE); + } else { + NONE_OF { + MESSAGE("Foe Vivillon's burn was healed."); + STATUS_ICON(opponentLeft, none: TRUE); + } + } + } +} + +SINGLE_BATTLE_TEST("Shield Dust blocks Sparkling Aria in singles") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_VIVILLON) { Ability(ABILITY_SHIELD_DUST); Status1(STATUS1_BURN); } + } WHEN { + TURN { MOVE(player, MOVE_SPARKLING_ARIA); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPARKLING_ARIA, player); + NONE_OF { + MESSAGE("Foe Vivillon's burn was healed."); + STATUS_ICON(opponent, none: TRUE); + } } } diff --git a/test/battle/ability/supreme_overlord.c b/test/battle/ability/supreme_overlord.c index 5d24850245..061324c739 100644 --- a/test/battle/ability/supreme_overlord.c +++ b/test/battle/ability/supreme_overlord.c @@ -94,17 +94,14 @@ SINGLE_BATTLE_TEST("Supreme Overlord does not boost attack if party members are SINGLE_BATTLE_TEST("Supreme Overlord's message displays correctly after all battlers fainted - Player") { - // For some reason the Ability Pop Up fails to appear after Explosion. - KNOWN_FAILING; GIVEN { ASSUME(gMovesInfo[MOVE_EXPLOSION].effect == EFFECT_EXPLOSION); PLAYER(SPECIES_WOBBUFFET) { HP(1);} - PLAYER(SPECIES_KINGAMBIT); + PLAYER(SPECIES_KINGAMBIT) { Ability(ABILITY_SUPREME_OVERLORD); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(opponent, MOVE_EXPLOSION); SEND_OUT(player, 1); SEND_OUT(opponent, 1); } - TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_KOWTOW_CLEAVE); } } SCENE { HP_BAR(opponent, hp: 0); ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, opponent); @@ -118,18 +115,14 @@ SINGLE_BATTLE_TEST("Supreme Overlord's message displays correctly after all batt SINGLE_BATTLE_TEST("Supreme Overlord's message displays correctly after all battlers fainted - Opponent") { - // For some reason the Ability Pop Up fails to appear after Explosion. - KNOWN_FAILING; GIVEN { ASSUME(gMovesInfo[MOVE_EXPLOSION].effect == EFFECT_EXPLOSION); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { HP(1);} - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_KINGAMBIT); + OPPONENT(SPECIES_KINGAMBIT) { Ability(ABILITY_SUPREME_OVERLORD); } } WHEN { TURN { MOVE(player, MOVE_EXPLOSION); SEND_OUT(player, 1); SEND_OUT(opponent, 1); } - TURN { SWITCH(opponent, 2); MOVE(player, MOVE_TACKLE); } } SCENE { HP_BAR(player, hp: 0); ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player); diff --git a/test/battle/item_effect/covert_cloak.c b/test/battle/item_effect/covert_cloak.c new file mode 100644 index 0000000000..4953ef4682 --- /dev/null +++ b/test/battle/item_effect/covert_cloak.c @@ -0,0 +1,162 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Covert Cloak blocks secondary effects") +{ + u16 move; + PARAMETRIZE { move = MOVE_NUZZLE; } + PARAMETRIZE { move = MOVE_INFERNO; } + PARAMETRIZE { move = MOVE_MORTAL_SPIN; } + PARAMETRIZE { move = MOVE_FAKE_OUT; } + PARAMETRIZE { move = MOVE_ROCK_TOMB; } + PARAMETRIZE { move = MOVE_SPIRIT_SHACKLE; } + PARAMETRIZE { move = MOVE_PSYCHIC_NOISE; } + + GIVEN { + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_NUZZLE, MOVE_EFFECT_PARALYSIS, 100) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_INFERNO, MOVE_EFFECT_BURN, 100) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_MORTAL_SPIN, MOVE_EFFECT_POISON, 100) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_FAKE_OUT, MOVE_EFFECT_FLINCH, 100) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_ROCK_TOMB, MOVE_EFFECT_SPD_MINUS_1, 100) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_SPIRIT_SHACKLE, MOVE_EFFECT_PREVENT_ESCAPE, 100) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_PSYCHIC_NOISE, MOVE_EFFECT_PSYCHIC_NOISE, 100) == TRUE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_COVERT_CLOAK); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + NONE_OF { + MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!"); + MESSAGE("Foe Wobbuffet was burned!"); + MESSAGE("Foe Wobbuffet was poisoned!"); + MESSAGE("Foe Wobbuffet flinched!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet was prevented from healing!"); + } + } THEN { // Can't find good way to test trapping + EXPECT(!(opponent->status2 & STATUS2_ESCAPE_PREVENTION)); + } +} + +SINGLE_BATTLE_TEST("Covert Cloak does not block primary effects") +{ + u16 move; + PARAMETRIZE { move = MOVE_INFESTATION; } + PARAMETRIZE { move = MOVE_THOUSAND_ARROWS; } + PARAMETRIZE { move = MOVE_JAW_LOCK; } + PARAMETRIZE { move = MOVE_PAY_DAY; } + + GIVEN { + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_INFESTATION, MOVE_EFFECT_WRAP, 0) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_THOUSAND_ARROWS, MOVE_EFFECT_SMACK_DOWN, 0) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_JAW_LOCK, MOVE_EFFECT_TRAP_BOTH, 0) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_PAY_DAY, MOVE_EFFECT_PAYDAY, 0) == TRUE); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_SMACK_DOWN, MOVE_EFFECT_SMACK_DOWN, 0) == TRUE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SKARMORY) { Item(ITEM_COVERT_CLOAK); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + switch (move) { + case MOVE_INFESTATION: + MESSAGE("Foe Skarmory has been afflicted with an infestation by Wobbuffet!"); + break; + case MOVE_THOUSAND_ARROWS: + MESSAGE("Foe Skarmory fell straight down!"); + break; + case MOVE_JAW_LOCK: + MESSAGE("Neither Pokémon can run away!"); + break; + case MOVE_PAY_DAY: + MESSAGE("Coins scattered everywhere!"); + break; + } + } THEN { // Can't find good way to test trapping + if (move == MOVE_JAW_LOCK) { + EXPECT(opponent->status2 & STATUS2_ESCAPE_PREVENTION); + EXPECT(player->status2 & STATUS2_ESCAPE_PREVENTION); + } + } +} + +SINGLE_BATTLE_TEST("Covert Cloak does not block self-targeting effects, primary or secondary") +{ + u16 move; + PARAMETRIZE { move = MOVE_POWER_UP_PUNCH; } + PARAMETRIZE { move = MOVE_RAPID_SPIN; } + PARAMETRIZE { move = MOVE_LEAF_STORM; } + PARAMETRIZE { move = MOVE_METEOR_ASSAULT; } + + GIVEN { + ASSUME(MoveHasAdditionalEffectSelf(MOVE_POWER_UP_PUNCH, MOVE_EFFECT_ATK_PLUS_1) == TRUE); + ASSUME(MoveHasAdditionalEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_RAPID_SPIN) == TRUE); + ASSUME(MoveHasAdditionalEffectSelf(MOVE_LEAF_STORM, MOVE_EFFECT_SP_ATK_MINUS_2) == TRUE); + ASSUME(MoveHasAdditionalEffectSelf(MOVE_METEOR_ASSAULT, MOVE_EFFECT_RECHARGE) == TRUE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_COVERT_CLOAK); } + } WHEN { + TURN { MOVE(player, move); } + if (move == MOVE_METEOR_ASSAULT) { + TURN { SKIP_TURN(player); } + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + switch (move) { + case MOVE_POWER_UP_PUNCH: + case MOVE_RAPID_SPIN: + case MOVE_LEAF_STORM: + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + break; + case MOVE_METEOR_ASSAULT: // second turn + MESSAGE("Wobbuffet must recharge!"); + break; + } + } +} + +DOUBLE_BATTLE_TEST("Covert Cloak does or does not block Sparkling Aria depending on number of targets hit") +{ + u32 moveToUse; + PARAMETRIZE { moveToUse = MOVE_FINAL_GAMBIT; } + PARAMETRIZE { moveToUse = MOVE_TACKLE; } + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_COVERT_CLOAK); Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerRight, moveToUse, target: opponentRight); MOVE(playerLeft, MOVE_SPARKLING_ARIA); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPARKLING_ARIA, playerLeft); + if (moveToUse == MOVE_TACKLE) { + MESSAGE("Foe Wobbuffet's burn was healed."); + STATUS_ICON(opponentLeft, none: TRUE); + } else { + NONE_OF { + MESSAGE("Foe Wobbuffet's burn was healed."); + STATUS_ICON(opponentLeft, none: TRUE); + } + } + } +} + +SINGLE_BATTLE_TEST("Covert Cloak blocks Sparkling Aria in singles") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_COVERT_CLOAK); Status1(STATUS1_BURN); } + } WHEN { + TURN { MOVE(player, MOVE_SPARKLING_ARIA); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPARKLING_ARIA, player); + NONE_OF { + MESSAGE("Foe Wobbuffet's burn was healed."); + STATUS_ICON(opponent, none: TRUE); + } + } +} diff --git a/test/battle/move_effect/explosion.c b/test/battle/move_effect/explosion.c index 21d3f1b790..10e9feaa80 100644 --- a/test/battle/move_effect/explosion.c +++ b/test/battle/move_effect/explosion.c @@ -62,7 +62,6 @@ SINGLE_BATTLE_TEST("Explosion causes the user to faint even if it has no effect" TURN { MOVE(player, MOVE_EXPLOSION); } } SCENE { HP_BAR(player, hp: 0); - ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player); MESSAGE("It doesn't affect Foe Gastly…"); NOT HP_BAR(opponent); MESSAGE("Wobbuffet fainted!"); @@ -91,3 +90,36 @@ DOUBLE_BATTLE_TEST("Explosion causes everyone to faint in a double battle") MESSAGE("Wobbuffet fainted!"); } } + +SINGLE_BATTLE_TEST("Explosion is blocked by Ability Damp") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_DAMP); } + } WHEN { + TURN { MOVE(player, MOVE_EXPLOSION); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, player); + HP_BAR(player, hp: 0); + } + ABILITY_POPUP(opponent, ABILITY_DAMP); + MESSAGE("Foe Golduck's Damp prevents Wobbuffet from using Explosion!"); + } +} + +SINGLE_BATTLE_TEST("Explosion does not trigger Destiny Bond") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DESTINY_BOND); MOVE(opponent, MOVE_EXPLOSION);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, opponent); + HP_BAR(player); + NOT HP_BAR(opponent); + } +} diff --git a/test/battle/move_effect/hit_escape.c b/test/battle/move_effect/hit_escape.c index f4bfc42cc8..235e0773fe 100644 --- a/test/battle/move_effect/hit_escape.c +++ b/test/battle/move_effect/hit_escape.c @@ -137,6 +137,7 @@ SINGLE_BATTLE_TEST("Held items are consumed immediately after a mon switched in SINGLE_BATTLE_TEST("Held items are consumed immediately after a mon switched in by U-turn and Intimidate activates after it: opposing side") { + KNOWN_FAILING; GIVEN { PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); }; PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } diff --git a/test/battle/move_effect/knock_off.c b/test/battle/move_effect/knock_off.c index 49e5c499d3..93039e0017 100644 --- a/test/battle/move_effect/knock_off.c +++ b/test/battle/move_effect/knock_off.c @@ -193,3 +193,15 @@ DOUBLE_BATTLE_TEST("Knock Off does not trigger the opposing ally's Symbiosis") EXPECT(playerLeft->item == ITEM_NONE); } } + +SINGLE_BATTLE_TEST("Knock Off doesn't knock off items from Pokemon behind substitutes") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_POKE_BALL); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + NOT MESSAGE("Wobbuffet knocked off Foe Wobbuffet's Poké Ball"); + } +} diff --git a/test/battle/move_effect/max_hp_50_recoil.c b/test/battle/move_effect/max_hp_50_recoil.c index d310de84c2..8d5cbdaed2 100644 --- a/test/battle/move_effect/max_hp_50_recoil.c +++ b/test/battle/move_effect/max_hp_50_recoil.c @@ -6,21 +6,80 @@ ASSUMPTIONS ASSUME(gMovesInfo[MOVE_STEEL_BEAM].effect == EFFECT_MAX_HP_50_RECOIL); } -SINGLE_BATTLE_TEST("Steel Beam causes the user to take damage equal to half of its maximum HP") +SINGLE_BATTLE_TEST("Steel Beam makes the user lose 1/2 of its Max HP") { - s16 recoilDamage; - GIVEN { - PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_STEEL_BEAM); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player); - HP_BAR(opponent); - HP_BAR(player, captureDamage: &recoilDamage); - } THEN { - EXPECT_EQ(player->maxHP / 2, recoilDamage); + HP_BAR(player, damage: 200); + NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint. + } +} + +DOUBLE_BATTLE_TEST("Steel Beam makes the user lose 1/2 of its Max HP in a double battle") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_STEEL_BEAM, target:opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, playerLeft); + HP_BAR(playerLeft, damage: 200); + NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint. + } +} + +SINGLE_BATTLE_TEST("Steel Beam causes the user to faint when below 1/2 of its Max HP") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STEEL_BEAM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player); + HP_BAR(player, hp: 0); + MESSAGE("Wobbuffet fainted!"); + } +} + +DOUBLE_BATTLE_TEST("Steel Beam causes the user to faint when below 1/2 of its Max HP in a double battle") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_STEEL_BEAM, target:opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, playerLeft); + HP_BAR(playerLeft, hp: 0); + MESSAGE("Wobbuffet fainted!"); + } +} + +SINGLE_BATTLE_TEST("Steel Beam causes the user & the target to faint when below 1/2 of its Max HP") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(200) ; MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STEEL_BEAM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player); + HP_BAR(opponent, hp: 0); + MESSAGE("Foe Wobbuffet fainted!"); + HP_BAR(player, hp: 0); + MESSAGE("Wobbuffet fainted!"); } } @@ -32,8 +91,58 @@ SINGLE_BATTLE_TEST("Steel Beam hp loss is prevented by Magic Guard") } WHEN { TURN { MOVE(player, MOVE_STEEL_BEAM); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player); - HP_BAR(opponent); NOT HP_BAR(player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player); + } +} + +SINGLE_BATTLE_TEST("Steel Beam makes the user lose HP even if the opposing mon protected") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_STEEL_BEAM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Steel Beam does not cause the user to lose HP if there is no target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_MEMENTO); MOVE(player, MOVE_STEEL_BEAM); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player); + HP_BAR(player); + } + MESSAGE("Wobbuffet used Steel Beam!"); + MESSAGE("But it failed!"); + MESSAGE("2 sent out Wobbuffet!"); + } +} + +SINGLE_BATTLE_TEST("Steel Beam is not blocked by Damp") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); } + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_DAMP); } + } WHEN { + TURN { MOVE(player, MOVE_STEEL_BEAM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_BEAM, player); + HP_BAR(player, damage: 200); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_DAMP); + MESSAGE("Foe Golduck's Damp prevents Wobbuffet from using Steel Beam!"); + } } } diff --git a/test/battle/move_effect/mind_blown.c b/test/battle/move_effect/mind_blown.c index 4f4d31cb18..f1b7d8b98a 100644 --- a/test/battle/move_effect/mind_blown.c +++ b/test/battle/move_effect/mind_blown.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(gMovesInfo[MOVE_MIND_BLOWN].effect == EFFECT_MIND_BLOWN); } -SINGLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its HP") +SINGLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its Max HP") { GIVEN { PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); } @@ -14,13 +14,13 @@ SINGLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its HP") } WHEN { TURN { MOVE(player, MOVE_MIND_BLOWN); } } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); HP_BAR(player, damage: 200); - ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint. } } -DOUBLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its HP in a double battle") +DOUBLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its Max HP in a double battle") { GIVEN { PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); } @@ -30,13 +30,13 @@ DOUBLE_BATTLE_TEST("Mind Blown makes the user lose 1/2 of its HP in a double bat } WHEN { TURN { MOVE(playerLeft, MOVE_MIND_BLOWN); } } SCENE { - HP_BAR(playerLeft, damage: 200); ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, playerLeft); + HP_BAR(playerLeft, damage: 200); NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint. } } -SINGLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its HP") +SINGLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its Max HP") { GIVEN { PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); } @@ -44,13 +44,13 @@ SINGLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its HP } WHEN { TURN { MOVE(player, MOVE_MIND_BLOWN); } } SCENE { - HP_BAR(player, hp: 0); ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); + HP_BAR(player, hp: 0); MESSAGE("Wobbuffet fainted!"); } } -DOUBLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its HP in a double battle") +DOUBLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its Max HP in a double battle") { GIVEN { PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); } @@ -60,13 +60,13 @@ DOUBLE_BATTLE_TEST("Mind Blown causes the user to faint when below 1/2 of its HP } WHEN { TURN { MOVE(playerLeft, MOVE_MIND_BLOWN); } } SCENE { - HP_BAR(playerLeft, hp: 0); ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, playerLeft); + HP_BAR(playerLeft, hp: 0); MESSAGE("Wobbuffet fainted!"); } } -SINGLE_BATTLE_TEST("Mind Blown causes the user & the target to faint when below 1/2 of its HP") +SINGLE_BATTLE_TEST("Mind Blown causes the user & the target to faint when below 1/2 of its Max HP") { GIVEN { PLAYER(SPECIES_WOBBUFFET) { HP(200) ; MaxHP(400); } @@ -75,10 +75,10 @@ SINGLE_BATTLE_TEST("Mind Blown causes the user & the target to faint when below } WHEN { TURN { MOVE(player, MOVE_MIND_BLOWN); } } SCENE { - HP_BAR(player, hp: 0); ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); HP_BAR(opponent, hp: 0); MESSAGE("Foe Wobbuffet fainted!"); + HP_BAR(player, hp: 0); MESSAGE("Wobbuffet fainted!"); } } @@ -94,7 +94,6 @@ DOUBLE_BATTLE_TEST("Mind Blown causes everyone to faint in a double battle") } WHEN { TURN { MOVE(playerLeft, MOVE_MIND_BLOWN); } } SCENE { - HP_BAR(playerLeft, hp: 0); ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, playerLeft); HP_BAR(opponentLeft, hp: 0); MESSAGE("Foe Abra fainted!"); @@ -102,6 +101,7 @@ DOUBLE_BATTLE_TEST("Mind Blown causes everyone to faint in a double battle") MESSAGE("Wynaut fainted!"); HP_BAR(opponentRight, hp: 0); MESSAGE("Foe Kadabra fainted!"); + HP_BAR(playerLeft, hp: 0); MESSAGE("Wobbuffet fainted!"); } } @@ -118,3 +118,69 @@ SINGLE_BATTLE_TEST("Mind Blown hp loss is prevented by Magic Guard") ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); } } + +SINGLE_BATTLE_TEST("Mind Blown is blocked by Damp") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); } + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_DAMP); } + } WHEN { + TURN { MOVE(player, MOVE_MIND_BLOWN); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); + HP_BAR(player, damage: 200); + } + ABILITY_POPUP(opponent, ABILITY_DAMP); + MESSAGE("Foe Golduck's Damp prevents Wobbuffet from using Mind Blown!"); + } +} + +SINGLE_BATTLE_TEST("Mind Blown makes the user lose HP even if the opposing mon protected") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_MIND_BLOWN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Mind Blown makes the user lose HP even if it is absorbed by Flash Fire") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_MIND_BLOWN].type == TYPE_FIRE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CYNDAQUIL) { Ability(ABILITY_FLASH_FIRE); } + } WHEN { + TURN { MOVE(player, MOVE_MIND_BLOWN); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_FLASH_FIRE); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Mind Blown does not cause the user to lose HP if there is no target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_MEMENTO); MOVE(player, MOVE_MIND_BLOWN); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, player); + HP_BAR(player); + } + MESSAGE("Wobbuffet used Mind Blown!"); + MESSAGE("But it failed!"); + MESSAGE("2 sent out Wobbuffet!"); + } +} diff --git a/test/battle/move_effect/salt_cure.c b/test/battle/move_effect/salt_cure.c index 547797e38b..939e32f0a6 100644 --- a/test/battle/move_effect/salt_cure.c +++ b/test/battle/move_effect/salt_cure.c @@ -85,3 +85,17 @@ SINGLE_BATTLE_TEST("If Salt Cure faints the target no status will be applied") MESSAGE("Foe Wobbuffet fainted!"); } } + +SINGLE_BATTLE_TEST("Salt Cure does not get applied if hitting a Substitute") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_SALT_CURE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SALT_CURE, player); + MESSAGE("The SUBSTITUTE took damage for Foe Wobbuffet!"); + NOT MESSAGE("Foe Wobbuffet is being salt cured!"); + } +} diff --git a/test/battle/move_effect/smack_down.c b/test/battle/move_effect/smack_down.c new file mode 100644 index 0000000000..54bf6885af --- /dev/null +++ b/test/battle/move_effect/smack_down.c @@ -0,0 +1,19 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_SMACK_DOWN].additionalEffects->moveEffect == MOVE_EFFECT_SMACK_DOWN); +} + +SINGLE_BATTLE_TEST("Smack Down does not ground mons behind substitutes") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SKARMORY); + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_SMACK_DOWN); } + } SCENE { + NOT MESSAGE("Foe Skarmory fell straight down!"); + } +} diff --git a/test/battle/move_effect/smelling_salts.c b/test/battle/move_effect/smelling_salts.c new file mode 100644 index 0000000000..09168f8a1e --- /dev/null +++ b/test/battle/move_effect/smelling_salts.c @@ -0,0 +1,63 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_SMELLING_SALTS].additionalEffects->moveEffect == MOVE_EFFECT_REMOVE_STATUS); + ASSUME(gMovesInfo[MOVE_SMELLING_SALTS].argument == STATUS1_PARALYSIS); +} + +SINGLE_BATTLE_TEST("Smelling Salts does not cure paralyzed pokemons behind substitutes or get increased power") +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_INNER_FOCUS; } + PARAMETRIZE { ability = ABILITY_INFILTRATOR; } + GIVEN { + PLAYER(SPECIES_CROBAT) { Ability(ability); } + OPPONENT(SPECIES_SEISMITOAD) { Status1(STATUS1_PARALYSIS); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_CELEBRATE); } + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SMELLING_SALTS); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SMELLING_SALTS, player); + if (ability == ABILITY_INNER_FOCUS) + { + MESSAGE("The SUBSTITUTE took damage for Foe Seismitoad!"); + NONE_OF + { + MESSAGE("Foe Seismitoad's SUBSTITUTE faded!"); // Smelling Salts does 86 damage, the sub has 122 HP, if hitting a sub it shouldn't get boosted damage. + MESSAGE("Foe Seismitoad was healed of paralysis!"); + STATUS_ICON(opponent, none: TRUE); + } + } + else + { + MESSAGE("Foe Seismitoad was healed of paralysis!"); + STATUS_ICON(opponent, none: TRUE); + } + } +} + +SINGLE_BATTLE_TEST("Smelling Salts get incread power vs. paralyzed targets") +{ + u32 status1; + PARAMETRIZE { status1 = STATUS1_PARALYSIS; } + PARAMETRIZE { status1 = STATUS1_NONE; } + GIVEN { + PLAYER(SPECIES_CROBAT); + OPPONENT(SPECIES_LOTAD) { Status1(status1); } + } WHEN { + TURN { MOVE(player, MOVE_SMELLING_SALTS); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SMELLING_SALTS, player); + if (status1 == STATUS1_PARALYSIS) + { + MESSAGE("Foe Lotad fainted!"); + } + else + { + NOT MESSAGE("Foe Lotad fainted!"); + MESSAGE("Foe Lotad used Celebrate!"); + } + } +} diff --git a/test/battle/move_effect/sparkling_aria.c b/test/battle/move_effect/sparkling_aria.c new file mode 100644 index 0000000000..1bf7de2df4 --- /dev/null +++ b/test/battle/move_effect/sparkling_aria.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_SPARKLING_ARIA].additionalEffects->moveEffect == MOVE_EFFECT_REMOVE_STATUS); + ASSUME(gMovesInfo[MOVE_SPARKLING_ARIA].argument == STATUS1_BURN); + ASSUME(gMovesInfo[MOVE_SPARKLING_ARIA].soundMove == TRUE); +} + +DOUBLE_BATTLE_TEST("Sparkling Aria cures burns from all Pokemon on the field and behind substitutes") +{ + GIVEN { + PLAYER(SPECIES_PRIMARINA); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WYNAUT) { Status1(STATUS1_BURN); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SUBSTITUTE); MOVE(opponentRight, MOVE_CELEBRATE); MOVE(playerRight, MOVE_CELEBRATE); MOVE(playerLeft, MOVE_SPARKLING_ARIA); } + } SCENE { + MESSAGE("Foe Wobbuffet's burn was healed."); + MESSAGE("Wobbuffet's burn was healed."); + MESSAGE("Foe Wynaut's burn was healed."); + } +} diff --git a/test/battle/move_effect/thousand_arrows.c b/test/battle/move_effect/thousand_arrows.c new file mode 100644 index 0000000000..bff3706c34 --- /dev/null +++ b/test/battle/move_effect/thousand_arrows.c @@ -0,0 +1,55 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_THOUSAND_ARROWS].additionalEffects->moveEffect == MOVE_EFFECT_SMACK_DOWN); + ASSUME(gMovesInfo[MOVE_THOUSAND_ARROWS].ignoreTypeIfFlyingAndUngrounded == TRUE); +} + +SINGLE_BATTLE_TEST("Thousand Arrows does not ground mons behind substitutes") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SKARMORY); + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_THOUSAND_ARROWS); } + } SCENE { + NOT MESSAGE("Foe Skarmory fell straight down!"); + } +} + +SINGLE_BATTLE_TEST("Thousand Arrows does neutral damage to non-grounded Flying types regardless of other typings") +{ + u32 pokemon; + PARAMETRIZE { pokemon = SPECIES_SKARMORY; } + PARAMETRIZE { pokemon = SPECIES_SCYTHER; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(pokemon); + } WHEN { + TURN { MOVE(player, MOVE_THOUSAND_ARROWS); } + TURN { MOVE(player, MOVE_THOUSAND_ARROWS); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THOUSAND_ARROWS, player); + if (pokemon == SPECIES_SKARMORY) { + MESSAGE("Foe Skarmory fell straight down!"); + MESSAGE("Foe Skarmory used Celebrate!"); + } else { + MESSAGE("Foe Scyther fell straight down!"); + MESSAGE("Foe Scyther used Celebrate!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + MESSAGE("Congratulations, 1!"); + MESSAGE("Wobbuffet used ThousndArrws!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_THOUSAND_ARROWS, player); + if (pokemon == SPECIES_SKARMORY) + { + MESSAGE("It's super effective!"); + } + else + { + MESSAGE("It's not very effective…"); + } + } +} diff --git a/test/battle/move_effect/wake_up_slap.c b/test/battle/move_effect/wake_up_slap.c new file mode 100644 index 0000000000..98bcf95b20 --- /dev/null +++ b/test/battle/move_effect/wake_up_slap.c @@ -0,0 +1,57 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_WAKE_UP_SLAP].additionalEffects->moveEffect == MOVE_EFFECT_REMOVE_STATUS); + ASSUME(gMovesInfo[MOVE_WAKE_UP_SLAP].argument == STATUS1_SLEEP); +} + +SINGLE_BATTLE_TEST("Wake-Up Slap does not cure paralyzed pokemons behind substitutes or get increased power") +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_INNER_FOCUS; } + PARAMETRIZE { ability = ABILITY_INFILTRATOR; } + GIVEN { + PLAYER(SPECIES_CROBAT) { Ability(ability); } + OPPONENT(SPECIES_SEISMITOAD); + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_SING); } + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_WAKE_UP_SLAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WAKE_UP_SLAP, player); + if (ability == ABILITY_INNER_FOCUS) { + MESSAGE("The SUBSTITUTE took damage for Foe Seismitoad!"); + NONE_OF + { + MESSAGE("Foe Seismitoad's SUBSTITUTE faded!"); // Smelling Salts does 86 damage, the sub has 122 HP, if hitting a sub it shouldn't get boosted damage. + MESSAGE("Foe Seismitoad woke up!"); + STATUS_ICON(opponent, none: TRUE); + } + } else { + MESSAGE("Foe Seismitoad woke up!"); + STATUS_ICON(opponent, none: TRUE); + } + } +} + +SINGLE_BATTLE_TEST("Wake-Up Slap get incread power vs. sleeping targets") +{ + u32 status1; + PARAMETRIZE { status1 = STATUS1_SLEEP; } + PARAMETRIZE { status1 = STATUS1_NONE; } + GIVEN { + PLAYER(SPECIES_CROBAT); + OPPONENT(SPECIES_LOTAD) { Status1(status1); } + } WHEN { + TURN { MOVE(player, MOVE_WAKE_UP_SLAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WAKE_UP_SLAP, player); + if (status1 == STATUS1_SLEEP) { + MESSAGE("Foe Lotad fainted!"); + } else { + NOT MESSAGE("Foe Lotad fainted!"); + MESSAGE("Foe Lotad used Celebrate!"); + } + } +}