mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-03-13 09:12:24 +01:00
outline AI_CheckGoodMove
This commit is contained in:
parent
ac332d5e98
commit
916d0416e3
@ -7,9 +7,6 @@
|
||||
#define AI_CHOICE_WATCH 5
|
||||
#define AI_CHOICE_SWITCH 7
|
||||
|
||||
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef);
|
||||
s32 AI_CalcPartyMonDamage(u16 move, u8 battlerAtk, u8 battlerDef, struct Pokemon *mon);
|
||||
u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef);
|
||||
void BattleAI_SetupItems(void);
|
||||
void BattleAI_SetupFlags(void);
|
||||
void BattleAI_SetupAIData(u8 defaultScoreMoves);
|
||||
@ -17,12 +14,6 @@ u8 BattleAI_ChooseMoveOrAction(void);
|
||||
bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler);
|
||||
bool32 IsBattlerAIControlled(u32 battlerId);
|
||||
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);
|
||||
|
||||
extern u8 sBattler_AI;
|
||||
|
||||
|
@ -24,14 +24,13 @@ u32 GetHealthPercentage(u8 battler);
|
||||
bool32 IsBattlerTrapped(u8 battler, bool8 switching);
|
||||
bool32 IsBattlerFaster(u8 battler);
|
||||
bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk);
|
||||
bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgMod);
|
||||
s32 AI_GetAbility(u32 battlerId);
|
||||
u16 AI_GetHoldEffect(u32 battlerId);
|
||||
u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u8 atkHoldEffect, u8 defHoldEffect, u16 move);
|
||||
bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move);
|
||||
bool32 AI_WeatherHasEffect(void);
|
||||
bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index);
|
||||
s32 CountUsablePartyMons(u8 battlerId);
|
||||
bool32 IsPartyFullyHealedExceptBattler(u8 battler);
|
||||
bool32 AI_IsBattlerGrounded(u8 battlerId);
|
||||
bool32 BattlerHasDamagingMove(u8 battlerId);
|
||||
bool32 BattlerHasSecondaryDamage(u8 battlerId);
|
||||
@ -39,6 +38,7 @@ bool32 BattlerWillFaintFromWeather(u8 battler, u16 ability);
|
||||
bool32 ShouldTryOHKO(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u32 accuracy, u16 move);
|
||||
bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveIndex);
|
||||
u16 GetBattlerSideSpeedAverage(u8 battler);
|
||||
bool32 ShouldRecover(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage);
|
||||
|
||||
// stat stage checks
|
||||
bool32 AnyStatIsRaised(u8 battlerId);
|
||||
@ -51,13 +51,15 @@ u32 CountNegativeStatStages(u8 battlerId);
|
||||
bool32 BattlerShouldRaiseAttacks(u8 battlerId, u16 ability);
|
||||
|
||||
// move checks
|
||||
u8 GetMovePowerResult(u16 move);
|
||||
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef);
|
||||
u8 GetMoveDamageResult(u16 move);
|
||||
u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef);
|
||||
u8 AI_GetMoveEffectiveness(u16 move);
|
||||
u16 *GetMovesArray(u32 battler);
|
||||
bool32 IsConfusionMoveEffect(u16 moveEffect);
|
||||
bool32 HasMoveWithSplit(u32 battler, u32 split);
|
||||
bool32 HasMoveWithType(u32 battler, u8 type);
|
||||
bool32 HasMoveEffect(u32 battlerId, u16 moveEffect);
|
||||
bool32 TestMoveFlagsInMoveset(u8 battler, u32 flags);
|
||||
bool32 IsAromaVeilProtectedMove(u16 move);
|
||||
bool32 IsNonVolatileStatusMoveEffect(u16 moveEffect);
|
||||
@ -70,13 +72,13 @@ bool32 MoveRequiresRecharging(u16 move);
|
||||
bool32 IsInstructBannedMove(u16 move);
|
||||
|
||||
// status checks
|
||||
bool32 AI_ShouldPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
|
||||
bool32 AI_ShouldPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
|
||||
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
|
||||
bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
|
||||
bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
|
||||
bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof);
|
||||
bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove);
|
||||
bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove);
|
||||
bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 atkGender, u8 defGender);
|
||||
bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof);
|
||||
|
||||
// partner logic
|
||||
u16 GetAllyChosenMove(void);
|
||||
@ -91,4 +93,9 @@ bool32 PartnerMoveIs(u8 battlerAtkPartner, u16 partnerMove, u16 moveCheck);
|
||||
bool32 PartnerMoveIsSameAsAttacker(u8 battlerAtkPartner, u8 battlerDef, u16 move, u16 partnerMove);
|
||||
bool32 PartnerMoveIsSameNoTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove);
|
||||
|
||||
// party logic
|
||||
s32 AI_CalcPartyMonDamage(u16 move, u8 battlerAtk, u8 battlerDef, struct Pokemon *mon);
|
||||
s32 CountUsablePartyMons(u8 battlerId);
|
||||
bool32 IsPartyFullyHealedExceptBattler(u8 battler);
|
||||
|
||||
#endif //GUARD_BATTLE_AI_UTIL_H
|
@ -38,7 +38,7 @@
|
||||
// AI Flags. Most run specific functions to update score, new flags are used for internal logic in other scripts
|
||||
#define AI_FLAG_CHECK_BAD_MOVE (1 << 0)
|
||||
#define AI_FLAG_TRY_TO_FAINT (1 << 1)
|
||||
#define AI_FLAG_CHECK_VIABILITY (1 << 2)
|
||||
#define AI_FLAG_CHECK_GOOD_MOVE (1 << 2) // was AI_SCRIPT_CHECK_VIABILITY
|
||||
#define AI_FLAG_SETUP_FIRST_TURN (1 << 3)
|
||||
#define AI_FLAG_RISKY (1 << 4)
|
||||
#define AI_FLAG_PREFER_STRONGEST_MOVE (1 << 5)
|
||||
@ -49,6 +49,7 @@
|
||||
#define AI_FLAG_NEGATE_AWARE (1 << 9) // AI is aware of negating effects like wonder room, mold breaker, etc (eg. smart trainers). TODO unfinished
|
||||
#define AI_FLAG_HELP_PARTNER (1 << 10) // AI can try to help partner. If not set, will tend not to target partner
|
||||
#define AI_FLAG_WILL_SUICIDE (1 << 11) // AI will use explosion / self destruct / final gambit / etc
|
||||
#define AI_FLAG_PREFER_STATUS_MOVES (1 << 12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves
|
||||
|
||||
// 'other' ai logic flags
|
||||
#define AI_FLAG_ROAMING (1 << 29)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "battle_ai_script_commands.h"
|
||||
#include "battle_ai_util.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_controllers.h"
|
||||
#include "battle_setup.h"
|
||||
|
@ -266,6 +266,63 @@ bool32 IsBattlerTrapped(u8 battler, bool8 checkSwitch)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// move checks
|
||||
static bool32 AI_GetIfCrit(u32 move, u8 battlerAtk, u8 battlerDef)
|
||||
{
|
||||
bool32 isCrit;
|
||||
|
||||
switch (CalcCritChanceStage(battlerAtk, battlerDef, move, FALSE))
|
||||
{
|
||||
case -1:
|
||||
case 0:
|
||||
default:
|
||||
isCrit = FALSE;
|
||||
break;
|
||||
case 1:
|
||||
if (gBattleMoves[move].flags & FLAG_HIGH_CRIT && (Random() % 5 == 0))
|
||||
isCrit = TRUE;
|
||||
else
|
||||
isCrit = FALSE;
|
||||
break;
|
||||
case 2:
|
||||
if (gBattleMoves[move].flags & FLAG_HIGH_CRIT && (Random() % 2 == 0))
|
||||
isCrit = TRUE;
|
||||
else if (!(gBattleMoves[move].flags & FLAG_HIGH_CRIT) && (Random() % 4) == 0)
|
||||
isCrit = TRUE;
|
||||
else
|
||||
isCrit = FALSE;
|
||||
break;
|
||||
case -2:
|
||||
case 3:
|
||||
case 4:
|
||||
isCrit = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return isCrit;
|
||||
}
|
||||
|
||||
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
|
||||
{
|
||||
s32 dmg, moveType;
|
||||
|
||||
SaveBattlerData(battlerAtk);
|
||||
SaveBattlerData(battlerDef);
|
||||
|
||||
SetBattlerData(battlerAtk);
|
||||
SetBattlerData(battlerDef);
|
||||
|
||||
gBattleStruct->dynamicMoveType = 0;
|
||||
SetTypeBeforeUsingMove(move, battlerAtk);
|
||||
GET_MOVE_TYPE(move, moveType);
|
||||
dmg = CalculateMoveDamage(move, battlerAtk, battlerDef, moveType, 0, AI_GetIfCrit(move, battlerAtk, battlerDef), FALSE, FALSE);
|
||||
|
||||
RestoreBattlerData(battlerAtk);
|
||||
RestoreBattlerData(battlerDef);
|
||||
|
||||
return dmg;
|
||||
}
|
||||
|
||||
// Checks if one of the moves has side effects or perks
|
||||
static u32 WhichMoveBetter(u32 move1, u32 move2)
|
||||
{
|
||||
@ -324,7 +381,7 @@ static u32 WhichMoveBetter(u32 move1, u32 move2)
|
||||
return 2;
|
||||
}
|
||||
|
||||
u8 GetMovePowerResult(u16 move)
|
||||
u8 GetMoveDamageResult(u16 move)
|
||||
{
|
||||
s32 i, checkedMove, bestId, currId, hp;
|
||||
s32 moveDmgs[MAX_MON_MOVES];
|
||||
@ -458,8 +515,8 @@ u8 AI_GetMoveEffectiveness(u16 move)
|
||||
return damageVar;
|
||||
}
|
||||
|
||||
// 0: is user(ai) faster
|
||||
// 1: is target faster
|
||||
// AI_CHECK_FASTER: is user(ai) faster
|
||||
// AI_CHECK_SLOWER: is target faster
|
||||
bool32 IsBattlerFaster(u8 battler)
|
||||
{
|
||||
u32 fasterAI = 0, fasterPlayer = 0, i;
|
||||
@ -525,6 +582,26 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check if target has means to faint ai mon after modding hp/dmg
|
||||
bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgMod)
|
||||
{
|
||||
u32 i;
|
||||
u32 unusable = CheckMoveLimitations(battlerDef, 0, 0xFF & ~MOVE_LIMITATION_PP);
|
||||
u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef];
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
u32 dmg = AI_CalcDamage(moves[i], battlerDef, battlerAtk) + dmgMod;
|
||||
u32 hpCheck = gBattleMons[battlerAtk].hp + hpMod;
|
||||
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i]) && dmg >= hpCheck)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// does NOT include ability suppression checks
|
||||
s32 AI_GetAbility(u32 battlerId)
|
||||
{
|
||||
@ -954,42 +1031,6 @@ bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 CountUsablePartyMons(u8 battlerId)
|
||||
{
|
||||
s32 battlerOnField1, battlerOnField2, i, ret;
|
||||
struct Pokemon *party;
|
||||
|
||||
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
party = gEnemyParty;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
battlerOnField1 = gBattlerPartyIndexes[battlerId];
|
||||
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(GetBattlerPosition(battlerId) ^ BIT_FLANK)];
|
||||
}
|
||||
else // In singles there's only one battlerId by side.
|
||||
{
|
||||
battlerOnField1 = gBattlerPartyIndexes[battlerId];
|
||||
battlerOnField2 = gBattlerPartyIndexes[battlerId];
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (i != battlerOnField1 && i != battlerOnField2
|
||||
&& GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG)
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u16 *GetMovesArray(u32 battler)
|
||||
{
|
||||
if (IsBattlerAIControlled(battler) || IsBattlerAIControlled(BATTLE_PARTNER(battler)))
|
||||
@ -1026,6 +1067,20 @@ bool32 HasMoveWithType(u32 battler, u8 type)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasMoveEffect(u32 battlerId, u16 moveEffect)
|
||||
{
|
||||
s32 i;
|
||||
u16 *moves = GetMovesArray(battlerId);
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && gBattleMoves[moves[i]].effect == moveEffect)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsInstructBannedMove(u16 move)
|
||||
{
|
||||
u32 i;
|
||||
@ -1251,7 +1306,7 @@ bool32 BattlerWillFaintFromWeather(u8 battler, u16 ability)
|
||||
}
|
||||
|
||||
// status checks
|
||||
bool32 AI_ShouldPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
|
||||
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
|
||||
{
|
||||
if (defAbility == ABILITY_INSOMNIA
|
||||
|| defAbility == ABILITY_VITAL_SPIRIT
|
||||
@ -1264,7 +1319,7 @@ bool32 AI_ShouldPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 mov
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 AI_ShouldPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
|
||||
bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
|
||||
{
|
||||
if (defAbility == ABILITY_IMMUNITY
|
||||
|| defAbility == ABILITY_PASTEL_VEIL
|
||||
@ -1358,28 +1413,6 @@ bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsPartyFullyHealedExceptBattler(u8 battlerId)
|
||||
{
|
||||
struct Pokemon *party;
|
||||
u32 i;
|
||||
|
||||
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
party = gEnemyParty;
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (i != gBattlerPartyIndexes[battlerId]
|
||||
&& GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG
|
||||
&& GetMonData(&party[i], MON_DATA_HP) < GetMonData(&party[i], MON_DATA_MAX_HP))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u16 GetBattlerSideSpeedAverage(u8 battler)
|
||||
{
|
||||
u16 speed1 = 0;
|
||||
@ -1415,6 +1448,30 @@ bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveI
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 ShouldRecover(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage)
|
||||
{
|
||||
if (move == 0xFFFF || GetWhoStrikesFirst(sBattler_AI, gBattlerTarget, TRUE) == 0)
|
||||
{
|
||||
// using item or user goes first
|
||||
u8 healPercent = (gBattleMoves[move].argument == 0) ? 50 : gBattleMoves[move].argument;
|
||||
s32 healDmg = (healPercent * damage) / 100;
|
||||
|
||||
if (CanTargetFaintAi(battlerDef, battlerAtk)
|
||||
&& !CanTargetFaintAiWithMod(battlerDef, battlerAtk, healDmg, 0))
|
||||
return TRUE; // target can faint attacker unless they heal
|
||||
else if (!CanTargetFaintAi(battlerDef, battlerAtk) && GetHealthPercentage(battlerAtk) < 60 && (Random() % 3))
|
||||
return TRUE; // target can't faint attacker at all, attacker health is about half, 2/3rds rate of encouraging healing
|
||||
}
|
||||
else
|
||||
{
|
||||
// opponent goes first
|
||||
if (!CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Partner Logic
|
||||
bool32 IsValidDoubleBattle(u8 battlerAtk)
|
||||
{
|
||||
@ -1556,3 +1613,82 @@ bool32 PartnerMoveIsSameNoTarget(u8 battlerAtkPartner, u16 move, u16 partnerMove
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// party logic
|
||||
s32 AI_CalcPartyMonDamage(u16 move, u8 battlerAtk, u8 battlerDef, struct Pokemon *mon)
|
||||
{
|
||||
s32 dmg;
|
||||
u32 i;
|
||||
struct BattlePokemon *battleMons = Alloc(sizeof(struct BattlePokemon) * MAX_BATTLERS_COUNT);
|
||||
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
battleMons[i] = gBattleMons[i];
|
||||
|
||||
PokemonToBattleMon(mon, &gBattleMons[battlerAtk]);
|
||||
dmg = AI_CalcDamage(move, battlerAtk, battlerDef);
|
||||
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
gBattleMons[i] = battleMons[i];
|
||||
|
||||
Free(battleMons);
|
||||
|
||||
return dmg;
|
||||
}
|
||||
|
||||
s32 CountUsablePartyMons(u8 battlerId)
|
||||
{
|
||||
s32 battlerOnField1, battlerOnField2, i, ret;
|
||||
struct Pokemon *party;
|
||||
|
||||
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
party = gEnemyParty;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
battlerOnField1 = gBattlerPartyIndexes[battlerId];
|
||||
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(GetBattlerPosition(battlerId) ^ BIT_FLANK)];
|
||||
}
|
||||
else // In singles there's only one battlerId by side.
|
||||
{
|
||||
battlerOnField1 = gBattlerPartyIndexes[battlerId];
|
||||
battlerOnField2 = gBattlerPartyIndexes[battlerId];
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (i != battlerOnField1 && i != battlerOnField2
|
||||
&& GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG)
|
||||
{
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool32 IsPartyFullyHealedExceptBattler(u8 battlerId)
|
||||
{
|
||||
struct Pokemon *party;
|
||||
u32 i;
|
||||
|
||||
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
party = gEnemyParty;
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (i != gBattlerPartyIndexes[battlerId]
|
||||
&& GetMonData(&party[i], MON_DATA_HP) != 0
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG
|
||||
&& GetMonData(&party[i], MON_DATA_HP) < GetMonData(&party[i], MON_DATA_MAX_HP))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -850,13 +850,13 @@ u32 GetAiScriptsInBattleFactory(void)
|
||||
int challengeNum = gSaveBlock2Ptr->frontier.factoryWinStreaks[battleMode][lvlMode] / 7;
|
||||
|
||||
if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN)
|
||||
return AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY;
|
||||
return AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_GOOD_MOVE;
|
||||
else if (challengeNum < 2)
|
||||
return 0;
|
||||
else if (challengeNum < 4)
|
||||
return AI_FLAG_CHECK_BAD_MOVE;
|
||||
else
|
||||
return AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY;
|
||||
return AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_GOOD_MOVE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "battle.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_ai_script_commands.h"
|
||||
#include "battle_ai_util.h"
|
||||
#include "battle_arena.h"
|
||||
#include "battle_controllers.h"
|
||||
#include "battle_interface.h"
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "battle_message.h"
|
||||
#include "battle_anim.h"
|
||||
#include "battle_ai_script_commands.h"
|
||||
#include "battle_ai_util.h"
|
||||
#include "battle_scripts.h"
|
||||
#include "constants/moves.h"
|
||||
#include "constants/abilities.h"
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "window.h"
|
||||
#include "battle_message.h"
|
||||
#include "battle_ai_script_commands.h"
|
||||
#include "battle_ai_util.h"
|
||||
#include "event_data.h"
|
||||
#include "link.h"
|
||||
#include "malloc.h"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -897,7 +897,7 @@ void FillHillTrainersParties(void)
|
||||
// hill trainers.
|
||||
u32 GetTrainerHillAIFlags(void)
|
||||
{
|
||||
return (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY);
|
||||
return (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_GOOD_MOVE);
|
||||
}
|
||||
|
||||
u8 GetTrainerEncounterMusicIdInTrainerHill(u16 trainerId)
|
||||
|
Loading…
x
Reference in New Issue
Block a user