diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index ac5d433a3..7073fae68 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7236,6 +7236,9 @@ BattleScript_ToxicDebrisActivates:: printstring STRINGID_POISONSPIKESSCATTERED waitmessage B_WAIT_TIME_LONG BattleScript_ToxicDebrisRet: + copybyte sBATTLER, gBattlerTarget + copybyte gBattlerTarget, gBattlerAttacker + copybyte gBattlerAttacker, sBATTLER return BattleScript_EarthEaterActivates:: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 28113e3f1..9bd9ef2f7 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1143,7 +1143,7 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) for (i = 0; i < MAX_MON_MOVES; i++) { if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !(unusable & gBitTable[i]) - && AI_DATA->simulatedDmg[battlerDef][battlerAtk][moves[i]] >= gBattleMons[battlerAtk].hp) + && AI_DATA->simulatedDmg[battlerDef][battlerAtk][i] >= gBattleMons[battlerAtk].hp) { return TRUE; } diff --git a/src/battle_util.c b/src/battle_util.c index 0b0aadab3..ef53ce8f5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5672,10 +5672,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IS_MOVE_PHYSICAL(gCurrentMove) && TARGET_TURN_DAMAGED - && !(gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_TOXIC_SPIKES) + && (gSideTimers[gBattlerAttacker].toxicSpikesAmount != 2) && IsBattlerAlive(gBattlerTarget)) { - gBattlerTarget = gBattlerAttacker; + SWAP(gBattlerAttacker, gBattlerTarget, i); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ToxicDebrisActivates; effect++; diff --git a/test/battle/ability/toxic_debris.c b/test/battle/ability/toxic_debris.c new file mode 100644 index 000000000..95749358a --- /dev/null +++ b/test/battle/ability/toxic_debris.c @@ -0,0 +1,96 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Toxic Debris sets Toxic Spikes on the opposing side if hit by a physical attack") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE;} + PARAMETRIZE { move = MOVE_SWIFT;} + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TOXIC_DEBRIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + if (move == MOVE_TACKLE) { + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } + else { + NOT ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + NOT MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } + } +} + +SINGLE_BATTLE_TEST("Toxic Debris does not activate if two layers of Toxic Spikes are already up") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TOXIC_DEBRIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + NOT ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + NOT MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } +} + +SINGLE_BATTLE_TEST("If a Substitute is hit, Toxic Debris does not set Toxic Spikes") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TOXIC_DEBRIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); } + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + NOT ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + NOT MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } +} + +SINGLE_BATTLE_TEST("Each hit of a Multi Hit move activates Toxic Debris") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TOXIC_DEBRIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_FURY_SWIPES); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, opponent); + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, opponent); + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } +} + +SINGLE_BATTLE_TEST("Air Balloon is popped after Toxic Debris activates") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TOXIC_DEBRIS); Item(ITEM_AIR_BALLOON); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + MESSAGE("Wobbuffet's Air Balloon popped!"); + } +} diff --git a/test/battle/hold_effect/cure_status.c b/test/battle/hold_effect/cure_status.c new file mode 100644 index 000000000..c8c32ecf7 --- /dev/null +++ b/test/battle/hold_effect/cure_status.c @@ -0,0 +1,215 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_LUM_BERRY].holdEffect == HOLD_EFFECT_CURE_STATUS); +} + +SINGLE_BATTLE_TEST("Pecha and Lum Berries cure poison") +{ + u16 item; + + PARAMETRIZE { item = ITEM_PECHA_BERRY; } + PARAMETRIZE { item = ITEM_LUM_BERRY; } + + GIVEN { + ASSUME(gItems[ITEM_PECHA_BERRY].holdEffect == HOLD_EFFECT_CURE_PSN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_POISON_POWDER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_POWDER, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + STATUS_ICON(opponent, poison: FALSE); + } +} + +SINGLE_BATTLE_TEST("Pecha and Lum Berries cure bad poison") +{ + u16 item; + + PARAMETRIZE { item = ITEM_PECHA_BERRY; } + PARAMETRIZE { item = ITEM_LUM_BERRY; } + + GIVEN { + ASSUME(gItems[ITEM_PECHA_BERRY].holdEffect == HOLD_EFFECT_CURE_PSN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_TOXIC); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, badPoison: TRUE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + STATUS_ICON(opponent, badPoison: FALSE); + } +} + +SINGLE_BATTLE_TEST("Rawst and Lum Berries cure burn") +{ + u16 item; + + PARAMETRIZE { item = ITEM_RAWST_BERRY; } + PARAMETRIZE { item = ITEM_LUM_BERRY; } + + GIVEN { + ASSUME(gItems[ITEM_RAWST_BERRY].holdEffect == HOLD_EFFECT_CURE_BRN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_WILL_O_WISP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WILL_O_WISP, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent); + STATUS_ICON(opponent, burn: TRUE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + STATUS_ICON(opponent, burn: FALSE); + } +} + +SINGLE_BATTLE_TEST("Aspear and Lum Berries cure freeze") +{ + u16 item; + + PARAMETRIZE { item = ITEM_ASPEAR_BERRY; } + PARAMETRIZE { item = ITEM_LUM_BERRY; } + + GIVEN { + ASSUME(gItems[ITEM_ASPEAR_BERRY].holdEffect == HOLD_EFFECT_CURE_FRZ); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_ICE_PUNCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_PUNCH, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + STATUS_ICON(opponent, freeze: TRUE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + STATUS_ICON(opponent, freeze: FALSE); + } +} + +SINGLE_BATTLE_TEST("Chesto and Lum Berries cure sleep") +{ + u16 item; + + PARAMETRIZE { item = ITEM_CHESTO_BERRY; } + PARAMETRIZE { item = ITEM_LUM_BERRY; } + + GIVEN { + ASSUME(gItems[ITEM_CHESTO_BERRY].holdEffect == HOLD_EFFECT_CURE_SLP); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_HYPNOSIS); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPNOSIS, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent); + STATUS_ICON(opponent, sleep: TRUE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + STATUS_ICON(opponent, sleep: FALSE); + } +} + +SINGLE_BATTLE_TEST("Cheri and Lum Berries cure paralysis") +{ + u16 item; + + PARAMETRIZE { item = ITEM_CHERI_BERRY; } + PARAMETRIZE { item = ITEM_LUM_BERRY; } + + GIVEN { + ASSUME(gItems[ITEM_CHERI_BERRY].holdEffect == HOLD_EFFECT_CURE_PAR); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_THUNDER_WAVE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent); + STATUS_ICON(opponent, paralysis: TRUE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + STATUS_ICON(opponent, paralysis: FALSE); + } +} + +SINGLE_BATTLE_TEST("Perism and Lum Berries cure confusion") +{ + u16 item; + + PARAMETRIZE { item = ITEM_PERSIM_BERRY; } + PARAMETRIZE { item = ITEM_LUM_BERRY; } + + GIVEN { + ASSUME(gItems[ITEM_PERSIM_BERRY].holdEffect == HOLD_EFFECT_CURE_CONFUSION); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_CONFUSE_RAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } +} + +SINGLE_BATTLE_TEST("Berry hold effect cures status if a pokemon enters a battle") +{ + u16 status; + u16 item; + + PARAMETRIZE{ status = STATUS1_BURN; item = ITEM_RAWST_BERRY; } + PARAMETRIZE{ status = STATUS1_FREEZE; item = ITEM_ASPEAR_BERRY; } + PARAMETRIZE{ status = STATUS1_PARALYSIS; item = ITEM_CHERI_BERRY; } + PARAMETRIZE{ status = STATUS1_POISON; item = ITEM_PECHA_BERRY; } + PARAMETRIZE{ status = STATUS1_TOXIC_POISON; item = ITEM_PECHA_BERRY; } + PARAMETRIZE{ status = STATUS1_SLEEP; item = ITEM_CHESTO_BERRY; } + + GIVEN { + ASSUME(gItems[ITEM_RAWST_BERRY].holdEffect == HOLD_EFFECT_CURE_BRN); + ASSUME(gItems[ITEM_ASPEAR_BERRY].holdEffect == HOLD_EFFECT_CURE_FRZ); + ASSUME(gItems[ITEM_CHERI_BERRY].holdEffect == HOLD_EFFECT_CURE_PAR); + ASSUME(gItems[ITEM_PECHA_BERRY].holdEffect == HOLD_EFFECT_CURE_PSN); + ASSUME(gItems[ITEM_CHESTO_BERRY].holdEffect == HOLD_EFFECT_CURE_SLP); + PLAYER(SPECIES_WOBBUFFET) { Status1(status); Item(ITEM_LUM_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(status); Item(item); } + } WHEN { + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } +} + +SINGLE_BATTLE_TEST("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); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_TOXIC_SPIKES); } + TURN { SWITCH(opponent, 1); } + TURN { SWITCH(opponent, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + STATUS_ICON(opponent, poison: FALSE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + } +}