Fix Primal Reversion not activating when switching in after fainting (#3141)

* Fixed Primal Reversion not activating when switching in after a fainting
* add tests for primal reversion

Co-authored-by: Eduardo Quezada <eduardo602002@gmail.com>
This commit is contained in:
DizzyEggg 2023-07-16 13:26:54 +02:00 committed by GitHub
parent 3c5c68ac58
commit 1f1d24b3e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 250 additions and 22 deletions

View File

@ -6768,9 +6768,6 @@ BattleScript_DoSwitchOut::
hidepartystatussummary BS_ATTACKER
switchinanim BS_ATTACKER, FALSE
waitstate
jumpifcantreverttoprimal BattleScript_DoSwitchOut2
call BattleScript_PrimalReversionRet
BattleScript_DoSwitchOut2:
switchineffects BS_ATTACKER
moveendcase MOVEEND_STATUS_IMMUNITY_ABILITIES
moveendcase MOVEEND_MIRROR_MOVE
@ -7925,17 +7922,12 @@ BattleScript_WishMegaEvolution::
goto BattleScript_MegaEvolutionAfterString
BattleScript_PrimalReversion::
printstring STRINGID_EMPTYSTRING3
waitmessage 1
setbyte gIsCriticalHit, 0
handleprimalreversion BS_ATTACKER, 0
handleprimalreversion BS_ATTACKER, 1
playanimation BS_ATTACKER, B_ANIM_PRIMAL_REVERSION
waitanimation
handleprimalreversion BS_ATTACKER, 2
printstring STRINGID_PKMNREVERTEDTOPRIMAL
waitmessage B_WAIT_TIME_LONG
switchinabilities BS_ATTACKER
call BattleScript_PrimalReversionRet
end2
BattleScript_PrimalReversionRestoreAttacker::
call BattleScript_PrimalReversionRet
copybyte gBattlerAttacker, sSAVED_BATTLER
end2
BattleScript_PrimalReversionRet::
@ -7949,6 +7941,7 @@ BattleScript_PrimalReversionRet::
handleprimalreversion BS_ATTACKER, 2
printstring STRINGID_PKMNREVERTEDTOPRIMAL
waitmessage B_WAIT_TIME_LONG
switchinabilities BS_ATTACKER
return
BattleScript_AttackerFormChange::

View File

@ -418,6 +418,7 @@ extern const u8 BattleScript_AttackWeakenedByStrongWinds[];
extern const u8 BattleScript_BlockedByPrimalWeatherEnd3[];
extern const u8 BattleScript_BlockedByPrimalWeatherRet[];
extern const u8 BattleScript_PrimalReversion[];
extern const u8 BattleScript_PrimalReversionRestoreAttacker[];
extern const u8 BattleScript_HyperspaceFuryRemoveProtect[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTacticsInPalace[];

View File

@ -142,6 +142,7 @@ u8 AtkCanceller_UnableToUseMove2(void);
bool8 HasNoMonsToSwitch(u8 battlerId, u8 r1, u8 r2);
bool32 TryChangeBattleWeather(u8 battler, u32 weatherEnumId, bool32 viaAbility);
u8 AbilityBattleEffects(u8 caseID, u8 battlerId, u16 ability, u8 special, u16 moveArg);
bool32 TryPrimalReversion(u8 battlerId);
bool32 IsNeutralizingGasOnField(void);
u32 GetBattlerAbility(u8 battlerId);
u32 IsAbilityOnSide(u32 battlerId, u32 ability);

View File

@ -3861,14 +3861,9 @@ static void TryDoEventsBeforeFirstTurn(void)
while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount)
{
gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->switchInAbilitiesCounter++];
// Primal Reversion
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_PRIMAL_ORB
&& GetBattleFormChangeTargetSpecies(gBattlerAttacker, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE)
{
BattleScriptExecute(BattleScript_PrimalReversion);
if (TryPrimalReversion(gBattlerAttacker))
return;
}
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0)
return;
}

View File

@ -7042,7 +7042,8 @@ static void SetDmgHazardsBattlescript(u8 battlerId, u8 multistringId)
bool32 DoSwitchInAbilitiesItems(u32 battlerId)
{
return (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battlerId, 0, 0, 0)
return (TryPrimalReversion(battlerId)
|| AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battlerId, 0, 0, 0)
|| (gBattleWeather & B_WEATHER_ANY && WEATHER_HAS_EFFECT && AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battlerId, 0, 0, 0))
|| (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battlerId, 0, 0, 0))
|| ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battlerId, FALSE)

View File

@ -6092,6 +6092,27 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
return effect;
}
bool32 TryPrimalReversion(u8 battlerId)
{
if (GetBattlerHoldEffect(battlerId, FALSE) == HOLD_EFFECT_PRIMAL_ORB
&& GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE)
{
if (gBattlerAttacker == battlerId)
{
BattleScriptExecute(BattleScript_PrimalReversion);
}
else
{
// edge case for scenarios like a switch-in after activated eject button
gBattleScripting.savedBattler = gBattlerAttacker;
gBattlerAttacker = battlerId;
BattleScriptExecute(BattleScript_PrimalReversionRestoreAttacker);
}
return TRUE;
}
return FALSE;
}
bool32 IsNeutralizingGasBannedAbility(u32 ability)
{
switch (ability)

216
test/primal_reversion.c Normal file
View File

@ -0,0 +1,216 @@
#include "global.h"
#include "test_battle.h"
SINGLE_BATTLE_TEST("Primal reversion happens for Groudon only when holding Red Orb")
{
u16 heldItem;
PARAMETRIZE { heldItem = ITEM_NONE;}
PARAMETRIZE { heldItem = ITEM_RED_ORB;}
PARAMETRIZE { heldItem = ITEM_BLUE_ORB;}
GIVEN {
PLAYER(SPECIES_GROUDON) { Item(heldItem); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_CELEBRATE); }
} SCENE {
if (heldItem == ITEM_RED_ORB) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
}
else {
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
}
}
} THEN {
if (heldItem == ITEM_RED_ORB) {
EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL);
}
else {
EXPECT_EQ(player->species, SPECIES_GROUDON);
}
}
}
SINGLE_BATTLE_TEST("Primal reversion happens for Kyogre only when holding Blue Orb")
{
u16 heldItem;
PARAMETRIZE { heldItem = ITEM_NONE;}
PARAMETRIZE { heldItem = ITEM_RED_ORB;}
PARAMETRIZE { heldItem = ITEM_BLUE_ORB;}
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KYOGRE) { Item(heldItem); }
} WHEN {
TURN { MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
if (heldItem == ITEM_BLUE_ORB) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponent);
MESSAGE("Foe Kyogre's Primal Reversion! It reverted to its primal form!");
}
else {
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponent);
MESSAGE("Foe Kyogre's Primal Reversion! It reverted to its primal form!");
}
}
} THEN {
if (heldItem == ITEM_BLUE_ORB) {
EXPECT_EQ(opponent->species, SPECIES_KYOGRE_PRIMAL);
}
else {
EXPECT_EQ(opponent->species, SPECIES_KYOGRE);
}
}
}
DOUBLE_BATTLE_TEST("Primal reversion's order is determined by Speed - opponent faster")
{
GIVEN {
PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); Speed(5); };
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(15); };
OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(10); }
OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); Speed(20); }
} WHEN {
TURN { MOVE(opponentLeft, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponentRight);
MESSAGE("Foe Kyogre's Primal Reversion! It reverted to its primal form!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, playerRight);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponentLeft);
MESSAGE("Foe Groudon's Primal Reversion! It reverted to its primal form!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, playerLeft);
MESSAGE("Kyogre's Primal Reversion! It reverted to its primal form!");
} THEN {
EXPECT_EQ(playerLeft->species, SPECIES_KYOGRE_PRIMAL);
EXPECT_EQ(opponentLeft->species, SPECIES_GROUDON_PRIMAL);
EXPECT_EQ(opponentRight->species, SPECIES_KYOGRE_PRIMAL);
EXPECT_EQ(playerRight->species, SPECIES_GROUDON_PRIMAL);
}
}
DOUBLE_BATTLE_TEST("Primal reversion's order is determined by Speed - player faster")
{
GIVEN {
PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); Speed(20); };
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(30); };
OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(10); }
OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); Speed(2); }
} WHEN {
TURN { MOVE(opponentLeft, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, playerRight);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, playerLeft);
MESSAGE("Kyogre's Primal Reversion! It reverted to its primal form!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponentLeft);
MESSAGE("Foe Groudon's Primal Reversion! It reverted to its primal form!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponentRight);
MESSAGE("Foe Kyogre's Primal Reversion! It reverted to its primal form!");
} THEN {
EXPECT_EQ(playerLeft->species, SPECIES_KYOGRE_PRIMAL);
EXPECT_EQ(opponentLeft->species, SPECIES_GROUDON_PRIMAL);
EXPECT_EQ(opponentRight->species, SPECIES_KYOGRE_PRIMAL);
EXPECT_EQ(playerRight->species, SPECIES_GROUDON_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Primal reversion happens after a mon is sent out after a mon is fainted")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
PLAYER(SPECIES_WOBBUFFET) {HP(1); }
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
MESSAGE("Wobbuffet fainted!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
} THEN {
EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Primal reversion happens after a mon is switched in")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_CELEBRATE); }
TURN { MOVE(opponent, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
} THEN {
EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Primal reversion happens after a switch-in caused by Eject Button")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
ASSUME(gItems[ITEM_EJECT_BUTTON].holdEffect == HOLD_EFFECT_EJECT_BUTTON);
PLAYER(SPECIES_WOBBUFFET) {Item(ITEM_EJECT_BUTTON); }
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
MESSAGE("Wobbuffet is switched out with the Eject Button!");
MESSAGE("Go! Groudon!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
} THEN {
EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Primal reversion happens after a switch-in caused by Red Card")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
ASSUME(gItems[ITEM_RED_CARD].holdEffect == HOLD_EFFECT_RED_CARD);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET) {Item(ITEM_RED_CARD); }
} WHEN {
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
MESSAGE("Foe Wobbuffet held up its Red Card against Wobbuffet!");
MESSAGE("Groudon was dragged out!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
} THEN {
EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL);
}
}
SINGLE_BATTLE_TEST("Primal reversion happens after the entry hazards damage")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_SPIKES].effect == EFFECT_SPIKES);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SPIKES); }
TURN { MOVE(opponent, MOVE_SPIKES); SWITCH(player, 1);}
} SCENE {
MESSAGE("Go! Groudon!");
HP_BAR(player);
MESSAGE("Groudon is hurt by spikes!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player);
MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!");
} THEN {
EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL);
}
}