mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-01-13 07:03:40 +01:00
revert ai item usage code
This commit is contained in:
parent
3ac480076c
commit
d108f77aa4
@ -3,10 +3,9 @@
|
||||
|
||||
// return values for BattleAI_ChooseMoveOrAction
|
||||
// 0 - 3 are move idx
|
||||
#define AI_CHOICE_FLEE 4
|
||||
#define AI_CHOICE_WATCH 5
|
||||
#define AI_CHOICE_SWITCH 7
|
||||
#define AI_CHOICE_USE_ITEM 8
|
||||
#define AI_CHOICE_FLEE 4
|
||||
#define AI_CHOICE_WATCH 5
|
||||
#define AI_CHOICE_SWITCH 7
|
||||
|
||||
#define RETURN_SCORE_PLUS(val) \
|
||||
{ \
|
||||
|
@ -32,7 +32,7 @@ enum {
|
||||
};
|
||||
|
||||
void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId);
|
||||
u8 AI_TrySwitchOrUseItem(u8 currAction);
|
||||
void AI_TrySwitchOrUseItem(void);
|
||||
u8 GetMostSuitableMonToSwitchInto(void);
|
||||
bool32 ShouldSwitch(void);
|
||||
|
||||
|
@ -21,8 +21,6 @@ struct UnknownPokemonStruct4
|
||||
/*0x1D*/ u8 language;
|
||||
};
|
||||
|
||||
struct ChooseMoveStruct;
|
||||
|
||||
#define TYPE_NAME_LENGTH 6
|
||||
#define ABILITY_NAME_LENGTH 12
|
||||
|
||||
@ -72,7 +70,6 @@ void RunBattleScriptCommands(void);
|
||||
bool8 TryRunFromBattle(u8 battlerId);
|
||||
void SpecialStatusesClear(void);
|
||||
void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk);
|
||||
void FillChooseMoveStruct(struct ChooseMoveStruct *moveInfo);
|
||||
|
||||
extern struct UnknownPokemonStruct4 gMultiPartnerParty[MULTI_PARTY_SIZE];
|
||||
|
||||
|
@ -209,10 +209,6 @@ u8 BattleAI_ChooseMoveOrAction(void)
|
||||
ret = ChooseMoveOrAction_Singles();
|
||||
else
|
||||
ret = ChooseMoveOrAction_Doubles();
|
||||
|
||||
AI_THINKING_STRUCT->movesetIndex = ret;
|
||||
AI_THINKING_STRUCT->moveConsidered = gBattleMons[sBattler_AI].moves[AI_THINKING_STRUCT->movesetIndex];
|
||||
ret = AI_TrySwitchOrUseItem(ret);
|
||||
|
||||
// Clear protect structures, some flags may be set during AI calcs
|
||||
// e.g. pranksterElevated from GetMovePriority
|
||||
@ -282,6 +278,48 @@ static u8 ChooseMoveOrAction_Singles(void)
|
||||
return AI_CHOICE_WATCH;
|
||||
|
||||
gActiveBattler = sBattler_AI;
|
||||
|
||||
// If can switch.
|
||||
if (CountUsablePartyMons(sBattler_AI) > 0
|
||||
&& !IsAbilityPreventingEscape(sBattler_AI)
|
||||
&& !(gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
|
||||
&& !(gStatuses3[gActiveBattler] & STATUS3_ROOTED)
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_ARENA | BATTLE_TYPE_PALACE))
|
||||
&& AI_THINKING_STRUCT->aiFlags & (AI_FLAG_CHECK_VIABILITY | AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_PREFER_BATON_PASS))
|
||||
{
|
||||
// Consider switching if all moves are worthless to use.
|
||||
if (GetTotalBaseStat(gBattleMons[sBattler_AI].species) >= 310 // Mon is not weak.
|
||||
&& gBattleMons[sBattler_AI].hp >= gBattleMons[sBattler_AI].maxHP / 2)
|
||||
{
|
||||
s32 cap = AI_THINKING_STRUCT->aiFlags & (AI_FLAG_CHECK_VIABILITY) ? 95 : 93;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (AI_THINKING_STRUCT->score[i] > cap)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAX_MON_MOVES && GetMostSuitableMonToSwitchInto() != PARTY_SIZE)
|
||||
{
|
||||
AI_THINKING_STRUCT->switchMon = TRUE;
|
||||
return AI_CHOICE_SWITCH;
|
||||
}
|
||||
}
|
||||
|
||||
// Consider switching if your mon with truant is bodied by Protect spam.
|
||||
// Or is using a double turn semi invulnerable move(such as Fly) and is faster.
|
||||
if (GetBattlerAbility(sBattler_AI) == ABILITY_TRUANT
|
||||
&& IsTruantMonVulnerable(sBattler_AI, gBattlerTarget)
|
||||
&& gDisableStructs[sBattler_AI].truantCounter
|
||||
&& gBattleMons[sBattler_AI].hp >= gBattleMons[sBattler_AI].maxHP / 2)
|
||||
{
|
||||
if (GetMostSuitableMonToSwitchInto() != PARTY_SIZE)
|
||||
{
|
||||
AI_THINKING_STRUCT->switchMon = TRUE;
|
||||
return AI_CHOICE_SWITCH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
numOfBestMoves = 1;
|
||||
currentMoveArray[0] = AI_THINKING_STRUCT->score[0];
|
||||
consideredMoveArray[0] = 0;
|
||||
|
@ -18,77 +18,8 @@
|
||||
static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng);
|
||||
static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent);
|
||||
static bool8 ShouldUseItem(void);
|
||||
static bool32 AI_ShouldHeal(u8 healAmount);
|
||||
|
||||
// Functions
|
||||
u8 AI_TrySwitchOrUseItem(u8 currAction)
|
||||
{
|
||||
struct Pokemon *party;
|
||||
u8 battlerIn1, battlerIn2;
|
||||
s32 firstId;
|
||||
s32 lastId; // + 1
|
||||
u8 battlerIdentity = GetBattlerPosition(gActiveBattler);
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
|
||||
return currAction;
|
||||
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty; // Player's partner
|
||||
else
|
||||
party = gEnemyParty; // Enemy trainer
|
||||
|
||||
// Switching logic
|
||||
if (ShouldSwitch())
|
||||
{
|
||||
if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE)
|
||||
{
|
||||
s32 monToSwitchId = GetMostSuitableMonToSwitchInto();
|
||||
if (monToSwitchId == PARTY_SIZE)
|
||||
{
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
|
||||
{
|
||||
battlerIn1 = GetBattlerAtPosition(battlerIdentity);
|
||||
battlerIn2 = battlerIn1;
|
||||
}
|
||||
else
|
||||
{
|
||||
battlerIn1 = GetBattlerAtPosition(battlerIdentity);
|
||||
battlerIn2 = GetBattlerAtPosition(battlerIdentity ^ BIT_FLANK);
|
||||
}
|
||||
|
||||
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
||||
|
||||
for (monToSwitchId = firstId; monToSwitchId < lastId; monToSwitchId++)
|
||||
{
|
||||
if (GetMonData(&party[monToSwitchId], MON_DATA_HP) == 0)
|
||||
continue;
|
||||
if (monToSwitchId == gBattlerPartyIndexes[battlerIn1])
|
||||
continue;
|
||||
if (monToSwitchId == gBattlerPartyIndexes[battlerIn2])
|
||||
continue;
|
||||
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
|
||||
continue;
|
||||
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = monToSwitchId;
|
||||
}
|
||||
|
||||
*(gBattleStruct->monToSwitchIntoId + gActiveBattler) = *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler);
|
||||
return AI_CHOICE_SWITCH;
|
||||
}
|
||||
|
||||
// Item Logic
|
||||
if (ShouldUseItem())
|
||||
return AI_CHOICE_USE_ITEM;
|
||||
|
||||
return currAction;
|
||||
}
|
||||
|
||||
void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId)
|
||||
{
|
||||
if (BATTLE_TWO_VS_ONE_OPPONENT && (battlerId & BIT_SIDE) == B_SIDE_OPPONENT)
|
||||
@ -110,52 +41,11 @@ void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId)
|
||||
|
||||
static bool8 ShouldSwitchIfAllBadMoves(void)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (AI_THINKING_STRUCT->aiFlags & (AI_FLAG_CHECK_VIABILITY | AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_PREFER_BATON_PASS))
|
||||
if (gBattleResources->ai->switchMon)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
// TODO double battle bad move switching logic
|
||||
}
|
||||
else
|
||||
{
|
||||
// Single battle. gActiveBattler is the enemy's battler id
|
||||
if (GetTotalBaseStat(gBattleMons[gActiveBattler].species) >= 310 // Mon is not weak.
|
||||
&& gBattleMons[gActiveBattler].hp >= gBattleMons[gActiveBattler].maxHP / 2)
|
||||
{
|
||||
s32 cap = AI_THINKING_STRUCT->aiFlags & (AI_FLAG_CHECK_VIABILITY) ? 95 : 93;
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (AI_THINKING_STRUCT->score[i] > cap)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAX_MON_MOVES && GetMostSuitableMonToSwitchInto() != PARTY_SIZE)
|
||||
{
|
||||
AI_THINKING_STRUCT->switchMon = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Consider switching if your mon with truant is bodied by Protect spam.
|
||||
// Or is using a double turn semi invulnerable move(such as Fly) and is faster.
|
||||
if (GetBattlerAbility(gActiveBattler) == ABILITY_TRUANT
|
||||
&& IsTruantMonVulnerable(gActiveBattler, gBattlerTarget)
|
||||
&& gDisableStructs[gActiveBattler].truantCounter
|
||||
&& gBattleMons[gActiveBattler].hp >= gBattleMons[gActiveBattler].maxHP / 2)
|
||||
{
|
||||
if (GetMostSuitableMonToSwitchInto() != PARTY_SIZE)
|
||||
{
|
||||
AI_THINKING_STRUCT->switchMon = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AI_THINKING_STRUCT->switchMon)
|
||||
{
|
||||
AI_THINKING_STRUCT->switchMon = FALSE;
|
||||
gBattleResources->ai->switchMon = 0;
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
@ -170,6 +60,7 @@ static bool8 ShouldSwitchIfPerishSong(void)
|
||||
&& gDisableStructs[gActiveBattler].perishSongTimer == 0)
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
@ -236,6 +127,7 @@ static bool8 ShouldSwitchIfWonderGuard(void)
|
||||
{
|
||||
// We found a mon.
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = i;
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@ -326,6 +218,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void)
|
||||
{
|
||||
// we found a mon.
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = i;
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@ -345,11 +238,13 @@ static bool8 ShouldSwitchIfNaturalCure(void)
|
||||
if ((gLastLandedMoves[gActiveBattler] == 0 || gLastLandedMoves[gActiveBattler] == 0xFFFF) && Random() & 1)
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
else if (gBattleMoves[gLastLandedMoves[gActiveBattler]].power == 0 && Random() & 1)
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -361,6 +256,7 @@ static bool8 ShouldSwitchIfNaturalCure(void)
|
||||
if (Random() & 1)
|
||||
{
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -541,10 +437,6 @@ bool32 ShouldSwitch(void)
|
||||
return FALSE;
|
||||
|
||||
availableToSwitch = 0;
|
||||
AI_THINKING_STRUCT->switchMon = FALSE;
|
||||
|
||||
if (CountUsablePartyMons(gActiveBattler) == 0) // No pokemon to switch to
|
||||
return FALSE;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
{
|
||||
@ -610,6 +502,74 @@ bool32 ShouldSwitch(void)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void AI_TrySwitchOrUseItem(void)
|
||||
{
|
||||
struct Pokemon *party;
|
||||
u8 battlerIn1, battlerIn2;
|
||||
s32 firstId;
|
||||
s32 lastId; // + 1
|
||||
u8 battlerIdentity = GetBattlerPosition(gActiveBattler);
|
||||
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
party = gEnemyParty;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
{
|
||||
if (ShouldSwitch())
|
||||
{
|
||||
if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE)
|
||||
{
|
||||
s32 monToSwitchId = GetMostSuitableMonToSwitchInto();
|
||||
if (monToSwitchId == PARTY_SIZE)
|
||||
{
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
|
||||
{
|
||||
battlerIn1 = GetBattlerAtPosition(battlerIdentity);
|
||||
battlerIn2 = battlerIn1;
|
||||
}
|
||||
else
|
||||
{
|
||||
battlerIn1 = GetBattlerAtPosition(battlerIdentity);
|
||||
battlerIn2 = GetBattlerAtPosition(battlerIdentity ^ BIT_FLANK);
|
||||
}
|
||||
|
||||
GetAIPartyIndexes(gActiveBattler, &firstId, &lastId);
|
||||
|
||||
for (monToSwitchId = firstId; monToSwitchId < lastId; monToSwitchId++)
|
||||
{
|
||||
if (GetMonData(&party[monToSwitchId], MON_DATA_HP) == 0)
|
||||
continue;
|
||||
if (monToSwitchId == gBattlerPartyIndexes[battlerIn1])
|
||||
continue;
|
||||
if (monToSwitchId == gBattlerPartyIndexes[battlerIn2])
|
||||
continue;
|
||||
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
|
||||
continue;
|
||||
if (monToSwitchId == *(gBattleStruct->monToSwitchIntoId + battlerIn2))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = monToSwitchId;
|
||||
}
|
||||
|
||||
*(gBattleStruct->monToSwitchIntoId + gActiveBattler) = *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler);
|
||||
return;
|
||||
}
|
||||
else if (ShouldUseItem())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// AI has decided it shouldn't switch or use an item, so it will now choose a move to use
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (gActiveBattler ^ BIT_SIDE) << 8);
|
||||
}
|
||||
|
||||
// If there are two(or more) mons to choose from, always choose one that has baton pass
|
||||
// as most often it can't do much on its own.
|
||||
static u32 GetBestMonBatonPass(struct Pokemon *party, int firstId, int lastId, u8 invalidMons, int aliveCount)
|
||||
@ -882,10 +842,21 @@ static bool8 ShouldUseItem(void)
|
||||
switch (*(gBattleStruct->AI_itemType + gActiveBattler / 2))
|
||||
{
|
||||
case AI_ITEM_FULL_RESTORE:
|
||||
shouldUse = AI_ShouldHeal(0);
|
||||
if (gBattleMons[gActiveBattler].hp >= gBattleMons[gActiveBattler].maxHP / 4)
|
||||
break;
|
||||
if (gBattleMons[gActiveBattler].hp == 0)
|
||||
break;
|
||||
shouldUse = TRUE;
|
||||
break;
|
||||
case AI_ITEM_HEAL_HP:
|
||||
shouldUse = AI_ShouldHeal(itemEffects[GetItemEffectParamOffset(item, 4, 4)]);
|
||||
paramOffset = GetItemEffectParamOffset(item, 4, 4);
|
||||
if (paramOffset == 0)
|
||||
break;
|
||||
if (gBattleMons[gActiveBattler].hp == 0)
|
||||
break;
|
||||
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 4
|
||||
|| gBattleMons[gActiveBattler].maxHP - gBattleMons[gActiveBattler].hp > itemEffects[paramOffset])
|
||||
shouldUse = TRUE;
|
||||
break;
|
||||
case AI_ITEM_CURE_CONDITION:
|
||||
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0;
|
||||
@ -967,6 +938,7 @@ static bool8 ShouldUseItem(void)
|
||||
|
||||
if (shouldUse)
|
||||
{
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_ITEM, 0);
|
||||
*(gBattleStruct->chosenItem + (gActiveBattler / 2) * 2) = item;
|
||||
gBattleResources->battleHistory->trainerItems[i] = 0;
|
||||
return shouldUse;
|
||||
@ -975,41 +947,3 @@ static bool8 ShouldUseItem(void)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 AI_ShouldHeal(u8 healAmount)
|
||||
{
|
||||
bool32 shouldHeal = FALSE;
|
||||
u32 i;
|
||||
|
||||
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 4
|
||||
|| gBattleMons[gActiveBattler].hp == 0
|
||||
|| (healAmount != 0 && gBattleMons[gActiveBattler].maxHP - gBattleMons[gActiveBattler].hp > healAmount))
|
||||
{
|
||||
// We have low enough HP to consider healing
|
||||
shouldHeal = TRUE;
|
||||
|
||||
// Check special cases to NOT heal
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (GetBattlerSide(i) == B_SIDE_PLAYER)
|
||||
{
|
||||
if (CanTargetFaintAiWithMod(i, gActiveBattler, healAmount, 0))
|
||||
{
|
||||
// Target is expected to faint us even after we heal. So why bother.
|
||||
shouldHeal = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
// AI_THINKING_STRUCT->movesetIndex is the array index of the AI's chosen move
|
||||
if (CanIndexMoveFaintTarget(gActiveBattler, i, AI_THINKING_STRUCT->movesetIndex, 0) && AI_WhoStrikesFirst(gActiveBattler, i) == AI_IS_FASTER)
|
||||
{
|
||||
// We can faint the target and move first -> don't heal
|
||||
shouldHeal = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shouldHeal;
|
||||
}
|
||||
|
@ -1545,70 +1545,7 @@ static void OpponentHandlePrintSelectionString(void)
|
||||
|
||||
static void OpponentHandleChooseAction(void)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
|
||||
{
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, ChooseMoveAndTargetInBattlePalace());
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 chosenMoveId;
|
||||
struct ChooseMoveStruct moveInfo;
|
||||
|
||||
FillChooseMoveStruct(&moveInfo);
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER))
|
||||
{
|
||||
BattleAI_SetupAIData(0xF);
|
||||
chosenMoveId = BattleAI_ChooseMoveOrAction();
|
||||
switch (chosenMoveId)
|
||||
{
|
||||
case AI_CHOICE_USE_ITEM:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_ITEM, 0);
|
||||
break;
|
||||
case AI_CHOICE_SWITCH:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
break;
|
||||
case AI_CHOICE_WATCH:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SAFARI_WATCH_CAREFULLY, 0);
|
||||
break;
|
||||
case AI_CHOICE_FLEE:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_RUN, 0);
|
||||
break;
|
||||
default:
|
||||
if (gBattleMoves[moveInfo.moves[chosenMoveId]].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
gBattlerTarget = gActiveBattler;
|
||||
if (gBattleMoves[moveInfo.moves[chosenMoveId]].target & MOVE_TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
|
||||
}
|
||||
|
||||
if (CanMegaEvolve(gActiveBattler)) { // If opponent can mega evolve, do it.
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (RET_MEGA_EVOLUTION) | (gBattlerTarget << 8));
|
||||
} else {
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (gBattlerTarget << 8));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // Wild pokemon - use random move
|
||||
{
|
||||
u16 move;
|
||||
do
|
||||
{
|
||||
chosenMoveId = Random() & 3;
|
||||
move = moveInfo.moves[chosenMoveId];
|
||||
} while (move == MOVE_NONE);
|
||||
|
||||
if (gBattleMoves[move].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (gActiveBattler << 8));
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (GetBattlerAtPosition(Random() & 2) << 8));
|
||||
else
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) << 8));
|
||||
}
|
||||
}
|
||||
|
||||
AI_TrySwitchOrUseItem(); // TODO consider move choice first
|
||||
OpponentBufferExecCompleted();
|
||||
}
|
||||
|
||||
@ -1619,9 +1556,74 @@ static void OpponentHandleYesNoBox(void)
|
||||
|
||||
static void OpponentHandleChooseMove(void)
|
||||
{
|
||||
u8 *bufferB = gBattleResources->bufferB[gActiveBattler];
|
||||
BtlController_EmitTwoReturnValues(1, 10, bufferB[2] | (bufferB[3] << 8));
|
||||
OpponentBufferExecCompleted();
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
|
||||
{
|
||||
BtlController_EmitTwoReturnValues(1, 10, ChooseMoveAndTargetInBattlePalace());
|
||||
OpponentBufferExecCompleted();
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 chosenMoveId;
|
||||
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]);
|
||||
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER))
|
||||
{
|
||||
BattleAI_SetupAIData(0xF);
|
||||
chosenMoveId = BattleAI_ChooseMoveOrAction();
|
||||
|
||||
switch (chosenMoveId)
|
||||
{
|
||||
case AI_CHOICE_WATCH:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SAFARI_WATCH_CAREFULLY, 0);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
gBattlerTarget = gActiveBattler;
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
|
||||
}
|
||||
|
||||
// If opponent can mega evolve, do it.
|
||||
if (CanMegaEvolve(gActiveBattler))
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (RET_MEGA_EVOLUTION) | (gBattlerTarget << 8));
|
||||
else
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gBattlerTarget << 8));
|
||||
break;
|
||||
}
|
||||
|
||||
OpponentBufferExecCompleted();
|
||||
}
|
||||
else // Wild pokemon - use random move
|
||||
{
|
||||
u16 move;
|
||||
do
|
||||
{
|
||||
chosenMoveId = Random() & 3;
|
||||
move = moveInfo->moves[chosenMoveId];
|
||||
} while (move == MOVE_NONE);
|
||||
|
||||
if (gBattleMoves[move].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER))
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gActiveBattler << 8));
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (GetBattlerAtPosition(Random() & 2) << 8));
|
||||
else
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) << 8));
|
||||
|
||||
OpponentBufferExecCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void OpponentHandleChooseItem(void)
|
||||
|
@ -1509,37 +1509,7 @@ static void PlayerPartnerHandlePrintSelectionString(void)
|
||||
|
||||
static void PlayerPartnerHandleChooseAction(void)
|
||||
{
|
||||
u8 chosenMoveId;
|
||||
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]);
|
||||
|
||||
BattleAI_SetupAIData(0xF);
|
||||
chosenMoveId = BattleAI_ChooseMoveOrAction();
|
||||
|
||||
switch (chosenMoveId)
|
||||
{
|
||||
case AI_CHOICE_USE_ITEM:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_ITEM, 0);
|
||||
break;
|
||||
case AI_CHOICE_SWITCH:
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
|
||||
break;
|
||||
default:
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED))
|
||||
gBattlerTarget = gActiveBattler;
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
}
|
||||
|
||||
if (CanMegaEvolve(gActiveBattler)) // If partner can mega evolve, do it.
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (RET_MEGA_EVOLUTION) | (gBattlerTarget << 8));
|
||||
else
|
||||
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (chosenMoveId) | (gBattlerTarget << 8));
|
||||
break;
|
||||
}
|
||||
|
||||
AI_TrySwitchOrUseItem();
|
||||
PlayerPartnerBufferExecCompleted();
|
||||
}
|
||||
|
||||
@ -1550,6 +1520,26 @@ static void PlayerPartnerHandleYesNoBox(void)
|
||||
|
||||
static void PlayerPartnerHandleChooseMove(void)
|
||||
{
|
||||
u8 chosenMoveId;
|
||||
struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]);
|
||||
|
||||
BattleAI_SetupAIData(0xF);
|
||||
chosenMoveId = BattleAI_ChooseMoveOrAction();
|
||||
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED))
|
||||
gBattlerTarget = gActiveBattler;
|
||||
if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH)
|
||||
{
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
}
|
||||
|
||||
if (CanMegaEvolve(gActiveBattler)) // If partner can mega evolve, do it.
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (RET_MEGA_EVOLUTION) | (gBattlerTarget << 8));
|
||||
else
|
||||
BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gBattlerTarget << 8));
|
||||
|
||||
PlayerPartnerBufferExecCompleted();
|
||||
}
|
||||
|
||||
|
@ -3877,7 +3877,22 @@ static void HandleTurnActionSelectionState(void)
|
||||
{
|
||||
struct ChooseMoveStruct moveInfo;
|
||||
|
||||
FillChooseMoveStruct(&moveInfo);
|
||||
moveInfo.mega = gBattleStruct->mega;
|
||||
moveInfo.species = gBattleMons[gActiveBattler].species;
|
||||
moveInfo.monType1 = gBattleMons[gActiveBattler].type1;
|
||||
moveInfo.monType2 = gBattleMons[gActiveBattler].type2;
|
||||
moveInfo.monType3 = gBattleMons[gActiveBattler].type3;
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
moveInfo.moves[i] = gBattleMons[gActiveBattler].moves[i];
|
||||
moveInfo.currentPp[i] = gBattleMons[gActiveBattler].pp[i];
|
||||
moveInfo.maxPp[i] = CalculatePPWithBonus(
|
||||
gBattleMons[gActiveBattler].moves[i],
|
||||
gBattleMons[gActiveBattler].ppBonuses,
|
||||
i);
|
||||
}
|
||||
|
||||
BtlController_EmitChooseMove(0, (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) != 0, FALSE, &moveInfo);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
@ -5302,24 +5317,3 @@ void SetTotemBoost(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FillChooseMoveStruct(struct ChooseMoveStruct * moveInfo)
|
||||
{
|
||||
int i;
|
||||
|
||||
moveInfo->mega = gBattleStruct->mega;
|
||||
moveInfo->species = gBattleMons[gActiveBattler].species;
|
||||
moveInfo->monType1 = gBattleMons[gActiveBattler].type1;
|
||||
moveInfo->monType2 = gBattleMons[gActiveBattler].type2;
|
||||
moveInfo->monType3 = gBattleMons[gActiveBattler].type3;
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
moveInfo->moves[i] = gBattleMons[gActiveBattler].moves[i];
|
||||
moveInfo->currentPp[i] = gBattleMons[gActiveBattler].pp[i];
|
||||
moveInfo->maxPp[i] = CalculatePPWithBonus(
|
||||
gBattleMons[gActiveBattler].moves[i],
|
||||
gBattleMons[gActiveBattler].ppBonuses,
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user