diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_anim_mons.c | 2 | ||||
-rw-r--r-- | src/battle_anim_status_effects.c | 2 | ||||
-rw-r--r-- | src/fire.c | 2 | ||||
-rw-r--r-- | src/graphics.c | 14 | ||||
-rw-r--r-- | src/ground.c | 2 | ||||
-rw-r--r-- | src/ice.c | 4 | ||||
-rw-r--r-- | src/normal.c | 2 | ||||
-rw-r--r-- | src/poison.c | 6 | ||||
-rw-r--r-- | src/rock.c | 4 | ||||
-rw-r--r-- | src/water.c | 2225 |
10 files changed, 2245 insertions, 18 deletions
diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index 741fdf312..d6c601572 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -2225,7 +2225,7 @@ static void sub_80772F4(struct Sprite *sprite) DestroyAnimSprite(sprite); } -void sub_8077350(struct Sprite *sprite) +void AnimWeatherBallDown(struct Sprite *sprite) { s32 x; diff --git a/src/battle_anim_status_effects.c b/src/battle_anim_status_effects.c index 4eb475a5c..8797670db 100644 --- a/src/battle_anim_status_effects.c +++ b/src/battle_anim_status_effects.c @@ -87,7 +87,7 @@ const struct SpriteTemplate gSpriteTemplate_83BF44C = .anims = sSpriteAnimTable_83BF430, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_8077350, + .callback = AnimWeatherBallDown, }; static const union AnimCmd sUnknown_83BF464[] = diff --git a/src/fire.c b/src/fire.c index a5a2ee5f6..51c9dff84 100644 --- a/src/fire.c +++ b/src/fire.c @@ -337,7 +337,7 @@ const struct SpriteTemplate gUnknown_83E5E14 = .anims = gUnknown_83E5D48, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_8077350, + .callback = AnimWeatherBallDown, }; static const struct SpriteTemplate gUnknown_83E5E2C = diff --git a/src/graphics.c b/src/graphics.c index 7eee42bf0..655bf43bc 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1019,7 +1019,7 @@ const u32 gBattleAnimBgTilemap_InAir[] = INCBIN_U32("graphics/battle_anims/backg const u32 gBattleAnimSpriteGfx_Protect[] = INCBIN_U32("graphics/battle_anims/sprites/protect.4bpp.lz"); const u32 gBattleAnimSpritePal_Protect[] = INCBIN_U32("graphics/battle_anims/sprites/protect.gbapal.lz"); -const u32 gFile_graphics_battle_anims_backgrounds_water_muddy_palette[] = INCBIN_U32("graphics/battle_anims/backgrounds/water_muddy.gbapal.lz"); +const u32 gBattleAnimBgPalette_MuddyWater[] = INCBIN_U32("graphics/battle_anims/backgrounds/water_muddy.gbapal.lz"); const u32 gFile_graphics_battle_interface_enemy_mon_shadow_sheet[] = INCBIN_U32("graphics/battle_interface/enemy_mon_shadow.4bpp.lz"); @@ -1085,11 +1085,13 @@ const u32 gBattleAnimSpritePal_Bird[] = INCBIN_U32("graphics/battle_anims/sprite const u32 gBattleAnimSpriteGfx_CrossImpact[] = INCBIN_U32("graphics/battle_anims/sprites/cross_impact.4bpp.lz"); const u32 gBattleAnimSpritePal_CrossImpact[] = INCBIN_U32("graphics/battle_anims/sprites/cross_impact.gbapal.lz"); -const u32 gFile_graphics_battle_anims_backgrounds_water_sheet[] = INCBIN_U32("graphics/battle_anims/backgrounds/water.4bpp.lz"); -const u32 gFile_graphics_battle_anims_backgrounds_water_palette[] = INCBIN_U32("graphics/battle_anims/backgrounds/water.gbapal.lz"); -const u32 gFile_graphics_unknown_unknown_E81D14_tilemap[] = INCBIN_U32("graphics/unknown/unknown_E81D14.bin.lz"); -const u32 gFile_graphics_unknown_unknown_E81FE4_tilemap[] = INCBIN_U32("graphics/unknown/unknown_E81FE4.bin.lz"); -const u32 gFile_graphics_unknown_unknown_E822B8_tilemap[] = INCBIN_U32("graphics/unknown/unknown_E822B8.bin.lz"); +const u32 gBattleAnimBgImage_Surf[] = INCBIN_U32("graphics/battle_anims/backgrounds/water.4bpp.lz"); +const u32 gBattleAnimBgPalette_Surf[] = INCBIN_U32("graphics/battle_anims/backgrounds/water.gbapal.lz"); + +// TODO Rename and move graphics +const u32 gBattleAnimBgTilemap_SurfOpponent[] = INCBIN_U32("graphics/battle_anims/backgrounds/water_opponent.bin.lz"); +const u32 gBattleAnimBgTilemap_SurfPlayer[] = INCBIN_U32("graphics/battle_anims/backgrounds/water_player.bin.lz"); +const u32 gBattleAnimBgTilemap_SurfContest[] = INCBIN_U32("graphics/battle_anims/backgrounds/water_contest.bin.lz"); const u32 gBattleAnimSpritePal_Slash2[] = INCBIN_U32("graphics/battle_anims/sprites/slash_2.gbapal.lz"); diff --git a/src/ground.c b/src/ground.c index 423671112..5c4291623 100644 --- a/src/ground.c +++ b/src/ground.c @@ -538,7 +538,7 @@ static void AnimDigDirtMound(struct Sprite *sprite) sprite->callback = WaitAnimForDuration; } -void sub_80B94B4(u8 taskId) +void AnimTask_HorizontalShake(u8 taskId) { u16 i; struct Task *task = &gTasks[taskId]; @@ -130,7 +130,7 @@ static const union AnimCmd *const gUnknown_83E632C[] = gUnknown_83E6308, }; -const union AnimCmd *const gUnknown_83E6330[] = +const union AnimCmd *const gAnims_SmallBubblePair[] = { gUnknown_83E6310, }; @@ -432,7 +432,7 @@ const struct SpriteTemplate gUnknown_83E65BC = .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gUnknown_83E65A0, - .callback = sub_8077350, + .callback = AnimWeatherBallDown, }; static const union AnimCmd gUnknown_83E65D4[] = diff --git a/src/normal.c b/src/normal.c index 5a4d98907..c20316942 100644 --- a/src/normal.c +++ b/src/normal.c @@ -186,7 +186,7 @@ const struct SpriteTemplate gUnknown_83E7C20 = .callback = sub_80BA5F8, }; -const struct SpriteTemplate gUnknown_83E7C38 = +const struct SpriteTemplate gWaterHitSplatSpriteTemplate = { .tileTag = ANIM_TAG_WATER_IMPACT, .paletteTag = ANIM_TAG_WATER_IMPACT, diff --git a/src/poison.c b/src/poison.c index af7f8ee86..250fbcac4 100644 --- a/src/poison.c +++ b/src/poison.c @@ -134,7 +134,7 @@ static const union AffineAnimCmd gUnknown_83E6A68[] = AFFINEANIMCMD_JUMP(0), }; -const union AffineAnimCmd *const gUnknown_83E6A80[] = +const union AffineAnimCmd *const gAffineAnims_Droplet[] = { gUnknown_83E6A68, }; @@ -146,7 +146,7 @@ const struct SpriteTemplate gUnknown_83E6A84 = .oam = &gOamData_AffineDouble_ObjNormal_16x16, .anims = gUnknown_83E69E0, .images = NULL, - .affineAnims = gUnknown_83E6A80, + .affineAnims = gAffineAnims_Droplet, .callback = sub_80B17C4, }; @@ -178,7 +178,7 @@ const struct SpriteTemplate gWaterBubbleSpriteTemplate = .tileTag = ANIM_TAG_SMALL_BUBBLES, .paletteTag = ANIM_TAG_SMALL_BUBBLES, .oam = &gOamData_AffineNormal_ObjBlend_16x16, - .anims = gUnknown_83E5A78, + .anims = gAnims_WaterBubble, .images = NULL, .affineAnims = gUnknown_83E6AB4, .callback = AnimBubbleEffect, diff --git a/src/rock.c b/src/rock.c index a2d28d057..565ce9461 100644 --- a/src/rock.c +++ b/src/rock.c @@ -100,7 +100,7 @@ const struct SpriteTemplate gUnknown_83E7420 = .tileTag = ANIM_TAG_WATER_ORB, .paletteTag = ANIM_TAG_WATER_ORB, .oam = &gOamData_AffineNormal_ObjBlend_16x16, - .anims = gUnknown_83E5958, + .anims = gAnims_WaterMudOrb, .images = NULL, .affineAnims = gUnknown_83E741C, .callback = sub_80B477C, @@ -310,7 +310,7 @@ const struct SpriteTemplate gUnknown_83E7590 = .anims = gUnknown_83E74B0, .images = NULL, .affineAnims = gUnknown_83E7540, - .callback = sub_8077350, + .callback = AnimWeatherBallDown, }; static void sub_80B4634(struct Sprite *sprite) diff --git a/src/water.c b/src/water.c new file mode 100644 index 000000000..31a4b32e7 --- /dev/null +++ b/src/water.c @@ -0,0 +1,2225 @@ +#include "global.h" +#include "battle_anim.h" +#include "decompress.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "palette.h" +#include "pokemon.h" +#include "random.h" +#include "scanline_effect.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "util.h" + +static void AnimRainDrop(struct Sprite *); +static void AnimRainDrop_Step(struct Sprite *); +static void AnimWaterBubbleProjectile(struct Sprite *); +static void AnimWaterBubbleProjectile_Step1(struct Sprite *); +static void AnimWaterBubbleProjectile_Step2(struct Sprite *); +static void AnimWaterBubbleProjectile_Step3(struct Sprite *); +static void AnimAuroraBeamRings(struct Sprite *); +static void AnimAuroraBeamRings_Step(struct Sprite *); +static void AnimToTargetInSinWave(struct Sprite *); +static void AnimToTargetInSinWave_Step(struct Sprite *); +static void AnimHydroCannonCharge(struct Sprite *); +static void AnimHydroCannonCharge_Step(struct Sprite *); +static void AnimHydroCannonBeam(struct Sprite *); +static void AnimWaterGunDroplet(struct Sprite *); +static void AnimSmallBubblePair(struct Sprite *); +static void AnimSmallBubblePair_Step(struct Sprite *); +static void AnimSmallDriftingBubbles(struct Sprite *); +static void AnimSmallDriftingBubbles_Step(struct Sprite *); +static void AnimSmallWaterOrb(struct Sprite *); +static void AnimWaterSpoutRain(struct Sprite *); +static void AnimWaterSpoutRainHit(struct Sprite *); +static void AnimWaterSportDroplet(struct Sprite *); +static void AnimWaterSportDroplet_Step(struct Sprite *); +static void AnimWaterPulseBubble(struct Sprite *); +static void AnimWaterPulseBubble_Step(struct Sprite *); +static void AnimWaterPulseRingBubble(struct Sprite *); +static void AnimWaterPulseRing_Step(struct Sprite *); +static void AnimTask_RotateAuroraRingColors_Step(u8); +static void AnimTask_RunSinAnimTimer(u8); +static void AnimTask_CreateSurfWave_Step1(u8); +static void AnimTask_CreateSurfWave_Step2(u8); +static void AnimTask_SurfWaveScanlineEffect(u8); +static void AnimTask_WaterSpoutLaunch_Step(u8); +static void AnimTask_WaterSpoutRain_Step(u8); +static u8 GetWaterSpoutPowerForAnim(void); +static void CreateWaterSpoutLaunchDroplets(struct Task*, u8); +static void CreateWaterSpoutRainDroplet(struct Task*, u8); +static void AnimTask_WaterSport_Step(u8); +static void CreateWaterSportDroplet(struct Task*); +static void CreateWaterPulseRingBubbles(struct Sprite*, int, int); + +// Both unused? Comment copied from pokeemerald +const u8 gUnknown_83E44F4[] = INCBIN_U8("graphics/battle_anims/unk_83E4874.4bpp"); +const u8 gUnknown_83E4874[] = INCBIN_U8("graphics/battle_anims/unk_83E4874.bin"); + +static const union AnimCmd sAnim_RainDrop[] = +{ + ANIMCMD_FRAME(0, 2), + ANIMCMD_FRAME(8, 2), + ANIMCMD_FRAME(16, 2), + ANIMCMD_FRAME(24, 6), + ANIMCMD_FRAME(32, 2), + ANIMCMD_FRAME(40, 2), + ANIMCMD_FRAME(48, 2), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_RainDrop[] = +{ + sAnim_RainDrop, +}; + +const struct SpriteTemplate gRainDropSpriteTemplate = +{ + .tileTag = ANIM_TAG_RAIN_DROPS, + .paletteTag = ANIM_TAG_RAIN_DROPS, + .oam = &gOamData_AffineOff_ObjNormal_16x32, + .anims = sAnims_RainDrop, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRainDrop, +}; + +static const union AffineAnimCmd sAffineAnim_WaterBubbleProjectile[] = +{ + AFFINEANIMCMD_FRAME(0xFFFB, 0xFFFB, 0, 10), + AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 10), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sAffineAnims_WaterBubbleProjectile[] = +{ + sAffineAnim_WaterBubbleProjectile, +}; + +static const union AnimCmd sAnim_WaterBubbleProjectile[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_WaterBubbleProjectile[] = +{ + sAnim_WaterBubbleProjectile, +}; + +const struct SpriteTemplate gWaterBubbleProjectileSpriteTemplate = +{ + .tileTag = ANIM_TAG_BUBBLE, + .paletteTag = ANIM_TAG_BUBBLE, + .oam = &gOamData_AffineNormal_ObjBlend_16x16, + .anims = sAnims_WaterBubbleProjectile, + .images = NULL, + .affineAnims = sAffineAnims_WaterBubbleProjectile, + .callback = AnimWaterBubbleProjectile, +}; + +static const union AnimCmd sAnim_AuroraBeamRing_0[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_AuroraBeamRing_1[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_AuroraBeamRing[] = +{ + sAnim_AuroraBeamRing_0, + sAnim_AuroraBeamRing_1, +}; + +static const union AffineAnimCmd sAffineAnim_AuroraBeamRing[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 1), + AFFINEANIMCMD_FRAME(0x60, 0x60, 0, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_AuroraBeamRing[] = +{ + sAffineAnim_AuroraBeamRing, +}; + +const struct SpriteTemplate gAuroraBeamRingSpriteTemplate = +{ + .tileTag = ANIM_TAG_RAINBOW_RINGS, + .paletteTag = ANIM_TAG_RAINBOW_RINGS, + .oam = &gOamData_AffineDouble_ObjNormal_8x16, + .anims = sAnims_AuroraBeamRing, + .images = NULL, + .affineAnims = sAffineAnims_AuroraBeamRing, + .callback = AnimAuroraBeamRings, +}; + +static const union AnimCmd sAnim_WaterMudOrb[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_FRAME(4, 1), + ANIMCMD_FRAME(8, 1), + ANIMCMD_FRAME(12, 1), + ANIMCMD_JUMP(0), +}; + +const union AnimCmd *const gAnims_WaterMudOrb[] = +{ + sAnim_WaterMudOrb, +}; + +const struct SpriteTemplate gHydroPumpOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_WATER_ORB, + .paletteTag = ANIM_TAG_WATER_ORB, + .oam = &gOamData_AffineOff_ObjBlend_16x16, + .anims = gAnims_WaterMudOrb, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimToTargetInSinWave, +}; + +const struct SpriteTemplate gMudShotOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_BROWN_ORB, + .paletteTag = ANIM_TAG_BROWN_ORB, + .oam = &gOamData_AffineOff_ObjBlend_16x16, + .anims = gAnims_WaterMudOrb, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimToTargetInSinWave, +}; + +const struct SpriteTemplate gSignalBeamRedOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_GLOWY_RED_ORB, + .paletteTag = ANIM_TAG_GLOWY_RED_ORB, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimToTargetInSinWave, +}; + +const struct SpriteTemplate gSignalBeamGreenOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_GLOWY_GREEN_ORB, + .paletteTag = ANIM_TAG_GLOWY_GREEN_ORB, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimToTargetInSinWave, +}; + +static const union AnimCmd sAnim_FlamethrowerFlame[] = +{ + ANIMCMD_FRAME(16, 2), + ANIMCMD_FRAME(32, 2), + ANIMCMD_FRAME(48, 2), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_FlamethrowerFlame[] = +{ + sAnim_FlamethrowerFlame, +}; + +const struct SpriteTemplate gFlamethrowerFlameSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_FlamethrowerFlame, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimToTargetInSinWave, +}; + +const struct SpriteTemplate gPsywaveRingSpriteTemplate = +{ + .tileTag = ANIM_TAG_BLUE_RING, + .paletteTag = ANIM_TAG_BLUE_RING, + .oam = &gOamData_AffineDouble_ObjNormal_16x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gGrowingRingAffineAnimTable, + .callback = AnimToTargetInSinWave, +}; + +static const union AffineAnimCmd sAffineAnim_HydroCannonCharge[] = +{ + AFFINEANIMCMD_FRAME(0x3, 0x3, 10, 50), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 10), + AFFINEANIMCMD_FRAME(0xFFEC, 0xFFEC, -10, 20), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_HydroCannonBeam[] = +{ + AFFINEANIMCMD_FRAME(0x150, 0x150, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_HydroCannonCharge[] = +{ + sAffineAnim_HydroCannonCharge, +}; + +static const union AffineAnimCmd *const sAffineAnims_HydroCannonBeam[] = +{ + sAffineAnim_HydroCannonBeam, +}; + +const struct SpriteTemplate gHydroCannonChargeSpriteTemplate = +{ + .tileTag = ANIM_TAG_WATER_ORB, + .paletteTag = ANIM_TAG_WATER_ORB, + .oam = &gOamData_AffineDouble_ObjBlend_16x16, + .anims = gAnims_WaterMudOrb, + .images = NULL, + .affineAnims = sAffineAnims_HydroCannonCharge, + .callback = AnimHydroCannonCharge, +}; + +const struct SpriteTemplate gHydroCannonBeamSpriteTemplate = +{ + .tileTag = ANIM_TAG_WATER_ORB, + .paletteTag = ANIM_TAG_WATER_ORB, + .oam = &gOamData_AffineDouble_ObjBlend_16x16, + .anims = gAnims_WaterMudOrb, + .images = NULL, + .affineAnims = sAffineAnims_HydroCannonBeam, + .callback = AnimHydroCannonBeam, +}; + +static const union AnimCmd sAnim_WaterBubble[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_WaterGunDroplet[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_END, +}; + +const union AnimCmd *const gAnims_WaterBubble[] = +{ + sAnim_WaterBubble, +}; + +static const union AnimCmd *const sAnims_WaterGunDroplet[] = +{ + sAnim_WaterGunDroplet, +}; + +const struct SpriteTemplate gWaterGunProjectileSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineOff_ObjBlend_16x16, + .anims = gAnims_WaterBubble, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimThrowProjectile, +}; + +const struct SpriteTemplate gWaterGunDropletSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineDouble_ObjBlend_16x16, + .anims = sAnims_WaterGunDroplet, + .images = NULL, + .affineAnims = gAffineAnims_Droplet, + .callback = AnimWaterGunDroplet, +}; + +const struct SpriteTemplate gSmallBubblePairSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, // ice_crystals_4, which are bubbles + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gAnims_SmallBubblePair, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSmallBubblePair, +}; + +const struct SpriteTemplate gSmallDriftingBubblesSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSmallDriftingBubbles, +}; + +// Used by Water Spout / Water Sport +const struct SpriteTemplate gSmallWaterOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_GLOWY_BLUE_ORB, + .paletteTag = ANIM_TAG_GLOWY_BLUE_ORB, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSmallWaterOrb, +}; + +static const union AnimCmd sAnim_WaterPulseBubble_0[] = +{ + ANIMCMD_FRAME(8, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_WaterPulseBubble_1[] = +{ + ANIMCMD_FRAME(9, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_WeatherBallWaterDown[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_WaterPulseBubble[] = +{ + sAnim_WaterPulseBubble_0, + sAnim_WaterPulseBubble_1, +}; + +static const union AnimCmd *const sAnims_WeatherBallWaterDown[] = +{ + sAnim_WeatherBallWaterDown, +}; + +static const union AffineAnimCmd sAffineAnim_WaterPulseRingBubble_0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0xFFF6, 0xFFF6, 0, 15), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_WaterPulseRingBubble_1[] = +{ + AFFINEANIMCMD_FRAME(0xE0, 0xE0, 0, 0), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 15), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_WeatherBallWaterDown[] = +{ + AFFINEANIMCMD_FRAME(0x150, 0x150, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 15), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_WaterPulseRingBubble[] = +{ + sAffineAnim_WaterPulseRingBubble_0, + sAffineAnim_WaterPulseRingBubble_1, +}; + +static const union AffineAnimCmd *const sAffineAnims_WeatherBallWaterDown[] = +{ + sAffineAnim_WeatherBallWaterDown, +}; + +const struct SpriteTemplate gWaterPulseBubbleSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = sAnims_WaterPulseBubble, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWaterPulseBubble, +}; + +const struct SpriteTemplate gWaterPulseRingBubbleSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineNormal_ObjNormal_8x8, + .anims = sAnims_WaterPulseBubble, + .images = NULL, + .affineAnims = sAffineAnims_WaterPulseRingBubble, + .callback = AnimWaterPulseRingBubble, +}; + +const struct SpriteTemplate gWeatherBallWaterDownSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = sAnims_WeatherBallWaterDown, + .images = NULL, + .affineAnims = sAffineAnims_WeatherBallWaterDown, + .callback = AnimWeatherBallDown, +}; + +void AnimTask_CreateRaindrops(u8 taskId) +{ + u8 x, y; + + if (gTasks[taskId].data[0] == 0) + { + gTasks[taskId].data[1] = gBattleAnimArgs[0]; + gTasks[taskId].data[2] = gBattleAnimArgs[1]; + gTasks[taskId].data[3] = gBattleAnimArgs[2]; + } + gTasks[taskId].data[0]++; + if (gTasks[taskId].data[0] % gTasks[taskId].data[2] == 1) + { + x = Random() % 240; + y = Random() % 80; + CreateSprite(&gRainDropSpriteTemplate, x, y, 4); + } + if (gTasks[taskId].data[0] == gTasks[taskId].data[3]) + DestroyAnimVisualTask(taskId); +} + +static void AnimRainDrop(struct Sprite *sprite) { + sprite->callback = AnimRainDrop_Step; +} + +static void AnimRainDrop_Step(struct Sprite *sprite) { + if (++sprite->data[0] < 14) // Was 13 in emerald + { + sprite->pos2.x += 1; + sprite->pos2.y += 4; + } + if (sprite->animEnded) + { + DestroySprite(sprite); + } +} + +// For water bubbles that move to a dest, as in Bubble/Bubblebeam +static void AnimWaterBubbleProjectile(struct Sprite *sprite) +{ + u8 spriteId; + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2) - gBattleAnimArgs[0]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + gBattleAnimArgs[1]; + sprite->animPaused = TRUE; + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2) + gBattleAnimArgs[0]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + gBattleAnimArgs[1]; + sprite->animPaused = TRUE; + } + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[6]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + InitAnimLinearTranslation(sprite); + spriteId = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy); + sprite->data[5] = spriteId; + sprite->pos1.x -= Sin((u8)gBattleAnimArgs[4], gBattleAnimArgs[2]); + sprite->pos1.y -= Cos((u8)gBattleAnimArgs[4], gBattleAnimArgs[3]); + gSprites[spriteId].data[0] = gBattleAnimArgs[2]; + gSprites[spriteId].data[1] = gBattleAnimArgs[3]; + gSprites[spriteId].data[2] = gBattleAnimArgs[5]; + gSprites[spriteId].data[3] = (u8)gBattleAnimArgs[4] * 256; + gSprites[spriteId].data[4] = gBattleAnimArgs[6]; + sprite->callback = AnimWaterBubbleProjectile_Step1; + sprite->callback(sprite); +} + +static void AnimWaterBubbleProjectile_Step1(struct Sprite *sprite) +{ + u8 otherSpriteId = sprite->data[5]; + u8 timer = gSprites[otherSpriteId].data[4]; + u16 trigIndex = gSprites[otherSpriteId].data[3]; + + sprite->data[0] = 1; + AnimTranslateLinear(sprite); + sprite->pos2.x += Sin(trigIndex >> 8, gSprites[otherSpriteId].data[0]); + sprite->pos2.y += Cos(trigIndex >> 8, gSprites[otherSpriteId].data[1]); + gSprites[otherSpriteId].data[3] = trigIndex + gSprites[otherSpriteId].data[2]; + if (--timer != 0) + { + gSprites[otherSpriteId].data[4] = timer; + } + else + { + sprite->callback = AnimWaterBubbleProjectile_Step2; + DestroySprite(&gSprites[otherSpriteId]); + } +} + +static void AnimWaterBubbleProjectile_Step2(struct Sprite *sprite) +{ + sprite->animPaused = FALSE; + sprite->callback = RunStoredCallbackWhenAnimEnds; + StoreSpriteCallbackInData6(sprite, AnimWaterBubbleProjectile_Step3); +} + +static void AnimWaterBubbleProjectile_Step3(struct Sprite *sprite) +{ + sprite->data[0] = 10; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); +} + +static void AnimAuroraBeamRings(struct Sprite *sprite) +{ + s16 unkArg; + + InitSpritePosToAnimAttacker(sprite, TRUE); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + unkArg = -gBattleAnimArgs[2]; + else + unkArg = gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + unkArg; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + gBattleAnimArgs[3]; + InitAnimLinearTranslation(sprite); + sprite->callback = AnimAuroraBeamRings_Step; + sprite->affineAnimPaused = TRUE; + sprite->callback(sprite); +} + +static void AnimAuroraBeamRings_Step(struct Sprite *sprite) +{ + if ((u16)gBattleAnimArgs[7] == 0xFFFF) + { + StartSpriteAnim(sprite, 1); + sprite->affineAnimPaused = FALSE; + } + if (AnimTranslateLinear(sprite)) + DestroyAnimSprite(sprite); +} + +// Updates the palette on the rainbow rings used in Aurora Beam to make them appear to be rotating counterclockwise +void AnimTask_RotateAuroraRingColors(u8 taskId) +{ + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gTasks[taskId].data[2] = IndexOfSpritePaletteTag(ANIM_TAG_RAINBOW_RINGS) * 16 + 256; + gTasks[taskId].func = AnimTask_RotateAuroraRingColors_Step; +} + +#ifdef NONMATCHING +static void AnimTask_RotateAuroraRingColors_Step(u8 taskId) +{ + int i; + u16 palIndex; + u16 *palPtr1; + u16 *palPtr2; + u16 rgbBuffer; + + if (++gTasks[taskId].data[10] == 3) + { + gTasks[taskId].data[10] = 0; + palIndex = gTasks[taskId].data[2] + 1; + palPtr1 = &gPlttBufferFaded[palIndex]; + rgbBuffer = *palPtr1; + palPtr2 = &palPtr1[1]; + for (i = 0; i < 7; i++) + palPtr1[i] = palPtr2[i]; + gPlttBufferFaded[palIndex + 7] = rgbBuffer; + } + if (++gTasks[taskId].data[11] == gTasks[taskId].data[0]) + DestroyAnimVisualTask(taskId); +} +#else +NAKED +static void AnimTask_RotateAuroraRingColors_Step(u8 taskId) +{ + asm_unified("push {r4-r7,lr}\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + ldr r1, =gTasks\n\ + lsls r0, r4, 2\n\ + adds r0, r4\n\ + lsls r0, 3\n\ + adds r2, r0, r1\n\ + ldrh r0, [r2, 0x1C]\n\ + adds r0, 0x1\n\ + strh r0, [r2, 0x1C]\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + mov r12, r1\n\ + cmp r0, 0x3\n\ + bne _081075BE\n\ + movs r0, 0\n\ + strh r0, [r2, 0x1C]\n\ + ldrh r0, [r2, 0xC]\n\ + adds r0, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + ldr r1, =gPlttBufferFaded\n\ + lsls r0, r5, 1\n\ + adds r0, r1\n\ + ldrh r6, [r0]\n\ + adds r7, r1, 0\n\ + adds r3, r0, 0x2\n\ + movs r1, 0x6\n\ + adds r2, r0, 0\n\ +_081075A8:\n\ + ldrh r0, [r3]\n\ + strh r0, [r2]\n\ + adds r3, 0x2\n\ + adds r2, 0x2\n\ + subs r1, 0x1\n\ + cmp r1, 0\n\ + bge _081075A8\n\ + adds r0, r5, 0x7\n\ + lsls r0, 1\n\ + adds r0, r7\n\ + strh r6, [r0]\n\ +_081075BE:\n\ + lsls r0, r4, 2\n\ + adds r0, r4\n\ + lsls r0, 3\n\ + add r0, r12\n\ + ldrh r1, [r0, 0x1E]\n\ + adds r1, 0x1\n\ + strh r1, [r0, 0x1E]\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + movs r2, 0x8\n\ + ldrsh r0, [r0, r2]\n\ + cmp r1, r0\n\ + bne _081075DE\n\ + adds r0, r4, 0\n\ + bl DestroyAnimVisualTask\n\ +_081075DE:\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n"); +} +#endif + +// For animating undulating beam attacks (e.g. Flamethrower, Hydro Pump, Signal Beam) +static void AnimToTargetInSinWave(struct Sprite *sprite) +{ + u16 retArg; + + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[0] = 30; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + InitAnimLinearTranslation(sprite); + sprite->data[5] = 0xD200 / sprite->data[0]; + sprite->data[7] = gBattleAnimArgs[3]; + retArg = gBattleAnimArgs[7]; + if (gBattleAnimArgs[7] > 127) + { + sprite->data[6] = (retArg - 127) * 256; + sprite->data[7] = -sprite->data[7]; + } + else + { + sprite->data[6] = retArg * 256; + } + sprite->callback = AnimToTargetInSinWave_Step; + sprite->callback(sprite); +} + +static void AnimToTargetInSinWave_Step(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + DestroyAnimSprite(sprite); + sprite->pos2.y += Sin(sprite->data[6] >> 8, sprite->data[7]); + if ((sprite->data[6] + sprite->data[5]) >> 8 > 127) + { + sprite->data[6] = 0; + sprite->data[7] = -sprite->data[7]; + } + else + { + sprite->data[6] += sprite->data[5]; + } +} + +void AnimTask_StartSinAnimTimer(u8 taskId) +{ + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gBattleAnimArgs[7] = 0; + gTasks[taskId].func = AnimTask_RunSinAnimTimer; +} + +static void AnimTask_RunSinAnimTimer(u8 taskId) +{ + gBattleAnimArgs[7] = (gBattleAnimArgs[7] + 3) & 0xFF; + if (--gTasks[taskId].data[0] == 0) + DestroyAnimVisualTask(taskId); +} + +// Flashing blue orbs grow in size near the attacker. First stage of Hydro Cannon +static void AnimHydroCannonCharge(struct Sprite *sprite) +{ + u8 priority; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1); + sprite->pos2.y = -10; + priority = GetBattlerSpriteSubpriority(gBattleAnimAttacker); + if (!IsContest()) + { + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + sprite->pos2.x = 10; + sprite->subpriority = priority + 2; + } + else + { + sprite->pos2.x = -10; + sprite->subpriority = priority - 2; + } + } + else + { + sprite->pos2.x = -10; + sprite->subpriority = priority + 2; + } + sprite->callback = AnimHydroCannonCharge_Step; +} + +static void AnimHydroCannonCharge_Step(struct Sprite *sprite) +{ + if (sprite->affineAnimEnded) + DestroyAnimSprite(sprite); +} + +// Flashing blue orbs move from the attacker to the target. Second stage of Hydro Cannon +static void AnimHydroCannonBeam(struct Sprite *sprite) +{ + bool8 animType; + u8 coordType; + if (GetBattlerSide(gBattleAnimAttacker) == GetBattlerSide(gBattleAnimTarget)) + { + gBattleAnimArgs[0] *= -1; + if (GetBattlerPosition(gBattleAnimAttacker) == B_POSITION_PLAYER_LEFT || GetBattlerPosition(gBattleAnimAttacker) == B_POSITION_OPPONENT_LEFT) + gBattleAnimArgs[0] *= -1; + } + if ((gBattleAnimArgs[5] & 0xFF00) == 0) + animType = TRUE; + else + animType = FALSE; + if ((u8)gBattleAnimArgs[5] == 0) + coordType = 3; + else + coordType = 1; + InitSpritePosToAnimAttacker(sprite, animType); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, coordType) + gBattleAnimArgs[3]; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Water droplet appears and drips down. Used by Water Gun on impact +static void AnimWaterGunDroplet(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[4]; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void AnimSmallBubblePair(struct Sprite *sprite) +{ + if (gBattleAnimArgs[3] != ANIM_ATTACKER) + InitSpritePosToAnimTarget(sprite, TRUE); + else + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[7] = gBattleAnimArgs[2]; + sprite->callback = AnimSmallBubblePair_Step; +} + +static void AnimSmallBubblePair_Step(struct Sprite *sprite) +{ + sprite->data[0] = (sprite->data[0] + 11) & 0xFF; + sprite->pos2.x = Sin(sprite->data[0], 4); + sprite->data[1] += 48; + sprite->pos2.y = -(sprite->data[1] >> 8); + if (--sprite->data[7] == -1) + DestroyAnimSprite(sprite); +} + +#ifdef NONMATCHING +void AnimTask_CreateSurfWave(u8 taskId) +{ + struct BattleAnimBgData animBg; + u8 taskId2; + + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 1); + sub_80752A0(&animBg); + if (!IsContest()) + { + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + AnimLoadCompressedBgTilemap(animBg.bgId, gBattleAnimBgTilemap_SurfOpponent); + else + AnimLoadCompressedBgTilemap(animBg.bgId, gBattleAnimBgTilemap_SurfPlayer); + } + else + { + // Changed from Emerald + LZDecompressVram(gBattleAnimBgTilemap_SurfContest, animBg->bgTilemap); + sub_80730C0(animBg.paletteId, animBg.bgTilemap, 0, 1); + } + AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Surf, animBg.tilesOffset); + if (gBattleAnimArgs[0] == 0) + LoadCompressedPalette(gBattleAnimBgPalette_Surf, animBg.paletteId * 16, 32); + else + LoadCompressedPalette(gBattleAnimBgPalette_MuddyWater, animBg.paletteId * 16, 32); + taskId2 = CreateTask(AnimTask_SurfWaveScanlineEffect, gTasks[taskId].priority + 1); + gTasks[taskId].data[15] = taskId2; + gTasks[taskId2].data[0] = 0; + gTasks[taskId2].data[1] = 0x1000; + gTasks[taskId2].data[2] = 0x1000; + if (IsContest()) + { + gBattle_BG1_X = -80; + gBattle_BG1_Y = -48; + gTasks[taskId].data[0] = 2; + gTasks[taskId].data[1] = 1; + gTasks[taskId2].data[3] = 0; + } + else if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + { + gBattle_BG1_X = -224; + gBattle_BG1_Y = 256; + gTasks[taskId].data[0] = 2; + gTasks[taskId].data[1] = -1; + gTasks[taskId2].data[3] = 1; + } + else + { + gBattle_BG1_X = 0; + gBattle_BG1_Y = -48; + gTasks[taskId].data[0] = -2; + gTasks[taskId].data[1] = 1; + gTasks[taskId2].data[3] = 0; + } + SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); + SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); + if (gTasks[taskId2].data[3] == 0) + { + gTasks[taskId2].data[4] = 48; + gTasks[taskId2].data[5] = 112; + } + else + { + gTasks[taskId2].data[4] = 0; + gTasks[taskId2].data[5] = 0; + } + gTasks[taskId].data[6] = 1; + gTasks[taskId].func = AnimTask_CreateSurfWave_Step1; +} +#else +NAKED +void AnimTask_CreateSurfWave(u8 taskId) +{ + asm_unified("push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x10\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r10, r0\n\ + ldr r1, =0x00003f42\n\ + movs r0, 0x50\n\ + bl SetGpuReg\n\ + movs r1, 0x80\n\ + lsls r1, 5\n\ + movs r0, 0x52\n\ + bl SetGpuReg\n\ + movs r0, 0x1\n\ + movs r1, 0x4\n\ + movs r2, 0x1\n\ + bl SetAnimBgAttribute\n\ + movs r0, 0x1\n\ + movs r1, 0\n\ + movs r2, 0x1\n\ + bl SetAnimBgAttribute\n\ + mov r0, sp\n\ + bl sub_80752A0\n\ + bl IsContest\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _081079E0\n\ + movs r0, 0x1\n\ + movs r1, 0x3\n\ + movs r2, 0x1\n\ + bl SetAnimBgAttribute\n\ + ldr r0, =gBattleAnimAttacker\n\ + ldrb r0, [r0]\n\ + bl GetBattlerSide\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _081079D0\n\ + mov r0, sp\n\ + ldrb r0, [r0, 0x9]\n\ + ldr r1, =gBattleAnimBgTilemap_SurfOpponent\n\ + bl AnimLoadCompressedBgTilemap\n\ + b _081079EA\n\ + .pool\n\ +_081079D0:\n\ + mov r0, sp\n\ + ldrb r0, [r0, 0x9]\n\ + ldr r1, =gBattleAnimBgTilemap_SurfPlayer\n\ + bl AnimLoadCompressedBgTilemap\n\ + b _081079EA\n\ + .pool\n\ +_081079E0:\n\ + ldr r0, =gBattleAnimBgTilemap_SurfContest\n\ + ldr r1, [sp, 0x4]\n\ + bl LZDecompressVram\n\ + mov r0, sp\n\ + ldrb r0, [r0, 0x8]\n\ + ldr r1, [sp, 0x4]\n\ + movs r2, 0\n\ + movs r3, 0x1\n\ + bl sub_80730C0\n\ +_081079EA:\n\ + mov r0, sp\n\ + ldrb r0, [r0, 0x9]\n\ + ldr r1, =gBattleAnimBgImage_Surf\n\ + mov r2, sp\n\ + ldrh r2, [r2, 0xA]\n\ + bl AnimLoadCompressedBgGfx\n\ + ldr r0, =gBattleAnimArgs\n\ + movs r1, 0\n\ + ldrsh r0, [r0, r1]\n\ + cmp r0, 0\n\ + bne _08107A24\n\ + ldr r0, =gBattleAnimBgPalette_Surf\n\ + mov r1, sp\n\ + ldrb r1, [r1, 0x8]\n\ + lsls r1, 4\n\ + movs r2, 0x20\n\ + bl LoadCompressedPalette\n\ + b _08107A32\n\ + .pool\n\ +_08107A24:\n\ + ldr r0, =gBattleAnimBgPalette_MuddyWater\n\ + mov r1, sp\n\ + ldrb r1, [r1, 0x8]\n\ + lsls r1, 4\n\ + movs r2, 0x20\n\ + bl LoadCompressedPalette\n\ +_08107A32:\n\ + ldr r0, =AnimTask_SurfWaveScanlineEffect\n\ + ldr r4, =gTasks\n\ + mov r2, r10\n\ + lsls r5, r2, 2\n\ + adds r1, r5, r2\n\ + lsls r1, 3\n\ + adds r6, r1, r4\n\ + ldrb r1, [r6, 0x7]\n\ + adds r1, 0x1\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + bl CreateTask\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + movs r0, 0\n\ + mov r9, r0\n\ + mov r1, r8\n\ + strh r1, [r6, 0x26]\n\ + mov r2, r8\n\ + lsls r0, r2, 2\n\ + add r0, r8\n\ + lsls r0, 3\n\ + adds r7, r0, r4\n\ + mov r0, r9\n\ + strh r0, [r7, 0x8]\n\ + movs r0, 0x80\n\ + lsls r0, 5\n\ + strh r0, [r7, 0xA]\n\ + strh r0, [r7, 0xC]\n\ + bl IsContest\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r4, 0\n\ + beq _08107AB4\n\ + ldr r1, =0x0000ffb0\n\ + adds r0, r1, 0\n\ + ldr r2, =gBattle_BG1_X\n\ + strh r0, [r2]\n\ + adds r1, 0x20\n\ + adds r0, r1, 0\n\ + ldr r2, =gBattle_BG1_Y\n\ + strh r0, [r2]\n\ + movs r0, 0x2\n\ + strh r0, [r6, 0x8]\n\ + movs r0, 0x1\n\ + strh r0, [r6, 0xA]\n\ + mov r0, r9\n\ + strh r0, [r7, 0xE]\n\ + b _08107B0E\n\ + .pool\n\ +_08107AB4:\n\ + ldr r0, =gBattleAnimAttacker\n\ + ldrb r0, [r0]\n\ + bl GetBattlerSide\n\ + lsls r0, 24\n\ + lsrs r1, r0, 24\n\ + cmp r1, 0x1\n\ + bne _08107AF8\n\ + ldr r2, =0x0000ff20\n\ + adds r0, r2, 0\n\ + ldr r2, =gBattle_BG1_X\n\ + strh r0, [r2]\n\ + movs r2, 0x80\n\ + lsls r2, 1\n\ + adds r0, r2, 0\n\ + ldr r2, =gBattle_BG1_Y\n\ + strh r0, [r2]\n\ + movs r0, 0x2\n\ + strh r0, [r6, 0x8]\n\ + ldr r0, =0x0000ffff\n\ + strh r0, [r6, 0xA]\n\ + strh r1, [r7, 0xE]\n\ + b _08107B0E\n\ + .pool\n\ +_08107AF8:\n\ + ldr r0, =gBattle_BG1_X\n\ + strh r4, [r0]\n\ + ldr r1, =0x0000ffd0\n\ + adds r0, r1, 0\n\ + ldr r2, =gBattle_BG1_Y\n\ + strh r0, [r2]\n\ + ldr r0, =0x0000fffe\n\ + strh r0, [r6, 0x8]\n\ + movs r0, 0x1\n\ + strh r0, [r6, 0xA]\n\ + strh r4, [r7, 0xE]\n\ +_08107B0E:\n\ + ldr r0, =gBattle_BG1_X\n\ + ldrh r1, [r0]\n\ + movs r0, 0x14\n\ + bl SetGpuReg\n\ + ldr r2, =gBattle_BG1_Y\n\ + ldrh r1, [r2]\n\ + movs r0, 0x16\n\ + bl SetGpuReg\n\ + ldr r1, =gTasks\n\ + mov r2, r8\n\ + lsls r0, r2, 2\n\ + add r0, r8\n\ + lsls r0, 3\n\ + adds r1, r0, r1\n\ + movs r2, 0xE\n\ + ldrsh r0, [r1, r2]\n\ + cmp r0, 0\n\ + bne _08107B54\n\ + movs r0, 0x30\n\ + strh r0, [r1, 0x10]\n\ + movs r0, 0x70\n\ + b _08107B58\n\ + .pool\n\ +_08107B54:\n\ + movs r0, 0\n\ + strh r0, [r1, 0x10]\n\ +_08107B58:\n\ + strh r0, [r1, 0x12]\n\ + ldr r1, =gTasks\n\ + mov r2, r10\n\ + adds r0, r5, r2\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + movs r1, 0x1\n\ + strh r1, [r0, 0x14]\n\ + ldr r1, =AnimTask_CreateSurfWave_Step1\n\ + str r1, [r0]\n\ + add sp, 0x10\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n"); +} +#endif + +#ifdef NONMATCHING +static void AnimTask_CreateSurfWave_Step1(u8 taskId) +{ + struct BattleAnimBgData animBg; + u8 i; + u16 rgbBuffer; + u16 *BGptrX = &gBattle_BG1_X; + u16 *BGptrY = &gBattle_BG1_Y; + s16 unkUse; + u32 palOffset; + u16 palNum; + + *BGptrX += gTasks[taskId].data[0]; + *BGptrY += gTasks[taskId].data[1]; + sub_80752A0(&animBg); + gTasks[taskId].data[2] += gTasks[taskId].data[1]; + if (++gTasks[taskId].data[5] == 4) + { + rgbBuffer = gPlttBufferFaded[animBg.paletteId * 16 + 7]; + for (i = 6; i != 0; i--) + { + palNum = animBg.paletteId * 16; + palOffset = 1 + i; + gPlttBufferFaded[palNum + palOffset] = gPlttBufferFaded[palNum + palOffset - 1]; + } + gPlttBufferFaded[animBg.paletteId * 16 + 1] = rgbBuffer; + gTasks[taskId].data[5] = 0; + } + if (++gTasks[taskId].data[6] > 1) + { + gTasks[taskId].data[6] = 0; + unkUse = ++gTasks[taskId].data[3]; + if (unkUse <= 13) + { + gTasks[gTasks[taskId].data[15]].data[1] = unkUse | ((16 - unkUse) * 256); + gTasks[taskId].data[4]++; + } + if (gTasks[taskId].data[3] > 54) + { + unkUse = --gTasks[taskId].data[4]; + gTasks[gTasks[taskId].data[15]].data[1] = unkUse | ((16 - unkUse) * 256); + } + } + if (!(gTasks[gTasks[taskId].data[15]].data[1] & 0x1F)) + { + gTasks[taskId].data[0] = gTasks[gTasks[taskId].data[15]].data[1] & 0x1F; + gTasks[taskId].func = AnimTask_CreateSurfWave_Step2; + } +} +#else +NAKED +static void AnimTask_CreateSurfWave_Step1(u8 taskId) +{ + asm_unified("push {r4-r7,lr}\n\ + sub sp, 0x10\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + ldr r1, =gBattle_BG1_X\n\ + ldr r2, =gBattle_BG1_Y\n\ + ldr r0, =gTasks\n\ + lsls r4, r5, 2\n\ + adds r4, r5\n\ + lsls r4, 3\n\ + adds r4, r0\n\ + ldrh r0, [r4, 0x8]\n\ + ldrh r3, [r1]\n\ + adds r0, r3\n\ + strh r0, [r1]\n\ + ldrh r0, [r4, 0xA]\n\ + ldrh r1, [r2]\n\ + adds r0, r1\n\ + strh r0, [r2]\n\ + mov r0, sp\n\ + bl sub_80752A0\n\ + ldrh r0, [r4, 0xA]\n\ + ldrh r3, [r4, 0xC]\n\ + adds r0, r3\n\ + strh r0, [r4, 0xC]\n\ + ldrh r0, [r4, 0x12]\n\ + adds r0, 0x1\n\ + strh r0, [r4, 0x12]\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + cmp r0, 0x4\n\ + bne _08107C18\n\ + ldr r1, =gPlttBufferFaded\n\ + mov r0, sp\n\ + ldrb r0, [r0, 0x8]\n\ + lsls r0, 4\n\ + adds r0, 0x7\n\ + lsls r0, 1\n\ + adds r0, r1\n\ + ldrh r6, [r0]\n\ + movs r2, 0x6\n\ + adds r7, r1, 0\n\ + adds r3, r7, 0\n\ + mov r4, sp\n\ +_08107BDE:\n\ + ldrb r0, [r4, 0x8]\n\ + lsls r0, 4\n\ + adds r1, r2, 0x1\n\ + adds r0, r1\n\ + lsls r1, r0, 1\n\ + adds r1, r3\n\ + subs r0, 0x1\n\ + lsls r0, 1\n\ + adds r0, r3\n\ + ldrh r0, [r0]\n\ + strh r0, [r1]\n\ + subs r0, r2, 0x1\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + cmp r2, 0\n\ + bne _08107BDE\n\ + mov r0, sp\n\ + ldrb r0, [r0, 0x8]\n\ + lsls r0, 4\n\ + adds r0, 0x1\n\ + lsls r0, 1\n\ + adds r0, r7\n\ + strh r6, [r0]\n\ + ldr r1, =gTasks\n\ + lsls r0, r5, 2\n\ + adds r0, r5\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + strh r2, [r0, 0x12]\n\ +_08107C18:\n\ + ldr r1, =gTasks\n\ + lsls r2, r5, 2\n\ + adds r0, r2, r5\n\ + lsls r0, 3\n\ + adds r3, r0, r1\n\ + ldrh r0, [r3, 0x14]\n\ + adds r0, 0x1\n\ + strh r0, [r3, 0x14]\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + adds r4, r1, 0\n\ + adds r6, r2, 0\n\ + cmp r0, 0x1\n\ + ble _08107C86\n\ + movs r0, 0\n\ + strh r0, [r3, 0x14]\n\ + ldrh r0, [r3, 0xE]\n\ + adds r2, r0, 0x1\n\ + strh r2, [r3, 0xE]\n\ + lsls r0, r2, 16\n\ + asrs r0, 16\n\ + cmp r0, 0xD\n\ + bgt _08107C62\n\ + movs r1, 0x26\n\ + ldrsh r0, [r3, r1]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 3\n\ + adds r1, r4\n\ + movs r0, 0x10\n\ + subs r0, r2\n\ + lsls r0, 8\n\ + orrs r2, r0\n\ + strh r2, [r1, 0xA]\n\ + ldrh r0, [r3, 0x10]\n\ + adds r0, 0x1\n\ + strh r0, [r3, 0x10]\n\ +_08107C62:\n\ + movs r1, 0xE\n\ + ldrsh r0, [r3, r1]\n\ + cmp r0, 0x36\n\ + ble _08107C86\n\ + ldrh r2, [r3, 0x10]\n\ + subs r2, 0x1\n\ + strh r2, [r3, 0x10]\n\ + movs r1, 0x26\n\ + ldrsh r0, [r3, r1]\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 3\n\ + adds r1, r4\n\ + movs r0, 0x10\n\ + subs r0, r2\n\ + lsls r0, 8\n\ + orrs r2, r0\n\ + strh r2, [r1, 0xA]\n\ +_08107C86:\n\ + adds r0, r6, r5\n\ + lsls r0, 3\n\ + adds r2, r0, r4\n\ + movs r3, 0x26\n\ + ldrsh r1, [r2, r3]\n\ + lsls r0, r1, 2\n\ + adds r0, r1\n\ + lsls r0, 3\n\ + adds r0, r4\n\ + ldrh r0, [r0, 0xA]\n\ + movs r3, 0x1F\n\ + ands r3, r0\n\ + cmp r3, 0\n\ + bne _08107CA8\n\ + strh r3, [r2, 0x8]\n\ + ldr r0, =AnimTask_CreateSurfWave_Step2\n\ + str r0, [r2]\n\ +_08107CA8:\n\ + add sp, 0x10\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n"); +} +#endif + +static void AnimTask_CreateSurfWave_Step2(u8 taskId) +{ + u16 *BGptrX = &gBattle_BG1_X; + u16 *BGptrY = &gBattle_BG1_Y; + if (gTasks[taskId].data[0] == 0) + { + sub_8075358(1); + sub_8075358(2); + gTasks[taskId].data[0]++; + } + else + { + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); + *BGptrX = 0; + *BGptrY = 0; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + gTasks[gTasks[taskId].data[15]].data[15] = -1; + DestroyAnimVisualTask(taskId); + } +} + +static void AnimTask_SurfWaveScanlineEffect(u8 taskId) +{ + s16 i; + struct ScanlineEffectParams params; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + for (i = 0; i < task->data[4]; i++) + gScanlineEffectRegBuffers[0][i] = gScanlineEffectRegBuffers[1][i] = task->data[2]; + for (i = task->data[4]; i < task->data[5]; i++) + gScanlineEffectRegBuffers[0][i] = gScanlineEffectRegBuffers[1][i] = task->data[1]; + for (i = task->data[5]; i < 160; i++) + gScanlineEffectRegBuffers[0][i] = gScanlineEffectRegBuffers[1][i] = task->data[2]; + + if (task->data[4] == 0) + gScanlineEffectRegBuffers[0][i] = gScanlineEffectRegBuffers[1][i] = task->data[1]; + else + gScanlineEffectRegBuffers[0][i] = gScanlineEffectRegBuffers[1][i] = task->data[2]; + + params.dmaDest = (vu16 *)REG_ADDR_BLDALPHA; + params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; + params.initState = 1; + params.unused9 = 0; + ScanlineEffect_SetParams(params); + task->data[0]++; + break; + case 1: + if (task->data[3] == 0) + { + if (--task->data[4] <= 0) + { + task->data[4] = 0; + task->data[0]++; + } + } + else if (++task->data[5] > 111) + { + task->data[0]++; + } + + for (i = 0; i < task->data[4]; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = task->data[2]; + for (i = task->data[4]; i < task->data[5]; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = task->data[1]; + for (i = task->data[5]; i < 160; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = task->data[2]; + break; + case 2: + for (i = 0; i < task->data[4]; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = task->data[2]; + for (i = task->data[4]; i < task->data[5]; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = task->data[1]; + for (i = task->data[5]; i < 160; i++) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = task->data[2]; + + if (task->data[15] == -1) + { + ScanlineEffect_Stop(); + DestroyTask(taskId); + } + break; + } +} + +static void AnimSmallDriftingBubbles(struct Sprite *sprite) +{ + s16 randData; + s16 randData2; + + sprite->oam.tileNum += 8; + InitSpritePosToAnimTarget(sprite, TRUE); + randData = (Random() & 0xFF) | 256; + randData2 = (Random() & 0x1FF); + if (randData2 > 255) + randData2 = 256 - randData2; + sprite->data[1] = randData; + sprite->data[2] = randData2; + sprite->callback = AnimSmallDriftingBubbles_Step; +} + +static void AnimSmallDriftingBubbles_Step(struct Sprite *sprite) +{ + sprite->data[3] += sprite->data[1]; + sprite->data[4] += sprite->data[2]; + if (sprite->data[1] & 1) + sprite->pos2.x = -(sprite->data[3] >> 8); + else + sprite->pos2.x = sprite->data[3] >> 8; + sprite->pos2.y = sprite->data[4] >> 8; + if (++sprite->data[0] == 21) + DestroyAnimSprite(sprite); +} + +void AnimTask_WaterSpoutLaunch(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[5] = gSprites[task->data[15]].pos1.y; + task->data[1] = GetWaterSpoutPowerForAnim(); + PrepareBattlerSpriteForRotScale(task->data[15], ST_OAM_OBJ_NORMAL); + task->func = AnimTask_WaterSpoutLaunch_Step; +} + +static void AnimTask_WaterSpoutLaunch_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + sub_80765D4(task, task->data[15], 0x100, 0x100, 224, 0x200, 32); + task->data[0]++; + case 1: + if (++task->data[3] > 1) + { + task->data[3] = 0; + if (++task->data[4] & 1) + { + gSprites[task->data[15]].pos2.x = 3; + gSprites[task->data[15]].pos1.y++; + } + else + { + gSprites[task->data[15]].pos2.x = -3; + } + } + if (sub_8076640(task) == 0) + { + SetBattlerSpriteYOffsetFromYScale(task->data[15]); + gSprites[task->data[15]].pos2.x = 0; + task->data[3] = 0; + task->data[4] = 0; + task->data[0]++; + } + break; + case 2: + if (++task->data[3] > 4) + { + sub_80765D4(task, task->data[15], 224, 0x200, 384, 224, 8); + task->data[3] = 0; + task->data[0]++; + } + break; + case 3: + if (sub_8076640(task) == 0) + { + task->data[3] = 0; + task->data[4] = 0; + task->data[0]++; + } + break; + case 4: + CreateWaterSpoutLaunchDroplets(task, taskId); + task->data[0]++; + case 5: + if (++task->data[3] > 1) + { + task->data[3] = 0; + if (++task->data[4] & 1) + gSprites[task->data[15]].pos2.y += 2; + else + gSprites[task->data[15]].pos2.y -= 2; + if (task->data[4] == 10) + { + sub_80765D4(task, task->data[15], 384, 224, 0x100, 0x100, 8); + task->data[3] = 0; + task->data[4] = 0; + task->data[0]++; + } + } + break; + case 6: + gSprites[task->data[15]].pos1.y--; + if (sub_8076640(task) == 0) + { + ResetSpriteRotScale(task->data[15]); + gSprites[task->data[15]].pos1.y = task->data[5]; + task->data[4] = 0; + task->data[0]++; + } + break; + case 7: + if (task->data[2] == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + +// Returns a value 0-3 relative to which quarter HP the attacker is in +// A higher number results in more water sprites during the Water Spout animation +static u8 GetWaterSpoutPowerForAnim(void) +{ + u8 i; + u16 hp; + u16 maxhp; + u16 partyIndex; + struct Pokemon *slot; + + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + partyIndex = gBattlerPartyIndexes[gBattleAnimAttacker]; + slot = &gPlayerParty[partyIndex]; + maxhp = GetMonData(slot, MON_DATA_MAX_HP); + hp = GetMonData(slot, MON_DATA_HP); + maxhp /= 4; + } + else + { + partyIndex = gBattlerPartyIndexes[gBattleAnimAttacker]; + slot = &gEnemyParty[partyIndex]; + maxhp = GetMonData(slot, MON_DATA_MAX_HP); + hp = GetMonData(slot, MON_DATA_HP); + maxhp /= 4; + } + for (i = 0; i < 3; i++) + { + if (hp < maxhp * (i + 1)) + return i; + } + return 3; +} + +static void CreateWaterSpoutLaunchDroplets(struct Task *task, u8 taskId) +{ + s16 i; + s16 attackerCoordX = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + s16 attackerCoordY = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + s16 trigIndex = 172; + u8 subpriority = GetBattlerSpriteSubpriority(gBattleAnimAttacker) - 1; + s16 increment = 4 - task->data[1]; + u8 spriteId; + + if (increment <= 0) + increment = 1; + for (i = 0; i < 20; i += increment) + { + spriteId = CreateSprite(&gSmallWaterOrbSpriteTemplate, attackerCoordX, attackerCoordY, subpriority); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].data[1] = i; + gSprites[spriteId].data[2] = attackerCoordX * 16; + gSprites[spriteId].data[3] = attackerCoordY * 16; + gSprites[spriteId].data[4] = Cos(trigIndex, 64); + gSprites[spriteId].data[5] = Sin(trigIndex, 64); + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = 2; + if (task->data[2] & 1) + AnimSmallWaterOrb(&gSprites[spriteId]); + task->data[2]++; + } + trigIndex = (trigIndex + increment * 2); + trigIndex &= 0xFF; + } +} + +static void AnimSmallWaterOrb(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->data[4] += (sprite->data[1] % 6) * 3; + sprite->data[5] += (sprite->data[1] % 3) * 3; + sprite->data[0]++; + case 1: + sprite->data[2] += sprite->data[4]; + sprite->data[3] += sprite->data[5]; + sprite->pos1.x = sprite->data[2] >> 4; + sprite->pos1.y = sprite->data[3] >> 4; + if (sprite->pos1.x < -8 || sprite->pos1.x > 248 || sprite->pos1.y < -8 || sprite->pos1.y > 120) + { + gTasks[sprite->data[6]].data[sprite->data[7]]--; + DestroySprite(sprite); + } + break; + } +} + +void AnimTask_WaterSpoutRain(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[1] = GetWaterSpoutPowerForAnim(); + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + task->data[4] = 136; + task->data[6] = 40; + } + else + { + task->data[4] = 16; + task->data[6] = 80; + } + task->data[5] = 98; + task->data[7] = task->data[4] + 49; + task->data[12] = task->data[1] * 5 + 5; + task->func = AnimTask_WaterSpoutRain_Step; +} + +static void AnimTask_WaterSpoutRain_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 taskId2; + + switch (task->data[0]) + { + case 0: + if (++task->data[2] > 2) + { + task->data[2] = 0; + CreateWaterSpoutRainDroplet(task, taskId); + } + if (task->data[10] != 0 && task->data[13] == 0) + { + gBattleAnimArgs[0] = ANIM_TARGET; + gBattleAnimArgs[1] = 0; + gBattleAnimArgs[2] = 12; + taskId2 = CreateTask(AnimTask_HorizontalShake, 80); + if (taskId2 != 0xFF) + { + gTasks[taskId2].func(taskId2); + gAnimVisualTaskCount++; + } + gBattleAnimArgs[0] = ANIM_DEF_PARTNER; + taskId2 = CreateTask(AnimTask_HorizontalShake, 80); + if (taskId2 != 0xFF) + { + gTasks[taskId2].func(taskId2); + gAnimVisualTaskCount++; + } + task->data[13] = 1; + } + if (task->data[11] >= task->data[12]) + task->data[0]++; + break; + case 1: + if (task->data[9] == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + +static void CreateWaterSpoutRainDroplet(struct Task *task, u8 taskId) +{ + u16 yPosArg = ((gSineTable[task->data[8]] + 3) >> 4) + task->data[6]; + u8 spriteId = CreateSprite(&gSmallWaterOrbSpriteTemplate, task->data[7], 0, 0); + + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].callback = AnimWaterSpoutRain; + gSprites[spriteId].data[5] = yPosArg; + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = 9; + task->data[9]++; + } + task->data[11]++; + task->data[8] = (task->data[8] + 39) & 0xFF; + task->data[7] = (ISO_RANDOMIZE2(task->data[7]) % task->data[5]) + task->data[4]; +} + +static void AnimWaterSpoutRain(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + sprite->pos1.y += 8; + if (sprite->pos1.y >= sprite->data[5]) + { + gTasks[sprite->data[6]].data[10] = 1; + sprite->data[1] = CreateSprite(&gWaterHitSplatSpriteTemplate, sprite->pos1.x, sprite->pos1.y, 1); + if (sprite->data[1] != MAX_SPRITES) + { + StartSpriteAffineAnim(&gSprites[sprite->data[1]], 3); + gSprites[sprite->data[1]].data[6] = sprite->data[6]; + gSprites[sprite->data[1]].data[7] = sprite->data[7]; + gSprites[sprite->data[1]].callback = AnimWaterSpoutRainHit; + } + DestroySprite(sprite); + } + } +} + +static void AnimWaterSpoutRainHit(struct Sprite *sprite) +{ + if (++sprite->data[1] > 1) + { + sprite->data[1] = 0; + sprite->invisible ^= 1; + if (++sprite->data[2] == 12) + { + gTasks[sprite->data[6]].data[sprite->data[7]]--; + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } + } +} + +void AnimTask_WaterSport(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[3] = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + task->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + task->data[7] = (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) ? 1 : -1; + if (IsContest()) + task->data[7] *= -1; + task->data[5] = task->data[3] + task->data[7] * 8; + task->data[6] = task->data[4] - task->data[7] * 8; + task->data[9] = -32; + task->data[1] = 0; + task->data[0] = 0; + task->func = AnimTask_WaterSport_Step; +} + +static void AnimTask_WaterSport_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + CreateWaterSportDroplet(task); + if (task->data[10] != 0) + task->data[0]++; + break; + case 1: + CreateWaterSportDroplet(task); + if (++task->data[1] > 16) + { + task->data[1] = 0; + task->data[0]++; + } + break; + case 2: + CreateWaterSportDroplet(task); + task->data[5] += task->data[7] * 6; + if (!(task->data[5] >= -16 && task->data[5] <= 256)) + { + if (++task->data[12] > 2) + { + task->data[13] = 1; + task->data[0] = 6; + task->data[1] = 0; + } + else + { + task->data[1] = 0; + task->data[0]++; + } + } + break; + case 3: + CreateWaterSportDroplet(task); + task->data[6] -= task->data[7] * 2; + if (++task->data[1] > 7) + task->data[0]++; + break; + case 4: + CreateWaterSportDroplet(task); + task->data[5] -= task->data[7] * 6; + if (!(task->data[5] >= -16 && task->data[5] <= 256)) + { + task->data[12]++; + task->data[1] = 0; + task->data[0]++; + } + break; + case 5: + CreateWaterSportDroplet(task); + task->data[6] -= task->data[7] * 2; + if (++task->data[1] > 7) + task->data[0] = 2; + break; + case 6: + if (task->data[8] == 0) + task->data[0]++; + break; + default: + DestroyAnimVisualTask(taskId); + break; + } +} + +static void CreateWaterSportDroplet(struct Task *task) +{ + u8 spriteId; + + if (++task->data[2] > 1) + { + task->data[2] = 0; + spriteId = CreateSprite(&gSmallWaterOrbSpriteTemplate, task->data[3], task->data[4], 10); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].data[0] = 16; + gSprites[spriteId].data[2] = task->data[5]; + gSprites[spriteId].data[4] = task->data[6]; + gSprites[spriteId].data[5] = task->data[9]; + InitAnimArcTranslation(&gSprites[spriteId]); + gSprites[spriteId].callback = AnimWaterSportDroplet; + task->data[8]++; + } + } +} + +static void AnimWaterSportDroplet(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->data[0] = 6; + sprite->data[2] = (Random() & 0x1F) - 16 + sprite->pos1.x; + sprite->data[4] = (Random() & 0x1F) - 16 + sprite->pos1.y; + sprite->data[5] = ~(Random() & 7); + InitAnimArcTranslation(sprite); + sprite->callback = AnimWaterSportDroplet_Step; + } +} + +static void AnimWaterSportDroplet_Step(struct Sprite *sprite) +{ + u16 i; + + if (TranslateAnimHorizontalArc(sprite)) + { + for (i = 0; i < NUM_TASKS; i++) + { + if (gTasks[i].func == AnimTask_WaterSport_Step) + { + gTasks[i].data[10] = 1; + gTasks[i].data[8]--; + DestroySprite(sprite); + } + } + } +} + +static void AnimWaterPulseBubble(struct Sprite *sprite) +{ + sprite->pos1.x = gBattleAnimArgs[0]; + sprite->pos1.y = gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[2] = gBattleAnimArgs[4]; + sprite->data[3] = gBattleAnimArgs[5]; + sprite->callback = AnimWaterPulseBubble_Step; +} + +static void AnimWaterPulseBubble_Step(struct Sprite *sprite) +{ + sprite->data[4] -= sprite->data[0]; + sprite->pos2.y = sprite->data[4] / 10; + sprite->data[5] = (sprite->data[5] + sprite->data[1]) & 0xFF; + sprite->pos2.x = Sin(sprite->data[5], sprite->data[2]); + if (--sprite->data[3] == 0) + DestroyAnimSprite(sprite); +} + +static void AnimWaterPulseRingBubble(struct Sprite *sprite) +{ + sprite->data[3] += sprite->data[1]; + sprite->data[4] += sprite->data[2]; + sprite->pos2.x = sprite->data[3] >> 7; + sprite->pos2.y = sprite->data[4] >> 7; + if (--sprite->data[0] == 0) + { + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + } +} + +void AnimWaterPulseRing(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->data[3] = gBattleAnimArgs[2]; + sprite->data[4] = gBattleAnimArgs[3]; + sprite->callback = AnimWaterPulseRing_Step; +} + +static void AnimWaterPulseRing_Step(struct Sprite *sprite) +{ + int xDiff = sprite->data[1] - sprite->pos1.x; + int yDiff = sprite->data[2] - sprite->pos1.y; + + sprite->pos2.x = (sprite->data[0] * xDiff) / sprite->data[3]; + sprite->pos2.y = (sprite->data[0] * yDiff) / sprite->data[3]; + if (++sprite->data[5] == sprite->data[4]) + { + sprite->data[5] = 0; + CreateWaterPulseRingBubbles(sprite, xDiff, yDiff); + } + if (sprite->data[3] == sprite->data[0]) + DestroyAnimSprite(sprite); + sprite->data[0]++; +} + +#ifdef NONMATCHING +static void CreateWaterPulseRingBubbles(struct Sprite *sprite, int xDiff, int yDiff) +{ + s16 something = sprite->data[0] / 2; + s16 combinedX = sprite->pos1.x + sprite->pos2.x; + s16 combinedY = sprite->pos1.y + sprite->pos2.y; + s16 randomSomethingY = yDiff + (Random() % 10) - 5; + s16 randomSomethingX = -xDiff + (Random() % 10) - 5; + s16 i; + u8 spriteId; + + for (i = 0; i <= 0; i++) + { + spriteId = CreateSprite(&gWaterPulseRingBubbleSpriteTemplate, combinedX, combinedY + something, 130); + gSprites[spriteId].data[0] = 20; + gSprites[spriteId].data[1] = randomSomethingY; + gSprites[spriteId].subpriority = GetBattlerSpriteSubpriority(gBattleAnimAttacker) - 1; + if (randomSomethingX < 0) + gSprites[spriteId].data[2] = -randomSomethingX; + else + gSprites[spriteId].data[2] = randomSomethingX; + } + for (i = 0; i <= 0; i++) + { + spriteId = CreateSprite(&gWaterPulseRingBubbleSpriteTemplate, combinedX, combinedY - something, 130); + gSprites[spriteId].data[0] = 20; + gSprites[spriteId].data[1] = randomSomethingY; + gSprites[spriteId].subpriority = GetBattlerSpriteSubpriority(gBattleAnimAttacker) - 1; + if (randomSomethingX > 0) + gSprites[spriteId].data[2] = -randomSomethingX; + else + gSprites[spriteId].data[2] = randomSomethingX; + } +} +#else +NAKED +static void CreateWaterPulseRingBubbles(struct Sprite *sprite, int xDiff, int yDiff) +{ + asm_unified("push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x18\n\ + adds r4, r1, 0\n\ + adds r5, r2, 0\n\ + movs r2, 0x2E\n\ + ldrsh r1, [r0, r2]\n\ + lsrs r2, r1, 31\n\ + adds r1, r2\n\ + lsls r1, 15\n\ + lsrs r1, 16\n\ + str r1, [sp]\n\ + ldrh r1, [r0, 0x24]\n\ + ldrh r3, [r0, 0x20]\n\ + adds r1, r3\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + mov r8, r1\n\ + ldrh r1, [r0, 0x26]\n\ + ldrh r0, [r0, 0x22]\n\ + adds r1, r0\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + mov r10, r1\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0xA\n\ + bl __umodsi3\n\ + adds r0, r5, r0\n\ + subs r0, 0x5\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + mov r9, r0\n\ + bl Random\n\ + negs r4, r4\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0xA\n\ + bl __umodsi3\n\ + adds r4, r0\n\ + subs r4, 0x5\n\ + lsls r4, 16\n\ + lsrs r7, r4, 16\n\ + movs r6, 0\n\ + mov r0, r8\n\ + lsls r0, 16\n\ + mov r8, r0\n\ + mov r1, r10\n\ + lsls r1, 16\n\ + str r1, [sp, 0xC]\n\ + ldr r2, [sp]\n\ + lsls r2, 16\n\ + str r2, [sp, 0x10]\n\ + asrs r1, 16\n\ + lsls r0, r7, 16\n\ + asrs r5, r0, 16\n\ + str r0, [sp, 0x14]\n\ + negs r3, r5\n\ + str r3, [sp, 0x4]\n\ + asrs r0, r2, 16\n\ + adds r1, r0\n\ + lsls r1, 16\n\ + mov r10, r1\n\ +_08108DE2:\n\ + ldr r0, =gWaterPulseRingBubbleSpriteTemplate\n\ + mov r2, r8\n\ + asrs r1, r2, 16\n\ + mov r3, r10\n\ + asrs r2, r3, 16\n\ + movs r3, 0x82\n\ + bl CreateSprite\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + ldr r1, =gSprites\n\ + lsls r0, r2, 4\n\ + adds r0, r2\n\ + lsls r0, 2\n\ + adds r4, r0, r1\n\ + movs r0, 0x14\n\ + strh r0, [r4, 0x2E]\n\ + mov r0, r9\n\ + strh r0, [r4, 0x30]\n\ + ldr r0, =gBattleAnimAttacker\n\ + ldrb r0, [r0]\n\ + bl GetBattlerSpriteSubpriority\n\ + subs r0, 0x1\n\ + adds r1, r4, 0\n\ + adds r1, 0x43\n\ + strb r0, [r1]\n\ + cmp r5, 0\n\ + bge _08108E30\n\ + mov r1, sp\n\ + ldrh r1, [r1, 0x4]\n\ + strh r1, [r4, 0x32]\n\ + b _08108E32\n\ + .pool\n\ +_08108E30:\n\ + strh r7, [r4, 0x32]\n\ +_08108E32:\n\ + lsls r0, r6, 16\n\ + movs r2, 0x80\n\ + lsls r2, 9\n\ + adds r0, r2\n\ + lsrs r6, r0, 16\n\ + cmp r0, 0\n\ + ble _08108DE2\n\ + movs r6, 0\n\ + ldr r3, [sp, 0xC]\n\ + asrs r1, r3, 16\n\ + ldr r0, [sp, 0x14]\n\ + asrs r5, r0, 16\n\ + negs r2, r5\n\ + str r2, [sp, 0x8]\n\ + ldr r3, [sp, 0x10]\n\ + asrs r0, r3, 16\n\ + subs r1, r0\n\ + lsls r1, 16\n\ + mov r10, r1\n\ +_08108E58:\n\ + ldr r0, =gWaterPulseRingBubbleSpriteTemplate\n\ + mov r2, r8\n\ + asrs r1, r2, 16\n\ + mov r3, r10\n\ + asrs r2, r3, 16\n\ + movs r3, 0x82\n\ + bl CreateSprite\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + ldr r1, =gSprites\n\ + lsls r0, r2, 4\n\ + adds r0, r2\n\ + lsls r0, 2\n\ + adds r4, r0, r1\n\ + movs r0, 0x14\n\ + strh r0, [r4, 0x2E]\n\ + mov r0, r9\n\ + strh r0, [r4, 0x30]\n\ + ldr r0, =gBattleAnimAttacker\n\ + ldrb r0, [r0]\n\ + bl GetBattlerSpriteSubpriority\n\ + subs r0, 0x1\n\ + adds r1, r4, 0\n\ + adds r1, 0x43\n\ + strb r0, [r1]\n\ + cmp r5, 0\n\ + ble _08108EA8\n\ + mov r1, sp\n\ + ldrh r1, [r1, 0x8]\n\ + strh r1, [r4, 0x32]\n\ + b _08108EAA\n\ + .pool\n\ +_08108EA8:\n\ + strh r7, [r4, 0x32]\n\ +_08108EAA:\n\ + lsls r0, r6, 16\n\ + movs r2, 0x80\n\ + lsls r2, 9\n\ + adds r0, r2\n\ + lsrs r6, r0, 16\n\ + cmp r0, 0\n\ + ble _08108E58\n\ + add sp, 0x18\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n"); +} +#endif
\ No newline at end of file |