Fixes Eject Pack triggering twice on Intimidate (#6072)

This commit is contained in:
Alex 2025-01-21 23:58:52 +01:00 committed by GitHub
parent b2f2a8c9fb
commit f2840cb047
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 75 deletions

View File

@ -65,7 +65,7 @@ enum {
#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6
// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try
enum ItemEffect
enum ItemCaseId
{
ITEMEFFECT_NONE,
ITEMEFFECT_ON_SWITCH_IN,
@ -80,6 +80,16 @@ enum ItemEffect
ITEMEFFECT_STATS_CHANGED, // For White Herb and Eject Pack
};
enum ItemEffect
{
ITEM_NO_EFFECT,
ITEM_STATUS_CHANGE,
ITEM_EFFECT_OTHER,
ITEM_PP_CHANGE,
ITEM_HP_CHANGE,
ITEM_STATS_CHANGE,
};
#define WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK)))
#define IS_WHOLE_SIDE_ALIVE(battler) ((IsBattlerAlive(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))))
@ -215,7 +225,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 CanBattlerEscape(u32 battler); // no ability check
void BattleScriptExecute(const u8 *BS_ptr);
void BattleScriptPushCursorAndCallback(const u8 *BS_ptr);
u32 ItemBattleEffects(enum ItemEffect, u32 battler, bool32 moveTurn);
u32 ItemBattleEffects(enum ItemCaseId, u32 battler, bool32 moveTurn);
void ClearVariousBattlerFlags(u32 battler);
void HandleAction_RunBattleScript(void);
u32 SetRandomTarget(u32 battler);
@ -272,7 +282,7 @@ void TryRestoreHeldItems(void);
bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item);
void TrySaveExchangedItem(u32 battler, u16 stolenItem);
bool32 IsPartnerMonFromSameTrainer(u32 battler);
u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemEffect caseID);
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemCaseId caseID);
bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes);
void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast);
bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind);

View File

@ -10536,25 +10536,25 @@ static void Cmd_various(void)
VARIOUS_ARGS(const u8 *failInstr);
if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SEEDS)
{
u8 effect = 0;
enum ItemEffect effect = ITEM_NO_EFFECT;
u16 item = gBattleMons[battler].item;
switch (GetBattlerHoldEffectParam(battler))
{
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE);
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
break;
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE);
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
break;
case HOLD_EFFECT_PARAM_MISTY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE);
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
break;
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE);
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN);
break;
}
if (effect)
if (effect != ITEM_NO_EFFECT)
return;
}
gBattlescriptCurrInstr = cmd->failInstr;

View File

@ -6699,16 +6699,6 @@ void BattleScriptPushCursorAndCallback(const u8 *BS_ptr)
gBattleMainFunc = RunBattleScriptCommands;
}
enum
{
ITEM_NO_EFFECT,
ITEM_STATUS_CHANGE,
ITEM_EFFECT_OTHER,
ITEM_PP_CHANGE,
ITEM_HP_CHANGE,
ITEM_STATS_CHANGE,
};
bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag)
{
if (!(gFieldStatuses & terrainFlag))
@ -6844,7 +6834,7 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId)
return FALSE;
}
static u32 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemEffect caseID)
static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemCaseId caseID)
{
if (HasEnoughHpToEatBerry(battler, (B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2), itemId)
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)))
@ -6880,10 +6870,10 @@ static u32 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemEffe
return ITEM_HP_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u32 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemEffect caseID)
static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemCaseId caseID)
{
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId))
{
@ -6911,7 +6901,7 @@ static u32 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum ItemEffect c
return ITEM_NO_EFFECT;
}
static u32 RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemCaseId caseID)
{
s32 i;
u16 stringId;
@ -6959,10 +6949,10 @@ static u32 RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
return ITEM_STATS_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
static enum ItemEffect TrySetMicleBerry(u32 battler, u32 itemId, enum ItemCaseId caseID)
{
if (HasEnoughHpToEatBerry(battler, 4, itemId))
{
@ -6978,10 +6968,10 @@ static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID)
}
return ITEM_EFFECT_OTHER;
}
return 0;
return ITEM_NO_EFFECT;
}
static u8 TrySetEnigmaBerry(u32 battler)
static enum ItemEffect TrySetEnigmaBerry(u32 battler)
{
if (IsBattlerAlive(battler)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
@ -6998,10 +6988,10 @@ static u8 TrySetEnigmaBerry(u32 battler)
gBattlescriptCurrInstr = BattleScript_ItemHealHP_RemoveItemRet;
return ITEM_HP_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
static enum ItemEffect DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
{
if (IsBattlerAlive(battler)
&& CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)
@ -7027,10 +7017,10 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet;
return ITEM_STATS_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemEffect caseID)
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum ItemCaseId caseID)
{
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
{
@ -7040,7 +7030,7 @@ u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum Ite
SET_STATCHANGER(statId, 1, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
gBattleScripting.animArg2 = 0;
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL)
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)
{
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
}
@ -7051,10 +7041,33 @@ u32 TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 itemId, enum Ite
}
return ITEM_STATS_CHANGE;
}
return 0;
return ITEM_NO_EFFECT;
}
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemEffect caseID)
static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID)
{
if (gProtectStructs[battler].statFell
&& !gProtectStructs[battler].disableEjectPack
&& CountUsablePartyMons(battler) > 0
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
{
gProtectStructs[battler].statFell = FALSE;
gBattleScripting.battler = battler;
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)
{
BattleScriptExecute(BattleScript_EjectPackActivate_End2);
}
else
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
}
return ITEM_STATS_CHANGE;
}
return ITEM_NO_EFFECT;
}
static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID)
{
struct Pokemon *party = GetBattlerParty(battler);
struct Pokemon *mon = &party[gBattlerPartyIndexes[battler]];
@ -7101,7 +7114,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemEffect caseID)
return 0;
}
static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemEffect caseID, bool32 percentHeal)
static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemCaseId caseID, bool32 percentHeal)
{
if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP)
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
@ -7198,7 +7211,7 @@ static bool32 GetMentalHerbEffect(u32 battler)
return ret;
}
static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID)
static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID)
{
u32 effect = 0;
@ -7223,7 +7236,7 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID)
return effect;
}
static inline u32 TryBoosterEnergy(u32 battler, enum ItemEffect caseID)
static inline u32 TryBoosterEnergy(u32 battler, enum ItemCaseId caseID)
{
if (gBattleStruct->boosterEnergyActivates & (1u << battler) || gBattleMons[battler].status2 & STATUS2_TRANSFORMED)
return ITEM_NO_EFFECT;
@ -7487,7 +7500,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
return effect;
}
static inline bool32 TryCureStatus(u32 battler, enum ItemEffect caseId)
static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId)
{
u32 effect = ITEM_NO_EFFECT;
u32 string = 0;
@ -7546,10 +7559,10 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemEffect caseId)
return effect;
}
u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
{
u32 moveType = 0;
u32 effect = ITEM_NO_EFFECT;
enum ItemEffect effect = ITEM_NO_EFFECT;
u32 battlerHoldEffect = 0, atkHoldEffect = 0;
u32 atkHoldEffectParam = 0;
u32 atkItem = 0;
@ -7746,24 +7759,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
}
break;
case HOLD_EFFECT_EJECT_PACK:
if (gProtectStructs[battler].statFell
&& gProtectStructs[battler].disableEjectPack == 0
&& CountUsablePartyMons(battler) > 0
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
{
gProtectStructs[battler].statFell = FALSE;
gBattleScripting.battler = battler;
effect = ITEM_STATS_CHANGE;
if (moveTurn)
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
}
else
{
BattleScriptExecute(BattleScript_EjectPackActivate_End2);
}
}
effect = TryEjectPack(battler, caseID);
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
@ -7791,12 +7787,10 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
{
gSpecialStatuses[battler].switchInItemDone = TRUE;
gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting.battler = battler;
switch (effect)
if (effect == ITEM_STATUS_CHANGE)
{
case ITEM_STATUS_CHANGE:
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
break;
}
}
}
@ -8007,12 +8001,10 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
if (effect != 0)
{
gBattlerAttacker = gPotentialItemEffectBattler = gBattleScripting.battler = battler;
switch (effect)
if (effect == ITEM_STATUS_CHANGE)
{
case ITEM_STATUS_CHANGE:
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
break;
}
}
}
@ -8369,16 +8361,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn)
}
break;
case HOLD_EFFECT_EJECT_PACK:
if (gProtectStructs[battler].statFell
&& gProtectStructs[battler].disableEjectPack == 0
&& CountUsablePartyMons(battler) > 0)
{
gBattleScripting.battler = battler;
gPotentialItemEffectBattler = battler;
effect = ITEM_STATS_CHANGE;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
}
effect = TryEjectPack(battler, ITEMEFFECT_ON_SWITCH_IN);
break;
}
break;

View File

@ -105,7 +105,6 @@ SINGLE_BATTLE_TEST("Eject Pack activates once intimidate mon switches in")
SINGLE_BATTLE_TEST("Eject Pack will not activate if Parting Shot user can switch out")
{
ASSUME(gItemsInfo[ITEM_EJECT_PACK].holdEffect == HOLD_EFFECT_EJECT_PACK);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
PLAYER(SPECIES_WOBBUFFET);
@ -121,3 +120,20 @@ SINGLE_BATTLE_TEST("Eject Pack will not activate if Parting Shot user can switch
}
}
}
DOUBLE_BATTLE_TEST("Eject Pack will not trigger if the conditions are not met")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
PLAYER(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); };
PLAYER(SPECIES_RALTS) { Ability(ABILITY_TRACE); Item(ITEM_EJECT_PACK); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
} WHEN {
TURN { SWITCH(opponentLeft, 2); SEND_OUT(playerLeft, 2); }
} SCENE {
}
}