Fixed Belly Drum/Contrary interaction at max Attack (#8078)
This commit is contained in:
parent
c77c624e9f
commit
8de86ba243
@ -187,8 +187,13 @@
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro unused_0x21
|
||||
.macro jumpifstatignorecontrary battler:req, comparison:req, stat:req, value:req, jumpInstr:req
|
||||
.byte 0x21
|
||||
.byte \battler
|
||||
.byte \comparison
|
||||
.byte \stat
|
||||
.byte \value
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro jumpbasedontype battler:req, type:req, jumpIfType:req, jumpInstr:req
|
||||
|
||||
@ -4221,7 +4221,7 @@ BattleScript_EffectBellyDrum::
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed
|
||||
jumpifstatignorecontrary BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed
|
||||
halvehp BattleScript_ButItFailed
|
||||
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE
|
||||
attackanimation
|
||||
|
||||
@ -332,7 +332,7 @@ bool32 IsPartnerMonFromSameTrainer(u32 battler);
|
||||
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);
|
||||
bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind, u32 ability);
|
||||
bool32 TryRoomService(u32 battler);
|
||||
void BufferStatChange(u32 battler, u8 statId, enum StringID stringId);
|
||||
bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget);
|
||||
|
||||
@ -370,7 +370,7 @@ static void Cmd_jumpifvolatile(void);
|
||||
static void Cmd_jumpifability(void);
|
||||
static void Cmd_jumpifsideaffecting(void);
|
||||
static void Cmd_jumpifstat(void);
|
||||
static void Cmd_unused_0x21(void);
|
||||
static void Cmd_jumpifstatignorecontrary(void);
|
||||
static void Cmd_jumpbasedontype(void);
|
||||
static void Cmd_getexp(void);
|
||||
static void Cmd_checkteamslost(void);
|
||||
@ -629,7 +629,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
||||
Cmd_jumpifability, //0x1E
|
||||
Cmd_jumpifsideaffecting, //0x1F
|
||||
Cmd_jumpifstat, //0x20
|
||||
Cmd_unused_0x21, //0x21
|
||||
Cmd_jumpifstatignorecontrary, //0x21
|
||||
Cmd_jumpbasedontype, //0x22
|
||||
Cmd_getexp, //0x23
|
||||
Cmd_checkteamslost, //0x24
|
||||
@ -4432,7 +4432,7 @@ static void Cmd_jumpifstat(void)
|
||||
u8 value = cmd->value;
|
||||
u8 comparison = cmd->comparison;
|
||||
|
||||
ret = CompareStat(battler, stat, value, comparison);
|
||||
ret = CompareStat(battler, stat, value, comparison, GetBattlerAbility(battler));
|
||||
|
||||
if (ret)
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
@ -4440,8 +4440,22 @@ static void Cmd_jumpifstat(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void Cmd_unused_0x21(void)
|
||||
static void Cmd_jumpifstatignorecontrary(void)
|
||||
{
|
||||
CMD_ARGS(u8 battler, u8 comparison, u8 stat, u8 value, const u8 *jumpInstr);
|
||||
|
||||
bool32 ret = 0;
|
||||
u8 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
u8 stat = cmd->stat;
|
||||
u8 value = cmd->value;
|
||||
u8 comparison = cmd->comparison;
|
||||
|
||||
ret = CompareStat(battler, stat, value, comparison, ABILITY_NONE);
|
||||
|
||||
if (ret)
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void Cmd_jumpbasedontype(void)
|
||||
@ -5620,7 +5634,7 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move
|
||||
else if (abilityAtk == ABILITY_GRIM_NEIGH || abilityAtk == ABILITY_AS_ONE_SHADOW_RIDER)
|
||||
stat = STAT_SPATK;
|
||||
|
||||
if (numMonsFainted && CompareStat(battlerAtk, stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (numMonsFainted && CompareStat(battlerAtk, stat, MAX_STAT_STAGE, CMP_LESS_THAN, abilityAtk))
|
||||
{
|
||||
gLastUsedAbility = abilityAtk;
|
||||
if (abilityAtk == ABILITY_AS_ONE_ICE_RIDER)
|
||||
@ -5660,17 +5674,17 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move
|
||||
else
|
||||
{
|
||||
u32 numStatBuffs = 0;
|
||||
if (CompareStat(battlerAtk, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(battlerAtk, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, abilityAtk))
|
||||
{
|
||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_ATK) + STAT_ANIM_PLUS1;
|
||||
numStatBuffs++;
|
||||
}
|
||||
if (CompareStat(battlerAtk, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(battlerAtk, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, abilityAtk))
|
||||
{
|
||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_SPATK) + STAT_ANIM_PLUS1;
|
||||
numStatBuffs++;
|
||||
}
|
||||
if (CompareStat(battlerAtk, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(battlerAtk, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, abilityAtk))
|
||||
{
|
||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_SPEED) + STAT_ANIM_PLUS1;
|
||||
numStatBuffs++;
|
||||
@ -5876,7 +5890,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect)
|
||||
&& !IsBattlerAlive(gBattlerTarget)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerAttacker)))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE);
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK);
|
||||
@ -6106,7 +6120,7 @@ static void Cmd_moveend(void)
|
||||
&& !IsBattlerAlly(gBattlerAttacker, gBattlerTarget)
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& !IsBattleMoveStatus(gCurrentMove)
|
||||
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget)))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||
BattleScriptCall(BattleScript_RageIsBuilding);
|
||||
@ -6522,7 +6536,7 @@ static void Cmd_moveend(void)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_THROAT_SPRAY
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& IsAnyTargetAffected(gBattlerAttacker)
|
||||
&& CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
&& CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerAttacker))
|
||||
&& !NoAliveMonsForEitherParty()) // Don't activate if battle will end
|
||||
{
|
||||
gLastUsedItem = gBattleMons[gBattlerAttacker].item;
|
||||
@ -12089,7 +12103,7 @@ static void Cmd_jumpifconfusedandstatmaxed(void)
|
||||
CMD_ARGS(u8 stat, const u8 *jumpInstr);
|
||||
|
||||
if (gBattleMons[gBattlerTarget].volatiles.confusionTurns > 0
|
||||
&& !CompareStat(gBattlerTarget, cmd->stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& !CompareStat(gBattlerTarget, cmd->stat, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget)))
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr; // Fails if we're confused AND stat cannot be raised
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
@ -16014,7 +16028,7 @@ void BS_CanTarShotWork(void)
|
||||
NATIVE_ARGS(const u8 *failInstr);
|
||||
// Tar Shot will fail if it's already been used on the target or if its speed can't be lowered further
|
||||
if (!gDisableStructs[gBattlerTarget].tarShot
|
||||
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget)))
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
@ -16968,7 +16982,7 @@ void BS_TryAcupressure(void)
|
||||
u32 bits = 0;
|
||||
for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++)
|
||||
{
|
||||
if (CompareStat(gBattlerTarget, stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(gBattlerTarget, stat, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget)))
|
||||
bits |= 1u << stat;
|
||||
}
|
||||
if (bits)
|
||||
@ -17367,10 +17381,11 @@ void BS_TryActivateSoulheart(void)
|
||||
while (gBattleStruct->soulheartBattlerId < gBattlersCount)
|
||||
{
|
||||
gBattleScripting.battler = gBattleStruct->soulheartBattlerId++;
|
||||
if (GetBattlerAbility(gBattleScripting.battler) == ABILITY_SOUL_HEART
|
||||
u32 ability = GetBattlerAbility(gBattleScripting.battler);
|
||||
if (ability == ABILITY_SOUL_HEART
|
||||
&& IsBattlerAlive(gBattleScripting.battler)
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, ability))
|
||||
{
|
||||
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK);
|
||||
@ -18278,10 +18293,11 @@ void BS_CutOneThirdHpAndRaiseStats(void)
|
||||
|
||||
bool8 atLeastOneStatBoosted = FALSE;
|
||||
u16 hpFraction = max(1, GetNonDynamaxMaxHP(gBattlerAttacker) / 3);
|
||||
u32 ability = GetBattlerAbility(gBattlerAttacker);
|
||||
|
||||
for (u32 stat = 1; stat < NUM_STATS; stat++)
|
||||
{
|
||||
if (CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_LESS_THAN, ability))
|
||||
{
|
||||
atLeastOneStatBoosted = TRUE;
|
||||
break;
|
||||
|
||||
@ -1196,7 +1196,7 @@ void PrepareStringBattle(enum StringID stringId, u32 battler)
|
||||
else if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8
|
||||
&& stringId == STRINGID_PKMNCUTSATTACKWITH
|
||||
&& targetAbility == ABILITY_RATTLED
|
||||
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, targetAbility))
|
||||
{
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
BattleScriptCall(BattleScript_AbilityRaisesDefenderStat);
|
||||
@ -1702,13 +1702,13 @@ u32 GetBattlerAffectionHearts(u32 battler)
|
||||
// gBattlerAttacker is the battler that's trying to raise their stats and due to limitations of RandomUniformExcept, cannot be an argument
|
||||
bool32 MoodyCantRaiseStat(u32 stat)
|
||||
{
|
||||
return CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_EQUAL);
|
||||
return CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_EQUAL, GetBattlerAbility(gBattlerAttacker));
|
||||
}
|
||||
|
||||
// gBattlerAttacker is the battler that's trying to lower their stats and due to limitations of RandomUniformExcept, cannot be an argument
|
||||
bool32 MoodyCantLowerStat(u32 stat)
|
||||
{
|
||||
return stat == GET_STAT_BUFF_ID(gBattleScripting.statChanger) || CompareStat(gBattlerAttacker, stat, MIN_STAT_STAGE, CMP_EQUAL);
|
||||
return stat == GET_STAT_BUFF_ID(gBattleScripting.statChanger) || CompareStat(gBattlerAttacker, stat, MIN_STAT_STAGE, CMP_EQUAL, GetBattlerAbility(gBattlerAttacker));
|
||||
}
|
||||
|
||||
void TryToRevertMimicryAndFlags(void)
|
||||
@ -3213,7 +3213,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32
|
||||
break;
|
||||
case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY:
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN, abilityDef))
|
||||
{
|
||||
if ((gProtectStructs[battlerAtk].notFirstStrike))
|
||||
battleScript = BattleScript_MonMadeMoveUseless;
|
||||
@ -3776,7 +3776,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
|
||||
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
@ -3988,7 +3988,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (GetGenConfig(GEN_INTREPID_SWORD) == GEN_9)
|
||||
GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||
@ -4003,7 +4003,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (GetGenConfig(GEN_DAUNTLESS_SHIELD) == GEN_9)
|
||||
GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||
@ -4013,7 +4013,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
break;
|
||||
case ABILITY_WIND_RIDER:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)
|
||||
&& gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
@ -4149,7 +4149,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
else //ABILITY_EMBODY_ASPECT_TEAL_MASK
|
||||
stat = STAT_SPEED;
|
||||
|
||||
if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_EQUAL))
|
||||
if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_EQUAL, gLastUsedAbility))
|
||||
break;
|
||||
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
@ -4302,7 +4302,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
break;
|
||||
case ABILITY_SPEED_BOOST:
|
||||
if (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) && gDisableStructs[battler].isFirstTurn != 2)
|
||||
if (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility) && gDisableStructs[battler].isFirstTurn != 2)
|
||||
{
|
||||
SET_STATCHANGER(STAT_SPEED, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_SpeedBoostActivates);
|
||||
@ -4318,9 +4318,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
|
||||
for (i = STAT_ATK; i < statsNum; i++)
|
||||
{
|
||||
if (CompareStat(battler, i, MIN_STAT_STAGE, CMP_GREATER_THAN))
|
||||
if (CompareStat(battler, i, MIN_STAT_STAGE, CMP_GREATER_THAN, gLastUsedAbility))
|
||||
validToLower |= 1u << i;
|
||||
if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
validToRaise |= 1u << i;
|
||||
}
|
||||
|
||||
@ -4457,7 +4457,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (IsBattlerTurnDamaged(battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& moveType == TYPE_DARK
|
||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
gEffectBattler = battler;
|
||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||
@ -4469,7 +4469,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (IsBattlerTurnDamaged(battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST)
|
||||
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
gEffectBattler = battler;
|
||||
SET_STATCHANGER(STAT_SPEED, 1, FALSE);
|
||||
@ -4481,7 +4481,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (IsBattlerTurnDamaged(battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& moveType == TYPE_WATER
|
||||
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
gEffectBattler = battler;
|
||||
SET_STATCHANGER(STAT_DEF, 2, FALSE);
|
||||
@ -4493,7 +4493,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (gBattlerAttacker != gBattlerTarget
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
gEffectBattler = battler;
|
||||
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
||||
@ -4507,7 +4507,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& HadMoreThanHalfHpNowDoesnt(battler)
|
||||
&& (gMultiHitCounter == 0 || gMultiHitCounter == 1)
|
||||
&& !(TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove))
|
||||
&& CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
gEffectBattler = battler;
|
||||
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||
@ -4519,8 +4519,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (IsBattlerTurnDamaged(battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& IsBattleMovePhysical(gCurrentMove)
|
||||
&& (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) // Don't activate if both Speed and Defense cannot be raised.
|
||||
|| CompareStat(battler, STAT_DEF, MIN_STAT_STAGE, CMP_GREATER_THAN)))
|
||||
&& (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility) // Don't activate if both Speed and Defense cannot be raised.
|
||||
|| CompareStat(battler, STAT_DEF, MIN_STAT_STAGE, CMP_GREATER_THAN, gLastUsedAbility)))
|
||||
{
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_HIT_ESCAPE && CanBattlerSwitch(gBattlerAttacker))
|
||||
gProtectStructs[battler].disableEjectPack = TRUE; // Set flag for target
|
||||
@ -4597,7 +4597,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (gSpecialStatuses[battler].criticalHit
|
||||
&& IsBattlerTurnDamaged(battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, MAX_STAT_STAGE - gBattleMons[battler].statStages[STAT_ATK], FALSE);
|
||||
BattleScriptCall(BattleScript_TargetsStatWasMaxedOut);
|
||||
@ -4622,7 +4622,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_GOOEY:
|
||||
case ABILITY_TANGLING_HAIR:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR)
|
||||
&& (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, gLastUsedAbility) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR)
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move))
|
||||
@ -4830,7 +4830,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_STEAM_ENGINE:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)
|
||||
&& (moveType == TYPE_FIRE || moveType == TYPE_WATER))
|
||||
{
|
||||
gEffectBattler = battler;
|
||||
@ -4916,7 +4916,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_THERMAL_EXCHANGE:
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)
|
||||
&& moveType == TYPE_FIRE)
|
||||
{
|
||||
gEffectBattler = gBattlerTarget;
|
||||
@ -5870,11 +5870,12 @@ static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, e
|
||||
|
||||
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))
|
||||
u32 ability = GetBattlerAbility(battler);
|
||||
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, ability) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId))
|
||||
{
|
||||
BufferStatChange(battler, statId, STRINGID_STATROSE);
|
||||
gEffectBattler = gBattleScripting.battler = battler;
|
||||
if (GetBattlerAbility(battler) == ABILITY_RIPEN)
|
||||
if (ability == ABILITY_RIPEN)
|
||||
SET_STATCHANGER(statId, 2, FALSE);
|
||||
else
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
@ -5895,15 +5896,15 @@ static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemCa
|
||||
{
|
||||
s32 stat;
|
||||
enum StringID stringId;
|
||||
u32 battlerAbility = GetBattlerAbility(battler);
|
||||
|
||||
for (stat = STAT_ATK; stat < NUM_STATS; stat++)
|
||||
{
|
||||
if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_LESS_THAN, battlerAbility))
|
||||
break;
|
||||
}
|
||||
if (stat != NUM_STATS && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId))
|
||||
{
|
||||
u16 battlerAbility = GetBattlerAbility(battler);
|
||||
u32 savedAttacker = gBattlerAttacker;
|
||||
// MoodyCantRaiseStat requires that the battler is set to gBattlerAttacker
|
||||
gBattlerAttacker = gBattleScripting.battler = battler;
|
||||
@ -5976,8 +5977,9 @@ static enum ItemEffect TrySetEnigmaBerry(u32 battler)
|
||||
|
||||
static enum ItemEffect DamagedStatBoostBerryEffect(u32 battler, u8 statId, enum DamageCategory category)
|
||||
{
|
||||
u32 ability = GetBattlerAbility(battler);
|
||||
if (IsBattlerAlive(battler)
|
||||
&& CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
&& CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, ability)
|
||||
&& (gBattleScripting.overrideBerryRequirements
|
||||
|| (!DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
|
||||
&& GetBattleMoveCategory(gCurrentMove) == category
|
||||
@ -5988,7 +5990,7 @@ static enum ItemEffect DamagedStatBoostBerryEffect(u32 battler, u8 statId, enum
|
||||
BufferStatChange(battler, statId, STRINGID_STATROSE);
|
||||
|
||||
gEffectBattler = battler;
|
||||
if (GetBattlerAbility(battler) == ABILITY_RIPEN)
|
||||
if (ability == ABILITY_RIPEN)
|
||||
SET_STATCHANGER(statId, 2, FALSE);
|
||||
else
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
@ -6004,7 +6006,7 @@ static enum ItemEffect DamagedStatBoostBerryEffect(u32 battler, u8 statId, enum
|
||||
|
||||
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))
|
||||
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battler)))
|
||||
{
|
||||
BufferStatChange(battler, statId, STRINGID_STATROSE);
|
||||
gLastUsedItem = itemId; // For surge abilities
|
||||
@ -6961,7 +6963,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler)
|
||||
case HOLD_EFFECT_BLUNDER_POLICY:
|
||||
if (gBattleStruct->blunderPolicy
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& CompareStat(gBattlerAttacker, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
&& CompareStat(gBattlerAttacker, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerAttacker)))
|
||||
{
|
||||
gBattleStruct->blunderPolicy = FALSE;
|
||||
gLastUsedItem = atkItem;
|
||||
@ -10757,15 +10759,15 @@ bool32 TestIfSheerForceAffected(u32 battler, u16 move)
|
||||
return GetBattlerAbility(battler) == ABILITY_SHEER_FORCE && MoveIsAffectedBySheerForce(move);
|
||||
}
|
||||
|
||||
// This function is the body of "jumpifstat", but can be used dynamically in a function
|
||||
bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind)
|
||||
// This function is the body of "jumpifstat", but can be used dynamically in a function. It considers Contrary.
|
||||
bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind, u32 ability)
|
||||
{
|
||||
bool32 ret = FALSE;
|
||||
u8 statValue = gBattleMons[battler].statStages[statId];
|
||||
|
||||
// Because this command is used as a way of checking if a stat can be lowered/raised,
|
||||
// we need to do some modification at run-time.
|
||||
if (GetBattlerAbility(battler) == ABILITY_CONTRARY)
|
||||
if (ability == ABILITY_CONTRARY)
|
||||
{
|
||||
if (cmpKind == CMP_GREATER_THAN)
|
||||
cmpKind = CMP_LESS_THAN;
|
||||
@ -10836,7 +10838,7 @@ void BufferStatChange(u32 battler, u8 statId, enum StringID stringId)
|
||||
|
||||
bool32 TryRoomService(u32 battler)
|
||||
{
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN))
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, GetBattlerAbility(battler)))
|
||||
{
|
||||
BufferStatChange(battler, STAT_SPEED, STRINGID_STATFELL);
|
||||
gEffectBattler = gBattleScripting.battler = battler;
|
||||
|
||||
@ -128,7 +128,7 @@ static void SetUpItemUseCallback(u8 taskId)
|
||||
type = gTasks[taskId].tEnigmaBerryType - 1;
|
||||
else
|
||||
type = GetItemType(gSpecialVar_ItemId) - 1;
|
||||
|
||||
|
||||
if (gTasks[taskId].tUsingRegisteredKeyItem && type == (ITEM_USE_PARTY_MENU - 1))
|
||||
{
|
||||
FadeScreen(FADE_TO_BLACK, 0);
|
||||
@ -1291,15 +1291,18 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon)
|
||||
}
|
||||
break;
|
||||
case EFFECT_ITEM_INCREASE_ALL_STATS:
|
||||
{
|
||||
u32 ability = GetBattlerAbility(gBattlerInMenuId);
|
||||
for (i = STAT_ATK; i < NUM_STATS; i++)
|
||||
{
|
||||
if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL))
|
||||
if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL, ability))
|
||||
{
|
||||
cannotUse = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EFFECT_ITEM_RESTORE_HP:
|
||||
if (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))
|
||||
cannotUse = TRUE;
|
||||
|
||||
@ -159,7 +159,6 @@ SINGLE_BATTLE_TEST("Belly Drum maximizes the user's Attack stat, even when below
|
||||
|
||||
SINGLE_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6, even with Contrary")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_CHARM) == EFFECT_ATTACK_DOWN_2);
|
||||
PLAYER(SPECIES_SERPERIOR) { Ability(ABILITY_CONTRARY); }
|
||||
@ -190,7 +189,6 @@ SINGLE_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6, even
|
||||
|
||||
SINGLE_BATTLE_TEST("Belly Drum deducts HP if the user has Contrary and is at -6")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
|
||||
PLAYER(SPECIES_SERPERIOR) { Ability(ABILITY_CONTRARY); }
|
||||
@ -215,6 +213,6 @@ SINGLE_BATTLE_TEST("Belly Drum deducts HP if the user has Contrary and is at -6"
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player);
|
||||
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
|
||||
HP_BAR(player, hp: maxHP / 2);
|
||||
MESSAGE("Wobbuffet cut its own HP and maximized its Attack!");
|
||||
MESSAGE("Serperior cut its own HP and maximized its Attack!");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user