Fixes Powder (status) interactions + tests (#5370)
* Simplified fix from #4638 * Fixes interactions with Z-Moves, Magic Guard, Heavy Rain, Pledge * Powder Tests * Remove duplicate * Assume Powder is a powder move * Add config for Powder Rain interaction * Only primal rain * Z-Moves fix handled in Canceller_Z_Moves * Fix BattleScript name * Make sure Z-Move + Powder still damages user
This commit is contained in:
parent
9633cefd11
commit
100c7dd8ad
9 changed files with 452 additions and 9 deletions
|
@ -9404,6 +9404,16 @@ BattleScript_ZMoveActivateStatus::
|
||||||
copybyte sSTATCHANGER, sSAVED_STAT_CHANGER
|
copybyte sSTATCHANGER, sSAVED_STAT_CHANGER
|
||||||
return
|
return
|
||||||
|
|
||||||
|
BattleScript_ZMoveActivatePowder::
|
||||||
|
flushtextbox
|
||||||
|
trytrainerslidezmovemsg
|
||||||
|
savetarget
|
||||||
|
printstring STRINGID_ZPOWERSURROUNDS
|
||||||
|
playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL
|
||||||
|
setzeffect
|
||||||
|
restoretarget
|
||||||
|
goto BattleScript_MoveUsedPowder
|
||||||
|
|
||||||
BattleScript_ZEffectPrintString::
|
BattleScript_ZEffectPrintString::
|
||||||
printfromtable gZEffectStringIds
|
printfromtable gZEffectStringIds
|
||||||
waitmessage B_WAIT_TIME_LONG
|
waitmessage B_WAIT_TIME_LONG
|
||||||
|
|
|
@ -329,6 +329,7 @@ extern const u8 BattleScript_ProteanActivates[];
|
||||||
extern const u8 BattleScript_DazzlingProtected[];
|
extern const u8 BattleScript_DazzlingProtected[];
|
||||||
extern const u8 BattleScript_MoveUsedPsychicTerrainPrevents[];
|
extern const u8 BattleScript_MoveUsedPsychicTerrainPrevents[];
|
||||||
extern const u8 BattleScript_MoveUsedPowder[];
|
extern const u8 BattleScript_MoveUsedPowder[];
|
||||||
|
extern const u8 BattleScript_ZMoveActivatePowder[];
|
||||||
extern const u8 BattleScript_SelectingNotAllowedStuffCheeks[];
|
extern const u8 BattleScript_SelectingNotAllowedStuffCheeks[];
|
||||||
extern const u8 BattleScript_SelectingNotAllowedStuffCheeksInPalace[];
|
extern const u8 BattleScript_SelectingNotAllowedStuffCheeksInPalace[];
|
||||||
extern const u8 BattleScript_SelectingNotAllowedBelch[];
|
extern const u8 BattleScript_SelectingNotAllowedBelch[];
|
||||||
|
|
|
@ -122,6 +122,7 @@
|
||||||
#define B_KNOCK_OFF_REMOVAL GEN_LATEST // In Gen5+, Knock Off removes the foe's item instead of rendering it unusable.
|
#define B_KNOCK_OFF_REMOVAL GEN_LATEST // In Gen5+, Knock Off removes the foe's item instead of rendering it unusable.
|
||||||
#define B_HEAL_BELL_SOUNDPROOF GEN_LATEST // In Gen5, Heal Bell affects all mons with Soundproof. In Gen6-8 it affects inactive mons, but not battlers. In Gen9 it always affects the user.
|
#define B_HEAL_BELL_SOUNDPROOF GEN_LATEST // In Gen5, Heal Bell affects all mons with Soundproof. In Gen6-8 it affects inactive mons, but not battlers. In Gen9 it always affects the user.
|
||||||
#define B_CHARGE GEN_LATEST // In Gen8-, Charge status is lost regardless of the typing of the next move.
|
#define B_CHARGE GEN_LATEST // In Gen8-, Charge status is lost regardless of the typing of the next move.
|
||||||
|
#define B_POWDER_RAIN GEN_LATEST // In Gen7+, Powder doesn't damage the user of a Fire type move in heavy rain.
|
||||||
|
|
||||||
// Ability settings
|
// Ability settings
|
||||||
#define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters.
|
#define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters.
|
||||||
|
|
|
@ -6291,19 +6291,20 @@ static void Cmd_moveend(void)
|
||||||
if (gMovesInfo[gCurrentMove].danceMove)
|
if (gMovesInfo[gCurrentMove].danceMove)
|
||||||
{
|
{
|
||||||
u32 battler, nextDancer = 0;
|
u32 battler, nextDancer = 0;
|
||||||
bool32 turnOnHitmarker = FALSE;
|
bool32 hasDancerTriggered = FALSE;
|
||||||
|
|
||||||
for (battler = 0; battler < gBattlersCount; battler++)
|
for (battler = 0; battler < gBattlersCount; battler++)
|
||||||
{
|
{
|
||||||
if (gSpecialStatuses[battler].dancerUsedMove)
|
if (gSpecialStatuses[battler].dancerUsedMove)
|
||||||
{
|
{
|
||||||
// in case a battler fails to act on a Dancer-called move
|
// in case a battler fails to act on a Dancer-called move
|
||||||
turnOnHitmarker = TRUE;
|
hasDancerTriggered = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)
|
if (!(gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)
|
||||||
|
|| (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE && !hasDancerTriggered)
|
||||||
|| (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove && gBattleStruct->bouncedMoveIsUsed)))
|
|| (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove && gBattleStruct->bouncedMoveIsUsed)))
|
||||||
{ // Dance move succeeds
|
{ // Dance move succeeds
|
||||||
// Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move
|
// Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move
|
||||||
|
@ -6317,8 +6318,6 @@ static void Cmd_moveend(void)
|
||||||
{
|
{
|
||||||
if (GetBattlerAbility(battler) == ABILITY_DANCER && !gSpecialStatuses[battler].dancerUsedMove)
|
if (GetBattlerAbility(battler) == ABILITY_DANCER && !gSpecialStatuses[battler].dancerUsedMove)
|
||||||
{
|
{
|
||||||
if (turnOnHitmarker)
|
|
||||||
gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED;
|
|
||||||
if (!nextDancer || (gBattleMons[battler].speed < gBattleMons[nextDancer & 0x3].speed))
|
if (!nextDancer || (gBattleMons[battler].speed < gBattleMons[nextDancer & 0x3].speed))
|
||||||
nextDancer = battler | 0x4;
|
nextDancer = battler | 0x4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3558,11 +3558,20 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||||
case CANCELLER_POWDER_STATUS:
|
case CANCELLER_POWDER_STATUS:
|
||||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER)
|
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER)
|
||||||
{
|
{
|
||||||
if (moveType == TYPE_FIRE)
|
u32 partnerMove = gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].moves[gBattleStruct->chosenMovePositions[BATTLE_PARTNER(gBattlerAttacker)]];
|
||||||
|
if ((moveType == TYPE_FIRE && !gBattleStruct->pledgeMove)
|
||||||
|
|| (gCurrentMove == MOVE_FIRE_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE)
|
||||||
|
|| (gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_FIRE_PLEDGE && gBattleStruct->pledgeMove))
|
||||||
{
|
{
|
||||||
gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE;
|
gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE;
|
||||||
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4;
|
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD
|
||||||
gBattlescriptCurrInstr = BattleScript_MoveUsedPowder;
|
&& (B_POWDER_RAIN < GEN_7 || !IsBattlerWeatherAffected(gBattlerAttacker, B_WEATHER_RAIN_PRIMAL)))
|
||||||
|
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4;
|
||||||
|
|
||||||
|
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE
|
||||||
|
|| gBattleStruct->obedienceResult != OBEYS
|
||||||
|
|| HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE))
|
||||||
|
gBattlescriptCurrInstr = BattleScript_MoveUsedPowder;
|
||||||
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
|
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
|
||||||
effect = 1;
|
effect = 1;
|
||||||
}
|
}
|
||||||
|
@ -3592,7 +3601,15 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||||
SetGimmickAsActivated(gBattlerAttacker, GIMMICK_Z_MOVE);
|
SetGimmickAsActivated(gBattlerAttacker, GIMMICK_Z_MOVE);
|
||||||
|
|
||||||
gBattleScripting.battler = gBattlerAttacker;
|
gBattleScripting.battler = gBattlerAttacker;
|
||||||
if (gMovesInfo[gCurrentMove].category == DAMAGE_CATEGORY_STATUS)
|
if (gProtectStructs[gBattlerAttacker].powderSelfDmg)
|
||||||
|
{
|
||||||
|
if (!alreadyUsed)
|
||||||
|
{
|
||||||
|
BattleScriptPushCursor();
|
||||||
|
gBattlescriptCurrInstr = BattleScript_ZMoveActivatePowder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (gMovesInfo[gCurrentMove].category == DAMAGE_CATEGORY_STATUS)
|
||||||
{
|
{
|
||||||
if (!alreadyUsed)
|
if (!alreadyUsed)
|
||||||
{
|
{
|
||||||
|
@ -6058,7 +6075,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||||
if (IsBattlerAlive(battler)
|
if (IsBattlerAlive(battler)
|
||||||
&& (gMovesInfo[gCurrentMove].danceMove)
|
&& (gMovesInfo[gCurrentMove].danceMove)
|
||||||
&& !gSpecialStatuses[battler].dancerUsedMove
|
&& !gSpecialStatuses[battler].dancerUsedMove
|
||||||
&& (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED)
|
|
||||||
&& gBattlerAttacker != battler)
|
&& gBattlerAttacker != battler)
|
||||||
{
|
{
|
||||||
// Set bit and save Dancer mon's original target
|
// Set bit and save Dancer mon's original target
|
||||||
|
|
|
@ -145,3 +145,25 @@ SINGLE_BATTLE_TEST("Dancer-called attacks have their type updated")
|
||||||
MESSAGE("It's super effective!");
|
MESSAGE("It's super effective!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Dancer doesn't call a move that didn't execute due to Powder")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_FIERY_DANCE].danceMove == TRUE);
|
||||||
|
ASSUME(gMovesInfo[MOVE_FIERY_DANCE].type == TYPE_FIRE);
|
||||||
|
PLAYER(SPECIES_VOLCARONA);
|
||||||
|
PLAYER(SPECIES_ORICORIO);
|
||||||
|
OPPONENT(SPECIES_WYNAUT);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentRight, MOVE_POWDER, target: playerLeft); MOVE(playerLeft, MOVE_FIERY_DANCE, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentRight);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIERY_DANCE, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
ABILITY_POPUP(playerRight, ABILITY_DANCER);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIERY_DANCE, playerRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -397,6 +397,60 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Z-Sleep Talk turns Weather Ball into Breakneck Blit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("(Z-MOVE) Powder blocks Fire type Z-Moves and deals 25% of maximum HP to the user")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_EMBER].type == TYPE_FIRE);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_FIRIUM_Z); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER, gimmick: GIMMICK_Z_MOVE); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ZMOVE_ACTIVATE, player);
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_INFERNO_OVERDRIVE, player);
|
||||||
|
} THEN {
|
||||||
|
EXPECT_MUL_EQ(player->maxHP, UQ_4_12(0.75), player->hp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("(Z-MOVE) Powder blocks Fire type Z-Moves (from Z-Mirror Move)")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_EMBER].type == TYPE_FIRE);
|
||||||
|
ASSUME(gMovesInfo[MOVE_MIRROR_MOVE].type == TYPE_FLYING);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_FLYINIUM_Z); }
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentRight, MOVE_POWDER, target: playerLeft); MOVE(opponentLeft, MOVE_EMBER, target: playerLeft); MOVE(playerLeft, MOVE_MIRROR_MOVE, gimmick: GIMMICK_Z_MOVE); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponentLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ZMOVE_ACTIVATE, playerLeft);
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_INFERNO_OVERDRIVE, playerLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("(Z-MOVE) Powder blocks Fire type Z-Moves but not boosts granted")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_WILL_O_WISP].type == TYPE_FIRE);
|
||||||
|
ASSUME(gMovesInfo[MOVE_WILL_O_WISP].zMove.effect == Z_EFFECT_ATK_UP_1);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_FIRIUM_Z); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_WILL_O_WISP, gimmick: GIMMICK_Z_MOVE); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ZMOVE_ACTIVATE, player);
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WILL_O_WISP, player);
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Miscellaneous Interactions
|
// Miscellaneous Interactions
|
||||||
DOUBLE_BATTLE_TEST("(Z-MOVE) Instruct fails if the target last used a Z-Move")
|
DOUBLE_BATTLE_TEST("(Z-MOVE) Instruct fails if the target last used a Z-Move")
|
||||||
{
|
{
|
||||||
|
|
|
@ -331,6 +331,51 @@ DOUBLE_BATTLE_TEST("Damage calculation: Combined pledge move")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Pledge move combo interactions with Powder are correct")
|
||||||
|
{
|
||||||
|
// Fire Pledge as the first move or Fire Pledge combo should fail
|
||||||
|
u32 moveLeft, moveRight, speedLeft, speedRight;
|
||||||
|
PARAMETRIZE { moveLeft = MOVE_FIRE_PLEDGE; moveRight = MOVE_WATER_PLEDGE; speedLeft = 4; speedRight = 3; } // FAIL 1
|
||||||
|
PARAMETRIZE { moveLeft = MOVE_FIRE_PLEDGE; moveRight = MOVE_WATER_PLEDGE; speedLeft = 3; speedRight = 4; }
|
||||||
|
PARAMETRIZE { moveLeft = MOVE_WATER_PLEDGE; moveRight = MOVE_FIRE_PLEDGE; speedLeft = 4; speedRight = 3; }
|
||||||
|
PARAMETRIZE { moveLeft = MOVE_WATER_PLEDGE; moveRight = MOVE_FIRE_PLEDGE; speedLeft = 3; speedRight = 4; }
|
||||||
|
PARAMETRIZE { moveLeft = MOVE_FIRE_PLEDGE; moveRight = MOVE_GRASS_PLEDGE; speedLeft = 4; speedRight = 3; } // FAIL 1
|
||||||
|
PARAMETRIZE { moveLeft = MOVE_FIRE_PLEDGE; moveRight = MOVE_GRASS_PLEDGE; speedLeft = 3; speedRight = 4; } // FAIL 2
|
||||||
|
PARAMETRIZE { moveLeft = MOVE_GRASS_PLEDGE; moveRight = MOVE_FIRE_PLEDGE; speedLeft = 4; speedRight = 3; }
|
||||||
|
PARAMETRIZE { moveLeft = MOVE_GRASS_PLEDGE; moveRight = MOVE_FIRE_PLEDGE; speedLeft = 3; speedRight = 4; } // FAIL 2
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_FIRE_PLEDGE].type == TYPE_FIRE);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Speed(speedLeft); }
|
||||||
|
PLAYER(SPECIES_WYNAUT) { Speed(speedRight); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Speed(8); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON) { Speed(5); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentRight, MOVE_POWDER, target: playerLeft); MOVE(playerLeft, moveLeft, target: opponentLeft); MOVE(playerRight, moveRight, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentRight);
|
||||||
|
if (speedLeft > speedRight && moveLeft == MOVE_FIRE_PLEDGE) { // FAIL 1
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, moveLeft, playerLeft);
|
||||||
|
HP_BAR(playerLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, moveRight, playerRight);
|
||||||
|
}
|
||||||
|
else if (speedLeft > speedRight) {
|
||||||
|
NOT HP_BAR(playerLeft);
|
||||||
|
if (moveLeft == MOVE_GRASS_PLEDGE)
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_PLEDGE, playerRight);
|
||||||
|
else
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_PLEDGE, playerRight);
|
||||||
|
}
|
||||||
|
else if (moveLeft == MOVE_WATER_PLEDGE || moveRight == MOVE_WATER_PLEDGE) {
|
||||||
|
NOT HP_BAR(playerLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_PLEDGE, playerLeft);
|
||||||
|
}
|
||||||
|
else { // FAIL 2
|
||||||
|
HP_BAR(playerLeft);
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_PLEDGE, playerLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DOUBLE_BATTLE_TEST("Pledge move combo fails if ally fails to act - Sleep Right")
|
DOUBLE_BATTLE_TEST("Pledge move combo fails if ally fails to act - Sleep Right")
|
||||||
{
|
{
|
||||||
u32 speedPLeft, speedPRight, speedOLeft, speedORight;
|
u32 speedPLeft, speedPRight, speedOLeft, speedORight;
|
||||||
|
|
295
test/battle/move_effect/powder.c
Normal file
295
test/battle/move_effect/powder.c
Normal file
|
@ -0,0 +1,295 @@
|
||||||
|
#include "global.h"
|
||||||
|
#include "test/battle.h"
|
||||||
|
|
||||||
|
ASSUMPTIONS
|
||||||
|
{
|
||||||
|
ASSUME(gMovesInfo[MOVE_POWDER].effect == EFFECT_POWDER);
|
||||||
|
ASSUME(gMovesInfo[MOVE_POWDER].powderMove == TRUE);
|
||||||
|
ASSUME(gMovesInfo[MOVE_EMBER].type == TYPE_FIRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder blocks the target's Fire type moves and deals 25% of maximum HP to target")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
} THEN {
|
||||||
|
EXPECT_MUL_EQ(player->maxHP, UQ_4_12(0.75), player->hp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder blocks the target's Fire type moves and consumes PP")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_EMBER); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(player->pp[0], gMovesInfo[MOVE_EMBER].pp - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder only blocks the target's Fire type moves on the same turn")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); }
|
||||||
|
TURN { MOVE(player, MOVE_EMBER); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(player->maxHP, player->hp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder doesn't damage target if it has Magic Guard")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_ALAKAZAM) { Ability(ABILITY_MAGIC_GUARD); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(player->maxHP, player->hp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder doesn't damage target under heavy rain")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(B_POWDER_RAIN >= GEN_7);
|
||||||
|
PLAYER(SPECIES_KYOGRE_PRIMAL) { Ability(ABILITY_PRIMORDIAL_SEA); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(player->maxHP, player->hp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Powder blocks the target's Fire type moves even if it doesn't target Powder user")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WYNAUT);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentRight, MOVE_POWDER, target: playerLeft); MOVE(playerLeft, MOVE_EMBER, target: opponentLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentRight);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Powder fails if target is already affected by Powder")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentRight, MOVE_POWDER, target: playerLeft); MOVE(opponentLeft, MOVE_POWDER, target: playerLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentRight);
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder fails if the target is Grass type")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gSpeciesInfo[SPECIES_VENUSAUR].types[0] == TYPE_GRASS || gSpeciesInfo[SPECIES_VENUSAUR].types[1] == TYPE_GRASS);
|
||||||
|
PLAYER(SPECIES_VENUSAUR);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); }
|
||||||
|
} SCENE {
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder fails if the target has Overcoat")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_FORRETRESS) { Ability(ABILITY_OVERCOAT); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); }
|
||||||
|
} SCENE {
|
||||||
|
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Powder still blocks the target's Fire type moves even if it was given Grass type")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].effect == EFFECT_THIRD_TYPE);
|
||||||
|
ASSUME(gMovesInfo[MOVE_FORESTS_CURSE].argument == TYPE_GRASS);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_TREVENANT);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentRight, MOVE_POWDER, target: playerLeft); MOVE(opponentLeft, MOVE_FORESTS_CURSE, target: playerLeft); MOVE(playerLeft, MOVE_EMBER, target: opponentRight); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_FORESTS_CURSE, opponentLeft);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Powder still blocks the target's Fire type moves even if it was given Overcoat")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_DOODLE].effect == EFFECT_DOODLE);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_FORRETRESS) { Ability(ABILITY_OVERCOAT); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentRight, MOVE_POWDER, target: playerLeft); MOVE(playerRight, MOVE_DOODLE, target: opponentLeft); MOVE(playerLeft, MOVE_EMBER, target: opponentRight); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DOODLE, playerRight);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
}
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(playerLeft->ability, ABILITY_OVERCOAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder prevents Protean from changing its user to Fire type")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_GRENINJA) { Ability(ABILITY_PROTEAN); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
NONE_OF {
|
||||||
|
ABILITY_POPUP(player, ABILITY_PROTEAN);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder doesn't prevent a Fire move from thawing its user out")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_FLAME_WHEEL].thawsUser);
|
||||||
|
ASSUME(gMovesInfo[MOVE_FLAME_WHEEL].type == TYPE_FIRE);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_FLAME_WHEEL); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
MESSAGE("Wobbuffet was defrosted by Flame Wheel!");
|
||||||
|
STATUS_ICON(player, none: TRUE);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLAME_WHEEL, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Powder doesn't consume Berry from Fire type Natural Gift but prevents using the move")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_NATURAL_GIFT].effect == EFFECT_NATURAL_GIFT);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_CHERI_BERRY); }
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_NATURAL_GIFT); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
}
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(player->item, ITEM_CHERI_BERRY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Powder damages a target using Shell Trap even if it wasn't hit by a Physical move")
|
||||||
|
{
|
||||||
|
u32 move;
|
||||||
|
PARAMETRIZE { move = MOVE_TACKLE; }
|
||||||
|
PARAMETRIZE { move = MOVE_EMBER; }
|
||||||
|
PARAMETRIZE { move = MOVE_TICKLE;}
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gMovesInfo[MOVE_SHELL_TRAP].effect == EFFECT_SHELL_TRAP);
|
||||||
|
ASSUME(gMovesInfo[MOVE_SHELL_TRAP].type == TYPE_FIRE);
|
||||||
|
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
|
||||||
|
ASSUME(gMovesInfo[MOVE_EMBER].category == DAMAGE_CATEGORY_SPECIAL);
|
||||||
|
ASSUME(gMovesInfo[MOVE_TICKLE].category == DAMAGE_CATEGORY_STATUS);
|
||||||
|
ASSUME(gMovesInfo[MOVE_TICKLE].effect == EFFECT_TICKLE);
|
||||||
|
PLAYER(SPECIES_TURTONATOR);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WYNAUT);
|
||||||
|
OPPONENT(SPECIES_VIVILLON);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(playerLeft, MOVE_SHELL_TRAP); MOVE(opponentRight, MOVE_POWDER, target: playerLeft); MOVE(opponentLeft, move, target: playerLeft); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SHELL_TRAP_SETUP, playerLeft);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponentRight);
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, opponentLeft);
|
||||||
|
if (move != MOVE_TICKLE)
|
||||||
|
HP_BAR(playerLeft);
|
||||||
|
NONE_OF {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, playerLeft);
|
||||||
|
HP_BAR(opponentLeft);
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
}
|
||||||
|
HP_BAR(playerLeft);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue