tumbledemerald-legacy/src/battle_anim_effects_3.c

5472 lines
153 KiB
C
Executable File

#include "global.h"
#include "malloc.h"
#include "battle.h"
#include "battle_anim.h"
#include "bg.h"
#include "contest.h"
#include "data.h"
#include "decompress.h"
#include "dma3.h"
#include "gpu_regs.h"
#include "graphics.h"
#include "palette.h"
#include "pokemon_icon.h"
#include "random.h"
#include "scanline_effect.h"
#include "sound.h"
#include "sprite.h"
#include "task.h"
#include "trig.h"
#include "util.h"
#include "constants/battle_anim.h"
#include "constants/rgb.h"
#include "constants/songs.h"
#include "constants/weather.h"
extern const struct SpriteTemplate gThoughtBubbleSpriteTemplate;
static void AnimBlackSmoke(struct Sprite *);
static void AnimBlackSmoke_Step(struct Sprite *);
static void AnimWhiteHalo(struct Sprite *);
static void AnimWhiteHalo_Step1(struct Sprite *);
static void AnimWhiteHalo_Step2(struct Sprite *);
static void AnimTealAlert(struct Sprite *);
static void AnimMeanLookEye(struct Sprite *);
static void AnimMeanLookEye_Step1(struct Sprite *);
static void AnimMeanLookEye_Step2(struct Sprite *);
static void AnimMeanLookEye_Step3(struct Sprite *);
static void AnimMeanLookEye_Step4(struct Sprite *);
static void AnimSpikes(struct Sprite *);
static void AnimSpikes_Step1(struct Sprite *);
static void AnimSpikes_Step2(struct Sprite *);
static void AnimLeer(struct Sprite *);
static void AnimLetterZ(struct Sprite *);
static void AnimFang(struct Sprite *);
static void AnimSpotlight(struct Sprite *);
static void AnimSpotlight_Step1(struct Sprite *);
static void AnimSpotlight_Step2(struct Sprite *);
static void AnimClappingHand(struct Sprite *);
static void AnimClappingHand_Step(struct Sprite *);
static void AnimClappingHand2(struct Sprite *);
static void AnimRapidSpin(struct Sprite *);
static void AnimRapidSpin_Step(struct Sprite *);
static void AnimTriAttackTriangle(struct Sprite *);
static void AnimBatonPassPokeball(struct Sprite *);
static void AnimWishStar(struct Sprite *);
static void AnimWishStar_Step(struct Sprite *);
static void AnimMiniTwinklingStar(struct Sprite *);
static void AnimMiniTwinklingStar_Step(struct Sprite *);
static void AnimSwallowBlueOrb(struct Sprite *);
static void AnimGreenStar(struct Sprite *);
static void AnimGreenStar_Step1(struct Sprite *);
static void AnimGreenStar_Step2(struct Sprite *);
static void AnimGreenStar_Callback(struct Sprite *);
static void AnimWeakFrustrationAngerMark(struct Sprite *);
static void AnimSweetScentPetal(struct Sprite *);
static void AnimSweetScentPetal_Step(struct Sprite *);
static void AnimPainSplitProjectile(struct Sprite *);
static void AnimFlatterConfetti(struct Sprite *);
static void AnimFlatterConfetti_Step(struct Sprite *);
static void AnimFlatterSpotlight(struct Sprite *);
static void AnimFlatterSpotlight_Step(struct Sprite *);
static void AnimReversalOrb(struct Sprite *);
static void AnimReversalOrb_Step(struct Sprite *);
static void AnimYawnCloud(struct Sprite *);
static void AnimYawnCloud_Step(struct Sprite *);
static void AnimSmokeBallEscapeCloud(struct Sprite *);
static void AnimFacadeSweatDrop(struct Sprite *);
static void AnimRoarNoiseLine(struct Sprite *);
static void AnimRoarNoiseLine_Step(struct Sprite *);
static void AnimGlareEyeDot(struct Sprite *);
static void AnimAssistPawprint(struct Sprite *);
static void AnimSmellingSaltsHand(struct Sprite *);
static void AnimSmellingSaltsHand_Step(struct Sprite *);
static void AnimSmellingSaltExclamation(struct Sprite *);
static void AnimSmellingSaltExclamation_Step(struct Sprite *);
static void AnimHelpingHandClap(struct Sprite *);
static void AnimHelpingHandClap_Step(struct Sprite *);
static void AnimForesightMagnifyingGlass(struct Sprite *);
static void AnimForesightMagnifyingGlass_Step(struct Sprite *);
static void AnimMeteorMashStar(struct Sprite *);
static void AnimMeteorMashStar_Step(struct Sprite *sprite);
static void AnimBlockX(struct Sprite *);
static void AnimBlockX_Step(struct Sprite *);
static void AnimUnusedItemBagSteal(struct Sprite *);
static void AnimKnockOffStrike(struct Sprite *);
static void AnimKnockOffStrike_Step(struct Sprite *sprite);
static void AnimRecycle(struct Sprite *);
static void AnimRecycle_Step(struct Sprite *);
static void SetPsychicBackground_Step(u8);
static void FadeScreenToWhite_Step(u8);
static void RapinSpinMonElevation_Step(u8);
static void TormentAttacker_Step(u8);
static void TormentAttacker_Callback(struct Sprite *);
static void AnimTask_RockMonBackAndForth_Step(u8);
static void AnimTask_FlailMovement_Step(u8);
static void AnimTask_RolePlaySilhouette_Step1(u8);
static void AnimTask_RolePlaySilhouette_Step2(u8);
static void AnimTask_AcidArmor_Step(u8);
static void AnimTask_DeepInhale_Step(u8);
static void AnimTask_SquishAndSweatDroplets_Step(u8);
static void CreateSweatDroplets(u8, bool8);
static void AnimTask_FacadeColorBlend_Step(u8);
static void AnimTask_GlareEyeDots_Step(u8);
static void GetGlareEyeDotCoords(s16, s16, s16, s16, u8, u8, s16 *, s16 *);
static void AnimTask_BarrageBall_Step(u8);
static void AnimTask_SmellingSaltsSquish_Step(u8);
static void AnimTask_HelpingHandAttackerMovement_Step(u8);
static void AnimTask_MonToSubstituteDoll(u8);
static void AnimTask_OdorSleuthMovementWaitFinish(u8);
static void MoveOdorSleuthClone(struct Sprite *);
static void AnimTask_TeeterDanceMovement_Step(u8);
static void AnimTask_SlackOffSquish_Step(u8);
const union AnimCmd gScratchAnimCmds[] =
{
ANIMCMD_FRAME(0, 4),
ANIMCMD_FRAME(16, 4),
ANIMCMD_FRAME(32, 4),
ANIMCMD_FRAME(48, 4),
ANIMCMD_FRAME(64, 4),
ANIMCMD_END,
};
const union AnimCmd *const gScratchAnimTable[] =
{
gScratchAnimCmds,
};
const struct SpriteTemplate gScratchSpriteTemplate =
{
.tileTag = ANIM_TAG_SCRATCH,
.paletteTag = ANIM_TAG_SCRATCH,
.oam = &gOamData_AffineOff_ObjBlend_32x32,
.anims = gScratchAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimSpriteOnMonPos,
};
const struct SpriteTemplate gBlackSmokeSpriteTemplate =
{
.tileTag = ANIM_TAG_BLACK_SMOKE,
.paletteTag = ANIM_TAG_BLACK_SMOKE,
.oam = &gOamData_AffineOff_ObjNormal_32x16,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimBlackSmoke,
};
const struct SpriteTemplate gBlackBallSpriteTemplate =
{
.tileTag = ANIM_TAG_BLACK_BALL,
.paletteTag = ANIM_TAG_BLACK_BALL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimThrowProjectile,
};
const union AnimCmd gOpeningEyeAnimCmds[] =
{
ANIMCMD_FRAME(0, 40),
ANIMCMD_FRAME(16, 8),
ANIMCMD_FRAME(32, 40),
ANIMCMD_END,
};
const union AnimCmd *const gOpeningEyeAnimTable[] =
{
gOpeningEyeAnimCmds,
};
const struct SpriteTemplate gOpeningEyeSpriteTemplate =
{
.tileTag = ANIM_TAG_OPENING_EYE,
.paletteTag = ANIM_TAG_OPENING_EYE,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gOpeningEyeAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimSpriteOnMonPos,
};
const struct SpriteTemplate gWhiteHaloSpriteTemplate =
{
.tileTag = ANIM_TAG_ROUND_WHITE_HALO,
.paletteTag = ANIM_TAG_ROUND_WHITE_HALO,
.oam = &gOamData_AffineOff_ObjBlend_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimWhiteHalo,
};
const struct SpriteTemplate gTealAlertSpriteTemplate =
{
.tileTag = ANIM_TAG_TEAL_ALERT,
.paletteTag = ANIM_TAG_TEAL_ALERT,
.oam = &gOamData_AffineNormal_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimTealAlert,
};
const union AffineAnimCmd gMeanLookEyeAffineAnimCmds1[] =
{
AFFINEANIMCMD_FRAME(0x180, 0x180, 0, 0),
AFFINEANIMCMD_FRAME(-0x20, 0x18, 0, 5),
AFFINEANIMCMD_FRAME(0x18, -0x20, 0, 5),
AFFINEANIMCMD_JUMP(1),
};
const union AffineAnimCmd gMeanLookEyeAffineAnimCmds2[] =
{
AFFINEANIMCMD_FRAME(0x30, 0x30, 0, 0),
AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 6),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd *const gMeanLookEyeAffineAnimTable[] =
{
gMeanLookEyeAffineAnimCmds1,
gMeanLookEyeAffineAnimCmds2,
};
const struct SpriteTemplate gMeanLookEyeSpriteTemplate =
{
.tileTag = ANIM_TAG_EYE,
.paletteTag = ANIM_TAG_EYE,
.oam = &gOamData_AffineDouble_ObjBlend_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gMeanLookEyeAffineAnimTable,
.callback = AnimMeanLookEye,
};
const struct SpriteTemplate gSpikesSpriteTemplate =
{
.tileTag = ANIM_TAG_SPIKES,
.paletteTag = ANIM_TAG_SPIKES,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimSpikes,
};
const union AnimCmd gLeerAnimCmds[] =
{
ANIMCMD_FRAME(0, 3),
ANIMCMD_FRAME(16, 3),
ANIMCMD_FRAME(32, 3),
ANIMCMD_FRAME(48, 3),
ANIMCMD_FRAME(64, 3),
ANIMCMD_END,
};
const union AnimCmd *const gLeerAnimTable[] =
{
gLeerAnimCmds,
};
const struct SpriteTemplate gLeerSpriteTemplate =
{
.tileTag = ANIM_TAG_LEER,
.paletteTag = ANIM_TAG_LEER,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gLeerAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimLeer,
};
const union AnimCmd gLetterZAnimCmds[] =
{
ANIMCMD_FRAME(0, 3),
ANIMCMD_END,
};
const union AnimCmd *const gLetterZAnimTable[] =
{
gLetterZAnimCmds,
};
const union AffineAnimCmd gLetterZAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(-7, -7, -3, 16),
AFFINEANIMCMD_FRAME(7, 7, 3, 16),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd *const gLetterZAffineAnimTable[] =
{
gLetterZAffineAnimCmds,
};
const struct SpriteTemplate gLetterZSpriteTemplate =
{
.tileTag = ANIM_TAG_LETTER_Z,
.paletteTag = ANIM_TAG_LETTER_Z,
.oam = &gOamData_AffineNormal_ObjNormal_32x32,
.anims = gLetterZAnimTable,
.images = NULL,
.affineAnims = gLetterZAffineAnimTable,
.callback = AnimLetterZ,
};
const union AnimCmd gFangAnimCmds[] =
{
ANIMCMD_FRAME(0, 8),
ANIMCMD_FRAME(16, 16),
ANIMCMD_FRAME(32, 4),
ANIMCMD_FRAME(48, 4),
ANIMCMD_END,
};
const union AnimCmd *const gFangAnimTable[] =
{
gFangAnimCmds,
};
const union AffineAnimCmd gFangAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0),
AFFINEANIMCMD_FRAME(-0x20, -0x20, 0, 8),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd *const gFangAffineAnimTable[] =
{
gFangAffineAnimCmds,
};
const struct SpriteTemplate gFangSpriteTemplate =
{
.tileTag = ANIM_TAG_FANG_ATTACK,
.paletteTag = ANIM_TAG_FANG_ATTACK,
.oam = &gOamData_AffineDouble_ObjNormal_32x32,
.anims = gFangAnimTable,
.images = NULL,
.affineAnims = gFangAffineAnimTable,
.callback = AnimFang,
};
const union AffineAnimCmd gSpotlightAffineAnimCmds1[] =
{
AFFINEANIMCMD_FRAME(0x0, 0x180, 0, 0),
AFFINEANIMCMD_FRAME(0x10, 0x0, 0, 20),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd gSpotlightAffineAnimCmds2[] =
{
AFFINEANIMCMD_FRAME(0x140, 0x180, 0, 0),
AFFINEANIMCMD_FRAME(-0x10, 0x0, 0, 19),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd *const gSpotlightAffineAnimTable[] =
{
gSpotlightAffineAnimCmds1,
gSpotlightAffineAnimCmds2,
};
const struct SpriteTemplate gSpotlightSpriteTemplate =
{
.tileTag = ANIM_TAG_SPOTLIGHT,
.paletteTag = ANIM_TAG_SPOTLIGHT,
.oam = &gOamData_AffineDouble_ObjNormal_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gSpotlightAffineAnimTable,
.callback = AnimSpotlight,
};
const struct SpriteTemplate gClappingHandSpriteTemplate =
{
.tileTag = ANIM_TAG_TAG_HAND,
.paletteTag = ANIM_TAG_TAG_HAND,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimClappingHand,
};
const struct SpriteTemplate gClappingHand2SpriteTemplate =
{
.tileTag = ANIM_TAG_TAG_HAND,
.paletteTag = ANIM_TAG_TAG_HAND,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimClappingHand2,
};
const union AnimCmd gRapidSpinAnimCmds[] =
{
ANIMCMD_FRAME(0, 2),
ANIMCMD_FRAME(8, 2),
ANIMCMD_FRAME(16, 2),
ANIMCMD_JUMP(0),
};
const union AnimCmd *const gRapidSpinAnimTable[] =
{
gRapidSpinAnimCmds,
};
const struct SpriteTemplate gRapidSpinSpriteTemplate =
{
.tileTag = ANIM_TAG_RAPID_SPIN,
.paletteTag = ANIM_TAG_RAPID_SPIN,
.oam = &gOamData_AffineOff_ObjNormal_32x16,
.anims = gRapidSpinAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimRapidSpin,
};
static const union AffineAnimCmd sAffineAnims_Torment[] =
{
AFFINEANIMCMD_FRAME(-12, 8, 0, 4),
AFFINEANIMCMD_FRAME(20, -20, 0, 4),
AFFINEANIMCMD_FRAME(-8, 12, 0, 4),
AFFINEANIMCMD_END,
};
const union AnimCmd gTriAttackTriangleAnimCmds[] =
{
ANIMCMD_FRAME(0, 8),
ANIMCMD_END,
};
const union AnimCmd *const gTriAttackTriangleAnimTable[] =
{
gTriAttackTriangleAnimCmds,
};
const union AffineAnimCmd gTriAttackTriangleAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(0, 0, 5, 40),
AFFINEANIMCMD_FRAME(0, 0, 10, 10),
AFFINEANIMCMD_FRAME(0, 0, 15, 10),
AFFINEANIMCMD_FRAME(0, 0, 20, 40),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd *const gTriAttackTriangleAffineAnimTable[] =
{
gTriAttackTriangleAffineAnimCmds,
};
const struct SpriteTemplate gTriAttackTriangleSpriteTemplate =
{
.tileTag = ANIM_TAG_TRI_ATTACK_TRIANGLE,
.paletteTag = ANIM_TAG_TRI_ATTACK_TRIANGLE,
.oam = &gOamData_AffineDouble_ObjNormal_64x64,
.anims = gTriAttackTriangleAnimTable,
.images = NULL,
.affineAnims = gTriAttackTriangleAffineAnimTable,
.callback = AnimTriAttackTriangle,
};
const union AnimCmd gEclipsingOrbAnimCmds[] =
{
ANIMCMD_FRAME(0, 3),
ANIMCMD_FRAME(16, 3),
ANIMCMD_FRAME(32, 3),
ANIMCMD_FRAME(48, 3),
ANIMCMD_FRAME(32, 3, .hFlip = TRUE),
ANIMCMD_FRAME(16, 3, .hFlip = TRUE),
ANIMCMD_FRAME(0, 3, .hFlip = TRUE),
ANIMCMD_LOOP(1),
ANIMCMD_END,
};
const union AnimCmd *const gEclipsingOrbAnimTable[] =
{
gEclipsingOrbAnimCmds,
};
const struct SpriteTemplate gEclipsingOrbSpriteTemplate =
{
.tileTag = ANIM_TAG_ECLIPSING_ORB,
.paletteTag = ANIM_TAG_ECLIPSING_ORB,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gEclipsingOrbAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimSpriteOnMonPos,
};
const union AffineAnimCmd DefenseCurlDeformMonAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(-12, 20, 0, 8),
AFFINEANIMCMD_FRAME(12, -20, 0, 8),
AFFINEANIMCMD_LOOP(2),
AFFINEANIMCMD_END,
};
const struct SpriteTemplate gBatonPassPokeballSpriteTemplate =
{
.tileTag = ANIM_TAG_POKEBALL,
.paletteTag = ANIM_TAG_POKEBALL,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimBatonPassPokeball,
};
const struct SpriteTemplate gWishStarSpriteTemplate =
{
.tileTag = ANIM_TAG_GOLD_STARS,
.paletteTag = ANIM_TAG_GOLD_STARS,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimWishStar,
};
const struct SpriteTemplate gMiniTwinklingStarSpriteTemplate =
{
.tileTag = ANIM_TAG_GOLD_STARS,
.paletteTag = ANIM_TAG_GOLD_STARS,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimMiniTwinklingStar,
};
const union AffineAnimCmd gStockpileDeformMonAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(8, -8, 0, 12),
AFFINEANIMCMD_FRAME(-16, 16, 0, 12),
AFFINEANIMCMD_FRAME(8, -8, 0, 12),
AFFINEANIMCMD_LOOP(1),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd gSpitUpDeformMonAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(0, 6, 0, 20),
AFFINEANIMCMD_FRAME(0, 0, 0, 20),
AFFINEANIMCMD_FRAME(0, -18, 0, 6),
AFFINEANIMCMD_FRAME(-18, -18, 0, 3),
AFFINEANIMCMD_FRAME(0, 0, 0, 15),
AFFINEANIMCMD_FRAME(4, 4, 0, 13),
AFFINEANIMCMD_END,
};
const struct SpriteTemplate gSwallowBlueOrbSpriteTemplate =
{
.tileTag = ANIM_TAG_BLUE_ORB,
.paletteTag = ANIM_TAG_BLUE_ORB,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimSwallowBlueOrb,
};
const union AffineAnimCmd gSwallowDeformMonAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(0, 6, 0, 20),
AFFINEANIMCMD_FRAME(0, 0, 0, 20),
AFFINEANIMCMD_FRAME(7, -30, 0, 6),
AFFINEANIMCMD_FRAME(0, 0, 0, 20),
AFFINEANIMCMD_FRAME(-2, 3, 0, 20),
AFFINEANIMCMD_END,
};
const s8 gMorningSunLightBeamCoordsTable[] =
{
0xE8,
0x18,
0xFC,
0x00,
};
const union AnimCmd gGreenStarAnimCmds1[] =
{
ANIMCMD_FRAME(0, 6),
ANIMCMD_FRAME(4, 6),
ANIMCMD_JUMP(0),
};
const union AnimCmd gGreenStarAnimCmds2[] =
{
ANIMCMD_FRAME(8, 6),
ANIMCMD_END,
};
const union AnimCmd gGreenStarAnimCmds3[] =
{
ANIMCMD_FRAME(12, 6),
ANIMCMD_END,
};
const union AnimCmd *const gGreenStarAnimTable[] =
{
gGreenStarAnimCmds1,
gGreenStarAnimCmds2,
gGreenStarAnimCmds3,
};
const struct SpriteTemplate gGreenStarSpriteTemplate =
{
.tileTag = ANIM_TAG_GREEN_STAR,
.paletteTag = ANIM_TAG_GREEN_STAR,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = gGreenStarAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimGreenStar,
};
const s8 gDoomDesireLightBeamCoordTable[] =
{
0x78,
0x50,
0x28,
0x00,
};
const u8 gDoomDesireLightBeamDelayTable[] =
{
0,
0,
0,
0,
50,
};
const union AffineAnimCmd gStrongFrustrationAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(0, -15, 0, 7),
AFFINEANIMCMD_FRAME(0, 15, 0, 7),
AFFINEANIMCMD_LOOP(2),
AFFINEANIMCMD_END,
};
const struct SpriteTemplate gWeakFrustrationAngerMarkSpriteTemplate =
{
.tileTag = ANIM_TAG_ANGER,
.paletteTag = ANIM_TAG_ANGER,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimWeakFrustrationAngerMark,
};
const union AnimCmd gSweetScentPetalAnimCmds1[] =
{
ANIMCMD_FRAME(0, 8),
ANIMCMD_FRAME(1, 8),
ANIMCMD_FRAME(2, 8),
ANIMCMD_FRAME(3, 8),
ANIMCMD_FRAME(3, 8, .vFlip = TRUE),
ANIMCMD_FRAME(2, 8, .vFlip = TRUE),
ANIMCMD_FRAME(0, 8, .vFlip = TRUE),
ANIMCMD_FRAME(1, 8, .vFlip = TRUE),
ANIMCMD_JUMP(0),
};
const union AnimCmd gSweetScentPetalAnimCmds2[] =
{
ANIMCMD_FRAME(0, 8, .hFlip = TRUE),
ANIMCMD_FRAME(1, 8, .hFlip = TRUE),
ANIMCMD_FRAME(2, 8, .hFlip = TRUE),
ANIMCMD_FRAME(3, 8, .hFlip = TRUE),
ANIMCMD_FRAME(3, 8, .vFlip = TRUE, .hFlip = TRUE),
ANIMCMD_FRAME(2, 8, .vFlip = TRUE, .hFlip = TRUE),
ANIMCMD_FRAME(0, 8, .vFlip = TRUE, .hFlip = TRUE),
ANIMCMD_FRAME(1, 8, .vFlip = TRUE, .hFlip = TRUE),
ANIMCMD_JUMP(0),
};
const union AnimCmd gSweetScentPetalAnimCmds3[] =
{
ANIMCMD_FRAME(0, 8),
ANIMCMD_END,
};
const union AnimCmd *const gSweetScentPetalAnimCmdTable[] =
{
gSweetScentPetalAnimCmds1,
gSweetScentPetalAnimCmds2,
gSweetScentPetalAnimCmds3,
};
const struct SpriteTemplate gSweetScentPetalSpriteTemplate =
{
.tileTag = ANIM_TAG_PINK_PETAL,
.paletteTag = ANIM_TAG_PINK_PETAL,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = gSweetScentPetalAnimCmdTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimSweetScentPetal,
};
static const u16 sUnusedPalette[] = INCBIN_U16("graphics/battle_anims/unused/unknown.gbapal");
const union AnimCmd gPainSplitAnimCmds[] =
{
ANIMCMD_FRAME(0, 5),
ANIMCMD_FRAME(4, 9),
ANIMCMD_FRAME(8, 5),
ANIMCMD_END,
};
const union AnimCmd *const gPainSplitAnimCmdTable[] =
{
gPainSplitAnimCmds,
};
const struct SpriteTemplate gPainSplitProjectileSpriteTemplate =
{
.tileTag = ANIM_TAG_PAIN_SPLIT,
.paletteTag = ANIM_TAG_PAIN_SPLIT,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = gPainSplitAnimCmdTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimPainSplitProjectile,
};
const struct SpriteTemplate gFlatterConfettiSpriteTemplate =
{
.tileTag = ANIM_TAG_CONFETTI,
.paletteTag = ANIM_TAG_CONFETTI,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimFlatterConfetti,
};
const struct SpriteTemplate gFlatterSpotlightSpriteTemplate =
{
.tileTag = ANIM_TAG_SPOTLIGHT,
.paletteTag = ANIM_TAG_SPOTLIGHT,
.oam = &gOamData_AffineDouble_ObjNormal_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gSpotlightAffineAnimTable,
.callback = AnimFlatterSpotlight,
};
const struct SpriteTemplate gReversalOrbSpriteTemplate =
{
.tileTag = ANIM_TAG_BLUE_ORB,
.paletteTag = ANIM_TAG_BLUE_ORB,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimReversalOrb,
};
const union AffineAnimCmd gDeepInhaleAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(16, 0, 0, 4),
AFFINEANIMCMD_FRAME(0, -3, 0, 16),
AFFINEANIMCMD_FRAME(4, 0, 0, 4),
AFFINEANIMCMD_FRAME(0, 0, 0, 24),
AFFINEANIMCMD_FRAME(-5, 3, 0, 16),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd gYawnCloudAffineAnimCmds1[] =
{
AFFINEANIMCMD_FRAME(0x80, 0x80, 0, 0),
AFFINEANIMCMD_FRAME(-8, -8, 0, 8),
AFFINEANIMCMD_FRAME(8, 8, 0, 8),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd gYawnCloudAffineAnimCmds2[] =
{
AFFINEANIMCMD_FRAME(0xC0, 0xC0, 0, 0),
AFFINEANIMCMD_FRAME(8, 8, 0, 8),
AFFINEANIMCMD_FRAME(-8, -8, 0, 8),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd gYawnCloudAffineAnimCmds3[] =
{
AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
AFFINEANIMCMD_FRAME(8, 8, 0, 8),
AFFINEANIMCMD_FRAME(-8, -8, 0, 8),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd *const gYawnCloudAffineAnimTable[] =
{
gYawnCloudAffineAnimCmds1,
gYawnCloudAffineAnimCmds2,
gYawnCloudAffineAnimCmds3,
};
const struct SpriteTemplate gYawnCloudSpriteTemplate =
{
.tileTag = ANIM_TAG_PINK_CLOUD,
.paletteTag = ANIM_TAG_PINK_CLOUD,
.oam = &gOamData_AffineNormal_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gYawnCloudAffineAnimTable,
.callback = AnimYawnCloud,
};
const union AffineAnimCmd gSmokeBallEscapeCloudAffineAnimCmds1[] =
{
AFFINEANIMCMD_FRAME(0x80, 0x80, 0, 0),
AFFINEANIMCMD_FRAME(-4, -6, 0, 16),
AFFINEANIMCMD_FRAME(4, 6, 0, 16),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd gSmokeBallEscapeCloudAffineAnimCmds2[] =
{
AFFINEANIMCMD_FRAME(0xC0, 0xC0, 0, 0),
AFFINEANIMCMD_FRAME(4, 6, 0, 16),
AFFINEANIMCMD_FRAME(-4, -6, 0, 16),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd gSmokeBallEscapeCloudAffineAnimCmds3[] =
{
AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
AFFINEANIMCMD_FRAME(4, 6, 0, 16),
AFFINEANIMCMD_FRAME(-4, -6, 0, 16),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd gSmokeBallEscapeCloudAffineAnimCmds4[] =
{
AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
AFFINEANIMCMD_FRAME(8, 10, 0, 30),
AFFINEANIMCMD_FRAME(-8, -10, 0, 16),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd *const gSmokeBallEscapeCloudAffineAnimTable[] =
{
gSmokeBallEscapeCloudAffineAnimCmds1,
gSmokeBallEscapeCloudAffineAnimCmds2,
gSmokeBallEscapeCloudAffineAnimCmds3,
gSmokeBallEscapeCloudAffineAnimCmds4,
};
const struct SpriteTemplate gSmokeBallEscapeCloudSpriteTemplate =
{
.tileTag = ANIM_TAG_PINK_CLOUD,
.paletteTag = ANIM_TAG_PINK_CLOUD,
.oam = &gOamData_AffineDouble_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gSmokeBallEscapeCloudAffineAnimTable,
.callback = AnimSmokeBallEscapeCloud,
};
const union AffineAnimCmd gFacadeSquishAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(-16, 16, 0, 6),
AFFINEANIMCMD_FRAME(16, -16, 0, 12),
AFFINEANIMCMD_FRAME(-16, 16, 0, 6),
AFFINEANIMCMD_END,
};
const struct SpriteTemplate gFacadeSweatDropSpriteTemplate =
{
.tileTag = ANIM_TAG_SWEAT_DROP,
.paletteTag = ANIM_TAG_SWEAT_DROP,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimFacadeSweatDrop,
};
const u16 gFacadeBlendColors[] = {
RGB(28, 25, 1),
RGB(28, 21, 5),
RGB(27, 18, 8),
RGB(27, 14, 11),
RGB(26, 10, 15),
RGB(26, 7, 18),
RGB(25, 3, 21),
RGB(25, 0, 25),
RGB(25, 0, 23),
RGB(25, 0, 20),
RGB(25, 0, 16),
RGB(25, 0, 13),
RGB(26, 0, 10),
RGB(26, 0, 6),
RGB(26, 0, 3),
RGB(27, 0, 0),
RGB(27, 1, 0),
RGB(27, 5, 0),
RGB(27, 9, 0),
RGB(27, 12, 0),
RGB(28, 16, 0),
RGB(28, 19, 0),
RGB(28, 23, 0),
RGB(29, 27, 0),
};
const union AnimCmd gRoarNoiseLineAnimCmds1[] =
{
ANIMCMD_FRAME(0, 3),
ANIMCMD_FRAME(16, 3),
ANIMCMD_JUMP(0),
};
const union AnimCmd gRoarNoiseLineAnimCmds2[] =
{
ANIMCMD_FRAME(32, 3),
ANIMCMD_FRAME(48, 3),
ANIMCMD_JUMP(0),
};
const union AnimCmd *const gRoarNoiseLineAnimTable[] =
{
gRoarNoiseLineAnimCmds1,
gRoarNoiseLineAnimCmds2,
};
const struct SpriteTemplate gRoarNoiseLineSpriteTemplate =
{
.tileTag = ANIM_TAG_NOISE_LINE,
.paletteTag = ANIM_TAG_NOISE_LINE,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gRoarNoiseLineAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimRoarNoiseLine,
};
const struct SpriteTemplate gGlareEyeDotSpriteTemplate =
{
.tileTag = ANIM_TAG_SMALL_RED_EYE,
.paletteTag = ANIM_TAG_SMALL_RED_EYE,
.oam = &gOamData_AffineOff_ObjNormal_8x8,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimGlareEyeDot,
};
const struct SpriteTemplate gAssistPawprintSpriteTemplate =
{
.tileTag = ANIM_TAG_PAW_PRINT,
.paletteTag = ANIM_TAG_PAW_PRINT,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimAssistPawprint,
};
const union AffineAnimCmd gBarrageBallAffineAnimCmds1[] =
{
AFFINEANIMCMD_FRAME(0, 0, -4, 24),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd gBarrageBallAffineAnimCmds2[] =
{
AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0),
AFFINEANIMCMD_FRAME(0, 0, 4, 24),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd *const gBarrageBallAffineAnimTable[] =
{
gBarrageBallAffineAnimCmds1,
gBarrageBallAffineAnimCmds2,
};
const struct SpriteTemplate gBarrageBallSpriteTemplate =
{
.tileTag = ANIM_TAG_RED_BALL,
.paletteTag = ANIM_TAG_RED_BALL,
.oam = &gOamData_AffineNormal_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gBarrageBallAffineAnimTable,
.callback = SpriteCallbackDummy,
};
const struct SpriteTemplate gSmellingSaltsHandSpriteTemplate =
{
.tileTag = ANIM_TAG_TAG_HAND,
.paletteTag = ANIM_TAG_TAG_HAND,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimSmellingSaltsHand,
};
const union AffineAnimCmd gSmellingSaltsSquishAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(0, -16, 0, 6),
AFFINEANIMCMD_FRAME(0, 16, 0, 6),
AFFINEANIMCMD_END,
};
const struct SpriteTemplate gSmellingSaltExclamationSpriteTemplate =
{
.tileTag = ANIM_TAG_SMELLINGSALT_EFFECT,
.paletteTag = ANIM_TAG_SMELLINGSALT_EFFECT,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimSmellingSaltExclamation,
};
const struct SpriteTemplate gHelpingHandClapSpriteTemplate =
{
.tileTag = ANIM_TAG_TAG_HAND,
.paletteTag = ANIM_TAG_TAG_HAND,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimHelpingHandClap,
};
const struct SpriteTemplate gForesightMagnifyingGlassSpriteTemplate =
{
.tileTag = ANIM_TAG_MAGNIFYING_GLASS,
.paletteTag = ANIM_TAG_MAGNIFYING_GLASS,
.oam = &gOamData_AffineOff_ObjBlend_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimForesightMagnifyingGlass,
};
const struct SpriteTemplate gMeteorMashStarSpriteTemplate =
{
.tileTag = ANIM_TAG_GOLD_STARS,
.paletteTag = ANIM_TAG_GOLD_STARS,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimMeteorMashStar,
};
static const struct SpriteTemplate sUnusedStarBurstSpriteTemplate =
{
.tileTag = ANIM_TAG_GOLD_STARS,
.paletteTag = ANIM_TAG_GOLD_STARS,
.oam = &gOamData_AffineOff_ObjNormal_16x16,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimParticleBurst,
};
const struct SpriteTemplate gBlockXSpriteTemplate =
{
.tileTag = ANIM_TAG_X_SIGN,
.paletteTag = ANIM_TAG_X_SIGN,
.oam = &gOamData_AffineOff_ObjNormal_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimBlockX,
};
static const struct SpriteTemplate sUnusedItemBagStealSpriteTemplate =
{
.tileTag = ANIM_TAG_ITEM_BAG,
.paletteTag = ANIM_TAG_ITEM_BAG,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimUnusedItemBagSteal,
};
const union AnimCmd gKnockOffStrikeAnimCmds[] =
{
ANIMCMD_FRAME(0, 4),
ANIMCMD_FRAME(64, 4),
ANIMCMD_END,
};
const union AnimCmd *const gKnockOffStrikeAnimTable[] =
{
gKnockOffStrikeAnimCmds,
};
const union AffineAnimCmd gKnockOffStrikeAffineanimCmds1[] =
{
AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
AFFINEANIMCMD_FRAME(0, 0, -4, 8),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd gKnockOffStrikeAffineanimCmds2[] =
{
AFFINEANIMCMD_FRAME(-0x100, 0x100, 0, 0),
AFFINEANIMCMD_FRAME(0, 0, 4, 8),
AFFINEANIMCMD_END,
};
const union AffineAnimCmd *const gKnockOffStrikeAffineAnimTable[] =
{
gKnockOffStrikeAffineanimCmds1,
gKnockOffStrikeAffineanimCmds2,
};
const struct SpriteTemplate gKnockOffStrikeSpriteTemplate =
{
.tileTag = ANIM_TAG_SLAM_HIT_2,
.paletteTag = ANIM_TAG_SLAM_HIT_2,
.oam = &gOamData_AffineNormal_ObjNormal_64x64,
.anims = gKnockOffStrikeAnimTable,
.images = NULL,
.affineAnims = gKnockOffStrikeAffineAnimTable,
.callback = AnimKnockOffStrike,
};
const union AffineAnimCmd gRecycleSpriteAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(0, 0, -4, 64),
AFFINEANIMCMD_JUMP(0),
};
const union AffineAnimCmd *const gRecycleSpriteAffineAnimTable[] =
{
gRecycleSpriteAffineAnimCmds,
};
const struct SpriteTemplate gRecycleSpriteTemplate =
{
.tileTag = ANIM_TAG_RECYCLE,
.paletteTag = ANIM_TAG_RECYCLE,
.oam = &gOamData_AffineNormal_ObjBlend_64x64,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gRecycleSpriteAffineAnimTable,
.callback = AnimRecycle,
};
const union AffineAnimCmd gSlackOffSquishAffineAnimCmds[] =
{
AFFINEANIMCMD_FRAME(0, 16, 0, 4),
AFFINEANIMCMD_FRAME(-2, 0, 0, 8),
AFFINEANIMCMD_FRAME(0, 4, 0, 4),
AFFINEANIMCMD_FRAME(0, 0, 0, 24),
AFFINEANIMCMD_FRAME(1, -5, 0, 16),
AFFINEANIMCMD_END,
};
static void AnimBlackSmoke(struct Sprite *sprite)
{
sprite->x += gBattleAnimArgs[0];
sprite->y += gBattleAnimArgs[1];
if (!gBattleAnimArgs[3])
sprite->data[0] = gBattleAnimArgs[2];
else
sprite->data[0] = -gBattleAnimArgs[2];
sprite->data[1] = gBattleAnimArgs[4];
sprite->callback = AnimBlackSmoke_Step;
}
static void AnimBlackSmoke_Step(struct Sprite *sprite)
{
if (sprite->data[1] > 0)
{
sprite->x2 = sprite->data[2] >> 8;
sprite->data[2] += sprite->data[0];
sprite->invisible ^= 1;
sprite->data[1]--;
}
else
{
DestroyAnimSprite(sprite);
}
}
void AnimTask_SmokescreenImpact(u8 taskId)
{
SmokescreenImpact(
GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + 8,
GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + 8,
0);
DestroyAnimVisualTask(taskId);
}
static void AnimWhiteHalo(struct Sprite *sprite)
{
sprite->data[0] = 90;
sprite->callback = WaitAnimForDuration;
sprite->data[1] = 7;
StoreSpriteCallbackInData6(sprite, AnimWhiteHalo_Step1);
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[1], 16 - sprite->data[1]));
}
static void AnimWhiteHalo_Step1(struct Sprite *sprite)
{
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[1], 16 - sprite->data[1]));
if (--sprite->data[1] < 0)
{
sprite->invisible = TRUE;
sprite->callback = AnimWhiteHalo_Step2;
}
}
static void AnimWhiteHalo_Step2(struct Sprite *sprite)
{
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
DestroyAnimSprite(sprite);
}
static void AnimTealAlert(struct Sprite *sprite)
{
u16 rotation;
u8 x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2);
u8 y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET);
InitSpritePosToAnimTarget(sprite, TRUE);
rotation = ArcTan2Neg(sprite->x - x, sprite->y - y);
rotation += 0x6000;
if (IsContest())
rotation += 0x4000;
TrySetSpriteRotScale(sprite, FALSE, 0x100, 0x100, rotation);
sprite->data[0] = gBattleAnimArgs[2];
sprite->data[2] = x;
sprite->data[4] = y;
sprite->callback = StartAnimLinearTranslation;
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
}
static void AnimMeanLookEye(struct Sprite *sprite)
{
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16));
sprite->data[0] = 4;
sprite->callback = AnimMeanLookEye_Step1;
}
static void AnimMeanLookEye_Step1(struct Sprite *sprite)
{
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[0], 16 - sprite->data[0]));
if (sprite->data[1])
sprite->data[0]--;
else
sprite->data[0]++;
if (sprite->data[0] == 15 || sprite->data[0] == 4)
sprite->data[1] ^= 1;
if (sprite->data[2]++ > 70)
{
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
StartSpriteAffineAnim(sprite, 1);
sprite->data[2] = 0;
sprite->invisible = TRUE;
sprite->affineAnimPaused = 1;
sprite->callback = AnimMeanLookEye_Step2;
}
}
static void AnimMeanLookEye_Step2(struct Sprite *sprite)
{
if (sprite->data[2]++ > 9)
{
sprite->invisible = FALSE;
sprite->affineAnimPaused = 0;
if (sprite->affineAnimEnded)
sprite->callback = AnimMeanLookEye_Step3;
}
}
static void AnimMeanLookEye_Step3(struct Sprite *sprite)
{
switch (sprite->data[3])
{
case 0:
case 1:
sprite->x2 = 1;
sprite->y2 = 0;
break;
case 2:
case 3:
sprite->x2 = -1;
sprite->y2 = 0;
break;
case 4:
case 5:
sprite->x2 = 0;
sprite->y2 = 1;
break;
case 6:
default:
sprite->x2 = 0;
sprite->y2 = -1;
break;
}
if (++sprite->data[3] > 7)
sprite->data[3] = 0;
if (sprite->data[4]++ > 15)
{
sprite->data[0] = 16;
sprite->data[1] = 0;
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[0], 0));
sprite->callback = AnimMeanLookEye_Step4;
}
}
static void AnimMeanLookEye_Step4(struct Sprite *sprite)
{
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[0], 16 - sprite->data[0]));
if (sprite->data[1]++ > 1)
{
sprite->data[0]--;
sprite->data[1] = 0;
}
if (sprite->data[0] == 0)
sprite->invisible = TRUE;
if (sprite->data[0] < 0)
{
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
DestroyAnimSprite(sprite);
}
}
void AnimTask_SetPsychicBackground(u8 taskId)
{
gTasks[taskId].func = SetPsychicBackground_Step;
gAnimVisualTaskCount--;
}
static void SetPsychicBackground_Step(u8 taskId)
{
int i;
u16 lastColor;
u8 paletteIndex = GetBattleBgPaletteNum();
if (++gTasks[taskId].data[5] == 4)
{
lastColor = gPlttBufferFaded[paletteIndex * 16 + 11];
for (i = 10; i > 0; i--)
gPlttBufferFaded[paletteIndex * 16 + i + 1] = gPlttBufferFaded[paletteIndex * 16 + i];
gPlttBufferFaded[paletteIndex * 16 + 1] = lastColor;
gTasks[taskId].data[5] = 0;
}
if ((u16)gBattleAnimArgs[7] == 0xFFFF)
DestroyTask(taskId);
}
void AnimTask_FadeScreenToWhite(u8 taskId)
{
gTasks[taskId].func = FadeScreenToWhite_Step;
gAnimVisualTaskCount--;
}
static void FadeScreenToWhite_Step(u8 taskId)
{
int i;
u16 lastColor;
u8 paletteIndex = GetBattleBgPaletteNum();
if (++gTasks[taskId].data[5] == 4)
{
lastColor = gPlttBufferFaded[paletteIndex * 16 + 11];
for (i = 10; i > 0; i--)
gPlttBufferFaded[paletteIndex * 16 + i + 1] = gPlttBufferFaded[paletteIndex * 16 + i];
gPlttBufferFaded[paletteIndex * 16 + 1] = lastColor;
lastColor = gPlttBufferUnfaded[paletteIndex * 16 + 11];
for (i = 10; i > 0; i--)
gPlttBufferUnfaded[paletteIndex * 16 + i + 1] = gPlttBufferUnfaded[paletteIndex * 16 + i];
gPlttBufferUnfaded[paletteIndex * 16 + 1] = lastColor;
gTasks[taskId].data[5] = 0;
}
if ((u16)gBattleAnimArgs[7] == 0xFFFF)
DestroyTask(taskId);
}
static void AnimSpikes(struct Sprite *sprite)
{
u16 x;
u16 y;
InitSpritePosToAnimAttacker(sprite, TRUE);
SetAverageBattlerPositions(gBattleAnimTarget, FALSE, &x, &y);
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
gBattleAnimArgs[2] = -gBattleAnimArgs[2];
sprite->data[0] = gBattleAnimArgs[4];
sprite->data[2] = x + gBattleAnimArgs[2];
sprite->data[4] = y + gBattleAnimArgs[3];
sprite->data[5] = -50;
InitAnimArcTranslation(sprite);
sprite->callback = AnimSpikes_Step1;
}
static void AnimSpikes_Step1(struct Sprite *sprite)
{
if (TranslateAnimHorizontalArc(sprite))
{
sprite->data[0] = 30;
sprite->data[1] = 0;
sprite->callback = WaitAnimForDuration;
StoreSpriteCallbackInData6(sprite, AnimSpikes_Step2);
}
}
static void AnimSpikes_Step2(struct Sprite *sprite)
{
if (sprite->data[1] & 1)
sprite->invisible ^= 1;
if (++sprite->data[1] == 16)
DestroyAnimSprite(sprite);
}
static void AnimLeer(struct Sprite *sprite)
{
SetSpriteCoordsToAnimAttackerCoords(sprite);
SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]);
sprite->y += gBattleAnimArgs[1];
sprite->callback = RunStoredCallbackWhenAnimEnds;
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
}
static void AnimLetterZ(struct Sprite *sprite)
{
int var0;
if (sprite->data[0] == 0)
{
SetSpriteCoordsToAnimAttackerCoords(sprite);
SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]);
if (!IsContest())
{
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
{
sprite->data[1] = gBattleAnimArgs[2];
sprite->data[2] = gBattleAnimArgs[3];
}
else
{
sprite->data[1] = -1 * gBattleAnimArgs[2];
sprite->data[2] = -1 * gBattleAnimArgs[3];
}
}
else
{
sprite->data[1] = -1 * gBattleAnimArgs[2];
sprite->data[2] = gBattleAnimArgs[3];
}
}
sprite->data[0]++;
var0 = (sprite->data[0] * 20) & 0xFF;
sprite->data[3] += sprite->data[1];
sprite->data[4] += sprite->data[2];
sprite->x2 = sprite->data[3] / 2;
sprite->y2 = Sin(var0 & 0xFF, 5) + (sprite->data[4] / 2);
if ((u16)(sprite->x + sprite->x2) > DISPLAY_WIDTH)
DestroyAnimSprite(sprite);
}
static void AnimFang(struct Sprite *sprite)
{
if (sprite->animEnded)
DestroyAnimSprite(sprite);
}
void AnimTask_IsTargetPlayerSide(u8 taskId)
{
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_OPPONENT)
gBattleAnimArgs[ARG_RET_ID] = FALSE;
else
gBattleAnimArgs[ARG_RET_ID] = TRUE;
DestroyAnimVisualTask(taskId);
}
void AnimTask_IsHealingMove(u8 taskId)
{
if (gAnimMoveDmg > 0)
gBattleAnimArgs[ARG_RET_ID] = FALSE;
else
gBattleAnimArgs[ARG_RET_ID] = TRUE;
DestroyAnimVisualTask(taskId);
}
static void AnimSpotlight(struct Sprite *sprite)
{
SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ);
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON);
gBattle_WIN0H = 0;
gBattle_WIN0V = 0;
SetGpuReg(REG_OFFSET_WIN0H, gBattle_WIN0H);
SetGpuReg(REG_OFFSET_WIN0V, gBattle_WIN0V);
InitSpritePosToAnimTarget(sprite, FALSE);
sprite->oam.objMode = ST_OAM_OBJ_WINDOW;
sprite->invisible = TRUE;
sprite->callback = AnimSpotlight_Step1;
}
static void AnimSpotlight_Step1(struct Sprite *sprite)
{
switch (sprite->data[0])
{
case 0:
sprite->invisible = FALSE;
if (sprite->affineAnimEnded)
sprite->data[0]++;
break;
case 1:
case 3:
sprite->data[1] += 117;
sprite->x2 = sprite->data[1] >> 8;
if (++sprite->data[2] == 21)
{
sprite->data[2] = 0;
sprite->data[0]++;
}
break;
case 2:
sprite->data[1] -= 117;
sprite->x2 = sprite->data[1] >> 8;
if (++sprite->data[2] == 41)
{
sprite->data[2] = 0;
sprite->data[0]++;
}
break;
case 4:
ChangeSpriteAffineAnim(sprite, 1);
sprite->data[0]++;
break;
case 5:
if (sprite->affineAnimEnded)
{
sprite->invisible = TRUE;
sprite->callback = AnimSpotlight_Step2;
}
break;
}
}
static void AnimSpotlight_Step2(struct Sprite *sprite)
{
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_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) ^ DISPCNT_OBJWIN_ON);
DestroyAnimSprite(sprite);
}
static void AnimClappingHand(struct Sprite *sprite)
{
if (gBattleAnimArgs[3] == 0)
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X);
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y);
}
sprite->x += gBattleAnimArgs[0];
sprite->y += gBattleAnimArgs[1];
sprite->oam.tileNum += 16;
if (gBattleAnimArgs[2] == 0)
{
sprite->oam.matrixNum = ST_OAM_HFLIP;
sprite->x2 = -12;
sprite->data[1] = 2;
}
else
{
sprite->x2 = 12;
sprite->data[1] = -2;
}
sprite->data[0] = gBattleAnimArgs[4];
if (sprite->data[3] != 255)
sprite->data[3] = gBattleAnimArgs[2];
sprite->callback = AnimClappingHand_Step;
}
static void AnimClappingHand_Step(struct Sprite *sprite)
{
if (sprite->data[2] == 0)
{
sprite->x2 += sprite->data[1];
if (sprite->x2 == 0)
{
sprite->data[2]++;
if (sprite->data[3] == 0)
{
PlaySE1WithPanning(SE_M_ENCORE, BattleAnimAdjustPanning(-64));
}
}
}
else
{
sprite->x2 -= sprite->data[1];
if (abs(sprite->x2) == 12)
{
sprite->data[0]--;
sprite->data[2]--;
}
}
if (sprite->data[0] == 0)
DestroyAnimSprite(sprite);
}
static void AnimClappingHand2(struct Sprite *sprite)
{
sprite->oam.objMode = ST_OAM_OBJ_WINDOW;
sprite->data[3] = 255;
AnimClappingHand(sprite);
}
void AnimTask_CreateSpotlight(u8 taskId)
{
if (IsContest())
{
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ);
gBattle_WIN1H = WIN_RANGE(152, DISPLAY_WIDTH);
gBattle_WIN1V = WIN_RANGE(0, DISPLAY_HEIGHT);
SetGpuReg(REG_OFFSET_WIN1H, gBattle_WIN0H);
SetGpuReg(REG_OFFSET_WIN1V, gBattle_WIN0V);
}
else
{
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ);
gBattle_WIN1H = WIN_RANGE(0, DISPLAY_WIDTH);
gBattle_WIN1V = WIN_RANGE(120, DISPLAY_HEIGHT);
SetGpuReg(REG_OFFSET_WIN1H, gBattle_WIN1H);
SetGpuReg(REG_OFFSET_WIN1V, gBattle_WIN1V);
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN1_ON);
}
DestroyAnimVisualTask(taskId);
}
void AnimTask_RemoveSpotlight(u8 taskId)
{
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR);
gBattle_WIN1H = 0;
gBattle_WIN1V = 0;
if (!IsContest())
ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN1_ON);
DestroyAnimVisualTask(taskId);
}
static void AnimRapidSpin(struct Sprite *sprite)
{
if (gBattleAnimArgs[0] == 0)
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X) + gBattleAnimArgs[1];
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y);
}
else
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X) + gBattleAnimArgs[1];
sprite->y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y);
}
sprite->y2 = gBattleAnimArgs[2];
sprite->data[0] = (sprite->y2 > gBattleAnimArgs[3]);
sprite->data[1] = 0;
sprite->data[2] = gBattleAnimArgs[4];
sprite->data[3] = gBattleAnimArgs[5];
sprite->data[4] = gBattleAnimArgs[3];
sprite->callback = AnimRapidSpin_Step;
}
static void AnimRapidSpin_Step(struct Sprite *sprite)
{
sprite->data[1] = (sprite->data[1] + sprite->data[2]) & 0xFF;
sprite->x2 = gSineTable[sprite->data[1]] >> 4;
sprite->y2 += sprite->data[3];
if (sprite->data[0])
{
if (sprite->y2 < sprite->data[4])
DestroyAnimSprite(sprite);
}
else
{
if (sprite->y2 > sprite->data[4])
DestroyAnimSprite(sprite);
}
}
void AnimTask_RapinSpinMonElevation(u8 taskId)
{
s16 var0;
u8 toBG2;
s16 var2;
int var3;
int var4;
s16 i;
struct ScanlineEffectParams scanlineParams;
struct Task *task = &gTasks[taskId];
if (!gBattleAnimArgs[0])
{
var0 = GetBattlerYCoordWithElevation(gBattleAnimAttacker);
toBG2 = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker);
}
else
{
var0 = GetBattlerYCoordWithElevation(gBattleAnimTarget);
toBG2 = GetBattlerSpriteBGPriorityRank(gBattleAnimTarget);
}
task->data[0] = var0 + 36;
task->data[1] = task->data[0];
task->data[2] = var0 - 33;
if (task->data[2] < 0)
task->data[2] = 0;
task->data[3] = task->data[0];
task->data[4] = 8;
task->data[5] = gBattleAnimArgs[1];
task->data[6] = 0;
task->data[7] = 0;
if (toBG2 == 1)
{
var3 = gBattle_BG1_X;
task->data[8] = var3;
var4 = var3 + DISPLAY_WIDTH;
}
else
{
var3 = gBattle_BG2_X;
task->data[8] = var3;
var4 = var3 + DISPLAY_WIDTH;
}
task->data[9] = var4;
task->data[10] = gBattleAnimArgs[2];
if (!gBattleAnimArgs[2])
{
task->data[11] = var4;
var2 = task->data[8];
}
else
{
task->data[11] = var3;
var2 = task->data[9];
}
task->data[15] = 0;
i = task->data[2];
while (i <= task->data[3])
{
gScanlineEffectRegBuffers[0][i] = var2;
gScanlineEffectRegBuffers[1][i] = var2;
i++;
}
if (toBG2 == 1)
scanlineParams.dmaDest = &REG_BG1HOFS;
else
scanlineParams.dmaDest = &REG_BG2HOFS;
scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT;
scanlineParams.initState = 1;
scanlineParams.unused9 = 0;
ScanlineEffect_SetParams(scanlineParams);
task->func = RapinSpinMonElevation_Step;
}
static void RapinSpinMonElevation_Step(u8 taskId)
{
s16 i;
struct Task *task = &gTasks[taskId];
task->data[0] -= task->data[5];
if (task->data[0] < task->data[2])
task->data[0] = task->data[2];
if (task->data[4] == 0)
{
task->data[1] -= task->data[5];
if (task->data[1] < task->data[2])
{
task->data[1] = task->data[2];
task->data[15] = 1;
}
}
else
{
task->data[4]--;
}
if (++task->data[6] > 1)
{
task->data[6] = 0;
task->data[7] = task->data[7] == 0 ? 1 : 0;
if (task->data[7])
task->data[12] = task->data[8];
else
task->data[12] = task->data[9];
}
i = task->data[0];
while (i < task->data[1])
{
gScanlineEffectRegBuffers[0][i] = task->data[12];
gScanlineEffectRegBuffers[1][i] = task->data[12];
i++;
}
i = task->data[1];
while (i <= task->data[3])
{
gScanlineEffectRegBuffers[0][i] = task->data[11];
gScanlineEffectRegBuffers[1][i] = task->data[11];
i++;
}
if (task->data[15])
{
if (task->data[10])
gScanlineEffect.state = 3;
DestroyAnimVisualTask(taskId);
}
}
void AnimTask_TormentAttacker(u8 taskId)
{
struct Task *task = &gTasks[taskId];
task->data[0] = 0;
task->data[1] = 0;
task->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
task->data[3] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
task->data[4] = 32;
task->data[5] = -20;
task->data[6] = 0;
task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER);
task->func = TormentAttacker_Step;
}
static void TormentAttacker_Step(u8 taskId)
{
int var0, var1;
s16 x, y;
u16 i, j;
u8 spriteId;
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
var0 = task->data[2];
if (task->data[1] & 1)
{
var1 = task->data[4];
x = var0 - var1;
}
else
{
var1 = task->data[4];
x = var0 + var1;
}
y = task->data[3] + task->data[5];
spriteId = CreateSprite(&gThoughtBubbleSpriteTemplate, x, y, 6 - task->data[1]);
PlaySE12WithPanning(SE_M_METRONOME, BattleAnimAdjustPanning(-64));
if (spriteId != MAX_SPRITES)
{
gSprites[spriteId].hFlip = task->data[1] & 1;
gSprites[spriteId].callback = SpriteCallbackDummy;
}
if (task->data[1] & 1)
{
task->data[4] -= 6;
task->data[5] -= 6;
}
PrepareAffineAnimInTaskData(task, task->data[15], sAffineAnims_Torment);
task->data[1]++;
task->data[0] = 1;
break;
case 1:
if (!RunAffineAnimFromTaskData(task))
{
if (task->data[1] == 6)
{
task->data[6] = 8;
task->data[0] = 3;
}
else
{
if (task->data[1] <= 2)
task->data[6] = 10;
else
task->data[6] = 0;
task->data[0] = 2;
}
}
break;
case 2:
if (task->data[6] != 0)
task->data[6]--;
else
task->data[0] = 0;
break;
case 3:
if (task->data[6] != 0)
task->data[6]--;
else
task->data[0] = 4;
break;
case 4:
for (i = 0, j = 0; i < MAX_SPRITES; i++)
{
if (gSprites[i].template == &gThoughtBubbleSpriteTemplate)
{
gSprites[i].data[0] = taskId;
gSprites[i].data[1] = 6;
StartSpriteAnim(&gSprites[i], 2);
gSprites[i].callback = TormentAttacker_Callback;
if (++j == 6)
break;
}
}
task->data[6] = j;
task->data[0] = 5;
break;
case 5:
if (task->data[6] == 0)
DestroyAnimVisualTask(taskId);
break;
}
}
static void TormentAttacker_Callback(struct Sprite *sprite)
{
if (sprite->animEnded)
{
gTasks[sprite->data[0]].data[sprite->data[1]]--;
DestroySprite(sprite);
}
}
static void AnimTriAttackTriangle(struct Sprite *sprite)
{
if (sprite->data[0] == 0)
InitSpritePosToAnimAttacker(sprite, FALSE);
if (++sprite->data[0] < 40)
{
u16 var = sprite->data[0];
if ((var & 1) == 0)
sprite->invisible = TRUE;
else
sprite->invisible = FALSE;
}
if (sprite->data[0] > 30)
sprite->invisible = FALSE;
if (sprite->data[0] == 61)
{
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
sprite->x += sprite->x2;
sprite->y += sprite->y2;
sprite->x2 = 0;
sprite->y2 = 0;
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;
}
}
void AnimTask_DefenseCurlDeformMon(u8 taskId)
{
switch (gTasks[taskId].data[0])
{
case 0:
PrepareAffineAnimInTaskData(&gTasks[taskId], GetAnimBattlerSpriteId(ANIM_ATTACKER), DefenseCurlDeformMonAffineAnimCmds);
gTasks[taskId].data[0]++;
break;
case 1:
if (!RunAffineAnimFromTaskData(&gTasks[taskId]))
DestroyAnimVisualTask(taskId);
break;
}
}
static void AnimBatonPassPokeball(struct Sprite *sprite)
{
u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER);
switch (sprite->data[0])
{
case 0:
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_NORMAL);
sprite->data[1] = 256;
sprite->data[2] = 256;
sprite->data[0]++;
break;
case 1:
sprite->data[1] += 96;
sprite->data[2] -= 26;
SetSpriteRotScale(spriteId, sprite->data[1], sprite->data[2], 0);
if (++sprite->data[3] == 5)
sprite->data[0]++;
// fall through
case 2:
sprite->data[1] += 96;
sprite->data[2] += 48;
SetSpriteRotScale(spriteId, sprite->data[1], sprite->data[2], 0);
if (++sprite->data[3] == 9)
{
sprite->data[3] = 0;
gSprites[spriteId].invisible = TRUE;
ResetSpriteRotScale(spriteId);
sprite->data[0]++;
}
break;
case 3:
sprite->y2 -= 6;
if (sprite->y + sprite->y2 < -32)
DestroyAnimSprite(sprite);
break;
}
}
static void AnimWishStar(struct Sprite *sprite)
{
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
sprite->x = -16;
else
sprite->x = 256;
sprite->y = 0;
sprite->callback = AnimWishStar_Step;
}
static void AnimWishStar_Step(struct Sprite *sprite)
{
u32 newX;
sprite->data[0] += 72;
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
sprite->x2 = sprite->data[0] >> 4;
else
sprite->x2 = -(sprite->data[0] >> 4);
sprite->data[1] += 16;
sprite->y2 += sprite->data[1] >> 8;
if (++sprite->data[2] % 3 == 0)
{
CreateSpriteAndAnimate(
&gMiniTwinklingStarSpriteTemplate,
sprite->x + sprite->x2,
sprite->y + sprite->y2,
sprite->subpriority + 1);
}
newX = sprite->x + sprite->x2 + 32;
if (newX > 304)
DestroyAnimSprite(sprite);
}
static void AnimMiniTwinklingStar(struct Sprite *sprite)
{
u8 rand;
s8 y;
rand = Random2() & 3;
if (rand == 0)
sprite->oam.tileNum += 4;
else
sprite->oam.tileNum += 5;
y = Random2() & 7;
if (y > 3)
y = -y;
sprite->y2 = y;
sprite->callback = AnimMiniTwinklingStar_Step;
}
static void AnimMiniTwinklingStar_Step(struct Sprite *sprite)
{
if (++sprite->data[0] < 30)
{
if (++sprite->data[1] == 2)
{
sprite->invisible ^= 1;
sprite->data[1] = 0;
}
}
else
{
if (sprite->data[1] == 2)
sprite->invisible = FALSE;
if (sprite->data[1] == 3)
{
sprite->invisible = TRUE;
sprite->data[1] = -1;
}
sprite->data[1]++;
}
if (sprite->data[0] > 60)
DestroySprite(sprite);
}
void AnimTask_StockpileDeformMon(u8 taskId)
{
if (!gTasks[taskId].data[0])
{
PrepareAffineAnimInTaskData(&gTasks[taskId], GetAnimBattlerSpriteId(ANIM_ATTACKER), gStockpileDeformMonAffineAnimCmds);
gTasks[taskId].data[0]++;
}
else
{
if (!RunAffineAnimFromTaskData(&gTasks[taskId]))
DestroyAnimVisualTask(taskId);
}
}
void AnimTask_SpitUpDeformMon(u8 taskId)
{
if (!gTasks[taskId].data[0])
{
PrepareAffineAnimInTaskData(&gTasks[taskId], GetAnimBattlerSpriteId(ANIM_ATTACKER), gSpitUpDeformMonAffineAnimCmds);
gTasks[taskId].data[0]++;
}
else
{
if (!RunAffineAnimFromTaskData(&gTasks[taskId]))
DestroyAnimVisualTask(taskId);
}
}
static void AnimSwallowBlueOrb(struct Sprite *sprite)
{
switch (sprite->data[0])
{
case 0:
InitSpritePosToAnimAttacker(sprite, FALSE);
sprite->data[1] = 0x900;
sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
sprite->data[0]++;
break;
case 1:
sprite->y2 -= sprite->data[1] >> 8;
sprite->data[1] -= 96;
if (sprite->y + sprite->y2 > sprite->data[2])
DestroyAnimSprite(sprite);
break;
}
}
void AnimTask_SwallowDeformMon(u8 taskId)
{
if (!gTasks[taskId].data[0])
{
PrepareAffineAnimInTaskData(&gTasks[taskId], GetAnimBattlerSpriteId(ANIM_ATTACKER), gSwallowDeformMonAffineAnimCmds);
gTasks[taskId].data[0]++;
}
else
{
if (!RunAffineAnimFromTaskData(&gTasks[taskId]))
DestroyAnimVisualTask(taskId);
}
}
void AnimTask_TransformMon(u8 taskId)
{
int i, j;
u8 position;
struct BattleAnimBgData animBg;
u8 *dest;
u8 *src;
u16 *bgTilemap;
u16 stretch;
switch (gTasks[taskId].data[0])
{
case 0:
SetGpuReg(REG_OFFSET_MOSAIC, 0);
if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1)
SetAnimBgAttribute(1, BG_ANIM_MOSAIC, 1);
else
SetAnimBgAttribute(2, BG_ANIM_MOSAIC, 1);
gTasks[taskId].data[10] = gBattleAnimArgs[0];
gTasks[taskId].data[0]++;
break;
case 1:
if (gTasks[taskId].data[2]++ > 1)
{
gTasks[taskId].data[2] = 0;
gTasks[taskId].data[1]++;
stretch = gTasks[taskId].data[1];
SetGpuReg(REG_OFFSET_MOSAIC, (stretch << 4) | stretch);
if (stretch == 15)
gTasks[taskId].data[0]++;
}
break;
case 2:
HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, gTasks[taskId].data[10]);
GetBgDataForTransform(&animBg, gBattleAnimAttacker);
if (IsContest())
position = B_POSITION_PLAYER_LEFT;
else
position = GetBattlerPosition(gBattleAnimAttacker);
src = gMonSpritesGfxPtr->sprites.ptr[position] + (gBattleMonForms[gBattleAnimAttacker] << 11);
dest = animBg.bgTiles;
CpuCopy32(src, dest, MON_PIC_SIZE);
LoadBgTiles(1, animBg.bgTiles, 0x800, animBg.tilesOffset);
if (IsContest())
{
if (IsSpeciesNotUnown(gContestResources->moveAnim->species) != IsSpeciesNotUnown(gContestResources->moveAnim->targetSpecies))
{
bgTilemap = (u16 *)animBg.bgTilemap;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 4; j++)
{
u16 temp = bgTilemap[j + i * 0x20];
bgTilemap[j + i * 0x20] = bgTilemap[(7 - j) + i * 0x20];
bgTilemap[(7 - j) + i * 0x20] = temp;
}
}
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
bgTilemap[j + i * 0x20] ^= 0x400;
}
}
}
if (IsSpeciesNotUnown(gContestResources->moveAnim->targetSpecies))
gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].affineAnims = gAffineAnims_BattleSpriteContest;
else
gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].affineAnims = gAffineAnims_BattleSpriteOpponentSide;
StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[gBattleAnimAttacker]], BATTLER_AFFINE_NORMAL);
}
gTasks[taskId].data[0]++;
break;
case 3:
if (gTasks[taskId].data[2]++ > 1)
{
gTasks[taskId].data[2] = 0;
gTasks[taskId].data[1]--;
stretch = gTasks[taskId].data[1];
SetGpuReg(REG_OFFSET_MOSAIC, (stretch << 4) | stretch);
if (stretch == 0)
gTasks[taskId].data[0]++;
}
break;
case 4:
SetGpuReg(REG_OFFSET_MOSAIC, 0);
if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1)
SetAnimBgAttribute(1, BG_ANIM_MOSAIC, 0);
else
SetAnimBgAttribute(2, BG_ANIM_MOSAIC, 0);
if (!IsContest())
{
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT)
{
if (gTasks[taskId].data[10] == 0)
SetBattlerShadowSpriteCallback(gBattleAnimAttacker, gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies);
}
}
DestroyAnimVisualTask(taskId);
break;
}
}
void AnimTask_IsMonInvisible(u8 taskId)
{
gBattleAnimArgs[ARG_RET_ID] = gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].invisible;
DestroyAnimVisualTask(taskId);
}
void AnimTask_CastformGfxDataChange(u8 taskId)
{
HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, TRUE);
DestroyAnimVisualTask(taskId);
}
void AnimTask_MorningSunLightBeam(u8 taskId)
{
struct BattleAnimBgData animBg;
switch (gTasks[taskId].data[0])
{
case 0:
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16));
SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0);
SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1);
if (!IsContest())
SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1);
GetBattleAnimBg1Data(&animBg);
AnimLoadCompressedBgTilemapHandleContest(&animBg, &gBattleAnimMaskTilemap_LightBeam, FALSE);
if (IsContest())
{
gBattle_BG1_X = -56;
gBattle_BG1_Y = 0;
}
else
{
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
gBattle_BG1_X = -135;
else
gBattle_BG1_X = -10;
gBattle_BG1_Y = 0;
}
AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimMaskImage_LightBeam, animBg.tilesOffset);
LoadCompressedPalette(gBattleAnimMaskPalette_LightBeam, animBg.paletteId * 16, 32);
gTasks[taskId].data[10] = gBattle_BG1_X;
gTasks[taskId].data[11] = gBattle_BG1_Y;
gTasks[taskId].data[0]++;
PlaySE12WithPanning(SE_M_MORNING_SUN, BattleAnimAdjustPanning(-64));
break;
case 1:
if (gTasks[taskId].data[4]++ > 0)
{
gTasks[taskId].data[4] = 0;
if (++gTasks[taskId].data[1] > 12)
gTasks[taskId].data[1] = 12;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[1], 16 - gTasks[taskId].data[1]));
if (gTasks[taskId].data[1] == 12)
gTasks[taskId].data[0]++;
}
break;
case 2:
if (--gTasks[taskId].data[1] < 0)
gTasks[taskId].data[1] = 0;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[1], 16 - gTasks[taskId].data[1]));
if (!gTasks[taskId].data[1])
{
gBattle_BG1_X = gMorningSunLightBeamCoordsTable[gTasks[taskId].data[2]] + gTasks[taskId].data[10];
if (++gTasks[taskId].data[2] == 4)
gTasks[taskId].data[0] = 4;
else
gTasks[taskId].data[0] = 3;
}
break;
case 3:
if (++gTasks[taskId].data[3] == 4)
{
gTasks[taskId].data[3] = 0;
gTasks[taskId].data[0] = 1;
PlaySE12WithPanning(SE_M_MORNING_SUN, BattleAnimAdjustPanning(-64));
}
break;
case 4:
GetBattleAnimBg1Data(&animBg);
ClearBattleAnimBg(animBg.bgId);
if (!IsContest())
SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0);
SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1);
gBattle_BG1_X = 0;
gBattle_BG1_Y = 0;
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
DestroyAnimVisualTask(taskId);
break;
}
}
static void AnimGreenStar(struct Sprite *sprite)
{
s16 xOffset;
u8 spriteId1;
u8 spriteId2;
xOffset = Random2();
xOffset &= 0x3F;
if (xOffset > 31)
xOffset = 32 - xOffset;
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X) + xOffset;
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + 32;
sprite->data[1] = gBattleAnimArgs[0];
sprite->data[2] = gBattleAnimArgs[1];
spriteId1 = CreateSprite(&gGreenStarSpriteTemplate, sprite->x, sprite->y, sprite->subpriority + 1);
spriteId2 = CreateSprite(&gGreenStarSpriteTemplate, sprite->x, sprite->y, sprite->subpriority + 1);
StartSpriteAnim(&gSprites[spriteId1], 1);
StartSpriteAnim(&gSprites[spriteId2], 2);
gSprites[spriteId1].data[1] = gBattleAnimArgs[0];
gSprites[spriteId1].data[2] = gBattleAnimArgs[1];
gSprites[spriteId2].data[1] = gBattleAnimArgs[0];
gSprites[spriteId2].data[2] = gBattleAnimArgs[1];
gSprites[spriteId1].data[7] = -1;
gSprites[spriteId2].data[7] = -1;
gSprites[spriteId1].invisible = TRUE;
gSprites[spriteId2].invisible = TRUE;
gSprites[spriteId1].callback = AnimGreenStar_Callback;
gSprites[spriteId2].callback = AnimGreenStar_Callback;
sprite->data[6] = spriteId1;
sprite->data[7] = spriteId2;
sprite->callback = AnimGreenStar_Step1;
}
static void AnimGreenStar_Step1(struct Sprite *sprite)
{
s16 delta = sprite->data[3] + sprite->data[2];
sprite->y2 -= delta >> 8;
sprite->data[3] += sprite->data[2];
sprite->data[3] &= 0xFF;
if (sprite->data[4] == 0 && sprite->y2 < -8)
{
gSprites[sprite->data[6]].invisible = FALSE;
sprite->data[4]++;
}
if (sprite->data[4] == 1 && sprite->y2 < -16)
{
gSprites[sprite->data[7]].invisible = FALSE;
sprite->data[4]++;
}
if (--sprite->data[1] == -1)
{
sprite->invisible = TRUE;
sprite->callback = AnimGreenStar_Step2;
}
}
static void AnimGreenStar_Step2(struct Sprite *sprite)
{
if (gSprites[sprite->data[6]].callback == SpriteCallbackDummy
&& gSprites[sprite->data[7]].callback == SpriteCallbackDummy)
{
DestroySprite(&gSprites[sprite->data[6]]);
DestroySprite(&gSprites[sprite->data[7]]);
DestroyAnimSprite(sprite);
}
}
static void AnimGreenStar_Callback(struct Sprite *sprite)
{
if (!sprite->invisible)
{
s16 delta = sprite->data[3] + sprite->data[2];
sprite->y2 -= delta >> 8;
sprite->data[3] += sprite->data[2];
sprite->data[3] &= 0xFF;
if (--sprite->data[1] == -1)
{
sprite->invisible = TRUE;
sprite->callback = SpriteCallbackDummy;
}
}
}
void AnimTask_DoomDesireLightBeam(u8 taskId)
{
struct BattleAnimBgData animBg;
switch (gTasks[taskId].data[0])
{
case 0:
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(3, 13));
SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0);
SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1);
if (!IsContest())
SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1);
GetBattleAnimBg1Data(&animBg);
AnimLoadCompressedBgTilemapHandleContest(&animBg, &gBattleAnimMaskTilemap_LightBeam, FALSE);
if (IsContest())
{
gBattle_BG1_X = -56;
gBattle_BG1_Y = 0;
}
else
{
u8 position = GetBattlerPosition(gBattleAnimTarget);
if (IsDoubleBattle() == TRUE)
{
if (position == B_POSITION_OPPONENT_LEFT)
gBattle_BG1_X = -155;
if (position == B_POSITION_OPPONENT_RIGHT)
gBattle_BG1_X = -115;
if (position == B_POSITION_PLAYER_LEFT)
gBattle_BG1_X = 14;
if (position == B_POSITION_PLAYER_RIGHT)
gBattle_BG1_X = -20;
}
else
{
if (position == B_POSITION_OPPONENT_LEFT)
gBattle_BG1_X = -135;
if (position == B_POSITION_PLAYER_LEFT)
gBattle_BG1_X = -10;
}
gBattle_BG1_Y = 0;
}
AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimMaskImage_LightBeam, animBg.tilesOffset);
LoadCompressedPalette(gBattleAnimMaskPalette_LightBeam, animBg.paletteId * 16, 32);
gTasks[taskId].data[10] = gBattle_BG1_X;
gTasks[taskId].data[11] = gBattle_BG1_Y;
gTasks[taskId].data[0]++;
break;
case 1:
gTasks[taskId].data[3] = 0;
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_OPPONENT)
gBattle_BG1_X = gTasks[taskId].data[10] + gDoomDesireLightBeamCoordTable[gTasks[taskId].data[2]];
else
gBattle_BG1_X = gTasks[taskId].data[10] - gDoomDesireLightBeamCoordTable[gTasks[taskId].data[2]];
if (++gTasks[taskId].data[2] == 5)
gTasks[taskId].data[0] = 5;
else
gTasks[taskId].data[0]++;
break;
case 2:
if (--gTasks[taskId].data[1] <= 4)
gTasks[taskId].data[1] = 5;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(3, gTasks[taskId].data[1]));
if (gTasks[taskId].data[1] == 5)
gTasks[taskId].data[0]++;
break;
case 3:
if (++gTasks[taskId].data[3] > gDoomDesireLightBeamDelayTable[gTasks[taskId].data[2]])
gTasks[taskId].data[0]++;
break;
case 4:
if (++gTasks[taskId].data[1] > 13)
gTasks[taskId].data[1] = 13;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(3, gTasks[taskId].data[1]));
if (gTasks[taskId].data[1] == 13)
gTasks[taskId].data[0] = 1;
break;
case 5:
GetBattleAnimBg1Data(&animBg);
ClearBattleAnimBg(animBg.bgId);
if (!IsContest())
SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0);
SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1);
gBattle_BG1_X = 0;
gBattle_BG1_Y = 0;
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
DestroyAnimVisualTask(taskId);
break;
}
}
// Briefly vertically grows and shrinks the attacking mon's sprite.
// No args.
void AnimTask_StrongFrustrationGrowAndShrink(u8 taskId)
{
if (gTasks[taskId].data[0] == 0)
{
PrepareAffineAnimInTaskData(&gTasks[taskId], GetAnimBattlerSpriteId(ANIM_ATTACKER), gStrongFrustrationAffineAnimCmds);
gTasks[taskId].data[0]++;
}
else
{
if (!RunAffineAnimFromTaskData(&gTasks[taskId]))
DestroyAnimVisualTask(taskId);
}
}
// Animates an anger mark near the mon's head.
// arg 0: initial x pixel offset
// arg 1: initial y pixel offset
static void AnimWeakFrustrationAngerMark(struct Sprite *sprite)
{
if (sprite->data[0] == 0)
{
InitSpritePosToAnimAttacker(sprite, 0);
sprite->data[0]++;
}
else if (sprite->data[0]++ > 20)
{
sprite->data[1] += 160;
sprite->data[2] += 128;
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
sprite->x2 = -(sprite->data[1] >> 8);
else
sprite->x2 = sprite->data[1] >> 8;
sprite->y2 += sprite->data[2] >> 8;
if (sprite->y2 > 64)
DestroyAnimSprite(sprite);
}
}
// Rocks the mon back and forth. This is done on a pivot so it is done via rotation.
// arg 0: which battler
// arg 1: number of rocks
// arg 2: rotation speed increase
void AnimTask_RockMonBackAndForth(u8 taskId)
{
u8 side;
struct Task *task = &gTasks[taskId];
if (!gBattleAnimArgs[1])
{
DestroyAnimVisualTask(taskId);
return;
}
if (gBattleAnimArgs[2] < 0)
gBattleAnimArgs[2] = 0;
if (gBattleAnimArgs[2] > 2)
gBattleAnimArgs[2] = 2;
task->data[0] = 0;
task->data[1] = 0;
task->data[2] = 0;
task->data[3] = 8 - (2 * gBattleAnimArgs[2]);
task->data[4] = 0x100 + (gBattleAnimArgs[2] * 128);
task->data[5] = gBattleAnimArgs[2] + 2;
task->data[6] = gBattleAnimArgs[1] - 1;
task->data[15] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
side = GetBattlerSide(gBattleAnimAttacker);
else
side = GetBattlerSide(gBattleAnimTarget);
if (side == B_SIDE_OPPONENT)
{
task->data[4] *= -1;
task->data[5] *= -1;
}
PrepareBattlerSpriteForRotScale(task->data[15], ST_OAM_OBJ_NORMAL);
task->func = AnimTask_RockMonBackAndForth_Step;
}
static void AnimTask_RockMonBackAndForth_Step(u8 taskId)
{
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
gSprites[task->data[15]].x2 += task->data[5];
task->data[2] -= task->data[4];
SetSpriteRotScale(task->data[15], 0x100, 0x100, task->data[2]);
SetBattlerSpriteYOffsetFromRotation(task->data[15]);
if (++task->data[1] >= task->data[3])
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 1:
gSprites[task->data[15]].x2 -= task->data[5];
task->data[2] += task->data[4];
SetSpriteRotScale(task->data[15], 0x100, 0x100, task->data[2]);
SetBattlerSpriteYOffsetFromRotation(task->data[15]);
if (++task->data[1] >= task->data[3] * 2)
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 2:
gSprites[task->data[15]].x2 += task->data[5];
task->data[2] -= task->data[4];
SetSpriteRotScale(task->data[15], 0x100, 0x100, task->data[2]);
SetBattlerSpriteYOffsetFromRotation(task->data[15]);
if (++task->data[1] >= task->data[3])
{
if (task->data[6])
{
task->data[6]--;
task->data[1] = 0;
task->data[0] = 0;
}
else
{
task->data[0]++;
}
}
break;
case 3:
ResetSpriteRotScale(task->data[15]);
DestroyAnimVisualTask(taskId);
break;
}
}
// Floats a petal across the screen towards the target mon's side.
// arg 0: initial y pixel offset
// arg 1: sprite anim num
// arg 2: unused
static void AnimSweetScentPetal(struct Sprite *sprite)
{
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
{
sprite->x = 0;
sprite->y = gBattleAnimArgs[0];
}
else
{
sprite->x = DISPLAY_WIDTH;
sprite->y = gBattleAnimArgs[0] - 30;
}
sprite->data[2] = gBattleAnimArgs[2];
StartSpriteAnim(sprite, gBattleAnimArgs[1]);
sprite->callback = AnimSweetScentPetal_Step;
}
static void AnimSweetScentPetal_Step(struct Sprite *sprite)
{
sprite->data[0] += 3;
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
{
sprite->x += 5;
sprite->y -= 1;
if (sprite->x > DISPLAY_WIDTH)
DestroyAnimSprite(sprite);
sprite->y2 = Sin(sprite->data[0] & 0xFF, 16);
}
else
{
sprite->x -= 5;
sprite->y += 1;
if (sprite->x < 0)
DestroyAnimSprite(sprite);
sprite->y2 = Cos(sprite->data[0] & 0xFF, 16);
}
}
// Moves the mon sprite in a flailing back-and-forth motion.
// arg 0: which battler
void AnimTask_FlailMovement(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] = 0x20;
task->data[13] = 0x40;
task->data[14] = 0x800;
task->data[15] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
PrepareBattlerSpriteForRotScale(task->data[15], ST_OAM_OBJ_NORMAL);
task->func = AnimTask_FlailMovement_Step;
}
static void AnimTask_FlailMovement_Step(u8 taskId)
{
int temp;
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
task->data[2] += 0x200;
if (task->data[2] >= task->data[14])
{
s16 diff = task->data[14] - task->data[2];
s16 div = diff / (task->data[14] * 2);
s16 mod = diff % (task->data[14] * 2);
if ((div & 1) == 0)
{
task->data[2] = task->data[14] - mod;
task->data[0] = 1;
}
else
{
task->data[2] = mod - task->data[14];
}
}
break;
case 1:
task->data[2] -= 0x200;
if (task->data[2] <= -task->data[14])
{
s16 diff = task->data[14] - task->data[2];
s16 div = diff / (task->data[14] * 2);
s16 mod = diff % (task->data[14] * 2);
if ((1 & div) == 0)
{
task->data[2] = mod - task->data[14];
task->data[0] = 0;
}
else
{
task->data[2] = task->data[14] - mod;
}
}
break;
case 2:
ResetSpriteRotScale(task->data[15]);
DestroyAnimVisualTask(taskId);
return;
}
SetSpriteRotScale(task->data[15], 0x100, 0x100, task->data[2]);
SetBattlerSpriteYOffsetFromRotation(task->data[15]);
gSprites[task->data[15]].x2 = -(((temp = task->data[2]) >= 0 ? task->data[2] : temp + 63) >> 6);
if (++task->data[1] > 8)
{
if (task->data[12])
{
task->data[12]--;
task->data[14] -= task->data[13];
if (task->data[14] < 16)
task->data[14] = 16;
}
else
{
task->data[0] = 2;
}
}
}
// Makes a spark-like projectile fall on top of the mon.
// arg 0: initial x pixel offset
// arg 1: initial y pixel offset
// arg 2: which battler
static void AnimPainSplitProjectile(struct Sprite *sprite)
{
if (!sprite->data[0])
{
if (gBattleAnimArgs[2] == ANIM_ATTACKER)
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
}
sprite->x += gBattleAnimArgs[0];
sprite->y += gBattleAnimArgs[1];
sprite->data[1] = 0x80;
sprite->data[2] = 0x300;
sprite->data[3] = gBattleAnimArgs[1];
sprite->data[0]++;
}
else
{
sprite->x2 = sprite->data[1] >> 8;
sprite->y2 += sprite->data[2] >> 8;
if (sprite->data[4] == 0 && sprite->y2 > -sprite->data[3])
{
sprite->data[4] = 1;
sprite->data[2] = (-sprite->data[2] / 3) * 2;
}
sprite->data[1] += 192;
sprite->data[2] += 128;
if (sprite->animEnded)
DestroyAnimSprite(sprite);
}
}
// Performs one of several affine transformations on the mon sprite.
// arg 0: which battler
// arg 1: which transformation
void AnimTask_PainSplitMovement(u8 taskId)
{
u8 spriteId;
if (gTasks[taskId].data[0] == 0)
{
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
gTasks[taskId].data[11] = gBattleAnimAttacker;
else
gTasks[taskId].data[11] = gBattleAnimTarget;
spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
gTasks[taskId].data[10] = spriteId;
PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_NORMAL);
switch (gBattleAnimArgs[1])
{
case 0:
SetSpriteRotScale(spriteId, 0xE0, 0x140, 0);
SetBattlerSpriteYOffsetFromYScale(spriteId);
break;
case 1:
SetSpriteRotScale(spriteId, 0xD0, 0x130, 0xF00);
SetBattlerSpriteYOffsetFromYScale(spriteId);
if (IsContest() || GetBattlerSide(gTasks[taskId].data[11]) == B_SIDE_PLAYER)
gSprites[spriteId].y2 += 16;
break;
case 2:
SetSpriteRotScale(spriteId, 0xD0, 0x130, 0xF100);
SetBattlerSpriteYOffsetFromYScale(spriteId);
if (IsContest() || GetBattlerSide(gTasks[taskId].data[11]) == B_SIDE_PLAYER)
gSprites[spriteId].y2 += 16;
break;
}
gSprites[spriteId].x2 = 2;
gTasks[taskId].data[0]++;
}
else
{
spriteId = gTasks[taskId].data[10];
if (++gTasks[taskId].data[2] == 3)
{
gTasks[taskId].data[2] = 0;
gSprites[spriteId].x2 = -gSprites[spriteId].x2;
}
if (++gTasks[taskId].data[1] == 13)
{
ResetSpriteRotScale(spriteId);
gSprites[spriteId].x2 = 0;
gSprites[spriteId].y2 = 0;
DestroyAnimVisualTask(taskId);
}
}
}
// Move a piece of confetti in a slightly-random speed across the screen.
// arg 0: which battler the confetti starts from
static void AnimFlatterConfetti(struct Sprite *sprite)
{
u8 tileOffset;
int rand1;
int rand2;
tileOffset = Random2() % 12;
sprite->oam.tileNum += tileOffset;
rand1 = Random2() & 0x1FF;
rand2 = Random2() & 0xFF;
if (rand1 & 1)
sprite->data[0] = 0x5E0 + rand1;
else
sprite->data[0] = 0x5E0 - rand1;
if (rand2 & 1)
sprite->data[1] = 0x480 + rand2;
else
sprite->data[1] = 0x480 - rand2;
sprite->data[2] = gBattleAnimArgs[0];
if (sprite->data[2] == ANIM_ATTACKER)
sprite->x = -8;
else
sprite->x = 248;
sprite->y = 104;
sprite->callback = AnimFlatterConfetti_Step;
}
static void AnimFlatterConfetti_Step(struct Sprite *sprite)
{
if (sprite->data[2] == 0)
{
sprite->x2 += sprite->data[0] >> 8;
sprite->y2 -= sprite->data[1] >> 8;
}
else
{
sprite->x2 -= sprite->data[0] >> 8;
sprite->y2 -= sprite->data[1] >> 8;
}
sprite->data[0] -= 22;
sprite->data[1] -= 48;
if (sprite->data[0] < 0)
sprite->data[0] = 0;
if (++sprite->data[3] == 31)
DestroyAnimSprite(sprite);
}
// Uses a spotlight sprite as a light mask to illuminate the target mon. The spotlight grows and shrinks.
// arg 0: initial x pixel offset
// arg 1: initial y pixel offset
// arg 2: duration of fully-opened spotlight
static void AnimFlatterSpotlight(struct Sprite *sprite)
{
SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ);
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON);
gBattle_WIN0H = 0;
gBattle_WIN0V = 0;
SetGpuReg(REG_OFFSET_WIN0H, gBattle_WIN0H);
SetGpuReg(REG_OFFSET_WIN0V, gBattle_WIN0V);
sprite->data[0] = gBattleAnimArgs[2];
InitSpritePosToAnimTarget(sprite, FALSE);
sprite->oam.objMode = ST_OAM_OBJ_WINDOW;
sprite->invisible = TRUE;
sprite->callback = AnimFlatterSpotlight_Step;
}
static void AnimFlatterSpotlight_Step(struct Sprite *sprite)
{
switch (sprite->data[1])
{
case 0:
sprite->invisible = FALSE;
if (sprite->affineAnimEnded)
sprite->data[1]++;
break;
case 1:
if (--sprite->data[0] == 0)
{
ChangeSpriteAffineAnim(sprite, 1);
sprite->data[1]++;
}
break;
case 2:
if (sprite->affineAnimEnded)
{
sprite->invisible = TRUE;
sprite->data[1]++;
}
break;
case 3:
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_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) ^ DISPCNT_OBJWIN_ON);
DestroyAnimSprite(sprite);
break;
}
}
// Spins an orb around the attacking mon, while its path radius grows and shrinks.
// arg 0: duration
// arg 1: initial wave offset
static void AnimReversalOrb(struct Sprite *sprite)
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
sprite->data[0] = gBattleAnimArgs[0];
sprite->data[1] = gBattleAnimArgs[1];
sprite->callback = AnimReversalOrb_Step;
sprite->callback(sprite);
}
static void AnimReversalOrb_Step(struct Sprite *sprite)
{
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;
if ((u16)sprite->data[1] < 64 || sprite->data[1] > 195)
sprite->subpriority = GetBattlerSpriteSubpriority(gBattleAnimAttacker) - 1;
else
sprite->subpriority = GetBattlerSpriteSubpriority(gBattleAnimAttacker) + 1;
if (!sprite->data[5])
{
sprite->data[2] += 0x400;
sprite->data[3] += 0x100;
sprite->data[4]++;
if (sprite->data[4] == sprite->data[0])
{
sprite->data[4] = 0;
sprite->data[5] = 1;
}
}
else if (sprite->data[5] == 1)
{
sprite->data[2] -= 0x400;
sprite->data[3] -= 0x100;
sprite->data[4]++;
if (sprite->data[4] == sprite->data[0])
DestroyAnimSprite(sprite);
}
}
// Copies the target mon's sprite, and makes a white silhouette that shrinks away.
void AnimTask_RolePlaySilhouette(u8 taskId)
{
u8 isBackPic;
u32 personality;
u32 otId;
u16 species;
s16 xOffset;
u32 priority;
u8 spriteId;
s16 coord1, coord2;
GetAnimBattlerSpriteId(ANIM_ATTACKER);
if (IsContest())
{
isBackPic = TRUE;
personality = gContestResources->moveAnim->targetPersonality;
otId = gContestResources->moveAnim->otId;
species = gContestResources->moveAnim->targetSpecies;
xOffset = 20;
priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
}
else
{
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
{
isBackPic = 0;
personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_PERSONALITY);
otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_OT_ID);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies == SPECIES_NONE)
{
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_SPECIES);
else
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_SPECIES);
}
else
{
species = gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies;
}
xOffset = 20;
priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
}
else
{
isBackPic = 1;
personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_PERSONALITY);
otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_OT_ID);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies == SPECIES_NONE)
{
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_SPECIES);
else
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_SPECIES);
}
else
{
species = gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies;
}
xOffset = -20;
priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
}
}
coord1 = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X);
coord2 = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y);
spriteId = CreateAdditionalMonSpriteForMoveAnim(species, isBackPic, 0, coord1 + xOffset, coord2, 5, personality, otId, gBattleAnimTarget, TRUE);
gSprites[spriteId].oam.priority = priority;
gSprites[spriteId].oam.objMode = ST_OAM_OBJ_BLEND;
FillPalette(RGB_WHITE, (gSprites[spriteId].oam.paletteNum << 4) + 0x100, 32);
gSprites[spriteId].oam.priority = priority;
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL);
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[1], 16 - gTasks[taskId].data[1]));
gTasks[taskId].data[0] = spriteId;
gTasks[taskId].func = AnimTask_RolePlaySilhouette_Step1;
}
static void AnimTask_RolePlaySilhouette_Step1(u8 taskId)
{
if (gTasks[taskId].data[10]++ > 1)
{
gTasks[taskId].data[10] = 0;
gTasks[taskId].data[1]++;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[1], 16 - gTasks[taskId].data[1]));
if (gTasks[taskId].data[1] == 10)
{
gTasks[taskId].data[10] = 256;
gTasks[taskId].data[11] = 256;
gTasks[taskId].func = AnimTask_RolePlaySilhouette_Step2;
}
}
}
static void AnimTask_RolePlaySilhouette_Step2(u8 taskId)
{
u8 spriteId = gTasks[taskId].data[0];
gTasks[taskId].data[10] -= 16;
gTasks[taskId].data[11] += 128;
gSprites[spriteId].oam.affineMode |= ST_OAM_AFFINE_DOUBLE_MASK;
TrySetSpriteRotScale(&gSprites[spriteId], TRUE, gTasks[taskId].data[10], gTasks[taskId].data[11], 0);
if (++gTasks[taskId].data[12] == 9)
{
ResetSpriteRotScale_PreserveAffine(&gSprites[spriteId]);
DestroySpriteAndFreeResources_(&gSprites[spriteId]);
gTasks[taskId].func = DestroyAnimVisualTaskAndDisableBlend;
}
}
// Performs a wavy transformation on the mon's sprite, and fades out.
// arg 0: which battler
void AnimTask_AcidArmor(u8 taskId)
{
u8 battler;
u16 bgX, bgY;
s16 y, i;
struct ScanlineEffectParams scanlineParams;
struct Task *task = &gTasks[taskId];
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
battler = gBattleAnimAttacker;
else
battler = gBattleAnimTarget;
task->data[0] = 0;
task->data[1] = 0;
task->data[2] = 0;
task->data[3] = 16;
task->data[4] = 0;
task->data[5] = battler;
task->data[6] = 32;
task->data[7] = 0;
task->data[8] = 24;
if (GetBattlerSide(battler) == B_SIDE_OPPONENT)
task->data[8] *= -1;
task->data[13] = GetBattlerYCoordWithElevation(battler) - 34;
if (task->data[13] < 0)
task->data[13] = 0;
task->data[14] = task->data[13] + 66;
task->data[15] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
if (GetBattlerSpriteBGPriorityRank(battler) == 1)
{
scanlineParams.dmaDest = &REG_BG1HOFS;
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1);
bgX = gBattle_BG1_X;
bgY = gBattle_BG1_Y;
}
else
{
scanlineParams.dmaDest = &REG_BG2HOFS;
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2);
bgX = gBattle_BG2_X;
bgY = gBattle_BG2_Y;
}
for (y = 0, i = 0; y < 160; y++, i += 2)
{
gScanlineEffectRegBuffers[0][i] = bgX;
gScanlineEffectRegBuffers[1][i] = bgX;
gScanlineEffectRegBuffers[0][i + 1] = bgY;
gScanlineEffectRegBuffers[1][i + 1] = bgY;
}
scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_32BIT;
scanlineParams.initState = 1;
scanlineParams.unused9 = 0;
ScanlineEffect_SetParams(scanlineParams);
task->func = AnimTask_AcidArmor_Step;
}
static void AnimTask_AcidArmor_Step(u8 taskId)
{
struct Task *task;
s16 var1;
s16 var2;
s16 bgX, bgY;
s16 offset;
s16 var0;
s16 i;
s16 sineIndex;
s16 var3;
task = &gTasks[taskId];
if (GetBattlerSpriteBGPriorityRank(task->data[5]) == 1)
{
bgX = gBattle_BG1_X;
bgY = gBattle_BG1_Y;
}
else
{
bgX = gBattle_BG2_X;
bgY = gBattle_BG2_Y;
}
switch (task->data[0])
{
case 0:
offset = task->data[14] * 2;
var1 = 0;
var2 = 0;
i = 0;
task->data[1] = (task->data[1] + 2) & 0xFF;
sineIndex = task->data[1];
task->data[9] = 0x7E0 / task->data[6];
task->data[10] = -((task->data[7] * 2) / task->data[9]);
task->data[11] = task->data[7];
var3 = task->data[11] >> 5;
task->data[12] = var3;
var0 = task->data[14];
while (var0 > task->data[13])
{
gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][offset + 1] = (i - var2) + bgY;
gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][offset] = bgX + var3 + (gSineTable[sineIndex] >> 5);
sineIndex = (sineIndex + 10) & 0xFF;
task->data[11] += task->data[10];
var3 = task->data[11] >> 5;
task->data[12] = var3;
i++;
offset -= 2;
var1 += task->data[6];
var2 = var1 >> 5;
var0--;
}
var0 *= 2;
while (var0 >= 0)
{
gScanlineEffectRegBuffers[0][var0] = bgX + 240;
gScanlineEffectRegBuffers[1][var0] = bgX + 240;
var0 -= 2;
}
if (++task->data[6] > 63)
{
task->data[6] = 64;
task->data[2]++;
if (task->data[2] & 1)
task->data[3]--;
else
task->data[4]++;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4]));
if (task->data[3] == 0 && task->data[4] == 16)
{
task->data[2] = 0;
task->data[3] = 0;
task->data[0]++;
}
}
else
{
task->data[7] += task->data[8];
}
break;
case 1:
if (++task->data[2] > 12)
{
gScanlineEffect.state = 3;
task->data[2] = 0;
task->data[0]++;
}
break;
case 2:
task->data[2]++;
if (task->data[2] & 1)
task->data[3]++;
else
task->data[4]--;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4]));
if (task->data[3] == 16 && task->data[4] == 0)
{
task->data[2] = 0;
task->data[3] = 0;
task->data[0]++;
}
break;
case 3:
DestroyAnimVisualTask(taskId);
break;
}
}
// Runs an affine animation that makes it look like the mon is inhaling deeply.
// arg 0: which battler
void AnimTask_DeepInhale(u8 taskId)
{
struct Task *task = &gTasks[taskId];
task->data[0] = 0;
task->data[15] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
PrepareAffineAnimInTaskData(&gTasks[taskId], task->data[15], gDeepInhaleAffineAnimCmds);
task->func = AnimTask_DeepInhale_Step;
}
static void AnimTask_DeepInhale_Step(u8 taskId)
{
u16 var0;
struct Task *task = &gTasks[taskId];
var0 = task->data[0];
task->data[0]++;
var0 -= 20;
if (var0 < 23)
{
if (++task->data[1] > 1)
{
task->data[1] = 0;
task->data[2]++;
if (task->data[2] & 1)
gSprites[task->data[15]].x2 = 1;
else
gSprites[task->data[15]].x2 = -1;
}
}
else
{
gSprites[task->data[15]].x2 = 0;
}
if (!RunAffineAnimFromTaskData(&gTasks[taskId]))
DestroyAnimVisualTask(taskId);
}
static void InitYawnCloudPosition(struct Sprite *sprite, s16 startX, s16 startY, s16 destX, s16 destY, u16 duration)
{
sprite->x = startX;
sprite->y = startY;
sprite->data[4] = startX << 4;
sprite->data[5] = startY << 4;
sprite->data[6] = ((destX - startX) << 4) / duration;
sprite->data[7] = ((destY - startY) << 4) / duration;
}
static void UpdateYawnCloudPosition(struct Sprite *sprite)
{
sprite->data[4] += sprite->data[6];
sprite->data[5] += sprite->data[7];
sprite->x = sprite->data[4] >> 4;
sprite->y = sprite->data[5] >> 4;
}
// Drifts a cloud in a wavy path towards the target mon.
// arg 0: which affine anim
static void AnimYawnCloud(struct Sprite *sprite)
{
s16 destX = sprite->x;
s16 destY = sprite->y;
SetSpriteCoordsToAnimAttackerCoords(sprite);
StartSpriteAffineAnim(sprite, gBattleAnimArgs[0]);
InitYawnCloudPosition(sprite, sprite->x, sprite->y, destX, destY, 64);
sprite->data[0] = 0;
sprite->callback = AnimYawnCloud_Step;
}
static void AnimYawnCloud_Step(struct Sprite *sprite)
{
int index;
sprite->data[0]++;
index = (sprite->data[0] * 8) & 0xFF;
UpdateYawnCloudPosition(sprite);
sprite->y2 = Sin(index, 8);
if (sprite->data[0] > 58)
{
if (++sprite->data[1] > 1)
{
sprite->data[1] = 0;
sprite->data[2]++;
sprite->invisible = sprite->data[2] & 1;
if (sprite->data[2] > 3)
DestroySpriteAndMatrix(sprite);
}
}
}
// Animates a cloud coming from the smoke ball.
// arg 0: ?
// arg 1: initial x pixel offset
// arg 2: initial y pixel offset
// arg 3: time until destroyed
static void AnimSmokeBallEscapeCloud(struct Sprite *sprite)
{
sprite->data[0] = gBattleAnimArgs[3];
StartSpriteAffineAnim(sprite, gBattleAnimArgs[0]);
if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER)
gBattleAnimArgs[1] = -gBattleAnimArgs[1];
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) + gBattleAnimArgs[1];
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[2];
sprite->callback = DestroyAnimSpriteAfterTimer;
}
static void AnimTask_SlideMonForFocusBand_Step2(u8 taskId)
{
u16 var0 = 0;
u16 var1 = 0;
gTasks[taskId].data[0]--;
if ((gTasks[taskId].data[6] & 0x8000) && (--gTasks[taskId].data[1] == -1))
{
if (gTasks[taskId].data[9] == 0)
{
gTasks[taskId].data[9] = gTasks[taskId].data[4];
gTasks[taskId].data[4] = -gTasks[taskId].data[4];
}
else
{
gTasks[taskId].data[9] = 0;
}
if (gTasks[taskId].data[10] == 0)
{
gTasks[taskId].data[10] = gTasks[taskId].data[5];
gTasks[taskId].data[5] = -gTasks[taskId].data[5];
}
else
{
gTasks[taskId].data[10] = 0;
}
gTasks[taskId].data[1] = gTasks[taskId].data[13];
}
var0 = gTasks[taskId].data[7];
var1 = gTasks[taskId].data[8];
if (gTasks[taskId].data[2] & 0x8000)
gSprites[gTasks[taskId].data[15]].x2 = gTasks[taskId].data[9] - (var0 >> 8);
else
gSprites[gTasks[taskId].data[15]].x2 = gTasks[taskId].data[9] + (var0 >> 8);
if (gTasks[taskId].data[3] & 0x8000)
gSprites[gTasks[taskId].data[15]].y2 = gTasks[taskId].data[10] - (var1 >> 8);
else
gSprites[gTasks[taskId].data[15]].y2 = gTasks[taskId].data[10] + (var1 >> 8);
if (gTasks[taskId].data[0] < 1)
{
DestroyTask(taskId);
gAnimVisualTaskCount--;
}
}
static void AnimTask_SlideMonForFocusBand_Step1(u8 taskId)
{
u16 var0 = 0;
u16 var1 = 0;
gTasks[taskId].data[0]--;
if ((gTasks[taskId].data[6] & 0x8000) && (--gTasks[taskId].data[1] == -1))
{
if (gTasks[taskId].data[9] == 0)
{
gTasks[taskId].data[9] = gTasks[taskId].data[4];
gTasks[taskId].data[4] = -gTasks[taskId].data[4];
}
else
{
gTasks[taskId].data[9] = var0;
}
if (gTasks[taskId].data[10] == 0)
{
gTasks[taskId].data[10] = gTasks[taskId].data[5];
gTasks[taskId].data[5] = -gTasks[taskId].data[5];
}
else
{
gTasks[taskId].data[10] = 0;
}
gTasks[taskId].data[1] = gTasks[taskId].data[13];
}
var0 = (gTasks[taskId].data[2] & 0x7FFF) + gTasks[taskId].data[7];
var1 = (gTasks[taskId].data[3] & 0x7FFF) + gTasks[taskId].data[8];
if (gTasks[taskId].data[2] & 0x8000)
gSprites[gTasks[taskId].data[15]].x2 = gTasks[taskId].data[9] - (var0 >> 8);
else
gSprites[gTasks[taskId].data[15]].x2 = gTasks[taskId].data[9] + (var0 >> 8);
if (gTasks[taskId].data[3] & 0x8000)
gSprites[gTasks[taskId].data[15]].y2 = gTasks[taskId].data[10] - (var1 >> 8);
else
gSprites[gTasks[taskId].data[15]].y2 = gTasks[taskId].data[10] + (var1 >> 8);
gTasks[taskId].data[7] = var0;
gTasks[taskId].data[8] = var1;
if (gTasks[taskId].data[0] < 1)
{
gTasks[taskId].data[0] = 30;
gTasks[taskId].data[13] = 0;
gTasks[taskId].func = AnimTask_SlideMonForFocusBand_Step2;
}
}
void AnimTask_SlideMonForFocusBand(u8 taskId)
{
gTasks[taskId].data[15] = gBattlerSpriteIds[gBattleAnimAttacker];
gTasks[taskId].data[14] = gBattleAnimArgs[0];
gTasks[taskId].data[0] = gBattleAnimArgs[0];
gTasks[taskId].data[13] = gBattleAnimArgs[6];
if (gBattleAnimArgs[3])
gTasks[taskId].data[6] = gTasks[taskId].data[6] | -0x8000;
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
{
gTasks[taskId].data[2] = gBattleAnimArgs[1];
gTasks[taskId].data[3] = gBattleAnimArgs[2];
}
else
{
if (gBattleAnimArgs[1] & 0x8000)
gTasks[taskId].data[2] = gBattleAnimArgs[1] & 0x7FFF;
else
gTasks[taskId].data[2] = gBattleAnimArgs[1] | -0x8000;
if (gBattleAnimArgs[2] & 0x8000)
gTasks[taskId].data[3] = gBattleAnimArgs[2] & 0x7FFF;
else
gTasks[taskId].data[3] = gBattleAnimArgs[2] | -0x8000;
}
gTasks[taskId].data[8] = 0;
gTasks[taskId].data[7] = 0;
gTasks[taskId].data[4] = gBattleAnimArgs[4];
gTasks[taskId].data[5] = gBattleAnimArgs[5];
gTasks[taskId].func = AnimTask_SlideMonForFocusBand_Step1;
}
// Squishes the mon vertically and emits sweat droplets a few times.
// arg 0: battler
// arg 1: num squishes
void AnimTask_SquishAndSweatDroplets(u8 taskId)
{
u8 battler;
struct Task *task = &gTasks[taskId];
if (!gBattleAnimArgs[1])
DestroyAnimVisualTask(taskId);
task->data[0] = 0;
task->data[1] = 0;
task->data[2] = 0;
task->data[3] = gBattleAnimArgs[1];
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
battler = gBattleAnimAttacker;
else
battler = gBattleAnimTarget;
task->data[4] = GetBattlerSpriteCoord(battler, BATTLER_COORD_X);
task->data[5] = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y);
task->data[6] = GetBattlerSpriteSubpriority(battler);
task->data[15] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
PrepareAffineAnimInTaskData(task, task->data[15], gFacadeSquishAffineAnimCmds);
task->func = AnimTask_SquishAndSweatDroplets_Step;
}
static void AnimTask_SquishAndSweatDroplets_Step(u8 taskId)
{
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
task->data[1]++;
if (task->data[1] == 6)
CreateSweatDroplets(taskId, TRUE);
if (task->data[1] == 18)
CreateSweatDroplets(taskId, FALSE);
if (!RunAffineAnimFromTaskData(task))
{
if (--task->data[3] == 0)
{
task->data[0]++;
}
else
{
task->data[1] = 0;
PrepareAffineAnimInTaskData(task, task->data[15], gFacadeSquishAffineAnimCmds);
}
}
break;
case 1:
if (task->data[2] == 0)
DestroyAnimVisualTask(taskId);
break;
}
}
static void CreateSweatDroplets(u8 taskId, bool8 arg1)
{
u8 i;
s8 xOffset, yOffset;
struct Task *task;
s16 xCoords[4];
s16 yCoords[2];
task = &gTasks[taskId];
if (!arg1)
{
xOffset = 18;
yOffset = -20;
}
else
{
xOffset = 30;
yOffset = 20;
}
xCoords[0] = task->data[4] - xOffset;
xCoords[1] = task->data[4] - xOffset - 4;
xCoords[2] = task->data[4] + xOffset;
xCoords[3] = task->data[4] + xOffset + 4;
yCoords[0] = task->data[5] + yOffset;
yCoords[1] = task->data[5] + yOffset + 6;
for (i = 0; i < 4; i++)
{
u8 spriteId = CreateSprite(&gFacadeSweatDropSpriteTemplate, xCoords[i], yCoords[i & 1], task->data[6] - 5);
if (spriteId != MAX_SPRITES)
{
gSprites[spriteId].data[0] = 0;
gSprites[spriteId].data[1] = i < 2 ? -2 : 2;
gSprites[spriteId].data[2] = -1;
gSprites[spriteId].data[3] = taskId;
gSprites[spriteId].data[4] = 2;
task->data[2]++;
}
}
}
static void AnimFacadeSweatDrop(struct Sprite *sprite)
{
sprite->x += sprite->data[1];
sprite->y += sprite->data[2];
if (++sprite->data[0] > 6)
{
gTasks[sprite->data[3]].data[sprite->data[4]]--;
DestroySprite(sprite);
}
}
// Blends the mon sprite's color with a rotating set of colors.
// arg 0: battler
// arg 1: duration
void AnimTask_FacadeColorBlend(u8 taskId)
{
u8 spriteId;
gTasks[taskId].data[0] = 0;
gTasks[taskId].data[1] = gBattleAnimArgs[1];
spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
gTasks[taskId].data[2] = 0x100 + gSprites[spriteId].oam.paletteNum * 16;
gTasks[taskId].func = AnimTask_FacadeColorBlend_Step;
}
static void AnimTask_FacadeColorBlend_Step(u8 taskId)
{
if (gTasks[taskId].data[1])
{
BlendPalette(gTasks[taskId].data[2], 16, 8, gFacadeBlendColors[gTasks[taskId].data[0]]);
if (++gTasks[taskId].data[0] > 23)
gTasks[taskId].data[0] = 0;
gTasks[taskId].data[1]--;
}
else
{
BlendPalette(gTasks[taskId].data[2], 16, 0, RGB(0, 0, 0));
DestroyAnimVisualTask(taskId);
}
}
// The sliding circle effect used by Refresh and Aromatherapy
void AnimTask_StatusClearedEffect(u8 taskId)
{
StartMonScrollingBgMask(
taskId,
0,
0x1A0,
gBattleAnimAttacker,
gBattleAnimArgs[0],
10,
2,
30,
gCureBubblesGfx,
gCureBubblesTilemap,
gCureBubblesPal);
}
// Moves a noise line from the mon.
// arg 0: initial x pixel offset
// arg 1: initial y pixel offset
// arg 2: which direction (0 = upward, 1 = downward, 2 = horizontal)
static void AnimRoarNoiseLine(struct Sprite *sprite)
{
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT)
gBattleAnimArgs[0] = -gBattleAnimArgs[0];
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X) + gBattleAnimArgs[0];
sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + gBattleAnimArgs[1];
if (gBattleAnimArgs[2] == 0)
{
sprite->data[0] = 0x280;
sprite->data[1] = -0x280;
}
else if (gBattleAnimArgs[2] == 1)
{
sprite->vFlip = 1;
sprite->data[0] = 0x280;
sprite->data[1] = 0x280;
}
else
{
StartSpriteAnim(sprite, 1);
sprite->data[0] = 0x280;
}
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
{
sprite->data[0] = -sprite->data[0];
sprite->hFlip = 1;
}
sprite->callback = AnimRoarNoiseLine_Step;
}
static void AnimRoarNoiseLine_Step(struct Sprite *sprite)
{
sprite->data[6] += sprite->data[0];
sprite->data[7] += sprite->data[1];
sprite->x2 = sprite->data[6] >> 8;
sprite->y2 = sprite->data[7] >> 8;
if (++sprite->data[5] == 14)
DestroyAnimSprite(sprite);
}
// Makes a series of dots in a trail from the attacker to the target.
// arg 0: unused
void AnimTask_GlareEyeDots(u8 taskId)
{
struct Task *task = &gTasks[taskId];
if (IsContest())
{
task->data[5] = 8;
task->data[6] = 3;
task->data[7] = 1;
}
else
{
task->data[5] = 12;
task->data[6] = 3;
task->data[7] = 0;
}
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
task->data[11] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) + GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_HEIGHT) / 4;
else
task->data[11] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) - GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_HEIGHT) / 4;
task->data[12] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET) - GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_HEIGHT) / 4;
task->data[13] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2);
task->data[14] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET);
task->func = AnimTask_GlareEyeDots_Step;
}
static void AnimTask_GlareEyeDots_Step(u8 taskId)
{
u8 i;
s16 x, y;
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
if (++task->data[1] > 3)
{
task->data[1] = 0;
GetGlareEyeDotCoords(
task->data[11],
task->data[12],
task->data[13],
task->data[14],
task->data[5],
task->data[2],
&x,
&y);
for (i = 0; i < 2; i++)
{
u8 spriteId = CreateSprite(&gGlareEyeDotSpriteTemplate, x, y, 35);
if (spriteId != MAX_SPRITES)
{
if (task->data[7] == 0)
{
if (i == 0)
gSprites[spriteId].x2 = gSprites[spriteId].y2 = -task->data[6];
else
gSprites[spriteId].x2 = gSprites[spriteId].y2 = task->data[6];
}
else
{
if (i == 0)
{
gSprites[spriteId].x2 = -task->data[6];
gSprites[spriteId].y2 = task->data[6];
}
else
{
gSprites[spriteId].x2 = task->data[6];
gSprites[spriteId].y2 = -task->data[6];
}
}
gSprites[spriteId].data[0] = 0;
gSprites[spriteId].data[1] = taskId;
gSprites[spriteId].data[2] = 10;
task->data[10]++;
}
}
if (task->data[2] == task->data[5])
task->data[0]++;
task->data[2]++;
}
break;
case 1:
if (task->data[10] == 0)
DestroyAnimVisualTask(taskId);
break;
}
}
static void GetGlareEyeDotCoords(s16 arg0, s16 arg1, s16 arg2, s16 arg3, u8 arg4, u8 arg5, s16 *x, s16 *y)
{
int x2;
int y2;
if (arg5 == 0)
{
*x = arg0;
*y = arg1;
return;
}
if (arg5 >= arg4)
{
*x = arg2;
*y = arg3;
return;
}
arg4--;
x2 = (arg0 << 8) + arg5 * (((arg2 - arg0) << 8) / arg4);
y2 = (arg1 << 8) + arg5 * (((arg3 - arg1) << 8) / arg4);
*x = x2 >> 8;
*y = y2 >> 8;
}
static void AnimGlareEyeDot(struct Sprite *sprite)
{
if (++sprite->data[0] > 36)
{
gTasks[sprite->data[1]].data[sprite->data[2]]--;
DestroySprite(sprite);
}
}
// Moves a pawprint in a straight line.
// arg 0: initial x position
// arg 1: initial y position
// arg 2: destination x position
// arg 3: destination y position
// arg 4: duration
static void AnimAssistPawprint(struct Sprite *sprite)
{
sprite->x = gBattleAnimArgs[0];
sprite->y = gBattleAnimArgs[1];
sprite->data[2] = gBattleAnimArgs[2];
sprite->data[4] = gBattleAnimArgs[3];
sprite->data[0] = gBattleAnimArgs[4];
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
sprite->callback = InitAndRunAnimFastLinearTranslation;
}
// Moves a ball in an arc twoards the target, and rotates the ball while arcing.
// No args.
void AnimTask_BarrageBall(u8 taskId)
{
struct Task *task = &gTasks[taskId];
task->data[11] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
task->data[12] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET);
task->data[13] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2);
task->data[14] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_HEIGHT) / 4;
task->data[15] = CreateSprite(&gBarrageBallSpriteTemplate, task->data[11], task->data[12], GetBattlerSpriteSubpriority(gBattleAnimTarget) - 5);
if (task->data[15] != MAX_SPRITES)
{
gSprites[task->data[15]].data[0] = 16;
gSprites[task->data[15]].data[2] = task->data[13];
gSprites[task->data[15]].data[4] = task->data[14];
gSprites[task->data[15]].data[5] = -32;
InitAnimArcTranslation(&gSprites[task->data[15]]);
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT)
StartSpriteAffineAnim(&gSprites[task->data[15]], 1);
task->func = AnimTask_BarrageBall_Step;
}
else
{
DestroyAnimVisualTask(taskId);
}
}
static void AnimTask_BarrageBall_Step(u8 taskId)
{
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
if (++task->data[1] > 1)
{
task->data[1] = 0;
TranslateAnimHorizontalArc(&gSprites[task->data[15]]);
if (++task->data[2] > 7)
task->data[0]++;
}
break;
case 1:
if (TranslateAnimHorizontalArc(&gSprites[task->data[15]]))
{
task->data[1] = 0;
task->data[2] = 0;
task->data[0]++;
}
break;
case 2:
if (++task->data[1] > 1)
{
task->data[1] = 0;
task->data[2]++;
gSprites[task->data[15]].invisible = task->data[2] & 1;
if (task->data[2] == 16)
{
FreeOamMatrix(gSprites[task->data[15]].oam.matrixNum);
DestroySprite(&gSprites[task->data[15]]);
task->data[0]++;
}
}
break;
case 3:
DestroyAnimVisualTask(taskId);
break;
}
}
// Moves a hand back and forth in a squishing motion.
// arg 0: which battler
// arg 1: horizontal flip
// arg 2: num squishes
static void AnimSmellingSaltsHand(struct Sprite *sprite)
{
u8 battler;
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
battler = gBattleAnimAttacker;
else
battler = gBattleAnimTarget;
sprite->oam.tileNum += 16;
sprite->data[6] = gBattleAnimArgs[2];
sprite->data[7] = gBattleAnimArgs[1] == 0 ? -1 : 1;
sprite->y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET);
if (gBattleAnimArgs[1] == 0)
{
sprite->oam.matrixNum |= ST_OAM_HFLIP;
sprite->x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_LEFT) - 8;
}
else
{
sprite->x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_RIGHT) + 8;
}
sprite->callback = AnimSmellingSaltsHand_Step;
}
static void AnimSmellingSaltsHand_Step(struct Sprite *sprite)
{
switch (sprite->data[0])
{
case 0:
if (++sprite->data[1] > 1)
{
sprite->data[1] = 0;
sprite->x2 += sprite->data[7];
if (++sprite->data[2] == 12)
sprite->data[0]++;
}
break;
case 1:
if (++sprite->data[1] == 8)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 2:
sprite->x2 -= sprite->data[7] * 4;
if (++sprite->data[1] == 6)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 3:
sprite->x2 += sprite->data[7] * 3;
if (++sprite->data[1] == 8)
{
if (--sprite->data[6])
{
sprite->data[1] = 0;
sprite->data[0]--;
}
else
{
DestroyAnimSprite(sprite);
}
}
break;
}
}
// Squishes the mon horizontally a few times.
// arg 0: which mon
// arg 1: number of squishes
void AnimTask_SmellingSaltsSquish(u8 taskId)
{
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
{
DestroyAnimVisualTask(taskId);
}
else
{
gTasks[taskId].data[0] = gBattleAnimArgs[1];
gTasks[taskId].data[15] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
PrepareAffineAnimInTaskData(&gTasks[taskId], gTasks[taskId].data[15], gSmellingSaltsSquishAffineAnimCmds);
gTasks[taskId].func = AnimTask_SmellingSaltsSquish_Step;
}
}
static void AnimTask_SmellingSaltsSquish_Step(u8 taskId)
{
struct Task *task = &gTasks[taskId];
if (++task->data[1] > 1)
{
task->data[1] = 0;
if (!(task->data[2] & 1))
gSprites[task->data[15]].x2 = 2;
else
gSprites[task->data[15]].x2 = -2;
}
if (!RunAffineAnimFromTaskData(task))
{
gSprites[task->data[15]].x2 = 0;
if (--task->data[0])
{
PrepareAffineAnimInTaskData(&gTasks[taskId], gTasks[taskId].data[15], gSmellingSaltsSquishAffineAnimCmds);
task->data[1] = 0;
task->data[2] = 0;
}
else
{
DestroyAnimVisualTask(taskId);
}
}
}
// Blinks an exclamation image over the mon a few times.
// arg 0: which mon
// arg 1: blink delay
// arg 2: number of blinks
static void AnimSmellingSaltExclamation(struct Sprite *sprite)
{
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
sprite->y = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_TOP);
}
else
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2);
sprite->y = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_TOP);
}
if (sprite->y < 8)
sprite->y = 8;
sprite->data[0] = 0;
sprite->data[1] = gBattleAnimArgs[1];
sprite->data[2] = 0;
sprite->data[3] = gBattleAnimArgs[2];
sprite->callback = AnimSmellingSaltExclamation_Step;
}
static void AnimSmellingSaltExclamation_Step(struct Sprite *sprite)
{
if (++sprite->data[0] >= sprite->data[1])
{
sprite->data[0] = 0;
sprite->data[2] = (sprite->data[2] + 1) & 1;
sprite->invisible = sprite->data[2];
if (sprite->data[2] && --sprite->data[3] == 0)
DestroyAnimSprite(sprite);
}
}
// Claps a hand several times.
// arg 0: which hand
// arg 1:
static void AnimHelpingHandClap(struct Sprite *sprite)
{
if (gBattleAnimArgs[0] == 0)
{
sprite->oam.matrixNum |= ST_OAM_HFLIP;
sprite->x = 100;
sprite->data[7] = 1;
}
else
{
sprite->x = 140;
sprite->data[7] = -1;
}
sprite->y = 56;
sprite->callback = AnimHelpingHandClap_Step;
}
static void AnimHelpingHandClap_Step(struct Sprite *sprite)
{
switch (sprite->data[0])
{
case 0:
sprite->y -= sprite->data[7] * 2;
if (sprite->data[1] & 1)
sprite->x -= sprite->data[7] * 2;
if (++sprite->data[1] == 9)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 1:
if (++sprite->data[1] == 4)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 2:
sprite->data[1]++;
sprite->y += sprite->data[7] * 3;
sprite->x2 = sprite->data[7] * (gSineTable[sprite->data[1] * 10] >> 3);
if (sprite->data[1] == 12)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 3:
if (++sprite->data[1] == 2)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 4:
sprite->data[1]++;
sprite->y -= sprite->data[7] * 3;
sprite->x2 = sprite->data[7] * (gSineTable[sprite->data[1] * 10] >> 3);
if (sprite->data[1] == 12)
sprite->data[0]++;
break;
case 5:
sprite->data[1]++;
sprite->y += sprite->data[7] * 3;
sprite->x2 = sprite->data[7] * (gSineTable[sprite->data[1] * 10] >> 3);
if (sprite->data[1] == 15)
sprite->oam.tileNum += 16;
if (sprite->data[1] == 18)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 6:
sprite->x += sprite->data[7] * 6;
if (++sprite->data[1] == 9)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 7:
sprite->x += sprite->data[7] * 2;
if (++sprite->data[1] == 1)
{
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 8:
sprite->x -= sprite->data[7] * 3;
if (++sprite->data[1] == 5)
DestroyAnimSprite(sprite);
break;
}
}
// Repeatedly moves the attacking mon in a horizontal lunging motion.
// No args.
void AnimTask_HelpingHandAttackerMovement(u8 taskId)
{
struct Task *task = &gTasks[taskId];
task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER);
if (!IsContest())
{
if (IsDoubleBattle() == TRUE)
{
int attackerX = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X);
int partnerX = GetBattlerSpriteCoord(BATTLE_PARTNER(gBattleAnimAttacker), BATTLER_COORD_X);
if (attackerX > partnerX)
task->data[14] = 1;
else
task->data[14] = -1;
}
else
{
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
task->data[14] = -1;
else
task->data[14] = 1;
}
}
else
{
task->data[14] = 1;
}
task->func = AnimTask_HelpingHandAttackerMovement_Step;
}
static void AnimTask_HelpingHandAttackerMovement_Step(u8 taskId)
{
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
if (++task->data[1] == 13)
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 1:
gSprites[task->data[15]].x2 -= task->data[14] * 3;
if (++task->data[1] == 6)
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 2:
gSprites[task->data[15]].x2 += task->data[14] * 3;
if (++task->data[1] == 6)
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 3:
if (++task->data[1] == 2)
{
task->data[1] = 0;
if (task->data[2] == 0)
{
task->data[2]++;
task->data[0] = 1;
}
else
{
task->data[0]++;
}
}
break;
case 4:
gSprites[task->data[15]].x2 += task->data[14];
if (++task->data[1] == 3)
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 5:
if (++task->data[1] == 6)
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 6:
gSprites[task->data[15]].x2 -= task->data[14] * 4;
if (++task->data[1] == 5)
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 7:
gSprites[task->data[15]].x2 += task->data[14] * 4;
if (++task->data[1] == 5)
{
task->data[1] = 0;
task->data[0]++;
}
break;
case 8:
gSprites[task->data[15]].x2 = 0;
DestroyAnimVisualTask(taskId);
break;
}
}
// Moves a magnifying glass around in straight lines.
// arg 0: magnifying glass target mon
static void AnimForesightMagnifyingGlass(struct Sprite *sprite)
{
if (gBattleAnimArgs[0] == ANIM_ATTACKER)
{
InitSpritePosToAnimAttacker(sprite, TRUE);
sprite->data[7] = gBattleAnimAttacker;
}
else
{
sprite->data[7] = gBattleAnimTarget;
}
if (GetBattlerSide(sprite->data[7]) == B_SIDE_OPPONENT)
sprite->oam.matrixNum = ST_OAM_HFLIP;
sprite->oam.priority = GetBattlerSpriteBGPriority(sprite->data[7]);
sprite->oam.objMode = ST_OAM_OBJ_BLEND;
sprite->callback = AnimForesightMagnifyingGlass_Step;
}
static void AnimForesightMagnifyingGlass_Step(struct Sprite *sprite)
{
u16 x, y;
switch (sprite->data[5])
{
case 0:
switch (sprite->data[6])
{
default:
sprite->data[6] = 0;
case 0:
case 4:
x = GetBattlerSpriteCoordAttr(sprite->data[7], BATTLER_COORD_ATTR_RIGHT) - 4;
y = GetBattlerSpriteCoordAttr(sprite->data[7], BATTLER_COORD_ATTR_BOTTOM) - 4;
break;
case 1:
x = GetBattlerSpriteCoordAttr(sprite->data[7], BATTLER_COORD_ATTR_RIGHT) - 4;
y = GetBattlerSpriteCoordAttr(sprite->data[7], BATTLER_COORD_ATTR_TOP) + 4;
break;
case 2:
x = GetBattlerSpriteCoordAttr(sprite->data[7], BATTLER_COORD_ATTR_LEFT) + 4;
y = GetBattlerSpriteCoordAttr(sprite->data[7], BATTLER_COORD_ATTR_BOTTOM) - 4;
break;
case 3:
x = GetBattlerSpriteCoordAttr(sprite->data[7], BATTLER_COORD_ATTR_LEFT) + 4;
y = GetBattlerSpriteCoordAttr(sprite->data[7], BATTLER_COORD_ATTR_TOP) - 4;
break;
case 5:
x = GetBattlerSpriteCoord(sprite->data[7], BATTLER_COORD_X_2);
y = GetBattlerSpriteCoord(sprite->data[7], BATTLER_COORD_Y_PIC_OFFSET);
break;
}
if (sprite->data[6] == 4)
sprite->data[0] = 24;
else if (sprite->data[6] == 5)
sprite->data[0] = 6;
else
sprite->data[0] = 12;
sprite->data[1] = sprite->x;
sprite->data[2] = x;
sprite->data[3] = sprite->y;
sprite->data[4] = y;
InitAnimLinearTranslation(sprite);
sprite->data[5]++;
break;
case 1:
if (AnimTranslateLinear(sprite))
{
switch (sprite->data[6])
{
default:
sprite->x += sprite->x2;
sprite->y += sprite->y2;
sprite->y2 = 0;
sprite->x2 = 0;
sprite->data[0] = 0;
sprite->data[5]++;
sprite->data[6]++;
break;
case 4:
sprite->x += sprite->x2;
sprite->y += sprite->y2;
sprite->y2 = 0;
sprite->x2 = 0;
sprite->data[5] = 0;
sprite->data[6]++;
break;
case 5:
sprite->data[0] = 0;
sprite->data[1] = 16;
sprite->data[2] = 0;
sprite->data[5] = 3;
break;
}
}
break;
case 2:
if (++sprite->data[0] == 4)
sprite->data[5] = 0;
break;
case 3:
if (!(sprite->data[0] & 1))
sprite->data[1]--;
else
sprite->data[2]++;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[1], sprite->data[2]));
if (++sprite->data[0] == 32)
{
sprite->invisible = TRUE;
sprite->data[5]++;
}
break;
case 4:
DestroyAnimSprite(sprite);
break;
}
}
static void AnimMeteorMashStar_Step(struct Sprite *sprite)
{
sprite->x2 = ((sprite->data[2] - sprite->data[0]) * sprite->data[5]) / sprite->data[4];
sprite->y2 = ((sprite->data[3] - sprite->data[1]) * sprite->data[5]) / sprite->data[4];
if (!(sprite->data[5] & 1))
{
CreateSprite(
&gMiniTwinklingStarSpriteTemplate,
sprite->x + sprite->x2,
sprite->y + sprite->y2, 5);
}
if (sprite->data[5] == sprite->data[4])
DestroyAnimSprite(sprite);
sprite->data[5]++;
}
// Moves a shooting star across the screen that leaves little twinkling stars behind its path.
// arg 0: initial x pixel offset
// arg 1: initial y pixel offset
// arg 2: destination x pixel offset
// arg 3: destination y pixel offset
// arg 4: duration
static void AnimMeteorMashStar(struct Sprite *sprite)
{
s16 y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); // unused local variable
s16 x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); // unused local variable
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER || IsContest())
{
sprite->data[0] = sprite->x - gBattleAnimArgs[0];
sprite->data[2] = sprite->x - gBattleAnimArgs[2];
}
else
{
sprite->data[0] = sprite->x + gBattleAnimArgs[0];
sprite->data[2] = sprite->x + gBattleAnimArgs[2];
}
sprite->data[1] = sprite->y + gBattleAnimArgs[1];
sprite->data[3] = sprite->y + gBattleAnimArgs[3];
sprite->data[4] = gBattleAnimArgs[4];
sprite->x = sprite->data[0];
sprite->y = sprite->data[1];
sprite->callback = AnimMeteorMashStar_Step;
}
void AnimTask_MonToSubstitute(u8 taskId)
{
int i;
u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER);
if (gTasks[taskId].data[0] == 0)
{
PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_NORMAL);
gTasks[taskId].data[1] = 0x100;
gTasks[taskId].data[2] = 0x100;
gTasks[taskId].data[0]++;
}
else if (gTasks[taskId].data[0] == 1)
{
gTasks[taskId].data[1] += 0x60;
gTasks[taskId].data[2] -= 0xD;
SetSpriteRotScale(spriteId, gTasks[taskId].data[1], gTasks[taskId].data[2], 0);
if (++gTasks[taskId].data[3] == 9)
{
gTasks[taskId].data[3] = 0;
ResetSpriteRotScale(spriteId);
gSprites[spriteId].invisible = TRUE;
gTasks[taskId].data[0]++;
}
}
else
{
LoadBattleMonGfxAndAnimate(gBattleAnimAttacker, 0, spriteId);
if (IsContest())
{
gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].affineAnims = gAffineAnims_BattleSpriteContest;
StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[gBattleAnimAttacker]], BATTLER_AFFINE_NORMAL);
}
for (i = 0; i < NUM_TASK_DATA; i++)
gTasks[taskId].data[i] = 0;
gTasks[taskId].func = AnimTask_MonToSubstituteDoll;
}
}
static void AnimTask_MonToSubstituteDoll(u8 taskId)
{
u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER);
switch (gTasks[taskId].data[0])
{
case 0:
gSprites[spriteId].y2 = -200;
gSprites[spriteId].x2 = 200;
gSprites[spriteId].invisible = FALSE;
gTasks[taskId].data[10] = 0;
gTasks[taskId].data[0]++;
break;
case 1:
gTasks[taskId].data[10] += 112;
gSprites[spriteId].y2 += gTasks[taskId].data[10] >> 8;
if (gSprites[spriteId].y + gSprites[spriteId].y2 >= -32)
gSprites[spriteId].x2 = 0;
if (gSprites[spriteId].y2 > 0)
gSprites[spriteId].y2 = 0;
if (gSprites[spriteId].y2 == 0)
{
PlaySE12WithPanning(SE_M_BUBBLE2, BattleAnimAdjustPanning(-64));
gTasks[taskId].data[10] -= 0x800;
gTasks[taskId].data[0]++;
}
break;
case 2:
gTasks[taskId].data[10] -= 112;
if (gTasks[taskId].data[10] < 0)
gTasks[taskId].data[10] = 0;
gSprites[spriteId].y2 -= gTasks[taskId].data[10] >> 8;
if (gTasks[taskId].data[10] == 0)
gTasks[taskId].data[0]++;
break;
case 3:
gTasks[taskId].data[10] += 112;
gSprites[spriteId].y2 += gTasks[taskId].data[10] >> 8;
if (gSprites[spriteId].y2 > 0)
gSprites[spriteId].y2 = 0;
if (gSprites[spriteId].y2 == 0)
{
PlaySE12WithPanning(SE_M_BUBBLE2, BattleAnimAdjustPanning(-64));
DestroyAnimVisualTask(taskId);
}
break;
}
}
// Moves down an X that flickers and disappears.
// No args.
static void AnimBlockX(struct Sprite *sprite)
{
s16 y;
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
{
sprite->subpriority = GetBattlerSpriteSubpriority(gBattleAnimTarget) - 2;
y = -144;
}
else
{
sprite->subpriority = GetBattlerSpriteSubpriority(gBattleAnimTarget) + 2;
y = -96;
}
sprite->y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET);
sprite->y2 = y;
sprite->callback = AnimBlockX_Step;
}
static void AnimBlockX_Step(struct Sprite *sprite)
{
switch (sprite->data[0])
{
case 0:
sprite->y2 += 10;
if (sprite->y2 >= 0)
{
PlaySE12WithPanning(SE_M_SKETCH, BattleAnimAdjustPanning(63));
sprite->y2 = 0;
sprite->data[0]++;
}
break;
case 1:
sprite->data[1] += 4;
sprite->y2 = -(gSineTable[sprite->data[1]] >> 3);
if (sprite->data[1] > 0x7F)
{
PlaySE12WithPanning(SE_M_SKETCH, BattleAnimAdjustPanning(63));
sprite->data[1] = 0;
sprite->y2 = 0;
sprite->data[0]++;
}
break;
case 2:
sprite->data[1] += 6;
sprite->y2 = -(gSineTable[sprite->data[1]] >> 4);
if (sprite->data[1] > 0x7F)
{
sprite->data[1] = 0;
sprite->y2 = 0;
sprite->data[0]++;
}
break;
case 3:
if (++sprite->data[1] > 8)
{
PlaySE12WithPanning(SE_M_LEER, BattleAnimAdjustPanning(63));
sprite->data[1] = 0;
sprite->data[0]++;
}
break;
case 4:
if (++sprite->data[1] > 8)
{
sprite->data[1] = 0;
sprite->data[2]++;
sprite->invisible = sprite->data[2] & 1;
if (sprite->data[2] == 7)
DestroyAnimSprite(sprite);
}
break;
}
}
// Quickly moves two clones of the target mon back and forth.
// No args.
void AnimTask_OdorSleuthMovement(u8 taskId)
{
s16 spriteId1, spriteId2;
if (IsContest())
{
DestroyAnimVisualTask(taskId);
return;
}
spriteId1 = CloneBattlerSpriteWithBlend(ANIM_TARGET);
if (spriteId1 < 0)
{
DestroyAnimVisualTask(taskId);
return;
}
spriteId2 = CloneBattlerSpriteWithBlend(ANIM_TARGET);
if (spriteId2 < 0)
{
DestroySpriteWithActiveSheet(&gSprites[spriteId1]);
DestroyAnimVisualTask(taskId);
return;
}
gSprites[spriteId2].x2 += 24;
gSprites[spriteId1].x2 -= 24;
gSprites[spriteId2].data[0] = 0;
gSprites[spriteId1].data[0] = 0;
gSprites[spriteId2].data[1] = 0;
gSprites[spriteId1].data[1] = 0;
gSprites[spriteId2].data[2] = 0;
gSprites[spriteId1].data[2] = 0;
gSprites[spriteId2].data[3] = 16;
gSprites[spriteId1].data[3] = -16;
gSprites[spriteId2].data[4] = 0;
gSprites[spriteId1].data[4] = 128;
gSprites[spriteId2].data[5] = 24;
gSprites[spriteId1].data[5] = 24;
gSprites[spriteId2].data[6] = taskId;
gSprites[spriteId1].data[6] = taskId;
gSprites[spriteId2].data[7] = 0;
gSprites[spriteId1].data[7] = 0;
gTasks[taskId].data[0] = 2;
if (!gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].invisible)
{
gSprites[spriteId2].invisible = FALSE;
gSprites[spriteId1].invisible = TRUE;
}
else
{
gSprites[spriteId2].invisible = TRUE;
gSprites[spriteId1].invisible = TRUE;
}
gSprites[spriteId2].oam.objMode = ST_OAM_OBJ_NORMAL;
gSprites[spriteId1].oam.objMode = ST_OAM_OBJ_NORMAL;
gSprites[spriteId2].callback = MoveOdorSleuthClone;
gSprites[spriteId1].callback = MoveOdorSleuthClone;
gTasks[taskId].func = AnimTask_OdorSleuthMovementWaitFinish;
}
static void AnimTask_OdorSleuthMovementWaitFinish(u8 taskId)
{
if (gTasks[taskId].data[0] == 0)
DestroyAnimVisualTask(taskId);
}
static void MoveOdorSleuthClone(struct Sprite *sprite)
{
if (++sprite->data[1] > 1)
{
sprite->data[1] = 0;
if (!gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].invisible)
sprite->invisible ^= 1;
}
sprite->data[4] = sprite->data[4] + sprite->data[3];
sprite->data[4] &= 0xFF;
sprite->x2 = Cos(sprite->data[4], sprite->data[5]);
switch (sprite->data[0])
{
case 0:
if (++sprite->data[2] == 60)
{
sprite->data[2] = 0;
sprite->data[0]++;
}
break;
case 1:
if (++sprite->data[2] > 0)
{
sprite->data[2] = 0;
sprite->data[5] -= 2;
if (sprite->data[5] < 0)
{
gTasks[sprite->data[6]].data[sprite->data[7]]--;
DestroySpriteWithActiveSheet(sprite);
}
}
break;
}
}
void AnimTask_GetReturnPowerLevel(u8 taskId)
{
gBattleAnimArgs[ARG_RET_ID] = 0;
if (gAnimFriendship < 60)
gBattleAnimArgs[ARG_RET_ID] = 0;
if (gAnimFriendship > 60 && gAnimFriendship < 92)
gBattleAnimArgs[ARG_RET_ID] = 1;
if (gAnimFriendship > 91 && gAnimFriendship < 201)
gBattleAnimArgs[ARG_RET_ID] = 2;
if (gAnimFriendship > 200)
gBattleAnimArgs[ARG_RET_ID] = 3;
DestroyAnimVisualTask(taskId);
}
// Makes the mon run out of screen, run past the opposing mon, and return to its original position.
// No args.
void AnimTask_SnatchOpposingMonMove(u8 taskId)
{
u8 spriteId, spriteId2;
int personality;
int otId;
u16 species;
u8 subpriority;
bool8 isBackPic;
s16 x;
switch (gTasks[taskId].data[0])
{
case 0:
spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER);
gTasks[taskId].data[1] += 0x800;
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
gSprites[spriteId].x2 += (gTasks[taskId].data[1] >> 8);
else
gSprites[spriteId].x2 -= (gTasks[taskId].data[1] >> 8);
gTasks[taskId].data[1] &= 0xFF;
x = gSprites[spriteId].x + gSprites[spriteId].x2;
if ((u16)(x + 32) > 304)
{
gTasks[taskId].data[1] = 0;
gTasks[taskId].data[0]++;
}
break;
case 1:
if (IsContest())
{
personality = gContestResources->moveAnim->personality;
otId = gContestResources->moveAnim->otId;
species = gContestResources->moveAnim->species;
subpriority = GetBattlerSpriteSubpriority(gBattleAnimAttacker);
isBackPic = FALSE;
x = -32;
}
else
{
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
{
personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_PERSONALITY);
otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_OT_ID);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies == SPECIES_NONE)
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES);
else
species = gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies;
subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority + 1;
isBackPic = FALSE;
x = DISPLAY_WIDTH + 32;
}
else
{
personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_PERSONALITY);
otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_OT_ID);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies == SPECIES_NONE)
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES);
else
species = gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies;
subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority - 1;
isBackPic = TRUE;
x = -32;
}
}
spriteId2 = CreateAdditionalMonSpriteForMoveAnim(species, isBackPic, 0, x, GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y), subpriority, personality, otId, gBattleAnimAttacker, FALSE);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies != SPECIES_NONE)
BlendPalette((gSprites[spriteId2].oam.paletteNum * 16) | 0x100, 16, 6, RGB_WHITE);
gTasks[taskId].data[15] = spriteId2;
gTasks[taskId].data[0]++;
break;
case 2:
spriteId2 = gTasks[taskId].data[15];
gTasks[taskId].data[1] += 0x800;
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
gSprites[spriteId2].x2 -= (gTasks[taskId].data[1] >> 8);
else
gSprites[spriteId2].x2 += (gTasks[taskId].data[1] >> 8);
gTasks[taskId].data[1] &= 0xFF;
x = gSprites[spriteId2].x + gSprites[spriteId2].x2;
if (gTasks[taskId].data[14] == 0)
{
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
{
if (x < GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X))
{
gTasks[taskId].data[14]++;
gBattleAnimArgs[7] = 0xFFFF;
}
}
else
{
if (x > GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X))
{
gTasks[taskId].data[14]++;
gBattleAnimArgs[7] = 0xFFFF;
}
}
}
if ((u16)(x + 32) > 304)
{
gTasks[taskId].data[1] = 0;
gTasks[taskId].data[0]++;
}
break;
case 3:
spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER);
spriteId2 = gTasks[taskId].data[15];
DestroySpriteAndFreeResources_(&gSprites[spriteId2]);
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
gSprites[spriteId].x2 = -gSprites[spriteId].x - 32;
else
gSprites[spriteId].x2 = DISPLAY_WIDTH + 32 - gSprites[spriteId].x;
gTasks[taskId].data[0]++;
break;
case 4:
spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER);
gTasks[taskId].data[1] += 0x800;
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
{
gSprites[spriteId].x2 += (gTasks[taskId].data[1] >> 8);
if (gSprites[spriteId].x2 + gSprites[spriteId].x >= GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X))
gSprites[spriteId].x2 = 0;
}
else
{
gSprites[spriteId].x2 -= (gTasks[taskId].data[1] >> 8);
if (gSprites[spriteId].x2 + gSprites[spriteId].x <= GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X))
gSprites[spriteId].x2 = 0;
}
gTasks[taskId].data[1] &= 0xFF;
if (gSprites[spriteId].x2 == 0)
DestroyAnimVisualTask(taskId);
break;
}
}
static void AnimUnusedItemBagSteal(struct Sprite *sprite)
{
switch (sprite->data[7])
{
case 0:
if (gBattleAnimArgs[7] == -1)
{
PlaySE12WithPanning(SE_M_VITAL_THROW, BattleAnimAdjustPanning(63));
sprite->y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + 16;
sprite->data[0] = -32;
sprite->data[7]++;
sprite->invisible = FALSE;
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT && !IsContest())
sprite->subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority - 1;
}
else
{
sprite->invisible = TRUE;
}
break;
case 1:
sprite->y2 = Sin(sprite->data[1], sprite->data[0]);
sprite->data[1] += 5;
if (sprite->data[1] > 0x7F)
{
sprite->data[0] = sprite->data[0] / 2;
sprite->data[3]++;
sprite->data[1] -= 0x7F;
}
sprite->data[2] += 0x100;
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
sprite->x2 -= (sprite->data[2] >> 8);
else
sprite->x2 += (sprite->data[2] >> 8);
sprite->data[2] &= 0xFF;
if (sprite->data[3] == 2)
DestroyAnimSprite(sprite);
break;
}
}
// Quickly moves the mon towards its partner and back.
// No args.
void AnimTask_SnatchPartnerMove(u8 taskId)
{
s16 attackerX, targetX;
u8 spriteId;
switch (gTasks[taskId].data[15])
{
case 0:
attackerX = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X);
targetX = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X);
gTasks[taskId].data[0] = 6;
if (attackerX > targetX)
gTasks[taskId].data[0] *= -1;
gTasks[taskId].data[1] = attackerX;
gTasks[taskId].data[2] = targetX;
gTasks[taskId].data[15]++;
break;
case 1:
spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
gSprites[spriteId].x2 += gTasks[taskId].data[0];
if (gTasks[taskId].data[0] > 0)
{
if (gSprites[spriteId].x + gSprites[spriteId].x2 >= gTasks[taskId].data[2])
gTasks[taskId].data[15]++;
}
else
{
if (gSprites[spriteId].x + gSprites[spriteId].x2 <= gTasks[taskId].data[2])
gTasks[taskId].data[15]++;
}
break;
case 2:
gTasks[taskId].data[0] *= -1;
gTasks[taskId].data[15]++;
break;
case 3:
spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
gSprites[spriteId].x2 += gTasks[taskId].data[0];
if (gTasks[taskId].data[0] < 0)
{
if (gSprites[spriteId].x + gSprites[spriteId].x2 <= gTasks[taskId].data[1])
gTasks[taskId].data[15]++;
}
else
{
if (gSprites[spriteId].x + gSprites[spriteId].x2 >= gTasks[taskId].data[1])
gTasks[taskId].data[15]++;
}
break;
case 4:
default:
spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
gSprites[spriteId].x2 = 0;
DestroyAnimVisualTask(taskId);
break;
}
}
// Moves the mon's sprite back and forth in an unpredictable swaying motion.
// No args.
void AnimTask_TeeterDanceMovement(u8 taskId)
{
struct Task *task = &gTasks[taskId];
task->data[3] = GetAnimBattlerSpriteId(ANIM_ATTACKER);
task->data[4] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER ? 1 : -1;
task->data[6] = gSprites[task->data[3]].y;
task->data[5] = gSprites[task->data[3]].x;
task->data[9] = 0;
task->data[11] = 0;
task->data[10] = 1;
task->data[12] = 0;
task->func = AnimTask_TeeterDanceMovement_Step;
}
static void AnimTask_TeeterDanceMovement_Step(u8 taskId)
{
struct Task *task = &gTasks[taskId];
switch (task->data[0])
{
case 0:
task->data[11] += 8;
task->data[11] &= 0xFF;
gSprites[task->data[3]].x2 = gSineTable[task->data[11]] >> 5;
task->data[9] += 2;
task->data[9] &= 0xFF;
gSprites[task->data[3]].x = (gSineTable[task->data[9]] >> 3) * task->data[4] + task->data[5];
if (task->data[9] == 0)
{
gSprites[task->data[3]].x = task->data[5];
task->data[0]++;
}
break;
case 1:
task->data[11] += 8;
task->data[11] &= 0xFF;
gSprites[task->data[3]].x2 = gSineTable[task->data[11]] >> 5;
if (task->data[11] == 0)
{
gSprites[task->data[3]].x2 = 0;
task->data[0]++;
}
break;
case 2:
DestroyAnimVisualTask(taskId);
break;
}
}
static void AnimKnockOffStrike_Step(struct Sprite *sprite)
{
// These two cases are identical.
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
{
sprite->data[1] += sprite->data[0];
sprite->data[1] &= 0xFF;
}
else
{
sprite->data[1] += sprite->data[0];
sprite->data[1] &= 0xFF;
}
sprite->x2 = Cos(sprite->data[1], 20);
sprite->y2 = Sin(sprite->data[1], 20);
if (sprite->animEnded)
DestroyAnimSprite(sprite);
sprite->data[2]++;
}
// Animates a strike that swipes downard at the target mon.
// arg 0: initial x pixel offset
// arg 1: initial y pixel offset
static void AnimKnockOffStrike(struct Sprite *sprite)
{
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
{
sprite->x -= gBattleAnimArgs[0];
sprite->y += gBattleAnimArgs[1];
sprite->data[0] = -11;
sprite->data[1] = 192;
StartSpriteAffineAnim(sprite, 1);
}
else
{
sprite->data[0] = 11;
sprite->data[1] = 192;
sprite->x += gBattleAnimArgs[0];
sprite->y += gBattleAnimArgs[1];
}
sprite->callback = AnimKnockOffStrike_Step;
}
// Gradually fades a rotating recyle arrow sprite in and back out.
// No args.
static void AnimRecycle(struct Sprite *sprite)
{
sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2);
sprite->y = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_TOP);
if (sprite->y < 16)
sprite->y = 16;
sprite->data[6] = 0;
sprite->data[7] = 16;
sprite->callback = AnimRecycle_Step;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[6], sprite->data[7]));
}
static void AnimRecycle_Step(struct Sprite *sprite)
{
switch (sprite->data[2])
{
case 0:
if (++sprite->data[0] > 1)
{
sprite->data[0] = 0;
if (!(sprite->data[1] & 1))
{
if (sprite->data[6] < 16)
sprite->data[6]++;
}
else
{
if (sprite->data[7] != 0)
sprite->data[7]--;
}
sprite->data[1]++;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[6], sprite->data[7]));
if (sprite->data[7] == 0)
sprite->data[2]++;
}
break;
case 1:
if (++sprite->data[0] == 10)
{
sprite->data[0] = 0;
sprite->data[1] = 0;
sprite->data[2]++;
}
break;
case 2:
if (++sprite->data[0] > 1)
{
sprite->data[0] = 0;
if (!(sprite->data[1] & 1))
{
if (sprite->data[6] != 0)
sprite->data[6]--;
}
else
{
if (sprite->data[7] < 16)
sprite->data[7]++;
}
sprite->data[1]++;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[6], sprite->data[7]));
if (sprite->data[7] == 16)
sprite->data[2]++;
}
break;
case 3:
DestroySpriteAndMatrix(sprite);
break;
}
}
void AnimTask_GetWeather(u8 taskId)
{
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_NONE;
if (gWeatherMoveAnim & B_WEATHER_SUN)
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_SUN;
else if (gWeatherMoveAnim & B_WEATHER_RAIN)
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_RAIN;
else if (gWeatherMoveAnim & B_WEATHER_SANDSTORM)
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_SANDSTORM;
else if (gWeatherMoveAnim & B_WEATHER_HAIL)
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_HAIL;
DestroyAnimVisualTask(taskId);
}
// Squishes the mon sprite vertically, and shakes it back and forth.
// arg 0: which battler
void AnimTask_SlackOffSquish(u8 taskId)
{
struct Task *task = &gTasks[taskId];
task->data[0] = 0;
task->data[15] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]);
PrepareAffineAnimInTaskData(task, task->data[15], gSlackOffSquishAffineAnimCmds);
task->func = AnimTask_SlackOffSquish_Step;
}
static void AnimTask_SlackOffSquish_Step(u8 taskId)
{
struct Task *task = &gTasks[taskId];
gTasks[taskId].data[0]++;
if (gTasks[taskId].data[0] > 16 && gTasks[taskId].data[0] < 40)
{
if (++task->data[1] > 2)
{
task->data[1] = 0;
task->data[2]++;
if (!(task->data[2] & 1))
gSprites[task->data[15]].x2 = -1;
else
gSprites[task->data[15]].x2 = 1;
}
}
else
{
gSprites[task->data[15]].x2 = 0;
}
if (!RunAffineAnimFromTaskData(&gTasks[taskId]))
DestroyAnimVisualTask(taskId);
}