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

View file

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

View file

@ -4633,7 +4633,7 @@ bool32 NoAliveMonsForEitherParty(void)
return (NoAliveMonsForPlayer() || NoAliveMonsForOpponent()); 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 // command does is check whether the player has won/lost by totaling each team's HP. It then
// sets gBattleOutcome accordingly, if necessary. // sets gBattleOutcome accordingly, if necessary.
static void Cmd_checkteamslost(void) static void Cmd_checkteamslost(void)
@ -4649,10 +4649,16 @@ static void Cmd_checkteamslost(void)
if (NoAliveMonsForOpponent()) if (NoAliveMonsForOpponent())
gBattleOutcome |= B_OUTCOME_WON; gBattleOutcome |= B_OUTCOME_WON;
// For link battles that haven't ended, count number of empty battler spots // Fair switching - everyone has to switch in most at the same time, without knowing which pokemon the other trainer selected.
// In link multi battles, jump to pointer if more than 1 spot empty // 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 // 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; s32 i, emptyPlayerSpots, emptyOpponentSpots;
@ -6769,7 +6775,7 @@ static void Cmd_openpartyscreen(void)
u32 i, battler = 0; u32 i, battler = 0;
const u8 *failInstr = cmd->failInstr; 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)) if ((gBattleTypeFlags & BATTLE_TYPE_MULTI) || !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
{ {
@ -6924,7 +6930,7 @@ static void Cmd_openpartyscreen(void)
} }
gBattlescriptCurrInstr = cmd->nextInstr; 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)) if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
{ {
@ -7307,7 +7313,7 @@ static void Cmd_switchineffects(void)
gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp; 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; u32 hitmarkerFaintBits = gHitMarker >> 28;

View file

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