diff options
Diffstat (limited to 'src/battle')
28 files changed, 55459 insertions, 0 deletions
diff --git a/src/battle/battle_2.c b/src/battle/battle_2.c new file mode 100644 index 000000000..770aa1209 --- /dev/null +++ b/src/battle/battle_2.c @@ -0,0 +1,2442 @@ +#include "global.h" +#include "abilities.h" +#include "battle.h" +#include "battle_interface.h" +#include "battle_setup.h" +#include "data2.h" +#include "item.h" +#include "link.h" +#include "main.h" +#include "name_string_util.h" +#include "palette.h" +#include "party_menu.h" +#include "pokeball.h" +#include "pokedex.h" +#include "pokemon.h" +#include "rng.h" +#include "rom3.h" +#include "rom_8077ABC.h" +#include "rom_8094928.h" +#include "songs.h" +#include "sound.h" +#include "species.h" +#include "sprite.h" +#include "task.h" +#include "text.h" +#include "trig.h" +#include "unknown_task.h" +#include "util.h" +#include "items.h" +#include "hold_effects.h" +#include "battle_move_effects.h" + +struct UnknownStruct6 +{ + u16 unk0[0xA0]; + u8 fillerA0[0x640]; + u16 unk780[0xA0]; +}; + +struct UnknownStruct7 +{ + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; +}; + +struct UnknownStruct8 +{ + u8 unk0[7]; + u8 unk7; + u8 unk8[18]; + u8 unk1A; +}; + +struct UnknownPokemonStruct2 +{ + /*0x00*/ u16 species; + /*0x02*/ u16 heldItem; + /*0x04*/ u8 nickname[11]; + /*0x0F*/ u8 level; + /*0x10*/ u16 hp; + /*0x12*/ u16 maxhp; + /*0x14*/ u32 status; + /*0x18*/ u32 personality; + /*0x1C*/ u8 gender; + /*0x1D*/ u8 language; +}; + +struct UnknownStruct12 +{ + u32 unk0; + u8 filler4[0x54]; +}; + +extern const u16 gUnknown_08D004E0[]; +extern const struct MonCoords gCastformFrontSpriteCoords[]; + +extern u8 ewram[]; +#define ewram0 (*(struct UnknownStruct7 *)(ewram + 0x0)) +#define ewram4 (*(struct UnknownStruct8 *)(ewram + 0x4)) +#define ewram16000 (ewram[0x16000]) +#define ewram16001 (ewram[0x16001]) +#define ewram16002 (ewram[0x16002]) +#define ewram16003 (ewram[0x16003]) +#define ewram1600C (ewram[0x1600C]) +#define ewram1600E (ewram[0x1600E]) +#define ewram1601B (ewram[0x1601B]) +#define ewram16020 ((u8 *)(ewram + 0x16020)) +#define ewram16056 (ewram[0x16056]) +#define ewram16058 (ewram[0x16058]) +#define ewram16059 (ewram[0x16059]) +#define ewram16078 (ewram[0x16078]) +#define ewram16084 (ewram[0x16084]) +#define ewram16086 (ewram[0x16086]) +#define ewram16087 (ewram[0x16087]) +#define ewram16088 (ewram[0x16088]) +#define ewram16089 (ewram[0x16089]) +#define ewram160A1 (ewram[0x160A1]) +#define ewram160A6 (ewram[0x160A6]) +#define ewram160AC ((u8 *)(ewram + 0x160AC)) +#define ewram160BC ((u16 *)(ewram + 0x160BC)) // hp +#define ewram160C8 (ewram[0x160C8]) +#define ewram160C9 (ewram[0x160C9]) +#define ewram160CB (ewram[0x160CB]) +#define ewram160CC ((u8 *)(ewram + 0x160CC)) +#define ewram160E6 (ewram[0x160E6]) +#define ewram160E8 ((u8 *)(ewram + 0x160E8)) +#define ewram160F0 ((u8 *)(ewram + 0x160F0)) +#define ewram160F9 (ewram[0x160F9]) +#define ewram16100 ((u8 *)(ewram + 0x16100)) +#define ewram16108 ((u8 *)(ewram + 0x16108)) +#define ewram16110 (ewram[0x16110]) +#define ewram16111 (ewram[0x16111]) +#define ewram16113 (ewram[0x16113]) +#define ewram17100 ((u32 *)(ewram + 0x17100)) +#define ewram17130 (ewram[0x17130]) +#define ewram17160 (ewram[0x17160]) +#define ewram1D000 ((struct Pokemon *)(ewram + 0x1D000)) + +extern struct UnknownPokemonStruct2 gUnknown_02023A00[]; +extern u8 gBattleBufferB[][0x200]; +extern u8 gActiveBank; +extern u32 gBattleExecBuffer; +extern u8 gNoOfAllBanks; +extern u16 gBattlePartyID[]; +extern u8 gFightStateTracker; +extern u8 gTurnOrder[]; +extern struct UnknownStruct12 gUnknown_02024AD0[]; +extern u8 gObjectBankIDs[]; +extern u16 gCurrentMove; +extern u8 gLastUsedAbility; +extern u8 gStringBank; +extern u8 gAbsentBankFlags; +extern u8 gMultiHitCounter; +extern u8 gActionForBanks[]; +extern u16 gUnknown_02024C2C[]; +extern u16 gLastUsedMove[]; +extern u16 gMoveHitWith[]; +extern u16 gUnknown_02024C44[]; +extern u16 gUnknown_02024C4C[]; +extern u16 gLockedMove[]; +extern u8 gUnknown_02024C5C[]; +extern u16 gChosenMovesByBanks[]; +extern u32 gHitMarker; +extern u8 gUnknown_02024C70[]; +extern u16 gSideAffecting[]; +extern u32 gStatuses3[]; +//extern u8 gDisableStructs[][0x1C]; +extern u16 gPauseCounterBattle; +extern u16 gPaydayMoney; +extern u16 gRandomTurnNumber; +extern u8 gBattleCommunication[]; +extern u8 gUnknown_02024D1F[]; // I don't actually know what type this is. +extern u8 gBattleOutcome; +extern u16 gUnknown_02024DE8; +extern u8 gActionSelectionCursor[]; +extern u8 gMoveSelectionCursor[]; +extern u8 gUnknown_02038470[]; +extern u16 gUnknown_030041B0; +extern u16 gUnknown_030041B4; +extern u16 gUnknown_030041B8; +extern struct Window gUnknown_030041D0; +extern u16 gUnknown_03004200; +extern struct Window gUnknown_03004210; +extern u16 gUnknown_03004244; +extern struct Window gUnknown_03004250; +extern u16 gUnknown_03004240; +extern u16 gUnknown_03004280; +extern u32 gUnknown_03004284; +extern u16 gUnknown_03004288; +extern u16 gUnknown_030042A0; +extern u16 gUnknown_030042A4; +extern u16 gUnknown_030042C0; +extern u16 gUnknown_030042C4; +extern MainCallback gPreBattleCallback1; +extern void (*gBattleMainFunc)(void); +extern u8 gLeveledUpInBattle; +extern void (*gBattleBankFunc[])(void); +extern u8 gHealthboxIDs[]; +extern struct UnknownStruct6 gUnknown_03004DE0; +//extern u16 gUnknown_03004DE0[][0xA0]; // possibly? +extern u16 gBattleTypeFlags; +extern s8 gBattleTerrain; // I'm not sure if this is supposed to be s8 or u8. Regardless, it must have the same type as the return value of BattleSetup_GetTerrain. +extern u8 gReservedSpritePaletteCount; +extern u16 gTrainerBattleOpponent; +extern struct BattleEnigmaBerry gEnigmaBerries[]; +extern u16 gBlockRecvBuffer[MAX_LINK_PLAYERS][BLOCK_BUFFER_SIZE / 2]; +extern u8 gBattleMonForms[]; +extern u8 gBankAttacker; +extern u8 gBankTarget; +extern u16 gBattleWeather; +extern u32 gBattleMoveDamage; +extern struct BattlePokemon gBattleMons[]; +extern u8 gBattleMoveFlags; + +static void BattlePrepIntroSlide(void); + +void sub_800E7C4(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + sub_800B858(); + SetMainCallback2(sub_800F104); + gBattleCommunication[0] = 0; + } + else + { + InitBattle(); + } +} + +void InitBattle(void) +{ + s32 i; + + SetHBlankCallback(NULL); + SetVBlankCallback(NULL); + + CpuFill32(0, (void *)VRAM, VRAM_SIZE); + + REG_MOSAIC = 0; + REG_WIN0H = 0xF0; + REG_WIN0V = 0x5051; + REG_WININ = 0; + REG_WINOUT = 0; + gUnknown_030042C4 = 0xF0; + gUnknown_03004240 = 0x5051; + dp12_8087EA4(); + + for (i = 0; i < 80; i++) + { + gUnknown_03004DE0.unk0[i] = 0xF0; + gUnknown_03004DE0.unk780[i] = 0xF0; + } + for (i = 80; i < 160; i++) + { + asm(""::"r"(i)); // Needed to stop the compiler from optimizing out the loop counter + gUnknown_03004DE0.unk0[i] = 0xFF10; + gUnknown_03004DE0.unk780[i] = 0xFF10; + } + //sub_80895F8(gUnknown_081F9674.unk0, gUnknown_081F9674.unk4, gUnknown_081F9674.unk8); + sub_80895F8(gUnknown_081F9674); + SetUpWindowConfig(&gWindowConfig_81E6C58); + ResetPaletteFade(); + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + gUnknown_030042C0 = 0; + gUnknown_030041B4 = 0; + gUnknown_03004288 = 0; + gUnknown_03004280 = 0; + gUnknown_030041B0 = 0; + gUnknown_030041B8 = 0; + gBattleTerrain = BattleSetup_GetTerrain(); + InitWindowFromConfig(&gUnknown_03004210, &gWindowConfig_81E6C58); + InitWindowFromConfig(&gUnknown_030041D0, &gWindowConfig_81E71D0); + InitWindowFromConfig(&gUnknown_03004250, &gWindowConfig_81E71EC); + sub_800D6D4(); + sub_800DAB8(); + ResetSpriteData(); + ResetTasks(); + sub_800E23C(); + FreeAllSpritePalettes(); + gReservedSpritePaletteCount = 4; + SetVBlankCallback(sub_800FCFC); + setup_poochyena_battle(); + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + SetMainCallback2(sub_800F298); + else + SetMainCallback2(sub_800EC9C); + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)) + { + CreateNPCTrainerParty(gEnemyParty, gTrainerBattleOpponent); + SetWildMonHeldItem(); + } + gMain.inBattle = TRUE; + for (i = 0; i < 6; i++) + AdjustFriendship(&gPlayerParty[i], 3); + gBattleCommunication[0] = 0; +} + +void sub_800E9EC(void) +{ + u16 r6 = 0; + u16 species; + u16 hp; + u32 status; + s32 i; + + for (i = 0; i < 6; i++) + { + species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2); + hp = GetMonData(&gPlayerParty[i], MON_DATA_HP); + status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS); + + if (species == 0) + continue; + if (species != SPECIES_EGG && hp != 0 && status == 0) + r6 |= 1 << i * 2; + + if (species == 0) + continue; + if (hp != 0 && (species == SPECIES_EGG || status != 0)) + r6 |= 2 << i * 2; + + if (species == 0) + continue; + if (species != SPECIES_EGG && hp == 0) + r6 |= 3 << i * 2; + } + ewram0.unk2 = r6; + ewram0.unk3 = r6 >> 8; +} + +void sub_800EAAC(void) +{ + s32 i; + struct UnknownStruct8 *_ewram4 = &ewram4; + + for (i = 0; i < 7; i++) + _ewram4->unk0[i] = gSaveBlock1.enigmaBerry.berry.name[i]; + for (i = 0; i < 18; i++) + _ewram4->unk8[i] = gSaveBlock1.enigmaBerry.itemEffect[i]; + _ewram4->unk7 = gSaveBlock1.enigmaBerry.holdEffect; + _ewram4->unk1A = gSaveBlock1.enigmaBerry.holdEffectParam; +} + +void sub_800EB08(void) +{ + s32 i; + s32 j; + + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)) + { + for (i = 0; i < 7; i++) + { + gEnigmaBerries[0].name[i] = gSaveBlock1.enigmaBerry.berry.name[i]; + gEnigmaBerries[2].name[i] = gSaveBlock1.enigmaBerry.berry.name[i]; + } + for (i = 0; i < 18; i++) + { + gEnigmaBerries[0].itemEffect[i] = gSaveBlock1.enigmaBerry.itemEffect[i]; + gEnigmaBerries[2].itemEffect[i] = gSaveBlock1.enigmaBerry.itemEffect[i]; + } + gEnigmaBerries[0].holdEffect = gSaveBlock1.enigmaBerry.holdEffect; + gEnigmaBerries[2].holdEffect = gSaveBlock1.enigmaBerry.holdEffect; + gEnigmaBerries[0].holdEffectParam = gSaveBlock1.enigmaBerry.holdEffectParam; + gEnigmaBerries[2].holdEffectParam = gSaveBlock1.enigmaBerry.holdEffectParam; + } + else + { + s32 numPlayers; + struct BattleEnigmaBerry *src; + u8 r4; + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + numPlayers = 4; + else + numPlayers = 2; + for (i = 0; i < numPlayers; i++) + { + src = (struct BattleEnigmaBerry *)(gBlockRecvBuffer[i] + 2); + r4 = gLinkPlayers[i].lp_field_18; + + for (j = 0; j < 7; j++) + gEnigmaBerries[r4].name[j] = src->name[j]; + for (j = 0; j < 18; j++) + gEnigmaBerries[r4].itemEffect[j] = src->itemEffect[j]; + gEnigmaBerries[r4].holdEffect = src->holdEffect; + gEnigmaBerries[r4].holdEffectParam = src->holdEffectParam; + } + } +} + +void shedinja_something(struct Pokemon *pkmn) +{ + u8 nickname[POKEMON_NAME_LENGTH + 1]; + u8 language = 1; + + if (GetMonData(pkmn, MON_DATA_SPECIES) == SPECIES_SHEDINJA + && GetMonData(pkmn, MON_DATA_LANGUAGE) != language) + { + GetMonData(pkmn, MON_DATA_NICKNAME, nickname); + if (StringCompareWithoutExtCtrlCodes(nickname, gUnknown_081F96C8) == 0) + SetMonData(pkmn, MON_DATA_LANGUAGE, &language); + } +} + +void sub_800EC9C(void) +{ + u8 playerId; + u8 enemyId; + + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + playerId = GetMultiplayerId(); + ewram160CB = playerId; + enemyId = playerId ^ 1; + + switch (gBattleCommunication[0]) + { + case 0: + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + if (gReceivedRemoteLinkPlayers != 0 && sub_8007ECC()) + { + ewram0.unk0 = 1; + ewram0.unk1 = 1; + sub_800E9EC(); + sub_800EAAC(); + SendBlock(bitmask_all_link_players_but_self(), &ewram0, 32); + gBattleCommunication[0] = 1; + } + } + else + { + gBattleTypeFlags |= BATTLE_TYPE_WILD; + gBattleCommunication[0] = 8; + sub_800EB08(); + } + break; + case 1: + if ((GetBlockReceivedStatus() & 3) == 3) + { + s32 id; + u8 taskId; + + ResetBlockReceivedFlags(); + id = 0; + if (gBlockRecvBuffer[0][0] == 0x100) + { + if (playerId == 0) + gBattleTypeFlags |= 12; + else + gBattleTypeFlags |= 8; + id++; + } + if (id == 0) + { + if (gBlockRecvBuffer[0][0] == gBlockRecvBuffer[1][0]) + { + if (playerId == 0) + gBattleTypeFlags |= 12; + else + gBattleTypeFlags |= 8; + id++; + } + if (id == 0) + { + while (id < 2) + { + if (gBlockRecvBuffer[id][0] > 0x0101 && id != playerId) + break; + id++; + } + if (id == 2) + gBattleTypeFlags |= 12; + else + gBattleTypeFlags |= 8; + } + } + sub_800EB08(); + taskId = CreateTask(sub_800DE30, 0); + gTasks[taskId].data[1] = 0x10E; + gTasks[taskId].data[2] = 0x5A; + gTasks[taskId].data[5] = 0; + gTasks[taskId].data[3] = ewram0.unk2 | (ewram0.unk3 << 8); + gTasks[taskId].data[4] = gBlockRecvBuffer[enemyId][1]; + gBattleCommunication[0]++; + } + break; + case 2: + if (sub_8007ECC()) + { + SendBlock(bitmask_all_link_players_but_self(), gPlayerParty, sizeof(*gPlayerParty) * 2); + gBattleCommunication[0]++; + } + break; + case 3: + if ((GetBlockReceivedStatus() & 3) == 3) + { + ResetBlockReceivedFlags(); + memcpy(gEnemyParty, gBlockRecvBuffer[enemyId], sizeof(*gEnemyParty) * 2); + gBattleCommunication[0]++; + } + break; + case 4: + if (sub_8007ECC()) + { + SendBlock(bitmask_all_link_players_but_self(), gPlayerParty + 2, sizeof(*gPlayerParty) * 2); + gBattleCommunication[0]++; + } + break; + case 5: + if ((GetBlockReceivedStatus() & 3) == 3) + { + ResetBlockReceivedFlags(); + memcpy(gEnemyParty + 2, gBlockRecvBuffer[enemyId], sizeof(*gEnemyParty) * 2); + gBattleCommunication[0]++; + } + break; + case 6: + if (sub_8007ECC()) + { + SendBlock(bitmask_all_link_players_but_self(), gPlayerParty + 4, sizeof(*gPlayerParty) * 2); + gBattleCommunication[0]++; + } + break; + case 7: + if ((GetBlockReceivedStatus() & 3) == 3) + { + ResetBlockReceivedFlags(); + memcpy(gEnemyParty + 4, gBlockRecvBuffer[enemyId], sizeof(*gEnemyParty) * 2); + shedinja_something(&gEnemyParty[0]); + shedinja_something(&gEnemyParty[1]); + shedinja_something(&gEnemyParty[2]); + shedinja_something(&gEnemyParty[3]); + shedinja_something(&gEnemyParty[4]); + shedinja_something(&gEnemyParty[5]); + gBattleCommunication[0]++; + } + break; + case 8: + sub_800B950(); + gBattleCommunication[0]++; + gBattleCommunication[1] = 0; + gBattleCommunication[2] = 0; + break; + case 9: + if (battle_load_something(gUnknown_02024D1F, gUnknown_02024D1F + 1) != 0) + { + gPreBattleCallback1 = gMain.callback1; + gMain.callback1 = sub_8010824; + SetMainCallback2(sub_800F808); + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gTrainerBattleOpponent = 0x800; + gBattleTypeFlags |= BATTLE_TYPE_20; + } + } + break; + } +} + +void sub_800F02C(void) +{ + s32 i; + + for (i = 0; i < 3; i++) + { + u8 *nickname = gUnknown_02023A00[i].nickname; + + gUnknown_02023A00[i].species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES); + gUnknown_02023A00[i].heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); + GetMonData(&gPlayerParty[i], MON_DATA_NICKNAME, nickname); + gUnknown_02023A00[i].level = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL); + gUnknown_02023A00[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP); + gUnknown_02023A00[i].maxhp = GetMonData(&gPlayerParty[i], MON_DATA_MAX_HP); + gUnknown_02023A00[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS); + gUnknown_02023A00[i].personality = GetMonData(&gPlayerParty[i], MON_DATA_PERSONALITY); + gUnknown_02023A00[i].gender = GetMonGender(&gPlayerParty[i]); + StripExtCtrlCodes(nickname); + gUnknown_02023A00[i].language = GetMonData(&gPlayerParty[i], MON_DATA_LANGUAGE); + if (gUnknown_02023A00[i].language != 1) + PadNameString(nickname, 0); + } + memcpy(ewram, gUnknown_02023A00, 0x60); +} + +void sub_800F104(void) +{ + u8 playerId; + MainCallback *pSavedCallback; + u16 *pSavedBattleTypeFlags; + + playerId = GetMultiplayerId(); + ewram160CB = playerId; + // Seriously, Game Freak? + pSavedCallback = (MainCallback *)(ewram + 0x160C4); + pSavedBattleTypeFlags = (u16 *)(ewram + 0x160C2); + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + + switch (gBattleCommunication[0]) + { + case 0: + if (gReceivedRemoteLinkPlayers != 0 && sub_8007ECC()) + { + sub_800F02C(); + SendBlock(bitmask_all_link_players_but_self(), ewram, 0x60); + gBattleCommunication[0]++; + } + break; + case 1: + if ((GetBlockReceivedStatus() & 0xF) == 0xF) + { + s32 i; + + ResetBlockReceivedFlags(); + for (i = 0; i < 4; i++) + { + if (i != playerId) + { + if ((!(gLinkPlayers[i].lp_field_18 & 1) && !(gLinkPlayers[playerId].lp_field_18 & 1)) + || ((gLinkPlayers[i].lp_field_18 & 1) && (gLinkPlayers[playerId].lp_field_18 & 1))) + memcpy(gUnknown_02023A00, gBlockRecvBuffer[i], 0x60); + } + } + gBattleCommunication[0]++; + *pSavedCallback = gMain.savedCallback; + *pSavedBattleTypeFlags = gBattleTypeFlags; + gMain.savedCallback = sub_800F104; + OpenPartyMenu(5, 0); + } + break; + case 2: + if (!gPaletteFade.active) + { + gBattleCommunication[0] = 3; + sub_800832C(); + } + break; + case 3: + if (gReceivedRemoteLinkPlayers == 0) + { + gBattleTypeFlags = *pSavedBattleTypeFlags; + gMain.savedCallback = *pSavedCallback; + SetMainCallback2(InitBattle); + } + break; + } +} + +void sub_800F298(void) +{ + u8 playerId; + s32 id; + + playerId = GetMultiplayerId(); + ewram160CB = playerId; + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + switch (gBattleCommunication[0]) + { + case 0: + if (gReceivedRemoteLinkPlayers != 0 && sub_8007ECC()) + { + ewram0.unk0 = 1; + ewram0.unk1 = 1; + sub_800E9EC(); + sub_800EAAC(); + SendBlock(bitmask_all_link_players_but_self(), ewram, 0x20); + gBattleCommunication[0]++; + } + break; + case 1: + if ((GetBlockReceivedStatus() & 0xF) == 0xF) + { + u8 taskId; + + ResetBlockReceivedFlags(); + id = 0; + if (gBlockRecvBuffer[0][0] == 0x100) + { + if (playerId == 0) + gBattleTypeFlags |= 12; + else + gBattleTypeFlags |= 8; + id++; + } + if (id == 0) + { + s32 i; + + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + if (gBlockRecvBuffer[0][0] != gBlockRecvBuffer[i][0]) + break; + } + if (i == MAX_LINK_PLAYERS) + { + if (playerId == 0) + gBattleTypeFlags |= 12; + else + gBattleTypeFlags |= 8; + id++; + } + if (id == 0) + { + while (id < MAX_LINK_PLAYERS) + { + if (gBlockRecvBuffer[id][0] == 0x0101 && id != playerId) + if (id < playerId) + break; + if (gBlockRecvBuffer[id][0] > 0x0101 && id != playerId) + break; + id++; + } + if (id == MAX_LINK_PLAYERS) + gBattleTypeFlags |= 12; + else + gBattleTypeFlags |= 8; + } + } + sub_800EB08(); + memcpy(ewram1D000, gPlayerParty, sizeof(struct Pokemon) * 3); + taskId = CreateTask(sub_800DE30, 0); + gTasks[taskId].data[1] = 0x10E; + gTasks[taskId].data[2] = 0x5A; + gTasks[taskId].data[5] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = 0; + for (id = 0; id < MAX_LINK_PLAYERS; id++) + { + switch (gLinkPlayers[id].lp_field_18) + { + case 0: + gTasks[taskId].data[3] |= gBlockRecvBuffer[id][1] & 0x3F; + break; + case 1: + gTasks[taskId].data[4] |= gBlockRecvBuffer[id][1] & 0x3F; + break; + case 2: + gTasks[taskId].data[3] |= (gBlockRecvBuffer[id][1] & 0x3F) << 6; + break; + case 3: + gTasks[taskId].data[4] |= (gBlockRecvBuffer[id][1] & 0x3F) << 6; + break; + } + } + ZeroPlayerPartyMons(); + ZeroEnemyPartyMons(); + gBattleCommunication[0]++; + goto step_2; + } + break; + case 2: + step_2: + if (sub_8007ECC()) + { + SendBlock(bitmask_all_link_players_but_self(), ewram1D000, sizeof(struct Pokemon) * 2); + gBattleCommunication[0]++; + } + break; + case 3: + if ((GetBlockReceivedStatus() & 0xF) == 0xF) + { + ResetBlockReceivedFlags(); + for (id = 0; id < MAX_LINK_PLAYERS; id++) + { + if (id == playerId) + { + switch (gLinkPlayers[id].lp_field_18) + { + case 0: + case 3: + memcpy(gPlayerParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2); + break; + case 1: + case 2: + memcpy(gPlayerParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2); + break; + } + } + else + { + if ((!(gLinkPlayers[id].lp_field_18 & 1) && !(gLinkPlayers[playerId].lp_field_18 & 1)) + || ((gLinkPlayers[id].lp_field_18 & 1) && (gLinkPlayers[playerId].lp_field_18 & 1))) + { + switch (gLinkPlayers[id].lp_field_18) + { + case 0: + case 3: + memcpy(gPlayerParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2); + break; + case 1: + case 2: + memcpy(gPlayerParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2); + break; + } + } + else + { + switch (gLinkPlayers[id].lp_field_18) + { + case 0: + case 3: + memcpy(gEnemyParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2); + break; + case 1: + case 2: + memcpy(gEnemyParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2); + break; + } + } + } + } + gBattleCommunication[0]++; + } + break; + case 4: + if (sub_8007ECC()) + { + SendBlock(bitmask_all_link_players_but_self(), ewram1D000 + 2, sizeof(struct Pokemon)); + gBattleCommunication[0]++; + } + break; + case 5: + if ((GetBlockReceivedStatus() & 0xF) == 0xF) + { + ResetBlockReceivedFlags(); + for (id = 0; id < MAX_LINK_PLAYERS; id++) + { + if (id == playerId) + { + switch (gLinkPlayers[id].lp_field_18) + { + case 0: + case 3: + memcpy(gPlayerParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon)); + break; + case 1: + case 2: + memcpy(gPlayerParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon)); + break; + } + } + else + { + if ((!(gLinkPlayers[id].lp_field_18 & 1) && !(gLinkPlayers[playerId].lp_field_18 & 1)) + || ((gLinkPlayers[id].lp_field_18 & 1) && (gLinkPlayers[playerId].lp_field_18 & 1))) + { + switch (gLinkPlayers[id].lp_field_18) + { + case 0: + case 3: + memcpy(gPlayerParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon)); + break; + case 1: + case 2: + memcpy(gPlayerParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon)); + break; + } + } + else + { + switch (gLinkPlayers[id].lp_field_18) + { + case 0: + case 3: + memcpy(gEnemyParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon)); + break; + case 1: + case 2: + memcpy(gEnemyParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon)); + break; + } + } + } + } + + shedinja_something(&gPlayerParty[0]); + shedinja_something(&gPlayerParty[1]); + shedinja_something(&gPlayerParty[2]); + shedinja_something(&gPlayerParty[3]); + shedinja_something(&gPlayerParty[4]); + shedinja_something(&gPlayerParty[5]); + + shedinja_something(&gEnemyParty[0]); + shedinja_something(&gEnemyParty[1]); + shedinja_something(&gEnemyParty[2]); + shedinja_something(&gEnemyParty[3]); + shedinja_something(&gEnemyParty[4]); + shedinja_something(&gEnemyParty[5]); + + gBattleCommunication[0]++; + } + break; + case 6: + sub_800B950(); + gBattleCommunication[0]++; + gBattleCommunication[1] = 0; + gBattleCommunication[2] = 0; + break; + case 7: + if (battle_load_something(gUnknown_02024D1F, gUnknown_02024D1F + 1) != 0) + { + gPreBattleCallback1 = gMain.callback1; + gMain.callback1 = sub_8010824; + SetMainCallback2(sub_800F808); + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gTrainerBattleOpponent = 0x800; + gBattleTypeFlags |= BATTLE_TYPE_20; + } + } + break; + } +} + +void sub_800F808(void) +{ + AnimateSprites(); + BuildOamBuffer(); + sub_800374C(&gUnknown_03004210); + UpdatePaletteFade(); + RunTasks(); +} + +void sub_800F828(struct Sprite *sprite) +{ + sprite->data0 = 0; + sprite->callback = sub_800F838; +} + +void sub_800F838(struct Sprite *sprite) +{ + u16 *arr = (u16 *)ewram; + + switch (sprite->data0) + { + case 0: + sprite->data0++; + sprite->data1 = 0; + sprite->data2 = 0x281; + sprite->data3 = 0; + sprite->data4 = 1; + // fall through + case 1: + sprite->data4--; + if (sprite->data4 == 0) + { + s32 i; + s32 r2; + s32 r0; + + sprite->data4 = 2; + r2 = sprite->data1 + sprite->data3 * 32; + r0 = sprite->data2 - sprite->data3 * 32; + for (i = 0; i < 29; i += 2) + { + arr[r2 + i] = 0x3D; + arr[r0 + i] = 0x3D; + } + sprite->data3++; + if (sprite->data3 == 21) + { + sprite->data0++; + sprite->data1 = 32; + } + } + break; + case 2: + sprite->data1--; + if (sprite->data1 == 20) + SetMainCallback2(sub_800E7C4); + break; + } +} + +u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum) +{ + u32 nameHash = 0; + s32 i; + + if (trainerNum == 0x400) + return 0; + + if ((gBattleTypeFlags & 0x908) == 8) + { + ZeroEnemyPartyMons(); + for (i = 0; i < gTrainers[trainerNum].partySize; i++) + { + u32 personalityValue; + s32 j; + u8 fixedIV; + + if (gTrainers[trainerNum].doubleBattle == TRUE) + personalityValue = 0x80; + else if (gTrainers[trainerNum].encounterMusic_gender & 0x80) + personalityValue = 0x78; + else + personalityValue = 0x88; + + for (j = 0; gTrainers[trainerNum].trainerName[j] != 0xFF; j++) + nameHash += gTrainers[trainerNum].trainerName[j]; + + switch (gTrainers[trainerNum].partyFlags) + { + case 0: + { + struct TrainerPartyMember0 *partyData = gTrainers[trainerNum].party; + + for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++) + nameHash += gSpeciesNames[partyData[i].species][j]; + personalityValue += nameHash << 8; + fixedIV = partyData[i].iv * 31 / 255; + CreateMon(&party[i], partyData[i].species, partyData[i].level, fixedIV, TRUE, personalityValue, 2, 0); + break; + } + case 1: + { + struct TrainerPartyMember1 *partyData = gTrainers[trainerNum].party; + + for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++) + nameHash += gSpeciesNames[partyData[i].species][j]; + personalityValue += nameHash << 8; + fixedIV = partyData[i].iv * 31 / 255; + CreateMon(&party[i], partyData[i].species, partyData[i].level, fixedIV, TRUE, personalityValue, 2, 0); + + for (j = 0; j < 4; j++) + { + SetMonData(&party[i], MON_DATA_MOVE1 + j, (u8 *)&partyData[i].moves[j]); + SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); + } + break; + } + case 2: + { + struct TrainerPartyMember2 *partyData = gTrainers[trainerNum].party; + + for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++) + nameHash += gSpeciesNames[partyData[i].species][j]; + personalityValue += nameHash << 8; + fixedIV = partyData[i].iv * 31 / 255; + CreateMon(&party[i], partyData[i].species, partyData[i].level, fixedIV, TRUE, personalityValue, 2, 0); + + SetMonData(&party[i], MON_DATA_HELD_ITEM, (u8 *)&partyData[i].heldItem); + break; + } + case 3: + { + struct TrainerPartyMember3 *partyData = gTrainers[trainerNum].party; + + for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++) + nameHash += gSpeciesNames[partyData[i].species][j]; + personalityValue += nameHash << 8; + fixedIV = partyData[i].iv * 31 / 255; + CreateMon(&party[i], partyData[i].species, partyData[i].level, fixedIV, TRUE, personalityValue, 2, 0); + + SetMonData(&party[i], MON_DATA_HELD_ITEM, (u8 *)&partyData[i].heldItem); + for (j = 0; j < 4; j++) + { + SetMonData(&party[i], MON_DATA_MOVE1 + j, (u8 *)&partyData[i].moves[j]); + SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); + } + break; + } + } + } + gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle; + } + return gTrainers[trainerNum].partySize; +} + +void sub_800FCD4(void) +{ + if (REG_VCOUNT < 0xA0 && REG_VCOUNT >= 0x6F ) + REG_BG0CNT = 0x9800; +} + +void sub_800FCFC(void) +{ + Random(); // unused return value + REG_BG0HOFS = gUnknown_030042A4; + REG_BG0VOFS = gUnknown_030042A0; + REG_BG1HOFS = gUnknown_030042C0; + REG_BG1VOFS = gUnknown_030041B4; + REG_BG2HOFS = gUnknown_03004288; + REG_BG2VOFS = gUnknown_03004280; + REG_BG3HOFS = gUnknown_030041B0; + REG_BG3VOFS = gUnknown_030041B8; + REG_WIN0H = gUnknown_030042C4; + REG_WIN0V = gUnknown_03004240; + REG_WIN1H = gUnknown_03004200; + REG_WIN1V = gUnknown_03004244; + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); + sub_8089668(); +} + +void nullsub_36(struct Sprite *sprite) +{ +} + +void sub_800FDB0(struct Sprite *sprite) +{ + if (sprite->data0 != 0) + sprite->pos1.x = sprite->data1 + ((sprite->data2 & 0xFF00) >> 8); + else + sprite->pos1.x = sprite->data1 - ((sprite->data2 & 0xFF00) >> 8); + sprite->data2 += 0x180; + if (sprite->affineAnimEnded) + { + FreeSpriteTilesByTag(0x2710); + FreeSpritePaletteByTag(0x2710); + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + } +} + +void sub_800FE20(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, 1); + sprite->callback = sub_800FDB0; + PlaySE(SE_BT_START); +} + +void sub_800FE40(u8 taskId) +{ + struct Pokemon *sp4 = NULL; + struct Pokemon *sp8 = NULL; + u8 r2 = ewram160CB; + u32 r7; + s32 i; + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + switch (gLinkPlayers[r2].lp_field_18) + { + case 0: + case 2: + sp4 = gPlayerParty; + sp8 = gEnemyParty; + break; + case 1: + case 3: + sp4 = gEnemyParty; + sp8 = gPlayerParty; + break; + } + } + else + { + sp4 = gPlayerParty; + sp8 = gEnemyParty; + } + + r7 = 0; + for (i = 0; i < 6; i++) + { + u16 species = GetMonData(&sp4[i], MON_DATA_SPECIES2); + u16 hp = GetMonData(&sp4[i], MON_DATA_HP); + u32 status = GetMonData(&sp4[i], MON_DATA_STATUS); + + if (species == 0) + continue; + if (species != SPECIES_EGG && hp != 0 && status == 0) + r7 |= 1 << i * 2; + + if (species == 0) + continue; + if (hp != 0 && (species == SPECIES_EGG || status != 0)) + r7 |= 2 << i * 2; + + if (species == 0) + continue; + if (species != SPECIES_EGG && hp == 0) + r7 |= 3 << i * 2; + } + gTasks[taskId].data[3] = r7; + + r7 = 0; + for (i = 0; i < 6; i++) + { + u16 species = GetMonData(&sp8[i], MON_DATA_SPECIES2); + u16 hp = GetMonData(&sp8[i], MON_DATA_HP); + u32 status = GetMonData(&sp8[i], MON_DATA_STATUS); + + if (species == 0) + continue; + if (species != SPECIES_EGG && hp != 0 && status == 0) + r7 |= 1 << i * 2; + + if (species == 0) + continue; + if (hp != 0 && (species == SPECIES_EGG || status != 0)) + r7 |= 2 << i * 2; + + if (species == 0) + continue; + if (species != SPECIES_EGG && hp == 0) + r7 |= 3 << i * 2; + } + gTasks[taskId].data[4] = r7; +} + +void c2_8011A1C(void) +{ + s32 i; + u8 taskId; + + SetHBlankCallback(NULL); + SetVBlankCallback(NULL); + CpuFill32(0, (void *)VRAM, VRAM_SIZE); + REG_MOSAIC = 0; + REG_WIN0H = 0xF0; + REG_WIN0V = 0x5051; + REG_WININ = 0; + REG_WINOUT = 0; + gUnknown_030042C4 = 0xF0; + gUnknown_03004240 = 0x5051; + dp12_8087EA4(); + + for (i = 0; i < 80; i++) + { + gUnknown_03004DE0.unk0[i] = 0xF0; + gUnknown_03004DE0.unk780[i] = 0xF0; + } + for (i = 80; i < 160; i++) + { + asm(""::"r"(i)); // Needed to stop the compiler from optimizing out the loop counter + gUnknown_03004DE0.unk0[i] = 0xFF10; + gUnknown_03004DE0.unk780[i] = 0xFF10; + } + SetUpWindowConfig(&gWindowConfig_81E6C58); + ResetPaletteFade(); + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + gUnknown_030042C0 = 0; + gUnknown_030041B4 = 0; + gUnknown_03004288 = 0; + gUnknown_03004280 = 0; + gUnknown_030041B0 = 0; + gUnknown_030041B8 = 0; + + InitWindowFromConfig(&gUnknown_03004210, &gWindowConfig_81E6C58); + InitWindowFromConfig(&gUnknown_030041D0, &gWindowConfig_81E71D0); + InitWindowFromConfig(&gUnknown_03004250, &gWindowConfig_81E71EC); + sub_800D6D4(); + LoadCompressedPalette(gUnknown_08D004E0, 0, 64); + sub_800D74C(); + ResetSpriteData(); + ResetTasks(); + sub_800E23C(); + REG_WINOUT = 0x37; + FreeAllSpritePalettes(); + gReservedSpritePaletteCount = 4; + SetVBlankCallback(sub_800FCFC); + taskId = CreateTask(sub_800DE30, 0); + gTasks[taskId].data[1] = 0x10E; + gTasks[taskId].data[2] = 0x5A; + gTasks[taskId].data[5] = 1; + sub_800FE40(taskId); + SetMainCallback2(sub_80101B8); + gBattleCommunication[0] = 0; +} + +void sub_80101B8(void) +{ + c2_081284E0(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); + RunTasks(); +} + +void c2_081284E0(void) +{ + switch (gBattleCommunication[0]) + { + case 0: + gBattleCommunication[1] = 0xFF; + gBattleCommunication[0]++; + break; + case 1: + gBattleCommunication[1]--; + if (gBattleCommunication[1] == 0) + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gBattleCommunication[0]++; + } + break; + case 2: + if (!gPaletteFade.active) + SetMainCallback2(gMain.savedCallback); + break; + } +} + +void oac_poke_opponent(struct Sprite *sprite) +{ + sprite->callback = sub_8010278; + StartSpriteAnimIfDifferent(sprite, 0); + BeginNormalPaletteFade(0x00020000, 0, 10, 10, 0x3DEF); +} + +void sub_8010278(struct Sprite *sprite) +{ + if ((gUnknown_02024DE8 & 1) == 0) + { + sprite->pos2.x += 2; + if (sprite->pos2.x == 0) + { + sprite->callback = sub_80102AC; + PlayCry1(sprite->data2, 25); + } + } +} + +void sub_80102AC(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + sub_804777C(sprite->data0); + sub_8043DFC(gHealthboxIDs[sprite->data0]); + sprite->callback = nullsub_37; + StartSpriteAnimIfDifferent(sprite, 0); + BeginNormalPaletteFade(0x00020000, 0, 10, 0, 0x3DEF); + } +} + +void nullsub_37(struct Sprite *sprite) +{ +} + +void unref_sub_801030C(struct Sprite *sprite) +{ + sprite->data3 = 6; + sprite->data4 = 1; + sprite->callback = sub_8010320; +} + +void sub_8010320(struct Sprite *sprite) +{ + sprite->data4--; + if (sprite->data4 == 0) + { + sprite->data4 = 8; + sprite->invisible ^= 1; + sprite->data3--; + if (sprite->data3 == 0) + { + sprite->invisible = FALSE; + sprite->callback = nullsub_37; + gUnknown_03004284 = 0; + } + } +} + +void sub_8010384(struct Sprite *sprite) +{ + u8 r6 = sprite->data0; + u16 species; + u8 yOffset; + + if (ewram17800[r6].transformedSpecies != 0) + species = ewram17800[r6].transformedSpecies; + else + species = sprite->data2; + + GetMonData(&gEnemyParty[gBattlePartyID[r6]], MON_DATA_PERSONALITY); // Unused return value + + if (species == SPECIES_UNOWN) + { + u32 personalityValue = GetMonData(&gEnemyParty[gBattlePartyID[r6]], MON_DATA_PERSONALITY); + u16 unownForm = ((((personalityValue & 0x3000000) >> 18) | ((personalityValue & 0x30000) >> 12) | ((personalityValue & 0x300) >> 6) | (personalityValue & 3)) % 0x1C); + u16 unownSpecies; + + if (unownForm == 0) + unownSpecies = SPECIES_UNOWN; // Use the A Unown form + else + unownSpecies = NUM_SPECIES + unownForm; // Use one of the other Unown letters + + yOffset = gMonFrontPicCoords[unownSpecies].y_offset; + } + else if (species == SPECIES_CASTFORM) + { + yOffset = gCastformFrontSpriteCoords[gBattleMonForms[r6]].y_offset; + } + else if (species > NUM_SPECIES) + { + yOffset = gMonFrontPicCoords[SPECIES_NONE].y_offset; + } + else + { + yOffset = gMonFrontPicCoords[species].y_offset; + } + + sprite->data3 = 8 - yOffset / 8; + sprite->data4 = 1; + sprite->callback = sub_8010494; +} + +void sub_8010494(struct Sprite *sprite) +{ + s32 i; + + sprite->data4--; + if (sprite->data4 == 0) + { + sprite->data4 = 2; + sprite->pos2.y += 8; + sprite->data3--; + if (sprite->data3 < 0) + { + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + } + else + { + u8 *dst = (u8 *)gUnknown_081FAF4C[GetBankIdentity(sprite->data0)] + (gBattleMonForms[sprite->data0] << 11) + (sprite->data3 << 8); + + for (i = 0; i < 0x100; i++) + *(dst++) = 0; + StartSpriteAnim(sprite, gBattleMonForms[sprite->data0]); + } + } +} + +void sub_8010520(struct Sprite *sprite) +{ + sprite->data3 = 8; + sprite->data4 = sprite->invisible; + sprite->callback = sub_801053C; +} + +void sub_801053C(struct Sprite *sprite) +{ + sprite->data3--; + if (sprite->data3 == 0) + { + sprite->invisible ^= 1; + sprite->data3 = 8; + } +} + +void sub_8010574(struct Sprite *sprite) +{ + sprite->invisible = sprite->data4; + sprite->data4 = FALSE; + sprite->callback = nullsub_37; +} + +void sub_80105A0(struct Sprite *sprite) +{ + sprite->callback = oac_poke_ally_; +} + +void oac_poke_ally_(struct Sprite *sprite) +{ + if ((gUnknown_02024DE8 & 1) == 0) + { + sprite->pos2.x -= 2; + if (sprite->pos2.x == 0) + { + sprite->callback = nullsub_86; + sprite->data1 = 0; + } + } +} + +void sub_80105DC(struct Sprite *sprite) +{ + sprite->callback = nullsub_86; +} + +void nullsub_86(struct Sprite *sprite) +{ +} + +void sub_80105EC(struct Sprite *sprite) +{ + if ((gUnknown_02024DE8 & 1) == 0) + { + sprite->pos2.x += sprite->data1; + sprite->pos2.y += sprite->data2; + } +} + +void dp11b_obj_instanciate(u8 bank, u8 b, s8 c, s8 d) +{ + u8 spriteId; + u8 objectID; + + if (b) + { + if (ewram17810[bank].unk0_1) + return; + } + else + { + if (ewram17810[bank].unk0_2) + return; + } + + spriteId = CreateInvisibleSpriteWithCallback(objc_dp11b_pingpong); + if (b == TRUE) + { + objectID = gHealthboxIDs[bank]; + ewram17810[bank].unk2 = spriteId; + ewram17810[bank].unk0_1 = 1; + gSprites[spriteId].data0 = 0x80; + } + else + { + objectID = gObjectBankIDs[bank]; + ewram17810[bank].unk3 = spriteId; + ewram17810[bank].unk0_2 = 1; + gSprites[spriteId].data0 = 0xC0; + } + gSprites[spriteId].data1 = c; + gSprites[spriteId].data2 = d; + gSprites[spriteId].data3 = objectID; + gSprites[spriteId].data4 = b; + gSprites[objectID].pos2.x = 0; + gSprites[objectID].pos2.y = 0; +} + +void dp11b_obj_free(u8 a, u8 b) +{ + u8 r4; + + if (b == TRUE) + { + if (!ewram17810[a].unk0_1) + return; + r4 = gSprites[ewram17810[a].unk2].data3; + DestroySprite(&gSprites[ewram17810[a].unk2]); + ewram17810[a].unk0_1 = 0; + } + else + { + if (!ewram17810[a].unk0_2) + return; + r4 = gSprites[ewram17810[a].unk3].data3; + DestroySprite(&gSprites[ewram17810[a].unk3]); + ewram17810[a].unk0_2 = 0; + } + gSprites[r4].pos2.x = 0; + gSprites[r4].pos2.y = 0; +} + +void objc_dp11b_pingpong(struct Sprite *sprite) +{ + u8 spriteId = sprite->data3; + s32 var; + + if (sprite->data4 == 1) + var = sprite->data0; + else + var = sprite->data0; + + gSprites[spriteId].pos2.y = Sin(var, sprite->data2) + sprite->data2; + sprite->data0 = (sprite->data0 + sprite->data1) & 0xFF; +} + +void nullsub_41(void) +{ +} + +void sub_8010800(void) +{ + sub_8010874(); + gBattleCommunication[1] = 0; + gBattleMainFunc = bc_8012FAC; +} + +void sub_8010824(void) +{ + gBattleMainFunc(); + + for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++) + gBattleBankFunc[gActiveBank](); +} + +void sub_8010874(void) +{ + s32 i; + u32 j; + u8 *r4; + + TurnValuesCleanUp(0); + SpecialStatusesClear(); + + for (i = 0; i < 4; i++) + { + gStatuses3[i] = 0; + + r4 = (u8 *)&gDisableStructs[i]; + for (j = 0; j < (u32)0x1C; j++) + r4[j] = 0; + + gDisableStructs[i].isFirstTurn= 2; + gUnknown_02024C70[i] = 0; + gLastUsedMove[i] = 0; + gMoveHitWith[i] = 0; + gUnknown_02024C44[i] = 0; + gUnknown_02024C4C[i] = 0; + gUnknown_02024C5C[i] = 0xFF; + gLockedMove[i] = 0; + gUnknown_02024C2C[i] = 0; + ewram17100[i] = 0; + } + + for (i = 0; i < 2; i++) + { + gSideAffecting[i] = 0; + + r4 = (u8 *)&gSideTimer[i]; + for (j = 0; j < 12; j++) + r4[j] = 0; + } + + gBankAttacker = 0; + gBankTarget = 0; + gBattleWeather = 0; + + r4 = (u8 *)&gWishFutureKnock; + for (i = 0; i < (u32)0x2C; i++) + r4[i] = 0; + + gHitMarker = 0; + if ((gBattleTypeFlags & BATTLE_TYPE_LINK) == 0 && gSaveBlock2.optionsBattleSceneOff == TRUE) + gHitMarker = HITMARKER_NO_ANIMATIONS; + ewram16084 = gSaveBlock2.optionsBattleStyle; + gMultiHitCounter = 0; + gBattleOutcome = 0; + gBattleExecBuffer = 0; + gPaydayMoney = 0; + ewram17130 = 0; + ewram17160 = 0; + for (i = 0; i < 8; i++) + gBattleCommunication[i] = 0; + gPauseCounterBattle = 0; + gBattleMoveDamage = 0; + gUnknown_02024DE8 = 0; + ewram16002 = 0; + ewram160A1 = 0; + gLeveledUpInBattle = 0; + gAbsentBankFlags = 0; + ewram16078 = 0; + ewram16086 = 0; + ewram16087 = 0; + ewram16089 = gBaseStats[GetMonData(&gEnemyParty[0], MON_DATA_SPECIES)].catchRate * 100 / 1275; + ewram16088 = 3; + ewram1601B = 0; + ewram16056 = 1; + + for (i = 0; i < 8; i++) + { + ewram[i + 0x160AC] = 0; + ewram[i + 0x160CC] = 0; + ewram[i + 0x160E8] = 0; + ewram[i + 0x160F0] = 0; + ewram[i + 0x16100] = 0; + ewram[i + 0x16108] = 0; + } + + ewram160C8 = 6; + ewram160C9 = 6; + ewram16113 = 0; + for (i = 0; i < 11; i++) + gBattleResults.unk36[i] = 0; + gBattleResults.battleTurnCounter = 0; + gBattleResults.playerFaintCounter = 0; + gBattleResults.opponentFaintCounter = 0; + gBattleResults.unk2 = 0; + gBattleResults.unk3 = 0; + gBattleResults.unk4 = 0; + gBattleResults.unk5_0 = 0; + gBattleResults.unk5_1 = 0; + gBattleResults.lastOpponentSpecies = 0; + gBattleResults.lastUsedMove = 0; + gBattleResults.opponentMove = 0; + gBattleResults.poke1Species = 0; + gBattleResults.opponentSpecies = 0; + gBattleResults.caughtPoke = 0; + for (i = 0; i < 10; i++) + { + gBattleResults.pokeString1[i] = 0; + gBattleResults.pokeString2[i] = 0; + gBattleResults.caughtNick[i] = 0; + } +} + +void SwitchInClearStructs(void) +{ + struct DisableStruct sp0 = gDisableStructs[gActiveBank]; + s32 i; + u8 *ptr; + u32 *ptr2; + + if (gBattleMoves[gCurrentMove].effect != EFFECT_BATON_PASS) + { + for (i = 0; i < 8; i++) + gBattleMons[gActiveBank].statStages[i] = 6; + for (i = 0; i < gNoOfAllBanks; i++) + { + struct UnknownStruct12 *sp20 = &gUnknown_02024AD0[i]; + + if ((sp20->unk0 & 0x04000000) && gDisableStructs[i].bankPreventingEscape == gActiveBank) + sp20->unk0 &= ~0x04000000; + if ((gStatuses3[i] & STATUS3_ALWAYS_HITS) && gDisableStructs[i].bankWithSureHit == gActiveBank) + { + gStatuses3[i] &= ~STATUS3_ALWAYS_HITS; + gDisableStructs[i].bankWithSureHit = 0; + } + } + } + if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS) + { + gBattleMons[gActiveBank].status2 &= (STATUS2_CONFUSION | STATUS2_FOCUS_ENERGY | STATUS2_SUBSTITUTE | STATUS2_ESCAPE_PREVENTION | STATUS2_CURSED); + gStatuses3[gActiveBank] &= (STATUS3_LEECHSEED_BANK | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED | STATUS3_MUDSPORT | STATUS3_WATERSPORT); + + for (i = 0; i < gNoOfAllBanks; i++) + { + if (GetBankSide(gActiveBank) != GetBankSide(i) + && (gStatuses3[i] & STATUS3_ALWAYS_HITS) != 0 + && (gDisableStructs[i].bankWithSureHit == gActiveBank)) + { + gStatuses3[i] &= ~STATUS3_ALWAYS_HITS; + gStatuses3[i] |= 0x10; + } + } + } + else + { + gBattleMons[gActiveBank].status2 = 0; + gStatuses3[gActiveBank] = 0; + } + + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gUnknown_02024AD0[i].unk0 & (gBitTable[gActiveBank] << 16)) + gUnknown_02024AD0[i].unk0 &= ~(gBitTable[gActiveBank] << 16); + if ((gUnknown_02024AD0[i].unk0 & 0xE000) && ewram[0x16020 + i] == gActiveBank) + gUnknown_02024AD0[i].unk0 &= ~0xE000; + } + + gActionSelectionCursor[gActiveBank] = 0; + gMoveSelectionCursor[gActiveBank] = 0; + + ptr = (u8 *)&gDisableStructs[gActiveBank]; + for (i = 0; i < (u32)0x1C; i++) + ptr[i] = 0; + + if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS) + { + gDisableStructs[gActiveBank].substituteHP = sp0.substituteHP; + gDisableStructs[gActiveBank].bankWithSureHit = sp0.bankWithSureHit; + gDisableStructs[gActiveBank].perishSong1 = sp0.perishSong1; + gDisableStructs[gActiveBank].perishSong2 = sp0.perishSong2; + } + + gDisableStructs[gActiveBank].isFirstTurn= 2; + gLastUsedMove[gActiveBank] = 0; + gMoveHitWith[gActiveBank] = 0; + gUnknown_02024C44[gActiveBank] = 0; + gUnknown_02024C4C[gActiveBank] = 0; + gUnknown_02024C2C[gActiveBank] = 0; + gUnknown_02024C5C[gActiveBank] = 0xFF; + + ewram[0x160AC + gActiveBank * 2 + 0] = 0; + ewram[0x160AC + gActiveBank * 2 + 1] = 0; + ewram[0x16100 + gActiveBank * 4 + 0] = 0; + ewram[0x16100 + gActiveBank * 4 + 1] = 0; + ewram[0x16100 + gActiveBank * 4 + 2] = 0; + ewram[0x16100 + gActiveBank * 4 + 3] = 0; + ewram[0x160E8 + gActiveBank * 2 + 0] = 0; + ewram[0x160E8 + gActiveBank * 2 + 1] = 0; + + ptr2 = (u32 *)(ewram + 0x17100); + ptr2[gActiveBank] = 0; + + gCurrentMove = 0; +} + +void UndoEffectsAfterFainting(void) +{ + s32 i; + u8 *ptr; + u32 *ptr2; + + for (i = 0; i < 8; i++) + gBattleMons[gActiveBank].statStages[i] = 6; + gBattleMons[gActiveBank].status2 = 0; + gStatuses3[gActiveBank] = 0; + for (i = 0; i < gNoOfAllBanks; i++) + { + if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].bankPreventingEscape == gActiveBank) + gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION; + if (gBattleMons[i].status2 & (gBitTable[gActiveBank] << 16)) + gBattleMons[i].status2 &= ~(gBitTable[gActiveBank] << 16); + if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && ewram[0x16020 + i] == gActiveBank) + gBattleMons[i].status2 &= ~STATUS2_WRAPPED; + } + gActionSelectionCursor[gActiveBank] = 0; + gMoveSelectionCursor[gActiveBank] = 0; + + ptr = (u8 *)&gDisableStructs[gActiveBank]; + for (i = 0; i < (u32)0x1C; i++) + ptr[i] = 0; + gProtectStructs[gActiveBank].protected = 0; + gProtectStructs[gActiveBank].endured = 0; + gProtectStructs[gActiveBank].onlyStruggle = 0; + gProtectStructs[gActiveBank].helpingHand = 0; + gProtectStructs[gActiveBank].bounceMove = 0; + gProtectStructs[gActiveBank].stealMove = 0; + gProtectStructs[gActiveBank].flag0Unknown = 0; + gProtectStructs[gActiveBank].prlzImmobility = 0; + gProtectStructs[gActiveBank].confusionSelfDmg = 0; + gProtectStructs[gActiveBank].notEffective = 0; + gProtectStructs[gActiveBank].chargingTurn = 0; + gProtectStructs[gActiveBank].fleeFlag = 0; + gProtectStructs[gActiveBank].usedImprisionedMove = 0; + gProtectStructs[gActiveBank].loveImmobility = 0; + gProtectStructs[gActiveBank].usedDisabledMove = 0; + gProtectStructs[gActiveBank].usedTauntedMove = 0; + gProtectStructs[gActiveBank].flag2Unknown = 0; + gProtectStructs[gActiveBank].flinchImmobility = 0; + gProtectStructs[gActiveBank].notFirstStrike = 0; + + gDisableStructs[gActiveBank].isFirstTurn= 2; + gLastUsedMove[gActiveBank] = 0; + gMoveHitWith[gActiveBank] = 0; + gUnknown_02024C44[gActiveBank] = 0; + gUnknown_02024C4C[gActiveBank] = 0; + gUnknown_02024C2C[gActiveBank] = 0; + gUnknown_02024C5C[gActiveBank] = 0xFF; + + ewram[0x160E8 + gActiveBank * 2 + 0] = 0; + ewram[0x160E8 + gActiveBank * 2 + 1] = 0; + ewram[0x160AC + gActiveBank * 2 + 0] = 0; + ewram[0x160AC + gActiveBank * 2 + 1] = 0; + ewram[0x16100 + gActiveBank * 4 + 0] = 0; + ewram[0x16100 + gActiveBank * 4 + 1] = 0; + ewram[0x16100 + gActiveBank * 4 + 2] = 0; + ewram[0x16100 + gActiveBank * 4 + 3] = 0; + + ptr2 = (u32 *)(ewram + 0x17100); + ptr2[gActiveBank] = 0; + + gBattleMons[gActiveBank].type1 = gBaseStats[gBattleMons[gActiveBank].species].type1; + gBattleMons[gActiveBank].type2 = gBaseStats[gBattleMons[gActiveBank].species].type2; +} + +void bc_8012FAC(void) +{ + switch (gBattleCommunication[0]) + { + case 0: + gActiveBank = gBattleCommunication[1]; + EmitGetAttributes(0, 0, 0); + MarkBufferBankForExecution(gActiveBank); + gBattleCommunication[0]++; + break; + case 1: + if (gBattleExecBuffer == 0) + { + gBattleCommunication[1]++; + if (gBattleCommunication[1] == gNoOfAllBanks) + gBattleMainFunc = BattlePrepIntroSlide; + else + gBattleCommunication[0] = 0; + } + break; + } +} + +static void BattlePrepIntroSlide(void) +{ + if (gBattleExecBuffer == 0) + { + gActiveBank = GetBankByPlayerAI(0); + EmitIntroSlide(0, gBattleTerrain); + MarkBufferBankForExecution(gActiveBank); + gBattleMainFunc = sub_8011384; + gBattleCommunication[0] = 0; + gBattleCommunication[1] = 0; + } +} + +void sub_8011384(void) +{ + u8 *ptr; + s32 i; + + if (gBattleExecBuffer == 0) + { + for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++) + { + if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI) + && GetBankSide(gActiveBank) == 0) + { + ptr = (u8 *)&gBattleMons[gActiveBank]; + for (i = 0; i < (u32)0x58; i++) + ptr[i] = 0; + } + else + { + u8 r0; + + ptr = (u8 *)&gBattleMons[gActiveBank]; + for (i = 0; i < (u32)0x58; i++) + ptr[i] = gBattleBufferB[gActiveBank][4 + i]; + + gBattleMons[gActiveBank].type1 = gBaseStats[gBattleMons[gActiveBank].species].type1; + gBattleMons[gActiveBank].type2 = gBaseStats[gBattleMons[gActiveBank].species].type2; + gBattleMons[gActiveBank].ability = GetAbilityBySpecies(gBattleMons[gActiveBank].species, gBattleMons[gActiveBank].altAbility); + r0 = GetBankSide(gActiveBank); + ewram160BC[r0] = gBattleMons[gActiveBank].hp; + for (i = 0; i < 8; i++) + gBattleMons[gActiveBank].statStages[i] = 6; + gBattleMons[gActiveBank].status2 = 0; + } + + if (GetBankIdentity(gActiveBank) == 0) + { + EmitTrainerThrow(0); + MarkBufferBankForExecution(gActiveBank); + } + + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + if (GetBankIdentity(gActiveBank) == 1) + { + EmitTrainerThrow(0); + MarkBufferBankForExecution(gActiveBank); + } + if (GetBankSide(gActiveBank) == 1 + && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_LINK))) + GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), 2); + } + else + { + if (GetBankSide(gActiveBank) == 1 + && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_LINK))) + { + GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), 2); + EmitLoadPokeSprite(0); + MarkBufferBankForExecution(gActiveBank); + } + } + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (GetBankIdentity(gActiveBank) == 2 + || GetBankIdentity(gActiveBank) == 3) + { + EmitTrainerThrow(0); + MarkBufferBankForExecution(gActiveBank); + } + } + } + gBattleMainFunc = bc_801333C; + } +} + +void bc_801333C(void) +{ + s32 i; + + if (gBattleExecBuffer == 0) + { + struct + { + u16 hp; + u32 status; + } sp0[6]; + + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + for (i = 0; i < 6; i++) + { + if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == 0 + || GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG) + { + sp0[i].hp = 0xFFFF; + sp0[i].status = 0; + } + else + { + sp0[i].hp = GetMonData(&gEnemyParty[i], MON_DATA_HP); + sp0[i].status = GetMonData(&gEnemyParty[i], MON_DATA_STATUS); + } + } + gActiveBank = GetBankByPlayerAI(1); + Emitcmd48(0, (u8 *)sp0, 0x80); + MarkBufferBankForExecution(gActiveBank); + + for (i = 0; i < 6; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == 0 + || GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG) + { + sp0[i].hp = 0xFFFF; + sp0[i].status = 0; + } + else + { + sp0[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP); + sp0[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS); + } + } + gActiveBank = GetBankByPlayerAI(0); + Emitcmd48(0, (u8 *)sp0, 0x80); + MarkBufferBankForExecution(gActiveBank); + + gBattleMainFunc = bc_battle_begin_message; + } + else + { + // The array gets set here, but nothing is ever done with it. + // Likely unfinished code. + + for (i = 0; i < 6; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == 0 + || GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG) + { + sp0[i].hp = 0xFFFF; + sp0[i].status = 0; + } + else + { + sp0[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP); + sp0[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS); + } + } + + gBattleMainFunc = bc_8013568; + } + } +} + +void bc_battle_begin_message(void) +{ + if (gBattleExecBuffer == 0) + { + gActiveBank = GetBankByPlayerAI(1); + PrepareStringBattle(0, gActiveBank); + gBattleMainFunc = sub_8011800; + } +} + +void bc_8013568(void) +{ + if (gBattleExecBuffer == 0) + { + gBattleMainFunc = sub_8011970; + PrepareStringBattle(0, 0); + } +} + +void sub_8011800(void) +{ + if (gBattleExecBuffer == 0) + { + PrepareStringBattle(1, GetBankByPlayerAI(1)); + gBattleMainFunc = sub_8011834; + } +} + +void sub_8011834(void) +{ + if (gBattleExecBuffer == 0) + { + for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++) + { + if (GetBankIdentity(gActiveBank) == 1) + { + EmitTrainerBallThrow(0); + MarkBufferBankForExecution(gActiveBank); + } + if ((gBattleTypeFlags & BATTLE_TYPE_MULTI) + && GetBankIdentity(gActiveBank) == 3) + { + EmitTrainerBallThrow(0); + MarkBufferBankForExecution(gActiveBank); + } + } + gBattleMainFunc = bc_801362C; + } +} + +void bc_801362C(void) +{ + if (gBattleExecBuffer == 0) + { + for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++) + { + if (GetBankSide(gActiveBank) == 1 + && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_LINK))) + GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), 2); + } + gBattleMainFunc = sub_8011970; + } +} + +void unref_sub_8011950(void) +{ + if (gBattleExecBuffer == 0) + gBattleMainFunc = sub_8011970; +} + +void sub_8011970(void) +{ + if (gBattleExecBuffer == 0) + { + if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) + PrepareStringBattle(1, GetBankByPlayerAI(0)); + gBattleMainFunc = sub_80119B4; + } +} + +void sub_80119B4(void) +{ + if (gBattleExecBuffer == 0) + { + for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++) + { + if (GetBankIdentity(gActiveBank) == 0) + { + EmitTrainerBallThrow(0); + MarkBufferBankForExecution(gActiveBank); + } + if ((gBattleTypeFlags & BATTLE_TYPE_MULTI) + && GetBankIdentity(gActiveBank) == 2) + { + EmitTrainerBallThrow(0); + MarkBufferBankForExecution(gActiveBank); + } + } + ewram16058 = 0; + ewram160F9 = 0; + ewram160E6 = 0; + gBattleMainFunc = BattleBeginFirstTurn; + } +} + +void unref_sub_8011A68(void) +{ + if (gBattleExecBuffer == 0) + { + for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++) + { + if (GetBankSide(gActiveBank) == 0) + { + EmitSendOutPoke(0, gBattlePartyID[gActiveBank], 0); + MarkBufferBankForExecution(gActiveBank); + } + } + ewram16058 = 0; + ewram160F9 = 0; + ewram160E6 = 0; + gBattleMainFunc = BattleBeginFirstTurn; + } +} + +void BattleBeginFirstTurn(void) +{ + s32 i; + s32 j; + u8 r9 = 0; + + if (gBattleExecBuffer == 0) + { + if (ewram16058 == 0) + { + for (i = 0; i < gNoOfAllBanks; i++) + gTurnOrder[i] = i; + for (i = 0; i < gNoOfAllBanks - 1; i++) + { + for (j = i + 1; j < gNoOfAllBanks; j++) + { + if (GetWhoStrikesFirst(gTurnOrder[i], gTurnOrder[j], 1) != 0) + sub_8012FBC(i, j); + } + } + } + if (ewram160E6 == 0 && AbilityBattleEffects(0, 0, 0, 0xFF, 0) != 0) + { + ewram160E6 = 1; + return; + } + while (ewram16058 < gNoOfAllBanks) + { + if (AbilityBattleEffects(0, gTurnOrder[ewram16058], 0, 0, 0) != 0) + r9++; + ewram16058++; + if (r9 != 0) + return; + } + if (AbilityBattleEffects(9, 0, 0, 0, 0) != 0) + return; + if (AbilityBattleEffects(11, 0, 0, 0, 0) != 0) + return; + while (ewram160F9 < gNoOfAllBanks) + { + if (ItemBattleEffects(0, gTurnOrder[ewram160F9], 0) != 0) + r9++; + ewram160F9++; + if (r9 != 0) + return; + } + // Absolutely pointless for-loop that somehow doesn't get optimized out + for (i = 0; i < gNoOfAllBanks; i++) + ; + for (i = 0; i < 4; i++) + { + ewram[0x16068 + i] = 6; + gActionForBanks[i] = 0xFF; + gChosenMovesByBanks[i] = 0; + } + TurnValuesCleanUp(0); + SpecialStatusesClear(); + ewram160A6 = gAbsentBankFlags; + gBattleMainFunc = sub_8012324; + sub_80156DC(); + for (i = 0; i < 8; i++) + gBattleCommunication[i] = 0; + for (i = 0; i < gNoOfAllBanks; i++) + gBattleMons[i].status2 &= ~8; + ewram16000 = 0; + ewram16001 = 0; + ewram16110 = 0; + ewram16111 = 0; + ewram1600C = 0; + ewram16059 = 0; + ewram1600E = 0; + gBattleMoveFlags = 0; + gRandomTurnNumber = Random(); + } +} + +void bc_8013B1C(void) +{ + s32 i; + + if (gBattleExecBuffer == 0) + { + gBattleMainFunc = BattleTurnPassed; + for (i = 0; i < 8; i++) + gBattleCommunication[i] = 0; + for (i = 0; i < gNoOfAllBanks; i++) + { + gBattleMons[i].status2 &= ~8; + if ((gBattleMons[i].status1 & 7) && (gBattleMons[i].status2 & 0x1000)) + CancelMultiTurnMoves(i); + } + ewram16000 = 0; + ewram16001 = 0; + ewram16110 = 0; + ewram16111 = 0; + ewram1600E = 0; + gBattleMoveFlags = 0; + } +} + +void BattleTurnPassed(void) +{ + s32 i; + + TurnValuesCleanUp(1); + if (gBattleOutcome == 0) + { + if (UpdateTurnCounters() != 0) + return; + if (TurnBasedEffects() != 0) + return; + } + if (sub_80173A4() != 0) + return; + ewram16059 = 0; + if (sub_80170DC() != 0) + return; + TurnValuesCleanUp(0); + gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; + gHitMarker &= ~0x80000; + gHitMarker &= ~0x400000; + gHitMarker &= ~0x100000; + ewram16002 = 0; + ewram160A1 = 0; + ewram1600C = 0; + gBattleMoveDamage = 0; + gBattleMoveFlags = 0; + for (i = 0; i < 5; i++) + gBattleCommunication[i] = 0; + if (gBattleOutcome != 0) + { + gFightStateTracker = 12; + gBattleMainFunc = sub_80138F0; + return; + } + if (gBattleResults.battleTurnCounter < 0xFF) + gBattleResults.battleTurnCounter++; + for (i = 0; i < gNoOfAllBanks; i++) + { + gActionForBanks[i] = 0xFF; + gChosenMovesByBanks[i] = 0; + } + for (i = 0; i < 4; i++) + ewram[0x16068 + i] = 6; + ewram160A6 = gAbsentBankFlags; + gBattleMainFunc = sub_8012324; + gRandomTurnNumber = Random(); +} + +u8 CanRunFromBattle(void) +{ + u8 r2; + u8 r6; + s32 i; + + if (gBattleMons[gActiveBank].item == ITEM_ENIGMA_BERRY) + r2 = gEnigmaBerries[gActiveBank].holdEffect; + else + r2 = ItemId_GetHoldEffect(gBattleMons[gActiveBank].item); + gStringBank = gActiveBank; + if (r2 == HOLD_EFFECT_CAN_ALWAYS_RUN) + return 0; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + return 0; + if (gBattleMons[gActiveBank].ability == ABILITY_RUN_AWAY) + return 0; + r6 = GetBankSide(gActiveBank); + for (i = 0; i < gNoOfAllBanks; i++) + { + if (r6 != GetBankSide(i) + && gBattleMons[i].ability == ABILITY_SHADOW_TAG) + { + ewram16003 = i; + gLastUsedAbility = gBattleMons[i].ability; + gBattleCommunication[5] = 2; + return 2; + } + if (r6 != GetBankSide(i) + && gBattleMons[gActiveBank].ability != ABILITY_LEVITATE + && gBattleMons[gActiveBank].type1 != 2 + && gBattleMons[gActiveBank].type2 != 2 + && gBattleMons[i].ability == ABILITY_ARENA_TRAP) + { + ewram16003 = i; + gLastUsedAbility = gBattleMons[i].ability; + gBattleCommunication[5] = 2; + return 2; + } + } + i = AbilityBattleEffects(15, gActiveBank, ABILITY_MAGNET_PULL, 0, 0); + if (i != 0 && (gBattleMons[gActiveBank].type1 == 8 || gBattleMons[gActiveBank].type2 == 8)) + { + ewram16003 = i - 1; + gLastUsedAbility = gBattleMons[i - 1].ability; + gBattleCommunication[5] = 2; + return 2; + } + if ((gBattleMons[gActiveBank].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)) || (gStatuses3[gActiveBank] & STATUS3_ROOTED)) + { + gBattleCommunication[5] = 0; + return 1; + } + if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) + { + gBattleCommunication[5] = 1; + return 1; + } + return 0; +} + +void sub_8012258(u8 a) +{ + s32 i; + u8 r4; + u8 r1; + + for (i = 0; i < 3; i++) + gUnknown_02038470[i] = ewram[0x1606C + i + a * 3]; + r4 = pokemon_order_func(gBattlePartyID[a]); + r1 = pokemon_order_func(ewram[0x16068 + a]); + sub_8094C98(r4, r1); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + for (i = 0; i < 3; i++) + { + ewram[0x1606C + i + a * 3] = gUnknown_02038470[i]; + ewram[0x1606C + i + (a ^ 2) * 3] = gUnknown_02038470[i]; + } + } + else + { + for (i = 0; i < 3; i++) + { + ewram[0x1606C + i + a * 3] = gUnknown_02038470[i]; + } + } +} + +/* +void sub_8012324(void) +{ + u8 r5; + + gBattleCommunication[4] = 0; + // inverted loop + //_0801234C + for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++) + { + r5 = GetBankIdentity(gActiveBank); + switch (gBattleCommunication[gActiveBank]) + { + case 0: + ewram[0x016068 + gActiveBank] = 6; + if (!(gBattleTypeFlags & 0x40) + && (r5 & 2) + && !(ewram160A6 & gBitTable[GetBankByPlayerAI(r5 ^ 2)]) + && gBattleCommunication[GetBankByPlayerAI(r5)] != 4) + break; + //_080123F8 + if (ewram160A6 & gBitTable[gActiveBank]) + { + gActionForBanks[gActiveBank] = 13; + if (!(gBattleTypeFlags & 0x40)) + gBattleCommunication[gActiveBank] = 4; + //_08012454 + else + gBattleCommunication[gActiveBank] = 3; + break; + } + //_08012468 + if ((gBattleMons[gActiveBank].status2 & 0x1000) + || (gBattleMons[gActiveBank].status2 & 0x10000000)) + { + gActionForBanks[gActiveBank] = 0; + gBattleCommunication[gActiveBank] = 3; + } + else + { + Emitcmd18(0, gActionForBanks[0], gBattleBufferB[0][1] | (gBattleBufferB[0][2] << 8)); + MarkBufferBankForExecution(gActiveBank); + gBattleCommunication[gActiveBank]++; + } + break; + case 1: + } + } +} +*/ diff --git a/src/battle/battle_3.c b/src/battle/battle_3.c new file mode 100644 index 000000000..b59757f00 --- /dev/null +++ b/src/battle/battle_3.c @@ -0,0 +1,6595 @@ +#include "global.h" +#include "abilities.h" +#include "battle.h" +#include "moves.h" +#include "item.h" +#include "items.h" +#include "hold_effects.h" +#include "species.h" +#include "pokemon.h" +#include "data2.h" +#include "rng.h" +#include "text.h" +#include "battle_move_effects.h" +#include "string_util.h" +#include "flags.h" + +extern u8* gBattlescriptCurrInstr; +extern u8 gActiveBank; +extern u8 gBattleBufferB[4][0x200]; +extern u8* gUnknown_02024C1C[4]; //battlescript location when you try to choose a move you're not allowed to +extern u16 gLastUsedMove[4]; +extern struct BattlePokemon gBattleMons[4]; +extern struct BattleEnigmaBerry gEnigmaBerries[4]; +extern u8 gStringBank; +extern u16 gLastUsedItem; +extern u16 gCurrentMove; +extern const u32 gBitTable[]; +extern u16 gBattleTypeFlags; +extern u8 gNoOfAllBanks; +extern u32 gStatuses3[4]; +extern u8 gBankAttacker; +extern u8 gBankTarget; +extern u8 gTurnOrder[4]; +extern u16 gSideAffecting[2]; +extern u16 gBattleWeather; +extern void (*gBattleMainFunc)(void); +extern u8 gAbsentBankFlags; +extern u8 gBattleCommunication[]; +extern u32 gHitMarker; +extern u8 gEffectBank; +extern u8 gBank1; +extern s32 gBattleMoveDamage; +extern u16 gBattlePartyID[4]; +extern u16 gChosenMovesByBanks[4]; +extern s32 gTakenDmg[4]; +extern u8 gTakenDmgBanks[4]; +extern u8 gBattleMoveFlags; +extern u8 gLastUsedAbility; +extern u8 gBattleTextBuff2[]; +extern u8 gFightStateTracker; +extern struct BattleEnigmaBerry gEnigmaBerries[4]; +extern u8 gUnknown_02024BE5; +extern u8 gCurrMovePos; +extern u16 gRandomMove; +extern s32 gBattleMoveDamage; +extern u16 gDynamicBasePower; +extern u32 gBattleExecBuffer; +extern const u16 gSoundMovesTable[]; +extern const u8 gStatusConditionString_PoisonJpn[]; +extern const u8 gStatusConditionString_SleepJpn[]; +extern const u8 gStatusConditionString_ParalysisJpn[]; +extern const u8 gStatusConditionString_BurnJpn[]; +extern const u8 gStatusConditionString_IceJpn[]; +extern const u8 gStatusConditionString_ConfusionJpn[]; +extern const u8 gStatusConditionString_LoveJpn[]; +extern const BattleCmdFunc gBattleScriptingCommandsTable[]; + +u8 IsImprisoned(u8 bank, u16 move); +u8 GetBankByPlayerAI(u8 ID); +u8 GetBankIdentity(u8 bank); +u8 GetBankSide(u8 bank); +void b_call_bc_move_exec(u8* BS_ptr); +bool8 sub_8015660(u8 bank); //check if a move failed +void SetMoveEffect(bool8 primary, u8 certainArg); +bool8 UproarWakeUpCheck(u8 bank); +bool8 sub_8018018(u8 bank, u8, u8); +void sub_8015740(u8 bank); +s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 a4, u16 powerOverride, u8 typeOverride, u8 bank_atk, u8 bank_def); +u8 CountTrailingZeroBits(u32 a); +u8 GetMoveTarget(u16 move, u8 useMoveTarget); +u8 sub_803FC34(u8 bank); +u16 sub_803FBFC(u8 a); +u8 weather_get_current(void); +void b_push_move_exec(u8* BS_ptr); +void RecordAbilityBattle(u8 bank, u8 ability); +void RecordItemBattle(u8 bank, u8 holdEffect); +void sub_8013F54(void); +void sub_8013FBC(void); +s8 GetPokeFlavourRelation(u32 pid, u8 flavor); + +extern u8 BattleScript_MoveSelectionDisabledMove[]; +extern u8 BattleScript_MoveSelectionTormented[]; +extern u8 BattleScript_MoveSelectionTaunted[]; +extern u8 BattleScript_MoveSelectionImprisoned[]; +extern u8 BattleScript_MoveSelectionChoiceBanded[]; +extern u8 BattleScript_MoveSelectionNoPP[]; +extern u8 BattleScript_NoMovesLeft[]; +extern u8 BattleScript_WishComesTrue[]; +extern u8 BattleScript_IngrainTurnHeal[]; +extern u8 BattleScript_LeechSeedTurnDrain[]; +extern u8 BattleScript_PoisonTurnDmg[]; +extern u8 BattleScript_BurnTurnDmg[]; +extern u8 BattleScript_NightmareTurnDmg[]; +extern u8 BattleScript_CurseTurnDmg[]; +extern u8 BattleScript_WrapTurnDmg[]; +extern u8 BattleScript_WrapEnds[]; +extern u8 BattleScript_DisabledNoMore[]; +extern u8 BattleScript_EncoredNoMore[]; + +extern u8 gUnknown_081D9030[]; +extern u8 gUnknown_081D8F62[]; +extern u8 gUnknown_081D8FFF[]; +extern u8 gUnknown_081D8F7D[]; +extern u8 gUnknown_081D9016[]; +extern u8 gUnknown_081D9008[]; +extern u8 gUnknown_081D9041[]; +extern u8 gUnknown_081D950F[]; //uproar wakeup BS +extern u8 gUnknown_081D957E[]; //uproar BS +extern u8 BattleScript_ThrashConfuses[]; +extern u8 BattleScript_YawnMakesAsleep[]; +extern u8 BattleScript_FutureSightHits[]; +extern u8 BattleScript_PerishSongHits[]; +extern u8 BattleScript_PerishSongTimerGoesDown[]; +extern u8 gUnknown_081D8C72[]; +extern u8 gUnknown_081D8C7B[]; + +extern u8 BattleScript_MoveUsedIsAsleep[]; +extern u8 BattleScript_MoveUsedWokeUp[]; +extern u8 BattleScript_MoveUsedIsFrozen[]; +extern u8 BattleScript_MoveUsedUnfroze[]; +extern u8 BattleScript_MoveUsedLoafingAround[]; +extern u8 BattleScript_MoveUsedMustRecharge[]; +extern u8 BattleScript_MoveUsedFlinched[]; +extern u8 BattleScript_MoveUsedIsDisabled[]; +extern u8 BattleScript_MoveUsedIsTaunted[]; +extern u8 BattleScript_MoveUsedIsImprisoned[]; +extern u8 BattleScript_MoveUsedIsConfused[]; +extern u8 BattleScript_MoveUsedIsConfusedNoMore[]; +extern u8 BattleScript_MoveUsedIsParalyzed[]; +extern u8 BattleScript_MoveUsedIsParalyzedCantAttack[]; +extern u8 BattleScript_MoveUsedIsInLove[]; +extern u8 BattleScript_BideStoringEnergy[]; +extern u8 BattleScript_BideAttack[]; +extern u8 BattleScript_BideNoEnergyToAttack[]; + +extern u8 gUnknown_081D901D[]; //load weather from overworld +extern u8 BattleScript_DrizzleActivates[]; +extern u8 BattleScript_SandstreamActivates[]; +extern u8 BattleScript_DroughtActivates[]; +extern u8 BattleScript_CastformChange[]; +extern u8 BattleScript_RainDishActivates[]; +extern u8 BattleScript_ShedSkinActivates[]; +extern u8 BattleScript_SpeedBoostActivates[]; +extern u8 BattleScript_SoundproofProtected[]; +extern u8 BattleScript_MoveHPDrain[]; +extern u8 BattleScript_MoveHPDrain_PPLoss[]; +extern u8 BattleScript_FlashFireBoost[]; +extern u8 BattleScript_FlashFireBoost_PPLoss[]; +extern u8 BattleScript_MoveHPDrain_FullHP[]; +extern u8 BattleScript_MoveHPDrain_FullHP_PPLoss[]; +extern u8 BattleScript_ColorChangeActivates[]; +extern u8 BattleScript_RoughSkinActivates[]; +extern u8 BattleScript_ApplySecondaryEffect[]; +extern u8 BattleScript_CuteCharmActivates[]; +extern u8 gUnknown_081D9956[]; //ability status clear +extern u8 BattleScript_SynchronizeActivates[]; +extern u8 gUnknown_081D978C[]; //intimidate1 +extern u8 gUnknown_081D9795[]; //intimidate2 +extern u8 BattleScript_TraceActivates[]; + +extern u8 BattleScript_WhiteHerbEnd2[]; +extern u8 BattleScript_WhiteHerbRet[]; +extern u8 BattleScript_ItemHealHP_RemoveItem[]; +extern u8 BattleScript_BerryPPHealEnd2[]; +extern u8 BattleScript_ItemHealHP_End2[]; +extern u8 BattleScript_BerryConfuseHealEnd2[]; +extern u8 BattleScript_BerryStatRaiseEnd2[]; +extern u8 BattleScript_BerryFocusEnergyEnd2[]; +extern u8 BattleScript_BerryCurePrlzEnd2[]; +extern u8 BattleScript_BerryCurePsnEnd2[]; +extern u8 BattleScript_BerryCureBrnEnd2[]; +extern u8 BattleScript_BerryCureFrzEnd2[]; +extern u8 BattleScript_BerryCureSlpEnd2[]; +extern u8 BattleScript_BerryCureConfusionEnd2[]; +extern u8 gUnknown_081D9A44[]; //berry cure any status end2 +extern u8 BattleScript_BerryCureParRet[]; +extern u8 BattleScript_BerryCurePsnRet[]; +extern u8 BattleScript_BerryCureBrnRet[]; +extern u8 BattleScript_BerryCureFrzRet[]; +extern u8 BattleScript_BerryCureSlpRet[]; +extern u8 BattleScript_BerryCureConfusionRet[]; +extern u8 gUnknown_081D9A4A[]; //berry cure any status return + +extern u8 BattleScript_ItemHealHP_Ret[]; + +extern u8 gUnknown_081D995F[]; //disobedient while asleep +extern u8 gUnknown_081D996F[]; //disobedient, uses a random move +extern u8 gUnknown_081D9989[]; //disobedient, went to sleep +extern u8 gUnknown_081D99A0[]; //disobedient, hits itself + +#define CHOICED_MOVE(bank)(((u16*)(&ewram[bank * 2 + 0x160e8]))) + +//array entries for battle communication +#define MOVE_EFFECT_BYTE 0x3 +#define MULTISTRING_CHOOSER 0x5 +#define MSG_DISPLAY 0x7 + +void b_movescr_stack_push(u8* BS_ptr) +{ + B_BATTLESCRIPTS_STACK->ptr[B_BATTLESCRIPTS_STACK->size++] = BS_ptr; +} + +void b_movescr_stack_push_cursor(void) +{ + B_BATTLESCRIPTS_STACK->ptr[B_BATTLESCRIPTS_STACK->size++] = gBattlescriptCurrInstr; +} + +void b_movescr_stack_pop_cursor(void) +{ + gBattlescriptCurrInstr = B_BATTLESCRIPTS_STACK->ptr[--B_BATTLESCRIPTS_STACK->size]; +} + +u8 sub_8015894(void) //msg can't select a move +{ + u8 limitations = 0; + u16 move = gBattleMons[gActiveBank].moves[gBattleBufferB[gActiveBank][2]]; + u8 holdEffect; + u16* choicedMove = CHOICED_MOVE(gActiveBank); + if (gDisableStructs[gActiveBank].disabledMove == move && move) + { + BATTLE_STRUCT->scriptingActive = gActiveBank; + gCurrentMove = move; + gUnknown_02024C1C[gActiveBank] = BattleScript_MoveSelectionDisabledMove; + limitations++; + } + if (move == gLastUsedMove[gActiveBank] && move != MOVE_STRUGGLE && gBattleMons[gActiveBank].status2 & STATUS2_TORMENT) + { + CancelMultiTurnMoves(gActiveBank); + gUnknown_02024C1C[gActiveBank] = BattleScript_MoveSelectionTormented; + limitations++; + } + if (gDisableStructs[gActiveBank].tauntTimer1 && gBattleMoves[move].power == 0) + { + gCurrentMove = move; + gUnknown_02024C1C[gActiveBank] = BattleScript_MoveSelectionTaunted; + limitations++; + } + if (IsImprisoned(gActiveBank, move)) + { + gCurrentMove = move; + gUnknown_02024C1C[gActiveBank] = BattleScript_MoveSelectionImprisoned; + limitations++; + } + if (gBattleMons[gActiveBank].item == ITEM_ENIGMA_BERRY) + holdEffect = gEnigmaBerries[gActiveBank].holdEffect; + else + holdEffect = ItemId_GetHoldEffect(gBattleMons[gActiveBank].item); + gStringBank = gActiveBank; + if (holdEffect == HOLD_EFFECT_CHOICE_BAND && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != move) + { + gCurrentMove = *choicedMove; + gLastUsedItem = gBattleMons[gActiveBank].item; + gUnknown_02024C1C[gActiveBank] = BattleScript_MoveSelectionChoiceBanded; + limitations++; + } + if (gBattleMons[gActiveBank].pp[gBattleBufferB[gActiveBank][2]] == 0) + { + gUnknown_02024C1C[gActiveBank] = BattleScript_MoveSelectionNoPP; + limitations++; + } + return limitations; +} + +#define MOVE_LIMITATION_ZEROMOVE (1 << 0) +#define MOVE_LIMITATION_PP (1 << 1) +#define MOVE_LIMITATION_DISABLED (1 << 2) +#define MOVE_LIMITATION_TORMENTED (1 << 3) +#define MOVE_LIMITATION_TAUNT (1 << 4) +#define MOVE_LIMITATION_IMPRISION (1 << 5) + +u8 CheckMoveLimitations(u8 bank, u8 unusableMoves, u8 check) +{ + u8 holdEffect; + u16* choicedMove = CHOICED_MOVE(bank); + s32 i; + if (gBattleMons[bank].item == ITEM_ENIGMA_BERRY) + holdEffect = gEnigmaBerries[bank].holdEffect; + else + holdEffect = ItemId_GetHoldEffect(gBattleMons[bank].item); + gStringBank = bank; + for (i = 0; i < 4; i++) + { + if (gBattleMons[bank].moves[i] == 0 && check & MOVE_LIMITATION_ZEROMOVE) + unusableMoves |= gBitTable[i]; + if (gBattleMons[bank].pp[i] == 0 && check & MOVE_LIMITATION_PP) + unusableMoves |= gBitTable[i]; + if (gBattleMons[bank].moves[i] == gDisableStructs[bank].disabledMove && check & MOVE_LIMITATION_DISABLED) + unusableMoves |= gBitTable[i]; + if (gBattleMons[bank].moves[i] == gLastUsedMove[bank] && check & MOVE_LIMITATION_TORMENTED && gBattleMons[bank].status2 & STATUS2_TORMENT) + unusableMoves |= gBitTable[i]; + if (gDisableStructs[bank].tauntTimer1 && check & MOVE_LIMITATION_TAUNT && gBattleMoves[gBattleMons[bank].moves[i]].power == 0) + unusableMoves |= gBitTable[i]; + if (IsImprisoned(bank, gBattleMons[bank].moves[i]) && check & MOVE_LIMITATION_IMPRISION) + unusableMoves |= gBitTable[i]; + if (gDisableStructs[bank].encoreTimer1 && gDisableStructs[bank].encoredMove != gBattleMons[bank].moves[i]) + unusableMoves |= gBitTable[i]; + if (holdEffect == HOLD_EFFECT_CHOICE_BAND && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != gBattleMons[bank].moves[i]) + unusableMoves |= gBitTable[i]; + } + return unusableMoves; +} + +bool8 AreAllMovesUnusable(void) +{ + u8 unusable; + unusable = CheckMoveLimitations(gActiveBank, 0, 0xFF); + if (unusable == 0xF) //all moves are unusable + { + gProtectStructs[gActiveBank].onlyStruggle = 1; + gUnknown_02024C1C[gActiveBank] = BattleScript_NoMovesLeft; + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + gBattleBufferB[gActiveBank][3] = GetBankByPlayerAI((GetBankIdentity(gActiveBank) ^ 1) | (Random() & 2)); + else + gBattleBufferB[gActiveBank][3] = GetBankByPlayerAI(GetBankIdentity(gActiveBank) ^ 1); + } + else + gProtectStructs[gActiveBank].onlyStruggle = 0; + return (unusable == 0xF); +} + +u8 IsImprisoned(u8 bank, u16 move) +{ + u8 imprisionedMoves = 0; + u8 bankSide = GetBankSide(bank); + s32 i; + for (i = 0; i < gNoOfAllBanks; i++) + { + if (bankSide != GetBankSide(i) && gStatuses3[i] & STATUS3_IMPRISIONED) + { + s32 j; + for (j = 0; j < 4; j++) + { + if (move == gBattleMons[i].moves[j]) + break; + } + if (j < 4) + imprisionedMoves++; + } + } + return imprisionedMoves; +} + +u8 UpdateTurnCounters(void) +{ + u8 effect = 0; + s32 i; + + for (gBankAttacker = 0; gBankAttacker < gNoOfAllBanks && gAbsentBankFlags & gBitTable[gBankAttacker]; gBankAttacker++) + { + } + for (gBankTarget = 0; gBankTarget < gNoOfAllBanks && gAbsentBankFlags & gBitTable[gBankTarget]; gBankTarget++) + { + } + + do + { + u8 sideBank; + + switch (BATTLE_STRUCT->turncountersTracker) + { + case 0: + for (i = 0; i < gNoOfAllBanks; i++) + { + gTurnOrder[i] = i; + } + for (i = 0; i < gNoOfAllBanks - 1; i++) + { + s32 j; + for (j = i + 1; j < gNoOfAllBanks; j++) + { + if (GetWhoStrikesFirst(gTurnOrder[i], gTurnOrder[j], 0)) + sub_8012FBC(i, j); + } + } + BATTLE_STRUCT->turncountersTracker++; + BATTLE_STRUCT->turnSideTracker = 0; + case 1: + while (BATTLE_STRUCT->turnSideTracker < 2) + { + gActiveBank = gBankAttacker = sideBank = BATTLE_STRUCT->turnSideTracker; + + if (gSideAffecting[sideBank] & SIDE_STATUS_REFLECT) + { + if (--gSideTimer[sideBank].reflectTimer == 0) + { + + gSideAffecting[sideBank] &= ~SIDE_STATUS_REFLECT; + b_call_bc_move_exec(gUnknown_081D9030); + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = MOVE_REFLECT; + gBattleTextBuff1[3] = MOVE_REFLECT >> 8; + gBattleTextBuff1[4] = EOS; + effect++; + } + } + BATTLE_STRUCT->turnSideTracker++; + if (effect) + break; + } + if (!effect) + { + BATTLE_STRUCT->turncountersTracker++; + BATTLE_STRUCT->turnSideTracker = 0; + } + break; + case 2: + while (BATTLE_STRUCT->turnSideTracker < 2) + { + gActiveBank = gBankAttacker = sideBank = BATTLE_STRUCT->turnSideTracker; + if (gSideAffecting[sideBank] & SIDE_STATUS_LIGHTSCREEN) + { + if (--gSideTimer[sideBank].lightscreenTimer == 0) + { + gSideAffecting[sideBank] &= ~SIDE_STATUS_LIGHTSCREEN; + b_call_bc_move_exec(gUnknown_081D9030); + gBattleCommunication[MULTISTRING_CHOOSER] = sideBank; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = MOVE_LIGHT_SCREEN; + gBattleTextBuff1[3] = MOVE_LIGHT_SCREEN >> 8; + gBattleTextBuff1[4] = EOS; + effect++; + } + } + BATTLE_STRUCT->turnSideTracker++; + if (effect) + break; + } + if (!effect) + { + BATTLE_STRUCT->turncountersTracker++; + BATTLE_STRUCT->turnSideTracker = 0; + } + break; + case 3: + while (BATTLE_STRUCT->turnSideTracker < 2) + { + gActiveBank = gBankAttacker = sideBank = BATTLE_STRUCT->turnSideTracker; + if (gSideTimer[sideBank].mistTimer && --gSideTimer[sideBank].mistTimer == 0) + { + gSideAffecting[sideBank] &= ~SIDE_STATUS_MIST; + b_call_bc_move_exec(gUnknown_081D9030); + gBattleCommunication[MULTISTRING_CHOOSER] = sideBank; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = MOVE_MIST; + gBattleTextBuff1[3] = MOVE_MIST >> 8; + gBattleTextBuff1[4] = EOS; + effect++; + } + BATTLE_STRUCT->turnSideTracker++; + if (effect) + break; + } + if (!effect) + { + BATTLE_STRUCT->turncountersTracker++; + BATTLE_STRUCT->turnSideTracker = 0; + } + break; + case 4: + while (BATTLE_STRUCT->turnSideTracker < 2) + { + gActiveBank = gBankAttacker = sideBank = BATTLE_STRUCT->turnSideTracker; + if (gSideAffecting[sideBank] & SIDE_STATUS_SAFEGUARD) + { + if (--gSideTimer[sideBank].safeguardTimer == 0) + { + gSideAffecting[sideBank] &= ~SIDE_STATUS_SAFEGUARD; + b_call_bc_move_exec(gUnknown_081D9041); + effect++; + } + } + BATTLE_STRUCT->turnSideTracker++; + if (effect) + break; + } + if (!effect) + { + BATTLE_STRUCT->turncountersTracker++; + BATTLE_STRUCT->turnSideTracker = 0; + } + break; + case 5: + while (BATTLE_STRUCT->turnSideTracker < gNoOfAllBanks) + { + gActiveBank = gTurnOrder[BATTLE_STRUCT->turnSideTracker]; + if (gWishFutureKnock.wishCounter[gActiveBank] && --gWishFutureKnock.wishCounter[gActiveBank] == 0 && gBattleMons[gActiveBank].hp) + { + gBankTarget = gActiveBank; + b_call_bc_move_exec(BattleScript_WishComesTrue); + effect++; + } + BATTLE_STRUCT->turnSideTracker++; + if (effect) + break; + } + if (!effect) + { + BATTLE_STRUCT->turncountersTracker++; + } + break; + case 6: + if (gBattleWeather & WEATHER_RAIN_ANY) + { + if (!(gBattleWeather & WEATHER_RAIN_PERMANENT)) + { + if (--gWishFutureKnock.weatherDuration == 0) + { + gBattleWeather &= ~WEATHER_RAIN_TEMPORARY; + gBattleWeather &= ~WEATHER_RAIN_DOWNPOUR; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else if (gBattleWeather & WEATHER_RAIN_DOWNPOUR) + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + else if (gBattleWeather & WEATHER_RAIN_DOWNPOUR) + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + b_call_bc_move_exec(gUnknown_081D8F62); + effect++; + } + BATTLE_STRUCT->turncountersTracker++; + break; + case 7: + if (gBattleWeather & WEATHER_SANDSTORM_ANY) + { + if (!(gBattleWeather & WEATHER_SANDSTORM_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) + { + gBattleWeather &= ~WEATHER_SANDSTORM_TEMPORARY; + gBattlescriptCurrInstr = gUnknown_081D8FFF; + } + else + gBattlescriptCurrInstr = gUnknown_081D8F7D; + + BATTLE_STRUCT->animArg1 = 0xC; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + b_call_bc_move_exec(gBattlescriptCurrInstr); + effect++; + } + BATTLE_STRUCT->turncountersTracker++; + break; + case 8: + if (gBattleWeather & WEATHER_SUN_ANY) + { + if (!(gBattleWeather & WEATHER_SUN_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) + { + gBattleWeather &= ~WEATHER_SUN_TEMPORARY; + gBattlescriptCurrInstr = gUnknown_081D9016; + } + else + gBattlescriptCurrInstr = gUnknown_081D9008; + + b_call_bc_move_exec(gBattlescriptCurrInstr); + effect++; + } + BATTLE_STRUCT->turncountersTracker++; + break; + case 9: + if (gBattleWeather & WEATHER_HAIL) + { + if (--gWishFutureKnock.weatherDuration == 0) + { + gBattleWeather &= ~WEATHER_HAIL; + gBattlescriptCurrInstr = gUnknown_081D8FFF; + } + else + gBattlescriptCurrInstr = gUnknown_081D8F7D; + + BATTLE_STRUCT->animArg1 = 0xD; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + b_call_bc_move_exec(gBattlescriptCurrInstr); + effect++; + } + BATTLE_STRUCT->turncountersTracker++; + break; + case 10: + effect++; + break; + } + } while (effect == 0); + return (gBattleMainFunc != BattleTurnPassed); +} + +#define TURNBASED_MAX_CASE 19 + +u8 TurnBasedEffects(void) +{ + u8 effect = 0; + + gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20); + while (BATTLE_STRUCT->turnEffectsBank < gNoOfAllBanks && BATTLE_STRUCT->turnEffectsTracker <= TURNBASED_MAX_CASE) + { + gActiveBank = gBankAttacker = gTurnOrder[BATTLE_STRUCT->turnEffectsBank]; + if (gAbsentBankFlags & gBitTable[gActiveBank]) + { + BATTLE_STRUCT->turnEffectsBank++; + } + else + { + switch (BATTLE_STRUCT->turnEffectsTracker) + { + case 0: // ingrain + if ((gStatuses3[gActiveBank] & STATUS3_ROOTED) + && gBattleMons[gActiveBank].hp != gBattleMons[gActiveBank].maxHP + && gBattleMons[gActiveBank].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + b_call_bc_move_exec(BattleScript_IngrainTurnHeal); + effect++; + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 1: // end turn abilities + if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, gActiveBank, 0, 0, 0)) + effect++; + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 2: // item effects + if (ItemBattleEffects(1, gActiveBank, 0)) + effect++; + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 18: // item effects again + if (ItemBattleEffects(1, gActiveBank, 1)) + effect++; + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 3: // leech seed + if (gStatuses3[gActiveBank] & STATUS3_LEECHSEED && gBattleMons[gStatuses3[gActiveBank] & STATUS3_LEECHSEED_BANK].hp != 0 && gBattleMons[gActiveBank].hp != 0) + { + gBankTarget = gStatuses3[gActiveBank] & STATUS3_LEECHSEED_BANK; //funny how the 'target' is actually the bank that receives HP + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BATTLE_STRUCT->animArg1 = gBankTarget; + BATTLE_STRUCT->animArg2 = gBankAttacker; + b_call_bc_move_exec(BattleScript_LeechSeedTurnDrain); + effect++; + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 4: // poison + if ((gBattleMons[gActiveBank].status1 & STATUS_POISON) && gBattleMons[gActiveBank].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + b_call_bc_move_exec(BattleScript_PoisonTurnDmg); + effect++; + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 5: // toxic poison + if ((gBattleMons[gActiveBank].status1 & STATUS_TOXIC_POISON) && gBattleMons[gActiveBank].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if ((gBattleMons[gActiveBank].status1 & 0xF00) != 0xF00) //not 16 turns + gBattleMons[gActiveBank].status1 += 0x100; + gBattleMoveDamage *= (gBattleMons[gActiveBank].status1 & 0xF00) >> 8; + b_call_bc_move_exec(BattleScript_PoisonTurnDmg); + effect++; + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 6: // burn + if ((gBattleMons[gActiveBank].status1 & STATUS_BURN) && gBattleMons[gActiveBank].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + b_call_bc_move_exec(BattleScript_BurnTurnDmg); + effect++; + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 7: // spooky nightmares + if ((gBattleMons[gActiveBank].status2 & STATUS2_NIGHTMARE) && gBattleMons[gActiveBank].hp != 0) + { + // missing sleep check + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + b_call_bc_move_exec(BattleScript_NightmareTurnDmg); + effect++; + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 8: // curse + if ((gBattleMons[gActiveBank].status2 & STATUS2_CURSED) && gBattleMons[gActiveBank].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + b_call_bc_move_exec(BattleScript_CurseTurnDmg); + effect++; + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 9: // wrap + if ((gBattleMons[gActiveBank].status2 & STATUS2_WRAPPED) && gBattleMons[gActiveBank].hp != 0) + { + gBattleMons[gActiveBank].status2 -= 0x2000; + if (gBattleMons[gActiveBank].status2 & STATUS2_WRAPPED) // damaged by wrap + { + BATTLE_STRUCT->animArg1 = ewram[gActiveBank * 2 + 0x16004]; + BATTLE_STRUCT->animArg2 = ewram[gActiveBank * 2 + 0x16005]; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = ewram[gActiveBank * 2 + 0x16004]; + gBattleTextBuff1[3] = ewram[gActiveBank * 2 + 0x16005]; + gBattleTextBuff1[4] = EOS; + gBattlescriptCurrInstr = BattleScript_WrapTurnDmg; + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } + else // broke free + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = ewram[gActiveBank * 2 + 0x16004]; + gBattleTextBuff1[3] = ewram[gActiveBank * 2 + 0x16005]; + gBattleTextBuff1[4] = EOS; + gBattlescriptCurrInstr = BattleScript_WrapEnds; + } + b_call_bc_move_exec(gBattlescriptCurrInstr); + effect++; + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 10: // uproar + if (gBattleMons[gActiveBank].status2 & STATUS2_UPROAR) + { + for (gBankAttacker = 0; gBankAttacker < gNoOfAllBanks; gBankAttacker++) + { + if ((gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) + && gBattleMons[gBankAttacker].ability != ABILITY_SOUNDPROOF) + { + gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP); + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE); + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + b_call_bc_move_exec(gUnknown_081D950F); + gActiveBank = gBankAttacker; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + break; + } + } + if (gBankAttacker != gNoOfAllBanks) + { + effect = 2; // a pokemon was awaken + break; + } + else + { + gBankAttacker = gActiveBank; + gBattleMons[gActiveBank].status2 -= 0x10; // uproar timer goes down + if (sub_8015660(gActiveBank)) + { + CancelMultiTurnMoves(gActiveBank); + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else if (gBattleMons[gActiveBank].status2 & STATUS2_UPROAR) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattleMons[gActiveBank].status2 |= STATUS2_MULTIPLETURNS; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + CancelMultiTurnMoves(gActiveBank); + } + b_call_bc_move_exec(gUnknown_081D957E); + effect = 1; + } + } + if (effect != 2) + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 11: // thrash + if (gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE) + { + gBattleMons[gActiveBank].status2 -= 0x400; + if (sub_8015660(gActiveBank)) + CancelMultiTurnMoves(gActiveBank); + else if (!(gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE) + && (gBattleMons[gActiveBank].status2 & STATUS2_MULTIPLETURNS)) + { + gBattleMons[gActiveBank].status2 &= ~(STATUS2_MULTIPLETURNS); + if (!(gBattleMons[gActiveBank].status2 & STATUS2_CONFUSION)) + { + gBattleCommunication[MOVE_EFFECT_BYTE] = 0x47; + SetMoveEffect(1, 0); + if (gBattleMons[gActiveBank].status2 & STATUS2_CONFUSION) + b_call_bc_move_exec(BattleScript_ThrashConfuses); + effect++; + } + } + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 12: // disable + if (gDisableStructs[gActiveBank].disableTimer1 != 0) + { + int i; + for (i = 0; i < 4; i++) + { + if (gDisableStructs[gActiveBank].disabledMove == gBattleMons[gActiveBank].moves[i]) + break; + } + if (i == 4) // pokemon does not have the disabled move anymore + { + gDisableStructs[gActiveBank].disabledMove = 0; + gDisableStructs[gActiveBank].disableTimer1 = 0; + } + else if (--gDisableStructs[gActiveBank].disableTimer1 == 0) // disable ends + { + gDisableStructs[gActiveBank].disabledMove = 0; + b_call_bc_move_exec(BattleScript_DisabledNoMore); + effect++; + } + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 13: // encore + if (gDisableStructs[gActiveBank].encoreTimer1 != 0) + { + if (gBattleMons[gActiveBank].moves[gDisableStructs[gActiveBank].encoredMovePos] != gDisableStructs[gActiveBank].encoredMove) // pokemon does not have the encored move anymore + { + gDisableStructs[gActiveBank].encoredMove = 0; + gDisableStructs[gActiveBank].encoreTimer1 = 0; + } + else if (--gDisableStructs[gActiveBank].encoreTimer1 == 0 + || gBattleMons[gActiveBank].pp[gDisableStructs[gActiveBank].encoredMovePos] == 0) + { + gDisableStructs[gActiveBank].encoredMove = 0; + gDisableStructs[gActiveBank].encoreTimer1 = 0; + b_call_bc_move_exec(BattleScript_EncoredNoMore); + effect++; + } + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 14: // lock-on decrement + if (gStatuses3[gActiveBank] & STATUS3_ALWAYS_HITS) + gStatuses3[gActiveBank] -= 0x8; + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 15: // charge + if (gDisableStructs[gActiveBank].chargeTimer1 && --gDisableStructs[gActiveBank].chargeTimer1 == 0) + gStatuses3[gActiveBank] &= ~STATUS3_CHARGED_UP; + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 16: // taunt + if (gDisableStructs[gActiveBank].tauntTimer1) + gDisableStructs[gActiveBank].tauntTimer1--; + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 17: // yawn + if (gStatuses3[gActiveBank] & STATUS3_YAWN) + { + gStatuses3[gActiveBank] -= 0x800; + if (!(gStatuses3[gActiveBank] & STATUS3_YAWN) && !(gBattleMons[gActiveBank].status1 & STATUS_ANY) + && gBattleMons[gActiveBank].ability != ABILITY_VITAL_SPIRIT + && gBattleMons[gActiveBank].ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBank)) + { + CancelMultiTurnMoves(gActiveBank); + gBattleMons[gActiveBank].status1 |= (Random() & 3) + 2; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + gEffectBank = gActiveBank; + b_call_bc_move_exec(BattleScript_YawnMakesAsleep); + effect++; + } + } + BATTLE_STRUCT->turnEffectsTracker++; + break; + case 19: // done + BATTLE_STRUCT->turnEffectsTracker = 0; + BATTLE_STRUCT->turnEffectsBank++; + break; + } + if (effect != 0) + return effect; + } + } + gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20); + return 0; +} + +bool8 sub_80170DC(void) // handle future sight and perish song +{ + gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20); + switch (BATTLE_STRUCT->sub80170DC_Tracker) + { + case 0: // future sight + while (BATTLE_STRUCT->sub80170DC_Bank < gNoOfAllBanks) + { + gActiveBank = BATTLE_STRUCT->sub80170DC_Bank; + if (gAbsentBankFlags & gBitTable[gActiveBank]) + BATTLE_STRUCT->sub80170DC_Bank++; + else + { + BATTLE_STRUCT->sub80170DC_Bank++; + if (gWishFutureKnock.futureSightCounter[gActiveBank] && --gWishFutureKnock.futureSightCounter[gActiveBank] == 0 && gBattleMons[gActiveBank].hp) + { + if (gWishFutureKnock.futureSightMove[gActiveBank] == MOVE_FUTURE_SIGHT) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else //Doom Desire + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = gWishFutureKnock.futureSightMove[gActiveBank]; + gBattleTextBuff1[3] = gWishFutureKnock.futureSightMove[gActiveBank] >> 8; + gBattleTextBuff1[4] = 0xFF; + gBankTarget = gActiveBank; + gBankAttacker = gWishFutureKnock.futureSightAttacker[gActiveBank]; + gBattleMoveDamage = gWishFutureKnock.futureSightDmg[gActiveBank]; + gSpecialStatuses[gBankTarget].moveturnLostHP = 0xFFFF; + b_call_bc_move_exec(BattleScript_FutureSightHits); + return 1; + } + } + } + BATTLE_STRUCT->sub80170DC_Tracker = 1; + BATTLE_STRUCT->sub80170DC_Bank = 0; + case 1: // perish song + while (BATTLE_STRUCT->sub80170DC_Bank < gNoOfAllBanks) + { + gActiveBank = gBankAttacker = gTurnOrder[BATTLE_STRUCT->sub80170DC_Bank]; + if (gAbsentBankFlags & gBitTable[gActiveBank]) + BATTLE_STRUCT->sub80170DC_Bank++; + else + { + BATTLE_STRUCT->sub80170DC_Bank++; + if (gStatuses3[gActiveBank] & STATUS3_PERISH_SONG) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 1; + gBattleTextBuff1[2] = 1; + gBattleTextBuff1[3] = 1; + gBattleTextBuff1[4] = gDisableStructs[gActiveBank].perishSong1; + gBattleTextBuff1[5] = 0xFF; + if (gDisableStructs[gActiveBank].perishSong1 == 0) + { + gStatuses3[gActiveBank] &= ~(STATUS3_PERISH_SONG); + gBattleMoveDamage = gBattleMons[gActiveBank].hp; + gBattlescriptCurrInstr = BattleScript_PerishSongHits; + } + else + { + gDisableStructs[gActiveBank].perishSong1--; + gBattlescriptCurrInstr = BattleScript_PerishSongTimerGoesDown; + } + b_call_bc_move_exec(gBattlescriptCurrInstr); + return 1; + } + } + } + break; + } + gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20); + return 0; +} + +#define sub_80173A4_MAX_CASE 7 + +bool8 sub_80173A4(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + return 0; + do + { + int i; + switch (BATTLE_STRUCT->sub80173A4_Tracker) + { + case 0: + BATTLE_STRUCT->unk1605A = 0; + BATTLE_STRUCT->sub80173A4_Tracker++; + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gAbsentBankFlags & gBitTable[i] && !sub_8018018(i, 6, 6)) + gAbsentBankFlags &= ~(gBitTable[i]); + } + case 1: + do + { + gBank1 = gBankTarget = BATTLE_STRUCT->unk1605A; + if (gBattleMons[BATTLE_STRUCT->unk1605A].hp == 0 && !(BATTLE_STRUCT->unk16113 & gBitTable[gBattlePartyID[BATTLE_STRUCT->unk1605A]]) && !(gAbsentBankFlags & gBitTable[BATTLE_STRUCT->unk1605A])) + { + b_call_bc_move_exec(gUnknown_081D8C72); + BATTLE_STRUCT->sub80173A4_Tracker = 2; + return 1; + } + } while (++BATTLE_STRUCT->unk1605A != gNoOfAllBanks); + BATTLE_STRUCT->sub80173A4_Tracker = 3; + break; + case 2: + sub_8015740(gBank1); + if (++BATTLE_STRUCT->unk1605A == gNoOfAllBanks) + BATTLE_STRUCT->sub80173A4_Tracker = 3; + else + BATTLE_STRUCT->sub80173A4_Tracker = 1; + break; + case 3: + BATTLE_STRUCT->unk1605A = 0; + BATTLE_STRUCT->sub80173A4_Tracker++; + case 4: + do + { + gBank1 = gBankTarget = BATTLE_STRUCT->unk1605A; //or should banks be switched? + if (gBattleMons[BATTLE_STRUCT->unk1605A].hp == 0 && !(gAbsentBankFlags & gBitTable[BATTLE_STRUCT->unk1605A])) + { + b_call_bc_move_exec(gUnknown_081D8C7B); + BATTLE_STRUCT->sub80173A4_Tracker = 5; + return 1; + } + } while (++BATTLE_STRUCT->unk1605A != gNoOfAllBanks); + BATTLE_STRUCT->sub80173A4_Tracker = 6; + break; + case 5: + if (++BATTLE_STRUCT->unk1605A == gNoOfAllBanks) + BATTLE_STRUCT->sub80173A4_Tracker = 6; + else + BATTLE_STRUCT->sub80173A4_Tracker = 4; + break; + case 6: + if (AbilityBattleEffects(9, 0, 0, 0, 0) || AbilityBattleEffects(0xB, 0, 0, 0, 0) || ItemBattleEffects(1, 0, 1) || AbilityBattleEffects(6, 0, 0, 0, 0)) + return 1; + BATTLE_STRUCT->sub80173A4_Tracker++; + break; + case 7: + break; + } + } while (BATTLE_STRUCT->sub80173A4_Tracker != sub_80173A4_MAX_CASE); + return 0; +} + +void b_clear_atk_up_if_hit_flag_unless_enraged(void) +{ + int i; + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].status2 & STATUS2_RAGE && gChosenMovesByBanks[i] != MOVE_RAGE) + gBattleMons[i].status2 &= ~(STATUS2_RAGE); + } +} + +#define ATKCANCELLER_MAX_CASE 14 + +u8 AtkCanceller_UnableToUseMove(void) +{ + u8 effect = 0; + s32* bideDmg = &BATTLE_STRUCT->bideDmg; + do + { + switch (BATTLE_STRUCT->atkCancellerTracker) + { + case 0: // flags clear + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_DESTINY_BOND); + gStatuses3[gBankAttacker] &= ~(STATUS3_GRUDGE); + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 1: // check being asleep + if (gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) + { + if (UproarWakeUpCheck(gBankAttacker)) + { + gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP); + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE); + b_movescr_stack_push_cursor(); + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp; + effect = 2; + } + else + { + u8 toSub; + if (gBattleMons[gBankAttacker].ability == ABILITY_EARLY_BIRD) + toSub = 2; + else + toSub = 1; + if ((gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) < toSub) + gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP); + else + gBattleMons[gBankAttacker].status1 -= toSub; + if (gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) + { + if (gCurrentMove != MOVE_SNORE && gCurrentMove != MOVE_SLEEP_TALK) + { + gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + effect = 2; + } + } + else + { + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE); + b_movescr_stack_push_cursor(); + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp; + effect = 2; + } + } + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 2: // check being frozen + if (gBattleMons[gBankAttacker].status1 & STATUS_FREEZE) + { + if (Random() % 5) + { + if (gBattleMoves[gCurrentMove].effect != EFFECT_THAW_HIT) // unfreezing via a move effect happens in case 13 + { + gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen; + gHitMarker |= HITMARKER_NO_ATTACKSTRING; + } + else + { + BATTLE_STRUCT->atkCancellerTracker++; + break; + } + } + else // unfreeze + { + gBattleMons[gBankAttacker].status1 &= ~(STATUS_FREEZE); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + effect = 2; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 3: // truant + if (gBattleMons[gBankAttacker].ability == ABILITY_TRUANT && gDisableStructs[gBankAttacker].truantCounter) + { + CancelMultiTurnMoves(gBankAttacker); + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; + gBattleMoveFlags |= MOVESTATUS_MISSED; + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 4: // recharge + if (gBattleMons[gBankAttacker].status2 & STATUS2_RECHARGE) + { + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_RECHARGE); + gDisableStructs[gBankAttacker].rechargeCounter = 0; + CancelMultiTurnMoves(gBankAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 5: // flinch + if (gBattleMons[gBankAttacker].status2 & STATUS2_FLINCHED) + { + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_FLINCHED); + gProtectStructs[gBankAttacker].flinchImmobility = 1; + CancelMultiTurnMoves(gBankAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 6: // disabled move + if (gDisableStructs[gBankAttacker].disabledMove == gCurrentMove && gDisableStructs[gBankAttacker].disabledMove != 0) + { + gProtectStructs[gBankAttacker].usedDisabledMove = 1; + BATTLE_STRUCT->scriptingActive = gBankAttacker; + CancelMultiTurnMoves(gBankAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 7: // taunt + if (gDisableStructs[gBankAttacker].tauntTimer1 && gBattleMoves[gCurrentMove].power == 0) + { + gProtectStructs[gBankAttacker].usedTauntedMove = 1; + CancelMultiTurnMoves(gBankAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 8: // imprisoned + if (IsImprisoned(gBankAttacker, gCurrentMove)) + { + gProtectStructs[gBankAttacker].usedImprisionedMove = 1; + CancelMultiTurnMoves(gBankAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 9: // confusion + if (gBattleMons[gBankAttacker].status2 & STATUS2_CONFUSION) + { + gBattleMons[gBankAttacker].status2--; + if (gBattleMons[gBankAttacker].status2 & STATUS2_CONFUSION) + { + if (Random() & 1) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + b_movescr_stack_push_cursor(); + } + else // confusion dmg + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBankTarget = gBankAttacker; + gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankAttacker], MOVE_POUND, 0, 40, 0, gBankAttacker, gBankAttacker); + gProtectStructs[gBankAttacker].confusionSelfDmg = 1; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + } + gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused; + } + else // snapped out of confusion + { + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfusedNoMore; + } + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 10: // paralysis + if (gBattleMons[gBankAttacker].status1 & STATUS_PARALYSIS && (Random() % 4) == 0) + { + gProtectStructs[gBankAttacker].prlzImmobility = 1; + CancelMultiTurnMoves(gBankAttacker); + gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 11: // infatuation + if (gBattleMons[gBankAttacker].status2 & STATUS2_INFATUATION) + { + BATTLE_STRUCT->scriptingActive = CountTrailingZeroBits((gBattleMons[gBankAttacker].status2 & STATUS2_INFATUATION) >> 0x10); + if (Random() & 1) + b_movescr_stack_push_cursor(); + else + { + b_movescr_stack_push(BattleScript_MoveUsedIsParalyzedCantAttack); + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + gProtectStructs[gBankAttacker].loveImmobility = 1; + CancelMultiTurnMoves(gBankAttacker); + } + gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove; + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 12: // bide + if (gBattleMons[gBankAttacker].status2 & STATUS2_BIDE) + { + gBattleMons[gBankAttacker].status2 -= 0x100; + if (gBattleMons[gBankAttacker].status2 & STATUS2_BIDE) + gBattlescriptCurrInstr = BattleScript_BideStoringEnergy; + else + { + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS); + if (gTakenDmg[gBankAttacker]) + { + gCurrentMove = MOVE_BIDE; + *bideDmg = gTakenDmg[gBankAttacker] * 2; + gBankTarget = gTakenDmgBanks[gBankAttacker]; + if (gAbsentBankFlags & gBitTable[gBankTarget]) + gBankTarget = GetMoveTarget(MOVE_BIDE, 1); + gBattlescriptCurrInstr = BattleScript_BideAttack; + } + else + gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack; + } + effect = 1; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 13: // move thawing + if (gBattleMons[gBankAttacker].status1 & STATUS_FREEZE) + { + if (gBattleMoves[gCurrentMove].effect == EFFECT_THAW_HIT) + { + gBattleMons[gBankAttacker].status1 &= ~(STATUS_FREEZE); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + effect = 2; + } + BATTLE_STRUCT->atkCancellerTracker++; + break; + case 14: // last case + break; + } + + } while (BATTLE_STRUCT->atkCancellerTracker != ATKCANCELLER_MAX_CASE && effect == 0); + + if (effect == 2) + { + gActiveBank = gBankAttacker; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + } + return effect; +} + +bool8 sub_8018018(u8 bank, u8 r1, u8 r2) +{ + struct Pokemon* party; + u8 r7; + u8 r6; + s32 i; + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + return 0; + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + r7 = sub_803FC34(bank); + if (GetBankSide(bank) == 0) + party = gPlayerParty; + else + party = gEnemyParty; + r6 = sub_803FBFC(r7); + for (i = r6 * 3; i < r6 * 3 + 3; i++) + { + if (GetMonData(&party[i], MON_DATA_HP) && GetMonData(&party[i], MON_DATA_SPECIES2) && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG) + break; + } + return (i == r6 * 3 + 3); + } + else + { + if (GetBankSide(bank) == 1) + { + r7 = GetBankByPlayerAI(1); + r6 = GetBankByPlayerAI(3); + party = gEnemyParty; + } + else + { + r7 = GetBankByPlayerAI(0); + r6 = GetBankByPlayerAI(2); + party = gPlayerParty; + } + if (r1 == 6) + r1 = gBattlePartyID[r7]; + if (r2 == 6) + r2 = gBattlePartyID[r6]; + for (i = 0; i < 6; i++) + { + if (GetMonData(&party[i], MON_DATA_HP) && GetMonData(&party[i], MON_DATA_SPECIES2) && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG && i != r1 && i != r2 && i != ewram[r7 + 0x16068] && i != ewram[r6 + 0x16068]) + break; + } + return (i == 6); + } +} + +enum +{ + CASTFORM_NO_CHANGE, //0 + CASTFORM_TO_NORMAL, //1 + CASTFORM_TO_FIRE, //2 + CASTFORM_TO_WATER, //3 + CASTFORM_TO_ICE, //4 +}; + +u8 CastformDataTypeChange(u8 bank) +{ + u8 formChange = 0; + if (gBattleMons[bank].species != SPECIES_CASTFORM || gBattleMons[bank].ability != ABILITY_FORECAST || gBattleMons[bank].hp == 0) + return CASTFORM_NO_CHANGE; + if (!WEATHER_HAS_EFFECT && gBattleMons[bank].type1 != TYPE_NORMAL && gBattleMons[bank].type2 != TYPE_NORMAL) + { + gBattleMons[bank].type1 = TYPE_NORMAL; + gBattleMons[bank].type2 = TYPE_NORMAL; + return CASTFORM_TO_NORMAL; + } + if (!WEATHER_HAS_EFFECT) + return CASTFORM_NO_CHANGE; + if (!(gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL)) && gBattleMons[bank].type1 != TYPE_NORMAL && gBattleMons[bank].type2 != TYPE_NORMAL) + { + gBattleMons[bank].type1 = TYPE_NORMAL; + gBattleMons[bank].type2 = TYPE_NORMAL; + formChange = CASTFORM_TO_NORMAL; + } + if (gBattleWeather & WEATHER_SUN_ANY && gBattleMons[bank].type1 != TYPE_FIRE && gBattleMons[bank].type2 != TYPE_FIRE) + { + gBattleMons[bank].type1 = TYPE_FIRE; + gBattleMons[bank].type2 = TYPE_FIRE; + formChange = CASTFORM_TO_FIRE; + } + if (gBattleWeather & WEATHER_RAIN_ANY && gBattleMons[bank].type1 != TYPE_WATER && gBattleMons[bank].type2 != TYPE_WATER) + { + gBattleMons[bank].type1 = TYPE_WATER; + gBattleMons[bank].type2 = TYPE_WATER; + formChange = CASTFORM_TO_WATER; + } + if (gBattleWeather & WEATHER_HAIL && gBattleMons[bank].type1 != TYPE_ICE && gBattleMons[bank].type2 != TYPE_ICE) + { + gBattleMons[bank].type1 = TYPE_ICE; + gBattleMons[bank].type2 = TYPE_ICE; + formChange = CASTFORM_TO_ICE; + } + return formChange; +} + +#ifdef NONMATCHING + +struct Struct2017100 +{ + u32 arr[4]; +}; + +#define ewram17100 (*(struct Struct2017100 *)(ewram + 0x17100)) + +u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg) +{ + u8 effect = 0; + struct Pokemon* pokeAtk; + struct Pokemon* pokeDef; + u16 speciesAtk; + u16 speciesDef; + u32 pidAtk; + u32 pidDef; + + if (gBankAttacker >= gNoOfAllBanks) + gBankAttacker = bank; + if (GetBankSide(gBankAttacker) == 0) + pokeAtk = &gPlayerParty[gBattlePartyID[gBankAttacker]]; + else + pokeAtk = &gEnemyParty[gBattlePartyID[gBankAttacker]]; + + if (gBankTarget >= gNoOfAllBanks) + gBankTarget = bank; + if (GetBankSide(gBankTarget) == 0) + pokeDef = &gPlayerParty[gBattlePartyID[gBankTarget]]; + else + pokeDef = &gEnemyParty[gBattlePartyID[gBankTarget]]; + + speciesAtk = GetMonData(pokeAtk, MON_DATA_SPECIES); + pidAtk = GetMonData(pokeAtk, MON_DATA_PERSONALITY); + + speciesDef = GetMonData(pokeDef, MON_DATA_SPECIES); + pidDef = GetMonData(pokeDef, MON_DATA_PERSONALITY); + + if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) // why isn't that check done at the beginning? + { + //_08018436 + int i; // r4 + u16 move; + // Hmm... + #define moveType moveArg + //u16 moveType; + u8 side; + + if (special) + gLastUsedAbility = special; + else + gLastUsedAbility = gBattleMons[bank].ability; + + if (moveArg) + move = moveArg; + else + move = gCurrentMove; + + if (BATTLE_STRUCT->dynamicMoveType) + moveType = BATTLE_STRUCT->dynamicMoveType & 0x3F; + else + moveType = gBattleMoves[move].type; + + //_080184AC + switch (caseID) + { + case ABILITYEFFECT_ON_SWITCHIN: // 0 + //_08018518 + if (gBankAttacker >= gNoOfAllBanks) + gBankAttacker = bank; + switch (gLastUsedAbility) + { + case 0xFF: //weather from overworld + //_08018586 + switch (weather_get_current()) + { + case 3: + case 5: + case 13: + if (!(gBattleWeather & WEATHER_RAIN_ANY)) + { + gBattleWeather = (WEATHER_RAIN_TEMPORARY | WEATHER_RAIN_PERMANENT); + BATTLE_STRUCT->animArg1 = 0xA; + BATTLE_STRUCT->scriptingActive = bank; + effect++; + } + break; + case 8: + if (!(gBattleWeather & WEATHER_SANDSTORM_ANY)) + { + gBattleWeather = (WEATHER_SANDSTORM_PERMANENT | WEATHER_SANDSTORM_TEMPORARY); + BATTLE_STRUCT->animArg1 = 0xC; + BATTLE_STRUCT->scriptingActive = bank; + effect++; + } + break; + case 12: + if (!(gBattleWeather & WEATHER_SUN_ANY)) + { + gBattleWeather = (WEATHER_SUN_PERMANENT | WEATHER_SUN_TEMPORARY); + BATTLE_STRUCT->animArg1 = 0xB; + BATTLE_STRUCT->scriptingActive = bank; + effect++; + } + break; + } + if (effect) + { + gBattleCommunication[MULTISTRING_CHOOSER] = weather_get_current(); + b_push_move_exec(gUnknown_081D901D); + } + break; + case ABILITY_DRIZZLE: + //_08018680 + if (!(gBattleWeather & WEATHER_RAIN_PERMANENT)) + { + gBattleWeather = (WEATHER_RAIN_PERMANENT | WEATHER_RAIN_TEMPORARY); + b_push_move_exec(BattleScript_DrizzleActivates); + BATTLE_STRUCT->scriptingActive = bank; + effect++; + } + break; + case ABILITY_SAND_STREAM: + //_080186B8 + if (!(gBattleWeather & WEATHER_SANDSTORM_PERMANENT)) + { + gBattleWeather = (WEATHER_SANDSTORM_PERMANENT | WEATHER_SANDSTORM_TEMPORARY); + b_push_move_exec(BattleScript_SandstreamActivates); + BATTLE_STRUCT->scriptingActive = bank; + effect++; + } + break; + case ABILITY_DROUGHT: + //_080186F0 + if (!(gBattleWeather & WEATHER_SUN_PERMANENT)) + { + gBattleWeather = (WEATHER_SUN_PERMANENT | WEATHER_SUN_TEMPORARY); + b_push_move_exec(BattleScript_DroughtActivates); + BATTLE_STRUCT->scriptingActive = bank; + effect++; + } + break; + case ABILITY_INTIMIDATE: + //_08018728 + if (!(gSpecialStatuses[bank].intimidatedPoke)) + { + gStatuses3[bank] |= STATUS3_INTIMIDATE_POKES; + gSpecialStatuses[bank].intimidatedPoke = 1; + } + break; + case ABILITY_FORECAST: + //_0801875C + effect = CastformDataTypeChange(bank); + if (effect != 0) + { + b_push_move_exec(BattleScript_CastformChange); + BATTLE_STRUCT->scriptingActive = bank; + BATTLE_STRUCT->castformToChangeInto = effect - 1; + } + break; + case ABILITY_TRACE: + //_080187A0 + if (!(gSpecialStatuses[bank].traced)) + { + gStatuses3[bank] |= STATUS3_TRACE; + gSpecialStatuses[bank].traced = 1; + } + break; + case ABILITY_CLOUD_NINE: + case ABILITY_AIR_LOCK: + //_080187DC + { + u8 i; + + for (i = 0; i < gNoOfAllBanks; i++) + { + // TODO: i should be in r6 here + //asm("":::"r4","r5"); + effect = CastformDataTypeChange(i); + if (effect != 0) + { + b_push_move_exec(BattleScript_CastformChange); + BATTLE_STRUCT->scriptingActive = i; + BATTLE_STRUCT->castformToChangeInto = effect - 1; + break; + } + } + } + break; + } + break; + case ABILITYEFFECT_ENDTURN: // 1 + //_08018814 + if (gBattleMons[bank].hp != 0) + { + gBankAttacker = bank; + switch (gLastUsedAbility) + { + case ABILITY_RAIN_DISH: + if (WEATHER_HAS_EFFECT && (gBattleWeather & WEATHER_RAIN_ANY) + && gBattleMons[bank].maxHP > gBattleMons[bank].hp) + { + gLastUsedAbility = ABILITY_RAIN_DISH; //why + b_push_move_exec(BattleScript_RainDishActivates); + gBattleMoveDamage = gBattleMons[bank].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + effect++; + } + break; + case ABILITY_SHED_SKIN: + if ((gBattleMons[bank].status1 & STATUS_ANY) && (Random() % 3) == 0) + { + if (gBattleMons[bank].status1 & (STATUS_POISON | STATUS_TOXIC_POISON)) + StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); + if (gBattleMons[bank].status1 & STATUS_SLEEP) + StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); + if (gBattleMons[bank].status1 & STATUS_PARALYSIS) + StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); + if (gBattleMons[bank].status1 & STATUS_BURN) + StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); + if (gBattleMons[bank].status1 & STATUS_FREEZE) + StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); + gBattleMons[bank].status1 = 0; + //gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE); fixed in Emerald + BATTLE_STRUCT->scriptingActive = gActiveBank = bank; + b_push_move_exec(BattleScript_ShedSkinActivates); + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[bank].status1); + MarkBufferBankForExecution(gActiveBank); + effect++; + } + break; + case ABILITY_SPEED_BOOST: + if (gBattleMons[bank].statStages[STAT_STAGE_SPEED] < 0xC && gDisableStructs[bank].isFirstTurn != 2) + { + gBattleMons[bank].statStages[STAT_STAGE_SPEED]++; + BATTLE_STRUCT->animArg1 = 0x11; + BATTLE_STRUCT->animArg2 = 0; + b_push_move_exec(BattleScript_SpeedBoostActivates); + BATTLE_STRUCT->scriptingActive = bank; + effect++; + } + break; + case ABILITY_TRUANT: + gDisableStructs[gBankAttacker].truantCounter ^= 1; + break; + } + } + break; + case ABILITYEFFECT_MOVES_BLOCK: // 2 + //_08018A40 + if (gLastUsedAbility == ABILITY_SOUNDPROOF) + { + for (i = 0; gSoundMovesTable[i] != 0xFFFF; i++) + { + if (gSoundMovesTable[i] == move) + break; + } + if (gSoundMovesTable[i] != 0xFFFF) + { + if (gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS) + gHitMarker |= HITMARKER_NO_PPDEDUCT; + gBattlescriptCurrInstr = BattleScript_SoundproofProtected; + effect = 1; + } + } + break; + case ABILITYEFFECT_ABSORBING: // 3 + //_08018AD8 + if (move) + { + switch (gLastUsedAbility) + { + case ABILITY_VOLT_ABSORB: + if (moveType == TYPE_ELECTRIC && gBattleMoves[move].power != 0) + { + if (gProtectStructs[gBankAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_MoveHPDrain; + else + gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss; + effect = 1; + } + break; + case ABILITY_WATER_ABSORB: + if (moveType == TYPE_WATER && gBattleMoves[move].power != 0) + { + if (gProtectStructs[gBankAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_MoveHPDrain; + else + gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss; + effect = 1; + } + break; + case ABILITY_FLASH_FIRE: + if (moveType == TYPE_FIRE && !(gBattleMons[bank].status1 & STATUS_FREEZE)) + { + if (!(ewram17100.arr[bank] & 1)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + if (gProtectStructs[gBankAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_FlashFireBoost; + else + gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; + ewram17100.arr[bank] |= 1; + effect = 2; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + if (gProtectStructs[gBankAttacker].notFirstStrike) + gBattlescriptCurrInstr = BattleScript_FlashFireBoost; + else + gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; + effect = 2; + } + } + break; + } + if (effect == 1) + { + if (gBattleMons[bank].maxHP == gBattleMons[bank].hp) + { + if ((gProtectStructs[gBankAttacker].notFirstStrike)) + gBattlescriptCurrInstr = BattleScript_MoveHPDrain; + else + gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss; + } + else + { + gBattleMoveDamage = gBattleMons[bank].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + } + } + } + break; + case ABILITYEFFECT_CONTACT: // 4 + //_08018CF0 + switch (gLastUsedAbility) + { + case ABILITY_COLOR_CHANGE: + //_08018DCC + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && move != MOVE_STRUGGLE + && gBattleMoves[move].power != 0 + && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special) + && gBattleMons[bank].type1 != moveType + && gBattleMons[bank].type2 != moveType + && gBattleMons[bank].hp != 0) + { + gBattleMons[bank].type1 = moveType; + gBattleMons[bank].type2 = moveType; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 3; + gBattleTextBuff1[2] = moveType; + gBattleTextBuff1[3] = 0xFF; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_ColorChangeActivates; + effect++; + } + break; + case ABILITY_ROUGH_SKIN: + //_08018E94 + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && gBattleMons[gBankAttacker].hp != 0 + && !gProtectStructs[gBankAttacker].confusionSelfDmg + && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special) + && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)) + { + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_RoughSkinActivates; + effect++; + } + break; + case ABILITY_EFFECT_SPORE: + //_08018F54 + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && gBattleMons[gBankAttacker].hp != 0 + && !gProtectStructs[gBankAttacker].confusionSelfDmg + && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special) + && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + && (Random() % 10) == 0) + { + do + { + gBattleCommunication[MOVE_EFFECT_BYTE] = Random() & 3; + } while (gBattleCommunication[MOVE_EFFECT_BYTE] == 0); + if (gBattleCommunication[MOVE_EFFECT_BYTE] == 3) + gBattleCommunication[MOVE_EFFECT_BYTE] += 2; + gBattleCommunication[MOVE_EFFECT_BYTE] += 0x40; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect; + gHitMarker |= HITMARKER_IGNORE_SAFEGUARD; + effect++; + } + break; + case ABILITY_POISON_POINT: + //_0801904C + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && gBattleMons[gBankAttacker].hp != 0 + && !gProtectStructs[gBankAttacker].confusionSelfDmg + && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special) + && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + && (Random() % 3) == 0) + { + gBattleCommunication[MOVE_EFFECT_BYTE] = 0x42; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect; + gHitMarker |= HITMARKER_IGNORE_SAFEGUARD; + effect++; + } + break; + case ABILITY_STATIC: + //_08019128 + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && gBattleMons[gBankAttacker].hp != 0 + && !gProtectStructs[gBankAttacker].confusionSelfDmg + && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special) + && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + && (Random() % 3) == 0) + { + gBattleCommunication[MOVE_EFFECT_BYTE] = 0x45; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect; + gHitMarker |= HITMARKER_IGNORE_SAFEGUARD; + effect++; + } + break; + case ABILITY_FLAME_BODY: + //_08019204 + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && gBattleMons[gBankAttacker].hp != 0 + && !gProtectStructs[gBankAttacker].confusionSelfDmg + && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special) + && (Random() % 3) == 0) + { + gBattleCommunication[MOVE_EFFECT_BYTE] = 0x43; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect; + gHitMarker |= HITMARKER_IGNORE_SAFEGUARD; + effect++; + } + break; + case ABILITY_CUTE_CHARM: + //_080192E0 + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && gBattleMons[gBankAttacker].hp != 0 + && !gProtectStructs[gBankAttacker].confusionSelfDmg + && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) + && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special) + && gBattleMons[gBankTarget].hp != 0 + && (Random() % 3) == 0 + && gBattleMons[gBankAttacker].ability != ABILITY_OBLIVIOUS + && GetGenderFromSpeciesAndPersonality(speciesAtk, pidAtk) != GetGenderFromSpeciesAndPersonality(speciesDef, pidDef) + && !(gBattleMons[gBankAttacker].status2 & STATUS2_INFATUATION) + && GetGenderFromSpeciesAndPersonality(speciesAtk, pidAtk) != 0xFF + && GetGenderFromSpeciesAndPersonality(speciesDef, pidDef) != 0xFF) + { + gBattleMons[gBankAttacker].status2 |= (gBitTable[gBankTarget] << 0x10); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_CuteCharmActivates; + effect++; + } + break; + } + break; + case ABILITYEFFECT_IMMUNITY: // 5 + //_08019448 + { + #define i bank + for (i = 0; i < gNoOfAllBanks; i++) + { + switch (gBattleMons[i].ability) + { + case ABILITY_IMMUNITY: + if (gBattleMons[i].status1 & (STATUS_POISON | STATUS_TOXIC_POISON | 0xF00)) // TODO: what is 0xF00? + { + StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); + effect = 1; + } + break; + case ABILITY_OWN_TEMPO: + if (gBattleMons[i].status2 & STATUS2_CONFUSION) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); + effect = 2; + } + break; + case ABILITY_LIMBER: + if (gBattleMons[i].status1 & STATUS_PARALYSIS) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); + effect = 1; + } + break; + case ABILITY_INSOMNIA: + case ABILITY_VITAL_SPIRIT: + if (gBattleMons[i].status1 & STATUS_SLEEP) + { + gBattleMons[i].status2 &= ~(STATUS2_NIGHTMARE); + StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); + effect = 1; + } + break; + case ABILITY_WATER_VEIL: + if (gBattleMons[i].status1 & STATUS_BURN) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); + effect = 1; + } + break; + case ABILITY_MAGMA_ARMOR: + if (gBattleMons[i].status1 & STATUS_FREEZE) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); + effect = 1; + } + break; + case ABILITY_OBLIVIOUS: + if (gBattleMons[i].status2 & STATUS2_INFATUATION) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); + effect = 3; + } + break; + } + if (effect) + { + switch (effect) + { + case 1: // status cleared + gBattleMons[i].status1 = 0; + break; + case 2: // get rid of confusion + gBattleMons[i].status2 &= ~(STATUS2_CONFUSION); + break; + case 3: // get rid of infatuation + gBattleMons[i].status2 &= ~(STATUS2_INFATUATION); + break; + } + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = gUnknown_081D9956; + BATTLE_STRUCT->scriptingActive = i; + gActiveBank = i; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + return effect; + } + } + #undef i + } + break; + case ABILITYEFFECT_FORECAST: // 6 + //_080197B4 + { + #define i bank + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].ability == ABILITY_FORECAST) + { + effect = CastformDataTypeChange(i); + if (effect) + { + b_push_move_exec(BattleScript_CastformChange); + BATTLE_STRUCT->scriptingActive = i; + BATTLE_STRUCT->castformToChangeInto = effect - 1; + return effect; + } + } + } + #undef i + } + break; + case ABILITYEFFECT_SYNCHRONIZE: // 7 + //_08019804 + if (gLastUsedAbility == ABILITY_SYNCHRONIZE && (gHitMarker & HITMARKER_SYNCHRONISE_EFFECT)) + { + gHitMarker &= ~(HITMARKER_SYNCHRONISE_EFFECT); + BATTLE_STRUCT->synchroniseEffect &= 0x3F; + if (BATTLE_STRUCT->synchroniseEffect == 6) + BATTLE_STRUCT->synchroniseEffect = 2; + gBattleCommunication[MOVE_EFFECT_BYTE] = BATTLE_STRUCT->synchroniseEffect + 0x40; + BATTLE_STRUCT->scriptingActive = gBankTarget; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_SynchronizeActivates; + gHitMarker |= HITMARKER_IGNORE_SAFEGUARD; + effect++; + } + break; + case ABILITYEFFECT_ATK_SYNCHRONIZE: // 8 + //_08019880 + if (gLastUsedAbility == ABILITY_SYNCHRONIZE && (gHitMarker & HITMARKER_SYNCHRONISE_EFFECT)) + { + gHitMarker &= ~(HITMARKER_SYNCHRONISE_EFFECT); + BATTLE_STRUCT->synchroniseEffect &= 0x3F; + if (BATTLE_STRUCT->synchroniseEffect == 6) + BATTLE_STRUCT->synchroniseEffect = 2; + gBattleCommunication[MOVE_EFFECT_BYTE] = BATTLE_STRUCT->synchroniseEffect; + BATTLE_STRUCT->scriptingActive = gBankAttacker; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_SynchronizeActivates; + gHitMarker |= HITMARKER_IGNORE_SAFEGUARD; + effect++; + } + break; + case ABILITYEFFECT_INTIMIDATE1: // 9 + //_080198FC + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].ability == ABILITY_INTIMIDATE && gStatuses3[i] & STATUS3_INTIMIDATE_POKES) + { + gLastUsedAbility = ABILITY_INTIMIDATE; + gStatuses3[i] &= ~(STATUS3_INTIMIDATE_POKES); + b_push_move_exec(gUnknown_081D978C); + BATTLE_STRUCT->intimidateBank = i; + effect++; + break; + } + } + break; + case ABILITYEFFECT_TRACE: // 11 + //_08019940 + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].ability == ABILITY_TRACE && (gStatuses3[i] & STATUS3_TRACE)) + { + u8 opposite = (GetBankIdentity(i) ^ 1) & 1; + u8 target1 = GetBankByPlayerAI(opposite); + u8 target2 = GetBankByPlayerAI(opposite + 2); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + if (gBattleMons[target1].ability != 0 && gBattleMons[target1].hp != 0 + && gBattleMons[target2].ability != 0 && gBattleMons[target2].hp != 0) + { + //_080199AE + gActiveBank = GetBankByPlayerAI(((Random() & 1) * 2) | opposite); + gBattleMons[i].ability = gBattleMons[gActiveBank].ability; + gLastUsedAbility = gBattleMons[gActiveBank].ability; + effect++; + } + else if (gBattleMons[target1].ability != 0 && gBattleMons[target1].hp != 0) + { + //_08019A34 + gActiveBank = target1; + gBattleMons[i].ability = gBattleMons[gActiveBank].ability; + gLastUsedAbility = gBattleMons[gActiveBank].ability; + effect++; + } + else if (gBattleMons[target2].ability != 0 && gBattleMons[target2].hp != 0) + { + //_08019A78 + gActiveBank = target2; + gBattleMons[i].ability = gBattleMons[gActiveBank].ability; + gLastUsedAbility = gBattleMons[gActiveBank].ability; + effect++; + } + } + else + //_08019ABC + { + gActiveBank = target1; + if (gBattleMons[target1].ability && gBattleMons[target1].hp) + { + gBattleMons[i].ability = gBattleMons[target1].ability; + gLastUsedAbility = gBattleMons[target1].ability; + effect++; + } + } + if (effect) + { + b_push_move_exec(BattleScript_TraceActivates); + gStatuses3[i] &= ~(STATUS3_TRACE); + BATTLE_STRUCT->scriptingActive = i; + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 4; + gBattleTextBuff1[2] = gActiveBank; + gBattleTextBuff1[3] = gBattlePartyID[gActiveBank]; + gBattleTextBuff1[4] = EOS; + + gBattleTextBuff2[0] = 0xFD; + gBattleTextBuff2[1] = 9; + gBattleTextBuff2[2] = gLastUsedAbility; + gBattleTextBuff2[3] = EOS; + break; + } + } + } + break; + case ABILITYEFFECT_INTIMIDATE2: // 10 + //_08019B1C + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].ability == ABILITY_INTIMIDATE && (gStatuses3[i] & STATUS3_INTIMIDATE_POKES)) + { + gLastUsedAbility = ABILITY_INTIMIDATE; + gStatuses3[i] &= ~(STATUS3_INTIMIDATE_POKES); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = gUnknown_081D9795; + BATTLE_STRUCT->intimidateBank = i; + effect++; + break; + } + } + break; + case ABILITYEFFECT_CHECK_OTHER_SIDE: // 12 + //_08019B60 + side = GetBankSide(bank); + for (i = 0; i < gNoOfAllBanks; i++) + { + if (GetBankSide(i) != side && gBattleMons[i].ability == ability) + { + gLastUsedAbility = ability; + effect = i + 1; + } + } + break; + case ABILITYEFFECT_CHECK_BANK_SIDE: // 13 + //_08019BBC + side = GetBankSide(bank); + for (i = 0; i < gNoOfAllBanks; i++) + { + if (GetBankSide(i) == side && gBattleMons[i].ability == ability) + { + gLastUsedAbility = ability; + effect = i + 1; + } + } + break; + case ABILITYEFFECT_FIELD_SPORT: // 14 + //_08019C18 + switch (gLastUsedAbility) + { + case 0xFD: + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gStatuses3[i] & STATUS3_MUDSPORT) + effect = i + 1; + } + break; + case 0xFE: + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gStatuses3[i] & STATUS3_WATERSPORT) + effect = i + 1; + } + break; + default: + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].ability == ability) + { + gLastUsedAbility = ability; + effect = i + 1; + } + } + break; + } + break; + case ABILITYEFFECT_CHECK_ON_FIELD: // 19 + //_08019CD4 + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].ability == ability && gBattleMons[i].hp != 0) + { + gLastUsedAbility = ability; + effect = i + 1; + } + } + break; + case ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK: // 15 + //_08019D18 + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].ability == ability && i != bank) + { + gLastUsedAbility = ability; + effect = i + 1; + } + } + break; + case ABILITYEFFECT_COUNT_OTHER_SIZE: // 16 + //_08019D5C + side = GetBankSide(bank); + for (i = 0; i < gNoOfAllBanks; i++) + { + if (GetBankSide(i) != side && gBattleMons[i].ability == ability) + { + gLastUsedAbility = ability; + effect++; + } + } + break; + case ABILITYEFFECT_COUNT_BANK_SIDE: // 17 + //_08019DB8 + side = GetBankSide(bank); + for (i = 0; i < gNoOfAllBanks; i++) + { + if (GetBankSide(i) == side && gBattleMons[i].ability == ability) + { + gLastUsedAbility = ability; + effect++; + } + } + break; + case ABILITYEFFECT_COUNT_ON_FIELD: // 18 + //_08019F44 + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].ability == ability && i != bank) + { + gLastUsedAbility = ability; + effect++; + } + } + break; + } + //_08019F76 + if (effect && caseID < 0xC && gLastUsedAbility != 0xFF) + RecordAbilityBattle(bank, gLastUsedAbility); + } + + return effect; +} + +#else +__attribute__((naked)) +u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x28\n\ + ldr r4, [sp, 0x48]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x4]\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + mov r10, r1\n\ + lsls r2, 24\n\ + lsrs r6, r2, 24\n\ + lsls r3, 24\n\ + lsrs r3, 24\n\ + mov r8, r3\n\ + lsls r4, 16\n\ + lsrs r4, 16\n\ + movs r0, 0\n\ + mov r9, r0\n\ + ldr r5, _08018380 @ =gBankAttacker\n\ + ldr r1, _08018384 @ =gNoOfAllBanks\n\ + ldrb r0, [r5]\n\ + ldrb r1, [r1]\n\ + cmp r0, r1\n\ + bcc _08018360\n\ + mov r1, r10\n\ + strb r1, [r5]\n\ +_08018360:\n\ + ldrb r0, [r5]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _08018390\n\ + ldr r1, _08018388 @ =gBattlePartyID\n\ + ldrb r0, [r5]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldrh r1, [r0]\n\ + movs r0, 0x64\n\ + muls r1, r0\n\ + ldr r0, _0801838C @ =gPlayerParty\n\ + b _080183A0\n\ + .align 2, 0\n\ +_08018380: .4byte gBankAttacker\n\ +_08018384: .4byte gNoOfAllBanks\n\ +_08018388: .4byte gBattlePartyID\n\ +_0801838C: .4byte gPlayerParty\n\ +_08018390:\n\ + ldr r1, _080183D0 @ =gBattlePartyID\n\ + ldrb r0, [r5]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldrh r1, [r0]\n\ + movs r0, 0x64\n\ + muls r1, r0\n\ + ldr r0, _080183D4 @ =gEnemyParty\n\ +_080183A0:\n\ + adds r7, r1, r0\n\ + ldr r5, _080183D8 @ =gBankTarget\n\ + ldr r1, _080183DC @ =gNoOfAllBanks\n\ + ldrb r0, [r5]\n\ + ldrb r1, [r1]\n\ + cmp r0, r1\n\ + bcc _080183B2\n\ + mov r2, r10\n\ + strb r2, [r5]\n\ +_080183B2:\n\ + ldrb r0, [r5]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _080183E4\n\ + ldr r1, _080183D0 @ =gBattlePartyID\n\ + ldrb r0, [r5]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldrh r1, [r0]\n\ + movs r0, 0x64\n\ + muls r1, r0\n\ + ldr r0, _080183E0 @ =gPlayerParty\n\ + b _080183F4\n\ + .align 2, 0\n\ +_080183D0: .4byte gBattlePartyID\n\ +_080183D4: .4byte gEnemyParty\n\ +_080183D8: .4byte gBankTarget\n\ +_080183DC: .4byte gNoOfAllBanks\n\ +_080183E0: .4byte gPlayerParty\n\ +_080183E4:\n\ + ldr r1, _08018444 @ =gBattlePartyID\n\ + ldrb r0, [r5]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldrh r1, [r0]\n\ + movs r0, 0x64\n\ + muls r1, r0\n\ + ldr r0, _08018448 @ =gEnemyParty\n\ +_080183F4:\n\ + adds r5, r1, r0\n\ + adds r0, r7, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + movs r1, 0\n\ + bl GetMonData\n\ + str r0, [sp, 0x10]\n\ + adds r0, r5, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [sp, 0xC]\n\ + adds r0, r5, 0\n\ + movs r1, 0\n\ + bl GetMonData\n\ + str r0, [sp, 0x14]\n\ + ldr r0, _0801844C @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x80\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018436\n\ + bl _08019F92\n\ +_08018436:\n\ + mov r3, r8\n\ + cmp r3, 0\n\ + beq _08018454\n\ + ldr r0, _08018450 @ =gLastUsedAbility\n\ + strb r3, [r0]\n\ + mov r8, r0\n\ + b _0801846A\n\ + .align 2, 0\n\ +_08018444: .4byte gBattlePartyID\n\ +_08018448: .4byte gEnemyParty\n\ +_0801844C: .4byte gBattleTypeFlags\n\ +_08018450: .4byte gLastUsedAbility\n\ +_08018454:\n\ + ldr r2, _08018474 @ =gLastUsedAbility\n\ + ldr r1, _08018478 @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r5, r10\n\ + muls r5, r0\n\ + adds r0, r5, 0\n\ + adds r0, r1\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + strb r0, [r2]\n\ + mov r8, r2\n\ +_0801846A:\n\ + cmp r4, 0\n\ + beq _0801847C\n\ + adds r3, r4, 0\n\ + b _08018480\n\ + .align 2, 0\n\ +_08018474: .4byte gLastUsedAbility\n\ +_08018478: .4byte gBattleMons\n\ +_0801847C:\n\ + ldr r0, _08018494 @ =gCurrentMove\n\ + ldrh r3, [r0]\n\ +_08018480:\n\ + ldr r1, _08018498 @ =0x02000000\n\ + ldr r2, _0801849C @ =0x0001601c\n\ + adds r0, r1, r2\n\ + ldrb r0, [r0]\n\ + adds r7, r1, 0\n\ + cmp r0, 0\n\ + beq _080184A0\n\ + movs r4, 0x3F\n\ + ands r4, r0\n\ + b _080184AC\n\ + .align 2, 0\n\ +_08018494: .4byte gCurrentMove\n\ +_08018498: .4byte 0x02000000\n\ +_0801849C: .4byte 0x0001601c\n\ +_080184A0:\n\ + ldr r1, _080184C0 @ =gBattleMoves\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r4, [r0, 0x2]\n\ +_080184AC:\n\ + ldr r5, [sp, 0x4]\n\ + cmp r5, 0x13\n\ + bls _080184B6\n\ + bl _08019F76\n\ +_080184B6:\n\ + lsls r0, r5, 2\n\ + ldr r1, _080184C4 @ =_080184C8\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_080184C0: .4byte gBattleMoves\n\ +_080184C4: .4byte _080184C8\n\ + .align 2, 0\n\ +_080184C8:\n\ + .4byte _08018518\n\ + .4byte _08018814\n\ + .4byte _08018A40\n\ + .4byte _08018AD8\n\ + .4byte _08018CF0\n\ + .4byte _08019448\n\ + .4byte _080197B4\n\ + .4byte _08019804\n\ + .4byte _08019880\n\ + .4byte _080198FC\n\ + .4byte _08019B1C\n\ + .4byte _08019940\n\ + .4byte _08019B60\n\ + .4byte _08019BBC\n\ + .4byte _08019C18\n\ + .4byte _08019D18\n\ + .4byte _08019D5C\n\ + .4byte _08019DB8\n\ + .4byte _08019F44\n\ + .4byte _08019CD4\n\ +_08018518:\n\ + ldr r2, _0801854C @ =gBankAttacker\n\ + ldr r0, _08018550 @ =gNoOfAllBanks\n\ + ldrb r1, [r2]\n\ + adds r5, r0, 0\n\ + ldrb r0, [r5]\n\ + cmp r1, r0\n\ + bcc _0801852A\n\ + mov r1, r10\n\ + strb r1, [r2]\n\ +_0801852A:\n\ + mov r2, r8\n\ + ldrb r0, [r2]\n\ + cmp r0, 0x2D\n\ + bne _08018534\n\ + b _080186B8\n\ +_08018534:\n\ + cmp r0, 0x2D\n\ + bgt _08018564\n\ + cmp r0, 0xD\n\ + bne _0801853E\n\ + b _080187DC\n\ +_0801853E:\n\ + cmp r0, 0xD\n\ + bgt _08018554\n\ + cmp r0, 0x2\n\ + bne _08018548\n\ + b _08018680\n\ +_08018548:\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_0801854C: .4byte gBankAttacker\n\ +_08018550: .4byte gNoOfAllBanks\n\ +_08018554:\n\ + cmp r0, 0x16\n\ + bne _0801855A\n\ + b _08018728\n\ +_0801855A:\n\ + cmp r0, 0x24\n\ + bne _08018560\n\ + b _080187A0\n\ +_08018560:\n\ + bl _08019F76\n\ +_08018564:\n\ + cmp r0, 0x46\n\ + bne _0801856A\n\ + b _080186F0\n\ +_0801856A:\n\ + cmp r0, 0x46\n\ + bgt _08018578\n\ + cmp r0, 0x3B\n\ + bne _08018574\n\ + b _0801875C\n\ +_08018574:\n\ + bl _08019F76\n\ +_08018578:\n\ + cmp r0, 0x4D\n\ + bne _0801857E\n\ + b _080187DC\n\ +_0801857E:\n\ + cmp r0, 0xFF\n\ + beq _08018586\n\ + bl _08019F76\n\ +_08018586:\n\ + bl weather_get_current\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + subs r0, 0x3\n\ + cmp r0, 0xA\n\ + bhi _0801864C\n\ + lsls r0, 2\n\ + ldr r1, _080185A0 @ =_080185A4\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_080185A0: .4byte _080185A4\n\ + .align 2, 0\n\ +_080185A4:\n\ + .4byte _080185D0\n\ + .4byte _0801864C\n\ + .4byte _080185D0\n\ + .4byte _0801864C\n\ + .4byte _0801864C\n\ + .4byte _080185F8\n\ + .4byte _0801864C\n\ + .4byte _0801864C\n\ + .4byte _0801864C\n\ + .4byte _08018620\n\ + .4byte _080185D0\n\ +_080185D0:\n\ + ldr r2, _080185EC @ =gBattleWeather\n\ + ldrh r1, [r2]\n\ + movs r0, 0x7\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801864C\n\ + movs r0, 0x5\n\ + strh r0, [r2]\n\ + ldr r0, _080185F0 @ =0x02000000\n\ + ldr r3, _080185F4 @ =0x000160a4\n\ + adds r2, r0, r3\n\ + movs r1, 0xA\n\ + b _08018638\n\ + .align 2, 0\n\ +_080185EC: .4byte gBattleWeather\n\ +_080185F0: .4byte 0x02000000\n\ +_080185F4: .4byte 0x000160a4\n\ +_080185F8:\n\ + ldr r3, _08018614 @ =gBattleWeather\n\ + ldrh r1, [r3]\n\ + movs r2, 0x18\n\ + adds r0, r2, 0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801864C\n\ + strh r2, [r3]\n\ + ldr r0, _08018618 @ =0x02000000\n\ + ldr r3, _0801861C @ =0x000160a4\n\ + adds r2, r0, r3\n\ + movs r1, 0xC\n\ + b _08018638\n\ + .align 2, 0\n\ +_08018614: .4byte gBattleWeather\n\ +_08018618: .4byte 0x02000000\n\ +_0801861C: .4byte 0x000160a4\n\ +_08018620:\n\ + ldr r3, _08018668 @ =gBattleWeather\n\ + ldrh r1, [r3]\n\ + movs r2, 0x60\n\ + adds r0, r2, 0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801864C\n\ + strh r2, [r3]\n\ + ldr r0, _0801866C @ =0x02000000\n\ + ldr r3, _08018670 @ =0x000160a4\n\ + adds r2, r0, r3\n\ + movs r1, 0xB\n\ +_08018638:\n\ + strb r1, [r2]\n\ + ldr r5, _08018674 @ =0x00016003\n\ + adds r0, r5\n\ + mov r1, r10\n\ + strb r1, [r0]\n\ + mov r0, r9\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_0801864C:\n\ + mov r2, r9\n\ + cmp r2, 0\n\ + bne _08018656\n\ + bl _08019F92\n\ +_08018656:\n\ + bl weather_get_current\n\ + ldr r1, _08018678 @ =gBattleCommunication\n\ + strb r0, [r1, 0x5]\n\ + ldr r0, _0801867C @ =gUnknown_081D901D\n\ + bl b_push_move_exec\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_08018668: .4byte gBattleWeather\n\ +_0801866C: .4byte 0x02000000\n\ +_08018670: .4byte 0x000160a4\n\ +_08018674: .4byte 0x00016003\n\ +_08018678: .4byte gBattleCommunication\n\ +_0801867C: .4byte gUnknown_081D901D\n\ +_08018680:\n\ + ldr r2, _080186A8 @ =gBattleWeather\n\ + ldrh r1, [r2]\n\ + movs r0, 0x4\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018690\n\ + bl _08019F76\n\ +_08018690:\n\ + movs r0, 0x5\n\ + strh r0, [r2]\n\ + ldr r0, _080186AC @ =BattleScript_DrizzleActivates\n\ + bl b_push_move_exec\n\ + ldr r0, _080186B0 @ =0x02000000\n\ + ldr r3, _080186B4 @ =0x00016003\n\ + adds r0, r3\n\ + mov r5, r10\n\ + strb r5, [r0]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_080186A8: .4byte gBattleWeather\n\ +_080186AC: .4byte BattleScript_DrizzleActivates\n\ +_080186B0: .4byte 0x02000000\n\ +_080186B4: .4byte 0x00016003\n\ +_080186B8:\n\ + ldr r2, _080186E0 @ =gBattleWeather\n\ + ldrh r1, [r2]\n\ + movs r0, 0x10\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080186C8\n\ + bl _08019F76\n\ +_080186C8:\n\ + movs r0, 0x18\n\ + strh r0, [r2]\n\ + ldr r0, _080186E4 @ =BattleScript_SandstreamActivates\n\ + bl b_push_move_exec\n\ + ldr r0, _080186E8 @ =0x02000000\n\ + ldr r1, _080186EC @ =0x00016003\n\ + adds r0, r1\n\ + mov r2, r10\n\ + strb r2, [r0]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_080186E0: .4byte gBattleWeather\n\ +_080186E4: .4byte BattleScript_SandstreamActivates\n\ +_080186E8: .4byte 0x02000000\n\ +_080186EC: .4byte 0x00016003\n\ +_080186F0:\n\ + ldr r2, _08018718 @ =gBattleWeather\n\ + ldrh r1, [r2]\n\ + movs r0, 0x40\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018700\n\ + bl _08019F76\n\ +_08018700:\n\ + movs r0, 0x60\n\ + strh r0, [r2]\n\ + ldr r0, _0801871C @ =BattleScript_DroughtActivates\n\ + bl b_push_move_exec\n\ + ldr r0, _08018720 @ =0x02000000\n\ + ldr r3, _08018724 @ =0x00016003\n\ + adds r0, r3\n\ + mov r5, r10\n\ + strb r5, [r0]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_08018718: .4byte gBattleWeather\n\ +_0801871C: .4byte BattleScript_DroughtActivates\n\ +_08018720: .4byte 0x02000000\n\ +_08018724: .4byte 0x00016003\n\ +_08018728:\n\ + ldr r0, _08018754 @ =gSpecialStatuses\n\ + mov r1, r10\n\ + lsls r2, r1, 2\n\ + adds r1, r2, r1\n\ + lsls r1, 2\n\ + adds r3, r1, r0\n\ + ldrb r0, [r3]\n\ + lsls r0, 28\n\ + cmp r0, 0\n\ + bge _08018740\n\ + bl _08019F76\n\ +_08018740:\n\ + ldr r1, _08018758 @ =gStatuses3\n\ + adds r1, r2, r1\n\ + ldr r0, [r1]\n\ + movs r2, 0x80\n\ + lsls r2, 12\n\ + orrs r0, r2\n\ + str r0, [r1]\n\ + ldrb r0, [r3]\n\ + movs r1, 0x8\n\ + b _080187CA\n\ + .align 2, 0\n\ +_08018754: .4byte gSpecialStatuses\n\ +_08018758: .4byte gStatuses3\n\ +_0801875C:\n\ + mov r0, r10\n\ + bl CastformDataTypeChange\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ + cmp r0, 0\n\ + bne _08018770\n\ + bl _08019F92\n\ +_08018770:\n\ + ldr r0, _08018790 @ =BattleScript_CastformChange\n\ + bl b_push_move_exec\n\ + ldr r0, _08018794 @ =0x02000000\n\ + ldr r2, _08018798 @ =0x00016003\n\ + adds r1, r0, r2\n\ + mov r3, r10\n\ + strb r3, [r1]\n\ + mov r1, r9\n\ + subs r1, 0x1\n\ + ldr r5, _0801879C @ =0x0001609b\n\ + adds r0, r5\n\ + strb r1, [r0]\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_08018790: .4byte BattleScript_CastformChange\n\ +_08018794: .4byte 0x02000000\n\ +_08018798: .4byte 0x00016003\n\ +_0801879C: .4byte 0x0001609b\n\ +_080187A0:\n\ + ldr r0, _080187D4 @ =gSpecialStatuses\n\ + mov r1, r10\n\ + lsls r2, r1, 2\n\ + adds r1, r2, r1\n\ + lsls r1, 2\n\ + adds r3, r1, r0\n\ + ldrb r0, [r3]\n\ + lsls r0, 27\n\ + cmp r0, 0\n\ + bge _080187B8\n\ + bl _08019F76\n\ +_080187B8:\n\ + ldr r1, _080187D8 @ =gStatuses3\n\ + adds r1, r2, r1\n\ + ldr r0, [r1]\n\ + movs r2, 0x80\n\ + lsls r2, 13\n\ + orrs r0, r2\n\ + str r0, [r1]\n\ + ldrb r0, [r3]\n\ + movs r1, 0x10\n\ +_080187CA:\n\ + orrs r0, r1\n\ + strb r0, [r3]\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_080187D4: .4byte gSpecialStatuses\n\ +_080187D8: .4byte gStatuses3\n\ +_080187DC:\n\ + movs r6, 0\n\ + ldrb r5, [r5]\n\ + cmp r6, r5\n\ + bcc _080187E8\n\ + bl _08019F76\n\ +_080187E8:\n\ + adds r0, r6, 0\n\ + bl CastformDataTypeChange\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ + cmp r0, 0\n\ + beq _080187FC\n\ + bl _08019E14\n\ +_080187FC:\n\ + adds r0, r6, 0x1\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + ldr r0, _08018810 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r6, r0\n\ + bcc _080187E8\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_08018810: .4byte gNoOfAllBanks\n\ +_08018814:\n\ + ldr r2, _08018844 @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r1, r10\n\ + muls r1, r0\n\ + adds r4, r1, r2\n\ + ldrh r0, [r4, 0x28]\n\ + cmp r0, 0\n\ + bne _08018828\n\ + bl _08019F76\n\ +_08018828:\n\ + ldr r0, _08018848 @ =gBankAttacker\n\ + mov r3, r10\n\ + strb r3, [r0]\n\ + mov r3, r8\n\ + ldrb r5, [r3]\n\ + cmp r5, 0x2C\n\ + beq _0801885A\n\ + cmp r5, 0x2C\n\ + bgt _0801884C\n\ + cmp r5, 0x3\n\ + bne _08018840\n\ + b _080189B8\n\ +_08018840:\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_08018844: .4byte gBattleMons\n\ +_08018848: .4byte gBankAttacker\n\ +_0801884C:\n\ + cmp r5, 0x36\n\ + bne _08018852\n\ + b _08018A18\n\ +_08018852:\n\ + cmp r5, 0x3D\n\ + beq _080188DC\n\ + bl _08019F76\n\ +_0801885A:\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + movs r0, 0x13\n\ + movs r1, 0\n\ + movs r2, 0xD\n\ + movs r3, 0\n\ + bl AbilityBattleEffects\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0\n\ + beq _08018876\n\ + bl _08019F76\n\ +_08018876:\n\ + str r0, [sp]\n\ + movs r0, 0x13\n\ + movs r1, 0\n\ + movs r2, 0x4D\n\ + movs r3, 0\n\ + bl AbilityBattleEffects\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _0801888E\n\ + bl _08019F76\n\ +_0801888E:\n\ + ldr r0, _080188D0 @ =gBattleWeather\n\ + ldrh r1, [r0]\n\ + movs r0, 0x7\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801889E\n\ + bl _08019F76\n\ +_0801889E:\n\ + ldrh r0, [r4, 0x2C]\n\ + ldrh r1, [r4, 0x28]\n\ + cmp r0, r1\n\ + bhi _080188AA\n\ + bl _08019F76\n\ +_080188AA:\n\ + mov r2, r8\n\ + strb r5, [r2]\n\ + ldr r0, _080188D4 @ =BattleScript_RainDishActivates\n\ + bl b_push_move_exec\n\ + ldr r1, _080188D8 @ =gBattleMoveDamage\n\ + ldrh r0, [r4, 0x2C]\n\ + lsrs r0, 4\n\ + str r0, [r1]\n\ + cmp r0, 0\n\ + bne _080188C4\n\ + movs r0, 0x1\n\ + str r0, [r1]\n\ +_080188C4:\n\ + ldr r0, [r1]\n\ + negs r0, r0\n\ + str r0, [r1]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_080188D0: .4byte gBattleWeather\n\ +_080188D4: .4byte BattleScript_RainDishActivates\n\ +_080188D8: .4byte gBattleMoveDamage\n\ +_080188DC:\n\ + adds r0, r2, 0\n\ + adds r0, 0x4C\n\ + adds r5, r1, r0\n\ + ldrb r0, [r5]\n\ + cmp r0, 0\n\ + bne _080188EC\n\ + bl _08019F76\n\ +_080188EC:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x3\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + cmp r4, 0\n\ + beq _08018906\n\ + bl _08019F76\n\ +_08018906:\n\ + ldr r0, [r5]\n\ + movs r1, 0x88\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018918\n\ + ldr r0, _08018990 @ =gBattleTextBuff1\n\ + ldr r1, _08018994 @ =gStatusConditionString_PoisonJpn\n\ + bl StringCopy\n\ +_08018918:\n\ + ldr r0, [r5]\n\ + movs r1, 0x7\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801892A\n\ + ldr r0, _08018990 @ =gBattleTextBuff1\n\ + ldr r1, _08018998 @ =gStatusConditionString_SleepJpn\n\ + bl StringCopy\n\ +_0801892A:\n\ + ldr r0, [r5]\n\ + movs r1, 0x40\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801893C\n\ + ldr r0, _08018990 @ =gBattleTextBuff1\n\ + ldr r1, _0801899C @ =gStatusConditionString_ParalysisJpn\n\ + bl StringCopy\n\ +_0801893C:\n\ + ldr r0, [r5]\n\ + movs r1, 0x10\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801894E\n\ + ldr r0, _08018990 @ =gBattleTextBuff1\n\ + ldr r1, _080189A0 @ =gStatusConditionString_BurnJpn\n\ + bl StringCopy\n\ +_0801894E:\n\ + ldr r0, [r5]\n\ + movs r1, 0x20\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018960\n\ + ldr r0, _08018990 @ =gBattleTextBuff1\n\ + ldr r1, _080189A4 @ =gStatusConditionString_IceJpn\n\ + bl StringCopy\n\ +_08018960:\n\ + str r4, [r5]\n\ + ldr r0, _080189A8 @ =0x02000000\n\ + ldr r4, _080189AC @ =gActiveBank\n\ + mov r3, r10\n\ + strb r3, [r4]\n\ + ldr r1, _080189B0 @ =0x00016003\n\ + adds r0, r1\n\ + strb r3, [r0]\n\ + ldr r0, _080189B4 @ =BattleScript_ShedSkinActivates\n\ + bl b_push_move_exec\n\ + str r5, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x28\n\ + movs r2, 0\n\ + movs r3, 0x4\n\ + bl EmitSetAttributes\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_08018990: .4byte gBattleTextBuff1\n\ +_08018994: .4byte gStatusConditionString_PoisonJpn\n\ +_08018998: .4byte gStatusConditionString_SleepJpn\n\ +_0801899C: .4byte gStatusConditionString_ParalysisJpn\n\ +_080189A0: .4byte gStatusConditionString_BurnJpn\n\ +_080189A4: .4byte gStatusConditionString_IceJpn\n\ +_080189A8: .4byte 0x02000000\n\ +_080189AC: .4byte gActiveBank\n\ +_080189B0: .4byte 0x00016003\n\ +_080189B4: .4byte BattleScript_ShedSkinActivates\n\ +_080189B8:\n\ + ldrb r2, [r4, 0x1B]\n\ + movs r0, 0x1B\n\ + ldrsb r0, [r4, r0]\n\ + cmp r0, 0xB\n\ + ble _080189C6\n\ + bl _08019F76\n\ +_080189C6:\n\ + ldr r0, _08018A04 @ =gDisableStructs\n\ + mov r3, r10\n\ + lsls r1, r3, 3\n\ + subs r1, r3\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x16]\n\ + cmp r0, 0x2\n\ + bne _080189DC\n\ + bl _08019F76\n\ +_080189DC:\n\ + adds r0, r2, 0x1\n\ + movs r2, 0\n\ + strb r0, [r4, 0x1B]\n\ + ldr r5, _08018A08 @ =0x000160a4\n\ + adds r1, r7, r5\n\ + movs r0, 0x11\n\ + strb r0, [r1]\n\ + ldr r1, _08018A0C @ =0x000160a5\n\ + adds r0, r7, r1\n\ + strb r2, [r0]\n\ + ldr r0, _08018A10 @ =BattleScript_SpeedBoostActivates\n\ + bl b_push_move_exec\n\ + ldr r2, _08018A14 @ =0x00016003\n\ + adds r0, r7, r2\n\ + mov r3, r10\n\ + strb r3, [r0]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_08018A04: .4byte gDisableStructs\n\ +_08018A08: .4byte 0x000160a4\n\ +_08018A0C: .4byte 0x000160a5\n\ +_08018A10: .4byte BattleScript_SpeedBoostActivates\n\ +_08018A14: .4byte 0x00016003\n\ +_08018A18:\n\ + ldr r2, _08018A3C @ =gDisableStructs\n\ + ldrb r0, [r0]\n\ + lsls r1, r0, 3\n\ + subs r1, r0\n\ + lsls r1, 2\n\ + adds r1, r2\n\ + ldrb r3, [r1, 0x18]\n\ + lsls r0, r3, 31\n\ + lsrs r0, 31\n\ + movs r2, 0x1\n\ + eors r2, r0\n\ + movs r0, 0x2\n\ + negs r0, r0\n\ + ands r0, r3\n\ + orrs r0, r2\n\ + strb r0, [r1, 0x18]\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_08018A3C: .4byte gDisableStructs\n\ +_08018A40:\n\ + mov r5, r8\n\ + ldrb r0, [r5]\n\ + cmp r0, 0x2B\n\ + beq _08018A4C\n\ + bl _08019F76\n\ +_08018A4C:\n\ + movs r4, 0\n\ + ldr r0, _08018ABC @ =gSoundMovesTable\n\ + ldrh r2, [r0]\n\ + ldr r5, _08018AC0 @ =0x0000ffff\n\ + adds r1, r0, 0\n\ + cmp r2, r5\n\ + bne _08018A5E\n\ + bl _08019F76\n\ +_08018A5E:\n\ + cmp r2, r3\n\ + beq _08018A76\n\ + adds r2, r1, 0\n\ +_08018A64:\n\ + adds r2, 0x2\n\ + adds r4, 0x1\n\ + ldrh r0, [r2]\n\ + cmp r0, r5\n\ + bne _08018A72\n\ + bl _08019F76\n\ +_08018A72:\n\ + cmp r0, r3\n\ + bne _08018A64\n\ +_08018A76:\n\ + lsls r0, r4, 1\n\ + adds r0, r1\n\ + ldrh r1, [r0]\n\ + ldr r0, _08018AC0 @ =0x0000ffff\n\ + cmp r1, r0\n\ + bne _08018A86\n\ + bl _08019F76\n\ +_08018A86:\n\ + ldr r1, _08018AC4 @ =gBattleMons\n\ + ldr r0, _08018AC8 @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r1, 0x50\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 5\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018AAC\n\ + ldr r0, _08018ACC @ =gHitMarker\n\ + ldr r1, [r0]\n\ + movs r2, 0x80\n\ + lsls r2, 4\n\ + orrs r1, r2\n\ + str r1, [r0]\n\ +_08018AAC:\n\ + ldr r1, _08018AD0 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018AD4 @ =BattleScript_SoundproofProtected\n\ + str r0, [r1]\n\ + movs r0, 0x1\n\ + mov r9, r0\n\ + bl _08019F7C\n\ + .align 2, 0\n\ +_08018ABC: .4byte gSoundMovesTable\n\ +_08018AC0: .4byte 0x0000ffff\n\ +_08018AC4: .4byte gBattleMons\n\ +_08018AC8: .4byte gBankAttacker\n\ +_08018ACC: .4byte gHitMarker\n\ +_08018AD0: .4byte gBattlescriptCurrInstr\n\ +_08018AD4: .4byte BattleScript_SoundproofProtected\n\ +_08018AD8:\n\ + cmp r3, 0\n\ + bne _08018AE0\n\ + bl _08019F76\n\ +_08018AE0:\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + cmp r0, 0xB\n\ + beq _08018B50\n\ + cmp r0, 0xB\n\ + bgt _08018AF2\n\ + cmp r0, 0xA\n\ + beq _08018AF8\n\ + b _08018C6A\n\ +_08018AF2:\n\ + cmp r0, 0x12\n\ + beq _08018BA8\n\ + b _08018C6A\n\ +_08018AF8:\n\ + cmp r4, 0xD\n\ + beq _08018AFE\n\ + b _08018C6A\n\ +_08018AFE:\n\ + ldr r0, _08018B28 @ =gBattleMoves\n\ + lsls r1, r3, 1\n\ + adds r1, r3\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + cmp r0, 0\n\ + bne _08018B10\n\ + b _08018C6A\n\ +_08018B10:\n\ + ldr r1, _08018B2C @ =gProtectStructs\n\ + ldr r0, _08018B30 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + lsls r0, 4\n\ + adds r0, r1\n\ + ldrb r0, [r0, 0x2]\n\ + lsls r0, 28\n\ + cmp r0, 0\n\ + bge _08018B3C\n\ + ldr r1, _08018B34 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018B38 @ =BattleScript_MoveHPDrain\n\ + b _08018B40\n\ + .align 2, 0\n\ +_08018B28: .4byte gBattleMoves\n\ +_08018B2C: .4byte gProtectStructs\n\ +_08018B30: .4byte gBankAttacker\n\ +_08018B34: .4byte gBattlescriptCurrInstr\n\ +_08018B38: .4byte BattleScript_MoveHPDrain\n\ +_08018B3C:\n\ + ldr r1, _08018B48 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018B4C @ =BattleScript_MoveHPDrain_PPLoss\n\ +_08018B40:\n\ + str r0, [r1]\n\ + movs r2, 0x1\n\ + b _08018C68\n\ + .align 2, 0\n\ +_08018B48: .4byte gBattlescriptCurrInstr\n\ +_08018B4C: .4byte BattleScript_MoveHPDrain_PPLoss\n\ +_08018B50:\n\ + cmp r4, 0xB\n\ + beq _08018B56\n\ + b _08018C6A\n\ +_08018B56:\n\ + ldr r0, _08018B80 @ =gBattleMoves\n\ + lsls r1, r3, 1\n\ + adds r1, r3\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + cmp r0, 0\n\ + bne _08018B68\n\ + b _08018C6A\n\ +_08018B68:\n\ + ldr r1, _08018B84 @ =gProtectStructs\n\ + ldr r0, _08018B88 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + lsls r0, 4\n\ + adds r0, r1\n\ + ldrb r0, [r0, 0x2]\n\ + lsls r0, 28\n\ + cmp r0, 0\n\ + bge _08018B94\n\ + ldr r1, _08018B8C @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018B90 @ =BattleScript_MoveHPDrain\n\ + b _08018B98\n\ + .align 2, 0\n\ +_08018B80: .4byte gBattleMoves\n\ +_08018B84: .4byte gProtectStructs\n\ +_08018B88: .4byte gBankAttacker\n\ +_08018B8C: .4byte gBattlescriptCurrInstr\n\ +_08018B90: .4byte BattleScript_MoveHPDrain\n\ +_08018B94:\n\ + ldr r1, _08018BA0 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018BA4 @ =BattleScript_MoveHPDrain_PPLoss\n\ +_08018B98:\n\ + str r0, [r1]\n\ + movs r3, 0x1\n\ + mov r9, r3\n\ + b _08018C6A\n\ + .align 2, 0\n\ +_08018BA0: .4byte gBattlescriptCurrInstr\n\ +_08018BA4: .4byte BattleScript_MoveHPDrain_PPLoss\n\ +_08018BA8:\n\ + cmp r4, 0xA\n\ + bne _08018C6A\n\ + ldr r1, _08018BF4 @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r5, r10\n\ + muls r5, r0\n\ + adds r0, r5, 0\n\ + adds r1, 0x4C\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x20\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08018C6A\n\ + ldr r2, _08018BF8 @ =0x02017100\n\ + mov r0, r10\n\ + lsls r1, r0, 2\n\ + adds r0, r1, r2\n\ + ldr r3, [r0]\n\ + movs r4, 0x1\n\ + ands r3, r4\n\ + adds r5, r1, 0\n\ + cmp r3, 0\n\ + bne _08018C30\n\ + ldr r0, _08018BFC @ =gBattleCommunication\n\ + strb r3, [r0, 0x5]\n\ + ldr r1, _08018C00 @ =gProtectStructs\n\ + ldr r0, _08018C04 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + lsls r0, 4\n\ + adds r0, r1\n\ + ldrb r0, [r0, 0x2]\n\ + lsls r0, 28\n\ + cmp r0, 0\n\ + bge _08018C10\n\ + ldr r1, _08018C08 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018C0C @ =BattleScript_FlashFireBoost\n\ + b _08018C14\n\ + .align 2, 0\n\ +_08018BF4: .4byte gBattleMons\n\ +_08018BF8: .4byte 0x02017100\n\ +_08018BFC: .4byte gBattleCommunication\n\ +_08018C00: .4byte gProtectStructs\n\ +_08018C04: .4byte gBankAttacker\n\ +_08018C08: .4byte gBattlescriptCurrInstr\n\ +_08018C0C: .4byte BattleScript_FlashFireBoost\n\ +_08018C10:\n\ + ldr r1, _08018C28 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018C2C @ =BattleScript_FlashFireBoost_PPLoss\n\ +_08018C14:\n\ + str r0, [r1]\n\ + adds r0, r5, r2\n\ + ldr r1, [r0]\n\ + movs r2, 0x1\n\ + orrs r1, r2\n\ + str r1, [r0]\n\ + movs r1, 0x2\n\ + mov r9, r1\n\ + b _08018C6A\n\ + .align 2, 0\n\ +_08018C28: .4byte gBattlescriptCurrInstr\n\ +_08018C2C: .4byte BattleScript_FlashFireBoost_PPLoss\n\ +_08018C30:\n\ + ldr r0, _08018C4C @ =gBattleCommunication\n\ + strb r4, [r0, 0x5]\n\ + ldr r1, _08018C50 @ =gProtectStructs\n\ + ldr r0, _08018C54 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + lsls r0, 4\n\ + adds r0, r1\n\ + ldrb r0, [r0, 0x2]\n\ + lsls r0, 28\n\ + cmp r0, 0\n\ + bge _08018C60\n\ + ldr r1, _08018C58 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018C5C @ =BattleScript_FlashFireBoost\n\ + b _08018C64\n\ + .align 2, 0\n\ +_08018C4C: .4byte gBattleCommunication\n\ +_08018C50: .4byte gProtectStructs\n\ +_08018C54: .4byte gBankAttacker\n\ +_08018C58: .4byte gBattlescriptCurrInstr\n\ +_08018C5C: .4byte BattleScript_FlashFireBoost\n\ +_08018C60:\n\ + ldr r1, _08018CA4 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018CA8 @ =BattleScript_FlashFireBoost_PPLoss\n\ +_08018C64:\n\ + str r0, [r1]\n\ + movs r2, 0x2\n\ +_08018C68:\n\ + mov r9, r2\n\ +_08018C6A:\n\ + mov r3, r9\n\ + cmp r3, 0x1\n\ + beq _08018C74\n\ + bl _08019F76\n\ +_08018C74:\n\ + ldr r1, _08018CAC @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r5, r10\n\ + muls r5, r0\n\ + adds r0, r5, 0\n\ + adds r1, r0, r1\n\ + ldrh r0, [r1, 0x2C]\n\ + ldrh r2, [r1, 0x28]\n\ + cmp r0, r2\n\ + bne _08018CD0\n\ + ldr r1, _08018CB0 @ =gProtectStructs\n\ + ldr r0, _08018CB4 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + lsls r0, 4\n\ + adds r0, r1\n\ + ldrb r0, [r0, 0x2]\n\ + lsls r0, 28\n\ + cmp r0, 0\n\ + bge _08018CBC\n\ + ldr r1, _08018CA4 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018CB8 @ =BattleScript_MoveHPDrain_FullHP\n\ + str r0, [r1]\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_08018CA4: .4byte gBattlescriptCurrInstr\n\ +_08018CA8: .4byte BattleScript_FlashFireBoost_PPLoss\n\ +_08018CAC: .4byte gBattleMons\n\ +_08018CB0: .4byte gProtectStructs\n\ +_08018CB4: .4byte gBankAttacker\n\ +_08018CB8: .4byte BattleScript_MoveHPDrain_FullHP\n\ +_08018CBC:\n\ + ldr r1, _08018CC8 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018CCC @ =BattleScript_MoveHPDrain_FullHP_PPLoss\n\ + str r0, [r1]\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_08018CC8: .4byte gBattlescriptCurrInstr\n\ +_08018CCC: .4byte BattleScript_MoveHPDrain_FullHP_PPLoss\n\ +_08018CD0:\n\ + ldr r2, _08018CEC @ =gBattleMoveDamage\n\ + ldrh r0, [r1, 0x2C]\n\ + lsrs r0, 2\n\ + str r0, [r2]\n\ + cmp r0, 0\n\ + bne _08018CE0\n\ + mov r3, r9\n\ + str r3, [r2]\n\ +_08018CE0:\n\ + ldr r0, [r2]\n\ + negs r0, r0\n\ + str r0, [r2]\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_08018CEC: .4byte gBattleMoveDamage\n\ +_08018CF0:\n\ + mov r5, r8\n\ + ldrb r0, [r5]\n\ + subs r0, 0x9\n\ + cmp r0, 0x2F\n\ + bls _08018CFE\n\ + bl _08019F76\n\ +_08018CFE:\n\ + lsls r0, 2\n\ + ldr r1, _08018D08 @ =_08018D0C\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_08018D08: .4byte _08018D0C\n\ + .align 2, 0\n\ +_08018D0C:\n\ + .4byte _08019128\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08018DCC\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08018E94\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08018F54\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _0801904C\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019204\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _08019F76\n\ + .4byte _080192E0\n\ +_08018DCC:\n\ + ldr r0, _08018E74 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018DDC\n\ + bl _08019F76\n\ +_08018DDC:\n\ + cmp r3, 0xA5\n\ + bne _08018DE4\n\ + bl _08019F76\n\ +_08018DE4:\n\ + ldr r0, _08018E78 @ =gBattleMoves\n\ + lsls r1, r3, 1\n\ + adds r1, r3\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + cmp r0, 0\n\ + bne _08018DF8\n\ + bl _08019F76\n\ +_08018DF8:\n\ + ldr r2, _08018E7C @ =gSpecialStatuses\n\ + ldr r0, _08018E80 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r1, r0, 2\n\ + adds r0, r2, 0\n\ + adds r0, 0x8\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08018E20\n\ + adds r0, r2, 0\n\ + adds r0, 0xC\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08018E20\n\ + bl _08019F76\n\ +_08018E20:\n\ + ldr r1, _08018E84 @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r2, r10\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + adds r1, r0, r1\n\ + adds r3, r1, 0\n\ + adds r3, 0x21\n\ + ldrb r0, [r3]\n\ + cmp r0, r4\n\ + bne _08018E3A\n\ + bl _08019F76\n\ +_08018E3A:\n\ + adds r2, r1, 0\n\ + adds r2, 0x22\n\ + ldrb r0, [r2]\n\ + cmp r0, r4\n\ + bne _08018E48\n\ + bl _08019F76\n\ +_08018E48:\n\ + ldrh r0, [r1, 0x28]\n\ + cmp r0, 0\n\ + bne _08018E52\n\ + bl _08019F76\n\ +_08018E52:\n\ + strb r4, [r3]\n\ + strb r4, [r2]\n\ + ldr r1, _08018E88 @ =gBattleTextBuff1\n\ + movs r0, 0xFD\n\ + strb r0, [r1]\n\ + movs r0, 0x3\n\ + strb r0, [r1, 0x1]\n\ + strb r4, [r1, 0x2]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x3]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08018E8C @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018E90 @ =BattleScript_ColorChangeActivates\n\ + str r0, [r1]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_08018E74: .4byte gBattleMoveFlags\n\ +_08018E78: .4byte gBattleMoves\n\ +_08018E7C: .4byte gSpecialStatuses\n\ +_08018E80: .4byte gBankTarget\n\ +_08018E84: .4byte gBattleMons\n\ +_08018E88: .4byte gBattleTextBuff1\n\ +_08018E8C: .4byte gBattlescriptCurrInstr\n\ +_08018E90: .4byte BattleScript_ColorChangeActivates\n\ +_08018E94:\n\ + ldr r0, _08018F2C @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018EA4\n\ + bl _08019F76\n\ +_08018EA4:\n\ + ldr r1, _08018F30 @ =gBattleMons\n\ + ldr r0, _08018F34 @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r4, r0, r1\n\ + ldrh r0, [r4, 0x28]\n\ + cmp r0, 0\n\ + bne _08018EBA\n\ + bl _08019F76\n\ +_08018EBA:\n\ + ldr r0, _08018F38 @ =gProtectStructs\n\ + lsls r1, r2, 4\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _08018ECC\n\ + bl _08019F76\n\ +_08018ECC:\n\ + ldr r2, _08018F3C @ =gSpecialStatuses\n\ + ldr r0, _08018F40 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r1, r0, 2\n\ + adds r0, r2, 0\n\ + adds r0, 0x8\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08018EF4\n\ + adds r0, r2, 0\n\ + adds r0, 0xC\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08018EF4\n\ + bl _08019F76\n\ +_08018EF4:\n\ + ldr r1, _08018F44 @ =gBattleMoves\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r1, [r0, 0x8]\n\ + movs r2, 0x1\n\ + adds r0, r2, 0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08018F0E\n\ + bl _08019F76\n\ +_08018F0E:\n\ + ldr r1, _08018F48 @ =gBattleMoveDamage\n\ + ldrh r0, [r4, 0x2C]\n\ + lsrs r0, 4\n\ + str r0, [r1]\n\ + cmp r0, 0\n\ + bne _08018F1C\n\ + str r2, [r1]\n\ +_08018F1C:\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08018F4C @ =gBattlescriptCurrInstr\n\ + ldr r0, _08018F50 @ =BattleScript_RoughSkinActivates\n\ + str r0, [r1]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_08018F2C: .4byte gBattleMoveFlags\n\ +_08018F30: .4byte gBattleMons\n\ +_08018F34: .4byte gBankAttacker\n\ +_08018F38: .4byte gProtectStructs\n\ +_08018F3C: .4byte gSpecialStatuses\n\ +_08018F40: .4byte gBankTarget\n\ +_08018F44: .4byte gBattleMoves\n\ +_08018F48: .4byte gBattleMoveDamage\n\ +_08018F4C: .4byte gBattlescriptCurrInstr\n\ +_08018F50: .4byte BattleScript_RoughSkinActivates\n\ +_08018F54:\n\ + ldr r0, _08019020 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08018F64\n\ + bl _08019F76\n\ +_08018F64:\n\ + ldr r1, _08019024 @ =gBattleMons\n\ + ldr r0, _08019028 @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + bne _08018F7A\n\ + bl _08019F76\n\ +_08018F7A:\n\ + ldr r0, _0801902C @ =gProtectStructs\n\ + lsls r1, r2, 4\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _08018F8C\n\ + bl _08019F76\n\ +_08018F8C:\n\ + ldr r2, _08019030 @ =gSpecialStatuses\n\ + ldr r0, _08019034 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r1, r0, 2\n\ + adds r0, r2, 0\n\ + adds r0, 0x8\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08018FB4\n\ + adds r0, r2, 0\n\ + adds r0, 0xC\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08018FB4\n\ + bl _08019F76\n\ +_08018FB4:\n\ + ldr r1, _08019038 @ =gBattleMoves\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r1, [r0, 0x8]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08018FCC\n\ + bl _08019F76\n\ +_08018FCC:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0xA\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + beq _08018FE4\n\ + bl _08019F76\n\ +_08018FE4:\n\ + ldr r5, _0801903C @ =gBattleCommunication\n\ + movs r4, 0x3\n\ +_08018FE8:\n\ + bl Random\n\ + ands r0, r4\n\ + strb r0, [r5, 0x3]\n\ + cmp r0, 0\n\ + beq _08018FE8\n\ + ldr r1, _0801903C @ =gBattleCommunication\n\ + ldrb r0, [r1, 0x3]\n\ + cmp r0, 0x3\n\ + bne _08019000\n\ + adds r0, 0x2\n\ + strb r0, [r1, 0x3]\n\ +_08019000:\n\ + ldrb r0, [r1, 0x3]\n\ + adds r0, 0x40\n\ + strb r0, [r1, 0x3]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08019040 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08019044 @ =BattleScript_ApplySecondaryEffect\n\ + str r0, [r1]\n\ + ldr r2, _08019048 @ =gHitMarker\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_08019020: .4byte gBattleMoveFlags\n\ +_08019024: .4byte gBattleMons\n\ +_08019028: .4byte gBankAttacker\n\ +_0801902C: .4byte gProtectStructs\n\ +_08019030: .4byte gSpecialStatuses\n\ +_08019034: .4byte gBankTarget\n\ +_08019038: .4byte gBattleMoves\n\ +_0801903C: .4byte gBattleCommunication\n\ +_08019040: .4byte gBattlescriptCurrInstr\n\ +_08019044: .4byte BattleScript_ApplySecondaryEffect\n\ +_08019048: .4byte gHitMarker\n\ +_0801904C:\n\ + ldr r0, _080190FC @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801905C\n\ + bl _08019F76\n\ +_0801905C:\n\ + ldr r1, _08019100 @ =gBattleMons\n\ + ldr r0, _08019104 @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + bne _08019072\n\ + bl _08019F76\n\ +_08019072:\n\ + ldr r0, _08019108 @ =gProtectStructs\n\ + lsls r1, r2, 4\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _08019084\n\ + bl _08019F76\n\ +_08019084:\n\ + ldr r2, _0801910C @ =gSpecialStatuses\n\ + ldr r0, _08019110 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r1, r0, 2\n\ + adds r0, r2, 0\n\ + adds r0, 0x8\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _080190AC\n\ + adds r0, r2, 0\n\ + adds r0, 0xC\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _080190AC\n\ + bl _08019F76\n\ +_080190AC:\n\ + ldr r1, _08019114 @ =gBattleMoves\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r1, [r0, 0x8]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080190C4\n\ + bl _08019F76\n\ +_080190C4:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x3\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + beq _080190DC\n\ + bl _08019F76\n\ +_080190DC:\n\ + ldr r1, _08019118 @ =gBattleCommunication\n\ + movs r0, 0x42\n\ + strb r0, [r1, 0x3]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _0801911C @ =gBattlescriptCurrInstr\n\ + ldr r0, _08019120 @ =BattleScript_ApplySecondaryEffect\n\ + str r0, [r1]\n\ + ldr r2, _08019124 @ =gHitMarker\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_080190FC: .4byte gBattleMoveFlags\n\ +_08019100: .4byte gBattleMons\n\ +_08019104: .4byte gBankAttacker\n\ +_08019108: .4byte gProtectStructs\n\ +_0801910C: .4byte gSpecialStatuses\n\ +_08019110: .4byte gBankTarget\n\ +_08019114: .4byte gBattleMoves\n\ +_08019118: .4byte gBattleCommunication\n\ +_0801911C: .4byte gBattlescriptCurrInstr\n\ +_08019120: .4byte BattleScript_ApplySecondaryEffect\n\ +_08019124: .4byte gHitMarker\n\ +_08019128:\n\ + ldr r0, _080191D8 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08019138\n\ + bl _08019F76\n\ +_08019138:\n\ + ldr r1, _080191DC @ =gBattleMons\n\ + ldr r0, _080191E0 @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + bne _0801914E\n\ + bl _08019F76\n\ +_0801914E:\n\ + ldr r0, _080191E4 @ =gProtectStructs\n\ + lsls r1, r2, 4\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _08019160\n\ + bl _08019F76\n\ +_08019160:\n\ + ldr r2, _080191E8 @ =gSpecialStatuses\n\ + ldr r0, _080191EC @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r1, r0, 2\n\ + adds r0, r2, 0\n\ + adds r0, 0x8\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08019188\n\ + adds r0, r2, 0\n\ + adds r0, 0xC\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08019188\n\ + bl _08019F76\n\ +_08019188:\n\ + ldr r1, _080191F0 @ =gBattleMoves\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r1, [r0, 0x8]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080191A0\n\ + bl _08019F76\n\ +_080191A0:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x3\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + beq _080191B8\n\ + bl _08019F76\n\ +_080191B8:\n\ + ldr r1, _080191F4 @ =gBattleCommunication\n\ + movs r0, 0x45\n\ + strb r0, [r1, 0x3]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _080191F8 @ =gBattlescriptCurrInstr\n\ + ldr r0, _080191FC @ =BattleScript_ApplySecondaryEffect\n\ + str r0, [r1]\n\ + ldr r2, _08019200 @ =gHitMarker\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_080191D8: .4byte gBattleMoveFlags\n\ +_080191DC: .4byte gBattleMons\n\ +_080191E0: .4byte gBankAttacker\n\ +_080191E4: .4byte gProtectStructs\n\ +_080191E8: .4byte gSpecialStatuses\n\ +_080191EC: .4byte gBankTarget\n\ +_080191F0: .4byte gBattleMoves\n\ +_080191F4: .4byte gBattleCommunication\n\ +_080191F8: .4byte gBattlescriptCurrInstr\n\ +_080191FC: .4byte BattleScript_ApplySecondaryEffect\n\ +_08019200: .4byte gHitMarker\n\ +_08019204:\n\ + ldr r0, _080192B4 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08019214\n\ + bl _08019F76\n\ +_08019214:\n\ + ldr r1, _080192B8 @ =gBattleMons\n\ + ldr r0, _080192BC @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + bne _0801922A\n\ + bl _08019F76\n\ +_0801922A:\n\ + ldr r0, _080192C0 @ =gProtectStructs\n\ + lsls r1, r2, 4\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _0801923C\n\ + bl _08019F76\n\ +_0801923C:\n\ + ldr r1, _080192C4 @ =gBattleMoves\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r1, [r0, 0x8]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08019254\n\ + bl _08019F76\n\ +_08019254:\n\ + ldr r2, _080192C8 @ =gSpecialStatuses\n\ + ldr r0, _080192CC @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r1, r0, 2\n\ + adds r0, r2, 0\n\ + adds r0, 0x8\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _0801927C\n\ + adds r0, r2, 0\n\ + adds r0, 0xC\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _0801927C\n\ + bl _08019F76\n\ +_0801927C:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x3\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + beq _08019294\n\ + bl _08019F76\n\ +_08019294:\n\ + ldr r1, _080192D0 @ =gBattleCommunication\n\ + movs r0, 0x43\n\ + strb r0, [r1, 0x3]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _080192D4 @ =gBattlescriptCurrInstr\n\ + ldr r0, _080192D8 @ =BattleScript_ApplySecondaryEffect\n\ + str r0, [r1]\n\ + ldr r2, _080192DC @ =gHitMarker\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_080192B4: .4byte gBattleMoveFlags\n\ +_080192B8: .4byte gBattleMons\n\ +_080192BC: .4byte gBankAttacker\n\ +_080192C0: .4byte gProtectStructs\n\ +_080192C4: .4byte gBattleMoves\n\ +_080192C8: .4byte gSpecialStatuses\n\ +_080192CC: .4byte gBankTarget\n\ +_080192D0: .4byte gBattleCommunication\n\ +_080192D4: .4byte gBattlescriptCurrInstr\n\ +_080192D8: .4byte BattleScript_ApplySecondaryEffect\n\ +_080192DC: .4byte gHitMarker\n\ +_080192E0:\n\ + ldr r0, _08019420 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080192F0\n\ + bl _08019F76\n\ +_080192F0:\n\ + ldr r5, _08019424 @ =gBattleMons\n\ + ldr r7, _08019428 @ =gBankAttacker\n\ + ldrb r1, [r7]\n\ + movs r6, 0x58\n\ + adds r0, r1, 0\n\ + muls r0, r6\n\ + adds r0, r5\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + bne _08019308\n\ + bl _08019F76\n\ +_08019308:\n\ + ldr r0, _0801942C @ =gProtectStructs\n\ + lsls r1, 4\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _0801931A\n\ + bl _08019F76\n\ +_0801931A:\n\ + ldr r1, _08019430 @ =gBattleMoves\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r1, [r0, 0x8]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08019332\n\ + bl _08019F76\n\ +_08019332:\n\ + ldr r3, _08019434 @ =gSpecialStatuses\n\ + ldr r0, _08019438 @ =gBankTarget\n\ + mov r8, r0\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r2, r0, 2\n\ + adds r0, r3, 0\n\ + adds r0, 0x8\n\ + adds r0, r2, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _0801935C\n\ + adds r0, r3, 0\n\ + adds r0, 0xC\n\ + adds r0, r2, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _0801935C\n\ + bl _08019F76\n\ +_0801935C:\n\ + adds r0, r1, 0\n\ + muls r0, r6\n\ + adds r0, r5\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + bne _0801936C\n\ + bl _08019F76\n\ +_0801936C:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x3\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + beq _08019384\n\ + bl _08019F76\n\ +_08019384:\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r0, r5\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xC\n\ + bne _08019396\n\ + bl _08019F76\n\ +_08019396:\n\ + ldr r0, [sp, 0x8]\n\ + ldr r1, [sp, 0x10]\n\ + bl GetGenderFromSpeciesAndPersonality\n\ + adds r4, r0, 0\n\ + ldr r0, [sp, 0xC]\n\ + ldr r1, [sp, 0x14]\n\ + bl GetGenderFromSpeciesAndPersonality\n\ + lsls r4, 24\n\ + lsls r0, 24\n\ + cmp r4, r0\n\ + bne _080193B4\n\ + bl _08019F76\n\ +_080193B4:\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r4, r5, 0\n\ + adds r4, 0x50\n\ + adds r0, r4\n\ + ldr r0, [r0]\n\ + movs r1, 0xF0\n\ + lsls r1, 12\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080193CE\n\ + bl _08019F76\n\ +_080193CE:\n\ + ldr r0, [sp, 0x8]\n\ + ldr r1, [sp, 0x10]\n\ + bl GetGenderFromSpeciesAndPersonality\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0xFF\n\ + bne _080193E2\n\ + bl _08019F76\n\ +_080193E2:\n\ + ldr r0, [sp, 0xC]\n\ + ldr r1, [sp, 0x14]\n\ + bl GetGenderFromSpeciesAndPersonality\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0xFF\n\ + bne _080193F6\n\ + bl _08019F76\n\ +_080193F6:\n\ + ldrb r0, [r7]\n\ + adds r2, r0, 0\n\ + muls r2, r6\n\ + adds r2, r4\n\ + ldr r1, _0801943C @ =gBitTable\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r1, [r0]\n\ + lsls r1, 16\n\ + ldr r0, [r2]\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08019440 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08019444 @ =BattleScript_CuteCharmActivates\n\ + str r0, [r1]\n\ + bl _08019F22\n\ + .align 2, 0\n\ +_08019420: .4byte gBattleMoveFlags\n\ +_08019424: .4byte gBattleMons\n\ +_08019428: .4byte gBankAttacker\n\ +_0801942C: .4byte gProtectStructs\n\ +_08019430: .4byte gBattleMoves\n\ +_08019434: .4byte gSpecialStatuses\n\ +_08019438: .4byte gBankTarget\n\ +_0801943C: .4byte gBitTable\n\ +_08019440: .4byte gBattlescriptCurrInstr\n\ +_08019444: .4byte BattleScript_CuteCharmActivates\n\ +_08019448:\n\ + movs r5, 0\n\ + mov r10, r5\n\ + ldr r0, _0801947C @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r10, r0\n\ + bcc _08019458\n\ + bl _08019F76\n\ +_08019458:\n\ + ldr r1, _08019480 @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r2, r10\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + adds r0, r1\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + subs r0, 0x7\n\ + adds r2, r1, 0\n\ + cmp r0, 0x41\n\ + bls _08019472\n\ + b _080196D6\n\ +_08019472:\n\ + lsls r0, 2\n\ + ldr r1, _08019484 @ =_08019488\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_0801947C: .4byte gNoOfAllBanks\n\ +_08019480: .4byte gBattleMons\n\ +_08019484: .4byte _08019488\n\ + .align 2, 0\n\ +_08019488:\n\ + .4byte _080195EC\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196B0\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _08019614\n\ + .4byte _080196D6\n\ + .4byte _08019590\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080195BC\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _08019680\n\ + .4byte _08019650\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _080196D6\n\ + .4byte _08019614\n\ +_08019590:\n\ + movs r0, 0x58\n\ + mov r3, r10\n\ + muls r3, r0\n\ + adds r0, r3, 0\n\ + adds r1, r2, 0\n\ + adds r1, 0x4C\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + ldr r1, _080195B0 @ =0x00000f88\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080195AA\n\ + b _080196D6\n\ +_080195AA:\n\ + ldr r0, _080195B4 @ =gBattleTextBuff1\n\ + ldr r1, _080195B8 @ =gStatusConditionString_PoisonJpn\n\ + b _0801969C\n\ + .align 2, 0\n\ +_080195B0: .4byte 0x00000f88\n\ +_080195B4: .4byte gBattleTextBuff1\n\ +_080195B8: .4byte gStatusConditionString_PoisonJpn\n\ +_080195BC:\n\ + movs r0, 0x58\n\ + mov r1, r10\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + adds r1, r2, 0\n\ + adds r1, 0x50\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x7\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080195D6\n\ + b _080196D6\n\ +_080195D6:\n\ + ldr r0, _080195E4 @ =gBattleTextBuff1\n\ + ldr r1, _080195E8 @ =gStatusConditionString_ConfusionJpn\n\ + bl StringCopy\n\ + movs r2, 0x2\n\ + mov r9, r2\n\ + b _080196DC\n\ + .align 2, 0\n\ +_080195E4: .4byte gBattleTextBuff1\n\ +_080195E8: .4byte gStatusConditionString_ConfusionJpn\n\ +_080195EC:\n\ + movs r0, 0x58\n\ + mov r3, r10\n\ + muls r3, r0\n\ + adds r0, r3, 0\n\ + adds r1, r2, 0\n\ + adds r1, 0x4C\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x40\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080196D6\n\ + ldr r0, _0801960C @ =gBattleTextBuff1\n\ + ldr r1, _08019610 @ =gStatusConditionString_ParalysisJpn\n\ + b _0801969C\n\ + .align 2, 0\n\ +_0801960C: .4byte gBattleTextBuff1\n\ +_08019610: .4byte gStatusConditionString_ParalysisJpn\n\ +_08019614:\n\ + movs r0, 0x58\n\ + mov r3, r10\n\ + muls r3, r0\n\ + adds r0, r2, 0\n\ + adds r0, 0x4C\n\ + adds r0, r3, r0\n\ + ldr r0, [r0]\n\ + movs r1, 0x7\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080196D6\n\ + adds r2, 0x50\n\ + adds r2, r3, r2\n\ + ldr r0, [r2]\n\ + ldr r1, _08019644 @ =0xf7ffffff\n\ + ands r0, r1\n\ + str r0, [r2]\n\ + ldr r0, _08019648 @ =gBattleTextBuff1\n\ + ldr r1, _0801964C @ =gStatusConditionString_SleepJpn\n\ + bl StringCopy\n\ + movs r0, 0x1\n\ + mov r9, r0\n\ + b _080196DC\n\ + .align 2, 0\n\ +_08019644: .4byte 0xf7ffffff\n\ +_08019648: .4byte gBattleTextBuff1\n\ +_0801964C: .4byte gStatusConditionString_SleepJpn\n\ +_08019650:\n\ + movs r0, 0x58\n\ + mov r1, r10\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + adds r1, r2, 0\n\ + adds r1, 0x4C\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x10\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080196D6\n\ + ldr r0, _08019678 @ =gBattleTextBuff1\n\ + ldr r1, _0801967C @ =gStatusConditionString_BurnJpn\n\ + bl StringCopy\n\ + movs r2, 0x1\n\ + mov r9, r2\n\ + b _080196DC\n\ + .align 2, 0\n\ +_08019678: .4byte gBattleTextBuff1\n\ +_0801967C: .4byte gStatusConditionString_BurnJpn\n\ +_08019680:\n\ + movs r0, 0x58\n\ + mov r3, r10\n\ + muls r3, r0\n\ + adds r0, r3, 0\n\ + adds r1, r2, 0\n\ + adds r1, 0x4C\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x20\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080196D6\n\ + ldr r0, _080196A8 @ =gBattleTextBuff1\n\ + ldr r1, _080196AC @ =gStatusConditionString_IceJpn\n\ +_0801969C:\n\ + bl StringCopy\n\ + movs r5, 0x1\n\ + mov r9, r5\n\ + b _080196DC\n\ + .align 2, 0\n\ +_080196A8: .4byte gBattleTextBuff1\n\ +_080196AC: .4byte gStatusConditionString_IceJpn\n\ +_080196B0:\n\ + movs r0, 0x58\n\ + mov r1, r10\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + adds r1, r2, 0\n\ + adds r1, 0x50\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0xF0\n\ + lsls r1, 12\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080196D6\n\ + ldr r0, _080196EC @ =gBattleTextBuff1\n\ + ldr r1, _080196F0 @ =gStatusConditionString_LoveJpn\n\ + bl StringCopy\n\ + movs r2, 0x3\n\ + mov r9, r2\n\ +_080196D6:\n\ + mov r3, r9\n\ + cmp r3, 0\n\ + beq _08019798\n\ +_080196DC:\n\ + mov r5, r9\n\ + cmp r5, 0x2\n\ + beq _08019710\n\ + cmp r5, 0x2\n\ + bgt _080196F4\n\ + cmp r5, 0x1\n\ + beq _080196FC\n\ + b _0801973C\n\ + .align 2, 0\n\ +_080196EC: .4byte gBattleTextBuff1\n\ +_080196F0: .4byte gStatusConditionString_LoveJpn\n\ +_080196F4:\n\ + mov r0, r9\n\ + cmp r0, 0x3\n\ + beq _08019728\n\ + b _0801973C\n\ +_080196FC:\n\ + ldr r1, _0801970C @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r2, r10\n\ + muls r2, r0\n\ + adds r1, 0x4C\n\ + adds r2, r1\n\ + movs r0, 0\n\ + b _0801973A\n\ + .align 2, 0\n\ +_0801970C: .4byte gBattleMons\n\ +_08019710:\n\ + ldr r1, _08019724 @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r2, r10\n\ + muls r2, r0\n\ + adds r1, 0x50\n\ + adds r2, r1\n\ + ldr r0, [r2]\n\ + movs r1, 0x8\n\ + negs r1, r1\n\ + b _08019738\n\ + .align 2, 0\n\ +_08019724: .4byte gBattleMons\n\ +_08019728:\n\ + ldr r1, _08019778 @ =gBattleMons\n\ + movs r0, 0x58\n\ + mov r2, r10\n\ + muls r2, r0\n\ + adds r1, 0x50\n\ + adds r2, r1\n\ + ldr r0, [r2]\n\ + ldr r1, _0801977C @ =0xfff0ffff\n\ +_08019738:\n\ + ands r0, r1\n\ +_0801973A:\n\ + str r0, [r2]\n\ +_0801973C:\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08019780 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08019784 @ =gUnknown_081D9956\n\ + str r0, [r1]\n\ + ldr r0, _08019788 @ =0x02000000\n\ + ldr r1, _0801978C @ =0x00016003\n\ + adds r0, r1\n\ + mov r2, r10\n\ + strb r2, [r0]\n\ + ldr r4, _08019790 @ =gActiveBank\n\ + strb r2, [r4]\n\ + ldrb r1, [r4]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + ldr r1, _08019794 @ =gUnknown_02024ACC\n\ + adds r0, r1\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x28\n\ + movs r2, 0\n\ + movs r3, 0x4\n\ + bl EmitSetAttributes\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + bl _08019F92\n\ + .align 2, 0\n\ +_08019778: .4byte gBattleMons\n\ +_0801977C: .4byte 0xfff0ffff\n\ +_08019780: .4byte gBattlescriptCurrInstr\n\ +_08019784: .4byte gUnknown_081D9956\n\ +_08019788: .4byte 0x02000000\n\ +_0801978C: .4byte 0x00016003\n\ +_08019790: .4byte gActiveBank\n\ +_08019794: .4byte gUnknown_02024ACC\n\ +_08019798:\n\ + mov r0, r10\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r10, r0\n\ + ldr r0, _080197B0 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r10, r0\n\ + bcs _080197AC\n\ + b _08019458\n\ +_080197AC:\n\ + bl _08019F76\n\ + .align 2, 0\n\ +_080197B0: .4byte gNoOfAllBanks\n\ +_080197B4:\n\ + movs r3, 0\n\ + mov r10, r3\n\ + ldr r0, _080197FC @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r10, r0\n\ + bcc _080197C2\n\ + b _08019F76\n\ +_080197C2:\n\ + ldr r4, _08019800 @ =gBattleMons\n\ +_080197C4:\n\ + movs r0, 0x58\n\ + mov r5, r10\n\ + muls r5, r0\n\ + adds r0, r5, 0\n\ + adds r0, r4\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x3B\n\ + bne _080197E8\n\ + mov r0, r10\n\ + bl CastformDataTypeChange\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ + cmp r0, 0\n\ + beq _080197E8\n\ + b _08019E40\n\ +_080197E8:\n\ + mov r0, r10\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r10, r0\n\ + ldr r0, _080197FC @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r10, r0\n\ + bcc _080197C4\n\ + b _08019F76\n\ + .align 2, 0\n\ +_080197FC: .4byte gNoOfAllBanks\n\ +_08019800: .4byte gBattleMons\n\ +_08019804:\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + cmp r0, 0x1C\n\ + beq _0801980E\n\ + b _08019F76\n\ +_0801980E:\n\ + ldr r4, _08019860 @ =gHitMarker\n\ + ldr r1, [r4]\n\ + movs r0, 0x80\n\ + lsls r0, 7\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801981E\n\ + b _08019F76\n\ +_0801981E:\n\ + ldr r0, _08019864 @ =0xffffbfff\n\ + ands r1, r0\n\ + str r1, [r4]\n\ + ldr r3, _08019868 @ =0x000160ca\n\ + adds r2, r7, r3\n\ + ldrb r1, [r2]\n\ + movs r0, 0x3F\n\ + ands r0, r1\n\ + strb r0, [r2]\n\ + cmp r0, 0x6\n\ + bne _08019838\n\ + movs r0, 0x2\n\ + strb r0, [r2]\n\ +_08019838:\n\ + ldr r1, _0801986C @ =gBattleCommunication\n\ + ldrb r0, [r2]\n\ + adds r0, 0x40\n\ + strb r0, [r1, 0x3]\n\ + ldr r0, _08019870 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + ldr r5, _08019874 @ =0x00016003\n\ + adds r0, r7, r5\n\ + strb r1, [r0]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08019878 @ =gBattlescriptCurrInstr\n\ + ldr r0, _0801987C @ =BattleScript_SynchronizeActivates\n\ + str r0, [r1]\n\ + ldr r0, [r4]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + orrs r0, r1\n\ + str r0, [r4]\n\ + b _08019F22\n\ + .align 2, 0\n\ +_08019860: .4byte gHitMarker\n\ +_08019864: .4byte 0xffffbfff\n\ +_08019868: .4byte 0x000160ca\n\ +_0801986C: .4byte gBattleCommunication\n\ +_08019870: .4byte gBankTarget\n\ +_08019874: .4byte 0x00016003\n\ +_08019878: .4byte gBattlescriptCurrInstr\n\ +_0801987C: .4byte BattleScript_SynchronizeActivates\n\ +_08019880:\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + cmp r0, 0x1C\n\ + beq _0801988A\n\ + b _08019F76\n\ +_0801988A:\n\ + ldr r4, _080198DC @ =gHitMarker\n\ + ldr r1, [r4]\n\ + movs r0, 0x80\n\ + lsls r0, 7\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801989A\n\ + b _08019F76\n\ +_0801989A:\n\ + ldr r0, _080198E0 @ =0xffffbfff\n\ + ands r1, r0\n\ + str r1, [r4]\n\ + ldr r3, _080198E4 @ =0x000160ca\n\ + adds r2, r7, r3\n\ + ldrb r1, [r2]\n\ + movs r0, 0x3F\n\ + ands r0, r1\n\ + strb r0, [r2]\n\ + cmp r0, 0x6\n\ + bne _080198B4\n\ + movs r0, 0x2\n\ + strb r0, [r2]\n\ +_080198B4:\n\ + ldr r1, _080198E8 @ =gBattleCommunication\n\ + ldrb r0, [r2]\n\ + strb r0, [r1, 0x3]\n\ + ldr r0, _080198EC @ =gBankAttacker\n\ + ldrb r1, [r0]\n\ + ldr r5, _080198F0 @ =0x00016003\n\ + adds r0, r7, r5\n\ + strb r1, [r0]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _080198F4 @ =gBattlescriptCurrInstr\n\ + ldr r0, _080198F8 @ =BattleScript_SynchronizeActivates\n\ + str r0, [r1]\n\ + ldr r0, [r4]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + orrs r0, r1\n\ + str r0, [r4]\n\ + b _08019F22\n\ + .align 2, 0\n\ +_080198DC: .4byte gHitMarker\n\ +_080198E0: .4byte 0xffffbfff\n\ +_080198E4: .4byte 0x000160ca\n\ +_080198E8: .4byte gBattleCommunication\n\ +_080198EC: .4byte gBankAttacker\n\ +_080198F0: .4byte 0x00016003\n\ +_080198F4: .4byte gBattlescriptCurrInstr\n\ +_080198F8: .4byte BattleScript_SynchronizeActivates\n\ +_080198FC:\n\ + movs r4, 0\n\ + ldr r0, _08019934 @ =gNoOfAllBanks\n\ + ldrb r1, [r0]\n\ + cmp r4, r1\n\ + blt _08019908\n\ + b _08019F76\n\ +_08019908:\n\ + ldr r0, _08019938 @ =gBattleMons\n\ + adds r5, r1, 0\n\ + ldr r2, _0801993C @ =gStatuses3\n\ + adds r3, r0, 0\n\ + adds r3, 0x20\n\ + movs r6, 0x80\n\ + lsls r6, 12\n\ +_08019916:\n\ + ldrb r1, [r3]\n\ + cmp r1, 0x16\n\ + bne _08019926\n\ + ldr r0, [r2]\n\ + ands r0, r6\n\ + cmp r0, 0\n\ + beq _08019926\n\ + b _08019E6C\n\ +_08019926:\n\ + adds r2, 0x4\n\ + adds r3, 0x58\n\ + adds r4, 0x1\n\ + cmp r4, r5\n\ + blt _08019916\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019934: .4byte gNoOfAllBanks\n\ +_08019938: .4byte gBattleMons\n\ +_0801993C: .4byte gStatuses3\n\ +_08019940:\n\ + movs r4, 0\n\ + ldr r0, _08019A1C @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _0801994C\n\ + b _08019F76\n\ +_0801994C:\n\ + ldr r0, _08019A20 @ =gActiveBank\n\ + mov r8, r0\n\ + ldr r1, _08019A24 @ =gBattleMons\n\ + adds r1, 0x20\n\ + str r1, [sp, 0x1C]\n\ + movs r2, 0\n\ + str r2, [sp, 0x20]\n\ +_0801995A:\n\ + ldr r3, [sp, 0x1C]\n\ + ldrb r0, [r3]\n\ + cmp r0, 0x24\n\ + beq _08019964\n\ + b _08019AF6\n\ +_08019964:\n\ + ldr r0, _08019A28 @ =gStatuses3\n\ + ldr r5, [sp, 0x20]\n\ + adds r0, r5, r0\n\ + ldr r1, [r0]\n\ + movs r0, 0x80\n\ + lsls r0, 13\n\ + ands r1, r0\n\ + str r5, [sp, 0x18]\n\ + cmp r1, 0\n\ + bne _0801997A\n\ + b _08019AF6\n\ +_0801997A:\n\ + lsls r0, r4, 24\n\ + lsrs r0, 24\n\ + bl GetBankIdentity\n\ + movs r1, 0x1\n\ + adds r5, r0, 0\n\ + eors r5, r1\n\ + ands r5, r1\n\ + adds r0, r5, 0\n\ + bl GetBankByPlayerAI\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + adds r0, r5, 0x2\n\ + bl GetBankByPlayerAI\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ + ldr r0, _08019A2C @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r2, 0x1\n\ + adds r0, r2, 0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080199AE\n\ + b _08019ABC\n\ +_080199AE:\n\ + movs r1, 0x58\n\ + adds r0, r6, 0\n\ + muls r0, r1\n\ + ldr r3, _08019A24 @ =gBattleMons\n\ + adds r1, r0, r3\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _08019A78\n\ + ldrh r0, [r1, 0x28]\n\ + cmp r0, 0\n\ + beq _08019A34\n\ + movs r1, 0x58\n\ + adds r0, r7, 0\n\ + muls r0, r1\n\ + adds r1, r0, r3\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _08019A34\n\ + ldrh r0, [r1, 0x28]\n\ + cmp r0, 0\n\ + beq _08019A34\n\ + str r2, [sp, 0x24]\n\ + bl Random\n\ + ldr r2, [sp, 0x24]\n\ + adds r1, r2, 0\n\ + ands r1, r0\n\ + lsls r1, 1\n\ + orrs r5, r1\n\ + adds r0, r5, 0\n\ + bl GetBankByPlayerAI\n\ + mov r2, r8\n\ + strb r0, [r2]\n\ + ldrb r0, [r2]\n\ + movs r3, 0x58\n\ + muls r0, r3\n\ + ldr r5, _08019A24 @ =gBattleMons\n\ + adds r0, r5\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + ldr r1, [sp, 0x1C]\n\ + strb r0, [r1]\n\ + ldrb r0, [r2]\n\ + muls r0, r3\n\ + adds r0, r5\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + ldr r2, _08019A30 @ =gLastUsedAbility\n\ + strb r0, [r2]\n\ + b _08019AE4\n\ + .align 2, 0\n\ +_08019A1C: .4byte gNoOfAllBanks\n\ +_08019A20: .4byte gActiveBank\n\ +_08019A24: .4byte gBattleMons\n\ +_08019A28: .4byte gStatuses3\n\ +_08019A2C: .4byte gBattleTypeFlags\n\ +_08019A30: .4byte gLastUsedAbility\n\ +_08019A34:\n\ + ldr r3, _08019A74 @ =gBattleMons\n\ + movs r2, 0x58\n\ + adds r0, r6, 0\n\ + muls r0, r2\n\ + adds r1, r0, r3\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _08019A78\n\ + ldrh r0, [r1, 0x28]\n\ + cmp r0, 0\n\ + beq _08019A78\n\ + mov r5, r8\n\ + strb r6, [r5]\n\ + adds r1, r4, 0\n\ + muls r1, r2\n\ + adds r1, r3\n\ + ldrb r0, [r5]\n\ + muls r0, r2\n\ + adds r0, r3\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + adds r1, 0x20\n\ + strb r0, [r1]\n\ + ldrb r0, [r5]\n\ + muls r0, r2\n\ + adds r0, r3\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + b _08019AE0\n\ + .align 2, 0\n\ +_08019A74: .4byte gBattleMons\n\ +_08019A78:\n\ + ldr r3, _08019AB8 @ =gBattleMons\n\ + movs r2, 0x58\n\ + adds r0, r7, 0\n\ + muls r0, r2\n\ + adds r1, r0, r3\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _08019AEE\n\ + ldrh r0, [r1, 0x28]\n\ + cmp r0, 0\n\ + beq _08019AEE\n\ + mov r5, r8\n\ + strb r7, [r5]\n\ + adds r1, r4, 0\n\ + muls r1, r2\n\ + adds r1, r3\n\ + ldrb r0, [r5]\n\ + muls r0, r2\n\ + adds r0, r3\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + adds r1, 0x20\n\ + strb r0, [r1]\n\ + ldrb r0, [r5]\n\ + muls r0, r2\n\ + adds r0, r3\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + b _08019AE0\n\ + .align 2, 0\n\ +_08019AB8: .4byte gBattleMons\n\ +_08019ABC:\n\ + mov r2, r8\n\ + strb r6, [r2]\n\ + movs r3, 0x58\n\ + adds r0, r6, 0\n\ + muls r0, r3\n\ + ldr r5, _08019B10 @ =gBattleMons\n\ + adds r0, r5\n\ + adds r2, r0, 0\n\ + adds r2, 0x20\n\ + ldrb r1, [r2]\n\ + cmp r1, 0\n\ + beq _08019AEE\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + beq _08019AEE\n\ + ldr r0, [sp, 0x1C]\n\ + strb r1, [r0]\n\ + ldrb r0, [r2]\n\ +_08019AE0:\n\ + ldr r1, _08019B14 @ =gLastUsedAbility\n\ + strb r0, [r1]\n\ +_08019AE4:\n\ + mov r0, r9\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019AEE:\n\ + mov r2, r9\n\ + cmp r2, 0\n\ + beq _08019AF6\n\ + b _08019E88\n\ +_08019AF6:\n\ + ldr r3, [sp, 0x1C]\n\ + adds r3, 0x58\n\ + str r3, [sp, 0x1C]\n\ + ldr r5, [sp, 0x20]\n\ + adds r5, 0x4\n\ + str r5, [sp, 0x20]\n\ + adds r4, 0x1\n\ + ldr r0, _08019B18 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + bge _08019B0E\n\ + b _0801995A\n\ +_08019B0E:\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019B10: .4byte gBattleMons\n\ +_08019B14: .4byte gLastUsedAbility\n\ +_08019B18: .4byte gNoOfAllBanks\n\ +_08019B1C:\n\ + movs r4, 0\n\ + ldr r0, _08019B54 @ =gNoOfAllBanks\n\ + ldrb r1, [r0]\n\ + cmp r4, r1\n\ + blt _08019B28\n\ + b _08019F76\n\ +_08019B28:\n\ + ldr r0, _08019B58 @ =gBattleMons\n\ + adds r5, r1, 0\n\ + ldr r2, _08019B5C @ =gStatuses3\n\ + adds r3, r0, 0\n\ + adds r3, 0x20\n\ + movs r6, 0x80\n\ + lsls r6, 12\n\ +_08019B36:\n\ + ldrb r1, [r3]\n\ + cmp r1, 0x16\n\ + bne _08019B46\n\ + ldr r0, [r2]\n\ + ands r0, r6\n\ + cmp r0, 0\n\ + beq _08019B46\n\ + b _08019F04\n\ +_08019B46:\n\ + adds r2, 0x4\n\ + adds r3, 0x58\n\ + adds r4, 0x1\n\ + cmp r4, r5\n\ + blt _08019B36\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019B54: .4byte gNoOfAllBanks\n\ +_08019B58: .4byte gBattleMons\n\ +_08019B5C: .4byte gStatuses3\n\ +_08019B60:\n\ + mov r0, r10\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + movs r4, 0\n\ + ldr r0, _08019BB0 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019B76\n\ + b _08019F76\n\ +_08019B76:\n\ + ldr r7, _08019BB4 @ =gBattleMons\n\ +_08019B78:\n\ + lsls r0, r4, 24\n\ + lsrs r0, 24\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + adds r3, r4, 0x1\n\ + cmp r0, r5\n\ + beq _08019BA2\n\ + movs r0, 0x58\n\ + muls r0, r4\n\ + adds r0, r7\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, r6\n\ + bne _08019BA2\n\ + ldr r0, _08019BB8 @ =gLastUsedAbility\n\ + strb r6, [r0]\n\ + lsls r0, r3, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019BA2:\n\ + adds r4, r3, 0\n\ + ldr r0, _08019BB0 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019B78\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019BB0: .4byte gNoOfAllBanks\n\ +_08019BB4: .4byte gBattleMons\n\ +_08019BB8: .4byte gLastUsedAbility\n\ +_08019BBC:\n\ + mov r0, r10\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + movs r4, 0\n\ + ldr r0, _08019C0C @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019BD2\n\ + b _08019F76\n\ +_08019BD2:\n\ + ldr r7, _08019C10 @ =gBattleMons\n\ +_08019BD4:\n\ + lsls r0, r4, 24\n\ + lsrs r0, 24\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + adds r3, r4, 0x1\n\ + cmp r0, r5\n\ + bne _08019BFE\n\ + movs r0, 0x58\n\ + muls r0, r4\n\ + adds r0, r7\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, r6\n\ + bne _08019BFE\n\ + ldr r0, _08019C14 @ =gLastUsedAbility\n\ + strb r6, [r0]\n\ + lsls r0, r3, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019BFE:\n\ + adds r4, r3, 0\n\ + ldr r0, _08019C0C @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019BD4\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019C0C: .4byte gNoOfAllBanks\n\ +_08019C10: .4byte gBattleMons\n\ +_08019C14: .4byte gLastUsedAbility\n\ +_08019C18:\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + cmp r0, 0xFD\n\ + beq _08019C40\n\ + cmp r0, 0xFE\n\ + beq _08019C78\n\ + movs r4, 0\n\ + ldr r0, _08019C38 @ =gNoOfAllBanks\n\ + adds r5, r0, 0\n\ + ldrb r2, [r5]\n\ + cmp r4, r2\n\ + blt _08019C32\n\ + b _08019F76\n\ +_08019C32:\n\ + ldr r2, _08019C3C @ =gBattleMons\n\ + b _08019CB0\n\ + .align 2, 0\n\ +_08019C38: .4byte gNoOfAllBanks\n\ +_08019C3C: .4byte gBattleMons\n\ +_08019C40:\n\ + movs r4, 0\n\ + ldr r0, _08019C70 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019C4C\n\ + b _08019F76\n\ +_08019C4C:\n\ + ldr r5, _08019C74 @ =gStatuses3\n\ + movs r2, 0x80\n\ + lsls r2, 9\n\ + adds r1, r0, 0\n\ +_08019C54:\n\ + lsls r0, r4, 2\n\ + adds r0, r5\n\ + ldr r0, [r0]\n\ + ands r0, r2\n\ + adds r3, r4, 0x1\n\ + cmp r0, 0\n\ + beq _08019C68\n\ + lsls r0, r3, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019C68:\n\ + adds r4, r3, 0\n\ + cmp r4, r1\n\ + blt _08019C54\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019C70: .4byte gNoOfAllBanks\n\ +_08019C74: .4byte gStatuses3\n\ +_08019C78:\n\ + movs r4, 0\n\ + ldr r0, _08019CA8 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019C84\n\ + b _08019F76\n\ +_08019C84:\n\ + ldr r5, _08019CAC @ =gStatuses3\n\ + movs r2, 0x80\n\ + lsls r2, 10\n\ + adds r1, r0, 0\n\ +_08019C8C:\n\ + lsls r0, r4, 2\n\ + adds r0, r5\n\ + ldr r0, [r0]\n\ + ands r0, r2\n\ + adds r3, r4, 0x1\n\ + cmp r0, 0\n\ + beq _08019CA0\n\ + lsls r0, r3, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019CA0:\n\ + adds r4, r3, 0\n\ + cmp r4, r1\n\ + blt _08019C8C\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019CA8: .4byte gNoOfAllBanks\n\ +_08019CAC: .4byte gStatuses3\n\ +_08019CB0:\n\ + movs r0, 0x58\n\ + muls r0, r4\n\ + adds r0, r2\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + adds r3, r4, 0x1\n\ + cmp r0, r6\n\ + bne _08019CCA\n\ + mov r0, r8\n\ + strb r6, [r0]\n\ + lsls r0, r3, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019CCA:\n\ + adds r4, r3, 0\n\ + ldrb r1, [r5]\n\ + cmp r4, r1\n\ + blt _08019CB0\n\ + b _08019F76\n\ +_08019CD4:\n\ + movs r4, 0\n\ + ldr r0, _08019D10 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019CE0\n\ + b _08019F76\n\ +_08019CE0:\n\ + ldr r7, _08019D14 @ =gBattleMons\n\ + adds r2, r0, 0\n\ + movs r5, 0x58\n\ +_08019CE6:\n\ + adds r0, r4, 0\n\ + muls r0, r5\n\ + adds r1, r0, r7\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + adds r3, r4, 0x1\n\ + cmp r0, r6\n\ + bne _08019D08\n\ + ldrh r0, [r1, 0x28]\n\ + cmp r0, 0\n\ + beq _08019D08\n\ + mov r0, r8\n\ + strb r6, [r0]\n\ + lsls r0, r3, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019D08:\n\ + adds r4, r3, 0\n\ + cmp r4, r2\n\ + blt _08019CE6\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019D10: .4byte gNoOfAllBanks\n\ +_08019D14: .4byte gBattleMons\n\ +_08019D18:\n\ + movs r4, 0\n\ + ldr r0, _08019D50 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019D24\n\ + b _08019F76\n\ +_08019D24:\n\ + ldr r7, _08019D54 @ =gBattleMons\n\ + adds r1, r0, 0\n\ + movs r5, 0x58\n\ + ldr r2, _08019D58 @ =gLastUsedAbility\n\ +_08019D2C:\n\ + adds r0, r4, 0\n\ + muls r0, r5\n\ + adds r0, r7\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + adds r3, r4, 0x1\n\ + cmp r0, r6\n\ + bne _08019D48\n\ + cmp r4, r10\n\ + beq _08019D48\n\ + strb r6, [r2]\n\ + lsls r0, r3, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019D48:\n\ + adds r4, r3, 0\n\ + cmp r4, r1\n\ + blt _08019D2C\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019D50: .4byte gNoOfAllBanks\n\ +_08019D54: .4byte gBattleMons\n\ +_08019D58: .4byte gLastUsedAbility\n\ +_08019D5C:\n\ + mov r0, r10\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + movs r4, 0\n\ + ldr r0, _08019DAC @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019D72\n\ + b _08019F76\n\ +_08019D72:\n\ + ldr r7, _08019DB0 @ =gBattleMons\n\ +_08019D74:\n\ + lsls r0, r4, 24\n\ + lsrs r0, 24\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, r5\n\ + beq _08019DA0\n\ + movs r0, 0x58\n\ + muls r0, r4\n\ + adds r0, r7\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, r6\n\ + bne _08019DA0\n\ + ldr r0, _08019DB4 @ =gLastUsedAbility\n\ + strb r6, [r0]\n\ + mov r0, r9\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019DA0:\n\ + adds r4, 0x1\n\ + ldr r0, _08019DAC @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019D74\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019DAC: .4byte gNoOfAllBanks\n\ +_08019DB0: .4byte gBattleMons\n\ +_08019DB4: .4byte gLastUsedAbility\n\ +_08019DB8:\n\ + mov r0, r10\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + movs r4, 0\n\ + ldr r0, _08019E08 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019DCE\n\ + b _08019F76\n\ +_08019DCE:\n\ + ldr r7, _08019E0C @ =gBattleMons\n\ +_08019DD0:\n\ + lsls r0, r4, 24\n\ + lsrs r0, 24\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, r5\n\ + bne _08019DFC\n\ + movs r0, 0x58\n\ + muls r0, r4\n\ + adds r0, r7\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, r6\n\ + bne _08019DFC\n\ + ldr r0, _08019E10 @ =gLastUsedAbility\n\ + strb r6, [r0]\n\ + mov r0, r9\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019DFC:\n\ + adds r4, 0x1\n\ + ldr r0, _08019E08 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + blt _08019DD0\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019E08: .4byte gNoOfAllBanks\n\ +_08019E0C: .4byte gBattleMons\n\ +_08019E10: .4byte gLastUsedAbility\n\ +_08019E14:\n\ + ldr r0, _08019E30 @ =BattleScript_CastformChange\n\ + bl b_push_move_exec\n\ + ldr r0, _08019E34 @ =0x02000000\n\ + ldr r2, _08019E38 @ =0x00016003\n\ + adds r1, r0, r2\n\ + strb r6, [r1]\n\ + mov r1, r9\n\ + subs r1, 0x1\n\ + ldr r3, _08019E3C @ =0x0001609b\n\ + adds r0, r3\n\ + strb r1, [r0]\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019E30: .4byte BattleScript_CastformChange\n\ +_08019E34: .4byte 0x02000000\n\ +_08019E38: .4byte 0x00016003\n\ +_08019E3C: .4byte 0x0001609b\n\ +_08019E40:\n\ + ldr r0, _08019E5C @ =BattleScript_CastformChange\n\ + bl b_push_move_exec\n\ + ldr r0, _08019E60 @ =0x02000000\n\ + ldr r5, _08019E64 @ =0x00016003\n\ + adds r1, r0, r5\n\ + mov r2, r10\n\ + strb r2, [r1]\n\ + mov r1, r9\n\ + subs r1, 0x1\n\ + ldr r3, _08019E68 @ =0x0001609b\n\ + adds r0, r3\n\ + strb r1, [r0]\n\ + b _08019F92\n\ + .align 2, 0\n\ +_08019E5C: .4byte BattleScript_CastformChange\n\ +_08019E60: .4byte 0x02000000\n\ +_08019E64: .4byte 0x00016003\n\ +_08019E68: .4byte 0x0001609b\n\ +_08019E6C:\n\ + mov r5, r8\n\ + strb r1, [r5]\n\ + ldr r0, [r2]\n\ + ldr r1, _08019E80 @ =0xfff7ffff\n\ + ands r0, r1\n\ + str r0, [r2]\n\ + ldr r0, _08019E84 @ =gUnknown_081D978C\n\ + bl b_push_move_exec\n\ + b _08019F1A\n\ + .align 2, 0\n\ +_08019E80: .4byte 0xfff7ffff\n\ +_08019E84: .4byte gUnknown_081D978C\n\ +_08019E88:\n\ + ldr r0, _08019EDC @ =BattleScript_TraceActivates\n\ + bl b_push_move_exec\n\ + ldr r1, _08019EE0 @ =gStatuses3\n\ + ldr r2, [sp, 0x18]\n\ + adds r1, r2, r1\n\ + ldr r0, [r1]\n\ + ldr r2, _08019EE4 @ =0xffefffff\n\ + ands r0, r2\n\ + str r0, [r1]\n\ + ldr r0, _08019EE8 @ =0x02000000\n\ + ldr r3, _08019EEC @ =0x00016003\n\ + adds r0, r3\n\ + strb r4, [r0]\n\ + ldr r1, _08019EF0 @ =gBattleTextBuff1\n\ + movs r4, 0xFD\n\ + strb r4, [r1]\n\ + movs r0, 0x4\n\ + strb r0, [r1, 0x1]\n\ + ldr r2, _08019EF4 @ =gActiveBank\n\ + ldrb r0, [r2]\n\ + strb r0, [r1, 0x2]\n\ + ldr r3, _08019EF8 @ =gBattlePartyID\n\ + ldrb r0, [r2]\n\ + lsls r0, 1\n\ + adds r0, r3\n\ + ldrh r0, [r0]\n\ + strb r0, [r1, 0x3]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x4]\n\ + ldr r1, _08019EFC @ =gBattleTextBuff2\n\ + strb r4, [r1]\n\ + movs r0, 0x9\n\ + strb r0, [r1, 0x1]\n\ + ldr r0, _08019F00 @ =gLastUsedAbility\n\ + ldrb r0, [r0]\n\ + strb r0, [r1, 0x2]\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + strb r0, [r1, 0x3]\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019EDC: .4byte BattleScript_TraceActivates\n\ +_08019EE0: .4byte gStatuses3\n\ +_08019EE4: .4byte 0xffefffff\n\ +_08019EE8: .4byte 0x02000000\n\ +_08019EEC: .4byte 0x00016003\n\ +_08019EF0: .4byte gBattleTextBuff1\n\ +_08019EF4: .4byte gActiveBank\n\ +_08019EF8: .4byte gBattlePartyID\n\ +_08019EFC: .4byte gBattleTextBuff2\n\ +_08019F00: .4byte gLastUsedAbility\n\ +_08019F04:\n\ + mov r5, r8\n\ + strb r1, [r5]\n\ + ldr r0, [r2]\n\ + ldr r1, _08019F30 @ =0xfff7ffff\n\ + ands r0, r1\n\ + str r0, [r2]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08019F34 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08019F38 @ =gUnknown_081D9795\n\ + str r0, [r1]\n\ +_08019F1A:\n\ + ldr r0, _08019F3C @ =0x02000000\n\ + ldr r1, _08019F40 @ =0x000160dd\n\ + adds r0, r1\n\ + strb r4, [r0]\n\ +_08019F22:\n\ + mov r0, r9\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ + b _08019F76\n\ + .align 2, 0\n\ +_08019F30: .4byte 0xfff7ffff\n\ +_08019F34: .4byte gBattlescriptCurrInstr\n\ +_08019F38: .4byte gUnknown_081D9795\n\ +_08019F3C: .4byte 0x02000000\n\ +_08019F40: .4byte 0x000160dd\n\ +_08019F44:\n\ + movs r4, 0\n\ + ldr r0, _08019FA4 @ =gNoOfAllBanks\n\ + ldrb r1, [r0]\n\ + cmp r4, r1\n\ + bge _08019F76\n\ + ldr r0, _08019FA8 @ =gBattleMons\n\ + adds r2, r1, 0\n\ + adds r1, r0, 0\n\ + adds r1, 0x20\n\ + ldr r3, _08019FAC @ =gLastUsedAbility\n\ +_08019F58:\n\ + ldrb r0, [r1]\n\ + cmp r0, r6\n\ + bne _08019F6E\n\ + cmp r4, r10\n\ + beq _08019F6E\n\ + strb r6, [r3]\n\ + mov r0, r9\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08019F6E:\n\ + adds r1, 0x58\n\ + adds r4, 0x1\n\ + cmp r4, r2\n\ + blt _08019F58\n\ +_08019F76:\n\ + mov r2, r9\n\ + cmp r2, 0\n\ + beq _08019F92\n\ +_08019F7C:\n\ + ldr r3, [sp, 0x4]\n\ + cmp r3, 0xB\n\ + bhi _08019F92\n\ + ldr r1, _08019FAC @ =gLastUsedAbility\n\ + ldrb r0, [r1]\n\ + cmp r0, 0xFF\n\ + beq _08019F92\n\ + adds r1, r0, 0\n\ + mov r0, r10\n\ + bl RecordAbilityBattle\n\ +_08019F92:\n\ + mov r0, r9\n\ + add sp, 0x28\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .align 2, 0\n\ +_08019FA4: .4byte gNoOfAllBanks\n\ +_08019FA8: .4byte gBattleMons\n\ +_08019FAC: .4byte gLastUsedAbility\n\ + .syntax divided"); +} + +#endif // NONMATCHING + +void b_call_bc_move_exec(u8* BS_ptr) +{ + gBattlescriptCurrInstr = BS_ptr; + B_FUNCTION_STACK->ptr[B_FUNCTION_STACK->size++] = gBattleMainFunc; + gBattleMainFunc = sub_8013F54; + gFightStateTracker = 0; +} + +void b_push_move_exec(u8* BS_ptr) +{ + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BS_ptr; + B_FUNCTION_STACK->ptr[B_FUNCTION_STACK->size++] = gBattleMainFunc; + gBattleMainFunc = sub_8013FBC; +} + +enum +{ + ITEM_NO_EFFECT, // 0 + ITEM_STATUS_CHANGE, // 1 + ITEM_EFFECT_OTHER, // 2 + ITEM_PP_CHANGE, // 3 + ITEM_HP_CHANGE, // 4 + ITEM_STATS_CHANGE, // 5 +}; + +enum +{ + FLAVOR_SPICY, // 0 + FLAVOR_DRY, // 1 + FLAVOR_SWEET, // 2 + FLAVOR_BITTER, // 3 + FLAVOR_SOUR, // 4 +}; + +u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn) +{ + int i = 0; + u8 effect = ITEM_NO_EFFECT; + u8 changedPP = 0; + u8 bankHoldEffect, atkHoldEffect, defHoldEffect; + u8 bankQuality, atkQuality, defQuality; + u16 atkItem, defItem; + + gLastUsedItem = gBattleMons[bank].item; + if (gLastUsedItem == ITEM_ENIGMA_BERRY) + { + bankHoldEffect = gEnigmaBerries[bank].holdEffect; + bankQuality = gEnigmaBerries[bank].holdEffectParam; + } + else + { + bankHoldEffect = ItemId_GetHoldEffect(gLastUsedItem); + bankQuality = ItemId_GetHoldEffectParam(gLastUsedItem); + } + + atkItem = gBattleMons[gBankAttacker].item; + if (atkItem == ITEM_ENIGMA_BERRY) + { + atkHoldEffect = gEnigmaBerries[gBankAttacker].holdEffect; + atkQuality = gEnigmaBerries[gBankAttacker].holdEffectParam; + } + else + { + atkHoldEffect = ItemId_GetHoldEffect(atkItem); + atkQuality = ItemId_GetHoldEffectParam(atkItem); + } + + // def variables are unused + defItem = gBattleMons[gBankTarget].item; + if (defItem == ITEM_ENIGMA_BERRY) + { + defHoldEffect = gEnigmaBerries[gBankTarget].holdEffect; + defQuality = gEnigmaBerries[gBankTarget].holdEffectParam; + } + else + { + defHoldEffect = ItemId_GetHoldEffect(defItem); + defQuality = ItemId_GetHoldEffectParam(defItem); + } + + switch (caseID) + { + case 0: + switch (bankHoldEffect) + { + case HOLD_EFFECT_DOUBLE_PRIZE: + BATTLE_STRUCT->moneyMultiplier = 2; + break; + case HOLD_EFFECT_RESTORE_STATS: + for (i = 0; i < 8; i++) + { + if (gBattleMons[bank].statStages[i] < 6) + { + gBattleMons[bank].statStages[i] = 6; + effect = ITEM_STATS_CHANGE; + } + } + if (effect) + { + BATTLE_STRUCT->scriptingActive = bank; + gStringBank = bank; + gActiveBank = gBankAttacker = bank; + b_call_bc_move_exec(BattleScript_WhiteHerbEnd2); + } + break; + } + break; + case 1: + if (gBattleMons[bank].hp) + { + switch (bankHoldEffect) + { + case HOLD_EFFECT_RESTORE_HP: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn) + { + gBattleMoveDamage = bankQuality; + if (gBattleMons[bank].hp + bankQuality > gBattleMons[bank].maxHP) + gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp; + gBattleMoveDamage *= -1; + b_call_bc_move_exec(BattleScript_ItemHealHP_RemoveItem); + effect = 4; + } + break; + case HOLD_EFFECT_RESTORE_PP: + if (!moveTurn) + { + struct Pokemon* poke; + u8 ppBonuses; + u16 move; + + if (GetBankSide(bank) == 0) + poke = &gPlayerParty[gBattlePartyID[bank]]; + else + poke = &gEnemyParty[gBattlePartyID[bank]]; + for (i = 0; i < 4; i++) + { + move = GetMonData(poke, MON_DATA_MOVE1 + i); + changedPP = GetMonData(poke, MON_DATA_PP1 + i); + ppBonuses = GetMonData(poke, MON_DATA_PP_BONUSES); + if (move && changedPP == 0) + break; + } + if (i != 4) + { + u8 maxPP = CalculatePPWithBonus(move, ppBonuses, i); + if (changedPP + bankQuality > maxPP) + changedPP = maxPP; + else + changedPP = changedPP + bankQuality; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = move; + gBattleTextBuff1[3] = move >> 8; + gBattleTextBuff1[4] = 0xFF; + b_call_bc_move_exec(BattleScript_BerryPPHealEnd2); + EmitSetAttributes(0, i + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP); + MarkBufferBankForExecution(gActiveBank); + effect = ITEM_PP_CHANGE; + } + } + break; + case HOLD_EFFECT_RESTORE_STATS: + for (i = 0; i < 8; i++) + { + if (gBattleMons[bank].statStages[i] < 6) + { + gBattleMons[bank].statStages[i] = 6; + effect = ITEM_STATS_CHANGE; + } + } + if (effect) + { + BATTLE_STRUCT->scriptingActive = bank; + gStringBank = bank; + gActiveBank = gBankAttacker = bank; + b_call_bc_move_exec(BattleScript_WhiteHerbEnd2); + } + break; + case HOLD_EFFECT_LEFTOVERS: + if (gBattleMons[bank].hp < gBattleMons[bank].maxHP && !moveTurn) + { + gBattleMoveDamage = gBattleMons[bank].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP) + gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp; + gBattleMoveDamage *= -1; + b_call_bc_move_exec(BattleScript_ItemHealHP_End2); + effect = ITEM_HP_CHANGE; + RecordItemBattle(bank, bankHoldEffect); + } + break; + // nice copy/paste there gamefreak, making a function for confuse berries was too much eh? + case HOLD_EFFECT_CONFUSE_SPICY: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 8; + gBattleTextBuff1[2] = FLAVOR_SPICY; + gBattleTextBuff1[3] = EOS; + gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP) + gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp; + gBattleMoveDamage *= -1; + if (GetPokeFlavourRelation(gBattleMons[bank].personality, FLAVOR_SPICY) < 0) + b_call_bc_move_exec(BattleScript_BerryConfuseHealEnd2); + else + b_call_bc_move_exec(BattleScript_ItemHealHP_RemoveItem); + effect = ITEM_HP_CHANGE; + } + break; + case HOLD_EFFECT_CONFUSE_DRY: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 8; + gBattleTextBuff1[2] = FLAVOR_DRY; + gBattleTextBuff1[3] = EOS; + gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP) + gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp; + gBattleMoveDamage *= -1; + if (GetPokeFlavourRelation(gBattleMons[bank].personality, FLAVOR_DRY) < 0) + b_call_bc_move_exec(BattleScript_BerryConfuseHealEnd2); + else + b_call_bc_move_exec(BattleScript_ItemHealHP_RemoveItem); + effect = ITEM_HP_CHANGE; + } + break; + case HOLD_EFFECT_CONFUSE_SWEET: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 8; + gBattleTextBuff1[2] = FLAVOR_SWEET; + gBattleTextBuff1[3] = EOS; + gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP) + gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp; + gBattleMoveDamage *= -1; + if (GetPokeFlavourRelation(gBattleMons[bank].personality, FLAVOR_SWEET) < 0) + b_call_bc_move_exec(BattleScript_BerryConfuseHealEnd2); + else + b_call_bc_move_exec(BattleScript_ItemHealHP_RemoveItem); + effect = ITEM_HP_CHANGE; + } + break; + case HOLD_EFFECT_CONFUSE_BITTER: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 8; + gBattleTextBuff1[2] = FLAVOR_BITTER; + gBattleTextBuff1[3] = EOS; + gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP) + gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp; + gBattleMoveDamage *= -1; + if (GetPokeFlavourRelation(gBattleMons[bank].personality, FLAVOR_BITTER) < 0) + b_call_bc_move_exec(BattleScript_BerryConfuseHealEnd2); + else + b_call_bc_move_exec(BattleScript_ItemHealHP_RemoveItem); + effect = ITEM_HP_CHANGE; + } + break; + case HOLD_EFFECT_CONFUSE_SOUR: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 8; + gBattleTextBuff1[2] = FLAVOR_SOUR; + gBattleTextBuff1[3] = EOS; + gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP) + gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp; + gBattleMoveDamage *= -1; + if (GetPokeFlavourRelation(gBattleMons[bank].personality, FLAVOR_SOUR) < 0) + b_call_bc_move_exec(BattleScript_BerryConfuseHealEnd2); + else + b_call_bc_move_exec(BattleScript_ItemHealHP_RemoveItem); + effect = ITEM_HP_CHANGE; + } + break; + // copy/paste again, smh + case HOLD_EFFECT_ATTACK_UP: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_ATK] < 0xC) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 5; + gBattleTextBuff1[2] = STAT_STAGE_ATK; + gBattleTextBuff1[3] = EOS; + + gBattleTextBuff2[0] = 0xFD; + gBattleTextBuff2[1] = 0; + gBattleTextBuff2[2] = 0xD2; + gBattleTextBuff2[3] = 0xD2 >> 8; + gBattleTextBuff2[4] = EOS; + + gEffectBank = bank; + BATTLE_STRUCT->statChanger = 0x10 + STAT_STAGE_ATK; + BATTLE_STRUCT->animArg1 = 0xE + STAT_STAGE_ATK; + BATTLE_STRUCT->animArg2 = 0; + b_call_bc_move_exec(BattleScript_BerryStatRaiseEnd2); + effect = ITEM_STATS_CHANGE; + } + break; + case HOLD_EFFECT_DEFENSE_UP: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_DEF] < 0xC) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 5; + gBattleTextBuff1[2] = STAT_STAGE_DEF; + gBattleTextBuff1[3] = EOS; + + gEffectBank = bank; + BATTLE_STRUCT->statChanger = 0x10 + STAT_STAGE_DEF; + BATTLE_STRUCT->animArg1 = 0xE + STAT_STAGE_DEF; + BATTLE_STRUCT->animArg2 = 0; + b_call_bc_move_exec(BattleScript_BerryStatRaiseEnd2); + effect = ITEM_STATS_CHANGE; + } + break; + case HOLD_EFFECT_SPEED_UP: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_SPEED] < 0xC) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 5; + gBattleTextBuff1[2] = STAT_STAGE_SPEED; + gBattleTextBuff1[3] = EOS; + + gEffectBank = bank; + BATTLE_STRUCT->statChanger = 0x10 + STAT_STAGE_SPEED; + BATTLE_STRUCT->animArg1 = 0xE + STAT_STAGE_SPEED; + BATTLE_STRUCT->animArg2 = 0; + b_call_bc_move_exec(BattleScript_BerryStatRaiseEnd2); + effect = ITEM_STATS_CHANGE; + } + break; + case HOLD_EFFECT_SP_ATTACK_UP: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_SPATK] < 0xC) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 5; + gBattleTextBuff1[2] = STAT_STAGE_SPATK; + gBattleTextBuff1[3] = EOS; + + gEffectBank = bank; + BATTLE_STRUCT->statChanger = 0x10 + STAT_STAGE_SPATK; + BATTLE_STRUCT->animArg1 = 0xE + STAT_STAGE_SPATK; + BATTLE_STRUCT->animArg2 = 0; + b_call_bc_move_exec(BattleScript_BerryStatRaiseEnd2); + effect = ITEM_STATS_CHANGE; + } + break; + case HOLD_EFFECT_SP_DEFENSE_UP: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_SPDEF] < 0xC) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 5; + gBattleTextBuff1[2] = STAT_STAGE_SPDEF; + gBattleTextBuff1[3] = EOS; + + gEffectBank = bank; + BATTLE_STRUCT->statChanger = 0x10 + STAT_STAGE_SPDEF; + BATTLE_STRUCT->animArg1 = 0xE + STAT_STAGE_SPDEF; + BATTLE_STRUCT->animArg2 = 0; + b_call_bc_move_exec(BattleScript_BerryStatRaiseEnd2); + effect = ITEM_STATS_CHANGE; + } + break; + case HOLD_EFFECT_CRITICAL_UP: + if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && !(gBattleMons[bank].status2 & STATUS2_FOCUS_ENERGY)) + { + gBattleMons[bank].status2 |= STATUS2_FOCUS_ENERGY; + b_call_bc_move_exec(BattleScript_BerryFocusEnergyEnd2); + effect = ITEM_EFFECT_OTHER; + } + break; + case HOLD_EFFECT_RANDOM_STAT_UP: + if (!moveTurn && gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality) + { + for (i = 0; i < 5; i++) + { + if (gBattleMons[bank].statStages[STAT_STAGE_ATK + i] < 0xC) + break; + } + if (i != 5) + { + do + { + i = Random() % 5; + } while (gBattleMons[bank].statStages[STAT_STAGE_ATK + i] == 0xC); + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 5; + gBattleTextBuff1[2] = i + 1; + gBattleTextBuff1[3] = EOS; + + gBattleTextBuff2[0] = 0xFD; + gBattleTextBuff2[1] = 0; + gBattleTextBuff2[2] = 0xD1; + gBattleTextBuff2[3] = 0xD1 >> 8; + gBattleTextBuff2[4] = 0; + gBattleTextBuff2[5] = 0xD2; + gBattleTextBuff2[6] = 0xD2 >> 8; + gBattleTextBuff2[7] = EOS; + + gEffectBank = bank; + BATTLE_STRUCT->statChanger = 0x21 + i; + BATTLE_STRUCT->animArg1 = 0x21 + i + 6; + BATTLE_STRUCT->animArg2 = 0; + b_call_bc_move_exec(BattleScript_BerryStatRaiseEnd2); + effect = ITEM_STATS_CHANGE; + } + } + break; + case HOLD_EFFECT_CURE_PAR: + if (gBattleMons[bank].status1 & STATUS_PARALYSIS) + { + gBattleMons[bank].status1 &= ~(STATUS_PARALYSIS); + b_call_bc_move_exec(BattleScript_BerryCurePrlzEnd2); + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_PSN: + if (gBattleMons[bank].status1 & STATUS_PSN_ANY) + { + gBattleMons[bank].status1 &= ~(STATUS_PSN_ANY | STATUS_TOXIC_COUNTER); + b_call_bc_move_exec(BattleScript_BerryCurePsnEnd2); + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_BRN: + if (gBattleMons[bank].status1 & STATUS_BURN) + { + gBattleMons[bank].status1 &= ~(STATUS_BURN); + b_call_bc_move_exec(BattleScript_BerryCureBrnEnd2); + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_FRZ: + if (gBattleMons[bank].status1 & STATUS_FREEZE) + { + gBattleMons[bank].status1 &= ~(STATUS_FREEZE); + b_call_bc_move_exec(BattleScript_BerryCureFrzEnd2); + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_SLP: + if (gBattleMons[bank].status1 & STATUS_SLEEP) + { + gBattleMons[bank].status1 &= ~(STATUS_SLEEP); + gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE); + b_call_bc_move_exec(BattleScript_BerryCureSlpEnd2); + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_CONFUSION: + if (gBattleMons[bank].status2 & STATUS2_CONFUSION) + { + gBattleMons[bank].status2 &= ~(STATUS2_CONFUSION); + b_call_bc_move_exec(BattleScript_BerryCureConfusionEnd2); + effect = ITEM_EFFECT_OTHER; + } + break; + case HOLD_EFFECT_CURE_STATUS: + if (gBattleMons[bank].status1 & STATUS_ANY || gBattleMons[bank].status2 & STATUS2_CONFUSION) + { + i = 0; + if (gBattleMons[bank].status1 & STATUS_PSN_ANY) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); + i++; + } + if (gBattleMons[bank].status1 & STATUS_SLEEP) + { + gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE); + StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); + i++; + } + if (gBattleMons[bank].status1 & STATUS_PARALYSIS) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); + i++; + } + if (gBattleMons[bank].status1 & STATUS_BURN) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); + i++; + } + if (gBattleMons[bank].status1 & STATUS_FREEZE) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); + i++; + } + if (gBattleMons[bank].status2 & STATUS2_CONFUSION) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); + i++; + } + if (!(i > 1)) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBattleMons[bank].status1 = 0; + gBattleMons[bank].status2 &= ~(STATUS2_CONFUSION); + b_call_bc_move_exec(gUnknown_081D9A44); + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_ATTRACT: + if (gBattleMons[bank].status2 & STATUS2_INFATUATION) + { + gBattleMons[bank].status2 &= ~(STATUS2_INFATUATION); + StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); + b_call_bc_move_exec(gUnknown_081D9A44); + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + effect = ITEM_EFFECT_OTHER; + } + break; + } + if (effect) + { + BATTLE_STRUCT->scriptingActive = bank; + gStringBank = bank; + gActiveBank = gBankAttacker = bank; + switch (effect) + { + case ITEM_STATUS_CHANGE: + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[bank].status1); + MarkBufferBankForExecution(gActiveBank); + break; + case ITEM_PP_CHANGE: + if (!(gBattleMons[bank].status2 & STATUS2_TRANSFORMED) && !(gDisableStructs[bank].unk18_b & gBitTable[i])) + gBattleMons[bank].pp[i] = changedPP; + break; + } + } + } + break; + case 2: + break; + case 3: + for (bank = 0; bank < gNoOfAllBanks; bank++) + { + gLastUsedItem = gBattleMons[bank].item; + if (gBattleMons[bank].item == ITEM_ENIGMA_BERRY) + { + bankHoldEffect = gEnigmaBerries[bank].holdEffect; + bankQuality = gEnigmaBerries[bank].holdEffectParam; + } + else + { + bankHoldEffect = ItemId_GetHoldEffect(gLastUsedItem); + bankQuality = ItemId_GetHoldEffectParam(gLastUsedItem); + } + switch (bankHoldEffect) + { + case HOLD_EFFECT_CURE_PAR: + if (gBattleMons[bank].status1 & STATUS_PARALYSIS) + { + gBattleMons[bank].status1 &= ~(STATUS_PARALYSIS); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_BerryCureParRet; + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_PSN: + if (gBattleMons[bank].status1 & STATUS_PSN_ANY) + { + gBattleMons[bank].status1 &= ~(STATUS_PSN_ANY | STATUS_TOXIC_COUNTER); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_BerryCurePsnRet; + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_BRN: + if (gBattleMons[bank].status1 & STATUS_BURN) + { + gBattleMons[bank].status1 &= ~(STATUS_BURN); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_BerryCureBrnRet; + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_FRZ: + if (gBattleMons[bank].status1 & STATUS_FREEZE) + { + gBattleMons[bank].status1 &= ~(STATUS_FREEZE); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_BerryCureFrzRet; + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_SLP: + if (gBattleMons[bank].status1 & STATUS_SLEEP) + { + gBattleMons[bank].status1 &= ~(STATUS_SLEEP); + gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_BerryCureSlpRet; + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_CURE_CONFUSION: + if (gBattleMons[bank].status2 & STATUS2_CONFUSION) + { + gBattleMons[bank].status2 &= ~(STATUS2_CONFUSION); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_BerryCureConfusionRet; + effect = ITEM_EFFECT_OTHER; + } + break; + case HOLD_EFFECT_CURE_ATTRACT: + if (gBattleMons[bank].status2 & STATUS2_INFATUATION) + { + gBattleMons[bank].status2 &= ~(STATUS2_INFATUATION); + StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); + b_movescr_stack_push_cursor(); + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattlescriptCurrInstr = gUnknown_081D9A4A; + effect = ITEM_EFFECT_OTHER; + } + break; + case HOLD_EFFECT_CURE_STATUS: + if (gBattleMons[bank].status1 & STATUS_ANY || gBattleMons[bank].status2 & STATUS2_CONFUSION) + { + if (gBattleMons[bank].status1 & STATUS_PSN_ANY) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); + } + if (gBattleMons[bank].status1 & STATUS_SLEEP) + { + gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE); + StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); + } + if (gBattleMons[bank].status1 & STATUS_PARALYSIS) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); + } + if (gBattleMons[bank].status1 & STATUS_BURN) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); + } + if (gBattleMons[bank].status1 & STATUS_FREEZE) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); + } + if (gBattleMons[bank].status2 & STATUS2_CONFUSION) + { + StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); + } + gBattleMons[bank].status1 = 0; + gBattleMons[bank].status2 &= ~(STATUS2_CONFUSION); + b_movescr_stack_push_cursor(); + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattlescriptCurrInstr = gUnknown_081D9A4A; + effect = ITEM_STATUS_CHANGE; + } + break; + case HOLD_EFFECT_RESTORE_STATS: + for (i = 0; i < 8; i++) + { + if (gBattleMons[bank].statStages[i] < 6) + { + gBattleMons[bank].statStages[i] = 6; + effect = ITEM_STATS_CHANGE; + } + } + if (effect) + { + BATTLE_STRUCT->scriptingActive = bank; + gStringBank = bank; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_WhiteHerbRet; + return effect; // unnecessary return + } + break; + } + if (effect) + { + BATTLE_STRUCT->scriptingActive = bank; + gStringBank = bank; + gActiveBank = bank; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + break; + } + } + break; + case 4: + if (gBattleMoveDamage) + { + switch (atkHoldEffect) + { + case HOLD_EFFECT_FLINCH: + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special) + && (Random() % 100) < bankQuality + && gBattleMoves[gCurrentMove].flags & FLAG_KINGSROCK_AFFECTED + && gBattleMons[gBankTarget].hp) + { + gBattleCommunication[MOVE_EFFECT_BYTE] = 8; + b_movescr_stack_push_cursor(); + SetMoveEffect(0, 0); + b_movescr_stack_pop_cursor(); + } + break; + case HOLD_EFFECT_SHELL_BELL: + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) + && gSpecialStatuses[gBankTarget].moveturnLostHP != 0 + && gSpecialStatuses[gBankTarget].moveturnLostHP != 0xFFFF + && gBankAttacker != gBankTarget + && gBattleMons[gBankAttacker].hp != gBattleMons[gBankAttacker].maxHP + && gBattleMons[gBankAttacker].hp != 0) + { + gLastUsedItem = atkItem; + gStringBank = gBankAttacker; + BATTLE_STRUCT->scriptingActive = gBankAttacker; + gBattleMoveDamage = (gSpecialStatuses[gBankTarget].moveturnLostHP / atkQuality) * -1; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = -1; + gSpecialStatuses[gBankTarget].moveturnLostHP = 0; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret; + effect++; + } + break; + } + } + break; + } + + return effect; +} + +struct CombinedMove +{ + u16 move1; + u16 move2; + u16 newMove; +}; + +static const struct CombinedMove sCombinedMoves[2] = +{ + {MOVE_EMBER, MOVE_GUST, MOVE_HEAT_WAVE}, + {0xFFFF, 0xFFFF, 0xFFFF} +}; + +void unref_sub_801B40C(void) +{ + int i = 0; + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + do + { + u8 bank = 0; + do + { + u8 absent = gAbsentBankFlags; + if (gBitTable[bank] & absent || absent & gBitTable[bank + 2]) + bank++; + else + { + if (sCombinedMoves[i].move1 == gChosenMovesByBanks[bank] && sCombinedMoves[i].move2 == gChosenMovesByBanks[bank + 2]) + { + gSideTimer[GetBankIdentity(bank) & 1].field3 = (bank) | ((bank + 2) << 4); + gSideTimer[GetBankIdentity(bank) & 1].field4 = sCombinedMoves[i].newMove; + gSideAffecting[GetBankIdentity(bank) & 1] |= SIDE_STATUS_X4; + } + if (sCombinedMoves[i].move1 == gChosenMovesByBanks[bank + 2] && sCombinedMoves[i].move2 == gChosenMovesByBanks[bank]) + { + gSideTimer[GetBankIdentity(bank) & 1].field3 = (bank + 2) | ((bank) << 4); + gSideTimer[GetBankIdentity(bank) & 1].field4 = sCombinedMoves[i].newMove; + gSideAffecting[GetBankIdentity(bank) & 1] |= SIDE_STATUS_X4; + } + bank++; + } + } while (bank < 2); + i++; + } while (sCombinedMoves[i].move1 != 0xFFFF); + } +} + +void sub_801B594(void) +{ + if (gBattleExecBuffer == 0) + gBattleScriptingCommandsTable[*gBattlescriptCurrInstr](); +} + +u8 GetMoveTarget(u16 move, u8 useMoveTarget) //get move target +{ + u8 targetBank = 0; + u8 moveTarget; + u8 side; + + if (useMoveTarget) + moveTarget = useMoveTarget - 1; + else + moveTarget = gBattleMoves[move].target; + + switch (moveTarget) + { + case 0: + side = GetBankSide(gBankAttacker) ^ 1; + if (gSideTimer[side].followmeTimer && gBattleMons[gSideTimer[side].followmeTarget].hp) + targetBank = gSideTimer[side].followmeTarget; + else + { + side = GetBankSide(gBankAttacker); + do + { + targetBank = Random() % gNoOfAllBanks; + } while (targetBank == gBankAttacker || side == GetBankSide(targetBank) || gAbsentBankFlags & gBitTable[targetBank]); + if (gBattleMoves[move].type == TYPE_ELECTRIC + && AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIZE, gBankAttacker, ABILITY_LIGHTNING_ROD, 0, 0) + && gBattleMons[targetBank].ability != ABILITY_LIGHTNING_ROD) + { + targetBank ^= 2; + RecordAbilityBattle(targetBank, gBattleMons[targetBank].ability); + gSpecialStatuses[targetBank].lightningRodRedirected = 1; + } + } + break; + case 1: + case 8: + case 32: + case 64: + targetBank = GetBankByPlayerAI((GetBankIdentity(gBankAttacker) & 1) ^ 1); + if (gAbsentBankFlags & gBitTable[targetBank]) + targetBank ^= 2; + break; + case 4: + side = GetBankSide(gBankAttacker) ^ 1; + if (gSideTimer[side].followmeTimer && gBattleMons[gSideTimer[side].followmeTarget].hp) + targetBank = gSideTimer[side].followmeTarget; + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & 4) + { + if (GetBankSide(gBankAttacker) == 0) + { + if (Random() & 1) + targetBank = GetBankByPlayerAI(1); + else + targetBank = GetBankByPlayerAI(3); + } + else + { + if (Random() & 1) + targetBank = GetBankByPlayerAI(0); + else + targetBank = GetBankByPlayerAI(2); + } + if (gAbsentBankFlags & gBitTable[targetBank]) + targetBank ^= 2; + } + else + targetBank = GetBankByPlayerAI((GetBankIdentity(gBankAttacker) & 1) ^ 1); + break; + case 2: + case 16: + targetBank = gBankAttacker; + break; + } + ewram[gBankAttacker + 0x16010] = targetBank; + return targetBank; +} + +u8 IsPokeDisobedient(void) +{ + u8 obedienceLevel; + s32 rnd; + s32 calc; + + if (gBattleTypeFlags & BATTLE_TYPE_LINK + || GetBankSide(gBankAttacker) == 1 + || !IsOtherTrainer(gBattleMons[gBankAttacker].otId, gBattleMons[gBankAttacker].otName) + || FlagGet(BADGE08_GET)) + return 0; + + obedienceLevel = 10; + if (FlagGet(BADGE02_GET)) + obedienceLevel = 30; + if (FlagGet(BADGE04_GET)) + obedienceLevel = 50; + if (FlagGet(BADGE06_GET)) + obedienceLevel = 70; + + if (gBattleMons[gBankAttacker].level <= obedienceLevel) + return 0; + rnd = (Random() & 255); + calc = (gBattleMons[gBankAttacker].level + obedienceLevel) * rnd >> 8; + if (calc < obedienceLevel) + return 0; + + // is not obedient + if (gCurrentMove == MOVE_RAGE) + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_RAGE); + if (gBattleMons[gBankAttacker].status1 & STATUS_SLEEP && (gCurrentMove == MOVE_SNORE || gCurrentMove == MOVE_SLEEP_TALK)) + { + gBattlescriptCurrInstr = gUnknown_081D995F; + return 1; + } + + rnd = (Random() & 255); + calc = (gBattleMons[gBankAttacker].level + obedienceLevel) * rnd >> 8; + if (calc < obedienceLevel) + { + calc = CheckMoveLimitations(gBankAttacker, gBitTable[gCurrMovePos], 0xFF); + if (calc == 0xF) // all moves cannot be used + { + gBattleCommunication[MULTISTRING_CHOOSER] = Random() & 3; + gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; + return 1; + } + else // use a random move + { + do + { + gCurrMovePos = gUnknown_02024BE5 = Random() & 3; + } while (gBitTable[gCurrMovePos] & calc); + gRandomMove = gBattleMons[gBankAttacker].moves[gCurrMovePos]; + gBattleCommunication[3] = 0; + gDynamicBasePower = 0; + BATTLE_STRUCT->dynamicMoveType = 0; + gBattlescriptCurrInstr = gUnknown_081D996F; + gBankTarget = GetMoveTarget(gRandomMove, 0); + gHitMarker |= HITMARKER_x200000; + return 2; + } + } + else + { + obedienceLevel = gBattleMons[gBankAttacker].level - obedienceLevel; + + calc = (Random() & 255); + if (calc < obedienceLevel && !(gBattleMons[gBankAttacker].status1 & STATUS_ANY) && gBattleMons[gBankAttacker].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gBankAttacker].ability != ABILITY_INSOMNIA) + { + // try putting asleep + int i; + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleMons[i].status2 & STATUS2_UPROAR) + break; + } + if (i == gNoOfAllBanks) + { + gBattlescriptCurrInstr = gUnknown_081D9989; + return 1; + } + } + calc -= obedienceLevel; + if (calc < obedienceLevel) + { + gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankAttacker], MOVE_POUND, 0, 40, 0, gBankAttacker, gBankAttacker); + gBankTarget = gBankAttacker; + gBattlescriptCurrInstr = gUnknown_081D99A0; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + return 2; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = Random() & 3; + gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; + return 1; + } + } +} diff --git a/src/battle/battle_4.c b/src/battle/battle_4.c new file mode 100644 index 000000000..e4a4895b5 --- /dev/null +++ b/src/battle/battle_4.c @@ -0,0 +1,17641 @@ +#include "global.h" +#include "battle.h" +#include "battle_move_effects.h" +#include "moves.h" +#include "abilities.h" +#include "item.h" +#include "items.h" +#include "data2.h" +#include "hold_effects.h" +#include "rng.h" +#include "rom3.h" +#include "species.h" +#include "pokemon.h" +#include "text.h" +#include "palette.h" +#include "main.h" +#include "songs.h" +#include "sound.h" +#include "task.h" +#include "decompress.h" +#include "naming_screen.h" + +//extern needed variables +extern u8 gCritMultiplier; +extern s32 gBattleMoveDamage; +extern u32 gStatuses3[4]; +extern u16 gBattleTypeFlags; +extern const u32 gBitTable[]; +extern const struct BaseStats gBaseStats[]; +extern struct BattleEnigmaBerry gEnigmaBerries[4]; +extern struct BattlePokemon gBattleMons[4]; +extern u8 gActiveBank; +extern u32 gBattleExecBuffer; +extern u8 gNoOfAllBanks; +extern u16 gBattlePartyID[4]; +extern u8 gTurnOrder[4]; +extern u8 gUnknown_02024A76[4]; +extern u16 gCurrentMove; +extern u8 gLastUsedAbility; +extern u16 gBattleWeather; +extern u8 gStringBank; +extern u8 gEffectBank; +extern u8 gAbsentBankFlags; +extern u8 gMultiHitCounter; +extern u16 gLastUsedMove[4]; +extern u16 gLockedMove[4]; +extern u16 gChosenMovesByBanks[4]; +extern u16 gSideAffecting[2]; +extern u16 gPauseCounterBattle; +extern u16 gPaydayMoney; +extern u16 gRandomTurnNumber; +extern u8 gBattleOutcome; +extern u8 gBattleTerrain; +extern u16 gTrainerBattleOpponent; +extern u8 gBankAttacker; +extern u8 gBankTarget; +extern u8* gBattlescriptCurrInstr; +extern u8 gCurrMovePos; +extern u8 gFightStateTracker; +extern u32 gHitMarker; +extern u8 gBattleMoveFlags; +extern u8 gBattleCommunication[]; +extern u16 gMoveHitWith[4]; +extern u16 gUnknown_02024C44[4]; +extern u8 gStringBank; +extern u16 gDynamicBasePower; +extern const u8 gTypeEffectiveness[]; +extern u16 gLastUsedItem; +extern u16 gBattleMovePower; +extern s32 gHP_dealt; +extern s32 gTakenDmg[4]; +extern u8 gTakenDmgBanks[4]; +extern const u16 gMissStrings[]; +extern u8 gSentPokesToOpponent[2]; +extern u8 gBank1; +extern u16 gExpShareExp; +extern u8 gBattleTextBuff1[]; +extern u8 gBattleTextBuff2[]; +extern u8 gBattleTextBuff3[]; +extern u8 gLeveledUpInBattle; +extern void (*gBattleMainFunc)(void); +extern struct Window gUnknown_03004210; +extern const u8 gUnknown_08400D7A[]; +extern u8 gPlayerPartyCount; +extern u16 gMoveToLearn; //move to learn +extern const u8 gTrainerMoney[]; +extern u16 gRandomMove; +extern u8* gBattleScriptsEffectsTable[]; +extern u16 gUnknown_02024BE8; //last used move in battle +extern u8 gBankInMenu; +extern u8 gActionForBanks[4]; +extern u16 gUnknown_02024C2C[4]; //last used moves 2, used by sketch +extern u16 gUnknown_030041B0; +extern u16 gUnknown_02024C4C[4]; //last used moves by banks, another one +extern u8 gCurrentMoveTurn; +extern u16 gTrappingMoves[]; + +//extern functions +u8 AtkCanceller_UnableToUseMove(void); +void PressurePPLose(u8 bank_atk, u8 bank_def, u16 move); +void CancelMultiTurnMoves(u8 bank); +void b_movescr_stack_push(u8* BS_ptr); +void b_movescr_stack_push_cursor(void); +void RecordAbilityBattle(u8 bank, u8 ability); +void RecordItemBattle(u8 bank, u8 holdEffect); +int IsPokeDisobedient(void); +static bool8 IsTwoTurnsMove(u16 move); +static void DestinyBondFlagUpdate(void); +static void b_wonderguard_and_levitate(void); +u8 GetBankIdentity(u8 bank); +u8 GetBankSide(u8 bank); +u8 GetBattleBank(u8 bankValue); +s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 a4, u16 powerOverride, u8 typeOverride, u8 bank_atk, u8 bank_def); +static u8 AttacksThisTurn(u8 bank, u16 move); //Note: returns 1 if it's a charging turn, otherwise 2 +void UndoEffectsAfterFainting(void); +void BattleMusicStop(void); +void PlayBGM(u16 songID); +void MonGainEVs(struct Pokemon*, u16 defeatedSpecies); +extern u8 gBattleBufferB[4][0x200]; +void sub_80324F8(struct Pokemon*, u8 bank); +void AdjustFriendship(struct Pokemon*, u8 value); +bool8 IsTradedMon(struct Pokemon*); +void b_movescr_stack_pop_cursor(void); +void SwitchInClearStructs(void); +u8* ConvertIntToDecimalStringN(u8*, s32, u8, u8); +u8 GetSetPokedexFlag(u16 nationalNum, u8 caseID); +u16 SpeciesToNationalPokedexNum(u16 species); +u8 sub_803FC34(u8 bank); +u16 sub_803FBFC(u8 a); +u8 GetBankByPlayerAI(u8 ID); +void sub_8012258(u8); +void sub_80157C4(u8 bank); //update sent pokes in battle +//MonTryLearningNewMove teach poke a move +u16 GiveMoveToBattleMon(struct BattlePokemon *mon, u16 move); +void IncrementGameStat(u8 index); +u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale); +u16 GetPokedexHeightWeight(u16 national_num, u8 heightweight); +u8 sub_814A5C0(u8 a1, u16 a2, u8 a3, u16 a4, u8 a5); +void DestroyMenuCursor(void); +void sub_802BC6C(void); +void sub_809D9F0(struct Pokemon *party, u8, u8, void *, u32); +u8 sub_809FA30(void); +bool32 IsHMMove2(u16 move); +void sub_802BBD4(u8 r0, u8 r1, u8 r2, u8 r3, u8 sp0); +void nullsub_6(void); +void ReshowBattleScreenAfterMenu(void); +void sub_800F808(void); +void AddMoney(u32* moneySaveblock, u32 to_give); +void sub_80156DC(void); //set sentpokes value +bool8 sub_8014AB8(u8 bank); //can run from battle +u8 CountAliveMons(u8 caseID); +void sub_803E1B0(struct Pokemon*, u16 item, u8 partyID, u8 r3, u8 sp); +u8 CanRunFromBattle(void); +u8 GetMoveTarget(u16 move, u8 targetbyte); //get target of move +void sub_80153D0(u8 atk); //pressure perish song pp decrement +u8 CastformDataTypeChange(u8 bank); +void b_push_move_exec(u8* bs_ptr); +u8 Overworld_GetMapTypeOfSaveblockLocation(void); +u8 CalculatePlayerPartyCount(void); +u16 Sqrt(u32 num); +u8 sub_809070C(u16 nationalNum, u32 TiD, u32 PiD); //task prepare poke dex display +void sub_814A880(u8 a1, u8 a2); +u8 CheckMoveLimitations(u8 bank, u8 unusable_moves, u8 flags); +void sub_801529C(u8 bank); +bool8 IsLinkDoubleBattle(void); +void sub_8094B6C(u8 bank, u8 partyID, u8 r2); + +//extern BattleScripts +extern u8 BattleScript_EndTurn[]; +extern u8 BattleScript_NoPPForMove[]; +extern u8 BattleScript_MagicCoatBounce[]; +extern u8 BattleScript_TookAttack[]; +extern u8 BattleScript_SnatchedMove[]; +extern u8 BattleScript_Pausex20[]; +extern u8 BattleScript_SubstituteFade[]; +extern u8 BattleScript_HangedOnMsg[]; +extern u8 BattleScript_OneHitKOMsg[]; +extern u8 BattleScript_EnduredMsg[]; +extern u8 BattleScript_PSNPrevention[]; +extern u8 BattleScript_BRNPrevention[]; +extern u8 BattleScript_PRLZPrevention[]; +extern u8 BattleScript_FlinchPrevention[]; +extern u8 BattleScript_StatUp[]; +extern u8 BattleScript_StatDown[]; +extern u8 BattleScript_NoItemSteal[]; +extern u8 BattleScript_ItemSteal[]; +extern u8 BattleScript_RapidSpinAway[]; +extern u8 BattleScript_TargetPRLZHeal[]; +extern u8 BattleScript_KnockedOff[]; +extern u8 BattleScript_LevelUp[]; +extern u8 BattleScript_WrapFree[]; +extern u8 BattleScript_LeechSeedFree[]; +extern u8 BattleScript_SpikesFree[]; +extern u8 BattleScript_ButItFailed[]; +extern u8 BattleScript_ObliviousPreventsAttraction[]; +extern u8 BattleScript_MistProtected[]; +extern u8 BattleScript_AbilityNoStatLoss[]; +extern u8 BattleScript_AbilityNoSpecificStatLoss[]; +extern u8 BattleScript_TrainerBallBlock[]; +extern u8 BattleScript_WallyBallThrow[]; +extern u8 BattleScript_SuccessBallThrow[]; +extern u8 BattleScript_ShakeBallThrow[]; +extern u8 BattleScript_AllStatsUp[]; +extern u8 BattleScript_AtkDefDown[]; +extern u8 BattleScript_SAtkDown2[]; + +extern u8 gUnknown_081D919F[]; //spikes1 +extern u8 gUnknown_081D9171[]; //spikes2 +extern u8 gUnknown_081D91CD[]; //spikes3 +extern u8 BattleScript_1D6F44[]; //present dmg +extern u8 BattleScript_1D83B5[]; //present full hp +extern u8 BattleScript_1D839B[]; //present hp heal +extern u8 BattleScript_1D6F74[]; +extern u8 BattleScript_CastformChange[]; +extern u8 gUnknown_081D9834[]; +extern u8 gUnknown_081D90FC[]; //bs random switchout +extern u8 gUnknown_081D95DB[]; //bs payday money give +extern u8 gUnknown_081D8C58[]; +extern u8 gUnknown_081D8C65[]; +extern u8 gUnknown_081D9156[]; +extern u8 gUnknown_081D9468[]; + + +//useful macros +//read via orr +#define BSScriptRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24) +#define BSScriptRead8(ptr) (((u8)((ptr)[0]))) +#define BSScriptReadPtr(ptr) ((void *)BSScriptRead32(ptr)) + +//read via add +#define BS2ScriptRead32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) +#define BS2ScriptRead16(ptr) ((ptr)[0] + ((ptr)[1] << 8)) +#define BS2ScriptReadPtr(ptr) ((void *)BS2ScriptRead32(ptr)) + +#define TargetProtectAffected ((gProtectStructs[gBankTarget].protected && gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED)) + +//array entries for battle communication +#define MOVE_EFFECT_BYTE 0x3 +#define MULTISTRING_CHOOSER 0x5 +#define MSG_DISPLAY 0x7 + +#define TARGET_SELECTED 0x0 +#define TARGET_DEPENDS 0x1 +#define TARGET_BOTH 0x8 +#define TARGET_FOES_AND_ALLY 0x20 +#define TARGET_OPPONENTS_FIELD 0x40 + +#define TYPE_FORESIGHT 0xFE +#define TYPE_ENDTABLE 0xFF + +#define CMP_EQUAL 0x0 +#define CMP_NOT_EQUAL 0x1 +#define CMP_GREATER_THAN 0x2 +#define CMP_LESS_THAN 0x3 +#define CMP_COMMON_BITS 0x4 +#define CMP_NO_COMMON_BITS 0x5 + +#define uBYTE0_16(value)(( (u8) (((u16)(value) & (0x000000FF)) >> 0x00))) +#define uBYTE1_16(value)(( (u8) (((u16)(value) & (0x0000FF00)) >> 0x08))) + +#define uBYTE0_32(value)(( (u8) (((u32)(value) & (0x000000FF)) >> 0x00))) +#define uBYTE1_32(value)(( (u8) (((u32)(value) & (0x0000FF00)) >> 0x08))) +#define uBYTE2_32(value)(( (u8) (((u32)(value) & (0x00FF0000)) >> 0x10))) +#define uBYTE3_32(value)(( (u8) (((u32)(value) & (0xFF000000)) >> 0x18))) + +#define sBYTE0_16(value)(( (u8) (((s16)(value) & (0x000000FF)) >> 0x00))) +#define sBYTE1_16(value)(( (u8) (((s16)(value) & (0x0000FF00)) >> 0x08))) + +#define sBYTE0_32(value)(( (u8) (((s32)(value) & (0x000000FF)) >> 0x00))) +#define sBYTE1_32(value)(( (u8) (((s32)(value) & (0x0000FF00)) >> 0x08))) +#define sBYTE2_32(value)(( (u8) (((s32)(value) & (0x00FF0000)) >> 0x10))) +#define sBYTE3_32(value)(( (u8) (((s32)(value) & (0xFF000000)) >> 0x18))) + +#define USED_HELD_ITEM(bank)((((u16*)(&unk_2000000[bank * 2 + 0x160cc])))) + +#define RecordAbilitySetField6(ability, fieldValue) \ +(gLastUsedAbility = ability, gBattleCommunication[6] = fieldValue, RecordAbilityBattle(gBankTarget, ability)) + +#define TARGET_TURN_DAMAGED (((gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_physical.moveturnLostHP_special))) + +#define HP_ON_SWITCHOUT (((u16*)(0x020160bc))) + +static void atk00_attackcanceler(void); +static void atk01_accuracycheck(void); +static void atk02_attackstring(void); +static void atk03_ppreduce(void); +static void atk04_critcalc(void); +static void atk05_damagecalc1(void); +static void atk06_typecalc(void); +static void atk07_dmg_adjustment(void); +static void atk08_dmg_adjustment2(void); +static void atk09_attackanimation(void); +static void atk0A_waitanimation(void); +static void atk0B_healthbarupdate(void); +static void atk0C_datahpupdate(void); +static void atk0D_critmessage(void); +static void atk0E_effectiveness_sound(void); +static void atk0F_resultmessage(void); +static void atk10_printstring(void); +static void atk11_printstring_playeronly(void); +static void atk12_waitmessage(void); +static void atk13_printfromtable(void); +static void atk14_printfromtable_playeronly(void); +static void atk15_seteffectwithchancetarget(void); +static void atk16_seteffectprimary(void); +static void atk17_seteffectsecondary(void); +static void atk18_status_effect_clear(void); +static void atk19_faint_pokemon(void); +static void atk1A_faint_animation(void); +static void atk1B_faint_effects_clear(void); +static void atk1C_jumpifstatus(void); +static void atk1D_jumpifstatus2(void); +static void atk1E_jumpifability(void); +static void atk1F_jumpifsideaffecting(void); +static void atk20_jumpifstat(void); +static void atk21_jumpifstatus3(void); +static void atk22_jumpiftype(void); +static void atk23_getexp(void); +static void atk24(void); +static void atk25_move_values_cleanup(void); +static void atk26_set_multihit(void); +static void atk27_decrement_multihit(void); +static void atk28_goto(void); +static void atk29_jumpifbyte(void); +static void atk2A_jumpifhalfword(void); +static void atk2B_jumpifword(void); +static void atk2C_jumpifarrayequal(void); +static void atk2D_jumpifarraynotequal(void); +static void atk2E_setbyte(void); +static void atk2F_addbyte(void); +static void atk30_subbyte(void); +static void atk31_copyarray(void); +static void atk32_copyarray_withindex(void); +static void atk33_orbyte(void); +static void atk34_orhalfword(void); +static void atk35_orword(void); +static void atk36_bicbyte(void); +static void atk37_bichalfword(void); +static void atk38_bicword(void); +static void atk39_pause(void); +static void atk3A_waitstate(void); +static void atk3B_healthbar_update(void); +static void atk3C_return(void); +static void atk3D_end(void); +static void atk3E_end2(void); +static void atk3F_end3(void); +static void atk40_jump_if_move_affected_by_protect(void); +static void atk41_call(void); +static void atk42_jumpiftype2(void); +static void atk43_jumpifabilitypresent(void); +static void atk44(void); +static void atk45_playanimation(void); +static void atk46_playanimation2(void); +static void atk47_setgraphicalstatchangevalues(void); +static void atk48_playstatchangeanimation(void); +static void atk49_moveendturn(void); +static void atk4A_typecalc2(void); +static void atk4B_return_atk_to_ball(void); +static void atk4C_copy_poke_data(void); +static void atk4D_switch_data_update(void); +static void atk4E_switchin_anim(void); +static void atk4F_jump_if_cannot_switch(void); +static void atk50_openpartyscreen(void); +static void atk51_switch_handle_order(void); +static void atk52_switch_in_effects(void); +static void atk53_trainer_slide(void); +static void atk54_effectiveness_sound(void); +static void atk55_play_sound(void); +static void atk56_fainting_cry(void); +static void atk57(void); +static void atk58_return_to_ball(void); +void atk59_learnmove_inbattle(void); +static void atk5A(void); +static void atk5B_80256E0(void); +static void atk5C_hitanimation(void); +static void atk5D_getmoneyreward(void); +static void atk5E_8025A70(void); +static void atk5F_8025B24(void); +static void atk60_increment_gamestat(void); +static void atk61_8025BA4(void); +static void atk62_08025C6C(void); +static void atk63_jumptorandomattack(void); +static void atk64_statusanimation(void); +static void atk65_status2animation(void); +static void atk66_chosenstatusanimation(void); +static void atk67_8025ECC(void); +static void atk68_80246A0(void); +static void atk69_dmg_adjustment2(void); +void atk6A_removeitem(void); +static void atk6B_atknameinbuff1(void); +static void atk6C_lvlbox_display(void); +static void atk6D_set_sentpokes_values(void); +static void atk6E_set_atk_to_player0(void); +static void atk6F_set_visible(void); +static void atk70_record_ability(void); +static void atk71_buffer_move_to_learn(void); +static void atk72_jump_if_can_run_frombattle(void); +static void atk73_hp_thresholds(void); +static void atk74_hp_thresholds2(void); +static void atk75_8026A58(void); +static void atk76_various(void); +static void atk77_setprotect(void); +static void atk78_faintifabilitynotdamp(void); +static void atk79_setatkhptozero(void); +static void atk7A_jumpwhiletargetvalid(void); +static void atk7B_healhalfHP_if_possible(void); +static void atk7C_8025508(void); +static void atk7D_set_rain(void); +static void atk7E_setreflect(void); +static void atk7F_setseeded(void); +static void atk80_manipulatedamage(void); +static void atk81_setrest(void); +static void atk82_jumpifnotfirstturn(void); +static void atk83_nop(void); +static void atk84_jump_if_cant_sleep(void); +static void atk85_stockpile(void); +static void atk86_stockpiletobasedamage(void); +static void atk87_stockpiletohpheal(void); +static void atk88_negativedamage(void); +static u8 ChangeStatBuffs(s8, u8, u8, u8*); +static void atk89_statbuffchange(void); +static void atk8A_normalisebuffs(void); +static void atk8B_setbide(void); +static void atk8C_confuseifrepeatingattackends(void); +static void atk8D_setmultihit_counter(void); +static void atk8E_prepare_multihit(void); +static void atk8F_forcerandomswitch(void); +static void atk90_conversion_type_change(void); +static void atk91_givepaydaymoney(void); +static void atk92_setlightscreen(void); +static void atk93_ko_move(void); +static void atk94_gethalfcurrentenemyhp(void); +static void atk95_setsandstorm(void); +static void atk96_weatherdamage(void); +static void atk97_try_infatuation(void); +static void atk98_status_icon_update(void); +static void atk99_setmist(void); +static void atk9A_set_focusenergy(void); +static void atk9B_transformdataexecution(void); +static void atk9C_set_substitute(void); +static void atk9D_copyattack(void); +static void atk9E_metronome(void); +static void atk9F_dmgtolevel(void); +static void atkA0_psywavedamageeffect(void); +static void atkA1_counterdamagecalculator(void); +static void atkA2_mirrorcoatdamagecalculator(void); +static void atkA3_disablelastusedattack(void); +static void atkA4_setencore(void); +static void atkA5_painsplitdmgcalc(void); +static void atkA6_settypetorandomresistance(void); +static void atkA7_setalwayshitflag(void); +static void atkA8_copymovepermanently(void); +static void atkA9_sleeptalk_choose_move(void); +static void atkAA_set_destinybond(void); +static void atkAB_DestinyBondFlagUpdate(void); +static void atkAC_remaininghptopower(void); +static void atkAD_spite_ppreduce(void); +static void atkAE_heal_party_status(void); +static void atkAF_cursetarget(void); +static void atkB0_set_spikes(void); +static void atkB1_set_foresight(void); +static void atkB2_setperishsong(void); +static void atkB3_rolloutdamagecalculation(void); +static void atkB4_jumpifconfusedandstatmaxed(void); +static void atkB5_furycuttercalc(void); +static void atkB6_happinesstodamagecalculation(void); +static void atkB7_presentdamagecalculation(void); +static void atkB8_set_safeguard(void); +static void atkB9_magnitudedamagecalculation(void); +static void atkBA_jumpifnopursuitswitchdmg(void); +static void atkBB_setsunny(void); +static void atkBC_maxattackhalvehp(void); +static void atkBD_copyfoestats(void); +static void atkBE_breakfree(void); +static void atkBF_set_defense_curl(void); +static void atkC0_recoverbasedonsunlight(void); +static void atkC1_hidden_power(void); +static void atkC2_selectnexttarget(void); +static void atkC3_setfutureattack(void); +static void atkC4_beat_up(void); +static void atkC5_hidepreattack(void); +static void atkC6_unhidepostattack(void); +static void atkC7_setminimize(void); +static void atkC8_sethail(void); +static void atkC9_jumpifattackandspecialattackcannotfall(void); +static void atkCA_setforcedtarget(void); +static void atkCB_setcharge(void); +static void atkCC_callterrainattack(void); +static void atkCD_cureifburnedparalysedorpoisoned(void); +static void atkCE_settorment(void); +static void atkCF_jumpifnodamage(void); +static void atkD0_settaunt(void); +static void atkD1_set_helpinghand(void); +static void atkD2_swap_items(void); +static void atkD3_copy_ability(void); +static void atkD4_wish_effect(void); +static void atkD5_setroots(void); +static void atkD6_doubledamagedealtifdamaged(void); +static void atkD7_setyawn(void); +static void atkD8_setdamagetohealthdifference(void); +static void atkD9_scaledamagebyhealthratio(void); +static void atkDA_abilityswap(void); +static void atkDB_imprisoneffect(void); +static void atkDC_setgrudge(void); +static void atkDD_weightdamagecalculation(void); +static void atkDE_asistattackselect(void); +static void atkDF_setmagiccoat(void); +static void atkE0_setstealstatchange(void); +static void atkE1_intimidate_string_loader(void); +static void atkE2_switchout_abilities(void); +static void atkE3_jumpiffainted(void); +static void atkE4_getsecretpowereffect(void); +static void atkE5_pickup(void); +static void atkE6_castform_change_animation(void); +static void atkE7_castform_data_change(void); +static void atkE8_settypebasedhalvers(void); +static void atkE9_setweatherballtype(void); +static void atkEA_recycleitem(void); +static void atkEB_settypetoterrain(void); +static void atkEC_pursuit_sth(void); +static void atkED_802B4B4(void); +static void atkEE_removelightscreenreflect(void); +void atkEF_pokeball_catch_calculation(void); +static void atkF0_copy_caught_poke(void); +static void atkF1_setpoke_as_caught(void); +static void atkF2_display_dex_info(void); +static void atkF3_nickname_caught_poke(void); +static void atkF4_802BEF0(void); +static void atkF5_removeattackerstatus1(void); +static void atkF6_802BF48(void); +static void atkF7_802BF54(void); + +const BattleCmdFunc gBattleScriptingCommandsTable[] = +{ + atk00_attackcanceler, + atk01_accuracycheck, + atk02_attackstring, + atk03_ppreduce, + atk04_critcalc, + atk05_damagecalc1, + atk06_typecalc, + atk07_dmg_adjustment, + atk08_dmg_adjustment2, + atk09_attackanimation, + atk0A_waitanimation, + atk0B_healthbarupdate, + atk0C_datahpupdate, + atk0D_critmessage, + atk0E_effectiveness_sound, + atk0F_resultmessage, + atk10_printstring, + atk11_printstring_playeronly, + atk12_waitmessage, + atk13_printfromtable, + atk14_printfromtable_playeronly, + atk15_seteffectwithchancetarget, + atk16_seteffectprimary, + atk17_seteffectsecondary, + atk18_status_effect_clear, + atk19_faint_pokemon, + atk1A_faint_animation, + atk1B_faint_effects_clear, + atk1C_jumpifstatus, + atk1D_jumpifstatus2, + atk1E_jumpifability, + atk1F_jumpifsideaffecting, + atk20_jumpifstat, + atk21_jumpifstatus3, + atk22_jumpiftype, + atk23_getexp, + atk24, + atk25_move_values_cleanup, + atk26_set_multihit, + atk27_decrement_multihit, + atk28_goto, + atk29_jumpifbyte, + atk2A_jumpifhalfword, + atk2B_jumpifword, + atk2C_jumpifarrayequal, + atk2D_jumpifarraynotequal, + atk2E_setbyte, + atk2F_addbyte, + atk30_subbyte, + atk31_copyarray, + atk32_copyarray_withindex, + atk33_orbyte, + atk34_orhalfword, + atk35_orword, + atk36_bicbyte, + atk37_bichalfword, + atk38_bicword, + atk39_pause, + atk3A_waitstate, + atk3B_healthbar_update, + atk3C_return, + atk3D_end, + atk3E_end2, + atk3F_end3, + atk40_jump_if_move_affected_by_protect, + atk41_call, + atk42_jumpiftype2, + atk43_jumpifabilitypresent, + atk44, + atk45_playanimation, + atk46_playanimation2, + atk47_setgraphicalstatchangevalues, + atk48_playstatchangeanimation, + atk49_moveendturn, + atk4A_typecalc2, + atk4B_return_atk_to_ball, + atk4C_copy_poke_data, + atk4D_switch_data_update, + atk4E_switchin_anim, + atk4F_jump_if_cannot_switch, + atk50_openpartyscreen, + atk51_switch_handle_order, + atk52_switch_in_effects, + atk53_trainer_slide, + atk54_effectiveness_sound, + atk55_play_sound, + atk56_fainting_cry, + atk57, + atk58_return_to_ball, + atk59_learnmove_inbattle, + atk5A, + atk5B_80256E0, + atk5C_hitanimation, + atk5D_getmoneyreward, + atk5E_8025A70, + atk5F_8025B24, + atk60_increment_gamestat, + atk61_8025BA4, + atk62_08025C6C, + atk63_jumptorandomattack, + atk64_statusanimation, + atk65_status2animation, + atk66_chosenstatusanimation, + atk67_8025ECC, + atk68_80246A0, + atk69_dmg_adjustment2, + atk6A_removeitem, + atk6B_atknameinbuff1, + atk6C_lvlbox_display, + atk6D_set_sentpokes_values, + atk6E_set_atk_to_player0, + atk6F_set_visible, + atk70_record_ability, + atk71_buffer_move_to_learn, + atk72_jump_if_can_run_frombattle, + atk73_hp_thresholds, + atk74_hp_thresholds2, + atk75_8026A58, + atk76_various, + atk77_setprotect, + atk78_faintifabilitynotdamp, + atk79_setatkhptozero, + atk7A_jumpwhiletargetvalid, + atk7B_healhalfHP_if_possible, + atk7C_8025508, + atk7D_set_rain, + atk7E_setreflect, + atk7F_setseeded, + atk80_manipulatedamage, + atk81_setrest, + atk82_jumpifnotfirstturn, + atk83_nop, + atk84_jump_if_cant_sleep, + atk85_stockpile, + atk86_stockpiletobasedamage, + atk87_stockpiletohpheal, + atk88_negativedamage, + atk89_statbuffchange, + atk8A_normalisebuffs, + atk8B_setbide, + atk8C_confuseifrepeatingattackends, + atk8D_setmultihit_counter, + atk8E_prepare_multihit, + atk8F_forcerandomswitch, + atk90_conversion_type_change, + atk91_givepaydaymoney, + atk92_setlightscreen, + atk93_ko_move, + atk94_gethalfcurrentenemyhp, + atk95_setsandstorm, + atk96_weatherdamage, + atk97_try_infatuation, + atk98_status_icon_update, + atk99_setmist, + atk9A_set_focusenergy, + atk9B_transformdataexecution, + atk9C_set_substitute, + atk9D_copyattack, + atk9E_metronome, + atk9F_dmgtolevel, + atkA0_psywavedamageeffect, + atkA1_counterdamagecalculator, + atkA2_mirrorcoatdamagecalculator, + atkA3_disablelastusedattack, + atkA4_setencore, + atkA5_painsplitdmgcalc, + atkA6_settypetorandomresistance, + atkA7_setalwayshitflag, + atkA8_copymovepermanently, + atkA9_sleeptalk_choose_move, + atkAA_set_destinybond, + atkAB_DestinyBondFlagUpdate, + atkAC_remaininghptopower, + atkAD_spite_ppreduce, + atkAE_heal_party_status, + atkAF_cursetarget, + atkB0_set_spikes, + atkB1_set_foresight, + atkB2_setperishsong, + atkB3_rolloutdamagecalculation, + atkB4_jumpifconfusedandstatmaxed, + atkB5_furycuttercalc, + atkB6_happinesstodamagecalculation, + atkB7_presentdamagecalculation, + atkB8_set_safeguard, + atkB9_magnitudedamagecalculation, + atkBA_jumpifnopursuitswitchdmg, + atkBB_setsunny, + atkBC_maxattackhalvehp, + atkBD_copyfoestats, + atkBE_breakfree, + atkBF_set_defense_curl, + atkC0_recoverbasedonsunlight, + atkC1_hidden_power, + atkC2_selectnexttarget, + atkC3_setfutureattack, + atkC4_beat_up, + atkC5_hidepreattack, + atkC6_unhidepostattack, + atkC7_setminimize, + atkC8_sethail, + atkC9_jumpifattackandspecialattackcannotfall, + atkCA_setforcedtarget, + atkCB_setcharge, + atkCC_callterrainattack, + atkCD_cureifburnedparalysedorpoisoned, + atkCE_settorment, + atkCF_jumpifnodamage, + atkD0_settaunt, + atkD1_set_helpinghand, + atkD2_swap_items, + atkD3_copy_ability, + atkD4_wish_effect, + atkD5_setroots, + atkD6_doubledamagedealtifdamaged, + atkD7_setyawn, + atkD8_setdamagetohealthdifference, + atkD9_scaledamagebyhealthratio, + atkDA_abilityswap, + atkDB_imprisoneffect, + atkDC_setgrudge, + atkDD_weightdamagecalculation, + atkDE_asistattackselect, + atkDF_setmagiccoat, + atkE0_setstealstatchange, + atkE1_intimidate_string_loader, + atkE2_switchout_abilities, + atkE3_jumpiffainted, + atkE4_getsecretpowereffect, + atkE5_pickup, + atkE6_castform_change_animation, + atkE7_castform_data_change, + atkE8_settypebasedhalvers, + atkE9_setweatherballtype, + atkEA_recycleitem, + atkEB_settypetoterrain, + atkEC_pursuit_sth, + atkED_802B4B4, + atkEE_removelightscreenreflect, + atkEF_pokeball_catch_calculation, + atkF0_copy_caught_poke, + atkF1_setpoke_as_caught, + atkF2_display_dex_info, + atkF3_nickname_caught_poke, + atkF4_802BEF0, + atkF5_removeattackerstatus1, + atkF6_802BF48, + atkF7_802BF54, +}; + +struct statFractions +{ + u8 dividend; + u8 divisor; +}; + +static const struct statFractions gAccuracyStageRatios[] = +{ + { 33, 100}, // -6 + { 36, 100}, // -5 + { 43, 100}, // -4 + { 50, 100}, // -3 + { 60, 100}, // -2 + { 75, 100}, // -1 + { 1, 1}, // 0 + {133, 100}, // +1 + {166, 100}, // +2 + { 2, 1}, // +3 + {233, 100}, // +4 + {133, 50}, // +5 + { 3, 1}, // +6 +}; + +//The chance is 1/N for each stage. +static const u16 gCriticalHitChance[] = {16, 8, 4, 3, 2}; + +static const u32 gStatusFlagsForMoveEffects[] = +{ + 0x00000000, + 0x00000007, + 0x00000008, + 0x00000010, + 0x00000020, + 0x00000040, + 0x00000080, + 0x00000007, + 0x00000008, + 0x00000000, + 0x00000070, + 0x00000000, + 0x00001000, + 0x0000E000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00400000, + 0x00000000, + 0x00000000, + 0x04000000, + 0x08000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000C00, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; + +extern u8 BattleScript_1D963E[]; +extern u8 BattleScript_1D965A[]; +extern u8 BattleScript_1D9669[]; +extern u8 BattleScript_1D9678[]; +extern u8 BattleScript_1D9687[]; +extern u8 BattleScript_1D969D[]; +extern u8 BattleScript_1D96BA[]; +extern u8 BattleScript_1D9696[]; +extern u8 BattleScript_1D96B1[]; +extern u8 BattleScript_1D96AA[]; +extern u8 BattleScript_1D96C8[]; + +u8* const gMoveEffectBS_Ptrs[] = +{ + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D965A, + BattleScript_1D9669, + BattleScript_1D9678, + BattleScript_1D9687, + BattleScript_1D969D, + BattleScript_1D96BA, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D9696, + BattleScript_1D96AA, + BattleScript_1D963E, + BattleScript_1D96B1, + BattleScript_1D96C8, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D963E, + BattleScript_1D96C8 +}; + +const u8 sUnreferencedBitMask1[] = {0, 1, 3, 7, 0xF, 0x1F, 0x3F}; + +const u8 gLevelUpStatBoxStats[] = {MON_DATA_MAX_HP, MON_DATA_SPATK, MON_DATA_ATK, MON_DATA_SPDEF, MON_DATA_DEF, MON_DATA_SPD}; + +static const u16 sProtectSuccessRates[] = {0xFFFF, 0x7FFF, 0x3FFF, 0x1FFF}; + +static const u16 sUnknown_081FACFE[] = //banned moves to copy +{ + MOVE_METRONOME, + MOVE_STRUGGLE, + MOVE_SKETCH, + MOVE_MIMIC, + 0xFFFE, + MOVE_COUNTER, + MOVE_MIRROR_COAT, + MOVE_PROTECT, + MOVE_DETECT, + MOVE_ENDURE, + MOVE_DESTINY_BOND, + MOVE_SLEEP_TALK, + MOVE_THIEF, + MOVE_FOLLOW_ME, + MOVE_SNATCH, + MOVE_HELPING_HAND, + MOVE_COVET, + MOVE_TRICK, + MOVE_FOCUS_PUNCH, + 0xFFFF +}; + +static const u8 sUnknown_081FAD26[] = //reversal+flail HP thresholds to power +{ + 1, 200, + 4, 150, + 9, 100, + 16, 80, + 32, 40, + 48, 20 +}; + +static const u16 sNaturePowerMoves[] = +{ + MOVE_STUN_SPORE, + MOVE_RAZOR_LEAF, + MOVE_EARTHQUAKE, + MOVE_HYDRO_PUMP, + MOVE_SURF, + MOVE_BUBBLE_BEAM, + MOVE_ROCK_SLIDE, + MOVE_SHADOW_BALL, + MOVE_SWIFT, + MOVE_SWIFT +}; + +//weight-based damage table for Low Kick +//format: min. weight (hectograms), base power +static const u16 sWeightDamage[] = +{ + 100, 20, + 250, 40, + 500, 60, + 1000, 80, + 2000, 100, + -1, -1 +}; + +static const u16 sPickupItems[] = +{ + ITEM_SUPER_POTION, 30, + ITEM_FULL_HEAL, 40, + ITEM_ULTRA_BALL, 50, + ITEM_RARE_CANDY, 60, + ITEM_FULL_RESTORE, 70, + ITEM_REVIVE, 80, + ITEM_NUGGET, 90, + ITEM_PROTEIN, 95, + ITEM_PP_UP, 99, + ITEM_KINGS_ROCK, 1 +}; + +static const u8 sTerrainToType[] = +{ + TYPE_GRASS, // tall grass + TYPE_GRASS, // long grass + TYPE_GROUND, // sand + TYPE_WATER, // underwater + TYPE_WATER, // water + TYPE_WATER, // pond water + TYPE_ROCK , // rock + TYPE_ROCK , // cave + TYPE_NORMAL, // building + TYPE_NORMAL, // plain +}; + +static const u8 sBallCatchBonuses[] = +{ + 20, 15, 10, 15 //Ultra, Great, Poke, Safari +}; + +static void atk00_attackcanceler(void) +{ + int i; + if (gBattleOutcome) + { + gFightStateTracker = 0xC; + return; + } + if (gBattleMons[gBankAttacker].hp == 0 && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) + { + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + gBattlescriptCurrInstr = BattleScript_EndTurn; + return; + } + if (AtkCanceller_UnableToUseMove()) + return; + if (AbilityBattleEffects(2, gBankTarget, 0, 0, 0)) + return; + if (!gBattleMons[gBankAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE && !(gHitMarker & 0x800200) + && !(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)) + { + gBattlescriptCurrInstr = BattleScript_NoPPForMove; + gBattleMoveFlags |= MOVESTATUS_MISSED; + return; + } + gHitMarker &= ~(HITMARKER_x800000); + if (!(gHitMarker & HITMARKER_OBEYS) && !(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)) + { + u8 disobedient = IsPokeDisobedient(); + asm("":::"r0"); //It's impossible to match + asm("":::"r1"); + if ((disobedient)) + { + if (disobedient == 2) + gHitMarker |= HITMARKER_OBEYS; + else + gBattleMoveFlags |= MOVESTATUS_MISSED; + return; + } + } + gHitMarker |= HITMARKER_OBEYS; + if (gProtectStructs[gBankTarget].bounceMove && gBattleMoves[gCurrentMove].flags & FLAG_MAGICCOAT_AFFECTED) + { + PressurePPLose(gBankAttacker, gBankTarget, MOVE_MAGIC_COAT); + gProtectStructs[gBankTarget].bounceMove = 0; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_MagicCoatBounce; + return; + } + for (i = 0; i < gNoOfAllBanks; i++) + { + if ((gProtectStructs[gTurnOrder[i]].stealMove) && gBattleMoves[gCurrentMove].flags & FLAG_SNATCH_AFFECTED) + { + PressurePPLose(gBankAttacker, gTurnOrder[i], MOVE_SNATCH); + gProtectStructs[gTurnOrder[i]].stealMove = 0; + BATTLE_STRUCT->scriptingActive = gTurnOrder[i]; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_SnatchedMove; + return; + } + } + if (gSpecialStatuses[gBankTarget].lightningRodRedirected) + { + gSpecialStatuses[gBankTarget].lightningRodRedirected = 0; + gLastUsedAbility = ABILITY_LIGHTNING_ROD; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_TookAttack; + RecordAbilityBattle(gBankTarget, gLastUsedAbility); + } + else if (TargetProtectAffected + && (gCurrentMove != MOVE_CURSE || (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST)) + && ((!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)))) + { + CancelMultiTurnMoves(gBankAttacker); + gBattleMoveFlags |= MOVESTATUS_MISSED; + gMoveHitWith[gBankTarget] = 0; + gUnknown_02024C44[gBankTarget] = 0; + gBattleCommunication[6] = 1; + gBattlescriptCurrInstr++; + } + else + { + gBattlescriptCurrInstr++; + } +} + +static void JumpIfMoveFailed(u8 adder, u16 move) +{ + void* to_store = gBattlescriptCurrInstr + adder; + if (gBattleMoveFlags & MOVESTATUS_NOEFFECT) + { + gMoveHitWith[gBankTarget] = 0; + gUnknown_02024C44[gBankTarget] = 0; + to_store = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + DestinyBondFlagUpdate(); + if (AbilityBattleEffects(3, gBankTarget, 0, 0, move)) + return; + } + gBattlescriptCurrInstr = to_store; +} + +static void atk40_jump_if_move_affected_by_protect(void) +{ + if (TargetProtectAffected) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + JumpIfMoveFailed(5, 0); + gBattleCommunication[6] = 1; + } + else + { + gBattlescriptCurrInstr += 5; + } +} + +static bool8 JumpIfMoveAffectedByProtect(u16 move) +{ + bool8 affected = 0; + if (TargetProtectAffected) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + JumpIfMoveFailed(7, move); + gBattleCommunication[6] = 1; + affected = 1; + } + return affected; +} + +static bool8 AccuracyCalcHelper(u16 move) +{ + if (gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker) + { + JumpIfMoveFailed(7, move); + return TRUE; + } + + if (!(gHitMarker & HITMARKER_IGNORE_ON_AIR) && gStatuses3[gBankTarget] & STATUS3_ON_AIR) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + JumpIfMoveFailed(7, move); + return TRUE; + } + gHitMarker &= ~HITMARKER_IGNORE_ON_AIR; + + if (!(gHitMarker & HITMARKER_IGNORE_UNDERGROUND) && gStatuses3[gBankTarget] & STATUS3_UNDERGROUND) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + JumpIfMoveFailed(7, move); + return TRUE; + } + gHitMarker &= ~HITMARKER_IGNORE_UNDERGROUND; + + if (!(gHitMarker & HITMARKER_IGNORE_UNDERWATER) && gStatuses3[gBankTarget] & STATUS3_UNDERWATER) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + JumpIfMoveFailed(7, move); + return TRUE; + } + gHitMarker &= ~HITMARKER_IGNORE_UNDERWATER; + + if ((WEATHER_HAS_EFFECT && (gBattleWeather & WEATHER_RAIN_ANY) && gBattleMoves[move].effect == EFFECT_THUNDER) + || (gBattleMoves[move].effect == EFFECT_ALWAYS_HIT || gBattleMoves[move].effect == EFFECT_VITAL_THROW)) + { + JumpIfMoveFailed(7, move); + return TRUE; + } + return FALSE; +} + +static void atk01_accuracycheck(void) +{ + u16 move = BS2ScriptRead16(gBattlescriptCurrInstr + 5); + if (move == 0xFFFE || move == 0xFFFF) + { + if (gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS && move == 0xFFFF && gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker) + gBattlescriptCurrInstr += 7; + else if (gStatuses3[gBankTarget] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else if (!JumpIfMoveAffectedByProtect(0)) + gBattlescriptCurrInstr += 7; + } + else + { + u8 type; s8 buff; u8 MoveAcc; u16 calc; u8 hold_effect; u8 quality; + if (move == 0) {move = gCurrentMove;} + + if (BATTLE_STRUCT->dynamicMoveType) + type = BATTLE_STRUCT->dynamicMoveType & 0x3F; + else + type = gBattleMoves[move].type; + + if (JumpIfMoveAffectedByProtect(move)) + return; + if (AccuracyCalcHelper(move)) + return; + + if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT) + { + u8 acc = gBattleMons[gBankAttacker].statStages[STAT_STAGE_ACC]; + buff = acc; + } + else + { + u8 acc = gBattleMons[gBankAttacker].statStages[STAT_STAGE_ACC]; + buff = acc + 6 - gBattleMons[gBankTarget].statStages[STAT_STAGE_EVASION]; + } + + if (buff < 0) {buff = 0;} + if (buff > 0xC) {buff = 0xC;} + + MoveAcc = gBattleMoves[move].accuracy; + //check Thunder on sunny weather + if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY && gBattleMoves[move].effect == EFFECT_THUNDER) + MoveAcc = 50; + + calc = gAccuracyStageRatios[buff].dividend * MoveAcc; + calc /= gAccuracyStageRatios[buff].divisor; + + if (gBattleMons[gBankAttacker].ability == ABILITY_COMPOUND_EYES) + calc = (calc * 130) / 100; //1.3 compound eyes boost + if (WEATHER_HAS_EFFECT && gBattleMons[gBankTarget].ability == ABILITY_SAND_VEIL && gBattleWeather & WEATHER_SANDSTORM_ANY) + calc = (calc * 80) / 100; //1.2 sand veil loss; + if (gBattleMons[gBankAttacker].ability == ABILITY_HUSTLE && type < 9) + calc = (calc * 80) / 100; //1.2 hustle loss; + + if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY) + hold_effect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam; + else + { + hold_effect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item); + quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item); + } + + gStringBank = gBankTarget; + + if (hold_effect == HOLD_EFFECT_EVASION_UP) + calc = (calc * (100 - quality)) / 100; + + //final calculation + if ((Random() % 100 + 1) > calc) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && (gBattleMoves[move].target == 0x8 || gBattleMoves[move].target == 0x20)) + gBattleCommunication[6] = 2; + else + gBattleCommunication[6] = 0; + b_wonderguard_and_levitate(); + + } + JumpIfMoveFailed(7, move); + } +} + +static void atk02_attackstring(void) +{ + if (gBattleExecBuffer) + return; + if (!(gHitMarker & (HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED))) + { + PrepareStringBattle(4, gBankAttacker); + gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; + } + gBattlescriptCurrInstr++; + gBattleCommunication[MSG_DISPLAY] = 0; +} + +static void atk03_ppreduce(void) +{ + int to_deduct = 1; + if (gBattleExecBuffer) + return; + if (!gSpecialStatuses[gBankAttacker].flag20) + { + switch (gBattleMoves[gCurrentMove].target) + { + case TARGET_FOES_AND_ALLY: + to_deduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_ON_FIELD, gBankAttacker, ABILITY_PRESSURE, 0, 0); + break; + case TARGET_BOTH: + case TARGET_OPPONENTS_FIELD: + to_deduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIZE, gBankAttacker, ABILITY_PRESSURE, 0, 0); + break; + default: + if (gBankAttacker != gBankTarget && gBattleMons[gBankTarget].ability == ABILITY_PRESSURE) + to_deduct++; + break; + } + } + if (!(gHitMarker & (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING)) && gBattleMons[gBankAttacker].pp[gCurrMovePos]) + { + gProtectStructs[gBankAttacker].notFirstStrike = 1; + if (gBattleMons[gBankAttacker].pp[gCurrMovePos] > to_deduct) + gBattleMons[gBankAttacker].pp[gCurrMovePos] -= to_deduct; + else + gBattleMons[gBankAttacker].pp[gCurrMovePos] = 0; + + if (!(gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED) + && !((gDisableStructs[gBankAttacker].unk18_b) & gBitTable[gCurrMovePos])) + { + gActiveBank = gBankAttacker; + EmitSetAttributes(0, REQUEST_PPMOVE1_BATTLE + gCurrMovePos, 0, 1, &gBattleMons[gBankAttacker].pp[gCurrMovePos]); + MarkBufferBankForExecution(gBankAttacker); + } + } + gHitMarker &= ~(HITMARKER_NO_PPDEDUCT); + gBattlescriptCurrInstr++; +} + +static void atk04_critcalc(void) +{ + u8 hold_effect; u16 item; u16 crit_chance; int adderv3, adderv5, adderv6, adderv7, adderv8, adderv9, adderv10, adderv11; u16 adderv12; + item = gBattleMons[gBankAttacker].item; + if (item == ITEM_ENIGMA_BERRY) + hold_effect = gEnigmaBerries[gBankAttacker].holdEffect; + else + hold_effect = ItemId_GetHoldEffect(item); + + gStringBank = gBankAttacker; + + if (gBattleMons[gBankAttacker].status2 & STATUS2_FOCUS_ENERGY) + adderv3 = 2; + else + adderv3 = 0; + + if (gBattleMoves[gCurrentMove].effect == EFFECT_HIGH_CRITICAL) {adderv3++;} + adderv5 = adderv3; + if (gBattleMoves[gCurrentMove].effect == EFFECT_SKY_ATTACK) {adderv5 = adderv3 + 1;} + + if (gBattleMoves[gCurrentMove].effect == EFFECT_BLAZE_KICK) {adderv5++;} + adderv6 = adderv5; + if (gBattleMoves[gCurrentMove].effect == EFFECT_POISON_TAIL) {adderv6 = adderv5 + 1;} + + adderv7 = 0; + if (hold_effect == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBankAttacker].species == SPECIES_CHANSEY) {adderv7 = 1;} + adderv8 = 2 * adderv7; + adderv9 = 0; + if (hold_effect == HOLD_EFFECT_STICK && gBattleMons[gBankAttacker].species == SPECIES_FARFETCHD) {adderv9 = 1;} + adderv11 = 2 * adderv9; + if (hold_effect == HOLD_EFFECT_SCOPE_LENS) + {adderv10 = 1 + adderv6 + adderv8; adderv12 = adderv10 + adderv11;} + else + {adderv10 = adderv6 + adderv8; adderv12 = adderv10 + adderv11;} + + crit_chance = adderv12; + + if (crit_chance > 4) {crit_chance = 4;} + + if ((gBattleMons[gBankTarget].ability != ABILITY_BATTLE_ARMOR && gBattleMons[gBankTarget].ability != ABILITY_SHELL_ARMOR) + && !(gStatuses3[gBankAttacker] & STATUS3_CANT_SCORE_A_CRIT) + && !(gBattleTypeFlags & (BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE)) + && !(Random() % gCriticalHitChance[crit_chance])) + gCritMultiplier = 2; + else + gCritMultiplier = 1; + gBattlescriptCurrInstr++; +} + +static void atk05_damagecalc1(void) +{ + u16 side_hword = gSideAffecting[GetBankIdentity(gBankTarget) & 1]; + gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove, + side_hword, gDynamicBasePower, + BATTLE_STRUCT->dynamicMoveType, gBankAttacker, gBankTarget); + gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * BATTLE_STRUCT->dmgMultiplier; + + if (gStatuses3[gBankAttacker] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC) + gBattleMoveDamage *= 2; + if (gProtectStructs[gBankAttacker].helpingHand) + gBattleMoveDamage = gBattleMoveDamage * 15 / 10; + + gBattlescriptCurrInstr++; +} + +void AI_CalcDmg(u8 BankAtk, u8 BankDef) +{ + u16 side_hword = gSideAffecting[GetBankIdentity(BankDef) & 1]; + gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[BankAtk], &gBattleMons[BankDef], gCurrentMove, + side_hword, gDynamicBasePower, + BATTLE_STRUCT->dynamicMoveType, BankAtk, BankDef); + gDynamicBasePower = 0; + gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * BATTLE_STRUCT->dmgMultiplier; + + if (gStatuses3[BankAtk] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC) + gBattleMoveDamage *= 2; + if (gProtectStructs[BankAtk].helpingHand) + gBattleMoveDamage = gBattleMoveDamage * 15 / 10; +} + +static void ModulateDmgByType(u8 multiplier) +{ + gBattleMoveDamage = gBattleMoveDamage * multiplier / 10; + if (gBattleMoveDamage == 0 && multiplier != 0) + gBattleMoveDamage = 1; + + switch (multiplier) + { + case 0: //no effect + gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED; + gBattleMoveFlags &= ~MOVESTATUS_NOTVERYEFFECTIVE; + gBattleMoveFlags &= ~MOVESTATUS_SUPEREFFECTIVE; + break; + case 5: //not very effecting + if (gBattleMoves[gCurrentMove].power && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT)) + { + if (gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE) + gBattleMoveFlags &= ~MOVESTATUS_SUPEREFFECTIVE; + else + gBattleMoveFlags |= MOVESTATUS_NOTVERYEFFECTIVE; + } + break; + case 20: //super effective + if (gBattleMoves[gCurrentMove].power && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT)) + { + if (gBattleMoveFlags & MOVESTATUS_NOTVERYEFFECTIVE) + gBattleMoveFlags &= ~MOVESTATUS_NOTVERYEFFECTIVE; + else + gBattleMoveFlags |= MOVESTATUS_SUPEREFFECTIVE; + } + break; + } +} + +static void atk06_typecalc(void) +{ + int i = 0; + u8 move_type; + if (gCurrentMove != MOVE_STRUGGLE) + { + if (BATTLE_STRUCT->dynamicMoveType) + move_type = BATTLE_STRUCT->dynamicMoveType & 0x3F; + else + move_type = gBattleMoves[gCurrentMove].type; + + //check stab + if (gBattleMons[gBankAttacker].type1 == move_type || gBattleMons[gBankAttacker].type2 == move_type) + { + gBattleMoveDamage = gBattleMoveDamage * 15; + gBattleMoveDamage = gBattleMoveDamage / 10; + } + + if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && move_type == TYPE_GROUND) + { + gLastUsedAbility = gBattleMons[gBankTarget].ability; + gBattleMoveFlags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED); + gMoveHitWith[gBankTarget] = 0; + gUnknown_02024C44[gBankTarget] = 0; + gBattleCommunication[6] = move_type; + RecordAbilityBattle(gBankTarget, gLastUsedAbility); + } + else + { + while (gTypeEffectiveness[i]!= TYPE_ENDTABLE) + { + if (gTypeEffectiveness[i] == TYPE_FORESIGHT) + { + if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT) + break; + i += 3; + continue; + } + + else if (gTypeEffectiveness[i] == move_type) + { + //check type1 + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1) + ModulateDmgByType(gTypeEffectiveness[i + 2]); + //check type2 + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 && + gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2) + ModulateDmgByType(gTypeEffectiveness[i + 2]); + } + i += 3; + } + } + + if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBankAttacker, gCurrentMove) == 2 + && (!(gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE) || ((gBattleMoveFlags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE))) + && gBattleMoves[gCurrentMove].power) + { + gLastUsedAbility = ABILITY_WONDER_GUARD; + gBattleMoveFlags |= MOVESTATUS_MISSED; + gMoveHitWith[gBankTarget] = 0; + gUnknown_02024C44[gBankTarget] = 0; + gBattleCommunication[6] = 3; + RecordAbilityBattle(gBankTarget, gLastUsedAbility); + } + if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) + gProtectStructs[gBankAttacker].notEffective = 1; + } + gBattlescriptCurrInstr++; +} +static void b_wonderguard_and_levitate(void) +{ + u8 flags = 0; + int i = 0; + u8 move_type; + + if (gCurrentMove == MOVE_STRUGGLE || !gBattleMoves[gCurrentMove].power) + return; + + if (BATTLE_STRUCT->dynamicMoveType) + move_type = BATTLE_STRUCT->dynamicMoveType & 0x3F; + else + move_type = gBattleMoves[gCurrentMove].type; + + if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && move_type == TYPE_GROUND) + { + RecordAbilitySetField6(ABILITY_LEVITATE, move_type); + return; + } + + while (gTypeEffectiveness[i]!= TYPE_ENDTABLE) + { + if (gTypeEffectiveness[i] == TYPE_FORESIGHT) + { + if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT) + break; + i += 3; + continue; + } + + if (gTypeEffectiveness[i] == move_type) + { + //check no effect + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 0) + { + gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED; + gProtectStructs[gBankAttacker].notEffective = 1; + } + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 && + gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 && + gTypeEffectiveness[i + 2] == 0) + { + gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED; + gProtectStructs[gBankAttacker].notEffective = 1; + } + + //check super effective + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 20) + flags |= 1; + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 + && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 + && gTypeEffectiveness[i + 2] == 20) + flags |= 1; + + //check not very effective + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 5) + flags |= 2; + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 + && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 + && gTypeEffectiveness[i + 2] == 5) + flags |= 2; + } + i += 3; + } + + if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBankAttacker, gCurrentMove) == 2) + { + if (((flags & 2) || !(flags & 1)) && gBattleMoves[gCurrentMove].power) + { + RecordAbilitySetField6(ABILITY_WONDER_GUARD, 3); + } + } +} + +static void ModulateDmgByType2(u8 multiplier, u16 move, u8* flags) //a literal copy of the ModulateDmgbyType1 with different args... +{ + gBattleMoveDamage = gBattleMoveDamage * multiplier / 10; + if (gBattleMoveDamage == 0 && multiplier != 0) + gBattleMoveDamage = 1; + + switch (multiplier) + { + case 0: //no effect + *flags |= MOVESTATUS_NOTAFFECTED; + *flags &= ~MOVESTATUS_NOTVERYEFFECTIVE; + *flags &= ~MOVESTATUS_SUPEREFFECTIVE; + break; + case 5: //not very effecting + if (gBattleMoves[move].power && !(*flags & MOVESTATUS_NOEFFECT)) + { + if (*flags & MOVESTATUS_SUPEREFFECTIVE) + *flags &= ~MOVESTATUS_SUPEREFFECTIVE; + else + *flags |= MOVESTATUS_NOTVERYEFFECTIVE; + } + break; + case 20: //super effective + if (gBattleMoves[move].power && !(*flags & MOVESTATUS_NOEFFECT)) + { + if (*flags & MOVESTATUS_NOTVERYEFFECTIVE) + *flags &= ~MOVESTATUS_NOTVERYEFFECTIVE; + else + *flags |= MOVESTATUS_SUPEREFFECTIVE; + } + break; + } +} + +u8 TypeCalc(u16 move, u8 bank_atk, u8 bank_def) +{ + int i = 0; + u8 flags = 0; + u8 move_type; + + if (move == MOVE_STRUGGLE) + return 0; + + move_type = gBattleMoves[move].type; + + //check stab + if (gBattleMons[bank_atk].type1 == move_type || gBattleMons[bank_atk].type2 == move_type) + { + gBattleMoveDamage = gBattleMoveDamage * 15; + gBattleMoveDamage = gBattleMoveDamage / 10; + } + + if (gBattleMons[bank_def].ability == ABILITY_LEVITATE && move_type == TYPE_GROUND) + { + flags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED); + } + else + { + while (gTypeEffectiveness[i]!= TYPE_ENDTABLE) + { + if (gTypeEffectiveness[i] == TYPE_FORESIGHT) + { + if (gBattleMons[bank_def].status2 & STATUS2_FORESIGHT) + break; + i += 3; + continue; + } + + else if (gTypeEffectiveness[i] == move_type) + { + //check type1 + if (gTypeEffectiveness[i + 1] == gBattleMons[bank_def].type1) + ModulateDmgByType2(gTypeEffectiveness[i + 2], move, &flags); + //check type2 + if (gTypeEffectiveness[i + 1] == gBattleMons[bank_def].type2 && + gBattleMons[gBankTarget /* what the christ */].type1 != gBattleMons[bank_def].type2) + ModulateDmgByType2(gTypeEffectiveness[i + 2], move, &flags); + } + i += 3; + } + } + + if (gBattleMons[bank_def].ability == ABILITY_WONDER_GUARD && !(flags & MOVESTATUS_MISSED) && + AttacksThisTurn(bank_atk, move) == 2 && + (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE))) && + gBattleMoves[move].power) + { + flags |= MOVESTATUS_MISSED; + } + return flags; +} + +u8 AI_TypeCalc(u16 move, u16 species, u8 ability) +{ + int i = 0; + u8 flags = 0; + u8 type1 = gBaseStats[species].type1, type2 = gBaseStats[species].type2, move_type; + + if (move == MOVE_STRUGGLE) + return 0; + + move_type = gBattleMoves[move].type; + + if (ability == ABILITY_LEVITATE && move_type == TYPE_GROUND) + flags = MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED; + else + { + while (gTypeEffectiveness[i]!= TYPE_ENDTABLE) + { + if (gTypeEffectiveness[i] == TYPE_FORESIGHT) + { + i += 3; + continue; + } + if (gTypeEffectiveness[i] == move_type) + { + //check type1 + if (gTypeEffectiveness[i + 1] == type1) + ModulateDmgByType2(gTypeEffectiveness[i + 2], move, &flags); + //check type2 + if (gTypeEffectiveness[i + 1] == type2 && gBattleMons[gBankTarget].type1 != type2) //gf you morons, you should check if (type1 != type2)... + ModulateDmgByType2(gTypeEffectiveness[i + 2], move, &flags); + } + i += 3; + } + } + if (ability == ABILITY_WONDER_GUARD + && (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE))) + && gBattleMoves[move].power) + flags |= MOVESTATUS_NOTAFFECTED; + return flags; +} + +// Multiplies the damage by a random factor between 85% to 100% inclusive +static inline void ApplyRandomDmgMultiplier(void) +{ + u16 rand = Random(); + u16 randPercent = 100 - (rand % 16); + + if (gBattleMoveDamage != 0) + { + gBattleMoveDamage *= randPercent; + gBattleMoveDamage /= 100; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } +} + +void Unused_ApplyRandomDmgMultiplier(void) +{ + ApplyRandomDmgMultiplier(); +} + +static void atk07_dmg_adjustment(void) +{ + u8 hold_effect, quality; + ApplyRandomDmgMultiplier(); + if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY) + { + hold_effect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam; + } + else + { + hold_effect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item); + quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item); + } + + gStringBank = gBankTarget; + + if (hold_effect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality) + { + RecordItemBattle(gBankTarget, hold_effect); + gSpecialStatuses[gBankTarget].focusBanded = 1; + } + if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE) + goto END; + if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE && !gProtectStructs[gBankTarget].endured + && !gSpecialStatuses[gBankTarget].focusBanded) + goto END; + + if (gBattleMons[gBankTarget].hp > gBattleMoveDamage) + goto END; + + gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1; + + if (gProtectStructs[gBankTarget].endured) + { + gBattleMoveFlags |= MOVESTATUS_ENDURED; + goto END; + } + if (gSpecialStatuses[gBankTarget].focusBanded) + { + gBattleMoveFlags |= MOVESTATUS_HUNGON; + gLastUsedItem = gBattleMons[gBankTarget].item; + } + + END: + gBattlescriptCurrInstr++; +} + +static void atk08_dmg_adjustment2(void) //literally the same as 0x7 except it doesn't check for false swipe move effect... +{ + u8 hold_effect, quality; + ApplyRandomDmgMultiplier(); + if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY) + { + hold_effect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam; + } + else + { + hold_effect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item); + quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item); + } + + gStringBank = gBankTarget; + + if (hold_effect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality) + { + RecordItemBattle(gBankTarget, hold_effect); + gSpecialStatuses[gBankTarget].focusBanded = 1; + } + if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE) + goto END; + if (!gProtectStructs[gBankTarget].endured + && !gSpecialStatuses[gBankTarget].focusBanded) + goto END; + + if (gBattleMons[gBankTarget].hp > gBattleMoveDamage) + goto END; + + gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1; + + if (gProtectStructs[gBankTarget].endured) + { + gBattleMoveFlags |= MOVESTATUS_ENDURED; + goto END; + } + if (gSpecialStatuses[gBankTarget].focusBanded) + { + gBattleMoveFlags |= MOVESTATUS_HUNGON; + gLastUsedItem = gBattleMons[gBankTarget].item; + } + + END: + gBattlescriptCurrInstr++; +} + +static void atk09_attackanimation(void) +{ + if (gBattleExecBuffer) + return; + + if ((gHitMarker & HITMARKER_NO_ANIMATIONS) && (gCurrentMove != MOVE_TRANSFORM && gCurrentMove != MOVE_SUBSTITUTE)) + { + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_Pausex20; + BATTLE_STRUCT->animTurn += 1; + BATTLE_STRUCT->animTargetsHit += 1; + } + else + { + if ((gBattleMoves[gCurrentMove].target & TARGET_BOTH || gBattleMoves[gCurrentMove].target & TARGET_FOES_AND_ALLY || gBattleMoves[gCurrentMove].target & TARGET_DEPENDS) && BATTLE_STRUCT->animTargetsHit) + { + gBattlescriptCurrInstr++; + return; + } + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)) + { + gActiveBank = gBankAttacker; + + EmitMoveAnimation(0, gCurrentMove, BATTLE_STRUCT->animTurn, gBattleMovePower, gBattleMoveDamage, gBattleMons[gBankAttacker].friendship, &gDisableStructs[gBankAttacker]); + BATTLE_STRUCT->animTurn += 1; + BATTLE_STRUCT->animTargetsHit += 1; + MarkBufferBankForExecution(gBankAttacker); + gBattlescriptCurrInstr++; + } + else + { + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_Pausex20; + } + } +} + +static void atk0A_waitanimation(void) +{ + if (gBattleExecBuffer == 0) + gBattlescriptCurrInstr++; +} + +static void atk0B_healthbarupdate(void) +{ + if (gBattleExecBuffer) + return; + if (gBattleMoveFlags & MOVESTATUS_NOEFFECT) + goto END; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + + if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBank].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE)) + { + PrepareStringBattle(0x80, gActiveBank); + goto END; + } + + EmitHealthBarUpdate(0, gBattleMoveDamage); + MarkBufferBankForExecution(gActiveBank); + + if (!GetBankSide(gActiveBank) && gBattleMoveDamage > 0) + gBattleResults.unk5_0 = 1; + + END: + gBattlescriptCurrInstr += 2; +} + +static void atk0C_datahpupdate(void) +{ + register u32 move_type asm("r6"); //no idea how to match it otherwise + u8 dynamic_move_type; + + if (gBattleExecBuffer) + return; + + dynamic_move_type = BATTLE_STRUCT->dynamicMoveType; + if (dynamic_move_type && !(dynamic_move_type & 0x40)) + { + move_type = 0x3F; + move_type &= dynamic_move_type; + } + else + { + move_type = gBattleMoves[gCurrentMove].type; + } + + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)) + { + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBank].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE)) + { + if (gDisableStructs[gActiveBank].substituteHP >= gBattleMoveDamage) + { + if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0) + gSpecialStatuses[gActiveBank].moveturnLostHP = gBattleMoveDamage; + gDisableStructs[gActiveBank].substituteHP -= gBattleMoveDamage; + gHP_dealt = gBattleMoveDamage; + } + else + { + if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0) + gSpecialStatuses[gActiveBank].moveturnLostHP = gDisableStructs[gActiveBank].substituteHP; + gHP_dealt = gDisableStructs[gActiveBank].substituteHP; + gDisableStructs[gActiveBank].substituteHP = 0; + } + //check substitute fading + if (gDisableStructs[gActiveBank].substituteHP == 0) + { + gBattlescriptCurrInstr += 2; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_SubstituteFade; + return; + } + } + else + { + gHitMarker &= ~(HITMARKER_IGNORE_SUBSTITUTE); + if (gBattleMoveDamage < 0) //hp goes up + { + gBattleMons[gActiveBank].hp -= gBattleMoveDamage; + if (gBattleMons[gActiveBank].hp > gBattleMons[gActiveBank].maxHP) + gBattleMons[gActiveBank].hp = gBattleMons[gActiveBank].maxHP; + + } + else //hp goes down + { + if (gHitMarker & HITMARKER_x20) + { + gHitMarker &= ~(HITMARKER_x20); + } + else + { + gTakenDmg[gActiveBank] += gBattleMoveDamage; + if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 0) + gTakenDmgBanks[gActiveBank] = gBankAttacker; + else + gTakenDmgBanks[gActiveBank] = gBankTarget; + } + + if (gBattleMons[gActiveBank].hp > gBattleMoveDamage) + { + gBattleMons[gActiveBank].hp -= gBattleMoveDamage; + gHP_dealt = gBattleMoveDamage; + } + else + { + gHP_dealt = gBattleMons[gActiveBank].hp; + gBattleMons[gActiveBank].hp = 0; + } + + if (!gSpecialStatuses[gActiveBank].moveturnLostHP && !(gHitMarker & HITMARKER_x100000)) + gSpecialStatuses[gActiveBank].moveturnLostHP = gHP_dealt; + + if (move_type <= 8 && !(gHitMarker & HITMARKER_x100000) && gCurrentMove != MOVE_PAIN_SPLIT) + { + gProtectStructs[gActiveBank].physicalDmg = gHP_dealt; + gSpecialStatuses[gActiveBank].moveturnLostHP_physical = gHP_dealt; + if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 0) + { + gProtectStructs[gActiveBank].physicalBank = gBankAttacker; + gSpecialStatuses[gActiveBank].moveturnPhysicalBank = gBankAttacker; + } + else + { + gProtectStructs[gActiveBank].physicalBank = gBankTarget; + gSpecialStatuses[gActiveBank].moveturnPhysicalBank = gBankTarget; + } + } + else if (move_type > 8 && !(gHitMarker & HITMARKER_x100000)) + { + gProtectStructs[gActiveBank].specialDmg = gHP_dealt; + gSpecialStatuses[gActiveBank].moveturnLostHP_special = gHP_dealt; + if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 0) + { + gProtectStructs[gActiveBank].specialBank = gBankAttacker; + gSpecialStatuses[gActiveBank].moveturnSpecialBank = gBankAttacker; + } + else + { + gProtectStructs[gActiveBank].specialBank = gBankTarget; + gSpecialStatuses[gActiveBank].moveturnSpecialBank = gBankTarget; + } + } + } + gHitMarker &= ~(HITMARKER_x100000); + EmitSetAttributes(0, REQUEST_HP_BATTLE, 0, 2, &gBattleMons[gActiveBank].hp); + MarkBufferBankForExecution(gActiveBank); + } + } + else + { + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0) + gSpecialStatuses[gActiveBank].moveturnLostHP = 0xFFFF; + } + gBattlescriptCurrInstr += 2; +} + +static void atk0D_critmessage(void) +{ + if (gBattleExecBuffer == 0) + { + if (gCritMultiplier == 2 && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT)) + { + PrepareStringBattle(0xD9, gBankAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + } + gBattlescriptCurrInstr++; + } +} + +static void atk0E_effectiveness_sound(void) +{ + if (gBattleExecBuffer) + return; + gActiveBank = gBankTarget; + if (!(gBattleMoveFlags & MOVESTATUS_MISSED)) + { + u8 flag = ~MOVESTATUS_MISSED; + switch (gBattleMoveFlags & flag) + { + case MOVESTATUS_SUPEREFFECTIVE: + EmitEffectivenessSound(0, 14); + MarkBufferBankForExecution(gActiveBank); + break; + case MOVESTATUS_NOTVERYEFFECTIVE: + EmitEffectivenessSound(0, 12); + MarkBufferBankForExecution(gActiveBank); + break; + case MOVESTATUS_NOTAFFECTED: + case MOVESTATUS_FAILED: + break; + case MOVESTATUS_ENDURED: + case MOVESTATUS_ONEHITKO: + case MOVESTATUS_HUNGON: + default: + if (gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE) + { + EmitEffectivenessSound(0, 14); + MarkBufferBankForExecution(gActiveBank); + } + else if (gBattleMoveFlags & MOVESTATUS_NOTVERYEFFECTIVE) + { + EmitEffectivenessSound(0, 12); + MarkBufferBankForExecution(gActiveBank); + } + else if (!(gBattleMoveFlags & (MOVESTATUS_NOTAFFECTED | MOVESTATUS_FAILED))) + { + EmitEffectivenessSound(0, 13); + MarkBufferBankForExecution(gActiveBank); + } + break; + } + } + gBattlescriptCurrInstr++; +} + +static void atk0F_resultmessage(void) +{ + u16 stringID = 0; + + if (gBattleExecBuffer) + return; + + if (gBattleMoveFlags & MOVESTATUS_MISSED && (!(gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) || gBattleCommunication[6] > 2)) + { + stringID = gMissStrings[gBattleCommunication[6]]; + gBattleCommunication[MSG_DISPLAY] = 1; + } + else + { + gBattleCommunication[MSG_DISPLAY] = 1; + switch (gBattleMoveFlags & 0xFE) + { + case MOVESTATUS_SUPEREFFECTIVE: + stringID = 0xDE; + break; + case MOVESTATUS_NOTVERYEFFECTIVE: + stringID = 0xDD; + break; + case MOVESTATUS_ONEHITKO: + stringID = 0xDA; + break; + case MOVESTATUS_ENDURED: + stringID = 0x99; + break; + case MOVESTATUS_FAILED: + goto FAILED; + case MOVESTATUS_NOTAFFECTED: + goto NOTAFFECTED; + case MOVESTATUS_HUNGON: + gLastUsedItem = gBattleMons[gBankTarget].item; + gStringBank = gBankTarget; + gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_HangedOnMsg; + return; + default: + if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) + NOTAFFECTED: + stringID = 0x1B; + else if (gBattleMoveFlags & MOVESTATUS_ONEHITKO) + { + gBattleMoveFlags &= ~(MOVESTATUS_ONEHITKO); + gBattleMoveFlags &= ~(MOVESTATUS_SUPEREFFECTIVE); + gBattleMoveFlags &= ~(MOVESTATUS_NOTVERYEFFECTIVE); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_OneHitKOMsg; + return; + } + else if (gBattleMoveFlags & MOVESTATUS_ENDURED) + { + gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_EnduredMsg; + return; + } + else if (gBattleMoveFlags & MOVESTATUS_HUNGON) + { + gLastUsedItem = gBattleMons[gBankTarget].item; + gStringBank = gBankTarget; + gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_HangedOnMsg; + return; + } + else if (gBattleMoveFlags & MOVESTATUS_FAILED) + FAILED: + stringID = 0xE5; + else + gBattleCommunication[MSG_DISPLAY] = 0; + } + } + + if (stringID) + { + register u16 dummy asm("r0") = stringID; //Can't match it otherwise + PrepareStringBattle(dummy, gBankAttacker); + } + gBattlescriptCurrInstr++; +} + +static void atk10_printstring(void) +{ + if (gBattleExecBuffer == 0) + { + u16 var = BS2ScriptRead16(gBattlescriptCurrInstr + 1); + PrepareStringBattle(var, gBankAttacker); + gBattlescriptCurrInstr += 3; + gBattleCommunication[MSG_DISPLAY] = 1; + } +} + +static void atk11_printstring_playeronly(void) +{ + gActiveBank = gBankAttacker; + EmitPrintStringPlayerOnly(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1)); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 3; + gBattleCommunication[MSG_DISPLAY] = 1; +} + +static void atk12_waitmessage(void) +{ + if (gBattleExecBuffer == 0) + { + if (!gBattleCommunication[MSG_DISPLAY]) + { + gBattlescriptCurrInstr += 3; + } + else + { + u16 to_wait = BS2ScriptRead16(gBattlescriptCurrInstr + 1); + if (++gPauseCounterBattle >= to_wait) + { + gPauseCounterBattle = 0; + gBattlescriptCurrInstr += 3; + gBattleCommunication[MSG_DISPLAY] = 0; + } + } + } +} + +static void atk13_printfromtable(void) +{ + if (gBattleExecBuffer == 0) + { + u16 *ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + ptr += gBattleCommunication[MULTISTRING_CHOOSER]; + PrepareStringBattle(*(u16*)ptr, gBankAttacker); + gBattlescriptCurrInstr += 5; + gBattleCommunication[MSG_DISPLAY] = 1; + } +} + +static void atk14_printfromtable_playeronly(void) +{ + if (gBattleExecBuffer == 0) + { + u16 *ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + ptr += gBattleCommunication[MULTISTRING_CHOOSER]; + gActiveBank = gBankAttacker; + EmitPrintStringPlayerOnly(0, *(u16*)ptr); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 5; + gBattleCommunication[MSG_DISPLAY] = 1; + } +} + +u8 BankGetTurnOrder(u8 bank) +{ + int i; + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gTurnOrder[i] == bank) + break; + } + return i; +} + +//Someone please decompile this monstrosity below... +#ifdef NONMATCHING +void SetMoveEffect(bool8 primary, u8 certainArg) +{ + #define EffectAffectsUser 0x40 + register u8 certain asm("r5") = certainArg; + register bool32 StatusChanged asm("r10") = 0; + register int AffectsUser asm("r6") = 0; //0x40 otherwise + bool32 NoSunCanFreeze = 1; + + if (gBattleCommunication[MOVE_EFFECT_BYTE] & EffectAffectsUser) + { + gEffectBank = gBankAttacker; //bank that effects get applied on + gBattleCommunication[MOVE_EFFECT_BYTE] &= ~(EffectAffectsUser); + AffectsUser = EffectAffectsUser; + BATTLE_STRUCT->scriptingActive = gBankTarget; //theoretically the attacker + } + else + { + gEffectBank = gBankTarget; + BATTLE_STRUCT->scriptingActive = gBankAttacker; + } + + if (gBattleMons[gEffectBank].ability == ABILITY_SHIELD_DUST && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD) && + !primary && gBattleCommunication[MOVE_EFFECT_BYTE] <= 9) + {gBattlescriptCurrInstr++; return;} + + if (gSideAffecting[GetBankIdentity(gEffectBank) & 1] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD) && + !primary && gBattleCommunication[MOVE_EFFECT_BYTE] <= 7) + {gBattlescriptCurrInstr++; return;} + + //make sure at least ONE HP except payday and thief + if (gBattleMons[gEffectBank].hp == 0 && gBattleCommunication[MOVE_EFFECT_BYTE] != 0xB && gBattleCommunication[MOVE_EFFECT_BYTE] != 0x1F) + {gBattlescriptCurrInstr++; return;} + + if (gBattleMons[gEffectBank].status2 & STATUS2_SUBSTITUTE && AffectsUser != EffectAffectsUser) + {gBattlescriptCurrInstr++; return;} + + if (gBattleCommunication[MOVE_EFFECT_BYTE] <= 6) //status change + { + switch (gStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]) + { + case STATUS_SLEEP: + //check active uproar + if (gBattleMons[gEffectBank].ability != ABILITY_SOUNDPROOF) + { + for (gActiveBank = 0; gActiveBank < gNoOfAllBanks && !(gBattleMons[gActiveBank].status2 & STATUS2_UPROAR); gActiveBank++) {} + } + else + gActiveBank = gNoOfAllBanks; + if (gBattleMons[gEffectBank].status1) {break;} + if (gActiveBank != gNoOfAllBanks) {break;} //nice way of checking uproar... + if (gBattleMons[gEffectBank].ability == ABILITY_VITAL_SPIRIT) {break;} + if (gBattleMons[gEffectBank].ability == ABILITY_INSOMNIA) {break;} + + CancelMultiTurnMoves(gEffectBank); + StatusChanged = 1; + break; + case STATUS_POISON: + if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY && (primary == 1 || certain == 0x80)) + { + gLastUsedAbility = ABILITY_IMMUNITY; + RecordAbilityBattle(gEffectBank, ABILITY_IMMUNITY); + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + //_0801E664: + gBattlescriptCurrInstr = BattleScript_PSNPrevention; + if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD); + return; + } + else + {gBattleCommunication[MULTISTRING_CHOOSER] = 0; return;} + } + if ((gBattleMons[gEffectBank].type1 == TYPE_POISON || gBattleMons[gEffectBank].type2 == TYPE_POISON || gBattleMons[gEffectBank].type1 == TYPE_STEEL || gBattleMons[gEffectBank].type2 == TYPE_STEEL) + && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD) && (primary == 1 || certain == 0x80)) + { + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_PSNPrevention; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + return; + } + if (gBattleMons[gEffectBank].type1 == TYPE_POISON) {break;} + if (gBattleMons[gEffectBank].type2 == TYPE_POISON) {break;} + if (gBattleMons[gEffectBank].type1 == TYPE_STEEL) {break;} + if (gBattleMons[gEffectBank].type2 == TYPE_STEEL) {break;} + if (gBattleMons[gEffectBank].status1) {break;} + if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY) {break;} + + StatusChanged = 1; + break; + case STATUS_BURN: + if (gBattleMons[gEffectBank].ability == ABILITY_WATER_VEIL && (primary == 1 || certain == 0x80)) + { + gLastUsedAbility = ABILITY_WATER_VEIL; + RecordAbilityBattle(gEffectBank, ABILITY_WATER_VEIL); + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + //_0801E664: + gBattlescriptCurrInstr = BattleScript_BRNPrevention; + if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD); + return; + } + else + {gBattleCommunication[MULTISTRING_CHOOSER] = 0; return;} + } + if ((gBattleMons[gEffectBank].type1 == TYPE_FIRE || gBattleMons[gEffectBank].type2 == TYPE_FIRE) + && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD) && (primary == 1 || certain == 0x80)) + { + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_BRNPrevention; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + return; + } + if (gBattleMons[gEffectBank].type1 == TYPE_FIRE) {break;} + if (gBattleMons[gEffectBank].type2 == TYPE_FIRE) {break;} + if (gBattleMons[gEffectBank].ability == ABILITY_WATER_VEIL) {break;} + if (gBattleMons[gEffectBank].status1 == 0) {break;} + StatusChanged = 1; + break; + case STATUS_FREEZE: + if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY) {NoSunCanFreeze = 0;} + if (gBattleMons[gEffectBank].type1 == TYPE_ICE) {break;} + if (gBattleMons[gEffectBank].type2 == TYPE_ICE) {break;} + if (gBattleMons[gEffectBank].status1) {break;} + if (NoSunCanFreeze == 0) {break;} + if (gBattleMons[gEffectBank].ability == ABILITY_MAGMA_ARMOR) {break;} + + CancelMultiTurnMoves(gEffectBank); + StatusChanged = 1; + break; + case STATUS_PARALYSIS: + if (gBattleMons[gEffectBank].ability == ABILITY_LIMBER) + { + if ((primary == 1 || certain == 0x80)) + { + gLastUsedAbility = ABILITY_LIMBER; + RecordAbilityBattle(gEffectBank, ABILITY_LIMBER); + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + //_0801E664: + gBattlescriptCurrInstr = BattleScript_PRLZPrevention; + if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD); + return; + } + else + {gBattleCommunication[MULTISTRING_CHOOSER] = 0; return;} + } + else {break;} + } + if (gBattleMons[gEffectBank].status1) {break;} + StatusChanged = 1; + break; + case STATUS_TOXIC_POISON: + if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY && (primary == 1 || certain == 0x80)) + { + gLastUsedAbility = ABILITY_IMMUNITY; + RecordAbilityBattle(gEffectBank, ABILITY_IMMUNITY); + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + //_0801E664: + gBattlescriptCurrInstr = BattleScript_PSNPrevention; + if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD); + return; + } + else + {gBattleCommunication[MULTISTRING_CHOOSER] = 0; return;} + } + if ((gBattleMons[gEffectBank].type1 == TYPE_POISON || gBattleMons[gEffectBank].type2 == TYPE_POISON || gBattleMons[gEffectBank].type1 == TYPE_STEEL || gBattleMons[gEffectBank].type2 == TYPE_STEEL) + && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD) && (primary == 1 || certain == 0x80)) + { + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_PSNPrevention; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + return; + } + if (gBattleMons[gEffectBank].status1) {break;} + if (gBattleMons[gEffectBank].type1 != TYPE_POISON && + gBattleMons[gEffectBank].type2 != TYPE_POISON && + gBattleMons[gEffectBank].type1 != TYPE_STEEL && + gBattleMons[gEffectBank].type2 != TYPE_STEEL) + { + if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY) {break;} + gBattleMons[gEffectBank].status1 &= ~(0x9); //This gets (correctly) optimized out... + StatusChanged = 1; + break; + } + else + gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED; + break; + } + if (StatusChanged == 1) + { + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + if (gStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]] == STATUS_SLEEP) + gBattleMons[gEffectBank].status1 |= ((Random() & 3) + 2); + else + gBattleMons[gEffectBank].status1 |= gStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]; + gBattlescriptCurrInstr = gMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]]; + gActiveBank = gEffectBank; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gEffectBank].status1); + MarkBufferBankForExecution(gActiveBank); + if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD); + } + else + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + if (gBattleCommunication[MOVE_EFFECT_BYTE] == 2 || gBattleCommunication[MOVE_EFFECT_BYTE] == 6 || gBattleCommunication[MOVE_EFFECT_BYTE] == 5 || gBattleCommunication[MOVE_EFFECT_BYTE] == 3) + { + BATTLE_STRUCT->synchroniseEffect = gBattleCommunication[MOVE_EFFECT_BYTE]; + gHitMarker |= HITMARKER_SYNCHRONISE_EFFECT; + } + return; + } + else if (StatusChanged == 0) + {gBattlescriptCurrInstr++; return;} + } + else + { + if (gBattleMons[gEffectBank].status2 & gStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]) + { + gBattlescriptCurrInstr++; + return; + } + switch (gStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]) + { + case 7: //confusion + if (gBattleMons[gEffectBank].ability == ABILITY_OWN_TEMPO) + {gBattlescriptCurrInstr++; return;} + if (gBattleMons[gEffectBank].status2 & STATUS2_CONFUSION) + {gBattlescriptCurrInstr++; return;} + gBattleMons[gEffectBank].status2 |= (((Random()) % 0x4)) + 2; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = gMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]]; + break; + case 8: //flinch + if (gBattleMons[gEffectBank].ability == ABILITY_INNER_FOCUS) + { + if (primary == 1 || certain == 0x80) + { + gLastUsedAbility = ABILITY_INNER_FOCUS; + RecordAbilityBattle(gEffectBank, ABILITY_INNER_FOCUS); + gBattlescriptCurrInstr = BattleScript_FlinchPrevention; + return; + } + else + {gBattlescriptCurrInstr++; return;} + } + else + { + if (BankGetTurnOrder(gEffectBank) > gCurrentMoveTurn) + gBattleMons[gEffectBank].status2 |= gStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]; + gBattlescriptCurrInstr++; return; + } + break; + case 10: //uproar + if (gBattleMons[gEffectBank].status2 & STATUS2_UPROAR) + {gBattlescriptCurrInstr++; return;} + gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS; + gLockedMove[gEffectBank] = gCurrentMove; + gBattleMons[gEffectBank].status2 |= ((Random() & 3) + 2) << 4; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = gMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]]; + break; + case 11: //pay day + if (!(GetBankIdentity(gBankAttacker) & 1)) + { + u16 PayDay = gPaydayMoney; + gPaydayMoney += (gBattleMons[gBankAttacker].level * 5); + if (PayDay > gPaydayMoney) + gPaydayMoney = 0xFFFF; + } + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = gMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]]; + break; + case 9: //tri attack + if (gBattleMons[gEffectBank].status1) + {gBattlescriptCurrInstr++; return;} + gBattleCommunication[MOVE_EFFECT_BYTE] = Random() % 3 + 3; + SetMoveEffect(0, 0); + break; + case 12: //charging move + gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS; + gLockedMove[gEffectBank] = gCurrentMove; + gProtectStructs[gEffectBank].chargingTurn = 1; + gBattlescriptCurrInstr++; + break; + case 13: //wrap + if (gBattleMons[gEffectBank].status2 & STATUS2_WRAPPED) + {gBattlescriptCurrInstr++; return;} + gBattleMons[gEffectBank].status2 |= ((Random() & 3) + 2) << 0xD; + BATTLE_STRUCT->wrappedMove[gEffectBank*2] = (u8)gCurrentMove; + (1 + BATTLE_STRUCT->wrappedMove)[gEffectBank*2] = gCurrentMove >> 8; //don't ask. + BATTLE_STRUCT->wrappedBy[gEffectBank] = gBankAttacker; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = gMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]]; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + while (gBattleCommunication[MULTISTRING_CHOOSER] <= 4 + && gCurrentMove != gTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]]) + gBattleCommunication[MULTISTRING_CHOOSER]++; + break; + case 14: //25% recoil + gBattleMoveDamage = (gHP_dealt) / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = gMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]]; + break; + case 15 ... 21: //stat + 1 + if (ChangeStatBuffs(0x10, gBattleCommunication[MOVE_EFFECT_BYTE] + 0xF2, certain, 0)) {gBattlescriptCurrInstr++;} + else + { + BATTLE_STRUCT->animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & 0x3F; //TODO: the arg ptr is wrong by one + BATTLE_STRUCT->animArg2 = 0; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_StatUp; + } + break; + case 22 ... 28: //stat - 1 + if (ChangeStatBuffs(~(0x6f), gBattleCommunication[MOVE_EFFECT_BYTE] + 0xEB, certain, 0)) {gBattlescriptCurrInstr++;} //TODO: negation doesnt work correctly + else + { + BATTLE_STRUCT->animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & 0x3F; + BATTLE_STRUCT->animArg2 = 0; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_StatDown; + } + break; + case 39 ... 45: //stat + 2 + if (ChangeStatBuffs(0x20, gBattleCommunication[MOVE_EFFECT_BYTE] + 0xDA, certain, 0)) {gBattlescriptCurrInstr++;} + else + { + BATTLE_STRUCT->animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & 0x3F; + BATTLE_STRUCT->animArg2 = 0; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_StatUp; + } + break; + case 46 ... 52: //stat - 2 + if (ChangeStatBuffs(~(0x5f), gBattleCommunication[MOVE_EFFECT_BYTE] + 0xD3, certain, 0)) {gBattlescriptCurrInstr++;} + else + { + BATTLE_STRUCT->animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & 0x3F; + BATTLE_STRUCT->animArg2 = 0; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_StatDown; + } + break; + case 29: //recharge + gBattleMons[gEffectBank].status2 |= STATUS2_RECHARGE; + gDisableStructs[gEffectBank].rechargeCounter = 2; + gLockedMove[gEffectBank] = gCurrentMove; + gBattlescriptCurrInstr++; + break; + case 30: //rage + gBattleMons[gBankAttacker].status2 |= STATUS2_RAGE; + gBattlescriptCurrInstr++; + break; + case 31: //item steal + { + u8 side = GetBankSide(gBankAttacker); + if (GetBankSide(gBankAttacker) == 1 && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_LINK)) && gTrainerBattleOpponent != 0x400) + {gBattlescriptCurrInstr++; return;} + if (!(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_LINK)) && gTrainerBattleOpponent != 0x400 && (gWishFutureKnock.knockedOffPokes[side] & gBitTable[gBattlePartyID[gBankAttacker]])) + {gBattlescriptCurrInstr++; return;} + if (gBattleMons[gBankTarget].item && gBattleMons[gBankTarget].ability == ABILITY_STICKY_HOLD) + { + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_NoItemSteal; + gLastUsedAbility = gBattleMons[gBankTarget].ability; + RecordAbilityBattle(gBankTarget, gLastUsedAbility); + return; + } + if (gBattleMons[gBankAttacker].item) + {gBattlescriptCurrInstr++; return;} + if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY) + {gBattlescriptCurrInstr++; return;} + if (gBattleMons[gBankTarget].item == 0) + {gBattlescriptCurrInstr++; return;} + + gLastUsedItem = gBattleMons[gBankTarget].item; + unk_2000000[gBankAttacker * 2 + 0x160cc] = gLastUsedItem; + gBattleMons[gBankTarget].item = 0; + + gActiveBank = gBankAttacker; + EmitSetAttributes(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem); + MarkBufferBankForExecution(gBankAttacker); + + gActiveBank = gBankTarget; + EmitSetAttributes(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gBankTarget].item); + MarkBufferBankForExecution(gBankTarget); + + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_ItemSteal; + + ewram[gBankTarget * 2 + 0x160e8] = 0; + //STORE_CHOICEMOVE(gBankTarget, 0); + } + break; + case 32: //escape prevention + gBattleMons[gBankTarget].status2 |= STATUS2_RECHARGE; + gDisableStructs[gBankTarget].bankPreventingEscape = gBankAttacker; + gBattlescriptCurrInstr++; + break; + case 33: //nightmare + gBattleMons[gBankTarget].status2 |= STATUS2_NIGHTMARE; + gBattlescriptCurrInstr++; + break; + case 34: //ancientpower + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_AllStatsUp; + return; + case 35: //break free rapidspin + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_RapidSpinAway; + return; + case 36: //paralysis removal + if (gBattleMons[gBankTarget].status1 & STATUS_PARALYSIS) + { + gBattleMons[gBankTarget].status1 &= ~(STATUS_PARALYSIS); + gActiveBank = gBankTarget; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBankTarget].status1); + MarkBufferBankForExecution(gActiveBank); + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal; + } + else + {gBattlescriptCurrInstr++; return;} + break; + case 37: //superpower + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_AtkDefDown; + return; + case 38: //33% recoil + gBattleMoveDamage = gHP_dealt / 3; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = gMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]]; + break; + case 53: //thrash + if (!(gBattleMons[gEffectBank].status2 & STATUS2_LOCK_CONFUSE)) + { + gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS; + gLockedMove[gEffectBank] = gCurrentMove; + gBattleMons[gEffectBank].status2 |= (((Random() & 1) + 2) << 0xA); + } + else + {gBattlescriptCurrInstr++; return;} + break; + case 54: //knock off + if (gBattleMons[gEffectBank].ability == ABILITY_STICKY_HOLD) + { + if (gBattleMons[gEffectBank].item == 0) + {gBattlescriptCurrInstr++; return;} + gLastUsedAbility = ABILITY_STICKY_HOLD; + gBattlescriptCurrInstr = BattleScript_NoItemSteal; + RecordAbilityBattle(gEffectBank, ABILITY_STICKY_HOLD); + return; + } + if (gBattleMons[gEffectBank].item == 0) + {gBattlescriptCurrInstr++; return;} + else + { + u8 side = GetBankSide(gEffectBank); + gLastUsedItem = gBattleMons[gEffectBank].item; + gBattleMons[gEffectBank].item = 0; + gWishFutureKnock.knockedOffPokes[side] |= gBitTable[gBattlePartyID[gEffectBank]]; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_KnockedOff; + + ewram[gEffectBank * 2 + 0x160e8] = 0; + //STORE_CHOICEMOVE(gEffectBank, 0); + } + break; + case 59: //overheat + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_SAtkDown2; + return; + } + } +} +#else +__attribute__((naked)) +void SetMoveEffect(bool8 primary, u8 certainArg) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x8\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + lsls r1, 24\n\ + lsrs r5, r1, 24\n\ + movs r0, 0\n\ + mov r10, r0\n\ + movs r6, 0\n\ + movs r1, 0x1\n\ + str r1, [sp, 0x4]\n\ + ldr r1, _0801E430 @ =gBattleCommunication\n\ + ldrb r3, [r1, 0x3]\n\ + movs r0, 0x40\n\ + ands r0, r3\n\ + adds r7, r1, 0\n\ + cmp r0, 0\n\ + beq _0801E444\n\ + ldr r2, _0801E434 @ =gEffectBank\n\ + ldr r0, _0801E438 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + strb r0, [r2]\n\ + movs r0, 0xBF\n\ + ands r0, r3\n\ + strb r0, [r7, 0x3]\n\ + movs r6, 0x40\n\ + ldr r0, _0801E43C @ =0x02000000\n\ + ldr r1, _0801E440 @ =gBankTarget\n\ + b _0801E450\n\ + .align 2, 0\n\ +_0801E430: .4byte gBattleCommunication\n\ +_0801E434: .4byte gEffectBank\n\ +_0801E438: .4byte gBankAttacker\n\ +_0801E43C: .4byte 0x02000000\n\ +_0801E440: .4byte gBankTarget\n\ +_0801E444:\n\ + ldr r2, _0801E538 @ =gEffectBank\n\ + ldr r0, _0801E53C @ =gBankTarget\n\ + ldrb r0, [r0]\n\ + strb r0, [r2]\n\ + ldr r0, _0801E540 @ =0x02000000\n\ + ldr r1, _0801E544 @ =gBankAttacker\n\ +_0801E450:\n\ + ldrb r1, [r1]\n\ + ldr r3, _0801E548 @ =0x00016003\n\ + adds r0, r3\n\ + strb r1, [r0]\n\ + mov r8, r2\n\ + ldr r2, _0801E54C @ =gBattleMons\n\ + mov r0, r8\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r0, r2\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x13\n\ + bne _0801E48A\n\ + ldr r0, _0801E550 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801E48A\n\ + cmp r4, 0\n\ + bne _0801E48A\n\ + ldrb r0, [r7, 0x3]\n\ + cmp r0, 0x9\n\ + bhi _0801E48A\n\ + bl _0801F5DC\n\ +_0801E48A:\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + bl GetBankIdentity\n\ + ldr r2, _0801E554 @ =gSideAffecting\n\ + movs r1, 0x1\n\ + ands r1, r0\n\ + lsls r1, 1\n\ + adds r1, r2\n\ + ldrh r1, [r1]\n\ + movs r0, 0x20\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801E4C4\n\ + ldr r0, _0801E550 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801E4C4\n\ + cmp r4, 0\n\ + bne _0801E4C4\n\ + ldr r0, _0801E558 @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + cmp r0, 0x7\n\ + bhi _0801E4C4\n\ + bl _0801F5DC\n\ +_0801E4C4:\n\ + ldr r3, _0801E54C @ =gBattleMons\n\ + ldr r2, _0801E538 @ =gEffectBank\n\ + ldrb r1, [r2]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r0, r3\n\ + ldrh r0, [r0, 0x28]\n\ + mov r8, r2\n\ + mov r9, r3\n\ + cmp r0, 0\n\ + bne _0801E4EA\n\ + ldr r0, _0801E558 @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + cmp r0, 0xB\n\ + beq _0801E4EA\n\ + cmp r0, 0x1F\n\ + beq _0801E4EA\n\ + bl _0801F5DC\n\ +_0801E4EA:\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + mov r1, r9\n\ + adds r1, 0x50\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 17\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801E50C\n\ + cmp r6, 0x40\n\ + beq _0801E50C\n\ + bl _0801F5DC\n\ +_0801E50C:\n\ + ldr r0, _0801E558 @ =gBattleCommunication\n\ + ldrb r1, [r0, 0x3]\n\ + adds r7, r0, 0\n\ + cmp r1, 0x6\n\ + bls _0801E518\n\ + b _0801EB4A\n\ +_0801E518:\n\ + ldr r1, _0801E55C @ =gStatusFlagsForMoveEffects\n\ + ldrb r0, [r7, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + cmp r0, 0x10\n\ + bne _0801E528\n\ + b _0801E714\n\ +_0801E528:\n\ + cmp r0, 0x10\n\ + bhi _0801E560\n\ + cmp r0, 0x7\n\ + beq _0801E57A\n\ + cmp r0, 0x8\n\ + bne _0801E536\n\ + b _0801E630\n\ +_0801E536:\n\ + b _0801EA14\n\ + .align 2, 0\n\ +_0801E538: .4byte gEffectBank\n\ +_0801E53C: .4byte gBankTarget\n\ +_0801E540: .4byte 0x02000000\n\ +_0801E544: .4byte gBankAttacker\n\ +_0801E548: .4byte 0x00016003\n\ +_0801E54C: .4byte gBattleMons\n\ +_0801E550: .4byte gHitMarker\n\ +_0801E554: .4byte gSideAffecting\n\ +_0801E558: .4byte gBattleCommunication\n\ +_0801E55C: .4byte gStatusFlagsForMoveEffects\n\ +_0801E560:\n\ + cmp r0, 0x40\n\ + bne _0801E566\n\ + b _0801E888\n\ +_0801E566:\n\ + cmp r0, 0x40\n\ + bhi _0801E572\n\ + cmp r0, 0x20\n\ + bne _0801E570\n\ + b _0801E7EA\n\ +_0801E570:\n\ + b _0801EA14\n\ +_0801E572:\n\ + cmp r0, 0x80\n\ + bne _0801E578\n\ + b _0801E8E4\n\ +_0801E578:\n\ + b _0801EA14\n\ +_0801E57A:\n\ + mov r3, r8\n\ + ldrb r1, [r3]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + add r0, r9\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x2B\n\ + beq _0801E5DC\n\ + ldr r0, _0801E5D4 @ =gActiveBank\n\ + movs r1, 0\n\ + strb r1, [r0]\n\ + ldr r1, _0801E5D8 @ =gNoOfAllBanks\n\ + ldrb r3, [r1]\n\ + adds r7, r0, 0\n\ + mov r12, r1\n\ + cmp r3, 0\n\ + beq _0801E5E8\n\ + mov r4, r9\n\ + ldr r0, [r4, 0x50]\n\ + movs r1, 0x70\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801E5E8\n\ + adds r1, r7, 0\n\ + mov r6, r9\n\ + adds r6, 0x50\n\ + movs r5, 0x58\n\ + movs r4, 0x70\n\ +_0801E5B4:\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, r3\n\ + bcs _0801E5E8\n\ + ldrb r0, [r7]\n\ + muls r0, r5\n\ + adds r0, r6\n\ + ldr r0, [r0]\n\ + ands r0, r4\n\ + cmp r0, 0\n\ + beq _0801E5B4\n\ + b _0801E5E8\n\ + .align 2, 0\n\ +_0801E5D4: .4byte gActiveBank\n\ +_0801E5D8: .4byte gNoOfAllBanks\n\ +_0801E5DC:\n\ + ldr r0, _0801E628 @ =gActiveBank\n\ + ldr r2, _0801E62C @ =gNoOfAllBanks\n\ + ldrb r1, [r2]\n\ + strb r1, [r0]\n\ + adds r7, r0, 0\n\ + mov r12, r2\n\ +_0801E5E8:\n\ + mov r0, r8\n\ + ldrb r2, [r0]\n\ + movs r0, 0x58\n\ + adds r1, r2, 0\n\ + muls r1, r0\n\ + mov r0, r9\n\ + adds r0, 0x4C\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _0801E600\n\ + b _0801EA14\n\ +_0801E600:\n\ + ldrb r0, [r7]\n\ + mov r3, r12\n\ + ldrb r3, [r3]\n\ + cmp r0, r3\n\ + beq _0801E60C\n\ + b _0801EA14\n\ +_0801E60C:\n\ + mov r4, r9\n\ + adds r0, r1, r4\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x48\n\ + bne _0801E61A\n\ + b _0801EA14\n\ +_0801E61A:\n\ + cmp r0, 0xF\n\ + bne _0801E620\n\ + b _0801EA14\n\ +_0801E620:\n\ + adds r0, r2, 0\n\ + bl CancelMultiTurnMoves\n\ + b _0801EA04\n\ + .align 2, 0\n\ +_0801E628: .4byte gActiveBank\n\ +_0801E62C: .4byte gNoOfAllBanks\n\ +_0801E630:\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + add r0, r9\n\ + adds r0, 0x20\n\ + ldrb r1, [r0]\n\ + cmp r1, 0x11\n\ + bne _0801E688\n\ + cmp r4, 0x1\n\ + beq _0801E64A\n\ + cmp r5, 0x80\n\ + bne _0801E688\n\ +_0801E64A:\n\ + ldr r0, _0801E678 @ =gLastUsedAbility\n\ + strb r1, [r0]\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + movs r1, 0x11\n\ + bl RecordAbilityBattle\n\ + ldr r4, _0801E67C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801E680 @ =BattleScript_PSNPrevention\n\ +_0801E664:\n\ + str r0, [r4]\n\ + ldr r2, _0801E684 @ =gHitMarker\n\ + ldr r1, [r2]\n\ + movs r0, 0x80\n\ + lsls r0, 6\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801E676\n\ + b _0801E928\n\ +_0801E676:\n\ + b _0801E94C\n\ + .align 2, 0\n\ +_0801E678: .4byte gLastUsedAbility\n\ +_0801E67C: .4byte gBattlescriptCurrInstr\n\ +_0801E680: .4byte BattleScript_PSNPrevention\n\ +_0801E684: .4byte gHitMarker\n\ +_0801E688:\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + movs r1, 0x58\n\ + muls r0, r1\n\ + add r0, r9\n\ + adds r1, r0, 0\n\ + adds r1, 0x21\n\ + ldrb r1, [r1]\n\ + cmp r1, 0x3\n\ + beq _0801E6AC\n\ + adds r0, 0x22\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x3\n\ + beq _0801E6AC\n\ + cmp r1, 0x8\n\ + beq _0801E6AC\n\ + cmp r0, 0x8\n\ + bne _0801E6C6\n\ +_0801E6AC:\n\ + ldr r0, _0801E710 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801E6C6\n\ + cmp r4, 0x1\n\ + bne _0801E6C0\n\ + b _0801E98C\n\ +_0801E6C0:\n\ + cmp r5, 0x80\n\ + bne _0801E6C6\n\ + b _0801E98C\n\ +_0801E6C6:\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + movs r0, 0x58\n\ + muls r1, r0\n\ + mov r4, r9\n\ + adds r3, r1, r4\n\ + adds r0, r3, 0\n\ + adds r0, 0x21\n\ + ldrb r4, [r0]\n\ + cmp r4, 0x3\n\ + bne _0801E6DE\n\ + b _0801EA14\n\ +_0801E6DE:\n\ + adds r0, 0x1\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x3\n\ + bne _0801E6E8\n\ + b _0801EA14\n\ +_0801E6E8:\n\ + cmp r4, 0x8\n\ + bne _0801E6EE\n\ + b _0801EA14\n\ +_0801E6EE:\n\ + cmp r0, 0x8\n\ + bne _0801E6F4\n\ + b _0801EA14\n\ +_0801E6F4:\n\ + mov r0, r9\n\ + adds r0, 0x4C\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _0801E702\n\ + b _0801EA14\n\ +_0801E702:\n\ + adds r0, r3, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x11\n\ + bne _0801E70E\n\ + b _0801EA14\n\ +_0801E70E:\n\ + b _0801EA04\n\ + .align 2, 0\n\ +_0801E710: .4byte gHitMarker\n\ +_0801E714:\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + add r0, r9\n\ + adds r0, 0x20\n\ + ldrb r1, [r0]\n\ + cmp r1, 0x29\n\ + bne _0801E758\n\ + cmp r4, 0x1\n\ + beq _0801E72E\n\ + cmp r5, 0x80\n\ + bne _0801E758\n\ +_0801E72E:\n\ + ldr r0, _0801E74C @ =gLastUsedAbility\n\ + strb r1, [r0]\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + movs r1, 0x29\n\ + bl RecordAbilityBattle\n\ + ldr r4, _0801E750 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801E754 @ =BattleScript_BRNPrevention\n\ + b _0801E664\n\ + .align 2, 0\n\ +_0801E74C: .4byte gLastUsedAbility\n\ +_0801E750: .4byte gBattlescriptCurrInstr\n\ +_0801E754: .4byte BattleScript_BRNPrevention\n\ +_0801E758:\n\ + mov r0, r8\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + mov r2, r9\n\ + adds r1, r0, r2\n\ + adds r0, r1, 0\n\ + adds r0, 0x21\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xA\n\ + beq _0801E778\n\ + adds r0, r1, 0\n\ + adds r0, 0x22\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xA\n\ + bne _0801E7A8\n\ +_0801E778:\n\ + ldr r0, _0801E79C @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801E7A8\n\ + cmp r4, 0x1\n\ + beq _0801E78E\n\ + cmp r5, 0x80\n\ + bne _0801E7A8\n\ +_0801E78E:\n\ + ldr r4, _0801E7A0 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801E7A4 @ =BattleScript_BRNPrevention\n\ + b _0801E998\n\ + .align 2, 0\n\ +_0801E79C: .4byte gHitMarker\n\ +_0801E7A0: .4byte gBattlescriptCurrInstr\n\ +_0801E7A4: .4byte BattleScript_BRNPrevention\n\ +_0801E7A8:\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + movs r1, 0x58\n\ + adds r2, r0, 0\n\ + muls r2, r1\n\ + mov r4, r9\n\ + adds r1, r2, r4\n\ + adds r0, r1, 0\n\ + adds r0, 0x21\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xA\n\ + bne _0801E7C2\n\ + b _0801EA14\n\ +_0801E7C2:\n\ + adds r0, r1, 0\n\ + adds r0, 0x22\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xA\n\ + bne _0801E7CE\n\ + b _0801EA14\n\ +_0801E7CE:\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x29\n\ + bne _0801E7DA\n\ + b _0801EA14\n\ +_0801E7DA:\n\ + mov r0, r9\n\ + adds r0, 0x4C\n\ + adds r0, r2, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _0801E7E8\n\ + b _0801EA14\n\ +_0801E7E8:\n\ + b _0801EA04\n\ +_0801E7EA:\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + movs r0, 0x13\n\ + movs r1, 0\n\ + movs r2, 0xD\n\ + movs r3, 0\n\ + bl AbilityBattleEffects\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0\n\ + bne _0801E826\n\ + str r0, [sp]\n\ + movs r0, 0x13\n\ + movs r1, 0\n\ + movs r2, 0x4D\n\ + movs r3, 0\n\ + bl AbilityBattleEffects\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _0801E826\n\ + ldr r0, _0801E87C @ =gBattleWeather\n\ + ldrh r1, [r0]\n\ + movs r0, 0x60\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801E826\n\ + movs r1, 0\n\ + str r1, [sp, 0x4]\n\ +_0801E826:\n\ + ldr r4, _0801E880 @ =gBattleMons\n\ + ldr r0, _0801E884 @ =gEffectBank\n\ + ldrb r3, [r0]\n\ + movs r0, 0x58\n\ + adds r2, r3, 0\n\ + muls r2, r0\n\ + adds r1, r2, r4\n\ + adds r0, r1, 0\n\ + adds r0, 0x21\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xF\n\ + bne _0801E840\n\ + b _0801EA14\n\ +_0801E840:\n\ + adds r0, r1, 0\n\ + adds r0, 0x22\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xF\n\ + bne _0801E84C\n\ + b _0801EA14\n\ +_0801E84C:\n\ + adds r0, r4, 0\n\ + adds r0, 0x4C\n\ + adds r0, r2, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _0801E85A\n\ + b _0801EA14\n\ +_0801E85A:\n\ + ldr r2, [sp, 0x4]\n\ + cmp r2, 0\n\ + bne _0801E862\n\ + b _0801EA14\n\ +_0801E862:\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x28\n\ + bne _0801E86E\n\ + b _0801EA14\n\ +_0801E86E:\n\ + adds r0, r3, 0\n\ + bl CancelMultiTurnMoves\n\ + movs r3, 0x1\n\ + mov r10, r3\n\ + b _0801EA14\n\ + .align 2, 0\n\ +_0801E87C: .4byte gBattleWeather\n\ +_0801E880: .4byte gBattleMons\n\ +_0801E884: .4byte gEffectBank\n\ +_0801E888:\n\ + mov r0, r8\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r1, r0\n\ + mov r2, r9\n\ + adds r0, r1, r2\n\ + adds r0, 0x20\n\ + ldrb r2, [r0]\n\ + cmp r2, 0x7\n\ + bne _0801E8D0\n\ + cmp r4, 0x1\n\ + beq _0801E8A6\n\ + cmp r5, 0x80\n\ + beq _0801E8A6\n\ + b _0801EA14\n\ +_0801E8A6:\n\ + ldr r0, _0801E8C4 @ =gLastUsedAbility\n\ + strb r2, [r0]\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + movs r1, 0x7\n\ + bl RecordAbilityBattle\n\ + ldr r4, _0801E8C8 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801E8CC @ =BattleScript_PRLZPrevention\n\ + b _0801E664\n\ + .align 2, 0\n\ +_0801E8C4: .4byte gLastUsedAbility\n\ +_0801E8C8: .4byte gBattlescriptCurrInstr\n\ +_0801E8CC: .4byte BattleScript_PRLZPrevention\n\ +_0801E8D0:\n\ + mov r0, r9\n\ + adds r0, 0x4C\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _0801E8DE\n\ + b _0801EA14\n\ +_0801E8DE:\n\ + movs r4, 0x1\n\ + mov r10, r4\n\ + b _0801EA14\n\ +_0801E8E4:\n\ + mov r0, r8\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + add r0, r9\n\ + adds r0, 0x20\n\ + ldrb r1, [r0]\n\ + cmp r1, 0x11\n\ + bne _0801E952\n\ + cmp r4, 0x1\n\ + beq _0801E8FE\n\ + cmp r5, 0x80\n\ + bne _0801E952\n\ +_0801E8FE:\n\ + ldr r0, _0801E938 @ =gLastUsedAbility\n\ + strb r1, [r0]\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + movs r1, 0x11\n\ + bl RecordAbilityBattle\n\ + ldr r4, _0801E93C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801E940 @ =BattleScript_PSNPrevention\n\ + str r0, [r4]\n\ + ldr r2, _0801E944 @ =gHitMarker\n\ + ldr r1, [r2]\n\ + movs r0, 0x80\n\ + lsls r0, 6\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801E94C\n\ +_0801E928:\n\ + movs r0, 0x1\n\ + strb r0, [r7, 0x5]\n\ + ldr r0, _0801E948 @ =0xffffdfff\n\ + ands r1, r0\n\ + str r1, [r2]\n\ + bl _0801F5FA\n\ + .align 2, 0\n\ +_0801E938: .4byte gLastUsedAbility\n\ +_0801E93C: .4byte gBattlescriptCurrInstr\n\ +_0801E940: .4byte BattleScript_PSNPrevention\n\ +_0801E944: .4byte gHitMarker\n\ +_0801E948: .4byte 0xffffdfff\n\ +_0801E94C:\n\ + strb r0, [r7, 0x5]\n\ + bl _0801F5FA\n\ +_0801E952:\n\ + mov r2, r8\n\ + ldrb r0, [r2]\n\ + movs r1, 0x58\n\ + muls r0, r1\n\ + add r0, r9\n\ + adds r1, r0, 0\n\ + adds r1, 0x21\n\ + ldrb r1, [r1]\n\ + cmp r1, 0x3\n\ + beq _0801E976\n\ + adds r0, 0x22\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x3\n\ + beq _0801E976\n\ + cmp r1, 0x8\n\ + beq _0801E976\n\ + cmp r0, 0x8\n\ + bne _0801E9B4\n\ +_0801E976:\n\ + ldr r0, _0801E9A4 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 6\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801E9B4\n\ + cmp r4, 0x1\n\ + beq _0801E98C\n\ + cmp r5, 0x80\n\ + bne _0801E9B4\n\ +_0801E98C:\n\ + ldr r4, _0801E9A8 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801E9AC @ =BattleScript_PSNPrevention\n\ +_0801E998:\n\ + str r0, [r4]\n\ + ldr r1, _0801E9B0 @ =gBattleCommunication\n\ + movs r0, 0x2\n\ + strb r0, [r1, 0x5]\n\ + bl _0801F5FA\n\ + .align 2, 0\n\ +_0801E9A4: .4byte gHitMarker\n\ +_0801E9A8: .4byte gBattlescriptCurrInstr\n\ +_0801E9AC: .4byte BattleScript_PSNPrevention\n\ +_0801E9B0: .4byte gBattleCommunication\n\ +_0801E9B4:\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + movs r6, 0x58\n\ + muls r0, r6\n\ + mov r2, r9\n\ + adds r2, 0x4C\n\ + adds r5, r0, r2\n\ + ldr r4, [r5]\n\ + cmp r4, 0\n\ + bne _0801EA14\n\ + mov r3, r9\n\ + adds r1, r0, r3\n\ + adds r0, r1, 0\n\ + adds r0, 0x21\n\ + ldrb r3, [r0]\n\ + cmp r3, 0x3\n\ + beq _0801EA0A\n\ + adds r0, 0x1\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x3\n\ + beq _0801EA0A\n\ + cmp r3, 0x8\n\ + beq _0801EA0A\n\ + cmp r0, 0x8\n\ + beq _0801EA0A\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x11\n\ + beq _0801EA14\n\ + mov r4, r8\n\ + ldrb r0, [r4]\n\ + adds r1, r0, 0\n\ + muls r1, r6\n\ + adds r1, r2\n\ + ldr r0, [r1]\n\ + movs r2, 0x9\n\ + negs r2, r2\n\ + ands r0, r2\n\ + str r0, [r1]\n\ +_0801EA04:\n\ + movs r0, 0x1\n\ + mov r10, r0\n\ + b _0801EA14\n\ +_0801EA0A:\n\ + ldr r0, _0801EA58 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r2, 0x8\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ +_0801EA14:\n\ + mov r1, r10\n\ + cmp r1, 0x1\n\ + beq _0801EA1C\n\ + b _0801EB3C\n\ +_0801EA1C:\n\ + ldr r0, _0801EA5C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r0]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r1, _0801EA60 @ =gStatusFlagsForMoveEffects\n\ + ldr r0, _0801EA64 @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r3, [r0]\n\ + cmp r3, 0x7\n\ + bne _0801EA70\n\ + bl Random\n\ + ldr r2, _0801EA68 @ =gBattleMons\n\ + ldr r1, _0801EA6C @ =gEffectBank\n\ + ldrb r3, [r1]\n\ + movs r1, 0x58\n\ + muls r3, r1\n\ + adds r2, 0x4C\n\ + adds r3, r2\n\ + movs r1, 0x3\n\ + ands r1, r0\n\ + adds r1, 0x2\n\ + ldr r0, [r3]\n\ + orrs r0, r1\n\ + str r0, [r3]\n\ + b _0801EA84\n\ + .align 2, 0\n\ +_0801EA58: .4byte gBattleMoveFlags\n\ +_0801EA5C: .4byte gBattlescriptCurrInstr\n\ +_0801EA60: .4byte gStatusFlagsForMoveEffects\n\ +_0801EA64: .4byte gBattleCommunication\n\ +_0801EA68: .4byte gBattleMons\n\ +_0801EA6C: .4byte gEffectBank\n\ +_0801EA70:\n\ + ldr r2, _0801EAD4 @ =gBattleMons\n\ + ldr r0, _0801EAD8 @ =gEffectBank\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r1, r0\n\ + adds r2, 0x4C\n\ + adds r1, r2\n\ + ldr r0, [r1]\n\ + orrs r0, r3\n\ + str r0, [r1]\n\ +_0801EA84:\n\ + ldr r2, _0801EADC @ =gBattlescriptCurrInstr\n\ + ldr r1, _0801EAE0 @ =gMoveEffectBS_Ptrs\n\ + ldr r5, _0801EAE4 @ =gBattleCommunication\n\ + ldrb r0, [r5, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + str r0, [r2]\n\ + ldr r4, _0801EAE8 @ =gActiveBank\n\ + ldr r1, _0801EAD8 @ =gEffectBank\n\ + ldrb r0, [r1]\n\ + strb r0, [r4]\n\ + ldrb r1, [r1]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + ldr r1, _0801EAEC @ =gUnknown_02024ACC\n\ + adds r0, r1\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x28\n\ + movs r2, 0\n\ + movs r3, 0x4\n\ + bl EmitSetAttributes\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + ldr r2, _0801EAF0 @ =gHitMarker\n\ + ldr r1, [r2]\n\ + movs r0, 0x80\n\ + lsls r0, 6\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801EAF8\n\ + movs r0, 0x1\n\ + strb r0, [r5, 0x5]\n\ + ldr r0, _0801EAF4 @ =0xffffdfff\n\ + ands r1, r0\n\ + str r1, [r2]\n\ + b _0801EAFA\n\ + .align 2, 0\n\ +_0801EAD4: .4byte gBattleMons\n\ +_0801EAD8: .4byte gEffectBank\n\ +_0801EADC: .4byte gBattlescriptCurrInstr\n\ +_0801EAE0: .4byte gMoveEffectBS_Ptrs\n\ +_0801EAE4: .4byte gBattleCommunication\n\ +_0801EAE8: .4byte gActiveBank\n\ +_0801EAEC: .4byte gUnknown_02024ACC\n\ +_0801EAF0: .4byte gHitMarker\n\ +_0801EAF4: .4byte 0xffffdfff\n\ +_0801EAF8:\n\ + strb r0, [r5, 0x5]\n\ +_0801EAFA:\n\ + ldr r0, _0801EB2C @ =gBattleCommunication\n\ + ldrb r2, [r0, 0x3]\n\ + adds r7, r0, 0\n\ + cmp r2, 0x2\n\ + beq _0801EB14\n\ + cmp r2, 0x6\n\ + beq _0801EB14\n\ + cmp r2, 0x5\n\ + beq _0801EB14\n\ + cmp r2, 0x3\n\ + beq _0801EB14\n\ + bl _0801F5FA\n\ +_0801EB14:\n\ + ldr r0, _0801EB30 @ =0x02000000\n\ + ldrb r1, [r7, 0x3]\n\ + ldr r2, _0801EB34 @ =0x000160ca\n\ + adds r0, r2\n\ + strb r1, [r0]\n\ + ldr r2, _0801EB38 @ =gHitMarker\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 7\n\ + bl _0801F4F2\n\ + .align 2, 0\n\ +_0801EB2C: .4byte gBattleCommunication\n\ +_0801EB30: .4byte 0x02000000\n\ +_0801EB34: .4byte 0x000160ca\n\ +_0801EB38: .4byte gHitMarker\n\ +_0801EB3C:\n\ + mov r3, r10\n\ + cmp r3, 0\n\ + beq _0801EB46\n\ + bl _0801F5FA\n\ +_0801EB46:\n\ + bl _0801F5DC\n\ +_0801EB4A:\n\ + mov r0, r8\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r1, r0\n\ + mov r0, r9\n\ + adds r0, 0x50\n\ + adds r1, r0\n\ + ldr r2, _0801EB84 @ =gStatusFlagsForMoveEffects\n\ + ldrb r3, [r7, 0x3]\n\ + lsls r0, r3, 2\n\ + adds r0, r2\n\ + ldr r1, [r1]\n\ + ldr r0, [r0]\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + beq _0801EB6E\n\ + bl _0801F5DC\n\ +_0801EB6E:\n\ + subs r0, r3, 0x7\n\ + cmp r0, 0x34\n\ + bls _0801EB78\n\ + bl _0801F5FA\n\ +_0801EB78:\n\ + lsls r0, 2\n\ + ldr r1, _0801EB88 @ =_0801EB8C\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_0801EB84: .4byte gStatusFlagsForMoveEffects\n\ +_0801EB88: .4byte _0801EB8C\n\ + .align 2, 0\n\ +_0801EB8C:\n\ + .4byte _0801EC60\n\ + .4byte _0801ECD4\n\ + .4byte _0801EE4C\n\ + .4byte _0801ED60\n\ + .4byte _0801EDDC\n\ + .4byte _0801EE84\n\ + .4byte _0801EECC\n\ + .4byte _0801EFA8\n\ + .4byte _0801EFEC\n\ + .4byte _0801EFEC\n\ + .4byte _0801EFEC\n\ + .4byte _0801EFEC\n\ + .4byte _0801EFEC\n\ + .4byte _0801EFEC\n\ + .4byte _0801EFEC\n\ + .4byte _0801F040\n\ + .4byte _0801F040\n\ + .4byte _0801F040\n\ + .4byte _0801F040\n\ + .4byte _0801F040\n\ + .4byte _0801F040\n\ + .4byte _0801F040\n\ + .4byte _0801F13C\n\ + .4byte _0801F184\n\ + .4byte _0801F1A4\n\ + .4byte _0801F364\n\ + .4byte _0801F3A0\n\ + .4byte _0801F3BC\n\ + .4byte _0801F3D4\n\ + .4byte _0801F3EC\n\ + .4byte _0801F44C\n\ + .4byte _0801F464\n\ + .4byte _0801F094\n\ + .4byte _0801F094\n\ + .4byte _0801F094\n\ + .4byte _0801F094\n\ + .4byte _0801F094\n\ + .4byte _0801F094\n\ + .4byte _0801F094\n\ + .4byte _0801F0E8\n\ + .4byte _0801F0E8\n\ + .4byte _0801F0E8\n\ + .4byte _0801F0E8\n\ + .4byte _0801F0E8\n\ + .4byte _0801F0E8\n\ + .4byte _0801F0E8\n\ + .4byte _0801F4A8\n\ + .4byte _0801F500\n\ + .4byte _0801F5FA\n\ + .4byte _0801F5FA\n\ + .4byte _0801F5FA\n\ + .4byte _0801F5FA\n\ + .4byte _0801F5EC\n\ +_0801EC60:\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + movs r5, 0x58\n\ + adds r1, r0, 0\n\ + muls r1, r5\n\ + mov r2, r9\n\ + adds r0, r1, r2\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x14\n\ + bne _0801EC7A\n\ + bl _0801F5DC\n\ +_0801EC7A:\n\ + mov r4, r9\n\ + adds r4, 0x50\n\ + adds r0, r1, r4\n\ + ldr r0, [r0]\n\ + movs r1, 0x7\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801EC8E\n\ + bl _0801F5DC\n\ +_0801EC8E:\n\ + bl Random\n\ + mov r3, r8\n\ + ldrb r1, [r3]\n\ + adds r2, r1, 0\n\ + muls r2, r5\n\ + adds r2, r4\n\ + lsls r0, 16\n\ + movs r1, 0xC0\n\ + lsls r1, 10\n\ + ands r1, r0\n\ + lsrs r1, 16\n\ + adds r1, 0x2\n\ + ldr r0, [r2]\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + ldr r4, _0801ECC8 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r1, _0801ECCC @ =gMoveEffectBS_Ptrs\n\ + ldr r0, _0801ECD0 @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + bl _0801F5F8\n\ + .align 2, 0\n\ +_0801ECC8: .4byte gBattlescriptCurrInstr\n\ +_0801ECCC: .4byte gMoveEffectBS_Ptrs\n\ +_0801ECD0: .4byte gBattleCommunication\n\ +_0801ECD4:\n\ + mov r0, r8\n\ + ldrb r2, [r0]\n\ + movs r6, 0x58\n\ + adds r0, r2, 0\n\ + muls r0, r6\n\ + add r0, r9\n\ + adds r0, 0x20\n\ + ldrb r1, [r0]\n\ + cmp r1, 0x27\n\ + bne _0801ED18\n\ + cmp r4, 0x1\n\ + beq _0801ECF4\n\ + cmp r5, 0x80\n\ + beq _0801ECF4\n\ + bl _0801F5DC\n\ +_0801ECF4:\n\ + ldr r0, _0801ED0C @ =gLastUsedAbility\n\ + strb r1, [r0]\n\ + mov r1, r8\n\ + ldrb r0, [r1]\n\ + movs r1, 0x27\n\ + bl RecordAbilityBattle\n\ + ldr r1, _0801ED10 @ =gBattlescriptCurrInstr\n\ + ldr r0, _0801ED14 @ =BattleScript_FlinchPrevention\n\ + str r0, [r1]\n\ + bl _0801F5FA\n\ + .align 2, 0\n\ +_0801ED0C: .4byte gLastUsedAbility\n\ +_0801ED10: .4byte gBattlescriptCurrInstr\n\ +_0801ED14: .4byte BattleScript_FlinchPrevention\n\ +_0801ED18:\n\ + adds r0, r2, 0\n\ + bl BankGetTurnOrder\n\ + ldr r1, _0801ED54 @ =gCurrentMoveTurn\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + ldrb r1, [r1]\n\ + cmp r0, r1\n\ + bhi _0801ED2E\n\ + bl _0801F5DC\n\ +_0801ED2E:\n\ + mov r2, r8\n\ + ldrb r0, [r2]\n\ + adds r2, r0, 0\n\ + muls r2, r6\n\ + mov r0, r9\n\ + adds r0, 0x50\n\ + adds r2, r0\n\ + ldr r1, _0801ED58 @ =gStatusFlagsForMoveEffects\n\ + ldr r0, _0801ED5C @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r1, [r2]\n\ + ldr r0, [r0]\n\ + orrs r1, r0\n\ + str r1, [r2]\n\ + bl _0801F5DC\n\ + .align 2, 0\n\ +_0801ED54: .4byte gCurrentMoveTurn\n\ +_0801ED58: .4byte gStatusFlagsForMoveEffects\n\ +_0801ED5C: .4byte gBattleCommunication\n\ +_0801ED60:\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + movs r5, 0x58\n\ + muls r0, r5\n\ + mov r4, r9\n\ + adds r4, 0x50\n\ + adds r2, r0, r4\n\ + ldr r1, [r2]\n\ + movs r0, 0x70\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801ED7C\n\ + bl _0801F5DC\n\ +_0801ED7C:\n\ + movs r0, 0x80\n\ + lsls r0, 5\n\ + orrs r1, r0\n\ + str r1, [r2]\n\ + ldr r1, _0801EDC8 @ =gLockedMove\n\ + ldrb r0, [r3]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldr r1, _0801EDCC @ =gCurrentMove\n\ + ldrh r1, [r1]\n\ + strh r1, [r0]\n\ + bl Random\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + adds r2, r1, 0\n\ + muls r2, r5\n\ + adds r2, r4\n\ + movs r1, 0x3\n\ + ands r1, r0\n\ + adds r1, 0x2\n\ + lsls r1, 4\n\ + ldr r0, [r2]\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + ldr r4, _0801EDD0 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r1, _0801EDD4 @ =gMoveEffectBS_Ptrs\n\ + ldr r0, _0801EDD8 @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + bl _0801F5F8\n\ + .align 2, 0\n\ +_0801EDC8: .4byte gLockedMove\n\ +_0801EDCC: .4byte gCurrentMove\n\ +_0801EDD0: .4byte gBattlescriptCurrInstr\n\ +_0801EDD4: .4byte gMoveEffectBS_Ptrs\n\ +_0801EDD8: .4byte gBattleCommunication\n\ +_0801EDDC:\n\ + ldr r5, _0801EE30 @ =gBankAttacker\n\ + ldrb r0, [r5]\n\ + bl GetBankIdentity\n\ + movs r1, 0x1\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + bne _0801EE14\n\ + ldr r4, _0801EE34 @ =gPaydayMoney\n\ + ldrh r3, [r4]\n\ + ldr r2, _0801EE38 @ =gBattleMons\n\ + ldrb r1, [r5]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r0, r2\n\ + adds r0, 0x2A\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + adds r0, r3, r0\n\ + strh r0, [r4]\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r3, r0\n\ + bls _0801EE14\n\ + ldr r3, _0801EE3C @ =0x0000ffff\n\ + adds r0, r3, 0\n\ + strh r0, [r4]\n\ +_0801EE14:\n\ + ldr r4, _0801EE40 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r1, _0801EE44 @ =gMoveEffectBS_Ptrs\n\ + ldr r0, _0801EE48 @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + bl _0801F5F8\n\ + .align 2, 0\n\ +_0801EE30: .4byte gBankAttacker\n\ +_0801EE34: .4byte gPaydayMoney\n\ +_0801EE38: .4byte gBattleMons\n\ +_0801EE3C: .4byte 0x0000ffff\n\ +_0801EE40: .4byte gBattlescriptCurrInstr\n\ +_0801EE44: .4byte gMoveEffectBS_Ptrs\n\ +_0801EE48: .4byte gBattleCommunication\n\ +_0801EE4C:\n\ + mov r4, r8\n\ + ldrb r1, [r4]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + mov r1, r9\n\ + adds r1, 0x4C\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _0801EE62\n\ + b _0801F5DC\n\ +_0801EE62:\n\ + bl Random\n\ + ldr r4, _0801EE80 @ =gBattleCommunication\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x3\n\ + bl __umodsi3\n\ + adds r0, 0x3\n\ + strb r0, [r4, 0x3]\n\ + movs r0, 0\n\ + movs r1, 0\n\ + bl SetMoveEffect\n\ + b _0801F5FA\n\ + .align 2, 0\n\ +_0801EE80: .4byte gBattleCommunication\n\ +_0801EE84:\n\ + mov r0, r8\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + adds r2, r1, 0\n\ + muls r2, r0\n\ + mov r0, r9\n\ + adds r0, 0x50\n\ + adds r2, r0\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 5\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + ldr r1, _0801EEC0 @ =gLockedMove\n\ + mov r2, r8\n\ + ldrb r0, [r2]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldr r1, _0801EEC4 @ =gCurrentMove\n\ + ldrh r1, [r1]\n\ + strh r1, [r0]\n\ + ldr r0, _0801EEC8 @ =gProtectStructs\n\ + ldrb r1, [r2]\n\ + lsls r1, 4\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + movs r2, 0x4\n\ + orrs r0, r2\n\ + strb r0, [r1, 0x1]\n\ + b _0801F5DC\n\ + .align 2, 0\n\ +_0801EEC0: .4byte gLockedMove\n\ +_0801EEC4: .4byte gCurrentMove\n\ +_0801EEC8: .4byte gProtectStructs\n\ +_0801EECC:\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + movs r6, 0x58\n\ + muls r0, r6\n\ + mov r4, r9\n\ + adds r4, 0x50\n\ + adds r0, r4\n\ + ldr r5, [r0]\n\ + movs r0, 0xE0\n\ + lsls r0, 8\n\ + ands r5, r0\n\ + cmp r5, 0\n\ + beq _0801EEE8\n\ + b _0801F5DC\n\ +_0801EEE8:\n\ + bl Random\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + adds r2, r1, 0\n\ + muls r2, r6\n\ + adds r2, r4\n\ + movs r1, 0x3\n\ + ands r1, r0\n\ + adds r1, 0x3\n\ + lsls r1, 13\n\ + ldr r0, [r2]\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + ldr r2, _0801EF80 @ =0x02000000\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + lsls r0, 1\n\ + ldr r4, _0801EF84 @ =0x00016004\n\ + adds r0, r4\n\ + adds r0, r2\n\ + ldr r6, _0801EF88 @ =gCurrentMove\n\ + ldrh r1, [r6]\n\ + strb r1, [r0]\n\ + ldrb r0, [r3]\n\ + lsls r0, 1\n\ + ldr r1, _0801EF8C @ =0x00016005\n\ + adds r0, r1\n\ + adds r0, r2\n\ + ldrh r1, [r6]\n\ + lsrs r1, 8\n\ + strb r1, [r0]\n\ + ldrb r0, [r3]\n\ + ldr r3, _0801EF90 @ =0x00016020\n\ + adds r0, r3\n\ + adds r0, r2\n\ + ldr r1, _0801EF94 @ =gBankAttacker\n\ + ldrb r1, [r1]\n\ + strb r1, [r0]\n\ + ldr r4, _0801EF98 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r1, _0801EF9C @ =gMoveEffectBS_Ptrs\n\ + ldr r2, _0801EFA0 @ =gBattleCommunication\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + str r0, [r4]\n\ + strb r5, [r2, 0x5]\n\ + ldr r1, _0801EFA4 @ =gTrappingMoves\n\ + ldrh r0, [r1]\n\ + ldrh r4, [r6]\n\ + cmp r0, r4\n\ + bne _0801EF5C\n\ + b _0801F5FA\n\ +_0801EF5C:\n\ + adds r3, r1, 0\n\ + adds r1, r6, 0\n\ +_0801EF60:\n\ + ldrb r0, [r2, 0x5]\n\ + adds r0, 0x1\n\ + strb r0, [r2, 0x5]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x4\n\ + bls _0801EF70\n\ + b _0801F5FA\n\ +_0801EF70:\n\ + ldrb r0, [r2, 0x5]\n\ + lsls r0, 1\n\ + adds r0, r3\n\ + ldrh r0, [r0]\n\ + ldrh r4, [r1]\n\ + cmp r0, r4\n\ + bne _0801EF60\n\ + b _0801F5FA\n\ + .align 2, 0\n\ +_0801EF80: .4byte 0x02000000\n\ +_0801EF84: .4byte 0x00016004\n\ +_0801EF88: .4byte gCurrentMove\n\ +_0801EF8C: .4byte 0x00016005\n\ +_0801EF90: .4byte 0x00016020\n\ +_0801EF94: .4byte gBankAttacker\n\ +_0801EF98: .4byte gBattlescriptCurrInstr\n\ +_0801EF9C: .4byte gMoveEffectBS_Ptrs\n\ +_0801EFA0: .4byte gBattleCommunication\n\ +_0801EFA4: .4byte gTrappingMoves\n\ +_0801EFA8:\n\ + ldr r1, _0801EFD8 @ =gBattleMoveDamage\n\ + ldr r0, _0801EFDC @ =gHP_dealt\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bge _0801EFB4\n\ + adds r0, 0x3\n\ +_0801EFB4:\n\ + asrs r0, 2\n\ + str r0, [r1]\n\ + cmp r0, 0\n\ + bne _0801EFC0\n\ + movs r0, 0x1\n\ + str r0, [r1]\n\ +_0801EFC0:\n\ + ldr r4, _0801EFE0 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r1, _0801EFE4 @ =gMoveEffectBS_Ptrs\n\ + ldr r0, _0801EFE8 @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801EFD8: .4byte gBattleMoveDamage\n\ +_0801EFDC: .4byte gHP_dealt\n\ +_0801EFE0: .4byte gBattlescriptCurrInstr\n\ +_0801EFE4: .4byte gMoveEffectBS_Ptrs\n\ +_0801EFE8: .4byte gBattleCommunication\n\ +_0801EFEC:\n\ + ldrb r1, [r7, 0x3]\n\ + adds r1, 0xF2\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + movs r0, 0x10\n\ + adds r2, r6, 0\n\ + movs r3, 0\n\ + bl ChangeStatBuffs\n\ + lsls r0, 24\n\ + lsrs r3, r0, 24\n\ + cmp r3, 0\n\ + beq _0801F008\n\ + b _0801F5DC\n\ +_0801F008:\n\ + ldr r2, _0801F02C @ =0x02000000\n\ + ldrb r1, [r7, 0x3]\n\ + movs r0, 0x3F\n\ + ands r0, r1\n\ + ldr r4, _0801F030 @ =0x000160a4\n\ + adds r1, r2, r4\n\ + strb r0, [r1]\n\ + ldr r0, _0801F034 @ =0x000160a5\n\ + adds r2, r0\n\ + strb r3, [r2]\n\ + ldr r4, _0801F038 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F03C @ =BattleScript_StatUp\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F02C: .4byte 0x02000000\n\ +_0801F030: .4byte 0x000160a4\n\ +_0801F034: .4byte 0x000160a5\n\ +_0801F038: .4byte gBattlescriptCurrInstr\n\ +_0801F03C: .4byte BattleScript_StatUp\n\ +_0801F040:\n\ + movs r0, 0x70\n\ + negs r0, r0\n\ + ldrb r1, [r7, 0x3]\n\ + adds r1, 0xEB\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + adds r2, r6, 0\n\ + movs r3, 0\n\ + bl ChangeStatBuffs\n\ + lsls r0, 24\n\ + lsrs r3, r0, 24\n\ + cmp r3, 0\n\ + beq _0801F05E\n\ + b _0801F5DC\n\ +_0801F05E:\n\ + ldr r2, _0801F080 @ =0x02000000\n\ + ldrb r1, [r7, 0x3]\n\ + movs r0, 0x3F\n\ + ands r0, r1\n\ + ldr r4, _0801F084 @ =0x000160a4\n\ + adds r1, r2, r4\n\ + strb r0, [r1]\n\ + ldr r0, _0801F088 @ =0x000160a5\n\ + adds r2, r0\n\ + strb r3, [r2]\n\ + ldr r4, _0801F08C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F090 @ =BattleScript_StatDown\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F080: .4byte 0x02000000\n\ +_0801F084: .4byte 0x000160a4\n\ +_0801F088: .4byte 0x000160a5\n\ +_0801F08C: .4byte gBattlescriptCurrInstr\n\ +_0801F090: .4byte BattleScript_StatDown\n\ +_0801F094:\n\ + ldrb r1, [r7, 0x3]\n\ + adds r1, 0xDA\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + movs r0, 0x20\n\ + adds r2, r6, 0\n\ + movs r3, 0\n\ + bl ChangeStatBuffs\n\ + lsls r0, 24\n\ + lsrs r3, r0, 24\n\ + cmp r3, 0\n\ + beq _0801F0B0\n\ + b _0801F5DC\n\ +_0801F0B0:\n\ + ldr r2, _0801F0D4 @ =0x02000000\n\ + ldrb r1, [r7, 0x3]\n\ + movs r0, 0x3F\n\ + ands r0, r1\n\ + ldr r4, _0801F0D8 @ =0x000160a4\n\ + adds r1, r2, r4\n\ + strb r0, [r1]\n\ + ldr r0, _0801F0DC @ =0x000160a5\n\ + adds r2, r0\n\ + strb r3, [r2]\n\ + ldr r4, _0801F0E0 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F0E4 @ =BattleScript_StatUp\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F0D4: .4byte 0x02000000\n\ +_0801F0D8: .4byte 0x000160a4\n\ +_0801F0DC: .4byte 0x000160a5\n\ +_0801F0E0: .4byte gBattlescriptCurrInstr\n\ +_0801F0E4: .4byte BattleScript_StatUp\n\ +_0801F0E8:\n\ + movs r0, 0x60\n\ + negs r0, r0\n\ + ldrb r1, [r7, 0x3]\n\ + adds r1, 0xD3\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + adds r2, r6, 0\n\ + movs r3, 0\n\ + bl ChangeStatBuffs\n\ + lsls r0, 24\n\ + lsrs r3, r0, 24\n\ + cmp r3, 0\n\ + beq _0801F106\n\ + b _0801F5DC\n\ +_0801F106:\n\ + ldr r2, _0801F128 @ =0x02000000\n\ + ldrb r1, [r7, 0x3]\n\ + movs r0, 0x3F\n\ + ands r0, r1\n\ + ldr r4, _0801F12C @ =0x000160a4\n\ + adds r1, r2, r4\n\ + strb r0, [r1]\n\ + ldr r0, _0801F130 @ =0x000160a5\n\ + adds r2, r0\n\ + strb r3, [r2]\n\ + ldr r4, _0801F134 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F138 @ =BattleScript_StatDown\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F128: .4byte 0x02000000\n\ +_0801F12C: .4byte 0x000160a4\n\ +_0801F130: .4byte 0x000160a5\n\ +_0801F134: .4byte gBattlescriptCurrInstr\n\ +_0801F138: .4byte BattleScript_StatDown\n\ +_0801F13C:\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + movs r0, 0x58\n\ + adds r2, r1, 0\n\ + muls r2, r0\n\ + mov r0, r9\n\ + adds r0, 0x50\n\ + adds r2, r0\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 15\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + ldr r2, _0801F178 @ =gDisableStructs\n\ + mov r3, r8\n\ + ldrb r1, [r3]\n\ + lsls r0, r1, 3\n\ + subs r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + movs r1, 0x2\n\ + strb r1, [r0, 0x19]\n\ + ldr r1, _0801F17C @ =gLockedMove\n\ + ldrb r0, [r3]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldr r1, _0801F180 @ =gCurrentMove\n\ + ldrh r1, [r1]\n\ + strh r1, [r0]\n\ + b _0801F5DC\n\ + .align 2, 0\n\ +_0801F178: .4byte gDisableStructs\n\ +_0801F17C: .4byte gLockedMove\n\ +_0801F180: .4byte gCurrentMove\n\ +_0801F184:\n\ + ldr r0, _0801F1A0 @ =gBankAttacker\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + adds r2, r1, 0\n\ + muls r2, r0\n\ + mov r0, r9\n\ + adds r0, 0x50\n\ + adds r2, r0\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 16\n\ +_0801F19A:\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + b _0801F5DC\n\ + .align 2, 0\n\ +_0801F1A0: .4byte gBankAttacker\n\ +_0801F1A4:\n\ + ldr r4, _0801F254 @ =gBankAttacker\n\ + ldrb r0, [r4]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + ldrb r0, [r4]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _0801F1D8\n\ + ldr r0, _0801F258 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + ldr r0, _0801F25C @ =0x00000902\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801F214\n\ + ldr r0, _0801F260 @ =gTrainerBattleOpponent\n\ + ldrh r1, [r0]\n\ + movs r0, 0x80\n\ + lsls r0, 3\n\ + cmp r1, r0\n\ + beq _0801F1D8\n\ + b _0801F5DC\n\ +_0801F1D8:\n\ + ldr r0, _0801F258 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + ldr r0, _0801F25C @ =0x00000902\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0801F214\n\ + ldr r0, _0801F260 @ =gTrainerBattleOpponent\n\ + ldrh r1, [r0]\n\ + movs r0, 0x80\n\ + lsls r0, 3\n\ + cmp r1, r0\n\ + beq _0801F214\n\ + ldr r0, _0801F264 @ =gWishFutureKnock\n\ + adds r0, 0x29\n\ + adds r0, r6, r0\n\ + ldrb r1, [r0]\n\ + ldr r3, _0801F268 @ =gBitTable\n\ + ldr r2, _0801F26C @ =gBattlePartyID\n\ + ldr r0, _0801F254 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + lsls r0, 1\n\ + adds r0, r2\n\ + ldrh r0, [r0]\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldr r0, [r0]\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + beq _0801F214\n\ + b _0801F5DC\n\ +_0801F214:\n\ + ldr r2, _0801F270 @ =gBattleMons\n\ + ldr r1, _0801F274 @ =gBankTarget\n\ + ldrb r0, [r1]\n\ + movs r3, 0x58\n\ + muls r0, r3\n\ + adds r4, r0, r2\n\ + ldrh r0, [r4, 0x2E]\n\ + adds r7, r1, 0\n\ + mov r9, r2\n\ + cmp r0, 0\n\ + beq _0801F284\n\ + adds r0, r4, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x3C\n\ + bne _0801F284\n\ + ldr r1, _0801F278 @ =gBattlescriptCurrInstr\n\ + ldr r0, _0801F27C @ =BattleScript_NoItemSteal\n\ + str r0, [r1]\n\ + ldr r1, _0801F280 @ =gLastUsedAbility\n\ + ldrb r0, [r7]\n\ + muls r0, r3\n\ + add r0, r9\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + strb r0, [r1]\n\ + ldrb r0, [r7]\n\ + ldrb r1, [r1]\n\ + bl RecordAbilityBattle\n\ + b _0801F5FA\n\ + .align 2, 0\n\ +_0801F254: .4byte gBankAttacker\n\ +_0801F258: .4byte gBattleTypeFlags\n\ +_0801F25C: .4byte 0x00000902\n\ +_0801F260: .4byte gTrainerBattleOpponent\n\ +_0801F264: .4byte gWishFutureKnock\n\ +_0801F268: .4byte gBitTable\n\ +_0801F26C: .4byte gBattlePartyID\n\ +_0801F270: .4byte gBattleMons\n\ +_0801F274: .4byte gBankTarget\n\ +_0801F278: .4byte gBattlescriptCurrInstr\n\ +_0801F27C: .4byte BattleScript_NoItemSteal\n\ +_0801F280: .4byte gLastUsedAbility\n\ +_0801F284:\n\ + ldr r4, _0801F340 @ =gBankAttacker\n\ + mov r10, r4\n\ + ldrb r1, [r4]\n\ + movs r0, 0x58\n\ + mov r8, r0\n\ + mov r0, r8\n\ + muls r0, r1\n\ + add r0, r9\n\ + ldrh r3, [r0, 0x2E]\n\ + cmp r3, 0\n\ + beq _0801F29C\n\ + b _0801F5DC\n\ +_0801F29C:\n\ + ldrb r0, [r7]\n\ + mov r2, r8\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + add r0, r9\n\ + ldrh r2, [r0, 0x2E]\n\ + adds r0, r2, 0\n\ + cmp r0, 0xAF\n\ + bne _0801F2B0\n\ + b _0801F5DC\n\ +_0801F2B0:\n\ + cmp r0, 0\n\ + bne _0801F2B6\n\ + b _0801F5DC\n\ +_0801F2B6:\n\ + lsls r0, r1, 1\n\ + ldr r5, _0801F344 @ =0x020160f0\n\ + adds r0, r5\n\ + ldr r1, _0801F348 @ =gLastUsedItem\n\ + strh r2, [r0]\n\ + strh r2, [r1]\n\ + ldrb r0, [r7]\n\ + mov r4, r8\n\ + muls r4, r0\n\ + adds r0, r4, 0\n\ + add r0, r9\n\ + movs r6, 0\n\ + strh r3, [r0, 0x2E]\n\ + ldr r4, _0801F34C @ =gActiveBank\n\ + mov r2, r10\n\ + ldrb r0, [r2]\n\ + strb r0, [r4]\n\ + str r1, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + movs r2, 0\n\ + movs r3, 0x2\n\ + bl EmitSetAttributes\n\ + mov r3, r10\n\ + ldrb r0, [r3]\n\ + bl MarkBufferBankForExecution\n\ + ldrb r0, [r7]\n\ + strb r0, [r4]\n\ + ldrb r0, [r7]\n\ + mov r4, r8\n\ + muls r4, r0\n\ + adds r0, r4, 0\n\ + mov r1, r9\n\ + adds r1, 0x2E\n\ + adds r0, r1\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + movs r2, 0\n\ + movs r3, 0x2\n\ + bl EmitSetAttributes\n\ + ldrb r0, [r7]\n\ + bl MarkBufferBankForExecution\n\ + ldr r4, _0801F350 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F354 @ =BattleScript_ItemSteal\n\ + str r0, [r4]\n\ + ldr r0, _0801F358 @ =0xfffe9f10\n\ + adds r5, r0\n\ + ldrb r0, [r7]\n\ + lsls r0, 1\n\ + ldr r1, _0801F35C @ =0x000160e8\n\ + adds r0, r1\n\ + adds r0, r5\n\ + strb r6, [r0]\n\ + ldrb r0, [r7]\n\ + lsls r0, 1\n\ + ldr r2, _0801F360 @ =0x000160e9\n\ + adds r0, r2\n\ + adds r0, r5\n\ + strb r6, [r0]\n\ + b _0801F5FA\n\ + .align 2, 0\n\ +_0801F340: .4byte gBankAttacker\n\ +_0801F344: .4byte 0x020160f0\n\ +_0801F348: .4byte gLastUsedItem\n\ +_0801F34C: .4byte gActiveBank\n\ +_0801F350: .4byte gBattlescriptCurrInstr\n\ +_0801F354: .4byte BattleScript_ItemSteal\n\ +_0801F358: .4byte 0xfffe9f10\n\ +_0801F35C: .4byte 0x000160e8\n\ +_0801F360: .4byte 0x000160e9\n\ +_0801F364:\n\ + ldr r3, _0801F394 @ =gBankTarget\n\ + ldrb r1, [r3]\n\ + movs r0, 0x58\n\ + adds r2, r1, 0\n\ + muls r2, r0\n\ + mov r0, r9\n\ + adds r0, 0x50\n\ + adds r2, r0\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 19\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + ldr r2, _0801F398 @ =gDisableStructs\n\ + ldrb r1, [r3]\n\ + lsls r0, r1, 3\n\ + subs r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldr r1, _0801F39C @ =gBankAttacker\n\ + ldrb r1, [r1]\n\ + strb r1, [r0, 0x14]\n\ + b _0801F5DC\n\ + .align 2, 0\n\ +_0801F394: .4byte gBankTarget\n\ +_0801F398: .4byte gDisableStructs\n\ +_0801F39C: .4byte gBankAttacker\n\ +_0801F3A0:\n\ + ldr r0, _0801F3B8 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + adds r2, r1, 0\n\ + muls r2, r0\n\ + mov r0, r9\n\ + adds r0, 0x50\n\ + adds r2, r0\n\ + ldr r0, [r2]\n\ + movs r1, 0x80\n\ + lsls r1, 20\n\ + b _0801F19A\n\ + .align 2, 0\n\ +_0801F3B8: .4byte gBankTarget\n\ +_0801F3BC:\n\ + ldr r4, _0801F3CC @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F3D0 @ =BattleScript_AllStatsUp\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F3CC: .4byte gBattlescriptCurrInstr\n\ +_0801F3D0: .4byte BattleScript_AllStatsUp\n\ +_0801F3D4:\n\ + ldr r4, _0801F3E4 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F3E8 @ =BattleScript_RapidSpinAway\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F3E4: .4byte gBattlescriptCurrInstr\n\ +_0801F3E8: .4byte BattleScript_RapidSpinAway\n\ +_0801F3EC:\n\ + ldr r6, _0801F43C @ =gBankTarget\n\ + ldrb r0, [r6]\n\ + movs r2, 0x58\n\ + muls r0, r2\n\ + mov r1, r9\n\ + adds r1, 0x4C\n\ + adds r5, r0, r1\n\ + ldr r4, [r5]\n\ + movs r0, 0x40\n\ + ands r0, r4\n\ + cmp r0, 0\n\ + bne _0801F406\n\ + b _0801F5DC\n\ +_0801F406:\n\ + movs r0, 0x41\n\ + negs r0, r0\n\ + ands r4, r0\n\ + str r4, [r5]\n\ + ldr r4, _0801F440 @ =gActiveBank\n\ + ldrb r0, [r6]\n\ + strb r0, [r4]\n\ + ldrb r0, [r4]\n\ + muls r0, r2\n\ + adds r0, r1\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x28\n\ + movs r2, 0\n\ + movs r3, 0x4\n\ + bl EmitSetAttributes\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + ldr r4, _0801F444 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F448 @ =BattleScript_TargetPRLZHeal\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F43C: .4byte gBankTarget\n\ +_0801F440: .4byte gActiveBank\n\ +_0801F444: .4byte gBattlescriptCurrInstr\n\ +_0801F448: .4byte BattleScript_TargetPRLZHeal\n\ +_0801F44C:\n\ + ldr r4, _0801F45C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F460 @ =BattleScript_AtkDefDown\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F45C: .4byte gBattlescriptCurrInstr\n\ +_0801F460: .4byte BattleScript_AtkDefDown\n\ +_0801F464:\n\ + ldr r4, _0801F494 @ =gBattleMoveDamage\n\ + ldr r0, _0801F498 @ =gHP_dealt\n\ + ldr r0, [r0]\n\ + movs r1, 0x3\n\ + bl __divsi3\n\ + str r0, [r4]\n\ + cmp r0, 0\n\ + bne _0801F47A\n\ + movs r0, 0x1\n\ + str r0, [r4]\n\ +_0801F47A:\n\ + ldr r4, _0801F49C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r1, _0801F4A0 @ =gMoveEffectBS_Ptrs\n\ + ldr r0, _0801F4A4 @ =gBattleCommunication\n\ + ldrb r0, [r0, 0x3]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + b _0801F5F8\n\ + .align 2, 0\n\ +_0801F494: .4byte gBattleMoveDamage\n\ +_0801F498: .4byte gHP_dealt\n\ +_0801F49C: .4byte gBattlescriptCurrInstr\n\ +_0801F4A0: .4byte gMoveEffectBS_Ptrs\n\ +_0801F4A4: .4byte gBattleCommunication\n\ +_0801F4A8:\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + movs r5, 0x58\n\ + muls r0, r5\n\ + mov r4, r9\n\ + adds r4, 0x50\n\ + adds r2, r0, r4\n\ + ldr r1, [r2]\n\ + movs r0, 0xC0\n\ + lsls r0, 4\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0801F4C4\n\ + b _0801F5DC\n\ +_0801F4C4:\n\ + movs r0, 0x80\n\ + lsls r0, 5\n\ + orrs r1, r0\n\ + str r1, [r2]\n\ + ldr r1, _0801F4F8 @ =gLockedMove\n\ + ldrb r0, [r3]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldr r1, _0801F4FC @ =gCurrentMove\n\ + ldrh r1, [r1]\n\ + strh r1, [r0]\n\ + bl Random\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + adds r2, r1, 0\n\ + muls r2, r5\n\ + adds r2, r4\n\ + movs r1, 0x1\n\ + ands r1, r0\n\ + adds r1, 0x2\n\ + lsls r1, 10\n\ + ldr r0, [r2]\n\ +_0801F4F2:\n\ + orrs r0, r1\n\ + str r0, [r2]\n\ + b _0801F5FA\n\ + .align 2, 0\n\ +_0801F4F8: .4byte gLockedMove\n\ +_0801F4FC: .4byte gCurrentMove\n\ +_0801F500:\n\ + mov r5, r8\n\ + ldrb r3, [r5]\n\ + movs r4, 0x58\n\ + adds r0, r3, 0\n\ + muls r0, r4\n\ + mov r2, r9\n\ + adds r1, r0, r2\n\ + adds r0, r1, 0\n\ + adds r0, 0x20\n\ + ldrb r2, [r0]\n\ + cmp r2, 0x3C\n\ + bne _0801F540\n\ + ldrh r0, [r1, 0x2E]\n\ + cmp r0, 0\n\ + beq _0801F5DC\n\ + ldr r0, _0801F534 @ =gLastUsedAbility\n\ + strb r2, [r0]\n\ + ldr r1, _0801F538 @ =gBattlescriptCurrInstr\n\ + ldr r0, _0801F53C @ =BattleScript_NoItemSteal\n\ + str r0, [r1]\n\ + ldrb r0, [r5]\n\ + movs r1, 0x3C\n\ + bl RecordAbilityBattle\n\ + b _0801F5FA\n\ + .align 2, 0\n\ +_0801F534: .4byte gLastUsedAbility\n\ +_0801F538: .4byte gBattlescriptCurrInstr\n\ +_0801F53C: .4byte BattleScript_NoItemSteal\n\ +_0801F540:\n\ + ldrh r0, [r1, 0x2E]\n\ + cmp r0, 0\n\ + beq _0801F5DC\n\ + adds r0, r3, 0\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + ldr r1, _0801F5B8 @ =gLastUsedItem\n\ + mov r3, r8\n\ + ldrb r0, [r3]\n\ + muls r0, r4\n\ + add r0, r9\n\ + ldrh r0, [r0, 0x2E]\n\ + strh r0, [r1]\n\ + ldrb r0, [r3]\n\ + muls r0, r4\n\ + add r0, r9\n\ + movs r5, 0\n\ + movs r1, 0\n\ + strh r1, [r0, 0x2E]\n\ + ldr r2, _0801F5BC @ =gWishFutureKnock\n\ + adds r2, 0x29\n\ + adds r2, r6, r2\n\ + ldr r3, _0801F5C0 @ =gBitTable\n\ + ldr r1, _0801F5C4 @ =gBattlePartyID\n\ + mov r4, r8\n\ + ldrb r0, [r4]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldrh r0, [r0]\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r4, _0801F5C8 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F5CC @ =BattleScript_KnockedOff\n\ + str r0, [r4]\n\ + ldr r1, _0801F5D0 @ =0x02000000\n\ + mov r2, r8\n\ + ldrb r0, [r2]\n\ + lsls r0, 1\n\ + ldr r3, _0801F5D4 @ =0x000160e8\n\ + adds r0, r3\n\ + adds r0, r1\n\ + strb r5, [r0]\n\ + ldrb r0, [r2]\n\ + lsls r0, 1\n\ + ldr r4, _0801F5D8 @ =0x000160e9\n\ + adds r0, r4\n\ + adds r0, r1\n\ + strb r5, [r0]\n\ + b _0801F5FA\n\ + .align 2, 0\n\ +_0801F5B8: .4byte gLastUsedItem\n\ +_0801F5BC: .4byte gWishFutureKnock\n\ +_0801F5C0: .4byte gBitTable\n\ +_0801F5C4: .4byte gBattlePartyID\n\ +_0801F5C8: .4byte gBattlescriptCurrInstr\n\ +_0801F5CC: .4byte BattleScript_KnockedOff\n\ +_0801F5D0: .4byte 0x02000000\n\ +_0801F5D4: .4byte 0x000160e8\n\ +_0801F5D8: .4byte 0x000160e9\n\ +_0801F5DC:\n\ + ldr r1, _0801F5E8 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x1\n\ + str r0, [r1]\n\ + b _0801F5FA\n\ + .align 2, 0\n\ +_0801F5E8: .4byte gBattlescriptCurrInstr\n\ +_0801F5EC:\n\ + ldr r4, _0801F60C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + bl b_movescr_stack_push\n\ + ldr r0, _0801F610 @ =BattleScript_SAtkDown2\n\ +_0801F5F8:\n\ + str r0, [r4]\n\ +_0801F5FA:\n\ + add sp, 0x8\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0801F60C: .4byte gBattlescriptCurrInstr\n\ +_0801F610: .4byte BattleScript_SAtkDown2\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + + +static void atk15_seteffectwithchancetarget(void) +{ + u32 PercentChance; + if (gBattleMons[gBankAttacker].ability == ABILITY_SERENE_GRACE) + PercentChance = gBattleMoves[gCurrentMove].secondaryEffectChance * 2; + else + PercentChance = gBattleMoves[gCurrentMove].secondaryEffectChance; + if (gBattleCommunication[MOVE_EFFECT_BYTE] & 0x80 && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT)) + { + gBattleCommunication[MOVE_EFFECT_BYTE] &= 0x7F; + SetMoveEffect(0, 0x80); + } + else if (Random() % 100 <= PercentChance && gBattleCommunication[MOVE_EFFECT_BYTE] && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT)) + { + if (PercentChance >= 100) + SetMoveEffect(0, 0x80); + else + SetMoveEffect(0, 0); + } + else + gBattlescriptCurrInstr++; + gBattleCommunication[MOVE_EFFECT_BYTE] = 0; + BATTLE_STRUCT->unk16112 = 0; +} + +static void atk16_seteffectprimary(void) +{ + SetMoveEffect(1, 0); +} + +static void atk17_seteffectsecondary(void) +{ + SetMoveEffect(0, 0); +} + +static void atk18_status_effect_clear(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (gBattleCommunication[MOVE_EFFECT_BYTE] <= 6) + gBattleMons[gActiveBank].status1 &= (~gStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]); + else + gBattleMons[gActiveBank].status2 &= (~gStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]); + + gBattleCommunication[MOVE_EFFECT_BYTE] = 0; + gBattlescriptCurrInstr += 2; + BATTLE_STRUCT->unk16112 = 0; +} + +static void atk19_faint_pokemon(void) +{ + u8 *r4; + + if (gBattlescriptCurrInstr[2] != 0) + { + gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]); + if (gHitMarker & HITMARKER_FAINTED(gActiveBank)) + { + r4 = BSScriptReadPtr(gBattlescriptCurrInstr + 3); + + b_movescr_stack_pop_cursor(); + gBattlescriptCurrInstr = r4; + gSideAffecting[GetBankSide(gActiveBank)] &= ~SIDE_STATUS_SPIKES_DAMAGED; + } + else + { + gBattlescriptCurrInstr += 7; + } + } + else + { + u8 bank; + + if (gBattlescriptCurrInstr[1] == 1) + { + gActiveBank = gBankAttacker; + bank = gBankTarget; + r4 = gUnknown_081D8C58; + } + else + { + gActiveBank = gBankTarget; + bank = gBankAttacker; + r4 = gUnknown_081D8C65; + } + if (!(gAbsentBankFlags & gBitTable[gActiveBank]) + && gBattleMons[gActiveBank].hp == 0) + { + ewram[0x160AC + bank * 2 + 0] = 0; + ewram[0x160AC + bank * 2 + 1] = 0; + ewram[0x16100 + bank * 4 + 0] = 0; + ewram[0x16100 + bank * 4 + 1] = 0; + ewram[0x16100 + bank * 4 + 2] = 0; + ewram[0x16100 + bank * 4 + 3] = 0; + + gHitMarker |= HITMARKER_FAINTED(gActiveBank); + b_movescr_stack_push(gBattlescriptCurrInstr + 7); + gBattlescriptCurrInstr = r4; + if (GetBankSide(gActiveBank) == 0) + { + gHitMarker |= HITMARKER_x400000; + if (gBattleResults.playerFaintCounter < 0xFF) + gBattleResults.playerFaintCounter++; + if (gBattleMons[bank].level > gBattleMons[gActiveBank].level) + { + if (gBattleMons[bank].level - gBattleMons[gActiveBank].level > 0x1D) + AdjustFriendship(&gPlayerParty[gBattlePartyID[gActiveBank]], 8); + else + AdjustFriendship(&gPlayerParty[gBattlePartyID[gActiveBank]], 6); + } + } + else + { + if (gBattleResults.opponentFaintCounter < 0xFF) + gBattleResults.opponentFaintCounter++; + gBattleResults.lastOpponentSpecies = gBattleMons[gActiveBank].species; + } + if ((gHitMarker & HITMARKER_DESTINYBOND) && gBattleMons[gBankAttacker].hp != 0) + { + b_movescr_stack_push(gBattlescriptCurrInstr); + gBattleMoveDamage = gBattleMons[bank].hp; + gBattlescriptCurrInstr = gUnknown_081D9156; + } + if ((gStatuses3[gBankTarget] & STATUS3_GRUDGE) + && !(gHitMarker & HITMARKER_GRUDGE) + && GetBankSide(gBankAttacker) != GetBankSide(gBankTarget) + && gBattleMons[gBankAttacker].hp != 0 + && gCurrentMove != MOVE_STRUGGLE) + { + u8 moveIndex = ewram[0x1608C + gBankAttacker]; + + gBattleMons[gBankAttacker].pp[moveIndex] = 0; + b_movescr_stack_push(gBattlescriptCurrInstr); + gBattlescriptCurrInstr = gUnknown_081D9468; + gActiveBank = gBankAttacker; + EmitSetAttributes(0, moveIndex + 9, 0, 1, &gBattleMons[gActiveBank].pp[moveIndex]); + MarkBufferBankForExecution(gActiveBank); + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = gBattleMons[gBankAttacker].moves[moveIndex]; + gBattleTextBuff1[3] = gBattleMons[gBankAttacker].moves[moveIndex] >> 8; + gBattleTextBuff1[4] = EOS; + } + } + else + { + gBattlescriptCurrInstr += 7; + } + } +} + +static void atk1A_faint_animation(void) +{ + if (gBattleExecBuffer == 0) + { + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + Emitcmd10(0); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; + } +} + +static void atk1B_faint_effects_clear(void) +{ + //Clears things like attraction or trapping to other banks + if (gBattleExecBuffer == 0) + { + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + gBattleMons[gActiveBank].status1 = 0; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 0x4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + UndoEffectsAfterFainting(); + gBattlescriptCurrInstr += 2; + } +} + +static void atk1C_jumpifstatus(void) +{ + u8 bank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + u32 flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2); + void* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6); + if (gBattleMons[bank].status1 & flags && gBattleMons[bank].hp) + gBattlescriptCurrInstr = jump_loc; + else + gBattlescriptCurrInstr += 10; +} + +static void atk1D_jumpifstatus2(void) +{ + u8 bank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + u32 flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2); + void* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6); + if (gBattleMons[bank].status2 & flags && gBattleMons[bank].hp) + gBattlescriptCurrInstr = jump_loc; + else + gBattlescriptCurrInstr += 10; +} + +static void atk1E_jumpifability(void) +{ + u8 bank; + u8 ability = BSScriptRead8(gBattlescriptCurrInstr + 2); + void* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3); + if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 8) + { + bank = AbilityBattleEffects(ABILITYEFFECT_CHECK_BANK_SIDE, gBankAttacker, ability, 0, 0); + if (bank) + { + gLastUsedAbility = ability; + gBattlescriptCurrInstr = jump_loc; + RecordAbilityBattle(bank -1, gLastUsedAbility); + unk_2000000[0x160f8] = bank - 1; + } + else + gBattlescriptCurrInstr += 7; + } + else if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 9) + { + bank = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gBankAttacker, ability, 0, 0); + if (bank) + { + gLastUsedAbility = ability; + gBattlescriptCurrInstr = jump_loc; + RecordAbilityBattle(bank - 1, gLastUsedAbility); + unk_2000000[0x160f8] = bank - 1; + } + else + gBattlescriptCurrInstr += 7; + } + else + { + bank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (gBattleMons[bank].ability == ability) + { + gLastUsedAbility = ability; + gBattlescriptCurrInstr = jump_loc; + RecordAbilityBattle(bank, gLastUsedAbility); + unk_2000000[0x160f8] = bank; + } + else + gBattlescriptCurrInstr += 7; + } +} + +static void atk1F_jumpifsideaffecting(void) +{ + u8 side; + u16 flags; + void* jump_loc; + if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 1) + side = GetBankIdentity(gBankAttacker) & 1; + else + side = GetBankIdentity(gBankTarget) & 1; + + flags = BS2ScriptRead16(gBattlescriptCurrInstr + 2); + jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 4); + + if (gSideAffecting[side] & flags) + gBattlescriptCurrInstr = jump_loc; + else + gBattlescriptCurrInstr += 8; +} + +static void atk20_jumpifstat(void) +{ + u8 ret = 0; + u8 bank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + u8 value = gBattleMons[bank].statStages[BSScriptRead8(gBattlescriptCurrInstr + 3)]; + switch (BSScriptRead8(gBattlescriptCurrInstr + 2)) + { + case CMP_EQUAL: + if (value == BSScriptRead8(gBattlescriptCurrInstr + 4)) + ret++; + break; + case CMP_NOT_EQUAL: + if (value != BSScriptRead8(gBattlescriptCurrInstr + 4)) + ret++; + break; + case CMP_GREATER_THAN: + if (value > BSScriptRead8(gBattlescriptCurrInstr + 4)) + ret++; + break; + case CMP_LESS_THAN: + if (value < BSScriptRead8(gBattlescriptCurrInstr + 4)) + ret++; + break; + case CMP_COMMON_BITS: + if (value & BSScriptRead8(gBattlescriptCurrInstr + 4)) + ret++; + break; + case CMP_NO_COMMON_BITS: + if (!(value & BSScriptRead8(gBattlescriptCurrInstr + 4))) + ret++; + break; + } + if (ret) + gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + else + gBattlescriptCurrInstr += 9; +} + +static void atk21_jumpifstatus3(void) +{ + u32 flags; + void* jump_loc; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2); + jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 7); + if (BSScriptRead8(gBattlescriptCurrInstr + 6)) + { + if ((gStatuses3[gActiveBank] & flags) != 0) + gBattlescriptCurrInstr += 11; + else + gBattlescriptCurrInstr = jump_loc; + } + else + { + if ((gStatuses3[gActiveBank] & flags) != 0) + gBattlescriptCurrInstr = jump_loc; + else + gBattlescriptCurrInstr += 11; + } +} + +static void atk22_jumpiftype(void) //u8 bank, u8 type, *ptr +{ + u8 bank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + u8 type = BSScriptRead8(gBattlescriptCurrInstr + 2); + void* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3); + + if (gBattleMons[bank].type1 == type || gBattleMons[bank].type2 == type) + gBattlescriptCurrInstr = jump_loc; + else + gBattlescriptCurrInstr += 7; +} + +//here we go again... +#ifdef NONMATCHING +static void atk23_getexp(void) +{ + u8 hold_effect; + int via_expshare = 0, sent_in; + u16* exp = &BATTLE_STRUCT->exp; + gBank1 = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + sent_in = gSentPokesToOpponent[(gBank1 & 2) >> 1]; + switch (BATTLE_STRUCT->atk23StateTracker) + { + case 0: //check if should receive exp at all + if (GetBankSide(gBank1) != 1 || (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER))) + BATTLE_STRUCT->atk23StateTracker = 6; //goto last case + else + { + BATTLE_STRUCT->atk23StateTracker++; + ((u8*)ewram)[0x16113] |= gBitTable[gBattlePartyID[gBank1]]; + } + break; + case 1: //calculate experience points to redistribute + { + int via_sent_in = 0; + u16 calculatedExp; + int i; + for (i = 0; i < 6; i++) + { + u16 item; + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) == 0 || GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0) + continue; + if (gBitTable[i] & sent_in) + via_sent_in++; + + item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); + if (item == ITEM_ENIGMA_BERRY) + hold_effect = gSaveBlock1.enigmaBerry.holdEffect; + else + hold_effect = ItemId_GetHoldEffect(item); + + if (hold_effect == HOLD_EFFECT_EXP_SHARE) + via_expshare++; + } + calculatedExp = gBaseStats[gBattleMons[gBank1].species].expYield * gBattleMons[gBank1].level / 7; + if (via_expshare) //at least one poke is getting exp via exp share + { + calculatedExp /= 2; + *exp = calculatedExp / via_sent_in; + if (*exp == 0) + *exp = 1; + + gExpShareExp = calculatedExp / via_expshare; + if (gExpShareExp == 0) + gExpShareExp = 1; + } + else + { + *exp = calculatedExp / via_sent_in; + if (*exp == 0) + *exp = 1; + gExpShareExp = 0; + } + BATTLE_STRUCT->atk23StateTracker++; + BATTLE_STRUCT->expGetterID = 0; + BATTLE_STRUCT->sentInPokes = sent_in; + } //no break statement + case 2: //loop; set exp value to the poke in expgetter_id and print message + if (gBattleExecBuffer == 0) + { + u16 item = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_HELD_ITEM); + u8* tracker; u32 zero; + if (item == ITEM_ENIGMA_BERRY) + hold_effect = gSaveBlock1.enigmaBerry.holdEffect; + else + hold_effect = ItemId_GetHoldEffect(item); + + if ((hold_effect != HOLD_EFFECT_EXP_SHARE && !(BATTLE_STRUCT->sentInPokes & 1))) + { + BATTLE_STRUCT->sentInPokes >>= 1; + tracker = &BATTLE_STRUCT->atk23StateTracker; + zero = 0; + *tracker = 5; //increment looper + gBattleMoveDamage = zero; //used for exp + } + else if (GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_LEVEL) == 100) + { + BATTLE_STRUCT->sentInPokes >>= 1; + tracker = &BATTLE_STRUCT->atk23StateTracker; + zero = 0; + *tracker = 5; //increment looper + gBattleMoveDamage = zero; //used for exp + } + else + { + //music change in wild battle after fainting a poke + if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) && gBattleMons[0].hp && !BATTLE_STRUCT->wildVictorySong) + { + BattleMusicStop(); + PlayBGM(0x161); + BATTLE_STRUCT->wildVictorySong++; + } + + if (GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_HP)) + { + s16 stringID; + if (BATTLE_STRUCT->sentInPokes & 1) + gBattleMoveDamage = *exp; + else + gBattleMoveDamage = 0; + + if (hold_effect == HOLD_EFFECT_EXP_SHARE) + gBattleMoveDamage += gExpShareExp; + if (hold_effect == HOLD_EFFECT_LUCKY_EGG) + gBattleMoveDamage = (gBattleMoveDamage * 150) / 100; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + gBattleMoveDamage = (gBattleMoveDamage * 150) / 100; + + if (IsTradedMon(&gPlayerParty[BATTLE_STRUCT->expGetterID])) + { + gBattleMoveDamage = (gBattleMoveDamage * 150) / 100; + stringID = 0x14A; + } + else + { + stringID = 0x149; + } + + //get exp getter bank + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + if (!(gBattlePartyID[2] != BATTLE_STRUCT->expGetterID) && !(gAbsentBankFlags & gBitTable[2])) + BATTLE_STRUCT->expGetterBank = 2; + else + { + if (!(gAbsentBankFlags & gBitTable[0])) + BATTLE_STRUCT->expGetterBank = 0; + else + BATTLE_STRUCT->expGetterBank = 2; + } + } + else + BATTLE_STRUCT->expGetterBank = 0; + + //buffer poke name + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 4; + gBattleTextBuff1[2] = BATTLE_STRUCT->expGetterBank; + gBattleTextBuff1[3] = BATTLE_STRUCT->expGetterID; + gBattleTextBuff1[4] = 0xFF; + + //buffer 'gained' or 'gained a boosted' + gBattleTextBuff2[0] = 0xFD; + gBattleTextBuff2[1] = 0; + gBattleTextBuff2[2] = stringID; + stringID = (stringID >> 8) & (0xFF); //this does not want to cooperate + gBattleTextBuff2[3] = stringID; + gBattleTextBuff2[4] = 0xFF; + + //buffer exp number + gBattleTextBuff3[0] = 0xFD; + gBattleTextBuff3[1] = 1; + gBattleTextBuff3[2] = 4; //word + gBattleTextBuff3[3] = 5; //max digits + gBattleTextBuff3[4] = gBattleMoveDamage; + gBattleTextBuff3[5] = sBYTE1_32(gBattleMoveDamage); + gBattleTextBuff3[6] = sBYTE2_32(gBattleMoveDamage); + gBattleTextBuff3[7] = sBYTE3_32(gBattleMoveDamage); + gBattleTextBuff3[8] = 0xFF; + + PrepareStringBattle(0xD, BATTLE_STRUCT->expGetterBank); + MonGainEVs(&gPlayerParty[BATTLE_STRUCT->expGetterID], gBattleMons[gBank1].species); + } + BATTLE_STRUCT->sentInPokes >>= 1; + BATTLE_STRUCT->atk23StateTracker++; + } + } + break; + case 3: //Set Stats and give exp + if (gBattleExecBuffer == 0) + { + gBattleBufferB[BATTLE_STRUCT->expGetterBank][0] = 0; + if (GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_HP) && GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_LEVEL) != 100) + { + // Doesn't match. + BATTLE_STRUCT->beforeLvlUp[0] = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_MAX_HP); + BATTLE_STRUCT->beforeLvlUp[1] = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_ATK); + BATTLE_STRUCT->beforeLvlUp[2] = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_DEF); + BATTLE_STRUCT->beforeLvlUp[3] = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPD); + BATTLE_STRUCT->beforeLvlUp[4] = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPATK); + BATTLE_STRUCT->beforeLvlUp[5] = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPDEF); + + gActiveBank = BATTLE_STRUCT->expGetterBank; + EmitExpBarUpdate(0, BATTLE_STRUCT->expGetterID, gBattleMoveDamage); + MarkBufferBankForExecution(gActiveBank); + } + BATTLE_STRUCT->atk23StateTracker++; + } + break; + case 4: //lvl up if necessary + if (gBattleExecBuffer == 0) + { + gActiveBank = BATTLE_STRUCT->expGetterBank; + if (gBattleBufferB[gActiveBank][0] == 0x21 && gBattleBufferB[gActiveBank][1] == 0xB) + { + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gBattlePartyID[gActiveBank] == BATTLE_STRUCT->expGetterID) + sub_80324F8(&gPlayerParty[gActiveBank], gActiveBank); + + //buff poke name + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 4; + gBattleTextBuff1[2] = gActiveBank; + gBattleTextBuff1[3] = BATTLE_STRUCT->expGetterID; + gBattleTextBuff1[4] = 0xFF; + + //buff level + gBattleTextBuff2[0] = 0xFD; + gBattleTextBuff2[1] = 1; + gBattleTextBuff2[2] = 1; + gBattleTextBuff2[3] = 3; + gBattleTextBuff2[4] = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_LEVEL); + gBattleTextBuff2[5] = 0xFF; + + b_movescr_stack_push_cursor(); + gLeveledUpInBattle |= gBitTable[BATTLE_STRUCT->expGetterID]; + gBattlescriptCurrInstr = BattleScript_LevelUp; + gBattleMoveDamage = (gBattleBufferB[gActiveBank][2] | (gBattleBufferB[gActiveBank][3] << 8)); + AdjustFriendship(&gPlayerParty[BATTLE_STRUCT->expGetterID], 0); + + //update battle mon structure after level up + if (gBattlePartyID[0] == BATTLE_STRUCT->expGetterID && gBattleMons[0].hp) + { + gBattleMons[0].level = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_LEVEL); + gBattleMons[0].hp = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_HP); + gBattleMons[0].maxHP = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_MAX_HP); + gBattleMons[0].attack = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_ATK); + gBattleMons[0].defense = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_DEF); + gBattleMons[0].speed = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPD); + gBattleMons[0].spAttack = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPATK); + gBattleMons[0].spDefense = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPDEF); + } + //What is else if? Guess it's too advanced for GameFreak + if (gBattlePartyID[2] == BATTLE_STRUCT->expGetterID && gBattleMons[2].hp && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + gBattleMons[2].level = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_LEVEL); + gBattleMons[2].hp = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_HP); + gBattleMons[2].maxHP = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_MAX_HP); + gBattleMons[2].attack = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_ATK); + gBattleMons[2].defense = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_DEF); + //There are no words...GF can't even copy&paste code properly + gBattleMons[2].speed = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPD); + gBattleMons[2].spAttack = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPD /*RIP*/); + gBattleMons[2].spDefense = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_SPATK); + } + BATTLE_STRUCT->atk23StateTracker = 5; + } + else + { + gBattleMoveDamage = 0; + BATTLE_STRUCT->atk23StateTracker = 5; + } + } + break; + case 5: //looper increment + if (gBattleMoveDamage) //there is exp to give, goto case 3 that gives exp + BATTLE_STRUCT->atk23StateTracker = 3; + else + { + if (++BATTLE_STRUCT->expGetterID <= 5) + BATTLE_STRUCT->atk23StateTracker = 2; //loop again + else + BATTLE_STRUCT->atk23StateTracker = 6; //we're done + } + break; + case 6: //increment instruction + if (gBattleExecBuffer == 0) + { + //not even sure why gamefreak clears that data in this place + gBattleMons[gBank1].item = 0; + gBattleMons[gBank1].ability = 0; + gBattlescriptCurrInstr += 2; + } + break; + } +} +#else +__attribute__((naked)) +static void atk23_getexp(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + movs r6, 0\n\ + ldr r0, _0802004C @ =0x0201605c\n\ + mov r10, r0\n\ + ldr r0, _08020050 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r0]\n\ + ldrb r0, [r0, 0x1]\n\ + bl GetBattleBank\n\ + ldr r1, _08020054 @ =gBank1\n\ + strb r0, [r1]\n\ + ldr r2, _08020058 @ =gSentPokesToOpponent\n\ + movs r1, 0x2\n\ + ands r1, r0\n\ + lsls r1, 24\n\ + lsrs r1, 25\n\ + adds r1, r2\n\ + ldrb r1, [r1]\n\ + mov r8, r1\n\ + mov r0, r10\n\ + subs r0, 0x4D\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x6\n\ + bls _08020040\n\ + bl _08020996\n\ +_08020040:\n\ + lsls r0, 2\n\ + ldr r1, _0802005C @ =_08020060\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_0802004C: .4byte 0x0201605c\n\ +_08020050: .4byte gBattlescriptCurrInstr\n\ +_08020054: .4byte gBank1\n\ +_08020058: .4byte gSentPokesToOpponent\n\ +_0802005C: .4byte _08020060\n\ + .align 2, 0\n\ +_08020060:\n\ + .4byte _0802007C\n\ + .4byte _080200FC\n\ + .4byte _08020216\n\ + .4byte _0802055C\n\ + .4byte _08020648\n\ + .4byte _08020910\n\ + .4byte _0802096C\n\ +_0802007C:\n\ + ldr r4, _080200A8 @ =gBank1\n\ + ldrb r0, [r4]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _08020098\n\ + ldr r0, _080200AC @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + ldr r0, _080200B0 @ =0x00000982\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080200BC\n\ +_08020098:\n\ + ldr r0, _080200B4 @ =0x02000000\n\ + ldr r1, _080200B8 @ =0x0001600f\n\ + adds r0, r1\n\ + movs r1, 0x6\n\ + strb r1, [r0]\n\ + bl _08020996\n\ + .align 2, 0\n\ +_080200A8: .4byte gBank1\n\ +_080200AC: .4byte gBattleTypeFlags\n\ +_080200B0: .4byte 0x00000982\n\ +_080200B4: .4byte 0x02000000\n\ +_080200B8: .4byte 0x0001600f\n\ +_080200BC:\n\ + ldr r2, _080200E8 @ =0x02000000\n\ + ldr r3, _080200EC @ =0x0001600f\n\ + adds r1, r2, r3\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ + ldr r0, _080200F0 @ =0x00016113\n\ + adds r2, r0\n\ + ldr r3, _080200F4 @ =gBitTable\n\ + ldr r1, _080200F8 @ =gBattlePartyID\n\ + ldrb r0, [r4]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldrh r0, [r0]\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + bl _08020996\n\ + .align 2, 0\n\ +_080200E8: .4byte 0x02000000\n\ +_080200EC: .4byte 0x0001600f\n\ +_080200F0: .4byte 0x00016113\n\ +_080200F4: .4byte gBitTable\n\ +_080200F8: .4byte gBattlePartyID\n\ +_080200FC:\n\ + movs r5, 0\n\ + movs r7, 0\n\ + ldr r1, _08020150 @ =gSaveBlock1 + 0x3688\n\ + mov r9, r1\n\ +_08020104:\n\ + movs r0, 0x64\n\ + adds r1, r7, 0\n\ + muls r1, r0\n\ + ldr r0, _08020154 @ =gPlayerParty\n\ + adds r4, r1, r0\n\ + adds r0, r4, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0802016A\n\ + adds r0, r4, 0\n\ + movs r1, 0x39\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0802016A\n\ + ldr r0, _08020158 @ =gBitTable\n\ + lsls r1, r7, 2\n\ + adds r1, r0\n\ + ldr r0, [r1]\n\ + mov r2, r8\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + beq _08020138\n\ + adds r5, 0x1\n\ +_08020138:\n\ + adds r0, r4, 0\n\ + movs r1, 0xC\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0xAF\n\ + bne _0802015C\n\ + mov r3, r9\n\ + ldrb r4, [r3]\n\ + b _08020164\n\ + .align 2, 0\n\ +_08020150: .4byte gSaveBlock1 + 0x3688\n\ +_08020154: .4byte gPlayerParty\n\ +_08020158: .4byte gBitTable\n\ +_0802015C:\n\ + bl ItemId_GetHoldEffect\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ +_08020164:\n\ + cmp r4, 0x19\n\ + bne _0802016A\n\ + adds r6, 0x1\n\ +_0802016A:\n\ + adds r7, 0x1\n\ + cmp r7, 0x5\n\ + ble _08020104\n\ + ldr r3, _080201D0 @ =gBaseStats\n\ + ldr r2, _080201D4 @ =gBattleMons\n\ + ldr r0, _080201D8 @ =gBank1\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r1, r0\n\ + adds r1, r2\n\ + ldrh r2, [r1]\n\ + lsls r0, r2, 3\n\ + subs r0, r2\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldrb r2, [r0, 0x9]\n\ + adds r1, 0x2A\n\ + ldrb r0, [r1]\n\ + muls r0, r2\n\ + movs r1, 0x7\n\ + bl __divsi3\n\ + lsls r0, 16\n\ + lsrs r1, r0, 16\n\ + cmp r6, 0\n\ + beq _080201E0\n\ + lsrs r4, r0, 17\n\ + adds r0, r4, 0\n\ + adds r1, r5, 0\n\ + bl __divsi3\n\ + mov r1, r10\n\ + strh r0, [r1]\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + bne _080201B6\n\ + movs r0, 0x1\n\ + strh r0, [r1]\n\ +_080201B6:\n\ + ldr r5, _080201DC @ =gExpShareExp\n\ + adds r0, r4, 0\n\ + adds r1, r6, 0\n\ + bl __divsi3\n\ + strh r0, [r5]\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + bne _080201FA\n\ + movs r0, 0x1\n\ + strh r0, [r5]\n\ + b _080201FA\n\ + .align 2, 0\n\ +_080201D0: .4byte gBaseStats\n\ +_080201D4: .4byte gBattleMons\n\ +_080201D8: .4byte gBank1\n\ +_080201DC: .4byte gExpShareExp\n\ +_080201E0:\n\ + adds r0, r1, 0\n\ + adds r1, r5, 0\n\ + bl __divsi3\n\ + mov r2, r10\n\ + strh r0, [r2]\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + bne _080201F6\n\ + movs r0, 0x1\n\ + strh r0, [r2]\n\ +_080201F6:\n\ + ldr r0, _08020248 @ =gExpShareExp\n\ + strh r6, [r0]\n\ +_080201FA:\n\ + ldr r1, _0802024C @ =0x02000000\n\ + ldr r3, _08020250 @ =0x0001600f\n\ + adds r2, r1, r3\n\ + ldrb r0, [r2]\n\ + adds r0, 0x1\n\ + movs r3, 0\n\ + strb r0, [r2]\n\ + ldr r2, _08020254 @ =0x00016018\n\ + adds r0, r1, r2\n\ + strb r3, [r0]\n\ + ldr r3, _08020258 @ =0x0001605f\n\ + adds r1, r3\n\ + mov r0, r8\n\ + strb r0, [r1]\n\ +_08020216:\n\ + ldr r0, _0802025C @ =gBattleExecBuffer\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _08020220\n\ + b _08020996\n\ +_08020220:\n\ + ldr r0, _0802024C @ =0x02000000\n\ + ldr r1, _08020254 @ =0x00016018\n\ + adds r0, r1\n\ + ldrb r1, [r0]\n\ + movs r0, 0x64\n\ + muls r0, r1\n\ + ldr r1, _08020260 @ =gPlayerParty\n\ + adds r0, r1\n\ + movs r1, 0xC\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0xAF\n\ + bne _0802026C\n\ + ldr r0, _08020264 @ =gSaveBlock1\n\ + ldr r2, _08020268 @ =0x00003688\n\ + adds r0, r2\n\ + ldrb r4, [r0]\n\ + b _08020274\n\ + .align 2, 0\n\ +_08020248: .4byte gExpShareExp\n\ +_0802024C: .4byte 0x02000000\n\ +_08020250: .4byte 0x0001600f\n\ +_08020254: .4byte 0x00016018\n\ +_08020258: .4byte 0x0001605f\n\ +_0802025C: .4byte gBattleExecBuffer\n\ +_08020260: .4byte gPlayerParty\n\ +_08020264: .4byte gSaveBlock1\n\ +_08020268: .4byte 0x00003688\n\ +_0802026C:\n\ + bl ItemId_GetHoldEffect\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ +_08020274:\n\ + ldr r5, _08020294 @ =0x02000000\n\ + cmp r4, 0x19\n\ + beq _080202A0\n\ + ldr r3, _08020298 @ =0x0001605f\n\ + adds r1, r5, r3\n\ + ldrb r0, [r1]\n\ + movs r2, 0x1\n\ + ands r2, r0\n\ + cmp r2, 0\n\ + bne _080202A0\n\ + lsrs r0, 1\n\ + strb r0, [r1]\n\ + ldr r0, _0802029C @ =0x0001600f\n\ + adds r1, r5, r0\n\ + b _080202C8\n\ + .align 2, 0\n\ +_08020294: .4byte 0x02000000\n\ +_08020298: .4byte 0x0001605f\n\ +_0802029C: .4byte 0x0001600f\n\ +_080202A0:\n\ + ldr r1, _080202D4 @ =0x00016018\n\ + adds r0, r5, r1\n\ + ldrb r1, [r0]\n\ + movs r0, 0x64\n\ + muls r0, r1\n\ + ldr r1, _080202D8 @ =gPlayerParty\n\ + adds r0, r1\n\ + movs r1, 0x38\n\ + bl GetMonData\n\ + cmp r0, 0x64\n\ + bne _080202E8\n\ + ldr r2, _080202DC @ =0x0001605f\n\ + adds r1, r5, r2\n\ + ldrb r0, [r1]\n\ + lsrs r0, 1\n\ + movs r2, 0\n\ + strb r0, [r1]\n\ + ldr r3, _080202E0 @ =0x0001600f\n\ + adds r1, r5, r3\n\ +_080202C8:\n\ + movs r0, 0x5\n\ + strb r0, [r1]\n\ + ldr r0, _080202E4 @ =gBattleMoveDamage\n\ + str r2, [r0]\n\ + b _08020996\n\ + .align 2, 0\n\ +_080202D4: .4byte 0x00016018\n\ +_080202D8: .4byte gPlayerParty\n\ +_080202DC: .4byte 0x0001605f\n\ +_080202E0: .4byte 0x0001600f\n\ +_080202E4: .4byte gBattleMoveDamage\n\ +_080202E8:\n\ + ldr r0, _0802034C @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08020316\n\ + ldr r0, _08020350 @ =gBattleMons\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + beq _08020316\n\ + ldr r0, _08020354 @ =0x0001601b\n\ + adds r5, r0\n\ + ldrb r0, [r5]\n\ + cmp r0, 0\n\ + bne _08020316\n\ + bl BattleMusicStop\n\ + ldr r0, _08020358 @ =0x00000161\n\ + bl PlayBGM\n\ + ldrb r0, [r5]\n\ + adds r0, 0x1\n\ + strb r0, [r5]\n\ +_08020316:\n\ + ldr r5, _0802035C @ =0x02000000\n\ + ldr r1, _08020360 @ =0x00016018\n\ + adds r0, r5, r1\n\ + ldrb r1, [r0]\n\ + movs r0, 0x64\n\ + muls r0, r1\n\ + ldr r1, _08020364 @ =gPlayerParty\n\ + adds r0, r1\n\ + movs r1, 0x39\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _08020332\n\ + b _0802051E\n\ +_08020332:\n\ + ldr r2, _08020368 @ =0x0001605f\n\ + adds r0, r5, r2\n\ + ldrb r0, [r0]\n\ + movs r3, 0x1\n\ + ands r3, r0\n\ + cmp r3, 0\n\ + beq _08020370\n\ + ldr r1, _0802036C @ =gBattleMoveDamage\n\ + mov r3, r10\n\ + ldrh r0, [r3]\n\ + str r0, [r1]\n\ + mov r8, r1\n\ + b _08020376\n\ + .align 2, 0\n\ +_0802034C: .4byte gBattleTypeFlags\n\ +_08020350: .4byte gBattleMons\n\ +_08020354: .4byte 0x0001601b\n\ +_08020358: .4byte 0x00000161\n\ +_0802035C: .4byte 0x02000000\n\ +_08020360: .4byte 0x00016018\n\ +_08020364: .4byte gPlayerParty\n\ +_08020368: .4byte 0x0001605f\n\ +_0802036C: .4byte gBattleMoveDamage\n\ +_08020370:\n\ + ldr r0, _080203EC @ =gBattleMoveDamage\n\ + str r3, [r0]\n\ + mov r8, r0\n\ +_08020376:\n\ + cmp r4, 0x19\n\ + bne _08020386\n\ + ldr r0, _080203F0 @ =gExpShareExp\n\ + ldrh r1, [r0]\n\ + mov r2, r8\n\ + ldr r0, [r2]\n\ + adds r0, r1\n\ + str r0, [r2]\n\ +_08020386:\n\ + cmp r4, 0x28\n\ + bne _0802039C\n\ + mov r3, r8\n\ + ldr r1, [r3]\n\ + movs r0, 0x96\n\ + muls r0, r1\n\ + movs r1, 0x64\n\ + bl __divsi3\n\ + mov r1, r8\n\ + str r0, [r1]\n\ +_0802039C:\n\ + ldr r0, _080203F4 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080203B8\n\ + ldr r4, _080203EC @ =gBattleMoveDamage\n\ + ldr r1, [r4]\n\ + movs r0, 0x96\n\ + muls r0, r1\n\ + movs r1, 0x64\n\ + bl __divsi3\n\ + str r0, [r4]\n\ +_080203B8:\n\ + ldr r0, _080203F8 @ =0x02000000\n\ + ldr r2, _080203FC @ =0x00016018\n\ + adds r0, r2\n\ + ldrb r1, [r0]\n\ + movs r0, 0x64\n\ + muls r0, r1\n\ + ldr r1, _08020400 @ =gPlayerParty\n\ + adds r0, r1\n\ + bl IsTradedMon\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08020404\n\ + ldr r4, _080203EC @ =gBattleMoveDamage\n\ + ldr r1, [r4]\n\ + movs r0, 0x96\n\ + muls r0, r1\n\ + movs r1, 0x64\n\ + bl __divsi3\n\ + str r0, [r4]\n\ + movs r7, 0xA5\n\ + lsls r7, 1\n\ + mov r8, r4\n\ + b _0802040A\n\ + .align 2, 0\n\ +_080203EC: .4byte gBattleMoveDamage\n\ +_080203F0: .4byte gExpShareExp\n\ +_080203F4: .4byte gBattleTypeFlags\n\ +_080203F8: .4byte 0x02000000\n\ +_080203FC: .4byte 0x00016018\n\ +_08020400: .4byte gPlayerParty\n\ +_08020404:\n\ + ldr r7, _0802043C @ =0x00000149\n\ + ldr r3, _08020440 @ =gBattleMoveDamage\n\ + mov r8, r3\n\ +_0802040A:\n\ + ldr r0, _08020444 @ =gBattleTypeFlags\n\ + ldrh r0, [r0]\n\ + movs r1, 0x1\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + beq _08020488\n\ + ldr r1, _08020448 @ =gBattlePartyID\n\ + ldr r0, _0802044C @ =0x02000000\n\ + ldr r3, _08020450 @ =0x00016018\n\ + adds r2, r0, r3\n\ + ldrh r1, [r1, 0x4]\n\ + adds r5, r0, 0\n\ + ldr r4, _08020454 @ =gBitTable\n\ + ldr r3, _08020458 @ =gAbsentBankFlags\n\ + ldrb r2, [r2]\n\ + cmp r1, r2\n\ + bne _08020460\n\ + ldrb r1, [r3]\n\ + ldr r0, [r4, 0x8]\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + bne _08020460\n\ + ldr r0, _0802045C @ =0x000160a2\n\ + adds r1, r5, r0\n\ + b _0802047C\n\ + .align 2, 0\n\ +_0802043C: .4byte 0x00000149\n\ +_08020440: .4byte gBattleMoveDamage\n\ +_08020444: .4byte gBattleTypeFlags\n\ +_08020448: .4byte gBattlePartyID\n\ +_0802044C: .4byte 0x02000000\n\ +_08020450: .4byte 0x00016018\n\ +_08020454: .4byte gBitTable\n\ +_08020458: .4byte gAbsentBankFlags\n\ +_0802045C: .4byte 0x000160a2\n\ +_08020460:\n\ + ldrb r2, [r3]\n\ + ldr r0, [r4]\n\ + ands r2, r0\n\ + cmp r2, 0\n\ + bne _08020478\n\ + ldr r1, _08020474 @ =0x000160a2\n\ + adds r0, r5, r1\n\ + strb r2, [r0]\n\ + b _08020490\n\ + .align 2, 0\n\ +_08020474: .4byte 0x000160a2\n\ +_08020478:\n\ + ldr r2, _08020484 @ =0x000160a2\n\ + adds r1, r5, r2\n\ +_0802047C:\n\ + movs r0, 0x2\n\ + strb r0, [r1]\n\ + b _08020490\n\ + .align 2, 0\n\ +_08020484: .4byte 0x000160a2\n\ +_08020488:\n\ + ldr r0, _08020530 @ =0x02000000\n\ + ldr r3, _08020534 @ =0x000160a2\n\ + adds r0, r3\n\ + strb r1, [r0]\n\ +_08020490:\n\ + ldr r1, _08020538 @ =gBattleTextBuff1\n\ + movs r3, 0\n\ + movs r2, 0xFD\n\ + strb r2, [r1]\n\ + movs r5, 0x4\n\ + strb r5, [r1, 0x1]\n\ + ldr r4, _08020530 @ =0x02000000\n\ + ldr r0, _08020534 @ =0x000160a2\n\ + adds r6, r4, r0\n\ + ldrb r0, [r6]\n\ + strb r0, [r1, 0x2]\n\ + ldr r0, _0802053C @ =0x00016018\n\ + adds r4, r0\n\ + ldrb r0, [r4]\n\ + strb r0, [r1, 0x3]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x4]\n\ + ldr r1, _08020540 @ =gBattleTextBuff2\n\ + strb r2, [r1]\n\ + strb r3, [r1, 0x1]\n\ + strb r7, [r1, 0x2]\n\ + movs r3, 0xFF\n\ + lsls r3, 8\n\ + ands r7, r3\n\ + asrs r0, r7, 8\n\ + strb r0, [r1, 0x3]\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + strb r0, [r1, 0x4]\n\ + ldr r1, _08020544 @ =gBattleTextBuff3\n\ + strb r2, [r1]\n\ + movs r0, 0x1\n\ + strb r0, [r1, 0x1]\n\ + strb r5, [r1, 0x2]\n\ + movs r0, 0x5\n\ + strb r0, [r1, 0x3]\n\ + mov r0, r8\n\ + ldr r2, [r0]\n\ + strb r2, [r1, 0x4]\n\ + adds r0, r2, 0\n\ + ands r0, r3\n\ + asrs r0, 8\n\ + strb r0, [r1, 0x5]\n\ + movs r0, 0xFF\n\ + lsls r0, 16\n\ + ands r0, r2\n\ + asrs r0, 16\n\ + strb r0, [r1, 0x6]\n\ + lsrs r2, 24\n\ + strb r2, [r1, 0x7]\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + strb r0, [r1, 0x8]\n\ + ldrb r1, [r6]\n\ + movs r0, 0xD\n\ + bl PrepareStringBattle\n\ + ldrb r1, [r4]\n\ + movs r0, 0x64\n\ + muls r0, r1\n\ + ldr r1, _08020548 @ =gPlayerParty\n\ + adds r0, r1\n\ + ldr r3, _0802054C @ =gBattleMons\n\ + ldr r1, _08020550 @ =gBank1\n\ + ldrb r2, [r1]\n\ + movs r1, 0x58\n\ + muls r1, r2\n\ + adds r1, r3\n\ + ldrh r1, [r1]\n\ + bl MonGainEVs\n\ +_0802051E:\n\ + ldr r1, _08020530 @ =0x02000000\n\ + ldr r3, _08020554 @ =0x0001605f\n\ + adds r2, r1, r3\n\ + ldrb r0, [r2]\n\ + lsrs r0, 1\n\ + strb r0, [r2]\n\ + ldr r0, _08020558 @ =0x0001600f\n\ + adds r1, r0\n\ + b _08020618\n\ + .align 2, 0\n\ +_08020530: .4byte 0x02000000\n\ +_08020534: .4byte 0x000160a2\n\ +_08020538: .4byte gBattleTextBuff1\n\ +_0802053C: .4byte 0x00016018\n\ +_08020540: .4byte gBattleTextBuff2\n\ +_08020544: .4byte gBattleTextBuff3\n\ +_08020548: .4byte gPlayerParty\n\ +_0802054C: .4byte gBattleMons\n\ +_08020550: .4byte gBank1\n\ +_08020554: .4byte 0x0001605f\n\ +_08020558: .4byte 0x0001600f\n\ +_0802055C:\n\ + ldr r0, _08020620 @ =gBattleExecBuffer\n\ + ldr r2, [r0]\n\ + cmp r2, 0\n\ + beq _08020566\n\ + b _08020996\n\ +_08020566:\n\ + ldr r1, _08020624 @ =gBattleBufferB\n\ + ldr r4, _08020628 @ =0x02000000\n\ + ldr r3, _0802062C @ =0x000160a2\n\ + adds r3, r4\n\ + mov r8, r3\n\ + ldrb r0, [r3]\n\ + lsls r0, 9\n\ + adds r0, r1\n\ + strb r2, [r0]\n\ + ldr r0, _08020630 @ =0x00016018\n\ + adds r7, r4, r0\n\ + ldrb r0, [r7]\n\ + movs r6, 0x64\n\ + muls r0, r6\n\ + ldr r5, _08020634 @ =gPlayerParty\n\ + adds r0, r5\n\ + movs r1, 0x39\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _08020612\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r0, r5\n\ + movs r1, 0x38\n\ + bl GetMonData\n\ + cmp r0, 0x64\n\ + beq _08020612\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r0, r5\n\ + movs r1, 0x3A\n\ + bl GetMonData\n\ + ldr r1, _08020638 @ =0x00017180\n\ + adds r4, r1\n\ + strh r0, [r4]\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r0, r5\n\ + movs r1, 0x3B\n\ + bl GetMonData\n\ + strh r0, [r4, 0x2]\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r0, r5\n\ + movs r1, 0x3C\n\ + bl GetMonData\n\ + strh r0, [r4, 0x4]\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r0, r5\n\ + movs r1, 0x3D\n\ + bl GetMonData\n\ + strh r0, [r4, 0x6]\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r0, r5\n\ + movs r1, 0x3E\n\ + bl GetMonData\n\ + strh r0, [r4, 0x8]\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + adds r0, r5\n\ + movs r1, 0x3F\n\ + bl GetMonData\n\ + strh r0, [r4, 0xA]\n\ + ldr r4, _0802063C @ =gActiveBank\n\ + mov r2, r8\n\ + ldrb r0, [r2]\n\ + strb r0, [r4]\n\ + ldrb r1, [r7]\n\ + ldr r0, _08020640 @ =gBattleMoveDamage\n\ + ldrh r2, [r0]\n\ + movs r0, 0\n\ + bl EmitExpBarUpdate\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ +_08020612:\n\ + ldr r1, _08020628 @ =0x02000000\n\ + ldr r3, _08020644 @ =0x0001600f\n\ + adds r1, r3\n\ +_08020618:\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ + b _08020996\n\ + .align 2, 0\n\ +_08020620: .4byte gBattleExecBuffer\n\ +_08020624: .4byte gBattleBufferB\n\ +_08020628: .4byte 0x02000000\n\ +_0802062C: .4byte 0x000160a2\n\ +_08020630: .4byte 0x00016018\n\ +_08020634: .4byte gPlayerParty\n\ +_08020638: .4byte 0x00017180\n\ +_0802063C: .4byte gActiveBank\n\ +_08020640: .4byte gBattleMoveDamage\n\ +_08020644: .4byte 0x0001600f\n\ +_08020648:\n\ + ldr r0, _080208AC @ =gBattleExecBuffer\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _08020652\n\ + b _08020996\n\ +_08020652:\n\ + ldr r1, _080208B0 @ =gActiveBank\n\ + ldr r4, _080208B4 @ =0x02000000\n\ + ldr r2, _080208B8 @ =0x000160a2\n\ + adds r0, r4, r2\n\ + ldrb r0, [r0]\n\ + strb r0, [r1]\n\ + ldr r2, _080208BC @ =gBattleBufferB\n\ + ldrb r3, [r1]\n\ + lsls r1, r3, 9\n\ + adds r0, r1, r2\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x21\n\ + beq _0802066E\n\ + b _080208F0\n\ +_0802066E:\n\ + adds r0, r2, 0x1\n\ + adds r0, r1, r0\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xB\n\ + beq _0802067A\n\ + b _080208F0\n\ +_0802067A:\n\ + ldr r0, _080208C0 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080206A8\n\ + ldr r1, _080208C4 @ =gBattlePartyID\n\ + lsls r0, r3, 1\n\ + adds r2, r0, r1\n\ + ldr r0, _080208C8 @ =0x00016018\n\ + adds r1, r4, r0\n\ + ldrh r0, [r2]\n\ + ldrb r1, [r1]\n\ + cmp r0, r1\n\ + bne _080206A8\n\ + adds r1, r0, 0\n\ + movs r0, 0x64\n\ + muls r0, r1\n\ + ldr r1, _080208CC @ =gPlayerParty\n\ + adds r0, r1\n\ + adds r1, r3, 0\n\ + bl sub_80324F8\n\ +_080206A8:\n\ + ldr r1, _080208D0 @ =gBattleTextBuff1\n\ + movs r2, 0xFD\n\ + strb r2, [r1]\n\ + movs r0, 0x4\n\ + strb r0, [r1, 0x1]\n\ + ldr r5, _080208B0 @ =gActiveBank\n\ + ldrb r0, [r5]\n\ + strb r0, [r1, 0x2]\n\ + ldr r0, _080208B4 @ =0x02000000\n\ + ldr r3, _080208C8 @ =0x00016018\n\ + adds r6, r0, r3\n\ + ldrb r0, [r6]\n\ + strb r0, [r1, 0x3]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x4]\n\ + ldr r4, _080208D4 @ =gBattleTextBuff2\n\ + strb r2, [r4]\n\ + movs r0, 0x1\n\ + strb r0, [r4, 0x1]\n\ + strb r0, [r4, 0x2]\n\ + movs r0, 0x3\n\ + strb r0, [r4, 0x3]\n\ + ldrb r0, [r6]\n\ + movs r1, 0x64\n\ + mov r8, r1\n\ + mov r2, r8\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + ldr r7, _080208CC @ =gPlayerParty\n\ + adds r0, r7\n\ + movs r1, 0x38\n\ + bl GetMonData\n\ + strb r0, [r4, 0x4]\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + strb r0, [r4, 0x5]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r2, _080208D8 @ =gLeveledUpInBattle\n\ + ldr r1, _080208DC @ =gBitTable\n\ + ldrb r0, [r6]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r1, _080208E0 @ =gBattlescriptCurrInstr\n\ + ldr r0, _080208E4 @ =BattleScript_LevelUp\n\ + str r0, [r1]\n\ + ldr r4, _080208E8 @ =gBattleMoveDamage\n\ + ldr r2, _080208BC @ =gBattleBufferB\n\ + ldrb r1, [r5]\n\ + lsls r1, 9\n\ + adds r0, r2, 0x2\n\ + adds r0, r1, r0\n\ + ldrb r3, [r0]\n\ + adds r2, 0x3\n\ + adds r1, r2\n\ + ldrb r0, [r1]\n\ + lsls r0, 8\n\ + orrs r3, r0\n\ + str r3, [r4]\n\ + ldrb r0, [r6]\n\ + mov r3, r8\n\ + muls r3, r0\n\ + adds r0, r3, 0\n\ + adds r0, r7\n\ + movs r1, 0\n\ + bl AdjustFriendship\n\ + ldr r0, _080208C4 @ =gBattlePartyID\n\ + ldrb r1, [r6]\n\ + ldrh r0, [r0]\n\ + cmp r0, r1\n\ + bne _080207EC\n\ + ldr r4, _080208EC @ =gBattleMons\n\ + ldrh r0, [r4, 0x28]\n\ + cmp r0, 0\n\ + beq _080207EC\n\ + mov r0, r8\n\ + muls r0, r1\n\ + adds r0, r7\n\ + movs r1, 0x38\n\ + bl GetMonData\n\ + adds r1, r4, 0\n\ + adds r1, 0x2A\n\ + strb r0, [r1]\n\ + ldrb r0, [r6]\n\ + mov r1, r8\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + adds r0, r7\n\ + movs r1, 0x39\n\ + bl GetMonData\n\ + strh r0, [r4, 0x28]\n\ + ldrb r0, [r6]\n\ + mov r2, r8\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + adds r0, r7\n\ + movs r1, 0x3A\n\ + bl GetMonData\n\ + strh r0, [r4, 0x2C]\n\ + ldrb r0, [r6]\n\ + mov r3, r8\n\ + muls r3, r0\n\ + adds r0, r3, 0\n\ + adds r0, r7\n\ + movs r1, 0x3B\n\ + bl GetMonData\n\ + strh r0, [r4, 0x2]\n\ + ldrb r0, [r6]\n\ + mov r1, r8\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + adds r0, r7\n\ + movs r1, 0x3C\n\ + bl GetMonData\n\ + strh r0, [r4, 0x4]\n\ + ldrb r0, [r6]\n\ + mov r2, r8\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + adds r0, r7\n\ + movs r1, 0x3D\n\ + bl GetMonData\n\ + strh r0, [r4, 0x6]\n\ + ldrb r0, [r6]\n\ + mov r3, r8\n\ + muls r3, r0\n\ + adds r0, r3, 0\n\ + adds r0, r7\n\ + movs r1, 0x3D\n\ + bl GetMonData\n\ + strh r0, [r4, 0x6]\n\ + ldrb r0, [r6]\n\ + mov r1, r8\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + adds r0, r7\n\ + movs r1, 0x3E\n\ + bl GetMonData\n\ + strh r0, [r4, 0x8]\n\ + ldrb r0, [r6]\n\ + mov r2, r8\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + adds r0, r7\n\ + movs r1, 0x3F\n\ + bl GetMonData\n\ + strh r0, [r4, 0xA]\n\ +_080207EC:\n\ + ldr r0, _080208C4 @ =gBattlePartyID\n\ + ldr r1, _080208B4 @ =0x02000000\n\ + ldr r3, _080208C8 @ =0x00016018\n\ + adds r7, r1, r3\n\ + ldrb r2, [r7]\n\ + ldrh r0, [r0, 0x4]\n\ + cmp r0, r2\n\ + bne _080208F6\n\ + ldr r6, _080208EC @ =gBattleMons\n\ + movs r0, 0xD8\n\ + adds r0, r6\n\ + mov r8, r0\n\ + ldrh r0, [r0]\n\ + cmp r0, 0\n\ + beq _080208F6\n\ + ldr r0, _080208C0 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080208F6\n\ + movs r5, 0x64\n\ + adds r0, r2, 0\n\ + muls r0, r5\n\ + ldr r4, _080208CC @ =gPlayerParty\n\ + adds r0, r4\n\ + movs r1, 0x38\n\ + bl GetMonData\n\ + adds r1, r6, 0\n\ + adds r1, 0xDA\n\ + strb r0, [r1]\n\ + ldrb r0, [r7]\n\ + muls r0, r5\n\ + adds r0, r4\n\ + movs r1, 0x39\n\ + bl GetMonData\n\ + mov r1, r8\n\ + strh r0, [r1]\n\ + ldrb r0, [r7]\n\ + muls r0, r5\n\ + adds r0, r4\n\ + movs r1, 0x3A\n\ + bl GetMonData\n\ + adds r1, r6, 0\n\ + adds r1, 0xDC\n\ + strh r0, [r1]\n\ + ldrb r0, [r7]\n\ + muls r0, r5\n\ + adds r0, r4\n\ + movs r1, 0x3B\n\ + bl GetMonData\n\ + adds r1, r6, 0\n\ + adds r1, 0xB2\n\ + strh r0, [r1]\n\ + ldrb r0, [r7]\n\ + muls r0, r5\n\ + adds r0, r4\n\ + movs r1, 0x3C\n\ + bl GetMonData\n\ + adds r1, r6, 0\n\ + adds r1, 0xB4\n\ + strh r0, [r1]\n\ + ldrb r0, [r7]\n\ + muls r0, r5\n\ + adds r0, r4\n\ + movs r1, 0x3D\n\ + bl GetMonData\n\ + movs r2, 0xB6\n\ + adds r2, r6\n\ + mov r8, r2\n\ + strh r0, [r2]\n\ + ldrb r0, [r7]\n\ + muls r0, r5\n\ + adds r0, r4\n\ + movs r1, 0x3D\n\ + bl GetMonData\n\ + mov r3, r8\n\ + strh r0, [r3]\n\ + ldrb r0, [r7]\n\ + muls r0, r5\n\ + adds r0, r4\n\ + movs r1, 0x3E\n\ + bl GetMonData\n\ + adds r1, r6, 0\n\ + adds r1, 0xB8\n\ + strh r0, [r1]\n\ + b _080208F6\n\ + .align 2, 0\n\ +_080208AC: .4byte gBattleExecBuffer\n\ +_080208B0: .4byte gActiveBank\n\ +_080208B4: .4byte 0x02000000\n\ +_080208B8: .4byte 0x000160a2\n\ +_080208BC: .4byte gBattleBufferB\n\ +_080208C0: .4byte gBattleTypeFlags\n\ +_080208C4: .4byte gBattlePartyID\n\ +_080208C8: .4byte 0x00016018\n\ +_080208CC: .4byte gPlayerParty\n\ +_080208D0: .4byte gBattleTextBuff1\n\ +_080208D4: .4byte gBattleTextBuff2\n\ +_080208D8: .4byte gLeveledUpInBattle\n\ +_080208DC: .4byte gBitTable\n\ +_080208E0: .4byte gBattlescriptCurrInstr\n\ +_080208E4: .4byte BattleScript_LevelUp\n\ +_080208E8: .4byte gBattleMoveDamage\n\ +_080208EC: .4byte gBattleMons\n\ +_080208F0:\n\ + ldr r1, _08020904 @ =gBattleMoveDamage\n\ + movs r0, 0\n\ + str r0, [r1]\n\ +_080208F6:\n\ + ldr r0, _08020908 @ =0x02000000\n\ + ldr r1, _0802090C @ =0x0001600f\n\ + adds r0, r1\n\ + movs r1, 0x5\n\ + strb r1, [r0]\n\ + b _08020996\n\ + .align 2, 0\n\ +_08020904: .4byte gBattleMoveDamage\n\ +_08020908: .4byte 0x02000000\n\ +_0802090C: .4byte 0x0001600f\n\ +_08020910:\n\ + ldr r0, _08020924 @ =gBattleMoveDamage\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _08020930\n\ + ldr r0, _08020928 @ =0x02000000\n\ + ldr r2, _0802092C @ =0x0001600f\n\ + adds r0, r2\n\ + movs r1, 0x3\n\ + strb r1, [r0]\n\ + b _08020996\n\ + .align 2, 0\n\ +_08020924: .4byte gBattleMoveDamage\n\ +_08020928: .4byte 0x02000000\n\ +_0802092C: .4byte 0x0001600f\n\ +_08020930:\n\ + ldr r2, _08020950 @ =0x02000000\n\ + ldr r3, _08020954 @ =0x00016018\n\ + adds r1, r2, r3\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x5\n\ + bhi _0802095C\n\ + ldr r0, _08020958 @ =0x0001600f\n\ + adds r1, r2, r0\n\ + movs r0, 0x2\n\ + strb r0, [r1]\n\ + b _08020996\n\ + .align 2, 0\n\ +_08020950: .4byte 0x02000000\n\ +_08020954: .4byte 0x00016018\n\ +_08020958: .4byte 0x0001600f\n\ +_0802095C:\n\ + ldr r3, _08020968 @ =0x0001600f\n\ + adds r1, r2, r3\n\ + movs r0, 0x6\n\ + strb r0, [r1]\n\ + b _08020996\n\ + .align 2, 0\n\ +_08020968: .4byte 0x0001600f\n\ +_0802096C:\n\ + ldr r0, _080209A4 @ =gBattleExecBuffer\n\ + ldr r5, [r0]\n\ + cmp r5, 0\n\ + bne _08020996\n\ + ldr r4, _080209A8 @ =gBattleMons\n\ + ldr r2, _080209AC @ =gBank1\n\ + ldrb r0, [r2]\n\ + movs r1, 0x58\n\ + muls r0, r1\n\ + adds r0, r4\n\ + movs r3, 0\n\ + strh r5, [r0, 0x2E]\n\ + ldrb r0, [r2]\n\ + muls r0, r1\n\ + adds r0, r4\n\ + adds r0, 0x20\n\ + strb r3, [r0]\n\ + ldr r1, _080209B0 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x2\n\ + str r0, [r1]\n\ +_08020996:\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080209A4: .4byte gBattleExecBuffer\n\ +_080209A8: .4byte gBattleMons\n\ +_080209AC: .4byte gBank1\n\ +_080209B0: .4byte gBattlescriptCurrInstr\n\ + .syntax divided\n"); +} + +#endif // NONMATCHING + +#ifdef NONMATCHING +static void atk24(void) +{ + u16 HP_count = 0; + int i; + if (gBattleExecBuffer) {return;} + + for (i = 0; i < 6; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + HP_count += GetMonData(&gPlayerParty[i], MON_DATA_HP); + } + + if (HP_count == 0) + gBattleOutcome |= BATTLE_LOST; + + for (HP_count = 0, i = 0; i < 6; i++) + { + if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES) && !GetMonData(&gEnemyParty[i], MON_DATA_IS_EGG)) + HP_count += GetMonData(&gEnemyParty[i], MON_DATA_HP); + } + + if (!HP_count) + gBattleOutcome |= BATTLE_WON; + + if (!gBattleOutcome && (gBattleTypeFlags & BATTLE_TYPE_LINK)) + { + register int found1 asm("r2"); + register int found2 asm("r4"); + + //I can't for the love of god decompile that part + + for (found1 = 0, i = 0; i < gNoOfAllBanks; i += 2) + { + if ((gHitMarker & HITMARKER_UNK(i)) && !gSpecialStatuses[i].flag40) + found1++; + } + + for (found2 = 0, i = 1; i < gNoOfAllBanks; i += 2) + { + if ((gHitMarker & HITMARKER_UNK(i)) && !gSpecialStatuses[i].flag40) + found2++; + } + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (found2 + found1 > 1) + gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + else + gBattlescriptCurrInstr += 5; + } + else + { + if (found2 != 0 && found1 != 0) + gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + else + gBattlescriptCurrInstr += 5; + } + } + else + gBattlescriptCurrInstr += 5; + +} +#else +__attribute__((naked)) +static void atk24(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + movs r6, 0\n\ + ldr r0, _08020AF0 @ =gBattleExecBuffer\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _080209C6\n\ + b _08020B46\n\ +_080209C6:\n\ + movs r5, 0\n\ +_080209C8:\n\ + movs r0, 0x64\n\ + adds r1, r5, 0\n\ + muls r1, r0\n\ + ldr r0, _08020AF4 @ =gPlayerParty\n\ + adds r4, r1, r0\n\ + adds r0, r4, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _080209F8\n\ + adds r0, r4, 0\n\ + movs r1, 0x2D\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _080209F8\n\ + adds r0, r4, 0\n\ + movs r1, 0x39\n\ + bl GetMonData\n\ + adds r0, r6, r0\n\ + lsls r0, 16\n\ + lsrs r6, r0, 16\n\ +_080209F8:\n\ + adds r5, 0x1\n\ + cmp r5, 0x5\n\ + ble _080209C8\n\ + cmp r6, 0\n\ + bne _08020A0C\n\ + ldr r0, _08020AF8 @ =gBattleOutcome\n\ + ldrb r1, [r0]\n\ + movs r2, 0x2\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ +_08020A0C:\n\ + movs r6, 0\n\ + movs r5, 0\n\ +_08020A10:\n\ + movs r0, 0x64\n\ + adds r1, r5, 0\n\ + muls r1, r0\n\ + ldr r0, _08020AFC @ =gEnemyParty\n\ + adds r4, r1, r0\n\ + adds r0, r4, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _08020A40\n\ + adds r0, r4, 0\n\ + movs r1, 0x2D\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _08020A40\n\ + adds r0, r4, 0\n\ + movs r1, 0x39\n\ + bl GetMonData\n\ + adds r0, r6, r0\n\ + lsls r0, 16\n\ + lsrs r6, r0, 16\n\ +_08020A40:\n\ + adds r5, 0x1\n\ + cmp r5, 0x5\n\ + ble _08020A10\n\ + ldr r2, _08020AF8 @ =gBattleOutcome\n\ + cmp r6, 0\n\ + bne _08020A54\n\ + ldrb r0, [r2]\n\ + movs r1, 0x1\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ +_08020A54:\n\ + ldrb r0, [r2]\n\ + cmp r0, 0\n\ + bne _08020B3E\n\ + ldr r2, _08020B00 @ =gBattleTypeFlags\n\ + ldrh r1, [r2]\n\ + movs r0, 0x2\n\ + ands r0, r1\n\ + mov r8, r2\n\ + cmp r0, 0\n\ + beq _08020B3E\n\ + movs r2, 0\n\ + movs r5, 0\n\ + ldr r0, _08020B04 @ =gNoOfAllBanks\n\ + ldrb r3, [r0]\n\ + mov r12, r0\n\ + ldr r7, _08020B08 @ =gBattlescriptCurrInstr\n\ + cmp r2, r3\n\ + bge _08020AA0\n\ + ldr r0, _08020B0C @ =gHitMarker\n\ + movs r1, 0x80\n\ + lsls r1, 21\n\ + ldr r6, [r0]\n\ + adds r4, r3, 0\n\ + ldr r3, _08020B10 @ =gSpecialStatuses\n\ +_08020A84:\n\ + adds r0, r1, 0\n\ + lsls r0, r5\n\ + ands r0, r6\n\ + cmp r0, 0\n\ + beq _08020A98\n\ + ldrb r0, [r3]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08020A98\n\ + adds r2, 0x1\n\ +_08020A98:\n\ + adds r3, 0x28\n\ + adds r5, 0x2\n\ + cmp r5, r4\n\ + blt _08020A84\n\ +_08020AA0:\n\ + movs r4, 0\n\ + movs r5, 0x1\n\ + mov r0, r12\n\ + ldrb r3, [r0]\n\ + cmp r5, r3\n\ + bge _08020ADA\n\ + ldr r0, _08020B0C @ =gHitMarker\n\ + movs r1, 0x80\n\ + lsls r1, 21\n\ + mov r12, r1\n\ + ldr r1, [r0]\n\ + ldr r0, _08020B10 @ =gSpecialStatuses\n\ + adds r6, r3, 0\n\ + adds r3, r0, 0\n\ + adds r3, 0x14\n\ +_08020ABE:\n\ + mov r0, r12\n\ + lsls r0, r5\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08020AD2\n\ + ldrb r0, [r3]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08020AD2\n\ + adds r4, 0x1\n\ +_08020AD2:\n\ + adds r3, 0x28\n\ + adds r5, 0x2\n\ + cmp r5, r6\n\ + blt _08020ABE\n\ +_08020ADA:\n\ + mov r0, r8\n\ + ldrh r1, [r0]\n\ + movs r0, 0x40\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08020B14\n\ + adds r0, r4, r2\n\ + cmp r0, 0x1\n\ + bgt _08020B1C\n\ + b _08020B36\n\ + .align 2, 0\n\ +_08020AF0: .4byte gBattleExecBuffer\n\ +_08020AF4: .4byte gPlayerParty\n\ +_08020AF8: .4byte gBattleOutcome\n\ +_08020AFC: .4byte gEnemyParty\n\ +_08020B00: .4byte gBattleTypeFlags\n\ +_08020B04: .4byte gNoOfAllBanks\n\ +_08020B08: .4byte gBattlescriptCurrInstr\n\ +_08020B0C: .4byte gHitMarker\n\ +_08020B10: .4byte gSpecialStatuses\n\ +_08020B14:\n\ + cmp r4, 0\n\ + beq _08020B36\n\ + cmp r2, 0\n\ + beq _08020B36\n\ +_08020B1C:\n\ + ldr r2, [r7]\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2, 0x2]\n\ + lsls r0, 8\n\ + adds r1, r0\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 16\n\ + adds r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + lsls r0, 24\n\ + adds r1, r0\n\ + str r1, [r7]\n\ + b _08020B46\n\ +_08020B36:\n\ + ldr r0, [r7]\n\ + adds r0, 0x5\n\ + str r0, [r7]\n\ + b _08020B46\n\ +_08020B3E:\n\ + ldr r1, _08020B50 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x5\n\ + str r0, [r1]\n\ +_08020B46:\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08020B50: .4byte gBattlescriptCurrInstr\n\ + .syntax divided\n"); +} +#endif + +static void MoveValuesCleanUp(void) +{ + gBattleMoveFlags = 0; + BATTLE_STRUCT->dmgMultiplier = 1; + gCritMultiplier = 1; + gBattleCommunication[MOVE_EFFECT_BYTE] = 0; + gBattleCommunication[6] = 0; + gHitMarker &= ~(HITMARKER_DESTINYBOND); + gHitMarker &= ~(HITMARKER_SYNCHRONISE_EFFECT); +} + +static void atk25_move_values_cleanup(void) +{ + MoveValuesCleanUp(); + gBattlescriptCurrInstr += 1; +} + +static void atk26_set_multihit(void) +{ + gMultiHitCounter = BSScriptRead8(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr += 2; +} + +static void atk27_decrement_multihit(void) +{ + if (--gMultiHitCounter == 0) + gBattlescriptCurrInstr += 5; + else + gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atk28_goto(void) +{ + gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atk29_jumpifbyte(void) +{ + u8 caseID = BSScriptRead8(gBattlescriptCurrInstr + 1); + u8* ptr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2); + u8 value = BSScriptRead8(gBattlescriptCurrInstr + 6); + u8* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 7); + gBattlescriptCurrInstr += 11; + switch (caseID) + { + case CMP_EQUAL: + if (*ptr == value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_NOT_EQUAL: + if (*ptr != value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_GREATER_THAN: + if (*ptr > value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_LESS_THAN: + if (*ptr < value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_COMMON_BITS: + if (*ptr & value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_NO_COMMON_BITS: + if (!(*ptr & value)) + gBattlescriptCurrInstr = jump_loc; + break; + } +} + +static void atk2A_jumpifhalfword(void) +{ + u8 caseID = BSScriptRead8(gBattlescriptCurrInstr + 1); + u16* ptr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2); + u16 value = BS2ScriptRead16(gBattlescriptCurrInstr + 6); + u8* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 8); + gBattlescriptCurrInstr += 12; + switch (caseID) + { + case CMP_EQUAL: + if (*ptr == value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_NOT_EQUAL: + if (*ptr != value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_GREATER_THAN: + if (*ptr > value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_LESS_THAN: + if (*ptr < value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_COMMON_BITS: + if (*ptr & value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_NO_COMMON_BITS: + if (!(*ptr & value)) + gBattlescriptCurrInstr = jump_loc; + break; + } +} + +static void atk2B_jumpifword(void) +{ + u8 caseID = BSScriptRead8(gBattlescriptCurrInstr + 1); + u32* ptr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2); + u32 value = BSScriptRead32(gBattlescriptCurrInstr + 6); + u8* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10); + gBattlescriptCurrInstr += 14; + switch (caseID) + { + case CMP_EQUAL: + if (*ptr == value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_NOT_EQUAL: + if (*ptr != value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_GREATER_THAN: + if (*ptr > value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_LESS_THAN: + if (*ptr < value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_COMMON_BITS: + if (*ptr & value) + gBattlescriptCurrInstr = jump_loc; + break; + case CMP_NO_COMMON_BITS: + if (!(*ptr & value)) + gBattlescriptCurrInstr = jump_loc; + break; + } +} + +static void atk2C_jumpifarrayequal(void) +{ + //Mem1, Mem2, Size, Jump Loc + u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + u32 size = BSScriptRead8(gBattlescriptCurrInstr + 9); + u8* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10); + + u8 i; + for (i = 0; i < size; i++) + { + if (*mem1 != *mem2) + { + gBattlescriptCurrInstr += 14; + break; + } + mem1++, mem2++; + } + + if (i == size) + gBattlescriptCurrInstr = jump_loc; +} + +static void atk2D_jumpifarraynotequal(void) +{ + //Mem1, Mem2, Size, Jump Loc + u8 equal_bytes = 0; + u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + u32 size = BSScriptRead8(gBattlescriptCurrInstr + 9); + u8* jump_loc = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10); + + u8 i; + for (i = 0; i < size; i++) + { + if (*mem1 == *mem2) + { + equal_bytes++; + } + mem1++, mem2++; + } + + if (equal_bytes != size) + gBattlescriptCurrInstr = jump_loc; + else + gBattlescriptCurrInstr += 14; +} + +static void atk2E_setbyte(void) +{ + u8* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + *mem = BSScriptRead8(gBattlescriptCurrInstr + 5); + gBattlescriptCurrInstr += 6; +} + +static void atk2F_addbyte(void) +{ + u8* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + *mem += BSScriptRead8(gBattlescriptCurrInstr + 5); + gBattlescriptCurrInstr += 6; +} + +static void atk30_subbyte(void) +{ + u8* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + *mem -= BSScriptRead8(gBattlescriptCurrInstr + 5); + gBattlescriptCurrInstr += 6; +} + +static void atk31_copyarray(void) +{ + u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + s32 size = BSScriptRead8(gBattlescriptCurrInstr + 9); + + s32 i; + for (i = 0; i < size; i++) + { + mem1[i] = mem2[i]; + } + + gBattlescriptCurrInstr += 10; +} + +static void atk32_copyarray_withindex(void) +{ + u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + u8* index = BS2ScriptReadPtr(gBattlescriptCurrInstr + 9); + s32 size = BSScriptRead8(gBattlescriptCurrInstr + 13); + + s32 i; + for (i = 0; i < size; i++) + { + mem1[i] = mem2[i + *index]; + } + + gBattlescriptCurrInstr += 14; +} + +static void atk33_orbyte(void) +{ + u8* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + *mem |= BSScriptRead8(gBattlescriptCurrInstr + 5); + gBattlescriptCurrInstr += 6; +} + +static void atk34_orhalfword(void) +{ + u16* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u16 val = BS2ScriptRead16(gBattlescriptCurrInstr + 5); + + *mem |= val; + gBattlescriptCurrInstr += 7; +} + +static void atk35_orword(void) +{ + u32* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u32 val = BS2ScriptRead32(gBattlescriptCurrInstr + 5); + + *mem |= val; + gBattlescriptCurrInstr += 9; +} + +static void atk36_bicbyte(void) +{ + u8* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + *mem &= ~(BSScriptRead8(gBattlescriptCurrInstr + 5)); + gBattlescriptCurrInstr += 6; +} + +static void atk37_bichalfword(void) +{ + u16* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u16 val = BS2ScriptRead16(gBattlescriptCurrInstr + 5); + + *mem &= ~val; + gBattlescriptCurrInstr += 7; +} + +static void atk38_bicword(void) +{ + u32* mem = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u32 val = BS2ScriptRead32(gBattlescriptCurrInstr + 5); + + *mem &= ~val; + gBattlescriptCurrInstr += 9; +} + +static void atk39_pause(void) +{ + if (gBattleExecBuffer == 0) + { + u16 value = BS2ScriptRead16(gBattlescriptCurrInstr + 1); + if (++gPauseCounterBattle >= value) + { + gPauseCounterBattle = 0; + gBattlescriptCurrInstr += 3; + } + } +} + +static void atk3A_waitstate(void) +{ + if (gBattleExecBuffer == 0) + gBattlescriptCurrInstr++; +} + +static void atk3B_healthbar_update(void) +{ + if (!BSScriptRead8(gBattlescriptCurrInstr + 1)) + gActiveBank = gBankTarget; + else + gActiveBank = gBankAttacker; + + EmitHealthBarUpdate(0, gBattleMoveDamage); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +static void atk3C_return(void) +{ + b_movescr_stack_pop_cursor(); +} + +static void atk3D_end(void) +{ + gBattleMoveFlags = 0; + gActiveBank = 0; + gFightStateTracker = 0xB; +} + +static void atk3E_end2(void) +{ + //not much difference between this and 3D. It's more apparent in Emerald + gActiveBank = 0; + gFightStateTracker = 0xB; +} + +static void atk3F_end3(void) //pops the main function stack +{ + b_movescr_stack_pop_cursor(); + if (B_FUNCTION_STACK->size) + B_FUNCTION_STACK->size--; + gBattleMainFunc = B_FUNCTION_STACK->ptr[B_FUNCTION_STACK->size]; +} + +static void atk41_call(void) +{ + b_movescr_stack_push(gBattlescriptCurrInstr + 5); + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atk42_jumpiftype2(void) //u8 bank, u8 type, *ptr +{ + u8 bank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + + if (BSScriptRead8(gBattlescriptCurrInstr + 2) == gBattleMons[bank].type1 || BSScriptRead8(gBattlescriptCurrInstr + 2) == gBattleMons[bank].type2) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 3); + else + gBattlescriptCurrInstr += 7; +} + +static void atk43_jumpifabilitypresent(void) +{ + if (AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, BSScriptRead8(gBattlescriptCurrInstr + 1), 0, 0)) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + else + gBattlescriptCurrInstr += 6; +} + +static void atk44(void) +{ + unk_2000000[gBankAttacker + 0x16060] = 1; +} + +#ifdef NONMATCHING + +static void atk45_playanimation(void) +{ + #define ANIMATION_ID BSScriptRead8(gBattlescriptCurrInstr + 2) + #define ARGUMENT (u16*) BS2ScriptReadPtr(gBattlescriptCurrInstr + 3) + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + + if ( ANIMATION_ID == 1 || ANIMATION_ID == 0x11 || ANIMATION_ID == 2) { + EmitBattleAnimation(0, ANIMATION_ID, *argument); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 7; + } else if (gHitMarker & HITMARKER_NO_ANIMATIONS) { + b_movescr_stack_push(gBattlescriptCurrInstr + 7); + gBattlescriptCurrInstr = BattleScript_Pausex20; + } else { + if (((ANIMATION_ID - 10) > 3 && gStatuses3[gActiveBank] & (STATUS3_SEMI_INVULNERABLE))) { + gBattlescriptCurrInstr += 7; + } else { + EmitBattleAnimation(0, ANIMATION_ID, *argument); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 7; + } + } +} + +#else +__attribute__((naked)) +static void atk45_playanimation(void) +{ + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + ldr r5, _08021444 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r5]\n\ + ldrb r0, [r0, 0x1]\n\ + bl GetBattleBank\n\ + ldr r6, _08021448 @ =gActiveBank\n\ + strb r0, [r6]\n\ + ldr r2, [r5]\n\ + ldrb r1, [r2, 0x3]\n\ + ldrb r0, [r2, 0x4]\n\ + lsls r0, 8\n\ + adds r1, r0\n\ + ldrb r0, [r2, 0x5]\n\ + lsls r0, 16\n\ + adds r1, r0\n\ + ldrb r0, [r2, 0x6]\n\ + lsls r0, 24\n\ + adds r3, r1, r0\n\ + ldrb r4, [r2, 0x2]\n\ + adds r0, r4, 0\n\ + cmp r0, 0x1\n\ + beq _08021426\n\ + cmp r0, 0x11\n\ + beq _08021426\n\ + cmp r0, 0x2\n\ + bne _0802144C\n\ +_08021426:\n\ + ldr r4, _08021444 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r4]\n\ + ldrb r1, [r0, 0x2]\n\ + ldrh r2, [r3]\n\ + movs r0, 0\n\ + bl EmitBattleAnimation\n\ + ldr r0, _08021448 @ =gActiveBank\n\ + ldrb r0, [r0]\n\ + bl MarkBufferBankForExecution\n\ + ldr r0, [r4]\n\ + adds r0, 0x7\n\ + str r0, [r4]\n\ + b _080214AE\n\ + .align 2, 0\n\ +_08021444: .4byte gBattlescriptCurrInstr\n\ +_08021448: .4byte gActiveBank\n\ +_0802144C:\n\ + ldr r0, _08021464 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0802146C\n\ + adds r0, r2, 0x7\n\ + bl b_movescr_stack_push\n\ + ldr r0, _08021468 @ =BattleScript_Pausex20\n\ + b _080214AC\n\ + .align 2, 0\n\ +_08021464: .4byte gHitMarker\n\ +_08021468: .4byte BattleScript_Pausex20\n\ +_0802146C:\n\ + adds r0, r4, 0\n\ + subs r0, 0xA\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x3\n\ + bls _08021498\n\ + ldr r1, _08021490 @ =gStatuses3\n\ + ldrb r0, [r6]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + ldr r1, _08021494 @ =0x000400c0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021498\n\ + adds r0, r2, 0x7\n\ + b _080214AC\n\ + .align 2, 0\n\ +_08021490: .4byte gStatuses3\n\ +_08021494: .4byte 0x000400c0\n\ +_08021498:\n\ + ldrb r1, [r2, 0x2]\n\ + ldrh r2, [r3]\n\ + movs r0, 0\n\ + bl EmitBattleAnimation\n\ + ldrb r0, [r6]\n\ + bl MarkBufferBankForExecution\n\ + ldr r0, [r5]\n\ + adds r0, 0x7\n\ +_080214AC:\n\ + str r0, [r5]\n\ +_080214AE:\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided"); +} +#endif // NONMATCHING + +#ifdef NONMATCHING +static void atk46_playanimation2(void) +{ + u8 arg1; + u8* arg2; + u16* arg3; + u32 something; + + arg1 = BSScriptRead8(gBattlescriptCurrInstr + 1); + gActiveBank = GetBattleBank(arg1); + arg2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2); + arg3 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6); + + if (*arg2 == 1 || *arg2 == 0x11 || *arg2 == 2) + { + EmitBattleAnimation(0, *arg2, *arg3); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 10; + return; + } + if ((gHitMarker & 0x80)) + { + something = (u32)(gBattlescriptCurrInstr + 10); + } + else + { + u8 yeah = *arg2 - 10; + if (yeah < 4 || (gStatuses3[gActiveBank] & 0x000400C0) == 0) + { + EmitBattleAnimation(0, *arg2, *arg3); + MarkBufferBankForExecution(gActiveBank); + } + something = (u32)(gBattlescriptCurrInstr + 10); + } + gBattlescriptCurrInstr = (u8*)something; +} +#else +__attribute__((naked)) +static void atk46_playanimation2(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + ldr r6, _0802151C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r6]\n\ + ldrb r0, [r0, 0x1]\n\ + bl GetBattleBank\n\ + ldr r7, _08021520 @ =gActiveBank\n\ + strb r0, [r7]\n\ + ldr r2, [r6]\n\ + ldrb r1, [r2, 0x2]\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 8\n\ + adds r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + lsls r0, 16\n\ + adds r1, r0\n\ + ldrb r0, [r2, 0x5]\n\ + lsls r0, 24\n\ + adds r3, r1, r0\n\ + ldrb r1, [r2, 0x6]\n\ + ldrb r0, [r2, 0x7]\n\ + lsls r0, 8\n\ + adds r1, r0\n\ + ldrb r0, [r2, 0x8]\n\ + lsls r0, 16\n\ + adds r1, r0\n\ + ldrb r0, [r2, 0x9]\n\ + lsls r0, 24\n\ + adds r4, r1, r0\n\ + ldrb r5, [r3]\n\ + adds r0, r5, 0\n\ + cmp r0, 0x1\n\ + beq _080214FE\n\ + cmp r0, 0x11\n\ + beq _080214FE\n\ + cmp r0, 0x2\n\ + bne _08021524\n\ +_080214FE:\n\ + ldrb r1, [r3]\n\ + ldrh r2, [r4]\n\ + movs r0, 0\n\ + bl EmitBattleAnimation\n\ + ldr r0, _08021520 @ =gActiveBank\n\ + ldrb r0, [r0]\n\ + bl MarkBufferBankForExecution\n\ + ldr r1, _0802151C @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0xA\n\ + str r0, [r1]\n\ + b _0802157A\n\ + .align 2, 0\n\ +_0802151C: .4byte gBattlescriptCurrInstr\n\ +_08021520: .4byte gActiveBank\n\ +_08021524:\n\ + ldr r0, _08021534 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021538\n\ + adds r0, r2, 0\n\ + b _08021576\n\ + .align 2, 0\n\ +_08021534: .4byte gHitMarker\n\ +_08021538:\n\ + adds r0, r5, 0\n\ + subs r0, 0xA\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x3\n\ + bls _08021564\n\ + ldr r1, _0802155C @ =gStatuses3\n\ + ldrb r0, [r7]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + ldr r1, _08021560 @ =0x000400c0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021564\n\ + adds r0, r2, 0\n\ + b _08021576\n\ + .align 2, 0\n\ +_0802155C: .4byte gStatuses3\n\ +_08021560: .4byte 0x000400c0\n\ +_08021564:\n\ + ldrb r1, [r3]\n\ + ldrh r2, [r4]\n\ + movs r0, 0\n\ + bl EmitBattleAnimation\n\ + ldrb r0, [r7]\n\ + bl MarkBufferBankForExecution\n\ + ldr r0, [r6]\n\ +_08021576:\n\ + adds r0, 0xA\n\ + str r0, [r6]\n\ +_0802157A:\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided "); +} +#endif // NONMATCHING + +static void atk47_setgraphicalstatchangevalues(void) +{ + u8 to_add = 0; + switch (BATTLE_STRUCT->statChanger & 0xF0) + { + case 0x10: //+1 + to_add = 0xF; + break; + case 0x20: //+2 + to_add = 0x27; + break; + case 0x90: //-1 + to_add = 0x16; + break; + case 0xA0: //-2 + to_add = 0x2E; + break; + } + BATTLE_STRUCT->animArg1 = (BATTLE_STRUCT->statChanger & 0xF) + to_add - 1; + BATTLE_STRUCT->animArg2 = 0; + gBattlescriptCurrInstr++; +} + +#ifdef NONMATCHING +static void atk48_playstatchangeanimation(void) +{ + int curr_stat = 0; + u16 stat_animID = 0; + int changeable_stats = 0; + u32 stats_to_check; + u8 arg3; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + stats_to_check = BSScriptRead8(gBattlescriptCurrInstr + 2); + arg3 = BSScriptRead8(gBattlescriptCurrInstr + 3); + if (arg3 & 1) + { + u16 r1 = 0x15; + if (arg3 & 0x2) + r1 = 0x2D; + while (stats_to_check != 0) + { + if (!(stats_to_check & 1)) + continue; + if (!(BSScriptRead8(gBattlescriptCurrInstr + 3))) + { + u8 ability; + if (gSideTimer[GetBankIdentity(gActiveBank) & 1].mistTimer) + continue; + ability = gBattleMons[gActiveBank].ability; + if (ability == ABILITY_CLEAR_BODY || ability == ABILITY_WHITE_SMOKE || (ability == ABILITY_KEEN_EYE && curr_stat == 6) || (ability == ABILITY_HYPER_CUTTER && curr_stat == 1)) + continue; + } + if (gBattleMons[gActiveBank].statStages[curr_stat] > 0) + { + stat_animID = r1; + changeable_stats++; + } + + stats_to_check >>= 1; + r1 += 1; + curr_stat++; + } + if (changeable_stats > 1 && BSScriptRead8(gBattlescriptCurrInstr + 3) & 2) + stat_animID = 0x39; + else + stat_animID = 0x3A; + } + else + { + u16 r1 = 0x15; + if (arg3 & 0x2) + r1 = 0x2D; + while (stats_to_check != 0) + { + if (!(stats_to_check & 1)) + continue; + if (gBattleMons[gActiveBank].statStages[curr_stat] < 0xB) + { + stat_animID = r1; + changeable_stats++; + } + + stats_to_check >>= 1; + r1 += 1; + curr_stat++; + } + if (changeable_stats > 1 && BSScriptRead8(gBattlescriptCurrInstr + 3) & 2) + stat_animID = 0x37; + else + stat_animID = 0x38; + } + if ((BSScriptRead8(gBattlescriptCurrInstr + 3) & 2 && changeable_stats <= 1) + || changeable_stats == 0 || BATTLE_STRUCT->filler2[0] != 0) + gBattlescriptCurrInstr += 4; + else + { + EmitBattleAnimation(0, 1, stat_animID); + MarkBufferBankForExecution(gActiveBank); + if ((BSScriptRead8(gBattlescriptCurrInstr + 3) & 4) && changeable_stats > 1) + BATTLE_STRUCT->filler2[0] = 1; + gBattlescriptCurrInstr += 4; + } +} + +#else +__attribute__((naked)) +static void atk48_playstatchangeanimation(void) +{ + asm(".syntax unified\n\ +push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x4\n\ + movs r7, 0\n\ + movs r0, 0\n\ + mov r8, r0\n\ + movs r3, 0\n\ + ldr r5, _08021670 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r5]\n\ + ldrb r0, [r0, 0x1]\n\ + str r3, [sp]\n\ + bl GetBattleBank\n\ + ldr r2, _08021674 @ =gActiveBank\n\ + strb r0, [r2]\n\ + ldr r0, [r5]\n\ + ldrb r4, [r0, 0x2]\n\ + ldrb r1, [r0, 0x3]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + ldr r3, [sp]\n\ + cmp r0, 0\n\ + beq _08021710\n\ + movs r0, 0x2\n\ + ands r0, r1\n\ + movs r1, 0x15\n\ + cmp r0, 0\n\ + beq _0802163C\n\ + movs r1, 0x2D\n\ +_0802163C:\n\ + cmp r4, 0\n\ + beq _080216E4\n\ + movs r0, 0x1\n\ + mov r10, r0\n\ + ldr r0, _08021678 @ =gUnknown_02024A98\n\ + mov r9, r0\n\ + lsls r5, r1, 16\n\ +_0802164A:\n\ + adds r0, r4, 0\n\ + mov r1, r10\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080216D6\n\ + ldr r0, _08021670 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r0]\n\ + ldrb r1, [r0, 0x3]\n\ + movs r0, 0x8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0802167C\n\ + ldr r0, _08021674 @ =gActiveBank\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r0, r7, r0\n\ + b _080216C4\n\ + .align 2, 0\n\ +_08021670: .4byte gBattlescriptCurrInstr\n\ +_08021674: .4byte gActiveBank\n\ +_08021678: .4byte gUnknown_02024A98\n\ +_0802167C:\n\ + ldr r6, _08021700 @ =gActiveBank\n\ + ldrb r0, [r6]\n\ + str r3, [sp]\n\ + bl GetBankIdentity\n\ + mov r1, r10\n\ + ands r1, r0\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + ldr r1, _08021704 @ =gSideTimer\n\ + adds r0, r1\n\ + ldrb r0, [r0, 0x2]\n\ + ldr r3, [sp]\n\ + cmp r0, 0\n\ + bne _080216D6\n\ + ldr r0, _08021708 @ =gBattleMons\n\ + ldrb r2, [r6]\n\ + movs r1, 0x58\n\ + muls r2, r1\n\ + adds r0, r2, r0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x1D\n\ + beq _080216D6\n\ + cmp r0, 0x49\n\ + beq _080216D6\n\ + cmp r0, 0x33\n\ + bne _080216BA\n\ + cmp r7, 0x6\n\ + beq _080216D6\n\ +_080216BA:\n\ + cmp r0, 0x34\n\ + bne _080216C2\n\ + cmp r7, 0x1\n\ + beq _080216D6\n\ +_080216C2:\n\ + adds r0, r7, r2\n\ +_080216C4:\n\ + add r0, r9\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + cmp r0, 0\n\ + ble _080216D6\n\ + lsrs r0, r5, 16\n\ + mov r8, r0\n\ + adds r3, 0x1\n\ +_080216D6:\n\ + lsrs r4, 1\n\ + movs r1, 0x80\n\ + lsls r1, 9\n\ + adds r5, r1\n\ + adds r7, 0x1\n\ + cmp r4, 0\n\ + bne _0802164A\n\ +_080216E4:\n\ + ldr r0, _0802170C @ =gBattlescriptCurrInstr\n\ + mov r9, r0\n\ + cmp r3, 0x1\n\ + ble _08021772\n\ + ldr r0, [r0]\n\ + ldrb r1, [r0, 0x3]\n\ + movs r0, 0x2\n\ + ands r0, r1\n\ + movs r1, 0x39\n\ + mov r8, r1\n\ + cmp r0, 0\n\ + beq _08021772\n\ + movs r0, 0x3A\n\ + b _08021770\n\ + .align 2, 0\n\ +_08021700: .4byte gActiveBank\n\ +_08021704: .4byte gSideTimer\n\ +_08021708: .4byte gBattleMons\n\ +_0802170C: .4byte gBattlescriptCurrInstr\n\ +_08021710:\n\ + movs r0, 0x2\n\ + ands r0, r1\n\ + movs r1, 0xE\n\ + cmp r0, 0\n\ + beq _0802171C\n\ + movs r1, 0x26\n\ +_0802171C:\n\ + mov r9, r5\n\ + cmp r4, 0\n\ + beq _08021758\n\ + ldr r6, _0802178C @ =gUnknown_02024A98\n\ + adds r5, r2, 0\n\ + lsls r2, r1, 16\n\ +_08021728:\n\ + movs r0, 0x1\n\ + ands r0, r4\n\ + cmp r0, 0\n\ + beq _0802174A\n\ + ldrb r1, [r5]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r0, r7, r0\n\ + adds r0, r6\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + cmp r0, 0xB\n\ + bgt _0802174A\n\ + lsrs r1, r2, 16\n\ + mov r8, r1\n\ + adds r3, 0x1\n\ +_0802174A:\n\ + lsrs r4, 1\n\ + movs r0, 0x80\n\ + lsls r0, 9\n\ + adds r2, r0\n\ + adds r7, 0x1\n\ + cmp r4, 0\n\ + bne _08021728\n\ +_08021758:\n\ + cmp r3, 0x1\n\ + ble _08021772\n\ + mov r1, r9\n\ + ldr r0, [r1]\n\ + ldrb r1, [r0, 0x3]\n\ + movs r0, 0x2\n\ + ands r0, r1\n\ + movs r1, 0x37\n\ + mov r8, r1\n\ + cmp r0, 0\n\ + beq _08021772\n\ + movs r0, 0x38\n\ +_08021770:\n\ + mov r8, r0\n\ +_08021772:\n\ + mov r1, r9\n\ + ldr r2, [r1]\n\ + ldrb r1, [r2, 0x3]\n\ + movs r0, 0x4\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021790\n\ + cmp r3, 0x1\n\ + bgt _08021790\n\ + adds r0, r2, 0x4\n\ + mov r1, r9\n\ + b _080217E6\n\ + .align 2, 0\n\ +_0802178C: .4byte gUnknown_02024A98\n\ +_08021790:\n\ + cmp r3, 0\n\ + beq _080217E0\n\ + ldr r0, _080217D0 @ =0x02000000\n\ + ldr r1, _080217D4 @ =0x000160dc\n\ + adds r4, r0, r1\n\ + ldrb r0, [r4]\n\ + cmp r0, 0\n\ + bne _080217E0\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + mov r2, r8\n\ + str r3, [sp]\n\ + bl EmitBattleAnimation\n\ + ldr r0, _080217D8 @ =gActiveBank\n\ + ldrb r0, [r0]\n\ + bl MarkBufferBankForExecution\n\ + ldr r0, _080217DC @ =gBattlescriptCurrInstr\n\ + ldr r0, [r0]\n\ + ldrb r1, [r0, 0x3]\n\ + movs r0, 0x4\n\ + ands r0, r1\n\ + ldr r3, [sp]\n\ + cmp r0, 0\n\ + beq _080217CC\n\ + cmp r3, 0x1\n\ + ble _080217CC\n\ + movs r0, 0x1\n\ + strb r0, [r4]\n\ +_080217CC:\n\ + ldr r1, _080217DC @ =gBattlescriptCurrInstr\n\ + b _080217E2\n\ + .align 2, 0\n\ +_080217D0: .4byte 0x02000000\n\ +_080217D4: .4byte 0x000160dc\n\ +_080217D8: .4byte gActiveBank\n\ +_080217DC: .4byte gBattlescriptCurrInstr\n\ +_080217E0:\n\ + mov r1, r9\n\ +_080217E2:\n\ + ldr r0, [r1]\n\ + adds r0, 0x4\n\ +_080217E6:\n\ + str r0, [r1]\n\ + add sp, 0x4\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided"); +} + +#endif // NONMATCHING + +#ifdef NONMATCHING +static void atk49_moveendturn(void) +{ + int i; + int effect = 0; + u16 last_move = 0, *choiced_move_atk; + int arg1, arg2, hold_effect_atk, move_type; + if (gLastUsedMove != 0xFFFF) + last_move = gLastUsedMove; + + arg1 = BSScriptRead8(gBattlescriptCurrInstr + 1); + arg2 = BSScriptRead8(gBattlescriptCurrInstr + 2); + if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY) + hold_effect_atk = gEnigmaBerries[gBankAttacker].holdEffect; + else + hold_effect_atk = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item); + + choiced_move_atk = (u16*)(gBankAttacker * 0x020160e8); + if (BATTLE_STRUCT->dynamicMoveType) + move_type = BATTLE_STRUCT->dynamicMoveType & 0x3F; + else + move_type = gBattleMoves[gCurrentMove].type; + + do + { + switch (BATTLE_STRUCT->cmd49StateTracker) + { + case 0: //rage check + if (gBattleMons[gBankTarget].status2 & STATUS2_RAGE + && gBattleMons[gBankTarget].hp && gBankAttacker != gBankTarget + && GetBankSide(gBankAttacker) != GetBankSide(gBankTarget) + && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT) && TARGET_TURN_DAMAGED + && gBattleMoves[gCurrentMove].power && gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK] <= 0xB) + { + gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK]++; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = gUnknown_081D9132; + effect = 1; + } + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 1: //defrosting check + if (gBattleMons[gBankTarget].status1 & STATUS_FREEZE + && gBattleMons[gBankTarget].hp && gBankAttacker != gBankTarget + && gSpecialStatuses[gBankTarget].moveturnLostHP + && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT) && move_type == TYPE_FIRE) + { + gBattleMons[gBankTarget].status1 &= ~(STATUS_FREEZE); + gActiveBank = gBankTarget; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBankTarget].status1); + MarkBufferBankForExecution(gActiveBank); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = gUnknown_081D955D; + effect = 1; + } + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 2: //target synchronize + if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBankTarget, 0, 0, 0)) + effect = 1; + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 3: //contact abilities + if (AbilityBattleEffects(ABILITYEFFECT_CONTACT, gBankTarget, 0, 0, 0)) + effect = 1; + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 4: //status immunities + if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, 0, 0, 0, 0)) + effect = 1; //it loops through 4 banks, so we increment after its done with all banks + else + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 5: //attacker synchronize + if (AbilityBattleEffects(ABILITYEFFECT_ATK_SYNCHRONIZE, gBankAttacker, 0, 0, 0)) + effect = 1; + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 6: //update choice band move + if (gHitMarker & HITMARKER_OBEYS && hold_effect_atk == HOLD_EFFECT_CHOICE_BAND + && gLastUsedMove != MOVE_STRUGGLE && (*choiced_move_atk == 0 || *choiced_move_atk == 0xFFF) + && gLastUsedMove != MOVE_BATON_PASS && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT)) + { + *choiced_move_atk = gLastUsedMove; + for (i = 0; i < 4 && gBattleMons[gBankAttacker].moves[i] != *choiced_move_atk; i++){} + if (i == 4) + *choiced_move_atk = 0; + } + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 7: //changed held items + for (i = 0; i < gNoOfAllBanks; i++) + { + #define CHANGED_ITEM (((*u16)(0x020160f0))) + if (CHANGED_ITEM(i)) + gBattleMons[i].item = CHANGED_ITEM(i); + } + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 8: //make sprite invisible + if (gStatuses3[gBankAttacker] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER) + && !(gHitMarker & HITMARKER_NO_ANIMATIONS)) + { + gActiveBank = gBankAttacker; + EmitSpriteInvisibility(0, 1); + MarkBufferBankForExecution(gActiveBank); + } + BATTLE_STRUCT->cmd49StateTracker++; + break; + //sub_8015660 CheckIfMoveFailed + case 9: //semi-invlurneable attacker make visible + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) || !(gStatuses3[gBankAttacker] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + || sub_8015660(gBankAttacker)) + { + gActiveBank = gBankAttacker; + EmitSpriteInvisibility(0, 0); + MarkBufferBankForExecution(gActiveBank); + gStatuses3 &= ~(STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER); + gSpecialStatuses[gBankAttacker].restored_bank_sprite = 1; + } + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 10: //semi-invlurneable target make visible + if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT) || !(gStatuses3[gBankTarget] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + || sub_8015660(gBankTarget)) + { + gActiveBank = gBankTarget; + EmitSpriteInvisibility(0, 0); + MarkBufferBankForExecution(gActiveBank); + gStatuses3 &= ~(STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER); + gSpecialStatuses[gBankTarget].restored_bank_sprite = 1; + } + BATTLE_STRUCT->cmd49StateTracker++; + break; + case 11: // + } + + } while (effect == 0) +} +#else +__attribute__((naked)) +static void atk49_moveendturn(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x18\n\ + movs r0, 0\n\ + mov r10, r0\n\ + ldr r0, _08021834 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r0]\n\ + ldrb r1, [r0, 0x1]\n\ + str r1, [sp, 0x10]\n\ + ldrb r0, [r0, 0x2]\n\ + str r0, [sp, 0x14]\n\ + ldr r1, _08021838 @ =gBattleMons\n\ + ldr r0, _0802183C @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r1, r0, r1\n\ + ldrh r0, [r1, 0x2E]\n\ + cmp r0, 0xAF\n\ + bne _08021844\n\ + ldr r1, _08021840 @ =gEnigmaBerries\n\ + lsls r0, r2, 3\n\ + subs r0, r2\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r0, [r0, 0x7]\n\ + b _0802184E\n\ + .align 2, 0\n\ +_08021834: .4byte gBattlescriptCurrInstr\n\ +_08021838: .4byte gBattleMons\n\ +_0802183C: .4byte gBankAttacker\n\ +_08021840: .4byte gEnigmaBerries\n\ +_08021844:\n\ + ldrh r0, [r1, 0x2E]\n\ + bl ItemId_GetHoldEffect\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ +_0802184E:\n\ + str r0, [sp, 0x8]\n\ + ldr r0, _0802186C @ =gBankAttacker\n\ + ldrb r1, [r0]\n\ + lsls r1, 1\n\ + ldr r0, _08021870 @ =0x020160e8\n\ + adds r1, r0\n\ + str r1, [sp, 0xC]\n\ + subs r0, 0xCC\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _080218C0\n\ + movs r2, 0x3F\n\ + ands r2, r0\n\ + str r2, [sp, 0x4]\n\ + b _080218D2\n\ + .align 2, 0\n\ +_0802186C: .4byte gBankAttacker\n\ +_08021870: .4byte 0x020160e8\n\ +_08021874:\n\ + strb r2, [r7]\n\ + ldr r0, [r5]\n\ + orrs r0, r6\n\ + str r0, [r5]\n\ + ldr r0, _080218AC @ =0x02000000\n\ + ldr r3, _080218B0 @ =0x0001600c\n\ + adds r0, r3\n\ + strb r4, [r0]\n\ + bl MoveValuesCleanUp\n\ + ldr r2, _080218B4 @ =gBattleScriptsEffectsTable\n\ + mov r4, r8\n\ + ldrh r1, [r4]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + add r0, r9\n\ + ldrb r0, [r0]\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldr r0, [r0]\n\ + bl b_movescr_stack_push\n\ + ldr r1, _080218B8 @ =gBattlescriptCurrInstr\n\ + ldr r0, _080218BC @ =gUnknown_081D9B2D\n\ + bl _0802229C\n\ + .align 2, 0\n\ +_080218AC: .4byte 0x02000000\n\ +_080218B0: .4byte 0x0001600c\n\ +_080218B4: .4byte gBattleScriptsEffectsTable\n\ +_080218B8: .4byte gBattlescriptCurrInstr\n\ +_080218BC: .4byte gUnknown_081D9B2D\n\ +_080218C0:\n\ + ldr r2, _080218D8 @ =gBattleMoves\n\ + ldr r0, _080218DC @ =gCurrentMove\n\ + ldrh r1, [r0]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldrb r0, [r0, 0x2]\n\ + str r0, [sp, 0x4]\n\ +_080218D2:\n\ + ldr r5, _080218E0 @ =0x02000000\n\ + mov r12, r5\n\ + b _080218EE\n\ + .align 2, 0\n\ +_080218D8: .4byte gBattleMoves\n\ +_080218DC: .4byte gCurrentMove\n\ +_080218E0: .4byte 0x02000000\n\ +_080218E4:\n\ + mov r0, r10\n\ + cmp r0, 0\n\ + beq _080218EE\n\ + bl _08022286\n\ +_080218EE:\n\ + ldr r0, _08021908 @ =0x0001600c\n\ + add r0, r12\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x11\n\ + bls _080218FC\n\ + bl _0802224E\n\ +_080218FC:\n\ + lsls r0, 2\n\ + ldr r1, _0802190C @ =_08021910\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_08021908: .4byte 0x0001600c\n\ +_0802190C: .4byte _08021910\n\ + .align 2, 0\n\ +_08021910:\n\ + .4byte _08021958\n\ + .4byte _08021A34\n\ + .4byte _08021AF0\n\ + .4byte _08021B20\n\ + .4byte _08021B44\n\ + .4byte _08021B78\n\ + .4byte _08021B9C\n\ + .4byte _08021C40\n\ + .4byte _08021C78\n\ + .4byte _08021CA8\n\ + .4byte _08021CCC\n\ + .4byte _08021D18\n\ + .4byte _08021DAC\n\ + .4byte _08021E30\n\ + .4byte _08021E70\n\ + .4byte _08022068\n\ + .4byte _080221C0\n\ + .4byte _0802224E\n\ +_08021958:\n\ + ldr r5, _08021A08 @ =gBattleMons\n\ + ldr r2, _08021A0C @ =gBankTarget\n\ + ldrb r4, [r2]\n\ + movs r6, 0x58\n\ + adds r3, r4, 0\n\ + muls r3, r6\n\ + adds r0, r5, 0\n\ + adds r0, 0x50\n\ + adds r0, r3, r0\n\ + ldr r1, [r0]\n\ + movs r0, 0x80\n\ + lsls r0, 16\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + beq _080219FE\n\ + adds r0, r3, r5\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + beq _080219FE\n\ + ldr r0, _08021A10 @ =gBankAttacker\n\ + ldrb r1, [r0]\n\ + cmp r1, r4\n\ + beq _080219FE\n\ + adds r0, r1, 0\n\ + bl GetBankSide\n\ + adds r4, r0, 0\n\ + ldr r1, _08021A0C @ =gBankTarget\n\ + ldrb r0, [r1]\n\ + bl GetBankSide\n\ + lsls r4, 24\n\ + lsls r0, 24\n\ + cmp r4, r0\n\ + beq _080219FE\n\ + ldr r0, _08021A14 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080219FE\n\ + ldr r2, _08021A18 @ =gProtectStructs\n\ + ldr r4, _08021A0C @ =gBankTarget\n\ + ldrb r3, [r4]\n\ + lsls r1, r3, 4\n\ + adds r0, r2, 0x4\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _080219C8\n\ + adds r0, r2, 0\n\ + adds r0, 0x8\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + beq _080219FE\n\ +_080219C8:\n\ + ldr r2, _08021A1C @ =gBattleMoves\n\ + ldr r0, _08021A20 @ =gCurrentMove\n\ + ldrh r1, [r0]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldrb r0, [r0, 0x1]\n\ + cmp r0, 0\n\ + beq _080219FE\n\ + adds r0, r3, 0\n\ + muls r0, r6\n\ + adds r1, r0, r5\n\ + ldrb r2, [r1, 0x19]\n\ + movs r0, 0x19\n\ + ldrsb r0, [r1, r0]\n\ + cmp r0, 0xB\n\ + bgt _080219FE\n\ + adds r0, r2, 0x1\n\ + strb r0, [r1, 0x19]\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08021A24 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08021A28 @ =gUnknown_081D9132\n\ + str r0, [r1]\n\ + movs r5, 0x1\n\ + mov r10, r5\n\ +_080219FE:\n\ + ldr r2, _08021A2C @ =0x02000000\n\ + ldr r0, _08021A30 @ =0x0001600c\n\ + adds r1, r2, r0\n\ + b _08021E00\n\ + .align 2, 0\n\ +_08021A08: .4byte gBattleMons\n\ +_08021A0C: .4byte gBankTarget\n\ +_08021A10: .4byte gBankAttacker\n\ +_08021A14: .4byte gBattleMoveFlags\n\ +_08021A18: .4byte gProtectStructs\n\ +_08021A1C: .4byte gBattleMoves\n\ +_08021A20: .4byte gCurrentMove\n\ +_08021A24: .4byte gBattlescriptCurrInstr\n\ +_08021A28: .4byte gUnknown_081D9132\n\ +_08021A2C: .4byte 0x02000000\n\ +_08021A30: .4byte 0x0001600c\n\ +_08021A34:\n\ + ldr r2, _08021AD0 @ =gBattleMons\n\ + ldr r1, _08021AD4 @ =gBankTarget\n\ + ldrb r4, [r1]\n\ + movs r3, 0x58\n\ + mov r12, r3\n\ + mov r3, r12\n\ + muls r3, r4\n\ + adds r7, r2, 0\n\ + adds r7, 0x4C\n\ + adds r6, r3, r7\n\ + ldr r5, [r6]\n\ + movs r0, 0x20\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + bne _08021A54\n\ + b _08021DFA\n\ +_08021A54:\n\ + adds r0, r3, r2\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + bne _08021A5E\n\ + b _08021DFA\n\ +_08021A5E:\n\ + ldr r0, _08021AD8 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + cmp r0, r4\n\ + bne _08021A68\n\ + b _08021DFA\n\ +_08021A68:\n\ + ldr r0, _08021ADC @ =gSpecialStatuses\n\ + lsls r1, r4, 2\n\ + adds r1, r4\n\ + lsls r1, 2\n\ + adds r0, 0xC\n\ + adds r1, r0\n\ + ldr r0, [r1]\n\ + cmp r0, 0\n\ + bne _08021A7C\n\ + b _08021DFA\n\ +_08021A7C:\n\ + ldr r0, _08021AE0 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021A8A\n\ + b _08021DFA\n\ +_08021A8A:\n\ + ldr r4, [sp, 0x4]\n\ + cmp r4, 0xA\n\ + beq _08021A92\n\ + b _08021DFA\n\ +_08021A92:\n\ + movs r0, 0x21\n\ + negs r0, r0\n\ + ands r5, r0\n\ + str r5, [r6]\n\ + ldr r4, _08021AE4 @ =gActiveBank\n\ + ldr r5, _08021AD4 @ =gBankTarget\n\ + ldrb r0, [r5]\n\ + strb r0, [r4]\n\ + ldrb r0, [r5]\n\ + mov r1, r12\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + adds r0, r7\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x28\n\ + movs r2, 0\n\ + movs r3, 0x4\n\ + bl EmitSetAttributes\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + bl b_movescr_stack_push_cursor\n\ + ldr r1, _08021AE8 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08021AEC @ =gUnknown_081D955D\n\ + str r0, [r1]\n\ + movs r2, 0x1\n\ + mov r10, r2\n\ + b _08021DFA\n\ + .align 2, 0\n\ +_08021AD0: .4byte gBattleMons\n\ +_08021AD4: .4byte gBankTarget\n\ +_08021AD8: .4byte gBankAttacker\n\ +_08021ADC: .4byte gSpecialStatuses\n\ +_08021AE0: .4byte gBattleMoveFlags\n\ +_08021AE4: .4byte gActiveBank\n\ +_08021AE8: .4byte gBattlescriptCurrInstr\n\ +_08021AEC: .4byte gUnknown_081D955D\n\ +_08021AF0:\n\ + ldr r0, _08021B14 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + movs r0, 0x7\n\ + movs r2, 0\n\ + movs r3, 0\n\ + bl AbilityBattleEffects\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08021B0C\n\ + movs r4, 0x1\n\ + mov r10, r4\n\ +_08021B0C:\n\ + ldr r2, _08021B18 @ =0x02000000\n\ + ldr r5, _08021B1C @ =0x0001600c\n\ + adds r1, r2, r5\n\ + b _08021E00\n\ + .align 2, 0\n\ +_08021B14: .4byte gBankTarget\n\ +_08021B18: .4byte 0x02000000\n\ +_08021B1C: .4byte 0x0001600c\n\ +_08021B20:\n\ + ldr r0, _08021B40 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + movs r0, 0x4\n\ + movs r2, 0\n\ + movs r3, 0\n\ + bl AbilityBattleEffects\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _08021B3A\n\ + b _08021DFA\n\ +_08021B3A:\n\ + movs r0, 0x1\n\ + mov r10, r0\n\ + b _08021DFA\n\ + .align 2, 0\n\ +_08021B40: .4byte gBankTarget\n\ +_08021B44:\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + movs r0, 0x5\n\ + movs r1, 0\n\ + movs r2, 0\n\ + movs r3, 0\n\ + bl AbilityBattleEffects\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08021B68\n\ + movs r4, 0x1\n\ + mov r10, r4\n\ + ldr r5, _08021B64 @ =0x02000000\n\ + mov r12, r5\n\ + b _0802224E\n\ + .align 2, 0\n\ +_08021B64: .4byte 0x02000000\n\ +_08021B68:\n\ + ldr r2, _08021B70 @ =0x02000000\n\ + ldr r0, _08021B74 @ =0x0001600c\n\ + adds r1, r2, r0\n\ + b _08021E00\n\ + .align 2, 0\n\ +_08021B70: .4byte 0x02000000\n\ +_08021B74: .4byte 0x0001600c\n\ +_08021B78:\n\ + ldr r0, _08021B98 @ =gBankAttacker\n\ + ldrb r1, [r0]\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + movs r0, 0x8\n\ + movs r2, 0\n\ + movs r3, 0\n\ + bl AbilityBattleEffects\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _08021B92\n\ + b _08021DFA\n\ +_08021B92:\n\ + movs r1, 0x1\n\ + mov r10, r1\n\ + b _08021DFA\n\ + .align 2, 0\n\ +_08021B98: .4byte gBankAttacker\n\ +_08021B9C:\n\ + ldr r0, _08021C28 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 18\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021BE0\n\ + ldr r4, [sp, 0x8]\n\ + cmp r4, 0x1D\n\ + bne _08021BE0\n\ + ldr r0, _08021C2C @ =gUnknown_02024BE8\n\ + ldrh r2, [r0]\n\ + adds r7, r0, 0\n\ + cmp r2, 0xA5\n\ + beq _08021BE0\n\ + ldr r5, [sp, 0xC]\n\ + ldrh r1, [r5]\n\ + cmp r1, 0\n\ + beq _08021BC8\n\ + ldr r0, _08021C30 @ =0x0000ffff\n\ + cmp r1, r0\n\ + bne _08021BE0\n\ +_08021BC8:\n\ + cmp r2, 0xE2\n\ + bne _08021BDA\n\ + ldr r0, _08021C34 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x20\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08021BDA\n\ + b _08022244\n\ +_08021BDA:\n\ + ldrh r0, [r7]\n\ + ldr r1, [sp, 0xC]\n\ + strh r0, [r1]\n\ +_08021BE0:\n\ + movs r4, 0\n\ + ldr r2, _08021C38 @ =gBattleMons\n\ + ldr r3, _08021C3C @ =gBankAttacker\n\ + ldrb r1, [r3]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r2, 0xC\n\ + adds r0, r2\n\ + ldrh r0, [r0]\n\ + ldr r5, [sp, 0xC]\n\ + ldrh r1, [r5]\n\ + mov r9, r3\n\ + cmp r0, r1\n\ + beq _08021C18\n\ + mov r6, r9\n\ + movs r3, 0x58\n\ + adds r5, r1, 0\n\ +_08021C02:\n\ + adds r4, 0x1\n\ + cmp r4, 0x3\n\ + bgt _08021C18\n\ + lsls r0, r4, 1\n\ + ldrb r1, [r6]\n\ + muls r1, r3\n\ + adds r0, r1\n\ + adds r0, r2\n\ + ldrh r0, [r0]\n\ + cmp r0, r5\n\ + bne _08021C02\n\ +_08021C18:\n\ + cmp r4, 0x4\n\ + beq _08021C1E\n\ + b _08022244\n\ +_08021C1E:\n\ + movs r0, 0\n\ + ldr r1, [sp, 0xC]\n\ +_08021C22:\n\ + strh r0, [r1]\n\ + b _08022244\n\ + .align 2, 0\n\ +_08021C28: .4byte gHitMarker\n\ +_08021C2C: .4byte gUnknown_02024BE8\n\ +_08021C30: .4byte 0x0000ffff\n\ +_08021C34: .4byte gBattleMoveFlags\n\ +_08021C38: .4byte gBattleMons\n\ +_08021C3C: .4byte gBankAttacker\n\ +_08021C40:\n\ + movs r4, 0\n\ + ldr r0, _08021C6C @ =gNoOfAllBanks\n\ + ldrb r2, [r0]\n\ + cmp r4, r2\n\ + blt _08021C4C\n\ + b _08022244\n\ +_08021C4C:\n\ + movs r5, 0\n\ + ldr r2, _08021C70 @ =0x020160f0\n\ + ldr r3, _08021C74 @ =gBattleMons\n\ +_08021C52:\n\ + ldrh r1, [r2]\n\ + cmp r1, 0\n\ + beq _08021C5C\n\ + strh r1, [r3, 0x2E]\n\ + strh r5, [r2]\n\ +_08021C5C:\n\ + adds r2, 0x2\n\ + adds r3, 0x58\n\ + adds r4, 0x1\n\ + ldrb r1, [r0]\n\ + cmp r4, r1\n\ + blt _08021C52\n\ + b _08022244\n\ + .align 2, 0\n\ +_08021C6C: .4byte gNoOfAllBanks\n\ +_08021C70: .4byte 0x020160f0\n\ +_08021C74: .4byte gBattleMons\n\ +_08021C78:\n\ + movs r0, 0x3\n\ + movs r1, 0\n\ + movs r2, 0\n\ + bl ItemBattleEffects\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08021C98\n\ + movs r2, 0x1\n\ + mov r10, r2\n\ + ldr r3, _08021C94 @ =0x02000000\n\ + mov r12, r3\n\ + b _0802224E\n\ + .align 2, 0\n\ +_08021C94: .4byte 0x02000000\n\ +_08021C98:\n\ + ldr r2, _08021CA0 @ =0x02000000\n\ + ldr r4, _08021CA4 @ =0x0001600c\n\ + adds r1, r2, r4\n\ + b _08021E00\n\ + .align 2, 0\n\ +_08021CA0: .4byte 0x02000000\n\ +_08021CA4: .4byte 0x0001600c\n\ +_08021CA8:\n\ + movs r0, 0x4\n\ + movs r1, 0\n\ + movs r2, 0\n\ + bl ItemBattleEffects\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08021CBC\n\ + movs r5, 0x1\n\ + mov r10, r5\n\ +_08021CBC:\n\ + ldr r2, _08021CC4 @ =0x02000000\n\ + ldr r0, _08021CC8 @ =0x0001600c\n\ + adds r1, r2, r0\n\ + b _08021E00\n\ + .align 2, 0\n\ +_08021CC4: .4byte 0x02000000\n\ +_08021CC8: .4byte 0x0001600c\n\ +_08021CCC:\n\ + ldr r1, _08021D04 @ =gStatuses3\n\ + ldr r0, _08021D08 @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + lsls r0, r2, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + ldr r1, _08021D0C @ =0x000400c0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08021CE2\n\ + b _08021DFA\n\ +_08021CE2:\n\ + ldr r0, _08021D10 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + movs r1, 0x80\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08021CF0\n\ + b _08021DFA\n\ +_08021CF0:\n\ + ldr r4, _08021D14 @ =gActiveBank\n\ + strb r2, [r4]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + bl EmitSpriteInvisibility\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + b _08021DFA\n\ + .align 2, 0\n\ +_08021D04: .4byte gStatuses3\n\ +_08021D08: .4byte gBankAttacker\n\ +_08021D0C: .4byte 0x000400c0\n\ +_08021D10: .4byte gHitMarker\n\ +_08021D14: .4byte gActiveBank\n\ +_08021D18:\n\ + ldr r0, _08021D88 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08021D44\n\ + ldr r1, _08021D8C @ =gStatuses3\n\ + ldr r0, _08021D90 @ =gBankAttacker\n\ + ldrb r2, [r0]\n\ + lsls r0, r2, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + ldr r1, _08021D94 @ =0x000400c0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021D44\n\ + adds r0, r2, 0\n\ + bl sub_8015660\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08021D7E\n\ +_08021D44:\n\ + ldr r4, _08021D98 @ =gActiveBank\n\ + ldr r5, _08021D90 @ =gBankAttacker\n\ + ldrb r0, [r5]\n\ + strb r0, [r4]\n\ + movs r0, 0\n\ + movs r1, 0\n\ + bl EmitSpriteInvisibility\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + ldr r0, _08021D8C @ =gStatuses3\n\ + ldrb r2, [r5]\n\ + lsls r2, 2\n\ + adds r2, r0\n\ + ldr r0, [r2]\n\ + ldr r1, _08021D9C @ =0xfffbff3f\n\ + ands r0, r1\n\ + str r0, [r2]\n\ + ldr r2, _08021DA0 @ =gSpecialStatuses\n\ + ldrb r1, [r5]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldrb r1, [r0]\n\ + movs r2, 0x4\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ +_08021D7E:\n\ + ldr r2, _08021DA4 @ =0x02000000\n\ + ldr r4, _08021DA8 @ =0x0001600c\n\ + adds r1, r2, r4\n\ + b _08021E00\n\ + .align 2, 0\n\ +_08021D88: .4byte gBattleMoveFlags\n\ +_08021D8C: .4byte gStatuses3\n\ +_08021D90: .4byte gBankAttacker\n\ +_08021D94: .4byte 0x000400c0\n\ +_08021D98: .4byte gActiveBank\n\ +_08021D9C: .4byte 0xfffbff3f\n\ +_08021DA0: .4byte gSpecialStatuses\n\ +_08021DA4: .4byte 0x02000000\n\ +_08021DA8: .4byte 0x0001600c\n\ +_08021DAC:\n\ + ldr r2, _08021E0C @ =gSpecialStatuses\n\ + ldr r1, _08021E10 @ =gBankTarget\n\ + ldrb r3, [r1]\n\ + lsls r4, r3, 2\n\ + adds r0, r4, r3\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldrb r0, [r0]\n\ + lsls r0, 29\n\ + cmp r0, 0\n\ + blt _08021DFA\n\ + ldr r0, _08021E14 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r3, r0\n\ + bcs _08021DFA\n\ + ldr r5, _08021E18 @ =gStatuses3\n\ + adds r0, r4, r5\n\ + ldr r0, [r0]\n\ + ldr r1, _08021E1C @ =0x000400c0\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08021DFA\n\ + ldr r4, _08021E20 @ =gActiveBank\n\ + strb r3, [r4]\n\ + movs r0, 0\n\ + movs r1, 0\n\ + bl EmitSpriteInvisibility\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + ldr r0, _08021E10 @ =gBankTarget\n\ + ldrb r2, [r0]\n\ + lsls r2, 2\n\ + adds r2, r5\n\ + ldr r0, [r2]\n\ + ldr r1, _08021E24 @ =0xfffbff3f\n\ + ands r0, r1\n\ + str r0, [r2]\n\ +_08021DFA:\n\ + ldr r2, _08021E28 @ =0x02000000\n\ + ldr r3, _08021E2C @ =0x0001600c\n\ + adds r1, r2, r3\n\ +_08021E00:\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ + mov r12, r2\n\ + b _0802224E\n\ + .align 2, 0\n\ +_08021E0C: .4byte gSpecialStatuses\n\ +_08021E10: .4byte gBankTarget\n\ +_08021E14: .4byte gNoOfAllBanks\n\ +_08021E18: .4byte gStatuses3\n\ +_08021E1C: .4byte 0x000400c0\n\ +_08021E20: .4byte gActiveBank\n\ +_08021E24: .4byte 0xfffbff3f\n\ +_08021E28: .4byte 0x02000000\n\ +_08021E2C: .4byte 0x0001600c\n\ +_08021E30:\n\ + movs r4, 0\n\ + ldr r0, _08021E60 @ =gNoOfAllBanks\n\ + ldrb r5, [r0]\n\ + cmp r4, r5\n\ + blt _08021E3C\n\ + b _08022244\n\ +_08021E3C:\n\ + ldr r2, _08021E64 @ =gDisableStructs\n\ + ldr r5, _08021E68 @ =0xfeffffff\n\ + adds r3, r0, 0\n\ + ldr r1, _08021E6C @ =gUnknown_02024AD0\n\ +_08021E44:\n\ + ldrb r0, [r2, 0xA]\n\ + cmp r0, 0\n\ + bne _08021E50\n\ + ldr r0, [r1]\n\ + ands r0, r5\n\ + str r0, [r1]\n\ +_08021E50:\n\ + adds r2, 0x1C\n\ + adds r1, 0x58\n\ + adds r4, 0x1\n\ + ldrb r0, [r3]\n\ + cmp r4, r0\n\ + blt _08021E44\n\ + b _08022244\n\ + .align 2, 0\n\ +_08021E60: .4byte gNoOfAllBanks\n\ +_08021E64: .4byte gDisableStructs\n\ +_08021E68: .4byte 0xfeffffff\n\ +_08021E6C: .4byte gUnknown_02024AD0\n\ +_08021E70:\n\ + ldr r1, _08021F2C @ =gHitMarker\n\ + ldr r3, [r1]\n\ + movs r0, 0x80\n\ + lsls r0, 5\n\ + ands r0, r3\n\ + ldr r2, _08021F30 @ =gBankAttacker\n\ + mov r9, r2\n\ + adds r5, r1, 0\n\ + cmp r0, 0\n\ + beq _08021E9A\n\ + ldr r0, _08021F34 @ =gActiveBank\n\ + ldrb r2, [r2]\n\ + strb r2, [r0]\n\ + ldr r1, _08021F38 @ =gBankTarget\n\ + ldrb r0, [r1]\n\ + mov r4, r9\n\ + strb r0, [r4]\n\ + strb r2, [r1]\n\ + ldr r0, _08021F3C @ =0xffffefff\n\ + ands r3, r0\n\ + str r3, [r5]\n\ +_08021E9A:\n\ + ldr r1, _08021F40 @ =gBattleMoves\n\ + ldr r2, _08021F44 @ =gUnknown_02024BE8\n\ + ldrh r3, [r2]\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + mov r8, r1\n\ + adds r7, r2, 0\n\ + cmp r0, 0x7F\n\ + bne _08021EBE\n\ + ldr r0, _08021F48 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021ECA\n\ +_08021EBE:\n\ + ldr r1, _08021F4C @ =gUnknown_02024C2C\n\ + mov r2, r9\n\ + ldrb r0, [r2]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + strh r3, [r0]\n\ +_08021ECA:\n\ + ldr r0, _08021F50 @ =gAbsentBankFlags\n\ + ldrb r1, [r0]\n\ + ldr r2, _08021F54 @ =gBitTable\n\ + mov r3, r9\n\ + ldrb r4, [r3]\n\ + lsls r0, r4, 2\n\ + adds r0, r2\n\ + ldr r3, [r0]\n\ + ands r1, r3\n\ + adds r6, r2, 0\n\ + cmp r1, 0\n\ + beq _08021EE4\n\ + b _08022244\n\ +_08021EE4:\n\ + ldr r0, _08021F58 @ =0x000160a6\n\ + add r0, r12\n\ + ldrb r0, [r0]\n\ + ands r0, r3\n\ + cmp r0, 0\n\ + beq _08021EF2\n\ + b _08022244\n\ +_08021EF2:\n\ + ldrh r2, [r7]\n\ + lsls r0, r2, 1\n\ + adds r0, r2\n\ + lsls r0, 2\n\ + add r0, r8\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x7F\n\ + bne _08021F04\n\ + b _08022244\n\ +_08021F04:\n\ + ldr r0, [r5]\n\ + movs r1, 0x80\n\ + lsls r1, 18\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08021F68\n\ + ldr r1, _08021F5C @ =gLastUsedMove\n\ + lsls r0, r4, 1\n\ + adds r0, r1\n\ + strh r2, [r0]\n\ + ldr r0, _08021F60 @ =gUnknown_02024C4C\n\ + mov r4, r9\n\ + ldrb r1, [r4]\n\ + lsls r1, 1\n\ + adds r1, r0\n\ + ldr r0, _08021F64 @ =gCurrentMove\n\ + ldrh r0, [r0]\n\ + strh r0, [r1]\n\ + b _08021F82\n\ + .align 2, 0\n\ +_08021F2C: .4byte gHitMarker\n\ +_08021F30: .4byte gBankAttacker\n\ +_08021F34: .4byte gActiveBank\n\ +_08021F38: .4byte gBankTarget\n\ +_08021F3C: .4byte 0xffffefff\n\ +_08021F40: .4byte gBattleMoves\n\ +_08021F44: .4byte gUnknown_02024BE8\n\ +_08021F48: .4byte gBattleMoveFlags\n\ +_08021F4C: .4byte gUnknown_02024C2C\n\ +_08021F50: .4byte gAbsentBankFlags\n\ +_08021F54: .4byte gBitTable\n\ +_08021F58: .4byte 0x000160a6\n\ +_08021F5C: .4byte gLastUsedMove\n\ +_08021F60: .4byte gUnknown_02024C4C\n\ +_08021F64: .4byte gCurrentMove\n\ +_08021F68:\n\ + ldr r1, _08021FD0 @ =gLastUsedMove\n\ + lsls r0, r4, 1\n\ + adds r0, r1\n\ + ldr r1, _08021FD4 @ =0x0000ffff\n\ + strh r1, [r0]\n\ + ldr r1, _08021FD8 @ =gUnknown_02024C4C\n\ + mov r2, r9\n\ + ldrb r0, [r2]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + movs r1, 0x1\n\ + negs r1, r1\n\ + strh r1, [r0]\n\ +_08021F82:\n\ + ldr r2, _08021FDC @ =gBankTarget\n\ + ldrb r3, [r2]\n\ + lsls r0, r3, 2\n\ + adds r0, r6\n\ + ldr r0, [r0]\n\ + lsls r0, 28\n\ + ldr r1, [r5]\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + bne _08021FA0\n\ + ldr r0, _08021FE0 @ =gUnknown_02024C5C\n\ + adds r0, r3, r0\n\ + mov r3, r9\n\ + ldrb r1, [r3]\n\ + strb r1, [r0]\n\ +_08021FA0:\n\ + ldr r0, [r5]\n\ + movs r1, 0x80\n\ + lsls r1, 18\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0802204C\n\ + ldr r0, _08021FE4 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0802204C\n\ + ldrh r2, [r7]\n\ + ldr r0, _08021FD4 @ =0x0000ffff\n\ + cmp r2, r0\n\ + bne _08021FEC\n\ + ldr r1, _08021FE8 @ =gMoveHitWith\n\ + ldr r4, _08021FDC @ =gBankTarget\n\ + ldrb r0, [r4]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + strh r2, [r0]\n\ + b _08022244\n\ + .align 2, 0\n\ +_08021FD0: .4byte gLastUsedMove\n\ +_08021FD4: .4byte 0x0000ffff\n\ +_08021FD8: .4byte gUnknown_02024C4C\n\ +_08021FDC: .4byte gBankTarget\n\ +_08021FE0: .4byte gUnknown_02024C5C\n\ +_08021FE4: .4byte gBattleMoveFlags\n\ +_08021FE8: .4byte gMoveHitWith\n\ +_08021FEC:\n\ + ldr r0, _08022014 @ =gMoveHitWith\n\ + ldr r5, _08022018 @ =gBankTarget\n\ + ldrb r1, [r5]\n\ + lsls r1, 1\n\ + adds r1, r0\n\ + ldr r4, _0802201C @ =gCurrentMove\n\ + ldrh r0, [r4]\n\ + strh r0, [r1]\n\ + ldr r0, _08022020 @ =0x0001601c\n\ + add r0, r12\n\ + ldrb r3, [r0]\n\ + cmp r3, 0\n\ + beq _08022028\n\ + ldr r0, _08022024 @ =gUnknown_02024C44\n\ + ldrb r1, [r5]\n\ + lsls r1, 1\n\ + adds r1, r0\n\ + movs r0, 0x3F\n\ + ands r0, r3\n\ + b _08021C22\n\ + .align 2, 0\n\ +_08022014: .4byte gMoveHitWith\n\ +_08022018: .4byte gBankTarget\n\ +_0802201C: .4byte gCurrentMove\n\ +_08022020: .4byte 0x0001601c\n\ +_08022024: .4byte gUnknown_02024C44\n\ +_08022028:\n\ + ldr r0, _08022044 @ =gUnknown_02024C44\n\ + ldr r1, _08022048 @ =gBankTarget\n\ + ldrb r2, [r1]\n\ + lsls r2, 1\n\ + adds r2, r0\n\ + ldrh r1, [r4]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + add r0, r8\n\ + ldrb r0, [r0, 0x2]\n\ + strh r0, [r2]\n\ + b _08022244\n\ + .align 2, 0\n\ +_08022044: .4byte gUnknown_02024C44\n\ +_08022048: .4byte gBankTarget\n\ +_0802204C:\n\ + ldr r0, _0802205C @ =gMoveHitWith\n\ + ldr r2, _08022060 @ =gBankTarget\n\ + ldrb r1, [r2]\n\ + lsls r1, 1\n\ + adds r1, r0\n\ + ldr r0, _08022064 @ =0x0000ffff\n\ + b _08021C22\n\ + .align 2, 0\n\ +_0802205C: .4byte gMoveHitWith\n\ +_08022060: .4byte gBankTarget\n\ +_08022064: .4byte 0x0000ffff\n\ +_08022068:\n\ + ldr r0, _0802212C @ =gAbsentBankFlags\n\ + ldrb r1, [r0]\n\ + ldr r6, _08022130 @ =gBitTable\n\ + ldr r2, _08022134 @ =gBankAttacker\n\ + ldrb r5, [r2]\n\ + lsls r0, r5, 2\n\ + adds r0, r6\n\ + ldr r4, [r0]\n\ + ands r1, r4\n\ + mov r9, r2\n\ + cmp r1, 0\n\ + beq _08022082\n\ + b _08022244\n\ +_08022082:\n\ + ldr r0, _08022138 @ =0x000160a6\n\ + add r0, r12\n\ + ldrb r0, [r0]\n\ + ands r0, r4\n\ + cmp r0, 0\n\ + beq _08022090\n\ + b _08022244\n\ +_08022090:\n\ + ldr r1, _0802213C @ =gBattleMoves\n\ + ldr r4, _08022140 @ =gUnknown_02024BE8\n\ + ldrh r3, [r4]\n\ + lsls r0, r3, 1\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r1, [r0, 0x8]\n\ + movs r0, 0x10\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0802215C\n\ + ldr r0, _08022144 @ =gHitMarker\n\ + ldr r1, [r0]\n\ + movs r0, 0x80\n\ + lsls r0, 18\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0802215C\n\ + ldr r2, _08022148 @ =gBankTarget\n\ + ldrb r0, [r2]\n\ + cmp r5, r0\n\ + bne _080220C0\n\ + b _08022244\n\ +_080220C0:\n\ + adds r2, r0, 0\n\ + lsls r0, r2, 2\n\ + adds r0, r6\n\ + ldr r0, [r0]\n\ + lsls r0, 28\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + bne _0802215C\n\ + ldr r0, _0802214C @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r0, 0x29\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0802215C\n\ + lsls r0, r2, 1\n\ + ldr r5, _08022150 @ =0x000160ac\n\ + adds r0, r5\n\ + add r0, r12\n\ + strb r3, [r0]\n\ + ldr r0, _08022148 @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + lsls r1, 1\n\ + ldr r2, _08022154 @ =0x000160ad\n\ + adds r1, r2\n\ + add r1, r12\n\ + ldrh r0, [r4]\n\ + lsrs r0, 8\n\ + strb r0, [r1]\n\ + ldr r3, _08022148 @ =gBankTarget\n\ + ldrb r2, [r3]\n\ + lsls r2, 2\n\ + mov r5, r9\n\ + ldrb r0, [r5]\n\ + lsrs r0, 1\n\ + lsls r0, 1\n\ + ldr r1, _08022158 @ =0x00016100\n\ + adds r0, r1\n\ + adds r2, r0\n\ + add r2, r12\n\ + ldrh r0, [r4]\n\ + strb r0, [r2]\n\ + ldrb r2, [r3]\n\ + lsls r2, 2\n\ + ldrb r0, [r5]\n\ + lsrs r0, 1\n\ + lsls r0, 1\n\ + adds r1, 0x1\n\ + adds r0, r1\n\ + adds r2, r0\n\ + add r2, r12\n\ + ldrh r0, [r4]\n\ + lsrs r0, 8\n\ + strb r0, [r2]\n\ + b _08022244\n\ + .align 2, 0\n\ +_0802212C: .4byte gAbsentBankFlags\n\ +_08022130: .4byte gBitTable\n\ +_08022134: .4byte gBankAttacker\n\ +_08022138: .4byte 0x000160a6\n\ +_0802213C: .4byte gBattleMoves\n\ +_08022140: .4byte gUnknown_02024BE8\n\ +_08022144: .4byte gHitMarker\n\ +_08022148: .4byte gBankTarget\n\ +_0802214C: .4byte gBattleMoveFlags\n\ +_08022150: .4byte 0x000160ac\n\ +_08022154: .4byte 0x000160ad\n\ +_08022158: .4byte 0x00016100\n\ +_0802215C:\n\ + mov r1, r9\n\ + ldrb r0, [r1]\n\ + ldr r2, _080221B4 @ =gBankTarget\n\ + ldrb r2, [r2]\n\ + cmp r0, r2\n\ + beq _08022244\n\ + ldr r3, _080221B4 @ =gBankTarget\n\ + ldrb r0, [r3]\n\ + lsls r0, 1\n\ + ldr r4, _080221B8 @ =0x000160ac\n\ + adds r0, r4\n\ + add r0, r12\n\ + movs r3, 0\n\ + strb r3, [r0]\n\ + ldr r5, _080221B4 @ =gBankTarget\n\ + ldrb r0, [r5]\n\ + lsls r0, 1\n\ + ldr r1, _080221BC @ =0x000160ad\n\ + adds r0, r1\n\ + add r0, r12\n\ + strb r3, [r0]\n\ + ldrb r2, [r5]\n\ + lsls r2, 2\n\ + mov r4, r9\n\ + ldrb r0, [r4]\n\ + lsrs r0, 1\n\ + lsls r0, 1\n\ + adds r1, 0x53\n\ + adds r0, r1\n\ + adds r2, r0\n\ + add r2, r12\n\ + strb r3, [r2]\n\ + ldrb r2, [r5]\n\ + lsls r2, 2\n\ + ldrb r0, [r4]\n\ + lsrs r0, 1\n\ + lsls r0, 1\n\ + adds r1, 0x1\n\ + adds r0, r1\n\ + adds r2, r0\n\ + add r2, r12\n\ + strb r3, [r2]\n\ + b _08022244\n\ + .align 2, 0\n\ +_080221B4: .4byte gBankTarget\n\ +_080221B8: .4byte 0x000160ac\n\ +_080221BC: .4byte 0x000160ad\n\ +_080221C0:\n\ + ldr r5, _080222B0 @ =gHitMarker\n\ + ldr r2, [r5]\n\ + movs r0, 0x80\n\ + lsls r0, 12\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + bne _08022244\n\ + ldr r0, _080222B4 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08022244\n\ + ldr r1, _080222B8 @ =gProtectStructs\n\ + ldr r0, _080222BC @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + lsls r0, 4\n\ + adds r0, r1\n\ + ldrb r0, [r0, 0x1]\n\ + lsls r0, 29\n\ + cmp r0, 0\n\ + blt _08022244\n\ + ldr r0, _080222C0 @ =gBattleMoves\n\ + mov r9, r0\n\ + ldr r1, _080222C4 @ =gCurrentMove\n\ + mov r8, r1\n\ + ldrh r0, [r1]\n\ + lsls r1, r0, 1\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + add r1, r9\n\ + ldrb r0, [r1, 0x6]\n\ + cmp r0, 0x8\n\ + bne _08022244\n\ + movs r6, 0x80\n\ + lsls r6, 2\n\ + adds r4, r6, 0\n\ + ands r4, r2\n\ + cmp r4, 0\n\ + bne _08022244\n\ + ldr r7, _080222C8 @ =gBankTarget\n\ + ldrb r0, [r7]\n\ + bl GetBankIdentity\n\ + movs r1, 0x2\n\ + eors r0, r1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + bl GetBankByPlayerAI\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + ldr r1, _080222CC @ =gBattleMons\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + beq _0802223A\n\ + bl _08021874\n\ +_0802223A:\n\ + ldr r0, [r5]\n\ + orrs r0, r6\n\ + str r0, [r5]\n\ + ldr r2, _080222D0 @ =0x02000000\n\ + mov r12, r2\n\ +_08022244:\n\ + ldr r1, _080222D4 @ =0x0001600c\n\ + add r1, r12\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ +_0802224E:\n\ + ldr r3, [sp, 0x10]\n\ + cmp r3, 0x1\n\ + bne _08022262\n\ + mov r4, r10\n\ + cmp r4, 0\n\ + bne _08022262\n\ + ldr r1, _080222D4 @ =0x0001600c\n\ + add r1, r12\n\ + movs r0, 0x11\n\ + strb r0, [r1]\n\ +_08022262:\n\ + ldr r5, [sp, 0x10]\n\ + cmp r5, 0x2\n\ + bne _08022278\n\ + ldr r1, _080222D4 @ =0x0001600c\n\ + add r1, r12\n\ + ldr r0, [sp, 0x14]\n\ + ldrb r2, [r1]\n\ + cmp r0, r2\n\ + bne _08022278\n\ + movs r0, 0x11\n\ + strb r0, [r1]\n\ +_08022278:\n\ + ldr r0, _080222D4 @ =0x0001600c\n\ + add r0, r12\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x11\n\ + beq _08022286\n\ + bl _080218E4\n\ +_08022286:\n\ + ldr r0, _080222D4 @ =0x0001600c\n\ + add r0, r12\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x11\n\ + bne _0802229E\n\ + mov r3, r10\n\ + cmp r3, 0\n\ + bne _0802229E\n\ + ldr r1, _080222D8 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x3\n\ +_0802229C:\n\ + str r0, [r1]\n\ +_0802229E:\n\ + add sp, 0x18\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080222B0: .4byte gHitMarker\n\ +_080222B4: .4byte gBattleTypeFlags\n\ +_080222B8: .4byte gProtectStructs\n\ +_080222BC: .4byte gBankAttacker\n\ +_080222C0: .4byte gBattleMoves\n\ +_080222C4: .4byte gCurrentMove\n\ +_080222C8: .4byte gBankTarget\n\ +_080222CC: .4byte gBattleMons\n\ +_080222D0: .4byte 0x02000000\n\ +_080222D4: .4byte 0x0001600c\n\ +_080222D8: .4byte gBattlescriptCurrInstr\n\ + .syntax divided" + ); +} +#endif // NONMATCHING + +static void atk4A_typecalc2(void) +{ + u8 flags = 0; + int i = 0; + u8 move_type = gBattleMoves[gCurrentMove].type; + + if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && move_type == TYPE_GROUND) + { + gLastUsedAbility = gBattleMons[gBankTarget].ability; + gBattleMoveFlags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED); + gMoveHitWith[gBankTarget] = 0; + gBattleCommunication[6] = move_type; + RecordAbilityBattle(gBankTarget, gLastUsedAbility); + } + else + { + while (gTypeEffectiveness[i]!= TYPE_ENDTABLE) + { + if (gTypeEffectiveness[i] == TYPE_FORESIGHT) + { + if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT) {break;} + else {i += 3; continue;} + } + + if (gTypeEffectiveness[i] == move_type) + { + //check type1 + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1) + { + if (gTypeEffectiveness[i + 2] == 0) + { + gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED; + break; + } + if (gTypeEffectiveness[i + 2] == 5) + flags |= MOVESTATUS_NOTVERYEFFECTIVE; + if (gTypeEffectiveness[i + 2] == 20) + flags |= MOVESTATUS_SUPEREFFECTIVE; + } + //check type2 + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2) + { + if (gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 + && gTypeEffectiveness[i + 2] == 0) + { + gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED; + break; + } + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 && gTypeEffectiveness[i + 2] == 5) + flags |= MOVESTATUS_NOTVERYEFFECTIVE; + if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 + && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 && gTypeEffectiveness[i + 2] == 20) + flags |= MOVESTATUS_SUPEREFFECTIVE; + } + } + i += 3; + } + } + + if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD && !(flags & MOVESTATUS_NOEFFECT) && AttacksThisTurn(gBankAttacker, gCurrentMove) == 2 && + (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE))) && + gBattleMoves[gCurrentMove].power) + { + gLastUsedAbility = ABILITY_WONDER_GUARD; + gBattleMoveFlags |= MOVESTATUS_MISSED; + gMoveHitWith[gBankTarget] = 0; + gBattleCommunication[6] = 3; + RecordAbilityBattle(gBankTarget, gLastUsedAbility); + } + if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) + gProtectStructs[gBankAttacker].notEffective = 1; + + gBattlescriptCurrInstr++; +} + +static void atk4B_return_atk_to_ball(void) +{ + gActiveBank = gBankAttacker; + if (!(gHitMarker & HITMARKER_FAINTED(gActiveBank))) + { + EmitReturnPokeToBall(0, 0); + MarkBufferBankForExecution(gActiveBank); + } + gBattlescriptCurrInstr++; +} + +static void atk4C_copy_poke_data(void) +{ + if (gBattleExecBuffer) + return; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + + gBattlePartyID[gActiveBank] = unk_2000000[0x16068 + gActiveBank]; + + EmitGetAttributes(0, 0, gBitTable[gBattlePartyID[gActiveBank]]); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +static inline u8 get_knocked_off_byte(u8 bank) +{ + register u32 side asm("r2") = GetBankSide(bank); + register struct WishFutureKnock* dummy = &gWishFutureKnock; + register u8* aa = ((u8*)((u8*)(dummy))); + register u8* bb = aa + 0x29; + register u8* cc asm("r0") = side + bb; + return *cc; +} + +static void atk4D_switch_data_update(void) +{ + struct BattlePokemon OldData; + int i; + u8 *monData; + if (gBattleExecBuffer) + return; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + OldData = gBattleMons[gActiveBank]; + monData = (u8*)(&gBattleMons[gActiveBank]); + for (i = 0; i < sizeof(struct BattlePokemon); i++) + { + monData[i] = gBattleBufferB[gActiveBank][4 + i]; + } + + gBattleMons[gActiveBank].type1 = gBaseStats[gBattleMons[gActiveBank].species].type1; + gBattleMons[gActiveBank].type2 = gBaseStats[gBattleMons[gActiveBank].species].type2; + gBattleMons[gActiveBank].ability = GetAbilityBySpecies(gBattleMons[gActiveBank].species, gBattleMons[gActiveBank].altAbility); + //check knocked off item + if (get_knocked_off_byte(gActiveBank) & gBitTable[gBattlePartyID[gActiveBank]]) + { + gBattleMons[gActiveBank].item = 0; + } + + if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS) + { + for (i = 0; i < 8; i++) + { + gBattleMons[gActiveBank].statStages[i] = OldData.statStages[i]; + } + gBattleMons[gActiveBank].status2 = OldData.status2; + } + SwitchInClearStructs(); + BATTLE_STRUCT->scriptingActive = gActiveBank; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 7; + gBattleTextBuff1[2] = gActiveBank; + gBattleTextBuff1[3] = gBattlePartyID[gActiveBank]; + gBattleTextBuff1[4] = EOS; + + gBattlescriptCurrInstr += 2; +} + +static void atk4E_switchin_anim(void) +{ + if (gBattleExecBuffer) + return; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (GetBankSide(gActiveBank) == 1 && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_BATTLE_TOWER))) + { + GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), 2); + } + gAbsentBankFlags &= ~(gBitTable[gActiveBank]); + EmitSendOutPoke(0, gBattlePartyID[gActiveBank], BSScriptRead8(gBattlescriptCurrInstr + 2)); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 3; +} + +static void atk4F_jump_if_cannot_switch(void) +{ + int val, to_cmp; + register struct Pokemon *party; + u8 r7; + //0x80 byte is used as a way of telling the function whether to not check status2/status3 + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1) & 0x7F); + if (!(BSScriptRead8(gBattlescriptCurrInstr + 1) & 0x80) + && ((gBattleMons[gActiveBank].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)) + || (gStatuses3[gActiveBank] & STATUS3_ROOTED))) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + return; + } + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (GetBankSide(gActiveBank) == 1) + party = gEnemyParty; + else + party = gPlayerParty; + val = 0; + if (sub_803FBFC(sub_803FC34(gActiveBank)) == 1) + val = 3; + for (to_cmp = val + 3; val < to_cmp; val++) + { + if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[val], MON_DATA_IS_EGG) + && GetMonData(&party[val], MON_DATA_HP) != 0 + && gBattlePartyID[gActiveBank] != val) + break; + } + if (val == to_cmp) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + else + gBattlescriptCurrInstr += 6; + } + else + { + if (GetBankSide(gActiveBank) == 1) + { + r7 = GetBankByPlayerAI(1); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + to_cmp = GetBankByPlayerAI(3); + else + to_cmp = r7; + party = gEnemyParty; + } + else + { + r7 = GetBankByPlayerAI(0); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + to_cmp = GetBankByPlayerAI(2); + else + to_cmp = r7; + party = gPlayerParty; + } + for (val = 0; val < 6; val++) + { + if (GetMonData(&party[val], MON_DATA_HP) != 0 + && GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[val], MON_DATA_IS_EGG) + && val != gBattlePartyID[r7] && val != gBattlePartyID[to_cmp]) + break; + } + if (val == 6) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + else + gBattlescriptCurrInstr += 6; + } +} + +void sub_8022A3C(u8 unkown) +{ + //BATTLE_STRUCT->unk16064[gActiveBank] = gBattlePartyID[gActiveBank]; + ewram[gActiveBank + 0x16064] = gBattlePartyID[gActiveBank]; + EmitChoosePokemon(0, 1, unkown, 0, BATTLE_STRUCT->unk1606C[gActiveBank]); + MarkBufferBankForExecution(gActiveBank); +} + +/* +static void atk50_openpartyscreen(void) +{ + int i = 0; + int r9 = 0; + u8* fail_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + + if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 5) + { + if ((gBattleTypeFlags & (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI)) != BATTLE_TYPE_DOUBLE) + { + for (gActiveBank = i; gActiveBank < gNoOfAllBanks; gActiveBank++) + { + if (!(gHitMarker & HITMARKER_FAINTED(gActiveBank))) + { + EmitLinkStandbyMsg(0, 2); + MarkBufferBankForExecution(gActiveBank); + } + else if (sub_8018018(gActiveBank, 6, 6) == 0 + && !gSpecialStatuses[gActiveBank].flag40) + { + sub_8022A3C(6); + gSpecialStatuses[gActiveBank].flag40 = 1; + } + else + { + gAbsentBankFlags |= gBitTable[gActiveBank]; + gHitMarker &= (~HITMARKER_FAINTED(gActiveBank)); + EmitLinkStandbyMsg(0, 2); + MarkBufferBankForExecution(gActiveBank); + } + } + } + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + if (!(gHitMarker >> 0x1C & gBitTable[0])) + { + + } + else if (sub_8018018(gActiveBank, 6, 6) == 0 + && !gSpecialStatuses[gActiveBank].flag40) + { + + } + else + { + + } + } + } +} +*/ + +__attribute__((naked)) +static void atk50_openpartyscreen(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r9\n\ + mov r6, r8\n\ + push {r6,r7}\n\ + sub sp, 0x4\n\ + movs r7, 0\n\ + movs r0, 0\n\ + mov r9, r0\n\ + ldr r6, _08022B44 @ =gBattlescriptCurrInstr\n\ + ldr r1, [r6]\n\ + ldrb r2, [r1, 0x2]\n\ + ldrb r0, [r1, 0x3]\n\ + lsls r0, 8\n\ + orrs r2, r0\n\ + ldrb r0, [r1, 0x4]\n\ + lsls r0, 16\n\ + orrs r2, r0\n\ + ldrb r0, [r1, 0x5]\n\ + lsls r0, 24\n\ + orrs r2, r0\n\ + mov r8, r2\n\ + ldrb r2, [r1, 0x1]\n\ + adds r0, r2, 0\n\ + mov r12, r6\n\ + cmp r0, 0x5\n\ + beq _08022ACE\n\ + b _08022F74\n\ +_08022ACE:\n\ + ldr r0, _08022B48 @ =gBattleTypeFlags\n\ + ldrh r0, [r0]\n\ + movs r1, 0x41\n\ + ands r1, r0\n\ + cmp r1, 0x1\n\ + beq _08022BBC\n\ + ldr r1, _08022B4C @ =gActiveBank\n\ + strb r7, [r1]\n\ + ldr r0, _08022B50 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r7, r0\n\ + bcc _08022AE8\n\ + b _08022F62\n\ +_08022AE8:\n\ + ldr r7, _08022B54 @ =gHitMarker\n\ + ldr r6, _08022B58 @ =gBitTable\n\ + adds r4, r1, 0\n\ + ldr r0, _08022B5C @ =gAbsentBankFlags\n\ + mov r8, r0\n\ +_08022AF2:\n\ + ldrb r2, [r4]\n\ + lsls r0, r2, 2\n\ + adds r0, r6\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + ldr r0, [r7]\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08022B94\n\ + adds r0, r2, 0\n\ + movs r1, 0x6\n\ + movs r2, 0x6\n\ + bl sub_8018018\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08022B60\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r0, [r0]\n\ + mov r2, r8\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + ldr r0, [r7]\n\ + bics r0, r1\n\ + str r0, [r7]\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + b _08022BA2\n\ + .align 2, 0\n\ +_08022B44: .4byte gBattlescriptCurrInstr\n\ +_08022B48: .4byte gBattleTypeFlags\n\ +_08022B4C: .4byte gActiveBank\n\ +_08022B50: .4byte gNoOfAllBanks\n\ +_08022B54: .4byte gHitMarker\n\ +_08022B58: .4byte gBitTable\n\ +_08022B5C: .4byte gAbsentBankFlags\n\ +_08022B60:\n\ + ldr r5, _08022B90 @ =gSpecialStatuses\n\ + ldrb r0, [r4]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r5\n\ + ldrb r0, [r1]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022BA2\n\ + movs r0, 0x6\n\ + bl sub_8022A3C\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r5\n\ + ldrb r1, [r0]\n\ + movs r2, 0x40\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _08022BA2\n\ + .align 2, 0\n\ +_08022B90: .4byte gSpecialStatuses\n\ +_08022B94:\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ +_08022BA2:\n\ + ldrb r0, [r4]\n\ + adds r0, 0x1\n\ + strb r0, [r4]\n\ + ldr r1, _08022BB8 @ =gNoOfAllBanks\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + ldrb r1, [r1]\n\ + cmp r0, r1\n\ + bcc _08022AF2\n\ + b _08022F62\n\ + .align 2, 0\n\ +_08022BB8: .4byte gNoOfAllBanks\n\ +_08022BBC:\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + bne _08022BC4\n\ + b _08022F62\n\ +_08022BC4:\n\ + ldr r0, _08022C1C @ =gHitMarker\n\ + mov r8, r0\n\ + ldr r0, [r0]\n\ + lsrs r5, r0, 28\n\ + ldr r6, _08022C20 @ =gBitTable\n\ + ldr r0, [r6]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _08022C7E\n\ + ldr r4, _08022C24 @ =gActiveBank\n\ + strb r7, [r4]\n\ + movs r0, 0\n\ + movs r1, 0x6\n\ + movs r2, 0x6\n\ + bl sub_8018018\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08022C2C\n\ + ldr r2, _08022C28 @ =gAbsentBankFlags\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + mov r2, r8\n\ + ldr r0, [r2]\n\ + bics r0, r1\n\ + str r0, [r2]\n\ + movs r0, 0\n\ + bl Emitcmd42\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + b _08022C7E\n\ + .align 2, 0\n\ +_08022C1C: .4byte gHitMarker\n\ +_08022C20: .4byte gBitTable\n\ +_08022C24: .4byte gActiveBank\n\ +_08022C28: .4byte gAbsentBankFlags\n\ +_08022C2C:\n\ + ldr r6, _08022C60 @ =gSpecialStatuses\n\ + ldrb r0, [r4]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r6\n\ + ldrb r0, [r1]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022C6C\n\ + ldr r0, _08022C64 @ =0x02000000\n\ + ldr r1, _08022C68 @ =0x0001606a\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + bl sub_8022A3C\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldrb r1, [r0]\n\ + movs r2, 0x40\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _08022C7E\n\ + .align 2, 0\n\ +_08022C60: .4byte gSpecialStatuses\n\ +_08022C64: .4byte 0x02000000\n\ +_08022C68: .4byte 0x0001606a\n\ +_08022C6C:\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + movs r2, 0x1\n\ + mov r9, r2\n\ +_08022C7E:\n\ + ldr r6, _08022CD8 @ =gBitTable\n\ + ldr r0, [r6, 0x8]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _08022D40\n\ + ldr r0, [r6]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + bne _08022D40\n\ + ldr r4, _08022CDC @ =gActiveBank\n\ + movs r0, 0x2\n\ + strb r0, [r4]\n\ + movs r0, 0x2\n\ + movs r1, 0x6\n\ + movs r2, 0x6\n\ + bl sub_8018018\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08022CE8\n\ + ldr r2, _08022CE0 @ =gAbsentBankFlags\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r2, _08022CE4 @ =gHitMarker\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + ldr r0, [r2]\n\ + bics r0, r1\n\ + str r0, [r2]\n\ + movs r0, 0\n\ + bl Emitcmd42\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + b _08022D40\n\ + .align 2, 0\n\ +_08022CD8: .4byte gBitTable\n\ +_08022CDC: .4byte gActiveBank\n\ +_08022CE0: .4byte gAbsentBankFlags\n\ +_08022CE4: .4byte gHitMarker\n\ +_08022CE8:\n\ + ldr r6, _08022D1C @ =gSpecialStatuses\n\ + ldrb r0, [r4]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r6\n\ + ldrb r0, [r1]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022D28\n\ + ldr r0, _08022D20 @ =0x02000000\n\ + ldr r1, _08022D24 @ =0x00016068\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + bl sub_8022A3C\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldrb r1, [r0]\n\ + movs r2, 0x40\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _08022D40\n\ + .align 2, 0\n\ +_08022D1C: .4byte gSpecialStatuses\n\ +_08022D20: .4byte 0x02000000\n\ +_08022D24: .4byte 0x00016068\n\ +_08022D28:\n\ + movs r0, 0x1\n\ + mov r2, r9\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + bne _08022D40\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ +_08022D40:\n\ + ldr r6, _08022D90 @ =gBitTable\n\ + ldr r0, [r6, 0x4]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _08022DF6\n\ + ldr r4, _08022D94 @ =gActiveBank\n\ + movs r0, 0x1\n\ + strb r0, [r4]\n\ + movs r0, 0x1\n\ + movs r1, 0x6\n\ + movs r2, 0x6\n\ + bl sub_8018018\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08022DA0\n\ + ldr r2, _08022D98 @ =gAbsentBankFlags\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r2, _08022D9C @ =gHitMarker\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + ldr r0, [r2]\n\ + bics r0, r1\n\ + str r0, [r2]\n\ + movs r0, 0\n\ + bl Emitcmd42\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + b _08022DF6\n\ + .align 2, 0\n\ +_08022D90: .4byte gBitTable\n\ +_08022D94: .4byte gActiveBank\n\ +_08022D98: .4byte gAbsentBankFlags\n\ +_08022D9C: .4byte gHitMarker\n\ +_08022DA0:\n\ + ldr r6, _08022DD4 @ =gSpecialStatuses\n\ + ldrb r0, [r4]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r6\n\ + ldrb r0, [r1]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022DE0\n\ + ldr r0, _08022DD8 @ =0x02000000\n\ + ldr r1, _08022DDC @ =0x0001606b\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + bl sub_8022A3C\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldrb r1, [r0]\n\ + movs r2, 0x40\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _08022DF6\n\ + .align 2, 0\n\ +_08022DD4: .4byte gSpecialStatuses\n\ +_08022DD8: .4byte 0x02000000\n\ +_08022DDC: .4byte 0x0001606b\n\ +_08022DE0:\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + movs r0, 0x2\n\ + mov r2, r9\n\ + orrs r2, r0\n\ + mov r9, r2\n\ +_08022DF6:\n\ + ldr r6, _08022E50 @ =gBitTable\n\ + ldr r0, [r6, 0xC]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _08022EB8\n\ + ldr r0, [r6, 0x4]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + bne _08022EB8\n\ + ldr r4, _08022E54 @ =gActiveBank\n\ + movs r0, 0x3\n\ + strb r0, [r4]\n\ + movs r0, 0x3\n\ + movs r1, 0x6\n\ + movs r2, 0x6\n\ + bl sub_8018018\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08022E60\n\ + ldr r2, _08022E58 @ =gAbsentBankFlags\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r2, _08022E5C @ =gHitMarker\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + ldr r0, [r2]\n\ + bics r0, r1\n\ + str r0, [r2]\n\ + movs r0, 0\n\ + bl Emitcmd42\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + b _08022EB8\n\ + .align 2, 0\n\ +_08022E50: .4byte gBitTable\n\ +_08022E54: .4byte gActiveBank\n\ +_08022E58: .4byte gAbsentBankFlags\n\ +_08022E5C: .4byte gHitMarker\n\ +_08022E60:\n\ + ldr r6, _08022E94 @ =gSpecialStatuses\n\ + ldrb r0, [r4]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r6\n\ + ldrb r0, [r1]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022EA0\n\ + ldr r0, _08022E98 @ =0x02000000\n\ + ldr r1, _08022E9C @ =0x00016069\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + bl sub_8022A3C\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldrb r1, [r0]\n\ + movs r2, 0x40\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _08022EB8\n\ + .align 2, 0\n\ +_08022E94: .4byte gSpecialStatuses\n\ +_08022E98: .4byte 0x02000000\n\ +_08022E9C: .4byte 0x00016069\n\ +_08022EA0:\n\ + movs r0, 0x2\n\ + mov r2, r9\n\ + ands r2, r0\n\ + cmp r2, 0\n\ + bne _08022EB8\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ +_08022EB8:\n\ + ldr r1, _08022EE8 @ =gSpecialStatuses\n\ + ldrb r0, [r1]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022F0C\n\ + adds r0, r1, 0\n\ + adds r0, 0x28\n\ + ldrb r0, [r0]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022F0C\n\ + cmp r5, 0\n\ + beq _08022F0C\n\ + ldr r0, _08022EEC @ =gAbsentBankFlags\n\ + ldrb r1, [r0]\n\ + ldr r0, _08022EF0 @ =gBitTable\n\ + ldr r0, [r0]\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + beq _08022EF8\n\ + ldr r1, _08022EF4 @ =gActiveBank\n\ + movs r0, 0x2\n\ + strb r0, [r1]\n\ + b _08022EFC\n\ + .align 2, 0\n\ +_08022EE8: .4byte gSpecialStatuses\n\ +_08022EEC: .4byte gAbsentBankFlags\n\ +_08022EF0: .4byte gBitTable\n\ +_08022EF4: .4byte gActiveBank\n\ +_08022EF8:\n\ + ldr r0, _08022F3C @ =gActiveBank\n\ + strb r1, [r0]\n\ +_08022EFC:\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldr r0, _08022F3C @ =gActiveBank\n\ + ldrb r0, [r0]\n\ + bl MarkBufferBankForExecution\n\ +_08022F0C:\n\ + ldr r1, _08022F40 @ =gSpecialStatuses\n\ + ldrb r0, [r1, 0x14]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022F62\n\ + adds r0, r1, 0\n\ + adds r0, 0x3C\n\ + ldrb r0, [r0]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _08022F62\n\ + cmp r5, 0\n\ + beq _08022F62\n\ + ldr r0, _08022F44 @ =gAbsentBankFlags\n\ + ldrb r0, [r0]\n\ + ldr r1, _08022F48 @ =gBitTable\n\ + ldr r1, [r1, 0x4]\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08022F4C\n\ + ldr r1, _08022F3C @ =gActiveBank\n\ + movs r0, 0x3\n\ + b _08022F50\n\ + .align 2, 0\n\ +_08022F3C: .4byte gActiveBank\n\ +_08022F40: .4byte gSpecialStatuses\n\ +_08022F44: .4byte gAbsentBankFlags\n\ +_08022F48: .4byte gBitTable\n\ +_08022F4C:\n\ + ldr r1, _08022F6C @ =gActiveBank\n\ + movs r0, 0x1\n\ +_08022F50:\n\ + strb r0, [r1]\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldr r0, _08022F6C @ =gActiveBank\n\ + ldrb r0, [r0]\n\ + bl MarkBufferBankForExecution\n\ +_08022F62:\n\ + ldr r1, _08022F70 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x6\n\ + str r0, [r1]\n\ + b _08023302\n\ + .align 2, 0\n\ +_08022F6C: .4byte gActiveBank\n\ +_08022F70: .4byte gBattlescriptCurrInstr\n\ +_08022F74:\n\ + cmp r0, 0x6\n\ + beq _08022F7A\n\ + b _08023170\n\ +_08022F7A:\n\ + ldr r0, _08022FF0 @ =gBattleTypeFlags\n\ + ldrh r2, [r0]\n\ + movs r0, 0x40\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + beq _08022F88\n\ + b _0802310C\n\ +_08022F88:\n\ + movs r0, 0x1\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + bne _08022F92\n\ + b _0802310C\n\ +_08022F92:\n\ + ldr r7, _08022FF4 @ =gHitMarker\n\ + ldr r0, [r7]\n\ + lsrs r5, r0, 28\n\ + ldr r4, _08022FF8 @ =gBitTable\n\ + ldr r0, [r4, 0x8]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _0802303A\n\ + ldr r0, [r4]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _0802303A\n\ + ldr r6, _08022FFC @ =gActiveBank\n\ + movs r0, 0x2\n\ + strb r0, [r6]\n\ + ldr r0, _08023000 @ =gBattleBufferB\n\ + ldrb r1, [r0, 0x1]\n\ + movs r0, 0x2\n\ + movs r2, 0x6\n\ + bl sub_8018018\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08023008\n\ + ldr r2, _08023004 @ =gAbsentBankFlags\n\ + ldrb r0, [r6]\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldrb r0, [r6]\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + ldr r0, [r7]\n\ + bics r0, r1\n\ + str r0, [r7]\n\ + movs r0, 0\n\ + bl Emitcmd42\n\ + ldrb r0, [r6]\n\ + bl MarkBufferBankForExecution\n\ + b _0802303A\n\ + .align 2, 0\n\ +_08022FF0: .4byte gBattleTypeFlags\n\ +_08022FF4: .4byte gHitMarker\n\ +_08022FF8: .4byte gBitTable\n\ +_08022FFC: .4byte gActiveBank\n\ +_08023000: .4byte gBattleBufferB\n\ +_08023004: .4byte gAbsentBankFlags\n\ +_08023008:\n\ + ldr r4, _08023098 @ =gSpecialStatuses\n\ + ldrb r0, [r6]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r4\n\ + ldrb r0, [r1]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _0802303A\n\ + ldr r0, _0802309C @ =0x02000000\n\ + ldr r1, _080230A0 @ =0x00016068\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + bl sub_8022A3C\n\ + ldrb r1, [r6]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldrb r1, [r0]\n\ + movs r2, 0x40\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ +_0802303A:\n\ + ldr r4, _080230A4 @ =gBitTable\n\ + ldr r0, [r4, 0xC]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _080230EE\n\ + ldr r0, [r4, 0x4]\n\ + ands r5, r0\n\ + cmp r5, 0\n\ + beq _080230EE\n\ + ldr r5, _080230A8 @ =gActiveBank\n\ + movs r0, 0x3\n\ + strb r0, [r5]\n\ + ldr r0, _080230AC @ =gBattleBufferB\n\ + ldr r2, _080230B0 @ =0x00000201\n\ + adds r0, r2\n\ + ldrb r1, [r0]\n\ + movs r0, 0x3\n\ + movs r2, 0x6\n\ + bl sub_8018018\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080230BC\n\ + ldr r2, _080230B4 @ =gAbsentBankFlags\n\ + ldrb r0, [r5]\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldr r0, [r0]\n\ + ldrb r1, [r2]\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r2, _080230B8 @ =gHitMarker\n\ + ldrb r0, [r5]\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + ldr r0, [r2]\n\ + bics r0, r1\n\ + str r0, [r2]\n\ + movs r0, 0\n\ + bl Emitcmd42\n\ + ldrb r0, [r5]\n\ + bl MarkBufferBankForExecution\n\ + b _080230EE\n\ + .align 2, 0\n\ +_08023098: .4byte gSpecialStatuses\n\ +_0802309C: .4byte 0x02000000\n\ +_080230A0: .4byte 0x00016068\n\ +_080230A4: .4byte gBitTable\n\ +_080230A8: .4byte gActiveBank\n\ +_080230AC: .4byte gBattleBufferB\n\ +_080230B0: .4byte 0x00000201\n\ +_080230B4: .4byte gAbsentBankFlags\n\ +_080230B8: .4byte gHitMarker\n\ +_080230BC:\n\ + ldr r4, _080230FC @ =gSpecialStatuses\n\ + ldrb r0, [r5]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r4\n\ + ldrb r0, [r1]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + blt _080230EE\n\ + ldr r0, _08023100 @ =0x02000000\n\ + ldr r1, _08023104 @ =0x00016069\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + bl sub_8022A3C\n\ + ldrb r1, [r5]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldrb r1, [r0]\n\ + movs r2, 0x40\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ +_080230EE:\n\ + ldr r1, _08023108 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x6\n\ + str r0, [r1]\n\ + mov r12, r1\n\ + b _08023110\n\ + .align 2, 0\n\ +_080230FC: .4byte gSpecialStatuses\n\ +_08023100: .4byte 0x02000000\n\ +_08023104: .4byte 0x00016069\n\ +_08023108: .4byte gBattlescriptCurrInstr\n\ +_0802310C:\n\ + adds r0, r1, 0x6\n\ + str r0, [r6]\n\ +_08023110:\n\ + ldr r0, _08023160 @ =gHitMarker\n\ + ldr r0, [r0]\n\ + lsrs r5, r0, 28\n\ + ldr r1, _08023164 @ =gBank1\n\ + movs r0, 0\n\ + strb r0, [r1]\n\ + ldr r4, _08023168 @ =gBitTable\n\ + ldr r2, [r4]\n\ + ands r2, r5\n\ + ldr r6, _0802316C @ =gNoOfAllBanks\n\ + cmp r2, 0\n\ + bne _0802314C\n\ + adds r7, r6, 0\n\ + ldrb r0, [r6]\n\ + cmp r2, r0\n\ + bcs _0802314C\n\ + adds r3, r1, 0\n\ +_08023132:\n\ + ldrb r0, [r3]\n\ + adds r0, 0x1\n\ + strb r0, [r3]\n\ + ldrb r2, [r3]\n\ + lsls r0, r2, 2\n\ + adds r0, r4\n\ + ldr r0, [r0]\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + bne _0802314C\n\ + ldrb r0, [r7]\n\ + cmp r2, r0\n\ + bcc _08023132\n\ +_0802314C:\n\ + ldrb r0, [r1]\n\ + ldrb r6, [r6]\n\ + cmp r0, r6\n\ + beq _08023156\n\ + b _08023302\n\ +_08023156:\n\ + mov r1, r8\n\ + mov r2, r12\n\ + str r1, [r2]\n\ + b _08023302\n\ + .align 2, 0\n\ +_08023160: .4byte gHitMarker\n\ +_08023164: .4byte gBank1\n\ +_08023168: .4byte gBitTable\n\ +_0802316C: .4byte gNoOfAllBanks\n\ +_08023170:\n\ + movs r0, 0x80\n\ + ands r0, r2\n\ + movs r5, 0x1\n\ + cmp r0, 0\n\ + beq _0802317C\n\ + movs r5, 0\n\ +_0802317C:\n\ + movs r0, 0x7F\n\ + ands r0, r2\n\ + bl GetBattleBank\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ + ldr r1, _080231A4 @ =gSpecialStatuses\n\ + lsls r0, r7, 2\n\ + adds r0, r7\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + lsls r0, 25\n\ + cmp r0, 0\n\ + bge _080231A8\n\ + ldr r0, [r6]\n\ + adds r0, 0x6\n\ + str r0, [r6]\n\ + b _08023302\n\ + .align 2, 0\n\ +_080231A4: .4byte gSpecialStatuses\n\ +_080231A8:\n\ + adds r0, r7, 0\n\ + movs r1, 0x6\n\ + movs r2, 0x6\n\ + bl sub_8018018\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080231F8\n\ + ldr r2, _080231E8 @ =gActiveBank\n\ + strb r7, [r2]\n\ + ldr r3, _080231EC @ =gAbsentBankFlags\n\ + ldr r4, _080231F0 @ =gBitTable\n\ + ldrb r0, [r2]\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldr r0, [r0]\n\ + ldrb r1, [r3]\n\ + orrs r0, r1\n\ + strb r0, [r3]\n\ + ldr r3, _080231F4 @ =gHitMarker\n\ + ldrb r0, [r2]\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldr r1, [r0]\n\ + lsls r1, 28\n\ + ldr r0, [r3]\n\ + bics r0, r1\n\ + str r0, [r3]\n\ + mov r0, r8\n\ + str r0, [r6]\n\ + b _08023302\n\ + .align 2, 0\n\ +_080231E8: .4byte gActiveBank\n\ +_080231EC: .4byte gAbsentBankFlags\n\ +_080231F0: .4byte gBitTable\n\ +_080231F4: .4byte gHitMarker\n\ +_080231F8:\n\ + ldr r4, _080232A0 @ =gActiveBank\n\ + strb r7, [r4]\n\ + ldr r3, _080232A4 @ =0x02000000\n\ + ldrb r0, [r4]\n\ + ldr r2, _080232A8 @ =0x00016064\n\ + adds r1, r0, r2\n\ + adds r1, r3\n\ + ldr r2, _080232AC @ =gBattlePartyID\n\ + lsls r0, 1\n\ + adds r0, r2\n\ + ldrh r0, [r0]\n\ + strb r0, [r1]\n\ + ldrb r1, [r4]\n\ + movs r0, 0x2\n\ + eors r0, r1\n\ + ldr r1, _080232B0 @ =0x00016068\n\ + adds r0, r1\n\ + adds r0, r3\n\ + ldrb r2, [r0]\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + ldr r1, _080232B4 @ =0x0001606c\n\ + adds r3, r1\n\ + adds r0, r3\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + adds r1, r5, 0\n\ + movs r3, 0\n\ + bl EmitChoosePokemon\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ + ldr r0, [r6]\n\ + adds r0, 0x6\n\ + str r0, [r6]\n\ + ldrb r0, [r4]\n\ + bl GetBankIdentity\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _0802325A\n\ + ldr r1, _080232B8 @ =gBattleResults\n\ + ldrb r0, [r1, 0x2]\n\ + cmp r0, 0xFE\n\ + bhi _0802325A\n\ + adds r0, 0x1\n\ + strb r0, [r1, 0x2]\n\ +_0802325A:\n\ + ldr r0, _080232BC @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x40\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080232C4\n\ + ldr r1, _080232A0 @ =gActiveBank\n\ + movs r0, 0\n\ + strb r0, [r1]\n\ + ldr r0, _080232C0 @ =gNoOfAllBanks\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _08023302\n\ + adds r4, r1, 0\n\ +_08023276:\n\ + ldrb r0, [r4]\n\ + cmp r0, r7\n\ + beq _0802328A\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ +_0802328A:\n\ + ldrb r0, [r4]\n\ + adds r0, 0x1\n\ + strb r0, [r4]\n\ + ldr r1, _080232C0 @ =gNoOfAllBanks\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + ldrb r1, [r1]\n\ + cmp r0, r1\n\ + bcc _08023276\n\ + b _08023302\n\ + .align 2, 0\n\ +_080232A0: .4byte gActiveBank\n\ +_080232A4: .4byte 0x02000000\n\ +_080232A8: .4byte 0x00016064\n\ +_080232AC: .4byte gBattlePartyID\n\ +_080232B0: .4byte 0x00016068\n\ +_080232B4: .4byte 0x0001606c\n\ +_080232B8: .4byte gBattleResults\n\ +_080232BC: .4byte gBattleTypeFlags\n\ +_080232C0: .4byte gNoOfAllBanks\n\ +_080232C4:\n\ + adds r0, r7, 0\n\ + bl GetBankIdentity\n\ + movs r1, 0x1\n\ + eors r0, r1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + bl GetBankByPlayerAI\n\ + ldr r4, _08023310 @ =gActiveBank\n\ + strb r0, [r4]\n\ + ldr r0, _08023314 @ =gAbsentBankFlags\n\ + ldrb r1, [r0]\n\ + ldr r2, _08023318 @ =gBitTable\n\ + ldrb r3, [r4]\n\ + lsls r0, r3, 2\n\ + adds r0, r2\n\ + ldr r0, [r0]\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + beq _080232F4\n\ + movs r0, 0x2\n\ + eors r3, r0\n\ + strb r3, [r4]\n\ +_080232F4:\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl EmitLinkStandbyMsg\n\ + ldrb r0, [r4]\n\ + bl MarkBufferBankForExecution\n\ +_08023302:\n\ + add sp, 0x4\n\ + pop {r3,r4}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08023310: .4byte gActiveBank\n\ +_08023314: .4byte gAbsentBankFlags\n\ +_08023318: .4byte gBitTable\n\ + .syntax divided"); +} + +static void atk51_switch_handle_order(void) +{ + int i; + if (gBattleExecBuffer) + return; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + switch (BSScriptRead8(gBattlescriptCurrInstr + 2)) + { + case 0: + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gBattleBufferB[i][0] == 0x22) + ewram[i + 0x16068] = gBattleBufferB[i][1]; + } + break; + case 1: + if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + sub_8012258(gActiveBank); + break; + case 2: + gBattleCommunication[0] = gBattleBufferB[gActiveBank][1]; + ewram[gActiveBank + 0x16068] = gBattleBufferB[gActiveBank][1]; + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + + ewram[(gActiveBank) * 3 + (0x1606C + 0)] &= 0xF; + ewram[(gActiveBank) * 3 + (0x1606C + 0)] |= (gBattleBufferB[gActiveBank][2] & 0xF0); + ewram[(gActiveBank) * 3 + (0x1606C + 1)] = gBattleBufferB[gActiveBank][3]; + + ewram[(gActiveBank ^ 2) * 3 + (0x1606C + 0)] &= (0xF0); + ewram[(gActiveBank ^ 2) * 3 + (0x1606C + 0)] |= (gBattleBufferB[gActiveBank][2] & 0xF0) >> 4; + ewram[(gActiveBank ^ 2) * 3 + (0x1606C + 2)] = gBattleBufferB[gActiveBank][3]; + } + else + sub_8012258(gActiveBank); + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 6; + gBattleTextBuff1[2] = gBattleMons[gBankAttacker].species; + gBattleTextBuff1[3] = gBattleMons[gBankAttacker].species >> 8; + gBattleTextBuff1[4] = 0xFF; + + gBattleTextBuff2[0] = 0xFD; + gBattleTextBuff2[1] = 7; + gBattleTextBuff2[2] = gActiveBank; + gBattleTextBuff2[3] = gBattleBufferB[gActiveBank][1]; + gBattleTextBuff2[4] = 0xFF; + break; + } + gBattlescriptCurrInstr += 3; +} + +static void atk52_switch_in_effects(void) +{ + int i; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + sub_80157C4(gActiveBank); + gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank)); + gSpecialStatuses[gActiveBank].flag40 = 0; + + if (!(gSideAffecting[GetBankSide(gActiveBank)] & SIDE_STATUS_SPIKES_DAMAGED) && (gSideAffecting[GetBankSide(gActiveBank)] & SIDE_STATUS_SPIKES) + && gBattleMons[gActiveBank].type1 != TYPE_FLYING && gBattleMons[gActiveBank].type2 != TYPE_FLYING && gBattleMons[gActiveBank].ability != ABILITY_LEVITATE) + { + u8 spikesDmg; + + gSideAffecting[GetBankSide(gActiveBank)] |= SIDE_STATUS_SPIKES_DAMAGED; + + spikesDmg = (5 - gSideTimer[GetBankSide(gActiveBank)].spikesAmount) * 2; + gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / (spikesDmg); + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + + BATTLE_STRUCT->scriptingActive = gActiveBank; + b_movescr_stack_push_cursor(); + + if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 0) + gBattlescriptCurrInstr = gUnknown_081D919F; + else if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 1) + gBattlescriptCurrInstr = gUnknown_081D9171; + else + gBattlescriptCurrInstr = gUnknown_081D91CD; + } + else + { + if (gBattleMons[gActiveBank].ability == ABILITY_TRUANT) + { + gDisableStructs[gActiveBank].truantCounter = 1; + } + + if (AbilityBattleEffects(0, gActiveBank, 0, 0, 0) == 0 && ItemBattleEffects(0, gActiveBank, 0) == 0) + { + gSideAffecting[GetBankSide(gActiveBank)] &= ~(SIDE_STATUS_SPIKES_DAMAGED); + + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gTurnOrder[i] == gActiveBank) + gUnknown_02024A76[i] = 0xC; + } + + for (i = 0; i < gNoOfAllBanks; i++) + { + *(HP_ON_SWITCHOUT + GetBankSide(i)) = gBattleMons[i].hp; + } + + if (BSScriptRead8(gBattlescriptCurrInstr + 1) == 5) + { + u32 hitmark = gHitMarker >> 0x1C; + gBank1++; + while (1) + { + if (hitmark & gBitTable[gBank1] && !(gAbsentBankFlags & gBitTable[gBank1])) + break; + if (gBank1 >= gNoOfAllBanks) + break; + gBank1++; + } + } + gBattlescriptCurrInstr += 2; + } + } +} + +static void atk53_trainer_slide(void) +{ + if (!BSScriptRead8(gBattlescriptCurrInstr + 1)) + gActiveBank = GetBankByPlayerAI(0); + else + gActiveBank = GetBankByPlayerAI(1); + + EmitTrainerSlide(0); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +static void atk54_effectiveness_sound(void) +{ + gActiveBank = gBankAttacker; + EmitEffectivenessSound(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1)); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 3; +} + +static void atk55_play_sound(void) +{ + gActiveBank = gBankAttacker; + Emitcmd44(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1)); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 3; +} + +static void atk56_fainting_cry(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + EmitFaintingCry(0); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +static void atk57(void) +{ + gActiveBank = GetBankByPlayerAI(0); + Emitcmd55(0, gBattleOutcome); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 1; +} + +static void atk58_return_to_ball(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + EmitReturnPokeToBall(0, 1); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +void atk59_learnmove_inbattle(void) +{ + u8* loc1 = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* loc2 = BSScriptReadPtr(gBattlescriptCurrInstr + 5); + + u16 ret = MonTryLearningNewMove(&gPlayerParty[BATTLE_STRUCT->expGetterID], BSScriptRead8(gBattlescriptCurrInstr + 9)); + while (ret == 0xFFFE) + ret = MonTryLearningNewMove(&gPlayerParty[BATTLE_STRUCT->expGetterID], 0); + + if (ret == 0) + { + gBattlescriptCurrInstr = loc2; + } + else if (ret == 0xFFFF) + { + gBattlescriptCurrInstr += 10; + } + else + { + gActiveBank = GetBankByPlayerAI(0); + if (gBattlePartyID[gActiveBank] == BATTLE_STRUCT->expGetterID && !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED)) + GiveMoveToBattleMon(&gBattleMons[gActiveBank], ret); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) //what is else if + { + gActiveBank = GetBankByPlayerAI(2); + if (gBattlePartyID[gActiveBank] == BATTLE_STRUCT->expGetterID && !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED)) + GiveMoveToBattleMon(&gBattleMons[gActiveBank], ret); + } + gBattlescriptCurrInstr = loc1; + } +} + +void sub_8023A80(void) +{ + sub_802BBD4(0x18, 8, 0x1D, 0xD, 0); + InitWindow(&gUnknown_03004210, gUnknown_08400D7A, 0x100, 0x19, 0x9); + sub_8002F44(&gUnknown_03004210); + sub_814A5C0(0, 0xFFFF, 0xC, 0x2D9F, 0x20); +} + +void sub_8023AD8(void) +{ + sub_802BBD4(0x18, 8, 0x1D, 0xD, 1); + DestroyMenuCursor(); +} + +static void atk5A(void) +{ + gActiveBank = 0; + switch (BATTLE_STRUCT->atk5A_StateTracker) + { + case 0: + sub_8023A80(); + BATTLE_STRUCT->atk5A_StateTracker++; + gBattleCommunication[1] = 0; + sub_802BC6C(); + break; + case 1: + if (gMain.newKeys & DPAD_UP && gBattleCommunication[1] != 0) + { + PlaySE(SE_SELECT); + nullsub_6(); + gBattleCommunication[1] = 0; + sub_802BC6C(); + } + if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[1] == 0) + { + PlaySE(SE_SELECT); + nullsub_6(); + gBattleCommunication[1] = 1; + sub_802BC6C(); + } + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if (gBattleCommunication[1] == 0) + { + sub_8023AD8(); + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + BATTLE_STRUCT->atk5A_StateTracker++; + return; + } + goto state_tracker_4; + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + state_tracker_4: + BATTLE_STRUCT->atk5A_StateTracker = 4; + } + break; + case 2: + if (!gPaletteFade.active) + { + sub_809D9F0(gPlayerParty, BATTLE_STRUCT->expGetterID, gPlayerPartyCount - 1, ReshowBattleScreenAfterMenu, gMoveToLearn); + BATTLE_STRUCT->atk5A_StateTracker++; + } + break; + case 3: + if (!gPaletteFade.active && gMain.callback2 == sub_800F808) + { + u8 move_pos = sub_809FA30(); + if (move_pos == 4) + { + BATTLE_STRUCT->atk5A_StateTracker = 4; + } + else + { + u16 move = GetMonData(&gPlayerParty[BATTLE_STRUCT->expGetterID], MON_DATA_MOVE1 + move_pos); + if (IsHMMove2(move)) + { + PrepareStringBattle(0x13F, gActiveBank); + BATTLE_STRUCT->atk5A_StateTracker = 5; + } + else + { + u8 *ptr; + + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + ptr = gBattleTextBuff2; + { + ptr[0] = 0xFD; + ptr[1] = 2; + ptr[2] = move; + ptr[3] = ((move & 0xFF00) >> 8); + ptr += 4; + } + ptr[0] = 0xFF; + RemoveMonPPBonus(&gPlayerParty[BATTLE_STRUCT->expGetterID], move_pos); + SetMonMoveSlot(&gPlayerParty[BATTLE_STRUCT->expGetterID], gMoveToLearn, move_pos); + if (gBattlePartyID[0] == BATTLE_STRUCT->expGetterID && !(gBattleMons[0].status2 & STATUS2_TRANSFORMED) + && !(gDisableStructs[0].unk18_b & gBitTable[move_pos])) + { + RemoveBattleMonPPBonus(&gBattleMons[0], move_pos); + SetBattleMonMoveSlot(&gBattleMons[0], gMoveToLearn, move_pos); + } + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattlePartyID[2] == BATTLE_STRUCT->expGetterID && !(gBattleMons[2].status2 & STATUS2_TRANSFORMED) + && !(gDisableStructs[2].unk18_b & gBitTable[move_pos])) + { + RemoveBattleMonPPBonus(&gBattleMons[2], move_pos); + SetBattleMonMoveSlot(&gBattleMons[2], gMoveToLearn, move_pos); + } + } + } + } + break; + case 4: + sub_8023AD8(); + gBattlescriptCurrInstr += 5; + break; + case 5: + if (gBattleExecBuffer == 0) + { + BATTLE_STRUCT->atk5A_StateTracker = 2; + } + break; + } +} + +static void atk5B_80256E0(void) +{ + switch (BATTLE_STRUCT->atk5A_StateTracker) + { + case 0: + sub_8023A80(); + BATTLE_STRUCT->atk5A_StateTracker++; + gBattleCommunication[1] = 0; + sub_802BC6C(); + break; + case 1: + if (gMain.newKeys & DPAD_UP && gBattleCommunication[1] != 0) + { + PlaySE(SE_SELECT); + nullsub_6(); + gBattleCommunication[1] = 0; + sub_802BC6C(); + } + if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[1] == 0) + { + PlaySE(SE_SELECT); + nullsub_6(); + gBattleCommunication[1] = 1; + sub_802BC6C(); + } + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if (gBattleCommunication[1] != 0) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + gBattlescriptCurrInstr += 5; + sub_8023AD8(); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + sub_8023AD8(); + } + } +} + +static void atk5C_hitanimation(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (gBattleMoveFlags & MOVESTATUS_NOEFFECT) + gBattlescriptCurrInstr += 2; + else if (!(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE) || !(gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE) || gDisableStructs[gActiveBank].substituteHP == 0) + { + EmitHitAnimation(0); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; + } + else + gBattlescriptCurrInstr += 2; +} + +#define MONEY_UNKNOWN ((*(u8*)(0x02017000 + 0x94))) + +#ifdef NONMATCHING +static void atk5D_getmoneyreward(void) +{ + int i = 0; + u8 r5 = 0; + u32 money_to_give; + if (gTrainerBattleOpponent == 0x400) + { + money_to_give = 2 * BATTLE_STRUCT->moneyMultiplier * MONEY_UNKNOWN; + } + else + { + switch(gTrainers[gTrainerBattleOpponent].partyFlags) + { + case 0: + { + const struct PokeTrainerData1 *data = &gTrainers[gTrainerBattleOpponent].party->noItemNoMoves; + r5 = data[gTrainers[gTrainerBattleOpponent].partySize - 1].lvl; + } + break; + case 2: + { + const struct PokeTrainerData2 *data = &gTrainers[gTrainerBattleOpponent].party->itemNoMoves; + r5 = data[gTrainers[gTrainerBattleOpponent].partySize - 1].lvl; + } + break; + case 1: + case 3: + { + const struct PokeTrainerData3 *data = &gTrainers[gTrainerBattleOpponent].party->itemMoves; + r5 = data[gTrainers[gTrainerBattleOpponent].partySize - 1].lvl; + } + break; + } + for (; gTrainerMoney[i * 4] != 0xFF && gTrainerMoney[i * 4 + 1] != gTrainers[gTrainerBattleOpponent].trainerClass ; i++) {} + + money_to_give = (r5 << 2) * BATTLE_STRUCT->moneyMultiplier; + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + money_to_give = 2 * gTrainerMoney[i * 4 + 1] * money_to_give; + else + money_to_give = 1 * gTrainerMoney[i * 4 + 1] * money_to_give; + } + + AddMoney(&gSaveBlock1.money, money_to_give); + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 1; + gBattleTextBuff1[2] = 4; + gBattleTextBuff1[3] = 5; + gBattleTextBuff1[4] = BYTE0(money_to_give); + gBattleTextBuff1[5] = BYTE1(money_to_give); + gBattleTextBuff1[6] = BYTE2(money_to_give); + gBattleTextBuff1[7] = BYTE3(money_to_give); + gBattleTextBuff1[8] = 0xFF; + + gBattlescriptCurrInstr += 1; +} +#else +__attribute__((naked)) +static void atk5D_getmoneyreward(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + movs r6, 0\n\ + movs r5, 0\n\ + ldr r0, _08024048 @ =gTrainerBattleOpponent\n\ + ldrh r2, [r0]\n\ + movs r1, 0x80\n\ + lsls r1, 3\n\ + cmp r2, r1\n\ + bne _08024058\n\ + ldr r0, _0802404C @ =0x02017000\n\ + adds r1, r0, 0\n\ + adds r1, 0x94\n\ + ldrb r2, [r1]\n\ + ldr r1, _08024050 @ =0xfffff056\n\ + adds r0, r1\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r4, r2, 0\n\ + muls r4, r0\n\ + ldr r0, _08024054 @ =gSaveBlock1 + 0x490\n\ + mov r8, r0\n\ + b _08024140\n\ + .align 2, 0\n\ +_08024048: .4byte gTrainerBattleOpponent\n\ +_0802404C: .4byte 0x02017000\n\ +_08024050: .4byte 0xfffff056\n\ +_08024054: .4byte gSaveBlock1 + 0x490\n\ +_08024058:\n\ + ldr r2, _08024074 @ =gTrainers\n\ + ldrh r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r3, r0, 3\n\ + adds r4, r3, r2\n\ + ldrb r1, [r4]\n\ + cmp r1, 0x1\n\ + beq _080240AE\n\ + cmp r1, 0x1\n\ + bgt _08024078\n\ + cmp r1, 0\n\ + beq _08024082\n\ + b _080240C4\n\ + .align 2, 0\n\ +_08024074: .4byte gTrainers\n\ +_08024078:\n\ + cmp r1, 0x2\n\ + beq _08024098\n\ + cmp r1, 0x3\n\ + beq _080240AE\n\ + b _080240C4\n\ +_08024082:\n\ + adds r0, r2, 0\n\ + adds r0, 0x24\n\ + adds r0, r3, r0\n\ + ldr r1, [r0]\n\ + adds r0, r4, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + subs r0, 0x8\n\ + b _080240C2\n\ +_08024098:\n\ + adds r0, r2, 0\n\ + adds r0, 0x24\n\ + adds r0, r3, r0\n\ + ldr r1, [r0]\n\ + adds r0, r4, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + subs r0, 0x8\n\ + b _080240C2\n\ +_080240AE:\n\ + adds r0, r2, 0\n\ + adds r0, 0x24\n\ + adds r0, r3, r0\n\ + ldr r1, [r0]\n\ + adds r0, r4, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + lsls r0, 4\n\ + adds r0, r1\n\ + subs r0, 0x10\n\ +_080240C2:\n\ + ldrb r5, [r0, 0x2]\n\ +_080240C4:\n\ + ldr r0, _08024120 @ =gTrainerMoney\n\ + lsls r1, r6, 2\n\ + adds r3, r1, r0\n\ + ldrb r1, [r3]\n\ + mov r12, r0\n\ + lsls r4, r5, 2\n\ + ldr r5, _08024124 @ =0x02000000\n\ + ldr r7, _08024128 @ =gBattleTypeFlags\n\ + ldr r0, _0802412C @ =gSaveBlock1 + 0x490\n\ + mov r8, r0\n\ + cmp r1, 0xFF\n\ + beq _080240FE\n\ + ldr r2, _08024130 @ =gTrainers\n\ + ldr r0, _08024134 @ =gTrainerBattleOpponent\n\ + ldrh r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 3\n\ + adds r0, r2\n\ + ldrb r2, [r0, 0x1]\n\ + adds r1, r3, 0\n\ +_080240EE:\n\ + ldrb r0, [r1]\n\ + cmp r0, r2\n\ + beq _080240FE\n\ + adds r1, 0x4\n\ + adds r6, 0x1\n\ + ldrb r0, [r1]\n\ + cmp r0, 0xFF\n\ + bne _080240EE\n\ +_080240FE:\n\ + ldr r1, _08024138 @ =0x00016056\n\ + adds r0, r5, r1\n\ + ldrb r0, [r0]\n\ + adds r3, r4, 0\n\ + muls r3, r0\n\ + lsls r0, r6, 2\n\ + add r0, r12\n\ + ldrb r2, [r0, 0x1]\n\ + ldrh r1, [r7]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0802413C\n\ + lsls r0, r2, 1\n\ + adds r4, r3, 0\n\ + muls r4, r0\n\ + b _08024140\n\ + .align 2, 0\n\ +_08024120: .4byte gTrainerMoney\n\ +_08024124: .4byte 0x02000000\n\ +_08024128: .4byte gBattleTypeFlags\n\ +_0802412C: .4byte gSaveBlock1 + 0x490\n\ +_08024130: .4byte gTrainers\n\ +_08024134: .4byte gTrainerBattleOpponent\n\ +_08024138: .4byte 0x00016056\n\ +_0802413C:\n\ + adds r4, r3, 0\n\ + muls r4, r2\n\ +_08024140:\n\ + mov r0, r8\n\ + adds r1, r4, 0\n\ + bl AddMoney\n\ + ldr r1, _0802418C @ =gBattleTextBuff1\n\ + movs r0, 0xFD\n\ + strb r0, [r1]\n\ + movs r0, 0x1\n\ + strb r0, [r1, 0x1]\n\ + movs r0, 0x4\n\ + strb r0, [r1, 0x2]\n\ + movs r0, 0x5\n\ + strb r0, [r1, 0x3]\n\ + strb r4, [r1, 0x4]\n\ + movs r0, 0xFF\n\ + lsls r0, 8\n\ + ands r0, r4\n\ + lsrs r0, 8\n\ + strb r0, [r1, 0x5]\n\ + movs r0, 0xFF\n\ + lsls r0, 16\n\ + ands r0, r4\n\ + lsrs r0, 16\n\ + strb r0, [r1, 0x6]\n\ + lsrs r0, r4, 24\n\ + strb r0, [r1, 0x7]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x8]\n\ + ldr r1, _08024190 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x1\n\ + str r0, [r1]\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0802418C: .4byte gBattleTextBuff1\n\ +_08024190: .4byte gBattlescriptCurrInstr\n\ + .syntax divided"); +} +#endif //NONMATCHING + +static void atk5E_8025A70(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + switch (gBattleCommunication[0]) + { + case 0: + EmitGetAttributes(0, REQUEST_ALL_BATTLE, 0); + MarkBufferBankForExecution(gActiveBank); + gBattleCommunication[0]++; + break; + case 1: + if (gBattleExecBuffer == 0) + { + int i; + struct BattlePokemon* bufferPoke = (struct BattlePokemon*) &gBattleBufferB[gActiveBank][4]; + for (i = 0; i < 4; i++) + { + gBattleMons[gActiveBank].moves[i] = bufferPoke->moves[i]; + gBattleMons[gActiveBank].pp[i] = bufferPoke->pp[i]; + } + gBattlescriptCurrInstr += 2; + } + break; + } +} + +static void atk5F_8025B24(void) +{ + gActiveBank = gBankAttacker; + gBankAttacker = gBankTarget; + gBankTarget = gActiveBank; + //what is xor... + if (gHitMarker & HITMARKER_PURSUIT_TRAP) + gHitMarker &= ~(HITMARKER_PURSUIT_TRAP); + else + gHitMarker |= HITMARKER_PURSUIT_TRAP; + gBattlescriptCurrInstr++; +} + +static void atk60_increment_gamestat(void) +{ + if (GetBankSide(gBankAttacker) == 0) + { + IncrementGameStat(BSScriptRead8(gBattlescriptCurrInstr + 1)); + } + gBattlescriptCurrInstr += 2; +} + +struct hp_status +{ + u16 hp; + u32 status; +}; + +static void atk61_8025BA4(void) +{ + int i; + struct Pokemon* party; + struct hp_status hpStatus[6]; + if (gBattleExecBuffer) + return; + + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (GetBankSide(gActiveBank) == 0) + party = gPlayerParty; + else + party = gEnemyParty; + + for (i = 0; i < 6; i++) + { + if (GetMonData(&party[i], MON_DATA_SPECIES2) == 0 || GetMonData(&party[i], MON_DATA_SPECIES2) == SPECIES_EGG) + { + hpStatus[i].hp = 0xFFFF; + hpStatus[i].status = 0; + } + else + { + hpStatus[i].hp = GetMonData(&party[i], MON_DATA_HP); + hpStatus[i].status = GetMonData(&party[i], MON_DATA_STATUS); + } + } + Emitcmd48(0, (u8*)(hpStatus), 1); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +static void atk62_08025C6C(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + Emitcmd49(0); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +static void atk63_jumptorandomattack(void) +{ + if (BSScriptRead8(gBattlescriptCurrInstr + 1)) + gCurrentMove = gRandomMove; + else + gUnknown_02024BE8 = gCurrentMove = gRandomMove; + gBattlescriptCurrInstr = gBattleScriptsEffectsTable[gBattleMoves[gCurrentMove].effect]; +} + +static void atk64_statusanimation(void) +{ + if (gBattleExecBuffer == 0) + { + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE) && gDisableStructs[gActiveBank].substituteHP == 0 && !(gHitMarker & HITMARKER_NO_ANIMATIONS)) + { + EmitStatusAnimation(0, 0, gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + } + gBattlescriptCurrInstr += 2; + } +} + +static void atk65_status2animation(void) +{ + if (gBattleExecBuffer == 0) + { + u32 possible_to_anim; + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + possible_to_anim = BSScriptRead32(gBattlescriptCurrInstr + 2); + if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE) && gDisableStructs[gActiveBank].substituteHP == 0 && !(gHitMarker & HITMARKER_NO_ANIMATIONS)) + { + EmitStatusAnimation(0, 1, gBattleMons[gActiveBank].status2 & possible_to_anim); + MarkBufferBankForExecution(gActiveBank); + } + gBattlescriptCurrInstr += 6; + } +} + +static void atk66_chosenstatusanimation(void) +{ + if (gBattleExecBuffer == 0) + { + u32 status; + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + status = BSScriptRead32(gBattlescriptCurrInstr + 3); + if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE) && gDisableStructs[gActiveBank].substituteHP == 0 && !(gHitMarker & HITMARKER_NO_ANIMATIONS)) + { + EmitStatusAnimation(0, BSScriptRead8(gBattlescriptCurrInstr + 2), status); + MarkBufferBankForExecution(gActiveBank); + } + gBattlescriptCurrInstr += 7; + } +} + +static void atk67_8025ECC(void) +{ + switch (gBattleCommunication[0]) + { + case 0: + sub_8023A80(); + gBattleCommunication[0]++; + gBattleCommunication[1] = 0; + sub_802BC6C(); + break; + case 1: + if (gMain.newKeys & DPAD_UP && gBattleCommunication[1] != 0) + { + PlaySE(SE_SELECT); + nullsub_6(); + gBattleCommunication[1] = 0; + sub_802BC6C(); + } + if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[1] == 0) + { + PlaySE(SE_SELECT); + nullsub_6(); + gBattleCommunication[1] = 1; + sub_802BC6C(); + } + if (gMain.newKeys & B_BUTTON) + { + gBattleCommunication[1] = 1; + PlaySE(SE_SELECT); + sub_8023AD8(); + gBattlescriptCurrInstr++; + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + sub_8023AD8(); + gBattlescriptCurrInstr++; + } + break; + } +} + +static void atk68_80246A0(void) +{ + int i; + for (i = 0; i < gNoOfAllBanks; i++) + { + gUnknown_02024A76[i] = 0xC; + } + gBattlescriptCurrInstr++; +} + +static void atk69_dmg_adjustment2(void) //literally a copy of atk07 except theres no rand dmg modifier... +{ + u8 hold_effect, quality; + if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY) + hold_effect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam; + else + { + hold_effect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item); + quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item); + } + + gStringBank = gBankTarget; + + if (hold_effect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality) + { + RecordItemBattle(gBankTarget, hold_effect); + gSpecialStatuses[gBankTarget].focusBanded = 1; + } + if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE) + goto END; + if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE && !gProtectStructs[gBankTarget].endured + && !gSpecialStatuses[gBankTarget].focusBanded) + goto END; + if (gBattleMons[gBankTarget].hp > gBattleMoveDamage) + goto END; + + gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1; + + if (gProtectStructs[gBankTarget].endured) + { + gBattleMoveFlags |= MOVESTATUS_ENDURED; + goto END; + } + if (gSpecialStatuses[gBankTarget].focusBanded) + { + gBattleMoveFlags |= MOVESTATUS_HUNGON; + gLastUsedItem = gBattleMons[gBankTarget].item; + } + + END: + gBattlescriptCurrInstr++; +} + +void atk6A_removeitem(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + #define USED_HELD_ITEMS(bank) (*(u16 *)&ewram[0x160CC + 2 * (bank)]) + USED_HELD_ITEMS(gActiveBank) = gBattleMons[gActiveBank].item; + + gBattleMons[gActiveBank].item = 0; + EmitSetAttributes(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gActiveBank].item); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +static void atk6B_atknameinbuff1(void) +{ + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 7; + gBattleTextBuff1[2] = gBankAttacker; + gBattleTextBuff1[3] = gBattlePartyID[gBankAttacker]; + gBattleTextBuff1[4] = 0xFF; + gBattlescriptCurrInstr++; +} + +#ifdef NONMATCHING +static void atk6C_lvlbox_display(void) +{ + u8 r1 = 0; + u8 r7 = 0; + switch (BATTLE_STRUCT->atk6C_statetracker) + { + case 0: + sub_802BBD4(0xB, 0, 0x1D, 0x7, r1); + StringCopy(gStringVar4, gUnknown_08400D9F); + + } +} + +#else +__attribute__((naked)) +static void atk6C_lvlbox_display(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x4\n\ + movs r1, 0\n\ + movs r7, 0\n\ + ldr r0, _08024928 @ =0x02000000\n\ + mov r10, r0\n\ + ldr r4, _0802492C @ =0x0001609c\n\ + add r4, r10\n\ + ldrb r0, [r4]\n\ + cmp r0, 0x1\n\ + bne _0802491C\n\ + b _08024AF4\n\ +_0802491C:\n\ + cmp r0, 0x1\n\ + bgt _08024930\n\ + cmp r0, 0\n\ + beq _0802493E\n\ + b _08024C38\n\ + .align 2, 0\n\ +_08024928: .4byte 0x02000000\n\ +_0802492C: .4byte 0x0001609c\n\ +_08024930:\n\ + cmp r0, 0x2\n\ + bne _08024936\n\ + b _08024C04\n\ +_08024936:\n\ + cmp r0, 0x3\n\ + bne _0802493C\n\ + b _08024C30\n\ +_0802493C:\n\ + b _08024C38\n\ +_0802493E:\n\ + str r1, [sp]\n\ + movs r0, 0xB\n\ + movs r1, 0\n\ + movs r2, 0x1D\n\ + movs r3, 0x7\n\ + bl sub_802BBD4\n\ + ldr r0, _0802499C @ =gStringVar4\n\ + ldr r1, _080249A0 @ =gUnknown_08400D9F\n\ + bl StringCopy\n\ + adds r5, r0, 0\n\ + movs r1, 0\n\ + mov r8, r1\n\ +_0802495A:\n\ + movs r2, 0\n\ + mov r9, r2\n\ + ldr r0, _080249A4 @ =gUnknown_0840165C\n\ + mov r1, r8\n\ + lsls r4, r1, 2\n\ + adds r0, r4, r0\n\ + ldr r1, [r0]\n\ + adds r0, r5, 0\n\ + bl StringAppend\n\ + adds r5, r0, 0\n\ + ldr r0, _080249A8 @ =0x02000000\n\ + ldr r2, _080249AC @ =0x00016018\n\ + adds r0, r2\n\ + ldrb r1, [r0]\n\ + movs r0, 0x64\n\ + muls r0, r1\n\ + ldr r1, _080249B0 @ =gPlayerParty\n\ + adds r0, r1\n\ + ldr r1, _080249B4 @ =gLevelUpStatBoxStats\n\ + add r1, r8\n\ + ldrb r1, [r1]\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r1, r0, 16\n\ + mov r0, r8\n\ + cmp r0, 0x5\n\ + bhi _08024A1A\n\ + ldr r0, _080249B8 @ =_080249BC\n\ + adds r0, r4, r0\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_0802499C: .4byte gStringVar4\n\ +_080249A0: .4byte gUnknown_08400D9F\n\ +_080249A4: .4byte gUnknown_0840165C\n\ +_080249A8: .4byte 0x02000000\n\ +_080249AC: .4byte 0x00016018\n\ +_080249B0: .4byte gPlayerParty\n\ +_080249B4: .4byte gLevelUpStatBoxStats\n\ +_080249B8: .4byte _080249BC\n\ + .align 2, 0\n\ +_080249BC:\n\ + .4byte _080249D4\n\ + .4byte _080249E0\n\ + .4byte _080249EC\n\ + .4byte _080249F8\n\ + .4byte _08024A04\n\ + .4byte _08024A10\n\ +_080249D4:\n\ + ldr r0, _080249DC @ =0x02017180\n\ + ldrh r0, [r0]\n\ + b _08024A14\n\ + .align 2, 0\n\ +_080249DC: .4byte 0x02017180\n\ +_080249E0:\n\ + ldr r0, _080249E8 @ =0x02017180\n\ + ldrh r0, [r0, 0x8]\n\ + b _08024A14\n\ + .align 2, 0\n\ +_080249E8: .4byte 0x02017180\n\ +_080249EC:\n\ + ldr r0, _080249F4 @ =0x02017180\n\ + ldrh r0, [r0, 0x2]\n\ + b _08024A14\n\ + .align 2, 0\n\ +_080249F4: .4byte 0x02017180\n\ +_080249F8:\n\ + ldr r0, _08024A00 @ =0x02017180\n\ + ldrh r0, [r0, 0xA]\n\ + b _08024A14\n\ + .align 2, 0\n\ +_08024A00: .4byte 0x02017180\n\ +_08024A04:\n\ + ldr r0, _08024A0C @ =0x02017180\n\ + ldrh r0, [r0, 0x4]\n\ + b _08024A14\n\ + .align 2, 0\n\ +_08024A0C: .4byte 0x02017180\n\ +_08024A10:\n\ + ldr r0, _08024A54 @ =0x02017180\n\ + ldrh r0, [r0, 0x6]\n\ +_08024A14:\n\ + subs r0, r1, r0\n\ + lsls r0, 16\n\ + lsrs r7, r0, 16\n\ +_08024A1A:\n\ + lsls r0, r7, 16\n\ + asrs r0, 16\n\ + cmp r0, 0\n\ + bge _08024A2C\n\ + negs r0, r0\n\ + lsls r0, 16\n\ + lsrs r7, r0, 16\n\ + movs r1, 0x1\n\ + add r9, r1\n\ +_08024A2C:\n\ + movs r0, 0xFC\n\ + strb r0, [r5]\n\ + movs r0, 0x13\n\ + strb r0, [r5, 0x1]\n\ + movs r1, 0x1\n\ + mov r2, r8\n\ + ands r1, r2\n\ + lsls r0, r1, 3\n\ + adds r0, r1\n\ + adds r0, 0x5\n\ + lsls r0, 3\n\ + adds r0, 0x6\n\ + strb r0, [r5, 0x2]\n\ + adds r5, 0x3\n\ + mov r0, r9\n\ + cmp r0, 0\n\ + beq _08024A5C\n\ + ldr r1, _08024A58 @ =gUnknown_08400DAC\n\ + b _08024A5E\n\ + .align 2, 0\n\ +_08024A54: .4byte 0x02017180\n\ +_08024A58: .4byte gUnknown_08400DAC\n\ +_08024A5C:\n\ + ldr r1, _08024AA4 @ =gUnknown_08400DAA\n\ +_08024A5E:\n\ + adds r0, r5, 0\n\ + bl StringCopy\n\ + adds r5, r0, 0\n\ + movs r6, 0xFC\n\ + strb r6, [r5]\n\ + movs r4, 0x14\n\ + strb r4, [r5, 0x1]\n\ + movs r0, 0x6\n\ + strb r0, [r5, 0x2]\n\ + adds r5, 0x3\n\ + lsls r1, r7, 16\n\ + asrs r1, 16\n\ + adds r0, r5, 0\n\ + movs r2, 0x1\n\ + movs r3, 0x2\n\ + bl ConvertIntToDecimalStringN\n\ + adds r5, r0, 0\n\ + strb r6, [r5]\n\ + strb r4, [r5, 0x1]\n\ + movs r0, 0\n\ + strb r0, [r5, 0x2]\n\ + adds r5, 0x3\n\ + movs r0, 0x1\n\ + mov r1, r8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08024AA8\n\ + movs r0, 0xFE\n\ + strb r0, [r5]\n\ + movs r0, 0xFF\n\ + strb r0, [r5, 0x1]\n\ + adds r5, 0x1\n\ + b _08024AB8\n\ + .align 2, 0\n\ +_08024AA4: .4byte gUnknown_08400DAA\n\ +_08024AA8:\n\ + strb r6, [r5]\n\ + movs r0, 0x11\n\ + strb r0, [r5, 0x1]\n\ + movs r0, 0x8\n\ + strb r0, [r5, 0x2]\n\ + adds r5, 0x3\n\ + movs r0, 0xFF\n\ + strb r0, [r5]\n\ +_08024AB8:\n\ + movs r2, 0x1\n\ + add r8, r2\n\ + mov r0, r8\n\ + cmp r0, 0x5\n\ + bgt _08024AC4\n\ + b _0802495A\n\ +_08024AC4:\n\ + ldr r4, _08024AE4 @ =gUnknown_03004210\n\ + ldr r1, _08024AE8 @ =gStringVar4\n\ + adds r2, 0xFF\n\ + movs r0, 0x1\n\ + str r0, [sp]\n\ + adds r0, r4, 0\n\ + movs r3, 0xC\n\ + bl InitWindow\n\ + adds r0, r4, 0\n\ + bl sub_8002F44\n\ + ldr r1, _08024AEC @ =0x02000000\n\ + ldr r2, _08024AF0 @ =0x0001609c\n\ + adds r1, r2\n\ + b _08024BEA\n\ + .align 2, 0\n\ +_08024AE4: .4byte gUnknown_03004210\n\ +_08024AE8: .4byte gStringVar4\n\ +_08024AEC: .4byte 0x02000000\n\ +_08024AF0: .4byte 0x0001609c\n\ +_08024AF4:\n\ + ldr r0, _08024B94 @ =gMain\n\ + ldrh r0, [r0, 0x2E]\n\ + cmp r0, 0\n\ + bne _08024AFE\n\ + b _08024C38\n\ +_08024AFE:\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + ldr r0, _08024B98 @ =gStringVar4\n\ + ldr r1, _08024B9C @ =gUnknown_08400D9F\n\ + bl StringCopy\n\ + adds r5, r0, 0\n\ + movs r0, 0\n\ + mov r8, r0\n\ + mov r9, r0\n\ + movs r6, 0xFC\n\ + movs r7, 0x14\n\ + ldr r1, _08024BA0 @ =0x00016018\n\ + add r10, r1\n\ +_08024B1C:\n\ + ldr r1, _08024BA4 @ =gUnknown_0840165C\n\ + mov r2, r8\n\ + lsls r0, r2, 2\n\ + adds r0, r1\n\ + ldr r1, [r0]\n\ + adds r0, r5, 0\n\ + bl StringAppend\n\ + adds r5, r0, 0\n\ + mov r0, r10\n\ + ldrb r1, [r0]\n\ + movs r0, 0x64\n\ + muls r0, r1\n\ + ldr r1, _08024BA8 @ =gPlayerParty\n\ + adds r0, r1\n\ + ldr r1, _08024BAC @ =gLevelUpStatBoxStats\n\ + add r1, r8\n\ + ldrb r1, [r1]\n\ + bl GetMonData\n\ + adds r1, r0, 0\n\ + strb r6, [r5]\n\ + movs r0, 0x13\n\ + strb r0, [r5, 0x1]\n\ + movs r4, 0x1\n\ + mov r2, r8\n\ + ands r4, r2\n\ + lsls r0, r4, 3\n\ + adds r0, r4\n\ + adds r0, 0x5\n\ + lsls r0, 3\n\ + adds r0, 0x6\n\ + strb r0, [r5, 0x2]\n\ + adds r5, 0x3\n\ + strb r6, [r5]\n\ + strb r7, [r5, 0x1]\n\ + movs r0, 0x6\n\ + strb r0, [r5, 0x2]\n\ + adds r5, 0x3\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + adds r0, r5, 0\n\ + movs r2, 0x1\n\ + movs r3, 0x3\n\ + bl ConvertIntToDecimalStringN\n\ + adds r5, r0, 0\n\ + strb r6, [r5]\n\ + strb r7, [r5, 0x1]\n\ + mov r0, r9\n\ + strb r0, [r5, 0x2]\n\ + adds r5, 0x3\n\ + cmp r4, 0\n\ + beq _08024BB0\n\ + movs r0, 0xFE\n\ + strb r0, [r5]\n\ + movs r0, 0xFF\n\ + strb r0, [r5, 0x1]\n\ + adds r5, 0x1\n\ + b _08024BC0\n\ + .align 2, 0\n\ +_08024B94: .4byte gMain\n\ +_08024B98: .4byte gStringVar4\n\ +_08024B9C: .4byte gUnknown_08400D9F\n\ +_08024BA0: .4byte 0x00016018\n\ +_08024BA4: .4byte gUnknown_0840165C\n\ +_08024BA8: .4byte gPlayerParty\n\ +_08024BAC: .4byte gLevelUpStatBoxStats\n\ +_08024BB0:\n\ + strb r6, [r5]\n\ + movs r0, 0x11\n\ + strb r0, [r5, 0x1]\n\ + movs r0, 0x8\n\ + strb r0, [r5, 0x2]\n\ + adds r5, 0x3\n\ + movs r0, 0xFF\n\ + strb r0, [r5]\n\ +_08024BC0:\n\ + movs r1, 0x1\n\ + add r8, r1\n\ + mov r2, r8\n\ + cmp r2, 0x5\n\ + ble _08024B1C\n\ + ldr r4, _08024BF4 @ =gUnknown_03004210\n\ + ldr r1, _08024BF8 @ =gStringVar4\n\ + movs r2, 0x80\n\ + lsls r2, 1\n\ + movs r0, 0x1\n\ + str r0, [sp]\n\ + adds r0, r4, 0\n\ + movs r3, 0xC\n\ + bl InitWindow\n\ + adds r0, r4, 0\n\ + bl sub_8002F44\n\ + ldr r1, _08024BFC @ =0x02000000\n\ + ldr r0, _08024C00 @ =0x0001609c\n\ + adds r1, r0\n\ +_08024BEA:\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ + b _08024C38\n\ + .align 2, 0\n\ +_08024BF4: .4byte gUnknown_03004210\n\ +_08024BF8: .4byte gStringVar4\n\ +_08024BFC: .4byte 0x02000000\n\ +_08024C00: .4byte 0x0001609c\n\ +_08024C04:\n\ + ldr r0, _08024C2C @ =gMain\n\ + ldrh r0, [r0, 0x2E]\n\ + cmp r0, 0\n\ + beq _08024C38\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x1\n\ + str r0, [sp]\n\ + movs r0, 0xB\n\ + movs r1, 0\n\ + movs r2, 0x1D\n\ + movs r3, 0x7\n\ + bl sub_802BBD4\n\ + ldrb r0, [r4]\n\ + adds r0, 0x1\n\ + strb r0, [r4]\n\ + b _08024C38\n\ + .align 2, 0\n\ +_08024C2C: .4byte gMain\n\ +_08024C30:\n\ + ldr r1, _08024C48 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x1\n\ + str r0, [r1]\n\ +_08024C38:\n\ + add sp, 0x4\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08024C48: .4byte gBattlescriptCurrInstr\n\ + .syntax divided"); +} + +#endif + +static void atk6D_set_sentpokes_values(void) +{ + sub_80156DC(); + gBattlescriptCurrInstr++; +} + +static void atk6E_set_atk_to_player0(void) +{ + gBankAttacker = GetBankByPlayerAI(0); + gBattlescriptCurrInstr++; +} + +static void atk6F_set_visible(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + EmitSpriteInvisibility(0, 0); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; +} + +static void atk70_record_ability(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + RecordAbilityBattle(gActiveBank, gLastUsedAbility); + gBattlescriptCurrInstr += 1; //buggy, should be += 2, one byte for command, one byte for argument... +} + +void sub_8024CEC(void) +{ + gBattleTextBuff2[0] = 0xFD; + gBattleTextBuff2[1] = 2; + gBattleTextBuff2[2] = (gMoveToLearn); + gBattleTextBuff2[3] = uBYTE1_16(gMoveToLearn); + gBattleTextBuff2[4] = 0xFF; +} + +static void atk71_buffer_move_to_learn(void) +{ + sub_8024CEC(); + gBattlescriptCurrInstr++; +} + +static void atk72_jump_if_can_run_frombattle(void) +{ + if (sub_8014AB8(gBank1)) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + gBattlescriptCurrInstr += 5; +} + +static void atk73_hp_thresholds(void) +{ + u8 opposing_bank; + s32 result; + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + opposing_bank = gActiveBank ^ 1; + + result = gBattleMons[opposing_bank].hp * 100 / gBattleMons[opposing_bank].maxHP; + if (result == 0) + result = 1; + + if (result > 69 || !gBattleMons[opposing_bank].hp) + BATTLE_STRUCT->hpScale = 0; + else if (result > 39) + BATTLE_STRUCT->hpScale = 1; + else if (result > 9) + BATTLE_STRUCT->hpScale = 2; + else + BATTLE_STRUCT->hpScale = 3; + } + + gBattlescriptCurrInstr += 2; +} + +static void atk74_hp_thresholds2(void) +{ + u8 opposing_bank; + u8 hp_switchout; + s32 result; + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + opposing_bank = gActiveBank ^ 1; + hp_switchout = ewram[2 * GetBankSide(opposing_bank) + 0x160bc]; //BATTLE_STRUCT->HP_OnSwitchout[GetBankSide(opposing_bank)]; + result = (hp_switchout - gBattleMons[opposing_bank].hp) * 100 / hp_switchout; + + if (gBattleMons[opposing_bank].hp >= hp_switchout) + BATTLE_STRUCT->hpScale = 0; + else if (result <= 29) + BATTLE_STRUCT->hpScale = 1; + else if (result <= 69) + BATTLE_STRUCT->hpScale = 2; + else + BATTLE_STRUCT->hpScale = 3; + } + + gBattlescriptCurrInstr += 2; +} + +static void atk75_8026A58(void) +{ + gBankInMenu = gBankAttacker; + sub_803E1B0(&gEnemyParty[gBattlePartyID[gBankAttacker]], gLastUsedItem, gBattlePartyID[gBankAttacker], 0, 1); + gBattlescriptCurrInstr += 1; +} + +static void atk76_various(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + switch (BSScriptRead8(gBattlescriptCurrInstr + 2)) + { + case 0: + CancelMultiTurnMoves(gActiveBank); + break; + case 1: + { + u8 side; + gBankAttacker = gBankTarget; + side = GetBankSide(gBankAttacker) ^ 1; + if (gSideTimer[side].followmeTimer && gBattleMons[gSideTimer[side].followmeTarget].hp) + gBankTarget = gSideTimer[side].followmeTarget; + else + gBankTarget = gActiveBank; + } + break; + case 2: + gBattleCommunication[0] = CanRunFromBattle(); + break; + case 3: + gBankTarget = GetMoveTarget(gCurrentMove, 0); + break; + case 4: + if (gHitMarker & HITMARKER_FAINTED(gActiveBank)) + gBattleCommunication[0] = 1; + else + gBattleCommunication[0] = 0; + break; + case 5: + gSpecialStatuses[gActiveBank].intimidatedPoke = 0; + gSpecialStatuses[gActiveBank].traced = 0; + break; + case 6: + { + int i; + u16* choiced_move; + if (gBattlePartyID[0] == BATTLE_STRUCT->expGetterID) + goto ACTIVE_0; + if (gBattlePartyID[2] != BATTLE_STRUCT->expGetterID) + break; + if (gBattlePartyID[0] == gBattlePartyID[2]) + { + ACTIVE_0: + gActiveBank = 0; + } + else + gActiveBank = 2; + + choiced_move = (u16*)(&ewram[gActiveBank * 2 + 0x160e8]); + for (i = 0; i < 4; i++) + { + if (gBattleMons[gActiveBank].moves[i] == *choiced_move) + break; + } + if (i == 4) + *choiced_move = 0; + } + break; + } + + gBattlescriptCurrInstr += 3; +} + +static void atk77_setprotect(void) //protect and endure +{ + bool8 not_last_turn = 1; + u16 last_move = gUnknown_02024C4C[gBankAttacker]; + + if (last_move != MOVE_PROTECT && last_move != MOVE_DETECT && last_move != MOVE_ENDURE) + gDisableStructs[gBankAttacker].protectUses = 0; + if (gCurrentMoveTurn == (gNoOfAllBanks - 1)) + not_last_turn = 0; + + if (sProtectSuccessRates[gDisableStructs[gBankAttacker].protectUses] > Random() && not_last_turn) + { + if (gBattleMoves[gCurrentMove].effect == EFFECT_PROTECT) + { + gProtectStructs[gBankAttacker].protected = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + if (gBattleMoves[gCurrentMove].effect == EFFECT_ENDURE) //what is else if + { + gProtectStructs[gBankAttacker].endured = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + gDisableStructs[gBankAttacker].protectUses++; + } + else + { + gDisableStructs[gBankAttacker].protectUses = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + gBattleMoveFlags |= MOVESTATUS_MISSED; + } + + gBattlescriptCurrInstr++; +} + +static void atk78_faintifabilitynotdamp(void) +{ + if (gBattleExecBuffer) + return; + + for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++) + { + if (gBattleMons[gBankTarget].ability == ABILITY_DAMP) + break; + } + + if (gBankTarget == gNoOfAllBanks) + { + gActiveBank = gBankAttacker; + gBattleMoveDamage = gBattleMons[gActiveBank].hp; + EmitHealthBarUpdate(0, 0x7FFF); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr++; + + for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++) + { + if (gBankTarget == gBankAttacker) + continue; + if (!(gAbsentBankFlags & gBitTable[gBankTarget])) + break; + } + } + else + { + gLastUsedAbility = ABILITY_DAMP; + RecordAbilityBattle(gBankTarget, gBattleMons[gBankTarget].ability); + gBattlescriptCurrInstr = gUnknown_081D9834; + } +} + +static void atk79_setatkhptozero(void) +{ + if (gBattleExecBuffer) + return; + + gActiveBank = gBankAttacker; + gBattleMons[gActiveBank].hp = 0; + EmitSetAttributes(0, REQUEST_HP_BATTLE, 0, 2, &gBattleMons[gActiveBank].hp); + MarkBufferBankForExecution(gActiveBank); + + gBattlescriptCurrInstr++; +} + +static void atk7A_jumpwhiletargetvalid(void) //used by intimidate to loop through all targets +{ + u8* jump_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + for (gBankTarget++; ; gBankTarget++) + { + if (gBankTarget == gBankAttacker) + continue; + if (!(gAbsentBankFlags & gBitTable[gBankTarget])) + break; + } + + if (gBankTarget >= gNoOfAllBanks) + gBattlescriptCurrInstr += 5; + else + gBattlescriptCurrInstr = jump_loc; + } + else + gBattlescriptCurrInstr += 5; +} + +static void atk7B_healhalfHP_if_possible(void) +{ + u8* fail_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + + if (BSScriptRead8(gBattlescriptCurrInstr + 5) == 1) + gBankTarget = gBankAttacker; + + gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + + if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP) + gBattlescriptCurrInstr = fail_loc; + else + gBattlescriptCurrInstr += 6; +} + +static void atk7C_8025508(void) +{ + u16 r7 = ewram[gBankAttacker * 2 + 0x160ac] | (ewram[gBankAttacker * 2 + 0x160ad] << 8); + u16 r6 = ewram[gBankAttacker * 4 + 0x16100] | (ewram[gBankAttacker * 4 + 0x16101] << 8); + u16 r5 = ewram[gBankAttacker * 4 + 0x16102] | (ewram[gBankAttacker * 4 + 0x16103] << 8); + + if (r7 !=0 && r7 != 0xFFFF) + { + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + gCurrentMove = r7; + gBankTarget = GetMoveTarget(gCurrentMove, 0); + gBattlescriptCurrInstr = gBattleScriptsEffectsTable[gBattleMoves[gCurrentMove].effect]; + } + else if (r6 != 0 && r5 != 0 && r6 != 0xFFFF && r5 != 0xFFFF) + { + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + if (Random() & 1) + gCurrentMove = r6; + else + gCurrentMove = r5; + gBankTarget = GetMoveTarget(gCurrentMove, 0); + gBattlescriptCurrInstr = gBattleScriptsEffectsTable[gBattleMoves[gCurrentMove].effect]; + } + else if (r6 != 0 && r6 != 0xFFFF) + { + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + gCurrentMove = r6; + gBankTarget = GetMoveTarget(gCurrentMove, 0); + gBattlescriptCurrInstr = gBattleScriptsEffectsTable[gBattleMoves[gCurrentMove].effect]; + } + else if (r5 != 0 && r5 != 0xFFFF) + { + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + gCurrentMove = r5; + gBankTarget = GetMoveTarget(gCurrentMove, 0); + gBattlescriptCurrInstr = gBattleScriptsEffectsTable[gBattleMoves[gCurrentMove].effect]; + } + else + { + gSpecialStatuses[gBankAttacker].flag20 = 1; + gBattlescriptCurrInstr++; + } +} + +static void atk7D_set_rain(void) +{ + if (gBattleWeather & WEATHER_RAIN_ANY) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else + { + gBattleWeather = WEATHER_RAIN_TEMPORARY; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gWishFutureKnock.weatherDuration = 5; + } + gBattlescriptCurrInstr++; +} + +static void atk7E_setreflect(void) +{ + if (gSideAffecting[GetBankIdentity(gBankAttacker) & 1] & SIDE_STATUS_REFLECT) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + else + { + gSideAffecting[GetBankIdentity(gBankAttacker) & 1] |= SIDE_STATUS_REFLECT; + gSideTimer[GetBankIdentity(gBankAttacker) & 1].reflectTimer = 5; + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMons(1) == 2) + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + gBattlescriptCurrInstr++; +} + +static void atk7F_setseeded(void) +{ + if (gBattleMoveFlags & MOVESTATUS_NOEFFECT || gStatuses3[gBankTarget] & STATUS3_LEECHSEED) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else if (gBattleMons[gBankTarget].type1 == TYPE_GRASS || gBattleMons[gBankTarget].type2 == TYPE_GRASS) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else + { + gStatuses3[gBankTarget] |= gBankAttacker; + gStatuses3[gBankTarget] |= STATUS3_LEECHSEED; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + + gBattlescriptCurrInstr++; +} + +static void atk80_manipulatedamage(void) +{ + switch (BSScriptRead8(gBattlescriptCurrInstr + 1)) + { + case 0: + gBattleMoveDamage *= -1; + break; + case 1: + gBattleMoveDamage /= 2; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if ((gBattleMons[gBankTarget].maxHP / 2) < gBattleMoveDamage) + gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2; + break; + case 2: + gBattleMoveDamage *= 2; + break; + } + + gBattlescriptCurrInstr += 2; +} + +static void atk81_setrest(void) +{ + u8* fail_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gActiveBank = gBankTarget = gBankAttacker; + gBattleMoveDamage = gBattleMons[gBankTarget].maxHP * (-1); + if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP) + gBattlescriptCurrInstr = fail_loc; + else + { + if (gBattleMons[gBankTarget].status1 & ((u8)(~STATUS_SLEEP))) + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + + gBattleMons[gBankTarget].status1 = 3; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 5; + } +} + +static void atk82_jumpifnotfirstturn(void) +{ + u8* jump_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + + if (gDisableStructs[gBankAttacker].isFirstTurn) + gBattlescriptCurrInstr += 5; + else + gBattlescriptCurrInstr = jump_loc; +} + +static void atk83_nop(void) +{ + gBattlescriptCurrInstr++; +} + +bool8 UproarWakeUpCheck(u8 bank) +{ + int i; + for (i = 0; i < gNoOfAllBanks; i++) + { + if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || gBattleMons[bank].ability == ABILITY_SOUNDPROOF) //wtf gamefreak, you should check this only once, not every time in a loop... + continue; + BATTLE_STRUCT->scriptingActive = i; + if (gBankTarget == 0xFF) + gBankTarget = i; + else if (gBankTarget == i) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + break; + } + if (i == gNoOfAllBanks) + return 0; + else + return 1; +} + +static void atk84_jump_if_cant_sleep(void) +{ + u8* jump_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + if (UproarWakeUpCheck(gBankTarget)) + gBattlescriptCurrInstr = jump_loc; + else if (gBattleMons[gBankTarget].ability == ABILITY_INSOMNIA || gBattleMons[gBankTarget].ability == ABILITY_VITAL_SPIRIT) + { + gLastUsedAbility = gBattleMons[gBankTarget].ability; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + gBattlescriptCurrInstr = jump_loc; + RecordAbilityBattle(gBankTarget, gLastUsedAbility); + } + else + { + gBattlescriptCurrInstr += 5; + } +} + +static void atk85_stockpile(void) +{ + if (gDisableStructs[gBankAttacker].stockpileCounter == 3) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else + { + gDisableStructs[gBankAttacker].stockpileCounter++; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 1; + gBattleTextBuff1[2] = 1; + gBattleTextBuff1[3] = 1; + gBattleTextBuff1[4] = gDisableStructs[gBankAttacker].stockpileCounter; + gBattleTextBuff1[5] = 0xFF; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + gBattlescriptCurrInstr++; +} + +static void atk86_stockpiletobasedamage(void) +{ + u8* jump_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + if (gDisableStructs[gBankAttacker].stockpileCounter == 0) + { + gBattlescriptCurrInstr = jump_loc; + } + else + { + if (gBattleCommunication[6] != 1) + { + gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove, + gSideAffecting[GetBankIdentity(gBankTarget) & 1], 0, + 0, gBankAttacker, gBankTarget) + * gDisableStructs[gBankAttacker].stockpileCounter; + BATTLE_STRUCT->animTurn = gDisableStructs[gBankAttacker].stockpileCounter; + + if (gProtectStructs[gBankAttacker].helpingHand) + gBattleMoveDamage = gBattleMoveDamage * 15 / 10; + } + gDisableStructs[gBankAttacker].stockpileCounter = 0; + gBattlescriptCurrInstr += 5; + } +} + +static void atk87_stockpiletohpheal(void) +{ + u8* jump_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + if (gDisableStructs[gBankAttacker].stockpileCounter == 0) + { + gBattlescriptCurrInstr = jump_loc; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + else if (gBattleMons[gBankAttacker].maxHP == gBattleMons[gBankAttacker].hp) + { + gDisableStructs[gBankAttacker].stockpileCounter = 0; + gBattlescriptCurrInstr = jump_loc; + gBankTarget = gBankAttacker; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else + { + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / (1 << (3 - gDisableStructs[gBankAttacker].stockpileCounter)); + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + BATTLE_STRUCT->animTurn = gDisableStructs[gBankAttacker].stockpileCounter; + gDisableStructs[gBankAttacker].stockpileCounter = 0; + gBattlescriptCurrInstr += 5; + gBankTarget = gBankAttacker; + } +} + +static void atk88_negativedamage(void) +{ + gBattleMoveDamage = -(gHP_dealt / 2); + if (gBattleMoveDamage == 0) + gBattleMoveDamage = -1; + gBattlescriptCurrInstr++; +} + +#ifdef NONMATCHING +u8 ChangeStatBuffs(s8 statchanger, u8 stat, u8 flags, u8* bs_ptr) +{ + u8 r9 = 0; + u8 r10 = 0; + u8 index; + if (flags & 0x40) + gActiveBank = gBankAttacker; + else + gActiveBank = gBankTarget; + flags &= ~(0x40); + if (flags & 0x80) + r9++; + flags &= ~(0x80); + if (flags & 0x20) + r10++; + flags &= ~(0x20); + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 5; + gBattleTextBuff1[2] = stat; + gBattleTextBuff1[3] = 0xFF; + + if ((statchanger << 0x18) < 0) //stat decrease + { + if (gSideTimer[GetBankIdentity(gActiveBank) & 1].mistTimer && !r9 && gCurrentMove != MOVE_CURSE) + { + if (flags == 1) + { + if (gSpecialStatuses[gActiveBank].statloweringflag) + gBattlescriptCurrInstr = bs_ptr; + else + { + b_movescr_stack_push(bs_ptr); + BATTLE_STRUCT->scriptingActive = gActiveBank; + gBattlescriptCurrInstr = BattleScript_MistProtected; + gSpecialStatuses[gActiveBank].statloweringflag = 1; + } + } + return 1; + } + else if (gCurrentMove != MOVE_CURSE && r10 != 1 && JumpIfMoveAffectedByProtect(0)) + { + gBattlescriptCurrInstr = BattleScript_ButItFailed; + return 1; + } + else if ((gBattleMons[gActiveBank].ability == ABILITY_CLEAR_BODY || gBattleMons[gActiveBank].ability == ABILITY_WHITE_SMOKE) && !r9 && gCurrentMove != MOVE_CURSE) + { + if (flags == 1) + { + if (gSpecialStatuses[gActiveBank].statloweringflag) + gBattlescriptCurrInstr = bs_ptr; + else + { + b_movescr_stack_push(bs_ptr); + BATTLE_STRUCT->scriptingActive = gActiveBank; + gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss; + gLastUsedAbility = gBattleMons[gActiveBank].ability; + RecordAbilityBattle(gActiveBank, gLastUsedAbility); + gSpecialStatuses[gActiveBank].statloweringflag = 1; + } + } + return 1; + } + else if (gBattleMons[gActiveBank].ability == ABILITY_KEEN_EYE && !r9 && stat == STAT_STAGE_ACC) + { + if (flags == 1) + { + b_movescr_stack_push(bs_ptr); + BATTLE_STRUCT->scriptingActive = gActiveBank; + gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss; + gLastUsedAbility = gBattleMons[gActiveBank].ability; + RecordAbilityBattle(gActiveBank, gLastUsedAbility); + } + return 1; + } + else if (gBattleMons[gActiveBank].ability == ABILITY_HYPER_CUTTER && !r9 && stat == STAT_STAGE_ATK) + { + if (flags == 1) + { + b_movescr_stack_push(bs_ptr); + BATTLE_STRUCT->scriptingActive = gActiveBank; + gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss; + gLastUsedAbility = gBattleMons[gActiveBank].ability; + RecordAbilityBattle(gActiveBank, gLastUsedAbility); + } + return 1; + } + else if (gBattleMons[gActiveBank].ability == ABILITY_SHIELD_DUST && flags == 0) + return 1; + else //decrease + { + statchanger = -((statchanger >> 4) & (7)); + gBattleTextBuff2[0] = 0xFD; + index = 1; + if (statchanger == -2) + { + gBattleTextBuff2[1] = 0; + gBattleTextBuff2[2] = 0xD3; //harshly + gBattleTextBuff2[3] = 0x0; + index = 4; + } + gBattleTextBuff2[index] = 0; + index++; + gBattleTextBuff2[index] = 0xD4; //fell + index++; + gBattleTextBuff2[index] = 0; + index++; + gBattleTextBuff2[index] = 0xFF; + + if (gBattleMons[gActiveBank].statStages[stat] == 0) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else + { + u8 stringID = 0; + if (gBankTarget == gActiveBank) + stringID = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = stringID; + } + } + } + else //stat increase + { + statchanger = (statchanger >> 4) & (7); + gBattleTextBuff2[0] = 0xFD; + index = 1; + if (statchanger == 2) + { + gBattleTextBuff2[1] = 0; + gBattleTextBuff2[2] = 0xD1; //sharply + gBattleTextBuff2[3] = 0x0; + index = 4; + } + gBattleTextBuff2[index] = 0; + index++; + gBattleTextBuff2[index] = 0xD2; //rose + index++; + gBattleTextBuff2[index] = 0; + index++; + gBattleTextBuff2[index] = 0xFF; + + if (gBattleMons[gActiveBank].statStages[stat] == 0xC) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else + { + u8 stringID = 0; + if (gBankTarget == gActiveBank) + stringID = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = stringID; + } + } + + gBattleMons[gActiveBank].statStages[stat] += statchanger; + if (gBattleMons[gActiveBank].statStages[stat] < 0) + gBattleMons[gActiveBank].statStages[stat] = 0; + if (gBattleMons[gActiveBank].statStages[stat] > 0xC) + gBattleMons[gActiveBank].statStages[stat] = 0xC; + + if (gBattleCommunication[MULTISTRING_CHOOSER] == 2) + { + if (flags & 1) + gBattleMoveFlags |= MOVESTATUS_MISSED; + if (gBattleCommunication[MULTISTRING_CHOOSER] == 2 && !(flags & 1)) //what the actual fuck gamefreak... + return 1; + } + return 0; +} + +#else +__attribute__((naked)) +u8 ChangeStatBuffs(s8 statchanger, u8 stat, u8 flags, u8* bs_ptr) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + mov r8, r3\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + lsls r1, 24\n\ + lsrs r7, r1, 24\n\ + lsls r2, 24\n\ + lsrs r5, r2, 24\n\ + movs r0, 0\n\ + mov r9, r0\n\ + mov r10, r0\n\ + movs r0, 0x40\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _08025E54\n\ + ldr r0, _08025E4C @ =gActiveBank\n\ + ldr r1, _08025E50 @ =gBankAttacker\n\ + b _08025E58\n\ + .align 2, 0\n\ +_08025E4C: .4byte gActiveBank\n\ +_08025E50: .4byte gBankAttacker\n\ +_08025E54:\n\ + ldr r0, _08025EF8 @ =gActiveBank\n\ + ldr r1, _08025EFC @ =gBankTarget\n\ +_08025E58:\n\ + ldrb r1, [r1]\n\ + strb r1, [r0]\n\ + movs r0, 0xBF\n\ + ands r5, r0\n\ + movs r0, 0x80\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _08025E72\n\ + mov r0, r9\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ +_08025E72:\n\ + movs r0, 0x7F\n\ + ands r5, r0\n\ + movs r0, 0x20\n\ + ands r0, r5\n\ + cmp r0, 0\n\ + beq _08025E88\n\ + mov r0, r10\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r10, r0\n\ +_08025E88:\n\ + movs r0, 0xDF\n\ + ands r5, r0\n\ + ldr r1, _08025F00 @ =gBattleTextBuff1\n\ + movs r4, 0\n\ + movs r2, 0xFD\n\ + strb r2, [r1]\n\ + movs r0, 0x5\n\ + strb r0, [r1, 0x1]\n\ + strb r7, [r1, 0x2]\n\ + movs r3, 0x1\n\ + negs r3, r3\n\ + mov r12, r3\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x3]\n\ + lsls r0, r6, 24\n\ + cmp r0, 0\n\ + blt _08025EAC\n\ + b _080261B0\n\ +_08025EAC:\n\ + ldr r4, _08025F04 @ =gSideTimer\n\ + ldr r1, _08025EF8 @ =gActiveBank\n\ + ldrb r0, [r1]\n\ + bl GetBankIdentity\n\ + movs r1, 0x1\n\ + ands r1, r0\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldrb r0, [r0, 0x2]\n\ + cmp r0, 0\n\ + beq _08025F54\n\ + mov r2, r9\n\ + cmp r2, 0\n\ + bne _08025F54\n\ + ldr r0, _08025F08 @ =gCurrentMove\n\ + ldrh r0, [r0]\n\ + cmp r0, 0xAE\n\ + beq _08025F84\n\ + cmp r5, 0x1\n\ + bne _08025F74\n\ + ldr r4, _08025F0C @ =gSpecialStatuses\n\ + ldr r3, _08025EF8 @ =gActiveBank\n\ + ldrb r0, [r3]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r4\n\ + ldrb r0, [r1]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _08025F14\n\ + ldr r0, _08025F10 @ =gBattlescriptCurrInstr\n\ + mov r4, r8\n\ + str r4, [r0]\n\ + b _08025F74\n\ + .align 2, 0\n\ +_08025EF8: .4byte gActiveBank\n\ +_08025EFC: .4byte gBankTarget\n\ +_08025F00: .4byte gBattleTextBuff1\n\ +_08025F04: .4byte gSideTimer\n\ +_08025F08: .4byte gCurrentMove\n\ +_08025F0C: .4byte gSpecialStatuses\n\ +_08025F10: .4byte gBattlescriptCurrInstr\n\ +_08025F14:\n\ + mov r0, r8\n\ + bl b_movescr_stack_push\n\ + ldr r0, _08025F40 @ =0x02000000\n\ + ldr r6, _08025F44 @ =gActiveBank\n\ + ldrb r1, [r6]\n\ + ldr r2, _08025F48 @ =0x00016003\n\ + adds r0, r2\n\ + strb r1, [r0]\n\ + ldr r1, _08025F4C @ =gBattlescriptCurrInstr\n\ + ldr r0, _08025F50 @ =BattleScript_MistProtected\n\ + str r0, [r1]\n\ + ldrb r1, [r6]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldrb r1, [r0]\n\ + movs r2, 0x1\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _08025F74\n\ + .align 2, 0\n\ +_08025F40: .4byte 0x02000000\n\ +_08025F44: .4byte gActiveBank\n\ +_08025F48: .4byte 0x00016003\n\ +_08025F4C: .4byte gBattlescriptCurrInstr\n\ +_08025F50: .4byte BattleScript_MistProtected\n\ +_08025F54:\n\ + ldr r0, _08025F78 @ =gCurrentMove\n\ + ldrh r0, [r0]\n\ + cmp r0, 0xAE\n\ + beq _08025F84\n\ + mov r3, r10\n\ + cmp r3, 0x1\n\ + beq _08025F84\n\ + movs r0, 0\n\ + bl JumpIfMoveAffectedByProtect\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08025F84\n\ + ldr r1, _08025F7C @ =gBattlescriptCurrInstr\n\ + ldr r0, _08025F80 @ =BattleScript_ButItFailed\n\ + str r0, [r1]\n\ +_08025F74:\n\ + movs r0, 0x1\n\ + b _080262A4\n\ + .align 2, 0\n\ +_08025F78: .4byte gCurrentMove\n\ +_08025F7C: .4byte gBattlescriptCurrInstr\n\ +_08025F80: .4byte BattleScript_ButItFailed\n\ +_08025F84:\n\ + ldr r2, _08025FCC @ =gBattleMons\n\ + ldr r1, _08025FD0 @ =gActiveBank\n\ + ldrb r3, [r1]\n\ + movs r4, 0x58\n\ + adds r0, r3, 0\n\ + muls r0, r4\n\ + adds r0, r2\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + mov r10, r2\n\ + cmp r0, 0x1D\n\ + beq _08025FA0\n\ + cmp r0, 0x49\n\ + bne _08026040\n\ +_08025FA0:\n\ + mov r0, r9\n\ + cmp r0, 0\n\ + bne _08026040\n\ + ldr r0, _08025FD4 @ =gCurrentMove\n\ + ldrh r0, [r0]\n\ + cmp r0, 0xAE\n\ + beq _08026040\n\ + cmp r5, 0x1\n\ + bne _08025F74\n\ + ldr r4, _08025FD8 @ =gSpecialStatuses\n\ + lsls r0, r3, 2\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldrb r0, [r0]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _08025FE0\n\ + ldr r0, _08025FDC @ =gBattlescriptCurrInstr\n\ + mov r1, r8\n\ + str r1, [r0]\n\ + b _08025F74\n\ + .align 2, 0\n\ +_08025FCC: .4byte gBattleMons\n\ +_08025FD0: .4byte gActiveBank\n\ +_08025FD4: .4byte gCurrentMove\n\ +_08025FD8: .4byte gSpecialStatuses\n\ +_08025FDC: .4byte gBattlescriptCurrInstr\n\ +_08025FE0:\n\ + mov r0, r8\n\ + bl b_movescr_stack_push\n\ + ldr r0, _08026028 @ =0x02000000\n\ + ldr r2, _0802602C @ =gActiveBank\n\ + ldrb r1, [r2]\n\ + ldr r3, _08026030 @ =0x00016003\n\ + adds r0, r3\n\ + strb r1, [r0]\n\ + ldr r1, _08026034 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08026038 @ =BattleScript_AbilityNoStatLoss\n\ + str r0, [r1]\n\ + ldr r1, _0802603C @ =gLastUsedAbility\n\ + ldrb r0, [r2]\n\ + movs r6, 0x58\n\ + muls r0, r6\n\ + add r0, r10\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + strb r0, [r1]\n\ + ldrb r0, [r2]\n\ + ldrb r1, [r1]\n\ + bl RecordAbilityBattle\n\ + ldr r0, _0802602C @ =gActiveBank\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r4\n\ + ldrb r1, [r0]\n\ + movs r2, 0x1\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ + b _08025F74\n\ + .align 2, 0\n\ +_08026028: .4byte 0x02000000\n\ +_0802602C: .4byte gActiveBank\n\ +_08026030: .4byte 0x00016003\n\ +_08026034: .4byte gBattlescriptCurrInstr\n\ +_08026038: .4byte BattleScript_AbilityNoStatLoss\n\ +_0802603C: .4byte gLastUsedAbility\n\ +_08026040:\n\ + ldr r1, _08026090 @ =gActiveBank\n\ + ldrb r0, [r1]\n\ + movs r4, 0x58\n\ + muls r0, r4\n\ + add r0, r10\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x33\n\ + bne _080260A8\n\ + mov r2, r9\n\ + cmp r2, 0\n\ + bne _080260A8\n\ + cmp r7, 0x6\n\ + bne _080260A8\n\ + cmp r5, 0x1\n\ + bne _08025F74\n\ + mov r0, r8\n\ + bl b_movescr_stack_push\n\ + ldr r0, _08026094 @ =0x02000000\n\ + ldr r3, _08026090 @ =gActiveBank\n\ + ldrb r1, [r3]\n\ + ldr r6, _08026098 @ =0x00016003\n\ + adds r0, r6\n\ + strb r1, [r0]\n\ + ldr r1, _0802609C @ =gBattlescriptCurrInstr\n\ + ldr r0, _080260A0 @ =BattleScript_AbilityNoSpecificStatLoss\n\ + str r0, [r1]\n\ + ldr r1, _080260A4 @ =gLastUsedAbility\n\ + ldrb r0, [r3]\n\ + muls r0, r4\n\ + add r0, r10\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + strb r0, [r1]\n\ + ldrb r0, [r3]\n\ + ldrb r1, [r1]\n\ + bl RecordAbilityBattle\n\ + b _08025F74\n\ + .align 2, 0\n\ +_08026090: .4byte gActiveBank\n\ +_08026094: .4byte 0x02000000\n\ +_08026098: .4byte 0x00016003\n\ +_0802609C: .4byte gBattlescriptCurrInstr\n\ +_080260A0: .4byte BattleScript_AbilityNoSpecificStatLoss\n\ +_080260A4: .4byte gLastUsedAbility\n\ +_080260A8:\n\ + ldr r1, _080260FC @ =gActiveBank\n\ + ldrb r0, [r1]\n\ + movs r4, 0x58\n\ + muls r0, r4\n\ + add r0, r10\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x34\n\ + bne _08026114\n\ + mov r2, r9\n\ + cmp r2, 0\n\ + bne _08026114\n\ + cmp r7, 0x1\n\ + bne _08026114\n\ + cmp r5, 0x1\n\ + beq _080260CA\n\ + b _08025F74\n\ +_080260CA:\n\ + mov r0, r8\n\ + bl b_movescr_stack_push\n\ + ldr r0, _08026100 @ =0x02000000\n\ + ldr r3, _080260FC @ =gActiveBank\n\ + ldrb r1, [r3]\n\ + ldr r6, _08026104 @ =0x00016003\n\ + adds r0, r6\n\ + strb r1, [r0]\n\ + ldr r1, _08026108 @ =gBattlescriptCurrInstr\n\ + ldr r0, _0802610C @ =BattleScript_AbilityNoSpecificStatLoss\n\ + str r0, [r1]\n\ + ldr r1, _08026110 @ =gLastUsedAbility\n\ + ldrb r0, [r3]\n\ + muls r0, r4\n\ + add r0, r10\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + strb r0, [r1]\n\ + ldrb r0, [r3]\n\ + ldrb r1, [r1]\n\ + bl RecordAbilityBattle\n\ + b _08025F74\n\ + .align 2, 0\n\ +_080260FC: .4byte gActiveBank\n\ +_08026100: .4byte 0x02000000\n\ +_08026104: .4byte 0x00016003\n\ +_08026108: .4byte gBattlescriptCurrInstr\n\ +_0802610C: .4byte BattleScript_AbilityNoSpecificStatLoss\n\ +_08026110: .4byte gLastUsedAbility\n\ +_08026114:\n\ + ldr r0, _080261A0 @ =gActiveBank\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + add r0, r10\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x13\n\ + bne _0802612C\n\ + cmp r5, 0\n\ + bne _0802612C\n\ + b _08025F74\n\ +_0802612C:\n\ + lsls r0, r6, 24\n\ + asrs r0, 28\n\ + movs r1, 0x7\n\ + ands r0, r1\n\ + negs r0, r0\n\ + lsls r0, 24\n\ + ldr r3, _080261A4 @ =gBattleTextBuff2\n\ + movs r4, 0\n\ + movs r1, 0xFD\n\ + strb r1, [r3]\n\ + movs r2, 0x1\n\ + lsrs r6, r0, 24\n\ + asrs r0, 24\n\ + subs r1, 0xFF\n\ + cmp r0, r1\n\ + bne _08026156\n\ + strb r4, [r3, 0x1]\n\ + movs r0, 0xD3\n\ + strb r0, [r3, 0x2]\n\ + strb r4, [r3, 0x3]\n\ + movs r2, 0x4\n\ +_08026156:\n\ + adds r0, r2, r3\n\ + strb r4, [r0]\n\ + adds r2, 0x1\n\ + adds r1, r2, r3\n\ + movs r0, 0xD4\n\ + strb r0, [r1]\n\ + adds r2, 0x1\n\ + adds r0, r2, r3\n\ + strb r4, [r0]\n\ + adds r2, 0x1\n\ + adds r1, r2, r3\n\ + movs r0, 0xFF\n\ + strb r0, [r1]\n\ + ldr r1, _080261A0 @ =gActiveBank\n\ + ldrb r2, [r1]\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + adds r0, r7, r0\n\ + mov r1, r10\n\ + adds r1, 0x18\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + cmp r0, 0\n\ + beq _08026206\n\ + movs r1, 0\n\ + ldr r0, _080261A8 @ =gBankTarget\n\ + ldrb r0, [r0]\n\ + ldr r3, _080261AC @ =gBattleCommunication\n\ + mov r8, r3\n\ + cmp r0, r2\n\ + bne _0802619A\n\ + movs r1, 0x1\n\ +_0802619A:\n\ + mov r4, r8\n\ + strb r1, [r4, 0x5]\n\ + b _08026234\n\ + .align 2, 0\n\ +_080261A0: .4byte gActiveBank\n\ +_080261A4: .4byte gBattleTextBuff2\n\ +_080261A8: .4byte gBankTarget\n\ +_080261AC: .4byte gBattleCommunication\n\ +_080261B0:\n\ + asrs r6, r0, 28\n\ + movs r0, 0x7\n\ + ands r6, r0\n\ + ldr r3, _08026210 @ =gBattleTextBuff2\n\ + strb r2, [r3]\n\ + movs r2, 0x1\n\ + cmp r6, 0x2\n\ + bne _080261CA\n\ + strb r4, [r3, 0x1]\n\ + movs r0, 0xD1\n\ + strb r0, [r3, 0x2]\n\ + strb r4, [r3, 0x3]\n\ + movs r2, 0x4\n\ +_080261CA:\n\ + adds r0, r2, r3\n\ + strb r4, [r0]\n\ + adds r2, 0x1\n\ + adds r1, r2, r3\n\ + movs r0, 0xD2\n\ + strb r0, [r1]\n\ + adds r2, 0x1\n\ + adds r0, r2, r3\n\ + strb r4, [r0]\n\ + adds r2, 0x1\n\ + adds r1, r2, r3\n\ + ldrb r0, [r1]\n\ + mov r2, r12\n\ + orrs r0, r2\n\ + strb r0, [r1]\n\ + ldr r2, _08026214 @ =gBattleMons\n\ + ldr r4, _08026218 @ =gActiveBank\n\ + ldrb r3, [r4]\n\ + movs r0, 0x58\n\ + muls r0, r3\n\ + adds r0, r7, r0\n\ + adds r1, r2, 0\n\ + adds r1, 0x18\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + mov r10, r2\n\ + cmp r0, 0xC\n\ + bne _08026220\n\ +_08026206:\n\ + ldr r1, _0802621C @ =gBattleCommunication\n\ + movs r0, 0x2\n\ + strb r0, [r1, 0x5]\n\ + mov r8, r1\n\ + b _08026234\n\ + .align 2, 0\n\ +_08026210: .4byte gBattleTextBuff2\n\ +_08026214: .4byte gBattleMons\n\ +_08026218: .4byte gActiveBank\n\ +_0802621C: .4byte gBattleCommunication\n\ +_08026220:\n\ + movs r1, 0\n\ + ldr r0, _080262B4 @ =gBankTarget\n\ + ldrb r0, [r0]\n\ + ldr r2, _080262B8 @ =gBattleCommunication\n\ + mov r8, r2\n\ + cmp r0, r3\n\ + bne _08026230\n\ + movs r1, 0x1\n\ +_08026230:\n\ + mov r3, r8\n\ + strb r1, [r3, 0x5]\n\ +_08026234:\n\ + ldr r2, _080262BC @ =gActiveBank\n\ + ldrb r0, [r2]\n\ + movs r4, 0x58\n\ + adds r1, r0, 0\n\ + muls r1, r4\n\ + adds r1, r7, r1\n\ + mov r3, r10\n\ + adds r3, 0x18\n\ + adds r1, r3\n\ + lsls r0, r6, 24\n\ + asrs r0, 24\n\ + ldrb r6, [r1]\n\ + adds r0, r6\n\ + strb r0, [r1]\n\ + ldrb r0, [r2]\n\ + muls r0, r4\n\ + adds r0, r7, r0\n\ + adds r1, r0, r3\n\ + movs r0, 0\n\ + ldrsb r0, [r1, r0]\n\ + cmp r0, 0\n\ + bge _08026264\n\ + movs r0, 0\n\ + strb r0, [r1]\n\ +_08026264:\n\ + ldr r1, _080262BC @ =gActiveBank\n\ + ldrb r0, [r1]\n\ + muls r0, r4\n\ + adds r0, r7, r0\n\ + adds r1, r0, r3\n\ + movs r0, 0\n\ + ldrsb r0, [r1, r0]\n\ + cmp r0, 0xC\n\ + ble _0802627A\n\ + movs r0, 0xC\n\ + strb r0, [r1]\n\ +_0802627A:\n\ + mov r2, r8\n\ + ldrb r0, [r2, 0x5]\n\ + cmp r0, 0x2\n\ + bne _080262A2\n\ + movs r3, 0x1\n\ + ands r3, r5\n\ + cmp r3, 0\n\ + beq _08026294\n\ + ldr r0, _080262C0 @ =gBattleMoveFlags\n\ + ldrb r1, [r0]\n\ + movs r2, 0x1\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ +_08026294:\n\ + mov r4, r8\n\ + ldrb r0, [r4, 0x5]\n\ + cmp r0, 0x2\n\ + bne _080262A2\n\ + cmp r3, 0\n\ + bne _080262A2\n\ + b _08025F74\n\ +_080262A2:\n\ + movs r0, 0\n\ +_080262A4:\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .align 2, 0\n\ +_080262B4: .4byte gBankTarget\n\ +_080262B8: .4byte gBattleCommunication\n\ +_080262BC: .4byte gActiveBank\n\ +_080262C0: .4byte gBattleMoveFlags\n\ + .syntax divided"); +} +#endif // NONMATCHING + +static void atk89_statbuffchange(void) +{ + u8* jump_loc = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + if (ChangeStatBuffs(BATTLE_STRUCT->statChanger & 0xF0, BATTLE_STRUCT->statChanger & 0xF, BSScriptRead8(gBattlescriptCurrInstr + 1), jump_loc) == 0) + gBattlescriptCurrInstr += 6; +} + +static void atk8A_normalisebuffs(void) //haze +{ + int i, j; + for (i = 0; i < gNoOfAllBanks; i++) + { + for (j = 0; j < 8; j++) + { + gBattleMons[i].statStages[j] = 6; + } + } + gBattlescriptCurrInstr++; +} + +static void atk8B_setbide(void) +{ + gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS; + gLockedMove[gBankAttacker] = gCurrentMove; + gTakenDmg[gBankAttacker] = 0; + gBattleMons[gBankAttacker].status2 |= (STATUS2_BIDE - 0x100); //2 turns + gBattlescriptCurrInstr++; +} + +static void atk8C_confuseifrepeatingattackends(void) +{ + if (!(gBattleMons[gBankAttacker].status2 & STATUS2_LOCK_CONFUSE)) + gBattleCommunication[MOVE_EFFECT_BYTE] = 0x75; + gBattlescriptCurrInstr++; +} + +static void atk8D_setmultihit_counter(void) +{ + if (BSScriptRead8(gBattlescriptCurrInstr + 1)) + gMultiHitCounter = BSScriptRead8(gBattlescriptCurrInstr + 1); + else + { + gMultiHitCounter = Random() & 3; + if (gMultiHitCounter > 1) + gMultiHitCounter = (Random() & 3) + 2; + else + gMultiHitCounter += 2; + } + gBattlescriptCurrInstr += 2; +} + +static void atk8E_prepare_multihit(void) +{ + ewram[0x160e0] = 0xFD; + ewram[0x160e1] = 1; + ewram[0x160e2] = 1; + ewram[0x160e3] = 1; + ewram[0x160e4] = 0; + ewram[0x160e5] = 0xFF; + gBattlescriptCurrInstr++; +} + +static bool8 sub_80264C0(void) +{ + if (gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level) + { + ewram[gBankTarget + 0x16064] = gBattlePartyID[gBankTarget]; + } + else + { + u16 random = Random() & 0xFF; + if ((u32)((random * (gBattleMons[gBankAttacker].level + gBattleMons[gBankTarget].level) >> 8) + 1) <= (gBattleMons[gBankTarget].level / 4)) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + return 0; + } + ewram[gBankTarget + 0x16064] = gBattlePartyID[gBankTarget]; + } + gBattlescriptCurrInstr = gUnknown_081D90FC; + return 1; +} + +static void atk8F_forcerandomswitch(void) +{ + if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)) + { + u8 i; + struct Pokemon* party; + u8 valid; + u8 val; + if (!GetBankSide(gBankTarget)) + party = gPlayerParty; + else + party = gEnemyParty; + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + valid = 0; + val = 0; + if (sub_803FBFC(sub_803FC34(gBankTarget)) == 1) + val = 3; + for (i = val; i < val + 3; i++) + { + if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[i], MON_DATA_IS_EGG) + && GetMonData(&party[i], MON_DATA_HP) != 0) + valid++; + } + } + else + { + valid = 0; + for (i = 0; i < 6; i++) + { + if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[i], MON_DATA_IS_EGG) + && GetMonData(&party[i], MON_DATA_HP) != 0) + valid++; + } + } + + if ((valid < 2 && (gBattleTypeFlags & (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI)) != BATTLE_TYPE_DOUBLE) + || (valid < 3 && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI))) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else if (sub_80264C0()) + { +#define MON_CAN_BATTLE(mon) (((GetMonData(mon, MON_DATA_SPECIES) && GetMonData(mon, MON_DATA_IS_EGG) != 1 && GetMonData(mon, MON_DATA_HP)))) + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + do + { + val = Random() % 3; + if (sub_803FBFC(sub_803FC34(gBankTarget)) == 1) + i = val + 3; + else + i = val; + } while (i == gBattlePartyID[gBankTarget] || i == gBattlePartyID[gBankTarget ^ 2] || !MON_CAN_BATTLE(&party[i])); + } + else + { + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + do + { + i = Random() % 6; + } while (i == gBattlePartyID[gBankTarget] || i == gBattlePartyID[gBankTarget ^ 2] || !MON_CAN_BATTLE(&party[i])); + } + else + { + do + { + i = Random() % 6; + } while (i == gBattlePartyID[gBankTarget] || !MON_CAN_BATTLE(&party[i])); + } + } + ewram[gBankTarget + 0x16068] = i; + if (!IsLinkDoubleBattle()) + sub_8012258(gBankTarget); + sub_8094B6C(gBankTarget, i, 0); + sub_8094B6C(gBankTarget ^ 2, i, 1); +#undef MON_CAN_BATTLE + } + } + else + { + sub_80264C0(); + } +} + +static void atk90_conversion_type_change(void) +{ + //randomly changes user's type to one of its moves' type + u8 valid_moves = 0; + u8 checked_move; + u8 move_type; + while (valid_moves < 4) + { + if (gBattleMons[gBankAttacker].moves[valid_moves] == 0) + break; + valid_moves++; + } + + for (checked_move = 0; checked_move < valid_moves; checked_move++) + { + move_type = gBattleMoves[gBattleMons[gBankAttacker].moves[checked_move]].type; + if (move_type == TYPE_MYSTERY) + { + if (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST) + move_type = TYPE_GHOST; + else + move_type = TYPE_NORMAL; + } + if (move_type != gBattleMons[gBankAttacker].type1 && move_type != gBattleMons[gBankAttacker].type2) + break; + } + + if (checked_move == valid_moves) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + do + { + + while ((checked_move = Random() & 3) >= valid_moves); + + move_type = gBattleMoves[gBattleMons[gBankAttacker].moves[checked_move]].type; + if (move_type == TYPE_MYSTERY) + { + if (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST) + move_type = TYPE_GHOST; + else + move_type = TYPE_NORMAL; + } + } while (move_type == gBattleMons[gBankAttacker].type1 || move_type == gBattleMons[gBankAttacker].type2); + + gBattleMons[gBankAttacker].type1 = move_type; + gBattleMons[gBankAttacker].type2 = move_type; + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 3; + gBattleTextBuff1[2] = move_type; + gBattleTextBuff1[3] = 0xFF; + + gBattlescriptCurrInstr += 5; + } +} + +static void atk91_givepaydaymoney(void) +{ + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK) && gPaydayMoney) + { + AddMoney(&gSaveBlock1.money, gPaydayMoney * BATTLE_STRUCT->moneyMultiplier); + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 1; + gBattleTextBuff1[2] = 2; + gBattleTextBuff1[3] = 5; + gBattleTextBuff1[4] = gPaydayMoney; + gBattleTextBuff1[5] = uBYTE1_16(gPaydayMoney); + gBattleTextBuff1[6] = 0xFF; + b_movescr_stack_push(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = gUnknown_081D95DB; + } + else + gBattlescriptCurrInstr++; +} + +static void atk92_setlightscreen(void) +{ + if (gSideAffecting[GetBankIdentity(gBankAttacker) & 1] & SIDE_STATUS_LIGHTSCREEN) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + else + { + gSideAffecting[GetBankIdentity(gBankAttacker) & 1] |= SIDE_STATUS_LIGHTSCREEN; + gSideTimer[GetBankIdentity(gBankAttacker) & 1].lightscreenTimer = 5; + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMons(1) == 2) + gBattleCommunication[MULTISTRING_CHOOSER] = 4; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 3; + } + gBattlescriptCurrInstr++; +} + +#ifdef NOTMATCHING +static void atk93_ko_move(void) +{ + if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY) + hold_effect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam; + else + { + hold_effect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item); + quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item); + } + + gStringBank = gBankTarget; + + if (hold_effect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality) + { + RecordItemBattle(gBankTarget, hold_effect); + gSpecialStatuses[gBankTarget].focusBanded = 1; + } + + if (gBattleMons[gBankTarget].ability == ABILITY_STURDY) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gLastUsedAbility = ABILITY_STURDY; + gBattlescriptCurrInstr = x; + RecordAbilityBattle(gBankTarget, ABILITY_STURDY); + return; + } + + if (!(gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS)) + { + u16 to_cmp = gBattleMons[gBankAttacker].level - gBattleMons[gBankTarget].level + gBattleMoves[gCurrentMove].accuracy; + if (Random() % 0x64 + 1 < to_cmp || gBattleMons[gBankAttacker].level < gBattleMons[gBankTarget].level) + { + goto MOVESTATUS_MISSED_LABEL; + } + } + else + { + if (gDisableStructs[gBankTarget].bankWithSureHit != gBankAttacker || gBattleMons[gBankAttacker].level < gBattleMons[gBankTarget].level) + { + + } + } + +MOVESTATUS_MISSED_LABEL: + gBattleTypeFlags |= MOVESTATUS_MISSED; + if (gBattleMons[gBankAttacker].level < gBattleMons[gBankTarget].level) + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +#else +__attribute((naked)) +static void atk93_ko_move(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + ldr r7, _08026BA8 @ =gBattleMons\n\ + ldr r6, _08026BAC @ =gBankTarget\n\ + ldrb r2, [r6]\n\ + movs r5, 0x58\n\ + adds r0, r2, 0\n\ + muls r0, r5\n\ + adds r1, r0, r7\n\ + ldrh r0, [r1, 0x2E]\n\ + cmp r0, 0xAF\n\ + bne _08026BB4\n\ + ldr r1, _08026BB0 @ =gEnigmaBerries\n\ + lsls r0, r2, 3\n\ + subs r0, r2\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r4, [r0, 0x7]\n\ + ldrb r6, [r0, 0x1A]\n\ + b _08026BCE\n\ + .align 2, 0\n\ +_08026BA8: .4byte gBattleMons\n\ +_08026BAC: .4byte gBankTarget\n\ +_08026BB0: .4byte gEnigmaBerries\n\ +_08026BB4:\n\ + ldrh r0, [r1, 0x2E]\n\ + bl ItemId_GetHoldEffect\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + ldrb r0, [r6]\n\ + muls r0, r5\n\ + adds r0, r7\n\ + ldrh r0, [r0, 0x2E]\n\ + bl ItemId_GetHoldEffectParam\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ +_08026BCE:\n\ + ldr r1, _08026C4C @ =gStringBank\n\ + ldr r5, _08026C50 @ =gBankTarget\n\ + ldrb r0, [r5]\n\ + strb r0, [r1]\n\ + cmp r4, 0x27\n\ + bne _08026C0C\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x64\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, r6\n\ + bcs _08026C0C\n\ + ldrb r0, [r5]\n\ + movs r1, 0x27\n\ + bl RecordItemBattle\n\ + ldr r2, _08026C54 @ =gSpecialStatuses\n\ + ldrb r1, [r5]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldrb r1, [r0]\n\ + movs r2, 0x80\n\ + orrs r1, r2\n\ + strb r1, [r0]\n\ +_08026C0C:\n\ + ldr r0, _08026C58 @ =gBattleMons\n\ + mov r8, r0\n\ + ldr r1, _08026C50 @ =gBankTarget\n\ + ldrb r2, [r1]\n\ + movs r6, 0x58\n\ + adds r0, r2, 0\n\ + muls r0, r6\n\ + mov r3, r8\n\ + adds r5, r0, r3\n\ + adds r0, r5, 0\n\ + adds r0, 0x20\n\ + ldrb r3, [r0]\n\ + mov r10, r8\n\ + cmp r3, 0x5\n\ + bne _08026C6C\n\ + ldr r2, _08026C5C @ =gBattleMoveFlags\n\ + ldrb r0, [r2]\n\ + movs r1, 0x1\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r0, _08026C60 @ =gLastUsedAbility\n\ + strb r3, [r0]\n\ + ldr r1, _08026C64 @ =gBattlescriptCurrInstr\n\ + ldr r0, _08026C68 @ =gUnknown_081D9826\n\ + str r0, [r1]\n\ + ldr r1, _08026C50 @ =gBankTarget\n\ + ldrb r0, [r1]\n\ + movs r1, 0x5\n\ + bl RecordAbilityBattle\n\ + b _08026E40\n\ + .align 2, 0\n\ +_08026C4C: .4byte gStringBank\n\ +_08026C50: .4byte gBankTarget\n\ +_08026C54: .4byte gSpecialStatuses\n\ +_08026C58: .4byte gBattleMons\n\ +_08026C5C: .4byte gBattleMoveFlags\n\ +_08026C60: .4byte gLastUsedAbility\n\ +_08026C64: .4byte gBattlescriptCurrInstr\n\ +_08026C68: .4byte gUnknown_081D9826\n\ +_08026C6C:\n\ + ldr r1, _08026CE0 @ =gStatuses3\n\ + lsls r0, r2, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x18\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _08026CF4\n\ + ldr r1, _08026CE4 @ =gBattleMoves\n\ + ldr r0, _08026CE8 @ =gCurrentMove\n\ + ldrh r0, [r0]\n\ + lsls r2, r0, 1\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r1\n\ + ldr r7, _08026CEC @ =gBankAttacker\n\ + ldrb r0, [r7]\n\ + muls r0, r6\n\ + add r0, r10\n\ + adds r0, 0x2A\n\ + ldrb r0, [r0]\n\ + adds r1, r5, 0\n\ + adds r1, 0x2A\n\ + ldrb r1, [r1]\n\ + subs r0, r1\n\ + ldrb r2, [r2, 0x3]\n\ + adds r0, r2\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x64\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + adds r0, 0x1\n\ + cmp r0, r4\n\ + bge _08026CDC\n\ + ldrb r0, [r7]\n\ + adds r1, r0, 0\n\ + muls r1, r6\n\ + add r1, r10\n\ + adds r1, 0x2A\n\ + ldr r2, _08026CF0 @ =gBankTarget\n\ + ldrb r0, [r2]\n\ + muls r0, r6\n\ + add r0, r10\n\ + adds r0, 0x2A\n\ + ldrb r1, [r1]\n\ + movs r4, 0x1\n\ + ldrb r0, [r0]\n\ + cmp r1, r0\n\ + bcs _08026D20\n\ +_08026CDC:\n\ + mov r10, r8\n\ + b _08026DE0\n\ + .align 2, 0\n\ +_08026CE0: .4byte gStatuses3\n\ +_08026CE4: .4byte gBattleMoves\n\ +_08026CE8: .4byte gCurrentMove\n\ +_08026CEC: .4byte gBankAttacker\n\ +_08026CF0: .4byte gBankTarget\n\ +_08026CF4:\n\ + ldr r0, _08026D4C @ =gDisableStructs\n\ + lsls r1, r2, 3\n\ + subs r1, r2\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + ldr r2, _08026D50 @ =gBankAttacker\n\ + ldrb r0, [r1, 0x15]\n\ + movs r4, 0\n\ + ldrb r3, [r2]\n\ + cmp r0, r3\n\ + bne _08026D20\n\ + ldrb r0, [r2]\n\ + muls r0, r6\n\ + add r0, r10\n\ + adds r0, 0x2A\n\ + adds r1, r5, 0\n\ + adds r1, 0x2A\n\ + ldrb r0, [r0]\n\ + ldrb r1, [r1]\n\ + cmp r0, r1\n\ + bcc _08026D20\n\ + movs r4, 0x1\n\ +_08026D20:\n\ + cmp r4, 0\n\ + beq _08026DE0\n\ + ldr r0, _08026D54 @ =gProtectStructs\n\ + ldr r1, _08026D58 @ =gBankTarget\n\ + ldrb r2, [r1]\n\ + lsls r1, r2, 4\n\ + adds r1, r0\n\ + ldrb r0, [r1]\n\ + lsls r0, 30\n\ + cmp r0, 0\n\ + bge _08026D64\n\ + ldr r1, _08026D5C @ =gBattleMoveDamage\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + add r0, r10\n\ + ldrh r0, [r0, 0x28]\n\ + subs r0, 0x1\n\ + str r0, [r1]\n\ + ldr r2, _08026D60 @ =gBattleMoveFlags\n\ + ldrb r0, [r2]\n\ + movs r1, 0x40\n\ + b _08026DC6\n\ + .align 2, 0\n\ +_08026D4C: .4byte gDisableStructs\n\ +_08026D50: .4byte gBankAttacker\n\ +_08026D54: .4byte gProtectStructs\n\ +_08026D58: .4byte gBankTarget\n\ +_08026D5C: .4byte gBattleMoveDamage\n\ +_08026D60: .4byte gBattleMoveFlags\n\ +_08026D64:\n\ + ldr r0, _08026DA0 @ =gSpecialStatuses\n\ + lsls r1, r2, 2\n\ + adds r1, r2\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + ldrb r0, [r1]\n\ + lsrs r0, 7\n\ + cmp r0, 0\n\ + beq _08026DB4\n\ + ldr r1, _08026DA4 @ =gBattleMoveDamage\n\ + movs r3, 0x58\n\ + adds r0, r2, 0\n\ + muls r0, r3\n\ + add r0, r10\n\ + ldrh r0, [r0, 0x28]\n\ + subs r0, 0x1\n\ + str r0, [r1]\n\ + ldr r2, _08026DA8 @ =gBattleMoveFlags\n\ + ldrb r0, [r2]\n\ + movs r1, 0x80\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r1, _08026DAC @ =gLastUsedItem\n\ + ldr r2, _08026DB0 @ =gBankTarget\n\ + ldrb r0, [r2]\n\ + muls r0, r3\n\ + add r0, r10\n\ + ldrh r0, [r0, 0x2E]\n\ + strh r0, [r1]\n\ + b _08026DCA\n\ + .align 2, 0\n\ +_08026DA0: .4byte gSpecialStatuses\n\ +_08026DA4: .4byte gBattleMoveDamage\n\ +_08026DA8: .4byte gBattleMoveFlags\n\ +_08026DAC: .4byte gLastUsedItem\n\ +_08026DB0: .4byte gBankTarget\n\ +_08026DB4:\n\ + ldr r1, _08026DD4 @ =gBattleMoveDamage\n\ + movs r0, 0x58\n\ + muls r0, r2\n\ + add r0, r10\n\ + ldrh r0, [r0, 0x28]\n\ + str r0, [r1]\n\ + ldr r2, _08026DD8 @ =gBattleMoveFlags\n\ + ldrb r0, [r2]\n\ + movs r1, 0x10\n\ +_08026DC6:\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ +_08026DCA:\n\ + ldr r1, _08026DDC @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x5\n\ + str r0, [r1]\n\ + b _08026E40\n\ + .align 2, 0\n\ +_08026DD4: .4byte gBattleMoveDamage\n\ +_08026DD8: .4byte gBattleMoveFlags\n\ +_08026DDC: .4byte gBattlescriptCurrInstr\n\ +_08026DE0:\n\ + ldr r2, _08026E10 @ =gBattleMoveFlags\n\ + ldrb r0, [r2]\n\ + movs r1, 0x1\n\ + orrs r0, r1\n\ + strb r0, [r2]\n\ + ldr r0, _08026E14 @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + movs r2, 0x58\n\ + adds r1, r0, 0\n\ + muls r1, r2\n\ + add r1, r10\n\ + adds r1, 0x2A\n\ + ldr r3, _08026E18 @ =gBankTarget\n\ + ldrb r0, [r3]\n\ + muls r0, r2\n\ + add r0, r10\n\ + adds r0, 0x2A\n\ + ldrb r1, [r1]\n\ + ldrb r0, [r0]\n\ + cmp r1, r0\n\ + bcc _08026E20\n\ + ldr r1, _08026E1C @ =gBattleCommunication\n\ + movs r0, 0\n\ + b _08026E24\n\ + .align 2, 0\n\ +_08026E10: .4byte gBattleMoveFlags\n\ +_08026E14: .4byte gBankAttacker\n\ +_08026E18: .4byte gBankTarget\n\ +_08026E1C: .4byte gBattleCommunication\n\ +_08026E20:\n\ + ldr r1, _08026E50 @ =gBattleCommunication\n\ + movs r0, 0x1\n\ +_08026E24:\n\ + strb r0, [r1, 0x5]\n\ + ldr r3, _08026E54 @ =gBattlescriptCurrInstr\n\ + ldr r2, [r3]\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2, 0x2]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 16\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + lsls r0, 24\n\ + orrs r1, r0\n\ + str r1, [r3]\n\ +_08026E40:\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08026E50: .4byte gBattleCommunication\n\ +_08026E54: .4byte gBattlescriptCurrInstr\n\ + .syntax divided"); +} +#endif // NOTMATCHING + +static void atk94_gethalfcurrentenemyhp(void) //super fang +{ + gBattleMoveDamage = gBattleMons[gBankTarget].hp / 2; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattlescriptCurrInstr++; +} + +static void atk95_setsandstorm(void) +{ + if (gBattleWeather & WEATHER_SANDSTORM_ANY) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else + { + gBattleWeather = WEATHER_SANDSTORM_TEMPORARY; + gBattleCommunication[MULTISTRING_CHOOSER] = 3; + gWishFutureKnock.weatherDuration = 5; + } + gBattlescriptCurrInstr++; +} + +static void atk96_weatherdamage(void) +{ + if (WEATHER_HAS_EFFECT) + { + if (gBattleWeather & WEATHER_SANDSTORM_ANY) + { + if (gBattleMons[gBankAttacker].type1 != TYPE_ROCK && gBattleMons[gBankAttacker].type1 != TYPE_STEEL && gBattleMons[gBankAttacker].type1 != TYPE_GROUND + && gBattleMons[gBankAttacker].type2 != TYPE_ROCK && gBattleMons[gBankAttacker].type2 != TYPE_STEEL && gBattleMons[gBankAttacker].type2 != TYPE_GROUND + && gBattleMons[gBankAttacker].ability != ABILITY_SAND_VEIL && !(gStatuses3[gBankAttacker] & STATUS3_UNDERGROUND) && !(gStatuses3[gBankAttacker] & STATUS3_UNDERWATER)) + { + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } + else + { + gBattleMoveDamage = 0; + } + } + if (gBattleWeather & WEATHER_HAIL) + { + if (gBattleMons[gBankAttacker].type1 != TYPE_ICE && gBattleMons[gBankAttacker].type2 != TYPE_ICE && !(gStatuses3[gBankAttacker] & STATUS3_UNDERGROUND) && !(gStatuses3[gBankAttacker] & STATUS3_UNDERWATER)) + { + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } + else + { + gBattleMoveDamage = 0; + } + } + } + else + gBattleMoveDamage = 0; + + if (gAbsentBankFlags & gBitTable[gBankAttacker]) + gBattleMoveDamage = 0; + + gBattlescriptCurrInstr++; +} + +static void atk97_try_infatuation(void) +{ + struct Pokemon *attacker, *target; + u16 atk_species, def_species; + u32 atk_pid, def_pid; + if (!GetBankSide(gBankAttacker)) + attacker = &gPlayerParty[gBattlePartyID[gBankAttacker]]; + else + attacker = &gEnemyParty[gBattlePartyID[gBankAttacker]]; + + if (!GetBankSide(gBankTarget)) + target = &gPlayerParty[gBattlePartyID[gBankTarget]]; + else + target = &gEnemyParty[gBattlePartyID[gBankTarget]]; + + atk_species = GetMonData(attacker, MON_DATA_SPECIES); + atk_pid = GetMonData(attacker, MON_DATA_PERSONALITY); + + def_species = GetMonData(target, MON_DATA_SPECIES); + def_pid = GetMonData(target, MON_DATA_PERSONALITY); + + if (gBattleMons[gBankTarget].ability == ABILITY_OBLIVIOUS) + { + gBattlescriptCurrInstr = BattleScript_ObliviousPreventsAttraction; + gLastUsedAbility = ABILITY_OBLIVIOUS; + RecordAbilityBattle(gBankTarget, ABILITY_OBLIVIOUS); + } + else + { + if (GetGenderFromSpeciesAndPersonality(atk_species, atk_pid) == GetGenderFromSpeciesAndPersonality(def_species, def_pid) + || gStatuses3[gBankTarget] & STATUS3_SEMI_INVULNERABLE || gBattleMons[gBankTarget].status2 & STATUS2_INFATUATION || GetGenderFromSpeciesAndPersonality(atk_species, atk_pid) == 0xFF + || GetGenderFromSpeciesAndPersonality(def_species, def_pid) == 0xFF) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + gBattleMons[gBankTarget].status2 |= (gBitTable[gBankAttacker] << 16); + gBattlescriptCurrInstr += 5; + } + } +} + +static void atk98_status_icon_update(void) +{ + if (gBattleExecBuffer) + return; + + if (BSScriptRead8(gBattlescriptCurrInstr + 1) != 4) + { + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 2; + } + else + { + gActiveBank = gBankAttacker; + if (!(gAbsentBankFlags & gBitTable[gActiveBank])) + { + EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2); + MarkBufferBankForExecution(gActiveBank); + } + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + gActiveBank = GetBankByPlayerAI(GetBankIdentity(gBankAttacker) ^ 2); + if (!(gAbsentBankFlags & gBitTable[gActiveBank])) + { + EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2); + MarkBufferBankForExecution(gActiveBank); + } + } + gBattlescriptCurrInstr += 2; + } +} + +static void atk99_setmist(void) +{ + if (gSideTimer[GetBankIdentity(gBankAttacker) & 1].mistTimer) + { + gBattleMoveFlags |= MOVESTATUS_FAILED; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else + { + gSideTimer[GetBankIdentity(gBankAttacker) & 1].mistTimer = 5; + gSideAffecting[GetBankIdentity(gBankAttacker) & 1] |= SIDE_STATUS_MIST; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + gBattlescriptCurrInstr++; +} + +static void atk9A_set_focusenergy(void) +{ + if (gBattleMons[gBankAttacker].status2 & STATUS2_FOCUS_ENERGY) + { + gBattleMoveFlags |= MOVESTATUS_FAILED; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else + { + gBattleMons[gBankAttacker].status2 |= STATUS2_FOCUS_ENERGY; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + gBattlescriptCurrInstr++; +} + +static void atk9B_transformdataexecution(void) +{ + gUnknown_02024BE8 = 0xFFFF; + gBattlescriptCurrInstr++; + if (gBattleMons[gBankTarget].status2 & STATUS2_TRANSFORMED || gStatuses3[gBankTarget] & STATUS3_SEMI_INVULNERABLE) + { + gBattleMoveFlags |= MOVESTATUS_FAILED; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else + { + u32 i; s32 j; + u8 *atk_data, *def_data; + gBattleMons[gBankAttacker].status2 |= STATUS2_TRANSFORMED; + gDisableStructs[gBankAttacker].disabledMove = 0; + gDisableStructs[gBankAttacker].disableTimer1 = 0; + gDisableStructs[gBankAttacker].unk0 = gBattleMons[gBankTarget].personality; + gDisableStructs[gBankAttacker].unk18_b = 0; + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 6; + gBattleTextBuff1[2] = (gBattleMons[gBankTarget].species); + gBattleTextBuff1[3] = uBYTE1_16(gBattleMons[gBankTarget].species); + gBattleTextBuff1[4] = 0xFF; + + atk_data = (u8*)(&gBattleMons[gBankAttacker]); + def_data = (u8*)(&gBattleMons[gBankTarget]); + + for (i = 0; i < 0x24; i++) + atk_data[i] = def_data[i]; + + for (j = 0; j < 4; j++) + { + if (gBattleMoves[gBattleMons[gBankAttacker].moves[j]].pp < 5) + gBattleMons[gBankAttacker].pp[j] = gBattleMoves[gBattleMons[gBankAttacker].moves[j]].pp; + else + gBattleMons[gBankAttacker].pp[j] = 5; + } + + gActiveBank = gBankAttacker; + EmitResetActionMoveSelection(0, 2); + MarkBufferBankForExecution(gActiveBank); + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } +} + +static void atk9C_set_substitute(void) +{ + u32 hp = gBattleMons[gBankAttacker].maxHP / 4; + if (gBattleMons[gBankAttacker].maxHP / 4 == 0) + hp = 1; + if (gBattleMons[gBankAttacker].hp <= hp) + { + gBattleMoveDamage = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else + { + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMons[gBankAttacker].status2 |= STATUS2_SUBSTITUTE; + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_WRAPPED); + gDisableStructs[gBankAttacker].substituteHP = gBattleMoveDamage; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE; + } + gBattlescriptCurrInstr++; +} + +static bool8 IsMoveUncopyable(u16 move) +{ + int i; + for (i = 0; sUnknown_081FACFE[i] != 0xFFFE && sUnknown_081FACFE[i] != move; i++) {} + return (sUnknown_081FACFE[i] != 0xFFFE); +} + +static void atk9D_copyattack(void) +{ + gUnknown_02024BE8 = 0xFFFF; + if (IsMoveUncopyable(gLastUsedMove[gBankTarget]) || gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED + || gLastUsedMove[gBankTarget] == 0 || gLastUsedMove[gBankTarget] == 0xFFFF) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + int i; + for (i = 0; i < 4; i++) + { + if (gBattleMons[gBankAttacker].moves[i] == gLastUsedMove[gBankTarget]) + break; + } + if (i == 4) + { + gBattleMons[gBankAttacker].moves[gCurrMovePos] = gLastUsedMove[gBankTarget]; + if (gBattleMoves[gLastUsedMove[gBankTarget]].pp < 5) + gBattleMons[gBankAttacker].pp[gCurrMovePos] = gBattleMoves[gLastUsedMove[gBankTarget]].pp; + else + gBattleMons[gBankAttacker].pp[gCurrMovePos] = 5; + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = gLastUsedMove[gBankTarget]; + gBattleTextBuff1[3] = uBYTE1_16(gLastUsedMove[gBankTarget]); + gBattleTextBuff1[4] = 0xFF; + + gDisableStructs[gBankAttacker].unk18_b |= gBitTable[gCurrMovePos]; + gBattlescriptCurrInstr += 5; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +#ifdef NONMATCHING +static void atk9E_metronome(void) +{ + // sUnknown_081FACFE + int i; + do + { + while ((gCurrentMove = (Random() & 0x1FF) + 1) > 0x162); + for (i = 0; sUnknown_081FACFE[i] != gCurrentMove && sUnknown_081FACFE[i] != 0xFFFF; i++); + } while (sUnknown_081FACFE[i] != 0xFFFF); + + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + gBattlescriptCurrInstr = gBattleScriptsEffectsTable[gBattleMoves[gCurrentMove].effect]; + gBankTarget = GetMoveTarget(gCurrentMove, 0); +} + +#else +__attribute__((naked)) +static void atk9E_metronome(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + ldr r7, _08027938 @ =gCurrentMove\n\ + movs r6, 0xB1\n\ + lsls r6, 1\n\ + ldr r5, _0802793C @ =sUnknown_081FACFE\n\ + ldr r0, _08027940 @ =gBattlescriptCurrInstr\n\ + mov r8, r0\n\ +_080278CA:\n\ + bl Random\n\ + ldr r2, _08027944 @ =0x000001ff\n\ + adds r1, r2, 0\n\ + ands r0, r1\n\ + adds r0, 0x1\n\ + strh r0, [r7]\n\ + cmp r0, r6\n\ + bhi _080278CA\n\ + movs r0, 0x3\n\ +_080278DE:\n\ + subs r0, 0x1\n\ + cmp r0, 0\n\ + bge _080278DE\n\ + ldr r4, _08027938 @ =gCurrentMove\n\ + ldrh r2, [r4]\n\ + ldr r3, _08027948 @ =0x0000ffff\n\ + subs r0, r5, 0x2\n\ +_080278EC:\n\ + adds r0, 0x2\n\ + ldrh r1, [r0]\n\ + cmp r1, r2\n\ + beq _080278F8\n\ + cmp r1, r3\n\ + bne _080278EC\n\ +_080278F8:\n\ + ldr r0, _08027948 @ =0x0000ffff\n\ + cmp r1, r0\n\ + bne _080278CA\n\ + ldr r2, _0802794C @ =gHitMarker\n\ + ldr r0, [r2]\n\ + ldr r1, _08027950 @ =0xfffffbff\n\ + ands r0, r1\n\ + str r0, [r2]\n\ + ldr r3, _08027954 @ =gBattleScriptsEffectsTable\n\ + ldr r2, _08027958 @ =gBattleMoves\n\ + ldrh r1, [r4]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldrb r0, [r0]\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldr r0, [r0]\n\ + mov r1, r8\n\ + str r0, [r1]\n\ + ldrh r0, [r4]\n\ + movs r1, 0\n\ + bl GetMoveTarget\n\ + ldr r1, _0802795C @ =gBankTarget\n\ + strb r0, [r1]\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08027938: .4byte gCurrentMove\n\ +_0802793C: .4byte sUnknown_081FACFE\n\ +_08027940: .4byte gBattlescriptCurrInstr\n\ +_08027944: .4byte 0x000001ff\n\ +_08027948: .4byte 0x0000ffff\n\ +_0802794C: .4byte gHitMarker\n\ +_08027950: .4byte 0xfffffbff\n\ +_08027954: .4byte gBattleScriptsEffectsTable\n\ +_08027958: .4byte gBattleMoves\n\ +_0802795C: .4byte gBankTarget\n\ + .syntax divided"); +} +#endif // NONMATCHING + +static void atk9F_dmgtolevel(void) +{ + gBattleMoveDamage = gBattleMons[gBankAttacker].level; + gBattlescriptCurrInstr++; +} + +static void atkA0_psywavedamageeffect(void) +{ + s32 rand_dmg; + while ((rand_dmg = (Random() & 0xF)) > 0xA); + rand_dmg *= 10; + gBattleMoveDamage = gBattleMons[gBankAttacker].level * (rand_dmg + 50) / 100; + gBattlescriptCurrInstr++; +} + +static void atkA1_counterdamagecalculator(void) +{ + u8 atk_side = GetBankSide(gBankAttacker); + u8 def_side = GetBankSide(gProtectStructs[gBankAttacker].physicalBank); + if (gProtectStructs[gBankAttacker].physicalDmg && atk_side != def_side && gBattleMons[gProtectStructs[gBankAttacker].physicalBank].hp) + { + gBattleMoveDamage = gProtectStructs[gBankAttacker].physicalDmg * 2; + if (gSideTimer[def_side].followmeTimer && gBattleMons[gSideTimer[def_side].followmeTarget].hp) + gBankTarget = gSideTimer[def_side].followmeTarget; + else + gBankTarget = gProtectStructs[gBankAttacker].physicalBank; + gBattlescriptCurrInstr += 5; + } + else + { + gSpecialStatuses[gBankAttacker].flag20 = 1; + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +static void atkA2_mirrorcoatdamagecalculator(void) //a copy of atkA1 with the physical -> special field changes +{ + u8 atk_side = GetBankSide(gBankAttacker); + u8 def_side = GetBankSide(gProtectStructs[gBankAttacker].specialBank); + if (gProtectStructs[gBankAttacker].specialDmg && atk_side != def_side && gBattleMons[gProtectStructs[gBankAttacker].specialBank].hp) + { + gBattleMoveDamage = gProtectStructs[gBankAttacker].specialDmg * 2; + if (gSideTimer[def_side].followmeTimer && gBattleMons[gSideTimer[def_side].followmeTarget].hp) + gBankTarget = gSideTimer[def_side].followmeTarget; + else + gBankTarget = gProtectStructs[gBankAttacker].specialBank; + gBattlescriptCurrInstr += 5; + } + else + { + gSpecialStatuses[gBankAttacker].flag20 = 1; + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +static void atkA3_disablelastusedattack(void) +{ + int i; + for (i = 0; i < 4; i++) + { + if (gBattleMons[gBankTarget].moves[i] == gLastUsedMove[gBankTarget]) + break; + } + if (gDisableStructs[gBankTarget].disabledMove == 0 && i != 4 && gBattleMons[gBankTarget].pp[i] != 0) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = gBattleMons[gBankTarget].moves[i]; + gBattleTextBuff1[3] = uBYTE1_16(gBattleMons[gBankTarget].moves[i]); + gBattleTextBuff1[4] = 0xFF; + + gDisableStructs[gBankTarget].disabledMove = gBattleMons[gBankTarget].moves[i]; + gDisableStructs[gBankTarget].disableTimer1 = (Random() & 3) + 2; + gDisableStructs[gBankTarget].disableTimer2 = gDisableStructs[gBankTarget].disableTimer1; //that's interesting + gBattlescriptCurrInstr += 5; + } + else + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +static void atkA4_setencore(void) +{ + int i; + for (i = 0; i < 4; i++) + { + if (gBattleMons[gBankTarget].moves[i] == gLastUsedMove[gBankTarget]) + break; + } + if (gLastUsedMove[gBankTarget] == MOVE_STRUGGLE || gLastUsedMove[gBankTarget] == MOVE_ENCORE || gLastUsedMove[gBankTarget] == MOVE_MIRROR_MOVE) + i = 4; + if (gDisableStructs[gBankTarget].encoredMove == 0 && i != 4 && gBattleMons[gBankTarget].pp[i] != 0) + { + gDisableStructs[gBankTarget].encoredMove = gBattleMons[gBankTarget].moves[i]; + gDisableStructs[gBankTarget].encoredMovePos = i; + gDisableStructs[gBankTarget].encoreTimer1 = (Random() & 3) + 3; + gDisableStructs[gBankTarget].encoreTimer2 = gDisableStructs[gBankTarget].encoreTimer1; + gBattlescriptCurrInstr += 5; + } + else + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +static void atkA5_painsplitdmgcalc(void) +{ + if (!(gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)) + { + s32 hp_diff = (gBattleMons[gBankAttacker].hp + gBattleMons[gBankTarget].hp) / 2; + s32 to_store = gBattleMoveDamage = gBattleMons[gBankTarget].hp - hp_diff; + BATTLE_STRUCT->unk16014 = sBYTE0_32(to_store); + BATTLE_STRUCT->unk16015 = sBYTE1_32(to_store); + BATTLE_STRUCT->unk16016 = sBYTE2_32(to_store); + BATTLE_STRUCT->unk16017 = sBYTE3_32(to_store); + + gBattleMoveDamage = gBattleMons[gBankAttacker].hp - hp_diff; + gSpecialStatuses[gBankTarget].moveturnLostHP = 0xFFFF; + + gBattlescriptCurrInstr += 5; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +#ifdef NONMATCHING +static void atkA6_settypetorandomresistance(void) +{ + if (gMoveHitWith[gBankAttacker] == 0 || gMoveHitWith[gBankAttacker] == 0xFFFF || (IsTwoTurnsMove(gMoveHitWith[gBankAttacker]) && !gProtectStructs[gBankAttacker].physicalDmg && !gProtectStructs[gBankAttacker].specialDmg)) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + int type = 0, rands = 0; + do + { + while (((type = (Random() & 0x7F)) > 0x70)); + type *= 3; + if (gTypeEffectiveness[type] == gUnknown_02024C44[gBankAttacker] && gTypeEffectiveness[type + 2] <= 5 && gBattleMons[gBankAttacker].type1 != gTypeEffectiveness[type + 1] && gBattleMons[gBankAttacker].type2 != gTypeEffectiveness[type + 1]) + { + gBattleMons[gBankAttacker].type1 = type; + gBattleMons[gBankAttacker].type2 = type; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 3; + gBattleTextBuff1[2] = type; + gBattleTextBuff1[3] = 0xFF; + gBattlescriptCurrInstr += 5; + return; + } + rands++; + } while (rands <= 999); + + type = 0, rands = 0; + do + { + if (gTypeEffectiveness[type] == 0xFE || gTypeEffectiveness[type] != 0xFF) + { + if (gTypeEffectiveness[type] == gUnknown_02024C44[gBankAttacker] && gTypeEffectiveness[type + 2] <= 5 && gBattleMons[gBankAttacker].type1 != gTypeEffectiveness[type + 1] && gBattleMons[gBankAttacker].type2 != gTypeEffectiveness[type + 1]) + { + gBattleMons[gBankAttacker].type1 = gTypeEffectiveness[rands + 1]; + gBattleMons[gBankAttacker].type2 = gTypeEffectiveness[rands + 1]; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 3; + gBattleTextBuff1[2] = gTypeEffectiveness[rands + 1]; + gBattleTextBuff1[3] = 0xFF; + gBattlescriptCurrInstr += 5; + return; + } + } + type += 3, rands += 3; + } while (rands < 336); + + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +#else +__attribute__((naked)) +static void atkA6_settypetorandomresistance(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + ldr r1, _08027FA8 @ =gMoveHitWith\n\ + ldr r4, _08027FAC @ =gBankAttacker\n\ + ldrb r0, [r4]\n\ + lsls r0, 1\n\ + adds r2, r0, r1\n\ + ldrh r1, [r2]\n\ + cmp r1, 0\n\ + beq _08027F8C\n\ + ldr r0, _08027FB0 @ =0x0000ffff\n\ + cmp r1, r0\n\ + beq _08027F8C\n\ + ldrh r0, [r2]\n\ + bl IsTwoTurnsMove\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08028024\n\ + ldr r2, _08027FB4 @ =gProtectStructs\n\ + ldrb r0, [r4]\n\ + lsls r1, r0, 4\n\ + adds r0, r2, 0x4\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08028024\n\ + adds r0, r2, 0\n\ + adds r0, 0x8\n\ + adds r0, r1, r0\n\ + ldr r0, [r0]\n\ + cmp r0, 0\n\ + bne _08028024\n\ +_08027F8C:\n\ + ldr r3, _08027FB8 @ =gBattlescriptCurrInstr\n\ + ldr r2, [r3]\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2, 0x2]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 16\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + lsls r0, 24\n\ + orrs r1, r0\n\ + str r1, [r3]\n\ + b _08028110\n\ + .align 2, 0\n\ +_08027FA8: .4byte gMoveHitWith\n\ +_08027FAC: .4byte gBankAttacker\n\ +_08027FB0: .4byte 0x0000ffff\n\ +_08027FB4: .4byte gProtectStructs\n\ +_08027FB8: .4byte gBattlescriptCurrInstr\n\ +_08027FBC:\n\ + mov r0, r12\n\ + strb r5, [r0]\n\ + mov r1, r10\n\ + ldrb r0, [r1]\n\ + muls r0, r2\n\ + adds r0, r7\n\ + adds r0, 0x22\n\ + strb r5, [r0]\n\ + ldr r1, _08027FE0 @ =gBattleTextBuff1\n\ + movs r0, 0xFD\n\ + strb r0, [r1]\n\ + movs r0, 0x3\n\ + strb r0, [r1, 0x1]\n\ + strb r5, [r1, 0x2]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x3]\n\ + ldr r1, _08027FE4 @ =gBattlescriptCurrInstr\n\ + b _08028012\n\ + .align 2, 0\n\ +_08027FE0: .4byte gBattleTextBuff1\n\ +_08027FE4: .4byte gBattlescriptCurrInstr\n\ +_08027FE8:\n\ + mov r0, r8\n\ + adds r0, 0x1\n\ + adds r0, r3\n\ + ldrb r2, [r0]\n\ + strb r2, [r4]\n\ + mov r4, r10\n\ + ldrb r0, [r4]\n\ + muls r0, r6\n\ + ldr r7, _0802801C @ =gBattleMons\n\ + adds r0, r7\n\ + adds r0, 0x22\n\ + strb r2, [r0]\n\ + ldr r1, _08028020 @ =gBattleTextBuff1\n\ + movs r0, 0xFD\n\ + strb r0, [r1]\n\ + movs r0, 0x3\n\ + strb r0, [r1, 0x1]\n\ + strb r2, [r1, 0x2]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x3]\n\ + mov r1, r12\n\ +_08028012:\n\ + ldr r0, [r1]\n\ + adds r0, 0x5\n\ + str r0, [r1]\n\ + b _08028110\n\ + .align 2, 0\n\ +_0802801C: .4byte gBattleMons\n\ +_08028020: .4byte gBattleTextBuff1\n\ +_08028024:\n\ + movs r4, 0\n\ + mov r8, r4\n\ + movs r7, 0x7F\n\ + mov r9, r7\n\ +_0802802C:\n\ + bl Random\n\ + mov r4, r9\n\ + ands r4, r0\n\ + cmp r4, 0x70\n\ + bhi _0802802C\n\ + lsls r0, r4, 1\n\ + adds r4, r0, r4\n\ + ldr r6, _08028120 @ =gTypeEffectiveness\n\ + adds r3, r4, r6\n\ + ldr r1, _08028124 @ =gUnknown_02024C44\n\ + ldr r2, _08028128 @ =gBankAttacker\n\ + ldrb r5, [r2]\n\ + lsls r0, r5, 1\n\ + adds r0, r1\n\ + ldrb r1, [r3]\n\ + mov r10, r2\n\ + ldrh r0, [r0]\n\ + cmp r1, r0\n\ + bne _08028088\n\ + adds r0, r4, 0x2\n\ + adds r0, r6\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x5\n\ + bhi _08028088\n\ + ldr r7, _0802812C @ =gBattleMons\n\ + movs r2, 0x58\n\ + adds r0, r5, 0\n\ + muls r0, r2\n\ + adds r3, r0, r7\n\ + movs r0, 0x21\n\ + adds r0, r3\n\ + mov r12, r0\n\ + adds r0, r4, 0x1\n\ + adds r0, r6\n\ + ldrb r5, [r0]\n\ + mov r1, r12\n\ + ldrb r0, [r1]\n\ + adds r1, r5, 0\n\ + cmp r0, r1\n\ + beq _08028088\n\ + adds r0, r3, 0\n\ + adds r0, 0x22\n\ + ldrb r0, [r0]\n\ + cmp r0, r1\n\ + bne _08027FBC\n\ +_08028088:\n\ + movs r7, 0x1\n\ + add r8, r7\n\ + ldr r0, _08028130 @ =0x000003e7\n\ + cmp r8, r0\n\ + ble _0802802C\n\ + movs r0, 0\n\ + mov r8, r0\n\ + ldr r1, _08028134 @ =gBattlescriptCurrInstr\n\ + mov r12, r1\n\ + ldr r3, _08028120 @ =gTypeEffectiveness\n\ + adds r0, r4, 0x1\n\ + adds r0, r3\n\ + mov r9, r0\n\ + adds r5, r3, 0\n\ +_080280A4:\n\ + ldrb r1, [r5]\n\ + cmp r1, 0xFF\n\ + bgt _080280AE\n\ + cmp r1, 0xFE\n\ + bge _080280E8\n\ +_080280AE:\n\ + mov r4, r10\n\ + ldrb r2, [r4]\n\ + lsls r0, r2, 1\n\ + ldr r7, _08028124 @ =gUnknown_02024C44\n\ + adds r0, r7\n\ + ldrh r0, [r0]\n\ + cmp r1, r0\n\ + bne _080280E8\n\ + ldrb r0, [r5, 0x2]\n\ + cmp r0, 0x5\n\ + bhi _080280E8\n\ + movs r6, 0x58\n\ + adds r0, r2, 0\n\ + muls r0, r6\n\ + ldr r1, _0802812C @ =gBattleMons\n\ + adds r2, r0, r1\n\ + adds r4, r2, 0\n\ + adds r4, 0x21\n\ + ldrb r0, [r4]\n\ + mov r7, r9\n\ + ldrb r1, [r7]\n\ + cmp r0, r1\n\ + beq _080280E8\n\ + adds r0, r2, 0\n\ + adds r0, 0x22\n\ + ldrb r0, [r0]\n\ + cmp r0, r1\n\ + beq _080280E8\n\ + b _08027FE8\n\ +_080280E8:\n\ + adds r5, 0x3\n\ + movs r0, 0x3\n\ + add r8, r0\n\ + ldr r0, _08028138 @ =0x0000014f\n\ + cmp r8, r0\n\ + bls _080280A4\n\ + mov r1, r12\n\ + ldr r2, [r1]\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2, 0x2]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 16\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + lsls r0, 24\n\ + orrs r1, r0\n\ + mov r4, r12\n\ + str r1, [r4]\n\ +_08028110:\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08028120: .4byte gTypeEffectiveness\n\ +_08028124: .4byte gUnknown_02024C44\n\ +_08028128: .4byte gBankAttacker\n\ +_0802812C: .4byte gBattleMons\n\ +_08028130: .4byte 0x000003e7\n\ +_08028134: .4byte gBattlescriptCurrInstr\n\ +_08028138: .4byte 0x0000014f\n\ + .syntax divided"); +} +#endif // NONMATCHING + +static void atkA7_setalwayshitflag(void) +{ + gStatuses3[gBankTarget] &= ~(STATUS3_ALWAYS_HITS); + gStatuses3[gBankTarget] |= 0x10; + gDisableStructs[gBankTarget].bankWithSureHit = gBankAttacker; + gBattlescriptCurrInstr++; +} + +struct move_pp +{ + u16 move[4]; + u8 pp[4]; + u8 ppBonuses; +}; + +static void atkA8_copymovepermanently(void) +{ + gUnknown_02024BE8 = 0xFFFF; + if (!(gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED) && gUnknown_02024C2C[gBankTarget] != MOVE_STRUGGLE && gUnknown_02024C2C[gBankTarget] != 0 && gUnknown_02024C2C[gBankTarget] != 0xFFFF && gUnknown_02024C2C[gBankTarget] != MOVE_SKETCH) + { + int i; + for (i = 0; i < 4; i++) + { + if (gBattleMons[gBankAttacker].moves[i] == MOVE_SKETCH) + continue; + if (gBattleMons[gBankAttacker].moves[i] == gUnknown_02024C2C[gBankTarget]) + break; + } + if (i != 4) //sketch fail + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else //sketch worked + { + struct move_pp moves_data; + gBattleMons[gBankAttacker].moves[gCurrMovePos] = gUnknown_02024C2C[gBankTarget]; + gBattleMons[gBankAttacker].pp[gCurrMovePos] = gBattleMoves[gUnknown_02024C2C[gBankTarget]].pp; + gActiveBank = gBankAttacker; + for (i = 0; i < 4; i++) + { + moves_data.move[i] = gBattleMons[gBankAttacker].moves[i]; + moves_data.pp[i] = gBattleMons[gBankAttacker].pp[i]; + } + moves_data.ppBonuses = gBattleMons[gBankAttacker].ppBonuses; + EmitSetAttributes(0, REQUEST_MOVES_PP_BATTLE, 0, sizeof(struct move_pp), &moves_data); + MarkBufferBankForExecution(gActiveBank); + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = gUnknown_02024C2C[gBankTarget]; + gBattleTextBuff1[3] = gUnknown_02024C2C[gBankTarget] >> 8; + gBattleTextBuff1[4] = 0xFF; + gBattlescriptCurrInstr += 5; + } + } + else //sketch fail + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static bool8 IsTwoTurnsMove(u16 move) +{ + u8 effect = gBattleMoves[move].effect; + if (effect == EFFECT_SKULL_BASH || effect == EFFECT_RAZOR_WIND || effect == EFFECT_SKY_ATTACK || effect == EFFECT_SOLARBEAM || effect == EFFECT_FLY || effect == EFFECT_BIDE) + return 1; + else + return 0; +} + +static bool8 IsMoveUnchoosable(u16 move) +{ + if (move == 0 || move == MOVE_SLEEP_TALK || move == MOVE_ASSIST || move == MOVE_MIRROR_MOVE || move == MOVE_METRONOME) + return 1; + else + return 0; +} + +static u8 AttacksThisTurn(u8 bank, u16 move) //Note: returns 1 if it's a charging turn, otherwise 2 +{ + //first argument is unused + u8 effect; + if (gBattleMoves[move].effect == EFFECT_SOLARBEAM && (gBattleWeather & WEATHER_SUN_ANY)) + return 2; + effect = gBattleMoves[move].effect; + if (effect == EFFECT_SKULL_BASH || effect == EFFECT_RAZOR_WIND || effect == EFFECT_SKY_ATTACK || effect == EFFECT_SOLARBEAM || effect == EFFECT_FLY || effect == EFFECT_BIDE) + { + if ((gHitMarker & HITMARKER_x8000000)) + return 1; + } + return 2; +} + +static void atkA9_sleeptalk_choose_move(void) +{ + u8 unusable_moves = 0; + int i; + + for (i = 0; i < 4; i++) + { + if (IsMoveUnchoosable(gBattleMons[gBankAttacker].moves[i]) || gBattleMons[gBankAttacker].moves[i] == MOVE_FOCUS_PUNCH + || gBattleMons[gBankAttacker].moves[i] == MOVE_UPROAR || IsTwoTurnsMove(gBattleMons[gBankAttacker].moves[i])) + unusable_moves |= gBitTable[i]; + } + unusable_moves = CheckMoveLimitations(gBankAttacker, unusable_moves, 0xFD); + if (unusable_moves == 0xF) //all 4 moves cannot be chosen + gBattlescriptCurrInstr += 5; + else //at least one move can be chosen + { + u32 random_pos; + do + { + random_pos = Random() & 3; + } while ((gBitTable[random_pos] & unusable_moves)); + + gRandomMove = gBattleMons[gBankAttacker].moves[random_pos]; + gCurrMovePos = random_pos; + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + gBankTarget = GetMoveTarget(gRandomMove, 0); + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +static void atkAA_set_destinybond(void) +{ + gBattleMons[gBankAttacker].status2 |= STATUS2_DESTINY_BOND; + gBattlescriptCurrInstr++; +} + +static void DestinyBondFlagUpdate(void) +{ + u8 atk_side = GetBankSide(gBankAttacker); + u8 def_side = GetBankSide(gBankTarget); + if (gBattleMons[gBankTarget].status2 & STATUS2_DESTINY_BOND && atk_side != def_side && !(gHitMarker & HITMARKER_GRUDGE)) + gHitMarker |= HITMARKER_DESTINYBOND; +} + +static void atkAB_DestinyBondFlagUpdate(void) +{ + DestinyBondFlagUpdate(); + gBattlescriptCurrInstr++; +} + +static void atkAC_remaininghptopower(void) +{ + s32 hp_fraction = GetScaledHPFraction(gBattleMons[gBankAttacker].hp, gBattleMons[gBankAttacker].maxHP, 48); + int i; + for (i = 0; i < 12; i += 2) + { + if (hp_fraction <= sUnknown_081FAD26[i]) + break; + } + gDynamicBasePower = sUnknown_081FAD26[i + 1]; + gBattlescriptCurrInstr++; +} + +static void atkAD_spite_ppreduce(void) +{ + if (gLastUsedMove[gBankTarget] != 0 && gLastUsedMove[gBankTarget] != 0xFFFF && !(gStatuses3[gBankTarget] & STATUS3_SEMI_INVULNERABLE)) + { + int i; + for (i = 0; i < 4; i++) + { + if (gLastUsedMove[gBankTarget] == gBattleMons[gBankTarget].moves[i]) + break; + } + if (i != 4 && gBattleMons[gBankTarget].pp[i] > 1) + { + s32 lost_pp = (Random() & 3) + 2; + if (gBattleMons[gBankTarget].pp[i] < lost_pp) + lost_pp = gBattleMons[gBankTarget].pp[i]; + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = gLastUsedMove[gBankTarget]; + gBattleTextBuff1[3] = gLastUsedMove[gBankTarget] >> 8; + gBattleTextBuff1[4] = 0xFF; + ConvertIntToDecimalStringN(gBattleTextBuff2, lost_pp, 0, 1); + gBattleTextBuff2[0] = 0xFD; + gBattleTextBuff2[1] = 1; + gBattleTextBuff2[2] = 1; + gBattleTextBuff2[3] = 1; + gBattleTextBuff2[4] = lost_pp; + gBattleTextBuff2[5] = 0xFF; + + gBattleMons[gBankTarget].pp[i] -= lost_pp; + gActiveBank = gBankTarget; + if (!(gDisableStructs[gActiveBank].unk18_b & gBitTable[i]) + && !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED)) + { + EmitSetAttributes(0, REQUEST_PPMOVE1_BATTLE + i, 0, 1, &gBattleMons[gActiveBank].pp[i]); + MarkBufferBankForExecution(gActiveBank); + } + gBattlescriptCurrInstr += 5; + if (gBattleMons[gBankTarget].pp[i] == 0) + CancelMultiTurnMoves(gBankTarget); + return; + } + } + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkAE_heal_party_status(void) +{ + register u32 zero2 asm("r4") = 0; + u32 zero = zero2; + u8 to_heal = 0; + if (gCurrentMove == MOVE_HEAL_BELL) + { + struct Pokemon* party; + int i; + + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + if (GetBankSide(gBankAttacker) == 0) + party = gPlayerParty; + else + party = gEnemyParty; + + if (gBattleMons[gBankAttacker].ability != ABILITY_SOUNDPROOF) + { + gBattleMons[gBankAttacker].status1 = 0; + } + else + { + RecordAbilityBattle(gBankAttacker, gBattleMons[gBankAttacker].ability); + gBattleCommunication[MULTISTRING_CHOOSER] |= 1; + } + + gActiveBank = BATTLE_STRUCT->scriptingActive = GetBankByPlayerAI(GetBankIdentity(gBankAttacker) ^ 2); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gAbsentBankFlags & gBitTable[gActiveBank])) + { + if (gBattleMons[gActiveBank].ability != ABILITY_SOUNDPROOF) + { + gBattleMons[gActiveBank].status1 = 0; + } + else + { + RecordAbilityBattle(gActiveBank, gBattleMons[gActiveBank].ability); + gBattleCommunication[MULTISTRING_CHOOSER] |= 2; + } + } + + for (i = 0; i < 6; i++) + { + u16 species = GetMonData(&party[i], MON_DATA_SPECIES2); + u8 abilityBit = GetMonData(&party[i], MON_DATA_ALT_ABILITY); + if (species != 0 && species != SPECIES_EGG) + { + u8 ability; + if (gBattlePartyID[gBankAttacker] == i) + ability = gBattleMons[gBankAttacker].ability; + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattlePartyID[gActiveBank] == i && !(gAbsentBankFlags & gBitTable[gActiveBank])) + ability = gBattleMons[gActiveBank].ability; + else + ability = GetAbilityBySpecies(species, abilityBit); + if (ability != ABILITY_SOUNDPROOF) + to_heal |= (1 << i); + } + } + } + else //Aromatherapy + { + gBattleCommunication[MULTISTRING_CHOOSER] = 4; + to_heal = 0x3F; + gBattleMons[gBankAttacker].status1 = zero2; + + gActiveBank = GetBankByPlayerAI(GetBankIdentity(gBankAttacker) ^ 2); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gAbsentBankFlags & gBitTable[gActiveBank])) + gBattleMons[gActiveBank].status1 = 0; + + } + //missing check? + gActiveBank = gBankAttacker; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, to_heal, 4, &zero); + MarkBufferBankForExecution(gActiveBank); + + gBattlescriptCurrInstr++; +} + +static void atkAF_cursetarget(void) +{ + if (gBattleMons[gBankTarget].status2 & STATUS2_CURSED || gStatuses3[gBankTarget] & STATUS3_SEMI_INVULNERABLE) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + gBattleMons[gBankTarget].status2 |= STATUS2_CURSED; + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattlescriptCurrInstr += 5; + } +} + +static void atkB0_set_spikes(void) +{ + u8 side = GetBankSide(gBankAttacker) ^ 1; + if (gSideTimer[side].spikesAmount == 3) + { + gSpecialStatuses[gBankAttacker].flag20 = 1; + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + gSideAffecting[side] |= SIDE_STATUS_SPIKES; + gSideTimer[side].spikesAmount++; + gBattlescriptCurrInstr += 5; + } +} + +static void atkB1_set_foresight(void) +{ + gBattleMons[gBankTarget].status2 |= STATUS2_FORESIGHT; + gBattlescriptCurrInstr++; +} + +static void atkB2_setperishsong(void) +{ + int not_affected_pokes = 0, i; + + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gStatuses3[i] & STATUS3_PERISH_SONG || gBattleMons[i].ability == ABILITY_SOUNDPROOF) + not_affected_pokes++; + else + { + gStatuses3[i] |= STATUS3_PERISH_SONG; + gDisableStructs[i].perishSong1 = 3; + gDisableStructs[i].perishSong2 = 3; + } + } + + sub_80153D0(gBankAttacker); + if (not_affected_pokes == gNoOfAllBanks) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + gBattlescriptCurrInstr += 5; +} + +static void atkB3_rolloutdamagecalculation(void) +{ + if (gBattleMoveFlags & MOVESTATUS_NOEFFECT) + { + CancelMultiTurnMoves(gBankAttacker); + gBattlescriptCurrInstr = BattleScript_1D6F74; + } + else + { + int i; + if (!(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)) //first hit + { + gDisableStructs[gBankAttacker].rolloutTimer1 = 5; + gDisableStructs[gBankAttacker].rolloutTimer2 = 5; + gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS; + gLockedMove[gBankAttacker] = gCurrentMove; + } + if (--gDisableStructs[gBankAttacker].rolloutTimer1 == 0) + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS); + + gDynamicBasePower = gBattleMoves[gCurrentMove].power; + for (i = 1; i < (5 - gDisableStructs[gBankAttacker].rolloutTimer1); i++) + gDynamicBasePower *= 2; + + if (gBattleMons[gBankAttacker].status2 & STATUS2_DEFENSE_CURL) + gDynamicBasePower *= 2; + + gBattlescriptCurrInstr++; + } +} + +static void atkB4_jumpifconfusedandstatmaxed(void) +{ + if (gBattleMons[gBankTarget].status2 & STATUS2_CONFUSION && gBattleMons[gBankTarget].statStages[BSScriptRead8(gBattlescriptCurrInstr + 1)] == 0xC) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + else + gBattlescriptCurrInstr += 6; +} + +static void atkB5_furycuttercalc(void) +{ + if (gBattleMoveFlags & MOVESTATUS_NOEFFECT) + { + gDisableStructs[gBankAttacker].furyCutterCounter = 0; + gBattlescriptCurrInstr = BattleScript_1D6F74; + } + else + { + int i; + + if (gDisableStructs[gBankAttacker].furyCutterCounter != 5) + gDisableStructs[gBankAttacker].furyCutterCounter++; + + gDynamicBasePower = gBattleMoves[gCurrentMove].power; + for (i = 1; i < gDisableStructs[gBankAttacker].furyCutterCounter; i++) + gDynamicBasePower *= 2; + + gBattlescriptCurrInstr++; + } +} + +static void atkB6_happinesstodamagecalculation(void) +{ + if (gBattleMoves[gCurrentMove].effect == EFFECT_RETURN) + gDynamicBasePower = 10 * (gBattleMons[gBankAttacker].friendship) / 25; + else //EFFECT_FRUSTRATION + gDynamicBasePower = 10 * (255 - gBattleMons[gBankAttacker].friendship) / 25; + gBattlescriptCurrInstr++; +} + +static void atkB7_presentdamagecalculation(void) +{ + s32 rand = Random() & 0xFF; + if (rand < 102) + gDynamicBasePower = 40; + else if (rand < 178) + gDynamicBasePower = 80; + else if (rand < 204) + gDynamicBasePower = 120; + else + { + gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + } + if (rand < 204) + gBattlescriptCurrInstr = BattleScript_1D6F44; + else if (gBattleMons[gBankTarget].maxHP == gBattleMons[gBankTarget].hp) + gBattlescriptCurrInstr = BattleScript_1D83B5; + else + { + //gBattleMoveFlags &= ~(MOVESTATUS_NOTAFFECTED); only in Emerald + gBattlescriptCurrInstr = BattleScript_1D839B; + } +} + +static void atkB8_set_safeguard(void) +{ + if (gSideAffecting[GetBankIdentity(gBankAttacker) & 1] & SIDE_STATUS_SAFEGUARD) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + else + { + gSideAffecting[GetBankIdentity(gBankAttacker) & 1] |= SIDE_STATUS_SAFEGUARD; + gSideTimer[GetBankIdentity(gBankAttacker) & 1].safeguardTimer = 5; + gBattleCommunication[MULTISTRING_CHOOSER] = 5; + } + gBattlescriptCurrInstr++; +} + +static void atkB9_magnitudedamagecalculation(void) +{ + s32 magnitude = Random() % 100; + if (magnitude < 5) + { + gDynamicBasePower = 10; + magnitude = 4; + } + else if (magnitude < 15) + { + gDynamicBasePower = 30; + magnitude = 5; + } + else if (magnitude < 35) + { + gDynamicBasePower = 50; + magnitude = 6; + } + else if (magnitude < 65) + { + gDynamicBasePower = 70; + magnitude = 7; + } + else if (magnitude < 85) + { + gDynamicBasePower = 90; + magnitude = 8; + } + else if (magnitude < 95) + { + gDynamicBasePower = 110; + magnitude = 9; + } + else + { + gDynamicBasePower = 150; + magnitude = 10; + } + + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 1; + gBattleTextBuff1[2] = 1; + gBattleTextBuff1[3] = 2; + gBattleTextBuff1[4] = magnitude; + gBattleTextBuff1[5] = 0xFF; + + for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++) + { + if (gBankTarget == gBankAttacker) + continue; + if (!(gAbsentBankFlags & gBitTable[gBankTarget])) //a valid target was found + break; + } + gBattlescriptCurrInstr++; +} + +static void atkBA_jumpifnopursuitswitchdmg(void) +{ + if (gMultiHitCounter == 1) + { + if (GetBankSide(gBankAttacker) == 0) + gBankTarget = GetBankByPlayerAI(1); + else + gBankTarget = GetBankByPlayerAI(0); + } + else + { + if (GetBankSide(gBankAttacker) == 0) + gBankTarget = GetBankByPlayerAI(3); + else + gBankTarget = GetBankByPlayerAI(2); + } + + if (gActionForBanks[gBankTarget] == 0 && gBankAttacker == ewram[gBankTarget + 0x16010] && !(gBattleMons[gBankTarget].status1 & (STATUS_SLEEP | STATUS_FREEZE)) + && gBattleMons[gBankAttacker].hp && !gDisableStructs[gBankTarget].truantCounter && gChosenMovesByBanks[gBankTarget] == MOVE_PURSUIT) + { + int i; + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gTurnOrder[i] == gBankTarget) + gUnknown_02024A76[i] = 11; + } + gCurrentMove = MOVE_PURSUIT; + gBattlescriptCurrInstr += 5; + BATTLE_STRUCT->animTurn = 1; + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkBB_setsunny(void) +{ + if (gBattleWeather & WEATHER_SUN_ANY) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else + { + gBattleWeather = WEATHER_SUN_TEMPORARY; + gBattleCommunication[MULTISTRING_CHOOSER] = 4; + gWishFutureKnock.weatherDuration = 5; + } + gBattlescriptCurrInstr++; +} + +static void atkBC_maxattackhalvehp(void) //belly drum +{ + u32 half_hp = gBattleMons[gBankAttacker].maxHP / 2; + if (!(gBattleMons[gBankAttacker].maxHP / 2)) + half_hp = 1; + + if (gBattleMons[gBankAttacker].statStages[STAT_STAGE_ATK] < 12 && gBattleMons[gBankAttacker].hp > half_hp) + { + gBattleMons[gBankAttacker].statStages[STAT_STAGE_ATK] = 12; + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattlescriptCurrInstr += 5; + } + else + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +static void atkBD_copyfoestats(void) //psych up +{ + int i; + for (i = 0; i < 8; i++) + { + gBattleMons[gBankAttacker].statStages[i] = gBattleMons[gBankTarget].statStages[i]; + } + gBattlescriptCurrInstr += 5; //why not 1? possible unused fail possibility? +} + +static void atkBE_breakfree(void) //rapid spin +{ + if (gBattleMons[gBankAttacker].status2 & STATUS2_WRAPPED) + { + gBattleMons[gBankAttacker].status2 &= ~(STATUS2_WRAPPED); + gBankTarget = ewram[gBankAttacker + 0x16020]; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 2; + gBattleTextBuff1[2] = ewram[gBankAttacker * 2 + 0x16004]; + gBattleTextBuff1[3] = ewram[gBankAttacker * 2 + 0x16005]; + gBattleTextBuff1[4] = 0xFF; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_WrapFree; + } + else if (gStatuses3[gBankAttacker] & STATUS3_LEECHSEED) + { + gStatuses3[gBankAttacker] &= ~(STATUS3_LEECHSEED); + gStatuses3[gBankAttacker] &= ~(STATUS3_LEECHSEED_BANK); + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_LeechSeedFree; + } + else if (gSideAffecting[GetBankSide(gBankAttacker)] & SIDE_STATUS_SPIKES) + { + gSideAffecting[GetBankSide(gBankAttacker)] &= ~(SIDE_STATUS_SPIKES); + gSideTimer[GetBankSide(gBankAttacker)].spikesAmount = 0; + b_movescr_stack_push_cursor(); + gBattlescriptCurrInstr = BattleScript_SpikesFree; + } + else + gBattlescriptCurrInstr++; +} + +static void atkBF_set_defense_curl(void) +{ + gBattleMons[gBankAttacker].status2 |= STATUS2_DEFENSE_CURL; + gBattlescriptCurrInstr++; +} + +static void atkC0_recoverbasedonsunlight(void) +{ + gBankTarget = gBankAttacker; + if (gBattleMons[gBankAttacker].hp != gBattleMons[gBankAttacker].maxHP) + { + if (!gBattleWeather || !WEATHER_HAS_EFFECT) + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2; + else if (gBattleWeather & WEATHER_SUN_ANY) + gBattleMoveDamage = 20 * gBattleMons[gBankAttacker].maxHP / 30; + else //not sunny weather + gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + gBattlescriptCurrInstr += 5; + } + else + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +__attribute__((naked)) +static void atkC1_hidden_power(void) +{ + asm(".syntax unified\n\ +push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + ldr r2, _08029894 @ =gBattleMons\n\ + ldr r0, _08029898 @ =gBankAttacker\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + adds r4, r1, 0\n\ + muls r4, r0\n\ + adds r4, r2\n\ + ldrb r0, [r4, 0x14]\n\ + mov r10, r0\n\ + mov r7, r10\n\ + lsls r7, 27\n\ + adds r0, r7, 0\n\ + lsrs r0, 27\n\ + mov r10, r0\n\ + movs r1, 0x2\n\ + mov r2, r10\n\ + ands r2, r1\n\ + asrs r2, 1\n\ + ldrh r7, [r4, 0x14]\n\ + mov r9, r7\n\ + mov r0, r9\n\ + lsls r0, 22\n\ + mov r9, r0\n\ + lsrs r3, r0, 27\n\ + adds r0, r1, 0\n\ + ands r0, r3\n\ + orrs r2, r0\n\ + ldrb r7, [r4, 0x15]\n\ + mov r8, r7\n\ + mov r0, r8\n\ + lsls r0, 25\n\ + mov r8, r0\n\ + lsrs r3, r0, 27\n\ + adds r0, r1, 0\n\ + ands r0, r3\n\ + lsls r0, 1\n\ + orrs r2, r0\n\ + ldr r6, [r4, 0x14]\n\ + lsls r6, 12\n\ + lsrs r3, r6, 27\n\ + adds r0, r1, 0\n\ + ands r0, r3\n\ + lsls r0, 2\n\ + orrs r2, r0\n\ + ldrh r5, [r4, 0x16]\n\ + lsls r5, 23\n\ + lsrs r3, r5, 27\n\ + adds r0, r1, 0\n\ + ands r0, r3\n\ + lsls r0, 3\n\ + orrs r2, r0\n\ + ldrb r3, [r4, 0x17]\n\ + lsls r3, 26\n\ + lsrs r0, r3, 27\n\ + ands r1, r0\n\ + lsls r1, 4\n\ + orrs r2, r1\n\ + movs r1, 0x1\n\ + adds r4, r1, 0\n\ + mov r7, r10\n\ + ands r4, r7\n\ + mov r0, r9\n\ + lsrs r0, 27\n\ + mov r9, r0\n\ + adds r0, r1, 0\n\ + mov r7, r9\n\ + ands r0, r7\n\ + lsls r0, 1\n\ + orrs r4, r0\n\ + mov r0, r8\n\ + lsrs r0, 27\n\ + mov r8, r0\n\ + adds r0, r1, 0\n\ + mov r7, r8\n\ + ands r0, r7\n\ + lsls r0, 2\n\ + orrs r4, r0\n\ + lsrs r6, 27\n\ + adds r0, r1, 0\n\ + ands r0, r6\n\ + lsls r0, 3\n\ + orrs r4, r0\n\ + lsrs r5, 27\n\ + adds r0, r1, 0\n\ + ands r0, r5\n\ + lsls r0, 4\n\ + orrs r4, r0\n\ + lsrs r3, 27\n\ + ands r1, r3\n\ + lsls r1, 5\n\ + orrs r4, r1\n\ + ldr r5, _0802989C @ =gDynamicBasePower\n\ + lsls r0, r2, 2\n\ + adds r0, r2\n\ + lsls r0, 3\n\ + movs r1, 0x3F\n\ + bl __divsi3\n\ + adds r0, 0x1E\n\ + strh r0, [r5]\n\ + ldr r5, _080298A0 @ =0x02000000\n\ + lsls r0, r4, 4\n\ + subs r0, r4\n\ + movs r1, 0x3F\n\ + bl __divsi3\n\ + adds r1, r0, 0x1\n\ + ldr r0, _080298A4 @ =0x0001601c\n\ + adds r5, r0\n\ + strb r1, [r5]\n\ + lsls r0, r1, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x8\n\ + bls _08029876\n\ + adds r0, r1, 0x1\n\ + strb r0, [r5]\n\ +_08029876:\n\ + ldrb r0, [r5]\n\ + movs r1, 0xC0\n\ + orrs r0, r1\n\ + strb r0, [r5]\n\ + ldr r1, _080298A8 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x1\n\ + str r0, [r1]\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08029894: .4byte gBattleMons\n\ +_08029898: .4byte gBankAttacker\n\ +_0802989C: .4byte gDynamicBasePower\n\ +_080298A0: .4byte 0x02000000\n\ +_080298A4: .4byte 0x0001601c\n\ +_080298A8: .4byte gBattlescriptCurrInstr\n\ + .syntax divided"); +} + +static void atkC2_selectnexttarget(void) +{ + for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++) + { + if (gBankTarget == gBankAttacker) + continue; + if (!(gAbsentBankFlags & gBitTable[gBankTarget])) + break; + } + gBattlescriptCurrInstr++; +} + +static void atkC3_setfutureattack(void) +{ + if (gWishFutureKnock.futureSightCounter[gBankTarget] != 0) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + gWishFutureKnock.futureSightMove[gBankTarget] = gCurrentMove; + gWishFutureKnock.futureSightAttacker[gBankTarget] = gBankAttacker; + gWishFutureKnock.futureSightCounter[gBankTarget] = 3; + gWishFutureKnock.futureSightDmg[gBankTarget] = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove, + gSideAffecting[GetBankIdentity(gBankTarget) & 1], 0, + 0, gBankAttacker, gBankTarget); + + if (gProtectStructs[gBankAttacker].helpingHand) + gWishFutureKnock.futureSightDmg[gBankTarget] = gWishFutureKnock.futureSightDmg[gBankTarget] * 15 / 10; + + if (gCurrentMove == MOVE_DOOM_DESIRE) + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + + gBattlescriptCurrInstr += 5; + } +} + +#ifdef NONMATCHING +static void atkC4_beat_up(void) +{ + register struct Pokemon* party asm("r7"); + if (GetBankSide(gBankAttacker) == 0) + party = gPlayerParty; + else + party = gEnemyParty; + + if (gBattleMons[gBankTarget].hp == 0) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + while (gBattleCommunication[0] < 6) + { + if (GetMonData(&party[gBattleCommunication[0]], MON_DATA_HP) && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES2) + && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES2) != SPECIES_EGG && !GetMonData(&party[gBattleCommunication[0]], MON_DATA_STATUS)) + break; + gBattleCommunication[0]++; + } + if (gBattleCommunication[0] < 6) + { + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 4; + gBattleTextBuff1[2] = gBankAttacker; + gBattleTextBuff1[3] = gBattleCommunication[0]; + gBattleTextBuff1[4] = 0xFF; + gBattlescriptCurrInstr += 9; + + gBattleMoveDamage = gBaseStats[GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES)].baseAttack; + gBattleMoveDamage *= gBattleMoves[gCurrentMove].power; + gBattleMoveDamage *= (GetMonData(&party[gBattleCommunication[0]], MON_DATA_LEVEL) * 2 / 5 + 2); + gBattleMoveDamage /= gBaseStats[gBattleMons[gBankTarget].species].baseDefense; + gBattleMoveDamage = (gBattleMoveDamage / 50) + 2; + if (gProtectStructs[gBankAttacker].helpingHand) + gBattleMoveDamage = gBattleMoveDamage * 15 / 10; + + gBattleCommunication[0]++; + } + else if (gBattleCommunication[0] != 0) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 5); + } +} +#else +__attribute__((naked)) +static void atkC4_beat_up(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r9\n\ + mov r6, r8\n\ + push {r6,r7}\n\ + ldr r0, _08029A8C @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + ldr r7, _08029A90 @ =gEnemyParty\n\ + cmp r0, 0\n\ + bne _08029A62\n\ + ldr r7, _08029A94 @ =gPlayerParty\n\ +_08029A62:\n\ + ldr r2, _08029A98 @ =gBattleMons\n\ + ldr r0, _08029A9C @ =gBankTarget\n\ + ldrb r1, [r0]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r0, r2\n\ + ldrh r0, [r0, 0x28]\n\ + cmp r0, 0\n\ + bne _08029AA4\n\ + ldr r3, _08029AA0 @ =gBattlescriptCurrInstr\n\ + ldr r2, [r3]\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2, 0x2]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 16\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + b _08029C40\n\ + .align 2, 0\n\ +_08029A8C: .4byte gBankAttacker\n\ +_08029A90: .4byte gEnemyParty\n\ +_08029A94: .4byte gPlayerParty\n\ +_08029A98: .4byte gBattleMons\n\ +_08029A9C: .4byte gBankTarget\n\ +_08029AA0: .4byte gBattlescriptCurrInstr\n\ +_08029AA4:\n\ + ldr r6, _08029BE0 @ =gBattleCommunication\n\ + ldrb r0, [r6]\n\ + mov r8, r0\n\ + cmp r0, 0x5\n\ + bls _08029AB0\n\ + b _08029C0C\n\ +_08029AB0:\n\ + adds r4, r6, 0\n\ + movs r5, 0x64\n\ +_08029AB4:\n\ + ldrb r0, [r4]\n\ + muls r0, r5\n\ + adds r0, r7, r0\n\ + movs r1, 0x39\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _08029AF8\n\ + ldrb r0, [r6]\n\ + muls r0, r5\n\ + adds r0, r7, r0\n\ + movs r1, 0x41\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _08029AF8\n\ + ldrb r0, [r4]\n\ + muls r0, r5\n\ + adds r0, r7, r0\n\ + movs r1, 0x41\n\ + bl GetMonData\n\ + movs r1, 0xCE\n\ + lsls r1, 1\n\ + cmp r0, r1\n\ + beq _08029AF8\n\ + ldrb r0, [r4]\n\ + muls r0, r5\n\ + adds r0, r7, r0\n\ + movs r1, 0x37\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _08029B08\n\ +_08029AF8:\n\ + ldrb r0, [r4]\n\ + adds r0, 0x1\n\ + strb r0, [r4]\n\ + adds r6, r4, 0\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x5\n\ + bls _08029AB4\n\ +_08029B08:\n\ + ldr r1, _08029BE0 @ =gBattleCommunication\n\ + mov r9, r1\n\ + ldrb r2, [r1]\n\ + cmp r2, 0x5\n\ + bhi _08029C0C\n\ + ldr r1, _08029BE4 @ =gBattleTextBuff1\n\ + movs r0, 0xFD\n\ + strb r0, [r1]\n\ + movs r0, 0x4\n\ + strb r0, [r1, 0x1]\n\ + ldr r6, _08029BE8 @ =gBankAttacker\n\ + ldrb r0, [r6]\n\ + strb r0, [r1, 0x2]\n\ + strb r2, [r1, 0x3]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x4]\n\ + ldr r1, _08029BEC @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x9\n\ + str r0, [r1]\n\ + ldr r2, _08029BF0 @ =gBattleMoveDamage\n\ + mov r8, r2\n\ + ldr r5, _08029BF4 @ =gBaseStats\n\ + mov r1, r9\n\ + ldrb r0, [r1]\n\ + movs r4, 0x64\n\ + muls r0, r4\n\ + adds r0, r7, r0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + lsls r1, r0, 3\n\ + subs r1, r0\n\ + lsls r1, 2\n\ + adds r1, r5\n\ + ldrb r3, [r1, 0x1]\n\ + mov r2, r8\n\ + str r3, [r2]\n\ + ldr r2, _08029BF8 @ =gBattleMoves\n\ + ldr r0, _08029BFC @ =gCurrentMove\n\ + ldrh r1, [r0]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldrb r0, [r0, 0x1]\n\ + muls r0, r3\n\ + mov r1, r8\n\ + str r0, [r1]\n\ + mov r2, r9\n\ + ldrb r0, [r2]\n\ + muls r0, r4\n\ + adds r0, r7, r0\n\ + movs r1, 0x38\n\ + bl GetMonData\n\ + lsls r0, 1\n\ + movs r1, 0x5\n\ + bl __udivsi3\n\ + adds r0, 0x2\n\ + mov r2, r8\n\ + ldr r1, [r2]\n\ + muls r0, r1\n\ + str r0, [r2]\n\ + ldr r3, _08029C00 @ =gBattleMons\n\ + ldr r1, _08029C04 @ =gBankTarget\n\ + ldrb r2, [r1]\n\ + movs r1, 0x58\n\ + muls r1, r2\n\ + adds r1, r3\n\ + ldrh r2, [r1]\n\ + lsls r1, r2, 3\n\ + subs r1, r2\n\ + lsls r1, 2\n\ + adds r1, r5\n\ + ldrb r1, [r1, 0x2]\n\ + bl __divsi3\n\ + mov r1, r8\n\ + str r0, [r1]\n\ + movs r1, 0x32\n\ + bl __divsi3\n\ + adds r2, r0, 0x2\n\ + mov r0, r8\n\ + str r2, [r0]\n\ + ldr r1, _08029C08 @ =gProtectStructs\n\ + ldrb r0, [r6]\n\ + lsls r0, 4\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + lsls r0, 28\n\ + cmp r0, 0\n\ + bge _08029BD4\n\ + lsls r0, r2, 4\n\ + subs r0, r2\n\ + movs r1, 0xA\n\ + bl __divsi3\n\ + mov r1, r8\n\ + str r0, [r1]\n\ +_08029BD4:\n\ + mov r2, r9\n\ + ldrb r0, [r2]\n\ + adds r0, 0x1\n\ + strb r0, [r2]\n\ + b _08029C46\n\ + .align 2, 0\n\ +_08029BE0: .4byte gBattleCommunication\n\ +_08029BE4: .4byte gBattleTextBuff1\n\ +_08029BE8: .4byte gBankAttacker\n\ +_08029BEC: .4byte gBattlescriptCurrInstr\n\ +_08029BF0: .4byte gBattleMoveDamage\n\ +_08029BF4: .4byte gBaseStats\n\ +_08029BF8: .4byte gBattleMoves\n\ +_08029BFC: .4byte gCurrentMove\n\ +_08029C00: .4byte gBattleMons\n\ +_08029C04: .4byte gBankTarget\n\ +_08029C08: .4byte gProtectStructs\n\ +_08029C0C:\n\ + mov r0, r8\n\ + cmp r0, 0\n\ + beq _08029C2C\n\ + ldr r3, _08029C28 @ =gBattlescriptCurrInstr\n\ + ldr r2, [r3]\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2, 0x2]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 16\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + b _08029C40\n\ + .align 2, 0\n\ +_08029C28: .4byte gBattlescriptCurrInstr\n\ +_08029C2C:\n\ + ldr r3, _08029C54 @ =gBattlescriptCurrInstr\n\ + ldr r2, [r3]\n\ + ldrb r1, [r2, 0x5]\n\ + ldrb r0, [r2, 0x6]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x7]\n\ + lsls r0, 16\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x8]\n\ +_08029C40:\n\ + lsls r0, 24\n\ + orrs r1, r0\n\ + str r1, [r3]\n\ +_08029C46:\n\ + pop {r3,r4}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08029C54: .4byte gBattlescriptCurrInstr\n\ + .syntax divided"); +} +#endif // NONMATCHING + +static void atkC5_hidepreattack(void) +{ + switch (gCurrentMove) + { + case MOVE_FLY: + case MOVE_BOUNCE: + gStatuses3[gBankAttacker] |= STATUS3_ON_AIR; + break; + case MOVE_DIG: + gStatuses3[gBankAttacker] |= STATUS3_UNDERGROUND; + break; + case MOVE_DIVE: + gStatuses3[gBankAttacker] |= STATUS3_UNDERWATER; + break; + } + gBattlescriptCurrInstr++; +} + +static void atkC6_unhidepostattack(void) +{ + switch (gCurrentMove) + { + case MOVE_FLY: + case MOVE_BOUNCE: + gStatuses3[gBankAttacker] &= ~STATUS3_ON_AIR; + break; + case MOVE_DIG: + gStatuses3[gBankAttacker] &= ~STATUS3_UNDERGROUND; + break; + case MOVE_DIVE: + gStatuses3[gBankAttacker] &= ~STATUS3_UNDERWATER; + break; + } + gBattlescriptCurrInstr++; +} + +static void atkC7_setminimize(void) +{ + if (gHitMarker & HITMARKER_OBEYS) + gStatuses3[gBankAttacker] |= STATUS3_MINIMIZED; + gBattlescriptCurrInstr++; +} + +static void atkC8_sethail(void) +{ + if (gBattleWeather & WEATHER_HAIL) + { + gBattleMoveFlags |= MOVESTATUS_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else + { + gBattleWeather = WEATHER_HAIL; + gBattleCommunication[MULTISTRING_CHOOSER] = 5; + gWishFutureKnock.weatherDuration = 5; + } + gBattlescriptCurrInstr++; +} + +static void atkC9_jumpifattackandspecialattackcannotfall(void) //memento +{ + if (gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK] == 0 + && gBattleMons[gBankTarget].statStages[STAT_STAGE_SPATK] == 0 + && gBattleCommunication[6] != 1) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + gActiveBank = gBankAttacker; + gBattleMoveDamage = gBattleMons[gActiveBank].hp; + EmitHealthBarUpdate(0, 0x7FFF); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 5; + } +} + +static void atkCA_setforcedtarget(void) //follow me +{ + gSideTimer[GetBankSide(gBankAttacker)].followmeTimer = 1; + gSideTimer[GetBankSide(gBankAttacker)].followmeTarget = gBankAttacker; + gBattlescriptCurrInstr++; +} + +static void atkCB_setcharge(void) +{ + gStatuses3[gBankAttacker] |= STATUS3_CHARGED_UP; + gDisableStructs[gBankAttacker].chargeTimer1 = 2; + gDisableStructs[gBankAttacker].chargeTimer2 = 2; + gBattlescriptCurrInstr++; +} + +static void atkCC_callterrainattack(void) //nature power +{ + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + gCurrentMove = sNaturePowerMoves[gBattleTerrain]; + gBankTarget = GetMoveTarget(gCurrentMove, 0); + b_movescr_stack_push(gBattleScriptsEffectsTable[gBattleMoves[gCurrentMove].effect]); + gBattlescriptCurrInstr++; +} + +static void atkCD_cureifburnedparalysedorpoisoned(void) //refresh +{ + if (gBattleMons[gBankAttacker].status1 & (STATUS_POISON | STATUS_BURN | STATUS_PARALYSIS | STATUS_TOXIC_POISON)) + { + gBattleMons[gBankAttacker].status1 = 0; + gBattlescriptCurrInstr += 5; + gActiveBank = gBankAttacker; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkCE_settorment(void) +{ + if (gBattleMons[gBankTarget].status2 & STATUS2_TORMENT) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + gBattleMons[gBankTarget].status2 |= STATUS2_TORMENT; + gBattlescriptCurrInstr += 5; + } +} + +static void atkCF_jumpifnodamage(void) +{ + if (gProtectStructs[gBankAttacker].physicalDmg || gProtectStructs[gBankAttacker].specialDmg) + gBattlescriptCurrInstr += 5; + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkD0_settaunt(void) +{ + if (gDisableStructs[gBankTarget].tauntTimer1 == 0) + { + gDisableStructs[gBankTarget].tauntTimer1 = 2; + gDisableStructs[gBankTarget].tauntTimer2 = 2; + gBattlescriptCurrInstr += 5; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkD1_set_helpinghand(void) +{ + gBankTarget = GetBankByPlayerAI(GetBankIdentity(gBankAttacker) ^ 2); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gAbsentBankFlags & gBitTable[gBankTarget]) + && !gProtectStructs[gBankAttacker].helpingHand && !gProtectStructs[gBankTarget].helpingHand) + { + gProtectStructs[gBankTarget].helpingHand = 1; + gBattlescriptCurrInstr += 5; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +#ifdef NONMATCHING +static void atkD2_swap_items(void) +{ + if ((GetBankSide(gBankAttacker) != 1 || gBattleTypeFlags & (BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER) || gTrainerBattleOpponent == 0x400)) + { + u8 side = GetBankSide(gBankAttacker); + if (gBattleTypeFlags) + } + + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +#else +__attribute__((naked)) +static void atkD2_swap_items(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x4\n\ + ldr r0, _0802A30C @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _0802A24C\n\ + ldr r0, _0802A310 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + ldr r0, _0802A314 @ =0x00000902\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0802A24C\n\ + ldr r0, _0802A318 @ =gTrainerBattleOpponent\n\ + ldrh r1, [r0]\n\ + movs r0, 0x80\n\ + lsls r0, 3\n\ + cmp r1, r0\n\ + bne _0802A2EE\n\ +_0802A24C:\n\ + ldr r4, _0802A30C @ =gBankAttacker\n\ + ldrb r0, [r4]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + ldr r0, _0802A310 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + ldr r0, _0802A314 @ =0x00000902\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0802A290\n\ + ldr r0, _0802A318 @ =gTrainerBattleOpponent\n\ + ldrh r1, [r0]\n\ + movs r0, 0x80\n\ + lsls r0, 3\n\ + cmp r1, r0\n\ + beq _0802A290\n\ + ldr r0, _0802A31C @ =gWishFutureKnock\n\ + adds r0, 0x29\n\ + adds r0, r2, r0\n\ + ldrb r1, [r0]\n\ + ldr r3, _0802A320 @ =gBitTable\n\ + ldr r2, _0802A324 @ =gBattlePartyID\n\ + ldrb r0, [r4]\n\ + lsls r0, 1\n\ + adds r0, r2\n\ + ldrh r0, [r0]\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldr r0, [r0]\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + bne _0802A2EE\n\ +_0802A290:\n\ + ldr r0, _0802A328 @ =gBattleMons\n\ + mov r9, r0\n\ + ldr r1, _0802A30C @ =gBankAttacker\n\ + ldrb r4, [r1]\n\ + movs r2, 0x58\n\ + mov r8, r2\n\ + mov r0, r8\n\ + muls r0, r4\n\ + mov r3, r9\n\ + adds r5, r0, r3\n\ + ldrh r3, [r5, 0x2E]\n\ + adds r1, r3, 0\n\ + cmp r1, 0\n\ + bne _0802A2BE\n\ + ldr r0, _0802A32C @ =gBankTarget\n\ + ldrb r0, [r0]\n\ + mov r2, r8\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + add r0, r9\n\ + ldrh r0, [r0, 0x2E]\n\ + cmp r0, 0\n\ + beq _0802A2EE\n\ +_0802A2BE:\n\ + cmp r1, 0xAF\n\ + beq _0802A2EE\n\ + ldr r7, _0802A32C @ =gBankTarget\n\ + ldrb r0, [r7]\n\ + mov r1, r8\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + mov r1, r9\n\ + adds r2, r0, r1\n\ + ldrh r1, [r2, 0x2E]\n\ + cmp r1, 0xAF\n\ + beq _0802A2EE\n\ + adds r0, r3, 0\n\ + subs r0, 0x79\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0xB\n\ + bls _0802A2EE\n\ + adds r0, r1, 0\n\ + subs r0, 0x79\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0xB\n\ + bhi _0802A334\n\ +_0802A2EE:\n\ + ldr r3, _0802A330 @ =gBattlescriptCurrInstr\n\ + ldr r2, [r3]\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2, 0x2]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 16\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + lsls r0, 24\n\ + orrs r1, r0\n\ + str r1, [r3]\n\ + b _0802A49A\n\ + .align 2, 0\n\ +_0802A30C: .4byte gBankAttacker\n\ +_0802A310: .4byte gBattleTypeFlags\n\ +_0802A314: .4byte 0x00000902\n\ +_0802A318: .4byte gTrainerBattleOpponent\n\ +_0802A31C: .4byte gWishFutureKnock\n\ +_0802A320: .4byte gBitTable\n\ +_0802A324: .4byte gBattlePartyID\n\ +_0802A328: .4byte gBattleMons\n\ +_0802A32C: .4byte gBankTarget\n\ +_0802A330: .4byte gBattlescriptCurrInstr\n\ +_0802A334:\n\ + adds r0, r2, 0\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x3C\n\ + bne _0802A36C\n\ + ldr r1, _0802A360 @ =gBattlescriptCurrInstr\n\ + ldr r0, _0802A364 @ =BattleScript_NoItemSteal\n\ + str r0, [r1]\n\ + ldr r1, _0802A368 @ =gLastUsedAbility\n\ + ldrb r0, [r7]\n\ + mov r2, r8\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + add r0, r9\n\ + adds r0, 0x20\n\ + ldrb r0, [r0]\n\ + strb r0, [r1]\n\ + ldrb r0, [r7]\n\ + ldrb r1, [r1]\n\ + bl RecordAbilityBattle\n\ + b _0802A49A\n\ + .align 2, 0\n\ +_0802A360: .4byte gBattlescriptCurrInstr\n\ +_0802A364: .4byte BattleScript_NoItemSteal\n\ +_0802A368: .4byte gLastUsedAbility\n\ +_0802A36C:\n\ + lsls r0, r4, 1\n\ + ldr r4, _0802A458 @ =0x020160f0\n\ + adds r6, r0, r4\n\ + ldrh r5, [r5, 0x2E]\n\ + mov r10, r5\n\ + strh r1, [r6]\n\ + ldr r3, _0802A45C @ =gBankAttacker\n\ + ldrb r0, [r3]\n\ + mov r1, r8\n\ + muls r1, r0\n\ + adds r0, r1, 0\n\ + add r0, r9\n\ + movs r1, 0\n\ + strh r1, [r0, 0x2E]\n\ + ldrb r0, [r7]\n\ + mov r2, r8\n\ + muls r2, r0\n\ + adds r0, r2, 0\n\ + add r0, r9\n\ + mov r3, r10\n\ + strh r3, [r0, 0x2E]\n\ + ldr r5, _0802A460 @ =gActiveBank\n\ + ldr r1, _0802A45C @ =gBankAttacker\n\ + ldrb r0, [r1]\n\ + strb r0, [r5]\n\ + str r6, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + movs r2, 0\n\ + movs r3, 0x2\n\ + bl EmitSetAttributes\n\ + ldr r2, _0802A45C @ =gBankAttacker\n\ + ldrb r0, [r2]\n\ + bl MarkBufferBankForExecution\n\ + ldrb r0, [r7]\n\ + strb r0, [r5]\n\ + ldrb r0, [r7]\n\ + mov r3, r8\n\ + muls r3, r0\n\ + adds r0, r3, 0\n\ + mov r1, r9\n\ + adds r1, 0x2E\n\ + adds r0, r1\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + movs r2, 0\n\ + movs r3, 0x2\n\ + bl EmitSetAttributes\n\ + ldrb r0, [r7]\n\ + bl MarkBufferBankForExecution\n\ + ldr r0, _0802A464 @ =0xfffe9f10\n\ + adds r4, r0\n\ + ldrb r0, [r7]\n\ + lsls r0, 1\n\ + ldr r2, _0802A468 @ =0x000160e8\n\ + adds r0, r2\n\ + adds r0, r4\n\ + movs r1, 0\n\ + strb r1, [r0]\n\ + ldrb r0, [r7]\n\ + lsls r0, 1\n\ + ldr r1, _0802A46C @ =0x000160e9\n\ + adds r0, r1\n\ + adds r0, r4\n\ + movs r3, 0\n\ + strb r3, [r0]\n\ + ldr r3, _0802A45C @ =gBankAttacker\n\ + ldrb r0, [r3]\n\ + lsls r0, 1\n\ + adds r0, r2\n\ + adds r0, r4\n\ + movs r2, 0\n\ + strb r2, [r0]\n\ + ldrb r0, [r3]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + adds r0, r4\n\ + strb r2, [r0]\n\ + ldr r1, _0802A470 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x5\n\ + str r0, [r1]\n\ + ldr r1, _0802A474 @ =gBattleTextBuff1\n\ + movs r3, 0xFD\n\ + strb r3, [r1]\n\ + movs r2, 0xA\n\ + strb r2, [r1, 0x1]\n\ + ldrh r0, [r6]\n\ + strb r0, [r1, 0x2]\n\ + ldrh r0, [r6]\n\ + lsrs r0, 8\n\ + strb r0, [r1, 0x3]\n\ + movs r0, 0xFF\n\ + strb r0, [r1, 0x4]\n\ + ldr r1, _0802A478 @ =gBattleTextBuff2\n\ + strb r3, [r1]\n\ + strb r2, [r1, 0x1]\n\ + mov r3, r10\n\ + strb r3, [r1, 0x2]\n\ + mov r2, r10\n\ + lsrs r0, r2, 8\n\ + strb r0, [r1, 0x3]\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + strb r0, [r1, 0x4]\n\ + cmp r2, 0\n\ + beq _0802A480\n\ + ldrh r0, [r6]\n\ + cmp r0, 0\n\ + beq _0802A494\n\ + ldr r1, _0802A47C @ =gBattleCommunication\n\ + movs r0, 0x2\n\ + b _0802A498\n\ + .align 2, 0\n\ +_0802A458: .4byte 0x020160f0\n\ +_0802A45C: .4byte gBankAttacker\n\ +_0802A460: .4byte gActiveBank\n\ +_0802A464: .4byte 0xfffe9f10\n\ +_0802A468: .4byte 0x000160e8\n\ +_0802A46C: .4byte 0x000160e9\n\ +_0802A470: .4byte gBattlescriptCurrInstr\n\ +_0802A474: .4byte gBattleTextBuff1\n\ +_0802A478: .4byte gBattleTextBuff2\n\ +_0802A47C: .4byte gBattleCommunication\n\ +_0802A480:\n\ + ldrh r0, [r6]\n\ + cmp r0, 0\n\ + beq _0802A494\n\ + ldr r0, _0802A490 @ =gBattleCommunication\n\ + movs r3, 0\n\ + strb r3, [r0, 0x5]\n\ + b _0802A49A\n\ + .align 2, 0\n\ +_0802A490: .4byte gBattleCommunication\n\ +_0802A494:\n\ + ldr r1, _0802A4AC @ =gBattleCommunication\n\ + movs r0, 0x1\n\ +_0802A498:\n\ + strb r0, [r1, 0x5]\n\ +_0802A49A:\n\ + add sp, 0x4\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0802A4AC: .4byte gBattleCommunication\n\ + .syntax divided"); +} +#endif // NONMATCHING + +static void atkD3_copy_ability(void) //role play +{ + if (gBattleMons[gBankTarget].ability != 0 && gBattleMons[gBankTarget].ability != ABILITY_WONDER_GUARD) + { + gBattleMons[gBankAttacker].ability = gBattleMons[gBankTarget].ability; + gLastUsedAbility = gBattleMons[gBankTarget].ability; + gBattlescriptCurrInstr += 5; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkD4_wish_effect(void) +{ + switch (BSScriptRead8(gBattlescriptCurrInstr + 1)) + { + case 0: //use wish + if (gWishFutureKnock.wishCounter[gBankAttacker] == 0) + { + gWishFutureKnock.wishCounter[gBankAttacker] = 2; + gWishFutureKnock.wishUserID[gBankAttacker] = gBattlePartyID[gBankAttacker]; + gBattlescriptCurrInstr += 6; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + break; + case 1: //heal effect + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 4; + gBattleTextBuff1[2] = gBankTarget; + gBattleTextBuff1[3] = gWishFutureKnock.wishUserID[gBankTarget]; + gBattleTextBuff1[4] = 0xFF; + gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + else + gBattlescriptCurrInstr += 6; + break; + } +} + +static void atkD5_setroots(void) //ingrain +{ + if (gStatuses3[gBankAttacker] & STATUS3_ROOTED) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + gStatuses3[gBankAttacker] |= STATUS3_ROOTED; + gBattlescriptCurrInstr += 5; + } +} + +static void atkD6_doubledamagedealtifdamaged(void) +{ + if ((gProtectStructs[gBankAttacker].physicalDmg && gProtectStructs[gBankAttacker].physicalBank == gBankTarget) + || (gProtectStructs[gBankAttacker].specialDmg && gProtectStructs[gBankAttacker].specialBank == gBankTarget)) + BATTLE_STRUCT->dmgMultiplier = 2; + gBattlescriptCurrInstr++; +} + +static void atkD7_setyawn(void) +{ + if (gStatuses3[gBankTarget] & STATUS3_YAWN || (u8) gBattleMons[gBankTarget].status1) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + gStatuses3[gBankTarget] |= 0x1000; + gBattlescriptCurrInstr += 5; + } +} + +static void atkD8_setdamagetohealthdifference(void) +{ + if (gBattleMons[gBankTarget].hp <= gBattleMons[gBankAttacker].hp) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + gBattleMoveDamage = gBattleMons[gBankTarget].hp - gBattleMons[gBankAttacker].hp; + gBattlescriptCurrInstr += 5; + } +} + +static void atkD9_scaledamagebyhealthratio(void) +{ + if (gDynamicBasePower == 0) + { + u8 power = gBattleMoves[gCurrentMove].power; + gDynamicBasePower = gBattleMons[gBankAttacker].hp * power / gBattleMons[gBankAttacker].maxHP; + if (gDynamicBasePower == 0) + gDynamicBasePower = 1; + } + gBattlescriptCurrInstr++; +} + +static void atkDA_abilityswap(void) +{ + if ((gBattleMons[gBankAttacker].ability == 0 && gBattleMons[gBankTarget].ability == 0) + || gBattleMons[gBankAttacker].ability == ABILITY_WONDER_GUARD || gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD + || gBattleMoveFlags & MOVESTATUS_NOEFFECT) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + u8 atk_ability = gBattleMons[gBankAttacker].ability; + gBattleMons[gBankAttacker].ability = gBattleMons[gBankTarget].ability; + gBattleMons[gBankTarget].ability = atk_ability; + gBattlescriptCurrInstr += 5; + } +} + +static void atkDB_imprisoneffect(void) +{ + u8 r8 = 0; + if ((gStatuses3[gBankAttacker] & STATUS3_IMPRISIONED)) + { + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + else + { + u8 bank; + sub_801529C(gBankAttacker); + for (bank = 0; bank < gNoOfAllBanks; bank++) + { + if (r8 != GetBankSide(bank)) + { + int j; + for (j = 0; j < 4; j++) + { + int k; + for (k = 0; k < 4; k++) + { + if (gBattleMons[gBankAttacker].moves[j] == gBattleMons[bank].moves[k] && gBattleMons[gBankAttacker].moves[j]) + break; + } + if (k != 4) + break; + } + if (j != 4) + { + gStatuses3[gBankAttacker] |= STATUS3_IMPRISIONED; + gBattlescriptCurrInstr += 5; + break; + } + } + } + if (bank == gNoOfAllBanks) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } +} + +static void atkDC_setgrudge(void) +{ + if (gStatuses3[gBankAttacker] & STATUS3_GRUDGE) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + gStatuses3[gBankAttacker] |= STATUS3_GRUDGE; + gBattlescriptCurrInstr += 5; + } +} + +static void atkDD_weightdamagecalculation(void) +{ + int i; + for (i = 0; sWeightDamage[i] != 0xFFFF; i += 2) + { + if (sWeightDamage[i] > GetPokedexHeightWeight(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), 1)) + break; + } + if (sWeightDamage[i] != 0xFFFF) + gDynamicBasePower = sWeightDamage[i + 1]; + else + gDynamicBasePower = 120; + gBattlescriptCurrInstr++; +} + +#ifdef NONMATCHING +static void atkDE_asistattackselect(void) +{ + u32 chooseable_moves_no = 0; + struct Pokemon* party; + int i, j; + u16* chooseable_moves; + if (GetBankIdentity(gBankAttacker) & 1) + party = gEnemyParty; + else + party = gPlayerParty; + + for (i = 0; i < 6; i++) + { + if (i == gBattlePartyID[gBankAttacker]) + break; + if (!GetMonData(&party[i], MON_DATA_SPECIES2) || GetMonData(&party[i], MON_DATA_SPECIES2) == SPECIES_EGG) + break; + chooseable_moves = &BATTLE_STRUCT->assistMove[chooseable_moves_no]; + for (j = 0; j < 4; j++) + { + int k; + u16 move = GetMonData(&party[i], MON_DATA_MOVE1 + i); + if (IsMoveUnchoosable(move)) + break; + //sUnknown_081FACFE[k] + for (k = 0; ;k++) + { + if (sUnknown_081FACFE[k] == 0xFFFF) + { + if (move) + { + *chooseable_moves = move; + chooseable_moves++; + chooseable_moves_no++; + } + break; + } + if (sUnknown_081FACFE[k] == move) + break; + } + } + } + if (chooseable_moves_no) + { + gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); + gRandomMove = BATTLE_STRUCT->assistMove[Random() % chooseable_moves_no]; + gBankTarget = GetMoveTarget(gRandomMove, 0); + gBattlescriptCurrInstr += 5; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +#else +__attribute__((naked)) +static void atkDE_asistattackselect(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x8\n\ + movs r0, 0\n\ + mov r10, r0\n\ + ldr r0, _0802AB9C @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + bl GetBankIdentity\n\ + movs r1, 0x1\n\ + ands r1, r0\n\ + ldr r0, _0802ABA0 @ =gPlayerParty\n\ + str r0, [sp]\n\ + cmp r1, 0\n\ + beq _0802AAAC\n\ + ldr r1, _0802ABA4 @ =gEnemyParty\n\ + str r1, [sp]\n\ +_0802AAAC:\n\ + movs r2, 0\n\ +_0802AAAE:\n\ + ldr r1, _0802ABA8 @ =gBattlePartyID\n\ + ldr r0, _0802AB9C @ =gBankAttacker\n\ + ldrb r0, [r0]\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + adds r1, r2, 0x1\n\ + str r1, [sp, 0x4]\n\ + ldrh r0, [r0]\n\ + cmp r2, r0\n\ + beq _0802AB54\n\ + movs r0, 0x64\n\ + adds r6, r2, 0\n\ + muls r6, r0\n\ + ldr r0, [sp]\n\ + adds r4, r0, r6\n\ + adds r0, r4, 0\n\ + movs r1, 0x41\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0802AB54\n\ + adds r0, r4, 0\n\ + movs r1, 0x41\n\ + bl GetMonData\n\ + movs r1, 0xCE\n\ + lsls r1, 1\n\ + cmp r0, r1\n\ + beq _0802AB54\n\ + movs r5, 0\n\ + ldr r1, _0802ABAC @ =0x0000ffff\n\ + mov r8, r1\n\ + mov r9, r6\n\ + mov r1, r10\n\ + lsls r0, r1, 1\n\ + ldr r1, _0802ABB0 @ =0x02016024\n\ + adds r6, r0, r1\n\ +_0802AAF8:\n\ + movs r7, 0\n\ + adds r1, r5, 0\n\ + adds r1, 0xD\n\ + ldr r0, [sp]\n\ + add r0, r9\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + adds r0, r4, 0\n\ + bl IsMoveUnchoosable\n\ + lsls r0, 24\n\ + adds r1, r5, 0x1\n\ + cmp r0, 0\n\ + bne _0802AB4E\n\ + ldr r0, _0802ABB4 @ =sUnknown_081FACFE\n\ + ldrh r2, [r0]\n\ + adds r3, r0, 0\n\ + cmp r2, r8\n\ + beq _0802AB42\n\ + cmp r4, r2\n\ + beq _0802AB38\n\ + ldr r5, _0802ABAC @ =0x0000ffff\n\ + adds r2, r3, 0\n\ +_0802AB2A:\n\ + adds r2, 0x2\n\ + adds r7, 0x1\n\ + ldrh r0, [r2]\n\ + cmp r0, r5\n\ + beq _0802AB42\n\ + cmp r4, r0\n\ + bne _0802AB2A\n\ +_0802AB38:\n\ + lsls r0, r7, 1\n\ + adds r0, r3\n\ + ldrh r0, [r0]\n\ + cmp r0, r8\n\ + bne _0802AB4E\n\ +_0802AB42:\n\ + cmp r4, 0\n\ + beq _0802AB4E\n\ + strh r4, [r6]\n\ + adds r6, 0x2\n\ + movs r0, 0x1\n\ + add r10, r0\n\ +_0802AB4E:\n\ + adds r5, r1, 0\n\ + cmp r5, 0x3\n\ + ble _0802AAF8\n\ +_0802AB54:\n\ + ldr r2, [sp, 0x4]\n\ + cmp r2, 0x5\n\ + ble _0802AAAE\n\ + mov r1, r10\n\ + cmp r1, 0\n\ + beq _0802ABCC\n\ + ldr r2, _0802ABB8 @ =gHitMarker\n\ + ldr r0, [r2]\n\ + ldr r1, _0802ABBC @ =0xfffffbff\n\ + ands r0, r1\n\ + str r0, [r2]\n\ + ldr r4, _0802ABC0 @ =gRandomMove\n\ + bl Random\n\ + movs r1, 0xFF\n\ + ands r1, r0\n\ + mov r0, r10\n\ + muls r0, r1\n\ + asrs r0, 8\n\ + lsls r0, 1\n\ + ldr r1, _0802ABB0 @ =0x02016024\n\ + adds r0, r1\n\ + ldrh r0, [r0]\n\ + strh r0, [r4]\n\ + ldrh r0, [r4]\n\ + movs r1, 0\n\ + bl GetMoveTarget\n\ + ldr r1, _0802ABC4 @ =gBankTarget\n\ + strb r0, [r1]\n\ + ldr r1, _0802ABC8 @ =gBattlescriptCurrInstr\n\ + ldr r0, [r1]\n\ + adds r0, 0x5\n\ + str r0, [r1]\n\ + b _0802ABE6\n\ + .align 2, 0\n\ +_0802AB9C: .4byte gBankAttacker\n\ +_0802ABA0: .4byte gPlayerParty\n\ +_0802ABA4: .4byte gEnemyParty\n\ +_0802ABA8: .4byte gBattlePartyID\n\ +_0802ABAC: .4byte 0x0000ffff\n\ +_0802ABB0: .4byte 0x02016024\n\ +_0802ABB4: .4byte sUnknown_081FACFE\n\ +_0802ABB8: .4byte gHitMarker\n\ +_0802ABBC: .4byte 0xfffffbff\n\ +_0802ABC0: .4byte gRandomMove\n\ +_0802ABC4: .4byte gBankTarget\n\ +_0802ABC8: .4byte gBattlescriptCurrInstr\n\ +_0802ABCC:\n\ + ldr r3, _0802ABF8 @ =gBattlescriptCurrInstr\n\ + ldr r2, [r3]\n\ + ldrb r1, [r2, 0x1]\n\ + ldrb r0, [r2, 0x2]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x3]\n\ + lsls r0, 16\n\ + orrs r1, r0\n\ + ldrb r0, [r2, 0x4]\n\ + lsls r0, 24\n\ + orrs r1, r0\n\ + str r1, [r3]\n\ +_0802ABE6:\n\ + add sp, 0x8\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0802ABF8: .4byte gBattlescriptCurrInstr\n\ + .syntax divided"); +} + +#endif // NONMATCHING + +static void atkDF_setmagiccoat(void) +{ + gBankTarget = gBankAttacker; + gSpecialStatuses[gBankAttacker].flag20 = 1; + if (gCurrentMoveTurn == gNoOfAllBanks - 1) //last turn + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + gProtectStructs[gBankAttacker].bounceMove = 1; + gBattlescriptCurrInstr += 5; + } +} + +static void atkE0_setstealstatchange(void) +{ + gSpecialStatuses[gBankAttacker].flag20 = 1; + if (gCurrentMoveTurn == gNoOfAllBanks - 1) //last turn + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + gProtectStructs[gBankAttacker].stealMove = 1; + gBattlescriptCurrInstr += 5; + } +} + +static void atkE1_intimidate_string_loader(void) +{ + u8 side; + + BATTLE_STRUCT->scriptingActive = ewram[0x160dd]; + side = GetBankSide(BATTLE_STRUCT->scriptingActive); + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 9; + gBattleTextBuff1[2] = gBattleMons[BATTLE_STRUCT->scriptingActive].ability; + gBattleTextBuff1[3] = 0xFF; + + for (;gBankTarget < gNoOfAllBanks; gBankTarget++) + { + if (GetBankSide(gBankTarget) == side) + continue; + if (!(gAbsentBankFlags & gBitTable[gBankTarget])) + break; + } + + if (gBankTarget >= gNoOfAllBanks) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + gBattlescriptCurrInstr += 5; +} + +static void atkE2_switchout_abilities(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + switch (gBattleMons[gActiveBank].ability) + { + case ABILITY_NATURAL_CURE: + gBattleMons[gActiveBank].status1 = 0; + EmitSetAttributes(0, REQUEST_STATUS_BATTLE, gBitTable[ewram[gActiveBank + 0x16064]], 4, &gBattleMons[gActiveBank].status1); + MarkBufferBankForExecution(gActiveBank); + break; + } + gBattlescriptCurrInstr += 2; +} + +static void atkE3_jumpiffainted(void) +{ + gActiveBank = GetBattleBank(BSScriptRead8(gBattlescriptCurrInstr + 1)); + if (gBattleMons[gActiveBank].hp == 0) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + else + gBattlescriptCurrInstr += 6; +} + +static void atkE4_getsecretpowereffect(void) +{ + switch (gBattleTerrain) + { + case BATTLE_TERRAIN_GRASS: + gBattleCommunication[MOVE_EFFECT_BYTE] = 2; + break; + case BATTLE_TERRAIN_LONG_GRASS: + gBattleCommunication[MOVE_EFFECT_BYTE] = 1; + break; + case BATTLE_TERRAIN_SAND: + gBattleCommunication[MOVE_EFFECT_BYTE] = 27; + break; + case BATTLE_TERRAIN_UNDERWATER: + gBattleCommunication[MOVE_EFFECT_BYTE] = 23; + break; + case BATTLE_TERRAIN_WATER: + gBattleCommunication[MOVE_EFFECT_BYTE] = 22; + break; + case BATTLE_TERRAIN_POND: + gBattleCommunication[MOVE_EFFECT_BYTE] = 24; + break; + case BATTLE_TERRAIN_MOUNTAIN: + gBattleCommunication[MOVE_EFFECT_BYTE] = 7; + break; + case BATTLE_TERRAIN_CAVE: + gBattleCommunication[MOVE_EFFECT_BYTE] = 8; + break; + default: + gBattleCommunication[MOVE_EFFECT_BYTE] = 5; + break; + } + gBattlescriptCurrInstr++; +} + +static void atkE5_pickup(void) +{ + int i; + for (i = 0; i < 6; i++) + { + u16 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2); + u16 held_item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); + u8 ability; + if (GetMonData(&gPlayerParty[i], MON_DATA_ALT_ABILITY)) + ability = gBaseStats[species].ability2; + else + ability = gBaseStats[species].ability1; + + if (ability == ABILITY_PICKUP && species != 0 && species != SPECIES_EGG && held_item == 0 && (Random() % 10) == 0) + { + s32 chance = Random() % 100; + s32 j; + for (j = 0; j < 18; j += 2) + { + if (sPickupItems[j + 1] > chance) + break; + } + SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, (const void*) &sPickupItems[j]); + } + } + gBattlescriptCurrInstr++; +} + +static void atkE6_castform_change_animation(void) +{ + gActiveBank = BATTLE_STRUCT->scriptingActive; + if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE) + BATTLE_STRUCT->castformToChangeInto |= 0x80; + EmitBattleAnimation(0, 0, BATTLE_STRUCT->castformToChangeInto); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr++; +} + +static void atkE7_castform_data_change(void) +{ + u8 form; + gBattlescriptCurrInstr++; + form = CastformDataTypeChange(BATTLE_STRUCT->scriptingActive); + if (form) + { + b_push_move_exec(BattleScript_CastformChange); + BATTLE_STRUCT->castformToChangeInto = form - 1; + } +} + +static void atkE8_settypebasedhalvers(void) //water/mud sport +{ + bool8 worked = FALSE; + if (gBattleMoves[gCurrentMove].effect == EFFECT_MUD_SPORT) + { + if (!(gStatuses3[gBankAttacker] & STATUS3_MUDSPORT)) + { + gStatuses3[gBankAttacker] |= STATUS3_MUDSPORT; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + worked = TRUE; + } + } + else //water sport + { + if (!(gStatuses3[gBankAttacker] & STATUS3_WATERSPORT)) + { + gStatuses3[gBankAttacker] |= STATUS3_WATERSPORT; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + worked = TRUE; + } + } + if (worked) + gBattlescriptCurrInstr += 5; + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkE9_setweatherballtype(void) +{ + if (WEATHER_HAS_EFFECT) + { + if ((u8)(gBattleWeather)) + BATTLE_STRUCT->dmgMultiplier = 2; + if (gBattleWeather & WEATHER_RAIN_ANY) + BATTLE_STRUCT->dynamicMoveType = TYPE_WATER | 0x80; + else if (gBattleWeather & WEATHER_SANDSTORM_ANY) + BATTLE_STRUCT->dynamicMoveType = TYPE_ROCK | 0x80; + else if (gBattleWeather & WEATHER_SUN_ANY) + BATTLE_STRUCT->dynamicMoveType = TYPE_FIRE | 0x80; + else if (gBattleWeather & WEATHER_HAIL) + BATTLE_STRUCT->dynamicMoveType = TYPE_ICE | 0x80; + else + BATTLE_STRUCT->dynamicMoveType = TYPE_NORMAL | 0x80; + } + gBattlescriptCurrInstr++; +} + +static void atkEA_recycleitem(void) +{ + u16* used_item; + gActiveBank = gBankAttacker; + used_item = USED_HELD_ITEM(gActiveBank); + if (*used_item && gBattleMons[gActiveBank].item == 0) + { + gLastUsedItem = *used_item; + *used_item = 0; + gBattleMons[gActiveBank].item = gLastUsedItem; + EmitSetAttributes(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gActiveBank].item); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr += 5; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkEB_settypetoterrain(void) +{ + if (gBattleMons[gBankAttacker].type1 != sTerrainToType[gBattleTerrain] && gBattleMons[gBankAttacker].type2 != sTerrainToType[gBattleTerrain]) + { + gBattleMons[gBankAttacker].type1 = sTerrainToType[gBattleTerrain]; + gBattleMons[gBankAttacker].type2 = sTerrainToType[gBattleTerrain]; + gBattleTextBuff1[0] = 0xFD; + gBattleTextBuff1[1] = 3; + gBattleTextBuff1[2] = sTerrainToType[gBattleTerrain]; + gBattleTextBuff1[3] = 0xFF; + gBattlescriptCurrInstr += 5; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkEC_pursuit_sth(void) +{ + gActiveBank = GetBankByPlayerAI(GetBankIdentity(gBankAttacker) ^ 2); + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gAbsentBankFlags & gBitTable[gActiveBank]) && gActionForBanks[gActiveBank] == 0 && gChosenMovesByBanks[gActiveBank] == MOVE_PURSUIT) + { + gUnknown_02024A76[gActiveBank] = 11; + gCurrentMove = MOVE_PURSUIT; + gBattlescriptCurrInstr += 5; + BATTLE_STRUCT->animTurn = 1; + BATTLE_STRUCT->unk160A7 = gBankAttacker; + gBankAttacker = gActiveBank; + } + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); +} + +static void atkED_802B4B4(void) +{ + gEffectBank = gBankAttacker; + if (gBankAttacker == gBankTarget) + gBankAttacker = gBankTarget = BATTLE_STRUCT->scriptingActive; + else + gBankTarget = BATTLE_STRUCT->scriptingActive; + BATTLE_STRUCT->scriptingActive = gEffectBank; + gBattlescriptCurrInstr++; +} + +static void atkEE_removelightscreenreflect(void) //brick break +{ + u8 side = GetBankSide(gBankAttacker) ^ 1; + if (gSideTimer[side].reflectTimer || gSideTimer[side].lightscreenTimer) + { + gSideAffecting[side] &= ~(SIDE_STATUS_REFLECT); + gSideAffecting[side] &= ~(SIDE_STATUS_LIGHTSCREEN); + gSideTimer[side].reflectTimer = 0; + gSideTimer[side].lightscreenTimer = 0; + BATTLE_STRUCT->animTurn = 1; + BATTLE_STRUCT->animTargetsHit = 1; + } + else + { + BATTLE_STRUCT->animTurn = 0; + BATTLE_STRUCT->animTargetsHit = 0; + } + gBattlescriptCurrInstr++; +} + +void atkEF_pokeball_catch_calculation(void) +{ + u8 ball_multiplier = 0; + if (gBattleExecBuffer) + return; + + gActiveBank = gBankAttacker; + gBankTarget = gBankAttacker ^ 1; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + EmitBallThrow(0, 5); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr = BattleScript_TrainerBallBlock; + } + else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) + { + EmitBallThrow(0, 4); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr = BattleScript_WallyBallThrow; + } + else + { + u32 odds; + u8 catch_rate; + if (gLastUsedItem == ITEM_SAFARI_BALL) + catch_rate = BATTLE_STRUCT->unk16089 * 1275 / 100; //correct the name to safariFleeRate + else + catch_rate = gBaseStats[gBattleMons[gBankTarget].species].catchRate; + if (gLastUsedItem > 5) + { + switch (gLastUsedItem) + { + case ITEM_NET_BALL: + if (gBattleMons[gBankTarget].type1 == TYPE_WATER || gBattleMons[gBankTarget].type2 == TYPE_WATER || gBattleMons[gBankTarget].type1 == TYPE_BUG || gBattleMons[gBankTarget].type2 == TYPE_BUG) + ball_multiplier = 30; + else + ball_multiplier = 10; + break; + case ITEM_DIVE_BALL: + if (Overworld_GetMapTypeOfSaveblockLocation() == 5) + ball_multiplier = 35; + else + ball_multiplier = 10; + break; + case ITEM_NEST_BALL: + if (gBattleMons[gBankTarget].level <= 39) + { + ball_multiplier = 40 - gBattleMons[gBankTarget].level; + if (ball_multiplier <= 9) + ball_multiplier = 10; + } + else + ball_multiplier = 10; + break; + case ITEM_REPEAT_BALL: + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), 1)) + ball_multiplier = 30; + else + ball_multiplier = 10; + break; + case ITEM_TIMER_BALL: + ball_multiplier = gBattleResults.battleTurnCounter + 10; + if (ball_multiplier > 40) + ball_multiplier = 40; + break; + case ITEM_LUXURY_BALL: + case ITEM_PREMIER_BALL: + ball_multiplier = 10; + break; + } + } + else + ball_multiplier = sBallCatchBonuses[gLastUsedItem - 2]; + + odds = (catch_rate * ball_multiplier / 10) * (gBattleMons[gBankTarget].maxHP * 3 - gBattleMons[gBankTarget].hp * 2) / (3 * gBattleMons[gBankTarget].maxHP); + if (gBattleMons[gBankTarget].status1 & (STATUS_SLEEP | STATUS_FREEZE)) + odds *= 2; + if (gBattleMons[gBankTarget].status1 & (STATUS_POISON | STATUS_BURN | STATUS_PARALYSIS /*| STATUS_TOXIC_POISON */)) //nice one gf + odds = (odds * 15) / 10; + + if (gLastUsedItem != ITEM_SAFARI_BALL) + { + if (gLastUsedItem == ITEM_MASTER_BALL) + { + gBattleResults.unk5_1 = 1; + } + else + { + if (gBattleResults.unk36[gLastUsedItem - ITEM_ULTRA_BALL] < 0xFF) + gBattleResults.unk36[gLastUsedItem - ITEM_ULTRA_BALL]++; + } + } + if (odds > 254) //poke caught + { + EmitBallThrow(0, 4); + MarkBufferBankForExecution(gActiveBank); + gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; + SetMonData(&gEnemyParty[gBattlePartyID[gBankTarget]], MON_DATA_POKEBALL, (const void*) &gLastUsedItem); + if (CalculatePlayerPartyCount() == 6) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else //poke may be caught, calculate shakes + { + u8 shakes; + odds = Sqrt(Sqrt(16711680 / odds)); + odds = 1048560 / odds; + for (shakes = 0; shakes < 4 && Random() < odds; shakes++) {} + if (gLastUsedItem == ITEM_MASTER_BALL) + shakes = 4; //why calculate the shakes before that check? + EmitBallThrow(0, shakes); + MarkBufferBankForExecution(gActiveBank); + if (shakes == 4) //poke caught, copy of the code above + { + gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; + SetMonData(&gEnemyParty[gBattlePartyID[gBankTarget]], MON_DATA_POKEBALL, (const void*) &gLastUsedItem); + if (CalculatePlayerPartyCount() == 6) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else //rip + { + gBattleCommunication[MULTISTRING_CHOOSER] = shakes; + gBattlescriptCurrInstr = BattleScript_ShakeBallThrow; + } + } + } +} + +static void atkF0_copy_caught_poke(void) +{ + GiveMonToPlayer(&gEnemyParty[gBattlePartyID[gBankAttacker ^ 1]]); + gBattleResults.caughtPoke = gBattleMons[gBankAttacker ^ 1].species; + GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ 1]], MON_DATA_NICKNAME, gBattleResults.caughtNick); + gBattlescriptCurrInstr++; +} + +static void atkF1_setpoke_as_caught(void) +{ + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), 1)) + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + else + { + GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), 3); + if (gBattleMons[gBankTarget].species == SPECIES_UNOWN) + gSaveBlock2.pokedex.unownPersonality = gBattleMons[gBankTarget].personality; + if (gBattleMons[gBankTarget].species == SPECIES_SPINDA) //else if + gSaveBlock2.pokedex.spindaPersonality = gBattleMons[gBankTarget].personality; + gBattlescriptCurrInstr += 5; + } +} + +extern const u32 gBattleTerrainTiles_Building[]; +extern const u32 gBattleTerrainTilemap_Building[]; +extern const u32 gBattleTerrainPalette_BattleTower[]; + +static void atkF2_display_dex_info(void) +{ + switch (gBattleCommunication[0]) + { + case 0: + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gBattleCommunication[0]++; + break; + case 1: + if (!gPaletteFade.active) + { + gBattleCommunication[1] = sub_809070C(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), gBattleMons[gBankTarget].otId, gBattleMons[gBankTarget].personality); + gBattleCommunication[0]++; + } + break; + case 2: + if (!gPaletteFade.active && gMain.callback2 == sub_800F808 && !gTasks[gBattleCommunication[1]].isActive) + { + LZDecompressVram(gBattleTerrainTiles_Building, (void*)(0x06008000)); + LZDecompressVram(gBattleTerrainTilemap_Building, (void*)(0x0600d000)); + LoadCompressedPalette(gBattleTerrainPalette_BattleTower, 0x20, 0x60); + REG_BG3CNT = 0x5a0b; + gUnknown_030041B0 = 0x100; + BeginNormalPaletteFade(0xfffc, 0, 0x10, 0, 0); + gBattleCommunication[0]++; + } + break; + case 3: + if (!gPaletteFade.active) + gBattlescriptCurrInstr++; + break; + } +} + +__attribute__((naked)) +void sub_802BBD4(u8 r0, u8 r1, u8 r2, u8 r3, u8 sp0) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + ldr r4, [sp, 0x20]\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + mov r12, r1\n\ + lsls r2, 24\n\ + lsrs r5, r2, 24\n\ + lsls r3, 24\n\ + lsrs r7, r3, 24\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + mov r8, r4\n\ + mov r2, r12\n\ + cmp r2, r7\n\ + bgt _0802BC5A\n\ + lsls r1, r6, 1\n\ + ldr r0, _0802BC20 @ =0x0600c000\n\ + adds r1, r0\n\ + mov r9, r1\n\ +_0802BC06:\n\ + adds r1, r6, 0\n\ + adds r0, r2, 0x1\n\ + mov r10, r0\n\ + cmp r1, r5\n\ + bgt _0802BC54\n\ + lsls r0, r2, 6\n\ + mov r4, r9\n\ + adds r3, r4, r0\n\ +_0802BC16:\n\ + cmp r2, r12\n\ + bne _0802BC28\n\ + ldr r0, _0802BC24 @ =0x00001022\n\ + b _0802BC36\n\ + .align 2, 0\n\ +_0802BC20: .4byte 0x0600c000\n\ +_0802BC24: .4byte 0x00001022\n\ +_0802BC28:\n\ + cmp r2, r7\n\ + bne _0802BC34\n\ + ldr r0, _0802BC30 @ =0x00001028\n\ + b _0802BC36\n\ + .align 2, 0\n\ +_0802BC30: .4byte 0x00001028\n\ +_0802BC34:\n\ + ldr r0, _0802BC68 @ =0x00001025\n\ +_0802BC36:\n\ + cmp r1, r6\n\ + beq _0802BC42\n\ + adds r0, 0x1\n\ + cmp r1, r5\n\ + bne _0802BC42\n\ + adds r0, 0x1\n\ +_0802BC42:\n\ + mov r4, r8\n\ + cmp r4, 0\n\ + beq _0802BC4A\n\ + movs r0, 0\n\ +_0802BC4A:\n\ + strh r0, [r3]\n\ + adds r3, 0x2\n\ + adds r1, 0x1\n\ + cmp r1, r5\n\ + ble _0802BC16\n\ +_0802BC54:\n\ + mov r2, r10\n\ + cmp r2, r7\n\ + ble _0802BC06\n\ +_0802BC5A:\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0802BC68: .4byte 0x00001025\n\ + .syntax divided"); +} + +void sub_802BC6C(void) +{ + sub_814A880(0xC8, ((gBattleCommunication[1] << 28) + 1207959552) >> 24); //what could that be? +} + +void nullsub_6(void) +{ + return; +} + +static void atkF3_nickname_caught_poke(void) +{ + switch (gBattleCommunication[0]) + { + case 0: + sub_8023A80(); + gBattleCommunication[0]++; + gBattleCommunication[1] = 0; + sub_802BC6C(); + break; + case 1: + if (gMain.newKeys & DPAD_UP && gBattleCommunication[1] != 0) + { + PlaySE(SE_SELECT); + nullsub_6(); + gBattleCommunication[1] = 0; + sub_802BC6C(); + } + if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[1] == 0) + { + PlaySE(SE_SELECT); + nullsub_6(); + gBattleCommunication[1] = 1; + sub_802BC6C(); + } + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if (gBattleCommunication[1] == 0) + { + gBattleCommunication[0]++; + BeginFastPaletteFade(3); + } + else + gBattleCommunication[0] = 4; + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gBattleCommunication[0] = 4; + } + break; + case 2: + if (!gPaletteFade.active) + { + GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ 1]], MON_DATA_NICKNAME, BATTLE_STRUCT->caughtNick); + DoNamingScreen(2, BATTLE_STRUCT->caughtNick, GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ 1]], MON_DATA_SPECIES), GetMonGender(&gEnemyParty[gBattlePartyID[gBankAttacker ^ 1]]), GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ 1]], MON_DATA_PERSONALITY, 0), sub_800F808); + gBattleCommunication[0]++; + } + break; + case 3: + if (gMain.callback2 == sub_800F808 && !gPaletteFade.active ) + { + SetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ 1]], MON_DATA_NICKNAME, BATTLE_STRUCT->caughtNick); + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + } + break; + case 4: + if (CalculatePlayerPartyCount() == 6) + gBattlescriptCurrInstr += 5; + else + gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + break; + } +} + +static void atkF4_802BEF0(void) +{ + gBattleMons[gBankAttacker].hp -= gBattleMoveDamage; + gBattlescriptCurrInstr++; +} + +static void atkF5_removeattackerstatus1(void) +{ + gBattleMons[gBankAttacker].status1 = 0; + gBattlescriptCurrInstr++; +} + +static void atkF6_802BF48(void) +{ + gFightStateTracker = 0xC; +} + +static void atkF7_802BF54(void) +{ + gFightStateTracker = 0xC; + gCurrentMoveTurn = gNoOfAllBanks; +} diff --git a/src/battle/battle_7.c b/src/battle/battle_7.c new file mode 100644 index 000000000..ad96510cf --- /dev/null +++ b/src/battle/battle_7.c @@ -0,0 +1,955 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_interface.h" +#include "blend_palette.h" +#include "data2.h" +#include "decompress.h" +#include "main.h" +#include "m4a.h" +#include "palette.h" +#include "pokemon.h" +#include "rom_8077ABC.h" +#include "rom_8094928.h" +#include "songs.h" +#include "sound.h" +#include "species.h" +#include "sprite.h" +#include "task.h" +#include "text.h" +#include "gba/m4a_internal.h" + +struct Struct2019348 +{ + u8 filler0[2]; + u16 unk2; + u8 filler4[4]; + u32 unk8; + u32 unkC; + u32 unk10; +}; + +extern u8 gBattleBufferA[][0x200]; +extern u8 gActiveBank; +extern u8 gNoOfAllBanks; +extern u16 gBattlePartyID[]; +extern u8 gBanksBySide[]; +extern u8 gObjectBankIDs[]; +extern u16 gUnknown_02024DE8; +extern u8 gDoingBattleAnim; +extern u32 gPID_perBank[]; +extern struct Window gUnknown_03004210; +extern void (*gBattleBankFunc[])(void); +extern u8 gHealthboxIDs[]; +extern u8 gUnknown_0300434C[]; +extern struct MusicPlayerInfo gMPlay_SE1; +extern struct MusicPlayerInfo gMPlay_SE2; +extern struct MusicPlayerInfo gMPlay_BGM; +extern u32 gBitTable[]; +extern u16 gBattleTypeFlags; +extern u8 gBattleMonForms[]; +extern u8 gBattleAnimBankAttacker; +extern u8 gBattleAnimBankTarget; +extern void (*gAnimScriptCallback)(void); +extern u8 gAnimScriptActive; +extern const u8 *const gBattleAnims_Unknown1[]; +extern const u8 *const gBattleAnims_Unknown2[]; +extern const struct CompressedSpriteSheet gTrainerFrontPicTable[]; +extern const struct MonCoords gTrainerFrontPicCoords[]; +extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; +extern const u8 gSubstituteDollTilemap[]; +extern const u8 gSubstituteDollGfx[]; +extern const u8 gSubstituteDollPal[]; +extern const struct CompressedSpriteSheet gUnknown_081FAF24; +extern const struct SpriteTemplate gSpriteTemplate_81FAF34; +extern const struct CompressedSpriteSheet gUnknown_0820A47C; +extern const struct CompressedSpriteSheet gUnknown_0820A484; +extern const struct CompressedSpriteSheet gUnknown_0820A48C[]; +extern const struct CompressedSpriteSheet gUnknown_0820A49C[]; +extern const struct CompressedSpriteSheet gUnknown_0820A4AC; +extern const struct CompressedSpriteSheet gUnknown_0820A4B4[]; +extern const struct SpritePalette gUnknown_0820A4D4[]; +extern const u8 gUnknown_08D09C48[]; + +#define ewram19348 (*(struct Struct2019348 *)(ewram + 0x19348)) + +extern void c3_0802FDF4(u8); +extern void sub_80440EC(); +extern void sub_804777C(); +extern void sub_8141828(); +extern u8 sub_8077ABC(); +extern u8 AnimBankSpriteExists(u8); +extern u8 sub_8077F68(u8); +extern u8 sub_8077F7C(u8); +extern void sub_8094958(void); +extern void sub_80105DC(struct Sprite *); +extern void move_anim_start_t2(); + +void sub_80315E8(u8); +u8 sub_803163C(u8); +void sub_80316CC(u8); +void sub_8031F0C(void); +void refresh_graphics_maybe(u8, u8, u8); +void sub_80324E0(u8 a); +void sub_80327CC(void); +void sub_8032978(struct Sprite *); +void sub_80328A4(struct Sprite *); + +void sub_80312F0(struct Sprite *sprite) +{ + u8 spriteId = sprite->data1; + + if (gSprites[spriteId].affineAnimEnded && !gSprites[spriteId].invisible) + { + if (gSprites[spriteId].animPaused) + gSprites[spriteId].animPaused = FALSE; + else if (gSprites[spriteId].animEnded) + { + gSprites[spriteId].callback = sub_80105DC; + StartSpriteAffineAnim(&gSprites[spriteId], 0); + sprite->callback = SpriteCallbackDummy; + } + } +} + +void unref_sub_8031364(struct Sprite *sprite, bool8 stupid) +{ + sprite->animPaused = TRUE; + sprite->callback = SpriteCallbackDummy; + if (!stupid) + StartSpriteAffineAnim(sprite, 1); + else + StartSpriteAffineAnim(sprite, 1); + AnimateSprite(sprite); +} + +void sub_80313A0(struct Sprite *sprite) +{ + if (!(gUnknown_02024DE8 & 1)) + { + sprite->pos2.x += sprite->data0; + if (sprite->pos2.x == 0) + sprite->callback = SpriteCallbackDummy; + } +} + +void move_anim_start_t2_for_situation(u8 a, u32 b) +{ + ewram17810[gActiveBank].unk0_4 = 1; + if (a == 0) + { + if (b == 0x20) + move_anim_start_t2(gActiveBank, 6); + else if (b == 8 || (b & 0x80)) + move_anim_start_t2(gActiveBank, 0); + else if (b == 0x10) + move_anim_start_t2(gActiveBank, 2); + else if (b & 7) + move_anim_start_t2(gActiveBank, 4); + else if (b == 0x40) + move_anim_start_t2(gActiveBank, 5); + else + ewram17810[gActiveBank].unk0_4 = 0; + } + else + { + if (b & 0x000F0000) + move_anim_start_t2(gActiveBank, 3); + else if (b & 7) + move_anim_start_t2(gActiveBank, 1); + else if (b & 0x10000000) + move_anim_start_t2(gActiveBank, 7); + else if (b & 0x08000000) + move_anim_start_t2(gActiveBank, 8); + else if (b & 0x0000E000) + move_anim_start_t2(gActiveBank, 9); + else + ewram17810[gActiveBank].unk0_4 = 0; + } +} + +bool8 move_anim_start_t3(u8 a, u8 b, u8 c, u8 d, u16 e) +{ + u8 taskId; + + if (d == 0 && (e & 0x80)) + { + gBattleMonForms[a] = e & 0x7F; + return TRUE; + } + if (ewram17800[a].substituteSprite && sub_803163C(d) == 0) + return TRUE; + if (ewram17800[a].substituteSprite && d == 2 && gSprites[gObjectBankIDs[a]].invisible) + { + refresh_graphics_maybe(a, 1, gObjectBankIDs[a]); + sub_80324E0(a); + return TRUE; + } + gBattleAnimBankAttacker = b; + gBattleAnimBankTarget = c; + ewram17840.unk0 = e; + DoMoveAnim(gBattleAnims_Unknown1, d, 0); + taskId = CreateTask(sub_80315E8, 10); + gTasks[taskId].data[0] = a; + ewram17810[gTasks[taskId].data[0]].unk0_5 = 1; + return FALSE; +} + +void sub_80315E8(u8 taskId) +{ + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + ewram17810[gTasks[taskId].data[0]].unk0_5 = 0; + DestroyTask(taskId); + } +} + +u8 sub_803163C(u8 a) +{ + switch (a) + { + case 2: + case 10: + case 11: + case 12: + case 13: + case 17: + return 1; + default: + return 0; + } +} + +void move_anim_start_t4(u8 a, u8 b, u8 c, u8 d) +{ + u8 taskId; + + gBattleAnimBankAttacker = b; + gBattleAnimBankTarget = c; + DoMoveAnim(gBattleAnims_Unknown2, d, 0); + taskId = CreateTask(sub_80316CC, 10); + gTasks[taskId].data[0] = a; + ewram17810[gTasks[taskId].data[0]].unk0_6 = 1; +} + +void sub_80316CC(u8 taskId) +{ + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + ewram17810[gTasks[taskId].data[0]].unk0_6 = 0; + DestroyTask(taskId); + } +} + +u8 sub_8031720(int unused1, int unused2) +{ + return 0; +} + +bool8 mplay_80342A4(u8 a) +{ + u8 zero = 0; + + if (IsSEPlaying()) + { + ewram17810[a].unk8++; + if (ewram17810[gActiveBank].unk8 < 30) + return TRUE; + m4aMPlayStop(&gMPlay_SE1); + m4aMPlayStop(&gMPlay_SE2); + } + if (zero == 0) + { + ewram17810[a].unk8 = 0; + return FALSE; + } + return TRUE; +} + +void BattleLoadOpponentMonSprite(struct Pokemon *pkmn, u8 b) +{ + u32 personalityValue; + u16 species; + u32 r7; + u32 otId; + u8 var; + u16 paletteOffset; + const u8 *lzPaletteData; + + personalityValue = GetMonData(pkmn, MON_DATA_PERSONALITY); + if (ewram17800[b].transformedSpecies == 0) + { + species = GetMonData(pkmn, MON_DATA_SPECIES); + r7 = personalityValue; + } + else + { + species = ewram17800[b].transformedSpecies; + r7 = gPID_perBank[b]; + } + otId = GetMonData(pkmn, MON_DATA_OT_ID); + var = GetBankIdentity(b); + HandleLoadSpecialPokePic( + &gMonFrontPicTable[species], + gMonFrontPicCoords[species].coords, + gMonFrontPicCoords[species].y_offset, + 0x02000000, + gUnknown_081FAF4C[var], + species, + r7); + paletteOffset = 0x100 + b * 16; + if (ewram17800[b].transformedSpecies == 0) + lzPaletteData = GetMonSpritePal(pkmn); + else + lzPaletteData = GetMonSpritePalFromOtIdPersonality(species, otId, personalityValue); + LZDecompressWram(lzPaletteData, ewram); + LoadPalette(ewram, paletteOffset, 0x20); + LoadPalette(ewram, 0x80 + b * 16, 0x20); + if (species == SPECIES_CASTFORM) + { + paletteOffset = 0x100 + b * 16; + LZDecompressWram(lzPaletteData, ewram + 0x16400); + LoadPalette(ewram + 0x16400 + gBattleMonForms[b] * 32, paletteOffset, 0x20); + } + if (ewram17800[b].transformedSpecies != 0) + { + BlendPalette(paletteOffset, 16, 6, 0x7FFF); + CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, 32); + } +} + +void BattleLoadPlayerMonSprite(struct Pokemon *pkmn, u8 b) +{ + u32 personalityValue; + u16 species; + u32 r7; + u32 otId; + u8 var; + u16 paletteOffset; + const u8 *lzPaletteData; + + personalityValue = GetMonData(pkmn, MON_DATA_PERSONALITY); + if (ewram17800[b].transformedSpecies == 0) + { + species = GetMonData(pkmn, MON_DATA_SPECIES); + r7 = personalityValue; + } + else + { + species = ewram17800[b].transformedSpecies; + r7 = gPID_perBank[b]; + } + otId = GetMonData(pkmn, MON_DATA_OT_ID); + var = GetBankIdentity(b); + HandleLoadSpecialPokePic( + &gMonBackPicTable[species], + gMonBackPicCoords[species].coords, + gMonBackPicCoords[species].y_offset, + 0x02000000, + gUnknown_081FAF4C[var], + species, + r7); + paletteOffset = 0x100 + b * 16; + if (ewram17800[b].transformedSpecies == 0) + lzPaletteData = GetMonSpritePal(pkmn); + else + lzPaletteData = GetMonSpritePalFromOtIdPersonality(species, otId, personalityValue); + LZDecompressWram(lzPaletteData, ewram); + LoadPalette(ewram, paletteOffset, 0x20); + LoadPalette(ewram, 0x80 + b * 16, 0x20); + if (species == SPECIES_CASTFORM) + { + paletteOffset = 0x100 + b * 16; + LZDecompressWram(lzPaletteData, ewram + 0x16400); + LoadPalette(ewram + 0x16400 + gBattleMonForms[b] * 32, paletteOffset, 0x20); + } + if (ewram17800[b].transformedSpecies != 0) + { + BlendPalette(paletteOffset, 16, 6, 0x7FFF); + CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, 32); + } +} + +void unref_sub_8031A64(void) +{ +} + +void nullsub_9(u16 unused) +{ +} + +void sub_8031A6C(u16 a, u8 b) +{ + u8 status; + struct CompressedSpriteSheet spriteSheet; + + status = GetBankIdentity(b); + DecompressPicFromTable_2( + &gTrainerFrontPicTable[a], + gTrainerFrontPicCoords[a].coords, + gTrainerFrontPicCoords[a].y_offset, + (void *)0x02000000, + gUnknown_081FAF4C[status], + 0); + spriteSheet.data = gUnknown_081FAF4C[status]; + spriteSheet.size = gTrainerFrontPicTable[a].size; + spriteSheet.tag = gTrainerFrontPicTable[a].tag; + LoadCompressedObjectPic(&spriteSheet); + LoadCompressedObjectPalette(&gTrainerFrontPicPaletteTable[a]); +} + +void LoadPlayerTrainerBankSprite(u16 a, u8 b) +{ + u8 status; + + status = GetBankIdentity(b); + DecompressPicFromTable_2( + &gTrainerBackPicTable[a], + gTrainerBackPicCoords[a].coords, + gTrainerBackPicCoords[a].y_offset, + (void *)0x02000000, + gUnknown_081FAF4C[status], + 0); + LoadCompressedPalette(gTrainerBackPicPaletteTable[a].data, 0x100 + b * 16, 32); +} + +void nullsub_10(int unused) +{ +} + +void sub_8031B74(u16 a) +{ + FreeSpritePaletteByTag(gTrainerFrontPicPaletteTable[a].tag); + FreeSpriteTilesByTag(gTrainerFrontPicTable[a].tag); +} + +void unref_sub_8031BA0(void) +{ + u8 count; + u8 i; + + LoadSpritePalette(&gUnknown_0820A4D4[0]); + LoadSpritePalette(&gUnknown_0820A4D4[1]); + if (!IsDoubleBattle()) + { + LoadCompressedObjectPic(&gUnknown_0820A47C); + LoadCompressedObjectPic(&gUnknown_0820A484); + count = 2; + } + else + { + LoadCompressedObjectPic(&gUnknown_0820A48C[0]); + LoadCompressedObjectPic(&gUnknown_0820A48C[1]); + LoadCompressedObjectPic(&gUnknown_0820A49C[0]); + LoadCompressedObjectPic(&gUnknown_0820A49C[1]); + count = 4; + } + for (i = 0; i < count; i++) + LoadCompressedObjectPic(&gUnknown_0820A4B4[gBanksBySide[i]]); +} + +bool8 sub_8031C30(u8 a) +{ + bool8 retVal = FALSE; + + if (a != 0) + { + if (a == 1) + { + LoadSpritePalette(&gUnknown_0820A4D4[0]); + LoadSpritePalette(&gUnknown_0820A4D4[1]); + } + else if (!IsDoubleBattle()) + { + if (a == 2) + { + if (gBattleTypeFlags & 0x80) + LoadCompressedObjectPic(&gUnknown_0820A4AC); + else + LoadCompressedObjectPic(&gUnknown_0820A47C); + } + else if (a == 3) + LoadCompressedObjectPic(&gUnknown_0820A484); + else if (a == 4) + LoadCompressedObjectPic(&gUnknown_0820A4B4[gBanksBySide[0]]); + else if (a == 5) + LoadCompressedObjectPic(&gUnknown_0820A4B4[gBanksBySide[1]]); + else + retVal = TRUE; + } + else + { + if (a == 2) + LoadCompressedObjectPic(&gUnknown_0820A48C[0]); + else if (a == 3) + LoadCompressedObjectPic(&gUnknown_0820A48C[1]); + else if (a == 4) + LoadCompressedObjectPic(&gUnknown_0820A49C[0]); + else if (a == 5) + LoadCompressedObjectPic(&gUnknown_0820A49C[1]); + else if (a == 6) + LoadCompressedObjectPic(&gUnknown_0820A4B4[gBanksBySide[0]]); + else if (a == 7) + LoadCompressedObjectPic(&gUnknown_0820A4B4[gBanksBySide[1]]); + else if (a == 8) + LoadCompressedObjectPic(&gUnknown_0820A4B4[gBanksBySide[2]]); + else if (a == 9) + LoadCompressedObjectPic(&gUnknown_0820A4B4[gBanksBySide[3]]); + else + retVal = TRUE; + } + } + return retVal; +} + +void load_gfxc_health_bar(void) +{ + LZDecompressWram(gUnknown_08D09C48, (void *)0x02000000); +} + +u8 battle_load_something(u8 *pState, u8 *b) +{ + bool8 retVal = FALSE; + + switch (*pState) + { + case 0: + sub_8031F0C(); + (*pState)++; + break; + case 1: + if (sub_8031C30(*b) == 0) + { + (*b)++; + } + else + { + *b = 0; + (*pState)++; + } + break; + case 2: + (*pState)++; + break; + case 3: + if ((gBattleTypeFlags & 0x80) && *b == 0) + gHealthboxIDs[*b] = battle_make_oam_safari_battle(); + else + gHealthboxIDs[*b] = battle_make_oam_normal_battle(*b); + (*b)++; + if (*b == gNoOfAllBanks) + { + *b = 0; + (*pState)++; + } + break; + case 4: + sub_8043F44(*b); + if (gBanksBySide[*b] <= 1) + nullsub_11(gHealthboxIDs[*b], 0); + else + nullsub_11(gHealthboxIDs[*b], 1); + (*b)++; + if (*b == gNoOfAllBanks) + { + *b = 0; + (*pState)++; + } + break; + case 5: + if (GetBankSide(*b) == 0) + { + if (!(gBattleTypeFlags & 0x80)) + sub_8045A5C(gHealthboxIDs[*b], &gPlayerParty[gBattlePartyID[*b]], 0); + } + else + { + sub_8045A5C(gHealthboxIDs[*b], &gEnemyParty[gBattlePartyID[*b]], 0); + } + sub_8043DB0(gHealthboxIDs[*b]); + (*b)++; + if (*b == gNoOfAllBanks) + { + *b = 0; + (*pState)++; + } + break; + case 6: + sub_80327CC(); + sub_8094958(); + retVal = TRUE; + break; + } + return retVal; +} + +void sub_8031EE8(void) +{ + memset(ewram17810, 0, 0x30); + memset(&ewram17840, 0, 0x10); +} + +void sub_8031F0C(void) +{ + sub_8031EE8(); + memset(ewram17800, 0, 0x10); +} + +void sub_8031F24(void) +{ + s32 i; + + for (i = 0; i < gNoOfAllBanks; i++) + ewram17800[i].invisible = gSprites[gObjectBankIDs[i]].invisible; +} + +void sub_8031F88(u8 a) +{ + ewram17800[a].invisible = gSprites[gObjectBankIDs[a]].invisible; +} + +void sub_8031FC4(u8 a, u8 b, bool8 c) +{ + u16 paletteOffset; + u16 species; + u32 personalityValue; + u32 otId; + u8 r10; + const u8 *lzPaletteData; + + if (c) + { + StartSpriteAnim(&gSprites[gObjectBankIDs[a]], ewram17840.unk0); + paletteOffset = 0x100 + a * 16; + LoadPalette(ewram + 0x16400 + ewram17840.unk0 * 32, paletteOffset, 32); + gBattleMonForms[a] = ewram17840.unk0; + if (ewram17800[a].transformedSpecies != 0) + { + BlendPalette(paletteOffset, 16, 6, 0x7FFF); + CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, 32); + } + gSprites[gObjectBankIDs[a]].pos1.y = sub_8077F68(a); + } + else + { + const void *src; + void *dst; + + if (IsContest()) + { + r10 = 0; + species = ewram19348.unk2; + personalityValue = ewram19348.unk8; + otId = ewram19348.unkC; + HandleLoadSpecialPokePic( + &gMonBackPicTable[species], + gMonBackPicCoords[species].coords, + gMonBackPicCoords[species].y_offset, + 0x02000000, + gUnknown_081FAF4C[0], + species, + ewram19348.unk10); + } + else + { + r10 = GetBankIdentity(a); + if (GetBankSide(b) == 1) + species = GetMonData(&gEnemyParty[gBattlePartyID[b]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlePartyID[b]], MON_DATA_SPECIES); + if (GetBankSide(a) == 0) + { + personalityValue = GetMonData(&gPlayerParty[gBattlePartyID[a]], MON_DATA_PERSONALITY); + otId = GetMonData(&gPlayerParty[gBattlePartyID[a]], MON_DATA_OT_ID); + HandleLoadSpecialPokePic( + &gMonBackPicTable[species], + gMonBackPicCoords[species].coords, + gMonBackPicCoords[species].y_offset, + 0x02000000, + gUnknown_081FAF4C[r10], + species, + gPID_perBank[a]); + } + else + { + personalityValue = GetMonData(&gEnemyParty[gBattlePartyID[a]], MON_DATA_PERSONALITY); + otId = GetMonData(&gEnemyParty[gBattlePartyID[a]], MON_DATA_OT_ID); + HandleLoadSpecialPokePic( + &gMonFrontPicTable[species], + gMonFrontPicCoords[species].coords, + gMonFrontPicCoords[species].y_offset, + 0x02000000, + gUnknown_081FAF4C[r10], + species, + gPID_perBank[a]); + } + } + src = gUnknown_081FAF4C[r10]; + dst = (void *)(VRAM + 0x10000 + gSprites[gObjectBankIDs[a]].oam.tileNum * 32); + DmaCopy32(3, src, dst, 0x800); + paletteOffset = 0x100 + a * 16; + lzPaletteData = GetMonSpritePalFromOtIdPersonality(species, otId, personalityValue); + LZDecompressWram(lzPaletteData, ewram); + LoadPalette(ewram, paletteOffset, 32); + if (species == SPECIES_CASTFORM) + { + u16 *paletteSrc = (u16 *)(ewram + 0x16400); + + LZDecompressWram(lzPaletteData, paletteSrc); + LoadPalette(paletteSrc + gBattleMonForms[b] * 16, paletteOffset, 32); + } + BlendPalette(paletteOffset, 16, 6, 0x7FFF); + CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, 32); + if (!IsContest()) + { + ewram17800[a].transformedSpecies = species; + gBattleMonForms[a] = gBattleMonForms[b]; + } + gSprites[gObjectBankIDs[a]].pos1.y = sub_8077F68(a); + StartSpriteAnim(&gSprites[gObjectBankIDs[a]], gBattleMonForms[a]); + } +} + +void BattleLoadSubstituteSprite(u8 a, u8 b) +{ + u8 r4; + u16 foo; + const u8 *gSubstituteDollPal_; + void *src; + s32 i; + + if (b == 0) + { + if (IsContest()) + r4 = 0; + else + r4 = GetBankIdentity(a); + if (IsContest()) + LZDecompressVram(gSubstituteDollTilemap, gUnknown_081FAF4C[r4]); + else if (GetBankSide(a) != 0) + LZDecompressVram(gSubstituteDollGfx, gUnknown_081FAF4C[r4]); + else + LZDecompressVram(gSubstituteDollTilemap, gUnknown_081FAF4C[r4]); + // There is probably a way to do this without all the temp variables, but I couldn't figure it out. + foo = a * 16; + gSubstituteDollPal_ = gSubstituteDollPal; + src = gUnknown_081FAF4C[r4]; + for (i = 0; i < 3; i++) + DmaCopy32(3, src, src + i * 0x800 + 0x800, 0x800); + LoadCompressedPalette(gSubstituteDollPal_, 0x100 + foo, 32); + } + else + { + if (!IsContest()) + { + if (GetBankSide(a) != 0) + BattleLoadOpponentMonSprite(&gEnemyParty[gBattlePartyID[a]], a); + else + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[a]], a); + } + } +} + +void refresh_graphics_maybe(u8 a, u8 b, u8 spriteId) +{ + BattleLoadSubstituteSprite(a, b); + StartSpriteAnim(&gSprites[spriteId], gBattleMonForms[a]); + if (b == 0) + gSprites[spriteId].pos1.y = sub_8077F7C(a); + else + gSprites[spriteId].pos1.y = sub_8077F68(a); +} + +void sub_80324BC(u8 a, u16 b) +{ + if (b == 0xA4) + ewram17800[a].substituteSprite = 1; +} + +void sub_80324E0(u8 a) +{ + ewram17800[a].substituteSprite = 0; +} + +void sub_80324F8(struct Pokemon *pkmn, u8 b) +{ + u16 hp = GetMonData(pkmn, MON_DATA_HP); + u16 maxHP = GetMonData(pkmn, MON_DATA_MAX_HP); + + if (GetHPBarLevel(hp, maxHP) == 1) + { + if (!ewram17800[b].unk0_1) + { + if (!ewram17800[b ^ 2].unk0_1) + PlaySE(SE_HINSI); + ewram17800[b].unk0_1 = 1; + } + } + else + { + ewram17800[b].unk0_1 = 0; + if (!IsDoubleBattle()) + { + m4aSongNumStop(SE_HINSI); + return; + } + if (IsDoubleBattle() && !ewram17800[b ^ 2].unk0_1) + { + m4aSongNumStop(SE_HINSI); + return; + } + } +} + +void BattleMusicStop(void) +{ + u8 r4 = GetBankByPlayerAI(0); + + ewram17800[r4].unk0_1 = 0; + if (IsDoubleBattle()) + ewram17800[r4 ^ 2].unk0_1 = 0; + m4aSongNumStop(SE_HINSI); +} + +u8 unref_sub_8032604(struct Pokemon *pkmn) +{ + u16 hp = GetMonData(pkmn, MON_DATA_HP); + u16 maxHP = GetMonData(pkmn, MON_DATA_MAX_HP); + + return GetHPBarLevel(hp, maxHP); +} + +void sub_8032638(void) +{ + if (gMain.inBattle) + { + u8 r8 = GetBankByPlayerAI(0); + u8 r9 = GetBankByPlayerAI(2); + u8 r4 = pokemon_order_func(gBattlePartyID[r8]); + u8 r5 = pokemon_order_func(gBattlePartyID[r9]); + + if (GetMonData(&gPlayerParty[r4], MON_DATA_HP) != 0) + sub_80324F8(&gPlayerParty[r4], r8); + if (IsDoubleBattle()) + { + if (GetMonData(&gPlayerParty[r5], MON_DATA_HP) != 0) + sub_80324F8(&gPlayerParty[r5], r9); + } + } +} + +void sub_80326EC(u8 a) +{ + s32 i; + + for (i = 0; i < gNoOfAllBanks; i++) + { + if (AnimBankSpriteExists(i) != 0) + { + gSprites[gObjectBankIDs[i]].oam.affineMode = a; + if (a == 0) + { + ewram17810[i].unk6 = gSprites[gObjectBankIDs[i]].oam.matrixNum; + gSprites[gObjectBankIDs[i]].oam.matrixNum = 0; + } + else + { + gSprites[gObjectBankIDs[i]].oam.matrixNum = ewram17810[i].unk6; + } + } + } +} + +void sub_80327CC(void) +{ + u8 r5; + + LoadCompressedObjectPic(&gUnknown_081FAF24); + r5 = GetBankByPlayerAI(1); + ewram17810[r5].unk7 = CreateSprite(&gSpriteTemplate_81FAF34, sub_8077ABC(r5, 0), sub_8077ABC(r5, 1) + 32, 0xC8); + gSprites[ewram17810[r5].unk7].data0 = r5; + if (IsDoubleBattle()) + { + r5 = GetBankByPlayerAI(3); + ewram17810[r5].unk7 = CreateSprite(&gSpriteTemplate_81FAF34, sub_8077ABC(r5, 0), sub_8077ABC(r5, 1) + 32, 0xC8); + gSprites[ewram17810[r5].unk7].data0 = r5; + } +} + +void sub_80328A4(struct Sprite *sprite) +{ + bool8 invisible = FALSE; + u8 r4 = sprite->data0; + struct Sprite *r7 = &gSprites[gObjectBankIDs[r4]]; + + if (!r7->inUse || AnimBankSpriteExists(r4) == 0) + { + sprite->callback = sub_8032978; + return; + } + if (gAnimScriptActive || r7->invisible) + invisible = TRUE; + else if (ewram17800[r4].transformedSpecies != 0 && gEnemyMonElevation[ewram17800[r4].transformedSpecies] == 0) + invisible = TRUE; + if (ewram17800[r4].substituteSprite) + invisible = TRUE; + sprite->pos1.x = r7->pos1.x; + sprite->pos2.x = r7->pos2.x; + sprite->invisible = invisible; +} + +void sub_8032978(struct Sprite *sprite) +{ + sprite->invisible = TRUE; +} + +void sub_8032984(u8 a, u16 b) +{ + if (GetBankSide(a) != 0) + { + if (ewram17800[a].transformedSpecies != 0) + b = ewram17800[a].transformedSpecies; + if (gEnemyMonElevation[b] != 0) + gSprites[ewram17810[a].unk7].callback = sub_80328A4; + else + gSprites[ewram17810[a].unk7].callback = sub_8032978; + } +} + +void sub_8032A08(u8 a) +{ + gSprites[ewram17810[a].unk7].callback = sub_8032978; +} + +void sub_8032A38(void) +{ + u16 *ptr = (u16 *)(VRAM + 0x240); + s32 i; + s32 j; + + for (i = 0; i < 9; i++) + { + for (j = 0; j < 16; j++) + { + if (!(*ptr & 0xF000)) + *ptr |= 0xF000; + if (!(*ptr & 0x0F00)) + *ptr |= 0x0F00; + if (!(*ptr & 0x00F0)) + *ptr |= 0x00F0; + if (!(*ptr & 0x000F)) + *ptr |= 0x000F; + ptr++; + } + } +} + +void sub_8032AA8(u8 a, u8 b) +{ + ewram17800[a].transformedSpecies = 0; + gBattleMonForms[a] = 0; + if (b == 0) + sub_80324E0(a); +} diff --git a/src/battle/battle_ai.c b/src/battle/battle_ai.c new file mode 100644 index 000000000..1869bbe36 --- /dev/null +++ b/src/battle/battle_ai.c @@ -0,0 +1,2150 @@ +#include "global.h" +#include "battle_ai.h" +#include "abilities.h" +#include "battle.h" +#include "battle_move_effects.h" +#include "data2.h" +#include "item.h" +#include "moves.h" +#include "pokemon.h" +#include "rng.h" +#include "rom_8077ABC.h" +#include "species.h" +#include "util.h" + +extern u16 gBattleTypeFlags; +extern u16 gBattleWeather; +extern u8 gActiveBank; +extern u16 gBattlePartyID[MAX_BANKS_BATTLE]; +extern u16 gCurrentMove; +extern int gBattleMoveDamage; +extern u8 gBankAttacker; +extern u8 gBankTarget; +extern u8 gAbsentBankFlags; +extern u8 gBattleMoveFlags; +extern u16 gDynamicBasePower; +extern u16 gLastUsedMove[MAX_BANKS_BATTLE]; +extern u32 gStatuses3[MAX_BANKS_BATTLE]; +extern u16 gSideAffecting[2]; +extern struct BattlePokemon gBattleMons[MAX_BANKS_BATTLE]; +extern u8 gCritMultiplier; +extern u16 gTrainerBattleOpponent; +extern u8 *BattleAIs[]; + +enum +{ + WEATHER_TYPE_SUN, + WEATHER_TYPE_RAIN, + WEATHER_TYPE_SANDSTORM, + WEATHER_TYPE_HAIL, +}; + +/* +gAIScriptPtr is a pointer to the next battle AI cmd command to read. +when a command finishes processing, gAIScriptPtr is incremented by +the number of bytes that the current command had reserved for arguments +in order to read the next command correctly. refer to battle_ai_scripts.s for the +AI scripts. +*/ +EWRAM_DATA u8 *gAIScriptPtr = NULL; + +static void BattleAICmd_if_random_less_than(void); +static void BattleAICmd_if_random_greater_than(void); +static void BattleAICmd_if_random_equal(void); +static void BattleAICmd_if_random_not_equal(void); +static void BattleAICmd_score(void); +static void BattleAICmd_if_hp_less_than(void); +static void BattleAICmd_if_hp_more_than(void); +static void BattleAICmd_if_hp_equal(void); +static void BattleAICmd_if_hp_not_equal(void); +static void BattleAICmd_if_status(void); +static void BattleAICmd_if_not_status(void); +static void BattleAICmd_if_status2(void); +static void BattleAICmd_if_not_status2(void); +static void BattleAICmd_if_status3(void); +static void BattleAICmd_if_not_status3(void); +static void BattleAICmd_if_status4(void); +static void BattleAICmd_if_not_status4(void); +static void BattleAICmd_if_less_than(void); +static void BattleAICmd_if_more_than(void); +static void BattleAICmd_if_equal(void); +static void BattleAICmd_if_not_equal(void); +static void BattleAICmd_if_less_than_32(void); +static void BattleAICmd_if_more_than_32(void); +static void BattleAICmd_if_equal_32(void); +static void BattleAICmd_if_not_equal_32(void); +static void BattleAICmd_if_move(void); +static void BattleAICmd_if_not_move(void); +static void BattleAICmd_if_in_bytes(void); +static void BattleAICmd_if_not_in_bytes(void); +static void BattleAICmd_if_in_words(void); +static void BattleAICmd_if_not_in_words(void); +static void BattleAICmd_if_user_can_damage(void); +static void BattleAICmd_if_user_cant_damage(void); +static void BattleAICmd_get_turn_count(void); +static void BattleAICmd_get_type(void); +static void BattleAICmd_get_move_power(void); +static void BattleAICmd_is_most_powerful_move(void); +static void BattleAICmd_get_move(void); +static void BattleAICmd_if_arg_equal(void); +static void BattleAICmd_if_arg_not_equal(void); +static void BattleAICmd_if_would_go_first(void); +static void BattleAICmd_if_would_not_go_first(void); +static void BattleAICmd_nullsub_2A(void); +static void BattleAICmd_nullsub_2B(void); +static void BattleAICmd_count_alive_pokemon(void); +static void BattleAICmd_get_considered_move(void); +static void BattleAICmd_get_considered_move_effect(void); +static void BattleAICmd_get_ability(void); +static void BattleAICmd_get_highest_possible_damage(void); +static void BattleAICmd_if_damage_bonus(void); +static void BattleAICmd_nullsub_32(void); +static void BattleAICmd_nullsub_33(void); +static void BattleAICmd_if_status_in_party(void); +static void BattleAICmd_if_status_not_in_party(void); +static void BattleAICmd_get_weather(void); +static void BattleAICmd_if_effect(void); +static void BattleAICmd_if_not_effect(void); +static void BattleAICmd_if_stat_level_less_than(void); +static void BattleAICmd_if_stat_level_more_than(void); +static void BattleAICmd_if_stat_level_equal(void); +static void BattleAICmd_if_stat_level_not_equal(void); +static void BattleAICmd_if_can_faint(void); +static void BattleAICmd_if_cant_faint(void); +static void BattleAICmd_if_has_move(void); +static void BattleAICmd_if_dont_have_move(void); +static void BattleAICmd_if_move_effect(void); +static void BattleAICmd_if_not_move_effect(void); +static void BattleAICmd_if_last_move_did_damage(void); +static void BattleAICmd_if_encored(void); +static void BattleAICmd_flee(void); +static void BattleAICmd_if_random_100(void); +static void BattleAICmd_watch(void); +static void BattleAICmd_get_hold_effect(void); +static void BattleAICmd_get_gender(void); +static void BattleAICmd_is_first_turn(void); +static void BattleAICmd_get_stockpile_count(void); +static void BattleAICmd_is_double_battle(void); +static void BattleAICmd_get_used_item(void); +static void BattleAICmd_get_move_type_from_result(void); +static void BattleAICmd_get_move_power_from_result(void); +static void BattleAICmd_get_move_effect_from_result(void); +static void BattleAICmd_get_protect_count(void); +static void BattleAICmd_nullsub_52(void); +static void BattleAICmd_nullsub_53(void); +static void BattleAICmd_nullsub_54(void); +static void BattleAICmd_nullsub_55(void); +static void BattleAICmd_nullsub_56(void); +static void BattleAICmd_nullsub_57(void); +static void BattleAICmd_call(void); +static void BattleAICmd_jump(void); +static void BattleAICmd_end(void); +static void BattleAICmd_if_level_compare(void); +static void BattleAICmd_if_taunted(void); +static void BattleAICmd_if_not_taunted(void); + +typedef void (*BattleAICmdFunc)(void); + +static const BattleAICmdFunc sBattleAICmdTable[] = +{ + BattleAICmd_if_random_less_than, // 0x0 + BattleAICmd_if_random_greater_than, // 0x1 + BattleAICmd_if_random_equal, // 0x2 + BattleAICmd_if_random_not_equal, // 0x3 + BattleAICmd_score, // 0x4 + BattleAICmd_if_hp_less_than, // 0x5 + BattleAICmd_if_hp_more_than, // 0x6 + BattleAICmd_if_hp_equal, // 0x7 + BattleAICmd_if_hp_not_equal, // 0x8 + BattleAICmd_if_status, // 0x9 + BattleAICmd_if_not_status, // 0xA + BattleAICmd_if_status2, // 0xB + BattleAICmd_if_not_status2, // 0xC + BattleAICmd_if_status3, // 0xD + BattleAICmd_if_not_status3, // 0xE + BattleAICmd_if_status4, // 0xF + BattleAICmd_if_not_status4, // 0x10 + BattleAICmd_if_less_than, // 0x11 + BattleAICmd_if_more_than, // 0x12 + BattleAICmd_if_equal, // 0x13 + BattleAICmd_if_not_equal, // 0x14 + BattleAICmd_if_less_than_32, // 0x15 + BattleAICmd_if_more_than_32, // 0x16 + BattleAICmd_if_equal_32, // 0x17 + BattleAICmd_if_not_equal_32, // 0x18 + BattleAICmd_if_move, // 0x19 + BattleAICmd_if_not_move, // 0x1A + BattleAICmd_if_in_bytes, // 0x1B + BattleAICmd_if_not_in_bytes, // 0x1C + BattleAICmd_if_in_words, // 0x1D + BattleAICmd_if_not_in_words, // 0x1E + BattleAICmd_if_user_can_damage, // 0x1F + BattleAICmd_if_user_cant_damage, // 0x20 + BattleAICmd_get_turn_count, // 0x21 + BattleAICmd_get_type, // 0x22 + BattleAICmd_get_move_power, // 0x23 + BattleAICmd_is_most_powerful_move, // 0x24 + BattleAICmd_get_move, // 0x25 + BattleAICmd_if_arg_equal, // 0x26 + BattleAICmd_if_arg_not_equal, // 0x27 + BattleAICmd_if_would_go_first, // 0x28 + BattleAICmd_if_would_not_go_first, // 0x29 + BattleAICmd_nullsub_2A, // 0x2A + BattleAICmd_nullsub_2B, // 0x2B + BattleAICmd_count_alive_pokemon, // 0x2C + BattleAICmd_get_considered_move, // 0x2D + BattleAICmd_get_considered_move_effect, // 0x2E + BattleAICmd_get_ability, // 0x2F + BattleAICmd_get_highest_possible_damage, // 0x30 + BattleAICmd_if_damage_bonus, // 0x31 + BattleAICmd_nullsub_32, // 0x32 + BattleAICmd_nullsub_33, // 0x33 + BattleAICmd_if_status_in_party, // 0x34 + BattleAICmd_if_status_not_in_party, // 0x35 + BattleAICmd_get_weather, // 0x36 + BattleAICmd_if_effect, // 0x37 + BattleAICmd_if_not_effect, // 0x38 + BattleAICmd_if_stat_level_less_than, // 0x39 + BattleAICmd_if_stat_level_more_than, // 0x3A + BattleAICmd_if_stat_level_equal, // 0x3B + BattleAICmd_if_stat_level_not_equal, // 0x3C + BattleAICmd_if_can_faint, // 0x3D + BattleAICmd_if_cant_faint, // 0x3E + BattleAICmd_if_has_move, // 0x3F + BattleAICmd_if_dont_have_move, // 0x40 + BattleAICmd_if_move_effect, // 0x41 + BattleAICmd_if_not_move_effect, // 0x42 + BattleAICmd_if_last_move_did_damage, // 0x43 + BattleAICmd_if_encored, // 0x44 + BattleAICmd_flee, // 0x45 + BattleAICmd_if_random_100, // 0x46 + BattleAICmd_watch, // 0x47 + BattleAICmd_get_hold_effect, // 0x48 + BattleAICmd_get_gender, // 0x49 + BattleAICmd_is_first_turn, // 0x4A + BattleAICmd_get_stockpile_count, // 0x4B + BattleAICmd_is_double_battle, // 0x4C + BattleAICmd_get_used_item, // 0x4D + BattleAICmd_get_move_type_from_result, // 0x4E + BattleAICmd_get_move_power_from_result, // 0x4F + BattleAICmd_get_move_effect_from_result, // 0x50 + BattleAICmd_get_protect_count, // 0x51 + BattleAICmd_nullsub_52, // 0x52 + BattleAICmd_nullsub_53, // 0x53 + BattleAICmd_nullsub_54, // 0x54 + BattleAICmd_nullsub_55, // 0x55 + BattleAICmd_nullsub_56, // 0x56 + BattleAICmd_nullsub_57, // 0x57 + BattleAICmd_call, // 0x58 + BattleAICmd_jump, // 0x59 + BattleAICmd_end, // 0x5A + BattleAICmd_if_level_compare, // 0x5B + BattleAICmd_if_taunted, // 0x5C + BattleAICmd_if_not_taunted, // 0x5D +}; + +#ifdef NONMATCHING +static +#endif +const u16 sDiscouragedPowerfulMoveEffects[] = +{ + EFFECT_EXPLOSION, + EFFECT_DREAM_EATER, + EFFECT_RAZOR_WIND, + EFFECT_SKY_ATTACK, + EFFECT_RECHARGE, + EFFECT_SKULL_BASH, + EFFECT_SOLARBEAM, + EFFECT_SPIT_UP, + EFFECT_FOCUS_PUNCH, + EFFECT_SUPERPOWER, + EFFECT_ERUPTION, + EFFECT_OVERHEAT, + 0xFFFF +}; + +// if the AI is a Link battle, safari, battle tower, or ereader, it will ignore considering item uses. +void BattleAI_HandleItemUseBeforeAISetup(void) +{ + s32 i; + u8 *data = (u8 *)UNK_2016A00_STRUCT; + + for (i = 0; (u32)i < sizeof(struct UnkBattleStruct1); i++) + data[i] = 0; + + if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) + && gTrainerBattleOpponent != 0x400 + && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER))) + { + for (i = 0; i < MAX_TRAINER_ITEMS; i++) + { + if (gTrainers[gTrainerBattleOpponent].items[i] != 0) + { + UNK_2016A00_STRUCT->items[UNK_2016A00_STRUCT->numOfItems] = gTrainers[gTrainerBattleOpponent].items[i]; + UNK_2016A00_STRUCT->numOfItems++; + } + } + } + + BattleAI_SetupAIData(); +} + +void BattleAI_SetupAIData(void) +{ + s32 i; + u8 *data = (u8 *)AI_THINKING_STRUCT; + u8 r7; + + // clear AI data and set default move score to 100. strange that they didn't use memset here. + for (i = 0; (u32)i < sizeof(struct AI_ThinkingStruct); i++) + data[i] = 0; + for (i = 0; i < MAX_MON_MOVES; i++) + AI_THINKING_STRUCT->score[i] = 100; + + r7 = CheckMoveLimitations(gActiveBank, 0, 0xFF); + + // probably sets up the moves to consider and ignores non-valid moves such as NO_MOVE or glitch moves. + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gBitTable[i] & r7) + AI_THINKING_STRUCT->score[i] = 0; + + AI_THINKING_STRUCT->simulatedRNG[i] = 100 - (Random() % 16); + } + + // clear AI stack. + AI_STACK->size = 0; + gBankAttacker = gActiveBank; + + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + gBankTarget = Random() & 2; // just pick somebody to target. + + if (gAbsentBankFlags & gBitTable[gBankTarget]) + gBankTarget ^= 2; + } + else + gBankTarget = gActiveBank ^ 1; + + // special AI flag cases. + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + AI_THINKING_STRUCT->aiFlags = 0x40000000; + else if (gBattleTypeFlags & BATTLE_TYPE_ROAMER) + AI_THINKING_STRUCT->aiFlags = 0x20000000; + else if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) + AI_THINKING_STRUCT->aiFlags = 0x80000000; +#ifdef GERMAN + else if (gBattleTypeFlags & 0x900 || gTrainerBattleOpponent == 0x400) + AI_THINKING_STRUCT->aiFlags = 7; +#endif + else // otherwise, just set aiFlags to whatever flags the trainer has set in their data. + AI_THINKING_STRUCT->aiFlags = gTrainers[gTrainerBattleOpponent].aiFlags; +} + +u8 BattleAI_GetAIActionToUse(void) +{ + u8 currentMoveArray[MAX_MON_MOVES]; + u8 consideredMoveArray[MAX_MON_MOVES]; + u8 numOfBestMoves; + s32 i; + + sub_810745C(); + while (AI_THINKING_STRUCT->aiFlags != 0) + { + if (AI_THINKING_STRUCT->aiFlags & 1) + { + AI_THINKING_STRUCT->aiState = AIState_SettingUp; + BattleAI_DoAIProcessing(); + } + AI_THINKING_STRUCT->aiFlags >>= 1; + AI_THINKING_STRUCT->aiLogicId++; + AI_THINKING_STRUCT->movesetIndex = 0; + } + + // special flee or watch cases for safari. + if (AI_THINKING_STRUCT->aiAction & (AI_ACTION_FLEE)) // flee + return 4; + if (AI_THINKING_STRUCT->aiAction & (AI_ACTION_WATCH)) // watch + return 5; + + numOfBestMoves = 1; + currentMoveArray[0] = AI_THINKING_STRUCT->score[0]; + consideredMoveArray[0] = 0; + + for (i = 1; i < MAX_MON_MOVES; i++) + { + if (currentMoveArray[0] < AI_THINKING_STRUCT->score[i]) + { + numOfBestMoves = 1; + currentMoveArray[0] = AI_THINKING_STRUCT->score[i]; + consideredMoveArray[0] = i; + } + if (currentMoveArray[0] == AI_THINKING_STRUCT->score[i]) + { + currentMoveArray[numOfBestMoves] = AI_THINKING_STRUCT->score[i]; + consideredMoveArray[numOfBestMoves++] = i; + } + } + + return consideredMoveArray[Random() % numOfBestMoves]; // break any ties that exist. +} + +void BattleAI_DoAIProcessing(void) +{ + while (AI_THINKING_STRUCT->aiState != AIState_FinishedProcessing) + { + switch (AI_THINKING_STRUCT->aiState) + { + case AIState_DoNotProcess: //Needed to match. + break; + case AIState_SettingUp: + gAIScriptPtr = BattleAIs[AI_THINKING_STRUCT->aiLogicId]; // set the AI ptr. + if (gBattleMons[gBankAttacker].pp[AI_THINKING_STRUCT->movesetIndex] == 0) + { + AI_THINKING_STRUCT->moveConsidered = MOVE_NONE; // don't consider a move you have 0 PP for, idiot. + } + else + { + AI_THINKING_STRUCT->moveConsidered = gBattleMons[gBankAttacker].moves[AI_THINKING_STRUCT->movesetIndex]; + } + AI_THINKING_STRUCT->aiState++; + break; + case AIState_Processing: + if (AI_THINKING_STRUCT->moveConsidered != MOVE_NONE) + sBattleAICmdTable[*(u8 *)gAIScriptPtr](); // run AI command. + else + { + AI_THINKING_STRUCT->score[AI_THINKING_STRUCT->movesetIndex] = 0; // definitely do not consider any move that has 0 PP. + AI_THINKING_STRUCT->aiAction |= AI_ACTION_DONE; + } + if (AI_THINKING_STRUCT->aiAction & AI_ACTION_DONE) + { + AI_THINKING_STRUCT->movesetIndex++; + if (AI_THINKING_STRUCT->movesetIndex < MAX_MON_MOVES && (AI_THINKING_STRUCT->aiAction & AI_ACTION_DO_NOT_ATTACK) == 0) + AI_THINKING_STRUCT->aiState = AIState_SettingUp; // as long as their are more moves to process, keep setting this to setup state. + else + AI_THINKING_STRUCT->aiState++; // done processing. + AI_THINKING_STRUCT->aiAction &= (AI_ACTION_FLEE | AI_ACTION_WATCH | AI_ACTION_DO_NOT_ATTACK | + AI_ACTION_UNK5 | AI_ACTION_UNK6 | AI_ACTION_UNK7 | AI_ACTION_UNK8); // disable AI_ACTION_DONE. + } + break; + } + } +} + +void sub_810745C(void) +{ + s32 i; + + for (i = 0; i < 8; i++) + { + if (UNK_2016A00_STRUCT->movesUsed[gBankTarget >> 1][i] == 0) + { + UNK_2016A00_STRUCT->movesUsed[gBankTarget >> 1][i] = gLastUsedMove[gBankTarget]; + return; + } + } +} + +void unref_sub_81074A0(u8 a) +{ + s32 i; + + for (i = 0; i < 8; i++) + UNK_2016A00_STRUCT->movesUsed[a / 2][i] = 0; +} + +void RecordAbilityBattle(u8 a, u8 b) +{ + if (GetBankSide(a) == 0) + UNK_2016A00_STRUCT->unk20[GetBankIdentity(a) & 1] = b; +} + +void RecordItemBattle(u8 a, u8 b) +{ + if (GetBankSide(a) == 0) + UNK_2016A00_STRUCT->unk22[GetBankIdentity(a) & 1] = b; +} + +static void BattleAICmd_if_random_less_than(void) +{ + if (Random() % 256 < gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_random_greater_than(void) +{ + if (Random() % 256 > gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_random_equal(void) +{ + if (Random() % 256 == gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_random_not_equal(void) +{ + if (Random() % 256 != gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_score(void) +{ + AI_THINKING_STRUCT->score[AI_THINKING_STRUCT->movesetIndex] += gAIScriptPtr[1]; // add the result to the array of the move consider's score. + + if (AI_THINKING_STRUCT->score[AI_THINKING_STRUCT->movesetIndex] < 0) // if the score is negative, flatten it to 0. + AI_THINKING_STRUCT->score[AI_THINKING_STRUCT->movesetIndex] = 0; + + gAIScriptPtr += 2; // AI return. +} + +static void BattleAICmd_if_hp_less_than(void) +{ + u16 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + if ((u32)(100 * gBattleMons[index].hp / gBattleMons[index].maxHP) < gAIScriptPtr[2]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + else + gAIScriptPtr += 7; +} + +static void BattleAICmd_if_hp_more_than(void) +{ + u16 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + if ((u32)(100 * gBattleMons[index].hp / gBattleMons[index].maxHP) > gAIScriptPtr[2]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + else + gAIScriptPtr += 7; +} + +static void BattleAICmd_if_hp_equal(void) +{ + u16 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + if ((u32)(100 * gBattleMons[index].hp / gBattleMons[index].maxHP) == gAIScriptPtr[2]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + else + gAIScriptPtr += 7; +} + +static void BattleAICmd_if_hp_not_equal(void) +{ + u16 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + if ((u32)(100 * gBattleMons[index].hp / gBattleMons[index].maxHP) != gAIScriptPtr[2]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + else + gAIScriptPtr += 7; +} + +static void BattleAICmd_if_status(void) +{ + u16 index; + u32 arg; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + arg = AIScriptRead32(gAIScriptPtr + 2); + + if ((gBattleMons[index].status1 & arg) != 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + else + gAIScriptPtr += 10; +} + +static void BattleAICmd_if_not_status(void) +{ + u16 index; + u32 arg; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + arg = AIScriptRead32(gAIScriptPtr + 2); + + if ((gBattleMons[index].status1 & arg) == 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + else + gAIScriptPtr += 10; +} + +static void BattleAICmd_if_status2(void) +{ + u16 index; + u32 arg; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + arg = AIScriptRead32(gAIScriptPtr + 2); + + if ((gBattleMons[index].status2 & arg) != 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + else + gAIScriptPtr += 10; +} + +static void BattleAICmd_if_not_status2(void) +{ + u16 index; + u32 arg; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + arg = AIScriptRead32(gAIScriptPtr + 2); + + if ((gBattleMons[index].status2 & arg) == 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + else + gAIScriptPtr += 10; +} + +static void BattleAICmd_if_status3(void) +{ + u16 index; + u32 arg; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + arg = AIScriptRead32(gAIScriptPtr + 2); + + if ((gStatuses3[index] & arg) != 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + else + gAIScriptPtr += 10; +} + +static void BattleAICmd_if_not_status3(void) +{ + u16 index; + u32 arg; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + arg = AIScriptRead32(gAIScriptPtr + 2); + + if ((gStatuses3[index] & arg) == 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + else + gAIScriptPtr += 10; +} + +static void BattleAICmd_if_status4(void) +{ + u16 index; + u32 arg1, arg2; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + arg1 = GetBankIdentity(index) & 1; + arg2 = AIScriptRead32(gAIScriptPtr + 2); + + if ((gSideAffecting[arg1] & arg2) != 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + else + gAIScriptPtr += 10; +} + +static void BattleAICmd_if_not_status4(void) +{ + u16 index; + u32 arg1, arg2; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + arg1 = GetBankIdentity(index) & 1; + arg2 = AIScriptRead32(gAIScriptPtr + 2); + + if ((gSideAffecting[arg1] & arg2) == 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + else + gAIScriptPtr += 10; +} + +static void BattleAICmd_if_less_than(void) +{ + if (AI_THINKING_STRUCT->funcResult < gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_more_than(void) +{ + if (AI_THINKING_STRUCT->funcResult > gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_equal(void) +{ + if (AI_THINKING_STRUCT->funcResult == gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_not_equal(void) +{ + if (AI_THINKING_STRUCT->funcResult != gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_less_than_32(void) +{ + u8 *temp = AIScriptReadPtr(gAIScriptPtr + 1); + + if (AI_THINKING_STRUCT->funcResult < *temp) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + else + gAIScriptPtr += 9; +} + +static void BattleAICmd_if_more_than_32(void) +{ + u8 *temp = AIScriptReadPtr(gAIScriptPtr + 1); + + if (AI_THINKING_STRUCT->funcResult > *temp) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + else + gAIScriptPtr += 9; +} + +static void BattleAICmd_if_equal_32(void) +{ + u8 *temp = AIScriptReadPtr(gAIScriptPtr + 1); + + if (AI_THINKING_STRUCT->funcResult == *temp) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + else + gAIScriptPtr += 9; +} + +static void BattleAICmd_if_not_equal_32(void) +{ + u8 *temp = AIScriptReadPtr(gAIScriptPtr + 1); + + if (AI_THINKING_STRUCT->funcResult != *temp) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + else + gAIScriptPtr += 9; +} + +static void BattleAICmd_if_move(void) +{ + u16 move = AIScriptRead16(gAIScriptPtr + 1); + + if (AI_THINKING_STRUCT->moveConsidered == move) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + else + gAIScriptPtr += 7; +} + +static void BattleAICmd_if_not_move(void) +{ + u16 move = AIScriptRead16(gAIScriptPtr + 1); + + if (AI_THINKING_STRUCT->moveConsidered != move) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + else + gAIScriptPtr += 7; +} + +static void BattleAICmd_if_in_bytes(void) +{ + u8 *ptr = AIScriptReadPtr(gAIScriptPtr + 1); + + while (*ptr != 0xFF) + { + if (AI_THINKING_STRUCT->funcResult == *ptr) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + return; + } + ptr++; + } + gAIScriptPtr += 9; +} + +static void BattleAICmd_if_not_in_bytes(void) +{ + u8 *ptr = AIScriptReadPtr(gAIScriptPtr + 1); + + while (*ptr != 0xFF) + { + if (AI_THINKING_STRUCT->funcResult == *ptr) + { + gAIScriptPtr += 9; + return; + } + ptr++; + } + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); +} + +static void BattleAICmd_if_in_words(void) +{ + u16 *ptr = (u16 *)AIScriptReadPtr(gAIScriptPtr + 1); + + while (*ptr != 0xFFFF) + { + if (AI_THINKING_STRUCT->funcResult == *ptr) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + return; + } + ptr++; + } + gAIScriptPtr += 9; +} + +static void BattleAICmd_if_not_in_words(void) +{ + u16 *ptr = (u16 *)AIScriptReadPtr(gAIScriptPtr + 1); + + while (*ptr != 0xFFFF) + { + if (AI_THINKING_STRUCT->funcResult == *ptr) + { + gAIScriptPtr += 9; + return; + } + ptr++; + } + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); +} + +static void BattleAICmd_if_user_can_damage(void) +{ + s32 i; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gBattleMons[gBankAttacker].moves[i] != 0 + && gBattleMoves[gBattleMons[gBankAttacker].moves[i]].power != 0) + break; + } + if (i == MAX_MON_MOVES) + gAIScriptPtr += 5; + else + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); +} + +static void BattleAICmd_if_user_cant_damage(void) +{ + s32 i; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gBattleMons[gBankAttacker].moves[i] != 0 + && gBattleMoves[gBattleMons[gBankAttacker].moves[i]].power != 0) + break; + } + if (i != MAX_MON_MOVES) + gAIScriptPtr += 5; + else + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); +} + +static void BattleAICmd_get_turn_count(void) +{ + AI_THINKING_STRUCT->funcResult = gBattleResults.battleTurnCounter; + gAIScriptPtr += 1; +} + +static void BattleAICmd_get_type(void) +{ + switch (gAIScriptPtr[1]) + { + case 1: // player primary type + AI_THINKING_STRUCT->funcResult = gBattleMons[gBankAttacker].type1; + break; + case 0: // enemy primary type + AI_THINKING_STRUCT->funcResult = gBattleMons[gBankTarget].type1; + break; + case 3: // player secondary type + AI_THINKING_STRUCT->funcResult = gBattleMons[gBankAttacker].type2; + break; + case 2: // enemy secondary type + AI_THINKING_STRUCT->funcResult = gBattleMons[gBankTarget].type2; + break; + case 4: // type of move being pointed to + AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->moveConsidered].type; + break; + } + gAIScriptPtr += 2; +} + +static void BattleAICmd_get_move_power(void) +{ + AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->moveConsidered].power; + gAIScriptPtr += 1; +} + +#ifdef NONMATCHING +static void BattleAICmd_is_most_powerful_move(void) +{ + int i, j; + s32 damages[MAX_MON_MOVES]; + + for (i = 0; sDiscouragedPowerfulMoveEffects[i] != 0xFFFF; i++) + if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect == sDiscouragedPowerfulMoveEffects[i]) + break; + + if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].power > 1 + && sDiscouragedPowerfulMoveEffects[i] == 0xFFFF) + { + gDynamicBasePower = 0; + ewram[0x1601C] = 0; // why is this a manual array? + ewram[0x1601F] = 1; + gBattleMoveFlags = 0; + gCritMultiplier = 1; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + for (j = 0; sDiscouragedPowerfulMoveEffects[j] != 0xFFFF; j++) + { // _08108276 + if (gBattleMoves[gBattleMons[gBankAttacker].moves[i]].effect == sDiscouragedPowerfulMoveEffects[j]) + break; + } + + // _081082BA + if (gBattleMons[gBankAttacker].moves[i] + && sDiscouragedPowerfulMoveEffects[j] == 0xFFFF + && gBattleMoves[gBattleMons[gBankAttacker].moves[i]].power > 1) + { + gCurrentMove = gBattleMons[gBankAttacker].moves[i]; + AI_CalcDmg(gBankAttacker, gBankTarget); + TypeCalc(gCurrentMove, gBankAttacker, gBankTarget); + damages[i] = (gBattleMoveDamage * AI_THINKING_STRUCT->simulatedRNG[i]) / 100; + + if (damages[i] == 0) // moves always do at least 1 damage. + damages[i] = 1; + } + else + { + damages[i] = 0; + } + } + + for (i = 0; i < MAX_MON_MOVES; i++) + if (damages[i] > damages[AI_THINKING_STRUCT->movesetIndex]) + break; + + if (i == MAX_MON_MOVES) + AI_THINKING_STRUCT->funcResult = 2; + else + AI_THINKING_STRUCT->funcResult = 1; + } + else + { + AI_THINKING_STRUCT->funcResult = 0; + } + + gAIScriptPtr += 1; +} +#else +__attribute__((naked)) +static void BattleAICmd_is_most_powerful_move(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x14\n\ + movs r3, 0\n\ + ldr r0, _08108328 @ =sDiscouragedPowerfulMoveEffects\n\ + ldrh r1, [r0]\n\ + ldr r4, _0810832C @ =0x0000ffff\n\ + ldr r6, _08108330 @ =gBattleMoves\n\ + ldr r5, _08108334 @ =0x02016800\n\ + cmp r1, r4\n\ + beq _0810822E\n\ + ldrh r1, [r5, 0x2]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldrb r2, [r0]\n\ + ldr r1, _08108328 @ =sDiscouragedPowerfulMoveEffects\n\ +_0810821E:\n\ + ldrh r0, [r1]\n\ + cmp r2, r0\n\ + beq _0810822E\n\ + adds r1, 0x2\n\ + adds r3, 0x1\n\ + ldrh r0, [r1]\n\ + cmp r0, r4\n\ + bne _0810821E\n\ +_0810822E:\n\ + ldrh r0, [r5, 0x2]\n\ + lsls r1, r0, 1\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r6\n\ + ldrb r0, [r1, 0x1]\n\ + cmp r0, 0x1\n\ + bhi _08108240\n\ + b _081083B2\n\ +_08108240:\n\ + lsls r0, r3, 1\n\ + ldr r1, _08108328 @ =sDiscouragedPowerfulMoveEffects\n\ + adds r0, r1\n\ + ldrh r3, [r0]\n\ + ldr r0, _0810832C @ =0x0000ffff\n\ + cmp r3, r0\n\ + beq _08108250\n\ + b _081083B2\n\ +_08108250:\n\ + ldr r0, _08108338 @ =gDynamicBasePower\n\ + movs r1, 0\n\ + strh r1, [r0]\n\ + ldr r2, _0810833C @ =0xfffff81c\n\ + adds r0, r5, r2\n\ + strb r1, [r0]\n\ + adds r2, 0x3\n\ + adds r0, r5, r2\n\ + movs r2, 0x1\n\ + strb r2, [r0]\n\ + ldr r0, _08108340 @ =gBattleMoveFlags\n\ + strb r1, [r0]\n\ + ldr r0, _08108344 @ =gCritMultiplier\n\ + strb r2, [r0]\n\ + movs r6, 0\n\ + mov r9, r3\n\ + ldr r0, _08108328 @ =sDiscouragedPowerfulMoveEffects\n\ + ldrh r0, [r0]\n\ + str r0, [sp, 0x10]\n\ +_08108276:\n\ + movs r3, 0\n\ + ldr r5, _08108348 @ =gBattleMons\n\ + lsls r4, r6, 1\n\ + ldr r7, _0810834C @ =gBankAttacker\n\ + lsls r1, r6, 2\n\ + mov r8, r1\n\ + adds r2, r6, 0x1\n\ + mov r10, r2\n\ + ldr r0, [sp, 0x10]\n\ + cmp r0, r9\n\ + beq _081082BA\n\ + ldr r2, _08108330 @ =gBattleMoves\n\ + ldrb r1, [r7]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r0, r4, r0\n\ + adds r1, r5, 0\n\ + adds r1, 0xC\n\ + adds r0, r1\n\ + ldrh r1, [r0]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldrb r2, [r0]\n\ + ldr r1, _08108328 @ =sDiscouragedPowerfulMoveEffects\n\ +_081082AA:\n\ + ldrh r0, [r1]\n\ + cmp r2, r0\n\ + beq _081082BA\n\ + adds r1, 0x2\n\ + adds r3, 0x1\n\ + ldrh r0, [r1]\n\ + cmp r0, r9\n\ + bne _081082AA\n\ +_081082BA:\n\ + ldrb r1, [r7]\n\ + movs r0, 0x58\n\ + muls r0, r1\n\ + adds r0, r4, r0\n\ + adds r1, r5, 0\n\ + adds r1, 0xC\n\ + adds r1, r0, r1\n\ + ldrh r0, [r1]\n\ + cmp r0, 0\n\ + beq _0810835C\n\ + lsls r0, r3, 1\n\ + ldr r2, _08108328 @ =sDiscouragedPowerfulMoveEffects\n\ + adds r0, r2\n\ + ldrh r0, [r0]\n\ + cmp r0, r9\n\ + bne _0810835C\n\ + ldr r0, _08108330 @ =gBattleMoves\n\ + ldrh r2, [r1]\n\ + lsls r1, r2, 1\n\ + adds r1, r2\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + cmp r0, 0x1\n\ + bls _0810835C\n\ + ldr r5, _08108350 @ =gCurrentMove\n\ + strh r2, [r5]\n\ + ldrb r0, [r7]\n\ + ldr r4, _08108354 @ =gBankTarget\n\ + ldrb r1, [r4]\n\ + bl AI_CalcDmg\n\ + ldrh r0, [r5]\n\ + ldrb r1, [r7]\n\ + ldrb r2, [r4]\n\ + bl TypeCalc\n\ + mov r4, sp\n\ + add r4, r8\n\ + ldr r2, _08108358 @ =gBattleMoveDamage\n\ + ldr r0, _08108334 @ =0x02016800\n\ + adds r0, 0x18\n\ + adds r0, r6, r0\n\ + ldrb r1, [r0]\n\ + ldr r0, [r2]\n\ + muls r0, r1\n\ + movs r1, 0x64\n\ + bl __divsi3\n\ + str r0, [r4]\n\ + cmp r0, 0\n\ + bne _08108364\n\ + movs r0, 0x1\n\ + str r0, [r4]\n\ + b _08108364\n\ + .align 2, 0\n\ +_08108328: .4byte sDiscouragedPowerfulMoveEffects\n\ +_0810832C: .4byte 0x0000ffff\n\ +_08108330: .4byte gBattleMoves\n\ +_08108334: .4byte 0x02016800\n\ +_08108338: .4byte gDynamicBasePower\n\ +_0810833C: .4byte 0xfffff81c\n\ +_08108340: .4byte gBattleMoveFlags\n\ +_08108344: .4byte gCritMultiplier\n\ +_08108348: .4byte gBattleMons\n\ +_0810834C: .4byte gBankAttacker\n\ +_08108350: .4byte gCurrentMove\n\ +_08108354: .4byte gBankTarget\n\ +_08108358: .4byte gBattleMoveDamage\n\ +_0810835C:\n\ + mov r1, sp\n\ + add r1, r8\n\ + movs r0, 0\n\ + str r0, [r1]\n\ +_08108364:\n\ + mov r6, r10\n\ + cmp r6, 0x3\n\ + ble _08108276\n\ + movs r6, 0\n\ + ldr r1, _081083A4 @ =0x02016800\n\ + ldrb r0, [r1, 0x1]\n\ + lsls r0, 2\n\ + add r0, sp\n\ + ldr r2, [sp]\n\ + ldr r0, [r0]\n\ + adds r5, r1, 0\n\ + ldr r4, _081083A8 @ =gAIScriptPtr\n\ + cmp r2, r0\n\ + bgt _0810839A\n\ + adds r3, r5, 0\n\ + mov r2, sp\n\ +_08108384:\n\ + adds r2, 0x4\n\ + adds r6, 0x1\n\ + cmp r6, 0x3\n\ + bgt _0810839A\n\ + ldrb r0, [r3, 0x1]\n\ + lsls r0, 2\n\ + add r0, sp\n\ + ldr r1, [r2]\n\ + ldr r0, [r0]\n\ + cmp r1, r0\n\ + ble _08108384\n\ +_0810839A:\n\ + cmp r6, 0x4\n\ + bne _081083AC\n\ + movs r0, 0x2\n\ + str r0, [r5, 0x8]\n\ + b _081083B8\n\ + .align 2, 0\n\ +_081083A4: .4byte 0x02016800\n\ +_081083A8: .4byte gAIScriptPtr\n\ +_081083AC:\n\ + movs r0, 0x1\n\ + str r0, [r5, 0x8]\n\ + b _081083B8\n\ +_081083B2:\n\ + movs r0, 0\n\ + str r0, [r5, 0x8]\n\ + ldr r4, _081083D0 @ =gAIScriptPtr\n\ +_081083B8:\n\ + ldr r0, [r4]\n\ + adds r0, 0x1\n\ + str r0, [r4]\n\ + add sp, 0x14\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_081083D0: .4byte gAIScriptPtr\n\ + .syntax divided\n"); +} +#endif // NONMATCHING + +static void BattleAICmd_get_move(void) +{ + if (gAIScriptPtr[1] == USER) + AI_THINKING_STRUCT->funcResult = gLastUsedMove[gBankAttacker]; + else + AI_THINKING_STRUCT->funcResult = gLastUsedMove[gBankTarget]; + + gAIScriptPtr += 2; +} + +static void BattleAICmd_if_arg_equal(void) +{ + if (gAIScriptPtr[1] == AI_THINKING_STRUCT->funcResult) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_arg_not_equal(void) +{ + if (gAIScriptPtr[1] != AI_THINKING_STRUCT->funcResult) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_would_go_first(void) +{ + if (GetWhoStrikesFirst(gBankAttacker, gBankTarget, 1) == gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_would_not_go_first(void) +{ + if (GetWhoStrikesFirst(gBankAttacker, gBankTarget, 1) != gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_nullsub_2A(void) +{ +} + +static void BattleAICmd_nullsub_2B(void) +{ +} + +static void BattleAICmd_count_alive_pokemon(void) +{ + struct Pokemon *party; + int i; + u8 index; + u8 var, var2; + + AI_THINKING_STRUCT->funcResult = 0; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + if (GetBankSide(index) == 0) + party = gPlayerParty; + else + party = gEnemyParty; + + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + u32 status; + var = gBattlePartyID[index]; + status = GetBankIdentity(index) ^ 2; + var2 = gBattlePartyID[GetBankByPlayerAI(status)]; + } + else + { + var = gBattlePartyID[index]; + var2 = gBattlePartyID[index]; + } + + for (i = 0; i < 6; i++) + { + if (i != var && i != var2 + && GetMonData(&party[i], MON_DATA_HP) != 0 + && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_NONE + && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG) + { + AI_THINKING_STRUCT->funcResult++; + } + } + + gAIScriptPtr += 2; +} + +static void BattleAICmd_get_considered_move(void) +{ + AI_THINKING_STRUCT->funcResult = AI_THINKING_STRUCT->moveConsidered; + gAIScriptPtr += 1; +} + +static void BattleAICmd_get_considered_move_effect(void) +{ + AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect; + gAIScriptPtr += 1; +} + +static void BattleAICmd_get_ability(void) +{ + u8 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + if (GetBankSide(index) == TARGET) + { + u16 unk = GetBankIdentity(index) & 1; + + if (UNK_2016A00_STRUCT->unk20[unk] != 0) + { + AI_THINKING_STRUCT->funcResult = UNK_2016A00_STRUCT->unk20[unk]; + gAIScriptPtr += 2; + return; + } + + // abilities that prevent fleeing. + if (gBattleMons[index].ability == ABILITY_SHADOW_TAG + || gBattleMons[index].ability == ABILITY_MAGNET_PULL + || gBattleMons[index].ability == ABILITY_ARENA_TRAP) + { + AI_THINKING_STRUCT->funcResult = gBattleMons[index].ability; + gAIScriptPtr += 2; + return; + } + + if (gBaseStats[gBattleMons[index].species].ability1 != ABILITY_NONE) + { + if (gBaseStats[gBattleMons[index].species].ability2 != ABILITY_NONE) + { + // AI has no knowledge of opponent, so it guesses which ability. + if (Random() % 2) + { + AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[index].species].ability1; + } + else + { + AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[index].species].ability2; + } + } + else + { + AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[index].species].ability1; // it's definitely ability 1. + } + } + else + { + AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[index].species].ability2; // AI cant actually reach this part since every mon has at least 1 ability. + } + } + else + { + // The AI knows its own ability. + AI_THINKING_STRUCT->funcResult = gBattleMons[index].ability; + } + gAIScriptPtr += 2; +} + +static void BattleAICmd_get_highest_possible_damage(void) +{ + s32 i; + + gDynamicBasePower = 0; + BATTLE_STRUCT->dynamicMoveType = 0; + BATTLE_STRUCT->dmgMultiplier = 1; + gBattleMoveFlags = 0; + gCritMultiplier = 1; + AI_THINKING_STRUCT->funcResult = 0; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + gBattleMoveDamage = 40; + gCurrentMove = gBattleMons[gBankAttacker].moves[i]; + + if (gCurrentMove) + { + TypeCalc(gCurrentMove, gBankAttacker, gBankTarget); + + // reduce by 1/3. + if (gBattleMoveDamage == 120) + gBattleMoveDamage = 80; + if (gBattleMoveDamage == 240) + gBattleMoveDamage = 160; + if (gBattleMoveDamage == 30) + gBattleMoveDamage = 20; + if (gBattleMoveDamage == 15) + gBattleMoveDamage = 10; + + if (gBattleMoveFlags & 8) // if it's a status move, it wont do anything. + gBattleMoveDamage = 0; + + if (AI_THINKING_STRUCT->funcResult < gBattleMoveDamage) + AI_THINKING_STRUCT->funcResult = gBattleMoveDamage; + } + } + gAIScriptPtr += 1; +} + +static void BattleAICmd_if_damage_bonus(void) +{ + u8 damageVar; + + gDynamicBasePower = 0; + BATTLE_STRUCT->dynamicMoveType = 0; + BATTLE_STRUCT->dmgMultiplier = 1; + gBattleMoveFlags = 0; + gCritMultiplier = 1; + + gBattleMoveDamage = 40; + gCurrentMove = AI_THINKING_STRUCT->moveConsidered; + + TypeCalc(gCurrentMove, gBankAttacker, gBankTarget); + + if (gBattleMoveDamage == 120) + gBattleMoveDamage = 80; + if (gBattleMoveDamage == 240) + gBattleMoveDamage = 160; + if (gBattleMoveDamage == 30) + gBattleMoveDamage = 20; + if (gBattleMoveDamage == 15) + gBattleMoveDamage = 10; + + if (gBattleMoveFlags & 8) + gBattleMoveDamage = 0; + + // store gBattleMoveDamage in a u8 variable because gAIScriptPtr[1] is a u8. + damageVar = gBattleMoveDamage; + + if (damageVar == gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_nullsub_32(void) +{ +} + +static void BattleAICmd_nullsub_33(void) +{ +} + +static void BattleAICmd_if_status_in_party(void) +{ + struct Pokemon *party; + struct Pokemon *partyPtr; + int i; + u32 statusToCompareTo; + + // for whatever reason, game freak put the party pointer into 2 variables instead of 1. it's possible at some point the switch encompassed the whole function and used each respective variable creating largely duplicate code. + switch (gAIScriptPtr[1]) + { + case 1: + party = partyPtr = gEnemyParty; + break; + default: + party = partyPtr = gPlayerParty; + break; + } + + statusToCompareTo = AIScriptRead32(gAIScriptPtr + 2); + + for (i = 0; i < 6; i++) + { + u16 species = GetMonData(&party[i], MON_DATA_SPECIES); + u16 hp = GetMonData(&party[i], MON_DATA_HP); + u32 status = GetMonData(&party[i], MON_DATA_STATUS); + + if (species != SPECIES_NONE && species != SPECIES_EGG && hp != 0 && status == statusToCompareTo) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); // WHAT. why is this being merged into the above switch + return; + } + } + + gAIScriptPtr += 10; +} + +// bugged, doesnt return properly. also unused +static void BattleAICmd_if_status_not_in_party(void) +{ + struct Pokemon *party; + struct Pokemon *partyPtr; + int i; + u32 statusToCompareTo; + + switch (gAIScriptPtr[1]) + { + case 1: + party = partyPtr = gEnemyParty; + break; + default: + party = partyPtr = gPlayerParty; + break; + } + + statusToCompareTo = AIScriptRead32(gAIScriptPtr + 2); + + for (i = 0; i < 6; i++) + { + u16 species = GetMonData(&party[i], MON_DATA_SPECIES); + u16 hp = GetMonData(&party[i], MON_DATA_HP); + u32 status = GetMonData(&party[i], MON_DATA_STATUS); + + // everytime the status is found, the AI's logic jumps further and further past its intended destination. this results in a broken AI macro and is probably why it is unused. + if (species != SPECIES_NONE && species != SPECIES_EGG && hp != 0 && status == statusToCompareTo) + gAIScriptPtr += 10; // doesnt return? + } + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); +} + +static void BattleAICmd_get_weather(void) +{ + if (gBattleWeather & WEATHER_RAIN_ANY) + AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_RAIN; + if (gBattleWeather & WEATHER_SANDSTORM_ANY) + AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SANDSTORM; + if (gBattleWeather & WEATHER_SUN_ANY) + AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SUN; + if (gBattleWeather & WEATHER_HAIL) + AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_HAIL; + + gAIScriptPtr += 1; +} + +static void BattleAICmd_if_effect(void) +{ + if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect == gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_not_effect(void) +{ + if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect != gAIScriptPtr[1]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + else + gAIScriptPtr += 6; +} + +static void BattleAICmd_if_stat_level_less_than(void) +{ + u32 party; + + if (gAIScriptPtr[1] == USER) + party = gBankAttacker; + else + party = gBankTarget; + + if (gBattleMons[party].statStages[gAIScriptPtr[2]] < gAIScriptPtr[3]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + else + gAIScriptPtr += 8; +} + +static void BattleAICmd_if_stat_level_more_than(void) +{ + u32 party; + + if (gAIScriptPtr[1] == USER) + party = gBankAttacker; + else + party = gBankTarget; + + if (gBattleMons[party].statStages[gAIScriptPtr[2]] > gAIScriptPtr[3]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + else + gAIScriptPtr += 8; +} + +static void BattleAICmd_if_stat_level_equal(void) +{ + u32 party; + + if (gAIScriptPtr[1] == USER) + party = gBankAttacker; + else + party = gBankTarget; + + if (gBattleMons[party].statStages[gAIScriptPtr[2]] == gAIScriptPtr[3]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + else + gAIScriptPtr += 8; +} + +static void BattleAICmd_if_stat_level_not_equal(void) +{ + u32 party; + + if (gAIScriptPtr[1] == USER) + party = gBankAttacker; + else + party = gBankTarget; + + if (gBattleMons[party].statStages[gAIScriptPtr[2]] != gAIScriptPtr[3]) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + else + gAIScriptPtr += 8; +} + +static void BattleAICmd_if_can_faint(void) +{ + if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].power < 2) + { + gAIScriptPtr += 5; + return; + } + + gDynamicBasePower = 0; + BATTLE_STRUCT->dynamicMoveType = 0; + BATTLE_STRUCT->dmgMultiplier = 1; + gBattleMoveFlags = 0; + gCritMultiplier = 1; + gCurrentMove = AI_THINKING_STRUCT->moveConsidered; + AI_CalcDmg(gBankAttacker, gBankTarget); + TypeCalc(gCurrentMove, gBankAttacker, gBankTarget); + + gBattleMoveDamage = gBattleMoveDamage * AI_THINKING_STRUCT->simulatedRNG[AI_THINKING_STRUCT->movesetIndex] / 100; + + // moves always do at least 1 damage. + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + + if (gBattleMons[gBankTarget].hp <= gBattleMoveDamage) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + else + gAIScriptPtr += 5; +} + +static void BattleAICmd_if_cant_faint(void) +{ + if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].power < 2) + { + gAIScriptPtr += 5; + return; + } + + gDynamicBasePower = 0; + BATTLE_STRUCT->dynamicMoveType = 0; + BATTLE_STRUCT->dmgMultiplier = 1; + gBattleMoveFlags = 0; + gCritMultiplier = 1; + gCurrentMove = AI_THINKING_STRUCT->moveConsidered; + AI_CalcDmg(gBankAttacker, gBankTarget); + TypeCalc(gCurrentMove, gBankAttacker, gBankTarget); + + gBattleMoveDamage = gBattleMoveDamage * AI_THINKING_STRUCT->simulatedRNG[AI_THINKING_STRUCT->movesetIndex] / 100; + + // this macro is missing the damage 0 = 1 assumption. + + if (gBattleMons[gBankTarget].hp > gBattleMoveDamage) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + else + gAIScriptPtr += 5; +} + +static void BattleAICmd_if_has_move(void) +{ + int i; + u16 *temp_ptr = (u16 *)(gAIScriptPtr + 2); + + switch (gAIScriptPtr[1]) + { + case 1: + case 3: + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gBattleMons[gBankAttacker].moves[i] == *temp_ptr) + break; + } + if (i == MAX_MON_MOVES) + gAIScriptPtr += 8; + else + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + break; + case 0: + case 2: + for (i = 0; i < 8; i++) + { + if (UNK_2016A00_STRUCT->movesUsed[gBankTarget >> 1][i] == *temp_ptr) + break; + } + if (i == 8) + gAIScriptPtr += 8; + else + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + break; + } +} + +static void BattleAICmd_if_dont_have_move(void) +{ + int i; + u16 *temp_ptr = (u16 *)(gAIScriptPtr + 2); + + switch (gAIScriptPtr[1]) + { + case 1: + case 3: + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gBattleMons[gBankAttacker].moves[i] == *temp_ptr) + break; + } + if (i != MAX_MON_MOVES) + gAIScriptPtr += 8; + else + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + break; + case 0: + case 2: + for (i = 0; i < 8; i++) + { + if (UNK_2016A00_STRUCT->movesUsed[gBankTarget >> 1][i] == *temp_ptr) + break; + } + if (i != 8) + gAIScriptPtr += 8; + else + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + break; + } +} + +static void BattleAICmd_if_move_effect(void) +{ + int i; + + switch (gAIScriptPtr[1]) + { + case 1: + case 3: + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gBattleMons[gBankAttacker].moves[i] != 0 && gBattleMoves[gBattleMons[gBankAttacker].moves[i]].effect == gAIScriptPtr[2]) + break; + } + if (i != MAX_MON_MOVES) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + else + gAIScriptPtr += 7; + break; + case 0: + case 2: + for (i = 0; i < 8; i++) + { + if (gBattleMons[gBankAttacker].moves[i] != 0 && gBattleMoves[UNK_2016A00_STRUCT->movesUsed[gBankTarget >> 1][i]].effect == gAIScriptPtr[2]) + break; + } + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + } +} + +static void BattleAICmd_if_not_move_effect(void) +{ + int i; + + switch (gAIScriptPtr[1]) + { + case 1: + case 3: + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gBattleMons[gBankAttacker].moves[i] != 0 && gBattleMoves[gBattleMons[gBankAttacker].moves[i]].effect == gAIScriptPtr[2]) + break; + } + if (i != MAX_MON_MOVES) + gAIScriptPtr += 7; + else + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + break; + case 0: + case 2: + for (i = 0; i < 8; i++) + { + if (UNK_2016A00_STRUCT->movesUsed[gBankTarget >> 1][i] != 0 && gBattleMoves[UNK_2016A00_STRUCT->movesUsed[gBankTarget >> 1][i]].effect == gAIScriptPtr[2]) + break; + } + gAIScriptPtr += 7; + } +} + +static void BattleAICmd_if_last_move_did_damage(void) +{ + u8 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + if (gAIScriptPtr[2] == 0) + { + if (gDisableStructs[index].disabledMove == 0) + { + gAIScriptPtr += 7; + return; + } + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + return; + } + else if (gAIScriptPtr[2] != 1) // ignore the macro if its not 0 or 1. + { + gAIScriptPtr += 7; + return; + } + else if (gDisableStructs[index].encoredMove != 0) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + return; + } + gAIScriptPtr += 7; +} + +static void BattleAICmd_if_encored(void) +{ + switch (gAIScriptPtr[1]) + { + case 0: // _08109348 + if (gDisableStructs[gActiveBank].disabledMove == AI_THINKING_STRUCT->moveConsidered) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + return; + } + gAIScriptPtr += 6; + return; + case 1: // _08109370 + if (gDisableStructs[gActiveBank].encoredMove == AI_THINKING_STRUCT->moveConsidered) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + return; + } + gAIScriptPtr += 6; + return; + default: + gAIScriptPtr += 6; + return; + } +} + +static void BattleAICmd_flee(void) +{ + AI_THINKING_STRUCT->aiAction |= (AI_ACTION_DONE | AI_ACTION_FLEE | AI_ACTION_DO_NOT_ATTACK); // what matters is AI_ACTION_FLEE being enabled. +} + +static void BattleAICmd_if_random_100(void) +{ + u8 safariFleeRate = BATTLE_STRUCT->safariFleeRate * 5; // safari flee rate, from 0-20 + + if ((u8)(Random() % 100) < safariFleeRate) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + else + gAIScriptPtr += 5; +} + +static void BattleAICmd_watch(void) +{ + AI_THINKING_STRUCT->aiAction |= (AI_ACTION_DONE | AI_ACTION_WATCH | AI_ACTION_DO_NOT_ATTACK); // what matters is AI_ACTION_WATCH being enabled. +} + +static void BattleAICmd_get_hold_effect(void) +{ + u8 index; + u16 status; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + if (GetBankSide(index) == 0) + { + status = (GetBankIdentity(index) & 1); + AI_THINKING_STRUCT->funcResult = UNK_2016A00_STRUCT->unk22[status]; + } + else + AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(gBattleMons[index].item); + + gAIScriptPtr += 2; +} + +static void BattleAICmd_get_gender(void) +{ + u8 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + AI_THINKING_STRUCT->funcResult = GetGenderFromSpeciesAndPersonality(gBattleMons[index].species, gBattleMons[index].personality); + + gAIScriptPtr += 2; +} + +static void BattleAICmd_is_first_turn(void) +{ + u8 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + AI_THINKING_STRUCT->funcResult = gDisableStructs[index].isFirstTurn; + + gAIScriptPtr += 2; +} + +static void BattleAICmd_get_stockpile_count(void) +{ + u8 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + AI_THINKING_STRUCT->funcResult = gDisableStructs[index].stockpileCounter; + + gAIScriptPtr += 2; +} + +static void BattleAICmd_is_double_battle(void) +{ + AI_THINKING_STRUCT->funcResult = gBattleTypeFlags & BATTLE_TYPE_DOUBLE; + + gAIScriptPtr += 1; +} + +static void BattleAICmd_get_used_item(void) +{ + u8 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + // this hack and a half matches. whatever. i dont care. someone else fix this mess later. PS: still cant fix this. + AI_THINKING_STRUCT->funcResult = ewram[MULTI_DIM_ARR(index, B_16, 0x160CC)]; + + gAIScriptPtr += 2; +} + +static void BattleAICmd_get_move_type_from_result(void) +{ + AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->funcResult].type; + + gAIScriptPtr += 1; +} + +static void BattleAICmd_get_move_power_from_result(void) +{ + AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->funcResult].power; + + gAIScriptPtr += 1; +} + +static void BattleAICmd_get_move_effect_from_result(void) +{ + AI_THINKING_STRUCT->funcResult = gBattleMoves[AI_THINKING_STRUCT->funcResult].effect; + + gAIScriptPtr += 1; +} + +static void BattleAICmd_get_protect_count(void) +{ + u8 index; + + if (gAIScriptPtr[1] == USER) + index = gBankAttacker; + else + index = gBankTarget; + + AI_THINKING_STRUCT->funcResult = gDisableStructs[index].protectUses; + + gAIScriptPtr += 2; +} + +static void BattleAICmd_nullsub_52(void) +{ +} + +static void BattleAICmd_nullsub_53(void) +{ +} + +static void BattleAICmd_nullsub_54(void) +{ +} + +static void BattleAICmd_nullsub_55(void) +{ +} + +static void BattleAICmd_nullsub_56(void) +{ +} + +static void BattleAICmd_nullsub_57(void) +{ +} + +static void BattleAICmd_call(void) +{ + AIStackPushVar(gAIScriptPtr + 5); + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); +} + +static void BattleAICmd_jump(void) +{ + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); +} + +static void BattleAICmd_end(void) +{ + if (AIStackPop() == FALSE) + AI_THINKING_STRUCT->aiAction |= AI_ACTION_DONE; +} + +static void BattleAICmd_if_level_compare(void) +{ + switch (gAIScriptPtr[1]) + { + case 0: // greater than + if (gBattleMons[gBankAttacker].level > gBattleMons[gBankTarget].level) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + return; + } + gAIScriptPtr += 6; + return; + case 1: // less than + if (gBattleMons[gBankAttacker].level < gBattleMons[gBankTarget].level) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + return; + } + gAIScriptPtr += 6; + return; + case 2: // equal + if (gBattleMons[gBankAttacker].level == gBattleMons[gBankTarget].level) + { + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + return; + } + gAIScriptPtr += 6; + return; + } +} + +static void BattleAICmd_if_taunted(void) +{ + if (gDisableStructs[gBankTarget].tauntTimer1 != 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + else + gAIScriptPtr += 5; +} + +static void BattleAICmd_if_not_taunted(void) +{ + if (gDisableStructs[gBankTarget].tauntTimer1 == 0) + gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + else + gAIScriptPtr += 5; +} + +void AIStackPushVar(u8 *var) +{ + AI_STACK->ptr[AI_STACK->size++] = var; +} + +// unused +void AIStackPushAIPtr(void) +{ + AI_STACK->ptr[AI_STACK->size++] = gAIScriptPtr; +} + +bool8 AIStackPop(void) +{ + if (AI_STACK->size != 0) + { + --AI_STACK->size; + gAIScriptPtr = AI_STACK->ptr[AI_STACK->size]; + return TRUE; + } + else + return FALSE; +} diff --git a/src/battle/battle_anim.c b/src/battle/battle_anim.c new file mode 100644 index 000000000..111d72813 --- /dev/null +++ b/src/battle/battle_anim.c @@ -0,0 +1,2270 @@ +#include "global.h" +#include "battle_anim.h" +#include "battle.h" +#include "battle_anim_80CA710.h" +#include "battle_interface.h" +#include "contest.h" +#include "decompress.h" +#include "m4a.h" +#include "main.h" +#include "palette.h" +#include "rom_8077ABC.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" + +// sprites start at 10000 and thus must be subtracted of 10000 to account for the true index. +#define GET_TRUE_SPRITE_INDEX(i) (i - 10000) + +extern u8 unk_2000000[]; +extern u16 gBattlePartyID[4]; +extern u8 gObjectBankIDs[]; +extern u8 gBankAttacker; +extern u8 gBankTarget; +EWRAM_DATA const u8 *gBattleAnimScriptPtr = NULL; +EWRAM_DATA const u8 *gBattleAnimScriptRetAddr = NULL; +EWRAM_DATA void (*gAnimScriptCallback)(void) = NULL; +EWRAM_DATA s8 gAnimFramesToWait = 0; +EWRAM_DATA u8 gAnimScriptActive = FALSE; +EWRAM_DATA u8 gAnimVisualTaskCount = 0; +EWRAM_DATA u8 gAnimSoundTaskCount = 0; +EWRAM_DATA u32 gDisableStructMoveAnim = 0; +EWRAM_DATA u32 gMoveDmgMoveAnim = 0; +EWRAM_DATA u16 gMovePowerMoveAnim = 0; +EWRAM_DATA u8 gHappinessMoveAnim = 0; +EWRAM_DATA u16 gWeatherMoveAnim = 0; +EWRAM_DATA u8 gMonAnimTaskIdArray[2] = {0}; +EWRAM_DATA u8 gUnknown_0202F7C4 = 0; +EWRAM_DATA u8 gUnknown_0202F7C5 = 0; +EWRAM_DATA u16 gAnimMoveIndex = 0; // set but unused. +EWRAM_DATA u8 gBattleAnimBankAttacker = 0; +EWRAM_DATA u8 gBattleAnimBankTarget = 0; +EWRAM_DATA u16 gUnknown_0202F7CA[4] = {0}; +EWRAM_DATA u8 gUnknown_0202F7D2 = 0; +extern u16 gUnknown_030041B4; +extern u16 gUnknown_03004200; +extern u16 gUnknown_03004240; +extern u16 gUnknown_03004244; +extern u16 gUnknown_03004280; +extern u16 gUnknown_03004288; +extern u16 gUnknown_030042C0; +extern u16 gUnknown_030042C4; + +u16 gSoundAnimFramesToWait; +s16 gBattleAnimArgs[8]; +u16 gAnimSpriteIndexArray[8]; + +extern struct MusicPlayerInfo gMPlay_BGM; +extern struct MusicPlayerInfo gMPlay_SE1; +extern struct MusicPlayerInfo gMPlay_SE2; + +extern const u16 gUnknown_081C7160[]; +extern const u8 *const gBattleAnims_Moves[]; +extern const struct CompressedSpriteSheet gBattleAnimPicTable[]; +extern const struct CompressedSpritePalette gBattleAnimPaletteTable[]; +extern const struct BattleAnimBackground gBattleAnimBackgroundTable[]; + +static void RunAnimScriptCommand(void); +static void ScriptCmd_loadsprite(void); +static void ScriptCmd_unloadsprite(void); +static void ScriptCmd_sprite(void); +static void ScriptCmd_createtask(void); +static void ScriptCmd_delay(void); +static void ScriptCmd_waitforvisualfinish(void); +static void ScriptCmd_hang1(void); +static void ScriptCmd_hang2(void); +static void ScriptCmd_end(void); +static void ScriptCmd_playse(void); +static void ScriptCmd_monbg(void); +static void sub_8076380(void); +static void task_pA_ma0A_obj_to_bg_pal(u8); +static void ScriptCmd_clearmonbg(void); +static void sub_807672C(u8); +static void ScriptCmd_monbg_22(void); +static void ScriptCmd_clearmonbg_23(void); +static void sub_80769A4(u8); +static void ScriptCmd_setalpha(void); +static void ScriptCmd_setbldcnt(void); +static void ScriptCmd_blendoff(void); +static void ScriptCmd_call(void); +static void ScriptCmd_return(void); +static void ScriptCmd_setvar(void); +static void ScriptCmd_ifelse(void); +static void ScriptCmd_jumpif(void); +static void ScriptCmd_jump(void); +static void ScriptCmd_fadetobg(void); +static void ScriptCmd_fadetobg_25(void); +static void task_p5_load_battle_screen_elements(u8); +static void sub_8076DB8(u16); +static void dp01t_11_3_message_for_player_only(void); +static void ScriptCmd_restorebg(void); +static void ScriptCmd_waitbgfadeout(void); +static void ScriptCmd_waitbgfadein(void); +static void ScriptCmd_changebg(void); +static void ScriptCmd_panse_19(void); +static void ScriptCmd_setpan(void); +static void ScriptCmd_panse_1B(void); +static void c3_08073CEC(u8); +static void ScriptCmd_panse_26(void); +static void ScriptCmd_panse_27(void); +static void ScriptCmd_panse_1C(void); +static void sub_80774FC(u8); +static void ScriptCmd_panse_1D(void); +static void sub_80775CC(u8); +static void ScriptCmd_createtask_1F(void); +static void ScriptCmd_waitsound(void); +static void ScriptCmd_jumpvareq(void); +static void ScriptCmd_jumpunkcond(void); +static void ScriptCmd_monbgprio_28(void); +static void ScriptCmd_monbgprio_29(void); +static void ScriptCmd_monbgprio_2A(void); +static void ScriptCmd_invisible(void); +static void ScriptCmd_visible(void); +static void ScriptCmd_doublebattle_2D(void); +static void ScriptCmd_doublebattle_2E(void); +static void ScriptCmd_stopsound(void); + +static void (*const sScriptCmdTable[])(void) = { + ScriptCmd_loadsprite, + ScriptCmd_unloadsprite, + ScriptCmd_sprite, + ScriptCmd_createtask, + ScriptCmd_delay, + ScriptCmd_waitforvisualfinish, + ScriptCmd_hang1, + ScriptCmd_hang2, + ScriptCmd_end, + ScriptCmd_playse, + ScriptCmd_monbg, + ScriptCmd_clearmonbg, + ScriptCmd_setalpha, + ScriptCmd_blendoff, + ScriptCmd_call, + ScriptCmd_return, + ScriptCmd_setvar, + ScriptCmd_ifelse, + ScriptCmd_jumpif, + ScriptCmd_jump, + ScriptCmd_fadetobg, + ScriptCmd_restorebg, + ScriptCmd_waitbgfadeout, + ScriptCmd_waitbgfadein, + ScriptCmd_changebg, + ScriptCmd_panse_19, + ScriptCmd_setpan, + ScriptCmd_panse_1B, + ScriptCmd_panse_1C, + ScriptCmd_panse_1D, + ScriptCmd_setbldcnt, + ScriptCmd_createtask_1F, + ScriptCmd_waitsound, + ScriptCmd_jumpvareq, + ScriptCmd_monbg_22, + ScriptCmd_clearmonbg_23, + ScriptCmd_jumpunkcond, + ScriptCmd_fadetobg_25, + ScriptCmd_panse_26, + ScriptCmd_panse_27, + ScriptCmd_monbgprio_28, + ScriptCmd_monbgprio_29, + ScriptCmd_monbgprio_2A, + ScriptCmd_invisible, + ScriptCmd_visible, + ScriptCmd_doublebattle_2D, + ScriptCmd_doublebattle_2E, + ScriptCmd_stopsound, +}; + +void battle_anim_clear_some_data(void) +{ + s32 i; + + gAnimFramesToWait = 0; + gAnimScriptActive = FALSE; + gAnimVisualTaskCount = 0; + gAnimSoundTaskCount = 0; + gDisableStructMoveAnim = 0; + gMoveDmgMoveAnim = 0; + gMovePowerMoveAnim = 0; + gHappinessMoveAnim = 0; + + // clear index array. + for (i = 0; i < 8; i++) + gAnimSpriteIndexArray[i] |= 0xFFFF; + + // clear anim args. + for (i = 0; i < 8; i++) + gBattleAnimArgs[i] = 0; + + gMonAnimTaskIdArray[0] = 0xFF; + gMonAnimTaskIdArray[1] = 0xFF; + gUnknown_0202F7C4 = 0; + gUnknown_0202F7C5 = 0; + gAnimMoveIndex = 0; + gBattleAnimBankAttacker = 0; + gBattleAnimBankTarget = 0; + gUnknown_0202F7D2 = 0; +} + +void ExecuteMoveAnim(u16 move) +{ + gBattleAnimBankAttacker = gBankAttacker; + gBattleAnimBankTarget = gBankTarget; + DoMoveAnim(gBattleAnims_Moves, move, 1); +} + +void DoMoveAnim(const u8 *const moveAnims[], u16 move, u8 c) +{ + s32 i; + + if (IsContest() == 0) + { + sub_8079E24(); + sub_8043EB4(0); + for (i = 0; i < 4; i++) + { + if (GetBankSide(i) != 0) + gUnknown_0202F7CA[i] = GetMonData(&gEnemyParty[gBattlePartyID[i]], MON_DATA_SPECIES); + else + gUnknown_0202F7CA[i] = GetMonData(&gPlayerParty[gBattlePartyID[i]], MON_DATA_SPECIES); + } + } + else + { + for (i = 0; i < 4; i++) + gUnknown_0202F7CA[i] = EWRAM_19348; + } + + if (c == 0) + gAnimMoveIndex = 0; + else + gAnimMoveIndex = move; + + for (i = 0; i < 8; i++) + gBattleAnimArgs[i] = 0; + + gMonAnimTaskIdArray[0] = 0xFF; + gMonAnimTaskIdArray[1] = 0xFF; + gBattleAnimScriptPtr = moveAnims[move]; + gAnimScriptActive = TRUE; + gAnimFramesToWait = 0; + gAnimScriptCallback = RunAnimScriptCommand; + + for (i = 0; i < 8; i++) + gAnimSpriteIndexArray[i] |= 0xFFFF; + + if (c != 0) + { + for (i = 0; gUnknown_081C7160[i] != 0xFFFF; i++) + { + if (move == gUnknown_081C7160[i]) + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 128); + break; + } + } + } + + gUnknown_030042C4 = 0; + gUnknown_03004240 = 0; + gUnknown_03004200 = 0; + gUnknown_03004244 = 0; +} + +void move_anim_8072740(struct Sprite *sprite) +{ + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + gAnimVisualTaskCount--; +} + +void DestroyAnimVisualTask(u8 taskId) +{ + DestroyTask(taskId); + gAnimVisualTaskCount--; +} + +void DestroyAnimSoundTask(u8 taskId) +{ + DestroyTask(taskId); + gAnimSoundTaskCount--; +} + +static void AddSpriteIndex(u16 index) +{ + s32 i; + + for (i = 0; i < 8; i++) + { + if (gAnimSpriteIndexArray[i] == 0xFFFF) + { + gAnimSpriteIndexArray[i] = index; + return; + } + } +} + +static void ClearSpriteIndex(u16 index) +{ + s32 i; + + for (i = 0; i < 8; i++) + { + if (gAnimSpriteIndexArray[i] == index) + { + gAnimSpriteIndexArray[i] |= 0xFFFF; + return; + } + } +} + +static void WaitAnimFrameCount(void) +{ + if (gAnimFramesToWait <= 0) + { + gAnimScriptCallback = RunAnimScriptCommand; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait--; + } +} + +static void RunAnimScriptCommand(void) +{ + do + { + sScriptCmdTable[SCRIPT_READ_8(gBattleAnimScriptPtr)](); + } while (gAnimFramesToWait == 0 && gAnimScriptActive != FALSE); +} + +static void ScriptCmd_loadsprite(void) +{ + u16 index; + + gBattleAnimScriptPtr++; + index = SCRIPT_READ_16(gBattleAnimScriptPtr); + LoadCompressedObjectPic(&gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)]); + LoadCompressedObjectPalette(&gBattleAnimPaletteTable[GET_TRUE_SPRITE_INDEX(index)]); + gBattleAnimScriptPtr += 2; + AddSpriteIndex(GET_TRUE_SPRITE_INDEX(index)); + gAnimFramesToWait = 1; + gAnimScriptCallback = WaitAnimFrameCount; +} + +static void ScriptCmd_unloadsprite(void) +{ + u16 index; + + gBattleAnimScriptPtr++; + index = SCRIPT_READ_16(gBattleAnimScriptPtr); + FreeSpriteTilesByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag); + FreeSpritePaletteByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag); + gBattleAnimScriptPtr += 2; + ClearSpriteIndex(GET_TRUE_SPRITE_INDEX(index)); +} + +#ifdef NONMATCHING +static void ScriptCmd_sprite(void) +{ + s32 i; + struct SpriteTemplate *r7; + u8 r4; + u8 r0; + u8 _r0; + u16 r6; + u8 r2; + s8 r1; + + gBattleAnimScriptPtr++; + r7 = (struct SpriteTemplate *)(SCRIPT_READ_32(gBattleAnimScriptPtr)); + gBattleAnimScriptPtr += 4; + r4 = SCRIPT_READ_8(gBattleAnimScriptPtr); + gBattleAnimScriptPtr++; + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr); + gBattleAnimScriptPtr++; + for (i = 0; i < r0; i++) + { + gBattleAnimArgs[i] = SCRIPT_READ_16(gBattleAnimScriptPtr); + gBattleAnimScriptPtr += 2; + } + if (r4 & 0x80) + { + r4 ^= 0x80; + if (r4 > 0x3F) + r4 -= 0x40; + else + r4 = -r4; + _r0 = sub_8079E90(gBattleAnimBankTarget); + r1 = r4; + + } + else + { + //_08075B44 + if (r4 > 0x3F) + r4 -= 0x40; + else + r4 = -r4; + _r0 = sub_8079E90(gBattleAnimBankAttacker); + r1 = r4; + } + r6 = _r0 + r1; + if ((s16)r6 < 3) + r6 = 3; + + r4 = sub_8077ABC(gBattleAnimBankTarget, 2); + r2 = sub_8077ABC(gBattleAnimBankTarget, 3); + CreateSpriteAndAnimate(r7, r4, r2, r6); + gAnimVisualTaskCount++; +} +#else +__attribute__((naked)) +static void ScriptCmd_sprite(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + ldr r5, _08075B2C @ =gBattleAnimScriptPtr\n\ + ldr r1, [r5]\n\ + adds r3, r1, 0x1\n\ + str r3, [r5]\n\ + ldrb r2, [r1, 0x1]\n\ + ldrb r0, [r3, 0x1]\n\ + lsls r0, 8\n\ + adds r2, r0\n\ + ldrb r0, [r3, 0x2]\n\ + lsls r0, 16\n\ + adds r2, r0\n\ + ldrb r0, [r3, 0x3]\n\ + lsls r0, 24\n\ + adds r7, r2, r0\n\ + adds r0, r1, 0x5\n\ + str r0, [r5]\n\ + ldrb r4, [r1, 0x5]\n\ + adds r0, r1, 0x6\n\ + str r0, [r5]\n\ + ldrb r0, [r1, 0x6]\n\ + adds r1, 0x7\n\ + str r1, [r5]\n\ + cmp r0, 0\n\ + beq _08075B14\n\ + adds r6, r5, 0\n\ + ldr r5, _08075B30 @ =gBattleAnimArgs\n\ + adds r3, r0, 0\n\ +_08075AFC:\n\ + ldr r2, [r6]\n\ + ldrb r1, [r2]\n\ + ldrb r0, [r2, 0x1]\n\ + lsls r0, 8\n\ + orrs r1, r0\n\ + strh r1, [r5]\n\ + adds r2, 0x2\n\ + str r2, [r6]\n\ + adds r5, 0x2\n\ + subs r3, 0x1\n\ + cmp r3, 0\n\ + bne _08075AFC\n\ +_08075B14:\n\ + movs r0, 0x80\n\ + ands r0, r4\n\ + cmp r0, 0\n\ + beq _08075B44\n\ + movs r0, 0x80\n\ + eors r4, r0\n\ + cmp r4, 0x3F\n\ + bls _08075B34\n\ + adds r0, r4, 0\n\ + subs r0, 0x40\n\ + b _08075B36\n\ + .align 2, 0\n\ +_08075B2C: .4byte gBattleAnimScriptPtr\n\ +_08075B30: .4byte gBattleAnimArgs\n\ +_08075B34:\n\ + negs r0, r4\n\ +_08075B36:\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + ldr r0, _08075B40 @ =gBattleAnimBankTarget\n\ + b _08075B56\n\ + .align 2, 0\n\ +_08075B40: .4byte gBattleAnimBankTarget\n\ +_08075B44:\n\ + cmp r4, 0x3F\n\ + bls _08075B4E\n\ + adds r0, r4, 0\n\ + subs r0, 0x40\n\ + b _08075B50\n\ +_08075B4E:\n\ + negs r0, r4\n\ +_08075B50:\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + ldr r0, _08075BAC @ =gBattleAnimBankAttacker\n\ +_08075B56:\n\ + ldrb r0, [r0]\n\ + bl sub_8079E90\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r1, r4, 24\n\ + asrs r1, 24\n\ + adds r0, r1\n\ + lsls r0, 16\n\ + lsrs r6, r0, 16\n\ + lsls r0, r6, 16\n\ + asrs r0, 16\n\ + cmp r0, 0x2\n\ + bgt _08075B74\n\ + movs r6, 0x3\n\ +_08075B74:\n\ + ldr r5, _08075BB0 @ =gBattleAnimBankTarget\n\ + ldrb r0, [r5]\n\ + movs r1, 0x2\n\ + bl sub_8077ABC\n\ + adds r4, r0, 0\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + ldrb r0, [r5]\n\ + movs r1, 0x3\n\ + bl sub_8077ABC\n\ + adds r2, r0, 0\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + lsls r3, r6, 24\n\ + lsrs r3, 24\n\ + adds r0, r7, 0\n\ + adds r1, r4, 0\n\ + bl CreateSpriteAndAnimate\n\ + ldr r1, _08075BB4 @ =gAnimVisualTaskCount\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08075BAC: .4byte gBattleAnimBankAttacker\n\ +_08075BB0: .4byte gBattleAnimBankTarget\n\ +_08075BB4: .4byte gAnimVisualTaskCount\n\ + .syntax divided\n"); +} +#endif + +static void ScriptCmd_createtask(void) +{ + TaskFunc taskFunc; + u8 taskPriority; + u8 taskId; + u8 numArgs; + s32 i; + + gBattleAnimScriptPtr++; + taskFunc = (TaskFunc)SCRIPT_READ_32(gBattleAnimScriptPtr); + gBattleAnimScriptPtr += 4; + taskPriority = SCRIPT_READ_8(gBattleAnimScriptPtr); + gBattleAnimScriptPtr++; + numArgs = SCRIPT_READ_8(gBattleAnimScriptPtr); + gBattleAnimScriptPtr++; + + for (i = 0; i < numArgs; i++) + { + gBattleAnimArgs[i] = SCRIPT_READ_16(gBattleAnimScriptPtr); + gBattleAnimScriptPtr += 2; + } + + taskId = CreateTask(taskFunc, taskPriority); + taskFunc(taskId); + gAnimVisualTaskCount++; +} + +static void ScriptCmd_delay(void) +{ + gBattleAnimScriptPtr++; + gAnimFramesToWait = SCRIPT_READ_8(gBattleAnimScriptPtr); + if (gAnimFramesToWait == 0) + gAnimFramesToWait = -1; + gBattleAnimScriptPtr++; + gAnimScriptCallback = WaitAnimFrameCount; +} + +// wait for visual tasks to finish. +static void ScriptCmd_waitforvisualfinish(void) +{ + if (gAnimVisualTaskCount == 0) + { + gBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } +} + +static void ScriptCmd_hang1(void) +{ +} + +static void ScriptCmd_hang2(void) +{ +} + +static void ScriptCmd_end(void) +{ + s32 i; + bool32 continuousAnim = FALSE; + + // keep waiting as long as there is animations to be done. + if (gAnimVisualTaskCount != 0 || gAnimSoundTaskCount != 0 + || gMonAnimTaskIdArray[0] != 0xFF || gMonAnimTaskIdArray[1] != 0xFF) + { + gSoundAnimFramesToWait = 0; + gAnimFramesToWait = 1; + return; + } + + // finish the sound effects. + if (IsSEPlaying()) + { + if (++gSoundAnimFramesToWait <= 90) // wait 90 frames, then halt the sound effect. + { + gAnimFramesToWait = 1; + return; + } + else + { + m4aMPlayStop(&gMPlay_SE1); + m4aMPlayStop(&gMPlay_SE2); + } + } + + // the SE has halted, so set the SE Frame Counter to 0 and continue. + gSoundAnimFramesToWait = 0; + + for (i = 0; i < 8; i++) + { + if (gAnimSpriteIndexArray[i] != 0xFFFF) + { + FreeSpriteTilesByTag(gBattleAnimPicTable[gAnimSpriteIndexArray[i]].tag); + FreeSpritePaletteByTag(gBattleAnimPicTable[gAnimSpriteIndexArray[i]].tag); + gAnimSpriteIndexArray[i] |= 0xFFFF; // set terminator. + } + } + + if (continuousAnim == FALSE) // may have been used for debug? + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 256); + if (IsContest() == 0) + { + sub_8079E24(); + sub_8043EB4(1); + } + gAnimScriptActive = FALSE; + } +} + +static void ScriptCmd_playse(void) +{ + gBattleAnimScriptPtr++; + PlaySE(SCRIPT_READ_16(gBattleAnimScriptPtr)); + gBattleAnimScriptPtr += 2; +} + +static void ScriptCmd_monbg(void) +{ + u8 r6; + u8 r5; + u8 r0; + u8 r7; + u16 r4; + u8 taskId; + + gBattleAnimScriptPtr++; + r6 = SCRIPT_READ_8(gBattleAnimScriptPtr); + if (r6 == 0) + r6 = 2; + else if (r6 == 1) + r6 = 3; + if (r6 == 0 || r6 == 2) + r5 = gBattleAnimBankAttacker; + else + r5 = gBattleAnimBankTarget; + if (IsAnimBankSpriteVisible(r5)) + { + r0 = GetBankIdentity(r5); + r0 += 0xFF; + if (r0 <= 1 || IsContest() != 0) + r7 = 0; + else + r7 = 1; + sub_8076034(r5, r7); + r4 = gObjectBankIDs[r5]; + taskId = CreateTask(task_pA_ma0A_obj_to_bg_pal, 10); + gTasks[taskId].data[0] = r4; + gTasks[taskId].data[1] = gSprites[r4].pos1.x + gSprites[r4].pos2.x; + gTasks[taskId].data[2] = gSprites[r4].pos1.y + gSprites[r4].pos2.y; + if (r7 == 0) + { + gTasks[taskId].data[3] = gUnknown_030042C0; + gTasks[taskId].data[4] = gUnknown_030041B4; + } + else + { + gTasks[taskId].data[3] = gUnknown_03004288; + gTasks[taskId].data[4] = gUnknown_03004280; + } + gTasks[taskId].data[5] = r7; + gTasks[taskId].data[6] = r5; + gMonAnimTaskIdArray[0] = taskId; + + } + r5 ^= 2; + if (r6 > 1 && IsAnimBankSpriteVisible(r5)) + { + r0 = GetBankIdentity(r5); + r0 += 0xFF; + if (r0 <= 1 || IsContest() != 0) + r7 = 0; + else + r7 = 1; + sub_8076034(r5, r7); + r4 = gObjectBankIDs[r5]; + taskId = CreateTask(task_pA_ma0A_obj_to_bg_pal, 10); + gTasks[taskId].data[0] = r4; + gTasks[taskId].data[1] = gSprites[r4].pos1.x + gSprites[r4].pos2.x; + gTasks[taskId].data[2] = gSprites[r4].pos1.y + gSprites[r4].pos2.y; + if (r7 == 0) + { + gTasks[taskId].data[3] = gUnknown_030042C0; + gTasks[taskId].data[4] = gUnknown_030041B4; + } + else + { + gTasks[taskId].data[3] = gUnknown_03004288; + gTasks[taskId].data[4] = gUnknown_03004280; + } + gTasks[taskId].data[5] = r7; + gTasks[taskId].data[6] = r5; + gMonAnimTaskIdArray[1] = taskId; + } + gBattleAnimScriptPtr++; +} + +#ifdef NONMATCHING +bool8 IsAnimBankSpriteVisible(u8 a) +{ + if (IsContest()) + { + if (a == gBattleAnimBankAttacker) + return TRUE; + else + return FALSE; + } + if (!AnimBankSpriteExists(a)) + return FALSE; + if (IsContest()) + return TRUE; // this line wont ever be reached. + if (!(EWRAM_17800[a].unk0 & 1)) + return TRUE; + if (gSprites[gObjectBankIDs[a]].invisible) + return FALSE; + return TRUE; +} +#else +__attribute__((naked)) +bool8 IsAnimBankSpriteVisible(u8 a) +{ + asm(".syntax unified\n\ + push {r4,r5,lr}\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + adds r5, r4, 0\n\ + bl IsContest\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08075FDC\n\ + ldr r0, _08075FD8 @ =gBattleAnimBankAttacker\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + beq _0807601C\n\ + b _0807602C\n\ + .align 2, 0\n\ +_08075FD8: .4byte gBattleAnimBankAttacker\n\ +_08075FDC:\n\ + adds r0, r4, 0\n\ + bl AnimBankSpriteExists\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _0807602C\n\ + bl IsContest\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _0807601C\n\ + lsls r0, r5, 2\n\ + ldr r1, _08076020 @ =0x02017800\n\ + adds r0, r1\n\ + ldrb r1, [r0]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0807601C\n\ + ldr r2, _08076024 @ =gSprites\n\ + ldr r0, _08076028 @ =gObjectBankIDs\n\ + adds r0, r5, r0\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + adds r0, 0x3E\n\ + ldrb r0, [r0]\n\ + lsls r0, 29\n\ + cmp r0, 0\n\ + blt _0807602C\n\ +_0807601C:\n\ + movs r0, 0x1\n\ + b _0807602E\n\ + .align 2, 0\n\ +_08076020: .4byte 0x02017800\n\ +_08076024: .4byte gSprites\n\ +_08076028: .4byte gObjectBankIDs\n\ +_0807602C:\n\ + movs r0, 0\n\ +_0807602E:\n\ + pop {r4,r5}\n\ + pop {r1}\n\ + bx r1\n\ + .syntax divided\n"); +} +#endif + +void sub_8076034(u8 a, u8 b) +{ + volatile u8 pointlessZero; + u16 *addr2; + u8 spriteId; + + if (b == 0) + { + struct UnknownStruct2 s; + u8 *addr; + u32 size; + u8 r2; + u16 *addr3; + + sub_8078914(&s); + addr = s.unk0; + size = 0x2000; + while (1) + { + DmaFill32(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill32(3, 0, addr, size); + break; + } + } + pointlessZero = 0; + pointlessZero = 0; + addr2 = (void *)s.unk4; + DmaFill16(3, 0xFF, addr2, 0x1000); + + REG_BG1CNT_BITFIELD.priority = 2; + REG_BG1CNT_BITFIELD.screenSize = 1; + REG_BG1CNT_BITFIELD.areaOverflowMode = 0; + + spriteId = gObjectBankIDs[a]; + gUnknown_030042C0 = -(gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x) + 32; + if (IsContest() != 0 && sub_80AEB1C(EWRAM_19348) != 0) + gUnknown_030042C0--; + gUnknown_030041B4 = -(gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y) + 32; + gSprites[gObjectBankIDs[a]].invisible = TRUE; + + REG_BG1HOFS = gUnknown_030042C0; + REG_BG1VOFS = gUnknown_030041B4; + + LoadPalette(gPlttBufferUnfaded + 0x100 + a * 16, s.unk8 * 16, 32); + addr3 = (u16 *)PLTT + s.unk8 * 16; + DmaCopy32(3, gPlttBufferUnfaded + 0x100 + a * 16, addr3, 32); + + if (IsContest() != 0) + r2 = 0; + else + r2 = GetBankIdentity(a); + sub_80E4EF8(0, 0, r2, s.unk8, (u32)s.unk0, (((s32)s.unk4 - VRAM) / 2048), REG_BG1CNT_BITFIELD.charBaseBlock); + if (IsContest() != 0) + sub_8076380(); + } + else + { + u8 *addr; + u32 size; + u16 *addr3; + + addr = (void *)(VRAM + 0x6000); + size = 0x2000; + while (1) + { + DmaFill32(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill32(3, 0, addr, size); + break; + } + } + pointlessZero = 0; + pointlessZero = 0; + addr2 = (void *)(VRAM + 0xF000); + DmaFill32(3, 0, addr2, 0x800); + + REG_BG2CNT_BITFIELD.priority = 2; + REG_BG2CNT_BITFIELD.screenSize = 1; + REG_BG2CNT_BITFIELD.areaOverflowMode = 0; + + spriteId = gObjectBankIDs[a]; + gUnknown_03004288 = -(gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x) + 32; + gUnknown_03004280 = -(gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y) + 32; + gSprites[gObjectBankIDs[a]].invisible = TRUE; + + REG_BG2HOFS = gUnknown_03004288; + REG_BG2VOFS = gUnknown_03004280; + + LoadPalette(gPlttBufferUnfaded + 0x100 + a * 16, 0x90, 32); + addr3 = (void *)(PLTT + 0x120); + DmaCopy32(3, gPlttBufferUnfaded + 0x100 + a * 16, addr3, 32); + + sub_80E4EF8(0, 0, GetBankIdentity(a), 9, 0x6000, 0x1E, REG_BG2CNT_BITFIELD.charBaseBlock); + } +} + +static void sub_8076380(void) +{ + int i; + int j; + struct UnknownStruct2 s; + u16 *ptr; + + if (sub_80AEB1C(EWRAM_19348) != 0) + { + sub_8078914(&s); + ptr = s.unk4; + for (i = 0; i < 8; i++) + { + for (j = 0; j < 4; j++) + { + u16 temp = ptr[j + i * 32]; + + ptr[j + i * 32] = ptr[7 - j + i * 32]; + ptr[7 - j + i * 32] = temp; + } + } + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + ptr[j + i * 32] ^= 0x400; + } + } +} + +void sub_80763FC(u16 a, u16 *b, u32 c, u8 d) +{ + u8 i; + u8 j; + u32 r9; + + if (d == 0) + r9 = 32; + else + r9 = 64; + a <<= 12; + for (i = 0; i < r9; i++) + { + for (j = 0; j < 32; j++) + b[j + i * 32] = ((b[j + i * 32] & 0xFFF) | a) + c; + } +} + +void sub_8076464(u8 a) +{ + u8 *addr; + u32 size; + volatile u8 pointlessZero; + struct UnknownStruct2 s; + + sub_8078914(&s); + if (a == 0 || IsContest() != 0) + { + u16 *addr2; + + addr = s.unk0; + size = 0x2000; + while (1) + { + DmaFill32(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill32(3, 0, addr, size); + break; + } + } + pointlessZero = 0; + pointlessZero = 0; + addr2 = s.unk4; + DmaFill32(3, 0, addr2, 0x800); + gUnknown_030042C0 = 0; + gUnknown_030041B4 = 0; + } + else + { + u16 *addr2; + + addr = (void *)(VRAM + 0x6000); + size = 0x2000; + while (1) + { + DmaFill32(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill32(3, 0, addr, size); + break; + } + } + pointlessZero = 0; + pointlessZero = 0; + addr2 = (void *)(VRAM + 0xF000); + DmaFill32(3, 0, addr2, 0x800); + gUnknown_03004288 = 0; + gUnknown_03004280 = 0; + } +} + +static void task_pA_ma0A_obj_to_bg_pal(u8 taskId) +{ + u8 r4; + u8 r6; + s16 r3; + s16 r2; + struct UnknownStruct2 s; + + r4 = gTasks[taskId].data[0]; + r6 = gTasks[taskId].data[6]; + sub_8078914(&s); + r3 = gTasks[taskId].data[1] - (gSprites[r4].pos1.x + gSprites[r4].pos2.x); + r2 = gTasks[taskId].data[2] - (gSprites[r4].pos1.y + gSprites[r4].pos2.y); + if (gTasks[taskId].data[5] == 0) + { + u16 *src; + u16 *dst; + + gUnknown_030042C0 = r3 + gTasks[taskId].data[3]; + gUnknown_030041B4 = r2 + gTasks[taskId].data[4]; + src = gPlttBufferFaded + 0x100 + r6 * 16; + dst = gPlttBufferFaded + 0x100 + s.unk8 * 16 - 256; + DmaCopy32(3, src, dst, 32); + } + else + { + u16 *src; + u16 *dst; + + gUnknown_03004288 = r3 + gTasks[taskId].data[3]; + gUnknown_03004280 = r2 + gTasks[taskId].data[4]; + src = gPlttBufferFaded + 0x100 + r6 * 16; + dst = gPlttBufferFaded + 0x100 - 112; + DmaCopy32(3, src, dst, 32); + } +} + +static void ScriptCmd_clearmonbg(void) +{ + u8 r4; + u8 r5; + u8 taskId; + + gBattleAnimScriptPtr++; + r4 = SCRIPT_READ_8(gBattleAnimScriptPtr); + if (r4 == 0) + r4 = 2; + else if (r4 == 1) + r4 = 3; + if (r4 == 0 || r4 == 2) + r5 = gBattleAnimBankAttacker; + else + r5 = gBattleAnimBankTarget; + if (gMonAnimTaskIdArray[0] != 0xFF) + gSprites[gObjectBankIDs[r5]].invisible = FALSE; + if (r4 > 1 && gMonAnimTaskIdArray[1] != 0xFF) + gSprites[gObjectBankIDs[r5 ^ 2]].invisible = FALSE; + else + r4 = 0; + taskId = CreateTask(sub_807672C, 5); + gTasks[taskId].data[0] = r4; + gTasks[taskId].data[2] = r5; + gBattleAnimScriptPtr++; +} + +static void sub_807672C(u8 taskId) +{ + u8 var; + u8 r4; + + gTasks[taskId].data[1]++; + if (gTasks[taskId].data[1] != 1) + { + var = GetBankIdentity(gTasks[taskId].data[2]); + var += 0xFF; + if (var <= 1 || IsContest() != 0) + r4 = 0; + else + r4 = 1; + if (gMonAnimTaskIdArray[0] != 0xFF) + { + sub_8076464(r4); + DestroyTask(gMonAnimTaskIdArray[0]); + gMonAnimTaskIdArray[0] = 0xFF; + } + if (gTasks[taskId].data[0] > 1) + { + sub_8076464(r4 ^ 1); + DestroyTask(gMonAnimTaskIdArray[1]); + gMonAnimTaskIdArray[1] = 0xFF; + } + DestroyTask(taskId); + } +} + +static void ScriptCmd_monbg_22(void) +{ + u8 r5; + u8 r4; + u8 r0; + u8 r1; + + gBattleAnimScriptPtr++; + r5 = SCRIPT_READ_8(gBattleAnimScriptPtr); + if (r5 == 0) + r5 = 2; + else if (r5 == 1) + r5 = 3; + if (r5 == 0 || r5 == 2) + r4 = gBattleAnimBankAttacker; + else + r4 = gBattleAnimBankTarget; + if (IsAnimBankSpriteVisible(r4)) + { + r0 = GetBankIdentity(r4); + r0 += 0xFF; + if (r0 <= 1 || IsContest() != 0) + r1 = 0; + else + r1 = 1; + sub_8076034(r4, r1); + gSprites[gObjectBankIDs[r4]].invisible = FALSE; + } + r4 ^= 2; + if (r5 > 1 && IsAnimBankSpriteVisible(r4)) + { + r0 = GetBankIdentity(r4); + r0 += 0xFF; + if (r0 <= 1 || IsContest() != 0) + r1 = 0; + else + r1 = 1; + sub_8076034(r4, r1); + gSprites[gObjectBankIDs[r4]].invisible = FALSE; + } + gBattleAnimScriptPtr++; +} + +static void ScriptCmd_clearmonbg_23(void) +{ + u8 r5; + u8 r6; + u8 taskId; + + gBattleAnimScriptPtr++; + r5 = SCRIPT_READ_8(gBattleAnimScriptPtr); + if (r5 == 0) + r5 = 2; + else if (r5 == 1) + r5 = 3; + if (r5 == 0 || r5 == 2) + r6 = gBattleAnimBankAttacker; + else + r6 = gBattleAnimBankTarget; + if (IsAnimBankSpriteVisible(r6)) + gSprites[gObjectBankIDs[r6]].invisible = FALSE; + if (r5 > 1 && IsAnimBankSpriteVisible(r6 ^ 2)) + gSprites[gObjectBankIDs[r6 ^ 2]].invisible = FALSE; + else + r5 = 0; + taskId = CreateTask(sub_80769A4, 5); + gTasks[taskId].data[0] = r5; + gTasks[taskId].data[2] = r6; + gBattleAnimScriptPtr++; +} + +static void sub_80769A4(u8 taskId) +{ + u8 r0; + u8 r4; + u8 r5; + + gTasks[taskId].data[1]++; + if (gTasks[taskId].data[1] != 1) + { + r4 = gTasks[taskId].data[2]; + r0 = GetBankIdentity(r4); + r0 += 0xFF; + if (r0 <= 1 || IsContest() != 0) + r5 = 0; + else + r5 = 1; + if (IsAnimBankSpriteVisible(r4)) + sub_8076464(r5); + if (gTasks[taskId].data[0] > 1 && IsAnimBankSpriteVisible(r4 ^ 2)) + sub_8076464(r5 ^ 1); + DestroyTask(taskId); + } +} + +static void ScriptCmd_setalpha(void) +{ + u16 r3; + u16 r1; + + gBattleAnimScriptPtr++; + r3 = *(gBattleAnimScriptPtr++); + r1 = *(gBattleAnimScriptPtr++) << 8; + REG_BLDCNT = 0x3F40; + REG_BLDALPHA = r3 | r1; +} + +static void ScriptCmd_setbldcnt(void) +{ + u16 r3; + u16 r1; + + gBattleAnimScriptPtr++; + r3 = *(gBattleAnimScriptPtr++); + r1 = *(gBattleAnimScriptPtr++) << 8; + REG_BLDCNT = r3 | r1; +} + +static void ScriptCmd_blendoff(void) +{ + gBattleAnimScriptPtr++; + REG_BLDCNT = 0; + REG_BLDALPHA = 0; +} + +static void ScriptCmd_call(void) +{ + u32 addr; + + gBattleAnimScriptPtr++; + gBattleAnimScriptRetAddr = gBattleAnimScriptPtr + 4; + addr = SCRIPT_READ_32(gBattleAnimScriptPtr); + gBattleAnimScriptPtr = (u8 *)addr; +} + +static void ScriptCmd_return(void) +{ + gBattleAnimScriptPtr = gBattleAnimScriptRetAddr; +} + +static void ScriptCmd_setvar(void) +{ + const u8 *addr = gBattleAnimScriptPtr; + u16 r4; + u8 r2; + + gBattleAnimScriptPtr++; + r2 = SCRIPT_READ_8(gBattleAnimScriptPtr); + gBattleAnimScriptPtr++; + r4 = SCRIPT_READ_16(gBattleAnimScriptPtr); + gBattleAnimScriptPtr = addr + 4; + gBattleAnimArgs[r2] = r4; +} + +static void ScriptCmd_ifelse(void) +{ + u32 addr; + + gBattleAnimScriptPtr++; + if (gUnknown_0202F7C4 & 1) + gBattleAnimScriptPtr += 4; + addr = SCRIPT_READ_32(gBattleAnimScriptPtr); + gBattleAnimScriptPtr = (u8 *)addr; +} + +static void ScriptCmd_jumpif(void) +{ + u8 r1; + u32 addr; + + gBattleAnimScriptPtr++; + r1 = SCRIPT_READ_8(gBattleAnimScriptPtr); + gBattleAnimScriptPtr++; + if (r1 == gUnknown_0202F7C4) + { + addr = SCRIPT_READ_32(gBattleAnimScriptPtr); + gBattleAnimScriptPtr = (u8 *)addr; + } + else + { + gBattleAnimScriptPtr += 4; + } +} + +static void ScriptCmd_jump(void) +{ + u32 addr; + + gBattleAnimScriptPtr++; + addr = SCRIPT_READ_32(gBattleAnimScriptPtr); + gBattleAnimScriptPtr = (u8 *)addr; +} + +// Uses of this function that rely on a TRUE return are expecting inBattle to not be ticked as defined in contest behavior. As a result, if misused, this function cannot reliably discern between field and contest status and could result in undefined behavior. +bool8 IsContest(void) +{ + if (!gMain.inBattle) + return TRUE; + else + return FALSE; +} + +static void ScriptCmd_fadetobg(void) +{ + u8 r4; + u8 taskId; + + gBattleAnimScriptPtr++; + r4 = SCRIPT_READ_8(gBattleAnimScriptPtr); + gBattleAnimScriptPtr++; + taskId = CreateTask(task_p5_load_battle_screen_elements, 5); + gTasks[taskId].data[0] = r4; + gUnknown_0202F7C5 = 1; +} + +static void ScriptCmd_fadetobg_25(void) +{ + u8 r8; + u8 r7; + u8 r6; + u8 taskId; + + gBattleAnimScriptPtr++; + r8 = gBattleAnimScriptPtr[0]; + r7 = gBattleAnimScriptPtr[1]; + r6 = gBattleAnimScriptPtr[2]; + gBattleAnimScriptPtr += 3; + taskId = CreateTask(task_p5_load_battle_screen_elements, 5); + if (IsContest() != 0) + gTasks[taskId].data[0] = r6; + else if (GetBankSide(gBattleAnimBankTarget) == 0) + gTasks[taskId].data[0] = r7; + else + gTasks[taskId].data[0] = r8; + gUnknown_0202F7C5 = 1; +} + +static void task_p5_load_battle_screen_elements(u8 taskId) +{ + if (gTasks[taskId].data[10] == 0) + { + BeginHardwarePaletteFade(0xE8, 0, 0, 16, 0); + gTasks[taskId].data[10]++; + return; + } + if (gPaletteFade.active) + return; + if (gTasks[taskId].data[10] == 1) + { + gTasks[taskId].data[10]++; + gUnknown_0202F7C5 = 2; + } + else if (gTasks[taskId].data[10] == 2) + { + s16 data0 = (u16)gTasks[taskId].data[0]; + + if (data0 == -1) + dp01t_11_3_message_for_player_only(); + else + sub_8076DB8(data0); + BeginHardwarePaletteFade(0xE8, 0, 16, 0, 1); + gTasks[taskId].data[10]++; + return; + } + if (gPaletteFade.active) + return; + if (gTasks[taskId].data[10] == 3) + { + DestroyTask(taskId); + gUnknown_0202F7C5 = 0; + } +} + +static void sub_8076DB8(u16 a) +{ + if (IsContest()) + { + void *tilemap = gBattleAnimBackgroundTable[a].tilemap; + void *dmaSrc; + void *dmaDest; + + LZDecompressWram(tilemap, IsContest() ? EWRAM_14800 : EWRAM_18000); + sub_80763FC(sub_80789BC(), IsContest() ? EWRAM_14800 : EWRAM_18000, 0x100, 0); + dmaSrc = IsContest() ? EWRAM_14800 : EWRAM_18000; + dmaDest = (void *)(VRAM + 0xD000); + DmaCopy32(3, dmaSrc, dmaDest, 0x800); + LZDecompressVram(gBattleAnimBackgroundTable[a].image, (void *)(VRAM + 0x2000)); + LoadCompressedPalette(gBattleAnimBackgroundTable[a].palette, sub_80789BC() * 16, 32); + } + else + { + LZDecompressVram(gBattleAnimBackgroundTable[a].tilemap, (void *)(VRAM + 0xD000)); + LZDecompressVram(gBattleAnimBackgroundTable[a].image, (void *)(VRAM + 0x8000)); + LoadCompressedPalette(gBattleAnimBackgroundTable[a].palette, 32, 32); + } +} + +static void dp01t_11_3_message_for_player_only(void) +{ + if (IsContest()) + sub_80AB2AC(); + else + sub_800D7B8(); +} + +static void ScriptCmd_restorebg(void) +{ + u8 taskId; + + gBattleAnimScriptPtr++; + taskId = CreateTask(task_p5_load_battle_screen_elements, 5); + gTasks[taskId].data[0] = 0xFFFF; + gUnknown_0202F7C5 = 1; +} + +static void ScriptCmd_waitbgfadeout(void) +{ + if (gUnknown_0202F7C5 == 2) + { + gBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } +} + +static void ScriptCmd_waitbgfadein(void) +{ + if (gUnknown_0202F7C5 == 0) + { + gBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } +} + +static void ScriptCmd_changebg(void) +{ + gBattleAnimScriptPtr++; + sub_8076DB8(SCRIPT_READ_8(gBattleAnimScriptPtr)); + gBattleAnimScriptPtr++; +} + +//Weird control flow +/* +s8 sub_8076F98(s8 a) +{ + if (!IsContest() && (EWRAM_17810[gBattleAnimBankAttacker].unk0 & 0x10)) + { + a = GetBankSide(gBattleAnimBankAttacker) ? 0xC0 : 0x3F; + } + //_08076FDC + else + { + if (IsContest()) + { + if (gBattleAnimBankAttacker == gBattleAnimBankTarget && gBattleAnimBankAttacker == 2 + && a == 0x3F) + { + //jump to _0807707A + if (a < -0x40) + a = 0xC0; + return a; + } + } + //_08077004 + else + { + if (GetBankSide(gBattleAnimBankAttacker) == 0) + { + if (GetBankSide(gBattleAnimBankTarget) == 0) + } + //_08077042 + else + { + + } + //_0807706C + } + } + //_0807706E +} +*/ +__attribute__((naked)) +s8 sub_8076F98(s8 a) +{ + asm(".syntax unified\n\ + push {r4,lr}\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + bl IsContest\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _08076FDC\n\ + ldr r0, _08076FD4 @ =gBattleAnimBankAttacker\n\ + ldrb r2, [r0]\n\ + lsls r0, r2, 1\n\ + adds r0, r2\n\ + lsls r0, 2\n\ + ldr r1, _08076FD8 @ =0x02017810\n\ + adds r0, r1\n\ + ldrb r1, [r0]\n\ + movs r0, 0x10\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08076FDC\n\ + adds r0, r2, 0\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + movs r4, 0xC0\n\ + cmp r0, 0\n\ + beq _0807706E\n\ + movs r4, 0x3F\n\ + b _0807706E\n\ + .align 2, 0\n\ +_08076FD4: .4byte gBattleAnimBankAttacker\n\ +_08076FD8: .4byte 0x02017810\n\ +_08076FDC:\n\ + bl IsContest\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _08077004\n\ + ldr r0, _08076FFC @ =gBattleAnimBankAttacker\n\ + ldr r1, _08077000 @ =gBattleAnimBankTarget\n\ + ldrb r0, [r0]\n\ + ldrb r1, [r1]\n\ + cmp r0, r1\n\ + bne _08077068\n\ + cmp r0, 0x2\n\ + bne _08077068\n\ + cmp r4, 0x3F\n\ + beq _0807707A\n\ + b _08077068\n\ + .align 2, 0\n\ +_08076FFC: .4byte gBattleAnimBankAttacker\n\ +_08077000: .4byte gBattleAnimBankTarget\n\ +_08077004:\n\ + ldr r0, _0807702C @ =gBattleAnimBankAttacker\n\ + ldrb r0, [r0]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _08077042\n\ + ldr r0, _08077030 @ =gBattleAnimBankTarget\n\ + ldrb r0, [r0]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _0807706E\n\ + lsls r0, r4, 24\n\ + asrs r1, r0, 24\n\ + cmp r1, 0x3F\n\ + bne _08077034\n\ + movs r4, 0xC0\n\ + b _0807706E\n\ + .align 2, 0\n\ +_0807702C: .4byte gBattleAnimBankAttacker\n\ +_08077030: .4byte gBattleAnimBankTarget\n\ +_08077034:\n\ + movs r0, 0x40\n\ + negs r0, r0\n\ + cmp r1, r0\n\ + beq _0807706E\n\ + negs r0, r1\n\ + lsls r0, 24\n\ + b _0807706C\n\ +_08077042:\n\ + ldr r0, _08077064 @ =gBattleAnimBankTarget\n\ + ldrb r0, [r0]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _08077068\n\ + lsls r0, r4, 24\n\ + asrs r0, 24\n\ + movs r1, 0x40\n\ + negs r1, r1\n\ + cmp r0, r1\n\ + bne _0807706E\n\ + movs r4, 0x3F\n\ + b _0807706E\n\ + .align 2, 0\n\ +_08077064: .4byte gBattleAnimBankTarget\n\ +_08077068:\n\ + lsls r0, r4, 24\n\ + negs r0, r0\n\ +_0807706C:\n\ + lsrs r4, r0, 24\n\ +_0807706E:\n\ + lsls r0, r4, 24\n\ + asrs r0, 24\n\ + cmp r0, 0x3F\n\ + ble _0807707A\n\ + movs r4, 0x3F\n\ + b _08077088\n\ +_0807707A:\n\ + lsls r0, r4, 24\n\ + asrs r0, 24\n\ + movs r1, 0x40\n\ + negs r1, r1\n\ + cmp r0, r1\n\ + bge _08077088\n\ + movs r4, 0xC0\n\ +_08077088:\n\ + lsls r0, r4, 24\n\ + asrs r0, 24\n\ + pop {r4}\n\ + pop {r1}\n\ + bx r1\n\ + .syntax divided\n"); +} + +s8 sub_8077094(s8 a) +{ + if (!IsContest() && (EWRAM_17810[gBattleAnimBankAttacker].unk0 & 0x10)) + { + if (GetBankSide(gBattleAnimBankAttacker) != 0) + a = 0x3F; + else + a = 0xC0; + } + else + { + if (GetBankSide(gBattleAnimBankAttacker) != 0 || IsContest() != 0) + a = -a; + } + return a; +} + +s16 sub_8077104(s16 a) +{ + s16 var = a; + + if (var > 63) + var = 63; + else if (var < -64) + var = -64; + return var; +} + +s16 sub_807712C(s16 a, s16 b, s16 c) +{ + u16 var; + + if (a < b) + var = ((c < 0) ? -c : c); + else if (a > b) + var = -((c < 0) ? -c : c); + else + var = 0; + return var; +} + +static void ScriptCmd_panse_19(void) +{ + u16 r4; + s8 r0; + + gBattleAnimScriptPtr++; + r4 = SCRIPT_READ_16(gBattleAnimScriptPtr); + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr + 2); + PlaySE12WithPanning(r4, sub_8076F98(r0)); + gBattleAnimScriptPtr += 3; +} + +static void ScriptCmd_setpan(void) +{ + s8 r0; + + gBattleAnimScriptPtr++; + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr); + SE12PanpotControl(sub_8076F98(r0)); + gBattleAnimScriptPtr++; +} + +static void ScriptCmd_panse_1B(void) +{ + u16 songNum; + s8 r0; + s8 r4; + s8 r6; + u8 r7; + s8 panning; + s8 r8; + u8 taskId; + + gBattleAnimScriptPtr++; + songNum = SCRIPT_READ_16(gBattleAnimScriptPtr); + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr + 2); + r4 = SCRIPT_READ_8(gBattleAnimScriptPtr + 3); + r6 = SCRIPT_READ_8(gBattleAnimScriptPtr + 4); + r7 = SCRIPT_READ_8(gBattleAnimScriptPtr + 5); + panning = sub_8076F98(r0); + r8 = sub_8076F98(r4); + r4 = sub_807712C(panning, r8, r6); + taskId = CreateTask(c3_08073CEC, 1); + gTasks[taskId].data[0] = panning; + gTasks[taskId].data[1] = r8; + gTasks[taskId].data[2] = r4; + gTasks[taskId].data[3] = r7; + gTasks[taskId].data[4] = panning; + PlaySE12WithPanning(songNum, panning); + gAnimSoundTaskCount++; + gBattleAnimScriptPtr += 6; +} + +#ifdef NONMATCHING +static void c3_08073CEC(u8 taskId) +{ + u16 r7 = 0; + s16 r0; + s16 r6; + s16 r3; + s16 r4; + int foo; + + r0 = gTasks[taskId].data[8]; + gTasks[taskId].data[8]++; + if (r0 >= gTasks[taskId].data[3]) + { + gTasks[taskId].data[8] = r7; + r6 = gTasks[taskId].data[0]; + r3 = gTasks[taskId].data[1]; + foo = gTasks[taskId].data[4] + gTasks[taskId].data[2]; + r4 = foo; + gTasks[taskId].data[4] = r4; + if (gTasks[taskId].data[2] == 0) + { + r4 = r3; + DestroyTask(taskId); + gAnimSoundTaskCount--; + } + //_080772D8 + else + { + if (r6 < r3) + { + if (r4 < r3) + goto check; + DestroyTask(taskId); + gAnimSoundTaskCount--; + } + else + { + if (r4 <= r3) + r7 = 1; + check: + if (r7 != 0) + { + DestroyTask(taskId); + gAnimSoundTaskCount--; + } + } + } + //_080772F8 + SE12PanpotControl(r4); + } + //_08077314 +} +#else +__attribute__((naked)) +static void c3_08073CEC(u8 taskId) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + movs r7, 0\n\ + ldr r1, _080772D4 @ =gTasks\n\ + lsls r0, r5, 2\n\ + adds r0, r5\n\ + lsls r0, 3\n\ + adds r2, r0, r1\n\ + ldrh r0, [r2, 0x18]\n\ + adds r1, r0, 0x1\n\ + strh r1, [r2, 0x18]\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + movs r3, 0xE\n\ + ldrsh r1, [r2, r3]\n\ + cmp r0, r1\n\ + blt _08077314\n\ + strh r7, [r2, 0x18]\n\ + ldrh r6, [r2, 0x8]\n\ + ldrh r3, [r2, 0xA]\n\ + movs r4, 0x10\n\ + ldrsh r0, [r2, r4]\n\ + movs r4, 0xC\n\ + ldrsh r1, [r2, r4]\n\ + adds r0, r1\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + strh r4, [r2, 0x10]\n\ + cmp r1, 0\n\ + bne _080772D8\n\ + lsls r2, r3, 16\n\ + b _080772FC\n\ + .align 2, 0\n\ +_080772D4: .4byte gTasks\n\ +_080772D8:\n\ + lsls r1, r6, 16\n\ + lsls r0, r3, 16\n\ + asrs r3, r0, 16\n\ + adds r2, r0, 0\n\ + cmp r1, r2\n\ + bge _080772EE\n\ + lsls r0, r4, 16\n\ + asrs r0, 16\n\ + cmp r0, r3\n\ + blt _080772F8\n\ + b _080772FC\n\ +_080772EE:\n\ + lsls r0, r4, 16\n\ + asrs r0, 16\n\ + cmp r0, r3\n\ + bgt _080772F8\n\ + movs r7, 0x1\n\ +_080772F8:\n\ + cmp r7, 0\n\ + beq _0807730C\n\ +_080772FC:\n\ + lsrs r4, r2, 16\n\ + adds r0, r5, 0\n\ + bl DestroyTask\n\ + ldr r1, _0807731C @ =gAnimSoundTaskCount\n\ + ldrb r0, [r1]\n\ + subs r0, 0x1\n\ + strb r0, [r1]\n\ +_0807730C:\n\ + lsls r0, r4, 24\n\ + asrs r0, 24\n\ + bl SE12PanpotControl\n\ +_08077314:\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0807731C: .4byte gAnimSoundTaskCount\n\ + .syntax divided\n"); +} +#endif + +static void ScriptCmd_panse_26(void) +{ + u16 r8; + s8 r4; + s8 r5; + s8 r6; + u8 r10; + u8 taskId; + + gBattleAnimScriptPtr++; + r8 = SCRIPT_READ_16(gBattleAnimScriptPtr); + r4 = SCRIPT_READ_8(gBattleAnimScriptPtr + 2); + r5 = SCRIPT_READ_8(gBattleAnimScriptPtr + 3); + r6 = SCRIPT_READ_8(gBattleAnimScriptPtr + 4); + r10 = SCRIPT_READ_8(gBattleAnimScriptPtr + 5); + taskId = CreateTask(c3_08073CEC, 1); + gTasks[taskId].data[0] = r4; + gTasks[taskId].data[1] = r5; + gTasks[taskId].data[2] = r6; + gTasks[taskId].data[3] = r10; + gTasks[taskId].data[4] = r4; + PlaySE12WithPanning(r8, r4); + gAnimSoundTaskCount++; + gBattleAnimScriptPtr += 6; +} + +static void ScriptCmd_panse_27(void) +{ + u16 r9; + u8 r4; + u8 r8; + u8 r7; + u8 r0; + s8 r6; + s8 r5; + s8 r4_2; + u8 taskId; + + gBattleAnimScriptPtr++; + r9 = SCRIPT_READ_16(gBattleAnimScriptPtr); + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr + 2); + r4 = SCRIPT_READ_8(gBattleAnimScriptPtr + 3); + r8 = SCRIPT_READ_8(gBattleAnimScriptPtr + 4); + r7 = SCRIPT_READ_8(gBattleAnimScriptPtr + 5); + r6 = sub_8077094(r0); + r5 = sub_8077094(r4); + r4_2 = sub_8077094(r8); + taskId = CreateTask(c3_08073CEC, 1); + gTasks[taskId].data[0] = r6; + gTasks[taskId].data[1] = r5; + gTasks[taskId].data[2] = r4_2; + gTasks[taskId].data[3] = r7; + gTasks[taskId].data[4] = r6; + PlaySE12WithPanning(r9, r6); + gAnimSoundTaskCount++; + gBattleAnimScriptPtr += 6; +} + +static void ScriptCmd_panse_1C(void) +{ + u16 r5; + u8 r0; + u8 r8; + u8 r9; + s8 r4; + u8 taskId; + + gBattleAnimScriptPtr++; + r5 = SCRIPT_READ_16(gBattleAnimScriptPtr); + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr + 2); + r8 = SCRIPT_READ_8(gBattleAnimScriptPtr + 3); + r9 = SCRIPT_READ_8(gBattleAnimScriptPtr + 4); + r4 = sub_8076F98(r0); + taskId = CreateTask(sub_80774FC, 1); + gTasks[taskId].data[0] = r5; + gTasks[taskId].data[1] = r4; + gTasks[taskId].data[2] = r8; + gTasks[taskId].data[3] = r9; + gTasks[taskId].data[8] = r8; + gTasks[taskId].func(taskId); + gAnimSoundTaskCount++; + gBattleAnimScriptPtr += 5; +} + +static void sub_80774FC(u8 taskId) +{ + s16 data8; + u16 r0; + s8 r1; + u8 r4; + + data8 = gTasks[taskId].data[8]; + gTasks[taskId].data[8]++; + if (data8 >= gTasks[taskId].data[2]) + { + gTasks[taskId].data[8] = 0; + r0 = gTasks[taskId].data[0]; + r1 = gTasks[taskId].data[1]; + gTasks[taskId].data[3]--; + r4 = gTasks[taskId].data[3]; + PlaySE12WithPanning(r0, r1); + if (r4 == 0) + { + DestroyTask(taskId); + gAnimSoundTaskCount--; + } + } +} + +static void ScriptCmd_panse_1D(void) +{ + u16 r5; + u8 r0; + u8 r8; + s8 r4; + u8 taskId; + + gBattleAnimScriptPtr++; + r5 = SCRIPT_READ_16(gBattleAnimScriptPtr); + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr + 2); + r8 = SCRIPT_READ_8(gBattleAnimScriptPtr + 3); + r4 = sub_8076F98(r0); + taskId = CreateTask(sub_80775CC, 1); + gTasks[taskId].data[0] = r5; + gTasks[taskId].data[1] = r4; + gTasks[taskId].data[2] = r8; + gAnimSoundTaskCount++; + gBattleAnimScriptPtr += 4; +} + +static void sub_80775CC(u8 taskId) +{ + s16 r0; + + r0 = gTasks[taskId].data[2]; + gTasks[taskId].data[2]--; + if (r0 <= 0) + { + PlaySE12WithPanning(gTasks[taskId].data[0], gTasks[taskId].data[1]); + DestroyTask(taskId); + gAnimSoundTaskCount--; + } +} + +static void ScriptCmd_createtask_1F(void) +{ + TaskFunc func; + u8 numArgs; + int i; + u8 taskId; + + gBattleAnimScriptPtr++; + func = (TaskFunc)SCRIPT_READ_32(gBattleAnimScriptPtr); + gBattleAnimScriptPtr += 4; + numArgs = SCRIPT_READ_8(gBattleAnimScriptPtr); + gBattleAnimScriptPtr++; + for (i = 0; i < numArgs; i++) + { + gBattleAnimArgs[i] = SCRIPT_READ_16(gBattleAnimScriptPtr); + gBattleAnimScriptPtr += 2; + } + taskId = CreateTask(func, 1); + func(taskId); + gAnimSoundTaskCount++; +} + +static void ScriptCmd_waitsound(void) +{ + if (gAnimSoundTaskCount != 0) + { + gSoundAnimFramesToWait = 0; + gAnimFramesToWait = 1; + } + else if (IsSEPlaying()) + { + if (++gSoundAnimFramesToWait > 90) + { + m4aMPlayStop(&gMPlay_SE1); + m4aMPlayStop(&gMPlay_SE2); + gSoundAnimFramesToWait = 0; + } + else + { + gAnimFramesToWait = 1; + } + } + else + { + gSoundAnimFramesToWait = 0; + gBattleAnimScriptPtr++; + gAnimFramesToWait = 0; + } +} + +static void ScriptCmd_jumpvareq(void) +{ + u8 r2; + s16 r1; + u8 *addr; + + gBattleAnimScriptPtr++; + r2 = SCRIPT_READ_8(gBattleAnimScriptPtr); + r1 = SCRIPT_READ_16(gBattleAnimScriptPtr + 1); + if (r1 == gBattleAnimArgs[r2]) + { + addr = (u8 *)SCRIPT_READ_32(gBattleAnimScriptPtr + 3); + gBattleAnimScriptPtr = addr; + } + else + { + gBattleAnimScriptPtr += 7; + } +} + +static void ScriptCmd_jumpunkcond(void) +{ + u8 *addr; + + gBattleAnimScriptPtr++; + if (IsContest()) + { + addr = (u8 *)SCRIPT_READ_32(gBattleAnimScriptPtr); + gBattleAnimScriptPtr = addr; + } + else + { + gBattleAnimScriptPtr += 4; + } +} + +static void ScriptCmd_monbgprio_28(void) +{ + u8 r2; + u8 r0; + u8 r4; + + r2 = SCRIPT_READ_8(gBattleAnimScriptPtr + 1); + gBattleAnimScriptPtr += 2; + if (r2 != 0) + r0 = gBattleAnimBankTarget; + else + r0 = gBattleAnimBankAttacker; + r4 = GetBankIdentity(r0); + if (!IsContest() && (r4 == 0 || r4 == 3)) + { + REG_BG1CNT_BITFIELD.priority = 1; + REG_BG2CNT_BITFIELD.priority = 2; + } +} + +static void ScriptCmd_monbgprio_29(void) +{ + gBattleAnimScriptPtr++; + if (!IsContest()) + { + REG_BG1CNT_BITFIELD.priority = 1; + REG_BG2CNT_BITFIELD.priority = 2; + } +} + +static void ScriptCmd_monbgprio_2A(void) +{ + u8 r6; + u8 r4; + u8 r0; + + r6 = SCRIPT_READ_8(gBattleAnimScriptPtr + 1); + gBattleAnimScriptPtr += 2; + if (GetBankSide(gBattleAnimBankAttacker) != GetBankSide(gBattleAnimBankTarget)) + { + if (r6 != 0) + r0 = gBattleAnimBankTarget; + else + r0 = gBattleAnimBankAttacker; + r4 = GetBankIdentity(r0); + if (!IsContest() && (r4 == 0 || r4 == 3)) + { + REG_BG1CNT_BITFIELD.priority = 1; + REG_BG2CNT_BITFIELD.priority = 2; + } + } +} + +static void ScriptCmd_invisible(void) +{ + u8 r0; + u8 spriteId; + + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr + 1); + spriteId = GetAnimBankSpriteId(r0); + if (spriteId != 0xFF) + { + gSprites[spriteId].invisible = TRUE; + } + gBattleAnimScriptPtr += 2; +} + +static void ScriptCmd_visible(void) +{ + u8 r0; + u8 spriteId; + + r0 = SCRIPT_READ_8(gBattleAnimScriptPtr + 1); + spriteId = GetAnimBankSpriteId(r0); + if (spriteId != 0xFF) + { + gSprites[spriteId].invisible = FALSE; + } + gBattleAnimScriptPtr += 2; +} + +static void ScriptCmd_doublebattle_2D(void) +{ + u8 r7; + u8 r4; + u8 spriteId; + + r7 = SCRIPT_READ_8(gBattleAnimScriptPtr + 1); + gBattleAnimScriptPtr += 2; + if (!IsContest() && IsDoubleBattle() + && GetBankSide(gBattleAnimBankAttacker) == GetBankSide(gBattleAnimBankTarget)) + { + if (r7 == 0) + { + r4 = GetBankIdentity_permutated(gBattleAnimBankAttacker); + spriteId = GetAnimBankSpriteId(0); + } + else + { + r4 = GetBankIdentity_permutated(gBattleAnimBankTarget); + spriteId = GetAnimBankSpriteId(1); + } + if (spriteId != 0xFF) + { + gSprites[spriteId].invisible = FALSE; + if (r4 == 2) + gSprites[spriteId].oam.priority = 3; + if (r4 == 1) + sub_8076464(0); + else + sub_8076464(1); + } + } +} + +static void ScriptCmd_doublebattle_2E(void) +{ + u8 r7; + u8 r4; + u8 spriteId; + + r7 = SCRIPT_READ_8(gBattleAnimScriptPtr + 1); + gBattleAnimScriptPtr += 2; + if (!IsContest() && IsDoubleBattle() + && GetBankSide(gBattleAnimBankAttacker) == GetBankSide(gBattleAnimBankTarget)) + { + if (r7 == 0) + { + r4 = GetBankIdentity_permutated(gBattleAnimBankAttacker); + spriteId = GetAnimBankSpriteId(0); + } + else + { + r4 = GetBankIdentity_permutated(gBattleAnimBankTarget); + spriteId = GetAnimBankSpriteId(1); + } + if (spriteId != 0xFF && r4 == 2) + { + gSprites[spriteId].oam.priority = 2; + } + } +} + +static void ScriptCmd_stopsound(void) +{ + m4aMPlayStop(&gMPlay_SE1); + m4aMPlayStop(&gMPlay_SE2); + gBattleAnimScriptPtr++; +} diff --git a/src/battle/battle_anim_807B69C.c b/src/battle/battle_anim_807B69C.c new file mode 100644 index 000000000..bf3eb7ef1 --- /dev/null +++ b/src/battle/battle_anim_807B69C.c @@ -0,0 +1,353 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "blend_palette.h" +#include "decompress.h" +#include "palette.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" + +extern u8 gBattleAnimBankAttacker; +extern u8 gBattleAnimBankTarget; +extern bool8 gAnimScriptActive; +extern void (*gAnimScriptCallback)(void); +extern s16 gBattleAnimArgs[]; +extern u8 gBattleAnimBankTarget; +extern u8 gObjectBankIDs[]; +extern const struct CompressedSpriteSheet gBattleAnimPicTable[]; +extern const struct CompressedSpritePalette gBattleAnimPaletteTable[]; +extern const u8 *const gBattleAnims_StatusConditions[]; +extern const struct OamData gOamData_837E05C; +extern const struct OamData gOamData_837DF24; + +extern u8 sub_8077ABC(u8, u8); +extern void sub_80E32E0(u8); + + +static const struct Subsprite gSubspriteTable_83931B8[] = +{ + {.x = -16, .y = -16, .shape = ST_OAM_SQUARE, .size = 3, .tileOffset = 0, .priority = 2}, + {.x = -16, .y = 48, .shape = ST_OAM_H_RECTANGLE, .size = 3, .tileOffset = 64, .priority = 2}, + {.x = 48, .y = -16, .shape = ST_OAM_V_RECTANGLE, .size = 3, .tileOffset = 96, .priority = 2}, + {.x = 48, .y = 48, .shape = ST_OAM_SQUARE, .size = 2, .tileOffset = 128, .priority = 2}, +}; + +static const struct SubspriteTable gSubspriteTables_83931D8[] = +{ + {ARRAY_COUNT(gSubspriteTable_83931B8), gSubspriteTable_83931B8}, +}; + +static const struct SpriteTemplate gSpriteTemplate_83931E0 = +{ + .tileTag = 10010, + .paletteTag = 10010, + .oam = &gOamData_837E05C, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +static void sub_807B870(struct Sprite *); +static const struct SpriteTemplate gSpriteTemplate_83931F8 = +{ + .tileTag = 10136, + .paletteTag = 10136, + .oam = &gOamData_837DF24, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_807B870, +}; + +static void sub_807B7E0(u8); +static void sub_807B8A4(struct Sprite *); +static void sub_807B9D8(u8); +static void sub_807BA24(u8); +static void sub_807BAD4(u8); +static void sub_807BB24(u8); +static void sub_807BDAC(u8); + +u8 unref_sub_807B69C(u8 a, u8 b) +{ + u8 spriteId1 = gObjectBankIDs[a]; + u8 taskId = CreateTask(sub_807B7E0, 10); + u8 spriteId2; + u8 i; + + LoadCompressedObjectPic(&gBattleAnimPicTable[136]); + LoadCompressedObjectPalette(&gBattleAnimPaletteTable[136]); + gTasks[taskId].data[0] = a; + if (b != 0) + { + gTasks[taskId].data[1] = 0x1F; + for (i = 0; i < 10; i++) + { + spriteId2 = CreateSprite(&gSpriteTemplate_83931F8, gSprites[spriteId1].pos1.x, gSprites[spriteId1].pos1.y + 32, 0); + gSprites[spriteId2].data0 = i * 51; + gSprites[spriteId2].data1 = -256; + gSprites[spriteId2].invisible = TRUE; + if (i > 4) + gSprites[spriteId2].data6 = 21; + } + } + else + { + gTasks[taskId].data[1] = 0x7C00; + for (i = 0; i < 10; i++) + { + spriteId2 = CreateSprite(&gSpriteTemplate_83931F8, gSprites[spriteId1].pos1.x, gSprites[spriteId1].pos1.y - 32, 0); + gSprites[spriteId2].data0 = i * 51; + gSprites[spriteId2].data1 = 256; + gSprites[spriteId2].invisible = TRUE; + if (i > 4) + gSprites[spriteId2].data6 = 21; + } + } + gSprites[spriteId2].data7 = 1; + return taskId; +} + +static void sub_807B7E0(u8 taskId) +{ + if (gTasks[taskId].data[2] == 2) + { + gTasks[taskId].data[2] = 0; + BlendPalette(0x100 + gTasks[taskId].data[0] * 16, 16, gTasks[taskId].data[4], gTasks[taskId].data[1]); + if (gTasks[taskId].data[5] == 0) + { + gTasks[taskId].data[4]++; + if (gTasks[taskId].data[4] > 8) + gTasks[taskId].data[5] ^= 1; + } + else + { + u16 var = gTasks[taskId].data[4]; + + gTasks[taskId].data[4]--; + if (gTasks[taskId].data[4] < 0) + { + gTasks[taskId].data[4] = var; + gTasks[taskId].data[5] ^= 1; + gTasks[taskId].data[3]++; + if (gTasks[taskId].data[3] == 2) + DestroyTask(taskId); + } + } + } + else + { + gTasks[taskId].data[2]++; + } +} + +static void sub_807B870(struct Sprite *sprite) +{ + if (sprite->data6 == 0) + { + sprite->invisible = FALSE; + sprite->callback = sub_807B8A4; + sub_807B8A4(sprite); + } + else + { + sprite->data6 --; + } +} + +static void sub_807B8A4(struct Sprite *sprite) +{ + sprite->pos2.x = Cos(sprite->data0, 32); + sprite->pos2.y = Sin(sprite->data0, 8); + if (sprite->data0 < 128) + sprite->subpriority = 29; + else + sprite->subpriority = 31; + sprite->data0 = (sprite->data0 + 8) & 0xFF; + sprite->data5 += sprite->data1; + sprite->pos2.y += sprite->data5 >> 8; + sprite->data2++; + if (sprite->data2 == 52) + { + if (sprite->data7 != 0) + DestroySpriteAndFreeResources(sprite); + else + DestroySprite(sprite); + } +} + +void sub_807B920(u8 taskId) +{ + s16 x = sub_8077ABC(gBattleAnimBankTarget, 2) - 32; + s16 y = sub_8077ABC(gBattleAnimBankTarget, 3) - 36; + u8 spriteId; + + if (IsContest()) + x -= 6; + REG_BLDCNT = 0x3F40; + REG_BLDALPHA = 0x1000; + spriteId = CreateSprite(&gSpriteTemplate_83931E0, x, y, 4); + SetSubspriteTables(&gSprites[spriteId], gSubspriteTables_83931D8); + gTasks[taskId].data[15] = spriteId; + gTasks[taskId].func = sub_807B9D8; +} + +static void sub_807B9D8(u8 taskId) +{ + gTasks[taskId].data[1]++; + if (gTasks[taskId].data[1] == 10) + { + gTasks[taskId].func = sub_807BA24; + gTasks[taskId].data[1] = 0; + } + else + { + u8 var = gTasks[taskId].data[1]; + + REG_BLDALPHA = ((16 - var) << 8) | var; + } +} + +static void sub_807BA24(u8 taskId) +{ + u8 r2 = IndexOfSpritePaletteTag(0x271A); + + if (gTasks[taskId].data[1]++ > 13) + { + gTasks[taskId].data[2]++; + if (gTasks[taskId].data[2] == 3) + { + u16 temp; + + temp = gPlttBufferFaded[0x100 + r2 * 16 + 13]; + gPlttBufferFaded[0x100 + r2 * 16 + 13] = gPlttBufferFaded[0x100 + r2 * 16 + 14]; + gPlttBufferFaded[0x100 + r2 * 16 + 14] = gPlttBufferFaded[0x100 + r2 * 16 + 15]; + gPlttBufferFaded[0x100 + r2 * 16 + 15] = temp; + + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3]++; + if (gTasks[taskId].data[3] == 3) + { + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[4]++; + if (gTasks[taskId].data[4] == 2) + { + gTasks[taskId].data[1] = 9; + gTasks[taskId].func = sub_807BAD4; + } + } + } + } +} + +static void sub_807BAD4(u8 taskId) +{ + gTasks[taskId].data[1]--; + if (gTasks[taskId].data[1] == -1) + { + gTasks[taskId].func = sub_807BB24; + gTasks[taskId].data[1] = 0; + } + else + { + u8 var = gTasks[taskId].data[1]; + + REG_BLDALPHA = ((16 - var) << 8) | var; + } +} + +static void sub_807BB24(u8 taskId) +{ + gTasks[taskId].data[1]++; + if (gTasks[taskId].data[1] == 37) + { + u8 spriteId = gTasks[taskId].data[15]; + + FreeSpriteOamMatrix(&gSprites[spriteId]); + DestroySprite(&gSprites[spriteId]); + } + else if (gTasks[taskId].data[1] == 39) + { + REG_BLDCNT = 0; + REG_BLDALPHA = 0; + DestroyAnimVisualTask(taskId); + } +} + +void sub_807BB88(u8 taskId) +{ + s16 r5; + s16 r2; + s16 r3 = 0; + + switch (ewram17840.unk0) + { + case 15: r5 = 0; r2 = 0; break; + case 16: r5 = 0; r2 = 1; break; + case 17: r5 = 0; r2 = 3; break; + case 18: r5 = 0; r2 = 5; break; + case 19: r5 = 0; r2 = 6; break; + case 20: r5 = 0; r2 = 2; break; + case 21: r5 = 0; r2 = 4; break; + case 22: r5 = 1; r2 = 0; break; + case 23: r5 = 1; r2 = 1; break; + case 24: r5 = 1; r2 = 3; break; + case 25: r5 = 1; r2 = 5; break; + case 26: r5 = 1; r2 = 6; break; + case 27: r5 = 1; r2 = 2; break; + case 28: r5 = 1; r2 = 4; break; + case 39: r5 = 0; r2 = 0; r3 = 1; break; + case 40: r5 = 0; r2 = 1; r3 = 1; break; + case 41: r5 = 0; r2 = 3; r3 = 1; break; + case 42: r5 = 0; r2 = 5; r3 = 1; break; + case 43: r5 = 0; r2 = 6; r3 = 1; break; + case 44: r5 = 0; r2 = 2; r3 = 1; break; + case 45: r5 = 0; r2 = 4; r3 = 1; break; + case 46: r5 = 1; r2 = 0; r3 = 1; break; + case 47: r5 = 1; r2 = 1; r3 = 1; break; + case 48: r5 = 1; r2 = 3; r3 = 1; break; + case 49: r5 = 1; r2 = 5; r3 = 1; break; + case 50: r5 = 1; r2 = 6; r3 = 1; break; + case 51: r5 = 1; r2 = 2; r3 = 1; break; + case 52: r5 = 1; r2 = 4; r3 = 1; break; + case 55: r5 = 0; r2 = 0xFF; r3 = 0; break; + case 56: r5 = 0; r2 = 0xFF; r3 = 1; break; + case 57: r5 = 1; r2 = 0xFF; r3 = 0; break; + case 58: r5 = 1; r2 = 0xFF; r3 = 1; break; + + default: + DestroyAnimVisualTask(taskId); + return; + } + + gBattleAnimArgs[0] = r5; + gBattleAnimArgs[1] = r2; + gBattleAnimArgs[2] = 0; + gBattleAnimArgs[3] = 0; + gBattleAnimArgs[4] = r3; + gTasks[taskId].func = sub_80E32E0; + sub_80E32E0(taskId); +} + +void move_anim_start_t2(u8 a, u8 b) +{ + u8 taskId; + + gBattleAnimBankAttacker = a; + gBattleAnimBankTarget = a; + DoMoveAnim(gBattleAnims_StatusConditions, b, 0); + taskId = CreateTask(sub_807BDAC, 10); + gTasks[taskId].data[0] = a; +} + +static void sub_807BDAC(u8 taskId) +{ + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + ewram17810[gTasks[taskId].data[0]].unk0_4 = 0; + DestroyTask(taskId); + } +} diff --git a/src/battle/battle_anim_80A7E7C.c b/src/battle/battle_anim_80A7E7C.c new file mode 100644 index 000000000..e0c79dc8e --- /dev/null +++ b/src/battle/battle_anim_80A7E7C.c @@ -0,0 +1,940 @@ +#include "global.h" +#include "battle_anim.h" +#include "rom_8077ABC.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" + +#define SPRITE gSprites[TASK.data[0]] + +extern s16 gBattleAnimArgs[8]; + +extern u8 gObjectBankIDs[]; +extern s32 gMoveDmgMoveAnim; +extern u16 gMovePowerMoveAnim; +extern u8 gBattleAnimBankAttacker; +extern u8 gBattleAnimBankTarget; + +static void sub_80A7EF0(u8 taskId); +static void sub_80A808C(u8 taskId); +static void sub_80A81D8(u8 taskId); +static void sub_80A8374(u8 taskId); +static void sub_80A8488(u8 taskId); +static void sub_80A85A4(struct Sprite *sprite); +void sub_80A8614(struct Sprite* sprite); +static void sub_80A86F4(struct Sprite *sprite); +static void sub_80A88F0(struct Sprite *sprite); +static void sub_80A89B4(u8 taskId); +static void sub_80A8A18(u8 taskId); +static void sub_80A8C0C(u8 taskId); +static void sub_80A8D8C(u8 taskId); +void sub_80A8FD8(u8 taskId); +static void sub_80A913C(u8 taskId); + +void sub_80A7E7C(u8 taskId) +{ + u8 sprite; + sprite = GetAnimBankSpriteId(gBattleAnimArgs[0]); + if (sprite == 0xff) + { + DestroyAnimVisualTask(taskId); + return; + } + gSprites[sprite].pos2.x = gBattleAnimArgs[1]; + gSprites[sprite].pos2.y = gBattleAnimArgs[2]; + TASK.data[0] = sprite; + TASK.data[1] = gBattleAnimArgs[3]; + TASK.data[2] = gBattleAnimArgs[4]; + TASK.data[3] = gBattleAnimArgs[4]; + TASK.data[4] = gBattleAnimArgs[1]; + TASK.data[5] = gBattleAnimArgs[2]; + TASK.func = sub_80A7EF0; + sub_80A7EF0(taskId); +} + +static void sub_80A7EF0(u8 taskId) +{ + if (TASK.data[3] == 0) + { + if (SPRITE.pos2.x == 0) + { + SPRITE.pos2.x = TASK.data[4]; + } + else + { + SPRITE.pos2.x = 0; + } + if (SPRITE.pos2.y == 0) + { + SPRITE.pos2.y = TASK.data[5]; + } + else + { + SPRITE.pos2.y = 0; + } + TASK.data[3] = TASK.data[2]; + if (--TASK.data[1] == 0) + { + SPRITE.pos2.x = 0; + SPRITE.pos2.y = 0; + DestroyAnimVisualTask(taskId); + return; + } + } + else + { + TASK.data[3]--; + } +} + + +void sub_80A7FA0(u8 taskId) +{ + u8 sprite; + bool8 r6; + u8 side; + r6 = 0; + if (gBattleAnimArgs[0] < 4) + { + sprite = GetAnimBankSpriteId(gBattleAnimArgs[0]); + if (sprite == 0xff) + { + DestroyAnimVisualTask(taskId); + return; + } + } + else if (gBattleAnimArgs[0] != 8) + { + switch (gBattleAnimArgs[0]) + { + case 4: + side = GetBankByPlayerAI(0); + break; + case 5: + side = GetBankByPlayerAI(2); + break; + case 6: + side = GetBankByPlayerAI(1); + break; + case 7: + default: + side = GetBankByPlayerAI(3); + break; + } + if (IsAnimBankSpriteVisible(side) == FALSE) + { + r6 = 1; + } + sprite = gObjectBankIDs[side]; + } + else + { + sprite = gObjectBankIDs[gBattleAnimBankAttacker]; + } + if (r6) + { + DestroyAnimVisualTask(taskId); + return; + } + gSprites[sprite].pos2.x = gBattleAnimArgs[1]; + gSprites[sprite].pos2.y = gBattleAnimArgs[2]; + TASK.data[0] = sprite; + TASK.data[1] = gBattleAnimArgs[3]; + TASK.data[2] = gBattleAnimArgs[4]; + TASK.data[3] = gBattleAnimArgs[4]; + TASK.data[4] = gBattleAnimArgs[1]; + TASK.data[5] = gBattleAnimArgs[2]; + TASK.func = sub_80A808C; + sub_80A808C(taskId); +} + +static void sub_80A808C(u8 taskId) +{ + if (TASK.data[3] == 0) + { + if (SPRITE.pos2.x == TASK.data[4]) + { + SPRITE.pos2.x = -TASK.data[4]; + } + else + { + SPRITE.pos2.x = TASK.data[4]; + } + if (SPRITE.pos2.y == TASK.data[5]) + { + SPRITE.pos2.y = -TASK.data[5]; + } + else + { + SPRITE.pos2.y = TASK.data[5]; + } + TASK.data[3] = TASK.data[2]; + if (--TASK.data[1] == 0) + { + SPRITE.pos2.x = 0; + SPRITE.pos2.y = 0; + DestroyAnimVisualTask(taskId); + return; + } + } + else + { + TASK.data[3]--; + } +} + +void sub_80A8154(u8 taskId) +{ + u8 sprite; + sprite = GetAnimBankSpriteId(gBattleAnimArgs[0]); + if (sprite == 0xff) + { + DestroyAnimVisualTask(taskId); + return; + } + gSprites[sprite].pos2.x += gBattleAnimArgs[1]; + gSprites[sprite].pos2.y += gBattleAnimArgs[2]; + TASK.data[0] = sprite; + TASK.data[1] = 0; + TASK.data[2] = gBattleAnimArgs[3]; + TASK.data[3] = 0; + TASK.data[4] = gBattleAnimArgs[4]; + TASK.data[5] = gBattleAnimArgs[1] * 2; + TASK.data[6] = gBattleAnimArgs[2] * 2; + TASK.func = sub_80A81D8; + sub_80A81D8(taskId); +} + +static void sub_80A81D8(u8 taskId) +{ + if (TASK.data[3] == 0) + { + if (TASK.data[1] & 1) + { + SPRITE.pos2.x += TASK.data[5]; + SPRITE.pos2.y += TASK.data[6]; + } + else + { + SPRITE.pos2.x -= TASK.data[5]; + SPRITE.pos2.y -= TASK.data[6]; + } + TASK.data[3] = TASK.data[4]; + if (++TASK.data[1] >= TASK.data[2]) + { + if (TASK.data[1] & 1) + { + SPRITE.pos2.x += TASK.data[5] / 2; + SPRITE.pos2.y += TASK.data[6] / 2; + } + else + { + SPRITE.pos2.x -= TASK.data[5] / 2; + SPRITE.pos2.y -= TASK.data[6] / 2; + } + DestroyAnimVisualTask(taskId); + return; + } + } + else + { + TASK.data[3]--; + } +} + +void sub_80A8314(u8 taskId) +{ + u8 sprite = GetAnimBankSpriteId(gBattleAnimArgs[0]); + gSprites[sprite].pos2.x = gBattleAnimArgs[1]; + TASK.data[0] = sprite; + TASK.data[1] = gBattleAnimArgs[1]; + TASK.data[2] = gBattleAnimArgs[2]; + TASK.data[3] = gBattleAnimArgs[3]; + TASK.data[4] = gBattleAnimArgs[4]; + TASK.func = sub_80A8374; + sub_80A8374(taskId); +} + +static void sub_80A8374(u8 taskId) +{ + s16 x; + u8 sprite; + sprite = TASK.data[0]; + x = TASK.data[1]; + if (TASK.data[2] == TASK.data[8]++) + { + TASK.data[8] = 0; + if (gSprites[sprite].pos2.x == x) + { + x = -x; + } + gSprites[sprite].pos2.x += x; + } + TASK.data[1] = x; + TASK.data[9] += TASK.data[3]; + gSprites[sprite].pos2.y = TASK.data[9] >> 8; + if (--TASK.data[4] == 0) + { + DestroyAnimVisualTask(taskId); + return; + } +} + +void sub_80A8408(u8 taskId) +{ + u8 i; + u8 sprite; + u8 v1; + v1 = 1; + sprite = GetAnimBankSpriteId(gBattleAnimArgs[0]); + if (gBattleAnimArgs[4] > 5) + { + gBattleAnimArgs[4] = 5; + } + for (i = 0; i < gBattleAnimArgs[4]; i++) + { + v1 <<= 1; + } + TASK.data[0] = sprite; + TASK.data[1] = gBattleAnimArgs[1]; + TASK.data[2] = gBattleAnimArgs[2]; + TASK.data[3] = gBattleAnimArgs[3]; + TASK.data[4] = v1; + TASK.func = sub_80A8488; + sub_80A8488(taskId); +} + +static void sub_80A8488(u8 taskId) +{ + u8 sprite; + sprite = TASK.data[0]; + gSprites[sprite].pos2.x = Sin(TASK.data[5], TASK.data[1]); + gSprites[sprite].pos2.y = -Cos(TASK.data[5], TASK.data[2]); + gSprites[sprite].pos2.y += TASK.data[2]; + TASK.data[5] += TASK.data[4]; + TASK.data[5] &= 0xff; + if (TASK.data[5] == 0) + { + TASK.data[3]--; + } + if (TASK.data[3] == 0) + { + gSprites[sprite].pos2.x = 0; + gSprites[sprite].pos2.y = 0; + DestroyAnimVisualTask(taskId); + return; + } +} + +void sub_80A8500(u8 taskId) +{ + if (GetBankSide(gBattleAnimBankAttacker)) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + } + sub_80A8408(taskId); +} + +void sub_80A8530(struct Sprite *sprite) +{ + sprite->invisible = TRUE; + if (GetBankSide(gBattleAnimBankAttacker)) + { + sprite->data1 = -gBattleAnimArgs[1]; + } + else + { + sprite->data1 = gBattleAnimArgs[1]; + } + sprite->data0 = gBattleAnimArgs[0]; + sprite->data2 = 0; + sprite->data3 = gObjectBankIDs[gBattleAnimBankAttacker]; + sprite->data4 = gBattleAnimArgs[0]; + StoreSpriteCallbackInData6(sprite, sub_80A85A4); + sprite->callback = sub_8078458; +} + +static void sub_80A85A4(struct Sprite *sprite) +{ + sprite->data0 = sprite->data4; + sprite->data1 = -sprite->data1; + sprite->callback = sub_8078458; + StoreSpriteCallbackInData6(sprite, move_anim_8072740); +} + +void sub_80A85C8(struct Sprite *sprite) +{ + u8 spriteId; + sprite->invisible = TRUE; + spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]); + sprite->data0 = gBattleAnimArgs[0]; + sprite->data1 = 0; + sprite->data2 = gBattleAnimArgs[1]; + sprite->data3 = spriteId; + sprite->data4 = gBattleAnimArgs[0]; + StoreSpriteCallbackInData6(sprite, sub_80A8614); + sprite->callback = sub_8078458; +} + +void sub_80A8614(struct Sprite *sprite) +{ + sprite->data0 = sprite->data4; + sprite->data2 = -sprite->data2; + sprite->callback = sub_8078458; + StoreSpriteCallbackInData6(sprite, move_anim_8072740); +} + +void sub_80A8638(struct Sprite *sprite) +{ + int something; + int spriteId; + if (!gBattleAnimArgs[0]) + { + spriteId = gObjectBankIDs[gBattleAnimBankAttacker]; + } + else + { + spriteId = gObjectBankIDs[gBattleAnimBankTarget]; + } + sprite->data0 = gBattleAnimArgs[2]; + sprite->data1 = gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x; + sprite->data2 = gSprites[spriteId].pos1.x; + sprite->data3 = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y; + sprite->data4 = gSprites[spriteId].pos1.y; + something = 0; + sub_8078A5C(sprite); + sprite->data3 = something; + sprite->data4 = something; + sprite->data5 = gSprites[spriteId].pos2.x; + sprite->data6 = gSprites[spriteId].pos2.y; + sprite->invisible = TRUE; + if (gBattleAnimArgs[1] == 1) + { + sprite->data2 = something; + } + else if (gBattleAnimArgs[1] == 2) + { + sprite->data1 = something; + } + sprite->data7 = gBattleAnimArgs[1]; + sprite->data7 |= spriteId << 8; + sprite->callback = sub_80A86F4; +} + +static void sub_80A86F4(struct Sprite *sprite) +{ + s8 spriteId; + u8 lo; + struct Sprite *sprite2; + lo = sprite->data7 & 0xff; + spriteId = sprite->data7 >> 8; + sprite2 = &gSprites[spriteId]; + if (sprite->data0 == 0) + { + if (lo < 2) + { + sprite2->pos2.x = 0; + } + if (lo == 2 || lo == 0) + { + sprite2->pos2.y = 0; + } + move_anim_8072740(sprite); + } + else + { + sprite->data0--; + sprite->data3 += sprite->data1; + sprite->data4 += sprite->data2; + sprite2->pos2.x = (s8)(sprite->data3 >> 8) + sprite->data5; + sprite2->pos2.y = (s8)(sprite->data4 >> 8) + sprite->data6; + } +} + +void sub_80A8764(struct Sprite *sprite) +{ + u8 v1; + u8 spriteId; + if (!gBattleAnimArgs[0]) + { + v1 = gBattleAnimBankAttacker; + } + else + { + v1 = gBattleAnimBankTarget; + } + spriteId = gObjectBankIDs[v1]; + if (GetBankSide(v1)) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + if (gBattleAnimArgs[3] == 1) + { + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + } + } + sprite->data0 = gBattleAnimArgs[4]; + sprite->data1 = gSprites[spriteId].pos1.x; + sprite->data2 = gSprites[spriteId].pos1.x + gBattleAnimArgs[1]; + sprite->data3 = gSprites[spriteId].pos1.y; + sprite->data4 = gSprites[spriteId].pos1.y + gBattleAnimArgs[2]; + sub_8078A5C(sprite); + sprite->data3 = 0; + sprite->data4 = 0; + sprite->data5 = spriteId; + sprite->invisible = TRUE; + StoreSpriteCallbackInData6(sprite, move_anim_8072740); + sprite->callback = sub_80784A8; +} + +void sub_80A8818(struct Sprite *sprite) +{ + u8 spriteId; + u8 v1; + sprite->invisible = TRUE; + if (!gBattleAnimArgs[0]) + { + v1 = gBattleAnimBankAttacker; + } + else + { + v1 = gBattleAnimBankTarget; + } + spriteId = gObjectBankIDs[v1]; + if (GetBankSide(v1)) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + if (gBattleAnimArgs[3] == 1) + { + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + } + } + sprite->data0 = gBattleAnimArgs[4]; + sprite->data1 = gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x; + sprite->data2 = sprite->data1 + gBattleAnimArgs[1]; + sprite->data3 = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y; + sprite->data4 = sprite->data3 + gBattleAnimArgs[2]; + sub_8078A5C(sprite); + sprite->data3 = gSprites[spriteId].pos2.x << 8; + sprite->data4 = gSprites[spriteId].pos2.y << 8; + sprite->data5 = spriteId; + sprite->data6 = gBattleAnimArgs[5]; + if (!gBattleAnimArgs[5]) + { + StoreSpriteCallbackInData6(sprite, move_anim_8072740); + } + else + { + StoreSpriteCallbackInData6(sprite, sub_80A88F0); + } + sprite->callback = sub_80784A8; +} + + +static void sub_80A88F0(struct Sprite *sprite) +{ + gSprites[sprite->data5].pos2.x = 0; + gSprites[sprite->data5].pos2.y = 0; + move_anim_8072740(sprite); +} + +void sub_80A8920(u8 taskId) +{ + s16 r7; + r7 = 0x8000 / gBattleAnimArgs[3]; + if (GetBankSide(gBattleAnimBankAttacker)) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[5] = -gBattleAnimArgs[5]; + } + TASK.data[0] = GetAnimBankSpriteId(gBattleAnimArgs[0]); + TASK.data[1] = (gBattleAnimArgs[1] << 8) / gBattleAnimArgs[3]; + TASK.data[2] = gBattleAnimArgs[2]; + TASK.data[3] = gBattleAnimArgs[3]; + TASK.data[4] = gBattleAnimArgs[4]; + TASK.data[5] = (gBattleAnimArgs[5] << 8) / gBattleAnimArgs[6]; + TASK.data[6] = gBattleAnimArgs[6]; + TASK.data[7] = r7; + TASK.func = sub_80A89B4; +} + +static void sub_80A89B4(u8 taskId) +{ + u8 spriteId; + spriteId = TASK.data[0]; + TASK.data[11] += TASK.data[1]; + gSprites[spriteId].pos2.x = TASK.data[11] >> 8; + gSprites[spriteId].pos2.y = Sin((u8)(TASK.data[10] >> 8), TASK.data[2]); + TASK.data[10] += TASK.data[7]; + if (--TASK.data[3] == 0) + { + TASK.func = sub_80A8A18; + } +} + +static void sub_80A8A18(u8 taskId) +{ + u8 spriteId; + if (TASK.data[4] > 0) + { + TASK.data[4]--; + } + else + { + spriteId = TASK.data[0]; + TASK.data[12] += TASK.data[5]; + gSprites[spriteId].pos2.x = (TASK.data[12] >> 8) + (TASK.data[11] >> 8); + if (--TASK.data[6] == 0) + { + DestroyAnimVisualTask(taskId); + return; + } + } +} + +static void sub_80A8B3C(u8 taskId); + +void sub_80A8A80(u8 taskId) +{ + u8 spriteId; + switch (gBattleAnimArgs[0]) + { + case 0: + case 1: + spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]); + break; + case 2: + if (!IsAnimBankSpriteVisible(gBattleAnimBankAttacker ^ 2)) + { + DestroyAnimVisualTask(taskId); + return; + } + spriteId = gObjectBankIDs[gBattleAnimBankAttacker ^ 2]; + break; + case 3: + if (!IsAnimBankSpriteVisible(gBattleAnimBankTarget ^ 2)) + { + DestroyAnimVisualTask(taskId); + return; + } + spriteId = gObjectBankIDs[gBattleAnimBankTarget ^ 2]; + break; + default: + DestroyAnimVisualTask(taskId); + return; + } + TASK.data[0] = spriteId; + if (GetBankSide(gBattleAnimBankTarget)) + { + TASK.data[1] = gBattleAnimArgs[1]; + } + else + { + TASK.data[1] = -gBattleAnimArgs[1]; + } + TASK.func = sub_80A8B3C; +} + +static void sub_80A8B3C(u8 taskId) +{ + u8 spriteId = TASK.data[0]; + gSprites[spriteId].pos2.x += TASK.data[1]; + if (gSprites[spriteId].pos2.x + gSprites[spriteId].pos1.x + 0x20 > 0x130u) + { + DestroyAnimVisualTask(taskId); + return; + } +} + +void sub_80A8B88(u8 taskId) +{ + u8 spriteId; + if (GetBankSide(gBattleAnimBankAttacker)) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + } + spriteId = GetAnimBankSpriteId(gBattleAnimArgs[4]); + TASK.data[0] = gBattleAnimArgs[0]; + TASK.data[1] = gBattleAnimArgs[1]; + TASK.data[2] = gBattleAnimArgs[2]; + TASK.data[3] = gBattleAnimArgs[3]; + TASK.data[4] = spriteId; + if (gBattleAnimArgs[4] == 0) + { + TASK.data[5] = gBattleAnimBankAttacker; + } + else + { + TASK.data[5] = gBattleAnimBankTarget; + } + TASK.data[12] = 1; + TASK.func = sub_80A8C0C; +} + +static void sub_80A8C0C(u8 taskId) +{ + s16 y; + u8 spriteId; + int index; + u16 val; + spriteId = TASK.data[4]; + val = TASK.data[10] + TASK.data[2]; + TASK.data[10] = val; + index = val >> 8; + y = Sin(index, TASK.data[1]); + if (TASK.data[0] == 0) + { + gSprites[spriteId].pos2.x = y; + } + else + { + if (GetBankSide(TASK.data[5]) == 0) + { + gSprites[spriteId].pos2.y = (y >= 0) ? y : -y; + } + else + { + gSprites[spriteId].pos2.y = (y >= 0) ? -y : y; + } + } + if (((index >= 0x80u) && (TASK.data[11] == 0) && (TASK.data[12] == 1)) + || ((index < 0x7fu) && (TASK.data[11] == 1) && (TASK.data[12] == 0))) + { + TASK.data[11] ^= 1; + TASK.data[12] ^= 1; + if (--TASK.data[3] == 0) + { + gSprites[spriteId].pos2.x = 0; + gSprites[spriteId].pos2.y = 0; + DestroyAnimVisualTask(taskId); + return; + } + } +} + +void sub_80A8D34(u8 taskId) +{ + u8 spriteId; + spriteId = GetAnimBankSpriteId(gBattleAnimArgs[3]); + sub_8078E70(spriteId, gBattleAnimArgs[4]); + TASK.data[0] = gBattleAnimArgs[0]; + TASK.data[1] = gBattleAnimArgs[1]; + TASK.data[2] = gBattleAnimArgs[2]; + TASK.data[3] = gBattleAnimArgs[2]; + TASK.data[4] = spriteId; + TASK.data[10] = 0x100; + TASK.data[11] = 0x100; + TASK.func = sub_80A8D8C; +} + +static void sub_80A8D8C(u8 taskId) +{ + u8 spriteId; + TASK.data[10] += TASK.data[0]; + TASK.data[11] += TASK.data[1]; + spriteId = TASK.data[4]; + obj_id_set_rotscale(spriteId, TASK.data[10], TASK.data[11], 0); + if (--TASK.data[2] == 0) + { + if (TASK.data[3] > 0) + { + TASK.data[0] = -TASK.data[0]; + TASK.data[1] = -TASK.data[1]; + TASK.data[2] = TASK.data[3]; + TASK.data[3] = 0; + } + else + { + sub_8078F40(spriteId); + DestroyAnimVisualTask(taskId); + return; + } + } +} + +void sub_80A8E04(u8 taskId) +{ + u8 spriteId; + spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]); + sub_8078E70(spriteId, 0); + TASK.data[1] = 0; + TASK.data[2] = gBattleAnimArgs[0]; + if (gBattleAnimArgs[3] != 1) + { + TASK.data[3] = 0; + } + else + { + TASK.data[3] = gBattleAnimArgs[0] * gBattleAnimArgs[1]; + } + TASK.data[4] = gBattleAnimArgs[1]; + TASK.data[5] = spriteId; + TASK.data[6] = gBattleAnimArgs[3]; + if (IsContest()) + { + TASK.data[7] = 1; + } + else + { + if (gBattleAnimArgs[2] == 0) + { + TASK.data[7] = !GetBankSide(gBattleAnimBankAttacker); + } + else + { + TASK.data[7] = !GetBankSide(gBattleAnimBankTarget); + } + } + if (TASK.data[7]) + { + if (!IsContest()) + { + TASK.data[3] *= -1; + TASK.data[4] *= -1; + } + } + TASK.func = sub_80A8FD8; +} + +void sub_80A8EFC(u8 taskId) +{ + u8 spriteId; + spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]); + sub_8078E70(spriteId, 0); + TASK.data[1] = 0; + TASK.data[2] = gBattleAnimArgs[0]; + if (gBattleAnimArgs[2] == 0) + { + if (GetBankSide(gBattleAnimBankAttacker)) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + } + } + else + { + if (GetBankSide(gBattleAnimBankTarget)) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + } + } + if (gBattleAnimArgs[3] != 1) + { + TASK.data[3] = 0; + } + else + { + TASK.data[3] = gBattleAnimArgs[0] * gBattleAnimArgs[1]; + } + TASK.data[4] = gBattleAnimArgs[1]; + TASK.data[5] = spriteId; + TASK.data[6] = gBattleAnimArgs[3]; + TASK.data[7] = 1; + TASK.data[3] *= -1; + TASK.data[4] *= -1; + TASK.func = sub_80A8FD8; +} + +void sub_80A8FD8(u8 taskId) +{ + TASK.data[3] += TASK.data[4]; + obj_id_set_rotscale(TASK.data[5], 0x100, 0x100, TASK.data[3]); + if (TASK.data[7]) + { + sub_8078F9C(TASK.data[5]); + } + if (++TASK.data[1] >= TASK.data[2]) + { + switch (TASK.data[6]) + { + case 1: + sub_8078F40(TASK.data[5]); + case 0: + default: + DestroyAnimVisualTask(taskId); + return; + case 2: + TASK.data[1] = 0; + TASK.data[4] *= -1; + TASK.data[6] = 1; + break; + } + } +} + +void sub_80A9058(u8 taskId) +{ + if (!gBattleAnimArgs[0]) + { + TASK.data[15] = gMovePowerMoveAnim / 12; + if (TASK.data[15] < 1) + { + TASK.data[15] = 1; + } + if (TASK.data[15] > 16) + { + TASK.data[15] = 16; + } + } + else + { + TASK.data[15] = gMoveDmgMoveAnim / 12; + if (TASK.data[15] < 1) + { + TASK.data[15] = 1; + } + if (TASK.data[15] > 16) + { + TASK.data[15] = 16; + } + } + TASK.data[14] = TASK.data[15] / 2; + TASK.data[13] = TASK.data[14] + (TASK.data[15] & 1); + TASK.data[12] = 0; + TASK.data[10] = gBattleAnimArgs[3]; + TASK.data[11] = gBattleAnimArgs[4]; + TASK.data[7] = GetAnimBankSpriteId(1); + TASK.data[8] = gSprites[TASK.data[7]].pos2.x; + TASK.data[9] = gSprites[TASK.data[7]].pos2.y; + TASK.data[0] = 0; + TASK.data[1] = gBattleAnimArgs[1]; + TASK.data[2] = gBattleAnimArgs[2]; + TASK.func = sub_80A913C; +} + +static void sub_80A913C(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + if (++task->data[0] > task->data[1]) + { + task->data[0] = 0; + task->data[12] = (task->data[12] + 1) & 1; + if (task->data[10]) + { + if (task->data[12]) + { + gSprites[task->data[7]].pos2.x = task->data[8] + task->data[13]; + } + else + { + gSprites[task->data[7]].pos2.x = task->data[8] - task->data[14]; + } + } + if (task->data[11]) + { + if (task->data[12]) + { + gSprites[task->data[7]].pos2.y = task->data[15]; + } + else + { + gSprites[task->data[7]].pos2.y = 0; + } + } + if (!--task->data[2]) + { + gSprites[task->data[7]].pos2.x = 0; + gSprites[task->data[7]].pos2.y = 0; + DestroyAnimVisualTask(taskId); + return; + } + } +} diff --git a/src/battle/battle_anim_80CA710.c b/src/battle/battle_anim_80CA710.c new file mode 100644 index 000000000..65ccd7c21 --- /dev/null +++ b/src/battle/battle_anim_80CA710.c @@ -0,0 +1,18 @@ + +// Includes +#include "global.h" + +// Static type declarations + +// Static RAM declarations + +IWRAM_DATA u32 filler_03000724; +IWRAM_DATA u16 gUnknown_03000728[4]; +IWRAM_DATA u16 gUnknown_03000730[6]; +IWRAM_DATA u32 filler_0300073c; + +// Static ROM declarations + +// .rodata + +// .text diff --git a/src/battle/battle_anim_81258BC.c b/src/battle/battle_anim_81258BC.c new file mode 100644 index 000000000..5bdbb4946 --- /dev/null +++ b/src/battle/battle_anim_81258BC.c @@ -0,0 +1,50 @@ +#include "global.h" +#include "battle_anim_81258BC.h" +#include "battle.h" +#include "battle_message.h" +#include "menu_cursor.h" +#include "text.h" + +extern struct Window gUnknown_03004210; +extern u8 gDisplayedStringBattle[]; +extern u8 gActionSelectionCursor[]; + +extern const u8 gUnknown_08400CBB[]; +extern u8 gActiveBank; +extern const u8 gUnknown_08400D15[]; + +extern void *gBattleBankFunc[]; +extern u16 gUnknown_030042A0; +extern u16 gUnknown_030042A4; + +#if ENGLISH +#define SUB_812BB10_TILE_DATA_OFFSET 440 +#elif GERMAN +#define SUB_812BB10_TILE_DATA_OFFSET 444 +#endif + +void sub_812BB10(void) { + int i; + + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 160; + gUnknown_03004210.paletteNum = 0; + FillWindowRect_DefaultPalette(&gUnknown_03004210, 10, 2, 15, 27, 18); + FillWindowRect_DefaultPalette(&gUnknown_03004210, 10, 2, 35, 16, 36); + gBattleBankFunc[gActiveBank] = bx_battle_menu_t6_2; + + InitWindow(&gUnknown_03004210, gUnknown_08400D15, 400, 18, 35); + sub_8002F44(&gUnknown_03004210); + sub_814A5C0(0, 0xFFFF, 12, 11679, 0); + + for (i = 0; i < 4; i++) + { + nullsub_8(i); + } + + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + StrCpyDecodeToDisplayedStringBattle((u8 *) gUnknown_08400CBB); + + InitWindow(&gUnknown_03004210, gDisplayedStringBattle, SUB_812BB10_TILE_DATA_OFFSET, 2, 35); + sub_8002F44(&gUnknown_03004210); +}
\ No newline at end of file diff --git a/src/battle/battle_controller_linkopponent.c b/src/battle/battle_controller_linkopponent.c new file mode 100644 index 000000000..0b6c3b6a1 --- /dev/null +++ b/src/battle/battle_controller_linkopponent.c @@ -0,0 +1,1782 @@ +#include "global.h" +#include "battle.h" +#include "battle_interface.h" +#include "data2.h" +#include "link.h" +#include "m4a.h" +#include "main.h" +#include "palette.h" +#include "rom_8077ABC.h" +#include "rom3.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "util.h" + +struct UnknownStruct3 +{ + u16 moves[4]; + u8 pp[4]; + u8 ppBonuses; +}; + +extern u8 gActiveBank; +extern u8 gBattleBufferA[][0x200]; +extern u8 gObjectBankIDs[]; +extern u16 gBattlePartyID[]; +extern u8 gHealthboxIDs[]; +extern u16 gBattleTypeFlags; +extern u8 gBattleMonForms[]; +extern void (*gBattleBankFunc[])(void); +extern u32 *gDisableStructMoveAnim; +extern u32 gMoveDmgMoveAnim; +extern u16 gMovePowerMoveAnim; +extern u8 gHappinessMoveAnim; +extern u16 gWeatherMoveAnim; +extern u32 gPID_perBank[]; +extern u8 gAnimScriptActive; +extern void (*gAnimScriptCallback)(void); +extern u8 gDisplayedStringBattle[]; +extern bool8 gDoingBattleAnim; +extern u8 gBattleOutcome; +extern u16 gUnknown_02024DE8; +extern u8 gUnknown_02024E68[]; +extern struct SpriteTemplate gUnknown_02024E8C; +extern u8 gUnknown_0202F7C4; +extern struct Window gUnknown_03004210; +extern u16 gUnknown_030042A0; +extern u16 gUnknown_030042A4; +extern u8 gUnknown_0300434C[]; +extern u32 gBattleExecBuffer; +extern MainCallback gPreBattleCallback1; +extern struct MusicPlayerInfo gMPlay_BGM; + +extern u8 sub_8077F68(); +extern u8 sub_8079E90(); +extern u8 GetBankIdentity(u8); +extern void BattleLoadOpponentMonSprite(struct Pokemon *, u8); +extern void sub_8037A74(void); +extern void sub_8032984(u8, u16); +extern void sub_8037E30(void); +extern void sub_80312F0(struct Sprite *); +extern u8 sub_8046400(); +extern void sub_8032A08(); +extern void sub_8043DB0(); +extern void sub_8037BBC(void); +extern s32 sub_803FC34(u16); +extern void sub_8031A6C(u16, u8); +extern void sub_80313A0(struct Sprite *); +extern void sub_803757C(void); +extern void oamt_add_pos2_onto_pos1(); +extern void StoreSpriteCallbackInData6(); +extern void sub_8078B34(struct Sprite *); +extern void sub_80375B4(void); +extern void sub_8010384(struct Sprite *); +extern void sub_8037B78(void); +extern u8 sub_8031720(); +extern bool8 mplay_80342A4(u8); +extern void ExecuteMoveAnim(); +extern void sub_80326EC(); +extern void sub_8031F24(void); +extern void sub_80324BC(); +extern void BufferStringBattle(); +extern void sub_8037C2C(void); +extern void sub_8043D84(); +extern void sub_8037B24(void); +extern void sub_8045A5C(); +extern void sub_8037FAC(void); +extern void move_anim_start_t2_for_situation(); +extern void dp01t_0F_4_move_anim(void); +extern void sub_8047858(); +extern u8 GetBankSide(u8); +extern void sub_80E43C0(); +extern void sub_803A3A8(struct Sprite *); +extern void sub_8044CA0(u8); +extern void nullsub_47(void); +extern bool8 IsDoubleBattle(void); +extern void sub_8037840(void); +extern void sub_8031B74(); +extern u8 AnimBankSpriteExists(); +extern u8 move_anim_start_t3(); +extern void sub_8037FD8(void); +extern void sub_8037F34(void); +extern void LinkOpponentBufferExecCompleted(void); +extern void sub_8141828(); +extern void sub_804777C(); + +// this file's functions + +u32 dp01_getattr_by_ch1_for_player_pokemon__(u8, u8 *); +void sub_803752C(void); +void sub_8037D2C(void); +void sub_8038900(u8); +void sub_8039430(u8, u8); +void sub_8039648(void); +void sub_8039B64(void); +void sub_803A2C4(u8); +void sub_803A4E0(void); + +void LinkOpponentHandleGetAttributes(void); +void LinkOpponentHandlecmd1(void); +void LinkOpponentHandleSetAttributes(void); +void LinkOpponentHandlecmd3(void); +void LinkOpponentHandleLoadPokeSprite(void); +void LinkOpponentHandleSendOutPoke(void); +void LinkOpponentHandleReturnPokeToBall(void); +void LinkOpponentHandleTrainerThrow(void); +void LinkOpponentHandleTrainerSlide(void); +void LinkOpponentHandleTrainerSlideBack(void); +void LinkOpponentHandlecmd10(void); +void LinkOpponentHandlecmd11(void); +void LinkOpponentHandlecmd12(void); +void LinkOpponentHandleBallThrow(void); +void LinkOpponentHandlePuase(void); +void LinkOpponentHandleMoveAnimation(void); +void LinkOpponentHandlePrintString(void); +void LinkOpponentHandlePrintStringPlayerOnly(void); +void LinkOpponentHandlecmd18(void); +void LinkOpponentHandlecmd19(void); +void LinkOpponentHandlecmd20(void); +void LinkOpponentHandleOpenBag(void); +void LinkOpponentHandlecmd22(void); +void LinkOpponentHandlecmd23(void); +void LinkOpponentHandleHealthBarUpdate(void); +void LinkOpponentHandleExpBarUpdate(void); +void LinkOpponentHandleStatusIconUpdate(void); +void LinkOpponentHandleStatusAnimation(void); +void LinkOpponentHandleStatusXor(void); +void LinkOpponentHandlecmd29(void); +void LinkOpponentHandleDMATransfer(void); +void LinkOpponentHandlecmd31(void); +void LinkOpponentHandlecmd32(void); +void LinkOpponentHandlecmd33(void); +void LinkOpponentHandlecmd34(void); +void LinkOpponentHandlecmd35(void); +void LinkOpponentHandlecmd36(void); +void LinkOpponentHandlecmd37(void); +void LinkOpponentHandlecmd38(void); +void LinkOpponentHandlecmd39(void); +void LinkOpponentHandlecmd40(void); +void LinkOpponentHandleHitAnimation(void); +void LinkOpponentHandlecmd42(void); +void LinkOpponentHandleEffectivenessSound(void); +void LinkOpponentHandlecmd44(void); +void LinkOpponentHandleFaintingCry(void); +void LinkOpponentHandleIntroSlide(void); +void LinkOpponentHandleTrainerBallThrow(void); +void LinkOpponentHandlecmd48(void); +void LinkOpponentHandlecmd49(void); +void LinkOpponentHandlecmd50(void); +void LinkOpponentHandleSpriteInvisibility(void); +void LinkOpponentHandleBattleAnimation(void); +void LinkOpponentHandleLinkStandbyMsg(void); +void LinkOpponentHandleResetActionMoveSelection(void); +void LinkOpponentHandlecmd55(void); +void LinkOpponentHandlecmd56(void); + +// const data + +typedef void (*BattleBufferCmd) (void); +const BattleBufferCmd gLinkOpponentBufferCommands[] = +{ + LinkOpponentHandleGetAttributes, + LinkOpponentHandlecmd1, + LinkOpponentHandleSetAttributes, + LinkOpponentHandlecmd3, + LinkOpponentHandleLoadPokeSprite, + LinkOpponentHandleSendOutPoke, + LinkOpponentHandleReturnPokeToBall, + LinkOpponentHandleTrainerThrow, + LinkOpponentHandleTrainerSlide, + LinkOpponentHandleTrainerSlideBack, + LinkOpponentHandlecmd10, + LinkOpponentHandlecmd11, + LinkOpponentHandlecmd12, + LinkOpponentHandleBallThrow, + LinkOpponentHandlePuase, + LinkOpponentHandleMoveAnimation, + LinkOpponentHandlePrintString, + LinkOpponentHandlePrintStringPlayerOnly, + LinkOpponentHandlecmd18, + LinkOpponentHandlecmd19, + LinkOpponentHandlecmd20, + LinkOpponentHandleOpenBag, + LinkOpponentHandlecmd22, + LinkOpponentHandlecmd23, + LinkOpponentHandleHealthBarUpdate, + LinkOpponentHandleExpBarUpdate, + LinkOpponentHandleStatusIconUpdate, + LinkOpponentHandleStatusAnimation, + LinkOpponentHandleStatusXor, + LinkOpponentHandlecmd29, + LinkOpponentHandleDMATransfer, + LinkOpponentHandlecmd31, + LinkOpponentHandlecmd32, + LinkOpponentHandlecmd33, + LinkOpponentHandlecmd34, + LinkOpponentHandlecmd35, + LinkOpponentHandlecmd36, + LinkOpponentHandlecmd37, + LinkOpponentHandlecmd38, + LinkOpponentHandlecmd39, + LinkOpponentHandlecmd40, + LinkOpponentHandleHitAnimation, + LinkOpponentHandlecmd42, + LinkOpponentHandleEffectivenessSound, + LinkOpponentHandlecmd44, + LinkOpponentHandleFaintingCry, + LinkOpponentHandleIntroSlide, + LinkOpponentHandleTrainerBallThrow, + LinkOpponentHandlecmd48, + LinkOpponentHandlecmd49, + LinkOpponentHandlecmd50, + LinkOpponentHandleSpriteInvisibility, + LinkOpponentHandleBattleAnimation, + LinkOpponentHandleLinkStandbyMsg, + LinkOpponentHandleResetActionMoveSelection, + LinkOpponentHandlecmd55, + LinkOpponentHandlecmd56 +}; + +// code + +void nullsub_47(void) +{ +} + +void SetBankFuncToLinkOpponentBufferRunCommand(void) +{ + gBattleBankFunc[gActiveBank] = sub_803752C; +} + +void sub_803752C(void) +{ + if (gBattleExecBuffer & gBitTable[gActiveBank]) + { + if (gBattleBufferA[gActiveBank][0] <= 0x38) + gLinkOpponentBufferCommands[gBattleBufferA[gActiveBank][0]](); + else + LinkOpponentBufferExecCompleted(); + } +} + +void sub_803757C(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + LinkOpponentBufferExecCompleted(); +} + +void sub_80375B4(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + { + sub_8031B74(gSprites[gObjectBankIDs[gActiveBank]].oam.affineParam); + gSprites[gObjectBankIDs[gActiveBank]].oam.tileNum = gSprites[gObjectBankIDs[gActiveBank]].data5; + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + LinkOpponentBufferExecCompleted(); + } +} + +void sub_8037644(void) +{ + if ((--ewram17810[gActiveBank].unk9) == 0xFF) + { + ewram17810[gActiveBank].unk9 = 0; + LinkOpponentBufferExecCompleted(); + } +} + +void sub_8037680(void) +{ + bool8 r6 = FALSE; + + if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + { + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy) + r6 = TRUE; + } + else + { + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy + && gSprites[gHealthboxIDs[gActiveBank ^ 2]].callback == SpriteCallbackDummy) + r6 = TRUE; + } + if (IsCryPlayingOrClearCrySongs()) + r6 = FALSE; + + if (r6) + { + if (GetBankIdentity(gActiveBank) == 1) + { + if (!ewram17810[gActiveBank].unk1_0 || !ewram17810[gActiveBank ^ 2].unk1_0) + return; + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + ewram17810[gActiveBank ^ 2].unk0_7 = 0; + ewram17810[gActiveBank ^ 2].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + } + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (GetBankIdentity(gActiveBank) == 1) + m4aMPlayContinue(&gMPlay_BGM); + } + else + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 256); + } + ewram17810[gActiveBank].unk9 = 3; + gBattleBankFunc[gActiveBank] = sub_8037644; + } +} + +void sub_8037840(void) +{ + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank].unk0_7) + sub_8141828(gActiveBank, &gEnemyParty[gBattlePartyID[gActiveBank]]); + if (!ewram17810[gActiveBank ^ 2].unk0_3 && !ewram17810[gActiveBank ^ 2].unk0_7) + sub_8141828(gActiveBank ^ 2, &gEnemyParty[gBattlePartyID[gActiveBank ^ 2]]); + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank ^ 2].unk0_3) + { + if ((gBattleTypeFlags & BATTLE_TYPE_MULTI) && GetBankIdentity(gActiveBank) == 3) + { + if (++ewram17810[gActiveBank].unk9 == 1) + return; + ewram17810[gActiveBank].unk9 = 0; + } + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank ^ 2]]); + sub_8045A5C( + gHealthboxIDs[gActiveBank ^ 2], + &gEnemyParty[gBattlePartyID[gActiveBank ^ 2]], + 0); + sub_804777C(gActiveBank ^ 2); + sub_8043DFC(gHealthboxIDs[gActiveBank ^ 2]); + sub_8032984( + gActiveBank ^ 2, + GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank ^ 2]], MON_DATA_SPECIES)); + } + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + sub_8045A5C( + gHealthboxIDs[gActiveBank], + &gEnemyParty[gBattlePartyID[gActiveBank]], + 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + sub_8032984( + gActiveBank, + GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES)); + + ewram17840.unk9_0 = 0; + gBattleBankFunc[gActiveBank] = sub_8037680; + } +} + +void sub_8037A74(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].animEnded == TRUE + && gSprites[gObjectBankIDs[gActiveBank]].pos2.x == 0) + { + if (!ewram17810[gActiveBank].unk0_7) + { + sub_8141828(gActiveBank, &gEnemyParty[gBattlePartyID[gActiveBank]]); + return; + } + if (ewram17810[gActiveBank].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + LinkOpponentBufferExecCompleted(); + return; + } + } +} + +void sub_8037B24(void) +{ + s16 r4 = sub_8045C78(gActiveBank, gHealthboxIDs[gActiveBank], 0, 0); + + sub_8043DFC(gHealthboxIDs[gActiveBank]); + if (r4 != -1) + sub_80440EC(gHealthboxIDs[gActiveBank], r4, 0); + else + LinkOpponentBufferExecCompleted(); +} + +void sub_8037B78(void) +{ + if (!gSprites[gObjectBankIDs[gActiveBank]].inUse) + { + sub_8043DB0(gHealthboxIDs[gActiveBank]); + LinkOpponentBufferExecCompleted(); + } +} + +void sub_8037BBC(void) +{ + if (!ewram17810[gActiveBank].unk0_6) + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8032A08(gActiveBank); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + LinkOpponentBufferExecCompleted(); + } +} + +void sub_8037C2C(void) +{ + if (gUnknown_03004210.state == 0) + LinkOpponentBufferExecCompleted(); +} + +void dp01t_0F_4_move_anim(void) +{ + u8 spriteId = gObjectBankIDs[gActiveBank]; + + if (gSprites[spriteId].data1 == 32) + { + gSprites[spriteId].data1 = 0; + gSprites[spriteId].invisible = FALSE; + gDoingBattleAnim = 0; + LinkOpponentBufferExecCompleted(); + } + else + { + if (((u16)gSprites[spriteId].data1 % 4) == 0) + gSprites[spriteId].invisible ^= 1; + gSprites[spriteId].data1++; + } +} + +void sub_8037CC0(void) +{ + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy) + { + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + gBattleBankFunc[gActiveBank] = sub_8037D2C; + } +} + +void sub_8037D2C(void) +{ + if (!ewram17810[gActiveBank].unk0_6) + { + CreateTask(c3_0802FDF4, 10); + LinkOpponentBufferExecCompleted(); + } +} + +void sub_8037D64(void) +{ + if (ewram17810[gActiveBank].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], 0); + sub_8045A5C( + gHealthboxIDs[gActiveBank], + &gEnemyParty[gBattlePartyID[gActiveBank]], + 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + sub_8031F88(gActiveBank); + gBattleBankFunc[gActiveBank] = sub_8037CC0; + } +} + +void sub_8037E30(void) +{ + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank].unk0_7) + sub_8141828(gActiveBank, &gEnemyParty[gBattlePartyID[gActiveBank]]); + if (gSprites[gUnknown_0300434C[gActiveBank]].callback == SpriteCallbackDummy + && !ewram17810[gActiveBank].unk0_3) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + sub_8032984(gActiveBank, GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES)); + gBattleBankFunc[gActiveBank] = sub_8037D64; + } +} + +void sub_8037EF0(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + m4aSongNumStop(SE_HINSI); + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(c2_8011A1C); + } +} + +void sub_8037F34(void) +{ + if (!gPaletteFade.active) + { + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + sub_800832C(); + gBattleBankFunc[gActiveBank] = sub_8037EF0; + } + else + { + m4aSongNumStop(SE_HINSI); + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } + } +} + +void sub_8037FAC(void) +{ + if (!ewram17810[gActiveBank].unk0_4) + LinkOpponentBufferExecCompleted(); +} + +void sub_8037FD8(void) +{ + if (!ewram17810[gActiveBank].unk0_5) + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentBufferExecCompleted(void) +{ + gBattleBankFunc[gActiveBank] = sub_803752C; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + u8 playerId = GetMultiplayerId(); + + PrepareBufferDataTransferLink(2, 4, &playerId); + gBattleBufferA[gActiveBank][0] = 0x38; + } + else + { + gBattleExecBuffer &= ~gBitTable[gActiveBank]; + } +} + +void LinkOpponentHandleGetAttributes(void) +{ + u8 buffer[0x100]; + u32 r6 = 0; + u8 r4; + s32 i; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + r6 = dp01_getattr_by_ch1_for_player_pokemon__(gBattlePartyID[gActiveBank], buffer); + } + else + { + r4 = gBattleBufferA[gActiveBank][2]; + for (i = 0; i < 6; i++) + { + if (r4 & 1) + r6 += dp01_getattr_by_ch1_for_player_pokemon__(i, buffer + r6); + r4 >>= 1; + } + } + Emitcmd29(1, r6, buffer); + LinkOpponentBufferExecCompleted(); +} + +u32 dp01_getattr_by_ch1_for_player_pokemon__(u8 a, u8 *buffer) +{ + struct BattlePokemon battlePokemon; + struct UnknownStruct3 moveData; + u8 nickname[20]; + u8 *src; + s16 data16; + u32 data32; + s32 size = 0; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + battlePokemon.species = GetMonData(&gEnemyParty[a], MON_DATA_SPECIES); + battlePokemon.item = GetMonData(&gEnemyParty[a], MON_DATA_HELD_ITEM); + for (size = 0; size < 4; size++) + { + battlePokemon.moves[size] = GetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + size); + battlePokemon.pp[size] = GetMonData(&gEnemyParty[a], MON_DATA_PP1 + size); + } + battlePokemon.ppBonuses = GetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES); + battlePokemon.friendship = GetMonData(&gEnemyParty[a], MON_DATA_FRIENDSHIP); + battlePokemon.experience = GetMonData(&gEnemyParty[a], MON_DATA_EXP); + battlePokemon.hpIV = GetMonData(&gEnemyParty[a], MON_DATA_HP_IV); + battlePokemon.attackIV = GetMonData(&gEnemyParty[a], MON_DATA_ATK_IV); + battlePokemon.defenseIV = GetMonData(&gEnemyParty[a], MON_DATA_DEF_IV); + battlePokemon.speedIV = GetMonData(&gEnemyParty[a], MON_DATA_SPD_IV); + battlePokemon.spAttackIV = GetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV); + battlePokemon.spDefenseIV = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV); + battlePokemon.personality = GetMonData(&gEnemyParty[a], MON_DATA_PERSONALITY); + battlePokemon.status1 = GetMonData(&gEnemyParty[a], MON_DATA_STATUS); + battlePokemon.level = GetMonData(&gEnemyParty[a], MON_DATA_LEVEL); + battlePokemon.hp = GetMonData(&gEnemyParty[a], MON_DATA_HP); + battlePokemon.maxHP = GetMonData(&gEnemyParty[a], MON_DATA_MAX_HP); + battlePokemon.attack = GetMonData(&gEnemyParty[a], MON_DATA_ATK); + battlePokemon.defense = GetMonData(&gEnemyParty[a], MON_DATA_DEF); + battlePokemon.speed = GetMonData(&gEnemyParty[a], MON_DATA_SPD); + battlePokemon.spAttack = GetMonData(&gEnemyParty[a], MON_DATA_SPATK); + battlePokemon.spDefense = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF); + battlePokemon.isEgg = GetMonData(&gEnemyParty[a], MON_DATA_IS_EGG); + battlePokemon.altAbility = GetMonData(&gEnemyParty[a], MON_DATA_ALT_ABILITY); + battlePokemon.otId = GetMonData(&gEnemyParty[a], MON_DATA_OT_ID); + GetMonData(&gEnemyParty[a], MON_DATA_NICKNAME, nickname); + StringCopy10(battlePokemon.nickname, nickname); + GetMonData(&gEnemyParty[a], MON_DATA_OT_NAME, battlePokemon.otName); + src = (u8 *)&battlePokemon; + for (size = 0; size < sizeof(battlePokemon); size++) + buffer[size] = src[size]; + break; + case 1: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_SPECIES); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 2: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_HELD_ITEM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 3: + for (size = 0; size < 4; size++) + { + moveData.moves[size] = GetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + size); + moveData.pp[size] = GetMonData(&gEnemyParty[a], MON_DATA_PP1 + size); + } + moveData.ppBonuses = GetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES); + src = (u8 *)&moveData; + for (size = 0; size < sizeof(moveData); size++) + buffer[size] = src[size]; + break; + case 4: + case 5: + case 6: + case 7: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 8: + for (size = 0; size < 4; size++) + buffer[size] = GetMonData(&gEnemyParty[a], MON_DATA_PP1 + size); + buffer[size] = GetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES); + size++; + break; + case 9: + case 10: + case 11: + case 12: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9); + size = 1; + break; + case 17: + data32 = GetMonData(&gEnemyParty[a], MON_DATA_OT_ID); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 18: + data32 = GetMonData(&gEnemyParty[a], MON_DATA_EXP); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 19: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_HP_EV); + size = 1; + break; + case 20: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_ATK_EV); + size = 1; + break; + case 21: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_DEF_EV); + size = 1; + break; + case 22: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPD_EV); + size = 1; + break; + case 23: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPATK_EV); + size = 1; + break; + case 24: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF_EV); + size = 1; + break; + case 25: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_FRIENDSHIP); + size = 1; + break; + case 26: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_POKERUS); + size = 1; + break; + case 27: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_MET_LOCATION); + size = 1; + break; + case 28: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_MET_LEVEL); + size = 1; + break; + case 29: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_MET_GAME); + size = 1; + break; + case 30: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_POKEBALL); + size = 1; + break; + case 31: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_HP_IV); + buffer[1] = GetMonData(&gEnemyParty[a], MON_DATA_ATK_IV); + buffer[2] = GetMonData(&gEnemyParty[a], MON_DATA_DEF_IV); + buffer[3] = GetMonData(&gEnemyParty[a], MON_DATA_SPD_IV); + buffer[4] = GetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV); + buffer[5] = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV); + size = 6; + break; + case 32: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_HP_IV); + size = 1; + break; + case 33: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_ATK_IV); + size = 1; + break; + case 34: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_DEF_IV); + size = 1; + break; + case 35: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPD_IV); + size = 1; + break; + case 36: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV); + size = 1; + break; + case 37: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV); + size = 1; + break; + case 38: + data32 = GetMonData(&gEnemyParty[a], MON_DATA_PERSONALITY); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 39: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_CHECKSUM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 40: + data32 = GetMonData(&gEnemyParty[a], MON_DATA_STATUS); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 41: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_LEVEL); + size = 1; + break; + case 42: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 43: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_MAX_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 44: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_ATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 45: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_DEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 46: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_SPD); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 47: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_SPATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 48: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 49: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_COOL); + size = 1; + break; + case 50: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_BEAUTY); + size = 1; + break; + case 51: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_CUTE); + size = 1; + break; + case 52: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SMART); + size = 1; + break; + case 53: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_TOUGH); + size = 1; + break; + case 54: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SHEEN); + size = 1; + break; + case 55: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_COOL_RIBBON); + size = 1; + break; + case 56: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_BEAUTY_RIBBON); + size = 1; + break; + case 57: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_CUTE_RIBBON); + size = 1; + break; + case 58: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SMART_RIBBON); + size = 1; + break; + case 59: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_TOUGH_RIBBON); + size = 1; + break; + } + return size; +} + +void LinkOpponentHandlecmd1(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleSetAttributes(void) +{ + u8 i; + u8 r4; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + sub_8038900(gBattlePartyID[gActiveBank]); + } + else + { + r4 = gBattleBufferA[gActiveBank][2]; + for (i = 0; i < 6; i++) + { + if (r4 & 1) + sub_8038900(i); + r4 >>= 1; + } + } + LinkOpponentBufferExecCompleted(); +} + +void sub_8038900(u8 a) +{ + struct BattlePokemon *battlePokemon = (struct BattlePokemon *)&gBattleBufferA[gActiveBank][3]; + struct UnknownStruct3 *moveData = (struct UnknownStruct3 *)&gBattleBufferA[gActiveBank][3]; + s32 i; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + { + u8 iv; + + SetMonData(&gEnemyParty[a], MON_DATA_SPECIES, (u8 *)&battlePokemon->species); + SetMonData(&gEnemyParty[a], MON_DATA_HELD_ITEM, (u8 *)&battlePokemon->item); + for (i = 0; i < 4; i++) + { + SetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + i, (u8 *)&battlePokemon->moves[i]); + SetMonData(&gEnemyParty[a], MON_DATA_PP1 + i, (u8 *)&battlePokemon->pp[i]); + } + SetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES, (u8 *)&battlePokemon->ppBonuses); + SetMonData(&gEnemyParty[a], MON_DATA_FRIENDSHIP, (u8 *)&battlePokemon->friendship); + SetMonData(&gEnemyParty[a], MON_DATA_EXP, (u8 *)&battlePokemon->experience); + iv = battlePokemon->hpIV; + SetMonData(&gEnemyParty[a], MON_DATA_HP_IV, (u8 *)&iv); + iv = battlePokemon->attackIV; + SetMonData(&gEnemyParty[a], MON_DATA_ATK_IV, (u8 *)&iv); + iv = battlePokemon->defenseIV; + SetMonData(&gEnemyParty[a], MON_DATA_DEF_IV, (u8 *)&iv); + iv = battlePokemon->speedIV; + SetMonData(&gEnemyParty[a], MON_DATA_SPD_IV, (u8 *)&iv); + iv = battlePokemon->spAttackIV; + SetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV, (u8 *)&iv); + iv = battlePokemon->spDefenseIV; + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV, (u8 *)&iv); + SetMonData(&gEnemyParty[a], MON_DATA_PERSONALITY, (u8 *)&battlePokemon->personality); + SetMonData(&gEnemyParty[a], MON_DATA_STATUS, (u8 *)&battlePokemon->status1); + SetMonData(&gEnemyParty[a], MON_DATA_LEVEL, (u8 *)&battlePokemon->level); + SetMonData(&gEnemyParty[a], MON_DATA_HP, (u8 *)&battlePokemon->hp); + SetMonData(&gEnemyParty[a], MON_DATA_MAX_HP, (u8 *)&battlePokemon->maxHP); + SetMonData(&gEnemyParty[a], MON_DATA_ATK, (u8 *)&battlePokemon->attack); + SetMonData(&gEnemyParty[a], MON_DATA_DEF, (u8 *)&battlePokemon->defense); + SetMonData(&gEnemyParty[a], MON_DATA_SPD, (u8 *)&battlePokemon->speed); + SetMonData(&gEnemyParty[a], MON_DATA_SPATK, (u8 *)&battlePokemon->spAttack); + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF, (u8 *)&battlePokemon->spDefense); + } + break; + case 1: + SetMonData(&gEnemyParty[a], MON_DATA_SPECIES, &gBattleBufferA[gActiveBank][3]); + break; + case 2: + SetMonData(&gEnemyParty[a], MON_DATA_HELD_ITEM, &gBattleBufferA[gActiveBank][3]); + break; + case 3: + for (i = 0; i < 4; i++) + { + SetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + i, (u8 *)&moveData->moves[i]); + SetMonData(&gEnemyParty[a], MON_DATA_PP1 + i, (u8 *)&moveData->pp[i]); + } + SetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES, &moveData->ppBonuses); + break; + case 4: + case 5: + case 6: + case 7: + SetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4, &gBattleBufferA[gActiveBank][3]); + break; + case 8: + SetMonData(&gEnemyParty[a], MON_DATA_PP1, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gEnemyParty[a], MON_DATA_PP2, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gEnemyParty[a], MON_DATA_PP3, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gEnemyParty[a], MON_DATA_PP4, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES, &gBattleBufferA[gActiveBank][7]); + break; + case 9: + case 10: + case 11: + case 12: + SetMonData(&gEnemyParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9, &gBattleBufferA[gActiveBank][3]); + break; + case 17: + SetMonData(&gEnemyParty[a], MON_DATA_OT_ID, &gBattleBufferA[gActiveBank][3]); + break; + case 18: + SetMonData(&gEnemyParty[a], MON_DATA_EXP, &gBattleBufferA[gActiveBank][3]); + break; + case 19: + SetMonData(&gEnemyParty[a], MON_DATA_HP_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 20: + SetMonData(&gEnemyParty[a], MON_DATA_ATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 21: + SetMonData(&gEnemyParty[a], MON_DATA_DEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 22: + SetMonData(&gEnemyParty[a], MON_DATA_SPD_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 23: + SetMonData(&gEnemyParty[a], MON_DATA_SPATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 24: + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 25: + SetMonData(&gEnemyParty[a], MON_DATA_FRIENDSHIP, &gBattleBufferA[gActiveBank][3]); + break; + case 26: + SetMonData(&gEnemyParty[a], MON_DATA_POKERUS, &gBattleBufferA[gActiveBank][3]); + break; + case 27: + SetMonData(&gEnemyParty[a], MON_DATA_MET_LOCATION, &gBattleBufferA[gActiveBank][3]); + break; + case 28: + SetMonData(&gEnemyParty[a], MON_DATA_MET_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 29: + SetMonData(&gEnemyParty[a], MON_DATA_MET_GAME, &gBattleBufferA[gActiveBank][3]); + break; + case 30: + SetMonData(&gEnemyParty[a], MON_DATA_POKEBALL, &gBattleBufferA[gActiveBank][3]); + break; + case 31: + SetMonData(&gEnemyParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gEnemyParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gEnemyParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gEnemyParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][7]); + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][8]); + break; + case 32: + SetMonData(&gEnemyParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 33: + SetMonData(&gEnemyParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 34: + SetMonData(&gEnemyParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 35: + SetMonData(&gEnemyParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 36: + SetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 37: + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 38: + SetMonData(&gEnemyParty[a], MON_DATA_PERSONALITY, &gBattleBufferA[gActiveBank][3]); + break; + case 39: + SetMonData(&gEnemyParty[a], MON_DATA_CHECKSUM, &gBattleBufferA[gActiveBank][3]); + break; + case 40: + SetMonData(&gEnemyParty[a], MON_DATA_STATUS, &gBattleBufferA[gActiveBank][3]); + break; + case 41: + SetMonData(&gEnemyParty[a], MON_DATA_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 42: + SetMonData(&gEnemyParty[a], MON_DATA_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 43: + SetMonData(&gEnemyParty[a], MON_DATA_MAX_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 44: + SetMonData(&gEnemyParty[a], MON_DATA_ATK, &gBattleBufferA[gActiveBank][3]); + break; + case 45: + SetMonData(&gEnemyParty[a], MON_DATA_DEF, &gBattleBufferA[gActiveBank][3]); + break; + case 46: + SetMonData(&gEnemyParty[a], MON_DATA_SPD, &gBattleBufferA[gActiveBank][3]); + break; + case 47: + SetMonData(&gEnemyParty[a], MON_DATA_SPATK, &gBattleBufferA[gActiveBank][3]); + break; + case 48: + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF, &gBattleBufferA[gActiveBank][3]); + break; + case 49: + SetMonData(&gEnemyParty[a], MON_DATA_COOL, &gBattleBufferA[gActiveBank][3]); + break; + case 50: + SetMonData(&gEnemyParty[a], MON_DATA_BEAUTY, &gBattleBufferA[gActiveBank][3]); + break; + case 51: + SetMonData(&gEnemyParty[a], MON_DATA_CUTE, &gBattleBufferA[gActiveBank][3]); + break; + case 52: + SetMonData(&gEnemyParty[a], MON_DATA_SMART, &gBattleBufferA[gActiveBank][3]); + break; + case 53: + SetMonData(&gEnemyParty[a], MON_DATA_TOUGH, &gBattleBufferA[gActiveBank][3]); + break; + case 54: + SetMonData(&gEnemyParty[a], MON_DATA_SHEEN, &gBattleBufferA[gActiveBank][3]); + break; + case 55: + SetMonData(&gEnemyParty[a], MON_DATA_COOL_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 56: + SetMonData(&gEnemyParty[a], MON_DATA_BEAUTY_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 57: + SetMonData(&gEnemyParty[a], MON_DATA_CUTE_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 58: + SetMonData(&gEnemyParty[a], MON_DATA_SMART_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 59: + SetMonData(&gEnemyParty[a], MON_DATA_TOUGH_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + } +} + +void LinkOpponentHandlecmd3(void) +{ + u8 *dst; + u8 i; + + dst = (u8 *)&gEnemyParty[gBattlePartyID[gActiveBank]] + gBattleBufferA[gActiveBank][1]; + for (i = 0; i < gBattleBufferA[gActiveBank][2]; i++) + dst[i] = gBattleBufferA[gActiveBank][3 + i]; + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleLoadPokeSprite(void) +{ + u16 species = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES); + + BattleLoadOpponentMonSprite(&gEnemyParty[gBattlePartyID[gActiveBank]], gActiveBank); + GetMonSpriteTemplate_803C56C(species, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + sub_8077ABC(gActiveBank, 2), + sub_8077F68(gActiveBank), + sub_8079E90(gActiveBank)); + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = -240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], gBattleMonForms[gActiveBank]); + sub_8032984(gActiveBank, GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES)); + gBattleBankFunc[gActiveBank] = sub_8037A74; +} + +void LinkOpponentHandleSendOutPoke(void) +{ + gBattlePartyID[gActiveBank] = gBattleBufferA[gActiveBank][1]; + sub_8039430(gActiveBank, gBattleBufferA[gActiveBank][2]); + gBattleBankFunc[gActiveBank] = sub_8037E30; +} + +void sub_8039430(u8 a, u8 b) +{ + u16 species; + + sub_8032AA8(a, b); + gBattlePartyID[a] = gBattleBufferA[a][1]; + species = GetMonData(&gEnemyParty[gBattlePartyID[a]], MON_DATA_SPECIES); + gUnknown_0300434C[a] = CreateInvisibleSpriteWithCallback(sub_80312F0); + BattleLoadOpponentMonSprite(&gEnemyParty[gBattlePartyID[a]], a); + GetMonSpriteTemplate_803C56C(species, GetBankIdentity(a)); + gObjectBankIDs[a] = CreateSprite( + &gUnknown_02024E8C, + sub_8077ABC(a, 2), + sub_8077F68(a), + sub_8079E90(a)); + gSprites[gUnknown_0300434C[a]].data1 = gObjectBankIDs[a]; + gSprites[gObjectBankIDs[a]].data0 = a; + gSprites[gObjectBankIDs[a]].data2 = species; + gSprites[gObjectBankIDs[a]].oam.paletteNum = a; + StartSpriteAnim(&gSprites[gObjectBankIDs[a]], gBattleMonForms[a]); + gSprites[gObjectBankIDs[a]].invisible = TRUE; + gSprites[gObjectBankIDs[a]].callback = SpriteCallbackDummy; + gSprites[gUnknown_0300434C[a]].data0 = sub_8046400(0, 0xFE); +} + +void LinkOpponentHandleReturnPokeToBall(void) +{ + if (gBattleBufferA[gActiveBank][1] == 0) + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_8039648; + } + else + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8032A08(gActiveBank); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + LinkOpponentBufferExecCompleted(); + } +} + +void sub_8039648(void) +{ + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (!ewram17810[gActiveBank].unk0_6) + { + ewram17810[gActiveBank].unk4 = 0; + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 2); + gBattleBankFunc[gActiveBank] = sub_8037BBC; + } + break; + } +} + +void LinkOpponentHandleTrainerThrow(void) +{ + s16 xOffset; + u32 gender; + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (GetBankIdentity(gActiveBank) & 2) + xOffset = -16; + else + xOffset = 16; + gender = gLinkPlayers[sub_803FC34(gActiveBank)].gender; + } + else + { + xOffset = 0; + gender = gLinkPlayers[GetMultiplayerId() ^ 1].gender; + } + sub_8031A6C(gender, gActiveBank); + GetMonSpriteTemplate_803C5A0(gender, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + 176 + xOffset, 40 + 4 * (8 - gTrainerFrontPicCoords[gender].coords), + sub_8079E90(gActiveBank)); + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = -240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = 2; + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerFrontPicPaletteTable[gender].tag); + gSprites[gObjectBankIDs[gActiveBank]].data5 = gSprites[gObjectBankIDs[gActiveBank]].oam.tileNum; + gSprites[gObjectBankIDs[gActiveBank]].oam.tileNum = GetSpriteTileStartByTag(gTrainerFrontPicTable[gender].tag); + gSprites[gObjectBankIDs[gActiveBank]].oam.affineParam = gender; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_803757C; +} + +void LinkOpponentHandleTrainerSlide(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleTrainerSlideBack(void) +{ + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 35; + gSprites[gObjectBankIDs[gActiveBank]].data2 = 280; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], SpriteCallbackDummy); + gBattleBankFunc[gActiveBank] = sub_80375B4; +} + +void LinkOpponentHandlecmd10(void) +{ + if (ewram17810[gActiveBank].unk4 == 0) + { + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4++; + } + else if (!ewram17810[gActiveBank].unk0_6) + { + ewram17810[gActiveBank].unk4 = 0; + PlaySE12WithPanning(SE_POKE_DEAD, 63); + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8010384; + gBattleBankFunc[gActiveBank] = sub_8037B78; + } +} + +void LinkOpponentHandlecmd11(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd12(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleBallThrow(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlePuase(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleMoveAnimation(void) +{ + if (!mplay_80342A4(gActiveBank)) + { + u32 r0 = gBattleBufferA[gActiveBank][1] + | (gBattleBufferA[gActiveBank][2] << 8); + + gUnknown_0202F7C4 = gBattleBufferA[gActiveBank][3]; + gMovePowerMoveAnim = gBattleBufferA[gActiveBank][4] + | (gBattleBufferA[gActiveBank][5] << 8); + gMoveDmgMoveAnim = gBattleBufferA[gActiveBank][6] + | (gBattleBufferA[gActiveBank][7] << 8) + | (gBattleBufferA[gActiveBank][8] << 16) + | (gBattleBufferA[gActiveBank][9] << 24); + gHappinessMoveAnim = gBattleBufferA[gActiveBank][10]; + gWeatherMoveAnim = gBattleBufferA[gActiveBank][12] + | (gBattleBufferA[gActiveBank][13] << 8); + gDisableStructMoveAnim = (u32 *)&gBattleBufferA[gActiveBank][16]; + gPID_perBank[gActiveBank] = *gDisableStructMoveAnim; + + // Dead code. sub_8031720 always returns 0. + if (sub_8031720(r0, gUnknown_0202F7C4) != 0) + { + LinkOpponentBufferExecCompleted(); + } + else + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_8039B64; + } + } +} + +void sub_8039B64(void) +{ + u16 r4 = gBattleBufferA[gActiveBank][1] + | (gBattleBufferA[gActiveBank][2] << 8); + u8 r7 = gBattleBufferA[gActiveBank][11]; + + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite && !ewram17800[gActiveBank].unk0_3) + { + ewram17800[gActiveBank].unk0_3 = 1; + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + } + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (!ewram17810[gActiveBank].unk0_6) + { + sub_80326EC(0); + ExecuteMoveAnim(r4); + ewram17810[gActiveBank].unk4 = 2; + } + break; + case 2: + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + sub_80326EC(1); + if ((ewram17800[gActiveBank].substituteSprite) && r7 <= 1) + { + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + ewram17800[gActiveBank].unk0_3 = 0; + } + ewram17810[gActiveBank].unk4 = 3; + } + break; + case 3: + if (!ewram17810[gActiveBank].unk0_6) + { + sub_8031F24(); + sub_80324BC( + gActiveBank, + gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + ewram17810[gActiveBank].unk4 = 0; + LinkOpponentBufferExecCompleted(); + } + break; + } +} + +void LinkOpponentHandlePrintString(void) +{ + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + BufferStringBattle(*(u16 *)&gBattleBufferA[gActiveBank][2]); + sub_8002EB0(&gUnknown_03004210, gDisplayedStringBattle, 144, 2, 15); + gBattleBankFunc[gActiveBank] = sub_8037C2C; +} + +void LinkOpponentHandlePrintStringPlayerOnly(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd18(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd19(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd20(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleOpenBag(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd22(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd23(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleHealthBarUpdate(void) +{ + s16 r7; + + load_gfxc_health_bar(0); + r7 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + if (r7 != 0x7FFF) + { + u32 maxHP = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + u32 hp = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, hp, r7); + } + else + { + u32 maxHP = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, 0, r7); + } + gBattleBankFunc[gActiveBank] = sub_8037B24; +} + +void LinkOpponentHandleExpBarUpdate(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleStatusIconUpdate(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + sub_8045A5C(gHealthboxIDs[gActiveBank], &gEnemyParty[gBattlePartyID[gActiveBank]], 9); + ewram17810[gActiveBank].unk0_4 = 0; + gBattleBankFunc[gActiveBank] = sub_8037FAC; + } +} + +void LinkOpponentHandleStatusAnimation(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + move_anim_start_t2_for_situation( + gBattleBufferA[gActiveBank][1], + gBattleBufferA[gActiveBank][2] + | (gBattleBufferA[gActiveBank][3] << 8) + | (gBattleBufferA[gActiveBank][4] << 16) + | (gBattleBufferA[gActiveBank][5] << 24)); + gBattleBankFunc[gActiveBank] = sub_8037FAC; + } +} + +void LinkOpponentHandleStatusXor(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd29(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleDMATransfer(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd31(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd32(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd33(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd34(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd35(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd36(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd37(void) +{ + gUnknown_020238C8.unk0_0 = 0; + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd38(void) +{ + gUnknown_020238C8.unk0_0 = gBattleBufferA[gActiveBank][1]; + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd39(void) +{ + gUnknown_020238C8.unk0_7 = 0; + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd40(void) +{ + gUnknown_020238C8.unk0_7 ^= 1; + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleHitAnimation(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].invisible == TRUE) + { + LinkOpponentBufferExecCompleted(); + } + else + { + gDoingBattleAnim = TRUE; + gSprites[gObjectBankIDs[gActiveBank]].data1 = 0; + sub_8047858(gActiveBank); + gBattleBankFunc[gActiveBank] = dp01t_0F_4_move_anim; + } +} + +void LinkOpponentHandlecmd42(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleEffectivenessSound(void) +{ + s8 pan; + + if (GetBankSide(gActiveBank) == 0) + pan = -64; + else + pan = 63; + PlaySE12WithPanning(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8), pan); + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd44(void) +{ + PlayFanfare(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleFaintingCry(void) +{ + PlayCry3( + GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES), + 25, 5); + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleIntroSlide(void) +{ + sub_80E43C0(gBattleBufferA[gActiveBank][1]); + gUnknown_02024DE8 |= 1; + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleTrainerBallThrow(void) +{ + u8 taskId; + + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 35; + gSprites[gObjectBankIDs[gActiveBank]].data2 = 280; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], sub_803A3A8); + taskId = CreateTask(sub_803A2C4, 5); + gTasks[taskId].data[0] = gActiveBank; + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + ewram17840.unk9_0 = 1; + gBattleBankFunc[gActiveBank] = nullsub_47; +} + +void sub_803A2C4(u8 taskId) +{ + u8 r9; + + r9 = gActiveBank; + gActiveBank = gTasks[taskId].data[0]; + if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_8039430(gActiveBank, 0); + } + else + { + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_8039430(gActiveBank, 0); + gActiveBank ^= 2; + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_8039430(gActiveBank, 0); + gActiveBank ^= 2; + } + gBattleBankFunc[gActiveBank] = sub_8037840; + gActiveBank = r9; + DestroyTask(taskId); +} + +void sub_803A3A8(struct Sprite *sprite) +{ + sub_8031B74(sprite->oam.affineParam); + sprite->oam.tileNum = sprite->data5; + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); +} + +void LinkOpponentHandlecmd48(void) +{ + if (gBattleBufferA[gActiveBank][1] != 0 && GetBankSide(gActiveBank) == 0) + { + LinkOpponentBufferExecCompleted(); + return; + } + + ewram17810[gActiveBank].unk0_0 = 1; + if (gBattleBufferA[gActiveBank][2] != 0) + { + if (ewram17810[gActiveBank].unk1_1 < 2) + { + ewram17810[gActiveBank].unk1_1++; + return; + } + else + { + ewram17810[gActiveBank].unk1_1 = 0; + } + } + gUnknown_02024E68[gActiveBank] = sub_8044804( + gActiveBank, + (struct BattleInterfaceStruct2 *)&gBattleBufferA[gActiveBank][4], + gBattleBufferA[gActiveBank][1], + gBattleBufferA[gActiveBank][2]); + ewram17810[gActiveBank].unk5 = 0; + if (gBattleBufferA[gActiveBank][2] != 0) + ewram17810[gActiveBank].unk5 = 0x5D; + gBattleBankFunc[gActiveBank] = sub_803A4E0; +} + +void sub_803A4E0(void) +{ + if (ewram17810[gActiveBank].unk5++ >= 93) + { + ewram17810[gActiveBank].unk5 = 0; + LinkOpponentBufferExecCompleted(); + } +} + +void LinkOpponentHandlecmd49(void) +{ + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd50(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleSpriteInvisibility(void) +{ + if (AnimBankSpriteExists(gActiveBank) != 0) + { + gSprites[gObjectBankIDs[gActiveBank]].invisible = gBattleBufferA[gActiveBank][1]; + sub_8031F88(gActiveBank); + } + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleBattleAnimation(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + u8 r3 = gBattleBufferA[gActiveBank][1]; + u16 r4 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + + if (move_anim_start_t3(gActiveBank, gActiveBank, gActiveBank, r3, r4) != 0) + LinkOpponentBufferExecCompleted(); + else + gBattleBankFunc[gActiveBank] = sub_8037FD8; + } +} + +void LinkOpponentHandleLinkStandbyMsg(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandleResetActionMoveSelection(void) +{ + LinkOpponentBufferExecCompleted(); +} + +void LinkOpponentHandlecmd55(void) +{ + if (gBattleBufferA[gActiveBank][1] == 3) + gBattleOutcome = gBattleBufferA[gActiveBank][1]; + else + gBattleOutcome = gBattleBufferA[gActiveBank][1] ^ 3; + FadeOutMapMusic(5); + BeginFastPaletteFade(3); + LinkOpponentBufferExecCompleted(); + gBattleBankFunc[gActiveBank] = sub_8037F34; +} + +void LinkOpponentHandlecmd56(void) +{ +} diff --git a/src/battle/battle_controller_linkpartner.c b/src/battle/battle_controller_linkpartner.c new file mode 100644 index 000000000..3e34b2e25 --- /dev/null +++ b/src/battle/battle_controller_linkpartner.c @@ -0,0 +1,1728 @@ +#include "global.h" +#include "battle.h" +#include "battle_interface.h" +#include "data2.h" +#include "battle_811DA74.h" +#include "battle_anim_813F0F4.h" +#include "link.h" +#include "m4a.h" +#include "main.h" +#include "palette.h" +#include "pokeball.h" +#include "pokemon.h" +#include "rom3.h" +#include "rom_8077ABC.h" +#include "sound.h" +#include "songs.h" +#include "sprite.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "util.h" + +struct UnknownStruct1 +{ + u8 unk0; + u8 unk1; + u8 unk2[0x1FE]; +}; + +//Possibly PokemonSubstruct1 +struct UnknownStruct3 +{ + u16 moves[4]; + u8 pp[4]; + u8 ppBonuses; +}; + +extern u16 gBattleTypeFlags; +extern u8 gDisplayedStringBattle[]; +extern u8 gBattleBufferA[][0x200]; +extern u8 gActiveBank; +extern u32 gBattleExecBuffer; +extern u16 gBattlePartyID[]; +extern u8 gObjectBankIDs[]; +extern u8 gBattleOutcome; +extern u16 gUnknown_02024DE8; +extern u8 gUnknown_02024E68[]; +extern u8 gDoingBattleAnim; +extern u32 gPID_perBank[]; +extern struct SpriteTemplate gUnknown_02024E8C; +extern u32 *gDisableStructMoveAnim; +extern u32 gMoveDmgMoveAnim; +extern u16 gMovePowerMoveAnim; +extern u8 gHappinessMoveAnim; +extern u16 gWeatherMoveAnim; +extern u8 gUnknown_0202F7C4; +extern struct Window gUnknown_03004210; +extern u16 gUnknown_030042A0; +extern u16 gUnknown_030042A4; +extern MainCallback gPreBattleCallback1; +extern void (*gBattleBankFunc[])(void); +extern u8 gHealthboxIDs[]; +extern u8 gUnknown_0300434C[]; +extern u8 gBattleMonForms[]; +extern u8 gAnimScriptActive; +extern void (*gAnimScriptCallback)(void); + +extern u8 move_anim_start_t3(); +extern u8 AnimBankSpriteExists(); +extern void sub_8044CA0(u8); +extern void sub_8030E38(struct Sprite *); +extern void sub_80E43C0(); +extern void sub_8047858(); +extern void move_anim_start_t2_for_situation(); +extern void load_gfxc_health_bar(); +extern void sub_8043D84(); +extern void BufferStringBattle(); +extern void sub_8031F24(void); +extern void sub_80326EC(); +extern void ExecuteMoveAnim(); +extern void sub_80324BC(); +extern u8 sub_8031720(); +extern u8 mplay_80342A4(); +extern void oamt_add_pos2_onto_pos1(); +extern void StoreSpriteCallbackInData6(); +extern void sub_8078B34(struct Sprite *); +extern void sub_80105EC(struct Sprite *); +extern s32 sub_803FC34(u16); +extern void LoadPlayerTrainerBankSprite(); +extern void sub_80313A0(struct Sprite *); +extern u8 sub_8046400(); +extern void sub_80312F0(struct Sprite *); +extern u8 CreateInvisibleSpriteWithCallback(); +extern void BattleLoadPlayerMonSprite(); +extern u8 sub_8077ABC(); +extern u8 sub_8077F68(); +extern u8 sub_8079E90(); +extern void nullsub_10(); +extern void sub_8045A5C(); +extern void sub_804777C(); +extern void sub_8043DFC(); +//extern s16 sub_8045C78(); +extern void sub_80440EC(); +extern void sub_80324F8(); +extern void nullsub_9(u16); +extern void sub_8043DB0(); +extern void move_anim_start_t4(); +extern void c3_0802FDF4(u8); +extern void sub_8031F88(); +extern void sub_8141828(); +extern void c2_8011A1C(void); + +// this file's functions + +void LinkPartnerBufferRunCommand(void); +void sub_811E0A0(void); +void LinkPartnerBufferExecCompleted(void); +u32 dp01_getattr_by_ch1_for_player_pokemon(u8 a, u8 *b); +void sub_811EC68(u8); +void sub_811F864(u8, u8); +void sub_811FA5C(void); +void sub_811FF30(void); +void sub_812071C(u8); +void sub_81208E0(void); + +void LinkPartnerHandleGetAttributes(void); +void LinkPartnerHandlecmd1(void); +void LinkPartnerHandleSetAttributes(void); +void LinkPartnerHandlecmd3(void); +void LinkPartnerHandleLoadPokeSprite(void); +void LinkPartnerHandleSendOutPoke(void); +void LinkPartnerHandleReturnPokeToBall(void); +void LinkPartnerHandleTrainerThrow(void); +void LinkPartnerHandleTrainerSlide(void); +void LinkPartnerHandleTrainerSlideBack(void); +void LinkPartnerHandlecmd10(void); +void LinkPartnerHandlecmd11(void); +void LinkPartnerHandlecmd12(void); +void LinkPartnerHandleBallThrow(void); +void LinkPartnerHandlePuase(void); +void LinkPartnerHandleMoveAnimation(void); +void LinkPartnerHandlePrintString(void); +void LinkPartnerHandlePrintStringPlayerOnly(void); +void LinkPartnerHandlecmd18(void); +void LinkPartnerHandlecmd19(void); +void LinkPartnerHandlecmd20(void); +void LinkPartnerHandleOpenBag(void); +void LinkPartnerHandlecmd22(void); +void LinkPartnerHandlecmd23(void); +void LinkPartnerHandleHealthBarUpdate(void); +void LinkPartnerHandleExpBarUpdate(void); +void LinkPartnerHandleStatusIconUpdate(void); +void LinkPartnerHandleStatusAnimation(void); +void LinkPartnerHandleStatusXor(void); +void LinkPartnerHandlecmd29(void); +void LinkPartnerHandleDMATransfer(void); +void LinkPartnerHandlecmd31(void); +void LinkPartnerHandlecmd32(void); +void LinkPartnerHandlecmd33(void); +void LinkPartnerHandlecmd34(void); +void LinkPartnerHandlecmd35(void); +void LinkPartnerHandlecmd36(void); +void LinkPartnerHandlecmd37(void); +void LinkPartnerHandlecmd38(void); +void LinkPartnerHandlecmd39(void); +void LinkPartnerHandlecmd40(void); +void LinkPartnerHandleHitAnimation(void); +void LinkPartnerHandlecmd42(void); +void LinkPartnerHandleEffectivenessSound(void); +void LinkPartnerHandlecmd44(void); +void LinkPartnerHandleFaintingCry(void); +void LinkPartnerHandleIntroSlide(void); +void LinkPartnerHandleTrainerBallThrow(void); +void LinkPartnerHandlecmd48(void); +void LinkPartnerHandlecmd49(void); +void LinkPartnerHandlecmd50(void); +void LinkPartnerHandleSpriteInvisibility(void); +void LinkPartnerHandleBattleAnimation(void); +void LinkPartnerHandleLinkStandbyMsg(void); +void LinkPartnerHandleResetActionMoveSelection(void); +void LinkPartnerHandlecmd55(void); +void LinkPartnerHandlecmd56(void); + +// const data +typedef void (*BattleBufferCmd) (void); +static const BattleBufferCmd gLinkPartnerBufferCommands[] = +{ + LinkPartnerHandleGetAttributes, + LinkPartnerHandlecmd1, + LinkPartnerHandleSetAttributes, + LinkPartnerHandlecmd3, + LinkPartnerHandleLoadPokeSprite, + LinkPartnerHandleSendOutPoke, + LinkPartnerHandleReturnPokeToBall, + LinkPartnerHandleTrainerThrow, + LinkPartnerHandleTrainerSlide, + LinkPartnerHandleTrainerSlideBack, + LinkPartnerHandlecmd10, + LinkPartnerHandlecmd11, + LinkPartnerHandlecmd12, + LinkPartnerHandleBallThrow, + LinkPartnerHandlePuase, + LinkPartnerHandleMoveAnimation, + LinkPartnerHandlePrintString, + LinkPartnerHandlePrintStringPlayerOnly, + LinkPartnerHandlecmd18, + LinkPartnerHandlecmd19, + LinkPartnerHandlecmd20, + LinkPartnerHandleOpenBag, + LinkPartnerHandlecmd22, + LinkPartnerHandlecmd23, + LinkPartnerHandleHealthBarUpdate, + LinkPartnerHandleExpBarUpdate, + LinkPartnerHandleStatusIconUpdate, + LinkPartnerHandleStatusAnimation, + LinkPartnerHandleStatusXor, + LinkPartnerHandlecmd29, + LinkPartnerHandleDMATransfer, + LinkPartnerHandlecmd31, + LinkPartnerHandlecmd32, + LinkPartnerHandlecmd33, + LinkPartnerHandlecmd34, + LinkPartnerHandlecmd35, + LinkPartnerHandlecmd36, + LinkPartnerHandlecmd37, + LinkPartnerHandlecmd38, + LinkPartnerHandlecmd39, + LinkPartnerHandlecmd40, + LinkPartnerHandleHitAnimation, + LinkPartnerHandlecmd42, + LinkPartnerHandleEffectivenessSound, + LinkPartnerHandlecmd44, + LinkPartnerHandleFaintingCry, + LinkPartnerHandleIntroSlide, + LinkPartnerHandleTrainerBallThrow, + LinkPartnerHandlecmd48, + LinkPartnerHandlecmd49, + LinkPartnerHandlecmd50, + LinkPartnerHandleSpriteInvisibility, + LinkPartnerHandleBattleAnimation, + LinkPartnerHandleLinkStandbyMsg, + LinkPartnerHandleResetActionMoveSelection, + LinkPartnerHandlecmd55, + LinkPartnerHandlecmd56, +}; +// code starts here + +void nullsub_74(void) +{ +} + +void SetBankFuncToLinkPartnerBufferRunCommand(void) +{ + gBattleBankFunc[gActiveBank] = LinkPartnerBufferRunCommand; +} + +void LinkPartnerBufferRunCommand(void) +{ + if (gBattleExecBuffer & gBitTable[gActiveBank]) + { + if (gBattleBufferA[gActiveBank][0] <= 0x38) + gLinkPartnerBufferCommands[gBattleBufferA[gActiveBank][0]](); + else + LinkPartnerBufferExecCompleted(); + } +} + +void sub_811DAE4(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + LinkPartnerBufferExecCompleted(); +} + +void sub_811DB1C(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + { + nullsub_10(0); + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + LinkPartnerBufferExecCompleted(); + } +} + +void sub_811DB84(void) +{ + if ((--ewram17810[gActiveBank].unk9) == 0xFF) + { + ewram17810[gActiveBank].unk9 = 0; + LinkPartnerBufferExecCompleted(); + } +} + +void sub_811DBC0(void) +{ + bool8 r6 = FALSE; + + if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & 0x40))) + { + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy) + r6 = TRUE; + } + else + { + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy + && gSprites[gHealthboxIDs[gActiveBank ^ 2]].callback == SpriteCallbackDummy) + r6 = TRUE; + } + if (IsCryPlayingOrClearCrySongs()) + r6 = FALSE; + if (r6) + { + ewram17810[gActiveBank].unk9 = 3; + gBattleBankFunc[gActiveBank] = sub_811DB84; + } +} + +void sub_811DCA0(void) +{ + u8 r2; + + if (!ewram17810[gActiveBank].unk0_3) + { + // I couldn't get it to work as a bitfield here + r2 = *((u8 *)&ewram17810[gActiveBank ^ 2]) & 8; + if (!r2 && (++ewram17810[gActiveBank].unk9) != 1) + { + ewram17810[gActiveBank].unk9 = r2; + if (IsDoubleBattle() && !(gBattleTypeFlags & 0x40)) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank ^ 2]]); + sub_8045A5C(gHealthboxIDs[gActiveBank ^ 2], &gPlayerParty[gBattlePartyID[gActiveBank ^ 2]], 0); + sub_804777C(gActiveBank ^ 2); + sub_8043DFC(gHealthboxIDs[gActiveBank ^ 2]); + } + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + sub_8045A5C(gHealthboxIDs[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + (s8)ewram17810[4].unk9 &= ~1; + gBattleBankFunc[gActiveBank] = sub_811DBC0; + } + } +} + +void sub_811DDE8(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].animEnded + && gSprites[gObjectBankIDs[gActiveBank]].pos2.x == 0) + LinkPartnerBufferExecCompleted(); +} + +void bx_t3_healthbar_update(void) +{ + s16 r4; + + r4 = sub_8045C78(gActiveBank, gHealthboxIDs[gActiveBank], 0, 0); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + if (r4 != -1) + { + sub_80440EC(gHealthboxIDs[gActiveBank], r4, 0); + } + else + { + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + LinkPartnerBufferExecCompleted(); + } +} + +void sub_811DE98(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].pos1.y + gSprites[gObjectBankIDs[gActiveBank]].pos2.y > 160) + { + nullsub_9(GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES)); + FreeOamMatrix(gSprites[gObjectBankIDs[gActiveBank]].oam.matrixNum); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + LinkPartnerBufferExecCompleted(); + } +} + +void sub_811DF34(void) +{ + if (!ewram17810[gActiveBank].unk0_6) + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + LinkPartnerBufferExecCompleted(); + } +} + +void sub_811DFA0(void) +{ + if (gUnknown_03004210.state == 0) + LinkPartnerBufferExecCompleted(); +} + +void bx_blink_t3(void) +{ + u8 spriteId = gObjectBankIDs[gActiveBank]; + if (gSprites[spriteId].data1 == 32) + { + gSprites[spriteId].data1 = 0; + gSprites[spriteId].invisible = FALSE; + gDoingBattleAnim = 0; + LinkPartnerBufferExecCompleted(); + } + else + { + if ((gSprites[spriteId].data1 % 4) == 0) + { + gSprites[spriteId].invisible ^= 1; + } + gSprites[spriteId].data1++; + } +} + +void sub_811E034(void) +{ + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy) + { + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + gBattleBankFunc[gActiveBank] = sub_811E0A0; + } +} + +void sub_811E0A0(void) +{ + if (!ewram17810[gActiveBank].unk0_6) + LinkPartnerBufferExecCompleted(); +} + +void sub_811E0CC(void) +{ + if (ewram17810[gActiveBank].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + CreateTask(c3_0802FDF4, 10); + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], 0); + sub_8045A5C(gHealthboxIDs[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + sub_8031F88(gActiveBank); + gBattleBankFunc[gActiveBank] = sub_811E034; + } +} + +void sub_811E1BC(void) +{ + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank].unk0_7) + sub_8141828(gActiveBank, &gPlayerParty[gBattlePartyID[gActiveBank]]); + if (gSprites[gUnknown_0300434C[gActiveBank]].callback == SpriteCallbackDummy + && !ewram17810[gActiveBank].unk0_3) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + gBattleBankFunc[gActiveBank] = sub_811E0CC; + } +} + +void sub_811E258(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + m4aSongNumStop(0x5A); + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(c2_8011A1C); + } +} + +void sub_811E29C(void) +{ + if (!gPaletteFade.active) + { + if (gBattleTypeFlags & 2) + { + sub_800832C(); + gBattleBankFunc[gActiveBank] = sub_811E258; + } + else + { + m4aSongNumStop(0x5A); + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } + } +} + +void LinkPartnerBufferExecCompleted(void) +{ + u8 multiplayerId; + + gBattleBankFunc[gActiveBank] = LinkPartnerBufferRunCommand; + if (gBattleTypeFlags & 2) + { + multiplayerId = GetMultiplayerId(); + PrepareBufferDataTransferLink(2, 4, &multiplayerId); + gBattleBufferA[gActiveBank][0] = 0x38; + } + else + { + gBattleExecBuffer &= ~gBitTable[gActiveBank]; + } +} + +void sub_811E38C(void) +{ + if (!ewram17810[gActiveBank].unk0_4) + LinkPartnerBufferExecCompleted(); +} + +void sub_811E3B8(void) +{ + if (!ewram17810[gActiveBank].unk0_5) + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleGetAttributes(void) +{ + u8 unk[256]; + int r6 = 0; + s32 i; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + r6 = dp01_getattr_by_ch1_for_player_pokemon(gBattlePartyID[gActiveBank], unk); + } + else + { + u8 r4 = gBattleBufferA[gActiveBank][2]; + + for (i = 0; i < 6; i++) + { + if (r4 & 1) + r6 += dp01_getattr_by_ch1_for_player_pokemon(i, unk + r6); + r4 >>= 1; + } + } + Emitcmd29(1, r6, unk); + LinkPartnerBufferExecCompleted(); +} + +// Duplicate of dp01_getattr_by_ch1_for_player_pokemon_ +u32 dp01_getattr_by_ch1_for_player_pokemon(u8 a, u8 *buffer) +{ + struct BattlePokemon battlePokemon; + struct UnknownStruct3 moveData; + u8 nickname[20]; + u8 *src; + s16 data16; + u32 data32; + s32 size = 0; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + battlePokemon.species = GetMonData(&gPlayerParty[a], MON_DATA_SPECIES); + battlePokemon.item = GetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM); + for (size = 0; size < 4; size++) + { + battlePokemon.moves[size] = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + size); + battlePokemon.pp[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + } + battlePokemon.ppBonuses = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + battlePokemon.friendship = GetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP); + battlePokemon.experience = GetMonData(&gPlayerParty[a], MON_DATA_EXP); + battlePokemon.hpIV = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + battlePokemon.attackIV = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + battlePokemon.defenseIV = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + battlePokemon.speedIV = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + battlePokemon.spAttackIV = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + battlePokemon.spDefenseIV = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + battlePokemon.personality = GetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY); + battlePokemon.status1 = GetMonData(&gPlayerParty[a], MON_DATA_STATUS); + battlePokemon.level = GetMonData(&gPlayerParty[a], MON_DATA_LEVEL); + battlePokemon.hp = GetMonData(&gPlayerParty[a], MON_DATA_HP); + battlePokemon.maxHP = GetMonData(&gPlayerParty[a], MON_DATA_MAX_HP); + battlePokemon.attack = GetMonData(&gPlayerParty[a], MON_DATA_ATK); + battlePokemon.defense = GetMonData(&gPlayerParty[a], MON_DATA_DEF); + battlePokemon.speed = GetMonData(&gPlayerParty[a], MON_DATA_SPD); + battlePokemon.spAttack = GetMonData(&gPlayerParty[a], MON_DATA_SPATK); + battlePokemon.spDefense = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF); + battlePokemon.isEgg = GetMonData(&gPlayerParty[a], MON_DATA_IS_EGG); + battlePokemon.altAbility = GetMonData(&gPlayerParty[a], MON_DATA_ALT_ABILITY); + battlePokemon.otId = GetMonData(&gPlayerParty[a], MON_DATA_OT_ID); + GetMonData(&gPlayerParty[a], MON_DATA_NICKNAME, nickname); + StringCopy10(battlePokemon.nickname, nickname); + GetMonData(&gPlayerParty[a], MON_DATA_OT_NAME, battlePokemon.otName); + src = (u8 *)&battlePokemon; + for (size = 0; size < sizeof(battlePokemon); size++) + buffer[size] = src[size]; + break; + case 1: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPECIES); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 2: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 3: + for (size = 0; size < 4; size++) + { + moveData.moves[size] = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + size); + moveData.pp[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + } + moveData.ppBonuses = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + src = (u8 *)&moveData; + for (size = 0; size < sizeof(moveData); size++) + buffer[size] = src[size]; + break; + case 4: + case 5: + case 6: + case 7: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 8: + for (size = 0; size < 4; size++) + buffer[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + buffer[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + size++; + break; + case 9: + case 10: + case 11: + case 12: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9); + size = 1; + break; + case 17: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_OT_ID); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 18: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_EXP); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 19: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_EV); + size = 1; + break; + case 20: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_EV); + size = 1; + break; + case 21: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_EV); + size = 1; + break; + case 22: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_EV); + size = 1; + break; + case 23: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_EV); + size = 1; + break; + case 24: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_EV); + size = 1; + break; + case 25: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP); + size = 1; + break; + case 26: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_POKERUS); + size = 1; + break; + case 27: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_LOCATION); + size = 1; + break; + case 28: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_LEVEL); + size = 1; + break; + case 29: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_GAME); + size = 1; + break; + case 30: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_POKEBALL); + size = 1; + break; + case 31: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + buffer[1] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + buffer[2] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + buffer[3] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + buffer[4] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + buffer[5] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + size = 6; + break; + case 32: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + size = 1; + break; + case 33: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + size = 1; + break; + case 34: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + size = 1; + break; + case 35: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + size = 1; + break; + case 36: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + size = 1; + break; + case 37: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + size = 1; + break; + case 38: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 39: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_CHECKSUM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 40: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_STATUS); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 41: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_LEVEL); + size = 1; + break; + case 42: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 43: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_MAX_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 44: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_ATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 45: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_DEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 46: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPD); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 47: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 48: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 49: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_COOL); + size = 1; + break; + case 50: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_BEAUTY); + size = 1; + break; + case 51: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_CUTE); + size = 1; + break; + case 52: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SMART); + size = 1; + break; + case 53: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_TOUGH); + size = 1; + break; + case 54: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SHEEN); + size = 1; + break; + case 55: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_COOL_RIBBON); + size = 1; + break; + case 56: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_BEAUTY_RIBBON); + size = 1; + break; + case 57: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_CUTE_RIBBON); + size = 1; + break; + case 58: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SMART_RIBBON); + size = 1; + break; + case 59: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_TOUGH_RIBBON); + size = 1; + break; + } + return size; +} + +void LinkPartnerHandlecmd1(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleSetAttributes(void) +{ + u8 i; + u8 r4; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + sub_811EC68(gBattlePartyID[gActiveBank]); + } + else + { + r4 = gBattleBufferA[gActiveBank][2]; + for (i = 0; i < 6; i++) + { + if (r4 & 1) + sub_811EC68(i); + r4 >>= 1; + } + } + LinkPartnerBufferExecCompleted(); +} + +// Duplicate of dp01_setattr_by_ch1_for_player_pokemon +void sub_811EC68(u8 a) +{ + struct BattlePokemon *battlePokemon = (struct BattlePokemon *)&gBattleBufferA[gActiveBank][3]; + struct UnknownStruct3 *moveData = (struct UnknownStruct3 *)&gBattleBufferA[gActiveBank][3]; + s32 i; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + { + u8 iv; + + SetMonData(&gPlayerParty[a], MON_DATA_SPECIES, (u8 *)&battlePokemon->species); + SetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM, (u8 *)&battlePokemon->item); + for (i = 0; i < 4; i++) + { + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + i, (u8 *)&battlePokemon->moves[i]); + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + i, (u8 *)&battlePokemon->pp[i]); + } + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, (u8 *)&battlePokemon->ppBonuses); + SetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP, (u8 *)&battlePokemon->friendship); + SetMonData(&gPlayerParty[a], MON_DATA_EXP, (u8 *)&battlePokemon->experience); + iv = battlePokemon->hpIV; + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, (u8 *)&iv); + iv = battlePokemon->attackIV; + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, (u8 *)&iv); + iv = battlePokemon->defenseIV; + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, (u8 *)&iv); + iv = battlePokemon->speedIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, (u8 *)&iv); + iv = battlePokemon->spAttackIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, (u8 *)&iv); + iv = battlePokemon->spDefenseIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, (u8 *)&iv); + SetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY, (u8 *)&battlePokemon->personality); + SetMonData(&gPlayerParty[a], MON_DATA_STATUS, (u8 *)&battlePokemon->status1); + SetMonData(&gPlayerParty[a], MON_DATA_LEVEL, (u8 *)&battlePokemon->level); + SetMonData(&gPlayerParty[a], MON_DATA_HP, (u8 *)&battlePokemon->hp); + SetMonData(&gPlayerParty[a], MON_DATA_MAX_HP, (u8 *)&battlePokemon->maxHP); + SetMonData(&gPlayerParty[a], MON_DATA_ATK, (u8 *)&battlePokemon->attack); + SetMonData(&gPlayerParty[a], MON_DATA_DEF, (u8 *)&battlePokemon->defense); + SetMonData(&gPlayerParty[a], MON_DATA_SPD, (u8 *)&battlePokemon->speed); + SetMonData(&gPlayerParty[a], MON_DATA_SPATK, (u8 *)&battlePokemon->spAttack); + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF, (u8 *)&battlePokemon->spDefense); + } + break; + case 1: + SetMonData(&gPlayerParty[a], MON_DATA_SPECIES, &gBattleBufferA[gActiveBank][3]); + break; + case 2: + SetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM, &gBattleBufferA[gActiveBank][3]); + break; + case 3: + for (i = 0; i < 4; i++) + { + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + i, (u8 *)&moveData->moves[i]); + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + i, (u8 *)&moveData->pp[i]); + } + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, &moveData->ppBonuses); + break; + case 4: + case 5: + case 6: + case 7: + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4, &gBattleBufferA[gActiveBank][3]); + break; + case 8: + SetMonData(&gPlayerParty[a], MON_DATA_PP1, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gPlayerParty[a], MON_DATA_PP2, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gPlayerParty[a], MON_DATA_PP3, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gPlayerParty[a], MON_DATA_PP4, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, &gBattleBufferA[gActiveBank][7]); + break; + case 9: + case 10: + case 11: + case 12: + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9, &gBattleBufferA[gActiveBank][3]); + break; + case 17: + SetMonData(&gPlayerParty[a], MON_DATA_OT_ID, &gBattleBufferA[gActiveBank][3]); + break; + case 18: + SetMonData(&gPlayerParty[a], MON_DATA_EXP, &gBattleBufferA[gActiveBank][3]); + break; + case 19: + SetMonData(&gPlayerParty[a], MON_DATA_HP_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 20: + SetMonData(&gPlayerParty[a], MON_DATA_ATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 21: + SetMonData(&gPlayerParty[a], MON_DATA_DEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 22: + SetMonData(&gPlayerParty[a], MON_DATA_SPD_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 23: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 24: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 25: + SetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP, &gBattleBufferA[gActiveBank][3]); + break; + case 26: + SetMonData(&gPlayerParty[a], MON_DATA_POKERUS, &gBattleBufferA[gActiveBank][3]); + break; + case 27: + SetMonData(&gPlayerParty[a], MON_DATA_MET_LOCATION, &gBattleBufferA[gActiveBank][3]); + break; + case 28: + SetMonData(&gPlayerParty[a], MON_DATA_MET_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 29: + SetMonData(&gPlayerParty[a], MON_DATA_MET_GAME, &gBattleBufferA[gActiveBank][3]); + break; + case 30: + SetMonData(&gPlayerParty[a], MON_DATA_POKEBALL, &gBattleBufferA[gActiveBank][3]); + break; + case 31: + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][7]); + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][8]); + break; + case 32: + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 33: + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 34: + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 35: + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 36: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 37: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 38: + SetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY, &gBattleBufferA[gActiveBank][3]); + break; + case 39: + SetMonData(&gPlayerParty[a], MON_DATA_CHECKSUM, &gBattleBufferA[gActiveBank][3]); + break; + case 40: + SetMonData(&gPlayerParty[a], MON_DATA_STATUS, &gBattleBufferA[gActiveBank][3]); + break; + case 41: + SetMonData(&gPlayerParty[a], MON_DATA_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 42: + SetMonData(&gPlayerParty[a], MON_DATA_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 43: + SetMonData(&gPlayerParty[a], MON_DATA_MAX_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 44: + SetMonData(&gPlayerParty[a], MON_DATA_ATK, &gBattleBufferA[gActiveBank][3]); + break; + case 45: + SetMonData(&gPlayerParty[a], MON_DATA_DEF, &gBattleBufferA[gActiveBank][3]); + break; + case 46: + SetMonData(&gPlayerParty[a], MON_DATA_SPD, &gBattleBufferA[gActiveBank][3]); + break; + case 47: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK, &gBattleBufferA[gActiveBank][3]); + break; + case 48: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF, &gBattleBufferA[gActiveBank][3]); + break; + case 49: + SetMonData(&gPlayerParty[a], MON_DATA_COOL, &gBattleBufferA[gActiveBank][3]); + break; + case 50: + SetMonData(&gPlayerParty[a], MON_DATA_BEAUTY, &gBattleBufferA[gActiveBank][3]); + break; + case 51: + SetMonData(&gPlayerParty[a], MON_DATA_CUTE, &gBattleBufferA[gActiveBank][3]); + break; + case 52: + SetMonData(&gPlayerParty[a], MON_DATA_SMART, &gBattleBufferA[gActiveBank][3]); + break; + case 53: + SetMonData(&gPlayerParty[a], MON_DATA_TOUGH, &gBattleBufferA[gActiveBank][3]); + break; + case 54: + SetMonData(&gPlayerParty[a], MON_DATA_SHEEN, &gBattleBufferA[gActiveBank][3]); + break; + case 55: + SetMonData(&gPlayerParty[a], MON_DATA_COOL_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 56: + SetMonData(&gPlayerParty[a], MON_DATA_BEAUTY_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 57: + SetMonData(&gPlayerParty[a], MON_DATA_CUTE_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 58: + SetMonData(&gPlayerParty[a], MON_DATA_SMART_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 59: + SetMonData(&gPlayerParty[a], MON_DATA_TOUGH_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + } + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); +} + +void LinkPartnerHandlecmd3(void) +{ + u8 *dst; + u8 i; + + dst = (u8 *)&gPlayerParty[gBattlePartyID[gActiveBank]] + gBattleBufferA[gActiveBank][1]; + for (i = 0; i < gBattleBufferA[gActiveBank][2]; i++) + dst[i] = gBattleBufferA[gActiveBank][3 + i]; + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleLoadPokeSprite(void) +{ + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + GetMonSpriteTemplate_803C56C( + GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES), + GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + sub_8077ABC(gActiveBank, 2), + sub_8077F68(gActiveBank), + sub_8079E90(gActiveBank)); + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = -240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], gBattleMonForms[gActiveBank]); + gBattleBankFunc[gActiveBank] = sub_811DDE8; +} + +void LinkPartnerHandleSendOutPoke(void) +{ + sub_8032AA8(gActiveBank, gBattleBufferA[gActiveBank][2]); + gBattlePartyID[gActiveBank] = gBattleBufferA[gActiveBank][1]; + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + sub_811F864(gActiveBank, gBattleBufferA[gActiveBank][2]); + gBattleBankFunc[gActiveBank] = sub_811E1BC; +} + +void sub_811F864(u8 a, u8 b) +{ + u16 species; + + sub_8032AA8(a, b); + gBattlePartyID[a] = gBattleBufferA[a][1]; + species = GetMonData(&gPlayerParty[gBattlePartyID[a]], MON_DATA_SPECIES); + gUnknown_0300434C[a] = CreateInvisibleSpriteWithCallback(sub_80312F0); + GetMonSpriteTemplate_803C56C(species, GetBankIdentity(a)); + gObjectBankIDs[a] = CreateSprite( + &gUnknown_02024E8C, + sub_8077ABC(a, 2), + sub_8077F68(a), + sub_8079E90(a)); + gSprites[gUnknown_0300434C[a]].data1 = gObjectBankIDs[a]; + gSprites[gObjectBankIDs[a]].data0 = a; + gSprites[gObjectBankIDs[a]].data2 = species; + gSprites[gObjectBankIDs[a]].oam.paletteNum = a; + StartSpriteAnim(&gSprites[gObjectBankIDs[a]], gBattleMonForms[a]); + gSprites[gObjectBankIDs[a]].invisible = TRUE; + gSprites[gObjectBankIDs[a]].callback = SpriteCallbackDummy; + gSprites[gUnknown_0300434C[a]].data0 = sub_8046400(0, 0xFF); +} + +void LinkPartnerHandleReturnPokeToBall(void) +{ + if (gBattleBufferA[gActiveBank][1] == 0) + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_811FA5C; + } + else + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + LinkPartnerBufferExecCompleted(); + } +} + +void sub_811FA5C(void) +{ + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (!ewram17810[gActiveBank].unk0_6) + { + ewram17810[gActiveBank].unk4 = 0; + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 1); + gBattleBankFunc[gActiveBank] = sub_811DF34; + } + break; + } +} + +void LinkPartnerHandleTrainerThrow(void) +{ + s16 xOffset; + u32 gender; + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (GetBankIdentity(gActiveBank) & 2) + xOffset = 16; + else + xOffset = -16; + gender = gLinkPlayers[sub_803FC34(gActiveBank)].gender; + } + else + { + xOffset = 0; + gender = gLinkPlayers[GetMultiplayerId() ^ 1].gender; + } + LoadPlayerTrainerBankSprite(gender, gActiveBank); + GetMonSpriteTemplate_803C5A0(gender, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + 80 + xOffset, 80 + 4 * (8 - gTrainerBackPicCoords[gender].coords), + sub_8079E90(gActiveBank)); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = 240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = -2; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_811DAE4; +} + +void LinkPartnerHandleTrainerSlide(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleTrainerSlideBack(void) +{ + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 35; + gSprites[gObjectBankIDs[gActiveBank]].data2 = -40; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], SpriteCallbackDummy); + gBattleBankFunc[gActiveBank] = sub_811DB1C; +} + +void LinkPartnerHandlecmd10(void) +{ + if (ewram17810[gActiveBank].unk4 == 0) + { + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4++; + } + else if (!ewram17810[gActiveBank].unk0_6) + { + ewram17810[gActiveBank].unk4 = 0; + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + PlaySE12WithPanning(SE_POKE_DEAD, -64); + gSprites[gObjectBankIDs[gActiveBank]].data1 = 0; + gSprites[gObjectBankIDs[gActiveBank]].data2 = 5; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80105EC; + gBattleBankFunc[gActiveBank] = sub_811DE98; + } +} + +void LinkPartnerHandlecmd11(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd12(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleBallThrow(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlePuase(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleMoveAnimation(void) +{ + if (!mplay_80342A4(gActiveBank)) + { + u32 r0 = gBattleBufferA[gActiveBank][1] + | (gBattleBufferA[gActiveBank][2] << 8); + + gUnknown_0202F7C4 = gBattleBufferA[gActiveBank][3]; + gMovePowerMoveAnim = gBattleBufferA[gActiveBank][4] + | (gBattleBufferA[gActiveBank][5] << 8); + gMoveDmgMoveAnim = gBattleBufferA[gActiveBank][6] + | (gBattleBufferA[gActiveBank][7] << 8) + | (gBattleBufferA[gActiveBank][8] << 16) + | (gBattleBufferA[gActiveBank][9] << 24); + gHappinessMoveAnim = gBattleBufferA[gActiveBank][10]; + gWeatherMoveAnim = gBattleBufferA[gActiveBank][12] + | (gBattleBufferA[gActiveBank][13] << 8); + gDisableStructMoveAnim = (u32 *)&gBattleBufferA[gActiveBank][16]; + gPID_perBank[gActiveBank] = *gDisableStructMoveAnim; + + if (sub_8031720(r0, gUnknown_0202F7C4) != 0) + LinkPartnerBufferExecCompleted(); + else + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_811FF30; + } + } +} + +void sub_811FF30(void) +{ + u16 r4 = gBattleBufferA[gActiveBank][1] + | (gBattleBufferA[gActiveBank][2] << 8); + u8 r7 = gBattleBufferA[gActiveBank][11]; + + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite && !ewram17800[gActiveBank].unk0_3) + { + ewram17800[gActiveBank].unk0_3 = 1; + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + } + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (!ewram17810[gActiveBank].unk0_6) + { + sub_80326EC(0); + ExecuteMoveAnim(r4); + ewram17810[gActiveBank].unk4 = 2; + } + break; + case 2: + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + sub_80326EC(1); + if ((ewram17800[gActiveBank].substituteSprite) && r7 <= 1) + { + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + ewram17800[gActiveBank].unk0_3 = 0; + } + ewram17810[gActiveBank].unk4 = 3; + } + break; + case 3: + if (!ewram17810[gActiveBank].unk0_6) + { + sub_8031F24(); + sub_80324BC( + gActiveBank, + gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + ewram17810[gActiveBank].unk4 = 0; + LinkPartnerBufferExecCompleted(); + } + break; + } +} + +void LinkPartnerHandlePrintString(void) +{ + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + BufferStringBattle(*(u16 *)&gBattleBufferA[gActiveBank][2]); + sub_8002EB0(&gUnknown_03004210, gDisplayedStringBattle, 144, 2, 15); + gBattleBankFunc[gActiveBank] = sub_811DFA0; +} + +void LinkPartnerHandlePrintStringPlayerOnly(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd18(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd19(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd20(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleOpenBag(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd22(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd23(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleHealthBarUpdate(void) +{ + s16 r7; + + load_gfxc_health_bar(0); + r7 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + if (r7 != 0x7FFF) + { + u32 maxHP = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + u32 hp = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, hp, r7); + } + else + { + u32 maxHP = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, 0, r7); + } + gBattleBankFunc[gActiveBank] = bx_t3_healthbar_update; +} + +void LinkPartnerHandleExpBarUpdate(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleStatusIconUpdate(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + sub_8045A5C(gHealthboxIDs[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], 9); + ewram17810[gActiveBank].unk0_4 = 0; + gBattleBankFunc[gActiveBank] = sub_811E38C; + } +} + +void LinkPartnerHandleStatusAnimation(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + move_anim_start_t2_for_situation( + gBattleBufferA[gActiveBank][1], + gBattleBufferA[gActiveBank][2] + | (gBattleBufferA[gActiveBank][3] << 8) + | (gBattleBufferA[gActiveBank][4] << 16) + | (gBattleBufferA[gActiveBank][5] << 24)); + gBattleBankFunc[gActiveBank] = sub_811E38C; + } +} + +void LinkPartnerHandleStatusXor(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd29(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleDMATransfer(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd31(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd32(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd33(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd34(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd35(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd36(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd37(void) +{ + gUnknown_020238C8.unk0_0 = 0; + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd38(void) +{ + gUnknown_020238C8.unk0_0 = gBattleBufferA[gActiveBank][1]; + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd39(void) +{ + gUnknown_020238C8.unk0_7 = 0; + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd40(void) +{ + gUnknown_020238C8.unk0_7 ^= 1; + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleHitAnimation(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].invisible == TRUE) + { + LinkPartnerBufferExecCompleted(); + } + else + { + gDoingBattleAnim = TRUE; + gSprites[gObjectBankIDs[gActiveBank]].data1 = 0; + sub_8047858(gActiveBank); + gBattleBankFunc[gActiveBank] = bx_blink_t3; + } +} + +void LinkPartnerHandlecmd42(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleEffectivenessSound(void) +{ + s8 pan; + + if (GetBankSide(gActiveBank) == 0) + pan = -64; + else + pan = 63; + PlaySE12WithPanning(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8), pan); + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd44(void) +{ + PlayFanfare(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleFaintingCry(void) +{ + PlayCry3( + GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES), + -25, 5); + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleIntroSlide(void) +{ + sub_80E43C0(gBattleBufferA[gActiveBank][1]); + gUnknown_02024DE8 |= 1; + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleTrainerBallThrow(void) +{ + u8 r4; + u8 taskId; + + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 50; + gSprites[gObjectBankIDs[gActiveBank]].data2 = -40; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + gSprites[gObjectBankIDs[gActiveBank]].data5 = gActiveBank; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], sub_8030E38); + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], 1); + r4 = AllocSpritePalette(0xD6F9); + LoadCompressedPalette( + gTrainerBackPicPaletteTable[gLinkPlayers[sub_803FC34(gActiveBank)].gender].data, + 0x100 + r4 * 16, 0x20); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = r4; + taskId = CreateTask(sub_812071C, 5); + gTasks[taskId].data[0] = gActiveBank; + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + ewram17840.unk9_0 = 1; + gBattleBankFunc[gActiveBank] = nullsub_74; +} + +void sub_812071C(u8 taskId) +{ + u8 r9; + + if (gTasks[taskId].data[1] < 24) + { + gTasks[taskId].data[1]++; + return; + } + + r9 = gActiveBank; + gActiveBank = gTasks[taskId].data[0]; + if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_811F864(gActiveBank, 0); + } + else + { + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_811F864(gActiveBank, 0); + gActiveBank ^= 2; + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + sub_811F864(gActiveBank, 0); + gActiveBank ^= 2; + } + gBattleBankFunc[gActiveBank] = sub_811DCA0; + gActiveBank = r9; + DestroyTask(taskId); +} + +void LinkPartnerHandlecmd48(void) +{ + if (gBattleBufferA[gActiveBank][1] != 0 && GetBankSide(gActiveBank) == 0) + { + LinkPartnerBufferExecCompleted(); + return; + } + + ewram17810[gActiveBank].unk0_0 = 1; + gUnknown_02024E68[gActiveBank] = sub_8044804( + gActiveBank, + (struct BattleInterfaceStruct2 *)&gBattleBufferA[gActiveBank][4], + gBattleBufferA[gActiveBank][1], + gBattleBufferA[gActiveBank][2]); + ewram17810[gActiveBank].unk5 = 0; + if (gBattleBufferA[gActiveBank][2] != 0) + ewram17810[gActiveBank].unk5 = 0x5D; + gBattleBankFunc[gActiveBank] = sub_81208E0; +} + +void sub_81208E0(void) +{ + if (ewram17810[gActiveBank].unk5++ >= 93) + { + ewram17810[gActiveBank].unk5 = 0; + LinkPartnerBufferExecCompleted(); + } +} + +void LinkPartnerHandlecmd49(void) +{ + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd50(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleSpriteInvisibility(void) +{ + if (AnimBankSpriteExists(gActiveBank) != 0) + { + gSprites[gObjectBankIDs[gActiveBank]].invisible = gBattleBufferA[gActiveBank][1]; + sub_8031F88(gActiveBank); + } + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleBattleAnimation(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + u8 r3 = gBattleBufferA[gActiveBank][1]; + u16 r4 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + + if (move_anim_start_t3(gActiveBank, gActiveBank, gActiveBank, r3, r4) != 0) + LinkPartnerBufferExecCompleted(); + else + gBattleBankFunc[gActiveBank] = sub_811E3B8; + } +} + +void LinkPartnerHandleLinkStandbyMsg(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandleResetActionMoveSelection(void) +{ + LinkPartnerBufferExecCompleted(); +} + +void LinkPartnerHandlecmd55(void) +{ + gBattleOutcome = gBattleBufferA[gActiveBank][1]; + FadeOutMapMusic(5); + BeginFastPaletteFade(3); + LinkPartnerBufferExecCompleted(); + gBattleBankFunc[gActiveBank] = sub_811E29C; +} + +void LinkPartnerHandlecmd56(void) +{ +} diff --git a/src/battle/battle_controller_opponent.c b/src/battle/battle_controller_opponent.c new file mode 100644 index 000000000..72b56b962 --- /dev/null +++ b/src/battle/battle_controller_opponent.c @@ -0,0 +1,2055 @@ +#include "global.h" +#include "battle.h" +#include "battle_interface.h" +#include "data2.h" +#include "battle_811DA74.h" +#include "battle_anim_813F0F4.h" +#include "link.h" +#include "m4a.h" +#include "main.h" +#include "palette.h" +#include "pokeball.h" +#include "pokemon.h" +#include "rom3.h" +#include "rom_8077ABC.h" +#include "sound.h" +#include "songs.h" +#include "sprite.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "util.h" + +struct UnknownStruct3 +{ + u16 moves[4]; + u8 pp[4]; + u8 ppBonuses; +}; + +extern u8 gActiveBank; +extern u8 gBattleBufferA[][0x200]; +extern u16 gBattlePartyID[]; +extern u8 gObjectBankIDs[]; +extern u8 gBattleMonForms[]; +extern struct SpriteTemplate gUnknown_02024E8C; +extern void (*gBattleBankFunc[])(void); +extern u8 gUnknown_0300434C[]; +extern u8 gHealthboxIDs[]; +extern u16 gBattleTypeFlags; +extern u16 gTrainerBattleOpponent; +extern u32 *gDisableStructMoveAnim; +extern u32 gMoveDmgMoveAnim; +extern u16 gMovePowerMoveAnim; +extern u8 gHappinessMoveAnim; +extern u16 gWeatherMoveAnim; +extern u32 gPID_perBank[]; +extern u8 gUnknown_0202F7C4; +extern u8 gAnimScriptActive; +extern void (*gAnimScriptCallback)(void); +extern struct Window gUnknown_03004210; +extern u16 gUnknown_030042A0; +extern u16 gUnknown_030042A4; +extern u8 gDisplayedStringBattle[]; +extern u8 gBankTarget; +extern u8 gAbsentBankFlags; +extern bool8 gDoingBattleAnim; +extern u16 gUnknown_02024DE8; +extern u8 gUnknown_02024E68[]; +extern MainCallback gPreBattleCallback1; +extern void (*const gOpponentBufferCommands[])(void); +extern struct MusicPlayerInfo gMPlay_SE1; +extern struct MusicPlayerInfo gMPlay_SE2; +extern struct MusicPlayerInfo gMPlay_BGM; +extern u32 gBattleExecBuffer; + +extern u8 sub_8077ABC(); +extern u8 sub_8077F68(); +extern u8 sub_8079E90(); +extern void sub_8033018(void); +extern void BattleLoadOpponentMonSprite(); +extern u8 GetBankIdentity(u8); +extern void sub_8032984(u8, u16); +extern void sub_80333D4(void); +extern void sub_80312F0(struct Sprite *); +extern u8 sub_8046400(); +extern void sub_8032A08(); +extern void sub_8043DB0(); +extern void sub_8033160(void); +extern u8 sub_8135FBC(void); +extern u8 get_trainer_class_pic_index(void); +extern void sub_80313A0(struct Sprite *); +extern void sub_8032B4C(void); +extern void sub_8031A6C(u16, u8); +extern void sub_8032B84(void); +extern void sub_8078B34(struct Sprite *); +extern void sub_8032BBC(void); +extern void oamt_add_pos2_onto_pos1(); +extern void StoreSpriteCallbackInData6(); +extern void sub_803311C(void); +extern void sub_8010384(struct Sprite *); +extern bool8 mplay_80342A4(u8); +extern u8 sub_8031720(); +extern void ExecuteMoveAnim(); +extern void sub_80326EC(); +extern void sub_8031F24(void); +extern void sub_80324BC(); +extern void BufferStringBattle(); +extern void sub_80331D0(void); +extern void sub_8036B0C(void); +extern u8 GetBankByPlayerAI(u8); +extern u8 sub_8036CD4(void); +extern void sub_80330C8(void); +extern void sub_8043D84(); +extern void sub_8045A5C(); +void sub_8033494(void); +extern void move_anim_start_t2_for_situation(); +extern void bx_blink_t7(void); +extern void sub_8047858(); +extern u8 GetBankSide(u8); +extern void sub_80E43C0(); +extern void sub_8044CA0(u8); +extern void nullsub_45(void); +extern void sub_8031B74(); +extern bool8 IsDoubleBattle(void); +extern void sub_8032E2C(void); +extern u8 AnimBankSpriteExists(); +extern u8 move_anim_start_t3(); +extern void sub_80334C0(void); + +// this file's functions + +void OpponentBufferExecCompleted(void); +void OpponentBufferRunCommand(void); +u32 sub_8033598(u8, u8 *); +void sub_8033E24(u8); +void sub_803495C(u8, u8); +void sub_8034B74(void); +void sub_8035238(void); +void sub_8035C10(struct Sprite *); +void sub_8035C44(u8); +void sub_8035E2C(void); +void sub_80332D0(void); + +void OpponentHandleGetAttributes(void); +void OpponentHandlecmd1(void); +void OpponentHandleSetAttributes(void); +void OpponentHandlecmd3(void); +void OpponentHandleLoadPokeSprite(void); +void OpponentHandleSendOutPoke(void); +void OpponentHandleReturnPokeToBall(void); +void OpponentHandleTrainerThrow(void); +void OpponentHandleTrainerSlide(void); +void OpponentHandleTrainerSlideBack(void); +void OpponentHandlecmd10(void); +void OpponentHandlecmd11(void); +void OpponentHandlecmd12(void); +void OpponentHandleBallThrow(void); +void OpponentHandlePuase(void); +void OpponentHandleMoveAnimation(void); +void OpponentHandlePrintString(void); +void OpponentHandlePrintStringPlayerOnly(void); +void OpponentHandlecmd18(void); +void OpponentHandlecmd19(void); +void OpponentHandlecmd20(void); +void OpponentHandleOpenBag(void); +void OpponentHandlecmd22(void); +void OpponentHandlecmd23(void); +void OpponentHandleHealthBarUpdate(void); +void OpponentHandleExpBarUpdate(void); +void OpponentHandleStatusIconUpdate(void); +void OpponentHandleStatusAnimation(void); +void OpponentHandleStatusXor(void); +void OpponentHandlecmd29(void); +void OpponentHandleDMATransfer(void); +void OpponentHandlecmd31(void); +void OpponentHandlecmd32(void); +void OpponentHandlecmd33(void); +void OpponentHandlecmd34(void); +void OpponentHandlecmd35(void); +void OpponentHandlecmd36(void); +void OpponentHandlecmd37(void); +void OpponentHandlecmd38(void); +void OpponentHandlecmd39(void); +void OpponentHandlecmd40(void); +void OpponentHandleHitAnimation(void); +void OpponentHandlecmd42(void); +void OpponentHandleEffectivenessSound(void); +void OpponentHandlecmd44(void); +void OpponentHandleFaintingCry(void); +void OpponentHandleIntroSlide(void); +void OpponentHandleTrainerBallThrow(void); +void OpponentHandlecmd48(void); +void OpponentHandlecmd49(void); +void OpponentHandlecmd50(void); +void OpponentHandleSpriteInvisibility(void); +void OpponentHandleBattleAnimation(void); +void OpponentHandleLinkStandbyMsg(void); +void OpponentHandleResetActionMoveSelection(void); +void OpponentHandlecmd55(void); +void OpponentHandlecmd56(void); + +// const data +typedef void (*BattleBufferCmd) (void); +static const BattleBufferCmd gOpponentBufferCommands[] = +{ + OpponentHandleGetAttributes, + OpponentHandlecmd1, + OpponentHandleSetAttributes, + OpponentHandlecmd3, + OpponentHandleLoadPokeSprite, + OpponentHandleSendOutPoke, + OpponentHandleReturnPokeToBall, + OpponentHandleTrainerThrow, + OpponentHandleTrainerSlide, + OpponentHandleTrainerSlideBack, + OpponentHandlecmd10, + OpponentHandlecmd11, + OpponentHandlecmd12, + OpponentHandleBallThrow, + OpponentHandlePuase, + OpponentHandleMoveAnimation, + OpponentHandlePrintString, + OpponentHandlePrintStringPlayerOnly, + OpponentHandlecmd18, + OpponentHandlecmd19, + OpponentHandlecmd20, + OpponentHandleOpenBag, + OpponentHandlecmd22, + OpponentHandlecmd23, + OpponentHandleHealthBarUpdate, + OpponentHandleExpBarUpdate, + OpponentHandleStatusIconUpdate, + OpponentHandleStatusAnimation, + OpponentHandleStatusXor, + OpponentHandlecmd29, + OpponentHandleDMATransfer, + OpponentHandlecmd31, + OpponentHandlecmd32, + OpponentHandlecmd33, + OpponentHandlecmd34, + OpponentHandlecmd35, + OpponentHandlecmd36, + OpponentHandlecmd37, + OpponentHandlecmd38, + OpponentHandlecmd39, + OpponentHandlecmd40, + OpponentHandleHitAnimation, + OpponentHandlecmd42, + OpponentHandleEffectivenessSound, + OpponentHandlecmd44, + OpponentHandleFaintingCry, + OpponentHandleIntroSlide, + OpponentHandleTrainerBallThrow, + OpponentHandlecmd48, + OpponentHandlecmd49, + OpponentHandlecmd50, + OpponentHandleSpriteInvisibility, + OpponentHandleBattleAnimation, + OpponentHandleLinkStandbyMsg, + OpponentHandleResetActionMoveSelection, + OpponentHandlecmd55, + OpponentHandlecmd56, +}; + +static const u8 sUnknownBytes[] = {0xB0, 0xB0, 0xC8, 0x98, 0x28, 0x28, 0x28, 0x20}; + +// code + +void nullsub_45(void) +{ +} + +void SetBankFuncToOpponentBufferRunCommand(void) +{ + gBattleBankFunc[gActiveBank] = OpponentBufferRunCommand; +} + +void OpponentBufferRunCommand(void) +{ + if (gBattleExecBuffer & gBitTable[gActiveBank]) + { + if (gBattleBufferA[gActiveBank][0] <= 0x38) + gOpponentBufferCommands[gBattleBufferA[gActiveBank][0]](); + else + OpponentBufferExecCompleted(); + } +} + +void sub_8032B4C(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + OpponentBufferExecCompleted(); +} + +// Duplicate of sub_8032B4C +void sub_8032B84(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + OpponentBufferExecCompleted(); +} + +void sub_8032BBC(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + { + sub_8031B74(gSprites[gObjectBankIDs[gActiveBank]].oam.affineParam); + gSprites[gObjectBankIDs[gActiveBank]].oam.tileNum = gSprites[gObjectBankIDs[gActiveBank]].data5; + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + OpponentBufferExecCompleted(); + } +} + +void sub_8032C4C(void) +{ + if ((--ewram17810[gActiveBank].unk9) == 0xFF) + { + ewram17810[gActiveBank].unk9 = 0; + OpponentBufferExecCompleted(); + } +} + +void sub_8032C88(void) +{ + bool8 r6 = FALSE; + + if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + { + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy) + r6 = TRUE; + } + else + { + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy + && gSprites[gHealthboxIDs[gActiveBank ^ 2]].callback == SpriteCallbackDummy) + r6 = TRUE; + } + if (IsCryPlayingOrClearCrySongs()) + r6 = FALSE; + + if (r6 && ewram17810[gActiveBank].unk1_0 && ewram17810[gActiveBank ^ 2].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + ewram17810[gActiveBank ^ 2].unk0_7 = 0; + ewram17810[gActiveBank ^ 2].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + m4aMPlayContinue(&gMPlay_BGM); + else + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 256); + ewram17810[gActiveBank].unk9 = 3; + gBattleBankFunc[gActiveBank] = sub_8032C4C; + } +} + +void sub_8032E2C(void) +{ + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank].unk0_7) + sub_8141828(gActiveBank, &gEnemyParty[gBattlePartyID[gActiveBank]]); + if (!ewram17810[gActiveBank ^ 2].unk0_3 && !ewram17810[gActiveBank ^ 2].unk0_7) + sub_8141828(gActiveBank ^ 2, &gEnemyParty[gBattlePartyID[gActiveBank ^ 2]]); + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank ^ 2].unk0_3) + { + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank ^ 2]]); + sub_8045A5C( + gHealthboxIDs[gActiveBank ^ 2], + &gEnemyParty[gBattlePartyID[gActiveBank ^ 2]], + 0); + sub_804777C(gActiveBank ^ 2); + sub_8043DFC(gHealthboxIDs[gActiveBank ^ 2]); + sub_8032984( + gActiveBank ^ 2, + GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank ^ 2]], MON_DATA_SPECIES)); + } + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + sub_8045A5C( + gHealthboxIDs[gActiveBank], + &gEnemyParty[gBattlePartyID[gActiveBank]], + 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + sub_8032984( + gActiveBank, + GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES)); + + ewram17840.unk9_0 = 0; + gBattleBankFunc[gActiveBank] = sub_8032C88; + } +} + +void sub_8033018(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].animEnded == TRUE + && gSprites[gObjectBankIDs[gActiveBank]].pos2.x == 0) + { + if (!ewram17810[gActiveBank].unk0_7) + { + sub_8141828(gActiveBank, &gEnemyParty[gBattlePartyID[gActiveBank]]); + return; + } + if (ewram17810[gActiveBank].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + OpponentBufferExecCompleted(); + return; + } + } +} + +void sub_80330C8(void) +{ + s16 r4 = sub_8045C78(gActiveBank, gHealthboxIDs[gActiveBank], 0, 0); + + sub_8043DFC(gHealthboxIDs[gActiveBank]); + if (r4 != -1) + sub_80440EC(gHealthboxIDs[gActiveBank], r4, 0); + else + OpponentBufferExecCompleted(); +} + +void sub_803311C(void) +{ + if (!gSprites[gObjectBankIDs[gActiveBank]].inUse) + { + sub_8043DB0(gHealthboxIDs[gActiveBank]); + OpponentBufferExecCompleted(); + } +} + +void sub_8033160(void) +{ + if (!ewram17810[gActiveBank].unk0_6) + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8032A08(gActiveBank); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + OpponentBufferExecCompleted(); + } +} + +void sub_80331D0(void) +{ + if (gUnknown_03004210.state == 0) + OpponentBufferExecCompleted(); +} + +void bx_blink_t7(void) +{ + u8 spriteId = gObjectBankIDs[gActiveBank]; + + if (gSprites[spriteId].data1 == 32) + { + gSprites[spriteId].data1 = 0; + gSprites[spriteId].invisible = FALSE; + gDoingBattleAnim = 0; + OpponentBufferExecCompleted(); + } + else + { + if (((u16)gSprites[spriteId].data1 % 4) == 0) + gSprites[spriteId].invisible ^= 1; + gSprites[spriteId].data1++; + } +} + +void sub_8033264(void) +{ + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy) + { + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + gBattleBankFunc[gActiveBank] = sub_80332D0; + } +} + +void sub_80332D0(void) +{ + if (!ewram17810[gActiveBank].unk0_6) + { + CreateTask(c3_0802FDF4, 10); + OpponentBufferExecCompleted(); + } +} + +void sub_8033308(void) +{ + if (ewram17810[gActiveBank].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], 0); + sub_8045A5C( + gHealthboxIDs[gActiveBank], + &gEnemyParty[gBattlePartyID[gActiveBank]], + 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + sub_8031F88(gActiveBank); + gBattleBankFunc[gActiveBank] = sub_8033264; + } +} + +void sub_80333D4(void) +{ + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank].unk0_7) + sub_8141828(gActiveBank, &gEnemyParty[gBattlePartyID[gActiveBank]]); + if (gSprites[gUnknown_0300434C[gActiveBank]].callback == SpriteCallbackDummy + && !ewram17810[gActiveBank].unk0_3) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + sub_8032984(gActiveBank, GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES)); + gBattleBankFunc[gActiveBank] = sub_8033308; + } +} + +void sub_8033494(void) +{ + if (!ewram17810[gActiveBank].unk0_4) + OpponentBufferExecCompleted(); +} + +void sub_80334C0(void) +{ + if (!ewram17810[gActiveBank].unk0_5) + OpponentBufferExecCompleted(); +} + +void OpponentBufferExecCompleted(void) +{ + gBattleBankFunc[gActiveBank] = OpponentBufferRunCommand; + gBattleExecBuffer &= ~gBitTable[gActiveBank]; +} + +void OpponentHandleGetAttributes(void) +{ + u8 buffer[256]; + int r6 = 0; + s32 i; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + r6 = sub_8033598(gBattlePartyID[gActiveBank], buffer); + } + else + { + u8 r4 = gBattleBufferA[gActiveBank][2]; + + for (i = 0; i < 6; i++) + { + if (r4 & 1) + r6 += sub_8033598(i, buffer + r6); + r4 >>= 1; + } + } + Emitcmd29(1, r6, buffer); + OpponentBufferExecCompleted(); +} + +u32 sub_8033598(u8 a, u8 *buffer) +{ + struct BattlePokemon battlePokemon; + struct UnknownStruct3 moveData; + u8 nickname[20]; + u8 *src; + s16 data16; + u32 data32; + s32 size = 0; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + battlePokemon.species = GetMonData(&gEnemyParty[a], MON_DATA_SPECIES); + battlePokemon.item = GetMonData(&gEnemyParty[a], MON_DATA_HELD_ITEM); + for (size = 0; size < 4; size++) + { + battlePokemon.moves[size] = GetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + size); + battlePokemon.pp[size] = GetMonData(&gEnemyParty[a], MON_DATA_PP1 + size); + } + battlePokemon.ppBonuses = GetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES); + battlePokemon.friendship = GetMonData(&gEnemyParty[a], MON_DATA_FRIENDSHIP); + battlePokemon.experience = GetMonData(&gEnemyParty[a], MON_DATA_EXP); + battlePokemon.hpIV = GetMonData(&gEnemyParty[a], MON_DATA_HP_IV); + battlePokemon.attackIV = GetMonData(&gEnemyParty[a], MON_DATA_ATK_IV); + battlePokemon.defenseIV = GetMonData(&gEnemyParty[a], MON_DATA_DEF_IV); + battlePokemon.speedIV = GetMonData(&gEnemyParty[a], MON_DATA_SPD_IV); + battlePokemon.spAttackIV = GetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV); + battlePokemon.spDefenseIV = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV); + battlePokemon.personality = GetMonData(&gEnemyParty[a], MON_DATA_PERSONALITY); + battlePokemon.status1 = GetMonData(&gEnemyParty[a], MON_DATA_STATUS); + battlePokemon.level = GetMonData(&gEnemyParty[a], MON_DATA_LEVEL); + battlePokemon.hp = GetMonData(&gEnemyParty[a], MON_DATA_HP); + battlePokemon.maxHP = GetMonData(&gEnemyParty[a], MON_DATA_MAX_HP); + battlePokemon.attack = GetMonData(&gEnemyParty[a], MON_DATA_ATK); + battlePokemon.defense = GetMonData(&gEnemyParty[a], MON_DATA_DEF); + battlePokemon.speed = GetMonData(&gEnemyParty[a], MON_DATA_SPD); + battlePokemon.spAttack = GetMonData(&gEnemyParty[a], MON_DATA_SPATK); + battlePokemon.spDefense = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF); + battlePokemon.isEgg = GetMonData(&gEnemyParty[a], MON_DATA_IS_EGG); + battlePokemon.altAbility = GetMonData(&gEnemyParty[a], MON_DATA_ALT_ABILITY); + battlePokemon.otId = GetMonData(&gEnemyParty[a], MON_DATA_OT_ID); + GetMonData(&gEnemyParty[a], MON_DATA_NICKNAME, nickname); + StringCopy10(battlePokemon.nickname, nickname); + GetMonData(&gEnemyParty[a], MON_DATA_OT_NAME, battlePokemon.otName); + src = (u8 *)&battlePokemon; + for (size = 0; size < sizeof(battlePokemon); size++) + buffer[size] = src[size]; + break; + case 1: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_SPECIES); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 2: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_HELD_ITEM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 3: + for (size = 0; size < 4; size++) + { + moveData.moves[size] = GetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + size); + moveData.pp[size] = GetMonData(&gEnemyParty[a], MON_DATA_PP1 + size); + } + moveData.ppBonuses = GetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES); + src = (u8 *)&moveData; + for (size = 0; size < sizeof(moveData); size++) + buffer[size] = src[size]; + break; + case 4: + case 5: + case 6: + case 7: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 8: + for (size = 0; size < 4; size++) + buffer[size] = GetMonData(&gEnemyParty[a], MON_DATA_PP1 + size); + buffer[size] = GetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES); + size++; + break; + case 9: + case 10: + case 11: + case 12: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9); + size = 1; + break; + case 17: + data32 = GetMonData(&gEnemyParty[a], MON_DATA_OT_ID); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 18: + data32 = GetMonData(&gEnemyParty[a], MON_DATA_EXP); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 19: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_HP_EV); + size = 1; + break; + case 20: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_ATK_EV); + size = 1; + break; + case 21: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_DEF_EV); + size = 1; + break; + case 22: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPD_EV); + size = 1; + break; + case 23: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPATK_EV); + size = 1; + break; + case 24: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF_EV); + size = 1; + break; + case 25: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_FRIENDSHIP); + size = 1; + break; + case 26: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_POKERUS); + size = 1; + break; + case 27: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_MET_LOCATION); + size = 1; + break; + case 28: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_MET_LEVEL); + size = 1; + break; + case 29: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_MET_GAME); + size = 1; + break; + case 30: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_POKEBALL); + size = 1; + break; + case 31: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_HP_IV); + buffer[1] = GetMonData(&gEnemyParty[a], MON_DATA_ATK_IV); + buffer[2] = GetMonData(&gEnemyParty[a], MON_DATA_DEF_IV); + buffer[3] = GetMonData(&gEnemyParty[a], MON_DATA_SPD_IV); + buffer[4] = GetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV); + buffer[5] = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV); + size = 6; + break; + case 32: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_HP_IV); + size = 1; + break; + case 33: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_ATK_IV); + size = 1; + break; + case 34: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_DEF_IV); + size = 1; + break; + case 35: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPD_IV); + size = 1; + break; + case 36: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV); + size = 1; + break; + case 37: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV); + size = 1; + break; + case 38: + data32 = GetMonData(&gEnemyParty[a], MON_DATA_PERSONALITY); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 39: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_CHECKSUM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 40: + data32 = GetMonData(&gEnemyParty[a], MON_DATA_STATUS); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 41: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_LEVEL); + size = 1; + break; + case 42: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 43: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_MAX_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 44: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_ATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 45: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_DEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 46: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_SPD); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 47: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_SPATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 48: + data16 = GetMonData(&gEnemyParty[a], MON_DATA_SPDEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 49: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_COOL); + size = 1; + break; + case 50: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_BEAUTY); + size = 1; + break; + case 51: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_CUTE); + size = 1; + break; + case 52: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SMART); + size = 1; + break; + case 53: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_TOUGH); + size = 1; + break; + case 54: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SHEEN); + size = 1; + break; + case 55: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_COOL_RIBBON); + size = 1; + break; + case 56: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_BEAUTY_RIBBON); + size = 1; + break; + case 57: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_CUTE_RIBBON); + size = 1; + break; + case 58: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_SMART_RIBBON); + size = 1; + break; + case 59: + buffer[0] = GetMonData(&gEnemyParty[a], MON_DATA_TOUGH_RIBBON); + size = 1; + break; + } + return size; +} + +void OpponentHandlecmd1(void) +{ + struct BattlePokemon buffer; + u8 *src = (u8 *)&gEnemyParty[gBattlePartyID[gActiveBank]] + gBattleBufferA[gActiveBank][1]; + u8 *dst = (u8 *)&buffer + gBattleBufferA[gActiveBank][1]; + u8 i; + + for (i = 0; i < gBattleBufferA[gActiveBank][2]; i++) + dst[i] = src[i]; + Emitcmd29(1, gBattleBufferA[gActiveBank][2], dst); + OpponentBufferExecCompleted(); +} + +void OpponentHandleSetAttributes(void) +{ + u8 i; + u8 r4; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + sub_8033E24(gBattlePartyID[gActiveBank]); + } + else + { + r4 = gBattleBufferA[gActiveBank][2]; + for (i = 0; i < 6; i++) + { + if (r4 & 1) + sub_8033E24(i); + r4 >>= 1; + } + } + OpponentBufferExecCompleted(); +} + +void sub_8033E24(u8 a) +{ + struct BattlePokemon *battlePokemon = (struct BattlePokemon *)&gBattleBufferA[gActiveBank][3]; + struct UnknownStruct3 *moveData = (struct UnknownStruct3 *)&gBattleBufferA[gActiveBank][3]; + s32 i; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + { + u8 iv; + + SetMonData(&gEnemyParty[a], MON_DATA_SPECIES, (u8 *)&battlePokemon->species); + SetMonData(&gEnemyParty[a], MON_DATA_HELD_ITEM, (u8 *)&battlePokemon->item); + for (i = 0; i < 4; i++) + { + SetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + i, (u8 *)&battlePokemon->moves[i]); + SetMonData(&gEnemyParty[a], MON_DATA_PP1 + i, (u8 *)&battlePokemon->pp[i]); + } + SetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES, (u8 *)&battlePokemon->ppBonuses); + SetMonData(&gEnemyParty[a], MON_DATA_FRIENDSHIP, (u8 *)&battlePokemon->friendship); + SetMonData(&gEnemyParty[a], MON_DATA_EXP, (u8 *)&battlePokemon->experience); + iv = battlePokemon->hpIV; + SetMonData(&gEnemyParty[a], MON_DATA_HP_IV, (u8 *)&iv); + iv = battlePokemon->attackIV; + SetMonData(&gEnemyParty[a], MON_DATA_ATK_IV, (u8 *)&iv); + iv = battlePokemon->defenseIV; + SetMonData(&gEnemyParty[a], MON_DATA_DEF_IV, (u8 *)&iv); + iv = battlePokemon->speedIV; + SetMonData(&gEnemyParty[a], MON_DATA_SPD_IV, (u8 *)&iv); + iv = battlePokemon->spAttackIV; + SetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV, (u8 *)&iv); + iv = battlePokemon->spDefenseIV; + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV, (u8 *)&iv); + SetMonData(&gEnemyParty[a], MON_DATA_PERSONALITY, (u8 *)&battlePokemon->personality); + SetMonData(&gEnemyParty[a], MON_DATA_STATUS, (u8 *)&battlePokemon->status1); + SetMonData(&gEnemyParty[a], MON_DATA_LEVEL, (u8 *)&battlePokemon->level); + SetMonData(&gEnemyParty[a], MON_DATA_HP, (u8 *)&battlePokemon->hp); + SetMonData(&gEnemyParty[a], MON_DATA_MAX_HP, (u8 *)&battlePokemon->maxHP); + SetMonData(&gEnemyParty[a], MON_DATA_ATK, (u8 *)&battlePokemon->attack); + SetMonData(&gEnemyParty[a], MON_DATA_DEF, (u8 *)&battlePokemon->defense); + SetMonData(&gEnemyParty[a], MON_DATA_SPD, (u8 *)&battlePokemon->speed); + SetMonData(&gEnemyParty[a], MON_DATA_SPATK, (u8 *)&battlePokemon->spAttack); + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF, (u8 *)&battlePokemon->spDefense); + } + break; + case 1: + SetMonData(&gEnemyParty[a], MON_DATA_SPECIES, &gBattleBufferA[gActiveBank][3]); + break; + case 2: + SetMonData(&gEnemyParty[a], MON_DATA_HELD_ITEM, &gBattleBufferA[gActiveBank][3]); + break; + case 3: + for (i = 0; i < 4; i++) + { + SetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + i, (u8 *)&moveData->moves[i]); + SetMonData(&gEnemyParty[a], MON_DATA_PP1 + i, (u8 *)&moveData->pp[i]); + } + SetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES, &moveData->ppBonuses); + break; + case 4: + case 5: + case 6: + case 7: + SetMonData(&gEnemyParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4, &gBattleBufferA[gActiveBank][3]); + break; + case 8: + SetMonData(&gEnemyParty[a], MON_DATA_PP1, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gEnemyParty[a], MON_DATA_PP2, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gEnemyParty[a], MON_DATA_PP3, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gEnemyParty[a], MON_DATA_PP4, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gEnemyParty[a], MON_DATA_PP_BONUSES, &gBattleBufferA[gActiveBank][7]); + break; + case 9: + case 10: + case 11: + case 12: + SetMonData(&gEnemyParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9, &gBattleBufferA[gActiveBank][3]); + break; + case 17: + SetMonData(&gEnemyParty[a], MON_DATA_OT_ID, &gBattleBufferA[gActiveBank][3]); + break; + case 18: + SetMonData(&gEnemyParty[a], MON_DATA_EXP, &gBattleBufferA[gActiveBank][3]); + break; + case 19: + SetMonData(&gEnemyParty[a], MON_DATA_HP_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 20: + SetMonData(&gEnemyParty[a], MON_DATA_ATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 21: + SetMonData(&gEnemyParty[a], MON_DATA_DEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 22: + SetMonData(&gEnemyParty[a], MON_DATA_SPD_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 23: + SetMonData(&gEnemyParty[a], MON_DATA_SPATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 24: + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 25: + SetMonData(&gEnemyParty[a], MON_DATA_FRIENDSHIP, &gBattleBufferA[gActiveBank][3]); + break; + case 26: + SetMonData(&gEnemyParty[a], MON_DATA_POKERUS, &gBattleBufferA[gActiveBank][3]); + break; + case 27: + SetMonData(&gEnemyParty[a], MON_DATA_MET_LOCATION, &gBattleBufferA[gActiveBank][3]); + break; + case 28: + SetMonData(&gEnemyParty[a], MON_DATA_MET_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 29: + SetMonData(&gEnemyParty[a], MON_DATA_MET_GAME, &gBattleBufferA[gActiveBank][3]); + break; + case 30: + SetMonData(&gEnemyParty[a], MON_DATA_POKEBALL, &gBattleBufferA[gActiveBank][3]); + break; + case 31: + SetMonData(&gEnemyParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gEnemyParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gEnemyParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gEnemyParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][7]); + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][8]); + break; + case 32: + SetMonData(&gEnemyParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 33: + SetMonData(&gEnemyParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 34: + SetMonData(&gEnemyParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 35: + SetMonData(&gEnemyParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 36: + SetMonData(&gEnemyParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 37: + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 38: + SetMonData(&gEnemyParty[a], MON_DATA_PERSONALITY, &gBattleBufferA[gActiveBank][3]); + break; + case 39: + SetMonData(&gEnemyParty[a], MON_DATA_CHECKSUM, &gBattleBufferA[gActiveBank][3]); + break; + case 40: + SetMonData(&gEnemyParty[a], MON_DATA_STATUS, &gBattleBufferA[gActiveBank][3]); + break; + case 41: + SetMonData(&gEnemyParty[a], MON_DATA_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 42: + SetMonData(&gEnemyParty[a], MON_DATA_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 43: + SetMonData(&gEnemyParty[a], MON_DATA_MAX_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 44: + SetMonData(&gEnemyParty[a], MON_DATA_ATK, &gBattleBufferA[gActiveBank][3]); + break; + case 45: + SetMonData(&gEnemyParty[a], MON_DATA_DEF, &gBattleBufferA[gActiveBank][3]); + break; + case 46: + SetMonData(&gEnemyParty[a], MON_DATA_SPD, &gBattleBufferA[gActiveBank][3]); + break; + case 47: + SetMonData(&gEnemyParty[a], MON_DATA_SPATK, &gBattleBufferA[gActiveBank][3]); + break; + case 48: + SetMonData(&gEnemyParty[a], MON_DATA_SPDEF, &gBattleBufferA[gActiveBank][3]); + break; + case 49: + SetMonData(&gEnemyParty[a], MON_DATA_COOL, &gBattleBufferA[gActiveBank][3]); + break; + case 50: + SetMonData(&gEnemyParty[a], MON_DATA_BEAUTY, &gBattleBufferA[gActiveBank][3]); + break; + case 51: + SetMonData(&gEnemyParty[a], MON_DATA_CUTE, &gBattleBufferA[gActiveBank][3]); + break; + case 52: + SetMonData(&gEnemyParty[a], MON_DATA_SMART, &gBattleBufferA[gActiveBank][3]); + break; + case 53: + SetMonData(&gEnemyParty[a], MON_DATA_TOUGH, &gBattleBufferA[gActiveBank][3]); + break; + case 54: + SetMonData(&gEnemyParty[a], MON_DATA_SHEEN, &gBattleBufferA[gActiveBank][3]); + break; + case 55: + SetMonData(&gEnemyParty[a], MON_DATA_COOL_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 56: + SetMonData(&gEnemyParty[a], MON_DATA_BEAUTY_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 57: + SetMonData(&gEnemyParty[a], MON_DATA_CUTE_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 58: + SetMonData(&gEnemyParty[a], MON_DATA_SMART_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 59: + SetMonData(&gEnemyParty[a], MON_DATA_TOUGH_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + } +} + +void OpponentHandlecmd3(void) +{ + u8 *dst; + u8 i; + + dst = (u8 *)&gEnemyParty[gBattlePartyID[gActiveBank]] + gBattleBufferA[gActiveBank][1]; + for (i = 0; i < gBattleBufferA[gActiveBank][2]; i++) + dst[i] = gBattleBufferA[gActiveBank][3 + i]; + OpponentBufferExecCompleted(); +} + +void OpponentHandleLoadPokeSprite(void) +{ + u16 species = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES); + + BattleLoadOpponentMonSprite(&gEnemyParty[gBattlePartyID[gActiveBank]], gActiveBank); + GetMonSpriteTemplate_803C56C(species, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + sub_8077ABC(gActiveBank, 2), + sub_8077F68(gActiveBank), + sub_8079E90(gActiveBank)); + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = -240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].data2 = species; + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], gBattleMonForms[gActiveBank]); + sub_8032984(gActiveBank, GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES)); + gBattleBankFunc[gActiveBank] = sub_8033018; +} + +void OpponentHandleSendOutPoke(void) +{ + gBattlePartyID[gActiveBank] = gBattleBufferA[gActiveBank][1]; + + sub_803495C(gActiveBank, gBattleBufferA[gActiveBank][2]); + gBattleBankFunc[gActiveBank] = sub_80333D4; +} + +void sub_803495C(u8 a, u8 b) +{ + u16 species; + + sub_8032AA8(a, b); + gBattlePartyID[a] = gBattleBufferA[a][1]; + species = GetMonData(&gEnemyParty[gBattlePartyID[a]], MON_DATA_SPECIES); + gUnknown_0300434C[a] = CreateInvisibleSpriteWithCallback(sub_80312F0); + BattleLoadOpponentMonSprite(&gEnemyParty[gBattlePartyID[a]], a); + GetMonSpriteTemplate_803C56C(species, GetBankIdentity(a)); + gObjectBankIDs[a] = CreateSprite( + &gUnknown_02024E8C, + sub_8077ABC(a, 2), + sub_8077F68(a), + sub_8079E90(a)); + gSprites[gObjectBankIDs[a]].data0 = a; + gSprites[gObjectBankIDs[a]].data2 = species; + gSprites[gUnknown_0300434C[a]].data1 = gObjectBankIDs[a]; + gSprites[gObjectBankIDs[a]].oam.paletteNum = a; + StartSpriteAnim(&gSprites[gObjectBankIDs[a]], gBattleMonForms[a]); + gSprites[gObjectBankIDs[a]].invisible = TRUE; + gSprites[gObjectBankIDs[a]].callback = SpriteCallbackDummy; + gSprites[gUnknown_0300434C[a]].data0 = sub_8046400(0, 0xFE); +} + +void OpponentHandleReturnPokeToBall(void) +{ + if (gBattleBufferA[gActiveBank][1] == 0) + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_8034B74; + } + else + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8032A08(gActiveBank); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + OpponentBufferExecCompleted(); + } +} + +void sub_8034B74(void) +{ + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (!ewram17810[gActiveBank].unk0_6) + { + ewram17810[gActiveBank].unk4 = 0; + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 2); + gBattleBankFunc[gActiveBank] = sub_8033160; + } + break; + } +} + +void OpponentHandleTrainerThrow(void) +{ + u32 trainerPicIndex; + + if (gTrainerBattleOpponent == 0x400) + trainerPicIndex = GetSecretBaseTrainerPicIndex(); + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + trainerPicIndex = get_trainer_class_pic_index(); + else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) + trainerPicIndex = sub_8135FBC(); + else + trainerPicIndex = gTrainers[gTrainerBattleOpponent].trainerPic; + + sub_8031A6C(trainerPicIndex, gActiveBank); + GetMonSpriteTemplate_803C5A0(trainerPicIndex, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + 0xB0, + 40 + 4 * (8 - gTrainerFrontPicCoords[trainerPicIndex].coords), + sub_8079E90(gActiveBank)); + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = -240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = 2; + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerFrontPicPaletteTable[trainerPicIndex].tag); + gSprites[gObjectBankIDs[gActiveBank]].data5 = gSprites[gObjectBankIDs[gActiveBank]].oam.tileNum; + gSprites[gObjectBankIDs[gActiveBank]].oam.tileNum = GetSpriteTileStartByTag(gTrainerFrontPicTable[trainerPicIndex].tag); + gSprites[gObjectBankIDs[gActiveBank]].oam.affineParam = trainerPicIndex; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_8032B4C; +} + +void OpponentHandleTrainerSlide(void) +{ + u32 trainerPicIndex; + + if (gTrainerBattleOpponent == 0x400) + trainerPicIndex = GetSecretBaseTrainerPicIndex(); + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + trainerPicIndex = get_trainer_class_pic_index(); + else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) + trainerPicIndex = sub_8135FBC(); + else + trainerPicIndex = gTrainers[gTrainerBattleOpponent].trainerPic; + + sub_8031A6C(trainerPicIndex, gActiveBank); + GetMonSpriteTemplate_803C5A0(trainerPicIndex, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + 0xB0, + 40 + 4 * (8 - gTrainerFrontPicCoords[trainerPicIndex].coords), + 0x1E); + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = 96; + gSprites[gObjectBankIDs[gActiveBank]].pos1.x += 32; + gSprites[gObjectBankIDs[gActiveBank]].data0 = -2; + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerFrontPicPaletteTable[trainerPicIndex].tag); + gSprites[gObjectBankIDs[gActiveBank]].data5 = gSprites[gObjectBankIDs[gActiveBank]].oam.tileNum; + gSprites[gObjectBankIDs[gActiveBank]].oam.tileNum = GetSpriteTileStartByTag(gTrainerFrontPicTable[trainerPicIndex].tag); + gSprites[gObjectBankIDs[gActiveBank]].oam.affineParam = trainerPicIndex; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_8032B84; +} + +void OpponentHandleTrainerSlideBack(void) +{ + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 35; + gSprites[gObjectBankIDs[gActiveBank]].data2 = 280; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], SpriteCallbackDummy); + gBattleBankFunc[gActiveBank] = sub_8032BBC; +} + +void OpponentHandlecmd10(void) +{ + if (ewram17810[gActiveBank].unk4 == 0) + { + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4++; + } + else if (!ewram17810[gActiveBank].unk0_6) + { + ewram17810[gActiveBank].unk4 = 0; + PlaySE12WithPanning(SE_POKE_DEAD, 63); + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8010384; + gBattleBankFunc[gActiveBank] = sub_803311C; + } +} + +void OpponentHandlecmd11(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd12(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandleBallThrow(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlePuase(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandleMoveAnimation(void) +{ + if (!mplay_80342A4(gActiveBank)) + { + u32 r0 = gBattleBufferA[gActiveBank][1] + | (gBattleBufferA[gActiveBank][2] << 8); + + gUnknown_0202F7C4 = gBattleBufferA[gActiveBank][3]; + gMovePowerMoveAnim = gBattleBufferA[gActiveBank][4] + | (gBattleBufferA[gActiveBank][5] << 8); + gMoveDmgMoveAnim = gBattleBufferA[gActiveBank][6] + | (gBattleBufferA[gActiveBank][7] << 8) + | (gBattleBufferA[gActiveBank][8] << 16) + | (gBattleBufferA[gActiveBank][9] << 24); + gHappinessMoveAnim = gBattleBufferA[gActiveBank][10]; + gWeatherMoveAnim = gBattleBufferA[gActiveBank][12] + | (gBattleBufferA[gActiveBank][13] << 8); + gDisableStructMoveAnim = (u32 *)&gBattleBufferA[gActiveBank][16]; + gPID_perBank[gActiveBank] = *gDisableStructMoveAnim; + + // Dead code. sub_8031720 always returns 0. + if (sub_8031720(r0, gUnknown_0202F7C4) != 0) + { + OpponentBufferExecCompleted(); + } + else + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_8035238; + } + } +} + +void sub_8035238(void) +{ + u16 r4 = gBattleBufferA[gActiveBank][1] + | (gBattleBufferA[gActiveBank][2] << 8); + u8 r7 = gBattleBufferA[gActiveBank][11]; + + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite && !ewram17800[gActiveBank].unk0_3) + { + ewram17800[gActiveBank].unk0_3 = 1; + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + } + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (!ewram17810[gActiveBank].unk0_6) + { + sub_80326EC(0); + ExecuteMoveAnim(r4); + ewram17810[gActiveBank].unk4 = 2; + } + break; + case 2: + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + sub_80326EC(1); + if ((ewram17800[gActiveBank].substituteSprite) && r7 <= 1) + { + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + ewram17800[gActiveBank].unk0_3 = 0; + } + ewram17810[gActiveBank].unk4 = 3; + } + break; + case 3: + if (!ewram17810[gActiveBank].unk0_6) + { + sub_8031F24(); + sub_80324BC( + gActiveBank, + gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + ewram17810[gActiveBank].unk4 = 0; + OpponentBufferExecCompleted(); + } + break; + } +} + +void OpponentHandlePrintString(void) +{ + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + BufferStringBattle(*(u16 *)&gBattleBufferA[gActiveBank][2]); + sub_8002EB0(&gUnknown_03004210, gDisplayedStringBattle, 144, 2, 15); + gBattleBankFunc[gActiveBank] = sub_80331D0; +} + +void OpponentHandlePrintStringPlayerOnly(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd18(void) +{ + sub_8036B0C(); + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd19(void) +{ + OpponentBufferExecCompleted(); +} + +#ifdef NONMATCHING +void OpponentHandlecmd20(void) +{ + u16 r4; + // Needed to match closer + struct {u16 moves[4];} *r5 = (void *)&gBattleBufferA[gActiveBank][4]; + + if (gBattleTypeFlags & 0x498) + { + BattleAI_SetupAIData(); + r4 = BattleAI_GetAIActionToUse(); + switch (r4) + { + case 5: + Emitcmd33(1, 4, 0); + break; + case 4: + Emitcmd33(1, 3, 0); + break; + default: + if (gBattleMoves[r5->moves[r4]].target & 0x12) + gBankTarget = gActiveBank; + if (gBattleMoves[r5->moves[r4]].target & 8) + { + gBankTarget = GetBankByPlayerAI(0); + if (gAbsentBankFlags & gBitTable[gBankTarget]) + gBankTarget = GetBankByPlayerAI(2); + } + r4 |= gBankTarget << 8; + Emitcmd33(1, 10, r4); + break; + } + OpponentBufferExecCompleted(); + } + else + { + u16 r2; + + do + { + // Can't for the life of me get this to match. + r4 = Random() % 4; + r2 = r5->moves[r4]; + } while (r2 == 0); + + if (gBattleMoves[r2].target & 0x12) + { + r4 |= gActiveBank << 8; + Emitcmd33(1, 10, r4); + } + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + u16 r2 = GetBankByPlayerAI(Random() & 2) << 8; + + Emitcmd33(1, 10, r4 | r2); + } + else + { + u16 r2 = GetBankByPlayerAI(0) << 8; + + Emitcmd33(1, 10, r4 | r2); + } + OpponentBufferExecCompleted(); + } +} +#else +__attribute__((naked)) +void OpponentHandlecmd20(void) +{ + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + ldr r6, _0803545C @ =gActiveBank\n\ + ldrb r0, [r6]\n\ + lsls r0, 9\n\ + ldr r1, _08035460 @ =gUnknown_02023A64\n\ + adds r5, r0, r1\n\ + ldr r0, _08035464 @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x93\n\ + lsls r0, 3\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080354F8\n\ + bl BattleAI_SetupAIData\n\ + bl BattleAI_GetAIActionToUse\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r4, 0x4\n\ + beq _08035468\n\ + cmp r4, 0x5\n\ + bne _08035474\n\ + movs r0, 0x1\n\ + movs r1, 0x4\n\ + b _0803546C\n\ + .align 2, 0\n\ +_0803545C: .4byte gActiveBank\n\ +_08035460: .4byte gUnknown_02023A64\n\ +_08035464: .4byte gBattleTypeFlags\n\ +_08035468:\n\ + movs r0, 0x1\n\ + movs r1, 0x3\n\ +_0803546C:\n\ + movs r2, 0\n\ + bl Emitcmd33\n\ + b _080354E0\n\ +_08035474:\n\ + ldr r3, _080354E8 @ =gBattleMoves\n\ + lsls r0, r4, 1\n\ + adds r2, r5, r0\n\ + ldrh r1, [r2]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldrb r1, [r0, 0x6]\n\ + movs r0, 0x12\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08035494\n\ + ldr r1, _080354EC @ =gBankTarget\n\ + ldrb r0, [r6]\n\ + strb r0, [r1]\n\ +_08035494:\n\ + ldrh r1, [r2]\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r3\n\ + ldrb r1, [r0, 0x6]\n\ + movs r0, 0x8\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080354CE\n\ + movs r0, 0\n\ + bl GetBankByPlayerAI\n\ + ldr r5, _080354EC @ =gBankTarget\n\ + strb r0, [r5]\n\ + ldr r0, _080354F0 @ =gAbsentBankFlags\n\ + ldrb r1, [r0]\n\ + ldr r2, _080354F4 @ =gBitTable\n\ + ldrb r0, [r5]\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldr r0, [r0]\n\ + ands r1, r0\n\ + cmp r1, 0\n\ + beq _080354CE\n\ + movs r0, 0x2\n\ + bl GetBankByPlayerAI\n\ + strb r0, [r5]\n\ +_080354CE:\n\ + ldr r0, _080354EC @ =gBankTarget\n\ + ldrb r0, [r0]\n\ + lsls r0, 8\n\ + orrs r4, r0\n\ + movs r0, 0x1\n\ + movs r1, 0xA\n\ + adds r2, r4, 0\n\ + bl Emitcmd33\n\ +_080354E0:\n\ + bl OpponentBufferExecCompleted\n\ + b _0803558A\n\ + .align 2, 0\n\ +_080354E8: .4byte gBattleMoves\n\ +_080354EC: .4byte gBankTarget\n\ +_080354F0: .4byte gAbsentBankFlags\n\ +_080354F4: .4byte gBitTable\n\ +_080354F8:\n\ + movs r6, 0x3\n\ +_080354FA:\n\ + bl Random\n\ + adds r4, r0, 0\n\ + ands r4, r6\n\ + lsls r0, r4, 1\n\ + adds r0, r5, r0\n\ + ldrh r2, [r0]\n\ + cmp r2, 0\n\ + beq _080354FA\n\ + ldr r1, _08035534 @ =gBattleMoves\n\ + lsls r0, r2, 1\n\ + adds r0, r2\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r1, [r0, 0x6]\n\ + movs r0, 0x12\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0803553C\n\ + ldr r0, _08035538 @ =gActiveBank\n\ + ldrb r0, [r0]\n\ + lsls r0, 8\n\ + orrs r4, r0\n\ + movs r0, 0x1\n\ + movs r1, 0xA\n\ + adds r2, r4, 0\n\ + bl Emitcmd33\n\ + b _08035586\n\ + .align 2, 0\n\ +_08035534: .4byte gBattleMoves\n\ +_08035538: .4byte gActiveBank\n\ +_0803553C:\n\ + ldr r0, _0803556C @ =gBattleTypeFlags\n\ + ldrh r1, [r0]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08035570\n\ + bl Random\n\ + movs r1, 0x2\n\ + ands r1, r0\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + adds r0, r1, 0\n\ + bl GetBankByPlayerAI\n\ + adds r2, r0, 0\n\ + lsls r2, 24\n\ + lsrs r2, 16\n\ + orrs r2, r4\n\ + movs r0, 0x1\n\ + movs r1, 0xA\n\ + bl Emitcmd33\n\ + b _08035586\n\ + .align 2, 0\n\ +_0803556C: .4byte gBattleTypeFlags\n\ +_08035570:\n\ + movs r0, 0\n\ + bl GetBankByPlayerAI\n\ + adds r2, r0, 0\n\ + lsls r2, 24\n\ + lsrs r2, 16\n\ + orrs r2, r4\n\ + movs r0, 0x1\n\ + movs r1, 0xA\n\ + bl Emitcmd33\n\ +_08035586:\n\ + bl OpponentBufferExecCompleted\n\ +_0803558A:\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided\n"); +} +#endif + +void OpponentHandleOpenBag(void) +{ + // What is this? + Emitcmd35(1, ewram[0x160D4 + gActiveBank / 2 * 2]); + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd22(void) +{ + s32 r4; + + if (ewram[0x160C8 + GetBankIdentity(gActiveBank) / 2] == 6) + { + u8 r6; + u8 r5; + + r4 = sub_8036CD4(); + if (r4 == 6) + { + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + { + r5 = GetBankByPlayerAI(1); + r6 = r5; + } + else + { + r6 = GetBankByPlayerAI(1); + r5 = GetBankByPlayerAI(3); + } + for (r4 = 0; r4 < 6; r4++) + { + if (GetMonData(&gEnemyParty[r4], MON_DATA_HP) != 0 + && r4 != gBattlePartyID[r6] + && r4 != gBattlePartyID[r5]) + break; + } + } + } + else + { + r4 = ewram[0x160C8 + GetBankIdentity(gActiveBank) / 2]; + ewram[0x160C8 + GetBankIdentity(gActiveBank) / 2] = 6; + } + ewram[0x16068 + gActiveBank] = r4; + Emitcmd34(1, r4, 0); + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd23(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandleHealthBarUpdate(void) +{ + s16 r7; + + load_gfxc_health_bar(0); + r7 = (gBattleBufferA[gActiveBank][3] << 8) | gBattleBufferA[gActiveBank][2]; + if (r7 != 0x7FFF) + { + u32 maxHP = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + u32 hp = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, hp, r7); + } + else + { + u32 maxHP = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, 0, r7); + } + gBattleBankFunc[gActiveBank] = sub_80330C8; +} + +void OpponentHandleExpBarUpdate(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandleStatusIconUpdate(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + sub_8045A5C(gHealthboxIDs[gActiveBank], &gEnemyParty[gBattlePartyID[gActiveBank]], 9); + ewram17810[gActiveBank].unk0_4 = 0; + gBattleBankFunc[gActiveBank] = sub_8033494; + } +} + +void OpponentHandleStatusAnimation(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + move_anim_start_t2_for_situation( + gBattleBufferA[gActiveBank][1], + gBattleBufferA[gActiveBank][2] + | (gBattleBufferA[gActiveBank][3] << 8) + | (gBattleBufferA[gActiveBank][4] << 16) + | (gBattleBufferA[gActiveBank][5] << 24)); + gBattleBankFunc[gActiveBank] = sub_8033494; + } +} + +void OpponentHandleStatusXor(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd29(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandleDMATransfer(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd31(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd32(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd33(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd34(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd35(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd36(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd37(void) +{ + gUnknown_020238C8.unk0_0 = 0; + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd38(void) +{ + gUnknown_020238C8.unk0_0 = gBattleBufferA[gActiveBank][1]; + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd39(void) +{ + gUnknown_020238C8.unk0_7 = 0; + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd40(void) +{ + gUnknown_020238C8.unk0_7 ^= 1; + OpponentBufferExecCompleted(); +} + +void OpponentHandleHitAnimation(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].invisible == TRUE) + { + OpponentBufferExecCompleted(); + } + else + { + gDoingBattleAnim = TRUE; + gSprites[gObjectBankIDs[gActiveBank]].data1 = 0; + sub_8047858(gActiveBank); + gBattleBankFunc[gActiveBank] = bx_blink_t7; + } +} + +void OpponentHandlecmd42(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandleEffectivenessSound(void) +{ + s8 pan; + + if (GetBankSide(gActiveBank) == 0) + pan = -64; + else + pan = 63; + PlaySE12WithPanning(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8), pan); + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd44(void) +{ + PlayFanfare(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + OpponentBufferExecCompleted(); +} + +void OpponentHandleFaintingCry(void) +{ + PlayCry3( + GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES), + 25, 5); + OpponentBufferExecCompleted(); +} + +void OpponentHandleIntroSlide(void) +{ + sub_80E43C0(gBattleBufferA[gActiveBank][1]); + gUnknown_02024DE8 |= 1; + OpponentBufferExecCompleted(); +} + +void OpponentHandleTrainerBallThrow(void) +{ + u8 taskId; + + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 35; + gSprites[gObjectBankIDs[gActiveBank]].data2 = 280; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], sub_8035C10); + taskId = CreateTask(sub_8035C44, 5); + gTasks[taskId].data[0] = gActiveBank; + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + ewram17840.unk9_0 = 1; + gBattleBankFunc[gActiveBank] = nullsub_45; +} + +void sub_8035C10(struct Sprite *sprite) +{ + sub_8031B74(sprite->oam.affineParam); + sprite->oam.tileNum = sprite->data5; + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); +} + +void sub_8035C44(u8 taskId) +{ + u8 r9; + + r9 = gActiveBank; + gActiveBank = gTasks[taskId].data[0]; + if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_803495C(gActiveBank, 0); + } + else + { + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_803495C(gActiveBank, 0); + gActiveBank ^= 2; + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_803495C(gActiveBank, 0); + gActiveBank ^= 2; + } + gBattleBankFunc[gActiveBank] = sub_8032E2C; + gActiveBank = r9; + DestroyTask(taskId); +} + +void OpponentHandlecmd48(void) +{ + if (gBattleBufferA[gActiveBank][1] != 0 && GetBankSide(gActiveBank) == 0) + { + OpponentBufferExecCompleted(); + return; + } + + ewram17810[gActiveBank].unk0_0 = 1; + if (gBattleBufferA[gActiveBank][2] != 0) + { + if (ewram17810[gActiveBank].unk1_1 < 2) + { + ewram17810[gActiveBank].unk1_1++; + return; + } + else + { + ewram17810[gActiveBank].unk1_1 = 0; + } + } + gUnknown_02024E68[gActiveBank] = sub_8044804( + gActiveBank, + (struct BattleInterfaceStruct2 *)&gBattleBufferA[gActiveBank][4], + gBattleBufferA[gActiveBank][1], + gBattleBufferA[gActiveBank][2]); + ewram17810[gActiveBank].unk5 = 0; + if (gBattleBufferA[gActiveBank][2] != 0) + ewram17810[gActiveBank].unk5 = 0x5D; + gBattleBankFunc[gActiveBank] = sub_8035E2C; +} + +void sub_8035E2C(void) +{ + if (ewram17810[gActiveBank].unk5++ >= 93) + { + ewram17810[gActiveBank].unk5 = 0; + OpponentBufferExecCompleted(); + } +} + +void OpponentHandlecmd49(void) +{ + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd50(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandleSpriteInvisibility(void) +{ + if (AnimBankSpriteExists(gActiveBank) != 0) + { + gSprites[gObjectBankIDs[gActiveBank]].invisible = gBattleBufferA[gActiveBank][1]; + sub_8031F88(gActiveBank); + } + OpponentBufferExecCompleted(); +} + +void OpponentHandleBattleAnimation(void) +{ + if (mplay_80342A4(gActiveBank) == 0) + { + u8 r3 = gBattleBufferA[gActiveBank][1]; + u16 r4 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + + if (move_anim_start_t3(gActiveBank, gActiveBank, gActiveBank, r3, r4) != 0) + OpponentBufferExecCompleted(); + else + gBattleBankFunc[gActiveBank] = sub_80334C0; + } +} + +void OpponentHandleLinkStandbyMsg(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandleResetActionMoveSelection(void) +{ + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd55(void) +{ + if ((gBattleTypeFlags & BATTLE_TYPE_LINK) && !(gBattleTypeFlags & BATTLE_TYPE_WILD)) + { + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } + OpponentBufferExecCompleted(); +} + +void OpponentHandlecmd56(void) +{ +} diff --git a/src/battle/battle_controller_player.c b/src/battle/battle_controller_player.c new file mode 100644 index 000000000..53b596c5e --- /dev/null +++ b/src/battle/battle_controller_player.c @@ -0,0 +1,3066 @@ +#include "global.h" +#include "data2.h" +#include "battle.h" +#include "battle_interface.h" +#include "battle_message.h" +#include "item.h" +#include "items.h" +#include "link.h" +#include "m4a.h" +#include "main.h" +#include "menu_cursor.h" +#include "moves.h" +#include "palette.h" +#include "pokemon.h" +#include "rom3.h" +#include "songs.h" +#include "sound.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "util.h" + +//Possibly PokemonSubstruct1 +struct UnknownStruct3 +{ + u16 moves[4]; + u8 pp[4]; + u8 ppBonuses; +}; + +#if ENGLISH +#define SUB_803037C_TILE_DATA_OFFSET 440 +#elif GERMAN +#define SUB_803037C_TILE_DATA_OFFSET 444 +#endif + +extern u16 gUnknown_030042A4; +extern u16 gUnknown_030042A0; + +extern struct Window gUnknown_03004210; + +extern void (*gBattleBankFunc[])(void); + +extern u8 gActiveBank; +extern u8 gActionSelectionCursor[]; +extern u8 gDisplayedStringBattle[]; +extern u8 gMoveSelectionCursor[]; +extern u8 gBattleBufferA[][0x200]; +extern u8 gBankInMenu; +extern u16 gBattlePartyID[]; +extern u8 gHealthboxIDs[]; +extern u8 gDoingBattleAnim; +extern u8 gObjectBankIDs[]; +extern u16 gBattleTypeFlags; +extern u8 gBattleOutcome; +extern void (*gAnimScriptCallback)(void); +extern bool8 gAnimScriptActive; +extern u16 gMovePowerMoveAnim; +extern u32 gMoveDmgMoveAnim; +extern u8 gHappinessMoveAnim; +extern u16 gWeatherMoveAnim; +extern u32 *gDisableStructMoveAnim; +extern u32 gPID_perBank[]; +extern u8 gBattleMonForms[]; +extern u16 gUnknown_02024DE8; +extern u8 gUnknown_02024E68[]; +extern struct SpriteTemplate gUnknown_02024E8C; +extern u8 gUnknown_0202F7C4; +extern u8 gUnknown_02038470[]; +extern u16 gUnknown_030041B0; +extern u16 gUnknown_030041B4; +extern u16 gUnknown_030041B8; +extern u16 gUnknown_03004280; +extern u16 gUnknown_03004288; +extern u16 gUnknown_030042A4; +extern u16 gUnknown_030042C0; +extern u8 gUnknown_03004344; +extern u8 gUnknown_0300434C[]; + +extern const u8 gUnknown_08400CA8[]; +extern const u8 gUnknown_08400CF3[]; +extern const u8 gUnknown_08400D38[]; + +extern void sub_802C68C(void); +extern void sub_802E1B0(void); +extern void sub_802E220(); +extern void sub_802E2D4(); +extern void sub_802E004(void); +extern void sub_802DF30(void); +extern void BattleMusicStop(void); +extern void PlayerBufferExecCompleted(void); +extern void bx_t1_healthbar_update(void); +extern void nullsub_91(void); +extern void sub_802D924(u8); +extern void sub_802E434(void); +extern bool8 mplay_80342A4(u8); +extern void move_anim_start_t2_for_situation(); +extern void bx_blink_t1(void); +extern void sub_8047858(); +extern u8 GetBankSide(u8); +extern void sub_80E43C0(); +extern void oamt_add_pos2_onto_pos1(); +extern void sub_8078B34(struct Sprite *); +extern void StoreSpriteCallbackInData6(); +extern void BattleLoadPlayerMonSprite(); +extern bool8 IsDoubleBattle(void); +extern void sub_802D500(void); +extern bool8 AnimBankSpriteExists(u8); +extern bool8 move_anim_start_t3(); +extern void sub_802E460(void); +extern void b_link_standby_message(void); +extern void sub_802D18C(void); +extern void sub_802DF18(void); +extern void BufferStringBattle(); +extern void sub_80326EC(); +extern void ExecuteMoveAnim(); +extern void sub_8031F24(void); +extern void sub_80324BC(); +extern u8 sub_8031720(); +extern void bx_wait_t1(void); +extern u8 GetBankByPlayerAI(u8); +extern void sub_802DE10(void); +extern void sub_80105EC(struct Sprite *); +extern void sub_802D274(void); +extern void sub_802D23C(void); +extern u8 GetBankIdentity(u8); +extern void LoadPlayerTrainerBankSprite(); +extern void sub_80313A0(struct Sprite *); +extern void sub_802D204(void); +extern u8 sub_8079E90(); +extern void sub_802DEAC(void); +extern void sub_80312F0(struct Sprite *); +extern u8 sub_8077ABC(); +extern u8 sub_8077F68(); +extern u8 sub_8046400(); +extern void sub_802D798(void); +extern void bx_0802E404(void); +extern u8 gActiveBank; +extern void (*gBattleBankFunc[])(void); +extern bool8 gDoingBattleAnim; +extern u16 gBattleTypeFlags; +extern u32 gBattleExecBuffer; +extern u8 gBattleBufferA[][0x200]; +extern u8 gObjectBankIDs[]; +extern u8 gActionSelectionCursor[]; +extern u8 gMoveSelectionCursor[]; +extern u8 gAbsentBankFlags; +extern u8 gUnknown_03004344; +extern u8 gNoOfAllBanks; +extern u16 gBattlePartyID[]; +extern u16 gUnknown_030042A0; +extern u16 gUnknown_030042A4; +extern struct Window gUnknown_03004210; +extern const u8 gUnknown_08400D89[]; +extern u8 gUnknown_03004348; +extern struct BattlePokemon gBattleMons[]; +extern MainCallback gPreBattleCallback1; +extern u8 gHealthboxIDs[]; +extern struct MusicPlayerInfo gMPlay_BGM; +extern u8 gUnknown_0300434C[]; +extern u8 gUnknown_0202E8F4; +extern u8 gUnknown_0202E8F5; +extern u8 gUnknown_02038470[]; +extern u16 gScriptItemId; +extern u8 gDisplayedStringBattle[]; +extern const u8 gUnknown_08400CE0[]; + +extern void dp11b_obj_instanciate(u8, u8, s8, s8); +extern u8 GetBankIdentity(u8); +extern u8 GetBankByPlayerAI(u8); +extern void dp11b_obj_free(u8, u8); +extern void sub_8010520(struct Sprite *); +extern void sub_8010574(struct Sprite *); +extern bool8 IsDoubleBattle(); +extern void sub_804777C(); +extern void sub_8141828(); +extern void sub_8094E20(u8); +extern void nullsub_14(void); +extern void sub_80A6DCC(void); +extern void ReshowBattleScreenAfterMenu(void); + +void PlayerHandleGetAttributes(void); +void PlayerHandlecmd1(void); +void PlayerHandleSetAttributes(void); +void PlayerHandlecmd3(void); +void PlayerHandleLoadPokeSprite(void); +void PlayerHandleSendOutPoke(void); +void PlayerHandleReturnPokeToBall(void); +void PlayerHandleTrainerThrow(void); +void PlayerHandleTrainerSlide(void); +void PlayerHandleTrainerSlideBack(void); +void PlayerHandlecmd10(void); +void PlayerHandlecmd11(void); +void PlayerHandlecmd12(void); +void PlayerHandleBallThrow(void); +void PlayerHandlePuase(void); +void PlayerHandleMoveAnimation(void); +void PlayerHandlePrintString(void); +void PlayerHandlePrintStringPlayerOnly(void); +void PlayerHandlecmd18(void); +void PlayerHandlecmd19(void); +void PlayerHandlecmd20(void); +void PlayerHandleOpenBag(void); +void PlayerHandlecmd22(void); +void PlayerHandlecmd23(void); +void PlayerHandleHealthBarUpdate(void); +void PlayerHandleExpBarUpdate(void); +void PlayerHandleStatusIconUpdate(void); +void PlayerHandleStatusAnimation(void); +void PlayerHandleStatusXor(void); +void PlayerHandlecmd29(void); +void PlayerHandleDMATransfer(void); +void PlayerHandlecmd31(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 PlayerHandlecmd44(void); +void PlayerHandleFaintingCry(void); +void PlayerHandleIntroSlide(void); +void PlayerHandleTrainerBallThrow(void); +void PlayerHandlecmd48(void); +void PlayerHandlecmd49(void); +void PlayerHandlecmd50(void); +void PlayerHandleSpriteInvisibility(void); +void PlayerHandleBattleAnimation(void); +void PlayerHandleLinkStandbyMsg(void); +void PlayerHandleResetActionMoveSelection(void); +void PlayerHandlecmd55(void); +void PlayerHandlecmd56(void); + +const u8 gString_TurnJP[] = _("ターン"); + +void (*const gPlayerBufferCommands[])(void) = +{ + PlayerHandleGetAttributes, + PlayerHandlecmd1, + PlayerHandleSetAttributes, + PlayerHandlecmd3, + PlayerHandleLoadPokeSprite, + PlayerHandleSendOutPoke, + PlayerHandleReturnPokeToBall, + PlayerHandleTrainerThrow, + PlayerHandleTrainerSlide, + PlayerHandleTrainerSlideBack, + PlayerHandlecmd10, + PlayerHandlecmd11, + PlayerHandlecmd12, + PlayerHandleBallThrow, + PlayerHandlePuase, + PlayerHandleMoveAnimation, + PlayerHandlePrintString, + PlayerHandlePrintStringPlayerOnly, + PlayerHandlecmd18, + PlayerHandlecmd19, + PlayerHandlecmd20, + PlayerHandleOpenBag, + PlayerHandlecmd22, + PlayerHandlecmd23, + PlayerHandleHealthBarUpdate, + PlayerHandleExpBarUpdate, + PlayerHandleStatusIconUpdate, + PlayerHandleStatusAnimation, + PlayerHandleStatusXor, + PlayerHandlecmd29, + PlayerHandleDMATransfer, + PlayerHandlecmd31, + PlayerHandlecmd32, + PlayerHandlecmd33, + PlayerHandlecmd34, + PlayerHandlecmd35, + PlayerHandlecmd36, + PlayerHandlecmd37, + PlayerHandlecmd38, + PlayerHandlecmd39, + PlayerHandlecmd40, + PlayerHandleHitAnimation, + PlayerHandlecmd42, + PlayerHandleEffectivenessSound, + PlayerHandlecmd44, + PlayerHandleFaintingCry, + PlayerHandleIntroSlide, + PlayerHandleTrainerBallThrow, + PlayerHandlecmd48, + PlayerHandlecmd49, + PlayerHandlecmd50, + PlayerHandleSpriteInvisibility, + PlayerHandleBattleAnimation, + PlayerHandleLinkStandbyMsg, + PlayerHandleResetActionMoveSelection, + PlayerHandlecmd55, + PlayerHandlecmd56, +}; + +void PlayerBufferRunCommand(void); +void sub_802C2EC(void); +void sub_802C68C(void); +void sub_802CA60(void); +void sub_802D730(void); +void sub_802DA9C(u8); +void sub_802DB6C(u8); +void sub_802DCB0(u8); +void sub_802DD10(u8); +void sub_802DDC4(u8); +void sub_802DF88(void); +void sub_802E03C(void); +void sub_802E12C(s32, const u8 *); +void sub_802E1B0(void); +void sub_802E220(void); +void sub_802E2D4(void); +void sub_802E3B4(u8, int); +void nullsub_7(u8); +void b_link_standby_message(void); +u32 dp01_getattr_by_ch1_for_player_pokemon_(u8, u8 *); +void dp01_setattr_by_ch1_for_player_pokemon(u8); +void sub_802F934(u8, u8); +void sub_802FB2C(void); +void sub_8030190(void); +void sub_80304A8(void); +void sub_8030E38(struct Sprite *); +void task05_08033660(u8); +void sub_8031064(void); + +void nullsub_91(void) +{ +} + +void SetBankFuncToPlayerBufferRunCommand(void) +{ + gBattleBankFunc[gActiveBank] = PlayerBufferRunCommand; + gDoingBattleAnim = FALSE; +} + +void PlayerBufferExecCompleted(void) +{ + gBattleBankFunc[gActiveBank] = PlayerBufferRunCommand; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + u8 playerId = GetMultiplayerId(); + + PrepareBufferDataTransferLink(2, 4, &playerId); + gBattleBufferA[gActiveBank][0] = 0x38; + } + else + { + gBattleExecBuffer &= ~gBitTable[gActiveBank]; + } +} + +void PlayerBufferRunCommand(void) +{ + if (gBattleExecBuffer & gBitTable[gActiveBank]) + { + if (gBattleBufferA[gActiveBank][0] < 0x39) + gPlayerBufferCommands[gBattleBufferA[gActiveBank][0]](); + else + PlayerBufferExecCompleted(); + } +} + +void bx_0802E404(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].pos2.x == 0) + PlayerBufferExecCompleted(); +} + +void sub_802C098(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.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + DestroyMenuCursor(); + + // Useless switch statement. + switch (gActionSelectionCursor[gActiveBank]) + { + case 0: + Emitcmd33(1, 0, 0); + break; + case 1: + Emitcmd33(1, 1, 0); + break; + case 2: + Emitcmd33(1, 2, 0); + break; + case 3: + Emitcmd33(1, 3, 0); + break; + } + PlayerBufferExecCompleted(); + } + else if (gMain.newKeys & DPAD_LEFT) + { + if (gActionSelectionCursor[gActiveBank] & 1) + { + PlaySE(SE_SELECT); + nullsub_8(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 1; + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_RIGHT) + { + if (!(gActionSelectionCursor[gActiveBank] & 1)) + { + PlaySE(SE_SELECT); + nullsub_8(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 1; + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_UP) + { + if (gActionSelectionCursor[gActiveBank] & 2) + { + PlaySE(SE_SELECT); + nullsub_8(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 2; + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (!(gActionSelectionCursor[gActiveBank] & 2)) + { + PlaySE(SE_SELECT); + nullsub_8(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 2; + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & B_BUTTON) + { + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + && GetBankIdentity(gActiveBank) == 2 + && !(gAbsentBankFlags & gBitTable[GetBankByPlayerAI(0)]) + && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + if (gBattleBufferA[gActiveBank][1] == 1) + { + // Add item to bag if it is a ball + if (itemId <= ITEM_PREMIER_BALL) + AddBagItem(itemId, 1); + else + return; + } + PlaySE(SE_SELECT); + Emitcmd33(1, 12, 0); + PlayerBufferExecCompleted(); + DestroyMenuCursor(); + } + } + else if (gMain.newKeys & START_BUTTON) + { + sub_804454C(); + } +} + +void unref_sub_802C2B8(void) +{ + dp11b_obj_free(gActiveBank, 1); + dp11b_obj_free(gActiveBank, 0); + gBattleBankFunc[gActiveBank] = sub_802C2EC; +} + +// TODO: fix this function +void sub_802C2EC(void) +{ + u8 arr[4] = {0, 2, 3, 1}; + s32 i; + + dp11b_obj_instanciate(gUnknown_03004344, 1, 15, 1); + i = 0; + if (gNoOfAllBanks != 0) + { + do + { + if (i != gUnknown_03004344) + dp11b_obj_free(i, 1); + i++; + } while (i < gNoOfAllBanks); + } + if (gMain.newKeys & A_BUTTON) + { + DestroyMenuCursor(); + PlaySE(SE_SELECT); + gSprites[gObjectBankIDs[gUnknown_03004344]].callback = sub_8010574; + Emitcmd33(1, 10, gMoveSelectionCursor[gActiveBank] | (gUnknown_03004344 << 8)); + dp11b_obj_free(gUnknown_03004344, 1); + PlayerBufferExecCompleted(); + } + //_0802C3A8 + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gSprites[gObjectBankIDs[gUnknown_03004344]].callback = sub_8010574; + gBattleBankFunc[gActiveBank] = sub_802C68C; + dp11b_obj_instanciate(gActiveBank, 1, 7, 1); + dp11b_obj_instanciate(gActiveBank, 0, 7, 1); + dp11b_obj_free(gUnknown_03004344, 1); + } + else if (gMain.newKeys & 0x60) + { + PlaySE(SE_SELECT); + gSprites[gObjectBankIDs[gUnknown_03004344]].callback = sub_8010574; + do + { + u8 var = GetBankIdentity(gUnknown_03004344); + + for (i = 0; i < 4; i++) + { + if (var == arr[i]) + break; + } + do + { + i--; + if (i < 0) + i = 3; + gUnknown_03004344 = GetBankByPlayerAI(arr[i]); + } while(gUnknown_03004344 == gNoOfAllBanks); + i = 0; + switch (GetBankIdentity(gUnknown_03004344)) + { + case 0: + case 2: + if (gActiveBank == gUnknown_03004344) + { + u32 moveId; + + asm("":::"memory"); + moveId = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBank]); + if (!(gBattleMoves[moveId].target & 2)) + break; + } + i++; + break; + case 1: + case 3: + i++; + } + //_0802C500 + if (gAbsentBankFlags & gBitTable[gUnknown_03004344]) + i = 0; + } while (i == 0); + gSprites[gObjectBankIDs[gUnknown_03004344]].callback = sub_8010520; + } + //_0802C540 + else if (gMain.newKeys & 0x90) + { + PlaySE(SE_SELECT); + gSprites[gObjectBankIDs[gUnknown_03004344]].callback = sub_8010574; + do + { + u8 var = GetBankIdentity(gUnknown_03004344); + + for (i = 0; i < 4; i++) + { + if (var == arr[i]) + break; + } + do + { + i++; + if (i > 3) + i = 0; + gUnknown_03004344 = GetBankByPlayerAI(arr[i]); + } while (gUnknown_03004344 == gNoOfAllBanks); + i = 0; + switch (GetBankIdentity(gUnknown_03004344)) + { + case 0: + case 2: + if (gActiveBank == gUnknown_03004344) + { + u32 moveId; + + asm("":::"memory"); + moveId = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBank]); + if (!(gBattleMoves[moveId].target & 2)) + break; + } + i++; + break; + case 1: + case 3: + i++; + } + if (gAbsentBankFlags & gBitTable[gUnknown_03004344]) + i = 0; + } while (i == 0); + gSprites[gObjectBankIDs[gUnknown_03004344]].callback = sub_8010520; + } +} + +struct UnknownStruct1 +{ + u16 moves[4]; + u8 pp[4]; + u8 unkC[0x12-0xC]; + u8 unk12; + u8 unk13; + u8 filler14[0x20-0x14]; +}; + +const u8 gUnknown_081FAE80[] = _("{PALETTE 5}{COLOR_HIGHLIGHT_SHADOW WHITE LIGHT_BLUE WHITE2}"); + +void sub_802C68C(void) +{ + u32 r8 = 0; + struct UnknownStruct1 *r6 = (struct UnknownStruct1 *)(gBattleBufferA[gActiveBank] + 4); + + if (gMain.newKeys & A_BUTTON) + { + u32 r4; + + PlaySE(SE_SELECT); + + if (r6->moves[gMoveSelectionCursor[gActiveBank]] == MOVE_CURSE) + r4 = (r6->unk12 != TYPE_GHOST && (r6->unk13 ^ 7)) ? 0x10 : 0; + else + r4 = gBattleMoves[r6->moves[gMoveSelectionCursor[gActiveBank]]].target; + + if (r4 & 0x10) + gUnknown_03004344 = gActiveBank; + else + gUnknown_03004344 = GetBankByPlayerAI((GetBankIdentity(gActiveBank) & 1) ^ 1); + + if (gBattleBufferA[gActiveBank][1] == 0) + { + if ((r4 & 2) && gBattleBufferA[gActiveBank][2] == 0) + r8++; + } + else + { + if (!(r4 & 0x7D)) + r8++; + if (r6->pp[gMoveSelectionCursor[gActiveBank]] == 0) + { + r8 = 0; + } + else if (!(r4 & 0x12) && CountAliveMons(0) <= 1) + { + gUnknown_03004344 = sub_803C434(gActiveBank); + r8 = 0; + } + } + if (r8 == 0) + { + DestroyMenuCursor(); + Emitcmd33(1, 10, gMoveSelectionCursor[gActiveBank] | (gUnknown_03004344 << 8)); + PlayerBufferExecCompleted(); + } + else + { + gBattleBankFunc[gActiveBank] = sub_802C2EC; + if (r4 & 0x12) + gUnknown_03004344 = gActiveBank; + else if (gAbsentBankFlags & gBitTable[GetBankByPlayerAI(1)]) + gUnknown_03004344 = GetBankByPlayerAI(3); + else + gUnknown_03004344 = GetBankByPlayerAI(1); + gSprites[gObjectBankIDs[gUnknown_03004344]].callback = sub_8010520; + } + } + else if (gMain.newKeys & B_BUTTON) + { + DestroyMenuCursor(); + PlaySE(SE_SELECT); + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 320; + Emitcmd33(1, 10, 0xFFFF); + PlayerBufferExecCompleted(); + } + else if (gMain.newKeys & DPAD_LEFT) + { + if (gMoveSelectionCursor[gActiveBank] & 1) + { + nullsub_7(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 1; + PlaySE(SE_SELECT); + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0); + sub_802E220(); + sub_802E2D4(); + } + } + else if (gMain.newKeys & DPAD_RIGHT) + { + if (!(gMoveSelectionCursor[gActiveBank] & 1) + && (gMoveSelectionCursor[gActiveBank] ^ 1) < gUnknown_03004348) + { + nullsub_7(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 1; + PlaySE(SE_SELECT); + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0); + sub_802E220(); + sub_802E2D4(); + } + } + else if (gMain.newKeys & DPAD_UP) + { + if (gMoveSelectionCursor[gActiveBank] & 2) + { + nullsub_7(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 2; + PlaySE(SE_SELECT); + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0); + sub_802E220(); + sub_802E2D4(); + } + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (!(gMoveSelectionCursor[gActiveBank] & 2) + && (gMoveSelectionCursor[gActiveBank] ^ 2) < gUnknown_03004348) + { + nullsub_7(gMoveSelectionCursor[gActiveBank]); + gMoveSelectionCursor[gActiveBank] ^= 2; + PlaySE(SE_SELECT); + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0); + sub_802E220(); + sub_802E2D4(); + } + } + else if (gMain.newKeys & SELECT_BUTTON) + { + if (gUnknown_03004348 > 1 && !(gBattleTypeFlags & BATTLE_TYPE_LINK)) + { + sub_802E12C(gMoveSelectionCursor[gActiveBank], gUnknown_081FAE80); + if (gMoveSelectionCursor[gActiveBank] != 0) + gUnknown_03004344 = 0; + else + gUnknown_03004344 = gMoveSelectionCursor[gActiveBank] + 1; + sub_802E3B4(gUnknown_03004344, 27); + FillWindowRect(&gUnknown_03004210, 0x1016, 0x17, 0x37, 0x1C, 0x3A); + InitWindow(&gUnknown_03004210, gUnknown_08400D89, 0x290, 0x17, 0x37); + sub_8002F44(&gUnknown_03004210); + gBattleBankFunc[gActiveBank] = sub_802CA60; + } + } +} + +extern const u8 gUnknown_08400D49[]; +extern const u8 gUnknown_08400D38[]; + +void sub_802CA60(void) +{ + u8 perMovePPBonuses[4]; + struct + { + u16 moves[4]; + u8 pp[4]; + u8 filler18[8]; // what is this? + } sp0; + //struct UnknownStruct1 sp0; + u8 totalPPBonuses; + + if (gMain.newKeys & (A_BUTTON | SELECT_BUTTON)) + { + PlaySE(SE_SELECT); + if (gMoveSelectionCursor[gActiveBank] != gUnknown_03004344) + { + struct UnknownStruct1 *r9 = (struct UnknownStruct1 *)&gBattleBufferA[gActiveBank][4]; + s32 i; + + i = r9->moves[gMoveSelectionCursor[gActiveBank]]; + r9->moves[gMoveSelectionCursor[gActiveBank]] = r9->moves[gUnknown_03004344]; + r9->moves[gUnknown_03004344] = i; + + i = r9->pp[gMoveSelectionCursor[gActiveBank]]; + r9->pp[gMoveSelectionCursor[gActiveBank]] = r9->pp[gUnknown_03004344]; + r9->pp[gUnknown_03004344] = i; + + i = r9->unkC[gMoveSelectionCursor[gActiveBank]]; + r9->unkC[gMoveSelectionCursor[gActiveBank]] = r9->unkC[gUnknown_03004344]; + r9->unkC[gUnknown_03004344] = i; + + if (gDisableStructs[gActiveBank].unk18_b & gBitTable[gMoveSelectionCursor[gActiveBank]]) + { + gDisableStructs[gActiveBank].unk18_b &= ~gBitTable[gMoveSelectionCursor[gActiveBank]]; + gDisableStructs[gActiveBank].unk18_b |= gBitTable[gUnknown_03004344]; + } + + sub_802E1B0(); + + for (i = 0; i < 4; i++) + perMovePPBonuses[i] = (gBattleMons[gActiveBank].ppBonuses & (3 << (i * 2))) >> (i * 2); + totalPPBonuses = perMovePPBonuses[gMoveSelectionCursor[gActiveBank]]; + perMovePPBonuses[gMoveSelectionCursor[gActiveBank]] = perMovePPBonuses[gUnknown_03004344]; + perMovePPBonuses[gUnknown_03004344] = 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] = r9->moves[i]; + gBattleMons[gActiveBank].pp[i] = r9->pp[i]; + } + if (!(gBattleMons[gActiveBank].status2 & 0x200000)) + { + for (i = 0; i < 4; i++) + { + sp0.moves[i] = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MOVE1 + i); + sp0.pp[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 = sp0.moves[gMoveSelectionCursor[gActiveBank]]; + sp0.moves[gMoveSelectionCursor[gActiveBank]] = sp0.moves[gUnknown_03004344]; + sp0.moves[gUnknown_03004344] = i; + + i = sp0.pp[gMoveSelectionCursor[gActiveBank]]; + sp0.pp[gMoveSelectionCursor[gActiveBank]] = sp0.pp[gUnknown_03004344]; + sp0.pp[gUnknown_03004344] = i; + + totalPPBonuses = perMovePPBonuses[gMoveSelectionCursor[gActiveBank]]; + perMovePPBonuses[gMoveSelectionCursor[gActiveBank]] = perMovePPBonuses[gUnknown_03004344]; + perMovePPBonuses[gUnknown_03004344] = 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, (u8 *)&sp0.moves[i]); + SetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_PP1 + i, &sp0.pp[i]); + } + SetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_PP_BONUSES, &totalPPBonuses); + } + } + else + { + sub_802E12C(gUnknown_03004344, gUnknown_08400D49); + } + gBattleBankFunc[gActiveBank] = sub_802C68C; + gMoveSelectionCursor[gActiveBank] = gUnknown_03004344; + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0); + FillWindowRect(&gUnknown_03004210, 0x1016, 0x17, 0x37, 0x1C, 0x3A); + InitWindow(&gUnknown_03004210, gUnknown_08400D38, 0x290, 0x17, 0x37); + sub_8002F44(&gUnknown_03004210); + sub_802E220(); + sub_802E2D4(); + } + if (gMain.newKeys & (B_BUTTON | SELECT_BUTTON)) + { + PlaySE(SE_SELECT); + nullsub_7(gUnknown_03004344); + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0); + sub_802E12C(gMoveSelectionCursor[gActiveBank], gUnknown_08400D49); + gBattleBankFunc[gActiveBank] = sub_802C68C; + FillWindowRect(&gUnknown_03004210, 0x1016, 0x17, 0x37, 0x1C, 0x3A); + InitWindow(&gUnknown_03004210, gUnknown_08400D38, 0x290, 0x17, 0x37); + sub_8002F44(&gUnknown_03004210); + sub_802E220(); + sub_802E2D4(); + } + if ((gMain.newKeys & DPAD_LEFT) && (gUnknown_03004344 & 1)) + { + if (gUnknown_03004344 == gMoveSelectionCursor[gActiveBank]) + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0x1D); + else + nullsub_7(gUnknown_03004344); + gUnknown_03004344 ^= 1; + PlaySE(SE_SELECT); + if (gUnknown_03004344 == gMoveSelectionCursor[gActiveBank]) + sub_802E3B4(gUnknown_03004344, 0); + else + sub_802E3B4(gUnknown_03004344, 0x1B); + } + if ((gMain.newKeys & DPAD_RIGHT) && !(gUnknown_03004344 & 1) && (gUnknown_03004344 ^ 1) < gUnknown_03004348) + { + if (gUnknown_03004344 == gMoveSelectionCursor[gActiveBank]) + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0x1D); + else + nullsub_7(gUnknown_03004344); + gUnknown_03004344 ^= 1; + PlaySE(SE_SELECT); + if (gUnknown_03004344 == gMoveSelectionCursor[gActiveBank]) + sub_802E3B4(gUnknown_03004344, 0); + else + sub_802E3B4(gUnknown_03004344, 0x1B); + } + if ((gMain.newKeys & DPAD_UP) && (gUnknown_03004344 & 2)) + { + if (gUnknown_03004344 == gMoveSelectionCursor[gActiveBank]) + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0x1D); + else + nullsub_7(gUnknown_03004344); + gUnknown_03004344 ^= 2; + PlaySE(SE_SELECT); + if (gUnknown_03004344 == gMoveSelectionCursor[gActiveBank]) + sub_802E3B4(gUnknown_03004344, 0); + else + sub_802E3B4(gUnknown_03004344, 0x1B); + } + if ((gMain.newKeys & DPAD_DOWN) && !(gUnknown_03004344 & 2) && (gUnknown_03004344 ^ 2) < gUnknown_03004348) + { + if (gUnknown_03004344 == gMoveSelectionCursor[gActiveBank]) + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0x1D); + else + nullsub_7(gUnknown_03004344); + gUnknown_03004344 ^= 2; + PlaySE(SE_SELECT); + if (gUnknown_03004344 == gMoveSelectionCursor[gActiveBank]) + sub_802E3B4(gUnknown_03004344, 0); + else + sub_802E3B4(gUnknown_03004344, 0x1B); + } +} + +void sub_802D148(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + m4aSongNumStop(SE_HINSI); + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(c2_8011A1C); + } +} + +void sub_802D18C(void) +{ + if (!gPaletteFade.active) + { + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + sub_800832C(); + gBattleBankFunc[gActiveBank] = sub_802D148; + } + else + { + m4aSongNumStop(SE_HINSI); + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } + } +} + +void sub_802D204(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + PlayerBufferExecCompleted(); +} + +// duplicate of sub_802D204 +void sub_802D23C(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + PlayerBufferExecCompleted(); +} + +void sub_802D274(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + { + nullsub_10(gSaveBlock2.playerGender); + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + PlayerBufferExecCompleted(); + } +} + +void sub_802D2E0(void) +{ + if (--ewram17810[gActiveBank].unk9 == 0xFF) + { + ewram17810[gActiveBank].unk9 = 0; + PlayerBufferExecCompleted(); + } +} + +void sub_802D31C(void) +{ + bool8 r6 = FALSE; + + if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + { + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy) + r6 = TRUE; + } + else + { + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy + && gSprites[gHealthboxIDs[gActiveBank ^ 2]].callback == SpriteCallbackDummy) + r6 = TRUE; + } + if (IsCryPlayingOrClearCrySongs()) + r6 = FALSE; + + if (r6 && ewram17810[gActiveBank].unk1_0 && ewram17810[gActiveBank ^ 2].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + ewram17810[gActiveBank ^ 2].unk0_7 = 0; + ewram17810[gActiveBank ^ 2].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + m4aMPlayContinue(&gMPlay_BGM); + else + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 256); + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + if (IsDoubleBattle()) + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank ^ 2]], gActiveBank ^ 2); + ewram17810[gActiveBank].unk9 = 3; + gBattleBankFunc[gActiveBank] = sub_802D2E0; + } +} + +void sub_802D500(void) +{ + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank].unk0_7) + sub_8141828(gActiveBank, &gPlayerParty[gBattlePartyID[gActiveBank]]); + if (!ewram17810[gActiveBank ^ 2].unk0_3 && !ewram17810[gActiveBank ^ 2].unk0_7) + sub_8141828(gActiveBank ^ 2, &gPlayerParty[gBattlePartyID[gActiveBank ^ 2]]); + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank ^ 2].unk0_3) + { + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank ^ 2]]); + sub_8045A5C( + gHealthboxIDs[gActiveBank ^ 2], + &gPlayerParty[gBattlePartyID[gActiveBank ^ 2]], + 0); + sub_804777C(gActiveBank ^ 2); + sub_8043DFC(gHealthboxIDs[gActiveBank ^ 2]); + } + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + sub_8045A5C( + gHealthboxIDs[gActiveBank], + &gPlayerParty[gBattlePartyID[gActiveBank]], + 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + ewram17840.unk9_0 = 0; + gBattleBankFunc[gActiveBank] = sub_802D31C; + } +} + +void sub_802D680(void) +{ + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy + && ewram17810[gActiveBank].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + gBattleBankFunc[gActiveBank] = sub_802D730; + } +} + +void sub_802D730(void) +{ + if (!ewram17810[gActiveBank].unk0_6 && !IsCryPlayingOrClearCrySongs()) + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100); + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + PlayerBufferExecCompleted(); + } +} + +void sub_802D798(void) +{ + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank].unk0_7) + sub_8141828(gActiveBank, &gPlayerParty[gBattlePartyID[gActiveBank]]); + if (gSprites[gUnknown_0300434C[gActiveBank]].callback == SpriteCallbackDummy + && !ewram17810[gActiveBank].unk0_3) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + sub_8045A5C(gHealthboxIDs[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + sub_8031F88(gActiveBank); + gBattleBankFunc[gActiveBank] = sub_802D680; + } +} + +void c3_0802FDF4(u8 taskId) +{ + if (!IsCryPlayingOrClearCrySongs()) + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100); + DestroyTask(taskId); + } +} + +void bx_t1_healthbar_update(void) +{ + s16 r4 = sub_8045C78(gActiveBank, gHealthboxIDs[gActiveBank], 0, 0); + + sub_8043DFC(gHealthboxIDs[gActiveBank]); + if (r4 != -1) + { + sub_80440EC(gHealthboxIDs[gActiveBank], r4, 0); + } + else + { + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + PlayerBufferExecCompleted(); + } +} + +void sub_802D90C(void) +{ + if (gUnknown_03004210.state == 0) + PlayerBufferExecCompleted(); +} + +// Rare Candy usage, maybe? +void sub_802D924(u8 taskId) +{ + u32 pkmnIndex = (u8)gTasks[taskId].data[0]; + u8 bank = gTasks[taskId].data[2]; + s16 gainedExp = gTasks[taskId].data[1]; + + if (IsDoubleBattle() == TRUE || pkmnIndex != gBattlePartyID[bank]) + { + struct Pokemon *pkmn = &gPlayerParty[pkmnIndex]; + u16 species = GetMonData(pkmn, MON_DATA_SPECIES); + u8 level = GetMonData(pkmn, MON_DATA_LEVEL); + u32 currExp = GetMonData(pkmn, MON_DATA_EXP); + u32 nextLvlExp = gExperienceTables[gBaseStats[species].growthRate][level + 1]; + + if (currExp + gainedExp >= nextLvlExp) + { + u8 savedActiveBank; + + SetMonData(pkmn, MON_DATA_EXP, (u8 *)&nextLvlExp); + CalculateMonStats(pkmn); + gainedExp -= nextLvlExp - currExp; + savedActiveBank = gActiveBank; + gActiveBank = bank; + Emitcmd33(1, 11, gainedExp); + gActiveBank = savedActiveBank; + + if (IsDoubleBattle() == TRUE + && ((u16)pkmnIndex == gBattlePartyID[bank] || (u16)pkmnIndex == gBattlePartyID[bank ^ 2])) + gTasks[taskId].func = sub_802DCB0; + else + gTasks[taskId].func = sub_802DDC4; + } + else + { + currExp += gainedExp; + SetMonData(pkmn, MON_DATA_EXP, (u8 *)&currExp); + gBattleBankFunc[bank] = sub_802D90C; + DestroyTask(taskId); + } + } + else + { + gTasks[taskId].func = sub_802DA9C; + } +} + +void sub_802DA9C(u8 taskId) +{ + u8 pkmnIndex = gTasks[taskId].data[0]; + s32 r9 = gTasks[taskId].data[1]; + u8 bank = gTasks[taskId].data[2]; + struct Pokemon *pkmn = &gPlayerParty[pkmnIndex]; + u8 level = GetMonData(pkmn, MON_DATA_LEVEL); + u16 species = GetMonData(pkmn, MON_DATA_SPECIES); + u32 exp = GetMonData(pkmn, MON_DATA_EXP); + u32 currLvlExp = gExperienceTables[gBaseStats[species].growthRate][level]; + u32 expToNextLvl; + + exp -= currLvlExp; + expToNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLvlExp; + sub_8043D84(bank, gHealthboxIDs[bank], expToNextLvl, exp, -r9); + PlaySE(SE_EXP); + gTasks[taskId].func = sub_802DB6C; +} + +#ifdef NONMATCHING +void sub_802DB6C(u8 taskId) +{ + if (gTasks[taskId].data[10] < 13) + { + gTasks[taskId].data[10]++; + } + else + { + u8 r9 = gTasks[taskId].data[0]; + s32 r10 = gTasks[taskId].data[1]; //s16? + u8 r7 = gTasks[taskId].data[2]; + s16 r4; + + r4 = sub_8045C78(r7, gHealthboxIDs[r7], 1, 0); + sub_8043DFC(gHealthboxIDs[r7]); + if (r4 == -1) + { + struct Pokemon *pkmn; + u8 r4; + u32 sp4; + u16 r0; + u32 sp0; + + m4aSongNumStop(SE_EXP); + pkmn = &gPlayerParty[r9]; + r4 = GetMonData(pkmn, MON_DATA_LEVEL); + sp4 = GetMonData(pkmn, MON_DATA_EXP); + r0 = GetMonData(pkmn, MON_DATA_SPECIES); + sp0 = gExperienceTables[gBaseStats[r0].growthRate][r4 + 1]; + if (sp4 + r10 >= sp0) + { + u8 r5; + u32 asdf; + + SetMonData(pkmn, MON_DATA_EXP, (u8 *)&sp0); + CalculateMonStats(pkmn); + //r10 -= sp0 - sp4; + asdf = sp0 - sp4; + //asdf = r10 - (sp0 - sp4); + r10 -= asdf; + r5 = gActiveBank; + gActiveBank = r7; + Emitcmd33(1, 11, r10); + gActiveBank = r5; + gTasks[taskId].func = sub_802DCB0; + } + else + { + //u32 asdf = sp4 + r10; + sp4 += r10; + SetMonData(pkmn, MON_DATA_EXP, (u8 *)&sp4); + gBattleBankFunc[r7] = sub_802D90C; + DestroyTask(taskId); + } + } + } +} +#else +__attribute__((naked)) +void sub_802DB6C(u8 taskId) +{ + asm_unified("push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x8\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + ldr r1, _0802DB98 @ =gTasks\n\ + lsls r0, 2\n\ + add r0, r8\n\ + lsls r0, 3\n\ + adds r6, r0, r1\n\ + ldrh r1, [r6, 0x1C]\n\ + movs r2, 0x1C\n\ + ldrsh r0, [r6, r2]\n\ + cmp r0, 0xC\n\ + bgt _0802DB9C\n\ + adds r0, r1, 0x1\n\ + strh r0, [r6, 0x1C]\n\ + b _0802DC98\n\ + .align 2, 0\n\ +_0802DB98: .4byte gTasks\n\ +_0802DB9C:\n\ + ldrb r0, [r6, 0x8]\n\ + mov r9, r0\n\ + ldrh r2, [r6, 0xA]\n\ + mov r10, r2\n\ + ldrb r7, [r6, 0xC]\n\ + ldr r5, _0802DC64 @ =gHealthboxIDs\n\ + adds r5, r7, r5\n\ + ldrb r1, [r5]\n\ + adds r0, r7, 0\n\ + movs r2, 0x1\n\ + movs r3, 0\n\ + bl sub_8045C78\n\ + adds r4, r0, 0\n\ + lsls r4, 16\n\ + lsrs r4, 16\n\ + ldrb r0, [r5]\n\ + bl sub_8043DFC\n\ + lsls r4, 16\n\ + asrs r4, 16\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + cmp r4, r0\n\ + bne _0802DC98\n\ + movs r0, 0x21\n\ + bl m4aSongNumStop\n\ + movs r0, 0x64\n\ + mov r1, r9\n\ + muls r1, r0\n\ + ldr r0, _0802DC68 @ =gPlayerParty\n\ + adds r5, r1, r0\n\ + adds r0, r5, 0\n\ + movs r1, 0x38\n\ + bl GetMonData\n\ + adds r4, r0, 0\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + adds r0, r5, 0\n\ + movs r1, 0x19\n\ + bl GetMonData\n\ + str r0, [sp, 0x4]\n\ + adds r0, r5, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + ldr r3, _0802DC6C @ =gExperienceTables\n\ + adds r4, 0x1\n\ + lsls r4, 2\n\ + ldr r2, _0802DC70 @ =gBaseStats\n\ + lsls r1, r0, 3\n\ + subs r1, r0\n\ + lsls r1, 2\n\ + adds r1, r2\n\ + ldrb r1, [r1, 0x13]\n\ + movs r0, 0xCA\n\ + lsls r0, 1\n\ + muls r0, r1\n\ + adds r4, r0\n\ + adds r4, r3\n\ + ldr r1, [r4]\n\ + str r1, [sp]\n\ + mov r2, r10\n\ + lsls r0, r2, 16\n\ + asrs r4, r0, 16\n\ + ldr r0, [sp, 0x4]\n\ + adds r0, r4\n\ + cmp r0, r1\n\ + blt _0802DC7C\n\ + adds r0, r5, 0\n\ + movs r1, 0x19\n\ + mov r2, sp\n\ + bl SetMonData\n\ + adds r0, r5, 0\n\ + bl CalculateMonStats\n\ + ldr r2, [sp]\n\ + add r0, sp, 0x4\n\ + ldrh r0, [r0]\n\ + subs r2, r0\n\ + subs r2, r4, r2\n\ + ldr r4, _0802DC74 @ =gActiveBank\n\ + ldrb r5, [r4]\n\ + strb r7, [r4]\n\ + lsls r2, 16\n\ + lsrs r2, 16\n\ + movs r0, 0x1\n\ + movs r1, 0xB\n\ + bl Emitcmd33\n\ + strb r5, [r4]\n\ + ldr r0, _0802DC78 @ =sub_802DCB0\n\ + str r0, [r6]\n\ + b _0802DC98\n\ + .align 2, 0\n\ +_0802DC64: .4byte gHealthboxIDs\n\ +_0802DC68: .4byte gPlayerParty\n\ +_0802DC6C: .4byte gExperienceTables\n\ +_0802DC70: .4byte gBaseStats\n\ +_0802DC74: .4byte gActiveBank\n\ +_0802DC78: .4byte sub_802DCB0\n\ +_0802DC7C:\n\ + str r0, [sp, 0x4]\n\ + add r2, sp, 0x4\n\ + adds r0, r5, 0\n\ + movs r1, 0x19\n\ + bl SetMonData\n\ + ldr r1, _0802DCA8 @ =gBattleBankFunc\n\ + lsls r0, r7, 2\n\ + adds r0, r1\n\ + ldr r1, _0802DCAC @ =sub_802D90C\n\ + str r1, [r0]\n\ + mov r0, r8\n\ + bl DestroyTask\n\ +_0802DC98:\n\ + add sp, 0x8\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0802DCA8: .4byte gBattleBankFunc\n\ +_0802DCAC: .4byte sub_802D90C\n"); +} +#endif + +void sub_802DCB0(u8 taskId) +{ + u8 bank = gTasks[taskId].data[2]; + u8 pkmnIndex = gTasks[taskId].data[0]; + + if (IsDoubleBattle() == TRUE && pkmnIndex == gBattlePartyID[bank ^ 2]) + bank ^= 2; + move_anim_start_t4(bank, bank, bank, 0); + gTasks[taskId].func = sub_802DD10; +} + +void sub_802DD10(u8 taskId) +{ + u8 bank = gTasks[taskId].data[2]; + + if (!ewram17810[bank].unk0_6) + { + u8 pkmnIndex = gTasks[taskId].data[0]; + + GetMonData(&gPlayerParty[pkmnIndex], MON_DATA_LEVEL); // Unused return value + if (IsDoubleBattle() == TRUE && pkmnIndex == gBattlePartyID[bank ^ 2]) + sub_8045A5C(gHealthboxIDs[bank ^ 2], &gPlayerParty[pkmnIndex], 0); + else + sub_8045A5C(gHealthboxIDs[bank], &gPlayerParty[pkmnIndex], 0); + gTasks[taskId].func = sub_802DDC4; + } +} + +void sub_802DDC4(u8 taskId) +{ + u8 pkmnIndex; + u8 bank; + + pkmnIndex = gTasks[taskId].data[0]; + GetMonData(&gPlayerParty[pkmnIndex], MON_DATA_LEVEL); // Unused return value + bank = gTasks[taskId].data[2]; + gBattleBankFunc[bank] = sub_802D90C; + DestroyTask(taskId); +} + +void sub_802DE10(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].pos1.y + gSprites[gObjectBankIDs[gActiveBank]].pos2.y > DISPLAY_HEIGHT) + { + u16 species = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES); + + nullsub_9(species); + FreeOamMatrix(gSprites[gObjectBankIDs[gActiveBank]].oam.matrixNum); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + PlayerBufferExecCompleted(); + } +} + +void sub_802DEAC(void) +{ + if (!ewram17810[gActiveBank].unk0_6) + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + PlayerBufferExecCompleted(); + } +} + +// Duplicate of sub_802D90C +void sub_802DF18(void) +{ + if (gUnknown_03004210.state == 0) + PlayerBufferExecCompleted(); +} + +void sub_802DF30(void) +{ + if (!gPaletteFade.active) + { + u8 r4; + + gBattleBankFunc[gActiveBank] = sub_802DF88; + r4 = gTasks[gUnknown_0300434C[gActiveBank]].data[0]; + DestroyTask(gUnknown_0300434C[gActiveBank]); + sub_8094E20(r4); + } +} + +void sub_802DF88(void) +{ + if (gMain.callback2 == sub_800F808 && !gPaletteFade.active) + { + if (gUnknown_0202E8F4 == 1) + Emitcmd34(1, gUnknown_0202E8F5, gUnknown_02038470); + else + Emitcmd34(1, 6, NULL); + if ((gBattleBufferA[gActiveBank][1] & 0xF) == 1) + b_link_standby_message(); + PlayerBufferExecCompleted(); + } +} + +void sub_802E004(void) +{ + if (!gPaletteFade.active) + { + gBattleBankFunc[gActiveBank] = sub_802E03C; + nullsub_14(); + sub_80A6DCC(); + } +} + +void sub_802E03C(void) +{ + if (gMain.callback2 == sub_800F808 && !gPaletteFade.active) + { + Emitcmd35(1, gScriptItemId); + PlayerBufferExecCompleted(); + } +} + +void bx_wait_t1(void) +{ + if (!gDoingBattleAnim || !ewram17810[gActiveBank].unk0_6) + PlayerBufferExecCompleted(); +} + +void bx_blink_t1(void) +{ + u8 spriteId = gObjectBankIDs[gActiveBank]; + + if (gSprites[spriteId].data1 == 32) + { + gSprites[spriteId].data1 = 0; + gSprites[spriteId].invisible = FALSE; + gDoingBattleAnim = 0; + PlayerBufferExecCompleted(); + } + else + { + if (((u16)gSprites[spriteId].data1 % 4) == 0) + gSprites[spriteId].invisible ^= 1; + gSprites[spriteId].data1++; + } +} + +void sub_802E12C(s32 a, const u8 *b) +{ + struct UnknownStruct1 *r4 = (struct UnknownStruct1 *)&gBattleBufferA[gActiveBank][4]; + + StringCopy(gDisplayedStringBattle, b); + StringAppend(gDisplayedStringBattle, gMoveNames[r4->moves[a]]); + InitWindow( + &gUnknown_03004210, + gDisplayedStringBattle, + 0x300 + a * 20, + (a & 1) ? 11 : 1, + (a < 2) ? 0x37 : 0x39); + sub_8002F44(&gUnknown_03004210); +} + +void sub_802E1B0(void) +{ + struct UnknownStruct1 *r4 = (struct UnknownStruct1 *)&gBattleBufferA[gActiveBank][4]; + s32 i; + + gUnknown_03004348 = 0; + FillWindowRect(&gUnknown_03004210, 0x1016, 1, 0x37, 0x14, 0x3A); + for (i = 0; i < 4; i++) + { + nullsub_7(i); + sub_802E12C(i, gUnknown_08400D49); + if (r4->moves[i] != 0) + gUnknown_03004348++; + } +} + +void sub_802E220(void) +{ + if (gBattleBufferA[gActiveBank][2] != 1) + { + struct UnknownStruct1 *r4 = (struct UnknownStruct1 *)&gBattleBufferA[gActiveBank][4]; + u8 *str = gDisplayedStringBattle; + + str = StringCopy(str, gUnknown_08400D49); + str[0] = EXT_CTRL_CODE_BEGIN; + str[1] = 0x11; + str[2] = 2; + str += 3; + str[0] = EXT_CTRL_CODE_BEGIN; + str[1] = 0x14; + str[2] = 6; + str += 3; + str = ConvertIntToDecimalStringN(str, r4->pp[gMoveSelectionCursor[gActiveBank]], 1, 2); + *str++ = CHAR_SLASH; + ConvertIntToDecimalStringN(str, r4->unkC[gMoveSelectionCursor[gActiveBank]], 1, 2); + InitWindow(&gUnknown_03004210, gDisplayedStringBattle, 0x2A2, 0x19, 0x37); + sub_8002F44(&gUnknown_03004210); + } +} + +extern const u8 gUnknown_08400D52[]; +extern const u8 gTypeNames[][7]; + +void sub_802E2D4(void) +{ + if (gBattleBufferA[gActiveBank][2] == 1) + { + FillWindowRect(&gUnknown_03004210, 0x1016, 0x17, 0x37, 0x1C, 0x3A); + InitWindow(&gUnknown_03004210, gUnknown_08400D52, 0x290, 0x13, 0x37); + } + else + { + struct UnknownStruct1 *r4 = (struct UnknownStruct1 *)&gBattleBufferA[gActiveBank][4]; + u8 *str = gDisplayedStringBattle; + + str = StringCopy(str, gUnknown_08400D49); + StringCopy(str, gTypeNames[gBattleMoves[r4->moves[gMoveSelectionCursor[gActiveBank]]].type]); + FillWindowRect(&gUnknown_03004210, 0x1016, 0x17, 0x39, 0x1C, 0x3A); + InitWindow(&gUnknown_03004210, gDisplayedStringBattle, 0x2C0, 0x17, 0x39); + } + sub_8002F44(&gUnknown_03004210); +} + +const u8 gUnknown_081FAE89[][2] = +{ + { 8, 120}, + {88, 120}, + { 8, 136}, + {88, 136}, +}; + +const u8 gUnknown_081FAE91[][2] = +{ + {144, 120}, + {190, 120}, + {144, 136}, + {190, 136}, + { 72, 72}, + { 32, 90}, + { 80, 80}, + { 80, 88}, +}; + +void sub_802E3B4(u8 a, int unused) +{ + sub_814A958(0x48); + sub_814A880(gUnknown_081FAE89[a][0], gUnknown_081FAE89[a][1]); +} + +void nullsub_7(u8 a) +{ +} + +void sub_802E3E4(u8 a, int unused) +{ + sub_814A958(0x2A); + sub_814A880(gUnknown_081FAE91[a][0], gUnknown_081FAE91[a][1]); +} + +void nullsub_8(u8 a) +{ +} + +void sub_802E414(void) +{ + SetMainCallback2(ReshowBattleScreenAfterMenu); +} + +void sub_802E424(void) +{ + SetMainCallback2(ReshowBattleScreenAfterMenu); +} + +void sub_802E434(void) +{ + if (!ewram17810[gActiveBank].unk0_4) + PlayerBufferExecCompleted(); +} + +void sub_802E460(void) +{ + if (!ewram17810[gActiveBank].unk0_5) + PlayerBufferExecCompleted(); +} + +void b_link_standby_message(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + sub_8002EB0(&gUnknown_03004210, gUnknown_08400CE0, 0x90, 2, 15); + } +} + +void PlayerHandleGetAttributes(void) +{ + u8 unkData[0x100]; + u32 offset = 0; + u8 r4; + s32 i; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + offset += dp01_getattr_by_ch1_for_player_pokemon_(gBattlePartyID[gActiveBank], unkData); + } + else + { + r4 = gBattleBufferA[gActiveBank][2]; + for (i = 0; i < 6; i++) + { + if (r4 & 1) + offset += dp01_getattr_by_ch1_for_player_pokemon_(i, unkData + offset); + r4 >>= 1; + } + } + Emitcmd29(1, offset, unkData); + PlayerBufferExecCompleted(); +} + +// Duplicate of dp01_getattr_by_ch1_for_player_pokemon +u32 dp01_getattr_by_ch1_for_player_pokemon_(u8 a, u8 *buffer) +{ + struct BattlePokemon battlePokemon; + struct UnknownStruct3 moveData; + u8 nickname[20]; + u8 *src; + s16 data16; + u32 data32; + s32 size = 0; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + battlePokemon.species = GetMonData(&gPlayerParty[a], MON_DATA_SPECIES); + battlePokemon.item = GetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM); + for (size = 0; size < 4; size++) + { + battlePokemon.moves[size] = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + size); + battlePokemon.pp[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + } + battlePokemon.ppBonuses = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + battlePokemon.friendship = GetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP); + battlePokemon.experience = GetMonData(&gPlayerParty[a], MON_DATA_EXP); + battlePokemon.hpIV = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + battlePokemon.attackIV = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + battlePokemon.defenseIV = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + battlePokemon.speedIV = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + battlePokemon.spAttackIV = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + battlePokemon.spDefenseIV = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + battlePokemon.personality = GetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY); + battlePokemon.status1 = GetMonData(&gPlayerParty[a], MON_DATA_STATUS); + battlePokemon.level = GetMonData(&gPlayerParty[a], MON_DATA_LEVEL); + battlePokemon.hp = GetMonData(&gPlayerParty[a], MON_DATA_HP); + battlePokemon.maxHP = GetMonData(&gPlayerParty[a], MON_DATA_MAX_HP); + battlePokemon.attack = GetMonData(&gPlayerParty[a], MON_DATA_ATK); + battlePokemon.defense = GetMonData(&gPlayerParty[a], MON_DATA_DEF); + battlePokemon.speed = GetMonData(&gPlayerParty[a], MON_DATA_SPD); + battlePokemon.spAttack = GetMonData(&gPlayerParty[a], MON_DATA_SPATK); + battlePokemon.spDefense = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF); + battlePokemon.isEgg = GetMonData(&gPlayerParty[a], MON_DATA_IS_EGG); + battlePokemon.altAbility = GetMonData(&gPlayerParty[a], MON_DATA_ALT_ABILITY); + battlePokemon.otId = GetMonData(&gPlayerParty[a], MON_DATA_OT_ID); + GetMonData(&gPlayerParty[a], MON_DATA_NICKNAME, nickname); + StringCopy10(battlePokemon.nickname, nickname); + GetMonData(&gPlayerParty[a], MON_DATA_OT_NAME, battlePokemon.otName); + src = (u8 *)&battlePokemon; + for (size = 0; size < sizeof(battlePokemon); size++) + buffer[size] = src[size]; + break; + case 1: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPECIES); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 2: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 3: + for (size = 0; size < 4; size++) + { + moveData.moves[size] = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + size); + moveData.pp[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + } + moveData.ppBonuses = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + src = (u8 *)&moveData; + for (size = 0; size < sizeof(moveData); size++) + buffer[size] = src[size]; + break; + case 4: + case 5: + case 6: + case 7: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 8: + for (size = 0; size < 4; size++) + buffer[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + buffer[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + size++; + break; + case 9: + case 10: + case 11: + case 12: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9); + size = 1; + break; + case 17: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_OT_ID); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 18: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_EXP); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 19: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_EV); + size = 1; + break; + case 20: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_EV); + size = 1; + break; + case 21: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_EV); + size = 1; + break; + case 22: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_EV); + size = 1; + break; + case 23: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_EV); + size = 1; + break; + case 24: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_EV); + size = 1; + break; + case 25: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP); + size = 1; + break; + case 26: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_POKERUS); + size = 1; + break; + case 27: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_LOCATION); + size = 1; + break; + case 28: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_LEVEL); + size = 1; + break; + case 29: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_GAME); + size = 1; + break; + case 30: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_POKEBALL); + size = 1; + break; + case 31: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + buffer[1] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + buffer[2] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + buffer[3] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + buffer[4] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + buffer[5] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + size = 6; + break; + case 32: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + size = 1; + break; + case 33: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + size = 1; + break; + case 34: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + size = 1; + break; + case 35: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + size = 1; + break; + case 36: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + size = 1; + break; + case 37: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + size = 1; + break; + case 38: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 39: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_CHECKSUM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 40: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_STATUS); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 41: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_LEVEL); + size = 1; + break; + case 42: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 43: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_MAX_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 44: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_ATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 45: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_DEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 46: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPD); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 47: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 48: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 49: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_COOL); + size = 1; + break; + case 50: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_BEAUTY); + size = 1; + break; + case 51: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_CUTE); + size = 1; + break; + case 52: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SMART); + size = 1; + break; + case 53: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_TOUGH); + size = 1; + break; + case 54: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SHEEN); + size = 1; + break; + case 55: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_COOL_RIBBON); + size = 1; + break; + case 56: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_BEAUTY_RIBBON); + size = 1; + break; + case 57: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_CUTE_RIBBON); + size = 1; + break; + case 58: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SMART_RIBBON); + size = 1; + break; + case 59: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_TOUGH_RIBBON); + size = 1; + break; + } + return size; +} + +void PlayerHandlecmd1(void) +{ + struct BattlePokemon battleMon; // I think this is a BattlePokemon + u8 *src = (u8 *)&gPlayerParty[gBattlePartyID[gActiveBank]] + gBattleBufferA[gActiveBank][1]; + u8 *dst = (u8 *)&battleMon + gBattleBufferA[gActiveBank][1]; + u8 i; + + for (i = 0; i < gBattleBufferA[gActiveBank][2]; i++) + dst[i] = src[i]; + Emitcmd29(1, gBattleBufferA[gActiveBank][2], dst); + PlayerBufferExecCompleted(); +} + +void PlayerHandleSetAttributes(void) +{ + u8 r4; + u8 i; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + dp01_setattr_by_ch1_for_player_pokemon(gBattlePartyID[gActiveBank]); + } + else + { + r4 = gBattleBufferA[gActiveBank][2]; + for (i = 0; i < 6; i++) + { + if (r4 & 1) + dp01_setattr_by_ch1_for_player_pokemon(i); + r4 >>= 1; + } + } + PlayerBufferExecCompleted(); +} + +// Duplicate of sub_811EC68 +void dp01_setattr_by_ch1_for_player_pokemon(u8 a) +{ + struct BattlePokemon *battlePokemon = (struct BattlePokemon *)&gBattleBufferA[gActiveBank][3]; + struct UnknownStruct3 *moveData = (struct UnknownStruct3 *)&gBattleBufferA[gActiveBank][3]; + s32 i; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + { + u8 iv; + + SetMonData(&gPlayerParty[a], MON_DATA_SPECIES, (u8 *)&battlePokemon->species); + SetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM, (u8 *)&battlePokemon->item); + for (i = 0; i < 4; i++) + { + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + i, (u8 *)&battlePokemon->moves[i]); + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + i, (u8 *)&battlePokemon->pp[i]); + } + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, (u8 *)&battlePokemon->ppBonuses); + SetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP, (u8 *)&battlePokemon->friendship); + SetMonData(&gPlayerParty[a], MON_DATA_EXP, (u8 *)&battlePokemon->experience); + iv = battlePokemon->hpIV; + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, (u8 *)&iv); + iv = battlePokemon->attackIV; + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, (u8 *)&iv); + iv = battlePokemon->defenseIV; + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, (u8 *)&iv); + iv = battlePokemon->speedIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, (u8 *)&iv); + iv = battlePokemon->spAttackIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, (u8 *)&iv); + iv = battlePokemon->spDefenseIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, (u8 *)&iv); + SetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY, (u8 *)&battlePokemon->personality); + SetMonData(&gPlayerParty[a], MON_DATA_STATUS, (u8 *)&battlePokemon->status1); + SetMonData(&gPlayerParty[a], MON_DATA_LEVEL, (u8 *)&battlePokemon->level); + SetMonData(&gPlayerParty[a], MON_DATA_HP, (u8 *)&battlePokemon->hp); + SetMonData(&gPlayerParty[a], MON_DATA_MAX_HP, (u8 *)&battlePokemon->maxHP); + SetMonData(&gPlayerParty[a], MON_DATA_ATK, (u8 *)&battlePokemon->attack); + SetMonData(&gPlayerParty[a], MON_DATA_DEF, (u8 *)&battlePokemon->defense); + SetMonData(&gPlayerParty[a], MON_DATA_SPD, (u8 *)&battlePokemon->speed); + SetMonData(&gPlayerParty[a], MON_DATA_SPATK, (u8 *)&battlePokemon->spAttack); + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF, (u8 *)&battlePokemon->spDefense); + } + break; + case 1: + SetMonData(&gPlayerParty[a], MON_DATA_SPECIES, &gBattleBufferA[gActiveBank][3]); + break; + case 2: + SetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM, &gBattleBufferA[gActiveBank][3]); + break; + case 3: + for (i = 0; i < 4; i++) + { + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + i, (u8 *)&moveData->moves[i]); + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + i, (u8 *)&moveData->pp[i]); + } + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, &moveData->ppBonuses); + break; + case 4: + case 5: + case 6: + case 7: + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4, &gBattleBufferA[gActiveBank][3]); + break; + case 8: + SetMonData(&gPlayerParty[a], MON_DATA_PP1, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gPlayerParty[a], MON_DATA_PP2, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gPlayerParty[a], MON_DATA_PP3, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gPlayerParty[a], MON_DATA_PP4, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, &gBattleBufferA[gActiveBank][7]); + break; + case 9: + case 10: + case 11: + case 12: + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9, &gBattleBufferA[gActiveBank][3]); + break; + case 17: + SetMonData(&gPlayerParty[a], MON_DATA_OT_ID, &gBattleBufferA[gActiveBank][3]); + break; + case 18: + SetMonData(&gPlayerParty[a], MON_DATA_EXP, &gBattleBufferA[gActiveBank][3]); + break; + case 19: + SetMonData(&gPlayerParty[a], MON_DATA_HP_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 20: + SetMonData(&gPlayerParty[a], MON_DATA_ATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 21: + SetMonData(&gPlayerParty[a], MON_DATA_DEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 22: + SetMonData(&gPlayerParty[a], MON_DATA_SPD_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 23: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 24: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 25: + SetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP, &gBattleBufferA[gActiveBank][3]); + break; + case 26: + SetMonData(&gPlayerParty[a], MON_DATA_POKERUS, &gBattleBufferA[gActiveBank][3]); + break; + case 27: + SetMonData(&gPlayerParty[a], MON_DATA_MET_LOCATION, &gBattleBufferA[gActiveBank][3]); + break; + case 28: + SetMonData(&gPlayerParty[a], MON_DATA_MET_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 29: + SetMonData(&gPlayerParty[a], MON_DATA_MET_GAME, &gBattleBufferA[gActiveBank][3]); + break; + case 30: + SetMonData(&gPlayerParty[a], MON_DATA_POKEBALL, &gBattleBufferA[gActiveBank][3]); + break; + case 31: + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][7]); + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][8]); + break; + case 32: + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 33: + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 34: + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 35: + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 36: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 37: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 38: + SetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY, &gBattleBufferA[gActiveBank][3]); + break; + case 39: + SetMonData(&gPlayerParty[a], MON_DATA_CHECKSUM, &gBattleBufferA[gActiveBank][3]); + break; + case 40: + SetMonData(&gPlayerParty[a], MON_DATA_STATUS, &gBattleBufferA[gActiveBank][3]); + break; + case 41: + SetMonData(&gPlayerParty[a], MON_DATA_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 42: + SetMonData(&gPlayerParty[a], MON_DATA_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 43: + SetMonData(&gPlayerParty[a], MON_DATA_MAX_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 44: + SetMonData(&gPlayerParty[a], MON_DATA_ATK, &gBattleBufferA[gActiveBank][3]); + break; + case 45: + SetMonData(&gPlayerParty[a], MON_DATA_DEF, &gBattleBufferA[gActiveBank][3]); + break; + case 46: + SetMonData(&gPlayerParty[a], MON_DATA_SPD, &gBattleBufferA[gActiveBank][3]); + break; + case 47: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK, &gBattleBufferA[gActiveBank][3]); + break; + case 48: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF, &gBattleBufferA[gActiveBank][3]); + break; + case 49: + SetMonData(&gPlayerParty[a], MON_DATA_COOL, &gBattleBufferA[gActiveBank][3]); + break; + case 50: + SetMonData(&gPlayerParty[a], MON_DATA_BEAUTY, &gBattleBufferA[gActiveBank][3]); + break; + case 51: + SetMonData(&gPlayerParty[a], MON_DATA_CUTE, &gBattleBufferA[gActiveBank][3]); + break; + case 52: + SetMonData(&gPlayerParty[a], MON_DATA_SMART, &gBattleBufferA[gActiveBank][3]); + break; + case 53: + SetMonData(&gPlayerParty[a], MON_DATA_TOUGH, &gBattleBufferA[gActiveBank][3]); + break; + case 54: + SetMonData(&gPlayerParty[a], MON_DATA_SHEEN, &gBattleBufferA[gActiveBank][3]); + break; + case 55: + SetMonData(&gPlayerParty[a], MON_DATA_COOL_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 56: + SetMonData(&gPlayerParty[a], MON_DATA_BEAUTY_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 57: + SetMonData(&gPlayerParty[a], MON_DATA_CUTE_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 58: + SetMonData(&gPlayerParty[a], MON_DATA_SMART_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 59: + SetMonData(&gPlayerParty[a], MON_DATA_TOUGH_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + } + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); +} + +void PlayerHandlecmd3(void) +{ + u8 *dst = (u8 *)&gPlayerParty[gBattlePartyID[gActiveBank]] + gBattleBufferA[gActiveBank][1]; + u8 i; + + for (i = 0; i < gBattleBufferA[gActiveBank][2]; i++) + dst[i] = gBattleBufferA[gActiveBank][3 + i]; + PlayerBufferExecCompleted(); +} + +void PlayerHandleLoadPokeSprite(void) +{ + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + gBattleBankFunc[gActiveBank] = bx_0802E404; +} + +void PlayerHandleSendOutPoke(void) +{ + sub_8032AA8(gActiveBank, gBattleBufferA[gActiveBank][2]); + gBattlePartyID[gActiveBank] = gBattleBufferA[gActiveBank][1]; + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + gActionSelectionCursor[gActiveBank] = 0; + gMoveSelectionCursor[gActiveBank] = 0; + sub_802F934(gActiveBank, gBattleBufferA[gActiveBank][2]); + gBattleBankFunc[gActiveBank] = sub_802D798; +} + +void sub_802F934(u8 bank, u8 b) +{ + u16 species; + + sub_8032AA8(bank, b); + gBattlePartyID[bank] = gBattleBufferA[bank][1]; + species = GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_SPECIES); + gUnknown_0300434C[bank] = CreateInvisibleSpriteWithCallback(sub_80312F0); + GetMonSpriteTemplate_803C56C(species, GetBankIdentity(bank)); + gObjectBankIDs[bank] = CreateSprite( + &gUnknown_02024E8C, + sub_8077ABC(bank, 2), + sub_8077F68(bank), + sub_8079E90(bank)); + gSprites[gUnknown_0300434C[bank]].data1 = gObjectBankIDs[bank]; + gSprites[gObjectBankIDs[bank]].data0 = bank; + gSprites[gObjectBankIDs[bank]].data2 = species; + gSprites[gObjectBankIDs[bank]].oam.paletteNum = bank; + StartSpriteAnim(&gSprites[gObjectBankIDs[bank]], gBattleMonForms[bank]); + gSprites[gObjectBankIDs[bank]].invisible = TRUE; + gSprites[gObjectBankIDs[bank]].callback = SpriteCallbackDummy; + gSprites[gUnknown_0300434C[bank]].data0 = sub_8046400(0, 0xFF); +} + +void PlayerHandleReturnPokeToBall(void) +{ + if (gBattleBufferA[gActiveBank][1] == 0) + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_802FB2C; + } + else + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + PlayerBufferExecCompleted(); + } +} + +void sub_802FB2C(void) +{ + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (!ewram17810[gActiveBank].unk0_6) + { + ewram17810[gActiveBank].unk4 = 0; + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 1); + gBattleBankFunc[gActiveBank] = sub_802DEAC; + } + } +} + +void PlayerHandleTrainerThrow(void) +{ + s16 r7; + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (GetBankIdentity(gActiveBank) & 2) + r7 = 16; + else + r7 = -16; + } + else + { + r7 = 0; + } + LoadPlayerTrainerBankSprite(gSaveBlock2.playerGender, gActiveBank); + GetMonSpriteTemplate_803C5A0(gSaveBlock2.playerGender, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + r7 + 80, + (8 - gTrainerBackPicCoords[gSaveBlock2.playerGender].coords) * 4 + 80, + sub_8079E90(gActiveBank)); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = 240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = -2; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_802D204; +} + +void PlayerHandleTrainerSlide(void) +{ + LoadPlayerTrainerBankSprite(gSaveBlock2.playerGender, gActiveBank); + GetMonSpriteTemplate_803C5A0(gSaveBlock2.playerGender, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + 80, + (8 - gTrainerBackPicCoords[gSaveBlock2.playerGender].coords) * 4 + 80, + 30); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = -96; + gSprites[gObjectBankIDs[gActiveBank]].data0 = 2; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_802D23C; +} + +void PlayerHandleTrainerSlideBack(void) +{ + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 50; + gSprites[gObjectBankIDs[gActiveBank]].data2 = -40; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], SpriteCallbackDummy); + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], 1); + gBattleBankFunc[gActiveBank] = sub_802D274; +} + +void PlayerHandlecmd10(void) +{ + if (ewram17810[gActiveBank].unk4 == 0) + { + if (ewram17800[gActiveBank].substituteSprite) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4++; + } + else + { + if (ewram17810[gActiveBank].unk0_6 == 0) + { + ewram17810[gActiveBank].unk4 = 0; + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + PlaySE12WithPanning(SE_POKE_DEAD, -64); + gSprites[gObjectBankIDs[gActiveBank]].data1 = 0; + gSprites[gObjectBankIDs[gActiveBank]].data2 = 5; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80105EC; + gBattleBankFunc[gActiveBank] = sub_802DE10; + } + } +} + +void PlayerHandlecmd11(void) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 2, 0, 16, 0); + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd12(void) +{ + ewram17840.unk8 = 4; + gDoingBattleAnim = 1; + move_anim_start_t4(gActiveBank, gActiveBank, GetBankByPlayerAI(1), 3); + gBattleBankFunc[gActiveBank] = bx_wait_t1; +} + +void PlayerHandleBallThrow(void) +{ + u8 var = gBattleBufferA[gActiveBank][1]; + + ewram17840.unk8 = var; + gDoingBattleAnim = 1; + move_anim_start_t4(gActiveBank, gActiveBank, GetBankByPlayerAI(1), 3); + gBattleBankFunc[gActiveBank] = bx_wait_t1; +} + +void PlayerHandlePuase(void) +{ + u8 var = gBattleBufferA[gActiveBank][1]; + + // WTF is this?? + while (var != 0) + var--; + + PlayerBufferExecCompleted(); +} + +void PlayerHandleMoveAnimation(void) +{ + if (!mplay_80342A4(gActiveBank)) + { + u16 r0 = gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8); + + gUnknown_0202F7C4 = gBattleBufferA[gActiveBank][3]; + gMovePowerMoveAnim = gBattleBufferA[gActiveBank][4] | (gBattleBufferA[gActiveBank][5] << 8); + gMoveDmgMoveAnim = gBattleBufferA[gActiveBank][6] | (gBattleBufferA[gActiveBank][7] << 8) | (gBattleBufferA[gActiveBank][8] << 16) | (gBattleBufferA[gActiveBank][9] << 24); + gHappinessMoveAnim = gBattleBufferA[gActiveBank][10]; + gWeatherMoveAnim = gBattleBufferA[gActiveBank][12] | (gBattleBufferA[gActiveBank][13] << 8); + gDisableStructMoveAnim = (u32 *)&gBattleBufferA[gActiveBank][16]; + gPID_perBank[gActiveBank] = *gDisableStructMoveAnim; + if (sub_8031720(r0, gUnknown_0202F7C4) != 0) + { + // Dead code. sub_8031720 always returns 0. + PlayerBufferExecCompleted(); + } + else + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_8030190; + } + } +} + +void sub_8030190(void) +{ + u16 r4 = gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8); + u8 r7 = gBattleBufferA[gActiveBank][11]; + + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite == 1 && ewram17800[gActiveBank].unk0_3 == 0) + { + ewram17800[gActiveBank].unk0_3 = 1; + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + } + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (ewram17810[gActiveBank].unk0_6 == 0) + { + sub_80326EC(0); + ExecuteMoveAnim(r4); + ewram17810[gActiveBank].unk4 = 2; + } + break; + case 2: + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + sub_80326EC(1); + if (ewram17800[gActiveBank].substituteSprite == 1 && r7 < 2) + { + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + ewram17800[gActiveBank].unk0_3 = 0; + } + ewram17810[gActiveBank].unk4 = 3; + } + break; + case 3: + if (ewram17810[gActiveBank].unk0_6 == 0) + { + sub_8031F24(); + sub_80324BC(gActiveBank, gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + ewram17810[gActiveBank].unk4 = 0; + PlayerBufferExecCompleted(); + } + break; + } +} + +void PlayerHandlePrintString(void) +{ + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + BufferStringBattle(*(u16 *)&gBattleBufferA[gActiveBank][2]); + sub_8002EB0(&gUnknown_03004210, gDisplayedStringBattle, 0x90, 2, 15); + gBattleBankFunc[gActiveBank] = sub_802DF18; +} + +void PlayerHandlePrintStringPlayerOnly(void) +{ + if (GetBankSide(gActiveBank) == 0) + PlayerHandlePrintString(); + else + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd18(void) +{ + int r4; + + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 160; + FillWindowRect(&gUnknown_03004210, 10, 2, 15, 27, 18); + FillWindowRect(&gUnknown_03004210, 10, 2, 35, 16, 38); + + gBattleBankFunc[gActiveBank] = sub_802C098; + + InitWindow(&gUnknown_03004210, gUnknown_08400CF3, 400, 18, 35); + sub_8002F44(&gUnknown_03004210); + sub_814A5C0(0, 0xFFFF, 12, 11679, 0); + + for (r4 = 0; r4 < 4; r4++) + nullsub_8(r4); + + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + + StrCpyDecodeToDisplayedStringBattle((u8 *) gUnknown_08400CA8); + InitWindow(&gUnknown_03004210, gDisplayedStringBattle, SUB_803037C_TILE_DATA_OFFSET, 2, 35); + sub_8002F44(&gUnknown_03004210); +} + +void PlayerHandlecmd19() +{ +} + +void PlayerHandlecmd20(void) +{ + sub_814A5C0(0, 0xFFFF, 12, 0x2D9F, 0); + sub_80304A8(); + gBattleBankFunc[gActiveBank] = sub_802C68C; +} + +void sub_80304A8(void) +{ + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 320; + sub_802E1B0(); + gUnknown_03004344 = 0xFF; + sub_802E3B4(gMoveSelectionCursor[gActiveBank], 0); + if (gBattleBufferA[gActiveBank][2] != 1) + { + InitWindow(&gUnknown_03004210, gUnknown_08400D38, 656, 23, 55); + sub_8002F44(&gUnknown_03004210); + } + sub_802E220(); + sub_802E2D4(); +} + +void PlayerHandleOpenBag(void) +{ + s32 i; + + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gBattleBankFunc[gActiveBank] = sub_802E004; + gBankInMenu = gActiveBank; + for (i = 0; i < 3; i++) + gUnknown_02038470[i] = gBattleBufferA[gActiveBank][1 + i]; +} + +void PlayerHandlecmd22(void) +{ + s32 i; + + gUnknown_0300434C[gActiveBank] = CreateTask(TaskDummy, 0xFF); + gTasks[gUnknown_0300434C[gActiveBank]].data[0] = gBattleBufferA[gActiveBank][1] & 0xF; + ewram[0x16054] = gBattleBufferA[gActiveBank][1] >> 4; + ewram[0x1609D] = gBattleBufferA[gActiveBank][2]; + ewram[0x160C0] = gBattleBufferA[gActiveBank][3]; + for (i = 0; i < 3; i++) + gUnknown_02038470[i] = gBattleBufferA[gActiveBank][4 + i]; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gBattleBankFunc[gActiveBank] = sub_802DF30; + gBankInMenu = gActiveBank; +} + +void PlayerHandlecmd23(void) +{ + BattleMusicStop(); + BeginNormalPaletteFade(0xFFFFFFFF, 2, 0, 16, 0); + PlayerBufferExecCompleted(); +} + +void PlayerHandleHealthBarUpdate(void) +{ + s16 r7; + + load_gfxc_health_bar(0); + r7 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + if (r7 != 0x7FFF) + { + u32 maxHP = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + u32 curHP = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, curHP, r7); + } + else + { + u32 maxHP = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, 0, r7); + sub_80440EC(gHealthboxIDs[gActiveBank], 0, 0); + } + gBattleBankFunc[gActiveBank] = bx_t1_healthbar_update; +} + +void PlayerHandleExpBarUpdate(void) +{ + u8 r7 = gBattleBufferA[gActiveBank][1]; + + if (GetMonData(&gPlayerParty[r7], MON_DATA_LEVEL) >= 100) + { + PlayerBufferExecCompleted(); + } + else + { + u16 r4; + u8 taskId; + + load_gfxc_health_bar(1); + GetMonData(&gPlayerParty[r7], MON_DATA_SPECIES); // unused return value + r4 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + taskId = CreateTask(sub_802D924, 10); + gTasks[taskId].data[0] = r7; + gTasks[taskId].data[1] = r4; + gTasks[taskId].data[2] = gActiveBank; + gBattleBankFunc[gActiveBank] = nullsub_91; + } +} + +void PlayerHandleStatusIconUpdate(void) +{ + if (!mplay_80342A4(gActiveBank)) + { + sub_8045A5C(gHealthboxIDs[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], 9); + ewram17810[gActiveBank].unk0_4 = 0; + gBattleBankFunc[gActiveBank] = sub_802E434; + } +} + +void PlayerHandleStatusAnimation(void) +{ + if (!mplay_80342A4(gActiveBank)) + { + move_anim_start_t2_for_situation( + gBattleBufferA[gActiveBank][1], + gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8) | (gBattleBufferA[gActiveBank][4] << 16) | (gBattleBufferA[gActiveBank][5] << 24)); + gBattleBankFunc[gActiveBank] = sub_802E434; + } +} + +void PlayerHandleStatusXor(void) +{ + u8 val = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_STATUS) ^ gBattleBufferA[gActiveBank][1]; + + SetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_STATUS, &val); + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd29(void) +{ + PlayerBufferExecCompleted(); +} + +void PlayerHandleDMATransfer(void) +{ + u32 val1 = gBattleBufferA[gActiveBank][1] + | (gBattleBufferA[gActiveBank][2] << 8) + | (gBattleBufferA[gActiveBank][3] << 16) + | (gBattleBufferA[gActiveBank][4] << 24); + u16 val2 = gBattleBufferA[gActiveBank][5] | (gBattleBufferA[gActiveBank][6] << 8); + + const u8 *src = &gBattleBufferA[gActiveBank][7]; + u8 *dst = (u8 *)val1; + u32 size = val2; + + while (1) + { + if (size <= 0x1000) + { + DmaCopy16(3, src, dst, size); + break; + } + DmaCopy16(3, src, dst, 0x1000); + src += 0x1000; + dst += 0x1000; + size -= 0x1000; + } + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd31(void) +{ + PlayBGM(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd32(void) +{ + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd33(void) +{ + Emitcmd33(1, 0, 0); + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd34(void) +{ + Emitcmd34(1, 0, 0); + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd35(void) +{ + Emitcmd35(1, 0); + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd36(void) +{ + Emitcmd36(1, 0); + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd37(void) +{ + gUnknown_020238C8.unk0_0 = 0; + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd38(void) +{ + gUnknown_020238C8.unk0_0 = gBattleBufferA[gActiveBank][1]; + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd39(void) +{ + gUnknown_020238C8.unk0_7 = 0; + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd40(void) +{ + gUnknown_020238C8.unk0_7 ^= 1; + PlayerBufferExecCompleted(); +} + +void PlayerHandleHitAnimation(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].invisible == TRUE) + { + PlayerBufferExecCompleted(); + } + else + { + gDoingBattleAnim = 1; + gSprites[gObjectBankIDs[gActiveBank]].data1 = 0; + sub_8047858(gActiveBank); + gBattleBankFunc[gActiveBank] = bx_blink_t1; + } +} + +void PlayerHandlecmd42(void) +{ + PlayerBufferExecCompleted(); +} + +void PlayerHandleEffectivenessSound(void) +{ + s8 pan; + + if (GetBankSide(gActiveBank) == 0) + pan = -64; + else + pan = 63; + PlaySE12WithPanning(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8), pan); + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd44(void) +{ + PlayFanfare(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + PlayerBufferExecCompleted(); +} + +void PlayerHandleFaintingCry(void) +{ + u16 species = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES); + + PlayCry3(species, -25, 5); + PlayerBufferExecCompleted(); +} + +void PlayerHandleIntroSlide(void) +{ + sub_80E43C0(gBattleBufferA[gActiveBank][1]); + gUnknown_02024DE8 |= 1; + PlayerBufferExecCompleted(); +} + +void PlayerHandleTrainerBallThrow(void) +{ + u8 paletteNum; + u8 taskId; + + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 50; + gSprites[gObjectBankIDs[gActiveBank]].data2 = -40; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + gSprites[gObjectBankIDs[gActiveBank]].data5 = gActiveBank; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], sub_8030E38); + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], 1); + paletteNum = AllocSpritePalette(0xD6F8); + LoadCompressedPalette(gTrainerBackPicPaletteTable[gSaveBlock2.playerGender].data, 0x100 + paletteNum * 16, 32); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = paletteNum; + taskId = CreateTask(task05_08033660, 5); + gTasks[taskId].data[0] = gActiveBank; + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + ewram17810[4].unk9 |= 1; + gBattleBankFunc[gActiveBank] = nullsub_91; +} + +void sub_8030E38(struct Sprite *sprite) +{ + u8 r4 = sprite->data5; + + FreeSpriteOamMatrix(sprite); + FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(sprite->oam.paletteNum)); + DestroySprite(sprite); + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[r4]], r4); + StartSpriteAnim(&gSprites[gObjectBankIDs[r4]], 0); +} + +void task05_08033660(u8 taskId) +{ + if (gTasks[taskId].data[1] < 31) + { + gTasks[taskId].data[1]++; + } + else + { + u8 savedActiveBank = gActiveBank; + + gActiveBank = gTasks[taskId].data[0]; + if (!IsDoubleBattle() || (gBattleTypeFlags & 0x40)) + { + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_802F934(gActiveBank, 0); + } + else + { + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_802F934(gActiveBank, 0); + gActiveBank ^= 2; + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + sub_802F934(gActiveBank, 0); + gActiveBank ^= 2; + } + gBattleBankFunc[gActiveBank] = sub_802D500; + gActiveBank = savedActiveBank; + DestroyTask(taskId); + } +} + +void PlayerHandlecmd48(void) +{ + if (gBattleBufferA[gActiveBank][1] != 0 && GetBankSide(gActiveBank) == 0) + { + PlayerBufferExecCompleted(); + } + else + { + ewram17810[gActiveBank].unk0_0 = 1; + gUnknown_02024E68[gActiveBank] = sub_8044804(gActiveBank, (struct BattleInterfaceStruct2 *)&gBattleBufferA[gActiveBank][4], gBattleBufferA[gActiveBank][1], gBattleBufferA[gActiveBank][2]); + ewram17810[gActiveBank].unk5 = 0; + if (gBattleBufferA[gActiveBank][2] != 0) + ewram17810[gActiveBank].unk5 = 0x5D; + gBattleBankFunc[gActiveBank] = sub_8031064; + } +} + +void sub_8031064(void) +{ + if (ewram17810[gActiveBank].unk5++ > 0x5C) + { + ewram17810[gActiveBank].unk5 = 0; + PlayerBufferExecCompleted(); + } +} + +void PlayerHandlecmd49(void) +{ + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd50(void) +{ + dp11b_obj_free(gActiveBank, 1); + dp11b_obj_free(gActiveBank, 0); + PlayerBufferExecCompleted(); +} + +void PlayerHandleSpriteInvisibility(void) +{ + if (AnimBankSpriteExists(gActiveBank)) + { + gSprites[gObjectBankIDs[gActiveBank]].invisible = gBattleBufferA[gActiveBank][1]; + sub_8031F88(gActiveBank); + } + PlayerBufferExecCompleted(); +} + +void PlayerHandleBattleAnimation(void) +{ + if (!mplay_80342A4(gActiveBank)) + { + u8 val2 = gBattleBufferA[gActiveBank][1]; + u16 val = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + + if (move_anim_start_t3(gActiveBank, gActiveBank, gActiveBank, val2, val)) + PlayerBufferExecCompleted(); + else + gBattleBankFunc[gActiveBank] = sub_802E460; + } +} + +void PlayerHandleLinkStandbyMsg(void) +{ + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + b_link_standby_message(); + // fall through + case 1: + dp11b_obj_free(gActiveBank, 1); + dp11b_obj_free(gActiveBank, 0); + break; + case 2: + b_link_standby_message(); + break; + } + PlayerBufferExecCompleted(); +} + +void PlayerHandleResetActionMoveSelection(void) +{ + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + gActionSelectionCursor[gActiveBank] = 0; + gMoveSelectionCursor[gActiveBank] = 0; + break; + case 1: + gActionSelectionCursor[gActiveBank] = 0; + break; + case 2: + gMoveSelectionCursor[gActiveBank] = 0; + break; + } + PlayerBufferExecCompleted(); +} + +void PlayerHandlecmd55(void) +{ + gBattleOutcome = gBattleBufferA[gActiveBank][1]; + FadeOutMapMusic(5); + BeginFastPaletteFade(3); + PlayerBufferExecCompleted(); + gBattleBankFunc[gActiveBank] = sub_802D18C; +} + +void PlayerHandlecmd56(void) +{ +} diff --git a/src/battle/battle_controller_safari.c b/src/battle/battle_controller_safari.c new file mode 100644 index 000000000..e05578c31 --- /dev/null +++ b/src/battle/battle_controller_safari.c @@ -0,0 +1,709 @@ +#include "global.h" +#include "battle_anim_81258BC.h" +#include "battle.h" +#include "battle_message.h" +#include "data2.h" +#include "link.h" +#include "main.h" +#include "menu_cursor.h" +#include "palette.h" +#include "rom3.h" +#include "songs.h" +#include "sound.h" +#include "text.h" +#include "util.h" + +extern struct Window gUnknown_03004210; +extern u8 gDisplayedStringBattle[]; +extern u8 gActionSelectionCursor[]; + +extern const u8 gUnknown_08400CBB[]; +extern u8 gActiveBank; +extern const u8 gUnknown_08400D15[]; + +extern void *gBattleBankFunc[]; +extern u16 gUnknown_030042A0; +extern u16 gUnknown_030042A4; +extern u8 gBattleBufferA[][0x200]; +extern bool8 gDoingBattleAnim; +extern u8 gObjectBankIDs[]; +extern struct SpriteTemplate gUnknown_02024E8C; +extern u16 gBattleTypeFlags; +extern u32 gBattleExecBuffer; +extern u16 gScriptItemId; +extern MainCallback gPreBattleCallback1; +extern u8 gBankInMenu; +extern u8 gHealthboxIDs[]; +extern u16 gBattlePartyID[]; +extern u16 gUnknown_02024DE8; +extern u8 gBattleOutcome; + +extern u8 GetBankSide(u8); +extern u8 GetBankByPlayerAI(u8); +extern u8 GetBankIdentity(u8); +extern void LoadPlayerTrainerBankSprite(); +extern u8 sub_8079E90(); +extern void sub_80313A0(struct Sprite *); +extern void sub_810BADC(void); +extern void sub_8045A5C(); +extern void sub_80E43C0(); +extern void sub_804777C(); +extern void sub_8043DFC(); +extern bool8 move_anim_start_t3(); + +#if ENGLISH +#define SUB_812BB10_TILE_DATA_OFFSET 440 +#elif GERMAN +#define SUB_812BB10_TILE_DATA_OFFSET 444 +#endif + +// this file's functions +void SafariHandleGetAttributes(void); +void SafariHandlecmd1(void); +void SafariHandleSetAttributes(void); +void SafariHandlecmd3(void); +void SafariHandleLoadPokeSprite(void); +void SafariHandleSendOutPoke(void); +void SafariHandleReturnPokeToBall(void); +void SafariHandleTrainerThrow(void); +void SafariHandleTrainerSlide(void); +void SafariHandleTrainerSlideBack(void); +void SafariHandlecmd10(void); +void SafariHandlecmd11(void); +void SafariHandlecmd12(void); +void SafariHandleBallThrow(void); +void SafariHandlePuase(void); +void SafariHandleMoveAnimation(void); +void SafariHandlePrintString(void); +void SafariHandlePrintStringPlayerOnly(void); +void SafariHandlecmd18(void); +void SafariHandlecmd19(void); +void SafariHandlecmd20(void); +void SafariHandleOpenBag(void); +void SafariHandlecmd22(void); +void SafariHandlecmd23(void); +void SafariHandleHealthBarUpdate(void); +void SafariHandleExpBarUpdate(void); +void SafariHandleStatusIconUpdate(void); +void SafariHandleStatusAnimation(void); +void SafariHandleStatusXor(void); +void SafariHandlecmd29(void); +void SafariHandleDMATransfer(void); +void SafariHandlecmd31(void); +void SafariHandlecmd32(void); +void SafariHandlecmd33(void); +void SafariHandlecmd34(void); +void SafariHandlecmd35(void); +void SafariHandlecmd36(void); +void SafariHandlecmd37(void); +void SafariHandlecmd38(void); +void SafariHandlecmd39(void); +void SafariHandlecmd40(void); +void SafariHandleHitAnimation(void); +void SafariHandlecmd42(void); +void SafariHandleEffectivenessSound(void); +void SafariHandlecmd44(void); +void SafariHandleFaintingCry(void); +void SafariHandleIntroSlide(void); +void SafariHandleTrainerBallThrow(void); +void SafariHandlecmd48(void); +void SafariHandlecmd49(void); +void SafariHandlecmd50(void); +void SafariHandleSpriteInvisibility(void); +void SafariHandleBattleAnimation(void); +void SafariHandleLinkStandbyMsg(void); +void SafariHandleResetActionMoveSelection(void); +void SafariHandlecmd55(void); +void SafariHandlecmd56(void); + +// const data +typedef void (*BattleBufferCmd) (void); +const BattleBufferCmd gSafariBufferCommands[] = +{ + SafariHandleGetAttributes, + SafariHandlecmd1, + SafariHandleSetAttributes, + SafariHandlecmd3, + SafariHandleLoadPokeSprite, + SafariHandleSendOutPoke, + SafariHandleReturnPokeToBall, + SafariHandleTrainerThrow, + SafariHandleTrainerSlide, + SafariHandleTrainerSlideBack, + SafariHandlecmd10, + SafariHandlecmd11, + SafariHandlecmd12, + SafariHandleBallThrow, + SafariHandlePuase, + SafariHandleMoveAnimation, + SafariHandlePrintString, + SafariHandlePrintStringPlayerOnly, + SafariHandlecmd18, + SafariHandlecmd19, + SafariHandlecmd20, + SafariHandleOpenBag, + SafariHandlecmd22, + SafariHandlecmd23, + SafariHandleHealthBarUpdate, + SafariHandleExpBarUpdate, + SafariHandleStatusIconUpdate, + SafariHandleStatusAnimation, + SafariHandleStatusXor, + SafariHandlecmd29, + SafariHandleDMATransfer, + SafariHandlecmd31, + SafariHandlecmd32, + SafariHandlecmd33, + SafariHandlecmd34, + SafariHandlecmd35, + SafariHandlecmd36, + SafariHandlecmd37, + SafariHandlecmd38, + SafariHandlecmd39, + SafariHandlecmd40, + SafariHandleHitAnimation, + SafariHandlecmd42, + SafariHandleEffectivenessSound, + SafariHandlecmd44, + SafariHandleFaintingCry, + SafariHandleIntroSlide, + SafariHandleTrainerBallThrow, + SafariHandlecmd48, + SafariHandlecmd49, + SafariHandlecmd50, + SafariHandleSpriteInvisibility, + SafariHandleBattleAnimation, + SafariHandleLinkStandbyMsg, + SafariHandleResetActionMoveSelection, + SafariHandlecmd55, + SafariHandlecmd56, +}; +// code + +void SafariBufferExecCompleted(void); +void bx_wait_t6(void); +void sub_812B65C(void); +void SafariBufferRunCommand(void); +void sub_812B758(void); + +void unref_sub_812B464(void) +{ +} + +void SetBankFuncToSafariBufferRunCommand(void) +{ + gBattleBankFunc[gActiveBank] = SafariBufferRunCommand; +} + +void SafariBufferRunCommand(void) +{ + if (gBattleExecBuffer & gBitTable[gActiveBank]) + { + if (gBattleBufferA[gActiveBank][0] < 0x39) + gSafariBufferCommands[gBattleBufferA[gActiveBank][0]](); + else + SafariBufferExecCompleted(); + } +} + +void bx_battle_menu_t6_2(void) +{ + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + DestroyMenuCursor(); + + // Useless switch statement. + switch (gActionSelectionCursor[gActiveBank]) + { + case 0: + Emitcmd33(1, 5, 0); + break; + case 1: + Emitcmd33(1, 6, 0); + break; + case 2: + Emitcmd33(1, 7, 0); + break; + case 3: + Emitcmd33(1, 8, 0); + break; + } + SafariBufferExecCompleted(); + } + else if (gMain.newKeys & DPAD_LEFT) + { + if (gActionSelectionCursor[gActiveBank] & 1) + { + PlaySE(SE_SELECT); + nullsub_8(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 1; + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_RIGHT) + { + if (!(gActionSelectionCursor[gActiveBank] & 1)) + { + PlaySE(SE_SELECT); + nullsub_8(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 1; + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_UP) + { + if (gActionSelectionCursor[gActiveBank] & 2) + { + PlaySE(SE_SELECT); + nullsub_8(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 2; + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + } + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (!(gActionSelectionCursor[gActiveBank] & 2)) + { + PlaySE(SE_SELECT); + nullsub_8(gActionSelectionCursor[gActiveBank]); + gActionSelectionCursor[gActiveBank] ^= 2; + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + } + } +} + +void sub_812B65C(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + SafariBufferExecCompleted(); +} + +void sub_812B694(void) +{ + if (gUnknown_03004210.state == 0) + SafariBufferExecCompleted(); +} + +void sub_812B6AC(void) +{ + if (!gPaletteFade.active) + { + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } +} + +void bx_wait_t6(void) +{ + if (!gDoingBattleAnim || !ewram17810[gActiveBank].unk0_6) + SafariBufferExecCompleted(); +} + +void sub_812B724(void) +{ + if (!gPaletteFade.active) + { + gBattleBankFunc[gActiveBank] = sub_812B758; + sub_810BADC(); + } +} + +void sub_812B758(void) +{ + if (gMain.callback2 == sub_800F808 && !gPaletteFade.active) + { + Emitcmd35(1, gScriptItemId); + SafariBufferExecCompleted(); + } +} + +void sub_812B794(void) +{ + if (!ewram17810[gActiveBank].unk0_5) + SafariBufferExecCompleted(); +} + +void SafariBufferExecCompleted(void) +{ + gBattleBankFunc[gActiveBank] = SafariBufferRunCommand; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + u8 playerId = GetMultiplayerId(); + + PrepareBufferDataTransferLink(2, 4, &playerId); + gBattleBufferA[gActiveBank][0] = 0x38; + } + else + { + gBattleExecBuffer &= ~gBitTable[gActiveBank]; + } +} + +void unref_sub_812B838(void) +{ + if (!ewram17810[gActiveBank].unk0_4) + SafariBufferExecCompleted(); +} + +void SafariHandleGetAttributes(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd1(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleSetAttributes(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd3(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleLoadPokeSprite(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleSendOutPoke(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleReturnPokeToBall(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleTrainerThrow(void) +{ + LoadPlayerTrainerBankSprite(gSaveBlock2.playerGender, gActiveBank); + GetMonSpriteTemplate_803C5A0(gSaveBlock2.playerGender, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + 80, + (8 - gTrainerBackPicCoords[gSaveBlock2.playerGender].coords) * 4 + 80, + 30); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = 240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = -2; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_812B65C; +} + +void SafariHandleTrainerSlide(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleTrainerSlideBack(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd10(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd11(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd12(void) +{ + ewram17840.unk8 = 4; + gDoingBattleAnim = 1; + move_anim_start_t4(gActiveBank, gActiveBank, GetBankByPlayerAI(1), 4); + gBattleBankFunc[gActiveBank] = bx_wait_t6; +} + +void SafariHandleBallThrow(void) +{ + u8 var = gBattleBufferA[gActiveBank][1]; + + ewram17840.unk8 = var; + gDoingBattleAnim = 1; + move_anim_start_t4(gActiveBank, gActiveBank, GetBankByPlayerAI(1), 4); + gBattleBankFunc[gActiveBank] = bx_wait_t6; +} + +// TODO: spell Pause correctly +void SafariHandlePuase(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleMoveAnimation(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlePrintString(void) +{ + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + BufferStringBattle(*(u16 *)&gBattleBufferA[gActiveBank][2]); + sub_8002EB0(&gUnknown_03004210, gDisplayedStringBattle, 144, 2, 15); + gBattleBankFunc[gActiveBank] = sub_812B694; +} + +void SafariHandlePrintStringPlayerOnly(void) +{ + if (GetBankSide(gActiveBank) == 0) + SafariHandlePrintString(); + else + SafariBufferExecCompleted(); +} + +void SafariHandlecmd18(void) +{ + int i; + + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 160; + gUnknown_03004210.paletteNum = 0; + FillWindowRect_DefaultPalette(&gUnknown_03004210, 10, 2, 15, 27, 18); + FillWindowRect_DefaultPalette(&gUnknown_03004210, 10, 2, 35, 16, 36); + gBattleBankFunc[gActiveBank] = bx_battle_menu_t6_2; + + InitWindow(&gUnknown_03004210, gUnknown_08400D15, 400, 18, 35); + sub_8002F44(&gUnknown_03004210); + sub_814A5C0(0, 0xFFFF, 12, 11679, 0); + + for (i = 0; i < 4; i++) + nullsub_8(i); + + sub_802E3E4(gActionSelectionCursor[gActiveBank], 0); + StrCpyDecodeToDisplayedStringBattle((u8 *) gUnknown_08400CBB); + + InitWindow(&gUnknown_03004210, gDisplayedStringBattle, SUB_812BB10_TILE_DATA_OFFSET, 2, 35); + sub_8002F44(&gUnknown_03004210); +} + +void SafariHandlecmd19(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd20(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleOpenBag(void) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gBattleBankFunc[gActiveBank] = sub_812B724; + gBankInMenu = gActiveBank; +} + +void SafariHandlecmd22(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd23(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleHealthBarUpdate(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleExpBarUpdate(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleStatusIconUpdate(void) +{ + sub_8045A5C(gHealthboxIDs[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], 11); + SafariBufferExecCompleted(); +} + +void SafariHandleStatusAnimation(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleStatusXor(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd29(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleDMATransfer(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd31(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd32(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd33(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd34(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd35(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd36(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd37(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd38(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd39(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd40(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleHitAnimation(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd42(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleEffectivenessSound(void) +{ + s8 pan; + + if (GetBankSide(gActiveBank) == 0) + pan = -64; + else + pan = 63; + PlaySE12WithPanning(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8), pan); + SafariBufferExecCompleted(); +} + +void SafariHandlecmd44(void) +{ + PlayFanfare(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + SafariBufferExecCompleted(); +} + +void SafariHandleFaintingCry(void) +{ + u16 species = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES); + + PlayCry1(species, 25); + SafariBufferExecCompleted(); +} + +void SafariHandleIntroSlide(void) +{ + sub_80E43C0(gBattleBufferA[gActiveBank][1]); + gUnknown_02024DE8 |= 1; + SafariBufferExecCompleted(); +} + +void SafariHandleTrainerBallThrow(void) +{ + sub_8045A5C(gHealthboxIDs[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], 10); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + SafariBufferExecCompleted(); +} + +void SafariHandlecmd48(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd49(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd50(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleSpriteInvisibility(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleBattleAnimation(void) +{ + u8 r3 = gBattleBufferA[gActiveBank][1]; + u16 r4 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + + if (move_anim_start_t3(gActiveBank, gActiveBank, gActiveBank, r3, r4) != 0) + SafariBufferExecCompleted(); + else + gBattleBankFunc[gActiveBank] = sub_812B794; +} + +void SafariHandleLinkStandbyMsg(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandleResetActionMoveSelection(void) +{ + SafariBufferExecCompleted(); +} + +void SafariHandlecmd55(void) +{ + gBattleOutcome = gBattleBufferA[gActiveBank][1]; + FadeOutMapMusic(5); + BeginFastPaletteFade(3); + SafariBufferExecCompleted(); + if ((gBattleTypeFlags & BATTLE_TYPE_LINK) && !(gBattleTypeFlags & BATTLE_TYPE_WILD)) + gBattleBankFunc[gActiveBank] = sub_812B6AC; +} + +void SafariHandlecmd56(void) +{ +} diff --git a/src/battle/battle_controller_wally.c b/src/battle/battle_controller_wally.c new file mode 100644 index 000000000..bf6ef0892 --- /dev/null +++ b/src/battle/battle_controller_wally.c @@ -0,0 +1,1611 @@ +#include "global.h" +#include "battle.h" +#include "battle_interface.h" +#include "battle_message.h" +#include "data2.h" +#include "link.h" +#include "main.h" +#include "menu_cursor.h" +#include "palette.h" +#include "pokemon.h" +#include "rom3.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "item_use.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "util.h" + +//Possibly PokemonSubstruct1 +struct UnknownStruct3 +{ + u16 moves[4]; + u8 pp[4]; + u8 ppBonuses; +}; + +extern u8 gActiveBank; +extern void (*gBattleBankFunc[])(void); +extern u32 gBattleExecBuffer; +extern u8 gBattleBufferA[][0x200]; +extern u8 gObjectBankIDs[]; +extern MainCallback gPreBattleCallback1; +extern bool8 gDoingBattleAnim; +extern u16 gBattlePartyID[]; +extern u8 gHealthboxIDs[]; +extern u16 gBattleTypeFlags; +extern u16 gMovePowerMoveAnim; +extern u32 gMoveDmgMoveAnim; +extern u8 gHappinessMoveAnim; +extern u16 gWeatherMoveAnim; +extern u32 *gDisableStructMoveAnim; +extern u32 gPID_perBank[]; +extern void (*gAnimScriptCallback)(void); +extern bool8 gAnimScriptActive; +extern u8 gDisplayedStringBattle[]; +extern u8 gBankInMenu; +extern u8 gBattleMonForms[]; +extern u8 gBattleOutcome; +extern u16 gUnknown_02024DE8; +extern u8 gUnknown_02024E68[]; +extern struct SpriteTemplate gUnknown_02024E8C; +extern u8 gUnknown_0202F7C4; +extern struct Window gUnknown_03004210; +extern u16 gUnknown_030042A0; +extern u16 gUnknown_030042A4; +extern u8 gUnknown_0300434C[]; +extern const u8 gUnknown_08400CCC[]; +extern const u8 gUnknown_08400CF3[]; + +// TODO: include rom3.h when my other PR gets merged +extern void Emitcmd33(u8, u8, u16); +extern void Emitcmd35(u8, u16); + +extern void nullsub_14(void); +extern void PrepareBagForWallyTutorial(void); +extern void sub_8141828(); +extern void sub_8045A5C(); +extern void sub_804777C(); +extern void sub_8043DFC(); +extern bool8 IsDoubleBattle(void); +extern void c3_0802FDF4(u8); +extern void PlayerHandlecmd1(void); +extern void LoadPlayerTrainerBankSprite(); +extern u8 GetBankIdentity(u8); +extern void sub_80313A0(struct Sprite *); +extern u8 GetBankByPlayerAI(u8); +extern u8 sub_8031720(); +extern void ExecuteMoveAnim(); +extern void sub_80326EC(); +extern void sub_8031F24(void); +extern void sub_80324BC(); +extern void BufferStringBattle(); +extern u8 GetBankSide(u8); +extern void sub_80304A8(void); +extern void sub_8047858(); +extern void sub_80E43C0(); +extern void oamt_add_pos2_onto_pos1(); +extern void sub_8078B34(struct Sprite *); +extern void sub_8030E38(struct Sprite *); +extern void StoreSpriteCallbackInData6(); +extern u8 sub_8046400(); +extern u8 sub_8077ABC(); +extern u8 sub_8077F68(); +extern u8 sub_8079E90(); +extern void sub_80312F0(struct Sprite *); +extern bool8 move_anim_start_t3(); + +// this file's functions + +void WallyBufferRunCommand(void); +void sub_81374FC(void); +void sub_81376B8(void); +void WallyBufferExecCompleted(void); +u32 sub_8137A84(u8, u8 *); +void sub_8138294(u8); +void sub_81390D0(void); +void sub_8139A2C(u8); + +void WallyHandleGetAttributes(void); +void WallyHandlecmd1(void); +void WallyHandleSetAttributes(void); +void WallyHandlecmd3(void); +void WallyHandleLoadPokeSprite(void); +void WallyHandleSendOutPoke(void); +void WallyHandleReturnPokeToBall(void); +void WallyHandleTrainerThrow(void); +void WallyHandleTrainerSlide(void); +void WallyHandleTrainerSlideBack(void); +void WallyHandlecmd10(void); +void WallyHandlecmd11(void); +void WallyHandlecmd12(void); +void WallyHandleBallThrow(void); +void WallyHandlePuase(void); +void WallyHandleMoveAnimation(void); +void WallyHandlePrintString(void); +void WallyHandlePrintStringPlayerOnly(void); +void WallyHandlecmd18(void); +void WallyHandlecmd19(void); +void WallyHandlecmd20(void); +void WallyHandleOpenBag(void); +void WallyHandlecmd22(void); +void WallyHandlecmd23(void); +void WallyHandleHealthBarUpdate(void); +void WallyHandleExpBarUpdate(void); +void WallyHandleStatusIconUpdate(void); +void WallyHandleStatusAnimation(void); +void WallyHandleStatusXor(void); +void WallyHandlecmd29(void); +void WallyHandleDMATransfer(void); +void WallyHandlecmd31(void); +void WallyHandlecmd32(void); +void WallyHandlecmd33(void); +void WallyHandlecmd34(void); +void WallyHandlecmd35(void); +void WallyHandlecmd36(void); +void WallyHandlecmd37(void); +void WallyHandlecmd38(void); +void WallyHandlecmd39(void); +void WallyHandlecmd40(void); +void WallyHandleHitAnimation(void); +void WallyHandlecmd42(void); +void WallyHandleEffectivenessSound(void); +void WallyHandlecmd44(void); +void WallyHandleFaintingCry(void); +void WallyHandleIntroSlide(void); +void WallyHandleTrainerBallThrow(void); +void WallyHandlecmd48(void); +void WallyHandlecmd49(void); +void WallyHandlecmd50(void); +void WallyHandleSpriteInvisibility(void); +void WallyHandleBattleAnimation(void); +void WallyHandleLinkStandbyMsg(void); +void WallyHandleResetActionMoveSelection(void); +void WallyHandlecmd55(void); +void WallyHandlecmd56(void); + +// const data + +typedef void (*BattleBufferCmd) (void); +static const BattleBufferCmd gWallyBufferCommands[] = +{ + WallyHandleGetAttributes, + WallyHandlecmd1, + WallyHandleSetAttributes, + WallyHandlecmd3, + WallyHandleLoadPokeSprite, + WallyHandleSendOutPoke, + WallyHandleReturnPokeToBall, + WallyHandleTrainerThrow, + WallyHandleTrainerSlide, + WallyHandleTrainerSlideBack, + WallyHandlecmd10, + WallyHandlecmd11, + WallyHandlecmd12, + WallyHandleBallThrow, + WallyHandlePuase, + WallyHandleMoveAnimation, + WallyHandlePrintString, + WallyHandlePrintStringPlayerOnly, + WallyHandlecmd18, + WallyHandlecmd19, + WallyHandlecmd20, + WallyHandleOpenBag, + WallyHandlecmd22, + WallyHandlecmd23, + WallyHandleHealthBarUpdate, + WallyHandleExpBarUpdate, + WallyHandleStatusIconUpdate, + WallyHandleStatusAnimation, + WallyHandleStatusXor, + WallyHandlecmd29, + WallyHandleDMATransfer, + WallyHandlecmd31, + WallyHandlecmd32, + WallyHandlecmd33, + WallyHandlecmd34, + WallyHandlecmd35, + WallyHandlecmd36, + WallyHandlecmd37, + WallyHandlecmd38, + WallyHandlecmd39, + WallyHandlecmd40, + WallyHandleHitAnimation, + WallyHandlecmd42, + WallyHandleEffectivenessSound, + WallyHandlecmd44, + WallyHandleFaintingCry, + WallyHandleIntroSlide, + WallyHandleTrainerBallThrow, + WallyHandlecmd48, + WallyHandlecmd49, + WallyHandlecmd50, + WallyHandleSpriteInvisibility, + WallyHandleBattleAnimation, + WallyHandleLinkStandbyMsg, + WallyHandleResetActionMoveSelection, + WallyHandlecmd55, + WallyHandlecmd56, +}; + +// code + +void unref_sub_8137220(void) +{ +} + +void SetBankFuncToWallyBufferRunCommand(void) +{ + gBattleBankFunc[gActiveBank] = WallyBufferRunCommand; + ewram[0x160A8] = 0; + ewram[0x160A9] = 0; + ewram[0x160AA] = 0; + ewram[0x160AB] = 0; +} + +void WallyBufferRunCommand(void) +{ + if (gBattleExecBuffer & gBitTable[gActiveBank]) + { + if (gBattleBufferA[gActiveBank][0] < 0x39) + gWallyBufferCommands[gBattleBufferA[gActiveBank][0]](); + else + WallyBufferExecCompleted(); + } +} + +void sub_81372BC(void) +{ + u8 r4; + + switch (ewram[0x160A8]) + { + case 0: + ewram[0x160AA] = 64; + ewram[0x160A8]++; + // fall through + case 1: + r4 = --ewram[0x160AA]; + if (r4 == 0) + { + PlaySE(SE_SELECT); + Emitcmd33(1, 0, 0); + WallyBufferExecCompleted(); + ewram[0x160A8]++; + ewram[0x160A9] = r4; + ewram[0x160AA] = 64; + } + break; + case 2: + r4 = --ewram[0x160AA]; + if (r4 == 0) + { + PlaySE(SE_SELECT); + Emitcmd33(1, 0, 0); + WallyBufferExecCompleted(); + ewram[0x160A8]++; + ewram[0x160A9] = r4; + ewram[0x160AA] = 64; + } + break; + case 3: + r4 = --ewram[0x160AA]; + if (r4 == 0) + { + Emitcmd33(1, 9, 0); + WallyBufferExecCompleted(); + ewram[0x160A8]++; + ewram[0x160A9] = r4; + ewram[0x160AA] = 64; + } + break; + case 4: + if (--ewram[0x160AA] == 0) + { + PlaySE(SE_SELECT); + nullsub_8(0); + sub_802E3E4(1, 0); + ewram[0x160AA] = 64; + ewram[0x160A8]++; + } + break; + case 5: + if (--ewram[0x160AA] == 0) + { + PlaySE(SE_SELECT); + DestroyMenuCursor(); + Emitcmd33(1, 1, 0); + WallyBufferExecCompleted(); + } + break; + } +} + +void sub_813741C(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + WallyBufferExecCompleted(); +} + +void sub_8137454(void) +{ + if (gUnknown_03004210.state == 0) + WallyBufferExecCompleted(); +} + +void sub_813746C(void) +{ + if (!gPaletteFade.active) + { + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } +} + +void bx_wait_t5(void) +{ + if (!gDoingBattleAnim) + WallyBufferExecCompleted(); +} + +void sub_81374C4(void) +{ + if (!gPaletteFade.active) + { + gBattleBankFunc[gActiveBank] = sub_81374FC; + nullsub_14(); + PrepareBagForWallyTutorial(); + } +} + +void sub_81374FC(void) +{ + if (gMain.callback2 == sub_800F808 + && !gPaletteFade.active) + { + Emitcmd35(1, gScriptItemId); + WallyBufferExecCompleted(); + } +} + +void sub_8137538(void) +{ + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank].unk0_7) + sub_8141828(gActiveBank, &gPlayerParty[gBattlePartyID[gActiveBank]]); + + if (!ewram17810[gActiveBank ^ 2].unk0_3 && !ewram17810[gActiveBank ^ 2].unk0_7) + sub_8141828(gActiveBank ^ 2, &gPlayerParty[gBattlePartyID[gActiveBank ^ 2]]); + + if (!ewram17810[gActiveBank].unk0_3 && !ewram17810[gActiveBank ^ 2].unk0_3) + { + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank ^ 2]]); + sub_8045A5C(gHealthboxIDs[gActiveBank ^ 2], &gPlayerParty[gBattlePartyID[gActiveBank ^ 2]], 0); + sub_804777C(gActiveBank ^ 2); + sub_8043DFC(gHealthboxIDs[gActiveBank ^ 2]); + } + DestroySprite(&gSprites[gUnknown_0300434C[gActiveBank]]); + sub_8045A5C(gHealthboxIDs[gActiveBank], &gPlayerParty[gBattlePartyID[gActiveBank]], 0); + sub_804777C(gActiveBank); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + ewram17840.unk9_0 = 0; + gBattleBankFunc[gActiveBank] = sub_81376B8; + } +} + +void sub_81376B8(void) +{ + bool8 r4 = FALSE; + + if (gSprites[gHealthboxIDs[gActiveBank]].callback == SpriteCallbackDummy) + r4 = TRUE; + if (r4 && ewram17810[gActiveBank].unk1_0 && ewram17810[gActiveBank ^ 2].unk1_0) + { + ewram17810[gActiveBank].unk0_7 = 0; + ewram17810[gActiveBank].unk1_0 = 0; + ewram17810[gActiveBank ^ 2].unk0_7 = 0; + ewram17810[gActiveBank ^ 2].unk1_0 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + CreateTask(c3_0802FDF4, 10); + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + WallyBufferExecCompleted(); + } +} + +void sub_81377B0(void) +{ + s16 r4; + + r4 = sub_8045C78(gActiveBank, gHealthboxIDs[gActiveBank], 0, 0); + sub_8043DFC(gHealthboxIDs[gActiveBank]); + if (r4 != -1) + { + sub_80440EC(gHealthboxIDs[gActiveBank], r4, 0); + } + else + { + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); + WallyBufferExecCompleted(); + } +} + +void bx_blink_t5(void) +{ + u8 spriteId = gObjectBankIDs[gActiveBank]; + + if (gSprites[spriteId].data1 == 32) + { + gSprites[spriteId].data1 = 0; + gSprites[spriteId].invisible = FALSE; + gDoingBattleAnim = FALSE; + WallyBufferExecCompleted(); + } + else + { + if (((u16)gSprites[spriteId].data1 % 4) == 0) + gSprites[spriteId].invisible ^= 1; + gSprites[spriteId].data1++; + } +} + +void sub_813789C(void) +{ + if (!ewram17810[gActiveBank].unk0_6) + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + WallyBufferExecCompleted(); + } +} + +// Duplicate of sub_813741C +void sub_8137908(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].callback == SpriteCallbackDummy) + WallyBufferExecCompleted(); +} + +void sub_8137940(void) +{ + if (!ewram17810[gActiveBank].unk0_5) + WallyBufferExecCompleted(); +} + +void WallyBufferExecCompleted(void) +{ + gBattleBankFunc[gActiveBank] = WallyBufferRunCommand; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + u8 multiplayerId = GetMultiplayerId(); + + PrepareBufferDataTransferLink(2, 4, &multiplayerId); + gBattleBufferA[gActiveBank][0] = 0x38; + } + else + { + gBattleExecBuffer &= ~gBitTable[gActiveBank]; + } +} + +void unref_sub_81379E4(void) +{ + if (!ewram17810[gActiveBank].unk0_4) + WallyBufferExecCompleted(); +} + +void WallyHandleGetAttributes(void) +{ + u8 arr[0x100]; + u32 r6 = 0; + u8 r4; + s32 i; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + r6 = sub_8137A84(gBattlePartyID[gActiveBank], arr); + } + else + { + r4 = gBattleBufferA[gActiveBank][2]; + for (i = 0; i < 6; i++) + { + if (r4 & 1) + r6 += sub_8137A84(i, arr + r6); + r4 >>= 1; + } + } + Emitcmd29(1, r6, arr); + WallyBufferExecCompleted(); +} + +u32 sub_8137A84(u8 a, u8 *buffer) +{ + struct BattlePokemon battlePokemon; + struct UnknownStruct3 moveData; + u8 nickname[20]; + u8 *src; + s16 data16; + u32 data32; + s32 size = 0; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + battlePokemon.species = GetMonData(&gPlayerParty[a], MON_DATA_SPECIES); + battlePokemon.item = GetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM); + for (size = 0; size < 4; size++) + { + battlePokemon.moves[size] = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + size); + battlePokemon.pp[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + } + battlePokemon.ppBonuses = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + battlePokemon.friendship = GetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP); + battlePokemon.experience = GetMonData(&gPlayerParty[a], MON_DATA_EXP); + battlePokemon.hpIV = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + battlePokemon.attackIV = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + battlePokemon.defenseIV = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + battlePokemon.speedIV = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + battlePokemon.spAttackIV = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + battlePokemon.spDefenseIV = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + battlePokemon.personality = GetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY); + battlePokemon.status1 = GetMonData(&gPlayerParty[a], MON_DATA_STATUS); + battlePokemon.level = GetMonData(&gPlayerParty[a], MON_DATA_LEVEL); + battlePokemon.hp = GetMonData(&gPlayerParty[a], MON_DATA_HP); + battlePokemon.maxHP = GetMonData(&gPlayerParty[a], MON_DATA_MAX_HP); + battlePokemon.attack = GetMonData(&gPlayerParty[a], MON_DATA_ATK); + battlePokemon.defense = GetMonData(&gPlayerParty[a], MON_DATA_DEF); + battlePokemon.speed = GetMonData(&gPlayerParty[a], MON_DATA_SPD); + battlePokemon.spAttack = GetMonData(&gPlayerParty[a], MON_DATA_SPATK); + battlePokemon.spDefense = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF); + battlePokemon.isEgg = GetMonData(&gPlayerParty[a], MON_DATA_IS_EGG); + battlePokemon.altAbility = GetMonData(&gPlayerParty[a], MON_DATA_ALT_ABILITY); + battlePokemon.otId = GetMonData(&gPlayerParty[a], MON_DATA_OT_ID); + GetMonData(&gPlayerParty[a], MON_DATA_NICKNAME, nickname); + StringCopy10(battlePokemon.nickname, nickname); + GetMonData(&gPlayerParty[a], MON_DATA_OT_NAME, battlePokemon.otName); + src = (u8 *)&battlePokemon; + for (size = 0; size < sizeof(battlePokemon); size++) + buffer[size] = src[size]; + break; + case 1: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPECIES); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 2: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 3: + for (size = 0; size < 4; size++) + { + moveData.moves[size] = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + size); + moveData.pp[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + } + moveData.ppBonuses = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + src = (u8 *)&moveData; + for (size = 0; size < sizeof(moveData); size++) + buffer[size] = src[size]; + break; + case 4: + case 5: + case 6: + case 7: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 8: + for (size = 0; size < 4; size++) + buffer[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + size); + buffer[size] = GetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES); + size++; + break; + case 9: + case 10: + case 11: + case 12: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9); + size = 1; + break; + case 17: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_OT_ID); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 18: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_EXP); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case 19: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_EV); + size = 1; + break; + case 20: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_EV); + size = 1; + break; + case 21: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_EV); + size = 1; + break; + case 22: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_EV); + size = 1; + break; + case 23: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_EV); + size = 1; + break; + case 24: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_EV); + size = 1; + break; + case 25: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP); + size = 1; + break; + case 26: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_POKERUS); + size = 1; + break; + case 27: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_LOCATION); + size = 1; + break; + case 28: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_LEVEL); + size = 1; + break; + case 29: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_MET_GAME); + size = 1; + break; + case 30: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_POKEBALL); + size = 1; + break; + case 31: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + buffer[1] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + buffer[2] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + buffer[3] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + buffer[4] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + buffer[5] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + size = 6; + break; + case 32: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_HP_IV); + size = 1; + break; + case 33: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_ATK_IV); + size = 1; + break; + case 34: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_DEF_IV); + size = 1; + break; + case 35: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPD_IV); + size = 1; + break; + case 36: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV); + size = 1; + break; + case 37: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV); + size = 1; + break; + case 38: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 39: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_CHECKSUM); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 40: + data32 = GetMonData(&gPlayerParty[a], MON_DATA_STATUS); + buffer[0] = (data32 & 0x000000FF); + buffer[1] = (data32 & 0x0000FF00) >> 8; + buffer[2] = (data32 & 0x00FF0000) >> 16; + buffer[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case 41: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_LEVEL); + size = 1; + break; + case 42: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 43: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_MAX_HP); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 44: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_ATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 45: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_DEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 46: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPD); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 47: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPATK); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 48: + data16 = GetMonData(&gPlayerParty[a], MON_DATA_SPDEF); + buffer[0] = data16; + buffer[1] = data16 >> 8; + size = 2; + break; + case 49: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_COOL); + size = 1; + break; + case 50: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_BEAUTY); + size = 1; + break; + case 51: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_CUTE); + size = 1; + break; + case 52: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SMART); + size = 1; + break; + case 53: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_TOUGH); + size = 1; + break; + case 54: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SHEEN); + size = 1; + break; + case 55: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_COOL_RIBBON); + size = 1; + break; + case 56: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_BEAUTY_RIBBON); + size = 1; + break; + case 57: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_CUTE_RIBBON); + size = 1; + break; + case 58: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_SMART_RIBBON); + size = 1; + break; + case 59: + buffer[0] = GetMonData(&gPlayerParty[a], MON_DATA_TOUGH_RIBBON); + size = 1; + break; + } + return size; +} + +void WallyHandlecmd1(void) +{ + PlayerHandlecmd1(); +} + +void WallyHandleSetAttributes(void) +{ + u8 r4; + u8 i; + + if (gBattleBufferA[gActiveBank][2] == 0) + { + sub_8138294(gBattlePartyID[gActiveBank]); + } + else + { + r4 = gBattleBufferA[gActiveBank][2]; + for (i = 0; i < 6; i++) + { + if (r4 & 1) + sub_8138294(i); + r4 >>= 1; + } + } + WallyBufferExecCompleted(); +} + +void sub_8138294(u8 a) +{ + struct BattlePokemon *battlePokemon = (struct BattlePokemon *)&gBattleBufferA[gActiveBank][3]; + struct UnknownStruct3 *moveData = (struct UnknownStruct3 *)&gBattleBufferA[gActiveBank][3]; + s32 i; + + switch (gBattleBufferA[gActiveBank][1]) + { + case 0: + { + u8 iv; + + SetMonData(&gPlayerParty[a], MON_DATA_SPECIES, (u8 *)&battlePokemon->species); + SetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM, (u8 *)&battlePokemon->item); + for (i = 0; i < 4; i++) + { + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + i, (u8 *)&battlePokemon->moves[i]); + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + i, (u8 *)&battlePokemon->pp[i]); + } + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, (u8 *)&battlePokemon->ppBonuses); + SetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP, (u8 *)&battlePokemon->friendship); + SetMonData(&gPlayerParty[a], MON_DATA_EXP, (u8 *)&battlePokemon->experience); + iv = battlePokemon->hpIV; + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, (u8 *)&iv); + iv = battlePokemon->attackIV; + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, (u8 *)&iv); + iv = battlePokemon->defenseIV; + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, (u8 *)&iv); + iv = battlePokemon->speedIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, (u8 *)&iv); + iv = battlePokemon->spAttackIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, (u8 *)&iv); + iv = battlePokemon->spDefenseIV; + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, (u8 *)&iv); + SetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY, (u8 *)&battlePokemon->personality); + SetMonData(&gPlayerParty[a], MON_DATA_STATUS, (u8 *)&battlePokemon->status1); + SetMonData(&gPlayerParty[a], MON_DATA_LEVEL, (u8 *)&battlePokemon->level); + SetMonData(&gPlayerParty[a], MON_DATA_HP, (u8 *)&battlePokemon->hp); + SetMonData(&gPlayerParty[a], MON_DATA_MAX_HP, (u8 *)&battlePokemon->maxHP); + SetMonData(&gPlayerParty[a], MON_DATA_ATK, (u8 *)&battlePokemon->attack); + SetMonData(&gPlayerParty[a], MON_DATA_DEF, (u8 *)&battlePokemon->defense); + SetMonData(&gPlayerParty[a], MON_DATA_SPD, (u8 *)&battlePokemon->speed); + SetMonData(&gPlayerParty[a], MON_DATA_SPATK, (u8 *)&battlePokemon->spAttack); + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF, (u8 *)&battlePokemon->spDefense); + } + break; + case 1: + SetMonData(&gPlayerParty[a], MON_DATA_SPECIES, &gBattleBufferA[gActiveBank][3]); + break; + case 2: + SetMonData(&gPlayerParty[a], MON_DATA_HELD_ITEM, &gBattleBufferA[gActiveBank][3]); + break; + case 3: + for (i = 0; i < 4; i++) + { + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + i, (u8 *)&moveData->moves[i]); + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + i, (u8 *)&moveData->pp[i]); + } + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, &moveData->ppBonuses); + break; + case 4: + case 5: + case 6: + case 7: + SetMonData(&gPlayerParty[a], MON_DATA_MOVE1 + gBattleBufferA[gActiveBank][1] - 4, &gBattleBufferA[gActiveBank][3]); + break; + case 8: + SetMonData(&gPlayerParty[a], MON_DATA_PP1, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gPlayerParty[a], MON_DATA_PP2, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gPlayerParty[a], MON_DATA_PP3, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gPlayerParty[a], MON_DATA_PP4, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gPlayerParty[a], MON_DATA_PP_BONUSES, &gBattleBufferA[gActiveBank][7]); + break; + case 9: + case 10: + case 11: + case 12: + SetMonData(&gPlayerParty[a], MON_DATA_PP1 + gBattleBufferA[gActiveBank][1] - 9, &gBattleBufferA[gActiveBank][3]); + break; + case 17: + SetMonData(&gPlayerParty[a], MON_DATA_OT_ID, &gBattleBufferA[gActiveBank][3]); + break; + case 18: + SetMonData(&gPlayerParty[a], MON_DATA_EXP, &gBattleBufferA[gActiveBank][3]); + break; + case 19: + SetMonData(&gPlayerParty[a], MON_DATA_HP_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 20: + SetMonData(&gPlayerParty[a], MON_DATA_ATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 21: + SetMonData(&gPlayerParty[a], MON_DATA_DEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 22: + SetMonData(&gPlayerParty[a], MON_DATA_SPD_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 23: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 24: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_EV, &gBattleBufferA[gActiveBank][3]); + break; + case 25: + SetMonData(&gPlayerParty[a], MON_DATA_FRIENDSHIP, &gBattleBufferA[gActiveBank][3]); + break; + case 26: + SetMonData(&gPlayerParty[a], MON_DATA_POKERUS, &gBattleBufferA[gActiveBank][3]); + break; + case 27: + SetMonData(&gPlayerParty[a], MON_DATA_MET_LOCATION, &gBattleBufferA[gActiveBank][3]); + break; + case 28: + SetMonData(&gPlayerParty[a], MON_DATA_MET_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 29: + SetMonData(&gPlayerParty[a], MON_DATA_MET_GAME, &gBattleBufferA[gActiveBank][3]); + break; + case 30: + SetMonData(&gPlayerParty[a], MON_DATA_POKEBALL, &gBattleBufferA[gActiveBank][3]); + break; + case 31: + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][4]); + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][5]); + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][6]); + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][7]); + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][8]); + break; + case 32: + SetMonData(&gPlayerParty[a], MON_DATA_HP_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 33: + SetMonData(&gPlayerParty[a], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 34: + SetMonData(&gPlayerParty[a], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 35: + SetMonData(&gPlayerParty[a], MON_DATA_SPD_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 36: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 37: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBank][3]); + break; + case 38: + SetMonData(&gPlayerParty[a], MON_DATA_PERSONALITY, &gBattleBufferA[gActiveBank][3]); + break; + case 39: + SetMonData(&gPlayerParty[a], MON_DATA_CHECKSUM, &gBattleBufferA[gActiveBank][3]); + break; + case 40: + SetMonData(&gPlayerParty[a], MON_DATA_STATUS, &gBattleBufferA[gActiveBank][3]); + break; + case 41: + SetMonData(&gPlayerParty[a], MON_DATA_LEVEL, &gBattleBufferA[gActiveBank][3]); + break; + case 42: + SetMonData(&gPlayerParty[a], MON_DATA_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 43: + SetMonData(&gPlayerParty[a], MON_DATA_MAX_HP, &gBattleBufferA[gActiveBank][3]); + break; + case 44: + SetMonData(&gPlayerParty[a], MON_DATA_ATK, &gBattleBufferA[gActiveBank][3]); + break; + case 45: + SetMonData(&gPlayerParty[a], MON_DATA_DEF, &gBattleBufferA[gActiveBank][3]); + break; + case 46: + SetMonData(&gPlayerParty[a], MON_DATA_SPD, &gBattleBufferA[gActiveBank][3]); + break; + case 47: + SetMonData(&gPlayerParty[a], MON_DATA_SPATK, &gBattleBufferA[gActiveBank][3]); + break; + case 48: + SetMonData(&gPlayerParty[a], MON_DATA_SPDEF, &gBattleBufferA[gActiveBank][3]); + break; + case 49: + SetMonData(&gPlayerParty[a], MON_DATA_COOL, &gBattleBufferA[gActiveBank][3]); + break; + case 50: + SetMonData(&gPlayerParty[a], MON_DATA_BEAUTY, &gBattleBufferA[gActiveBank][3]); + break; + case 51: + SetMonData(&gPlayerParty[a], MON_DATA_CUTE, &gBattleBufferA[gActiveBank][3]); + break; + case 52: + SetMonData(&gPlayerParty[a], MON_DATA_SMART, &gBattleBufferA[gActiveBank][3]); + break; + case 53: + SetMonData(&gPlayerParty[a], MON_DATA_TOUGH, &gBattleBufferA[gActiveBank][3]); + break; + case 54: + SetMonData(&gPlayerParty[a], MON_DATA_SHEEN, &gBattleBufferA[gActiveBank][3]); + break; + case 55: + SetMonData(&gPlayerParty[a], MON_DATA_COOL_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 56: + SetMonData(&gPlayerParty[a], MON_DATA_BEAUTY_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 57: + SetMonData(&gPlayerParty[a], MON_DATA_CUTE_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 58: + SetMonData(&gPlayerParty[a], MON_DATA_SMART_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + case 59: + SetMonData(&gPlayerParty[a], MON_DATA_TOUGH_RIBBON, &gBattleBufferA[gActiveBank][3]); + break; + } + sub_80324F8(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank); +} + +void WallyHandlecmd3(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleLoadPokeSprite(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleSendOutPoke(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleReturnPokeToBall(void) +{ + if (gBattleBufferA[gActiveBank][1] == 0) + { + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 1); + gBattleBankFunc[gActiveBank] = sub_813789C; + } + else + { + FreeSpriteOamMatrix(&gSprites[gObjectBankIDs[gActiveBank]]); + DestroySprite(&gSprites[gObjectBankIDs[gActiveBank]]); + sub_8043DB0(gHealthboxIDs[gActiveBank]); + WallyBufferExecCompleted(); + } +} + +void WallyHandleTrainerThrow(void) +{ + LoadPlayerTrainerBankSprite(2, gActiveBank); + GetMonSpriteTemplate_803C5A0(2, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + 80, 80 + 4 * (8 - gTrainerBackPicCoords[2].coords), + 30); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = 240; + gSprites[gObjectBankIDs[gActiveBank]].data0 = -2; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_813741C; +} + +void WallyHandleTrainerSlide(void) +{ + LoadPlayerTrainerBankSprite(2, gActiveBank); + GetMonSpriteTemplate_803C5A0(2, GetBankIdentity(gActiveBank)); + gObjectBankIDs[gActiveBank] = CreateSprite( + &gUnknown_02024E8C, + 80, 80 + 4 * (8 - gTrainerBackPicCoords[2].coords), + 30); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = gActiveBank; + gSprites[gObjectBankIDs[gActiveBank]].pos2.x = -96; + gSprites[gObjectBankIDs[gActiveBank]].data0 = 2; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_80313A0; + gBattleBankFunc[gActiveBank] = sub_8137908; +} + +void WallyHandleTrainerSlideBack(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd10(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd11(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd12(void) +{ + ewram17840.unk8 = 4; + gDoingBattleAnim = TRUE; + move_anim_start_t4(gActiveBank, gActiveBank, GetBankByPlayerAI(1), 4); + gBattleBankFunc[gActiveBank] = bx_wait_t5; +} + +void WallyHandleBallThrow(void) +{ + u8 val = gBattleBufferA[gActiveBank][1]; + + ewram17840.unk8 = val; + gDoingBattleAnim = TRUE; + move_anim_start_t4(gActiveBank, gActiveBank, GetBankByPlayerAI(1), 4); + gBattleBankFunc[gActiveBank] = bx_wait_t5; +} + +void WallyHandlePuase(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleMoveAnimation(void) +{ + u16 r0 = gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8); + + gUnknown_0202F7C4 = gBattleBufferA[gActiveBank][3]; + gMovePowerMoveAnim = gBattleBufferA[gActiveBank][4] | (gBattleBufferA[gActiveBank][5] << 8); + gMoveDmgMoveAnim = gBattleBufferA[gActiveBank][6] | (gBattleBufferA[gActiveBank][7] << 8) | (gBattleBufferA[gActiveBank][8] << 16) | (gBattleBufferA[gActiveBank][9] << 24); + gHappinessMoveAnim = gBattleBufferA[gActiveBank][10]; + gWeatherMoveAnim = gBattleBufferA[gActiveBank][12] | (gBattleBufferA[gActiveBank][13] << 8); + gDisableStructMoveAnim = (u32 *)&gBattleBufferA[gActiveBank][16]; + gPID_perBank[gActiveBank] = *gDisableStructMoveAnim; + if (sub_8031720(r0, gUnknown_0202F7C4) != 0) + { + // Dead code. sub_8031720 always returns 0. + WallyBufferExecCompleted(); + } + else + { + ewram17810[gActiveBank].unk4 = 0; + gBattleBankFunc[gActiveBank] = sub_81390D0; + } +} + +void sub_81390D0(void) +{ + u16 r4 = gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8); + +#ifndef NONMATCHING + asm("":::"r6"); +#endif + + switch (ewram17810[gActiveBank].unk4) + { + case 0: + if (ewram17800[gActiveBank].substituteSprite == 1) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 5); + ewram17810[gActiveBank].unk4 = 1; + break; + case 1: + if (ewram17810[gActiveBank].unk0_6 == 0) + { + sub_80326EC(0); + ExecuteMoveAnim(r4); + ewram17810[gActiveBank].unk4 = 2; + } + break; + case 2: + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + sub_80326EC(1); + if (ewram17800[gActiveBank].substituteSprite == 1) + move_anim_start_t4(gActiveBank, gActiveBank, gActiveBank, 6); + ewram17810[gActiveBank].unk4 = 3; + } + break; + case 3: + if (ewram17810[gActiveBank].unk0_6 == 0) + { + sub_8031F24(); + sub_80324BC(gActiveBank, gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + ewram17810[gActiveBank].unk4 = 0; + WallyBufferExecCompleted(); + } + break; + } +} + +void WallyHandlePrintString(void) +{ + u16 *ptr; + + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + ptr = (u16 *)&gBattleBufferA[gActiveBank][2]; + if (*ptr == 2) + DestroyMenuCursor(); + BufferStringBattle(*ptr); + sub_8002EB0(&gUnknown_03004210, gDisplayedStringBattle, 0x90, 2, 15); + gBattleBankFunc[gActiveBank] = sub_8137454; +} + +void WallyHandlePrintStringPlayerOnly(void) +{ + if (GetBankSide(gActiveBank) == 0) + WallyHandlePrintString(); + else + WallyBufferExecCompleted(); +} + +void WallyHandlecmd18(void) +{ + s32 i; + + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 160; + gUnknown_03004210.paletteNum = 0; + FillWindowRect_DefaultPalette(&gUnknown_03004210, 10, 2, 15, 27, 18); + FillWindowRect_DefaultPalette(&gUnknown_03004210, 10, 2, 35, 16, 36); + gBattleBankFunc[gActiveBank] = sub_81372BC; + InitWindow(&gUnknown_03004210, gUnknown_08400CF3, 400, 18, 35); + sub_8002F44(&gUnknown_03004210); + sub_814A5C0(0, 0xFFFF, 12, 0x2D9F, 0); + for (i = 0; i < 4; i++) + nullsub_8(i); + sub_802E3E4(0, 0); + StrCpyDecodeToDisplayedStringBattle(gUnknown_08400CCC); +#ifdef ENGLISH + InitWindow(&gUnknown_03004210, gDisplayedStringBattle, 440, 2, 35); +#else + InitWindow(&gUnknown_03004210, gDisplayedStringBattle, 444, 2, 35); +#endif + sub_8002F44(&gUnknown_03004210); +} + +void WallyHandlecmd19(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd20(void) +{ + switch (ewram[0x160A9]) + { + case 0: + sub_80304A8(); + ewram[0x160A9]++; + ewram[0x160AB] = 80; + // fall through + case 1: + ewram[0x160AB]--; + if (ewram[0x160AB] == 0) + { + DestroyMenuCursor(); + PlaySE(SE_SELECT); + Emitcmd33(1, 10, 256); + WallyBufferExecCompleted(); + } + break; + } +} + +void WallyHandleOpenBag(void) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gBattleBankFunc[gActiveBank] = sub_81374C4; + gBankInMenu = gActiveBank; +} + +void WallyHandlecmd22(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd23(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleHealthBarUpdate(void) +{ + s16 r7; + + load_gfxc_health_bar(0); + r7 = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + if (r7 != 0x7FFF) + { + u32 maxHP = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + u32 curHP = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, curHP, r7); + } + else + { + u32 maxHP = GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_MAX_HP); + + sub_8043D84(gActiveBank, gHealthboxIDs[gActiveBank], maxHP, 0, r7); + sub_80440EC(gHealthboxIDs[gActiveBank], 0, 0); + } + gBattleBankFunc[gActiveBank] = sub_81377B0; +} + +void WallyHandleExpBarUpdate(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleStatusIconUpdate(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleStatusAnimation(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleStatusXor(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd29(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleDMATransfer(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd31(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd32(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd33(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd34(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd35(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd36(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd37(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd38(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd39(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd40(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleHitAnimation(void) +{ + if (gSprites[gObjectBankIDs[gActiveBank]].invisible == TRUE) + { + WallyBufferExecCompleted(); + } + else + { + gDoingBattleAnim = 1; + gSprites[gObjectBankIDs[gActiveBank]].data1 = 0; + sub_8047858(gActiveBank); + gBattleBankFunc[gActiveBank] = bx_blink_t5; + } +} + +void WallyHandlecmd42(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleEffectivenessSound(void) +{ + PlaySE(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + WallyBufferExecCompleted(); +} + +void WallyHandlecmd44(void) +{ + PlayFanfare(gBattleBufferA[gActiveBank][1] | (gBattleBufferA[gActiveBank][2] << 8)); + WallyBufferExecCompleted(); +} + +void WallyHandleFaintingCry(void) +{ + PlayCry1(GetMonData(&gPlayerParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES), 25); + WallyBufferExecCompleted(); +} + +void WallyHandleIntroSlide(void) +{ + sub_80E43C0(gBattleBufferA[gActiveBank][1]); + gUnknown_02024DE8 |= 1; + WallyBufferExecCompleted(); +} + +void WallyHandleTrainerBallThrow(void) +{ + u8 paletteNum; + u8 taskId; + + oamt_add_pos2_onto_pos1(&gSprites[gObjectBankIDs[gActiveBank]]); + gSprites[gObjectBankIDs[gActiveBank]].data0 = 50; + gSprites[gObjectBankIDs[gActiveBank]].data2 = -40; + gSprites[gObjectBankIDs[gActiveBank]].data4 = gSprites[gObjectBankIDs[gActiveBank]].pos1.y; + gSprites[gObjectBankIDs[gActiveBank]].callback = sub_8078B34; + gSprites[gObjectBankIDs[gActiveBank]].data5 = gActiveBank; + StoreSpriteCallbackInData6(&gSprites[gObjectBankIDs[gActiveBank]], sub_8030E38); + StartSpriteAnim(&gSprites[gObjectBankIDs[gActiveBank]], 1); + paletteNum = AllocSpritePalette(0xD6F8); + LoadCompressedPalette(gTrainerBackPicPaletteTable[2].data, 0x100 + paletteNum * 16, 32); + gSprites[gObjectBankIDs[gActiveBank]].oam.paletteNum = paletteNum; + taskId = CreateTask(sub_8139A2C, 5); + gTasks[taskId].data[0] = gActiveBank; + if (ewram17810[gActiveBank].unk0_0) + gTasks[gUnknown_02024E68[gActiveBank]].func = sub_8044CA0; + ewram17810[4].unk9 |= 1; + gBattleBankFunc[gActiveBank] = nullsub_91; +} + +void sub_81398BC(u8 bank) +{ + u16 species; + + ewram17800[bank].transformedSpecies = 0; + gBattlePartyID[bank] = gBattleBufferA[bank][1]; + species = GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_SPECIES); + gUnknown_0300434C[bank] = CreateInvisibleSpriteWithCallback(sub_80312F0); + GetMonSpriteTemplate_803C56C(species, GetBankIdentity(bank)); + gObjectBankIDs[bank] = CreateSprite( + &gUnknown_02024E8C, + sub_8077ABC(bank, 2), + sub_8077F68(bank), + sub_8079E90(bank)); + gSprites[gUnknown_0300434C[bank]].data1 = gObjectBankIDs[bank]; + gSprites[gObjectBankIDs[bank]].data0 = bank; + gSprites[gObjectBankIDs[bank]].data2 = species; + gSprites[gObjectBankIDs[bank]].oam.paletteNum = bank; + StartSpriteAnim(&gSprites[gObjectBankIDs[bank]], gBattleMonForms[bank]); + gSprites[gObjectBankIDs[bank]].invisible = TRUE; + gSprites[gObjectBankIDs[bank]].callback = SpriteCallbackDummy; + gSprites[gUnknown_0300434C[bank]].data0 = sub_8046400(0, 0xFF); +} + +void sub_8139A2C(u8 taskId) +{ + if (gTasks[taskId].data[1] < 31) + { + gTasks[taskId].data[1]++; + } + else + { + u8 savedActiveBank = gActiveBank; + + gActiveBank = gTasks[taskId].data[0]; + gBattleBufferA[gActiveBank][1] = gBattlePartyID[gActiveBank]; + sub_81398BC(gActiveBank); + gBattleBankFunc[gActiveBank] = sub_8137538; + gActiveBank = savedActiveBank; + DestroyTask(taskId); + } +} + +void WallyHandlecmd48(void) +{ + if (gBattleBufferA[gActiveBank][1] != 0 && GetBankSide(gActiveBank) == 0) + { + WallyBufferExecCompleted(); + } + else + { + ewram17810[gActiveBank].unk0_0 = 1; + gUnknown_02024E68[gActiveBank] = sub_8044804(gActiveBank, (struct BattleInterfaceStruct2 *)&gBattleBufferA[gActiveBank][4], gBattleBufferA[gActiveBank][1], gBattleBufferA[gActiveBank][2]); + WallyBufferExecCompleted(); + } +} + +void WallyHandlecmd49(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd50(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleSpriteInvisibility(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleBattleAnimation(void) +{ + u8 val2 = gBattleBufferA[gActiveBank][1]; + u16 val = gBattleBufferA[gActiveBank][2] | (gBattleBufferA[gActiveBank][3] << 8); + + if (move_anim_start_t3(gActiveBank, gActiveBank, gActiveBank, val2, val)) + WallyBufferExecCompleted(); + else + gBattleBankFunc[gActiveBank] = sub_8137940; +} + +void WallyHandleLinkStandbyMsg(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandleResetActionMoveSelection(void) +{ + WallyBufferExecCompleted(); +} + +void WallyHandlecmd55(void) +{ + gBattleOutcome = gBattleBufferA[gActiveBank][1]; + FadeOutMapMusic(5); + BeginFastPaletteFade(3); + WallyBufferExecCompleted(); + if ((gBattleTypeFlags & BATTLE_TYPE_LINK) && !(gBattleTypeFlags & BATTLE_TYPE_WILD)) + gBattleBankFunc[gActiveBank] = sub_813746C; +} + +void WallyHandlecmd56(void) +{ +} diff --git a/src/battle/battle_interface.c b/src/battle/battle_interface.c new file mode 100644 index 000000000..0741ad33a --- /dev/null +++ b/src/battle/battle_interface.c @@ -0,0 +1,3049 @@ +#include "global.h" +#include "battle.h" +#include "battle_interface.h" +#include "decompress.h" +#include "palette.h" +#include "pokedex.h" +#include "pokemon.h" +#include "rom_8077ABC.h" +#include "safari_zone.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "string_util.h" +#include "task.h" +#include "text.h" + +struct UnknownStruct5 +{ + u8 unk0; + u32 unk4; + u32 unk8; + u32 unkC; + u32 unk10; +}; + +struct UnknownStruct7 +{ + u8 filler0[0x180]; +}; + +extern u8 ewram[]; +#define ewram520 ((struct UnknownStruct7 *)(ewram + 0x00520)) +#define ewram16088 (*(u8 *) (ewram + 0x16088)) +#define ewram16089 (*(u8 *) (ewram + 0x16089)) +#define ewram17850 ((struct UnknownStruct5 *)(ewram + 0x17850)) + +extern u8 gDisplayedStringBattle[]; +extern u8 gNoOfAllBanks; +extern u16 gBattlePartyID[]; +extern u8 gBanksBySide[]; +extern u8 gHealthboxIDs[]; + +extern u16 gBattleTypeFlags; + +extern const struct SpriteTemplate gSpriteTemplate_820A4EC[]; +extern const struct SpriteTemplate gSpriteTemplate_820A51C[]; +extern const struct SpriteTemplate gSpriteTemplate_820A54C; +extern const struct SpriteTemplate gSpriteTemplate_820A56C[]; +extern const struct SubspriteTable gSubspriteTables_820A684[]; +extern const struct SubspriteTable gSubspriteTables_820A6E4[]; +extern const struct SubspriteTable gSubspriteTables_820A6EC[]; +extern const struct SpriteSheet gUnknown_0820A754[]; +extern const struct SpritePalette gUnknown_0820A764[]; +extern const struct SpritePalette gUnknown_0820A774[]; +extern const struct SpriteSheet gUnknown_0820A784[]; +extern const struct SpriteTemplate gSpriteTemplate_820A7A4[]; +extern const struct SpriteTemplate gSpriteTemplate_820A7D4[]; +extern void *const gUnknown_0820A804[]; +extern void *const gUnknown_0820A80C[]; +extern void *const gUnknown_0820A814[]; +extern void *const gUnknown_0820A83C[]; +extern void *const gUnknown_0820A848[]; +extern void *const gUnknown_0820A854[]; +extern void *const gUnknown_0820A85C[]; +extern void *const gUnknown_0820A87C[]; +extern void *const gUnknown_0820A894[]; +extern void *const gUnknown_0820A8B4[]; +extern void *const gUnknown_0820A8DC[]; +extern void *const gUnknown_0820A904[]; +extern const u8 gUnknown_0820A81C[]; +extern const u8 gUnknown_0820A864[]; +extern const u8 gUnknown_0820A89C[]; +extern const u8 gUnknown_0820A8B0[]; +extern const u8 BattleText_SafariBalls[]; +extern const u8 BattleText_SafariBallsLeft[]; +extern const u8 BattleText_HighlightRed[]; +extern const u8 gUnknown_08D1216C[][32]; + +extern const u16 gBattleInterfaceStatusIcons_DynPal[]; + +#define ABS(n) ((n) >= 0 ? (n) : -(n)) +// Used for computing copy destination addresses +#define MACRO1(n) ((n) - (n) / 8 * 8) + 64 * ((n) / 8) + +static void sub_8043D5C(struct Sprite *); +static const void *sub_8043CDC(u8); +static void sub_8044210(u8, s16, u8); +static void draw_status_ailment_maybe(u8); +extern void sub_8045180(struct Sprite *); +static void sub_8045110(struct Sprite *); +static void sub_8045048(struct Sprite *); +static void sub_8044F70(u8 taskId); +static void sub_8044E74(u8 taskId); +static void sub_8044ECC(u8 taskId); +static u8 sub_80457E8(u8, u8); +static int sub_8045F58(s32, s32, int, int *, u8, u16); +static u8 GetScaledExpFraction(int, int, int, u8); +static void sub_8045D58(u8, u8); +static u8 sub_804602C(int, int, int, int *, u8 *, u8); +static void sub_8046128(struct BattleInterfaceStruct1 *a, int *b, void *c); + +static int do_nothing(s16 unused1, s16 unused2, int unused3) +{ + return 9; +} + +#ifdef NONMATCHING +void sub_8043740(s16 a, u16 *b, u8 c) +{ + u8 sp0[4]; + s8 i; + s8 j; + s32 r9; + + for (i = 0; i < 4; i++) + sp0[i] = 0; + + //_0804377C + //i = 3; + //r9 = -1; + for (i = 3, r9 = -1;;) + { + if (a > 0) + { + sp0[i] = a % 10; + a /= 10; + i--; + } + else + break; + asm(""::"r"(r9)); + } + + //_080437AA + for (; i > r9; i--) + { + //asm("":"=r"(r9)); + sp0[i] = -1; + } + //_080437CE + if (sp0[3] == 0xFF) + sp0[3] = 0; + + //_080437DA + if (c == 0) + { + for (i = 0, j = 0; i < 4; i++) + { + if (sp0[j] == 0xFF) + { + b[j] = (b[j] & 0xFC00) | 0x1E; + b[i + 0x20] = (b[i + 0x20] & 0xFC00) | 0x1E; + } + else + { + b[j] = (b[j] & 0xFC00) | (sp0[j] + 0x14); + b[i + 0x20] = (b[i + 0x20] & 0xFC00) | (sp0[i] + 0x34); + } + j++; + } + + } + //_0804386A + else + { + for (i = 0; i < 4; i++) + { + if (sp0[i] == 0xFF) + { + b[i] = (b[i] & 0xFC00) | 0x1E; + b[i + 0x20] = (b[i + 0x20] & 0xFC00) | 0x1E; + } + else + { + b[i] = (b[i] & 0xFC00) | (sp0[i] + 0x14); + b[i + 0x20] = (b[i + 0x20] & 0xFC00) | (sp0[i] + 0x34); + } + } + } + asm(""::"r"(r9)); +} +#else +__attribute__((naked)) +void sub_8043740(s16 a, u16 *b, u8 c) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x4\n\ + adds r7, r1, 0\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + mov r10, r2\n\ + movs r3, 0\n\ + movs r2, 0\n\ +_0804375C:\n\ + lsls r0, r3, 24\n\ + asrs r0, 24\n\ + mov r3, sp\n\ + adds r1, r3, r0\n\ + strb r2, [r1]\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r3, r0, 24\n\ + asrs r0, 24\n\ + cmp r0, 0x3\n\ + ble _0804375C\n\ + movs r3, 0x3\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + mov r9, r0\n\ + mov r8, sp\n\ +_0804377C:\n\ + lsls r0, r5, 16\n\ + asrs r6, r0, 16\n\ + cmp r6, 0\n\ + ble _080437AA\n\ + lsls r4, r3, 24\n\ + asrs r4, 24\n\ + mov r1, sp\n\ + adds r5, r1, r4\n\ + adds r0, r6, 0\n\ + movs r1, 0xA\n\ + bl __modsi3\n\ + strb r0, [r5]\n\ + adds r0, r6, 0\n\ + movs r1, 0xA\n\ + bl __divsi3\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + subs r4, 0x1\n\ + lsls r4, 24\n\ + lsrs r3, r4, 24\n\ + b _0804377C\n\ +_080437AA:\n\ + lsls r1, r3, 24\n\ + asrs r0, r1, 24\n\ + cmp r0, r9\n\ + ble _080437CE\n\ + movs r4, 0xFF\n\ + movs r3, 0x1\n\ + negs r3, r3\n\ +_080437B8:\n\ + asrs r2, r1, 24\n\ + mov r5, sp\n\ + adds r1, r5, r2\n\ + ldrb r0, [r1]\n\ + orrs r0, r4\n\ + strb r0, [r1]\n\ + subs r2, 0x1\n\ + lsls r1, r2, 24\n\ + asrs r0, r1, 24\n\ + cmp r0, r3\n\ + bgt _080437B8\n\ +_080437CE:\n\ + mov r1, r8\n\ + ldrb r0, [r1, 0x3]\n\ + cmp r0, 0xFF\n\ + bne _080437DA\n\ + movs r0, 0\n\ + strb r0, [r1, 0x3]\n\ +_080437DA:\n\ + mov r2, r10\n\ + cmp r2, 0\n\ + bne _0804386A\n\ + movs r3, 0\n\ + movs r1, 0\n\ + movs r6, 0xFC\n\ + lsls r6, 8\n\ + movs r5, 0x1E\n\ + mov r12, r5\n\ +_080437EC:\n\ + lsls r1, 24\n\ + asrs r2, r1, 24\n\ + mov r0, sp\n\ + adds r5, r0, r2\n\ + ldrb r0, [r5]\n\ + mov r8, r1\n\ + cmp r0, 0xFF\n\ + bne _08043822\n\ + lsls r1, r2, 1\n\ + adds r1, r7\n\ + ldrh r2, [r1]\n\ + adds r0, r6, 0\n\ + ands r0, r2\n\ + mov r2, r12\n\ + orrs r0, r2\n\ + strh r0, [r1]\n\ + lsls r3, 24\n\ + asrs r1, r3, 23\n\ + adds r1, r7\n\ + adds r1, 0x40\n\ + ldrh r2, [r1]\n\ + adds r0, r6, 0\n\ + ands r0, r2\n\ + mov r5, r12\n\ + orrs r0, r5\n\ + strh r0, [r1]\n\ + b _08043852\n\ +_08043822:\n\ + lsls r2, 1\n\ + adds r2, r7\n\ + ldrh r0, [r2]\n\ + adds r1, r6, 0\n\ + ands r1, r0\n\ + ldrb r0, [r5]\n\ + adds r0, 0x14\n\ + orrs r1, r0\n\ + strh r1, [r2]\n\ + lsls r4, r3, 24\n\ + asrs r3, r4, 24\n\ + lsls r2, r3, 1\n\ + adds r2, r7\n\ + adds r2, 0x40\n\ + ldrh r0, [r2]\n\ + adds r1, r6, 0\n\ + ands r1, r0\n\ + mov r5, sp\n\ + adds r0, r5, r3\n\ + ldrb r0, [r0]\n\ + adds r0, 0x34\n\ + orrs r1, r0\n\ + strh r1, [r2]\n\ + adds r3, r4, 0\n\ +_08043852:\n\ + movs r0, 0x80\n\ + lsls r0, 17\n\ + add r0, r8\n\ + lsrs r1, r0, 24\n\ + movs r2, 0x80\n\ + lsls r2, 17\n\ + adds r0, r3, r2\n\ + lsrs r3, r0, 24\n\ + asrs r0, 24\n\ + cmp r0, 0x3\n\ + ble _080437EC\n\ + b _080438CE\n\ +_0804386A:\n\ + movs r3, 0\n\ + movs r4, 0xFC\n\ + lsls r4, 8\n\ + movs r6, 0x1E\n\ +_08043872:\n\ + lsls r1, r3, 24\n\ + asrs r2, r1, 24\n\ + mov r3, sp\n\ + adds r5, r3, r2\n\ + ldrb r0, [r5]\n\ + adds r3, r1, 0\n\ + cmp r0, 0xFF\n\ + bne _0804389E\n\ + lsls r1, r2, 1\n\ + adds r1, r7\n\ + ldrh r2, [r1]\n\ + adds r0, r4, 0\n\ + ands r0, r2\n\ + orrs r0, r6\n\ + strh r0, [r1]\n\ + adds r1, 0x40\n\ + ldrh r2, [r1]\n\ + adds r0, r4, 0\n\ + ands r0, r2\n\ + orrs r0, r6\n\ + strh r0, [r1]\n\ + b _080438C0\n\ +_0804389E:\n\ + lsls r2, 1\n\ + adds r2, r7\n\ + ldrh r0, [r2]\n\ + adds r1, r4, 0\n\ + ands r1, r0\n\ + ldrb r0, [r5]\n\ + adds r0, 0x14\n\ + orrs r1, r0\n\ + strh r1, [r2]\n\ + adds r2, 0x40\n\ + ldrh r0, [r2]\n\ + adds r1, r4, 0\n\ + ands r1, r0\n\ + ldrb r0, [r5]\n\ + adds r0, 0x34\n\ + orrs r1, r0\n\ + strh r1, [r2]\n\ +_080438C0:\n\ + movs r5, 0x80\n\ + lsls r5, 17\n\ + adds r0, r3, r5\n\ + lsrs r3, r0, 24\n\ + asrs r0, 24\n\ + cmp r0, 0x3\n\ + ble _08043872\n\ +_080438CE:\n\ + add sp, 0x4\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided\n"); +} +#endif + +void unref_sub_80438E0(s16 a, s16 b, u16 *c) +{ + c[4] = 0x1E; + sub_8043740(b, c, 0); + sub_8043740(a, c + 5, 1); +} + +u8 battle_make_oam_normal_battle(u8 a) +{ + int sp0 = 0; + u8 spriteId1; + u8 spriteId2; + u8 spriteId3; + struct Sprite *sprite; + + if (!IsDoubleBattle()) + { + if (GetBankSide(a) == 0) + { + spriteId1 = CreateSprite(&gSpriteTemplate_820A4EC[0], 240, 160, 1); + spriteId2 = CreateSpriteAtEnd(&gSpriteTemplate_820A4EC[0], 240, 160, 1); + + gSprites[spriteId1].oam.shape = 0; + gSprites[spriteId2].oam.shape = 0; + gSprites[spriteId2].oam.tileNum += 64; + } + else + { + spriteId1 = CreateSprite(&gSpriteTemplate_820A51C[0], 240, 160, 1); + spriteId2 = CreateSpriteAtEnd(&gSpriteTemplate_820A51C[0], 240, 160, 1); + + gSprites[spriteId2].oam.tileNum += 32; + sp0 = 2; + } + //_080439F2 + + gSprites[spriteId1].oam.affineParam = spriteId2; + gSprites[spriteId2].data5 = spriteId1; + gSprites[spriteId2].callback = sub_8043D5C; + } + //_08043A28 + else + { + if (GetBankSide(a) == 0) + { + spriteId1 = CreateSprite(&gSpriteTemplate_820A4EC[GetBankIdentity(a) / 2], 240, 160, 1); + spriteId2 = CreateSpriteAtEnd(&gSpriteTemplate_820A4EC[GetBankIdentity(a) / 2], 240, 160, 1); + + gSprites[spriteId1].oam.affineParam = spriteId2; + gSprites[spriteId2].data5 = spriteId1; + gSprites[spriteId2].oam.tileNum += 32; + gSprites[spriteId2].callback = sub_8043D5C; + sp0 = 1; + } + //_08043ACC + else + { + spriteId1 = CreateSprite(&gSpriteTemplate_820A51C[GetBankIdentity(a) / 2], 240, 160, 1); + spriteId2 = CreateSpriteAtEnd(&gSpriteTemplate_820A51C[GetBankIdentity(a) / 2], 240, 160, 1); + + gSprites[spriteId1].oam.affineParam = spriteId2; + gSprites[spriteId2].data5 = spriteId1; + gSprites[spriteId2].oam.tileNum += 32; + gSprites[spriteId2].callback = sub_8043D5C; + sp0 = 2; + } + //_08043B4E + } + //_08043B50 + + spriteId3 = CreateSpriteAtEnd(&gSpriteTemplate_820A56C[gBanksBySide[a]], 140, 60, 0); + sprite = &gSprites[spriteId3]; + SetSubspriteTables(sprite, &gSubspriteTables_820A684[GetBankSide(a)]); + sprite->subspriteMode = 2; + sprite->oam.priority = 1; + CpuCopy32(sub_8043CDC(1), (void *)(OBJ_VRAM0 + sprite->oam.tileNum * 32), 64); + + gSprites[spriteId1].data5 = spriteId3; + gSprites[spriteId1].data6 = a; + gSprites[spriteId1].invisible = TRUE; + gSprites[spriteId2].invisible = TRUE; + sprite->data5 = spriteId1; + sprite->data6 = sp0; + sprite->invisible = TRUE; + + return spriteId1; +} + +u8 battle_make_oam_safari_battle(void) +{ + u8 spriteId1 = CreateSprite(&gSpriteTemplate_820A54C, 240, 160, 1); + u8 spriteId2 = CreateSpriteAtEnd(&gSpriteTemplate_820A54C, 240, 160, 1); + + gSprites[spriteId1].oam.shape = 0; + gSprites[spriteId2].oam.shape = 0; + gSprites[spriteId2].oam.tileNum += 0x40; + gSprites[spriteId1].oam.affineParam = spriteId2; + gSprites[spriteId2].data5 = spriteId1; + gSprites[spriteId2].callback = sub_8043D5C; + return spriteId1; +} + +static const void *sub_8043CDC(u8 a) +{ + return gUnknown_08D1216C[a]; +} + +void sub_8043CEC(struct Sprite *sprite) +{ + u8 r5 = sprite->data5; + + switch (sprite->data6) + { + case 0: + sprite->pos1.x = gSprites[r5].pos1.x + 16; + sprite->pos1.y = gSprites[r5].pos1.y; + break; + case 1: + sprite->pos1.x = gSprites[r5].pos1.x + 16; + sprite->pos1.y = gSprites[r5].pos1.y; + break; + default: + case 2: + sprite->pos1.x = gSprites[r5].pos1.x + 8; + sprite->pos1.y = gSprites[r5].pos1.y; + break; + } + sprite->pos2.x = gSprites[r5].pos2.x; + sprite->pos2.y = gSprites[r5].pos2.y; +} + +static void sub_8043D5C(struct Sprite *sprite) +{ + u8 data5 = sprite->data5; + + sprite->pos1.x = gSprites[data5].pos1.x + 64; + sprite->pos1.y = gSprites[data5].pos1.y; + sprite->pos2.x = gSprites[data5].pos2.x; + sprite->pos2.y = gSprites[data5].pos2.y; +} + +void sub_8043D84(u8 a, u8 b, u32 c, u32 d, u32 e) +{ + ewram17850[a].unk0 = b; + ewram17850[a].unk4 = c; + ewram17850[a].unk8 = d; + ewram17850[a].unkC = e; + ewram17850[a].unk10 = 0xFFFF8000; +} + +void sub_8043DB0(u8 a) +{ + gSprites[a].invisible = TRUE; + gSprites[gSprites[a].data5].invisible = TRUE; + gSprites[gSprites[a].oam.affineParam].invisible = TRUE; +} + +void sub_8043DFC(u8 a) +{ + gSprites[a].invisible = FALSE; + gSprites[gSprites[a].data5].invisible = FALSE; + gSprites[gSprites[a].oam.affineParam].invisible = FALSE; +} + +static void sub_8043E50(u8 spriteId, s16 x, s16 y) +{ + gSprites[spriteId].pos1.x = x; + gSprites[spriteId].pos1.y = y; +} + +void unref_sub_8043E70(u8 a) +{ + DestroySprite(&gSprites[gSprites[a].oam.affineParam]); + DestroySprite(&gSprites[gSprites[a].data5]); + DestroySprite(&gSprites[a]); +} + +void nullsub_11() +{ +} + +void sub_8043EB4(u8 priority) +{ + s32 i; + + for (i = 0; i < gNoOfAllBanks; i++) + { + u8 spriteId1; + u8 spriteId2; + u8 spriteId3; + + spriteId1 = gHealthboxIDs[i]; + spriteId2 = gSprites[spriteId1].oam.affineParam; + spriteId3 = gSprites[spriteId1].data5; + gSprites[spriteId1].oam.priority = priority; + gSprites[spriteId2].oam.priority = priority; + gSprites[spriteId3].oam.priority = priority; + } +} + +void sub_8043F44(u8 a) +{ + s16 x = 0; + s16 y = 0; + + if (!IsDoubleBattle()) + { + if (GetBankSide(a) != 0) + { + x = 44; + y = 30; + } + else + { + x = 158; + y = 88; + } + } + else + { + switch (GetBankIdentity(a)) + { + case 0: + x = 159; + y = 77; + break; + case 2: + x = 171; + y = 102; + break; + case 1: + x = 44; + y = 19; + break; + case 3: + x = 32; + y = 44; + break; + } + } + sub_8043E50(gHealthboxIDs[a], x, y); +} + +#if ENGLISH +#define CHAR_LV_SEPARATOR CHAR_COLON +#elif GERMAN +#define CHAR_LV_SEPARATOR CHAR_PERIOD +#endif + +static void sub_8043FC0(u8 a, u8 b) +{ + u8 str[30]; + void *const *r7; + u8 *ptr; + s32 i; + s32 two; + + // TODO: Make this a local variable + memcpy(str, gUnknown_0820A81C, sizeof(str)); + if (!IsDoubleBattle()) + { + if (GetBankSide(gSprites[a].data6) == 0) + r7 = gUnknown_0820A804; + else + r7 = gUnknown_0820A80C; + } + else + { + if (GetBankSide(gSprites[a].data6) == 0) + r7 = gUnknown_0820A814; + else + r7 = gUnknown_0820A80C; + } + + ptr = str + 6; + if (b == 100) + { + ptr = ConvertIntToDecimalStringN(ptr, 100, 0, 3); + } + else + { + *(ptr++) = EXT_CTRL_CODE_BEGIN; + *(ptr++) = 0x11; + *(ptr++) = 1; + *(ptr++) = EXT_CTRL_CODE_BEGIN; + *(ptr++) = 0x14; + *(ptr++) = 4; + *(ptr++) = CHAR_LV_SEPARATOR; + *(ptr++) = EXT_CTRL_CODE_BEGIN; + *(ptr++) = 0x14; + *(ptr++) = 0; + ptr = ConvertIntToDecimalStringN(ptr, b, 0, 2); + } + + *(ptr++) = EXT_CTRL_CODE_BEGIN; + *(ptr++) = 0x13; + *(ptr++) = 0xF; + *(ptr++) = EOS; + sub_80034D4((u8 *)0x02000000, str); + + two = 2; + for (i = 0; i < two; i++) + CpuCopy32((void *)(0x02000020 + i * 64), r7[i] + gSprites[a].oam.tileNum * 32, 32); +} + +#ifdef NONMATCHING +void sub_80440EC(u8 a, s16 b, u8 c) +{ + u8 str[0x14]; + u8 *ptr; + s32 foo; + void *const *r4; + s32 i; + + // TODO: make this a local variable + memcpy(str, gUnknown_0820A864, sizeof(str)); + foo = gSprites[a].data6; + + if (IsDoubleBattle() == TRUE || GetBankSide(foo) == 1) + { + //_08044136 + sub_8044210(a, b, c); + return; + } + // + ptr = str + 6; + if (c == 0) + { + if (GetBankSide(gSprites[a].data6) == 0) + r4 = gUnknown_0820A83C; + else + r4 = gUnknown_0820A848; + c = 3; + ptr = sub_8003504(ptr, b, 0x13, 1); + *(ptr++) = 0xBA; + *(ptr++) = 0xFF; + sub_80034D4((u8 *)0x02000000, str); + } + else + { + if (GetBankSide(gSprites[a].data6) == 0) + r4 = gUnknown_0820A854; + else + r4 = gUnknown_0820A85C; + c = 2; + sub_8003504(ptr, b, 0xF, 1); + sub_80034D4((u8 *)0x02000000, str); + } + //asm(""::"r"(a)); + //_080441B6 + for (i = 0; i < c; i++) // _080440BC + { + void *temp = r4[i] + gSprites[a].oam.tileNum * 32; + CpuCopy32((void *)(0x02000020 + i * 0x40), temp, 0x20); + } +} +#else +__attribute__((naked)) +void sub_80440EC(u8 a, s16 b, u8 c) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + sub sp, 0x14\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ + lsls r1, 16\n\ + lsrs r6, r1, 16\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + mov r8, r2\n\ + ldr r1, _08044144 @ =gUnknown_0820A864\n\ + mov r0, sp\n\ + movs r2, 0x14\n\ + bl memcpy\n\ + ldr r1, _08044148 @ =gSprites\n\ + lsls r0, r7, 4\n\ + adds r0, r7\n\ + lsls r0, 2\n\ + adds r4, r0, r1\n\ + movs r0, 0x3A\n\ + ldrsh r5, [r4, r0]\n\ + bl IsDoubleBattle\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + beq _08044136\n\ + lsls r0, r5, 24\n\ + lsrs r0, 24\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _0804414C\n\ +_08044136:\n\ + lsls r1, r6, 16\n\ + asrs r1, 16\n\ + adds r0, r7, 0\n\ + mov r2, r8\n\ + bl sub_8044210\n\ + b _080441F0\n\ + .align 2, 0\n\ +_08044144: .4byte gUnknown_0820A864\n\ +_08044148: .4byte gSprites\n\ +_0804414C:\n\ + mov r5, sp\n\ + adds r5, 0x6\n\ + mov r0, r8\n\ + cmp r0, 0\n\ + bne _08044190\n\ + ldrh r0, [r4, 0x3A]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + ldr r4, _08044188 @ =gUnknown_0820A848\n\ + cmp r0, 0\n\ + bne _0804416A\n\ + ldr r4, _0804418C @ =gUnknown_0820A83C\n\ +_0804416A:\n\ + movs r0, 0x3\n\ + mov r8, r0\n\ + lsls r1, r6, 16\n\ + asrs r1, 16\n\ + adds r0, r5, 0\n\ + movs r2, 0x13\n\ + movs r3, 0x1\n\ + bl sub_8003504\n\ + adds r5, r0, 0\n\ + movs r0, 0xBA\n\ + strb r0, [r5]\n\ + movs r0, 0xFF\n\ + strb r0, [r5, 0x1]\n\ + b _080441B6\n\ + .align 2, 0\n\ +_08044188: .4byte gUnknown_0820A848\n\ +_0804418C: .4byte gUnknown_0820A83C\n\ +_08044190:\n\ + ldrh r0, [r4, 0x3A]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + ldr r4, _080441FC @ =gUnknown_0820A85C\n\ + cmp r0, 0\n\ + bne _080441A4\n\ + ldr r4, _08044200 @ =gUnknown_0820A854\n\ +_080441A4:\n\ + movs r0, 0x2\n\ + mov r8, r0\n\ + lsls r1, r6, 16\n\ + asrs r1, 16\n\ + adds r0, r5, 0\n\ + movs r2, 0xF\n\ + movs r3, 0x1\n\ + bl sub_8003504\n\ +_080441B6:\n\ + movs r0, 0x80\n\ + lsls r0, 18\n\ + mov r1, sp\n\ + bl sub_80034D4\n\ + mov r0, r8\n\ + cmp r0, 0\n\ + beq _080441F0\n\ + ldr r1, _08044204 @ =gSprites\n\ + lsls r0, r7, 4\n\ + adds r0, r7\n\ + lsls r0, 2\n\ + adds r6, r0, r1\n\ + adds r7, r4, 0\n\ + ldr r5, _08044208 @ =0x02000020\n\ + mov r4, r8\n\ +_080441D6:\n\ + ldrh r0, [r6, 0x4]\n\ + lsls r0, 22\n\ + lsrs r0, 17\n\ + ldm r7!, {r1}\n\ + adds r1, r0\n\ + adds r0, r5, 0\n\ + ldr r2, _0804420C @ =REG_BG0CNT\n\ + bl CpuSet\n\ + adds r5, 0x40\n\ + subs r4, 0x1\n\ + cmp r4, 0\n\ + bne _080441D6\n\ +_080441F0:\n\ + add sp, 0x14\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080441FC: .4byte gUnknown_0820A85C\n\ +_08044200: .4byte gUnknown_0820A854\n\ +_08044204: .4byte gSprites\n\ +_08044208: .4byte 0x02000020\n\ +_0804420C: .4byte 0x04000008\n\ + .syntax divided\n"); +} +#endif + +static void sub_8044210(u8 a, s16 b, u8 c) +{ + u8 str[0x14]; + u8 *ptr; + void *const *r7; + int r10; + int r4; + int i; + + // TODO: make this a local variable + memcpy(str, gUnknown_0820A89C, sizeof(str)); + r4 = gSprites[a].data6; + if ((ewram17800[r4].unk0_4) == 0) + return; + ptr = str + 6; + if (c == 0) + { + r7 = gUnknown_0820A87C; + r10 = 6; + ptr = sub_8003504(ptr, b, 0x2B, 1); + *(ptr++) = CHAR_SLASH; + *(ptr++) = EOS; + } + else + { + r7 = gUnknown_0820A894; + r10 = 2; + sub_8003504(ptr, b, 0xF, 1); + if (GetBankSide(r4) == 0) + { + CpuCopy32(sub_8043CDC(0x74), (void *)(OBJ_VRAM0 + (gSprites[a].oam.tileNum + 0x34) * 32), 32); + } + } + r4 = gSprites[a].data5; + sub_80034D4((u8 *)0x02000000, str); + for (i = 0; i < r10; i++) + { + CpuCopy32((void *)(0x02000020 + i * 0x40), r7[i] + gSprites[r4].oam.tileNum * 32, 0x20); + } +} + +#ifdef NONMATCHING +void sub_8044338(u8 a, struct Pokemon *pkmn) +{ + u8 str[0x14]; + u8 *r6; + s32 r8; + u8 nature; // = GetNature(pkmn); + s32 r7; + u8 i; + u8 r5; + + // TODO: make this a local variable + memcpy(str, gUnknown_0820A864, sizeof(str)); + r6 = ewram520[GetBankIdentity(gSprites[a].data6)].filler0; + r8 = 5; + nature = GetNature(pkmn); + StringCopy(str + 6, gNatureNames[nature]); + sub_80034D4(r6, str); + r7 = 6; + for (i = 0; i < (u32)r8; i++, r7++) //_080443AA + { + u8 val; + + if ((u8)(str[r7] - 0x37) <= 0x13 || (u8)(str[r7] + 0x79) <= 0x13) + val = 0x2C; + //_080443DC + else if ((u8)(str[r7] - 0x4B) <= 4 || (u8)(str[r7] + 0x65) <= 4) + val = 0x2D; + else + val = 0x2B; + + CpuCopy32(sub_8043CDC(val), r6 + i * 64, 32); + } + //r7 = 1; + //sp18 = a * 16; + for (r7 = 1; r7 < r8 + 1; r7++) + { + int foo; + + foo = gSprites[a].oam.tileNum + MACRO1(r7); + CpuCopy32(r6, (u8 *)0x06010000 + foo * 32, 32); + r6 += 32; + + foo = gSprites[a].oam.tileNum + 8 + MACRO1(r7); + CpuCopy32(r6, (u8 *)0x06010000 + foo * 32, 32); + r6 += 32; + } + //_08044486 + r5 = gSprites[a].data5; + ConvertIntToDecimalStringN(str + 6, ewram[0x16089], 1, 2); + ConvertIntToDecimalStringN(str + 9, ewram[0x16088], 1, 2); + str[5] = 0; + str[8] = 0xBA; + sub_80034D4((u8 *)0x02000000, str); + + for (r7 = 0; r7 < 5; r7++) + { + if (r7 <= 1) + { + int foo = (gSprites[r5].oam.tileNum + 2 + r7); + CpuCopy32((u8 *)0x02000020 + r7 * 0x40, (u8 *)0x06010000 + foo * 32, 32); + } + else + { + int foo = (r7 + gSprites[r5].oam.tileNum); + CpuCopy32((u8 *)0x02000020 + r7 * 0x40, (u8 *)0x060100C0 + foo * 32, 32); + } + } +} +#else +__attribute__((naked)) +void sub_8044338(u8 a, struct Pokemon *pkmn) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x20\n\ + adds r4, r1, 0\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x14]\n\ + ldr r1, _080443CC @ =gUnknown_0820A864\n\ + mov r0, sp\n\ + movs r2, 0x14\n\ + bl memcpy\n\ + ldr r1, _080443D0 @ =gSprites\n\ + ldr r2, [sp, 0x14]\n\ + lsls r0, r2, 4\n\ + adds r0, r2\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x3A]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + bl GetBankIdentity\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r1, r0, 1\n\ + adds r1, r0\n\ + lsls r1, 7\n\ + ldr r3, _080443D4 @ =0x02000520\n\ + adds r6, r1, r3\n\ + movs r0, 0x5\n\ + mov r8, r0\n\ + adds r0, r4, 0\n\ + bl GetNature\n\ + lsls r0, 24\n\ + mov r4, sp\n\ + adds r4, 0x6\n\ + ldr r1, _080443D8 @ =gNatureNames\n\ + lsrs r0, 22\n\ + adds r0, r1\n\ + ldr r1, [r0]\n\ + adds r0, r4, 0\n\ + bl StringCopy\n\ + adds r0, r6, 0\n\ + mov r1, sp\n\ + bl sub_80034D4\n\ + movs r7, 0x6\n\ + movs r5, 0\n\ + mov r1, sp\n\ + adds r1, 0x9\n\ + str r1, [sp, 0x1C]\n\ +_080443AA:\n\ + mov r2, sp\n\ + adds r0, r2, r7\n\ + ldrb r1, [r0]\n\ + adds r0, r1, 0\n\ + subs r0, 0x37\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x13\n\ + bls _080443C8\n\ + adds r0, r1, 0\n\ + adds r0, 0x79\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x13\n\ + bhi _080443DC\n\ +_080443C8:\n\ + movs r0, 0x2C\n\ + b _080443FA\n\ + .align 2, 0\n\ +_080443CC: .4byte gUnknown_0820A864\n\ +_080443D0: .4byte gSprites\n\ +_080443D4: .4byte 0x02000520\n\ +_080443D8: .4byte gNatureNames\n\ +_080443DC:\n\ + adds r0, r1, 0\n\ + subs r0, 0x4B\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x4\n\ + bls _080443F4\n\ + adds r0, r1, 0\n\ + adds r0, 0x65\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x4\n\ + bhi _080443F8\n\ +_080443F4:\n\ + movs r0, 0x2D\n\ + b _080443FA\n\ +_080443F8:\n\ + movs r0, 0x2B\n\ +_080443FA:\n\ + bl sub_8043CDC\n\ + lsls r1, r5, 6\n\ + adds r1, r6, r1\n\ + ldr r2, _080444F8 @ =REG_BG0CNT\n\ + bl CpuSet\n\ + adds r0, r5, 0x1\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + adds r7, 0x1\n\ + cmp r5, r8\n\ + bcc _080443AA\n\ + movs r7, 0x1\n\ + ldr r3, [sp, 0x14]\n\ + lsls r3, 4\n\ + str r3, [sp, 0x18]\n\ + movs r0, 0x1\n\ + add r0, r8\n\ + mov r9, r0\n\ + cmp r7, r9\n\ + bge _08044486\n\ + ldr r1, _080444FC @ =gSprites\n\ + ldr r2, _080444F8 @ =REG_BG0CNT\n\ + mov r10, r2\n\ + ldr r2, [sp, 0x14]\n\ + adds r0, r3, r2\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + mov r8, r0\n\ +_08044436:\n\ + mov r3, r8\n\ + ldrh r0, [r3, 0x4]\n\ + lsls r0, 22\n\ + lsrs r0, 22\n\ + adds r5, r7, 0\n\ + cmp r7, 0\n\ + bge _08044446\n\ + adds r5, r7, 0x7\n\ +_08044446:\n\ + asrs r5, 3\n\ + lsls r4, r5, 3\n\ + subs r4, r7, r4\n\ + adds r0, r4\n\ + lsls r5, 6\n\ + adds r0, r5\n\ + lsls r0, 5\n\ + ldr r2, _08044500 @ =0x06010000\n\ + adds r1, r0, r2\n\ + adds r0, r6, 0\n\ + mov r2, r10\n\ + bl CpuSet\n\ + adds r6, 0x20\n\ + mov r3, r8\n\ + ldrh r0, [r3, 0x4]\n\ + lsls r0, 22\n\ + lsrs r0, 22\n\ + adds r4, 0x8\n\ + adds r0, r4\n\ + adds r0, r5\n\ + lsls r0, 5\n\ + ldr r2, _08044500 @ =0x06010000\n\ + adds r1, r0, r2\n\ + adds r0, r6, 0\n\ + mov r2, r10\n\ + bl CpuSet\n\ + adds r6, 0x20\n\ + adds r7, 0x1\n\ + cmp r7, r9\n\ + blt _08044436\n\ +_08044486:\n\ + ldr r6, _080444FC @ =gSprites\n\ + ldr r3, [sp, 0x18]\n\ + ldr r1, [sp, 0x14]\n\ + adds r0, r3, r1\n\ + lsls r0, 2\n\ + adds r0, r6\n\ + ldrh r5, [r0, 0x38]\n\ + lsls r5, 24\n\ + lsrs r5, 24\n\ + ldr r4, _08044504 @ =0x02000000\n\ + ldr r2, _08044508 @ =0x00016089\n\ + adds r0, r4, r2\n\ + ldrb r1, [r0]\n\ + mov r0, sp\n\ + adds r0, 0x6\n\ + movs r2, 0x1\n\ + movs r3, 0x2\n\ + bl ConvertIntToDecimalStringN\n\ + ldr r3, _0804450C @ =0x00016088\n\ + adds r4, r3\n\ + ldrb r1, [r4]\n\ + ldr r0, [sp, 0x1C]\n\ + movs r2, 0x1\n\ + movs r3, 0x2\n\ + bl ConvertIntToDecimalStringN\n\ + mov r1, sp\n\ + movs r0, 0\n\ + strb r0, [r1, 0x5]\n\ + movs r0, 0xBA\n\ + strb r0, [r1, 0x8]\n\ + movs r0, 0x80\n\ + lsls r0, 18\n\ + bl sub_80034D4\n\ + movs r7, 0\n\ + lsls r0, r5, 4\n\ + adds r0, r5\n\ + lsls r0, 2\n\ + adds r5, r0, r6\n\ + ldr r4, _08044510 @ =0x02000020\n\ +_080444DA:\n\ + cmp r7, 0x1\n\ + bgt _08044514\n\ + ldrh r1, [r5, 0x4]\n\ + lsls r1, 22\n\ + lsrs r1, 22\n\ + adds r0, r7, 0x2\n\ + adds r1, r0\n\ + lsls r1, 5\n\ + ldr r0, _08044500 @ =0x06010000\n\ + adds r1, r0\n\ + adds r0, r4, 0\n\ + ldr r2, _080444F8 @ =REG_BG0CNT\n\ + bl CpuSet\n\ + b _0804452A\n\ + .align 2, 0\n\ +_080444F8: .4byte 0x04000008\n\ +_080444FC: .4byte gSprites\n\ +_08044500: .4byte 0x06010000\n\ +_08044504: .4byte 0x02000000\n\ +_08044508: .4byte 0x00016089\n\ +_0804450C: .4byte 0x00016088\n\ +_08044510: .4byte 0x02000020\n\ +_08044514:\n\ + ldrh r1, [r5, 0x4]\n\ + lsls r1, 22\n\ + lsrs r1, 22\n\ + adds r1, r7, r1\n\ + lsls r1, 5\n\ + ldr r2, _08044544 @ =0x060100c0\n\ + adds r1, r2\n\ + adds r0, r4, 0\n\ + ldr r2, _08044548 @ =REG_BG0CNT\n\ + bl CpuSet\n\ +_0804452A:\n\ + adds r4, 0x40\n\ + adds r7, 0x1\n\ + cmp r7, 0x4\n\ + ble _080444DA\n\ + add sp, 0x20\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_08044544: .4byte 0x060100c0\n\ +_08044548: .4byte 0x04000008\n\ + .syntax divided\n"); +} +#endif + +void sub_804454C(void) +{ + s32 i; + u8 spriteId; + + for (i = 0; i < gNoOfAllBanks; i++) + { + if (gSprites[gHealthboxIDs[i]].callback == SpriteCallbackDummy + && GetBankSide(i) != 1 + && (IsDoubleBattle() || GetBankSide(i) != 0)) + { + u8 r6; + + ewram17800[i].unk0_4 ^= 1; + r6 = ewram17800[i].unk0_4; + if (GetBankSide(i) == 0) + { + + if (!IsDoubleBattle()) + continue; + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + continue; + + if (r6 == 1) + { + spriteId = gSprites[gHealthboxIDs[i]].data5; + + CpuFill32(0, (void *)(OBJ_VRAM0 + gSprites[spriteId].oam.tileNum * 32), 0x100); + sub_8044210(gHealthboxIDs[i], GetMonData(&gPlayerParty[gBattlePartyID[i]], MON_DATA_HP), 0); + sub_8044210(gHealthboxIDs[i], GetMonData(&gPlayerParty[gBattlePartyID[i]], MON_DATA_MAX_HP), 1); + } + else + { + draw_status_ailment_maybe(gHealthboxIDs[i]); + sub_8045A5C(gHealthboxIDs[i], &gPlayerParty[gBattlePartyID[i]], 5); + CpuCopy32(sub_8043CDC(0x75), (void *)(OBJ_VRAM0 + 0x680 + gSprites[gHealthboxIDs[i]].oam.tileNum * 32), 32); + } + } + else + { + if (r6 == 1) + { + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + { + sub_8044338(gHealthboxIDs[i], &gEnemyParty[gBattlePartyID[i]]); + } + else + { + spriteId = gSprites[gHealthboxIDs[i]].data5; + + CpuFill32(0, (void *)(OBJ_VRAM0 + gSprites[spriteId].oam.tileNum * 32), 0x100); + sub_8044210(gHealthboxIDs[i], GetMonData(&gEnemyParty[gBattlePartyID[i]], MON_DATA_HP), 0); + sub_8044210(gHealthboxIDs[i], GetMonData(&gEnemyParty[gBattlePartyID[i]], MON_DATA_MAX_HP), 1); + } + } + else + { + draw_status_ailment_maybe(gHealthboxIDs[i]); + sub_8045A5C(gHealthboxIDs[i], &gEnemyParty[gBattlePartyID[i]], 5); + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + sub_8045A5C(gHealthboxIDs[i], &gEnemyParty[gBattlePartyID[i]], 4); + } + } + gSprites[gHealthboxIDs[i]].data7 ^= 1; + } + } +} + +// This function almost matches except for just two instructions around 0x08044B52 that are swapped. +#ifdef NONMATCHING +u8 sub_8044804(u8 a, const struct BattleInterfaceStruct2 *b, u8 c, u8 d) +{ + u8 r7; + s16 x; + s16 y; + s16 r8; + s16 r5; + + int i; + u8 sp[6]; + s8 sp14; + u8 sp18; + u8 taskId; + + if (c == 0 || GetBankIdentity(a) != 3) + { + if (GetBankSide(a) == 0) + { + r7 = 0; + x = 136; + y = 96; + r8 = 100; + r5 = -5; + } + else + { + r7 = 1; + if (c == 0 || !IsDoubleBattle()) + { + x = 104; + y = 40; + } + else + { + x = 104; + y = 16; + } + r8 = -100; + r5 = 5; + } + } + else + { + r7 = 1; + x = 104; + y = 40; + r8 = -100; + r5 = 5; + } + //_08044884 + + sp14 = 0; + for (i = 0; i < 6; i++) //_080448A0 + { + if (b[i].unk0 != 0xFFFF) + sp14++; + } + + LoadCompressedObjectPic(&gUnknown_0820A754[r7]); + LoadSpriteSheet(&gUnknown_0820A784[r7]); + LoadSpritePalette(&gUnknown_0820A764[r7]); + LoadSpritePalette(&gUnknown_0820A774[r7]); + + sp18 = CreateSprite(&gSpriteTemplate_820A7A4[r7], x, y, 10); + SetSubspriteTables(&gSprites[sp18], gSubspriteTables_820A6E4); + gSprites[sp18].pos2.x = r8; + gSprites[sp18].data0 = r5; + if (r7 != 0) + { + gSprites[sp18].pos1.x -= 96; + gSprites[sp18].oam.matrixNum = 8; + } + else + { + gSprites[sp18].pos1.x += 0x60; + } + //_0804495A + for (i = 0; i < 6; i++) //_08044970 + { + sp[i] = CreateSpriteAtEnd(&gSpriteTemplate_820A7D4[r7], x, y - 4, 9); + if (d == 0) + { + gSprites[sp[i]].callback = sub_8045180; + } + //_080449A0 + if (r7 == 0) + { + gSprites[sp[i]].pos2.x = 0; + gSprites[sp[i]].pos2.y = 0; + } + //_080449BE + gSprites[sp[i]].data0 = sp18; + if (r7 == 0) + { + gSprites[sp[i]].pos1.x += 10 * i + 24; + gSprites[sp[i]].data1 = i * 7 + 10; + gSprites[sp[i]].pos2.x = 120; + } + //_08044A18 + else + { + gSprites[sp[i]].pos1.x -= 10 * (5 - i) + 24; + gSprites[sp[i]].data1 = (6 - i) * 7 + 10; + gSprites[sp[i]].pos2.x = -120; + } + //_08044A56 + gSprites[sp[i]].data2 = r7; + } + //_08044A76 + if (GetBankSide(a) == 0) + { + for (i = 0; i < 6; i++) //_08044A9A + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) // && b[i] != 0xFFFF && b[i] + { + if (b[i].unk0 == 0xFFFF) + { + //_08044AE6 + gSprites[sp[i]].oam.tileNum += 1; + gSprites[sp[i]].data7 = 1; + // to _08044B52 + } + else if (b[i].unk0 == 0) + { + gSprites[sp[i]].oam.tileNum += 3; + // to _08044B46 + } + else if (b[i].unk4 != 0) + { + gSprites[sp[i]].oam.tileNum += 2; + } + } + //_08044ADC + else + { + if (i >= sp14) + { + //_08044AE6 + gSprites[sp[i]].oam.tileNum += 1; + gSprites[sp[i]].data7 = 1; + // to _08044B52 + } + else if (b[i].unk0 == 0) + { + //_08044B14 + gSprites[sp[i]].oam.tileNum += 3; + // to _08044B46 + } + else if (b[i].unk4 != 0) + { + gSprites[sp[i]].oam.tileNum += 2; + } + } + } + } + //_08044B5E + else + { + // Mismatch occurrs in this loop initialization + for (i = 0; i < 6; i++) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (b[i].unk0 == 0xFFFF) + { + gSprites[sp[5 - i]].oam.tileNum += 1; + gSprites[sp[5 - i]].data7 = 1; + } + else if (b[i].unk0 == 0) + { + gSprites[sp[5 - i]].oam.tileNum += 3; + } + else if (b[i].unk4 != 0) + { + gSprites[sp[5 - i]].oam.tileNum += 2; + } + } + else + { + if (i >= sp14) + { + gSprites[sp[5 - i]].oam.tileNum += 1; + gSprites[sp[5 - i]].data7 = 1; + } + else if (b[i].unk0 == 0) + { + gSprites[sp[5 - i]].oam.tileNum += 3; + } + else if (b[i].unk4 != 0) + { + gSprites[sp[5 - i]].oam.tileNum += 2; + } + } + // This corrects the initialization order, but messes up the counter update order + asm(""::"r"(&b[i])); + } + } + //_08044C38 + taskId = CreateTask(TaskDummy, 5); + gTasks[taskId].data[0] = a; + gTasks[taskId].data[1] = sp18; + for (i = 0; i < 6; i++) + gTasks[taskId].data[3 + i] = sp[i]; + gTasks[taskId].data[10] = d; + PlaySE12WithPanning(SE_TB_START, 0); + return taskId; +} +#else +__attribute__((naked)) +u8 sub_8044804(u8 a, const struct BattleInterfaceStruct2 *b, u8 c, u8 d) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x28\n\ + str r1, [sp, 0xC]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x8]\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + adds r4, r2, 0\n\ + lsls r3, 24\n\ + lsrs r3, 24\n\ + str r3, [sp, 0x10]\n\ + cmp r4, 0\n\ + beq _08044834\n\ + bl GetBankIdentity\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x3\n\ + beq _08044878\n\ +_08044834:\n\ + ldr r0, [sp, 0x8]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _08044854\n\ + movs r7, 0\n\ + movs r1, 0x88\n\ + movs r2, 0x60\n\ + movs r0, 0x64\n\ + mov r8, r0\n\ + ldr r5, _08044850 @ =0x0000fffb\n\ + b _08044884\n\ + .align 2, 0\n\ +_08044850: .4byte 0x0000fffb\n\ +_08044854:\n\ + movs r7, 0x1\n\ + cmp r4, 0\n\ + beq _08044864\n\ + bl IsDoubleBattle\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _0804486A\n\ +_08044864:\n\ + movs r1, 0x68\n\ + movs r2, 0x28\n\ + b _0804486E\n\ +_0804486A:\n\ + movs r1, 0x68\n\ + movs r2, 0x10\n\ +_0804486E:\n\ + ldr r3, _08044874 @ =0x0000ff9c\n\ + mov r8, r3\n\ + b _08044882\n\ + .align 2, 0\n\ +_08044874: .4byte 0x0000ff9c\n\ +_08044878:\n\ + movs r7, 0x1\n\ + movs r1, 0x68\n\ + movs r2, 0x28\n\ + ldr r5, _08044930 @ =0x0000ff9c\n\ + mov r8, r5\n\ +_08044882:\n\ + movs r5, 0x5\n\ +_08044884:\n\ + movs r6, 0\n\ + str r6, [sp, 0x14]\n\ + lsls r4, r7, 3\n\ + ldr r0, _08044934 @ =gUnknown_0820A754\n\ + mov r10, r0\n\ + lsls r3, r7, 1\n\ + mov r9, r3\n\ + lsls r1, 16\n\ + str r1, [sp, 0x20]\n\ + lsls r2, 16\n\ + str r2, [sp, 0x24]\n\ + ldr r2, _08044938 @ =0x0000ffff\n\ + ldr r1, [sp, 0xC]\n\ + movs r6, 0x5\n\ +_080448A0:\n\ + ldrh r0, [r1]\n\ + cmp r0, r2\n\ + beq _080448B4\n\ + ldr r3, [sp, 0x14]\n\ + lsls r0, r3, 24\n\ + movs r3, 0x80\n\ + lsls r3, 17\n\ + adds r0, r3\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x14]\n\ +_080448B4:\n\ + adds r1, 0x8\n\ + subs r6, 0x1\n\ + cmp r6, 0\n\ + bge _080448A0\n\ + mov r6, r10\n\ + adds r0, r4, r6\n\ + bl LoadCompressedObjectPic\n\ + ldr r0, _0804493C @ =gUnknown_0820A784\n\ + adds r0, r4, r0\n\ + bl LoadSpriteSheet\n\ + ldr r0, _08044940 @ =gUnknown_0820A764\n\ + adds r0, r4, r0\n\ + bl LoadSpritePalette\n\ + ldr r0, _08044944 @ =gUnknown_0820A774\n\ + adds r0, r4, r0\n\ + bl LoadSpritePalette\n\ + mov r1, r9\n\ + adds r0, r1, r7\n\ + lsls r0, 3\n\ + ldr r1, _08044948 @ =gSpriteTemplate_820A7A4\n\ + adds r0, r1\n\ + ldr r2, [sp, 0x20]\n\ + asrs r1, r2, 16\n\ + ldr r3, [sp, 0x24]\n\ + asrs r2, r3, 16\n\ + movs r3, 0xA\n\ + bl CreateSprite\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x18]\n\ + lsls r0, 4\n\ + ldr r6, [sp, 0x18]\n\ + adds r0, r6\n\ + lsls r0, 2\n\ + ldr r1, _0804494C @ =gSprites\n\ + adds r4, r0, r1\n\ + ldr r1, _08044950 @ =gSubspriteTables_820A6E4\n\ + adds r0, r4, 0\n\ + bl SetSubspriteTables\n\ + mov r0, r8\n\ + strh r0, [r4, 0x24]\n\ + strh r5, [r4, 0x2E]\n\ + cmp r7, 0\n\ + beq _08044954\n\ + ldrh r0, [r4, 0x20]\n\ + subs r0, 0x60\n\ + strh r0, [r4, 0x20]\n\ + ldrb r1, [r4, 0x3]\n\ + movs r0, 0x3F\n\ + negs r0, r0\n\ + ands r0, r1\n\ + movs r1, 0x10\n\ + orrs r0, r1\n\ + strb r0, [r4, 0x3]\n\ + b _0804495A\n\ + .align 2, 0\n\ +_08044930: .4byte 0x0000ff9c\n\ +_08044934: .4byte gUnknown_0820A754\n\ +_08044938: .4byte 0x0000ffff\n\ +_0804493C: .4byte gUnknown_0820A784\n\ +_08044940: .4byte gUnknown_0820A764\n\ +_08044944: .4byte gUnknown_0820A774\n\ +_08044948: .4byte gSpriteTemplate_820A7A4\n\ +_0804494C: .4byte gSprites\n\ +_08044950: .4byte gSubspriteTables_820A6E4\n\ +_08044954:\n\ + ldrh r0, [r4, 0x20]\n\ + adds r0, 0x60\n\ + strh r0, [r4, 0x20]\n\ +_0804495A:\n\ + movs r6, 0\n\ + ldr r1, _08044A04 @ =gSprites\n\ + mov r10, r1\n\ + mov r4, sp\n\ + mov r2, r9\n\ + adds r0, r2, r7\n\ + lsls r0, 3\n\ + str r0, [sp, 0x1C]\n\ + movs r3, 0xA\n\ + mov r9, r3\n\ + mov r8, r6\n\ +_08044970:\n\ + ldr r0, _08044A08 @ =gSpriteTemplate_820A7D4\n\ + ldr r5, [sp, 0x24]\n\ + ldr r1, _08044A0C @ =0xfffc0000\n\ + adds r2, r5, r1\n\ + ldr r3, [sp, 0x1C]\n\ + adds r0, r3, r0\n\ + ldr r5, [sp, 0x20]\n\ + asrs r1, r5, 16\n\ + asrs r2, 16\n\ + movs r3, 0x9\n\ + bl CreateSpriteAtEnd\n\ + strb r0, [r4]\n\ + ldr r0, [sp, 0x10]\n\ + cmp r0, 0\n\ + bne _080449A0\n\ + ldrb r0, [r4]\n\ + lsls r1, r0, 4\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + ldr r2, _08044A10 @ =gSprites + 0x1C\n\ + adds r1, r2\n\ + ldr r0, _08044A14 @ =sub_8045180\n\ + str r0, [r1]\n\ +_080449A0:\n\ + ldr r5, _08044A04 @ =gSprites\n\ + cmp r7, 0\n\ + bne _080449BE\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + add r0, r10\n\ + strh r7, [r0, 0x24]\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + add r0, r10\n\ + strh r7, [r0, 0x26]\n\ +_080449BE:\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r5\n\ + movs r1, 0\n\ + mov r3, sp\n\ + ldrh r3, [r3, 0x18]\n\ + strh r3, [r0, 0x2E]\n\ + cmp r7, 0\n\ + bne _08044A18\n\ + ldrb r0, [r4]\n\ + lsls r1, r0, 4\n\ + adds r1, r0\n\ + lsls r1, 2\n\ + adds r1, r5\n\ + ldrh r0, [r1, 0x20]\n\ + adds r0, 0x18\n\ + add r0, r8\n\ + strh r0, [r1, 0x20]\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r5\n\ + mov r1, r9\n\ + strh r1, [r0, 0x30]\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r5\n\ + movs r1, 0x78\n\ + b _08044A56\n\ + .align 2, 0\n\ +_08044A04: .4byte gSprites\n\ +_08044A08: .4byte gSpriteTemplate_820A7D4\n\ +_08044A0C: .4byte 0xfffc0000\n\ +_08044A10: .4byte gSprites + 0x1C\n\ +_08044A14: .4byte sub_8045180\n\ +_08044A18:\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r5\n\ + ldrh r3, [r2, 0x20]\n\ + subs r3, 0x18\n\ + movs r1, 0x5\n\ + subs r1, r6\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 1\n\ + subs r3, r0\n\ + strh r3, [r2, 0x20]\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r5\n\ + movs r1, 0x6\n\ + subs r1, r6\n\ + lsls r0, r1, 3\n\ + subs r0, r1\n\ + adds r0, 0xA\n\ + strh r0, [r2, 0x30]\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r5\n\ + ldr r1, _08044AC4 @ =0x0000ff88\n\ +_08044A56:\n\ + strh r1, [r0, 0x24]\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r5\n\ + strh r7, [r0, 0x32]\n\ + adds r4, 0x1\n\ + movs r2, 0x7\n\ + add r9, r2\n\ + movs r3, 0xA\n\ + add r8, r3\n\ + adds r6, 0x1\n\ + cmp r6, 0x5\n\ + bgt _08044A76\n\ + b _08044970\n\ +_08044A76:\n\ + ldr r0, [sp, 0x8]\n\ + bl GetBankSide\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _08044B5E\n\ + movs r6, 0\n\ + ldr r5, _08044AC8 @ =gBattleTypeFlags\n\ + mov r10, r5\n\ + ldr r0, _08044ACC @ =0x0000ffff\n\ + mov r9, r0\n\ + ldr r7, _08044AD0 @ =gSprites\n\ + ldr r1, _08044AD4 @ =0x000003ff\n\ + mov r12, r1\n\ + ldr r2, _08044AD8 @ =0xfffffc00\n\ + mov r8, r2\n\ + mov r4, sp\n\ + ldr r5, [sp, 0xC]\n\ +_08044A9A:\n\ + mov r3, r10\n\ + ldrh r1, [r3]\n\ + movs r0, 0x40\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08044ADC\n\ + ldrh r0, [r5]\n\ + cmp r0, r9\n\ + beq _08044AE6\n\ + cmp r0, 0\n\ + bne _08044B2E\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r7\n\ + ldrh r3, [r2, 0x4]\n\ + lsls r1, r3, 22\n\ + lsrs r1, 22\n\ + adds r1, 0x3\n\ + b _08044B46\n\ + .align 2, 0\n\ +_08044AC4: .4byte 0x0000ff88\n\ +_08044AC8: .4byte gBattleTypeFlags\n\ +_08044ACC: .4byte 0x0000ffff\n\ +_08044AD0: .4byte gSprites\n\ +_08044AD4: .4byte 0x000003ff\n\ +_08044AD8: .4byte 0xfffffc00\n\ +_08044ADC:\n\ + ldr r1, [sp, 0x14]\n\ + lsls r0, r1, 24\n\ + asrs r0, 24\n\ + cmp r6, r0\n\ + blt _08044B14\n\ +_08044AE6:\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r7\n\ + ldrh r3, [r2, 0x4]\n\ + lsls r1, r3, 22\n\ + lsrs r1, 22\n\ + adds r1, 0x1\n\ + mov r0, r12\n\ + ands r1, r0\n\ + mov r0, r8\n\ + ands r0, r3\n\ + orrs r0, r1\n\ + strh r0, [r2, 0x4]\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r7\n\ + movs r1, 0x1\n\ + strh r1, [r0, 0x3C]\n\ + b _08044B52\n\ +_08044B14:\n\ + ldrh r0, [r5]\n\ + cmp r0, 0\n\ + bne _08044B2E\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r7\n\ + ldrh r3, [r2, 0x4]\n\ + lsls r1, r3, 22\n\ + lsrs r1, 22\n\ + adds r1, 0x3\n\ + b _08044B46\n\ +_08044B2E:\n\ + ldr r0, [r5, 0x4]\n\ + cmp r0, 0\n\ + beq _08044B52\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r7\n\ + ldrh r3, [r2, 0x4]\n\ + lsls r1, r3, 22\n\ + lsrs r1, 22\n\ + adds r1, 0x2\n\ +_08044B46:\n\ + mov r0, r12\n\ + ands r1, r0\n\ + mov r0, r8\n\ + ands r0, r3\n\ + orrs r0, r1\n\ + strh r0, [r2, 0x4]\n\ +_08044B52:\n\ + adds r4, 0x1\n\ + adds r5, 0x8\n\ + adds r6, 0x1\n\ + cmp r6, 0x5\n\ + ble _08044A9A\n\ + b _08044C38\n\ +_08044B5E:\n\ + movs r6, 0\n\ + ldr r1, _08044BA4 @ =gBattleTypeFlags\n\ + mov r10, r1\n\ + ldr r2, _08044BA8 @ =0x0000ffff\n\ + mov r9, r2\n\ + ldr r7, _08044BAC @ =gSprites\n\ + ldr r3, _08044BB0 @ =0x000003ff\n\ + mov r12, r3\n\ + ldr r5, _08044BB4 @ =0xfffffc00\n\ + mov r8, r5\n\ + ldr r5, [sp, 0xC]\n\ + mov r4, sp\n\ + adds r4, 0x5\n\ +_08044B78:\n\ + mov r0, r10\n\ + ldrh r1, [r0]\n\ + movs r0, 0x40\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _08044BB8\n\ + ldrh r0, [r5]\n\ + cmp r0, r9\n\ + beq _08044BC2\n\ + cmp r0, 0\n\ + bne _08044C0A\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r7\n\ + ldrh r3, [r2, 0x4]\n\ + lsls r1, r3, 22\n\ + lsrs r1, 22\n\ + adds r1, 0x3\n\ + b _08044C22\n\ + .align 2, 0\n\ +_08044BA4: .4byte gBattleTypeFlags\n\ +_08044BA8: .4byte 0x0000ffff\n\ +_08044BAC: .4byte gSprites\n\ +_08044BB0: .4byte 0x000003ff\n\ +_08044BB4: .4byte 0xfffffc00\n\ +_08044BB8:\n\ + ldr r1, [sp, 0x14]\n\ + lsls r0, r1, 24\n\ + asrs r0, 24\n\ + cmp r6, r0\n\ + blt _08044BF0\n\ +_08044BC2:\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r7\n\ + ldrh r3, [r2, 0x4]\n\ + lsls r1, r3, 22\n\ + lsrs r1, 22\n\ + adds r1, 0x1\n\ + mov r0, r12\n\ + ands r1, r0\n\ + mov r0, r8\n\ + ands r0, r3\n\ + orrs r0, r1\n\ + strh r0, [r2, 0x4]\n\ + ldrb r1, [r4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + adds r0, r7\n\ + movs r1, 0x1\n\ + strh r1, [r0, 0x3C]\n\ + b _08044C2E\n\ +_08044BF0:\n\ + ldrh r0, [r5]\n\ + cmp r0, 0\n\ + bne _08044C0A\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r7\n\ + ldrh r3, [r2, 0x4]\n\ + lsls r1, r3, 22\n\ + lsrs r1, 22\n\ + adds r1, 0x3\n\ + b _08044C22\n\ +_08044C0A:\n\ + ldr r0, [r5, 0x4]\n\ + cmp r0, 0\n\ + beq _08044C2E\n\ + ldrb r0, [r4]\n\ + lsls r2, r0, 4\n\ + adds r2, r0\n\ + lsls r2, 2\n\ + adds r2, r7\n\ + ldrh r3, [r2, 0x4]\n\ + lsls r1, r3, 22\n\ + lsrs r1, 22\n\ + adds r1, 0x2\n\ +_08044C22:\n\ + mov r0, r12\n\ + ands r1, r0\n\ + mov r0, r8\n\ + ands r0, r3\n\ + orrs r0, r1\n\ + strh r0, [r2, 0x4]\n\ +_08044C2E:\n\ + subs r4, 0x1\n\ + adds r5, 0x8\n\ + adds r6, 0x1\n\ + cmp r6, 0x5\n\ + ble _08044B78\n\ +_08044C38:\n\ + ldr r0, _08044C98 @ =TaskDummy\n\ + movs r1, 0x5\n\ + bl CreateTask\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + ldr r2, _08044C9C @ =gTasks\n\ + lsls r3, r4, 2\n\ + adds r1, r3, r4\n\ + lsls r1, 3\n\ + adds r0, r1, r2\n\ + mov r5, sp\n\ + ldrh r5, [r5, 0x8]\n\ + strh r5, [r0, 0x8]\n\ + mov r6, sp\n\ + ldrh r6, [r6, 0x18]\n\ + strh r6, [r0, 0xA]\n\ + movs r6, 0\n\ + adds r0, r2, 0\n\ + adds r0, 0xE\n\ + adds r1, r0\n\ +_08044C62:\n\ + mov r5, sp\n\ + adds r0, r5, r6\n\ + ldrb r0, [r0]\n\ + strh r0, [r1]\n\ + adds r1, 0x2\n\ + adds r6, 0x1\n\ + cmp r6, 0x5\n\ + ble _08044C62\n\ + adds r0, r3, r4\n\ + lsls r0, 3\n\ + adds r0, r2\n\ + ldrh r6, [r5, 0x10]\n\ + strh r6, [r0, 0x1C]\n\ + movs r0, 0x72\n\ + movs r1, 0\n\ + bl PlaySE12WithPanning\n\ + adds r0, r4, 0\n\ + add sp, 0x28\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .align 2, 0\n\ +_08044C98: .4byte TaskDummy\n\ +_08044C9C: .4byte gTasks\n\ + .syntax divided\n"); +} +#endif + +void sub_8044CA0(u8 taskId) +{ + u8 sp[6]; + u8 r9; + u8 r10; + u8 sp8; + s32 i; + + r9 = gTasks[taskId].data[10]; + r10 = gTasks[taskId].data[1]; + sp8 = gTasks[taskId].data[0]; + for (i = 0; i < 6; i++) + sp[i] = gTasks[taskId].data[3 + i]; + + REG_BLDCNT = 0x3F40; + REG_BLDALPHA = 0x10; + gTasks[taskId].data[15] = 16; + for (i = 0; i < 6; i++) + gSprites[sp[i]].oam.objMode = 1; + gSprites[r10].oam.objMode = 1; + if (r9 != 0) + { + for (i = 0; i < 6; i++) + { + if (GetBankSide(sp8) != 0) + { + gSprites[sp[5 - i]].data1 = 7 * i; + gSprites[sp[5 - i]].data3 = 0; + gSprites[sp[5 - i]].data4 = 0; + gSprites[sp[5 - i]].callback = sub_8045110; + } + else + { + gSprites[sp[i]].data1 = 7 * i; + gSprites[sp[i]].data3 = 0; + gSprites[sp[i]].data4 = 0; + gSprites[sp[i]].callback = sub_8045110; + } + } + gSprites[r10].data0 /= 2; + gSprites[r10].data1 = 0; + gSprites[r10].callback = sub_8045048; + SetSubspriteTables(&gSprites[r10], gSubspriteTables_820A6EC); + gTasks[taskId].func = sub_8044E74; + } + else + { + gTasks[taskId].func = sub_8044F70; + } +} + +static void sub_8044E74(u8 taskId) +{ + u16 temp = gTasks[taskId].data[11]++; + + if ((temp & 1) == 0) + { + gTasks[taskId].data[15]--; + if (gTasks[taskId].data[15] < 0) + return; + REG_BLDALPHA = (gTasks[taskId].data[15]) | ((16 - gTasks[taskId].data[15]) << 8); + } + if (gTasks[taskId].data[15] == 0) + gTasks[taskId].func = sub_8044ECC; +} + +static void sub_8044ECC(u8 taskId) +{ + u8 sp[6]; + s32 i; + + gTasks[taskId].data[15]--; + if (gTasks[taskId].data[15] == -1) + { + u8 var = gTasks[taskId].data[1]; + + for (i = 0; i < 6; i++) + sp[i] = gTasks[taskId].data[3 + i]; + DestroySpriteAndFreeResources(&gSprites[var]); + DestroySpriteAndFreeResources(&gSprites[sp[0]]); + for (i = 1; i < 6; i++) + DestroySprite(&gSprites[sp[i]]); + } + else if (gTasks[taskId].data[15] == -3) + { + REG_BLDCNT = 0; + REG_BLDALPHA = 0; + DestroyTask(taskId); + } +} + +static void sub_8044F70(u8 taskId) +{ + u8 sp[6]; + s32 i; + + gTasks[taskId].data[15]--; + // Same as above function except with this check. + if (gTasks[taskId].data[15] >= 0) + { + REG_BLDALPHA = (gTasks[taskId].data[15]) | ((16 - gTasks[taskId].data[15]) << 8); + } + else if (gTasks[taskId].data[15] == -1) + { + u8 var = gTasks[taskId].data[1]; + + for (i = 0; i < 6; i++) + sp[i] = gTasks[taskId].data[3 + i]; + DestroySpriteAndFreeResources(&gSprites[var]); + DestroySpriteAndFreeResources(&gSprites[sp[0]]); + for (i = 1; i < 6; i++) + DestroySprite(&gSprites[sp[i]]); + } + else if (gTasks[taskId].data[15] == -3) + { + REG_BLDCNT = 0; + REG_BLDALPHA = 0; + DestroyTask(taskId); + } +} + +void sub_8045030(struct Sprite *sprite) +{ + if (sprite->pos2.x != 0) + sprite->pos2.x += sprite->data0; +} + +static void sub_8045048(struct Sprite *sprite) +{ + sprite->data1 += 32; + if (sprite->data0 > 0) + sprite->pos2.x += sprite->data1 >> 4; + else + sprite->pos2.x -= sprite->data1 >> 4; + sprite->data1 &= 0xF; +} + +void sub_804507C(struct Sprite *sprite) +{ + u8 r3; + u16 r2; + s8 pan; + + if (sprite->data1 > 0) + { + sprite->data1--; + return; + } + r3 = sprite->data2; + r2 = sprite->data3; + r2 += 56; + sprite->data3 = r2 & 0xFFF0; + if (r3 != 0) + { + sprite->pos2.x += r2 >> 4; + if (sprite->pos2.x > 0) + sprite->pos2.x = 0; + } + else + { + sprite->pos2.x -= r2 >> 4; + if (sprite->pos2.x < 0) + sprite->pos2.x = 0; + } + if (sprite->pos2.x == 0) + { + pan = 63; + if (r3 != 0) + pan = -64; + if (sprite->data7 != 0) + PlaySE2WithPanning(SE_TB_KARA, pan); + else + PlaySE1WithPanning(SE_TB_KON, pan); + sprite->callback = SpriteCallbackDummy; + } +} + +static void sub_8045110(struct Sprite *sprite) +{ + u8 r0; + u16 r2; + + if (sprite->data1 > 0) + { + sprite->data1--; + return; + } + r0 = sprite->data2; + r2 = sprite->data3; + r2 += 56; + sprite->data3 = r2 & 0xFFF0; + if (r0 != 0) + sprite->pos2.x += r2 >> 4; + else + sprite->pos2.x -= r2 >> 4; + if (sprite->pos2.x + sprite->pos1.x > 248 + || sprite->pos2.x + sprite->pos1.x < -8) + { + sprite->invisible = TRUE; + sprite->callback = SpriteCallbackDummy; + } +} + +void sub_8045180(struct Sprite *sprite) +{ + u8 spriteId = sprite->data0; + + sprite->pos2.x = gSprites[spriteId].pos2.x; + sprite->pos2.y = gSprites[spriteId].pos2.y; +} + +static void sub_80451A0(u8 a, struct Pokemon *pkmn) +{ + u8 nickname[POKEMON_NAME_LENGTH]; + u8 gender; + u16 species; + u8 language; + u8 *ptr; + s32 i; + s32 _7; + u8 *const *r1; + + StringCopy(gDisplayedStringBattle, gUnknown_0820A8B0); + GetMonData(pkmn, MON_DATA_NICKNAME, nickname); + StringGetEnd10(nickname); + ptr = StringCopy(gDisplayedStringBattle + 3, nickname); + ptr[0] = EXT_CTRL_CODE_BEGIN; + ptr[1] = 3; + ptr[2] = 2; + ptr[3] = EXT_CTRL_CODE_BEGIN; + ptr[4] = 1; + ptr += 5; + gender = GetMonGender(pkmn); + species = GetMonData(pkmn, MON_DATA_SPECIES); + language = GetMonData(pkmn, MON_DATA_LANGUAGE); + if (sub_8040D3C(species, nickname, language)) + gender = 100; + switch (gender) + { + default: + ptr[0] = 0xB; + ptr[1] = EOS; + ptr += 1; + break; + case MON_MALE: + ptr[0] = 0xB; + ptr[1] = CHAR_MALE; + ptr[2] = EOS; + ptr += 2; + break; + case MON_FEMALE: + ptr[0] = 0xA; + ptr[1] = CHAR_FEMALE; + ptr[2] = EOS; + ptr += 2; + break; + } + ptr[0] = EXT_CTRL_CODE_BEGIN; + ptr[1] = 0x13; + ptr[2] = 0x37; + ptr[3] = EOS; + ptr = (u8 *)0x02000520 + GetBankIdentity(gSprites[a].data6) * 0x180; + sub_80034D4(ptr, gDisplayedStringBattle); + + i = 0; + _7 = 7; + if (GetMonData(pkmn, MON_DATA_LANGUAGE) == 1 + && GetMonData(pkmn, MON_DATA_IS_EGG) == 0) + { + u8 *p = gDisplayedStringBattle; + + while (*p != EOS) + { + if (*p == EXT_CTRL_CODE_BEGIN) + { + p += GetExtCtrlCodeLength(p[1]) + 1; + } + else + { + u8 r0; + + if ((*p >= 0x37 && *p <= 0x4A) || (*p >= 0x87 && *p <= 0x9A)) + r0 = 0x2C; + else if ((*p >= 0x4B && *p <= 0x4F) || (*p >= 0x9B && *p <= 0x9F)) + r0 = 0x2D; + else + r0 = 0x2B; + + CpuCopy32(sub_8043CDC(r0), ptr + 0x40 * i, 32); + i++; + p++; + } + } + } + + for (; i < _7; i++) + CpuCopy32(sub_8043CDC(0x2B), ptr + 64 * i, 32); + + if (GetBankSide(gSprites[a].data6) == 0 && !IsDoubleBattle()) + { + r1 = (u8 *const *)gUnknown_0820A8B4; + for (i = 0; i < _7; i++) + { + u8 *r4 = r1[i]; + + r4 += gSprites[a].oam.tileNum * 32; + CpuCopy32(ptr, r4, 32); + ptr += 32; + + r4 += 0x100; + CpuCopy32(ptr, r4, 32); + ptr += 32; + } + } + else + { + if (GetBankSide(gSprites[a].data6) == 0) + r1 = (u8 *const *)gUnknown_0820A904; + else + r1 = (u8 *const *)gUnknown_0820A8DC; + for (i = 0; i < _7; i++) + { + u8 *r4 = r1[i]; + + r4 += gSprites[a].oam.tileNum * 32; + CpuCopy32(ptr, r4, 32); + ptr += 32; + + r4 += 0x100; + CpuCopy32(ptr, r4, 32); + ptr += 32; + } + } +} + +static void sub_8045458(u8 a, u8 b) +{ + u8 r4; + + if (gBattleTypeFlags & 0x200) + return; + if (gBattleTypeFlags & 8) + return; + + r4 = gSprites[a].data6; + if (GetBankSide(r4) != 0) + { + u16 species = GetMonData(&gEnemyParty[gBattlePartyID[r4]], MON_DATA_SPECIES); + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), 1) != 0) + { + r4 = gSprites[a].data5; + if (b != 0) + CpuCopy32(sub_8043CDC(0x46), (void *)(OBJ_VRAM0 + (gSprites[r4].oam.tileNum + 8) * 32), 32); + else + CpuFill32(0, (void *)(OBJ_VRAM0 + (gSprites[r4].oam.tileNum + 8) * 32), 32); + } + } +} + +static void draw_status_ailment_maybe(u8 a) +{ + s32 r4; + s32 r4_2; + u8 r7; + u8 r10; + s16 r8; + const u8 *r6; + u8 r0; + s32 i; + + r7 = gSprites[a].data6; + r10 = gSprites[a].data5; + if (GetBankSide(r7) == 0) + { + r4 = GetMonData(&gPlayerParty[gBattlePartyID[r7]], MON_DATA_STATUS); + if (!IsDoubleBattle()) + r8 = 0x1A; + else + r8 = 0x12; + } + else + { + r4 = GetMonData(&gEnemyParty[gBattlePartyID[r7]], MON_DATA_STATUS); + r8 = 0x11; + } + if (r4 & 7) + { + r6 = sub_8043CDC(sub_80457E8(0x1B, r7)); + r0 = 2; + } + else if (r4 & 0x88) + { + r6 = sub_8043CDC(sub_80457E8(0x15, r7)); + r0 = 0; + } + else if (r4 & 0x10) + { + r6 = sub_8043CDC(sub_80457E8(0x21, r7)); + r0 = 4; + } + else if (r4 & 0x20) + { + r6 = sub_8043CDC(sub_80457E8(0x1E, r7)); + r0 = 3; + } + else if (r4 & 0x40) + { + r6 = sub_8043CDC(sub_80457E8(0x18, r7)); + r0 = 1; + } + else + { + r6 = sub_8043CDC(0x27); + + for (i = 0; i < 3; i++) + CpuCopy32(r6, (void *)(OBJ_VRAM0 + (gSprites[a].oam.tileNum + r8 + i) * 32), 32); + + if (!ewram17800[r7].unk0_4) + CpuCopy32(sub_8043CDC(1), (void *)(OBJ_VRAM0 + gSprites[r10].oam.tileNum * 32), 64); + + sub_8045458(a, 1); + return; + } + + r4_2 = gSprites[a].oam.paletteNum * 16; + r4_2 += r7 + 12; + // I don't like writing the array index like this, but I can't get it to match otherwise. + FillPalette(r0[gBattleInterfaceStatusIcons_DynPal], r4_2 + 0x100, 2); + CpuCopy16(gPlttBufferUnfaded + 0x100 + r4_2, (void *)(OBJ_PLTT + r4_2 * 2), 2); + CpuCopy32(r6, (void *)(OBJ_VRAM0 + (gSprites[a].oam.tileNum + r8) * 32), 96); + if (IsDoubleBattle() == TRUE || GetBankSide(r7) == TRUE) + { + if (!ewram17800[r7].unk0_4) + { + CpuCopy32(sub_8043CDC(0), (void *)(OBJ_VRAM0 + gSprites[r10].oam.tileNum * 32), 32); + CpuCopy32(sub_8043CDC(0x41), (void *)(OBJ_VRAM0 + (gSprites[r10].oam.tileNum + 1) * 32), 32); + } + } + sub_8045458(a, 0); +} + +static u8 sub_80457E8(u8 a, u8 b) +{ + u8 ret = a; + + switch (a) + { + case 21: + if (b == 0) + ret = 21; + else if (b == 1) + ret = 71; + else if (b == 2) + ret = 86; + else + ret = 101; + break; + case 24: + if (b == 0) + ret = 24; + else if (b == 1) + ret = 74; + else if (b == 2) + ret = 89; + else + ret = 104; + break; + case 27: + if (b == 0) + ret = 27; + else if (b == 1) + ret = 77; + else if (b == 2) + ret = 92; + else + ret = 107; + break; + case 30: + if (b == 0) + ret = 30; + else if (b == 1) + ret = 80; + else if (b == 2) + ret = 95; + else + ret = 110; + break; + case 33: + if (b == 0) + ret = 33; + else if (b == 1) + ret = 83; + else if (b == 2) + ret = 98; + else + ret = 113; + break; + } + return ret; +} + +static void sub_80458B0(u8 a) +{ + u8 *r6; + u8 r8; + u8 i; + s32 r7; + u8 *addr; + + r6 = (u8 *)0x02000520 + GetBankIdentity(gSprites[a].data6) * 0x180; + r8 = 7; + sub_80034D4(r6, BattleText_SafariBalls); + for (i = 0; i < r8; i++) + CpuCopy32(sub_8043CDC(0x2B), r6 + i * 64, 32); + for (r7 = 3; r7 < 3 + r8; r7++) + { + addr = (void *)(OBJ_VRAM0 + (gSprites[a].oam.tileNum + MACRO1(r7)) * 32); + CpuCopy32(r6, addr, 32); + r6 += 32; + + addr = (void *)(OBJ_VRAM0 + (8 + gSprites[a].oam.tileNum + MACRO1(r7)) * 32); + CpuCopy32(r6, addr, 32); + r6 += 32; + } + +} + +static void sub_8045998(u8 a) +{ + u8 *r7; + u8 status; + s32 r6; + s32 i; + + r7 = StringCopy(gDisplayedStringBattle, BattleText_SafariBallsLeft); + r7 = sub_8003504(r7, gNumSafariBalls, 10, 1); + StringAppend(r7, BattleText_HighlightRed); + status = GetBankIdentity(gSprites[a].data6); + r7 = (u8 *)0x02000520 + status * 0x180; + r6 = 5; + sub_80034D4(r7, gDisplayedStringBattle); + r7 = (u8 *)0x02000520 + status * 0x180 + 32; + for (i = 6; i < 6 + r6; i++) + { + CpuCopy32(r7, (void *)(OBJ_VRAM0 + (gSprites[a].oam.tileNum + 0x18 + MACRO1(i)) * 32), 32); + r7 += 64; + } +} + +void sub_8045A5C(u8 a, struct Pokemon *pkmn, u8 c) +{ + u8 r10; + u32 maxhp; + u32 currhp; + + r10 = gSprites[a].data6; + if (GetBankSide(r10) == 0) + { + if (c == 3 || c == 0) + sub_8043FC0(a, GetMonData(pkmn, MON_DATA_LEVEL)); + if (c == 1 || c == 0) + sub_80440EC(a, GetMonData(pkmn, MON_DATA_HP), 0); + if (c == 2 || c == 0) + sub_80440EC(a, GetMonData(pkmn, MON_DATA_MAX_HP), 1); + if (c == 5 || c == 0) + { + load_gfxc_health_bar(0); + maxhp = GetMonData(pkmn, MON_DATA_MAX_HP); + currhp = GetMonData(pkmn, MON_DATA_HP); + sub_8043D84(r10, a, maxhp, currhp, 0); + sub_8045C78(r10, a, 0, 0); + } + if (!IsDoubleBattle() && (c == 6 || c == 0)) + { + u16 species; + u8 level; + u32 exp; + u32 var1; + u32 var2; + u32 currLevelExp; + + load_gfxc_health_bar(3); + species = GetMonData(pkmn, MON_DATA_SPECIES); + level = GetMonData(pkmn, MON_DATA_LEVEL); + exp = GetMonData(pkmn, MON_DATA_EXP); + currLevelExp = gExperienceTables[gBaseStats[species].growthRate][level]; + var1 = exp - currLevelExp; + var2 = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLevelExp; + sub_8043D84(r10, a, var2, var1, 0); + sub_8045C78(r10, a, 1, 0); + } + if (c == 4 || c == 0) + sub_80451A0(a, pkmn); + if (c == 9 || c == 0) + draw_status_ailment_maybe(a); + if (c == 10) + sub_80458B0(a); + if (c == 10 || c == 11) + sub_8045998(a); + } + else + { + if (c == 3 || c == 0) + sub_8043FC0(a, GetMonData(pkmn, MON_DATA_LEVEL)); + if (c == 5 || c == 0) + { + load_gfxc_health_bar(0); + maxhp = GetMonData(pkmn, MON_DATA_MAX_HP); + currhp = GetMonData(pkmn, MON_DATA_HP); + sub_8043D84(r10, a, maxhp, currhp, 0); + sub_8045C78(r10, a, 0, 0); + } + if (c == 4 || c == 0) + sub_80451A0(a, pkmn); + if (c == 9 || c == 0) + draw_status_ailment_maybe(a); + } +} + +s32 sub_8045C78(u8 a, u8 unused1, u8 c, u8 unused2) +{ + s32 r6; + + if (c == 0) + { + r6 = sub_8045F58(ewram17850[a].unk4, ewram17850[a].unk8, ewram17850[a].unkC, &ewram17850[a].unk10, 6, 1); + } + else + { + u16 r5; + s32 r8; + + r5 = GetScaledExpFraction(ewram17850[a].unk8, ewram17850[a].unkC, ewram17850[a].unk4, 8); + if (r5 == 0) + r5 = 1; + r8 = ewram17850[a].unkC; + r5 = ABS(r8 / r5); + r6 = sub_8045F58(ewram17850[a].unk4, ewram17850[a].unk8, r8, &ewram17850[a].unk10, 8, r5); + } + if (c == 1 || (c == 0 && (!ewram17800[a].unk0_4))) + sub_8045D58(a, c); + if (r6 == -1) + ewram17850[a].unk10 = 0; + return r6; +} + +static void sub_8045D58(u8 a, u8 b) +{ + u8 sp8[7]; + u8 r0; + u8 r8; + u8 i; + + switch (b) + { + case 0: + r0 = sub_804602C(ewram17850[a].unk4, ewram17850[a].unk8, ewram17850[a].unkC, &ewram17850[a].unk10, sp8, 6); + r8 = 3; + if (r0 <= 0x18) + { + r8 = 0x38; + if (r0 > 9) + r8 = 0x2F; + } + for (i = 0; i < 6; i++) + { + u8 r4 = gSprites[ewram17850[a].unk0].data5; + if (i < 2) + CpuCopy32(sub_8043CDC(r8) + sp8[i] * 32, (void *)(OBJ_VRAM0 + (gSprites[r4].oam.tileNum + 2 + i) * 32), 32); + else + CpuCopy32(sub_8043CDC(r8) + sp8[i] * 32, (void *)(OBJ_VRAM0 + 64 + (i + gSprites[r4].oam.tileNum) * 32), 32); + } + break; + case 1: + sub_804602C(ewram17850[a].unk4, ewram17850[a].unk8, ewram17850[a].unkC, &ewram17850[a].unk10, sp8, 8); + r0 = GetMonData(&gPlayerParty[gBattlePartyID[a]], MON_DATA_LEVEL); + if (r0 == 100) + { + for (i = 0; i < 8; i++) + sp8[i] = 0; + } + for (i = 0; i < 8; i++) + { + if (i < 4) + CpuCopy32(sub_8043CDC(0xC) + sp8[i] * 32, (void *)(OBJ_VRAM0 + (gSprites[ewram17850[a].unk0].oam.tileNum + 0x24 + i) * 32), 32); + else + CpuCopy32(sub_8043CDC(0xC) + sp8[i] * 32, (void *)(OBJ_VRAM0 + 0xB80 + (i + gSprites[ewram17850[a].unk0].oam.tileNum) * 32), 32); + } + break; + } +} + +static int sub_8045F58(s32 a, s32 b, int c, int *d, u8 e, u16 f) +{ + u8 r2 = e << 3; + int r6; + int ret; + + if (*d == -32768) + { + if (a < r2) + *d = b << 8; + else + *d = b; + } + //_08045F8A + b -= c; + if (b < 0) + b = 0; + else if (b > a) + b = a; + if (a < r2) + { + int var = *d >> 8; + + r6 = *d; + if (b == var && (r6 & 0xFF) == 0) + return -1; + } + else + { + r6 = *d; + if (b == r6) + return -1; + } + //_08045FC4 + if (a < r2) + { + int r0 = (a << 8) / r2; + + if (c < 0) + { + *d = r6 + r0; + ret = *d >> 8; + if (ret >= b) + { + *d = b << 8; + ret = b; + } + } + //_08045FE2 + else + { + *d = r6 - r0; + ret = *d >> 8; + if ((*d & 0xFF) > 0) + ret++; + if (ret <= b) + { + *d = b << 8; + ret = b; + } + } + } + else + { + //_08045FFE + if (c < 0) + { + *d += f; + if (*d > b) + *d = b; + ret = *d; + } + //_08046010 + else + { + *d -= f; + if (*d < b) + *d = b; + ret = *d; + } + } + return ret; +} + +static u8 sub_804602C(int a, int b, int c, int *d, u8 *e, u8 f) +{ + s32 r5 = b - c; + u8 r3; + u8 i; + u8 r2; + + if (r5 < 0) + r5 = 0; + else if (r5 > a) + r5 = a; + r3 = f << 3; + for (i = 0; i < f; i++) + e[i] = 0; + if (a < r3) + r2 = *d * r3 / a >> 8; + else + r2 = *d * r3 / a; + r3 = r2; + if (r3 == 0 && r5 > 0) + { + e[0] = 1; + r3 = 1; + } + else + { + for (i = 0; i < f; i++) + { + if (r2 >= 8) + { + e[i] = 8; + } + else + { + e[i] = r2; + break; + } + r2 -= 8; + } + } + return r3; +} + +s16 sub_80460C8(struct BattleInterfaceStruct1 *a, int *b, void *c, int d) +{ + u16 r7; + s16 r1; + + r7 = sub_8045F58(a->unk0, a->unk4, a->unk8, b, 6, 1); + sub_8046128(a, b, c); + if (a->unk0 < 0x30) + r1 = *b >> 8; + else + r1 = *b; + do_nothing(a->unk0, r1, d); + return r7; +} + +static void sub_8046128(struct BattleInterfaceStruct1 *a, int *b, void *c) +{ + u8 sp8[6]; + u16 sp10[6]; + u8 i; + + sub_804602C(a->unk0, a->unk4, a->unk8, b, (u8 *)sp8, 6); + for (i = 0; i < 6; i++) + sp10[i] = (a->unkC_0 << 12) | (a->unk10 + sp8[i]); + CpuCopy16(sp10, c, sizeof(sp10)); +} + +static u8 GetScaledExpFraction(int a, int b, int c, u8 d) +{ + u8 r7 = d * 8; + int r5 = a - b; + s8 r4; + s8 r0; + s32 result; + + if (r5 < 0) + r5 = 0; + else if (r5 > c) + r5 = c; + + r4 = a * r7 / c; + r0 = r5 * r7 / c; + result = r4 - r0; + return ABS(result); +} + +u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale) +{ + u8 result = hp * scale / maxhp; + + if (result == 0 && hp > 0) + return 1; + return result; +} + +u8 GetHPBarLevel(s16 hp, s16 maxhp) +{ + int result; + + if (hp == maxhp) + result = 4; + else + { + u8 fraction = GetScaledHPFraction(hp, maxhp, 48); + if (fraction > 24) + result = 3; + else if (fraction > 9) + result = 2; + else if (fraction > 0) + result = 1; + else + result = 0; + } + return result; +} diff --git a/src/battle/battle_message.c b/src/battle/battle_message.c new file mode 100644 index 000000000..a3cc320ad --- /dev/null +++ b/src/battle/battle_message.c @@ -0,0 +1,959 @@ +#include "global.h" +#include "battle_message.h" +#include "battle.h" +#include "item.h" +#include "items.h" +#include "pokemon.h" +#include "data2.h" +#include "text.h" +#include "string_util.h" +#include "link.h" +#include "battle_setup.h" +#include "battle_tower.h" +#include "flags.h" + +#define BATTLESTRING_TO_SUB 12 +#define BATTLESTRINGS_NO 351 +#define BATTLESTRINGS_MAX BATTLESTRINGS_NO + BATTLESTRING_TO_SUB + +extern const u8* const gBattleStringsTable[BATTLESTRINGS_NO]; + +extern u16 gLastUsedItem; +extern u8 gLastUsedAbility; +extern u8 gActiveBank; +extern u8 gBankAttacker; +extern u8 gBankTarget; +extern u8 gStringBank; +extern u8 gEffectBank; +extern u8 gAbilitiesPerBank[4]; +extern u8 gBattleTextBuff1[]; +extern u8 gBattleTextBuff2[]; +extern u8 gBattleTextBuff3[]; +extern u8 gStringVar1[]; +extern u8 gStringVar2[]; +extern u8 gStringVar3[]; +extern u16 gBattleTypeFlags; +extern u16 gTrainerBattleOpponent; +extern u8 gDisplayedStringBattle[]; +extern u8 gStringVar1[]; +extern u8 gStringVar2[]; +extern u8 gStringVar3[]; +extern u16 gBattlePartyID[4]; +extern struct BattleEnigmaBerry gEnigmaBerries[4]; +extern u8 gBattleBufferA[4][0x200]; + +extern const u8 gUnknown_084005DB[]; +extern const u8 gUnknown_084005C7[]; +extern const u8 gUnknown_084005AA[]; +extern const u8 gUnknown_08400568[]; +extern const u8 gUnknown_08400590[]; +extern const u8 gUnknown_0840057B[]; +extern const u8 gUnknown_08400555[]; +extern const u8 gUnknown_084006F1[]; +extern const u8 gUnknown_084006A4[]; +extern const u8 gUnknown_0840069C[]; +extern const u8 gUnknown_0840065C[]; +extern const u8 gUnknown_08400645[]; +extern const u8 gUnknown_08400608[]; +extern const u8 gUnknown_08400635[]; +extern const u8 gUnknown_084005F5[]; +extern const u8 gUnknown_08400709[]; +extern const u8 gUnknown_08400727[]; +extern const u8 gUnknown_08400736[]; +extern const u8 gUnknown_08400749[]; +extern const u8 gUnknown_08400781[]; +extern const u8 gUnknown_08400771[]; +extern const u8 gUnknown_0840075E[]; +extern const u8 gUnknown_084006B3[]; +extern const u8 gUnknown_084006BB[]; +extern const u8 gUnknown_084006C6[]; +extern const u8 gUnknown_084006D5[]; +extern const u8 gUnknown_0840068C[]; +extern const u8 gUnknown_0840067C[]; +extern const u8 gUnknown_08400622[]; +extern const u8 gUnknown_084007BD[]; +extern const u8 gUnknown_083FFEFC[]; +extern const u8 gUnknown_083FFFF7[]; +extern const u8 gUnknown_083FFFEA[]; +extern const u8 gUnknown_083FFF6A[]; +extern const u8 gUnknown_083FFF99[]; +extern const u8 gUnknown_083FFFCB[]; +extern const u8 gUnknown_083FFF56[]; +extern const u8 gUnknown_083FFF81[]; +extern const u8 gUnknown_083FFFB3[]; +extern const u8 gUnknown_08400A78[]; +extern const u8 gUnknown_08400A85[]; +extern const u8 gUnknown_08400797[]; +extern const u8 gUnknown_08400791[]; +extern const u8 gUnknown_084007B7[]; +extern const u8 gUnknown_084007B2[]; +extern const u8 gUnknown_0840079C[]; +extern const u8 gUnknown_084007A1[]; +extern const u8 gUnknown_084007A7[]; +extern const u8 gUnknown_084007AC[]; +extern const u8 gUnknown_084009ED[]; +extern const u8 gUnknown_084009F7[]; +extern const u8 gUnknown_084007C8[]; +extern const u8 gUnknown_084007CA[]; +extern const u8 gUnknown_084007CC[]; +extern const u8 gUnknown_084007CE[]; +extern const u8 gUnknown_084007D0[]; +extern const u8 gUnknown_08400E5E[]; +extern const u8 gUnknown_08400E62[]; + +extern const u16 gUnknown_084016BC[]; // a table of moves + +extern const u8* const gUnknown_08401674[]; // table of pointers to 'a -TYPE' strings +extern const u8* const gUnknown_08400F58[]; // table of pointers to stat strings +extern const u8* const gUnknown_08400F78[]; // table of pointers to flavour strings + +struct StatusFlagString +{ + u8* flag; + u8* ptr; +}; + +extern const struct StatusFlagString gUnknown_081FA6D4[7]; // status flag/text +extern const u8 gUnknown_084017A8[8]; // empty flags + +extern struct StringInfoBattle* gSelectedOrderFromParty; +#define gStringInfo gSelectedOrderFromParty + +void sub_8121D1C(u8* textBuff); +void sub_8121D74(u8* textBuff); +void StrCpyDecodeBattleTextBuff(u8* src, u8* dst); + +u8 GetBankSide(u8 bank); +s32 sub_803FC34(u16); +void get_trainer_name(u8* dst); +u8 get_trainer_class_name_index(void); +u8 sub_8135FD8(void); +u8 GetMultiplayerId(void); +u8 GetBankByPlayerAI(u8 ID); +u8 GetBankSide(u8 bank); +u8 GetBankIdentity(u8 bank); +#ifdef GERMAN +extern u8 *de_sub_804110C(); +#endif + +void BufferStringBattle(u16 stringID) +{ + int i; + const u8* stringPtr = NULL; + + gStringInfo = (struct StringInfoBattle*)(&gBattleBufferA[gActiveBank][4]); + gLastUsedItem = gStringInfo->lastItem; + gLastUsedAbility = gStringInfo->lastAbility; + BATTLE_STRUCT->scriptingActive = gStringInfo->scrActive; + BATTLE_STRUCT->unk1605E = gStringInfo->unk1605E; + BATTLE_STRUCT->hpScale = gStringInfo->hpScale; + gStringBank = gStringInfo->StringBank; + BATTLE_STRUCT->stringMoveType = gStringInfo->moveType; + for (i = 0; i < 4; i++) + { + gAbilitiesPerBank[i] = gStringInfo->abilities[i]; + } + for (i = 0; i < 0x10; i++) + { + gBattleTextBuff1[i] = gStringInfo->textBuffs[0][i]; + gBattleTextBuff2[i] = gStringInfo->textBuffs[1][i]; + gBattleTextBuff3[i] = gStringInfo->textBuffs[2][i]; + } + switch (stringID) + { + case 0: // first battle msg + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + stringPtr = gUnknown_084005DB; + else + stringPtr = gUnknown_084005C7; + } + else + { + stringPtr = gUnknown_084005AA; +#ifdef GERMAN + stringPtr = de_sub_804110C(0xFFFF, stringPtr); +#endif + } + } + else + { + if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) + stringPtr = gUnknown_08400568; + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) // interesting, looks like they had something planned for wild double battles + stringPtr = gUnknown_08400590; + else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) + stringPtr = gUnknown_0840057B; + else + stringPtr = gUnknown_08400555; + } + break; + case 1: // poke first send-out + if (GetBankSide(gActiveBank) == 0) + { + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + stringPtr = gUnknown_084006F1; + else + stringPtr = gUnknown_084006A4; + } + else + stringPtr = gUnknown_0840069C; + } + else + { + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + stringPtr = gUnknown_0840065C; + else if (gBattleTypeFlags & BATTLE_TYPE_LINK) + stringPtr = gUnknown_08400645; + else + { + stringPtr = gUnknown_08400608; +#ifdef GERMAN + stringPtr = de_sub_804110C(0xFFFF, stringPtr); +#endif + } + } + else if (gBattleTypeFlags & BATTLE_TYPE_LINK) + stringPtr = gUnknown_08400635; + else + { + stringPtr = gUnknown_084005F5; +#ifdef GERMAN + stringPtr = de_sub_804110C(0xFFFF, stringPtr); +#endif + } + } + break; + case 2: // sending poke to ball msg + if (GetBankSide(gActiveBank) == 0) + { + if (BATTLE_STRUCT->hpScale == 0) + stringPtr = gUnknown_08400709; + else if (BATTLE_STRUCT->hpScale == 1 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + stringPtr = gUnknown_08400727; + else if (BATTLE_STRUCT->hpScale == 2) + stringPtr = gUnknown_08400736; + else + stringPtr = gUnknown_08400749; + } + else + { + if (gTrainerBattleOpponent == 0x800) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + stringPtr = gUnknown_08400781; + else + stringPtr = gUnknown_08400771; + } + else + { + stringPtr = gUnknown_0840075E; +#ifdef GERMAN + stringPtr = de_sub_804110C(0xFFFF, stringPtr); +#endif + } + } + break; + case 3: // switch-in msg + if (GetBankSide(BATTLE_STRUCT->scriptingActive) == 0) + { + if (BATTLE_STRUCT->hpScale == 0 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + stringPtr = gUnknown_084006B3; + else if (BATTLE_STRUCT->hpScale == 1) + stringPtr = gUnknown_084006BB; + else if (BATTLE_STRUCT->hpScale == 2) + stringPtr = gUnknown_084006C6; + else + stringPtr = gUnknown_084006D5; + } + else + { + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + stringPtr = gUnknown_0840068C; + else + stringPtr = gUnknown_0840067C; + } + else + { + stringPtr = gUnknown_08400622; +#ifdef GERMAN + stringPtr = de_sub_804110C(0xFFFF, stringPtr); +#endif + } + } + break; + case 4: // pokemon used a move msg + sub_8121D1C(gBattleTextBuff1); + if (gStringInfo->currentMove > 0x162) + StringCopy(gBattleTextBuff2, gUnknown_08401674[BATTLE_STRUCT->stringMoveType]); + else + StringCopy(gBattleTextBuff2, gMoveNames[gStringInfo->currentMove]); + sub_8121D74(gBattleTextBuff2); + stringPtr = gUnknown_084007BD; + break; + case 5: // battle end + if (gBattleTextBuff1[0] & 0x80) + { + gBattleTextBuff1[0] &= ~(0x80); + if (GetBankSide(gActiveBank) == 1 && gBattleTextBuff1[0] != 3) + gBattleTextBuff1[0] ^= 3; + if (gBattleTextBuff1[0] == BATTLE_LOST || gBattleTextBuff1[0] == BATTLE_DREW) + stringPtr = gUnknown_083FFEFC; + else + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + stringPtr = gUnknown_083FFFF7; + else + stringPtr = gUnknown_083FFFEA; + } + } + else + { + if (GetBankSide(gActiveBank) == 1 && gBattleTextBuff1[0] != 3) + gBattleTextBuff1[0] ^= 3; + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + switch (gBattleTextBuff1[0]) + { + case BATTLE_WON: + stringPtr = gUnknown_083FFF6A; + break; + case BATTLE_LOST: + stringPtr = gUnknown_083FFF99; + break; + case BATTLE_DREW: + stringPtr = gUnknown_083FFFCB; + break; + } + } + else + { + switch (gBattleTextBuff1[0]) + { + case BATTLE_WON: + stringPtr = gUnknown_083FFF56; + break; + case BATTLE_LOST: + stringPtr = gUnknown_083FFF81; + break; + case BATTLE_DREW: + stringPtr = gUnknown_083FFFB3; + break; + } + } + } + break; + default: // load a string from the table + if (stringID >= BATTLESTRINGS_MAX) + { + gDisplayedStringBattle[0] = EOS; + return; + } + else + { + stringPtr = gBattleStringsTable[stringID - BATTLESTRING_TO_SUB]; +#ifdef GERMAN + stringPtr = de_sub_804110C(stringID, stringPtr); +#endif + } + break; + } + StrCpyDecodeToDisplayedStringBattle(stringPtr); +} + +u32 StrCpyDecodeToDisplayedStringBattle(const u8* src) +{ + StrCpyDecodeBattle(src, gDisplayedStringBattle); +} + +const u8* AppendStatusString(u8* src) +{ + u32 i; + u8 status[8]; + u32 flag1, flag2; + u8* statusPtr; + + memcpy(status, gUnknown_084017A8, 8); + + statusPtr = status; + for (i = 0; i < sizeof(struct StatusFlagString); i++) + { + if (*src == EOS) + break; + *statusPtr = *src; + src++; + statusPtr++; + } + flag1 = *(u32*)(&status[0]); + flag2 = *(u32*)(&status[4]); + for (i = 0; i < 7; i++) + { + if (flag1 == *(u32*)(&gUnknown_081FA6D4[i].flag[0]) && flag2 == *(u32*)(&gUnknown_081FA6D4[i].flag[4])) + return gUnknown_081FA6D4[i].ptr; + } + return NULL; +} + +#ifdef GERMAN +extern u8 *de_sub_8073174(u8 *, const u8 *); +extern u8 *de_sub_8041024(s32, u32); +#endif + +#ifdef ENGLISH +#define HANDLE_NICKNAME_STRING_CASE(bank, monIndex) \ + if (GetBankSide(bank) != 0) \ + { \ + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) \ + toCpy = gUnknown_08400797; \ + else \ + toCpy = gUnknown_08400791; \ + while (*toCpy != EOS) \ + { \ + dst[dstID] = *toCpy; \ + dstID++; \ + toCpy++; \ + } \ + GetMonData(&gEnemyParty[monIndex], MON_DATA_NICKNAME, text); \ + } \ + else \ + { \ + GetMonData(&gPlayerParty[monIndex], MON_DATA_NICKNAME, text); \ + } \ + StringGetEnd10(text); \ + toCpy = text; +#else +#define HANDLE_NICKNAME_STRING_CASE(bank, monIndex) \ + if (GetBankSide(bank) != 0) \ + { \ + GetMonData(&gEnemyParty[monIndex], MON_DATA_NICKNAME, text); \ + StringGetEnd10(text); \ + toCpy = text; \ + while (*toCpy != EOS) \ + { \ + dst[dstID] = *toCpy; \ + dstID++; \ + toCpy++; \ + } \ + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) \ + toCpy = gUnknown_08400797; \ + else \ + toCpy = gUnknown_08400791; \ + } \ + else \ + { \ + GetMonData(&gPlayerParty[monIndex], MON_DATA_NICKNAME, text); \ + StringGetEnd10(text); \ + toCpy = text; \ + } +#endif + +u32 StrCpyDecodeBattle(const u8* src, u8* dst) +{ + u32 dstID = 0; // if they used dstID, why not use srcID as well? + const u8* toCpy = NULL; + u8 text[12]; + u8 multiplayerID = GetMultiplayerId(); + + while (*src != EOS) + { + if (*src == 0xFD) + { + src++; + switch (*src) + { + case 0: + if (gBattleTextBuff1[0] == 0xFD) + { + StrCpyDecodeBattleTextBuff(gBattleTextBuff1, gStringVar1); + toCpy = gStringVar1; + } + else + { + toCpy = AppendStatusString(gBattleTextBuff1); + if (toCpy == 0) + toCpy = gBattleTextBuff1; + } + break; + case 1: + if (gBattleTextBuff2[0] == 0xFD) + { + StrCpyDecodeBattleTextBuff(gBattleTextBuff2, gStringVar2); + toCpy = gStringVar2; + } + else + toCpy = gBattleTextBuff2; + break; + case 42: + if (gBattleTextBuff3[0] == 0xFD) + { + StrCpyDecodeBattleTextBuff(gBattleTextBuff3, gStringVar3); + toCpy = gStringVar3; + } + else + toCpy = gBattleTextBuff3; + break; + case 2: // first player poke name + GetMonData(&gPlayerParty[gBattlePartyID[GetBankByPlayerAI(0)]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; + case 3: // first enemy poke name + GetMonData(&gEnemyParty[gBattlePartyID[GetBankByPlayerAI(1)]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; + case 4: // second player poke name + GetMonData(&gPlayerParty[gBattlePartyID[GetBankByPlayerAI(2)]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; + case 5: // second enemy poke name + GetMonData(&gEnemyParty[gBattlePartyID[GetBankByPlayerAI(3)]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; + case 6: // link first player poke name + GetMonData(&gPlayerParty[gBattlePartyID[gLinkPlayers[multiplayerID].lp_field_18]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; + case 7: // link first opponent poke name + GetMonData(&gEnemyParty[gBattlePartyID[gLinkPlayers[multiplayerID].lp_field_18 ^ 1]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; + case 8: // link second player poke name + GetMonData(&gPlayerParty[gBattlePartyID[gLinkPlayers[multiplayerID].lp_field_18 ^ 2]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; + case 9: // link second opponent poke name + GetMonData(&gEnemyParty[gBattlePartyID[gLinkPlayers[multiplayerID].lp_field_18 ^ 3]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; + case 10: // attacker name with prefix, only bank 0/1 + HANDLE_NICKNAME_STRING_CASE(gBankAttacker, gBattlePartyID[GetBankByPlayerAI(GetBankIdentity(gBankAttacker) & 1)]) + break; + case 11: // attacker partner name, only bank 0/1 + if (GetBankSide(gBankAttacker) == 0) + GetMonData(&gPlayerParty[gBattlePartyID[GetBankByPlayerAI(GetBankIdentity(gBankAttacker) & 1) + 2]], MON_DATA_NICKNAME, text); + else + GetMonData(&gEnemyParty[gBattlePartyID[GetBankByPlayerAI(GetBankIdentity(gBankAttacker) & 1) + 2]], MON_DATA_NICKNAME, text); + + StringGetEnd10(text); + toCpy = text; + break; + case 12: // attacker name with prefix + HANDLE_NICKNAME_STRING_CASE(gBankAttacker, gBattlePartyID[gBankAttacker]) + break; + case 13: // target name with prefix + HANDLE_NICKNAME_STRING_CASE(gBankTarget, gBattlePartyID[gBankTarget]) + break; + case 14: // effect bank name with prefix + HANDLE_NICKNAME_STRING_CASE(gEffectBank, gBattlePartyID[gEffectBank]) + break; + case 15: // active bank name with prefix + HANDLE_NICKNAME_STRING_CASE(gActiveBank, gBattlePartyID[gActiveBank]) + break; + case 16: // scripting active bank name with prefix + HANDLE_NICKNAME_STRING_CASE(BATTLE_STRUCT->scriptingActive, gBattlePartyID[BATTLE_STRUCT->scriptingActive]) + break; + case 17: // current move name + if (gStringInfo->currentMove > 0x162) + toCpy = (void*) &gUnknown_08401674[BATTLE_STRUCT->stringMoveType]; + else + toCpy = gMoveNames[gStringInfo->currentMove]; + break; + case 18: // last used move name + if (gStringInfo->lastMove > 0x162) + toCpy = (void*) &gUnknown_08401674[BATTLE_STRUCT->stringMoveType]; + else + toCpy = gMoveNames[gStringInfo->lastMove]; + break; + case 19: // last used item + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + if (gLastUsedItem == ITEM_ENIGMA_BERRY) + { + if (gLinkPlayers[BATTLE_STRUCT->linkPlayerIndex].lp_field_18 == gStringBank) + { + StringCopy(text, gEnigmaBerries[gStringBank].name); +#ifdef ENGLISH + StringAppend(text, gUnknown_08400A85); +#else + de_sub_8073174(text, gUnknown_08400A85); +#endif + toCpy = text; + } + else + toCpy = gUnknown_08400A78; + } + else + { + CopyItemName(gLastUsedItem, text); + toCpy = text; + } + } + else + { + CopyItemName(gLastUsedItem, text); + toCpy = text; + } + break; + case 20: // last used ability + toCpy = gAbilityNames[gLastUsedAbility]; + break; + case 21: // attacker ability + toCpy = gAbilityNames[gAbilitiesPerBank[gBankAttacker]]; + break; + case 22: // target ability + toCpy = gAbilityNames[gAbilitiesPerBank[gBankTarget]]; + break; + case 23: // scripting active ability + toCpy = gAbilityNames[gAbilitiesPerBank[BATTLE_STRUCT->scriptingActive]]; + break; + case 24: // effect bank ability + toCpy = gAbilityNames[gAbilitiesPerBank[gEffectBank]]; + break; + case 25: // trainer class name +#ifdef ENGLISH + if (gTrainerBattleOpponent == 0x400) + toCpy = gTrainerClassNames[GetSecretBaseTrainerNameIndex()]; + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + toCpy = gTrainerClassNames[get_trainer_class_name_index()]; + else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) + toCpy = gTrainerClassNames[sub_8135FD8()]; + else + toCpy = gTrainerClassNames[gTrainers[gTrainerBattleOpponent].trainerClass]; + break; +#else + if (gTrainerBattleOpponent == 0x400) + toCpy = de_sub_8041024(gTrainerBattleOpponent, 0); + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + toCpy = de_sub_8041024(BATTLE_TYPE_BATTLE_TOWER, 0); + else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) + toCpy = de_sub_8041024(BATTLE_TYPE_EREADER_TRAINER, 0); + else + toCpy = de_sub_8041024(0, gTrainerBattleOpponent); + break; +#endif + case 26: // trainer name + if (gTrainerBattleOpponent == 0x400) + { + memset(text, 0xFF, 8); + memcpy(text, &ewram[0x17002], 7); + toCpy = text; + } + else if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + { + get_trainer_name(text); + toCpy = text; + } + else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) + { + sub_8135FF4(text); + toCpy = text; + } + else + toCpy = gTrainers[gTrainerBattleOpponent].trainerName; + break; + case 27: // link player name? + toCpy = gLinkPlayers[multiplayerID].name; + break; + case 28: // link partner name? + toCpy = gLinkPlayers[sub_803FC34(2 ^ gLinkPlayers[multiplayerID].lp_field_18)].name; + break; + case 29: // link opponent 1 name? + toCpy = gLinkPlayers[sub_803FC34(1 ^ gLinkPlayers[multiplayerID].lp_field_18)].name; + break; + case 30: // link opponent 2 name? + toCpy = gLinkPlayers[sub_803FC34(3 ^ gLinkPlayers[multiplayerID].lp_field_18)].name; + break; + case 31: // link scripting active name + toCpy = gLinkPlayers[sub_803FC34(BATTLE_STRUCT->scriptingActive)].name; + break; + case 32: // player name + toCpy = gSaveBlock2.playerName; + break; + case 33: // ? + toCpy = sub_8082830(); + break; + case 34: // ? + HANDLE_NICKNAME_STRING_CASE(BATTLE_STRUCT->scriptingActive, BATTLE_STRUCT->unk1605E) + break; + case 35: // lanette pc + if (FlagGet(SYS_PC_LANETTE)) + toCpy = gUnknown_084009F7; + else + toCpy = gUnknown_084009ED; + break; + case 38: + if (GetBankSide(gBankAttacker) == 0) + toCpy = gUnknown_084007AC; + else + toCpy = gUnknown_084007A7; + break; + case 39: + if (GetBankSide(gBankTarget) == 0) + toCpy = gUnknown_084007AC; + else + toCpy = gUnknown_084007A7; + break; + case 36: + if (GetBankSide(gBankAttacker) == 0) + toCpy = gUnknown_084007A1; + else + toCpy = gUnknown_0840079C; + break; + case 37: + if (GetBankSide(gBankTarget) == 0) + toCpy = gUnknown_084007A1; + else + toCpy = gUnknown_0840079C; + break; + case 40: + if (GetBankSide(gBankAttacker) == 0) + toCpy = gUnknown_084007B7; + else + toCpy = gUnknown_084007B2; + break; + case 41: + if (GetBankSide(gBankTarget) == 0) + toCpy = gUnknown_084007B7; + else + toCpy = gUnknown_084007B2; + break; + } + //if (toCpy != NULL) really GF, why did you forget about this? + while (*toCpy != EOS) + { + dst[dstID] = *toCpy; + dstID++; + toCpy++; + } + if (*src == 33) + { + dst[dstID] = 0xFC; + dstID++; + dst[dstID] = 9; + dstID++; + } + } + else + { + dst[dstID] = *src; + dstID++; + } + src++; + } + dst[dstID] = *src; + dstID++; + return dstID; +} + +#define ByteRead16(ptr) ((ptr)[0] | ((ptr)[1] << 8)) +#define ByteRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24) + +void StrCpyDecodeBattleTextBuff(u8* src, u8* dst) +{ + u32 srcID = 1; + u32 value = 0; + u8 text[12]; + u16 hword; + + *dst = EOS; + while (src[srcID] != EOS) + { + switch (src[srcID]) + { + case 0: // battle string + hword = ByteRead16(&src[srcID + 1]); +#ifdef GERMAN + if (hword == 209 || hword == 211) + srcID += 3; +#endif + StringAppend(dst, gBattleStringsTable[hword - BATTLESTRING_TO_SUB]); + srcID += 3; + break; + case 1: // int to string + switch (src[srcID + 1]) + { + case 1: + value = src[srcID + 3]; + break; + case 2: + value = ByteRead16(&src[srcID + 3]); + break; + case 4: + value = ByteRead32(&src[srcID + 3]); + break; + } + ConvertIntToDecimalStringN(dst, value, 0, src[srcID + 2]); + srcID += src[srcID + 1] + 3; + break; + case 2: // move name + StringAppend(dst, gMoveNames[ByteRead16(&src[srcID + 1])]); + srcID += 3; + break; + case 3: // type name + StringAppend(dst, gTypeNames[src[srcID + 1]]); + srcID += 2; + break; + case 4: // poke nick with prefix +#ifdef ENGLISH + if (GetBankSide(src[srcID + 1]) == 0) + { + GetMonData(&gPlayerParty[src[srcID + 2]], MON_DATA_NICKNAME, text); + } + else + { + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + StringAppend(dst, gUnknown_08400797); + else + StringAppend(dst, gUnknown_08400791); + GetMonData(&gEnemyParty[src[srcID + 2]], MON_DATA_NICKNAME, text); + } + StringGetEnd10(text); + StringAppend(dst, text); +#else + if (GetBankSide(src[srcID + 1]) == 0) + { + GetMonData(&gPlayerParty[src[srcID + 2]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + StringAppend(dst, text); + } + else + { + GetMonData(&gEnemyParty[src[srcID + 2]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + StringAppend(dst, text); + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + StringAppend(dst, gUnknown_08400797); + else + StringAppend(dst, gUnknown_08400791); + } +#endif + srcID += 3; + break; + case 5: // stats + StringAppend(dst, gUnknown_08400F58[src[srcID + 1]]); + srcID += 2; + break; + case 6: // species name + GetSpeciesName(dst, ByteRead16(&src[srcID + 1])); + srcID += 3; + break; + case 7: // poke nick without prefix + if (GetBankSide(src[srcID + 1]) == 0) + GetMonData(&gPlayerParty[src[srcID + 2]], MON_DATA_NICKNAME, dst); + else + GetMonData(&gEnemyParty[src[srcID + 2]], MON_DATA_NICKNAME, dst); + StringGetEnd10(dst); + srcID += 3; + break; + case 8: // flavour table + StringAppend(dst, gUnknown_08400F78[src[srcID + 1]]); + srcID += 2; + break; + case 9: // ability names + StringAppend(dst, gAbilityNames[src[srcID + 1]]); + srcID += 2; + break; + case 10: // item name + { + hword = ByteRead16(&src[srcID + 1]); + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + if (hword == ITEM_ENIGMA_BERRY) + { + if (gLinkPlayers[BATTLE_STRUCT->linkPlayerIndex].lp_field_18 == gStringBank) + { + StringCopy(dst, gEnigmaBerries[gStringBank].name); +#ifdef ENGLISH + StringAppend(dst, gUnknown_08400A85); +#else + de_sub_8073174(dst, gUnknown_08400A85); +#endif + } + else + StringAppend(dst, gUnknown_08400A78); + } + else + CopyItemName(hword, dst); + } + else + CopyItemName(hword, dst); + srcID += 3; + } + break; + } + } +} + +void sub_8121D1C(u8* textBuff) +{ + s32 counter = 0; + u32 i = 0; + + while (counter != 4) + { + if (gUnknown_084016BC[i] == 0) + counter++; + if (gUnknown_084016BC[i++] == gStringInfo->currentMove) + break; + } + + if (counter >= 0) + { + if (counter <= 2) + StringCopy(textBuff, gUnknown_08400E5E); // is + else if (counter <= 4) + StringCopy(textBuff, gUnknown_08400E62); // 's + } +} + +void sub_8121D74(u8* dst) +{ + s32 counter = 0; + s32 i = 0; + + while (*dst != EOS) + dst++; + + while (counter != 4) + { + if (gUnknown_084016BC[i] == 0) + counter++; + if (gUnknown_084016BC[i++] == gStringInfo->currentMove) + break; + } + + switch (counter) + { + case 0: + StringCopy(dst, gUnknown_084007C8); + break; + case 1: + StringCopy(dst, gUnknown_084007CA); + break; + case 2: + StringCopy(dst, gUnknown_084007CC); + break; + case 3: + StringCopy(dst, gUnknown_084007CE); + break; + case 4: + StringCopy(dst, gUnknown_084007D0); + break; + } +} diff --git a/src/battle/battle_party_menu.c b/src/battle/battle_party_menu.c new file mode 100644 index 000000000..49e0b8432 --- /dev/null +++ b/src/battle/battle_party_menu.c @@ -0,0 +1,749 @@ +#include "global.h" +#include "battle_party_menu.h" +#include "battle.h" +#include "item_menu.h" +#include "item_use.h" +#include "main.h" +#include "menu.h" +#include "menu_helpers.h" +#include "palette.h" +#include "party_menu.h" +#include "pokemon.h" +#include "pokemon_summary_screen.h" +#include "rom_8077ABC.h" +#include "rom_8094928.h" +#include "songs.h" +#include "sound.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "text.h" + +extern u8 ewram[]; +#define UNK_201606C_ARRAY (ewram + 0x1606C) // lazy define but whatever. + +extern u8 IsLinkDoubleBattle(void); +extern void TryCreatePartyMenuMonIcon(u8, u8, struct Pokemon *); +extern void LoadHeldItemIconGraphics(void); +extern void CreateHeldItemIcons_806DC34(); +extern u8 sub_806BD58(u8, u8); +extern void PartyMenuPrintMonsLevelOrStatus(void); +extern void PrintPartyMenuMonNicknames(void); +extern void PartyMenuTryPrintMonsHP(void); +extern void nullsub_13(void); +extern void PartyMenuDrawHPBars(void); +extern u8 sub_806B58C(u8); +extern u8 GetItemEffectType(); +extern void sub_806E750(u8, const struct PartyPopupMenu *, const struct PartyMenuItem *, int); +extern void sub_806D5A4(void); +extern void sub_802E414(void); +extern void sub_80A6DCC(void); +extern void sub_806AF4C(); +extern void sub_806AEDC(void); +extern TaskFunc PartyMenuGetPopupMenuFunc(u8, const struct PartyPopupMenu *, const struct PartyMenuItem *, u8); +extern void sub_806E7D0(u8, const struct PartyPopupMenu *); +extern u8 *sub_8040D08(); +extern void sub_8040B8C(void); +extern void sub_806E6F0(); +extern void nullsub_14(); +extern void OpenPartyMenu(); +extern u8 sub_803FBBC(void); + +extern u8 gPlayerPartyCount; +extern u8 gNoOfAllBanks; +extern u16 gBattlePartyID[]; +extern u8 gBankInMenu; +extern u8 gUnknown_0202E8F4; +extern u8 gUnknown_0202E8F5; +extern u8 gUnknown_0202E8F6; +extern u8 gUnknown_02038470[3]; +extern u8 gUnknown_02038473; +extern u8 gUnknown_020384F0; +extern void (*gUnknown_03004AE4)(); //don't know types yet +extern struct PokemonStorage gPokemonStorage; +extern void nullsub_14(); + +void sub_8094C98(u8, u8); +u8 pokemon_order_func(u8); + +static void sub_8094998(u8[3], u8); +static void sub_8094A74(u8[3], u8, u32); +static void sub_8094D60(void); +static void Task_809527C(u8); +static void Task_80952B4(u8); +static void Task_80952E4(u8); +static void Task_8095330(u8); +static void Task_809538C(void); +static void Task_HandlePopupMenuInput(u8); +static void Task_BattlePartyMenuSummary(u8 taskId); +static void Task_BattlePartyMenuShift(u8 taskId); +static void Task_BattlePartyMenuCancel(u8 taskId); + +static const struct PartyMenuItem sBattlePartyMenuActions[] = +{ + {OtherText_Summary, Task_BattlePartyMenuSummary}, + {gOtherText_CancelNoTerminator, Task_BattlePartyMenuCancel}, + {OtherText_Shift, Task_BattlePartyMenuShift}, + {OtherText_SendOut, Task_BattlePartyMenuShift}, +}; +static const u8 Unknown_83B5FEC[] = {2, 0, 1}; //SHIFT, SUMMARY, CANCEL +static const u8 Unknown_83B5FEF[] = {3, 0, 1}; //SEND OUT, SUMMARY, CANCEL +static const u8 Unknown_83B5FF2[] = {0, 1}; //SUMMARY, CANCEL +static const struct PartyPopupMenu sBattlePartyPopupMenus[] = +{ + {ARRAY_COUNT(Unknown_83B5FEC), 9, Unknown_83B5FEC}, + {ARRAY_COUNT(Unknown_83B5FEF), 9, Unknown_83B5FEF}, + {ARRAY_COUNT(Unknown_83B5FF2), 9, Unknown_83B5FF2}, +}; + +void unref_sub_8094928(struct PokemonStorage *ptr) +{ + *ptr = gPokemonStorage; +} + +void unref_sub_8094940(struct PokemonStorage *ptr) +{ + gPokemonStorage = *ptr; +} + +void sub_8094958(void) +{ + sub_8094998(gUnknown_02038470, sub_803FBBC()); +} + +void sub_8094978(u8 arg1, u8 arg2) +{ + sub_8094A74((UNK_201606C_ARRAY) + arg1 * 3, arg2, arg1); +} + +static void sub_8094998(u8 arg[3], u8 player_number) +{ + int i; + u32 pos; + u8 temp[6]; + if (IsLinkDoubleBattle() == TRUE) + { + if (player_number) + { + *arg = 0x30; + arg[1] = 0x45; + arg[2] = 0x12; + } + else + { + *arg = 0x03; + arg[1] = 0x12; + arg[2] = 0x45; + } + } + else + { + if (!IsDoubleBattle()) + { + pos = 1; + *temp = gBattlePartyID[GetBankByPlayerAI(0)]; + for (i = 0; i <= 5; i++) + if (i != *temp) + temp[pos++] = i; + } + else + { + pos = 2; + *temp = gBattlePartyID[GetBankByPlayerAI(0)]; + temp[1] = gBattlePartyID[GetBankByPlayerAI(2)]; + for (i = 0; i <= 5; i++) + if ((i != *temp) && (i != temp[1])) + temp[pos++] = i; + } + for (i = 0; i <= 2; i++) + arg[i] = (temp[i << 1] << 4) | temp[(i << 1) + 1]; + } +} + +static void sub_8094A74(u8 arg[3], u8 player_number, u32 arg3) +{ + int i, j; + u8 temp[6]; + if (!GetBankSide(arg3)) + { + i = GetBankByPlayerAI(0); + j = GetBankByPlayerAI(2); + } + else + { + i = GetBankByPlayerAI(1); + j = GetBankByPlayerAI(3); + } + if (IsLinkDoubleBattle() == TRUE) + { + if (player_number) + { + *arg = 0x30; + arg[1] = 0x45; + arg[2] = 0x12; + } + else + { + *arg = 0x03; + arg[1] = 0x12; + arg[2] = 0x45; + } + } + else + { + if (!IsDoubleBattle()) + { + int pos = 1; + *temp = gBattlePartyID[i]; + for (i = 0; i <= 5; i++) + if (i != *temp) + temp[pos++] = i; + } + else + { + int pos = 2; + *temp = gBattlePartyID[i]; + temp[1] = gBattlePartyID[j]; + for (i = 0; i <= 5; i++) + if ((i != *temp) && (i != temp[1])) + temp[pos++] = i; + } + for (i = 0; i <= 2; i++) + arg[i] = (temp[i << 1] << 4) | temp[(i << 1) + 1]; + } +} + +void sub_8094B6C(u8 a, u8 b, u8 c) +{ + s32 i; + s32 j; + u8 temp[6]; + u8 r3; + u8 r7 = 0; + + if (IsLinkDoubleBattle()) + { + u8 *arr = ewram + 0x1606C + a * 3; + + for (i = 0, j = 0; i < 3; i++) + { + temp[j++] = arr[i] >> 4; + temp[j++] = arr[i] & 0xF; + } + r3 = temp[c]; + for (i = 0; i < 6; i++) + { + if (temp[i] == b) + { + r7 = temp[i]; + temp[i] = r3; + break; + } + } + if (i != 6) + { + temp[c] = r7; + + arr[0] = (temp[0] << 4) | temp[1]; + arr[1] = (temp[2] << 4) | temp[3]; + arr[2] = (temp[4] << 4) | temp[5]; + } + } +} + +u8 sub_8094C20(u8 a) +{ + u8 retVal; + u8 val = a & 1; + + a /= 2; + if (val) + retVal = gUnknown_02038470[a] & 0xF; + else + retVal = gUnknown_02038470[a] >> 4; + return retVal; +} + +void sub_8094C54(u8 a, u8 b) +{ + u8 val = a & 1; + + a /= 2; + if (val) + gUnknown_02038470[a] = (gUnknown_02038470[a] & 0xF0) | b; + else + gUnknown_02038470[a] = (gUnknown_02038470[a] & 0xF) | (b << 4); +} + +void sub_8094C98(u8 a, u8 b) +{ + u8 r4 = sub_8094C20(a); + u8 r1 = sub_8094C20(b); + + sub_8094C54(a, r1); + sub_8094C54(b, r4); +} + +u8 pokemon_order_func(u8 a) +{ + u8 i; + u8 r2; + + for (i = 0, r2 = 0; i < 3; i++) + { + if ((gUnknown_02038470[i] >> 4) == a) + return r2; + r2++; + if ((gUnknown_02038470[i] & 0xF) == a) + return r2; + r2++; + } + return 0; +} + +void pokemon_change_order(void) +{ + u8 i; + + memcpy(ewram1B000.unk0, gPlayerParty, sizeof(gPlayerParty)); + for (i = 0; i < 6; i++) + { + u8 n = pokemon_order_func(i); + + memcpy(&gPlayerParty[n], &ewram1B000.unk0[i], sizeof(struct Pokemon)); + } +} + +static void sub_8094D60(void) +{ + struct Pokemon temp[6]; + u8 i; + + memcpy(temp, gPlayerParty, sizeof(gPlayerParty)); + for (i = 0; i < 6; i++) + { + u8 n = sub_8094C20(i); + + memcpy(&gPlayerParty[n], &temp[i], sizeof(struct Pokemon)); + } +} + +void unref_sub_8094DB0(void) +{ + u8 i; + u8 r4; + + for (i = 1; i < 6; i++) + { + u8 n = sub_8094C20(i); + + if (GetMonData(&gPlayerParty[n], MON_DATA_SPECIES) != 0 + && GetMonData(&gPlayerParty[n], MON_DATA_HP) != 0) + { + r4 = sub_8094C20(0); + sub_8094C98(0, i); + sub_806E6F0(&gPlayerParty[r4], &gPlayerParty[n]); + break; + } + } +} + +void sub_8094E20(u8 a) +{ + gPaletteFade.bufferTransferDisabled = TRUE; + gUnknown_02038473 = a; + nullsub_14(); + pokemon_change_order(); + OpenPartyMenu(1, 0xFF); +} + +void sub_8094E4C(void) +{ + sub_8094E20(3); +} + +int SetUpBattlePartyMenu(void) +{ + switch (EWRAM_1B000.unk264) + //switch (ewram1B000.unk264[0]) + { + case 0: + //TODO: try to get rid of this duplicate code + if (IsLinkDoubleBattle() == TRUE) + { + if (EWRAM_1B000.unk266 != 6) + { + TryCreatePartyMenuMonIcon(EWRAM_1B000.unk260, EWRAM_1B000.unk266, &gPlayerParty[EWRAM_1B000.unk266]); + EWRAM_1B000.unk266++; + } + else + { + EWRAM_1B000.unk266 = 0; + EWRAM_1B000.unk264++; + } + } + else + { + if (EWRAM_1B000.unk266 < 6) + { + TryCreatePartyMenuMonIcon(EWRAM_1B000.unk260, EWRAM_1B000.unk266, &gPlayerParty[EWRAM_1B000.unk266]); + EWRAM_1B000.unk266++; + } + else + { + EWRAM_1B000.unk266 = 0; + EWRAM_1B000.unk264++; + } + } + break; + case 1: + LoadHeldItemIconGraphics(); + EWRAM_1B000.unk264++; + break; + case 2: + CreateHeldItemIcons_806DC34(EWRAM_1B000.unk260); + EWRAM_1B000.unk264++; + break; + case 3: + if (sub_806BD58(EWRAM_1B000.unk260, EWRAM_1B000.unk266) == 1) + { + EWRAM_1B000.unk266 = 0; + EWRAM_1B000.unk264++; + } + else + EWRAM_1B000.unk266++; + break; + case 4: + PartyMenuPrintMonsLevelOrStatus(); + EWRAM_1B000.unk264++; + break; + case 5: + PrintPartyMenuMonNicknames(); + EWRAM_1B000.unk264++; + break; + case 6: + PartyMenuTryPrintMonsHP(); + EWRAM_1B000.unk264++; + break; + case 7: + nullsub_13(); + EWRAM_1B000.unk264++; + break; + case 8: + PartyMenuDrawHPBars(); + EWRAM_1B000.unk264++; + break; + case 9: + if (sub_806B58C(EWRAM_1B000.unk266) == 1) + { + EWRAM_1B000.unk266 = 0; + EWRAM_1B000.unk264++; + } + else + EWRAM_1B000.unk266++; + break; + case 10: + if (gUnknown_02038473 == 3) + { + if (GetItemEffectType(gScriptItemId) == 10) + ewram1B000.unk259 = 0xFF; + else + ewram1B000.unk259 = 3; + } + return TRUE; + } + return FALSE; +} + +static void sub_8095050(u8 a, u8 b) +{ + if (!GetMonData(&gPlayerParty[b], MON_DATA_IS_EGG)) + { + if (gUnknown_02038473 == 1) + { + gTasks[EWRAM_1B000.unk260].data[4] = 1; + gTasks[EWRAM_1B000.unk260].data[5] = 1; + } + else + { + gTasks[EWRAM_1B000.unk260].data[4] = 0; + gTasks[EWRAM_1B000.unk260].data[5] = 0; + } + } + else + { + gTasks[EWRAM_1B000.unk260].data[4] = 2; + gTasks[EWRAM_1B000.unk260].data[5] = 2; + } + sub_806E750(gTasks[a].data[4], sBattlePartyPopupMenus, sBattlePartyMenuActions, 0); +} + +void SetUpBattlePokemonMenu(u8 a) +{ + if (!gPaletteFade.active) + { + if (gUnknown_02038473 == 3 && GetItemEffectType(gScriptItemId) == 10) + { + gUnknown_03004AE4(a, gScriptItemId, Task_80952E4); + return; + } + + switch (sub_806BD80(a)) + { + case 1: + if (gUnknown_02038473 == 3) + { + if (GetMonData(&gPlayerParty[sub_806CA38(a)], MON_DATA_IS_EGG)) + PlaySE(SE_HAZURE); + else + { + sub_806D5A4(); + gUnknown_03004AE4(a, gScriptItemId, Task_80952E4); + } + } + else + { + PlaySE(SE_SELECT); + GetMonNickname(&gPlayerParty[sub_806CA38(a)], gStringVar1); + sub_8095050(a, sub_806CA38(a)); + SetTaskFuncWithFollowupFunc(a, Task_HandlePopupMenuInput, SetUpBattlePokemonMenu); + } + break; + case 2: + if (gUnknown_02038473 == 1) + PlaySE(SE_HAZURE); + else + { + PlaySE(SE_SELECT); + if (gUnknown_02038473 == 3) + { + gUnknown_0202E8F4 = 0; + gTasks[a].func = Task_80952E4; + } + else + { + gUnknown_0202E8F4 = 0; + gTasks[a].func = Task_809527C; + } + } + break; + } + } +} + +static void Task_809527C(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = Task_80952B4; +} + +static void Task_80952B4(u8 taskId) +{ + if (!gPaletteFade.active) + { + sub_8094D60(); + DestroyTask(taskId); + SetMainCallback2(sub_802E414); + } +} + +static void Task_80952E4(u8 taskId) +{ + if (gUnknown_0202E8F4 != 0) + Task_809527C(taskId); + else + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = Task_8095330; + } +} + +static void Task_8095330(u8 taskId) +{ + if (!gPaletteFade.active) + { + sub_8094D60(); + DestroyTask(taskId); + sub_80A6DCC(); + } +} + +static void Task_809535C(void) +{ + gPaletteFade.bufferTransferDisabled = TRUE; + sub_806AF4C(1, 0xFF, SetUpBattlePokemonMenu, 5); + SetMainCallback2(Task_809538C); +} + +static void Task_809538C(void) +{ + do + { + if (sub_806B124() == TRUE) + { + sub_806C994(EWRAM_1B000.unk260, gUnknown_020384F0); + sub_806BF74(EWRAM_1B000.unk260, 0); + GetMonNickname(&gPlayerParty[gUnknown_020384F0], gStringVar1); + sub_8095050(EWRAM_1B000.unk260, gUnknown_020384F0); + SetTaskFuncWithFollowupFunc(EWRAM_1B000.unk260, Task_HandlePopupMenuInput, SetUpBattlePokemonMenu); + SetMainCallback2(sub_806AEDC); + return; + } + } while (sub_80F9344() != 1); +} + +static void Task_HandlePopupMenuInput(u8 taskId) +{ + TaskFunc func; + + if (!gPaletteFade.active) + { + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + return; + } + if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + return; + } + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + func = PartyMenuGetPopupMenuFunc(gTasks[taskId].data[4], + sBattlePartyPopupMenus, + sBattlePartyMenuActions, + GetMenuCursorPos()); + func(taskId); + return; + } + if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + Task_BattlePartyMenuCancel(taskId); + return; + } + } +} + +static void Task_80954C0(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + Task_BattlePartyMenuCancel(taskId); +} + +static void Task_ShowSummaryScreen(u8 taskId) +{ + u8 partySelection = sub_806CA38(taskId); + + if (!gPaletteFade.active) + { + DestroyTask(taskId); + EWRAM_1B000.unk262 = 1; + ShowPokemonSummaryScreen(gPlayerParty, partySelection, gPlayerPartyCount - 1, Task_809535C, 4); + } +} + +static void Task_BattlePartyMenuSummary(u8 taskId) +{ + sub_806CA38(taskId); //an unused variable was probably set with this. + gTasks[taskId].func = Task_ShowSummaryScreen; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); +} + +static void Task_BattlePartyMenuShift(u8 taskId) +{ + u8 partySelection; + u8 i; + u8 r4; + + sub_806E7D0(gTasks[taskId].data[4], sBattlePartyPopupMenus); + partySelection = sub_806CA38(taskId); + if (IsLinkDoubleBattle() == TRUE && (partySelection == 1 || partySelection == 4 || partySelection == 5)) + { + sub_806D5A4(); + StringCopy(gStringVar1, sub_8040D08()); + StringExpandPlaceholders(gStringVar4, gOtherText_CantSwitchPokeWithYours); + sub_806E834(gStringVar4, 0); + gTasks[taskId].func = Task_80954C0; + return; + } + if (GetMonData(&gPlayerParty[partySelection], MON_DATA_HP) == 0) + { + sub_806D5A4(); + GetMonNickname(&gPlayerParty[partySelection], gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_NoEnergyLeft); + sub_806E834(gStringVar4, 0); + gTasks[taskId].func = Task_80954C0; + return; + } + for (i = 0; i < gNoOfAllBanks; i++) + { + if (GetBankSide(i) == 0 + && sub_8094C20(partySelection) == gBattlePartyID[i]) + { + sub_806D5A4(); + GetMonNickname(&gPlayerParty[partySelection], gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_AlreadyBattle); + sub_806E834(gStringVar4, 0); + gTasks[taskId].func = Task_80954C0; + return; + } + } + if (GetMonData(&gPlayerParty[partySelection], MON_DATA_IS_EGG)) + { + sub_806D5A4(); + StringExpandPlaceholders(gStringVar4, gOtherText_EGGCantBattle); + sub_806E834(gStringVar4, 0); + gTasks[taskId].func = Task_80954C0; + return; + } + if (sub_8094C20(partySelection) == EWRAM_1609D) + { + sub_806D5A4(); + GetMonNickname(&gPlayerParty[partySelection], gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_AlreadySelected); + sub_806E834(gStringVar4, 0); + gTasks[taskId].func = Task_80954C0; + return; + } + if (gUnknown_02038473 == 4) + { + sub_806D5A4(); + sub_8040B8C(); + sub_806E834(gStringVar4, 0); + gTasks[taskId].func = Task_80954C0; + return; + } + if (gUnknown_02038473 == 2) + { + u8 r0; + u8 r4 = gBankInMenu; + + sub_806D5A4(); + r0 = pokemon_order_func(gBattlePartyID[r4]); + GetMonNickname(&gPlayerParty[r0], gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_CantBeSwitched); + sub_806E834(gStringVar4, 0); + gTasks[taskId].func = Task_80954C0; + return; + } + gUnknown_0202E8F5 = sub_8094C20(partySelection); + gUnknown_0202E8F4 = 1; + r4 = pokemon_order_func(gBattlePartyID[gBankInMenu]); + sub_8094C98(r4, partySelection); + sub_806E6F0(&gPlayerParty[r4], &gPlayerParty[partySelection]); + gTasks[taskId].func = Task_809527C; +} + +static void Task_BattlePartyMenuCancel(u8 taskId) +{ + HandleDestroyMenuCursors(); + sub_806E7D0(gTasks[taskId].data[4], sBattlePartyPopupMenus); + gTasks[taskId].data[4] = gTasks[taskId].data[5]; + sub_806D538(0, 0); + SwitchTaskToFollowupFunc(taskId); +} diff --git a/src/battle/battle_records.c b/src/battle/battle_records.c new file mode 100644 index 000000000..d848a10b8 --- /dev/null +++ b/src/battle/battle_records.c @@ -0,0 +1,334 @@ +#include "global.h" +#include "battle_records.h" +#include "game_stat.h" +#include "link.h" +#include "menu.h" +#include "overworld.h" +#include "string_util.h" +#include "strings2.h" +#include "trainer_card.h" + +extern struct LinkPlayerMapObject gLinkPlayerMapObjects[4]; +extern u8 gBattleOutcome; + +static void InitLinkBattleRecord(struct LinkBattleRecord *record) +{ + CpuFill16(0, record, sizeof(struct LinkBattleRecord)); + record->name[0] = 0xFF; + record->trainerId = 0; + record->wins = 0; + record->losses = 0; + record->draws = 0; +} + +static void InitLinkBattleRecords_(struct LinkBattleRecord *records) +{ + int i; + for (i = 0; i < 5; i++) + { + InitLinkBattleRecord(records + i); + } + SetGameStat(GAME_STAT_LINK_BATTLE_WINS, 0); + SetGameStat(GAME_STAT_LINK_BATTLE_LOSSES, 0); + SetGameStat(GAME_STAT_LINK_BATTLE_DRAWS, 0); +} + +static int GetLinkBattleRecordTotalBattles(struct LinkBattleRecord *record) +{ + return record->wins + record->losses + record->draws; +} + +static int FindLinkBattleRecord(struct LinkBattleRecord *records, u8 *name, u16 trainerId) +{ + int i; + + for (i = 0; i < 5; i++) + { + memcpy(gStringVar1, records[i].name, 7); + gStringVar1[7] = EOS; + if (!StringCompareWithoutExtCtrlCodes(gStringVar1, name) && records[i].trainerId == trainerId) + return i; + } + + return 5; +} + +static void SortLinkBattleRecords(struct LinkBattleRecord *records) +{ + int i, j; + + for (i = 4; i > 0; i--) + { + for (j = i - 1; j >= 0; j--) + { + int totalBattlesI = GetLinkBattleRecordTotalBattles(records + i); + int totalBattlesJ = GetLinkBattleRecordTotalBattles(records + j); + + if (totalBattlesI > totalBattlesJ) + { + struct LinkBattleRecord temp = *(records + i); + *(records + i) = *(records + j); + *(records + j) = temp; + } + } + } +} + +static void UpdateLinkBattleRecord(struct LinkBattleRecord *record, int battleOutcome) +{ + switch (battleOutcome) + { + case 1: + record->wins++; + if (record->wins > 9999) + record->wins = 9999; + break; + case 2: + record->losses++; + if (record->losses > 9999) + record->losses = 9999; + break; + case 3: + record->draws++; + if (record->draws > 9999) + record->draws = 9999; + break; + } +} + +static void UpdateLinkBattleGameStats(int battleOutcome) +{ + u8 stat; + + switch (battleOutcome) + { + case 1: + stat = GAME_STAT_LINK_BATTLE_WINS; + break; + case 2: + stat = GAME_STAT_LINK_BATTLE_LOSSES; + break; + case 3: + stat = GAME_STAT_LINK_BATTLE_DRAWS; + break; + default: + return; + } + + if (GetGameStat(stat) < 9999) + IncrementGameStat(stat); +} + +static void UpdateLinkBattleRecords_(struct LinkBattleRecord *records, u8 *name, u16 trainerId, int battleOutcome, u8 language) +{ + int index; + UpdateLinkBattleGameStats(battleOutcome); + SortLinkBattleRecords(records); + index = FindLinkBattleRecord(records, name, trainerId); + if (index == 5) + { + index = 4; + InitLinkBattleRecord(records + index); + if (language == LANGUAGE_JAPANESE) + { + records[index].name[0] = EXT_CTRL_CODE_BEGIN; + records[index].name[1] = 0x15; + StringCopyN(records[index].name + 2, name, 5); + } + else + { + StringCopyN(records[index].name, name, 7); + } + + // needed block to match + { + struct LinkBattleRecord *record = records + index; + record->trainerId = trainerId; + } + } + UpdateLinkBattleRecord(records + index, battleOutcome); + SortLinkBattleRecords(records); +} + +void InitLinkBattleRecords(void) +{ + InitLinkBattleRecords_(gSaveBlock1.linkBattleRecords); +} + +static void IncTrainerCardWins(int id) +{ + u16 *wins = &gTrainerCards[id].linkBattleWins; + (*wins)++; + if (*wins > 9999) + *wins = 9999; +} + +static void IncTrainerCardLosses(int id) +{ + u16 *losses = &gTrainerCards[id].linkBattleLosses; + (*losses)++; + if (*losses > 9999) + *losses = 9999; +} + +static void UpdateTrainerCardWinsLosses(int id) +{ + switch (gBattleOutcome) + { + case 1: + IncTrainerCardWins(id ^ 1); + IncTrainerCardLosses(id); + break; + case 2: + IncTrainerCardLosses(id ^ 1); + IncTrainerCardWins(id); + break; + } +} + +void UpdateLinkBattleRecords(int id) +{ + UpdateTrainerCardWinsLosses(id); + UpdateLinkBattleRecords_( + gSaveBlock1.linkBattleRecords, + gTrainerCards[id].playerName, + gTrainerCards[id].trainerId, + gBattleOutcome, + gLinkPlayers[gLinkPlayerMapObjects[id].linkPlayerId].language); +} + +static void PrintLinkBattleWinsLossesDraws(struct LinkBattleRecord *records) +{ + ConvertIntToDecimalStringN_DigitWidth6(gStringVar1, GetGameStat(GAME_STAT_LINK_BATTLE_WINS), STR_CONV_MODE_RIGHT_ALIGN, 4); + ConvertIntToDecimalStringN_DigitWidth6(gStringVar2, GetGameStat(GAME_STAT_LINK_BATTLE_LOSSES), STR_CONV_MODE_RIGHT_ALIGN, 4); + ConvertIntToDecimalStringN_DigitWidth6(gStringVar3, GetGameStat(GAME_STAT_LINK_BATTLE_DRAWS), STR_CONV_MODE_RIGHT_ALIGN, 4); + MenuPrint(gOtherText_WinRecord, 3, 3); +} + +static void PrintLinkBattleRecord(struct LinkBattleRecord *record, u8 y) +{ + if (!record->wins && !record->losses && !record->draws) + { + u8 buffer[16]; + buffer[0] = EXT_CTRL_CODE_BEGIN; + buffer[1] = 0x14; + buffer[2] = 6; + buffer[3] = EXT_CTRL_CODE_BEGIN; + buffer[4] = 0x11; + buffer[5] = 1; + StringCopy(buffer + 6, gOtherText_SevenDashes); + MenuPrint(buffer, 3, y); + StringCopy(buffer + 6, gOtherText_FourDashes); + MenuPrint(buffer, 11, y); + MenuPrint(buffer, 17, y); + MenuPrint(buffer, 23, y); + } + else + { + StringFillWithTerminator(gStringVar1, 8); + StringCopyN(gStringVar1, record->name, 7); + MenuPrint(gStringVar1, 3, y); + gStringVar1[0] = EXT_CTRL_CODE_BEGIN; + gStringVar1[1] = 0x14; + gStringVar1[2] = 6; + ConvertIntToDecimalStringN(gStringVar1 + 3, record->wins, STR_CONV_MODE_RIGHT_ALIGN, 4); + MenuPrint(gStringVar1, 11, y); + ConvertIntToDecimalStringN(gStringVar1 + 3, record->losses, STR_CONV_MODE_RIGHT_ALIGN, 4); + MenuPrint(gStringVar1, 17, y); + ConvertIntToDecimalStringN(gStringVar1 + 3, record->draws, STR_CONV_MODE_RIGHT_ALIGN, 4); + MenuPrint(gStringVar1, 23, y); + } +} + +void ShowLinkBattleRecords(void) { + s32 i; + MenuDrawTextWindow(1, 0, 28, 18); + sub_8072BD8((u8 *) gOtherText_BattleResults, 0, 1, 240); + + PrintLinkBattleWinsLossesDraws(gSaveBlock1.linkBattleRecords); +#if ENGLISH + MenuPrint(gOtherText_WinLoseDraw, 12, 6); +#elif GERMAN + MenuPrint_PixelCoords(gOtherText_WinLoseDraw, 88, 48, 1); +#endif + + for (i = 0; i < 5; i++) + { + PrintLinkBattleRecord(&gSaveBlock1.linkBattleRecords[i], 6 + (i + 1) * 2); + } +} + +static bool32 sub_8110494(u8 level) +{ + struct SaveBlock2_Sub *sb2sub = &gSaveBlock2.filler_A8; + + switch (sb2sub->var_4AE[level]) + { + case 0: + return FALSE; + case 1: + return FALSE; + case 2: + return TRUE; + case 4: + return FALSE; + case 3: + return TRUE; + case 5: + return FALSE; + case 6: + return TRUE; + default: + return FALSE; + } +} + +static void PrintWinStreak(const u8 *str, u16 streak, u8 left, u8 top) +{ + MenuPrint(str, left, top); + if (streak > 9999) + streak = 9999; + sub_8072C14(gStringVar1, streak, 24, 1); + MenuPrint(gOtherText_WinStreak, left + 7, top); +} + +static void PrintRecordWinStreak(u8 level, u8 left, u8 top) +{ + struct SaveBlock2_Sub *sb2sub = &gSaveBlock2.filler_A8; + u16 winStreak = sb2sub->recordWinStreak[level]; + PrintWinStreak(gOtherText_Record, winStreak, left, top); +} + +static u16 GetLastWinStreak(u8 level) +{ + u16 result = gSaveBlock2.filler_A8.winStreak[level]; + if (result > 9999) + result = 9999; + return result; +} + +static void PrintLastWinStreak(u8 level, u8 left, u8 top) +{ + u16 winStreak = GetLastWinStreak(level); + if (sub_8110494(level) == TRUE) + PrintWinStreak(gOtherText_Current, winStreak, left, top); + else + PrintWinStreak(gOtherText_Prev, winStreak, left, top); +} + +void ShowBattleTowerRecords(void) +{ + u16 i; + MenuDrawTextWindow(3, 1, 27, 17); + sub_8072BD8(gOtherText_BattleTowerResults, 3, 2, 0xC8); + MenuPrint(gOtherText_Lv50, 5, 6); + MenuPrint(gOtherText_Lv100, 5, 12); + for (i = 5; i < 26; i++) + { + sub_8071F60(CHAR_HYPHEN, i, 10); + } + PrintLastWinStreak(0, 10, 6); + PrintRecordWinStreak(0, 10, 8); + PrintLastWinStreak(1, 10, 12); + PrintRecordWinStreak(1, 10, 14); +} diff --git a/src/battle/battle_setup.c b/src/battle/battle_setup.c new file mode 100644 index 000000000..59e17e9eb --- /dev/null +++ b/src/battle/battle_setup.c @@ -0,0 +1,1459 @@ +#include "global.h" +#include "battle_setup.h" +#include "battle.h" +#include "battle_transition.h" +#include "data2.h" +#include "event_data.h" +#include "field_control_avatar.h" +#include "field_fadetransition.h" +#include "field_map_obj_helpers.h" +#include "field_message_box.h" +#include "field_player_avatar.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "fldeff_80C5CD4.h" +#include "main.h" +#include "map_constants.h" +#include "metatile_behavior.h" +#include "opponent_constants.h" +#include "palette.h" +#include "rng.h" +#include "overworld.h" +#include "safari_zone.h" +#include "script.h" +#include "script_pokemon_80C4.h" +#include "secret_base.h" +#include "songs.h" +#include "sound.h" +#include "species.h" +#include "starter_choose.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "text.h" +#include "trainer.h" + +extern u16 gScriptResult; + +extern void (*gFieldCallback)(void); + +EWRAM_DATA static u16 sTrainerBattleMode = 0; +EWRAM_DATA u16 gTrainerBattleOpponent = 0; +EWRAM_DATA static u16 sTrainerMapObjectLocalId = 0; +EWRAM_DATA static u8 *sTrainerIntroSpeech = NULL; +EWRAM_DATA static u8 *sTrainerDefeatSpeech = NULL; +EWRAM_DATA static u8 *sTrainerVictorySpeech = NULL; +EWRAM_DATA static u8 *sTrainerCannotBattleSpeech = NULL; +EWRAM_DATA static u8 *sTrainerBattleScriptRetAddr = NULL; +EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL; + +extern u16 gBattleTypeFlags; +extern u16 gScriptLastTalked; +extern u8 gBattleOutcome; + +extern struct MapObject gMapObjects[]; + +extern u8 gUnknown_0819F818[]; +extern u8 gUnknown_0819F840[]; +extern u8 gUnknown_0819F878[]; +extern u8 gUnknown_0819F887[]; +extern u8 gUnknown_0819F8AE[]; + +extern u8 gUnknown_0819F80B[]; +extern u8 gUnknown_081C6C02[]; + +// The first transition is used if the enemy pokemon are lower level than our pokemon. +// Otherwise, the second transition is used. +static const u8 gBattleTransitionTable_Wild[][2] = +{ + {B_TRANSITION_SLICE, B_TRANSITION_WHITEFADE}, // Normal + {B_TRANSITION_CLOCKWISE_BLACKFADE, B_TRANSITION_GRID_SQUARES}, // Cave + {B_TRANSITION_BLUR, B_TRANSITION_GRID_SQUARES}, // Cave with flash used + {B_TRANSITION_WAVE, B_TRANSITION_RIPPLE}, // Water +}; +static const u8 gBattleTransitionTable_Trainer[][2] = +{ + {B_TRANSITION_POKEBALLS_TRAIL, B_TRANSITION_SHARDS}, // Normal + {B_TRANSITION_SHUFFLE, B_TRANSITION_BIG_POKEBALL}, // Cave + {B_TRANSITION_BLUR, B_TRANSITION_GRID_SQUARES}, // Cave with flash used + {B_TRANSITION_SWIRL, B_TRANSITION_RIPPLE}, // Water +}; + +enum +{ + TRAINER_PARAM_LOAD_VAL_8BIT, + TRAINER_PARAM_LOAD_VAL_16BIT, + TRAINER_PARAM_LOAD_VAL_32BIT, + TRAINER_PARAM_CLEAR_VAL_8BIT, + TRAINER_PARAM_CLEAR_VAL_16BIT, + TRAINER_PARAM_CLEAR_VAL_32BIT, + TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR, +}; + +struct TrainerBattleParameter +{ + void *varPtr; + u8 ptrType; +}; + +static const struct TrainerBattleParameter gTrainerBattleSpecs_0[] = +{ + {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, + {&gTrainerBattleOpponent, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerBattleEndScript, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerBattleScriptRetAddr, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, +}; +static const struct TrainerBattleParameter gTrainerBattleSpecs_1[] = +{ + {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, + {&gTrainerBattleOpponent, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerBattleScriptRetAddr, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, +}; +static const struct TrainerBattleParameter gTrainerBattleSpecs_2[] = +{ + {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, + {&gTrainerBattleOpponent, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerCannotBattleSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerBattleEndScript, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerBattleScriptRetAddr, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, +}; +static const struct TrainerBattleParameter gTrainerBattleSpecs_3[] = +{ + {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, + {&gTrainerBattleOpponent, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerBattleEndScript, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerBattleScriptRetAddr, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, +}; +static const struct TrainerBattleParameter gTrainerBattleSpecs_4[] = +{ + {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT}, + {&gTrainerBattleOpponent, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT}, + {&sTrainerIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT}, + {&sTrainerCannotBattleSpeech, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_VAL_32BIT}, + {&sTrainerBattleScriptRetAddr, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR}, +}; + +const struct TrainerEyeTrainer gTrainerEyeTrainers[] = +{ + { + {OPPONENT_ROSE_1, OPPONENT_ROSE_2, OPPONENT_ROSE_3, OPPONENT_ROSE_4, OPPONENT_ROSE_5}, + MAP_GROUP_ROUTE118, + MAP_ID_ROUTE118, + }, + { + {OPPONENT_DUSTY_1, OPPONENT_DUSTY_2, OPPONENT_DUSTY_3, OPPONENT_DUSTY_4, OPPONENT_DUSTY_5}, + MAP_GROUP_ROUTE111, + MAP_ID_ROUTE111, + }, + { + {OPPONENT_LOLA_1, OPPONENT_LOLA_2, OPPONENT_LOLA_3, OPPONENT_LOLA_4, OPPONENT_LOLA_5}, + MAP_GROUP_ROUTE109, + MAP_ID_ROUTE109, + }, + { + {OPPONENT_RICKY_1, OPPONENT_RICKY_2, OPPONENT_RICKY_3, OPPONENT_RICKY_4, OPPONENT_RICKY_5}, + MAP_GROUP_ROUTE109, + MAP_ID_ROUTE109, + }, + { + {OPPONENT_RITA_AND_SAM_1, OPPONENT_RITA_AND_SAM_2, OPPONENT_RITA_AND_SAM_3, OPPONENT_RITA_AND_SAM_4, OPPONENT_RITA_AND_SAM_5}, + MAP_GROUP_ROUTE124, + MAP_ID_ROUTE124, + }, + { + {OPPONENT_BROOKE_1, OPPONENT_BROOKE_2, OPPONENT_BROOKE_3, OPPONENT_BROOKE_4, OPPONENT_BROOKE_5}, + MAP_GROUP_ROUTE111, + MAP_ID_ROUTE111, + }, + { + {OPPONENT_WILTON_1, OPPONENT_WILTON_2, OPPONENT_WILTON_3, OPPONENT_WILTON_4, OPPONENT_WILTON_5}, + MAP_GROUP_ROUTE111, + MAP_ID_ROUTE111, + }, + { + {OPPONENT_VALERIE_1, OPPONENT_VALERIE_2, OPPONENT_VALERIE_3, OPPONENT_VALERIE_4, OPPONENT_VALERIE_5}, + MAP_GROUP_MT_PYRE_6F, + MAP_ID_MT_PYRE_6F, + }, + { + {OPPONENT_CINDY_1, OPPONENT_CINDY_3, OPPONENT_CINDY_4, OPPONENT_CINDY_5, OPPONENT_CINDY_6}, + MAP_GROUP_ROUTE104, + MAP_ID_ROUTE104, + }, + { + {OPPONENT_JESSICA_1, OPPONENT_JESSICA_2, OPPONENT_JESSICA_3, OPPONENT_JESSICA_4, OPPONENT_JESSICA_5}, + MAP_GROUP_ROUTE121, + MAP_ID_ROUTE121, + }, + { + {OPPONENT_WINSTON_1, OPPONENT_WINSTON_2, OPPONENT_WINSTON_3, OPPONENT_WINSTON_4, OPPONENT_WINSTON_5}, + MAP_GROUP_ROUTE104, + MAP_ID_ROUTE104, + }, + { + {OPPONENT_STEVE_1, OPPONENT_STEVE_2, OPPONENT_STEVE_3, OPPONENT_STEVE_4, OPPONENT_STEVE_5}, + MAP_GROUP_ROUTE114, + MAP_ID_ROUTE114, + }, + { + {OPPONENT_TONY_1, OPPONENT_TONY_2, OPPONENT_TONY_3, OPPONENT_TONY_4, OPPONENT_TONY_5}, + MAP_GROUP_ROUTE107, + MAP_ID_ROUTE107, + }, + { + {OPPONENT_NOB_1, OPPONENT_NOB_2, OPPONENT_NOB_3, OPPONENT_NOB_4, OPPONENT_NOB_5}, + MAP_GROUP_ROUTE115, + MAP_ID_ROUTE115, + }, + { + {OPPONENT_DALTON_1, OPPONENT_DALTON_2, OPPONENT_DALTON_3, OPPONENT_DALTON_4, OPPONENT_DALTON_5}, + MAP_GROUP_ROUTE118, + MAP_ID_ROUTE118, + }, + { + {OPPONENT_BERNIE_1, OPPONENT_BERNIE_2, OPPONENT_BERNIE_3, OPPONENT_BERNIE_4, OPPONENT_BERNIE_5}, + MAP_GROUP_ROUTE114, + MAP_ID_ROUTE114, + }, + { + {OPPONENT_ETHAN_1, OPPONENT_ETHAN_2, OPPONENT_ETHAN_3, OPPONENT_ETHAN_4, OPPONENT_ETHAN_5}, + MAP_GROUP_JAGGED_PASS, + MAP_ID_JAGGED_PASS, + }, + { + {OPPONENT_JOHN_AND_JAY_1, OPPONENT_JOHN_AND_JAY_2, OPPONENT_JOHN_AND_JAY_3, OPPONENT_JOHN_AND_JAY_4, OPPONENT_JOHN_AND_JAY_5}, + MAP_GROUP_METEOR_FALLS_1F_2R, + MAP_ID_METEOR_FALLS_1F_2R, + }, + { + {OPPONENT_BRANDON_1, OPPONENT_BRANDON_2, OPPONENT_BRANDON_3, OPPONENT_BRANDON_4, OPPONENT_BRANDON_5}, + MAP_GROUP_ROUTE120, + MAP_ID_ROUTE120, + }, + { + {OPPONENT_CAMERON_1, OPPONENT_CAMERON_2, OPPONENT_CAMERON_3, OPPONENT_CAMERON_4, OPPONENT_CAMERON_5}, + MAP_GROUP_ROUTE123, + MAP_ID_ROUTE123, + }, + { + {OPPONENT_JACKI_1, OPPONENT_JACKI_2, OPPONENT_JACKI_3, OPPONENT_JACKI_4, OPPONENT_JACKI_5}, + MAP_GROUP_ROUTE123, + MAP_ID_ROUTE123, + }, + { + {OPPONENT_WALTER_1, OPPONENT_WALTER_2, OPPONENT_WALTER_3, OPPONENT_WALTER_4, OPPONENT_WALTER_5}, + MAP_GROUP_ROUTE121, + MAP_ID_ROUTE121, + }, + { + {OPPONENT_KAREN_1, OPPONENT_KAREN_2, OPPONENT_KAREN_3, OPPONENT_KAREN_4, OPPONENT_KAREN_5}, + MAP_GROUP_ROUTE116, + MAP_ID_ROUTE116, + }, + { + {OPPONENT_JERRY_1, OPPONENT_JERRY_2, OPPONENT_JERRY_3, OPPONENT_JERRY_4, OPPONENT_JERRY_5}, + MAP_GROUP_ROUTE116, + MAP_ID_ROUTE116, + }, + { + {OPPONENT_ANNA_AND_MEG_1, OPPONENT_ANNA_AND_MEG_2, OPPONENT_ANNA_AND_MEG_3, OPPONENT_ANNA_AND_MEG_4, OPPONENT_ANNA_AND_MEG_5}, + MAP_GROUP_ROUTE117, + MAP_ID_ROUTE117, + }, + { + {OPPONENT_ISABEL_1, OPPONENT_ISABEL_2, OPPONENT_ISABEL_3, OPPONENT_ISABEL_4, OPPONENT_ISABEL_5}, + MAP_GROUP_ROUTE110, + MAP_ID_ROUTE110, + }, + { + {OPPONENT_MIGUEL_1, OPPONENT_MIGUEL_2, OPPONENT_MIGUEL_3, OPPONENT_MIGUEL_4, OPPONENT_MIGUEL_5}, + MAP_GROUP_ROUTE103, + MAP_ID_ROUTE103, + }, + { + {OPPONENT_TIMOTHY_1, OPPONENT_TIMOTHY_2, OPPONENT_TIMOTHY_3, OPPONENT_TIMOTHY_4, OPPONENT_TIMOTHY_5}, + MAP_GROUP_ROUTE115, + MAP_ID_ROUTE115, + }, + { + {OPPONENT_SHELBY_1, OPPONENT_SHELBY_2, OPPONENT_SHELBY_3, OPPONENT_SHELBY_4, OPPONENT_SHELBY_5}, + MAP_GROUP_MT_CHIMNEY, + MAP_ID_MT_CHIMNEY, + }, + { + {OPPONENT_CALVIN_1, OPPONENT_CALVIN_2, OPPONENT_CALVIN_3, OPPONENT_CALVIN_4, OPPONENT_CALVIN_5}, + MAP_GROUP_ROUTE102, + MAP_ID_ROUTE102, + }, + { + {OPPONENT_ELLIOT_1, OPPONENT_ELLIOT_2, OPPONENT_ELLIOT_3, OPPONENT_ELLIOT_4, OPPONENT_ELLIOT_5}, + MAP_GROUP_ROUTE106, + MAP_ID_ROUTE106, + }, + { + {OPPONENT_ABIGAIL_1, OPPONENT_ABIGAIL_2, OPPONENT_ABIGAIL_3, OPPONENT_ABIGAIL_4, OPPONENT_ABIGAIL_5}, + MAP_GROUP_ROUTE110, + MAP_ID_ROUTE110, + }, + { + {OPPONENT_BENJAMIN_1, OPPONENT_BENJAMIN_2, OPPONENT_BENJAMIN_3, OPPONENT_BENJAMIN_4, OPPONENT_BENJAMIN_5}, + MAP_GROUP_ROUTE110, + MAP_ID_ROUTE110, + }, + { + {OPPONENT_ISAIAH_1, OPPONENT_ISAIAH_2, OPPONENT_ISAIAH_3, OPPONENT_ISAIAH_4, OPPONENT_ISAIAH_5}, + MAP_GROUP_ROUTE128, + MAP_ID_ROUTE128, + }, + { + {OPPONENT_KATELYN_1, OPPONENT_KATELYN_2, OPPONENT_KATELYN_3, OPPONENT_KATELYN_4, OPPONENT_KATELYN_5}, + MAP_GROUP_ROUTE128, + MAP_ID_ROUTE128, + }, + { + {OPPONENT_MARIA_1, OPPONENT_MARIA_2, OPPONENT_MARIA_3, OPPONENT_MARIA_4, OPPONENT_MARIA_5}, + MAP_GROUP_ROUTE117, + MAP_ID_ROUTE117, + }, + { + {OPPONENT_DYLAN_1, OPPONENT_DYLAN_2, OPPONENT_DYLAN_3, OPPONENT_DYLAN_4, OPPONENT_DYLAN_5}, + MAP_GROUP_ROUTE117, + MAP_ID_ROUTE117, + }, + { + {OPPONENT_NICOLAS_1, OPPONENT_NICOLAS_2, OPPONENT_NICOLAS_3, OPPONENT_NICOLAS_4, OPPONENT_NICOLAS_5}, + MAP_GROUP_METEOR_FALLS_1F_2R, + MAP_ID_METEOR_FALLS_1F_2R, + }, + { + {OPPONENT_ROBERT_1, OPPONENT_ROBERT_2, OPPONENT_ROBERT_3, OPPONENT_ROBERT_4, OPPONENT_ROBERT_5}, + MAP_GROUP_ROUTE120, + MAP_ID_ROUTE120, + }, + { + {OPPONENT_LAO_1, OPPONENT_LAO_2, OPPONENT_LAO_3, OPPONENT_LAO_4, OPPONENT_LAO_5}, + MAP_GROUP_ROUTE113, + MAP_ID_ROUTE113, + }, + { + {OPPONENT_CYNDY_1, OPPONENT_CYNDY_2, OPPONENT_CYNDY_3, OPPONENT_CYNDY_4, OPPONENT_CYNDY_5}, + MAP_GROUP_ROUTE115, + MAP_ID_ROUTE115, + }, + { + {OPPONENT_MADELINE_1, OPPONENT_MADELINE_2, OPPONENT_MADELINE_3, OPPONENT_MADELINE_4, OPPONENT_MADELINE_5}, + MAP_GROUP_ROUTE113, + MAP_ID_ROUTE113, + }, + { + {OPPONENT_JENNY_1, OPPONENT_JENNY_2, OPPONENT_JENNY_3, OPPONENT_JENNY_4, OPPONENT_JENNY_5}, + MAP_GROUP_ROUTE124, + MAP_ID_ROUTE124, + }, + { + {OPPONENT_DIANA_1, OPPONENT_DIANA_2, OPPONENT_DIANA_3, OPPONENT_DIANA_4, OPPONENT_DIANA_5}, + MAP_GROUP_JAGGED_PASS, + MAP_ID_JAGGED_PASS, + }, + { + {OPPONENT_AMY_AND_LIV_1, OPPONENT_AMY_AND_LIV_2, OPPONENT_AMY_AND_LIV_4, OPPONENT_AMY_AND_LIV_5, OPPONENT_AMY_AND_LIV_6}, + MAP_GROUP_ROUTE103, + MAP_ID_ROUTE103, + }, + { + {OPPONENT_ERNEST_1, OPPONENT_ERNEST_2, OPPONENT_ERNEST_3, OPPONENT_ERNEST_4, OPPONENT_ERNEST_5}, + MAP_GROUP_ROUTE125, + MAP_ID_ROUTE125, + }, + { + {OPPONENT_EDWIN_1, OPPONENT_EDWIN_2, OPPONENT_EDWIN_3, OPPONENT_EDWIN_4, OPPONENT_EDWIN_5}, + MAP_GROUP_ROUTE110, + MAP_ID_ROUTE110, + }, + { + {OPPONENT_LYDIA_1, OPPONENT_LYDIA_2, OPPONENT_LYDIA_3, OPPONENT_LYDIA_4, OPPONENT_LYDIA_5}, + MAP_GROUP_ROUTE117, + MAP_ID_ROUTE117, + }, + { + {OPPONENT_ISAAC_1, OPPONENT_ISAAC_2, OPPONENT_ISAAC_3, OPPONENT_ISAAC_4, OPPONENT_ISAAC_5}, + MAP_GROUP_ROUTE117, + MAP_ID_ROUTE117, + }, + { + {OPPONENT_CATHERINE_1, OPPONENT_CATHERINE_2, OPPONENT_CATHERINE_3, OPPONENT_CATHERINE_4, OPPONENT_CATHERINE_5}, + MAP_GROUP_ROUTE119, + MAP_ID_ROUTE119, + }, + { + {OPPONENT_JACKSON_1, OPPONENT_JACKSON_2, OPPONENT_JACKSON_3, OPPONENT_JACKSON_4, OPPONENT_JACKSON_5}, + MAP_GROUP_ROUTE119, + MAP_ID_ROUTE119, + }, + { + {OPPONENT_HALEY_1, OPPONENT_HALEY_2, OPPONENT_HALEY_3, OPPONENT_HALEY_4, OPPONENT_HALEY_5}, + MAP_GROUP_ROUTE104, + MAP_ID_ROUTE104, + }, + { + {OPPONENT_JAMES_1, OPPONENT_JAMES_2, OPPONENT_JAMES_3, OPPONENT_JAMES_4, OPPONENT_JAMES_5}, + MAP_GROUP_PETALBURG_WOODS, + MAP_ID_PETALBURG_WOODS, + }, + { + {OPPONENT_TRENT_1, OPPONENT_TRENT_2, OPPONENT_TRENT_3, OPPONENT_TRENT_4, OPPONENT_TRENT_5}, + MAP_GROUP_ROUTE112, + MAP_ID_ROUTE112, + }, + { + {OPPONENT_LOIS_AND_HAL_1, OPPONENT_LOIS_AND_HAL_2, OPPONENT_LOIS_AND_HAL_3, OPPONENT_LOIS_AND_HAL_4, OPPONENT_LOIS_AND_HAL_5}, + MAP_GROUP_ABANDONED_SHIP_ROOMS2_1F, + MAP_ID_ABANDONED_SHIP_ROOMS2_1F, + }, + { + {OPPONENT_WALLY_3, OPPONENT_WALLY_4, OPPONENT_WALLY_5, OPPONENT_WALLY_6, OPPONENT_NONE}, + MAP_GROUP_VICTORY_ROAD_1F, + MAP_ID_VICTORY_ROAD_1F, + }, +}; + +static const u16 sBadgeFlags[] = {BADGE01_GET, BADGE02_GET, BADGE03_GET, BADGE04_GET, BADGE05_GET, BADGE06_GET, BADGE07_GET, BADGE08_GET}; + +static void DoStandardWildBattle(void); +static void DoSafariBattle(void); +static void SetTrainerFlagsAfterTrainerEyeRematch(void); +static void CB2_EndWildBattle(void); +static void CB2_EndScriptedWildBattle(void); +static u8 GetWildBattleTransition(void); +static u8 GetTrainerBattleTransition(void); +static void CB2_GiveStarter(void); +static void CB2_StartFirstBattle(void); +static void CB2_EndFirstBattle(void); +static bool32 IsPlayerDefeated(u32 a1); + +#define tState data[0] +#define tTransition data[1] + +static void Task_BattleStart(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (tState) + { + case 0: + if (!FieldPoisonEffectIsRunning()) // is poison not active? + { + BattleTransition_StartOnField(tTransition); + tState++; // go to case 1. + } + break; + case 1: + if (IsBattleTransitionDone() == TRUE) + { + SetMainCallback2(sub_800E7C4); + prev_quest_postbuffer_cursor_backup_reset(); + overworld_poison_timer_set(); + DestroyTask(taskId); + } + break; + } +} + +static void CreateBattleStartTask(u8 transition, u16 song) +{ + u8 taskId = CreateTask(Task_BattleStart, 1); + + gTasks[taskId].tTransition = transition; + current_map_music_set__default_for_battle(song); +} + +#undef tState +#undef tTransition + +void BattleSetup_StartWildBattle(void) +{ + if (GetSafariZoneFlag()) + DoSafariBattle(); + else + DoStandardWildBattle(); +} + +static void DoStandardWildBattle(void) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + sub_80597F4(); + gMain.savedCallback = CB2_EndWildBattle; + gBattleTypeFlags = 0; + CreateBattleStartTask(GetWildBattleTransition(), 0); + IncrementGameStat(7); + IncrementGameStat(8); +} + +void BattleSetup_StartRoamerBattle(void) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + sub_80597F4(); + gMain.savedCallback = CB2_EndWildBattle; + gBattleTypeFlags = BATTLE_TYPE_ROAMER; + CreateBattleStartTask(GetWildBattleTransition(), 0); + IncrementGameStat(7); + IncrementGameStat(8); +} + +static void DoSafariBattle(void) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + sub_80597F4(); + gMain.savedCallback = sub_80C824C; + gBattleTypeFlags = BATTLE_TYPE_SAFARI; + CreateBattleStartTask(GetWildBattleTransition(), 0); +} + +static void StartTheBattle(void) +{ + CreateBattleStartTask(GetTrainerBattleTransition(), 0); + IncrementGameStat(7); + IncrementGameStat(9); +} + +//Initiates battle where Wally catches Ralts +void ScrSpecial_StartWallyTutorialBattle(void) +{ + CreateMaleMon(&gEnemyParty[0], SPECIES_RALTS, 5); + ScriptContext2_Enable(); + gMain.savedCallback = c2_exit_to_overworld_1_continue_scripts_restart_music; + gBattleTypeFlags = BATTLE_TYPE_WALLY_TUTORIAL; + CreateBattleStartTask(B_TRANSITION_SLICE, 0); +} + +void BattleSetup_StartScriptedWildBattle(void) +{ + ScriptContext2_Enable(); + gMain.savedCallback = CB2_EndScriptedWildBattle; + gBattleTypeFlags = 0; + CreateBattleStartTask(GetWildBattleTransition(), 0); + IncrementGameStat(7); + IncrementGameStat(8); +} + +void ScrSpecial_StartSouthernIslandBattle(void) +{ + ScriptContext2_Enable(); + gMain.savedCallback = CB2_EndScriptedWildBattle; + gBattleTypeFlags = BATTLE_TYPE_LEGENDARY; + CreateBattleStartTask(GetWildBattleTransition(), 0); + IncrementGameStat(7); + IncrementGameStat(8); +} + +void ScrSpecial_StartRayquazaBattle(void) +{ + ScriptContext2_Enable(); + gMain.savedCallback = CB2_EndScriptedWildBattle; + gBattleTypeFlags = BATTLE_TYPE_LEGENDARY; + CreateBattleStartTask(B_TRANSITION_BLUR, BGM_BATTLE34); + IncrementGameStat(7); + IncrementGameStat(8); +} + +void ScrSpecial_StartGroudonKyogreBattle(void) +{ + ScriptContext2_Enable(); + gMain.savedCallback = CB2_EndScriptedWildBattle; + gBattleTypeFlags = BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_KYOGRE_GROUDON; + if (gGameVersion == VERSION_RUBY) + CreateBattleStartTask(B_TRANSITION_SHARDS, BGM_BATTLE34); // GROUDON + else + CreateBattleStartTask(B_TRANSITION_RIPPLE, BGM_BATTLE34); // KYOGRE + IncrementGameStat(7); + IncrementGameStat(8); +} + +void ScrSpecial_StartRegiBattle(void) +{ + ScriptContext2_Enable(); + gMain.savedCallback = CB2_EndScriptedWildBattle; + gBattleTypeFlags = BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_REGI; + CreateBattleStartTask(B_TRANSITION_GRID_SQUARES, BGM_BATTLE36); + IncrementGameStat(7); + IncrementGameStat(8); +} + +static void CB2_EndWildBattle(void) +{ + CpuFill16(0, (void *)BG_PLTT, BG_PLTT_SIZE); + ResetOamRange(0, 128); + + if (IsPlayerDefeated(gBattleOutcome) == TRUE) + { + SetMainCallback2(CB2_WhiteOut); + } + else + { + SetMainCallback2(c2_exit_to_overworld_2_switch); + gFieldCallback = sub_8080E44; + } +} + +void CB2_EndScriptedWildBattle(void) +{ + CpuFill16(0, (void *)BG_PLTT, BG_PLTT_SIZE); + ResetOamRange(0, 128); + + if (IsPlayerDefeated(gBattleOutcome) == TRUE) + SetMainCallback2(CB2_WhiteOut); + else + SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); +} + +s8 BattleSetup_GetTerrain(void) +{ + u16 tileBehavior; + s16 x, y; + + PlayerGetDestCoords(&x, &y); + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + + if (MetatileBehavior_IsTallGrass(tileBehavior)) + return BATTLE_TERRAIN_GRASS; + if (MetatileBehavior_IsLongGrass(tileBehavior)) + return BATTLE_TERRAIN_LONG_GRASS; + if (MetatileBehavior_IsSandOrDeepSand(tileBehavior)) + return BATTLE_TERRAIN_SAND; + switch (gMapHeader.mapType) + { + case MAP_TYPE_TOWN: + case MAP_TYPE_CITY: + case MAP_TYPE_ROUTE: + break; + case MAP_TYPE_UNDERGROUND: + if (sub_80574C4(tileBehavior)) + return BATTLE_TERRAIN_BUILDING; + if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior)) + return BATTLE_TERRAIN_POND; + return BATTLE_TERRAIN_CAVE; + case MAP_TYPE_INDOOR: + case MAP_TYPE_SECRET_BASE: + return BATTLE_TERRAIN_BUILDING; + case MAP_TYPE_UNDERWATER: + return BATTLE_TERRAIN_UNDERWATER; + case MAP_TYPE_6: + if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior)) + return BATTLE_TERRAIN_WATER; + return BATTLE_TERRAIN_PLAIN; + } + if (sub_8057568(tileBehavior)) + return BATTLE_TERRAIN_WATER; + if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior)) + return BATTLE_TERRAIN_POND; + if (sub_80574D8(tileBehavior)) + return BATTLE_TERRAIN_MOUNTAIN; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + { + if (sub_8057450(tileBehavior)) + return BATTLE_TERRAIN_POND; + if (MetatileBehavior_IsBridge(tileBehavior) == TRUE) + return BATTLE_TERRAIN_WATER; + } + if (gSaveBlock1.location.mapGroup == MAP_GROUP_ROUTE113 && gSaveBlock1.location.mapNum == MAP_ID_ROUTE113) + return BATTLE_TERRAIN_SAND; + if (GetSav1Weather() == 8) + return BATTLE_TERRAIN_SAND; + return BATTLE_TERRAIN_PLAIN; +} + +static s8 GetBattleTransitionTypeByMap(void) +{ + u16 tileBehavior; + s16 x, y; + + PlayerGetDestCoords(&x, &y); + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + if (Overworld_GetFlashLevel()) + return 2; + if (!MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior)) + { + switch (gMapHeader.mapType) + { + case MAP_TYPE_UNDERGROUND: + return 1; + case MAP_TYPE_UNDERWATER: + return 3; + default: + return 0; + } + } + return 3; +} + +static u16 GetSumOfPlayerPartyLevel(u8 numMons) +{ + u8 sum = 0; + int i; + + for (i = 0; i < 6; i++) + { + u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2); + + if (species != SPECIES_EGG && species != SPECIES_NONE && GetMonData(&gPlayerParty[i], MON_DATA_HP) != 0) + { + sum += GetMonData(&gPlayerParty[i], MON_DATA_LEVEL); + numMons--; + if (numMons == 0) + break; + } + } + return sum; +} + +static u8 GetSumOfEnemyPartyLevel(u16 opponentId, u8 numMons) +{ + u8 i; + u8 sum; + u32 count = numMons; + void *party; + + if (gTrainers[opponentId].partySize < count) + count = gTrainers[opponentId].partySize; + + sum = 0; + + switch (gTrainers[opponentId].partyFlags) + { + case 0: + party = gTrainers[opponentId].party; + for (i = 0; i < count; i++) + sum += ((struct TrainerPartyMember0 *)party)[i].level; + break; + case 1: + party = gTrainers[opponentId].party; + for (i = 0; i < count; i++) + sum += ((struct TrainerPartyMember1 *)party)[i].level; + break; + case 2: + party = gTrainers[opponentId].party; + for (i = 0; i < count; i++) + sum += ((struct TrainerPartyMember2 *)party)[i].level; + break; + case 3: + party = gTrainers[opponentId].party; + for (i = 0; i < count; i++) + sum += ((struct TrainerPartyMember3 *)party)[i].level; + break; + } + + return sum; +} + +static u8 GetWildBattleTransition(void) +{ + u8 transitionType = GetBattleTransitionTypeByMap(); + u8 enemyLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL); + u8 playerLevel = GetSumOfPlayerPartyLevel(1); + + if (enemyLevel < playerLevel) + return gBattleTransitionTable_Wild[transitionType][0]; + else + return gBattleTransitionTable_Wild[transitionType][1]; +} + +static u8 GetTrainerBattleTransition(void) +{ + const struct Trainer *trainer; + u8 minPartyCount; + u8 transitionType; + u8 enemyLevel; + u8 playerLevel; + + if (gTrainerBattleOpponent == 1024) // link battle? + return B_TRANSITION_STEVEN; + + trainer = gTrainers; + + if (trainer[gTrainerBattleOpponent].trainerClass == 24) // league? + { + if (gTrainerBattleOpponent == 261) + return B_TRANSITION_SYDNEY; + if (gTrainerBattleOpponent == 262) + return B_TRANSITION_PHOEBE; + if (gTrainerBattleOpponent == 263) + return B_TRANSITION_GLACIA; + if (gTrainerBattleOpponent == 264) + return B_TRANSITION_DRAKE; + return B_TRANSITION_STEVEN; + } + + if (trainer[gTrainerBattleOpponent].trainerClass == 32) // team leader? + return B_TRANSITION_STEVEN; + + if (trainer[gTrainerBattleOpponent].doubleBattle == TRUE) + minPartyCount = 2; // double battles always at least have 2 pokemon. + else + minPartyCount = 1; + + transitionType = GetBattleTransitionTypeByMap(); + enemyLevel = GetSumOfEnemyPartyLevel(gTrainerBattleOpponent, minPartyCount); + playerLevel = GetSumOfPlayerPartyLevel(minPartyCount); + if (enemyLevel < playerLevel) // is wild mon level than the player's mon level? + return gBattleTransitionTable_Trainer[transitionType][0]; + else + return gBattleTransitionTable_Trainer[transitionType][1]; +} + +u8 BattleSetup_GetBattleTowerBattleTransition(void) +{ + u8 enemyLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL); + u8 playerLevel = GetSumOfPlayerPartyLevel(1); + + if (enemyLevel < playerLevel) + return B_TRANSITION_POKEBALLS_TRAIL; + else + return B_TRANSITION_BIG_POKEBALL; +} + +void ScrSpecial_ChooseStarter(void) +{ + SetMainCallback2(CB2_ChooseStarter); + gMain.savedCallback = CB2_GiveStarter; +} + +static void CB2_GiveStarter(void) +{ + u16 starterPoke; + + *GetVarPointer(0x4023) = gScriptResult; + starterPoke = GetStarterPokemon(gScriptResult); + ScriptGiveMon(starterPoke, 5, 0, 0, 0, 0); + ResetTasks(); + sub_80408BC(); + SetMainCallback2(CB2_StartFirstBattle); + BattleTransition_Start(0); +} + +static void CB2_StartFirstBattle(void) +{ + UpdatePaletteFade(); + RunTasks(); + + if (IsBattleTransitionDone() == TRUE) + { + gBattleTypeFlags = BATTLE_TYPE_FIRST_BATTLE; + gMain.savedCallback = CB2_EndFirstBattle; + SetMainCallback2(sub_800E7C4); + prev_quest_postbuffer_cursor_backup_reset(); + overworld_poison_timer_set(); + IncrementGameStat(7); + IncrementGameStat(8); + } +} + +static void CB2_EndFirstBattle(void) +{ + sav1_reset_battle_music_maybe(); + SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); +} + +static u32 TrainerBattleLoadArg32(const u8 *ptr) +{ + return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); +} + +static u16 TrainerBattleLoadArg16(const u8 *ptr) +{ + return ptr[0] | (ptr[1] << 8); +} + +static u8 TrainerBattleLoadArg8(const u8 *ptr) +{ + return ptr[0]; +} + +static u16 CurrentOpponentTrainerFlag(void) +{ + return TRAINER_FLAG_START + gTrainerBattleOpponent; +} + +static bool32 IsPlayerDefeated(u32 battleOutcome) +{ + switch (battleOutcome) + { + case 2: + case 3: + return TRUE; + case 1: + case 4: + case 5: + case 6: + case 7: + return FALSE; + } + return FALSE; +} + +static void sub_80822BC(void) +{ + sTrainerBattleMode = 0; + gTrainerBattleOpponent = 0; + sTrainerMapObjectLocalId = 0; + sTrainerIntroSpeech = 0; + sTrainerDefeatSpeech = 0; + sTrainerVictorySpeech = 0; + sTrainerCannotBattleSpeech = 0; + sTrainerBattleScriptRetAddr = 0; + sTrainerBattleEndScript = 0; +} + +static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, const u8 *data) +{ + while (1) + { + switch (specs->ptrType) + { + case TRAINER_PARAM_LOAD_VAL_8BIT: + *(u8 *)specs->varPtr = TrainerBattleLoadArg8(data); + data += 1; + break; + case TRAINER_PARAM_LOAD_VAL_16BIT: + *(u16 *)specs->varPtr = TrainerBattleLoadArg16(data); + data += 2; + break; + case TRAINER_PARAM_LOAD_VAL_32BIT: + *(u32 *)specs->varPtr = TrainerBattleLoadArg32(data); + data += 4; + break; + case TRAINER_PARAM_CLEAR_VAL_8BIT: + *(u8 *)specs->varPtr = 0; + break; + case TRAINER_PARAM_CLEAR_VAL_16BIT: + *(u16 *)specs->varPtr = 0; + break; + case TRAINER_PARAM_CLEAR_VAL_32BIT: + *(u32 *)specs->varPtr = 0; + break; + case TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR: + *(const u8 **)specs->varPtr = data; + return; + } + specs++; + } +} + +static void battle_80801F0(void) +{ + if (sTrainerMapObjectLocalId) + { + gScriptLastTalked = sTrainerMapObjectLocalId; + gSelectedMapObject = GetFieldObjectIdByLocalIdAndMap(sTrainerMapObjectLocalId, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + } +} + +u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data) +{ + sub_80822BC(); + sTrainerBattleMode = TrainerBattleLoadArg8(data); + + switch (sTrainerBattleMode) + { + case 3: + TrainerBattleLoadArgs(gTrainerBattleSpecs_3, data); + return gUnknown_0819F878; + case 4: + TrainerBattleLoadArgs(gTrainerBattleSpecs_2, data); + battle_80801F0(); + return gUnknown_0819F840; + case 1: + case 2: + TrainerBattleLoadArgs(gTrainerBattleSpecs_1, data); + battle_80801F0(); + return gUnknown_0819F818; + case 6: + case 8: + TrainerBattleLoadArgs(gTrainerBattleSpecs_4, data); + battle_80801F0(); + return gUnknown_0819F840; + case 7: + TrainerBattleLoadArgs(gTrainerBattleSpecs_2, data); + battle_80801F0(); + gTrainerBattleOpponent = sub_8082C4C(gTrainerBattleOpponent); + return gUnknown_0819F8AE; + case 5: + TrainerBattleLoadArgs(gTrainerBattleSpecs_0, data); + battle_80801F0(); + gTrainerBattleOpponent = sub_8082C4C(gTrainerBattleOpponent); + return gUnknown_0819F887; + default: + TrainerBattleLoadArgs(gTrainerBattleSpecs_0, data); + battle_80801F0(); + return gUnknown_0819F818; + } +} + +void TrainerWantsBattle(u8 trainerMapObjId, u8 *trainerScript) +{ + gSelectedMapObject = trainerMapObjId; + gScriptLastTalked = gMapObjects[trainerMapObjId].localId; + BattleSetup_ConfigureTrainerBattle(trainerScript + 1); + ScriptContext1_SetupScript(gUnknown_0819F80B); + ScriptContext2_Enable(); +} + +bool32 GetTrainerFlagFromScriptPointer(u8 *data) +{ + u32 flag = TrainerBattleLoadArg16(data + 2); + return FlagGet(TRAINER_FLAG_START + flag); +} + +void sub_8082524(void) +{ + struct MapObject *mapObject = &gMapObjects[gSelectedMapObject]; + + npc_set_running_behaviour_etc(mapObject, npc_running_behaviour_by_direction(mapObject->mapobj_unk_18)); +} + +u8 ScrSpecial_GetTrainerBattleMode(void) +{ + return sTrainerBattleMode; +} + +u8 ScrSpecial_HasTrainerBeenFought(void) +{ + return FlagGet(CurrentOpponentTrainerFlag()); +} + +void SetCurrentTrainerBattledFlag(void) +{ + FlagSet(CurrentOpponentTrainerFlag()); +} + +void unref_sub_8082590(void) +{ + FlagSet(CurrentOpponentTrainerFlag()); // duplicate function +} + +u8 HasTrainerAlreadyBeenFought(u16 flag) +{ + return FlagGet(TRAINER_FLAG_START + flag); +} + +void trainer_flag_set(u16 flag) +{ + FlagSet(TRAINER_FLAG_START + flag); +} + +void trainer_flag_clear(u16 flag) +{ + FlagClear(TRAINER_FLAG_START + flag); +} + +void BattleSetup_StartTrainerBattle(void) +{ + gBattleTypeFlags = BATTLE_TYPE_TRAINER; + gMain.savedCallback = sub_808260C; + StartTheBattle(); + ScriptContext1_Stop(); +} + +void sub_808260C(void) +{ + if (gTrainerBattleOpponent == 1024) + { + SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); // link battle? + } + else if (IsPlayerDefeated(gBattleOutcome) == TRUE) + { + SetMainCallback2(CB2_WhiteOut); + } + else + { + SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetCurrentTrainerBattledFlag(); + } +} + +void CB2_EndTrainerEyeRematchBattle(void) +{ + if (gTrainerBattleOpponent == 1024) + { + SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); // link battle? + } + else if (IsPlayerDefeated(gBattleOutcome) == TRUE) + { + SetMainCallback2(CB2_WhiteOut); + } + else + { + SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetCurrentTrainerBattledFlag(); + SetTrainerFlagsAfterTrainerEyeRematch(); + } +} + +void ScrSpecial_StartTrainerEyeRematch(void) +{ + gBattleTypeFlags = BATTLE_TYPE_TRAINER; + gMain.savedCallback = CB2_EndTrainerEyeRematchBattle; + StartTheBattle(); + ScriptContext1_Stop(); +} + +static u8 *GetTrainerIntroSpeech(void); +static u8 *GetTrainerNonBattlingSpeech(void); + +void ScrSpecial_ShowTrainerIntroSpeech(void) +{ + ShowFieldMessage(GetTrainerIntroSpeech()); +} + +u8 *BattleSetup_GetScriptAddrAfterBattle(void) +{ + if (sTrainerBattleScriptRetAddr) + return sTrainerBattleScriptRetAddr; + else + return gUnknown_081C6C02; +} + +u8 *BattleSetup_GetTrainerPostBattleScript(void) +{ + if (sTrainerBattleEndScript) + return sTrainerBattleEndScript; + else + return gUnknown_081C6C02; +} + +void ScrSpecial_ShowTrainerNonBattlingSpeech(void) +{ + ShowFieldMessage(GetTrainerNonBattlingSpeech()); +} + +void PlayTrainerEncounterMusic(void) +{ + u16 music; + + if (sTrainerBattleMode != 1 && sTrainerBattleMode != 8) + { + switch (sub_803FC58(gTrainerBattleOpponent)) + { + case TRAINER_ENCOUNTER_MUSIC_MALE: + music = BGM_BOYEYE; + break; + case TRAINER_ENCOUNTER_MUSIC_FEMALE: + music = BGM_GIRLEYE; + break; + case TRAINER_ENCOUNTER_MUSIC_GIRL: + music = BGM_SYOUJOEYE; + break; + case TRAINER_ENCOUNTER_MUSIC_INTENSE: + music = BGM_HAGESHII; + break; + case TRAINER_ENCOUNTER_MUSIC_COOL: + music = BGM_KAKKOII; + break; + case TRAINER_ENCOUNTER_MUSIC_AQUA: + music = BGM_AQA_0; + break; + case TRAINER_ENCOUNTER_MUSIC_MAGMA: + music = BGM_MGM0; + break; + case TRAINER_ENCOUNTER_MUSIC_SWIMMER: + music = BGM_SWIMEYE; + break; + case TRAINER_ENCOUNTER_MUSIC_TWINS: + music = BGM_HUTAGO; + break; + case TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR: + music = BGM_SITENNOU; + break; + case TRAINER_ENCOUNTER_MUSIC_HIKER: + music = BGM_YAMA_EYE; + break; + case TRAINER_ENCOUNTER_MUSIC_INTERVIEWER: + music = BGM_INTER_V; + break; + case TRAINER_ENCOUNTER_MUSIC_RICH: + music = BGM_TEST; + break; + default: + music = BGM_AYASII; + } + PlayNewMapMusic(music); + } +} + +//Returns an empty string if a null pointer was passed, otherwise returns str +static u8 *SanitizeString(const u8 *str) +{ + if (str) + return (u8 *) str; + else + return (u8 *) gOtherText_CancelWithTerminator; +} + +static u8 *GetTrainerIntroSpeech(void) +{ + return SanitizeString(sTrainerIntroSpeech); +} + +u8 *sub_8082830(void) +{ + u8 *str; + + if (gTrainerBattleOpponent == 1024) + str = sub_80BCCE8(); + else + str = sTrainerDefeatSpeech; + + StringExpandPlaceholders(gStringVar4, SanitizeString(str)); + return gStringVar4; +} + +u8 *unref_sub_808286C(void) +{ + return SanitizeString(sTrainerVictorySpeech); +} + +static u8 *GetTrainerNonBattlingSpeech(void) +{ + return SanitizeString(sTrainerCannotBattleSpeech); +} + +s32 sub_8082894(const struct TrainerEyeTrainer *trainers, u16 opponentId) +{ + s32 i; + + for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++) + { + if (trainers[i].opponentIDs[0] == opponentId) + return i; + } + return -1; +} + +s32 sub_80828B8(const struct TrainerEyeTrainer *trainers, u16 opponentId) +{ + s32 i; + s32 j; + + for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++) + { + for (j = 0; j < 5 && trainers[i].opponentIDs[j] != 0; j++) + { + if (trainers[i].opponentIDs[j] == opponentId) + return i; + } + } + return -1; +} + +bool32 UpdateRandomTrainerEyeRematches(const struct TrainerEyeTrainer *trainers, u16 mapGroup, u16 mapNum) +{ + int i; + bool32 ret = FALSE; + + for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++) + { + if (trainers[i].mapGroup == mapGroup && trainers[i].mapNum == mapNum) + { + if (gSaveBlock1.trainerRematches[i] != 0) + { + // Trainer already wants rematch. Don't bother updating it + ret = TRUE; + } + else if (HasTrainerAlreadyBeenFought(trainers[i].opponentIDs[0]) == TRUE + && (Random() % 100) <= 30) // 31% chance of getting a rematch + { + int rematches = 1; + + while (rematches < 5 && trainers[i].opponentIDs[rematches] != 0 + && HasTrainerAlreadyBeenFought(trainers[i].opponentIDs[rematches])) + rematches++; + gSaveBlock1.trainerRematches[i] = rematches; + ret = TRUE; + } + } + } + return ret; +} + +s32 sub_80829A8(const struct TrainerEyeTrainer *trainers, u16 mapGroup, u16 mapNum) +{ + s32 i; + + for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++) + { + if (trainers[i].mapGroup == mapGroup && trainers[i].mapNum == mapNum && gSaveBlock1.trainerRematches[i]) + return 1; + } + return 0; +} + +s32 sub_80829E8(const struct TrainerEyeTrainer *trainers, u16 mapGroup, u16 mapNum) +{ + s32 i; + + for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++) + { + if (trainers[i].mapGroup == mapGroup && trainers[i].mapNum == mapNum) + return 1; + } + return 0; +} + +bool8 sub_8082A18(const struct TrainerEyeTrainer *trainers, u16 opponentId) +{ + s32 trainerEyeIndex = sub_8082894(trainers, opponentId); + + if (trainerEyeIndex != -1 && trainerEyeIndex < 100 && gSaveBlock1.trainerRematches[trainerEyeIndex]) + return TRUE; + else + return FALSE; +} + +bool8 GetTrainerEyeRematchFlag(const struct TrainerEyeTrainer *trainers, u16 opponentId) +{ + s32 trainerEyeIndex = sub_80828B8(trainers, opponentId); + + if (trainerEyeIndex != -1 && trainerEyeIndex < 100 && gSaveBlock1.trainerRematches[trainerEyeIndex]) + return TRUE; + else + return FALSE; +} + +u16 sub_8082A90(const struct TrainerEyeTrainer *trainers, u16 opponentId) +{ + int i; + const struct TrainerEyeTrainer *trainer; + s32 trainerEyeIndex = sub_8082894(trainers, opponentId); + + if (trainerEyeIndex == -1) + return 0; + trainer = &trainers[trainerEyeIndex]; + for (i = 1; i < 5; i++) + { + if (!trainer->opponentIDs[i]) + return trainer->opponentIDs[i - 1]; + if (!HasTrainerAlreadyBeenFought(trainer->opponentIDs[i])) + return trainer->opponentIDs[i]; + } + return trainer->opponentIDs[4]; +} + +void ClearTrainerEyeRematchFlag(const struct TrainerEyeTrainer *trainers, u16 opponentId) +{ + s32 trainerEyeIndex = sub_80828B8(trainers, opponentId); + + if (trainerEyeIndex != -1) + gSaveBlock1.trainerRematches[trainerEyeIndex] = 0; +} + +bool8 sub_8082B10(const struct TrainerEyeTrainer *trainers, u16 opponentId) +{ + s32 trainerEyeIndex = sub_8082894(trainers, opponentId); + + if (trainerEyeIndex != -1 && HasTrainerAlreadyBeenFought(trainers[trainerEyeIndex].opponentIDs[1])) + return TRUE; + else + return FALSE; +} + +bool32 sub_8082B44(void) +{ + int badgeCount = 0; + u32 i; + + for (i = 0; i < 8; i++) + { + if (FlagGet(sBadgeFlags[i]) == TRUE) + { + badgeCount++; + if (badgeCount >= 5) + return TRUE; + } + } + return FALSE; +} + +void sub_8082B78(void) +{ + if (sub_8082B44()) + { + if (gSaveBlock1.trainerRematchStepCounter >= TRAINER_REMATCH_STEPS) + gSaveBlock1.trainerRematchStepCounter = TRAINER_REMATCH_STEPS; + else + gSaveBlock1.trainerRematchStepCounter++; + } +} + +bool32 sub_8082BA4(void) +{ + if (sub_8082B44() && gSaveBlock1.trainerRematchStepCounter >= TRAINER_REMATCH_STEPS) + return TRUE; + else + return FALSE; +} + +void sub_8082BD0(u16 mapGroup, u16 mapNum) +{ + if (sub_8082BA4() && UpdateRandomTrainerEyeRematches(gTrainerEyeTrainers, mapGroup, mapNum) == TRUE) + gSaveBlock1.trainerRematchStepCounter = 0; +} + +s32 sub_8082C0C(u16 mapGroup, u16 mapNum) +{ + return sub_80829A8(gTrainerEyeTrainers, mapGroup, mapNum); +} + +s32 unref_sub_8082C2C(u16 mapGroup, u16 mapNum) +{ + return sub_80829E8(gTrainerEyeTrainers, mapGroup, mapNum); +} + +u16 sub_8082C4C(u16 opponentId) +{ + return sub_8082A90(gTrainerEyeTrainers, opponentId); +} + +s32 sub_8082C68(void) +{ + if (sub_8082A18(gTrainerEyeTrainers, gTrainerBattleOpponent)) + return 1; + else + return sub_8082B10(gTrainerEyeTrainers, gTrainerBattleOpponent); +} + +u8 ScrSpecial_GetTrainerEyeRematchFlag(void) +{ + return GetTrainerEyeRematchFlag(gTrainerEyeTrainers, gTrainerBattleOpponent); +} + +void SetTrainerFlagsAfterTrainerEyeRematch(void) +{ + ClearTrainerEyeRematchFlag(gTrainerEyeTrainers, gTrainerBattleOpponent); + SetCurrentTrainerBattledFlag(); +} diff --git a/src/battle/battle_transition.c b/src/battle/battle_transition.c new file mode 100644 index 000000000..53d32d03a --- /dev/null +++ b/src/battle/battle_transition.c @@ -0,0 +1,2513 @@ +#include "global.h" +#include "battle_transition.h" +#include "main.h" +#include "overworld.h" +#include "task.h" +#include "palette.h" +#include "trig.h" +#include "field_effect.h" +#include "rng.h" +#include "sprite.h" +#include "sound.h" +#include "songs.h" +#include "trainer.h" +#include "field_camera.h" + +void sub_807DE10(void); +void dp12_8087EA4(void); + +extern u8 ewram[]; +extern u16 gUnknown_03005560[]; +extern u16 gUnknown_03004DE0[][0x3C0]; + +extern const struct OamData gFieldOamData_32x32; + +struct TransitionData +{ + vs8 VBlank_DMA; + u16 WININ; + u16 WINOUT; + u16 field_6; + u16 WIN0V; + u16 field_A; + u16 field_C; + u16 BLDCNT; + u16 BLDALPHA; + u16 BLDY; + s16 field_14; + s16 field_16; + s16 field_18; + s16 field_1A; + s16 field_1C; + s16 field_1E; // unused + s16 field_20; + s16 field_22; // unused + s16 data[11]; +}; + +#define TRANSITION_STRUCT (*(struct TransitionData *) (ewram + 0xC000)) +typedef bool8 (*TransitionState)(struct Task* task); +typedef bool8 (*TransitionSpriteCallback)(struct Sprite* sprite); + +// this file's functions +static void LaunchBattleTransitionTask(u8 transitionID); +static void Task_BattleTransitionMain(u8 taskID); +static void Phase1Task_TransitionAll(u8 taskID); +static void Phase2Task_Transition_Blur(u8 taskID); +static void Phase2Task_Transition_Swirl(u8 taskID); +static void Phase2Task_Transition_Shuffle(u8 taskID); +static void Phase2Task_Transition_BigPokeball(u8 taskID); +static void Phase2Task_Transition_PokeballsTrail(u8 taskID); +static void Phase2Task_Transition_Clockwise_BlackFade(u8 taskID); +static void Phase2Task_Transition_Ripple(u8 taskID); +static void Phase2Task_Transition_Wave(u8 taskID); +static void Phase2Task_Transition_Slice(u8 taskID); +static void Phase2Task_Transition_WhiteFade(u8 taskID); +static void Phase2Task_Transition_GridSquares(u8 taskID); +static void Phase2Task_Transition_Shards(u8 taskID); +static void Phase2Task_Transition_Sydney(u8 taskID); +static void Phase2Task_Transition_Phoebe(u8 taskID); +static void Phase2Task_Transition_Glacia(u8 taskID); +static void Phase2Task_Transition_Drake(u8 taskID); +static void Phase2Task_Transition_Steven(u8 taskID); +static bool8 Transition_Phase1(struct Task* task); +static bool8 Transition_WaitForPhase1(struct Task* task); +static bool8 Transition_Phase2(struct Task* task); +static bool8 Transition_WaitForPhase2(struct Task* task); +static void VBlankCB_Phase2_Transition_Swirl(void); +static void HBlankCB_Phase2_Transition_Swirl(void); +static void VBlankCB_Phase2_Transition_Shuffle(void); +static void HBlankCB_Phase2_Transition_Shuffle(void); +static void VBlankCB0_Phase2_Transition_BigPokeball(void); +static void VBlankCB1_Phase2_Transition_BigPokeball(void); +static void VBlankCB_Phase2_Transition_Clockwise_BlackFade(void); +static void VBlankCB_Phase2_Transition_Ripple(void); +static void HBlankCB_Phase2_Transition_Ripple(void); +static void VBlankCB_Phase2_Transition_Wave(void); +static void VBlankCB_Phase2_Transition_Slice(void); +static void HBlankCB_Phase2_Transition_Slice(void); +static void VBlankCB0_Phase2_Transition_WhiteFade(void); +static void VBlankCB1_Phase2_Transition_WhiteFade(void); +static void HBlankCB_Phase2_Transition_WhiteFade(void); +static void VBlankCB0_Phase2_Mugshots(void); +static void VBlankCB1_Phase2_Mugshots(void); +static void HBlankCB_Phase2_Mugshots(void); +static void VBlankCB_Phase2_Transition_Shards(void); +static bool8 Phase2_Transition_Blur_Func1(struct Task* task); +static bool8 Phase2_Transition_Blur_Func2(struct Task* task); +static bool8 Phase2_Transition_Blur_Func3(struct Task* task); +static bool8 Phase2_Transition_Swirl_Func1(struct Task* task); +static bool8 Phase2_Transition_Swirl_Func2(struct Task* task); +static bool8 Phase2_Transition_Shuffle_Func1(struct Task* task); +static bool8 Phase2_Transition_Shuffle_Func2(struct Task* task); +static bool8 Phase2_Transition_BigPokeball_Func1(struct Task* task); +static bool8 Phase2_Transition_BigPokeball_Func2(struct Task* task); +static bool8 Phase2_Transition_BigPokeball_Func3(struct Task* task); +static bool8 Phase2_Transition_BigPokeball_Func4(struct Task* task); +static bool8 Phase2_Transition_BigPokeball_Func5(struct Task* task); +static bool8 Phase2_Transition_BigPokeball_Func6(struct Task* task); +static bool8 Phase2_Transition_PokeballsTrail_Func1(struct Task* task); +static bool8 Phase2_Transition_PokeballsTrail_Func2(struct Task* task); +static bool8 Phase2_Transition_PokeballsTrail_Func3(struct Task* task); +static bool8 Phase2_Transition_Clockwise_BlackFade_Func1(struct Task* task); +static bool8 Phase2_Transition_Clockwise_BlackFade_Func2(struct Task* task); +static bool8 Phase2_Transition_Clockwise_BlackFade_Func3(struct Task* task); +static bool8 Phase2_Transition_Clockwise_BlackFade_Func4(struct Task* task); +static bool8 Phase2_Transition_Clockwise_BlackFade_Func5(struct Task* task); +static bool8 Phase2_Transition_Clockwise_BlackFade_Func6(struct Task* task); +static bool8 Phase2_Transition_Clockwise_BlackFade_Func7(struct Task* task); +static bool8 Phase2_Transition_Ripple_Func1(struct Task* task); +static bool8 Phase2_Transition_Ripple_Func2(struct Task* task); +static bool8 Phase2_Transition_Wave_Func1(struct Task* task); +static bool8 Phase2_Transition_Wave_Func2(struct Task* task); +static bool8 Phase2_Transition_Wave_Func3(struct Task* task); +static bool8 Phase2_Transition_Slice_Func1(struct Task* task); +static bool8 Phase2_Transition_Slice_Func2(struct Task* task); +static bool8 Phase2_Transition_Slice_Func3(struct Task* task); +static bool8 Phase2_Transition_WhiteFade_Func1(struct Task* task); +static bool8 Phase2_Transition_WhiteFade_Func2(struct Task* task); +static bool8 Phase2_Transition_WhiteFade_Func3(struct Task* task); +static bool8 Phase2_Transition_WhiteFade_Func4(struct Task* task); +static bool8 Phase2_Transition_WhiteFade_Func5(struct Task* task); +static bool8 Phase2_Transition_GridSquares_Func1(struct Task* task); +static bool8 Phase2_Transition_GridSquares_Func2(struct Task* task); +static bool8 Phase2_Transition_GridSquares_Func3(struct Task* task); +static bool8 Phase2_Transition_Shards_Func1(struct Task* task); +static bool8 Phase2_Transition_Shards_Func2(struct Task* task); +static bool8 Phase2_Transition_Shards_Func3(struct Task* task); +static bool8 Phase2_Transition_Shards_Func4(struct Task* task); +static bool8 Phase2_Transition_Shards_Func5(struct Task* task); +static bool8 Phase2_Mugshot_Func1(struct Task* task); +static bool8 Phase2_Mugshot_Func2(struct Task* task); +static bool8 Phase2_Mugshot_Func3(struct Task* task); +static bool8 Phase2_Mugshot_Func4(struct Task* task); +static bool8 Phase2_Mugshot_Func5(struct Task* task); +static bool8 Phase2_Mugshot_Func6(struct Task* task); +static bool8 Phase2_Mugshot_Func7(struct Task* task); +static bool8 Phase2_Mugshot_Func8(struct Task* task); +static bool8 Phase2_Mugshot_Func9(struct Task* task); +static bool8 Phase2_Mugshot_Func10(struct Task* task); +static void Phase2Task_MugShotTransition(u8 taskID); +static void Mugshots_CreateOpponentPlayerSprites(struct Task* task); +static void sub_811CA10(s16 spriteID, s16 value); +static void sub_811CA28(s16 spriteID); +static s16 sub_811CA44(s16 spriteID); +static bool8 sub_811C934(struct Sprite* sprite); +static bool8 sub_811C938(struct Sprite* sprite); +static bool8 sub_811C984(struct Sprite* sprite); +static bool8 sub_811C9B8(struct Sprite* sprite); +static bool8 sub_811C9E4(struct Sprite* sprite); +static void CreatePhase1Task(s16 a0, s16 a1, s16 a2, s16 a3, s16 a4); +static bool8 sub_811D52C(void); +static void Phase1_Task_RunFuncs(u8 taskID); +static bool8 Phase1_TransitionAll_Func1(struct Task* task); +static bool8 Phase1_TransitionAll_Func2(struct Task* task); +static void sub_811D658(void); +static void VBlankCB_BattleTransition(void); +static void sub_811D6A8(u16** a0, u16** a1); +static void sub_811D690(u16** a0); +static void sub_811D6D4(void); +static void sub_811D6E8(s16* array, s16 sinAdd, s16 index, s16 indexIncrementer, s16 amplitude, s16 arrSize); +static void sub_811D764(u16* a0, s16 a1, s16 a2, s16 a3); +static void sub_811D8FC(s16* a0, s16 a1, s16 a2, s16 a3, s16 a4, s16 a5, s16 a6); +static bool8 sub_811D978(s16* a0, bool8 a1, bool8 a2); +static void sub_811CFD0(struct Sprite* sprite); +static void sub_811B720(struct Sprite* sprite); +static void sub_811C90C(struct Sprite* sprite); + +// const data + +static const u32 sBigPokeball_Tileset[] = INCBIN_U32("graphics/battle_transitions/big_pokeball.4bpp"); +static const u32 sPokeballTrail_Tileset[] = INCBIN_U32("graphics/battle_transitions/pokeball_trail.4bpp"); +static const u8 sSpriteImage_83FC148[] = INCBIN_U8("graphics/battle_transitions/pokeball.4bpp"); +static const u32 sUnknown_083FC348[] = INCBIN_U32("graphics/battle_transitions/elite_four_bg.4bpp"); +static const u8 sSpriteImage_83FC528[] = INCBIN_U8("graphics/battle_transitions/unused_brendan.4bpp"); +static const u8 sSpriteImage_83FCD28[] = INCBIN_U8("graphics/battle_transitions/unused_lass.4bpp"); +static const u32 sShrinkingBoxTileset[] = INCBIN_U32("graphics/battle_transitions/shrinking_box.4bpp"); + +static struct TransitionData * const sTransitionStructPtr = &TRANSITION_STRUCT; + +static const TaskFunc sPhase1_Tasks[TRANSITIONS_NO] = +{ + [0 ... TRANSITIONS_NO - 1] = &Phase1Task_TransitionAll +}; + +static const TaskFunc sPhase2_Tasks[TRANSITIONS_NO] = +{ + Phase2Task_Transition_Blur, // 0 + Phase2Task_Transition_Swirl, // 1 + Phase2Task_Transition_Shuffle, // 2 + Phase2Task_Transition_BigPokeball, // 3 + Phase2Task_Transition_PokeballsTrail, // 4 + Phase2Task_Transition_Clockwise_BlackFade, // 5 + Phase2Task_Transition_Ripple, // 6 + Phase2Task_Transition_Wave, // 7 + Phase2Task_Transition_Slice, // 8 + Phase2Task_Transition_WhiteFade, // 9 + Phase2Task_Transition_GridSquares, // 10 + Phase2Task_Transition_Shards, // 11 + Phase2Task_Transition_Sydney, // 12 + Phase2Task_Transition_Phoebe, // 13 + Phase2Task_Transition_Glacia, // 14 + Phase2Task_Transition_Drake, // 15 + Phase2Task_Transition_Steven, // 16 +}; + +static const TransitionState sMainTransitionPhases[] = +{ + &Transition_Phase1, + &Transition_WaitForPhase1, + &Transition_Phase2, + &Transition_WaitForPhase2 +}; + +static const TransitionState sPhase2_Transition_Blur_Funcs[] = +{ + Phase2_Transition_Blur_Func1, + Phase2_Transition_Blur_Func2, + Phase2_Transition_Blur_Func3 +}; + +static const TransitionState sPhase2_Transition_Swirl_Funcs[] = +{ + Phase2_Transition_Swirl_Func1, + Phase2_Transition_Swirl_Func2, +}; + +static const TransitionState sPhase2_Transition_Shuffle_Funcs[] = +{ + Phase2_Transition_Shuffle_Func1, + Phase2_Transition_Shuffle_Func2, +}; + +static const TransitionState sPhase2_Transition_BigPokeball_Funcs[] = +{ + Phase2_Transition_BigPokeball_Func1, + Phase2_Transition_BigPokeball_Func2, + Phase2_Transition_BigPokeball_Func3, + Phase2_Transition_BigPokeball_Func4, + Phase2_Transition_BigPokeball_Func5, + Phase2_Transition_BigPokeball_Func6 +}; + +static const TransitionState sPhase2_Transition_PokeballsTrail_Funcs[] = +{ + Phase2_Transition_PokeballsTrail_Func1, + Phase2_Transition_PokeballsTrail_Func2, + Phase2_Transition_PokeballsTrail_Func3 +}; + +static const s16 sUnknown_083FD7E4[2] = {-16, 256}; +static const s16 sUnknown_083FD7E8[5] = {0, 32, 64, 18, 48}; +static const s16 sUnknown_083FD7F2[2] = {8, -8}; + +static const TransitionState sPhase2_Transition_Clockwise_BlackFade_Funcs[] = +{ + Phase2_Transition_Clockwise_BlackFade_Func1, + Phase2_Transition_Clockwise_BlackFade_Func2, + Phase2_Transition_Clockwise_BlackFade_Func3, + Phase2_Transition_Clockwise_BlackFade_Func4, + Phase2_Transition_Clockwise_BlackFade_Func5, + Phase2_Transition_Clockwise_BlackFade_Func6, + Phase2_Transition_Clockwise_BlackFade_Func7 +}; + +static const TransitionState sPhase2_Transition_Ripple_Funcs[] = +{ + Phase2_Transition_Ripple_Func1, + Phase2_Transition_Ripple_Func2 +}; + +static const TransitionState sPhase2_Transition_Wave_Funcs[] = +{ + Phase2_Transition_Wave_Func1, + Phase2_Transition_Wave_Func2, + Phase2_Transition_Wave_Func3 +}; + +static const TransitionState sPhase2_Mugshot_Transition_Funcs[] = +{ + Phase2_Mugshot_Func1, + Phase2_Mugshot_Func2, + Phase2_Mugshot_Func3, + Phase2_Mugshot_Func4, + Phase2_Mugshot_Func5, + Phase2_Mugshot_Func6, + Phase2_Mugshot_Func7, + Phase2_Mugshot_Func8, + Phase2_Mugshot_Func9, + Phase2_Mugshot_Func10 +}; + +static const u8 sMugshotsTrainerPicIDsTable[MUGSHOTS_NO] = {TRAINER_PIC_SIDNEY, TRAINER_PIC_PHOEBE, TRAINER_PIC_GLACIA, TRAINER_PIC_DRAKE, TRAINER_PIC_STEVEN}; +static const s16 sMugshotsOpponentRotationScales[MUGSHOTS_NO][2] = +{ + {0x200, 0x200}, + {0x200, 0x200}, + {0x1B0, 0x1B0}, + {0x1A0, 0x1A0}, + {0x188, 0x188}, +}; +static const s16 sMugshotsOpponentCoords[MUGSHOTS_NO][2] = +{ + {0, 0}, + {0, 0}, + {-4, 4}, + {0, 5}, + {0, 7}, +}; + +static const TransitionSpriteCallback sUnknown_083FD880[] = +{ + sub_811C934, + sub_811C938, + sub_811C984, + sub_811C9B8, + sub_811C934, + sub_811C9E4, + sub_811C934 +}; + +static const s16 sUnknown_083FD89C[2] = {12, -12}; +static const s16 sUnknown_083FD8A0[2] = {-1, 1}; + +static const TransitionState sPhase2_Transition_Slice_Funcs[] = +{ + Phase2_Transition_Slice_Func1, + Phase2_Transition_Slice_Func2, + Phase2_Transition_Slice_Func3 +}; + +static const TransitionState sPhase2_Transition_WhiteFade_Funcs[] = +{ + Phase2_Transition_WhiteFade_Func1, + Phase2_Transition_WhiteFade_Func2, + Phase2_Transition_WhiteFade_Func3, + Phase2_Transition_WhiteFade_Func4, + Phase2_Transition_WhiteFade_Func5 +}; + +static const s16 sUnknown_083FD8C4[8] = {0, 20, 15, 40, 10, 25, 35, 5}; + +static const TransitionState sPhase2_Transition_GridSquares_Funcs[] = +{ + Phase2_Transition_GridSquares_Func1, + Phase2_Transition_GridSquares_Func2, + Phase2_Transition_GridSquares_Func3 +}; + +static const TransitionState sPhase2_Transition_Shards_Funcs[] = +{ + Phase2_Transition_Shards_Func1, + Phase2_Transition_Shards_Func2, + Phase2_Transition_Shards_Func3, + Phase2_Transition_Shards_Func4, + Phase2_Transition_Shards_Func5 +}; + +static const s16 sUnknown_083FD8F4[][5] = +{ + {56, 0, 0, 160, 0}, + {104, 160, 240, 88, 1}, + {240, 72, 56, 0, 1}, + {0, 32, 144, 160, 0}, + {144, 160, 184, 0, 1}, + {56, 0, 168, 160, 0}, + {168, 160, 48, 0, 1}, +}; + +static const s16 sUnknown_083FD93A[] = {8, 4, 2, 1, 1, 1, 0}; + +static const TransitionState sPhase1_TransitionAll_Funcs[] = +{ + Phase1_TransitionAll_Func1, + Phase1_TransitionAll_Func2 +}; + +static const struct SpriteFrameImage sSpriteImageTable_83FD950[] = +{ + sSpriteImage_83FC148, 0x200 +}; + +static const union AnimCmd sSpriteAnim_83FD958[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_83FD960[] = +{ + sSpriteAnim_83FD958 +}; + +static const union AffineAnimCmd sSpriteAffineAnim_83FD964[] = +{ + AFFINEANIMCMD_FRAME(0, 0, -4, 1), + AFFINEANIMCMD_JUMP(0) +}; + +static const union AffineAnimCmd sSpriteAffineAnim_83FD974[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 4, 1), + AFFINEANIMCMD_JUMP(0) +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_83FD984[] = +{ + sSpriteAffineAnim_83FD964, + sSpriteAffineAnim_83FD974 +}; + +static const struct SpriteTemplate sSpriteTemplate_83FD98C = +{ + .tileTag = 0xFFFF, + .paletteTag = 4105, + .oam = &gFieldOamData_32x32, + .anims = sSpriteAnimTable_83FD960, + .images = sSpriteImageTable_83FD950, + .affineAnims = sSpriteAffineAnimTable_83FD984, + .callback = sub_811B720 +}; + +static const struct OamData gOamData_83FD9A4 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteFrameImage sSpriteImageTable_83FD9AC[] = +{ + sSpriteImage_83FC528, 0x800 +}; + +static const struct SpriteFrameImage sSpriteImageTable_83FD9B4[] = +{ + sSpriteImage_83FCD28, 0x800 +}; + +static const union AnimCmd sSpriteAnim_83FD9BC[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_83FD9C4[] = +{ + sSpriteAnim_83FD9BC +}; + +static const struct SpriteTemplate sSpriteTemplate_83FD9C8 = +{ + .tileTag = 0xFFFF, + .paletteTag = 4106, + .oam = &gOamData_83FD9A4, + .anims = sSpriteAnimTable_83FD9C4, + .images = sSpriteImageTable_83FD9AC, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_811C90C +}; + +static const struct SpriteTemplate sSpriteTemplate_83FD9E0 = +{ + .tileTag = 0xFFFF, + .paletteTag = 4106, + .oam = &gOamData_83FD9A4, + .anims = sSpriteAnimTable_83FD9C4, + .images = sSpriteImageTable_83FD9B4, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_811C90C +}; + +static const u16 gFieldEffectObjectPalette10[] = INCBIN_U16("graphics/field_effect_objects/palettes/10.gbapal"); + +const struct SpritePalette gFieldEffectObjectPaletteInfo10 = +{ + gFieldEffectObjectPalette10, 0x1009 +}; + +static const u16 sMugshotPal_Sydney[] = INCBIN_U16("graphics/battle_transitions/sidney_bg.gbapal"); +static const u16 sMugshotPal_Phoebe[] = INCBIN_U16("graphics/battle_transitions/phoebe_bg.gbapal"); +static const u16 sMugshotPal_Glacia[] = INCBIN_U16("graphics/battle_transitions/glacia_bg.gbapal"); +static const u16 sMugshotPal_Drake[] = INCBIN_U16("graphics/battle_transitions/drake_bg.gbapal"); +static const u16 sMugshotPal_Steven[] = INCBIN_U16("graphics/battle_transitions/steven_bg.gbapal"); +static const u16 sMugshotPal_Brendan[] = INCBIN_U16("graphics/battle_transitions/brendan_bg.gbapal"); +static const u16 sMugshotPal_May[] = INCBIN_U16("graphics/battle_transitions/may_bg.gbapal"); + +static const u16 * const sOpponentMugshotsPals[MUGSHOTS_NO] = +{ + sMugshotPal_Sydney, + sMugshotPal_Phoebe, + sMugshotPal_Glacia, + sMugshotPal_Drake, + sMugshotPal_Steven +}; + +static const u16 * const sPlayerMugshotsPals[2] = +{ + sMugshotPal_Brendan, + sMugshotPal_May +}; + +static const u16 sUnusedTrainerPalette[] = INCBIN_U16("graphics/battle_transitions/unused_trainer.gbapal"); +static const struct SpritePalette sSpritePalette_UnusedTrainer = +{ + sUnusedTrainerPalette, 0x100A +}; + +static const u16 sBigPokeball_Tilemap[] = INCBIN_U16("graphics/battle_transitions/big_pokeball_map.bin"); +static const u16 sMugshotsTilemap[] = INCBIN_U16("graphics/battle_transitions/elite_four_bg_map.bin"); + +// actual code starts here + +void BattleTransition_StartOnField(u8 transitionID) +{ + gMain.callback2 = CB2_OverworldBasic; + LaunchBattleTransitionTask(transitionID); +} + +void BattleTransition_Start(u8 transitionID) +{ + LaunchBattleTransitionTask(transitionID); +} + +#define tState data[0] +#define tTransitionID data[1] +#define tTransitionDone data[15] + +bool8 IsBattleTransitionDone(void) +{ + u8 taskID = FindTaskIdByFunc(Task_BattleTransitionMain); + if (gTasks[taskID].tTransitionDone) + { + DestroyTask(taskID); + return TRUE; + } + else + return FALSE; +} + +static void LaunchBattleTransitionTask(u8 transitionID) +{ + u8 taskID = CreateTask(Task_BattleTransitionMain, 2); + gTasks[taskID].tTransitionID = transitionID; +} + +static void Task_BattleTransitionMain(u8 taskID) +{ + while (sMainTransitionPhases[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Transition_Phase1(struct Task* task) +{ + sub_807DE10(); + CpuCopy32(gPlttBufferFaded, gPlttBufferUnfaded, 0x400); + if (sPhase1_Tasks[task->tTransitionID] != NULL) + { + CreateTask(sPhase1_Tasks[task->tTransitionID], 4); + task->tState++; + return FALSE; + } + else + { + task->tState = 2; + return TRUE; + } +} + +static bool8 Transition_WaitForPhase1(struct Task* task) +{ + if (FindTaskIdByFunc(sPhase1_Tasks[task->tTransitionID]) == 0xFF) + { + task->tState++; + return TRUE; + } + else + return FALSE; +} + +static bool8 Transition_Phase2(struct Task* task) +{ + CreateTask(sPhase2_Tasks[task->tTransitionID], 0); + task->tState++; + return FALSE; +} + +static bool8 Transition_WaitForPhase2(struct Task* task) +{ + task->tTransitionDone = 0; + if (FindTaskIdByFunc(sPhase2_Tasks[task->tTransitionID]) == 0xFF) + task->tTransitionDone = 1; + return FALSE; +} + +static void Phase1Task_TransitionAll(u8 taskID) +{ + if (gTasks[taskID].tState == 0) + { + gTasks[taskID].tState++; + CreatePhase1Task(0, 0, 3, 2, 2); + } + else if (sub_811D52C()) + DestroyTask(taskID); +} + +static void Phase2Task_Transition_Blur(u8 taskID) +{ + while (sPhase2_Transition_Blur_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_Blur_Func1(struct Task* task) +{ + REG_MOSAIC = 0; + REG_BG1CNT |= BGCNT_MOSAIC; + REG_BG2CNT |= BGCNT_MOSAIC; + REG_BG3CNT |= BGCNT_MOSAIC; + task->tState++; + return TRUE; +} + +static bool8 Phase2_Transition_Blur_Func2(struct Task* task) +{ + if (task->data[1] != 0) + task->data[1]--; + else + { + task->data[1] = 4; + if (++task->data[2] == 10) + BeginNormalPaletteFade(-1, -1, 0, 0x10, 0); + REG_MOSAIC = (task->data[2] & 15) * 17; + if (task->data[2] > 14) + task->tState++; + } + return FALSE; +} + +static bool8 Phase2_Transition_Blur_Func3(struct Task* task) +{ + if (!gPaletteFade.active) + { + u8 taskID = FindTaskIdByFunc(Phase2Task_Transition_Blur); + DestroyTask(taskID); + } + return FALSE; +} + +static void Phase2Task_Transition_Swirl(u8 taskID) +{ + while (sPhase2_Transition_Swirl_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_Swirl_Func1(struct Task* task) +{ + u16 savedIME; + + sub_811D658(); + dp12_8087EA4(); + BeginNormalPaletteFade(-1, 4, 0, 0x10, 0); + sub_811D6E8(gUnknown_03005560, TRANSITION_STRUCT.field_14, 0, 2, 0, 160); + + SetVBlankCallback(VBlankCB_Phase2_Transition_Swirl); + SetHBlankCallback(HBlankCB_Phase2_Transition_Swirl); + + savedIME = REG_IME; + REG_IME = 0; + REG_IE |= (INTR_FLAG_VBLANK | INTR_FLAG_HBLANK); + REG_IME = savedIME; + REG_DISPSTAT |= (DISPSTAT_VBLANK_INTR | DISPSTAT_HBLANK_INTR); + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_Swirl_Func2(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + task->data[1] += 4; + task->data[2] += 8; + + sub_811D6E8(gUnknown_03004DE0[0], TRANSITION_STRUCT.field_14, task->data[1], 2, task->data[2], 160); + + if (!gPaletteFade.active) + { + u8 taskID = FindTaskIdByFunc(Phase2Task_Transition_Swirl); + DestroyTask(taskID); + } + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static void VBlankCB_Phase2_Transition_Swirl(void) +{ + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); +} + +static void HBlankCB_Phase2_Transition_Swirl(void) +{ + u16 var = gUnknown_03004DE0[1][REG_VCOUNT]; + REG_BG1HOFS = var; + REG_BG2HOFS = var; + REG_BG3HOFS = var; +} + +static void Phase2Task_Transition_Shuffle(u8 taskID) +{ + while (sPhase2_Transition_Shuffle_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_Shuffle_Func1(struct Task* task) +{ + u16 savedIME; + + sub_811D658(); + dp12_8087EA4(); + + BeginNormalPaletteFade(-1, 4, 0, 0x10, 0); + memset(gUnknown_03005560, TRANSITION_STRUCT.field_16, 0x140); + + SetVBlankCallback(VBlankCB_Phase2_Transition_Shuffle); + SetHBlankCallback(HBlankCB_Phase2_Transition_Shuffle); + + savedIME = REG_IME; + REG_IME = 0; + REG_IE |= (INTR_FLAG_VBLANK | INTR_FLAG_HBLANK); + REG_IME = savedIME; + REG_DISPSTAT |= (DISPSTAT_VBLANK_INTR | DISPSTAT_HBLANK_INTR); + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_Shuffle_Func2(struct Task* task) +{ + u8 i; + u16 r3, r4; + + TRANSITION_STRUCT.VBlank_DMA = 0; + r4 = task->data[1]; + r3 = task->data[2] >> 8; + task->data[1] += 4224; + task->data[2] += 384; + + for (i = 0; i < 160; i++, r4 += 4224) + { + u16 var = r4 / 256; + gUnknown_03004DE0[0][i] = TRANSITION_STRUCT.field_16 + Sin(var, r3); + } + + if (!gPaletteFade.active) + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_Shuffle)); + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static void VBlankCB_Phase2_Transition_Shuffle(void) +{ + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); +} + +static void HBlankCB_Phase2_Transition_Shuffle(void) +{ + u16 var = gUnknown_03004DE0[1][REG_VCOUNT]; + REG_BG1VOFS = var; + REG_BG2VOFS = var; + REG_BG3VOFS = var; +} + +static void Phase2Task_Transition_BigPokeball(u8 taskID) +{ + while (sPhase2_Transition_BigPokeball_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_BigPokeball_Func1(struct Task* task) +{ + u16 i; + u16 *dst1, *dst2; + + sub_811D658(); + dp12_8087EA4(); + + task->data[1] = 16; + task->data[2] = 0; + task->data[4] = 0; + task->data[5] = 0x4000; + TRANSITION_STRUCT.WININ = 63; + TRANSITION_STRUCT.WINOUT = 0; + TRANSITION_STRUCT.field_6 = 240; + TRANSITION_STRUCT.WIN0V = 160; + TRANSITION_STRUCT.BLDCNT = 0x3F41; + TRANSITION_STRUCT.BLDALPHA = task->data[1] * 256; // 16 * 256 = 0x1000 + + for (i = 0; i < 160; i++) + { + gUnknown_03005560[i] = 240; + } + + SetVBlankCallback(VBlankCB0_Phase2_Transition_BigPokeball); + + sub_811D6A8(&dst1, & dst2); + CpuFill16(0, dst1, 0x800); + CpuSet(sBigPokeball_Tileset, dst2, 0x2C0); + LoadPalette(gFieldEffectObjectPalette10, 240, 32); + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_BigPokeball_Func2(struct Task* task) +{ + s16 i, j; + u16 *dst1, *dst2; + const u16* BigPokeballMap; + + BigPokeballMap = sBigPokeball_Tilemap; + sub_811D6A8(&dst1, &dst2); + for (i = 0; i < 20; i++) + { + for (j = 0; j < 30; j++, BigPokeballMap++) + { + dst1[i * 32 + j] = *BigPokeballMap | 0xF000; + } + } + sub_811D6E8(gUnknown_03004DE0[0], 0, task->data[4], 132, task->data[5], 160); + + task->tState++; + return TRUE; +} + +static bool8 Phase2_Transition_BigPokeball_Func3(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + if (task->data[3] == 0 || --task->data[3] == 0) + { + task->data[2]++; + task->data[3] = 2; + } + TRANSITION_STRUCT.BLDALPHA = (task->data[1] << 8) | task->data[2]; + if (task->data[2] > 15) + task->tState++; + task->data[4] += 8; + task->data[5] -= 256; + + sub_811D6E8(gUnknown_03004DE0[0], 0, task->data[4], 132, task->data[5] >> 8, 160); + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_BigPokeball_Func4(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + if (task->data[3] == 0 || --task->data[3] == 0) + { + task->data[1]--; + task->data[3] = 2; + } + TRANSITION_STRUCT.BLDALPHA = (task->data[1] << 8) | task->data[2]; + if (task->data[1] == 0) + task->tState++; + task->data[4] += 8; + task->data[5] -= 256; + + sub_811D6E8(gUnknown_03004DE0[0], 0, task->data[4], 132, task->data[5] >> 8, 160); + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_BigPokeball_Func5(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + task->data[4] += 8; + task->data[5] -= 256; + + sub_811D6E8(gUnknown_03004DE0[0], 0, task->data[4], 132, task->data[5] >> 8, 160); + + if (task->data[5] <= 0) + { + task->tState++; + task->data[1] = 160; + task->data[2] = 256; + task->data[3] = 0; + } + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_BigPokeball_Func6(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + if (task->data[2] < 1024) + task->data[2] += 128; + if (task->data[1] != 0) + { + task->data[1] -= (task->data[2] >> 8); + if (task->data[1] < 0) + task->data[1] = 0; + } + sub_811D764(gUnknown_03004DE0[0], 120, 80, task->data[1]); + if (task->data[1] == 0) + { + DmaStop(0); + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_BigPokeball)); + } + if (task->data[3] == 0) + { + task->data[3]++; + SetVBlankCallback(VBlankCB1_Phase2_Transition_BigPokeball); + } + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static void Transition_BigPokeball_Vblank(void) +{ + DmaStop(0); + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); + REG_WININ = TRANSITION_STRUCT.WININ; + REG_WINOUT = TRANSITION_STRUCT.WINOUT; + REG_WIN0V = TRANSITION_STRUCT.WIN0V; + REG_BLDCNT = TRANSITION_STRUCT.BLDCNT; + REG_BLDALPHA = TRANSITION_STRUCT.BLDALPHA; +} + +static void VBlankCB0_Phase2_Transition_BigPokeball(void) +{ + Transition_BigPokeball_Vblank(); + DmaSet(0, gUnknown_03005560, ®_BG0HOFS, 0xA2400001); +} + +static void VBlankCB1_Phase2_Transition_BigPokeball(void) +{ + Transition_BigPokeball_Vblank(); + DmaSet(0, gUnknown_03005560, ®_WIN0H, 0xA2400001); +} + +static void Phase2Task_Transition_PokeballsTrail(u8 taskID) +{ + while (sPhase2_Transition_PokeballsTrail_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_PokeballsTrail_Func1(struct Task* task) +{ + u16 *dst1, *dst2; + + sub_811D6A8(&dst1, &dst2); + CpuSet(sPokeballTrail_Tileset, dst2, 0x20); + CpuFill32(0, dst1, 0x800); + LoadPalette(gFieldEffectObjectPalette10, 0xF0, 0x20); + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_PokeballsTrail_Func2(struct Task* task) +{ + s16 i; + s16 rand; + s16 arr0[2]; + s16 arr1[5]; + + memcpy(arr0, sUnknown_083FD7E4, sizeof(sUnknown_083FD7E4)); + memcpy(arr1, sUnknown_083FD7E8, sizeof(sUnknown_083FD7E8)); + rand = Random() & 1; + for (i = 0; i <= 4; i++, rand ^= 1) + { + gFieldEffectArguments[0] = arr0[rand]; // x + gFieldEffectArguments[1] = (i * 32) + 16; // y + gFieldEffectArguments[2] = rand; + gFieldEffectArguments[3] = arr1[i]; + FieldEffectStart(FLDEFF_POKEBALL); + } + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_PokeballsTrail_Func3(struct Task* task) +{ + if (!FieldEffectActiveListContains(FLDEFF_POKEBALL)) + { + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_PokeballsTrail)); + } + return FALSE; +} + +bool8 FldEff_Pokeball(void) +{ + u8 spriteID = CreateSpriteAtEnd(&sSpriteTemplate_83FD98C, gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + gSprites[spriteID].oam.priority = 0; + gSprites[spriteID].oam.affineMode = 1; + gSprites[spriteID].data0 = gFieldEffectArguments[2]; + gSprites[spriteID].data1 = gFieldEffectArguments[3]; + gSprites[spriteID].data2 = -1; + InitSpriteAffineAnim(&gSprites[spriteID]); + StartSpriteAffineAnim(&gSprites[spriteID], gFieldEffectArguments[2]); + return FALSE; +} + +#define SOME_VRAM_STORE(ptr, posY, posX, toStore) \ +{ \ + u32 index = (posY) * 32 + posX; \ + ptr[index] = toStore; \ +} + +static void sub_811B720(struct Sprite* sprite) +{ + s16 arr0[2]; + + memcpy(arr0, sUnknown_083FD7F2, sizeof(sUnknown_083FD7F2)); + if (sprite->data1 != 0) + sprite->data1--; + else + { + if (sprite->pos1.x >= 0 && sprite->pos1.x <= 240) + { + s16 posX = sprite->pos1.x >> 3; + s16 posY = sprite->pos1.y >> 3; + + if (posX != sprite->data2) + { + u32 var; + u16 *ptr; + + sprite->data2 = posX; + var = (((REG_BG0CNT >> 8) & 0x1F) << 11); // r2 + ptr = (u16 *)(VRAM + var); + + SOME_VRAM_STORE(ptr, posY - 2, posX, 0xF001); + SOME_VRAM_STORE(ptr, posY - 1, posX, 0xF001); + SOME_VRAM_STORE(ptr, posY - 0, posX, 0xF001); + SOME_VRAM_STORE(ptr, posY + 1, posX, 0xF001); + } + } + sprite->pos1.x += arr0[sprite->data0]; + if (sprite->pos1.x < -15 || sprite->pos1.x > 255) + FieldEffectStop(sprite, FLDEFF_POKEBALL); + } +} + +static void Phase2Task_Transition_Clockwise_BlackFade(u8 taskID) +{ + while (sPhase2_Transition_Clockwise_BlackFade_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_Clockwise_BlackFade_Func1(struct Task* task) +{ + u16 i; + + sub_811D658(); + dp12_8087EA4(); + + TRANSITION_STRUCT.WININ = 0; + TRANSITION_STRUCT.WINOUT = 63; + TRANSITION_STRUCT.field_6 = -3855; + TRANSITION_STRUCT.WIN0V = 160; + + for (i = 0; i < 160; i++) + { + gUnknown_03005560[i] = 0xF3F4; + } + + SetVBlankCallback(VBlankCB_Phase2_Transition_Clockwise_BlackFade); + TRANSITION_STRUCT.data[4] = 120; + + task->tState++; + return TRUE; +} + +static bool8 Phase2_Transition_Clockwise_BlackFade_Func2(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + + sub_811D8FC(TRANSITION_STRUCT.data, 120, 80, TRANSITION_STRUCT.data[4], -1, 1, 1); + do + { + gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] = (TRANSITION_STRUCT.data[2] + 1) | 0x7800; + } while (!sub_811D978(TRANSITION_STRUCT.data, 1, 1)); + + TRANSITION_STRUCT.data[4] += 16; + if (TRANSITION_STRUCT.data[4] >= 240) + { + TRANSITION_STRUCT.data[5] = 0; + task->tState++; + } + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_Clockwise_BlackFade_Func3(struct Task* task) +{ + s16 r1, r3; + vu8 var = 0; + + TRANSITION_STRUCT.VBlank_DMA = 0; + + sub_811D8FC(TRANSITION_STRUCT.data, 120, 80, 240, TRANSITION_STRUCT.data[5], 1, 1); + + while (1) + { + r1 = 120, r3 = TRANSITION_STRUCT.data[2] + 1; + if (TRANSITION_STRUCT.data[5] >= 80) + r1 = TRANSITION_STRUCT.data[2], r3 = 240; + gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] = (r3) | (r1 << 8); + if (var != 0) + break; + var = sub_811D978(TRANSITION_STRUCT.data, 1, 1); + } + + TRANSITION_STRUCT.data[5] += 8; + if (TRANSITION_STRUCT.data[5] >= 160) + { + TRANSITION_STRUCT.data[4] = 240; + task->tState++; + } + else + { + while (TRANSITION_STRUCT.data[3] < TRANSITION_STRUCT.data[5]) + { + gUnknown_03004DE0[0][++TRANSITION_STRUCT.data[3]] = (r3) | (r1 << 8); + } + } + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_Clockwise_BlackFade_Func4(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + + sub_811D8FC(TRANSITION_STRUCT.data, 120, 80, TRANSITION_STRUCT.data[4], 160, 1, 1); + do + { + gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] = (TRANSITION_STRUCT.data[2] << 8) | 0xF0; + } while (!sub_811D978(TRANSITION_STRUCT.data, 1, 1)); + + TRANSITION_STRUCT.data[4] -= 16; + if (TRANSITION_STRUCT.data[4] <= 0) + { + TRANSITION_STRUCT.data[5] = 160; + task->tState++; + } + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_Clockwise_BlackFade_Func5(struct Task* task) +{ + s16 r1, r2, r3; + vu8 var = 0; + + TRANSITION_STRUCT.VBlank_DMA = 0; + + sub_811D8FC(TRANSITION_STRUCT.data, 120, 80, 0, TRANSITION_STRUCT.data[5], 1, 1); + + while (1) + { + r1 = gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] & 0xFF, r2 = TRANSITION_STRUCT.data[2]; + if (TRANSITION_STRUCT.data[5] <= 80) + r2 = 120, r1 = TRANSITION_STRUCT.data[2]; + gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] = (r1) | (r2 << 8); + r3 = 0; + if (var != 0) + break; + var = sub_811D978(TRANSITION_STRUCT.data, 1, 1); + } + + TRANSITION_STRUCT.data[5] -= 8; + if (TRANSITION_STRUCT.data[5] <= 0) + { + TRANSITION_STRUCT.data[4] = r3; + task->tState++; + } + else + { + while (TRANSITION_STRUCT.data[3] > TRANSITION_STRUCT.data[5]) + { + gUnknown_03004DE0[0][--TRANSITION_STRUCT.data[3]] = (r1) | (r2 << 8); + } + } + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_Clockwise_BlackFade_Func6(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + + sub_811D8FC(TRANSITION_STRUCT.data, 120, 80, TRANSITION_STRUCT.data[4], 0, 1, 1); + do + { + s16 r2, r3; + + r2 = 120, r3 = TRANSITION_STRUCT.data[2]; + if (TRANSITION_STRUCT.data[2] >= 120) + r2 = 0, r3 = 240; + gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] = (r3) | (r2 << 8); + + } while (!sub_811D978(TRANSITION_STRUCT.data, 1, 1)); + + TRANSITION_STRUCT.data[4] += 16; + if (TRANSITION_STRUCT.data[2] > 120) + task->tState++; + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_Clockwise_BlackFade_Func7(struct Task* task) +{ + DmaStop(0); + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_Clockwise_BlackFade)); + return FALSE; +} + +static void VBlankCB_Phase2_Transition_Clockwise_BlackFade(void) +{ + DmaStop(0); + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA != 0) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); + REG_WININ = TRANSITION_STRUCT.WININ; + REG_WINOUT = TRANSITION_STRUCT.WINOUT; + REG_WIN0V = TRANSITION_STRUCT.WIN0V; + REG_WIN0H = gUnknown_03004DE0[1][0]; + DmaSet(0, gUnknown_03004DE0[1], ®_WIN0H, 0xA2400001); +} + +static void Phase2Task_Transition_Ripple(u8 taskID) +{ + while (sPhase2_Transition_Ripple_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_Ripple_Func1(struct Task* task) +{ + u8 i; + + sub_811D658(); + dp12_8087EA4(); + + for (i = 0; i < 160; i++) + { + gUnknown_03005560[i] = TRANSITION_STRUCT.field_16; + } + + SetVBlankCallback(VBlankCB_Phase2_Transition_Ripple); + SetHBlankCallback(HBlankCB_Phase2_Transition_Ripple); + + REG_IE |= INTR_FLAG_HBLANK; + REG_DISPSTAT |= DISPSTAT_HBLANK_INTR; + + task->tState++; + return TRUE; +} + +static bool8 Phase2_Transition_Ripple_Func2(struct Task* task) +{ + u8 i; + s16 r3; + u16 r4, r8; + + TRANSITION_STRUCT.VBlank_DMA = 0; + + r3 = task->data[2] >> 8; + r4 = task->data[1]; + r8 = 384; + task->data[1] += 0x400; + if (task->data[2] <= 0x1FFF) + task->data[2] += 0x180; + + for (i = 0; i < 160; i++, r4 += r8) + { + // todo: fix the asm + s16 var = r4 >> 8; + asm(""); + gUnknown_03004DE0[0][i] = TRANSITION_STRUCT.field_16 + Sin(var, r3); + asm(""); + } + + if (++task->data[3] == 81) + { + task->data[4]++; + BeginNormalPaletteFade(-1, -2, 0, 0x10, 0); + } + + if (task->data[4] != 0 && !gPaletteFade.active) + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_Ripple)); + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static void VBlankCB_Phase2_Transition_Ripple(void) +{ + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); +} + +static void HBlankCB_Phase2_Transition_Ripple(void) +{ + u16 var = gUnknown_03004DE0[1][REG_VCOUNT]; + REG_BG1VOFS = var; + REG_BG2VOFS = var; + REG_BG3VOFS = var; +} + +static void Phase2Task_Transition_Wave(u8 taskID) +{ + while (sPhase2_Transition_Wave_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_Wave_Func1(struct Task* task) +{ + u8 i; + + sub_811D658(); + dp12_8087EA4(); + + TRANSITION_STRUCT.WININ = 63; + TRANSITION_STRUCT.WINOUT = 0; + TRANSITION_STRUCT.field_6 = 240; + TRANSITION_STRUCT.WIN0V = 160; + + for (i = 0; i < 160; i++) + { + gUnknown_03004DE0[1][i] = 242; + } + + SetVBlankCallback(VBlankCB_Phase2_Transition_Wave); + + task->tState++; + return TRUE; +} + +static bool8 Phase2_Transition_Wave_Func2(struct Task* task) +{ + u8 i, r5; + u16* toStore; + bool8 nextFunc; + + TRANSITION_STRUCT.VBlank_DMA = 0; + toStore = gUnknown_03004DE0[0]; + r5 = task->data[2]; + task->data[2] += 16; + task->data[1] += 8; + + for (i = 0, nextFunc = TRUE; i < 160; i++, r5 += 4, toStore++) + { + s16 value = task->data[1] + Sin(r5, 40); + if (value < 0) + value = 0; + if (value > 240) + value = 240; + *toStore = (value << 8) | (0xF1); + if (value < 240) + nextFunc = FALSE; + } + if (nextFunc) + task->tState++; + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_Wave_Func3(struct Task* task) +{ + DmaStop(0); + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_Wave)); + return FALSE; +} + +static void VBlankCB_Phase2_Transition_Wave(void) +{ + DmaStop(0); + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA != 0) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); + REG_WININ = TRANSITION_STRUCT.WININ; + REG_WINOUT = TRANSITION_STRUCT.WINOUT; + REG_WIN0V = TRANSITION_STRUCT.WIN0V; + DmaSet(0, gUnknown_03004DE0[1], ®_WIN0H, 0xA2400001); +} + +#define tMugshotOpponentID data[13] +#define tMugshotPlayerID data[14] +#define tMugshotID data[15] + +static void Phase2Task_Transition_Sydney(u8 taskID) +{ + gTasks[taskID].tMugshotID = MUGSHOT_SYDNEY; + Phase2Task_MugShotTransition(taskID); +} + +static void Phase2Task_Transition_Phoebe(u8 taskID) +{ + gTasks[taskID].tMugshotID = MUGSHOT_PHOEBE; + Phase2Task_MugShotTransition(taskID); +} + +static void Phase2Task_Transition_Glacia(u8 taskID) +{ + gTasks[taskID].tMugshotID = MUGSHOT_GLACIA; + Phase2Task_MugShotTransition(taskID); +} + +static void Phase2Task_Transition_Drake(u8 taskID) +{ + gTasks[taskID].tMugshotID = MUGSHOT_DRAKE; + Phase2Task_MugShotTransition(taskID); +} + +static void Phase2Task_Transition_Steven(u8 taskID) +{ + gTasks[taskID].tMugshotID = MUGSHOT_STEVEN; + Phase2Task_MugShotTransition(taskID); +} + +static void Phase2Task_MugShotTransition(u8 taskID) +{ + while (sPhase2_Mugshot_Transition_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Mugshot_Func1(struct Task* task) +{ + u8 i; + + sub_811D658(); + dp12_8087EA4(); + Mugshots_CreateOpponentPlayerSprites(task); + + task->data[1] = 0; + task->data[2] = 1; + task->data[3] = 239; + TRANSITION_STRUCT.WININ = 63; + TRANSITION_STRUCT.WINOUT = 62; + TRANSITION_STRUCT.WIN0V = 160; + + for (i = 0; i < 160; i++) + { + gUnknown_03004DE0[1][i] = 0xF0F1; + } + + SetVBlankCallback(VBlankCB0_Phase2_Mugshots); + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Mugshot_Func2(struct Task* task) +{ + s16 i, j; + u16 *dst1, *dst2; + const u16* MugshotsMap; + + MugshotsMap = sMugshotsTilemap; + sub_811D6A8(&dst1, &dst2); + CpuSet(sUnknown_083FC348, dst2, 0xF0); + LoadPalette(sOpponentMugshotsPals[task->tMugshotID], 0xF0, 0x20); + LoadPalette(sPlayerMugshotsPals[gSaveBlock2.playerGender], 0xFA, 0xC); + + for (i = 0; i < 20; i++) + { + for (j = 0; j < 32; j++, MugshotsMap++) + { + dst1[i * 32 + j] = *MugshotsMap | 0xF000; + } + } + + REG_IE |= INTR_FLAG_HBLANK; + REG_DISPSTAT |= DISPSTAT_HBLANK_INTR; + SetHBlankCallback(HBlankCB_Phase2_Mugshots); + task->tState++; + return FALSE; +} + +static bool8 Phase2_Mugshot_Func3(struct Task* task) +{ + u8 i, r5; + u16* toStore; + s16 value; + s32 mergedValue; + + TRANSITION_STRUCT.VBlank_DMA = 0; + + toStore = gUnknown_03004DE0[0]; + r5 = task->data[1]; + task->data[1] += 0x10; + + for (i = 0; i < 80; i++, toStore++, r5 += 0x10) + { + value = task->data[2] + Sin(r5, 0x10); + if (value < 0) + value = 1; + if (value > 0xF0) + value = 0xF0; + *toStore = value; + } + for (; i < 160; i++, toStore++, r5 += 0x10) + { + value = task->data[3] - Sin(r5, 0x10); + if (value < 0) + value = 0; + if (value > 0xEF) + value = 0xEF; + *toStore = (value << 8) | (0xF0); + } + + task->data[2] += 8; + task->data[3] -= 8; + if (task->data[2] > 0xF0) + task->data[2] = 0xF0; + if (task->data[3] < 0) + task->data[3] = 0; + mergedValue = *(s32*)(&task->data[2]); + if (mergedValue == 0xF0) + task->tState++; + + TRANSITION_STRUCT.field_18 -= 8; + TRANSITION_STRUCT.field_1A += 8; + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Mugshot_Func4(struct Task* task) +{ + u8 i; + u16* toStore; + + TRANSITION_STRUCT.VBlank_DMA = 0; + + for (i = 0, toStore = gUnknown_03004DE0[0]; i < 160; i++, toStore++) + { + *toStore = 0xF0; + } + + task->tState++; + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 0; + TRANSITION_STRUCT.field_18 -= 8; + TRANSITION_STRUCT.field_1A += 8; + + sub_811CA10(task->tMugshotOpponentID, 0); + sub_811CA10(task->tMugshotPlayerID, 1); + sub_811CA28(task->tMugshotOpponentID); + + PlaySE(SE_BT_START); + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Mugshot_Func5(struct Task* task) +{ + TRANSITION_STRUCT.field_18 -= 8; + TRANSITION_STRUCT.field_1A += 8; + if (sub_811CA44(task->tMugshotOpponentID)) + { + task->tState++; + sub_811CA28(task->tMugshotPlayerID); + } + return FALSE; +} + +static bool8 Phase2_Mugshot_Func6(struct Task* task) +{ + TRANSITION_STRUCT.field_18 -= 8; + TRANSITION_STRUCT.field_1A += 8; + if (sub_811CA44(task->tMugshotPlayerID)) + { + TRANSITION_STRUCT.VBlank_DMA = 0; + SetVBlankCallback(NULL); + DmaStop(0); + memset(gUnknown_03004DE0[0], 0, 0x140); + memset(gUnknown_03004DE0[1], 0, 0x140); + REG_WIN0H = 0xF0; + REG_BLDY = 0; + task->tState++; + task->data[3] = 0; + task->data[4] = 0; + TRANSITION_STRUCT.BLDCNT = 0xBF; + SetVBlankCallback(VBlankCB1_Phase2_Mugshots); + } + return FALSE; +} + +static bool8 Phase2_Mugshot_Func7(struct Task* task) +{ + bool32 r6; + + TRANSITION_STRUCT.VBlank_DMA = 0; + r6 = TRUE; + TRANSITION_STRUCT.field_18 -= 8; + TRANSITION_STRUCT.field_1A += 8; + + if (task->data[4] < 0x50) + task->data[4] += 2; + if (task->data[4] > 0x50) + task->data[4] = 0x50; + + if (++task->data[3] & 1) + { + s16 i; + for (i = 0, r6 = FALSE; i <= task->data[4]; i++) + { + s16 index1 = 0x50 - i; + s16 index2 = 0x50 + i; + if (gUnknown_03004DE0[0][index1] <= 15) + { + r6 = TRUE; + gUnknown_03004DE0[0][index1]++; + } + if (gUnknown_03004DE0[0][index2] <= 15) + { + r6 = TRUE; + gUnknown_03004DE0[0][index2]++; + } + } + } + + if (task->data[4] == 0x50 && !r6) + task->tState++; + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Mugshot_Func8(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + BlendPalettes(-1, 0x10, 0x7FFF); + TRANSITION_STRUCT.BLDCNT = 0xFF; + task->data[3] = 0; + + task->tState++; + return TRUE; +} + +static bool8 Phase2_Mugshot_Func9(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + + task->data[3]++; + memset(gUnknown_03004DE0[0], task->data[3], 0x140); + if (task->data[3] > 15) + task->tState++; + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Mugshot_Func10(struct Task* task) +{ + DmaStop(0); + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(task->func)); + return FALSE; +} + +static void VBlankCB0_Phase2_Mugshots(void) +{ + DmaStop(0); + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA != 0) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); + REG_BG0VOFS = TRANSITION_STRUCT.field_1C; + REG_WININ = TRANSITION_STRUCT.WININ; + REG_WINOUT = TRANSITION_STRUCT.WINOUT; + REG_WIN0V = TRANSITION_STRUCT.WIN0V; + DmaSet(0, gUnknown_03004DE0[1], ®_WIN0H, 0xA2400001); +} + +static void VBlankCB1_Phase2_Mugshots(void) +{ + DmaStop(0); + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA != 0) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); + REG_BLDCNT = TRANSITION_STRUCT.BLDCNT; + DmaSet(0, gUnknown_03004DE0[1], ®_BLDY, 0xA2400001); +} + +static void HBlankCB_Phase2_Mugshots(void) +{ + if (REG_VCOUNT < 80) + REG_BG0HOFS = TRANSITION_STRUCT.field_18; + else + REG_BG0HOFS = TRANSITION_STRUCT.field_1A; +} + +static void Mugshots_CreateOpponentPlayerSprites(struct Task* task) +{ + struct Sprite *opponentSprite, *playerSprite; + + s16 mugshotID = task->tMugshotID; + task->tMugshotOpponentID = CreateTrainerSprite(sMugshotsTrainerPicIDsTable[mugshotID], + sMugshotsOpponentCoords[mugshotID][0] - 32, + sMugshotsOpponentCoords[mugshotID][1] + 42, + 0, &ewram[0xC03C]); + task->tMugshotPlayerID = CreateTrainerSprite(gSaveBlock2.playerGender, 272, 106, 0, &ewram[0xC03C]); + + opponentSprite = &gSprites[task->tMugshotOpponentID]; + playerSprite = &gSprites[task->tMugshotPlayerID]; + + opponentSprite->callback = sub_811C90C; + playerSprite->callback = sub_811C90C; + + opponentSprite->oam.affineMode = 3; + playerSprite->oam.affineMode = 3; + + opponentSprite->oam.matrixNum = AllocOamMatrix(); + playerSprite->oam.matrixNum = AllocOamMatrix(); + + opponentSprite->oam.shape = 1; + playerSprite->oam.shape = 1; + + opponentSprite->oam.size = 3; + playerSprite->oam.size = 3; + + CalcCenterToCornerVec(opponentSprite, 1, 3, 3); + CalcCenterToCornerVec(playerSprite, 1, 3, 3); + + SetOamMatrixRotationScaling(opponentSprite->oam.matrixNum, sMugshotsOpponentRotationScales[mugshotID][0], sMugshotsOpponentRotationScales[mugshotID][1], 0); + SetOamMatrixRotationScaling(playerSprite->oam.matrixNum, -512, 0x200, 0); +} + +static void sub_811C90C(struct Sprite* sprite) +{ + while (sUnknown_083FD880[sprite->data0](sprite)); +} + +static bool8 sub_811C934(struct Sprite* sprite) +{ + return FALSE; +} + +static bool8 sub_811C938(struct Sprite* sprite) +{ + s16 arr0[2]; + s16 arr1[2]; + + memcpy(arr0, sUnknown_083FD89C, sizeof(sUnknown_083FD89C)); + memcpy(arr1, sUnknown_083FD8A0, sizeof(sUnknown_083FD8A0)); + + sprite->data0++; + sprite->data1 = arr0[sprite->data7]; + sprite->data2 = arr1[sprite->data7]; + return TRUE; +} + +static bool8 sub_811C984(struct Sprite* sprite) +{ + sprite->pos1.x += sprite->data1; + if (sprite->data7 && sprite->pos1.x < 133) + sprite->data0++; + else if (!sprite->data7 && sprite->pos1.x > 103) + sprite->data0++; + return FALSE; +} + +static bool8 sub_811C9B8(struct Sprite* sprite) +{ + sprite->data1 += sprite->data2; + sprite->pos1.x += sprite->data1; + if (sprite->data1 == 0) + { + sprite->data0++; + sprite->data2 = -sprite->data2; + sprite->data6 = 1; + } + return FALSE; +} + +static bool8 sub_811C9E4(struct Sprite* sprite) +{ + sprite->data1 += sprite->data2; + sprite->pos1.x += sprite->data1; + if (sprite->pos1.x < -31 || sprite->pos1.x > 271) + sprite->data0++; + return FALSE; +} + +static void sub_811CA10(s16 spriteID, s16 value) +{ + gSprites[spriteID].data7 = value; +} + +static void sub_811CA28(s16 spriteID) +{ + gSprites[spriteID].data0++; +} + +static s16 sub_811CA44(s16 spriteID) +{ + return gSprites[spriteID].data6; +} + +#undef tMugshotOpponentID +#undef tMugshotPlayerID +#undef tMugshotID + +static void Phase2Task_Transition_Slice(u8 taskID) +{ + while (sPhase2_Transition_Slice_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_Slice_Func1(struct Task* task) +{ + u16 i; + + sub_811D658(); + dp12_8087EA4(); + + task->data[2] = 256; + task->data[3] = 1; + TRANSITION_STRUCT.WININ = 63; + TRANSITION_STRUCT.WINOUT = 0; + TRANSITION_STRUCT.WIN0V = 160; + + for (i = 0; i < 160; i++) + { + gUnknown_03004DE0[1][i] = TRANSITION_STRUCT.field_14; + gUnknown_03004DE0[1][160 + i] = 0xF0; + } + + REG_IE |= INTR_FLAG_HBLANK; + REG_DISPSTAT |= DISPSTAT_HBLANK_INTR; + + SetVBlankCallback(VBlankCB_Phase2_Transition_Slice); + SetHBlankCallback(HBlankCB_Phase2_Transition_Slice); + + task->tState++; + return TRUE; +} + +static bool8 Phase2_Transition_Slice_Func2(struct Task* task) +{ + u16 i; + + TRANSITION_STRUCT.VBlank_DMA = 0; + + task->data[1] += (task->data[2] >> 8); + if (task->data[1] > 0xF0) + task->data[1] = 0xF0; + if (task->data[2] <= 0xFFF) + task->data[2] += task->data[3]; + if (task->data[3] < 128) + task->data[3] <<= 1; // multiplying by two + + for (i = 0; i < 160; i++) + { + u16* storeLoc1 = &gUnknown_03004DE0[0][i]; + u16* storeLoc2 = &gUnknown_03004DE0[0][i + 160]; + if (1 & i) + { + *storeLoc1 = TRANSITION_STRUCT.field_14 + task->data[1]; + *storeLoc2 = 0xF0 - task->data[1]; + } + else + { + *storeLoc1 = TRANSITION_STRUCT.field_14 - task->data[1]; + *storeLoc2 = (task->data[1] << 8) | (0xF1); + } + } + + if (task->data[1] > 0xEF) + task->tState++; + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_Slice_Func3(struct Task* task) +{ + DmaStop(0); + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_Slice)); + return FALSE; +} + +static void VBlankCB_Phase2_Transition_Slice(void) +{ + DmaStop(0); + VBlankCB_BattleTransition(); + REG_WININ = TRANSITION_STRUCT.WININ; + REG_WINOUT = TRANSITION_STRUCT.WINOUT; + REG_WIN0V = TRANSITION_STRUCT.WIN0V; + if (TRANSITION_STRUCT.VBlank_DMA) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 640); + DmaSet(0, &gUnknown_03004DE0[1][160], ®_WIN0H, 0xA2400001); +} + +static void HBlankCB_Phase2_Transition_Slice(void) +{ + u16 var = gUnknown_03004DE0[1][REG_VCOUNT]; + REG_BG1HOFS = var; + REG_BG2HOFS = var; + REG_BG3HOFS = var; +} + +static void Phase2Task_Transition_WhiteFade(u8 taskID) +{ + while (sPhase2_Transition_WhiteFade_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_WhiteFade_Func1(struct Task* task) +{ + u16 i; + + sub_811D658(); + dp12_8087EA4(); + + TRANSITION_STRUCT.BLDCNT = 0xBF; + TRANSITION_STRUCT.BLDY = 0; + TRANSITION_STRUCT.WININ = 0x1E; + TRANSITION_STRUCT.WINOUT = 0x3F; + TRANSITION_STRUCT.WIN0V = 0xA0; + + for (i = 0; i < 160; i++) + { + gUnknown_03004DE0[1][i] = 0; + gUnknown_03004DE0[1][i + 160] = 0xF0; + } + + REG_IE |= INTR_FLAG_HBLANK; + REG_DISPSTAT |= DISPSTAT_HBLANK_INTR; + + SetHBlankCallback(HBlankCB_Phase2_Transition_WhiteFade); + SetVBlankCallback(VBlankCB0_Phase2_Transition_WhiteFade); + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_WhiteFade_Func2(struct Task* task) +{ + s16 i, posY; + s16 arr1[8]; + struct Sprite* sprite; + + memcpy(arr1, sUnknown_083FD8C4, sizeof(sUnknown_083FD8C4)); + for (i = 0, posY = 0; i < 8; i++, posY += 0x14) + { + sprite = &gSprites[CreateInvisibleSprite(sub_811CFD0)]; + sprite->pos1.x = 0xF0; + sprite->pos1.y = posY; + sprite->data5 = arr1[i]; + } + sprite->data6++; + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_WhiteFade_Func3(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + if (TRANSITION_STRUCT.field_20 > 7) + { + BlendPalettes(-1, 0x10, 0x7FFF); + task->tState++; + } + return FALSE; +} + +static bool8 Phase2_Transition_WhiteFade_Func4(struct Task* task) +{ + TRANSITION_STRUCT.VBlank_DMA = 0; + + DmaStop(0); + SetVBlankCallback(0); + SetHBlankCallback(0); + + TRANSITION_STRUCT.field_6 = 0xF0; + TRANSITION_STRUCT.BLDY = 0; + TRANSITION_STRUCT.BLDCNT = 0xFF; + TRANSITION_STRUCT.WININ = 0x3F; + + SetVBlankCallback(VBlankCB1_Phase2_Transition_WhiteFade); + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_WhiteFade_Func5(struct Task* task) +{ + if (++TRANSITION_STRUCT.BLDY > 16) + { + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_WhiteFade)); + } + return FALSE; +} + +static void VBlankCB0_Phase2_Transition_WhiteFade(void) +{ + DmaStop(0); + VBlankCB_BattleTransition(); + REG_BLDCNT = TRANSITION_STRUCT.BLDCNT; + REG_WININ = TRANSITION_STRUCT.WININ; + REG_WINOUT = TRANSITION_STRUCT.WINOUT; + REG_WIN0V = TRANSITION_STRUCT.field_6; + if (TRANSITION_STRUCT.VBlank_DMA) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 640); + DmaSet(0, &gUnknown_03004DE0[1][160], ®_WIN0H, 0xA2400001); +} + +static void VBlankCB1_Phase2_Transition_WhiteFade(void) +{ + VBlankCB_BattleTransition(); + REG_BLDY = TRANSITION_STRUCT.BLDY; + REG_BLDCNT = TRANSITION_STRUCT.BLDCNT; + REG_WININ = TRANSITION_STRUCT.WININ; + REG_WINOUT = TRANSITION_STRUCT.WINOUT; + REG_WIN0H = TRANSITION_STRUCT.field_6; + REG_WIN0V = TRANSITION_STRUCT.WIN0V; +} + +static void HBlankCB_Phase2_Transition_WhiteFade(void) +{ + REG_BLDY = gUnknown_03004DE0[1][REG_VCOUNT]; +} + +static void sub_811CFD0(struct Sprite* sprite) +{ + if (sprite->data5) + { + sprite->data5--; + if (sprite->data6) + TRANSITION_STRUCT.VBlank_DMA = 1; + } + else + { + u16 i; + u16* ptr1 = &gUnknown_03004DE0[0][sprite->pos1.y]; + u16* ptr2 = &gUnknown_03004DE0[0][sprite->pos1.y + 160]; + for (i = 0; i < 20; i++) + { + ptr1[i] = sprite->data0 >> 8; + ptr2[i] = (u8)(sprite->pos1.x); + } + if (sprite->pos1.x == 0 && sprite->data0 == 0x1000) + sprite->data1 = 1; + + sprite->pos1.x -= 16; + sprite->data0 += 0x80; + + if (sprite->pos1.x < 0) + sprite->pos1.x = 0; + if (sprite->data0 > 0x1000) + sprite->data0 = 0x1000; + + if (sprite->data6) + TRANSITION_STRUCT.VBlank_DMA = 1; + + if (sprite->data1) + { + if (sprite->data6 == 0 || (TRANSITION_STRUCT.field_20 > 6 && sprite->data2++ > 7)) + { + TRANSITION_STRUCT.field_20++; + DestroySprite(sprite); + } + } + } +} + +static void Phase2Task_Transition_GridSquares(u8 taskID) +{ + while (sPhase2_Transition_GridSquares_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_GridSquares_Func1(struct Task* task) +{ + u16 *dst1, *dst2; + + sub_811D6A8(&dst1, &dst2); + CpuSet(sShrinkingBoxTileset, dst2, 0x10); + CpuFill16(0xF000, dst1, 0x800); + LoadPalette(gFieldEffectObjectPalette10, 0xF0, 0x20); + + task->tState++; + return FALSE; +} + +static bool8 Phase2_Transition_GridSquares_Func2(struct Task* task) +{ + u16* dst1; + + if (task->data[1] == 0) + { + sub_811D690(&dst1); + task->data[1] = 3; + task->data[2]++; + CpuSet(sShrinkingBoxTileset + (task->data[2] * 8), dst1, 0x10); + if (task->data[2] > 0xD) + { + task->tState++; + task->data[1] = 16; + } + } + + task->data[1]--; + return FALSE; +} + +static bool8 Phase2_Transition_GridSquares_Func3(struct Task* task) +{ + if (--task->data[1] == 0) + { + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_GridSquares)); + } + return FALSE; +} + +static void Phase2Task_Transition_Shards(u8 taskID) +{ + while (sPhase2_Transition_Shards_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase2_Transition_Shards_Func1(struct Task* task) +{ + u16 i; + + sub_811D658(); + dp12_8087EA4(); + + TRANSITION_STRUCT.WININ = 0x3F; + TRANSITION_STRUCT.WINOUT = 0; + TRANSITION_STRUCT.WIN0V = 0xA0; + + for (i = 0; i < 160; i++) + { + gUnknown_03004DE0[0][i] = 0xF0; + } + + CpuSet(gUnknown_03004DE0[0], gUnknown_03004DE0[1], 0xA0); + SetVBlankCallback(VBlankCB_Phase2_Transition_Shards); + + task->tState++; + return TRUE; +} + +static bool8 Phase2_Transition_Shards_Func2(struct Task* task) +{ + sub_811D8FC(TRANSITION_STRUCT.data, + sUnknown_083FD8F4[task->data[1]][0], + sUnknown_083FD8F4[task->data[1]][1], + sUnknown_083FD8F4[task->data[1]][2], + sUnknown_083FD8F4[task->data[1]][3], + 1, 1); + task->data[2] = sUnknown_083FD8F4[task->data[1]][4]; + task->tState++; + return TRUE; +} + +static bool8 Phase2_Transition_Shards_Func3(struct Task* task) +{ + s16 i; + bool8 nextFunc; + + TRANSITION_STRUCT.VBlank_DMA = 0; + + for (i = 0, nextFunc = FALSE; i < 16; i++) + { + s16 r3 = gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] >> 8; + s16 r4 = gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] & 0xFF; + if (task->data[2] == 0) + { + if (r3 < TRANSITION_STRUCT.data[2]) + r3 = TRANSITION_STRUCT.data[2]; + if (r3 > r4) + r3 = r4; + } + else + { + if (r4 > TRANSITION_STRUCT.data[2]) + r4 = TRANSITION_STRUCT.data[2]; + if (r4 <= r3) + r4 = r3; + } + gUnknown_03004DE0[0][TRANSITION_STRUCT.data[3]] = (r4) | (r3 << 8); + if (nextFunc) + { + task->tState++; + break; + } + else + nextFunc = sub_811D978(TRANSITION_STRUCT.data, 1, 1); + } + + TRANSITION_STRUCT.VBlank_DMA++; + return FALSE; +} + +static bool8 Phase2_Transition_Shards_Func4(struct Task* task) +{ + if (++task->data[1] < 7) + { + task->tState++; + task->data[3] = sUnknown_083FD93A[task->data[1] - 1]; + return TRUE; + } + else + { + DmaStop(0); + sub_811D6D4(); + DestroyTask(FindTaskIdByFunc(Phase2Task_Transition_Shards)); + return FALSE; + } +} + +static bool8 Phase2_Transition_Shards_Func5(struct Task* task) +{ + if (--task->data[3] == 0) + { + task->tState = 1; + return TRUE; + } + else + return FALSE; +} + +static void VBlankCB_Phase2_Transition_Shards(void) +{ + DmaStop(0); + VBlankCB_BattleTransition(); + if (TRANSITION_STRUCT.VBlank_DMA) + DmaCopy16(3, gUnknown_03004DE0[0], gUnknown_03004DE0[1], 320); + REG_WININ = TRANSITION_STRUCT.WININ; + REG_WINOUT = TRANSITION_STRUCT.WINOUT; + REG_WIN0V = TRANSITION_STRUCT.WIN0V; + REG_WIN0H = gUnknown_03004DE0[1][0]; + DmaSet(0, gUnknown_03004DE0[1], ®_WIN0H, 0xA2400001); +} + +static void CreatePhase1Task(s16 a0, s16 a1, s16 a2, s16 a3, s16 a4) +{ + u8 taskID = CreateTask(Phase1_Task_RunFuncs, 3); + gTasks[taskID].data[1] = a0; + gTasks[taskID].data[2] = a1; + gTasks[taskID].data[3] = a2; + gTasks[taskID].data[4] = a3; + gTasks[taskID].data[5] = a4; + gTasks[taskID].data[6] = a0; +} + +static bool8 sub_811D52C(void) +{ + if (FindTaskIdByFunc(Phase1_Task_RunFuncs) == 0xFF) + return TRUE; + else + return FALSE; +} + +static void Phase1_Task_RunFuncs(u8 taskID) +{ + while (sPhase1_TransitionAll_Funcs[gTasks[taskID].tState](&gTasks[taskID])); +} + +static bool8 Phase1_TransitionAll_Func1(struct Task* task) +{ + if (task->data[6] == 0 || --task->data[6] == 0) + { + task->data[6] = task->data[1]; + task->data[7] += task->data[4]; + if (task->data[7] > 16) + task->data[7] = 16; + BlendPalettes(-1, task->data[7], 0x2D6B); + } + if (task->data[7] > 15) + { + task->tState++; + task->data[6] = task->data[2]; + } + return FALSE; +} + +static bool8 Phase1_TransitionAll_Func2(struct Task* task) +{ + if (task->data[6] == 0 || --task->data[6] == 0) + { + task->data[6] = task->data[2]; + task->data[7] -= task->data[5]; + if (task->data[7] < 0) + task->data[7] = 0; + BlendPalettes(-1, task->data[7], 0x2D6B); + } + if (task->data[7] == 0) + { + if (--task->data[3] == 0) + DestroyTask(FindTaskIdByFunc(Phase1_Task_RunFuncs)); + else + { + task->data[6] = task->data[1]; + task->tState = 0; + } + } + return FALSE; +} + +static void sub_811D658(void) +{ + struct TransitionData* const* dummy = &sTransitionStructPtr; + memset(*dummy, 0, sizeof(struct TransitionData)); + sub_8057B14(&TRANSITION_STRUCT.field_14, &TRANSITION_STRUCT.field_16); +} + +static void VBlankCB_BattleTransition(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void sub_811D690(u16** a0) +{ + u16 reg, *vram; + + reg = REG_BG0CNT >> 2; + reg <<= 0xE; + vram = (u16*)(VRAM + reg); + + *a0 = vram; +} + +static void sub_811D6A8(u16** a0, u16** a1) +{ + u16 reg0, reg1, *vram0, *vram1; + + reg0 = REG_BG0CNT >> 8; + reg1 = REG_BG0CNT >> 2; + + reg0 <<= 0xB; + reg1 <<= 0xE; + + vram0 = (u16*)(VRAM + reg0); + *a0 = vram0; + + vram1 = (u16*)(VRAM + reg1); + *a1 = vram1; +} + +static void sub_811D6D4(void) +{ + BlendPalettes(-1, 0x10, 0); +} + +static void sub_811D6E8(s16* array, s16 sinAdd, s16 index, s16 indexIncrementer, s16 amplitude, s16 arrSize) +{ + u8 i; + for (i = 0; arrSize > 0; arrSize--, i++, index += indexIncrementer) + { + array[i] = sinAdd + Sin(0xFF & index, amplitude); + } +} + +static void sub_811D764(u16* array, s16 a1, s16 a2, s16 a3) +{ + s16 i; + + memset(array, 0xA, 160 * sizeof(s16)); + for (i = 0; i < 64; i++) + { + s16 sinResult, cosResult; + s16 toStoreOrr, r2, r3, toStore, r7, r8; + + sinResult = Sin(i, a3); + cosResult = Cos(i, a3); + + toStoreOrr = a1 - sinResult; + toStore = a1 + sinResult; + r7 = a2 - cosResult; + r8 = a2 + cosResult; + + if (toStoreOrr < 0) + toStoreOrr = 0; + if (toStore > 0xF0) + toStore = 0xF0; + if (r7 < 0) + r7 = 0; + if (r8 > 0x9F) + r8 = 0x9F; + + toStore |= (toStoreOrr << 8); + array[r7] = toStore; + array[r8] = toStore; + + cosResult = Cos(i + 1, a3); + r3 = a2 - cosResult; + r2 = a2 + cosResult; + + if (r3 < 0) + r3 = 0; + if (r2 > 0x9F) + r2 = 0x9F; + + while (r7 > r3) + array[--r7] = toStore; + while (r7 < r3) + array[++r7] = toStore; + + while (r8 > r2) + array[--r8] = toStore; + while (r8 < r2) + array[++r8] = toStore; + } +} + +static void sub_811D8FC(s16* data, s16 a1, s16 a2, s16 a3, s16 a4, s16 a5, s16 a6) +{ + data[0] = a1; + data[1] = a2; + data[2] = a1; + data[3] = a2; + data[4] = a3; + data[5] = a4; + data[6] = a5; + data[7] = a6; + data[8] = a3 - a1; + if (data[8] < 0) + { + data[8] = -data[8]; + data[6] = -a5; + } + data[9] = a4 - a2; + if (data[9] < 0) + { + data[9] = -data[9]; + data[7] = -a6; + } + data[10] = 0; +} + +static bool8 sub_811D978(s16* data, bool8 a1, bool8 a2) +{ + u8 var; + if (data[8] > data[9]) + { + data[2] += data[6]; + data[10] += data[9]; + if (data[10] > data[8]) + { + data[3] += data[7]; + data[10] -= data[8]; + } + } + else + { + data[3] += data[7]; + data[10] += data[8]; + if (data[10] > data[9]) + { + data[2] += data[6]; + data[10] -= data[9]; + } + } + var = 0; + if ((data[6] > 0 && data[2] >= data[4]) || (data[6] < 0 && data[2] <= data[4])) + { + var++; + if (a1) + data[2] = data[4]; + } + if ((data[7] > 0 && data[3] >= data[5]) || (data[7] < 0 && data[3] <= data[5])) + { + var++; + if (a2) + data[3] = data[5]; + } + if (var == 2) + return TRUE; + else + return FALSE; +} diff --git a/src/battle/calculate_base_damage.c b/src/battle/calculate_base_damage.c new file mode 100644 index 000000000..f5c679876 --- /dev/null +++ b/src/battle/calculate_base_damage.c @@ -0,0 +1,309 @@ +#include "global.h" +#include "abilities.h" +#include "battle.h" +#include "berry.h" +#include "data2.h" +#include "event_data.h" +#include "hold_effects.h" +#include "item.h" +#include "items.h" +#include "pokemon.h" +#include "species.h" +#include "moves.h" +#include "battle_move_effects.h" + +extern u32 dword_2017100[]; +extern u16 gBattleTypeFlags; +extern struct BattlePokemon gBattleMons[4]; +extern u16 gCurrentMove; +extern u8 gCritMultiplier; +extern u16 gBattleWeather; +extern struct BattleEnigmaBerry gEnigmaBerries[]; +extern u16 gBattleMovePower; +extern u16 gTrainerBattleOpponent; + +extern const u8 gHoldEffectToType[][2]; +extern const u8 gStatStageRatios[][2]; + +u8 GetBankSide(u8 bank); + +#define APPLY_STAT_MOD(var, mon, stat, statIndex) \ +{ \ + (var) = (stat) * (gStatStageRatios)[(mon)->statStages[(statIndex)]][0]; \ + (var) /= (gStatStageRatios)[(mon)->statStages[(statIndex)]][1]; \ +} + +s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef) +{ + u32 i; + s32 damage = 0; + s32 damageHelper; + u8 type; + u16 attack, defense; + u16 spAttack, spDefense; + u8 defenderHoldEffect; + u8 defenderHoldEffectParam; + u8 attackerHoldEffect; + u8 attackerHoldEffectParam; + + if (!powerOverride) + gBattleMovePower = gBattleMoves[move].power; + else + gBattleMovePower = powerOverride; + + if (!typeOverride) + type = gBattleMoves[move].type; + else + type = typeOverride & 0x3F; + + attack = attacker->attack; + defense = defender->defense; + spAttack = attacker->spAttack; + spDefense = defender->spDefense; + + if (attacker->item == ITEM_ENIGMA_BERRY) + { + attackerHoldEffect = gEnigmaBerries[bankAtk].holdEffect; + attackerHoldEffectParam = gEnigmaBerries[bankAtk].holdEffectParam; + } + else + { + attackerHoldEffect = ItemId_GetHoldEffect(attacker->item); + attackerHoldEffectParam = ItemId_GetHoldEffectParam(attacker->item); + } + + if (defender->item == ITEM_ENIGMA_BERRY) + { + defenderHoldEffect = gEnigmaBerries[bankDef].holdEffect; + defenderHoldEffectParam = gEnigmaBerries[bankDef].holdEffectParam; + } + else + { + defenderHoldEffect = ItemId_GetHoldEffect(defender->item); + defenderHoldEffectParam = ItemId_GetHoldEffectParam(defender->item); + } + + if (attacker->ability == ABILITY_HUGE_POWER || attacker->ability == ABILITY_PURE_POWER) + attack *= 2; + + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER))) + { + if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) + && gTrainerBattleOpponent != 1024 + && FlagGet(BADGE01_GET) + && !GetBankSide(bankAtk)) + attack = (110 * attack) / 100; + } + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER))) + { + if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) + && gTrainerBattleOpponent != 1024 + && FlagGet(BADGE05_GET) + && !GetBankSide(bankDef)) + defense = (110 * defense) / 100; + } + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER))) + { + if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) + && gTrainerBattleOpponent != 1024 + && FlagGet(BADGE07_GET) + && !GetBankSide(bankAtk)) + spAttack = (110 * spAttack) / 100; + } + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER))) + { + if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) + && gTrainerBattleOpponent != 1024 + && FlagGet(BADGE07_GET) + && !GetBankSide(bankDef)) + spDefense = (110 * spDefense) / 100; + } + + for (i = 0; i < 17; i++) + { + if (attackerHoldEffect == gHoldEffectToType[i][0] + && type == gHoldEffectToType[i][1]) + { + if (type <= 8) + attack = (attack * (attackerHoldEffectParam + 100)) / 100; + else + spAttack = (spAttack * (attackerHoldEffectParam + 100)) / 100; + break; + } + } + + if (attackerHoldEffect == HOLD_EFFECT_CHOICE_BAND) + attack = (150 * attack) / 100; + if (attackerHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) && (attacker->species == SPECIES_LATIAS || attacker->species == SPECIES_LATIOS)) + spAttack = (150 * spAttack) / 100; + if (defenderHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) && (defender->species == SPECIES_LATIAS || defender->species == SPECIES_LATIOS)) + spDefense = (150 * spDefense) / 100; + if (attackerHoldEffect == HOLD_EFFECT_DEEP_SEA_TOOTH && attacker->species == SPECIES_CLAMPERL) + spAttack *= 2; + if (defenderHoldEffect == HOLD_EFFECT_DEEP_SEA_SCALE && defender->species == SPECIES_CLAMPERL) + spDefense *= 2; + if (attackerHoldEffect == HOLD_EFFECT_LIGHT_BALL && attacker->species == SPECIES_PIKACHU) + spAttack *= 2; + if (defenderHoldEffect == HOLD_EFFECT_METAL_POWDER && defender->species == SPECIES_DITTO) + defense *= 2; + if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK)) + attack *= 2; + if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE)) + spAttack /= 2; + if (attacker->ability == ABILITY_HUSTLE) + attack = (150 * attack) / 100; + if (attacker->ability == ABILITY_PLUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MINUS, 0, 0)) + spAttack = (150 * spAttack) / 100; + if (attacker->ability == ABILITY_MINUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_PLUS, 0, 0)) + spAttack = (150 * spAttack) / 100; + if (attacker->ability == ABILITY_GUTS && attacker->status1) + attack = (150 * attack) / 100; + if (defender->ability == ABILITY_MARVEL_SCALE && defender->status1) + defense = (150 * defense) / 100; + if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFD, 0)) + gBattleMovePower /= 2; + if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFE, 0)) + gBattleMovePower /= 2; + if (type == TYPE_GRASS && attacker->ability == ABILITY_OVERGROW && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_FIRE && attacker->ability == ABILITY_BLAZE && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_WATER && attacker->ability == ABILITY_TORRENT && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION) + defense /= 2; + + if (type < TYPE_MYSTERY) // is physical + { + if (gCritMultiplier == 2) + { + if (attacker->statStages[STAT_STAGE_ATK] > 6) + APPLY_STAT_MOD(damage, attacker, attack, STAT_STAGE_ATK) + else + damage = attack; + } + else + APPLY_STAT_MOD(damage, attacker, attack, STAT_STAGE_ATK) + + damage = damage * gBattleMovePower; + damage *= (2 * attacker->level / 5 + 2); + + if (gCritMultiplier == 2) + { + if (defender->statStages[STAT_STAGE_DEF] < 6) + APPLY_STAT_MOD(damageHelper, defender, defense, STAT_STAGE_DEF) + else + damageHelper = defense; + } + else + APPLY_STAT_MOD(damageHelper, defender, defense, STAT_STAGE_DEF) + + damage = damage / damageHelper; + damage /= 50; + + if ((attacker->status1 & STATUS_BURN) && attacker->ability != ABILITY_GUTS) + damage /= 2; + + if ((sideStatus & SIDE_STATUS_REFLECT) && gCritMultiplier == 1) + { + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMons(2) == 2) + damage = 2 * (damage / 3); + else + damage /= 2; + } + + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMons(2) == 2) + damage /= 2; + + // moves always do at least 1 damage. + if (damage == 0) + damage = 1; + } + + if (type == TYPE_MYSTERY) + damage = 0; // is ??? type. does 0 damage. + + if (type > TYPE_MYSTERY) // is special? + { + if (gCritMultiplier == 2) + { + if (attacker->statStages[STAT_STAGE_SPATK] > 6) + APPLY_STAT_MOD(damage, attacker, spAttack, STAT_STAGE_SPATK) + else + damage = spAttack; + } + else + APPLY_STAT_MOD(damage, attacker, spAttack, STAT_STAGE_SPATK) + + damage = damage * gBattleMovePower; + damage *= (2 * attacker->level / 5 + 2); + + if (gCritMultiplier == 2) + { + if (defender->statStages[STAT_STAGE_SPDEF] < 6) + APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_STAGE_SPDEF) + else + damageHelper = spDefense; + } + else + APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_STAGE_SPDEF) + + damage = (damage / damageHelper); + damage /= 50; + + if ((sideStatus & SIDE_STATUS_LIGHTSCREEN) && gCritMultiplier == 1) + { + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMons(2) == 2) + damage = 2 * (damage / 3); + else + damage /= 2; + } + + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMons(2) == 2) + damage /= 2; + + // are effects of weather negated with cloud nine or air lock + if (!AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_CLOUD_NINE, 0, 0) + && !AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_AIR_LOCK, 0, 0)) + { + if (gBattleWeather & WEATHER_RAIN_TEMPORARY) + { + switch (type) + { + case TYPE_FIRE: + damage /= 2; + break; + case TYPE_WATER: + damage = (15 * damage) / 10; + break; + } + } + + // any weather except sun weakens solar beam + if ((gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SANDSTORM_ANY | WEATHER_HAIL)) && gCurrentMove == MOVE_SOLAR_BEAM) + damage /= 2; + + // sunny + if (gBattleWeather & WEATHER_SUN_ANY) + { + switch (type) + { + case TYPE_FIRE: + damage = (15 * damage) / 10; + break; + case TYPE_WATER: + damage /= 2; + break; + } + } + } + + // flash fire triggered + if ((dword_2017100[bankAtk] & 1) && type == TYPE_FIRE) + damage = (15 * damage) / 10; + } + + return damage + 2; +} diff --git a/src/battle/contest_link_80C857C.c b/src/battle/contest_link_80C857C.c new file mode 100644 index 000000000..0ae98af09 --- /dev/null +++ b/src/battle/contest_link_80C857C.c @@ -0,0 +1,55 @@ +#include "global.h" +#include "link.h" + +#if GERMAN + +void de_sub_80C9274(bool32 arg0) { + if (deUnkValue2 != 1) + { + return; + } + + if (arg0) + { + deUnkValue2 = 3; + } + else + { + deUnkValue2 = 2; + } +} + +void de_sub_80C9294(bool32 arg0) { + if (deUnkValue2 == 1) + { + if (arg0) + { + deUnkValue2 = 3; + } + else + { + deUnkValue2 = 2; + } + + return; + } + + + if (deUnkValue2 == 2) + { + SendBlock(0, sBlockRequestLookupTable[deUnkValue1].address, sBlockRequestLookupTable[deUnkValue1].size); + + if (arg0) + { + deUnkValue2 = 0; + } + else + { + deUnkValue2 = 1; + } + + return; + } +} + +#endif diff --git a/src/battle/pokeball.c b/src/battle/pokeball.c new file mode 100644 index 000000000..ee3b95678 --- /dev/null +++ b/src/battle/pokeball.c @@ -0,0 +1,1193 @@ +#include "global.h" +#include "gba/m4a_internal.h" +#include "battle.h" +#include "decompress.h" +#include "graphics.h" +#include "m4a.h" +#include "main.h" +#include "pokeball.h" +#include "pokemon.h" +#include "rom_8077ABC.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "util.h" + +extern struct MusicPlayerInfo gMPlay_BGM; +extern u16 gBattleTypeFlags; +extern u8 gBankTarget; +extern u8 gActiveBank; +extern u16 gBattlePartyID[]; +extern u8 gObjectBankIDs[]; +extern u8 gDoingBattleAnim; +extern u8 gHealthboxIDs[]; + +#define GFX_TAG_POKEBALL 55000 +#define GFX_TAG_GREATBALL 55001 +#define GFX_TAG_SAFARIBALL 55002 +#define GFX_TAG_ULTRABALL 55003 +#define GFX_TAG_MASTERBALL 55004 +#define GFX_TAG_NETBALL 55005 +#define GFX_TAG_DIVEBALL 55006 +#define GFX_TAG_NESTBALL 55007 +#define GFX_TAG_REPEATBALL 55008 +#define GFX_TAG_TIMERBALL 55009 +#define GFX_TAG_LUXURYBALL 55010 +#define GFX_TAG_PREMIERBALL 55011 + +static const struct CompressedSpriteSheet sBallSpriteSheets[] = +{ + {gInterfaceGfx_PokeBall, 384, GFX_TAG_POKEBALL}, + {gInterfaceGfx_GreatBall, 384, GFX_TAG_GREATBALL}, + {gInterfaceGfx_SafariBall, 384, GFX_TAG_SAFARIBALL}, + {gInterfaceGfx_UltraBall, 384, GFX_TAG_ULTRABALL}, + {gInterfaceGfx_MasterBall, 384, GFX_TAG_MASTERBALL}, + {gInterfaceGfx_NetBall, 384, GFX_TAG_NETBALL}, + {gInterfaceGfx_DiveBall, 384, GFX_TAG_DIVEBALL}, + {gInterfaceGfx_NestBall, 384, GFX_TAG_NESTBALL}, + {gInterfaceGfx_RepeatBall, 384, GFX_TAG_REPEATBALL}, + {gInterfaceGfx_TimerBall, 384, GFX_TAG_TIMERBALL}, + {gInterfaceGfx_LuxuryBall, 384, GFX_TAG_LUXURYBALL}, + {gInterfaceGfx_PremierBall, 384, GFX_TAG_PREMIERBALL}, +}; + +static const struct CompressedSpritePalette sBallSpritePalettes[] = +{ + {gInterfacePal_PokeBall, GFX_TAG_POKEBALL}, + {gInterfacePal_GreatBall, GFX_TAG_GREATBALL}, + {gInterfacePal_SafariBall, GFX_TAG_SAFARIBALL}, + {gInterfacePal_UltraBall, GFX_TAG_ULTRABALL}, + {gInterfacePal_MasterBall, GFX_TAG_MASTERBALL}, + {gInterfacePal_NetBall, GFX_TAG_NETBALL}, + {gInterfacePal_DiveBall, GFX_TAG_DIVEBALL}, + {gInterfacePal_NestBall, GFX_TAG_NESTBALL}, + {gInterfacePal_RepeatBall, GFX_TAG_REPEATBALL}, + {gInterfacePal_TimerBall, GFX_TAG_TIMERBALL}, + {gInterfacePal_LuxuryBall, GFX_TAG_LUXURYBALL}, + {gInterfacePal_PremierBall, GFX_TAG_PREMIERBALL}, +}; + +static const struct OamData sBallOamData = +{ + .y = 0, + .affineMode = 3, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 2, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd sBallAnimSeq3[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sBallAnimSeq5[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sBallAnimSeq4[] = +{ + ANIMCMD_FRAME(8, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sBallAnimSeq6[] = +{ + ANIMCMD_FRAME(12, 1), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sBallAnimSeq0[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sBallAnimSeq1[] = +{ + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sBallAnimSeq2[] = +{ + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sBallAnimSequences[] = +{ + sBallAnimSeq0, + sBallAnimSeq1, + sBallAnimSeq2, + + // unused? + sBallAnimSeq3, + sBallAnimSeq4, + sBallAnimSeq5, + sBallAnimSeq6, +}; + +static const union AffineAnimCmd sBallAffineAnimSeq0[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 0, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sBallAffineAnimSeq1[] = +{ + AFFINEANIMCMD_FRAME(0, 0, -3, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sBallAffineAnimSeq2[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 3, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sBallAffineAnimSeq3[] = +{ + AFFINEANIMCMD_FRAME(256, 256, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sBallAffineAnimSeq4[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 25, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sBallAffineAnimSequences[] = +{ + sBallAffineAnimSeq0, + sBallAffineAnimSeq1, + sBallAffineAnimSeq2, + sBallAffineAnimSeq3, + sBallAffineAnimSeq4, +}; + +static void objc_0804ABD4(struct Sprite *sprite); +const struct SpriteTemplate gBallSpriteTemplates[] = +{ + { + .tileTag = GFX_TAG_POKEBALL, + .paletteTag = GFX_TAG_POKEBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_GREATBALL, + .paletteTag = GFX_TAG_GREATBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_SAFARIBALL, + .paletteTag = GFX_TAG_SAFARIBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_ULTRABALL, + .paletteTag = GFX_TAG_ULTRABALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_MASTERBALL, + .paletteTag = GFX_TAG_MASTERBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_NETBALL, + .paletteTag = GFX_TAG_NETBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_DIVEBALL, + .paletteTag = GFX_TAG_DIVEBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_NESTBALL, + .paletteTag = GFX_TAG_NESTBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_REPEATBALL, + .paletteTag = GFX_TAG_REPEATBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_TIMERBALL, + .paletteTag = GFX_TAG_TIMERBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_LUXURYBALL, + .paletteTag = GFX_TAG_LUXURYBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, + { + .tileTag = GFX_TAG_PREMIERBALL, + .paletteTag = GFX_TAG_PREMIERBALL, + .oam = &sBallOamData, + .anims = sBallAnimSequences, + .images = NULL, + .affineAnims = sBallAffineAnimSequences, + .callback = objc_0804ABD4, + }, +}; + +extern u32 ball_number_to_ball_processing_index(u16); // not sure of return type +extern void sub_80786EC(); +extern bool8 sub_8078718(struct Sprite *); +extern u8 sub_814086C(u8, u8, int, int, u8); +extern u8 sub_8141314(u8, u8, int, u8); + +static void sub_8046464(u8); +static void sub_80466E8(struct Sprite *); +static void sub_80466F4(struct Sprite *); +static void sub_8046760(struct Sprite *); +static void sub_80467F8(struct Sprite *); +static void sub_804684C(struct Sprite *); +static void sub_8046944(struct Sprite *); +static void sub_8046984(struct Sprite *); +static void sub_8046C78(struct Sprite *); +static void sub_8046E7C(struct Sprite *); +static void sub_8046E9C(struct Sprite *); +static void sub_8046FBC(struct Sprite *); +static void sub_8047074(struct Sprite *); +static void sub_80470C4(struct Sprite *); +static void sub_8047230(struct Sprite *); +static void sub_8047254(struct Sprite *); +static void sub_80473D0(struct Sprite *); +static void sub_804748C(struct Sprite *); +static void sub_8047638(struct Sprite *); +static void sub_80476E0(struct Sprite *); +static void sub_8047754(struct Sprite *); +static void sub_804780C(struct Sprite *); +static void sub_8047830(struct Sprite *); +static void oamc_804BEB4(struct Sprite *); +static u16 sub_8047978(u8); + +u8 sub_8046400(u16 a, u8 b) +{ + u8 taskId; + + gDoingBattleAnim = 1; + ewram17810[gActiveBank].unk0_3 = 1; + taskId = CreateTask(sub_8046464, 5); + gTasks[taskId].data[1] = a; + gTasks[taskId].data[2] = b; + gTasks[taskId].data[3] = gActiveBank; + return 0; +} + +static void sub_8046464(u8 taskId) +{ + bool8 sp0 = FALSE; + u16 r8; + u8 r5; + u16 ball; + u8 r4; + u8 spriteId; + + if (gTasks[taskId].data[0] == 0) + { + gTasks[taskId].data[0]++; + return; + } + r8 = gTasks[taskId].data[2]; + r5 = gTasks[taskId].data[3]; + if (GetBankSide(r5) != 0) + ball = GetMonData(&gEnemyParty[gBattlePartyID[r5]], MON_DATA_POKEBALL); + else + ball = GetMonData(&gPlayerParty[gBattlePartyID[r5]], MON_DATA_POKEBALL); + r4 = ball_number_to_ball_processing_index(ball); + sub_80478DC(r4); + spriteId = CreateSprite(&gBallSpriteTemplates[r4], 32, 80, 0x1D); + gSprites[spriteId].data0 = 0x80; + gSprites[spriteId].data1 = 0; + gSprites[spriteId].data7 = r8; + switch (r8) + { + case 0xFF: + gBankTarget = r5; + gSprites[spriteId].pos1.x = 24; + gSprites[spriteId].pos1.y = 68; + gSprites[spriteId].callback = sub_8047074; + break; + case 0xFE: + gSprites[spriteId].pos1.x = sub_8077ABC(r5, 0); + gSprites[spriteId].pos1.y = sub_8077ABC(r5, 1) + 24; + gBankTarget = r5; + gSprites[spriteId].data0 = 0; + gSprites[spriteId].callback = sub_8047254; + break; + default: + gBankTarget = GetBankByPlayerAI(1); + sp0 = TRUE; + break; + } + gSprites[spriteId].data6 = gBankTarget; + if (!sp0) + { + DestroyTask(taskId); + return; + } + gSprites[spriteId].data0 = 0x22; + gSprites[spriteId].data2 = sub_8077ABC(gBankTarget, 0); + gSprites[spriteId].data4 = sub_8077ABC(gBankTarget, 1) - 16; + gSprites[spriteId].data5 = -40; + sub_80786EC(&gSprites[spriteId]); + gSprites[spriteId].oam.affineParam = taskId; + gTasks[taskId].data[4] = gBankTarget; + gTasks[taskId].func = TaskDummy; + PlaySE(SE_NAGERU); +} + +static void objc_0804ABD4(struct Sprite *sprite) +{ + if (sub_8078718(sprite)) + { + u8 taskId = sprite->oam.affineParam; + u8 r5 = gTasks[taskId].data[4]; + u8 r8 = gTasks[taskId].data[2]; + u32 r4; // not sure of this type + + StartSpriteAnim(sprite, 1); + sprite->affineAnimPaused = TRUE; + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + sprite->data5 = 0; + r4 = ball_number_to_ball_processing_index(sub_8047978(r5)); + sub_814086C(sprite->pos1.x, sprite->pos1.y - 5, 1, 0x1C, r4); + sprite->data0 = sub_8141314(0, r5, 14, r4); + sprite->data6 = r5; + sprite->data7 = r8; + DestroyTask(taskId); + sprite->callback = sub_80466E8; + } +} + +static void sub_80466E8(struct Sprite *sprite) +{ + sprite->callback = sub_80466F4; +} + +static void sub_80466F4(struct Sprite *sprite) +{ + sprite->data5++; + if (sprite->data5 == 10) + { + sprite->data5 = 0; + sprite->callback = sub_8046760; + StartSpriteAffineAnim(&gSprites[gObjectBankIDs[sprite->data6]], 2); + AnimateSprite(&gSprites[gObjectBankIDs[sprite->data6]]); + gSprites[gObjectBankIDs[sprite->data6]].data1 = 0; + } +} + +static void sub_8046760(struct Sprite *sprite) +{ + sprite->data5++; + if (sprite->data5 == 11) + PlaySE(SE_SUIKOMU); + if (gSprites[gObjectBankIDs[sprite->data6]].affineAnimEnded) + { + StartSpriteAnim(sprite, 2); + gSprites[gObjectBankIDs[sprite->data6]].invisible = TRUE; + sprite->data5 = 0; + sprite->callback = sub_80467F8; + } + else + { + gSprites[gObjectBankIDs[sprite->data6]].data1 += 0x60; + gSprites[gObjectBankIDs[sprite->data6]].pos2.y = -gSprites[gObjectBankIDs[sprite->data6]].data1 >> 8; + } +} + +static void sub_80467F8(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + sprite->data5++; + if (sprite->data5 == 1) + { + sprite->data3 = 0; + sprite->data4 = 32; + sprite->data5 = 0; + sprite->pos1.y += Cos(0, 32); + sprite->pos2.y = -Cos(0, sprite->data4); + sprite->callback = sub_804684C; + } + } +} + +static void sub_804684C(struct Sprite *sprite) +{ + bool8 r5 = FALSE; + + switch (sprite->data3 & 0xFF) + { + case 0: + sprite->pos2.y = -Cos(sprite->data5, sprite->data4); + sprite->data5 += 4 + (sprite->data3 >> 8); + if (sprite->data5 >= 64) + { + sprite->data4 -= 10; + sprite->data3 += 0x101; + if (sprite->data3 >> 8 == 4) + r5 = TRUE; + switch (sprite->data3 >> 8) + { + case 1: + PlaySE(SE_KON); + break; + case 2: + PlaySE(SE_KON2); + break; + case 3: + PlaySE(SE_KON3); + break; + default: + PlaySE(SE_KON4); + break; + } + } + break; + case 1: + sprite->pos2.y = -Cos(sprite->data5, sprite->data4); + sprite->data5 -= 4 + (sprite->data3 >> 8); + if (sprite->data5 <= 0) + { + sprite->data5 = 0; + sprite->data3 &= 0xFF00; + } + break; + } + if (r5) + { + sprite->data3 = 0; + sprite->pos1.y += Cos(64, 32); + sprite->pos2.y = 0; + if (sprite->data7 == 0) + { + sprite->callback = sub_8046C78; + } + else + { + sprite->callback = sub_8046944; + sprite->data4 = 1; + sprite->data5 = 0; + } + } +} + +static void sub_8046944(struct Sprite *sprite) +{ + sprite->data3++; + if (sprite->data3 == 31) + { + sprite->data3 = 0; + sprite->affineAnimPaused = TRUE; + StartSpriteAffineAnim(sprite, 1); + sprite->callback = sub_8046984; + PlaySE(SE_BOWA); + } +} + +static void sub_8046984(struct Sprite *sprite) +{ + switch (sprite->data3 & 0xFF) + { + case 0: + case 2: + sprite->pos2.x += sprite->data4; + sprite->data5 += sprite->data4; + sprite->affineAnimPaused = FALSE; + if (sprite->data5 > 3 || sprite->data5 < -3) + { + sprite->data3++; + sprite->data5 = 0; + } + break; + case 1: + sprite->data5++; + if (sprite->data5 == 1) + { + sprite->data5 = 0; + sprite->data4 = -sprite->data4; + sprite->data3++; + sprite->affineAnimPaused = FALSE; + if (sprite->data4 < 0) + ChangeSpriteAffineAnim(sprite, 2); + else + ChangeSpriteAffineAnim(sprite, 1); + } + else + { + sprite->affineAnimPaused = TRUE; + } + break; + case 3: + sprite->data3 += 0x100; + if (sprite->data3 >> 8 == sprite->data7) + { + sprite->callback = sub_8046C78; + } + else + { + if (sprite->data7 == 4 && sprite->data3 >> 8 == 3) + { + sprite->callback = sub_8046E7C; + sprite->affineAnimPaused = TRUE; + } + else + { + sprite->data3++; + sprite->affineAnimPaused = TRUE; + } + } + break; + case 4: + default: + sprite->data5++; + if (sprite->data5 == 31) + { + sprite->data5 = 0; + sprite->data3 &= 0xFF00; + StartSpriteAffineAnim(sprite, 3); + if (sprite->data4 < 0) + StartSpriteAffineAnim(sprite, 2); + else + StartSpriteAffineAnim(sprite, 1); + PlaySE(SE_BOWA); + } + break; + } +} + +static void sub_8046AD0(u8 taskId) +{ + u8 r6 = gTasks[taskId].data[2]; + u8 r3 = gTasks[taskId].data[1]; + u16 species = gTasks[taskId].data[0]; + + switch (gTasks[taskId].data[15]) + { + case 0: + default: + if (gTasks[taskId].data[8] < 3) + gTasks[taskId].data[8]++; + else + gTasks[taskId].data[15] = r6 + 1; + break; + case 1: + PlayCry1(species, r3); + DestroyTask(taskId); + break; + case 2: + StopCryAndClearCrySongs(); + gTasks[taskId].data[10] = 3; + gTasks[taskId].data[15] = 20; + break; + case 20: + if (gTasks[taskId].data[10] != 0) + { + gTasks[taskId].data[10]--; + break; + } + PlayCry4(species, r3, 1); + DestroyTask(taskId); + break; + case 3: + gTasks[taskId].data[10] = 6; + gTasks[taskId].data[15] = 30; + break; + case 30: + if (gTasks[taskId].data[10] != 0) + { + gTasks[taskId].data[10]--; + break; + } + gTasks[taskId].data[15]++; + // fall through + case 31: + if (!IsCryPlayingOrClearCrySongs()) + { + StopCryAndClearCrySongs(); + gTasks[taskId].data[10] = 3; + gTasks[taskId].data[15]++; + } + break; + case 32: + if (gTasks[taskId].data[10] != 0) + { + gTasks[taskId].data[10]--; + break; + } + PlayCry4(species, r3, 0); + DestroyTask(taskId); + break; + } +} + +static void sub_8046C78(struct Sprite *sprite) +{ + u8 r5 = sprite->data6; + u32 r4; // not sure of this type + + StartSpriteAnim(sprite, 1); + r4 = ball_number_to_ball_processing_index(sub_8047978(r5)); + sub_814086C(sprite->pos1.x, sprite->pos1.y - 5, 1, 0x1C, r4); + sprite->data0 = sub_8141314(1, sprite->data6, 14, r4); + sprite->callback = sub_8046E9C; + if (gMain.inBattle) + { + struct Pokemon *pkmn; + u16 species; + s8 r8; + u16 r4_2; + u8 taskId; + + if (GetBankSide(r5) != 0) + { + pkmn = &gEnemyParty[gBattlePartyID[r5]]; + r8 = 25; + } + else + { + pkmn = &gPlayerParty[gBattlePartyID[r5]]; + r8 = -25; + } + species = GetMonData(pkmn, MON_DATA_SPECIES); + if ((r5 == GetBankByPlayerAI(0) || r5 == GetBankByPlayerAI(1)) + && IsDoubleBattle() && ewram17840.unk9_0) + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (IsBGMPlaying()) + m4aMPlayStop(&gMPlay_BGM); + } + else + { + m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 128); + } + } + if (!IsDoubleBattle() || !ewram17840.unk9_0) + r4_2 = 0; + else if (r5 == GetBankByPlayerAI(0) || r5 == GetBankByPlayerAI(1)) + r4_2 = 1; + else + r4_2 = 2; + taskId = CreateTask(sub_8046AD0, 3); + gTasks[taskId].data[0] = species; + gTasks[taskId].data[1] = r8; + gTasks[taskId].data[2] = r4_2; + gTasks[taskId].data[15] = 0; + } + StartSpriteAffineAnim(&gSprites[gObjectBankIDs[sprite->data6]], 1); + AnimateSprite(&gSprites[gObjectBankIDs[sprite->data6]]); + gSprites[gObjectBankIDs[sprite->data6]].data1 = 0x1000; +} + +static void sub_8046E7C(struct Sprite *sprite) +{ + sprite->animPaused = TRUE; + sprite->callback = sub_8046FBC; + sprite->data3 = 0; + sprite->data4 = 0; + sprite->data5 = 0; +} + +static void sub_8046E9C(struct Sprite *sprite) +{ + bool8 r7 = FALSE; + u8 r4 = sprite->data6; + + gSprites[gObjectBankIDs[r4]].invisible = FALSE; + if (sprite->animEnded) + sprite->invisible = TRUE; + if (gSprites[gObjectBankIDs[r4]].affineAnimEnded) + { + StartSpriteAffineAnim(&gSprites[gObjectBankIDs[r4]], 0); + r7 = TRUE; + } + else + { + gSprites[gObjectBankIDs[r4]].data1 -= 288; + gSprites[gObjectBankIDs[r4]].pos2.y = gSprites[gObjectBankIDs[r4]].data1 >> 8; + } + if (sprite->animEnded && r7) + { + s32 i; + u32 r3; + + gSprites[gObjectBankIDs[r4]].pos2.y = 0; + gDoingBattleAnim = 0; + ewram17810[r4].unk0_3 = 0; + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + for (r3 = 0, i = 0; i < 4; i++) + { + if (ewram17810[i].unk0_3 == 0) + r3++; + } + if (r3 == 4) + { + for (i = 0; i < 12; i++) + sub_804794C(i); + } + } +} + +static void sub_8046FBC(struct Sprite *sprite) +{ + u8 r7 = sprite->data6; + + sprite->data4++; + if (sprite->data4 == 40) + { + return; + } + else if (sprite->data4 == 95) + { + gDoingBattleAnim = 0; + m4aMPlayAllStop(); + PlaySE(BGM_FANFA5); + } + else if (sprite->data4 == 315) + { + FreeOamMatrix(gSprites[gObjectBankIDs[sprite->data6]].oam.matrixNum); + DestroySprite(&gSprites[gObjectBankIDs[sprite->data6]]); + DestroySpriteAndFreeResources(sprite); + if (gMain.inBattle) + ewram17810[r7].unk0_3 = 0; + } +} + +static void sub_8047074(struct Sprite *sprite) +{ + sprite->data0 = 25; + sprite->data2 = sub_8077ABC(sprite->data6, 2); + sprite->data4 = sub_8077ABC(sprite->data6, 3) + 24; + sprite->data5 = -30; + sprite->oam.affineParam = sprite->data6; + sub_80786EC(sprite); + sprite->callback = sub_80470C4; +} + +#define HIBYTE(x) (((x) >> 8) & 0xFF) + +static void sub_80470C4(struct Sprite *sprite) +{ + u32 r6; + u32 r7; + + if (HIBYTE(sprite->data7) >= 35 && HIBYTE(sprite->data7) < 80) + { + s16 r4; + + if ((sprite->oam.affineParam & 0xFF00) == 0) + { + r6 = sprite->data1 & 1; + r7 = sprite->data2 & 1; + sprite->data1 = ((sprite->data1 / 3) & ~1) | r6; + sprite->data2 = ((sprite->data2 / 3) & ~1) | r7; + StartSpriteAffineAnim(sprite, 4); + } + r4 = sprite->data0; + sub_8078B5C(sprite); + sprite->data7 += sprite->data6 / 3; + sprite->pos2.y += Sin(HIBYTE(sprite->data7), sprite->data5); + sprite->oam.affineParam += 0x100; + if ((sprite->oam.affineParam >> 8) % 3 != 0) + sprite->data0 = r4; + else + sprite->data0 = r4 - 1; + if (HIBYTE(sprite->data7) >= 80) + { + r6 = sprite->data1 & 1; + r7 = sprite->data2 & 1; + sprite->data1 = ((sprite->data1 * 3) & ~1) | r6; + sprite->data2 = ((sprite->data2 * 3) & ~1) | r7; + } + } + else + { + if (sub_8078718(sprite)) + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + sprite->data6 = sprite->oam.affineParam & 0xFF; + sprite->data0 = 0; + if (IsDoubleBattle() && ewram17840.unk9_0 + && sprite->data6 == GetBankByPlayerAI(2)) + sprite->callback = sub_8047230; + else + sprite->callback = sub_8046C78; + StartSpriteAffineAnim(sprite, 0); + } + } +} + +static void sub_8047230(struct Sprite *sprite) +{ + if (sprite->data0++ > 24) + { + sprite->data0 = 0; + sprite->callback = sub_8046C78; + } +} + +static void sub_8047254(struct Sprite *sprite) +{ + sprite->data0++; + if (sprite->data0 > 15) + { + sprite->data0 = 0; + if (IsDoubleBattle() && ewram17840.unk9_0 + && sprite->data6 == GetBankByPlayerAI(3)) + sprite->callback = sub_8047230; + else + sprite->callback = sub_8046C78; + } +} + +static u8 sub_80472B0(u8 a, u8 b, u8 c, u8 d) +{ + return sub_814086C(a, b, c, d, 0); +} + +static u8 sub_80472D8(u8 a, u8 b, u32 c) +{ + return sub_8141314(a, b, c, 0); +} + +void CreatePokeballSprite(u8 a, u8 b, u8 x, u8 y, u8 e, u8 f, u8 g, u32 h) +{ + u8 spriteId; + + LoadCompressedObjectPic(&sBallSpriteSheets[0]); + LoadCompressedObjectPalette(&sBallSpritePalettes[0]); + spriteId = CreateSprite(&gBallSpriteTemplates[0], x, y, f); + gSprites[spriteId].data0 = a; + gSprites[spriteId].data5 = gSprites[a].pos1.x; + gSprites[spriteId].data6 = gSprites[a].pos1.y; + gSprites[a].pos1.x = x; + gSprites[a].pos1.y = y; + gSprites[spriteId].data1 = g; + gSprites[spriteId].data2 = b; + gSprites[spriteId].data3 = h; + gSprites[spriteId].data4 = h >> 16; + gSprites[spriteId].oam.priority = e; + gSprites[spriteId].callback = sub_80473D0; + gSprites[a].invisible = TRUE; +} + +static void sub_80473D0(struct Sprite *sprite) +{ + if (sprite->data1 == 0) + { + u8 r5; + u8 r7 = sprite->data0; + u8 r8 = sprite->data2; + u32 r4 = (u16)sprite->data3 | ((u16)sprite->data4 << 16); + + if (sprite->subpriority != 0) + r5 = sprite->subpriority - 1; + else + r5 = 0; + StartSpriteAnim(sprite, 1); + sub_80472B0(sprite->pos1.x, sprite->pos1.y - 5, sprite->oam.priority, r5); + sprite->data1 = sub_80472D8(1, r8, r4); + sprite->callback = sub_804748C; + gSprites[r7].invisible = FALSE; + StartSpriteAffineAnim(&gSprites[r7], 1); + AnimateSprite(&gSprites[r7]); + gSprites[r7].data1 = 0x1000; + sprite->data7 = 0; + } + else + { + sprite->data1--; + } +} + +static void sub_804748C(struct Sprite *sprite) +{ + bool8 r12 = FALSE; + bool8 r6 = FALSE; + u8 r3 = sprite->data0; + u16 var1; + u16 var2; + + if (sprite->animEnded) + sprite->invisible = TRUE; + if (gSprites[r3].affineAnimEnded) + { + StartSpriteAffineAnim(&gSprites[r3], 0); + r12 = TRUE; + } + var1 = (sprite->data5 - sprite->pos1.x) * sprite->data7 / 128 + sprite->pos1.x; + var2 = (sprite->data6 - sprite->pos1.y) * sprite->data7 / 128 + sprite->pos1.y; + gSprites[r3].pos1.x = var1; + gSprites[r3].pos1.y = var2; + if (sprite->data7 < 128) + { + s16 sine = -(gSineTable[(u8)sprite->data7] / 8); + + sprite->data7 += 4; + gSprites[r3].pos2.x = sine; + gSprites[r3].pos2.y = sine; + } + else + { + gSprites[r3].pos1.x = sprite->data5; + gSprites[r3].pos1.y = sprite->data6; + gSprites[r3].pos2.x = 0; + gSprites[r3].pos2.y = 0; + r6 = TRUE; + } + if (sprite->animEnded && r12 && r6) + DestroySpriteAndFreeResources(sprite); +} + +u8 sub_8047580(u8 a, u8 b, u8 x, u8 y, u8 e, u8 f, u8 g, u32 h) +{ + u8 spriteId; + + LoadCompressedObjectPic(&sBallSpriteSheets[0]); + LoadCompressedObjectPalette(&sBallSpritePalettes[0]); + spriteId = CreateSprite(&gBallSpriteTemplates[0], x, y, f); + gSprites[spriteId].data0 = a; + gSprites[spriteId].data1 = g; + gSprites[spriteId].data2 = b; + gSprites[spriteId].data3 = h; + gSprites[spriteId].data4 = h >> 16; + gSprites[spriteId].oam.priority = e; + gSprites[spriteId].callback = sub_8047638; + return spriteId; +} + +static void sub_8047638(struct Sprite *sprite) +{ + if (sprite->data1 == 0) + { + u8 r6; + u8 r7 = sprite->data0; + u8 r8 = sprite->data2; + u32 r5 = (u16)sprite->data3 | ((u16)sprite->data4 << 16); + + if (sprite->subpriority != 0) + r6 = sprite->subpriority - 1; + else + r6 = 0; + StartSpriteAnim(sprite, 1); + sub_80472B0(sprite->pos1.x, sprite->pos1.y - 5, sprite->oam.priority, r6); + sprite->data1 = sub_80472D8(1, r8, r5); + sprite->callback = sub_80476E0; + StartSpriteAffineAnim(&gSprites[r7], 2); + AnimateSprite(&gSprites[r7]); + gSprites[r7].data1 = 0; + } + else + { + sprite->data1--; + } +} + +static void sub_80476E0(struct Sprite *sprite) +{ + u8 r1; + + sprite->data5++; + if (sprite->data5 == 11) + PlaySE(SE_SUIKOMU); + r1 = sprite->data0; + if (gSprites[r1].affineAnimEnded) + { + StartSpriteAnim(sprite, 2); + gSprites[r1].invisible = TRUE; + sprite->data5 = 0; + sprite->callback = sub_8047754; + } + else + { + gSprites[r1].data1 += 96; + gSprites[r1].pos2.y = -gSprites[r1].data1 >> 8; + } +} + +static void sub_8047754(struct Sprite *sprite) +{ + if (sprite->animEnded) + sprite->callback = SpriteCallbackDummy; +} + +void obj_delete_and_free_associated_resources_(struct Sprite *sprite) +{ + DestroySpriteAndFreeResources(sprite); +} + +void sub_804777C(u8 a) +{ + struct Sprite *sprite = &gSprites[gHealthboxIDs[a]]; + + sprite->data0 = 5; + sprite->data1 = 0; + sprite->pos2.x = 0x73; + sprite->pos2.y = 0; + sprite->callback = sub_8047830; + if (GetBankSide(a) != 0) + { + sprite->data0 = -sprite->data0; + sprite->data1 = -sprite->data1; + sprite->pos2.x = -sprite->pos2.x; + sprite->pos2.y = -sprite->pos2.y; + } + gSprites[sprite->data5].callback(&gSprites[sprite->data5]); + if (GetBankIdentity(a) == 2) + sprite->callback = sub_804780C; +} + +static void sub_804780C(struct Sprite *sprite) +{ + sprite->data1++; + if (sprite->data1 == 20) + { + sprite->data1 = 0; + sprite->callback = sub_8047830; + } +} + +static void sub_8047830(struct Sprite *sprite) +{ + sprite->pos2.x -= sprite->data0; + sprite->pos2.y -= sprite->data1; + if (sprite->pos2.x == 0 && sprite->pos2.y == 0) + sprite->callback = SpriteCallbackDummy; +} + +void sub_8047858(u8 a) +{ + u8 spriteId; + + spriteId = CreateInvisibleSpriteWithCallback(oamc_804BEB4); + gSprites[spriteId].data0 = 1; + gSprites[spriteId].data1 = gHealthboxIDs[a]; + gSprites[spriteId].callback = oamc_804BEB4; +} + +static void oamc_804BEB4(struct Sprite *sprite) +{ + u8 r1 = sprite->data1; + + gSprites[r1].pos2.y = sprite->data0; + sprite->data0 = -sprite->data0; + sprite->data2++; + if (sprite->data2 == 21) + { + gSprites[r1].pos2.x = 0; + gSprites[r1].pos2.y = 0; + DestroySprite(sprite); + } +} + +void sub_80478DC(u8 a) +{ + u16 var; + + if (GetSpriteTileStartByTag(sBallSpriteSheets[a].tag) == 0xFFFF) + { + LoadCompressedObjectPic(&sBallSpriteSheets[a]); + LoadCompressedObjectPalette(&sBallSpritePalettes[a]); + } + switch (a) + { + case 6: + case 10: + case 11: + break; + default: + var = GetSpriteTileStartByTag(sBallSpriteSheets[a].tag); + LZDecompressVram(gUnknown_08D030D0, (void *)(VRAM + 0x10100 + var * 32)); + break; + } +} + +void sub_804794C(u8 a) +{ + FreeSpriteTilesByTag(sBallSpriteSheets[a].tag); + FreeSpritePaletteByTag(sBallSpritePalettes[a].tag); +} + +static u16 sub_8047978(u8 a) +{ + if (GetBankSide(a) == 0) + return GetMonData(&gPlayerParty[gBattlePartyID[a]], MON_DATA_POKEBALL); + else + return GetMonData(&gEnemyParty[gBattlePartyID[a]], MON_DATA_POKEBALL); +} diff --git a/src/battle/post_battle_event_funcs.c b/src/battle/post_battle_event_funcs.c new file mode 100644 index 000000000..27d7022fe --- /dev/null +++ b/src/battle/post_battle_event_funcs.c @@ -0,0 +1,69 @@ +#include "global.h" +#include "event_data.h" +#include "hall_of_fame.h" +#include "load_save.h" +#include "main.h" +#include "pokemon.h" +#include "overworld.h" +#include "script_pokemon_80C4.h" + +extern u8 gUnknown_02039324; + +int GameClear(void) +{ + int i; + bool32 ribbonGet; + + ScrSpecial_HealPlayerParty(); + + if (FlagGet(SYS_GAME_CLEAR) == TRUE) + { + gUnknown_02039324 = 1; + } + else + { + gUnknown_02039324 = 0; + FlagSet(SYS_GAME_CLEAR); + } + + if (!GetGameStat(1)) + SetGameStat(1, (gSaveBlock2.playTimeHours << 16) | (gSaveBlock2.playTimeMinutes << 8) | gSaveBlock2.playTimeSeconds); + + SetSecretBase2Field_9(); + + if (gSaveBlock2.playerGender == MALE) + sub_80537CC(1); + else + sub_80537CC(2); + + ribbonGet = FALSE; + + for (i = 0; i < 6; i++) + { + u8 val; + u8 *ptr = &val; + if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_BIT2) + && !GetMonData(&gPlayerParty[i], MON_DATA_SANITY_BIT3) + && !GetMonData(&gPlayerParty[i], MON_DATA_CHAMPION_RIBBON)) + { + *ptr = 1; + SetMonData(&gPlayerParty[i], MON_DATA_CHAMPION_RIBBON, ptr); + ribbonGet = TRUE; + } + } + + if (ribbonGet == TRUE) + { + IncrementGameStat(42); + FlagSet(SYS_RIBBON_GET); + } + + SetMainCallback2(sub_8141F90); + return 0; +} + +int sp0C8_whiteout_maybe(void) +{ + SetMainCallback2(CB2_WhiteOut); + return 0; +} diff --git a/src/battle/reshow_battle_screen.c b/src/battle/reshow_battle_screen.c new file mode 100644 index 000000000..343c8f183 --- /dev/null +++ b/src/battle/reshow_battle_screen.c @@ -0,0 +1,332 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "palette.h" +#include "main.h" +#include "unknown_task.h" +#include "text.h" +#include "rom_8077ABC.h" +#include "data2.h" + +extern struct SpriteTemplate gUnknown_02024E8C; +extern struct Window gUnknown_03004210; +extern u16 gUnknown_03004280; +extern u16 gUnknown_03004288; +extern u16 gUnknown_030042A4; +extern u16 gUnknown_030042C0; +extern u16 gUnknown_030041B0; +extern u16 gUnknown_030041B4; +extern u16 gUnknown_030041B8; +extern u16 gUnknown_030042A0; +extern u8 gReservedSpritePaletteCount; +extern u8 gActionSelectionCursor[4]; +extern u8 gBankInMenu; +extern u16 gBattlePartyID[4]; +extern u8 gNoOfAllBanks; +extern u16 gBattleTypeFlags; +extern u8 gObjectBankIDs[4]; +extern u8 gBattleMonForms[4]; +extern u8 gHealthboxIDs[4]; + +bool8 sub_800E414(u8 a0); +bool8 sub_8031C30(u8 a0); +void sub_8031EE8(void); +void sub_80327CC(void); +void sub_8032984(u8 a, u16 b); +void sub_800FCD4(void); +void BattleLoadOpponentMonSprite(struct Pokemon *, u8 bank); +void BattleLoadPlayerMonSprite(struct Pokemon *, u8 bank); +void BattleLoadSubstituteSprite(u8 bank, u8 b); +void LoadPlayerTrainerBankSprite(u16 a0, u8 bank); +u8 sub_8077F7C(u8 bank); +u8 sub_8077F68(u8 bank); +void nullsub_11(u8 healthboxID, u8 a1); +void sub_8043DB0(u8 bank); +u8 battle_make_oam_normal_battle(u8 bank); +u8 battle_make_oam_safari_battle(void); +void sub_8045A5C(u8 healthboxID, struct Pokemon*, u8); +void sub_8043F44(u8 bank); +void sub_8043DFC(u8 healthboxID); + +// this file's functions +static void CB2_ReshowBattleScreenAfterMenu(void); +static bool8 LoadAppropiateBankSprite(u8 bank); +static void sub_807B184(u8 bank); +static void sub_807B508(u8 bank); +static void sub_807B06C(void); + +#define gReshowState ewram[0x1FFFF] +#define gHelperState ewram[0x1FFFE] + +void nullsub_14(void) +{ + +} + +void ReshowBattleScreenAfterMenu(void) +{ + gPaletteFade.bufferTransferDisabled = 1; + SetHBlankCallback(0); + SetVBlankCallback(0); + REG_MOSAIC = 0; + gReshowState = 0; + gHelperState = 0; + SetMainCallback2(CB2_ReshowBattleScreenAfterMenu); +} + +static void CB2_ReshowBattleScreenAfterMenu(void) +{ + switch (gReshowState) + { + case 0: + dp12_8087EA4(); + SetUpWindowConfig(&gWindowConfig_81E6C58); + ResetPaletteFade(); + InitWindowFromConfig(&gUnknown_03004210, &gWindowConfig_81E6C58); + gUnknown_030042A4 = 0; + gUnknown_030042A0 = 0; + gUnknown_030042C0 = 0; + gUnknown_030041B4 = 0; + gUnknown_03004288 = 0; + gUnknown_03004280 = 0; + gUnknown_030041B0 = 0; + gUnknown_030041B8 = 0; + break; + case 1: + { + const u32 zero = 0; + CpuFastSet(&zero, (void*) VRAM, 0x1006000); + } + break; + case 2: + if (!sub_800E414(gHelperState)) + { + gHelperState++; + gReshowState--; + } + else + gHelperState = 0; + break; + case 3: + ResetSpriteData(); + break; + case 4: + FreeAllSpritePalettes(); + gReservedSpritePaletteCount = 4; + break; + case 5: + sub_8031EE8(); + break; + case 6: + if (sub_8031C30(gHelperState)) + gHelperState = 0; + else + { + gHelperState++; + gReshowState--; + } + break; + case 7: + if (!LoadAppropiateBankSprite(0)) + gReshowState--; + break; + case 8: + if (!LoadAppropiateBankSprite(1)) + gReshowState--; + break; + case 9: + if (!LoadAppropiateBankSprite(2)) + gReshowState--; + break; + case 10: + if (!LoadAppropiateBankSprite(3)) + gReshowState--; + break; + case 11: + sub_807B184(0); + break; + case 12: + sub_807B184(1); + break; + case 13: + sub_807B184(2); + break; + case 14: + sub_807B184(3); + break; + case 15: + sub_807B508(0); + break; + case 16: + sub_807B508(1); + break; + case 17: + sub_807B508(2); + break; + case 18: + sub_807B508(3); + break; + case 19: + { + u8 opponentBank; + u16 species; + + sub_80327CC(); + + opponentBank = GetBankByPlayerAI(1); + species = GetMonData(&gEnemyParty[gBattlePartyID[opponentBank]], MON_DATA_SPECIES); + sub_8032984(opponentBank, species); + + if (IsDoubleBattle()) + { + opponentBank = GetBankByPlayerAI(3); + species = GetMonData(&gEnemyParty[gBattlePartyID[opponentBank]], MON_DATA_SPECIES); + sub_8032984(opponentBank, species); + } + sub_802E3E4(gActionSelectionCursor[gBankInMenu], 0); + } + break; + default: + SetHBlankCallback(sub_800FCD4); + SetVBlankCallback(sub_800FCFC); + sub_807B06C(); + BeginHardwarePaletteFade(0xFF, 0, 0x10, 0, 1); + gPaletteFade.bufferTransferDisabled = 0; + SetMainCallback2(sub_800F808); + break; + } + gReshowState++; +} + +static void sub_807B06C(void) +{ + struct BGCntrlBitfield *regBgcnt1, *regBgcnt2; + + sub_800D6D4(); + + regBgcnt1 = (void*)(®_BG1CNT); + regBgcnt1->charBaseBlock = 0; + + regBgcnt2 = (void*)(®_BG2CNT); + regBgcnt2->charBaseBlock = 0; +} + +static bool8 LoadAppropiateBankSprite(u8 bank) +{ + if (bank < gNoOfAllBanks) + { + if (GetBankSide(bank)) + { + if (!ewram17800[bank].substituteSprite) + BattleLoadOpponentMonSprite(&gEnemyParty[gBattlePartyID[bank]], bank); + else + BattleLoadSubstituteSprite(bank, 0); + } + else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && bank == 0) + LoadPlayerTrainerBankSprite(gSaveBlock2.playerGender, 0); + else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL && bank == 0) + LoadPlayerTrainerBankSprite(2, 0); + else if (!ewram17800[bank].substituteSprite) + BattleLoadPlayerMonSprite(&gPlayerParty[gBattlePartyID[bank]], bank); + else + BattleLoadSubstituteSprite(bank, 0); + + gHelperState = 0; + } + return 1; +} + +static void sub_807B184(u8 bank) +{ + if (bank < gNoOfAllBanks) + { + u8 posY; + + if (ewram17800[bank].substituteSprite) + posY = sub_8077F7C(bank); + else + posY = sub_8077F68(bank); + if (GetBankSide(bank)) + { + if (GetMonData(&gEnemyParty[gBattlePartyID[bank]], MON_DATA_HP) == 0) + return; + GetMonSpriteTemplate_803C56C(GetMonData(&gEnemyParty[gBattlePartyID[bank]], MON_DATA_SPECIES), GetBankIdentity(bank)); + gObjectBankIDs[bank] = CreateSprite(&gUnknown_02024E8C, sub_8077ABC(bank, 2), posY, sub_8079E90(bank)); + gSprites[gObjectBankIDs[bank]].oam.paletteNum = bank; + gSprites[gObjectBankIDs[bank]].callback = SpriteCallbackDummy; + gSprites[gObjectBankIDs[bank]].data0 = bank; + gSprites[gObjectBankIDs[bank]].data2 = GetMonData(&gEnemyParty[gBattlePartyID[bank]], MON_DATA_SPECIES); + StartSpriteAnim(&gSprites[gObjectBankIDs[bank]], gBattleMonForms[bank]); + } + else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && bank == 0) + { + GetMonSpriteTemplate_803C5A0(gSaveBlock2.playerGender, GetBankIdentity(0)); + gObjectBankIDs[bank] = CreateSprite(&gUnknown_02024E8C, 0x50, + (8 - gTrainerBackPicCoords[gSaveBlock2.playerGender].coords) * 4 + 80, + sub_8079E90(0)); + gSprites[gObjectBankIDs[bank]].oam.paletteNum = bank; + gSprites[gObjectBankIDs[bank]].callback = SpriteCallbackDummy; + gSprites[gObjectBankIDs[bank]].data0 = bank; + } + else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL && bank == 0) + { + GetMonSpriteTemplate_803C5A0(2, GetBankIdentity(0)); + gObjectBankIDs[bank] = CreateSprite(&gUnknown_02024E8C, 0x50, + (8 - gTrainerBackPicCoords[2].coords) * 4 + 80, + sub_8079E90(0)); + gSprites[gObjectBankIDs[bank]].oam.paletteNum = bank; + gSprites[gObjectBankIDs[bank]].callback = SpriteCallbackDummy; + gSprites[gObjectBankIDs[bank]].data0 = bank; + } + else + { + if (GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_HP) == 0) + return; + GetMonSpriteTemplate_803C56C(GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_SPECIES), GetBankIdentity(bank)); + gObjectBankIDs[bank] = CreateSprite(&gUnknown_02024E8C, sub_8077ABC(bank, 2), posY, sub_8079E90(bank)); + gSprites[gObjectBankIDs[bank]].oam.paletteNum = bank; + gSprites[gObjectBankIDs[bank]].callback = SpriteCallbackDummy; + gSprites[gObjectBankIDs[bank]].data0 = bank; + gSprites[gObjectBankIDs[bank]].data2 = GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_SPECIES); + StartSpriteAnim(&gSprites[gObjectBankIDs[bank]], gBattleMonForms[bank]); + } + gSprites[gObjectBankIDs[bank]].invisible = ewram17800[bank].invisible; + } +} + +static void sub_807B508(u8 bank) +{ + if (bank < gNoOfAllBanks) + { + u8 healthboxID; + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && bank == 0) + healthboxID = battle_make_oam_safari_battle(); + else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL && bank == 0) + return; + else + healthboxID = battle_make_oam_normal_battle(bank); + gHealthboxIDs[bank] = healthboxID; + sub_8043F44(bank); + sub_8043DFC(healthboxID); + if (GetBankSide(bank)) + sub_8045A5C(gHealthboxIDs[bank], &gEnemyParty[gBattlePartyID[bank]], 0); + else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + sub_8045A5C(gHealthboxIDs[bank], &gPlayerParty[gBattlePartyID[bank]], 10); + else + sub_8045A5C(gHealthboxIDs[bank], &gPlayerParty[gBattlePartyID[bank]], 0); + if (GetBankIdentity(bank) == 3 || GetBankIdentity(bank) == 2) + nullsub_11(gHealthboxIDs[bank], 1); + else + nullsub_11(gHealthboxIDs[bank], 0); + if (GetBankSide(bank)) + { + if (GetMonData(&gEnemyParty[gBattlePartyID[bank]], MON_DATA_HP) == 0) + sub_8043DB0(healthboxID); + } + else if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) + { + if (GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_HP) == 0) + sub_8043DB0(healthboxID); + } + } +} diff --git a/src/battle/smokescreen.c b/src/battle/smokescreen.c new file mode 100644 index 000000000..8345cb6ad --- /dev/null +++ b/src/battle/smokescreen.c @@ -0,0 +1,73 @@ +#include "global.h" +#include "data2.h" +#include "decompress.h" +#include "sprite.h" +#include "util.h" + + +static void sub_8046388(struct Sprite *); + + +u8 sub_8046234(s16 x, s16 y, u8 a3) +{ + u8 mainSpriteId; + u8 spriteId1, spriteId2, spriteId3, spriteId4; + struct Sprite *mainSprite; + + if (GetSpriteTileStartByTag(gUnknown_081FAEA4.tag) == 0xFFFF) + { + LoadCompressedObjectPic(&gUnknown_081FAEA4); + LoadCompressedObjectPalette(&gUnknown_081FAEAC); + } + + mainSpriteId = CreateInvisibleSpriteWithCallback(sub_8046388); + mainSprite = &gSprites[mainSpriteId]; + mainSprite->data1 = a3; + + spriteId1 = CreateSprite(&gSpriteTemplate_81FAF0C, x - 16, y - 16, 2); + gSprites[spriteId1].data0 = mainSpriteId; + mainSprite->data0++; + AnimateSprite(&gSprites[spriteId1]); + + spriteId2 = CreateSprite(&gSpriteTemplate_81FAF0C, x, y - 16, 2); + gSprites[spriteId2].data0 = mainSpriteId; + mainSprite->data0++; + StartSpriteAnim(&gSprites[spriteId2], 1); + AnimateSprite(&gSprites[spriteId2]); + + spriteId3 = CreateSprite(&gSpriteTemplate_81FAF0C, x - 16, y, 2); + gSprites[spriteId3].data0 = mainSpriteId; + mainSprite->data0++; + StartSpriteAnim(&gSprites[spriteId3], 2); + AnimateSprite(&gSprites[spriteId3]); + + spriteId4 = CreateSprite(&gSpriteTemplate_81FAF0C, x, y, 2); + gSprites[spriteId4].data0 = mainSpriteId; + mainSprite->data0++; + StartSpriteAnim(&gSprites[spriteId4], 3); + AnimateSprite(&gSprites[spriteId4]); + + return mainSpriteId; +} + +static void sub_8046388(struct Sprite *sprite) +{ + if (!sprite->data0) + { + FreeSpriteTilesByTag(gUnknown_081FAEA4.tag); + FreeSpritePaletteByTag(gUnknown_081FAEAC.tag); + if (!sprite->data1) + DestroySprite(sprite); + else + sprite->callback = SpriteCallbackDummy; + } +} + +void sub_80463CC(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + gSprites[sprite->data0].data0--; + DestroySprite(sprite); + } +} |