pokeemerald/include/battle_ai_util.h

192 lines
10 KiB
C
Raw Normal View History

#ifndef GUARD_BATTLE_AI_UTIL_H
#define GUARD_BATTLE_AI_UTIL_H
// for AI_WhoStrikesFirst
#define AI_IS_FASTER 0
#define AI_IS_SLOWER 1
2020-12-11 16:05:00 +01:00
#define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE)
2020-12-13 23:02:21 +01:00
#define AI_STRIKES_FIRST(battlerAi, battlerDef, move)((AI_WhoStrikesFirst(battlerAi, battlerDef, move) == AI_IS_FASTER))
bool32 AI_RandLessThan(u8 val);
2023-08-09 15:57:22 +02:00
bool32 IsAiVsAiBattle(void);
2023-03-28 16:38:48 +02:00
bool32 BattlerHasAi(u32 battlerId);
2023-04-10 17:36:17 +02:00
bool32 IsAiBattlerAware(u32 battlerId);
2020-12-11 16:05:00 +01:00
void ClearBattlerMoveHistory(u8 battlerId);
void RecordLastUsedMoveBy(u32 battlerId, u32 move);
void RecordKnownMove(u8 battlerId, u32 move);
void RecordAbilityBattle(u8 battlerId, u16 abilityId);
void ClearBattlerAbilityHistory(u8 battlerId);
void RecordItemEffectBattle(u8 battlerId, u8 itemEffect);
void ClearBattlerItemEffectHistory(u8 battlerId);
void SaveBattlerData(u32 battlerId);
void SetBattlerData(u32 battlerId);
void RestoreBattlerData(u32 battlerId);
u16 GetAIChosenMove(u8 battlerId);
2020-12-11 16:05:00 +01:00
2020-12-20 22:47:20 +01:00
u32 GetTotalBaseStat(u32 species);
bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler);
2020-12-20 05:58:23 +01:00
bool32 AtMaxHp(u8 battler);
u32 GetHealthPercentage(u8 battler);
bool32 IsBattlerTrapped(u8 battler, bool8 switching);
u32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered);
bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk);
bool32 CanMoveFaintBattler(u16 move, u32 battlerDef, u32 battlerAtk, u8 nHits);
bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dmgMod);
2020-12-13 23:02:21 +01:00
s32 AI_GetAbility(u32 battlerId);
u16 AI_GetHoldEffect(u32 battlerId);
u32 AI_GetMoveAccuracy(u32 battlerAtk, u32 battlerDef, u16 move);
2020-12-13 23:02:21 +01:00
bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move);
bool32 AI_WeatherHasEffect(void);
bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u8 numHits);
bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u8 index, u8 numHits);
2021-07-11 00:41:41 +02:00
bool32 AI_IsTerrainAffected(u8 battlerId, u32 flags);
2020-12-13 23:02:21 +01:00
bool32 AI_IsBattlerGrounded(u8 battlerId);
2020-12-20 05:58:23 +01:00
bool32 HasDamagingMove(u8 battlerId);
bool32 HasDamagingMoveOfType(u8 battlerId, u8 type);
u32 GetBattlerSecondaryDamage(u8 battlerId);
2020-12-13 23:02:21 +01:00
bool32 BattlerWillFaintFromWeather(u8 battler, u16 ability);
2020-12-20 05:58:23 +01:00
bool32 BattlerWillFaintFromSecondaryDamage(u8 battler, u16 ability);
bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u16 atkAbility, u16 defAbility, u16 move);
bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u8 moveIndex);
2020-12-13 23:02:21 +01:00
u16 GetBattlerSideSpeedAverage(u8 battler);
bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u16 move, s32 damage);
bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u16 move, u8 healPercent);
bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, u16 moveEffect);
bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u8 moveIndex);
2020-12-20 05:58:23 +01:00
bool32 IsRecycleEncouragedItem(u16 item);
bool32 ShouldRestoreHpBerry(u32 battlerAtk, u16 item);
2021-11-08 17:37:41 +01:00
bool32 IsStatBoostingBerry(u16 item);
2020-12-20 05:58:23 +01:00
bool32 CanKnockOffItem(u8 battler, u16 item);
bool32 IsAbilityOfRating(u16 ability, s8 rating);
s8 GetAbilityRating(u16 ability);
2021-11-04 15:43:33 +01:00
bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move);
u32 AI_GetBattlerMoveTargetType(u8 battlerId, u16 move);
bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u16 chosenMove);
2020-12-13 23:02:21 +01:00
// stat stage checks
bool32 AnyStatIsRaised(u8 battlerId);
bool32 ShouldLowerStat(u8 battler, u16 battlerAbility, u8 stat);
2020-12-13 23:02:21 +01:00
bool32 BattlerStatCanRise(u8 battler, u16 battlerAbility, u8 stat);
bool32 AreBattlersStatsMaxed(u8 battler);
bool32 BattlerHasAnyStatRaised(u8 battlerId);
u32 CountPositiveStatStages(u8 battlerId);
u32 CountNegativeStatStages(u8 battlerId);
bool32 ShouldLowerAttack(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerDefense(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerSpeed(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerSpAtk(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerSpDef(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerAccuracy(u32 battlerAtk, u32 battlerDef, u16 defAbility);
bool32 ShouldLowerEvasion(u32 battlerAtk, u32 battlerDef, u16 defAbility);
2020-12-13 23:02:21 +01:00
// move checks
2020-12-20 05:58:23 +01:00
bool32 IsAffectedByPowder(u8 battler, u16 ability, u16 holdEffect);
bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split);
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);
void SetMoveDamageResult(u32 battlerAtk, u16 *moves);
u32 GetMoveDamageResult(u32 battlerAtk, u32 battlerDef, u32 moveIndex);
u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef);
uq4_12_t AI_GetTypeEffectiveness(u16 move, u32 battlerAtk, u32 battlerDef);
u32 AI_GetMoveEffectiveness(u16 move, u32 battlerAtk, u32 battlerDef);
2020-12-13 23:02:21 +01:00
u16 *GetMovesArray(u32 battler);
bool32 IsConfusionMoveEffect(u16 moveEffect);
2020-12-20 05:58:23 +01:00
bool32 HasMove(u32 battlerId, u32 move);
bool32 HasOnlyMovesWithSplit(u32 battlerId, u32 split, bool32 onlyOffensive);
2020-12-13 23:02:21 +01:00
bool32 HasMoveWithSplit(u32 battler, u32 split);
bool32 HasMoveWithType(u32 battler, u8 type);
2020-12-20 05:58:23 +01:00
bool32 HasMoveWithTypeAndSplit(u32 battler, u8 type, u8 split);
2020-12-16 05:57:33 +01:00
bool32 HasMoveEffect(u32 battlerId, u16 moveEffect);
bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u8 accCheck, bool32 ignoreStatus, u16 atkAbility, u16 defAbility, u16 atkHoldEffect, u16 defHoldEffect);
2020-12-13 23:02:21 +01:00
bool32 IsAromaVeilProtectedMove(u16 move);
bool32 IsNonVolatileStatusMoveEffect(u16 moveEffect);
bool32 IsStatLoweringMoveEffect(u16 moveEffect);
bool32 IsMoveRedirectionPrevented(u16 move, u16 atkAbility);
bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u16 move);
2020-12-13 23:02:21 +01:00
bool32 IsHazardMoveEffect(u16 moveEffect);
bool32 MoveCallsOtherMove(u16 move);
bool32 MoveRequiresRecharging(u16 move);
2020-12-20 05:58:23 +01:00
bool32 IsEncoreEncouragedEffect(u16 moveEffect);
2023-09-13 09:27:49 +02:00
void ProtectChecks(u32 battlerAtk, u32 battlerDef, u16 move, u16 predictedMove, s32 *score);
2020-12-20 05:58:23 +01:00
bool32 ShouldSetSandstorm(u8 battler, u16 ability, u16 holdEffect);
bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect);
2023-04-29 12:30:39 +02:00
bool32 ShouldSetSnow(u8 battler, u16 ability, u16 holdEffect);
bool32 ShouldSetRain(u32 battlerAtk, u16 ability, u16 holdEffect);
bool32 ShouldSetSun(u32 battlerAtk, u16 atkAbility, u16 holdEffect);
bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef);
2020-12-20 05:58:23 +01:00
bool32 IsHealingMoveEffect(u16 effect);
bool32 HasHealingEffect(u32 battler);
2021-01-13 19:08:43 +01:00
bool32 IsTrappingMoveEffect(u16 effect);
bool32 HasTrappingMoveEffect(u8 battler);
bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u16 move);
Convert move flags and bans into GCC bitfields (#2952) * Slicing moves to new bitfield * Wind moves to new bitfield * Two-strike moves to new bitfield * Forgot to add flagTwoStrikes to battle_moves.h * Removed "flag" from field names * FLAG_HIT_IN_SUBSTITUTE and FLAG_THAW_USER * Airborne moves * FLAG_POWDER, FLAG_TARGET_ABILITY_IGNORED and FLAG_DANCE * FLAG_BALLISTIC and FLAG_PROTECTION_MOVE * Fixed missing uses of MOVE_UNAVAILABLE in battle_ai_util.c * FLAG_SOUND * FLAG_DMG_UNDERGROUND and FLAG_DMG_UNDERWATER * FLAG_DMG_MINIMIZE * Cleanup * FLAG_STAT_STAGES_IGNORED * Updated Pollen Puff's ballistic flag * FLAG_STRONG_JAW_BOOST and FLAG_MEGA_LAUNCHER_BOOST * thaw * FLAG_THREE_STRIKES * FLAG_IRON_FIST_BOOST * FLAG_RECKLESS_BOOST * FLAG_HIGH_CRIT * Removed empty flags * Moves that fail when called by Me First + added missing Shell Trap * Moves that fail when Gravity is active * Better names for banned fields * Moves that fail when called by Instruct * Cleanup * Contact Moves + Fixed Wandering Spirit skipping contact checks * Inverted FLAG_PROTECT_AFFECTED so that there's a flag for moves that SKIP protect. * Simplified B_MOVE_FLAGS configs * FORBIDDEN_METRONOME * Renamed hitsPastSubstitute to ignoresSubstitute * FORBIDDEN_PARENTAL_BOND * Struggle uncallable by Metronome * FORBIDDEN_MIMIC * FLAG_KINGS_ROCK_AFFECTED * Made a single config for move flags * Macro for checking move flags * FLAG_MAGIC_COAT_AFFECTED * Fixed HasMagicCoatAffectedMove * FLAG_SNATCH_AFFECTED * Removed unused EFFECT_FLINCH_MINIMIZE_HIT * Fixed Stench/King's Rock interaction * Removed sMovesNotAffectedByStench in favor of checking move effects * Removed EFFECT_TWISTER, which was a repeat of EFFECT_FLINCH_HIT * Changed Gen2 configs to less than Gen 3 * FORBIDDEN_SLEEP_TALK * Cleanup * Inverted FLAG_MIRROR_MOVE_AFFECTED * FLAG_SHEER_FORCE_BOOST * Ordered * FORBIDDEN_ASSIST and FORBIDDEN_COPYCAT * Removed TestMoveFlags and TestMoveFlagsInMoveset + flags field * Fixed Triple Arrows test
2023-07-03 10:01:59 +02:00
bool32 HasThawingMove(u8 battler);
2020-12-20 22:47:20 +01:00
bool32 IsStatRaisingEffect(u16 effect);
bool32 IsStatLoweringEffect(u16 effect);
bool32 IsStatRaisingEffect(u16 effect);
bool32 IsAttackBoostMoveEffect(u16 effect);
2021-01-13 19:08:43 +01:00
bool32 IsUngroundingEffect(u16 effect);
bool32 IsSemiInvulnerable(u32 battlerDef, u16 move);
Convert move flags and bans into GCC bitfields (#2952) * Slicing moves to new bitfield * Wind moves to new bitfield * Two-strike moves to new bitfield * Forgot to add flagTwoStrikes to battle_moves.h * Removed "flag" from field names * FLAG_HIT_IN_SUBSTITUTE and FLAG_THAW_USER * Airborne moves * FLAG_POWDER, FLAG_TARGET_ABILITY_IGNORED and FLAG_DANCE * FLAG_BALLISTIC and FLAG_PROTECTION_MOVE * Fixed missing uses of MOVE_UNAVAILABLE in battle_ai_util.c * FLAG_SOUND * FLAG_DMG_UNDERGROUND and FLAG_DMG_UNDERWATER * FLAG_DMG_MINIMIZE * Cleanup * FLAG_STAT_STAGES_IGNORED * Updated Pollen Puff's ballistic flag * FLAG_STRONG_JAW_BOOST and FLAG_MEGA_LAUNCHER_BOOST * thaw * FLAG_THREE_STRIKES * FLAG_IRON_FIST_BOOST * FLAG_RECKLESS_BOOST * FLAG_HIGH_CRIT * Removed empty flags * Moves that fail when called by Me First + added missing Shell Trap * Moves that fail when Gravity is active * Better names for banned fields * Moves that fail when called by Instruct * Cleanup * Contact Moves + Fixed Wandering Spirit skipping contact checks * Inverted FLAG_PROTECT_AFFECTED so that there's a flag for moves that SKIP protect. * Simplified B_MOVE_FLAGS configs * FORBIDDEN_METRONOME * Renamed hitsPastSubstitute to ignoresSubstitute * FORBIDDEN_PARENTAL_BOND * Struggle uncallable by Metronome * FORBIDDEN_MIMIC * FLAG_KINGS_ROCK_AFFECTED * Made a single config for move flags * Macro for checking move flags * FLAG_MAGIC_COAT_AFFECTED * Fixed HasMagicCoatAffectedMove * FLAG_SNATCH_AFFECTED * Removed unused EFFECT_FLINCH_MINIMIZE_HIT * Fixed Stench/King's Rock interaction * Removed sMovesNotAffectedByStench in favor of checking move effects * Removed EFFECT_TWISTER, which was a repeat of EFFECT_FLINCH_HIT * Changed Gen2 configs to less than Gen 3 * FORBIDDEN_SLEEP_TALK * Cleanup * Inverted FLAG_MIRROR_MOVE_AFFECTED * FLAG_SHEER_FORCE_BOOST * Ordered * FORBIDDEN_ASSIST and FORBIDDEN_COPYCAT * Removed TestMoveFlags and TestMoveFlagsInMoveset + flags field * Fixed Triple Arrows test
2023-07-03 10:01:59 +02:00
bool32 HasSoundMove(u8 battler);
bool32 HasHighCritRatioMove(u8 battler);
bool32 HasMagicCoatAffectedMove(u8 battler);
bool32 HasSnatchAffectedMove(u8 battler);
2020-12-13 23:02:21 +01:00
// status checks
bool32 AI_CanBeBurned(u8 battler, u16 ability);
2023-04-23 20:53:51 +02:00
bool32 AI_CanGetFrostbite(u8 battler, u16 ability);
bool32 AI_CanBeConfused(u8 battler, u16 ability);
bool32 AI_CanSleep(u8 battler, u16 ability);
2020-12-20 22:47:20 +01:00
bool32 IsBattlerIncapacitated(u8 battler, u16 ability);
bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
2020-12-20 05:58:23 +01:00
bool32 ShouldPoisonSelf(u8 battler, u16 ability);
bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove);
2020-12-20 05:58:23 +01:00
bool32 ShouldBurnSelf(u8 battler, u16 ability);
bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u16 defAbility, u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u16 defAbility);
2020-12-16 05:57:33 +01:00
bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof);
u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u16 atkAbility, u16 defAbility, u16 move);
bool32 ShouldTrap(u32 battlerAtk, u32 battlerDef, u16 move);
2020-12-20 05:58:23 +01:00
bool32 IsWakeupTurn(u8 battler);
2023-03-27 14:19:48 +02:00
bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId);
2020-12-13 23:02:21 +01:00
// partner logic
2022-01-13 17:28:27 +01:00
u16 GetAllyChosenMove(u8 battlerId);
bool32 IsValidDoubleBattle(u32 battlerAtk);
bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef);
bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u16 move, u16 partnerMove);
bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u16 partnerMove);
bool32 PartnerMoveEffectIsWeather(u32 battlerAtkPartner, u16 partnerMove);
bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u16 partnerMove);
bool32 PartnerMoveIs(u32 battlerAtkPartner, u16 partnerMove, u16 moveCheck);
bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u16 move, u16 partnerMove);
bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u16 move, u16 partnerMove);
bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u16 move);
2020-12-16 05:57:33 +01:00
// party logic
2023-07-18 12:01:25 +02:00
struct BattlePokemon *AllocSaveBattleMons(void);
void FreeRestoreBattleMons(struct BattlePokemon *savedBattleMons);
2023-07-18 11:36:09 +02:00
s32 AI_CalcPartyMonBestMoveDamage(u32 battlerAtk, u32 battlerDef, struct Pokemon *attackerMon, struct Pokemon *targetMon);
2020-12-16 05:57:33 +01:00
s32 CountUsablePartyMons(u8 battlerId);
bool32 IsPartyFullyHealedExceptBattler(u8 battler);
2020-12-20 05:58:23 +01:00
bool32 PartyHasMoveSplit(u8 battlerId, u8 split);
bool32 SideHasMoveSplit(u8 battlerId, u8 split);
// score increases
2023-09-13 09:27:49 +02:00
void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u8 statId, s32 *score);
void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u16 move, s32 *score);
void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u16 move, s32 *score);
void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u16 move, s32 *score);
void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u16 move, s32 *score);
void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u16 move, s32 *score);
void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u16 move, s32 *score);
2020-12-16 05:57:33 +01:00
#endif //GUARD_BATTLE_AI_UTIL_H