Merge branch 'master' of https://github.com/rh-hideout/pokeemerald-expansion into masterintoupcoming18jun
This commit is contained in:
commit
a24b767276
24 changed files with 819 additions and 223 deletions
|
@ -4221,7 +4221,6 @@ Move_SMACK_DOWN::
|
|||
createvisualtask AnimTask_SmokescreenImpact, 0x8, 0x400, 0x1902
|
||||
fadetobg BG_IN_AIR
|
||||
waitbgfadeout
|
||||
createvisualtask AnimTask_StartSlidingBg, 5, 0x0, 0x0, 0x0, 0xffff
|
||||
createvisualtask AnimTask_SeismicTossBgAccelerateDownAtEnd, 3
|
||||
goto SeismicTossWeak
|
||||
|
||||
|
|
|
@ -5828,6 +5828,7 @@ BattleScript_DoSwitchOut::
|
|||
|
||||
BattleScript_PursuitDmgOnSwitchOut::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
orword gHitMarker, HITMARKER_OBEYS
|
||||
attackstring
|
||||
ppreduce
|
||||
critcalc
|
||||
|
@ -5845,11 +5846,12 @@ BattleScript_PursuitDmgOnSwitchOut::
|
|||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
tryfaintmon BS_TARGET
|
||||
moveendfromto MOVEEND_ABILITIES, MOVEEND_CHOICE_MOVE
|
||||
moveendfromto MOVEEND_ABILITIES, MOVEEND_ATTACKER_INVISIBLE @ MOVEEND_CHOICE_MOVE has to be included
|
||||
jumpiffainted BS_TARGET, FALSE, BattleScript_PursuitDmgOnSwitchOutRet
|
||||
setbyte sGIVEEXP_STATE, 0
|
||||
getexp BS_TARGET
|
||||
BattleScript_PursuitDmgOnSwitchOutRet:
|
||||
bicword gHitMarker, HITMARKER_OBEYS
|
||||
return
|
||||
|
||||
BattleScript_Pausex20::
|
||||
|
|
|
@ -313,6 +313,9 @@ MossdeepCity_SpaceCenter_2F_EventScript_DefeatedMaxieTabitha::
|
|||
setobjectmovementtype LOCALID_SCIENTIST, MOVEMENT_TYPE_WANDER_AROUND
|
||||
addobject LOCALID_SCIENTIST
|
||||
fadescreen FADE_FROM_BLACK
|
||||
#ifdef BUGFIX
|
||||
releaseall
|
||||
#endif
|
||||
end
|
||||
|
||||
MossdeepCity_SpaceCenter_2F_EventScript_StevenFacePlayer::
|
||||
|
|
|
@ -203,10 +203,10 @@ u8 GetBattlerSpriteDefault_Y(u8 battlerId);
|
|||
u8 GetSubstituteSpriteDefault_Y(u8 battlerId);
|
||||
|
||||
// battle_anim_status_effects.c
|
||||
#define STAT_ANIM_PLUS1 MOVE_EFFECT_ATK_PLUS_1 - 1
|
||||
#define STAT_ANIM_PLUS2 MOVE_EFFECT_ATK_PLUS_2 - 1
|
||||
#define STAT_ANIM_MINUS1 MOVE_EFFECT_ATK_MINUS_1 - 1
|
||||
#define STAT_ANIM_MINUS2 MOVE_EFFECT_ATK_MINUS_2 - 1
|
||||
#define STAT_ANIM_PLUS1 (MOVE_EFFECT_ATK_PLUS_1 - 1)
|
||||
#define STAT_ANIM_PLUS2 (MOVE_EFFECT_ATK_PLUS_2 - 1)
|
||||
#define STAT_ANIM_MINUS1 (MOVE_EFFECT_ATK_MINUS_1 - 1)
|
||||
#define STAT_ANIM_MINUS2 (MOVE_EFFECT_ATK_MINUS_2 - 1)
|
||||
#define STAT_ANIM_MULTIPLE_PLUS1 55
|
||||
#define STAT_ANIM_MULTIPLE_PLUS2 56
|
||||
#define STAT_ANIM_MULTIPLE_MINUS1 57
|
||||
|
|
|
@ -600,14 +600,15 @@ struct Roamer
|
|||
/*0x08*/ u16 species;
|
||||
/*0x0A*/ u16 hp;
|
||||
/*0x0C*/ u8 level;
|
||||
/*0x0D*/ u16 status;
|
||||
/*0x0F*/ u8 cool;
|
||||
/*0x10*/ u8 beauty;
|
||||
/*0x11*/ u8 cute;
|
||||
/*0x12*/ u8 smart;
|
||||
/*0x0D*/ u8 statusA;
|
||||
/*0x0E*/ u8 cool;
|
||||
/*0x0F*/ u8 beauty;
|
||||
/*0x10*/ u8 cute;
|
||||
/*0x11*/ u8 smart;
|
||||
/*0x12*/ u8 tough;
|
||||
/*0x13*/ bool8 active;
|
||||
/*0x14*/ u8 tough;
|
||||
/*0x15*/ u8 filler[0x7];
|
||||
/*0x14*/ u8 statusB; // Stores frostbite
|
||||
/*0x14*/ u8 filler[0x7];
|
||||
};
|
||||
|
||||
struct RamScriptData
|
||||
|
|
|
@ -695,6 +695,7 @@ struct BattleTestData
|
|||
struct BattleTestRunnerState
|
||||
{
|
||||
u8 battlersCount;
|
||||
bool8 forceMoveAnim;
|
||||
u16 parametersCount; // Valid only in BattleTest_Setup.
|
||||
u16 parameters;
|
||||
u16 runParameter;
|
||||
|
@ -991,6 +992,8 @@ void SendOut(u32 sourceLine, struct BattlePokemon *, u32 partyIndex);
|
|||
#define NONE_OF for (OpenQueueGroup(__LINE__, QUEUE_GROUP_NONE_OF); gBattleTestRunnerState->data.queueGroupType != QUEUE_GROUP_NONE; CloseQueueGroup(__LINE__))
|
||||
#define NOT NONE_OF
|
||||
|
||||
#define FORCE_MOVE_ANIM(set) gBattleTestRunnerState->forceMoveAnim = (set)
|
||||
|
||||
#define ABILITY_POPUP(battler, ...) QueueAbility(__LINE__, battler, (struct AbilityEventContext) { __VA_ARGS__ })
|
||||
#define ANIMATION(type, id, ...) QueueAnimation(__LINE__, type, id, (struct AnimationEventContext) { __VA_ARGS__ })
|
||||
#define HP_BAR(battler, ...) QueueHP(__LINE__, battler, (struct HPEventContext) { R_APPEND_TRUE(__VA_ARGS__) })
|
||||
|
|
|
@ -3758,7 +3758,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
case EFFECT_SANDSTORM:
|
||||
if (ShouldSetSandstorm(battlerAtk, aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerAtk]))
|
||||
if (ShouldSetSandstorm(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk]))
|
||||
{
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_SMOOTH_ROCK)
|
||||
|
|
|
@ -521,7 +521,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
|
|||
}
|
||||
else if (gMovesInfo[move].effect == EFFECT_PHOTON_GEYSER)
|
||||
gBattleStruct->swapDamageCategory = (GetCategoryBasedOnStats(gBattlerAttacker) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
else if (move == MOVE_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_SPECIAL)
|
||||
else if (move == MOVE_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL)
|
||||
gBattleStruct->swapDamageCategory = TRUE;
|
||||
else if (gMovesInfo[move].effect == EFFECT_NATURE_POWER)
|
||||
move = GetNaturePowerMove();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "sprite.h"
|
||||
#include "task.h"
|
||||
#include "test_runner.h"
|
||||
#include "test/battle.h"
|
||||
#include "constants/battle_anim.h"
|
||||
#include "constants/moves.h"
|
||||
|
||||
|
@ -239,6 +240,9 @@ void LaunchBattleAnimation(u32 animType, u32 animId)
|
|||
TestRunner_Battle_RecordAnimation(animType, animId);
|
||||
// Play Transform and Ally Switch even in Headless as these move animations also change mon data.
|
||||
if (gTestRunnerHeadless
|
||||
#if TESTING // Because gBattleTestRunnerState is not seen outside of test env.
|
||||
&& !gBattleTestRunnerState->forceMoveAnim
|
||||
#endif // TESTING
|
||||
&& !(animType == ANIM_TYPE_MOVE && (animId == MOVE_TRANSFORM || animId == MOVE_ALLY_SWITCH)))
|
||||
{
|
||||
gAnimScriptCallback = Nop;
|
||||
|
@ -446,7 +450,7 @@ static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets)
|
|||
u32 i;
|
||||
u32 ignoredTgt = gBattlerAttacker;
|
||||
u32 target = GetBattlerMoveTargetType(gBattleAnimAttacker, gAnimMoveIndex);
|
||||
|
||||
|
||||
switch (battlerAnimId)
|
||||
{
|
||||
case ANIM_ATTACKER:
|
||||
|
@ -458,7 +462,7 @@ static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets)
|
|||
ignoredTgt = gBattlerAttacker;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch (target)
|
||||
{
|
||||
case MOVE_TARGET_FOES_AND_ALLY:
|
||||
|
|
|
@ -1961,7 +1961,7 @@ static void Cmd_damagecalc(void)
|
|||
u8 moveType;
|
||||
|
||||
GET_MOVE_TYPE(gCurrentMove, moveType);
|
||||
if (gBattleStruct->shellSideArmCategory[gBattlerAttacker][gBattlerTarget] == DAMAGE_CATEGORY_SPECIAL && gCurrentMove == MOVE_SHELL_SIDE_ARM)
|
||||
if (gBattleStruct->shellSideArmCategory[gBattlerAttacker][gBattlerTarget] == DAMAGE_CATEGORY_PHYSICAL && gCurrentMove == MOVE_SHELL_SIDE_ARM)
|
||||
gBattleStruct->swapDamageCategory = TRUE;
|
||||
gBattleMoveDamage = CalculateMoveDamage(gCurrentMove, gBattlerAttacker, gBattlerTarget, moveType, 0, gIsCriticalHit, TRUE, TRUE);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
@ -5389,7 +5389,6 @@ static void Cmd_moveend(void)
|
|||
bool32 effect = FALSE;
|
||||
u32 moveType = 0;
|
||||
u32 holdEffectAtk = 0;
|
||||
u16 *choicedMoveAtk = NULL;
|
||||
u32 endMode, endState;
|
||||
u32 originallyUsedMove;
|
||||
|
||||
|
@ -5402,7 +5401,6 @@ static void Cmd_moveend(void)
|
|||
endState = cmd->endState;
|
||||
|
||||
holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE);
|
||||
choicedMoveAtk = &gBattleStruct->choicedMove[gBattlerAttacker];
|
||||
GET_MOVE_TYPE(gCurrentMove, moveType);
|
||||
|
||||
do
|
||||
|
@ -5612,29 +5610,34 @@ static void Cmd_moveend(void)
|
|||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_CHOICE_MOVE: // update choice band move
|
||||
if (gHitMarker & HITMARKER_OBEYS
|
||||
&& (HOLD_EFFECT_CHOICE(holdEffectAtk) || GetBattlerAbility(gBattlerAttacker) == ABILITY_GORILLA_TACTICS)
|
||||
&& gChosenMove != MOVE_STRUGGLE
|
||||
&& (*choicedMoveAtk == MOVE_NONE || *choicedMoveAtk == MOVE_UNAVAILABLE))
|
||||
{
|
||||
if ((gMovesInfo[gChosenMove].effect == EFFECT_BATON_PASS
|
||||
|| gMovesInfo[gChosenMove].effect == EFFECT_HEALING_WISH)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_FAILED))
|
||||
u16 *choicedMoveAtk = &gBattleStruct->choicedMove[gBattlerAttacker];
|
||||
if (gHitMarker & HITMARKER_OBEYS
|
||||
&& (HOLD_EFFECT_CHOICE(holdEffectAtk) || GetBattlerAbility(gBattlerAttacker) == ABILITY_GORILLA_TACTICS)
|
||||
&& gChosenMove != MOVE_STRUGGLE
|
||||
&& (*choicedMoveAtk == MOVE_NONE || *choicedMoveAtk == MOVE_UNAVAILABLE))
|
||||
{
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
if ((gMovesInfo[gChosenMove].effect == EFFECT_BATON_PASS
|
||||
|| gMovesInfo[gChosenMove].effect == EFFECT_HEALING_WISH)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_FAILED))
|
||||
{
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
*choicedMoveAtk = gChosenMove;
|
||||
}
|
||||
*choicedMoveAtk = gChosenMove;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].moves[i] == *choicedMoveAtk)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_MON_MOVES)
|
||||
{
|
||||
*choicedMoveAtk = MOVE_NONE;
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].moves[i] == *choicedMoveAtk)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_MON_MOVES)
|
||||
*choicedMoveAtk = MOVE_NONE;
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_CHANGED_ITEMS: // changed held items
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
|
@ -12825,7 +12828,11 @@ static void Cmd_trysetencore(void)
|
|||
{
|
||||
gDisableStructs[gBattlerTarget].encoredMove = gBattleMons[gBattlerTarget].moves[i];
|
||||
gDisableStructs[gBattlerTarget].encoredMovePos = i;
|
||||
gDisableStructs[gBattlerTarget].encoreTimer = 3;
|
||||
// Encore always lasts 3 turns, but we need to account for a scenario where Encore changes the move during the same turn.
|
||||
if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget))
|
||||
gDisableStructs[gBattlerTarget].encoreTimer = 4;
|
||||
else
|
||||
gDisableStructs[gBattlerTarget].encoreTimer = 3;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
|
@ -13543,7 +13550,7 @@ static void Cmd_jumpifnopursuitswitchdmg(void)
|
|||
gActionsByTurnOrder[i] = B_ACTION_TRY_FINISH;
|
||||
}
|
||||
|
||||
gCurrentMove = gChosenMoveByBattler[gBattlerTarget];
|
||||
gCurrentMove = gChosenMove = gChosenMoveByBattler[gBattlerTarget];
|
||||
gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerTarget);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
gBattleScripting.animTurn = 1;
|
||||
|
@ -16437,9 +16444,9 @@ void BS_SetRemoveTerrain(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
u16 atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE);
|
||||
u32 atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE);
|
||||
|
||||
gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY;
|
||||
gFieldStatuses &= ~(STATUS_FIELD_TERRAIN_ANY | STATUS_FIELD_TERRAIN_PERMANENT);
|
||||
gFieldStatuses |= statusFlag;
|
||||
gFieldTimers.terrainTimer = (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
@ -16537,7 +16544,8 @@ void BS_TryRelicSong(void)
|
|||
{
|
||||
NATIVE_ARGS();
|
||||
|
||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SHEER_FORCE && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED))
|
||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SHEER_FORCE && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED)
|
||||
&& (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA_ARIA || gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA_PIROUETTE))
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA_ARIA)
|
||||
gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA_PIROUETTE;
|
||||
|
@ -16548,7 +16556,9 @@ void BS_TryRelicSong(void)
|
|||
gBattlescriptCurrInstr = BattleScript_AttackerFormChangeMoveEffect;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
|
||||
void BS_SetPledge(void)
|
||||
|
|
|
@ -3883,7 +3883,7 @@ static bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag, u8 *timer)
|
|||
{
|
||||
if ((!(gFieldStatuses & statusFlag) && (!gBattleStruct->isSkyBattle)))
|
||||
{
|
||||
gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN);
|
||||
gFieldStatuses &= ~(STATUS_FIELD_TERRAIN_ANY | STATUS_FIELD_TERRAIN_PERMANENT);
|
||||
gFieldStatuses |= statusFlag;
|
||||
gDisableStructs[battler].terrainAbilityDone = FALSE;
|
||||
|
||||
|
@ -6558,7 +6558,7 @@ static u8 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, bool32 end2)
|
|||
else
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
|
||||
gBattleScripting.animArg1 = 14 + statId;
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
if (end2)
|
||||
|
@ -6609,7 +6609,7 @@ static u8 RandomStatRaiseBerry(u32 battler, u32 itemId, bool32 end2)
|
|||
else
|
||||
SET_STATCHANGER(i + 1, 2, FALSE);
|
||||
|
||||
gBattleScripting.animArg1 = 0x21 + i + 6;
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS2 + i + 1;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
if (end2)
|
||||
{
|
||||
|
@ -6686,7 +6686,7 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
|
|||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
|
||||
gBattleScripting.battler = battler;
|
||||
gBattleScripting.animArg1 = 14 + statId;
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet;
|
||||
|
@ -6703,7 +6703,7 @@ u8 TryHandleSeed(u32 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 exe
|
|||
gLastUsedItem = itemId; // For surge abilities
|
||||
gEffectBattler = gBattleScripting.battler = battler;
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
gBattleScripting.animArg1 = 14 + statId;
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
if (execute)
|
||||
{
|
||||
|
@ -7111,7 +7111,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
|
|||
}
|
||||
SET_STATCHANGER(STAT_ATK, 2, FALSE);
|
||||
|
||||
gBattleScripting.animArg1 = 14 + STAT_ATK;
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
|
||||
|
@ -7393,7 +7393,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
|
|||
}
|
||||
SET_STATCHANGER(STAT_ATK, 2, FALSE);
|
||||
|
||||
gBattleScripting.animArg1 = 14 + STAT_ATK;
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
|
||||
|
@ -7657,7 +7657,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
|
|||
}
|
||||
SET_STATCHANGER(STAT_ATK, 2, FALSE);
|
||||
|
||||
gBattleScripting.animArg1 = 14 + STAT_ATK;
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
|
||||
|
@ -8343,7 +8343,7 @@ bool32 IsMoveMakingContact(u32 move, u32 battlerAtk)
|
|||
|
||||
if (!gMovesInfo[move].makesContact)
|
||||
{
|
||||
if (move == MOVE_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][gBattlerTarget] == DAMAGE_CATEGORY_SPECIAL)
|
||||
if (move == MOVE_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][gBattlerTarget] == DAMAGE_CATEGORY_PHYSICAL)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
|
@ -8383,7 +8383,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||
// Protective Pads doesn't stop Unseen Fist from bypassing Protect effects, so IsMoveMakingContact() isn't used here.
|
||||
// This means extra logic is needed to handle Shell Side Arm.
|
||||
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_UNSEEN_FIST
|
||||
&& (gMovesInfo[move].makesContact || (move == MOVE_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_SPECIAL))
|
||||
&& (gMovesInfo[move].makesContact || (move == MOVE_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL))
|
||||
&& !gProtectStructs[battlerDef].maxGuarded) // Max Guard cannot be bypassed by Unseen Fist
|
||||
return FALSE;
|
||||
else if (gMovesInfo[move].ignoresProtect)
|
||||
|
@ -9316,7 +9316,11 @@ static inline u32 CalcAttackStat(u32 move, u32 battlerAtk, u32 battlerDef, u32 m
|
|||
if (IS_MOVE_PHYSICAL(move))
|
||||
{
|
||||
atkStat = gBattleMons[battlerAtk].defense;
|
||||
atkStage = gBattleMons[battlerAtk].statStages[STAT_DEF];
|
||||
// Edge case: Body Press used during Wonder Room. For some reason, it still uses Defense over Sp.Def, but uses Sp.Def stat changes
|
||||
if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM)
|
||||
atkStage = gBattleMons[battlerAtk].statStages[STAT_SPDEF];
|
||||
else
|
||||
atkStage = gBattleMons[battlerAtk].statStages[STAT_DEF];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -11222,7 +11226,7 @@ bool32 TryRoomService(u32 battler)
|
|||
BufferStatChange(battler, STAT_SPEED, STRINGID_STATFELL);
|
||||
gEffectBattler = gBattleScripting.battler = battler;
|
||||
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
|
||||
gBattleScripting.animArg1 = 14 + STAT_SPEED;
|
||||
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_SPEED;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
return TRUE;
|
||||
|
@ -11608,7 +11612,9 @@ void SetShellSideArmCategory(void)
|
|||
|
||||
special = ((((2 * gBattleMons[battlerAtk].level / 5 + 2) * gMovesInfo[MOVE_SHELL_SIDE_ARM].power * attackerSpAtkStat) / targetSpDefStat) / 50);
|
||||
|
||||
if (((physical > special) || (physical == special && RandomPercentage(RNG_SHELL_SIDE_ARM, 50))))
|
||||
if ((physical > special) || (physical == special && RandomPercentage(RNG_SHELL_SIDE_ARM, 50)))
|
||||
gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] = DAMAGE_CATEGORY_PHYSICAL;
|
||||
else
|
||||
gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] = DAMAGE_CATEGORY_SPECIAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1040,12 +1040,14 @@ static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parent
|
|||
eggSpecies = SPECIES_ILLUMISE;
|
||||
else if (eggSpecies == SPECIES_MANAPHY)
|
||||
eggSpecies = SPECIES_PHIONE;
|
||||
else if (eggSpecies == SPECIES_SINISTEA_ANTIQUE)
|
||||
eggSpecies = SPECIES_SINISTEA_PHONY;
|
||||
else if (GET_BASE_SPECIES_ID(eggSpecies) == SPECIES_ROTOM)
|
||||
eggSpecies = SPECIES_ROTOM;
|
||||
else if (GET_BASE_SPECIES_ID(eggSpecies) == SPECIES_FURFROU)
|
||||
eggSpecies = SPECIES_FURFROU;
|
||||
else if (eggSpecies == SPECIES_SINISTEA_ANTIQUE)
|
||||
eggSpecies = SPECIES_SINISTEA_PHONY;
|
||||
else if (eggSpecies == SPECIES_POLTCHAGEIST_ARTISAN)
|
||||
eggSpecies = SPECIES_POLTCHAGEIST_COUNTERFEIT;
|
||||
// To avoid single-stage Totem Pokémon to breed more of themselves.
|
||||
else if (eggSpecies == SPECIES_MIMIKYU_TOTEM_DISGUISED)
|
||||
eggSpecies = SPECIES_MIMIKYU_DISGUISED;
|
||||
|
|
15
src/roamer.c
15
src/roamer.c
|
@ -105,7 +105,8 @@ static void CreateInitialRoamerMon(u8 index, u16 species, u8 level)
|
|||
ROAMER(index)->personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY);
|
||||
ROAMER(index)->species = species;
|
||||
ROAMER(index)->level = level;
|
||||
ROAMER(index)->status = 0;
|
||||
ROAMER(index)->statusA = 0;
|
||||
ROAMER(index)->statusB = 0;
|
||||
ROAMER(index)->hp = GetMonData(&gEnemyParty[0], MON_DATA_MAX_HP);
|
||||
ROAMER(index)->cool = GetMonData(&gEnemyParty[0], MON_DATA_COOL);
|
||||
ROAMER(index)->beauty = GetMonData(&gEnemyParty[0], MON_DATA_BEAUTY);
|
||||
|
@ -238,18 +239,13 @@ bool8 IsRoamerAt(u32 roamerIndex, u8 mapGroup, u8 mapNum)
|
|||
|
||||
void CreateRoamerMonInstance(u32 roamerIndex)
|
||||
{
|
||||
u32 status;
|
||||
u32 status = ROAMER(roamerIndex)->statusA + (ROAMER(roamerIndex)->statusB << 8);
|
||||
struct Pokemon *mon = &gEnemyParty[0];
|
||||
ZeroEnemyPartyMons();
|
||||
CreateMonWithIVsPersonality(mon, ROAMER(roamerIndex)->species, ROAMER(roamerIndex)->level, ROAMER(roamerIndex)->ivs, ROAMER(roamerIndex)->personality);
|
||||
// The roamer's status field is u16, but SetMonData expects status to be u32, so will set the roamer's status
|
||||
// using the status field and the following 3 bytes (cool, beauty, and cute).
|
||||
#ifdef BUGFIX
|
||||
status = ROAMER(roamerIndex)->status;
|
||||
SetMonData(mon, MON_DATA_STATUS, &status);
|
||||
#else
|
||||
SetMonData(mon, MON_DATA_STATUS, &ROAMER->status);
|
||||
#endif
|
||||
SetMonData(mon, MON_DATA_HP, &ROAMER(roamerIndex)->hp);
|
||||
SetMonData(mon, MON_DATA_COOL, &ROAMER(roamerIndex)->cool);
|
||||
SetMonData(mon, MON_DATA_BEAUTY, &ROAMER(roamerIndex)->beauty);
|
||||
|
@ -276,8 +272,11 @@ bool8 TryStartRoamerEncounter(void)
|
|||
|
||||
void UpdateRoamerHPStatus(struct Pokemon *mon)
|
||||
{
|
||||
u32 status = GetMonData(mon, MON_DATA_STATUS);
|
||||
|
||||
ROAMER(gEncounteredRoamerIndex)->hp = GetMonData(mon, MON_DATA_HP);
|
||||
ROAMER(gEncounteredRoamerIndex)->status = GetMonData(mon, MON_DATA_STATUS);
|
||||
ROAMER(gEncounteredRoamerIndex)->statusA = status;
|
||||
ROAMER(gEncounteredRoamerIndex)->statusB = status >> 8;
|
||||
|
||||
RoamerMoveToOtherLocationSet(gEncounteredRoamerIndex);
|
||||
}
|
||||
|
|
73
test/battle/ability/anger_point.c
Normal file
73
test/battle/ability/anger_point.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Anger Point raises Attack stage to maximum after receiving a critical hit")
|
||||
{
|
||||
ASSUME(gMovesInfo[MOVE_FROST_BREATH].alwaysCriticalHit);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_PRIMEAPE) { Ability(ABILITY_ANGER_POINT); }
|
||||
OPPONENT(SPECIES_SNORUNT);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_FROST_BREATH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FROST_BREATH, opponent);
|
||||
MESSAGE("A critical hit!");
|
||||
ABILITY_POPUP(player, ABILITY_ANGER_POINT);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Primeape's Anger Point maxed its Attack!");
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], MAX_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anger Point does not trigger when already at maximum Attack stage")
|
||||
{
|
||||
ASSUME(gMovesInfo[MOVE_FROST_BREATH].alwaysCriticalHit);
|
||||
ASSUME(gMovesInfo[MOVE_BELLY_DRUM].effect == EFFECT_BELLY_DRUM);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_PRIMEAPE) { Ability(ABILITY_ANGER_POINT); Speed(2); }
|
||||
OPPONENT(SPECIES_SNORUNT) { Speed(1); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BELLY_DRUM); MOVE(opponent, MOVE_FROST_BREATH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Primeape cut its own HP and maximized ATTACK!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FROST_BREATH, opponent);
|
||||
MESSAGE("A critical hit!");
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_ANGER_POINT);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Primeape's Anger Point maxed its Attack!");
|
||||
}
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], MAX_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Anger Point does not trigger when a substitute takes the hit")
|
||||
{
|
||||
ASSUME(gMovesInfo[MOVE_FROST_BREATH].alwaysCriticalHit);
|
||||
ASSUME(gMovesInfo[MOVE_SUBSTITUTE].effect == EFFECT_SUBSTITUTE);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_PRIMEAPE) { Ability(ABILITY_ANGER_POINT); Speed(2); }
|
||||
OPPONENT(SPECIES_SNORUNT) { Speed(1); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SUBSTITUTE); MOVE(opponent, MOVE_FROST_BREATH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, player);
|
||||
MESSAGE("Primeape made a SUBSTITUTE!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FROST_BREATH, opponent);
|
||||
MESSAGE("A critical hit!");
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_ANGER_POINT);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Primeape's Anger Point maxed its Attack!");
|
||||
}
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
|
||||
}
|
||||
}
|
|
@ -1,15 +1,19 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body prevents intimidate")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent intimidate")
|
||||
{
|
||||
s16 turnOneHit;
|
||||
s16 turnTwoHit;
|
||||
u32 species, ability;
|
||||
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); };
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); };
|
||||
OPPONENT(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); };
|
||||
OPPONENT(species) { Ability(ability); };
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TACKLE); }
|
||||
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); }
|
||||
|
@ -20,24 +24,38 @@ SINGLE_BATTLE_TEST("Clear Body prevents intimidate")
|
|||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
}
|
||||
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
MESSAGE("Foe Beldum's Clear Body prevents stat loss!");
|
||||
ABILITY_POPUP(opponent, ability);
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal's White Smoke prevents stat loss!");
|
||||
else
|
||||
MESSAGE("Foe Metang's Clear Body prevents stat loss!");
|
||||
HP_BAR(player, captureDamage: &turnTwoHit);
|
||||
} THEN {
|
||||
EXPECT_EQ(turnOneHit, turnTwoHit);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body prevents stat stage reduction from moves")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent stat stage reduction from moves")
|
||||
{
|
||||
u16 move;
|
||||
PARAMETRIZE{ move = MOVE_GROWL; }
|
||||
PARAMETRIZE{ move = MOVE_LEER; }
|
||||
PARAMETRIZE{ move = MOVE_CONFIDE; }
|
||||
PARAMETRIZE{ move = MOVE_FAKE_TEARS; }
|
||||
PARAMETRIZE{ move = MOVE_SCARY_FACE; }
|
||||
PARAMETRIZE{ move = MOVE_SWEET_SCENT; }
|
||||
PARAMETRIZE{ move = MOVE_SAND_ATTACK; }
|
||||
u16 move = MOVE_NONE;
|
||||
u32 j, species = SPECIES_NONE, ability = ABILITY_NONE;
|
||||
static const u16 statReductionMoves[] = {
|
||||
MOVE_GROWL,
|
||||
MOVE_LEER,
|
||||
MOVE_CONFIDE,
|
||||
MOVE_FAKE_TEARS,
|
||||
MOVE_SCARY_FACE,
|
||||
MOVE_SWEET_SCENT,
|
||||
MOVE_SAND_ATTACK,
|
||||
};
|
||||
for (j = 0; j < ARRAY_COUNT(statReductionMoves); j++)
|
||||
{
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; move = statReductionMoves[j]; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; move = statReductionMoves[j]; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; move = statReductionMoves[j]; }
|
||||
}
|
||||
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN);
|
||||
|
@ -48,7 +66,7 @@ SINGLE_BATTLE_TEST("Clear Body prevents stat stage reduction from moves")
|
|||
ASSUME(gMovesInfo[MOVE_SWEET_SCENT].effect == (B_UPDATED_MOVE_DATA >= GEN_6 ? EFFECT_EVASION_DOWN_2 : EFFECT_EVASION_DOWN));
|
||||
ASSUME(gMovesInfo[MOVE_SAND_ATTACK].effect == EFFECT_ACCURACY_DOWN);
|
||||
PLAYER(SPECIES_WOBBUFFET)
|
||||
OPPONENT(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); }
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
|
@ -56,18 +74,27 @@ SINGLE_BATTLE_TEST("Clear Body prevents stat stage reduction from moves")
|
|||
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
}
|
||||
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
MESSAGE("Foe Beldum's Clear Body prevents stat loss!");
|
||||
ABILITY_POPUP(opponent, ability);
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal's White Smoke prevents stat loss!");
|
||||
else
|
||||
MESSAGE("Foe Metang's Clear Body prevents stat loss!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body prevents Sticky Web")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke prevent Sticky Web effect on switchin")
|
||||
{
|
||||
u32 species, ability;
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; }
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_STICKY_WEB].effect == EFFECT_STICKY_WEB);
|
||||
PLAYER(SPECIES_WOBBUFFET)
|
||||
OPPONENT(SPECIES_WOBBUFFET)
|
||||
OPPONENT(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); }
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STICKY_WEB); }
|
||||
TURN { SWITCH(opponent, 1); }
|
||||
|
@ -75,32 +102,43 @@ SINGLE_BATTLE_TEST("Clear Body prevents Sticky Web")
|
|||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
}
|
||||
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
MESSAGE("Foe Beldum's Clear Body prevents stat loss!");
|
||||
ABILITY_POPUP(opponent, ability);
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal's White Smoke prevents stat loss!");
|
||||
else
|
||||
MESSAGE("Foe Metang's Clear Body prevents stat loss!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body doesn't prevent stat stage reduction from moves used by the user")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent stat stage reduction from moves used by the user")
|
||||
{
|
||||
u32 species, ability;
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; }
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffectSelf(MOVE_SUPERPOWER, MOVE_EFFECT_ATK_DEF_DOWN) == TRUE);
|
||||
PLAYER(SPECIES_WOBBUFFET)
|
||||
OPPONENT(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); }
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUPERPOWER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPERPOWER, opponent);
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
MESSAGE("Foe Beldum's Clear Body prevents stat loss!");
|
||||
ABILITY_POPUP(opponent, ability);
|
||||
MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!");
|
||||
MESSAGE("Foe Torkoal's White Smoke prevents stat loss!");
|
||||
MESSAGE("Foe Metang's Clear Body prevents stat loss!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Mold Breaker, Teravolt, and Turboblaze ignore Clear Body")
|
||||
SINGLE_BATTLE_TEST("Mold Breaker, Teravolt, and Turboblaze ignore Clear Body and White Smoke, but not Full Metal Body")
|
||||
{
|
||||
u32 j, k;
|
||||
u16 ability = ABILITY_NONE;
|
||||
u32 j, k, species = SPECIES_NONE, ability = ABILITY_NONE;
|
||||
u16 breakerAbility = ABILITY_NONE;
|
||||
u16 move = ABILITY_NONE;
|
||||
static const u16 breakerAbilities[] = {
|
||||
ABILITY_MOLD_BREAKER,
|
||||
|
@ -121,7 +159,9 @@ SINGLE_BATTLE_TEST("Mold Breaker, Teravolt, and Turboblaze ignore Clear Body")
|
|||
{
|
||||
for (k = 0; k < ARRAY_COUNT(breakerAbilities); k++)
|
||||
{
|
||||
PARAMETRIZE{ move = statReductionMoves[j]; ability = breakerAbilities[k]; }
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; move = statReductionMoves[j]; breakerAbility = breakerAbilities[k]; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; move = statReductionMoves[j]; breakerAbility = breakerAbilities[k]; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; move = statReductionMoves[j]; breakerAbility = breakerAbilities[k]; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,146 +173,242 @@ SINGLE_BATTLE_TEST("Mold Breaker, Teravolt, and Turboblaze ignore Clear Body")
|
|||
ASSUME(gMovesInfo[MOVE_SCARY_FACE].effect == EFFECT_SPEED_DOWN_2);
|
||||
ASSUME(gMovesInfo[MOVE_SWEET_SCENT].effect == (B_UPDATED_MOVE_DATA >= GEN_6 ? EFFECT_EVASION_DOWN_2 : EFFECT_EVASION_DOWN));
|
||||
ASSUME(gMovesInfo[MOVE_SAND_ATTACK].effect == EFFECT_ACCURACY_DOWN);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ability); }
|
||||
OPPONENT(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(breakerAbility); }
|
||||
OPPONENT(species) { Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
MESSAGE("Foe Beldum's Clear Body prevents stat loss!");
|
||||
if (ability == ABILITY_FULL_METAL_BODY){ // Full Metal Body can't be ignored by breaker abilities
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
ABILITY_POPUP(opponent, ability);
|
||||
MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!");
|
||||
}
|
||||
else{
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ability);
|
||||
MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!");
|
||||
MESSAGE("Foe Torkoal's White Smoke prevents stat loss!");
|
||||
MESSAGE("Foe Metang's Clear Body prevents stat loss!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body doesn't prevent Speed reduction from Iron Ball")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Speed reduction from Iron Ball")
|
||||
{
|
||||
u16 heldItem;
|
||||
PARAMETRIZE{ heldItem = ITEM_NONE; }
|
||||
PARAMETRIZE{ heldItem = ITEM_IRON_BALL; }
|
||||
u32 j, species = SPECIES_NONE, ability = ABILITY_NONE;
|
||||
u16 heldItem = ITEM_NONE;
|
||||
static const u16 heldItems[] = {
|
||||
ITEM_NONE,
|
||||
ITEM_IRON_BALL,
|
||||
};
|
||||
for (j = 0; j < ARRAY_COUNT(heldItems); j++)
|
||||
{
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; heldItem = heldItems[j]; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; heldItem = heldItems[j]; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; heldItem = heldItems[j]; }
|
||||
}
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_IRON_BALL].holdEffect == HOLD_EFFECT_IRON_BALL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
|
||||
OPPONENT(SPECIES_BELDUM) { Speed(6); Ability(ABILITY_CLEAR_BODY); Item(heldItem); }
|
||||
OPPONENT(species) { Speed(6); Ability(ability); Item(heldItem); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
NOT ABILITY_POPUP(opponent, ability);
|
||||
if (heldItem == ITEM_IRON_BALL) {
|
||||
MESSAGE("Wobbuffet used Celebrate!");
|
||||
MESSAGE("Foe Beldum used Celebrate!");
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
else
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
} else {
|
||||
MESSAGE("Foe Beldum used Celebrate!");
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
else
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
MESSAGE("Wobbuffet used Celebrate!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body doesn't prevent Speed reduction from paralysis")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Speed reduction from paralysis")
|
||||
{
|
||||
u32 species, ability;
|
||||
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
|
||||
OPPONENT(SPECIES_BELDUM) { Speed(6); Ability(ABILITY_CLEAR_BODY); }
|
||||
OPPONENT(species) { Speed(6); Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_THUNDER_WAVE); }
|
||||
TURN { MOVE(player, MOVE_THUNDER_WAVE); }
|
||||
} SCENE {
|
||||
MESSAGE("Foe Beldum used Celebrate!");
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
else
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
MESSAGE("Wobbuffet used Thunder Wave!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, player);
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
NOT ABILITY_POPUP(opponent, ability);
|
||||
MESSAGE("Wobbuffet used Thunder Wave!");
|
||||
ONE_OF {
|
||||
MESSAGE("Foe Beldum used Celebrate!");
|
||||
MESSAGE("Foe Beldum is paralyzed! It can't move!");
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
MESSAGE("Foe Metang is paralyzed! It can't move!");
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
MESSAGE("Foe Solgaleo is paralyzed! It can't move!");
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
MESSAGE("Foe Torkoal is paralyzed! It can't move!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body doesn't prevent Attack reduction from burn", s16 damage)
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Attack reduction from burn", s16 damage)
|
||||
{
|
||||
bool32 burned;
|
||||
PARAMETRIZE{ burned = FALSE; }
|
||||
PARAMETRIZE{ burned = TRUE; }
|
||||
bool32 burned = FALSE;
|
||||
u32 species, ability;
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; burned = FALSE; }
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; burned = TRUE; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; burned = FALSE; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; burned = TRUE; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; burned = FALSE; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; burned = TRUE; }
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
|
||||
PLAYER(SPECIES_WOBBUFFET)
|
||||
OPPONENT(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); if (burned) Status1(STATUS1_BURN); }
|
||||
OPPONENT(species) { Ability(ability); if (burned) Status1(STATUS1_BURN); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TACKLE); }
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
NOT ABILITY_POPUP(opponent, ability);
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body doesn't prevent receiving negative stat changes from Baton Pass")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent receiving negative stat changes from Baton Pass")
|
||||
{
|
||||
u32 species, ability;
|
||||
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_SCARY_FACE].effect == EFFECT_SPEED_DOWN_2);
|
||||
ASSUME(gMovesInfo[MOVE_BATON_PASS].effect == EFFECT_BATON_PASS);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
OPPONENT(SPECIES_BELDUM) { Speed(6); Ability(ABILITY_CLEAR_BODY); }
|
||||
OPPONENT(species) { Speed(6); Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); MOVE(opponent, MOVE_BATON_PASS); SEND_OUT(opponent, 1); }
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Scary Face!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
MESSAGE("Foe Beldum used Celebrate!");
|
||||
ABILITY_POPUP(opponent, ability);
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
else
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body doesn't prevent Topsy-Turvy")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Topsy-Turvy")
|
||||
{
|
||||
u32 species, ability;
|
||||
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_TOPSY_TURVY].effect == EFFECT_TOPSY_TURVY);
|
||||
ASSUME(gMovesInfo[MOVE_SCARY_FACE].effect == EFFECT_SPEED_DOWN_2);
|
||||
ASSUME(gMovesInfo[MOVE_BATON_PASS].effect == EFFECT_BATON_PASS);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
OPPONENT(SPECIES_BELDUM) { Speed(6); Ability(ABILITY_CLEAR_BODY); }
|
||||
OPPONENT(species) { Speed(6); Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); MOVE(opponent, MOVE_BATON_PASS); SEND_OUT(opponent, 1); }
|
||||
TURN { MOVE(player, MOVE_TOPSY_TURVY); }
|
||||
TURN { MOVE(player, MOVE_SCARY_FACE); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Topsy-Turvy!");
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
NOT ABILITY_POPUP(opponent, ability);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOPSY_TURVY, player);
|
||||
MESSAGE("Foe Beldum used Celebrate!");
|
||||
MESSAGE("Foe Beldum used Celebrate!");
|
||||
if (ability == ABILITY_FULL_METAL_BODY) {
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
}
|
||||
else if (ability == ABILITY_WHITE_SMOKE) {
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
}
|
||||
else {
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
}
|
||||
MESSAGE("Wobbuffet used Scary Face!");
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player);
|
||||
ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
ABILITY_POPUP(opponent, ability);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Clear Body doesn't prevent Spectral Thief from resetting positive stat changes")
|
||||
SINGLE_BATTLE_TEST("Clear Body, Full Metal Body, and White Smoke don't prevent Spectral Thief from resetting positive stat changes")
|
||||
{
|
||||
u32 species, ability;
|
||||
|
||||
PARAMETRIZE{ species = SPECIES_METANG; ability = ABILITY_CLEAR_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; }
|
||||
PARAMETRIZE{ species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_SPECTRAL_THIEF, MOVE_EFFECT_SPECTRAL_THIEF) == TRUE);
|
||||
ASSUME(gMovesInfo[MOVE_AGILITY].effect == EFFECT_SPEED_UP_2);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
|
||||
OPPONENT(SPECIES_METANG) { Speed(5); Ability(ABILITY_CLEAR_BODY); }
|
||||
OPPONENT(species) { Speed(5); Ability(ability); }
|
||||
} WHEN {
|
||||
TURN{ MOVE(opponent, MOVE_AGILITY); }
|
||||
TURN{ MOVE(player, MOVE_SPECTRAL_THIEF); }
|
||||
TURN{ }
|
||||
} SCENE {
|
||||
MESSAGE("Foe Metang used Agility!");
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo used Agility!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal used Agility!");
|
||||
else
|
||||
MESSAGE("Foe Metang used Agility!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_AGILITY, opponent);
|
||||
MESSAGE("Wobbuffet used Celebrate!");
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
else
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
MESSAGE("Wobbuffet used Spectral Thief!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPECTRAL_THIEF, player);
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY);
|
||||
NOT ABILITY_POPUP(opponent, ability);
|
||||
MESSAGE("Wobbuffet used Celebrate!");
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
if (ability == ABILITY_FULL_METAL_BODY)
|
||||
MESSAGE("Foe Solgaleo used Celebrate!");
|
||||
else if (ability == ABILITY_WHITE_SMOKE)
|
||||
MESSAGE("Foe Torkoal used Celebrate!");
|
||||
else
|
||||
MESSAGE("Foe Metang used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Full Metal Body prevents intimidate")
|
||||
{
|
||||
s16 turnOneHit;
|
||||
s16 turnTwoHit;
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); };
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); };
|
||||
OPPONENT(SPECIES_SOLGALEO) { Ability(ABILITY_FULL_METAL_BODY); };
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TACKLE); }
|
||||
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); }
|
||||
|
||||
} SCENE {
|
||||
HP_BAR(player, captureDamage: &turnOneHit);
|
||||
ABILITY_POPUP(player, ABILITY_INTIMIDATE);
|
||||
NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); }
|
||||
ABILITY_POPUP(opponent, ABILITY_FULL_METAL_BODY);
|
||||
MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!");
|
||||
HP_BAR(player, captureDamage: &turnTwoHit);
|
||||
} THEN {
|
||||
EXPECT_EQ(turnOneHit, turnTwoHit);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Full Metal Body prevents stat stage reduction from moves"); // Growl, Leer, Confide, Fake Tears, Scary Face, Sweet Scent, Sand Attack (Attack, Defense, Sp. Attack, Sp. Defense, Speed, Evasion, Accuracy
|
||||
TO_DO_BATTLE_TEST("Full Metal Body prevents Sticky Web");
|
||||
TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent stat stage reduction from moves used by the user"); // e.g. Superpower
|
||||
TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Speed reduction from Iron Ball");
|
||||
TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Speed reduction from paralysis");
|
||||
TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Attack reduction from burn");
|
||||
TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent receiving negative stat changes from Baton Pass");
|
||||
TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Topsy-Turvy");
|
||||
TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Spectral Thief from resetting positive stat changes");
|
||||
TO_DO_BATTLE_TEST("Full Metal Body is ignored by Mold Breaker");
|
121
test/battle/ability/moxie.c
Normal file
121
test/battle/ability/moxie.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
DOUBLE_BATTLE_TEST("Moxie raises Attack by one stage after directly causing a Pokemon to faint")
|
||||
{
|
||||
ASSUME(gMovesInfo[MOVE_EARTHQUAKE].target == MOVE_TARGET_FOES_AND_ALLY);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SALAMENCE) { Ability(ABILITY_MOXIE); }
|
||||
PLAYER(SPECIES_SNORUNT) { HP(1); }
|
||||
OPPONENT(SPECIES_GLALIE) { HP(1); }
|
||||
OPPONENT(SPECIES_ABRA) { HP(1); }
|
||||
OPPONENT(SPECIES_ABRA);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_EARTHQUAKE); SEND_OUT(opponentLeft, 2); }
|
||||
} SCENE {
|
||||
int i;
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, playerLeft);
|
||||
for (i = 0; i < 3; i++) {
|
||||
ONE_OF {
|
||||
MESSAGE("Snorunt fainted!");
|
||||
MESSAGE("Foe Glalie fainted!");
|
||||
MESSAGE("Foe Abra fainted!");
|
||||
}
|
||||
ABILITY_POPUP(playerLeft, ABILITY_MOXIE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
MESSAGE("Salamence's Moxie raised its Attack!");
|
||||
}
|
||||
} THEN {
|
||||
EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 3);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Moxie does not trigger if Pokemon faint to indirect damage or damage from other Pokemon")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SALAMENCE) { Ability(ABILITY_MOXIE); }
|
||||
PLAYER(SPECIES_SNORUNT) { HP(1); Status1(STATUS1_POISON); }
|
||||
OPPONENT(SPECIES_GLALIE) { HP(1); Status1(STATUS1_BURN); }
|
||||
OPPONENT(SPECIES_ABRA) { HP(1); }
|
||||
OPPONENT(SPECIES_ABRA);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentRight); SEND_OUT(opponentLeft, 2); }
|
||||
} SCENE {
|
||||
int i;
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, playerRight);
|
||||
for (i = 0; i < 3; i++) {
|
||||
ONE_OF {
|
||||
MESSAGE("Snorunt fainted!");
|
||||
MESSAGE("Foe Glalie fainted!");
|
||||
MESSAGE("Foe Abra fainted!");
|
||||
}
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(playerLeft, ABILITY_MOXIE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
MESSAGE("Salamence's Moxie raised its Attack!");
|
||||
}
|
||||
}
|
||||
} THEN {
|
||||
EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Moxie does not trigger when already at maximum Attack stage")
|
||||
{
|
||||
ASSUME(gMovesInfo[MOVE_BELLY_DRUM].effect == EFFECT_BELLY_DRUM);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SALAMENCE) { Ability(ABILITY_MOXIE); }
|
||||
OPPONENT(SPECIES_SNORUNT) { HP(1); }
|
||||
OPPONENT(SPECIES_SNORUNT);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BELLY_DRUM); }
|
||||
TURN { MOVE(player, MOVE_QUICK_ATTACK); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Salamence cut its own HP and maximized ATTACK!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player);
|
||||
MESSAGE("Foe Snorunt fainted!");
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_MOXIE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Salamence's Moxie raised its Attack!");
|
||||
}
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], MAX_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Moxie does not increase damage done by the same move that causes another Pokemon to faint")
|
||||
{
|
||||
s16 damage[2];
|
||||
|
||||
ASSUME(gMovesInfo[MOVE_EARTHQUAKE].target == MOVE_TARGET_FOES_AND_ALLY);
|
||||
|
||||
KNOWN_FAILING; // Requires simultaneous damage implementation
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SALAMENCE) { Ability(ABILITY_MOXIE); }
|
||||
PLAYER(SPECIES_ABRA) { HP(1); }
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
OPPONENT(SPECIES_ABRA);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_EARTHQUAKE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, playerLeft);
|
||||
HP_BAR(opponentLeft, captureDamage: &damage[0]);
|
||||
HP_BAR(playerRight);
|
||||
MESSAGE("Abra fainted!");
|
||||
ABILITY_POPUP(playerLeft, ABILITY_MOXIE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
MESSAGE("Salamence's Moxie raised its Attack!");
|
||||
HP_BAR(opponentRight, captureDamage: &damage[1]);
|
||||
} THEN {
|
||||
EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
|
||||
EXPECT_EQ(damage[0], damage[1]);
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("White Smoke prevents intimidate")
|
||||
{
|
||||
s16 turnOneHit;
|
||||
s16 turnTwoHit;
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); };
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); };
|
||||
OPPONENT(SPECIES_TORKOAL) { Ability(ABILITY_WHITE_SMOKE); };
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TACKLE); }
|
||||
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); }
|
||||
|
||||
} SCENE {
|
||||
HP_BAR(player, captureDamage: &turnOneHit);
|
||||
ABILITY_POPUP(player, ABILITY_INTIMIDATE);
|
||||
NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); }
|
||||
ABILITY_POPUP(opponent, ABILITY_WHITE_SMOKE);
|
||||
MESSAGE("Foe Torkoal's White Smoke prevents stat loss!");
|
||||
HP_BAR(player, captureDamage: &turnTwoHit);
|
||||
} THEN {
|
||||
EXPECT_EQ(turnOneHit, turnTwoHit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TO_DO_BATTLE_TEST("White Smoke prevents stat stage reduction from moves"); // Growl, Leer, Confide, Fake Tears, Scary Face, Sweet Scent, Sand Attack (Attack, Defense, Sp. Attack, Sp. Defense, Speed, Evasion, Accuracy
|
||||
TO_DO_BATTLE_TEST("White Smoke prevents Sticky Web");
|
||||
TO_DO_BATTLE_TEST("White Smoke doesn't prevent stat stage reduction from moves used by the user"); // e.g. Superpower
|
||||
TO_DO_BATTLE_TEST("White Smoke doesn't prevent Speed reduction from Iron Ball");
|
||||
TO_DO_BATTLE_TEST("White Smoke doesn't prevent Speed reduction from paralysis");
|
||||
TO_DO_BATTLE_TEST("White Smoke doesn't prevent Attack reduction from burn");
|
||||
TO_DO_BATTLE_TEST("White Smoke doesn't prevent receiving negative stat changes from Baton Pass");
|
||||
TO_DO_BATTLE_TEST("White Smoke doesn't prevent Topsy-Turvy");
|
||||
TO_DO_BATTLE_TEST("White Smoke doesn't prevent Spectral Thief from resetting positive stat changes");
|
||||
TO_DO_BATTLE_TEST("White Smoke is ignored by Mold Breaker");
|
25
test/battle/move_animations/smack_down.c
Normal file
25
test/battle/move_animations/smack_down.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Move Animation Test: Smack Down works when used 15 times in a row")
|
||||
{
|
||||
u16 j, nTurns = 15;
|
||||
FORCE_MOVE_ANIM(TRUE);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
for (j = 0; j < nTurns; j++)
|
||||
{
|
||||
TURN { MOVE(player, MOVE_SMACK_DOWN); MOVE(opponent, MOVE_HELPING_HAND); } // Helping Hand, so there's no anim on the opponent's side.
|
||||
}
|
||||
} SCENE {
|
||||
for (j = 0; j < nTurns; j++)
|
||||
{
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SMACK_DOWN, player);
|
||||
}
|
||||
} THEN {
|
||||
FORCE_MOVE_ANIM(FALSE);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ SINGLE_BATTLE_TEST("Body Press uses physical defense stat of target", s16 damage
|
|||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_DRILL_PECK].power == gMovesInfo[MOVE_BODY_PRESS].power);
|
||||
ASSUME(gMovesInfo[MOVE_CHARM].effect == EFFECT_ATTACK_DOWN_2);
|
||||
ASSUME(gMovesInfo[MOVE_CHARM].effect == EFFECT_ATTACK_DOWN_2);
|
||||
PLAYER(SPECIES_MEW);
|
||||
OPPONENT(SPECIES_SHELLDER);
|
||||
} WHEN {
|
||||
|
@ -30,8 +29,95 @@ SINGLE_BATTLE_TEST("Body Press uses physical defense stat of target", s16 damage
|
|||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Body Press's damage depends on the user's base Defense instead of its base Attack");
|
||||
TO_DO_BATTLE_TEST("Body Press's damage depends on the user's Defense stat stages");
|
||||
SINGLE_BATTLE_TEST("Body Press's damage depends on the user's base Defense instead of its base Attack", s16 damage)
|
||||
{
|
||||
u32 def, atk;
|
||||
PARAMETRIZE { def = 150; atk = 179; } // Atk is higher
|
||||
PARAMETRIZE { atk = 150; def = 179; } // Atk is lower
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Attack(atk); Defense(def); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_BODY_PRESS); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BODY_PRESS, opponent);
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_GT(results[1].damage, results[0].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Body Press's damage depends on the user's Defense and not Attack stat stages", s16 damage)
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_IRON_DEFENSE; }
|
||||
PARAMETRIZE { move = MOVE_SWORDS_DANCE; }
|
||||
PARAMETRIZE { move = MOVE_CELEBRATE; } // Nothing, stats are default
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_IRON_DEFENSE].effect == EFFECT_DEFENSE_UP_2);
|
||||
ASSUME(gMovesInfo[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Attack(150); Defense(150); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, move); }
|
||||
TURN { MOVE(opponent, MOVE_BODY_PRESS); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BODY_PRESS, opponent);
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_GT(results[0].damage, results[1].damage);
|
||||
EXPECT_EQ(results[1].damage, results[2].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Body Press uses Defense Stat even in Wonder Room", s16 damage)
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_WONDER_ROOM; }
|
||||
PARAMETRIZE { move = MOVE_CELEBRATE; }
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_WONDER_ROOM].effect == EFFECT_WONDER_ROOM);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { SpDefense(50); Defense(150); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, move); }
|
||||
TURN { MOVE(opponent, MOVE_BODY_PRESS); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BODY_PRESS, opponent);
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Body Press uses Special Defense stat Stages in Wonder Room", s16 damage)
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_IRON_DEFENSE; }
|
||||
PARAMETRIZE { move = MOVE_AMNESIA; }
|
||||
PARAMETRIZE { move = MOVE_CELEBRATE; } // Nothing, stats are default
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_IRON_DEFENSE].effect == EFFECT_DEFENSE_UP_2);
|
||||
ASSUME(gMovesInfo[MOVE_AMNESIA].effect == EFFECT_SPECIAL_DEFENSE_UP_2);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { SpDefense(150); Defense(150); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, move); MOVE(player, MOVE_WONDER_ROOM); }
|
||||
TURN { MOVE(opponent, MOVE_BODY_PRESS); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BODY_PRESS, opponent);
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_GT(results[1].damage, results[0].damage);
|
||||
EXPECT_EQ(results[0].damage, results[2].damage);
|
||||
}
|
||||
}
|
||||
|
||||
// Could be split into multiple tests or maybe to separate files based on the modifier?
|
||||
TO_DO_BATTLE_TEST("Body Press's damage is influenced by all other Attack modifiers that are not stat stages");
|
||||
|
|
|
@ -6,40 +6,90 @@ ASSUMPTIONS
|
|||
ASSUME(gMovesInfo[MOVE_ENCORE].effect == EFFECT_ENCORE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 2 turns for player")
|
||||
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for player: Encore used before move")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(opponent, MOVE_ENCORE); MOVE(player, MOVE_CELEBRATE); }
|
||||
// TURN { FORCED_MOVE(player); }
|
||||
TURN { FORCED_MOVE(player); }
|
||||
TURN { FORCED_MOVE(player); }
|
||||
TURN { MOVE(player, MOVE_SPLASH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for player: Encore used after move")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_ENCORE); }
|
||||
TURN { FORCED_MOVE(player); }
|
||||
TURN { FORCED_MOVE(player); }
|
||||
TURN { FORCED_MOVE(player); }
|
||||
TURN { MOVE(player, MOVE_SPLASH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 2 turns for opponent")
|
||||
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for opponent: Encore used before move")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_ENCORE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
// TURN { FORCED_MOVE(opponent); }
|
||||
TURN { FORCED_MOVE(opponent); }
|
||||
TURN { FORCED_MOVE(opponent); }
|
||||
TURN { MOVE(opponent, MOVE_SPLASH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Encore forces consecutive move uses for 3 turns for opponent: Encore used after move")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_ENCORE); }
|
||||
TURN { FORCED_MOVE(opponent); }
|
||||
TURN { FORCED_MOVE(opponent); }
|
||||
TURN { FORCED_MOVE(opponent); }
|
||||
TURN { MOVE(opponent, MOVE_SPLASH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, opponent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,4 +25,25 @@ SINGLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and ac
|
|||
}
|
||||
}
|
||||
|
||||
// Checked so that Pursuit has only 1 PP and it forces the player to use Struggle.
|
||||
SINGLE_BATTLE_TEST("Pursuit becomes a locked move after being used on switch-out while holding a Choice Item")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_CHOICE_BAND].holdEffect == HOLD_EFFECT_CHOICE_BAND);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_CHOICE_BAND); MovesWithPP({MOVE_PURSUIT, 1}, {MOVE_CELEBRATE, 10}, {MOVE_WATER_GUN, 10}, {MOVE_TACKLE, 10}); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { SWITCH(opponent, 1); MOVE(player, MOVE_PURSUIT); }
|
||||
TURN { FORCED_MOVE(player); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, player);
|
||||
HP_BAR(opponent);
|
||||
MESSAGE("2 sent out Wobbuffet!");
|
||||
|
||||
MESSAGE("Wobbuffet used Struggle!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, player);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Baton Pass doesn't cause Pursuit to increase its power or priority");
|
||||
|
|
|
@ -85,6 +85,25 @@ SINGLE_BATTLE_TEST("Relic Song transforms Meloetta if used successfully")
|
|||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Relic Song does not transform Pokemon other than Meloetta")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_RELIC_SONG); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
|
||||
HP_BAR(opponent);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
|
||||
MESSAGE("Wobbuffet transformed!");
|
||||
}
|
||||
} THEN {
|
||||
EXPECT_EQ(player->species, SPECIES_WOBBUFFET);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Relic Song transforms Meloetta twice if used successfully")
|
||||
{
|
||||
GIVEN {
|
||||
|
|
113
test/battle/terrain/starting_terrain.c
Normal file
113
test/battle/terrain/starting_terrain.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
#include "global.h"
|
||||
#include "event_data.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
#if B_VAR_STARTING_STATUS != 0
|
||||
|
||||
SINGLE_BATTLE_TEST("B_VAR_STARTING_STATUS starts a chosen terrain at the beginning of battle and lasts infinitely long")
|
||||
{
|
||||
u16 terrain;
|
||||
|
||||
PARAMETRIZE { terrain = STARTING_STATUS_GRASSY_TERRAIN; }
|
||||
PARAMETRIZE { terrain = STARTING_STATUS_PSYCHIC_TERRAIN; }
|
||||
PARAMETRIZE { terrain = STARTING_STATUS_MISTY_TERRAIN; }
|
||||
PARAMETRIZE { terrain = STARTING_STATUS_ELECTRIC_TERRAIN; }
|
||||
|
||||
VarSet(B_VAR_STARTING_STATUS, terrain);
|
||||
VarSet(B_VAR_STARTING_STATUS_TIMER, 0);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
// More than 5 turns
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
} SCENE {
|
||||
switch (terrain) {
|
||||
case STARTING_STATUS_GRASSY_TERRAIN:
|
||||
MESSAGE("Grass grew to cover the battlefield!");
|
||||
break;
|
||||
case STARTING_STATUS_PSYCHIC_TERRAIN:
|
||||
MESSAGE("The battlefield got weird!");
|
||||
break;
|
||||
case STARTING_STATUS_MISTY_TERRAIN:
|
||||
MESSAGE("Mist swirled about the battlefield!");
|
||||
break;
|
||||
case STARTING_STATUS_ELECTRIC_TERRAIN:
|
||||
MESSAGE("An electric current runs across the battlefield!");
|
||||
break;
|
||||
}
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG);
|
||||
MESSAGE("The weirdness disappeared from the battlefield.");
|
||||
MESSAGE("The electricity disappeared from the battlefield.");
|
||||
MESSAGE("The mist disappeared from the battlefield.");
|
||||
MESSAGE("The grass disappeared from the battlefield.");
|
||||
}
|
||||
} THEN {
|
||||
VarSet(B_VAR_STARTING_STATUS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Terrain started after the one which started the battle lasts only 5 turns")
|
||||
{
|
||||
bool32 viaMove;
|
||||
|
||||
PARAMETRIZE { viaMove = TRUE; }
|
||||
PARAMETRIZE { viaMove = FALSE; }
|
||||
|
||||
VarSet(B_VAR_STARTING_STATUS, STARTING_STATUS_ELECTRIC_TERRAIN);
|
||||
VarSet(B_VAR_STARTING_STATUS_TIMER, 0);
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(viaMove == TRUE ? ABILITY_SHADOW_TAG : ABILITY_GRASSY_SURGE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
// More than 5 turns
|
||||
TURN { MOVE(player, viaMove == TRUE ? MOVE_GRASSY_TERRAIN : MOVE_CELEBRATE); }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
TURN { ; }
|
||||
} SCENE {
|
||||
// Electric Terrain at battle's start
|
||||
MESSAGE("An electric current runs across the battlefield!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG);
|
||||
// Player uses Grassy Terrain
|
||||
if (viaMove) {
|
||||
MESSAGE("Wobbuffet used GrssyTerrain!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GRASSY_TERRAIN, player);
|
||||
MESSAGE("Grass grew to cover the battlefield!");
|
||||
} else {
|
||||
ABILITY_POPUP(player, ABILITY_GRASSY_SURGE);
|
||||
MESSAGE("Grass grew to cover the battlefield!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG);
|
||||
}
|
||||
|
||||
// 5 turns
|
||||
MESSAGE("Wobbuffet used Celebrate!");
|
||||
MESSAGE("Foe Wobbuffet used Celebrate!");
|
||||
|
||||
MESSAGE("Wobbuffet used Celebrate!");
|
||||
MESSAGE("Foe Wobbuffet used Celebrate!");
|
||||
|
||||
MESSAGE("Wobbuffet used Celebrate!");
|
||||
MESSAGE("Foe Wobbuffet used Celebrate!");
|
||||
|
||||
MESSAGE("The grass disappeared from the battlefield.");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG);
|
||||
} THEN {
|
||||
VarSet(B_VAR_STARTING_STATUS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // B_VAR_STARTING_STATUS
|
Loading…
Reference in a new issue