optimize dmg calc and ai dmg calc to reduce lag

This commit is contained in:
DizzyEggg 2023-09-12 23:20:09 +02:00
parent 2d9cbef684
commit 44bd830d2a
10 changed files with 259 additions and 274 deletions

View File

@ -8,7 +8,6 @@
#define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE) #define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE)
bool32 AI_RandLessThan(u8 val); bool32 AI_RandLessThan(u8 val);
void RecordLastUsedMoveByTarget(void);
bool32 IsAiVsAiBattle(void); bool32 IsAiVsAiBattle(void);
bool32 BattlerHasAi(u32 battlerId); bool32 BattlerHasAi(u32 battlerId);
bool32 IsAiBattlerAware(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId);
@ -19,9 +18,9 @@ void RecordAbilityBattle(u8 battlerId, u16 abilityId);
void ClearBattlerAbilityHistory(u8 battlerId); void ClearBattlerAbilityHistory(u8 battlerId);
void RecordItemEffectBattle(u8 battlerId, u8 itemEffect); void RecordItemEffectBattle(u8 battlerId, u8 itemEffect);
void ClearBattlerItemEffectHistory(u8 battlerId); void ClearBattlerItemEffectHistory(u8 battlerId);
void SaveBattlerData(u8 battlerId); void SaveBattlerData(u32 battlerId);
void SetBattlerData(u8 battlerId); void SetBattlerData(u32 battlerId);
void RestoreBattlerData(u8 battlerId); void RestoreBattlerData(u32 battlerId);
u16 GetAIChosenMove(u8 battlerId); u16 GetAIChosenMove(u8 battlerId);
bool32 WillAIStrikeFirst(void); bool32 WillAIStrikeFirst(void);
@ -31,16 +30,16 @@ bool32 AtMaxHp(u8 battler);
u32 GetHealthPercentage(u8 battler); u32 GetHealthPercentage(u8 battler);
bool32 IsBattlerTrapped(u8 battler, bool8 switching); bool32 IsBattlerTrapped(u8 battler, bool8 switching);
u8 AI_WhoStrikesFirst(u8 battlerAI, u8 battler2, u16 consideredMove); u8 AI_WhoStrikesFirst(u8 battlerAI, u8 battler2, u16 consideredMove);
bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk); bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk);
bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits); bool32 CanMoveFaintBattler(u16 move, u32 battlerDef, u32 battlerAtk, u8 nHits);
bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgMod); bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dmgMod);
s32 AI_GetAbility(u32 battlerId); s32 AI_GetAbility(u32 battlerId);
u16 AI_GetHoldEffect(u32 battlerId); u16 AI_GetHoldEffect(u32 battlerId);
u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 move); u32 AI_GetMoveAccuracy(u32 battlerAtk, u32 battlerDef, u16 move);
bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move); bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move);
bool32 AI_WeatherHasEffect(void); bool32 AI_WeatherHasEffect(void);
bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits); bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u8 numHits);
bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits); bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u8 index, u8 numHits);
bool32 AI_IsTerrainAffected(u8 battlerId, u32 flags); bool32 AI_IsTerrainAffected(u8 battlerId, u32 flags);
bool32 AI_IsBattlerGrounded(u8 battlerId); bool32 AI_IsBattlerGrounded(u8 battlerId);
bool32 HasDamagingMove(u8 battlerId); bool32 HasDamagingMove(u8 battlerId);
@ -48,15 +47,15 @@ bool32 HasDamagingMoveOfType(u8 battlerId, u8 type);
u32 GetBattlerSecondaryDamage(u8 battlerId); u32 GetBattlerSecondaryDamage(u8 battlerId);
bool32 BattlerWillFaintFromWeather(u8 battler, u16 ability); bool32 BattlerWillFaintFromWeather(u8 battler, u16 ability);
bool32 BattlerWillFaintFromSecondaryDamage(u8 battler, u16 ability); bool32 BattlerWillFaintFromSecondaryDamage(u8 battler, u16 ability);
bool32 ShouldTryOHKO(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u16 move); bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u16 atkAbility, u16 defAbility, u16 move);
bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveIndex); bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u8 moveIndex);
u16 GetBattlerSideSpeedAverage(u8 battler); u16 GetBattlerSideSpeedAverage(u8 battler);
bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage); bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u16 move, s32 damage);
bool32 ShouldRecover(u8 battlerAtk, u8 battlerDef, u16 move, u8 healPercent); bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u16 move, u8 healPercent);
bool32 ShouldSetScreen(u8 battlerAtk, u8 battlerDef, u16 moveEffect); bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, u16 moveEffect);
bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 moveIndex); bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u8 moveIndex);
bool32 IsRecycleEncouragedItem(u16 item); bool32 IsRecycleEncouragedItem(u16 item);
bool32 ShouldRestoreHpBerry(u8 battlerAtk, u16 item); bool32 ShouldRestoreHpBerry(u32 battlerAtk, u16 item);
bool32 IsStatBoostingBerry(u16 item); bool32 IsStatBoostingBerry(u16 item);
bool32 CanKnockOffItem(u8 battler, u16 item); bool32 CanKnockOffItem(u8 battler, u16 item);
bool32 IsAbilityOfRating(u16 ability, s8 rating); bool32 IsAbilityOfRating(u16 ability, s8 rating);
@ -64,7 +63,7 @@ s8 GetAbilityRating(u16 ability);
bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability); bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move); bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move);
u32 AI_GetBattlerMoveTargetType(u8 battlerId, u16 move); u32 AI_GetBattlerMoveTargetType(u8 battlerId, u16 move);
bool32 ShouldUseZMove(u8 activeId, u8 targetId, u16 chosenMove); bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u16 chosenMove);
// stat stage checks // stat stage checks
bool32 AnyStatIsRaised(u8 battlerId); bool32 AnyStatIsRaised(u8 battlerId);
@ -74,23 +73,24 @@ bool32 AreBattlersStatsMaxed(u8 battler);
bool32 BattlerHasAnyStatRaised(u8 battlerId); bool32 BattlerHasAnyStatRaised(u8 battlerId);
u32 CountPositiveStatStages(u8 battlerId); u32 CountPositiveStatStages(u8 battlerId);
u32 CountNegativeStatStages(u8 battlerId); u32 CountNegativeStatStages(u8 battlerId);
bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility); bool32 ShouldLowerAttack(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility); bool32 ShouldLowerDefense(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility); bool32 ShouldLowerSpeed(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility); bool32 ShouldLowerSpAtk(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility); bool32 ShouldLowerSpDef(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility); bool32 ShouldLowerAccuracy(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility); bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u16 defAbility);
// move checks // move checks
bool32 IsAffectedByPowder(u8 battler, u16 ability, u16 holdEffect); bool32 IsAffectedByPowder(u8 battler, u16 ability, u16 holdEffect);
bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split); bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split);
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *effectiveness, bool32 considerZPower); s32 AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower);
s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower);
u32 GetNoOfHitsToKO(u32 dmg, s32 hp); u32 GetNoOfHitsToKO(u32 dmg, s32 hp);
u8 GetMoveDamageResult(u16 move); u8 GetMoveDamageResult(u16 move);
u32 GetCurrDamageHpPercent(u8 battlerAtk, u8 battlerDef); u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef);
uq4_12_t AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef); uq4_12_t AI_GetTypeEffectiveness(u16 move, u32 battlerAtk, u32 battlerDef);
u32 AI_GetMoveEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef); u32 AI_GetMoveEffectiveness(u16 move, u32 battlerAtk, u32 battlerDef);
u16 *GetMovesArray(u32 battler); u16 *GetMovesArray(u32 battler);
bool32 IsConfusionMoveEffect(u16 moveEffect); bool32 IsConfusionMoveEffect(u16 moveEffect);
bool32 HasMove(u32 battlerId, u32 move); bool32 HasMove(u32 battlerId, u32 move);
@ -99,35 +99,35 @@ bool32 HasMoveWithSplit(u32 battler, u32 split);
bool32 HasMoveWithType(u32 battler, u8 type); bool32 HasMoveWithType(u32 battler, u8 type);
bool32 HasMoveWithTypeAndSplit(u32 battler, u8 type, u8 split); bool32 HasMoveWithTypeAndSplit(u32 battler, u8 type, u8 split);
bool32 HasMoveEffect(u32 battlerId, u16 moveEffect); bool32 HasMoveEffect(u32 battlerId, u16 moveEffect);
bool32 HasMoveWithLowAccuracy(u8, u8, u8, bool32, u16, u16, u16, u16); bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u8 accCheck, bool32 ignoreStatus, u16 atkAbility, u16 defAbility, u16 atkHoldEffect, u16 defHoldEffect);
bool32 IsAromaVeilProtectedMove(u16 move); bool32 IsAromaVeilProtectedMove(u16 move);
bool32 IsNonVolatileStatusMoveEffect(u16 moveEffect); bool32 IsNonVolatileStatusMoveEffect(u16 moveEffect);
bool32 IsStatLoweringMoveEffect(u16 moveEffect); bool32 IsStatLoweringMoveEffect(u16 moveEffect);
bool32 IsMoveRedirectionPrevented(u16 move, u16 atkAbility); bool32 IsMoveRedirectionPrevented(u16 move, u16 atkAbility);
bool32 IsMoveEncouragedToHit(u8 battlerAtk, u8 battlerDef, u16 move); bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u16 move);
bool32 IsHazardMoveEffect(u16 moveEffect); bool32 IsHazardMoveEffect(u16 moveEffect);
bool32 MoveCallsOtherMove(u16 move); bool32 MoveCallsOtherMove(u16 move);
bool32 MoveRequiresRecharging(u16 move); bool32 MoveRequiresRecharging(u16 move);
bool32 IsEncoreEncouragedEffect(u16 moveEffect); bool32 IsEncoreEncouragedEffect(u16 moveEffect);
void ProtectChecks(u8 battlerAtk, u8 battlerDef, u16 move, u16 predictedMove, s16 *score); void ProtectChecks(u32 battlerAtk, u32 battlerDef, u16 move, u16 predictedMove, s16 *score);
bool32 ShouldSetSandstorm(u8 battler, u16 ability, u16 holdEffect); bool32 ShouldSetSandstorm(u8 battler, u16 ability, u16 holdEffect);
bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect); bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect);
bool32 ShouldSetSnow(u8 battler, u16 ability, u16 holdEffect); bool32 ShouldSetSnow(u8 battler, u16 ability, u16 holdEffect);
bool32 ShouldSetRain(u8 battlerAtk, u16 ability, u16 holdEffect); bool32 ShouldSetRain(u32 battlerAtk, u16 ability, u16 holdEffect);
bool32 ShouldSetSun(u8 battlerAtk, u16 atkAbility, u16 holdEffect); bool32 ShouldSetSun(u32 battlerAtk, u16 atkAbility, u16 holdEffect);
bool32 HasSleepMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef); bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef);
bool32 IsHealingMoveEffect(u16 effect); bool32 IsHealingMoveEffect(u16 effect);
bool32 HasHealingEffect(u32 battler); bool32 HasHealingEffect(u32 battler);
bool32 IsTrappingMoveEffect(u16 effect); bool32 IsTrappingMoveEffect(u16 effect);
bool32 HasTrappingMoveEffect(u8 battler); bool32 HasTrappingMoveEffect(u8 battler);
bool32 ShouldFakeOut(u8 battlerAtk, u8 battlerDef, u16 move); bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u16 move);
bool32 HasThawingMove(u8 battler); bool32 HasThawingMove(u8 battler);
bool32 IsStatRaisingEffect(u16 effect); bool32 IsStatRaisingEffect(u16 effect);
bool32 IsStatLoweringEffect(u16 effect); bool32 IsStatLoweringEffect(u16 effect);
bool32 IsStatRaisingEffect(u16 effect); bool32 IsStatRaisingEffect(u16 effect);
bool32 IsAttackBoostMoveEffect(u16 effect); bool32 IsAttackBoostMoveEffect(u16 effect);
bool32 IsUngroundingEffect(u16 effect); bool32 IsUngroundingEffect(u16 effect);
bool32 IsSemiInvulnerable(u8 battlerDef, u16 move); bool32 IsSemiInvulnerable(u32 battlerDef, u16 move);
bool32 HasSoundMove(u8 battler); bool32 HasSoundMove(u8 battler);
bool32 HasHighCritRatioMove(u8 battler); bool32 HasHighCritRatioMove(u8 battler);
bool32 HasMagicCoatAffectedMove(u8 battler); bool32 HasMagicCoatAffectedMove(u8 battler);
@ -139,34 +139,34 @@ bool32 AI_CanGetFrostbite(u8 battler, u16 ability);
bool32 AI_CanBeConfused(u8 battler, u16 ability); bool32 AI_CanBeConfused(u8 battler, u16 ability);
bool32 AI_CanSleep(u8 battler, u16 ability); bool32 AI_CanSleep(u8 battler, u16 ability);
bool32 IsBattlerIncapacitated(u8 battler, u16 ability); bool32 IsBattlerIncapacitated(u8 battler, u16 ability);
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove); bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 ShouldPoisonSelf(u8 battler, u16 ability); bool32 ShouldPoisonSelf(u8 battler, u16 ability);
bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove); bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove); bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 ShouldBurnSelf(u8 battler, u16 ability); bool32 ShouldBurnSelf(u8 battler, u16 ability);
bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 AI_CanGiveFrostbite(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility); bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof); bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof);
u32 ShouldTryToFlinch(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u16 move); u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u16 atkAbility, u16 defAbility, u16 move);
bool32 ShouldTrap(u8 battlerAtk, u8 battlerDef, u16 move); bool32 ShouldTrap(u32 battlerAtk, u32 battlerDef, u16 move);
bool32 IsWakeupTurn(u8 battler); bool32 IsWakeupTurn(u8 battler);
bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId); bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId);
// partner logic // partner logic
u16 GetAllyChosenMove(u8 battlerId); u16 GetAllyChosenMove(u8 battlerId);
bool32 IsValidDoubleBattle(u8 battlerAtk); bool32 IsValidDoubleBattle(u32 battlerAtk);
bool32 IsTargetingPartner(u8 battlerAtk, u8 battlerDef); bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef);
bool32 DoesPartnerHaveSameMoveEffect(u8 battlerAtkPartner, u8 battlerDef, u16 move, u16 partnerMove); bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u16 move, u16 partnerMove);
bool32 PartnerHasSameMoveEffectWithoutTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 PartnerMoveEffectIsStatusSameTarget(u8 battlerAtkPartner, u8 battlerDef, u16 partnerMove); bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u16 partnerMove);
bool32 PartnerMoveEffectIsWeather(u8 battlerAtkPartner, u16 partnerMove); bool32 PartnerMoveEffectIsWeather(u32 battlerAtkPartner, u16 partnerMove);
bool32 PartnerMoveEffectIsTerrain(u8 battlerAtkPartner, u16 partnerMove); bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u16 partnerMove);
bool32 PartnerMoveIs(u8 battlerAtkPartner, u16 partnerMove, u16 moveCheck); bool32 PartnerMoveIs(u32 battlerAtkPartner, u16 partnerMove, u16 moveCheck);
bool32 PartnerMoveIsSameAsAttacker(u8 battlerAtkPartner, u8 battlerDef, u16 move, u16 partnerMove); bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u16 move, u16 partnerMove);
bool32 PartnerMoveIsSameNoTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 ShouldUseWishAromatherapy(u8 battlerAtk, u8 battlerDef, u16 move); bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u16 move);
// party logic // party logic
struct BattlePokemon *AllocSaveBattleMons(void); struct BattlePokemon *AllocSaveBattleMons(void);
@ -178,12 +178,12 @@ bool32 PartyHasMoveSplit(u8 battlerId, u8 split);
bool32 SideHasMoveSplit(u8 battlerId, u8 split); bool32 SideHasMoveSplit(u8 battlerId, u8 split);
// score increases // score increases
void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score); void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u8 statId, s16 *score);
void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score);
void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score);
void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score);
void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score);
void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score);
void IncreaseFrostbiteScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score);
#endif //GUARD_BATTLE_AI_UTIL_H #endif //GUARD_BATTLE_AI_UTIL_H

View File

@ -67,7 +67,7 @@ void RunBattleScriptCommands_PopCallbacksStack(void);
void RunBattleScriptCommands(void); void RunBattleScriptCommands(void);
bool8 TryRunFromBattle(u8 battlerId); bool8 TryRunFromBattle(u8 battlerId);
void SpecialStatusesClear(void); void SpecialStatusesClear(void);
void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk); void SetTypeBeforeUsingMove(u16 move, u32 battlerAtk);
bool32 IsWildMonSmart(void); bool32 IsWildMonSmart(void);
u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags); u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags);
void ModifyPersonalityForNature(u32 *personality, u32 newNature); void ModifyPersonalityForNature(u32 *personality, u32 newNature);

View File

@ -16,8 +16,8 @@ struct StatFractions
u8 divisor; u8 divisor;
}; };
s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility); s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility);
s8 GetInverseCritChance(u8 battlerAtk, u8 battlerDef, u32 move); s8 GetInverseCritChance(u32 battlerAtk, u32 battlerDef, u32 move);
u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect);
u8 GetBattlerTurnOrderNum(u8 battlerId); u8 GetBattlerTurnOrderNum(u8 battlerId);
bool32 NoAliveMonsForEitherParty(void); bool32 NoAliveMonsForEitherParty(void);
@ -28,8 +28,8 @@ void BattleCreateYesNoCursorAt(u8 cursorPosition);
void BufferMoveToLearnIntoBattleTextBuff2(void); void BufferMoveToLearnIntoBattleTextBuff2(void);
void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags); void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags);
bool8 UproarWakeUpCheck(u8 battlerId); bool8 UproarWakeUpCheck(u8 battlerId);
bool32 DoesSubstituteBlockMove(u8 battlerAtk, u8 battlerDef, u32 move); bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 DoesDisguiseBlockMove(u8 battlerAtk, u8 battlerDef, u32 move); bool32 DoesDisguiseBlockMove(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 CanPoisonType(u8 battlerAttacker, u8 battlerTarget); bool32 CanPoisonType(u8 battlerAttacker, u8 battlerTarget);
bool32 CanParalyzeType(u8 battlerAttacker, u8 battlerTarget); bool32 CanParalyzeType(u8 battlerAttacker, u8 battlerTarget);
bool32 CanUseLastResort(u8 battlerId); bool32 CanUseLastResort(u8 battlerId);

View File

@ -161,20 +161,20 @@ void HandleAction_RunBattleScript(void);
u32 SetRandomTarget(u32 battler); u32 SetRandomTarget(u32 battler);
u32 GetMoveTarget(u16 move, u8 setTarget); u32 GetMoveTarget(u16 move, u8 setTarget);
u8 IsMonDisobedient(void); u8 IsMonDisobedient(void);
u32 GetBattlerHoldEffect(u8 battler, bool32 checkNegating); u32 GetBattlerHoldEffect(u32 battler, bool32 checkNegating);
u32 GetBattlerHoldEffectParam(u8 battler); u32 GetBattlerHoldEffectParam(u8 battler);
bool32 IsMoveMakingContact(u16 move, u8 battlerAtk); bool32 IsMoveMakingContact(u16 move, u32 battlerAtk);
bool32 IsBattlerGrounded(u8 battler); bool32 IsBattlerGrounded(u8 battler);
bool32 IsBattlerAlive(u8 battler); bool32 IsBattlerAlive(u8 battler);
u8 GetBattleMonMoveSlot(struct BattlePokemon *battleMon, u16 move); u8 GetBattleMonMoveSlot(struct BattlePokemon *battleMon, u16 move);
u32 GetBattlerWeight(u8 battler); u32 GetBattlerWeight(u8 battler);
u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer); u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer);
u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter); u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter);
s32 CalculateMoveDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 fixedBasePower, bool32 isCrit, bool32 randomFactor, bool32 updateFlags); s32 CalculateMoveDamage(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, bool32 isCrit, bool32 randomFactor, bool32 updateFlags);
s32 CalculateMoveDamageAndEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 fixedBasePower, uq4_12_t *typeEffectivenessModifier); s32 CalculateMoveDamageAndEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, uq4_12_t *typeEffectivenessModifier);
uq4_12_t CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities); uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, bool32 recordAbilities);
uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef);
uq4_12_t GetTypeModifier(u8 atkType, u8 defType); uq4_12_t GetTypeModifier(u32 atkType, u32 defType);
s32 GetStealthHazardDamage(u8 hazardType, u8 battler); s32 GetStealthHazardDamage(u8 hazardType, u8 battler);
s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp); s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp);
bool32 CanMegaEvolve(u8 battler); bool32 CanMegaEvolve(u8 battler);
@ -209,11 +209,11 @@ void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast);
bool32 CompareStat(u8 battler, u8 statId, u8 cmpTo, u8 cmpKind); bool32 CompareStat(u8 battler, u8 statId, u8 cmpTo, u8 cmpKind);
bool32 TryRoomService(u8 battler); bool32 TryRoomService(u8 battler);
void BufferStatChange(u8 battler, u8 statId, u8 stringId); void BufferStatChange(u8 battler, u8 statId, u8 stringId);
bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget); bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u32 battlerDef, bool32 checkTarget);
u16 GetUsedHeldItem(u8 battler); u16 GetUsedHeldItem(u8 battler);
bool32 IsBattlerWeatherAffected(u8 battler, u32 weatherFlags); bool32 IsBattlerWeatherAffected(u8 battler, u32 weatherFlags);
u32 GetBattlerMoveTargetType(u8 battler, u16 move); u32 GetBattlerMoveTargetType(u8 battler, u16 move);
bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move); bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move);
bool8 IsMoveAffectedByParentalBond(u16 move, u8 battler); bool8 IsMoveAffectedByParentalBond(u16 move, u8 battler);
void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon); void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon);
void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon); void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon);

View File

@ -9,7 +9,7 @@
// Battle Debug Menu // Battle Debug Menu
#define DEBUG_BATTLE_MENU TRUE // If set to TRUE, enables a debug menu to use in battles by pressing the Select button. #define DEBUG_BATTLE_MENU TRUE // If set to TRUE, enables a debug menu to use in battles by pressing the Select button.
#define DEBUG_AI_DELAY_TIMER FALSE // If set to TRUE, displays the number of frames it takes for the AI to choose a move. Replaces the "What will PKMN do" text. Useful for devs or anyone who modifies the AI code and wants to see if it doesn't take too long to run. #define DEBUG_AI_DELAY_TIMER TRUE // If set to TRUE, displays the number of frames it takes for the AI to choose a move. Replaces the "What will PKMN do" text. Useful for devs or anyone who modifies the AI code and wants to see if it doesn't take too long to run.
// Pokémon Debug // Pokémon Debug
#define DEBUG_POKEMON_MENU TRUE // Enables a debug menu for pokemon sprites and icons, accessed by pressing SELECT in the summary screen. #define DEBUG_POKEMON_MENU TRUE // Enables a debug menu for pokemon sprites and icons, accessed by pressing SELECT in the summary screen.

View File

@ -47,20 +47,20 @@ EWRAM_DATA const u8 *gAIScriptPtr = NULL; // Still used in contests
EWRAM_DATA u8 sBattler_AI = 0; EWRAM_DATA u8 sBattler_AI = 0;
// const rom data // const rom data
static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_Risky(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_Risky(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_PreferStrongestMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_PreferStrongestMove(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_HPAware(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_Roaming(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_Roaming(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_Safari(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_Safari(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_FirstBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score); static s16 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u16 move, s16 score);
static s16 (*const sBattleAiFuncTable[])(u8, u8, u16, s16) = static s16 (*const sBattleAiFuncTable[])(u32, u32, u16, s16) =
{ {
[0] = AI_CheckBadMove, // AI_FLAG_CHECK_BAD_MOVE [0] = AI_CheckBadMove, // AI_FLAG_CHECK_BAD_MOVE
[1] = AI_TryToFaint, // AI_FLAG_TRY_TO_FAINT [1] = AI_TryToFaint, // AI_FLAG_TRY_TO_FAINT
@ -349,9 +349,7 @@ static void SetBattlerAiData(u32 battler)
void SetAiLogicDataForTurn(void) void SetAiLogicDataForTurn(void)
{ {
u32 battlerAtk, battlerDef, i, move; u32 battlerAtk, battlerDef, i, battlersCount;
u8 effectiveness;
s32 dmg;
memset(AI_DATA, 0, sizeof(struct AiLogicData)); memset(AI_DATA, 0, sizeof(struct AiLogicData));
@ -360,33 +358,29 @@ void SetAiLogicDataForTurn(void)
gBattleStruct->aiDelayTimer = gMain.vblankCounter1; gBattleStruct->aiDelayTimer = gMain.vblankCounter1;
// get/assume all battler data // get/assume all battler data and simulate AI damage
for (i = 0; i < gBattlersCount; i++) battlersCount = gBattlersCount;
for (battlerAtk = 0; battlerAtk < battlersCount; battlerAtk++)
{ {
if (IsBattlerAlive(i)) { if (!IsBattlerAlive(battlerAtk))
SetBattlerAiData(i);
}
}
// simulate AI damage
for (battlerAtk = 0; battlerAtk < gBattlersCount; battlerAtk++)
{
if (!IsBattlerAlive(battlerAtk)
|| !IsAiBattlerAware(battlerAtk)) {
continue; continue;
}
for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) SetBattlerAiData(battlerAtk);
if (!IsAiBattlerAware(battlerAtk))
continue;
SaveBattlerData(battlerAtk);
for (battlerDef = 0; battlerDef < battlersCount; battlerDef++)
{ {
if (battlerAtk == battlerDef) if (battlerAtk == battlerDef)
continue; continue;
RecordKnownMove(battlerDef, gLastMoves[battlerDef]); SaveBattlerData(battlerDef);
for (i = 0; i < MAX_MON_MOVES; i++) for (i = 0; i < MAX_MON_MOVES; i++)
{ {
dmg = 0; s32 dmg = 0;
effectiveness = AI_EFFECTIVENESS_x0; u8 effectiveness = AI_EFFECTIVENESS_x0;
move = gBattleMons[battlerAtk].moves[i]; u32 move = gBattleMons[battlerAtk].moves[i];
if (move != 0 if (move != 0
&& move != 0xFFFF && move != 0xFFFF
@ -562,8 +556,6 @@ static u8 ChooseMoveOrAction_Doubles(void)
BattleAI_SetupAIData(0xF, sBattler_AI); BattleAI_SetupAIData(0xF, sBattler_AI);
gBattlerTarget = i; gBattlerTarget = i;
if ((i & BIT_SIDE) != (sBattler_AI & BIT_SIDE))
RecordLastUsedMoveByTarget();
AI_DATA->partnerMove = GetAllyChosenMove(i); AI_DATA->partnerMove = GetAllyChosenMove(i);
AI_THINKING_STRUCT->aiLogicId = 0; AI_THINKING_STRUCT->aiLogicId = 0;
@ -710,7 +702,7 @@ static void BattleAI_DoAIProcessing(void)
// AI Score Functions // AI Score Functions
// AI_FLAG_CHECK_BAD_MOVE - decreases move scores // AI_FLAG_CHECK_BAD_MOVE - decreases move scores
static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
// move data // move data
u8 atkPriority = GetMovePriority(battlerAtk, move); u8 atkPriority = GetMovePriority(battlerAtk, move);
@ -2694,7 +2686,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
return score; return score;
} }
static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
return score; return score;
@ -2749,14 +2741,14 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
// double battle logic // double battle logic
static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
// move data // move data
u8 moveType = gBattleMoves[move].type; u8 moveType = gBattleMoves[move].type;
u16 effect = gBattleMoves[move].effect; u16 effect = gBattleMoves[move].effect;
u16 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move); u16 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move);
// ally data // ally data
u8 battlerAtkPartner = BATTLE_PARTNER(battlerAtk); u32 battlerAtkPartner = BATTLE_PARTNER(battlerAtk);
u16 atkPartnerAbility = AI_DATA->abilities[BATTLE_PARTNER(battlerAtk)]; u16 atkPartnerAbility = AI_DATA->abilities[BATTLE_PARTNER(battlerAtk)];
u16 atkPartnerHoldEffect = AI_DATA->holdEffects[BATTLE_PARTNER(battlerAtk)]; u16 atkPartnerHoldEffect = AI_DATA->holdEffects[BATTLE_PARTNER(battlerAtk)];
bool32 partnerProtecting = (gBattleMoves[AI_DATA->partnerMove].effect == EFFECT_PROTECT); bool32 partnerProtecting = (gBattleMoves[AI_DATA->partnerMove].effect == EFFECT_PROTECT);
@ -3148,7 +3140,7 @@ static bool32 IsPinchBerryItemEffect(u16 holdEffect)
return FALSE; return FALSE;
} }
static u32 GetAIMostDamagingMoveId(u8 battlerAtk, u8 battlerDef) static u32 GetAIMostDamagingMoveId(u32 battlerAtk, u32 battlerDef)
{ {
u32 i, id = 0; u32 i, id = 0;
u32 mostDmg = 0; u32 mostDmg = 0;
@ -3162,7 +3154,7 @@ static u32 GetAIMostDamagingMoveId(u8 battlerAtk, u8 battlerDef)
} }
// AI_FLAG_CHECK_VIABILITY - a weird mix of increasing and decreasing scores // AI_FLAG_CHECK_VIABILITY - a weird mix of increasing and decreasing scores
static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
// move data // move data
u16 moveEffect = gBattleMoves[move].effect; u16 moveEffect = gBattleMoves[move].effect;
@ -4964,7 +4956,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
// Effects that are encouraged on the first turn of battle // Effects that are encouraged on the first turn of battle
static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef) if (IsTargetingPartner(battlerAtk, battlerDef)
|| gBattleResults.battleTurnCounter != 0) || gBattleResults.battleTurnCounter != 0)
@ -5075,7 +5067,7 @@ static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
// Adds score bonus to 'riskier' move effects and high crit moves // Adds score bonus to 'riskier' move effects and high crit moves
static s16 AI_Risky(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_Risky(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
return score; return score;
@ -5114,7 +5106,7 @@ static s16 AI_Risky(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
// Adds score bonus to best powered move // Adds score bonus to best powered move
static s16 AI_PreferStrongestMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_PreferStrongestMove(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
return score; return score;
@ -5126,7 +5118,7 @@ static s16 AI_PreferStrongestMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 sc
} }
// Prefers moves that are good for baton pass // Prefers moves that are good for baton pass
static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
u32 i; u32 i;
@ -5181,7 +5173,7 @@ static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
return score; return score;
} }
static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_HPAware(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
u16 effect = gBattleMoves[move].effect; u16 effect = gBattleMoves[move].effect;
u8 moveType = gBattleMoves[move].type; u8 moveType = gBattleMoves[move].type;
@ -5384,7 +5376,7 @@ static void AI_Watch(void)
} }
// Roaming pokemon logic // Roaming pokemon logic
static s16 AI_Roaming(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_Roaming(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
if (IsBattlerTrapped(battlerAtk, FALSE)) if (IsBattlerTrapped(battlerAtk, FALSE))
return score; return score;
@ -5394,7 +5386,7 @@ static s16 AI_Roaming(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
// Safari pokemon logic // Safari pokemon logic
static s16 AI_Safari(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_Safari(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
u8 safariFleeRate = gBattleStruct->safariEscapeFactor * 5; // Safari flee rate, from 0-20. u8 safariFleeRate = gBattleStruct->safariEscapeFactor * 5; // Safari flee rate, from 0-20.
@ -5407,7 +5399,7 @@ static s16 AI_Safari(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
// First battle logic // First battle logic
static s16 AI_FirstBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u16 move, s16 score)
{ {
if (AI_DATA->hpPercents[battlerDef] <= 20) if (AI_DATA->hpPercents[battlerDef] <= 20)
AI_Flee(); AI_Flee();

View File

@ -436,11 +436,6 @@ bool32 AI_RandLessThan(u8 val)
return FALSE; return FALSE;
} }
void RecordLastUsedMoveByTarget(void)
{
RecordKnownMove(gBattlerTarget, gLastMoves[gBattlerTarget]);
}
bool32 IsAiVsAiBattle(void) bool32 IsAiVsAiBattle(void)
{ {
return (B_FLAG_AI_VS_AI_BATTLE && FlagGet(B_FLAG_AI_VS_AI_BATTLE)); return (B_FLAG_AI_VS_AI_BATTLE && FlagGet(B_FLAG_AI_VS_AI_BATTLE));
@ -529,7 +524,7 @@ void ClearBattlerItemEffectHistory(u8 battlerId)
BATTLE_HISTORY->itemEffects[battlerId] = 0; BATTLE_HISTORY->itemEffects[battlerId] = 0;
} }
void SaveBattlerData(u8 battlerId) void SaveBattlerData(u32 battlerId)
{ {
if (!BattlerHasAi(battlerId)) if (!BattlerHasAi(battlerId))
{ {
@ -580,7 +575,7 @@ static bool32 ShouldFailForIllusion(u16 illusionSpecies, u32 battlerId)
return TRUE; return TRUE;
} }
void SetBattlerData(u8 battlerId) void SetBattlerData(u32 battlerId)
{ {
if (!BattlerHasAi(battlerId)) if (!BattlerHasAi(battlerId))
{ {
@ -624,7 +619,7 @@ void SetBattlerData(u8 battlerId)
} }
} }
void RestoreBattlerData(u8 battlerId) void RestoreBattlerData(u32 battlerId)
{ {
if (!BattlerHasAi(battlerId)) if (!BattlerHasAi(battlerId))
{ {
@ -741,7 +736,7 @@ bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split)
return (usable == 0); return (usable == 0);
} }
static bool32 AI_GetIfCrit(u32 move, u8 battlerAtk, u8 battlerDef) static bool32 AI_GetIfCrit(u32 move, u32 battlerAtk, u32 battlerDef)
{ {
bool32 isCrit; bool32 isCrit;
@ -776,12 +771,23 @@ static bool32 AI_GetIfCrit(u32 move, u8 battlerAtk, u8 battlerDef)
return isCrit; return isCrit;
} }
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness, bool32 considerZPower) // To save computation time this function has 2 variants. One saves, sets and restores battlers, while the other doesn't.
s32 AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower)
{
SaveBattlerData(battlerAtk);
SaveBattlerData(battlerDef);
AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower);
}
s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectiveness, bool32 considerZPower)
{ {
s32 dmg, moveType, critDmg, normalDmg, fixedBasePower, n; s32 dmg, moveType, critDmg, normalDmg, fixedBasePower, n;
s8 critChance; s8 critChance;
uq4_12_t effectivenessMultiplier; uq4_12_t effectivenessMultiplier;
SetBattlerData(battlerAtk);
SetBattlerData(battlerDef);
if (considerZPower && IsViableZMove(battlerAtk, move)) if (considerZPower && IsViableZMove(battlerAtk, move))
{ {
//temporarily enable z moves for damage calcs //temporarily enable z moves for damage calcs
@ -789,12 +795,6 @@ s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *typeEffectiveness,
gBattleStruct->zmove.active = TRUE; gBattleStruct->zmove.active = TRUE;
} }
SaveBattlerData(battlerAtk);
SaveBattlerData(battlerDef);
SetBattlerData(battlerAtk);
SetBattlerData(battlerDef);
gBattleStruct->dynamicMoveType = 0; gBattleStruct->dynamicMoveType = 0;
if (move == MOVE_NATURE_POWER) if (move == MOVE_NATURE_POWER)
@ -1026,14 +1026,14 @@ u8 GetMoveDamageResult(u16 move)
return AI_THINKING_STRUCT->funcResult; return AI_THINKING_STRUCT->funcResult;
} }
u32 GetCurrDamageHpPercent(u8 battlerAtk, u8 battlerDef) u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef)
{ {
int bestDmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]; int bestDmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex];
return (bestDmg * 100) / gBattleMons[battlerDef].maxHP; return (bestDmg * 100) / gBattleMons[battlerDef].maxHP;
} }
uq4_12_t AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef) uq4_12_t AI_GetTypeEffectiveness(u16 move, u32 battlerAtk, u32 battlerDef)
{ {
uq4_12_t typeEffectiveness; uq4_12_t typeEffectiveness;
u16 moveType; u16 moveType;
@ -1055,7 +1055,7 @@ uq4_12_t AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef)
return typeEffectiveness; return typeEffectiveness;
} }
u32 AI_GetMoveEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef) u32 AI_GetMoveEffectiveness(u16 move, u32 battlerAtk, u32 battlerDef)
{ {
gMoveResultFlags = 0; gMoveResultFlags = 0;
return AI_GetEffectiveness(AI_GetTypeEffectiveness(move, battlerAtk, battlerDef)); return AI_GetEffectiveness(AI_GetTypeEffectiveness(move, battlerAtk, battlerDef));
@ -1134,7 +1134,7 @@ u8 AI_WhoStrikesFirst(u8 battlerAI, u8 battler2, u16 moveConsidered)
} }
// Check if target has means to faint ai mon. // Check if target has means to faint ai mon.
bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk) bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk)
{ {
s32 i, dmg; s32 i, dmg;
u32 unusable = AI_DATA->moveLimitations[battlerDef]; u32 unusable = AI_DATA->moveLimitations[battlerDef];
@ -1154,7 +1154,7 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk)
// Check if AI mon has the means to faint the target with any of its moves. // Check if AI mon has the means to faint the target with any of its moves.
// If numHits > 1, check if the target will be KO'ed by that number of hits (ignoring healing effects) // If numHits > 1, check if the target will be KO'ed by that number of hits (ignoring healing effects)
bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits) bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u8 numHits)
{ {
s32 i, dmg; s32 i, dmg;
u32 moveLimitations = AI_DATA->moveLimitations[battlerAtk]; u32 moveLimitations = AI_DATA->moveLimitations[battlerAtk];
@ -1178,7 +1178,7 @@ bool32 CanAIFaintTarget(u8 battlerAtk, u8 battlerDef, u8 numHits)
return FALSE; return FALSE;
} }
bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits) bool32 CanMoveFaintBattler(u16 move, u32 battlerDef, u32 battlerAtk, u8 nHits)
{ {
s32 i, dmg; s32 i, dmg;
u8 effectiveness; u8 effectiveness;
@ -1187,14 +1187,14 @@ bool32 CanMoveFaintBattler(u16 move, u8 battlerDef, u8 battlerAtk, u8 nHits)
if (move != MOVE_NONE if (move != MOVE_NONE
&& move != 0xFFFF && move != 0xFFFF
&& !(unusable & gBitTable[i]) && !(unusable & gBitTable[i])
&& AI_CalcDamage(move, battlerDef, battlerAtk, &effectiveness, FALSE) >= gBattleMons[battlerAtk].hp) && AI_CalcDamageSaveBattlers(move, battlerDef, battlerAtk, &effectiveness, FALSE) >= gBattleMons[battlerAtk].hp)
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
// Check if target has means to faint ai mon after modding hp/dmg // Check if target has means to faint ai mon after modding hp/dmg
bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgMod) bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dmgMod)
{ {
u32 i; u32 i;
u32 unusable = AI_DATA->moveLimitations[battlerDef]; u32 unusable = AI_DATA->moveLimitations[battlerDef];
@ -1466,13 +1466,13 @@ bool32 IsMoveRedirectionPrevented(u16 move, u16 atkAbility)
return FALSE; return FALSE;
} }
u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 move) u32 AI_GetMoveAccuracy(u32 battlerAtk, u32 battlerDef, u16 move)
{ {
return GetTotalAccuracy(battlerAtk, battlerDef, move, AI_DATA->abilities[battlerAtk], AI_DATA->abilities[battlerDef], return GetTotalAccuracy(battlerAtk, battlerDef, move, AI_DATA->abilities[battlerAtk], AI_DATA->abilities[battlerDef],
AI_DATA->holdEffects[battlerAtk], AI_DATA->holdEffects[battlerDef]); AI_DATA->holdEffects[battlerAtk], AI_DATA->holdEffects[battlerDef]);
} }
bool32 IsSemiInvulnerable(u8 battlerDef, u16 move) bool32 IsSemiInvulnerable(u32 battlerDef, u16 move)
{ {
if (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE) if (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE)
return TRUE; return TRUE;
@ -1486,7 +1486,7 @@ bool32 IsSemiInvulnerable(u8 battlerDef, u16 move)
return FALSE; return FALSE;
} }
bool32 IsMoveEncouragedToHit(u8 battlerAtk, u8 battlerDef, u16 move) bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u16 move)
{ {
if (IsSemiInvulnerable(battlerDef, move)) if (IsSemiInvulnerable(battlerDef, move))
return FALSE; return FALSE;
@ -1526,7 +1526,7 @@ bool32 IsMoveEncouragedToHit(u8 battlerAtk, u8 battlerDef, u16 move)
return FALSE; return FALSE;
} }
bool32 ShouldTryOHKO(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u16 move) bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u16 atkAbility, u16 defAbility, u16 move)
{ {
u32 holdEffect = AI_DATA->holdEffects[battlerDef]; u32 holdEffect = AI_DATA->holdEffects[battlerDef];
u32 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, move); u32 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, move);
@ -1608,7 +1608,7 @@ bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect)
return FALSE; return FALSE;
} }
bool32 ShouldSetRain(u8 battlerAtk, u16 atkAbility, u16 holdEffect) bool32 ShouldSetRain(u32 battlerAtk, u16 atkAbility, u16 holdEffect)
{ {
if (!AI_WeatherHasEffect()) if (!AI_WeatherHasEffect())
return FALSE; return FALSE;
@ -1631,7 +1631,7 @@ bool32 ShouldSetRain(u8 battlerAtk, u16 atkAbility, u16 holdEffect)
return FALSE; return FALSE;
} }
bool32 ShouldSetSun(u8 battlerAtk, u16 atkAbility, u16 holdEffect) bool32 ShouldSetSun(u32 battlerAtk, u16 atkAbility, u16 holdEffect)
{ {
if (!AI_WeatherHasEffect()) if (!AI_WeatherHasEffect())
return FALSE; return FALSE;
@ -1679,7 +1679,7 @@ bool32 ShouldSetSnow(u8 battler, u16 ability, u16 holdEffect)
return FALSE; return FALSE;
} }
void ProtectChecks(u8 battlerAtk, u8 battlerDef, u16 move, u16 predictedMove, s16 *score) void ProtectChecks(u32 battlerAtk, u32 battlerDef, u16 move, u16 predictedMove, s16 *score)
{ {
// TODO more sophisticated logic // TODO more sophisticated logic
u16 predictedEffect = gBattleMoves[predictedMove].effect; u16 predictedEffect = gBattleMoves[predictedMove].effect;
@ -1793,7 +1793,7 @@ u32 CountNegativeStatStages(u8 battlerId)
return count; return count;
} }
bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerAttack(u32 battlerAtk, u32 battlerDef, u16 defAbility)
{ {
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy. return FALSE; // Don't bother lowering stats if can kill enemy.
@ -1810,7 +1810,7 @@ bool32 ShouldLowerAttack(u8 battlerAtk, u8 battlerDef, u16 defAbility)
return FALSE; return FALSE;
} }
bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerDefense(u32 battlerAtk, u32 battlerDef, u16 defAbility)
{ {
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy. return FALSE; // Don't bother lowering stats if can kill enemy.
@ -1827,7 +1827,7 @@ bool32 ShouldLowerDefense(u8 battlerAtk, u8 battlerDef, u16 defAbility)
return FALSE; return FALSE;
} }
bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpeed(u32 battlerAtk, u32 battlerDef, u16 defAbility)
{ {
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy. return FALSE; // Don't bother lowering stats if can kill enemy.
@ -1842,7 +1842,7 @@ bool32 ShouldLowerSpeed(u8 battlerAtk, u8 battlerDef, u16 defAbility)
return FALSE; return FALSE;
} }
bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpAtk(u32 battlerAtk, u32 battlerDef, u16 defAbility)
{ {
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy. return FALSE; // Don't bother lowering stats if can kill enemy.
@ -1858,7 +1858,7 @@ bool32 ShouldLowerSpAtk(u8 battlerAtk, u8 battlerDef, u16 defAbility)
return FALSE; return FALSE;
} }
bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerSpDef(u32 battlerAtk, u32 battlerDef, u16 defAbility)
{ {
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy. return FALSE; // Don't bother lowering stats if can kill enemy.
@ -1874,7 +1874,7 @@ bool32 ShouldLowerSpDef(u8 battlerAtk, u8 battlerDef, u16 defAbility)
return FALSE; return FALSE;
} }
bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerAccuracy(u32 battlerAtk, u32 battlerDef, u16 defAbility)
{ {
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy. return FALSE; // Don't bother lowering stats if can kill enemy.
@ -1889,7 +1889,7 @@ bool32 ShouldLowerAccuracy(u8 battlerAtk, u8 battlerDef, u16 defAbility)
return FALSE; return FALSE;
} }
bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u16 defAbility)
{ {
if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (WillAIStrikeFirst() && (AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return FALSE; // Don't bother lowering stats if can kill enemy. return FALSE; // Don't bother lowering stats if can kill enemy.
@ -1904,7 +1904,7 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility)
return FALSE; return FALSE;
} }
bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits) bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u8 index, u8 numHits)
{ {
s32 dmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][index]; s32 dmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][index];
@ -1996,7 +1996,7 @@ bool32 HasMove(u32 battlerId, u32 move)
return FALSE; return FALSE;
} }
bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32 ignoreStatus, u16 atkAbility, u16 defAbility, u16 atkHoldEffect, u16 defHoldEffect) bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u8 accCheck, bool32 ignoreStatus, u16 atkAbility, u16 defAbility, u16 atkHoldEffect, u16 defHoldEffect)
{ {
s32 i; s32 i;
u16 *moves = GetMovesArray(battlerAtk); u16 *moves = GetMovesArray(battlerAtk);
@ -2023,7 +2023,7 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32
return FALSE; return FALSE;
} }
bool32 HasSleepMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef) bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef)
{ {
u8 moveLimitations = AI_DATA->moveLimitations[battlerAtk]; u8 moveLimitations = AI_DATA->moveLimitations[battlerAtk];
u32 i; u32 i;
@ -2560,7 +2560,7 @@ enum {
CAN_TRY_PIVOT, CAN_TRY_PIVOT,
PIVOT, PIVOT,
}; };
bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 moveIndex) bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u8 moveIndex)
{ {
bool8 hasStatBoost = AnyUsefulStatIsRaised(battlerAtk) || gBattleMons[battlerDef].statStages[STAT_EVASION] >= 9; //Significant boost in evasion for any class bool8 hasStatBoost = AnyUsefulStatIsRaised(battlerAtk) || gBattleMons[battlerDef].statStages[STAT_EVASION] >= 9; //Significant boost in evasion for any class
bool32 shouldSwitch; bool32 shouldSwitch;
@ -2789,7 +2789,7 @@ bool32 AI_CanSleep(u8 battler, u16 ability)
return TRUE; return TRUE;
} }
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove) bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{ {
if (!AI_CanSleep(battlerDef, defAbility) if (!AI_CanSleep(battlerDef, defAbility)
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
@ -2804,7 +2804,7 @@ static bool32 AI_CanPoisonType(u8 battlerAttacker, u8 battlerTarget)
|| !(IS_BATTLER_OF_TYPE(battlerTarget, TYPE_POISON) || IS_BATTLER_OF_TYPE(battlerTarget, TYPE_STEEL))); || !(IS_BATTLER_OF_TYPE(battlerTarget, TYPE_POISON) || IS_BATTLER_OF_TYPE(battlerTarget, TYPE_STEEL)));
} }
static bool32 AI_CanBePoisoned(u8 battlerAtk, u8 battlerDef) static bool32 AI_CanBePoisoned(u32 battlerAtk, u32 battlerDef)
{ {
u16 ability = AI_DATA->abilities[battlerDef]; u16 ability = AI_DATA->abilities[battlerDef];
@ -2836,7 +2836,7 @@ bool32 ShouldPoisonSelf(u8 battler, u16 ability)
return FALSE; return FALSE;
} }
bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove) bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{ {
if (!AI_CanBePoisoned(battlerAtk, battlerDef) if (!AI_CanBePoisoned(battlerAtk, battlerDef)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
@ -2862,7 +2862,7 @@ static bool32 AI_CanBeParalyzed(u8 battler, u16 ability)
return TRUE; return TRUE;
} }
bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove) bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{ {
if (!AI_CanBeParalyzed(battlerDef, defAbility) if (!AI_CanBeParalyzed(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
@ -2882,7 +2882,7 @@ bool32 AI_CanBeConfused(u8 battler, u16 ability)
return TRUE; return TRUE;
} }
bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove) bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove)
{ {
if (!AI_CanBeConfused(battlerDef, defAbility) if (!AI_CanBeConfused(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
@ -2935,7 +2935,7 @@ bool32 ShouldBurnSelf(u8 battler, u16 ability)
return FALSE; return FALSE;
} }
bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove) bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove)
{ {
if (!AI_CanBeBurned(battlerDef, defAbility) if (!AI_CanBeBurned(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
@ -2947,7 +2947,7 @@ bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPar
return TRUE; return TRUE;
} }
bool32 AI_CanGiveFrostbite(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove) bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove)
{ {
if (!AI_CanGetFrostbite(battlerDef, defAbility) if (!AI_CanGetFrostbite(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
@ -2959,7 +2959,7 @@ bool32 AI_CanGiveFrostbite(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 batt
return TRUE; return TRUE;
} }
bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility) bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u16 defAbility)
{ {
if ((gBattleMons[battlerDef].status2 & STATUS2_INFATUATION) if ((gBattleMons[battlerDef].status2 & STATUS2_INFATUATION)
|| AI_GetMoveEffectiveness(AI_THINKING_STRUCT->moveConsidered, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 || AI_GetMoveEffectiveness(AI_THINKING_STRUCT->moveConsidered, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
@ -2970,7 +2970,7 @@ bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility)
return TRUE; return TRUE;
} }
u32 ShouldTryToFlinch(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u16 move) u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u16 atkAbility, u16 defAbility, u16 move)
{ {
if (((AI_DATA->abilities[battlerAtk] != ABILITY_MOLD_BREAKER && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS)) if (((AI_DATA->abilities[battlerAtk] != ABILITY_MOLD_BREAKER && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS))
|| AI_GetHoldEffect(battlerDef) == HOLD_EFFECT_COVERT_CLOAK || AI_GetHoldEffect(battlerDef) == HOLD_EFFECT_COVERT_CLOAK
@ -2991,7 +2991,7 @@ u32 ShouldTryToFlinch(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbili
return 0; // don't try to flinch return 0; // don't try to flinch
} }
bool32 ShouldTrap(u8 battlerAtk, u8 battlerDef, u16 move) bool32 ShouldTrap(u32 battlerAtk, u32 battlerDef, u16 move)
{ {
if (BattlerWillFaintFromSecondaryDamage(battlerDef, AI_DATA->abilities[battlerDef])) if (BattlerWillFaintFromSecondaryDamage(battlerDef, AI_DATA->abilities[battlerDef]))
return TRUE; // battler is taking secondary damage with low HP return TRUE; // battler is taking secondary damage with low HP
@ -3005,7 +3005,7 @@ bool32 ShouldTrap(u8 battlerAtk, u8 battlerDef, u16 move)
return FALSE; return FALSE;
} }
bool32 ShouldFakeOut(u8 battlerAtk, u8 battlerDef, u16 move) bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u16 move)
{ {
if (!gDisableStructs[battlerAtk].isFirstTurn if (!gDisableStructs[battlerAtk].isFirstTurn
|| AI_DATA->abilities[battlerAtk] == ABILITY_GORILLA_TACTICS || AI_DATA->abilities[battlerAtk] == ABILITY_GORILLA_TACTICS
@ -3082,7 +3082,7 @@ u16 GetBattlerSideSpeedAverage(u8 battler)
return (speed1 + speed2) / numBattlersAlive; return (speed1 + speed2) / numBattlersAlive;
} }
bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveIndex) bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u8 moveIndex)
{ {
if (recoilDmg >= gBattleMons[battlerAtk].hp //Recoil kills attacker if (recoilDmg >= gBattleMons[battlerAtk].hp //Recoil kills attacker
&& CountUsablePartyMons(battlerDef) != 0) //Foe has more than 1 target left && CountUsablePartyMons(battlerDef) != 0) //Foe has more than 1 target left
@ -3096,7 +3096,7 @@ bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveI
return TRUE; return TRUE;
} }
bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage) bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u16 move, s32 damage)
{ {
if (move == 0xFFFF || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) if (move == 0xFFFF || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
{ {
@ -3123,7 +3123,7 @@ bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage)
return FALSE; return FALSE;
} }
bool32 ShouldRecover(u8 battlerAtk, u8 battlerDef, u16 move, u8 healPercent) bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u16 move, u8 healPercent)
{ {
if (move == 0xFFFF || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) if (move == 0xFFFF || AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
{ {
@ -3142,7 +3142,7 @@ bool32 ShouldRecover(u8 battlerAtk, u8 battlerDef, u16 move, u8 healPercent)
return FALSE; return FALSE;
} }
bool32 ShouldSetScreen(u8 battlerAtk, u8 battlerDef, u16 moveEffect) bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, u16 moveEffect)
{ {
u8 atkSide = GetBattlerSide(battlerAtk); u8 atkSide = GetBattlerSide(battlerAtk);
switch (moveEffect) switch (moveEffect)
@ -3171,7 +3171,7 @@ bool32 ShouldSetScreen(u8 battlerAtk, u8 battlerDef, u16 moveEffect)
} }
// Partner Logic // Partner Logic
bool32 IsValidDoubleBattle(u8 battlerAtk) bool32 IsValidDoubleBattle(u32 battlerAtk)
{ {
if (IsDoubleBattle() if (IsDoubleBattle()
&& ((IsBattlerAlive(BATTLE_OPPOSITE(battlerAtk)) && IsBattlerAlive(BATTLE_PARTNER(BATTLE_OPPOSITE(battlerAtk)))) || IsBattlerAlive(BATTLE_PARTNER(battlerAtk)))) && ((IsBattlerAlive(BATTLE_OPPOSITE(battlerAtk)) && IsBattlerAlive(BATTLE_PARTNER(BATTLE_OPPOSITE(battlerAtk)))) || IsBattlerAlive(BATTLE_PARTNER(battlerAtk))))
@ -3191,7 +3191,7 @@ u16 GetAllyChosenMove(u8 battlerId)
return gBattleMons[partnerBattler].moves[gBattleStruct->chosenMovePositions[partnerBattler]]; return gBattleMons[partnerBattler].moves[gBattleStruct->chosenMovePositions[partnerBattler]];
} }
bool32 IsTargetingPartner(u8 battlerAtk, u8 battlerDef) bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef)
{ {
if ((battlerAtk & BIT_SIDE) == (battlerDef & BIT_SIDE)) if ((battlerAtk & BIT_SIDE) == (battlerDef & BIT_SIDE))
return TRUE; return TRUE;
@ -3200,7 +3200,7 @@ bool32 IsTargetingPartner(u8 battlerAtk, u8 battlerDef)
} }
//PARTNER_MOVE_EFFECT_IS_SAME //PARTNER_MOVE_EFFECT_IS_SAME
bool32 DoesPartnerHaveSameMoveEffect(u8 battlerAtkPartner, u8 battlerDef, u16 move, u16 partnerMove) bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u16 move, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
@ -3215,7 +3215,7 @@ bool32 DoesPartnerHaveSameMoveEffect(u8 battlerAtkPartner, u8 battlerDef, u16 mo
} }
//PARTNER_MOVE_EFFECT_IS_SAME_NO_TARGET //PARTNER_MOVE_EFFECT_IS_SAME_NO_TARGET
bool32 PartnerHasSameMoveEffectWithoutTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove) bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u16 move, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
@ -3227,7 +3227,7 @@ bool32 PartnerHasSameMoveEffectWithoutTarget(u8 battlerAtkPartner, u16 move, u16
} }
//PARTNER_MOVE_EFFECT_IS_STATUS_SAME_TARGET //PARTNER_MOVE_EFFECT_IS_STATUS_SAME_TARGET
bool32 PartnerMoveEffectIsStatusSameTarget(u8 battlerAtkPartner, u8 battlerDef, u16 partnerMove) bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
@ -3245,7 +3245,7 @@ bool32 PartnerMoveEffectIsStatusSameTarget(u8 battlerAtkPartner, u8 battlerDef,
} }
//PARTNER_MOVE_EFFECT_IS_WEATHER //PARTNER_MOVE_EFFECT_IS_WEATHER
bool32 PartnerMoveEffectIsWeather(u8 battlerAtkPartner, u16 partnerMove) bool32 PartnerMoveEffectIsWeather(u32 battlerAtkPartner, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
@ -3262,7 +3262,7 @@ bool32 PartnerMoveEffectIsWeather(u8 battlerAtkPartner, u16 partnerMove)
} }
//PARTNER_MOVE_EFFECT_IS_TERRAIN //PARTNER_MOVE_EFFECT_IS_TERRAIN
bool32 PartnerMoveEffectIsTerrain(u8 battlerAtkPartner, u16 partnerMove) bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
@ -3278,7 +3278,7 @@ bool32 PartnerMoveEffectIsTerrain(u8 battlerAtkPartner, u16 partnerMove)
} }
//PARTNER_MOVE_IS_TAILWIND_TRICKROOM //PARTNER_MOVE_IS_TAILWIND_TRICKROOM
bool32 PartnerMoveIs(u8 battlerAtkPartner, u16 partnerMove, u16 moveCheck) bool32 PartnerMoveIs(u32 battlerAtkPartner, u16 partnerMove, u16 moveCheck)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
@ -3289,7 +3289,7 @@ bool32 PartnerMoveIs(u8 battlerAtkPartner, u16 partnerMove, u16 moveCheck)
} }
//PARTNER_MOVE_IS_SAME //PARTNER_MOVE_IS_SAME
bool32 PartnerMoveIsSameAsAttacker(u8 battlerAtkPartner, u8 battlerDef, u16 move, u16 partnerMove) bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u16 move, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
@ -3300,7 +3300,7 @@ bool32 PartnerMoveIsSameAsAttacker(u8 battlerAtkPartner, u8 battlerDef, u16 move
} }
//PARTNER_MOVE_IS_SAME_NO_TARGET //PARTNER_MOVE_IS_SAME_NO_TARGET
bool32 PartnerMoveIsSameNoTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove) bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u16 move, u16 partnerMove)
{ {
if (!IsDoubleBattle()) if (!IsDoubleBattle())
return FALSE; return FALSE;
@ -3309,7 +3309,7 @@ bool32 PartnerMoveIsSameNoTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove
return FALSE; return FALSE;
} }
bool32 ShouldUseWishAromatherapy(u8 battlerAtk, u8 battlerDef, u16 move) bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u16 move)
{ {
u32 i; u32 i;
u32 firstId, lastId; u32 firstId, lastId;
@ -3413,7 +3413,7 @@ s32 AI_CalcPartyMonBestMoveDamage(u32 battlerAtk, u32 battlerDef, struct Pokemon
if (move != MOVE_NONE && gBattleMoves[move].power != 0) if (move != MOVE_NONE && gBattleMoves[move].power != 0)
{ {
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, FALSE); dmg = AI_CalcDamageSaveBattlers(move, battlerAtk, battlerDef, &effectiveness, FALSE);
if (dmg > bestDmg) if (dmg > bestDmg)
bestDmg = dmg; bestDmg = dmg;
} }
@ -3568,7 +3568,7 @@ bool32 IsStatBoostingBerry(u16 item)
} }
} }
bool32 ShouldRestoreHpBerry(u8 battlerAtk, u16 item) bool32 ShouldRestoreHpBerry(u32 battlerAtk, u16 item)
{ {
switch (item) switch (item)
{ {
@ -3602,7 +3602,7 @@ bool32 IsRecycleEncouragedItem(u16 item)
// score increases // score increases
#define STAT_UP_2_STAGE 8 #define STAT_UP_2_STAGE 8
#define STAT_UP_STAGE 10 #define STAT_UP_STAGE 10
void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score) void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u8 statId, s16 *score)
{ {
if (AI_DATA->abilities[battlerAtk] == ABILITY_CONTRARY) if (AI_DATA->abilities[battlerAtk] == ABILITY_CONTRARY)
return; return;
@ -3682,7 +3682,7 @@ void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score)
} }
} }
void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score)
{ {
if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_PSN || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS) || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_PSN || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS)
@ -3706,7 +3706,7 @@ void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
} }
} }
void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score)
{ {
if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_BRN || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS) || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_BRN || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS)
@ -3726,7 +3726,7 @@ void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
} }
} }
void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score)
{ {
if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_PAR || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS) || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_PAR || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS)
@ -3748,7 +3748,7 @@ void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
} }
} }
void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score)
{ {
if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_SLP || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS) || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_SLP || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS)
@ -3767,7 +3767,7 @@ void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
(*score)++; (*score)++;
} }
void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score)
{ {
if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if (((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_CONFUSION || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS) || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_CONFUSION || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS)
@ -3786,7 +3786,7 @@ void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
} }
} }
void IncreaseFrostbiteScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u16 move, s16 *score)
{ {
if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0))
return; return;
@ -3815,7 +3815,7 @@ bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move)
} }
//TODO - this could use some more sophisticated logic //TODO - this could use some more sophisticated logic
bool32 ShouldUseZMove(u8 battlerAtk, u8 battlerDef, u16 chosenMove) bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u16 chosenMove)
{ {
// simple logic. just upgrades chosen move to z move if possible, unless regular move would kill opponent // simple logic. just upgrades chosen move to z move if possible, unless regular move would kill opponent
if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && battlerDef == BATTLE_PARTNER(battlerAtk)) if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && battlerDef == BATTLE_PARTNER(battlerAtk))
@ -3837,7 +3837,7 @@ bool32 ShouldUseZMove(u8 battlerAtk, u8 battlerDef, u16 chosenMove)
else if (!IS_MOVE_STATUS(chosenMove) && IS_MOVE_STATUS(gBattleStruct->zmove.chosenZMove)) else if (!IS_MOVE_STATUS(chosenMove) && IS_MOVE_STATUS(gBattleStruct->zmove.chosenZMove))
return FALSE; return FALSE;
if (!IS_MOVE_STATUS(chosenMove) && AI_CalcDamage(chosenMove, battlerAtk, battlerDef, &effectiveness, FALSE) >= gBattleMons[battlerDef].hp) if (!IS_MOVE_STATUS(chosenMove) && AI_CalcDamageSaveBattlers(chosenMove, battlerAtk, battlerDef, &effectiveness, FALSE) >= gBattleMons[battlerDef].hp)
return FALSE; // don't waste damaging z move if can otherwise faint target return FALSE; // don't waste damaging z move if can otherwise faint target
return TRUE; return TRUE;

View File

@ -5575,7 +5575,7 @@ void RunBattleScriptCommands(void)
gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]](); gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
} }
void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk) void SetTypeBeforeUsingMove(u16 move, u32 battlerAtk)
{ {
u32 moveType, ateType, attackerAbility; u32 moveType, ateType, attackerAbility;
u16 holdEffect = GetBattlerHoldEffect(battlerAtk, TRUE); u16 holdEffect = GetBattlerHoldEffect(battlerAtk, TRUE);

View File

@ -1907,7 +1907,7 @@ static void Cmd_ppreduce(void)
#endif // B_CRIT_CHANCE #endif // B_CRIT_CHANCE
#define BENEFITS_FROM_LEEK(battler, holdEffect)((holdEffect == HOLD_EFFECT_LEEK) && (GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_FARFETCHD || gBattleMons[battler].species == SPECIES_SIRFETCHD)) #define BENEFITS_FROM_LEEK(battler, holdEffect)((holdEffect == HOLD_EFFECT_LEEK) && (GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_FARFETCHD || gBattleMons[battler].species == SPECIES_SIRFETCHD))
s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility) s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility)
{ {
s32 critChance = 0; s32 critChance = 0;
u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); u32 abilityAtk = GetBattlerAbility(gBattlerAttacker);
@ -1952,7 +1952,7 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi
} }
#undef BENEFITS_FROM_LEEK #undef BENEFITS_FROM_LEEK
s8 GetInverseCritChance(u8 battlerAtk, u8 battlerDef, u32 move) s8 GetInverseCritChance(u32 battlerAtk, u32 battlerDef, u32 move)
{ {
s32 critChanceIndex = CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE); s32 critChanceIndex = CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE);
if(critChanceIndex < 0) if(critChanceIndex < 0)
@ -5657,6 +5657,7 @@ static void Cmd_moveend(void)
if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove) if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
{ {
gLastMoves[gBattlerAttacker] = gChosenMove; gLastMoves[gBattlerAttacker] = gChosenMove;
RecordKnownMove(gBattlerAttacker, gChosenMove);
gLastResultingMoves[gBattlerAttacker] = gCurrentMove; gLastResultingMoves[gBattlerAttacker] = gCurrentMove;
} }
} }
@ -8242,7 +8243,7 @@ static void RemoveAllTerrains(void)
} \ } \
} }
static bool32 TryDefogClear(u8 battlerAtk, bool32 clear) static bool32 TryDefogClear(u32 battlerAtk, bool32 clear)
{ {
s32 i; s32 i;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
@ -14760,7 +14761,7 @@ static void Cmd_settypebasedhalvers(void)
gBattlescriptCurrInstr = cmd->failInstr; gBattlescriptCurrInstr = cmd->failInstr;
} }
bool32 DoesSubstituteBlockMove(u8 battlerAtk, u8 battlerDef, u32 move) bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move)
{ {
if (!(gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE)) if (!(gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE))
return FALSE; return FALSE;
@ -14776,7 +14777,7 @@ bool32 DoesSubstituteBlockMove(u8 battlerAtk, u8 battlerDef, u32 move)
return TRUE; return TRUE;
} }
bool32 DoesDisguiseBlockMove(u8 battlerAtk, u8 battlerDef, u32 move) bool32 DoesDisguiseBlockMove(u32 battlerAtk, u32 battlerDef, u32 move)
{ {
if (gBattleMons[battlerDef].species != SPECIES_MIMIKYU if (gBattleMons[battlerDef].species != SPECIES_MIMIKYU
|| gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED || gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED

View File

@ -4244,7 +4244,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
gBattleWeather = B_WEATHER_SNOW; gBattleWeather = B_WEATHER_SNOW;
gBattleScripting.animArg1 = B_ANIM_SNOW_CONTINUES; gBattleScripting.animArg1 = B_ANIM_SNOW_CONTINUES;
effect++; effect++;
#else #else
gBattleWeather = B_WEATHER_HAIL; gBattleWeather = B_WEATHER_HAIL;
gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES; gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES;
effect++; effect++;
@ -8100,7 +8100,7 @@ u8 IsMonDisobedient(void)
} }
} }
u32 GetBattlerHoldEffect(u8 battler, bool32 checkNegating) u32 GetBattlerHoldEffect(u32 battler, bool32 checkNegating)
{ {
if (checkNegating) if (checkNegating)
{ {
@ -8136,7 +8136,7 @@ u32 GetBattlerHoldEffectParam(u8 battler)
return ItemId_GetHoldEffectParam(gBattleMons[battler].item); return ItemId_GetHoldEffectParam(gBattleMons[battler].item);
} }
bool32 IsMoveMakingContact(u16 move, u8 battlerAtk) bool32 IsMoveMakingContact(u16 move, u32 battlerAtk)
{ {
u16 atkHoldEffect = GetBattlerHoldEffect(battlerAtk, TRUE); u16 atkHoldEffect = GetBattlerHoldEffect(battlerAtk, TRUE);
@ -8321,7 +8321,7 @@ u32 CountBattlerStatIncreases(u8 battler, bool32 countEvasionAcc)
return count; return count;
} }
u32 GetMoveTargetCount(u16 move, u8 battlerAtk, u8 battlerDef) u32 GetMoveTargetCount(u16 move, u32 battlerAtk, u32 battlerDef)
{ {
switch (GetBattlerMoveTargetType(gBattlerAttacker, move)) switch (GetBattlerMoveTargetType(gBattlerAttacker, move))
{ {
@ -8460,7 +8460,7 @@ u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter)
return basePower; return basePower;
} }
static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) static inline u16 CalcMoveBasePower(u16 move, u32 battlerAtk, u32 battlerDef, u32 abilityDef)
{ {
u32 i; u32 i;
u16 basePower = gBattleMoves[move].power; u16 basePower = gBattleMoves[move].power;
@ -8535,7 +8535,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
basePower = gNaturalGiftTable[ITEM_TO_BERRY(gBattleMons[battlerAtk].item)].power; basePower = gNaturalGiftTable[ITEM_TO_BERRY(gBattleMons[battlerAtk].item)].power;
break; break;
case EFFECT_WAKE_UP_SLAP: case EFFECT_WAKE_UP_SLAP:
if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP || GetBattlerAbility(battlerDef) == ABILITY_COMATOSE) if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP || abilityDef == ABILITY_COMATOSE)
basePower *= 2; basePower *= 2;
break; break;
case EFFECT_SMELLINGSALT: case EFFECT_SMELLINGSALT:
@ -8547,7 +8547,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
break; break;
case EFFECT_HEX: case EFFECT_HEX:
case EFFECT_INFERNAL_PARADE: case EFFECT_INFERNAL_PARADE:
if (gBattleMons[battlerDef].status1 & STATUS1_ANY || GetBattlerAbility(battlerDef) == ABILITY_COMATOSE) if (gBattleMons[battlerDef].status1 & STATUS1_ANY || abilityDef == ABILITY_COMATOSE)
basePower *= 2; basePower *= 2;
break; break;
case EFFECT_ASSURANCE: case EFFECT_ASSURANCE:
@ -8716,16 +8716,14 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
return basePower; return basePower;
} }
static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, bool32 updateFlags) static inline u32 CalcMoveBasePowerAfterModifiers(u16 move, u32 battlerAtk, u32 battlerDef, u8 moveType, bool32 updateFlags, u32 atkAbility, u32 defAbility, u32 holdEffectAtk)
{ {
u32 i; u32 i;
u32 holdEffectAtk, holdEffectParamAtk; u32 holdEffectParamAtk;
u16 basePower = CalcMoveBasePower(move, battlerAtk, battlerDef); u16 basePower = CalcMoveBasePower(move, battlerAtk, battlerDef, defAbility);
uq4_12_t holdEffectModifier; uq4_12_t holdEffectModifier;
uq4_12_t modifier = UQ_4_12(1.0); uq4_12_t modifier = UQ_4_12(1.0);
u32 atkSide = GET_BATTLER_SIDE(battlerAtk); u32 atkSide = GET_BATTLER_SIDE(battlerAtk);
u16 atkAbility = GetBattlerAbility(battlerAtk);
u16 defAbility = GetBattlerAbility(battlerDef);
// move effect // move effect
switch (gBattleMoves[move].effect) switch (gBattleMoves[move].effect)
@ -9020,7 +9018,6 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
break; break;
} }
holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE);
holdEffectParamAtk = GetBattlerHoldEffectParam(battlerAtk); holdEffectParamAtk = GetBattlerHoldEffectParam(battlerAtk);
if (holdEffectParamAtk > 100) if (holdEffectParamAtk > 100)
holdEffectParamAtk = 100; holdEffectParamAtk = 100;
@ -9099,7 +9096,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
} }
#undef TERRAIN_TYPE_BOOST #undef TERRAIN_TYPE_BOOST
static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, bool32 isCrit, bool32 updateFlags) static inline u32 CalcAttackStat(u16 move, u32 battlerAtk, u32 battlerDef, u8 moveType, bool32 isCrit, bool32 updateFlags, u32 atkAbility, u32 defAbility, u32 holdEffectAtk)
{ {
u8 atkStage; u8 atkStage;
u32 atkStat; u32 atkStat;
@ -9144,7 +9141,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
if (isCrit && atkStage < DEFAULT_STAT_STAGE) if (isCrit && atkStage < DEFAULT_STAT_STAGE)
atkStage = DEFAULT_STAT_STAGE; atkStage = DEFAULT_STAT_STAGE;
// pokemon with unaware ignore attack stat changes while taking damage // pokemon with unaware ignore attack stat changes while taking damage
if (GetBattlerAbility(battlerDef) == ABILITY_UNAWARE) if (defAbility == ABILITY_UNAWARE)
atkStage = DEFAULT_STAT_STAGE; atkStage = DEFAULT_STAT_STAGE;
atkStat *= gStatStageRatios[atkStage][0]; atkStat *= gStatStageRatios[atkStage][0];
@ -9154,7 +9151,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
modifier = UQ_4_12(1.0); modifier = UQ_4_12(1.0);
// attacker's abilities // attacker's abilities
switch (GetBattlerAbility(battlerAtk)) switch (atkAbility)
{ {
case ABILITY_HUGE_POWER: case ABILITY_HUGE_POWER:
case ABILITY_PURE_POWER: case ABILITY_PURE_POWER:
@ -9232,7 +9229,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
} }
// target's abilities // target's abilities
switch (GetBattlerAbility(battlerDef)) switch (defAbility)
{ {
case ABILITY_THICK_FAT: case ABILITY_THICK_FAT:
if (moveType == TYPE_FIRE || moveType == TYPE_ICE) if (moveType == TYPE_FIRE || moveType == TYPE_ICE)
@ -9257,7 +9254,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
} }
// attacker's hold effect // attacker's hold effect
switch (GetBattlerHoldEffect(battlerAtk, TRUE)) switch (holdEffectAtk)
{ {
case HOLD_EFFECT_THICK_CLUB: case HOLD_EFFECT_THICK_CLUB:
if ((atkBaseSpeciesId == SPECIES_CUBONE || atkBaseSpeciesId == SPECIES_MAROWAK) && IS_MOVE_PHYSICAL(move)) if ((atkBaseSpeciesId == SPECIES_CUBONE || atkBaseSpeciesId == SPECIES_MAROWAK) && IS_MOVE_PHYSICAL(move))
@ -9303,7 +9300,7 @@ static bool32 CanEvolve(u32 species)
return FALSE; return FALSE;
} }
static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, bool32 isCrit, bool32 updateFlags) static inline u32 CalcDefenseStat(u16 move, u32 battlerAtk, u32 battlerDef, u8 moveType, bool32 isCrit, bool32 updateFlags, u32 atkAbility, u32 defAbility, u32 holdEffectDef)
{ {
bool32 usesDefStat; bool32 usesDefStat;
u8 defStage; u8 defStage;
@ -9344,7 +9341,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType,
if (isCrit && defStage > DEFAULT_STAT_STAGE) if (isCrit && defStage > DEFAULT_STAT_STAGE)
defStage = DEFAULT_STAT_STAGE; defStage = DEFAULT_STAT_STAGE;
// pokemon with unaware ignore defense stat changes while dealing damage // pokemon with unaware ignore defense stat changes while dealing damage
if (GetBattlerAbility(battlerAtk) == ABILITY_UNAWARE) if (atkAbility == ABILITY_UNAWARE)
defStage = DEFAULT_STAT_STAGE; defStage = DEFAULT_STAT_STAGE;
// certain moves also ignore stat changes // certain moves also ignore stat changes
if (gBattleMoves[move].ignoresTargetDefenseEvasionStages) if (gBattleMoves[move].ignoresTargetDefenseEvasionStages)
@ -9357,7 +9354,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType,
modifier = UQ_4_12(1.0); modifier = UQ_4_12(1.0);
// target's abilities // target's abilities
switch (GetBattlerAbility(battlerDef)) switch (defAbility)
{ {
case ABILITY_MARVEL_SCALE: case ABILITY_MARVEL_SCALE:
if (gBattleMons[battlerDef].status1 & STATUS1_ANY && usesDefStat) if (gBattleMons[battlerDef].status1 & STATUS1_ANY && usesDefStat)
@ -9406,7 +9403,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType,
} }
// target's hold effects // target's hold effects
switch (GetBattlerHoldEffect(battlerDef, TRUE)) switch (holdEffectDef)
{ {
case HOLD_EFFECT_DEEP_SEA_SCALE: case HOLD_EFFECT_DEEP_SEA_SCALE:
if (gBattleMons[battlerDef].species == SPECIES_CLAMPERL && !usesDefStat) if (gBattleMons[battlerDef].species == SPECIES_CLAMPERL && !usesDefStat)
@ -9582,13 +9579,12 @@ static inline uq4_12_t GetAirborneModifier(u32 move, u32 battlerDef)
return UQ_4_12(1.0); return UQ_4_12(1.0);
} }
static inline uq4_12_t GetScreensModifier(u32 move, u32 battlerAtk, u32 battlerDef, bool32 isCrit) static inline uq4_12_t GetScreensModifier(u32 move, u32 battlerAtk, u32 battlerDef, bool32 isCrit, u32 abilityAtk)
{ {
u32 sideStatus = gSideStatuses[GET_BATTLER_SIDE(battlerDef)]; u32 sideStatus = gSideStatuses[GET_BATTLER_SIDE(battlerDef)];
bool32 lightScreen = (sideStatus & SIDE_STATUS_LIGHTSCREEN) && IS_MOVE_SPECIAL(move); bool32 lightScreen = (sideStatus & SIDE_STATUS_LIGHTSCREEN) && IS_MOVE_SPECIAL(move);
bool32 reflect = (sideStatus & SIDE_STATUS_REFLECT) && IS_MOVE_PHYSICAL(move); bool32 reflect = (sideStatus & SIDE_STATUS_REFLECT) && IS_MOVE_PHYSICAL(move);
bool32 auroraVeil = sideStatus & SIDE_STATUS_AURORA_VEIL; bool32 auroraVeil = sideStatus & SIDE_STATUS_AURORA_VEIL;
u32 abilityAtk = GetBattlerAbility(battlerAtk);
if (isCrit || abilityAtk == ABILITY_INFILTRATOR || gProtectStructs[battlerAtk].confusionSelfDmg) if (isCrit || abilityAtk == ABILITY_INFILTRATOR || gProtectStructs[battlerAtk].confusionSelfDmg)
return UQ_4_12(1.0); return UQ_4_12(1.0);
@ -9604,9 +9600,8 @@ static inline uq4_12_t GetCollisionCourseElectroDriftModifier(u32 move, uq4_12_t
return UQ_4_12(1.0); return UQ_4_12(1.0);
} }
static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, bool32 isCrit) static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, bool32 isCrit, u32 abilityAtk)
{ {
u32 abilityAtk = GetBattlerAbility(battlerAtk);
switch (abilityAtk) switch (abilityAtk)
{ {
case ABILITY_NEUROFORCE: case ABILITY_NEUROFORCE:
@ -9625,9 +9620,8 @@ static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typ
return UQ_4_12(1.0); return UQ_4_12(1.0);
} }
static inline uq4_12_t GetDefenderAbilitiesModifier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t typeEffectivenessModifier) static inline uq4_12_t GetDefenderAbilitiesModifier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t typeEffectivenessModifier, u32 abilityDef)
{ {
u32 abilityDef = GetBattlerAbility(battlerDef);
switch (abilityDef) switch (abilityDef)
{ {
case ABILITY_MULTISCALE: case ABILITY_MULTISCALE:
@ -9673,9 +9667,8 @@ static inline uq4_12_t GetDefenderPartnerAbilitiesModifier(u32 battlerPartnerDef
return UQ_4_12(1.0); return UQ_4_12(1.0);
} }
static inline uq4_12_t GetAttackerItemsModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier) static inline uq4_12_t GetAttackerItemsModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, u32 holdEffectAtk)
{ {
u32 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE);
u32 percentBoost; u32 percentBoost;
switch (holdEffectAtk) switch (holdEffectAtk)
{ {
@ -9694,12 +9687,10 @@ static inline uq4_12_t GetAttackerItemsModifier(u32 battlerAtk, uq4_12_t typeEff
return UQ_4_12(1.0); return UQ_4_12(1.0);
} }
static inline uq4_12_t GetDefenderItemsModifier(u32 moveType, u32 battlerDef, uq4_12_t typeEffectivenessModifier, bool32 updateFlags) static inline uq4_12_t GetDefenderItemsModifier(u32 moveType, u32 battlerDef, uq4_12_t typeEffectivenessModifier, bool32 updateFlags, u32 abilityDef, u32 holdEffectDef)
{ {
u32 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE);
u32 holdEffectDefParam = GetBattlerHoldEffectParam(battlerDef); u32 holdEffectDefParam = GetBattlerHoldEffectParam(battlerDef);
u32 itemDef = gBattleMons[battlerDef].item; u32 itemDef = gBattleMons[battlerDef].item;
u32 abilityDef = GetBattlerAbility(battlerDef);
switch (holdEffectDef) switch (holdEffectDef)
{ {
@ -9727,9 +9718,9 @@ static inline uq4_12_t GetDefenderItemsModifier(u32 moveType, u32 battlerDef, uq
// https://bulbapedia.bulbagarden.net/wiki/Damage#Generation_V_onward // https://bulbapedia.bulbagarden.net/wiki/Damage#Generation_V_onward
// Please Note: Fixed Point Multiplication is not associative. // Please Note: Fixed Point Multiplication is not associative.
// The order of operations is relevant. // The order of operations is relevant.
static uq4_12_t GetOtherModifiers(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, bool32 isCrit, uq4_12_t typeEffectivenessModifier, bool32 updateFlags) static inline uq4_12_t GetOtherModifiers(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, bool32 isCrit, uq4_12_t typeEffectivenessModifier, bool32 updateFlags,
u32 abilityAtk, u32 abilityDef, u32 holdEffectAtk, u32 holdEffectDef)
{ {
u32 abilityAtk = GetBattlerAbility(battlerAtk);
uq4_12_t finalModifier = UQ_4_12(1.0); uq4_12_t finalModifier = UQ_4_12(1.0);
u32 battlerDefPartner = BATTLE_PARTNER(battlerDef); u32 battlerDefPartner = BATTLE_PARTNER(battlerDef);
u32 unmodifiedAttackerSpeed = gBattleMons[battlerAtk].speed; u32 unmodifiedAttackerSpeed = gBattleMons[battlerAtk].speed;
@ -9739,24 +9730,24 @@ static uq4_12_t GetOtherModifiers(u32 move, u32 moveType, u32 battlerAtk, u32 ba
DAMAGE_MULTIPLY_MODIFIER(GetUndergroundModifier(move, battlerDef)); DAMAGE_MULTIPLY_MODIFIER(GetUndergroundModifier(move, battlerDef));
DAMAGE_MULTIPLY_MODIFIER(GetDiveModifier(move, battlerDef)); DAMAGE_MULTIPLY_MODIFIER(GetDiveModifier(move, battlerDef));
DAMAGE_MULTIPLY_MODIFIER(GetAirborneModifier(move, battlerDef)); DAMAGE_MULTIPLY_MODIFIER(GetAirborneModifier(move, battlerDef));
DAMAGE_MULTIPLY_MODIFIER(GetScreensModifier(move, battlerAtk, battlerDef, isCrit)); DAMAGE_MULTIPLY_MODIFIER(GetScreensModifier(move, battlerAtk, battlerDef, isCrit, abilityAtk));
DAMAGE_MULTIPLY_MODIFIER(GetCollisionCourseElectroDriftModifier(move, typeEffectivenessModifier)); DAMAGE_MULTIPLY_MODIFIER(GetCollisionCourseElectroDriftModifier(move, typeEffectivenessModifier));
if (unmodifiedAttackerSpeed >= unmodifiedDefenderSpeed) if (unmodifiedAttackerSpeed >= unmodifiedDefenderSpeed)
{ {
DAMAGE_MULTIPLY_MODIFIER(GetAttackerAbilitiesModifier(battlerAtk, typeEffectivenessModifier, isCrit)); DAMAGE_MULTIPLY_MODIFIER(GetAttackerAbilitiesModifier(battlerAtk, typeEffectivenessModifier, isCrit, abilityAtk));
DAMAGE_MULTIPLY_MODIFIER(GetDefenderAbilitiesModifier(move, moveType, battlerAtk, battlerDef, typeEffectivenessModifier)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderAbilitiesModifier(move, moveType, battlerAtk, battlerDef, typeEffectivenessModifier, abilityDef));
DAMAGE_MULTIPLY_MODIFIER(GetDefenderPartnerAbilitiesModifier(battlerDefPartner)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderPartnerAbilitiesModifier(battlerDefPartner));
DAMAGE_MULTIPLY_MODIFIER(GetAttackerItemsModifier(battlerAtk, typeEffectivenessModifier)); DAMAGE_MULTIPLY_MODIFIER(GetAttackerItemsModifier(battlerAtk, typeEffectivenessModifier, holdEffectAtk));
DAMAGE_MULTIPLY_MODIFIER(GetDefenderItemsModifier(moveType, battlerDef, typeEffectivenessModifier, updateFlags)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderItemsModifier(moveType, battlerDef, typeEffectivenessModifier, updateFlags, abilityDef, holdEffectDef));
} }
else else
{ {
DAMAGE_MULTIPLY_MODIFIER(GetDefenderAbilitiesModifier(move, moveType, battlerAtk, battlerDef, typeEffectivenessModifier)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderAbilitiesModifier(move, moveType, battlerAtk, battlerDef, typeEffectivenessModifier, abilityDef));
DAMAGE_MULTIPLY_MODIFIER(GetDefenderPartnerAbilitiesModifier(battlerDefPartner)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderPartnerAbilitiesModifier(battlerDefPartner));
DAMAGE_MULTIPLY_MODIFIER(GetAttackerAbilitiesModifier(battlerAtk, typeEffectivenessModifier, isCrit)); DAMAGE_MULTIPLY_MODIFIER(GetAttackerAbilitiesModifier(battlerAtk, typeEffectivenessModifier, isCrit, abilityAtk));
DAMAGE_MULTIPLY_MODIFIER(GetDefenderItemsModifier(moveType, battlerDef, typeEffectivenessModifier, updateFlags)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderItemsModifier(moveType, battlerDef, typeEffectivenessModifier, updateFlags, abilityDef, holdEffectDef));
DAMAGE_MULTIPLY_MODIFIER(GetAttackerItemsModifier(battlerAtk, typeEffectivenessModifier)); DAMAGE_MULTIPLY_MODIFIER(GetAttackerItemsModifier(battlerAtk, typeEffectivenessModifier, holdEffectAtk));
} }
return finalModifier; return finalModifier;
} }
@ -9767,7 +9758,7 @@ static uq4_12_t GetOtherModifiers(u32 move, u32 moveType, u32 battlerAtk, u32 ba
dmg = uq4_12_multiply_by_int_half_down(modifier, dmg); \ dmg = uq4_12_multiply_by_int_half_down(modifier, dmg); \
} while (0) } while (0)
static s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, static inline s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower,
bool32 isCrit, bool32 randomFactor, bool32 updateFlags, uq4_12_t typeEffectivenessModifier) bool32 isCrit, bool32 randomFactor, bool32 updateFlags, uq4_12_t typeEffectivenessModifier)
{ {
s32 dmg; s32 dmg;
@ -9776,6 +9767,7 @@ static s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveTy
u32 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); u32 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE);
u32 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); u32 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE);
u32 abilityAtk = GetBattlerAbility(battlerAtk); u32 abilityAtk = GetBattlerAbility(battlerAtk);
u32 abilityDef = GetBattlerAbility(battlerDef);
if (typeEffectivenessModifier == UQ_4_12(0.0)) if (typeEffectivenessModifier == UQ_4_12(0.0))
return 0; return 0;
@ -9783,10 +9775,10 @@ static s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveTy
if (fixedBasePower) if (fixedBasePower)
gBattleMovePower = fixedBasePower; gBattleMovePower = fixedBasePower;
else else
gBattleMovePower = CalcMoveBasePowerAfterModifiers(move, battlerAtk, battlerDef, moveType, updateFlags); gBattleMovePower = CalcMoveBasePowerAfterModifiers(move, battlerAtk, battlerDef, moveType, updateFlags, abilityAtk, abilityDef, holdEffectAtk);
userFinalAttack = CalcAttackStat(move, battlerAtk, battlerDef, moveType, isCrit, updateFlags); userFinalAttack = CalcAttackStat(move, battlerAtk, battlerDef, moveType, isCrit, updateFlags, abilityAtk, abilityDef, holdEffectAtk);
targetFinalDefense = CalcDefenseStat(move, battlerAtk, battlerDef, moveType, isCrit, updateFlags); targetFinalDefense = CalcDefenseStat(move, battlerAtk, battlerDef, moveType, isCrit, updateFlags, abilityAtk, abilityDef, holdEffectDef);
dmg = CalculateBaseDamage(gBattleMovePower, userFinalAttack, gBattleMons[battlerAtk].level, targetFinalDefense); dmg = CalculateBaseDamage(gBattleMovePower, userFinalAttack, gBattleMons[battlerAtk].level, targetFinalDefense);
DAMAGE_APPLY_MODIFIER(GetTargetDamageModifier(move, battlerAtk, battlerDef)); DAMAGE_APPLY_MODIFIER(GetTargetDamageModifier(move, battlerAtk, battlerDef));
@ -9804,7 +9796,7 @@ static s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveTy
DAMAGE_APPLY_MODIFIER(typeEffectivenessModifier); DAMAGE_APPLY_MODIFIER(typeEffectivenessModifier);
DAMAGE_APPLY_MODIFIER(GetBurnOrFrostBiteModifier(battlerAtk, move, abilityAtk)); DAMAGE_APPLY_MODIFIER(GetBurnOrFrostBiteModifier(battlerAtk, move, abilityAtk));
DAMAGE_APPLY_MODIFIER(GetZMoveAgainstProtectionModifier(battlerDef)); DAMAGE_APPLY_MODIFIER(GetZMoveAgainstProtectionModifier(battlerDef));
DAMAGE_APPLY_MODIFIER(GetOtherModifiers(move, moveType, battlerAtk, battlerDef, isCrit, typeEffectivenessModifier, updateFlags)); DAMAGE_APPLY_MODIFIER(GetOtherModifiers(move, moveType, battlerAtk, battlerDef, isCrit, typeEffectivenessModifier, updateFlags, abilityAtk, abilityDef, holdEffectAtk, holdEffectDef));
if (dmg == 0) if (dmg == 0)
dmg = 1; dmg = 1;
@ -9813,20 +9805,20 @@ static s32 DoMoveDamageCalc(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveTy
#undef DAMAGE_APPLY_MODIFIER #undef DAMAGE_APPLY_MODIFIER
s32 CalculateMoveDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 fixedBasePower, bool32 isCrit, bool32 randomFactor, bool32 updateFlags) s32 CalculateMoveDamage(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, bool32 isCrit, bool32 randomFactor, bool32 updateFlags)
{ {
return DoMoveDamageCalc(move, battlerAtk, battlerDef, moveType, fixedBasePower, isCrit, randomFactor, return DoMoveDamageCalc(move, battlerAtk, battlerDef, moveType, fixedBasePower, isCrit, randomFactor,
updateFlags, CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, updateFlags)); updateFlags, CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, updateFlags));
} }
// for AI - get move damage and effectiveness with one function call // for AI - get move damage and effectiveness with one function call
s32 CalculateMoveDamageAndEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 fixedBasePower, uq4_12_t *typeEffectivenessModifier) s32 CalculateMoveDamageAndEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, s32 fixedBasePower, uq4_12_t *typeEffectivenessModifier)
{ {
*typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, FALSE); *typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, FALSE);
return DoMoveDamageCalc(move, battlerAtk, battlerDef, moveType, fixedBasePower, FALSE, FALSE, FALSE, *typeEffectivenessModifier); return DoMoveDamageCalc(move, battlerAtk, battlerDef, moveType, fixedBasePower, FALSE, FALSE, FALSE, *typeEffectivenessModifier);
} }
static void MulByTypeEffectiveness(uq4_12_t *modifier, u16 move, u8 moveType, u8 battlerDef, u8 defType, u8 battlerAtk, bool32 recordAbilities) static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 moveType, u32 battlerDef, u32 defType, u32 battlerAtk, bool32 recordAbilities)
{ {
uq4_12_t mod = GetTypeModifier(moveType, defType); uq4_12_t mod = GetTypeModifier(moveType, defType);
@ -9866,7 +9858,7 @@ static void MulByTypeEffectiveness(uq4_12_t *modifier, u16 move, u8 moveType, u8
*modifier = uq4_12_multiply(*modifier, mod); *modifier = uq4_12_multiply(*modifier, mod);
} }
static void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t resultingModifier, u32 illusionSpecies) static inline void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t resultingModifier, u32 illusionSpecies)
{ {
// Check if the type effectiveness would've been different if the pokemon really had the types as the disguise. // Check if the type effectiveness would've been different if the pokemon really had the types as the disguise.
uq4_12_t presumedModifier = UQ_4_12(1.0); uq4_12_t presumedModifier = UQ_4_12(1.0);
@ -9901,10 +9893,9 @@ static void UpdateMoveResultFlags(uq4_12_t modifier)
} }
} }
static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities, uq4_12_t modifier) static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, bool32 recordAbilities, uq4_12_t modifier, u32 defAbility)
{ {
u32 illusionSpecies; u32 illusionSpecies;
u16 defAbility = GetBattlerAbility(battlerDef);
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type1, battlerAtk, recordAbilities); MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type1, battlerAtk, recordAbilities);
if (gBattleMons[battlerDef].type2 != gBattleMons[battlerDef].type1) if (gBattleMons[battlerDef].type2 != gBattleMons[battlerDef].type1)
@ -9974,15 +9965,16 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat
return modifier; return modifier;
} }
uq4_12_t CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities) uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, bool32 recordAbilities)
{ {
uq4_12_t modifier = UQ_4_12(1.0); uq4_12_t modifier = UQ_4_12(1.0);
if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY) if (move != MOVE_STRUGGLE && moveType != TYPE_MYSTERY)
{ {
modifier = CalcTypeEffectivenessMultiplierInternal(move, moveType, battlerAtk, battlerDef, recordAbilities, modifier); u32 defAbility = GetBattlerAbility(defAbility);
modifier = CalcTypeEffectivenessMultiplierInternal(move, moveType, battlerAtk, battlerDef, recordAbilities, modifier, defAbility);
if (gBattleMoves[move].effect == EFFECT_TWO_TYPED_MOVE) if (gBattleMoves[move].effect == EFFECT_TWO_TYPED_MOVE)
modifier = CalcTypeEffectivenessMultiplierInternal(move, gBattleMoves[move].argument, battlerAtk, battlerDef, recordAbilities, modifier); modifier = CalcTypeEffectivenessMultiplierInternal(move, gBattleMoves[move].argument, battlerAtk, battlerDef, recordAbilities, modifier, defAbility);
} }
if (recordAbilities) if (recordAbilities)
@ -10026,7 +10018,7 @@ static uq4_12_t GetInverseTypeMultiplier(uq4_12_t multiplier)
} }
} }
uq4_12_t GetTypeModifier(u8 atkType, u8 defType) uq4_12_t GetTypeModifier(u32 atkType, u32 defType)
{ {
#if B_FLAG_INVERSE_BATTLE != 0 #if B_FLAG_INVERSE_BATTLE != 0
if (FlagGet(B_FLAG_INVERSE_BATTLE)) if (FlagGet(B_FLAG_INVERSE_BATTLE))
@ -10959,7 +10951,7 @@ bool32 TryRoomService(u8 battler)
} }
} }
bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget) bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u32 battlerDef, bool32 checkTarget)
{ {
#if B_PRANKSTER_DARK_TYPES >= GEN_7 #if B_PRANKSTER_DARK_TYPES >= GEN_7
if (!gProtectStructs[battlerPrankster].pranksterElevated) if (!gProtectStructs[battlerPrankster].pranksterElevated)
@ -11009,7 +11001,7 @@ u32 GetBattlerMoveTargetType(u8 battler, u16 move)
return gBattleMoves[move].target; return gBattleMoves[move].target;
} }
bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move) bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move)
{ {
if (gBattleMoves[move].effect == EFFECT_HIT_ENEMY_HEAL_ALLY if (gBattleMoves[move].effect == EFFECT_HIT_ENEMY_HEAL_ALLY
&& GetBattlerSide(battlerAtk) == GetBattlerSide(battlerDef) && GetBattlerSide(battlerAtk) == GetBattlerSide(battlerDef)