Merge branch '_RHH/master' into _RHH/upcoming

# Conflicts:
#	src/battle_script_commands.c
This commit is contained in:
Eduardo Quezada 2024-05-13 11:00:12 -04:00
commit 3219a48adf
42 changed files with 851 additions and 223 deletions

View file

@ -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

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 792 B

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 781 B

After

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 B

View file

@ -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[];

View file

@ -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,

View file

@ -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,

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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))

View file

@ -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;

View file

@ -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;

View file

@ -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
},

View file

@ -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");

View file

@ -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,

View file

@ -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,

View file

@ -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);
}
}
}

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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); }

View file

@ -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");
}
}

View file

@ -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!");
}
}
}

View file

@ -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!");
}
}

View file

@ -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!");
}
}

View file

@ -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!");
}
}

View file

@ -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!");
}
}
}

View file

@ -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.");
}
}

View file

@ -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…");
}
}
}

View file

@ -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!");
}
}
}