diff --git a/include/battle_util.h b/include/battle_util.h index dba6299dee..463d6609db 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -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); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 01b97938ef..55a192958c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -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; diff --git a/src/battle_util.c b/src/battle_util.c index d4debdd0de..f1457eacb3 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -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; diff --git a/test/battle/hold_effect/eject_pack.c b/test/battle/hold_effect/eject_pack.c index bba874e1b3..3d674fe9e8 100644 --- a/test/battle/hold_effect/eject_pack.c +++ b/test/battle/hold_effect/eject_pack.c @@ -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 { + + } +}