CanAbilityX Function Cleanup (#6183)
Co-authored-by: ghoulslash <pokevoyager0@gmail.com>
This commit is contained in:
parent
cad1a37566
commit
dc21befcc9
@ -22,13 +22,10 @@
|
||||
#define MOVE_LIMITATION_PLACEHOLDER (1 << 15)
|
||||
#define MOVE_LIMITATIONS_ALL 0xFFFF
|
||||
|
||||
enum MoveBlocked
|
||||
enum AbilityEffectOptions
|
||||
{
|
||||
MOVE_BLOCKED_BY_NO_ABILITY,
|
||||
MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF,
|
||||
MOVE_BLOCKED_BY_DAZZLING,
|
||||
MOVE_BLOCKED_BY_PARTNER_DAZZLING,
|
||||
MOVE_BLOCKED_BY_GOOD_AS_GOLD,
|
||||
ABILITY_CHECK_TRIGGER,
|
||||
ABILITY_RUN_SCRIPT,
|
||||
};
|
||||
|
||||
enum MoveAbsorbed
|
||||
@ -216,9 +213,8 @@ u32 AtkCanceller_MoveSuccessOrder(void);
|
||||
void SetAtkCancellerForCalledMove(void);
|
||||
bool32 HasNoMonsToSwitch(u32 battler, u8 r1, u8 r2);
|
||||
bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility);
|
||||
u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef);
|
||||
u32 CanPartnerAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef);
|
||||
u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType);
|
||||
bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef, enum AbilityEffectOptions option);
|
||||
bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum AbilityEffectOptions option);
|
||||
u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg);
|
||||
bool32 TryPrimalReversion(u32 battler);
|
||||
bool32 IsNeutralizingGasOnField(void);
|
||||
|
||||
@ -893,10 +893,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
// target ability checks
|
||||
if (!DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move))
|
||||
{
|
||||
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef]))
|
||||
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef], FALSE))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
|
||||
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType))
|
||||
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType, FALSE))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
|
||||
switch (aiData->abilities[battlerDef])
|
||||
@ -997,9 +997,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
// target partner ability checks & not attacking partner
|
||||
if (isDoubleBattle)
|
||||
{
|
||||
if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[BATTLE_PARTNER(battlerDef)]))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
|
||||
switch (aiData->abilities[BATTLE_PARTNER(battlerDef)])
|
||||
{
|
||||
case ABILITY_LIGHTNING_ROD:
|
||||
|
||||
@ -424,18 +424,11 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy
|
||||
{
|
||||
struct AiLogicData *aiData = AI_DATA;
|
||||
u32 battlerDefAbility;
|
||||
u32 partnerBattlerDefAbility;
|
||||
|
||||
if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move))
|
||||
{
|
||||
battlerDefAbility = ABILITY_NONE;
|
||||
partnerBattlerDefAbility = ABILITY_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
battlerDefAbility = aiData->abilities[battlerDef];
|
||||
partnerBattlerDefAbility = aiData->abilities[BATTLE_PARTNER(battlerDef)];
|
||||
}
|
||||
|
||||
if (battlerDef == BATTLE_PARTNER(battlerAtk))
|
||||
battlerDefAbility = aiData->abilities[battlerDef];
|
||||
@ -443,13 +436,10 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy
|
||||
if (gBattleStruct->battlerState[battlerDef].commandingDondozo)
|
||||
return TRUE;
|
||||
|
||||
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef]))
|
||||
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef], FALSE))
|
||||
return TRUE;
|
||||
|
||||
if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, partnerBattlerDefAbility))
|
||||
return TRUE;
|
||||
|
||||
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType))
|
||||
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType, FALSE))
|
||||
return TRUE;
|
||||
|
||||
switch (GetMoveEffect(move))
|
||||
|
||||
@ -4229,67 +4229,87 @@ static void ChooseStatBoostAnimation(u32 battler)
|
||||
#undef ANIM_STAT_ACC
|
||||
#undef ANIM_STAT_EVASION
|
||||
|
||||
u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef)
|
||||
bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef, enum AbilityEffectOptions option)
|
||||
{
|
||||
enum MoveBlocked effect = MOVE_BLOCKED_BY_NO_ABILITY;
|
||||
|
||||
const u8 *battleScriptBlocksMove = NULL;
|
||||
u32 atkPriority = AI_DATA->aiCalcInProgress ? GetBattleMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk);
|
||||
u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move);
|
||||
u32 battlerAbility = battlerDef;
|
||||
|
||||
switch (abilityDef)
|
||||
{
|
||||
case ABILITY_SOUNDPROOF:
|
||||
if (IsSoundMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER))
|
||||
effect = MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF;
|
||||
if (IsSoundMove(move) && !(moveTarget & MOVE_TARGET_USER))
|
||||
{
|
||||
if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS)
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
battleScriptBlocksMove = BattleScript_SoundproofProtected;
|
||||
}
|
||||
break;
|
||||
case ABILITY_BULLETPROOF:
|
||||
if (IsBallisticMove(move))
|
||||
effect = MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF;
|
||||
{
|
||||
if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS)
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
battleScriptBlocksMove = BattleScript_SoundproofProtected;
|
||||
}
|
||||
break;
|
||||
case ABILITY_DAZZLING:
|
||||
case ABILITY_QUEENLY_MAJESTY:
|
||||
case ABILITY_ARMOR_TAIL:
|
||||
if (GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef))
|
||||
if (atkPriority > 0 && !IsAlly(battlerAtk, battlerDef))
|
||||
{
|
||||
u32 priority = AI_DATA->aiCalcInProgress ? GetBattleMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk);
|
||||
if (priority > 0)
|
||||
effect = MOVE_BLOCKED_BY_DAZZLING;
|
||||
if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS)
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
battleScriptBlocksMove = BattleScript_DazzlingProtected;
|
||||
}
|
||||
break;
|
||||
case ABILITY_GOOD_AS_GOLD:
|
||||
if (IsBattleMoveStatus(move))
|
||||
{
|
||||
u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move);
|
||||
if (!(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) && !(moveTarget & MOVE_TARGET_ALL_BATTLERS))
|
||||
effect = MOVE_BLOCKED_BY_GOOD_AS_GOLD;
|
||||
battleScriptBlocksMove = BattleScript_GoodAsGoldActivates;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!effect)
|
||||
effect = CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, GetBattlerAbility(BATTLE_PARTNER(battlerDef)));
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
u32 CanPartnerAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef)
|
||||
{
|
||||
switch (abilityDef)
|
||||
// Check def partner ability
|
||||
if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battlerDef)))
|
||||
{
|
||||
case ABILITY_DAZZLING:
|
||||
case ABILITY_QUEENLY_MAJESTY:
|
||||
case ABILITY_ARMOR_TAIL:
|
||||
if (GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef))
|
||||
switch (GetBattlerAbility(BATTLE_PARTNER(battlerDef)))
|
||||
{
|
||||
s32 priority = AI_DATA->aiCalcInProgress ? GetBattleMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk);
|
||||
if (priority > 0)
|
||||
return MOVE_BLOCKED_BY_PARTNER_DAZZLING;
|
||||
case ABILITY_DAZZLING:
|
||||
case ABILITY_QUEENLY_MAJESTY:
|
||||
case ABILITY_ARMOR_TAIL:
|
||||
if (atkPriority > 0 && !IsAlly(battlerAtk, BATTLE_PARTNER(battlerDef)))
|
||||
{
|
||||
if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS)
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
battlerAbility = BATTLE_PARTNER(battlerDef);
|
||||
battleScriptBlocksMove = BattleScript_DazzlingProtected;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return MOVE_BLOCKED_BY_NO_ABILITY;
|
||||
|
||||
if (battleScriptBlocksMove == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (option == ABILITY_RUN_SCRIPT)
|
||||
{
|
||||
gBattleScripting.battler = gBattlerAbility = battlerAbility;
|
||||
gBattlescriptCurrInstr = battleScriptBlocksMove;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType)
|
||||
bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum AbilityEffectOptions option)
|
||||
{
|
||||
enum MoveAbsorbed effect = MOVE_ABSORBED_BY_NO_ABILITY;
|
||||
const u8 *battleScript = NULL;
|
||||
u32 statId = 0;
|
||||
u32 statAmount = 1;
|
||||
|
||||
switch (abilityDef)
|
||||
{
|
||||
@ -4311,33 +4331,130 @@ u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 mov
|
||||
break;
|
||||
case ABILITY_MOTOR_DRIVE:
|
||||
if (moveType == TYPE_ELECTRIC && GetMoveTarget(move) != MOVE_TARGET_ALL_BATTLERS) // Potential bug in singles (might be solved with simu hp reudction)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_SPEED;
|
||||
}
|
||||
break;
|
||||
case ABILITY_LIGHTNING_ROD:
|
||||
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && GetMoveTarget(move) != MOVE_TARGET_ALL_BATTLERS) // Potential bug in singles (might be solved with simu hp reudction)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_SPATK;
|
||||
}
|
||||
break;
|
||||
case ABILITY_STORM_DRAIN:
|
||||
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_WATER)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_SPATK;
|
||||
}
|
||||
break;
|
||||
case ABILITY_SAP_SIPPER:
|
||||
if (moveType == TYPE_GRASS)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_ATK;
|
||||
}
|
||||
break;
|
||||
case ABILITY_WELL_BAKED_BODY:
|
||||
if (moveType == TYPE_FIRE)
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statAmount = 2;
|
||||
statId = STAT_DEF;
|
||||
}
|
||||
break;
|
||||
case ABILITY_WIND_RIDER:
|
||||
if (IsWindMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER))
|
||||
{
|
||||
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
|
||||
statId = STAT_ATK;
|
||||
}
|
||||
break;
|
||||
case ABILITY_FLASH_FIRE:
|
||||
if (moveType == TYPE_FIRE && (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[battlerDef].status1 & STATUS1_FREEZE)))
|
||||
effect = MOVE_ABSORBED_BY_BOOST_FLASH_FIRE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (effect == MOVE_ABSORBED_BY_NO_ABILITY || option == ABILITY_CHECK_TRIGGER)
|
||||
return effect;
|
||||
|
||||
switch (effect)
|
||||
{
|
||||
default:
|
||||
return FALSE;
|
||||
case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY:
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (IsBattlerAtMaxHp(battlerDef) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK))
|
||||
{
|
||||
if ((gProtectStructs[battlerAtk].notFirstStrike))
|
||||
battleScript = BattleScript_MonMadeMoveUseless;
|
||||
else
|
||||
battleScript = BattleScript_MonMadeMoveUseless_PPLoss;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gProtectStructs[battlerAtk].notFirstStrike)
|
||||
battleScript = BattleScript_MoveHPDrain;
|
||||
else
|
||||
battleScript = BattleScript_MoveHPDrain_PPLoss;
|
||||
|
||||
gBattleStruct->moveDamage[battlerDef] = GetNonDynamaxMaxHP(battlerDef) / 4;
|
||||
if (gBattleStruct->moveDamage[battlerDef] == 0)
|
||||
gBattleStruct->moveDamage[battlerDef] = 1;
|
||||
gBattleStruct->moveDamage[battlerDef] *= -1;
|
||||
}
|
||||
break;
|
||||
case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY:
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
if ((gProtectStructs[battlerAtk].notFirstStrike))
|
||||
battleScript = BattleScript_MonMadeMoveUseless;
|
||||
else
|
||||
battleScript = BattleScript_MonMadeMoveUseless_PPLoss;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gProtectStructs[battlerAtk].notFirstStrike)
|
||||
battleScript = BattleScript_MoveStatDrain;
|
||||
else
|
||||
battleScript = BattleScript_MoveStatDrain_PPLoss;
|
||||
|
||||
SET_STATCHANGER(statId, statAmount, FALSE);
|
||||
if (B_ABSORBING_ABILITY_STRING < GEN_5)
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
}
|
||||
break;
|
||||
case MOVE_ABSORBED_BY_BOOST_FLASH_FIRE:
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (!gDisableStructs[battlerDef].flashFireBoosted)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST;
|
||||
if (gProtectStructs[battlerAtk].notFirstStrike)
|
||||
battleScript = BattleScript_FlashFireBoost;
|
||||
else
|
||||
battleScript = BattleScript_FlashFireBoost_PPLoss;
|
||||
gDisableStructs[battlerDef].flashFireBoosted = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST;
|
||||
if (gProtectStructs[battlerAtk].notFirstStrike)
|
||||
battleScript = BattleScript_FlashFireBoost;
|
||||
else
|
||||
battleScript = BattleScript_FlashFireBoost_PPLoss;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (battleScript != NULL)
|
||||
{
|
||||
gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed.
|
||||
gBattlescriptCurrInstr = battleScript;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
@ -5470,153 +5587,35 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_WOULD_BLOCK:
|
||||
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility);
|
||||
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility, ABILITY_CHECK_TRIGGER);
|
||||
if (effect && gLastUsedAbility != 0xFFFF)
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
break;
|
||||
return effect;
|
||||
case ABILITYEFFECT_MOVES_BLOCK:
|
||||
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility, ABILITY_RUN_SCRIPT);
|
||||
|
||||
// prankster check
|
||||
if (effect == 0
|
||||
&& GetChosenMovePriority(gBattlerAttacker) > 0
|
||||
&& BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE)
|
||||
&& !(IsBattleMoveStatus(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove)))
|
||||
{
|
||||
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility);
|
||||
const u8 * battleScriptBlocksMove = NULL;
|
||||
switch (effect)
|
||||
{
|
||||
case MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF:
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
battleScriptBlocksMove = BattleScript_SoundproofProtected;
|
||||
break;
|
||||
case MOVE_BLOCKED_BY_DAZZLING:
|
||||
case MOVE_BLOCKED_BY_PARTNER_DAZZLING:
|
||||
if (effect == MOVE_BLOCKED_BY_PARTNER_DAZZLING)
|
||||
gBattleScripting.battler = BATTLE_PARTNER(battler);
|
||||
else
|
||||
gBattleScripting.battler = battler;
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
battleScriptBlocksMove = BattleScript_DazzlingProtected;
|
||||
break;
|
||||
case MOVE_BLOCKED_BY_GOOD_AS_GOLD:
|
||||
battleScriptBlocksMove = BattleScript_GoodAsGoldActivates;
|
||||
break;
|
||||
default:
|
||||
if (GetChosenMovePriority(gBattlerAttacker) > 0
|
||||
&& BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE)
|
||||
&& !(IsBattleMoveStatus(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove)))
|
||||
{
|
||||
if (!IsDoubleBattle()
|
||||
|| !(GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
||||
battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster;
|
||||
effect = 1;
|
||||
}
|
||||
}
|
||||
if (effect)
|
||||
gBattlescriptCurrInstr = battleScriptBlocksMove;
|
||||
if (!IsDoubleBattle()
|
||||
|| !(GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
|
||||
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
||||
gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster;
|
||||
effect = 1;
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_WOULD_ABSORB:
|
||||
effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType);
|
||||
effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType, ABILITY_CHECK_TRIGGER);
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (effect && gLastUsedAbility != 0xFFFF)
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
return effect;
|
||||
case ABILITYEFFECT_ABSORBING:
|
||||
{
|
||||
u32 statId = 0;
|
||||
u32 statAmount = 1;
|
||||
effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType);
|
||||
if (effect)
|
||||
{
|
||||
switch(gLastUsedAbility)
|
||||
{
|
||||
case ABILITY_MOTOR_DRIVE:
|
||||
statId = STAT_SPEED;
|
||||
break;
|
||||
case ABILITY_LIGHTNING_ROD:
|
||||
case ABILITY_STORM_DRAIN:
|
||||
statId = STAT_SPATK;
|
||||
break;
|
||||
case ABILITY_SAP_SIPPER:
|
||||
case ABILITY_WIND_RIDER:
|
||||
statId = STAT_ATK;
|
||||
break;
|
||||
case ABILITY_WELL_BAKED_BODY:
|
||||
statAmount = 2;
|
||||
statId = STAT_DEF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (effect)
|
||||
{
|
||||
case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY:
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (IsBattlerAtMaxHp(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK))
|
||||
{
|
||||
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
|
||||
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
|
||||
gBattlescriptCurrInstr = BattleScript_MoveHPDrain;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss;
|
||||
|
||||
gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4;
|
||||
if (gBattleStruct->moveDamage[battler] == 0)
|
||||
gBattleStruct->moveDamage[battler] = 1;
|
||||
gBattleStruct->moveDamage[battler] *= -1;
|
||||
}
|
||||
break;
|
||||
case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY:
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
|
||||
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
|
||||
gBattlescriptCurrInstr = BattleScript_MoveStatDrain;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss;
|
||||
|
||||
SET_STATCHANGER(statId, statAmount, FALSE);
|
||||
if (B_ABSORBING_ABILITY_STRING < GEN_5)
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
}
|
||||
break;
|
||||
case MOVE_ABSORBED_BY_BOOST_FLASH_FIRE:
|
||||
gBattleStruct->pledgeMove = FALSE;
|
||||
if (!gDisableStructs[battler].flashFireBoosted)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST;
|
||||
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
|
||||
gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
|
||||
gDisableStructs[battler].flashFireBoosted = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST;
|
||||
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
|
||||
gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
|
||||
else
|
||||
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (effect)
|
||||
gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed.
|
||||
|
||||
}
|
||||
effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType, ABILITY_RUN_SCRIPT);
|
||||
break;
|
||||
case ABILITYEFFECT_MOVE_END: // Think contact abilities.
|
||||
switch (gLastUsedAbility)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user