diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index ea97d5e10e..a4e0a0cbf2 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2562,3 +2562,8 @@ callnative BS_JumpIfNoWhiteOut .4byte \jumpInstr .endm + + .macro tryboosterenergy onFieldStatus:req + callnative BS_TryBoosterEnergy + .byte \onFieldStatus + .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 60d0f77b9f..13503b0f91 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5561,6 +5561,7 @@ BattleScript_TerrainEnds_Ret:: printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG + tryboosterenergy ON_TERRAIN return BattleScript_TerrainEnds:: @@ -7399,6 +7400,7 @@ BattleScript_ShedSkinActivates:: BattleScript_ActivateWeatherAbilities: saveattacker savetarget + tryboosterenergy ON_WEATHER setbyte gBattlerAttacker, 0 BattleScript_ActivateWeatherAbilities_Loop: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 @@ -7703,6 +7705,7 @@ BattleScript_SnowWarningActivatesSnow:: BattleScript_ActivateTerrainEffects: saveattacker savetarget + tryboosterenergy ON_TERRAIN setbyte gBattlerAttacker, 0 BattleScript_ActivateTerrainSeed: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 @@ -8897,6 +8900,7 @@ BattleScript_ActivateTeraformZero_RemoveTerrain: printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ActivateTeraformZero_End: + tryboosterenergy ON_ANY end3 BattleScript_QuickClawActivation:: diff --git a/include/battle.h b/include/battle.h index 821aa995e1..52af53effc 100644 --- a/include/battle.h +++ b/include/battle.h @@ -128,7 +128,7 @@ struct DisableStruct u8 usedProteanLibero:1; u8 flashFireBoosted:1; u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) - u8 boosterEnergyActivates:1; + u8 boosterEnergyActivated:1; u8 roostActive:1; u8 unburdenActive:1; u8 neutralizingGas:1; diff --git a/include/battle_util.h b/include/battle_util.h index f6c591635b..d1ab994132 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -264,7 +264,7 @@ u32 GetProtectType(enum ProtectMethod method); bool32 CanBattlerEscape(u32 battler); // no ability check void BattleScriptExecute(const u8 *BS_ptr); void BattleScriptPushCursorAndCallback(const u8 *BS_ptr); -u32 ItemBattleEffects(enum ItemCaseId, u32 battler, bool32 moveTurn); +u32 ItemBattleEffects(enum ItemCaseId, u32 battler); void ClearVariousBattlerFlags(u32 battler); void HandleAction_RunBattleScript(void); u32 SetRandomTarget(u32 battler); @@ -396,5 +396,6 @@ void UpdateStallMons(void); bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId); u32 GetMonVolatile(u32 battler, enum Volatile volatile); void SetMonVolatile(u32 battler, enum Volatile volatile, u32 newValue); +u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 630687e0b3..8061399d27 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -306,4 +306,11 @@ enum StatusTrigger TRIGGER_ON_PROTECT, }; +enum TriggerOnFieldStatus +{ + ON_ANY, + ON_TERRAIN, + ON_WEATHER, +}; + #endif // GUARD_CONSTANTS_BATTLE_SCRIPT_COMMANDS_H diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 7d4314c6dd..b63fd3938f 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -512,7 +512,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) { case HOLD_EFFECT_LEFTOVERS: case HOLD_EFFECT_BLACK_SLUDGE: - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) effect = TRUE; break; default: @@ -1423,11 +1423,11 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) case HOLD_EFFECT_FLAME_ORB: case HOLD_EFFECT_STICKY_BARB: case HOLD_EFFECT_TOXIC_ORB: - if (ItemBattleEffects(ITEMEFFECT_ORBS, battler, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_ORBS, battler)) effect = TRUE; break; case HOLD_EFFECT_WHITE_HERB: - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) effect = TRUE; break; default: @@ -1485,7 +1485,7 @@ static bool32 HandleEndTurnFourthEventBlock(u32 battler) enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); if (holdEffect == HOLD_EFFECT_EJECT_PACK) { - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) effect = TRUE; } gBattleStruct->eventBlockCounter = 0; diff --git a/src/battle_main.c b/src/battle_main.c index b62f3d2cc9..7b86856a3e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3869,7 +3869,7 @@ static void TryDoEventsBeforeFirstTurn(void) case FIRST_TURN_EVENTS_ITEM_EFFECTS: while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest { - if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN, gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++], FALSE)) + if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN, gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++])) return; } gBattleStruct->switchInBattlerCounter = 0; @@ -4734,9 +4734,9 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h speed *= 2; else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0) speed /= 2; - else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivates)) + else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivated)) speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; - else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivates)) + else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivated)) speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; else if (ability == ABILITY_UNBURDEN && gDisableStructs[battler].unburdenActive) speed *= 2; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d0784a137e..3008680337 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6378,7 +6378,7 @@ static void Cmd_moveend(void) break; } case MOVEEND_ITEM_EFFECTS_TARGET: - if (ItemBattleEffects(ITEMEFFECT_TARGET, gBattlerTarget, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_TARGET, gBattlerTarget)) effect = TRUE; gBattleScripting.moveendState++; break; @@ -6448,14 +6448,14 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_ITEM_EFFECTS_ALL: // item effects for all battlers - if (ItemBattleEffects(ITEMEFFECT_MOVE_END, 0, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_MOVE_END, 0)) effect = TRUE; else gBattleScripting.moveendState++; break; case MOVEEND_KINGSROCK: // King's rock // These effects will occur at each hit in a multi-strike move - if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0)) effect = TRUE; gBattleScripting.moveendState++; break; @@ -6866,7 +6866,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_ITEM_EFFECTS_ATTACKER: - if (ItemBattleEffects(ITEMEFFECT_MOVE_END, gBattlerAttacker, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_MOVE_END, gBattlerAttacker)) effect = TRUE; gBattleScripting.moveendState++; break; @@ -7047,7 +7047,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_LIFEORB_SHELLBELL: - if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0)) effect = TRUE; gBattleScripting.moveendState++; break; @@ -8143,7 +8143,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gDisableStructs[battler].truantSwitchInHack = 0; - if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler, FALSE)) + if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler)) return TRUE; else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0)) return TRUE; @@ -10962,7 +10962,7 @@ static void Cmd_various(void) case VARIOUS_MOVEEND_ITEM_EFFECTS: { VARIOUS_ARGS(); - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) return; break; } @@ -11235,7 +11235,7 @@ static void Cmd_various(void) gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry = TRUE; gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID - if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler, FALSE)) + if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler)) return; gBattlescriptCurrInstr = cmd->nextInstr; return; @@ -17602,7 +17602,7 @@ void BS_RunStatChangeItems(void) // Change instruction before calling ItemBattleEffects. gBattlescriptCurrInstr = cmd->nextInstr; - ItemBattleEffects(ITEMEFFECT_STATS_CHANGED, GetBattlerForBattleScript(cmd->battler), FALSE); + ItemBattleEffects(ITEMEFFECT_STATS_CHANGED, GetBattlerForBattleScript(cmd->battler)); } static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMove) @@ -18601,6 +18601,28 @@ void BS_JumpIfNoWhiteOut(void) gBattlescriptCurrInstr = cmd->nextInstr; } +void BS_TryBoosterEnergy(void) +{ + NATIVE_ARGS(u8 onFieldStatus); + + for (u32 orderNum = 0; orderNum < gBattlersCount; orderNum++) + { + u32 battlerByTurnOrder = gBattlerByTurnOrder[orderNum]; + if (GetBattlerHoldEffect(battlerByTurnOrder, TRUE) != HOLD_EFFECT_BOOSTER_ENERGY) + continue; + + u32 ability = GetBattlerAbility(battlerByTurnOrder); + if (!(ability == ABILITY_PROTOSYNTHESIS && cmd->onFieldStatus != ON_TERRAIN) + && !(ability == ABILITY_QUARK_DRIVE && cmd->onFieldStatus != ON_WEATHER)) + continue; + + if (TryBoosterEnergy(battlerByTurnOrder, ability, ITEMEFFECT_NONE)) + return; + } + + gBattlescriptCurrInstr = cmd->nextInstr; +} + void BS_JumpIfAbilityCantBeSuppressed(void) { NATIVE_ARGS(u8 battler, const u8 *jumpInstr); diff --git a/src/battle_util.c b/src/battle_util.c index 66e5dfd4e2..8ea025f534 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1755,7 +1755,7 @@ bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck) return TRUE; } -#define FAINTED_ACTIONS_MAX_CASE 7 +#define FAINTED_ACTIONS_MAX_CASE 6 bool32 HandleFaintedMonActions(void) { if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) @@ -1830,19 +1830,14 @@ bool32 HandleFaintedMonActions(void) return TRUE; } } while (++gBattleStruct->faintedActionsBattlerId != gBattlersCount); - gBattleStruct->faintedActionsState = 6; + gBattleStruct->faintedActionsState = FAINTED_ACTIONS_MAX_CASE; break; case 5: if (++gBattleStruct->faintedActionsBattlerId == gBattlersCount) - gBattleStruct->faintedActionsState = 6; + gBattleStruct->faintedActionsState = FAINTED_ACTIONS_MAX_CASE; else gBattleStruct->faintedActionsState = 4; break; - case 6: - if (ItemBattleEffects(ITEMEFFECT_NORMAL, 0, TRUE)) - return TRUE; - gBattleStruct->faintedActionsState++; - break; case FAINTED_ACTIONS_MAX_CASE: break; } @@ -5303,7 +5298,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gDisableStructs[battler].weatherAbilityDone && (gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect() && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) - && !gDisableStructs[battler].boosterEnergyActivates) + && !gDisableStructs[battler].boosterEnergyActivated) { gDisableStructs[battler].weatherAbilityDone = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); @@ -5332,7 +5327,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gDisableStructs[battler].terrainAbilityDone && gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) - && !gDisableStructs[battler].boosterEnergyActivates) + && !gDisableStructs[battler].boosterEnergyActivated) { gDisableStructs[battler].terrainAbilityDone = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); @@ -6256,7 +6251,6 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID) if (gProtectStructs[battler].eatMirrorHerb) { - gLastUsedItem = gBattleMons[battler].item; gBattleScripting.battler = battler; gProtectStructs[battler].eatMirrorHerb = 0; @@ -6270,17 +6264,19 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID) return effect; } -static inline u32 TryBoosterEnergy(u32 battler, enum ItemCaseId caseID) +u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID) { - if (gDisableStructs[battler].boosterEnergyActivates || gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gDisableStructs[battler].boosterEnergyActivated || gBattleMons[battler].status2 & STATUS2_TRANSFORMED) return ITEM_NO_EFFECT; - if (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect())) - || ((GetBattlerAbility(battler) == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))) + if (((ability == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect())) + || ((ability == ABILITY_QUARK_DRIVE) && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN))) { PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); gBattlerAbility = gBattleScripting.battler = battler; - gDisableStructs[battler].boosterEnergyActivates = TRUE; + gDisableStructs[battler].boosterEnergyActivated = TRUE; + gLastUsedItem = ITEM_BOOSTER_ENERGY; + RecordAbilityBattle(battler, ability); if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) BattleScriptExecute(BattleScript_BoosterEnergyEnd2); else @@ -6564,7 +6560,7 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) return effect; } -u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) +u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) { u32 moveType = 0; enum ItemEffect effect = ITEM_NO_EFFECT; @@ -6771,7 +6767,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) effect = TryConsumeMirrorHerb(battler, caseID); break; case HOLD_EFFECT_BOOSTER_ENERGY: - effect = TryBoosterEnergy(battler, caseID); + effect = TryBoosterEnergy(battler, GetBattlerAbility(battler), caseID); break; default: break; @@ -6795,16 +6791,13 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) switch (battlerHoldEffect) { case HOLD_EFFECT_RESTORE_HP: - if (!moveTurn) - effect = ItemHealHp(battler, gLastUsedItem, caseID, FALSE); + effect = ItemHealHp(battler, gLastUsedItem, caseID, FALSE); break; case HOLD_EFFECT_RESTORE_PCT_HP: - if (!moveTurn) - effect = ItemHealHp(battler, gLastUsedItem, caseID, TRUE); + effect = ItemHealHp(battler, gLastUsedItem, caseID, TRUE); break; case HOLD_EFFECT_RESTORE_PP: - if (!moveTurn) - effect = ItemRestorePp(battler, gLastUsedItem, caseID); + effect = ItemRestorePp(battler, gLastUsedItem, caseID); break; case HOLD_EFFECT_WHITE_HERB: effect = RestoreWhiteHerbStats(battler); @@ -6816,7 +6809,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) { goto LEFTOVERS; } - else if (GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD && !moveTurn) + else if (!IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; if (gBattleStruct->moveDamage[battler] == 0) @@ -6829,7 +6822,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_LEFTOVERS: LEFTOVERS: - if (gBattleMons[battler].hp < gBattleMons[battler].maxHP && !moveTurn + if (gBattleMons[battler].hp < gBattleMons[battler].maxHP && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; @@ -6842,47 +6835,37 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_CONFUSE_SPICY: - if (!moveTurn) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, caseID); + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, caseID); break; case HOLD_EFFECT_CONFUSE_DRY: - if (!moveTurn) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, caseID); + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, caseID); break; case HOLD_EFFECT_CONFUSE_SWEET: - if (!moveTurn) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, caseID); + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, caseID); break; case HOLD_EFFECT_CONFUSE_BITTER: - if (!moveTurn) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, caseID); + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, caseID); break; case HOLD_EFFECT_CONFUSE_SOUR: - if (!moveTurn) - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, caseID); + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, caseID); break; case HOLD_EFFECT_ATTACK_UP: - if (!moveTurn) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, caseID); + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, caseID); break; case HOLD_EFFECT_DEFENSE_UP: - if (!moveTurn) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, caseID); + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, caseID); break; case HOLD_EFFECT_SPEED_UP: - if (!moveTurn) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, caseID); + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, caseID); break; case HOLD_EFFECT_SP_ATTACK_UP: - if (!moveTurn) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, caseID); + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, caseID); break; case HOLD_EFFECT_SP_DEFENSE_UP: - if (!moveTurn) - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, caseID); + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, caseID); break; case HOLD_EFFECT_CRITICAL_UP: - if (!moveTurn && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + if (!(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) { gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; @@ -6892,8 +6875,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_RANDOM_STAT_UP: - if (!moveTurn) - effect = RandomStatRaiseBerry(battler, gLastUsedItem, caseID); + effect = RandomStatRaiseBerry(battler, gLastUsedItem, caseID); break; case HOLD_EFFECT_CURE_PAR: if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && !UnnerveOn(battler, gLastUsedItem)) @@ -6964,8 +6946,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_MICLE_BERRY: - if (!moveTurn) - effect = TrySetMicleBerry(battler, gLastUsedItem, caseID); + effect = TrySetMicleBerry(battler, gLastUsedItem, caseID); break; case HOLD_EFFECT_BERSERK_GENE: effect = ConsumeBerserkGene(battler, caseID); @@ -6973,9 +6954,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) case HOLD_EFFECT_MIRROR_HERB: effect = TryConsumeMirrorHerb(battler, caseID); break; - case HOLD_EFFECT_BOOSTER_ENERGY: - effect = TryBoosterEnergy(battler, caseID); - break; default: break; } @@ -8469,7 +8447,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) case ABILITY_PROTOSYNTHESIS: { u8 defHighestStat = GetHighestStatId(battlerDef); - if (((ctx->weather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battlerDef].boosterEnergyActivates) + if (((ctx->weather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battlerDef].boosterEnergyActivated) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); @@ -8478,7 +8456,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) case ABILITY_QUARK_DRIVE: { u8 defHighestStat = GetHighestStatId(battlerDef); - if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerDef].boosterEnergyActivates) + if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerDef].boosterEnergyActivated) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); @@ -8726,7 +8704,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) { u32 atkHighestStat = GetHighestStatId(battlerAtk); - if (((ctx->weather & B_WEATHER_SUN) && HasWeatherEffect()) || gDisableStructs[battlerAtk].boosterEnergyActivates) + if (((ctx->weather & B_WEATHER_SUN) && HasWeatherEffect()) || gDisableStructs[battlerAtk].boosterEnergyActivated) { if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); @@ -8737,7 +8715,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) { u32 atkHighestStat = GetHighestStatId(battlerAtk); - if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerAtk].boosterEnergyActivates) + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerAtk].boosterEnergyActivated) { if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); @@ -11396,7 +11374,7 @@ bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId) if (gItemsInfo[gBattleMons[battler].item].pocket == POCKET_BERRIES || GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RESTORE_HP) // Edge case for Berry Juice { - if (ItemBattleEffects(caseId, battler, FALSE)) + if (ItemBattleEffects(caseId, battler)) return TRUE; } return FALSE; diff --git a/test/battle/hold_effect/booster_energy.c b/test/battle/hold_effect/booster_energy.c index f6f44a272c..41e5fe3b47 100644 --- a/test/battle/hold_effect/booster_energy.c +++ b/test/battle/hold_effect/booster_energy.c @@ -234,3 +234,53 @@ DOUBLE_BATTLE_TEST("Booster Energy triggers correctly for all battlers if multip ABILITY_POPUP(opponentLeft, ABILITY_PROTOSYNTHESIS); } } + +DOUBLE_BATTLE_TEST("Booster Energy activates on any terrain") +{ + GIVEN { + PLAYER(SPECIES_IRON_MOTH) { Speed(110); Ability(ABILITY_QUARK_DRIVE); Item(ITEM_BOOSTER_ENERGY); } + PLAYER(SPECIES_WOBBUFFET) { Speed(80); } + OPPONENT(SPECIES_TAPU_BULU) { Speed(100); Ability(ABILITY_GRASSY_SURGE); } + OPPONENT(SPECIES_TAPU_KOKO) { Speed(10); Ability(ABILITY_ELECTRIC_SURGE); }; + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(opponentLeft, ABILITY_GRASSY_SURGE); + ABILITY_POPUP(playerLeft, ABILITY_QUARK_DRIVE); + ABILITY_POPUP(opponentRight, ABILITY_ELECTRIC_SURGE); + } +} + +DOUBLE_BATTLE_TEST("Booster Energy activates on air locked sun") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_RAGING_BOLT) { Ability(ABILITY_PROTOSYNTHESIS); Item(ITEM_BOOSTER_ENERGY); } + OPPONENT(SPECIES_PSYDUCK) { Ability(ABILITY_CLOUD_NINE); } + OPPONENT(SPECIES_TORKOAL) { Ability(ABILITY_DROUGHT); }; + } WHEN { + TURN { SWITCH(playerLeft, 2); } + } SCENE { + ABILITY_POPUP(opponentLeft, ABILITY_CLOUD_NINE); + ABILITY_POPUP(opponentRight, ABILITY_DROUGHT); + ABILITY_POPUP(playerLeft, ABILITY_PROTOSYNTHESIS); + } +} + +DOUBLE_BATTLE_TEST("Booster Energy will not activate on terrain if user has Protosynthesis instead of Quark Drive") +{ + GIVEN { + PLAYER(SPECIES_RAGING_BOLT) { Speed(110); Ability(ABILITY_PROTOSYNTHESIS); Item(ITEM_BOOSTER_ENERGY); } + PLAYER(SPECIES_WOBBUFFET) { Speed(80); } + OPPONENT(SPECIES_TAPU_BULU) { Speed(100); Ability(ABILITY_GRASSY_SURGE); } + OPPONENT(SPECIES_TAPU_KOKO) { Speed(10); Ability(ABILITY_ELECTRIC_SURGE); }; + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(opponentLeft, ABILITY_GRASSY_SURGE); + NOT ABILITY_POPUP(playerLeft, ABILITY_PROTOSYNTHESIS); + ABILITY_POPUP(opponentRight, ABILITY_ELECTRIC_SURGE); + ABILITY_POPUP(playerLeft, ABILITY_PROTOSYNTHESIS); // Activation after all terrains + } +}