Fix AI's right slot switching-in too early (#4851)

* apply safe switching to trainer doubles battles - with a config

* get rid of the config

* make it compile
This commit is contained in:
DizzyEggg 2024-06-21 12:17:12 +02:00 committed by GitHub
parent c31f982a7b
commit d0bb03e5a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 26 additions and 20 deletions

View file

@ -5407,7 +5407,7 @@ BattleScript_GiveExp::
BattleScript_HandleFaintedMon::
setbyte sSHIFT_SWITCHED, 0
checkteamslost BattleScript_LinkHandleFaintedMonMultiple
checkteamslost BattleScript_HandleFaintedMonMultiple
jumpifbyte CMP_NOT_EQUAL, gBattleOutcome, 0, BattleScript_FaintedMonEnd
jumpifbattletype BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE, BattleScript_FaintedMonTryChoose
jumpifword CMP_NO_COMMON_BITS, gHitMarker, HITMARKER_PLAYER_FAINTED, BattleScript_FaintedMonTryChoose
@ -5488,13 +5488,13 @@ BattleScript_FaintedMonShiftSwitched:
copybyte gBattlerTarget, sSAVED_BATTLER
goto BattleScript_FaintedMonSendOutNewEnd
BattleScript_LinkHandleFaintedMonMultiple::
openpartyscreen BS_FAINTED_LINK_MULTIPLE_1, BattleScript_LinkHandleFaintedMonMultipleStart
BattleScript_LinkHandleFaintedMonMultipleStart::
BattleScript_HandleFaintedMonMultiple::
openpartyscreen BS_FAINTED_MULTIPLE_1, BattleScript_HandleFaintedMonMultipleStart
BattleScript_HandleFaintedMonMultipleStart::
switchhandleorder BS_FAINTED, 0
openpartyscreen BS_FAINTED_LINK_MULTIPLE_2, BattleScript_LinkHandleFaintedMonMultipleEnd
openpartyscreen BS_FAINTED_MULTIPLE_2, BattleScript_HandleFaintedMonMultipleEnd
switchhandleorder BS_FAINTED, 0
BattleScript_LinkHandleFaintedMonLoop::
BattleScript_HandleFaintedMonLoop::
switchhandleorder BS_FAINTED, 3
drawpartystatussummary BS_FAINTED
getswitchedmondata BS_FAINTED
@ -5506,9 +5506,9 @@ BattleScript_LinkHandleFaintedMonLoop::
hidepartystatussummary BS_FAINTED
switchinanim BS_FAINTED, FALSE
waitstate
switchineffects BS_FAINTED_LINK_MULTIPLE_1
jumpifbytenotequal gBattlerFainted, gBattlersCount, BattleScript_LinkHandleFaintedMonLoop
BattleScript_LinkHandleFaintedMonMultipleEnd::
switchineffects BS_FAINTED_MULTIPLE_1
jumpifbytenotequal gBattlerFainted, gBattlersCount, BattleScript_HandleFaintedMonLoop
BattleScript_HandleFaintedMonMultipleEnd::
end2
BattleScript_LocalTrainerBattleWon::

View file

@ -63,8 +63,8 @@
#define BS_EFFECT_BATTLER 2
#define BS_FAINTED 3
#define BS_ATTACKER_WITH_PARTNER 4 // for Cmd_updatestatusicon
#define BS_FAINTED_LINK_MULTIPLE_1 5 // for openpartyscreen
#define BS_FAINTED_LINK_MULTIPLE_2 6 // for openpartyscreen
#define BS_FAINTED_MULTIPLE_1 5 // for openpartyscreen
#define BS_FAINTED_MULTIPLE_2 6 // for openpartyscreen
#define BS_BATTLER_0 7
#define BS_ATTACKER_SIDE 8 // for Cmd_jumpifability
#define BS_TARGET_SIDE 9 // for Cmd_jumpifability

View file

@ -4633,7 +4633,7 @@ bool32 NoAliveMonsForEitherParty(void)
return (NoAliveMonsForPlayer() || NoAliveMonsForOpponent());
}
// For battles that aren't BATTLE_TYPE_LINK or BATTLE_TYPE_RECORDED_LINK, the only thing this
// For battles that aren't BATTLE_TYPE_LINK or BATTLE_TYPE_RECORDED_LINK or double trainer battles, the only thing this
// command does is check whether the player has won/lost by totaling each team's HP. It then
// sets gBattleOutcome accordingly, if necessary.
static void Cmd_checkteamslost(void)
@ -4649,10 +4649,16 @@ static void Cmd_checkteamslost(void)
if (NoAliveMonsForOpponent())
gBattleOutcome |= B_OUTCOME_WON;
// For link battles that haven't ended, count number of empty battler spots
// In link multi battles, jump to pointer if more than 1 spot empty
// Fair switching - everyone has to switch in most at the same time, without knowing which pokemon the other trainer selected.
// In vanilla Emerald this was only used for link battles, in expansion it's also used for regular trainers in double battles.
// For battles that haven't ended, count number of empty battler spots
// In multi battles, jump to pointer if more than 1 spot empty
// In non-multi battles, jump to pointer if 1 spot is missing on both sides
if (gBattleOutcome == 0 && (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)))
if (gBattleOutcome == 0
&& (((gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)))
|| ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
)
)
{
s32 i, emptyPlayerSpots, emptyOpponentSpots;
@ -6769,7 +6775,7 @@ static void Cmd_openpartyscreen(void)
u32 i, battler = 0;
const u8 *failInstr = cmd->failInstr;
if (cmd->battler == BS_FAINTED_LINK_MULTIPLE_1)
if (cmd->battler == BS_FAINTED_MULTIPLE_1)
{
if ((gBattleTypeFlags & BATTLE_TYPE_MULTI) || !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
{
@ -6924,7 +6930,7 @@ static void Cmd_openpartyscreen(void)
}
gBattlescriptCurrInstr = cmd->nextInstr;
}
else if (cmd->battler == BS_FAINTED_LINK_MULTIPLE_2)
else if (cmd->battler == BS_FAINTED_MULTIPLE_2)
{
if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
{
@ -7307,7 +7313,7 @@ static void Cmd_switchineffects(void)
gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp;
}
if (cmd->battler == BS_FAINTED_LINK_MULTIPLE_1)
if (cmd->battler == BS_FAINTED_MULTIPLE_1)
{
u32 hitmarkerFaintBits = gHitMarker >> 28;

View file

@ -958,11 +958,11 @@ u8 GetBattlerForBattleScript(u8 caseId)
case BS_FAINTED:
ret = gBattlerFainted;
break;
case BS_FAINTED_LINK_MULTIPLE_1:
case BS_FAINTED_MULTIPLE_1:
ret = gBattlerFainted;
break;
case BS_ATTACKER_WITH_PARTNER:
case BS_FAINTED_LINK_MULTIPLE_2:
case BS_FAINTED_MULTIPLE_2:
case BS_ATTACKER_SIDE:
case BS_TARGET_SIDE:
case BS_PLAYER1: