mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 19:47:35 +01:00
Added AI_FLAG_ACE_POKEMON
When this flag is set, the trainer will have an "Ace" pokemon that will always be sent out last. If this flag is set, the last Pokemon in the party will be considered the "Ace" Pokemon. This is similar to the gym leader functionality found in Sword & Shield.
This commit is contained in:
parent
bb978764f3
commit
a4b53126f6
@ -56,6 +56,7 @@
|
|||||||
#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished
|
#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished
|
||||||
#define AI_FLAG_SCREENER (1 << 14) // AI prefers screening effects like reflect, mist, etc. TODO unfinished
|
#define AI_FLAG_SCREENER (1 << 14) // AI prefers screening effects like reflect, mist, etc. TODO unfinished
|
||||||
#define AI_FLAG_SMART_SWITCHING (1 << 15) // AI includes a lot more switching checks
|
#define AI_FLAG_SMART_SWITCHING (1 << 15) // AI includes a lot more switching checks
|
||||||
|
#define AI_FLAG_ACE_POKEMON (1 << 16) // AI has Ace Pokemon -- Saves until last
|
||||||
|
|
||||||
// 'other' ai logic flags
|
// 'other' ai logic flags
|
||||||
#define AI_FLAG_ROAMING (1 << 29)
|
#define AI_FLAG_ROAMING (1 << 29)
|
||||||
|
@ -199,6 +199,10 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
|
|||||||
continue;
|
continue;
|
||||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||||
continue;
|
continue;
|
||||||
|
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||||
|
&& i == (CalculateEnemyPartyCount()-1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
species = GetMonData(&party[i], MON_DATA_SPECIES);
|
species = GetMonData(&party[i], MON_DATA_SPECIES);
|
||||||
if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0)
|
if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0)
|
||||||
@ -276,6 +280,10 @@ static bool8 ShouldSwitchIfGameStatePrompt(void)
|
|||||||
|
|
||||||
for (i = firstId; i < lastId; i++)
|
for (i = firstId; i < lastId; i++)
|
||||||
{
|
{
|
||||||
|
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||||
|
&& i == (CalculateEnemyPartyCount()-1))
|
||||||
|
break;
|
||||||
|
|
||||||
//Look for mon in party that is able to be switched into and has ability that sets terrain
|
//Look for mon in party that is able to be switched into and has ability that sets terrain
|
||||||
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
if (GetMonData(&party[i], MON_DATA_HP) != 0
|
||||||
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE
|
&& GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE
|
||||||
@ -562,6 +570,10 @@ static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent)
|
|||||||
continue;
|
continue;
|
||||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||||
continue;
|
continue;
|
||||||
|
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||||
|
&& i == (CalculateEnemyPartyCount()-1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
species = GetMonData(&party[i], MON_DATA_SPECIES);
|
species = GetMonData(&party[i], MON_DATA_SPECIES);
|
||||||
if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0)
|
if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0)
|
||||||
@ -650,6 +662,9 @@ bool32 ShouldSwitch(void)
|
|||||||
continue;
|
continue;
|
||||||
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
if (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||||
continue;
|
continue;
|
||||||
|
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||||
|
&& i == (CalculateEnemyPartyCount()-1))
|
||||||
|
continue;
|
||||||
|
|
||||||
availableToSwitch++;
|
availableToSwitch++;
|
||||||
}
|
}
|
||||||
@ -712,7 +727,7 @@ void AI_TrySwitchOrUseItem(void)
|
|||||||
|
|
||||||
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
||||||
|
|
||||||
for (monToSwitchId = firstId; monToSwitchId < lastId; monToSwitchId++)
|
for (monToSwitchId = (lastId-1); monToSwitchId >= firstId; monToSwitchId--)
|
||||||
{
|
{
|
||||||
if (GetMonData(&party[monToSwitchId], MON_DATA_HP) == 0)
|
if (GetMonData(&party[monToSwitchId], MON_DATA_HP) == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -724,6 +739,9 @@ void AI_TrySwitchOrUseItem(void)
|
|||||||
continue;
|
continue;
|
||||||
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||||
continue;
|
continue;
|
||||||
|
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||||
|
&& monToSwitchId == (CalculateEnemyPartyCount()-1))
|
||||||
|
continue;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -921,7 +939,9 @@ u8 GetMostSuitableMonToSwitchInto(void)
|
|||||||
|| gBattlerPartyIndexes[battlerIn2] == i
|
|| gBattlerPartyIndexes[battlerIn2] == i
|
||||||
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn1)
|
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn1)
|
||||||
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn2)
|
|| i == *(gBattleStruct->monToSwitchIntoId + battlerIn2)
|
||||||
|| (GetMonAbility(&party[i]) == ABILITY_TRUANT && IsTruantMonVulnerable(gActiveBattler, opposingBattler))) // While not really invalid per say, not really wise to switch into this mon.
|
|| (GetMonAbility(&party[i]) == ABILITY_TRUANT && IsTruantMonVulnerable(gActiveBattler, opposingBattler)) // While not really invalid per say, not really wise to switch into this mon.
|
||||||
|
|| (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||||
|
&& i == (CalculateEnemyPartyCount()-1))) //Save Ace Pokemon for last
|
||||||
invalidMons |= gBitTable[i];
|
invalidMons |= gBitTable[i];
|
||||||
else
|
else
|
||||||
aliveCount++;
|
aliveCount++;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "battle.h"
|
#include "battle.h"
|
||||||
#include "battle_ai_main.h"
|
#include "battle_ai_main.h"
|
||||||
#include "battle_ai_util.h"
|
#include "battle_ai_util.h"
|
||||||
|
#include "constants/battle_ai.h"
|
||||||
#include "battle_anim.h"
|
#include "battle_anim.h"
|
||||||
#include "battle_arena.h"
|
#include "battle_arena.h"
|
||||||
#include "battle_controllers.h"
|
#include "battle_controllers.h"
|
||||||
@ -94,6 +95,7 @@ static void OpponentHandleResetActionMoveSelection(void);
|
|||||||
static void OpponentHandleEndLinkBattle(void);
|
static void OpponentHandleEndLinkBattle(void);
|
||||||
static void OpponentHandleDebugMenu(void);
|
static void OpponentHandleDebugMenu(void);
|
||||||
static void OpponentCmdEnd(void);
|
static void OpponentCmdEnd(void);
|
||||||
|
static u8 CountAIAliveNonEggMonsExcept(u8 slotToIgnore);
|
||||||
|
|
||||||
static void OpponentBufferRunCommand(void);
|
static void OpponentBufferRunCommand(void);
|
||||||
static void OpponentBufferExecCompleted(void);
|
static void OpponentBufferExecCompleted(void);
|
||||||
@ -1670,6 +1672,7 @@ static void OpponentHandleChooseItem(void)
|
|||||||
static void OpponentHandleChoosePokemon(void)
|
static void OpponentHandleChoosePokemon(void)
|
||||||
{
|
{
|
||||||
s32 chosenMonId;
|
s32 chosenMonId;
|
||||||
|
s32 pokemonInBattle = 1;
|
||||||
|
|
||||||
if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE)
|
if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE)
|
||||||
{
|
{
|
||||||
@ -1687,15 +1690,20 @@ static void OpponentHandleChoosePokemon(void)
|
|||||||
{
|
{
|
||||||
battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||||
battler2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
battler2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||||
|
pokemonInBattle = 2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
||||||
|
|
||||||
for (chosenMonId = firstId; chosenMonId < lastId; chosenMonId++)
|
for (chosenMonId = (lastId-1); chosenMonId >= firstId; chosenMonId--)
|
||||||
{
|
{
|
||||||
if (GetMonData(&gEnemyParty[chosenMonId], MON_DATA_HP) != 0
|
if (GetMonData(&gEnemyParty[chosenMonId], MON_DATA_HP) != 0
|
||||||
&& chosenMonId != gBattlerPartyIndexes[battler1]
|
&& chosenMonId != gBattlerPartyIndexes[battler1]
|
||||||
&& chosenMonId != gBattlerPartyIndexes[battler2])
|
&& chosenMonId != gBattlerPartyIndexes[battler2]
|
||||||
|
&& (AI_THINKING_STRUCT->aiFlags & AI_FLAG_ACE_POKEMON
|
||||||
|
&& (!(chosenMonId == (CalculateEnemyPartyCount()-1))
|
||||||
|
|| CountAIAliveNonEggMonsExcept(PARTY_SIZE) == pokemonInBattle)))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1714,6 +1722,24 @@ static void OpponentHandleChoosePokemon(void)
|
|||||||
OpponentBufferExecCompleted();
|
OpponentBufferExecCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u8 CountAIAliveNonEggMonsExcept(u8 slotToIgnore)
|
||||||
|
{
|
||||||
|
u16 i, count;
|
||||||
|
|
||||||
|
for (i = 0, count = 0; i < PARTY_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (i != slotToIgnore
|
||||||
|
&& GetMonData(&gEnemyParty[i], MON_DATA_SPECIES) != SPECIES_NONE
|
||||||
|
&& !GetMonData(&gEnemyParty[i], MON_DATA_IS_EGG)
|
||||||
|
&& GetMonData(&gEnemyParty[i], MON_DATA_HP) != 0)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static void OpponentHandleCmd23(void)
|
static void OpponentHandleCmd23(void)
|
||||||
{
|
{
|
||||||
OpponentBufferExecCompleted();
|
OpponentBufferExecCompleted();
|
||||||
|
Loading…
Reference in New Issue
Block a user