revert ai item usage code

This commit is contained in:
ghoulslash 2021-11-28 13:12:56 -05:00
parent 3ac480076c
commit d108f77aa4
8 changed files with 243 additions and 289 deletions

View File

@ -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) \
{ \

View File

@ -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);

View File

@ -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];

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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();
}

View File

@ -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);
}
}