Merge branch 'RHH/master' into RHH/upcoming

This commit is contained in:
Eduardo Quezada 2023-10-02 14:11:24 -03:00
commit ca81aba3b6
14 changed files with 374 additions and 44 deletions

View file

@ -6892,7 +6892,6 @@ BattleScript_RoarSuccessSwitch::
BattleScript_RoarSuccessSwitch_Ret:
swapattackerwithtarget @ continuation of RedCardActivates
restoretarget
removeitem BS_TARGET
setbyte sSWITCH_CASE, B_SWITCH_NORMAL
return
@ -8538,6 +8537,7 @@ BattleScript_IntimidateLoop:
jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_IntimidateInReverse
BattleScript_IntimidateEffect:
copybyte sBATTLER, gBattlerAttacker
setstatchanger STAT_ATK, 1, TRUE
statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_IntimidateLoopIncrement
setgraphicalstatchangevalues
jumpifability BS_TARGET, ABILITY_CONTRARY, BattleScript_IntimidateContrary
@ -10170,6 +10170,7 @@ BattleScript_RedCardActivates::
swapattackerwithtarget
jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_ROOTED, BattleScript_RedCardIngrain
jumpifability BS_EFFECT_BATTLER, ABILITY_SUCTION_CUPS, BattleScript_RedCardSuctionCups
removeitem BS_SCRIPTING
setbyte sSWITCH_CASE, B_SWITCH_RED_CARD
forcerandomswitch BattleScript_RedCardEnd
@ changes the current battle script. the rest happens in BattleScript_RoarSuccessSwitch_Ret, if switch is successful
@ -10340,6 +10341,8 @@ BattleScript_CouldntFullyProtect::
BattleScript_BerserkGeneRet::
BattleScript_BerserkGeneRet_Anim:
savetarget
copybyte gBattlerTarget, sBATTLER
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse
setgraphicalstatchangevalues
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
@ -10362,6 +10365,7 @@ BattleScript_BerserkGeneRet_OwnTempoPrevents:
printstring STRINGID_PKMNPREVENTSCONFUSIONWITH
waitmessage B_WAIT_TIME_LONG
BattleScript_BerserkGeneRet_End:
restoretarget
removeitem BS_SCRIPTING
end3

View file

@ -99,6 +99,10 @@ struct DisableStruct
u8 tarShot:1;
u8 octolock:1;
u8 cudChew:1;
u8 spikesDone:1;
u8 toxicSpikesDone:1;
u8 stickyWebDone:1;
u8 stealthRockDone:1;
};
struct ProtectStruct

View file

@ -2,7 +2,7 @@
#define GUARD_CONFIG_ITEM_H
// Item config
#define I_SHINY_CHARM_REROLLS 3 // Amount of re-rolls if the player has the Shiny Charm. Set to 0 to disable Shiny Charm's effects.
#define I_SHINY_CHARM_ADDITIONAL_ROLLS 2 // Amount of additional shiny rolls if the player has the Shiny Charm. Set it to 0 to disable Shiny Charm's effects.
#define I_KEY_FOSSILS GEN_LATEST // In Gen4+, all Gen 3 fossils became regular items.
#define I_KEY_ESCAPE_ROPE GEN_LATEST // In Gen8, Escape Rope became a Key Item. Keep in mind, this will make it free to buy in marts.
#define I_HEALTH_RECOVERY GEN_LATEST // In Gen7+, certain healing items recover a different amount of HP than they used to.

View file

@ -225,15 +225,13 @@
#define SIDE_STATUS_SAFEGUARD (1 << 5)
#define SIDE_STATUS_FUTUREATTACK (1 << 6)
#define SIDE_STATUS_MIST (1 << 8)
#define SIDE_STATUS_SPIKES_DAMAGED (1 << 9)
// (1 << 9) previously was SIDE_STATUS_SPIKES_DAMAGED
#define SIDE_STATUS_TAILWIND (1 << 10)
#define SIDE_STATUS_AURORA_VEIL (1 << 11)
#define SIDE_STATUS_LUCKY_CHANT (1 << 12)
#define SIDE_STATUS_TOXIC_SPIKES (1 << 13)
#define SIDE_STATUS_STEALTH_ROCK (1 << 14)
#define SIDE_STATUS_STEALTH_ROCK_DAMAGED (1 << 15)
#define SIDE_STATUS_TOXIC_SPIKES_DAMAGED (1 << 16)
#define SIDE_STATUS_STICKY_WEB_DAMAGED (1 << 17)
// Missing flags previously were SIDE_STATUS_TOXIC_SPIKES_DAMAGED, SIDE_STATUS_STEALTH_ROCK_DAMAGED, SIDE_STATUS_STICKY_WEB_DAMAGED
#define SIDE_STATUS_QUICK_GUARD (1 << 18)
#define SIDE_STATUS_WIDE_GUARD (1 << 19)
#define SIDE_STATUS_CRAFTY_SHIELD (1 << 20)

View file

@ -553,7 +553,7 @@ static const u8 sText_ShieldedFromCriticalHits[] = _("The {B_CURRENT_MOVE} shiel
static const u8 sText_SwitchedAtkAndSpAtk[] = _("{B_ATK_NAME_WITH_PREFIX} switched all its\nchanges to its Attack and\pSp. Atk with the target!");
static const u8 sText_SwitchedDefAndSpDef[] = _("{B_ATK_NAME_WITH_PREFIX} switched all its\nchanges to its Defense and\pSp. Def with the target!");
static const u8 sText_PkmnAcquiredAbility[] = _("{B_DEF_NAME_WITH_PREFIX} acquired\n{B_DEF_ABILITY}!");
static const u8 sText_PoisonSpikesScattered[] = _("Poison Spikes were scattered all\naround the opposing team's feet!");
static const u8 sText_PoisonSpikesScattered[] = _("Poison Spikes were scattered all\naround {B_DEF_TEAM2} team's feet!");
static const u8 sText_PkmnSwitchedStatChanges[] = _("{B_ATK_NAME_WITH_PREFIX} switched stat changes\nwith the target!");
static const u8 sText_PkmnSurroundedWithVeilOfWater[] = _("{B_ATK_NAME_WITH_PREFIX} surrounded itself\nwith a veil of water!");
static const u8 sText_PkmnLevitatedOnElectromagnetism[] = _("{B_ATK_NAME_WITH_PREFIX} levitated on\nelectromagnetism!");
@ -627,7 +627,7 @@ static const u8 sText_MagicBounceActivates[] = _("The {B_DEF_NAME_WITH_PREFIX} b
static const u8 sText_ProteanTypeChange[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} transformed\nit into the {B_BUFF1} type!");
static const u8 sText_SymbiosisItemPass[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} passed its {B_LAST_ITEM}\nto {B_ATK_NAME_WITH_PREFIX} through {B_LAST_ABILITY}!");
static const u8 sText_StealthRockDmg[] = _("Pointed stones dug into\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}!");
static const u8 sText_ToxicSpikesAbsorbed[] = _("The poison spikes disappeared\nfrom around the opposing team's feet!");
static const u8 sText_ToxicSpikesAbsorbed[] = _("The poison spikes disappeared\nfrom around {B_DEF_TEAM2} team's feet!");
static const u8 sText_ToxicSpikesPoisoned[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} was poisoned!");
static const u8 sText_StickyWebSwitchIn[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} was\ncaught in a Sticky Web!");
static const u8 sText_HealingWishCameTrue[] = _("The healing wish came true\nfor {B_ATK_NAME_WITH_PREFIX}!");

View file

@ -3769,7 +3769,6 @@ static void Cmd_tryfaintmon(void)
{
BattleScriptPop();
gBattlescriptCurrInstr = cmd->instr;
gSideStatuses[GetBattlerSide(battler)] &= ~(SIDE_STATUS_SPIKES_DAMAGED | SIDE_STATUS_TOXIC_SPIKES_DAMAGED | SIDE_STATUS_STEALTH_ROCK_DAMAGED | SIDE_STATUS_STICKY_WEB_DAMAGED);
}
else
{
@ -6886,7 +6885,7 @@ static void Cmd_switchineffects(void)
gBattleStruct->storedLunarDance &= ~(gBitTable[battler]);
}
}
else if (!(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SPIKES_DAMAGED)
else if (!(gDisableStructs[battler].spikesDone)
&& (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SPIKES)
&& GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD
&& IsBattlerAffectedByHazards(battler, FALSE)
@ -6897,25 +6896,25 @@ static void Cmd_switchineffects(void)
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gSideStatuses[GetBattlerSide(battler)] |= SIDE_STATUS_SPIKES_DAMAGED;
gDisableStructs[battler].spikesDone = TRUE;
SetDmgHazardsBattlescript(battler, B_MSG_PKMNHURTBYSPIKES);
}
else if (!(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STEALTH_ROCK_DAMAGED)
else if (!(gDisableStructs[battler].stealthRockDone)
&& (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STEALTH_ROCK)
&& IsBattlerAffectedByHazards(battler, FALSE)
&& GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD)
{
gSideStatuses[GetBattlerSide(battler)] |= SIDE_STATUS_STEALTH_ROCK_DAMAGED;
gDisableStructs[battler].stealthRockDone = TRUE;
gBattleMoveDamage = GetStealthHazardDamage(gBattleMoves[MOVE_STEALTH_ROCK].type, battler);
if (gBattleMoveDamage != 0)
SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG);
}
else if (!(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TOXIC_SPIKES_DAMAGED)
else if (!(gDisableStructs[battler].toxicSpikesDone)
&& (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TOXIC_SPIKES)
&& IsBattlerGrounded(battler))
{
gSideStatuses[GetBattlerSide(battler)] |= SIDE_STATUS_TOXIC_SPIKES_DAMAGED;
gDisableStructs[battler].toxicSpikesDone = TRUE;
if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) // Absorb the toxic spikes.
{
gSideStatuses[GetBattlerSide(battler)] &= ~SIDE_STATUS_TOXIC_SPIKES;
@ -6946,12 +6945,12 @@ static void Cmd_switchineffects(void)
}
}
}
else if (!(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STICKY_WEB_DAMAGED)
else if (!(gDisableStructs[battler].stickyWebDone)
&& (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STICKY_WEB)
&& IsBattlerAffectedByHazards(battler, FALSE)
&& IsBattlerGrounded(battler))
{
gSideStatuses[GetBattlerSide(battler)] |= SIDE_STATUS_STICKY_WEB_DAMAGED;
gDisableStructs[battler].stickyWebDone = TRUE;
gBattleScripting.battler = battler;
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
BattleScriptPushCursor();
@ -6990,7 +6989,10 @@ static void Cmd_switchineffects(void)
return;
}
gSideStatuses[GetBattlerSide(battler)] &= ~(SIDE_STATUS_SPIKES_DAMAGED | SIDE_STATUS_TOXIC_SPIKES_DAMAGED | SIDE_STATUS_STEALTH_ROCK_DAMAGED | SIDE_STATUS_STICKY_WEB_DAMAGED);
gDisableStructs[battler].stickyWebDone = FALSE;
gDisableStructs[battler].spikesDone = FALSE;
gDisableStructs[battler].toxicSpikesDone = FALSE;
gDisableStructs[battler].stealthRockDone = FALSE;
for (i = 0; i < gBattlersCount; i++)
{
@ -10782,8 +10784,9 @@ static void Cmd_setprotectlike(void)
bool32 fail = TRUE;
bool32 notLastTurn = TRUE;
u32 lastMove = gLastResultingMoves[gBattlerAttacker];
if (!gBattleMoves[gLastResultingMoves[gBattlerAttacker]].protectionMove)
if (lastMove == MOVE_UNAVAILABLE || !(gBattleMoves[lastMove].protectionMove))
gDisableStructs[gBattlerAttacker].protectUses = 0;
if (gCurrentTurnActionNumber == (gBattlersCount - 1))

View file

@ -3488,7 +3488,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
{
u32 totalRerolls = 0;
if (CheckBagHasItem(ITEM_SHINY_CHARM, 1))
totalRerolls += I_SHINY_CHARM_REROLLS;
totalRerolls += I_SHINY_CHARM_ADDITIONAL_ROLLS;
if (LURE_STEP_COUNT != 0)
totalRerolls += 1;

View file

@ -6,7 +6,7 @@ ASSUMPTIONS
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
}
SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated", s16 damage)
SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a single battle", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_CONTRARY; }
@ -30,6 +30,52 @@ SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated", s16 damage)
}
}
DOUBLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a double battle", s16 damageLeft, s16 damageRight)
{
u32 abilityLeft, abilityRight;
PARAMETRIZE { abilityLeft = ABILITY_CONTRARY; abilityRight = ABILITY_CONTRARY; }
PARAMETRIZE { abilityLeft = ABILITY_TANGLED_FEET; abilityRight = ABILITY_TANGLED_FEET; }
PARAMETRIZE { abilityLeft = ABILITY_CONTRARY; abilityRight = ABILITY_TANGLED_FEET; }
PARAMETRIZE { abilityLeft = ABILITY_TANGLED_FEET; abilityRight = ABILITY_CONTRARY; }
GIVEN {
PLAYER(SPECIES_MIGHTYENA) { Ability(ABILITY_INTIMIDATE); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SPINDA) { Ability(abilityLeft); }
OPPONENT(SPECIES_SPINDA) { Ability(abilityRight); }
} WHEN {
TURN { MOVE(opponentLeft, MOVE_TACKLE, target: playerLeft); MOVE(opponentRight, MOVE_TACKLE, target: playerRight); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
if (abilityLeft == ABILITY_CONTRARY) {
ABILITY_POPUP(opponentLeft, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("Foe Spinda's Attack rose!");
} else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
MESSAGE("Mightyena's Intimidate cuts Foe Spinda's attack!");
}
if (abilityRight == ABILITY_CONTRARY) {
ABILITY_POPUP(opponentRight, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
MESSAGE("Foe Spinda's Attack rose!");
} else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
MESSAGE("Mightyena's Intimidate cuts Foe Spinda's attack!");
}
HP_BAR(playerLeft, captureDamage: &results[i].damageLeft);
HP_BAR(playerRight, captureDamage: &results[i].damageRight);
} THEN {
EXPECT_EQ(opponentLeft->statStages[STAT_ATK], (abilityLeft == ABILITY_CONTRARY) ? DEFAULT_STAT_STAGE+1 : DEFAULT_STAT_STAGE-1);
EXPECT_EQ(opponentRight->statStages[STAT_ATK], (abilityRight == ABILITY_CONTRARY) ? DEFAULT_STAT_STAGE+1 : DEFAULT_STAT_STAGE-1);
}
FINALLY {
EXPECT_MUL_EQ(results[1].damageLeft, Q_4_12(2.25), results[0].damageLeft);
EXPECT_MUL_EQ(results[1].damageRight, Q_4_12(2.25), results[0].damageRight);
}
}
SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normally lower them: Overheat", s16 damageBefore, s16 damageAfter)
{
u32 ability;

View file

@ -6,18 +6,18 @@ ASSUMPTIONS
ASSUME(gItems[ITEM_BERSERK_GENE].holdEffect == HOLD_EFFECT_BERSERK_GENE);
}
SINGLE_BATTLE_TEST("Berserk Gene sharply raises attack at the start of battle", s16 damage)
SINGLE_BATTLE_TEST("Berserk Gene sharply raises attack at the start of a single battle", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
u16 item;
PARAMETRIZE { item = ITEM_NONE; }
PARAMETRIZE { item = ITEM_BERSERK_GENE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); }
PLAYER(SPECIES_WOBBUFFET) { Item(item); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, WITH_RNG(RNG_CONFUSION, FALSE)); }
} SCENE {
if (useItem)
if (item == ITEM_BERSERK_GENE)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
@ -30,20 +30,46 @@ SINGLE_BATTLE_TEST("Berserk Gene sharply raises attack at the start of battle",
}
}
DOUBLE_BATTLE_TEST("Berserk Gene sharply raises attack at the start of a double battle", s16 damage)
{
u16 item;
PARAMETRIZE { item = ITEM_NONE; }
PARAMETRIZE { item = ITEM_BERSERK_GENE; }
GIVEN {
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET) { Item(item); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerRight, MOVE_TACKLE, target:opponentLeft, WITH_RNG(RNG_CONFUSION, FALSE)); }
} SCENE {
if (item == ITEM_BERSERK_GENE)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, playerRight);
MESSAGE("Wobbuffet became confused!");
}
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Berserk Gene activates on switch in", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
u16 item;
PARAMETRIZE { item = ITEM_NONE; }
PARAMETRIZE { item = ITEM_BERSERK_GENE; }
GIVEN {
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); }
PLAYER(SPECIES_WOBBUFFET) { Item(item); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { SWITCH(player, 1); }
TURN { MOVE(player, MOVE_TACKLE, WITH_RNG(RNG_CONFUSION, FALSE)); }
} SCENE {
if (useItem)
if (item == ITEM_BERSERK_GENE)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
@ -56,20 +82,20 @@ SINGLE_BATTLE_TEST("Berserk Gene activates on switch in", s16 damage)
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not confuse a Pokemon with Own Tempo but still raises attack sharply", s16 damage)
SINGLE_BATTLE_TEST("Berserk Gene does not confuse a Pokemon with Own Tempo but still raises attack sharply in a single battle", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
u16 item;
PARAMETRIZE { item = ITEM_NONE; }
PARAMETRIZE { item = ITEM_BERSERK_GENE; }
GIVEN {
PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_OWN_TEMPO); if (useItem) Item(ITEM_BERSERK_GENE); }
PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_OWN_TEMPO); Item(item); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
if (useItem)
if (item == ITEM_BERSERK_GENE)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Slowbro sharply rose!");
@ -83,6 +109,45 @@ SINGLE_BATTLE_TEST("Berserk Gene does not confuse a Pokemon with Own Tempo but s
}
}
DOUBLE_BATTLE_TEST("Berserk Gene does not confuse a Pokemon with Own Tempo but still raises attack sharply in a double battle", s16 damage)
{
u16 item;
bool8 positionLeft = FALSE;
PARAMETRIZE { item = ITEM_NONE; }
PARAMETRIZE { item = ITEM_BERSERK_GENE; positionLeft = TRUE; }
PARAMETRIZE { item = ITEM_BERSERK_GENE; positionLeft = FALSE; }
GIVEN {
if (positionLeft) {
PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_OWN_TEMPO); Item(item); }
PLAYER(SPECIES_WOBBUFFET);
} else {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_OWN_TEMPO); Item(item); }
}
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE((positionLeft != 0) ? playerLeft : playerRight, MOVE_TACKLE, target: opponentLeft);
}
} SCENE {
if (item == ITEM_BERSERK_GENE)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, (positionLeft != 0) ? playerLeft : playerRight);
MESSAGE("Using Berserk Gene, the Attack of Slowbro sharply rose!");
ABILITY_POPUP((positionLeft != 0) ? playerLeft : playerRight, ABILITY_OWN_TEMPO);
MESSAGE("Slowbro's Own Tempo prevents confusion!");
}
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
NOT MESSAGE("Slowbro became confused!");
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[2].damage);
EXPECT_EQ(((positionLeft != 0) ? playerLeft : playerRight)->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not confuse on Misty Terrain but still raises attack sharply")
{
GIVEN {

View file

@ -186,16 +186,16 @@ SINGLE_BATTLE_TEST("Berry hold effect cures status if a pokemon enters a battle"
}
}
SINGLE_BATTLE_TEST("Pokemon can be further poisoned with Toxic spikes after a status healing hold effect was previously used")
SINGLE_BATTLE_TEST("Opponent Pokemon can be further poisoned with Toxic spikes after a status healing hold effect was previously used")
{
u16 item;
PARAMETRIZE { item = ITEM_PECHA_BERRY; }
PARAMETRIZE { item = ITEM_LUM_BERRY; }
KNOWN_FAILING;
GIVEN {
ASSUME(gItems[ITEM_PECHA_BERRY].holdEffect == HOLD_EFFECT_CURE_PSN);
ASSUME(gItems[ITEM_LUM_BERRY].holdEffect == HOLD_EFFECT_CURE_STATUS);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT) { Item(item); }
@ -204,12 +204,64 @@ SINGLE_BATTLE_TEST("Pokemon can be further poisoned with Toxic spikes after a st
TURN { SWITCH(opponent, 1); }
TURN { SWITCH(opponent, 0); }
} SCENE {
MESSAGE("Wobbuffet used Toxic Spikes!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, player);
MESSAGE("Poison Spikes were scattered all around the opposing team's feet!");
// 1st switch-in
MESSAGE("2 sent out Wynaut!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
STATUS_ICON(opponent, poison: TRUE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
if (item == ITEM_PECHA_BERRY) {
MESSAGE("Foe Wynaut's Pecha Berry cured poison!");
} else {
MESSAGE("Foe Wynaut's Lum Berry cured its poison problem!");
}
STATUS_ICON(opponent, poison: FALSE);
// 2nd switch-in
MESSAGE("2 sent out Wobbuffet!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
STATUS_ICON(opponent, poison: TRUE);
}
}
// Basically same as above, but with the sides reversed.
SINGLE_BATTLE_TEST("Player Pokemon can be further poisoned with Toxic spikes after a status healing hold effect was previously used")
{
u16 item;
PARAMETRIZE { item = ITEM_PECHA_BERRY; }
PARAMETRIZE { item = ITEM_LUM_BERRY; }
GIVEN {
ASSUME(gItems[ITEM_PECHA_BERRY].holdEffect == HOLD_EFFECT_CURE_PSN);
ASSUME(gItems[ITEM_LUM_BERRY].holdEffect == HOLD_EFFECT_CURE_STATUS);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET) {Item(item); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); }
TURN { SWITCH(player, 1); }
TURN { SWITCH(player, 2); }
} SCENE {
MESSAGE("Foe Wobbuffet used Toxic Spikes!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent);
MESSAGE("Poison Spikes were scattered all around your team's feet!");
// 1st switch-in
MESSAGE("Go! Wobbuffet!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, player);
STATUS_ICON(player, poison: TRUE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
if (item == ITEM_PECHA_BERRY) {
MESSAGE("Wobbuffet's Pecha Berry cured poison!");
} else {
MESSAGE("Wobbuffet's Lum Berry cured its poison problem!");
}
STATUS_ICON(player, poison: FALSE);
// 2nd switch-in
MESSAGE("Go! Wynaut!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, player);
STATUS_ICON(player, poison: TRUE);
}
}

View file

@ -22,6 +22,8 @@ SINGLE_BATTLE_TEST("Red Card switches the attacker with a random non-fainted rep
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
MESSAGE("Foe Bulbasaur was dragged out!");
} THEN {
EXPECT(player->item == ITEM_NONE);
}
}
@ -43,6 +45,8 @@ DOUBLE_BATTLE_TEST("Red Card switches the target with a random non-battler, non-
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
MESSAGE("Foe Bulbasaur was dragged out!");
} THEN {
EXPECT(playerLeft->item == ITEM_NONE);
}
}
@ -61,6 +65,8 @@ SINGLE_BATTLE_TEST("Red Card does not activate if holder faints")
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
}
} THEN {
EXPECT(player->item == ITEM_NONE);
}
}
@ -78,6 +84,8 @@ SINGLE_BATTLE_TEST("Red Card does not activate if target is behind a Substitute"
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
}
} THEN {
EXPECT(player->item == ITEM_RED_CARD); // Not activated, so still has the item.
}
}
@ -95,6 +103,8 @@ SINGLE_BATTLE_TEST("Red Card activates after the last hit of a multi-hit move")
HP_BAR(player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
} THEN {
EXPECT(player->item == ITEM_NONE);
}
}
@ -111,6 +121,8 @@ SINGLE_BATTLE_TEST("Red Card does not activate if no replacements")
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
}
} THEN {
EXPECT(player->item == ITEM_RED_CARD); // Not activated, so still has the item.
}
}
@ -128,6 +140,8 @@ SINGLE_BATTLE_TEST("Red Card does not activate if replacements fainted")
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
}
} THEN {
EXPECT(player->item == ITEM_RED_CARD); // Not activated, so still has the item.
}
}
@ -145,6 +159,8 @@ SINGLE_BATTLE_TEST("Red Card does not activate if knocked off")
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
}
} THEN {
EXPECT(player->item == ITEM_NONE);
}
}
@ -173,6 +189,8 @@ SINGLE_BATTLE_TEST("Red Card does not activate if stolen by a move")
MESSAGE("Wobbuffet held up its Red Card against Foe Wobbuffet!");
}
}
} THEN {
EXPECT(player->item == ITEM_NONE);
}
}
@ -201,6 +219,8 @@ SINGLE_BATTLE_TEST("Red Card does not activate if stolen by Magician")
MESSAGE("Wobbuffet held up its Red Card against Foe Fennekin!");
}
}
} THEN {
EXPECT(player->item == ITEM_NONE);
}
}
@ -229,6 +249,9 @@ DOUBLE_BATTLE_TEST("Red Card activates for only the fastest target")
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
MESSAGE("Wynaut held up its Red Card against Foe Wynaut!");
MESSAGE("Foe Wobbuffet was dragged out!");
} THEN {
EXPECT(playerLeft->item == ITEM_NONE);
EXPECT(playerRight->item == ITEM_NONE);
}
}
@ -377,4 +400,36 @@ SINGLE_BATTLE_TEST("Red Card activates before Emergency Exit")
}
}
SINGLE_BATTLE_TEST("Red Card is consumed after dragged out replacement has its Speed lowered by Sticky Web")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STICKY_WEB].effect == EFFECT_STICKY_WEB);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT) { Moves(MOVE_TACKLE); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
} WHEN {
TURN { MOVE(opponent, MOVE_STICKY_WEB); }
TURN { MOVE(player, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
// 1st turn Sticky Web
ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponent);
// 2nd turn Red Card activation
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
MESSAGE("Foe Wobbuffet held up its Red Card against Wobbuffet!");
MESSAGE("Wynaut was dragged out!");
MESSAGE("Wynaut was caught in a Sticky Web!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
// 3rd turn, Red Card was consumed, it can't trigger again
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
MESSAGE("Foe Wobbuffet held up its Red Card against Wynaut!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
}
} THEN {
EXPECT(opponent->item == ITEM_NONE);
}
}
// SINGLE_BATTLE_TEST("Red Card activates but fails if the attacker has Dynamaxed")

View file

@ -0,0 +1,71 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_HEADBUTT].effect == EFFECT_FLINCH_HIT);
}
SINGLE_BATTLE_TEST("Headbutt flinches the target if attacker is faster")
{
bool8 isFaster;
u16 spdPlayer, spdOpponent;
PARAMETRIZE { isFaster = TRUE; spdPlayer = 10; spdOpponent = 5; }
PARAMETRIZE { isFaster = FALSE; spdPlayer = 5; spdOpponent = 10; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(spdPlayer); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(spdOpponent); }
} WHEN {
TURN { MOVE(player, MOVE_HEADBUTT); }
TURN { MOVE(player, MOVE_HEADBUTT); }
} SCENE {
// 1st turn
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, player);
HP_BAR(opponent);
if (isFaster) {
MESSAGE("Foe Wobbuffet flinched!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
} else {
NOT MESSAGE("Foe Wobbuffet flinched!");
}
// 2nd turn
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, player);
HP_BAR(opponent);
if (isFaster) {
MESSAGE("Foe Wobbuffet flinched!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
} else {
NOT MESSAGE("Foe Wobbuffet flinched!");
}
}
}
SINGLE_BATTLE_TEST("Protect always works when used after flinching")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); }
} WHEN {
TURN { MOVE(player, MOVE_PROTECT); MOVE(opponent, MOVE_HEADBUTT); }
TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_HEADBUTT); }
TURN { MOVE(player, MOVE_PROTECT); MOVE(opponent, MOVE_HEADBUTT); }
} SCENE {
// 1st turn
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, player);
MESSAGE("Wobbuffet protected itself!");
// 2nd turn
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, opponent);
HP_BAR(player);
MESSAGE("Wobbuffet flinched!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
// 3rd turn
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, player);
MESSAGE("Wobbuffet protected itself!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HEADBUTT, opponent);
}
}

View file

@ -208,3 +208,35 @@ SINGLE_BATTLE_TEST("Toxic Spikes are removed by Poison-types affected by Magnet
NOT STATUS_ICON(opponent, poison: TRUE);
}
}
SINGLE_BATTLE_TEST("Toxic Spikes inflicts poison on switch in after Primal Reversed mon fainted") // Oddly specific, but encountered during testing
{
GIVEN {
ASSUME(gBattleMoves[MOVE_MEMENTO].effect == EFFECT_MEMENTO); // Faints the user.
PLAYER(SPECIES_WOBBUFFET) {Speed(5); }
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(1); }
PLAYER(SPECIES_WYNAUT) {Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) {Speed(15); }
} WHEN {
TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); }
TURN { SWITCH(player, 1); }
TURN { MOVE(player, MOVE_MEMENTO); SEND_OUT(player, 2); }
} SCENE {
MESSAGE("Foe Wobbuffet used Toxic Spikes!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent);
MESSAGE("Poison Spikes were scattered all around your team's feet!");
// Switch in
MESSAGE("Go! Groudon!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, player);
STATUS_ICON(player, poison: TRUE);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
// Memento
MESSAGE("Groudon used Memento!");
MESSAGE("Groudon fainted!");
// 2nd switch-in
MESSAGE("Go! Wynaut!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, player);
STATUS_ICON(player, poison: TRUE);
}
}