Adds move Spicy Extract (#4211)
* Adds move Spicy Extract * remove uneeded line * anim, new tests, acc change * Clear Amulet, Contrary interaction * ai * correction * simplify script a bit * clean up * Spicy Extract script overhaul * merge rhh/upcoming * alignment * AI changes/additions * add Foul Play check * Remove useless ai checks * remove wrong test * review issues
This commit is contained in:
parent
7d84cd62ef
commit
faf61e62fb
12 changed files with 367 additions and 9 deletions
|
@ -17848,10 +17848,54 @@ ElectroShotUnleash:
|
|||
blendoff
|
||||
end
|
||||
|
||||
Move_SPICY_EXTRACT::
|
||||
loadspritegfx ANIM_TAG_SMALL_EMBER
|
||||
loadspritegfx ANIM_TAG_POISON_BUBBLE
|
||||
loadspritegfx ANIM_TAG_SMALL_BUBBLES
|
||||
createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_POISON_BUBBLE, 0, 12, 12, 0x061D @Orange
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
call SludgeBombProjectile
|
||||
createvisualtask AnimTask_ShakeMon2, 5, ANIM_TARGET, 3, 0, 15, 1
|
||||
createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_TARGET, 3, 0, 9, RGB_RED
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 42, 27, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -27, 44, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 39, -28, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -42, -42, 20
|
||||
playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_TARGET
|
||||
delay 5
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 0, 40, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -8, -44, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -46, -28, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 46, 9, 20
|
||||
playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_TARGET
|
||||
delay 5
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 42, 0, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -43, -12, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 16, -46, 20
|
||||
createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -16, 44, 20
|
||||
playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_TARGET
|
||||
call LetsSnuggleForeverTears
|
||||
delay 0x8
|
||||
call LetsSnuggleForeverTears
|
||||
delay 0x8
|
||||
call LetsSnuggleForeverTears
|
||||
waitsound
|
||||
waitforvisualfinish
|
||||
createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_TARGET, 3, 9, 0, RGB_RED
|
||||
waitforvisualfinish
|
||||
end
|
||||
|
||||
Move_TERA_BLAST::
|
||||
Move_AXE_KICK::
|
||||
Move_ORDER_UP::
|
||||
Move_SPICY_EXTRACT::
|
||||
Move_SPIN_OUT::
|
||||
Move_POPULATION_BOMB::
|
||||
Move_GLAIVE_RUSH::
|
||||
|
|
|
@ -52,6 +52,43 @@ BattleScript_LowerAtkSpAtkTrySpAtk::
|
|||
BattleScript_LowerAtkSpAtkEnd:
|
||||
return
|
||||
|
||||
BattleScript_EffectSpicyExtract::
|
||||
attackcanceler
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE BattleScript_SpicyExtract_CheckShouldSkipAttackAnim
|
||||
jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_SpicyExtract_CheckShouldSkipAttackAnim
|
||||
goto BattleScript_ButItFailed
|
||||
BattleScript_SpicyExtract_CheckShouldSkipAttackAnim:
|
||||
jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0, BattleScript_SpicyExtract_RaiseAtk
|
||||
attackstring
|
||||
ppreduce
|
||||
bicword gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT
|
||||
goto BattleScript_SpicyExtract_SkipAttackAnim
|
||||
BattleScript_SpicyExtract_RaiseAtk:
|
||||
attackstring
|
||||
ppreduce
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_SpicyExtract_SkipAttackAnim:
|
||||
setbyte sSTAT_ANIM_PLAYED, FALSE
|
||||
playstatchangeanimation BS_TARGET, BIT_ATK, STAT_CHANGE_BY_TWO
|
||||
setstatchanger STAT_ATK, 2, FALSE
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_EffectSpicyExtractDefenseDown
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectSpicyExtractDefenseDown
|
||||
printfromtable gStatUpStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_EffectSpicyExtractDefenseDown:
|
||||
setbyte sSTAT_ANIM_PLAYED, FALSE
|
||||
playstatchangeanimation BS_TARGET, BIT_DEF, STAT_CHANGE_NEGATIVE | STAT_CHANGE_BY_TWO
|
||||
setstatchanger STAT_DEF, 2, TRUE
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_EffectSpicyExtract_End
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_EffectSpicyExtract_End
|
||||
printfromtable gStatDownStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_EffectSpicyExtract_End:
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectTidyUp::
|
||||
attackcanceler
|
||||
attackstring
|
||||
|
@ -3132,6 +3169,7 @@ BattleScript_EffectStatDown:
|
|||
BattleScript_StatDownFromAttackString:
|
||||
attackstring
|
||||
ppreduce
|
||||
BattleScript_EffectStatDownFromStatBuffChange:
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_StatDownEnd
|
||||
jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_StatDownDoAnim
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StatDownEnd
|
||||
|
@ -3142,6 +3180,7 @@ BattleScript_StatDownDoAnim::
|
|||
waitanimation
|
||||
setgraphicalstatchangevalues
|
||||
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
|
||||
bicword gHitMarker, HITMARKER_DISABLE_ANIMATION
|
||||
BattleScript_StatDownPrintString::
|
||||
printfromtable gStatDownStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
|
|
|
@ -193,5 +193,6 @@ s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle);
|
|||
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
|
||||
bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData);
|
||||
void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
|
||||
bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData);
|
||||
|
||||
#endif //GUARD_BATTLE_AI_UTIL_H
|
||||
|
|
|
@ -179,6 +179,7 @@ extern const u8 BattleScript_FlashFireBoost_PPLoss[];
|
|||
extern const u8 BattleScript_FlashFireBoost[];
|
||||
extern const u8 BattleScript_AbilityNoStatLoss[];
|
||||
extern const u8 BattleScript_ItemNoStatLoss[];
|
||||
extern const u8 BattleScript_ItemNoStatLossSpicyExtract[];
|
||||
extern const u8 BattleScript_BRNPrevention[];
|
||||
extern const u8 BattleScript_PRLZPrevention[];
|
||||
extern const u8 BattleScript_PSNPrevention[];
|
||||
|
@ -836,5 +837,6 @@ extern const u8 BattleScript_EffectFilletAway[];
|
|||
extern const u8 BattleScript_EffectShedTail[];
|
||||
extern const u8 BattleScript_EffectUpperHand[];
|
||||
extern const u8 BattleScript_EffectTidyUp[];
|
||||
extern const u8 BattleScript_EffectSpicyExtract[];
|
||||
|
||||
#endif // GUARD_BATTLE_SCRIPTS_H
|
||||
|
|
|
@ -350,6 +350,7 @@ enum {
|
|||
EFFECT_DRAGON_CHEER,
|
||||
EFFECT_LAST_RESPECTS,
|
||||
EFFECT_TIDY_UP,
|
||||
EFFECT_SPICY_EXTRACT,
|
||||
EFFECT_TERA_BLAST,
|
||||
EFFECT_TERA_STARSTORM,
|
||||
NUM_BATTLE_MOVE_EFFECTS,
|
||||
|
|
|
@ -439,7 +439,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3
|
|||
weather = AI_GetWeather(aiData);
|
||||
|
||||
SetBattlerData(battlerAtk);
|
||||
|
||||
|
||||
// Simulate dmg for both ai controlled mons and for player controlled mons.
|
||||
for (battlerDef = 0; battlerDef < battlersCount; battlerDef++)
|
||||
{
|
||||
|
@ -1367,9 +1367,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
break;
|
||||
case EFFECT_EVASION_DOWN:
|
||||
case EFFECT_EVASION_DOWN_2:
|
||||
if (!ShouldLowerStat(battlerDef, aiData->abilities[battlerDef], STAT_EVASION))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_TICKLE:
|
||||
if (!ShouldLowerStat(battlerDef, aiData->abilities[battlerDef], STAT_ATK))
|
||||
ADJUST_SCORE(-10);
|
||||
|
@ -2639,6 +2636,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
&& !BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPDEF))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_SPICY_EXTRACT:
|
||||
if (battlerAtk != BATTLE_PARTNER(battlerDef)
|
||||
&& (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)
|
||||
|| aiData->abilities[battlerDef] == ABILITY_CLEAR_BODY
|
||||
|| aiData->abilities[battlerDef] == ABILITY_GOOD_AS_GOLD
|
||||
|| aiData->holdEffects[battlerDef] == HOLD_EFFECT_CLEAR_AMULET))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_UPPER_HAND:
|
||||
if (predictedMove == MOVE_NONE || IS_MOVE_STATUS(predictedMove) || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER || GetMovePriority(battlerDef, move) < 1 || GetMovePriority(battlerDef, move) > 3) // Opponent going first or not using priority move
|
||||
ADJUST_SCORE(-10);
|
||||
|
@ -2769,6 +2774,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
|| gMovesInfo[aiData->partnerMove].criticalHitStage > 0
|
||||
|| HasMoveWithCriticalHitChance(battlerAtkPartner))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
} // our effect relative to partner
|
||||
|
||||
// consider global move effects
|
||||
|
@ -2922,6 +2928,12 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
{
|
||||
switch (effect)
|
||||
{
|
||||
case EFFECT_SPICY_EXTRACT:
|
||||
if (AI_ShouldSpicyExtract(battlerAtk, battlerAtkPartner, move, aiData))
|
||||
{
|
||||
RETURN_SCORE_PLUS(GOOD_EFFECT);
|
||||
}
|
||||
break;
|
||||
case EFFECT_PURIFY:
|
||||
if (gBattleMons[battlerAtkPartner].status1 & STATUS1_ANY)
|
||||
{
|
||||
|
@ -3383,6 +3395,9 @@ 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_SPICY_EXTRACT:
|
||||
// TODO: Make IncreaseStatDownScore function, just like IncreaseStatUpScore
|
||||
break;
|
||||
case EFFECT_BIDE:
|
||||
if (aiData->hpPercents[battlerAtk] < 90)
|
||||
ADJUST_SCORE(-2); // Should be either removed or turned into increasing score
|
||||
|
@ -3404,7 +3419,7 @@ 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)
|
||||
if ((gMovesInfo[move].soundMove && aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF)
|
||||
|| aiData->abilities[battlerDef] == ABILITY_SUCTION_CUPS)
|
||||
break;
|
||||
else if (IsDynamaxed(battlerDef))
|
||||
|
|
|
@ -3819,3 +3819,42 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
|
|||
if (gStatuses3[battlerDef] & STATUS3_LEECHSEED)
|
||||
ADJUST_SCORE_PTR(-2);
|
||||
}
|
||||
|
||||
bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData)
|
||||
{
|
||||
u32 preventsStatLoss;
|
||||
u32 partnerAbility;
|
||||
u32 partnerHoldEffect = aiData->holdEffects[battlerAtkPartner];
|
||||
|
||||
if (DoesBattlerIgnoreAbilityChecks(aiData->abilities[battlerAtk], move))
|
||||
partnerAbility = ABILITY_NONE;
|
||||
else
|
||||
partnerAbility = aiData->abilities[battlerAtkPartner];
|
||||
|
||||
if (gBattleMons[battlerAtkPartner].statStages[STAT_ATK] == MAX_STAT_STAGE
|
||||
|| partnerAbility == ABILITY_CONTRARY
|
||||
|| partnerAbility == ABILITY_GOOD_AS_GOLD
|
||||
|| HasMoveEffect(BATTLE_OPPOSITE(battlerAtk), EFFECT_FOUL_PLAY)
|
||||
|| HasMoveEffect(BATTLE_OPPOSITE(battlerAtkPartner), EFFECT_FOUL_PLAY))
|
||||
return FALSE;
|
||||
|
||||
preventsStatLoss = (partnerAbility == ABILITY_CLEAR_BODY
|
||||
|| partnerAbility == ABILITY_FULL_METAL_BODY
|
||||
|| partnerAbility == ABILITY_WHITE_SMOKE
|
||||
|| partnerHoldEffect == HOLD_EFFECT_CLEAR_AMULET);
|
||||
|
||||
switch (gMovesInfo[aiData->partnerMove].effect)
|
||||
{
|
||||
case EFFECT_DEFENSE_UP:
|
||||
case EFFECT_DEFENSE_UP_2:
|
||||
case EFFECT_DEFENSE_UP_3:
|
||||
case EFFECT_BULK_UP:
|
||||
case EFFECT_STOCKPILE:
|
||||
if (!preventsStatLoss)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (preventsStatLoss
|
||||
&& AI_STRIKES_FIRST(battlerAtk, battlerAtkPartner, TRUE)
|
||||
&& HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL));
|
||||
}
|
||||
|
|
|
@ -11647,17 +11647,18 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
|||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattleScripting.battler = battler;
|
||||
if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET)
|
||||
{
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattlescriptCurrInstr = BattleScript_ItemNoStatLoss;
|
||||
RecordItemEffectBattle(battler, HOLD_EFFECT_CLEAR_AMULET);
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlerAbility = battler;
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss;
|
||||
gLastUsedAbility = battlerAbility;
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
|
|
|
@ -2231,6 +2231,13 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
|||
.encourageEncore = TRUE,
|
||||
},
|
||||
|
||||
[EFFECT_SPICY_EXTRACT] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectSpicyExtract,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
.encourageEncore = TRUE,
|
||||
},
|
||||
|
||||
[EFFECT_TERA_BLAST] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectPhotonGeyser,
|
||||
|
|
|
@ -18577,7 +18577,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
|||
.description = COMPOUND_STRING(
|
||||
"Sharply ups target's Attack,\n"
|
||||
"harshly lowers its Defense."),
|
||||
.effect = EFFECT_PLACEHOLDER, // EFFECT_SPICY_EXTRACT
|
||||
.effect = EFFECT_SPICY_EXTRACT,
|
||||
.power = 0,
|
||||
.type = TYPE_GRASS,
|
||||
.accuracy = 0,
|
||||
|
|
|
@ -5689,4 +5689,4 @@ const struct SpeciesInfo gSpeciesInfoGen4[] =
|
|||
|
||||
#ifdef __INTELLISENSE__
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
|
209
test/battle/move_effect/spicy_extract.c
Normal file
209
test/battle/move_effect/spicy_extract.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gMovesInfo[MOVE_SPICY_EXTRACT].effect == EFFECT_SPICY_EXTRACT);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Spicy Extract raises target's Attack by 2 stages and lowers target's Defense by 2 stages")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SPICY_EXTRACT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPICY_EXTRACT, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Wobbuffet's Attack sharply rose!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Wobbuffet's Defense harshly fell!");
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
|
||||
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 2);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Spicy Extract is prevented by target's ability if it's Attack stat is maxed out")
|
||||
{
|
||||
u16 ability;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE { ability = ABILITY_LIGHT_METAL; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_BELDUM) { Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SWORDS_DANCE); }
|
||||
TURN { MOVE(opponent, MOVE_SWORDS_DANCE); }
|
||||
TURN { MOVE(opponent, MOVE_SWORDS_DANCE); MOVE(player, MOVE_SPICY_EXTRACT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Wobbuffet used Spicy Extract!");
|
||||
if (ability == ABILITY_CLEAR_BODY) {
|
||||
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
MESSAGE("Foe Beldum's Clear Body prevents stat loss!");
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPICY_EXTRACT, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
}
|
||||
} else {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPICY_EXTRACT, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Spicy Extract Defense loss is prevented by Big Pecks")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_PIDGEY) { Ability(ABILITY_BIG_PECKS); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SPICY_EXTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Spicy Extract!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPICY_EXTRACT, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Pidgey's Attack sharply rose!");
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Wobbuffet's Defense harshly fell!");
|
||||
}
|
||||
ABILITY_POPUP(opponent, ABILITY_BIG_PECKS);
|
||||
MESSAGE("Foe Pidgey's Big Pecks prevents Defense loss!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Spicy Extract bypasses accuracy checks")
|
||||
{
|
||||
PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHTPOWDER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SPICY_EXTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Spicy Extract!");
|
||||
NOT MESSAGE("Wobbuffet's attack missed!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPICY_EXTRACT, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Wobbuffet's Attack sharply rose!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Wobbuffet's Defense harshly fell!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Spicy Extract will fail if target is in a semi-invulnerability state")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHTPOWDER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_DIVE); MOVE(player, MOVE_SPICY_EXTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Foe Wobbuffet used Dive!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DIVE, opponent);
|
||||
MESSAGE("Wobbuffet used Spicy Extract!");
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SPICY_EXTRACT, player);
|
||||
MESSAGE("Wobbuffet's attack missed!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Spicy Extract stat changes will be inverted by Contrary")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SNIVY) { Ability(ABILITY_CONTRARY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SPICY_EXTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Spicy Extract!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPICY_EXTRACT, player);
|
||||
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Snivy's Attack harshly fell!");
|
||||
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Snivy's Defense sharply rose!");
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 2);
|
||||
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 2);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Spicy Extract against Clear Amulet and Contrary raises Defense only")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SNIVY) { Ability(ABILITY_CONTRARY); Item(ITEM_CLEAR_AMULET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SPICY_EXTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Spicy Extract!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPICY_EXTRACT, player);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Snivy's Attack harshly fell!");
|
||||
}
|
||||
MESSAGE("Foe Snivy's Clear Amulet prevents its stats from being lowered!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Foe Snivy's Defense sharply rose!");
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
|
||||
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 2);
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("Spicy Extract user will use it if partner holds Clear Amulet and a physical move")
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_TACKLE; }
|
||||
PARAMETRIZE { move = MOVE_SWIFT;}
|
||||
|
||||
AI_LOG;
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); Item(ITEM_CLEAR_AMULET); Moves(move); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(40); Moves(MOVE_TACKLE, MOVE_SPICY_EXTRACT); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
if (move == MOVE_TACKLE)
|
||||
EXPECT_MOVE(opponentRight, MOVE_SPICY_EXTRACT);
|
||||
else
|
||||
EXPECT_MOVE(opponentRight, MOVE_TACKLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("Spicy Extract user will not choose the move if it does not benefit partner")
|
||||
{
|
||||
u32 species;
|
||||
u32 ability;
|
||||
|
||||
PARAMETRIZE { species = SPECIES_GHOLDENGO; ability = ABILITY_GOOD_AS_GOLD; }
|
||||
PARAMETRIZE { species = SPECIES_SNIVY; ability = ABILITY_CONTRARY; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
OPPONENT(species) { Speed(20); Ability(ability); Moves(MOVE_TACKLE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(40); Moves(MOVE_TACKLE, MOVE_SPICY_EXTRACT); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
EXPECT_MOVE(opponentRight, MOVE_TACKLE);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue