Fixes Booster Energy timing activation + Clean up (#7175)

Co-authored-by: PhallenTree <168426989+PhallenTree@users.noreply.github.com>
This commit is contained in:
Alex 2025-06-25 18:20:55 +02:00 committed by GitHub
parent f8551830c9
commit 7d7ffd58ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 144 additions and 77 deletions

View File

@ -2562,3 +2562,8 @@
callnative BS_JumpIfNoWhiteOut
.4byte \jumpInstr
.endm
.macro tryboosterenergy onFieldStatus:req
callnative BS_TryBoosterEnergy
.byte \onFieldStatus
.endm

View File

@ -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::

View File

@ -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;

View File

@ -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

View File

@ -306,4 +306,11 @@ enum StatusTrigger
TRIGGER_ON_PROTECT,
};
enum TriggerOnFieldStatus
{
ON_ANY,
ON_TERRAIN,
ON_WEATHER,
};
#endif // GUARD_CONSTANTS_BATTLE_SCRIPT_COMMANDS_H

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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
}
}