Fix incorrect "last to move" check for Analytic, Snatch, and Magic Coat (#8536)
This commit is contained in:
parent
bc0bbc5490
commit
755bec128b
@ -238,6 +238,7 @@ void MarkBattlerForControllerExec(u32 battler);
|
||||
void MarkBattlerReceivedLinkData(u32 battler);
|
||||
const u8 *CancelMultiTurnMoves(u32 battler, enum SkyDropState skyDropState);
|
||||
bool32 WasUnableToUseMove(u32 battler);
|
||||
bool32 IsLastMonToMove(u32 battler);
|
||||
bool32 ShouldDefiantCompetitiveActivate(u32 battler, enum Ability ability);
|
||||
void PrepareStringBattle(enum StringID stringId, u32 battler);
|
||||
void ResetSentPokesToOpponentValue(void);
|
||||
|
||||
@ -9711,7 +9711,7 @@ static void Cmd_setprotectlike(void)
|
||||
|
||||
TryResetProtectUseCounter(gBattlerAttacker);
|
||||
|
||||
if (gCurrentTurnActionNumber == (gBattlersCount - 1))
|
||||
if (IsLastMonToMove(gBattlerAttacker))
|
||||
notLastTurn = FALSE;
|
||||
|
||||
if ((sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] >= RandomUniform(RNG_PROTECT_FAIL, 0, USHRT_MAX) && notLastTurn)
|
||||
@ -13136,7 +13136,7 @@ static void Cmd_trysetmagiccoat(void)
|
||||
{
|
||||
CMD_ARGS(const u8 *failInstr);
|
||||
|
||||
if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn
|
||||
if (IsLastMonToMove(gBattlerAttacker)) // fails if moving last
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
@ -13152,7 +13152,7 @@ static void Cmd_trysetsnatch(void)
|
||||
{
|
||||
CMD_ARGS(const u8 *failInstr);
|
||||
|
||||
if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn
|
||||
if (IsLastMonToMove(gBattlerAttacker)) // fails if moving last
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
|
||||
@ -1216,6 +1216,26 @@ bool32 WasUnableToUseMove(u32 battler)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Returns TRUE if no other battler after this one in turn order will use a move
|
||||
bool32 IsLastMonToMove(u32 battler)
|
||||
{
|
||||
u32 i;
|
||||
u32 battlerTurnOrderNum = GetBattlerTurnOrderNum(battler);
|
||||
|
||||
if (battlerTurnOrderNum >= gBattlersCount - 1)
|
||||
return TRUE;
|
||||
|
||||
for (i = battlerTurnOrderNum + 1; i < gBattlersCount; i++)
|
||||
{
|
||||
u32 otherBattler = gBattlerByTurnOrder[i];
|
||||
if (!IsBattlerAlive(otherBattler))
|
||||
continue;
|
||||
if (gActionsByTurnOrder[i] == B_ACTION_USE_MOVE)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 ShouldDefiantCompetitiveActivate(u32 battler, enum Ability ability)
|
||||
{
|
||||
u32 side = GetBattlerSide(battler);
|
||||
@ -7358,7 +7378,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(0.75));
|
||||
break;
|
||||
case ABILITY_ANALYTIC:
|
||||
if (GetBattlerTurnOrderNum(battlerAtk) == gBattlersCount - 1 && move != MOVE_FUTURE_SIGHT && move != MOVE_DOOM_DESIRE)
|
||||
if (IsLastMonToMove(battlerAtk) && move != MOVE_FUTURE_SIGHT && move != MOVE_DOOM_DESIRE)
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.3));
|
||||
break;
|
||||
case ABILITY_TOUGH_CLAWS:
|
||||
|
||||
@ -20,9 +20,59 @@ SINGLE_BATTLE_TEST("Analytic increases the power of moves by 30% if it's the las
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Analytic activates correctly with empty slot after fainting", s16 damage)
|
||||
{
|
||||
u32 speed;
|
||||
|
||||
PARAMETRIZE { speed = 50; }
|
||||
PARAMETRIZE { speed = 5; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_MAGNEMITE) { Ability(ABILITY_ANALYTIC); Speed(speed); }
|
||||
PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); }
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_CELEBRATE);
|
||||
MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft);
|
||||
}
|
||||
} SCENE {
|
||||
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Analytic does not activate when not moving last with empty slot", s16 damage)
|
||||
{
|
||||
u32 speed;
|
||||
|
||||
PARAMETRIZE { speed = 50; }
|
||||
PARAMETRIZE { speed = 15; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_MAGNEMITE) { Ability(ABILITY_ANALYTIC); Speed(speed); }
|
||||
PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); }
|
||||
TURN {
|
||||
MOVE(opponentLeft, MOVE_CELEBRATE);
|
||||
MOVE(opponentRight, MOVE_CELEBRATE);
|
||||
MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft);
|
||||
}
|
||||
} SCENE {
|
||||
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Analytic takes into account modifications to speeed an priority (Gen 5-8)"); //Eg. Paralysis, Power Weight, Stall
|
||||
TO_DO_BATTLE_TEST("Analytic does not take into account modifications to speeed an priority (Gen 8)"); //Eg. Paralysis, Power Weight, Stall
|
||||
TO_DO_BATTLE_TEST("Analytic takes into account the turn order of what fainted Pokémon would've moved");
|
||||
|
||||
// Triple Battles needed to test
|
||||
//TO_DO_BATTLE_TEST("If the Pokémon with Analytic is targeting a Pokémon in a flank position that chooses to switch with its ally in the middle, its move's power will always be normal when it attacks the Pokémon that is shifted into the flank position");
|
||||
|
||||
@ -33,6 +33,42 @@ SINGLE_BATTLE_TEST("Magic Coat prints the correct message when bouncing back a m
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Magic Coat fails if user moves last")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_MAGIC_COAT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_COAT, player);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Magic Coat fails when the only slower battler is a fainted ally")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); }
|
||||
TURN {
|
||||
MOVE(opponentLeft, MOVE_CELEBRATE);
|
||||
MOVE(opponentRight, MOVE_CELEBRATE);
|
||||
MOVE(playerLeft, MOVE_MAGIC_COAT);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
|
||||
MESSAGE("Wynaut fainted!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_COAT, playerLeft);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Magic Coat reflects hazards regardless of the user's position")
|
||||
{
|
||||
struct BattlePokemon *coatUser = NULL;
|
||||
|
||||
@ -356,6 +356,42 @@ SINGLE_BATTLE_TEST("Protect: Multi-hit moves don't hit a protected target and fa
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Protect fails if user moves last")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_PROTECT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, player);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Protect fails when the only slower battler is a fainted ally")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); }
|
||||
TURN {
|
||||
MOVE(opponentLeft, MOVE_CELEBRATE);
|
||||
MOVE(opponentRight, MOVE_CELEBRATE);
|
||||
MOVE(playerLeft, MOVE_PROTECT);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
|
||||
MESSAGE("Wynaut fainted!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, playerLeft);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Protect: Wide Guard protects self and ally from multi-target moves")
|
||||
{
|
||||
u16 move = MOVE_NONE;
|
||||
|
||||
@ -1,4 +1,64 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Snatch (Move Effect) test titles")
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_SNATCH) == EFFECT_SNATCH);
|
||||
ASSUME(MoveCanBeSnatched(MOVE_SWORDS_DANCE));
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Snatch steals stat-boosting moves from the opponent")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(5); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SNATCH); MOVE(opponent, MOVE_SWORDS_DANCE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNATCH, player);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Snatch fails if user moves last")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SNATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SNATCH, player);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Snatch fails when the only slower battler is a fainted ally")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
PLAYER(SPECIES_WYNAUT) { HP(1); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_SCRATCH, target: playerRight); }
|
||||
TURN {
|
||||
MOVE(opponentLeft, MOVE_CELEBRATE);
|
||||
MOVE(opponentRight, MOVE_CELEBRATE);
|
||||
MOVE(playerLeft, MOVE_SNATCH);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentLeft);
|
||||
MESSAGE("Wynaut fainted!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SNATCH, playerLeft);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Snatch does not steal moves that cannot be snatched");
|
||||
TO_DO_BATTLE_TEST("Snatch can steal healing moves");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user