From d0bb03e5a9998a30feebedd2d49860631f8e6d1e Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Fri, 21 Jun 2024 12:17:12 +0200 Subject: [PATCH] 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 --- data/battle_scripts_1.s | 18 +++++++++--------- include/constants/battle_script_commands.h | 4 ++-- src/battle_script_commands.c | 20 +++++++++++++------- src/battle_util.c | 4 ++-- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 33b3095953..32015580b8 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -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:: diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 6fdbcc9e96..10e7dfea51 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -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 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0d57f6e3be..2aa68b896d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -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; diff --git a/src/battle_util.c b/src/battle_util.c index 300cad8630..7c8690ff01 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -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: