rh-hideout / pokeemerald-expansion

Feature branche for the pokeemerald decompilation. See the wiki for more info.
364 stars 1.14k forks source link

Switch in ability bug when mulitply mons faint at the same time #5427

Open iriv24 opened 1 month ago

iriv24 commented 1 month ago

Description

Ya know I was originally submitting this for Booster Energy/Protosynthesis not procing when it was supposed to, but I'm starting to think there's a more general "things that happen on throw in" issue, maybe related to #5425 as well.

Here's a vid that has a few bugs in it, taken on master. The bugs: Roaring moon's protosynthesis gets activated by its booster energy, but the ability popup shows up in the wrong place and shows the wrong ability. Torkoal's drought does not activate. Gouging Fire's protosynthesis does not activate, it is holding a booster energy as well. I was originally trying to capture what i thought was a bug if 2 mons with booster energies/protosynthesis were thrown in, only one would proc, but there's a lot goin on here.

https://github.com/user-attachments/assets/11cfd852-6230-4b15-b743-d29764268b46

pokeemerald-1 pokeemerald-3 pokeemerald-4

Version

1.9.2 (Latest release)

Upcoming/master Version

No response

Discord contact info

iriv24

AlexOn1ine commented 1 month ago

I did some investigation.

In function Cmd_switchineffects the case BS_FAINTED_MULTIPLE_2 only activates the ability for the fastest battler and jumps out of the function.

Both this and #5425 are the same issue

PhallenTree commented 1 month ago

The main issue here is battle scripts that use end2 cause BattleScript_HandleFaintedMon to end early. Some tests that fail due to this bug:

DOUBLE_BATTLE_TEST("Booster Energy triggers correctly for all battlers if multiple fainted the previous turn")
{
    GIVEN {
        PLAYER(SPECIES_WOBBUFFET);
        PLAYER(SPECIES_CATERPIE) { HP(1); }
        PLAYER(SPECIES_GOUGING_FIRE) { Item(ITEM_BOOSTER_ENERGY); }
        PLAYER(SPECIES_IRON_MOTH) { Item(ITEM_BOOSTER_ENERGY); }
        OPPONENT(SPECIES_CATERPIE) { HP(1); }
        OPPONENT(SPECIES_CATERPIE) { HP(1); }
        OPPONENT(SPECIES_FLUTTER_MANE) { Item(ITEM_BOOSTER_ENERGY); }
        OPPONENT(SPECIES_CATERPIE);
    } WHEN {
        TURN { MOVE(playerLeft, MOVE_EXPLOSION);
               SEND_OUT(opponentRight, 3);
               SEND_OUT(opponentLeft, 2);
               SEND_OUT(playerRight, 3);
               SEND_OUT(playerLeft, 2); }
    } SCENE {
        ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, playerLeft);
        ABILITY_POPUP(playerLeft, ABILITY_PROTOSYNTHESIS);
        ABILITY_POPUP(playerRight, ABILITY_QUARK_DRIVE);
        ABILITY_POPUP(opponentLeft, ABILITY_PROTOSYNTHESIS);
    }
}

DOUBLE_BATTLE_TEST("Lum Berry correctly cures all battlers if multiple fainted the previous turn")
{
    GIVEN {
        PLAYER(SPECIES_WOBBUFFET);
        PLAYER(SPECIES_CATERPIE) { HP(1); }
        PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); Status1(STATUS1_BURN); }
        PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); Status1(STATUS1_POISON); }
        OPPONENT(SPECIES_CATERPIE) { HP(1); }
        OPPONENT(SPECIES_CATERPIE) { HP(1); }
        OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); Status1(STATUS1_PARALYSIS); }
        OPPONENT(SPECIES_CATERPIE);
    } WHEN {
        TURN { MOVE(playerLeft, MOVE_EXPLOSION);
               SEND_OUT(opponentRight, 3);
               SEND_OUT(opponentLeft, 2);
               SEND_OUT(playerRight, 3);
               SEND_OUT(playerLeft, 2); }
    } SCENE {
        ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, playerLeft);
    } THEN {
        EXPECT_EQ(playerLeft->status1, STATUS1_NONE);
        EXPECT_EQ(playerRight->status1, STATUS1_NONE);
        EXPECT_EQ(opponentLeft->status1, STATUS1_NONE);

    }
}
AlexOn1ine commented 1 month ago

I think instead of doing all the ability effects in Cmd_switchineffects we should move the logic that happens after several mons fainted to HandleFaintedMonActions. Add a case for sorting battlers and a case for the switchineffects.