diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 67d97fda02..cd52f9629b 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1751,6 +1751,16 @@ callnative BS_RemoveTerrain .endm + .macro tryspectralthiefsteal jumpInstr:req + callnative BS_TrySpectralThiefSteal + .4byte \jumpInstr + .endm + + .macro spectralthiefprintstats + callnative BS_SpectralThiefPrintStats + .endm + + @ various command changed to more readable macros .macro cancelmultiturnmoves battler:req various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES @@ -2045,10 +2055,6 @@ various \battler, VARIOUS_SET_POWDER .endm - .macro spectralthiefprintstats - various BS_ATTACKER, VARIOUS_SPECTRAL_THIEF - .endm - .macro bringdownairbornebattler battler:req various \battler, VARIOUS_GRAVITY_ON_AIRBORNE_MONS .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index fff1961a9c..e56cf1eeaf 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1296,7 +1296,23 @@ BattleScript_SpectralThiefSteal:: setbyte sB_ANIM_ARG2, 0 playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 spectralthiefprintstats - return + goto BattleScript_EffectSpectralThiefFromDamage + +BattleScript_EffectSpectralThief:: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + typecalc + tryspectralthiefsteal BattleScript_SpectralThiefSteal +BattleScript_EffectSpectralThiefFromDamage: + critcalc + damagecalc + adjustdamage + call BattleScript_Hit_RetFromAtkAnimation + tryfaintmon BS_TARGET + moveendall + end BattleScript_EffectPartingShot:: attackcanceler diff --git a/include/battle_scripts.h b/include/battle_scripts.h index fb830c275b..40352b88e4 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -340,7 +340,7 @@ extern const u8 BattleScript_PsychicSurgeActivates[]; extern const u8 BattleScript_GrassySurgeActivates[]; extern const u8 BattleScript_MistySurgeActivates[]; extern const u8 BattleScript_ElectricSurgeActivates[]; -extern const u8 BattleScript_SpectralThiefSteal[]; +extern const u8 BattleScript_EffectSpectralThief[]; extern const u8 BattleScript_StatUpMsg[]; extern const u8 BattleScript_AbilityRaisesDefenderStat[]; extern const u8 BattleScript_PowderMoveNoEffect[]; diff --git a/include/constants/battle.h b/include/constants/battle.h index 865f5ce886..37cdf440d4 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -388,36 +388,35 @@ #define MOVE_EFFECT_SMACK_DOWN 57 #define MOVE_EFFECT_FLAME_BURST 58 #define MOVE_EFFECT_FEINT 59 -#define MOVE_EFFECT_SPECTRAL_THIEF 60 -#define MOVE_EFFECT_V_CREATE 61 -#define MOVE_EFFECT_HAPPY_HOUR 62 -#define MOVE_EFFECT_CORE_ENFORCER 63 -#define MOVE_EFFECT_THROAT_CHOP 64 -#define MOVE_EFFECT_INCINERATE 65 -#define MOVE_EFFECT_BUG_BITE 66 -#define MOVE_EFFECT_RECOIL_HP_25 67 -#define MOVE_EFFECT_TRAP_BOTH 68 -#define MOVE_EFFECT_ROUND 69 -#define MOVE_EFFECT_STOCKPILE_WORE_OFF 70 -#define MOVE_EFFECT_DIRE_CLAW 71 -#define MOVE_EFFECT_STEALTH_ROCK 72 -#define MOVE_EFFECT_SPIKES 73 -#define MOVE_EFFECT_SYRUP_BOMB 74 -#define MOVE_EFFECT_FLORAL_HEALING 75 -#define MOVE_EFFECT_SECRET_POWER 76 -#define MOVE_EFFECT_PSYCHIC_NOISE 77 -#define MOVE_EFFECT_TERA_BLAST 78 -#define MOVE_EFFECT_ORDER_UP 79 -#define MOVE_EFFECT_ION_DELUGE 80 -#define MOVE_EFFECT_AROMATHERAPY 81 // No functionality yet -#define MOVE_EFFECT_HAZE 82 -#define MOVE_EFFECT_LEECH_SEED 83 -#define MOVE_EFFECT_REFLECT 84 -#define MOVE_EFFECT_LIGHT_SCREEN 85 -#define MOVE_EFFECT_SALT_CURE 86 -#define MOVE_EFFECT_EERIE_SPELL 87 +#define MOVE_EFFECT_V_CREATE 60 +#define MOVE_EFFECT_HAPPY_HOUR 61 +#define MOVE_EFFECT_CORE_ENFORCER 62 +#define MOVE_EFFECT_THROAT_CHOP 63 +#define MOVE_EFFECT_INCINERATE 64 +#define MOVE_EFFECT_BUG_BITE 65 +#define MOVE_EFFECT_RECOIL_HP_25 66 +#define MOVE_EFFECT_TRAP_BOTH 67 +#define MOVE_EFFECT_ROUND 68 +#define MOVE_EFFECT_STOCKPILE_WORE_OFF 69 +#define MOVE_EFFECT_DIRE_CLAW 70 +#define MOVE_EFFECT_STEALTH_ROCK 71 +#define MOVE_EFFECT_SPIKES 72 +#define MOVE_EFFECT_SYRUP_BOMB 73 +#define MOVE_EFFECT_FLORAL_HEALING 74 +#define MOVE_EFFECT_SECRET_POWER 75 +#define MOVE_EFFECT_PSYCHIC_NOISE 76 +#define MOVE_EFFECT_TERA_BLAST 77 +#define MOVE_EFFECT_ORDER_UP 78 +#define MOVE_EFFECT_ION_DELUGE 79 +#define MOVE_EFFECT_AROMATHERAPY 80 // No functionality yet +#define MOVE_EFFECT_HAZE 81 +#define MOVE_EFFECT_LEECH_SEED 82 +#define MOVE_EFFECT_REFLECT 83 +#define MOVE_EFFECT_LIGHT_SCREEN 84 +#define MOVE_EFFECT_SALT_CURE 85 +#define MOVE_EFFECT_EERIE_SPELL 86 -#define NUM_MOVE_EFFECTS 88 +#define NUM_MOVE_EFFECTS 87 #define MOVE_EFFECT_AFFECTS_USER 0x2000 #define MOVE_EFFECT_CERTAIN 0x4000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index b32b7a3837..b321f488b0 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -349,6 +349,7 @@ enum { EFFECT_SHELL_SIDE_ARM, EFFECT_ORDER_UP, EFFECT_RAPID_SPIN, + EFFECT_SPECTRAL_THIEF, NUM_BATTLE_MOVE_EFFECTS, }; diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index c8f6b7cd5b..5d5eb54e04 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -153,7 +153,6 @@ enum CmdVarious VARIOUS_TRY_THIRD_TYPE, VARIOUS_ACUPRESSURE, VARIOUS_SET_POWDER, - VARIOUS_SPECTRAL_THIEF, VARIOUS_GRAVITY_ON_AIRBORNE_MONS, VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS, VARIOUS_JUMP_IF_ROAR_FAILS, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index c3cd5a4d5e..d65a5eaeaf 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3814,7 +3814,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_FLATTER: if (HasMoveEffect(battlerAtk, EFFECT_FOUL_PLAY) || HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP) - || HasMoveWithAdditionalEffect(battlerAtk, MOVE_EFFECT_SPECTRAL_THIEF)) + || HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) ADJUST_SCORE(DECENT_EFFECT); if (aiData->abilities[battlerDef] == ABILITY_CONTRARY) ADJUST_SCORE(GOOD_EFFECT); @@ -4422,8 +4422,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED)) ADJUST_SCORE(GOOD_EFFECT); + case EFFECT_SPECTRAL_THIEF: + ADJUST_SCORE(AI_ShouldCopyStatChanges(battlerAtk, battlerDef)); break; - } // move effect checks // check move additional effects that are likely to happen @@ -4547,9 +4548,6 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case MOVE_EFFECT_CLEAR_SMOG: score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE); break; - case MOVE_EFFECT_SPECTRAL_THIEF: - score += AI_ShouldCopyStatChanges(battlerAtk, battlerDef); - break; case MOVE_EFFECT_BUG_BITE: // And pluck if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) break; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a07ac4579f..bd4451f7d7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3662,52 +3662,6 @@ void SetMoveEffect(bool32 primary, bool32 certain) gBattlescriptCurrInstr = BattleScript_MoveEffectFeint; } break; - case MOVE_EFFECT_SPECTRAL_THIEF: - if (!NoAliveMonsForEitherParty()) - { - bool32 contrary = (GetBattlerAbility(gBattlerAttacker) == ABILITY_CONTRARY); - gBattleStruct->stolenStats[0] = 0; // Stats to steal. - gBattleScripting.animArg1 = 0; - for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) - { - if (gBattleMons[gBattlerTarget].statStages[i] > DEFAULT_STAT_STAGE && gBattleMons[gBattlerAttacker].statStages[i] != MAX_STAT_STAGE) - { - bool32 byTwo = FALSE; - - gBattleStruct->stolenStats[0] |= (1 << (i)); - // Store by how many stages to raise the stat. - gBattleStruct->stolenStats[i] = gBattleMons[gBattlerTarget].statStages[i] - DEFAULT_STAT_STAGE; - while (gBattleMons[gBattlerAttacker].statStages[i] + gBattleStruct->stolenStats[i] > MAX_STAT_STAGE) - gBattleStruct->stolenStats[i]--; - gBattleMons[gBattlerTarget].statStages[i] = DEFAULT_STAT_STAGE; - - if (gBattleStruct->stolenStats[i] >= 2) - byTwo++; - - if (gBattleScripting.animArg1 == 0) - { - if (byTwo) - gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MINUS2 : STAT_ANIM_PLUS2) + i; - else - gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MINUS1 : STAT_ANIM_PLUS1) + i; - } - else - { - if (byTwo) - gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MULTIPLE_MINUS2 : STAT_ANIM_MULTIPLE_PLUS2); - else - gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MULTIPLE_MINUS1 : STAT_ANIM_MULTIPLE_PLUS1); - } - } - } - - if (gBattleStruct->stolenStats[0] != 0) - { - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_SpectralThiefSteal; - } - } - break; case MOVE_EFFECT_V_CREATE: if (!NoAliveMonsForEitherParty()) { @@ -9543,26 +9497,6 @@ static void Cmd_various(void) gStatuses3[battler] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR | STATUS3_SKY_DROPPED); break; } - case VARIOUS_SPECTRAL_THIEF: - { - VARIOUS_ARGS(); - // Raise stats - for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) - { - if (gBattleStruct->stolenStats[0] & (1u << i)) - { - gBattleStruct->stolenStats[0] &= ~(1u << i); - SET_STATCHANGER(i, gBattleStruct->stolenStats[i], FALSE); - if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), i, MOVE_EFFECT_CERTAIN | MOVE_EFFECT_AFFECTS_USER, NULL) == STAT_CHANGE_WORKED) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_StatUpMsg; - return; - } - } - } - break; - } case VARIOUS_SET_POWDER: { VARIOUS_ARGS(); @@ -17646,3 +17580,80 @@ void BS_RemoveTerrain(void) RemoveAllTerrains(); gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_TrySpectralThiefSteal(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + + if (gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + { + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + + bool32 contrary = GetBattlerAbility(gBattlerAttacker) == ABILITY_CONTRARY; + gBattleStruct->stolenStats[0] = 0; // Stats to steal. + gBattleScripting.animArg1 = 0; + for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) + { + if (gBattleMons[gBattlerTarget].statStages[stat] > DEFAULT_STAT_STAGE && gBattleMons[gBattlerAttacker].statStages[stat] != MAX_STAT_STAGE) + { + bool32 byTwo = FALSE; + + gBattleStruct->stolenStats[0] |= (1 << (stat)); + // Store by how many stages to raise the stat. + gBattleStruct->stolenStats[stat] = gBattleMons[gBattlerTarget].statStages[stat] - DEFAULT_STAT_STAGE; + + while (gBattleMons[gBattlerAttacker].statStages[stat] + gBattleStruct->stolenStats[stat] > MAX_STAT_STAGE) + gBattleStruct->stolenStats[stat]--; + + gBattleMons[gBattlerTarget].statStages[stat] = DEFAULT_STAT_STAGE; + + if (gBattleStruct->stolenStats[stat] >= 2) + byTwo++; + + if (gBattleScripting.animArg1 == 0) + { + if (byTwo) + gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MINUS2 : STAT_ANIM_PLUS2) + stat; + else + gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MINUS1 : STAT_ANIM_PLUS1) + stat; + } + else + { + if (byTwo) + gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MULTIPLE_MINUS2 : STAT_ANIM_MULTIPLE_PLUS2); + else + gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MULTIPLE_MINUS1 : STAT_ANIM_MULTIPLE_PLUS1); + } + } + } + + if (gBattleStruct->stolenStats[0] != 0) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SpectralThiefPrintStats(void) +{ + NATIVE_ARGS(); + + for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) + { + if (gBattleStruct->stolenStats[0] & (1u << stat)) + { + gBattleStruct->stolenStats[0] &= ~(1u << stat); + SET_STATCHANGER(stat, gBattleStruct->stolenStats[stat], FALSE); + if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), + stat, + MOVE_EFFECT_CERTAIN | MOVE_EFFECT_AFFECTS_USER, NULL) == STAT_CHANGE_WORKED) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StatUpMsg; + return; + } + } + } + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index 0b6a1dd72f..7d244b5ebf 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -2225,4 +2225,10 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, + + [EFFECT_SPECTRAL_THIEF] = + { + .battleScript = BattleScript_EffectSpectralThief, + .battleTvScore = 0, // TODO: Assign points + }, }; diff --git a/src/data/moves_info.h b/src/data/moves_info.h index a7c46bd1fc..31ac2afe4c 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -16562,7 +16562,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .description = COMPOUND_STRING( "Steals the target's stat\n" "boosts, then attacks."), - .effect = EFFECT_HIT, + .effect = EFFECT_SPECTRAL_THIEF, .power = 90, .type = TYPE_GHOST, .accuracy = 100, @@ -16573,9 +16573,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = .ignoresSubstitute = TRUE, .makesContact = TRUE, .metronomeBanned = TRUE, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_SPECTRAL_THIEF, - }), .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, diff --git a/test/battle/ability/big_pecks.c b/test/battle/ability/big_pecks.c index 0c61dd3ba3..e8449fdf1a 100644 --- a/test/battle/ability/big_pecks.c +++ b/test/battle/ability/big_pecks.c @@ -76,7 +76,7 @@ SINGLE_BATTLE_TEST("Big Pecks doesn't prevent Spectral Thief from resetting posi { GIVEN { ASSUME(gMovesInfo[MOVE_HARDEN].effect == EFFECT_DEFENSE_UP); - ASSUME(MoveHasAdditionalEffect(MOVE_SPECTRAL_THIEF, MOVE_EFFECT_SPECTRAL_THIEF)); + ASSUME(gMovesInfo[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); ASSUME(gMovesInfo[MOVE_SOAK].effect == EFFECT_SOAK); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_PIDGEY) { Ability(ABILITY_BIG_PECKS); } @@ -86,8 +86,8 @@ SINGLE_BATTLE_TEST("Big Pecks doesn't prevent Spectral Thief from resetting posi } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_HARDEN, opponent); MESSAGE("The opposing Pidgey's Defense rose!"); - ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, player); MESSAGE("Wobbuffet stole the target's boosted stats!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, player); } THEN { EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE); } diff --git a/test/battle/ability/clear_body.c b/test/battle/ability/clear_body.c index 1e955431a1..cb4b21aefe 100644 --- a/test/battle/ability/clear_body.c +++ b/test/battle/ability/clear_body.c @@ -377,7 +377,7 @@ SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent S PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; } GIVEN { - ASSUME(MoveHasAdditionalEffect(MOVE_SPECTRAL_THIEF, MOVE_EFFECT_SPECTRAL_THIEF) == TRUE); + ASSUME(gMovesInfo[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); ASSUME(gMovesInfo[MOVE_AGILITY].effect == EFFECT_SPEED_UP_2); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } OPPONENT(species) { Speed(5); Ability(ability); } diff --git a/test/battle/ability/hyper_cutter.c b/test/battle/ability/hyper_cutter.c index a688da2531..d63938b606 100644 --- a/test/battle/ability/hyper_cutter.c +++ b/test/battle/ability/hyper_cutter.c @@ -117,7 +117,7 @@ SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Spectral Thief from resetting p { GIVEN { ASSUME(gMovesInfo[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2); - ASSUME(MoveHasAdditionalEffect(MOVE_SPECTRAL_THIEF, MOVE_EFFECT_SPECTRAL_THIEF)); + ASSUME(gMovesInfo[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); } } WHEN { @@ -125,8 +125,8 @@ SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Spectral Thief from resetting p } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent); MESSAGE("The opposing Krabby's Attack sharply rose!"); - ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, player); MESSAGE("Wobbuffet stole the target's boosted stats!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, player); } THEN { EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); } diff --git a/test/battle/ability/keen_eye.c b/test/battle/ability/keen_eye.c index b047ec988f..d1dfad7ceb 100644 --- a/test/battle/ability/keen_eye.c +++ b/test/battle/ability/keen_eye.c @@ -174,7 +174,7 @@ SINGLE_BATTLE_TEST("Keen Eye & Gen9+ Illuminate don't prevent Spectral Thief fro GIVEN { ASSUME(gMovesInfo[MOVE_HONE_CLAWS].effect == EFFECT_ATTACK_ACCURACY_UP); - ASSUME(MoveHasAdditionalEffect(MOVE_SPECTRAL_THIEF, MOVE_EFFECT_SPECTRAL_THIEF) == TRUE); + ASSUME(gMovesInfo[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) { Ability(ability); } } WHEN { @@ -191,8 +191,8 @@ SINGLE_BATTLE_TEST("Keen Eye & Gen9+ Illuminate don't prevent Spectral Thief fro MESSAGE("The opposing Staryu's Attack rose!"); MESSAGE("The opposing Staryu's accuracy rose!"); } - ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, player); MESSAGE("Wobbuffet stole the target's boosted stats!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, player); } THEN { EXPECT_EQ(opponent->statStages[STAT_ACC], DEFAULT_STAT_STAGE); } diff --git a/test/battle/move_effect/spectral_thief.c b/test/battle/move_effect/spectral_thief.c new file mode 100644 index 0000000000..7bb5d5a536 --- /dev/null +++ b/test/battle/move_effect/spectral_thief.c @@ -0,0 +1,52 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Spectral Thief steals opponents boost before attacking", s16 damage) +{ + u32 move; + PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_SWORDS_DANCE; } + + GIVEN { + ASSUME(gMovesInfo[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2); + ASSUME(gMovesInfo[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); + PLAYER(SPECIES_REGIROCK); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (move == MOVE_CELEBRATE) + TURN { MOVE(player, move); MOVE(opponent, MOVE_SPECTRAL_THIEF); } + else + TURN { MOVE(player, move); MOVE(opponent, MOVE_SPECTRAL_THIEF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + MESSAGE("The opposing Wobbuffet used Spectral Thief!"); + if (move == MOVE_SWORDS_DANCE) + MESSAGE("The opposing Wobbuffet stole the target's boosted stats!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, opponent); + HP_BAR(player, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Spectral Thief can't steal opponent's boost if target is immune") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2); + ASSUME(gMovesInfo[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); + PLAYER(SPECIES_MEOWTH); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SWORDS_DANCE); MOVE(opponent, MOVE_SPECTRAL_THIEF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player); + MESSAGE("The opposing Wobbuffet used Spectral Thief!"); + NONE_OF { + MESSAGE("The opposing Wobbuffet stole the target's boosted stats!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, opponent); + } + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + } +}