#include "global.h" #include "battle.h" #include "battle_anim.h" #include "constants/battle_anim.h" #include "sprite.h" #include "contest.h" #include "m4a.h" #include "pokemon.h" #include "battle_interface.h" #include "task.h" #include "decompress.h" #include "sound.h" #include "dma3.h" #include "bg.h" #include "gpu_regs.h" #include "palette.h" #include "main.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)) #define SCRIPT_READ_16(ptr) ((ptr)[0] | ((ptr)[1] << 8)) #define SCRIPT_READ_32(ptr) (((ptr)[0]) + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) #define SCRIPT_READ_PTR(ptr) ((const u8*)(SCRIPT_READ_32(ptr))) #define ANIM_SPRITE_INDEX_COUNT 8 extern u8 gBattleAttacker; extern u8 gBattleDefender; extern u16 gBattle_WIN0H; extern u16 gBattle_WIN0V; extern u16 gBattle_WIN1H; extern u16 gBattle_WIN1V; extern u16 gBattle_BG1_X; extern u16 gBattle_BG1_Y; extern u16 gBattle_BG2_X; extern u16 gBattle_BG2_Y; extern u16 gBattlePartyID[MAX_BATTLERS_COUNT]; extern u8 gBankSpriteIds[MAX_BATTLERS_COUNT]; extern struct MusicPlayerInfo gMPlayInfo_BGM; extern struct MusicPlayerInfo gMPlayInfo_SE1; extern struct MusicPlayerInfo gMPlayInfo_SE2; extern u8 gDecompressionBuffer[]; extern const u16 gUnknown_082C8D64[]; extern const u8 * const gBattleAnims_Moves[]; extern const struct CompressedSpriteSheet gBattleAnimPicTable[]; extern const struct CompressedSpritePalette gBattleAnimPaletteTable[]; extern const struct BattleAnimBackground gBattleAnimBackgroundTable[]; // this file's functions static void ScriptCmd_loadspritegfx(void); static void ScriptCmd_unloadspritegfx(void); static void ScriptCmd_createsprite(void); static void ScriptCmd_createvisualtask(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 ScriptCmd_clearmonbg(void); static void ScriptCmd_setalpha(void); static void ScriptCmd_blendoff(void); static void ScriptCmd_call(void); static void ScriptCmd_return(void); static void ScriptCmd_setarg(void); static void ScriptCmd_choosetwoturnanim(void); static void ScriptCmd_jumpifmoveturn(void); static void ScriptCmd_goto(void); static void ScriptCmd_fadetobg(void); static void ScriptCmd_restorebg(void); static void ScriptCmd_waitbgfadeout(void); static void ScriptCmd_waitbgfadein(void); static void ScriptCmd_changebg(void); static void ScriptCmd_playsewithpan(void); static void ScriptCmd_setpan(void); static void ScriptCmd_panse_1B(void); static void ScriptCmd_loopsewithpan(void); static void ScriptCmd_waitplaysewithpan(void); static void ScriptCmd_setbldcnt(void); static void ScriptCmd_createsoundtask(void); static void ScriptCmd_waitsound(void); static void ScriptCmd_jumpargeq(void); static void ScriptCmd_monbg_22(void); static void ScriptCmd_clearmonbg_23(void); static void ScriptCmd_jumpifcontest(void); static void ScriptCmd_fadetobgfromset(void); static void ScriptCmd_panse_26(void); static void ScriptCmd_panse_27(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 RunAnimScriptCommand(void); static void task_pA_ma0A_obj_to_bg_pal(u8 taskId); static void sub_80A46A0(void); static void sub_80A4980(u8 taskId); static void sub_80A4BB0(u8 taskId); static void Task_FadeToBg(u8 taskId); static void Task_PanFromInitialToTarget(u8 taskId); static void Task_LoopAndPlaySE(u8 taskId); static void Task_WaitAndPlaySE(u8 taskId); static void LoadDefaultBg(void); static void LoadMoveBg(u16 bgId); // ewram EWRAM_DATA static const u8 *sBattleAnimScriptPtr = NULL; EWRAM_DATA static const u8 *sBattleAnimScriptRetAddr = NULL; EWRAM_DATA void (*gAnimScriptCallback)(void) = NULL; EWRAM_DATA static s8 gAnimFramesToWait = 0; EWRAM_DATA bool8 gAnimScriptActive = FALSE; EWRAM_DATA u8 gAnimVisualTaskCount = 0; EWRAM_DATA u8 gAnimSoundTaskCount = 0; EWRAM_DATA struct DisableStruct *gAnimDisableStructPtr = NULL; EWRAM_DATA u32 gAnimMoveDmg = 0; EWRAM_DATA u16 gAnimMovePower = 0; EWRAM_DATA static u16 sAnimSpriteIndexArray[ANIM_SPRITE_INDEX_COUNT] = {0}; EWRAM_DATA u8 gAnimFriendship = 0; EWRAM_DATA u16 gWeatherMoveAnim = 0; EWRAM_DATA s16 gBattleAnimArgs[ANIM_ARGS_COUNT] = {0}; EWRAM_DATA static u16 sSoundAnimFramesToWait = 0; EWRAM_DATA static u8 sMonAnimTaskIdArray[2] = {0}; EWRAM_DATA u8 gAnimMoveTurn = 0; EWRAM_DATA static u8 sAnimBackgroundFadeState = 0; EWRAM_DATA static u16 sAnimMoveIndex = 0; // set but unused. EWRAM_DATA u8 gAnimBankAttacker = 0; EWRAM_DATA u8 gAnimBankTarget = 0; EWRAM_DATA u16 gAnimSpeciesByBanks[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gUnknown_02038440 = 0; // const rom data static void (* const sScriptCmdTable[])(void) = { ScriptCmd_loadspritegfx, ScriptCmd_unloadspritegfx, ScriptCmd_createsprite, ScriptCmd_createvisualtask, 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_setarg, ScriptCmd_choosetwoturnanim, ScriptCmd_jumpifmoveturn, ScriptCmd_goto, ScriptCmd_fadetobg, ScriptCmd_restorebg, ScriptCmd_waitbgfadeout, ScriptCmd_waitbgfadein, ScriptCmd_changebg, ScriptCmd_playsewithpan, ScriptCmd_setpan, ScriptCmd_panse_1B, ScriptCmd_loopsewithpan, ScriptCmd_waitplaysewithpan, ScriptCmd_setbldcnt, ScriptCmd_createsoundtask, ScriptCmd_waitsound, ScriptCmd_jumpargeq, ScriptCmd_monbg_22, ScriptCmd_clearmonbg_23, ScriptCmd_jumpifcontest, ScriptCmd_fadetobgfromset, 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 ClearBattleAnimationVars(void) { s32 i; gAnimFramesToWait = 0; gAnimScriptActive = FALSE; gAnimVisualTaskCount = 0; gAnimSoundTaskCount = 0; gAnimDisableStructPtr = NULL; gAnimMoveDmg = 0; gAnimMovePower = 0; gAnimFriendship = 0; // clear index array. for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) sAnimSpriteIndexArray[i] |= 0xFFFF; // clear anim args. for (i = 0; i < ANIM_ARGS_COUNT; i++) gBattleAnimArgs[i] = 0; sMonAnimTaskIdArray[0] = 0xFF; sMonAnimTaskIdArray[1] = 0xFF; gAnimMoveTurn = 0; sAnimBackgroundFadeState = 0; sAnimMoveIndex = 0; gAnimBankAttacker = 0; gAnimBankTarget = 0; gUnknown_02038440 = 0; } void DoMoveAnim(u16 move) { gAnimBankAttacker = gBattleAttacker; gAnimBankTarget = gBattleDefender; LaunchBattleAnimation(gBattleAnims_Moves, move, TRUE); } void LaunchBattleAnimation(const u8 *const animsTable[], u16 tableId, bool8 isMoveAnim) { s32 i; if (!IsContest()) { sub_80A8278(); UpdateOamPriorityInAllHealthboxes(0); for (i = 0; i < MAX_BATTLERS_COUNT; i++) { if (GetBattlerSide(i) != 0) gAnimSpeciesByBanks[i] = GetMonData(&gEnemyParty[gBattlePartyID[i]], MON_DATA_SPECIES); else gAnimSpeciesByBanks[i] = GetMonData(&gPlayerParty[gBattlePartyID[i]], MON_DATA_SPECIES); } } else { for (i = 0; i < 4; i++) gAnimSpeciesByBanks[i] = gContestResources->field_18->field_0; } if (!isMoveAnim) sAnimMoveIndex = 0; else sAnimMoveIndex = tableId; for (i = 0; i < ANIM_ARGS_COUNT; i++) gBattleAnimArgs[i] = 0; sMonAnimTaskIdArray[0] = 0xFF; sMonAnimTaskIdArray[1] = 0xFF; sBattleAnimScriptPtr = animsTable[tableId]; gAnimScriptActive = TRUE; gAnimFramesToWait = 0; gAnimScriptCallback = RunAnimScriptCommand; for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) sAnimSpriteIndexArray[i] |= 0xFFFF; if (isMoveAnim) { for (i = 0; gUnknown_082C8D64[i] != 0xFFFF; i++) { if (tableId == gUnknown_082C8D64[i]) { m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 128); break; } } } gBattle_WIN0H = 0; gBattle_WIN0V = 0; gBattle_WIN1H = 0; gBattle_WIN1V = 0; } void DestroyAnimSprite(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 < ANIM_SPRITE_INDEX_COUNT; i++) { if (sAnimSpriteIndexArray[i] == 0xFFFF) { sAnimSpriteIndexArray[i] = index; return; } } } static void ClearSpriteIndex(u16 index) { s32 i; for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) { if (sAnimSpriteIndexArray[i] == index) { sAnimSpriteIndexArray[i] |= 0xFFFF; return; } } } static void WaitAnimFrameCount(void) { if (gAnimFramesToWait <= 0) { gAnimScriptCallback = RunAnimScriptCommand; gAnimFramesToWait = 0; } else { gAnimFramesToWait--; } } static void RunAnimScriptCommand(void) { do { sScriptCmdTable[sBattleAnimScriptPtr[0]](); } while (gAnimFramesToWait == 0 && gAnimScriptActive); } static void ScriptCmd_loadspritegfx(void) { u16 index; sBattleAnimScriptPtr++; index = SCRIPT_READ_16(sBattleAnimScriptPtr); LoadCompressedObjectPicUsingHeap(&gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)]); LoadCompressedObjectPaletteUsingHeap(&gBattleAnimPaletteTable[GET_TRUE_SPRITE_INDEX(index)]); sBattleAnimScriptPtr += 2; AddSpriteIndex(GET_TRUE_SPRITE_INDEX(index)); gAnimFramesToWait = 1; gAnimScriptCallback = WaitAnimFrameCount; } static void ScriptCmd_unloadspritegfx(void) { u16 index; sBattleAnimScriptPtr++; index = SCRIPT_READ_16(sBattleAnimScriptPtr); FreeSpriteTilesByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag); FreeSpritePaletteByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag); sBattleAnimScriptPtr += 2; ClearSpriteIndex(GET_TRUE_SPRITE_INDEX(index)); } static void ScriptCmd_createsprite(void) { s32 i; const struct SpriteTemplate *template; u8 argVar; u8 argsCount; s16 subpriority; sBattleAnimScriptPtr++; template = (const struct SpriteTemplate *)(SCRIPT_READ_32(sBattleAnimScriptPtr)); sBattleAnimScriptPtr += 4; argVar = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; argsCount = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; for (i = 0; i < argsCount; i++) { gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 2; } if (argVar & 0x80) { argVar ^= 0x80; if (argVar >= 0x40) argVar -= 0x40; else argVar *= -1; subpriority = sub_80A82E4(gAnimBankTarget) + (s8)(argVar); } else { if (argVar >= 0x40) argVar -= 0x40; else argVar *= -1; subpriority = sub_80A82E4(gAnimBankAttacker) + (s8)(argVar); } if (subpriority < 3) subpriority = 3; CreateSpriteAndAnimate(template, GetBankCoord(gAnimBankTarget, 2), GetBankCoord(gAnimBankTarget, 3), subpriority); gAnimVisualTaskCount++; } static void ScriptCmd_createvisualtask(void) { TaskFunc taskFunc; u8 taskPriority; u8 taskId; u8 numArgs; s32 i; sBattleAnimScriptPtr++; taskFunc = (TaskFunc)SCRIPT_READ_32(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 4; taskPriority = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; numArgs = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; for (i = 0; i < numArgs; i++) { gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 2; } taskId = CreateTask(taskFunc, taskPriority); taskFunc(taskId); gAnimVisualTaskCount++; } static void ScriptCmd_delay(void) { sBattleAnimScriptPtr++; gAnimFramesToWait = sBattleAnimScriptPtr[0]; if (gAnimFramesToWait == 0) gAnimFramesToWait = -1; sBattleAnimScriptPtr++; gAnimScriptCallback = WaitAnimFrameCount; } // wait for visual tasks to finish. static void ScriptCmd_waitforvisualfinish(void) { if (gAnimVisualTaskCount == 0) { sBattleAnimScriptPtr++; 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 || sMonAnimTaskIdArray[0] != 0xFF || sMonAnimTaskIdArray[1] != 0xFF) { sSoundAnimFramesToWait = 0; gAnimFramesToWait = 1; return; } // finish the sound effects. if (IsSEPlaying()) { if (++sSoundAnimFramesToWait <= 90) // wait 90 frames, then halt the sound effect. { gAnimFramesToWait = 1; return; } else { m4aMPlayStop(&gMPlayInfo_SE1); m4aMPlayStop(&gMPlayInfo_SE2); } } // the SE has halted, so set the SE Frame Counter to 0 and continue. sSoundAnimFramesToWait = 0; for (i = 0; i < ANIM_SPRITE_INDEX_COUNT; i++) { if (sAnimSpriteIndexArray[i] != 0xFFFF) { FreeSpriteTilesByTag(gBattleAnimPicTable[sAnimSpriteIndexArray[i]].tag); FreeSpritePaletteByTag(gBattleAnimPicTable[sAnimSpriteIndexArray[i]].tag); sAnimSpriteIndexArray[i] |= 0xFFFF; // set terminator. } } if (!continuousAnim) // may have been used for debug? { m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 256); if (!IsContest()) { sub_80A8278(); UpdateOamPriorityInAllHealthboxes(1); } gAnimScriptActive = FALSE; } } static void ScriptCmd_playse(void) { sBattleAnimScriptPtr++; PlaySE(SCRIPT_READ_16(sBattleAnimScriptPtr)); sBattleAnimScriptPtr += 2; } #define t1_MONBG_BANK 0 #define t1_MON_IN_BG2 1 #define t1_CREATE_ANOTHER_TASK 2 #define t1_IS_SECONDMON_BG 3 #define t2_BANK_SPRITE_ID 0 #define t2_MON_IN_BG2 5 #define t2_MONBG_BANK 6 static void sub_80A40F4(u8 taskId) { u8 newTaskId; s16 *selfData = gTasks[taskId].data; u8 bankSpriteId = gBankSpriteIds[selfData[t1_MONBG_BANK]]; gSprites[bankSpriteId].invisible = 1; if (!selfData[t1_CREATE_ANOTHER_TASK]) { DestroyAnimVisualTask(taskId); return; } newTaskId = CreateTask(task_pA_ma0A_obj_to_bg_pal, 10); gTasks[newTaskId].data[t2_BANK_SPRITE_ID] = bankSpriteId; gTasks[newTaskId].data[1] = gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x; gTasks[newTaskId].data[2] = gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y; if (!selfData[t1_MON_IN_BG2]) { gTasks[newTaskId].data[3] = gBattle_BG1_X; gTasks[newTaskId].data[4] = gBattle_BG1_Y; } else { gTasks[newTaskId].data[3] = gBattle_BG2_X; gTasks[newTaskId].data[4] = gBattle_BG2_Y; } gTasks[newTaskId].data[t2_MON_IN_BG2] = selfData[t1_MON_IN_BG2]; gTasks[newTaskId].data[t2_MONBG_BANK] = selfData[t1_MONBG_BANK]; sMonAnimTaskIdArray[selfData[t1_IS_SECONDMON_BG]] = newTaskId; DestroyAnimVisualTask(taskId); } static void ScriptCmd_monbg(void) { bool8 toBG_2; u8 taskId; u8 bank; u8 animBank; sBattleAnimScriptPtr++; animBank = sBattleAnimScriptPtr[0]; if (animBank & ANIM_TARGET) bank = gAnimBankTarget; else bank = gAnimBankAttacker; if (IsAnimBankSpriteVisible(bank)) { u8 position = GetBattlerPosition(bank); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; sub_80A438C(bank, toBG_2, FALSE); taskId = CreateTask(sub_80A40F4, 10); gAnimVisualTaskCount++; gTasks[taskId].data[t1_MONBG_BANK] = bank; gTasks[taskId].data[t1_MON_IN_BG2] = toBG_2; gTasks[taskId].data[t1_CREATE_ANOTHER_TASK] = TRUE; gTasks[taskId].data[t1_IS_SECONDMON_BG] = 0; } bank ^= BIT_FLANK; if (IsAnimBankSpriteVisible(bank)) { u8 position = GetBattlerPosition(bank); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; sub_80A438C(bank, toBG_2, FALSE); taskId = CreateTask(sub_80A40F4, 10); gAnimVisualTaskCount++; gTasks[taskId].data[0] = bank; gTasks[taskId].data[1] = toBG_2; gTasks[taskId].data[t1_CREATE_ANOTHER_TASK] = TRUE; gTasks[taskId].data[t1_IS_SECONDMON_BG] = 1; } sBattleAnimScriptPtr++; gAnimFramesToWait = 1; gAnimScriptCallback = WaitAnimFrameCount; } bool8 IsAnimBankSpriteVisible(u8 bank) { if (IsContest()) { if (bank == gAnimBankAttacker) return TRUE; else return FALSE; } if (!IsBankSpritePresent(bank)) return FALSE; if (IsContest()) return TRUE; // this line wont ever be reached. if (!gBattleSpritesDataPtr->bankData[bank].invisible || !gSprites[gBankSpriteIds[bank]].invisible) return TRUE; return FALSE; } void sub_80A438C(u8 bank, bool8 toBG_2, bool8 setSpriteInvisible) { struct UnknownAnimStruct2 unknownStruct; u8 bankSpriteId; if (!toBG_2) { u8 bankIdentity; if (IsContest() == TRUE) { RequestDma3Fill(0, (void*)(VRAM + 0x8000), 0x2000, 1); RequestDma3Fill(0xFF, (void*)(VRAM + 0xF000), 0x1000, 0); } else { RequestDma3Fill(0, (void*)(VRAM + 0x4000), 0x2000, 1); RequestDma3Fill(0xFF, (void*)(VRAM + 0xe000), 0x1000, 0); } sub_80A6B30(&unknownStruct); CpuFill16(0, unknownStruct.unk0, 0x1000); CpuFill16(0xFF, unknownStruct.unk4, 0x800); SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 2); SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 1); SetAnimBgAttribute(1, BG_ANIM_AREA_OVERFLOW_MODE, 0); bankSpriteId = gBankSpriteIds[bank]; gBattle_BG1_X = -(gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x) + 0x20; if (IsContest() && IsSpeciesNotUnown(gContestResources->field_18->field_0)) gBattle_BG1_X--; gBattle_BG1_Y = -(gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y) + 0x20; if (setSpriteInvisible) gSprites[gBankSpriteIds[bank]].invisible = 1; SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); LoadPalette(&gPlttBufferUnfaded[0x100 + bank * 16], unknownStruct.unk8 * 16, 0x20); CpuCopy32(&gPlttBufferUnfaded[0x100 + bank * 16], (void*)(BG_PLTT + unknownStruct.unk8 * 32), 0x20); if (IsContest()) bankIdentity = 0; else bankIdentity = GetBattlerPosition(bank); sub_8118FBC(1, 0, 0, bankIdentity, unknownStruct.unk8, unknownStruct.unk0, unknownStruct.unk4, unknownStruct.unkA); if (IsContest()) sub_80A46A0(); } else { RequestDma3Fill(0, (void*)(VRAM + 0x6000), 0x2000, 1); RequestDma3Fill(0, (void*)(VRAM + 0xF000), 0x1000, 1); sub_80A6B90(&unknownStruct, 2); CpuFill16(0, unknownStruct.unk0 + 0x1000, 0x1000); CpuFill16(0, unknownStruct.unk4 + 0x400, 0x800); SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); SetAnimBgAttribute(2, BG_ANIM_SCREEN_SIZE, 1); SetAnimBgAttribute(2, BG_ANIM_AREA_OVERFLOW_MODE, 0); bankSpriteId = gBankSpriteIds[bank]; gBattle_BG2_X = -(gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x) + 0x20; gBattle_BG2_Y = -(gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y) + 0x20; if (setSpriteInvisible) gSprites[gBankSpriteIds[bank]].invisible = 1; SetGpuReg(REG_OFFSET_BG2HOFS, gBattle_BG2_X); SetGpuReg(REG_OFFSET_BG2VOFS, gBattle_BG2_Y); LoadPalette(&gPlttBufferUnfaded[0x100 + bank * 16], 0x90, 0x20); CpuCopy32(&gPlttBufferUnfaded[0x100 + bank * 16], (void*)(BG_PLTT + 0x120), 0x20); sub_8118FBC(2, 0, 0, GetBattlerPosition(bank), unknownStruct.unk8, unknownStruct.unk0 + 0x1000, unknownStruct.unk4 + 0x400, unknownStruct.unkA); } } static void sub_80A46A0(void) { s32 i, j; struct UnknownAnimStruct2 unknownStruct; u16 *ptr; if (IsSpeciesNotUnown(gContestResources->field_18->field_0)) { sub_80A6B30(&unknownStruct); ptr = unknownStruct.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_80A4720(u16 a, u16 *b, u32 c, u8 d) { s32 i, j; s32 var; if (d == 0) var = 32; else var = 64; a <<= 12; for (i = 0; i < var; i++) { for (j = 0; j < 32; j++) b[j + i * 32] = ((b[j + i * 32] & 0xFFF) | a) + c; } } void sub_80A477C(bool8 to_BG2) { struct UnknownAnimStruct2 unknownStruct; sub_80A6B30(&unknownStruct); if (!to_BG2 || IsContest()) { sub_80A6C68(1); gBattle_BG1_X = 0; gBattle_BG1_Y = 0; } else { sub_80A6C68(2); gBattle_BG2_X = 0; gBattle_BG2_Y = 0; } } static void task_pA_ma0A_obj_to_bg_pal(u8 taskId) { u8 spriteId, palIndex; s16 x, y; struct UnknownAnimStruct2 unknownStruct; spriteId = gTasks[taskId].data[0]; palIndex = gTasks[taskId].data[6]; sub_80A6B30(&unknownStruct); x = gTasks[taskId].data[1] - (gSprites[spriteId].pos1.x + gSprites[spriteId].pos2.x); y = gTasks[taskId].data[2] - (gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y); if (gTasks[taskId].data[5] == 0) { u16 *src; u16 *dst; gBattle_BG1_X = x + gTasks[taskId].data[3]; gBattle_BG1_Y = y + gTasks[taskId].data[4]; src = gPlttBufferFaded + 0x100 + palIndex * 16; dst = gPlttBufferFaded + 0x100 + unknownStruct.unk8 * 16 - 256; CpuCopy32(src, dst, 0x20); } else { u16 *src; u16 *dst; gBattle_BG2_X = x + gTasks[taskId].data[3]; gBattle_BG2_Y = y + gTasks[taskId].data[4]; src = gPlttBufferFaded + 0x100 + palIndex * 16; dst = gPlttBufferFaded + 0x100 - 112; CpuCopy32(src, dst, 0x20); } } static void ScriptCmd_clearmonbg(void) { u8 animBankId; u8 bank; u8 taskId; sBattleAnimScriptPtr++; animBankId = sBattleAnimScriptPtr[0]; if (animBankId == ANIM_ATTACKER) animBankId = ANIM_ATK_PARTNER; else if (animBankId == ANIM_TARGET) animBankId = ANIM_DEF_PARTNER; if (animBankId == ANIM_ATTACKER || animBankId == ANIM_ATK_PARTNER) bank = gAnimBankAttacker; else bank = gAnimBankTarget; if (sMonAnimTaskIdArray[0] != 0xFF) gSprites[gBankSpriteIds[bank]].invisible = 0; if (animBankId > 1 && sMonAnimTaskIdArray[1] != 0xFF) gSprites[gBankSpriteIds[bank ^ BIT_FLANK]].invisible = 0; else animBankId = 0; taskId = CreateTask(sub_80A4980, 5); gTasks[taskId].data[0] = animBankId; gTasks[taskId].data[2] = bank; sBattleAnimScriptPtr++; } static void sub_80A4980(u8 taskId) { gTasks[taskId].data[1]++; if (gTasks[taskId].data[1] != 1) { u8 to_BG2; u8 position = GetBattlerPosition(gTasks[taskId].data[2]); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) to_BG2 = FALSE; else to_BG2 = TRUE; if (sMonAnimTaskIdArray[0] != 0xFF) { sub_80A477C(to_BG2); DestroyTask(sMonAnimTaskIdArray[0]); sMonAnimTaskIdArray[0] = 0xFF; } if (gTasks[taskId].data[0] > 1) { sub_80A477C(to_BG2 ^ 1); DestroyTask(sMonAnimTaskIdArray[1]); sMonAnimTaskIdArray[1] = 0xFF; } DestroyTask(taskId); } } static void ScriptCmd_monbg_22(void) { bool8 toBG_2; u8 bank; u8 animBankId; sBattleAnimScriptPtr++; animBankId = sBattleAnimScriptPtr[0]; if (animBankId == ANIM_ATTACKER) animBankId = ANIM_ATK_PARTNER; else if (animBankId == ANIM_TARGET) animBankId = ANIM_DEF_PARTNER; if (animBankId == ANIM_ATTACKER || animBankId == ANIM_ATK_PARTNER) bank = gAnimBankAttacker; else bank = gAnimBankTarget; if (IsAnimBankSpriteVisible(bank)) { u8 position = GetBattlerPosition(bank); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; sub_80A438C(bank, toBG_2, FALSE); } bank ^= BIT_FLANK; if (animBankId > 1 && IsAnimBankSpriteVisible(bank)) { u8 position = GetBattlerPosition(bank); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; sub_80A438C(bank, toBG_2, FALSE); } sBattleAnimScriptPtr++; } static void ScriptCmd_clearmonbg_23(void) { u8 animBankId; u8 bank; u8 taskId; sBattleAnimScriptPtr++; animBankId = sBattleAnimScriptPtr[0]; if (animBankId == ANIM_ATTACKER) animBankId = ANIM_ATK_PARTNER; else if (animBankId == ANIM_TARGET) animBankId = ANIM_DEF_PARTNER; if (animBankId == ANIM_ATTACKER || animBankId == ANIM_ATK_PARTNER) bank = gAnimBankAttacker; else bank = gAnimBankTarget; if (IsAnimBankSpriteVisible(bank)) gSprites[gBankSpriteIds[bank]].invisible = 0; if (animBankId > 1 && IsAnimBankSpriteVisible(bank ^ BIT_FLANK)) gSprites[gBankSpriteIds[bank ^ BIT_FLANK]].invisible = 0; else animBankId = 0; taskId = CreateTask(sub_80A4BB0, 5); gTasks[taskId].data[0] = animBankId; gTasks[taskId].data[2] = bank; sBattleAnimScriptPtr++; } static void sub_80A4BB0(u8 taskId) { gTasks[taskId].data[1]++; if (gTasks[taskId].data[1] != 1) { bool8 toBG_2; u8 bank = gTasks[taskId].data[2]; u8 position = GetBattlerPosition(bank); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; if (IsAnimBankSpriteVisible(bank)) sub_80A477C(toBG_2); if (gTasks[taskId].data[0] > 1 && IsAnimBankSpriteVisible(bank ^ BIT_FLANK)) sub_80A477C(toBG_2 ^ 1); DestroyTask(taskId); } } #undef t1_MONBG_BANK #undef t1_MON_IN_BG2 #undef t1_CREATE_ANOTHER_TASK #undef t1_IS_SECONDMON_BG #undef t2_BANK_SPRITE_ID #undef t2_MON_IN_BG2 #undef t2_MONBG_BANK static void ScriptCmd_setalpha(void) { u16 half1, half2; sBattleAnimScriptPtr++; half1 = *(sBattleAnimScriptPtr++); half2 = *(sBattleAnimScriptPtr++) << 8; SetGpuReg(REG_OFFSET_BLDCNT, 0x3F40); SetGpuReg(REG_OFFSET_BLDALPHA, half1 | half2); } static void ScriptCmd_setbldcnt(void) { u16 half1, half2; sBattleAnimScriptPtr++; half1 = *(sBattleAnimScriptPtr++); half2 = *(sBattleAnimScriptPtr++) << 8; SetGpuReg(REG_OFFSET_BLDCNT, half1 | half2); } static void ScriptCmd_blendoff(void) { sBattleAnimScriptPtr++; SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); } static void ScriptCmd_call(void) { sBattleAnimScriptPtr++; sBattleAnimScriptRetAddr = sBattleAnimScriptPtr + 4; sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); } static void ScriptCmd_return(void) { sBattleAnimScriptPtr = sBattleAnimScriptRetAddr; } static void ScriptCmd_setarg(void) { const u8 *addr = sBattleAnimScriptPtr; u16 value; u8 argId; sBattleAnimScriptPtr++; argId = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; value = SCRIPT_READ_16(sBattleAnimScriptPtr); sBattleAnimScriptPtr = addr + 4; gBattleAnimArgs[argId] = value; } static void ScriptCmd_choosetwoturnanim(void) { sBattleAnimScriptPtr++; if (gAnimMoveTurn & 1) sBattleAnimScriptPtr += 4; sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); } static void ScriptCmd_jumpifmoveturn(void) { u8 toCheck; sBattleAnimScriptPtr++; toCheck = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; if (toCheck == gAnimMoveTurn) sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); else sBattleAnimScriptPtr += 4; } static void ScriptCmd_goto(void) { sBattleAnimScriptPtr++; sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); } // 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; } #define tBackgroundId data[0] #define tState data[10] static void ScriptCmd_fadetobg(void) { u8 backgroundId; u8 taskId; sBattleAnimScriptPtr++; backgroundId = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; taskId = CreateTask(Task_FadeToBg, 5); gTasks[taskId].tBackgroundId = backgroundId; sAnimBackgroundFadeState = 1; } static void ScriptCmd_fadetobgfromset(void) { u8 bg1, bg2, bg3; u8 taskId; sBattleAnimScriptPtr++; bg1 = sBattleAnimScriptPtr[0]; bg2 = sBattleAnimScriptPtr[1]; bg3 = sBattleAnimScriptPtr[2]; sBattleAnimScriptPtr += 3; taskId = CreateTask(Task_FadeToBg, 5); if (IsContest()) gTasks[taskId].tBackgroundId = bg3; else if (GetBattlerSide(gAnimBankTarget) == B_SIDE_PLAYER) gTasks[taskId].tBackgroundId = bg2; else gTasks[taskId].tBackgroundId = bg1; sAnimBackgroundFadeState = 1; } static void Task_FadeToBg(u8 taskId) { if (gTasks[taskId].tState == 0) { BeginHardwarePaletteFade(0xE8, 0, 0, 16, 0); gTasks[taskId].tState++; return; } if (gPaletteFade.active) return; if (gTasks[taskId].tState == 1) { gTasks[taskId].tState++; sAnimBackgroundFadeState = 2; } else if (gTasks[taskId].tState == 2) { s16 bgId = gTasks[taskId].tBackgroundId; if (bgId == -1) LoadDefaultBg(); else LoadMoveBg(bgId); BeginHardwarePaletteFade(0xE8, 0, 16, 0, 1); gTasks[taskId].tState++; return; } if (gPaletteFade.active) return; if (gTasks[taskId].tState == 3) { DestroyTask(taskId); sAnimBackgroundFadeState = 0; } } static void LoadMoveBg(u16 bgId) { if (IsContest()) { const void *tilemap = gBattleAnimBackgroundTable[bgId].tilemap; void *dmaSrc; void *dmaDest; LZDecompressWram(tilemap, gDecompressionBuffer); sub_80A4720(sub_80A6D94(), (void*)(gDecompressionBuffer), 0x100, 0); dmaSrc = gDecompressionBuffer; dmaDest = (void *)(VRAM + 0xD000); DmaCopy32(3, dmaSrc, dmaDest, 0x800); LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)(VRAM + 0x2000)); LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, sub_80A6D94() * 16, 32); } else { LZDecompressVram(gBattleAnimBackgroundTable[bgId].tilemap, (void *)(VRAM + 0xD000)); LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)(VRAM + 0x8000)); LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, 32, 32); } } static void LoadDefaultBg(void) { if (IsContest()) LoadContestBgAfterMoveAnim(); else DrawMainBattleBackground(); } static void ScriptCmd_restorebg(void) { u8 taskId; sBattleAnimScriptPtr++; taskId = CreateTask(Task_FadeToBg, 5); gTasks[taskId].tBackgroundId = -1; sAnimBackgroundFadeState = 1; } #undef tBackgroundId #undef tState static void ScriptCmd_waitbgfadeout(void) { if (sAnimBackgroundFadeState == 2) { sBattleAnimScriptPtr++; gAnimFramesToWait = 0; } else { gAnimFramesToWait = 1; } } static void ScriptCmd_waitbgfadein(void) { if (sAnimBackgroundFadeState == 0) { sBattleAnimScriptPtr++; gAnimFramesToWait = 0; } else { gAnimFramesToWait = 1; } } static void ScriptCmd_changebg(void) { sBattleAnimScriptPtr++; LoadMoveBg(sBattleAnimScriptPtr[0]); sBattleAnimScriptPtr++; } s8 BattleAnimAdjustPanning(s8 pan) { if (!IsContest() && gBattleSpritesDataPtr->healthBoxesData[gAnimBankAttacker].statusAnimActive) { if (GetBattlerSide(gAnimBankAttacker) != B_SIDE_PLAYER) pan = PAN_SIDE_OPPONENT; else pan = PAN_SIDE_PLAYER; } else if (IsContest()) { if (gAnimBankAttacker != gAnimBankTarget || gAnimBankAttacker != 2 || pan != PAN_SIDE_OPPONENT) pan *= -1; } else if (GetBattlerSide(gAnimBankAttacker) == B_SIDE_PLAYER) { if (GetBattlerSide(gAnimBankTarget) == B_SIDE_PLAYER) { if (pan == PAN_SIDE_OPPONENT) pan = PAN_SIDE_PLAYER; else if (pan != PAN_SIDE_PLAYER) pan *= -1; } } else if (GetBattlerSide(gAnimBankTarget) == B_SIDE_OPPONENT) { if (pan == PAN_SIDE_PLAYER) pan = PAN_SIDE_OPPONENT; } else { pan *= -1; } if (pan > PAN_SIDE_OPPONENT) pan = PAN_SIDE_OPPONENT; else if (pan < PAN_SIDE_PLAYER) pan = PAN_SIDE_PLAYER; return pan; } s8 BattleAnimAdjustPanning2(s8 pan) { if (!IsContest() && gBattleSpritesDataPtr->healthBoxesData[gAnimBankAttacker].statusAnimActive) { if (GetBattlerSide(gAnimBankAttacker) != B_SIDE_PLAYER) pan = PAN_SIDE_OPPONENT; else pan = PAN_SIDE_PLAYER; } else { if (GetBattlerSide(gAnimBankAttacker) != B_SIDE_PLAYER || IsContest()) pan = -pan; } return pan; } s16 sub_80A52EC(s16 a) { s16 var = a; if (var > 63) var = 63; else if (var < -64) var = -64; return var; } s16 CalculatePanIncrement(s16 sourcePan, s16 targetPan, s16 incrementPan) { s16 ret; if (sourcePan < targetPan) ret = ((incrementPan < 0) ? -incrementPan : incrementPan); else if (sourcePan > targetPan) ret = -((incrementPan < 0) ? -incrementPan : incrementPan); else ret = 0; return ret; } static void ScriptCmd_playsewithpan(void) { u16 songId; s8 pan; sBattleAnimScriptPtr++; songId = SCRIPT_READ_16(sBattleAnimScriptPtr); pan = sBattleAnimScriptPtr[2]; PlaySE12WithPanning(songId, BattleAnimAdjustPanning(pan)); sBattleAnimScriptPtr += 3; } static void ScriptCmd_setpan(void) { s8 pan; sBattleAnimScriptPtr++; pan = sBattleAnimScriptPtr[0]; SE12PanpotControl(BattleAnimAdjustPanning(pan)); sBattleAnimScriptPtr++; } #define tInitialPan data[0] #define tTargetPan data[1] #define tIncrementPan data[2] #define tFramesToWait data[3] #define tCurrentPan data[4] #define tFrameCounter data[8] static void ScriptCmd_panse_1B(void) { u16 songNum; s8 currentPanArg, incrementPan, incrementPanArg, currentPan, targetPan; u8 framesToWait; u8 taskId; sBattleAnimScriptPtr++; songNum = SCRIPT_READ_16(sBattleAnimScriptPtr); currentPanArg = sBattleAnimScriptPtr[2]; incrementPan = sBattleAnimScriptPtr[3]; incrementPanArg = sBattleAnimScriptPtr[4]; framesToWait = sBattleAnimScriptPtr[5]; currentPan = BattleAnimAdjustPanning(currentPanArg); targetPan = BattleAnimAdjustPanning(incrementPan); incrementPan = CalculatePanIncrement(currentPan, targetPan, incrementPanArg); taskId = CreateTask(Task_PanFromInitialToTarget, 1); gTasks[taskId].tInitialPan = currentPan; gTasks[taskId].tTargetPan = targetPan; gTasks[taskId].tIncrementPan = incrementPan; gTasks[taskId].tFramesToWait = framesToWait; gTasks[taskId].tCurrentPan = currentPan; PlaySE12WithPanning(songNum, currentPan); gAnimSoundTaskCount++; sBattleAnimScriptPtr += 6; } void Task_PanFromInitialToTarget(u8 taskId) { bool32 destroyTask = FALSE; if (gTasks[taskId].tFrameCounter++ >= gTasks[taskId].tFramesToWait) { s16 pan; s16 initialPanning, targetPanning, currentPan, incrementPan; gTasks[taskId].tFrameCounter = 0; initialPanning = gTasks[taskId].tInitialPan; targetPanning = gTasks[taskId].tTargetPan; currentPan = gTasks[taskId].tCurrentPan; incrementPan = gTasks[taskId].tIncrementPan; pan = currentPan + incrementPan; gTasks[taskId].tCurrentPan = pan; if (incrementPan == 0) // If we're not incrementing, just cancel the task immediately { destroyTask = TRUE; } else if (initialPanning < targetPanning) // Panning increasing { if (pan >= targetPanning) // Target reached destroyTask = TRUE; } else // Panning decreasing { if (pan <= targetPanning) // Target reached destroyTask = TRUE; } if (destroyTask) { pan = targetPanning; DestroyTask(taskId); gAnimSoundTaskCount--; } SE12PanpotControl(pan); } } static void ScriptCmd_panse_26(void) { u16 songId; s8 currentPan, targetPan, incrementPan; u8 framesToWait; u8 taskId; sBattleAnimScriptPtr++; songId = SCRIPT_READ_16(sBattleAnimScriptPtr); currentPan = sBattleAnimScriptPtr[2]; targetPan = sBattleAnimScriptPtr[3]; incrementPan = sBattleAnimScriptPtr[4]; framesToWait = sBattleAnimScriptPtr[5]; taskId = CreateTask(Task_PanFromInitialToTarget, 1); gTasks[taskId].tInitialPan = currentPan; gTasks[taskId].tTargetPan = targetPan; gTasks[taskId].tIncrementPan = incrementPan; gTasks[taskId].tFramesToWait = framesToWait; gTasks[taskId].tCurrentPan = currentPan; PlaySE12WithPanning(songId, currentPan); gAnimSoundTaskCount++; sBattleAnimScriptPtr += 6; } static void ScriptCmd_panse_27(void) { u16 songId; s8 targetPanArg, incrementPanArg, currentPanArg, currentPan, targetPan, incrementPan; u8 framesToWait; u8 taskId; sBattleAnimScriptPtr++; songId = SCRIPT_READ_16(sBattleAnimScriptPtr); currentPanArg = sBattleAnimScriptPtr[2]; targetPanArg = sBattleAnimScriptPtr[3]; incrementPanArg = sBattleAnimScriptPtr[4]; framesToWait = sBattleAnimScriptPtr[5]; currentPan = BattleAnimAdjustPanning2(currentPanArg); targetPan = BattleAnimAdjustPanning2(targetPanArg); incrementPan = BattleAnimAdjustPanning2(incrementPanArg); taskId = CreateTask(Task_PanFromInitialToTarget, 1); gTasks[taskId].tInitialPan = currentPan; gTasks[taskId].tTargetPan = targetPan; gTasks[taskId].tIncrementPan = incrementPan; gTasks[taskId].tFramesToWait = framesToWait; gTasks[taskId].tCurrentPan = currentPan; PlaySE12WithPanning(songId, currentPan); gAnimSoundTaskCount++; sBattleAnimScriptPtr += 6; } #undef tInitialPan #undef tTargetPan #undef tIncrementPan #undef tFramesToWait #undef tCurrentPan #undef tFrameCounter #define tSongId data[0] #define tPanning data[1] #define tFramesToWait data[2] #define tNumberOfPlays data[3] #define tFrameCounter data[8] static void ScriptCmd_loopsewithpan(void) { u16 songId; s8 panningArg, panning; u8 framesToWait, numberOfPlays; u8 taskId; sBattleAnimScriptPtr++; songId = SCRIPT_READ_16(sBattleAnimScriptPtr); panningArg = sBattleAnimScriptPtr[2]; framesToWait = sBattleAnimScriptPtr[3]; numberOfPlays = sBattleAnimScriptPtr[4]; panning = BattleAnimAdjustPanning(panningArg); taskId = CreateTask(Task_LoopAndPlaySE, 1); gTasks[taskId].tSongId = songId; gTasks[taskId].tPanning = panning; gTasks[taskId].tFramesToWait = framesToWait; gTasks[taskId].tNumberOfPlays = numberOfPlays; gTasks[taskId].tFrameCounter = framesToWait; gTasks[taskId].func(taskId); gAnimSoundTaskCount++; sBattleAnimScriptPtr += 5; } static void Task_LoopAndPlaySE(u8 taskId) { if (gTasks[taskId].tFrameCounter++ >= gTasks[taskId].tFramesToWait) { u16 songId; s8 panning; u8 numberOfPlays; gTasks[taskId].tFrameCounter = 0; songId = gTasks[taskId].tSongId; panning = gTasks[taskId].tPanning; numberOfPlays = --gTasks[taskId].tNumberOfPlays; PlaySE12WithPanning(songId, panning); if (numberOfPlays == 0) { DestroyTask(taskId); gAnimSoundTaskCount--; } } } #undef tSongId #undef tPanning #undef tFramesToWait #undef tNumberOfPlays #undef tFrameCounter #define tSongId data[0] #define tPanning data[1] #define tFramesToWait data[2] static void ScriptCmd_waitplaysewithpan(void) { u16 songId; s8 panningArg, panning; u8 framesToWait; u8 taskId; sBattleAnimScriptPtr++; songId = SCRIPT_READ_16(sBattleAnimScriptPtr); panningArg = sBattleAnimScriptPtr[2]; framesToWait = sBattleAnimScriptPtr[3]; panning = BattleAnimAdjustPanning(panningArg); taskId = CreateTask(Task_WaitAndPlaySE, 1); gTasks[taskId].tSongId = songId; gTasks[taskId].tPanning = panning; gTasks[taskId].tFramesToWait = framesToWait; gAnimSoundTaskCount++; sBattleAnimScriptPtr += 4; } static void Task_WaitAndPlaySE(u8 taskId) { if (gTasks[taskId].tFramesToWait-- <= 0) { PlaySE12WithPanning(gTasks[taskId].tSongId, gTasks[taskId].tPanning); DestroyTask(taskId); gAnimSoundTaskCount--; } } #undef tSongId #undef tPanning #undef tFramesToWait static void ScriptCmd_createsoundtask(void) { TaskFunc func; u8 numArgs, taskId; s32 i; sBattleAnimScriptPtr++; func = (TaskFunc)SCRIPT_READ_32(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 4; numArgs = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; for (i = 0; i < numArgs; i++) { gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 2; } taskId = CreateTask(func, 1); func(taskId); gAnimSoundTaskCount++; } static void ScriptCmd_waitsound(void) { if (gAnimSoundTaskCount != 0) { sSoundAnimFramesToWait = 0; gAnimFramesToWait = 1; } else if (IsSEPlaying()) { if (++sSoundAnimFramesToWait > 90) { m4aMPlayStop(&gMPlayInfo_SE1); m4aMPlayStop(&gMPlayInfo_SE2); sSoundAnimFramesToWait = 0; } else { gAnimFramesToWait = 1; } } else { sSoundAnimFramesToWait = 0; sBattleAnimScriptPtr++; gAnimFramesToWait = 0; } } static void ScriptCmd_jumpargeq(void) { u8 argId; s16 valueToCheck; sBattleAnimScriptPtr++; argId = sBattleAnimScriptPtr[0]; valueToCheck = SCRIPT_READ_16(sBattleAnimScriptPtr + 1); if (valueToCheck == gBattleAnimArgs[argId]) sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr + 3); else sBattleAnimScriptPtr += 7; } static void ScriptCmd_jumpifcontest(void) { sBattleAnimScriptPtr++; if (IsContest()) sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); else sBattleAnimScriptPtr += 4; } static void ScriptCmd_monbgprio_28(void) { u8 wantedBank; u8 bank; u8 bankIdentity; wantedBank = sBattleAnimScriptPtr[1]; sBattleAnimScriptPtr += 2; if (wantedBank != ANIM_ATTACKER) bank = gAnimBankTarget; else bank = gAnimBankAttacker; bankIdentity = GetBattlerPosition(bank); if (!IsContest() && (bankIdentity == B_POSITION_PLAYER_LEFT || bankIdentity == B_POSITION_OPPONENT_RIGHT)) { SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); } } static void ScriptCmd_monbgprio_29(void) { sBattleAnimScriptPtr++; if (!IsContest()) { SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); } } static void ScriptCmd_monbgprio_2A(void) { u8 wantedBank; u8 bankIdentity; u8 bank; wantedBank = sBattleAnimScriptPtr[1]; sBattleAnimScriptPtr += 2; if (GetBattlerSide(gAnimBankAttacker) != GetBattlerSide(gAnimBankTarget)) { if (wantedBank != ANIM_ATTACKER) bank = gAnimBankTarget; else bank = gAnimBankAttacker; bankIdentity = GetBattlerPosition(bank); if (!IsContest() && (bankIdentity == B_POSITION_PLAYER_LEFT || bankIdentity == B_POSITION_OPPONENT_RIGHT)) { SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); } } } static void ScriptCmd_invisible(void) { u8 spriteId; spriteId = GetAnimBankSpriteId(sBattleAnimScriptPtr[1]); if (spriteId != 0xFF) gSprites[spriteId].invisible = 1; sBattleAnimScriptPtr += 2; } static void ScriptCmd_visible(void) { u8 spriteId; spriteId = GetAnimBankSpriteId(sBattleAnimScriptPtr[1]); if (spriteId != 0xFF) gSprites[spriteId].invisible = 0; sBattleAnimScriptPtr += 2; } static void ScriptCmd_doublebattle_2D(void) { u8 wantedBank; u8 r4; u8 spriteId; wantedBank = sBattleAnimScriptPtr[1]; sBattleAnimScriptPtr += 2; if (!IsContest() && IsDoubleBattle() && GetBattlerSide(gAnimBankAttacker) == GetBattlerSide(gAnimBankTarget)) { if (wantedBank == ANIM_ATTACKER) { r4 = sub_80A8364(gAnimBankAttacker); spriteId = GetAnimBankSpriteId(ANIM_ATTACKER); } else { r4 = sub_80A8364(gAnimBankTarget); spriteId = GetAnimBankSpriteId(ANIM_TARGET); } if (spriteId != 0xFF) { gSprites[spriteId].invisible = FALSE; if (r4 == 2) gSprites[spriteId].oam.priority = 3; if (r4 == 1) sub_80A477C(FALSE); else sub_80A477C(TRUE); } } } static void ScriptCmd_doublebattle_2E(void) { u8 wantedBank; u8 r4; u8 spriteId; wantedBank = sBattleAnimScriptPtr[1]; sBattleAnimScriptPtr += 2; if (!IsContest() && IsDoubleBattle() && GetBattlerSide(gAnimBankAttacker) == GetBattlerSide(gAnimBankTarget)) { if (wantedBank == ANIM_ATTACKER) { r4 = sub_80A8364(gAnimBankAttacker); spriteId = GetAnimBankSpriteId(ANIM_ATTACKER); } else { r4 = sub_80A8364(gAnimBankTarget); spriteId = GetAnimBankSpriteId(ANIM_TARGET); } if (spriteId != 0xFF && r4 == 2) gSprites[spriteId].oam.priority = 2; } } static void ScriptCmd_stopsound(void) { m4aMPlayStop(&gMPlayInfo_SE1); m4aMPlayStop(&gMPlayInfo_SE2); sBattleAnimScriptPtr++; }