Prevent double Dynamax for single-trainer 2v1 multi battles (#8323)
Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
This commit is contained in:
parent
6daab57bd5
commit
bcf90b71a7
@ -640,6 +640,7 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData)
|
||||
u32 battlerAtk, battlersCount, weather;
|
||||
|
||||
memset(aiData, 0, sizeof(struct AiLogicData));
|
||||
gAiBattleData->aiUsingGimmick = 0;
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_HAS_AI) && !IsWildMonSmart())
|
||||
return;
|
||||
|
||||
|
||||
@ -1351,6 +1351,7 @@ void AI_TrySwitchOrUseItem(u32 battler)
|
||||
if (gAiLogicData->shouldSwitch & (1u << battler) && IsSwitchinValid(battler))
|
||||
{
|
||||
BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_SWITCH, 0);
|
||||
SetAIUsingGimmick(battler, NO_GIMMICK);
|
||||
if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE)
|
||||
{
|
||||
s32 monToSwitchId = gAiLogicData->mostSuitableMonId[battler];
|
||||
@ -1397,6 +1398,7 @@ void AI_TrySwitchOrUseItem(u32 battler)
|
||||
}
|
||||
else if (ShouldUseItem(battler))
|
||||
{
|
||||
SetAIUsingGimmick(battler, NO_GIMMICK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -462,12 +462,15 @@ static void OpponentHandleChooseMove(u32 battler)
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
|
||||
}
|
||||
// If opponent can and should use a gimmick (considering trainer data), do it
|
||||
if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE && IsAIUsingGimmick(battler))
|
||||
enum Gimmick usableGimmick = gBattleStruct->gimmick.usableGimmick[battler];
|
||||
if (usableGimmick != GIMMICK_NONE && IsAIUsingGimmick(battler) && !HasTrainerUsedGimmick(battler, usableGimmick))
|
||||
{
|
||||
gBattleStruct->gimmick.toActivate |= 1u << battler;
|
||||
BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (RET_GIMMICK) | (gBattlerTarget << 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAIUsingGimmick(battler, NO_GIMMICK);
|
||||
BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (gBattlerTarget << 8));
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,12 +269,15 @@ static void PlayerPartnerHandleChooseMove(u32 battler)
|
||||
gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
}
|
||||
// If partner can and should use a gimmick (considering trainer data), do it
|
||||
if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE && IsAIUsingGimmick(battler))
|
||||
enum Gimmick usableGimmick = gBattleStruct->gimmick.usableGimmick[battler];
|
||||
if (usableGimmick != GIMMICK_NONE && IsAIUsingGimmick(battler) && !HasTrainerUsedGimmick(battler, usableGimmick))
|
||||
{
|
||||
gBattleStruct->gimmick.toActivate |= 1u << battler;
|
||||
BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (RET_GIMMICK) | (gBattlerTarget << 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAIUsingGimmick(battler, NO_GIMMICK);
|
||||
BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (gBattlerTarget << 8));
|
||||
}
|
||||
|
||||
|
||||
@ -91,20 +91,15 @@ bool32 ShouldTrainerBattlerUseGimmick(u32 battler, enum Gimmick gimmick)
|
||||
// Returns whether a trainer has used a gimmick during a battle.
|
||||
bool32 HasTrainerUsedGimmick(u32 battler, enum Gimmick gimmick)
|
||||
{
|
||||
// Check whether partner battler has used gimmick or plans to during turn.
|
||||
if (IsDoubleBattle()
|
||||
&& IsPartnerMonFromSameTrainer(battler)
|
||||
&& (gBattleStruct->gimmick.activated[BATTLE_PARTNER(battler)][gimmick]
|
||||
|| ((gBattleStruct->gimmick.toActivate & (1u << BATTLE_PARTNER(battler))
|
||||
&& gBattleStruct->gimmick.usableGimmick[BATTLE_PARTNER(battler)] == gimmick))))
|
||||
if (IsDoubleBattle() && IsPartnerMonFromSameTrainer(battler))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
// Otherwise, return whether current battler has used gimmick.
|
||||
else
|
||||
{
|
||||
return gBattleStruct->gimmick.activated[battler][gimmick];
|
||||
u32 partner = BATTLE_PARTNER(battler);
|
||||
if (gBattleStruct->gimmick.activated[partner][gimmick]
|
||||
|| ((gBattleStruct->gimmick.toActivate & (1u << partner)) && gBattleStruct->gimmick.usableGimmick[partner] == gimmick))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return gBattleStruct->gimmick.activated[battler][gimmick];
|
||||
}
|
||||
|
||||
// Sets a gimmick as used by a trainer with checks for Multi Battles.
|
||||
|
||||
@ -8938,14 +8938,10 @@ s32 GetStealthHazardDamage(enum TypeSideHazard hazardType, u32 battler)
|
||||
|
||||
bool32 IsPartnerMonFromSameTrainer(u32 battler)
|
||||
{
|
||||
if (!IsOnPlayerSide(battler) && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
|
||||
return FALSE;
|
||||
else if (IsOnPlayerSide(battler) && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||
return FALSE;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
|
||||
return FALSE;
|
||||
if (!IsOnPlayerSide(battler))
|
||||
return !(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS);
|
||||
else
|
||||
return TRUE;
|
||||
return !(gBattleTypeFlags & BATTLE_TYPE_MULTI);
|
||||
}
|
||||
|
||||
bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId)
|
||||
|
||||
@ -37,5 +37,29 @@ AI_SINGLE_BATTLE_TEST("AI uses Dynamax -- AI does not dynamax before using a uti
|
||||
}
|
||||
}
|
||||
|
||||
AI_TWO_VS_ONE_BATTLE_TEST("AI only Dynamaxes once per trainer in 2v1 multi battles")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
|
||||
MULTI_PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH); }
|
||||
MULTI_PARTNER(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH); }
|
||||
MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH); DynamaxLevel(10); }
|
||||
MULTI_OPPONENT_A(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH); DynamaxLevel(10); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(playerLeft, MOVE_SPLASH);
|
||||
MOVE(playerRight, MOVE_SPLASH);
|
||||
EXPECT_MOVE(opponentLeft, MOVE_SPLASH, gimmick: GIMMICK_DYNAMAX);
|
||||
EXPECT_MOVE(opponentRight, MOVE_SPLASH, gimmick: GIMMICK_NONE);
|
||||
}
|
||||
TURN {
|
||||
MOVE(playerLeft, MOVE_SPLASH);
|
||||
MOVE(playerRight, MOVE_SPLASH);
|
||||
EXPECT_MOVE(opponentLeft, MOVE_SPLASH, gimmick: GIMMICK_NONE);
|
||||
EXPECT_MOVE(opponentRight, MOVE_SPLASH, gimmick: GIMMICK_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copycatting an ally's Max Guard rendition of Trick Room was a notable strategy.
|
||||
TO_DO_BATTLE_TEST("TODO: AI uses Dynamax -- AI uses Copycat against a Dynamaxed Pokemon intelligently")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user