27/04/25 Master to upcoming merge (#6701)
This commit is contained in:
commit
5dfbdf56da
@ -1366,6 +1366,10 @@
|
||||
callnative BS_RestoreAttacker
|
||||
.endm
|
||||
|
||||
.macro jumpifintimidateabilityprevented
|
||||
callnative BS_JumpIfIntimidateAbilityPrevented
|
||||
.endm
|
||||
|
||||
.macro metalburstdamagecalculator failInstr:req
|
||||
callnative BS_CalcMetalBurstDmg
|
||||
.4byte \failInstr
|
||||
@ -1382,6 +1386,10 @@
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
.macro tryintimidatejectpack
|
||||
callnative BS_TryIntimidatEjectpack
|
||||
.endm
|
||||
|
||||
.macro allyswitchswapbattlers
|
||||
callnative BS_AllySwitchSwapBattler
|
||||
.endm
|
||||
|
||||
@ -3197,7 +3197,7 @@ BattleScript_StatDownEnd::
|
||||
BattleScript_MirrorArmorReflect::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
call BattleScript_AbilityPopUp
|
||||
jumpifsubstituteblocks BattleScript_AbilityNoSpecificStatLoss
|
||||
jumpifstatus2 BS_ATTACKER, STATUS2_SUBSTITUTE, BattleScript_MirrorArmorDoesntAffect
|
||||
BattleScript_MirrorArmorReflectStatLoss:
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_MIRROR_ARMOR | STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_MirrorArmorReflectEnd
|
||||
jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_MirrorArmorReflectAnim
|
||||
@ -3211,6 +3211,13 @@ BattleScript_MirrorArmorReflectPrintString:
|
||||
BattleScript_MirrorArmorReflectEnd:
|
||||
return
|
||||
|
||||
BattleScript_MirrorArmorDoesntAffect:
|
||||
swapattackerwithtarget
|
||||
printstring STRINGID_ITDOESNTAFFECT
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
swapattackerwithtarget
|
||||
return
|
||||
|
||||
BattleScript_MirrorArmorReflectWontFall:
|
||||
copybyte gBattlerTarget, gBattlerAttacker @ STRINGID_STATSWONTDECREASE uses target
|
||||
goto BattleScript_MirrorArmorReflectPrintString
|
||||
@ -7719,13 +7726,7 @@ BattleScript_IntimidateLoop:
|
||||
jumpiftargetally BattleScript_IntimidateLoopIncrement
|
||||
jumpifabsent BS_TARGET, BattleScript_IntimidateLoopIncrement
|
||||
jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_IntimidateLoopIncrement
|
||||
.if B_UPDATED_INTIMIDATE >= GEN_8 @These abilties specifically prevent just intimidate, without blocking stat decreases
|
||||
jumpifability BS_TARGET, ABILITY_INNER_FOCUS, BattleScript_IntimidatePrevented
|
||||
jumpifability BS_TARGET, ABILITY_SCRAPPY, BattleScript_IntimidatePrevented
|
||||
jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_IntimidatePrevented
|
||||
jumpifability BS_TARGET, ABILITY_OBLIVIOUS, BattleScript_IntimidatePrevented
|
||||
.endif
|
||||
jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_IntimidateInReverse
|
||||
jumpifintimidateabilityprevented
|
||||
BattleScript_IntimidateEffect:
|
||||
copybyte sBATTLER, gBattlerAttacker
|
||||
setstatchanger STAT_ATK, 1, TRUE
|
||||
@ -7750,9 +7751,10 @@ BattleScript_IntimidateLoopIncrement:
|
||||
destroyabilitypopup
|
||||
restoretarget
|
||||
pause B_WAIT_TIME_MED
|
||||
tryintimidatejectpack
|
||||
end3
|
||||
|
||||
BattleScript_IntimidatePrevented:
|
||||
BattleScript_IntimidatePrevented::
|
||||
copybyte sBATTLER, gBattlerTarget
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_PKMNPREVENTSSTATLOSSWITH
|
||||
@ -7772,7 +7774,7 @@ BattleScript_IntimidateContrary_WontIncrease:
|
||||
printstring STRINGID_TARGETSTATWONTGOHIGHER
|
||||
goto BattleScript_IntimidateEffect_WaitString
|
||||
|
||||
BattleScript_IntimidateInReverse:
|
||||
BattleScript_IntimidateInReverse::
|
||||
copybyte sBATTLER, gBattlerTarget
|
||||
call BattleScript_AbilityPopUpTarget
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@ -9527,7 +9529,7 @@ BattleScript_EjectButtonActivates::
|
||||
printstring STRINGID_EJECTBUTTONACTIVATE
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
removeitem BS_SCRIPTING
|
||||
undodynamax BS_SCRIPTING
|
||||
undodynamax BS_SCRIPTING
|
||||
makeinvisible BS_SCRIPTING
|
||||
openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd
|
||||
copybyte sSAVED_BATTLER, sBATTLER
|
||||
|
||||
@ -174,7 +174,8 @@ struct ProtectStruct
|
||||
u16 eatMirrorHerb:1;
|
||||
u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy
|
||||
u16 usedAllySwitch:1;
|
||||
u16 padding:5;
|
||||
u16 lashOutAffected:1;
|
||||
u16 padding:4;
|
||||
// End of 16-bit bitfield
|
||||
u16 physicalDmg;
|
||||
u16 specialDmg;
|
||||
@ -1272,4 +1273,3 @@ static inline bool32 IsBattlerInvalidForSpreadMove(u32 battlerAtk, u32 battlerDe
|
||||
}
|
||||
|
||||
#endif // GUARD_BATTLE_H
|
||||
|
||||
|
||||
@ -171,6 +171,8 @@ extern const u8 BattleScript_RainDishActivates[];
|
||||
extern const u8 BattleScript_SandstreamActivates[];
|
||||
extern const u8 BattleScript_ShedSkinActivates[];
|
||||
extern const u8 BattleScript_IntimidateActivates[];
|
||||
extern const u8 BattleScript_IntimidatePrevented[];
|
||||
extern const u8 BattleScript_IntimidateInReverse[];
|
||||
extern const u8 BattleScript_DroughtActivates[];
|
||||
extern const u8 BattleScript_TookAttack[];
|
||||
extern const u8 BattleScript_SturdyPreventsOHKO[];
|
||||
|
||||
@ -368,6 +368,7 @@ void ClearPursuitValuesIfSet(u32 battler);
|
||||
void ClearPursuitValues(void);
|
||||
bool32 HasWeatherEffect(void);
|
||||
u32 RestoreWhiteHerbStats(u32 battler);
|
||||
bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef);
|
||||
bool32 HadMoreThanHalfHpNowDoesnt(u32 battler);
|
||||
|
||||
#endif // GUARD_BATTLE_UTIL_H
|
||||
|
||||
@ -335,8 +335,6 @@ static bool32 HandleEndTurnFutureSight(u32 battler)
|
||||
|
||||
if (gWishFutureKnock.futureSightCounter[battler] == gBattleTurnCounter)
|
||||
{
|
||||
struct Pokemon *party;
|
||||
|
||||
if (gWishFutureKnock.futureSightCounter[battler] == gBattleTurnCounter
|
||||
&& gWishFutureKnock.futureSightCounter[BATTLE_PARTNER(battler)] <= gBattleTurnCounter)
|
||||
{
|
||||
@ -357,8 +355,7 @@ static bool32 HandleEndTurnFutureSight(u32 battler)
|
||||
gBattlerAttacker = gWishFutureKnock.futureSightBattlerIndex[battler];
|
||||
gCurrentMove = gWishFutureKnock.futureSightMove[battler];
|
||||
|
||||
party = GetSideParty(GetBattlerSide(gBattlerAttacker));
|
||||
if (&party[gWishFutureKnock.futureSightPartyIndex[gBattlerTarget]] == &party[gBattlerPartyIndexes[gBattlerAttacker]])
|
||||
if (!IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget))
|
||||
SetTypeBeforeUsingMove(gCurrentMove, gBattlerAttacker);
|
||||
|
||||
BattleScriptExecute(BattleScript_MonTookFutureAttack);
|
||||
|
||||
@ -3746,6 +3746,7 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE; // Included here because switches can happen before during set ups (eg. eject pack)
|
||||
struct Pokemon *party = GetBattlerParty(i);
|
||||
struct Pokemon *mon = &party[gBattlerPartyIndexes[i]];
|
||||
if (!IsBattlerAlive(i) || gBattleMons[i].species == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG))
|
||||
@ -4758,6 +4759,8 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h
|
||||
speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
|
||||
else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivates))
|
||||
speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed;
|
||||
else if (ability == ABILITY_UNBURDEN && gDisableStructs[battler].unburdenActive)
|
||||
speed *= 2;
|
||||
|
||||
// stat stages
|
||||
speed *= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][0];
|
||||
@ -4784,8 +4787,6 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h
|
||||
// various effects
|
||||
if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND)
|
||||
speed *= 2;
|
||||
if (gDisableStructs[battler].unburdenActive)
|
||||
speed *= 2;
|
||||
|
||||
// paralysis drop
|
||||
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && ability != ABILITY_QUICK_FEET)
|
||||
@ -4854,7 +4855,6 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move)
|
||||
return priority;
|
||||
}
|
||||
|
||||
// Function for AI with variables provided as arguments to speed the computation time
|
||||
s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2,
|
||||
enum ItemHoldEffect holdEffectBattler1, enum ItemHoldEffect holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2)
|
||||
{
|
||||
@ -5140,6 +5140,7 @@ static void TurnValuesCleanUp(bool8 var0)
|
||||
|
||||
gSpecialStatuses[i].parentalBondState = PARENTAL_BOND_OFF;
|
||||
gBattleStruct->battlerState[i].usedEjectItem = FALSE;
|
||||
gProtectStructs[i].lashOutAffected = FALSE;
|
||||
}
|
||||
|
||||
gSideTimers[B_SIDE_PLAYER].followmeTimer = 0;
|
||||
|
||||
@ -4665,7 +4665,6 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
|
||||
static bool32 CanApplyAdditionalEffect(const struct AdditionalEffect *additionalEffect)
|
||||
{
|
||||
// Self-targeting move effects only apply after the last mon has been hit
|
||||
if (additionalEffect->self
|
||||
&& NumAffectedSpreadMoveTargets() > 1
|
||||
&& GetNextTarget(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), TRUE) != MAX_BATTLERS_COUNT)
|
||||
@ -6374,7 +6373,6 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move
|
||||
gEffectBattler = battlerDef;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MagicianActivates;
|
||||
gSpecialStatuses[battlerAtk].preventLifeOrbDamage = TRUE;
|
||||
effect = TRUE;
|
||||
}
|
||||
break;
|
||||
@ -7356,6 +7354,9 @@ static void Cmd_moveend(void)
|
||||
if (numEjectPackBattlers > 1)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].statFell = FALSE; // restore for every possible eject pack battler
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
u32 battler = battlers[i];
|
||||
@ -7370,7 +7371,6 @@ static void Cmd_moveend(void)
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
|
||||
AI_DATA->ejectPackSwitch = TRUE;
|
||||
gProtectStructs[battler].statFell = FALSE;
|
||||
break; // Only the fastest Eject item activates
|
||||
}
|
||||
}
|
||||
@ -7617,7 +7617,6 @@ static void Cmd_moveend(void)
|
||||
gProtectStructs[gBattlerAttacker].shellTrap = FALSE;
|
||||
gBattleStruct->ateBoost[gBattlerAttacker] = FALSE;
|
||||
gSpecialStatuses[gBattlerAttacker].gemBoost = FALSE;
|
||||
gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage = 0;
|
||||
gSpecialStatuses[gBattlerTarget].berryReduced = FALSE;
|
||||
gSpecialStatuses[gBattlerTarget].distortedTypeMatchups = FALSE;
|
||||
gBattleScripting.moveEffect = 0;
|
||||
@ -8392,6 +8391,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS;
|
||||
gSpecialStatuses[battler].announceNeutralizingGas = TRUE;
|
||||
gDisableStructs[battler].neutralizingGas = TRUE;
|
||||
gBattlerAbility = battler;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_SwitchInAbilityMsgRet;
|
||||
@ -8456,13 +8456,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler)
|
||||
else if (IsBattlerAffectedByHazards(battler, TRUE))
|
||||
{
|
||||
i = GetBattlerAbility(battler);
|
||||
if (!(gBattleMons[battler].status1 & STATUS1_ANY)
|
||||
&& !IS_BATTLER_OF_TYPE(battler, TYPE_STEEL)
|
||||
&& i != ABILITY_IMMUNITY
|
||||
&& i != ABILITY_PURIFYING_SALT
|
||||
&& !IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL)
|
||||
&& !(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD)
|
||||
&& !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
|
||||
if (CanBePoisoned(gBattlerAttacker, battler, i))
|
||||
{
|
||||
if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2)
|
||||
gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON;
|
||||
@ -12664,7 +12658,8 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
}
|
||||
else
|
||||
{
|
||||
gProtectStructs[battler].statFell = TRUE; // Eject pack, lash out
|
||||
gProtectStructs[battler].statFell = TRUE;
|
||||
gProtectStructs[battler].lashOutAffected = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL
|
||||
}
|
||||
}
|
||||
@ -18853,6 +18848,90 @@ void BS_SetSteelsurge(void)
|
||||
}
|
||||
}
|
||||
|
||||
void BS_JumpIfIntimidateAbilityPrevented(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
|
||||
u32 hasAbility = FALSE;
|
||||
u32 ability = GetBattlerAbility(gBattlerTarget);
|
||||
|
||||
switch (ability)
|
||||
{
|
||||
case ABILITY_INNER_FOCUS:
|
||||
case ABILITY_SCRAPPY:
|
||||
case ABILITY_OWN_TEMPO:
|
||||
case ABILITY_OBLIVIOUS:
|
||||
if (B_UPDATED_INTIMIDATE >= GEN_8)
|
||||
{
|
||||
hasAbility = TRUE;
|
||||
gBattlescriptCurrInstr = BattleScript_IntimidatePrevented;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
break;
|
||||
case ABILITY_GUARD_DOG:
|
||||
hasAbility = TRUE;
|
||||
gBattlescriptCurrInstr = BattleScript_IntimidateInReverse;
|
||||
break;
|
||||
default:
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasAbility)
|
||||
{
|
||||
gLastUsedAbility = ability;
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
|
||||
}
|
||||
}
|
||||
|
||||
void BS_TryIntimidatEjectpack(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
|
||||
u32 affectedBattler = 0xFF;
|
||||
u32 battler = BATTLE_OPPOSITE(gBattlerAttacker);
|
||||
u32 partnerBattler = BATTLE_PARTNER(battler);
|
||||
|
||||
bool32 ejectPackBattler = CanEjectPackTrigger(gBattlerAttacker, battler, MOVE_NONE);
|
||||
bool32 ejectPackPartnerBattler = CanEjectPackTrigger(gBattlerAttacker, partnerBattler, MOVE_NONE);
|
||||
|
||||
if (ejectPackBattler && ejectPackPartnerBattler)
|
||||
{
|
||||
u32 battlerSpeed = GetBattlerTotalSpeedStat(battler);
|
||||
u32 partnerbattlerSpeed = GetBattlerTotalSpeedStat(partnerBattler);
|
||||
|
||||
if (battlerSpeed >= partnerbattlerSpeed)
|
||||
affectedBattler = battler;
|
||||
else
|
||||
affectedBattler = partnerBattler;
|
||||
}
|
||||
else if (ejectPackBattler)
|
||||
{
|
||||
affectedBattler = battler;
|
||||
}
|
||||
else if (ejectPackPartnerBattler)
|
||||
{
|
||||
affectedBattler = partnerBattler;
|
||||
}
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
if (affectedBattler != 0xFF)
|
||||
{
|
||||
gProtectStructs[battler].statFell = FALSE;
|
||||
gProtectStructs[partnerBattler].statFell = FALSE;
|
||||
AI_DATA->ejectPackSwitch = TRUE;
|
||||
gBattleScripting.battler = affectedBattler;
|
||||
gLastUsedItem = gBattleMons[affectedBattler].item;
|
||||
RecordItemEffectBattle(affectedBattler, HOLD_EFFECT_EJECT_PACK);
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
|
||||
}
|
||||
}
|
||||
|
||||
void BS_JumpIfCanGigantamax(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
|
||||
|
||||
@ -4599,12 +4599,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& IsBattlerAlive(gBattlerAttacker))
|
||||
{
|
||||
// Prevent Innards Out effect if Future Sight user is currently not on field
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_FUTURE_SIGHT)
|
||||
{
|
||||
if (gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] != gBattlerPartyIndexes[gBattlerAttacker]
|
||||
&& gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] != BATTLE_PARTNER(gBattlerPartyIndexes[gBattlerAttacker]))
|
||||
break;
|
||||
}
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_FUTURE_SIGHT
|
||||
&& IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget))
|
||||
break;
|
||||
|
||||
gBattleScripting.battler = gBattlerTarget;
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = gBattleStruct->moveDamage[gBattlerTarget];
|
||||
@ -5961,6 +5958,9 @@ static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemCaseId caseID, bool32 pe
|
||||
|
||||
static bool32 UnnerveOn(u32 battler, u32 itemId)
|
||||
{
|
||||
if (gBattleScripting.overrideBerryRequirements > 0) // Berries that aren't eaten naturally ignore unnerve
|
||||
return FALSE;
|
||||
|
||||
if (ItemId_GetPocket(itemId) == POCKET_BERRIES && IsUnnerveAbilityOnOpposingSide(battler))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
@ -6934,7 +6934,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
&& (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveDamage[gBattlerTarget]) // Needs the second check in case of Substitute
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& !gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage)
|
||||
&& !IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget))
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 10;
|
||||
if (gBattleStruct->moveDamage[gBattlerAttacker] == 0)
|
||||
@ -7190,9 +7190,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
gBattlescriptCurrInstr = BattleScript_WhiteHerbRet;
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_EJECT_PACK:
|
||||
effect = TryEjectPack(battler, ITEMEFFECT_ON_SWITCH_IN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -8007,7 +8004,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_LASH_OUT:
|
||||
if (gProtectStructs[battlerAtk].statFell)
|
||||
if (gProtectStructs[battlerAtk].lashOutAffected)
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_EXPLOSION:
|
||||
@ -9361,8 +9358,6 @@ static inline s32 DoFutureSightAttackDamageCalcVars(struct DamageCalculationData
|
||||
if (dmg == 0)
|
||||
dmg = 1;
|
||||
|
||||
gSpecialStatuses[battlerAtk].preventLifeOrbDamage = TRUE;
|
||||
|
||||
return dmg;
|
||||
}
|
||||
|
||||
@ -9390,14 +9385,11 @@ static u32 GetWeather(void)
|
||||
return gBattleWeather;
|
||||
}
|
||||
|
||||
static inline bool32 IsFutureSightAttackerInParty(struct DamageCalculationData *damageCalcData)
|
||||
bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef)
|
||||
{
|
||||
if (GetMoveEffect(damageCalcData->move) != EFFECT_FUTURE_SIGHT)
|
||||
return FALSE;
|
||||
|
||||
struct Pokemon *party = GetSideParty(GetBattlerSide(damageCalcData->battlerAtk));
|
||||
return &party[gWishFutureKnock.futureSightPartyIndex[damageCalcData->battlerDef]]
|
||||
!= &party[gBattlerPartyIndexes[damageCalcData->battlerAtk]];
|
||||
struct Pokemon *party = GetSideParty(GetBattlerSide(battlerAtk));
|
||||
return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]]
|
||||
&& &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[BATTLE_PARTNER(gBattlerPartyIndexes[battlerAtk])];
|
||||
}
|
||||
|
||||
s32 CalculateMoveDamage(struct DamageCalculationData *damageCalcData, u32 fixedBasePower)
|
||||
@ -9409,7 +9401,8 @@ s32 CalculateMoveDamage(struct DamageCalculationData *damageCalcData, u32 fixedB
|
||||
GetBattlerAbility(damageCalcData->battlerDef),
|
||||
damageCalcData->updateFlags);
|
||||
|
||||
if (IsFutureSightAttackerInParty(damageCalcData))
|
||||
if (GetMoveEffect(damageCalcData->move) == EFFECT_FUTURE_SIGHT
|
||||
&& IsFutureSightAttackerInParty(damageCalcData->battlerAtk, damageCalcData->battlerDef))
|
||||
return DoFutureSightAttackDamageCalc(damageCalcData, typeEffectivenessMultiplier, GetWeather());
|
||||
|
||||
return DoMoveDamageCalc(damageCalcData, fixedBasePower, typeEffectivenessMultiplier, GetWeather());
|
||||
|
||||
@ -1850,13 +1850,10 @@ u8 CreateObjectGraphicsSpriteWithTag(u16 graphicsId, void (*callback)(struct Spr
|
||||
const struct ObjectEventGraphicsInfo *graphicsInfo = GetObjectEventGraphicsInfo(graphicsId);
|
||||
struct Sprite *sprite;
|
||||
u8 spriteId;
|
||||
bool32 isShiny = graphicsId & OBJ_EVENT_MON_SHINY;
|
||||
|
||||
spriteTemplate = Alloc(sizeof(struct SpriteTemplate));
|
||||
CopyObjectGraphicsInfoToSpriteTemplate(graphicsId, callback, spriteTemplate, &subspriteTables);
|
||||
|
||||
if (isShiny)
|
||||
graphicsId -= SPECIES_SHINY_TAG;
|
||||
|
||||
if (OW_GFX_COMPRESS)
|
||||
{
|
||||
|
||||
@ -1,7 +1,25 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Analytic increases the power of moves by 30% if it's the last one that uses its move");
|
||||
SINGLE_BATTLE_TEST("Analytic increases the power of moves by 30% if it's the last one that uses its move", s16 damage)
|
||||
{
|
||||
u32 speed;
|
||||
|
||||
PARAMETRIZE { speed = 3; }
|
||||
PARAMETRIZE { speed = 1; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_MAGNEMITE) { Ability(ABILITY_ANALYTIC); Speed(speed); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(2); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TACKLE); }
|
||||
} SCENE {
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Analytic takes into account modifications to speeed an priority (Gen 5-8)"); //Eg. Paralysis, Power Weight, Stall
|
||||
TO_DO_BATTLE_TEST("Analytic does not take into account modifications to speeed an priority (Gen 8)"); //Eg. Paralysis, Power Weight, Stall
|
||||
TO_DO_BATTLE_TEST("Analytic takes into account the turn order of what fainted Pokémon would've moved");
|
||||
|
||||
@ -55,3 +55,35 @@ SINGLE_BATTLE_TEST("Comatose may be suppressed if pokemon transformed into a pok
|
||||
else if (move == MOVE_SLEEP_POWDER) { STATUS_ICON(opponent, sleep: TRUE); }
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Comatose pokemon doesn't get poisoned by Toxic Spikes on switch-in")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); }
|
||||
TURN { SWITCH(player, 1); }
|
||||
} SCENE {
|
||||
NOT STATUS_ICON(player, STATUS1_POISON);
|
||||
ABILITY_POPUP(player, ABILITY_COMATOSE);
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Comatose pokemon don't get poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); }
|
||||
OPPONENT(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); }
|
||||
TURN { MOVE(opponent, MOVE_DRAGON_TAIL); }
|
||||
} SCENE {
|
||||
NOT STATUS_ICON(player, STATUS1_POISON);
|
||||
ABILITY_POPUP(player, ABILITY_COMATOSE);
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,3 +45,20 @@ SINGLE_BATTLE_TEST("Immunity prevents Toxic Spikes poison")
|
||||
NOT STATUS_ICON(opponent, poison: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Immunity doesn't prevent pokemon from being poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker, but it cures it immediately")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_DRAGON_TAIL) == EFFECT_HIT_SWITCH_TARGET);
|
||||
ASSUME(GetMoveEffect(MOVE_TOXIC_SPIKES) == EFFECT_TOXIC_SPIKES);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_SNORLAX) { Ability(ABILITY_IMMUNITY); }
|
||||
OPPONENT(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); }
|
||||
TURN { MOVE(opponent, MOVE_DRAGON_TAIL); }
|
||||
} SCENE {
|
||||
STATUS_ICON(player, STATUS1_POISON);
|
||||
NOT HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ DOUBLE_BATTLE_TEST("Intimidate doesn't activate on an empty field in a double ba
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Intimidate and Eject Button force the opponent to Attack")
|
||||
SINGLE_BATTLE_TEST("Intimidate and Eject Button don't force the opponent to Attack")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_EJECT_BUTTON].holdEffect == HOLD_EFFECT_EJECT_BUTTON);
|
||||
@ -365,6 +365,7 @@ DOUBLE_BATTLE_TEST("Intimidate will correctly decrease the attack of the second
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ABILITY_POPUP(playerLeft, ABILITY_PROTOSYNTHESIS);
|
||||
@ -372,7 +373,6 @@ DOUBLE_BATTLE_TEST("Intimidate will correctly decrease the attack of the second
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
}
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -390,3 +390,48 @@ SINGLE_BATTLE_TEST("Intimdate does not lose timing after mega evolution and swit
|
||||
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Intimidate drop down both opposing atk before eject pack has the chance to activate")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
} WHEN {
|
||||
TURN { SWITCH(opponentLeft, 2); SEND_OUT(playerLeft, 2); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Intimidate will not miss timing for competitive")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_MILOTIC) { Ability(ABILITY_COMPETITIVE); }
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
} WHEN {
|
||||
TURN { SWITCH(opponentLeft, 2); SEND_OUT(playerLeft, 2); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
ABILITY_POPUP(playerRight, ABILITY_COMPETITIVE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Magician does not get self-damage recoil after stealing Life Orb")
|
||||
SINGLE_BATTLE_TEST("Magician gets self-damage recoil after stealing Life Orb")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB);
|
||||
@ -16,10 +16,8 @@ SINGLE_BATTLE_TEST("Magician does not get self-damage recoil after stealing Life
|
||||
MESSAGE("Delphox used Tackle!");
|
||||
ABILITY_POPUP(player, ABILITY_MAGICIAN);
|
||||
MESSAGE("Delphox stole the opposing Wobbuffet's Life Orb!");
|
||||
NONE_OF {
|
||||
HP_BAR(player);
|
||||
MESSAGE("Delphox was hurt by the Life Orb!");
|
||||
}
|
||||
HP_BAR(player);
|
||||
MESSAGE("Delphox was hurt by the Life Orb!");
|
||||
// 2nd turn - Life Orb recoil happens now
|
||||
MESSAGE("Delphox used Tackle!");
|
||||
HP_BAR(player);
|
||||
|
||||
@ -102,10 +102,8 @@ SINGLE_BATTLE_TEST("Mirror Armor lowers the Attack of Pokemon with Intimidate")
|
||||
}
|
||||
}
|
||||
|
||||
// Unsure whether this should or should not fail, as Showdown has conflicting information. Needs testing in gen8 games.
|
||||
SINGLE_BATTLE_TEST("Mirror Armor doesn't lower the stats of an attacking Pokemon behind Substitute")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
|
||||
@ -100,3 +100,20 @@ SINGLE_BATTLE_TEST("Purifying Salt user can't be poisoned by Toxic Spikes")
|
||||
EXPECT_EQ(player->status1, STATUS1_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Purifying Salt doesn't prevent pokemon from being poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_DRAGON_TAIL) == EFFECT_HIT_SWITCH_TARGET);
|
||||
ASSUME(GetMoveEffect(MOVE_TOXIC_SPIKES) == EFFECT_TOXIC_SPIKES);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_GARGANACL) { Ability(ABILITY_PURIFYING_SALT); }
|
||||
OPPONENT(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); }
|
||||
TURN { MOVE(opponent, MOVE_DRAGON_TAIL); }
|
||||
} SCENE {
|
||||
STATUS_ICON(player, STATUS1_POISON);
|
||||
HP_BAR(player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +84,6 @@ SINGLE_BATTLE_TEST("Teraform Zero cannot be copied")
|
||||
|
||||
DOUBLE_BATTLE_TEST("Teraform Zero shouldn't cause Neutralizing Gas to show it's popup when trying to activate")
|
||||
{
|
||||
KNOWN_FAILING; // #5010
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_TERAPAGOS_TERASTAL);
|
||||
PLAYER(SPECIES_ABSOL) {Ability(ABILITY_PRESSURE); }
|
||||
@ -95,8 +94,8 @@ DOUBLE_BATTLE_TEST("Teraform Zero shouldn't cause Neutralizing Gas to show it's
|
||||
TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_TERA); }
|
||||
} SCENE {
|
||||
MESSAGE("Terapagos is storing energy!");
|
||||
MESSAGE("Terapagos terastalized into the Stellar type!");
|
||||
MESSAGE("Terapagos terastallized into the Stellar type!");
|
||||
NOT ABILITY_POPUP(playerRight, ABILITY_NEUTRALIZING_GAS);
|
||||
MESSAGE("Terapagos used Celebreate!");
|
||||
MESSAGE("Terapagos used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
||||
101
test/battle/ability/unburden.c
Normal file
101
test/battle/ability/unburden.c
Normal file
@ -0,0 +1,101 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Unburden doubles speed once user uses item")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(ItemId_GetHoldEffect(ITEM_GRASSY_SEED) == HOLD_EFFECT_SEEDS);
|
||||
ASSUME(GetMoveEffect(MOVE_U_TURN) == EFFECT_HIT_ESCAPE);
|
||||
PLAYER(SPECIES_DRIFBLIM) { Ability(ABILITY_UNBURDEN); Item(ITEM_GRASSY_SEED); Speed(5); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(7); }
|
||||
OPPONENT(SPECIES_RILLABOOM) { Speed(7); Ability(ABILITY_GRASSY_SURGE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_U_TURN); SEND_OUT(opponent, 1); }
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_GRASSY_SURGE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
// Turn 2, doubled speed
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Unburden doubles speed once user gets their item knocked off")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_KNOCK_OFF, MOVE_EFFECT_KNOCK_OFF));
|
||||
PLAYER(SPECIES_DRIFBLIM) { Ability(ABILITY_UNBURDEN); Item(ITEM_POTION); Speed(5); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(7); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_KNOCK_OFF); }
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_KNOCKOFF, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
// Turn 2, doubled speed
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Unburden doesn't activate when item is consumed in Neutralizing Gas")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_U_TURN) == EFFECT_HIT_ESCAPE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_KNOCK_OFF, MOVE_EFFECT_KNOCK_OFF));
|
||||
PLAYER(SPECIES_DRIFBLIM) { Ability(ABILITY_UNBURDEN); Item(ITEM_POTION); Speed(5); }
|
||||
OPPONENT(SPECIES_WEEZING) { Speed(7); Ability(ABILITY_NEUTRALIZING_GAS); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(7); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_KNOCK_OFF); }
|
||||
TURN { MOVE(opponent, MOVE_U_TURN); SEND_OUT(opponent, 1); }
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_KNOCKOFF, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
// Turn 2, no speed increase
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, opponent);
|
||||
MESSAGE("The effects of the neutralizing gas wore off!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
// Turn 3, no speed increase
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Unburden doubling speed effect is ignored by Neutralizing Gas")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_U_TURN) == EFFECT_HIT_ESCAPE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_KNOCK_OFF, MOVE_EFFECT_KNOCK_OFF));
|
||||
PLAYER(SPECIES_DRIFBLIM) { Ability(ABILITY_UNBURDEN); Item(ITEM_POTION); Speed(5); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(7); }
|
||||
OPPONENT(SPECIES_WEEZING) { Speed(7); Ability(ABILITY_NEUTRALIZING_GAS); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_KNOCK_OFF); }
|
||||
TURN { MOVE(opponent, MOVE_U_TURN); SEND_OUT(opponent, 1); }
|
||||
TURN { MOVE(opponent, MOVE_U_TURN); SEND_OUT(opponent, 0); }
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_KNOCKOFF, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
// Turn 2, doubled speed
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
|
||||
// Turn 3, no speed increase
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, opponent);
|
||||
MESSAGE("The effects of the neutralizing gas wore off!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
// Turn 4, doubled speed
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
|
||||
}
|
||||
}
|
||||
@ -160,3 +160,74 @@ SINGLE_BATTLE_TEST("Eject Pack will miss timing to switch out user if Eject Butt
|
||||
EXPECT(opponent->species == SPECIES_WYNAUT);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after intimidate")
|
||||
{
|
||||
u32 speed;
|
||||
|
||||
PARAMETRIZE { speed = 1; }
|
||||
PARAMETRIZE { speed = 11; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(speed); Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
OPPONENT(SPECIES_EKANS) { Speed(6); Ability(ABILITY_INTIMIDATE); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
SWITCH(opponentLeft, 2);
|
||||
if (speed == 11)
|
||||
SEND_OUT(playerRight, 2);
|
||||
else
|
||||
SEND_OUT(playerLeft, 2);
|
||||
}
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
if (speed == 11) {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after a move stat drop")
|
||||
{
|
||||
u32 speed;
|
||||
|
||||
PARAMETRIZE { speed = 1; }
|
||||
PARAMETRIZE { speed = 11; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(speed); Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentLeft, MOVE_BUBBLE);
|
||||
if (speed == 11)
|
||||
SEND_OUT(playerRight, 2);
|
||||
else
|
||||
SEND_OUT(playerLeft, 2);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BUBBLE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
if (speed == 11) {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,32 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Aqua Ring recovers 1/16th HP at end of turn");
|
||||
TO_DO_BATTLE_TEST("Aqua Ring can be used under Heal Block but will not heal the user");
|
||||
SINGLE_BATTLE_TEST("Aqua Ring recovers 1/16th HP at end of turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(128); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_AQUA_RING); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_AQUA_RING, player);
|
||||
} THEN {
|
||||
EXPECT(player->hp == 58);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Aqua Ring can be used under Heal Block but will not heal the user")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(128); Speed(50); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_HEAL_BLOCK); MOVE(player, MOVE_AQUA_RING); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_AQUA_RING, player);
|
||||
} THEN {
|
||||
EXPECT(player->hp == 50);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Baton Pass passes Aqua Ring's effect");
|
||||
|
||||
@ -1,7 +1,105 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Attract causes the target to become infatuated with the user if they have opposite genders");
|
||||
TO_DO_BATTLE_TEST("Attract ignores type immunity");
|
||||
TO_DO_BATTLE_TEST("Attract bypasses Substitute");
|
||||
TO_DO_BATTLE_TEST("Attract fails if the target is already infatuated");
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_ATTRACT) == EFFECT_ATTRACT);
|
||||
ASSUME(gSpeciesInfo[SPECIES_NIDOKING].genderRatio == MON_MALE);
|
||||
ASSUME(gSpeciesInfo[SPECIES_NIDOQUEEN].genderRatio == MON_FEMALE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Attract causes the target to become infatuated with the user if they have opposite genders")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_NIDOQUEEN);
|
||||
OPPONENT(SPECIES_NIDOKING);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player);
|
||||
MESSAGE("The opposing Nidoking fell in love!");
|
||||
} THEN {
|
||||
EXPECT(opponent->status2 & STATUS2_INFATUATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Attract ignores type immunity")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_ATTRACT) == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_NIDOQUEEN);
|
||||
OPPONENT(SPECIES_MISDREAVUS) { Gender(MON_MALE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player);
|
||||
MESSAGE("The opposing Misdreavus fell in love!");
|
||||
} THEN {
|
||||
EXPECT(opponent->status2 & STATUS2_INFATUATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Attract bypasses Substitute")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_NIDOQUEEN) { Speed(90); }
|
||||
OPPONENT(SPECIES_NIDOKING) { Speed(100); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUBSTITUTE); }
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player);
|
||||
MESSAGE("The opposing Nidoking fell in love!");
|
||||
} THEN {
|
||||
EXPECT(opponent->status2 & STATUS2_INFATUATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Attract fails if the target is already infatuated")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_NIDOQUEEN);
|
||||
OPPONENT(SPECIES_NIDOKING);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player);
|
||||
MESSAGE("The opposing Nidoking fell in love!");
|
||||
MESSAGE("Nidoqueen used Attract!");
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(opponent->status2 & STATUS2_INFATUATION);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Attract fails when used on a Pokémon of the same gender")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_NIDOQUEEN);
|
||||
OPPONENT(SPECIES_NIDOQUEEN);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Nidoqueen used Attract!");
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(!(opponent->status2 & STATUS2_INFATUATION));
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Attract fails when used on a genderless Pokémon")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_STARMIE].genderRatio == MON_GENDERLESS);
|
||||
PLAYER(SPECIES_NIDOQUEEN);
|
||||
OPPONENT(SPECIES_STARMIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Nidoqueen used Attract!");
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(!(opponent->status2 & STATUS2_INFATUATION));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,130 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Bestow transfers its held item to the target");
|
||||
TO_DO_BATTLE_TEST("Bestow fails if the user has no held item");
|
||||
TO_DO_BATTLE_TEST("Bestow fails if the target already has a held item");
|
||||
TO_DO_BATTLE_TEST("Bestow fails if the target is behind a Substitute");
|
||||
TO_DO_BATTLE_TEST("Bestow fails if the user is holding Mail");
|
||||
TO_DO_BATTLE_TEST("Bestow fails if the user's held item changes its form");
|
||||
TO_DO_BATTLE_TEST("Bestow fails if the user's held item is a Z-Crystal");
|
||||
SINGLE_BATTLE_TEST("Bestow transfers its held item to the target")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BESTOW); }
|
||||
} THEN {
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
EXPECT(opponent->item == ITEM_SITRUS_BERRY);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Bestow fails if the user has no held item")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BESTOW); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Bestow fails if the target already has a held item")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BESTOW); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->item == ITEM_SITRUS_BERRY);
|
||||
EXPECT(opponent->item == ITEM_LUM_BERRY);
|
||||
}
|
||||
}
|
||||
|
||||
#include "mail.h"
|
||||
SINGLE_BATTLE_TEST("Bestow fails if the user is holding Mail")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
|
||||
GIVEN {
|
||||
ASSUME(ItemIsMail(ITEM_ORANGE_MAIL));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ORANGE_MAIL); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BESTOW); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->item == ITEM_ORANGE_MAIL);
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Bestow fails if the user's held item is a Mega Stone")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_BLAZIKEN) { Item(ITEM_BLAZIKENITE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BESTOW); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->item == ITEM_BLAZIKENITE);
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Bestow fails if the user's held item is a Z-Crystal")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(ItemId_GetHoldEffect(ITEM_FIGHTINIUM_Z) == HOLD_EFFECT_Z_CRYSTAL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_FIGHTINIUM_Z); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BESTOW); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->item == ITEM_FIGHTINIUM_Z);
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Bestow fails if the target is behind a Substitute")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); Speed(50); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_BESTOW); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->item == ITEM_SITRUS_BERRY);
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Bestow fails if the user's held item changes its form")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_GIRATINA_ORIGIN) { Item(ITEM_GRISEOUS_ORB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BESTOW); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->item == ITEM_GRISEOUS_ORB);
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,112 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("Captivate decreases the target's Sp. Attack if they're opposite gender from the user");
|
||||
TO_DO_BATTLE_TEST("Captivate fails if the target and user share gender");
|
||||
TO_DO_BATTLE_TEST("Captivate fails if the target is genderless");
|
||||
TO_DO_BATTLE_TEST("Captivate fails if the user is genderless");
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_CAPTIVATE) == EFFECT_CAPTIVATE);
|
||||
ASSUME(gSpeciesInfo[SPECIES_NIDOKING].genderRatio == MON_MALE);
|
||||
ASSUME(gSpeciesInfo[SPECIES_NIDOQUEEN].genderRatio == MON_FEMALE);
|
||||
ASSUME(gSpeciesInfo[SPECIES_STARMIE].genderRatio == MON_GENDERLESS);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Captivate decreases the target's Sp. Attack if they're opposite gender from the user")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_NIDOQUEEN);
|
||||
OPPONENT(SPECIES_NIDOKING);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CAPTIVATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CAPTIVATE, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("The opposing Nidoking's Sp. Atk harshly fell!");
|
||||
} THEN {
|
||||
EXPECT(opponent->statStages[STAT_SPATK] == 4);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Captivate fails if the target and user share gender")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_NIDOKING);
|
||||
OPPONENT(SPECIES_NIDOKING);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CAPTIVATE); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(opponent->statStages[STAT_SPATK] == 6);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Captivate fails if the target is genderless")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_NIDOQUEEN);
|
||||
OPPONENT(SPECIES_STARMIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CAPTIVATE); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(opponent->statStages[STAT_SPATK] == 6);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Captivate fails if the user is genderless")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_STARMIE);
|
||||
OPPONENT(SPECIES_NIDOQUEEN);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CAPTIVATE); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(opponent->statStages[STAT_SPATK] == 6);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Captivate fails if both the user and the opponent are genderless")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_STARMIE);
|
||||
OPPONENT(SPECIES_STARMIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CAPTIVATE); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(opponent->statStages[STAT_SPATK] == 6);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Attract fails when used by a genderless Pokémon")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_STARMIE);
|
||||
OPPONENT(SPECIES_NIDOQUEEN);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Starmie used Attract!");
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(!(opponent->status2 & STATUS2_INFATUATION));
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Attract fails if both the user and the target are genderless")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_STARMIE);
|
||||
OPPONENT(SPECIES_STARMIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ATTRACT); }
|
||||
} SCENE {
|
||||
MESSAGE("Starmie used Attract!");
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(!(opponent->status2 & STATUS2_INFATUATION));
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,48 @@ AI_DOUBLE_BATTLE_TEST("AI prefers Entrainment'ing good abilities onto partner wi
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Entrainment changes the target's Ability to match the user's");
|
||||
TO_DO_BATTLE_TEST("Entrainment fails if the user's ability has cantBeCopied flag");
|
||||
TO_DO_BATTLE_TEST("Entrainment fails if the targets's ability has cantBeOverwritten flag");
|
||||
SINGLE_BATTLE_TEST("Entrainment changes the target's Ability to match the user's")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_SHADOW_TAG); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ENTRAINMENT); }
|
||||
} THEN {
|
||||
EXPECT(opponent->ability == ABILITY_TELEPATHY);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Entrainment fails if the user's ability has cantBeCopied flag")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gAbilitiesInfo[ABILITY_MULTITYPE].cantBeCopied);
|
||||
PLAYER(SPECIES_ARCEUS) { Ability(ABILITY_MULTITYPE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_SHADOW_TAG); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ENTRAINMENT); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->ability == ABILITY_MULTITYPE);
|
||||
EXPECT(opponent->ability == ABILITY_SHADOW_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Entrainment fails if the target's ability has cantBeOverwritten flag")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gAbilitiesInfo[ABILITY_MULTITYPE].cantBeOverwritten);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); }
|
||||
OPPONENT(SPECIES_ARCEUS) { Ability(ABILITY_MULTITYPE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ENTRAINMENT); }
|
||||
} SCENE {
|
||||
MESSAGE("But it failed!");
|
||||
} THEN {
|
||||
EXPECT(player->ability == ABILITY_TELEPATHY);
|
||||
EXPECT(opponent->ability == ABILITY_MULTITYPE);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Entrainment fails on Dynamaxed Pokémon");
|
||||
|
||||
@ -133,3 +133,18 @@ SINGLE_BATTLE_TEST("Tanga Berry activates before Bug Bite")
|
||||
EXPECT_EQ(player->item, ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Bug Bite ignores Unnerve")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_TYRANITAR) { Ability(ABILITY_UNNERVE); Item(ITEM_ORAN_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BUG_BITE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BUG_BITE, player);
|
||||
HP_BAR(player);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->item, ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user