Fixes Endure and Eject Pack issues (#7687)
Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
This commit is contained in:
parent
2f22780c17
commit
499e90ac4b
@ -130,16 +130,16 @@ struct DisableStruct
|
||||
u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case
|
||||
u8 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in
|
||||
u8 hazardsDone:1;
|
||||
u8 padding1:1;
|
||||
u8 endured:1;
|
||||
u8 octolockedBy:3;
|
||||
u8 padding2:5;
|
||||
u8 tryEjectPack:1;
|
||||
u8 padding:4;
|
||||
};
|
||||
|
||||
// Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects
|
||||
struct ProtectStruct
|
||||
{
|
||||
u32 protected:7; // 126 protect options
|
||||
u32 endured:1;
|
||||
u32 noValidMoves:1;
|
||||
u32 helpingHand:1;
|
||||
u32 bounceMove:1;
|
||||
@ -155,10 +155,9 @@ struct ProtectStruct
|
||||
u32 statRaised:1;
|
||||
u32 usedCustapBerry:1; // also quick claw
|
||||
u32 touchedProtectLike:1;
|
||||
u32 unused:8;
|
||||
u32 unused:9;
|
||||
// End of 32-bit bitfield
|
||||
u16 disableEjectPack:1;
|
||||
u16 tryEjectPack:1;
|
||||
u16 pranksterElevated:1;
|
||||
u16 quickDraw:1;
|
||||
u16 beakBlastCharge:1;
|
||||
@ -169,12 +168,12 @@ struct ProtectStruct
|
||||
u16 usedAllySwitch:1;
|
||||
u16 lashOutAffected:1;
|
||||
u16 assuranceDoubled:1;
|
||||
u16 padding:3;
|
||||
u16 padding:4;
|
||||
// End of 16-bit bitfield
|
||||
u16 physicalDmg;
|
||||
u16 specialDmg;
|
||||
u8 physicalBattlerId;
|
||||
u8 specialBattlerId;
|
||||
u8 physicalBattlerId:4;
|
||||
u8 specialBattlerId:4;
|
||||
};
|
||||
|
||||
// Cleared at the start of HandleAction_ActionFinished
|
||||
|
||||
@ -363,7 +363,7 @@ enum BattleWeather
|
||||
#define B_WEATHER_LOW_LIGHT (B_WEATHER_FOG | B_WEATHER_ICY_ANY | B_WEATHER_RAIN | B_WEATHER_SANDSTORM)
|
||||
#define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS)
|
||||
|
||||
// Explicit numbers until frostbite because those shouldn't be shifted
|
||||
// Explicit numbers until frostbite because those shouldn't be shifted
|
||||
enum __attribute__((packed)) MoveEffect
|
||||
{
|
||||
MOVE_EFFECT_NONE = 0,
|
||||
|
||||
@ -3197,6 +3197,9 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
|
||||
|
||||
memset(&gDisableStructs[battler], 0, sizeof(struct DisableStruct));
|
||||
|
||||
if (GetProtectType(gProtectStructs[battler].protected) == PROTECT_TYPE_SINGLE) // Side type protects expire at the end of the turn
|
||||
gProtectStructs[battler].protected = PROTECT_NONE;
|
||||
|
||||
if (effect == EFFECT_BATON_PASS)
|
||||
{
|
||||
gDisableStructs[battler].substituteHP = disableStructCopy.substituteHP;
|
||||
@ -3294,9 +3297,7 @@ const u8* FaintClearSetData(u32 battler)
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE;
|
||||
|
||||
bool32 keepGastroAcid = FALSE;
|
||||
if (gBattleMons[battler].volatiles.gastroAcid)
|
||||
keepGastroAcid = TRUE;
|
||||
bool32 keepGastroAcid = gBattleMons[battler].volatiles.gastroAcid;
|
||||
memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles));
|
||||
gBattleMons[battler].volatiles.gastroAcid = keepGastroAcid; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out.
|
||||
|
||||
@ -3323,7 +3324,6 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gProtectStructs[battler].protected = PROTECT_NONE;
|
||||
|
||||
gProtectStructs[battler].quash = FALSE;
|
||||
gProtectStructs[battler].endured = FALSE;
|
||||
gProtectStructs[battler].noValidMoves = FALSE;
|
||||
gProtectStructs[battler].helpingHand = FALSE;
|
||||
gProtectStructs[battler].bounceMove = FALSE;
|
||||
@ -3335,7 +3335,6 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gProtectStructs[battler].fleeType = 0;
|
||||
gProtectStructs[battler].notFirstStrike = FALSE;
|
||||
gProtectStructs[battler].statRaised = FALSE;
|
||||
gProtectStructs[battler].tryEjectPack = FALSE;
|
||||
gProtectStructs[battler].pranksterElevated = FALSE;
|
||||
|
||||
gDisableStructs[battler].isFirstTurn = 2;
|
||||
|
||||
@ -1920,7 +1920,7 @@ static void Cmd_adjustdamage(void)
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
}
|
||||
else if (gProtectStructs[battlerDef].endured)
|
||||
else if (gDisableStructs[battlerDef].endured)
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED;
|
||||
@ -5545,7 +5545,7 @@ static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum
|
||||
|
||||
static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect)
|
||||
{
|
||||
if (gProtectStructs[battlerDef].tryEjectPack
|
||||
if (gDisableStructs[battlerDef].tryEjectPack
|
||||
&& GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_PACK
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& CountUsablePartyMons(battlerDef) > 0
|
||||
@ -6565,7 +6565,7 @@ static void Cmd_moveend(void)
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
if (numEjectButtonBattlers > 1)
|
||||
@ -6628,7 +6628,7 @@ static void Cmd_moveend(void)
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
if (numEmergencyExitBattlers > 1)
|
||||
@ -6683,7 +6683,7 @@ static void Cmd_moveend(void)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
@ -6910,7 +6910,7 @@ static void Cmd_moveend(void)
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleStruct->battlerState[gBattlerAttacker].targetsDone[i] = FALSE;
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
if (gBattleStruct->battlerState[i].commanderSpecies != SPECIES_NONE && !IsBattlerAlive(i))
|
||||
{
|
||||
@ -9533,7 +9533,7 @@ static void Cmd_setprotectlike(void)
|
||||
{
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE)
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].endured = TRUE;
|
||||
gDisableStructs[gBattlerAttacker].endured = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF;
|
||||
}
|
||||
else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE)
|
||||
@ -10329,7 +10329,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan
|
||||
}
|
||||
else if (!flags.onlyChecking)
|
||||
{
|
||||
gProtectStructs[battler].tryEjectPack = TRUE;
|
||||
gDisableStructs[battler].tryEjectPack = TRUE;
|
||||
gProtectStructs[battler].lashOutAffected = TRUE;
|
||||
}
|
||||
}
|
||||
@ -10930,7 +10930,7 @@ static void Cmd_tryKO(void)
|
||||
|
||||
if (lands)
|
||||
{
|
||||
if (gProtectStructs[gBattlerTarget].endured)
|
||||
if (gDisableStructs[gBattlerTarget].endured)
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1;
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED;
|
||||
|
||||
@ -11461,7 +11461,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID)
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gProtectStructs[i].tryEjectPack
|
||||
if (gDisableStructs[i].tryEjectPack
|
||||
&& GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_EJECT_PACK
|
||||
&& IsBattlerAlive(i)
|
||||
&& CountUsablePartyMons(i) > 0)
|
||||
@ -11479,7 +11479,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
|
||||
@ -317,3 +317,24 @@ DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Eject Pack does not activate if mon is switched in due to Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_ARENA_TRAP); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_BUTTON); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); };
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(player, MOVE_BULLDOZE);
|
||||
SEND_OUT(opponent, 1);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLDOZE, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
MESSAGE("The opposing Wobbuffet is switched out with the Eject Button!");
|
||||
MESSAGE("2 sent out Wobbuffet!");
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,3 +131,22 @@ SINGLE_BATTLE_TEST("Life Orb activates if move connected but no damage was dealt
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Life Orb does not activate on a charge turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FLY); }
|
||||
TURN { SKIP_TURN(player); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, player);
|
||||
NONE_OF {
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
HP_BAR(opponent);
|
||||
HP_BAR(player); // Lief Orb
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,33 @@ SINGLE_BATTLE_TEST("Endure does not prevent multiple hits and stat changes occur
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Endure is not transferred to a mon that is switched in due to Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT) { HP(1); Item(ITEM_EJECT_BUTTON); }
|
||||
OPPONENT(SPECIES_SQUIRTLE) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_ENDURE);
|
||||
MOVE(playerLeft, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 2);
|
||||
MOVE(playerRight, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENDURE, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft);
|
||||
MESSAGE("The opposing Wynaut endured the hit!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight);
|
||||
NOT MESSAGE("The opposing Squirtle endured the hit!");
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Endure's success rate decreases for every consecutively used turn");
|
||||
TO_DO_BATTLE_TEST("Endure uses the same counter as Protect");
|
||||
TO_DO_BATTLE_TEST("Endure doesn't trigger effects that require damage to be done to the Pokémon (Gen 2-4)"); // Eg. Rough Skin
|
||||
|
||||
@ -675,3 +675,58 @@ SINGLE_BATTLE_TEST("Protect: Protective Pads protects from secondary effects")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Protect is not transferred to a mon that is switched in due to Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_URSHIFU) { Ability(ABILITY_UNSEEN_FIST); };
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT) { Item(ITEM_EJECT_BUTTON); }
|
||||
OPPONENT(SPECIES_SQUIRTLE);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_PROTECT);
|
||||
MOVE(playerLeft, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 2);
|
||||
MOVE(playerRight, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight);
|
||||
HP_BAR(opponentRight);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Wide Guard is still activate even if user is switched out due to Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT) { Item(ITEM_EJECT_BUTTON); }
|
||||
OPPONENT(SPECIES_SQUIRTLE);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_WIDE_GUARD);
|
||||
MOVE(playerLeft, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 2);
|
||||
MOVE(playerRight, MOVE_HYPER_VOICE, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_WIDE_GUARD, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, playerRight);
|
||||
HP_BAR(opponentLeft);
|
||||
HP_BAR(opponentRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user