diff options
Diffstat (limited to 'src/battle_controller_opponent.c')
-rw-r--r-- | src/battle_controller_opponent.c | 1788 |
1 files changed, 1788 insertions, 0 deletions
diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c new file mode 100644 index 000000000..25c6ffcb9 --- /dev/null +++ b/src/battle_controller_opponent.c @@ -0,0 +1,1788 @@ +#include "global.h" +#include "bg.h" +#include "data2.h" +#include "item.h" +#include "link.h" +#include "main.h" +#include "m4a.h" +#include "task.h" +#include "text.h" +#include "util.h" +#include "window.h" +#include "palette.h" +#include "pokeball.h" +#include "pokemon.h" +#include "random.h" +#include "sound.h" +#include "string_util.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_controllers.h" +#include "battle_message.h" +#include "battle_interface.h" +#include "battle_setup.h" +#include "battle_tower.h" +#include "battle_gfx_sfx_util.h" +#include "battle_ai_script_commands.h" +#include "battle_ai_switch_items.h" +#include "trainer_tower.h" +#include "reshow_battle_screen.h" +#include "constants/battle_anim.h" +#include "constants/items.h" +#include "constants/moves.h" +#include "constants/songs.h" + +static void OpponentHandleGetMonData(void); +static void OpponentHandleGetRawMonData(void); +static void OpponentHandleSetMonData(void); +static void OpponentHandleSetRawMonData(void); +static void OpponentHandleLoadMonSprite(void); +static void OpponentHandleSwitchInAnim(void); +static void OpponentHandleReturnMonToBall(void); +static void OpponentHandleDrawTrainerPic(void); +static void OpponentHandleTrainerSlide(void); +static void OpponentHandleTrainerSlideBack(void); +static void OpponentHandleFaintAnimation(void); +static void OpponentHandlePaletteFade(void); +static void OpponentHandleSuccessBallThrowAnim(void); +static void OpponentHandleBallThrow(void); +static void OpponentHandlePause(void); +static void OpponentHandleMoveAnimation(void); +static void OpponentHandlePrintString(void); +static void OpponentHandlePrintSelectionString(void); +static void OpponentHandleChooseAction(void); +static void OpponentHandleUnknownYesNoBox(void); +static void OpponentHandleChooseMove(void); +static void OpponentHandleChooseItem(void); +static void OpponentHandleChoosePokemon(void); +static void OpponentHandleCmd23(void); +static void OpponentHandleHealthBarUpdate(void); +static void OpponentHandleExpUpdate(void); +static void OpponentHandleStatusIconUpdate(void); +static void OpponentHandleStatusAnimation(void); +static void OpponentHandleStatusXor(void); +static void OpponentHandleDataTransfer(void); +static void OpponentHandleDMA3Transfer(void); +static void OpponentHandlePlayBGM(void); +static void OpponentHandleCmd32(void); +static void OpponentHandleTwoReturnValues(void); +static void OpponentHandleChosenMonReturnValue(void); +static void OpponentHandleOneReturnValue(void); +static void OpponentHandleOneReturnValue_Duplicate(void); +static void OpponentHandleCmd37(void); +static void OpponentHandleCmd38(void); +static void OpponentHandleCmd39(void); +static void OpponentHandleCmd40(void); +static void OpponentHandleHitAnimation(void); +static void OpponentHandleCmd42(void); +static void OpponentHandlePlaySE(void); +static void OpponentHandlePlayFanfare(void); +static void OpponentHandleFaintingCry(void); +static void OpponentHandleIntroSlide(void); +static void OpponentHandleIntroTrainerBallThrow(void); +static void OpponentHandleDrawPartyStatusSummary(void); +static void OpponentHandleHidePartyStatusSummary(void); +static void OpponentHandleEndBounceEffect(void); +static void OpponentHandleSpriteInvisibility(void); +static void OpponentHandleBattleAnimation(void); +static void OpponentHandleLinkStandbyMsg(void); +static void OpponentHandleResetActionMoveSelection(void); +static void OpponentHandleCmd55(void); +static void OpponentCmdEnd(void); + +static void OpponentBufferRunCommand(void); +static u32 GetOpponentMonData(u8 monId, u8 *dst); +static void SetOpponentMonData(u8 monId); +static void DoSwitchOutAnimation(void); +static void OpponentDoMoveAnimation(void); +static void sub_80362E8(void); +static void sub_8037A28(u8 battlerId, bool8 dontClearSubstituteBit); +static void sub_8038DC4(u8 taskId); +static void sub_8038D90(struct Sprite *sprite); +static void sub_8038FBC(void); + +static void (*const sOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(void) = +{ + OpponentHandleGetMonData, + OpponentHandleGetRawMonData, + OpponentHandleSetMonData, + OpponentHandleSetRawMonData, + OpponentHandleLoadMonSprite, + OpponentHandleSwitchInAnim, + OpponentHandleReturnMonToBall, + OpponentHandleDrawTrainerPic, + OpponentHandleTrainerSlide, + OpponentHandleTrainerSlideBack, + OpponentHandleFaintAnimation, + OpponentHandlePaletteFade, + OpponentHandleSuccessBallThrowAnim, + OpponentHandleBallThrow, + OpponentHandlePause, + OpponentHandleMoveAnimation, + OpponentHandlePrintString, + OpponentHandlePrintSelectionString, + OpponentHandleChooseAction, + OpponentHandleUnknownYesNoBox, + OpponentHandleChooseMove, + OpponentHandleChooseItem, + OpponentHandleChoosePokemon, + OpponentHandleCmd23, + OpponentHandleHealthBarUpdate, + OpponentHandleExpUpdate, + OpponentHandleStatusIconUpdate, + OpponentHandleStatusAnimation, + OpponentHandleStatusXor, + OpponentHandleDataTransfer, + OpponentHandleDMA3Transfer, + OpponentHandlePlayBGM, + OpponentHandleCmd32, + OpponentHandleTwoReturnValues, + OpponentHandleChosenMonReturnValue, + OpponentHandleOneReturnValue, + OpponentHandleOneReturnValue_Duplicate, + OpponentHandleCmd37, + OpponentHandleCmd38, + OpponentHandleCmd39, + OpponentHandleCmd40, + OpponentHandleHitAnimation, + OpponentHandleCmd42, + OpponentHandlePlaySE, + OpponentHandlePlayFanfare, + OpponentHandleFaintingCry, + OpponentHandleIntroSlide, + OpponentHandleIntroTrainerBallThrow, + OpponentHandleDrawPartyStatusSummary, + OpponentHandleHidePartyStatusSummary, + OpponentHandleEndBounceEffect, + OpponentHandleSpriteInvisibility, + OpponentHandleBattleAnimation, + OpponentHandleLinkStandbyMsg, + OpponentHandleResetActionMoveSelection, + OpponentHandleCmd55, + OpponentCmdEnd +}; + +// not used +static const u8 gUnknown_8250B18[] = { 0xB0, 0xB0, 0xC8, 0x98, 0x28, 0x28, 0x28, 0x20 }; + +static void nullsub_17(void) +{ +} + +void SetControllerToOpponent(void) +{ + gBattlerControllerFuncs[gActiveBattler] = OpponentBufferRunCommand; +} + +static void OpponentBufferRunCommand(void) +{ + if (gBattleControllerExecFlags & gBitTable[gActiveBattler]) + { + if (gBattleBufferA[gActiveBattler][0] < ARRAY_COUNT(sOpponentBufferCommands)) + sOpponentBufferCommands[gBattleBufferA[gActiveBattler][0]](); + else + OpponentBufferExecCompleted(); + } +} + +static void CompleteOnBattlerSpriteCallbackDummy(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + OpponentBufferExecCompleted(); +} + +static void CompleteOnBattlerSpriteCallbackDummy2(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + OpponentBufferExecCompleted(); +} + +static void sub_8035B58(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + { + FreeTrainerFrontPicPaletteAndTile(gSprites[gBattlerSpriteIds[gActiveBattler]].oam.affineParam); + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.tileNum = gSprites[gBattlerSpriteIds[gActiveBattler]].data[5]; + FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + OpponentBufferExecCompleted(); + } +} + +static void sub_8035BE8(void) +{ + if (--gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_9 == 0xFF) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_9 = 0; + OpponentBufferExecCompleted(); + } +} + +static void sub_8035C30(void) +{ + bool8 var = FALSE; + + if (!IsDoubleBattle() || ((IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI)))) + { + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + var = TRUE; + } + else if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy + && gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]].callback == gSprites[gHealthboxSpriteIds[gActiveBattler]].callback) + { + var = TRUE; + } + if (IsCryPlayingOrClearCrySongs()) + var = FALSE; + if (var && gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 && gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].field_1_x1) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].field_1_x1 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + m4aMPlayContinue(&gMPlayInfo_BGM); + else + m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 256); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_9 = 3; + gBattlerControllerFuncs[gActiveBattler] = sub_8035BE8; + } +} + +static void sub_8035DF0(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive) + sub_80F1720(gActiveBattler, &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]); + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].flag_x80 && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].ballAnimActive) + sub_80F1720(gActiveBattler ^ BIT_FLANK, &gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]]); + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].ballAnimActive) + { + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + DestroySprite(&gSprites[gUnknown_3004FFC[gActiveBattler ^ BIT_FLANK]]); + UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK], + &gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], + HEALTHBOX_ALL); + sub_804BD94(gActiveBattler ^ BIT_FLANK); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]); + SetBattlerShadowSpriteCallback(gActiveBattler ^ BIT_FLANK, GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], MON_DATA_SPECIES)); + } + DestroySprite(&gSprites[gUnknown_3004FFC[gActiveBattler]]); + UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], + &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], + HEALTHBOX_ALL); + sub_804BD94(gActiveBattler); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]); + SetBattlerShadowSpriteCallback(gActiveBattler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES)); + gBattleSpritesDataPtr->animationData->field_9_x1 = 0; + gBattlerControllerFuncs[gActiveBattler] = sub_8035C30; + } +} + +static void sub_8035FE8(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].animEnded == TRUE + && gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x == 0) + { + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80) + { + sub_80F1720(gActiveBattler, &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]); + } + else if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + OpponentBufferExecCompleted(); + } + } +} + +static void CompleteOnHealthbarDone(void) +{ + s16 hpValue = MoveBattleBar(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], HEALTH_BAR, 0); + + SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]); + if (hpValue != -1) + { + UpdateHpTextInHealthbox(gHealthboxSpriteIds[gActiveBattler], hpValue, HP_CURRENT); + } + else + { + if (!sub_80EB2E0(1) && (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)) + { + sub_80EB2F4(1); + gBattlerControllerFuncs[gActiveBattler] = sub_80E8570; + } + else + { + OpponentBufferExecCompleted(); + } + } +} + +static void sub_803612C(void) +{ + if (!gSprites[gBattlerSpriteIds[gActiveBattler]].inUse) + { + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]); + OpponentBufferExecCompleted(); + } +} + +static void sub_8036170(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + HideBattlerShadowSprite(gActiveBattler); + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]); + OpponentBufferExecCompleted(); + } +} + +static void CompleteOnInactiveTextPrinter(void) +{ + if (!IsTextPrinterActive(0)) + OpponentBufferExecCompleted(); +} + +static void DoHitAnimBlinkSpriteEffect(void) +{ + u8 spriteId = gBattlerSpriteIds[gActiveBattler]; + + if (gSprites[spriteId].data[1] == 32) + { + gSprites[spriteId].data[1] = 0; + gSprites[spriteId].invisible = FALSE; + gDoingBattleAnim = FALSE; + OpponentBufferExecCompleted(); + } + else + { + if ((gSprites[spriteId].data[1] % 4) == 0) + gSprites[spriteId].invisible ^= 1; + ++gSprites[spriteId].data[1]; + } +} + +static void sub_8036278(void) +{ + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + { + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute) + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_MON_TO_SUBSTITUTE); + gBattlerControllerFuncs[gActiveBattler] = sub_80362E8; + } +} + +static void sub_80362E8(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive && !IsCryPlayingOrClearCrySongs()) + { + m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100); + OpponentBufferExecCompleted(); + } +} + +static void sub_8036334(void) +{ + if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[gActiveBattler]], 0); + UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_ALL); + sub_804BD94(gActiveBattler); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]); + CopyBattleSpriteInvisibility(gActiveBattler); + gBattlerControllerFuncs[gActiveBattler] = sub_8036278; + } +} + +static void sub_8036408(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive) + sub_80F1720(gActiveBattler, &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]); + if (gSprites[gUnknown_3004FFC[gActiveBattler]].callback == SpriteCallbackDummy + && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive) + { + DestroySprite(&gSprites[gUnknown_3004FFC[gActiveBattler]]); + SetBattlerShadowSpriteCallback(gActiveBattler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES)); + gBattlerControllerFuncs[gActiveBattler] = sub_8036334; + } +} + +static void CompleteOnFinishedStatusAnimation(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive) + OpponentBufferExecCompleted(); +} + +static void CompleteOnFinishedBattleAnimation(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animFromTableActive) + OpponentBufferExecCompleted(); +} + +void OpponentBufferExecCompleted(void) +{ + gBattlerControllerFuncs[gActiveBattler] = OpponentBufferRunCommand; + gBattleControllerExecFlags &= ~gBitTable[gActiveBattler]; +} + +static void OpponentHandleGetMonData(void) +{ + u8 monData[sizeof(struct Pokemon) * 2 + 56]; // this allows to get full data of two pokemon, trying to get more will result in overwriting data + u32 size = 0; + u8 monToCheck; + s32 i; + + if (!gBattleBufferA[gActiveBattler][2]) + { + size += GetOpponentMonData(gBattlerPartyIndexes[gActiveBattler], monData); + } + else + { + monToCheck = gBattleBufferA[gActiveBattler][2]; + for (i = 0; i < PARTY_SIZE; ++i) + { + if (monToCheck & 1) + size += GetOpponentMonData(i, monData + size); + monToCheck >>= 1; + } + } + BtlController_EmitDataTransfer(1, size, monData); + OpponentBufferExecCompleted(); +} + +static u32 GetOpponentMonData(u8 monId, u8 *dst) +{ + struct BattlePokemon battleMon; + struct MovePpInfo moveData; + u8 nickname[20]; + u8 *src; + s16 data16; + u32 data32; + s32 size = 0; + + switch (gBattleBufferA[gActiveBattler][1]) + { + case REQUEST_ALL_BATTLE: + battleMon.species = GetMonData(&gEnemyParty[monId], MON_DATA_SPECIES); + battleMon.item = GetMonData(&gEnemyParty[monId], MON_DATA_HELD_ITEM); + for (size = 0; size < MAX_MON_MOVES; ++size) + { + battleMon.moves[size] = GetMonData(&gEnemyParty[monId], MON_DATA_MOVE1 + size); + battleMon.pp[size] = GetMonData(&gEnemyParty[monId], MON_DATA_PP1 + size); + } + battleMon.ppBonuses = GetMonData(&gEnemyParty[monId], MON_DATA_PP_BONUSES); + battleMon.friendship = GetMonData(&gEnemyParty[monId], MON_DATA_FRIENDSHIP); + battleMon.experience = GetMonData(&gEnemyParty[monId], MON_DATA_EXP); + battleMon.hpIV = GetMonData(&gEnemyParty[monId], MON_DATA_HP_IV); + battleMon.attackIV = GetMonData(&gEnemyParty[monId], MON_DATA_ATK_IV); + battleMon.defenseIV = GetMonData(&gEnemyParty[monId], MON_DATA_DEF_IV); + battleMon.speedIV = GetMonData(&gEnemyParty[monId], MON_DATA_SPEED_IV); + battleMon.spAttackIV = GetMonData(&gEnemyParty[monId], MON_DATA_SPATK_IV); + battleMon.spDefenseIV = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF_IV); + battleMon.personality = GetMonData(&gEnemyParty[monId], MON_DATA_PERSONALITY); + battleMon.status1 = GetMonData(&gEnemyParty[monId], MON_DATA_STATUS); + battleMon.level = GetMonData(&gEnemyParty[monId], MON_DATA_LEVEL); + battleMon.hp = GetMonData(&gEnemyParty[monId], MON_DATA_HP); + battleMon.maxHP = GetMonData(&gEnemyParty[monId], MON_DATA_MAX_HP); + battleMon.attack = GetMonData(&gEnemyParty[monId], MON_DATA_ATK); + battleMon.defense = GetMonData(&gEnemyParty[monId], MON_DATA_DEF); + battleMon.speed = GetMonData(&gEnemyParty[monId], MON_DATA_SPEED); + battleMon.spAttack = GetMonData(&gEnemyParty[monId], MON_DATA_SPATK); + battleMon.spDefense = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF); + battleMon.isEgg = GetMonData(&gEnemyParty[monId], MON_DATA_IS_EGG); + battleMon.abilityNum = GetMonData(&gEnemyParty[monId], MON_DATA_ABILITY_NUM); + battleMon.otId = GetMonData(&gEnemyParty[monId], MON_DATA_OT_ID); + GetMonData(&gEnemyParty[monId], MON_DATA_NICKNAME, nickname); + StringCopy10(battleMon.nickname, nickname); + GetMonData(&gEnemyParty[monId], MON_DATA_OT_NAME, battleMon.otName); + src = (u8 *)&battleMon; + for (size = 0; size < sizeof(battleMon); ++size) + dst[size] = src[size]; + break; + case REQUEST_SPECIES_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_SPECIES); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_HELDITEM_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_HELD_ITEM); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_MOVES_PP_BATTLE: + for (size = 0; size < MAX_MON_MOVES; ++size) + { + moveData.moves[size] = GetMonData(&gEnemyParty[monId], MON_DATA_MOVE1 + size); + moveData.pp[size] = GetMonData(&gEnemyParty[monId], MON_DATA_PP1 + size); + } + moveData.ppBonuses = GetMonData(&gEnemyParty[monId], MON_DATA_PP_BONUSES); + src = (u8*)(&moveData); + for (size = 0; size < sizeof(moveData); ++size) + dst[size] = src[size]; + break; + case REQUEST_MOVE1_BATTLE: + case REQUEST_MOVE2_BATTLE: + case REQUEST_MOVE3_BATTLE: + case REQUEST_MOVE4_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_MOVE1 + gBattleBufferA[gActiveBattler][1] - REQUEST_MOVE1_BATTLE); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_PP_DATA_BATTLE: + for (size = 0; size < MAX_MON_MOVES; ++size) + dst[size] = GetMonData(&gEnemyParty[monId], MON_DATA_PP1 + size); + dst[size] = GetMonData(&gEnemyParty[monId], MON_DATA_PP_BONUSES); + ++size; + break; + case REQUEST_PPMOVE1_BATTLE: + case REQUEST_PPMOVE2_BATTLE: + case REQUEST_PPMOVE3_BATTLE: + case REQUEST_PPMOVE4_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_PP1 + gBattleBufferA[gActiveBattler][1] - REQUEST_PPMOVE1_BATTLE); + size = 1; + break; + case REQUEST_OTID_BATTLE: + data32 = GetMonData(&gEnemyParty[monId], MON_DATA_OT_ID); + dst[0] = (data32 & 0x000000FF); + dst[1] = (data32 & 0x0000FF00) >> 8; + dst[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case REQUEST_EXP_BATTLE: + data32 = GetMonData(&gEnemyParty[monId], MON_DATA_EXP); + dst[0] = (data32 & 0x000000FF); + dst[1] = (data32 & 0x0000FF00) >> 8; + dst[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case REQUEST_HP_EV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_HP_EV); + size = 1; + break; + case REQUEST_ATK_EV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_ATK_EV); + size = 1; + break; + case REQUEST_DEF_EV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_DEF_EV); + size = 1; + break; + case REQUEST_SPEED_EV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SPEED_EV); + size = 1; + break; + case REQUEST_SPATK_EV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SPATK_EV); + size = 1; + break; + case REQUEST_SPDEF_EV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF_EV); + size = 1; + break; + case REQUEST_FRIENDSHIP_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_FRIENDSHIP); + size = 1; + break; + case REQUEST_POKERUS_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_POKERUS); + size = 1; + break; + case REQUEST_MET_LOCATION_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_MET_LOCATION); + size = 1; + break; + case REQUEST_MET_LEVEL_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_MET_LEVEL); + size = 1; + break; + case REQUEST_MET_GAME_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_MET_GAME); + size = 1; + break; + case REQUEST_POKEBALL_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_POKEBALL); + size = 1; + break; + case REQUEST_ALL_IVS_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_HP_IV); + dst[1] = GetMonData(&gEnemyParty[monId], MON_DATA_ATK_IV); + dst[2] = GetMonData(&gEnemyParty[monId], MON_DATA_DEF_IV); + dst[3] = GetMonData(&gEnemyParty[monId], MON_DATA_SPEED_IV); + dst[4] = GetMonData(&gEnemyParty[monId], MON_DATA_SPATK_IV); + dst[5] = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF_IV); + size = 6; + break; + case REQUEST_HP_IV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_HP_IV); + size = 1; + break; + case REQUEST_ATK_IV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_ATK_IV); + size = 1; + break; + case REQUEST_DEF_IV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_DEF_IV); + size = 1; + break; + case REQUEST_SPEED_IV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SPEED_IV); + size = 1; + break; + case REQUEST_SPATK_IV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SPATK_IV); + size = 1; + break; + case REQUEST_SPDEF_IV_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF_IV); + size = 1; + break; + case REQUEST_PERSONALITY_BATTLE: + data32 = GetMonData(&gEnemyParty[monId], MON_DATA_PERSONALITY); + dst[0] = (data32 & 0x000000FF); + dst[1] = (data32 & 0x0000FF00) >> 8; + dst[2] = (data32 & 0x00FF0000) >> 16; + dst[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case REQUEST_CHECKSUM_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_CHECKSUM); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_STATUS_BATTLE: + data32 = GetMonData(&gEnemyParty[monId], MON_DATA_STATUS); + dst[0] = (data32 & 0x000000FF); + dst[1] = (data32 & 0x0000FF00) >> 8; + dst[2] = (data32 & 0x00FF0000) >> 16; + dst[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case REQUEST_LEVEL_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_LEVEL); + size = 1; + break; + case REQUEST_HP_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_HP); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_MAX_HP_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_MAX_HP); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_ATK_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_ATK); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_DEF_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_DEF); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_SPEED_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_SPEED); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_SPATK_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_SPATK); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_SPDEF_BATTLE: + data16 = GetMonData(&gEnemyParty[monId], MON_DATA_SPDEF); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_COOL_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_COOL); + size = 1; + break; + case REQUEST_BEAUTY_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_BEAUTY); + size = 1; + break; + case REQUEST_CUTE_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_CUTE); + size = 1; + break; + case REQUEST_SMART_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SMART); + size = 1; + break; + case REQUEST_TOUGH_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_TOUGH); + size = 1; + break; + case REQUEST_SHEEN_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SHEEN); + size = 1; + break; + case REQUEST_COOL_RIBBON_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_COOL_RIBBON); + size = 1; + break; + case REQUEST_BEAUTY_RIBBON_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_BEAUTY_RIBBON); + size = 1; + break; + case REQUEST_CUTE_RIBBON_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_CUTE_RIBBON); + size = 1; + break; + case REQUEST_SMART_RIBBON_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_SMART_RIBBON); + size = 1; + break; + case REQUEST_TOUGH_RIBBON_BATTLE: + dst[0] = GetMonData(&gEnemyParty[monId], MON_DATA_TOUGH_RIBBON); + size = 1; + break; + } + return size; +} + +static void OpponentHandleGetRawMonData(void) +{ + struct BattlePokemon battleMon; + u8 *src = (u8 *)&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]] + gBattleBufferA[gActiveBattler][1]; + u8 *dst = (u8 *)&battleMon + gBattleBufferA[gActiveBattler][1]; + u8 i; + + for (i = 0; i < gBattleBufferA[gActiveBattler][2]; ++i) + dst[i] = src[i]; + BtlController_EmitDataTransfer(1, gBattleBufferA[gActiveBattler][2], dst); + OpponentBufferExecCompleted(); +} + +static void OpponentHandleSetMonData(void) +{ + u8 monToCheck; + u8 i; + + if (gBattleBufferA[gActiveBattler][2] == 0) + { + SetOpponentMonData(gBattlerPartyIndexes[gActiveBattler]); + } + else + { + monToCheck = gBattleBufferA[gActiveBattler][2]; + for (i = 0; i < PARTY_SIZE; ++i) + { + if (monToCheck & 1) + SetOpponentMonData(i); + monToCheck >>= 1; + } + } + OpponentBufferExecCompleted(); +} + +static void SetOpponentMonData(u8 monId) +{ + struct BattlePokemon *battlePokemon = (struct BattlePokemon *)&gBattleBufferA[gActiveBattler][3]; + struct MovePpInfo *moveData = (struct MovePpInfo *)&gBattleBufferA[gActiveBattler][3]; + s32 i; + + switch (gBattleBufferA[gActiveBattler][1]) + { + case REQUEST_ALL_BATTLE: + { + u8 iv; + + SetMonData(&gEnemyParty[monId], MON_DATA_SPECIES, &battlePokemon->species); + SetMonData(&gEnemyParty[monId], MON_DATA_HELD_ITEM, &battlePokemon->item); + for (i = 0; i < MAX_MON_MOVES; ++i) + { + SetMonData(&gEnemyParty[monId], MON_DATA_MOVE1 + i, &battlePokemon->moves[i]); + SetMonData(&gEnemyParty[monId], MON_DATA_PP1 + i, &battlePokemon->pp[i]); + } + SetMonData(&gEnemyParty[monId], MON_DATA_PP_BONUSES, &battlePokemon->ppBonuses); + SetMonData(&gEnemyParty[monId], MON_DATA_FRIENDSHIP, &battlePokemon->friendship); + SetMonData(&gEnemyParty[monId], MON_DATA_EXP, &battlePokemon->experience); + iv = battlePokemon->hpIV; + SetMonData(&gEnemyParty[monId], MON_DATA_HP_IV, &iv); + iv = battlePokemon->attackIV; + SetMonData(&gEnemyParty[monId], MON_DATA_ATK_IV, &iv); + iv = battlePokemon->defenseIV; + SetMonData(&gEnemyParty[monId], MON_DATA_DEF_IV, &iv); + iv = battlePokemon->speedIV; + SetMonData(&gEnemyParty[monId], MON_DATA_SPEED_IV, &iv); + iv = battlePokemon->spAttackIV; + SetMonData(&gEnemyParty[monId], MON_DATA_SPATK_IV, &iv); + iv = battlePokemon->spDefenseIV; + SetMonData(&gEnemyParty[monId], MON_DATA_SPDEF_IV, &iv); + SetMonData(&gEnemyParty[monId], MON_DATA_PERSONALITY, &battlePokemon->personality); + SetMonData(&gEnemyParty[monId], MON_DATA_STATUS, &battlePokemon->status1); + SetMonData(&gEnemyParty[monId], MON_DATA_LEVEL, &battlePokemon->level); + SetMonData(&gEnemyParty[monId], MON_DATA_HP, &battlePokemon->hp); + SetMonData(&gEnemyParty[monId], MON_DATA_MAX_HP, &battlePokemon->maxHP); + SetMonData(&gEnemyParty[monId], MON_DATA_ATK, &battlePokemon->attack); + SetMonData(&gEnemyParty[monId], MON_DATA_DEF, &battlePokemon->defense); + SetMonData(&gEnemyParty[monId], MON_DATA_SPEED, &battlePokemon->speed); + SetMonData(&gEnemyParty[monId], MON_DATA_SPATK, &battlePokemon->spAttack); + SetMonData(&gEnemyParty[monId], MON_DATA_SPDEF, &battlePokemon->spDefense); + } + break; + case REQUEST_SPECIES_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPECIES, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_HELDITEM_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_HELD_ITEM, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MOVES_PP_BATTLE: + for (i = 0; i < MAX_MON_MOVES; ++i) + { + SetMonData(&gEnemyParty[monId], MON_DATA_MOVE1 + i, &moveData->moves[i]); + SetMonData(&gEnemyParty[monId], MON_DATA_PP1 + i, &moveData->pp[i]); + } + SetMonData(&gEnemyParty[monId], MON_DATA_PP_BONUSES, &moveData->ppBonuses); + break; + case REQUEST_MOVE1_BATTLE: + case REQUEST_MOVE2_BATTLE: + case REQUEST_MOVE3_BATTLE: + case REQUEST_MOVE4_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_MOVE1 + gBattleBufferA[gActiveBattler][1] - REQUEST_MOVE1_BATTLE, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_PP_DATA_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_PP1, &gBattleBufferA[gActiveBattler][3]); + SetMonData(&gEnemyParty[monId], MON_DATA_PP2, &gBattleBufferA[gActiveBattler][4]); + SetMonData(&gEnemyParty[monId], MON_DATA_PP3, &gBattleBufferA[gActiveBattler][5]); + SetMonData(&gEnemyParty[monId], MON_DATA_PP4, &gBattleBufferA[gActiveBattler][6]); + SetMonData(&gEnemyParty[monId], MON_DATA_PP_BONUSES, &gBattleBufferA[gActiveBattler][7]); + break; + case REQUEST_PPMOVE1_BATTLE: + case REQUEST_PPMOVE2_BATTLE: + case REQUEST_PPMOVE3_BATTLE: + case REQUEST_PPMOVE4_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_PP1 + gBattleBufferA[gActiveBattler][1] - REQUEST_PPMOVE1_BATTLE, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_OTID_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_OT_ID, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_EXP_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_EXP, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_HP_EV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_HP_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_ATK_EV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_ATK_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_DEF_EV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_DEF_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPEED_EV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPEED_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPATK_EV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPATK_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPDEF_EV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPDEF_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_FRIENDSHIP_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_FRIENDSHIP, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_POKERUS_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_POKERUS, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MET_LOCATION_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_MET_LOCATION, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MET_LEVEL_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_MET_LEVEL, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MET_GAME_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_MET_GAME, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_POKEBALL_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_POKEBALL, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_ALL_IVS_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_HP_IV, &gBattleBufferA[gActiveBattler][3]); + SetMonData(&gEnemyParty[monId], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBattler][4]); + SetMonData(&gEnemyParty[monId], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBattler][5]); + SetMonData(&gEnemyParty[monId], MON_DATA_SPEED_IV, &gBattleBufferA[gActiveBattler][6]); + SetMonData(&gEnemyParty[monId], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBattler][7]); + SetMonData(&gEnemyParty[monId], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBattler][8]); + break; + case REQUEST_HP_IV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_HP_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_ATK_IV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_DEF_IV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPEED_IV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPEED_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPATK_IV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPDEF_IV_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_PERSONALITY_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_PERSONALITY, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_CHECKSUM_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_CHECKSUM, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_STATUS_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_STATUS, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_LEVEL_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_LEVEL, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_HP_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_HP, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MAX_HP_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_MAX_HP, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_ATK_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_ATK, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_DEF_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_DEF, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPEED_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPEED, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPATK_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPATK, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPDEF_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SPDEF, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_COOL_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_COOL, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_BEAUTY_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_BEAUTY, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_CUTE_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_CUTE, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SMART_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SMART, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_TOUGH_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_TOUGH, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SHEEN_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SHEEN, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_COOL_RIBBON_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_COOL_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_BEAUTY_RIBBON_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_BEAUTY_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_CUTE_RIBBON_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_CUTE_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SMART_RIBBON_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_SMART_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_TOUGH_RIBBON_BATTLE: + SetMonData(&gEnemyParty[monId], MON_DATA_TOUGH_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + } +} + +static void OpponentHandleSetRawMonData(void) +{ + u8 *dst = (u8 *)&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]] + gBattleBufferA[gActiveBattler][1]; + u8 i; + + for (i = 0; i < gBattleBufferA[gActiveBattler][2]; ++i) + dst[i] = gBattleBufferA[gActiveBattler][3 + i]; + OpponentBufferExecCompleted(); +} + +static void OpponentHandleLoadMonSprite(void) +{ + u16 species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES); + u32 y; + + if (gBattleTypeFlags & BATTLE_TYPE_GHOST) + { + DecompressGhostFrontPic(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); + y = GetGhostSpriteDefault_Y(gActiveBattler); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 = 1; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 = 1; + } + else + { + BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); + y = GetBattlerSpriteDefault_Y(gActiveBattler); + } + SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(gActiveBattler)); + gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate, + GetBattlerSpriteCoord(gActiveBattler, 2), + y, + GetBattlerSpriteSubpriority(gActiveBattler)); + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = -240; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = gActiveBattler; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[2] = species; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = gActiveBattler; + StartSpriteAnim(&gSprites[gBattlerSpriteIds[gActiveBattler]], gBattleMonForms[gActiveBattler]); + if (!(gBattleTypeFlags & BATTLE_TYPE_GHOST)) + SetBattlerShadowSpriteCallback(gActiveBattler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES)); + gBattlerControllerFuncs[gActiveBattler] = sub_8035FE8; +} + +static void OpponentHandleSwitchInAnim(void) +{ + *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = 6; + gBattlerPartyIndexes[gActiveBattler] = gBattleBufferA[gActiveBattler][1]; + sub_8037A28(gActiveBattler, gBattleBufferA[gActiveBattler][2]); + gBattlerControllerFuncs[gActiveBattler] = sub_8036408; +} + +static void sub_8037A28(u8 battlerId, bool8 dontClearSubstituteBit) +{ + u16 species; + + ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_3004FFC[battlerId] = CreateInvisibleSpriteWithCallback(sub_8033E3C); + BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId); + SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(battlerId)); + gBattlerSpriteIds[battlerId] = CreateSprite(&gMultiuseSpriteTemplate, + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + GetBattlerSpriteSubpriority(battlerId)); + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gUnknown_3004FFC[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; + gSprites[gUnknown_3004FFC[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_OPPONENT_SENDOUT); +} + +static void OpponentHandleReturnMonToBall(void) +{ + if (!gBattleBufferA[gActiveBattler][1]) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; + gBattlerControllerFuncs[gActiveBattler] = DoSwitchOutAnimation; + } + else + { + FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + HideBattlerShadowSprite(gActiveBattler); + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]); + OpponentBufferExecCompleted(); + } +} + +static void DoSwitchOutAnimation(void) +{ + switch (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState) + { + case 0: + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute) + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SUBSTITUTE_TO_MON); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 1; + break; + case 1: + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SWITCH_OUT_OPPONENT_MON); + gBattlerControllerFuncs[gActiveBattler] = sub_8036170; + } + break; + } +} + +static void OpponentHandleDrawTrainerPic(void) +{ + u32 trainerPicId; + + if (gTrainerBattleOpponent_A == 0x400) + trainerPicId = GetSecretBaseTrainerPicIndex(); + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + trainerPicId = GetBattleTowerTrainerFrontSpriteId(); + else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER) + trainerPicId = GetTrainerTowerTrainerFrontSpriteId(); + else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) + trainerPicId = GetEreaderTrainerFrontSpriteId(); + else + trainerPicId = gTrainers[gTrainerBattleOpponent_A].trainerPic; + DecompressTrainerFrontPic(trainerPicId, gActiveBattler); + SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(gActiveBattler)); + gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate, + 176, + (8 - gTrainerFrontPicCoords[trainerPicId].size) * 4 + 40, + GetBattlerSpriteSubpriority(gActiveBattler)); + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = -240; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = 2; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerFrontPicPaletteTable[trainerPicId].tag); + gSprites[gBattlerSpriteIds[gActiveBattler]].data[5] = gSprites[gBattlerSpriteIds[gActiveBattler]].oam.tileNum; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.tileNum = GetSpriteTileStartByTag(gTrainerFrontPicTable[trainerPicId].tag); + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.affineParam = trainerPicId; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8033EEC; + gBattlerControllerFuncs[gActiveBattler] = CompleteOnBattlerSpriteCallbackDummy; +} + +static void OpponentHandleTrainerSlide(void) +{ + u32 trainerPicId; + + if (gTrainerBattleOpponent_A == 0x400) + trainerPicId = GetSecretBaseTrainerPicIndex(); + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + trainerPicId = GetBattleTowerTrainerFrontSpriteId(); + else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER) + trainerPicId = GetTrainerTowerTrainerFrontSpriteId(); + else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) + trainerPicId = GetEreaderTrainerFrontSpriteId(); + else + trainerPicId = gTrainers[gTrainerBattleOpponent_A].trainerPic; + DecompressTrainerFrontPic(trainerPicId, gActiveBattler); + SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(gActiveBattler)); + gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate, + 176, + (8 - gTrainerFrontPicCoords[trainerPicId].size) * 4 + 40, + 30); + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = 96; + gSprites[gBattlerSpriteIds[gActiveBattler]].pos1.x += 32; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = -2; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerFrontPicPaletteTable[trainerPicId].tag); + gSprites[gBattlerSpriteIds[gActiveBattler]].data[5] = gSprites[gBattlerSpriteIds[gActiveBattler]].oam.tileNum; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.tileNum = GetSpriteTileStartByTag(gTrainerFrontPicTable[trainerPicId].tag); + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.affineParam = trainerPicId; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8033EEC; + gBattlerControllerFuncs[gActiveBattler] = CompleteOnBattlerSpriteCallbackDummy2; +} + +static void OpponentHandleTrainerSlideBack(void) +{ + SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = 35; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[2] = 280; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[4] = gSprites[gBattlerSpriteIds[gActiveBattler]].pos1.y; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[gActiveBattler]], SpriteCallbackDummy); + gBattlerControllerFuncs[gActiveBattler] = sub_8035B58; +} + +static void OpponentHandleFaintAnimation(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState) + { + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute) + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SUBSTITUTE_TO_MON); + ++gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState; + } + else + { + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; + PlaySE12WithPanning(SE_POKE_DEAD, SOUND_PAN_TARGET); + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = SpriteCB_FaintOpponentMon; + gBattlerControllerFuncs[gActiveBattler] = sub_803612C; + } + } +} + +static void OpponentHandlePaletteFade(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleSuccessBallThrowAnim(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleBallThrow(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandlePause(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleMoveAnimation(void) +{ + if (!mplay_80342A4(gActiveBattler)) + { + u16 move = gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8); + + gAnimMoveTurn = gBattleBufferA[gActiveBattler][3]; + gAnimMovePower = gBattleBufferA[gActiveBattler][4] | (gBattleBufferA[gActiveBattler][5] << 8); + gAnimMoveDmg = gBattleBufferA[gActiveBattler][6] | (gBattleBufferA[gActiveBattler][7] << 8) | (gBattleBufferA[gActiveBattler][8] << 16) | (gBattleBufferA[gActiveBattler][9] << 24); + gAnimFriendship = gBattleBufferA[gActiveBattler][10]; + gWeatherMoveAnim = gBattleBufferA[gActiveBattler][12] | (gBattleBufferA[gActiveBattler][13] << 8); + gAnimDisableStructPtr = (struct DisableStruct *)&gBattleBufferA[gActiveBattler][16]; + gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + if (IsMoveWithoutAnimation(move, gAnimMoveTurn)) // always returns FALSE + { + OpponentBufferExecCompleted(); + } + else + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; + gBattlerControllerFuncs[gActiveBattler] = OpponentDoMoveAnimation; + } + } +} + +static void OpponentDoMoveAnimation(void) +{ + u16 move = gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8); + u8 multihit = gBattleBufferA[gActiveBattler][11]; + + switch (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState) + { + case 0: + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute + && !gBattleSpritesDataPtr->battlerData[gActiveBattler].flag_x8) + { + gBattleSpritesDataPtr->battlerData[gActiveBattler].flag_x8 = 1; + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SUBSTITUTE_TO_MON); + } + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 1; + break; + case 1: + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + sub_8035450(0); + DoMoveAnim(move); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 2; + } + break; + case 2: + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + sub_8035450(1); + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute && multihit < 2) + { + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_MON_TO_SUBSTITUTE); + gBattleSpritesDataPtr->battlerData[gActiveBattler].flag_x8 = 0; + } + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 3; + } + break; + case 3: + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + CopyAllBattleSpritesInvisibilities(); + TrySetBehindSubstituteSpriteBit(gActiveBattler, gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8)); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; + OpponentBufferExecCompleted(); + } + break; + } +} + +static void OpponentHandlePrintString(void) +{ + u16 *stringId; + + gBattle_BG0_X = 0; + gBattle_BG0_Y = 0; + stringId = (u16 *)(&gBattleBufferA[gActiveBattler][2]); + BufferStringBattle(*stringId); + if (sub_80D89B0(*stringId)) + BattlePutTextOnWindow(gDisplayedStringBattle, 0x40); + else + BattlePutTextOnWindow(gDisplayedStringBattle, 0); + if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) + { + switch (*stringId) + { + case 0x17F: + gBattlerControllerFuncs[gActiveBattler] = sub_80E85C0; + return; + case 0xE3: + gBattlerControllerFuncs[gActiveBattler] = sub_80E8598; + return; + } + } + gBattlerControllerFuncs[gActiveBattler] = CompleteOnInactiveTextPrinter; +} + +static void OpponentHandlePrintSelectionString(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleChooseAction(void) +{ + AI_TrySwitchOrUseItem(); + OpponentBufferExecCompleted(); +} + +static void OpponentHandleUnknownYesNoBox(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleChooseMove(void) +{ + u8 chosenMoveId; + struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleBufferA[gActiveBattler][4]); + + if (gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER)) + { + + BattleAI_SetupAIData(); + chosenMoveId = BattleAI_GetAIActionToUse(); + + switch (chosenMoveId) + { + case AI_CHOICE_WATCH: + BtlController_EmitTwoReturnValues(1, B_ACTION_SAFARI_WATCH_CAREFULLY, 0); + break; + case AI_CHOICE_FLEE: + BtlController_EmitTwoReturnValues(1, B_ACTION_RUN, 0); + break; + default: + if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) + gBattlerTarget = gActiveBattler; + if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH) + { + gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); + } + BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gBattlerTarget << 8)); + break; + } + OpponentBufferExecCompleted(); + } + else + { + u16 move; + + do + { + chosenMoveId = Random() & 3; + move = moveInfo->moves[chosenMoveId]; + } + while (move == MOVE_NONE); + if (gBattleMoves[move].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) + BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gActiveBattler << 8)); + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (GetBattlerAtPosition(Random() & 2) << 8)); + else + BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) << 8)); + + OpponentBufferExecCompleted(); + } +} + +static void OpponentHandleChooseItem(void) +{ + BtlController_EmitOneReturnValue(1, *(gBattleStruct->chosenItem + (gActiveBattler / 2) * 2)); + OpponentBufferExecCompleted(); +} + +static void OpponentHandleChoosePokemon(void) +{ + s32 chosenMonId; + + if (*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) == PARTY_SIZE) + { + chosenMonId = GetMostSuitableMonToSwitchInto(); + + if (chosenMonId == PARTY_SIZE) + { + s32 battler1, battler2; + + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + battler2 = battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + } + else + { + battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + battler2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + } + for (chosenMonId = 0; chosenMonId < 6; ++chosenMonId) + if (GetMonData(&gEnemyParty[chosenMonId], MON_DATA_HP) != 0 + && chosenMonId != gBattlerPartyIndexes[battler1] + && chosenMonId != gBattlerPartyIndexes[battler2]) + break; + } + } + else + { + chosenMonId = *(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)); + *(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE; + } + *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; + BtlController_EmitChosenMonReturnValue(1, chosenMonId, NULL); + OpponentBufferExecCompleted(); +} + +static void OpponentHandleCmd23(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleHealthBarUpdate(void) +{ + s16 hpVal; + + LoadBattleBarGfx(0); + hpVal = (gBattleBufferA[gActiveBattler][3] << 8) | gBattleBufferA[gActiveBattler][2]; + + if (hpVal != INSTANT_HP_BAR_DROP) + { + u32 maxHP = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MAX_HP); + u32 curHP = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_HP); + + SetBattleBarStruct(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], maxHP, curHP, hpVal); + } + else + { + u32 maxHP = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MAX_HP); + + SetBattleBarStruct(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], maxHP, 0, hpVal); + } + gBattlerControllerFuncs[gActiveBattler] = CompleteOnHealthbarDone; +} + +static void OpponentHandleExpUpdate(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleStatusIconUpdate(void) +{ + if (!mplay_80342A4(gActiveBattler)) + { + u8 battlerId; + + UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; + gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; + } +} + +static void OpponentHandleStatusAnimation(void) +{ + if (!mplay_80342A4(gActiveBattler)) + { + InitAndLaunchChosenStatusAnimation(gBattleBufferA[gActiveBattler][1], + gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8) | (gBattleBufferA[gActiveBattler][4] << 16) | (gBattleBufferA[gActiveBattler][5] << 24)); + gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; + } +} + +static void OpponentHandleStatusXor(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleDataTransfer(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleDMA3Transfer(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandlePlayBGM(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleCmd32(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleTwoReturnValues(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleChosenMonReturnValue(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleOneReturnValue(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleOneReturnValue_Duplicate(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleCmd37(void) +{ + gUnknown_2022870.field_0 = 0; + OpponentBufferExecCompleted(); +} + +static void OpponentHandleCmd38(void) +{ + gUnknown_2022870.field_0 = gBattleBufferA[gActiveBattler][1]; + OpponentBufferExecCompleted(); +} + +static void OpponentHandleCmd39(void) +{ + gUnknown_2022870.flag_x80 = 0; + OpponentBufferExecCompleted(); +} + +static void OpponentHandleCmd40(void) +{ + gUnknown_2022870.flag_x80 ^= 1; + OpponentBufferExecCompleted(); +} + +static void OpponentHandleHitAnimation(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].invisible == TRUE) + { + OpponentBufferExecCompleted(); + } + else + { + gDoingBattleAnim = TRUE; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[1] = 0; + DoHitAnimHealthboxEffect(gActiveBattler); + gBattlerControllerFuncs[gActiveBattler] = DoHitAnimBlinkSpriteEffect; + } +} + +static void OpponentHandleCmd42(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandlePlaySE(void) +{ + s8 pan; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + pan = SOUND_PAN_ATTACKER; + else + pan = SOUND_PAN_TARGET; + PlaySE12WithPanning(gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8), pan); + OpponentBufferExecCompleted(); +} + +static void OpponentHandlePlayFanfare(void) +{ + PlayFanfare(gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8)); + OpponentBufferExecCompleted(); +} + +static void OpponentHandleFaintingCry(void) +{ + u16 species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES); + + PlayCry3(species, 25, 5); + OpponentBufferExecCompleted(); +} + +static void OpponentHandleIntroSlide(void) +{ + HandleIntroSlide(gBattleBufferA[gActiveBattler][1]); + gIntroSlideFlags |= 1; + OpponentBufferExecCompleted(); +} + +static void OpponentHandleIntroTrainerBallThrow(void) +{ + u8 paletteNum; + u8 taskId; + + SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = 35; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[2] = 280; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[4] = gSprites[gBattlerSpriteIds[gActiveBattler]].pos1.y; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[gActiveBattler]], sub_8038D90); + taskId = CreateTask(sub_8038DC4, 5); + gTasks[taskId].data[0] = gActiveBattler; + if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].partyStatusSummaryShown) + gTasks[gBattlerStatusSummaryTaskId[gActiveBattler]].func = Task_HidePartyStatusSummary; + gBattleSpritesDataPtr->animationData->field_9_x1 = 1; + gBattlerControllerFuncs[gActiveBattler] = nullsub_17; +} + +static void sub_8038D90(struct Sprite *sprite) +{ + FreeTrainerFrontPicPaletteAndTile(sprite->oam.affineParam); + sprite->oam.tileNum = sprite->data[5]; + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); +} + +static void sub_8038DC4(u8 taskId) +{ + u8 savedActiveBattler = gActiveBattler; + + gActiveBattler = gTasks[taskId].data[0]; + if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + gBattleBufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; + sub_8037A28(gActiveBattler, FALSE); + } + else + { + gBattleBufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; + sub_8037A28(gActiveBattler, FALSE); + gActiveBattler ^= BIT_FLANK; + gBattleBufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; + sub_8037A28(gActiveBattler, FALSE); + gActiveBattler ^= BIT_FLANK; + } + gBattlerControllerFuncs[gActiveBattler] = sub_8035DF0; + gActiveBattler = savedActiveBattler; + DestroyTask(taskId); +} + +static void OpponentHandleDrawPartyStatusSummary(void) +{ + if (gBattleBufferA[gActiveBattler][1] && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + OpponentBufferExecCompleted(); + } + else + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].partyStatusSummaryShown = 1; + if (gBattleBufferA[gActiveBattler][2]) + { + if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1E <= 1) + { + ++gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1E; + return; + } + else + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1E = 0; + } + } + gBattlerStatusSummaryTaskId[gActiveBattler] = CreatePartyStatusSummarySprites(gActiveBattler, + (struct HpAndStatus *)&gBattleBufferA[gActiveBattler][4], + gBattleBufferA[gActiveBattler][1], + gBattleBufferA[gActiveBattler][2]); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_5 = 0; + if (gBattleBufferA[gActiveBattler][2]) + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_5 = 0x5D; + gBattlerControllerFuncs[gActiveBattler] = sub_8038FBC; + } +} + +static void sub_8038FBC(void) +{ + if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_5++ > 0x5C) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_5 = 0; + OpponentBufferExecCompleted(); + } +} + +static void OpponentHandleHidePartyStatusSummary(void) +{ + if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].partyStatusSummaryShown) + gTasks[gBattlerStatusSummaryTaskId[gActiveBattler]].func = Task_HidePartyStatusSummary; + OpponentBufferExecCompleted(); +} + +static void OpponentHandleEndBounceEffect(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleSpriteInvisibility(void) +{ + if (IsBattlerSpritePresent(gActiveBattler)) + { + gSprites[gBattlerSpriteIds[gActiveBattler]].invisible = gBattleBufferA[gActiveBattler][1]; + CopyBattleSpriteInvisibility(gActiveBattler); + } + OpponentBufferExecCompleted(); +} + +static void OpponentHandleBattleAnimation(void) +{ + if (!mplay_80342A4(gActiveBattler)) + { + u8 animationId = gBattleBufferA[gActiveBattler][1]; + u16 argument = gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8); + + if (TryHandleLaunchBattleTableAnimation(gActiveBattler, gActiveBattler, gActiveBattler, animationId, argument)) + OpponentBufferExecCompleted(); + else + gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedBattleAnimation; + } +} + +static void OpponentHandleLinkStandbyMsg(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleResetActionMoveSelection(void) +{ + OpponentBufferExecCompleted(); +} + +static void OpponentHandleCmd55(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_LINK && !(gBattleTypeFlags & BATTLE_TYPE_IS_MASTER)) + { + gMain.inBattle = 0; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } + OpponentBufferExecCompleted(); +} + +static void OpponentCmdEnd(void) +{ +} |