#include "global.h" #include "malloc.h" #include "battle_anim.h" #include "battle_interface.h" #include "decompress.h" #include "gpu_regs.h" #include "graphics.h" #include "main.h" #include "math_util.h" #include "palette.h" #include "random.h" #include "scanline_effect.h" #include "sound.h" #include "trig.h" #include "util.h" #include "constants/rgb.h" #include "constants/songs.h" static void AnimCirclingFinger(struct Sprite *); static void AnimBouncingMusicNote(struct Sprite *); static void AnimBouncingMusicNote_Step(struct Sprite *); static void AnimVibrateBattlerBack(struct Sprite *); static void AnimMovingClamp(struct Sprite *); static void AnimMovingClamp_Step(struct Sprite *); static void AnimMovingClamp_End(struct Sprite *); static void AnimKinesisZapEnergy(struct Sprite *); static void AnimSwordsDanceBlade(struct Sprite *); static void AnimSwordsDanceBlade_Step(struct Sprite *); static void AnimSonicBoomProjectile(struct Sprite *); static void AnimAirWaveProjectile(struct Sprite *); static void AnimAirWaveProjectile_Step1(struct Sprite *sprite); static void AnimAirWaveProjectile_Step2(struct Sprite *sprite); static void AnimVoidLines(struct Sprite *); static void AnimVoidLines_Step(struct Sprite *); static void AnimCoinThrow(struct Sprite *); static void AnimFallingCoin(struct Sprite *); static void AnimFallingCoin_Step(struct Sprite *); static void AnimBulletSeed(struct Sprite *); static void AnimBulletSeed_Step1(struct Sprite *); static void AnimBulletSeed_Step2(struct Sprite *); static void AnimRazorWindTornado(struct Sprite *); static void AnimViceGripPincer(struct Sprite *); static void AnimViceGripPincer_Step(struct Sprite *); static void AnimGuillotinePincer(struct Sprite *); static void AnimGuillotinePincer_Step1(struct Sprite *); static void AnimGuillotinePincer_Step2(struct Sprite *); static void AnimGuillotinePincer_Step3(struct Sprite *); static void AnimBreathPuff(struct Sprite *); static void AnimAngerMark(struct Sprite *); static void AnimPencil(struct Sprite *); static void AnimPencil_Step(struct Sprite *); static void AnimBlendThinRing(struct Sprite *); static void AnimHyperVoiceRing(struct Sprite *); static void AnimUproarRing(struct Sprite *); static void AnimSoftBoiledEgg(struct Sprite *); static void AnimSoftBoiledEgg_Step1(struct Sprite *); static void AnimSoftBoiledEgg_Step2(struct Sprite *); static void AnimSoftBoiledEgg_Step3(struct Sprite *); static void AnimSoftBoiledEgg_Step3_Callback1(struct Sprite *); static void AnimSoftBoiledEgg_Step3_Callback2(struct Sprite *); static void AnimSoftBoiledEgg_Step4(struct Sprite *); static void AnimSoftBoiledEgg_Step4_Callback(struct Sprite *); static void AnimSpeedDust(struct Sprite *); static void AnimHealBellMusicNote(struct Sprite *); static void AnimMagentaHeart(struct Sprite *); static void AnimRedHeartProjectile(struct Sprite *); static void AnimRedHeartProjectile_Step(struct Sprite *); static void AnimRedHeartRising(struct Sprite *); static void AnimRedHeartRising_Step(struct Sprite *); static void AnimOrbitFast(struct Sprite *); static void AnimOrbitFast_Step(struct Sprite *); static void AnimOrbitScatter(struct Sprite *); static void AnimOrbitScatter_Step(struct Sprite *); static void AnimSpitUpOrb(struct Sprite *); static void AnimSpitUpOrb_Step(struct Sprite *sprite); static void AnimEyeSparkle(struct Sprite *); static void AnimEyeSparkle_Step(struct Sprite *sprite); static void AnimAngel(struct Sprite *); static void AnimPinkHeart(struct Sprite *); static void AnimDevil(struct Sprite *); static void AnimFurySwipes(struct Sprite *); static void AnimMovementWaves(struct Sprite *); static void AnimMovementWaves_Step(struct Sprite *); static void AnimJaggedMusicNote(struct Sprite *); static void AnimJaggedMusicNote_Step(struct Sprite *); static void AnimPerishSongMusicNote2(struct Sprite *); static void AnimPerishSongMusicNote(struct Sprite *); static void AnimPerishSongMusicNote_Step1(struct Sprite *); static void AnimPerishSongMusicNote_Step2(struct Sprite *); static void AnimGuardRing(struct Sprite *); static void AnimTask_Withdraw_Step(u8); static void AnimTask_GrowAndGrayscale_Step(u8); static void AnimTask_Minimize_Step(u8); static void CreateMinimizeSprite(struct Task *, u8); static void ClonedMinizeSprite_Step(struct Sprite *); static void AnimTask_Splash_Step(u8); static void AnimTask_GrowAndShrink_Step(u8); static void AnimTask_ThrashMoveMonHorizontal_Step(u8); static void AnimTask_ThrashMoveMonVertical_Step(u8); static void AnimTask_SketchDrawMon_Step(u8); static void AnimTask_AttackerStretchAndDisappear_Step(u8); static void AnimTask_ExtremeSpeedImpact_Step(u8); static void AnimTask_ExtremeSpeedMonReappear_Step(u8); static void AnimTask_SpeedDust_Step(u8); static void AnimTask_FakeOut_Step1(u8); static void AnimTask_FakeOut_Step2(u8); static void AnimTask_HeartsBackground_Step(u8); static void AnimTask_ScaryFace_Step(u8); static void AnimTask_UproarDistortion_Step(u8); // Unused static const struct SpriteTemplate sCirclingFingerSpriteTemplate = { .tileTag = ANIM_TAG_FINGER, .paletteTag = ANIM_TAG_FINGER, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimCirclingFinger, }; static const union AnimCmd sAnim_BouncingMusicNote[] = { ANIMCMD_FRAME(4, 1), ANIMCMD_END, }; // Unused (association assumed) static const union AnimCmd *const sAnims_BouncingMusicNote[] = { sAnim_BouncingMusicNote, }; // Unused static const struct SpriteTemplate sBouncingMusicNoteSpriteTemplate = { .tileTag = ANIM_TAG_MUSIC_NOTES, .paletteTag = ANIM_TAG_MUSIC_NOTES, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimBouncingMusicNote, }; // Unused static const struct SpriteTemplate sVibrateBattlerBackSpriteTemplate = { .tileTag = 0, .paletteTag = 0, .oam = &gDummyOamData, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimVibrateBattlerBack, }; // Unused static const struct SpriteTemplate sMovingClampSpriteTemplate = { .tileTag = ANIM_TAG_CLAMP, .paletteTag = ANIM_TAG_CLAMP, .oam = &gOamData_AffineNormal_ObjBlend_64x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gAffineAnims_Bite, .callback = AnimMovingClamp, }; static const union AnimCmd sAnim_SmallExplosion[] = { ANIMCMD_FRAME(0, 9), ANIMCMD_FRAME(16, 3), ANIMCMD_FRAME(32, 3), ANIMCMD_FRAME(48, 3), ANIMCMD_END, }; static const union AnimCmd *const sAnims_SmallExplosion[] = { sAnim_SmallExplosion, }; static const union AffineAnimCmd sAffineAnim_SmallExplosion[] = { AFFINEANIMCMD_FRAME(0x50, 0x50, 0, 0), AFFINEANIMCMD_FRAME(0x9, 0x9, 0, 18), AFFINEANIMCMD_END, }; static const union AffineAnimCmd *const sAffineAnims_SmallExplosion[] = { sAffineAnim_SmallExplosion, }; // Unused static const struct SpriteTemplate sSmallExplosionSpriteTemplate = { .tileTag = ANIM_TAG_EXPLOSION_6, .paletteTag = ANIM_TAG_EXPLOSION_6, .oam = &gOamData_AffineNormal_ObjNormal_32x32, .anims = sAnims_SmallExplosion, .images = NULL, .affineAnims = sAffineAnims_SmallExplosion, .callback = AnimSpriteOnMonPos, }; const union AnimCmd gKinesisZapEnergyAnimCmds[] = { ANIMCMD_FRAME(0, 3, .hFlip = TRUE), ANIMCMD_FRAME(8, 3, .hFlip = TRUE), ANIMCMD_FRAME(16, 3, .hFlip = TRUE), ANIMCMD_FRAME(24, 3, .hFlip = TRUE), ANIMCMD_FRAME(32, 3, .hFlip = TRUE), ANIMCMD_FRAME(40, 3, .hFlip = TRUE), ANIMCMD_FRAME(48, 3, .hFlip = TRUE), ANIMCMD_LOOP(1), ANIMCMD_END, }; const union AnimCmd *const gKinesisZapEnergyAnimTable[] = { gKinesisZapEnergyAnimCmds, }; const struct SpriteTemplate gKinesisZapEnergySpriteTemplate = { .tileTag = ANIM_TAG_ALERT, .paletteTag = ANIM_TAG_ALERT, .oam = &gOamData_AffineOff_ObjNormal_32x16, .anims = gKinesisZapEnergyAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimKinesisZapEnergy, }; const union AffineAnimCmd gSwordsDanceBladeAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), AFFINEANIMCMD_FRAME(0x14, 0x0, 0, 12), AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 32), AFFINEANIMCMD_END, }; const union AffineAnimCmd *const gSwordsDanceBladeAffineAnimTable[] = { gSwordsDanceBladeAffineAnimCmds, }; const struct SpriteTemplate gSwordsDanceBladeSpriteTemplate = { .tileTag = ANIM_TAG_SWORD, .paletteTag = ANIM_TAG_SWORD, .oam = &gOamData_AffineNormal_ObjBlend_32x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gSwordsDanceBladeAffineAnimTable, .callback = AnimSwordsDanceBlade, }; const struct SpriteTemplate gSonicBoomSpriteTemplate = { .tileTag = ANIM_TAG_AIR_WAVE, .paletteTag = ANIM_TAG_AIR_WAVE, .oam = &gOamData_AffineDouble_ObjBlend_32x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimSonicBoomProjectile, }; const struct SpriteTemplate gAirWaveProjectileSpriteTemplate = { .tileTag = ANIM_TAG_AIR_WAVE, .paletteTag = ANIM_TAG_AIR_WAVE, .oam = &gOamData_AffineOff_ObjBlend_32x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimAirWaveProjectile, }; const union AffineAnimCmd gGrowingRingAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), AFFINEANIMCMD_FRAME(0x7, 0x7, 0, -56), AFFINEANIMCMD_END, }; const union AffineAnimCmd gWaterPulseRingAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 10), AFFINEANIMCMD_FRAME(0xFFF6, 0xFFF6, 0, 10), AFFINEANIMCMD_FRAME(0xA, 0xA, 0, 10), AFFINEANIMCMD_FRAME(0xFFF6, 0xFFF6, 0, 10), AFFINEANIMCMD_FRAME(0xA, 0xA, 0, 10), AFFINEANIMCMD_FRAME(0xFFF6, 0xFFF6, 0, 10), AFFINEANIMCMD_FRAME(0xA, 0xA, 0, 10), AFFINEANIMCMD_END, }; const union AffineAnimCmd *const gGrowingRingAffineAnimTable[] = { gGrowingRingAffineAnimCmds, }; const union AffineAnimCmd *const gWaterPulseRingAffineAnimTable[] = { gWaterPulseRingAffineAnimCmds, }; const struct SpriteTemplate gSupersonicRingSpriteTemplate = { .tileTag = ANIM_TAG_GOLD_RING, .paletteTag = ANIM_TAG_GOLD_RING, .oam = &gOamData_AffineDouble_ObjNormal_16x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gGrowingRingAffineAnimTable, .callback = TranslateAnimSpriteToTargetMonLocation, }; const struct SpriteTemplate gScreechRingSpriteTemplate = { .tileTag = ANIM_TAG_PURPLE_RING, .paletteTag = ANIM_TAG_PURPLE_RING, .oam = &gOamData_AffineDouble_ObjNormal_16x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gGrowingRingAffineAnimTable, .callback = TranslateAnimSpriteToTargetMonLocation, }; const struct SpriteTemplate gMetalSoundSpriteTemplate = { .tileTag = ANIM_TAG_METAL_SOUND_WAVES, .paletteTag = ANIM_TAG_METAL_SOUND_WAVES, .oam = &gOamData_AffineDouble_ObjNormal_32x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gGrowingRingAffineAnimTable, .callback = TranslateAnimSpriteToTargetMonLocation, }; const struct SpriteTemplate gWaterPulseRingSpriteTemplate = { .tileTag = ANIM_TAG_BLUE_RING_2, .paletteTag = ANIM_TAG_BLUE_RING_2, .oam = &gOamData_AffineDouble_ObjNormal_16x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gWaterPulseRingAffineAnimTable, .callback = AnimWaterPulseRing, }; const struct SpriteTemplate gEggThrowSpriteTemplate = { .tileTag = ANIM_TAG_LARGE_FRESH_EGG, .paletteTag = ANIM_TAG_LARGE_FRESH_EGG, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimThrowProjectile, }; // Unused static const struct SpriteTemplate sVoidLinesSpriteTemplate = { .tileTag = ANIM_TAG_VOID_LINES, .paletteTag = ANIM_TAG_VOID_LINES, .oam = &gOamData_AffineOff_ObjBlend_64x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimVoidLines, }; const union AnimCmd gCoinAnimCmds[] = { ANIMCMD_FRAME(8, 1), ANIMCMD_END, }; const union AnimCmd *const gCoinAnimTable[] = { gCoinAnimCmds, }; const union AffineAnimCmd gFallingCoinAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x0, 0x0, 10, 1), AFFINEANIMCMD_JUMP(0), }; const union AffineAnimCmd *const gFallingCoinAffineAnimTable[] = { gFallingCoinAffineAnimCmds, }; const struct SpriteTemplate gCoinThrowSpriteTemplate = { .tileTag = ANIM_TAG_COIN, .paletteTag = ANIM_TAG_COIN, .oam = &gOamData_AffineNormal_ObjNormal_16x16, .anims = gCoinAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimCoinThrow, }; const struct SpriteTemplate gFallingCoinSpriteTemplate = { .tileTag = ANIM_TAG_COIN, .paletteTag = ANIM_TAG_COIN, .oam = &gOamData_AffineNormal_ObjNormal_16x16, .anims = gCoinAnimTable, .images = NULL, .affineAnims = gFallingCoinAffineAnimTable, .callback = AnimFallingCoin, }; const union AffineAnimCmd gBulletSeedAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x0, 0x0, 20, 1), AFFINEANIMCMD_JUMP(0), }; const union AffineAnimCmd *const gBulletSeedAffineAnimTable[] = { gBulletSeedAffineAnimCmds, }; const struct SpriteTemplate gBulletSeedSpriteTemplate = { .tileTag = ANIM_TAG_SEED, .paletteTag = ANIM_TAG_SEED, .oam = &gOamData_AffineNormal_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gBulletSeedAffineAnimTable, .callback = AnimBulletSeed, }; const union AffineAnimCmd gRazorWindTornadoAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), AFFINEANIMCMD_FRAME(0x4, 0x0, 0, 40), AFFINEANIMCMD_END, }; const union AffineAnimCmd *const gRazorWindTornadoAffineAnimTable[] = { gRazorWindTornadoAffineAnimCmds, }; const struct SpriteTemplate gRazorWindTornadoSpriteTemplate = { .tileTag = ANIM_TAG_GUST, .paletteTag = ANIM_TAG_GUST, .oam = &gOamData_AffineNormal_ObjNormal_32x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gRazorWindTornadoAffineAnimTable, .callback = AnimRazorWindTornado, }; const union AnimCmd gViceGripAnimCmds1[] = { ANIMCMD_FRAME(0, 3), ANIMCMD_FRAME(16, 3), ANIMCMD_FRAME(32, 20), ANIMCMD_END, }; const union AnimCmd gViceGripAnimCmds2[] = { ANIMCMD_FRAME(0, 3, .vFlip = TRUE, .hFlip = TRUE), ANIMCMD_FRAME(16, 3, .vFlip = TRUE, .hFlip = TRUE), ANIMCMD_FRAME(32, 20, .vFlip = TRUE, .hFlip = TRUE), ANIMCMD_END, }; const union AnimCmd *const gViceGripAnimTable[] = { gViceGripAnimCmds1, gViceGripAnimCmds2, }; const struct SpriteTemplate gViceGripSpriteTemplate = { .tileTag = ANIM_TAG_CUT, .paletteTag = ANIM_TAG_CUT, .oam = &gOamData_AffineOff_ObjBlend_32x32, .anims = gViceGripAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimViceGripPincer, }; const union AnimCmd gGuillotineAnimCmds1[] = { ANIMCMD_FRAME(0, 2), ANIMCMD_FRAME(16, 2), ANIMCMD_FRAME(32, 1), ANIMCMD_END, }; const union AnimCmd gGuillotineAnimCmds2[] = { ANIMCMD_FRAME(0, 2, .vFlip = TRUE, .hFlip = TRUE), ANIMCMD_FRAME(16, 2, .vFlip = TRUE, .hFlip = TRUE), ANIMCMD_FRAME(32, 1, .vFlip = TRUE, .hFlip = TRUE), ANIMCMD_END, }; const union AnimCmd *const gGuillotineAnimTable[] = { gGuillotineAnimCmds1, gGuillotineAnimCmds2, }; const struct SpriteTemplate gGuillotineSpriteTemplate = { .tileTag = ANIM_TAG_CUT, .paletteTag = ANIM_TAG_CUT, .oam = &gOamData_AffineOff_ObjBlend_32x32, .anims = gGuillotineAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimGuillotinePincer, }; const union AffineAnimCmd gSplashEffectAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(-6, 4, 0, 8), AFFINEANIMCMD_FRAME(10, -10, 0, 8), AFFINEANIMCMD_FRAME(-4, 6, 0, 8), AFFINEANIMCMD_END, }; const union AffineAnimCmd gGrowAndShrinkAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(-4, -5, 0, 12), AFFINEANIMCMD_FRAME(0, 0, 0, 24), AFFINEANIMCMD_FRAME(4, 5, 0, 12), AFFINEANIMCMD_END, }; const union AnimCmd gBreathPuffAnimCmds1[] = { ANIMCMD_FRAME(0, 4, .hFlip = TRUE), ANIMCMD_FRAME(4, 40, .hFlip = TRUE), ANIMCMD_FRAME(8, 4, .hFlip = TRUE), ANIMCMD_FRAME(12, 4, .hFlip = TRUE), ANIMCMD_END, }; const union AnimCmd gBreathPuffAnimCmds2[] = { ANIMCMD_FRAME(0, 4), ANIMCMD_FRAME(4, 40), ANIMCMD_FRAME(8, 4), ANIMCMD_FRAME(12, 4), ANIMCMD_END, }; const union AnimCmd *const gBreathPuffAnimTable[] = { gBreathPuffAnimCmds1, gBreathPuffAnimCmds2, }; const struct SpriteTemplate gBreathPuffSpriteTemplate = { .tileTag = ANIM_TAG_BREATH, .paletteTag = ANIM_TAG_BREATH, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gBreathPuffAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimBreathPuff, }; const union AffineAnimCmd gAngerMarkAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0xB, 0xB, 0, 8), AFFINEANIMCMD_FRAME(0xFFF5, 0xFFF5, 0, 8), AFFINEANIMCMD_END, }; const union AffineAnimCmd *const gAngerMarkAffineAnimTable[] = { gAngerMarkAffineAnimCmds, }; const struct SpriteTemplate gAngerMarkSpriteTemplate = { .tileTag = ANIM_TAG_ANGER, .paletteTag = ANIM_TAG_ANGER, .oam = &gOamData_AffineNormal_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gAngerMarkAffineAnimTable, .callback = AnimAngerMark, }; const union AffineAnimCmd gThrashMoveMonAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(-10, 9, 0, 7), AFFINEANIMCMD_FRAME(20, -20, 0, 7), AFFINEANIMCMD_FRAME(-20, 20, 0, 7), AFFINEANIMCMD_FRAME(10, -9, 0, 7), AFFINEANIMCMD_LOOP(2), AFFINEANIMCMD_END, }; const struct SpriteTemplate gPencilSpriteTemplate = { .tileTag = ANIM_TAG_PENCIL, .paletteTag = ANIM_TAG_PENCIL, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimPencil, }; const struct SpriteTemplate gSnoreZSpriteTemplate = { .tileTag = ANIM_TAG_SNORE_Z, .paletteTag = ANIM_TAG_SNORE_Z, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimTravelDiagonally, }; const union AnimCmd gExplosionAnimCmds[] = { ANIMCMD_FRAME(0, 5), ANIMCMD_FRAME(16, 5), ANIMCMD_FRAME(32, 5), ANIMCMD_FRAME(48, 5), ANIMCMD_END, }; const union AnimCmd *const gExplosionAnimTable[] = { gExplosionAnimCmds, }; const struct SpriteTemplate gExplosionSpriteTemplate = { .tileTag = ANIM_TAG_EXPLOSION, .paletteTag = ANIM_TAG_EXPLOSION, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gExplosionAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimSpriteOnMonPos, }; const union AffineAnimCmd gSoftBoiledEggAffineAnimCmds1[] = { AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 2), AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 4), AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 2), AFFINEANIMCMD_JUMP(0), }; const union AffineAnimCmd gSoftBoiledEggAffineAnimCmds2[] = { AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), AFFINEANIMCMD_END, }; const union AffineAnimCmd gSoftBoiledEggAffineAnimCmds3[] = { AFFINEANIMCMD_FRAME(0xFFF8, 0x4, 0, 8), AFFINEANIMCMD_LOOP(0), AFFINEANIMCMD_FRAME(0x10, 0xFFF8, 0, 8), AFFINEANIMCMD_FRAME(0xFFF0, 0x8, 0, 8), AFFINEANIMCMD_LOOP(1), AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 15), AFFINEANIMCMD_END, }; const union AffineAnimCmd *const gSoftBoiledEggAffineAnimTable[] = { gSoftBoiledEggAffineAnimCmds1, gSoftBoiledEggAffineAnimCmds2, gSoftBoiledEggAffineAnimCmds3, }; const struct SpriteTemplate gSoftBoiledEggSpriteTemplate = { .tileTag = ANIM_TAG_BREAKING_EGG, .paletteTag = ANIM_TAG_BREAKING_EGG, .oam = &gOamData_AffineDouble_ObjBlend_32x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gSoftBoiledEggAffineAnimTable, .callback = AnimSoftBoiledEgg, }; const union AffineAnimCmd gThinRingExpandingAffineAnimCmds1[] = { AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 30), AFFINEANIMCMD_END_ALT(1), }; const union AffineAnimCmd gThinRingExpandingAffineAnimCmds2[] = { AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 15), AFFINEANIMCMD_END_ALT(1), }; const union AffineAnimCmd gHyperVoiceRingAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), AFFINEANIMCMD_FRAME(0xB, 0xB, 0, 45), AFFINEANIMCMD_END_ALT(1), }; const union AffineAnimCmd *const gThinRingExpandingAffineAnimTable[] = { gThinRingExpandingAffineAnimCmds1, gThinRingExpandingAffineAnimCmds2, }; const union AffineAnimCmd *const gHyperVoiceRingAffineAnimTable[] = { gHyperVoiceRingAffineAnimCmds, }; const struct SpriteTemplate gThinRingExpandingSpriteTemplate = { .tileTag = ANIM_TAG_THIN_RING, .paletteTag = ANIM_TAG_THIN_RING, .oam = &gOamData_AffineDouble_ObjNormal_64x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gThinRingExpandingAffineAnimTable, .callback = AnimSpriteOnMonPos, }; const union AffineAnimCmd gThinRingShrinkingAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0), AFFINEANIMCMD_FRAME(0xFFF0, 0xFFF0, 0, 30), AFFINEANIMCMD_END_ALT(1), }; const union AffineAnimCmd *const gThinRingShrinkingAffineAnimTable[] = { gThinRingShrinkingAffineAnimCmds, }; const struct SpriteTemplate gThinRingShrinkingSpriteTemplate = { .tileTag = ANIM_TAG_THIN_RING, .paletteTag = ANIM_TAG_THIN_RING, .oam = &gOamData_AffineDouble_ObjBlend_64x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gThinRingShrinkingAffineAnimTable, .callback = AnimSpriteOnMonPos, }; const struct SpriteTemplate gBlendThinRingExpandingSpriteTemplate = { .tileTag = ANIM_TAG_THIN_RING, .paletteTag = ANIM_TAG_THIN_RING, .oam = &gOamData_AffineDouble_ObjBlend_64x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gThinRingExpandingAffineAnimTable, .callback = AnimBlendThinRing, }; const struct SpriteTemplate gHyperVoiceRingSpriteTemplate = { .tileTag = ANIM_TAG_THIN_RING, .paletteTag = ANIM_TAG_THIN_RING, .oam = &gOamData_AffineDouble_ObjBlend_64x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gHyperVoiceRingAffineAnimTable, .callback = AnimHyperVoiceRing, }; const struct SpriteTemplate gUproarRingSpriteTemplate = { .tileTag = ANIM_TAG_THIN_RING, .paletteTag = ANIM_TAG_THIN_RING, .oam = &gOamData_AffineDouble_ObjBlend_64x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gThinRingExpandingAffineAnimTable, .callback = AnimUproarRing, }; const union AffineAnimCmd gStretchAttackerAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(96, -13, 0, 8), AFFINEANIMCMD_END, }; const union AnimCmd gSpeedDustAnimCmds[] = { ANIMCMD_FRAME(0, 3), ANIMCMD_FRAME(4, 3), ANIMCMD_FRAME(8, 3), ANIMCMD_FRAME(4, 3), ANIMCMD_FRAME(0, 3), ANIMCMD_END, }; const union AnimCmd *const gSpeedDustAnimTable[] = { gSpeedDustAnimCmds, }; const struct SpriteTemplate gSpeedDustSpriteTemplate = { .tileTag = ANIM_TAG_SPEED_DUST, .paletteTag = ANIM_TAG_SPEED_DUST, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gSpeedDustAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimSpeedDust, }; const s8 gSpeedDustPosTable[][2] = { {30, 28}, {-20, 24}, {16, 26}, {-10, 28}, }; const union AnimCmd gBellAnimCmds[] = { ANIMCMD_FRAME(0, 6), ANIMCMD_FRAME(16, 6), ANIMCMD_FRAME(32, 15), ANIMCMD_FRAME(16, 6), ANIMCMD_FRAME(0, 6), ANIMCMD_FRAME(16, 6, .hFlip = TRUE), ANIMCMD_FRAME(32, 15, .hFlip = TRUE), ANIMCMD_FRAME(16, 6, .hFlip = TRUE), ANIMCMD_FRAME(0, 6), ANIMCMD_FRAME(16, 6), ANIMCMD_FRAME(32, 15), ANIMCMD_FRAME(16, 6), ANIMCMD_FRAME(0, 6), ANIMCMD_END, }; const union AnimCmd *const gBellAnimTable[] = { gBellAnimCmds, }; const struct SpriteTemplate gBellSpriteTemplate = { .tileTag = ANIM_TAG_BELL, .paletteTag = ANIM_TAG_BELL, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gBellAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimSpriteOnMonPos, }; #define NUM_MUSIC_NOTE_PAL_TAGS 3 static const u16 sMusicNotePaletteTagsTable[NUM_MUSIC_NOTE_PAL_TAGS] = { ANIM_TAG_MUSIC_NOTES_2, ANIM_SPRITES_START - 1, ANIM_SPRITES_START - 2, }; const struct SpriteTemplate gHealBellMusicNoteSpriteTemplate = { .tileTag = ANIM_TAG_MUSIC_NOTES_2, .paletteTag = ANIM_TAG_MUSIC_NOTES_2, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimHealBellMusicNote, }; const struct SpriteTemplate gMagentaHeartSpriteTemplate = { .tileTag = ANIM_TAG_MAGENTA_HEART, .paletteTag = ANIM_TAG_MAGENTA_HEART, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimMagentaHeart, }; static const union AffineAnimCmd sAffineAnims_StretchBattlerUp[] = { AFFINEANIMCMD_FRAME(0x000A, 0xFFF3, 0x00, 0x0A), AFFINEANIMCMD_FRAME(0xFFF6, 0x000D, 0x00, 0x0A), AFFINEANIMCMD_END, }; const struct SpriteTemplate gRedHeartProjectileSpriteTemplate = { .tileTag = ANIM_TAG_RED_HEART, .paletteTag = ANIM_TAG_RED_HEART, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimRedHeartProjectile, }; const struct SpriteTemplate gRedHeartBurstSpriteTemplate = { .tileTag = ANIM_TAG_RED_HEART, .paletteTag = ANIM_TAG_RED_HEART, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimParticleBurst, }; const struct SpriteTemplate gRedHeartRisingSpriteTemplate = { .tileTag = ANIM_TAG_RED_HEART, .paletteTag = ANIM_TAG_RED_HEART, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimRedHeartRising, }; const union AffineAnimCmd gHiddenPowerOrbAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x80, 0x80, 0, 0), AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 1), AFFINEANIMCMD_JUMP(1), }; const union AffineAnimCmd *const gHiddenPowerOrbAffineAnimTable[] = { gHiddenPowerOrbAffineAnimCmds, }; const struct SpriteTemplate gHiddenPowerOrbSpriteTemplate = { .tileTag = ANIM_TAG_RED_ORB, .paletteTag = ANIM_TAG_RED_ORB, .oam = &gOamData_AffineNormal_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gHiddenPowerOrbAffineAnimTable, .callback = AnimOrbitFast, }; const struct SpriteTemplate gHiddenPowerOrbScatterSpriteTemplate = { .tileTag = ANIM_TAG_RED_ORB, .paletteTag = ANIM_TAG_RED_ORB, .oam = &gOamData_AffineDouble_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gHiddenPowerOrbAffineAnimTable, .callback = AnimOrbitScatter, }; const union AffineAnimCmd gSpitUpOrbAffineAnimCmds[] = { AFFINEANIMCMD_FRAME(0x80, 0x80, 0, 0), AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 1), AFFINEANIMCMD_JUMP(1), }; const union AffineAnimCmd *const gSpitUpOrbAffineAnimTable[] = { gSpitUpOrbAffineAnimCmds, }; const struct SpriteTemplate gSpitUpOrbSpriteTemplate = { .tileTag = ANIM_TAG_RED_ORB_2, .paletteTag = ANIM_TAG_RED_ORB_2, .oam = &gOamData_AffineDouble_ObjNormal_8x8, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gSpitUpOrbAffineAnimTable, .callback = AnimSpitUpOrb, }; const union AnimCmd gEyeSparkleAnimCmds[] = { ANIMCMD_FRAME(0, 4), ANIMCMD_FRAME(4, 4), ANIMCMD_FRAME(8, 4), ANIMCMD_FRAME(4, 4), ANIMCMD_FRAME(0, 4), ANIMCMD_END, }; const union AnimCmd *const gEyeSparkleAnimTable[] = { gEyeSparkleAnimCmds, }; const struct SpriteTemplate gEyeSparkleSpriteTemplate = { .tileTag = ANIM_TAG_EYE_SPARKLE, .paletteTag = ANIM_TAG_EYE_SPARKLE, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gEyeSparkleAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimEyeSparkle, }; const union AnimCmd gAngelSpriteAnimCmds[] = { ANIMCMD_FRAME(0, 24), ANIMCMD_END, }; const union AnimCmd *const gAngelSpriteAnimTable[] = { gAngelSpriteAnimCmds, }; const struct SpriteTemplate gAngelSpriteTemplate = { .tileTag = ANIM_TAG_ANGEL, .paletteTag = ANIM_TAG_ANGEL, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gAngelSpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimAngel, }; const struct SpriteTemplate gPinkHeartSpriteTemplate = { .tileTag = ANIM_TAG_PINK_HEART, .paletteTag = ANIM_TAG_PINK_HEART, .oam = &gOamData_AffineOff_ObjNormal_16x16, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimPinkHeart, }; const union AnimCmd gDevilAnimCmds1[] = { ANIMCMD_FRAME(0, 3), ANIMCMD_JUMP(0), }; const union AnimCmd gDevilAnimCmds2[] = { ANIMCMD_FRAME(16, 3), ANIMCMD_JUMP(0), }; const union AnimCmd *const gDevilAnimTable[] = { gDevilAnimCmds1, gDevilAnimCmds2, }; const struct SpriteTemplate gDevilSpriteTemplate = { .tileTag = ANIM_TAG_DEVIL, .paletteTag = ANIM_TAG_DEVIL, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gDevilAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimDevil, }; static const union AnimCmd sAnim_FurySwipes[] = { ANIMCMD_FRAME(0, 4), ANIMCMD_FRAME(16, 4), ANIMCMD_FRAME(32, 4), ANIMCMD_FRAME(48, 4), ANIMCMD_END, }; static const union AnimCmd sAnim_FurySwipes_Flipped[] = { ANIMCMD_FRAME(0, 4, .hFlip = TRUE), ANIMCMD_FRAME(16, 4, .hFlip = TRUE), ANIMCMD_FRAME(32, 4, .hFlip = TRUE), ANIMCMD_FRAME(48, 4, .hFlip = TRUE), ANIMCMD_END, }; static const union AnimCmd *const sAnims_FurySwipes[] = { sAnim_FurySwipes, sAnim_FurySwipes_Flipped, }; const struct SpriteTemplate gFurySwipesSpriteTemplate = { .tileTag = ANIM_TAG_SWIPE, .paletteTag = ANIM_TAG_SWIPE, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = sAnims_FurySwipes, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimFurySwipes, }; const union AnimCmd gMovementWavesAnimCmds1[] = { ANIMCMD_FRAME(0, 8), ANIMCMD_FRAME(16, 8), ANIMCMD_FRAME(32, 8), ANIMCMD_FRAME(16, 8), ANIMCMD_END, }; const union AnimCmd gMovementWavesAnimCmds2[] = { ANIMCMD_FRAME(16, 8, .hFlip = TRUE), ANIMCMD_FRAME(32, 8, .hFlip = TRUE), ANIMCMD_FRAME(16, 8, .hFlip = TRUE), ANIMCMD_FRAME(0, 8, .hFlip = TRUE), ANIMCMD_END, }; const union AnimCmd *const gMovementWavesAnimTable[] = { gMovementWavesAnimCmds1, gMovementWavesAnimCmds2, }; const struct SpriteTemplate gMovementWavesSpriteTemplate = { .tileTag = ANIM_TAG_MOVEMENT_WAVES, .paletteTag = ANIM_TAG_MOVEMENT_WAVES, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gMovementWavesAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimMovementWaves, }; static const union AffineAnimCmd sAffineAnims_UproarDistortion[] = { AFFINEANIMCMD_FRAME(-12, 8, 0, 4), AFFINEANIMCMD_FRAME(20, -20, 0, 4), AFFINEANIMCMD_FRAME(-8, 12, 0, 4), AFFINEANIMCMD_END, }; const struct SpriteTemplate gJaggedMusicNoteSpriteTemplate = { .tileTag = ANIM_TAG_JAGGED_MUSIC_NOTE, .paletteTag = ANIM_TAG_JAGGED_MUSIC_NOTE, .oam = &gOamData_AffineOff_ObjNormal_32x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimJaggedMusicNote, }; const union AffineAnimCmd gPerishSongMusicNoteAffineAnimCmds1[] = { AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 5), AFFINEANIMCMD_END, }; const union AffineAnimCmd gPerishSongMusicNoteAffineAnimCmds2[] = { AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 16), AFFINEANIMCMD_END_ALT(1), }; const union AffineAnimCmd gPerishSongMusicNoteAffineAnimCmds3[] = { AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 16), AFFINEANIMCMD_END_ALT(1), }; const union AffineAnimCmd *const gPerishSongMusicNoteAffineAnimTable[] = { gPerishSongMusicNoteAffineAnimCmds1, gPerishSongMusicNoteAffineAnimCmds2, gPerishSongMusicNoteAffineAnimCmds3, }; extern const union AnimCmd *const gMusicNotesAnimTable[]; const struct SpriteTemplate gPerishSongMusicNoteSpriteTemplate = { .tileTag = ANIM_TAG_MUSIC_NOTES_2, .paletteTag = ANIM_TAG_MUSIC_NOTES_2, .oam = &gOamData_AffineNormal_ObjNormal_16x16, .anims = gMusicNotesAnimTable, .images = NULL, .affineAnims = gPerishSongMusicNoteAffineAnimTable, .callback = AnimPerishSongMusicNote, }; const struct SpriteTemplate gPerishSongMusicNote2SpriteTemplate = { .tileTag = ANIM_TAG_MUSIC_NOTES_2, .paletteTag = ANIM_TAG_MUSIC_NOTES_2, .oam = &gOamData_AffineNormal_ObjNormal_16x16, .anims = gMusicNotesAnimTable, .images = NULL, .affineAnims = gPerishSongMusicNoteAffineAnimTable, .callback = AnimPerishSongMusicNote2, }; const union AffineAnimCmd gGuardRingAffineAnimCmds1[] = { AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), AFFINEANIMCMD_END, }; const union AffineAnimCmd gGuardRingAffineAnimCmds2[] = { AFFINEANIMCMD_FRAME(0x200, 0x100, 0, 0), AFFINEANIMCMD_END, }; const union AffineAnimCmd *const gGuardRingAffineAnimTable[] = { gGuardRingAffineAnimCmds1, gGuardRingAffineAnimCmds2, }; const struct SpriteTemplate gGuardRingSpriteTemplate = { .tileTag = ANIM_TAG_GUARD_RING, .paletteTag = ANIM_TAG_GUARD_RING, .oam = &gOamData_AffineDouble_ObjBlend_64x32, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gGuardRingAffineAnimTable, .callback = AnimGuardRing, }; #define sAmplitudeX data[1] #define sCircleSpeed data[2] #define sMoveSteps data[3] #define sAmplitudeY data[4] static void AnimCirclingFinger(struct Sprite *sprite) { SetSpriteCoordsToAnimAttackerCoords(sprite); SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); sprite->y += gBattleAnimArgs[1]; sprite->sAmplitudeX = gBattleAnimArgs[2]; sprite->sCircleSpeed = gBattleAnimArgs[4]; sprite->sMoveSteps = gBattleAnimArgs[5]; sprite->sAmplitudeY = gBattleAnimArgs[3]; StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); sprite->callback = TranslateSpriteInEllipse; sprite->callback(sprite); } #undef sAmplitudeX #undef sCircleSpeed #undef sMoveSteps #undef sAmplitudeY static void AnimBouncingMusicNote(struct Sprite *sprite) { u8 battler; if (gBattleAnimArgs[0] == 0) battler = gBattleAnimAttacker; else battler = gBattleAnimTarget; SetSpriteNextToMonHead(battler, sprite); sprite->data[0] = 0; sprite->data[1] = 0; sprite->callback = AnimBouncingMusicNote_Step; } static void AnimBouncingMusicNote_Step(struct Sprite *sprite) { switch (sprite->data[0]) { case 0: sprite->y2 -= 3; if (++sprite->data[1] == 6) sprite->data[0]++; break; case 1: sprite->y2 += 3; if (--sprite->data[1] == 0) sprite->data[0]++; break; case 2: if (++sprite->data[1] == 64) DestroyAnimSprite(sprite); break; } } static void AnimVibrateBattlerBack_Step(struct Sprite *sprite) { s16 temp; gSprites[sprite->data[2]].x2 += sprite->data[1]; temp = sprite->data[1]; sprite->data[1] = -temp; if (sprite->data[0] == 0) { gSprites[sprite->data[2]].x2 = 0; DestroySpriteAndMatrix(sprite); } sprite->data[0]--; } static void AnimVibrateBattlerBack(struct Sprite *sprite) { u8 spriteId; sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); spriteId = gBattlerSpriteIds[gBattleAnimTarget]; if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) sprite->x -= gBattleAnimArgs[0]; else sprite->x += gBattleAnimArgs[0]; sprite->y += gBattleAnimArgs[1]; sprite->data[0] = gBattleAnimArgs[2]; sprite->data[1] = gBattleAnimArgs[3]; sprite->data[2] = spriteId; sprite->callback = AnimVibrateBattlerBack_Step; sprite->invisible = TRUE; } static void AnimMovingClamp(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, TRUE); sprite->data[0] = gBattleAnimArgs[2]; sprite->data[1] = gBattleAnimArgs[3]; sprite->data[5] = gBattleAnimArgs[4]; sprite->callback = WaitAnimForDuration; StoreSpriteCallbackInData6(sprite, AnimMovingClamp_Step); } static void AnimMovingClamp_Step(struct Sprite *sprite) { sprite->data[0] = sprite->data[1]; sprite->data[2] = sprite->x; sprite->data[4] = sprite->y + 15; sprite->callback = StartAnimLinearTranslation; StoreSpriteCallbackInData6(sprite, AnimMovingClamp_End); } static void AnimMovingClamp_End(struct Sprite *sprite) { if (sprite->data[5] == 0) DestroyAnimSprite(sprite); else sprite->data[5]--; } // Rotates the attacking mon sprite downwards and then back upwards to its original position. // No args. void AnimTask_Withdraw(u8 taskId) { PrepareBattlerSpriteForRotScale(gBattlerSpriteIds[gBattleAnimAttacker], ST_OAM_OBJ_NORMAL); gTasks[taskId].func = AnimTask_Withdraw_Step; } static void AnimTask_Withdraw_Step(u8 taskId) { u8 spriteId = gBattlerSpriteIds[gBattleAnimAttacker]; s16 rotation; if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) rotation = -gTasks[taskId].data[0]; else rotation = gTasks[taskId].data[0]; SetSpriteRotScale(spriteId, 0x100, 0x100, rotation); if (gTasks[taskId].data[1] == 0) { gTasks[taskId].data[0] += 0xB0; // this y position update gets overwritten by SetBattlerSpriteYOffsetFromRotation() gSprites[spriteId].y2++; } else if (gTasks[taskId].data[1] == 1) { if (++gTasks[taskId].data[3] == 30) gTasks[taskId].data[1] = 2; return; } else { gTasks[taskId].data[0] -= 0xB0; // this y position update gets overwritten by SetBattlerSpriteYOffsetFromRotation() gSprites[spriteId].y2--; } SetBattlerSpriteYOffsetFromRotation(spriteId); if (gTasks[taskId].data[0] == 0xF20 || gTasks[taskId].data[0] == 0) { if (gTasks[taskId].data[1] == 2) { ResetSpriteRotScale(spriteId); DestroyAnimVisualTask(taskId); } else { gTasks[taskId].data[1]++; } } } // Animates a "zap of energy" used in KINESIS. // arg 0: x pixel offset // arg 1: y pixel offset // arg 2: vertical flip static void AnimKinesisZapEnergy(struct Sprite *sprite) { SetSpriteCoordsToAnimAttackerCoords(sprite); if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) sprite->x -= gBattleAnimArgs[0]; else sprite->x += gBattleAnimArgs[0]; sprite->y += gBattleAnimArgs[1]; if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) { sprite->hFlip = 1; if (gBattleAnimArgs[2]) sprite->vFlip = 1; } else { if (gBattleAnimArgs[2]) sprite->vFlip = 1; } sprite->callback = RunStoredCallbackWhenAnimEnds; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); } // Animates a sword that rises into the air after a brief pause. // arg 0: x pixel offset // arg 1: y pixel offset static void AnimSwordsDanceBlade(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, FALSE); sprite->callback = RunStoredCallbackWhenAffineAnimEnds; StoreSpriteCallbackInData6(sprite, AnimSwordsDanceBlade_Step); } static void AnimSwordsDanceBlade_Step(struct Sprite *sprite) { sprite->data[0] = 6; sprite->data[2] = sprite->x; sprite->data[4] = sprite->y - 32; sprite->callback = StartAnimLinearTranslation; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); } // Moves a projectile towards the target mon. The sprite is rotated to be pointing // in the same direction it's moving. // arg 0: initial x pixel offset // arg 1: initial y pixel offset // arg 2: target x pixel offset // arg 3: target y pixel offset // arg 4: duration static void AnimSonicBoomProjectile(struct Sprite *sprite) { s16 targetXPos; s16 targetYPos; u16 rotation; if (IsContest()) { gBattleAnimArgs[2] = -gBattleAnimArgs[2]; } else if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) { gBattleAnimArgs[2] = -gBattleAnimArgs[2]; gBattleAnimArgs[1] = -gBattleAnimArgs[1]; gBattleAnimArgs[3] = -gBattleAnimArgs[3]; } InitSpritePosToAnimAttacker(sprite, TRUE); targetXPos = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; targetYPos = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; rotation = ArcTan2Neg(targetXPos - sprite->x, targetYPos - sprite->y); rotation += 0xF000; if (IsContest()) rotation -= 0x6000; TrySetSpriteRotScale(sprite, FALSE, 0x100, 0x100, rotation); sprite->data[0] = gBattleAnimArgs[4]; sprite->data[2] = targetXPos; sprite->data[4] = targetYPos; sprite->callback = StartAnimLinearTranslation; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); } static void AnimAirWaveProjectile_Step2(struct Sprite *sprite) { if (sprite->data[0]-- <= 0) { gTasks[sprite->data[7]].data[1]--; DestroySprite(sprite); } } static void AnimAirWaveProjectile_Step1(struct Sprite *sprite) { struct Task* task = &gTasks[sprite->data[7]]; if (sprite->data[0] > task->data[5]) { sprite->data[5] += sprite->data[3]; sprite->data[6] += sprite->data[4]; } else { sprite->data[5] -= sprite->data[3]; sprite->data[6] -= sprite->data[4]; } sprite->data[1] += sprite->data[5]; sprite->data[2] += sprite->data[6]; if (1 & task->data[7]) sprite->x2 = ((u16)sprite->data[1] >> 8) * -1; else sprite->x2 = (u16)sprite->data[1] >> 8; if (1 & task->data[8]) sprite->y2 = ((u16)sprite->data[2] / 256u) * -1; else sprite->y2 = (u16)sprite->data[2] / 256u; if (sprite->data[0]-- <= 0) { sprite->data[0] = 30; sprite->callback = AnimAirWaveProjectile_Step2; } } static void AnimAirWaveProjectile(struct Sprite *sprite) { s16 a; s16 b; s16 c; struct Task* task = &gTasks[sprite->data[7]]; sprite->data[1] += (-2 & task->data[7]); sprite->data[2] += (-2 & task->data[8]); if (1 & task->data[7]) sprite->x2 = ((u16)sprite->data[1] >> 8) * -1; else sprite->x2 = (u16)sprite->data[1] >> 8; if (1 & task->data[8]) sprite->y2 = ((u16)sprite->data[2] / 256u) * -1; else sprite->y2 = (u16)sprite->data[2] / 256u; if (sprite->data[0]-- <= 0) { sprite->data[0] = 8; task->data[5] = 4; a = MathUtil_Inv16(Q_8_8(16)); sprite->x += sprite->x2; sprite->y += sprite->y2; sprite->y2 = 0; sprite->x2 = 0; if (task->data[11] >= sprite->x) b = (task->data[11] - sprite->x) << 8; else b = (sprite->x - task->data[11]) << 8; if (task->data[12] >= sprite->y) c = (task->data[12] - sprite->y) << 8; else c = (sprite->y - task->data[12]) << 8; sprite->data[2] = 0; sprite->data[1] = 0; sprite->data[6] = 0; sprite->data[5] = 0; sprite->data[3] = MathUtil_Mul16(MathUtil_Mul16(b, a), MathUtil_Inv16(Q_8_8(1.75))); sprite->data[4] = MathUtil_Mul16(MathUtil_Mul16(c, a), MathUtil_Inv16(Q_8_8(1.75))); sprite->callback = AnimAirWaveProjectile_Step1; } } static void AirCutterProjectileStep2(u8 taskId) { if (gTasks[taskId].data[1] == 0) DestroyAnimVisualTask(taskId); } static void AirCutterProjectileStep1(u8 taskId) { if (gTasks[taskId].data[0]-- <= 0) { u8 spriteId; struct Sprite *sprite; spriteId = CreateSprite(&gAirWaveProjectileSpriteTemplate, gTasks[taskId].data[9], gTasks[taskId].data[10], gTasks[taskId].data[2] - gTasks[taskId].data[1]); sprite = &gSprites[spriteId]; switch (gTasks[taskId].data[4]) { case 1: sprite->oam.matrixNum |= (ST_OAM_HFLIP | ST_OAM_VFLIP); break; case 2: sprite->oam.matrixNum = ST_OAM_HFLIP; break; } sprite->data[0] = gTasks[taskId].data[5] - gTasks[taskId].data[6]; sprite->data[7] = taskId; gTasks[taskId].data[gTasks[taskId].data[1] + 13] = spriteId; gTasks[taskId].data[0] = gTasks[taskId].data[3]; gTasks[taskId].data[1]++; PlaySE12WithPanning(SE_M_BLIZZARD2, BattleAnimAdjustPanning(-63)); if (gTasks[taskId].data[1] > 2) gTasks[taskId].func = AirCutterProjectileStep2; } } void AnimTask_AirCutterProjectile(u8 taskId) { s16 attackerY = 0; s16 attackerX = 0; s16 targetX = 0; s16 targetY = 0; s16 xDiff, yDiff; if (IsContest()) { gTasks[taskId].data[4] = 2; gBattleAnimArgs[0] = -gBattleAnimArgs[0]; if (gBattleAnimArgs[2] & 1) gBattleAnimArgs[2] &= ~1; else gBattleAnimArgs[2] |= 1; } else { if ((gBattlerPositions[gBattleAnimTarget] & BIT_SIDE) == B_SIDE_PLAYER) { gTasks[taskId].data[4] = 1; gBattleAnimArgs[0] = -gBattleAnimArgs[0]; gBattleAnimArgs[1] = -gBattleAnimArgs[1]; if (gBattleAnimArgs[2] & 1) gBattleAnimArgs[2] &= ~1; else gBattleAnimArgs[2] |= 1; } } attackerX = gTasks[taskId].data[9] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); attackerY = gTasks[taskId].data[10] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y); if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimTarget))) { SetAverageBattlerPositions(gBattleAnimTarget, 0, &targetX, &targetY); } else { targetX = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X); targetY = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y); } targetX = gTasks[taskId].data[11] = targetX + gBattleAnimArgs[0]; targetY = gTasks[taskId].data[12] = targetY + gBattleAnimArgs[1]; if (targetX >= attackerX) xDiff = targetX - attackerX; else xDiff = attackerX - targetX; gTasks[taskId].data[5] = MathUtil_Mul16(xDiff, MathUtil_Inv16(gBattleAnimArgs[2] & ~1)); gTasks[taskId].data[6] = MathUtil_Mul16(gTasks[taskId].data[5], Q_8_8(0.5)); gTasks[taskId].data[7] = gBattleAnimArgs[2]; if (targetY >= attackerY) { yDiff = targetY - attackerY; gTasks[taskId].data[8] = MathUtil_Mul16(yDiff, MathUtil_Inv16(gTasks[taskId].data[5])) & ~1; } else { yDiff = attackerY - targetY; gTasks[taskId].data[8] = MathUtil_Mul16(yDiff, MathUtil_Inv16(gTasks[taskId].data[5])) | 1; } gTasks[taskId].data[3] = gBattleAnimArgs[3]; if (gBattleAnimArgs[4] & 0x80) { gBattleAnimArgs[4] ^= 0x80; if (gBattleAnimArgs[4] >= 64) { u16 var = GetBattlerSpriteSubpriority(gBattleAnimTarget) + (gBattleAnimArgs[4] - 64); gTasks[taskId].data[2] = var; } else { u16 var = GetBattlerSpriteSubpriority(gBattleAnimTarget) - gBattleAnimArgs[4]; gTasks[taskId].data[2] = var; } } else { if (gBattleAnimArgs[4] >= 64) { u16 var = GetBattlerSpriteSubpriority(gBattleAnimTarget) + (gBattleAnimArgs[4] - 64); gTasks[taskId].data[2] = var; } else { u16 var = GetBattlerSpriteSubpriority(gBattleAnimTarget) - gBattleAnimArgs[4]; gTasks[taskId].data[2] = var; } } if (gTasks[taskId].data[2] < 3) gTasks[taskId].data[2] = 3; gTasks[taskId].func = AirCutterProjectileStep1; } static void AnimVoidLines(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, FALSE); sprite->data[0] = 0x100 + (IndexOfSpritePaletteTag(sVoidLinesSpriteTemplate.paletteTag) << 4); sprite->callback = AnimVoidLines_Step; } static void AnimVoidLines_Step(struct Sprite *sprite) { u16 id, val; int i; if (++sprite->data[1] == 2) { sprite->data[1] = 0; id = sprite->data[0]; val = gPlttBufferFaded[8 + id]; for (i = 8; i < 16; i++) gPlttBufferFaded[i + id] = gPlttBufferFaded[i + id + 1]; gPlttBufferFaded[id + 15] = val; if (++sprite->data[2] == 24) DestroyAnimSprite(sprite); } } static void AnimCoinThrow(struct Sprite *sprite) { s16 r6; s16 r7; u16 var; InitSpritePosToAnimAttacker(sprite, TRUE); r6 = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); r7 = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; r6 += gBattleAnimArgs[2]; var = ArcTan2Neg(r6 - sprite->x, r7 - sprite->y); var += 0xC000; TrySetSpriteRotScale(sprite, FALSE, 0x100, 0x100, var); sprite->data[0] = gBattleAnimArgs[4]; sprite->data[2] = r6; sprite->data[4] = r7; sprite->callback = InitAnimLinearTranslationWithSpeedAndPos; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); } static void AnimFallingCoin(struct Sprite *sprite) { sprite->data[2] = -16; sprite->y += 8; sprite->callback = AnimFallingCoin_Step; } static void AnimFallingCoin_Step(struct Sprite *sprite) { sprite->data[0] += 0x80; sprite->x2 = sprite->data[0] >> 8; if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) sprite->x2 = -sprite->x2; sprite->y2 = Sin(sprite->data[1], sprite->data[2]); sprite->data[1] += 5; if (sprite->data[1] > 126) { sprite->data[1] = 0; sprite->data[2] /= 2; if (++sprite->data[3] == 2) DestroyAnimSprite(sprite); } } static void AnimBulletSeed(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, TRUE); sprite->data[0] = 20; sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); sprite->callback = StartAnimLinearTranslation; sprite->affineAnimPaused = 1; StoreSpriteCallbackInData6(sprite, AnimBulletSeed_Step1); } static void AnimBulletSeed_Step1(struct Sprite *sprite) { int i; u16 rand; s16* ptr; PlaySE12WithPanning(SE_M_HORN_ATTACK, BattleAnimAdjustPanning(63)); sprite->x += sprite->x2; sprite->y += sprite->y2; sprite->y2 = 0; sprite->x2 = 0; ptr = &sprite->data[7]; for (i = 0; i < 8; i++) ptr[i - 7] = 0; rand = Random2(); sprite->data[6] = 0xFFF4 - (rand & 7); rand = Random2(); sprite->data[7] = (rand % 0xA0) + 0xA0; sprite->callback = AnimBulletSeed_Step2; sprite->affineAnimPaused = 0; } static void AnimBulletSeed_Step2(struct Sprite *sprite) { sprite->data[0] += sprite->data[7]; sprite->x2 = sprite->data[0] >> 8; if (sprite->data[7] & 1) sprite->x2 = -sprite->x2; sprite->y2 = Sin(sprite->data[1], sprite->data[6]); sprite->data[1] += 8; if (sprite->data[1] > 126) { sprite->data[1] = 0; sprite->data[2] /= 2; if (++sprite->data[3] == 1) DestroyAnimSprite(sprite); } } // Moves a tornado in a circlular motion. // arg 0: initial x pixel offset // arg 1: initial y pixel offset // arg 2: wave amplitude // arg 3: unused // arg 4: initial wave offset // arg 5: wave period (higher means faster wave) // arg 6: duration static void AnimRazorWindTornado(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, FALSE); if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) sprite->y += 16; sprite->data[0] = gBattleAnimArgs[4]; sprite->data[1] = gBattleAnimArgs[2]; sprite->data[2] = gBattleAnimArgs[5]; sprite->data[3] = gBattleAnimArgs[6]; sprite->data[4] = gBattleAnimArgs[3]; sprite->callback = TranslateSpriteInCircle; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); sprite->callback(sprite); } // Animates a single pincer line that extends towards the center of the target mon. // arg 0: invert static void AnimViceGripPincer(struct Sprite *sprite) { s16 startXOffset = 32; s16 startYOffset = -32; s16 endXOffset = 16; s16 endYOffset = -16; if (gBattleAnimArgs[0]) { startXOffset = -32; startYOffset = 32; endXOffset = -16; endYOffset = 16; StartSpriteAnim(sprite, 1); } sprite->x += startXOffset; sprite->y += startYOffset; sprite->data[0] = 6; sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + endXOffset; sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + endYOffset; sprite->callback = StartAnimLinearTranslation; StoreSpriteCallbackInData6(sprite, AnimViceGripPincer_Step); } static void AnimViceGripPincer_Step(struct Sprite *sprite) { if (sprite->animEnded) DestroyAnimSprite(sprite); } // Animates a single pincer line that extends towards the center of the target mon, and then back out. // arg 0: animation id static void AnimGuillotinePincer(struct Sprite *sprite) { s16 startXOffset = 32; s16 startYOffset = -32; s16 endXOffset = 16; s16 endYOffset = -16; if (gBattleAnimArgs[0]) { startXOffset = -32; startYOffset = 32; endXOffset = -16; endYOffset = 16; StartSpriteAnim(sprite, gBattleAnimArgs[0]); } sprite->x += startXOffset; sprite->y += startYOffset; sprite->data[0] = 6; sprite->data[1] = sprite->x; sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + endXOffset; sprite->data[3] = sprite->y; sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + endYOffset; InitAnimLinearTranslation(sprite); sprite->data[5] = gBattleAnimArgs[0]; sprite->data[6] = sprite->data[0]; sprite->callback = AnimGuillotinePincer_Step1; } static void AnimGuillotinePincer_Step1(struct Sprite *sprite) { if (AnimTranslateLinear(sprite) && sprite->animEnded) { SeekSpriteAnim(sprite, 0); sprite->animPaused = 1; sprite->x += sprite->x2; sprite->y += sprite->y2; sprite->x2 = 2; sprite->y2 = -2; sprite->data[0] = sprite->data[6]; sprite->data[1] ^= 1; sprite->data[2] ^= 1; sprite->data[4] = 0; sprite->data[3] = 0; sprite->callback = AnimGuillotinePincer_Step2; } } static void AnimGuillotinePincer_Step2(struct Sprite *sprite) { if (sprite->data[3]) { sprite->x2 = -sprite->x2; sprite->y2 = -sprite->y2; } sprite->data[3] ^= 1; if (++sprite->data[4] == 51) { sprite->y2 = 0; sprite->x2 = 0; sprite->data[4] = 0; sprite->data[3] = 0; sprite->animPaused = 0; StartSpriteAnim(sprite, sprite->data[5] ^ 1); sprite->callback = AnimGuillotinePincer_Step3; } } static void AnimGuillotinePincer_Step3(struct Sprite *sprite) { if (AnimTranslateLinear(sprite)) DestroyAnimSprite(sprite); } // Scales up the target mon sprite, and sets the palette to grayscale. // Used in MOVE_DISABLE. // No args. void AnimTask_GrowAndGrayscale(u8 taskId) { u8 spriteId = GetAnimBattlerSpriteId(ANIM_TARGET); PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_BLEND); SetSpriteRotScale(spriteId, 0xD0, 0xD0, 0); SetGrayscaleOrOriginalPalette(gSprites[spriteId].oam.paletteNum + 16, FALSE); gTasks[taskId].data[0] = 80; gTasks[taskId].func = AnimTask_GrowAndGrayscale_Step; } static void AnimTask_GrowAndGrayscale_Step(u8 taskId) { if (--gTasks[taskId].data[0] == -1) { u8 spriteId = GetAnimBattlerSpriteId(ANIM_TARGET); ResetSpriteRotScale(spriteId); SetGrayscaleOrOriginalPalette(gSprites[spriteId].oam.paletteNum + 16, TRUE); DestroyAnimVisualTask(taskId); } } // Shrinks and grows the attacking mon several times. Also creates transparent versions of the // mon's sprite while it is shrinking. // No args. void AnimTask_Minimize(u8 taskId) { struct Task* task = &gTasks[taskId]; u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->data[0] = spriteId; PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_NORMAL); task->data[1] = 0; task->data[2] = 0; task->data[3] = 0; task->data[4] = 0x100; task->data[5] = 0; task->data[6] = 0; task->data[7] = GetBattlerSpriteSubpriority(gBattleAnimAttacker); task->func = AnimTask_Minimize_Step; } static void AnimTask_Minimize_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; switch (task->data[1]) { case 0: if (task->data[2] == 0 || task->data[2] == 3 || task->data[2] == 6) CreateMinimizeSprite(task, taskId); task->data[2]++; task->data[4] += 0x28; SetSpriteRotScale(task->data[0], task->data[4], task->data[4], 0); SetBattlerSpriteYOffsetFromYScale(task->data[0]); if (task->data[2] == 32) { task->data[5]++; task->data[1]++; } break; case 1: if (task->data[6] == 0) { if (task->data[5] == 3) { task->data[2] = 0; task->data[1] = 3; } else { task->data[2] = 0; task->data[3] = 0; task->data[4] = 0x100; SetSpriteRotScale(task->data[0], task->data[4], task->data[4], 0); SetBattlerSpriteYOffsetFromYScale(task->data[0]); task->data[1] = 2; } } break; case 2: task->data[1] = 0; break; case 3: if (++task->data[2] > 32) { task->data[2] = 0; task->data[1]++; } break; case 4: task->data[2] += 2; task->data[4] -= 0x50; SetSpriteRotScale(task->data[0], task->data[4], task->data[4], 0); SetBattlerSpriteYOffsetFromYScale(task->data[0]); if (task->data[2] == 32) { task->data[2] = 0; task->data[1]++; } break; case 5: ResetSpriteRotScale(task->data[0]); gSprites[task->data[15]].y2 = 0; DestroyAnimVisualTask(taskId); break; } } static void CreateMinimizeSprite(struct Task* task, u8 taskId) { u16 matrixNum; s16 spriteId = CloneBattlerSpriteWithBlend(ANIM_ATTACKER); if (spriteId >= 0) { if ((matrixNum = AllocOamMatrix()) == 0xFF) { DestroySpriteWithActiveSheet(&gSprites[spriteId]); } else { gSprites[spriteId].oam.objMode = ST_OAM_OBJ_BLEND; gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_DOUBLE; gSprites[spriteId].affineAnimPaused = TRUE; gSprites[spriteId].oam.matrixNum = matrixNum; gSprites[spriteId].subpriority = task->data[7] - task->data[3]; task->data[3]++; task->data[6]++; gSprites[spriteId].data[0] = 16; gSprites[spriteId].data[1] = taskId; gSprites[spriteId].data[2] = 6; gSprites[spriteId].callback = ClonedMinizeSprite_Step; SetSpriteRotScale(spriteId, task->data[4], task->data[4], 0); gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL; CalcCenterToCornerVec(&gSprites[spriteId], gSprites[spriteId].oam.shape, gSprites[spriteId].oam.size, gSprites[spriteId].oam.affineMode); } } } static void ClonedMinizeSprite_Step(struct Sprite *sprite) { if (--sprite->data[0] == 0) { gTasks[sprite->data[1]].data[sprite->data[2]]--; FreeOamMatrix(sprite->oam.matrixNum); DestroySpriteWithActiveSheet(sprite); } } // Task to facilitate expanding and hopping effect seen in Splash. // arg 0: anim battler // arg 1: num hops void AnimTask_Splash(u8 taskId) { struct Task* task = &gTasks[taskId]; if (gBattleAnimArgs[1] == 0) { DestroyAnimVisualTask(taskId); } else { u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); task->data[0] = spriteId; task->data[1] = 0; task->data[2] = gBattleAnimArgs[1]; task->data[3] = 0; task->data[4] = 0; PrepareAffineAnimInTaskData(task, spriteId, gSplashEffectAffineAnimCmds); task->func = AnimTask_Splash_Step; } } static void AnimTask_Splash_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; switch (task->data[1]) { case 0: RunAffineAnimFromTaskData(task); task->data[4] += 3; gSprites[task->data[0]].y2 += task->data[4]; if (++task->data[3] > 7) { task->data[3] = 0; task->data[1]++; } break; case 1: RunAffineAnimFromTaskData(task); gSprites[task->data[0]].y2 += task->data[4]; if (++task->data[3] > 7) { task->data[3] = 0; task->data[1]++; } break; case 2: if (task->data[4] != 0) { gSprites[task->data[0]].y2 -= 2; task->data[4] -= 2; } else task->data[1]++; break; case 3: if (!RunAffineAnimFromTaskData(task)) { if (--task->data[2] == 0) { gSprites[task->data[0]].y2 = 0; DestroyAnimVisualTask(taskId); } else { PrepareAffineAnimInTaskData(task, task->data[0], gSplashEffectAffineAnimCmds); task->data[1] = 0; } } break; } } // Grows, pauses, then shrinks the attacking mon. // Used by MOVE_SWAGGER and MOVE_BULK_UP // No args. void AnimTask_GrowAndShrink(u8 taskId) { struct Task* task = &gTasks[taskId]; u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); PrepareAffineAnimInTaskData(task, spriteId, gGrowAndShrinkAffineAnimCmds); task->func = AnimTask_GrowAndShrink_Step; } static void AnimTask_GrowAndShrink_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; if (!RunAffineAnimFromTaskData(task)) DestroyAnimVisualTask(taskId); } // Animates a little puff of the mon's breath. // Used by MOVE_SWAGGER and MOVE_BULK_UP // No args. static void AnimBreathPuff(struct Sprite *sprite) { if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) { StartSpriteAnim(sprite, 0); sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) + 32; sprite->data[1] = 64; } else { StartSpriteAnim(sprite, 1); sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) - 32; sprite->data[1] = -64; } sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); sprite->data[0] = 52; sprite->data[2] = 0; sprite->data[3] = 0; sprite->data[4] = 0; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); sprite->callback = TranslateSpriteLinearFixedPoint; } // Animates an "angry" mark above a mon's head. // arg 0: target mon (0 = attacker, 1 = target) // arg 1: x pixel offset // arg 2: y pixel offset static void AnimAngerMark(struct Sprite *sprite) { u8 battler; if (!gBattleAnimArgs[0]) battler = gBattleAnimAttacker; else battler = gBattleAnimTarget; if (GetBattlerSide(battler) == B_SIDE_OPPONENT) gBattleAnimArgs[1] *= -1; sprite->x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2) + gBattleAnimArgs[1]; sprite->y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[2]; if (sprite->y < 8) sprite->y = 8; StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); sprite->callback = RunStoredCallbackWhenAffineAnimEnds; } // left/right movements void AnimTask_ThrashMoveMonHorizontal(u8 taskId) { struct Task* task = &gTasks[taskId]; u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->data[0] = spriteId; task->data[1] = 0; PrepareAffineAnimInTaskData(task, spriteId, gThrashMoveMonAffineAnimCmds); task->func = AnimTask_ThrashMoveMonHorizontal_Step; } static void AnimTask_ThrashMoveMonHorizontal_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; if (!RunAffineAnimFromTaskData(task)) DestroyAnimVisualTask(taskId); } // up/down movements void AnimTask_ThrashMoveMonVertical(u8 taskId) { struct Task* task = &gTasks[taskId]; task->data[0] = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->data[1] = 0; task->data[2] = 4; task->data[3] = 7; task->data[4] = 3; task->data[5] = gSprites[task->data[0]].x; task->data[6] = gSprites[task->data[0]].y; task->data[7] = 0; task->data[8] = 0; task->data[9] = 2; if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) task->data[2] *= -1; task->func = AnimTask_ThrashMoveMonVertical_Step; } static void AnimTask_ThrashMoveMonVertical_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; if (++task->data[7] > 2) { task->data[7] = 0; task->data[8]++; if (task->data[8] & 1) gSprites[task->data[0]].y += task->data[9]; else gSprites[task->data[0]].y -= task->data[9]; } switch (task->data[1]) { case 0: gSprites[task->data[0]].x += task->data[2]; if (--task->data[3] == 0) { task->data[3] = 14; task->data[1] = 1; } break; case 1: gSprites[task->data[0]].x -= task->data[2]; if (--task->data[3] == 0) { task->data[3] = 7; task->data[1] = 2; } break; case 2: gSprites[task->data[0]].x += task->data[2]; if (--task->data[3] == 0) { if (--task->data[4] != 0) { task->data[3] = 7; task->data[1] = 0; } else { if ((task->data[8] & 1) != 0) gSprites[task->data[0]].y -= task->data[9]; DestroyAnimVisualTask(taskId); } } break; } } void AnimTask_SketchDrawMon(u8 taskId) { struct Task* task = &gTasks[taskId]; struct ScanlineEffectParams params; s16 i; task->data[0] = GetBattlerYCoordWithElevation(gBattleAnimTarget) + 32; task->data[1] = 4; task->data[2] = 0; task->data[3] = 0; task->data[4] = 0; task->data[5] = 0; task->data[15] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_HEIGHT); if (GetBattlerSpriteBGPriorityRank(gBattleAnimTarget) == 1) { task->data[6] = gBattle_BG1_X; params.dmaDest = ®_BG1HOFS; } else { task->data[6] = gBattle_BG2_X; params.dmaDest = ®_BG2HOFS; } for (i = task->data[0] - 0x40; i <= task->data[0]; i++) { if (i >= 0) { gScanlineEffectRegBuffers[0][i] = task->data[6] + 0xF0; gScanlineEffectRegBuffers[1][i] = task->data[6] + 0xF0; } } params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; params.initState = 1; params.unused9 = 0; ScanlineEffect_SetParams(params); task->func = AnimTask_SketchDrawMon_Step; } static void AnimTask_SketchDrawMon_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; switch (task->data[4]) { case 0: if (++task->data[5] > 20) task->data[4]++; break; case 1: if (++task->data[1] > 3) { task->data[1] = 0; task->data[2] = task->data[3] & 3; task->data[5] = task->data[0] - task->data[3]; switch (task->data[2]) { case 0: break; case 1: task->data[5] -= 2; break; case 2: task->data[5] += 1; break; case 3: task->data[5] += 1; break; } if (task->data[5] >= 0) { gScanlineEffectRegBuffers[0][task->data[5]] = task->data[6]; gScanlineEffectRegBuffers[1][task->data[5]] = task->data[6]; } if (++task->data[3] >= task->data[15]) { gScanlineEffect.state = 3; DestroyAnimVisualTask(taskId); } } break; } } static void AnimPencil(struct Sprite *sprite) { sprite->x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X) - 16; sprite->y = GetBattlerYCoordWithElevation(gBattleAnimTarget) + 16; sprite->data[0] = 0; sprite->data[1] = 0; sprite->data[2] = 0; sprite->data[3] = 16; sprite->data[4] = 0; sprite->data[5] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_HEIGHT) + 2; sprite->data[6] = BattleAnimAdjustPanning(63); sprite->callback = AnimPencil_Step; } static void AnimPencil_Step(struct Sprite *sprite) { switch (sprite->data[0]) { case 0: if (++sprite->data[2] > 1) { sprite->data[2] = 0; sprite->invisible = !sprite->invisible; } if (++sprite->data[1] > 16) { sprite->invisible = FALSE; sprite->data[0]++; } break; case 1: if (++sprite->data[1] > 3 && sprite->data[2] < sprite->data[5]) { sprite->data[1] = 0; sprite->y -= 1; sprite->data[2]++; if (sprite->data[2] % 10 == 0) PlaySE12WithPanning(SE_M_SKETCH, sprite->data[6]); } sprite->data[4] += sprite->data[3]; if (sprite->data[4] > 31) { sprite->data[4] = 0x40 - sprite->data[4]; sprite->data[3] *= -1; } else if (sprite->data[4] <= -32) { sprite->data[4] = -0x40 - sprite->data[4]; sprite->data[3] *= -1; } sprite->x2 = sprite->data[4]; if (sprite->data[5] == sprite->data[2]) { sprite->data[1] = 0; sprite->data[2] = 0; sprite->data[0]++; } break; case 2: if (++sprite->data[2] > 1) { sprite->data[2] = 0; sprite->invisible = !sprite->invisible; } if (++sprite->data[1] > 16) { sprite->invisible = FALSE; DestroyAnimSprite(sprite); } break; } } static void AnimBlendThinRing(struct Sprite *sprite) { u8 battler = 0; u16 sp0 = 0; u16 sp1 = 0; u8 r4; if (gBattleAnimArgs[2] == 0) battler = gBattleAnimAttacker; else battler = gBattleAnimTarget; r4 = gBattleAnimArgs[3] ^ 1; if (IsDoubleBattle() && IsBattlerSpriteVisible(BATTLE_PARTNER(battler))) { SetAverageBattlerPositions(battler, r4, &sp0, &sp1); if (r4 == 0) r4 = GetBattlerSpriteCoord(battler, BATTLER_COORD_X); else r4 = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2); if (GetBattlerSide(battler) != B_SIDE_PLAYER) gBattleAnimArgs[0] -= (sp0 - r4) - gBattleAnimArgs[0]; // This is weird. else gBattleAnimArgs[0] = sp0 - r4; } sprite->callback = AnimSpriteOnMonPos; sprite->callback(sprite); } static void AnimHyperVoiceRing_WaitEnd(struct Sprite *sprite) { if (AnimTranslateLinear(sprite)) { FreeSpriteOamMatrix(sprite); DestroyAnimSprite(sprite); } } static void AnimHyperVoiceRing(struct Sprite *sprite) { u16 startX = 0; u16 startY = 0; s16 x = 0; s16 y = 0; u8 yCoordType; u8 battler1; u8 battler2; u8 xCoordType; if (gBattleAnimArgs[5] == 0) { battler1 = gBattleAnimAttacker; battler2 = gBattleAnimTarget; } else { battler1 = gBattleAnimTarget; battler2 = gBattleAnimAttacker; } if (!gBattleAnimArgs[6]) { xCoordType = BATTLER_COORD_X; yCoordType = BATTLER_COORD_Y; } else { xCoordType = BATTLER_COORD_X_2; yCoordType = BATTLER_COORD_Y_PIC_OFFSET; } if (GetBattlerSide(battler1) != B_SIDE_PLAYER) { startX = GetBattlerSpriteCoord(battler1, xCoordType) + gBattleAnimArgs[0]; if (IsBattlerSpriteVisible(BATTLE_PARTNER(battler2))) sprite->subpriority = gSprites[gBattlerSpriteIds[BATTLE_PARTNER(battler2)]].subpriority - 1; else sprite->subpriority = gSprites[gBattlerSpriteIds[battler2]].subpriority - 1; } else { startX = GetBattlerSpriteCoord(battler1, xCoordType) - gBattleAnimArgs[0]; if (!IsContest() && IsBattlerSpriteVisible(BATTLE_PARTNER(battler1))) { if (gSprites[gBattlerSpriteIds[battler1]].x < gSprites[gBattlerSpriteIds[BATTLE_PARTNER(battler1)]].x) sprite->subpriority = gSprites[gBattlerSpriteIds[BATTLE_PARTNER(battler1)]].subpriority + 1; else sprite->subpriority = gSprites[gBattlerSpriteIds[battler1]].subpriority - 1; } else { sprite->subpriority = gSprites[gBattlerSpriteIds[battler1]].subpriority - 1; } } startY = GetBattlerSpriteCoord(battler1, yCoordType) + gBattleAnimArgs[1]; if (!IsContest() && IsBattlerSpriteVisible(BATTLE_PARTNER(battler2))) { SetAverageBattlerPositions(battler2, gBattleAnimArgs[6], &x, &y); } else { x = GetBattlerSpriteCoord(battler2, xCoordType); y = GetBattlerSpriteCoord(battler2, yCoordType); } if (GetBattlerSide(battler2)) x += gBattleAnimArgs[3]; else x -= gBattleAnimArgs[3]; y += gBattleAnimArgs[4]; sprite->x = sprite->data[1] = startX; sprite->y = sprite->data[3] = startY; sprite->data[2] = x; sprite->data[4] = y; sprite->data[0] = gBattleAnimArgs[0]; InitAnimLinearTranslation(sprite); sprite->callback = AnimHyperVoiceRing_WaitEnd; sprite->callback(sprite); } static void AnimUproarRing(struct Sprite *sprite) { u8 index = IndexOfSpritePaletteTag(ANIM_TAG_THIN_RING); if (index != 0xFF) { BlendPalette(((index << 20) + 0x1010000) >> 16, 15, gBattleAnimArgs[5], gBattleAnimArgs[4]); } StartSpriteAffineAnim(sprite, 1); sprite->callback = AnimSpriteOnMonPos; sprite->callback(sprite); } static void AnimSoftBoiledEgg(struct Sprite *sprite) { s16 r1; InitSpritePosToAnimAttacker(sprite, FALSE); r1 = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? -160 : 160; sprite->data[0] = 0x380; sprite->data[1] = r1; sprite->data[7] = gBattleAnimArgs[2]; sprite->callback = AnimSoftBoiledEgg_Step1; } static void AnimSoftBoiledEgg_Step1(struct Sprite *sprite) { s16 add; sprite->y2 -= (sprite->data[0] >> 8); sprite->x2 = sprite->data[1] >> 8; sprite->data[0] -= 32; add = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? -160 : 160; sprite->data[1] += add; if (sprite->y2 > 0) { sprite->y += sprite->y2; sprite->x += sprite->x2; sprite->y2 = 0; sprite->x2 = 0; sprite->data[0] = 0; StartSpriteAffineAnim(sprite, 1); sprite->callback = AnimSoftBoiledEgg_Step2; } } static void AnimSoftBoiledEgg_Step2(struct Sprite *sprite) { if (sprite->data[0]++ > 19) { StartSpriteAffineAnim(sprite, 2); sprite->callback = AnimSoftBoiledEgg_Step3; } } static void AnimSoftBoiledEgg_Step3(struct Sprite *sprite) { if (sprite->affineAnimEnded) { StartSpriteAffineAnim(sprite, 1); sprite->data[0] = 0; if (sprite->data[7] == 0) { sprite->oam.tileNum += 16; sprite->callback = AnimSoftBoiledEgg_Step3_Callback1; } else { sprite->oam.tileNum += 32; sprite->callback = AnimSoftBoiledEgg_Step4; } } } static void AnimSoftBoiledEgg_Step3_Callback1(struct Sprite *sprite) { sprite->y2 -= 2; if (++sprite->data[0] == 9) { sprite->data[0] = 16; sprite->data[1] = 0; SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND((u16)sprite->data[0], 0)); sprite->callback = AnimSoftBoiledEgg_Step3_Callback2; } } static void AnimSoftBoiledEgg_Step3_Callback2(struct Sprite *sprite) { if (sprite->data[1]++ % 3 == 0) { sprite->data[0]--; SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[0], 16 - sprite->data[0])); if (sprite->data[0] == 0) sprite->callback = AnimSoftBoiledEgg_Step4; } } static void AnimSoftBoiledEgg_Step4(struct Sprite *sprite) { if ((u16)gBattleAnimArgs[7] == 0xFFFF) { sprite->invisible = TRUE; if (sprite->data[7] == 0) sprite->callback = AnimSoftBoiledEgg_Step4_Callback; else sprite->callback = DestroyAnimSprite; } } static void AnimSoftBoiledEgg_Step4_Callback(struct Sprite *sprite) { SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); DestroyAnimSprite(sprite); } // Used by Extremespeed void AnimTask_AttackerStretchAndDisappear(u8 taskId) { struct Task* task = &gTasks[taskId]; u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->data[0] = spriteId; PrepareAffineAnimInTaskData(task, spriteId, gStretchAttackerAffineAnimCmds); task->func = AnimTask_AttackerStretchAndDisappear_Step; } static void AnimTask_AttackerStretchAndDisappear_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; if (!RunAffineAnimFromTaskData(task)) { gSprites[task->data[0]].y2 = 0; gSprites[task->data[0]].invisible = TRUE; DestroyAnimVisualTask(taskId); } } void AnimTask_ExtremeSpeedImpact(u8 taskId) { struct Task* task = &gTasks[taskId]; task->data[0] = 0; task->data[1] = 0; task->data[2] = 0; task->data[3] = 0; task->data[12] = 3; if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) { task->data[13] = 0xFFFF; task->data[14] = 8; } else { task->data[13] = 1; task->data[14] = -8; } task->data[15] = GetAnimBattlerSpriteId(ANIM_TARGET); task->func = AnimTask_ExtremeSpeedImpact_Step; } static void AnimTask_ExtremeSpeedImpact_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; switch (task->data[0]) { case 0: gSprites[task->data[15]].x2 += task->data[14]; task->data[1] = 0; task->data[2] = 0; task->data[3] = 0; task->data[0]++; break; case 1: if (++task->data[1] > 1) { task->data[1] = 0; task->data[2]++; if (task->data[2] & 1) gSprites[task->data[15]].x2 += 6; else gSprites[task->data[15]].x2 -= 6; if (++task->data[3] > 4) { if (task->data[2] & 1) gSprites[task->data[15]].x2 -= 6; task->data[0]++; } } break; case 2: if (--task->data[12] != 0) task->data[0] = 0; else task->data[0]++; break; case 3: gSprites[task->data[15]].x2 += task->data[13]; if (gSprites[task->data[15]].x2 == 0) DestroyAnimVisualTask(taskId); break; } } void AnimTask_ExtremeSpeedMonReappear(u8 taskId) { struct Task* task = &gTasks[taskId]; task->data[0] = 0; task->data[1] = 0; task->data[2] = 0; task->data[3] = 0; task->data[4] = 1; task->data[13] = 14; task->data[14] = 2; task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->func = AnimTask_ExtremeSpeedMonReappear_Step; } static void AnimTask_ExtremeSpeedMonReappear_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; if (task->data[0] == 0 && ++task->data[1] > task->data[4]) { task->data[1] = 0; if (++task->data[2] & 1) gSprites[task->data[15]].invisible = FALSE; else gSprites[task->data[15]].invisible = TRUE; if (++task->data[3] >= task->data[13]) { if (++task->data[4] < task->data[14]) { task->data[1] = 0; task->data[2] = 0; task->data[3] = 0; } else { gSprites[task->data[15]].invisible = FALSE; DestroyAnimVisualTask(taskId); } } } } void AnimTask_SpeedDust(u8 taskId) { struct Task* task = &gTasks[taskId]; task->data[0] = 0; task->data[1] = 4; task->data[2] = 0; task->data[3] = 0; task->data[4] = 0; task->data[5] = 0; task->data[6] = 0; task->data[7] = 0; task->data[8] = 0; task->data[13] = 0; task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); task->data[15] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y); task->func = AnimTask_SpeedDust_Step; } static void AnimTask_SpeedDust_Step(u8 taskId) { struct Task* task = &gTasks[taskId]; switch (task->data[8]) { case 0: if (++task->data[4] > 1) { task->data[4] = 0; task->data[5] = (task->data[5] + 1) & 1; if (++task->data[6] > 20) { if (task->data[7] == 0) { task->data[6] = 0; task->data[8] = 1; } else task->data[8] = 2; } } break; case 1: task->data[5] = 0; if (++task->data[4] > 20) { task->data[7] = 1; task->data[8] = 0; } break; case 2: task->data[5] = 1; break; } switch (task->data[0]) { case 0: if (++task->data[1] > 4) { u8 spriteId; task->data[1] = 0; spriteId = CreateSprite(&gSpeedDustSpriteTemplate, task->data[14], task->data[15], 0); if (spriteId != MAX_SPRITES) { gSprites[spriteId].data[0] = taskId; gSprites[spriteId].data[1] = 13; gSprites[spriteId].x2 = gSpeedDustPosTable[task->data[2]][0]; gSprites[spriteId].y2 = gSpeedDustPosTable[task->data[2]][1]; task->data[13]++; if (++task->data[2] > 3) { task->data[2] = 0; if (++task->data[3] > 5) task->data[0]++; } } } break; case 1: if (task->data[13] == 0) DestroyAnimVisualTask(taskId); break; } } static void AnimSpeedDust(struct Sprite *sprite) { sprite->invisible = gTasks[sprite->data[0]].data[5]; if (sprite->animEnded) { gTasks[sprite->data[0]].data[sprite->data[1]]--; DestroySprite(sprite); } } void AnimTask_LoadMusicNotesPals(u8 taskId) { int i; u8 paletteNums[NUM_MUSIC_NOTE_PAL_TAGS]; paletteNums[0] = IndexOfSpritePaletteTag(ANIM_TAG_MUSIC_NOTES_2); for (i = 1; i < NUM_MUSIC_NOTE_PAL_TAGS; i++) paletteNums[i] = AllocSpritePalette(ANIM_SPRITES_START - i); gMonSpritesGfxPtr->buffer = AllocZeroed(0x2000); LZDecompressWram(gBattleAnimSpritePal_MusicNotes2, gMonSpritesGfxPtr->buffer); for (i = 0; i < NUM_MUSIC_NOTE_PAL_TAGS; i++) LoadPalette(&gMonSpritesGfxPtr->buffer[i * 32], (u16)((paletteNums[i] << 4) + 0x100), 32); FREE_AND_SET_NULL(gMonSpritesGfxPtr->buffer); DestroyAnimVisualTask(taskId); } void AnimTask_FreeMusicNotesPals(u8 taskId) { int i; for (i = 0; i < NUM_MUSIC_NOTE_PAL_TAGS; i++) FreeSpritePaletteByTag(sMusicNotePaletteTagsTable[i]); DestroyAnimVisualTask(taskId); } static void SetMusicNotePalette(struct Sprite *sprite, u8 a, u8 b) { u8 tile; tile = (b & 1); tile = ((-tile | tile) >> 31) & 32; sprite->oam.tileNum += tile + (a << 2); sprite->oam.paletteNum = IndexOfSpritePaletteTag(sMusicNotePaletteTagsTable[b >> 1]); } static void AnimHealBellMusicNote(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, FALSE); if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; sprite->data[0] = gBattleAnimArgs[4]; sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X) + gBattleAnimArgs[2]; sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + gBattleAnimArgs[3]; sprite->callback = StartAnimLinearTranslation; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); SetMusicNotePalette(sprite, gBattleAnimArgs[5], gBattleAnimArgs[6]); } static void AnimMagentaHeart(struct Sprite *sprite) { if (++sprite->data[0] == 1) InitSpritePosToAnimAttacker(sprite, FALSE); sprite->x2 = Sin(sprite->data[1], 8); sprite->y2 = sprite->data[2] >> 8; sprite->data[1] = (sprite->data[1] + 7) & 0xFF; sprite->data[2] -= 0x80; if (sprite->data[0] == 60) DestroyAnimSprite(sprite); } void AnimTask_FakeOut(u8 taskId) { u16 win0h = IsContest() ? 152 : DISPLAY_WIDTH; u16 win0v = 0; gBattle_WIN0H = win0h; gBattle_WIN0V = DISPLAY_HEIGHT; SetGpuReg(REG_OFFSET_WIN0H, gBattle_WIN0H); SetGpuReg(REG_OFFSET_WIN0V, gBattle_WIN0V); SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN1_ALL); SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_ALL | WINOUT_WINOBJ_ALL); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG3 | BLDCNT_EFFECT_DARKEN); SetGpuReg(REG_OFFSET_BLDY, 16); gTasks[taskId].data[0] = win0v; gTasks[taskId].data[1] = win0h; gTasks[taskId].func = AnimTask_FakeOut_Step1; } static void AnimTask_FakeOut_Step1(u8 taskId) { gTasks[taskId].data[0] += 13; gTasks[taskId].data[1] -= 13; if (gTasks[taskId].data[0] >= gTasks[taskId].data[1]) { gBattle_WIN0H = 0; gTasks[taskId].func = AnimTask_FakeOut_Step2; } else { gBattle_WIN0H = WIN_RANGE(gTasks[taskId].data[0], gTasks[taskId].data[1]); } } static void AnimTask_FakeOut_Step2(u8 taskId) { if (++gTasks[taskId].data[10] == 5) { gTasks[taskId].data[11] = 0x88; SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG3 | BLDCNT_EFFECT_LIGHTEN); BlendPalettes(GetBattleBgPalettesMask(1, 0, 0, 0, 0, 0, 0), 16, RGB(31, 31, 31)); } else if (gTasks[taskId].data[10] > 4) { gBattle_WIN0H = 0; gBattle_WIN0V = 0; SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDY, 0); DestroyAnimVisualTask(taskId); } } void AnimTask_StretchTargetUp(u8 taskId) { u8 spriteId = GetAnimBattlerSpriteId(ANIM_TARGET); if (++gTasks[taskId].data[0] == 1) { PrepareAffineAnimInTaskData(&gTasks[taskId], GetAnimBattlerSpriteId(ANIM_TARGET), sAffineAnims_StretchBattlerUp); gSprites[spriteId].x2 = 4; } else { gSprites[spriteId].x2 = -gSprites[spriteId].x2; if (!RunAffineAnimFromTaskData(&gTasks[taskId])) { gSprites[spriteId].x2 = 0; gSprites[spriteId].y2 = 0; DestroyAnimVisualTask(taskId); } } } void AnimTask_StretchAttackerUp(u8 taskId) { u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); if (++gTasks[taskId].data[0] == 1) { PrepareAffineAnimInTaskData(&gTasks[taskId], GetAnimBattlerSpriteId(ANIM_ATTACKER), sAffineAnims_StretchBattlerUp); gSprites[spriteId].x2 = 4; } else { gSprites[spriteId].x2 = -gSprites[spriteId].x2; if (!RunAffineAnimFromTaskData(&gTasks[taskId])) { gSprites[spriteId].x2 = 0; gSprites[spriteId].y2 = 0; DestroyAnimVisualTask(taskId); } } } static void AnimRedHeartProjectile(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, TRUE); sprite->data[0] = 95; sprite->data[1] = sprite->x; sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); sprite->data[3] = sprite->y; sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); InitAnimLinearTranslation(sprite); sprite->callback = AnimRedHeartProjectile_Step; } static void AnimRedHeartProjectile_Step(struct Sprite *sprite) { if (!AnimTranslateLinear(sprite)) { sprite->y2 += Sin(sprite->data[5], 14); sprite->data[5] = (sprite->data[5] + 4) & 0xFF; } else { DestroyAnimSprite(sprite); } } void AnimParticleBurst(struct Sprite *sprite) { if (sprite->data[0] == 0) { sprite->data[1] = gBattleAnimArgs[0]; sprite->data[2] = gBattleAnimArgs[1]; sprite->data[0]++; } else { sprite->data[4] += sprite->data[1]; sprite->x2 = sprite->data[4] >> 8; sprite->y2 = Sin(sprite->data[3], sprite->data[2]); sprite->data[3] = (sprite->data[3] + 3) & 0xFF; if (sprite->data[3] > 100) sprite->invisible = sprite->data[3] % 2; if (sprite->data[3] > 120) DestroyAnimSprite(sprite); } } static void AnimRedHeartRising(struct Sprite *sprite) { sprite->x = gBattleAnimArgs[0]; sprite->y = DISPLAY_HEIGHT; sprite->data[0] = gBattleAnimArgs[2]; sprite->data[1] = gBattleAnimArgs[1]; sprite->callback = WaitAnimForDuration; StoreSpriteCallbackInData6(sprite, AnimRedHeartRising_Step); } static void AnimRedHeartRising_Step(struct Sprite *sprite) { s16 y; sprite->data[2] += sprite->data[1]; sprite->y2 = -((u16)sprite->data[2] >> 8); sprite->x2 = Sin(sprite->data[3], 4); sprite->data[3] = (sprite->data[3] + 3) & 0xFF; y = sprite->y + sprite->y2; if (y <= 72) { sprite->invisible = sprite->data[3] % 2; if (y <= 64) DestroyAnimSprite(sprite); } } void AnimTask_HeartsBackground(u8 taskId) { struct BattleAnimBgData animBg; SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 3); SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); if (!IsContest()) SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); gBattle_BG1_X = 0; gBattle_BG1_Y = 0; SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); GetBattleAnimBg1Data(&animBg); AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Attract, animBg.tilesOffset); AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_Attract, FALSE); LoadCompressedPalette(gBattleAnimBgPalette_Attract, animBg.paletteId * 16, 32); gTasks[taskId].func = AnimTask_HeartsBackground_Step; } static void AnimTask_HeartsBackground_Step(u8 taskId) { struct BattleAnimBgData animBg; switch (gTasks[taskId].data[12]) { case 0: if (++gTasks[taskId].data[10] == 4) { gTasks[taskId].data[10] = 0; gTasks[taskId].data[11]++; SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); if (gTasks[taskId].data[11] == 16) { gTasks[taskId].data[12]++; gTasks[taskId].data[11] = 0; } } break; case 1: if (++gTasks[taskId].data[11] == 141) { gTasks[taskId].data[11] = 16; gTasks[taskId].data[12]++; } break; case 2: if (++gTasks[taskId].data[10] == 4) { gTasks[taskId].data[10] = 0; gTasks[taskId].data[11]--; SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); if (gTasks[taskId].data[11] == 0) { gTasks[taskId].data[12]++; gTasks[taskId].data[11] = 0; } } break; case 3: GetBattleAnimBg1Data(&animBg); ClearBattleAnimBg(animBg.bgId); gTasks[taskId].data[12]++; break; case 4: if (!IsContest()) SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); DestroyAnimVisualTask(taskId); break; } } void AnimTask_ScaryFace(u8 taskId) { struct BattleAnimBgData animBg; SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); if (!IsContest()) SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); gBattle_BG1_X = 0; gBattle_BG1_Y = 0; SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); GetBattleAnimBg1Data(&animBg); if (IsContest()) AnimLoadCompressedBgTilemapHandleContest(&animBg, &gBattleAnimBgTilemap_ScaryFaceContest, FALSE); else if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_OPPONENT) AnimLoadCompressedBgTilemapHandleContest(&animBg, &gBattleAnimBgTilemap_ScaryFacePlayer, FALSE); else AnimLoadCompressedBgTilemapHandleContest(&animBg, &gBattleAnimBgTilemap_ScaryFaceOpponent, FALSE); AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_ScaryFace, animBg.tilesOffset); LoadCompressedPalette(gBattleAnimBgPalette_ScaryFace, animBg.paletteId * 16, 32); gTasks[taskId].func = AnimTask_ScaryFace_Step; } static void AnimTask_ScaryFace_Step(u8 taskId) { struct BattleAnimBgData animBg; switch (gTasks[taskId].data[12]) { case 0: if (++gTasks[taskId].data[10] == 2) { gTasks[taskId].data[10] = 0; gTasks[taskId].data[11]++; SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); if (gTasks[taskId].data[11] == 14) { gTasks[taskId].data[12]++; gTasks[taskId].data[11] = 0; } } break; case 1: if (++gTasks[taskId].data[11] == 21) { gTasks[taskId].data[11] = 14; gTasks[taskId].data[12]++; } break; case 2: if (++gTasks[taskId].data[10] == 2) { gTasks[taskId].data[10] = 0; gTasks[taskId].data[11]--; SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); if (gTasks[taskId].data[11] == 0) { gTasks[taskId].data[12]++; gTasks[taskId].data[11] = 0; } } break; case 3: GetBattleAnimBg1Data(&animBg); ClearBattleAnimBg(1); ClearBattleAnimBg(2); gTasks[taskId].data[12]++; // fall through case 4: if (!IsContest()) SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); DestroyAnimVisualTask(taskId); break; } } // Orbits a sphere in an ellipse around the mon. // Used by MOVE_HIDDEN_POWER // arg 0: duration // arg 1: initial wave offset static void AnimOrbitFast(struct Sprite *sprite) { sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); sprite->affineAnimPaused = 1; sprite->data[0] = gBattleAnimArgs[0]; sprite->data[1] = gBattleAnimArgs[1]; sprite->data[7] = GetBattlerSpriteSubpriority(gBattleAnimAttacker); sprite->callback = AnimOrbitFast_Step; sprite->callback(sprite); } static void AnimOrbitFast_Step(struct Sprite *sprite) { if (sprite->data[1] >= 64 && sprite->data[1] <= 191) sprite->subpriority = sprite->data[7] + 1; else sprite->subpriority = sprite->data[7] - 1; sprite->x2 = Sin(sprite->data[1], sprite->data[2] >> 8); sprite->y2 = Cos(sprite->data[1], sprite->data[3] >> 8); sprite->data[1] = (sprite->data[1] + 9) & 0xFF; switch (sprite->data[5]) { case 1: sprite->data[2] -= 0x400; sprite->data[3] -= 0x100; if (++sprite->data[4] == sprite->data[0]) { sprite->data[5] = 2; return; } break; case 0: sprite->data[2] += 0x400; sprite->data[3] += 0x100; if (++sprite->data[4] == sprite->data[0]) { sprite->data[4] = 0; sprite->data[5] = 1; } break; } if ((u16)gBattleAnimArgs[7] == 0xFFFF) DestroyAnimSprite(sprite); } // Moves orbs away from the mon, based on where they are in their orbit. // Used in MOVE_HIDDEN_POWER. // arg 0: initial wave offset static void AnimOrbitScatter(struct Sprite *sprite) { sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); sprite->data[0] = Sin(gBattleAnimArgs[0], 10); sprite->data[1] = Cos(gBattleAnimArgs[0], 7); sprite->callback = AnimOrbitScatter_Step; } static void AnimOrbitScatter_Step(struct Sprite *sprite) { sprite->x2 += sprite->data[0]; sprite->y2 += sprite->data[1]; if (sprite->x + sprite->x2 + 16 > ((u32)DISPLAY_WIDTH + 32) || sprite->y + sprite->y2 > DISPLAY_HEIGHT || sprite->y + sprite->y2 < -16) DestroyAnimSprite(sprite); } static void AnimSpitUpOrb_Step(struct Sprite *sprite) { sprite->x2 += sprite->data[0]; sprite->y2 += sprite->data[1]; if (sprite->data[3]++ >= sprite->data[2]) DestroyAnimSprite(sprite); } static void AnimSpitUpOrb(struct Sprite *sprite) { sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); sprite->data[0] = Sin(gBattleAnimArgs[0], 10); sprite->data[1] = Cos(gBattleAnimArgs[0], 7); sprite->data[2] = gBattleAnimArgs[1]; sprite->callback = AnimSpitUpOrb_Step; } static void AnimEyeSparkle_Step(struct Sprite *sprite) { if (sprite->animEnded) DestroyAnimSprite(sprite); } static void AnimEyeSparkle(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, TRUE); sprite->callback = AnimEyeSparkle_Step; } static void AnimAngel(struct Sprite *sprite) { s16 var0; if (!sprite->data[0]) { sprite->x += gBattleAnimArgs[0]; sprite->y += gBattleAnimArgs[1]; } sprite->data[0]++; var0 = (sprite->data[0] * 10) & 0xFF; sprite->x2 = Sin(var0, 80) >> 8; if (sprite->data[0] < 80) sprite->y2 = (sprite->data[0] / 2) + (Cos(var0, 80) >> 8); if (sprite->data[0] > 90) { sprite->data[2]++; sprite->x2 -= sprite->data[2] / 2; } if (sprite->data[0] > 100) DestroyAnimSprite(sprite); } static void AnimPinkHeart_Step(struct Sprite *sprite) { sprite->data[5]++; sprite->x2 = Sin(sprite->data[3], 5); sprite->y2 = sprite->data[5] / 2; sprite->data[3] = (sprite->data[3] + 3) & 0xFF; if (sprite->data[5] > 20) sprite->invisible = sprite->data[5] % 2; if (sprite->data[5] > 30) DestroyAnimSprite(sprite); } static void AnimPinkHeart(struct Sprite *sprite) { if (sprite->data[0] == 0) { sprite->data[1] = gBattleAnimArgs[0]; sprite->data[2] = gBattleAnimArgs[1]; sprite->data[0]++; } else { sprite->data[4] += sprite->data[1]; sprite->x2 = sprite->data[4] >> 8; sprite->y2 = Sin(sprite->data[3], sprite->data[2]); sprite->data[3] = (sprite->data[3] + 3) & 0xFF; if (sprite->data[3] > 70) { sprite->callback = AnimPinkHeart_Step; sprite->x += sprite->x2; sprite->y += sprite->y2; sprite->x2 = 0; sprite->y2 = 0; sprite->data[3] = Random2() % 180; } } } static void AnimDevil(struct Sprite *sprite) { if (sprite->data[3] == 0) { sprite->x += gBattleAnimArgs[0]; sprite->y += gBattleAnimArgs[1]; StartSpriteAnim(sprite, 0); sprite->subpriority = GetBattlerSpriteSubpriority(gBattleAnimTarget) - 1; sprite->data[2] = 1; } sprite->data[0] += sprite->data[2]; sprite->data[1] = (sprite->data[0] * 4) % 256; if (sprite->data[1] < 0) sprite->data[1] = 0; sprite->x2 = Cos(sprite->data[1], 30 - sprite->data[0] / 4); sprite->y2 = Sin(sprite->data[1], 10 - sprite->data[0] / 8); if (sprite->data[1] > 128 && sprite->data[2] > 0) sprite->data[2] = -1; if (sprite->data[1] == 0 && sprite->data[2] < 0) sprite->data[2] = 1; sprite->data[3]++; if (sprite->data[3] < 10 || sprite->data[3] > 80) sprite->invisible = sprite->data[0] % 2; else sprite->invisible = FALSE; if (sprite->data[3] > 90) DestroyAnimSprite(sprite); } static void AnimFurySwipes(struct Sprite *sprite) { if (sprite->data[0] == 0) { sprite->x += gBattleAnimArgs[0]; sprite->y += gBattleAnimArgs[1]; StartSpriteAnim(sprite, gBattleAnimArgs[2]); sprite->data[0]++; } else if (sprite->animEnded) { DestroyAnimSprite(sprite); } } static void AnimMovementWaves(struct Sprite *sprite) { if (!gBattleAnimArgs[2]) { DestroyAnimSprite(sprite); } else { if (!gBattleAnimArgs[0]) { sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); } else { sprite->x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); } if (!gBattleAnimArgs[1]) sprite->x += 32; else sprite->x -= 32; sprite->data[0] = gBattleAnimArgs[2]; sprite->data[1] = gBattleAnimArgs[1]; StartSpriteAnim(sprite, sprite->data[1]); sprite->callback = AnimMovementWaves_Step; } } static void AnimMovementWaves_Step(struct Sprite *sprite) { if (sprite->animEnded) { if (--sprite->data[0]) StartSpriteAnim(sprite, sprite->data[1]); else DestroyAnimSprite(sprite); } } void AnimTask_UproarDistortion(u8 taskId) { u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); PrepareAffineAnimInTaskData(&gTasks[taskId], spriteId, sAffineAnims_UproarDistortion); gTasks[taskId].func = AnimTask_UproarDistortion_Step; } static void AnimTask_UproarDistortion_Step(u8 taskId) { if (!RunAffineAnimFromTaskData(&gTasks[taskId])) DestroyAnimVisualTask(taskId); } static void AnimJaggedMusicNote(struct Sprite *sprite) { int var1; u8 battler = !gBattleAnimArgs[0] ? gBattleAnimAttacker : gBattleAnimTarget; if (GetBattlerSide(battler) == B_SIDE_OPPONENT) gBattleAnimArgs[1] *= -1; sprite->x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2) + gBattleAnimArgs[1]; sprite->y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[2]; sprite->data[0] = 0; sprite->data[1] = (u16)sprite->x << 3; sprite->data[2] = (u16)sprite->y << 3; var1 = gBattleAnimArgs[1] << 3; if (var1 < 0) var1 += 7; sprite->data[3] = var1 >> 3; var1 = gBattleAnimArgs[2] << 3; if (var1 < 0) var1 += 7; sprite->data[4] = var1 >> 3; sprite->oam.tileNum += gBattleAnimArgs[3] * 16; sprite->callback = AnimJaggedMusicNote_Step; } static void AnimJaggedMusicNote_Step(struct Sprite *sprite) { sprite->data[1] += sprite->data[3]; sprite->data[2] += sprite->data[4]; sprite->x = sprite->data[1] >> 3; sprite->y = sprite->data[2] >> 3; if (++sprite->data[0] > 16) DestroyAnimSprite(sprite); } static void AnimPerishSongMusicNote2(struct Sprite *sprite) { if (!sprite->data[0]) { sprite->data[1] = 120 - gBattleAnimArgs[0]; sprite->invisible = TRUE; } if (++sprite->data[0] == sprite->data[1]) SetGrayscaleOrOriginalPalette(sprite->oam.paletteNum + 16, 0); if (sprite->data[0] == sprite->data[1] + 80) DestroyAnimSprite(sprite); } static void AnimPerishSongMusicNote(struct Sprite *sprite) { int index; int var2; if (!sprite->data[0]) { sprite->x = 120; sprite->y = (gBattleAnimArgs[0] + (((u16)gBattleAnimArgs[0]) >> 31)) / 2 - 15; StartSpriteAnim(sprite, gBattleAnimArgs[1]); sprite->data[5] = 120; sprite->data[3] = gBattleAnimArgs[2]; } sprite->data[0]++; sprite->data[1] = (sprite->data[0] + ((u16)sprite->data[0] >> 31)) / 2; index = ((sprite->data[0] * 3) + (u16)sprite->data[3]); var2 = 0xFF; sprite->data[6] = (sprite->data[6] + 10) & 0xFF; index &= var2; sprite->x2 = Cos(index, 100); sprite->y2 = sprite->data[1] + Sin(index, 10) + Cos(sprite->data[6], 4); if (sprite->data[0] > sprite->data[5]) { sprite->callback = AnimPerishSongMusicNote_Step1; sprite->data[0] = 0; SetSpritePrimaryCoordsFromSecondaryCoords(sprite); sprite->data[2] = 5; sprite->data[4] = 0; sprite->data[3] = 0; StartSpriteAffineAnim(sprite, 1); } } static void AnimPerishSongMusicNote_Step1(struct Sprite *sprite) { if (++sprite->data[0] > 10) { sprite->data[0] = 0; sprite->callback = AnimPerishSongMusicNote_Step2; } } static void AnimPerishSongMusicNote_Step2(struct Sprite *sprite) { sprite->data[3] += sprite->data[2]; sprite->y2 = sprite->data[3]; sprite->data[2]++; if (sprite->data[3] > 48 && sprite->data[2] > 0) { sprite->data[2] = sprite->data[4] - 5; sprite->data[4]++; } if (sprite->data[4] > 3) { int var1 = sprite->data[2]; sprite->invisible = var1 - (((s32)(var1 + ((u32)var1 >> 31)) >> 1) << 1); DestroyAnimSprite(sprite); } if (sprite->data[4] == 4) { DestroyAnimSprite(sprite); } } static void AnimGuardRing(struct Sprite *sprite) { if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) { SetAverageBattlerPositions(gBattleAnimAttacker, 0, &sprite->x, &sprite->y); sprite->y += 40; StartSpriteAffineAnim(sprite, 1); } else { sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + 40; } sprite->data[0] = 13; sprite->data[2] = sprite->x; sprite->data[4] = sprite->y - 72; sprite->callback = StartAnimLinearTranslation; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); } void AnimTask_IsFuryCutterHitRight(u8 taskId) { gBattleAnimArgs[ARG_RET_ID] = gAnimDisableStructPtr->furyCutterCounter & 1; DestroyAnimVisualTask(taskId); } void AnimTask_GetFuryCutterHitCount(u8 taskId) { gBattleAnimArgs[ARG_RET_ID] = gAnimDisableStructPtr->furyCutterCounter; DestroyAnimVisualTask(taskId); }