diff options
Diffstat (limited to 'src/battle_controller_player.c')
-rw-r--r-- | src/battle_controller_player.c | 1600 |
1 files changed, 1600 insertions, 0 deletions
diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c new file mode 100644 index 000000000..33807b39a --- /dev/null +++ b/src/battle_controller_player.c @@ -0,0 +1,1600 @@ +#include "global.h" +#include "battle.h" +#include "battle_controllers.h" +#include "battle_message.h" +#include "battle_interface.h" +#include "battle_anim.h" +#include "pokemon.h" +#include "link.h" +#include "util.h" +#include "main.h" +#include "item.h" +#include "items.h" +#include "songs.h" +#include "sound.h" +#include "moves.h" +#include "window.h" +#include "m4a.h" +#include "palette.h" +#include "task.h" +#include "text.h" +#include "string_util.h" +#include "bg.h" +#include "reshow_battle_screen.h" + +extern u32 gBattleExecBuffer; +extern u8 gActiveBank; +extern u8 gBankSpriteIds[BATTLE_BANKS_COUNT]; +extern u8 gActionSelectionCursor[BATTLE_BANKS_COUNT]; +extern u8 gMoveSelectionCursor[BATTLE_BANKS_COUNT]; +extern u8 gAbsentBankFlags; +extern u8 gNoOfAllBanks; +extern bool8 gDoingBattleAnim; +extern u8 gUnknown_020244CC; +extern void (*gBattleBankFunc[BATTLE_BANKS_COUNT])(void); +extern void (*gPreBattleCallback1)(void); +extern u16 gBattlePartyID[BATTLE_BANKS_COUNT]; +extern u8 gBattleBufferA[BATTLE_BANKS_COUNT][0x200]; +extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200]; +extern u8 gMultiUsePlayerCursor; +extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT]; +extern struct MusicPlayerInfo gMPlay_BGM; + +extern const struct BattleMove gBattleMoves[]; + +extern void dp11b_obj_instanciate(u8, u8, s8, s8); +extern void dp11b_obj_free(u8, u8); +extern void sub_800AC34(void); + +// this file's functions +void PlayerHandleGetMonData(void); +void PlayerHandleGetRawMonData(void); +void PlayerHandleSetMonData(void); +void PlayerHandleSetRawMonData(void); +void PlayerHandleLoadMonSprite(void); +void PlayerHandleSwitchInAnim(void); +void PlayerHandleReturnMonToBall(void); +void PlayerHandleDrawTrainerPic(void); +void PlayerHandleTrainerSlide(void); +void PlayerHandleTrainerSlideBack(void); +void PlayerHandleFaintAnimation(void); +void PlayerHandleCmd11(void); +void PlayerHandleCmd12(void); +void PlayerHandleBallThrow(void); +void PlayerHandlePause(void); +void PlayerHandleMoveAnimation(void); +void PlayerHandlePrintString(void); +void PlayerHandlePrintStringPlayerOnly(void); +void PlayerHandleChooseAction(void); +void PlayerHandleCmd19(void); +void PlayerHandleChooseMove(void); +void PlayerHandleOpenBag(void); +void PlayerHandleChoosePokemon(void); +void PlayerHandleCmd23(void); +void PlayerHandleHealthBarUpdate(void); +void PlayerHandleExpUpdate(void); +void PlayerHandleStatusIconUpdate(void); +void PlayerHandleStatusAnimation(void); +void PlayerHandleStatusXor(void); +void PlayerHandleDataTransfer(void); +void PlayerHandleDMA3Transfer(void); +void PlayerHandlePlayBGM(void); +void PlayerHandleCmd32(void); +void PlayerHandleCmd33(void); +void PlayerHandleCmd34(void); +void PlayerHandleCmd35(void); +void PlayerHandleCmd36(void); +void PlayerHandleCmd37(void); +void PlayerHandleCmd38(void); +void PlayerHandleCmd39(void); +void PlayerHandleCmd40(void); +void PlayerHandleHitAnimation(void); +void PlayerHandleCmd42(void); +void PlayerHandleEffectivenessSound(void); +void PlayerHandlePlayFanfareOrBGM(void); +void PlayerHandleFaintingCry(void); +void PlayerHandleIntroSlide(void); +void PlayerHandleIntroTrainerBallThrow(void); +void PlayerHandleDrawPartyStatusSummary(void); +void PlayerHandleCmd49(void); +void PlayerHandleCmd50(void); +void PlayerHandleSpriteInvisibility(void); +void PlayerHandleBattleAnimation(void); +void PlayerHandleLinkStandbyMsg(void); +void PlayerHandleResetActionMoveSelection(void); +void PlayerHandleCmd55(void); +void nullsub_22(void); + +void PlayerBufferRunCommand(void); +void HandleInputChooseTarget(void); +void HandleInputChooseMove(void); +void MoveSelectionCreateCursorAt(u8 cursorPos, u8 arg1); +void MoveSelectionDestroyCursorAt(u8 cursorPos); +void MoveSelectionDisplayPpNumber(void); +void MoveSelectionDisplayPpString(void); +void MoveSelectionDisplayMoveType(void); +void MoveSelectionDisplayMoveNames(void); +void HandleMoveSwitchting(void); +void sub_8058FC0(void); +void sub_8059828(void); +void sub_80598E0(void); +void sub_8059544(u8 taskId); +void sub_8059330(u8 taskId); +void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId); +void sub_8059400(u8 taskId); +void sub_80595A4(u8 taskId); +void PrintLinkStandbyMsg(void); + +void (*const gPlayerBufferCommands[CONTOLLER_CMDS_COUNT])(void) = +{ + PlayerHandleGetMonData, + PlayerHandleGetRawMonData, + PlayerHandleSetMonData, + PlayerHandleSetRawMonData, + PlayerHandleLoadMonSprite, + PlayerHandleSwitchInAnim, + PlayerHandleReturnMonToBall, + PlayerHandleDrawTrainerPic, + PlayerHandleTrainerSlide, + PlayerHandleTrainerSlideBack, + PlayerHandleFaintAnimation, + PlayerHandleCmd11, + PlayerHandleCmd12, + PlayerHandleBallThrow, + PlayerHandlePause, + PlayerHandleMoveAnimation, + PlayerHandlePrintString, + PlayerHandlePrintStringPlayerOnly, + PlayerHandleChooseAction, + PlayerHandleCmd19, + PlayerHandleChooseMove, + PlayerHandleOpenBag, + PlayerHandleChoosePokemon, + PlayerHandleCmd23, + PlayerHandleHealthBarUpdate, + PlayerHandleExpUpdate, + PlayerHandleStatusIconUpdate, + PlayerHandleStatusAnimation, + PlayerHandleStatusXor, + PlayerHandleDataTransfer, + PlayerHandleDMA3Transfer, + PlayerHandlePlayBGM, + PlayerHandleCmd32, + PlayerHandleCmd33, + PlayerHandleCmd34, + PlayerHandleCmd35, + PlayerHandleCmd36, + PlayerHandleCmd37, + PlayerHandleCmd38, + PlayerHandleCmd39, + PlayerHandleCmd40, + PlayerHandleHitAnimation, + PlayerHandleCmd42, + PlayerHandleEffectivenessSound, + PlayerHandlePlayFanfareOrBGM, + PlayerHandleFaintingCry, + PlayerHandleIntroSlide, + PlayerHandleIntroTrainerBallThrow, + PlayerHandleDrawPartyStatusSummary, + PlayerHandleCmd49, + PlayerHandleCmd50, + PlayerHandleSpriteInvisibility, + PlayerHandleBattleAnimation, + PlayerHandleLinkStandbyMsg, + PlayerHandleResetActionMoveSelection, + PlayerHandleCmd55, + nullsub_22 +}; + +static const u8 sTargetIdentities[] = {IDENTITY_PLAYER_MON1, IDENTITY_PLAYER_MON2, IDENTITY_OPPONENT_MON2, IDENTITY_OPPONENT_MON1}; + +// unknown unused data +static const u8 gUnknown_0831C5FC[] = {0x48, 0x48, 0x20, 0x5a, 0x50, 0x50, 0x50, 0x58}; + +void nullsub_21(void) +{ +} + +void SetBankFuncToPlayerBufferRunCommand(void) +{ + gBattleBankFunc[gActiveBank] = PlayerBufferRunCommand; + gDoingBattleAnim = FALSE; + gUnknown_020244CC = 0; +} + +void PlayerBufferExecCompleted(void) +{ + gBattleBankFunc[gActiveBank] = PlayerBufferRunCommand; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + u8 playerId = GetMultiplayerId(); + + PrepareBufferDataTransferLink(2, 4, &playerId); + gBattleBufferA[gActiveBank][0] = CONTOLLER_CMDS_COUNT - 1; + } + else + { + gBattleExecBuffer &= ~gBitTable[gActiveBank]; + } +} + +void PlayerBufferRunCommand(void) +{ + if (gBattleExecBuffer & gBitTable[gActiveBank]) + { + if (gBattleBufferA[gActiveBank][0] < ARRAY_COUNT(gPlayerBufferCommands)) + gPlayerBufferCommands[gBattleBufferA[gActiveBank][0]](); + else + PlayerBufferExecCompleted(); + } +} + +void CompleteOnBankSpritePosX_0(void) +{ + if (gSprites[gBankSpriteIds[gActiveBank]].pos2.x == 0) + PlayerBufferExecCompleted(); +} + +void HandleInputChooseAction(void) +{ + u16 itemId = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + + dp11b_obj_instanciate(gActiveBank, 1, 7, 1); + dp11b_obj_instanciate(gActiveBank, 0, 7, 1); + + if (gMain.newAndRepeatedKeys & DPAD_ANY && gSaveBlock2Ptr->optionsButtonMode == 2) + gUnknown_020244CC++; + else + gUnknown_020244CC = 0; + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + + switch (gActionSelectionCursor[gActiveBank]) + { + case ACTION_USE_MOVE: + EmitCmd33(1, ACTION_USE_MOVE, 0); + break; + case ACTION_USE_ITEM: + EmitCmd33(1, ACTION_USE_ITEM, 0); + break; + case ACTION_SWITCH: + EmitCmd33(1, ACTION_SWITCH, 0); + break; + case ACTION_RUN: + EmitCmd33(1, ACTION_RUN, 0); + break; + } + PlayerBufferExecCompleted(); + } + else if (gMain.newKeys & DPAD_LEFT) + { + if (gActionSelectionCursor[gActiveBank] & 1) // if is ACTION_USE_ITEM or ACTION_RUN + { + PlaySE(SE_SELECT); + ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 1; + ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_RIGHT) + { + if (!(gActionSelectionCursor[gActiveBank] & 1)) // if is ACTION_USE_MOVE or ACTION_SWITCH + { + PlaySE(SE_SELECT); + ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 1; + ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_UP) + { + if (gActionSelectionCursor[gActiveBank] & 2) // if is ACTION_SWITCH or ACTION_RUN + { + PlaySE(SE_SELECT); + ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 2; + ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (!(gActionSelectionCursor[gActiveBank] & 2)) // if is ACTION_USE_MOVE or ACTION_USE_ITEM + { + PlaySE(SE_SELECT); + ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 2; + ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & B_BUTTON || gUnknown_020244CC > 59) + { + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + && GetBankIdentity(gActiveBank) == IDENTITY_PLAYER_MON2 + && !(gAbsentBankFlags & gBitTable[GetBankByIdentity(IDENTITY_PLAYER_MON1)]) + && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + if (gBattleBufferA[gActiveBank][1] == ACTION_USE_ITEM) + { + // Add item to bag if it is a ball + if (itemId <= ITEM_PREMIER_BALL) + AddBagItem(itemId, 1); + else + return; + } + PlaySE(SE_SELECT); + EmitCmd33(1, ACTION_CANCEL_PARTNER, 0); + PlayerBufferExecCompleted(); + } + } + else if (gMain.newKeys & START_BUTTON) + { + SwapHpBarsWithHpText(); + } +} + +void sub_80577F0(void) // unused +{ + dp11b_obj_free(gActiveBank, 1); + dp11b_obj_free(gActiveBank, 0); + gBattleBankFunc[gActiveBank] = HandleInputChooseTarget; +} + +void HandleInputChooseTarget(void) +{ + s32 i; + u8 identities[4]; + memcpy(identities, sTargetIdentities, ARRAY_COUNT(sTargetIdentities)); + + dp11b_obj_instanciate(gMultiUsePlayerCursor, 1, 0xF, 1); + + // what a weird loop + i = 0; + if (gNoOfAllBanks != 0) + { + do + { + if (i != gMultiUsePlayerCursor) + dp11b_obj_free(i, 1); + i++; + } while (i < gNoOfAllBanks); + } + + if (gMain.heldKeys & DPAD_ANY && gSaveBlock2Ptr->optionsButtonMode == 2) + gUnknown_020244CC++; + else + gUnknown_020244CC = 0; + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + gSprites[gBankSpriteIds[gMultiUsePlayerCursor]].callback = sub_8039B2C; + EmitCmd33(1, 10, gMoveSelectionCursor[gActiveBank] | (gMultiUsePlayerCursor << 8)); + dp11b_obj_free(gMultiUsePlayerCursor, 1); + PlayerBufferExecCompleted(); + } + else if (gMain.newKeys & B_BUTTON || gUnknown_020244CC > 59) + { + PlaySE(SE_SELECT); + gSprites[gBankSpriteIds[gMultiUsePlayerCursor]].callback = sub_8039B2C; + gBattleBankFunc[gActiveBank] = HandleInputChooseMove; + dp11b_obj_instanciate(gActiveBank, 1, 7, 1); + dp11b_obj_instanciate(gActiveBank, 0, 7, 1); + dp11b_obj_free(gMultiUsePlayerCursor, 1); + } + else if (gMain.newKeys & (DPAD_LEFT | DPAD_UP)) + { + PlaySE(SE_SELECT); + gSprites[gBankSpriteIds[gMultiUsePlayerCursor]].callback = sub_8039B2C; + + do + { + u8 currSelIdentity = GetBankIdentity(gMultiUsePlayerCursor); + + for (i = 0; i < BATTLE_BANKS_COUNT; i++) + { + if (currSelIdentity == identities[i]) + break; + } + do + { + if (--i < 0) + i = 4; // UB: array out of range + gMultiUsePlayerCursor = GetBankByIdentity(identities[i]); + } while (gMultiUsePlayerCursor == gNoOfAllBanks); + + i = 0; + switch (GetBankIdentity(gMultiUsePlayerCursor)) + { + case IDENTITY_PLAYER_MON1: + case IDENTITY_PLAYER_MON2: + if (gActiveBank != gMultiUsePlayerCursor) + i++; + else if (gBattleMoves[GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBank])].target & MOVE_TARGET_USER) + i++; + break; + case IDENTITY_OPPONENT_MON1: + case IDENTITY_OPPONENT_MON2: + i++; + break; + } + + if (gAbsentBankFlags & gBitTable[gMultiUsePlayerCursor]) + i = 0; + } while (i == 0); + gSprites[gBankSpriteIds[gMultiUsePlayerCursor]].callback = sub_8039AD8; + } + else if (gMain.newKeys & (DPAD_RIGHT | DPAD_DOWN)) + { + PlaySE(SE_SELECT); + gSprites[gBankSpriteIds[gMultiUsePlayerCursor]].callback = sub_8039B2C; + + do + { + u8 currSelIdentity = GetBankIdentity(gMultiUsePlayerCursor); + + for (i = 0; i < BATTLE_BANKS_COUNT; i++) + { + if (currSelIdentity == identities[i]) + break; + } + do + { + if (++i > 3) + i = 0; + gMultiUsePlayerCursor = GetBankByIdentity(identities[i]); + } while (gMultiUsePlayerCursor == gNoOfAllBanks); + + i = 0; + switch (GetBankIdentity(gMultiUsePlayerCursor)) + { + case IDENTITY_PLAYER_MON1: + case IDENTITY_PLAYER_MON2: + if (gActiveBank != gMultiUsePlayerCursor) + i++; + else if (gBattleMoves[GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBank])].target & MOVE_TARGET_USER) + i++; + break; + case IDENTITY_OPPONENT_MON1: + case IDENTITY_OPPONENT_MON2: + i++; + break; + } + + if (gAbsentBankFlags & gBitTable[gMultiUsePlayerCursor]) + i = 0; + } while (i == 0); + gSprites[gBankSpriteIds[gMultiUsePlayerCursor]].callback = sub_8039AD8; + } +} + +extern u8 gNumberOfMovesToChoose; +extern const u8 gText_BattleSwitchWhich[]; + +void HandleInputChooseMove(void) +{ + bool32 canSelectTarget = FALSE; + struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleBufferA[gActiveBank][4]); + + if (gMain.heldKeys & DPAD_ANY && gSaveBlock2Ptr->optionsButtonMode == 2) + gUnknown_020244CC++; + else + gUnknown_020244CC = 0; + + if (gMain.newKeys & A_BUTTON) + { + u8 moveTarget; + + PlaySE(SE_SELECT); + if (moveInfo->moves[gMoveSelectionCursor[gActiveBank]] == MOVE_CURSE) + { + if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST) + moveTarget = MOVE_TARGET_x10; + else + moveTarget = MOVE_TARGET_SELECTED; + } + else + { + moveTarget = gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBank]]].target; + } + + if (moveTarget & MOVE_TARGET_x10) + gMultiUsePlayerCursor = gActiveBank; + else + gMultiUsePlayerCursor = GetBankByIdentity((GetBankIdentity(gActiveBank) & BIT_SIDE) ^ BIT_SIDE); + + if (!gBattleBufferA[gActiveBank][1]) // not a double battle + { + if (moveTarget & MOVE_TARGET_USER && !gBattleBufferA[gActiveBank][2]) + canSelectTarget++; + } + else // double battle + { + if (!(moveTarget & (MOVE_TARGET_RANDOM | MOVE_TARGET_BOTH | MOVE_TARGET_DEPENDS | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_x10))) + canSelectTarget++; // either selected or user + + if (moveInfo->currentPp[gMoveSelectionCursor[gActiveBank]] == 0) + { + canSelectTarget = FALSE; + } + else if (!(moveTarget & (MOVE_TARGET_x10 | MOVE_TARGET_USER)) && CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) <= 1) + { + gMultiUsePlayerCursor = GetDefaultMoveTarget(gActiveBank); + canSelectTarget = FALSE; + } + } + + if (!canSelectTarget) + { + EmitCmd33(1, 10, gMoveSelectionCursor[gActiveBank] | (gMultiUsePlayerCursor << 8)); + PlayerBufferExecCompleted(); + } + else + { + gBattleBankFunc[gActiveBank] = HandleInputChooseTarget; + + if (moveTarget & (MOVE_TARGET_x10 | MOVE_TARGET_USER)) + gMultiUsePlayerCursor = gActiveBank; + else if (gAbsentBankFlags & gBitTable[GetBankByIdentity(IDENTITY_OPPONENT_MON1)]) + gMultiUsePlayerCursor = GetBankByIdentity(IDENTITY_OPPONENT_MON2); + else + gMultiUsePlayerCursor = GetBankByIdentity(IDENTITY_OPPONENT_MON1); + + gSprites[gBankSpriteIds[gMultiUsePlayerCursor]].callback = sub_8039AD8; + } + } + else if (gMain.newKeys & B_BUTTON || gUnknown_020244CC > 59) + { + PlaySE(SE_SELECT); + EmitCmd33(1, 10, 0xFFFF); + PlayerBufferExecCompleted(); + } + else if (gMain.newKeys & DPAD_LEFT) + { + if (gMoveSelectionCursor[gActiveBank] & 1) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 1; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + MoveSelectionDisplayPpNumber(); + MoveSelectionDisplayMoveType(); + } + } + else if (gMain.newKeys & DPAD_RIGHT) + { + if (!(gMoveSelectionCursor[gActiveBank] & 1) + && (gMoveSelectionCursor[gActiveBank] ^ 1) < gNumberOfMovesToChoose) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 1; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + MoveSelectionDisplayPpNumber(); + MoveSelectionDisplayMoveType(); + } + } + else if (gMain.newKeys & DPAD_UP) + { + if (gMoveSelectionCursor[gActiveBank] & 2) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 2; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + MoveSelectionDisplayPpNumber(); + MoveSelectionDisplayMoveType(); + } + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (!(gMoveSelectionCursor[gActiveBank] & 2) + && (gMoveSelectionCursor[gActiveBank] ^ 2) < gNumberOfMovesToChoose) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 2; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + MoveSelectionDisplayPpNumber(); + MoveSelectionDisplayMoveType(); + } + } + else if (gMain.newKeys & SELECT_BUTTON) + { + if (gNumberOfMovesToChoose > 1 && !(gBattleTypeFlags & BATTLE_TYPE_LINK)) + { + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 29); + + if (gMoveSelectionCursor[gActiveBank] != 0) + gMultiUsePlayerCursor = 0; + else + gMultiUsePlayerCursor = gMoveSelectionCursor[gActiveBank] + 1; + + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 27); + sub_814F9EC(gText_BattleSwitchWhich, 0xB); + gBattleBankFunc[gActiveBank] = HandleMoveSwitchting; + } + } +} + +extern u16 gBattle_BG0_X; +extern u16 gBattle_BG0_Y; + +u32 sub_8057FBC(void) // unused +{ + u32 var = 0; + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + var = 1; + } + if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gBattle_BG0_X = 0; + gBattle_BG0_Y = 0x140; + var = 0xFF; + } + if (gMain.newKeys & DPAD_LEFT && gMoveSelectionCursor[gActiveBank] & 1) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 1; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + } + if (gMain.newKeys & DPAD_RIGHT && !(gMoveSelectionCursor[gActiveBank] & 1) + && (gMoveSelectionCursor[gActiveBank] ^ 1) < gNumberOfMovesToChoose) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 1; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + } + if (gMain.newKeys & DPAD_UP && gMoveSelectionCursor[gActiveBank] & 2) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 2; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + } + if (gMain.newKeys & DPAD_DOWN && !(gMoveSelectionCursor[gActiveBank] & 2) + && (gMoveSelectionCursor[gActiveBank] ^ 2) < gNumberOfMovesToChoose) + { + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 2; + PlaySE(SE_SELECT); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + } + + return var; +} + +void HandleMoveSwitchting(void) +{ + u8 perMovePPBonuses[4]; + struct ChooseMoveStruct moveStruct; + u8 totalPPBonuses; + + if (gMain.newKeys & (A_BUTTON | SELECT_BUTTON)) + { + PlaySE(SE_SELECT); + + if (gMoveSelectionCursor[gActiveBank] != gMultiUsePlayerCursor) + { + struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleBufferA[gActiveBank][4]); + s32 i; + + // swap moves and pp + i = moveInfo->moves[gMoveSelectionCursor[gActiveBank]]; + moveInfo->moves[gMoveSelectionCursor[gActiveBank]] = moveInfo->moves[gMultiUsePlayerCursor]; + moveInfo->moves[gMultiUsePlayerCursor] = i; + + i = moveInfo->currentPp[gMoveSelectionCursor[gActiveBank]]; + moveInfo->currentPp[gMoveSelectionCursor[gActiveBank]] = moveInfo->currentPp[gMultiUsePlayerCursor]; + moveInfo->currentPp[gMultiUsePlayerCursor] = i; + + i = moveInfo->maxPp[gMoveSelectionCursor[gActiveBank]]; + moveInfo->maxPp[gMoveSelectionCursor[gActiveBank]] = moveInfo->maxPp[gMultiUsePlayerCursor]; + moveInfo->maxPp[gMultiUsePlayerCursor] = i; + + if (gDisableStructs[gActiveBank].unk18_b & gBitTable[gMoveSelectionCursor[gActiveBank]]) + { + gDisableStructs[gActiveBank].unk18_b &= (~gBitTable[gMoveSelectionCursor[gActiveBank]]); + gDisableStructs[gActiveBank].unk18_b |= gBitTable[gMultiUsePlayerCursor]; + } + + MoveSelectionDisplayMoveNames(); + + for (i = 0; i < 4; i++) + perMovePPBonuses[i] = (gBattleMons[gActiveBank].ppBonuses & (3 << (i * 2))) >> (i * 2); + + totalPPBonuses = perMovePPBonuses[gMoveSelectionCursor[gActiveBank]]; + perMovePPBonuses[gMoveSelectionCursor[gActiveBank]] = perMovePPBonuses[gMultiUsePlayerCursor]; + perMovePPBonuses[gMultiUsePlayerCursor] = totalPPBonuses; + + totalPPBonuses = 0; + for (i = 0; i < 4; i++) + totalPPBonuses |= perMovePPBonuses[i] << (i * 2); + + gBattleMons[gActiveBank].ppBonuses = totalPPBonuses; + + for (i = 0; i < 4; i++) + { + gBattleMons[gActiveBank].moves[i] = moveInfo->moves[i]; + gBattleMons[gActiveBank].pp[i] = moveInfo->currentPp[i]; + } + + if (!(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED)) + { + for (i = 0; i < 4; i++) + { + moveStruct.moves[i] = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MOVE1 + i); + moveStruct.currentPp[i] = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_PP1 + i); + } + + totalPPBonuses = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_PP_BONUSES); + for (i = 0; i < 4; i++) + perMovePPBonuses[i] = (totalPPBonuses & (3 << (i * 2))) >> (i * 2); + + i = moveStruct.moves[gMoveSelectionCursor[gActiveBank]]; + moveStruct.moves[gMoveSelectionCursor[gActiveBank]] = moveStruct.moves[gMultiUsePlayerCursor]; + moveStruct.moves[gMultiUsePlayerCursor] = i; + + i = moveStruct.currentPp[gMoveSelectionCursor[gActiveBank]]; + moveStruct.currentPp[gMoveSelectionCursor[gActiveBank]] = moveStruct.currentPp[gMultiUsePlayerCursor]; + moveStruct.currentPp[gMultiUsePlayerCursor] = i; + + totalPPBonuses = perMovePPBonuses[gMoveSelectionCursor[gActiveBank]]; + perMovePPBonuses[gMoveSelectionCursor[gActiveBank]] = perMovePPBonuses[gMultiUsePlayerCursor]; + perMovePPBonuses[gMultiUsePlayerCursor] = totalPPBonuses; + + totalPPBonuses = 0; + for (i = 0; i < 4; i++) + totalPPBonuses |= perMovePPBonuses[i] << (i * 2); + + for (i = 0; i < 4; i++) + { + SetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MOVE1 + i, &moveStruct.moves[i]); + SetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_PP1 + i, &moveStruct.currentPp[i]); + } + + SetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_PP_BONUSES, &totalPPBonuses); + } + } + + gBattleBankFunc[gActiveBank] = HandleInputChooseMove; + gMoveSelectionCursor[gActiveBank] = gMultiUsePlayerCursor; + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + MoveSelectionDisplayPpString(); + MoveSelectionDisplayPpNumber(); + MoveSelectionDisplayMoveType(); + } + else if (gMain.newKeys & (B_BUTTON | SELECT_BUTTON)) + { + PlaySE(SE_SELECT); + MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 0); + gBattleBankFunc[gActiveBank] = HandleInputChooseMove; + MoveSelectionDisplayPpString(); + MoveSelectionDisplayPpNumber(); + MoveSelectionDisplayMoveType(); + } + else if (gMain.newKeys & DPAD_LEFT) + { + if (gMultiUsePlayerCursor & 1) + { + if (gMultiUsePlayerCursor == gMoveSelectionCursor[gActiveBank]) + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 29); + else + MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + + gMultiUsePlayerCursor ^= 1; + PlaySE(SE_SELECT); + + if (gMultiUsePlayerCursor == gMoveSelectionCursor[gActiveBank]) + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 0); + else + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 27); + } + } + else if (gMain.newKeys & DPAD_RIGHT) + { + if (!(gMultiUsePlayerCursor & 1) && (gMultiUsePlayerCursor ^ 1) < gNumberOfMovesToChoose) + { + if (gMultiUsePlayerCursor == gMoveSelectionCursor[gActiveBank]) + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 29); + else + MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + + gMultiUsePlayerCursor ^= 1; + PlaySE(SE_SELECT); + + if (gMultiUsePlayerCursor == gMoveSelectionCursor[gActiveBank]) + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 0); + else + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 27); + } + } + else if (gMain.newKeys & DPAD_UP) + { + if (gMultiUsePlayerCursor & 2) + { + if (gMultiUsePlayerCursor == gMoveSelectionCursor[gActiveBank]) + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 29); + else + MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + + gMultiUsePlayerCursor ^= 2; + PlaySE(SE_SELECT); + + if (gMultiUsePlayerCursor == gMoveSelectionCursor[gActiveBank]) + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 0); + else + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 27); + } + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (!(gMultiUsePlayerCursor & 2) && (gMultiUsePlayerCursor ^ 2) < gNumberOfMovesToChoose) + { + if (gMultiUsePlayerCursor == gMoveSelectionCursor[gActiveBank]) + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBank], 29); + else + MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); + + gMultiUsePlayerCursor ^= 2; + PlaySE(SE_SELECT); + + if (gMultiUsePlayerCursor == gMoveSelectionCursor[gActiveBank]) + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 0); + else + MoveSelectionCreateCursorAt(gMultiUsePlayerCursor, 27); + } + } +} + +extern u8 gBattleOutcome; +extern void sub_817E3F4(void); // battle_link_817C95C + +void sub_80586F8(void) +{ + if (gLinkVSyncDisabled == 0) + { + if (gReceivedRemoteLinkPlayers == 0) + { + m4aSongNumStop(SE_HINSI); + gMain.inBattle = 0; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(sub_8038D64); + if (gBattleOutcome == BATTLE_WON) + sub_817E3F4(); + FreeAllWindowBuffers(); + } + } + else + { + if (sub_800A520()) + { + m4aSongNumStop(SE_HINSI); + gMain.inBattle = 0; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(sub_8038D64); + if (gBattleOutcome == BATTLE_WON) + sub_817E3F4(); + FreeAllWindowBuffers(); + } + } +} + +void sub_80587B0(void) +{ + if (!gPaletteFade.active) + { + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + if (sub_800A520()) + { + if (gLinkVSyncDisabled == 0) + sub_800AC34(); + else + sub_800ADF8(); + + gBattleBankFunc[gActiveBank] = sub_80586F8; + } + } + else + { + m4aSongNumStop(SE_HINSI); + gMain.inBattle = 0; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } + } +} + +void CompleteOnBankSpriteCallbackDummy(void) +{ + if (gSprites[gBankSpriteIds[gActiveBank]].callback == SpriteCallbackDummy) + PlayerBufferExecCompleted(); +} + +void CompleteOnBankSpriteCallbackDummy2(void) +{ + if (gSprites[gBankSpriteIds[gActiveBank]].callback == SpriteCallbackDummy) + PlayerBufferExecCompleted(); +} + +void sub_80588B4(void) +{ + if (gSprites[gBankSpriteIds[gActiveBank]].callback == SpriteCallbackDummy) + { + nullsub_25(gSaveBlock2Ptr->playerGender); + FreeSpriteOamMatrix(&gSprites[gBankSpriteIds[gActiveBank]]); + DestroySprite(&gSprites[gBankSpriteIds[gActiveBank]]); + PlayerBufferExecCompleted(); + } +} + +void sub_8058924(void) +{ + if (--gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_9 == 0xFF) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_9 = 0; + PlayerBufferExecCompleted(); + } +} + +extern u8 gHealthBoxesIds[BATTLE_BANKS_COUNT]; + +extern bool8 IsDoubleBattle(void); + +void sub_805896C(void) +{ + bool8 var = FALSE; + + if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + { + if (gSprites[gHealthBoxesIds[gActiveBank]].callback == SpriteCallbackDummy) + var = TRUE; + } + else + { + if (gSprites[gHealthBoxesIds[gActiveBank]].callback == SpriteCallbackDummy + && gSprites[gHealthBoxesIds[gActiveBank ^ BIT_MON]].callback == SpriteCallbackDummy) + var = TRUE; + } + + if (var && gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x1 + && gBattleSpritesDataPtr->healthBoxesData[gActiveBank ^ BIT_MON].field_1_x1) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x1 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBank ^ BIT_MON].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBank ^ BIT_MON].field_1_x1 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + + sub_805E990(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + + if (IsDoubleBattle()) + sub_805E990(&gPlayerParty[gBattlePartyID[gActiveBank ^ BIT_MON]], gActiveBank ^ BIT_MON); + + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_9 = 3; + gBattleBankFunc[gActiveBank] = sub_8058924; + } +} + +extern void sub_8172EF0(u8 bank, struct Pokemon *mon); +extern void sub_8076918(u8 bank); +extern u8 gUnknown_03005D7C[]; + +void sub_8058B40(void) +{ + bool32 r9 = FALSE; + bool32 r8 = FALSE; + + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x80 && !gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x8) + sub_8172EF0(gActiveBank, &gPlayerParty[gBattlePartyID[gActiveBank]]); + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank ^ BIT_MON].flag_x80 && !gBattleSpritesDataPtr->healthBoxesData[gActiveBank ^ BIT_MON].flag_x8) + sub_8172EF0(gActiveBank ^ BIT_MON, &gPlayerParty[gBattlePartyID[gActiveBank ^ BIT_MON]]); + + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x8 && !gBattleSpritesDataPtr->healthBoxesData[gActiveBank ^ BIT_MON].flag_x8) + { + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x80) + { + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + UpdateHealthboxAttribute(gHealthBoxesIds[gActiveBank ^ BIT_MON], &gPlayerParty[gBattlePartyID[gActiveBank ^ BIT_MON]], HEALTHBOX_ALL); + sub_8076918(gActiveBank ^ BIT_MON); + SetHealthboxSpriteVisible(gHealthBoxesIds[gActiveBank ^ BIT_MON]); + } + UpdateHealthboxAttribute(gHealthBoxesIds[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], HEALTHBOX_ALL); + sub_8076918(gActiveBank); + SetHealthboxSpriteVisible(gHealthBoxesIds[gActiveBank]); + } + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x80 = 1; + } + + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x40 + && gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x80 + && !gBattleSpritesDataPtr->healthBoxesData[gActiveBank ^ BIT_MON].field_1_x40 + && !IsCryPlayingOrClearCrySongs()) + { + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x20) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK) + m4aMPlayContinue(&gMPlay_BGM); + else + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100); + } + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x20 = 1; + r9 = TRUE; + } + + if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + { + if (gSprites[gUnknown_03005D7C[gActiveBank]].callback == SpriteCallbackDummy + && gSprites[gBankSpriteIds[gActiveBank]].callback == SpriteCallbackDummy) + { + r8 = TRUE; + } + } + else + { + if (gSprites[gUnknown_03005D7C[gActiveBank]].callback == SpriteCallbackDummy + && gSprites[gBankSpriteIds[gActiveBank]].callback == SpriteCallbackDummy + && gSprites[gUnknown_03005D7C[gActiveBank ^ BIT_MON]].callback == SpriteCallbackDummy + && gSprites[gBankSpriteIds[gActiveBank ^ BIT_MON]].callback == SpriteCallbackDummy) + { + r8 = TRUE; + } + } + + if (r9 && r8) + { + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + DestroySprite(&gSprites[gUnknown_03005D7C[gActiveBank ^ BIT_MON]]); + DestroySprite(&gSprites[gUnknown_03005D7C[gActiveBank]]); + + gBattleSpritesDataPtr->animationData->field_9_x1 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x20 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x80 = 0; + + gBattleBankFunc[gActiveBank] = sub_805896C; + } +} + +extern void sub_805E408(u8 bank); +extern void move_anim_start_t4(u8 arg0, u8 atkBank, u8 defBank, u8 tableId); + +void sub_8058EDC(void) +{ + if (gSprites[gHealthBoxesIds[gActiveBank]].callback == SpriteCallbackDummy + && gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x1 + && gSprites[gBankSpriteIds[gActiveBank]].callback == SpriteCallbackDummy) + { + sub_805E408(gActiveBank); + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBank].field_1_x1 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + + if (gBattleSpritesDataPtr->bankData[gActiveBank].behindSubstitute) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + + gBattleBankFunc[gActiveBank] = sub_8058FC0; + } +} + +void sub_8058FC0(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x40 + && !IsCryPlayingOrClearCrySongs()) + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100); + sub_805E990(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + PlayerBufferExecCompleted(); + } +} + +void sub_805902C(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x80 + && !gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x8) + { + sub_8172EF0(gActiveBank, &gPlayerParty[gBattlePartyID[gActiveBank]]); + } + + if (gSprites[gUnknown_03005D7C[gActiveBank]].callback == SpriteCallbackDummy + && !gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x8) + { + DestroySprite(&gSprites[gUnknown_03005D7C[gActiveBank]]); + UpdateHealthboxAttribute(gHealthBoxesIds[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], HEALTHBOX_ALL); + sub_8076918(gActiveBank); + SetHealthboxSpriteVisible(gHealthBoxesIds[gActiveBank]); + gBattleBankFunc[gActiveBank] = sub_8058EDC; + } +} + +void c3_0802FDF4(u8 taskId) +{ + if (!IsCryPlayingOrClearCrySongs()) + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100); + DestroyTask(taskId); + } +} + +void bx_t1_healthbar_update(void) +{ + s16 hpValue = sub_8074AA0(gActiveBank, gHealthBoxesIds[gActiveBank], 0, 0); + + SetHealthboxSpriteVisible(gHealthBoxesIds[gActiveBank]); + + if (hpValue != -1) + { + UpdateHpTextInHealthbox(gHealthBoxesIds[gActiveBank], hpValue, HP_CURRENT); + } + else + { + sub_805E990(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + PlayerBufferExecCompleted(); + } +} + +void CompleteOnInactiveTextPrinter(void) +{ + if (!IsTextPrinterActive(0)) + PlayerBufferExecCompleted(); +} + +void sub_80591B8(u8 taskId) +{ + u32 monId = (u8)(gTasks[taskId].data[0]); + u8 bank = gTasks[taskId].data[2]; + s16 gainedExp = gTasks[taskId].data[1]; + + if (IsDoubleBattle() == TRUE || monId != gBattlePartyID[bank]) + { + struct Pokemon *mon = &gPlayerParty[monId]; + u16 species = GetMonData(mon, MON_DATA_SPECIES); + u8 level = GetMonData(mon, MON_DATA_LEVEL); + u32 currExp = GetMonData(mon, MON_DATA_EXP); + u32 nextLvlExp = gExperienceTables[gBaseStats[species].growthRate][level + 1]; + + if (currExp + gainedExp >= nextLvlExp) + { + u8 savedActiveBank; + + SetMonData(mon, MON_DATA_EXP, &nextLvlExp); + CalculateMonStats(mon); + gainedExp -= nextLvlExp - currExp; + savedActiveBank = gActiveBank; + gActiveBank = bank; + EmitCmd33(1, 11, gainedExp); + gActiveBank = savedActiveBank; + + if (IsDoubleBattle() == TRUE + && ((u16)(monId) == gBattlePartyID[bank] || (u16)(monId) == gBattlePartyID[bank ^ BIT_MON])) + gTasks[taskId].func = sub_8059544; + else + gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; + } + else + { + currExp += gainedExp; + SetMonData(mon, MON_DATA_EXP, &currExp); + gBattleBankFunc[bank] = CompleteOnInactiveTextPrinter; + DestroyTask(taskId); + } + } + else + { + gTasks[taskId].func = sub_8059330; + } +} + +void sub_8059330(u8 taskId) +{ + u8 monIndex = gTasks[taskId].data[0]; + s32 gainedExp = gTasks[taskId].data[1]; + u8 bank = gTasks[taskId].data[2]; + struct Pokemon *mon = &gPlayerParty[monIndex]; + u8 level = GetMonData(mon, MON_DATA_LEVEL); + u16 species = GetMonData(mon, MON_DATA_SPECIES); + u32 exp = GetMonData(mon, MON_DATA_EXP); + u32 currLvlExp = gExperienceTables[gBaseStats[species].growthRate][level]; + u32 expToNextLvl; + + exp -= currLvlExp; + expToNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLvlExp; + SetBattleBarStruct(bank, gHealthBoxesIds[bank], expToNextLvl, exp, -gainedExp); + PlaySE(SE_EXP); + gTasks[taskId].func = sub_8059400; +} + +void sub_8059400(u8 taskId) +{ + if (gTasks[taskId].data[10] < 13) + { + gTasks[taskId].data[10]++; + } + else + { + u8 monId = gTasks[taskId].data[0]; + s16 gainedExp = gTasks[taskId].data[1]; + u8 bank = gTasks[taskId].data[2]; + s16 r4; + + r4 = sub_8074AA0(bank, gHealthBoxesIds[bank], 1, 0); + SetHealthboxSpriteVisible(gHealthBoxesIds[bank]); + if (r4 == -1) + { + u8 level; + s32 currExp; + u16 species; + s32 expOnNextLvl; + + m4aSongNumStop(SE_EXP); + level = GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL); + currExp = GetMonData(&gPlayerParty[monId], MON_DATA_EXP); + species = GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES); + expOnNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1]; + + if (currExp + gainedExp >= expOnNextLvl) + { + u8 savedActiveBank; + + SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &expOnNextLvl); + CalculateMonStats(&gPlayerParty[monId]); + gainedExp -= expOnNextLvl - currExp; + savedActiveBank = gActiveBank; + gActiveBank = bank; + EmitCmd33(1, 11, gainedExp); + gActiveBank = savedActiveBank; + gTasks[taskId].func = sub_8059544; + } + else + { + currExp += gainedExp; + SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &currExp); + gBattleBankFunc[bank] = CompleteOnInactiveTextPrinter; + DestroyTask(taskId); + } + } + } +} + +void sub_8059544(u8 taskId) +{ + u8 bank = gTasks[taskId].data[2]; + u8 monIndex = gTasks[taskId].data[0]; + + if (IsDoubleBattle() == TRUE && monIndex == gBattlePartyID[bank ^ BIT_MON]) + bank ^= BIT_MON; + + move_anim_start_t4(bank, bank, bank, 0); + gTasks[taskId].func = sub_80595A4; +} + +void sub_80595A4(u8 taskId) +{ + u8 bank = gTasks[taskId].data[2]; + + if (!gBattleSpritesDataPtr->healthBoxesData[bank].flag_x40) + { + u8 monIndex = gTasks[taskId].data[0]; + + GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value + + if (IsDoubleBattle() == TRUE && monIndex == gBattlePartyID[bank ^ BIT_MON]) + UpdateHealthboxAttribute(gHealthBoxesIds[bank ^ BIT_MON], &gPlayerParty[monIndex], HEALTHBOX_ALL); + else + UpdateHealthboxAttribute(gHealthBoxesIds[bank], &gPlayerParty[monIndex], HEALTHBOX_ALL); + + gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; + } +} + +void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId) +{ + u8 monIndex; + u8 bank; + + monIndex = gTasks[taskId].data[0]; + GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value + bank = gTasks[taskId].data[2]; + gBattleBankFunc[bank] = CompleteOnInactiveTextPrinter; + DestroyTask(taskId); +} + +void sub_80596A8(void) +{ + if (gSprites[gBankSpriteIds[gActiveBank]].pos1.y + gSprites[gBankSpriteIds[gActiveBank]].pos2.y > DISPLAY_HEIGHT) + { + u16 species = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES); + + nullsub_24(species); + FreeOamMatrix(gSprites[gBankSpriteIds[gActiveBank]].oam.matrixNum); + DestroySprite(&gSprites[gBankSpriteIds[gActiveBank]]); + SetHealthboxSpriteInvisible(gHealthBoxesIds[gActiveBank]); + PlayerBufferExecCompleted(); + } +} + +void sub_8059744(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x40) + { + FreeSpriteOamMatrix(&gSprites[gBankSpriteIds[gActiveBank]]); + DestroySprite(&gSprites[gBankSpriteIds[gActiveBank]]); + SetHealthboxSpriteInvisible(gHealthBoxesIds[gActiveBank]); + PlayerBufferExecCompleted(); + } +} + +void CompleteOnInactiveTextPrinter2(void) +{ + if (!IsTextPrinterActive(0)) + PlayerBufferExecCompleted(); +} + +extern void sub_81B89AC(u8 arg0); + +void sub_80597CC(void) +{ + if (!gPaletteFade.active) + { + u8 r4; + + gBattleBankFunc[gActiveBank] = sub_8059828; + r4 = gTasks[gUnknown_03005D7C[gActiveBank]].data[0]; + DestroyTask(gUnknown_03005D7C[gActiveBank]); + FreeAllWindowBuffers(); + sub_81B89AC(r4); + } +} + +extern u8 gUnknown_0203CEE8; +extern u8 gUnknown_0203CEE9; +extern u8 gUnknown_0203CF00[]; + +void sub_8059828(void) +{ + if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) + { + if (gUnknown_0203CEE8 == 1) + EmitCmd34(1, gUnknown_0203CEE9, gUnknown_0203CF00); + else + EmitCmd34(1, 6, NULL); + + if ((gBattleBufferA[gActiveBank][1] & 0xF) == 1) + PrintLinkStandbyMsg(); + + PlayerBufferExecCompleted(); + } +} + +extern void sub_81AABB0(void); +extern void nullsub_35(void); + +void sub_80598A4(void) +{ + if (!gPaletteFade.active) + { + gBattleBankFunc[gActiveBank] = sub_80598E0; + nullsub_35(); + FreeAllWindowBuffers(); + sub_81AABB0(); + } +} + +extern u16 gScriptItemId; + +void sub_80598E0(void) +{ + if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) + { + EmitCmd35(1, gScriptItemId); + PlayerBufferExecCompleted(); + } +} + +void sub_805991C(void) +{ + if (!gDoingBattleAnim || !gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x40) + PlayerBufferExecCompleted(); +} + +void DoHitAnimBlinkEffect(void) +{ + u8 spriteId = gBankSpriteIds[gActiveBank]; + + if (gSprites[spriteId].data1 == 32) + { + gSprites[spriteId].data1 = 0; + gSprites[spriteId].invisible = 0; + gDoingBattleAnim = FALSE; + PlayerBufferExecCompleted(); + } + else + { + if ((gSprites[spriteId].data1 % 4) == 0) + gSprites[spriteId].invisible ^= 1; + gSprites[spriteId].data1++; + } +} + +void sub_80599D4(void) +{ + if (gMain.newKeys & DPAD_UP && gMultiUsePlayerCursor != 0) + { + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gMultiUsePlayerCursor); + gMultiUsePlayerCursor = 0; + BattleCreateYesNoCursorAt(0); + } + if (gMain.newKeys & DPAD_DOWN && gMultiUsePlayerCursor == 0) + { + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gMultiUsePlayerCursor); + gMultiUsePlayerCursor = 1; + BattleCreateYesNoCursorAt(1); + } + if (gMain.newKeys & A_BUTTON) + { + sub_8056A3C(0x18, 8, 0x1D, 0xD, 1); + PlaySE(SE_SELECT); + + if (gMultiUsePlayerCursor != 0) + EmitCmd33(1, 0xE, 0); + else + EmitCmd33(1, 0xD, 0); + + PlayerBufferExecCompleted(); + } + if (gMain.newKeys & B_BUTTON) + { + sub_8056A3C(0x18, 8, 0x1D, 0xD, 1); + PlaySE(SE_SELECT); + PlayerBufferExecCompleted(); + } +} + +extern const u8 gText_MoveInterfacePP[]; +extern const u8 gText_MoveInterfaceType[]; + +void MoveSelectionDisplayMoveNames(void) +{ + s32 i; + struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleBufferA[gActiveBank][4]); + gNumberOfMovesToChoose = 0; + + for (i = 0; i < 4; i++) + { + MoveSelectionDestroyCursorAt(i); + StringCopy(gDisplayedStringBattle, gMoveNames[moveInfo->moves[i]]); + sub_814F9EC(gDisplayedStringBattle, i + 3); + if (moveInfo->moves[i] != MOVE_NONE) + gNumberOfMovesToChoose++; + } +} + +void MoveSelectionDisplayPpString(void) +{ + StringCopy(gDisplayedStringBattle, gText_MoveInterfacePP); + sub_814F9EC(gDisplayedStringBattle, 7); +} + +void MoveSelectionDisplayPpNumber(void) +{ + u8 *txtPtr; + struct ChooseMoveStruct *moveInfo; + + if (gBattleBufferA[gActiveBank][2] == TRUE) // check if we didn't want to display pp number + return; + + SetPpNumbersPaletteInMoveSelection(); + moveInfo = (struct ChooseMoveStruct*)(&gBattleBufferA[gActiveBank][4]); + txtPtr = ConvertIntToDecimalStringN(gDisplayedStringBattle, moveInfo->currentPp[gMoveSelectionCursor[gActiveBank]], STR_CONV_MODE_RIGHT_ALIGN, 2); + txtPtr[0] = CHAR_SLASH; + txtPtr++; + ConvertIntToDecimalStringN(txtPtr, moveInfo->maxPp[gMoveSelectionCursor[gActiveBank]], STR_CONV_MODE_RIGHT_ALIGN, 2); + + sub_814F9EC(gDisplayedStringBattle, 9); +} + +extern const u8 gTypeNames[][7]; + +void MoveSelectionDisplayMoveType(void) +{ + u8 *txtPtr; + struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleBufferA[gActiveBank][4]); + + txtPtr = StringCopy(gDisplayedStringBattle, gText_MoveInterfaceType); + txtPtr[0] = EXT_CTRL_CODE_BEGIN; + txtPtr++; + txtPtr[0] = 6; + txtPtr++; + txtPtr[0] = 1; + txtPtr++; + + StringCopy(txtPtr, gTypeNames[gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBank]]].type]); + sub_814F9EC(gDisplayedStringBattle, 10); +} + +void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 arg1) +{ + u16 src[2]; + src[0] = arg1 + 1; + src[1] = arg1 + 2; + + CopyToBgTilemapBufferRect_ChangePalette(0, src, 9 * (cursorPosition & 1) + 1, 55 + (cursorPosition & 2), 1, 2, 0x11); + CopyBgTilemapBufferToVram(0); +} + +void MoveSelectionDestroyCursorAt(u8 cursorPosition) +{ + u16 src[2]; + src[0] = 0x1016; + src[1] = 0x1016; + + CopyToBgTilemapBufferRect_ChangePalette(0, src, 9 * (cursorPosition & 1) + 1, 55 + (cursorPosition & 2), 1, 2, 0x11); + CopyBgTilemapBufferToVram(0); +} + +void ActionSelectionCreateCursorAt(u8 cursorPosition, u8 arg1) +{ + u16 src[2]; + src[0] = 1; + src[1] = 2; + + CopyToBgTilemapBufferRect_ChangePalette(0, src, 7 * (cursorPosition & 1) + 16, 35 + (cursorPosition & 2), 1, 2, 0x11); + CopyBgTilemapBufferToVram(0); +} + +void ActionSelectionDestroyCursorAt(u8 cursorPosition) +{ + u16 src[2]; + src[0] = 0x1016; + src[1] = 0x1016; + + CopyToBgTilemapBufferRect_ChangePalette(0, src, 7 * (cursorPosition & 1) + 16, 35 + (cursorPosition & 2), 1, 2, 0x11); + CopyBgTilemapBufferToVram(0); +} + +void SetCB2ToReshowScreenAfterMenu(void) +{ + SetMainCallback2(ReshowBattleScreenAfterMenu); +} + +void SetCB2ToReshowScreenAfterMenu2(void) +{ + SetMainCallback2(ReshowBattleScreenAfterMenu); +} + +void sub_8059D60(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x10) + PlayerBufferExecCompleted(); +} + +void sub_8059D90(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBank].flag_x20) + PlayerBufferExecCompleted(); +} + +extern const u8 gText_LinkStandby[]; + +void PrintLinkStandbyMsg(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gBattle_BG0_X = 0; + gBattle_BG0_Y = 0; + sub_814F9EC(gText_LinkStandby, 0); + } +} |