mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-28 04:34:28 +01:00
AI switch mons if all moves are not usable
This commit is contained in:
parent
30bd85a58a
commit
272fa07799
@ -249,6 +249,7 @@ struct AI_ThinkingStruct
|
||||
u8 aiLogicId;
|
||||
u8 simulatedRNG[4];
|
||||
struct AI_SavedBattleMon saved[4];
|
||||
bool8 switchMon; // Because all available moves have no/little effect.
|
||||
};
|
||||
|
||||
struct UsedMoves
|
||||
|
@ -5,6 +5,7 @@
|
||||
// 0 - 3 are move idx
|
||||
#define AI_CHOICE_FLEE 4
|
||||
#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);
|
||||
|
@ -54,6 +54,7 @@ static void RecordLastUsedMoveByTarget(void);
|
||||
static void BattleAI_DoAIProcessing(void);
|
||||
static void AIStackPushVar(const u8 *);
|
||||
static bool8 AIStackPop(void);
|
||||
static s32 CountUsablePartyMons(u8 battlerId);
|
||||
|
||||
static void BattleAICmd_if_random_less_than(void);
|
||||
static void BattleAICmd_if_random_greater_than(void);
|
||||
@ -448,6 +449,28 @@ static u8 ChooseMoveOrAction_Singles(void)
|
||||
if (AI_THINKING_STRUCT->aiAction & AI_ACTION_WATCH)
|
||||
return AI_CHOICE_WATCH;
|
||||
|
||||
// Consider switching if all moves are worthless to use.
|
||||
if (AI_THINKING_STRUCT->aiFlags & (AI_SCRIPT_CHECK_VIABILITY | AI_SCRIPT_CHECK_BAD_MOVE | AI_SCRIPT_TRY_TO_FAINT | AI_SCRIPT_PREFER_BATON_PASS)
|
||||
&& CountUsablePartyMons(sBattler_AI) >= 1
|
||||
&& gBattleMons[sBattler_AI].hp >= gBattleMons[sBattler_AI].maxHP / 2
|
||||
&& !(gBattleTypeFlags & BATTLE_TYPE_PALACE))
|
||||
{
|
||||
s32 cap = AI_THINKING_STRUCT->aiFlags & (AI_SCRIPT_CHECK_VIABILITY) ? 95 : 93;
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (AI_THINKING_STRUCT->score[i] > cap)
|
||||
break;
|
||||
}
|
||||
|
||||
gActiveBattler = sBattler_AI;
|
||||
if (i == MAX_MON_MOVES && GetMostSuitableMonToSwitchInto() != PARTY_SIZE)
|
||||
{
|
||||
AI_THINKING_STRUCT->switchMon = TRUE;
|
||||
return AI_CHOICE_SWITCH;
|
||||
}
|
||||
}
|
||||
|
||||
numOfBestMoves = 1;
|
||||
currentMoveArray[0] = AI_THINKING_STRUCT->score[0];
|
||||
consideredMoveArray[0] = 0;
|
||||
@ -1422,19 +1445,10 @@ static void BattleAICmd_nullsub_2B(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void BattleAICmd_count_usable_party_mons(void)
|
||||
static s32 CountUsablePartyMons(u8 battlerId)
|
||||
{
|
||||
u8 battlerId;
|
||||
u8 battlerOnField1, battlerOnField2;
|
||||
s32 battlerOnField1, battlerOnField2, i, ret;
|
||||
struct Pokemon *party;
|
||||
s32 i;
|
||||
|
||||
AI_THINKING_STRUCT->funcResult = 0;
|
||||
|
||||
if (gAIScriptPtr[1] == AI_USER)
|
||||
battlerId = sBattler_AI;
|
||||
else
|
||||
battlerId = gBattlerTarget;
|
||||
|
||||
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
@ -1443,10 +1457,8 @@ static void BattleAICmd_count_usable_party_mons(void)
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
u32 position;
|
||||
battlerOnField1 = gBattlerPartyIndexes[battlerId];
|
||||
position = GetBattlerPosition(battlerId) ^ BIT_FLANK;
|
||||
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(position)];
|
||||
battlerOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(GetBattlerPosition(battlerId) ^ BIT_FLANK)];
|
||||
}
|
||||
else // In singles there's only one battlerId by side.
|
||||
{
|
||||
@ -1454,6 +1466,7 @@ static void BattleAICmd_count_usable_party_mons(void)
|
||||
battlerOnField2 = gBattlerPartyIndexes[battlerId];
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (i != battlerOnField1 && i != battlerOnField2
|
||||
@ -1461,10 +1474,16 @@ static void BattleAICmd_count_usable_party_mons(void)
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG)
|
||||
{
|
||||
AI_THINKING_STRUCT->funcResult++;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void BattleAICmd_count_usable_party_mons(void)
|
||||
{
|
||||
AI_THINKING_STRUCT->funcResult = CountUsablePartyMons(BattleAI_GetWantedBattler(gAIScriptPtr[1]));
|
||||
gAIScriptPtr += 2;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,21 @@ void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId)
|
||||
}
|
||||
}
|
||||
|
||||
static bool8 ShouldSwitchIfAllBadMoves(void)
|
||||
{
|
||||
if (gBattleResources->ai->switchMon)
|
||||
{
|
||||
gBattleResources->ai->switchMon = 0;
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static bool8 ShouldSwitchIfPerishSong(void)
|
||||
{
|
||||
if (gStatuses3[gActiveBattler] & STATUS3_PERISH_SONG
|
||||
@ -474,6 +489,8 @@ static bool8 ShouldSwitch(void)
|
||||
|
||||
if (availableToSwitch == 0)
|
||||
return FALSE;
|
||||
if (ShouldSwitchIfAllBadMoves())
|
||||
return TRUE;
|
||||
if (ShouldSwitchIfPerishSong())
|
||||
return TRUE;
|
||||
if (ShouldSwitchIfWonderGuard())
|
||||
|
@ -1551,6 +1551,9 @@ static void OpponentHandleChooseMove(void)
|
||||
case AI_CHOICE_FLEE:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_RUN, 0);
|
||||
break;
|
||||
case AI_CHOICE_SWITCH:
|
||||
BtlController_EmitTwoReturnValues(1, 10, 0xFFFF);
|
||||
break;
|
||||
case 6:
|
||||
BtlController_EmitTwoReturnValues(1, 15, gBattlerTarget);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user