diff --git a/include/battle.h b/include/battle.h index 60c583e5035c..f24d65c9450d 100644 --- a/include/battle.h +++ b/include/battle.h @@ -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 diff --git a/include/constants/battle.h b/include/constants/battle.h index 0f0d39db8d5b..5e94f27fe98b 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -224,15 +224,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) diff --git a/src/battle_anim.c b/src/battle_anim.c index 9d0c9d77add2..8caa2850cb68 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -442,7 +442,7 @@ static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets) { case MOVE_TARGET_FOES_AND_ALLY: if (IS_ALIVE_AND_PRESENT(BATTLE_PARTNER(BATTLE_OPPOSITE(battler)))) { - targets[idx++] = BATTLE_PARTNER(BATTLE_OPPOSITE(battler)); + targets[idx++] = BATTLE_PARTNER(BATTLE_OPPOSITE(battler)); numTargets++; } // fallthrough @@ -455,7 +455,7 @@ static u8 GetBattleAnimMoveTargets(u8 battlerArgIndex, u8 *targets) if (IS_ALIVE_AND_PRESENT(battler)) { targets[idx++] = battler; numTargets++; - } + } break; default: targets[0] = gBattleAnimArgs[battlerArgIndex]; // original @@ -548,7 +548,7 @@ static void CreateSpriteOnTargets(const struct SpriteTemplate *template, u8 argV ntargets = GetBattleAnimMoveTargets(battlerArgIndex, targets); if (ntargets == 0) return; - + for (i = 0; i < ntargets; i++) { if (overwriteAnimTgt) @@ -675,7 +675,7 @@ static void Cmd_createvisualtaskontargets(void) numArgs = GetBattleAnimMoveTargets(battlerArgIndex, targets); if (numArgs == 0) return; - + for (i = 0; i < numArgs; i++) { gBattleAnimArgs[battlerArgIndex] = targets[i]; diff --git a/src/battle_message.c b/src/battle_message.c index a1c862beb473..41e34b44f355 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -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}!"); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 958600a1fddd..d9e8349241f8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3773,7 +3773,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 { @@ -6880,7 +6879,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) @@ -6891,25 +6890,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; @@ -6940,12 +6939,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(); @@ -6984,7 +6983,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++) { diff --git a/test/battle/hold_effect/cure_status.c b/test/battle/hold_effect/cure_status.c index c8c32ecf7622..3be29cbf80d2 100644 --- a/test/battle/hold_effect/cure_status.c +++ b/test/battle/hold_effect/cure_status.c @@ -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); + } +} diff --git a/test/battle/move_effect/toxic_spikes.c b/test/battle/move_effect/toxic_spikes.c index 3be2d1627f11..43de89ede9c2 100644 --- a/test/battle/move_effect/toxic_spikes.c +++ b/test/battle/move_effect/toxic_spikes.c @@ -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); + } +}