#include "global.h" #include "battle.h" #include "battle_ai_main.h" #include "battle_anim.h" #include "battle_controllers.h" #include "battle_interface.h" #include "battle_message.h" #include "battle_setup.h" #include "battle_tower.h" #include "battle_tv.h" #include "bg.h" #include "data.h" #include "item_menu.h" #include "item_use.h" #include "link.h" #include "main.h" #include "m4a.h" #include "palette.h" #include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "recorded_battle.h" #include "reshow_battle_screen.h" #include "sound.h" #include "string_util.h" #include "task.h" #include "test_runner.h" #include "text.h" #include "util.h" #include "window.h" #include "constants/battle_anim.h" #include "constants/songs.h" #include "constants/trainers.h" static void RecordedOpponentHandleLoadMonSprite(u32 battler); static void RecordedOpponentHandleSwitchInAnim(u32 battler); static void RecordedOpponentHandleDrawTrainerPic(u32 battler); static void RecordedOpponentHandleTrainerSlideBack(u32 battler); static void RecordedOpponentHandleMoveAnimation(u32 battler); static void RecordedOpponentHandlePrintString(u32 battler); static void RecordedOpponentHandleChooseAction(u32 battler); static void RecordedOpponentHandleChooseMove(u32 battler); static void RecordedOpponentHandleChooseItem(u32 battler); static void RecordedOpponentHandleChoosePokemon(u32 battler); static void RecordedOpponentHandleHealthBarUpdate(u32 battler); static void RecordedOpponentHandleStatusIconUpdate(u32 battler); static void RecordedOpponentHandleStatusAnimation(u32 battler); static void RecordedOpponentHandleIntroTrainerBallThrow(u32 battler); static void RecordedOpponentHandleDrawPartyStatusSummary(u32 battler); static void RecordedOpponentHandleBattleAnimation(u32 battler); static void RecordedOpponentHandleEndLinkBattle(u32 battler); static void RecordedOpponentBufferRunCommand(u32 battler); static void RecordedOpponentBufferExecCompleted(u32 battler); static void SwitchIn_HandleSoundAndEnd(u32 battler); static void (*const sRecordedOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { [CONTROLLER_GETMONDATA] = BtlController_HandleGetMonData, [CONTROLLER_GETRAWMONDATA] = BtlController_Empty, [CONTROLLER_SETMONDATA] = BtlController_HandleSetMonData, [CONTROLLER_SETRAWMONDATA] = BtlController_HandleSetRawMonData, [CONTROLLER_LOADMONSPRITE] = RecordedOpponentHandleLoadMonSprite, [CONTROLLER_SWITCHINANIM] = RecordedOpponentHandleSwitchInAnim, [CONTROLLER_RETURNMONTOBALL] = BtlController_HandleReturnMonToBall, [CONTROLLER_DRAWTRAINERPIC] = RecordedOpponentHandleDrawTrainerPic, [CONTROLLER_TRAINERSLIDE] = OpponentHandleTrainerSlide, [CONTROLLER_TRAINERSLIDEBACK] = RecordedOpponentHandleTrainerSlideBack, [CONTROLLER_FAINTANIMATION] = BtlController_HandleFaintAnimation, [CONTROLLER_PALETTEFADE] = BtlController_Empty, [CONTROLLER_SUCCESSBALLTHROWANIM] = BtlController_Empty, [CONTROLLER_BALLTHROWANIM] = BtlController_Empty, [CONTROLLER_PAUSE] = BtlController_Empty, [CONTROLLER_MOVEANIMATION] = RecordedOpponentHandleMoveAnimation, [CONTROLLER_PRINTSTRING] = RecordedOpponentHandlePrintString, [CONTROLLER_PRINTSTRINGPLAYERONLY] = BtlController_Empty, [CONTROLLER_CHOOSEACTION] = RecordedOpponentHandleChooseAction, [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = RecordedOpponentHandleChooseMove, [CONTROLLER_OPENBAG] = RecordedOpponentHandleChooseItem, [CONTROLLER_CHOOSEPOKEMON] = RecordedOpponentHandleChoosePokemon, [CONTROLLER_23] = BtlController_Empty, [CONTROLLER_HEALTHBARUPDATE] = RecordedOpponentHandleHealthBarUpdate, [CONTROLLER_EXPUPDATE] = BtlController_Empty, [CONTROLLER_STATUSICONUPDATE] = RecordedOpponentHandleStatusIconUpdate, [CONTROLLER_STATUSANIMATION] = RecordedOpponentHandleStatusAnimation, [CONTROLLER_STATUSXOR] = BtlController_Empty, [CONTROLLER_DATATRANSFER] = BtlController_Empty, [CONTROLLER_DMA3TRANSFER] = BtlController_Empty, [CONTROLLER_PLAYBGM] = BtlController_Empty, [CONTROLLER_32] = BtlController_Empty, [CONTROLLER_TWORETURNVALUES] = BtlController_Empty, [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, [CONTROLLER_PLAYFANFAREORBGM] = BtlController_HandlePlayFanfareOrBGM, [CONTROLLER_FAINTINGCRY] = BtlController_HandleFaintingCry, [CONTROLLER_INTROSLIDE] = BtlController_HandleIntroSlide, [CONTROLLER_INTROTRAINERBALLTHROW] = RecordedOpponentHandleIntroTrainerBallThrow, [CONTROLLER_DRAWPARTYSTATUSSUMMARY] = RecordedOpponentHandleDrawPartyStatusSummary, [CONTROLLER_HIDEPARTYSTATUSSUMMARY] = BtlController_HandleHidePartyStatusSummary, [CONTROLLER_ENDBOUNCE] = BtlController_Empty, [CONTROLLER_SPRITEINVISIBILITY] = BtlController_HandleSpriteInvisibility, [CONTROLLER_BATTLEANIMATION] = RecordedOpponentHandleBattleAnimation, [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, [CONTROLLER_ENDLINKBATTLE] = RecordedOpponentHandleEndLinkBattle, [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop }; void SetControllerToRecordedOpponent(u32 battler) { gBattlerControllerEndFuncs[battler] = RecordedOpponentBufferExecCompleted; gBattlerControllerFuncs[battler] = RecordedOpponentBufferRunCommand; } static void RecordedOpponentBufferRunCommand(u32 battler) { if (gBattleControllerExecFlags & (1u << battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedOpponentBufferCommands)) sRecordedOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); else RecordedOpponentBufferExecCompleted(battler); } } static void RecordedOpponentBufferExecCompleted(u32 battler) { gBattlerControllerFuncs[battler] = RecordedOpponentBufferRunCommand; if (gBattleTypeFlags & BATTLE_TYPE_LINK) { u8 playerId = GetMultiplayerId(); PrepareBufferDataTransferLink(battler, 2, 4, &playerId); gBattleResources->bufferA[battler][0] = CONTROLLER_TERMINATOR_NOP; } else { gBattleControllerExecFlags &= ~(1u << battler); } } static void Intro_DelayAndEnd(u32 battler) { if (--gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay == (u8)-1) { gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay = 0; RecordedOpponentBufferExecCompleted(battler); } } static void Intro_WaitForShinyAnimAndHealthbox(u32 battler) { bool8 healthboxAnimDone = FALSE; if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) { if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[battler]].animEnded) healthboxAnimDone = TRUE; } else { if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy && gSprites[gHealthboxSpriteIds[BATTLE_PARTNER(battler)]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[battler]].animEnded && gSprites[gBattlerSpriteIds[BATTLE_PARTNER(battler)]].animEnded) healthboxAnimDone = TRUE; } if (healthboxAnimDone) { if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) return; if (!gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim) return; gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].finishedShinyMonAnim = FALSE; FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); } gBattleSpritesDataPtr->healthBoxesData[battler].introEndDelay = 3; gBattlerControllerFuncs[battler] = Intro_DelayAndEnd; } } static void TrySetBattlerShadowSpriteCallback(u32 battler) { if (gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary].callback == SpriteCallbackDummy) { if (B_ENEMY_MON_SHADOW_STYLE <= GEN_3 || P_GBA_STYLE_SPECIES_GFX == TRUE || gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdSecondary].callback == SpriteCallbackDummy) { SetBattlerShadowSpriteCallback(battler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES)); } } } static void Intro_TryShinyAnimShowHealthbox(u32 battler) { bool32 bgmRestored = FALSE; bool32 battlerAnimsDone = FALSE; if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive) TryShinyAnimation(battler, &gEnemyParty[gBattlerPartyIndexes[battler]]); if (!gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].ballAnimActive) TryShinyAnimation(BATTLE_PARTNER(battler), &gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]]); if (!gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].ballAnimActive) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].healthboxSlideInStarted) { if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { UpdateHealthboxAttribute(gHealthboxSpriteIds[BATTLE_PARTNER(battler)], &gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]], HEALTHBOX_ALL); StartHealthboxSlideIn(BATTLE_PARTNER(battler)); SetHealthboxSpriteVisible(gHealthboxSpriteIds[BATTLE_PARTNER(battler)]); } UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gEnemyParty[gBattlerPartyIndexes[battler]], HEALTHBOX_ALL); StartHealthboxSlideIn(battler); SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]); } gBattleSpritesDataPtr->healthBoxesData[battler].healthboxSlideInStarted = TRUE; } if (!gBattleSpritesDataPtr->healthBoxesData[battler].waitForCry && gBattleSpritesDataPtr->healthBoxesData[battler].healthboxSlideInStarted && !gBattleSpritesDataPtr->healthBoxesData[BATTLE_PARTNER(battler)].waitForCry && !IsCryPlayingOrClearCrySongs()) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].bgmRestored) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK) { if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT) m4aMPlayContinue(&gMPlayInfo_BGM); } else { m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); } } gBattleSpritesDataPtr->healthBoxesData[battler].bgmRestored = TRUE; bgmRestored = TRUE; } if (!IsDoubleBattle()) { if (gSprites[gBattleControllerData[battler]].callback == SpriteCallbackDummy) { TrySetBattlerShadowSpriteCallback(battler); if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy) battlerAnimsDone = TRUE; } } else { if (gSprites[gBattleControllerData[battler]].callback == SpriteCallbackDummy && gSprites[gBattleControllerData[BATTLE_PARTNER(battler)]].callback == SpriteCallbackDummy) { TrySetBattlerShadowSpriteCallback(battler); TrySetBattlerShadowSpriteCallback(BATTLE_PARTNER(battler)); if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[BATTLE_PARTNER(battler)]].callback == SpriteCallbackDummy) { battlerAnimsDone = TRUE; } } } if (bgmRestored && battlerAnimsDone) { if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) DestroySprite(&gSprites[gBattleControllerData[BATTLE_PARTNER(battler)]]); DestroySprite(&gSprites[gBattleControllerData[battler]]); gBattleSpritesDataPtr->animationData->introAnimActive = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].bgmRestored = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].healthboxSlideInStarted = FALSE; gBattlerControllerFuncs[battler] = Intro_WaitForShinyAnimAndHealthbox; } } static void TryShinyAnimAfterMonAnim(u32 battler) { if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[battler]].x2 == 0) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim) { TryShinyAnimation(battler, &gEnemyParty[gBattlerPartyIndexes[battler]]); } else { if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) { gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); RecordedOpponentBufferExecCompleted(battler); } } } } static void SwitchIn_ShowSubstitute(u32 battler) { if (gSprites[gHealthboxSpriteIds[battler]].callback == SpriteCallbackDummy) { if (gBattleSpritesDataPtr->battlerData[battler].behindSubstitute) InitAndLaunchSpecialAnimation(battler, battler, battler, B_ANIM_MON_TO_SUBSTITUTE); gBattlerControllerFuncs[battler] = SwitchIn_HandleSoundAndEnd; } } static void SwitchIn_HandleSoundAndEnd(u32 battler) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].specialAnimActive && !IsCryPlayingOrClearCrySongs()) { if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy || gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy_2) { m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); RecordedOpponentBufferExecCompleted(battler); } } } static void SwitchIn_ShowHealthbox(u32 battler) { if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim && gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy) { gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; FreeSpriteTilesByTag(ANIM_TAG_GOLD_STARS); FreeSpritePaletteByTag(ANIM_TAG_GOLD_STARS); StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], 0); UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gEnemyParty[gBattlerPartyIndexes[battler]], HEALTHBOX_ALL); StartHealthboxSlideIn(battler); SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]); CopyBattleSpriteInvisibility(battler); gBattlerControllerFuncs[battler] = SwitchIn_ShowSubstitute; } } static void SwitchIn_TryShinyAnim(u32 battler) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim) TryShinyAnimation(battler, &gEnemyParty[gBattlerPartyIndexes[battler]]); if (gSprites[gBattleControllerData[battler]].callback == SpriteCallbackDummy && !gBattleSpritesDataPtr->healthBoxesData[battler].ballAnimActive) { DestroySprite(&gSprites[gBattleControllerData[battler]]); SetBattlerShadowSpriteCallback(battler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES)); gBattlerControllerFuncs[battler] = SwitchIn_ShowHealthbox; } } static void RecordedOpponentHandleLoadMonSprite(u32 battler) { BtlController_HandleLoadMonSprite(battler, TryShinyAnimAfterMonAnim); } static void RecordedOpponentHandleSwitchInAnim(u32 battler) { BtlController_HandleSwitchInAnim(battler, FALSE, SwitchIn_TryShinyAnim); } static void RecordedOpponentHandleDrawTrainerPic(u32 battler) { s16 xPos; u32 trainerPicId; if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { if ((GetBattlerPosition(battler) & BIT_FLANK) != 0) // second mon xPos = 152; else // first mon xPos = 200; if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) { if (battler == B_POSITION_OPPONENT_LEFT) trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.opponentA); else trainerPicId = GetFrontierTrainerFrontSpriteId(TRAINER_BATTLE_PARAM.opponentB); } else { trainerPicId = PlayerGenderToFrontTrainerPicId(GetBattlerLinkPlayerGender(battler)); } } else { xPos = 176; if (TRAINER_BATTLE_PARAM.opponentA == TRAINER_UNION_ROOM) { trainerPicId = GetUnionRoomTrainerPic(); } else { trainerPicId = PlayerGenderToFrontTrainerPicId(gLinkPlayers[gRecordedBattleMultiplayerId ^ BIT_SIDE].gender); } } BtlController_HandleDrawTrainerPic(battler, trainerPicId, TRUE, xPos, 40, -1); } static void RecordedOpponentHandleTrainerSlideBack(u32 battler) { BtlController_HandleTrainerSlideBack(battler, 35, FALSE); } static void RecordedOpponentHandleMoveAnimation(u32 battler) { BtlController_HandleMoveAnimation(battler, FALSE); } static void RecordedOpponentHandlePrintString(u32 battler) { BtlController_HandlePrintString(battler, FALSE, FALSE); } static void RecordedOpponentHandleChooseAction(u32 battler) { BtlController_EmitTwoReturnValues(battler, BUFFER_B, RecordedBattle_GetBattlerAction(RECORDED_ACTION_TYPE, battler), 0); RecordedOpponentBufferExecCompleted(battler); } static void RecordedOpponentHandleChooseMove(u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, ChooseMoveAndTargetInBattlePalace(battler)); } else { u8 moveId = RecordedBattle_GetBattlerAction(RECORDED_MOVE_SLOT, battler); u8 target = RecordedBattle_GetBattlerAction(RECORDED_MOVE_TARGET, battler); BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, moveId | (target << 8)); } RecordedOpponentBufferExecCompleted(battler); } static void RecordedOpponentHandleChooseItem(u32 battler) { u8 byte1 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, battler); u8 byte2 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, battler); gBattleStruct->chosenItem[battler] = (byte1 << 8) | byte2; gBattleStruct->itemPartyIndex[battler] = RecordedBattle_GetBattlerAction(RECORDED_ITEM_TARGET, battler); gBattleStruct->itemMoveIndex[battler] = RecordedBattle_GetBattlerAction(RECORDED_ITEM_MOVE, battler); BtlController_EmitOneReturnValue(battler, BUFFER_B, gBattleStruct->chosenItem[battler]); RecordedOpponentBufferExecCompleted(battler); } static void RecordedOpponentHandleChoosePokemon(u32 battler) { gBattleStruct->monToSwitchIntoId[battler] = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, battler); gSelectedMonPartyId = gBattleStruct->monToSwitchIntoId[battler]; // Revival Blessing BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, gBattleStruct->monToSwitchIntoId[battler], NULL); RecordedOpponentBufferExecCompleted(battler); } static void RecordedOpponentHandleHealthBarUpdate(u32 battler) { BtlController_HandleHealthBarUpdate(battler, FALSE); } static void RecordedOpponentHandleStatusIconUpdate(u32 battler) { if (!IsBattleSEPlaying(battler)) { DoStatusIconUpdate(battler); if (gTestRunnerEnabled) TestRunner_Battle_RecordStatus1(battler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_STATUS)); } } static void RecordedOpponentHandleStatusAnimation(u32 battler) { BtlController_HandleStatusAnimation(battler); } static void RecordedOpponentHandleIntroTrainerBallThrow(u32 battler) { BtlController_HandleIntroTrainerBallThrow(battler, 0, NULL, 0, Intro_TryShinyAnimShowHealthbox); } static void RecordedOpponentHandleDrawPartyStatusSummary(u32 battler) { BtlController_HandleDrawPartyStatusSummary(battler, B_SIDE_OPPONENT, TRUE); } static void RecordedOpponentHandleBattleAnimation(u32 battler) { BtlController_HandleBattleAnimation(battler, FALSE, FALSE); } static void RecordedOpponentHandleEndLinkBattle(u32 battler) { if (gBattleResources->bufferA[battler][1] == B_OUTCOME_DREW) gBattleOutcome = gBattleResources->bufferA[battler][1]; else gBattleOutcome = gBattleResources->bufferA[battler][1] ^ B_OUTCOME_DREW; FadeOutMapMusic(5); BeginFastPaletteFade(3); RecordedOpponentBufferExecCompleted(battler); gBattlerControllerFuncs[battler] = SetBattleEndCallbacks; }