From 51cd0ac08116674a8ebd258af0620c2f7de9dc0e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 23 Feb 2020 13:18:54 -0500 Subject: Rename battle anim type files, remove unneeded ARG_RET_IDs --- data/battle_anim_scripts.s | 40 +- include/battle_anim.h | 18 +- include/constants/battle_anim.h | 2 +- ld_script.txt | 64 +- src/battle_anim_bug.c | 492 +++++++++ src/battle_anim_dark.c | 993 ++++++++++++++++++ src/battle_anim_dragon.c | 440 ++++++++ src/battle_anim_effects_1.c | 12 +- src/battle_anim_effects_2.c | 4 +- src/battle_anim_effects_3.c | 10 +- src/battle_anim_electric.c | 1329 +++++++++++++++++++++++ src/battle_anim_fight.c | 1043 ++++++++++++++++++ src/battle_anim_fire.c | 1335 +++++++++++++++++++++++ src/battle_anim_flying.c | 1248 ++++++++++++++++++++++ src/battle_anim_ghost.c | 1341 +++++++++++++++++++++++ src/battle_anim_ground.c | 772 ++++++++++++++ src/battle_anim_ice.c | 1571 +++++++++++++++++++++++++++ src/battle_anim_normal.c | 1023 ++++++++++++++++++ src/battle_anim_poison.c | 319 ++++++ src/battle_anim_psychic.c | 1168 +++++++++++++++++++++ src/battle_anim_rock.c | 875 +++++++++++++++ src/battle_anim_smokescreen.c | 217 ++++ src/battle_anim_utility_funcs.c | 4 +- src/battle_anim_water.c | 2219 +++++++++++++++++++++++++++++++++++++++ src/bug.c | 492 --------- src/dark.c | 993 ------------------ src/dragon.c | 440 -------- src/electric.c | 1329 ----------------------- src/fight.c | 1043 ------------------ src/fire.c | 1335 ----------------------- src/flying.c | 1248 ---------------------- src/ghost.c | 1341 ----------------------- src/ground.c | 772 -------------- src/ice.c | 1571 --------------------------- src/normal.c | 1023 ------------------ src/poison.c | 319 ------ src/psychic.c | 1168 --------------------- src/rock.c | 875 --------------- src/smokescreen.c | 217 ---- src/water.c | 2219 --------------------------------------- sym_ewram.txt | 2 +- 41 files changed, 16462 insertions(+), 16464 deletions(-) create mode 100644 src/battle_anim_bug.c create mode 100644 src/battle_anim_dark.c create mode 100644 src/battle_anim_dragon.c create mode 100644 src/battle_anim_electric.c create mode 100644 src/battle_anim_fight.c create mode 100644 src/battle_anim_fire.c create mode 100644 src/battle_anim_flying.c create mode 100644 src/battle_anim_ghost.c create mode 100644 src/battle_anim_ground.c create mode 100644 src/battle_anim_ice.c create mode 100644 src/battle_anim_normal.c create mode 100644 src/battle_anim_poison.c create mode 100644 src/battle_anim_psychic.c create mode 100644 src/battle_anim_rock.c create mode 100644 src/battle_anim_smokescreen.c create mode 100644 src/battle_anim_water.c delete mode 100644 src/bug.c delete mode 100644 src/dark.c delete mode 100644 src/dragon.c delete mode 100644 src/electric.c delete mode 100644 src/fight.c delete mode 100644 src/fire.c delete mode 100644 src/flying.c delete mode 100644 src/ghost.c delete mode 100644 src/ground.c delete mode 100644 src/ice.c delete mode 100644 src/normal.c delete mode 100644 src/poison.c delete mode 100644 src/psychic.c delete mode 100644 src/rock.c delete mode 100644 src/smokescreen.c delete mode 100644 src/water.c diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index dfcc80748..23416bde8 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -1228,7 +1228,7 @@ Move_HIDDEN_POWER: createsprite gHiddenPowerOrbSpriteTemplate, ANIM_ATTACKER, 2, 26, 168 createsprite gHiddenPowerOrbSpriteTemplate, ANIM_ATTACKER, 2, 26, 210 delay 52 - setarg 7, -1 + setarg 7, 0xFFFF playsewithpan SE_W115, SOUND_PAN_ATTACKER createvisualtask AnimTask_ScaleMonAndRestore, 5, -7, -7, 11, ANIM_ATTACKER, 0 createsprite gHiddenPowerOrbScatterSpriteTemplate, ANIM_TARGET, 2, 0 @@ -2075,7 +2075,7 @@ Move_LOCK_ON: createsprite gLockOnMoveTargetSpriteTemplate, ANIM_ATTACKER, 40, 3 createsprite gLockOnMoveTargetSpriteTemplate, ANIM_ATTACKER, 40, 4 @ Also transitions to red target delay 120 - setarg 7, -1 @ Signal target to flash/disappear + setarg 7, 0xFFFF @ Signal target to flash/disappear waitforvisualfinish end @@ -2518,7 +2518,7 @@ HornDrillContinue: waitforvisualfinish restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein end @@ -2628,7 +2628,7 @@ Move_FISSURE: delay 40 restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein end @@ -3146,7 +3146,7 @@ MachPunchContinue: blendoff restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein end MachPunchAgainstPlayer: @@ -3418,7 +3418,7 @@ ExtremeSpeedContinue: waitforvisualfinish restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein clearmonbg ANIM_TARGET blendoff @@ -4814,7 +4814,7 @@ Move_THUNDER: waitforvisualfinish restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein end @@ -5403,7 +5403,7 @@ Move_AURORA_BEAM: call AuroraBeamCreateRings call AuroraBeamCreateRings call AuroraBeamCreateRings - setarg 7, -1 + setarg 7, 0xFFFF createsoundtask SoundTask_LoopSEAdjustPanning, SE_W062B, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 6, 0, 10 createvisualtask AnimTask_ShakeMon2, 5, ANIM_TARGET, 2, 0, 40, 1 call AuroraBeamCreateRings @@ -5537,7 +5537,7 @@ BlizzardContinue: delay 20 restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein clearmonbg ANIM_DEF_PARTNER end @@ -6133,7 +6133,7 @@ MegahornContinue: blendoff restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein end MegahornInContest: @@ -7604,7 +7604,7 @@ Move_MIMIC: delay 15 createsprite gMimicOrbSpriteTemplate, ANIM_TARGET, 2, -12, 24 delay 10 - setarg 7, -1 + setarg 7, 0xFFFF waitforvisualfinish playsewithpan SE_W036, SOUND_PAN_ATTACKER createvisualtask AnimTask_BlendColorCycle, 2, 2, 0, 2, 0, 11, RGB_WHITE @@ -7626,7 +7626,7 @@ Move_CONSTRICT: createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 3, 0, 6, 1 delay 20 playsewithpan SE_W020, SOUND_PAN_TARGET - setarg 7, -1 + setarg 7, 0xFFFF waitforvisualfinish end @@ -7692,7 +7692,7 @@ Move_SOFT_BOILED: delay 8 createsprite gThinRingExpandingSpriteTemplate, ANIM_ATTACKER, 3, 31, 16, 0, 1 delay 60 - setarg 7, -1 + setarg 7, 0xFFFF waitforvisualfinish clearmonbg ANIM_ATK_PARTNER call HealingEffect2 @@ -9070,7 +9070,7 @@ Move_COSMIC_POWER: waitforvisualfinish restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein waitforvisualfinish end @@ -9200,7 +9200,7 @@ SilverWindContinue: restorebg waitbgfadeout createvisualtask AnimTask_BlendBattleAnimPalExclude, 10, ANIM_TARGET, 0, 4, 0, RGB_BLACK - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein end SilverWindOnPlayer: @@ -9628,7 +9628,7 @@ Move_SKY_UPPERCUT: blendoff restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein end @@ -9729,7 +9729,7 @@ Move_MAGICAL_LEAF: createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, 10, 4, ANIM_TARGET, 2 createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 2, 0, 8, 1 delay 20 - setarg 7, -1 + setarg 7, 0xFFFF waitforvisualfinish clearmonbg ANIM_DEF_PARTNER blendoff @@ -10164,7 +10164,7 @@ SetPsychicBackground: UnsetPsychicBackground: restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein return @@ -10185,7 +10185,7 @@ SetSkyBgContest: UnsetSkyBg: restorebg waitbgfadeout - setarg 7, -1 + setarg 7, 0xFFFF waitbgfadein return @@ -10366,7 +10366,7 @@ Status_BindWrap: delay 3 createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 2, 0, 8, 1 delay 20 - setarg 7, -1 + setarg 7, 0xFFFF playsewithpan SE_W020, SOUND_PAN_TARGET waitforvisualfinish end diff --git a/include/battle_anim.h b/include/battle_anim.h index f10a25733..18727cc73 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -157,6 +157,8 @@ void SetBattlerSpriteYOffsetFromOtherYScale(u8 spriteId, u8 otherSpriteId); u8 GetBattlerSide(u8 battler); u8 GetBattlerPosition(u8 battler); u8 GetBattlerAtPosition(u8 position); +void sub_80A64EC(struct Sprite *sprite); +void sub_80A718C(struct Sprite *sprite); enum { @@ -191,11 +193,7 @@ void SetSpritePrimaryCoordsFromSecondaryCoords(struct Sprite *sprite); u8 GetBattlerSpriteDefault_Y(u8 battlerId); u8 GetSubstituteSpriteDefault_Y(u8 battlerId); -// battle_anim_80A64EC.c -void sub_80A64EC(struct Sprite *sprite); -void sub_80A718C(struct Sprite *sprite); - -// battle_anim_status_effects.s +// battle_anim_status_effects.c #define STAT_ANIM_PLUS1 15 #define STAT_ANIM_PLUS2 39 #define STAT_ANIM_MINUS1 22 @@ -206,7 +204,7 @@ void sub_80A718C(struct Sprite *sprite); #define STAT_ANIM_MULTIPLE_MINUS2 58 void LaunchStatusAnimation(u8 battlerId, u8 statusAnimId); -// ground.c +// battle_anim_ground.c void AnimTask_HorizontalShake(u8 taskId); // battle_anim_special.c @@ -215,7 +213,7 @@ u8 ItemIdToBallId(u16 itemId); u8 AnimateBallOpenParticles(u8 x, u8 y, u8 priority, u8 subpriority, u8 ballId); u8 LaunchBallFadeMonTask(bool8 unFadeLater, u8 battlerId, u32 selectedPalettes, u8 ballId); -// battle_anim_utility_funcs.s +// battle_anim_utility_funcs.c void sub_8116EB4(u8); void sub_8117854(u8 taskId, int unused, u16 arg2, u8 battler1, u8 arg4, u8 arg5, u8 arg6, u8 arg7, const u32 *arg8, const u32 *arg9, const u32 *palette); @@ -224,13 +222,13 @@ void SetSpriteNextToMonHead(u8 battler, struct Sprite* sprite); void AnimMoveTwisterParticle(struct Sprite* sprite); void AnimParticleBurst(struct Sprite *); -// water.c +// battle_anim_water.c void AnimWaterPulseRing(struct Sprite *sprite); -// flying.c +// battle_anim_flying.c void DestroyAnimSpriteAfterTimer(struct Sprite *sprite); -// smokescreen.c +// battle_anim_smokescreen.c u8 SmokescreenImpact(s16 x, s16 y, u8 a3); u32 UnpackSelectedBattleAnimPalettes(s16); diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 6800da1c9..dfdd9f912 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -392,7 +392,7 @@ #define B_ANIM_STATUS_NIGHTMARE 0x8 #define B_ANIM_STATUS_WRAPPED 0x9 // does not actually exist -// Most tasks return a value to gBattleAnimArgs[7]. +// Tasks with return values often assign them to gBattleAnimArgs[7]. #define ARG_RET_ID 7 // Trapping Wrap-like moves end turn animation. diff --git a/ld_script.txt b/ld_script.txt index d841557c3..94b737c57 100644 --- a/ld_script.txt +++ b/ld_script.txt @@ -99,7 +99,7 @@ SECTIONS { src/daycare.o(.text); src/egg_hatch.o(.text); src/battle_interface.o(.text); - src/smokescreen.o(.text); + src/battle_anim_smokescreen.o(.text); src/pokeball.o(.text); src/load_save.o(.text); src/trade.o(.text); @@ -179,21 +179,21 @@ SECTIONS { src/item_use.o(.text); src/battle_anim_effects_1.o(.text); src/battle_anim_effects_2.o(.text); - src/water.o(.text); - src/fire.o(.text); - src/electric.o(.text); - src/ice.o(.text); - src/fight.o(.text); - src/poison.o(.text); - src/flying.o(.text); - src/psychic.o(.text); - src/bug.o(.text); - src/rock.o(.text); - src/ghost.o(.text); - src/dragon.o(.text); - src/dark.o(.text); - src/ground.o(.text); - src/normal.o(.text); + src/battle_anim_water.o(.text); + src/battle_anim_fire.o(.text); + src/battle_anim_electric.o(.text); + src/battle_anim_ice.o(.text); + src/battle_anim_fight.o(.text); + src/battle_anim_poison.o(.text); + src/battle_anim_flying.o(.text); + src/battle_anim_psychic.o(.text); + src/battle_anim_bug.o(.text); + src/battle_anim_rock.o(.text); + src/battle_anim_ghost.o(.text); + src/battle_anim_dragon.o(.text); + src/battle_anim_dark.o(.text); + src/battle_anim_ground.o(.text); + src/battle_anim_normal.o(.text); src/battle_anim_utility_funcs.o(.text); src/battle_intro.o(.text); src/bike.o(.text); @@ -470,7 +470,7 @@ SECTIONS { src/battle_util.o(.rodata); src/battle_script_commands.o(.rodata); src/battle_controller_player.o(.rodata); - src/smokescreen.o(.rodata); + src/battle_anim_smokescreen.o(.rodata); src/battle_controller_opponent.o(.rodata); src/battle_ai_switch_items.o(.rodata); src/battle_controller_link_opponent.o(.rodata); @@ -550,21 +550,21 @@ SECTIONS { src/item_use.o(.rodata); src/battle_anim_effects_1.o(.rodata); src/battle_anim_effects_2.o(.rodata); - src/water.o(.rodata); - src/fire.o(.rodata); - src/electric.o(.rodata); - src/ice.o(.rodata); - src/fight.o(.rodata); - src/poison.o(.rodata); - src/flying.o(.rodata); - src/psychic.o(.rodata); - src/bug.o(.rodata); - src/rock.o(.rodata); - src/ghost.o(.rodata); - src/dragon.o(.rodata); - src/dark.o(.rodata); - src/ground.o(.rodata); - src/normal.o(.rodata); + src/battle_anim_water.o(.rodata); + src/battle_anim_fire.o(.rodata); + src/battle_anim_electric.o(.rodata); + src/battle_anim_ice.o(.rodata); + src/battle_anim_fight.o(.rodata); + src/battle_anim_poison.o(.rodata); + src/battle_anim_flying.o(.rodata); + src/battle_anim_psychic.o(.rodata); + src/battle_anim_bug.o(.rodata); + src/battle_anim_rock.o(.rodata); + src/battle_anim_ghost.o(.rodata); + src/battle_anim_dragon.o(.rodata); + src/battle_anim_dark.o(.rodata); + src/battle_anim_ground.o(.rodata); + src/battle_anim_normal.o(.rodata); src/battle_anim_utility_funcs.o(.rodata); src/battle_intro.o(.rodata); src/bike.o(.rodata); diff --git a/src/battle_anim_bug.c b/src/battle_anim_bug.c new file mode 100644 index 000000000..ea3df8098 --- /dev/null +++ b/src/battle_anim_bug.c @@ -0,0 +1,492 @@ +#include "global.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "trig.h" +#include "constants/rgb.h" + +static void AnimMegahornHorn(struct Sprite *); +static void AnimLeechLifeNeedle(struct Sprite *); +static void AnimTranslateWebThread(struct Sprite *); +static void AnimTranslateWebThread_Step(struct Sprite *); +static void AnimStringWrap(struct Sprite *); +static void AnimStringWrap_Step(struct Sprite *); +static void AnimSpiderWeb(struct Sprite *); +static void AnimSpiderWeb_Step(struct Sprite *); +static void AnimSpiderWeb_End(struct Sprite *); +static void AnimTranslateStinger(struct Sprite *); +static void AnimMissileArc(struct Sprite *); +static void AnimMissileArc_Step(struct Sprite *); +static void AnimTailGlowOrb(struct Sprite *); + +static const union AffineAnimCmd sAffineAnim_MegahornHorn_0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 30, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_MegahornHorn_1[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -99, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_MegahornHorn_2[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 94, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_MegahornHorn[] = +{ + sAffineAnim_MegahornHorn_0, + sAffineAnim_MegahornHorn_1, + sAffineAnim_MegahornHorn_2, +}; + +const struct SpriteTemplate gMegahornHornSpriteTemplate = +{ + .tileTag = ANIM_TAG_HORN_HIT_2, + .paletteTag = ANIM_TAG_HORN_HIT_2, + .oam = &gOamData_AffineDouble_ObjNormal_32x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_MegahornHorn, + .callback = AnimMegahornHorn, +}; + +static const union AffineAnimCmd sAffineAnim_LeechLifeNeedle_0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -33, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_LeechLifeNeedle_1[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 96, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_LeechLifeNeedle_2[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -96, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_LeechLifeNeedle[] = +{ + sAffineAnim_LeechLifeNeedle_0, + sAffineAnim_LeechLifeNeedle_1, + sAffineAnim_LeechLifeNeedle_2, +}; + +const struct SpriteTemplate gLeechLifeNeedleSpriteTemplate = +{ + .tileTag = ANIM_TAG_NEEDLE, + .paletteTag = ANIM_TAG_NEEDLE, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_LeechLifeNeedle, + .callback = AnimLeechLifeNeedle, +}; + +const struct SpriteTemplate gWebThreadSpriteTemplate = +{ + .tileTag = ANIM_TAG_WEB_THREAD, + .paletteTag = ANIM_TAG_WEB_THREAD, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimTranslateWebThread, +}; + +const struct SpriteTemplate gStringWrapSpriteTemplate = +{ + .tileTag = ANIM_TAG_STRING, + .paletteTag = ANIM_TAG_STRING, + .oam = &gOamData_AffineOff_ObjNormal_64x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimStringWrap, +}; + +static const union AffineAnimCmd sAffineAnim_SpiderWeb[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x6, 0x6, 0, 1), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const sAffineAnims_SpiderWeb[] = +{ + sAffineAnim_SpiderWeb, +}; + +const struct SpriteTemplate gSpiderWebSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPIDER_WEB, + .paletteTag = ANIM_TAG_SPIDER_WEB, + .oam = &gOamData_AffineDouble_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_SpiderWeb, + .callback = AnimSpiderWeb, +}; + +const struct SpriteTemplate gLinearStingerSpriteTemplate = +{ + .tileTag = ANIM_TAG_NEEDLE, + .paletteTag = ANIM_TAG_NEEDLE, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimTranslateStinger, +}; + +const struct SpriteTemplate gPinMissileSpriteTemplate = +{ + .tileTag = ANIM_TAG_NEEDLE, + .paletteTag = ANIM_TAG_NEEDLE, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMissileArc, +}; + +const struct SpriteTemplate gIcicleSpearSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICICLE_SPEAR, + .paletteTag = ANIM_TAG_ICICLE_SPEAR, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMissileArc, +}; + +static const union AffineAnimCmd sAffineAnim_TailGlowOrb[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 18), + AFFINEANIMCMD_LOOP(0), + AFFINEANIMCMD_FRAME(0xFFFB, 0xFFFB, 0, 8), + AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 8), + AFFINEANIMCMD_LOOP(5), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_TailGlowOrb[] = +{ + sAffineAnim_TailGlowOrb, +}; + +const struct SpriteTemplate gTailGlowOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_TailGlowOrb, + .callback = AnimTailGlowOrb, +}; + +static void AnimMegahornHorn(struct Sprite *sprite) +{ + if (IsContest()) + { + StartSpriteAffineAnim(sprite, 2); + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + } + else if (!GetBattlerSide(gBattleAnimTarget)) + { + StartSpriteAffineAnim(sprite, 1); + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + } + + sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimTarget, 2) + gBattleAnimArgs[0]; + sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimTarget, 3) + gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[4]; + + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + gBattleAnimArgs[3]; + + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void AnimLeechLifeNeedle(struct Sprite *sprite) +{ + if (IsContest()) + { + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + StartSpriteAffineAnim(sprite, 2); + } + else if (!GetBattlerSide(gBattleAnimTarget)) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + } + + sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimTarget, 2) + gBattleAnimArgs[0]; + sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimTarget, 3) + gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[2]; + + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Creates a single web thread that travels from attacker to target. +// Used by MOVE_STRING_SHOT and MOVE_SPIDER_WEB in their first move phase. +// arg 0: x +// arg 1: y +// arg 2: controls the left-to-right movement +// arg 3: amplitude +// arg 4: if targets both opponents +static void AnimTranslateWebThread(struct Sprite *sprite) +{ + if (IsContest()) + gBattleAnimArgs[2] /= 2; + + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + + if (!gBattleAnimArgs[4]) + { + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); + } + + sub_80A6FD4(sprite); + sprite->data[5] = gBattleAnimArgs[3]; + sprite->callback = AnimTranslateWebThread_Step; +} + +static void AnimTranslateWebThread_Step(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + { + DestroyAnimSprite(sprite); + return; + } + + sprite->pos2.x += Sin(sprite->data[6], sprite->data[5]); + sprite->data[6] = (sprite->data[6] + 13) & 0xFF; +} + +// Second stage of String Shot +static void AnimStringWrap(struct Sprite *sprite) +{ + SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimAttacker)) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + + sprite->pos1.y += gBattleAnimArgs[1]; + if (!GetBattlerSide(gBattleAnimTarget)) + sprite->pos1.y += 8; + + sprite->callback = AnimStringWrap_Step; +} + +static void AnimStringWrap_Step(struct Sprite *sprite) +{ + if (++sprite->data[0] == 3) + { + sprite->data[0] = 0; + sprite->invisible ^= 1; + } + + if (++sprite->data[1] == 51) + { + DestroyAnimSprite(sprite); + } +} + +static void AnimSpiderWeb(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + + sprite->data[0] = 16; + sprite->callback = AnimSpiderWeb_Step; +} + +static void AnimSpiderWeb_Step(struct Sprite *sprite) +{ + if (sprite->data[2] < 20) + { + sprite->data[2]++; + } + else if (sprite->data[1]++ & 1) + { + sprite->data[0]--; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[0], 16 - sprite->data[0])); + + if (sprite->data[0] == 0) + { + sprite->invisible = TRUE; + sprite->callback = AnimSpiderWeb_End; + } + } +} + +static void AnimSpiderWeb_End(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimSprite(sprite); +} + +// Translates a stinger sprite linearly to a destination location. The sprite is +// initially rotated so that it appears to be traveling in a straight line. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x pixel offset +// arg 3: target y pixel offset +// arg 4: duration +static void AnimTranslateStinger(struct Sprite *sprite) +{ + s16 lVarX, lVarY; + u16 rot; + + if (IsContest()) + { + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + } + else + { + if (GetBattlerSide(gBattleAnimAttacker)) + { + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + } + } + + if (!IsContest() && GetBattlerSide(gBattleAnimAttacker) == GetBattlerSide(gBattleAnimTarget)) + { + if (GetBattlerPosition(gBattleAnimTarget) == B_POSITION_PLAYER_LEFT + || GetBattlerPosition(gBattleAnimTarget) == B_POSITION_OPPONENT_LEFT) + { + s16 temp1, temp2; + + temp1 = gBattleAnimArgs[2]; + gBattleAnimArgs[2] = -temp1; + + temp2 = gBattleAnimArgs[0]; + gBattleAnimArgs[0] = -temp2; + } + } + + InitSpritePosToAnimAttacker(sprite, 1); + + lVarX = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2]; + lVarY = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + gBattleAnimArgs[3]; + rot = ArcTan2Neg(lVarX - sprite->pos1.x, lVarY - sprite->pos1.y); + rot += 0xC000; + TrySetSpriteRotScale(sprite, FALSE, 0x100, 0x100, rot); + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = lVarX; + sprite->data[4] = lVarY; + + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Rotates sprite and moves it in an arc, so that it appears like a missle or arrow traveling. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x pixel offset +// arg 3: target y pixel offset +// arg 4: duration +// arg 5: wave amplitude +static void AnimMissileArc(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + + if (GetBattlerSide(gBattleAnimAttacker)) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + gBattleAnimArgs[3]; + sprite->data[5] = gBattleAnimArgs[5]; + InitAnimArcTranslation(sprite); + + sprite->callback = AnimMissileArc_Step; + sprite->invisible = TRUE; +} + +static void AnimMissileArc_Step(struct Sprite *sprite) +{ + sprite->invisible = FALSE; + + if (TranslateAnimHorizontalArc(sprite)) + { + DestroyAnimSprite(sprite); + } + else + { + s16 tempData[8]; + u16 *data = sprite->data; + u16 x1 = sprite->pos1.x; + s16 x2 = sprite->pos2.x; + u16 y1 = sprite->pos1.y; + s16 y2 = sprite->pos2.y; + int i; + + for (i = 0; i < 8; i++) + tempData[i] = data[i]; + + x2 += x1; + y2 += y1; + + if (!TranslateAnimHorizontalArc(sprite)) + { + u16 rotation = ArcTan2Neg(sprite->pos1.x + sprite->pos2.x - x2, + sprite->pos1.y + sprite->pos2.y - y2); + rotation += 0xC000; + TrySetSpriteRotScale(sprite, FALSE, 0x100, 0x100, rotation); + + for (i = 0; i < 8; i++) + data[i] = tempData[i]; + } + } +} + +static void AnimTailGlowOrb(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + 18; + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + 18; + } + + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; +} diff --git a/src/battle_anim_dark.c b/src/battle_anim_dark.c new file mode 100644 index 000000000..dc3e8c83c --- /dev/null +++ b/src/battle_anim_dark.c @@ -0,0 +1,993 @@ +#include "global.h" +#include "battle_anim.h" +#include "contest.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "palette.h" +#include "scanline_effect.h" +#include "trig.h" +#include "util.h" +#include "constants/rgb.h" + +static void sub_81138D4(struct Sprite *); +static void AnimBite(struct Sprite *); +static void AnimTearDrop(struct Sprite *); +static void AnimClawSlash(struct Sprite *); +static void AnimTask_AttackerFadeToInvisible_Step(u8); +static void AnimTask_AttackerFadeFromInvisible_Step(u8); +static void sub_8113950(struct Sprite *); +static void AnimBite_Step1(struct Sprite *); +static void AnimBite_Step2(struct Sprite *); +static void AnimTearDrop_Step(struct Sprite *); +static void AnimTask_MoveAttackerMementoShadow_Step(u8); +static void AnimTask_MoveTargetMementoShadow_Step(u8); +static void sub_8114244(struct Task *); +static void sub_8114374(u8); +static void AnimTask_MetallicShine_Step(u8); + +// Unused +const struct SpriteTemplate gUnknown_08596FC8 = +{ + .tileTag = ANIM_TAG_TIED_BAG, + .paletteTag = ANIM_TAG_TIED_BAG, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_81138D4, +}; + +static const union AffineAnimCmd sAffineAnim_Bite_0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_Bite_1[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 32, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_Bite_2[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 64, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_Bite_3[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 96, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_Bite_4[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -128, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_Bite_5[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -96, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_Bite_6[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -64, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_Bite_7[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -32, 1), + AFFINEANIMCMD_END, +}; + +const union AffineAnimCmd *const gAffineAnims_Bite[] = +{ + sAffineAnim_Bite_0, + sAffineAnim_Bite_1, + sAffineAnim_Bite_2, + sAffineAnim_Bite_3, + sAffineAnim_Bite_4, + sAffineAnim_Bite_5, + sAffineAnim_Bite_6, + sAffineAnim_Bite_7, +}; + +const struct SpriteTemplate gSharpTeethSpriteTemplate = +{ + .tileTag = ANIM_TAG_SHARP_TEETH, + .paletteTag = ANIM_TAG_SHARP_TEETH, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_Bite, + .callback = AnimBite, +}; + +const struct SpriteTemplate gClampJawSpriteTemplate = +{ + .tileTag = ANIM_TAG_CLAMP, + .paletteTag = ANIM_TAG_CLAMP, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_Bite, + .callback = AnimBite, +}; + +static const union AffineAnimCmd sAffineAnim_TearDrop_0[] = +{ + AFFINEANIMCMD_FRAME(0xC0, 0xC0, 80, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -2, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_TearDrop_1[] = +{ + AFFINEANIMCMD_FRAME(0xC0, 0xC0, -80, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 2, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_TearDrop[] = +{ + sAffineAnim_TearDrop_0, + sAffineAnim_TearDrop_1, +}; + +const struct SpriteTemplate gTearDropSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_TearDrop, + .callback = AnimTearDrop, +}; + +static const union AnimCmd sAnim_ClawSlash_0[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(48, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_ClawSlash_1[] = +{ + ANIMCMD_FRAME(0, 4, .hFlip = TRUE), + ANIMCMD_FRAME(16, 4, .hFlip = TRUE), + ANIMCMD_FRAME(32, 4, .hFlip = TRUE), + ANIMCMD_FRAME(48, 4, .hFlip = TRUE), + ANIMCMD_FRAME(64, 4, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_ClawSlash[] = +{ + sAnim_ClawSlash_0, + sAnim_ClawSlash_1, +}; + +const struct SpriteTemplate gClawSlashSpriteTemplate = +{ + .tileTag = ANIM_TAG_CLAW_SLASH, + .paletteTag = ANIM_TAG_CLAW_SLASH, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_ClawSlash, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimClawSlash, +}; + +void AnimTask_AttackerFadeToInvisible(u8 taskId) +{ + int battler; + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + battler = gBattleAnimAttacker; + gTasks[taskId].data[1] = 16; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + if (GetBattlerSpriteBGPriorityRank(battler) == 1) + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); + else + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2); + + gTasks[taskId].func = AnimTask_AttackerFadeToInvisible_Step; +} + +static void AnimTask_AttackerFadeToInvisible_Step(u8 taskId) +{ + u8 blendA = gTasks[taskId].data[1] >> 8; + u8 blendB = gTasks[taskId].data[1]; + if (gTasks[taskId].data[2] == (u8)gTasks[taskId].data[0]) + { + blendA++; + blendB--; + gTasks[taskId].data[1] = BLDALPHA_BLEND(blendB, blendA); + SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1]); + gTasks[taskId].data[2] = 0; + if (blendA == 16) + { + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].invisible = TRUE; + DestroyAnimVisualTask(taskId); + } + } + else + { + gTasks[taskId].data[2]++; + } +} + +void AnimTask_AttackerFadeFromInvisible(u8 taskId) +{ + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gTasks[taskId].data[1] = BLDALPHA_BLEND(0, 16); + gTasks[taskId].func = AnimTask_AttackerFadeFromInvisible_Step; + SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1]); +} + +static void AnimTask_AttackerFadeFromInvisible_Step(u8 taskId) +{ + u8 blendA = gTasks[taskId].data[1] >> 8; + u8 blendB = gTasks[taskId].data[1]; + if (gTasks[taskId].data[2] == (u8)gTasks[taskId].data[0]) + { + blendA--; + blendB++; + gTasks[taskId].data[1] = (blendA << 8) | blendB; + SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1]); + gTasks[taskId].data[2] = 0; + if (blendA == 0) + { + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimVisualTask(taskId); + } + } + else + { + gTasks[taskId].data[2]++; + } +} + +void AnimTask_InitAttackerFadeFromInvisible(u8 taskId) +{ + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1) + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); + else + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2); + + DestroyAnimVisualTask(taskId); +} + +static void sub_81138D4(struct Sprite *sprite) +{ + sprite->data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->data[3] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->data[0] = 0x7E; + InitSpriteDataForLinearTranslation(sprite); + sprite->data[3] = -sprite->data[1]; + sprite->data[4] = -sprite->data[2]; + sprite->data[6] = 0xFFD8; + sprite->callback = sub_8113950; + sprite->callback(sprite); +} + +static void sub_8113950(struct Sprite *sprite) +{ + sprite->data[3] += sprite->data[1]; + sprite->data[4] += sprite->data[2]; + sprite->pos2.x = sprite->data[3] >> 8; + sprite->pos2.y = sprite->data[4] >> 8; + if (sprite->data[7] == 0) + { + sprite->data[3] += sprite->data[1]; + sprite->data[4] += sprite->data[2]; + sprite->pos2.x = sprite->data[3] >> 8; + sprite->pos2.y = sprite->data[4] >> 8; + sprite->data[0]--; + } + + sprite->pos2.y += Sin(sprite->data[5], sprite->data[6]); + sprite->data[5] = (sprite->data[5] + 3) & 0xFF; + if (sprite->data[5] > 0x7F) + { + sprite->data[5] = 0; + sprite->data[6] += 20; + sprite->data[7]++; + } + + if (--sprite->data[0] == 0) + DestroyAnimSprite(sprite); +} + +// Move sprite inward for Bite/Crunch and Clamp +static void AnimBite(struct Sprite *sprite) +{ + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + StartSpriteAffineAnim(sprite, gBattleAnimArgs[2]); + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[1] = gBattleAnimArgs[4]; + sprite->data[2] = gBattleAnimArgs[5]; + sprite->callback = AnimBite_Step1; +} + +static void AnimBite_Step1(struct Sprite *sprite) +{ + sprite->data[4] += sprite->data[0]; + sprite->data[5] += sprite->data[1]; + sprite->pos2.x = sprite->data[4] >> 8; + sprite->pos2.y = sprite->data[5] >> 8; + if (++sprite->data[3] == sprite->data[2]) + sprite->callback = AnimBite_Step2; +} + +static void AnimBite_Step2(struct Sprite *sprite) +{ + sprite->data[4] -= sprite->data[0]; + sprite->data[5] -= sprite->data[1]; + sprite->pos2.x = sprite->data[4] >> 8; + sprite->pos2.y = sprite->data[5] >> 8; + if (--sprite->data[3] == 0) + DestroySpriteAndMatrix(sprite); +} + +// Launches a tear drop away from the battler. Used by Fake Tears +static void AnimTearDrop(struct Sprite *sprite) +{ + u8 battler; + s8 xOffset; + + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + battler = gBattleAnimAttacker; + else + battler = gBattleAnimTarget; + + xOffset = 20; + sprite->oam.tileNum += 4; + + switch (gBattleAnimArgs[1]) + { + case 0: + sprite->pos1.x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_RIGHT) - 8; + sprite->pos1.y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_TOP) + 8; + break; + case 1: + sprite->pos1.x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_RIGHT) - 14; + sprite->pos1.y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_TOP) + 16; + break; + case 2: + sprite->pos1.x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_LEFT) + 8; + sprite->pos1.y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_TOP) + 8; + StartSpriteAffineAnim(sprite, 1); + xOffset = -20; + break; + case 3: + sprite->pos1.x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_LEFT) + 14; + sprite->pos1.y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_TOP) + 16; + StartSpriteAffineAnim(sprite, 1); + xOffset = -20; + break; + } + + sprite->data[0] = 32; + sprite->data[2] = sprite->pos1.x + xOffset; + sprite->data[4] = sprite->pos1.y + 12; + sprite->data[5] = -12; + + InitAnimArcTranslation(sprite); + sprite->callback = AnimTearDrop_Step; +} + +static void AnimTearDrop_Step(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroySpriteAndMatrix(sprite); +} + +void AnimTask_MoveAttackerMementoShadow(u8 taskId) +{ + struct ScanlineEffectParams scanlineParams; + struct BattleAnimBgData animBg; + u16 i; + u8 pos; + int var0; + struct Task *task = &gTasks[taskId]; + + task->data[7] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + 31; + task->data[6] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_TOP) - 7; + task->data[5] = task->data[7]; + task->data[4] = task->data[6]; + task->data[13] = (task->data[7] - task->data[6]) << 8; + + pos = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); + task->data[14] = pos - 32; + task->data[15] = pos + 32; + + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + task->data[8] = -12; + else + task->data[8] = -64; + + task->data[3] = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); + if (task->data[3] == 1) + { + sub_80A6B30(&animBg); + task->data[10] = gBattle_BG1_Y; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); + FillPalette(0, animBg.paletteId * 16, 32); + scanlineParams.dmaDest = ®_BG1VOFS; + var0 = WINOUT_WIN01_BG1; + if (!IsContest()) + gBattle_BG2_X += 240; + } + else + { + task->data[10] = gBattle_BG2_Y; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2); + FillPalette(0, 144, 32); + scanlineParams.dmaDest = ®_BG2VOFS; + var0 = WINOUT_WIN01_BG2; + if (!IsContest()) + gBattle_BG1_X += 240; + } + + scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; + scanlineParams.initState = 1; + scanlineParams.unused9 = 0; + task->data[11] = 0; + task->data[12] = 16; + task->data[0] = 0; + task->data[1] = 0; + task->data[2] = 0; + sub_8114374(3); + for (i = 0; i < 112; i++) + { + gScanlineEffectRegBuffers[0][i] = task->data[10]; + gScanlineEffectRegBuffers[1][i] = task->data[10]; + } + + ScanlineEffect_SetParams(scanlineParams); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | (var0 ^ (WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR))); + 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_WIN0H = (task->data[14] << 8) | task->data[15]; + gBattle_WIN0V = 160; + + task->func = AnimTask_MoveAttackerMementoShadow_Step; +} + +static void AnimTask_MoveAttackerMementoShadow_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + if (++task->data[1] > 1) + { + task->data[1] = 0; + if (++task->data[2] & 1) + { + if (task->data[11] != 12) + task->data[11]++; + } + else + { + if (task->data[12] != 8) + task->data[12]--; + } + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[11], task->data[12])); + + if (task->data[11] == 12 && task->data[12] == 8) + task->data[0]++; + } + break; + case 1: + task->data[4] -= 8; + sub_8114244(task); + + if (task->data[4] < task->data[8]) + task->data[0]++; + break; + case 2: + task->data[4] -= 8; + sub_8114244(task); + task->data[14] += 4; + task->data[15] -= 4; + + if (task->data[14] >= task->data[15]) + task->data[14] = task->data[15]; + + gBattle_WIN0H = (task->data[14] << 8) | task->data[15]; + + if (task->data[14] == task->data[15]) + task->data[0]++; + break; + case 3: + gScanlineEffect.state = 3; + task->data[0]++; + break; + case 4: + DestroyAnimVisualTask(taskId); + break; + } +} + +void AnimTask_MoveTargetMementoShadow(u8 taskId) +{ + struct BattleAnimBgData animBg; + struct ScanlineEffectParams scanlineParams; + u8 x; + u16 i; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + if (IsContest() == TRUE) + { + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); + DestroyAnimVisualTask(taskId); + } + else + { + task->data[3] = GetBattlerSpriteBGPriorityRank(gBattleAnimTarget); + if (task->data[3] == 1) + { + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); + gBattle_BG2_X += 240; + } + else + { + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2); + gBattle_BG1_X += 240; + } + + task->data[0]++; + } + break; + case 1: + if (task->data[3] == 1) + { + sub_80A6B30(&animBg); + task->data[10] = gBattle_BG1_Y; + FillPalette(0, animBg.paletteId * 16, 32); + } + else + { + task->data[10] = gBattle_BG2_Y; + FillPalette(0, 9 * 16, 32); + } + + sub_8114374(3); + task->data[0]++; + break; + case 2: + task->data[7] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + 31; + task->data[6] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_TOP) - 7; + task->data[13] = (task->data[7] - task->data[6]) << 8; + x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X); + task->data[14] = x - 4; + task->data[15] = x + 4; + + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + task->data[8] = -12; + else + task->data[8] = -64; + + task->data[4] = task->data[8]; + task->data[5] = task->data[8]; + task->data[11] = 12; + task->data[12] = 8; + task->data[0]++; + break; + case 3: + if (task->data[3] == 1) + scanlineParams.dmaDest = ®_BG1VOFS; + else + scanlineParams.dmaDest = ®_BG2VOFS; + + for (i = 0; i < 112; i++) + { + gScanlineEffectRegBuffers[0][i] = task->data[10] + (159 - i); + gScanlineEffectRegBuffers[1][i] = task->data[10] + (159 - i); + } + + scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; + scanlineParams.initState = 1; + scanlineParams.unused9 = 0; + ScanlineEffect_SetParams(scanlineParams); + task->data[0]++; + break; + case 4: + if (task->data[3] == 1) + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); + else + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG0 | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); + + 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_WIN0H = (task->data[14] << 8) | task->data[15]; + gBattle_WIN0V = 160; + + task->data[0] = 0; + task->data[1] = 0; + task->data[2] = 0; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(12, 8)); + task->func = AnimTask_MoveTargetMementoShadow_Step; + break; + } +} + +static void AnimTask_MoveTargetMementoShadow_Step(u8 taskId) +{ + u8 pos; + u16 i; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[5] += 8; + if (task->data[5] >= task->data[7]) + task->data[5] = task->data[7]; + + sub_8114244(task); + if (task->data[5] == task->data[7]) + task->data[0]++; + break; + case 1: + if (task->data[15] - task->data[14] < 0x40) + { + task->data[14] -= 4; + task->data[15] += 4; + } + else + { + task->data[1] = 1; + } + + gBattle_WIN0H = (task->data[14] << 8) | task->data[15]; + task->data[4] += 8; + if (task->data[4] >= task->data[6]) + task->data[4] = task->data[6]; + + sub_8114244(task); + if (task->data[4] == task->data[6] && task->data[1]) + { + task->data[1] = 0; + task->data[0]++; + } + break; + case 2: + if (++task->data[1] > 1) + { + task->data[1] = 0; + task->data[2]++; + if (task->data[2] & 1) + { + if (task->data[11]) + task->data[11]--; + } + else + { + if (task->data[12] < 16) + task->data[12]++; + } + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[11], task->data[12])); + if (task->data[11] == 0 && task->data[12] == 16) + task->data[0]++; + } + break; + case 3: + gScanlineEffect.state = 3; + task->data[0]++; + break; + case 4: + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_8114244(struct Task *task) +{ + int var0, var1; + s16 var2; + s16 i; + int var4; + + var2 = task->data[5] - task->data[4]; + if (var2 != 0) + { + var0 = task->data[13] / var2; + var1 = task->data[6] << 8; + + for (i = 0; i < task->data[4]; i++) + { + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = task->data[10] - (i - 159); + } + + for (i = task->data[4]; i <= task->data[5]; i++) + { + if (i >= 0) + { + s16 var3 = (var1 >> 8) - i; + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = var3 + task->data[10]; + } + + var1 += var0; + } + + var4 = task->data[10] - (i - 159); + for (i = i; i < task->data[7]; i++) + { + if (i >= 0) + { + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = var4; + var4--; + } + } + } + else + { + var4 = task->data[10] + 159; + for (i = 0; i < 112; i++) + { + gScanlineEffectRegBuffers[0][i] = var4; + gScanlineEffectRegBuffers[1][i] = var4; + var4--; + } + } +} + +static void sub_8114374(u8 priority) +{ + u16 i; + + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + u8 spriteId = GetAnimBattlerSpriteId(i); + if (spriteId != 0xFF) + gSprites[spriteId].oam.priority = priority; + } +} + +void AnimTask_InitMementoShadow(u8 taskId) +{ + u8 toBG2 = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) ^ 1 ? 1 : 0; + MoveBattlerSpriteToBG(gBattleAnimAttacker, toBG2, TRUE); + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].invisible = FALSE; + + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + { + MoveBattlerSpriteToBG(gBattleAnimAttacker ^ 2, toBG2 ^ 1, TRUE); + gSprites[gBattlerSpriteIds[gBattleAnimAttacker ^ 2]].invisible = FALSE; + } + + DestroyAnimVisualTask(taskId); +} + +void sub_8114470(u8 taskId) +{ + u8 toBG2 = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) ^ 1 ? 1 : 0; + sub_80A477C(toBG2); + + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + sub_80A477C(toBG2 ^ 1); + + DestroyAnimVisualTask(taskId); +} + +// Animates a deep slash from a claw. Used by Metal Claw, Dragon Claw, and Crush Claw +static void AnimClawSlash(struct Sprite *sprite) +{ + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + StartSpriteAnim(sprite, gBattleAnimArgs[2]); + sprite->callback = RunStoredCallbackWhenAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Makes the attacker metallic and shining. +// Used by MOVE_HARDEN and MOVE_IRON_DEFENSE. +// arg0: if true won't change battler's palette back +// arg1: if true, use custom color +// arg2: custom color +// Custom color argument is used in MOVE_POISON_TAIL to make the mon turn purplish/pinkish as if became cloaked in poison. +void AnimTask_MetallicShine(u8 taskId) +{ + u16 species; + u8 spriteId; + u8 newSpriteId; + u16 paletteNum; + struct BattleAnimBgData animBg; + bool32 priorityChanged = FALSE; + + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(8, 12)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 0); + SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); + + if (IsDoubleBattle() && !IsContest()) + { + if (GetBattlerPosition(gBattleAnimAttacker) == B_POSITION_OPPONENT_RIGHT || GetBattlerPosition(gBattleAnimAttacker) == B_POSITION_PLAYER_LEFT) + { + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker)) == TRUE) + { + gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)]].oam.priority--; + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + priorityChanged = TRUE; + } + } + } + + if (IsContest()) + { + species = gContestResources->field_18->species; + } + else + { + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES); + } + + spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + newSpriteId = sub_80A89C8(gBattleAnimAttacker, spriteId, species); + + sub_80A6B30(&animBg); + AnimLoadCompressedBgTilemap(animBg.bgId, gMetalShineTilemap); + AnimLoadCompressedBgGfx(animBg.bgId, gMetalShineGfx, animBg.tilesOffset); + LoadCompressedPalette(gMetalShinePalette, animBg.paletteId * 16, 32); + + gBattle_BG1_X = -gSprites[spriteId].pos1.x + 96; + gBattle_BG1_Y = -gSprites[spriteId].pos1.y + 32; + paletteNum = 16 + gSprites[spriteId].oam.paletteNum; + + if (gBattleAnimArgs[1] == 0) + SetGreyscaleOrOriginalPalette(paletteNum, FALSE); + else + BlendPalette(paletteNum * 16, 16, 11, gBattleAnimArgs[2]); + + gTasks[taskId].data[0] = newSpriteId; + gTasks[taskId].data[1] = gBattleAnimArgs[0]; + gTasks[taskId].data[2] = gBattleAnimArgs[1]; + gTasks[taskId].data[3] = gBattleAnimArgs[2]; + gTasks[taskId].data[6] = priorityChanged; + gTasks[taskId].func = AnimTask_MetallicShine_Step; +} + +static void AnimTask_MetallicShine_Step(u8 taskId) +{ + struct BattleAnimBgData animBg; + u16 paletteNum; + u8 spriteId; + + gTasks[taskId].data[10] += 4; + gBattle_BG1_X -= 4; + if (gTasks[taskId].data[10] == 128) + { + gTasks[taskId].data[10] = 0; + gBattle_BG1_X += 128; + gTasks[taskId].data[11]++; + if (gTasks[taskId].data[11] == 2) + { + spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + paletteNum = 16 + gSprites[spriteId].oam.paletteNum; + if (gTasks[taskId].data[1] == 0) + SetGreyscaleOrOriginalPalette(paletteNum, TRUE); + + DestroySprite(&gSprites[gTasks[taskId].data[0]]); + sub_80A6B30(&animBg); + sub_80A6C68(animBg.bgId); + if (gTasks[taskId].data[6] == 1) + gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)]].oam.priority++; + } + else if (gTasks[taskId].data[11] == 3) + { + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); + + SetGpuReg(REG_OFFSET_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) ^ DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimVisualTask(taskId); + } + } +} + +// Changes battler's palette to either greyscale or original. +// arg0: which battler +// arg1: FALSE grayscale, TRUE original +void AnimTask_SetGreyscaleOrOriginalPal(u8 taskId) +{ + u8 spriteId; + u8 battler; + bool8 calcSpriteId = FALSE; + u8 position = B_POSITION_PLAYER_LEFT; + + switch (gBattleAnimArgs[0]) + { + case ANIM_ATTACKER: + case ANIM_TARGET: + case ANIM_ATK_PARTNER: + case ANIM_DEF_PARTNER: + spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); + break; + case 4: + position = B_POSITION_PLAYER_LEFT; + calcSpriteId = TRUE; + break; + case 5: + position = B_POSITION_PLAYER_RIGHT; + calcSpriteId = TRUE; + break; + case 6: + position = B_POSITION_OPPONENT_LEFT; + calcSpriteId = TRUE; + break; + case 7: + position = B_POSITION_OPPONENT_RIGHT; + calcSpriteId = TRUE; + break; + default: + spriteId = 0xFF; + break; + } + + if (calcSpriteId) + { + battler = GetBattlerAtPosition(position); + if (IsBattlerSpriteVisible(battler)) + spriteId = gBattlerSpriteIds[battler]; + else + spriteId = 0xFF; + } + + if (spriteId != 0xFF) + SetGreyscaleOrOriginalPalette(gSprites[spriteId].oam.paletteNum + 16, gBattleAnimArgs[1]); + + DestroyAnimVisualTask(taskId); +} + +void GetIsDoomDesireHitTurn(u8 taskId) +{ + if (gAnimMoveTurn < 2) + gBattleAnimArgs[ARG_RET_ID] = FALSE; + + if (gAnimMoveTurn == 2) + gBattleAnimArgs[ARG_RET_ID] = TRUE; + + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_anim_dragon.c b/src/battle_anim_dragon.c new file mode 100644 index 000000000..1d426cac7 --- /dev/null +++ b/src/battle_anim_dragon.c @@ -0,0 +1,440 @@ +#include "global.h" +#include "battle_anim.h" +#include "scanline_effect.h" +#include "task.h" +#include "trig.h" +#include "constants/rgb.h" + +static void AnimOutrageFlame(struct Sprite *); +static void AnimDragonRageFirePlume(struct Sprite *); +static void AnimDragonFireToTarget(struct Sprite *); +static void AnimDragonDanceOrb(struct Sprite *); +static void AnimDragonDanceOrb_Step(struct Sprite *); +static void AnimOverheatFlame(struct Sprite *); +static void AnimOverheatFlame_Step(struct Sprite *); +static void AnimTask_DragonDanceWaver_Step(u8); +static void sub_8113574(struct Task *); + +EWRAM_DATA static u16 gUnknown_0203A100[7] = {0}; + +static const union AnimCmd gUnknown_08596E60[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(48, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_08596E78[] = +{ + gUnknown_08596E60, +}; + +const struct SpriteTemplate gOutrageFlameSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gUnknown_08596E78, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimOutrageFlame, +}; + +static const union AnimCmd sAnim_DragonBreathFire_0[] = +{ + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_DragonBreathFire_1[] = +{ + ANIMCMD_FRAME(16, 3, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_FRAME(32, 3, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_FRAME(48, 3, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_DragonBreathFire[] = +{ + sAnim_DragonBreathFire_0, + sAnim_DragonBreathFire_1, +}; + +static const union AffineAnimCmd sAffineAnim_DragonBreathFire_0[] = +{ + AFFINEANIMCMD_FRAME(0x50, 0x50, 127, 0), + AFFINEANIMCMD_FRAME(0xD, 0xD, 0, 100), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_DragonBreathFire_1[] = +{ + AFFINEANIMCMD_FRAME(0x50, 0x50, 0, 0), + AFFINEANIMCMD_FRAME(0xD, 0xD, 0, 100), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_DragonBreathFire[] = +{ + sAffineAnim_DragonBreathFire_0, + sAffineAnim_DragonBreathFire_1, +}; + +const struct SpriteTemplate gDragonBreathFireSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineDouble_ObjNormal_32x32, + .anims = sAnims_DragonBreathFire, + .images = NULL, + .affineAnims = sAffineAnims_DragonBreathFire, + .callback = AnimDragonFireToTarget, +}; + +static const union AnimCmd sAnim_DragonRageFirePlume[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 5), + ANIMCMD_FRAME(48, 5), + ANIMCMD_FRAME(64, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_DragonRageFirePlume[] = +{ + sAnim_DragonRageFirePlume, +}; + +const struct SpriteTemplate gDragonRageFirePlumeSpriteTemplate = +{ + .tileTag = ANIM_TAG_FIRE_PLUME, + .paletteTag = ANIM_TAG_FIRE_PLUME, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_DragonRageFirePlume, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDragonRageFirePlume, +}; + +static const union AnimCmd sAnim_DragonRageFire[] = +{ + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_DragonRageFire[] = +{ + sAnim_DragonRageFire, + sAnim_DragonRageFire, +}; + +static const union AffineAnimCmd sAffineAnim_DragonRageFire_0[] = +{ + AFFINEANIMCMD_FRAME(0x64, 0x64, 127, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_DragonRageFire_1[] = +{ + AFFINEANIMCMD_FRAME(0x64, 0x64, 0, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_DragonRageFire[] = +{ + sAffineAnim_DragonRageFire_0, + sAffineAnim_DragonRageFire_1, +}; + +const struct SpriteTemplate gDragonRageFireSpitSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineDouble_ObjNormal_32x32, + .anims = sAnims_DragonRageFire, + .images = NULL, + .affineAnims = sAffineAnims_DragonRageFire, + .callback = AnimDragonFireToTarget, +}; + +const struct SpriteTemplate gDragonDanceOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_HOLLOW_ORB, + .paletteTag = ANIM_TAG_HOLLOW_ORB, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDragonDanceOrb, +}; + +const struct SpriteTemplate gOverheatFlameSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gUnknown_08596E78, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimOverheatFlame, +}; + +static void AnimOutrageFlame(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + gBattleAnimArgs[4] = -gBattleAnimArgs[4]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + } + + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[3] = gBattleAnimArgs[4]; + sprite->data[5] = gBattleAnimArgs[5]; + sprite->invisible = TRUE; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = TranslateSpriteLinearAndFlicker; +} + +static void sub_8113100(struct Sprite *sprite) +{ + SetSpriteCoordsToAnimAttackerCoords(sprite); + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x -= gBattleAnimArgs[1]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] -= gBattleAnimArgs[2]; + sprite->data[4] += gBattleAnimArgs[3]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] += gBattleAnimArgs[2]; + sprite->data[4] += gBattleAnimArgs[3]; + StartSpriteAnim(sprite, 1); + } + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); +} + +static void AnimDragonRageFirePlume(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); + } + + SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[1]); + sprite->pos1.y += gBattleAnimArgs[2]; + sprite->callback = RunStoredCallbackWhenAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); +} + +// For Dragon Breath and Dragon Rage +static void AnimDragonFireToTarget(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + StartSpriteAffineAnim(sprite, 1); + + sub_8113100(sprite); +} + +static void AnimDragonDanceOrb(struct Sprite *sprite) +{ + u16 r5; + u16 r0; + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + sprite->data[4] = 0; + sprite->data[5] = 1; + sprite->data[6] = gBattleAnimArgs[0]; + r5 = GetBattlerSpriteCoordAttr(gBattlerAttacker, BATTLER_COORD_ATTR_HEIGHT); + r0 = GetBattlerSpriteCoordAttr(gBattlerAttacker, BATTLER_COORD_ATTR_WIDTH); + if (r5 > r0) + sprite->data[7] = r5 / 2; + else + sprite->data[7] = r0 / 2; + sprite->pos2.x = Cos(sprite->data[6], sprite->data[7]); + sprite->pos2.y = Sin(sprite->data[6], sprite->data[7]); + sprite->callback = AnimDragonDanceOrb_Step; +} + +static void AnimDragonDanceOrb_Step(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->data[6] = (sprite->data[6] - sprite->data[5]) & 0xFF; + sprite->pos2.x = Cos(sprite->data[6], sprite->data[7]); + sprite->pos2.y = Sin(sprite->data[6], sprite->data[7]); + if (++sprite->data[4] > 5) + { + sprite->data[4] = 0; + if (sprite->data[5] <= 15 && ++sprite->data[5] > 15) + sprite->data[5] = 16; + } + if (++sprite->data[3] > 0x3C) + { + sprite->data[3] = 0; + sprite->data[0]++; + } + break; + case 1: + sprite->data[6] = (sprite->data[6] - sprite->data[5]) & 0xFF; + if (sprite->data[7] <= 0x95 && (sprite->data[7] += 8) > 0x95) + sprite->data[7] = 0x96; + sprite->pos2.x = Cos(sprite->data[6], sprite->data[7]); + sprite->pos2.y = Sin(sprite->data[6], sprite->data[7]); + if (++sprite->data[4] > 5) + { + sprite->data[4] = 0; + if (sprite->data[5] <= 15 && ++sprite->data[5] > 15) + sprite->data[5] = 16; + } + if (++sprite->data[3] > 20) + DestroyAnimSprite(sprite); + break; + } +} + +// Wavers the attacker back and forth. Progressing vertical wave of scanline shifts +// Used by Dragon Dance +void AnimTask_DragonDanceWaver(u8 taskId) +{ + struct ScanlineEffectParams sp; + struct Task *task = &gTasks[taskId]; + u16 i; + u8 r1; + if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1) + { + sp.dmaDest = ®_BG1HOFS; + task->data[2] = gBattle_BG1_X; + } + else + { + sp.dmaDest = ®_BG2HOFS; + task->data[2] = gBattle_BG2_X; + } + + sp.dmaControl = 0xA2600001; + sp.initState = 1; + sp.unused9 = 0; + r1 = GetBattlerYCoordWithElevation(gBattleAnimAttacker); + task->data[3] = r1 - 32; + task->data[4] = r1 + 32; + if (task->data[3] < 0) + task->data[3] = 0; + + for (i = task->data[3]; i <= task->data[4]; i++) + { + gScanlineEffectRegBuffers[0][i] = task->data[2]; + gScanlineEffectRegBuffers[1][i] = task->data[2]; + } + + ScanlineEffect_SetParams(sp); + task->func = AnimTask_DragonDanceWaver_Step; +} + +static void AnimTask_DragonDanceWaver_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + switch (task->data[0]) + { + case 0: + if (++task->data[7] > 1) + { + task->data[7] = 0; + if (++task->data[6] == 3) + task->data[0]++; + } + sub_8113574(task); + break; + case 1: + if (++task->data[1] > 0x3C) + task->data[0]++; + sub_8113574(task); + break; + case 2: + if (++task->data[7] > 1) + { + task->data[7] = 0; + if (--task->data[6] == 0) + task->data[0]++; + } + sub_8113574(task); + break; + case 3: + gScanlineEffect.state = 3; + task->data[0]++; + break; + case 4: + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_8113574(struct Task *task) +{ + u16 r3 = task->data[5]; + u16 i; + for (i = task->data[3]; i <= task->data[4]; i++) + { + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = ((gSineTable[r3] * task->data[6]) >> 7) + task->data[2]; + r3 = (r3 + 8) & 0xFF; + } + + task->data[5] = (task->data[5] + 9) & 0xFF; +} + +static void AnimOverheatFlame(struct Sprite *sprite) +{ + int r6 = (gBattleAnimArgs[2] * 3) / 5; + int i; + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + gBattleAnimArgs[4]; + sprite->data[1] = Cos(gBattleAnimArgs[1], gBattleAnimArgs[2]); + sprite->data[2] = Sin(gBattleAnimArgs[1], r6); + sprite->pos1.x += sprite->data[1] * gBattleAnimArgs[0]; + sprite->pos1.y += sprite->data[2] * gBattleAnimArgs[0]; + sprite->data[3] = gBattleAnimArgs[3]; + sprite->callback = AnimOverheatFlame_Step; + for (i = 0; i < 7; i++) + gUnknown_0203A100[i] = sprite->data[i]; +} + +static void AnimOverheatFlame_Step(struct Sprite *sprite) +{ + sprite->data[4] += sprite->data[1]; + sprite->data[5] += sprite->data[2]; + sprite->pos2.x = sprite->data[4] / 10; + sprite->pos2.y = sprite->data[5] / 10; + if (++sprite->data[0] > sprite->data[3]) + DestroyAnimSprite(sprite); +} diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index ffcf24b9b..516c58e55 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -2761,7 +2761,7 @@ static void AnimConstrictBinding_Step1(struct Sprite* sprite) { u8 spriteId; - if ((u16)gBattleAnimArgs[ARG_RET_ID] == 0xFFFF) + if ((u16)gBattleAnimArgs[7] == 0xFFFF) { sprite->affineAnimPaused = 0; spriteId = GetAnimBattlerSpriteId(ANIM_TARGET); @@ -2835,7 +2835,7 @@ static void AnimTask_DuplicateAndShrinkToPos_Step1(u8 taskId) static void AnimTask_DuplicateAndShrinkToPos_Step2(u8 taskId) { - if ((u16)gBattleAnimArgs[ARG_RET_ID] == 0xFFFF) + if ((u16)gBattleAnimArgs[7] == 0xFFFF) { if (gTasks[taskId].data[0] == 0) { @@ -3655,7 +3655,7 @@ void AnimTask_CycleMagicalLeafPal(u8 taskId) break; } - if (gBattleAnimArgs[ARG_RET_ID] == -1) + if (gBattleAnimArgs[7] == -1) DestroyAnimVisualTask(taskId); } @@ -4355,7 +4355,7 @@ static void AnimLockOnTarget_Step4(struct Sprite* sprite) static void AnimLockOnTarget_Step5(struct Sprite* sprite) { - if ((u16)gBattleAnimArgs[ARG_RET_ID] == 0xFFFF) + if ((u16)gBattleAnimArgs[7] == 0xFFFF) { sprite->data[1] = 0; sprite->data[0] = 0; @@ -4847,7 +4847,7 @@ static void AnimConversion(struct Sprite* sprite) sprite->data[0]++; } - if ((u16)gBattleAnimArgs[ARG_RET_ID] == 0xFFFF) + if ((u16)gBattleAnimArgs[7] == 0xFFFF) DestroyAnimSprite(sprite); } @@ -4855,7 +4855,7 @@ void AnimTask_ConversionAlphaBlend(u8 taskId) { if (gTasks[taskId].data[2] == 1) { - gBattleAnimArgs[ARG_RET_ID] = 0xFFFF; + gBattleAnimArgs[7] = 0xFFFF; gTasks[taskId].data[2]++; } else if (gTasks[taskId].data[2] == 2) diff --git a/src/battle_anim_effects_2.c b/src/battle_anim_effects_2.c index 206c2032f..cf85e697a 100755 --- a/src/battle_anim_effects_2.c +++ b/src/battle_anim_effects_2.c @@ -2761,7 +2761,7 @@ static void AnimSoftBoiledEgg_Step3_Callback2(struct Sprite *sprite) static void AnimSoftBoiledEgg_Step4(struct Sprite *sprite) { - if ((u16)gBattleAnimArgs[ARG_RET_ID] == 0xFFFF) + if ((u16)gBattleAnimArgs[7] == 0xFFFF) { sprite->invisible = TRUE; if (sprite->data[7] == 0) @@ -3444,7 +3444,7 @@ static void AnimOrbitFast_Step(struct Sprite *sprite) break; } - if ((u16)gBattleAnimArgs[ARG_RET_ID] == 0xFFFF) + if ((u16)gBattleAnimArgs[7] == 0xFFFF) DestroyAnimSprite(sprite); } diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index c414deb84..fd68bbd37 100755 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -1392,7 +1392,7 @@ static void SetPsychicBackground_Step(u8 taskId) gTasks[taskId].data[5] = 0; } - if ((u16)gBattleAnimArgs[ARG_RET_ID] == 0xFFFF) + if ((u16)gBattleAnimArgs[7] == 0xFFFF) DestroyTask(taskId); } @@ -1423,7 +1423,7 @@ static void FadeScreenToWhite_Step(u8 taskId) gTasks[taskId].data[5] = 0; } - if ((u16)gBattleAnimArgs[ARG_RET_ID] == 0xFFFF) + if ((u16)gBattleAnimArgs[7] == 0xFFFF) DestroyTask(taskId); } @@ -5092,7 +5092,7 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId) if (x < GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X)) { gTasks[taskId].data[14]++; - gBattleAnimArgs[ARG_RET_ID] = 0xFFFF; + gBattleAnimArgs[7] = 0xFFFF; } } else @@ -5100,7 +5100,7 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId) if (x > GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X)) { gTasks[taskId].data[14]++; - gBattleAnimArgs[ARG_RET_ID] = 0xFFFF; + gBattleAnimArgs[7] = 0xFFFF; } } } @@ -5150,7 +5150,7 @@ static void sub_815FE80(struct Sprite *sprite) switch (sprite->data[7]) { case 0: - if (gBattleAnimArgs[ARG_RET_ID] == -1) + if (gBattleAnimArgs[7] == -1) { PlaySE12WithPanning(SE_W233, BattleAnimAdjustPanning(63)); sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + 16; diff --git a/src/battle_anim_electric.c b/src/battle_anim_electric.c new file mode 100644 index 000000000..c153dbc10 --- /dev/null +++ b/src/battle_anim_electric.c @@ -0,0 +1,1329 @@ +#include "global.h" +#include "battle_anim.h" +#include "constants/rgb.h" +#include "trig.h" +#include "constants/songs.h" +#include "sound.h" + +static void AnimLightning(struct Sprite *); +static void AnimLightning_Step(struct Sprite *); +static void sub_810A214(struct Sprite *); +static void sub_810A258(struct Sprite *); +static void sub_810A274(struct Sprite *); +static void AnimSparkElectricity(struct Sprite *); +static void AnimZapCannonSpark(struct Sprite *); +static void AnimZapCannonSpark_Step(struct Sprite *); +static void AnimThunderboltOrb(struct Sprite *); +static void AnimThunderboltOrb_Step(struct Sprite *); +static void AnimSparkElectricityFlashing(struct Sprite *); +static void AnimSparkElectricityFlashing_Step(struct Sprite *); +static void AnimElectricity(struct Sprite *); +static void AnimTask_ElectricBolt_Step(u8 taskId); +static void AnimElectricBoltSegment(struct Sprite *); +static void AnimThunderWave(struct Sprite *); +static void AnimThunderWave_Step(struct Sprite *); +static void AnimTask_ElectricChargingParticles_Step(u8 taskId); +static void AnimElectricChargingParticles(struct Sprite *); +static void AnimElectricChargingParticles_Step(struct Sprite *); +static void AnimGrowingChargeOrb(struct Sprite *); +static void AnimElectricPuff(struct Sprite *); +static void AnimVoltTackleOrbSlide(struct Sprite *); +static void AnimVoltTackleOrbSlide_Step(struct Sprite *); +static bool8 sub_810B154(struct Task *task, u8 taskId); +static void AnimVoltTackleBolt(struct Sprite *); +static void AnimGrowingShockWaveOrb(struct Sprite *); +static bool8 sub_810B430(struct Task *task, u8 taskId); +static void AnimShockWaveProgressingBolt(struct Sprite *); +static bool8 sub_810B614(struct Task *task, u8 taskId); +static void sub_810B684(struct Sprite *sprite); + +static const union AnimCmd sAnim_Lightning[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 8), + ANIMCMD_FRAME(48, 5), + ANIMCMD_FRAME(64, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_Lightning[] = +{ + sAnim_Lightning, +}; + +const struct SpriteTemplate gLightningSpriteTemplate = +{ + .tileTag = ANIM_TAG_LIGHTNING, + .paletteTag = ANIM_TAG_LIGHTNING, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_Lightning, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimLightning, +}; + +static const union AffineAnimCmd gUnknown_085956D8[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 20), + AFFINEANIMCMD_FRAME(0x0, 0x0, -16, 60), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_085956F8[] = +{ + gUnknown_085956D8, +}; + +// Unused +const struct SpriteTemplate gUnknown_085956FC = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_085956F8, + .callback = sub_810A214, +}; + +static const union AnimCmd gUnknown_08595714[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 5), + ANIMCMD_FRAME(48, 5), + ANIMCMD_FRAME(64, 5), + ANIMCMD_FRAME(80, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_08595730[] = +{ + gUnknown_08595714, +}; + +// Unused +const struct SpriteTemplate gUnknown_08595734 = +{ + .tileTag = ANIM_TAG_SHOCK, + .paletteTag = ANIM_TAG_SHOCK, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gUnknown_08595730, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810A274, +}; + +const struct SpriteTemplate gSparkElectricitySpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK_2, + .paletteTag = ANIM_TAG_SPARK_2, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSparkElectricity, +}; + +const struct SpriteTemplate gZapCannonBallSpriteTemplate = +{ + .tileTag = ANIM_TAG_BLACK_BALL_2, + .paletteTag = ANIM_TAG_BLACK_BALL_2, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = TranslateAnimSpriteToTargetMonLocation, +}; + +static const union AffineAnimCmd sAffineAnim_FlashingSpark[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 20, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sAffineAnims_FlashingSpark[] = +{ + sAffineAnim_FlashingSpark, +}; + +const struct SpriteTemplate gZapCannonSparkSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK_2, + .paletteTag = ANIM_TAG_SPARK_2, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_FlashingSpark, + .callback = AnimZapCannonSpark, +}; + +static const union AnimCmd sAnim_ThunderboltOrb[] = +{ + ANIMCMD_FRAME(0, 6), + ANIMCMD_FRAME(16, 6), + ANIMCMD_FRAME(32, 6), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_ThunderboltOrb[] = +{ + sAnim_ThunderboltOrb, +}; + +static const union AffineAnimCmd sAffineAnim_ThunderboltOrb[] = +{ + AFFINEANIMCMD_FRAME(0xE8, 0xE8, 0, 0), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 10), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 10), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const sAffineAnims_ThunderboltOrb[] = +{ + sAffineAnim_ThunderboltOrb, +}; + +const struct SpriteTemplate gThunderboltOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_SHOCK_3, + .paletteTag = ANIM_TAG_SHOCK_3, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = sAnims_ThunderboltOrb, + .images = NULL, + .affineAnims = sAffineAnims_ThunderboltOrb, + .callback = AnimThunderboltOrb, +}; + +const struct SpriteTemplate gSparkElectricityFlashingSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK_2, + .paletteTag = ANIM_TAG_SPARK_2, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_FlashingSpark, + .callback = AnimSparkElectricityFlashing, +}; + +const struct SpriteTemplate gElectricitySpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK_2, + .paletteTag = ANIM_TAG_SPARK_2, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimElectricity, +}; + +const struct SpriteTemplate gElectricBoltSegmentSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK, + .paletteTag = ANIM_TAG_SPARK, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimElectricBoltSegment, +}; + +const struct SpriteTemplate gThunderWaveSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK_H, + .paletteTag = ANIM_TAG_SPARK_H, + .oam = &gOamData_AffineOff_ObjNormal_32x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimThunderWave, +}; + +static const s8 sElectricChargingParticleCoordOffsets[][2] = +{ + { 58, -60}, + {-56, -36}, + { 8, -56}, + {-16, 56}, + { 58, -10}, + {-58, 10}, + { 48, -18}, + {-8, 56}, + { 16, -56}, + {-58, -42}, + { 58, 30}, + {-48, 40}, + { 12, -48}, + { 48, -12}, + {-56, 18}, + { 48, 48}, +}; + +static const union AnimCmd sAnim_ElectricChargingParticles_0[] = +{ + ANIMCMD_FRAME(3, 1), + ANIMCMD_FRAME(2, 1), + ANIMCMD_FRAME(1, 1), + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_ElectricChargingParticles_1[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(1, 5), + ANIMCMD_FRAME(2, 5), + ANIMCMD_FRAME(3, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_ElectricChargingParticles[] = +{ + sAnim_ElectricChargingParticles_0, + sAnim_ElectricChargingParticles_1, +}; + +const struct SpriteTemplate gElectricChargingParticlesSpriteTemplate = +{ + .tileTag = ANIM_TAG_ELECTRIC_ORBS, + .paletteTag = ANIM_TAG_ELECTRIC_ORBS, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = sAnims_ElectricChargingParticles, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_0[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 60), + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_LOOP(0), + AFFINEANIMCMD_FRAME(0xFFFC, 0xFFFC, 0, 5), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 5), + AFFINEANIMCMD_LOOP(10), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_1[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 30), + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0xFFFC, 0xFFFC, 0, 5), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 5), + AFFINEANIMCMD_JUMP(3), +}; + +static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_2[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 30), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 30), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_GrowingElectricOrb[] = +{ + sAffineAnim_GrowingElectricOrb_0, + sAffineAnim_GrowingElectricOrb_1, + sAffineAnim_GrowingElectricOrb_2, +}; + +const struct SpriteTemplate gGrowingChargeOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_GrowingElectricOrb, + .callback = AnimGrowingChargeOrb, +}; + +static const union AnimCmd sAnim_ElectricPuff[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_ElectricPuff[] = +{ + sAnim_ElectricPuff, +}; + +const struct SpriteTemplate gElectricPuffSpriteTemplate = +{ + .tileTag = ANIM_TAG_ELECTRICITY, + .paletteTag = ANIM_TAG_ELECTRICITY, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_ElectricPuff, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimElectricPuff, +}; + +const struct SpriteTemplate gVoltTackleOrbSlideSpriteTemplate = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_GrowingElectricOrb, + .callback = AnimVoltTackleOrbSlide, +}; + +static const union AnimCmd sAnim_VoltTackleBolt_0[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_VoltTackleBolt_1[] = +{ + ANIMCMD_FRAME(2, 3), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_VoltTackleBolt_2[] = +{ + ANIMCMD_FRAME(4, 3), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_VoltTackleBolt_3[] = +{ + ANIMCMD_FRAME(6, 3), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_VoltTackleBolt[] = +{ + sAnim_VoltTackleBolt_0, + sAnim_VoltTackleBolt_1, + sAnim_VoltTackleBolt_2, + sAnim_VoltTackleBolt_3, +}; + +static const union AffineAnimCmd sAffineAnim_VoltTackleBolt[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_VoltTackleBolt[] = +{ + sAffineAnim_VoltTackleBolt, +}; + +const struct SpriteTemplate gVoltTackleBoltSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK, + .paletteTag = ANIM_TAG_SPARK, + .oam = &gOamData_AffineDouble_ObjNormal_8x16, + .anims = sAnims_VoltTackleBolt, + .images = NULL, + .affineAnims = sAffineAnims_VoltTackleBolt, + .callback = AnimVoltTackleBolt, +}; + +const struct SpriteTemplate gGrowingShockWaveOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_GrowingElectricOrb, + .callback = AnimGrowingShockWaveOrb, +}; + +const struct SpriteTemplate gShockWaveProgressingBoltSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK, + .paletteTag = ANIM_TAG_SPARK, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimShockWaveProgressingBolt, +}; + +static void AnimLightning(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->callback = AnimLightning_Step; +} + +static void AnimLightning_Step(struct Sprite *sprite) +{ + if (sprite->animEnded) + DestroyAnimSprite(sprite); +} + +static void sub_810A214(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + + sprite->callback = sub_810A258; +} + +static void sub_810A258(struct Sprite *sprite) +{ + if (sprite->affineAnimEnded) + DestroySpriteAndMatrix(sprite); +} + +static void sub_810A274(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + sprite->pos1.y -= gBattleAnimArgs[1]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + sprite->data[0] = 0; + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[2] = gBattleAnimArgs[3]; + sprite->data[3] = gBattleAnimArgs[4]; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = TranslateSpriteInCircleOverDuration; +} + +static void AnimSparkElectricity(struct Sprite *sprite) +{ + u8 battler; + u32 matrixNum; + s16 sineVal; + + switch (gBattleAnimArgs[4]) + { + case ANIM_ATTACKER: + battler = gBattleAnimAttacker; + break; + case ANIM_TARGET: + default: + battler = gBattleAnimTarget; + break; + case ANIM_ATK_PARTNER: + if (!IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + battler = gBattleAnimAttacker; + else + battler = BATTLE_PARTNER(gBattleAnimAttacker); + break; + case ANIM_DEF_PARTNER: + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + battler = BATTLE_PARTNER(gBattleAnimTarget); + else + battler = gBattleAnimTarget; + break; + } + + if (gBattleAnimArgs[5] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X); + sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET); + } + + sprite->pos2.x = (gSineTable[gBattleAnimArgs[0]] * gBattleAnimArgs[1]) >> 8; + sprite->pos2.y = (gSineTable[gBattleAnimArgs[0] + 64] * gBattleAnimArgs[1]) >> 8; + + if (gBattleAnimArgs[6] & 1) + sprite->oam.priority = GetBattlerSpriteBGPriority(battler) + 1; + + matrixNum = sprite->oam.matrixNum; + sineVal = gSineTable[gBattleAnimArgs[2]]; + + gOamMatrices[matrixNum].a = gOamMatrices[matrixNum].d = gSineTable[gBattleAnimArgs[2] + 64]; + gOamMatrices[matrixNum].b = sineVal; + gOamMatrices[matrixNum].c = -sineVal; + + sprite->data[0] = gBattleAnimArgs[3]; + sprite->callback = DestroyAnimSpriteAfterTimer; +} + +static void AnimZapCannonSpark(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + InitAnimLinearTranslation(sprite); + sprite->data[5] = gBattleAnimArgs[2]; + sprite->data[6] = gBattleAnimArgs[5]; + sprite->data[7] = gBattleAnimArgs[4]; + sprite->oam.tileNum += gBattleAnimArgs[6] * 4; + sprite->callback = AnimZapCannonSpark_Step; + AnimZapCannonSpark_Step(sprite); +} + +static void AnimZapCannonSpark_Step(struct Sprite *sprite) +{ + if (!AnimTranslateLinear(sprite)) + { + sprite->pos2.x += Sin(sprite->data[7], sprite->data[5]); + sprite->pos2.y += Cos(sprite->data[7], sprite->data[5]); + sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; + if(!(sprite->data[7] % 3)) + sprite->invisible ^= 1; + } + else + DestroyAnimSprite(sprite); +} + +static void AnimThunderboltOrb_Step(struct Sprite *sprite) +{ + if (--sprite->data[5] == -1) + { + sprite->invisible ^= 1; + sprite->data[5] = sprite->data[4]; + } + if (sprite->data[3]-- <= 0) + DestroyAnimSprite(sprite); +} + +static void AnimThunderboltOrb(struct Sprite *sprite) +{ + if (IsContest() || GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[1]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[2]; + sprite->data[3] = gBattleAnimArgs[0]; + sprite->data[4] = gBattleAnimArgs[3]; + sprite->data[5] = gBattleAnimArgs[3]; + sprite->callback = AnimThunderboltOrb_Step; +} + +static void AnimSparkElectricityFlashing(struct Sprite *sprite) +{ + u8 battler; + + sprite->data[0] = gBattleAnimArgs[3]; + if (gBattleAnimArgs[7] & 0x8000) + battler = gBattleAnimTarget; + else + battler = gBattleAnimAttacker; + + if (IsContest() || GetBattlerSide(battler) == B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + + sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2) + gBattleAnimArgs[0]; + sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[1]; + + sprite->data[4] = gBattleAnimArgs[7] & 0x7FFF; + sprite->data[5] = gBattleAnimArgs[2]; + sprite->data[6] = gBattleAnimArgs[5]; + sprite->data[7] = gBattleAnimArgs[4]; + + sprite->oam.tileNum += gBattleAnimArgs[6] * 4; + sprite->callback = AnimSparkElectricityFlashing_Step; + sprite->callback(sprite); +} + +static void AnimSparkElectricityFlashing_Step(struct Sprite *sprite) +{ + sprite->pos2.x = Sin(sprite->data[7], sprite->data[5]); + sprite->pos2.y = Cos(sprite->data[7], sprite->data[5]); + + sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; + if (sprite->data[7] % sprite->data[4] == 0) + sprite->invisible ^= TRUE; + + if (sprite->data[0]-- <= 0) + DestroyAnimSprite(sprite); +} + +// Electricity arcs around the target. Used for Paralysis and various electric move hits +static void AnimElectricity(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, FALSE); + sprite->oam.tileNum += gBattleAnimArgs[3] * 4; + + if (gBattleAnimArgs[3] == 1) + sprite->oam.matrixNum = ST_OAM_HFLIP; + else if (gBattleAnimArgs[3] == 2) + sprite->oam.matrixNum = ST_OAM_VFLIP; + + sprite->data[0] = gBattleAnimArgs[2]; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// The vertical falling thunder bolt used in Thunder Wave/Shock/Bolt +void AnimTask_ElectricBolt(u8 taskId) +{ + gTasks[taskId].data[0] = GetBattlerSpriteCoord(gBattleAnimTarget, 0) + gBattleAnimArgs[0]; + gTasks[taskId].data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + gBattleAnimArgs[1]; + gTasks[taskId].data[2] = gBattleAnimArgs[2]; + gTasks[taskId].func = AnimTask_ElectricBolt_Step; +} + +static void AnimTask_ElectricBolt_Step(u8 taskId) +{ + u16 r8; + u16 r2; + s16 r12; + u8 spriteId = 0; + u8 r7 = 0; + u8 sp = gTasks[taskId].data[2]; + s16 x = gTasks[taskId].data[0]; + s16 y = gTasks[taskId].data[1]; + + if (!gTasks[taskId].data[2]) + { + r8 = 0; + r2 = 1; + r12 = 16; + } + else + { + r12 = 16; + r8 = 8; + r2 = 4; + } + + switch (gTasks[taskId].data[10]) + { + case 0: + r12 *= 1; + spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); + r7++; + break; + case 2: + r12 *= 2; + r8 += r2; + spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); + r7++; + break; + case 4: + r12 *= 3; + r8 += r2 * 2; + spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); + r7++; + break; + case 6: + r12 *= 4; + r8 += r2 * 3; + spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); + r7++; + break; + case 8: + r12 *= 5; + spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); + r7++; + break; + case 10: + DestroyAnimVisualTask(taskId); + return; + } + + if (r7) + { + gSprites[spriteId].oam.tileNum += r8; + gSprites[spriteId].data[0] = sp; + gSprites[spriteId].callback(&gSprites[spriteId]); + } + + gTasks[taskId].data[10]++; +} + +static void AnimElectricBoltSegment(struct Sprite *sprite) +{ + if (!sprite->data[0]) + { + sprite->oam.shape = SPRITE_SHAPE(8x16); + sprite->oam.size = SPRITE_SIZE(8x16); + } + else + { + sprite->oam.shape = SPRITE_SHAPE(16x16); + sprite->oam.size = SPRITE_SIZE(16x16); + } + if (++sprite->data[1] == 15) + DestroySprite(sprite); +} + +// The horizontal bands of electricity used in Thunder Wave +static void AnimThunderWave(struct Sprite *sprite) +{ + u8 spriteId; + + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + spriteId = CreateSprite(&gThunderWaveSpriteTemplate, sprite->pos1.x + 32, sprite->pos1.y, sprite->subpriority); + gSprites[spriteId].oam.tileNum += 8; + gAnimVisualTaskCount++; + gSprites[spriteId].callback = AnimThunderWave_Step; + sprite->callback = AnimThunderWave_Step; +} + +static void AnimThunderWave_Step(struct Sprite *sprite) +{ + if (++sprite->data[0] == 3) + { + sprite->data[0] = 0; + sprite->invisible ^= 1; + } + + if (++sprite->data[1] == 51) + DestroyAnimSprite(sprite); +} + +// Animates small electric orbs moving from around the battler inward. For Charge/Shock Wave +void AnimTask_ElectricChargingParticles(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + task->data[15] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + task->data[14] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + task->data[15] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + + task->data[6] = gBattleAnimArgs[1]; + task->data[7] = 0; + task->data[8] = 0; + task->data[9] = 0; + task->data[10] = 0; + task->data[11] = gBattleAnimArgs[3]; + task->data[12] = 0; + task->data[13] = gBattleAnimArgs[2]; + task->func = AnimTask_ElectricChargingParticles_Step; +} + +static void AnimTask_ElectricChargingParticles_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (task->data[6]) + { + if (++task->data[12] > task->data[13]) + { + u8 spriteId; + task->data[12] = 0; + spriteId = CreateSprite(&gElectricChargingParticlesSpriteTemplate, task->data[14], task->data[15], 2); + if (spriteId != MAX_SPRITES) + { + struct Sprite *sprite = &gSprites[spriteId]; + sprite->pos1.x += sElectricChargingParticleCoordOffsets[task->data[9]][0]; + sprite->pos1.y += sElectricChargingParticleCoordOffsets[task->data[9]][1]; + + sprite->data[0] = 40 - task->data[8] * 5; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = task->data[14]; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = task->data[15]; + sprite->data[5] = taskId; + + InitAnimLinearTranslation(sprite); + StoreSpriteCallbackInData6(sprite, AnimElectricChargingParticles); + sprite->callback = RunStoredCallbackWhenAnimEnds; + + if (++task->data[9] > 15) + task->data[9] = 0; + + if (++task->data[10] >= task->data[11]) + { + task->data[10] = 0; + if (task->data[8] <= 5) + task->data[8]++; + } + + task->data[7]++; + task->data[6]--; + } + } + } + else if(task->data[7] == 0) + DestroyAnimVisualTask(taskId); +} + +static void AnimElectricChargingParticles_Step(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + { + gTasks[sprite->data[5]].data[7]--; + DestroySprite(sprite); + } +} + +static void AnimElectricChargingParticles(struct Sprite *sprite) +{ + StartSpriteAnim(sprite, 1); + sprite->callback = AnimElectricChargingParticles_Step; +} + +static void AnimGrowingChargeOrb(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; +} + +// The quick electric burst at the end of Charge / during the Volt Tackle hit +static void AnimElectricPuff(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + + sprite->pos2.x = gBattleAnimArgs[1]; + sprite->pos2.y = gBattleAnimArgs[2]; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = RunStoredCallbackWhenAnimEnds; +} + +// Creates an orb of electricity that grows then slides off-screen. The attacker slides with it +static void AnimVoltTackleOrbSlide(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, 1); + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->data[6] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + sprite->data[7] = 16; + + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + sprite->data[7] *= -1; + + sprite->callback = AnimVoltTackleOrbSlide_Step; +} + +static void AnimVoltTackleOrbSlide_Step(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (++sprite->data[1] > 40) + sprite->data[0]++; + break; + case 1: + sprite->pos1.x += sprite->data[7]; + gSprites[sprite->data[6]].pos2.x += sprite->data[7]; + if ((u16)(sprite->pos1.x + 80) > 400) + DestroySpriteAndMatrix(sprite); + } +} + +void AnimTask_VoltTackleAttackerReappear(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + task->data[14] = -32; + task->data[13] = 2; + } + else + { + task->data[14] = 32; + task->data[13] = -2; + } + + gSprites[task->data[15]].pos2.x = task->data[14]; + task->data[0]++; + break; + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + gSprites[task->data[15]].invisible ^= 1; + + if (task->data[14]) + { + task->data[14] += task->data[13]; + gSprites[task->data[15]].pos2.x = task->data[14]; + } + else + task->data[0]++; + + } + break; + case 2: + if (++task->data[1] > 1) + { + task->data[1] = 0; + gSprites[task->data[15]].invisible ^= 1; + + if (++task->data[2] == 8) + task->data[0]++; + } + break; + case 3: + gSprites[task->data[15]].invisible = FALSE; + DestroyAnimVisualTask(taskId); + } +} + +// The horizontal bolts of electricity for Volt Tackle +void AnimTask_VoltTackleBolt(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch(task->data[0]) + { + case 0: + task->data[1] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER ? 1 : -1; + + switch (gBattleAnimArgs[0]) + { + case 0: + task->data[3] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + task->data[5] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + task->data[4] = (task->data[1] * 128) + 120; + break; + case 4: + task->data[3] = 120 - (task->data[1] * 128); + task->data[5] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + task->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) - (task->data[1] * 32); + break; + default: + if ((gBattleAnimArgs[0] & 1) != 0) + { + task->data[3] = 256; + task->data[4] = -16; + } + else + { + task->data[3] = -16; + task->data[4] = 256; + } + + if (task->data[1] == 1) + { + task->data[5] = 80 - gBattleAnimArgs[0] * 10; + } + else + { + u16 temp; + task->data[5] = gBattleAnimArgs[0] * 10 + 40; + temp = task->data[3]; + task->data[3] = task->data[4]; + task->data[4] = temp; + } + } + + if (task->data[3] < task->data[4]) + { + task->data[1] = 1; + task->data[6] = 0; + } + else + { + task->data[1] = -1; + task->data[6] = 3; + } + + task->data[0]++; + break; + case 1: + if (++task->data[2] > 0) + { + task->data[2] = 0; + if (sub_810B154(task, taskId) || sub_810B154(task, taskId)) + task->data[0]++; + } + break; + case 2: + if (task->data[7] == 0) + DestroyAnimVisualTask(taskId); + } +} + +static bool8 sub_810B154(struct Task *task, u8 taskId) +{ + u8 spriteId = CreateSprite(&gVoltTackleBoltSpriteTemplate, task->data[3], task->data[5], 35); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = 7; + task->data[7]++; + } + + task->data[6] += task->data[1]; + if (task->data[6] < 0) + task->data[6] = 3; + + if (task->data[6] > 3) + task->data[6] = 0; + + task->data[3] += task->data[1] * 16; + + if ((task->data[1] == 1 && task->data[3] >= task->data[4]) + || (task->data[1] == -1 && task->data[3] <= task->data[4])) + { + return TRUE; + } + else + { + return FALSE; + } +} + +static void AnimVoltTackleBolt(struct Sprite *sprite) +{ + if (++sprite->data[0] > 12) + { + gTasks[sprite->data[6]].data[sprite->data[7]]--; + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } +} + +static void AnimGrowingShockWaveOrb(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + StartSpriteAffineAnim(sprite, 2); + sprite->data[0]++; + break; + case 1: + if (sprite->affineAnimEnded) + DestroySpriteAndMatrix(sprite); + break; + } +} + +// Thin bolt of electricity that moves up and down toward the target. Used by Shock Wave +void AnimTask_ShockWaveProgressingBolt(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[6] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + task->data[7] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + task->data[8] = 4; + task->data[10] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + task->data[9] = (task->data[10] - task->data[6]) / 5; + task->data[4] = 7; + task->data[5] = -1; + task->data[11] = 12; + task->data[12] = BattleAnimAdjustPanning(task->data[11] - 76); + task->data[13] = BattleAnimAdjustPanning(SOUND_PAN_TARGET); + task->data[14] = task->data[12]; + task->data[15] = (task->data[13] - task->data[12]) / 3; + task->data[0]++; + break; + case 1: + if (++task->data[1] > 0) + { + task->data[1] = 0; + if (sub_810B430(task, taskId)) + { + if (task->data[2] == 5) + task->data[0] = 3; + else + task->data[0]++; + } + } + + if (task->data[11]) + task->data[11]--; + break; + case 2: + if (task->data[11]) + task->data[11]--; + + if (++task->data[1] > 4) + { + task->data[1] = 0; + if (task->data[2] & 1) + { + task->data[7] = 4; + task->data[8] = 68; + task->data[4] = 0; + task->data[5] = 1; + } + else + { + task->data[7] = 68; + task->data[8] = 4; + task->data[4] = 7; + task->data[5] = -1; + } + + if (task->data[11]) + task->data[0] = 4; + else + task->data[0] = 1; + } + break; + case 3: + if (task->data[3] == 0) + DestroyAnimVisualTask(taskId); + break; + case 4: + if (task->data[11]) + task->data[11]--; + else + task->data[0] = 1; + break; + } +} + +static bool8 sub_810B430(struct Task *task, u8 taskId) +{ + u8 spriteId = CreateSprite(&gShockWaveProgressingBoltSpriteTemplate, task->data[6], task->data[7], 35); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].oam.tileNum += task->data[4]; + task->data[4] += task->data[5]; + if (task->data[4] < 0) + task->data[4] = 7; + if (task->data[4] > 7) + task->data[4] = 0; + + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = 3; + task->data[3]++; + } + + if (task->data[4] == 0 && task->data[5] > 0) + { + task->data[14] += task->data[15]; + PlaySE12WithPanning(SE_W085, task->data[14]); + } + + if ((task->data[5] < 0 && task->data[7] <= task->data[8]) + || (task->data[5] > 0 && task->data[7] >= task->data[8])) + { + task->data[2]++; + task->data[6] += task->data[9]; + return TRUE; + } + else + { + task->data[7] += task->data[5] * 8; + return FALSE; + } +} + +// Just runs timer for sprite. See AnimTask_ShockWaveProgressingBolt +static void AnimShockWaveProgressingBolt(struct Sprite *sprite) +{ + if (++sprite->data[0] > 12) + { + gTasks[sprite->data[6]].data[sprite->data[7]]--; + DestroySprite(sprite); + } +} + +void AnimTask_ShockWaveLightning(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[15] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + 32; + task->data[14] = task->data[15]; + while (task->data[14] > 16) + { + task->data[14] -= 32; + } + + task->data[13] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + task->data[12] = GetBattlerSpriteSubpriority(gBattleAnimTarget) - 2; + task->data[0]++; + break; + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + if (sub_810B614(task, taskId)) + task->data[0]++; + } + break; + case 2: + if (task->data[10] == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + +bool8 sub_810B614(struct Task *task, u8 taskId) +{ + u8 spriteId = CreateSprite(&gLightningSpriteTemplate, task->data[13], task->data[14], task->data[12]); + + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].callback = sub_810B684; + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = 10; + task->data[10]++; + } + if (task->data[14] >= task->data[15]) + return TRUE; + task->data[14] += 32; + return FALSE; +} + +static void sub_810B684(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + gTasks[sprite->data[6]].data[sprite->data[7]]--; + DestroySprite(sprite); + } +} diff --git a/src/battle_anim_fight.c b/src/battle_anim_fight.c new file mode 100644 index 000000000..5211860e0 --- /dev/null +++ b/src/battle_anim_fight.c @@ -0,0 +1,1043 @@ +#include "global.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "random.h" +#include "task.h" +#include "trig.h" +#include "constants/rgb.h" + +static void unc_080B08A0(struct Sprite *); +static void AnimSlideHandOrFootToTarget(struct Sprite *); +static void AnimJumpKick(struct Sprite *); +static void AnimBasicFistOrFoot(struct Sprite *); +static void AnimFistOrFootRandomPos(struct Sprite *); +static void AnimFistOrFootRandomPos_Step(struct Sprite *); +static void AnimCrossChopHand(struct Sprite *); +static void AnimCrossChopHand_Step(struct Sprite *); +static void AnimSlidingKick(struct Sprite *); +static void AnimSlidingKick_Step(struct Sprite *); +static void AnimSpinningKickOrPunch(struct Sprite *); +static void AnimStompFoot(struct Sprite *); +static void AnimStompFoot_Step(struct Sprite *); +static void AnimStompFoot_End(struct Sprite *); +static void AnimDizzyPunchDuck(struct Sprite *); +static void AnimBrickBreakWall(struct Sprite *); +static void AnimBrickBreakWall_Step(struct Sprite *); +static void AnimBrickBreakWallShard(struct Sprite *); +static void AnimBrickBreakWallShard_Step(struct Sprite *); +static void AnimSuperpowerOrb(struct Sprite *); +static void AnimSuperpowerOrb_Step(struct Sprite *); +static void AnimSuperpowerRock(struct Sprite *); +static void AnimSuperpowerRock_Step1(struct Sprite *); +static void AnimSuperpowerRock_Step2(struct Sprite *); +static void AnimSuperpowerFireball(struct Sprite *); +static void AnimArmThrustHit(struct Sprite *); +static void AnimArmThrustHit_Step(struct Sprite *sprite); +static void AnimRevengeScratch(struct Sprite *); +static void AnimFocusPunchFist(struct Sprite *); +static void AnimSpinningKickOrPunchFinish(struct Sprite *); + +extern struct SpriteTemplate gBasicHitSplatSpriteTemplate; + +// Unused +const struct SpriteTemplate gUnknown_08595E14 = +{ + .tileTag = ANIM_TAG_HUMANOID_FOOT, + .paletteTag = ANIM_TAG_HUMANOID_FOOT, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = unc_080B08A0, +}; + +static const union AnimCmd sAnim_HandOrFoot[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_SlidingKick_0[] = +{ + ANIMCMD_FRAME(16, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_SlidingKick_1[] = +{ + ANIMCMD_FRAME(32, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_CrossChopHand_0[] = +{ + ANIMCMD_FRAME(48, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_CrossChopHand_1[] = +{ + ANIMCMD_FRAME(48, 1, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_HandOrFoot[] = +{ + sAnim_HandOrFoot, +}; + +static const union AnimCmd *const sAnims_SlidingKick[] = +{ + sAnim_SlidingKick_0, + sAnim_SlidingKick_1, +}; + +static const union AnimCmd *const sAnims_CrossChopHand[] = +{ + sAnim_CrossChopHand_0, + sAnim_CrossChopHand_1, +}; + +const struct SpriteTemplate gKarateChopSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_HandOrFoot, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSlideHandOrFootToTarget, +}; + +const struct SpriteTemplate gJumpKickSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_HandOrFoot, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimJumpKick, +}; + +const struct SpriteTemplate gFistFootSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_HandOrFoot, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimBasicFistOrFoot, +}; + +const struct SpriteTemplate gFistFootRandomPosSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_HandOrFoot, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFistOrFootRandomPos, +}; + +const struct SpriteTemplate gCrossChopHandSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_CrossChopHand, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimCrossChopHand, +}; + +const struct SpriteTemplate gSlidingKickSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_SlidingKick, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSlidingKick, +}; + +static const union AffineAnimCmd sAffineAnim_SpinningHandOrFoot[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 20, 1), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const sAffineAnims_SpinningHandOrFoot[] = +{ + sAffineAnim_SpinningHandOrFoot, +}; + +// Blaze Kick / Meteor Mash +const struct SpriteTemplate gSpinningHandOrFootSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineDouble_ObjNormal_32x32, + .anims = sAnims_HandOrFoot, + .images = NULL, + .affineAnims = sAffineAnims_SpinningHandOrFoot, + .callback = AnimSpinningKickOrPunch, +}; + +static const union AffineAnimCmd sAffineAnim_MegaPunchKick[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0xFFFC, 0xFFFC, 20, 1), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const sAffineAnims_MegaPunchKick[] = +{ + sAffineAnim_MegaPunchKick, +}; + +const struct SpriteTemplate gMegaPunchKickSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineDouble_ObjNormal_32x32, + .anims = sAnims_HandOrFoot, + .images = NULL, + .affineAnims = sAffineAnims_MegaPunchKick, + .callback = AnimSpinningKickOrPunch, +}; + +const struct SpriteTemplate gStompFootSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_SlidingKick, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimStompFoot, +}; + +const struct SpriteTemplate gDizzyPunchDuckSpriteTemplate = +{ + .tileTag = ANIM_TAG_DUCK, + .paletteTag = ANIM_TAG_DUCK, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDizzyPunchDuck, +}; + +const struct SpriteTemplate gBrickBreakWallSpriteTemplate = +{ + .tileTag = ANIM_TAG_BLUE_LIGHT_WALL, + .paletteTag = ANIM_TAG_BLUE_LIGHT_WALL, + .oam = &gOamData_AffineOff_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimBrickBreakWall, +}; + +const struct SpriteTemplate gBrickBreakWallShardSpriteTemplate = +{ + .tileTag = ANIM_TAG_TORN_METAL, + .paletteTag = ANIM_TAG_TORN_METAL, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimBrickBreakWallShard, +}; + +static const union AffineAnimCmd sAffineAnim_SuperpowerOrb[] = +{ + AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 64), + AFFINEANIMCMD_FRAME(0xFFFA, 0xFFFA, 0, 8), + AFFINEANIMCMD_FRAME(0x6, 0x6, 0, 8), + AFFINEANIMCMD_JUMP(2), +}; + +static const union AffineAnimCmd *const sAffineAnims_SuperpowerOrb[] = +{ + sAffineAnim_SuperpowerOrb, +}; + +const struct SpriteTemplate gSuperpowerOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineDouble_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_SuperpowerOrb, + .callback = AnimSuperpowerOrb, +}; + +const struct SpriteTemplate gSuperpowerRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_FLAT_ROCK, + .paletteTag = ANIM_TAG_FLAT_ROCK, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSuperpowerRock, +}; + +const struct SpriteTemplate gSuperpowerFireballSpriteTemplate = +{ + .tileTag = ANIM_TAG_METEOR, + .paletteTag = ANIM_TAG_METEOR, + .oam = &gOamData_AffineOff_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSuperpowerFireball, +}; + +const struct SpriteTemplate gArmThrustHandSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_HandOrFoot, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimArmThrustHit, +}; + +static const union AnimCmd sAnim_RevengeSmallScratch_0[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_RevengeSmallScratch_1[] = +{ + ANIMCMD_FRAME(0, 4, .vFlip = TRUE), + ANIMCMD_FRAME(16, 4, .vFlip = TRUE), + ANIMCMD_FRAME(32, 4, .vFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_RevengeSmallScratch_2[] = +{ + ANIMCMD_FRAME(0, 4, .hFlip = TRUE), + ANIMCMD_FRAME(16, 4, .hFlip = TRUE), + ANIMCMD_FRAME(32, 4, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_RevengeSmallScratch[] = +{ + sAnim_RevengeSmallScratch_0, + sAnim_RevengeSmallScratch_1, + sAnim_RevengeSmallScratch_2, +}; + +const struct SpriteTemplate gRevengeSmallScratchSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_SCRATCH, + .paletteTag = ANIM_TAG_PURPLE_SCRATCH, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_RevengeSmallScratch, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRevengeScratch, +}; + +static const union AnimCmd sAnim_RevengeBigScratch_0[] = +{ + ANIMCMD_FRAME(0, 6), + ANIMCMD_FRAME(64, 6), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_RevengeBigScratch_1[] = +{ + ANIMCMD_FRAME(0, 6, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_FRAME(64, 6, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_RevengeBigScratch_2[] = +{ + ANIMCMD_FRAME(0, 6, .hFlip = TRUE), + ANIMCMD_FRAME(64, 6, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_RevengeBigScratch[] = +{ + sAnim_RevengeBigScratch_0, + sAnim_RevengeBigScratch_1, + sAnim_RevengeBigScratch_2, +}; + +const struct SpriteTemplate gRevengeBigScratchSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_SWIPE, + .paletteTag = ANIM_TAG_PURPLE_SWIPE, + .oam = &gOamData_AffineOff_ObjNormal_64x64, + .anims = sAnims_RevengeBigScratch, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRevengeScratch, +}; + +static const union AffineAnimCmd sAffineAnim_FocusPunchFist[] = +{ + AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0), + AFFINEANIMCMD_FRAME(0xFFE0, 0xFFE0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_FocusPunchFist[] = +{ + sAffineAnim_FocusPunchFist, +}; + +const struct SpriteTemplate gFocusPunchFistSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_AffineDouble_ObjNormal_32x32, + .anims = sAnims_HandOrFoot, + .images = NULL, + .affineAnims = sAffineAnims_FocusPunchFist, + .callback = AnimFocusPunchFist, +}; + +static void unc_080B08A0(struct Sprite *sprite) +{ + SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = 15; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void AnimSlideHandOrFootToTarget(struct Sprite *sprite) +{ + if (gBattleAnimArgs[7] == 1 && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + } + + StartSpriteAnim(sprite, gBattleAnimArgs[6]); + gBattleAnimArgs[6] = 0; + AnimTravelDiagonally(sprite); +} + +static void AnimJumpKick(struct Sprite *sprite) +{ + if (IsContest()) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + } + + AnimSlideHandOrFootToTarget(sprite); +} + +// Displays a basic fist or foot sprite for a given duration. +// Used by many fighting moves (and elemental "punch" moves). +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: duration +// arg 3: ? (todo: related to initial pixel offsets) +// arg 4: anim num +static void AnimBasicFistOrFoot(struct Sprite *sprite) +{ + StartSpriteAnim(sprite, gBattleAnimArgs[4]); + + if (gBattleAnimArgs[3] == 0) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + + sprite->data[0] = gBattleAnimArgs[2]; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void AnimFistOrFootRandomPos(struct Sprite *sprite) +{ + u8 battler; + s16 xMod, yMod; + s16 x, y; + + if (gBattleAnimArgs[0] == 0) + battler = gBattleAnimAttacker; + else + battler = gBattleAnimTarget; + + if (gBattleAnimArgs[2] < 0) + gBattleAnimArgs[2] = Random2() % 5; + + StartSpriteAnim(sprite, gBattleAnimArgs[2]); + sprite->pos1.x = GetBattlerSpriteCoord(battler, 2); + sprite->pos1.y = GetBattlerSpriteCoord(battler, 3); + + xMod = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_WIDTH) / 2; + yMod = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_HEIGHT) / 4; + + x = Random2() % xMod; + y = Random2() % yMod; + + if (Random2() & 1) + x *= -1; + if (Random2() & 1) + y *= -1; + + if ((gBattlerPositions[battler] & BIT_SIDE) == B_SIDE_PLAYER) + y += 0xFFF0; + + sprite->pos1.x += x; + sprite->pos1.y += y; + + sprite->data[0] = gBattleAnimArgs[1]; + sprite->data[7] = CreateSprite(&gBasicHitSplatSpriteTemplate, sprite->pos1.x, sprite->pos1.y, sprite->subpriority + 1); + if (sprite->data[7] != 64) + { + StartSpriteAffineAnim(&gSprites[sprite->data[7]], 0); + gSprites[sprite->data[7]].callback = SpriteCallbackDummy; + } + + sprite->callback = AnimFistOrFootRandomPos_Step; +} + +static void AnimFistOrFootRandomPos_Step(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + if (sprite->data[7] != 64) + { + FreeOamMatrix(gSprites[sprite->data[7]].oam.matrixNum); + DestroySprite(&gSprites[sprite->data[7]]); + } + + DestroyAnimSprite(sprite); + } + else + { + sprite->data[0]--; + } +} + +static void AnimCrossChopHand(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = 30; + + if (gBattleAnimArgs[2] == 0) + { + sprite->data[2] = sprite->pos1.x - 20; + } + else + { + sprite->data[2] = sprite->pos1.x + 20; + sprite->hFlip = 1; + } + + sprite->data[4] = sprite->pos1.y - 20; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, AnimCrossChopHand_Step); +} + +static void AnimCrossChopHand_Step(struct Sprite *sprite) +{ + if (++sprite->data[5] == 11) + { + sprite->data[2] = sprite->pos1.x - sprite->pos2.x; + sprite->data[4] = sprite->pos1.y - sprite->pos2.y; + sprite->data[0] = 8; + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + } +} + +// Rolling Kick / Low Kick +static void AnimSlidingKick(struct Sprite *sprite) +{ + if (BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget && GetBattlerPosition(gBattleAnimTarget) < B_POSITION_PLAYER_RIGHT) + gBattleAnimArgs[0] *= -1; + + InitSpritePosToAnimTarget(sprite, TRUE); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y; + + InitAnimLinearTranslation(sprite); + + sprite->data[5] = gBattleAnimArgs[5]; + sprite->data[6] = gBattleAnimArgs[4]; + sprite->data[7] = 0; + + sprite->callback = AnimSlidingKick_Step; +} + +static void AnimSlidingKick_Step(struct Sprite *sprite) +{ + if (!AnimTranslateLinear(sprite)) + { + sprite->pos2.y += Sin(sprite->data[7] >> 8, sprite->data[5]); + sprite->data[7] += sprite->data[6]; + } + else + { + DestroyAnimSprite(sprite); + } +} + +// Animates the spinning, shrinking kick or punch, which then +// reappears at full size. Used by moves such as MOVE_MEGA_PUNCH and MOVE_MEGA_KICK. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: anim num +// arg 3: spin duration +static void AnimSpinningKickOrPunch(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + StartSpriteAnim(sprite, gBattleAnimArgs[2]); + sprite->data[0] = gBattleAnimArgs[3]; + + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, AnimSpinningKickOrPunchFinish); +} + +static void AnimSpinningKickOrPunchFinish(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, 0); + sprite->affineAnimPaused = 1; + sprite->data[0] = 20; + + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Animates MOVE_STOMP's foot that slides downward. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: initial wait duration +static void AnimStompFoot(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[2]; + + sprite->callback = AnimStompFoot_Step; +} + +static void AnimStompFoot_Step(struct Sprite *sprite) +{ + if (--sprite->data[0] == -1) + { + sprite->data[0] = 6; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, AnimStompFoot_End); + } +} + +static void AnimStompFoot_End(struct Sprite *sprite) +{ + sprite->data[0] = 15; + + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void AnimDizzyPunchDuck(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[2] = gBattleAnimArgs[3]; + sprite->data[0]++; + } + else + { + sprite->data[4] += sprite->data[1]; + sprite->pos2.x = sprite->data[4] >> 8; + sprite->pos2.y = Sin(sprite->data[3], sprite->data[2]); + sprite->data[3] = (sprite->data[3] + 3) & 0xFF; + + if (sprite->data[3] > 100) + sprite->invisible = sprite->data[3] % 2; + + if (sprite->data[3] > 120) + DestroyAnimSprite(sprite); + } +} + +// The wall that appears when Brick Break is going to shatter the target's defensive wall +static void AnimBrickBreakWall(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); + } + + sprite->pos1.x += gBattleAnimArgs[1]; + sprite->pos1.y += gBattleAnimArgs[2]; + + sprite->data[0] = 0; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[2] = gBattleAnimArgs[4]; + sprite->data[3] = 0; + sprite->callback = AnimBrickBreakWall_Step; +} + +static void AnimBrickBreakWall_Step(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (--sprite->data[1] == 0) + { + if (sprite->data[2] == 0) + DestroyAnimSprite(sprite); + else + sprite->data[0]++; + } + break; + case 1: + if (++sprite->data[1] > 1) + { + sprite->data[1] = 0; + sprite->data[3]++; + if (sprite->data[3] & 1) + sprite->pos2.x = 2; + else + sprite->pos2.x = -2; + } + + if (--sprite->data[2] == 0) + DestroyAnimSprite(sprite); + break; + } +} + +// Piece of shattered defensive wall flies off. Used by Brick Break when the target has a defensive wall +static void AnimBrickBreakWallShard(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0) + gBattleAnimArgs[2]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + gBattleAnimArgs[3]; + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0) + gBattleAnimArgs[2]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + gBattleAnimArgs[3]; + } + + sprite->oam.tileNum += gBattleAnimArgs[1] * 16; + sprite->data[0] = 0; + + switch (gBattleAnimArgs[1]) + { + case 0: + sprite->data[6] = -3; + sprite->data[7] = -3; + break; + case 1: + sprite->data[6] = 3; + sprite->data[7] = -3; + break; + case 2: + sprite->data[6] = -3; + sprite->data[7] = 3; + break; + case 3: + sprite->data[6] = 3; + sprite->data[7] = 3; + break; + default: + DestroyAnimSprite(sprite); + return; + } + + sprite->callback = AnimBrickBreakWallShard_Step; +} + +static void AnimBrickBreakWallShard_Step(struct Sprite *sprite) +{ + sprite->pos1.x += sprite->data[6]; + sprite->pos1.y += sprite->data[7]; + + if (++sprite->data[0] > 40) + DestroyAnimSprite(sprite); +} + +static void AnimSuperpowerOrb(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattlerAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattlerAttacker, 3); + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker); + sprite->data[7] = gBattleAnimTarget; + } + else + { + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + sprite->data[7] = gBattleAnimAttacker; + } + + sprite->data[0] = 0; + sprite->data[1] = 12; + sprite->data[2] = 8; + sprite->callback = AnimSuperpowerOrb_Step; +} + +static void AnimSuperpowerOrb_Step(struct Sprite *sprite) +{ + if (++sprite->data[0] == 180) + { + SetGpuReg(REG_OFFSET_BLDCNT, 0); + + sprite->data[0] = 16; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(sprite->data[7], 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(sprite->data[7], 3); + + InitAnimLinearTranslation(sprite); + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = sub_80A6F98; + } +} + +// Floating rock that flies off to hit the target. Used by Superpower +static void AnimSuperpowerRock(struct Sprite *sprite) +{ + sprite->pos1.x = gBattleAnimArgs[0]; + sprite->pos1.y = 120; + + sprite->data[0] = gBattleAnimArgs[3]; + StorePointerInVars(&sprite->data[4], &sprite->data[5], (void *)(sprite->pos1.y << 8)); + + sprite->data[6] = gBattleAnimArgs[1]; + sprite->oam.tileNum += gBattleAnimArgs[2] * 4; + + sprite->callback = AnimSuperpowerRock_Step1; +} + +static void AnimSuperpowerRock_Step1(struct Sprite *sprite) +{ + void *var0; + + if (sprite->data[0] != 0) + { + var0 = LoadPointerFromVars(sprite->data[4], sprite->data[5]); + var0 -= sprite->data[6]; + StorePointerInVars(&sprite->data[4], &sprite->data[5], var0); + + var0 = (void *)(((intptr_t)var0) >> 8); + sprite->pos1.y = (intptr_t)var0; + if (sprite->pos1.y < -8) + DestroyAnimSprite(sprite); + else + sprite->data[0]--; + } + else + { + s16 pos0 = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + s16 pos1 = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + s16 pos2 = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + s16 pos3 = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + + sprite->data[0] = pos2 - pos0; + sprite->data[1] = pos3 - pos1; + sprite->data[2] = sprite->pos1.x << 4; + sprite->data[3] = sprite->pos1.y << 4; + + sprite->callback = AnimSuperpowerRock_Step2; + } +} + +static void AnimSuperpowerRock_Step2(struct Sprite *sprite) +{ + u16 edgeX; + + sprite->data[2] += sprite->data[0]; + sprite->data[3] += sprite->data[1]; + sprite->pos1.x = sprite->data[2] >> 4; + sprite->pos1.y = sprite->data[3] >> 4; + + edgeX = sprite->pos1.x + 8; + if (edgeX > 256 || sprite->pos1.y < -8 || sprite->pos1.y > 120) + DestroyAnimSprite(sprite); +} + +static void AnimSuperpowerFireball(struct Sprite *sprite) +{ + u8 battler; + + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattlerAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattlerAttacker, 3); + battler = gBattleAnimTarget; + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker); + } + else + { + battler = gBattleAnimAttacker; + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + } + + if (IsContest()) + sprite->oam.matrixNum |= ST_OAM_HFLIP; + else if (GetBattlerSide(battler) == B_SIDE_PLAYER) + sprite->oam.matrixNum |= (ST_OAM_HFLIP | ST_OAM_VFLIP); + + sprite->data[0] = 16; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(battler, 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(battler, 3); + + InitAnimLinearTranslation(sprite); + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = sub_80A6F98; +} + +static void AnimArmThrustHit_Step(struct Sprite *sprite) +{ + if (sprite->data[0] == sprite->data[4]) + DestroyAnimSprite(sprite); + + sprite->data[0]++; +} + +static void AnimArmThrustHit(struct Sprite *sprite) +{ + u8 turn; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[2] = gBattleAnimArgs[0]; + sprite->data[3] = gBattleAnimArgs[1]; + sprite->data[4] = gBattleAnimArgs[2]; + + turn = gAnimMoveTurn; + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + turn++; + + if (turn & 1) + { + sprite->data[2] = -sprite->data[2]; + sprite->data[1]++; + } + + StartSpriteAnim(sprite, sprite->data[1]); + sprite->pos2.x = sprite->data[2]; + sprite->pos2.y = sprite->data[3]; + sprite->callback = AnimArmThrustHit_Step; +} + +static void AnimRevengeScratch(struct Sprite *sprite) +{ + if (gBattleAnimArgs[2] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, 0); + else + InitSpritePosToAnimTarget(sprite, FALSE); + + if (IsContest()) + { + StartSpriteAnim(sprite, 2); + } + else if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + StartSpriteAnim(sprite, 1); + } + + sprite->callback = RunStoredCallbackWhenAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Fist shrinks toward target and shakes +static void AnimFocusPunchFist(struct Sprite *sprite) +{ + if (sprite->affineAnimEnded) + { + sprite->data[1] = (sprite->data[1] + 40) & 0xFF; + sprite->pos2.x = Sin(sprite->data[1], 2); + if (++sprite->data[0] > 40) + DestroyAnimSprite(sprite); + } +} + +void AnimTask_MoveSkyUppercutBg(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + sub_80A6DAC(0); + task->data[8] = gBattleAnimArgs[0]; + task->data[0]++; + break; + case 1: + if (--task->data[8] == -1) + task->data[0]++; + break; + case 2: + default: + task->data[9] += 1280; + break; + } + + task->data[10] += 2816; + + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + gBattle_BG3_X += task->data[9] >> 8; + else + gBattle_BG3_X -= task->data[9] >> 8; + + gBattle_BG3_Y += task->data[10] >> 8; + task->data[9] &= 0xFF; + task->data[10] &= 0xFF; + + if (gBattleAnimArgs[7] == -1) + { + gBattle_BG3_X = 0; + gBattle_BG3_Y = 0; + sub_80A6DAC(1); + DestroyAnimVisualTask(taskId); + } +} diff --git a/src/battle_anim_fire.c b/src/battle_anim_fire.c new file mode 100644 index 000000000..f02ecae19 --- /dev/null +++ b/src/battle_anim_fire.c @@ -0,0 +1,1335 @@ +#include "global.h" +#include "battle_anim.h" +#include "constants/rgb.h" +#include "constants/songs.h" +#include "sound.h" +#include "util.h" +#include "task.h" +#include "trig.h" + +static void AnimFireSpiralInward(struct Sprite *); +static void AnimFireSpread(struct Sprite *); +static void AnimFirePlume(struct Sprite *); +static void AnimLargeFlame(struct Sprite *); +static void sub_8109028(struct Sprite *); +static void sub_8109064(struct Sprite *); +static void sub_81090D8(struct Sprite *); +static void AnimSunlight(struct Sprite *); +static void AnimEmberFlare(struct Sprite *); +static void AnimBurnFlame(struct Sprite *); +static void AnimFireRing(struct Sprite *); +static void AnimFireRing_Step1(struct Sprite *); +static void AnimFireRing_Step2(struct Sprite *); +static void AnimFireRing_Step3(struct Sprite *); +static void UpdateFireRingCircleOffset(struct Sprite *); +static void AnimFireCross(struct Sprite *); +static void AnimFireSpiralOutward(struct Sprite *); +static void AnimFireSpiralOutward_Step1(struct Sprite *); +static void AnimFireSpiralOutward_Step2(struct Sprite *); +static void AnimTask_EruptionLaunchRocks_Step(u8 taskId); +static void CreateEruptionLaunchRocks(u8 spriteId, u8 taskId, u8 a3); +static void AnimEruptionLaunchRock(struct Sprite *); +static u16 GetEruptionLaunchRockInitialYPos(u8 spriteId); +static void InitEruptionLaunchRockCoordData(struct Sprite *sprite, s16 x, s16 y); +static void UpdateEruptionLaunchRockPos(struct Sprite *); +static void AnimEruptionFallingRock(struct Sprite *); +static void AnimEruptionFallingRock_Step(struct Sprite *); +static void AnimWillOWispOrb(struct Sprite *); +static void AnimWillOWispOrb_Step(struct Sprite *); +static void AnimWillOWispFire(struct Sprite *); +static void AnimTask_MoveHeatWaveTargets_Step(u8 taskId); + +static const union AnimCmd sAnim_FireSpiralSpread_0[] = +{ + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(48, 4), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_FireSpiralSpread_1[] = +{ + ANIMCMD_FRAME(16, 4, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_FRAME(32, 4, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_FRAME(48, 4, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_FireSpiralSpread[] = +{ + sAnim_FireSpiralSpread_0, + sAnim_FireSpiralSpread_1, +}; + +const struct SpriteTemplate gFireSpiralInwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_FireSpiralSpread, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralInward, +}; + +const struct SpriteTemplate gFireSpreadSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_FireSpiralSpread, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpread, +}; + +static const union AnimCmd sAnim_LargeFlame[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_FRAME(64, 3), + ANIMCMD_FRAME(80, 3), + ANIMCMD_FRAME(96, 3), + ANIMCMD_FRAME(112, 3), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_LargeFlame[] = +{ + sAnim_LargeFlame, +}; + +static const union AnimCmd sAnim_FirePlume[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 5), + ANIMCMD_FRAME(48, 5), + ANIMCMD_FRAME(64, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_FirePlume[] = +{ + sAnim_FirePlume, +}; + +static const union AffineAnimCmd sAffineAnim_LargeFlame[] = +{ + AFFINEANIMCMD_FRAME(0x32, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x20, 0x0, 0, 7), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_LargeFlame[] = +{ + sAffineAnim_LargeFlame, +}; + +const struct SpriteTemplate gLargeFlameSpriteTemplate = +{ + .tileTag = ANIM_TAG_FIRE, + .paletteTag = ANIM_TAG_FIRE, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = sAnims_LargeFlame, + .images = NULL, + .affineAnims = sAffineAnims_LargeFlame, + .callback = AnimLargeFlame, +}; + +const struct SpriteTemplate gLargeFlameScatterSpriteTemplate = +{ + .tileTag = ANIM_TAG_FIRE, + .paletteTag = ANIM_TAG_FIRE, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_LargeFlame, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimLargeFlame, +}; + +const struct SpriteTemplate gFirePlumeSpriteTemplate = +{ + .tileTag = ANIM_TAG_FIRE_PLUME, + .paletteTag = ANIM_TAG_FIRE_PLUME, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_FirePlume, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFirePlume, +}; + +// Unused +const struct SpriteTemplate gUnknown_08595440 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_FirePlume, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFirePlume, +}; + +static const union AnimCmd gUnknown_08595458[] = +{ + ANIMCMD_FRAME(16, 6), + ANIMCMD_FRAME(32, 6), + ANIMCMD_FRAME(48, 6), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_08595468[] = +{ + gUnknown_08595458, +}; + +// Unused +const struct SpriteTemplate gUnknown_0859546C = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gUnknown_08595468, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_8109064, +}; + +static const union AffineAnimCmd sAffineAnim_SunlightRay[] = +{ + AFFINEANIMCMD_FRAME(0x50, 0x50, 0, 0), + AFFINEANIMCMD_FRAME(0x2, 0x2, 10, 1), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const sAffineAnims_SunlightRay[] = +{ + sAffineAnim_SunlightRay, +}; + +const struct SpriteTemplate gSunlightRaySpriteTemplate = +{ + .tileTag = ANIM_TAG_SUNLIGHT, + .paletteTag = ANIM_TAG_SUNLIGHT, + .oam = &gOamData_AffineNormal_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_SunlightRay, + .callback = AnimSunlight, +}; + +static const union AnimCmd sAnim_BasicFire[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(48, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_JUMP(0), +}; + +const union AnimCmd *const gAnims_BasicFire[] = +{ + sAnim_BasicFire, +}; + +const struct SpriteTemplate gEmberSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = TranslateAnimSpriteToTargetMonLocation, +}; + +const struct SpriteTemplate gEmberFlareSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimEmberFlare, +}; + +const struct SpriteTemplate gBurnFlameSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimBurnFlame, +}; + +const struct SpriteTemplate gFireBlastRingSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireRing, +}; + +static const union AnimCmd sAnim_FireBlastCross[] = +{ + ANIMCMD_FRAME(32, 6), + ANIMCMD_FRAME(48, 6), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_FireBlastCross[] = +{ + sAnim_FireBlastCross, +}; + +static const union AffineAnimCmd gUnknown_08595544[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_08595554[] = +{ + AFFINEANIMCMD_FRAME(0xA0, 0xA0, 0, 0), + AFFINEANIMCMD_END, +}; + +// Unused +static const union AffineAnimCmd *const gUnknown_08595564[] = +{ + gUnknown_08595544, + gUnknown_08595554, +}; + +const struct SpriteTemplate gFireBlastCrossSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_FireBlastCross, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireCross, +}; + +const struct SpriteTemplate gFireSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gWeatherBallFireDownSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWeatherBallDown, +}; + +const struct SpriteTemplate gEruptionLaunchRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_WARM_ROCK, + .paletteTag = ANIM_TAG_WARM_ROCK, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimEruptionLaunchRock, +}; + +static const s16 sEruptionLaunchRockCoords[][2] = +{ + {-2, -5}, + {-1, -1}, + { 3, -6}, + { 4, -2}, + { 2, -8}, + {-5, -5}, + { 4, -7}, +}; + +const struct SpriteTemplate gEruptionFallingRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_WARM_ROCK, + .paletteTag = ANIM_TAG_WARM_ROCK, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimEruptionFallingRock, +}; + +static const union AnimCmd sAnim_WillOWispOrb_0[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_FRAME(12, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_WillOWispOrb_1[] = +{ + ANIMCMD_FRAME(16, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_WillOWispOrb_2[] = +{ + ANIMCMD_FRAME(20, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_WillOWispOrb_3[] = +{ + ANIMCMD_FRAME(20, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_WillOWispOrb[] = +{ + sAnim_WillOWispOrb_0, + sAnim_WillOWispOrb_1, + sAnim_WillOWispOrb_2, + sAnim_WillOWispOrb_3, +}; + +const struct SpriteTemplate gWillOWispOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_WISP_ORB, + .paletteTag = ANIM_TAG_WISP_ORB, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = sAnims_WillOWispOrb, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWillOWispOrb, +}; + +static const union AnimCmd sAnim_WillOWispFire[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 5), + ANIMCMD_FRAME(48, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_WillOWispFire[] = +{ + sAnim_WillOWispFire, +}; + +const struct SpriteTemplate gWillOWispFireSpriteTemplate = +{ + .tileTag = ANIM_TAG_WISP_FIRE, + .paletteTag = ANIM_TAG_WISP_FIRE, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_WillOWispFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWillOWispFire, +}; + +// Directions for shaking up/down or left/right in AnimTask_ShakeTargetInPattern +// Only first 10 values are ever accessed. +// First pattern results in larger shakes, second results in faster oscillation +static const s8 sShakeDirsPattern0[16] = +{ + -1, -1, 0, 1, 1, 0, 0, -1, -1, 1, 1, 0, 0, -1, 0, 1, +}; + +static const s8 sShakeDirsPattern1[16] = +{ + -1, 0, 1, 0, -1, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 1, +}; + +// For the first stage of Fire Punch +static void AnimFireSpiralInward(struct Sprite *sprite) +{ + sprite->data[0] = gBattleAnimArgs[0]; + sprite->data[1] = 0x3C; + sprite->data[2] = 0x9; + sprite->data[3] = 0x1E; + sprite->data[4] = 0xFE00; + + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + + sprite->callback = TranslateSpriteInGrowingCircleOverDuration; + sprite->callback(sprite); +} + +// For the impact spread of fire sprites for moves like Blaze Kick or Fire Punch +static void AnimFireSpread(struct Sprite *sprite) +{ + SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); + + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[2] = gBattleAnimArgs[3]; + + sprite->callback = TranslateSpriteLinearFixedPoint; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void AnimFirePlume(struct Sprite *sprite) +{ + SetSpriteCoordsToAnimAttackerCoords(sprite); + + if (GetBattlerSide(gBattleAnimAttacker)) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] = -gBattleAnimArgs[4]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] = gBattleAnimArgs[4]; + } + + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[4] = gBattleAnimArgs[3]; + sprite->data[3] = gBattleAnimArgs[5]; + + sprite->callback = sub_8109028; +} + +static void AnimLargeFlame(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker)) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] = gBattleAnimArgs[4]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] = -gBattleAnimArgs[4]; + } + + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[4] = gBattleAnimArgs[3]; + sprite->data[3] = gBattleAnimArgs[5]; + + sprite->callback = sub_8109028; +} + +static void sub_8109028(struct Sprite *sprite) +{ + if (++sprite->data[0] < sprite->data[4]) + { + sprite->pos2.x += sprite->data[2]; + sprite->pos2.y += sprite->data[3]; + } + + if (sprite->data[0] == sprite->data[1]) + DestroySpriteAndMatrix(sprite); +} + +static void sub_8109064(struct Sprite *sprite) +{ + SetSpriteCoordsToAnimAttackerCoords(sprite); + + if (GetBattlerSide(gBattleAnimAttacker)) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->subpriority = 8; + } + + 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->data[4] = gBattleAnimArgs[6]; + sprite->data[5] = 0; + + sprite->callback = sub_81090D8; +} + +static void sub_81090D8(struct Sprite *sprite) +{ + if (sprite->data[3]) + { + if(sprite->data[5] > 10000) + sprite->subpriority = 1; + + sprite->pos2.x = Sin(sprite->data[0], sprite->data[1] + (sprite->data[5] >> 8)); + sprite->pos2.y = Cos(sprite->data[0], sprite->data[1] + (sprite->data[5] >> 8)); + + sprite->data[0] += sprite->data[2]; + sprite->data[5] += sprite->data[4]; + + if (sprite->data[0] > 255) + sprite->data[0] -= 256; + else if (sprite->data[0] < 0) + sprite->data[0] += 256; + + sprite->data[3]--; + } + else + { + DestroySpriteAndMatrix(sprite); + } +} + +// Sunlight from Sunny Day / sunny weather +static void AnimSunlight(struct Sprite *sprite) +{ + sprite->pos1.x = 0; + sprite->pos1.y = 0; + sprite->data[0] = 60; + sprite->data[2] = 140; + sprite->data[4] = 80; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +//fire 2 + +// Animates the secondary effect of MOVE_EMBER, where the flames grow and slide +// horizontally a bit. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x pixel offset +// arg 3: target y pixel offset +// arg 4: duration +// arg 5: ? (todo: something related to which mon the pixel offsets are based on) +// arg 6: ? (todo: something related to which mon the pixel offsets are based on) +static void AnimEmberFlare(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) == GetBattlerSide(gBattleAnimTarget) + && (gBattleAnimAttacker == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT) + || gBattleAnimAttacker == GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT))) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + + sprite->callback = AnimTravelDiagonally; + sprite->callback(sprite); +} + +static void AnimBurnFlame(struct Sprite *sprite) +{ + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + + sprite->callback = AnimTravelDiagonally; +} + +// Animates the a fire sprite in the first-half of the MOVE_FIRE_BLAST +// animation. The fire sprite first moves in a circle around the mon, +// and then it is translated towards the target mon, while still rotating. +// Lastly, it moves in a circle around the target mon. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: initial wave offset +//void AnimFireRing(struct Sprite *sprite) +void AnimFireRing(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + + sprite->data[7] = gBattleAnimArgs[2]; + sprite->data[0] = 0; + + sprite->callback = AnimFireRing_Step1; +} + +static void AnimFireRing_Step1(struct Sprite *sprite) +{ + UpdateFireRingCircleOffset(sprite); + + if (++sprite->data[0] == 0x12) + { + sprite->data[0] = 0x19; + 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->callback = AnimFireRing_Step2; + } +} + +static void AnimFireRing_Step2(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + { + sprite->data[0] = 0; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->pos2.y = 0; + sprite->pos2.x = 0; + + sprite->callback = AnimFireRing_Step3; + sprite->callback(sprite); + } + else + { + sprite->pos2.x += Sin(sprite->data[7], 28); + sprite->pos2.y += Cos(sprite->data[7], 28); + + sprite->data[7] = (sprite->data[7] + 20) & 0xFF; + } +} + +static void AnimFireRing_Step3(struct Sprite *sprite) +{ + UpdateFireRingCircleOffset(sprite); + + if (++sprite->data[0] == 0x1F) + DestroyAnimSprite(sprite); +} + +static void UpdateFireRingCircleOffset(struct Sprite *sprite) +{ + sprite->pos2.x = Sin(sprite->data[7], 28); + sprite->pos2.y = Cos(sprite->data[7], 28); + + sprite->data[7] = (sprite->data[7] + 20) & 0xFF; +} + +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: duration +// arg 3: x delta +// arg 4: y delta +// AnimFireCross(struct Sprite *sprite) +static void AnimFireCross(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]; + + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + + sprite->callback = TranslateSpriteLinear; +} + +static void AnimFireSpiralOutward(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[3]; + + sprite->invisible = TRUE; + sprite->callback = WaitAnimForDuration; + + StoreSpriteCallbackInData6(sprite, AnimFireSpiralOutward_Step1); +} + +static void AnimFireSpiralOutward_Step1(struct Sprite *sprite) +{ + sprite->invisible = FALSE; + + sprite->data[0] = sprite->data[1]; + sprite->data[1] = 0; + + sprite->callback = AnimFireSpiralOutward_Step2; + sprite->callback(sprite); +} + +static void AnimFireSpiralOutward_Step2(struct Sprite *sprite) +{ + sprite->pos2.x = Sin(sprite->data[1], sprite->data[2] >> 8); + sprite->pos2.y = Cos(sprite->data[1], sprite->data[2] >> 8); + + sprite->data[1] = (sprite->data[1] + 10) & 0xFF; + sprite->data[2] += 0xD0; + + if (--sprite->data[0] == -1) + DestroyAnimSprite(sprite); +} + +// Animates first stage of Eruption where the attacker squishes and launches rocks away from themself +void AnimTask_EruptionLaunchRocks(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + + task->data[0] = 0; + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 0; + task->data[4] = gSprites[task->data[15]].pos1.y; + task->data[5] = GetBattlerSide(gBattleAnimAttacker); + task->data[6] = 0; + + PrepareBattlerSpriteForRotScale(task->data[15], ST_OAM_OBJ_NORMAL); + + task->func = AnimTask_EruptionLaunchRocks_Step; +} + +static void AnimTask_EruptionLaunchRocks_Step(u8 taskId) // animate Move_ERUPTION? +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + sub_80A805C(task, task->data[15], 0x100, 0x100, 0xE0, 0x200, 0x20); + + task->data[0]++; + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + + if (++task->data[2] & 0x1) + gSprites[task->data[15]].pos2.x = 3; + else + gSprites[task->data[15]].pos2.x = -3; + } + + if (task->data[5]) + { + if (++task->data[3] > 4) + { + task->data[3] = 0; + gSprites[task->data[15]].pos1.y++; + } + } + + if(!sub_80A80C8(task)) + { + SetBattlerSpriteYOffsetFromYScale(task->data[15]); + gSprites[task->data[15]].pos2.x = 0; + + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 0; + task->data[0]++; + } + break; + case 2: + if (++task->data[1] > 4) + { + if (task->data[5]) + sub_80A805C(task, task->data[15], 0xE0, 0x200, 0x180, 0xF0, 0x6); + else + sub_80A805C(task, task->data[15], 0xE0, 0x200, 0x180, 0xC0, 0x6); + + task->data[1] = 0; + task->data[0]++; + } + break; + case 3: + if (!sub_80A80C8(task)) + { + CreateEruptionLaunchRocks(task->data[15], taskId, 6); + + task->data[0]++; + } + break; + case 4: + if (++task->data[1] > 1) + { + task->data[1] = 0; + + if (++task->data[2] & 1) + gSprites[task->data[15]].pos2.y += 3; + else + gSprites[task->data[15]].pos2.y -= 3; + } + + if (++task->data[3] > 0x18) + { + if (task->data[5]) + sub_80A805C(task, task->data[15], 0x180, 0xF0, 0x100, 0x100, 0x8); + else + sub_80A805C(task, task->data[15], 0x180, 0xC0, 0x100, 0x100, 0x8); + + if (task->data[2] & 1) + gSprites[task->data[15]].pos2.y -= 3; + + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 0; + task->data[0]++; + } + break; + case 5: + if (task->data[5]) + gSprites[task->data[15]].pos1.y--; + + if (!sub_80A80C8(task)) + { + gSprites[task->data[15]].pos1.y = task->data[4]; + ResetSpriteRotScale(task->data[15]); + + task->data[2] = 0; + task->data[0]++; + } + break; + case 6: + if (!task->data[6]) + DestroyAnimVisualTask(taskId); + + break; + default: + break; + } +} + +static void CreateEruptionLaunchRocks(u8 spriteId, u8 taskId, u8 a3) +{ + u16 i, j; + s8 sign; + + u16 y = GetEruptionLaunchRockInitialYPos(spriteId); + u16 x = gSprites[spriteId].pos1.x; + + if(!GetBattlerSide(gBattleAnimAttacker)) + { + x -= 0xC; + sign = 1; + } + else + { + x += 0x10; + sign = -1; + } + + for (i = 0, j = 0; i <= 6; i++) + { + u8 spriteId = CreateSprite(&gEruptionLaunchRockSpriteTemplate, x, y, 2); + + if (spriteId != 0x40) + { + gSprites[spriteId].oam.tileNum += j * 4 + 0x40; + + if (++j >= 5) + j = 0; + + InitEruptionLaunchRockCoordData(&gSprites[spriteId], sEruptionLaunchRockCoords[i][0] * sign, sEruptionLaunchRockCoords[i][1]); + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = a3; + + gTasks[taskId].data[a3]++; + } + } +} + +static void AnimEruptionLaunchRock(struct Sprite *sprite) +{ + UpdateEruptionLaunchRockPos(sprite); + + if (sprite->invisible) + { + gTasks[sprite->data[6]].data[sprite->data[7]]--; + DestroySprite(sprite); + } +} + +static u16 GetEruptionLaunchRockInitialYPos(u8 spriteId) +{ + u16 y = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y + gSprites[spriteId].centerToCornerVecY; + + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + y = ((y << 16) + 0x4A0000) >> 16; + } + else + { + y = ((y << 16) + 0x2C0000) >> 16; + } + + return y; +} + +static void InitEruptionLaunchRockCoordData(struct Sprite *sprite, s16 x, s16 y) +{ + sprite->data[0] = 0; + sprite->data[1] = 0; + sprite->data[2] = (u16)sprite->pos1.x * 8; + sprite->data[3] = (u16)sprite->pos1.y * 8; + sprite->data[4] = x * 8; + sprite->data[5] = y * 8; +} + +static void UpdateEruptionLaunchRockPos(struct Sprite *sprite) +{ + int var1; + if (++sprite->data[0] > 2) + { + sprite->data[0] = 0; + ++sprite->data[1]; + var1 = (u16)sprite->data[1] * (u16)sprite->data[1]; + sprite->data[3] += var1; + } + + sprite->data[2] += sprite->data[4]; + sprite->pos1.x = sprite->data[2] >> 3; + sprite->data[3] += sprite->data[5]; + sprite->pos1.y = sprite->data[3] >> 3; + + if (sprite->pos1.x < -8 || sprite->pos1.x > 0xf8 || sprite->pos1.y < -8 || sprite->pos1.y > 120) + sprite->invisible = TRUE; +} + +static void AnimEruptionFallingRock(struct Sprite *sprite) +{ + sprite->pos1.x = gBattleAnimArgs[0]; + sprite->pos1.y = gBattleAnimArgs[1]; + + sprite->data[0] = 0; + sprite->data[1] = 0; + sprite->data[2] = 0; + sprite->data[6] = gBattleAnimArgs[2]; + sprite->data[7] = gBattleAnimArgs[3]; + + sprite->oam.tileNum += gBattleAnimArgs[4] * 16; + sprite->callback = AnimEruptionFallingRock_Step; +} + +static void AnimEruptionFallingRock_Step(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (sprite->data[6] != 0) + { + sprite->data[6]--; + return; + } + + sprite->data[0]++; + // fall through + case 1: + sprite->pos1.y += 8; + if (sprite->pos1.y >= sprite->data[7]) + { + sprite->pos1.y = sprite->data[7]; + sprite->data[0]++; + } + break; + case 2: + if (++sprite->data[1] > 1) + { + sprite->data[1] = 0; + if ((++sprite->data[2] & 1) != 0) + { + sprite->pos2.y = -3; + } + else + { + sprite->pos2.y = 3; + } + } + + if (++sprite->data[3] > 16) + { + DestroyAnimSprite(sprite); + } + break; + } +} + +static void AnimWillOWispOrb(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + InitSpritePosToAnimAttacker(sprite, 0); + StartSpriteAnim(sprite, gBattleAnimArgs[2]); + sprite->data[7] = gBattleAnimArgs[2]; + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->data[4] = 4; + } + else + { + sprite->data[4] = -4; + } + + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + sprite->data[0]++; + break; + case 1: + sprite->data[1] += 192; + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos2.y = -(sprite->data[1] >> 8); + } + else + { + sprite->pos2.y = sprite->data[1] >> 8; + } + + sprite->pos2.x = Sin(sprite->data[2], sprite->data[4]); + sprite->data[2] = (sprite->data[2] + 4) & 0xFF; + + if (++sprite->data[3] == 1) + { + sprite->data[3] = 0; + sprite->data[0]++; + } + break; + case 2: + sprite->pos2.x = Sin(sprite->data[2], sprite->data[4]); + sprite->data[2] = (sprite->data[2] + 4) & 0xFF; + + if (++sprite->data[3] == 31) + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + + sprite->data[0] = 256; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + + sub_80A6FD4(sprite); + sprite->callback = AnimWillOWispOrb_Step; + } + break; + } +} + +static void AnimWillOWispOrb_Step(struct Sprite *sprite) +{ + s16 initialData5; + s16 newData5; + + if (!AnimTranslateLinear(sprite)) + { + sprite->pos2.x += Sin(sprite->data[5], 16); + initialData5 = sprite->data[5]; + sprite->data[5] = (sprite->data[5] + 4) & 0xFF; + newData5 = sprite->data[5]; + + if ((initialData5 == 0 || initialData5 > 196) && newData5 > 0 && sprite->data[7] == 0) + { + PlaySE12WithPanning(SE_W172, gAnimCustomPanning); + } + } + else + { + DestroyAnimSprite(sprite); + } +} + +static void AnimWillOWispFire(struct Sprite *sprite) +{ + if (!sprite->data[0]) + { + sprite->data[1] = gBattleAnimArgs[0]; + sprite->data[0] += 1; + } + + sprite->data[3] += 0xC0 * 2; + sprite->data[4] += 0xA0; + + sprite->pos2.x = Sin(sprite->data[1], sprite->data[3] >> 8); + sprite->pos2.y = Cos(sprite->data[1], sprite->data[4] >> 8); + + sprite->data[1] = (sprite->data[1] + 7) & 0xFF; + + if (!IsContest()) + { + if (sprite->data[1] < 64 || sprite->data[1] > 195) + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + else + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget) + 1; + } + else + { + if (sprite->data[1] < 64 || sprite->data[1] > 195) + sprite->subpriority = 0x1D; + else + sprite->subpriority = 0x1F; + } + + if (++sprite->data[2] > 0x14) + sprite->invisible ^= 1; + + if (sprite->data[2] == 0x1E) + DestroyAnimSprite(sprite); +} + +void AnimTask_MoveHeatWaveTargets(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[12] = !GetBattlerSide(gBattleAnimAttacker) ? 1 : -1; + task->data[13] = IsBattlerSpriteVisible(gBattleAnimTarget ^ 2) + 1; + task->data[14] = GetAnimBattlerSpriteId(ANIM_TARGET); + task->data[15] = GetAnimBattlerSpriteId(ANIM_DEF_PARTNER); + + task->func = AnimTask_MoveHeatWaveTargets_Step; +} + +static void AnimTask_MoveHeatWaveTargets_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[10] += task->data[12] * 2; + if (++task->data[1] >= 2) + { + task->data[1] = 0; + task->data[2]++; + if (task->data[2] & 1) + task->data[11] = 2; + else + task->data[11] = -2; + } + + for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) + { + gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; + } + + if (++task->data[9] == 16) + { + task->data[9] = 0; + task->data[0]++; + } + break; + case 1: + if (++task->data[1] >= 5) + { + task->data[1] = 0; + task->data[2]++; + + if (task->data[2] & 1) + task->data[11] = 2; + else + task->data[11] = -2; + } + + for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) + { + gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; + } + + if (++task->data[9] == 96) + { + task->data[9] = 0; + task->data[0]++; + } + break; + case 2: + task->data[10] -= task->data[12] * 2; + + if (++task->data[1] >= 2) + { + task->data[1] = 0; + task->data[2]++; + + if (task->data[2] & 1) + task->data[11] = 2; + else + task->data[11] = -2; + } + + for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) + { + gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; + } + + if (++task->data[9] == 16) + { + task->data[0]++; + } + break; + case 3: + for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) + { + gSprites[task->data[task->data[3] + 14]].pos2.x = 0; + } + + DestroyAnimVisualTask(taskId); + break; + } +} + +// Used to add a color mask to the battle interface / HUD in Heat Wave. +// arg 0: opacity +// arg 1: color code +void AnimTask_BlendBackground(u8 taskId) +{ + struct BattleAnimBgData animBg; + sub_80A6B30(&animBg); + BlendPalette(animBg.paletteId * 16, 16, gBattleAnimArgs[0], gBattleAnimArgs[1]); // u16 palOffset, u16 numEntries, u8 coeff, u16 blendColor + DestroyAnimVisualTask(taskId); +} + +#define tShakeNum data[0] +#define tMaxShakes data[1] +#define tShakeOffset data[2] // Never read, gBattleAnimArgs[1] is used directly instead +#define tVertical data[3] +#define tPatternId data[4] + +// Shakes target horizontally or vertically tMaxShakes times, following a set pattern of alternations +void AnimTask_ShakeTargetInPattern(u8 taskId) +{ + s8 dir; + u8 spriteId; + + if (gTasks[taskId].tShakeNum == 0) + { + gTasks[taskId].tMaxShakes = gBattleAnimArgs[0]; + gTasks[taskId].tShakeOffset = gBattleAnimArgs[1]; + gTasks[taskId].tVertical = gBattleAnimArgs[2]; + gTasks[taskId].tPatternId = gBattleAnimArgs[3]; + } + gTasks[taskId].tShakeNum++; + + spriteId = gBattlerSpriteIds[gBattleAnimTarget]; + + if (gTasks[taskId].tPatternId == 0) + dir = sShakeDirsPattern0[gTasks[taskId].tShakeNum % 10]; + else + dir = sShakeDirsPattern1[gTasks[taskId].tShakeNum % 10]; + + if (gTasks[taskId].tVertical == TRUE) + gSprites[spriteId].pos2.y = gBattleAnimArgs[1] * dir < 0 ? -(gBattleAnimArgs[1] * dir) : gBattleAnimArgs[1] * dir; + else + gSprites[spriteId].pos2.x = gBattleAnimArgs[1] * dir; + + if (gTasks[taskId].tShakeNum == gTasks[taskId].tMaxShakes) + { + gSprites[spriteId].pos2.x = 0; + gSprites[spriteId].pos2.y = 0; + DestroyAnimVisualTask(taskId); + } +} diff --git a/src/battle_anim_flying.c b/src/battle_anim_flying.c new file mode 100644 index 000000000..5179c1364 --- /dev/null +++ b/src/battle_anim_flying.c @@ -0,0 +1,1248 @@ +#include "global.h" +#include "battle_anim.h" +#include "palette.h" +#include "trig.h" +#include "constants/battle_anim.h" +#include "constants/rgb.h" +#include "random.h" + +extern const struct SpriteTemplate gFlashingHitSplatSpriteTemplate; + +static void AnimEllipticalGust(struct Sprite *); +static void AnimEllipticalGust_Step(struct Sprite *); +static void AnimGustToTarget(struct Sprite *); +static void AnimGustToTarget_Step(struct Sprite *); +static void AnimAirWaveCrescent(struct Sprite *); +static void AnimFlyBallUp(struct Sprite *); +static void AnimFlyBallUp_Step(struct Sprite *); +static void AnimFlyBallAttack(struct Sprite *); +static void AnimFlyBallAttack_Step(struct Sprite *); +static void AnimFallingFeather(struct Sprite *); +static void sub_810E520(struct Sprite *); +static void sub_810EB40(struct Sprite *); +static void sub_810EA4C(struct Sprite *); +static void AnimWhirlwindLine(struct Sprite *); +static void AnimBounceBallShrink(struct Sprite *); +static void AnimBounceBallLand(struct Sprite *); +static void AnimDiveBall(struct Sprite *); +static void AnimDiveBall_Step1(struct Sprite *); +static void AnimDiveBall_Step2(struct Sprite *); +static void AnimDiveWaterSplash(struct Sprite *); +static void AnimSprayWaterDroplet(struct Sprite *); +static void AnimSprayWaterDroplet_Step(struct Sprite *); +static void sub_810F004(struct Sprite *); +static void sub_810F018(struct Sprite *); +static void AnimSkyAttackBird(struct Sprite *); +static void AnimSkyAttackBird_Step(struct Sprite *); +static void AnimTask_AnimateGustTornadoPalette_Step(u8); + + +const struct SpriteTemplate gEllipticalGustSpriteTemplate = +{ + .tileTag = ANIM_TAG_GUST, + .paletteTag = ANIM_TAG_GUST, + .oam = &gOamData_AffineOff_ObjNormal_32x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimEllipticalGust, +}; + +static const union AffineAnimCmd sAffineAnim_GustToTarget[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0xA, 0x0, 0, 24), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_GustToTarget[] = +{ + sAffineAnim_GustToTarget, +}; + +const struct SpriteTemplate gGustToTargetSpriteTemplate = +{ + .tileTag = ANIM_TAG_GUST, + .paletteTag = ANIM_TAG_GUST, + .oam = &gOamData_AffineNormal_ObjNormal_32x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_GustToTarget, + .callback = AnimGustToTarget, +}; + +static const union AnimCmd sAffineAnim_AirWaveCrescent[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_FRAME(0, 3, .hFlip = TRUE), + ANIMCMD_FRAME(0, 3, .vFlip = TRUE), + ANIMCMD_FRAME(0, 3, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAffineAnims_AirWaveCrescent[] = +{ + sAffineAnim_AirWaveCrescent, +}; + +const struct SpriteTemplate gAirWaveCrescentSpriteTemplate = +{ + .tileTag = ANIM_TAG_AIR_WAVE_2, + .paletteTag = ANIM_TAG_AIR_WAVE_2, + .oam = &gOamData_AffineOff_ObjNormal_32x16, + .anims = sAffineAnims_AirWaveCrescent, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimAirWaveCrescent, +}; + +static const union AffineAnimCmd sAffineAnim_FlyBallUp[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), + AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), + AFFINEANIMCMD_FRAME(0xFFF0, 0x20, 0, 10), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_FlyBallUp[] = +{ + sAffineAnim_FlyBallUp, +}; + +static const union AffineAnimCmd sAffineAnim_FlyBallAttack_0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 50, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_FlyBallAttack_1[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -40, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_FlyBallAttack[] = +{ + sAffineAnim_FlyBallAttack_0, + sAffineAnim_FlyBallAttack_1, +}; + +const struct SpriteTemplate gFlyBallUpSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_FlyBallUp, + .callback = AnimFlyBallUp, +}; + +const struct SpriteTemplate gFlyBallAttackSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_AffineNormal_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_FlyBallAttack, + .callback = AnimFlyBallAttack, +}; + +static const union AnimCmd sAnim_FallingFeather_0[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_FallingFeather_1[] = +{ + ANIMCMD_FRAME(16, 0, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_FallingFeather[] = +{ + sAnim_FallingFeather_0, + sAnim_FallingFeather_1, +}; + +const struct SpriteTemplate gFallingFeatherSpriteTemplate = +{ + .tileTag = ANIM_TAG_WHITE_FEATHER, + .paletteTag = ANIM_TAG_WHITE_FEATHER, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = sAnims_FallingFeather, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFallingFeather, +}; + +const struct SpriteTemplate gUnknown_085963A0 = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810EA4C, +}; + +static const union AnimCmd sAnim_WhirlwindLines[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_FRAME(8, 1), + ANIMCMD_FRAME(16, 1), + ANIMCMD_FRAME(8, 1, .hFlip = TRUE), + ANIMCMD_FRAME(0, 1, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_WhirlwindLines[] = +{ + sAnim_WhirlwindLines, +}; + +const struct SpriteTemplate gWhirlwindLineSpriteTemplate = +{ + .tileTag = ANIM_TAG_WHIRLWIND_LINES, + .paletteTag = ANIM_TAG_WHIRLWIND_LINES, + .oam = &gOamData_AffineOff_ObjNormal_32x16, + .anims = sAnims_WhirlwindLines, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWhirlwindLine, +}; + +static const union AffineAnimCmd sAffineAnim_BounceBallShrink[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), + AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), + AFFINEANIMCMD_FRAME(0xFFEC, 0x0, 0, 7), + AFFINEANIMCMD_FRAME(0xFFEC, 0xFFEC, 0, 5), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_BounceBallShrink[] = +{ + sAffineAnim_BounceBallShrink, +}; + +const struct SpriteTemplate gBounceBallShrinkSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_BounceBallShrink, + .callback = AnimBounceBallShrink, +}; + +static const union AffineAnimCmd sAffineAnim_BounceBallLand[] = +{ + AFFINEANIMCMD_FRAME(0xA0, 0x100, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_BounceBallLand[] = +{ + sAffineAnim_BounceBallLand, +}; + +const struct SpriteTemplate gBounceBallLandSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_BounceBallLand, + .callback = AnimBounceBallLand, +}; + +static const union AffineAnimCmd sAffineAnim_DiveBall[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), + AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), + AFFINEANIMCMD_FRAME(0xFFF0, 0x20, 0, 10), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_DiveBall[] = +{ + sAffineAnim_DiveBall, +}; + +const struct SpriteTemplate gDiveBallSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_DiveBall, + .callback = AnimDiveBall, +}; + +static const union AffineAnimCmd gUnknown_085964A8[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x0, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x20, 0, 12), + AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 11), + AFFINEANIMCMD_END, +}; + +// Unused +static const union AffineAnimCmd *const gUnknown_085964C8[] = +{ + gUnknown_085964A8, +}; + +const struct SpriteTemplate gDiveWaterSplashSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPLASH, + .paletteTag = ANIM_TAG_SPLASH, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDiveWaterSplash, +}; + +const struct SpriteTemplate gSprayWaterDropletSpriteTemplate = +{ + .tileTag = ANIM_TAG_SWEAT_BEAD, + .paletteTag = ANIM_TAG_SWEAT_BEAD, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSprayWaterDroplet, +}; + +const struct SpriteTemplate gUnknown_085964FC = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineOff_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810F004, +}; + +const struct SpriteTemplate gSkyAttackBirdSpriteTemplate = +{ + .tileTag = ANIM_TAG_BIRD, + .paletteTag = ANIM_TAG_BIRD, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSkyAttackBird, +}; + + +static void AnimEllipticalGust(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, FALSE); + sprite->pos1.y += 20; + sprite->data[1] = 191; + sprite->callback = AnimEllipticalGust_Step; + sprite->callback(sprite); +} + +static void AnimEllipticalGust_Step(struct Sprite *sprite) +{ + sprite->pos2.x = Sin(sprite->data[1], 32); + sprite->pos2.y = Cos(sprite->data[1], 8); + sprite->data[1] += 5; + sprite->data[1] &= 0xFF; + if (++sprite->data[0] == 71) + DestroyAnimSprite(sprite); +} + +// Animates the palette on the gust tornado to make it look like its spinning +void AnimTask_AnimateGustTornadoPalette(u8 taskId) +{ + gTasks[taskId].data[0] = gBattleAnimArgs[1]; + gTasks[taskId].data[1] = gBattleAnimArgs[0]; + gTasks[taskId].data[2] = IndexOfSpritePaletteTag(ANIM_TAG_GUST); + gTasks[taskId].func = AnimTask_AnimateGustTornadoPalette_Step; +} + +static void AnimTask_AnimateGustTornadoPalette_Step(u8 taskId) +{ + u8 data2; + u16 temp; + int i, base; + + if (gTasks[taskId].data[10]++ == gTasks[taskId].data[1]) + { + gTasks[taskId].data[10] = 0; + data2 = gTasks[taskId].data[2]; + temp = gPlttBufferFaded[16 * data2 + 0x108]; + i = 7; + base = data2 * 16; + + do + { + gPlttBufferFaded[base + 0x101 + i] = gPlttBufferFaded[base + 0x100 + i]; + i--; + } while (i > 0); + + gPlttBufferFaded[base + 0x101] = temp; + } + + if (--gTasks[taskId].data[0] == 0) + DestroyAnimVisualTask(taskId); +} + +static void AnimGustToTarget(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, TRUE); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; + InitAnimLinearTranslation(sprite); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; + StoreSpriteCallbackInData6(sprite, AnimGustToTarget_Step); +} + +static void AnimGustToTarget_Step(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + DestroyAnimSprite(sprite); +} + +static void AnimAirWaveCrescent(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + } + + if (IsContest()) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + } + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[4]; + + if (gBattleAnimArgs[6] == 0) + { + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); + } + + sprite->data[2] = sprite->data[2] + gBattleAnimArgs[2]; + sprite->data[4] = sprite->data[4] + gBattleAnimArgs[3]; + sprite->callback = StartAnimLinearTranslation; + + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + SeekSpriteAnim(sprite, gBattleAnimArgs[5]); +} + +static void AnimFlyBallUp(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->callback = AnimFlyBallUp_Step; + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; +} + +static void AnimFlyBallUp_Step(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + { + sprite->data[0]--; + } + else + { + sprite->data[2] += sprite->data[1]; + sprite->pos2.y -= (sprite->data[2] >> 8); + } + + if (sprite->pos1.y + sprite->pos2.y < -32) + DestroyAnimSprite(sprite); +} + +static void AnimFlyBallAttack(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x = 272; + sprite->pos1.y = -32; + StartSpriteAffineAnim(sprite, 1); + } + else + { + sprite->pos1.x = -32; + sprite->pos1.y = -32; + } + + sprite->data[0] = gBattleAnimArgs[0]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + + InitAnimLinearTranslation(sprite); + sprite->callback = AnimFlyBallAttack_Step; +} + +static void AnimFlyBallAttack_Step(struct Sprite *sprite) +{ + sprite->data[0] = 1; + AnimTranslateLinear(sprite); + if (((u16)sprite->data[3] >> 8) > 200) + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos2.x = 0; + sprite->data[3] &= 0xFF; + } + + if (sprite->pos1.x + sprite->pos2.x < -32 + || sprite->pos1.x + sprite->pos2.x > 272 + || sprite->pos1.y + sprite->pos2.y > 160) + { + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = FALSE; + DestroyAnimSprite(sprite); + } +} + +void DestroyAnimSpriteAfterTimer(struct Sprite *sprite) +{ + if (sprite->data[0]-- <= 0) + { + if (sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK) + { + FreeOamMatrix(sprite->oam.matrixNum); + sprite->oam.affineMode = ST_OAM_AFFINE_OFF; + } + + DestroySprite(sprite); + gAnimVisualTaskCount--; + } +} + +struct FeatherDanceData +{ + u16 unk0_0a:1; + u16 unk0_0b:1; + u16 unk0_0c:1; + u16 unk0_0d:1; + u16 unk0_1:4; + u16 unk1:8; + u16 unk2; + s16 unk4; + u16 unk6; + u16 unk8; + u16 unkA; + u8 unkC[2]; + u16 unkE_0:1; + u16 unkE_1:15; +}; + +static void AnimFallingFeather(struct Sprite *sprite) +{ + u8 battler, matrixNum, sinIndex; + s16 spriteCoord, sinVal; + + struct FeatherDanceData *data = (struct FeatherDanceData *)sprite->data; + + if (gBattleAnimArgs[7] & 0x100) + battler = gBattleAnimAttacker; + else + battler = gBattleAnimTarget; + + if (GetBattlerSide(battler) == B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + + sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_ATTR_HEIGHT) + gBattleAnimArgs[0]; + spriteCoord = GetBattlerSpriteCoord(battler, BATTLER_COORD_ATTR_WIDTH); + sprite->pos1.y = spriteCoord + gBattleAnimArgs[1]; + + data->unk8 = sprite->pos1.y << 8; + data->unkE_1 = spriteCoord + gBattleAnimArgs[6]; + data->unk0_0c = 1; + data->unk2 = gBattleAnimArgs[2] & 0xFF; + data->unkA = (gBattleAnimArgs[2] >> 8) & 0xFF; + data->unk4 = gBattleAnimArgs[3]; + data->unk6 = gBattleAnimArgs[4]; + *(u16*)(data->unkC) = gBattleAnimArgs[5]; + + if (data->unk2 >= 64 && data->unk2 <= 191) + { + if (!IsContest()) + sprite->oam.priority = GetBattlerSpriteBGPriority(battler) + 1; + else + sprite->oam.priority = GetBattlerSpriteBGPriority(battler); + + data->unkE_0 = 0; + + if (!(data->unk4 & 0x8000)) + { + sprite->hFlip ^= 1; + sprite->animNum = sprite->hFlip; + + sprite->animBeginning = 1; + sprite->animEnded = 0; + } + } + else + { + sprite->oam.priority = GetBattlerSpriteBGPriority(battler); + data->unkE_0 = 1; + + if (data->unk4 & 0x8000) + { + sprite->hFlip ^= 1; + sprite->animNum = sprite->hFlip; + + sprite->animBeginning = 1; + sprite->animEnded = 0; + } + } + + data->unk0_1 = data->unk2 >> 6; + sprite->pos2.x = (gSineTable[data->unk2] * data->unkC[0]) >> 8; + matrixNum = sprite->oam.matrixNum; + + sinIndex = (-sprite->pos2.x >> 1) + data->unkA; + sinVal = gSineTable[sinIndex]; + + gOamMatrices[matrixNum].a = gOamMatrices[matrixNum].d = gSineTable[sinIndex + 64]; + // The comparison below is completely pointless. 'sprite' is sure to be a valid pointer and + // both the 'if' and 'else' parts are exactly the same. + // The only reason for this is making sure the compiler generates the exact ASM. + if (sprite) + { + gOamMatrices[matrixNum].b = sinVal; + gOamMatrices[matrixNum].c = -sinVal; + } + else + { + gOamMatrices[matrixNum].b = sinVal; + gOamMatrices[matrixNum].c = -sinVal; + } + + sprite->callback = sub_810E520; +} + +static void sub_810E520(struct Sprite *sprite) +{ + u8 matrixNum, sinIndex; + s16 sinVal = 0; + struct FeatherDanceData *data = (struct FeatherDanceData *)sprite->data; + if (data->unk0_0a) + { + if (data->unk1-- % 256 == 0) + { + data->unk0_0a = 0; + data->unk1 = 0; + } + } + else + { + switch (data->unk2 / 64) + { + case 0: + if (data->unk0_1 << 24 >> 24 == 1) // the shifts have to be here + { + data->unk0_0d = 1; + data->unk0_0a = 1; + data->unk1 = 0; + } + else if (data->unk0_1 << 24 >> 24 == 3) + { + data->unk0_0b ^= 1; + data->unk0_0a = 1; + data->unk1 = 0; + } + else if (data->unk0_0d) + { + sprite->hFlip ^= 1; + sprite->animNum = sprite->hFlip; + sprite->animBeginning = TRUE; + sprite->animEnded = FALSE; + if (data->unk0_0c) + { + if (!IsContest()) + { + if (!data->unkE_0) + { + sprite->oam.priority--; + data->unkE_0 ^= 1; + } + else + { + sprite->oam.priority++; + data->unkE_0 ^= 1; + } + } + else + { + if (!data->unkE_0) + { + sprite->subpriority -= 12; + data->unkE_0 ^= 1; + } + else + { + sprite->subpriority += 12; + data->unkE_0 ^= 1; + } + } + } + data->unk0_0d = 0; + data->unk2; + } + data->unk0_1 = 0; + break; + case 1: + if (data->unk0_1 << 24 >> 24 == 0) + { + data->unk0_0d = 1; + data->unk0_0a = 1; + data->unk1 = 0; + } + else if (data->unk0_1 << 24 >> 24 == 2) + { + data->unk0_0a = 1; + data->unk1 = 0; + } + else if (data->unk0_0d) + { + sprite->hFlip ^= 1; + sprite->animNum = sprite->hFlip; + sprite->animBeginning = TRUE; + sprite->animEnded = FALSE; + if (data->unk0_0c) + { + if (!IsContest()) + { + if (!data->unkE_0) + { + sprite->oam.priority--; + data->unkE_0 ^= 1; + } + else + { + sprite->oam.priority++; + data->unkE_0 ^= 1; + } + } + else + { + if (!data->unkE_0) + { + sprite->subpriority -= 12; + data->unkE_0 ^= 1; + } + else + { + sprite->subpriority += 12; + data->unkE_0 ^= 1; + } + } + } + data->unk0_0d = 0; + } + data->unk0_1 = 1; + break; + case 2: + if (data->unk0_1 << 24 >> 24 == 3) + { + data->unk0_0d = 1; + data->unk0_0a = 1; + data->unk1 = 0; + } + else if (data->unk0_1 << 24 >> 24 == 1) + { + data->unk0_0a = 1; + data->unk1 = 0; + } + else if (data->unk0_0d) + { + sprite->hFlip ^= 1; + sprite->animNum = sprite->hFlip; + sprite->animBeginning = TRUE; + sprite->animEnded = FALSE; + if (data->unk0_0c) + { + if (!IsContest()) + { + if (!data->unkE_0) + { + sprite->oam.priority--; + data->unkE_0 ^= 1; + } + else + { + sprite->oam.priority++; + data->unkE_0 ^= 1; + } + } + else + { + if (!data->unkE_0) + { + sprite->subpriority -= 12; + data->unkE_0 ^= 1; + } + else + { + sprite->subpriority += 12; + data->unkE_0 ^= 1; + } + } + } + data->unk0_0d = 0; + } + data->unk0_1 = 2; + break; + case 3: + if (data->unk0_1 << 24 >> 24 == 2) + { + data->unk0_0d = 1; + } + else if (data->unk0_1 << 24 >> 24 == 0) + { + data->unk0_0b ^= 1; + data->unk0_0a = 1; + data->unk1 = 0; + } + else if (data->unk0_0d) + { + sprite->hFlip ^= 1; + sprite->animNum = sprite->hFlip; + sprite->animBeginning = TRUE; + sprite->animEnded = FALSE; + if (data->unk0_0c) + { + if (!IsContest()) + { + if (!data->unkE_0) + { + sprite->oam.priority--; + data->unkE_0 ^= 1; + } + else + { + sprite->oam.priority++; + data->unkE_0 ^= 1; + } + } + else + { + if (!data->unkE_0) + { + sprite->subpriority -= 12; + data->unkE_0 ^= 1; + } + else + { + sprite->subpriority += 12; + data->unkE_0 ^= 1; + } + } + } + data->unk0_0d = 0; + } + data->unk0_1 = 3; + break; + } + #ifndef NONMATCHING + asm("":::"r8"); + #endif + sprite->pos2.x = (data->unkC[data->unk0_0b] * gSineTable[data->unk2]) >> 8; + matrixNum = sprite->oam.matrixNum; + + sinIndex = (-sprite->pos2.x >> 1) + data->unkA; + sinVal = gSineTable[sinIndex]; + + gOamMatrices[matrixNum].a = gOamMatrices[matrixNum].d = gSineTable[sinIndex + 64]; + gOamMatrices[matrixNum].b = sinVal; + gOamMatrices[matrixNum].c = -sinVal; + + data->unk8 += data->unk6; + sprite->pos1.y = data->unk8 >> 8; + if (data->unk4 & 0x8000) + data->unk2 = (data->unk2 - (data->unk4 & 0x7FFF)) & 0xFF; + else + data->unk2 = (data->unk2 + (data->unk4 & 0x7FFF)) & 0xFF; + + if (sprite->pos1.y + sprite->pos2.y >= data->unkE_1) + { + sprite->data[0] = 0; + sprite->callback = DestroyAnimSpriteAfterTimer; + } + } +} + +static void sub_810EA4C(struct Sprite *sprite) +{ + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + sprite->callback = TranslateAnimSpriteToTargetMonLocation; +} + +static void AnimWhirlwindLine(struct Sprite * sprite) +{ + u16 arg; + u8 mult; + + if (gBattleAnimArgs[2] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, 0); + else + InitSpritePosToAnimTarget(sprite, FALSE); + + if ((gBattleAnimArgs[2] == ANIM_ATTACKER && !GetBattlerSide(gBattleAnimAttacker)) + || (gBattleAnimArgs[2] == ANIM_TARGET && !GetBattlerSide(gBattleAnimTarget))) + { + sprite->pos1.x += 8; + } + + SeekSpriteAnim(sprite, gBattleAnimArgs[4]); + sprite->pos1.x -= 32; + sprite->data[1] = 0x0ccc; + + arg = gBattleAnimArgs[4]; + mult = 12; + sprite->pos2.x += mult * arg; + sprite->data[0] = arg; + sprite->data[7] = gBattleAnimArgs[3]; + sprite->callback = sub_810EB40; +} + +static void sub_810EB40(struct Sprite *sprite) +{ + sprite->pos2.x += sprite->data[1] >> 8; + + if (++sprite->data[0] == 6) + { + sprite->data[0] = 0; + sprite->pos2.x = 0; + StartSpriteAnim(sprite, 0); + } + + if (--sprite->data[7] == -1) + DestroyAnimSprite(sprite); +} + +void AnimTask_DrillPeckHitSplats(u8 task) +{ + if (!(gTasks[task].data[0] % 32)) + { + gAnimVisualTaskCount++; + + gBattleAnimArgs[0] = Sin(gTasks[task].data[0], -13); + gBattleAnimArgs[1] = Cos(gTasks[task].data[0], -13); + gBattleAnimArgs[2] = 1; + gBattleAnimArgs[3] = 3; + + CreateSpriteAndAnimate(&gFlashingHitSplatSpriteTemplate, + GetBattlerSpriteCoord(gBattleAnimTarget, 2), + GetBattlerSpriteCoord(gBattleAnimTarget, 3), + 3); + } + + gTasks[task].data[0] += 8; + + if (gTasks[task].data[0] > 255) + DestroyAnimVisualTask(task); +} + +static void AnimBounceBallShrink(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + InitSpritePosToAnimAttacker(sprite, 1); + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; + ++sprite->data[0]; + break; + case 1: + if (sprite->affineAnimEnded) + DestroyAnimSprite(sprite); + break; + } +} + +static void AnimBounceBallLand(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); + sprite->pos2.y = -sprite->pos1.y - 32; + sprite->data[0]++; + break; + case 1: + sprite->pos2.y += 10; + if (sprite->pos2.y >= 0) + ++sprite->data[0]; + break; + case 2: + sprite->pos2.y -= 10; + if (sprite->pos1.y + sprite->pos2.y < -32) + { + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = FALSE; + DestroyAnimSprite(sprite); + } + break; + } +} + +static void AnimDiveBall(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->callback = AnimDiveBall_Step1; + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; +} + +void AnimDiveBall_Step1(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + { + sprite->data[0]--; + } + else if (sprite->pos1.y + sprite->pos2.y > -32) + { + sprite->data[2] += sprite->data[1]; + sprite->pos2.y -= (sprite->data[2] >> 8); + } + else + { + sprite->invisible = TRUE; + if (sprite->data[3]++ > 20) + sprite->callback = AnimDiveBall_Step2; + } +} + +static void AnimDiveBall_Step2(struct Sprite *sprite) +{ + sprite->pos2.y += sprite->data[2] >> 8; + + if (sprite->pos1.y + sprite->pos2.y > -32) + sprite->invisible = FALSE; + + if (sprite->pos2.y > 0) + DestroyAnimSprite(sprite); +} + +static void AnimDiveWaterSplash(struct Sprite *sprite) +{ + u32 matrixNum; + int t1, t2; + + switch (sprite->data[0]) + { + case 0: + if (!gBattleAnimArgs[0]) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); + } + + sprite->data[1] = 512; + + TrySetSpriteRotScale(sprite, 0, 256, sprite->data[1], 0); + sprite->data[0]++; + break; + case 1: + if (sprite->data[2] <= 11) + sprite->data[1] -= 40; + else + sprite->data[1] += 40; + + sprite->data[2]++; + + TrySetSpriteRotScale(sprite, 0, 256, sprite->data[1], 0); + + matrixNum = sprite->oam.matrixNum; + + t1 = 15616; + t2 = t1 / gOamMatrices[matrixNum].d + 1; + + if (t2 > 128) + t2 = 128; + + t2 = (64 - t2) / 2; + sprite->pos2.y = t2; + + if (sprite->data[2] == 24) + { + sub_80A749C(sprite); + DestroyAnimSprite(sprite); + } + break; + } +} + +// Launches a water droplet away from the specified battler. Used by Astonish and Dive +static void AnimSprayWaterDroplet(struct Sprite *sprite) +{ + int v1 = 0x1ff & Random2(); + int v2 = 0x7f & Random2(); + + if (v1 % 2) + sprite->data[0] = 736 + v1; + else + sprite->data[0] = 736 - v1; + + if (v2 % 2) + sprite->data[1] = 896 + v2; + else + sprite->data[1] = 896 - v2; + + sprite->data[2] = gBattleAnimArgs[0]; + + if (sprite->data[2]) + sprite->oam.matrixNum = ST_OAM_HFLIP; + + if (gBattleAnimArgs[1] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 32; + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 32; + } + + sprite->callback = AnimSprayWaterDroplet_Step; +} + +static void AnimSprayWaterDroplet_Step(struct Sprite *sprite) +{ + if (sprite->data[2] == 0) + { + sprite->pos2.x += sprite->data[0] >> 8; + sprite->pos2.y -= sprite->data[1] >> 8; + } + else + { + sprite->pos2.x -= sprite->data[0] >> 8; + sprite->pos2.y -= sprite->data[1] >> 8; + } + + sprite->data[0] = sprite->data[0]; + sprite->data[1] -= 32; + + if (sprite->data[0] < 0) + sprite->data[0] = 0; + + if (++sprite->data[3] == 31) + DestroyAnimSprite(sprite); +} + +static void sub_810F004(struct Sprite *sprite) +{ + sprite->data[6] = 0; + sprite->data[7] = 64; + sprite->callback = sub_810F018; +} + +static void sub_810F018(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (++sprite->data[1] > 8) + { + sprite->data[1] = 0; + sprite->invisible ^= 1; + if (++sprite->data[2] > 5 && sprite->invisible) + sprite->data[0]++; + } + break; + case 1: + DestroyAnimSprite(sprite); + break; + } +} + +static void AnimSkyAttackBird(struct Sprite *sprite) +{ + u16 rotation; + s16 posx = sprite->pos1.x; + s16 posy = sprite->pos1.y; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + + sprite->data[4] = sprite->pos1.x << 4; + sprite->data[5] = sprite->pos1.y << 4; + + sprite->data[6] = ((posx - sprite->pos1.x) << 4) / 12; + sprite->data[7] = ((posy - sprite->pos1.y) << 4) / 12; + + rotation = ArcTan2Neg(posx - sprite->pos1.x, posy - sprite->pos1.y); + rotation += 49152; + + TrySetSpriteRotScale(sprite, 1, 0x100, 0x100, rotation); + + sprite->callback = AnimSkyAttackBird_Step; +} + +void AnimSkyAttackBird_Step(struct Sprite *sprite) +{ + sprite->data[4] += sprite->data[6]; + sprite->data[5] += sprite->data[7]; + + sprite->pos1.x = sprite->data[4] >> 4; + sprite->pos1.y = sprite->data[5] >> 4; + + if (sprite->pos1.x > 285 || sprite->pos1.x < -45 + || sprite->pos1.y > 157 || sprite->pos1.y < -45) + DestroySpriteAndMatrix(sprite); +} + +void unref_sub_810F184(u8 taskId) +{ + if (gBattleAnimArgs[0] == 0) + { + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + gSprites[spriteId].invisible = TRUE; + } + else + { + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + gSprites[spriteId].invisible = FALSE; + } + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_anim_ghost.c b/src/battle_anim_ghost.c new file mode 100644 index 000000000..b8de6b0e1 --- /dev/null +++ b/src/battle_anim_ghost.c @@ -0,0 +1,1341 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "palette.h" +#include "constants/rgb.h" +#include "scanline_effect.h" +#include "constants/songs.h" +#include "sound.h" +#include "trig.h" +#include "util.h" + +static void AnimConfuseRayBallBounce(struct Sprite *); +static void AnimConfuseRayBallBounce_Step1(struct Sprite *); +static void AnimConfuseRayBallBounce_Step2(struct Sprite *); +static void sub_8111764(struct Sprite *); +static void AnimConfuseRayBallSpiral(struct Sprite *); +static void AnimConfuseRayBallSpiral_Step(struct Sprite *); +static void AnimTask_NightShadeClone_Step1(u8 taskId); +static void AnimTask_NightShadeClone_Step2(u8 taskId); +static void AnimShadowBall(struct Sprite *); +static void AnimShadowBall_Step(struct Sprite *); +static void AnimLick(struct Sprite *); +static void AnimLick_Step(struct Sprite *); +static void AnimTask_NightmareClone_Step(u8 taskId); +static void AnimTask_SpiteTargetShadow_Step1(u8 taskId); +static void AnimTask_SpiteTargetShadow_Step2(u8 taskId); +static void AnimTask_SpiteTargetShadow_Step3(u8 taskId); +static void AnimDestinyBondWhiteShadow(struct Sprite *); +static void AnimDestinyBondWhiteShadow_Step(struct Sprite *); +static void AnimTask_DestinyBondWhiteShadow_Step(u8 taskId); +static void AnimTask_CurseStretchingBlackBg_Step1(u8 taskId); +static void AnimTask_CurseStretchingBlackBg_Step2(u8 taskId); +static void AnimCurseNail(struct Sprite *); +static void AnimCurseNail_Step1(struct Sprite *); +static void AnimCurseNail_Step2(struct Sprite *); +static void AnimCurseNail_End(struct Sprite *); +static void AnimGhostStatusSprite(struct Sprite *); +static void AnimGhostStatusSprite_Step(struct Sprite *); +static void AnimTask_GrudgeFlames_Step(u8 taskId); +static void AnimGrudgeFlame(struct Sprite *); +static void sub_8112F60(struct Sprite *); +static void sub_8112FB8(struct Sprite *); + +static const union AffineAnimCmd sAffineAnim_ConfuseRayBallBounce[] = +{ + AFFINEANIMCMD_FRAME(0x1E, 0x1E, 10, 5), + AFFINEANIMCMD_FRAME(0xFFE2, 0xFFE2, 10, 5), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sAffineAnims_ConfuseRayBallBounce[] = +{ + sAffineAnim_ConfuseRayBallBounce, +}; + +const struct SpriteTemplate gConfuseRayBallBounceSpriteTemplate = +{ + .tileTag = ANIM_TAG_YELLOW_BALL, + .paletteTag = ANIM_TAG_YELLOW_BALL, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_ConfuseRayBallBounce, + .callback = AnimConfuseRayBallBounce, +}; + +const struct SpriteTemplate gConfuseRayBallSpiralSpriteTemplate = +{ + .tileTag = ANIM_TAG_YELLOW_BALL, + .paletteTag = ANIM_TAG_YELLOW_BALL, + .oam = &gOamData_AffineOff_ObjBlend_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimConfuseRayBallSpiral, +}; + +static const union AffineAnimCmd sAffineAnim_ShadowBall[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 10, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sAffineAnims_ShadowBall[] = +{ + sAffineAnim_ShadowBall, +}; + +const struct SpriteTemplate gShadowBallSpriteTemplate = +{ + .tileTag = ANIM_TAG_SHADOW_BALL, + .paletteTag = ANIM_TAG_SHADOW_BALL, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_ShadowBall, + .callback = AnimShadowBall, +}; + +static const union AnimCmd sAnim_Lick[] = +{ + ANIMCMD_FRAME(0, 2), + ANIMCMD_FRAME(8, 2), + ANIMCMD_FRAME(16, 2), + ANIMCMD_FRAME(24, 2), + ANIMCMD_FRAME(32, 2), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_Lick[] = +{ + sAnim_Lick, +}; + +const struct SpriteTemplate gLickSpriteTemplate = +{ + .tileTag = ANIM_TAG_LICK, + .paletteTag = ANIM_TAG_LICK, + .oam = &gOamData_AffineOff_ObjNormal_16x32, + .anims = sAnims_Lick, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimLick, +}; + +static const union AffineAnimCmd gUnknown_08596DA4[] = +{ + AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0), + AFFINEANIMCMD_END, +}; + +// Unused +static const union AffineAnimCmd *const gUnknown_08596DB4[] = +{ + gUnknown_08596DA4, +}; + +const struct SpriteTemplate gDestinyBondWhiteShadowSpriteTemplate = +{ + .tileTag = ANIM_TAG_WHITE_SHADOW, + .paletteTag = ANIM_TAG_WHITE_SHADOW, + .oam = &gOamData_AffineOff_ObjBlend_64x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDestinyBondWhiteShadow, +}; + +const struct SpriteTemplate gCurseNailSpriteTemplate = +{ + .tileTag = ANIM_TAG_NAIL, + .paletteTag = ANIM_TAG_NAIL, + .oam = &gOamData_AffineOff_ObjBlend_32x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimCurseNail, +}; + +const struct SpriteTemplate gCurseGhostSpriteTemplate = +{ + .tileTag = ANIM_TAG_GHOSTLY_SPIRIT, + .paletteTag = ANIM_TAG_GHOSTLY_SPIRIT, + .oam = &gOamData_AffineOff_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimGhostStatusSprite, +}; + +const struct SpriteTemplate gNightmareDevilSpriteTemplate = +{ + .tileTag = ANIM_TAG_DEVIL, + .paletteTag = ANIM_TAG_DEVIL, + .oam = &gOamData_AffineOff_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimGhostStatusSprite, +}; + +static const union AnimCmd sAnim_GrudgeFlame[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(8, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(24, 4), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_GrudgeFlame[] = +{ + sAnim_GrudgeFlame, +}; + +const struct SpriteTemplate gGrudgeFlameSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_FLAME, + .paletteTag = ANIM_TAG_PURPLE_FLAME, + .oam = &gOamData_AffineOff_ObjBlend_16x32, + .anims = sAnims_GrudgeFlame, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimGrudgeFlame, +}; + +// Unused +const struct SpriteTemplate gUnknown_08596E48 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_8112F60, +}; + +static void AnimConfuseRayBallBounce(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sub_80A6FD4(sprite); + sprite->callback = AnimConfuseRayBallBounce_Step1; + sprite->data[6] = 16; + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, sprite->data[6]); +} + +static void AnimConfuseRayBallBounce_Step1(struct Sprite *sprite) +{ + s16 r0; + s16 r2; + sub_8111764(sprite); + if (AnimTranslateLinear(sprite)) + { + sprite->callback = AnimConfuseRayBallBounce_Step2; + return; + } + + sprite->pos2.x += Sin(sprite->data[5], 10); + sprite->pos2.y += Cos(sprite->data[5], 15); + r2 = sprite->data[5]; + sprite->data[5] = (sprite->data[5] + 5) & 0xFF; + r0 = sprite->data[5]; + if (r2 != 0 && r2 <= 196) + return; + if (r0 <= 0) + return; + PlaySE12WithPanning(SE_W109, gAnimCustomPanning); +} + +static void AnimConfuseRayBallBounce_Step2(struct Sprite *sprite) +{ + s16 r2; + s16 r0; + sprite->data[0] = 1; + AnimTranslateLinear(sprite); + sprite->pos2.x += Sin(sprite->data[5], 10); + sprite->pos2.y += Cos(sprite->data[5], 15); + + r2 = sprite->data[5]; + sprite->data[5] = (sprite->data[5] + 5) & 0xFF; + r0 = sprite->data[5]; + + if (r2 == 0 || r2 > 196) + { + if (r0 > 0) + PlaySE(SE_W109); + } + + if (sprite->data[6] == 0) + { + sprite->invisible = TRUE; + sprite->callback = DestroyAnimSpriteAndDisableBlend; + } + else + sub_8111764(sprite); +} + +static void sub_8111764(struct Sprite *sprite) +{ + + s16 r0; + if (sprite->data[6] > 0xFF) + { + if (++sprite->data[6] == 0x10d) + sprite->data[6] = 0; + return; + } + + r0 = sprite->data[7]; + sprite->data[7]++; + + if ((r0 & 0xFF) == 0) + { + sprite->data[7] &= 0xff00; + if ((sprite->data[7] & 0x100) != 0) + sprite->data[6]++; + else + sprite->data[6]--; + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[6], 16 - sprite->data[6])); + if (sprite->data[6] == 0 || sprite->data[6] == 16) + sprite->data[7] ^= 0x100; + if (sprite->data[6] == 0) + sprite->data[6] = 0x100; + } +} + +static void AnimConfuseRayBallSpiral(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->callback = AnimConfuseRayBallSpiral_Step; + sprite->callback(sprite); +} + +static void AnimConfuseRayBallSpiral_Step(struct Sprite *sprite) +{ + u16 temp1; + sprite->pos2.x = Sin(sprite->data[0], 32); + sprite->pos2.y = Cos(sprite->data[0], 8); + temp1 = sprite->data[0] - 65; + if (temp1 <= 130) + sprite->oam.priority = 2; + else + sprite->oam.priority = 1; + sprite->data[0] = (sprite->data[0] + 19) & 0xFF; + sprite->data[2] += 80; + sprite->pos2.y += sprite->data[2] >> 8; + sprite->data[7] += 1; + if (sprite->data[7] == 61) + DestroyAnimSprite(sprite); +} + +// Creates a large transparent clone of the attacker centered on their position which shrinks to original size +void AnimTask_NightShadeClone(u8 taskId) +{ + u8 spriteId; + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); + spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_BLEND); + SetSpriteRotScale(spriteId, 128, 128, 0); + gSprites[spriteId].invisible = FALSE; + gTasks[taskId].data[0] = 128; + gTasks[taskId].data[1] = *gBattleAnimArgs; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 16; + gTasks[taskId].func = AnimTask_NightShadeClone_Step1; +} + +static void AnimTask_NightShadeClone_Step1(u8 taskId) +{ + gTasks[taskId].data[10] += 1; + if (gTasks[taskId].data[10] == 3) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[2] += 1; + gTasks[taskId].data[3] -= 1; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[2], gTasks[taskId].data[3])); + if (gTasks[taskId].data[2] != 9) + return; + + gTasks[taskId].func = AnimTask_NightShadeClone_Step2; + } +} + +static void AnimTask_NightShadeClone_Step2(u8 taskId) +{ + u8 spriteId; + if (gTasks[taskId].data[1] > 0) + { + gTasks[taskId].data[1] -= 1; + return; + } + + spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + gTasks[taskId].data[0] += 8; + if (gTasks[taskId].data[0] <= 0xFF) + { + SetSpriteRotScale(spriteId, gTasks[taskId].data[0], gTasks[taskId].data[0], 0); + } + else + { + ResetSpriteRotScale(spriteId); + DestroyAnimVisualTask(taskId); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + } +} + +// Spins a sprite towards the target, pausing in the middle. +// Used in Shadow Ball. +// arg 0: duration step 1 (attacker -> center) +// arg 1: duration step 2 (spin center) +// arg 2: duration step 3 (center -> target) +static void AnimShadowBall(struct Sprite *sprite) +{ + s16 oldPosX = sprite->pos1.x; + s16 oldPosY = sprite->pos1.y; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + sprite->data[0] = 0; + sprite->data[1] = gBattleAnimArgs[0]; + sprite->data[2] = gBattleAnimArgs[1]; + sprite->data[3] = gBattleAnimArgs[2]; + sprite->data[4] = sprite->pos1.x << 4; + sprite->data[5] = sprite->pos1.y << 4; + sprite->data[6] = ((oldPosX - sprite->pos1.x) << 4) / (gBattleAnimArgs[0] << 1); + sprite->data[7] = ((oldPosY - sprite->pos1.y) << 4) / (gBattleAnimArgs[0] << 1); + sprite->callback = AnimShadowBall_Step; +} + +static void AnimShadowBall_Step(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->data[4] += sprite->data[6]; + sprite->data[5] += sprite->data[7]; + sprite->pos1.x = sprite->data[4] >> 4; + sprite->pos1.y = sprite->data[5] >> 4; + sprite->data[1] -= 1; + if (sprite->data[1] > 0) + break; + sprite->data[0] += 1; + break; + case 1: + sprite->data[2] -= 1; + if (sprite->data[2] > 0) + break; + sprite->data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->data[4] = sprite->pos1.x << 4; + sprite->data[5] = sprite->pos1.y << 4; + sprite->data[6] = ((sprite->data[1] - sprite->pos1.x) << 4) / sprite->data[3]; + sprite->data[7] = ((sprite->data[2] - sprite->pos1.y) << 4) / sprite->data[3]; + sprite->data[0] += 1; + break; + case 2: + sprite->data[4] += sprite->data[6]; + sprite->data[5] += sprite->data[7]; + sprite->pos1.x = sprite->data[4] >> 4; + sprite->pos1.y = sprite->data[5] >> 4; + sprite->data[3] -= 1; + if (sprite->data[3] > 0) + break; + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->data[0] += 1; + break; + case 3: + DestroySpriteAndMatrix(sprite); + break; + } +} + +static void AnimLick(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->callback = AnimLick_Step; +} + +static void AnimLick_Step(struct Sprite *sprite) +{ + bool8 r5 = FALSE; + bool8 r6 = FALSE; + + if (sprite->animEnded) + { + if (!sprite->invisible) + sprite->invisible = TRUE; + + switch (sprite->data[0]) + { + default: + r6 = TRUE; + break; + case 0: + if (sprite->data[1] == 2) + r5 = TRUE; + break; + case 1: + if (sprite->data[1] == 4) + r5 = TRUE; + break; + } + + if (r5) + { + sprite->invisible ^= 1; + sprite->data[2]++; + sprite->data[1] = 0; + if (sprite->data[2] == 5) + { + sprite->data[2] = 0; + sprite->data[0]++; + } + } + else if (r6) + { + DestroyAnimSprite(sprite); + } + else + { + sprite->data[1]++; + } + } +} + +// Creates a transparent clone of the target which drifts up and away to the side +void AnimTask_NightmareClone(u8 taskId) +{ + struct Task *task; + + task = &gTasks[taskId]; + task->data[0] = CloneBattlerSpriteWithBlend(ANIM_TARGET); + if (task->data[0] < 0) + { + DestroyAnimVisualTask(taskId); + return; + } + task->data[1] = 0; + task->data[2] = 15; + task->data[3] = 2; + task->data[4] = 0; + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[2], task->data[3])); + gSprites[task->data[0]].data[0] = 80; + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + { + gSprites[task->data[0]].data[1] = -144; + gSprites[task->data[0]].data[2] = 112; + } + else + { + gSprites[task->data[0]].data[1] = 144; + gSprites[task->data[0]].data[2] = -112; + } + gSprites[task->data[0]].data[3] = 0; + gSprites[task->data[0]].data[4] = 0; + StoreSpriteCallbackInData6(&gSprites[task->data[0]], SpriteCallbackDummy); + gSprites[task->data[0]].callback = TranslateSpriteLinearFixedPoint; + task->func = AnimTask_NightmareClone_Step; +} + +static void AnimTask_NightmareClone_Step(u8 taskId) +{ + struct Task *task; + + task = &gTasks[taskId]; + switch (task->data[4]) + { + case 0: + task->data[1] += 1; + task->data[5] = task->data[1] & 3; + if (task->data[5] == 1) + if (task->data[2] > 0) + task->data[2] -= 1; + if (task->data[5] == 3) + if (task->data[3] <= 15) + task->data[3] += 1; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[2], task->data[3])); + if (task->data[3] != 16 || task->data[2] != 0) + break; + if (task->data[1] <= 80) + break; + obj_delete_but_dont_free_vram(&gSprites[task->data[0]]); + task->data[4] = 1; + break; + case 1: + if (++task->data[6] <= 1) + break; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + task->data[4] += 1; + break; + case 2: + DestroyAnimVisualTask(taskId); + break; + } +} + +// Creates a blended copy of the target that wavers in front of them +void AnimTask_SpiteTargetShadow(u8 taskId) +{ + struct Task *task; + + task = &gTasks[taskId]; + task->data[15] = 0; + task->func = AnimTask_SpiteTargetShadow_Step1; + task->func(taskId); +} + +static void AnimTask_SpiteTargetShadow_Step1(u8 taskId) +{ + s16 startLine; + struct Task *task = &gTasks[taskId]; + u8 position = GetBattlerSpriteBGPriorityRank(gBattleAnimTarget); + + switch (task->data[15]) + { + case 0: + task->data[14] = AllocSpritePalette(ANIM_TAG_BENT_SPOON); + if (task->data[14] == 0xFF || task->data[14] == 0xF) + { + DestroyAnimVisualTask(taskId); + } + else + { + task->data[0] = CloneBattlerSpriteWithBlend(ANIM_TARGET); + if (task->data[0] < 0) + { + FreeSpritePaletteByTag(ANIM_TAG_BENT_SPOON); + DestroyAnimVisualTask(taskId); + } + else + { + s16 mask2; + gSprites[task->data[0]].oam.paletteNum = task->data[14]; + gSprites[task->data[0]].oam.objMode = ST_OAM_OBJ_NORMAL; + gSprites[task->data[0]].oam.priority = 3; + gSprites[task->data[0]].invisible = (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].invisible); + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 16; + task->data[13] = GetAnimBattlerSpriteId(ANIM_TARGET); + task->data[4] = (gSprites[task->data[13]].oam.paletteNum + 16) * 16; + if (position == 1) { + u16 mask = DISPCNT_BG1_ON; + mask2 = mask; + } + else { + u16 mask = DISPCNT_BG2_ON; + mask2 = mask; + } + ClearGpuRegBits(REG_OFFSET_DISPCNT, mask2); + task->data[15]++; + } + } + break; + case 1: + task->data[14] = (task->data[14] + 16) * 16; + CpuSet(&gPlttBufferUnfaded[task->data[4]], &gPlttBufferFaded[task->data[14]], 0x4000008); + BlendPalette(task->data[4], 16, 10, RGB(13, 0, 15)); + task->data[15]++; + break; + case 2: + startLine = gSprites[task->data[13]].pos1.y + gSprites[task->data[13]].pos2.y - 32; + if (startLine < 0) + startLine = 0; + + if (position == 1) + task->data[10] = ScanlineEffect_InitWave(startLine, startLine + 64, 2, 6, 0, 4, 1); + else + task->data[10] = ScanlineEffect_InitWave(startLine, startLine + 64, 2, 6, 0, 8, 1); + + task->data[15]++; + break; + case 3: + if (position == 1) + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL | BLDCNT_TGT1_BG1)); + else + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL | BLDCNT_TGT1_BG2)); + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); + task->data[15]++; + break; + case 4: + if (position == 1) + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); + else + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); + + task->func = AnimTask_SpiteTargetShadow_Step2; + task->data[15]++; + break; + default: + task->data[15]++; + break; + } +} + +static void AnimTask_SpiteTargetShadow_Step2(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + task->data[1]++; + task->data[5] = task->data[1] & 1; + if (task->data[5] == 0) + task->data[2] = gSineTable[task->data[1]] / 18; + + if (task->data[5] == 1) + task->data[3] = 16 - (gSineTable[task->data[1]] / 18); + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[2], task->data[3])); + if (task->data[1] == 128) + { + task->data[15] = 0; + task->func = AnimTask_SpiteTargetShadow_Step3; + task->func(taskId); + } +} + +static void AnimTask_SpiteTargetShadow_Step3(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 rank = GetBattlerSpriteBGPriorityRank(gBattleAnimTarget); + + switch (task->data[15]) + { + case 0: + gScanlineEffect.state = 3; + task->data[14] = GetAnimBattlerSpriteId(ANIM_TARGET); + if (rank == 1) + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); + else + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); + break; + case 1: + BlendPalette(task->data[4], 16, 0, RGB(13, 0, 15)); + break; + case 2: + gSprites[task->data[14]].invisible = TRUE; + obj_delete_but_dont_free_vram(&gSprites[task->data[0]]); + FreeSpritePaletteByTag(ANIM_TAG_BENT_SPOON); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + if (rank == 1) + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); + else + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); + + DestroyAnimVisualTask(taskId); + break; + } + + task->data[15]++; +} + +static void AnimDestinyBondWhiteShadow(struct Sprite *sprite) +{ + s16 battler1X, battler1Y; + s16 battler2X, battler2Y; + s16 yDiff; + + if (gBattleAnimArgs[0] == 0) + { + battler1X = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); + battler1Y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 28; + battler2X = GetBattlerSpriteCoord(gBattleAnimTarget, 0); + battler2Y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 28; + } + else + { + battler1X = GetBattlerSpriteCoord(gBattleAnimTarget, 0); + battler1Y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 28; + battler2X = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); + battler2Y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 28; + } + + yDiff = battler2Y - battler1Y; + sprite->data[0] = battler1X * 16; + sprite->data[1] = battler1Y * 16; + sprite->data[2] = ((battler2X - battler1X) * 16) / gBattleAnimArgs[1]; + sprite->data[3] = (yDiff * 16) / gBattleAnimArgs[1]; + sprite->data[4] = gBattleAnimArgs[1]; + sprite->data[5] = battler2X; + sprite->data[6] = battler2Y; + sprite->data[7] = sprite->data[4] / 2; + sprite->oam.priority = 2; + sprite->pos1.x = battler1X; + sprite->pos1.y = battler1Y; + sprite->callback = AnimDestinyBondWhiteShadow_Step; + sprite->invisible = TRUE; +} + +static void AnimDestinyBondWhiteShadow_Step(struct Sprite *sprite) +{ + if (sprite->data[4]) + { + sprite->data[0] += sprite->data[2]; + sprite->data[1] += sprite->data[3]; + sprite->pos1.x = sprite->data[0] >> 4; + sprite->pos1.y = sprite->data[1] >> 4; + if (--sprite->data[4] == 0) + sprite->data[0] = 0; + } +} + +void AnimTask_DestinyBondWhiteShadow(u8 taskId) +{ + struct Task *task; + s16 battler; + u8 spriteId; + s16 baseX, baseY; + s16 x, y; + + task = &gTasks[taskId]; + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); + task->data[5] = 0; + task->data[6] = 0; + task->data[7] = 0; + task->data[8] = 0; + task->data[9] = 16; + task->data[10] = gBattleAnimArgs[0]; + + baseX = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + baseY = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_BOTTOM); + if (!IsContest()) + { + for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++) + { + if (battler != gBattleAnimAttacker + && battler != (gBattleAnimAttacker ^ 2) + && IsBattlerSpriteVisible(battler)) + { + spriteId = CreateSprite(&gDestinyBondWhiteShadowSpriteTemplate, baseX, baseY, 55); + if (spriteId != MAX_SPRITES) + { + x = GetBattlerSpriteCoord(battler, 2); + y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_BOTTOM); + gSprites[spriteId].data[0] = baseX << 4; + gSprites[spriteId].data[1] = baseY << 4; + gSprites[spriteId].data[2] = ((x - baseX) << 4) / gBattleAnimArgs[1]; + gSprites[spriteId].data[3] = ((y - baseY) << 4) / gBattleAnimArgs[1]; + gSprites[spriteId].data[4] = gBattleAnimArgs[1]; + gSprites[spriteId].data[5] = x; + gSprites[spriteId].data[6] = y; + gSprites[spriteId].callback = AnimDestinyBondWhiteShadow_Step; + + task->data[task->data[12] + 13] = spriteId; + task->data[12]++; + } + } + } + } + else + { + spriteId = CreateSprite(&gDestinyBondWhiteShadowSpriteTemplate, baseX, baseY, 55); + if (spriteId != MAX_SPRITES) + { + x = 48; + y = 40; + gSprites[spriteId].data[0] = baseX << 4; + gSprites[spriteId].data[1] = baseY << 4; + gSprites[spriteId].data[2] = ((x - baseX) << 4) / gBattleAnimArgs[1]; + gSprites[spriteId].data[3] = ((y - baseY) << 4) / gBattleAnimArgs[1]; + gSprites[spriteId].data[4] = gBattleAnimArgs[1]; + gSprites[spriteId].data[5] = x; + gSprites[spriteId].data[6] = y; + gSprites[spriteId].callback = AnimDestinyBondWhiteShadow_Step; + + task->data[13] = spriteId; + task->data[12] = 1; + } + } + + task->func = AnimTask_DestinyBondWhiteShadow_Step; +} + +static void AnimTask_DestinyBondWhiteShadow_Step(u8 taskId) +{ + u16 i; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + if (task->data[6] == 0) + { + if (++task->data[5] > 1) + { + task->data[5] = 0; + task->data[7]++; + if (task->data[7] & 1) + { + if (task->data[8] < 16) + task->data[8]++; + } + else + { + if (task->data[9]) + task->data[9]--; + } + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[8], task->data[9])); + if (task->data[7] >= 24) + { + task->data[7] = 0; + task->data[6] = 1; + } + } + } + + if (task->data[10]) + task->data[10]--; + else if (task->data[6]) + task->data[0]++; + break; + case 1: + if (++task->data[5] > 1) + { + task->data[5] = 0; + task->data[7]++; + if (task->data[7] & 1) + { + if (task->data[8]) + task->data[8]--; + } + else + { + if (task->data[9] < 16) + task->data[9]++; + } + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[8], task->data[9])); + if (task->data[8] == 0 && task->data[9] == 16) + { + for (i = 0; i < task->data[12]; i++) + DestroySprite(&gSprites[task->data[i + 13]]); + + task->data[0]++; + } + } + break; + case 2: + if (++task->data[5] > 0) + task->data[0]++; + break; + case 3: + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimVisualTask(taskId); + break; + } +} + +void AnimTask_CurseStretchingBlackBg(u8 taskId) +{ + s16 startX, startY; + s16 leftDistance, topDistance, bottomDistance, rightDistance; + + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WININ, ((WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR) | + (WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR))); + SetGpuReg(REG_OFFSET_WINOUT, ((WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ) | + (WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR))); + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_TGT1_BG3 | BLDCNT_EFFECT_DARKEN)); + SetGpuReg(REG_OFFSET_BLDY, 0x10); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER || IsContest()) + startX = 40; + else + startX = 200; + + gBattle_WIN0H = (startX << 8) | startX; + startY = 40; + gBattle_WIN0V = (startY << 8) | startY; + + leftDistance = startX; + rightDistance = 240 - startX; + topDistance = startY; + bottomDistance = 72; + gTasks[taskId].data[1] = leftDistance; + gTasks[taskId].data[2] = rightDistance; + gTasks[taskId].data[3] = topDistance; + gTasks[taskId].data[4] = bottomDistance; + gTasks[taskId].data[5] = startX; + gTasks[taskId].data[6] = startY; + gTasks[taskId].func = AnimTask_CurseStretchingBlackBg_Step1; +} + +static void AnimTask_CurseStretchingBlackBg_Step1(u8 taskId) +{ + s16 step; + s16 leftDistance, rightDistance, topDistance, bottomDistance; + s16 startX, startY; + u16 left, right, top, bottom; + u16 selectedPalettes; + + step = gTasks[taskId].data[0]; + gTasks[taskId].data[0]++; + leftDistance = gTasks[taskId].data[1]; + rightDistance = gTasks[taskId].data[2]; + topDistance = gTasks[taskId].data[3]; + bottomDistance = gTasks[taskId].data[4]; + startX = gTasks[taskId].data[5]; + startY = gTasks[taskId].data[6]; + + if (step < 16) + { + left = startX - (leftDistance * 0.0625) * step; + right = startX + (rightDistance * 0.0625) * step; + top = startY - (topDistance * 0.0625) * step; + bottom = startY + (bottomDistance * 0.0625) * step; + } + else + { + left = 0; + right = 240; + top = 0; + bottom = 112; + selectedPalettes = sub_80A75AC(1, 0, 0, 0, 0, 0, 0); + BeginNormalPaletteFade(selectedPalettes, 0, 16, 16, RGB(0, 0, 0)); + gTasks[taskId].func = AnimTask_CurseStretchingBlackBg_Step2; + } + + gBattle_WIN0H = (left << 8) | right; + gBattle_WIN0V = (top << 8) | bottom; +} + +static void AnimTask_CurseStretchingBlackBg_Step2(u8 taskId) +{ + if (!gPaletteFade.active) + { + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + SetGpuReg(REG_OFFSET_WININ, ((WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR) | + (WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR))); + SetGpuReg(REG_OFFSET_WINOUT, ((WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR) | + (WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR))); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + DestroyAnimVisualTask(taskId); + } +} + +static void AnimCurseNail(struct Sprite *sprite) +{ + s16 xDelta; + s16 xDelta2; + + InitSpritePosToAnimAttacker(sprite, 1); + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + xDelta = 24; + xDelta2 = -2; + sprite->oam.matrixNum = ST_OAM_HFLIP; + } + else + { + xDelta = -24; + xDelta2 = 2; + } + + sprite->pos1.x += xDelta; + sprite->data[1] = xDelta2; + sprite->data[0] = 60; + sprite->callback = AnimCurseNail_Step1; +} + +static void AnimCurseNail_Step1(struct Sprite *sprite) +{ + u16 var0; + + if (sprite->data[0] > 0) + { + sprite->data[0]--; + } + else + { + sprite->pos2.x += sprite->data[1]; + var0 = sprite->pos2.x + 7; + if (var0 > 14) + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos2.x = 0; + sprite->oam.tileNum += 8; + if (++sprite->data[2] == 3) + { + sprite->data[0] = 30; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, AnimCurseNail_Step2); + } + else + { + sprite->data[0] = 40; + } + } + } +} + +static void AnimCurseNail_Step2(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + sprite->data[0]++; + sprite->data[1] = 0; + sprite->data[2] = 0; + } + else if (sprite->data[1] < 2) + { + sprite->data[1]++; + } + else + { + sprite->data[1] = 0; + sprite->data[2]++; + SetGpuReg(REG_OFFSET_BLDALPHA, (16 - sprite->data[2]) | (sprite->data[2] << 8)); + if (sprite->data[2] == 16) + { + sprite->invisible = TRUE; + sprite->callback = AnimCurseNail_End; + } + } +} + +static void AnimCurseNail_End(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + DestroyAnimSprite(sprite); +} + +static void AnimGhostStatusSprite(struct Sprite *sprite) +{ + u16 coeffB; + u16 coeffA; + + sprite->pos2.x = Sin(sprite->data[0], 12); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos2.x = -sprite->pos2.x; + + sprite->data[0] = (sprite->data[0] + 6) & 0xFF; + sprite->data[1] += 0x100; + sprite->pos2.y = -(sprite->data[1] >> 8); + + sprite->data[7]++; + if (sprite->data[7] == 1) + { + sprite->data[6] = 0x050B; + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, sprite->data[6]); + } + else if (sprite->data[7] > 30) + { + sprite->data[2]++; + coeffB = sprite->data[6] >> 8; + coeffA = sprite->data[6] & 0xFF; + + if (++coeffB > 16) + coeffB = 16; + --coeffA; + if ((s16)coeffA < 0) + coeffA = 0; + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(coeffA, coeffB)); + sprite->data[6] = BLDALPHA_BLEND(coeffA, coeffB); + if (coeffB == 16 && coeffA == 0) + { + sprite->invisible = TRUE; + sprite->callback = AnimGhostStatusSprite_Step; + } + } +} + +static void AnimGhostStatusSprite_Step(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimSprite(sprite); +} + +void AnimTask_GrudgeFlames(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[0] = 0; + task->data[1] = 16; + task->data[9] = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + task->data[10] = GetBattlerYCoordWithElevation(gBattleAnimAttacker); + task->data[11] = (GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_WIDTH) / 2) + 8; + task->data[7] = 0; + task->data[5] = GetBattlerSpriteBGPriority(gBattleAnimAttacker); + task->data[6] = GetBattlerSpriteSubpriority(gBattleAnimAttacker) - 2; + task->data[3] = 0; + task->data[4] = 16; + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); + task->data[8] = 0; + task->func = AnimTask_GrudgeFlames_Step; +} + +static void AnimTask_GrudgeFlames_Step(u8 taskId) +{ + u16 i; + u8 spriteId; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + for (i = 0; i < 6; i++) + { + spriteId = CreateSprite(&gGrudgeFlameSpriteTemplate, task->data[9], task->data[10], task->data[6]); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].data[0] = taskId; + gSprites[spriteId].data[1] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER; + + gSprites[spriteId].data[2] = (i * 42) & 0xFF; + gSprites[spriteId].data[3] = task->data[11]; + gSprites[spriteId].data[5] = i * 6; + task->data[7]++; + } + } + + task->data[0]++; + break; + case 1: + if (++task->data[1] & 1) + { + if (task->data[3] < 14) + task->data[3]++; + } + else + { + if (task->data[4] > 4) + task->data[4]--; + } + + if (task->data[3] == 14 && task->data[4] == 4) + { + task->data[1] = 0; + task->data[0]++; + } + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4])); + break; + case 2: + if (++task->data[1] > 30) + { + task->data[1] = 0; + task->data[0]++; + } + break; + case 3: + if (++task->data[1] & 1) + { + if (task->data[3] > 0) + task->data[3]--; + } + else + { + if (task->data[4] < 16) + task->data[4]++; + } + + if (task->data[3] == 0 && task->data[4] == 16) + { + task->data[8] = 1; + task->data[0]++; + } + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4])); + break; + case 4: + if (task->data[7] == 0) + task->data[0]++; + break; + case 5: + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimVisualTask(taskId); + break; + } +} + +static void AnimGrudgeFlame(struct Sprite *sprite) +{ + u16 index; + + if (sprite->data[1] == 0) + sprite->data[2] += 2; + else + sprite->data[2] -= 2; + + sprite->data[2] &= 0xFF; + sprite->pos2.x = Sin(sprite->data[2], sprite->data[3]); + + index = sprite->data[2] - 65; + if (index < 127) + sprite->oam.priority = gTasks[sprite->data[0]].data[5] + 1; + else + sprite->oam.priority = gTasks[sprite->data[0]].data[5]; + + sprite->data[5]++; + sprite->data[6] = (sprite->data[5] * 8) & 0xFF; + sprite->pos2.y = Sin(sprite->data[6], 7); + if (gTasks[sprite->data[0]].data[8]) + { + gTasks[sprite->data[0]].data[7]--; + DestroySprite(sprite); + } +} + +static void sub_8112F60(struct Sprite *sprite) +{ + sprite->invisible = TRUE; + sprite->data[5] = gBattlerSpriteIds[gBattleAnimAttacker]; + sprite->data[0] = 128; + sprite->data[1] = 10; + sprite->data[2] = gBattleAnimArgs[0]; + sprite->data[3] = gBattleAnimArgs[1]; + sprite->callback = sub_8112FB8; + + gSprites[sprite->data[5]].pos1.y += 8; +} + +static void sub_8112FB8(struct Sprite *sprite) +{ + if (sprite->data[3]) + { + sprite->data[3]--; + gSprites[sprite->data[5]].pos2.x = Sin(sprite->data[0], sprite->data[1]); + gSprites[sprite->data[5]].pos2.y = Cos(sprite->data[0], sprite->data[1]); + sprite->data[0] += sprite->data[2]; + if (sprite->data[0] > 255) + sprite->data[0] -= 256; + } + else + { + gSprites[sprite->data[5]].pos2.x = 0; + gSprites[sprite->data[5]].pos2.y = 0; + gSprites[sprite->data[5]].pos1.y -= 8; + sprite->callback = DestroySpriteAndMatrix; + } +} diff --git a/src/battle_anim_ground.c b/src/battle_anim_ground.c new file mode 100644 index 000000000..875ecbd75 --- /dev/null +++ b/src/battle_anim_ground.c @@ -0,0 +1,772 @@ +#include "global.h" +#include "battle_anim.h" +#include "random.h" +#include "scanline_effect.h" +#include "task.h" +#include "trig.h" +#include "constants/rgb.h" + +static void AnimBonemerangProjectile(struct Sprite *); +static void AnimBoneHitProjectile(struct Sprite *); +static void AnimDirtScatter(struct Sprite *); +static void AnimMudSportDirt(struct Sprite *); +static void AnimDirtPlumeParticle(struct Sprite *); +static void AnimDirtPlumeParticle_Step(struct Sprite *); +static void AnimDigDirtMound(struct Sprite *); +static void AnimBonemerangProjectile_Step(struct Sprite *); +static void AnimBonemerangProjectile_End(struct Sprite *); +static void AnimMudSportDirtRising(struct Sprite *); +static void AnimMudSportDirtFalling(struct Sprite *); +static void AnimTask_DigBounceMovement(u8); +static void AnimTask_DigEndBounceMovementSetInvisible(u8); +static void AnimTask_DigSetVisibleUnderground(u8); +static void AnimTask_DigRiseUpFromHole(u8); +static void sub_81150E0(u8, s16, s16); +static void AnimTask_ShakeTerrain(u8); +static void AnimTask_ShakeBattlers(u8); +static void SetBattlersXOffsetForShake(struct Task *); +static void sub_81156D0(u8); + +static const union AffineAnimCmd sAffineAnim_Bonemerang[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 15, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sAffineAnim_SpinningBone[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 20, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sAffineAnims_Bonemerang[] = +{ + sAffineAnim_Bonemerang, +}; + +static const union AffineAnimCmd *const sAffineAnims_SpinningBone[] = +{ + sAffineAnim_SpinningBone, +}; + +const struct SpriteTemplate gBonemerangSpriteTemplate = +{ + .tileTag = ANIM_TAG_BONE, + .paletteTag = ANIM_TAG_BONE, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_Bonemerang, + .callback = AnimBonemerangProjectile, +}; + +const struct SpriteTemplate gSpinningBoneSpriteTemplate = +{ + .tileTag = ANIM_TAG_BONE, + .paletteTag = ANIM_TAG_BONE, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_SpinningBone, + .callback = AnimBoneHitProjectile, +}; + +const struct SpriteTemplate gSandAttackDirtSpriteTemplate = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDirtScatter, +}; + +static const union AnimCmd sAnim_MudSlapMud[] = +{ + ANIMCMD_FRAME(1, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_MudSlapMud[] = +{ + sAnim_MudSlapMud, +}; + +const struct SpriteTemplate gMudSlapMudSpriteTemplate = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = sAnims_MudSlapMud, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDirtScatter, +}; + +const struct SpriteTemplate gMudsportMudSpriteTemplate = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMudSportDirt, +}; + +const struct SpriteTemplate gDirtPlumeSpriteTemplate = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDirtPlumeParticle, +}; + +const struct SpriteTemplate gDirtMoundSpriteTemplate = +{ + .tileTag = ANIM_TAG_DIRT_MOUND, + .paletteTag = ANIM_TAG_DIRT_MOUND, + .oam = &gOamData_AffineOff_ObjNormal_32x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDigDirtMound, +}; + +// Moves a bone projectile towards the target mon, which moves like +// a boomerang. After hitting the target mon, it comes back to the user. +static void AnimBonemerangProjectile(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + sprite->data[0] = 20; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->data[5] = -40; + InitAnimArcTranslation(sprite); + sprite->callback = AnimBonemerangProjectile_Step; +} + +static void AnimBonemerangProjectile_Step(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + sprite->data[0] = 20; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + sprite->data[5] = 40; + InitAnimArcTranslation(sprite); + sprite->callback = AnimBonemerangProjectile_End; + } +} + +static void AnimBonemerangProjectile_End(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroyAnimSprite(sprite); +} + +// Moves a bone projectile towards the target mon, starting right next to +// the target mon. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x pixel offset +// arg 3: target y pixel offset +// arg 4: duration +static void AnimBoneHitProjectile(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + 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, 3) + gBattleAnimArgs[3]; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Moves a small dirt projectile towards the target mon. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: duration +// arg 3: target x pixel offset +// arg 4: target y pixel offset +static void AnimDirtScatter(struct Sprite *sprite) +{ + u8 targetXPos, targetYPos; + s16 xOffset, yOffset; + + InitSpritePosToAnimAttacker(sprite, 1); + + targetXPos = GetBattlerSpriteCoord2(gBattleAnimTarget, 2); + targetYPos = GetBattlerSpriteCoord2(gBattleAnimTarget, 3); + + xOffset = Random2() & 0x1F; + yOffset = Random2() & 0x1F; + if (xOffset > 16) + xOffset = 16 - xOffset; + if (yOffset > 16) + yOffset = 16 - yOffset; + + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[2] = targetXPos + xOffset; + sprite->data[4] = targetYPos + yOffset; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); +} + +// Moves a particle of dirt in the Mud Sport animation. +// The dirt can either be rising upward, or falling down. +// arg 0: 0 = dirt is rising into the air, 1 = dirt is falling down +// arg 1: initial x pixel offset +// arg 2: initial y pixel offset +static void AnimMudSportDirt(struct Sprite *sprite) +{ + sprite->oam.tileNum++; + if (gBattleAnimArgs[0] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2) + gBattleAnimArgs[1]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[1] > 0 ? 1 : -1; + sprite->callback = AnimMudSportDirtRising; + } + else + { + sprite->pos1.x = gBattleAnimArgs[1]; + sprite->pos1.y = gBattleAnimArgs[2]; + sprite->pos2.y = -gBattleAnimArgs[2]; + sprite->callback = AnimMudSportDirtFalling; + } +} + +static void AnimMudSportDirtRising(struct Sprite *sprite) +{ + if (++sprite->data[1] > 1) + { + sprite->data[1] = 0; + sprite->pos1.x += sprite->data[0]; + } + + sprite->pos1.y -= 4; + if (sprite->pos1.y < -4) + DestroyAnimSprite(sprite); +} + +static void AnimMudSportDirtFalling(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->pos2.y += 4; + if (sprite->pos2.y >= 0) + { + sprite->pos2.y = 0; + sprite->data[0]++; + } + break; + case 1: + if (++sprite->data[1] > 0) + { + sprite->data[1] = 0; + sprite->invisible ^= 1; + if (++sprite->data[2] == 10) + DestroyAnimSprite(sprite); + } + break; + } +} + +void AnimTask_DigDownMovement(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (gBattleAnimArgs[0] == FALSE) + task->func = AnimTask_DigBounceMovement; + else + task->func = AnimTask_DigEndBounceMovementSetInvisible; + + task->func(taskId); +} + +static void AnimTask_DigBounceMovement(u8 taskId) +{ + u8 var0; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[11] = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); + if (task->data[11] == 1) + { + task->data[12] = gBattle_BG1_X; + task->data[13] = gBattle_BG1_Y; + } + else + { + task->data[12] = gBattle_BG2_X; + task->data[13] = gBattle_BG2_Y; + } + + var0 = GetBattlerYCoordWithElevation(gBattleAnimAttacker); + task->data[14] = var0 - 32; + task->data[15] = var0 + 32; + if (task->data[14] < 0) + task->data[14] = 0; + + gSprites[task->data[10]].invisible = TRUE; + task->data[0]++; + break; + case 1: + sub_81150E0(task->data[11], task->data[14], task->data[15]); + task->data[0]++; + break; + case 2: + task->data[2] = (task->data[2] + 6) & 0x7F; + if (++task->data[4] > 2) + { + task->data[4] = 0; + task->data[3]++; + } + + task->data[5] = task->data[3] + (gSineTable[task->data[2]] >> 4); + if (task->data[11] == 1) + gBattle_BG1_Y = task->data[13] - task->data[5]; + else + gBattle_BG2_Y = task->data[13] - task->data[5]; + + if (task->data[5] > 63) + { + task->data[5] = 120 - task->data[14]; + if (task->data[11] == 1) + gBattle_BG1_Y = task->data[13] - task->data[5]; + else + gBattle_BG2_Y = task->data[13] - task->data[5]; + + gSprites[task->data[10]].pos2.x = 272 - gSprites[task->data[10]].pos1.x; + task->data[0]++; + } + break; + case 3: + gScanlineEffect.state = 3; + task->data[0]++; + break; + case 4: + DestroyAnimVisualTask(taskId); + gSprites[task->data[10]].invisible = TRUE; + break; + } +} + +static void AnimTask_DigEndBounceMovementSetInvisible(u8 taskId) +{ + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + gSprites[spriteId].invisible = TRUE; + gSprites[spriteId].pos2.x = 0; + gSprites[spriteId].pos2.y = 0; + + if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1) + gBattle_BG1_Y = 0; + else + gBattle_BG2_Y = 0; + + DestroyAnimVisualTask(taskId); +} + +void AnimTask_DigUpMovement(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (gBattleAnimArgs[0] == FALSE) + task->func = AnimTask_DigSetVisibleUnderground; + else + task->func = AnimTask_DigRiseUpFromHole; + + task->func(taskId); +} + +static void AnimTask_DigSetVisibleUnderground(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + gSprites[task->data[10]].invisible = FALSE; + gSprites[task->data[10]].pos2.x = 0; + gSprites[task->data[10]].pos2.y = 160 - gSprites[task->data[10]].pos1.y; + task->data[0]++; + break; + case 1: + DestroyAnimVisualTask(taskId); + } +} + +static void AnimTask_DigRiseUpFromHole(u8 taskId) +{ + u8 var0; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[11] = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); + if (task->data[11] == 1) + task->data[12] = gBattle_BG1_X; + else + task->data[12] = gBattle_BG2_X; + + var0 = GetBattlerYCoordWithElevation(gBattleAnimAttacker); + task->data[14] = var0 - 32; + task->data[15] = var0 + 32; + task->data[0]++; + break; + case 1: + sub_81150E0(task->data[11], 0, task->data[15]); + task->data[0]++; + break; + case 2: + gSprites[task->data[10]].pos2.y = 96; + task->data[0]++; + break; + case 3: + gSprites[task->data[10]].pos2.y -= 8; + if (gSprites[task->data[10]].pos2.y == 0) + { + gScanlineEffect.state = 3; + task->data[0]++; + } + break; + case 4: + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_81150E0(u8 useBG1, s16 y, s16 endY) +{ + s16 bgX; + struct ScanlineEffectParams scanlineParams; + + if (useBG1 == 1) + { + bgX = gBattle_BG1_X; + scanlineParams.dmaDest = ®_BG1HOFS; + } + else + { + bgX = gBattle_BG2_X; + scanlineParams.dmaDest = ®_BG2HOFS; + } + + if (y < 0) + y = 0; + + while (y < endY) + { + gScanlineEffectRegBuffers[0][y] = bgX; + gScanlineEffectRegBuffers[1][y] = bgX; + y++; + } + + while (y < 160) + { + gScanlineEffectRegBuffers[0][y] = bgX + 240; + gScanlineEffectRegBuffers[1][y] = bgX + 240; + y++; + } + + scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; + scanlineParams.initState = 1; + scanlineParams.unused9 = 0; + ScanlineEffect_SetParams(scanlineParams); +} + +// Moves a particle of dirt in a plume of dirt. Used in Fissure and Dig. +// arg 0: which mon (0 = attacker, 1 = target) +// arg 1: which side of mon (0 = left, 1 = right) +// arg 2: target x offset +// arg 3: target y offset +// arg 4: wave amplitude +// arg 5: duration +void AnimDirtPlumeParticle(struct Sprite *sprite) +{ + s8 battler; + s16 xOffset; + + if (gBattleAnimArgs[0] == 0) + battler = gBattleAnimAttacker; + else + battler = gBattleAnimTarget; + + xOffset = 24; + if (gBattleAnimArgs[1] == 1) + { + xOffset *= -1; + gBattleAnimArgs[2] *= -1; + } + + sprite->pos1.x = GetBattlerSpriteCoord(battler, 2) + xOffset; + sprite->pos1.y = GetBattlerYCoordWithElevation(battler) + 30; + sprite->data[0] = gBattleAnimArgs[5]; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[3]; + sprite->data[5] = gBattleAnimArgs[4]; + InitAnimArcTranslation(sprite); + sprite->callback = AnimDirtPlumeParticle_Step; +} + +static void AnimDirtPlumeParticle_Step(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroyAnimSprite(sprite); +} + +// Displays the dirt mound seen in the move Dig for set duration. +// The dirt mound image is too large for a single sprite, so two +// sprites are lined up next to each other. +// arg 0: which mon (0 = attacker, 1 = target) +// arg 1: oam tile num (0 = left half of image, 1 = right half of image) +// arg 2: duration +static void AnimDigDirtMound(struct Sprite *sprite) +{ + s8 battler; + + if (gBattleAnimArgs[0] == 0) + battler = gBattleAnimAttacker; + else + battler = gBattleAnimTarget; + + sprite->pos1.x = GetBattlerSpriteCoord(battler, 0) - 16 + (gBattleAnimArgs[1] * 32); + sprite->pos1.y = GetBattlerYCoordWithElevation(battler) + 32; + sprite->oam.tileNum += gBattleAnimArgs[1] * 8; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->callback = WaitAnimForDuration; +} + + +#define tState data[0] +#define tDelay data[1] +#define tTimer data[2] +#define tMaxTime data[3] +#define tbattlerSpriteIds(i) data[9 + (i)] +#define tNumBattlers data[13] // AnimTask_ShakeBattlers +#define tInitialX data[13] // AnimTask_ShakeTerrain +#define tHorizOffset data[14] +#define tInitHorizOffset data[15] + +// Shakes battler(s) or the battle terrain back and forth horizontally. Used by e.g. Earthquake, Eruption +// arg0: What to shake. 0-3 for any specific battler, MAX_BATTLERS_COUNT for all battlers, MAX_BATTLERS_COUNT + 1 for the terrain +// arg1: Shake intensity, used to calculate horizontal pixel offset (if 0, use move power instead) +// arg2: Length of time to shake for +void AnimTask_HorizontalShake(u8 taskId) +{ + u16 i; + struct Task *task = &gTasks[taskId]; + + if (gBattleAnimArgs[1] != 0) + task->tHorizOffset = task->tInitHorizOffset = gBattleAnimArgs[1] + 3; + else + task->tHorizOffset = task->tInitHorizOffset = (gAnimMovePower / 10) + 3; + + task->tMaxTime = gBattleAnimArgs[2]; + switch (gBattleAnimArgs[0]) + { + case MAX_BATTLERS_COUNT + 1: // Shake terrain + task->tInitialX = gBattle_BG3_X; + task->func = AnimTask_ShakeTerrain; + break; + case MAX_BATTLERS_COUNT: // Shake all battlers + task->tNumBattlers = 0; + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (IsBattlerSpriteVisible(i)) + { + task->tbattlerSpriteIds(task->tNumBattlers) = gBattlerSpriteIds[i]; + task->tNumBattlers++; + } + } + task->func = AnimTask_ShakeBattlers; + break; + default: // Shake specific battler + task->tbattlerSpriteIds(0) = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); + if (task->tbattlerSpriteIds(0) == 0xFF) + { + DestroyAnimVisualTask(taskId); + } + else + { + task->tNumBattlers = 1; + task->func = AnimTask_ShakeBattlers; + } + break; + } +} + +static void AnimTask_ShakeTerrain(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->tState) + { + case 0: + if (++task->tDelay > 1) + { + task->tDelay = 0; + if ((task->tTimer & 1) == 0) + gBattle_BG3_X = task->tInitialX + task->tInitHorizOffset; + else + gBattle_BG3_X = task->tInitialX - task->tInitHorizOffset; + + if (++task->tTimer == task->tMaxTime) + { + task->tTimer = 0; + task->tHorizOffset--; + task->tState++; + } + } + break; + case 1: + if (++task->tDelay > 1) + { + task->tDelay = 0; + if ((task->tTimer & 1) == 0) + gBattle_BG3_X = task->tInitialX + task->tHorizOffset; + else + gBattle_BG3_X = task->tInitialX - task->tHorizOffset; + + if (++task->tTimer == 4) + { + task->tTimer = 0; + if (--task->tHorizOffset == 0) + task->tState++; + } + } + break; + case 2: + gBattle_BG3_X = task->tInitialX; + DestroyAnimVisualTask(taskId); + break; + } +} + +static void AnimTask_ShakeBattlers(u8 taskId) +{ + u16 i; + struct Task *task = &gTasks[taskId]; + + switch (task->tState) + { + case 0: + if (++task->tDelay > 1) + { + task->tDelay = 0; + SetBattlersXOffsetForShake(task); + if (++task->tTimer == task->tMaxTime) + { + task->tTimer = 0; + task->tHorizOffset--; + task->tState++; + } + } + break; + case 1: + if (++task->tDelay > 1) + { + task->tDelay = 0; + SetBattlersXOffsetForShake(task); + if (++task->tTimer == 4) + { + task->tTimer = 0; + if (--task->tHorizOffset == 0) + task->tState++; + } + } + break; + case 2: + for (i = 0; i < task->tNumBattlers; i++) + gSprites[task->tbattlerSpriteIds(i)].pos2.x = 0; + + DestroyAnimVisualTask(taskId); + break; + } +} + +static void SetBattlersXOffsetForShake(struct Task *task) +{ + u16 i; + u16 xOffset; + + if ((task->tTimer & 1) == 0) + xOffset = (task->tHorizOffset / 2) + (task->tHorizOffset & 1); + else + xOffset = -(task->tHorizOffset / 2); + + for (i = 0; i < task->tNumBattlers; i++) + { + gSprites[task->tbattlerSpriteIds(i)].pos2.x = xOffset; + } +} + +#undef tState +#undef tDelay +#undef tTimer +#undef tMaxTime +#undef tbattlerSpriteIds +#undef tNumBattlers +#undef tInitialX +#undef tHorizOffset +#undef tInitHorizOffset + +void AnimTask_IsPowerOver99(u8 taskId) +{ + gBattleAnimArgs[15] = gAnimMovePower > 99; + DestroyAnimVisualTask(taskId); +} + +void AnimTask_PositionFissureBgOnBattler(u8 taskId) +{ + struct Task *newTask; + u8 battler = (gBattleAnimArgs[0] & ANIM_TARGET) ? gBattleAnimTarget : gBattleAnimAttacker; + + if (gBattleAnimArgs[0] > ANIM_TARGET) + battler ^= 2; + + newTask = &gTasks[CreateTask(sub_81156D0, gBattleAnimArgs[1])]; + newTask->data[1] = (32 - GetBattlerSpriteCoord(battler, 2)) & 0x1FF; + newTask->data[2] = (64 - GetBattlerSpriteCoord(battler, 3)) & 0xFF; + gBattle_BG3_X = newTask->data[1]; + gBattle_BG3_Y = newTask->data[2]; + newTask->data[3] = gBattleAnimArgs[2]; + DestroyAnimVisualTask(taskId); +} + +static void sub_81156D0(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (gBattleAnimArgs[7] == task->data[3]) + { + gBattle_BG3_X = 0; + gBattle_BG3_Y = 0; + DestroyTask(taskId); + } + else + { + gBattle_BG3_X = task->data[1]; + gBattle_BG3_Y = task->data[2]; + } +} diff --git a/src/battle_anim_ice.c b/src/battle_anim_ice.c new file mode 100644 index 000000000..24ddf3b32 --- /dev/null +++ b/src/battle_anim_ice.c @@ -0,0 +1,1571 @@ +#include "global.h" +#include "battle_anim.h" +#include "bg.h" +#include "field_weather.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "main.h" +#include "palette.h" +#include "random.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "constants/battle_anim.h" +#include "constants/rgb.h" + +struct HailStruct { + s32 x:10; + s32 y:10; + s32 bPosition:8; + s32 unk3:4; +}; + +static void sub_810B6C4(struct Sprite *); +static void sub_810B848(struct Sprite *); +static void AnimIcePunchSwirlingParticle(struct Sprite *); +static void AnimIceBeamParticle(struct Sprite *); +static void AnimIceEffectParticle(struct Sprite *); +static void AnimFlickerIceEffectParticle(struct Sprite *); +static void AnimSwirlingSnowball(struct Sprite *); +static void AnimSwirlingSnowball_Step1(struct Sprite *); +static void AnimSwirlingSnowball_Step2(struct Sprite *); +static void AnimSwirlingSnowball_End(struct Sprite *); +static void AnimMoveParticleBeyondTarget(struct Sprite *); +static void AnimWiggleParticleTowardsTarget(struct Sprite *); +static void AnimWaveFromCenterOfTarget(struct Sprite *); +static void InitSwirlingFogAnim(struct Sprite *); +static void AnimSwirlingFogAnim(struct Sprite *); +static void AnimThrowMistBall(struct Sprite *); +static void InitPoisonGasCloudAnim(struct Sprite *); +static void MovePoisonGasCloud(struct Sprite *); +static void AnimHailBegin(struct Sprite *); +static void AnimHailContinue(struct Sprite *); +static void InitIceBallAnim(struct Sprite *); +static void AnimThrowIceBall(struct Sprite *); +static void InitIceBallParticle(struct Sprite *); +static void AnimIceBallParticle(struct Sprite *); +static void AnimTask_Haze2(u8); +static void AnimTask_OverlayFogTiles(u8); +static void AnimTask_Hail2(u8); +static bool8 GenerateHailParticle(u8 hailStructId, u8 affineAnimNum, u8 taskId, u8 c); + +static const union AnimCmd gUnknown_08595A48[] = +{ + ANIMCMD_FRAME(0, 5, .hFlip = TRUE), + ANIMCMD_FRAME(1, 5, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_08595A54[] = +{ + gUnknown_08595A48, +}; + +// Unused +const struct SpriteTemplate gUnknown_08595A58 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810B6C4, +}; + +static const union AnimCmd gUnknown_08595A70[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_IceCrystalLarge[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_IceCrystalSmall[] = +{ + ANIMCMD_FRAME(6, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Snowball[] = +{ + ANIMCMD_FRAME(7, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_BlizzardIceCrystal[] = +{ + ANIMCMD_FRAME(8, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_SmallBubblePair[] = +{ + ANIMCMD_FRAME(12, 6), + ANIMCMD_FRAME(13, 6), + ANIMCMD_JUMP(0), +}; + +// Unused +static const union AnimCmd *const gUnknown_08595AA4[] = +{ + gUnknown_08595A70, +}; + +static const union AnimCmd *const sAnims_IceCrystalLarge[] = +{ + sAnim_IceCrystalLarge, +}; + +static const union AnimCmd *const sAnims_IceCrystalSmall[] = +{ + sAnim_IceCrystalSmall, +}; + +static const union AnimCmd *const sAnims_Snowball[] = +{ + sAnim_Snowball, +}; + +static const union AnimCmd *const sAnims_BlizzardIceCrystal[] = +{ + sAnim_BlizzardIceCrystal, +}; + +const union AnimCmd *const gAnims_SmallBubblePair[] = +{ + sAnim_SmallBubblePair, +}; + +static const union AffineAnimCmd sAffineAnim_IceCrystalSpiralInwardLarge[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 40, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sAffineAnims_IceCrystalSpiralInwardLarge[] = +{ + sAffineAnim_IceCrystalSpiralInwardLarge, +}; + +const struct SpriteTemplate gIceCrystalSpiralInwardLarge = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineDouble_ObjBlend_8x16, + .anims = sAnims_IceCrystalLarge, + .images = NULL, + .affineAnims = sAffineAnims_IceCrystalSpiralInwardLarge, + .callback = AnimIcePunchSwirlingParticle, +}; + +const struct SpriteTemplate gIceCrystalSpiralInwardSmall = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineOff_ObjBlend_8x8, + .anims = sAnims_IceCrystalSmall, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimIcePunchSwirlingParticle, +}; + +static const union AffineAnimCmd sAffineAnim_IceBeamInnerCrystal[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 10, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sAffineAnims_IceBeamInnerCrystal[] = +{ + sAffineAnim_IceBeamInnerCrystal, +}; + +const struct SpriteTemplate gIceBeamInnerCrystalSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineNormal_ObjBlend_8x16, + .anims = sAnims_IceCrystalLarge, + .images = NULL, + .affineAnims = sAffineAnims_IceBeamInnerCrystal, + .callback = AnimIceBeamParticle, +}; + +const struct SpriteTemplate gIceBeamOuterCrystalSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineOff_ObjBlend_8x8, + .anims = sAnims_IceCrystalSmall, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimIceBeamParticle, +}; + +static const union AffineAnimCmd sAffineAnim_IceCrystalHit[] = +{ + AFFINEANIMCMD_FRAME(0xCE, 0xCE, 0, 0), + AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 10), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 6), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_IceCrystalHit[] = +{ + sAffineAnim_IceCrystalHit, +}; + +const struct SpriteTemplate gIceCrystalHitLargeSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineNormal_ObjBlend_8x16, + .anims = sAnims_IceCrystalLarge, + .images = NULL, + .affineAnims = sAffineAnims_IceCrystalHit, + .callback = AnimIceEffectParticle, +}; + +const struct SpriteTemplate gIceCrystalHitSmallSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineNormal_ObjBlend_8x8, + .anims = sAnims_IceCrystalSmall, + .images = NULL, + .affineAnims = sAffineAnims_IceCrystalHit, + .callback = AnimIceEffectParticle, +}; + +const struct SpriteTemplate gSwirlingSnowballSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = sAnims_Snowball, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSwirlingSnowball, +}; + +const struct SpriteTemplate gBlizzardIceCrystalSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = sAnims_BlizzardIceCrystal, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMoveParticleBeyondTarget, +}; + +const struct SpriteTemplate gPowderSnowSnowballSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = sAnims_Snowball, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMoveParticleBeyondTarget, +}; + +static const union AnimCmd sAnim_IceGroundSpike[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(2, 5), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(6, 5), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(2, 5), + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_IceGroundSpike[] = +{ + sAnim_IceGroundSpike, +}; + +const struct SpriteTemplate gIceGroundSpikeSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_SPIKES, + .paletteTag = ANIM_TAG_ICE_SPIKES, + .oam = &gOamData_AffineOff_ObjBlend_8x16, + .anims = sAnims_IceGroundSpike, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWaveFromCenterOfTarget, +}; + +static const union AnimCmd sAnim_Cloud[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(8, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_Cloud[] = +{ + sAnim_Cloud, +}; + +const struct SpriteTemplate gMistCloudSpriteTemplate = +{ + .tileTag = ANIM_TAG_MIST_CLOUD, + .paletteTag = ANIM_TAG_MIST_CLOUD, + .oam = &gOamData_AffineOff_ObjBlend_32x16, + .anims = sAnims_Cloud, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = InitSwirlingFogAnim, +}; + +const struct SpriteTemplate gSmogCloudSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_GAS_CLOUD, + .paletteTag = ANIM_TAG_PURPLE_GAS_CLOUD, + .oam = &gOamData_AffineOff_ObjBlend_32x16, + .anims = sAnims_Cloud, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = InitSwirlingFogAnim, +}; + +static const u8 sUnknown_08595C5C[] = +{ + 0, 1, 2, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 6, 7, 8, 8, 8, 9, +}; + +const struct SpriteTemplate gMistBallSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimThrowMistBall, +}; + +static const u8 sUnknown_08595C88[] = +{ + 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, +}; + +const struct SpriteTemplate gPoisonGasCloudSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_GAS_CLOUD, + .paletteTag = ANIM_TAG_PURPLE_GAS_CLOUD, + .oam = &gOamData_AffineOff_ObjBlend_32x16, + .anims = sAnims_Cloud, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = InitPoisonGasCloudAnim, +}; + +static const struct HailStruct sHailCoordData[] = +{ + {.x = 100, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 2}, + {.x = 85, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 0}, + {.x = 242, .y = 120, .bPosition = B_POSITION_OPPONENT_LEFT, .unk3 = 1}, + {.x = 66, .y = 120, .bPosition = B_POSITION_PLAYER_RIGHT, .unk3 = 1}, + {.x = 182, .y = 120, .bPosition = B_POSITION_OPPONENT_RIGHT, .unk3 = 0}, + {.x = 60, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 2}, + {.x = 214, .y = 120, .bPosition = B_POSITION_OPPONENT_LEFT, .unk3 = 0}, + {.x = 113, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 1}, + {.x = 210, .y = 120, .bPosition = B_POSITION_OPPONENT_RIGHT, .unk3 = 1}, + {.x = 38, .y = 120, .bPosition = B_POSITION_PLAYER_RIGHT, .unk3 = 0}, +}; + +static const union AffineAnimCmd sAffineAnim_HailParticle_0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_HailParticle_1[] = +{ + AFFINEANIMCMD_FRAME(0xF0, 0xF0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_HailParticle_2[] = +{ + AFFINEANIMCMD_FRAME(0xE0, 0xE0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_WeatherBallIceDown[] = +{ + AFFINEANIMCMD_FRAME(0x150, 0x150, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_HailParticle[] = +{ + sAffineAnim_HailParticle_0, + sAffineAnim_HailParticle_1, + sAffineAnim_HailParticle_2, +}; + +static const union AffineAnimCmd *const sAffineAnims_WeatherBallIceDown[] = +{ + sAffineAnim_WeatherBallIceDown, +}; + +const struct SpriteTemplate gHailParticleSpriteTemplate = +{ + .tileTag = ANIM_TAG_HAIL, + .paletteTag = ANIM_TAG_HAIL, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_HailParticle, + .callback = AnimHailBegin, +}; + +const struct SpriteTemplate gWeatherBallIceDownSpriteTemplate = +{ + .tileTag = ANIM_TAG_HAIL, + .paletteTag = ANIM_TAG_HAIL, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_WeatherBallIceDown, + .callback = AnimWeatherBallDown, +}; + +static const union AnimCmd sAnim_IceBallChunk_0[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_IceBallChunk_1[] = +{ + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(48, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_IceBallChunk[] = +{ + sAnim_IceBallChunk_0, + sAnim_IceBallChunk_1, +}; + +static const union AffineAnimCmd sAffineAnim_IceBallChunk_0[] = +{ + AFFINEANIMCMD_FRAME(0xE0, 0xE0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_IceBallChunk_1[] = +{ + AFFINEANIMCMD_FRAME(0x118, 0x118, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_IceBallChunk_2[] = +{ + AFFINEANIMCMD_FRAME(0x150, 0x150, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_IceBallChunk_3[] = +{ + AFFINEANIMCMD_FRAME(0x180, 0x180, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_IceBallChunk_4[] = +{ + AFFINEANIMCMD_FRAME(0x1C0, 0x1C0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_IceBallChunk[] = +{ + sAffineAnim_IceBallChunk_0, + sAffineAnim_IceBallChunk_1, + sAffineAnim_IceBallChunk_2, + sAffineAnim_IceBallChunk_3, + sAffineAnim_IceBallChunk_4, +}; + +const struct SpriteTemplate gIceBallChunkSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CHUNK, + .paletteTag = ANIM_TAG_ICE_CHUNK, + .oam = &gOamData_AffineDouble_ObjNormal_32x32, + .anims = sAnims_IceBallChunk, + .images = NULL, + .affineAnims = sAffineAnims_IceBallChunk, + .callback = InitIceBallAnim, +}; + +const struct SpriteTemplate gIceBallImpactShardSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = sAnims_IceCrystalSmall, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = InitIceBallParticle, +}; + +// Unused +static void sub_810B6C4(struct Sprite *sprite) +{ + s16 targetX, targetY, attackerX, attackerY; + + sprite->oam.tileNum += 7; + targetX = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + targetY = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + attackerX = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + attackerY = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = gBattleAnimArgs[0] + attackerX; + sprite->data[2] = gBattleAnimArgs[2] + targetX; + sprite->data[3] = gBattleAnimArgs[1] + attackerY; + sprite->data[4] = gBattleAnimArgs[3] + targetY; + sub_80A64EC(sprite); + + for (;(targetX >= -32 && targetX <= 272) && (targetY >= -32 && targetY <= 192); + targetX += sprite->data[1], targetY += sprite->data[2]) + ; + + sprite->data[1] = -sprite->data[1]; + sprite->data[2] = -sprite->data[2]; + for (;(attackerX >= -32 && attackerX <= 272) && (attackerY >= -32 && attackerY <= 192); + attackerX += sprite->data[1], attackerY += sprite->data[2]) + ; + + sprite->pos1.x = attackerX; + sprite->pos1.y = attackerY; + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = attackerX; + sprite->data[2] = targetX; + sprite->data[3] = attackerY; + sprite->data[4] = targetY; + sub_80A64EC(sprite); + sprite->data[3] = gBattleAnimArgs[5]; + sprite->data[4] = gBattleAnimArgs[6]; + sprite->callback = sub_810B848; +} + +static void sub_810B848(struct Sprite *sprite) +{ + if (sprite->data[0] != 0) + { + sprite->data[5] += sprite->data[1]; + sprite->data[6] += sprite->data[2]; + sprite->pos2.x = sprite->data[5]; + sprite->pos2.y = sprite->data[6]; + sprite->pos2.x += Sin(sprite->data[7], sprite->data[3]); + sprite->pos2.y += Sin(sprite->data[7], sprite->data[3]); + sprite->data[7] = (sprite->data[7] + sprite->data[4]) & 0xFF; + sprite->data[0]--; + } + else + { + DestroyAnimSprite(sprite); + } +} + +// Animates the swirling ice crystals in Ice Punch. +// arg 0: initial position angle around circle (0-256) +static void AnimIcePunchSwirlingParticle(struct Sprite *sprite) +{ + sprite->data[0] = gBattleAnimArgs[0]; + sprite->data[1] = 60; + sprite->data[2] = 9; + sprite->data[3] = 30; + sprite->data[4] = -512; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = TranslateSpriteInGrowingCircleOverDuration; + sprite->callback(sprite); +} + +// Animates the ice particles in Ice Beam. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: duration +static void AnimIceBeamParticle(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->data[2] -= gBattleAnimArgs[2]; + else + sprite->data[2] += gBattleAnimArgs[2]; + + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; + sprite->data[0] = gBattleAnimArgs[4]; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = StartAnimLinearTranslation; +} + +// Animates the ice crystals at the end of Ice Punch, Ice Beam, Tri Attack, +// Weather Ball (Hail), Blizzard, and Powder Snow. +// arg 0: target x offset +// arg 1: target y offset +// arg 2: ??? unknown boolean +static void AnimIceEffectParticle(struct Sprite *sprite) +{ + if (gBattleAnimArgs[2] == 0) + { + InitSpritePosToAnimTarget(sprite, TRUE); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + + StoreSpriteCallbackInData6(sprite, AnimFlickerIceEffectParticle); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; +} + +static void AnimFlickerIceEffectParticle(struct Sprite *sprite) +{ + sprite->invisible ^= 1; + sprite->data[0] += 1; + if (sprite->data[0] == 20) + DestroySpriteAndMatrix(sprite); +} + +// Animates the small snowballs that swirl around the target in Blizzard and Icy Wind. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: particle speed +// arg 5: multiple targets? (boolean) +static void AnimSwirlingSnowball(struct Sprite *sprite) +{ + int i; + s16 tempDataHolder[8]; + + InitSpritePosToAnimAttacker(sprite, TRUE); + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + + if (!gBattleAnimArgs[5]) + { + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); + } + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->data[2] -= gBattleAnimArgs[2]; + else + sprite->data[2] += gBattleAnimArgs[2]; + + for (i = 0; i < 8; i++) + tempDataHolder[i] = sprite->data[i]; + + InitAnimFastLinearTranslationWithSpeed(sprite); + sprite->data[1] ^= 1; + sprite->data[2] ^= 1; + + while (1) + { + sprite->data[0] = 1; + AnimFastTranslateLinear(sprite); + + if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 + || sprite->pos1.y + sprite->pos2.y > 160 + || sprite->pos1.y + sprite->pos2.y < -16) + break; + } + + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + + for (i = 0; i < 8; i++) + sprite->data[i] = tempDataHolder[i]; + + sprite->callback = sub_80A718C; + StoreSpriteCallbackInData6(sprite, AnimSwirlingSnowball_Step1); +} + +static void AnimSwirlingSnowball_Step1(struct Sprite *sprite) +{ + s16 tempVar; + + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + sprite->data[0] = 128; + + tempVar = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 20 : -20; + + sprite->data[3] = Sin(sprite->data[0], tempVar); + sprite->data[4] = Cos(sprite->data[0], 0xF); + sprite->data[5] = 0; + sprite->callback = AnimSwirlingSnowball_Step2; + sprite->callback(sprite); +} + +static void AnimSwirlingSnowball_Step2(struct Sprite *sprite) +{ + s16 tempVar; + tempVar = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 20 : -20; + + if (sprite->data[5] <= 31) + { + sprite->pos2.x = Sin(sprite->data[0], tempVar) - sprite->data[3]; + sprite->pos2.y = Cos(sprite->data[0], 15) - sprite->data[4]; + sprite->data[0] = (sprite->data[0] + 16) & 0xFF; + sprite->data[5] += 1; + } + else + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + sprite->data[4] = 0; + sprite->data[3] = 0; + sprite->callback = AnimSwirlingSnowball_End; + } +} + +static void AnimSwirlingSnowball_End(struct Sprite *sprite) +{ + sprite->data[0] = 1; + AnimFastTranslateLinear(sprite); + + if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 + || sprite->pos1.y + sprite->pos2.y > 256 + || sprite->pos1.y + sprite->pos2.y < -16) + DestroyAnimSprite(sprite); +} + +// Moves particles towards the target mon and off the screen. Used to animate +// the large snowballs in Blizzard and the small snowballs in Powder Snow. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: speed +// arg 5: wave amplitude +// arg 6: wave frequency +// arg 7: multiple targets? (boolean) +static void AnimMoveParticleBeyondTarget(struct Sprite *sprite) +{ + int i; + s16 tempDataHolder[8]; + + InitSpritePosToAnimAttacker(sprite, TRUE); + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + + if (!gBattleAnimArgs[7]) + { + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); + } + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->data[2] -= gBattleAnimArgs[2]; + else + sprite->data[2] += gBattleAnimArgs[2]; + + sprite->data[4] += gBattleAnimArgs[3]; + InitAnimFastLinearTranslationWithSpeed(sprite); + for (i = 0; i < 8; i++) + tempDataHolder[i] = sprite->data[i]; + + sprite->data[1] ^= 1; + sprite->data[2] ^= 1; + + while (1) + { + sprite->data[0] = 1; + AnimFastTranslateLinear(sprite); + if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 + || sprite->pos1.y + sprite->pos2.y > 160 + || sprite->pos1.y + sprite->pos2.y < -16) + break; + } + + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + + for (i = 0; i < 8; i++) + sprite->data[i] = tempDataHolder[i]; + + sprite->data[5] = gBattleAnimArgs[5]; + sprite->data[6] = gBattleAnimArgs[6]; + sprite->callback = AnimWiggleParticleTowardsTarget; +} + +// Moves particles in a sine wave towards the target. +static void AnimWiggleParticleTowardsTarget(struct Sprite *sprite) +{ + AnimFastTranslateLinear(sprite); + if (sprite->data[0] == 0) + sprite->data[0] = 1; + + sprite->pos2.y += Sin(sprite->data[7], sprite->data[5]); + sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; + if (sprite->data[0] == 1) + { + if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 + || sprite->pos1.y + sprite->pos2.y > 160 + || sprite->pos1.y + sprite->pos2.y < -16) + DestroyAnimSprite(sprite); + } +} + +// Animates the ice pilar wave used by Icy Wind. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: ??? unknown boolean +static void AnimWaveFromCenterOfTarget(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + if (gBattleAnimArgs[2] == 0) + { + InitSpritePosToAnimTarget(sprite, FALSE); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + + sprite->data[0]++; + } + else + { + if (sprite->animEnded) + DestroyAnimSprite(sprite); + } +} + +// Animates the fog that swirls around the mon in Mist and Smog. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: change in y pixels per rotation +// arg 3: duration +// arg 4: animate on opponent? (boolean) +// arg 5: ??? unknown boolean +static void InitSwirlingFogAnim(struct Sprite *sprite) +{ + s16 tempVar; + u8 battler; + + if (gBattleAnimArgs[4] == 0) + { + if (gBattleAnimArgs[5] == 0) + { + InitSpritePosToAnimAttacker(sprite, FALSE); + } + else + { + SetAverageBattlerPositions(gBattleAnimAttacker, 0, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + + sprite->pos1.y += gBattleAnimArgs[1]; + } + + battler = gBattleAnimAttacker; + } + else + { + if (gBattleAnimArgs[5] == 0) + { + InitSpritePosToAnimTarget(sprite, FALSE); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + + sprite->pos1.y += gBattleAnimArgs[1]; + } + + battler = gBattleAnimTarget; + } + + sprite->data[7] = battler; + if (gBattleAnimArgs[5] == 0 || !IsDoubleBattle()) + tempVar = 0x20; + else + tempVar = 0x40; + + sprite->data[6] = tempVar; + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + sprite->pos1.y += 8; + + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[2]; + + InitAnimLinearTranslation(sprite); + + sprite->data[5] = 64; + sprite->callback = AnimSwirlingFogAnim; + sprite->callback(sprite); +} + +// Animates swirling fog initialized by InitSwirlingFogAnim. +static void AnimSwirlingFogAnim(struct Sprite *sprite) +{ + if (!AnimTranslateLinear(sprite)) + { + sprite->pos2.x += Sin(sprite->data[5], sprite->data[6]); + sprite->pos2.y += Cos(sprite->data[5], -6); + + if ((u16)(sprite->data[5] - 64) <= 0x7F) + sprite->oam.priority = GetBattlerSpriteBGPriority(sprite->data[7]); + else + sprite->oam.priority = GetBattlerSpriteBGPriority(sprite->data[7]) + 1; + + sprite->data[5] = (sprite->data[5] + 3) & 0xFF; + } + else + { + DestroyAnimSprite(sprite); + } +} + +// Adds moving foggy overlay. Used by Haze. +void AnimTask_HazeScrollingFog(u8 taskId) +{ + struct BattleAnimBgData animBg; + + 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, 0); + + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); + + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); + SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); + + sub_80A6B30(&animBg); + LoadBgTiles(animBg.bgId, gWeatherFogHorizontalTiles, 0x800, animBg.tilesOffset); + AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimFogTilemap, 0); + LoadPalette(&gUnknown_083970E8, animBg.paletteId * 16, 32); + + gTasks[taskId].func = AnimTask_Haze2; +} + +static void AnimTask_Haze2(u8 taskId) +{ + struct BattleAnimBgData animBg; + + gBattle_BG1_X += -1; + gBattle_BG1_Y += 0; + + switch (gTasks[taskId].data[12]) + { + case 0: + if (++gTasks[taskId].data[10] == 4) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[9]++; + gTasks[taskId].data[11] = sUnknown_08595C5C[gTasks[taskId].data[9]]; + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 9) + { + gTasks[taskId].data[12]++; + gTasks[taskId].data[11] = 0; + } + } + break; + case 1: + if (++gTasks[taskId].data[11] == 0x51) + { + gTasks[taskId].data[11] = 9; + gTasks[taskId].data[12]++; + } + break; + case 2: + if (++gTasks[taskId].data[10] == 4) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11]--; + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 0) + { + gTasks[taskId].data[12]++; + gTasks[taskId].data[11] = 0; + } + } + break; + case 3: + sub_80A6B30(&animBg); + sub_80A6C68(1); + sub_80A6C68(2); + + gTasks[taskId].data[12]++; + + // fall through + case 4: + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); + + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + DestroyAnimVisualTask(taskId); + break; + } +} + +// Throws the ball in Mist Ball. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: targey x offset +// arg 3: target y offset +// arg 4: duration +// arg 5: ??? unknown (seems to vibrate target mon somehow) +static void AnimThrowMistBall(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->callback = TranslateAnimSpriteToTargetMonLocation; +} + +// Displays misty background in Mist Ball. +void AnimTask_LoadMistTiles(u8 taskId) +{ + struct BattleAnimBgData animBg; + + 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, 0); + + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); + + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); + SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); + + sub_80A6B30(&animBg); + LoadBgTiles(animBg.bgId, gWeatherFogHorizontalTiles, 0x800, animBg.tilesOffset); + AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimFogTilemap, 0); + LoadPalette(&gUnknown_083970E8, animBg.paletteId * 16, 32); + + gTasks[taskId].data[15] = -1; + gTasks[taskId].func = AnimTask_OverlayFogTiles; +} + +static void AnimTask_OverlayFogTiles(u8 taskId) +{ + struct BattleAnimBgData animBg; + + gBattle_BG1_X += gTasks[taskId].data[15]; + gBattle_BG1_Y += 0; + + switch (gTasks[taskId].data[12]) + { + case 0: + gTasks[taskId].data[9] += 1; + gTasks[taskId].data[11] = sUnknown_08595C88[gTasks[taskId].data[9]]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 17 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 5) + { + gTasks[taskId].data[12]++; + gTasks[taskId].data[11] = 0; + } + break; + case 1: + if (++gTasks[taskId].data[11] == 0x51) + { + gTasks[taskId].data[11] = 5; + gTasks[taskId].data[12]++; + } + break; + case 2: + if (++gTasks[taskId].data[10] == 4) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] -= 1; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 0) + { + gTasks[taskId].data[12]++; + gTasks[taskId].data[11] = 0; + } + } + break; + case 3: + sub_80A6B30(&animBg); + sub_80A6C68(1); + sub_80A6C68(2); + + gTasks[taskId].data[12]++; + + // fall through + case 4: + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); + + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + DestroyAnimVisualTask(taskId); + break; + } +} + +// Initializes gas clouds in the Poison Gas animation. +// arg 0: duration +// arg 1: ? target x offset +// arg 2: ? target y offset +// arg 3: ? swirl start x +// arg 4: ? swirl start y +// arg 5: ??? unknown +// arg 6: ??? unknown +// arg 7: ??? unknown boolean +static void InitPoisonGasCloudAnim(struct Sprite *sprite) +{ + sprite->data[0] = gBattleAnimArgs[0]; + + if (GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) < GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2)) + sprite->data[7] = 0x8000; + + if ((gBattlerPositions[gBattleAnimTarget] & BIT_SIDE) == B_SIDE_PLAYER) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + + if ((sprite->data[7] & 0x8000) && (gBattlerPositions[gBattleAnimAttacker] & BIT_SIDE) == B_SIDE_PLAYER) + sprite->subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority + 1; + + sprite->data[6] = 1; + } + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + if (gBattleAnimArgs[7]) + { + sprite->data[1] = sprite->pos1.x + gBattleAnimArgs[1]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[3]; + sprite->data[3] = sprite->pos1.y + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[4]; + sprite->data[7] |= GetBattlerSpriteBGPriority(gBattleAnimTarget) << 8; + } + else + { + sprite->data[1] = sprite->pos1.x + gBattleAnimArgs[1]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X) + gBattleAnimArgs[3]; + sprite->data[3] = sprite->pos1.y + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + gBattleAnimArgs[4]; + sprite->data[7] |= GetBattlerSpriteBGPriority(gBattleAnimTarget) << 8; + } + + if (IsContest()) + { + sprite->data[6] = 1; + sprite->subpriority = 0x80; + } + + InitAnimLinearTranslation(sprite); + sprite->callback = MovePoisonGasCloud; +} + +static void MovePoisonGasCloud(struct Sprite *sprite) +{ + int value; + + switch (sprite->data[7] & 0xFF) + { + case 0: + AnimTranslateLinear(sprite); + value = gSineTable[sprite->data[5]]; + sprite->pos2.x += value >> 4; + if (sprite->data[6]) + sprite->data[5] = (sprite->data[5] - 8) & 0xFF; + else + sprite->data[5] = (sprite->data[5] + 8) & 0xFF; + + if (sprite->data[0] <= 0) + { + sprite->data[0] = 80; + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X); + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x; + sprite->pos1.y += sprite->pos2.y; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y + 29; + sprite->data[7]++; + if (IsContest()) + sprite->data[5] = 80; + else if (GET_BATTLER_SIDE2(gBattleAnimTarget) != B_SIDE_PLAYER) + sprite->data[5] = 204; + else + sprite->data[5] = 80; + + sprite->pos2.y = 0; + value = gSineTable[sprite->data[5]]; + sprite->pos2.x = value >> 3; + sprite->data[5] = (sprite->data[5] + 2) & 0xFF; + InitAnimLinearTranslation(sprite); + } + break; + case 1: + AnimTranslateLinear(sprite); + value = gSineTable[sprite->data[5]]; + sprite->pos2.x += value >> 3; + sprite->pos2.y += (gSineTable[sprite->data[5] + 0x40] * -3) >> 8; + if (!IsContest()) + { + u16 var0 = sprite->data[5] - 0x40; + if (var0 <= 0x7F) + sprite->oam.priority = sprite->data[7] >> 8; + else + sprite->oam.priority = (sprite->data[7] >> 8) + 1; + + sprite->data[5] = (sprite->data[5] + 4) & 0xFF; + } + else + { + u16 var0 = sprite->data[5] - 0x40; + if (var0 <= 0x7F) + sprite->subpriority = 128; + else + sprite->subpriority = 140; + + sprite->data[5] = (sprite->data[5] - 4) & 0xFF; + } + + if (sprite->data[0] <= 0) + { + sprite->data[0] = 0x300; + sprite->data[1] = sprite->pos1.x += sprite->pos2.x; + sprite->data[3] = sprite->pos1.y += sprite->pos2.y; + sprite->data[4] = sprite->pos1.y + 4; + if (IsContest()) + sprite->data[2] = -0x10; + else if (GET_BATTLER_SIDE2(gBattleAnimTarget) != B_SIDE_PLAYER) + sprite->data[2] = 0x100; + else + sprite->data[2] = -0x10; + + sprite->data[7]++; + sprite->pos2.x = sprite->pos2.y = 0; + sub_80A6FD4(sprite); + } + break; + case 2: + if (AnimTranslateLinear(sprite)) + { + if (sprite->oam.affineMode & 1) + { + FreeOamMatrix(sprite->oam.matrixNum); + sprite->oam.affineMode = ST_OAM_AFFINE_OFF; + } + + DestroySprite(sprite); + gAnimVisualTaskCount--; + } + break; + } +} + +void AnimTask_Hail(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->func = AnimTask_Hail2; +} + +static void AnimTask_Hail2(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + switch (task->data[0]) + { + case 0: + if (++task->data[4] > 2) + { + task->data[4] = 0; + task->data[5] = 0; + task->data[2] = 0; + task->data[0]++; + } + break; + case 1: + if (task->data[5] == 0) + { + if (GenerateHailParticle(task->data[3], task->data[2], taskId, 1)) + task->data[1]++; + + if (++task->data[2] == 3) + { + if (++task->data[3] == 10) + task->data[0]++; + else + task->data[0]--; + } + else + { + task->data[5] = 1; + } + + } + else + { + task->data[5]--; + } + break; + case 2: + if (task->data[1] == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + +static bool8 GenerateHailParticle(u8 hailStructId, u8 affineAnimNum, u8 taskId, u8 c) +{ + u8 id; + s16 battlerX, battlerY; + s16 spriteX; + bool8 possibleBool = FALSE; + s8 unk = sHailCoordData[hailStructId].unk3; + + if (unk != 2) + { + id = GetBattlerAtPosition(sHailCoordData[hailStructId].bPosition); + if (IsBattlerSpriteVisible(id)) + { + possibleBool = TRUE; + battlerX = GetBattlerSpriteCoord(id, BATTLER_COORD_X_2); + battlerY = GetBattlerSpriteCoord(id, BATTLER_COORD_Y_PIC_OFFSET); + switch (unk) + { + case 0: + battlerX -= GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_WIDTH) / 6; + battlerY -= GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_HEIGHT) / 6; + break; + case 1: + battlerX += GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_WIDTH) / 6; + battlerY += GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_HEIGHT) / 6; + break; + } + } + else + { + battlerX = (sHailCoordData[hailStructId].x); + battlerY = (sHailCoordData[hailStructId].y); + } + } + else + { + battlerX = (sHailCoordData[hailStructId].x); + battlerY = (sHailCoordData[hailStructId].y); + } + spriteX = battlerX - ((battlerY + 8) / 2); + id = CreateSprite(&gHailParticleSpriteTemplate, spriteX, -8, 18); + if (id == MAX_SPRITES) + { + return FALSE; + } + else + { + StartSpriteAffineAnim(&gSprites[id], affineAnimNum); + gSprites[id].data[0] = possibleBool; + gSprites[id].data[3] = battlerX; + gSprites[id].data[4] = battlerY; + gSprites[id].data[5] = affineAnimNum; + gSprites[id].data[6] = taskId; + gSprites[id].data[7] = c; + return TRUE; + } +} + +static void AnimHailBegin(struct Sprite *sprite) +{ + u8 spriteId; + + sprite->pos1.x += 4; + sprite->pos1.y += 8; + + if (sprite->pos1.x < sprite->data[3] && sprite->pos1.y < sprite->data[4]) + return; + + if (sprite->data[0] == 1 && sprite->data[5] == 0) + { + spriteId = CreateSprite(&gIceCrystalHitLargeSpriteTemplate, + sprite->data[3], sprite->data[4], sprite->subpriority); + + sprite->data[0] = spriteId; + if (spriteId != 64) + { + gSprites[sprite->data[0]].callback = AnimHailContinue; + gSprites[sprite->data[0]].data[6] = sprite->data[6]; + gSprites[sprite->data[0]].data[7] = sprite->data[7]; + } + + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } + else + { + gTasks[sprite->data[6]].data[sprite->data[7]]--; + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } +} + +static void AnimHailContinue(struct Sprite *sprite) +{ + if (++sprite->data[0] == 20) + { + gTasks[sprite->data[6]].data[sprite->data[7]]--; + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } +} + +// Initializes the animation for Ice Ball. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: duration +// arg 5: arc height (negative) +static void InitIceBallAnim(struct Sprite *sprite) +{ + u8 animNum = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer - 1; + + if (animNum > 4) + animNum = 4; + + StartSpriteAffineAnim(sprite, animNum); + InitSpritePosToAnimAttacker(sprite, 1); + + sprite->data[0] = gBattleAnimArgs[4]; + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; + sprite->data[5] = gBattleAnimArgs[5]; + + InitAnimArcTranslation(sprite); + + sprite->callback = AnimThrowIceBall; +} + +// Throws the ball of ice in Ice Ball. +static void AnimThrowIceBall(struct Sprite *sprite) +{ + if (!TranslateAnimHorizontalArc(sprite)) + return; + + StartSpriteAnim(sprite, 1); + sprite->callback = RunStoredCallbackWhenAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Initializes the particles that scatter at the end of the Ice Ball animation. +static void InitIceBallParticle(struct Sprite *sprite) +{ + s16 randA, randB; + + sprite->oam.tileNum += 8; + InitSpritePosToAnimTarget(sprite, TRUE); + + randA = (Random2() & 0xFF) + 256; + randB = Random2() & 0x1FF; + + if (randB > 0xFF) + randB = 256 - randB; + + sprite->data[1] = randA; + sprite->data[2] = randB; + sprite->callback = AnimIceBallParticle; +} + +// Animates the particles created by InitIceBallParticle. +static void AnimIceBallParticle(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_GetIceBallCounter(u8 taskId) +{ + u8 arg = gBattleAnimArgs[0]; + + gBattleAnimArgs[arg] = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer - 1; + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_anim_normal.c b/src/battle_anim_normal.c new file mode 100644 index 000000000..f7df9a4a9 --- /dev/null +++ b/src/battle_anim_normal.c @@ -0,0 +1,1023 @@ +#include "global.h" +#include "battle_anim.h" +#include "palette.h" +#include "random.h" +#include "task.h" +#include "trig.h" +#include "constants/rgb.h" + +static void AnimConfusionDuck(struct Sprite *); +static void AnimSimplePaletteBlend(struct Sprite *); +static void AnimSimplePaletteBlend_Step(struct Sprite *); +static void AnimComplexPaletteBlend(struct Sprite *); +static void AnimComplexPaletteBlend_Step1(struct Sprite *); +static void AnimComplexPaletteBlend_Step2(struct Sprite *); +static void sub_81159B4(struct Sprite *); +static void AnimShakeMonOrBattleTerrain(struct Sprite *); +static void AnimShakeMonOrBattleTerrain_Step(struct Sprite *); +static void AnimShakeMonOrBattleTerrain_UpdateCoordOffsetEnabled(void); +static void AnimHitSplatBasic(struct Sprite *); +static void AnimHitSplatPersistent(struct Sprite *); +static void AnimHitSplatHandleInvert(struct Sprite *); +static void AnimHitSplatRandom(struct Sprite *); +static void AnimHitSplatOnMonEdge(struct Sprite *); +static void AnimCrossImpact(struct Sprite *); +static void AnimFlashingHitSplat(struct Sprite *); +static void AnimFlashingHitSplat_Step(struct Sprite *); +static void AnimConfusionDuck_Step(struct Sprite *); +static void BlendColorCycle(u8, u8, u8); +static void AnimTask_BlendColorCycleLoop(u8); +static void BlendColorCycleExclude(u8, u8, u8); +static void AnimTask_BlendColorCycleExcludeLoop(u8); +static void BlendColorCycleByTag(u8, u8, u8); +static void AnimTask_BlendColorCycleByTagLoop(u8); +static void AnimTask_FlashAnimTagWithColor_Step1(u8); +static void AnimTask_FlashAnimTagWithColor_Step2(u8); +static void AnimTask_ShakeBattleTerrain_Step(u8); + +static const union AnimCmd sAnim_ConfusionDuck_0[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(4, 8), + ANIMCMD_FRAME(0, 8, .hFlip = TRUE), + ANIMCMD_FRAME(8, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sAnim_ConfusionDuck_1[] = +{ + ANIMCMD_FRAME(0, 8, .hFlip = TRUE), + ANIMCMD_FRAME(4, 8), + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(8, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sAnims_ConfusionDuck[] = +{ + sAnim_ConfusionDuck_0, + sAnim_ConfusionDuck_1, +}; + +const struct SpriteTemplate gConfusionDuckSpriteTemplate = +{ + .tileTag = ANIM_TAG_DUCK, + .paletteTag = ANIM_TAG_DUCK, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = sAnims_ConfusionDuck, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimConfusionDuck, +}; + +const struct SpriteTemplate gSimplePaletteBlendSpriteTemplate = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSimplePaletteBlend, +}; + +const struct SpriteTemplate gComplexPaletteBlendSpriteTemplate = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimComplexPaletteBlend, +}; + +static const union AnimCmd gUnknown_085972A4[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_FRAME(64, 3), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_085972BC[] = +{ + gUnknown_085972A4, +}; + +// Unused +const struct SpriteTemplate gUnknown_085972C0 = +{ + .tileTag = ANIM_TAG_SPARKLE_4, + .paletteTag = ANIM_TAG_SPARKLE_4, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gUnknown_085972BC, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_81159B4, +}; + +const struct SpriteTemplate gShakeMonOrTerrainSpriteTemplate = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimShakeMonOrBattleTerrain, +}; + +static const union AffineAnimCmd sAffineAnim_HitSplat_0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_HitSplat_1[] = +{ + AFFINEANIMCMD_FRAME(0xD8, 0xD8, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_HitSplat_2[] = +{ + AFFINEANIMCMD_FRAME(0xB0, 0xB0, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_HitSplat_3[] = +{ + AFFINEANIMCMD_FRAME(0x80, 0x80, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_HitSplat[] = +{ + sAffineAnim_HitSplat_0, + sAffineAnim_HitSplat_1, + sAffineAnim_HitSplat_2, + sAffineAnim_HitSplat_3, +}; + +const struct SpriteTemplate gBasicHitSplatSpriteTemplate = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_AffineNormal_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_HitSplat, + .callback = AnimHitSplatBasic, +}; + +const struct SpriteTemplate gHandleInvertHitSplatSpriteTemplate = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_AffineNormal_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_HitSplat, + .callback = AnimHitSplatHandleInvert, +}; + +const struct SpriteTemplate gWaterHitSplatSpriteTemplate = +{ + .tileTag = ANIM_TAG_WATER_IMPACT, + .paletteTag = ANIM_TAG_WATER_IMPACT, + .oam = &gOamData_AffineNormal_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_HitSplat, + .callback = AnimHitSplatBasic, +}; + +const struct SpriteTemplate gRandomPosHitSplatSpriteTemplate = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_AffineNormal_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_HitSplat, + .callback = AnimHitSplatRandom, +}; + +const struct SpriteTemplate gMonEdgeHitSplatSpriteTemplate = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_AffineNormal_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_HitSplat, + .callback = AnimHitSplatOnMonEdge, +}; + +const struct SpriteTemplate gCrossImpactSpriteTemplate = +{ + .tileTag = ANIM_TAG_CROSS_IMPACT, + .paletteTag = ANIM_TAG_CROSS_IMPACT, + .oam = &gOamData_AffineOff_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimCrossImpact, +}; + +const struct SpriteTemplate gFlashingHitSplatSpriteTemplate = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_HitSplat, + .callback = AnimFlashingHitSplat, +}; + +const struct SpriteTemplate gPersistHitSplatSpriteTemplate = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_AffineNormal_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_HitSplat, + .callback = AnimHitSplatPersistent, +}; + +// Moves a spinning duck around the mon's head. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: initial wave offset +// arg 3: wave period (higher means faster wave) +// arg 4: duration +static void AnimConfusionDuck(struct Sprite *sprite) +{ + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[2]; + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->data[1] = -gBattleAnimArgs[3]; + sprite->data[4] = 1; + } + else + { + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[4] = 0; + StartSpriteAnim(sprite, 1); + } + + sprite->data[3] = gBattleAnimArgs[4]; + sprite->callback = AnimConfusionDuck_Step; + sprite->callback(sprite); +} + +static void AnimConfusionDuck_Step(struct Sprite *sprite) +{ + sprite->pos2.x = Cos(sprite->data[0], 30); + sprite->pos2.y = Sin(sprite->data[0], 10); + + if ((u16)sprite->data[0] < 128) + sprite->oam.priority = 1; + else + sprite->oam.priority = 3; + + sprite->data[0] = (sprite->data[0] + sprite->data[1]) & 0xFF; + if (++sprite->data[2] == sprite->data[3]) + DestroyAnimSprite(sprite); +} + +// Performs a simple color blend on a specified sprite. +// arg 0: palette selector +// arg 1: delay +// arg 2: start blend amount +// arg 3: end blend amount +// arg 4: blend color +static void AnimSimplePaletteBlend(struct Sprite *sprite) +{ + u32 selectedPalettes = UnpackSelectedBattleAnimPalettes(gBattleAnimArgs[0]); + BeginNormalPaletteFade(selectedPalettes, gBattleAnimArgs[1], gBattleAnimArgs[2], gBattleAnimArgs[3], gBattleAnimArgs[4]); + sprite->invisible = TRUE; + sprite->callback = AnimSimplePaletteBlend_Step; +} + +// Unpacks a bitfield and returns a bitmask of its selected palettes. +// Bits 0-6 of the selector parameter result in the following palettes being selected: +// 0: battle background palettes (BG palettes 1, 2, and 3) +// 1: gBattleAnimAttacker OBJ palette +// 2: gBattleAnimTarget OBJ palette +// 3: gBattleAnimAttacker partner OBJ palette +// 4: gBattleAnimTarget partner OBJ palette +// 5: BG palette 4 +// 6: BG palette 5 +u32 UnpackSelectedBattleAnimPalettes(s16 selector) +{ + u8 battleBackground = selector & 1; + u8 attacker = (selector >> 1) & 1; + u8 target = (selector >> 2) & 1; + u8 attackerPartner = (selector >> 3) & 1; + u8 targetPartner = (selector >> 4) & 1; + u8 arg5 = (selector >> 5) & 1; + u8 arg6 = (selector >> 6) & 1; + return sub_80A75AC(battleBackground, attacker, target, attackerPartner, targetPartner, arg5, arg6); +} + +static void AnimSimplePaletteBlend_Step(struct Sprite *sprite) +{ + if (!gPaletteFade.active) + DestroyAnimSprite(sprite); +} + +static void AnimComplexPaletteBlend(struct Sprite *sprite) +{ + u32 selectedPalettes; + + sprite->data[0] = gBattleAnimArgs[1]; + sprite->data[1] = gBattleAnimArgs[1]; + sprite->data[2] = gBattleAnimArgs[2]; + sprite->data[3] = gBattleAnimArgs[3]; + sprite->data[4] = gBattleAnimArgs[4]; + sprite->data[5] = gBattleAnimArgs[5]; + sprite->data[6] = gBattleAnimArgs[6]; + sprite->data[7] = gBattleAnimArgs[0]; + + selectedPalettes = UnpackSelectedBattleAnimPalettes(sprite->data[7]); + BlendPalettes(selectedPalettes, gBattleAnimArgs[4], gBattleAnimArgs[3]); + sprite->invisible = TRUE; + sprite->callback = AnimComplexPaletteBlend_Step1; +} + +static void AnimComplexPaletteBlend_Step1(struct Sprite *sprite) +{ + u32 selectedPalettes; + + if (sprite->data[0] > 0) + { + sprite->data[0]--; + return; + } + + if (gPaletteFade.active) + return; + + if (sprite->data[2] == 0) + { + sprite->callback = AnimComplexPaletteBlend_Step2; + return; + } + + selectedPalettes = UnpackSelectedBattleAnimPalettes(sprite->data[7]); + if (sprite->data[1] & 0x100) + BlendPalettes(selectedPalettes, sprite->data[4], sprite->data[3]); + else + BlendPalettes(selectedPalettes, sprite->data[6], sprite->data[5]); + + sprite->data[1] ^= 0x100; + sprite->data[0] = sprite->data[1] & 0xFF; + sprite->data[2]--; +} + +static void AnimComplexPaletteBlend_Step2(struct Sprite *sprite) +{ + u32 selectedPalettes; + + if (!gPaletteFade.active) + { + selectedPalettes = UnpackSelectedBattleAnimPalettes(sprite->data[7]); + BlendPalettes(selectedPalettes, 0, 0); + DestroyAnimSprite(sprite); + } +} + +static void sub_81159B4(struct Sprite *sprite) +{ + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = 0; + sprite->data[1] = 10; + sprite->data[2] = 8; + sprite->data[3] = 40; + sprite->data[4] = 112; + sprite->data[5] = 0; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = TranslateSpriteInGrowingCircleOverDuration; + sprite->callback(sprite); +} + +// Task data for AnimTask_BlendColorCycle, AnimTask_BlendColorCycleExclude, and AnimTask_BlendColorCycleByTag +#define tPalSelector data[0] // AnimTask_BlendColorCycle +#define tPalTag data[0] // AnimTask_BlendColorCycleByTag +#define tDelay data[1] +#define tNumBlends data[2] +#define tInitialBlendY data[3] +#define tTargetBlendY data[4] +#define tBlendColor data[5] +#define tRestoreBlend data[8] +#define tPalSelectorHi data[9] +#define tPalSelectorLo data[10] + +// Blends mon/screen to designated color or back alternately tNumBlends times +// Many uses of this task only set a tNumBlends of 2, which has the effect of blending to a color and back once +void AnimTask_BlendColorCycle(u8 taskId) +{ + gTasks[taskId].tPalSelector = gBattleAnimArgs[0]; + gTasks[taskId].tDelay = gBattleAnimArgs[1]; + gTasks[taskId].tNumBlends = gBattleAnimArgs[2]; + gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3]; + gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4]; + gTasks[taskId].tBlendColor = gBattleAnimArgs[5]; + gTasks[taskId].tRestoreBlend = FALSE; + BlendColorCycle(taskId, 0, gTasks[taskId].tTargetBlendY); + gTasks[taskId].func = AnimTask_BlendColorCycleLoop; +} + +static void BlendColorCycle(u8 taskId, u8 startBlendAmount, u8 targetBlendAmount) +{ + u32 selectedPalettes = UnpackSelectedBattleAnimPalettes(gTasks[taskId].tPalSelector); + BeginNormalPaletteFade( + selectedPalettes, + gTasks[taskId].tDelay, + startBlendAmount, + targetBlendAmount, + gTasks[taskId].tBlendColor); + + gTasks[taskId].tNumBlends--; + gTasks[taskId].tRestoreBlend ^= 1; +} + +static void AnimTask_BlendColorCycleLoop(u8 taskId) +{ + u8 startBlendAmount, targetBlendAmount; + if (!gPaletteFade.active) + { + if (gTasks[taskId].tNumBlends > 0) + { + if (!gTasks[taskId].tRestoreBlend) + { + // Blend to designated color + startBlendAmount = gTasks[taskId].tInitialBlendY; + targetBlendAmount = gTasks[taskId].tTargetBlendY; + } + else + { + // Blend back to original color + startBlendAmount = gTasks[taskId].tTargetBlendY; + targetBlendAmount = gTasks[taskId].tInitialBlendY; + } + + if (gTasks[taskId].tNumBlends == 1) + targetBlendAmount = 0; + + BlendColorCycle(taskId, startBlendAmount, targetBlendAmount); + } + else + { + DestroyAnimVisualTask(taskId); + } + } +} + +// See AnimTask_BlendColorCycle. Same, but excludes Attacker and Target +void AnimTask_BlendColorCycleExclude(u8 taskId) +{ + int battler; + u32 selectedPalettes = 0; + + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gTasks[taskId].tDelay = gBattleAnimArgs[1]; + gTasks[taskId].tNumBlends = gBattleAnimArgs[2]; + gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3]; + gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4]; + gTasks[taskId].tBlendColor = gBattleAnimArgs[5]; + gTasks[taskId].tRestoreBlend = 0; + + for (battler = 0; battler < gBattlersCount; battler++) + { + if (battler != gBattleAnimAttacker && battler != gBattleAnimTarget) + selectedPalettes |= 1 << (battler + 16); + } + + if (gBattleAnimArgs[0] == 1) + selectedPalettes |= 0xE; + + gTasks[taskId].tPalSelectorHi = selectedPalettes >> 16; + gTasks[taskId].tPalSelectorLo = selectedPalettes & 0xFF; + BlendColorCycleExclude(taskId, 0, gTasks[taskId].tTargetBlendY); + gTasks[taskId].func = AnimTask_BlendColorCycleExcludeLoop; +} + +static void BlendColorCycleExclude(u8 taskId, u8 startBlendAmount, u8 targetBlendAmount) +{ + u32 selectedPalettes = ((u16)gTasks[taskId].tPalSelectorHi << 16) | (u16)gTasks[taskId].tPalSelectorLo; + BeginNormalPaletteFade( + selectedPalettes, + gTasks[taskId].tDelay, + startBlendAmount, + targetBlendAmount, + gTasks[taskId].tBlendColor); + + gTasks[taskId].tNumBlends--; + gTasks[taskId].tRestoreBlend ^= 1; +} + +static void AnimTask_BlendColorCycleExcludeLoop(u8 taskId) +{ + u8 startBlendAmount, targetBlendAmount; + if (!gPaletteFade.active) + { + if (gTasks[taskId].tNumBlends > 0) + { + if (!gTasks[taskId].tRestoreBlend) + { + // Blend to designated color + startBlendAmount = gTasks[taskId].tInitialBlendY; + targetBlendAmount = gTasks[taskId].tTargetBlendY; + } + else + { + // Blend back to original color + startBlendAmount = gTasks[taskId].tTargetBlendY; + targetBlendAmount = gTasks[taskId].tInitialBlendY; + } + + if (gTasks[taskId].tNumBlends == 1) + targetBlendAmount = 0; + + BlendColorCycleExclude(taskId, startBlendAmount, targetBlendAmount); + } + else + { + DestroyAnimVisualTask(taskId); + } + } +} + +// See AnimTask_BlendColorCycle. Same, but selects palette by ANIM_TAG_* +void AnimTask_BlendColorCycleByTag(u8 taskId) +{ + u8 paletteIndex; + + gTasks[taskId].tPalTag = gBattleAnimArgs[0]; + gTasks[taskId].tDelay = gBattleAnimArgs[1]; + gTasks[taskId].tNumBlends = gBattleAnimArgs[2]; + gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3]; + gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4]; + gTasks[taskId].tBlendColor = gBattleAnimArgs[5]; + gTasks[taskId].tRestoreBlend = FALSE; + + BlendColorCycleByTag(taskId, 0, gTasks[taskId].tTargetBlendY); + gTasks[taskId].func = AnimTask_BlendColorCycleByTagLoop; +} + +static void BlendColorCycleByTag(u8 taskId, u8 startBlendAmount, u8 targetBlendAmount) +{ + u8 paletteIndex = IndexOfSpritePaletteTag(gTasks[taskId].tPalTag); + BeginNormalPaletteFade( + 1 << (paletteIndex + 16), + gTasks[taskId].tDelay, + startBlendAmount, + targetBlendAmount, + gTasks[taskId].tBlendColor); + + gTasks[taskId].tNumBlends--; + gTasks[taskId].tRestoreBlend ^= 1; +} + +static void AnimTask_BlendColorCycleByTagLoop(u8 taskId) +{ + u8 startBlendAmount, targetBlendAmount; + if (!gPaletteFade.active) + { + if (gTasks[taskId].tNumBlends > 0) + { + if (!gTasks[taskId].tRestoreBlend) + { + // Blend to designated color + startBlendAmount = gTasks[taskId].tInitialBlendY; + targetBlendAmount = gTasks[taskId].tTargetBlendY; + } + else + { + // Blend back to original color + startBlendAmount = gTasks[taskId].tTargetBlendY; + targetBlendAmount = gTasks[taskId].tInitialBlendY; + } + + if (gTasks[taskId].tNumBlends == 1) + targetBlendAmount = 0; + + BlendColorCycleByTag(taskId, startBlendAmount, targetBlendAmount); + } + else + { + DestroyAnimVisualTask(taskId); + } + } +} + +#undef tPalSelector +#undef tPalTag +#undef tDelay +#undef tNumBlends +#undef tInitialBlendY +#undef tTargetBlendY +#undef tBlendColor +#undef tRestoreBlend +#undef tPalSelectorHi +#undef tPalSelectorLo + +// Flashes the specified anim tag with given color. Used e.g. to flash the particles red in Hyper Beam +void AnimTask_FlashAnimTagWithColor(u8 taskId) +{ + u8 paletteIndex; + + gTasks[taskId].data[0] = gBattleAnimArgs[1]; + gTasks[taskId].data[1] = gBattleAnimArgs[1]; + gTasks[taskId].data[2] = gBattleAnimArgs[2]; + gTasks[taskId].data[3] = gBattleAnimArgs[3]; + gTasks[taskId].data[4] = gBattleAnimArgs[4]; + gTasks[taskId].data[5] = gBattleAnimArgs[5]; + gTasks[taskId].data[6] = gBattleAnimArgs[6]; + gTasks[taskId].data[7] = gBattleAnimArgs[0]; + + paletteIndex = IndexOfSpritePaletteTag(gBattleAnimArgs[0]); + BeginNormalPaletteFade( + 1 << (paletteIndex + 16), + 0, + gBattleAnimArgs[4], + gBattleAnimArgs[4], + gBattleAnimArgs[3]); + + gTasks[taskId].func = AnimTask_FlashAnimTagWithColor_Step1; +} + +static void AnimTask_FlashAnimTagWithColor_Step1(u8 taskId) +{ + u32 selectedPalettes; + + if (gTasks[taskId].data[0] > 0) + { + gTasks[taskId].data[0]--; + return; + } + + if (gPaletteFade.active) + return; + + if (gTasks[taskId].data[2] == 0) + { + gTasks[taskId].func = AnimTask_FlashAnimTagWithColor_Step2; + return; + } + + selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].data[7]) + 16); + if (gTasks[taskId].data[1] & 0x100) + { + BeginNormalPaletteFade( + selectedPalettes, + 0, + gTasks[taskId].data[4], + gTasks[taskId].data[4], + gTasks[taskId].data[3]); + } + else + { + BeginNormalPaletteFade( + selectedPalettes, + 0, + gTasks[taskId].data[6], + gTasks[taskId].data[6], + gTasks[taskId].data[5]); + } + + gTasks[taskId].data[1] ^= 0x100; + gTasks[taskId].data[0] = gTasks[taskId].data[1] & 0xFF; + gTasks[taskId].data[2]--; +} + +static void AnimTask_FlashAnimTagWithColor_Step2(u8 taskId) +{ + u32 selectedPalettes; + + if (!gPaletteFade.active) + { + selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].data[7]) + 16); + BeginNormalPaletteFade(selectedPalettes, 0, 0, 0, RGB(0, 0, 0)); + DestroyAnimVisualTask(taskId); + } +} + +void AnimTask_InvertScreenColor(u8 taskId) +{ + u32 selectedPalettes = 0; + u8 attackerBattler = gBattleAnimAttacker; + u8 targetBattler = gBattleAnimTarget; + + if (gBattleAnimArgs[0] & 0x100) + selectedPalettes = sub_80A75AC(1, 0, 0, 0, 0, 0, 0); + + if (gBattleAnimArgs[1] & 0x100) + selectedPalettes |= (0x10000 << attackerBattler); + + if (gBattleAnimArgs[2] & 0x100) + selectedPalettes |= (0x10000 << targetBattler); + + InvertPlttBuffer(selectedPalettes); + DestroyAnimVisualTask(taskId); +} + +void sub_8115F94(u8 taskId) +{ + u8 attackerBattler; + u8 targetBattler; + u8 paletteIndex; + u32 selectedPalettes = 0; + + if (gTasks[taskId].data[0] == 0) + { + gTasks[taskId].data[2] = gBattleAnimArgs[0]; + gTasks[taskId].data[3] = gBattleAnimArgs[1]; + gTasks[taskId].data[4] = gBattleAnimArgs[2]; + gTasks[taskId].data[1] = gBattleAnimArgs[3]; + gTasks[taskId].data[5] = gBattleAnimArgs[4]; + gTasks[taskId].data[6] = gBattleAnimArgs[5]; + gTasks[taskId].data[7] = gBattleAnimArgs[6]; + } + + gTasks[taskId].data[0]++; + attackerBattler = gBattleAnimAttacker; + targetBattler = gBattleAnimTarget; + + if (gTasks[taskId].data[2] & 0x100) + selectedPalettes = 0x0000FFFF; + + if (gTasks[taskId].data[2] & 0x1) + { + paletteIndex = IndexOfSpritePaletteTag(gSprites[gHealthboxSpriteIds[attackerBattler]].template->paletteTag); + selectedPalettes |= (1 << paletteIndex) << 16; + } + + if (gTasks[taskId].data[3] & 0x100) + selectedPalettes |= (1 << attackerBattler) << 16; + + if (gTasks[taskId].data[4] & 0x100) + selectedPalettes |= (1 << targetBattler) << 16; + + TintPlttBuffer(selectedPalettes, gTasks[taskId].data[5], gTasks[taskId].data[6], gTasks[taskId].data[7]); + if (gTasks[taskId].data[0] == gTasks[taskId].data[1]) + { + UnfadePlttBuffer(selectedPalettes); + DestroyAnimVisualTask(taskId); + } +} + +static void AnimShakeMonOrBattleTerrain(struct Sprite *sprite) +{ + u16 var0; + + sprite->invisible = TRUE; + sprite->data[0] = -gBattleAnimArgs[0]; + sprite->data[1] = gBattleAnimArgs[1]; + sprite->data[2] = gBattleAnimArgs[1]; + sprite->data[3] = gBattleAnimArgs[2]; + + switch (gBattleAnimArgs[3]) + { + case 0: + StoreSpriteCallbackInData6(sprite, (void *)&gBattle_BG3_X); + break; + case 1: + StoreSpriteCallbackInData6(sprite, (void *)&gBattle_BG3_Y); + break; + case 2: + StoreSpriteCallbackInData6(sprite, (void *)&gSpriteCoordOffsetX); + break; + default: + StoreSpriteCallbackInData6(sprite, (void *)&gSpriteCoordOffsetY); + break; + } + + sprite->data[4] = *(u16 *)(sprite->data[6] | (sprite->data[7] << 16)); + sprite->data[5] = gBattleAnimArgs[3]; + var0 = sprite->data[5] - 2; + if (var0 < 2) + AnimShakeMonOrBattleTerrain_UpdateCoordOffsetEnabled(); + + sprite->callback = AnimShakeMonOrBattleTerrain_Step; +} + +static void AnimShakeMonOrBattleTerrain_Step(struct Sprite *sprite) +{ + u8 i; + u16 var0; + + if (sprite->data[3] > 0) + { + sprite->data[3]--; + if (sprite->data[1] > 0) + { + sprite->data[1]--; + } + else + { + sprite->data[1] = sprite->data[2]; + *(u16 *)(sprite->data[6] | (sprite->data[7] << 16)) += sprite->data[0]; + sprite->data[0] = -sprite->data[0]; + } + } + else + { + *(u16 *)(sprite->data[6] | (sprite->data[7] << 16)) = sprite->data[4]; + var0 = sprite->data[5] - 2; + if (var0 < 2) + { + for (i = 0; i < gBattlersCount; i++) + gSprites[gBattlerSpriteIds[i]].coordOffsetEnabled = FALSE; + } + + DestroyAnimSprite(sprite); + } +} + +static void AnimShakeMonOrBattleTerrain_UpdateCoordOffsetEnabled(void) +{ + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = FALSE; + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = FALSE; + + if (gBattleAnimArgs[4] == 2) + { + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = TRUE; + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = TRUE; + } + else + { + if (gBattleAnimArgs[4] == 0) + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = TRUE; + else + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = TRUE; + } +} + +// Task data for AnimTask_ShakeBattleTerrain +#define tXOffset data[0] +#define tYOffset data[1] +#define tNumShakes data[2] +#define tTimer data[3] +#define tShakeDelay data[8] + +// Can shake battle terrain back and forth on the X or down and back to original pos on Y (cant shake up from orig pos) +// arg0: x offset of shake +// arg1: y offset of shake +// arg2: number of shakes +// arg3: time between shakes +void AnimTask_ShakeBattleTerrain(u8 taskId) +{ + gTasks[taskId].tXOffset = gBattleAnimArgs[0]; + gTasks[taskId].tYOffset = gBattleAnimArgs[1]; + gTasks[taskId].tNumShakes = gBattleAnimArgs[2]; + gTasks[taskId].tTimer = gBattleAnimArgs[3]; + gTasks[taskId].tShakeDelay = gBattleAnimArgs[3]; + gBattle_BG3_X = gBattleAnimArgs[0]; + gBattle_BG3_Y = gBattleAnimArgs[1]; + gTasks[taskId].func = AnimTask_ShakeBattleTerrain_Step; + gTasks[taskId].func(taskId); +} + +static void AnimTask_ShakeBattleTerrain_Step(u8 taskId) +{ + if (gTasks[taskId].tTimer == 0) + { + if (gBattle_BG3_X == gTasks[taskId].tXOffset) + gBattle_BG3_X = -gTasks[taskId].tXOffset; + else + gBattle_BG3_X = gTasks[taskId].tXOffset; + + if (gBattle_BG3_Y == -gTasks[taskId].tYOffset) + gBattle_BG3_Y = 0; + else + gBattle_BG3_Y = -gTasks[taskId].tYOffset; + + gTasks[taskId].tTimer = gTasks[taskId].tShakeDelay; + if (--gTasks[taskId].tNumShakes == 0) + { + gBattle_BG3_X = 0; + gBattle_BG3_Y = 0; + DestroyAnimVisualTask(taskId); + } + } + else + { + gTasks[taskId].tTimer--; + } +} + +#undef tXOffset +#undef tYOffset +#undef tNumShakes +#undef tTimer +#undef tShakeDelay + +static void AnimHitSplatBasic(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); + if (gBattleAnimArgs[2] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Same as basic hit splat but takes a length of time to persist for (arg4) +static void AnimHitSplatPersistent(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); + if (gBattleAnimArgs[2] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSpriteAfterTimer); +} + +// For paired hit splats whose position is inverted when used by the opponent on the player. +// Used by Twineedle and Spike Cannon +static void AnimHitSplatHandleInvert(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER && !IsContest()) + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + + AnimHitSplatBasic(sprite); +} + +static void AnimHitSplatRandom(struct Sprite *sprite) +{ + if (gBattleAnimArgs[1] == -1) + gBattleAnimArgs[1] = Random2() & 3; + + StartSpriteAffineAnim(sprite, gBattleAnimArgs[1]); + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, 0); + else + InitSpritePosToAnimTarget(sprite, FALSE); + + sprite->pos2.x += (Random2() % 48) - 24; + sprite->pos2.y += (Random2() % 24) - 12; + + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; +} + +static void AnimHitSplatOnMonEdge(struct Sprite *sprite) +{ + sprite->data[0] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); + sprite->pos1.x = gSprites[sprite->data[0]].pos1.x + gSprites[sprite->data[0]].pos2.x; + sprite->pos1.y = gSprites[sprite->data[0]].pos1.y + gSprites[sprite->data[0]].pos2.y; + sprite->pos2.x = gBattleAnimArgs[1]; + sprite->pos2.y = gBattleAnimArgs[2]; + StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; +} + +static void AnimCrossImpact(struct Sprite *sprite) +{ + if (gBattleAnimArgs[2] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + + sprite->data[0] = gBattleAnimArgs[3]; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = WaitAnimForDuration; +} + +static void AnimFlashingHitSplat(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); + if (gBattleAnimArgs[2] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + + sprite->callback = AnimFlashingHitSplat_Step; +} + +static void AnimFlashingHitSplat_Step(struct Sprite *sprite) +{ + sprite->invisible ^= 1; + if (sprite->data[0]++ > 12) + DestroyAnimSprite(sprite); +} diff --git a/src/battle_anim_poison.c b/src/battle_anim_poison.c new file mode 100644 index 000000000..bc5624249 --- /dev/null +++ b/src/battle_anim_poison.c @@ -0,0 +1,319 @@ +#include "global.h" +#include "battle_anim.h" +#include "trig.h" +#include "constants/rgb.h" + +static void AnimSludgeProjectile(struct Sprite *); +static void AnimSludgeProjectile_Step(struct Sprite *); +static void AnimAcidPoisonBubble(struct Sprite *); +static void AnimAcidPoisonBubble_Step(struct Sprite *); +static void AnimSludgeBombHitParticle(struct Sprite *); +static void AnimSludgeBombHitParticle_Step(struct Sprite *); +static void AnimAcidPoisonDroplet(struct Sprite *); +static void AnimBubbleEffect(struct Sprite *); +static void AnimBubbleEffect_Step(struct Sprite *); + +static const union AnimCmd sAnim_ToxicBubble[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(24, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_ToxicBubble[] = +{ + sAnim_ToxicBubble, +}; + +const struct SpriteTemplate gToxicBubbleSpriteTemplate = +{ + .tileTag = ANIM_TAG_TOXIC_BUBBLE, + .paletteTag = ANIM_TAG_TOXIC_BUBBLE, + .oam = &gOamData_AffineOff_ObjNormal_16x32, + .anims = sAnims_ToxicBubble, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSpriteOnMonPos, +}; + +static const union AnimCmd sAnim_PoisonProjectile[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_AcidPoisonDroplet[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_SludgeBombHit[] = +{ + ANIMCMD_FRAME(8, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_PoisonProjectile[] = +{ + sAnim_PoisonProjectile, +}; + +static const union AnimCmd *const sAnims_AcidPoisonDroplet[] = +{ + sAnim_AcidPoisonDroplet, +}; + +static const union AnimCmd *const sAnims_SludgeBombHit[] = +{ + sAnim_SludgeBombHit, +}; + +static const union AffineAnimCmd sAffineAnim_PoisonProjectile[] = +{ + AFFINEANIMCMD_FRAME(0x160, 0x160, 0, 0), + AFFINEANIMCMD_FRAME(0xFFF6, 0xFFF6, 0, 10), + AFFINEANIMCMD_FRAME(0xA, 0xA, 0, 10), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sAffineAnim_SludgeBombHit[] = +{ + AFFINEANIMCMD_FRAME(0xEC, 0xEC, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_PoisonProjectile[] = +{ + sAffineAnim_PoisonProjectile, +}; + +static const union AffineAnimCmd *const sAffineAnims_SludgeBombHit[] = +{ + sAffineAnim_SludgeBombHit, +}; + +const struct SpriteTemplate gSludgeProjectileSpriteTemplate = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = sAnims_PoisonProjectile, + .images = NULL, + .affineAnims = sAffineAnims_PoisonProjectile, + .callback = AnimSludgeProjectile, +}; + +const struct SpriteTemplate gAcidPoisonBubbleSpriteTemplate = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = sAnims_PoisonProjectile, + .images = NULL, + .affineAnims = sAffineAnims_PoisonProjectile, + .callback = AnimAcidPoisonBubble, +}; + +const struct SpriteTemplate gSludgeBombHitParticleSpriteTemplate = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = sAnims_SludgeBombHit, + .images = NULL, + .affineAnims = sAffineAnims_SludgeBombHit, + .callback = AnimSludgeBombHitParticle, +}; + +static const union AffineAnimCmd sAffineAnim_AcidPoisonDroplet[] = +{ + AFFINEANIMCMD_FRAME(0xFFF0, 0x10, 0, 6), + AFFINEANIMCMD_FRAME(0x10, 0xFFF0, 0, 6), + AFFINEANIMCMD_JUMP(0), +}; + +const union AffineAnimCmd *const gAffineAnims_Droplet[] = +{ + sAffineAnim_AcidPoisonDroplet, +}; + +const struct SpriteTemplate gAcidPoisonDropletSpriteTemplate = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = sAnims_AcidPoisonDroplet, + .images = NULL, + .affineAnims = gAffineAnims_Droplet, + .callback = AnimAcidPoisonDroplet, +}; + +static const union AffineAnimCmd sAffineAnim_Bubble[] = +{ + AFFINEANIMCMD_FRAME(0x9C, 0x9C, 0, 0), + AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 20), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_Bubble[] = +{ + sAffineAnim_Bubble, +}; + +const struct SpriteTemplate gPoisonBubbleSpriteTemplate = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = sAnims_PoisonProjectile, + .images = NULL, + .affineAnims = sAffineAnims_Bubble, + .callback = AnimBubbleEffect, +}; + +const struct SpriteTemplate gWaterBubbleSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_AffineNormal_ObjBlend_16x16, + .anims = gAnims_WaterBubble, + .images = NULL, + .affineAnims = sAffineAnims_Bubble, + .callback = AnimBubbleEffect, +}; + +static void AnimSludgeProjectile(struct Sprite *sprite) +{ + if (!gBattleAnimArgs[3]) + StartSpriteAnim(sprite, 2); + + InitSpritePosToAnimAttacker(sprite, 1); + + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->data[5] = -30; + + InitAnimArcTranslation(sprite); + + sprite->callback = AnimSludgeProjectile_Step; +} + +static void AnimSludgeProjectile_Step(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroyAnimSprite(sprite); +} + +static void AnimAcidPoisonBubble(struct Sprite *sprite) +{ + s16 l1, l2; + if (!gBattleAnimArgs[3]) + StartSpriteAnim(sprite, 2); + + InitSpritePosToAnimAttacker(sprite, 1); + SetAverageBattlerPositions(gBattleAnimTarget, 1, &l1, &l2); + + if (GetBattlerSide(gBattleAnimAttacker)) + gBattleAnimArgs[4] = -gBattleAnimArgs[4]; + + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[2] = l1 + gBattleAnimArgs[4]; + sprite->data[4] = l2 + gBattleAnimArgs[5]; + sprite->data[5] = -30; + + InitAnimArcTranslation(sprite); + + sprite->callback = AnimAcidPoisonBubble_Step; +} + +static void AnimAcidPoisonBubble_Step(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroyAnimSprite(sprite); +} + +static void AnimSludgeBombHitParticle(struct Sprite *sprite) +{ + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[0]; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[1]; + + InitSpriteDataForLinearTranslation(sprite); + + sprite->data[5] = sprite->data[1] / gBattleAnimArgs[2]; + sprite->data[6] = sprite->data[2] / gBattleAnimArgs[2]; + + sprite->callback = AnimSludgeBombHitParticle_Step; +} + +static void AnimSludgeBombHitParticle_Step(struct Sprite *sprite) +{ + TranslateSpriteLinearFixedPoint(sprite); + + sprite->data[1] -= sprite->data[5]; + sprite->data[2] -= sprite->data[6]; + + if (!sprite->data[0]) + DestroyAnimSprite(sprite); +} + +static void AnimAcidPoisonDroplet(struct Sprite *sprite) +{ + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->pos1.x, &sprite->pos1.y); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; + sprite->data[4] = sprite->pos1.y + sprite->data[0]; + + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Animates a bubble by rising upward, swaying side to side, and +// enlarging the sprite. This is used as an after-effect by poison-type +// moves, along with MOVE_BUBBLE, and MOVE_BUBBLEBEAM. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: 0 = single-target, 1 = multi-target +static void AnimBubbleEffect(struct Sprite *sprite) +{ + if (!gBattleAnimArgs[2]) + { + InitSpritePosToAnimTarget(sprite, TRUE); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->pos1.x, &sprite->pos1.y); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + + sprite->callback = AnimBubbleEffect_Step; +} + +static void AnimBubbleEffect_Step(struct Sprite *sprite) +{ + sprite->data[0] = (sprite->data[0] + 0xB) & 0xFF; + sprite->pos2.x = Sin(sprite->data[0], 4); + sprite->data[1] += 0x30; + sprite->pos2.y = -(sprite->data[1] >> 8); + + if (sprite->affineAnimEnded) + DestroyAnimSprite(sprite); +} diff --git a/src/battle_anim_psychic.c b/src/battle_anim_psychic.c new file mode 100644 index 000000000..7918698fc --- /dev/null +++ b/src/battle_anim_psychic.c @@ -0,0 +1,1168 @@ +#include "global.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "palette.h" +#include "sound.h" +#include "scanline_effect.h" +#include "trig.h" +#include "constants/rgb.h" +#include "constants/songs.h" + +static void AnimDefensiveWall(struct Sprite *); +static void AnimDefensiveWall_Step1(struct Sprite *); +static void AnimDefensiveWall_Step2(struct Sprite *); +static void AnimDefensiveWall_Step3(struct Sprite *); +static void AnimDefensiveWall_Step4(struct Sprite *); +static void AnimDefensiveWall_Step5(struct Sprite *); +static void AnimWallSparkle(struct Sprite *); +static void AnimBentSpoon(struct Sprite *); +static void AnimQuestionMark(struct Sprite *); +static void AnimQuestionMark_Step1(struct Sprite *); +static void AnimQuestionMark_Step2(struct Sprite *); +static void AnimRedX(struct Sprite *); +static void AnimSkillSwapOrb(struct Sprite *); +static void AnimPsychoBoost(struct Sprite *); +static void AnimTask_MeditateStretchAttacker_Step(u8); +static void AnimTask_Teleport_Step(u8); +static void AnimTask_ImprisonOrbs_Step(u8); +static void AnimTask_SkillSwap_Step(u8); +static void AnimTask_ExtrasensoryDistortion_Step(u8); +static void AnimTask_TransparentCloneGrowAndShrink_Step(u8); + +static const union AffineAnimCmd sAffineAnim_PsychUpSpiral[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0xFFFE, 0xFFFE, -10, 120), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_PsychUpSpiral[] = +{ + sAffineAnim_PsychUpSpiral, +}; + +const struct SpriteTemplate gPsychUpSpiralSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPIRAL, + .paletteTag = ANIM_TAG_SPIRAL, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_PsychUpSpiral, + .callback = AnimSpriteOnMonPos, +}; + +const struct SpriteTemplate gLightScreenWallSpriteTemplate = +{ + .tileTag = ANIM_TAG_GREEN_LIGHT_WALL, + .paletteTag = ANIM_TAG_GREEN_LIGHT_WALL, + .oam = &gOamData_AffineOff_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDefensiveWall, +}; + +const struct SpriteTemplate gReflectWallSpriteTemplate = +{ + .tileTag = ANIM_TAG_BLUE_LIGHT_WALL, + .paletteTag = ANIM_TAG_BLUE_LIGHT_WALL, + .oam = &gOamData_AffineOff_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDefensiveWall, +}; + +const struct SpriteTemplate gMirrorCoatWallSpriteTemplate = +{ + .tileTag = ANIM_TAG_RED_LIGHT_WALL, + .paletteTag = ANIM_TAG_RED_LIGHT_WALL, + .oam = &gOamData_AffineOff_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDefensiveWall, +}; + +const struct SpriteTemplate gBarrierWallSpriteTemplate = +{ + .tileTag = ANIM_TAG_GRAY_LIGHT_WALL, + .paletteTag = ANIM_TAG_GRAY_LIGHT_WALL, + .oam = &gOamData_AffineOff_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDefensiveWall, +}; + +const struct SpriteTemplate gMagicCoatWallSpriteTemplate = +{ + .tileTag = ANIM_TAG_ORANGE_LIGHT_WALL, + .paletteTag = ANIM_TAG_ORANGE_LIGHT_WALL, + .oam = &gOamData_AffineOff_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDefensiveWall, +}; + +static const union AnimCmd sAnim_ReflectSparkle[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_FRAME(64, 3), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_ReflectSparkle[] = +{ + sAnim_ReflectSparkle, +}; + +const struct SpriteTemplate gReflectSparkleSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARKLE_4, + .paletteTag = ANIM_TAG_SPARKLE_4, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_ReflectSparkle, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWallSparkle, +}; + +static const union AnimCmd sAnim_SpecialScreenSparkle[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_FRAME(12, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_SpecialScreenSparkle[] = +{ + sAnim_SpecialScreenSparkle, +}; + +const struct SpriteTemplate gSpecialScreenSparkleSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARKLE_3, + .paletteTag = ANIM_TAG_SPARKLE_3, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = sAnims_SpecialScreenSparkle, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWallSparkle, +}; + +const struct SpriteTemplate gGoldRingSpriteTemplate = +{ + .tileTag = ANIM_TAG_GOLD_RING, + .paletteTag = ANIM_TAG_GOLD_RING, + .oam = &gOamData_AffineOff_ObjNormal_16x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = TranslateAnimSpriteToTargetMonLocation, +}; + +static const union AnimCmd sAnim_BentSpoon_0[] = +{ + ANIMCMD_FRAME(8, 60, .hFlip = TRUE), + ANIMCMD_FRAME(16, 5, .hFlip = TRUE), + ANIMCMD_FRAME(8, 5, .hFlip = TRUE), + ANIMCMD_FRAME(0, 5, .hFlip = TRUE), + ANIMCMD_FRAME(8, 22, .hFlip = TRUE), + ANIMCMD_LOOP(0), + ANIMCMD_FRAME(16, 5, .hFlip = TRUE), + ANIMCMD_FRAME(8, 5, .hFlip = TRUE), + ANIMCMD_FRAME(0, 5, .hFlip = TRUE), + ANIMCMD_FRAME(8, 5, .hFlip = TRUE), + ANIMCMD_LOOP(1), + ANIMCMD_FRAME(8, 22, .hFlip = TRUE), + ANIMCMD_FRAME(24, 3, .hFlip = TRUE), + ANIMCMD_FRAME(32, 3, .hFlip = TRUE), + ANIMCMD_FRAME(40, 22, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_BentSpoon_1[] = +{ + ANIMCMD_FRAME(8, 60), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(8, 22), + ANIMCMD_LOOP(0), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_LOOP(1), + ANIMCMD_FRAME(8, 22), + ANIMCMD_FRAME(24, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(40, 22), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_BentSpoon[] = +{ + sAnim_BentSpoon_0, + sAnim_BentSpoon_1, +}; + +const struct SpriteTemplate gBentSpoonSpriteTemplate = +{ + .tileTag = ANIM_TAG_BENT_SPOON, + .paletteTag = ANIM_TAG_BENT_SPOON, + .oam = &gOamData_AffineOff_ObjNormal_16x32, + .anims = sAnims_BentSpoon, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimBentSpoon, +}; + +static const union AnimCmd sAnim_QuestionMark[] = +{ + ANIMCMD_FRAME(0, 6), + ANIMCMD_FRAME(16, 6), + ANIMCMD_FRAME(32, 6), + ANIMCMD_FRAME(48, 6), + ANIMCMD_FRAME(64, 6), + ANIMCMD_FRAME(80, 6), + ANIMCMD_FRAME(96, 18), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_QuestionMark[] = +{ + sAnim_QuestionMark, +}; + +static const union AffineAnimCmd sAffineAnim_QuestionMark[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 4, 4), + AFFINEANIMCMD_FRAME(0, 0, -4, 8), + AFFINEANIMCMD_FRAME(0, 0, 4, 4), + AFFINEANIMCMD_LOOP(2), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_QuestionMark[] = +{ + sAffineAnim_QuestionMark, +}; + +const struct SpriteTemplate gQuestionMarkSpriteTemplate = +{ + .tileTag = ANIM_TAG_AMNESIA, + .paletteTag = ANIM_TAG_AMNESIA, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_QuestionMark, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimQuestionMark, +}; + +static const union AffineAnimCmd sAffineAnim_MeditateStretchAttacker[] = +{ + AFFINEANIMCMD_FRAME(-8, 10, 0, 16), + AFFINEANIMCMD_FRAME(18, -18, 0, 16), + AFFINEANIMCMD_FRAME(-20, 16, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_Teleport[] = +{ + AFFINEANIMCMD_FRAME(64, -4, 0, 20), + AFFINEANIMCMD_FRAME(0, 0, 0, -56), + AFFINEANIMCMD_END, +}; + +const struct SpriteTemplate gImprisonOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_HOLLOW_ORB, + .paletteTag = ANIM_TAG_HOLLOW_ORB, + .oam = &gOamData_AffineOff_ObjBlend_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +const struct SpriteTemplate gRedXSpriteTemplate = +{ + .tileTag = ANIM_TAG_X_SIGN, + .paletteTag = ANIM_TAG_X_SIGN, + .oam = &gOamData_AffineOff_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRedX, +}; + +static const union AffineAnimCmd sAffineAnim_SkillSwapOrb_0[] = +{ + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 8), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sAffineAnim_SkillSwapOrb_1[] = +{ + AFFINEANIMCMD_FRAME(0xF0, 0xF0, 0, 0), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 6), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 2), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd sAffineAnim_SkillSwapOrb_2[] = +{ + AFFINEANIMCMD_FRAME(0xD0, 0xD0, 0, 0), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 4), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 4), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd sAffineAnim_SkillSwapOrb_3[] = +{ + AFFINEANIMCMD_FRAME(0xB0, 0xB0, 0, 0), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 2), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 6), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const sAffineAnims_SkillSwapOrb[] = +{ + sAffineAnim_SkillSwapOrb_0, + sAffineAnim_SkillSwapOrb_1, + sAffineAnim_SkillSwapOrb_2, + sAffineAnim_SkillSwapOrb_3, +}; + +const struct SpriteTemplate gSkillSwapOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_BLUEGREEN_ORB, + .paletteTag = ANIM_TAG_BLUEGREEN_ORB, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_SkillSwapOrb, + .callback = AnimSkillSwapOrb, +}; + +static const union AffineAnimCmd sAffineAnim_LusterPurgeCircle[] = +{ + AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 120), + AFFINEANIMCMD_END_ALT(1), +}; + +static const union AffineAnimCmd *const sAffineAnims_LusterPurgeCircle[] = +{ + sAffineAnim_LusterPurgeCircle, +}; + +const struct SpriteTemplate gLusterPurgeCircleSpriteTemplate = +{ + .tileTag = ANIM_TAG_WHITE_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_WHITE_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineDouble_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_LusterPurgeCircle, + .callback = AnimSpriteOnMonPos, +}; + +static const union AffineAnimCmd sAffineAnim_PsychoBoostOrb_0[] = +{ + AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 17), + AFFINEANIMCMD_LOOP(0), + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 10), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 10), + AFFINEANIMCMD_LOOP(4), + AFFINEANIMCMD_LOOP(0), + AFFINEANIMCMD_FRAME(0xFFF0, 0xFFF0, 0, 5), + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 5), + AFFINEANIMCMD_LOOP(7), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sAffineAnim_PsychoBoostOrb_1[] = +{ + AFFINEANIMCMD_FRAME(0xFFEC, 0x18, 0, 15), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sAffineAnims_PsychoBoostOrb[] = +{ + sAffineAnim_PsychoBoostOrb_0, + sAffineAnim_PsychoBoostOrb_1, +}; + +const struct SpriteTemplate gPsychoBoostOrbSpriteTemplate = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineDouble_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sAffineAnims_PsychoBoostOrb, + .callback = AnimPsychoBoost, +}; + +// For the rectangular wall sprite used by Reflect, Mirror Coat, etc +static void AnimDefensiveWall(struct Sprite *sprite) +{ + u8 isContest = IsContest(); + + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER || isContest) + { + sprite->oam.priority = 2; + sprite->subpriority = 200; + } + + if (!isContest) + { + u8 battlerCopy; + u8 battler = battlerCopy = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + u8 rank = GetBattlerSpriteBGPriorityRank(battler); + int var0 = 1; + u8 toBG_2 = (rank ^ var0) != 0; + + if (IsBattlerSpriteVisible(battler)) + MoveBattlerSpriteToBG(battler, toBG_2, FALSE); + + battler = BATTLE_PARTNER(battlerCopy); + if (IsBattlerSpriteVisible(battler)) + MoveBattlerSpriteToBG(battler, toBG_2 ^ var0, FALSE); + } + + if (!isContest && IsDoubleBattle()) + { + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + sprite->pos1.x = 72; + sprite->pos1.y = 80; + } + else + { + sprite->pos1.x = 176; + sprite->pos1.y = 40; + } + } + else + { + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X) + gBattleAnimArgs[0]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + gBattleAnimArgs[1]; + } + + sprite->data[0] = 256 + IndexOfSpritePaletteTag(gBattleAnimArgs[2]) * 16; + + if (isContest) + { + sprite->pos1.y += 9; + sprite->callback = AnimDefensiveWall_Step2; + sprite->callback(sprite); + } + else + { + sprite->callback = AnimDefensiveWall_Step1; + } +} + +static void AnimDefensiveWall_Step1(struct Sprite *sprite) +{ + u8 battler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + if (!sprite->data[7]) + { + sprite->data[7] = 1; + return; + } + + if (IsBattlerSpriteVisible(battler)) + gSprites[gBattlerSpriteIds[battler]].invisible = TRUE; + + battler = BATTLE_PARTNER(battler); + if (IsBattlerSpriteVisible(battler)) + gSprites[gBattlerSpriteIds[battler]].invisible = TRUE; + + sprite->callback = AnimDefensiveWall_Step2; + sprite->callback(sprite); +} + +static void AnimDefensiveWall_Step2(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[3], 16 - sprite->data[3])); + if (sprite->data[3] == 13) + sprite->callback = AnimDefensiveWall_Step3; + else + sprite->data[3]++; +} + +static void AnimDefensiveWall_Step3(struct Sprite *sprite) +{ + u16 color; + u16 startOffset; + int i; + + if (++sprite->data[1] == 2) + { + sprite->data[1] = 0; + startOffset = sprite->data[0]; + color = gPlttBufferFaded[startOffset + 8]; + + for (i = 8; i > 0; i--) + gPlttBufferFaded[startOffset + i] = gPlttBufferFaded[startOffset + i - 1]; + + gPlttBufferFaded[startOffset + 1] = color; + + if (++sprite->data[2] == 16) + sprite->callback = AnimDefensiveWall_Step4; + } +} + +static void AnimDefensiveWall_Step4(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[3], 16 - sprite->data[3])); + + if (--sprite->data[3] == -1) + { + if (!IsContest()) + { + u8 battlerCopy; + u8 battler = battlerCopy = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + + if (IsBattlerSpriteVisible(battler)) + gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; + + battler = BATTLE_PARTNER(battlerCopy); + if (IsBattlerSpriteVisible(battler)) + gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; + } + + sprite->invisible = TRUE; + sprite->callback = AnimDefensiveWall_Step5; + } +} + +static void AnimDefensiveWall_Step5(struct Sprite *sprite) +{ + if (!IsContest()) + { + u8 battlerCopy; + u8 battler = battlerCopy = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + u8 rank = GetBattlerSpriteBGPriorityRank(battler); + int var0 = 1; + u8 toBG_2 = (rank ^ var0) != 0; + + if (IsBattlerSpriteVisible(battler)) + sub_80A477C(toBG_2); + + battler = battlerCopy ^ 2; + if (IsBattlerSpriteVisible(battler)) + sub_80A477C(toBG_2 ^ var0); + } + + sprite->callback = DestroyAnimSprite; +} + +// Animates the sparkle that appears during Reflect or Light Screen/Mirror Coat +static void AnimWallSparkle(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + int arg3 = gBattleAnimArgs[3]; + bool8 respectMonPicOffsets = FALSE; + if (arg3 == 0) + respectMonPicOffsets = TRUE; + + if (!IsContest() && IsDoubleBattle()) + { + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + sprite->pos1.x = 72 - gBattleAnimArgs[0]; + sprite->pos1.y = gBattleAnimArgs[1] + 80; + } + else + { + sprite->pos1.x = gBattleAnimArgs[0] + 176; + sprite->pos1.y = gBattleAnimArgs[1] + 40; + } + } + else + { + if (gBattleAnimArgs[2] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, respectMonPicOffsets); + else + InitSpritePosToAnimTarget(sprite, respectMonPicOffsets); + } + + sprite->data[0]++; + } + else + { + if (sprite->animEnded || sprite->affineAnimEnded) + DestroySpriteAndMatrix(sprite); + } +} + +static void AnimBentSpoon(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + StartSpriteAnim(sprite, 1); + sprite->pos1.x -= 40; + sprite->pos1.y += 10; + sprite->data[1] = -1; + } + else + { + sprite->pos1.x += 40; + sprite->pos1.y -= 10; + sprite->data[1] = 1; + } + + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = RunStoredCallbackWhenAnimEnds; +} + +// Used by Amnesia +static void AnimQuestionMark(struct Sprite *sprite) +{ + s16 x = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_WIDTH) / 2; + s16 y = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_HEIGHT) / -2; + + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + x = -x; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2) + x; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + y; + + if (sprite->pos1.y < 16) + sprite->pos1.y = 16; + + StoreSpriteCallbackInData6(sprite, AnimQuestionMark_Step1); + sprite->callback = RunStoredCallbackWhenAnimEnds; +} + +static void AnimQuestionMark_Step1(struct Sprite *sprite) +{ + sprite->oam.affineMode = ST_OAM_AFFINE_NORMAL; + sprite->affineAnims = sAffineAnims_QuestionMark; + sprite->data[0] = 0; + InitSpriteAffineAnim(sprite); + sprite->callback = AnimQuestionMark_Step2; +} + +static void AnimQuestionMark_Step2(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (sprite->affineAnimEnded) + { + FreeOamMatrix(sprite->oam.matrixNum); + sprite->oam.affineMode = ST_OAM_AFFINE_OFF; + sprite->data[1] = 18; + sprite->data[0]++; + } + break; + case 1: + if (--sprite->data[1] == -1) + DestroyAnimSprite(sprite); + break; + } +} + +void AnimTask_MeditateStretchAttacker(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[0] = spriteId; + PrepareAffineAnimInTaskData(task, spriteId, sAffineAnim_MeditateStretchAttacker); + task->func = AnimTask_MeditateStretchAttacker_Step; +} + +static void AnimTask_MeditateStretchAttacker_Step(u8 taskId) +{ + if (!RunAffineAnimFromTaskData(&gTasks[taskId])) + DestroyAnimVisualTask(taskId); +} + +void AnimTask_Teleport(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[0] = spriteId; + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 4 : 8; + + PrepareAffineAnimInTaskData(task, task->data[0], sAffineAnim_Teleport); + task->func = AnimTask_Teleport_Step; +} + +static void AnimTask_Teleport_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[1]) + { + case 0: + RunAffineAnimFromTaskData(task); + if (++task->data[2] > 19) + task->data[1]++; + break; + case 1: + if (task->data[3] != 0) + { + gSprites[task->data[0]].pos2.y -= 8; + task->data[3]--; + } + else + { + gSprites[task->data[0]].invisible = TRUE; + gSprites[task->data[0]].pos1.x = 272; + ResetSpriteRotScale(task->data[0]); + DestroyAnimVisualTask(taskId); + } + break; + } +} + +void AnimTask_ImprisonOrbs(u8 taskId) +{ + u16 var0, var1; + + struct Task *task = &gTasks[taskId]; + + task->data[3] = 16; + task->data[4] = 0; + task->data[13] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + + var0 = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_WIDTH) / 3; + var1 = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_HEIGHT) / 3; + task->data[12] = var0 > var1 ? var0 : var1; + + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + + task->func = AnimTask_ImprisonOrbs_Step; +} + +static void AnimTask_ImprisonOrbs_Step(u8 taskId) +{ + u16 i; + u8 spriteId; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + if (++task->data[1] > 8) + { + task->data[1] = 0; + spriteId = CreateSprite(&gImprisonOrbSpriteTemplate, task->data[13], task->data[14], 0); + task->data[task->data[2] + 8] = spriteId; + if (spriteId != MAX_SPRITES) + { + switch (task->data[2]) + { + case 0: + gSprites[spriteId].pos2.x = task->data[12]; + gSprites[spriteId].pos2.y = -task->data[12]; + break; + case 1: + gSprites[spriteId].pos2.x = -task->data[12]; + gSprites[spriteId].pos2.y = task->data[12]; + break; + case 2: + gSprites[spriteId].pos2.x = task->data[12]; + gSprites[spriteId].pos2.y = task->data[12]; + break; + case 3: + gSprites[spriteId].pos2.x = -task->data[12]; + gSprites[spriteId].pos2.y = -task->data[12]; + break; + } + } + + if (++task->data[2] == 5) + task->data[0]++; + } + break; + case 1: + if (task->data[1] & 1) + task->data[3]--; + else + task->data[4]++; + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4])); + if (++task->data[1] == 32) + { + for (i = 8; i < 13; i++) + { + if (task->data[i] != 64) + DestroySprite(&gSprites[task->data[i]]); + } + + task->data[0]++; + } + break; + case 2: + task->data[0]++; + break; + case 3: + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_810FB60(struct Sprite *sprite) +{ + if (sprite->data[1] > sprite->data[0] - 10) + sprite->invisible = sprite->data[1] & 1; + + if (sprite->data[1] == sprite->data[0]) + DestroyAnimSprite(sprite); + + sprite->data[1]++; +} + +static void AnimRedX(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } + + sprite->data[0] = gBattleAnimArgs[1]; + sprite->callback = sub_810FB60; +} + +void AnimTask_SkillSwap(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (IsContest()) + { + if (gBattleAnimArgs[0] == ANIM_TARGET) + { + task->data[10] = -10; + task->data[11] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_RIGHT) - 8; + task->data[12] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_TOP) + 8; + task->data[13] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_RIGHT) - 8; + task->data[14] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_TOP) + 8; + } + else + { + task->data[10] = 10; + task->data[11] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_LEFT) + 8; + task->data[12] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_BOTTOM) - 8; + task->data[13] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_LEFT) + 8; + task->data[14] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_BOTTOM) - 8; + } + } + else + { + if (gBattleAnimArgs[0] == 1) + { + task->data[10] = -10; + task->data[11] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_LEFT) + 8; + task->data[12] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_TOP) + 8; + task->data[13] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_LEFT) + 8; + task->data[14] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_TOP) + 8; + } + else + { + task->data[10] = 10; + task->data[11] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_RIGHT) - 8; + task->data[12] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_BOTTOM) - 8; + task->data[13] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_RIGHT) - 8; + task->data[14] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_BOTTOM) - 8; + } + } + + task->data[1] = 6; + task->func = AnimTask_SkillSwap_Step; +} + +static void AnimTask_SkillSwap_Step(u8 taskId) +{ + u8 spriteId; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + if (++task->data[1] > 6) + { + task->data[1] = 0; + spriteId = CreateSprite(&gSkillSwapOrbSpriteTemplate, task->data[11], task->data[12], 0); + if (spriteId != 64) + { + gSprites[spriteId].data[0] = 16; + gSprites[spriteId].data[2] = task->data[13]; + gSprites[spriteId].data[4] = task->data[14]; + gSprites[spriteId].data[5] = task->data[10]; + + InitAnimArcTranslation(&gSprites[spriteId]); + StartSpriteAffineAnim(&gSprites[spriteId], task->data[2] & 3); + } + + if (++task->data[2] == 12) + task->data[0]++; + } + break; + case 1: + if (++task->data[1] > 17) + DestroyAnimVisualTask(taskId); + break; + } +} + +static void AnimSkillSwapOrb(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + { + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } +} + +// The scanline effect that distorts the target during Extrasensory by segmenting the mon vertically and shifting the slices +// arg0: Stage. Stage 0 is a slight right distortion, 1 is a medium left distortion, and 2 is a severe right distortion +void AnimTask_ExtrasensoryDistortion(u8 taskId) +{ + s16 i; + u8 yOffset; + struct ScanlineEffectParams scanlineParams; + struct Task *task = &gTasks[taskId]; + + yOffset = GetBattlerYCoordWithElevation(gBattleAnimTarget); + task->data[14] = yOffset - 32; + + switch (gBattleAnimArgs[0]) + { + case 0: + task->data[11] = 2; + task->data[12] = 5; + task->data[13] = 64; + task->data[15] = yOffset + 32; + break; + case 1: + task->data[11] = 2; + task->data[12] = 5; + task->data[13] = 192; + task->data[15] = yOffset + 32; + break; + case 2: + task->data[11] = 4; + task->data[12] = 4; + task->data[13] = 0; + task->data[15] = yOffset + 32; + break; + } + + if (task->data[14] < 0) + task->data[14] = 0; + + if (GetBattlerSpriteBGPriorityRank(gBattleAnimTarget) == 1) + { + task->data[10] = gBattle_BG1_X; + scanlineParams.dmaDest = ®_BG1HOFS; + } + else + { + task->data[10] = gBattle_BG2_X; + scanlineParams.dmaDest = ®_BG2HOFS; + } + + i = task->data[14]; + while (i <= task->data[14] + 64) + { + gScanlineEffectRegBuffers[0][i] = task->data[10]; + gScanlineEffectRegBuffers[1][i] = task->data[10]; + i++; + } + + scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; + scanlineParams.initState = 1; + scanlineParams.unused9 = 0; + ScanlineEffect_SetParams(scanlineParams); + task->func = AnimTask_ExtrasensoryDistortion_Step; +} + +static void AnimTask_ExtrasensoryDistortion_Step(u8 taskId) +{ + s16 sineIndex, i; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + sineIndex = task->data[13]; + i = task->data[14]; + while (i <= task->data[15]) + { + s16 var2 = (gSineTable[sineIndex] >> task->data[12]); + if (var2 > 0) + var2 += (task->data[1] & 3); + else if (var2 < 0) + var2 -= (task->data[1] & 3); + + gScanlineEffectRegBuffers[0][i] = task->data[10] + var2; + gScanlineEffectRegBuffers[1][i] = task->data[10] + var2; + sineIndex += task->data[11]; + i++; + } + + if (++task->data[1] > 23) + task->data[0]++; + break; + case 1: + gScanlineEffect.state = 3; + task->data[0]++; + break; + case 2: + DestroyAnimVisualTask(taskId); + break; + } +} + +// Creates a cloned transparent sprite of the battler that grows and then shrinks back to original size. Used by Extrasensory +// arg0: battler +void AnimTask_TransparentCloneGrowAndShrink(u8 taskId) +{ + s16 spriteId; + s16 matrixNum; + struct Task *task = &gTasks[taskId]; + + matrixNum = AllocOamMatrix(); + if (matrixNum == 0xFF) + { + DestroyAnimVisualTask(taskId); + return; + } + + spriteId = CloneBattlerSpriteWithBlend(gBattleAnimArgs[0]); + if (spriteId < 0) + { + FreeOamMatrix(matrixNum); + DestroyAnimVisualTask(taskId); + return; + } + + gSprites[spriteId].callback = SpriteCallbackDummy; + gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_DOUBLE; + gSprites[spriteId].oam.matrixNum = matrixNum; + gSprites[spriteId].affineAnimPaused = 1; + gSprites[spriteId].subpriority++; + SetSpriteRotScale(spriteId, 256, 256, 0); + CalcCenterToCornerVec(&gSprites[spriteId], gSprites[spriteId].oam.shape, gSprites[spriteId].oam.size, gSprites[spriteId].oam.affineMode); + task->data[13] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); + task->data[14] = matrixNum; + task->data[15] = spriteId; + task->func = AnimTask_TransparentCloneGrowAndShrink_Step; +} + +static void AnimTask_TransparentCloneGrowAndShrink_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[1] += 4; + task->data[2] = 256 - (gSineTable[task->data[1]] >> 1); + SetSpriteRotScale(task->data[15], task->data[2], task->data[2], 0); + SetBattlerSpriteYOffsetFromOtherYScale(task->data[15], task->data[13]); + if (task->data[1] == 48) + task->data[0]++; + break; + case 1: + task->data[1] -= 4; + task->data[2] = 256 - (gSineTable[task->data[1]] >> 1);; + SetSpriteRotScale(task->data[15], task->data[2], task->data[2], 0); + SetBattlerSpriteYOffsetFromOtherYScale(task->data[15], task->data[13]); + if (task->data[1] == 0) + task->data[0]++; + break; + case 2: + obj_delete_but_dont_free_vram(&gSprites[task->data[15]]); + task->data[0]++; + break; + case 3: + FreeOamMatrix(task->data[14]); + DestroyAnimVisualTask(taskId); + break; + } +} + +static void AnimPsychoBoost(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y); + + if (IsContest()) + sprite->pos1.y += 12; + + sprite->data[1] = 8; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[1], 16 - sprite->data[1])); + sprite->data[0]++; + break; + case 1: + if (sprite->affineAnimEnded) + { + PlaySE12WithPanning(SE_W100, BattleAnimAdjustPanning(-64)); + ChangeSpriteAffineAnim(sprite, 1); + sprite->data[0]++; + } + break; + case 2: + if (sprite->data[2]++ > 1) + { + sprite->data[2] = 0; + sprite->data[1]--; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[1], 16 - sprite->data[1])); + if (sprite->data[1] == 0) + { + sprite->data[0]++; + sprite->invisible = TRUE; + } + } + + sprite->data[3] += 0x380; + sprite->pos2.y -= sprite->data[3] >> 8; + sprite->data[3] &= 0xFF; + break; + case 3: + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimSprite(sprite); + break; + } +} diff --git a/src/battle_anim_rock.c b/src/battle_anim_rock.c new file mode 100644 index 000000000..1f22d2976 --- /dev/null +++ b/src/battle_anim_rock.c @@ -0,0 +1,875 @@ +#include "global.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "palette.h" +#include "sound.h" +#include "task.h" +#include "trig.h" +#include "constants/rgb.h" +#include "constants/songs.h" + +static void AnimFallingRock(struct Sprite *); +static void AnimFallingRock_Step(struct Sprite *); +static void AnimRockFragment(struct Sprite *); +static void AnimFlyingSandCrescent(struct Sprite *); +static void AnimRaiseSprite(struct Sprite *); +static void AnimTask_Rollout_Step(u8 taskId); +static void AnimRolloutParticle(struct Sprite *); +static void AnimRockTomb(struct Sprite *); +static void AnimRockTomb_Step(struct Sprite *sprite); +static void AnimRockBlastRock(struct Sprite *); +static void AnimRockScatter(struct Sprite *); +static void AnimRockScatter_Step(struct Sprite *sprite); +static void AnimParticleInVortex(struct Sprite *); +static void AnimParticleInVortex_Step(struct Sprite *sprite); +static void AnimTask_LoadSandstormBackground_Step(u8 taskId); +static void sub_8111214(struct Task *task); +static u8 GetRolloutCounter(void); + +static const union AnimCmd sAnim_FlyingRock_0[] = +{ + ANIMCMD_FRAME(32, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_FlyingRock_1[] = +{ + ANIMCMD_FRAME(48, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_FlyingRock_2[] = +{ + ANIMCMD_FRAME(64, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_FlyingRock[] = +{ + sAnim_FlyingRock_0, + sAnim_FlyingRock_1, + sAnim_FlyingRock_2, +}; + +const struct SpriteTemplate gFallingRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_FlyingRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFallingRock, +}; + +const struct SpriteTemplate gRockFragmentSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_FlyingRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockFragment, +}; + +const struct SpriteTemplate gSwirlingDirtSpriteTemplate = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimParticleInVortex, +}; + +static const union AffineAnimCmd sAffineAnim_Whirlpool[] = +{ + AFFINEANIMCMD_FRAME(0xC0, 0xC0, 0, 0), + AFFINEANIMCMD_FRAME(0x2, 0xFFFD, 0, 5), + AFFINEANIMCMD_FRAME(0xFFFE, 0x3, 0, 5), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const sAffineAnims_Whirlpool[] = +{ + sAffineAnim_Whirlpool, +}; + +const struct SpriteTemplate gWhirlpoolSpriteTemplate = +{ + .tileTag = ANIM_TAG_WATER_ORB, + .paletteTag = ANIM_TAG_WATER_ORB, + .oam = &gOamData_AffineNormal_ObjBlend_16x16, + .anims = gAnims_WaterMudOrb, + .images = NULL, + .affineAnims = sAffineAnims_Whirlpool, + .callback = AnimParticleInVortex, +}; + +const struct SpriteTemplate gFireSpinSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimParticleInVortex, +}; + +const struct SpriteTemplate gFlyingSandCrescentSpriteTemplate = +{ + .tileTag = ANIM_TAG_FLYING_DIRT, + .paletteTag = ANIM_TAG_FLYING_DIRT, + .oam = &gOamData_AffineOff_ObjNormal_32x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFlyingSandCrescent, +}; + +static const struct Subsprite sFlyingSandSubsprites[] = +{ + {.x = -16, .y = 0, .shape = SPRITE_SHAPE(32x16), .size = SPRITE_SIZE(32x16), .tileOffset = 0, .priority = 1}, + {.x = 16, .y = 0, .shape = SPRITE_SHAPE(32x16), .size = SPRITE_SIZE(32x16), .tileOffset = 8, .priority = 1}, +}; + +static const struct SubspriteTable sFlyingSandSubspriteTable[] = +{ + {ARRAY_COUNT(sFlyingSandSubsprites), sFlyingSandSubsprites}, +}; + +static const union AnimCmd sAnim_BasicRock_0[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_BasicRock_1[] = +{ + ANIMCMD_FRAME(16, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_WeatherBallRockDown_0[] = +{ + ANIMCMD_FRAME(32, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_WeatherBallRockDown_1[] = +{ + ANIMCMD_FRAME(48, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_TwisterRock_0[] = +{ + ANIMCMD_FRAME(64, 1), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_TwisterRock_1[] = +{ + ANIMCMD_FRAME(80, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_BasicRock[] = +{ + sAnim_BasicRock_0, + sAnim_BasicRock_1, +}; + +static const union AnimCmd *const sAnims_WeatherBallRockDown[] = +{ + sAnim_WeatherBallRockDown_0, + sAnim_WeatherBallRockDown_1, +}; + +static const union AnimCmd *const sAnims_TwisterRock[] = +{ + sAnim_TwisterRock_0, + sAnim_TwisterRock_1, +}; + +const struct SpriteTemplate gAncientPowerRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_BasicRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRaiseSprite, +}; + +const struct SpriteTemplate gRolloutMudSpriteTemplate = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_AffineOff_ObjNormal_8x8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRolloutParticle, +}; + +const struct SpriteTemplate gRolloutRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRolloutParticle, +}; + +const struct SpriteTemplate gRockTombRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_BasicRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockTomb, +}; + +static const union AffineAnimCmd sAffineAnim_BasicRock_0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -5, 5), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sAffineAnim_BasicRock_1[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 5, 5), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const sAffineAnims_BasicRock[] = +{ + sAffineAnim_BasicRock_0, + sAffineAnim_BasicRock_1, +}; + +const struct SpriteTemplate gRockBlastRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = sAnims_BasicRock, + .images = NULL, + .affineAnims = sAffineAnims_BasicRock, + .callback = AnimRockBlastRock, +}; + +const struct SpriteTemplate gRockScatterSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = sAnims_BasicRock, + .images = NULL, + .affineAnims = sAffineAnims_BasicRock, + .callback = AnimRockScatter, +}; + +const struct SpriteTemplate gTwisterRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_TwisterRock, + .images = NULL, + .affineAnims = sAffineAnims_BasicRock, + .callback = AnimMoveTwisterParticle, +}; + +const struct SpriteTemplate gWeatherBallRockDownSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = sAnims_WeatherBallRockDown, + .images = NULL, + .affineAnims = sAffineAnims_BasicRock, + .callback = AnimWeatherBallDown, +}; + +static void AnimFallingRock(struct Sprite *sprite) +{ + if (gBattleAnimArgs[3] != 0) + SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); + + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += 14; + + StartSpriteAnim(sprite, gBattleAnimArgs[1]); + AnimateSprite(sprite); + + sprite->data[0] = 0; + sprite->data[1] = 0; + sprite->data[2] = 4; + sprite->data[3] = 16; + sprite->data[4] = -70; + sprite->data[5] = gBattleAnimArgs[2]; + + StoreSpriteCallbackInData6(sprite, AnimFallingRock_Step); + sprite->callback = TranslateSpriteInEllipseOverDuration; + sprite->callback(sprite); +} + +static void AnimFallingRock_Step(struct Sprite *sprite) +{ + sprite->pos1.x += sprite->data[5]; + + sprite->data[0] = 192; + sprite->data[1] = sprite->data[5]; + sprite->data[2] = 4; + sprite->data[3] = 32; + sprite->data[4] = -24; + + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = TranslateSpriteInEllipseOverDuration; + sprite->callback(sprite); +} + +// Animates the rock particles that are shown on the impact for Rock Blast / Rock Smash +static void AnimRockFragment(struct Sprite *sprite) +{ + StartSpriteAnim(sprite, gBattleAnimArgs[5]); + AnimateSprite(sprite); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + + sprite->pos1.y += gBattleAnimArgs[1]; + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[3]; + + InitSpriteDataForLinearTranslation(sprite); + sprite->data[3] = 0; + sprite->data[4] = 0; + + sprite->callback = TranslateSpriteLinearFixedPoint; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); +} + +// Swirls particle in vortex. Used for moves like Fire Spin or Sand Tomb +static void AnimParticleInVortex(struct Sprite *sprite) +{ + if (gBattleAnimArgs[6] == ANIM_ATTACKER) + InitSpritePosToAnimAttacker(sprite, 0); + else + InitSpritePosToAnimTarget(sprite, FALSE); + + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[2] = gBattleAnimArgs[4]; + sprite->data[3] = gBattleAnimArgs[5]; + + sprite->callback = AnimParticleInVortex_Step; +} + +static void AnimParticleInVortex_Step(struct Sprite *sprite) +{ + sprite->data[4] += sprite->data[1]; + sprite->pos2.y = -(sprite->data[4] >> 8); + sprite->pos2.x = Sin(sprite->data[5], sprite->data[3]); + sprite->data[5] = (sprite->data[5] + sprite->data[2]) & 0xFF; + + if (--sprite->data[0] == -1) + { + DestroyAnimSprite(sprite); + } +} + +void AnimTask_LoadSandstormBackground(u8 taskId) +{ + int var0; + struct BattleAnimBgData animBg; + + var0 = 0; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); + + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); + + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); + SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); + + sub_80A6B30(&animBg); + AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Sandstorm, animBg.tilesOffset); + AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_Sandstorm, 0); + LoadCompressedPalette(gBattleAnimSpritePal_FlyingDirt, animBg.paletteId * 16, 32); + + if (gBattleAnimArgs[0] && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + var0 = 1; + + gTasks[taskId].data[0] = var0; + gTasks[taskId].func = AnimTask_LoadSandstormBackground_Step; +} + +static void AnimTask_LoadSandstormBackground_Step(u8 taskId) +{ + struct BattleAnimBgData animBg; + + if (gTasks[taskId].data[0] == 0) + gBattle_BG1_X += -6; + else + gBattle_BG1_X += 6; + + gBattle_BG1_Y += -1; + + switch (gTasks[taskId].data[12]) + { + case 0: + if (++gTasks[taskId].data[10] == 4) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11]++; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 7) + { + gTasks[taskId].data[12]++; + gTasks[taskId].data[11] = 0; + } + } + break; + case 1: + if (++gTasks[taskId].data[11] == 101) + { + gTasks[taskId].data[11] = 7; + gTasks[taskId].data[12]++; + } + break; + case 2: + if (++gTasks[taskId].data[10] == 4) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11]--; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 0) + { + gTasks[taskId].data[12]++; + gTasks[taskId].data[11] = 0; + } + } + break; + case 3: + sub_80A6B30(&animBg); + sub_80A6C68(animBg.bgId); + gTasks[taskId].data[12]++; + break; + case 4: + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); + + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + DestroyAnimVisualTask(taskId); + break; + } +} + +// Animates the sprites that fly diagonally across the screen +// in Sandstorm and Heat Wave. +// arg 0: initial y pixel offset +// arg 1: projectile speed +// arg 2: y pixel drop +// arg 3: ??? unknown (possibly a color bit) +static void AnimFlyingSandCrescent(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + if (gBattleAnimArgs[3] != 0 && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x = 304; + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + sprite->data[5] = 1; + sprite->oam.matrixNum = ST_OAM_HFLIP; + } + else + { + sprite->pos1.x = -64; + } + + sprite->pos1.y = gBattleAnimArgs[0]; + SetSubspriteTables(sprite, sFlyingSandSubspriteTable); + sprite->data[1] = gBattleAnimArgs[1]; + sprite->data[2] = gBattleAnimArgs[2]; + sprite->data[0]++; + } + else + { + sprite->data[3] += sprite->data[1]; + sprite->data[4] += sprite->data[2]; + sprite->pos2.x += (sprite->data[3] >> 8); + sprite->pos2.y += (sprite->data[4] >> 8); + sprite->data[3] &= 0xFF; + sprite->data[4] &= 0xFF; + + if (sprite->data[5] == 0) + { + if (sprite->pos1.x + sprite->pos2.x > 272) + { + sprite->callback = DestroyAnimSprite; + } + } + else if (sprite->pos1.x + sprite->pos2.x < -32) + { + sprite->callback = DestroyAnimSprite; + } + } +} + +// Animates the rising rocks in Ancient Power. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: terminal y offset +// arg 3: duration +// arg 4: sprite size [1,5] +static void AnimRaiseSprite(struct Sprite *sprite) +{ + StartSpriteAnim(sprite, gBattleAnimArgs[4]); + InitSpritePosToAnimAttacker(sprite, 0); + + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[2] = sprite->pos1.x; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[2]; + + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +void AnimTask_Rollout(u8 taskId) +{ + u16 var0, var1, var2, var3; + u8 rolloutCounter; + int var5; + s16 pan1, pan2; + struct Task *task; + + task = &gTasks[taskId]; + + var0 = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + var1 = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 24; + var2 = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + var3 = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 24; + + if (BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget) + var3 = var1; + + rolloutCounter = GetRolloutCounter(); + if (rolloutCounter == 1) + task->data[8] = 32; + else + task->data[8] = 48 - (rolloutCounter * 8); + + task->data[0] = 0; + task->data[11] = 0; + task->data[9] = 0; + task->data[12] = 1; + + var5 = task->data[8]; + if (var5 < 0) + var5 += 7; + + task->data[10] = (var5 >> 3) - 1; + + task->data[2] = var0 * 8; + task->data[3] = var1 * 8; + task->data[4] = ((var2 - var0) * 8) / task->data[8]; + task->data[5] = ((var3 - var1) * 8) / task->data[8]; + task->data[6] = 0; + task->data[7] = 0; + + pan1 = BattleAnimAdjustPanning(-64); + pan2 = BattleAnimAdjustPanning(63); + + task->data[13] = pan1; + task->data[14] = (pan2 - pan1) / task->data[8]; + task->data[1] = rolloutCounter; + task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + + task->func = AnimTask_Rollout_Step; +} + +static void AnimTask_Rollout_Step(u8 taskId) +{ + struct Task *task; + + task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[6] -= task->data[4]; + task->data[7] -= task->data[5]; + gSprites[task->data[15]].pos2.x = task->data[6] >> 3; + gSprites[task->data[15]].pos2.y = task->data[7] >> 3; + + if (++task->data[9] == 10) + { + task->data[11] = 20; + task->data[0]++; + } + + PlaySE12WithPanning(SE_W029, task->data[13]); + break; + case 1: + if (--task->data[11] == 0) + task->data[0]++; + break; + case 2: + if (--task->data[9] != 0) + { + task->data[6] += task->data[4]; + task->data[7] += task->data[5]; + } + else + { + task->data[6] = 0; + task->data[7] = 0; + task->data[0]++; + } + + gSprites[task->data[15]].pos2.x = task->data[6] >> 3; + gSprites[task->data[15]].pos2.y = task->data[7] >> 3; + break; + case 3: + task->data[2] += task->data[4]; + task->data[3] += task->data[5]; + if (++task->data[9] >= task->data[10]) + { + task->data[9] = 0; + sub_8111214(task); + task->data[13] += task->data[14]; + PlaySE12WithPanning(SE_W091, task->data[13]); + } + + if (--task->data[8] == 0) + { + task->data[0]++; + } + break; + case 4: + if (task->data[11] == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_8111214(struct Task *task) +{ + const struct SpriteTemplate *spriteTemplate; + int tileOffset; + u16 x, y; + u8 spriteId; + + switch (task->data[1]) + { + case 1: + spriteTemplate = &gRolloutMudSpriteTemplate; + tileOffset = 0; + break; + case 2: + case 3: + spriteTemplate = &gRolloutRockSpriteTemplate; + tileOffset = 80; + break; + case 4: + spriteTemplate = &gRolloutRockSpriteTemplate; + tileOffset = 64; + break; + case 5: + spriteTemplate = &gRolloutRockSpriteTemplate; + tileOffset = 48; + break; + default: + return; + } + + x = task->data[2] >> 3; + y = task->data[3] >> 3; + x += (task->data[12] * 4); + + spriteId = CreateSprite(spriteTemplate, x, y, 35); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].data[0] = 18; + gSprites[spriteId].data[2] = ((task->data[12] * 20) + x) + (task->data[1] * 3); + gSprites[spriteId].data[4] = y; + gSprites[spriteId].data[5] = -16 - (task->data[1] * 2); + gSprites[spriteId].oam.tileNum += tileOffset; + + InitAnimArcTranslation(&gSprites[spriteId]); + task->data[11]++; + } + + task->data[12] *= -1; +} + +static void AnimRolloutParticle(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + { + u8 taskId = FindTaskIdByFunc(AnimTask_Rollout_Step); + if (taskId != 0xFF) + gTasks[taskId].data[11]--; + + DestroySprite(sprite); + } +} + +static u8 GetRolloutCounter(void) +{ + u8 retVal = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer; + u8 var0 = retVal - 1; + if (var0 > 4) + retVal = 1; + + return retVal; +} + +static void AnimRockTomb(struct Sprite *sprite) +{ + StartSpriteAnim(sprite, gBattleAnimArgs[4]); + + sprite->pos2.x = gBattleAnimArgs[0]; + sprite->data[2] = gBattleAnimArgs[1]; + sprite->data[3] -= gBattleAnimArgs[2]; + sprite->data[0] = 3; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->callback = AnimRockTomb_Step; + sprite->invisible = TRUE; +} + +static void AnimRockTomb_Step(struct Sprite *sprite) +{ + sprite->invisible = FALSE; + if (sprite->data[3] != 0) + { + sprite->pos2.y = sprite->data[2] + sprite->data[3]; + sprite->data[3] += sprite->data[0]; + sprite->data[0]++; + if (sprite->data[3] > 0) + { + sprite->data[3] = 0; + } + } + else + { + if (--sprite->data[1] == 0) + DestroyAnimSprite(sprite); + } +} + +static void AnimRockBlastRock(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + StartSpriteAffineAnim(sprite, 1); + + TranslateAnimSpriteToTargetMonLocation(sprite); +} + +static void AnimRockScatter(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + + sprite->data[1] = gBattleAnimArgs[0]; + sprite->data[2] = gBattleAnimArgs[1]; + sprite->data[5] = gBattleAnimArgs[2]; + + StartSpriteAnim(sprite, gBattleAnimArgs[3]); + sprite->callback = AnimRockScatter_Step; +} + +static void AnimRockScatter_Step(struct Sprite *sprite) +{ + sprite->data[0] += 8; + sprite->data[3] += sprite->data[1]; + sprite->data[4] += sprite->data[2]; + + sprite->pos2.x += sprite->data[3] / 40; + sprite->pos2.y -= Sin(sprite->data[0], sprite->data[5]); + + if (sprite->data[0] > 140) + DestroyAnimSprite(sprite); +} + +void AnimTask_GetSeismicTossDamageLevel(u8 taskId) +{ + if (gAnimMoveDmg < 33) + gBattleAnimArgs[ARG_RET_ID] = 0; + if ((u32)gAnimMoveDmg - 33 < 33) + gBattleAnimArgs[ARG_RET_ID] = 1; + if (gAnimMoveDmg > 65) + gBattleAnimArgs[ARG_RET_ID] = 2; + + DestroyAnimVisualTask(taskId); +} + +void AnimTask_MoveSeismicTossBg(u8 taskId) +{ + if (gTasks[taskId].data[0] == 0) + { + sub_80A6DAC(FALSE); + gTasks[taskId].data[1] = 200; + } + + gBattle_BG3_Y += gTasks[taskId].data[1] / 10; + gTasks[taskId].data[1] -= 3; + + if (gTasks[taskId].data[0] == 120) + { + sub_80A6DAC(TRUE); + DestroyAnimVisualTask(taskId); + } + + gTasks[taskId].data[0]++; +} + +void AnimTask_SeismicTossBgAccelerateDownAtEnd(u8 taskId) +{ + if (gTasks[taskId].data[0] == 0) + { + sub_80A6DAC(FALSE); + gTasks[taskId].data[0]++; + gTasks[taskId].data[2] = gBattle_BG3_Y; + } + + gTasks[taskId].data[1] += 80; + gTasks[taskId].data[1] &= 0xFF; + gBattle_BG3_Y = gTasks[taskId].data[2] + Cos(4, gTasks[taskId].data[1]); + + if (gBattleAnimArgs[7] == 0xFFF) + { + gBattle_BG3_Y = 0; + sub_80A6DAC(TRUE); + DestroyAnimVisualTask(taskId); + } +} diff --git a/src/battle_anim_smokescreen.c b/src/battle_anim_smokescreen.c new file mode 100644 index 000000000..a8c043e67 --- /dev/null +++ b/src/battle_anim_smokescreen.c @@ -0,0 +1,217 @@ +#include "global.h" +#include "battle_gfx_sfx_util.h" +#include "data.h" +#include "decompress.h" +#include "graphics.h" +#include "sprite.h" +#include "util.h" +#include "constants/pokemon.h" + +static void SmokescreenImpact_Callback(struct Sprite *); +static void SpriteCB_DestroySprite(struct Sprite *sprite); + +// The below data for smokescreen starts and ends with some data that belongs to battle_gfx_sfx_util.c + +const u8 gUnknown_0831C604[] = +{ + [NATURE_HARDY] = 0, + [NATURE_LONELY] = 0, + [NATURE_BRAVE] = 1, + [NATURE_ADAMANT] = 0, + [NATURE_NAUGHTY] = 1, + [NATURE_BOLD] = 1, + [NATURE_DOCILE] = 2, + [NATURE_RELAXED] = 0, + [NATURE_IMPISH] = 0, + [NATURE_LAX] = 0, + [NATURE_TIMID] = 1, + [NATURE_HASTY] = 1, + [NATURE_SERIOUS] = 1, + [NATURE_JOLLY] = 0, + [NATURE_NAIVE] = 2, + [NATURE_MODEST] = 1, + [NATURE_MILD] = 0, + [NATURE_QUIET] = 1, + [NATURE_BASHFUL] = 1, + [NATURE_RASH] = 0, + [NATURE_CALM] = 0, + [NATURE_GENTLE] = 0, + [NATURE_SASSY] = 1, + [NATURE_CAREFUL] = 1, + [NATURE_QUIRKY] = 0, +}; + +static const struct CompressedSpriteSheet sSmokescreenImpactSpriteSheet = +{ + .data = gSmokescreenImpactTiles, .size = 0x180, .tag = 55019 +}; + +static const struct CompressedSpritePalette sSmokescreenImpactSpritePalette = +{ + .data = gSmokescreenImpactPalette, .tag = 55019 +}; + +static const struct OamData sOamData_SmokescreenImpact = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(16x16), + .x = 0, + .matrixNum = 0, + .size = SPRITE_SIZE(16x16), + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0 +}; + +static const union AnimCmd sAnim_SmokescreenImpact_0[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(4, 4), + ANIMCMD_FRAME(8, 4), + ANIMCMD_END +}; + +static const union AnimCmd sAnim_SmokescreenImpact_1[] = +{ + ANIMCMD_FRAME(0, 4, .hFlip = TRUE), + ANIMCMD_FRAME(4, 4, .hFlip = TRUE), + ANIMCMD_FRAME(8, 4, .hFlip = TRUE), + ANIMCMD_END +}; + +static const union AnimCmd sAnim_SmokescreenImpact_2[] = +{ + ANIMCMD_FRAME(0, 4, .vFlip = TRUE), + ANIMCMD_FRAME(4, 4, .vFlip = TRUE), + ANIMCMD_FRAME(8, 4, .vFlip = TRUE), + ANIMCMD_END +}; + +static const union AnimCmd sAnim_SmokescreenImpact_3[] = +{ + ANIMCMD_FRAME(0, 4, .hFlip = TRUE, .vFlip = TRUE), + ANIMCMD_FRAME(4, 4, .hFlip = TRUE, .vFlip = TRUE), + ANIMCMD_FRAME(8, 4, .hFlip = TRUE, .vFlip = TRUE), + ANIMCMD_END +}; + +static const union AnimCmd *const sAnims_SmokescreenImpact[] = +{ + sAnim_SmokescreenImpact_0, + sAnim_SmokescreenImpact_1, + sAnim_SmokescreenImpact_2, + sAnim_SmokescreenImpact_3, +}; + +static const struct SpriteTemplate sSmokescreenImpactSpriteTemplate = +{ + .tileTag = 55019, + .paletteTag = 55019, + .oam = &sOamData_SmokescreenImpact, + .anims = sAnims_SmokescreenImpact, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_DestroySprite +}; + +const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow = +{ + .data = gEnemyMonShadow_Gfx, .size = 0x80, .tag = 55129 +}; + +static const struct OamData gUnknown_0831C6A8 = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(32x8), + .x = 0, + .matrixNum = 0, + .size = SPRITE_SIZE(32x8), + .tileNum = 0, + .priority = 3, + .paletteNum = 0, + .affineParam = 0 +}; + +const struct SpriteTemplate gSpriteTemplate_EnemyShadow = +{ + .tileTag = 55129, + .paletteTag = 55039, + .oam = &gUnknown_0831C6A8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_SetInvisible +}; + +u8 SmokescreenImpact(s16 x, s16 y, u8 a3) +{ + u8 mainSpriteId; + u8 spriteId1, spriteId2, spriteId3, spriteId4; + struct Sprite *mainSprite; + + if (GetSpriteTileStartByTag(sSmokescreenImpactSpriteSheet.tag) == 0xFFFF) + { + LoadCompressedSpriteSheetUsingHeap(&sSmokescreenImpactSpriteSheet); + LoadCompressedSpritePaletteUsingHeap(&sSmokescreenImpactSpritePalette); + } + + mainSpriteId = CreateInvisibleSpriteWithCallback(SmokescreenImpact_Callback); + mainSprite = &gSprites[mainSpriteId]; + mainSprite->data[1] = a3; + + spriteId1 = CreateSprite(&sSmokescreenImpactSpriteTemplate, x - 16, y - 16, 2); + gSprites[spriteId1].data[0] = mainSpriteId; + mainSprite->data[0]++; + AnimateSprite(&gSprites[spriteId1]); + + spriteId2 = CreateSprite(&sSmokescreenImpactSpriteTemplate, x, y - 16, 2); + gSprites[spriteId2].data[0] = mainSpriteId; + mainSprite->data[0]++; + StartSpriteAnim(&gSprites[spriteId2], 1); + AnimateSprite(&gSprites[spriteId2]); + + spriteId3 = CreateSprite(&sSmokescreenImpactSpriteTemplate, x - 16, y, 2); + gSprites[spriteId3].data[0] = mainSpriteId; + mainSprite->data[0]++; + StartSpriteAnim(&gSprites[spriteId3], 2); + AnimateSprite(&gSprites[spriteId3]); + + spriteId4 = CreateSprite(&sSmokescreenImpactSpriteTemplate, x, y, 2); + gSprites[spriteId4].data[0] = mainSpriteId; + mainSprite->data[0]++; + StartSpriteAnim(&gSprites[spriteId4], 3); + AnimateSprite(&gSprites[spriteId4]); + + return mainSpriteId; +} + +static void SmokescreenImpact_Callback(struct Sprite *sprite) +{ + if (!sprite->data[0]) + { + FreeSpriteTilesByTag(sSmokescreenImpactSpriteSheet.tag); + FreeSpritePaletteByTag(sSmokescreenImpactSpritePalette.tag); + if (!sprite->data[1]) + DestroySprite(sprite); + else + sprite->callback = SpriteCallbackDummy; + } +} + +static void SpriteCB_DestroySprite(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + gSprites[sprite->data[0]].data[0]--; + DestroySprite(sprite); + } +} diff --git a/src/battle_anim_utility_funcs.c b/src/battle_anim_utility_funcs.c index 5d93a7cd1..dcef7d483 100644 --- a/src/battle_anim_utility_funcs.c +++ b/src/battle_anim_utility_funcs.c @@ -729,7 +729,7 @@ static void AnimTask_UpdateSlidingBg(u8 taskId) gTasks[taskId].data[10] &= 0xFF; gTasks[taskId].data[11] &= 0xFF; - if (gBattleAnimArgs[ARG_RET_ID] == gTasks[taskId].data[3]) + if (gBattleAnimArgs[7] == gTasks[taskId].data[3]) { gBattle_BG3_X = 0; gBattle_BG3_Y = 0; @@ -1058,7 +1058,7 @@ void AnimTask_SetAttackerInvisibleWaitForSignal(u8 taskId) static void AnimTask_WaitAndRestoreVisibility(u8 taskId) { - if (gBattleAnimArgs[ARG_RET_ID] == 0x1000) + if (gBattleAnimArgs[7] == 0x1000) { gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].invisible = (u8)gTasks[taskId].data[0] & 1; DestroyTask(taskId); diff --git a/src/battle_anim_water.c b/src/battle_anim_water.c new file mode 100644 index 000000000..5810b6bdc --- /dev/null +++ b/src/battle_anim_water.c @@ -0,0 +1,2219 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "palette.h" +#include "random.h" +#include "scanline_effect.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "util.h" +#include "constants/battle.h" +#include "constants/rgb.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 +const u8 gUnknown_8593C80[] = INCBIN_U8("graphics/unknown/unknown_593C80.4bpp"); +const u8 gUnknown_8593FFC[] = INCBIN_U8("graphics/unknown/unknown_593FFC.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 = Random2() % 240; + y = Random2() % 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] <= 13) + { + sprite->pos2.x++; + 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_80A6B30(&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 + { + AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_SurfContest, 1); + } + AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Surf, animBg.tilesOffset); + if (gBattleAnimArgs[0] == 0) + LoadCompressedPalette(gBattleAnimBgPalette_Surf, animBg.paletteId * 16, 32); + else + LoadCompressedPalette(gBattleAnimBackgroundImageMuddyWater_Pal, 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_80A6B30\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 r1, =gBattleAnimBgTilemap_SurfContest\n\ + mov r0, sp\n\ + movs r2, 0x1\n\ + bl AnimLoadCompressedBgTilemapHandleContest\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, =gBattleAnimBackgroundImageMuddyWater_Pal\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_80A6B30(&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_80A6B30\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_80A6C68(1); + sub_80A6C68(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 = (Random2() & 0xFF) | 256; + randData2 = (Random2() & 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_80A805C(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_80A80C8(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_80A805C(task, task->data[15], 224, 0x200, 384, 224, 8); + task->data[3] = 0; + task->data[0]++; + } + break; + case 3: + if (sub_80A80C8(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_80A805C(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_80A80C8(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] = (Random2() & 0x1F) - 16 + sprite->pos1.x; + sprite->data[4] = (Random2() & 0x1F) - 16 + sprite->pos1.y; + sprite->data[5] = ~(Random2() & 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 + (Random2() % 10) - 5; + s16 randomSomethingX = -xDiff + (Random2() % 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 Random2\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 Random2\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 diff --git a/src/bug.c b/src/bug.c deleted file mode 100644 index ea3df8098..000000000 --- a/src/bug.c +++ /dev/null @@ -1,492 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "gpu_regs.h" -#include "trig.h" -#include "constants/rgb.h" - -static void AnimMegahornHorn(struct Sprite *); -static void AnimLeechLifeNeedle(struct Sprite *); -static void AnimTranslateWebThread(struct Sprite *); -static void AnimTranslateWebThread_Step(struct Sprite *); -static void AnimStringWrap(struct Sprite *); -static void AnimStringWrap_Step(struct Sprite *); -static void AnimSpiderWeb(struct Sprite *); -static void AnimSpiderWeb_Step(struct Sprite *); -static void AnimSpiderWeb_End(struct Sprite *); -static void AnimTranslateStinger(struct Sprite *); -static void AnimMissileArc(struct Sprite *); -static void AnimMissileArc_Step(struct Sprite *); -static void AnimTailGlowOrb(struct Sprite *); - -static const union AffineAnimCmd sAffineAnim_MegahornHorn_0[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 30, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_MegahornHorn_1[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, -99, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_MegahornHorn_2[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 94, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_MegahornHorn[] = -{ - sAffineAnim_MegahornHorn_0, - sAffineAnim_MegahornHorn_1, - sAffineAnim_MegahornHorn_2, -}; - -const struct SpriteTemplate gMegahornHornSpriteTemplate = -{ - .tileTag = ANIM_TAG_HORN_HIT_2, - .paletteTag = ANIM_TAG_HORN_HIT_2, - .oam = &gOamData_AffineDouble_ObjNormal_32x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_MegahornHorn, - .callback = AnimMegahornHorn, -}; - -static const union AffineAnimCmd sAffineAnim_LeechLifeNeedle_0[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, -33, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_LeechLifeNeedle_1[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 96, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_LeechLifeNeedle_2[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, -96, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_LeechLifeNeedle[] = -{ - sAffineAnim_LeechLifeNeedle_0, - sAffineAnim_LeechLifeNeedle_1, - sAffineAnim_LeechLifeNeedle_2, -}; - -const struct SpriteTemplate gLeechLifeNeedleSpriteTemplate = -{ - .tileTag = ANIM_TAG_NEEDLE, - .paletteTag = ANIM_TAG_NEEDLE, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_LeechLifeNeedle, - .callback = AnimLeechLifeNeedle, -}; - -const struct SpriteTemplate gWebThreadSpriteTemplate = -{ - .tileTag = ANIM_TAG_WEB_THREAD, - .paletteTag = ANIM_TAG_WEB_THREAD, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimTranslateWebThread, -}; - -const struct SpriteTemplate gStringWrapSpriteTemplate = -{ - .tileTag = ANIM_TAG_STRING, - .paletteTag = ANIM_TAG_STRING, - .oam = &gOamData_AffineOff_ObjNormal_64x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimStringWrap, -}; - -static const union AffineAnimCmd sAffineAnim_SpiderWeb[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), - AFFINEANIMCMD_FRAME(0x6, 0x6, 0, 1), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd *const sAffineAnims_SpiderWeb[] = -{ - sAffineAnim_SpiderWeb, -}; - -const struct SpriteTemplate gSpiderWebSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPIDER_WEB, - .paletteTag = ANIM_TAG_SPIDER_WEB, - .oam = &gOamData_AffineDouble_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_SpiderWeb, - .callback = AnimSpiderWeb, -}; - -const struct SpriteTemplate gLinearStingerSpriteTemplate = -{ - .tileTag = ANIM_TAG_NEEDLE, - .paletteTag = ANIM_TAG_NEEDLE, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimTranslateStinger, -}; - -const struct SpriteTemplate gPinMissileSpriteTemplate = -{ - .tileTag = ANIM_TAG_NEEDLE, - .paletteTag = ANIM_TAG_NEEDLE, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimMissileArc, -}; - -const struct SpriteTemplate gIcicleSpearSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICICLE_SPEAR, - .paletteTag = ANIM_TAG_ICICLE_SPEAR, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimMissileArc, -}; - -static const union AffineAnimCmd sAffineAnim_TailGlowOrb[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 18), - AFFINEANIMCMD_LOOP(0), - AFFINEANIMCMD_FRAME(0xFFFB, 0xFFFB, 0, 8), - AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 8), - AFFINEANIMCMD_LOOP(5), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_TailGlowOrb[] = -{ - sAffineAnim_TailGlowOrb, -}; - -const struct SpriteTemplate gTailGlowOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .oam = &gOamData_AffineNormal_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_TailGlowOrb, - .callback = AnimTailGlowOrb, -}; - -static void AnimMegahornHorn(struct Sprite *sprite) -{ - if (IsContest()) - { - StartSpriteAffineAnim(sprite, 2); - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - } - else if (!GetBattlerSide(gBattleAnimTarget)) - { - StartSpriteAffineAnim(sprite, 1); - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - } - - sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimTarget, 2) + gBattleAnimArgs[0]; - sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimTarget, 3) + gBattleAnimArgs[1]; - sprite->data[0] = gBattleAnimArgs[4]; - - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2]; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + gBattleAnimArgs[3]; - - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -static void AnimLeechLifeNeedle(struct Sprite *sprite) -{ - if (IsContest()) - { - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - StartSpriteAffineAnim(sprite, 2); - } - else if (!GetBattlerSide(gBattleAnimTarget)) - { - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - } - - sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimTarget, 2) + gBattleAnimArgs[0]; - sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimTarget, 3) + gBattleAnimArgs[1]; - sprite->data[0] = gBattleAnimArgs[2]; - - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Creates a single web thread that travels from attacker to target. -// Used by MOVE_STRING_SHOT and MOVE_SPIDER_WEB in their first move phase. -// arg 0: x -// arg 1: y -// arg 2: controls the left-to-right movement -// arg 3: amplitude -// arg 4: if targets both opponents -static void AnimTranslateWebThread(struct Sprite *sprite) -{ - if (IsContest()) - gBattleAnimArgs[2] /= 2; - - InitSpritePosToAnimAttacker(sprite, TRUE); - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[1] = sprite->pos1.x; - sprite->data[3] = sprite->pos1.y; - - if (!gBattleAnimArgs[4]) - { - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - } - else - { - SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); - } - - sub_80A6FD4(sprite); - sprite->data[5] = gBattleAnimArgs[3]; - sprite->callback = AnimTranslateWebThread_Step; -} - -static void AnimTranslateWebThread_Step(struct Sprite *sprite) -{ - if (AnimTranslateLinear(sprite)) - { - DestroyAnimSprite(sprite); - return; - } - - sprite->pos2.x += Sin(sprite->data[6], sprite->data[5]); - sprite->data[6] = (sprite->data[6] + 13) & 0xFF; -} - -// Second stage of String Shot -static void AnimStringWrap(struct Sprite *sprite) -{ - SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); - if (GetBattlerSide(gBattleAnimAttacker)) - sprite->pos1.x -= gBattleAnimArgs[0]; - else - sprite->pos1.x += gBattleAnimArgs[0]; - - sprite->pos1.y += gBattleAnimArgs[1]; - if (!GetBattlerSide(gBattleAnimTarget)) - sprite->pos1.y += 8; - - sprite->callback = AnimStringWrap_Step; -} - -static void AnimStringWrap_Step(struct Sprite *sprite) -{ - if (++sprite->data[0] == 3) - { - sprite->data[0] = 0; - sprite->invisible ^= 1; - } - - if (++sprite->data[1] == 51) - { - DestroyAnimSprite(sprite); - } -} - -static void AnimSpiderWeb(struct Sprite *sprite) -{ - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); - - sprite->data[0] = 16; - sprite->callback = AnimSpiderWeb_Step; -} - -static void AnimSpiderWeb_Step(struct Sprite *sprite) -{ - if (sprite->data[2] < 20) - { - sprite->data[2]++; - } - else if (sprite->data[1]++ & 1) - { - sprite->data[0]--; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[0], 16 - sprite->data[0])); - - if (sprite->data[0] == 0) - { - sprite->invisible = TRUE; - sprite->callback = AnimSpiderWeb_End; - } - } -} - -static void AnimSpiderWeb_End(struct Sprite *sprite) -{ - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - DestroyAnimSprite(sprite); -} - -// Translates a stinger sprite linearly to a destination location. The sprite is -// initially rotated so that it appears to be traveling in a straight line. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: target x pixel offset -// arg 3: target y pixel offset -// arg 4: duration -static void AnimTranslateStinger(struct Sprite *sprite) -{ - s16 lVarX, lVarY; - u16 rot; - - if (IsContest()) - { - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - } - else - { - if (GetBattlerSide(gBattleAnimAttacker)) - { - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - } - } - - if (!IsContest() && GetBattlerSide(gBattleAnimAttacker) == GetBattlerSide(gBattleAnimTarget)) - { - if (GetBattlerPosition(gBattleAnimTarget) == B_POSITION_PLAYER_LEFT - || GetBattlerPosition(gBattleAnimTarget) == B_POSITION_OPPONENT_LEFT) - { - s16 temp1, temp2; - - temp1 = gBattleAnimArgs[2]; - gBattleAnimArgs[2] = -temp1; - - temp2 = gBattleAnimArgs[0]; - gBattleAnimArgs[0] = -temp2; - } - } - - InitSpritePosToAnimAttacker(sprite, 1); - - lVarX = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2]; - lVarY = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + gBattleAnimArgs[3]; - rot = ArcTan2Neg(lVarX - sprite->pos1.x, lVarY - sprite->pos1.y); - rot += 0xC000; - TrySetSpriteRotScale(sprite, FALSE, 0x100, 0x100, rot); - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[2] = lVarX; - sprite->data[4] = lVarY; - - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Rotates sprite and moves it in an arc, so that it appears like a missle or arrow traveling. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: target x pixel offset -// arg 3: target y pixel offset -// arg 4: duration -// arg 5: wave amplitude -static void AnimMissileArc(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, 1); - - if (GetBattlerSide(gBattleAnimAttacker)) - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2]; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + gBattleAnimArgs[3]; - sprite->data[5] = gBattleAnimArgs[5]; - InitAnimArcTranslation(sprite); - - sprite->callback = AnimMissileArc_Step; - sprite->invisible = TRUE; -} - -static void AnimMissileArc_Step(struct Sprite *sprite) -{ - sprite->invisible = FALSE; - - if (TranslateAnimHorizontalArc(sprite)) - { - DestroyAnimSprite(sprite); - } - else - { - s16 tempData[8]; - u16 *data = sprite->data; - u16 x1 = sprite->pos1.x; - s16 x2 = sprite->pos2.x; - u16 y1 = sprite->pos1.y; - s16 y2 = sprite->pos2.y; - int i; - - for (i = 0; i < 8; i++) - tempData[i] = data[i]; - - x2 += x1; - y2 += y1; - - if (!TranslateAnimHorizontalArc(sprite)) - { - u16 rotation = ArcTan2Neg(sprite->pos1.x + sprite->pos2.x - x2, - sprite->pos1.y + sprite->pos2.y - y2); - rotation += 0xC000; - TrySetSpriteRotScale(sprite, FALSE, 0x100, 0x100, rotation); - - for (i = 0; i < 8; i++) - data[i] = tempData[i]; - } - } -} - -static void AnimTailGlowOrb(struct Sprite *sprite) -{ - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + 18; - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3) + 18; - } - - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = RunStoredCallbackWhenAffineAnimEnds; -} diff --git a/src/dark.c b/src/dark.c deleted file mode 100644 index dc3e8c83c..000000000 --- a/src/dark.c +++ /dev/null @@ -1,993 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "contest.h" -#include "gpu_regs.h" -#include "graphics.h" -#include "palette.h" -#include "scanline_effect.h" -#include "trig.h" -#include "util.h" -#include "constants/rgb.h" - -static void sub_81138D4(struct Sprite *); -static void AnimBite(struct Sprite *); -static void AnimTearDrop(struct Sprite *); -static void AnimClawSlash(struct Sprite *); -static void AnimTask_AttackerFadeToInvisible_Step(u8); -static void AnimTask_AttackerFadeFromInvisible_Step(u8); -static void sub_8113950(struct Sprite *); -static void AnimBite_Step1(struct Sprite *); -static void AnimBite_Step2(struct Sprite *); -static void AnimTearDrop_Step(struct Sprite *); -static void AnimTask_MoveAttackerMementoShadow_Step(u8); -static void AnimTask_MoveTargetMementoShadow_Step(u8); -static void sub_8114244(struct Task *); -static void sub_8114374(u8); -static void AnimTask_MetallicShine_Step(u8); - -// Unused -const struct SpriteTemplate gUnknown_08596FC8 = -{ - .tileTag = ANIM_TAG_TIED_BAG, - .paletteTag = ANIM_TAG_TIED_BAG, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_81138D4, -}; - -static const union AffineAnimCmd sAffineAnim_Bite_0[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_Bite_1[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 32, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_Bite_2[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 64, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_Bite_3[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 96, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_Bite_4[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, -128, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_Bite_5[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, -96, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_Bite_6[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, -64, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_Bite_7[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, -32, 1), - AFFINEANIMCMD_END, -}; - -const union AffineAnimCmd *const gAffineAnims_Bite[] = -{ - sAffineAnim_Bite_0, - sAffineAnim_Bite_1, - sAffineAnim_Bite_2, - sAffineAnim_Bite_3, - sAffineAnim_Bite_4, - sAffineAnim_Bite_5, - sAffineAnim_Bite_6, - sAffineAnim_Bite_7, -}; - -const struct SpriteTemplate gSharpTeethSpriteTemplate = -{ - .tileTag = ANIM_TAG_SHARP_TEETH, - .paletteTag = ANIM_TAG_SHARP_TEETH, - .oam = &gOamData_AffineNormal_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gAffineAnims_Bite, - .callback = AnimBite, -}; - -const struct SpriteTemplate gClampJawSpriteTemplate = -{ - .tileTag = ANIM_TAG_CLAMP, - .paletteTag = ANIM_TAG_CLAMP, - .oam = &gOamData_AffineNormal_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gAffineAnims_Bite, - .callback = AnimBite, -}; - -static const union AffineAnimCmd sAffineAnim_TearDrop_0[] = -{ - AFFINEANIMCMD_FRAME(0xC0, 0xC0, 80, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, -2, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_TearDrop_1[] = -{ - AFFINEANIMCMD_FRAME(0xC0, 0xC0, -80, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 2, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_TearDrop[] = -{ - sAffineAnim_TearDrop_0, - sAffineAnim_TearDrop_1, -}; - -const struct SpriteTemplate gTearDropSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_BUBBLES, - .paletteTag = ANIM_TAG_SMALL_BUBBLES, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_TearDrop, - .callback = AnimTearDrop, -}; - -static const union AnimCmd sAnim_ClawSlash_0[] = -{ - ANIMCMD_FRAME(0, 4), - ANIMCMD_FRAME(16, 4), - ANIMCMD_FRAME(32, 4), - ANIMCMD_FRAME(48, 4), - ANIMCMD_FRAME(64, 4), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_ClawSlash_1[] = -{ - ANIMCMD_FRAME(0, 4, .hFlip = TRUE), - ANIMCMD_FRAME(16, 4, .hFlip = TRUE), - ANIMCMD_FRAME(32, 4, .hFlip = TRUE), - ANIMCMD_FRAME(48, 4, .hFlip = TRUE), - ANIMCMD_FRAME(64, 4, .hFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_ClawSlash[] = -{ - sAnim_ClawSlash_0, - sAnim_ClawSlash_1, -}; - -const struct SpriteTemplate gClawSlashSpriteTemplate = -{ - .tileTag = ANIM_TAG_CLAW_SLASH, - .paletteTag = ANIM_TAG_CLAW_SLASH, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_ClawSlash, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimClawSlash, -}; - -void AnimTask_AttackerFadeToInvisible(u8 taskId) -{ - int battler; - gTasks[taskId].data[0] = gBattleAnimArgs[0]; - battler = gBattleAnimAttacker; - gTasks[taskId].data[1] = 16; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); - if (GetBattlerSpriteBGPriorityRank(battler) == 1) - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); - else - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2); - - gTasks[taskId].func = AnimTask_AttackerFadeToInvisible_Step; -} - -static void AnimTask_AttackerFadeToInvisible_Step(u8 taskId) -{ - u8 blendA = gTasks[taskId].data[1] >> 8; - u8 blendB = gTasks[taskId].data[1]; - if (gTasks[taskId].data[2] == (u8)gTasks[taskId].data[0]) - { - blendA++; - blendB--; - gTasks[taskId].data[1] = BLDALPHA_BLEND(blendB, blendA); - SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1]); - gTasks[taskId].data[2] = 0; - if (blendA == 16) - { - gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].invisible = TRUE; - DestroyAnimVisualTask(taskId); - } - } - else - { - gTasks[taskId].data[2]++; - } -} - -void AnimTask_AttackerFadeFromInvisible(u8 taskId) -{ - gTasks[taskId].data[0] = gBattleAnimArgs[0]; - gTasks[taskId].data[1] = BLDALPHA_BLEND(0, 16); - gTasks[taskId].func = AnimTask_AttackerFadeFromInvisible_Step; - SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1]); -} - -static void AnimTask_AttackerFadeFromInvisible_Step(u8 taskId) -{ - u8 blendA = gTasks[taskId].data[1] >> 8; - u8 blendB = gTasks[taskId].data[1]; - if (gTasks[taskId].data[2] == (u8)gTasks[taskId].data[0]) - { - blendA--; - blendB++; - gTasks[taskId].data[1] = (blendA << 8) | blendB; - SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1]); - gTasks[taskId].data[2] = 0; - if (blendA == 0) - { - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - DestroyAnimVisualTask(taskId); - } - } - else - { - gTasks[taskId].data[2]++; - } -} - -void AnimTask_InitAttackerFadeFromInvisible(u8 taskId) -{ - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); - if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1) - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); - else - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2); - - DestroyAnimVisualTask(taskId); -} - -static void sub_81138D4(struct Sprite *sprite) -{ - sprite->data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->data[3] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - sprite->data[0] = 0x7E; - InitSpriteDataForLinearTranslation(sprite); - sprite->data[3] = -sprite->data[1]; - sprite->data[4] = -sprite->data[2]; - sprite->data[6] = 0xFFD8; - sprite->callback = sub_8113950; - sprite->callback(sprite); -} - -static void sub_8113950(struct Sprite *sprite) -{ - sprite->data[3] += sprite->data[1]; - sprite->data[4] += sprite->data[2]; - sprite->pos2.x = sprite->data[3] >> 8; - sprite->pos2.y = sprite->data[4] >> 8; - if (sprite->data[7] == 0) - { - sprite->data[3] += sprite->data[1]; - sprite->data[4] += sprite->data[2]; - sprite->pos2.x = sprite->data[3] >> 8; - sprite->pos2.y = sprite->data[4] >> 8; - sprite->data[0]--; - } - - sprite->pos2.y += Sin(sprite->data[5], sprite->data[6]); - sprite->data[5] = (sprite->data[5] + 3) & 0xFF; - if (sprite->data[5] > 0x7F) - { - sprite->data[5] = 0; - sprite->data[6] += 20; - sprite->data[7]++; - } - - if (--sprite->data[0] == 0) - DestroyAnimSprite(sprite); -} - -// Move sprite inward for Bite/Crunch and Clamp -static void AnimBite(struct Sprite *sprite) -{ - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - StartSpriteAffineAnim(sprite, gBattleAnimArgs[2]); - sprite->data[0] = gBattleAnimArgs[3]; - sprite->data[1] = gBattleAnimArgs[4]; - sprite->data[2] = gBattleAnimArgs[5]; - sprite->callback = AnimBite_Step1; -} - -static void AnimBite_Step1(struct Sprite *sprite) -{ - sprite->data[4] += sprite->data[0]; - sprite->data[5] += sprite->data[1]; - sprite->pos2.x = sprite->data[4] >> 8; - sprite->pos2.y = sprite->data[5] >> 8; - if (++sprite->data[3] == sprite->data[2]) - sprite->callback = AnimBite_Step2; -} - -static void AnimBite_Step2(struct Sprite *sprite) -{ - sprite->data[4] -= sprite->data[0]; - sprite->data[5] -= sprite->data[1]; - sprite->pos2.x = sprite->data[4] >> 8; - sprite->pos2.y = sprite->data[5] >> 8; - if (--sprite->data[3] == 0) - DestroySpriteAndMatrix(sprite); -} - -// Launches a tear drop away from the battler. Used by Fake Tears -static void AnimTearDrop(struct Sprite *sprite) -{ - u8 battler; - s8 xOffset; - - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - battler = gBattleAnimAttacker; - else - battler = gBattleAnimTarget; - - xOffset = 20; - sprite->oam.tileNum += 4; - - switch (gBattleAnimArgs[1]) - { - case 0: - sprite->pos1.x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_RIGHT) - 8; - sprite->pos1.y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_TOP) + 8; - break; - case 1: - sprite->pos1.x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_RIGHT) - 14; - sprite->pos1.y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_TOP) + 16; - break; - case 2: - sprite->pos1.x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_LEFT) + 8; - sprite->pos1.y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_TOP) + 8; - StartSpriteAffineAnim(sprite, 1); - xOffset = -20; - break; - case 3: - sprite->pos1.x = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_LEFT) + 14; - sprite->pos1.y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_TOP) + 16; - StartSpriteAffineAnim(sprite, 1); - xOffset = -20; - break; - } - - sprite->data[0] = 32; - sprite->data[2] = sprite->pos1.x + xOffset; - sprite->data[4] = sprite->pos1.y + 12; - sprite->data[5] = -12; - - InitAnimArcTranslation(sprite); - sprite->callback = AnimTearDrop_Step; -} - -static void AnimTearDrop_Step(struct Sprite *sprite) -{ - if (TranslateAnimHorizontalArc(sprite)) - DestroySpriteAndMatrix(sprite); -} - -void AnimTask_MoveAttackerMementoShadow(u8 taskId) -{ - struct ScanlineEffectParams scanlineParams; - struct BattleAnimBgData animBg; - u16 i; - u8 pos; - int var0; - struct Task *task = &gTasks[taskId]; - - task->data[7] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + 31; - task->data[6] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_TOP) - 7; - task->data[5] = task->data[7]; - task->data[4] = task->data[6]; - task->data[13] = (task->data[7] - task->data[6]) << 8; - - pos = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); - task->data[14] = pos - 32; - task->data[15] = pos + 32; - - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) - task->data[8] = -12; - else - task->data[8] = -64; - - task->data[3] = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); - if (task->data[3] == 1) - { - sub_80A6B30(&animBg); - task->data[10] = gBattle_BG1_Y; - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); - FillPalette(0, animBg.paletteId * 16, 32); - scanlineParams.dmaDest = ®_BG1VOFS; - var0 = WINOUT_WIN01_BG1; - if (!IsContest()) - gBattle_BG2_X += 240; - } - else - { - task->data[10] = gBattle_BG2_Y; - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2); - FillPalette(0, 144, 32); - scanlineParams.dmaDest = ®_BG2VOFS; - var0 = WINOUT_WIN01_BG2; - if (!IsContest()) - gBattle_BG1_X += 240; - } - - scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; - scanlineParams.initState = 1; - scanlineParams.unused9 = 0; - task->data[11] = 0; - task->data[12] = 16; - task->data[0] = 0; - task->data[1] = 0; - task->data[2] = 0; - sub_8114374(3); - for (i = 0; i < 112; i++) - { - gScanlineEffectRegBuffers[0][i] = task->data[10]; - gScanlineEffectRegBuffers[1][i] = task->data[10]; - } - - ScanlineEffect_SetParams(scanlineParams); - SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | (var0 ^ (WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR))); - 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_WIN0H = (task->data[14] << 8) | task->data[15]; - gBattle_WIN0V = 160; - - task->func = AnimTask_MoveAttackerMementoShadow_Step; -} - -static void AnimTask_MoveAttackerMementoShadow_Step(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - if (++task->data[1] > 1) - { - task->data[1] = 0; - if (++task->data[2] & 1) - { - if (task->data[11] != 12) - task->data[11]++; - } - else - { - if (task->data[12] != 8) - task->data[12]--; - } - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[11], task->data[12])); - - if (task->data[11] == 12 && task->data[12] == 8) - task->data[0]++; - } - break; - case 1: - task->data[4] -= 8; - sub_8114244(task); - - if (task->data[4] < task->data[8]) - task->data[0]++; - break; - case 2: - task->data[4] -= 8; - sub_8114244(task); - task->data[14] += 4; - task->data[15] -= 4; - - if (task->data[14] >= task->data[15]) - task->data[14] = task->data[15]; - - gBattle_WIN0H = (task->data[14] << 8) | task->data[15]; - - if (task->data[14] == task->data[15]) - task->data[0]++; - break; - case 3: - gScanlineEffect.state = 3; - task->data[0]++; - break; - case 4: - DestroyAnimVisualTask(taskId); - break; - } -} - -void AnimTask_MoveTargetMementoShadow(u8 taskId) -{ - struct BattleAnimBgData animBg; - struct ScanlineEffectParams scanlineParams; - u8 x; - u16 i; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - if (IsContest() == TRUE) - { - gBattle_WIN0H = 0; - gBattle_WIN0V = 0; - SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); - SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); - DestroyAnimVisualTask(taskId); - } - else - { - task->data[3] = GetBattlerSpriteBGPriorityRank(gBattleAnimTarget); - if (task->data[3] == 1) - { - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); - gBattle_BG2_X += 240; - } - else - { - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG2); - gBattle_BG1_X += 240; - } - - task->data[0]++; - } - break; - case 1: - if (task->data[3] == 1) - { - sub_80A6B30(&animBg); - task->data[10] = gBattle_BG1_Y; - FillPalette(0, animBg.paletteId * 16, 32); - } - else - { - task->data[10] = gBattle_BG2_Y; - FillPalette(0, 9 * 16, 32); - } - - sub_8114374(3); - task->data[0]++; - break; - case 2: - task->data[7] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + 31; - task->data[6] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_TOP) - 7; - task->data[13] = (task->data[7] - task->data[6]) << 8; - x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X); - task->data[14] = x - 4; - task->data[15] = x + 4; - - if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) - task->data[8] = -12; - else - task->data[8] = -64; - - task->data[4] = task->data[8]; - task->data[5] = task->data[8]; - task->data[11] = 12; - task->data[12] = 8; - task->data[0]++; - break; - case 3: - if (task->data[3] == 1) - scanlineParams.dmaDest = ®_BG1VOFS; - else - scanlineParams.dmaDest = ®_BG2VOFS; - - for (i = 0; i < 112; i++) - { - gScanlineEffectRegBuffers[0][i] = task->data[10] + (159 - i); - gScanlineEffectRegBuffers[1][i] = task->data[10] + (159 - i); - } - - scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; - scanlineParams.initState = 1; - scanlineParams.unused9 = 0; - ScanlineEffect_SetParams(scanlineParams); - task->data[0]++; - break; - case 4: - if (task->data[3] == 1) - SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); - else - SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG0 | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); - - 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_WIN0H = (task->data[14] << 8) | task->data[15]; - gBattle_WIN0V = 160; - - task->data[0] = 0; - task->data[1] = 0; - task->data[2] = 0; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(12, 8)); - task->func = AnimTask_MoveTargetMementoShadow_Step; - break; - } -} - -static void AnimTask_MoveTargetMementoShadow_Step(u8 taskId) -{ - u8 pos; - u16 i; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[5] += 8; - if (task->data[5] >= task->data[7]) - task->data[5] = task->data[7]; - - sub_8114244(task); - if (task->data[5] == task->data[7]) - task->data[0]++; - break; - case 1: - if (task->data[15] - task->data[14] < 0x40) - { - task->data[14] -= 4; - task->data[15] += 4; - } - else - { - task->data[1] = 1; - } - - gBattle_WIN0H = (task->data[14] << 8) | task->data[15]; - task->data[4] += 8; - if (task->data[4] >= task->data[6]) - task->data[4] = task->data[6]; - - sub_8114244(task); - if (task->data[4] == task->data[6] && task->data[1]) - { - task->data[1] = 0; - task->data[0]++; - } - break; - case 2: - if (++task->data[1] > 1) - { - task->data[1] = 0; - task->data[2]++; - if (task->data[2] & 1) - { - if (task->data[11]) - task->data[11]--; - } - else - { - if (task->data[12] < 16) - task->data[12]++; - } - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[11], task->data[12])); - if (task->data[11] == 0 && task->data[12] == 16) - task->data[0]++; - } - break; - case 3: - gScanlineEffect.state = 3; - task->data[0]++; - break; - case 4: - gBattle_WIN0H = 0; - gBattle_WIN0V = 0; - SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); - SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); - DestroyAnimVisualTask(taskId); - break; - } -} - -static void sub_8114244(struct Task *task) -{ - int var0, var1; - s16 var2; - s16 i; - int var4; - - var2 = task->data[5] - task->data[4]; - if (var2 != 0) - { - var0 = task->data[13] / var2; - var1 = task->data[6] << 8; - - for (i = 0; i < task->data[4]; i++) - { - gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = task->data[10] - (i - 159); - } - - for (i = task->data[4]; i <= task->data[5]; i++) - { - if (i >= 0) - { - s16 var3 = (var1 >> 8) - i; - gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = var3 + task->data[10]; - } - - var1 += var0; - } - - var4 = task->data[10] - (i - 159); - for (i = i; i < task->data[7]; i++) - { - if (i >= 0) - { - gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = var4; - var4--; - } - } - } - else - { - var4 = task->data[10] + 159; - for (i = 0; i < 112; i++) - { - gScanlineEffectRegBuffers[0][i] = var4; - gScanlineEffectRegBuffers[1][i] = var4; - var4--; - } - } -} - -static void sub_8114374(u8 priority) -{ - u16 i; - - for (i = 0; i < MAX_BATTLERS_COUNT; i++) - { - u8 spriteId = GetAnimBattlerSpriteId(i); - if (spriteId != 0xFF) - gSprites[spriteId].oam.priority = priority; - } -} - -void AnimTask_InitMementoShadow(u8 taskId) -{ - u8 toBG2 = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) ^ 1 ? 1 : 0; - MoveBattlerSpriteToBG(gBattleAnimAttacker, toBG2, TRUE); - gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].invisible = FALSE; - - if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) - { - MoveBattlerSpriteToBG(gBattleAnimAttacker ^ 2, toBG2 ^ 1, TRUE); - gSprites[gBattlerSpriteIds[gBattleAnimAttacker ^ 2]].invisible = FALSE; - } - - DestroyAnimVisualTask(taskId); -} - -void sub_8114470(u8 taskId) -{ - u8 toBG2 = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) ^ 1 ? 1 : 0; - sub_80A477C(toBG2); - - if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) - sub_80A477C(toBG2 ^ 1); - - DestroyAnimVisualTask(taskId); -} - -// Animates a deep slash from a claw. Used by Metal Claw, Dragon Claw, and Crush Claw -static void AnimClawSlash(struct Sprite *sprite) -{ - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - StartSpriteAnim(sprite, gBattleAnimArgs[2]); - sprite->callback = RunStoredCallbackWhenAnimEnds; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Makes the attacker metallic and shining. -// Used by MOVE_HARDEN and MOVE_IRON_DEFENSE. -// arg0: if true won't change battler's palette back -// arg1: if true, use custom color -// arg2: custom color -// Custom color argument is used in MOVE_POISON_TAIL to make the mon turn purplish/pinkish as if became cloaked in poison. -void AnimTask_MetallicShine(u8 taskId) -{ - u16 species; - u8 spriteId; - u8 newSpriteId; - u16 paletteNum; - struct BattleAnimBgData animBg; - bool32 priorityChanged = FALSE; - - gBattle_WIN0H = 0; - gBattle_WIN0V = 0; - SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); - SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); - SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON); - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_BG1); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(8, 12)); - SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 0); - SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); - if (!IsContest()) - SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); - - if (IsDoubleBattle() && !IsContest()) - { - if (GetBattlerPosition(gBattleAnimAttacker) == B_POSITION_OPPONENT_RIGHT || GetBattlerPosition(gBattleAnimAttacker) == B_POSITION_PLAYER_LEFT) - { - if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker)) == TRUE) - { - gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)]].oam.priority--; - SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); - priorityChanged = TRUE; - } - } - } - - if (IsContest()) - { - species = gContestResources->field_18->species; - } - else - { - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES); - else - species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES); - } - - spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - newSpriteId = sub_80A89C8(gBattleAnimAttacker, spriteId, species); - - sub_80A6B30(&animBg); - AnimLoadCompressedBgTilemap(animBg.bgId, gMetalShineTilemap); - AnimLoadCompressedBgGfx(animBg.bgId, gMetalShineGfx, animBg.tilesOffset); - LoadCompressedPalette(gMetalShinePalette, animBg.paletteId * 16, 32); - - gBattle_BG1_X = -gSprites[spriteId].pos1.x + 96; - gBattle_BG1_Y = -gSprites[spriteId].pos1.y + 32; - paletteNum = 16 + gSprites[spriteId].oam.paletteNum; - - if (gBattleAnimArgs[1] == 0) - SetGreyscaleOrOriginalPalette(paletteNum, FALSE); - else - BlendPalette(paletteNum * 16, 16, 11, gBattleAnimArgs[2]); - - gTasks[taskId].data[0] = newSpriteId; - gTasks[taskId].data[1] = gBattleAnimArgs[0]; - gTasks[taskId].data[2] = gBattleAnimArgs[1]; - gTasks[taskId].data[3] = gBattleAnimArgs[2]; - gTasks[taskId].data[6] = priorityChanged; - gTasks[taskId].func = AnimTask_MetallicShine_Step; -} - -static void AnimTask_MetallicShine_Step(u8 taskId) -{ - struct BattleAnimBgData animBg; - u16 paletteNum; - u8 spriteId; - - gTasks[taskId].data[10] += 4; - gBattle_BG1_X -= 4; - if (gTasks[taskId].data[10] == 128) - { - gTasks[taskId].data[10] = 0; - gBattle_BG1_X += 128; - gTasks[taskId].data[11]++; - if (gTasks[taskId].data[11] == 2) - { - spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - paletteNum = 16 + gSprites[spriteId].oam.paletteNum; - if (gTasks[taskId].data[1] == 0) - SetGreyscaleOrOriginalPalette(paletteNum, TRUE); - - DestroySprite(&gSprites[gTasks[taskId].data[0]]); - sub_80A6B30(&animBg); - sub_80A6C68(animBg.bgId); - if (gTasks[taskId].data[6] == 1) - gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)]].oam.priority++; - } - else if (gTasks[taskId].data[11] == 3) - { - gBattle_WIN0H = 0; - gBattle_WIN0V = 0; - SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); - SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR); - if (!IsContest()) - SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); - - SetGpuReg(REG_OFFSET_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) ^ DISPCNT_OBJWIN_ON); - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - DestroyAnimVisualTask(taskId); - } - } -} - -// Changes battler's palette to either greyscale or original. -// arg0: which battler -// arg1: FALSE grayscale, TRUE original -void AnimTask_SetGreyscaleOrOriginalPal(u8 taskId) -{ - u8 spriteId; - u8 battler; - bool8 calcSpriteId = FALSE; - u8 position = B_POSITION_PLAYER_LEFT; - - switch (gBattleAnimArgs[0]) - { - case ANIM_ATTACKER: - case ANIM_TARGET: - case ANIM_ATK_PARTNER: - case ANIM_DEF_PARTNER: - spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); - break; - case 4: - position = B_POSITION_PLAYER_LEFT; - calcSpriteId = TRUE; - break; - case 5: - position = B_POSITION_PLAYER_RIGHT; - calcSpriteId = TRUE; - break; - case 6: - position = B_POSITION_OPPONENT_LEFT; - calcSpriteId = TRUE; - break; - case 7: - position = B_POSITION_OPPONENT_RIGHT; - calcSpriteId = TRUE; - break; - default: - spriteId = 0xFF; - break; - } - - if (calcSpriteId) - { - battler = GetBattlerAtPosition(position); - if (IsBattlerSpriteVisible(battler)) - spriteId = gBattlerSpriteIds[battler]; - else - spriteId = 0xFF; - } - - if (spriteId != 0xFF) - SetGreyscaleOrOriginalPalette(gSprites[spriteId].oam.paletteNum + 16, gBattleAnimArgs[1]); - - DestroyAnimVisualTask(taskId); -} - -void GetIsDoomDesireHitTurn(u8 taskId) -{ - if (gAnimMoveTurn < 2) - gBattleAnimArgs[ARG_RET_ID] = FALSE; - - if (gAnimMoveTurn == 2) - gBattleAnimArgs[ARG_RET_ID] = TRUE; - - DestroyAnimVisualTask(taskId); -} diff --git a/src/dragon.c b/src/dragon.c deleted file mode 100644 index 1d426cac7..000000000 --- a/src/dragon.c +++ /dev/null @@ -1,440 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "scanline_effect.h" -#include "task.h" -#include "trig.h" -#include "constants/rgb.h" - -static void AnimOutrageFlame(struct Sprite *); -static void AnimDragonRageFirePlume(struct Sprite *); -static void AnimDragonFireToTarget(struct Sprite *); -static void AnimDragonDanceOrb(struct Sprite *); -static void AnimDragonDanceOrb_Step(struct Sprite *); -static void AnimOverheatFlame(struct Sprite *); -static void AnimOverheatFlame_Step(struct Sprite *); -static void AnimTask_DragonDanceWaver_Step(u8); -static void sub_8113574(struct Task *); - -EWRAM_DATA static u16 gUnknown_0203A100[7] = {0}; - -static const union AnimCmd gUnknown_08596E60[] = -{ - ANIMCMD_FRAME(0, 4), - ANIMCMD_FRAME(16, 4), - ANIMCMD_FRAME(32, 4), - ANIMCMD_FRAME(48, 4), - ANIMCMD_FRAME(64, 4), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const gUnknown_08596E78[] = -{ - gUnknown_08596E60, -}; - -const struct SpriteTemplate gOutrageFlameSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gUnknown_08596E78, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimOutrageFlame, -}; - -static const union AnimCmd sAnim_DragonBreathFire_0[] = -{ - ANIMCMD_FRAME(16, 3), - ANIMCMD_FRAME(32, 3), - ANIMCMD_FRAME(48, 3), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd sAnim_DragonBreathFire_1[] = -{ - ANIMCMD_FRAME(16, 3, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_FRAME(32, 3, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_FRAME(48, 3, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_DragonBreathFire[] = -{ - sAnim_DragonBreathFire_0, - sAnim_DragonBreathFire_1, -}; - -static const union AffineAnimCmd sAffineAnim_DragonBreathFire_0[] = -{ - AFFINEANIMCMD_FRAME(0x50, 0x50, 127, 0), - AFFINEANIMCMD_FRAME(0xD, 0xD, 0, 100), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_DragonBreathFire_1[] = -{ - AFFINEANIMCMD_FRAME(0x50, 0x50, 0, 0), - AFFINEANIMCMD_FRAME(0xD, 0xD, 0, 100), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_DragonBreathFire[] = -{ - sAffineAnim_DragonBreathFire_0, - sAffineAnim_DragonBreathFire_1, -}; - -const struct SpriteTemplate gDragonBreathFireSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_DragonBreathFire, - .images = NULL, - .affineAnims = sAffineAnims_DragonBreathFire, - .callback = AnimDragonFireToTarget, -}; - -static const union AnimCmd sAnim_DragonRageFirePlume[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(16, 5), - ANIMCMD_FRAME(32, 5), - ANIMCMD_FRAME(48, 5), - ANIMCMD_FRAME(64, 5), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_DragonRageFirePlume[] = -{ - sAnim_DragonRageFirePlume, -}; - -const struct SpriteTemplate gDragonRageFirePlumeSpriteTemplate = -{ - .tileTag = ANIM_TAG_FIRE_PLUME, - .paletteTag = ANIM_TAG_FIRE_PLUME, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_DragonRageFirePlume, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDragonRageFirePlume, -}; - -static const union AnimCmd sAnim_DragonRageFire[] = -{ - ANIMCMD_FRAME(16, 3), - ANIMCMD_FRAME(32, 3), - ANIMCMD_FRAME(48, 3), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_DragonRageFire[] = -{ - sAnim_DragonRageFire, - sAnim_DragonRageFire, -}; - -static const union AffineAnimCmd sAffineAnim_DragonRageFire_0[] = -{ - AFFINEANIMCMD_FRAME(0x64, 0x64, 127, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_DragonRageFire_1[] = -{ - AFFINEANIMCMD_FRAME(0x64, 0x64, 0, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_DragonRageFire[] = -{ - sAffineAnim_DragonRageFire_0, - sAffineAnim_DragonRageFire_1, -}; - -const struct SpriteTemplate gDragonRageFireSpitSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_DragonRageFire, - .images = NULL, - .affineAnims = sAffineAnims_DragonRageFire, - .callback = AnimDragonFireToTarget, -}; - -const struct SpriteTemplate gDragonDanceOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_HOLLOW_ORB, - .paletteTag = ANIM_TAG_HOLLOW_ORB, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDragonDanceOrb, -}; - -const struct SpriteTemplate gOverheatFlameSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gUnknown_08596E78, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimOverheatFlame, -}; - -static void AnimOutrageFlame(struct Sprite *sprite) -{ - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - sprite->pos1.x -= gBattleAnimArgs[0]; - gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - gBattleAnimArgs[4] = -gBattleAnimArgs[4]; - } - else - { - sprite->pos1.x += gBattleAnimArgs[0]; - } - - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[1] = gBattleAnimArgs[3]; - sprite->data[3] = gBattleAnimArgs[4]; - sprite->data[5] = gBattleAnimArgs[5]; - sprite->invisible = TRUE; - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = TranslateSpriteLinearAndFlicker; -} - -static void sub_8113100(struct Sprite *sprite) -{ - SetSpriteCoordsToAnimAttackerCoords(sprite); - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - sprite->pos1.x -= gBattleAnimArgs[1]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[2] -= gBattleAnimArgs[2]; - sprite->data[4] += gBattleAnimArgs[3]; - } - else - { - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[2] += gBattleAnimArgs[2]; - sprite->data[4] += gBattleAnimArgs[3]; - StartSpriteAnim(sprite, 1); - } - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); -} - -static void AnimDragonRageFirePlume(struct Sprite *sprite) -{ - if (gBattleAnimArgs[0] == 0) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1); - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); - } - - SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[1]); - sprite->pos1.y += gBattleAnimArgs[2]; - sprite->callback = RunStoredCallbackWhenAnimEnds; - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); -} - -// For Dragon Breath and Dragon Rage -static void AnimDragonFireToTarget(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - StartSpriteAffineAnim(sprite, 1); - - sub_8113100(sprite); -} - -static void AnimDragonDanceOrb(struct Sprite *sprite) -{ - u16 r5; - u16 r0; - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); - sprite->data[4] = 0; - sprite->data[5] = 1; - sprite->data[6] = gBattleAnimArgs[0]; - r5 = GetBattlerSpriteCoordAttr(gBattlerAttacker, BATTLER_COORD_ATTR_HEIGHT); - r0 = GetBattlerSpriteCoordAttr(gBattlerAttacker, BATTLER_COORD_ATTR_WIDTH); - if (r5 > r0) - sprite->data[7] = r5 / 2; - else - sprite->data[7] = r0 / 2; - sprite->pos2.x = Cos(sprite->data[6], sprite->data[7]); - sprite->pos2.y = Sin(sprite->data[6], sprite->data[7]); - sprite->callback = AnimDragonDanceOrb_Step; -} - -static void AnimDragonDanceOrb_Step(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - sprite->data[6] = (sprite->data[6] - sprite->data[5]) & 0xFF; - sprite->pos2.x = Cos(sprite->data[6], sprite->data[7]); - sprite->pos2.y = Sin(sprite->data[6], sprite->data[7]); - if (++sprite->data[4] > 5) - { - sprite->data[4] = 0; - if (sprite->data[5] <= 15 && ++sprite->data[5] > 15) - sprite->data[5] = 16; - } - if (++sprite->data[3] > 0x3C) - { - sprite->data[3] = 0; - sprite->data[0]++; - } - break; - case 1: - sprite->data[6] = (sprite->data[6] - sprite->data[5]) & 0xFF; - if (sprite->data[7] <= 0x95 && (sprite->data[7] += 8) > 0x95) - sprite->data[7] = 0x96; - sprite->pos2.x = Cos(sprite->data[6], sprite->data[7]); - sprite->pos2.y = Sin(sprite->data[6], sprite->data[7]); - if (++sprite->data[4] > 5) - { - sprite->data[4] = 0; - if (sprite->data[5] <= 15 && ++sprite->data[5] > 15) - sprite->data[5] = 16; - } - if (++sprite->data[3] > 20) - DestroyAnimSprite(sprite); - break; - } -} - -// Wavers the attacker back and forth. Progressing vertical wave of scanline shifts -// Used by Dragon Dance -void AnimTask_DragonDanceWaver(u8 taskId) -{ - struct ScanlineEffectParams sp; - struct Task *task = &gTasks[taskId]; - u16 i; - u8 r1; - if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1) - { - sp.dmaDest = ®_BG1HOFS; - task->data[2] = gBattle_BG1_X; - } - else - { - sp.dmaDest = ®_BG2HOFS; - task->data[2] = gBattle_BG2_X; - } - - sp.dmaControl = 0xA2600001; - sp.initState = 1; - sp.unused9 = 0; - r1 = GetBattlerYCoordWithElevation(gBattleAnimAttacker); - task->data[3] = r1 - 32; - task->data[4] = r1 + 32; - if (task->data[3] < 0) - task->data[3] = 0; - - for (i = task->data[3]; i <= task->data[4]; i++) - { - gScanlineEffectRegBuffers[0][i] = task->data[2]; - gScanlineEffectRegBuffers[1][i] = task->data[2]; - } - - ScanlineEffect_SetParams(sp); - task->func = AnimTask_DragonDanceWaver_Step; -} - -static void AnimTask_DragonDanceWaver_Step(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - switch (task->data[0]) - { - case 0: - if (++task->data[7] > 1) - { - task->data[7] = 0; - if (++task->data[6] == 3) - task->data[0]++; - } - sub_8113574(task); - break; - case 1: - if (++task->data[1] > 0x3C) - task->data[0]++; - sub_8113574(task); - break; - case 2: - if (++task->data[7] > 1) - { - task->data[7] = 0; - if (--task->data[6] == 0) - task->data[0]++; - } - sub_8113574(task); - break; - case 3: - gScanlineEffect.state = 3; - task->data[0]++; - break; - case 4: - DestroyAnimVisualTask(taskId); - break; - } -} - -static void sub_8113574(struct Task *task) -{ - u16 r3 = task->data[5]; - u16 i; - for (i = task->data[3]; i <= task->data[4]; i++) - { - gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = ((gSineTable[r3] * task->data[6]) >> 7) + task->data[2]; - r3 = (r3 + 8) & 0xFF; - } - - task->data[5] = (task->data[5] + 9) & 0xFF; -} - -static void AnimOverheatFlame(struct Sprite *sprite) -{ - int r6 = (gBattleAnimArgs[2] * 3) / 5; - int i; - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + gBattleAnimArgs[4]; - sprite->data[1] = Cos(gBattleAnimArgs[1], gBattleAnimArgs[2]); - sprite->data[2] = Sin(gBattleAnimArgs[1], r6); - sprite->pos1.x += sprite->data[1] * gBattleAnimArgs[0]; - sprite->pos1.y += sprite->data[2] * gBattleAnimArgs[0]; - sprite->data[3] = gBattleAnimArgs[3]; - sprite->callback = AnimOverheatFlame_Step; - for (i = 0; i < 7; i++) - gUnknown_0203A100[i] = sprite->data[i]; -} - -static void AnimOverheatFlame_Step(struct Sprite *sprite) -{ - sprite->data[4] += sprite->data[1]; - sprite->data[5] += sprite->data[2]; - sprite->pos2.x = sprite->data[4] / 10; - sprite->pos2.y = sprite->data[5] / 10; - if (++sprite->data[0] > sprite->data[3]) - DestroyAnimSprite(sprite); -} diff --git a/src/electric.c b/src/electric.c deleted file mode 100644 index 63511c91f..000000000 --- a/src/electric.c +++ /dev/null @@ -1,1329 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "constants/rgb.h" -#include "trig.h" -#include "constants/songs.h" -#include "sound.h" - -static void AnimLightning(struct Sprite *); -static void AnimLightning_Step(struct Sprite *); -static void sub_810A214(struct Sprite *); -static void sub_810A258(struct Sprite *); -static void sub_810A274(struct Sprite *); -static void AnimSparkElectricity(struct Sprite *); -static void AnimZapCannonSpark(struct Sprite *); -static void AnimZapCannonSpark_Step(struct Sprite *); -static void AnimThunderboltOrb(struct Sprite *); -static void AnimThunderboltOrb_Step(struct Sprite *); -static void AnimSparkElectricityFlashing(struct Sprite *); -static void AnimSparkElectricityFlashing_Step(struct Sprite *); -static void AnimElectricity(struct Sprite *); -static void AnimTask_ElectricBolt_Step(u8 taskId); -static void AnimElectricBoltSegment(struct Sprite *); -static void AnimThunderWave(struct Sprite *); -static void AnimThunderWave_Step(struct Sprite *); -static void AnimTask_ElectricChargingParticles_Step(u8 taskId); -static void AnimElectricChargingParticles(struct Sprite *); -static void AnimElectricChargingParticles_Step(struct Sprite *); -static void AnimGrowingChargeOrb(struct Sprite *); -static void AnimElectricPuff(struct Sprite *); -static void AnimVoltTackleOrbSlide(struct Sprite *); -static void AnimVoltTackleOrbSlide_Step(struct Sprite *); -static bool8 sub_810B154(struct Task *task, u8 taskId); -static void AnimVoltTackleBolt(struct Sprite *); -static void AnimGrowingShockWaveOrb(struct Sprite *); -static bool8 sub_810B430(struct Task *task, u8 taskId); -static void AnimShockWaveProgressingBolt(struct Sprite *); -static bool8 sub_810B614(struct Task *task, u8 taskId); -static void sub_810B684(struct Sprite *sprite); - -static const union AnimCmd sAnim_Lightning[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(16, 5), - ANIMCMD_FRAME(32, 8), - ANIMCMD_FRAME(48, 5), - ANIMCMD_FRAME(64, 5), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_Lightning[] = -{ - sAnim_Lightning, -}; - -const struct SpriteTemplate gLightningSpriteTemplate = -{ - .tileTag = ANIM_TAG_LIGHTNING, - .paletteTag = ANIM_TAG_LIGHTNING, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_Lightning, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimLightning, -}; - -static const union AffineAnimCmd gUnknown_085956D8[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 20), - AFFINEANIMCMD_FRAME(0x0, 0x0, -16, 60), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const gUnknown_085956F8[] = -{ - gUnknown_085956D8, -}; - -// Unused -const struct SpriteTemplate gUnknown_085956FC = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gUnknown_085956F8, - .callback = sub_810A214, -}; - -static const union AnimCmd gUnknown_08595714[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(16, 5), - ANIMCMD_FRAME(32, 5), - ANIMCMD_FRAME(48, 5), - ANIMCMD_FRAME(64, 5), - ANIMCMD_FRAME(80, 5), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const gUnknown_08595730[] = -{ - gUnknown_08595714, -}; - -// Unused -const struct SpriteTemplate gUnknown_08595734 = -{ - .tileTag = ANIM_TAG_SHOCK, - .paletteTag = ANIM_TAG_SHOCK, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gUnknown_08595730, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_810A274, -}; - -const struct SpriteTemplate gSparkElectricitySpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARK_2, - .paletteTag = ANIM_TAG_SPARK_2, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSparkElectricity, -}; - -const struct SpriteTemplate gZapCannonBallSpriteTemplate = -{ - .tileTag = ANIM_TAG_BLACK_BALL_2, - .paletteTag = ANIM_TAG_BLACK_BALL_2, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = TranslateAnimSpriteToTargetMonLocation, -}; - -static const union AffineAnimCmd sAffineAnim_FlashingSpark[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 20, 1), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd *const sAffineAnims_FlashingSpark[] = -{ - sAffineAnim_FlashingSpark, -}; - -const struct SpriteTemplate gZapCannonSparkSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARK_2, - .paletteTag = ANIM_TAG_SPARK_2, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_FlashingSpark, - .callback = AnimZapCannonSpark, -}; - -static const union AnimCmd sAnim_ThunderboltOrb[] = -{ - ANIMCMD_FRAME(0, 6), - ANIMCMD_FRAME(16, 6), - ANIMCMD_FRAME(32, 6), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_ThunderboltOrb[] = -{ - sAnim_ThunderboltOrb, -}; - -static const union AffineAnimCmd sAffineAnim_ThunderboltOrb[] = -{ - AFFINEANIMCMD_FRAME(0xE8, 0xE8, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 10), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 10), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd *const sAffineAnims_ThunderboltOrb[] = -{ - sAffineAnim_ThunderboltOrb, -}; - -const struct SpriteTemplate gThunderboltOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_SHOCK_3, - .paletteTag = ANIM_TAG_SHOCK_3, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = sAnims_ThunderboltOrb, - .images = NULL, - .affineAnims = sAffineAnims_ThunderboltOrb, - .callback = AnimThunderboltOrb, -}; - -const struct SpriteTemplate gSparkElectricityFlashingSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARK_2, - .paletteTag = ANIM_TAG_SPARK_2, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_FlashingSpark, - .callback = AnimSparkElectricityFlashing, -}; - -const struct SpriteTemplate gElectricitySpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARK_2, - .paletteTag = ANIM_TAG_SPARK_2, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimElectricity, -}; - -const struct SpriteTemplate gElectricBoltSegmentSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARK, - .paletteTag = ANIM_TAG_SPARK, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimElectricBoltSegment, -}; - -const struct SpriteTemplate gThunderWaveSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARK_H, - .paletteTag = ANIM_TAG_SPARK_H, - .oam = &gOamData_AffineOff_ObjNormal_32x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimThunderWave, -}; - -static const s8 sElectricChargingParticleCoordOffsets[][2] = -{ - { 58, -60}, - {-56, -36}, - { 8, -56}, - {-16, 56}, - { 58, -10}, - {-58, 10}, - { 48, -18}, - {-8, 56}, - { 16, -56}, - {-58, -42}, - { 58, 30}, - {-48, 40}, - { 12, -48}, - { 48, -12}, - {-56, 18}, - { 48, 48}, -}; - -static const union AnimCmd sAnim_ElectricChargingParticles_0[] = -{ - ANIMCMD_FRAME(3, 1), - ANIMCMD_FRAME(2, 1), - ANIMCMD_FRAME(1, 1), - ANIMCMD_FRAME(0, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_ElectricChargingParticles_1[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(1, 5), - ANIMCMD_FRAME(2, 5), - ANIMCMD_FRAME(3, 5), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_ElectricChargingParticles[] = -{ - sAnim_ElectricChargingParticles_0, - sAnim_ElectricChargingParticles_1, -}; - -const struct SpriteTemplate gElectricChargingParticlesSpriteTemplate = -{ - .tileTag = ANIM_TAG_ELECTRIC_ORBS, - .paletteTag = ANIM_TAG_ELECTRIC_ORBS, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = sAnims_ElectricChargingParticles, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCallbackDummy, -}; - -static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_0[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), - AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 60), - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_LOOP(0), - AFFINEANIMCMD_FRAME(0xFFFC, 0xFFFC, 0, 5), - AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 5), - AFFINEANIMCMD_LOOP(10), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_1[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 30), - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0xFFFC, 0xFFFC, 0, 5), - AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 5), - AFFINEANIMCMD_JUMP(3), -}; - -static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_2[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 30), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 30), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_GrowingElectricOrb[] = -{ - sAffineAnim_GrowingElectricOrb_0, - sAffineAnim_GrowingElectricOrb_1, - sAffineAnim_GrowingElectricOrb_2, -}; - -const struct SpriteTemplate gGrowingChargeOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .oam = &gOamData_AffineNormal_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_GrowingElectricOrb, - .callback = AnimGrowingChargeOrb, -}; - -static const union AnimCmd sAnim_ElectricPuff[] = -{ - ANIMCMD_FRAME(0, 3), - ANIMCMD_FRAME(16, 3), - ANIMCMD_FRAME(32, 3), - ANIMCMD_FRAME(48, 3), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_ElectricPuff[] = -{ - sAnim_ElectricPuff, -}; - -const struct SpriteTemplate gElectricPuffSpriteTemplate = -{ - .tileTag = ANIM_TAG_ELECTRICITY, - .paletteTag = ANIM_TAG_ELECTRICITY, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_ElectricPuff, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimElectricPuff, -}; - -const struct SpriteTemplate gVoltTackleOrbSlideSpriteTemplate = -{ - .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .oam = &gOamData_AffineNormal_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_GrowingElectricOrb, - .callback = AnimVoltTackleOrbSlide, -}; - -static const union AnimCmd sAnim_VoltTackleBolt_0[] = -{ - ANIMCMD_FRAME(0, 3), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_VoltTackleBolt_1[] = -{ - ANIMCMD_FRAME(2, 3), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_VoltTackleBolt_2[] = -{ - ANIMCMD_FRAME(4, 3), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_VoltTackleBolt_3[] = -{ - ANIMCMD_FRAME(6, 3), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_VoltTackleBolt[] = -{ - sAnim_VoltTackleBolt_0, - sAnim_VoltTackleBolt_1, - sAnim_VoltTackleBolt_2, - sAnim_VoltTackleBolt_3, -}; - -static const union AffineAnimCmd sAffineAnim_VoltTackleBolt[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_VoltTackleBolt[] = -{ - sAffineAnim_VoltTackleBolt, -}; - -const struct SpriteTemplate gVoltTackleBoltSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARK, - .paletteTag = ANIM_TAG_SPARK, - .oam = &gOamData_AffineDouble_ObjNormal_8x16, - .anims = sAnims_VoltTackleBolt, - .images = NULL, - .affineAnims = sAffineAnims_VoltTackleBolt, - .callback = AnimVoltTackleBolt, -}; - -const struct SpriteTemplate gGrowingShockWaveOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .oam = &gOamData_AffineNormal_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_GrowingElectricOrb, - .callback = AnimGrowingShockWaveOrb, -}; - -const struct SpriteTemplate gShockWaveProgressingBoltSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARK, - .paletteTag = ANIM_TAG_SPARK, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimShockWaveProgressingBolt, -}; - -static void AnimLightning(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - sprite->pos1.x -= gBattleAnimArgs[0]; - else - sprite->pos1.x += gBattleAnimArgs[0]; - - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->callback = AnimLightning_Step; -} - -static void AnimLightning_Step(struct Sprite *sprite) -{ - if (sprite->animEnded) - DestroyAnimSprite(sprite); -} - -static void sub_810A214(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - sprite->pos1.x -= gBattleAnimArgs[0]; - else - sprite->pos1.x += gBattleAnimArgs[0]; - - sprite->callback = sub_810A258; -} - -static void sub_810A258(struct Sprite *sprite) -{ - if (sprite->affineAnimEnded) - DestroySpriteAndMatrix(sprite); -} - -static void sub_810A274(struct Sprite *sprite) -{ - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - sprite->pos1.x -= gBattleAnimArgs[0]; - sprite->pos1.y -= gBattleAnimArgs[1]; - } - else - { - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - } - sprite->data[0] = 0; - sprite->data[1] = gBattleAnimArgs[2]; - sprite->data[2] = gBattleAnimArgs[3]; - sprite->data[3] = gBattleAnimArgs[4]; - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = TranslateSpriteInCircleOverDuration; -} - -static void AnimSparkElectricity(struct Sprite *sprite) -{ - u8 battler; - u32 matrixNum; - s16 sineVal; - - switch (gBattleAnimArgs[4]) - { - case ANIM_ATTACKER: - battler = gBattleAnimAttacker; - break; - case ANIM_TARGET: - default: - battler = gBattleAnimTarget; - break; - case ANIM_ATK_PARTNER: - if (!IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) - battler = gBattleAnimAttacker; - else - battler = BATTLE_PARTNER(gBattleAnimAttacker); - break; - case ANIM_DEF_PARTNER: - if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) - battler = BATTLE_PARTNER(gBattleAnimTarget); - else - battler = gBattleAnimTarget; - break; - } - - if (gBattleAnimArgs[5] == 0) - { - sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X); - sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y); - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET); - } - - sprite->pos2.x = (gSineTable[gBattleAnimArgs[0]] * gBattleAnimArgs[1]) >> 8; - sprite->pos2.y = (gSineTable[gBattleAnimArgs[0] + 64] * gBattleAnimArgs[1]) >> 8; - - if (gBattleAnimArgs[6] & 1) - sprite->oam.priority = GetBattlerSpriteBGPriority(battler) + 1; - - matrixNum = sprite->oam.matrixNum; - sineVal = gSineTable[gBattleAnimArgs[2]]; - - gOamMatrices[matrixNum].a = gOamMatrices[matrixNum].d = gSineTable[gBattleAnimArgs[2] + 64]; - gOamMatrices[matrixNum].b = sineVal; - gOamMatrices[matrixNum].c = -sineVal; - - sprite->data[0] = gBattleAnimArgs[3]; - sprite->callback = DestroyAnimSpriteAfterTimer; -} - -static void AnimZapCannonSpark(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, 1); - sprite->data[0] = gBattleAnimArgs[3]; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - InitAnimLinearTranslation(sprite); - sprite->data[5] = gBattleAnimArgs[2]; - sprite->data[6] = gBattleAnimArgs[5]; - sprite->data[7] = gBattleAnimArgs[4]; - sprite->oam.tileNum += gBattleAnimArgs[6] * 4; - sprite->callback = AnimZapCannonSpark_Step; - AnimZapCannonSpark_Step(sprite); -} - -static void AnimZapCannonSpark_Step(struct Sprite *sprite) -{ - if (!AnimTranslateLinear(sprite)) - { - sprite->pos2.x += Sin(sprite->data[7], sprite->data[5]); - sprite->pos2.y += Cos(sprite->data[7], sprite->data[5]); - sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; - if(!(sprite->data[7] % 3)) - sprite->invisible ^= 1; - } - else - DestroyAnimSprite(sprite); -} - -static void AnimThunderboltOrb_Step(struct Sprite *sprite) -{ - if (--sprite->data[5] == -1) - { - sprite->invisible ^= 1; - sprite->data[5] = sprite->data[4]; - } - if (sprite->data[3]-- <= 0) - DestroyAnimSprite(sprite); -} - -static void AnimThunderboltOrb(struct Sprite *sprite) -{ - if (IsContest() || GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[1]; - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[2]; - sprite->data[3] = gBattleAnimArgs[0]; - sprite->data[4] = gBattleAnimArgs[3]; - sprite->data[5] = gBattleAnimArgs[3]; - sprite->callback = AnimThunderboltOrb_Step; -} - -static void AnimSparkElectricityFlashing(struct Sprite *sprite) -{ - u8 battler; - - sprite->data[0] = gBattleAnimArgs[3]; - if (gBattleAnimArgs[ARG_RET_ID] & 0x8000) - battler = gBattleAnimTarget; - else - battler = gBattleAnimAttacker; - - if (IsContest() || GetBattlerSide(battler) == B_SIDE_PLAYER) - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - - sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2) + gBattleAnimArgs[0]; - sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[1]; - - sprite->data[4] = gBattleAnimArgs[ARG_RET_ID] & 0x7FFF; - sprite->data[5] = gBattleAnimArgs[2]; - sprite->data[6] = gBattleAnimArgs[5]; - sprite->data[7] = gBattleAnimArgs[4]; - - sprite->oam.tileNum += gBattleAnimArgs[6] * 4; - sprite->callback = AnimSparkElectricityFlashing_Step; - sprite->callback(sprite); -} - -static void AnimSparkElectricityFlashing_Step(struct Sprite *sprite) -{ - sprite->pos2.x = Sin(sprite->data[7], sprite->data[5]); - sprite->pos2.y = Cos(sprite->data[7], sprite->data[5]); - - sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; - if (sprite->data[7] % sprite->data[4] == 0) - sprite->invisible ^= TRUE; - - if (sprite->data[0]-- <= 0) - DestroyAnimSprite(sprite); -} - -// Electricity arcs around the target. Used for Paralysis and various electric move hits -static void AnimElectricity(struct Sprite *sprite) -{ - InitSpritePosToAnimTarget(sprite, FALSE); - sprite->oam.tileNum += gBattleAnimArgs[3] * 4; - - if (gBattleAnimArgs[3] == 1) - sprite->oam.matrixNum = ST_OAM_HFLIP; - else if (gBattleAnimArgs[3] == 2) - sprite->oam.matrixNum = ST_OAM_VFLIP; - - sprite->data[0] = gBattleAnimArgs[2]; - sprite->callback = WaitAnimForDuration; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// The vertical falling thunder bolt used in Thunder Wave/Shock/Bolt -void AnimTask_ElectricBolt(u8 taskId) -{ - gTasks[taskId].data[0] = GetBattlerSpriteCoord(gBattleAnimTarget, 0) + gBattleAnimArgs[0]; - gTasks[taskId].data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + gBattleAnimArgs[1]; - gTasks[taskId].data[2] = gBattleAnimArgs[2]; - gTasks[taskId].func = AnimTask_ElectricBolt_Step; -} - -static void AnimTask_ElectricBolt_Step(u8 taskId) -{ - u16 r8; - u16 r2; - s16 r12; - u8 spriteId = 0; - u8 r7 = 0; - u8 sp = gTasks[taskId].data[2]; - s16 x = gTasks[taskId].data[0]; - s16 y = gTasks[taskId].data[1]; - - if (!gTasks[taskId].data[2]) - { - r8 = 0; - r2 = 1; - r12 = 16; - } - else - { - r12 = 16; - r8 = 8; - r2 = 4; - } - - switch (gTasks[taskId].data[10]) - { - case 0: - r12 *= 1; - spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); - r7++; - break; - case 2: - r12 *= 2; - r8 += r2; - spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); - r7++; - break; - case 4: - r12 *= 3; - r8 += r2 * 2; - spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); - r7++; - break; - case 6: - r12 *= 4; - r8 += r2 * 3; - spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); - r7++; - break; - case 8: - r12 *= 5; - spriteId = CreateSprite(&gElectricBoltSegmentSpriteTemplate, x, y + r12, 2); - r7++; - break; - case 10: - DestroyAnimVisualTask(taskId); - return; - } - - if (r7) - { - gSprites[spriteId].oam.tileNum += r8; - gSprites[spriteId].data[0] = sp; - gSprites[spriteId].callback(&gSprites[spriteId]); - } - - gTasks[taskId].data[10]++; -} - -static void AnimElectricBoltSegment(struct Sprite *sprite) -{ - if (!sprite->data[0]) - { - sprite->oam.shape = SPRITE_SHAPE(8x16); - sprite->oam.size = SPRITE_SIZE(8x16); - } - else - { - sprite->oam.shape = SPRITE_SHAPE(16x16); - sprite->oam.size = SPRITE_SIZE(16x16); - } - if (++sprite->data[1] == 15) - DestroySprite(sprite); -} - -// The horizontal bands of electricity used in Thunder Wave -static void AnimThunderWave(struct Sprite *sprite) -{ - u8 spriteId; - - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - spriteId = CreateSprite(&gThunderWaveSpriteTemplate, sprite->pos1.x + 32, sprite->pos1.y, sprite->subpriority); - gSprites[spriteId].oam.tileNum += 8; - gAnimVisualTaskCount++; - gSprites[spriteId].callback = AnimThunderWave_Step; - sprite->callback = AnimThunderWave_Step; -} - -static void AnimThunderWave_Step(struct Sprite *sprite) -{ - if (++sprite->data[0] == 3) - { - sprite->data[0] = 0; - sprite->invisible ^= 1; - } - - if (++sprite->data[1] == 51) - DestroyAnimSprite(sprite); -} - -// Animates small electric orbs moving from around the battler inward. For Charge/Shock Wave -void AnimTask_ElectricChargingParticles(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - task->data[15] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - } - else - { - task->data[14] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - task->data[15] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - } - - task->data[6] = gBattleAnimArgs[1]; - task->data[7] = 0; - task->data[8] = 0; - task->data[9] = 0; - task->data[10] = 0; - task->data[11] = gBattleAnimArgs[3]; - task->data[12] = 0; - task->data[13] = gBattleAnimArgs[2]; - task->func = AnimTask_ElectricChargingParticles_Step; -} - -static void AnimTask_ElectricChargingParticles_Step(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - if (task->data[6]) - { - if (++task->data[12] > task->data[13]) - { - u8 spriteId; - task->data[12] = 0; - spriteId = CreateSprite(&gElectricChargingParticlesSpriteTemplate, task->data[14], task->data[15], 2); - if (spriteId != MAX_SPRITES) - { - struct Sprite *sprite = &gSprites[spriteId]; - sprite->pos1.x += sElectricChargingParticleCoordOffsets[task->data[9]][0]; - sprite->pos1.y += sElectricChargingParticleCoordOffsets[task->data[9]][1]; - - sprite->data[0] = 40 - task->data[8] * 5; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = task->data[14]; - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = task->data[15]; - sprite->data[5] = taskId; - - InitAnimLinearTranslation(sprite); - StoreSpriteCallbackInData6(sprite, AnimElectricChargingParticles); - sprite->callback = RunStoredCallbackWhenAnimEnds; - - if (++task->data[9] > 15) - task->data[9] = 0; - - if (++task->data[10] >= task->data[11]) - { - task->data[10] = 0; - if (task->data[8] <= 5) - task->data[8]++; - } - - task->data[7]++; - task->data[6]--; - } - } - } - else if(task->data[7] == 0) - DestroyAnimVisualTask(taskId); -} - -static void AnimElectricChargingParticles_Step(struct Sprite *sprite) -{ - if (AnimTranslateLinear(sprite)) - { - gTasks[sprite->data[5]].data[7]--; - DestroySprite(sprite); - } -} - -static void AnimElectricChargingParticles(struct Sprite *sprite) -{ - StartSpriteAnim(sprite, 1); - sprite->callback = AnimElectricChargingParticles_Step; -} - -static void AnimGrowingChargeOrb(struct Sprite *sprite) -{ - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - } - - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = RunStoredCallbackWhenAffineAnimEnds; -} - -// The quick electric burst at the end of Charge / during the Volt Tackle hit -static void AnimElectricPuff(struct Sprite *sprite) -{ - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - } - - sprite->pos2.x = gBattleAnimArgs[1]; - sprite->pos2.y = gBattleAnimArgs[2]; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - sprite->callback = RunStoredCallbackWhenAnimEnds; -} - -// Creates an orb of electricity that grows then slides off-screen. The attacker slides with it -static void AnimVoltTackleOrbSlide(struct Sprite *sprite) -{ - StartSpriteAffineAnim(sprite, 1); - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - sprite->data[6] = GetAnimBattlerSpriteId(ANIM_ATTACKER); - sprite->data[7] = 16; - - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) - sprite->data[7] *= -1; - - sprite->callback = AnimVoltTackleOrbSlide_Step; -} - -static void AnimVoltTackleOrbSlide_Step(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - if (++sprite->data[1] > 40) - sprite->data[0]++; - break; - case 1: - sprite->pos1.x += sprite->data[7]; - gSprites[sprite->data[6]].pos2.x += sprite->data[7]; - if ((u16)(sprite->pos1.x + 80) > 400) - DestroySpriteAndMatrix(sprite); - } -} - -void AnimTask_VoltTackleAttackerReappear(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); - task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) - { - task->data[14] = -32; - task->data[13] = 2; - } - else - { - task->data[14] = 32; - task->data[13] = -2; - } - - gSprites[task->data[15]].pos2.x = task->data[14]; - task->data[0]++; - break; - case 1: - if (++task->data[1] > 1) - { - task->data[1] = 0; - gSprites[task->data[15]].invisible ^= 1; - - if (task->data[14]) - { - task->data[14] += task->data[13]; - gSprites[task->data[15]].pos2.x = task->data[14]; - } - else - task->data[0]++; - - } - break; - case 2: - if (++task->data[1] > 1) - { - task->data[1] = 0; - gSprites[task->data[15]].invisible ^= 1; - - if (++task->data[2] == 8) - task->data[0]++; - } - break; - case 3: - gSprites[task->data[15]].invisible = FALSE; - DestroyAnimVisualTask(taskId); - } -} - -// The horizontal bolts of electricity for Volt Tackle -void AnimTask_VoltTackleBolt(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch(task->data[0]) - { - case 0: - task->data[1] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER ? 1 : -1; - - switch (gBattleAnimArgs[0]) - { - case 0: - task->data[3] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - task->data[5] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - task->data[4] = (task->data[1] * 128) + 120; - break; - case 4: - task->data[3] = 120 - (task->data[1] * 128); - task->data[5] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - task->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) - (task->data[1] * 32); - break; - default: - if ((gBattleAnimArgs[0] & 1) != 0) - { - task->data[3] = 256; - task->data[4] = -16; - } - else - { - task->data[3] = -16; - task->data[4] = 256; - } - - if (task->data[1] == 1) - { - task->data[5] = 80 - gBattleAnimArgs[0] * 10; - } - else - { - u16 temp; - task->data[5] = gBattleAnimArgs[0] * 10 + 40; - temp = task->data[3]; - task->data[3] = task->data[4]; - task->data[4] = temp; - } - } - - if (task->data[3] < task->data[4]) - { - task->data[1] = 1; - task->data[6] = 0; - } - else - { - task->data[1] = -1; - task->data[6] = 3; - } - - task->data[0]++; - break; - case 1: - if (++task->data[2] > 0) - { - task->data[2] = 0; - if (sub_810B154(task, taskId) || sub_810B154(task, taskId)) - task->data[0]++; - } - break; - case 2: - if (task->data[7] == 0) - DestroyAnimVisualTask(taskId); - } -} - -static bool8 sub_810B154(struct Task *task, u8 taskId) -{ - u8 spriteId = CreateSprite(&gVoltTackleBoltSpriteTemplate, task->data[3], task->data[5], 35); - if (spriteId != MAX_SPRITES) - { - gSprites[spriteId].data[6] = taskId; - gSprites[spriteId].data[7] = 7; - task->data[7]++; - } - - task->data[6] += task->data[1]; - if (task->data[6] < 0) - task->data[6] = 3; - - if (task->data[6] > 3) - task->data[6] = 0; - - task->data[3] += task->data[1] * 16; - - if ((task->data[1] == 1 && task->data[3] >= task->data[4]) - || (task->data[1] == -1 && task->data[3] <= task->data[4])) - { - return TRUE; - } - else - { - return FALSE; - } -} - -static void AnimVoltTackleBolt(struct Sprite *sprite) -{ - if (++sprite->data[0] > 12) - { - gTasks[sprite->data[6]].data[sprite->data[7]]--; - FreeOamMatrix(sprite->oam.matrixNum); - DestroySprite(sprite); - } -} - -static void AnimGrowingShockWaveOrb(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - StartSpriteAffineAnim(sprite, 2); - sprite->data[0]++; - break; - case 1: - if (sprite->affineAnimEnded) - DestroySpriteAndMatrix(sprite); - break; - } -} - -// Thin bolt of electricity that moves up and down toward the target. Used by Shock Wave -void AnimTask_ShockWaveProgressingBolt(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[6] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - task->data[7] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - task->data[8] = 4; - task->data[10] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - task->data[9] = (task->data[10] - task->data[6]) / 5; - task->data[4] = 7; - task->data[5] = -1; - task->data[11] = 12; - task->data[12] = BattleAnimAdjustPanning(task->data[11] - 76); - task->data[13] = BattleAnimAdjustPanning(SOUND_PAN_TARGET); - task->data[14] = task->data[12]; - task->data[15] = (task->data[13] - task->data[12]) / 3; - task->data[0]++; - break; - case 1: - if (++task->data[1] > 0) - { - task->data[1] = 0; - if (sub_810B430(task, taskId)) - { - if (task->data[2] == 5) - task->data[0] = 3; - else - task->data[0]++; - } - } - - if (task->data[11]) - task->data[11]--; - break; - case 2: - if (task->data[11]) - task->data[11]--; - - if (++task->data[1] > 4) - { - task->data[1] = 0; - if (task->data[2] & 1) - { - task->data[7] = 4; - task->data[8] = 68; - task->data[4] = 0; - task->data[5] = 1; - } - else - { - task->data[7] = 68; - task->data[8] = 4; - task->data[4] = 7; - task->data[5] = -1; - } - - if (task->data[11]) - task->data[0] = 4; - else - task->data[0] = 1; - } - break; - case 3: - if (task->data[3] == 0) - DestroyAnimVisualTask(taskId); - break; - case 4: - if (task->data[11]) - task->data[11]--; - else - task->data[0] = 1; - break; - } -} - -static bool8 sub_810B430(struct Task *task, u8 taskId) -{ - u8 spriteId = CreateSprite(&gShockWaveProgressingBoltSpriteTemplate, task->data[6], task->data[7], 35); - if (spriteId != MAX_SPRITES) - { - gSprites[spriteId].oam.tileNum += task->data[4]; - task->data[4] += task->data[5]; - if (task->data[4] < 0) - task->data[4] = 7; - if (task->data[4] > 7) - task->data[4] = 0; - - gSprites[spriteId].data[6] = taskId; - gSprites[spriteId].data[7] = 3; - task->data[3]++; - } - - if (task->data[4] == 0 && task->data[5] > 0) - { - task->data[14] += task->data[15]; - PlaySE12WithPanning(SE_W085, task->data[14]); - } - - if ((task->data[5] < 0 && task->data[7] <= task->data[8]) - || (task->data[5] > 0 && task->data[7] >= task->data[8])) - { - task->data[2]++; - task->data[6] += task->data[9]; - return TRUE; - } - else - { - task->data[7] += task->data[5] * 8; - return FALSE; - } -} - -// Just runs timer for sprite. See AnimTask_ShockWaveProgressingBolt -static void AnimShockWaveProgressingBolt(struct Sprite *sprite) -{ - if (++sprite->data[0] > 12) - { - gTasks[sprite->data[6]].data[sprite->data[7]]--; - DestroySprite(sprite); - } -} - -void AnimTask_ShockWaveLightning(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[15] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + 32; - task->data[14] = task->data[15]; - while (task->data[14] > 16) - { - task->data[14] -= 32; - } - - task->data[13] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - task->data[12] = GetBattlerSpriteSubpriority(gBattleAnimTarget) - 2; - task->data[0]++; - break; - case 1: - if (++task->data[1] > 1) - { - task->data[1] = 0; - if (sub_810B614(task, taskId)) - task->data[0]++; - } - break; - case 2: - if (task->data[10] == 0) - DestroyAnimVisualTask(taskId); - break; - } -} - -bool8 sub_810B614(struct Task *task, u8 taskId) -{ - u8 spriteId = CreateSprite(&gLightningSpriteTemplate, task->data[13], task->data[14], task->data[12]); - - if (spriteId != MAX_SPRITES) - { - gSprites[spriteId].callback = sub_810B684; - gSprites[spriteId].data[6] = taskId; - gSprites[spriteId].data[7] = 10; - task->data[10]++; - } - if (task->data[14] >= task->data[15]) - return TRUE; - task->data[14] += 32; - return FALSE; -} - -static void sub_810B684(struct Sprite *sprite) -{ - if (sprite->animEnded) - { - gTasks[sprite->data[6]].data[sprite->data[7]]--; - DestroySprite(sprite); - } -} diff --git a/src/fight.c b/src/fight.c deleted file mode 100644 index 9bb4a49d3..000000000 --- a/src/fight.c +++ /dev/null @@ -1,1043 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "gpu_regs.h" -#include "random.h" -#include "task.h" -#include "trig.h" -#include "constants/rgb.h" - -static void unc_080B08A0(struct Sprite *); -static void AnimSlideHandOrFootToTarget(struct Sprite *); -static void AnimJumpKick(struct Sprite *); -static void AnimBasicFistOrFoot(struct Sprite *); -static void AnimFistOrFootRandomPos(struct Sprite *); -static void AnimFistOrFootRandomPos_Step(struct Sprite *); -static void AnimCrossChopHand(struct Sprite *); -static void AnimCrossChopHand_Step(struct Sprite *); -static void AnimSlidingKick(struct Sprite *); -static void AnimSlidingKick_Step(struct Sprite *); -static void AnimSpinningKickOrPunch(struct Sprite *); -static void AnimStompFoot(struct Sprite *); -static void AnimStompFoot_Step(struct Sprite *); -static void AnimStompFoot_End(struct Sprite *); -static void AnimDizzyPunchDuck(struct Sprite *); -static void AnimBrickBreakWall(struct Sprite *); -static void AnimBrickBreakWall_Step(struct Sprite *); -static void AnimBrickBreakWallShard(struct Sprite *); -static void AnimBrickBreakWallShard_Step(struct Sprite *); -static void AnimSuperpowerOrb(struct Sprite *); -static void AnimSuperpowerOrb_Step(struct Sprite *); -static void AnimSuperpowerRock(struct Sprite *); -static void AnimSuperpowerRock_Step1(struct Sprite *); -static void AnimSuperpowerRock_Step2(struct Sprite *); -static void AnimSuperpowerFireball(struct Sprite *); -static void AnimArmThrustHit(struct Sprite *); -static void AnimArmThrustHit_Step(struct Sprite *sprite); -static void AnimRevengeScratch(struct Sprite *); -static void AnimFocusPunchFist(struct Sprite *); -static void AnimSpinningKickOrPunchFinish(struct Sprite *); - -extern struct SpriteTemplate gBasicHitSplatSpriteTemplate; - -// Unused -const struct SpriteTemplate gUnknown_08595E14 = -{ - .tileTag = ANIM_TAG_HUMANOID_FOOT, - .paletteTag = ANIM_TAG_HUMANOID_FOOT, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = unc_080B08A0, -}; - -static const union AnimCmd sAnim_HandOrFoot[] = -{ - ANIMCMD_FRAME(0, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_SlidingKick_0[] = -{ - ANIMCMD_FRAME(16, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_SlidingKick_1[] = -{ - ANIMCMD_FRAME(32, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_CrossChopHand_0[] = -{ - ANIMCMD_FRAME(48, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_CrossChopHand_1[] = -{ - ANIMCMD_FRAME(48, 1, .hFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_HandOrFoot[] = -{ - sAnim_HandOrFoot, -}; - -static const union AnimCmd *const sAnims_SlidingKick[] = -{ - sAnim_SlidingKick_0, - sAnim_SlidingKick_1, -}; - -static const union AnimCmd *const sAnims_CrossChopHand[] = -{ - sAnim_CrossChopHand_0, - sAnim_CrossChopHand_1, -}; - -const struct SpriteTemplate gKarateChopSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSlideHandOrFootToTarget, -}; - -const struct SpriteTemplate gJumpKickSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimJumpKick, -}; - -const struct SpriteTemplate gFistFootSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimBasicFistOrFoot, -}; - -const struct SpriteTemplate gFistFootRandomPosSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFistOrFootRandomPos, -}; - -const struct SpriteTemplate gCrossChopHandSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_CrossChopHand, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimCrossChopHand, -}; - -const struct SpriteTemplate gSlidingKickSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_SlidingKick, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSlidingKick, -}; - -static const union AffineAnimCmd sAffineAnim_SpinningHandOrFoot[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 20, 1), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd *const sAffineAnims_SpinningHandOrFoot[] = -{ - sAffineAnim_SpinningHandOrFoot, -}; - -// Blaze Kick / Meteor Mash -const struct SpriteTemplate gSpinningHandOrFootSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, - .images = NULL, - .affineAnims = sAffineAnims_SpinningHandOrFoot, - .callback = AnimSpinningKickOrPunch, -}; - -static const union AffineAnimCmd sAffineAnim_MegaPunchKick[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0xFFFC, 0xFFFC, 20, 1), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd *const sAffineAnims_MegaPunchKick[] = -{ - sAffineAnim_MegaPunchKick, -}; - -const struct SpriteTemplate gMegaPunchKickSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, - .images = NULL, - .affineAnims = sAffineAnims_MegaPunchKick, - .callback = AnimSpinningKickOrPunch, -}; - -const struct SpriteTemplate gStompFootSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_SlidingKick, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimStompFoot, -}; - -const struct SpriteTemplate gDizzyPunchDuckSpriteTemplate = -{ - .tileTag = ANIM_TAG_DUCK, - .paletteTag = ANIM_TAG_DUCK, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDizzyPunchDuck, -}; - -const struct SpriteTemplate gBrickBreakWallSpriteTemplate = -{ - .tileTag = ANIM_TAG_BLUE_LIGHT_WALL, - .paletteTag = ANIM_TAG_BLUE_LIGHT_WALL, - .oam = &gOamData_AffineOff_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimBrickBreakWall, -}; - -const struct SpriteTemplate gBrickBreakWallShardSpriteTemplate = -{ - .tileTag = ANIM_TAG_TORN_METAL, - .paletteTag = ANIM_TAG_TORN_METAL, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimBrickBreakWallShard, -}; - -static const union AffineAnimCmd sAffineAnim_SuperpowerOrb[] = -{ - AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), - AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 64), - AFFINEANIMCMD_FRAME(0xFFFA, 0xFFFA, 0, 8), - AFFINEANIMCMD_FRAME(0x6, 0x6, 0, 8), - AFFINEANIMCMD_JUMP(2), -}; - -static const union AffineAnimCmd *const sAffineAnims_SuperpowerOrb[] = -{ - sAffineAnim_SuperpowerOrb, -}; - -const struct SpriteTemplate gSuperpowerOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .oam = &gOamData_AffineDouble_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_SuperpowerOrb, - .callback = AnimSuperpowerOrb, -}; - -const struct SpriteTemplate gSuperpowerRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_FLAT_ROCK, - .paletteTag = ANIM_TAG_FLAT_ROCK, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSuperpowerRock, -}; - -const struct SpriteTemplate gSuperpowerFireballSpriteTemplate = -{ - .tileTag = ANIM_TAG_METEOR, - .paletteTag = ANIM_TAG_METEOR, - .oam = &gOamData_AffineOff_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSuperpowerFireball, -}; - -const struct SpriteTemplate gArmThrustHandSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimArmThrustHit, -}; - -static const union AnimCmd sAnim_RevengeSmallScratch_0[] = -{ - ANIMCMD_FRAME(0, 4), - ANIMCMD_FRAME(16, 4), - ANIMCMD_FRAME(32, 4), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_RevengeSmallScratch_1[] = -{ - ANIMCMD_FRAME(0, 4, .vFlip = TRUE), - ANIMCMD_FRAME(16, 4, .vFlip = TRUE), - ANIMCMD_FRAME(32, 4, .vFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_RevengeSmallScratch_2[] = -{ - ANIMCMD_FRAME(0, 4, .hFlip = TRUE), - ANIMCMD_FRAME(16, 4, .hFlip = TRUE), - ANIMCMD_FRAME(32, 4, .hFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_RevengeSmallScratch[] = -{ - sAnim_RevengeSmallScratch_0, - sAnim_RevengeSmallScratch_1, - sAnim_RevengeSmallScratch_2, -}; - -const struct SpriteTemplate gRevengeSmallScratchSpriteTemplate = -{ - .tileTag = ANIM_TAG_PURPLE_SCRATCH, - .paletteTag = ANIM_TAG_PURPLE_SCRATCH, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_RevengeSmallScratch, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimRevengeScratch, -}; - -static const union AnimCmd sAnim_RevengeBigScratch_0[] = -{ - ANIMCMD_FRAME(0, 6), - ANIMCMD_FRAME(64, 6), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_RevengeBigScratch_1[] = -{ - ANIMCMD_FRAME(0, 6, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_FRAME(64, 6, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_RevengeBigScratch_2[] = -{ - ANIMCMD_FRAME(0, 6, .hFlip = TRUE), - ANIMCMD_FRAME(64, 6, .hFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_RevengeBigScratch[] = -{ - sAnim_RevengeBigScratch_0, - sAnim_RevengeBigScratch_1, - sAnim_RevengeBigScratch_2, -}; - -const struct SpriteTemplate gRevengeBigScratchSpriteTemplate = -{ - .tileTag = ANIM_TAG_PURPLE_SWIPE, - .paletteTag = ANIM_TAG_PURPLE_SWIPE, - .oam = &gOamData_AffineOff_ObjNormal_64x64, - .anims = sAnims_RevengeBigScratch, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimRevengeScratch, -}; - -static const union AffineAnimCmd sAffineAnim_FocusPunchFist[] = -{ - AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0), - AFFINEANIMCMD_FRAME(0xFFE0, 0xFFE0, 0, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_FocusPunchFist[] = -{ - sAffineAnim_FocusPunchFist, -}; - -const struct SpriteTemplate gFocusPunchFistSpriteTemplate = -{ - .tileTag = ANIM_TAG_HANDS_AND_FEET, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, - .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, - .images = NULL, - .affineAnims = sAffineAnims_FocusPunchFist, - .callback = AnimFocusPunchFist, -}; - -static void unc_080B08A0(struct Sprite *sprite) -{ - SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[0] = 15; - sprite->callback = WaitAnimForDuration; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -static void AnimSlideHandOrFootToTarget(struct Sprite *sprite) -{ - if (gBattleAnimArgs[ARG_RET_ID] == 1 && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - } - - StartSpriteAnim(sprite, gBattleAnimArgs[6]); - gBattleAnimArgs[6] = 0; - AnimTravelDiagonally(sprite); -} - -static void AnimJumpKick(struct Sprite *sprite) -{ - if (IsContest()) - { - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - } - - AnimSlideHandOrFootToTarget(sprite); -} - -// Displays a basic fist or foot sprite for a given duration. -// Used by many fighting moves (and elemental "punch" moves). -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: duration -// arg 3: ? (todo: related to initial pixel offsets) -// arg 4: anim num -static void AnimBasicFistOrFoot(struct Sprite *sprite) -{ - StartSpriteAnim(sprite, gBattleAnimArgs[4]); - - if (gBattleAnimArgs[3] == 0) - InitSpritePosToAnimAttacker(sprite, 1); - else - InitSpritePosToAnimTarget(sprite, TRUE); - - sprite->data[0] = gBattleAnimArgs[2]; - sprite->callback = WaitAnimForDuration; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -static void AnimFistOrFootRandomPos(struct Sprite *sprite) -{ - u8 battler; - s16 xMod, yMod; - s16 x, y; - - if (gBattleAnimArgs[0] == 0) - battler = gBattleAnimAttacker; - else - battler = gBattleAnimTarget; - - if (gBattleAnimArgs[2] < 0) - gBattleAnimArgs[2] = Random2() % 5; - - StartSpriteAnim(sprite, gBattleAnimArgs[2]); - sprite->pos1.x = GetBattlerSpriteCoord(battler, 2); - sprite->pos1.y = GetBattlerSpriteCoord(battler, 3); - - xMod = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_WIDTH) / 2; - yMod = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_HEIGHT) / 4; - - x = Random2() % xMod; - y = Random2() % yMod; - - if (Random2() & 1) - x *= -1; - if (Random2() & 1) - y *= -1; - - if ((gBattlerPositions[battler] & BIT_SIDE) == B_SIDE_PLAYER) - y += 0xFFF0; - - sprite->pos1.x += x; - sprite->pos1.y += y; - - sprite->data[0] = gBattleAnimArgs[1]; - sprite->data[7] = CreateSprite(&gBasicHitSplatSpriteTemplate, sprite->pos1.x, sprite->pos1.y, sprite->subpriority + 1); - if (sprite->data[7] != 64) - { - StartSpriteAffineAnim(&gSprites[sprite->data[7]], 0); - gSprites[sprite->data[7]].callback = SpriteCallbackDummy; - } - - sprite->callback = AnimFistOrFootRandomPos_Step; -} - -static void AnimFistOrFootRandomPos_Step(struct Sprite *sprite) -{ - if (sprite->data[0] == 0) - { - if (sprite->data[7] != 64) - { - FreeOamMatrix(gSprites[sprite->data[7]].oam.matrixNum); - DestroySprite(&gSprites[sprite->data[7]]); - } - - DestroyAnimSprite(sprite); - } - else - { - sprite->data[0]--; - } -} - -static void AnimCrossChopHand(struct Sprite *sprite) -{ - InitSpritePosToAnimTarget(sprite, TRUE); - sprite->data[0] = 30; - - if (gBattleAnimArgs[2] == 0) - { - sprite->data[2] = sprite->pos1.x - 20; - } - else - { - sprite->data[2] = sprite->pos1.x + 20; - sprite->hFlip = 1; - } - - sprite->data[4] = sprite->pos1.y - 20; - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, AnimCrossChopHand_Step); -} - -static void AnimCrossChopHand_Step(struct Sprite *sprite) -{ - if (++sprite->data[5] == 11) - { - sprite->data[2] = sprite->pos1.x - sprite->pos2.x; - sprite->data[4] = sprite->pos1.y - sprite->pos2.y; - sprite->data[0] = 8; - sprite->pos1.x += sprite->pos2.x; - sprite->pos1.y += sprite->pos2.y; - sprite->pos2.y = 0; - sprite->pos2.x = 0; - - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - } -} - -// Rolling Kick / Low Kick -static void AnimSlidingKick(struct Sprite *sprite) -{ - if (BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget && GetBattlerPosition(gBattleAnimTarget) < B_POSITION_PLAYER_RIGHT) - gBattleAnimArgs[0] *= -1; - - InitSpritePosToAnimTarget(sprite, TRUE); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - - sprite->data[0] = gBattleAnimArgs[3]; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = sprite->pos1.y; - - InitAnimLinearTranslation(sprite); - - sprite->data[5] = gBattleAnimArgs[5]; - sprite->data[6] = gBattleAnimArgs[4]; - sprite->data[7] = 0; - - sprite->callback = AnimSlidingKick_Step; -} - -static void AnimSlidingKick_Step(struct Sprite *sprite) -{ - if (!AnimTranslateLinear(sprite)) - { - sprite->pos2.y += Sin(sprite->data[7] >> 8, sprite->data[5]); - sprite->data[7] += sprite->data[6]; - } - else - { - DestroyAnimSprite(sprite); - } -} - -// Animates the spinning, shrinking kick or punch, which then -// reappears at full size. Used by moves such as MOVE_MEGA_PUNCH and MOVE_MEGA_KICK. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: anim num -// arg 3: spin duration -static void AnimSpinningKickOrPunch(struct Sprite *sprite) -{ - InitSpritePosToAnimTarget(sprite, TRUE); - StartSpriteAnim(sprite, gBattleAnimArgs[2]); - sprite->data[0] = gBattleAnimArgs[3]; - - sprite->callback = WaitAnimForDuration; - StoreSpriteCallbackInData6(sprite, AnimSpinningKickOrPunchFinish); -} - -static void AnimSpinningKickOrPunchFinish(struct Sprite *sprite) -{ - StartSpriteAffineAnim(sprite, 0); - sprite->affineAnimPaused = 1; - sprite->data[0] = 20; - - sprite->callback = WaitAnimForDuration; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Animates MOVE_STOMP's foot that slides downward. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: initial wait duration -static void AnimStompFoot(struct Sprite *sprite) -{ - InitSpritePosToAnimTarget(sprite, TRUE); - sprite->data[0] = gBattleAnimArgs[2]; - - sprite->callback = AnimStompFoot_Step; -} - -static void AnimStompFoot_Step(struct Sprite *sprite) -{ - if (--sprite->data[0] == -1) - { - sprite->data[0] = 6; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, AnimStompFoot_End); - } -} - -static void AnimStompFoot_End(struct Sprite *sprite) -{ - sprite->data[0] = 15; - - sprite->callback = WaitAnimForDuration; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -static void AnimDizzyPunchDuck(struct Sprite *sprite) -{ - if (sprite->data[0] == 0) - { - InitSpritePosToAnimTarget(sprite, TRUE); - sprite->data[1] = gBattleAnimArgs[2]; - sprite->data[2] = gBattleAnimArgs[3]; - sprite->data[0]++; - } - else - { - sprite->data[4] += sprite->data[1]; - sprite->pos2.x = sprite->data[4] >> 8; - sprite->pos2.y = Sin(sprite->data[3], sprite->data[2]); - sprite->data[3] = (sprite->data[3] + 3) & 0xFF; - - if (sprite->data[3] > 100) - sprite->invisible = sprite->data[3] % 2; - - if (sprite->data[3] > 120) - DestroyAnimSprite(sprite); - } -} - -// The wall that appears when Brick Break is going to shatter the target's defensive wall -static void AnimBrickBreakWall(struct Sprite *sprite) -{ - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1); - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); - } - - sprite->pos1.x += gBattleAnimArgs[1]; - sprite->pos1.y += gBattleAnimArgs[2]; - - sprite->data[0] = 0; - sprite->data[1] = gBattleAnimArgs[3]; - sprite->data[2] = gBattleAnimArgs[4]; - sprite->data[3] = 0; - sprite->callback = AnimBrickBreakWall_Step; -} - -static void AnimBrickBreakWall_Step(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - if (--sprite->data[1] == 0) - { - if (sprite->data[2] == 0) - DestroyAnimSprite(sprite); - else - sprite->data[0]++; - } - break; - case 1: - if (++sprite->data[1] > 1) - { - sprite->data[1] = 0; - sprite->data[3]++; - if (sprite->data[3] & 1) - sprite->pos2.x = 2; - else - sprite->pos2.x = -2; - } - - if (--sprite->data[2] == 0) - DestroyAnimSprite(sprite); - break; - } -} - -// Piece of shattered defensive wall flies off. Used by Brick Break when the target has a defensive wall -static void AnimBrickBreakWallShard(struct Sprite *sprite) -{ - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0) + gBattleAnimArgs[2]; - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + gBattleAnimArgs[3]; - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0) + gBattleAnimArgs[2]; - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + gBattleAnimArgs[3]; - } - - sprite->oam.tileNum += gBattleAnimArgs[1] * 16; - sprite->data[0] = 0; - - switch (gBattleAnimArgs[1]) - { - case 0: - sprite->data[6] = -3; - sprite->data[7] = -3; - break; - case 1: - sprite->data[6] = 3; - sprite->data[7] = -3; - break; - case 2: - sprite->data[6] = -3; - sprite->data[7] = 3; - break; - case 3: - sprite->data[6] = 3; - sprite->data[7] = 3; - break; - default: - DestroyAnimSprite(sprite); - return; - } - - sprite->callback = AnimBrickBreakWallShard_Step; -} - -static void AnimBrickBreakWallShard_Step(struct Sprite *sprite) -{ - sprite->pos1.x += sprite->data[6]; - sprite->pos1.y += sprite->data[7]; - - if (++sprite->data[0] > 40) - DestroyAnimSprite(sprite); -} - -static void AnimSuperpowerOrb(struct Sprite *sprite) -{ - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattlerAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattlerAttacker, 3); - sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker); - sprite->data[7] = gBattleAnimTarget; - } - else - { - sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); - sprite->data[7] = gBattleAnimAttacker; - } - - sprite->data[0] = 0; - sprite->data[1] = 12; - sprite->data[2] = 8; - sprite->callback = AnimSuperpowerOrb_Step; -} - -static void AnimSuperpowerOrb_Step(struct Sprite *sprite) -{ - if (++sprite->data[0] == 180) - { - SetGpuReg(REG_OFFSET_BLDCNT, 0); - - sprite->data[0] = 16; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = GetBattlerSpriteCoord(sprite->data[7], 2); - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = GetBattlerSpriteCoord(sprite->data[7], 3); - - InitAnimLinearTranslation(sprite); - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = sub_80A6F98; - } -} - -// Floating rock that flies off to hit the target. Used by Superpower -static void AnimSuperpowerRock(struct Sprite *sprite) -{ - sprite->pos1.x = gBattleAnimArgs[0]; - sprite->pos1.y = 120; - - sprite->data[0] = gBattleAnimArgs[3]; - StorePointerInVars(&sprite->data[4], &sprite->data[5], (void *)(sprite->pos1.y << 8)); - - sprite->data[6] = gBattleAnimArgs[1]; - sprite->oam.tileNum += gBattleAnimArgs[2] * 4; - - sprite->callback = AnimSuperpowerRock_Step1; -} - -static void AnimSuperpowerRock_Step1(struct Sprite *sprite) -{ - void *var0; - - if (sprite->data[0] != 0) - { - var0 = LoadPointerFromVars(sprite->data[4], sprite->data[5]); - var0 -= sprite->data[6]; - StorePointerInVars(&sprite->data[4], &sprite->data[5], var0); - - var0 = (void *)(((intptr_t)var0) >> 8); - sprite->pos1.y = (intptr_t)var0; - if (sprite->pos1.y < -8) - DestroyAnimSprite(sprite); - else - sprite->data[0]--; - } - else - { - s16 pos0 = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - s16 pos1 = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); - s16 pos2 = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - s16 pos3 = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - - sprite->data[0] = pos2 - pos0; - sprite->data[1] = pos3 - pos1; - sprite->data[2] = sprite->pos1.x << 4; - sprite->data[3] = sprite->pos1.y << 4; - - sprite->callback = AnimSuperpowerRock_Step2; - } -} - -static void AnimSuperpowerRock_Step2(struct Sprite *sprite) -{ - u16 edgeX; - - sprite->data[2] += sprite->data[0]; - sprite->data[3] += sprite->data[1]; - sprite->pos1.x = sprite->data[2] >> 4; - sprite->pos1.y = sprite->data[3] >> 4; - - edgeX = sprite->pos1.x + 8; - if (edgeX > 256 || sprite->pos1.y < -8 || sprite->pos1.y > 120) - DestroyAnimSprite(sprite); -} - -static void AnimSuperpowerFireball(struct Sprite *sprite) -{ - u8 battler; - - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattlerAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattlerAttacker, 3); - battler = gBattleAnimTarget; - sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker); - } - else - { - battler = gBattleAnimAttacker; - sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); - } - - if (IsContest()) - sprite->oam.matrixNum |= ST_OAM_HFLIP; - else if (GetBattlerSide(battler) == B_SIDE_PLAYER) - sprite->oam.matrixNum |= (ST_OAM_HFLIP | ST_OAM_VFLIP); - - sprite->data[0] = 16; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = GetBattlerSpriteCoord(battler, 2); - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = GetBattlerSpriteCoord(battler, 3); - - InitAnimLinearTranslation(sprite); - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - sprite->callback = sub_80A6F98; -} - -static void AnimArmThrustHit_Step(struct Sprite *sprite) -{ - if (sprite->data[0] == sprite->data[4]) - DestroyAnimSprite(sprite); - - sprite->data[0]++; -} - -static void AnimArmThrustHit(struct Sprite *sprite) -{ - u8 turn; - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - sprite->data[1] = gBattleAnimArgs[3]; - sprite->data[2] = gBattleAnimArgs[0]; - sprite->data[3] = gBattleAnimArgs[1]; - sprite->data[4] = gBattleAnimArgs[2]; - - turn = gAnimMoveTurn; - if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) - turn++; - - if (turn & 1) - { - sprite->data[2] = -sprite->data[2]; - sprite->data[1]++; - } - - StartSpriteAnim(sprite, sprite->data[1]); - sprite->pos2.x = sprite->data[2]; - sprite->pos2.y = sprite->data[3]; - sprite->callback = AnimArmThrustHit_Step; -} - -static void AnimRevengeScratch(struct Sprite *sprite) -{ - if (gBattleAnimArgs[2] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, 0); - else - InitSpritePosToAnimTarget(sprite, FALSE); - - if (IsContest()) - { - StartSpriteAnim(sprite, 2); - } - else if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - StartSpriteAnim(sprite, 1); - } - - sprite->callback = RunStoredCallbackWhenAnimEnds; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Fist shrinks toward target and shakes -static void AnimFocusPunchFist(struct Sprite *sprite) -{ - if (sprite->affineAnimEnded) - { - sprite->data[1] = (sprite->data[1] + 40) & 0xFF; - sprite->pos2.x = Sin(sprite->data[1], 2); - if (++sprite->data[0] > 40) - DestroyAnimSprite(sprite); - } -} - -void AnimTask_MoveSkyUppercutBg(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - sub_80A6DAC(0); - task->data[8] = gBattleAnimArgs[0]; - task->data[0]++; - break; - case 1: - if (--task->data[8] == -1) - task->data[0]++; - break; - case 2: - default: - task->data[9] += 1280; - break; - } - - task->data[10] += 2816; - - if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) - gBattle_BG3_X += task->data[9] >> 8; - else - gBattle_BG3_X -= task->data[9] >> 8; - - gBattle_BG3_Y += task->data[10] >> 8; - task->data[9] &= 0xFF; - task->data[10] &= 0xFF; - - if (gBattleAnimArgs[ARG_RET_ID] == -1) - { - gBattle_BG3_X = 0; - gBattle_BG3_Y = 0; - sub_80A6DAC(1); - DestroyAnimVisualTask(taskId); - } -} diff --git a/src/fire.c b/src/fire.c deleted file mode 100644 index f02ecae19..000000000 --- a/src/fire.c +++ /dev/null @@ -1,1335 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "constants/rgb.h" -#include "constants/songs.h" -#include "sound.h" -#include "util.h" -#include "task.h" -#include "trig.h" - -static void AnimFireSpiralInward(struct Sprite *); -static void AnimFireSpread(struct Sprite *); -static void AnimFirePlume(struct Sprite *); -static void AnimLargeFlame(struct Sprite *); -static void sub_8109028(struct Sprite *); -static void sub_8109064(struct Sprite *); -static void sub_81090D8(struct Sprite *); -static void AnimSunlight(struct Sprite *); -static void AnimEmberFlare(struct Sprite *); -static void AnimBurnFlame(struct Sprite *); -static void AnimFireRing(struct Sprite *); -static void AnimFireRing_Step1(struct Sprite *); -static void AnimFireRing_Step2(struct Sprite *); -static void AnimFireRing_Step3(struct Sprite *); -static void UpdateFireRingCircleOffset(struct Sprite *); -static void AnimFireCross(struct Sprite *); -static void AnimFireSpiralOutward(struct Sprite *); -static void AnimFireSpiralOutward_Step1(struct Sprite *); -static void AnimFireSpiralOutward_Step2(struct Sprite *); -static void AnimTask_EruptionLaunchRocks_Step(u8 taskId); -static void CreateEruptionLaunchRocks(u8 spriteId, u8 taskId, u8 a3); -static void AnimEruptionLaunchRock(struct Sprite *); -static u16 GetEruptionLaunchRockInitialYPos(u8 spriteId); -static void InitEruptionLaunchRockCoordData(struct Sprite *sprite, s16 x, s16 y); -static void UpdateEruptionLaunchRockPos(struct Sprite *); -static void AnimEruptionFallingRock(struct Sprite *); -static void AnimEruptionFallingRock_Step(struct Sprite *); -static void AnimWillOWispOrb(struct Sprite *); -static void AnimWillOWispOrb_Step(struct Sprite *); -static void AnimWillOWispFire(struct Sprite *); -static void AnimTask_MoveHeatWaveTargets_Step(u8 taskId); - -static const union AnimCmd sAnim_FireSpiralSpread_0[] = -{ - ANIMCMD_FRAME(16, 4), - ANIMCMD_FRAME(32, 4), - ANIMCMD_FRAME(48, 4), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd sAnim_FireSpiralSpread_1[] = -{ - ANIMCMD_FRAME(16, 4, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_FRAME(32, 4, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_FRAME(48, 4, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_FireSpiralSpread[] = -{ - sAnim_FireSpiralSpread_0, - sAnim_FireSpiralSpread_1, -}; - -const struct SpriteTemplate gFireSpiralInwardSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_FireSpiralSpread, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFireSpiralInward, -}; - -const struct SpriteTemplate gFireSpreadSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_FireSpiralSpread, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFireSpread, -}; - -static const union AnimCmd sAnim_LargeFlame[] = -{ - ANIMCMD_FRAME(0, 3), - ANIMCMD_FRAME(16, 3), - ANIMCMD_FRAME(32, 3), - ANIMCMD_FRAME(48, 3), - ANIMCMD_FRAME(64, 3), - ANIMCMD_FRAME(80, 3), - ANIMCMD_FRAME(96, 3), - ANIMCMD_FRAME(112, 3), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_LargeFlame[] = -{ - sAnim_LargeFlame, -}; - -static const union AnimCmd sAnim_FirePlume[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(16, 5), - ANIMCMD_FRAME(32, 5), - ANIMCMD_FRAME(48, 5), - ANIMCMD_FRAME(64, 5), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_FirePlume[] = -{ - sAnim_FirePlume, -}; - -static const union AffineAnimCmd sAffineAnim_LargeFlame[] = -{ - AFFINEANIMCMD_FRAME(0x32, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0x20, 0x0, 0, 7), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_LargeFlame[] = -{ - sAffineAnim_LargeFlame, -}; - -const struct SpriteTemplate gLargeFlameSpriteTemplate = -{ - .tileTag = ANIM_TAG_FIRE, - .paletteTag = ANIM_TAG_FIRE, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = sAnims_LargeFlame, - .images = NULL, - .affineAnims = sAffineAnims_LargeFlame, - .callback = AnimLargeFlame, -}; - -const struct SpriteTemplate gLargeFlameScatterSpriteTemplate = -{ - .tileTag = ANIM_TAG_FIRE, - .paletteTag = ANIM_TAG_FIRE, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_LargeFlame, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimLargeFlame, -}; - -const struct SpriteTemplate gFirePlumeSpriteTemplate = -{ - .tileTag = ANIM_TAG_FIRE_PLUME, - .paletteTag = ANIM_TAG_FIRE_PLUME, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_FirePlume, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFirePlume, -}; - -// Unused -const struct SpriteTemplate gUnknown_08595440 = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_FirePlume, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFirePlume, -}; - -static const union AnimCmd gUnknown_08595458[] = -{ - ANIMCMD_FRAME(16, 6), - ANIMCMD_FRAME(32, 6), - ANIMCMD_FRAME(48, 6), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const gUnknown_08595468[] = -{ - gUnknown_08595458, -}; - -// Unused -const struct SpriteTemplate gUnknown_0859546C = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gUnknown_08595468, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_8109064, -}; - -static const union AffineAnimCmd sAffineAnim_SunlightRay[] = -{ - AFFINEANIMCMD_FRAME(0x50, 0x50, 0, 0), - AFFINEANIMCMD_FRAME(0x2, 0x2, 10, 1), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd *const sAffineAnims_SunlightRay[] = -{ - sAffineAnim_SunlightRay, -}; - -const struct SpriteTemplate gSunlightRaySpriteTemplate = -{ - .tileTag = ANIM_TAG_SUNLIGHT, - .paletteTag = ANIM_TAG_SUNLIGHT, - .oam = &gOamData_AffineNormal_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_SunlightRay, - .callback = AnimSunlight, -}; - -static const union AnimCmd sAnim_BasicFire[] = -{ - ANIMCMD_FRAME(0, 4), - ANIMCMD_FRAME(16, 4), - ANIMCMD_FRAME(32, 4), - ANIMCMD_FRAME(48, 4), - ANIMCMD_FRAME(64, 4), - ANIMCMD_JUMP(0), -}; - -const union AnimCmd *const gAnims_BasicFire[] = -{ - sAnim_BasicFire, -}; - -const struct SpriteTemplate gEmberSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = TranslateAnimSpriteToTargetMonLocation, -}; - -const struct SpriteTemplate gEmberFlareSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gAnims_BasicFire, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimEmberFlare, -}; - -const struct SpriteTemplate gBurnFlameSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gAnims_BasicFire, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimBurnFlame, -}; - -const struct SpriteTemplate gFireBlastRingSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gAnims_BasicFire, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFireRing, -}; - -static const union AnimCmd sAnim_FireBlastCross[] = -{ - ANIMCMD_FRAME(32, 6), - ANIMCMD_FRAME(48, 6), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_FireBlastCross[] = -{ - sAnim_FireBlastCross, -}; - -static const union AffineAnimCmd gUnknown_08595544[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd gUnknown_08595554[] = -{ - AFFINEANIMCMD_FRAME(0xA0, 0xA0, 0, 0), - AFFINEANIMCMD_END, -}; - -// Unused -static const union AffineAnimCmd *const gUnknown_08595564[] = -{ - gUnknown_08595544, - gUnknown_08595554, -}; - -const struct SpriteTemplate gFireBlastCrossSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_FireBlastCross, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFireCross, -}; - -const struct SpriteTemplate gFireSpiralOutwardSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gAnims_BasicFire, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFireSpiralOutward, -}; - -const struct SpriteTemplate gWeatherBallFireDownSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gAnims_BasicFire, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimWeatherBallDown, -}; - -const struct SpriteTemplate gEruptionLaunchRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_WARM_ROCK, - .paletteTag = ANIM_TAG_WARM_ROCK, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimEruptionLaunchRock, -}; - -static const s16 sEruptionLaunchRockCoords[][2] = -{ - {-2, -5}, - {-1, -1}, - { 3, -6}, - { 4, -2}, - { 2, -8}, - {-5, -5}, - { 4, -7}, -}; - -const struct SpriteTemplate gEruptionFallingRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_WARM_ROCK, - .paletteTag = ANIM_TAG_WARM_ROCK, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimEruptionFallingRock, -}; - -static const union AnimCmd sAnim_WillOWispOrb_0[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(4, 5), - ANIMCMD_FRAME(8, 5), - ANIMCMD_FRAME(12, 5), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd sAnim_WillOWispOrb_1[] = -{ - ANIMCMD_FRAME(16, 5), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_WillOWispOrb_2[] = -{ - ANIMCMD_FRAME(20, 5), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_WillOWispOrb_3[] = -{ - ANIMCMD_FRAME(20, 5), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_WillOWispOrb[] = -{ - sAnim_WillOWispOrb_0, - sAnim_WillOWispOrb_1, - sAnim_WillOWispOrb_2, - sAnim_WillOWispOrb_3, -}; - -const struct SpriteTemplate gWillOWispOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_WISP_ORB, - .paletteTag = ANIM_TAG_WISP_ORB, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = sAnims_WillOWispOrb, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimWillOWispOrb, -}; - -static const union AnimCmd sAnim_WillOWispFire[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(16, 5), - ANIMCMD_FRAME(32, 5), - ANIMCMD_FRAME(48, 5), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_WillOWispFire[] = -{ - sAnim_WillOWispFire, -}; - -const struct SpriteTemplate gWillOWispFireSpriteTemplate = -{ - .tileTag = ANIM_TAG_WISP_FIRE, - .paletteTag = ANIM_TAG_WISP_FIRE, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_WillOWispFire, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimWillOWispFire, -}; - -// Directions for shaking up/down or left/right in AnimTask_ShakeTargetInPattern -// Only first 10 values are ever accessed. -// First pattern results in larger shakes, second results in faster oscillation -static const s8 sShakeDirsPattern0[16] = -{ - -1, -1, 0, 1, 1, 0, 0, -1, -1, 1, 1, 0, 0, -1, 0, 1, -}; - -static const s8 sShakeDirsPattern1[16] = -{ - -1, 0, 1, 0, -1, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 1, -}; - -// For the first stage of Fire Punch -static void AnimFireSpiralInward(struct Sprite *sprite) -{ - sprite->data[0] = gBattleAnimArgs[0]; - sprite->data[1] = 0x3C; - sprite->data[2] = 0x9; - sprite->data[3] = 0x1E; - sprite->data[4] = 0xFE00; - - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - - sprite->callback = TranslateSpriteInGrowingCircleOverDuration; - sprite->callback(sprite); -} - -// For the impact spread of fire sprites for moves like Blaze Kick or Fire Punch -static void AnimFireSpread(struct Sprite *sprite) -{ - SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); - - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[1] = gBattleAnimArgs[2]; - sprite->data[2] = gBattleAnimArgs[3]; - - sprite->callback = TranslateSpriteLinearFixedPoint; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -static void AnimFirePlume(struct Sprite *sprite) -{ - SetSpriteCoordsToAnimAttackerCoords(sprite); - - if (GetBattlerSide(gBattleAnimAttacker)) - { - sprite->pos1.x -= gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[2] = -gBattleAnimArgs[4]; - } - else - { - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[2] = gBattleAnimArgs[4]; - } - - sprite->data[1] = gBattleAnimArgs[2]; - sprite->data[4] = gBattleAnimArgs[3]; - sprite->data[3] = gBattleAnimArgs[5]; - - sprite->callback = sub_8109028; -} - -static void AnimLargeFlame(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker)) - { - sprite->pos1.x -= gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[2] = gBattleAnimArgs[4]; - } - else - { - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[2] = -gBattleAnimArgs[4]; - } - - sprite->data[1] = gBattleAnimArgs[2]; - sprite->data[4] = gBattleAnimArgs[3]; - sprite->data[3] = gBattleAnimArgs[5]; - - sprite->callback = sub_8109028; -} - -static void sub_8109028(struct Sprite *sprite) -{ - if (++sprite->data[0] < sprite->data[4]) - { - sprite->pos2.x += sprite->data[2]; - sprite->pos2.y += sprite->data[3]; - } - - if (sprite->data[0] == sprite->data[1]) - DestroySpriteAndMatrix(sprite); -} - -static void sub_8109064(struct Sprite *sprite) -{ - SetSpriteCoordsToAnimAttackerCoords(sprite); - - if (GetBattlerSide(gBattleAnimAttacker)) - { - sprite->pos1.x -= gBattleAnimArgs[0]; - } - else - { - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->subpriority = 8; - } - - 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->data[4] = gBattleAnimArgs[6]; - sprite->data[5] = 0; - - sprite->callback = sub_81090D8; -} - -static void sub_81090D8(struct Sprite *sprite) -{ - if (sprite->data[3]) - { - if(sprite->data[5] > 10000) - sprite->subpriority = 1; - - sprite->pos2.x = Sin(sprite->data[0], sprite->data[1] + (sprite->data[5] >> 8)); - sprite->pos2.y = Cos(sprite->data[0], sprite->data[1] + (sprite->data[5] >> 8)); - - sprite->data[0] += sprite->data[2]; - sprite->data[5] += sprite->data[4]; - - if (sprite->data[0] > 255) - sprite->data[0] -= 256; - else if (sprite->data[0] < 0) - sprite->data[0] += 256; - - sprite->data[3]--; - } - else - { - DestroySpriteAndMatrix(sprite); - } -} - -// Sunlight from Sunny Day / sunny weather -static void AnimSunlight(struct Sprite *sprite) -{ - sprite->pos1.x = 0; - sprite->pos1.y = 0; - sprite->data[0] = 60; - sprite->data[2] = 140; - sprite->data[4] = 80; - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -//fire 2 - -// Animates the secondary effect of MOVE_EMBER, where the flames grow and slide -// horizontally a bit. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: target x pixel offset -// arg 3: target y pixel offset -// arg 4: duration -// arg 5: ? (todo: something related to which mon the pixel offsets are based on) -// arg 6: ? (todo: something related to which mon the pixel offsets are based on) -static void AnimEmberFlare(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker) == GetBattlerSide(gBattleAnimTarget) - && (gBattleAnimAttacker == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT) - || gBattleAnimAttacker == GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT))) - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - - sprite->callback = AnimTravelDiagonally; - sprite->callback(sprite); -} - -static void AnimBurnFlame(struct Sprite *sprite) -{ - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - - sprite->callback = AnimTravelDiagonally; -} - -// Animates the a fire sprite in the first-half of the MOVE_FIRE_BLAST -// animation. The fire sprite first moves in a circle around the mon, -// and then it is translated towards the target mon, while still rotating. -// Lastly, it moves in a circle around the target mon. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: initial wave offset -//void AnimFireRing(struct Sprite *sprite) -void AnimFireRing(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, 1); - - sprite->data[7] = gBattleAnimArgs[2]; - sprite->data[0] = 0; - - sprite->callback = AnimFireRing_Step1; -} - -static void AnimFireRing_Step1(struct Sprite *sprite) -{ - UpdateFireRingCircleOffset(sprite); - - if (++sprite->data[0] == 0x12) - { - sprite->data[0] = 0x19; - 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->callback = AnimFireRing_Step2; - } -} - -static void AnimFireRing_Step2(struct Sprite *sprite) -{ - if (AnimTranslateLinear(sprite)) - { - sprite->data[0] = 0; - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - sprite->pos2.y = 0; - sprite->pos2.x = 0; - - sprite->callback = AnimFireRing_Step3; - sprite->callback(sprite); - } - else - { - sprite->pos2.x += Sin(sprite->data[7], 28); - sprite->pos2.y += Cos(sprite->data[7], 28); - - sprite->data[7] = (sprite->data[7] + 20) & 0xFF; - } -} - -static void AnimFireRing_Step3(struct Sprite *sprite) -{ - UpdateFireRingCircleOffset(sprite); - - if (++sprite->data[0] == 0x1F) - DestroyAnimSprite(sprite); -} - -static void UpdateFireRingCircleOffset(struct Sprite *sprite) -{ - sprite->pos2.x = Sin(sprite->data[7], 28); - sprite->pos2.y = Cos(sprite->data[7], 28); - - sprite->data[7] = (sprite->data[7] + 20) & 0xFF; -} - -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: duration -// arg 3: x delta -// arg 4: y delta -// AnimFireCross(struct Sprite *sprite) -static void AnimFireCross(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]; - - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - - sprite->callback = TranslateSpriteLinear; -} - -static void AnimFireSpiralOutward(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, 1); - - sprite->data[1] = gBattleAnimArgs[2]; - sprite->data[0] = gBattleAnimArgs[3]; - - sprite->invisible = TRUE; - sprite->callback = WaitAnimForDuration; - - StoreSpriteCallbackInData6(sprite, AnimFireSpiralOutward_Step1); -} - -static void AnimFireSpiralOutward_Step1(struct Sprite *sprite) -{ - sprite->invisible = FALSE; - - sprite->data[0] = sprite->data[1]; - sprite->data[1] = 0; - - sprite->callback = AnimFireSpiralOutward_Step2; - sprite->callback(sprite); -} - -static void AnimFireSpiralOutward_Step2(struct Sprite *sprite) -{ - sprite->pos2.x = Sin(sprite->data[1], sprite->data[2] >> 8); - sprite->pos2.y = Cos(sprite->data[1], sprite->data[2] >> 8); - - sprite->data[1] = (sprite->data[1] + 10) & 0xFF; - sprite->data[2] += 0xD0; - - if (--sprite->data[0] == -1) - DestroyAnimSprite(sprite); -} - -// Animates first stage of Eruption where the attacker squishes and launches rocks away from themself -void AnimTask_EruptionLaunchRocks(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); - - task->data[0] = 0; - task->data[1] = 0; - task->data[2] = 0; - task->data[3] = 0; - task->data[4] = gSprites[task->data[15]].pos1.y; - task->data[5] = GetBattlerSide(gBattleAnimAttacker); - task->data[6] = 0; - - PrepareBattlerSpriteForRotScale(task->data[15], ST_OAM_OBJ_NORMAL); - - task->func = AnimTask_EruptionLaunchRocks_Step; -} - -static void AnimTask_EruptionLaunchRocks_Step(u8 taskId) // animate Move_ERUPTION? -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - sub_80A805C(task, task->data[15], 0x100, 0x100, 0xE0, 0x200, 0x20); - - task->data[0]++; - case 1: - if (++task->data[1] > 1) - { - task->data[1] = 0; - - if (++task->data[2] & 0x1) - gSprites[task->data[15]].pos2.x = 3; - else - gSprites[task->data[15]].pos2.x = -3; - } - - if (task->data[5]) - { - if (++task->data[3] > 4) - { - task->data[3] = 0; - gSprites[task->data[15]].pos1.y++; - } - } - - if(!sub_80A80C8(task)) - { - SetBattlerSpriteYOffsetFromYScale(task->data[15]); - gSprites[task->data[15]].pos2.x = 0; - - task->data[1] = 0; - task->data[2] = 0; - task->data[3] = 0; - task->data[0]++; - } - break; - case 2: - if (++task->data[1] > 4) - { - if (task->data[5]) - sub_80A805C(task, task->data[15], 0xE0, 0x200, 0x180, 0xF0, 0x6); - else - sub_80A805C(task, task->data[15], 0xE0, 0x200, 0x180, 0xC0, 0x6); - - task->data[1] = 0; - task->data[0]++; - } - break; - case 3: - if (!sub_80A80C8(task)) - { - CreateEruptionLaunchRocks(task->data[15], taskId, 6); - - task->data[0]++; - } - break; - case 4: - if (++task->data[1] > 1) - { - task->data[1] = 0; - - if (++task->data[2] & 1) - gSprites[task->data[15]].pos2.y += 3; - else - gSprites[task->data[15]].pos2.y -= 3; - } - - if (++task->data[3] > 0x18) - { - if (task->data[5]) - sub_80A805C(task, task->data[15], 0x180, 0xF0, 0x100, 0x100, 0x8); - else - sub_80A805C(task, task->data[15], 0x180, 0xC0, 0x100, 0x100, 0x8); - - if (task->data[2] & 1) - gSprites[task->data[15]].pos2.y -= 3; - - task->data[1] = 0; - task->data[2] = 0; - task->data[3] = 0; - task->data[0]++; - } - break; - case 5: - if (task->data[5]) - gSprites[task->data[15]].pos1.y--; - - if (!sub_80A80C8(task)) - { - gSprites[task->data[15]].pos1.y = task->data[4]; - ResetSpriteRotScale(task->data[15]); - - task->data[2] = 0; - task->data[0]++; - } - break; - case 6: - if (!task->data[6]) - DestroyAnimVisualTask(taskId); - - break; - default: - break; - } -} - -static void CreateEruptionLaunchRocks(u8 spriteId, u8 taskId, u8 a3) -{ - u16 i, j; - s8 sign; - - u16 y = GetEruptionLaunchRockInitialYPos(spriteId); - u16 x = gSprites[spriteId].pos1.x; - - if(!GetBattlerSide(gBattleAnimAttacker)) - { - x -= 0xC; - sign = 1; - } - else - { - x += 0x10; - sign = -1; - } - - for (i = 0, j = 0; i <= 6; i++) - { - u8 spriteId = CreateSprite(&gEruptionLaunchRockSpriteTemplate, x, y, 2); - - if (spriteId != 0x40) - { - gSprites[spriteId].oam.tileNum += j * 4 + 0x40; - - if (++j >= 5) - j = 0; - - InitEruptionLaunchRockCoordData(&gSprites[spriteId], sEruptionLaunchRockCoords[i][0] * sign, sEruptionLaunchRockCoords[i][1]); - gSprites[spriteId].data[6] = taskId; - gSprites[spriteId].data[7] = a3; - - gTasks[taskId].data[a3]++; - } - } -} - -static void AnimEruptionLaunchRock(struct Sprite *sprite) -{ - UpdateEruptionLaunchRockPos(sprite); - - if (sprite->invisible) - { - gTasks[sprite->data[6]].data[sprite->data[7]]--; - DestroySprite(sprite); - } -} - -static u16 GetEruptionLaunchRockInitialYPos(u8 spriteId) -{ - u16 y = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y + gSprites[spriteId].centerToCornerVecY; - - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) - { - y = ((y << 16) + 0x4A0000) >> 16; - } - else - { - y = ((y << 16) + 0x2C0000) >> 16; - } - - return y; -} - -static void InitEruptionLaunchRockCoordData(struct Sprite *sprite, s16 x, s16 y) -{ - sprite->data[0] = 0; - sprite->data[1] = 0; - sprite->data[2] = (u16)sprite->pos1.x * 8; - sprite->data[3] = (u16)sprite->pos1.y * 8; - sprite->data[4] = x * 8; - sprite->data[5] = y * 8; -} - -static void UpdateEruptionLaunchRockPos(struct Sprite *sprite) -{ - int var1; - if (++sprite->data[0] > 2) - { - sprite->data[0] = 0; - ++sprite->data[1]; - var1 = (u16)sprite->data[1] * (u16)sprite->data[1]; - sprite->data[3] += var1; - } - - sprite->data[2] += sprite->data[4]; - sprite->pos1.x = sprite->data[2] >> 3; - sprite->data[3] += sprite->data[5]; - sprite->pos1.y = sprite->data[3] >> 3; - - if (sprite->pos1.x < -8 || sprite->pos1.x > 0xf8 || sprite->pos1.y < -8 || sprite->pos1.y > 120) - sprite->invisible = TRUE; -} - -static void AnimEruptionFallingRock(struct Sprite *sprite) -{ - sprite->pos1.x = gBattleAnimArgs[0]; - sprite->pos1.y = gBattleAnimArgs[1]; - - sprite->data[0] = 0; - sprite->data[1] = 0; - sprite->data[2] = 0; - sprite->data[6] = gBattleAnimArgs[2]; - sprite->data[7] = gBattleAnimArgs[3]; - - sprite->oam.tileNum += gBattleAnimArgs[4] * 16; - sprite->callback = AnimEruptionFallingRock_Step; -} - -static void AnimEruptionFallingRock_Step(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - if (sprite->data[6] != 0) - { - sprite->data[6]--; - return; - } - - sprite->data[0]++; - // fall through - case 1: - sprite->pos1.y += 8; - if (sprite->pos1.y >= sprite->data[7]) - { - sprite->pos1.y = sprite->data[7]; - sprite->data[0]++; - } - break; - case 2: - if (++sprite->data[1] > 1) - { - sprite->data[1] = 0; - if ((++sprite->data[2] & 1) != 0) - { - sprite->pos2.y = -3; - } - else - { - sprite->pos2.y = 3; - } - } - - if (++sprite->data[3] > 16) - { - DestroyAnimSprite(sprite); - } - break; - } -} - -static void AnimWillOWispOrb(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - InitSpritePosToAnimAttacker(sprite, 0); - StartSpriteAnim(sprite, gBattleAnimArgs[2]); - sprite->data[7] = gBattleAnimArgs[2]; - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - sprite->data[4] = 4; - } - else - { - sprite->data[4] = -4; - } - - sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); - sprite->data[0]++; - break; - case 1: - sprite->data[1] += 192; - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - sprite->pos2.y = -(sprite->data[1] >> 8); - } - else - { - sprite->pos2.y = sprite->data[1] >> 8; - } - - sprite->pos2.x = Sin(sprite->data[2], sprite->data[4]); - sprite->data[2] = (sprite->data[2] + 4) & 0xFF; - - if (++sprite->data[3] == 1) - { - sprite->data[3] = 0; - sprite->data[0]++; - } - break; - case 2: - sprite->pos2.x = Sin(sprite->data[2], sprite->data[4]); - sprite->data[2] = (sprite->data[2] + 4) & 0xFF; - - if (++sprite->data[3] == 31) - { - sprite->pos1.x += sprite->pos2.x; - sprite->pos1.y += sprite->pos2.y; - sprite->pos2.y = 0; - sprite->pos2.x = 0; - - sprite->data[0] = 256; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - - sub_80A6FD4(sprite); - sprite->callback = AnimWillOWispOrb_Step; - } - break; - } -} - -static void AnimWillOWispOrb_Step(struct Sprite *sprite) -{ - s16 initialData5; - s16 newData5; - - if (!AnimTranslateLinear(sprite)) - { - sprite->pos2.x += Sin(sprite->data[5], 16); - initialData5 = sprite->data[5]; - sprite->data[5] = (sprite->data[5] + 4) & 0xFF; - newData5 = sprite->data[5]; - - if ((initialData5 == 0 || initialData5 > 196) && newData5 > 0 && sprite->data[7] == 0) - { - PlaySE12WithPanning(SE_W172, gAnimCustomPanning); - } - } - else - { - DestroyAnimSprite(sprite); - } -} - -static void AnimWillOWispFire(struct Sprite *sprite) -{ - if (!sprite->data[0]) - { - sprite->data[1] = gBattleAnimArgs[0]; - sprite->data[0] += 1; - } - - sprite->data[3] += 0xC0 * 2; - sprite->data[4] += 0xA0; - - sprite->pos2.x = Sin(sprite->data[1], sprite->data[3] >> 8); - sprite->pos2.y = Cos(sprite->data[1], sprite->data[4] >> 8); - - sprite->data[1] = (sprite->data[1] + 7) & 0xFF; - - if (!IsContest()) - { - if (sprite->data[1] < 64 || sprite->data[1] > 195) - sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); - else - sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget) + 1; - } - else - { - if (sprite->data[1] < 64 || sprite->data[1] > 195) - sprite->subpriority = 0x1D; - else - sprite->subpriority = 0x1F; - } - - if (++sprite->data[2] > 0x14) - sprite->invisible ^= 1; - - if (sprite->data[2] == 0x1E) - DestroyAnimSprite(sprite); -} - -void AnimTask_MoveHeatWaveTargets(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - task->data[12] = !GetBattlerSide(gBattleAnimAttacker) ? 1 : -1; - task->data[13] = IsBattlerSpriteVisible(gBattleAnimTarget ^ 2) + 1; - task->data[14] = GetAnimBattlerSpriteId(ANIM_TARGET); - task->data[15] = GetAnimBattlerSpriteId(ANIM_DEF_PARTNER); - - task->func = AnimTask_MoveHeatWaveTargets_Step; -} - -static void AnimTask_MoveHeatWaveTargets_Step(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[10] += task->data[12] * 2; - if (++task->data[1] >= 2) - { - task->data[1] = 0; - task->data[2]++; - if (task->data[2] & 1) - task->data[11] = 2; - else - task->data[11] = -2; - } - - for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) - { - gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; - } - - if (++task->data[9] == 16) - { - task->data[9] = 0; - task->data[0]++; - } - break; - case 1: - if (++task->data[1] >= 5) - { - task->data[1] = 0; - task->data[2]++; - - if (task->data[2] & 1) - task->data[11] = 2; - else - task->data[11] = -2; - } - - for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) - { - gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; - } - - if (++task->data[9] == 96) - { - task->data[9] = 0; - task->data[0]++; - } - break; - case 2: - task->data[10] -= task->data[12] * 2; - - if (++task->data[1] >= 2) - { - task->data[1] = 0; - task->data[2]++; - - if (task->data[2] & 1) - task->data[11] = 2; - else - task->data[11] = -2; - } - - for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) - { - gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; - } - - if (++task->data[9] == 16) - { - task->data[0]++; - } - break; - case 3: - for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) - { - gSprites[task->data[task->data[3] + 14]].pos2.x = 0; - } - - DestroyAnimVisualTask(taskId); - break; - } -} - -// Used to add a color mask to the battle interface / HUD in Heat Wave. -// arg 0: opacity -// arg 1: color code -void AnimTask_BlendBackground(u8 taskId) -{ - struct BattleAnimBgData animBg; - sub_80A6B30(&animBg); - BlendPalette(animBg.paletteId * 16, 16, gBattleAnimArgs[0], gBattleAnimArgs[1]); // u16 palOffset, u16 numEntries, u8 coeff, u16 blendColor - DestroyAnimVisualTask(taskId); -} - -#define tShakeNum data[0] -#define tMaxShakes data[1] -#define tShakeOffset data[2] // Never read, gBattleAnimArgs[1] is used directly instead -#define tVertical data[3] -#define tPatternId data[4] - -// Shakes target horizontally or vertically tMaxShakes times, following a set pattern of alternations -void AnimTask_ShakeTargetInPattern(u8 taskId) -{ - s8 dir; - u8 spriteId; - - if (gTasks[taskId].tShakeNum == 0) - { - gTasks[taskId].tMaxShakes = gBattleAnimArgs[0]; - gTasks[taskId].tShakeOffset = gBattleAnimArgs[1]; - gTasks[taskId].tVertical = gBattleAnimArgs[2]; - gTasks[taskId].tPatternId = gBattleAnimArgs[3]; - } - gTasks[taskId].tShakeNum++; - - spriteId = gBattlerSpriteIds[gBattleAnimTarget]; - - if (gTasks[taskId].tPatternId == 0) - dir = sShakeDirsPattern0[gTasks[taskId].tShakeNum % 10]; - else - dir = sShakeDirsPattern1[gTasks[taskId].tShakeNum % 10]; - - if (gTasks[taskId].tVertical == TRUE) - gSprites[spriteId].pos2.y = gBattleAnimArgs[1] * dir < 0 ? -(gBattleAnimArgs[1] * dir) : gBattleAnimArgs[1] * dir; - else - gSprites[spriteId].pos2.x = gBattleAnimArgs[1] * dir; - - if (gTasks[taskId].tShakeNum == gTasks[taskId].tMaxShakes) - { - gSprites[spriteId].pos2.x = 0; - gSprites[spriteId].pos2.y = 0; - DestroyAnimVisualTask(taskId); - } -} diff --git a/src/flying.c b/src/flying.c deleted file mode 100644 index e7babf9d7..000000000 --- a/src/flying.c +++ /dev/null @@ -1,1248 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "palette.h" -#include "trig.h" -#include "constants/battle_anim.h" -#include "constants/rgb.h" -#include "random.h" - -extern const struct SpriteTemplate gFlashingHitSplatSpriteTemplate; - -static void AnimEllipticalGust(struct Sprite *); -static void AnimEllipticalGust_Step(struct Sprite *); -static void AnimGustToTarget(struct Sprite *); -static void AnimGustToTarget_Step(struct Sprite *); -static void AnimAirWaveCrescent(struct Sprite *); -static void AnimFlyBallUp(struct Sprite *); -static void AnimFlyBallUp_Step(struct Sprite *); -static void AnimFlyBallAttack(struct Sprite *); -static void AnimFlyBallAttack_Step(struct Sprite *); -static void AnimFallingFeather(struct Sprite *); -static void sub_810E520(struct Sprite *); -static void sub_810EB40(struct Sprite *); -static void sub_810EA4C(struct Sprite *); -static void AnimWhirlwindLine(struct Sprite *); -static void AnimBounceBallShrink(struct Sprite *); -static void AnimBounceBallLand(struct Sprite *); -static void AnimDiveBall(struct Sprite *); -static void AnimDiveBall_Step1(struct Sprite *); -static void AnimDiveBall_Step2(struct Sprite *); -static void AnimDiveWaterSplash(struct Sprite *); -static void AnimSprayWaterDroplet(struct Sprite *); -static void AnimSprayWaterDroplet_Step(struct Sprite *); -static void sub_810F004(struct Sprite *); -static void sub_810F018(struct Sprite *); -static void AnimSkyAttackBird(struct Sprite *); -static void AnimSkyAttackBird_Step(struct Sprite *); -static void AnimTask_AnimateGustTornadoPalette_Step(u8); - - -const struct SpriteTemplate gEllipticalGustSpriteTemplate = -{ - .tileTag = ANIM_TAG_GUST, - .paletteTag = ANIM_TAG_GUST, - .oam = &gOamData_AffineOff_ObjNormal_32x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimEllipticalGust, -}; - -static const union AffineAnimCmd sAffineAnim_GustToTarget[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0xA, 0x0, 0, 24), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_GustToTarget[] = -{ - sAffineAnim_GustToTarget, -}; - -const struct SpriteTemplate gGustToTargetSpriteTemplate = -{ - .tileTag = ANIM_TAG_GUST, - .paletteTag = ANIM_TAG_GUST, - .oam = &gOamData_AffineNormal_ObjNormal_32x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_GustToTarget, - .callback = AnimGustToTarget, -}; - -static const union AnimCmd sAffineAnim_AirWaveCrescent[] = -{ - ANIMCMD_FRAME(0, 3), - ANIMCMD_FRAME(0, 3, .hFlip = TRUE), - ANIMCMD_FRAME(0, 3, .vFlip = TRUE), - ANIMCMD_FRAME(0, 3, .vFlip = TRUE, .hFlip = TRUE), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAffineAnims_AirWaveCrescent[] = -{ - sAffineAnim_AirWaveCrescent, -}; - -const struct SpriteTemplate gAirWaveCrescentSpriteTemplate = -{ - .tileTag = ANIM_TAG_AIR_WAVE_2, - .paletteTag = ANIM_TAG_AIR_WAVE_2, - .oam = &gOamData_AffineOff_ObjNormal_32x16, - .anims = sAffineAnims_AirWaveCrescent, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimAirWaveCrescent, -}; - -static const union AffineAnimCmd sAffineAnim_FlyBallUp[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), - AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), - AFFINEANIMCMD_FRAME(0xFFF0, 0x20, 0, 10), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_FlyBallUp[] = -{ - sAffineAnim_FlyBallUp, -}; - -static const union AffineAnimCmd sAffineAnim_FlyBallAttack_0[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 50, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_FlyBallAttack_1[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, -40, 1), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_FlyBallAttack[] = -{ - sAffineAnim_FlyBallAttack_0, - sAffineAnim_FlyBallAttack_1, -}; - -const struct SpriteTemplate gFlyBallUpSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROUND_SHADOW, - .paletteTag = ANIM_TAG_ROUND_SHADOW, - .oam = &gOamData_AffineDouble_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_FlyBallUp, - .callback = AnimFlyBallUp, -}; - -const struct SpriteTemplate gFlyBallAttackSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROUND_SHADOW, - .paletteTag = ANIM_TAG_ROUND_SHADOW, - .oam = &gOamData_AffineNormal_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_FlyBallAttack, - .callback = AnimFlyBallAttack, -}; - -static const union AnimCmd sAnim_FallingFeather_0[] = -{ - ANIMCMD_FRAME(0, 0), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_FallingFeather_1[] = -{ - ANIMCMD_FRAME(16, 0, .hFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_FallingFeather[] = -{ - sAnim_FallingFeather_0, - sAnim_FallingFeather_1, -}; - -const struct SpriteTemplate gFallingFeatherSpriteTemplate = -{ - .tileTag = ANIM_TAG_WHITE_FEATHER, - .paletteTag = ANIM_TAG_WHITE_FEATHER, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = sAnims_FallingFeather, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFallingFeather, -}; - -const struct SpriteTemplate gUnknown_085963A0 = -{ - .tileTag = ANIM_TAG_SMALL_BUBBLES, - .paletteTag = ANIM_TAG_SMALL_BUBBLES, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_810EA4C, -}; - -static const union AnimCmd sAnim_WhirlwindLines[] = -{ - ANIMCMD_FRAME(0, 1), - ANIMCMD_FRAME(8, 1), - ANIMCMD_FRAME(16, 1), - ANIMCMD_FRAME(8, 1, .hFlip = TRUE), - ANIMCMD_FRAME(0, 1, .hFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_WhirlwindLines[] = -{ - sAnim_WhirlwindLines, -}; - -const struct SpriteTemplate gWhirlwindLineSpriteTemplate = -{ - .tileTag = ANIM_TAG_WHIRLWIND_LINES, - .paletteTag = ANIM_TAG_WHIRLWIND_LINES, - .oam = &gOamData_AffineOff_ObjNormal_32x16, - .anims = sAnims_WhirlwindLines, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimWhirlwindLine, -}; - -static const union AffineAnimCmd sAffineAnim_BounceBallShrink[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), - AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), - AFFINEANIMCMD_FRAME(0xFFEC, 0x0, 0, 7), - AFFINEANIMCMD_FRAME(0xFFEC, 0xFFEC, 0, 5), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_BounceBallShrink[] = -{ - sAffineAnim_BounceBallShrink, -}; - -const struct SpriteTemplate gBounceBallShrinkSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROUND_SHADOW, - .paletteTag = ANIM_TAG_ROUND_SHADOW, - .oam = &gOamData_AffineDouble_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_BounceBallShrink, - .callback = AnimBounceBallShrink, -}; - -static const union AffineAnimCmd sAffineAnim_BounceBallLand[] = -{ - AFFINEANIMCMD_FRAME(0xA0, 0x100, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_BounceBallLand[] = -{ - sAffineAnim_BounceBallLand, -}; - -const struct SpriteTemplate gBounceBallLandSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROUND_SHADOW, - .paletteTag = ANIM_TAG_ROUND_SHADOW, - .oam = &gOamData_AffineDouble_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_BounceBallLand, - .callback = AnimBounceBallLand, -}; - -static const union AffineAnimCmd sAffineAnim_DiveBall[] = -{ - AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), - AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), - AFFINEANIMCMD_FRAME(0xFFF0, 0x20, 0, 10), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_DiveBall[] = -{ - sAffineAnim_DiveBall, -}; - -const struct SpriteTemplate gDiveBallSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROUND_SHADOW, - .paletteTag = ANIM_TAG_ROUND_SHADOW, - .oam = &gOamData_AffineDouble_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_DiveBall, - .callback = AnimDiveBall, -}; - -static const union AffineAnimCmd gUnknown_085964A8[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x0, 0, 0), - AFFINEANIMCMD_FRAME(0x0, 0x20, 0, 12), - AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 11), - AFFINEANIMCMD_END, -}; - -// Unused -static const union AffineAnimCmd *const gUnknown_085964C8[] = -{ - gUnknown_085964A8, -}; - -const struct SpriteTemplate gDiveWaterSplashSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPLASH, - .paletteTag = ANIM_TAG_SPLASH, - .oam = &gOamData_AffineDouble_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDiveWaterSplash, -}; - -const struct SpriteTemplate gSprayWaterDropletSpriteTemplate = -{ - .tileTag = ANIM_TAG_SWEAT_BEAD, - .paletteTag = ANIM_TAG_SWEAT_BEAD, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSprayWaterDroplet, -}; - -const struct SpriteTemplate gUnknown_085964FC = -{ - .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .oam = &gOamData_AffineOff_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_810F004, -}; - -const struct SpriteTemplate gSkyAttackBirdSpriteTemplate = -{ - .tileTag = ANIM_TAG_BIRD, - .paletteTag = ANIM_TAG_BIRD, - .oam = &gOamData_AffineDouble_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSkyAttackBird, -}; - - -static void AnimEllipticalGust(struct Sprite *sprite) -{ - InitSpritePosToAnimTarget(sprite, FALSE); - sprite->pos1.y += 20; - sprite->data[1] = 191; - sprite->callback = AnimEllipticalGust_Step; - sprite->callback(sprite); -} - -static void AnimEllipticalGust_Step(struct Sprite *sprite) -{ - sprite->pos2.x = Sin(sprite->data[1], 32); - sprite->pos2.y = Cos(sprite->data[1], 8); - sprite->data[1] += 5; - sprite->data[1] &= 0xFF; - if (++sprite->data[0] == 71) - DestroyAnimSprite(sprite); -} - -// Animates the palette on the gust tornado to make it look like its spinning -void AnimTask_AnimateGustTornadoPalette(u8 taskId) -{ - gTasks[taskId].data[0] = gBattleAnimArgs[1]; - gTasks[taskId].data[1] = gBattleAnimArgs[0]; - gTasks[taskId].data[2] = IndexOfSpritePaletteTag(ANIM_TAG_GUST); - gTasks[taskId].func = AnimTask_AnimateGustTornadoPalette_Step; -} - -static void AnimTask_AnimateGustTornadoPalette_Step(u8 taskId) -{ - u8 data2; - u16 temp; - int i, base; - - if (gTasks[taskId].data[10]++ == gTasks[taskId].data[1]) - { - gTasks[taskId].data[10] = 0; - data2 = gTasks[taskId].data[2]; - temp = gPlttBufferFaded[16 * data2 + 0x108]; - i = 7; - base = data2 * 16; - - do - { - gPlttBufferFaded[base + 0x101 + i] = gPlttBufferFaded[base + 0x100 + i]; - i--; - } while (i > 0); - - gPlttBufferFaded[base + 0x101] = temp; - } - - if (--gTasks[taskId].data[0] == 0) - DestroyAnimVisualTask(taskId); -} - -static void AnimGustToTarget(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, TRUE); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; - InitAnimLinearTranslation(sprite); - sprite->callback = RunStoredCallbackWhenAffineAnimEnds; - StoreSpriteCallbackInData6(sprite, AnimGustToTarget_Step); -} - -static void AnimGustToTarget_Step(struct Sprite *sprite) -{ - if (AnimTranslateLinear(sprite)) - DestroyAnimSprite(sprite); -} - -static void AnimAirWaveCrescent(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - } - - if (IsContest()) - { - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - } - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[0] = gBattleAnimArgs[4]; - - if (gBattleAnimArgs[6] == 0) - { - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - } - else - { - SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); - } - - sprite->data[2] = sprite->data[2] + gBattleAnimArgs[2]; - sprite->data[4] = sprite->data[4] + gBattleAnimArgs[3]; - sprite->callback = StartAnimLinearTranslation; - - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - SeekSpriteAnim(sprite, gBattleAnimArgs[5]); -} - -static void AnimFlyBallUp(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, TRUE); - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[1] = gBattleAnimArgs[3]; - sprite->callback = AnimFlyBallUp_Step; - gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; -} - -static void AnimFlyBallUp_Step(struct Sprite *sprite) -{ - if (sprite->data[0] > 0) - { - sprite->data[0]--; - } - else - { - sprite->data[2] += sprite->data[1]; - sprite->pos2.y -= (sprite->data[2] >> 8); - } - - if (sprite->pos1.y + sprite->pos2.y < -32) - DestroyAnimSprite(sprite); -} - -static void AnimFlyBallAttack(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - sprite->pos1.x = 272; - sprite->pos1.y = -32; - StartSpriteAffineAnim(sprite, 1); - } - else - { - sprite->pos1.x = -32; - sprite->pos1.y = -32; - } - - sprite->data[0] = gBattleAnimArgs[0]; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - - InitAnimLinearTranslation(sprite); - sprite->callback = AnimFlyBallAttack_Step; -} - -static void AnimFlyBallAttack_Step(struct Sprite *sprite) -{ - sprite->data[0] = 1; - AnimTranslateLinear(sprite); - if (((u16)sprite->data[3] >> 8) > 200) - { - sprite->pos1.x += sprite->pos2.x; - sprite->pos2.x = 0; - sprite->data[3] &= 0xFF; - } - - if (sprite->pos1.x + sprite->pos2.x < -32 - || sprite->pos1.x + sprite->pos2.x > 272 - || sprite->pos1.y + sprite->pos2.y > 160) - { - gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = FALSE; - DestroyAnimSprite(sprite); - } -} - -void DestroyAnimSpriteAfterTimer(struct Sprite *sprite) -{ - if (sprite->data[0]-- <= 0) - { - if (sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK) - { - FreeOamMatrix(sprite->oam.matrixNum); - sprite->oam.affineMode = ST_OAM_AFFINE_OFF; - } - - DestroySprite(sprite); - gAnimVisualTaskCount--; - } -} - -struct FeatherDanceData -{ - u16 unk0_0a:1; - u16 unk0_0b:1; - u16 unk0_0c:1; - u16 unk0_0d:1; - u16 unk0_1:4; - u16 unk1:8; - u16 unk2; - s16 unk4; - u16 unk6; - u16 unk8; - u16 unkA; - u8 unkC[2]; - u16 unkE_0:1; - u16 unkE_1:15; -}; - -static void AnimFallingFeather(struct Sprite *sprite) -{ - u8 battler, matrixNum, sinIndex; - s16 spriteCoord, sinVal; - - struct FeatherDanceData *data = (struct FeatherDanceData *)sprite->data; - - if (gBattleAnimArgs[ARG_RET_ID] & 0x100) - battler = gBattleAnimAttacker; - else - battler = gBattleAnimTarget; - - if (GetBattlerSide(battler) == B_SIDE_PLAYER) - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - - sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_ATTR_HEIGHT) + gBattleAnimArgs[0]; - spriteCoord = GetBattlerSpriteCoord(battler, BATTLER_COORD_ATTR_WIDTH); - sprite->pos1.y = spriteCoord + gBattleAnimArgs[1]; - - data->unk8 = sprite->pos1.y << 8; - data->unkE_1 = spriteCoord + gBattleAnimArgs[6]; - data->unk0_0c = 1; - data->unk2 = gBattleAnimArgs[2] & 0xFF; - data->unkA = (gBattleAnimArgs[2] >> 8) & 0xFF; - data->unk4 = gBattleAnimArgs[3]; - data->unk6 = gBattleAnimArgs[4]; - *(u16*)(data->unkC) = gBattleAnimArgs[5]; - - if (data->unk2 >= 64 && data->unk2 <= 191) - { - if (!IsContest()) - sprite->oam.priority = GetBattlerSpriteBGPriority(battler) + 1; - else - sprite->oam.priority = GetBattlerSpriteBGPriority(battler); - - data->unkE_0 = 0; - - if (!(data->unk4 & 0x8000)) - { - sprite->hFlip ^= 1; - sprite->animNum = sprite->hFlip; - - sprite->animBeginning = 1; - sprite->animEnded = 0; - } - } - else - { - sprite->oam.priority = GetBattlerSpriteBGPriority(battler); - data->unkE_0 = 1; - - if (data->unk4 & 0x8000) - { - sprite->hFlip ^= 1; - sprite->animNum = sprite->hFlip; - - sprite->animBeginning = 1; - sprite->animEnded = 0; - } - } - - data->unk0_1 = data->unk2 >> 6; - sprite->pos2.x = (gSineTable[data->unk2] * data->unkC[0]) >> 8; - matrixNum = sprite->oam.matrixNum; - - sinIndex = (-sprite->pos2.x >> 1) + data->unkA; - sinVal = gSineTable[sinIndex]; - - gOamMatrices[matrixNum].a = gOamMatrices[matrixNum].d = gSineTable[sinIndex + 64]; - // The comparison below is completely pointless. 'sprite' is sure to be a valid pointer and - // both the 'if' and 'else' parts are exactly the same. - // The only reason for this is making sure the compiler generates the exact ASM. - if (sprite) - { - gOamMatrices[matrixNum].b = sinVal; - gOamMatrices[matrixNum].c = -sinVal; - } - else - { - gOamMatrices[matrixNum].b = sinVal; - gOamMatrices[matrixNum].c = -sinVal; - } - - sprite->callback = sub_810E520; -} - -static void sub_810E520(struct Sprite *sprite) -{ - u8 matrixNum, sinIndex; - s16 sinVal = 0; - struct FeatherDanceData *data = (struct FeatherDanceData *)sprite->data; - if (data->unk0_0a) - { - if (data->unk1-- % 256 == 0) - { - data->unk0_0a = 0; - data->unk1 = 0; - } - } - else - { - switch (data->unk2 / 64) - { - case 0: - if (data->unk0_1 << 24 >> 24 == 1) // the shifts have to be here - { - data->unk0_0d = 1; - data->unk0_0a = 1; - data->unk1 = 0; - } - else if (data->unk0_1 << 24 >> 24 == 3) - { - data->unk0_0b ^= 1; - data->unk0_0a = 1; - data->unk1 = 0; - } - else if (data->unk0_0d) - { - sprite->hFlip ^= 1; - sprite->animNum = sprite->hFlip; - sprite->animBeginning = TRUE; - sprite->animEnded = FALSE; - if (data->unk0_0c) - { - if (!IsContest()) - { - if (!data->unkE_0) - { - sprite->oam.priority--; - data->unkE_0 ^= 1; - } - else - { - sprite->oam.priority++; - data->unkE_0 ^= 1; - } - } - else - { - if (!data->unkE_0) - { - sprite->subpriority -= 12; - data->unkE_0 ^= 1; - } - else - { - sprite->subpriority += 12; - data->unkE_0 ^= 1; - } - } - } - data->unk0_0d = 0; - data->unk2; - } - data->unk0_1 = 0; - break; - case 1: - if (data->unk0_1 << 24 >> 24 == 0) - { - data->unk0_0d = 1; - data->unk0_0a = 1; - data->unk1 = 0; - } - else if (data->unk0_1 << 24 >> 24 == 2) - { - data->unk0_0a = 1; - data->unk1 = 0; - } - else if (data->unk0_0d) - { - sprite->hFlip ^= 1; - sprite->animNum = sprite->hFlip; - sprite->animBeginning = TRUE; - sprite->animEnded = FALSE; - if (data->unk0_0c) - { - if (!IsContest()) - { - if (!data->unkE_0) - { - sprite->oam.priority--; - data->unkE_0 ^= 1; - } - else - { - sprite->oam.priority++; - data->unkE_0 ^= 1; - } - } - else - { - if (!data->unkE_0) - { - sprite->subpriority -= 12; - data->unkE_0 ^= 1; - } - else - { - sprite->subpriority += 12; - data->unkE_0 ^= 1; - } - } - } - data->unk0_0d = 0; - } - data->unk0_1 = 1; - break; - case 2: - if (data->unk0_1 << 24 >> 24 == 3) - { - data->unk0_0d = 1; - data->unk0_0a = 1; - data->unk1 = 0; - } - else if (data->unk0_1 << 24 >> 24 == 1) - { - data->unk0_0a = 1; - data->unk1 = 0; - } - else if (data->unk0_0d) - { - sprite->hFlip ^= 1; - sprite->animNum = sprite->hFlip; - sprite->animBeginning = TRUE; - sprite->animEnded = FALSE; - if (data->unk0_0c) - { - if (!IsContest()) - { - if (!data->unkE_0) - { - sprite->oam.priority--; - data->unkE_0 ^= 1; - } - else - { - sprite->oam.priority++; - data->unkE_0 ^= 1; - } - } - else - { - if (!data->unkE_0) - { - sprite->subpriority -= 12; - data->unkE_0 ^= 1; - } - else - { - sprite->subpriority += 12; - data->unkE_0 ^= 1; - } - } - } - data->unk0_0d = 0; - } - data->unk0_1 = 2; - break; - case 3: - if (data->unk0_1 << 24 >> 24 == 2) - { - data->unk0_0d = 1; - } - else if (data->unk0_1 << 24 >> 24 == 0) - { - data->unk0_0b ^= 1; - data->unk0_0a = 1; - data->unk1 = 0; - } - else if (data->unk0_0d) - { - sprite->hFlip ^= 1; - sprite->animNum = sprite->hFlip; - sprite->animBeginning = TRUE; - sprite->animEnded = FALSE; - if (data->unk0_0c) - { - if (!IsContest()) - { - if (!data->unkE_0) - { - sprite->oam.priority--; - data->unkE_0 ^= 1; - } - else - { - sprite->oam.priority++; - data->unkE_0 ^= 1; - } - } - else - { - if (!data->unkE_0) - { - sprite->subpriority -= 12; - data->unkE_0 ^= 1; - } - else - { - sprite->subpriority += 12; - data->unkE_0 ^= 1; - } - } - } - data->unk0_0d = 0; - } - data->unk0_1 = 3; - break; - } - #ifndef NONMATCHING - asm("":::"r8"); - #endif - sprite->pos2.x = (data->unkC[data->unk0_0b] * gSineTable[data->unk2]) >> 8; - matrixNum = sprite->oam.matrixNum; - - sinIndex = (-sprite->pos2.x >> 1) + data->unkA; - sinVal = gSineTable[sinIndex]; - - gOamMatrices[matrixNum].a = gOamMatrices[matrixNum].d = gSineTable[sinIndex + 64]; - gOamMatrices[matrixNum].b = sinVal; - gOamMatrices[matrixNum].c = -sinVal; - - data->unk8 += data->unk6; - sprite->pos1.y = data->unk8 >> 8; - if (data->unk4 & 0x8000) - data->unk2 = (data->unk2 - (data->unk4 & 0x7FFF)) & 0xFF; - else - data->unk2 = (data->unk2 + (data->unk4 & 0x7FFF)) & 0xFF; - - if (sprite->pos1.y + sprite->pos2.y >= data->unkE_1) - { - sprite->data[0] = 0; - sprite->callback = DestroyAnimSpriteAfterTimer; - } - } -} - -static void sub_810EA4C(struct Sprite *sprite) -{ - sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); - sprite->callback = TranslateAnimSpriteToTargetMonLocation; -} - -static void AnimWhirlwindLine(struct Sprite * sprite) -{ - u16 arg; - u8 mult; - - if (gBattleAnimArgs[2] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, 0); - else - InitSpritePosToAnimTarget(sprite, FALSE); - - if ((gBattleAnimArgs[2] == ANIM_ATTACKER && !GetBattlerSide(gBattleAnimAttacker)) - || (gBattleAnimArgs[2] == ANIM_TARGET && !GetBattlerSide(gBattleAnimTarget))) - { - sprite->pos1.x += 8; - } - - SeekSpriteAnim(sprite, gBattleAnimArgs[4]); - sprite->pos1.x -= 32; - sprite->data[1] = 0x0ccc; - - arg = gBattleAnimArgs[4]; - mult = 12; - sprite->pos2.x += mult * arg; - sprite->data[0] = arg; - sprite->data[7] = gBattleAnimArgs[3]; - sprite->callback = sub_810EB40; -} - -static void sub_810EB40(struct Sprite *sprite) -{ - sprite->pos2.x += sprite->data[1] >> 8; - - if (++sprite->data[0] == 6) - { - sprite->data[0] = 0; - sprite->pos2.x = 0; - StartSpriteAnim(sprite, 0); - } - - if (--sprite->data[7] == -1) - DestroyAnimSprite(sprite); -} - -void AnimTask_DrillPeckHitSplats(u8 task) -{ - if (!(gTasks[task].data[0] % 32)) - { - gAnimVisualTaskCount++; - - gBattleAnimArgs[0] = Sin(gTasks[task].data[0], -13); - gBattleAnimArgs[1] = Cos(gTasks[task].data[0], -13); - gBattleAnimArgs[2] = 1; - gBattleAnimArgs[3] = 3; - - CreateSpriteAndAnimate(&gFlashingHitSplatSpriteTemplate, - GetBattlerSpriteCoord(gBattleAnimTarget, 2), - GetBattlerSpriteCoord(gBattleAnimTarget, 3), - 3); - } - - gTasks[task].data[0] += 8; - - if (gTasks[task].data[0] > 255) - DestroyAnimVisualTask(task); -} - -static void AnimBounceBallShrink(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - InitSpritePosToAnimAttacker(sprite, 1); - gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; - ++sprite->data[0]; - break; - case 1: - if (sprite->affineAnimEnded) - DestroyAnimSprite(sprite); - break; - } -} - -static void AnimBounceBallLand(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); - sprite->pos2.y = -sprite->pos1.y - 32; - sprite->data[0]++; - break; - case 1: - sprite->pos2.y += 10; - if (sprite->pos2.y >= 0) - ++sprite->data[0]; - break; - case 2: - sprite->pos2.y -= 10; - if (sprite->pos1.y + sprite->pos2.y < -32) - { - gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = FALSE; - DestroyAnimSprite(sprite); - } - break; - } -} - -static void AnimDiveBall(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, 1); - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[1] = gBattleAnimArgs[3]; - sprite->callback = AnimDiveBall_Step1; - gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; -} - -void AnimDiveBall_Step1(struct Sprite *sprite) -{ - if (sprite->data[0] > 0) - { - sprite->data[0]--; - } - else if (sprite->pos1.y + sprite->pos2.y > -32) - { - sprite->data[2] += sprite->data[1]; - sprite->pos2.y -= (sprite->data[2] >> 8); - } - else - { - sprite->invisible = TRUE; - if (sprite->data[3]++ > 20) - sprite->callback = AnimDiveBall_Step2; - } -} - -static void AnimDiveBall_Step2(struct Sprite *sprite) -{ - sprite->pos2.y += sprite->data[2] >> 8; - - if (sprite->pos1.y + sprite->pos2.y > -32) - sprite->invisible = FALSE; - - if (sprite->pos2.y > 0) - DestroyAnimSprite(sprite); -} - -static void AnimDiveWaterSplash(struct Sprite *sprite) -{ - u32 matrixNum; - int t1, t2; - - switch (sprite->data[0]) - { - case 0: - if (!gBattleAnimArgs[0]) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1); - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); - } - - sprite->data[1] = 512; - - TrySetSpriteRotScale(sprite, 0, 256, sprite->data[1], 0); - sprite->data[0]++; - break; - case 1: - if (sprite->data[2] <= 11) - sprite->data[1] -= 40; - else - sprite->data[1] += 40; - - sprite->data[2]++; - - TrySetSpriteRotScale(sprite, 0, 256, sprite->data[1], 0); - - matrixNum = sprite->oam.matrixNum; - - t1 = 15616; - t2 = t1 / gOamMatrices[matrixNum].d + 1; - - if (t2 > 128) - t2 = 128; - - t2 = (64 - t2) / 2; - sprite->pos2.y = t2; - - if (sprite->data[2] == 24) - { - sub_80A749C(sprite); - DestroyAnimSprite(sprite); - } - break; - } -} - -// Launches a water droplet away from the specified battler. Used by Astonish and Dive -static void AnimSprayWaterDroplet(struct Sprite *sprite) -{ - int v1 = 0x1ff & Random2(); - int v2 = 0x7f & Random2(); - - if (v1 % 2) - sprite->data[0] = 736 + v1; - else - sprite->data[0] = 736 - v1; - - if (v2 % 2) - sprite->data[1] = 896 + v2; - else - sprite->data[1] = 896 - v2; - - sprite->data[2] = gBattleAnimArgs[0]; - - if (sprite->data[2]) - sprite->oam.matrixNum = ST_OAM_HFLIP; - - if (gBattleAnimArgs[1] == 0) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 32; - } - else - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 32; - } - - sprite->callback = AnimSprayWaterDroplet_Step; -} - -static void AnimSprayWaterDroplet_Step(struct Sprite *sprite) -{ - if (sprite->data[2] == 0) - { - sprite->pos2.x += sprite->data[0] >> 8; - sprite->pos2.y -= sprite->data[1] >> 8; - } - else - { - sprite->pos2.x -= sprite->data[0] >> 8; - sprite->pos2.y -= sprite->data[1] >> 8; - } - - sprite->data[0] = sprite->data[0]; - sprite->data[1] -= 32; - - if (sprite->data[0] < 0) - sprite->data[0] = 0; - - if (++sprite->data[3] == 31) - DestroyAnimSprite(sprite); -} - -static void sub_810F004(struct Sprite *sprite) -{ - sprite->data[6] = 0; - sprite->data[7] = 64; - sprite->callback = sub_810F018; -} - -static void sub_810F018(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - if (++sprite->data[1] > 8) - { - sprite->data[1] = 0; - sprite->invisible ^= 1; - if (++sprite->data[2] > 5 && sprite->invisible) - sprite->data[0]++; - } - break; - case 1: - DestroyAnimSprite(sprite); - break; - } -} - -static void AnimSkyAttackBird(struct Sprite *sprite) -{ - u16 rotation; - s16 posx = sprite->pos1.x; - s16 posy = sprite->pos1.y; - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); - - sprite->data[4] = sprite->pos1.x << 4; - sprite->data[5] = sprite->pos1.y << 4; - - sprite->data[6] = ((posx - sprite->pos1.x) << 4) / 12; - sprite->data[7] = ((posy - sprite->pos1.y) << 4) / 12; - - rotation = ArcTan2Neg(posx - sprite->pos1.x, posy - sprite->pos1.y); - rotation += 49152; - - TrySetSpriteRotScale(sprite, 1, 0x100, 0x100, rotation); - - sprite->callback = AnimSkyAttackBird_Step; -} - -void AnimSkyAttackBird_Step(struct Sprite *sprite) -{ - sprite->data[4] += sprite->data[6]; - sprite->data[5] += sprite->data[7]; - - sprite->pos1.x = sprite->data[4] >> 4; - sprite->pos1.y = sprite->data[5] >> 4; - - if (sprite->pos1.x > 285 || sprite->pos1.x < -45 - || sprite->pos1.y > 157 || sprite->pos1.y < -45) - DestroySpriteAndMatrix(sprite); -} - -void unref_sub_810F184(u8 taskId) -{ - if (gBattleAnimArgs[0] == 0) - { - u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - gSprites[spriteId].invisible = TRUE; - } - else - { - u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - gSprites[spriteId].invisible = FALSE; - } - DestroyAnimVisualTask(taskId); -} diff --git a/src/ghost.c b/src/ghost.c deleted file mode 100644 index b8de6b0e1..000000000 --- a/src/ghost.c +++ /dev/null @@ -1,1341 +0,0 @@ -#include "global.h" -#include "battle.h" -#include "battle_anim.h" -#include "gpu_regs.h" -#include "palette.h" -#include "constants/rgb.h" -#include "scanline_effect.h" -#include "constants/songs.h" -#include "sound.h" -#include "trig.h" -#include "util.h" - -static void AnimConfuseRayBallBounce(struct Sprite *); -static void AnimConfuseRayBallBounce_Step1(struct Sprite *); -static void AnimConfuseRayBallBounce_Step2(struct Sprite *); -static void sub_8111764(struct Sprite *); -static void AnimConfuseRayBallSpiral(struct Sprite *); -static void AnimConfuseRayBallSpiral_Step(struct Sprite *); -static void AnimTask_NightShadeClone_Step1(u8 taskId); -static void AnimTask_NightShadeClone_Step2(u8 taskId); -static void AnimShadowBall(struct Sprite *); -static void AnimShadowBall_Step(struct Sprite *); -static void AnimLick(struct Sprite *); -static void AnimLick_Step(struct Sprite *); -static void AnimTask_NightmareClone_Step(u8 taskId); -static void AnimTask_SpiteTargetShadow_Step1(u8 taskId); -static void AnimTask_SpiteTargetShadow_Step2(u8 taskId); -static void AnimTask_SpiteTargetShadow_Step3(u8 taskId); -static void AnimDestinyBondWhiteShadow(struct Sprite *); -static void AnimDestinyBondWhiteShadow_Step(struct Sprite *); -static void AnimTask_DestinyBondWhiteShadow_Step(u8 taskId); -static void AnimTask_CurseStretchingBlackBg_Step1(u8 taskId); -static void AnimTask_CurseStretchingBlackBg_Step2(u8 taskId); -static void AnimCurseNail(struct Sprite *); -static void AnimCurseNail_Step1(struct Sprite *); -static void AnimCurseNail_Step2(struct Sprite *); -static void AnimCurseNail_End(struct Sprite *); -static void AnimGhostStatusSprite(struct Sprite *); -static void AnimGhostStatusSprite_Step(struct Sprite *); -static void AnimTask_GrudgeFlames_Step(u8 taskId); -static void AnimGrudgeFlame(struct Sprite *); -static void sub_8112F60(struct Sprite *); -static void sub_8112FB8(struct Sprite *); - -static const union AffineAnimCmd sAffineAnim_ConfuseRayBallBounce[] = -{ - AFFINEANIMCMD_FRAME(0x1E, 0x1E, 10, 5), - AFFINEANIMCMD_FRAME(0xFFE2, 0xFFE2, 10, 5), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd *const sAffineAnims_ConfuseRayBallBounce[] = -{ - sAffineAnim_ConfuseRayBallBounce, -}; - -const struct SpriteTemplate gConfuseRayBallBounceSpriteTemplate = -{ - .tileTag = ANIM_TAG_YELLOW_BALL, - .paletteTag = ANIM_TAG_YELLOW_BALL, - .oam = &gOamData_AffineDouble_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_ConfuseRayBallBounce, - .callback = AnimConfuseRayBallBounce, -}; - -const struct SpriteTemplate gConfuseRayBallSpiralSpriteTemplate = -{ - .tileTag = ANIM_TAG_YELLOW_BALL, - .paletteTag = ANIM_TAG_YELLOW_BALL, - .oam = &gOamData_AffineOff_ObjBlend_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimConfuseRayBallSpiral, -}; - -static const union AffineAnimCmd sAffineAnim_ShadowBall[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 10, 1), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd *const sAffineAnims_ShadowBall[] = -{ - sAffineAnim_ShadowBall, -}; - -const struct SpriteTemplate gShadowBallSpriteTemplate = -{ - .tileTag = ANIM_TAG_SHADOW_BALL, - .paletteTag = ANIM_TAG_SHADOW_BALL, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_ShadowBall, - .callback = AnimShadowBall, -}; - -static const union AnimCmd sAnim_Lick[] = -{ - ANIMCMD_FRAME(0, 2), - ANIMCMD_FRAME(8, 2), - ANIMCMD_FRAME(16, 2), - ANIMCMD_FRAME(24, 2), - ANIMCMD_FRAME(32, 2), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_Lick[] = -{ - sAnim_Lick, -}; - -const struct SpriteTemplate gLickSpriteTemplate = -{ - .tileTag = ANIM_TAG_LICK, - .paletteTag = ANIM_TAG_LICK, - .oam = &gOamData_AffineOff_ObjNormal_16x32, - .anims = sAnims_Lick, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimLick, -}; - -static const union AffineAnimCmd gUnknown_08596DA4[] = -{ - AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0), - AFFINEANIMCMD_END, -}; - -// Unused -static const union AffineAnimCmd *const gUnknown_08596DB4[] = -{ - gUnknown_08596DA4, -}; - -const struct SpriteTemplate gDestinyBondWhiteShadowSpriteTemplate = -{ - .tileTag = ANIM_TAG_WHITE_SHADOW, - .paletteTag = ANIM_TAG_WHITE_SHADOW, - .oam = &gOamData_AffineOff_ObjBlend_64x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDestinyBondWhiteShadow, -}; - -const struct SpriteTemplate gCurseNailSpriteTemplate = -{ - .tileTag = ANIM_TAG_NAIL, - .paletteTag = ANIM_TAG_NAIL, - .oam = &gOamData_AffineOff_ObjBlend_32x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimCurseNail, -}; - -const struct SpriteTemplate gCurseGhostSpriteTemplate = -{ - .tileTag = ANIM_TAG_GHOSTLY_SPIRIT, - .paletteTag = ANIM_TAG_GHOSTLY_SPIRIT, - .oam = &gOamData_AffineOff_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimGhostStatusSprite, -}; - -const struct SpriteTemplate gNightmareDevilSpriteTemplate = -{ - .tileTag = ANIM_TAG_DEVIL, - .paletteTag = ANIM_TAG_DEVIL, - .oam = &gOamData_AffineOff_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimGhostStatusSprite, -}; - -static const union AnimCmd sAnim_GrudgeFlame[] = -{ - ANIMCMD_FRAME(0, 4), - ANIMCMD_FRAME(8, 4), - ANIMCMD_FRAME(16, 4), - ANIMCMD_FRAME(24, 4), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_GrudgeFlame[] = -{ - sAnim_GrudgeFlame, -}; - -const struct SpriteTemplate gGrudgeFlameSpriteTemplate = -{ - .tileTag = ANIM_TAG_PURPLE_FLAME, - .paletteTag = ANIM_TAG_PURPLE_FLAME, - .oam = &gOamData_AffineOff_ObjBlend_16x32, - .anims = sAnims_GrudgeFlame, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimGrudgeFlame, -}; - -// Unused -const struct SpriteTemplate gUnknown_08596E48 = -{ - .tileTag = 0, - .paletteTag = 0, - .oam = &gDummyOamData, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_8112F60, -}; - -static void AnimConfuseRayBallBounce(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, 1); - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - sub_80A6FD4(sprite); - sprite->callback = AnimConfuseRayBallBounce_Step1; - sprite->data[6] = 16; - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); - SetGpuReg(REG_OFFSET_BLDALPHA, sprite->data[6]); -} - -static void AnimConfuseRayBallBounce_Step1(struct Sprite *sprite) -{ - s16 r0; - s16 r2; - sub_8111764(sprite); - if (AnimTranslateLinear(sprite)) - { - sprite->callback = AnimConfuseRayBallBounce_Step2; - return; - } - - sprite->pos2.x += Sin(sprite->data[5], 10); - sprite->pos2.y += Cos(sprite->data[5], 15); - r2 = sprite->data[5]; - sprite->data[5] = (sprite->data[5] + 5) & 0xFF; - r0 = sprite->data[5]; - if (r2 != 0 && r2 <= 196) - return; - if (r0 <= 0) - return; - PlaySE12WithPanning(SE_W109, gAnimCustomPanning); -} - -static void AnimConfuseRayBallBounce_Step2(struct Sprite *sprite) -{ - s16 r2; - s16 r0; - sprite->data[0] = 1; - AnimTranslateLinear(sprite); - sprite->pos2.x += Sin(sprite->data[5], 10); - sprite->pos2.y += Cos(sprite->data[5], 15); - - r2 = sprite->data[5]; - sprite->data[5] = (sprite->data[5] + 5) & 0xFF; - r0 = sprite->data[5]; - - if (r2 == 0 || r2 > 196) - { - if (r0 > 0) - PlaySE(SE_W109); - } - - if (sprite->data[6] == 0) - { - sprite->invisible = TRUE; - sprite->callback = DestroyAnimSpriteAndDisableBlend; - } - else - sub_8111764(sprite); -} - -static void sub_8111764(struct Sprite *sprite) -{ - - s16 r0; - if (sprite->data[6] > 0xFF) - { - if (++sprite->data[6] == 0x10d) - sprite->data[6] = 0; - return; - } - - r0 = sprite->data[7]; - sprite->data[7]++; - - if ((r0 & 0xFF) == 0) - { - sprite->data[7] &= 0xff00; - if ((sprite->data[7] & 0x100) != 0) - sprite->data[6]++; - else - sprite->data[6]--; - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[6], 16 - sprite->data[6])); - if (sprite->data[6] == 0 || sprite->data[6] == 16) - sprite->data[7] ^= 0x100; - if (sprite->data[6] == 0) - sprite->data[6] = 0x100; - } -} - -static void AnimConfuseRayBallSpiral(struct Sprite *sprite) -{ - InitSpritePosToAnimTarget(sprite, TRUE); - sprite->callback = AnimConfuseRayBallSpiral_Step; - sprite->callback(sprite); -} - -static void AnimConfuseRayBallSpiral_Step(struct Sprite *sprite) -{ - u16 temp1; - sprite->pos2.x = Sin(sprite->data[0], 32); - sprite->pos2.y = Cos(sprite->data[0], 8); - temp1 = sprite->data[0] - 65; - if (temp1 <= 130) - sprite->oam.priority = 2; - else - sprite->oam.priority = 1; - sprite->data[0] = (sprite->data[0] + 19) & 0xFF; - sprite->data[2] += 80; - sprite->pos2.y += sprite->data[2] >> 8; - sprite->data[7] += 1; - if (sprite->data[7] == 61) - DestroyAnimSprite(sprite); -} - -// Creates a large transparent clone of the attacker centered on their position which shrinks to original size -void AnimTask_NightShadeClone(u8 taskId) -{ - u8 spriteId; - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); - spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_BLEND); - SetSpriteRotScale(spriteId, 128, 128, 0); - gSprites[spriteId].invisible = FALSE; - gTasks[taskId].data[0] = 128; - gTasks[taskId].data[1] = *gBattleAnimArgs; - gTasks[taskId].data[2] = 0; - gTasks[taskId].data[3] = 16; - gTasks[taskId].func = AnimTask_NightShadeClone_Step1; -} - -static void AnimTask_NightShadeClone_Step1(u8 taskId) -{ - gTasks[taskId].data[10] += 1; - if (gTasks[taskId].data[10] == 3) - { - gTasks[taskId].data[10] = 0; - gTasks[taskId].data[2] += 1; - gTasks[taskId].data[3] -= 1; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[2], gTasks[taskId].data[3])); - if (gTasks[taskId].data[2] != 9) - return; - - gTasks[taskId].func = AnimTask_NightShadeClone_Step2; - } -} - -static void AnimTask_NightShadeClone_Step2(u8 taskId) -{ - u8 spriteId; - if (gTasks[taskId].data[1] > 0) - { - gTasks[taskId].data[1] -= 1; - return; - } - - spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - gTasks[taskId].data[0] += 8; - if (gTasks[taskId].data[0] <= 0xFF) - { - SetSpriteRotScale(spriteId, gTasks[taskId].data[0], gTasks[taskId].data[0], 0); - } - else - { - ResetSpriteRotScale(spriteId); - DestroyAnimVisualTask(taskId); - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - } -} - -// Spins a sprite towards the target, pausing in the middle. -// Used in Shadow Ball. -// arg 0: duration step 1 (attacker -> center) -// arg 1: duration step 2 (spin center) -// arg 2: duration step 3 (center -> target) -static void AnimShadowBall(struct Sprite *sprite) -{ - s16 oldPosX = sprite->pos1.x; - s16 oldPosY = sprite->pos1.y; - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); - sprite->data[0] = 0; - sprite->data[1] = gBattleAnimArgs[0]; - sprite->data[2] = gBattleAnimArgs[1]; - sprite->data[3] = gBattleAnimArgs[2]; - sprite->data[4] = sprite->pos1.x << 4; - sprite->data[5] = sprite->pos1.y << 4; - sprite->data[6] = ((oldPosX - sprite->pos1.x) << 4) / (gBattleAnimArgs[0] << 1); - sprite->data[7] = ((oldPosY - sprite->pos1.y) << 4) / (gBattleAnimArgs[0] << 1); - sprite->callback = AnimShadowBall_Step; -} - -static void AnimShadowBall_Step(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - sprite->data[4] += sprite->data[6]; - sprite->data[5] += sprite->data[7]; - sprite->pos1.x = sprite->data[4] >> 4; - sprite->pos1.y = sprite->data[5] >> 4; - sprite->data[1] -= 1; - if (sprite->data[1] > 0) - break; - sprite->data[0] += 1; - break; - case 1: - sprite->data[2] -= 1; - if (sprite->data[2] > 0) - break; - sprite->data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - sprite->data[4] = sprite->pos1.x << 4; - sprite->data[5] = sprite->pos1.y << 4; - sprite->data[6] = ((sprite->data[1] - sprite->pos1.x) << 4) / sprite->data[3]; - sprite->data[7] = ((sprite->data[2] - sprite->pos1.y) << 4) / sprite->data[3]; - sprite->data[0] += 1; - break; - case 2: - sprite->data[4] += sprite->data[6]; - sprite->data[5] += sprite->data[7]; - sprite->pos1.x = sprite->data[4] >> 4; - sprite->pos1.y = sprite->data[5] >> 4; - sprite->data[3] -= 1; - if (sprite->data[3] > 0) - break; - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - sprite->data[0] += 1; - break; - case 3: - DestroySpriteAndMatrix(sprite); - break; - } -} - -static void AnimLick(struct Sprite *sprite) -{ - InitSpritePosToAnimTarget(sprite, TRUE); - sprite->callback = AnimLick_Step; -} - -static void AnimLick_Step(struct Sprite *sprite) -{ - bool8 r5 = FALSE; - bool8 r6 = FALSE; - - if (sprite->animEnded) - { - if (!sprite->invisible) - sprite->invisible = TRUE; - - switch (sprite->data[0]) - { - default: - r6 = TRUE; - break; - case 0: - if (sprite->data[1] == 2) - r5 = TRUE; - break; - case 1: - if (sprite->data[1] == 4) - r5 = TRUE; - break; - } - - if (r5) - { - sprite->invisible ^= 1; - sprite->data[2]++; - sprite->data[1] = 0; - if (sprite->data[2] == 5) - { - sprite->data[2] = 0; - sprite->data[0]++; - } - } - else if (r6) - { - DestroyAnimSprite(sprite); - } - else - { - sprite->data[1]++; - } - } -} - -// Creates a transparent clone of the target which drifts up and away to the side -void AnimTask_NightmareClone(u8 taskId) -{ - struct Task *task; - - task = &gTasks[taskId]; - task->data[0] = CloneBattlerSpriteWithBlend(ANIM_TARGET); - if (task->data[0] < 0) - { - DestroyAnimVisualTask(taskId); - return; - } - task->data[1] = 0; - task->data[2] = 15; - task->data[3] = 2; - task->data[4] = 0; - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[2], task->data[3])); - gSprites[task->data[0]].data[0] = 80; - if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) - { - gSprites[task->data[0]].data[1] = -144; - gSprites[task->data[0]].data[2] = 112; - } - else - { - gSprites[task->data[0]].data[1] = 144; - gSprites[task->data[0]].data[2] = -112; - } - gSprites[task->data[0]].data[3] = 0; - gSprites[task->data[0]].data[4] = 0; - StoreSpriteCallbackInData6(&gSprites[task->data[0]], SpriteCallbackDummy); - gSprites[task->data[0]].callback = TranslateSpriteLinearFixedPoint; - task->func = AnimTask_NightmareClone_Step; -} - -static void AnimTask_NightmareClone_Step(u8 taskId) -{ - struct Task *task; - - task = &gTasks[taskId]; - switch (task->data[4]) - { - case 0: - task->data[1] += 1; - task->data[5] = task->data[1] & 3; - if (task->data[5] == 1) - if (task->data[2] > 0) - task->data[2] -= 1; - if (task->data[5] == 3) - if (task->data[3] <= 15) - task->data[3] += 1; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[2], task->data[3])); - if (task->data[3] != 16 || task->data[2] != 0) - break; - if (task->data[1] <= 80) - break; - obj_delete_but_dont_free_vram(&gSprites[task->data[0]]); - task->data[4] = 1; - break; - case 1: - if (++task->data[6] <= 1) - break; - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - task->data[4] += 1; - break; - case 2: - DestroyAnimVisualTask(taskId); - break; - } -} - -// Creates a blended copy of the target that wavers in front of them -void AnimTask_SpiteTargetShadow(u8 taskId) -{ - struct Task *task; - - task = &gTasks[taskId]; - task->data[15] = 0; - task->func = AnimTask_SpiteTargetShadow_Step1; - task->func(taskId); -} - -static void AnimTask_SpiteTargetShadow_Step1(u8 taskId) -{ - s16 startLine; - struct Task *task = &gTasks[taskId]; - u8 position = GetBattlerSpriteBGPriorityRank(gBattleAnimTarget); - - switch (task->data[15]) - { - case 0: - task->data[14] = AllocSpritePalette(ANIM_TAG_BENT_SPOON); - if (task->data[14] == 0xFF || task->data[14] == 0xF) - { - DestroyAnimVisualTask(taskId); - } - else - { - task->data[0] = CloneBattlerSpriteWithBlend(ANIM_TARGET); - if (task->data[0] < 0) - { - FreeSpritePaletteByTag(ANIM_TAG_BENT_SPOON); - DestroyAnimVisualTask(taskId); - } - else - { - s16 mask2; - gSprites[task->data[0]].oam.paletteNum = task->data[14]; - gSprites[task->data[0]].oam.objMode = ST_OAM_OBJ_NORMAL; - gSprites[task->data[0]].oam.priority = 3; - gSprites[task->data[0]].invisible = (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].invisible); - task->data[1] = 0; - task->data[2] = 0; - task->data[3] = 16; - task->data[13] = GetAnimBattlerSpriteId(ANIM_TARGET); - task->data[4] = (gSprites[task->data[13]].oam.paletteNum + 16) * 16; - if (position == 1) { - u16 mask = DISPCNT_BG1_ON; - mask2 = mask; - } - else { - u16 mask = DISPCNT_BG2_ON; - mask2 = mask; - } - ClearGpuRegBits(REG_OFFSET_DISPCNT, mask2); - task->data[15]++; - } - } - break; - case 1: - task->data[14] = (task->data[14] + 16) * 16; - CpuSet(&gPlttBufferUnfaded[task->data[4]], &gPlttBufferFaded[task->data[14]], 0x4000008); - BlendPalette(task->data[4], 16, 10, RGB(13, 0, 15)); - task->data[15]++; - break; - case 2: - startLine = gSprites[task->data[13]].pos1.y + gSprites[task->data[13]].pos2.y - 32; - if (startLine < 0) - startLine = 0; - - if (position == 1) - task->data[10] = ScanlineEffect_InitWave(startLine, startLine + 64, 2, 6, 0, 4, 1); - else - task->data[10] = ScanlineEffect_InitWave(startLine, startLine + 64, 2, 6, 0, 8, 1); - - task->data[15]++; - break; - case 3: - if (position == 1) - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL | BLDCNT_TGT1_BG1)); - else - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL | BLDCNT_TGT1_BG2)); - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); - task->data[15]++; - break; - case 4: - if (position == 1) - SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); - else - SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); - - task->func = AnimTask_SpiteTargetShadow_Step2; - task->data[15]++; - break; - default: - task->data[15]++; - break; - } -} - -static void AnimTask_SpiteTargetShadow_Step2(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - task->data[1]++; - task->data[5] = task->data[1] & 1; - if (task->data[5] == 0) - task->data[2] = gSineTable[task->data[1]] / 18; - - if (task->data[5] == 1) - task->data[3] = 16 - (gSineTable[task->data[1]] / 18); - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[2], task->data[3])); - if (task->data[1] == 128) - { - task->data[15] = 0; - task->func = AnimTask_SpiteTargetShadow_Step3; - task->func(taskId); - } -} - -static void AnimTask_SpiteTargetShadow_Step3(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - u8 rank = GetBattlerSpriteBGPriorityRank(gBattleAnimTarget); - - switch (task->data[15]) - { - case 0: - gScanlineEffect.state = 3; - task->data[14] = GetAnimBattlerSpriteId(ANIM_TARGET); - if (rank == 1) - ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); - else - ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); - break; - case 1: - BlendPalette(task->data[4], 16, 0, RGB(13, 0, 15)); - break; - case 2: - gSprites[task->data[14]].invisible = TRUE; - obj_delete_but_dont_free_vram(&gSprites[task->data[0]]); - FreeSpritePaletteByTag(ANIM_TAG_BENT_SPOON); - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - if (rank == 1) - SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); - else - SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); - - DestroyAnimVisualTask(taskId); - break; - } - - task->data[15]++; -} - -static void AnimDestinyBondWhiteShadow(struct Sprite *sprite) -{ - s16 battler1X, battler1Y; - s16 battler2X, battler2Y; - s16 yDiff; - - if (gBattleAnimArgs[0] == 0) - { - battler1X = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); - battler1Y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 28; - battler2X = GetBattlerSpriteCoord(gBattleAnimTarget, 0); - battler2Y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 28; - } - else - { - battler1X = GetBattlerSpriteCoord(gBattleAnimTarget, 0); - battler1Y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 28; - battler2X = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); - battler2Y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 28; - } - - yDiff = battler2Y - battler1Y; - sprite->data[0] = battler1X * 16; - sprite->data[1] = battler1Y * 16; - sprite->data[2] = ((battler2X - battler1X) * 16) / gBattleAnimArgs[1]; - sprite->data[3] = (yDiff * 16) / gBattleAnimArgs[1]; - sprite->data[4] = gBattleAnimArgs[1]; - sprite->data[5] = battler2X; - sprite->data[6] = battler2Y; - sprite->data[7] = sprite->data[4] / 2; - sprite->oam.priority = 2; - sprite->pos1.x = battler1X; - sprite->pos1.y = battler1Y; - sprite->callback = AnimDestinyBondWhiteShadow_Step; - sprite->invisible = TRUE; -} - -static void AnimDestinyBondWhiteShadow_Step(struct Sprite *sprite) -{ - if (sprite->data[4]) - { - sprite->data[0] += sprite->data[2]; - sprite->data[1] += sprite->data[3]; - sprite->pos1.x = sprite->data[0] >> 4; - sprite->pos1.y = sprite->data[1] >> 4; - if (--sprite->data[4] == 0) - sprite->data[0] = 0; - } -} - -void AnimTask_DestinyBondWhiteShadow(u8 taskId) -{ - struct Task *task; - s16 battler; - u8 spriteId; - s16 baseX, baseY; - s16 x, y; - - task = &gTasks[taskId]; - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); - task->data[5] = 0; - task->data[6] = 0; - task->data[7] = 0; - task->data[8] = 0; - task->data[9] = 16; - task->data[10] = gBattleAnimArgs[0]; - - baseX = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - baseY = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_BOTTOM); - if (!IsContest()) - { - for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++) - { - if (battler != gBattleAnimAttacker - && battler != (gBattleAnimAttacker ^ 2) - && IsBattlerSpriteVisible(battler)) - { - spriteId = CreateSprite(&gDestinyBondWhiteShadowSpriteTemplate, baseX, baseY, 55); - if (spriteId != MAX_SPRITES) - { - x = GetBattlerSpriteCoord(battler, 2); - y = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_BOTTOM); - gSprites[spriteId].data[0] = baseX << 4; - gSprites[spriteId].data[1] = baseY << 4; - gSprites[spriteId].data[2] = ((x - baseX) << 4) / gBattleAnimArgs[1]; - gSprites[spriteId].data[3] = ((y - baseY) << 4) / gBattleAnimArgs[1]; - gSprites[spriteId].data[4] = gBattleAnimArgs[1]; - gSprites[spriteId].data[5] = x; - gSprites[spriteId].data[6] = y; - gSprites[spriteId].callback = AnimDestinyBondWhiteShadow_Step; - - task->data[task->data[12] + 13] = spriteId; - task->data[12]++; - } - } - } - } - else - { - spriteId = CreateSprite(&gDestinyBondWhiteShadowSpriteTemplate, baseX, baseY, 55); - if (spriteId != MAX_SPRITES) - { - x = 48; - y = 40; - gSprites[spriteId].data[0] = baseX << 4; - gSprites[spriteId].data[1] = baseY << 4; - gSprites[spriteId].data[2] = ((x - baseX) << 4) / gBattleAnimArgs[1]; - gSprites[spriteId].data[3] = ((y - baseY) << 4) / gBattleAnimArgs[1]; - gSprites[spriteId].data[4] = gBattleAnimArgs[1]; - gSprites[spriteId].data[5] = x; - gSprites[spriteId].data[6] = y; - gSprites[spriteId].callback = AnimDestinyBondWhiteShadow_Step; - - task->data[13] = spriteId; - task->data[12] = 1; - } - } - - task->func = AnimTask_DestinyBondWhiteShadow_Step; -} - -static void AnimTask_DestinyBondWhiteShadow_Step(u8 taskId) -{ - u16 i; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - if (task->data[6] == 0) - { - if (++task->data[5] > 1) - { - task->data[5] = 0; - task->data[7]++; - if (task->data[7] & 1) - { - if (task->data[8] < 16) - task->data[8]++; - } - else - { - if (task->data[9]) - task->data[9]--; - } - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[8], task->data[9])); - if (task->data[7] >= 24) - { - task->data[7] = 0; - task->data[6] = 1; - } - } - } - - if (task->data[10]) - task->data[10]--; - else if (task->data[6]) - task->data[0]++; - break; - case 1: - if (++task->data[5] > 1) - { - task->data[5] = 0; - task->data[7]++; - if (task->data[7] & 1) - { - if (task->data[8]) - task->data[8]--; - } - else - { - if (task->data[9] < 16) - task->data[9]++; - } - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[8], task->data[9])); - if (task->data[8] == 0 && task->data[9] == 16) - { - for (i = 0; i < task->data[12]; i++) - DestroySprite(&gSprites[task->data[i + 13]]); - - task->data[0]++; - } - } - break; - case 2: - if (++task->data[5] > 0) - task->data[0]++; - break; - case 3: - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - DestroyAnimVisualTask(taskId); - break; - } -} - -void AnimTask_CurseStretchingBlackBg(u8 taskId) -{ - s16 startX, startY; - s16 leftDistance, topDistance, bottomDistance, rightDistance; - - gBattle_WIN0H = 0; - gBattle_WIN0V = 0; - SetGpuReg(REG_OFFSET_WININ, ((WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR) | - (WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR))); - SetGpuReg(REG_OFFSET_WINOUT, ((WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ) | - (WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR))); - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_TGT1_BG3 | BLDCNT_EFFECT_DARKEN)); - SetGpuReg(REG_OFFSET_BLDY, 0x10); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER || IsContest()) - startX = 40; - else - startX = 200; - - gBattle_WIN0H = (startX << 8) | startX; - startY = 40; - gBattle_WIN0V = (startY << 8) | startY; - - leftDistance = startX; - rightDistance = 240 - startX; - topDistance = startY; - bottomDistance = 72; - gTasks[taskId].data[1] = leftDistance; - gTasks[taskId].data[2] = rightDistance; - gTasks[taskId].data[3] = topDistance; - gTasks[taskId].data[4] = bottomDistance; - gTasks[taskId].data[5] = startX; - gTasks[taskId].data[6] = startY; - gTasks[taskId].func = AnimTask_CurseStretchingBlackBg_Step1; -} - -static void AnimTask_CurseStretchingBlackBg_Step1(u8 taskId) -{ - s16 step; - s16 leftDistance, rightDistance, topDistance, bottomDistance; - s16 startX, startY; - u16 left, right, top, bottom; - u16 selectedPalettes; - - step = gTasks[taskId].data[0]; - gTasks[taskId].data[0]++; - leftDistance = gTasks[taskId].data[1]; - rightDistance = gTasks[taskId].data[2]; - topDistance = gTasks[taskId].data[3]; - bottomDistance = gTasks[taskId].data[4]; - startX = gTasks[taskId].data[5]; - startY = gTasks[taskId].data[6]; - - if (step < 16) - { - left = startX - (leftDistance * 0.0625) * step; - right = startX + (rightDistance * 0.0625) * step; - top = startY - (topDistance * 0.0625) * step; - bottom = startY + (bottomDistance * 0.0625) * step; - } - else - { - left = 0; - right = 240; - top = 0; - bottom = 112; - selectedPalettes = sub_80A75AC(1, 0, 0, 0, 0, 0, 0); - BeginNormalPaletteFade(selectedPalettes, 0, 16, 16, RGB(0, 0, 0)); - gTasks[taskId].func = AnimTask_CurseStretchingBlackBg_Step2; - } - - gBattle_WIN0H = (left << 8) | right; - gBattle_WIN0V = (top << 8) | bottom; -} - -static void AnimTask_CurseStretchingBlackBg_Step2(u8 taskId) -{ - if (!gPaletteFade.active) - { - gBattle_WIN0H = 0; - gBattle_WIN0V = 0; - SetGpuReg(REG_OFFSET_WININ, ((WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR) | - (WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR))); - SetGpuReg(REG_OFFSET_WINOUT, ((WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR) | - (WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR))); - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDY, 0); - DestroyAnimVisualTask(taskId); - } -} - -static void AnimCurseNail(struct Sprite *sprite) -{ - s16 xDelta; - s16 xDelta2; - - InitSpritePosToAnimAttacker(sprite, 1); - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) - { - xDelta = 24; - xDelta2 = -2; - sprite->oam.matrixNum = ST_OAM_HFLIP; - } - else - { - xDelta = -24; - xDelta2 = 2; - } - - sprite->pos1.x += xDelta; - sprite->data[1] = xDelta2; - sprite->data[0] = 60; - sprite->callback = AnimCurseNail_Step1; -} - -static void AnimCurseNail_Step1(struct Sprite *sprite) -{ - u16 var0; - - if (sprite->data[0] > 0) - { - sprite->data[0]--; - } - else - { - sprite->pos2.x += sprite->data[1]; - var0 = sprite->pos2.x + 7; - if (var0 > 14) - { - sprite->pos1.x += sprite->pos2.x; - sprite->pos2.x = 0; - sprite->oam.tileNum += 8; - if (++sprite->data[2] == 3) - { - sprite->data[0] = 30; - sprite->callback = WaitAnimForDuration; - StoreSpriteCallbackInData6(sprite, AnimCurseNail_Step2); - } - else - { - sprite->data[0] = 40; - } - } - } -} - -static void AnimCurseNail_Step2(struct Sprite *sprite) -{ - if (sprite->data[0] == 0) - { - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); - sprite->data[0]++; - sprite->data[1] = 0; - sprite->data[2] = 0; - } - else if (sprite->data[1] < 2) - { - sprite->data[1]++; - } - else - { - sprite->data[1] = 0; - sprite->data[2]++; - SetGpuReg(REG_OFFSET_BLDALPHA, (16 - sprite->data[2]) | (sprite->data[2] << 8)); - if (sprite->data[2] == 16) - { - sprite->invisible = TRUE; - sprite->callback = AnimCurseNail_End; - } - } -} - -static void AnimCurseNail_End(struct Sprite *sprite) -{ - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - gBattle_WIN0H = 0; - gBattle_WIN0V = 0; - DestroyAnimSprite(sprite); -} - -static void AnimGhostStatusSprite(struct Sprite *sprite) -{ - u16 coeffB; - u16 coeffA; - - sprite->pos2.x = Sin(sprite->data[0], 12); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - sprite->pos2.x = -sprite->pos2.x; - - sprite->data[0] = (sprite->data[0] + 6) & 0xFF; - sprite->data[1] += 0x100; - sprite->pos2.y = -(sprite->data[1] >> 8); - - sprite->data[7]++; - if (sprite->data[7] == 1) - { - sprite->data[6] = 0x050B; - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); - SetGpuReg(REG_OFFSET_BLDALPHA, sprite->data[6]); - } - else if (sprite->data[7] > 30) - { - sprite->data[2]++; - coeffB = sprite->data[6] >> 8; - coeffA = sprite->data[6] & 0xFF; - - if (++coeffB > 16) - coeffB = 16; - --coeffA; - if ((s16)coeffA < 0) - coeffA = 0; - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(coeffA, coeffB)); - sprite->data[6] = BLDALPHA_BLEND(coeffA, coeffB); - if (coeffB == 16 && coeffA == 0) - { - sprite->invisible = TRUE; - sprite->callback = AnimGhostStatusSprite_Step; - } - } -} - -static void AnimGhostStatusSprite_Step(struct Sprite *sprite) -{ - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - DestroyAnimSprite(sprite); -} - -void AnimTask_GrudgeFlames(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - task->data[0] = 0; - task->data[1] = 16; - task->data[9] = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - task->data[10] = GetBattlerYCoordWithElevation(gBattleAnimAttacker); - task->data[11] = (GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_WIDTH) / 2) + 8; - task->data[7] = 0; - task->data[5] = GetBattlerSpriteBGPriority(gBattleAnimAttacker); - task->data[6] = GetBattlerSpriteSubpriority(gBattleAnimAttacker) - 2; - task->data[3] = 0; - task->data[4] = 16; - SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); - task->data[8] = 0; - task->func = AnimTask_GrudgeFlames_Step; -} - -static void AnimTask_GrudgeFlames_Step(u8 taskId) -{ - u16 i; - u8 spriteId; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - for (i = 0; i < 6; i++) - { - spriteId = CreateSprite(&gGrudgeFlameSpriteTemplate, task->data[9], task->data[10], task->data[6]); - if (spriteId != MAX_SPRITES) - { - gSprites[spriteId].data[0] = taskId; - gSprites[spriteId].data[1] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER; - - gSprites[spriteId].data[2] = (i * 42) & 0xFF; - gSprites[spriteId].data[3] = task->data[11]; - gSprites[spriteId].data[5] = i * 6; - task->data[7]++; - } - } - - task->data[0]++; - break; - case 1: - if (++task->data[1] & 1) - { - if (task->data[3] < 14) - task->data[3]++; - } - else - { - if (task->data[4] > 4) - task->data[4]--; - } - - if (task->data[3] == 14 && task->data[4] == 4) - { - task->data[1] = 0; - task->data[0]++; - } - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4])); - break; - case 2: - if (++task->data[1] > 30) - { - task->data[1] = 0; - task->data[0]++; - } - break; - case 3: - if (++task->data[1] & 1) - { - if (task->data[3] > 0) - task->data[3]--; - } - else - { - if (task->data[4] < 16) - task->data[4]++; - } - - if (task->data[3] == 0 && task->data[4] == 16) - { - task->data[8] = 1; - task->data[0]++; - } - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4])); - break; - case 4: - if (task->data[7] == 0) - task->data[0]++; - break; - case 5: - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - DestroyAnimVisualTask(taskId); - break; - } -} - -static void AnimGrudgeFlame(struct Sprite *sprite) -{ - u16 index; - - if (sprite->data[1] == 0) - sprite->data[2] += 2; - else - sprite->data[2] -= 2; - - sprite->data[2] &= 0xFF; - sprite->pos2.x = Sin(sprite->data[2], sprite->data[3]); - - index = sprite->data[2] - 65; - if (index < 127) - sprite->oam.priority = gTasks[sprite->data[0]].data[5] + 1; - else - sprite->oam.priority = gTasks[sprite->data[0]].data[5]; - - sprite->data[5]++; - sprite->data[6] = (sprite->data[5] * 8) & 0xFF; - sprite->pos2.y = Sin(sprite->data[6], 7); - if (gTasks[sprite->data[0]].data[8]) - { - gTasks[sprite->data[0]].data[7]--; - DestroySprite(sprite); - } -} - -static void sub_8112F60(struct Sprite *sprite) -{ - sprite->invisible = TRUE; - sprite->data[5] = gBattlerSpriteIds[gBattleAnimAttacker]; - sprite->data[0] = 128; - sprite->data[1] = 10; - sprite->data[2] = gBattleAnimArgs[0]; - sprite->data[3] = gBattleAnimArgs[1]; - sprite->callback = sub_8112FB8; - - gSprites[sprite->data[5]].pos1.y += 8; -} - -static void sub_8112FB8(struct Sprite *sprite) -{ - if (sprite->data[3]) - { - sprite->data[3]--; - gSprites[sprite->data[5]].pos2.x = Sin(sprite->data[0], sprite->data[1]); - gSprites[sprite->data[5]].pos2.y = Cos(sprite->data[0], sprite->data[1]); - sprite->data[0] += sprite->data[2]; - if (sprite->data[0] > 255) - sprite->data[0] -= 256; - } - else - { - gSprites[sprite->data[5]].pos2.x = 0; - gSprites[sprite->data[5]].pos2.y = 0; - gSprites[sprite->data[5]].pos1.y -= 8; - sprite->callback = DestroySpriteAndMatrix; - } -} diff --git a/src/ground.c b/src/ground.c deleted file mode 100644 index 6ec17742a..000000000 --- a/src/ground.c +++ /dev/null @@ -1,772 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "random.h" -#include "scanline_effect.h" -#include "task.h" -#include "trig.h" -#include "constants/rgb.h" - -static void AnimBonemerangProjectile(struct Sprite *); -static void AnimBoneHitProjectile(struct Sprite *); -static void AnimDirtScatter(struct Sprite *); -static void AnimMudSportDirt(struct Sprite *); -static void AnimDirtPlumeParticle(struct Sprite *); -static void AnimDirtPlumeParticle_Step(struct Sprite *); -static void AnimDigDirtMound(struct Sprite *); -static void AnimBonemerangProjectile_Step(struct Sprite *); -static void AnimBonemerangProjectile_End(struct Sprite *); -static void AnimMudSportDirtRising(struct Sprite *); -static void AnimMudSportDirtFalling(struct Sprite *); -static void AnimTask_DigBounceMovement(u8); -static void AnimTask_DigEndBounceMovementSetInvisible(u8); -static void AnimTask_DigSetVisibleUnderground(u8); -static void AnimTask_DigRiseUpFromHole(u8); -static void sub_81150E0(u8, s16, s16); -static void AnimTask_ShakeTerrain(u8); -static void AnimTask_ShakeBattlers(u8); -static void SetBattlersXOffsetForShake(struct Task *); -static void sub_81156D0(u8); - -static const union AffineAnimCmd sAffineAnim_Bonemerang[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 15, 1), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd sAffineAnim_SpinningBone[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 20, 1), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd *const sAffineAnims_Bonemerang[] = -{ - sAffineAnim_Bonemerang, -}; - -static const union AffineAnimCmd *const sAffineAnims_SpinningBone[] = -{ - sAffineAnim_SpinningBone, -}; - -const struct SpriteTemplate gBonemerangSpriteTemplate = -{ - .tileTag = ANIM_TAG_BONE, - .paletteTag = ANIM_TAG_BONE, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_Bonemerang, - .callback = AnimBonemerangProjectile, -}; - -const struct SpriteTemplate gSpinningBoneSpriteTemplate = -{ - .tileTag = ANIM_TAG_BONE, - .paletteTag = ANIM_TAG_BONE, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_SpinningBone, - .callback = AnimBoneHitProjectile, -}; - -const struct SpriteTemplate gSandAttackDirtSpriteTemplate = -{ - .tileTag = ANIM_TAG_MUD_SAND, - .paletteTag = ANIM_TAG_MUD_SAND, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDirtScatter, -}; - -static const union AnimCmd sAnim_MudSlapMud[] = -{ - ANIMCMD_FRAME(1, 1), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_MudSlapMud[] = -{ - sAnim_MudSlapMud, -}; - -const struct SpriteTemplate gMudSlapMudSpriteTemplate = -{ - .tileTag = ANIM_TAG_MUD_SAND, - .paletteTag = ANIM_TAG_MUD_SAND, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = sAnims_MudSlapMud, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDirtScatter, -}; - -const struct SpriteTemplate gMudsportMudSpriteTemplate = -{ - .tileTag = ANIM_TAG_MUD_SAND, - .paletteTag = ANIM_TAG_MUD_SAND, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimMudSportDirt, -}; - -const struct SpriteTemplate gDirtPlumeSpriteTemplate = -{ - .tileTag = ANIM_TAG_MUD_SAND, - .paletteTag = ANIM_TAG_MUD_SAND, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDirtPlumeParticle, -}; - -const struct SpriteTemplate gDirtMoundSpriteTemplate = -{ - .tileTag = ANIM_TAG_DIRT_MOUND, - .paletteTag = ANIM_TAG_DIRT_MOUND, - .oam = &gOamData_AffineOff_ObjNormal_32x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDigDirtMound, -}; - -// Moves a bone projectile towards the target mon, which moves like -// a boomerang. After hitting the target mon, it comes back to the user. -static void AnimBonemerangProjectile(struct Sprite *sprite) -{ - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); - sprite->data[0] = 20; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - sprite->data[5] = -40; - InitAnimArcTranslation(sprite); - sprite->callback = AnimBonemerangProjectile_Step; -} - -static void AnimBonemerangProjectile_Step(struct Sprite *sprite) -{ - if (TranslateAnimHorizontalArc(sprite)) - { - sprite->pos1.x += sprite->pos2.x; - sprite->pos1.y += sprite->pos2.y; - sprite->pos2.y = 0; - sprite->pos2.x = 0; - sprite->data[0] = 20; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); - sprite->data[5] = 40; - InitAnimArcTranslation(sprite); - sprite->callback = AnimBonemerangProjectile_End; - } -} - -static void AnimBonemerangProjectile_End(struct Sprite *sprite) -{ - if (TranslateAnimHorizontalArc(sprite)) - DestroyAnimSprite(sprite); -} - -// Moves a bone projectile towards the target mon, starting right next to -// the target mon. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: target x pixel offset -// arg 3: target y pixel offset -// arg 4: duration -static void AnimBoneHitProjectile(struct Sprite *sprite) -{ - InitSpritePosToAnimTarget(sprite, TRUE); - 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, 3) + gBattleAnimArgs[3]; - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Moves a small dirt projectile towards the target mon. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: duration -// arg 3: target x pixel offset -// arg 4: target y pixel offset -static void AnimDirtScatter(struct Sprite *sprite) -{ - u8 targetXPos, targetYPos; - s16 xOffset, yOffset; - - InitSpritePosToAnimAttacker(sprite, 1); - - targetXPos = GetBattlerSpriteCoord2(gBattleAnimTarget, 2); - targetYPos = GetBattlerSpriteCoord2(gBattleAnimTarget, 3); - - xOffset = Random2() & 0x1F; - yOffset = Random2() & 0x1F; - if (xOffset > 16) - xOffset = 16 - xOffset; - if (yOffset > 16) - yOffset = 16 - yOffset; - - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[2] = targetXPos + xOffset; - sprite->data[4] = targetYPos + yOffset; - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); -} - -// Moves a particle of dirt in the Mud Sport animation. -// The dirt can either be rising upward, or falling down. -// arg 0: 0 = dirt is rising into the air, 1 = dirt is falling down -// arg 1: initial x pixel offset -// arg 2: initial y pixel offset -static void AnimMudSportDirt(struct Sprite *sprite) -{ - sprite->oam.tileNum++; - if (gBattleAnimArgs[0] == 0) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2) + gBattleAnimArgs[1]; - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + gBattleAnimArgs[2]; - sprite->data[0] = gBattleAnimArgs[1] > 0 ? 1 : -1; - sprite->callback = AnimMudSportDirtRising; - } - else - { - sprite->pos1.x = gBattleAnimArgs[1]; - sprite->pos1.y = gBattleAnimArgs[2]; - sprite->pos2.y = -gBattleAnimArgs[2]; - sprite->callback = AnimMudSportDirtFalling; - } -} - -static void AnimMudSportDirtRising(struct Sprite *sprite) -{ - if (++sprite->data[1] > 1) - { - sprite->data[1] = 0; - sprite->pos1.x += sprite->data[0]; - } - - sprite->pos1.y -= 4; - if (sprite->pos1.y < -4) - DestroyAnimSprite(sprite); -} - -static void AnimMudSportDirtFalling(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - sprite->pos2.y += 4; - if (sprite->pos2.y >= 0) - { - sprite->pos2.y = 0; - sprite->data[0]++; - } - break; - case 1: - if (++sprite->data[1] > 0) - { - sprite->data[1] = 0; - sprite->invisible ^= 1; - if (++sprite->data[2] == 10) - DestroyAnimSprite(sprite); - } - break; - } -} - -void AnimTask_DigDownMovement(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - if (gBattleAnimArgs[0] == FALSE) - task->func = AnimTask_DigBounceMovement; - else - task->func = AnimTask_DigEndBounceMovementSetInvisible; - - task->func(taskId); -} - -static void AnimTask_DigBounceMovement(u8 taskId) -{ - u8 var0; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); - task->data[11] = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); - if (task->data[11] == 1) - { - task->data[12] = gBattle_BG1_X; - task->data[13] = gBattle_BG1_Y; - } - else - { - task->data[12] = gBattle_BG2_X; - task->data[13] = gBattle_BG2_Y; - } - - var0 = GetBattlerYCoordWithElevation(gBattleAnimAttacker); - task->data[14] = var0 - 32; - task->data[15] = var0 + 32; - if (task->data[14] < 0) - task->data[14] = 0; - - gSprites[task->data[10]].invisible = TRUE; - task->data[0]++; - break; - case 1: - sub_81150E0(task->data[11], task->data[14], task->data[15]); - task->data[0]++; - break; - case 2: - task->data[2] = (task->data[2] + 6) & 0x7F; - if (++task->data[4] > 2) - { - task->data[4] = 0; - task->data[3]++; - } - - task->data[5] = task->data[3] + (gSineTable[task->data[2]] >> 4); - if (task->data[11] == 1) - gBattle_BG1_Y = task->data[13] - task->data[5]; - else - gBattle_BG2_Y = task->data[13] - task->data[5]; - - if (task->data[5] > 63) - { - task->data[5] = 120 - task->data[14]; - if (task->data[11] == 1) - gBattle_BG1_Y = task->data[13] - task->data[5]; - else - gBattle_BG2_Y = task->data[13] - task->data[5]; - - gSprites[task->data[10]].pos2.x = 272 - gSprites[task->data[10]].pos1.x; - task->data[0]++; - } - break; - case 3: - gScanlineEffect.state = 3; - task->data[0]++; - break; - case 4: - DestroyAnimVisualTask(taskId); - gSprites[task->data[10]].invisible = TRUE; - break; - } -} - -static void AnimTask_DigEndBounceMovementSetInvisible(u8 taskId) -{ - u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - gSprites[spriteId].invisible = TRUE; - gSprites[spriteId].pos2.x = 0; - gSprites[spriteId].pos2.y = 0; - - if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1) - gBattle_BG1_Y = 0; - else - gBattle_BG2_Y = 0; - - DestroyAnimVisualTask(taskId); -} - -void AnimTask_DigUpMovement(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - if (gBattleAnimArgs[0] == FALSE) - task->func = AnimTask_DigSetVisibleUnderground; - else - task->func = AnimTask_DigRiseUpFromHole; - - task->func(taskId); -} - -static void AnimTask_DigSetVisibleUnderground(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); - gSprites[task->data[10]].invisible = FALSE; - gSprites[task->data[10]].pos2.x = 0; - gSprites[task->data[10]].pos2.y = 160 - gSprites[task->data[10]].pos1.y; - task->data[0]++; - break; - case 1: - DestroyAnimVisualTask(taskId); - } -} - -static void AnimTask_DigRiseUpFromHole(u8 taskId) -{ - u8 var0; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); - task->data[11] = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); - if (task->data[11] == 1) - task->data[12] = gBattle_BG1_X; - else - task->data[12] = gBattle_BG2_X; - - var0 = GetBattlerYCoordWithElevation(gBattleAnimAttacker); - task->data[14] = var0 - 32; - task->data[15] = var0 + 32; - task->data[0]++; - break; - case 1: - sub_81150E0(task->data[11], 0, task->data[15]); - task->data[0]++; - break; - case 2: - gSprites[task->data[10]].pos2.y = 96; - task->data[0]++; - break; - case 3: - gSprites[task->data[10]].pos2.y -= 8; - if (gSprites[task->data[10]].pos2.y == 0) - { - gScanlineEffect.state = 3; - task->data[0]++; - } - break; - case 4: - DestroyAnimVisualTask(taskId); - break; - } -} - -static void sub_81150E0(u8 useBG1, s16 y, s16 endY) -{ - s16 bgX; - struct ScanlineEffectParams scanlineParams; - - if (useBG1 == 1) - { - bgX = gBattle_BG1_X; - scanlineParams.dmaDest = ®_BG1HOFS; - } - else - { - bgX = gBattle_BG2_X; - scanlineParams.dmaDest = ®_BG2HOFS; - } - - if (y < 0) - y = 0; - - while (y < endY) - { - gScanlineEffectRegBuffers[0][y] = bgX; - gScanlineEffectRegBuffers[1][y] = bgX; - y++; - } - - while (y < 160) - { - gScanlineEffectRegBuffers[0][y] = bgX + 240; - gScanlineEffectRegBuffers[1][y] = bgX + 240; - y++; - } - - scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; - scanlineParams.initState = 1; - scanlineParams.unused9 = 0; - ScanlineEffect_SetParams(scanlineParams); -} - -// Moves a particle of dirt in a plume of dirt. Used in Fissure and Dig. -// arg 0: which mon (0 = attacker, 1 = target) -// arg 1: which side of mon (0 = left, 1 = right) -// arg 2: target x offset -// arg 3: target y offset -// arg 4: wave amplitude -// arg 5: duration -void AnimDirtPlumeParticle(struct Sprite *sprite) -{ - s8 battler; - s16 xOffset; - - if (gBattleAnimArgs[0] == 0) - battler = gBattleAnimAttacker; - else - battler = gBattleAnimTarget; - - xOffset = 24; - if (gBattleAnimArgs[1] == 1) - { - xOffset *= -1; - gBattleAnimArgs[2] *= -1; - } - - sprite->pos1.x = GetBattlerSpriteCoord(battler, 2) + xOffset; - sprite->pos1.y = GetBattlerYCoordWithElevation(battler) + 30; - sprite->data[0] = gBattleAnimArgs[5]; - sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; - sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[3]; - sprite->data[5] = gBattleAnimArgs[4]; - InitAnimArcTranslation(sprite); - sprite->callback = AnimDirtPlumeParticle_Step; -} - -static void AnimDirtPlumeParticle_Step(struct Sprite *sprite) -{ - if (TranslateAnimHorizontalArc(sprite)) - DestroyAnimSprite(sprite); -} - -// Displays the dirt mound seen in the move Dig for set duration. -// The dirt mound image is too large for a single sprite, so two -// sprites are lined up next to each other. -// arg 0: which mon (0 = attacker, 1 = target) -// arg 1: oam tile num (0 = left half of image, 1 = right half of image) -// arg 2: duration -static void AnimDigDirtMound(struct Sprite *sprite) -{ - s8 battler; - - if (gBattleAnimArgs[0] == 0) - battler = gBattleAnimAttacker; - else - battler = gBattleAnimTarget; - - sprite->pos1.x = GetBattlerSpriteCoord(battler, 0) - 16 + (gBattleAnimArgs[1] * 32); - sprite->pos1.y = GetBattlerYCoordWithElevation(battler) + 32; - sprite->oam.tileNum += gBattleAnimArgs[1] * 8; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - sprite->data[0] = gBattleAnimArgs[2]; - sprite->callback = WaitAnimForDuration; -} - - -#define tState data[0] -#define tDelay data[1] -#define tTimer data[2] -#define tMaxTime data[3] -#define tbattlerSpriteIds(i) data[9 + (i)] -#define tNumBattlers data[13] // AnimTask_ShakeBattlers -#define tInitialX data[13] // AnimTask_ShakeTerrain -#define tHorizOffset data[14] -#define tInitHorizOffset data[15] - -// Shakes battler(s) or the battle terrain back and forth horizontally. Used by e.g. Earthquake, Eruption -// arg0: What to shake. 0-3 for any specific battler, MAX_BATTLERS_COUNT for all battlers, MAX_BATTLERS_COUNT + 1 for the terrain -// arg1: Shake intensity, used to calculate horizontal pixel offset (if 0, use move power instead) -// arg2: Length of time to shake for -void AnimTask_HorizontalShake(u8 taskId) -{ - u16 i; - struct Task *task = &gTasks[taskId]; - - if (gBattleAnimArgs[1] != 0) - task->tHorizOffset = task->tInitHorizOffset = gBattleAnimArgs[1] + 3; - else - task->tHorizOffset = task->tInitHorizOffset = (gAnimMovePower / 10) + 3; - - task->tMaxTime = gBattleAnimArgs[2]; - switch (gBattleAnimArgs[0]) - { - case MAX_BATTLERS_COUNT + 1: // Shake terrain - task->tInitialX = gBattle_BG3_X; - task->func = AnimTask_ShakeTerrain; - break; - case MAX_BATTLERS_COUNT: // Shake all battlers - task->tNumBattlers = 0; - for (i = 0; i < MAX_BATTLERS_COUNT; i++) - { - if (IsBattlerSpriteVisible(i)) - { - task->tbattlerSpriteIds(task->tNumBattlers) = gBattlerSpriteIds[i]; - task->tNumBattlers++; - } - } - task->func = AnimTask_ShakeBattlers; - break; - default: // Shake specific battler - task->tbattlerSpriteIds(0) = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); - if (task->tbattlerSpriteIds(0) == 0xFF) - { - DestroyAnimVisualTask(taskId); - } - else - { - task->tNumBattlers = 1; - task->func = AnimTask_ShakeBattlers; - } - break; - } -} - -static void AnimTask_ShakeTerrain(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->tState) - { - case 0: - if (++task->tDelay > 1) - { - task->tDelay = 0; - if ((task->tTimer & 1) == 0) - gBattle_BG3_X = task->tInitialX + task->tInitHorizOffset; - else - gBattle_BG3_X = task->tInitialX - task->tInitHorizOffset; - - if (++task->tTimer == task->tMaxTime) - { - task->tTimer = 0; - task->tHorizOffset--; - task->tState++; - } - } - break; - case 1: - if (++task->tDelay > 1) - { - task->tDelay = 0; - if ((task->tTimer & 1) == 0) - gBattle_BG3_X = task->tInitialX + task->tHorizOffset; - else - gBattle_BG3_X = task->tInitialX - task->tHorizOffset; - - if (++task->tTimer == 4) - { - task->tTimer = 0; - if (--task->tHorizOffset == 0) - task->tState++; - } - } - break; - case 2: - gBattle_BG3_X = task->tInitialX; - DestroyAnimVisualTask(taskId); - break; - } -} - -static void AnimTask_ShakeBattlers(u8 taskId) -{ - u16 i; - struct Task *task = &gTasks[taskId]; - - switch (task->tState) - { - case 0: - if (++task->tDelay > 1) - { - task->tDelay = 0; - SetBattlersXOffsetForShake(task); - if (++task->tTimer == task->tMaxTime) - { - task->tTimer = 0; - task->tHorizOffset--; - task->tState++; - } - } - break; - case 1: - if (++task->tDelay > 1) - { - task->tDelay = 0; - SetBattlersXOffsetForShake(task); - if (++task->tTimer == 4) - { - task->tTimer = 0; - if (--task->tHorizOffset == 0) - task->tState++; - } - } - break; - case 2: - for (i = 0; i < task->tNumBattlers; i++) - gSprites[task->tbattlerSpriteIds(i)].pos2.x = 0; - - DestroyAnimVisualTask(taskId); - break; - } -} - -static void SetBattlersXOffsetForShake(struct Task *task) -{ - u16 i; - u16 xOffset; - - if ((task->tTimer & 1) == 0) - xOffset = (task->tHorizOffset / 2) + (task->tHorizOffset & 1); - else - xOffset = -(task->tHorizOffset / 2); - - for (i = 0; i < task->tNumBattlers; i++) - { - gSprites[task->tbattlerSpriteIds(i)].pos2.x = xOffset; - } -} - -#undef tState -#undef tDelay -#undef tTimer -#undef tMaxTime -#undef tbattlerSpriteIds -#undef tNumBattlers -#undef tInitialX -#undef tHorizOffset -#undef tInitHorizOffset - -void AnimTask_IsPowerOver99(u8 taskId) -{ - gBattleAnimArgs[15] = gAnimMovePower > 99; - DestroyAnimVisualTask(taskId); -} - -void AnimTask_PositionFissureBgOnBattler(u8 taskId) -{ - struct Task *newTask; - u8 battler = (gBattleAnimArgs[0] & ANIM_TARGET) ? gBattleAnimTarget : gBattleAnimAttacker; - - if (gBattleAnimArgs[0] > ANIM_TARGET) - battler ^= 2; - - newTask = &gTasks[CreateTask(sub_81156D0, gBattleAnimArgs[1])]; - newTask->data[1] = (32 - GetBattlerSpriteCoord(battler, 2)) & 0x1FF; - newTask->data[2] = (64 - GetBattlerSpriteCoord(battler, 3)) & 0xFF; - gBattle_BG3_X = newTask->data[1]; - gBattle_BG3_Y = newTask->data[2]; - newTask->data[3] = gBattleAnimArgs[2]; - DestroyAnimVisualTask(taskId); -} - -static void sub_81156D0(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - if (gBattleAnimArgs[ARG_RET_ID] == task->data[3]) - { - gBattle_BG3_X = 0; - gBattle_BG3_Y = 0; - DestroyTask(taskId); - } - else - { - gBattle_BG3_X = task->data[1]; - gBattle_BG3_Y = task->data[2]; - } -} diff --git a/src/ice.c b/src/ice.c deleted file mode 100644 index e2b0c5287..000000000 --- a/src/ice.c +++ /dev/null @@ -1,1571 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "bg.h" -#include "field_weather.h" -#include "gpu_regs.h" -#include "graphics.h" -#include "main.h" -#include "palette.h" -#include "random.h" -#include "sprite.h" -#include "task.h" -#include "trig.h" -#include "constants/battle_anim.h" -#include "constants/rgb.h" - -struct HailStruct { - s32 x:10; - s32 y:10; - s32 bPosition:8; - s32 unk3:4; -}; - -static void sub_810B6C4(struct Sprite *); -static void sub_810B848(struct Sprite *); -static void AnimIcePunchSwirlingParticle(struct Sprite *); -static void AnimIceBeamParticle(struct Sprite *); -static void AnimIceEffectParticle(struct Sprite *); -static void AnimFlickerIceEffectParticle(struct Sprite *); -static void AnimSwirlingSnowball(struct Sprite *); -static void AnimSwirlingSnowball_Step1(struct Sprite *); -static void AnimSwirlingSnowball_Step2(struct Sprite *); -static void AnimSwirlingSnowball_End(struct Sprite *); -static void AnimMoveParticleBeyondTarget(struct Sprite *); -static void AnimWiggleParticleTowardsTarget(struct Sprite *); -static void AnimWaveFromCenterOfTarget(struct Sprite *); -static void InitSwirlingFogAnim(struct Sprite *); -static void AnimSwirlingFogAnim(struct Sprite *); -static void AnimThrowMistBall(struct Sprite *); -static void InitPoisonGasCloudAnim(struct Sprite *); -static void MovePoisonGasCloud(struct Sprite *); -static void AnimHailBegin(struct Sprite *); -static void AnimHailContinue(struct Sprite *); -static void InitIceBallAnim(struct Sprite *); -static void AnimThrowIceBall(struct Sprite *); -static void InitIceBallParticle(struct Sprite *); -static void AnimIceBallParticle(struct Sprite *); -static void AnimTask_Haze2(u8); -static void AnimTask_OverlayFogTiles(u8); -static void AnimTask_Hail2(u8); -static bool8 GenerateHailParticle(u8 hailStructId, u8 affineAnimNum, u8 taskId, u8 c); - -static const union AnimCmd gUnknown_08595A48[] = -{ - ANIMCMD_FRAME(0, 5, .hFlip = TRUE), - ANIMCMD_FRAME(1, 5, .hFlip = TRUE), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const gUnknown_08595A54[] = -{ - gUnknown_08595A48, -}; - -// Unused -const struct SpriteTemplate gUnknown_08595A58 = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_810B6C4, -}; - -static const union AnimCmd gUnknown_08595A70[] = -{ - ANIMCMD_FRAME(0, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_IceCrystalLarge[] = -{ - ANIMCMD_FRAME(4, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_IceCrystalSmall[] = -{ - ANIMCMD_FRAME(6, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Snowball[] = -{ - ANIMCMD_FRAME(7, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_BlizzardIceCrystal[] = -{ - ANIMCMD_FRAME(8, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_SmallBubblePair[] = -{ - ANIMCMD_FRAME(12, 6), - ANIMCMD_FRAME(13, 6), - ANIMCMD_JUMP(0), -}; - -// Unused -static const union AnimCmd *const gUnknown_08595AA4[] = -{ - gUnknown_08595A70, -}; - -static const union AnimCmd *const sAnims_IceCrystalLarge[] = -{ - sAnim_IceCrystalLarge, -}; - -static const union AnimCmd *const sAnims_IceCrystalSmall[] = -{ - sAnim_IceCrystalSmall, -}; - -static const union AnimCmd *const sAnims_Snowball[] = -{ - sAnim_Snowball, -}; - -static const union AnimCmd *const sAnims_BlizzardIceCrystal[] = -{ - sAnim_BlizzardIceCrystal, -}; - -const union AnimCmd *const gAnims_SmallBubblePair[] = -{ - sAnim_SmallBubblePair, -}; - -static const union AffineAnimCmd sAffineAnim_IceCrystalSpiralInwardLarge[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 40, 1), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd *const sAffineAnims_IceCrystalSpiralInwardLarge[] = -{ - sAffineAnim_IceCrystalSpiralInwardLarge, -}; - -const struct SpriteTemplate gIceCrystalSpiralInwardLarge = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineDouble_ObjBlend_8x16, - .anims = sAnims_IceCrystalLarge, - .images = NULL, - .affineAnims = sAffineAnims_IceCrystalSpiralInwardLarge, - .callback = AnimIcePunchSwirlingParticle, -}; - -const struct SpriteTemplate gIceCrystalSpiralInwardSmall = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineOff_ObjBlend_8x8, - .anims = sAnims_IceCrystalSmall, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimIcePunchSwirlingParticle, -}; - -static const union AffineAnimCmd sAffineAnim_IceBeamInnerCrystal[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 10, 1), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd *const sAffineAnims_IceBeamInnerCrystal[] = -{ - sAffineAnim_IceBeamInnerCrystal, -}; - -const struct SpriteTemplate gIceBeamInnerCrystalSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineNormal_ObjBlend_8x16, - .anims = sAnims_IceCrystalLarge, - .images = NULL, - .affineAnims = sAffineAnims_IceBeamInnerCrystal, - .callback = AnimIceBeamParticle, -}; - -const struct SpriteTemplate gIceBeamOuterCrystalSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineOff_ObjBlend_8x8, - .anims = sAnims_IceCrystalSmall, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimIceBeamParticle, -}; - -static const union AffineAnimCmd sAffineAnim_IceCrystalHit[] = -{ - AFFINEANIMCMD_FRAME(0xCE, 0xCE, 0, 0), - AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 10), - AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 6), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_IceCrystalHit[] = -{ - sAffineAnim_IceCrystalHit, -}; - -const struct SpriteTemplate gIceCrystalHitLargeSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineNormal_ObjBlend_8x16, - .anims = sAnims_IceCrystalLarge, - .images = NULL, - .affineAnims = sAffineAnims_IceCrystalHit, - .callback = AnimIceEffectParticle, -}; - -const struct SpriteTemplate gIceCrystalHitSmallSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineNormal_ObjBlend_8x8, - .anims = sAnims_IceCrystalSmall, - .images = NULL, - .affineAnims = sAffineAnims_IceCrystalHit, - .callback = AnimIceEffectParticle, -}; - -const struct SpriteTemplate gSwirlingSnowballSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = sAnims_Snowball, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSwirlingSnowball, -}; - -const struct SpriteTemplate gBlizzardIceCrystalSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = sAnims_BlizzardIceCrystal, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimMoveParticleBeyondTarget, -}; - -const struct SpriteTemplate gPowderSnowSnowballSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = sAnims_Snowball, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimMoveParticleBeyondTarget, -}; - -static const union AnimCmd sAnim_IceGroundSpike[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(2, 5), - ANIMCMD_FRAME(4, 5), - ANIMCMD_FRAME(6, 5), - ANIMCMD_FRAME(4, 5), - ANIMCMD_FRAME(2, 5), - ANIMCMD_FRAME(0, 5), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_IceGroundSpike[] = -{ - sAnim_IceGroundSpike, -}; - -const struct SpriteTemplate gIceGroundSpikeSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_SPIKES, - .paletteTag = ANIM_TAG_ICE_SPIKES, - .oam = &gOamData_AffineOff_ObjBlend_8x16, - .anims = sAnims_IceGroundSpike, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimWaveFromCenterOfTarget, -}; - -static const union AnimCmd sAnim_Cloud[] = -{ - ANIMCMD_FRAME(0, 8), - ANIMCMD_FRAME(8, 8), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_Cloud[] = -{ - sAnim_Cloud, -}; - -const struct SpriteTemplate gMistCloudSpriteTemplate = -{ - .tileTag = ANIM_TAG_MIST_CLOUD, - .paletteTag = ANIM_TAG_MIST_CLOUD, - .oam = &gOamData_AffineOff_ObjBlend_32x16, - .anims = sAnims_Cloud, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = InitSwirlingFogAnim, -}; - -const struct SpriteTemplate gSmogCloudSpriteTemplate = -{ - .tileTag = ANIM_TAG_PURPLE_GAS_CLOUD, - .paletteTag = ANIM_TAG_PURPLE_GAS_CLOUD, - .oam = &gOamData_AffineOff_ObjBlend_32x16, - .anims = sAnims_Cloud, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = InitSwirlingFogAnim, -}; - -static const u8 sUnknown_08595C5C[] = -{ - 0, 1, 2, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 6, 7, 8, 8, 8, 9, -}; - -const struct SpriteTemplate gMistBallSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_BUBBLES, - .paletteTag = ANIM_TAG_SMALL_BUBBLES, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimThrowMistBall, -}; - -static const u8 sUnknown_08595C88[] = -{ - 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, -}; - -const struct SpriteTemplate gPoisonGasCloudSpriteTemplate = -{ - .tileTag = ANIM_TAG_PURPLE_GAS_CLOUD, - .paletteTag = ANIM_TAG_PURPLE_GAS_CLOUD, - .oam = &gOamData_AffineOff_ObjBlend_32x16, - .anims = sAnims_Cloud, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = InitPoisonGasCloudAnim, -}; - -static const struct HailStruct sHailCoordData[] = -{ - {.x = 100, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 2}, - {.x = 85, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 0}, - {.x = 242, .y = 120, .bPosition = B_POSITION_OPPONENT_LEFT, .unk3 = 1}, - {.x = 66, .y = 120, .bPosition = B_POSITION_PLAYER_RIGHT, .unk3 = 1}, - {.x = 182, .y = 120, .bPosition = B_POSITION_OPPONENT_RIGHT, .unk3 = 0}, - {.x = 60, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 2}, - {.x = 214, .y = 120, .bPosition = B_POSITION_OPPONENT_LEFT, .unk3 = 0}, - {.x = 113, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 1}, - {.x = 210, .y = 120, .bPosition = B_POSITION_OPPONENT_RIGHT, .unk3 = 1}, - {.x = 38, .y = 120, .bPosition = B_POSITION_PLAYER_RIGHT, .unk3 = 0}, -}; - -static const union AffineAnimCmd sAffineAnim_HailParticle_0[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_HailParticle_1[] = -{ - AFFINEANIMCMD_FRAME(0xF0, 0xF0, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_HailParticle_2[] = -{ - AFFINEANIMCMD_FRAME(0xE0, 0xE0, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_WeatherBallIceDown[] = -{ - AFFINEANIMCMD_FRAME(0x150, 0x150, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_HailParticle[] = -{ - sAffineAnim_HailParticle_0, - sAffineAnim_HailParticle_1, - sAffineAnim_HailParticle_2, -}; - -static const union AffineAnimCmd *const sAffineAnims_WeatherBallIceDown[] = -{ - sAffineAnim_WeatherBallIceDown, -}; - -const struct SpriteTemplate gHailParticleSpriteTemplate = -{ - .tileTag = ANIM_TAG_HAIL, - .paletteTag = ANIM_TAG_HAIL, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_HailParticle, - .callback = AnimHailBegin, -}; - -const struct SpriteTemplate gWeatherBallIceDownSpriteTemplate = -{ - .tileTag = ANIM_TAG_HAIL, - .paletteTag = ANIM_TAG_HAIL, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_WeatherBallIceDown, - .callback = AnimWeatherBallDown, -}; - -static const union AnimCmd sAnim_IceBallChunk_0[] = -{ - ANIMCMD_FRAME(0, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_IceBallChunk_1[] = -{ - ANIMCMD_FRAME(16, 4), - ANIMCMD_FRAME(32, 4), - ANIMCMD_FRAME(48, 4), - ANIMCMD_FRAME(64, 4), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_IceBallChunk[] = -{ - sAnim_IceBallChunk_0, - sAnim_IceBallChunk_1, -}; - -static const union AffineAnimCmd sAffineAnim_IceBallChunk_0[] = -{ - AFFINEANIMCMD_FRAME(0xE0, 0xE0, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_IceBallChunk_1[] = -{ - AFFINEANIMCMD_FRAME(0x118, 0x118, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_IceBallChunk_2[] = -{ - AFFINEANIMCMD_FRAME(0x150, 0x150, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_IceBallChunk_3[] = -{ - AFFINEANIMCMD_FRAME(0x180, 0x180, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_IceBallChunk_4[] = -{ - AFFINEANIMCMD_FRAME(0x1C0, 0x1C0, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_IceBallChunk[] = -{ - sAffineAnim_IceBallChunk_0, - sAffineAnim_IceBallChunk_1, - sAffineAnim_IceBallChunk_2, - sAffineAnim_IceBallChunk_3, - sAffineAnim_IceBallChunk_4, -}; - -const struct SpriteTemplate gIceBallChunkSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CHUNK, - .paletteTag = ANIM_TAG_ICE_CHUNK, - .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_IceBallChunk, - .images = NULL, - .affineAnims = sAffineAnims_IceBallChunk, - .callback = InitIceBallAnim, -}; - -const struct SpriteTemplate gIceBallImpactShardSpriteTemplate = -{ - .tileTag = ANIM_TAG_ICE_CRYSTALS, - .paletteTag = ANIM_TAG_ICE_CRYSTALS, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = sAnims_IceCrystalSmall, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = InitIceBallParticle, -}; - -// Unused -static void sub_810B6C4(struct Sprite *sprite) -{ - s16 targetX, targetY, attackerX, attackerY; - - sprite->oam.tileNum += 7; - targetX = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - targetY = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - attackerX = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - attackerY = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[1] = gBattleAnimArgs[0] + attackerX; - sprite->data[2] = gBattleAnimArgs[2] + targetX; - sprite->data[3] = gBattleAnimArgs[1] + attackerY; - sprite->data[4] = gBattleAnimArgs[3] + targetY; - sub_80A64EC(sprite); - - for (;(targetX >= -32 && targetX <= 272) && (targetY >= -32 && targetY <= 192); - targetX += sprite->data[1], targetY += sprite->data[2]) - ; - - sprite->data[1] = -sprite->data[1]; - sprite->data[2] = -sprite->data[2]; - for (;(attackerX >= -32 && attackerX <= 272) && (attackerY >= -32 && attackerY <= 192); - attackerX += sprite->data[1], attackerY += sprite->data[2]) - ; - - sprite->pos1.x = attackerX; - sprite->pos1.y = attackerY; - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[1] = attackerX; - sprite->data[2] = targetX; - sprite->data[3] = attackerY; - sprite->data[4] = targetY; - sub_80A64EC(sprite); - sprite->data[3] = gBattleAnimArgs[5]; - sprite->data[4] = gBattleAnimArgs[6]; - sprite->callback = sub_810B848; -} - -static void sub_810B848(struct Sprite *sprite) -{ - if (sprite->data[0] != 0) - { - sprite->data[5] += sprite->data[1]; - sprite->data[6] += sprite->data[2]; - sprite->pos2.x = sprite->data[5]; - sprite->pos2.y = sprite->data[6]; - sprite->pos2.x += Sin(sprite->data[7], sprite->data[3]); - sprite->pos2.y += Sin(sprite->data[7], sprite->data[3]); - sprite->data[7] = (sprite->data[7] + sprite->data[4]) & 0xFF; - sprite->data[0]--; - } - else - { - DestroyAnimSprite(sprite); - } -} - -// Animates the swirling ice crystals in Ice Punch. -// arg 0: initial position angle around circle (0-256) -static void AnimIcePunchSwirlingParticle(struct Sprite *sprite) -{ - sprite->data[0] = gBattleAnimArgs[0]; - sprite->data[1] = 60; - sprite->data[2] = 9; - sprite->data[3] = 30; - sprite->data[4] = -512; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - sprite->callback = TranslateSpriteInGrowingCircleOverDuration; - sprite->callback(sprite); -} - -// Animates the ice particles in Ice Beam. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: target x offset -// arg 3: target y offset -// arg 4: duration -static void AnimIceBeamParticle(struct Sprite *sprite) -{ - InitSpritePosToAnimAttacker(sprite, TRUE); - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - sprite->data[2] -= gBattleAnimArgs[2]; - else - sprite->data[2] += gBattleAnimArgs[2]; - - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; - sprite->data[0] = gBattleAnimArgs[4]; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - sprite->callback = StartAnimLinearTranslation; -} - -// Animates the ice crystals at the end of Ice Punch, Ice Beam, Tri Attack, -// Weather Ball (Hail), Blizzard, and Powder Snow. -// arg 0: target x offset -// arg 1: target y offset -// arg 2: ??? unknown boolean -static void AnimIceEffectParticle(struct Sprite *sprite) -{ - if (gBattleAnimArgs[2] == 0) - { - InitSpritePosToAnimTarget(sprite, TRUE); - } - else - { - SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->pos1.x, &sprite->pos1.y); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - } - - StoreSpriteCallbackInData6(sprite, AnimFlickerIceEffectParticle); - sprite->callback = RunStoredCallbackWhenAffineAnimEnds; -} - -static void AnimFlickerIceEffectParticle(struct Sprite *sprite) -{ - sprite->invisible ^= 1; - sprite->data[0] += 1; - if (sprite->data[0] == 20) - DestroySpriteAndMatrix(sprite); -} - -// Animates the small snowballs that swirl around the target in Blizzard and Icy Wind. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: target x offset -// arg 3: target y offset -// arg 4: particle speed -// arg 5: multiple targets? (boolean) -static void AnimSwirlingSnowball(struct Sprite *sprite) -{ - int i; - s16 tempDataHolder[8]; - - InitSpritePosToAnimAttacker(sprite, TRUE); - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[1] = sprite->pos1.x; - sprite->data[3] = sprite->pos1.y; - - if (!gBattleAnimArgs[5]) - { - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; - } - else - { - SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); - } - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - sprite->data[2] -= gBattleAnimArgs[2]; - else - sprite->data[2] += gBattleAnimArgs[2]; - - for (i = 0; i < 8; i++) - tempDataHolder[i] = sprite->data[i]; - - InitAnimFastLinearTranslationWithSpeed(sprite); - sprite->data[1] ^= 1; - sprite->data[2] ^= 1; - - while (1) - { - sprite->data[0] = 1; - AnimFastTranslateLinear(sprite); - - if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 - || sprite->pos1.y + sprite->pos2.y > 160 - || sprite->pos1.y + sprite->pos2.y < -16) - break; - } - - sprite->pos1.x += sprite->pos2.x; - sprite->pos1.y += sprite->pos2.y; - sprite->pos2.y = 0; - sprite->pos2.x = 0; - - for (i = 0; i < 8; i++) - sprite->data[i] = tempDataHolder[i]; - - sprite->callback = sub_80A718C; - StoreSpriteCallbackInData6(sprite, AnimSwirlingSnowball_Step1); -} - -static void AnimSwirlingSnowball_Step1(struct Sprite *sprite) -{ - s16 tempVar; - - sprite->pos1.x += sprite->pos2.x; - sprite->pos1.y += sprite->pos2.y; - sprite->pos2.y = 0; - sprite->pos2.x = 0; - sprite->data[0] = 128; - - tempVar = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 20 : -20; - - sprite->data[3] = Sin(sprite->data[0], tempVar); - sprite->data[4] = Cos(sprite->data[0], 0xF); - sprite->data[5] = 0; - sprite->callback = AnimSwirlingSnowball_Step2; - sprite->callback(sprite); -} - -static void AnimSwirlingSnowball_Step2(struct Sprite *sprite) -{ - s16 tempVar; - tempVar = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 20 : -20; - - if (sprite->data[5] <= 31) - { - sprite->pos2.x = Sin(sprite->data[0], tempVar) - sprite->data[3]; - sprite->pos2.y = Cos(sprite->data[0], 15) - sprite->data[4]; - sprite->data[0] = (sprite->data[0] + 16) & 0xFF; - sprite->data[5] += 1; - } - else - { - sprite->pos1.x += sprite->pos2.x; - sprite->pos1.y += sprite->pos2.y; - sprite->pos2.y = 0; - sprite->pos2.x = 0; - sprite->data[4] = 0; - sprite->data[3] = 0; - sprite->callback = AnimSwirlingSnowball_End; - } -} - -static void AnimSwirlingSnowball_End(struct Sprite *sprite) -{ - sprite->data[0] = 1; - AnimFastTranslateLinear(sprite); - - if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 - || sprite->pos1.y + sprite->pos2.y > 256 - || sprite->pos1.y + sprite->pos2.y < -16) - DestroyAnimSprite(sprite); -} - -// Moves particles towards the target mon and off the screen. Used to animate -// the large snowballs in Blizzard and the small snowballs in Powder Snow. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: target x offset -// arg 3: target y offset -// arg 4: speed -// arg 5: wave amplitude -// arg 6: wave frequency -// arg 7: multiple targets? (boolean) -static void AnimMoveParticleBeyondTarget(struct Sprite *sprite) -{ - int i; - s16 tempDataHolder[8]; - - InitSpritePosToAnimAttacker(sprite, TRUE); - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[1] = sprite->pos1.x; - sprite->data[3] = sprite->pos1.y; - - if (!gBattleAnimArgs[ARG_RET_ID]) - { - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - } - else - { - SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); - } - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - sprite->data[2] -= gBattleAnimArgs[2]; - else - sprite->data[2] += gBattleAnimArgs[2]; - - sprite->data[4] += gBattleAnimArgs[3]; - InitAnimFastLinearTranslationWithSpeed(sprite); - for (i = 0; i < 8; i++) - tempDataHolder[i] = sprite->data[i]; - - sprite->data[1] ^= 1; - sprite->data[2] ^= 1; - - while (1) - { - sprite->data[0] = 1; - AnimFastTranslateLinear(sprite); - if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 - || sprite->pos1.y + sprite->pos2.y > 160 - || sprite->pos1.y + sprite->pos2.y < -16) - break; - } - - sprite->pos1.x += sprite->pos2.x; - sprite->pos1.y += sprite->pos2.y; - sprite->pos2.y = 0; - sprite->pos2.x = 0; - - for (i = 0; i < 8; i++) - sprite->data[i] = tempDataHolder[i]; - - sprite->data[5] = gBattleAnimArgs[5]; - sprite->data[6] = gBattleAnimArgs[6]; - sprite->callback = AnimWiggleParticleTowardsTarget; -} - -// Moves particles in a sine wave towards the target. -static void AnimWiggleParticleTowardsTarget(struct Sprite *sprite) -{ - AnimFastTranslateLinear(sprite); - if (sprite->data[0] == 0) - sprite->data[0] = 1; - - sprite->pos2.y += Sin(sprite->data[7], sprite->data[5]); - sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; - if (sprite->data[0] == 1) - { - if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 - || sprite->pos1.y + sprite->pos2.y > 160 - || sprite->pos1.y + sprite->pos2.y < -16) - DestroyAnimSprite(sprite); - } -} - -// Animates the ice pilar wave used by Icy Wind. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: ??? unknown boolean -static void AnimWaveFromCenterOfTarget(struct Sprite *sprite) -{ - if (sprite->data[0] == 0) - { - if (gBattleAnimArgs[2] == 0) - { - InitSpritePosToAnimTarget(sprite, FALSE); - } - else - { - SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - } - - sprite->data[0]++; - } - else - { - if (sprite->animEnded) - DestroyAnimSprite(sprite); - } -} - -// Animates the fog that swirls around the mon in Mist and Smog. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: change in y pixels per rotation -// arg 3: duration -// arg 4: animate on opponent? (boolean) -// arg 5: ??? unknown boolean -static void InitSwirlingFogAnim(struct Sprite *sprite) -{ - s16 tempVar; - u8 battler; - - if (gBattleAnimArgs[4] == 0) - { - if (gBattleAnimArgs[5] == 0) - { - InitSpritePosToAnimAttacker(sprite, FALSE); - } - else - { - SetAverageBattlerPositions(gBattleAnimAttacker, 0, &sprite->pos1.x, &sprite->pos1.y); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - sprite->pos1.x -= gBattleAnimArgs[0]; - else - sprite->pos1.x += gBattleAnimArgs[0]; - - sprite->pos1.y += gBattleAnimArgs[1]; - } - - battler = gBattleAnimAttacker; - } - else - { - if (gBattleAnimArgs[5] == 0) - { - InitSpritePosToAnimTarget(sprite, FALSE); - } - else - { - SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); - if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER) - sprite->pos1.x -= gBattleAnimArgs[0]; - else - sprite->pos1.x += gBattleAnimArgs[0]; - - sprite->pos1.y += gBattleAnimArgs[1]; - } - - battler = gBattleAnimTarget; - } - - sprite->data[7] = battler; - if (gBattleAnimArgs[5] == 0 || !IsDoubleBattle()) - tempVar = 0x20; - else - tempVar = 0x40; - - sprite->data[6] = tempVar; - if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) - sprite->pos1.y += 8; - - sprite->data[0] = gBattleAnimArgs[3]; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = sprite->pos1.x; - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[2]; - - InitAnimLinearTranslation(sprite); - - sprite->data[5] = 64; - sprite->callback = AnimSwirlingFogAnim; - sprite->callback(sprite); -} - -// Animates swirling fog initialized by InitSwirlingFogAnim. -static void AnimSwirlingFogAnim(struct Sprite *sprite) -{ - if (!AnimTranslateLinear(sprite)) - { - sprite->pos2.x += Sin(sprite->data[5], sprite->data[6]); - sprite->pos2.y += Cos(sprite->data[5], -6); - - if ((u16)(sprite->data[5] - 64) <= 0x7F) - sprite->oam.priority = GetBattlerSpriteBGPriority(sprite->data[7]); - else - sprite->oam.priority = GetBattlerSpriteBGPriority(sprite->data[7]) + 1; - - sprite->data[5] = (sprite->data[5] + 3) & 0xFF; - } - else - { - DestroyAnimSprite(sprite); - } -} - -// Adds moving foggy overlay. Used by Haze. -void AnimTask_HazeScrollingFog(u8 taskId) -{ - struct BattleAnimBgData animBg; - - 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, 0); - - if (!IsContest()) - SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); - - gBattle_BG1_X = 0; - gBattle_BG1_Y = 0; - SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); - SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); - - sub_80A6B30(&animBg); - LoadBgTiles(animBg.bgId, gWeatherFogHorizontalTiles, 0x800, animBg.tilesOffset); - AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimFogTilemap, 0); - LoadPalette(&gUnknown_083970E8, animBg.paletteId * 16, 32); - - gTasks[taskId].func = AnimTask_Haze2; -} - -static void AnimTask_Haze2(u8 taskId) -{ - struct BattleAnimBgData animBg; - - gBattle_BG1_X += -1; - gBattle_BG1_Y += 0; - - switch (gTasks[taskId].data[12]) - { - case 0: - if (++gTasks[taskId].data[10] == 4) - { - gTasks[taskId].data[10] = 0; - gTasks[taskId].data[9]++; - gTasks[taskId].data[11] = sUnknown_08595C5C[gTasks[taskId].data[9]]; - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); - if (gTasks[taskId].data[11] == 9) - { - gTasks[taskId].data[12]++; - gTasks[taskId].data[11] = 0; - } - } - break; - case 1: - if (++gTasks[taskId].data[11] == 0x51) - { - gTasks[taskId].data[11] = 9; - gTasks[taskId].data[12]++; - } - break; - case 2: - if (++gTasks[taskId].data[10] == 4) - { - gTasks[taskId].data[10] = 0; - gTasks[taskId].data[11]--; - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); - if (gTasks[taskId].data[11] == 0) - { - gTasks[taskId].data[12]++; - gTasks[taskId].data[11] = 0; - } - } - break; - case 3: - sub_80A6B30(&animBg); - sub_80A6C68(1); - sub_80A6C68(2); - - gTasks[taskId].data[12]++; - - // fall through - case 4: - if (!IsContest()) - SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); - - gBattle_BG1_X = 0; - gBattle_BG1_Y = 0; - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); - SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); - DestroyAnimVisualTask(taskId); - break; - } -} - -// Throws the ball in Mist Ball. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: targey x offset -// arg 3: target y offset -// arg 4: duration -// arg 5: ??? unknown (seems to vibrate target mon somehow) -static void AnimThrowMistBall(struct Sprite *sprite) -{ - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - sprite->callback = TranslateAnimSpriteToTargetMonLocation; -} - -// Displays misty background in Mist Ball. -void AnimTask_LoadMistTiles(u8 taskId) -{ - struct BattleAnimBgData animBg; - - 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, 0); - - if (!IsContest()) - SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); - - gBattle_BG1_X = 0; - gBattle_BG1_Y = 0; - SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); - SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); - - sub_80A6B30(&animBg); - LoadBgTiles(animBg.bgId, gWeatherFogHorizontalTiles, 0x800, animBg.tilesOffset); - AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimFogTilemap, 0); - LoadPalette(&gUnknown_083970E8, animBg.paletteId * 16, 32); - - gTasks[taskId].data[15] = -1; - gTasks[taskId].func = AnimTask_OverlayFogTiles; -} - -static void AnimTask_OverlayFogTiles(u8 taskId) -{ - struct BattleAnimBgData animBg; - - gBattle_BG1_X += gTasks[taskId].data[15]; - gBattle_BG1_Y += 0; - - switch (gTasks[taskId].data[12]) - { - case 0: - gTasks[taskId].data[9] += 1; - gTasks[taskId].data[11] = sUnknown_08595C88[gTasks[taskId].data[9]]; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 17 - gTasks[taskId].data[11])); - if (gTasks[taskId].data[11] == 5) - { - gTasks[taskId].data[12]++; - gTasks[taskId].data[11] = 0; - } - break; - case 1: - if (++gTasks[taskId].data[11] == 0x51) - { - gTasks[taskId].data[11] = 5; - gTasks[taskId].data[12]++; - } - break; - case 2: - if (++gTasks[taskId].data[10] == 4) - { - gTasks[taskId].data[10] = 0; - gTasks[taskId].data[11] -= 1; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); - if (gTasks[taskId].data[11] == 0) - { - gTasks[taskId].data[12]++; - gTasks[taskId].data[11] = 0; - } - } - break; - case 3: - sub_80A6B30(&animBg); - sub_80A6C68(1); - sub_80A6C68(2); - - gTasks[taskId].data[12]++; - - // fall through - case 4: - if (!IsContest()) - SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); - - gBattle_BG1_X = 0; - gBattle_BG1_Y = 0; - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); - SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); - DestroyAnimVisualTask(taskId); - break; - } -} - -// Initializes gas clouds in the Poison Gas animation. -// arg 0: duration -// arg 1: ? target x offset -// arg 2: ? target y offset -// arg 3: ? swirl start x -// arg 4: ? swirl start y -// arg 5: ??? unknown -// arg 6: ??? unknown -// arg 7: ??? unknown boolean -static void InitPoisonGasCloudAnim(struct Sprite *sprite) -{ - sprite->data[0] = gBattleAnimArgs[0]; - - if (GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) < GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2)) - sprite->data[7] = 0x8000; - - if ((gBattlerPositions[gBattleAnimTarget] & BIT_SIDE) == B_SIDE_PLAYER) - { - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - - if ((sprite->data[7] & 0x8000) && (gBattlerPositions[gBattleAnimAttacker] & BIT_SIDE) == B_SIDE_PLAYER) - sprite->subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority + 1; - - sprite->data[6] = 1; - } - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - if (gBattleAnimArgs[ARG_RET_ID]) - { - sprite->data[1] = sprite->pos1.x + gBattleAnimArgs[1]; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[3]; - sprite->data[3] = sprite->pos1.y + gBattleAnimArgs[2]; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[4]; - sprite->data[7] |= GetBattlerSpriteBGPriority(gBattleAnimTarget) << 8; - } - else - { - sprite->data[1] = sprite->pos1.x + gBattleAnimArgs[1]; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X) + gBattleAnimArgs[3]; - sprite->data[3] = sprite->pos1.y + gBattleAnimArgs[2]; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + gBattleAnimArgs[4]; - sprite->data[7] |= GetBattlerSpriteBGPriority(gBattleAnimTarget) << 8; - } - - if (IsContest()) - { - sprite->data[6] = 1; - sprite->subpriority = 0x80; - } - - InitAnimLinearTranslation(sprite); - sprite->callback = MovePoisonGasCloud; -} - -static void MovePoisonGasCloud(struct Sprite *sprite) -{ - int value; - - switch (sprite->data[7] & 0xFF) - { - case 0: - AnimTranslateLinear(sprite); - value = gSineTable[sprite->data[5]]; - sprite->pos2.x += value >> 4; - if (sprite->data[6]) - sprite->data[5] = (sprite->data[5] - 8) & 0xFF; - else - sprite->data[5] = (sprite->data[5] + 8) & 0xFF; - - if (sprite->data[0] <= 0) - { - sprite->data[0] = 80; - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X); - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = sprite->pos1.x; - sprite->pos1.y += sprite->pos2.y; - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = sprite->pos1.y + 29; - sprite->data[7]++; - if (IsContest()) - sprite->data[5] = 80; - else if (GET_BATTLER_SIDE2(gBattleAnimTarget) != B_SIDE_PLAYER) - sprite->data[5] = 204; - else - sprite->data[5] = 80; - - sprite->pos2.y = 0; - value = gSineTable[sprite->data[5]]; - sprite->pos2.x = value >> 3; - sprite->data[5] = (sprite->data[5] + 2) & 0xFF; - InitAnimLinearTranslation(sprite); - } - break; - case 1: - AnimTranslateLinear(sprite); - value = gSineTable[sprite->data[5]]; - sprite->pos2.x += value >> 3; - sprite->pos2.y += (gSineTable[sprite->data[5] + 0x40] * -3) >> 8; - if (!IsContest()) - { - u16 var0 = sprite->data[5] - 0x40; - if (var0 <= 0x7F) - sprite->oam.priority = sprite->data[7] >> 8; - else - sprite->oam.priority = (sprite->data[7] >> 8) + 1; - - sprite->data[5] = (sprite->data[5] + 4) & 0xFF; - } - else - { - u16 var0 = sprite->data[5] - 0x40; - if (var0 <= 0x7F) - sprite->subpriority = 128; - else - sprite->subpriority = 140; - - sprite->data[5] = (sprite->data[5] - 4) & 0xFF; - } - - if (sprite->data[0] <= 0) - { - sprite->data[0] = 0x300; - sprite->data[1] = sprite->pos1.x += sprite->pos2.x; - sprite->data[3] = sprite->pos1.y += sprite->pos2.y; - sprite->data[4] = sprite->pos1.y + 4; - if (IsContest()) - sprite->data[2] = -0x10; - else if (GET_BATTLER_SIDE2(gBattleAnimTarget) != B_SIDE_PLAYER) - sprite->data[2] = 0x100; - else - sprite->data[2] = -0x10; - - sprite->data[7]++; - sprite->pos2.x = sprite->pos2.y = 0; - sub_80A6FD4(sprite); - } - break; - case 2: - if (AnimTranslateLinear(sprite)) - { - if (sprite->oam.affineMode & 1) - { - FreeOamMatrix(sprite->oam.matrixNum); - sprite->oam.affineMode = ST_OAM_AFFINE_OFF; - } - - DestroySprite(sprite); - gAnimVisualTaskCount--; - } - break; - } -} - -void AnimTask_Hail(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - task->func = AnimTask_Hail2; -} - -static void AnimTask_Hail2(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - switch (task->data[0]) - { - case 0: - if (++task->data[4] > 2) - { - task->data[4] = 0; - task->data[5] = 0; - task->data[2] = 0; - task->data[0]++; - } - break; - case 1: - if (task->data[5] == 0) - { - if (GenerateHailParticle(task->data[3], task->data[2], taskId, 1)) - task->data[1]++; - - if (++task->data[2] == 3) - { - if (++task->data[3] == 10) - task->data[0]++; - else - task->data[0]--; - } - else - { - task->data[5] = 1; - } - - } - else - { - task->data[5]--; - } - break; - case 2: - if (task->data[1] == 0) - DestroyAnimVisualTask(taskId); - break; - } -} - -static bool8 GenerateHailParticle(u8 hailStructId, u8 affineAnimNum, u8 taskId, u8 c) -{ - u8 id; - s16 battlerX, battlerY; - s16 spriteX; - bool8 possibleBool = FALSE; - s8 unk = sHailCoordData[hailStructId].unk3; - - if (unk != 2) - { - id = GetBattlerAtPosition(sHailCoordData[hailStructId].bPosition); - if (IsBattlerSpriteVisible(id)) - { - possibleBool = TRUE; - battlerX = GetBattlerSpriteCoord(id, BATTLER_COORD_X_2); - battlerY = GetBattlerSpriteCoord(id, BATTLER_COORD_Y_PIC_OFFSET); - switch (unk) - { - case 0: - battlerX -= GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_WIDTH) / 6; - battlerY -= GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_HEIGHT) / 6; - break; - case 1: - battlerX += GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_WIDTH) / 6; - battlerY += GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_HEIGHT) / 6; - break; - } - } - else - { - battlerX = (sHailCoordData[hailStructId].x); - battlerY = (sHailCoordData[hailStructId].y); - } - } - else - { - battlerX = (sHailCoordData[hailStructId].x); - battlerY = (sHailCoordData[hailStructId].y); - } - spriteX = battlerX - ((battlerY + 8) / 2); - id = CreateSprite(&gHailParticleSpriteTemplate, spriteX, -8, 18); - if (id == MAX_SPRITES) - { - return FALSE; - } - else - { - StartSpriteAffineAnim(&gSprites[id], affineAnimNum); - gSprites[id].data[0] = possibleBool; - gSprites[id].data[3] = battlerX; - gSprites[id].data[4] = battlerY; - gSprites[id].data[5] = affineAnimNum; - gSprites[id].data[6] = taskId; - gSprites[id].data[7] = c; - return TRUE; - } -} - -static void AnimHailBegin(struct Sprite *sprite) -{ - u8 spriteId; - - sprite->pos1.x += 4; - sprite->pos1.y += 8; - - if (sprite->pos1.x < sprite->data[3] && sprite->pos1.y < sprite->data[4]) - return; - - if (sprite->data[0] == 1 && sprite->data[5] == 0) - { - spriteId = CreateSprite(&gIceCrystalHitLargeSpriteTemplate, - sprite->data[3], sprite->data[4], sprite->subpriority); - - sprite->data[0] = spriteId; - if (spriteId != 64) - { - gSprites[sprite->data[0]].callback = AnimHailContinue; - gSprites[sprite->data[0]].data[6] = sprite->data[6]; - gSprites[sprite->data[0]].data[7] = sprite->data[7]; - } - - FreeOamMatrix(sprite->oam.matrixNum); - DestroySprite(sprite); - } - else - { - gTasks[sprite->data[6]].data[sprite->data[7]]--; - FreeOamMatrix(sprite->oam.matrixNum); - DestroySprite(sprite); - } -} - -static void AnimHailContinue(struct Sprite *sprite) -{ - if (++sprite->data[0] == 20) - { - gTasks[sprite->data[6]].data[sprite->data[7]]--; - FreeOamMatrix(sprite->oam.matrixNum); - DestroySprite(sprite); - } -} - -// Initializes the animation for Ice Ball. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: target x offset -// arg 3: target y offset -// arg 4: duration -// arg 5: arc height (negative) -static void InitIceBallAnim(struct Sprite *sprite) -{ - u8 animNum = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer - 1; - - if (animNum > 4) - animNum = 4; - - StartSpriteAffineAnim(sprite, animNum); - InitSpritePosToAnimAttacker(sprite, 1); - - sprite->data[0] = gBattleAnimArgs[4]; - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - gBattleAnimArgs[2] = -gBattleAnimArgs[2]; - - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; - sprite->data[5] = gBattleAnimArgs[5]; - - InitAnimArcTranslation(sprite); - - sprite->callback = AnimThrowIceBall; -} - -// Throws the ball of ice in Ice Ball. -static void AnimThrowIceBall(struct Sprite *sprite) -{ - if (!TranslateAnimHorizontalArc(sprite)) - return; - - StartSpriteAnim(sprite, 1); - sprite->callback = RunStoredCallbackWhenAnimEnds; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Initializes the particles that scatter at the end of the Ice Ball animation. -static void InitIceBallParticle(struct Sprite *sprite) -{ - s16 randA, randB; - - sprite->oam.tileNum += 8; - InitSpritePosToAnimTarget(sprite, TRUE); - - randA = (Random2() & 0xFF) + 256; - randB = Random2() & 0x1FF; - - if (randB > 0xFF) - randB = 256 - randB; - - sprite->data[1] = randA; - sprite->data[2] = randB; - sprite->callback = AnimIceBallParticle; -} - -// Animates the particles created by InitIceBallParticle. -static void AnimIceBallParticle(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_GetIceBallCounter(u8 taskId) -{ - u8 arg = gBattleAnimArgs[0]; - - gBattleAnimArgs[arg] = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer - 1; - DestroyAnimVisualTask(taskId); -} diff --git a/src/normal.c b/src/normal.c deleted file mode 100644 index f7df9a4a9..000000000 --- a/src/normal.c +++ /dev/null @@ -1,1023 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "palette.h" -#include "random.h" -#include "task.h" -#include "trig.h" -#include "constants/rgb.h" - -static void AnimConfusionDuck(struct Sprite *); -static void AnimSimplePaletteBlend(struct Sprite *); -static void AnimSimplePaletteBlend_Step(struct Sprite *); -static void AnimComplexPaletteBlend(struct Sprite *); -static void AnimComplexPaletteBlend_Step1(struct Sprite *); -static void AnimComplexPaletteBlend_Step2(struct Sprite *); -static void sub_81159B4(struct Sprite *); -static void AnimShakeMonOrBattleTerrain(struct Sprite *); -static void AnimShakeMonOrBattleTerrain_Step(struct Sprite *); -static void AnimShakeMonOrBattleTerrain_UpdateCoordOffsetEnabled(void); -static void AnimHitSplatBasic(struct Sprite *); -static void AnimHitSplatPersistent(struct Sprite *); -static void AnimHitSplatHandleInvert(struct Sprite *); -static void AnimHitSplatRandom(struct Sprite *); -static void AnimHitSplatOnMonEdge(struct Sprite *); -static void AnimCrossImpact(struct Sprite *); -static void AnimFlashingHitSplat(struct Sprite *); -static void AnimFlashingHitSplat_Step(struct Sprite *); -static void AnimConfusionDuck_Step(struct Sprite *); -static void BlendColorCycle(u8, u8, u8); -static void AnimTask_BlendColorCycleLoop(u8); -static void BlendColorCycleExclude(u8, u8, u8); -static void AnimTask_BlendColorCycleExcludeLoop(u8); -static void BlendColorCycleByTag(u8, u8, u8); -static void AnimTask_BlendColorCycleByTagLoop(u8); -static void AnimTask_FlashAnimTagWithColor_Step1(u8); -static void AnimTask_FlashAnimTagWithColor_Step2(u8); -static void AnimTask_ShakeBattleTerrain_Step(u8); - -static const union AnimCmd sAnim_ConfusionDuck_0[] = -{ - ANIMCMD_FRAME(0, 8), - ANIMCMD_FRAME(4, 8), - ANIMCMD_FRAME(0, 8, .hFlip = TRUE), - ANIMCMD_FRAME(8, 8), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd sAnim_ConfusionDuck_1[] = -{ - ANIMCMD_FRAME(0, 8, .hFlip = TRUE), - ANIMCMD_FRAME(4, 8), - ANIMCMD_FRAME(0, 8), - ANIMCMD_FRAME(8, 8), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const sAnims_ConfusionDuck[] = -{ - sAnim_ConfusionDuck_0, - sAnim_ConfusionDuck_1, -}; - -const struct SpriteTemplate gConfusionDuckSpriteTemplate = -{ - .tileTag = ANIM_TAG_DUCK, - .paletteTag = ANIM_TAG_DUCK, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = sAnims_ConfusionDuck, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimConfusionDuck, -}; - -const struct SpriteTemplate gSimplePaletteBlendSpriteTemplate = -{ - .tileTag = 0, - .paletteTag = 0, - .oam = &gDummyOamData, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSimplePaletteBlend, -}; - -const struct SpriteTemplate gComplexPaletteBlendSpriteTemplate = -{ - .tileTag = 0, - .paletteTag = 0, - .oam = &gDummyOamData, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimComplexPaletteBlend, -}; - -static const union AnimCmd gUnknown_085972A4[] = -{ - ANIMCMD_FRAME(0, 3), - ANIMCMD_FRAME(16, 3), - ANIMCMD_FRAME(32, 3), - ANIMCMD_FRAME(48, 3), - ANIMCMD_FRAME(64, 3), - ANIMCMD_JUMP(0), -}; - -static const union AnimCmd *const gUnknown_085972BC[] = -{ - gUnknown_085972A4, -}; - -// Unused -const struct SpriteTemplate gUnknown_085972C0 = -{ - .tileTag = ANIM_TAG_SPARKLE_4, - .paletteTag = ANIM_TAG_SPARKLE_4, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gUnknown_085972BC, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_81159B4, -}; - -const struct SpriteTemplate gShakeMonOrTerrainSpriteTemplate = -{ - .tileTag = 0, - .paletteTag = 0, - .oam = &gDummyOamData, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimShakeMonOrBattleTerrain, -}; - -static const union AffineAnimCmd sAffineAnim_HitSplat_0[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_HitSplat_1[] = -{ - AFFINEANIMCMD_FRAME(0xD8, 0xD8, 0, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_HitSplat_2[] = -{ - AFFINEANIMCMD_FRAME(0xB0, 0xB0, 0, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_HitSplat_3[] = -{ - AFFINEANIMCMD_FRAME(0x80, 0x80, 0, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_HitSplat[] = -{ - sAffineAnim_HitSplat_0, - sAffineAnim_HitSplat_1, - sAffineAnim_HitSplat_2, - sAffineAnim_HitSplat_3, -}; - -const struct SpriteTemplate gBasicHitSplatSpriteTemplate = -{ - .tileTag = ANIM_TAG_IMPACT, - .paletteTag = ANIM_TAG_IMPACT, - .oam = &gOamData_AffineNormal_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_HitSplat, - .callback = AnimHitSplatBasic, -}; - -const struct SpriteTemplate gHandleInvertHitSplatSpriteTemplate = -{ - .tileTag = ANIM_TAG_IMPACT, - .paletteTag = ANIM_TAG_IMPACT, - .oam = &gOamData_AffineNormal_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_HitSplat, - .callback = AnimHitSplatHandleInvert, -}; - -const struct SpriteTemplate gWaterHitSplatSpriteTemplate = -{ - .tileTag = ANIM_TAG_WATER_IMPACT, - .paletteTag = ANIM_TAG_WATER_IMPACT, - .oam = &gOamData_AffineNormal_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_HitSplat, - .callback = AnimHitSplatBasic, -}; - -const struct SpriteTemplate gRandomPosHitSplatSpriteTemplate = -{ - .tileTag = ANIM_TAG_IMPACT, - .paletteTag = ANIM_TAG_IMPACT, - .oam = &gOamData_AffineNormal_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_HitSplat, - .callback = AnimHitSplatRandom, -}; - -const struct SpriteTemplate gMonEdgeHitSplatSpriteTemplate = -{ - .tileTag = ANIM_TAG_IMPACT, - .paletteTag = ANIM_TAG_IMPACT, - .oam = &gOamData_AffineNormal_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_HitSplat, - .callback = AnimHitSplatOnMonEdge, -}; - -const struct SpriteTemplate gCrossImpactSpriteTemplate = -{ - .tileTag = ANIM_TAG_CROSS_IMPACT, - .paletteTag = ANIM_TAG_CROSS_IMPACT, - .oam = &gOamData_AffineOff_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimCrossImpact, -}; - -const struct SpriteTemplate gFlashingHitSplatSpriteTemplate = -{ - .tileTag = ANIM_TAG_IMPACT, - .paletteTag = ANIM_TAG_IMPACT, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_HitSplat, - .callback = AnimFlashingHitSplat, -}; - -const struct SpriteTemplate gPersistHitSplatSpriteTemplate = -{ - .tileTag = ANIM_TAG_IMPACT, - .paletteTag = ANIM_TAG_IMPACT, - .oam = &gOamData_AffineNormal_ObjBlend_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_HitSplat, - .callback = AnimHitSplatPersistent, -}; - -// Moves a spinning duck around the mon's head. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: initial wave offset -// arg 3: wave period (higher means faster wave) -// arg 4: duration -static void AnimConfusionDuck(struct Sprite *sprite) -{ - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[0] = gBattleAnimArgs[2]; - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - sprite->data[1] = -gBattleAnimArgs[3]; - sprite->data[4] = 1; - } - else - { - sprite->data[1] = gBattleAnimArgs[3]; - sprite->data[4] = 0; - StartSpriteAnim(sprite, 1); - } - - sprite->data[3] = gBattleAnimArgs[4]; - sprite->callback = AnimConfusionDuck_Step; - sprite->callback(sprite); -} - -static void AnimConfusionDuck_Step(struct Sprite *sprite) -{ - sprite->pos2.x = Cos(sprite->data[0], 30); - sprite->pos2.y = Sin(sprite->data[0], 10); - - if ((u16)sprite->data[0] < 128) - sprite->oam.priority = 1; - else - sprite->oam.priority = 3; - - sprite->data[0] = (sprite->data[0] + sprite->data[1]) & 0xFF; - if (++sprite->data[2] == sprite->data[3]) - DestroyAnimSprite(sprite); -} - -// Performs a simple color blend on a specified sprite. -// arg 0: palette selector -// arg 1: delay -// arg 2: start blend amount -// arg 3: end blend amount -// arg 4: blend color -static void AnimSimplePaletteBlend(struct Sprite *sprite) -{ - u32 selectedPalettes = UnpackSelectedBattleAnimPalettes(gBattleAnimArgs[0]); - BeginNormalPaletteFade(selectedPalettes, gBattleAnimArgs[1], gBattleAnimArgs[2], gBattleAnimArgs[3], gBattleAnimArgs[4]); - sprite->invisible = TRUE; - sprite->callback = AnimSimplePaletteBlend_Step; -} - -// Unpacks a bitfield and returns a bitmask of its selected palettes. -// Bits 0-6 of the selector parameter result in the following palettes being selected: -// 0: battle background palettes (BG palettes 1, 2, and 3) -// 1: gBattleAnimAttacker OBJ palette -// 2: gBattleAnimTarget OBJ palette -// 3: gBattleAnimAttacker partner OBJ palette -// 4: gBattleAnimTarget partner OBJ palette -// 5: BG palette 4 -// 6: BG palette 5 -u32 UnpackSelectedBattleAnimPalettes(s16 selector) -{ - u8 battleBackground = selector & 1; - u8 attacker = (selector >> 1) & 1; - u8 target = (selector >> 2) & 1; - u8 attackerPartner = (selector >> 3) & 1; - u8 targetPartner = (selector >> 4) & 1; - u8 arg5 = (selector >> 5) & 1; - u8 arg6 = (selector >> 6) & 1; - return sub_80A75AC(battleBackground, attacker, target, attackerPartner, targetPartner, arg5, arg6); -} - -static void AnimSimplePaletteBlend_Step(struct Sprite *sprite) -{ - if (!gPaletteFade.active) - DestroyAnimSprite(sprite); -} - -static void AnimComplexPaletteBlend(struct Sprite *sprite) -{ - u32 selectedPalettes; - - sprite->data[0] = gBattleAnimArgs[1]; - sprite->data[1] = gBattleAnimArgs[1]; - sprite->data[2] = gBattleAnimArgs[2]; - sprite->data[3] = gBattleAnimArgs[3]; - sprite->data[4] = gBattleAnimArgs[4]; - sprite->data[5] = gBattleAnimArgs[5]; - sprite->data[6] = gBattleAnimArgs[6]; - sprite->data[7] = gBattleAnimArgs[0]; - - selectedPalettes = UnpackSelectedBattleAnimPalettes(sprite->data[7]); - BlendPalettes(selectedPalettes, gBattleAnimArgs[4], gBattleAnimArgs[3]); - sprite->invisible = TRUE; - sprite->callback = AnimComplexPaletteBlend_Step1; -} - -static void AnimComplexPaletteBlend_Step1(struct Sprite *sprite) -{ - u32 selectedPalettes; - - if (sprite->data[0] > 0) - { - sprite->data[0]--; - return; - } - - if (gPaletteFade.active) - return; - - if (sprite->data[2] == 0) - { - sprite->callback = AnimComplexPaletteBlend_Step2; - return; - } - - selectedPalettes = UnpackSelectedBattleAnimPalettes(sprite->data[7]); - if (sprite->data[1] & 0x100) - BlendPalettes(selectedPalettes, sprite->data[4], sprite->data[3]); - else - BlendPalettes(selectedPalettes, sprite->data[6], sprite->data[5]); - - sprite->data[1] ^= 0x100; - sprite->data[0] = sprite->data[1] & 0xFF; - sprite->data[2]--; -} - -static void AnimComplexPaletteBlend_Step2(struct Sprite *sprite) -{ - u32 selectedPalettes; - - if (!gPaletteFade.active) - { - selectedPalettes = UnpackSelectedBattleAnimPalettes(sprite->data[7]); - BlendPalettes(selectedPalettes, 0, 0); - DestroyAnimSprite(sprite); - } -} - -static void sub_81159B4(struct Sprite *sprite) -{ - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - sprite->data[0] = 0; - sprite->data[1] = 10; - sprite->data[2] = 8; - sprite->data[3] = 40; - sprite->data[4] = 112; - sprite->data[5] = 0; - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = TranslateSpriteInGrowingCircleOverDuration; - sprite->callback(sprite); -} - -// Task data for AnimTask_BlendColorCycle, AnimTask_BlendColorCycleExclude, and AnimTask_BlendColorCycleByTag -#define tPalSelector data[0] // AnimTask_BlendColorCycle -#define tPalTag data[0] // AnimTask_BlendColorCycleByTag -#define tDelay data[1] -#define tNumBlends data[2] -#define tInitialBlendY data[3] -#define tTargetBlendY data[4] -#define tBlendColor data[5] -#define tRestoreBlend data[8] -#define tPalSelectorHi data[9] -#define tPalSelectorLo data[10] - -// Blends mon/screen to designated color or back alternately tNumBlends times -// Many uses of this task only set a tNumBlends of 2, which has the effect of blending to a color and back once -void AnimTask_BlendColorCycle(u8 taskId) -{ - gTasks[taskId].tPalSelector = gBattleAnimArgs[0]; - gTasks[taskId].tDelay = gBattleAnimArgs[1]; - gTasks[taskId].tNumBlends = gBattleAnimArgs[2]; - gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3]; - gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4]; - gTasks[taskId].tBlendColor = gBattleAnimArgs[5]; - gTasks[taskId].tRestoreBlend = FALSE; - BlendColorCycle(taskId, 0, gTasks[taskId].tTargetBlendY); - gTasks[taskId].func = AnimTask_BlendColorCycleLoop; -} - -static void BlendColorCycle(u8 taskId, u8 startBlendAmount, u8 targetBlendAmount) -{ - u32 selectedPalettes = UnpackSelectedBattleAnimPalettes(gTasks[taskId].tPalSelector); - BeginNormalPaletteFade( - selectedPalettes, - gTasks[taskId].tDelay, - startBlendAmount, - targetBlendAmount, - gTasks[taskId].tBlendColor); - - gTasks[taskId].tNumBlends--; - gTasks[taskId].tRestoreBlend ^= 1; -} - -static void AnimTask_BlendColorCycleLoop(u8 taskId) -{ - u8 startBlendAmount, targetBlendAmount; - if (!gPaletteFade.active) - { - if (gTasks[taskId].tNumBlends > 0) - { - if (!gTasks[taskId].tRestoreBlend) - { - // Blend to designated color - startBlendAmount = gTasks[taskId].tInitialBlendY; - targetBlendAmount = gTasks[taskId].tTargetBlendY; - } - else - { - // Blend back to original color - startBlendAmount = gTasks[taskId].tTargetBlendY; - targetBlendAmount = gTasks[taskId].tInitialBlendY; - } - - if (gTasks[taskId].tNumBlends == 1) - targetBlendAmount = 0; - - BlendColorCycle(taskId, startBlendAmount, targetBlendAmount); - } - else - { - DestroyAnimVisualTask(taskId); - } - } -} - -// See AnimTask_BlendColorCycle. Same, but excludes Attacker and Target -void AnimTask_BlendColorCycleExclude(u8 taskId) -{ - int battler; - u32 selectedPalettes = 0; - - gTasks[taskId].data[0] = gBattleAnimArgs[0]; - gTasks[taskId].tDelay = gBattleAnimArgs[1]; - gTasks[taskId].tNumBlends = gBattleAnimArgs[2]; - gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3]; - gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4]; - gTasks[taskId].tBlendColor = gBattleAnimArgs[5]; - gTasks[taskId].tRestoreBlend = 0; - - for (battler = 0; battler < gBattlersCount; battler++) - { - if (battler != gBattleAnimAttacker && battler != gBattleAnimTarget) - selectedPalettes |= 1 << (battler + 16); - } - - if (gBattleAnimArgs[0] == 1) - selectedPalettes |= 0xE; - - gTasks[taskId].tPalSelectorHi = selectedPalettes >> 16; - gTasks[taskId].tPalSelectorLo = selectedPalettes & 0xFF; - BlendColorCycleExclude(taskId, 0, gTasks[taskId].tTargetBlendY); - gTasks[taskId].func = AnimTask_BlendColorCycleExcludeLoop; -} - -static void BlendColorCycleExclude(u8 taskId, u8 startBlendAmount, u8 targetBlendAmount) -{ - u32 selectedPalettes = ((u16)gTasks[taskId].tPalSelectorHi << 16) | (u16)gTasks[taskId].tPalSelectorLo; - BeginNormalPaletteFade( - selectedPalettes, - gTasks[taskId].tDelay, - startBlendAmount, - targetBlendAmount, - gTasks[taskId].tBlendColor); - - gTasks[taskId].tNumBlends--; - gTasks[taskId].tRestoreBlend ^= 1; -} - -static void AnimTask_BlendColorCycleExcludeLoop(u8 taskId) -{ - u8 startBlendAmount, targetBlendAmount; - if (!gPaletteFade.active) - { - if (gTasks[taskId].tNumBlends > 0) - { - if (!gTasks[taskId].tRestoreBlend) - { - // Blend to designated color - startBlendAmount = gTasks[taskId].tInitialBlendY; - targetBlendAmount = gTasks[taskId].tTargetBlendY; - } - else - { - // Blend back to original color - startBlendAmount = gTasks[taskId].tTargetBlendY; - targetBlendAmount = gTasks[taskId].tInitialBlendY; - } - - if (gTasks[taskId].tNumBlends == 1) - targetBlendAmount = 0; - - BlendColorCycleExclude(taskId, startBlendAmount, targetBlendAmount); - } - else - { - DestroyAnimVisualTask(taskId); - } - } -} - -// See AnimTask_BlendColorCycle. Same, but selects palette by ANIM_TAG_* -void AnimTask_BlendColorCycleByTag(u8 taskId) -{ - u8 paletteIndex; - - gTasks[taskId].tPalTag = gBattleAnimArgs[0]; - gTasks[taskId].tDelay = gBattleAnimArgs[1]; - gTasks[taskId].tNumBlends = gBattleAnimArgs[2]; - gTasks[taskId].tInitialBlendY = gBattleAnimArgs[3]; - gTasks[taskId].tTargetBlendY = gBattleAnimArgs[4]; - gTasks[taskId].tBlendColor = gBattleAnimArgs[5]; - gTasks[taskId].tRestoreBlend = FALSE; - - BlendColorCycleByTag(taskId, 0, gTasks[taskId].tTargetBlendY); - gTasks[taskId].func = AnimTask_BlendColorCycleByTagLoop; -} - -static void BlendColorCycleByTag(u8 taskId, u8 startBlendAmount, u8 targetBlendAmount) -{ - u8 paletteIndex = IndexOfSpritePaletteTag(gTasks[taskId].tPalTag); - BeginNormalPaletteFade( - 1 << (paletteIndex + 16), - gTasks[taskId].tDelay, - startBlendAmount, - targetBlendAmount, - gTasks[taskId].tBlendColor); - - gTasks[taskId].tNumBlends--; - gTasks[taskId].tRestoreBlend ^= 1; -} - -static void AnimTask_BlendColorCycleByTagLoop(u8 taskId) -{ - u8 startBlendAmount, targetBlendAmount; - if (!gPaletteFade.active) - { - if (gTasks[taskId].tNumBlends > 0) - { - if (!gTasks[taskId].tRestoreBlend) - { - // Blend to designated color - startBlendAmount = gTasks[taskId].tInitialBlendY; - targetBlendAmount = gTasks[taskId].tTargetBlendY; - } - else - { - // Blend back to original color - startBlendAmount = gTasks[taskId].tTargetBlendY; - targetBlendAmount = gTasks[taskId].tInitialBlendY; - } - - if (gTasks[taskId].tNumBlends == 1) - targetBlendAmount = 0; - - BlendColorCycleByTag(taskId, startBlendAmount, targetBlendAmount); - } - else - { - DestroyAnimVisualTask(taskId); - } - } -} - -#undef tPalSelector -#undef tPalTag -#undef tDelay -#undef tNumBlends -#undef tInitialBlendY -#undef tTargetBlendY -#undef tBlendColor -#undef tRestoreBlend -#undef tPalSelectorHi -#undef tPalSelectorLo - -// Flashes the specified anim tag with given color. Used e.g. to flash the particles red in Hyper Beam -void AnimTask_FlashAnimTagWithColor(u8 taskId) -{ - u8 paletteIndex; - - gTasks[taskId].data[0] = gBattleAnimArgs[1]; - gTasks[taskId].data[1] = gBattleAnimArgs[1]; - gTasks[taskId].data[2] = gBattleAnimArgs[2]; - gTasks[taskId].data[3] = gBattleAnimArgs[3]; - gTasks[taskId].data[4] = gBattleAnimArgs[4]; - gTasks[taskId].data[5] = gBattleAnimArgs[5]; - gTasks[taskId].data[6] = gBattleAnimArgs[6]; - gTasks[taskId].data[7] = gBattleAnimArgs[0]; - - paletteIndex = IndexOfSpritePaletteTag(gBattleAnimArgs[0]); - BeginNormalPaletteFade( - 1 << (paletteIndex + 16), - 0, - gBattleAnimArgs[4], - gBattleAnimArgs[4], - gBattleAnimArgs[3]); - - gTasks[taskId].func = AnimTask_FlashAnimTagWithColor_Step1; -} - -static void AnimTask_FlashAnimTagWithColor_Step1(u8 taskId) -{ - u32 selectedPalettes; - - if (gTasks[taskId].data[0] > 0) - { - gTasks[taskId].data[0]--; - return; - } - - if (gPaletteFade.active) - return; - - if (gTasks[taskId].data[2] == 0) - { - gTasks[taskId].func = AnimTask_FlashAnimTagWithColor_Step2; - return; - } - - selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].data[7]) + 16); - if (gTasks[taskId].data[1] & 0x100) - { - BeginNormalPaletteFade( - selectedPalettes, - 0, - gTasks[taskId].data[4], - gTasks[taskId].data[4], - gTasks[taskId].data[3]); - } - else - { - BeginNormalPaletteFade( - selectedPalettes, - 0, - gTasks[taskId].data[6], - gTasks[taskId].data[6], - gTasks[taskId].data[5]); - } - - gTasks[taskId].data[1] ^= 0x100; - gTasks[taskId].data[0] = gTasks[taskId].data[1] & 0xFF; - gTasks[taskId].data[2]--; -} - -static void AnimTask_FlashAnimTagWithColor_Step2(u8 taskId) -{ - u32 selectedPalettes; - - if (!gPaletteFade.active) - { - selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].data[7]) + 16); - BeginNormalPaletteFade(selectedPalettes, 0, 0, 0, RGB(0, 0, 0)); - DestroyAnimVisualTask(taskId); - } -} - -void AnimTask_InvertScreenColor(u8 taskId) -{ - u32 selectedPalettes = 0; - u8 attackerBattler = gBattleAnimAttacker; - u8 targetBattler = gBattleAnimTarget; - - if (gBattleAnimArgs[0] & 0x100) - selectedPalettes = sub_80A75AC(1, 0, 0, 0, 0, 0, 0); - - if (gBattleAnimArgs[1] & 0x100) - selectedPalettes |= (0x10000 << attackerBattler); - - if (gBattleAnimArgs[2] & 0x100) - selectedPalettes |= (0x10000 << targetBattler); - - InvertPlttBuffer(selectedPalettes); - DestroyAnimVisualTask(taskId); -} - -void sub_8115F94(u8 taskId) -{ - u8 attackerBattler; - u8 targetBattler; - u8 paletteIndex; - u32 selectedPalettes = 0; - - if (gTasks[taskId].data[0] == 0) - { - gTasks[taskId].data[2] = gBattleAnimArgs[0]; - gTasks[taskId].data[3] = gBattleAnimArgs[1]; - gTasks[taskId].data[4] = gBattleAnimArgs[2]; - gTasks[taskId].data[1] = gBattleAnimArgs[3]; - gTasks[taskId].data[5] = gBattleAnimArgs[4]; - gTasks[taskId].data[6] = gBattleAnimArgs[5]; - gTasks[taskId].data[7] = gBattleAnimArgs[6]; - } - - gTasks[taskId].data[0]++; - attackerBattler = gBattleAnimAttacker; - targetBattler = gBattleAnimTarget; - - if (gTasks[taskId].data[2] & 0x100) - selectedPalettes = 0x0000FFFF; - - if (gTasks[taskId].data[2] & 0x1) - { - paletteIndex = IndexOfSpritePaletteTag(gSprites[gHealthboxSpriteIds[attackerBattler]].template->paletteTag); - selectedPalettes |= (1 << paletteIndex) << 16; - } - - if (gTasks[taskId].data[3] & 0x100) - selectedPalettes |= (1 << attackerBattler) << 16; - - if (gTasks[taskId].data[4] & 0x100) - selectedPalettes |= (1 << targetBattler) << 16; - - TintPlttBuffer(selectedPalettes, gTasks[taskId].data[5], gTasks[taskId].data[6], gTasks[taskId].data[7]); - if (gTasks[taskId].data[0] == gTasks[taskId].data[1]) - { - UnfadePlttBuffer(selectedPalettes); - DestroyAnimVisualTask(taskId); - } -} - -static void AnimShakeMonOrBattleTerrain(struct Sprite *sprite) -{ - u16 var0; - - sprite->invisible = TRUE; - sprite->data[0] = -gBattleAnimArgs[0]; - sprite->data[1] = gBattleAnimArgs[1]; - sprite->data[2] = gBattleAnimArgs[1]; - sprite->data[3] = gBattleAnimArgs[2]; - - switch (gBattleAnimArgs[3]) - { - case 0: - StoreSpriteCallbackInData6(sprite, (void *)&gBattle_BG3_X); - break; - case 1: - StoreSpriteCallbackInData6(sprite, (void *)&gBattle_BG3_Y); - break; - case 2: - StoreSpriteCallbackInData6(sprite, (void *)&gSpriteCoordOffsetX); - break; - default: - StoreSpriteCallbackInData6(sprite, (void *)&gSpriteCoordOffsetY); - break; - } - - sprite->data[4] = *(u16 *)(sprite->data[6] | (sprite->data[7] << 16)); - sprite->data[5] = gBattleAnimArgs[3]; - var0 = sprite->data[5] - 2; - if (var0 < 2) - AnimShakeMonOrBattleTerrain_UpdateCoordOffsetEnabled(); - - sprite->callback = AnimShakeMonOrBattleTerrain_Step; -} - -static void AnimShakeMonOrBattleTerrain_Step(struct Sprite *sprite) -{ - u8 i; - u16 var0; - - if (sprite->data[3] > 0) - { - sprite->data[3]--; - if (sprite->data[1] > 0) - { - sprite->data[1]--; - } - else - { - sprite->data[1] = sprite->data[2]; - *(u16 *)(sprite->data[6] | (sprite->data[7] << 16)) += sprite->data[0]; - sprite->data[0] = -sprite->data[0]; - } - } - else - { - *(u16 *)(sprite->data[6] | (sprite->data[7] << 16)) = sprite->data[4]; - var0 = sprite->data[5] - 2; - if (var0 < 2) - { - for (i = 0; i < gBattlersCount; i++) - gSprites[gBattlerSpriteIds[i]].coordOffsetEnabled = FALSE; - } - - DestroyAnimSprite(sprite); - } -} - -static void AnimShakeMonOrBattleTerrain_UpdateCoordOffsetEnabled(void) -{ - gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = FALSE; - gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = FALSE; - - if (gBattleAnimArgs[4] == 2) - { - gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = TRUE; - gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = TRUE; - } - else - { - if (gBattleAnimArgs[4] == 0) - gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = TRUE; - else - gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = TRUE; - } -} - -// Task data for AnimTask_ShakeBattleTerrain -#define tXOffset data[0] -#define tYOffset data[1] -#define tNumShakes data[2] -#define tTimer data[3] -#define tShakeDelay data[8] - -// Can shake battle terrain back and forth on the X or down and back to original pos on Y (cant shake up from orig pos) -// arg0: x offset of shake -// arg1: y offset of shake -// arg2: number of shakes -// arg3: time between shakes -void AnimTask_ShakeBattleTerrain(u8 taskId) -{ - gTasks[taskId].tXOffset = gBattleAnimArgs[0]; - gTasks[taskId].tYOffset = gBattleAnimArgs[1]; - gTasks[taskId].tNumShakes = gBattleAnimArgs[2]; - gTasks[taskId].tTimer = gBattleAnimArgs[3]; - gTasks[taskId].tShakeDelay = gBattleAnimArgs[3]; - gBattle_BG3_X = gBattleAnimArgs[0]; - gBattle_BG3_Y = gBattleAnimArgs[1]; - gTasks[taskId].func = AnimTask_ShakeBattleTerrain_Step; - gTasks[taskId].func(taskId); -} - -static void AnimTask_ShakeBattleTerrain_Step(u8 taskId) -{ - if (gTasks[taskId].tTimer == 0) - { - if (gBattle_BG3_X == gTasks[taskId].tXOffset) - gBattle_BG3_X = -gTasks[taskId].tXOffset; - else - gBattle_BG3_X = gTasks[taskId].tXOffset; - - if (gBattle_BG3_Y == -gTasks[taskId].tYOffset) - gBattle_BG3_Y = 0; - else - gBattle_BG3_Y = -gTasks[taskId].tYOffset; - - gTasks[taskId].tTimer = gTasks[taskId].tShakeDelay; - if (--gTasks[taskId].tNumShakes == 0) - { - gBattle_BG3_X = 0; - gBattle_BG3_Y = 0; - DestroyAnimVisualTask(taskId); - } - } - else - { - gTasks[taskId].tTimer--; - } -} - -#undef tXOffset -#undef tYOffset -#undef tNumShakes -#undef tTimer -#undef tShakeDelay - -static void AnimHitSplatBasic(struct Sprite *sprite) -{ - StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); - if (gBattleAnimArgs[2] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, 1); - else - InitSpritePosToAnimTarget(sprite, TRUE); - - sprite->callback = RunStoredCallbackWhenAffineAnimEnds; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Same as basic hit splat but takes a length of time to persist for (arg4) -static void AnimHitSplatPersistent(struct Sprite *sprite) -{ - StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); - if (gBattleAnimArgs[2] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, 1); - else - InitSpritePosToAnimTarget(sprite, TRUE); - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->callback = RunStoredCallbackWhenAffineAnimEnds; - StoreSpriteCallbackInData6(sprite, DestroyAnimSpriteAfterTimer); -} - -// For paired hit splats whose position is inverted when used by the opponent on the player. -// Used by Twineedle and Spike Cannon -static void AnimHitSplatHandleInvert(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER && !IsContest()) - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - - AnimHitSplatBasic(sprite); -} - -static void AnimHitSplatRandom(struct Sprite *sprite) -{ - if (gBattleAnimArgs[1] == -1) - gBattleAnimArgs[1] = Random2() & 3; - - StartSpriteAffineAnim(sprite, gBattleAnimArgs[1]); - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, 0); - else - InitSpritePosToAnimTarget(sprite, FALSE); - - sprite->pos2.x += (Random2() % 48) - 24; - sprite->pos2.y += (Random2() % 24) - 12; - - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = RunStoredCallbackWhenAffineAnimEnds; -} - -static void AnimHitSplatOnMonEdge(struct Sprite *sprite) -{ - sprite->data[0] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); - sprite->pos1.x = gSprites[sprite->data[0]].pos1.x + gSprites[sprite->data[0]].pos2.x; - sprite->pos1.y = gSprites[sprite->data[0]].pos1.y + gSprites[sprite->data[0]].pos2.y; - sprite->pos2.x = gBattleAnimArgs[1]; - sprite->pos2.y = gBattleAnimArgs[2]; - StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = RunStoredCallbackWhenAffineAnimEnds; -} - -static void AnimCrossImpact(struct Sprite *sprite) -{ - if (gBattleAnimArgs[2] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, 1); - else - InitSpritePosToAnimTarget(sprite, TRUE); - - sprite->data[0] = gBattleAnimArgs[3]; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - sprite->callback = WaitAnimForDuration; -} - -static void AnimFlashingHitSplat(struct Sprite *sprite) -{ - StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); - if (gBattleAnimArgs[2] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, 1); - else - InitSpritePosToAnimTarget(sprite, TRUE); - - sprite->callback = AnimFlashingHitSplat_Step; -} - -static void AnimFlashingHitSplat_Step(struct Sprite *sprite) -{ - sprite->invisible ^= 1; - if (sprite->data[0]++ > 12) - DestroyAnimSprite(sprite); -} diff --git a/src/poison.c b/src/poison.c deleted file mode 100644 index bc5624249..000000000 --- a/src/poison.c +++ /dev/null @@ -1,319 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "trig.h" -#include "constants/rgb.h" - -static void AnimSludgeProjectile(struct Sprite *); -static void AnimSludgeProjectile_Step(struct Sprite *); -static void AnimAcidPoisonBubble(struct Sprite *); -static void AnimAcidPoisonBubble_Step(struct Sprite *); -static void AnimSludgeBombHitParticle(struct Sprite *); -static void AnimSludgeBombHitParticle_Step(struct Sprite *); -static void AnimAcidPoisonDroplet(struct Sprite *); -static void AnimBubbleEffect(struct Sprite *); -static void AnimBubbleEffect_Step(struct Sprite *); - -static const union AnimCmd sAnim_ToxicBubble[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(8, 5), - ANIMCMD_FRAME(16, 5), - ANIMCMD_FRAME(24, 5), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_ToxicBubble[] = -{ - sAnim_ToxicBubble, -}; - -const struct SpriteTemplate gToxicBubbleSpriteTemplate = -{ - .tileTag = ANIM_TAG_TOXIC_BUBBLE, - .paletteTag = ANIM_TAG_TOXIC_BUBBLE, - .oam = &gOamData_AffineOff_ObjNormal_16x32, - .anims = sAnims_ToxicBubble, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimSpriteOnMonPos, -}; - -static const union AnimCmd sAnim_PoisonProjectile[] = -{ - ANIMCMD_FRAME(0, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_AcidPoisonDroplet[] = -{ - ANIMCMD_FRAME(4, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_SludgeBombHit[] = -{ - ANIMCMD_FRAME(8, 1), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_PoisonProjectile[] = -{ - sAnim_PoisonProjectile, -}; - -static const union AnimCmd *const sAnims_AcidPoisonDroplet[] = -{ - sAnim_AcidPoisonDroplet, -}; - -static const union AnimCmd *const sAnims_SludgeBombHit[] = -{ - sAnim_SludgeBombHit, -}; - -static const union AffineAnimCmd sAffineAnim_PoisonProjectile[] = -{ - AFFINEANIMCMD_FRAME(0x160, 0x160, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF6, 0xFFF6, 0, 10), - AFFINEANIMCMD_FRAME(0xA, 0xA, 0, 10), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd sAffineAnim_SludgeBombHit[] = -{ - AFFINEANIMCMD_FRAME(0xEC, 0xEC, 0, 0), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_PoisonProjectile[] = -{ - sAffineAnim_PoisonProjectile, -}; - -static const union AffineAnimCmd *const sAffineAnims_SludgeBombHit[] = -{ - sAffineAnim_SludgeBombHit, -}; - -const struct SpriteTemplate gSludgeProjectileSpriteTemplate = -{ - .tileTag = ANIM_TAG_POISON_BUBBLE, - .paletteTag = ANIM_TAG_POISON_BUBBLE, - .oam = &gOamData_AffineDouble_ObjNormal_16x16, - .anims = sAnims_PoisonProjectile, - .images = NULL, - .affineAnims = sAffineAnims_PoisonProjectile, - .callback = AnimSludgeProjectile, -}; - -const struct SpriteTemplate gAcidPoisonBubbleSpriteTemplate = -{ - .tileTag = ANIM_TAG_POISON_BUBBLE, - .paletteTag = ANIM_TAG_POISON_BUBBLE, - .oam = &gOamData_AffineDouble_ObjNormal_16x16, - .anims = sAnims_PoisonProjectile, - .images = NULL, - .affineAnims = sAffineAnims_PoisonProjectile, - .callback = AnimAcidPoisonBubble, -}; - -const struct SpriteTemplate gSludgeBombHitParticleSpriteTemplate = -{ - .tileTag = ANIM_TAG_POISON_BUBBLE, - .paletteTag = ANIM_TAG_POISON_BUBBLE, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = sAnims_SludgeBombHit, - .images = NULL, - .affineAnims = sAffineAnims_SludgeBombHit, - .callback = AnimSludgeBombHitParticle, -}; - -static const union AffineAnimCmd sAffineAnim_AcidPoisonDroplet[] = -{ - AFFINEANIMCMD_FRAME(0xFFF0, 0x10, 0, 6), - AFFINEANIMCMD_FRAME(0x10, 0xFFF0, 0, 6), - AFFINEANIMCMD_JUMP(0), -}; - -const union AffineAnimCmd *const gAffineAnims_Droplet[] = -{ - sAffineAnim_AcidPoisonDroplet, -}; - -const struct SpriteTemplate gAcidPoisonDropletSpriteTemplate = -{ - .tileTag = ANIM_TAG_POISON_BUBBLE, - .paletteTag = ANIM_TAG_POISON_BUBBLE, - .oam = &gOamData_AffineDouble_ObjNormal_16x16, - .anims = sAnims_AcidPoisonDroplet, - .images = NULL, - .affineAnims = gAffineAnims_Droplet, - .callback = AnimAcidPoisonDroplet, -}; - -static const union AffineAnimCmd sAffineAnim_Bubble[] = -{ - AFFINEANIMCMD_FRAME(0x9C, 0x9C, 0, 0), - AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 20), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_Bubble[] = -{ - sAffineAnim_Bubble, -}; - -const struct SpriteTemplate gPoisonBubbleSpriteTemplate = -{ - .tileTag = ANIM_TAG_POISON_BUBBLE, - .paletteTag = ANIM_TAG_POISON_BUBBLE, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = sAnims_PoisonProjectile, - .images = NULL, - .affineAnims = sAffineAnims_Bubble, - .callback = AnimBubbleEffect, -}; - -const struct SpriteTemplate gWaterBubbleSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_BUBBLES, - .paletteTag = ANIM_TAG_SMALL_BUBBLES, - .oam = &gOamData_AffineNormal_ObjBlend_16x16, - .anims = gAnims_WaterBubble, - .images = NULL, - .affineAnims = sAffineAnims_Bubble, - .callback = AnimBubbleEffect, -}; - -static void AnimSludgeProjectile(struct Sprite *sprite) -{ - if (!gBattleAnimArgs[3]) - StartSpriteAnim(sprite, 2); - - InitSpritePosToAnimAttacker(sprite, 1); - - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); - sprite->data[5] = -30; - - InitAnimArcTranslation(sprite); - - sprite->callback = AnimSludgeProjectile_Step; -} - -static void AnimSludgeProjectile_Step(struct Sprite *sprite) -{ - if (TranslateAnimHorizontalArc(sprite)) - DestroyAnimSprite(sprite); -} - -static void AnimAcidPoisonBubble(struct Sprite *sprite) -{ - s16 l1, l2; - if (!gBattleAnimArgs[3]) - StartSpriteAnim(sprite, 2); - - InitSpritePosToAnimAttacker(sprite, 1); - SetAverageBattlerPositions(gBattleAnimTarget, 1, &l1, &l2); - - if (GetBattlerSide(gBattleAnimAttacker)) - gBattleAnimArgs[4] = -gBattleAnimArgs[4]; - - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[2] = l1 + gBattleAnimArgs[4]; - sprite->data[4] = l2 + gBattleAnimArgs[5]; - sprite->data[5] = -30; - - InitAnimArcTranslation(sprite); - - sprite->callback = AnimAcidPoisonBubble_Step; -} - -static void AnimAcidPoisonBubble_Step(struct Sprite *sprite) -{ - if (TranslateAnimHorizontalArc(sprite)) - DestroyAnimSprite(sprite); -} - -static void AnimSludgeBombHitParticle(struct Sprite *sprite) -{ - sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[0]; - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[1]; - - InitSpriteDataForLinearTranslation(sprite); - - sprite->data[5] = sprite->data[1] / gBattleAnimArgs[2]; - sprite->data[6] = sprite->data[2] / gBattleAnimArgs[2]; - - sprite->callback = AnimSludgeBombHitParticle_Step; -} - -static void AnimSludgeBombHitParticle_Step(struct Sprite *sprite) -{ - TranslateSpriteLinearFixedPoint(sprite); - - sprite->data[1] -= sprite->data[5]; - sprite->data[2] -= sprite->data[6]; - - if (!sprite->data[0]) - DestroyAnimSprite(sprite); -} - -static void AnimAcidPoisonDroplet(struct Sprite *sprite) -{ - SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->pos1.x, &sprite->pos1.y); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; - sprite->data[4] = sprite->pos1.y + sprite->data[0]; - - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -// Animates a bubble by rising upward, swaying side to side, and -// enlarging the sprite. This is used as an after-effect by poison-type -// moves, along with MOVE_BUBBLE, and MOVE_BUBBLEBEAM. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: 0 = single-target, 1 = multi-target -static void AnimBubbleEffect(struct Sprite *sprite) -{ - if (!gBattleAnimArgs[2]) - { - InitSpritePosToAnimTarget(sprite, TRUE); - } - else - { - SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->pos1.x, &sprite->pos1.y); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - } - - sprite->callback = AnimBubbleEffect_Step; -} - -static void AnimBubbleEffect_Step(struct Sprite *sprite) -{ - sprite->data[0] = (sprite->data[0] + 0xB) & 0xFF; - sprite->pos2.x = Sin(sprite->data[0], 4); - sprite->data[1] += 0x30; - sprite->pos2.y = -(sprite->data[1] >> 8); - - if (sprite->affineAnimEnded) - DestroyAnimSprite(sprite); -} diff --git a/src/psychic.c b/src/psychic.c deleted file mode 100644 index 7918698fc..000000000 --- a/src/psychic.c +++ /dev/null @@ -1,1168 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "gpu_regs.h" -#include "palette.h" -#include "sound.h" -#include "scanline_effect.h" -#include "trig.h" -#include "constants/rgb.h" -#include "constants/songs.h" - -static void AnimDefensiveWall(struct Sprite *); -static void AnimDefensiveWall_Step1(struct Sprite *); -static void AnimDefensiveWall_Step2(struct Sprite *); -static void AnimDefensiveWall_Step3(struct Sprite *); -static void AnimDefensiveWall_Step4(struct Sprite *); -static void AnimDefensiveWall_Step5(struct Sprite *); -static void AnimWallSparkle(struct Sprite *); -static void AnimBentSpoon(struct Sprite *); -static void AnimQuestionMark(struct Sprite *); -static void AnimQuestionMark_Step1(struct Sprite *); -static void AnimQuestionMark_Step2(struct Sprite *); -static void AnimRedX(struct Sprite *); -static void AnimSkillSwapOrb(struct Sprite *); -static void AnimPsychoBoost(struct Sprite *); -static void AnimTask_MeditateStretchAttacker_Step(u8); -static void AnimTask_Teleport_Step(u8); -static void AnimTask_ImprisonOrbs_Step(u8); -static void AnimTask_SkillSwap_Step(u8); -static void AnimTask_ExtrasensoryDistortion_Step(u8); -static void AnimTask_TransparentCloneGrowAndShrink_Step(u8); - -static const union AffineAnimCmd sAffineAnim_PsychUpSpiral[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0xFFFE, 0xFFFE, -10, 120), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_PsychUpSpiral[] = -{ - sAffineAnim_PsychUpSpiral, -}; - -const struct SpriteTemplate gPsychUpSpiralSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPIRAL, - .paletteTag = ANIM_TAG_SPIRAL, - .oam = &gOamData_AffineNormal_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_PsychUpSpiral, - .callback = AnimSpriteOnMonPos, -}; - -const struct SpriteTemplate gLightScreenWallSpriteTemplate = -{ - .tileTag = ANIM_TAG_GREEN_LIGHT_WALL, - .paletteTag = ANIM_TAG_GREEN_LIGHT_WALL, - .oam = &gOamData_AffineOff_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDefensiveWall, -}; - -const struct SpriteTemplate gReflectWallSpriteTemplate = -{ - .tileTag = ANIM_TAG_BLUE_LIGHT_WALL, - .paletteTag = ANIM_TAG_BLUE_LIGHT_WALL, - .oam = &gOamData_AffineOff_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDefensiveWall, -}; - -const struct SpriteTemplate gMirrorCoatWallSpriteTemplate = -{ - .tileTag = ANIM_TAG_RED_LIGHT_WALL, - .paletteTag = ANIM_TAG_RED_LIGHT_WALL, - .oam = &gOamData_AffineOff_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDefensiveWall, -}; - -const struct SpriteTemplate gBarrierWallSpriteTemplate = -{ - .tileTag = ANIM_TAG_GRAY_LIGHT_WALL, - .paletteTag = ANIM_TAG_GRAY_LIGHT_WALL, - .oam = &gOamData_AffineOff_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDefensiveWall, -}; - -const struct SpriteTemplate gMagicCoatWallSpriteTemplate = -{ - .tileTag = ANIM_TAG_ORANGE_LIGHT_WALL, - .paletteTag = ANIM_TAG_ORANGE_LIGHT_WALL, - .oam = &gOamData_AffineOff_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimDefensiveWall, -}; - -static const union AnimCmd sAnim_ReflectSparkle[] = -{ - ANIMCMD_FRAME(0, 3), - ANIMCMD_FRAME(16, 3), - ANIMCMD_FRAME(32, 3), - ANIMCMD_FRAME(48, 3), - ANIMCMD_FRAME(64, 3), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_ReflectSparkle[] = -{ - sAnim_ReflectSparkle, -}; - -const struct SpriteTemplate gReflectSparkleSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARKLE_4, - .paletteTag = ANIM_TAG_SPARKLE_4, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_ReflectSparkle, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimWallSparkle, -}; - -static const union AnimCmd sAnim_SpecialScreenSparkle[] = -{ - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(4, 5), - ANIMCMD_FRAME(8, 5), - ANIMCMD_FRAME(12, 5), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_SpecialScreenSparkle[] = -{ - sAnim_SpecialScreenSparkle, -}; - -const struct SpriteTemplate gSpecialScreenSparkleSpriteTemplate = -{ - .tileTag = ANIM_TAG_SPARKLE_3, - .paletteTag = ANIM_TAG_SPARKLE_3, - .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = sAnims_SpecialScreenSparkle, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimWallSparkle, -}; - -const struct SpriteTemplate gGoldRingSpriteTemplate = -{ - .tileTag = ANIM_TAG_GOLD_RING, - .paletteTag = ANIM_TAG_GOLD_RING, - .oam = &gOamData_AffineOff_ObjNormal_16x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = TranslateAnimSpriteToTargetMonLocation, -}; - -static const union AnimCmd sAnim_BentSpoon_0[] = -{ - ANIMCMD_FRAME(8, 60, .hFlip = TRUE), - ANIMCMD_FRAME(16, 5, .hFlip = TRUE), - ANIMCMD_FRAME(8, 5, .hFlip = TRUE), - ANIMCMD_FRAME(0, 5, .hFlip = TRUE), - ANIMCMD_FRAME(8, 22, .hFlip = TRUE), - ANIMCMD_LOOP(0), - ANIMCMD_FRAME(16, 5, .hFlip = TRUE), - ANIMCMD_FRAME(8, 5, .hFlip = TRUE), - ANIMCMD_FRAME(0, 5, .hFlip = TRUE), - ANIMCMD_FRAME(8, 5, .hFlip = TRUE), - ANIMCMD_LOOP(1), - ANIMCMD_FRAME(8, 22, .hFlip = TRUE), - ANIMCMD_FRAME(24, 3, .hFlip = TRUE), - ANIMCMD_FRAME(32, 3, .hFlip = TRUE), - ANIMCMD_FRAME(40, 22, .hFlip = TRUE), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_BentSpoon_1[] = -{ - ANIMCMD_FRAME(8, 60), - ANIMCMD_FRAME(16, 5), - ANIMCMD_FRAME(8, 5), - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(8, 22), - ANIMCMD_LOOP(0), - ANIMCMD_FRAME(16, 5), - ANIMCMD_FRAME(8, 5), - ANIMCMD_FRAME(0, 5), - ANIMCMD_FRAME(8, 5), - ANIMCMD_LOOP(1), - ANIMCMD_FRAME(8, 22), - ANIMCMD_FRAME(24, 3), - ANIMCMD_FRAME(32, 3), - ANIMCMD_FRAME(40, 22), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_BentSpoon[] = -{ - sAnim_BentSpoon_0, - sAnim_BentSpoon_1, -}; - -const struct SpriteTemplate gBentSpoonSpriteTemplate = -{ - .tileTag = ANIM_TAG_BENT_SPOON, - .paletteTag = ANIM_TAG_BENT_SPOON, - .oam = &gOamData_AffineOff_ObjNormal_16x32, - .anims = sAnims_BentSpoon, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimBentSpoon, -}; - -static const union AnimCmd sAnim_QuestionMark[] = -{ - ANIMCMD_FRAME(0, 6), - ANIMCMD_FRAME(16, 6), - ANIMCMD_FRAME(32, 6), - ANIMCMD_FRAME(48, 6), - ANIMCMD_FRAME(64, 6), - ANIMCMD_FRAME(80, 6), - ANIMCMD_FRAME(96, 18), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_QuestionMark[] = -{ - sAnim_QuestionMark, -}; - -static const union AffineAnimCmd sAffineAnim_QuestionMark[] = -{ - AFFINEANIMCMD_FRAME(0, 0, 4, 4), - AFFINEANIMCMD_FRAME(0, 0, -4, 8), - AFFINEANIMCMD_FRAME(0, 0, 4, 4), - AFFINEANIMCMD_LOOP(2), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_QuestionMark[] = -{ - sAffineAnim_QuestionMark, -}; - -const struct SpriteTemplate gQuestionMarkSpriteTemplate = -{ - .tileTag = ANIM_TAG_AMNESIA, - .paletteTag = ANIM_TAG_AMNESIA, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_QuestionMark, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimQuestionMark, -}; - -static const union AffineAnimCmd sAffineAnim_MeditateStretchAttacker[] = -{ - AFFINEANIMCMD_FRAME(-8, 10, 0, 16), - AFFINEANIMCMD_FRAME(18, -18, 0, 16), - AFFINEANIMCMD_FRAME(-20, 16, 0, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_Teleport[] = -{ - AFFINEANIMCMD_FRAME(64, -4, 0, 20), - AFFINEANIMCMD_FRAME(0, 0, 0, -56), - AFFINEANIMCMD_END, -}; - -const struct SpriteTemplate gImprisonOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_HOLLOW_ORB, - .paletteTag = ANIM_TAG_HOLLOW_ORB, - .oam = &gOamData_AffineOff_ObjBlend_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCallbackDummy, -}; - -const struct SpriteTemplate gRedXSpriteTemplate = -{ - .tileTag = ANIM_TAG_X_SIGN, - .paletteTag = ANIM_TAG_X_SIGN, - .oam = &gOamData_AffineOff_ObjNormal_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimRedX, -}; - -static const union AffineAnimCmd sAffineAnim_SkillSwapOrb_0[] = -{ - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 8), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd sAffineAnim_SkillSwapOrb_1[] = -{ - AFFINEANIMCMD_FRAME(0xF0, 0xF0, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 6), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 2), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd sAffineAnim_SkillSwapOrb_2[] = -{ - AFFINEANIMCMD_FRAME(0xD0, 0xD0, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 4), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 4), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd sAffineAnim_SkillSwapOrb_3[] = -{ - AFFINEANIMCMD_FRAME(0xB0, 0xB0, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 2), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 6), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd *const sAffineAnims_SkillSwapOrb[] = -{ - sAffineAnim_SkillSwapOrb_0, - sAffineAnim_SkillSwapOrb_1, - sAffineAnim_SkillSwapOrb_2, - sAffineAnim_SkillSwapOrb_3, -}; - -const struct SpriteTemplate gSkillSwapOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_BLUEGREEN_ORB, - .paletteTag = ANIM_TAG_BLUEGREEN_ORB, - .oam = &gOamData_AffineNormal_ObjNormal_16x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_SkillSwapOrb, - .callback = AnimSkillSwapOrb, -}; - -static const union AffineAnimCmd sAffineAnim_LusterPurgeCircle[] = -{ - AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), - AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 120), - AFFINEANIMCMD_END_ALT(1), -}; - -static const union AffineAnimCmd *const sAffineAnims_LusterPurgeCircle[] = -{ - sAffineAnim_LusterPurgeCircle, -}; - -const struct SpriteTemplate gLusterPurgeCircleSpriteTemplate = -{ - .tileTag = ANIM_TAG_WHITE_CIRCLE_OF_LIGHT, - .paletteTag = ANIM_TAG_WHITE_CIRCLE_OF_LIGHT, - .oam = &gOamData_AffineDouble_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_LusterPurgeCircle, - .callback = AnimSpriteOnMonPos, -}; - -static const union AffineAnimCmd sAffineAnim_PsychoBoostOrb_0[] = -{ - AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), - AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 17), - AFFINEANIMCMD_LOOP(0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 10), - AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 10), - AFFINEANIMCMD_LOOP(4), - AFFINEANIMCMD_LOOP(0), - AFFINEANIMCMD_FRAME(0xFFF0, 0xFFF0, 0, 5), - AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 5), - AFFINEANIMCMD_LOOP(7), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sAffineAnim_PsychoBoostOrb_1[] = -{ - AFFINEANIMCMD_FRAME(0xFFEC, 0x18, 0, 15), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sAffineAnims_PsychoBoostOrb[] = -{ - sAffineAnim_PsychoBoostOrb_0, - sAffineAnim_PsychoBoostOrb_1, -}; - -const struct SpriteTemplate gPsychoBoostOrbSpriteTemplate = -{ - .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, - .oam = &gOamData_AffineDouble_ObjBlend_64x64, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = sAffineAnims_PsychoBoostOrb, - .callback = AnimPsychoBoost, -}; - -// For the rectangular wall sprite used by Reflect, Mirror Coat, etc -static void AnimDefensiveWall(struct Sprite *sprite) -{ - u8 isContest = IsContest(); - - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER || isContest) - { - sprite->oam.priority = 2; - sprite->subpriority = 200; - } - - if (!isContest) - { - u8 battlerCopy; - u8 battler = battlerCopy = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - u8 rank = GetBattlerSpriteBGPriorityRank(battler); - int var0 = 1; - u8 toBG_2 = (rank ^ var0) != 0; - - if (IsBattlerSpriteVisible(battler)) - MoveBattlerSpriteToBG(battler, toBG_2, FALSE); - - battler = BATTLE_PARTNER(battlerCopy); - if (IsBattlerSpriteVisible(battler)) - MoveBattlerSpriteToBG(battler, toBG_2 ^ var0, FALSE); - } - - if (!isContest && IsDoubleBattle()) - { - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) - { - sprite->pos1.x = 72; - sprite->pos1.y = 80; - } - else - { - sprite->pos1.x = 176; - sprite->pos1.y = 40; - } - } - else - { - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - gBattleAnimArgs[0] = -gBattleAnimArgs[0]; - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X) + gBattleAnimArgs[0]; - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + gBattleAnimArgs[1]; - } - - sprite->data[0] = 256 + IndexOfSpritePaletteTag(gBattleAnimArgs[2]) * 16; - - if (isContest) - { - sprite->pos1.y += 9; - sprite->callback = AnimDefensiveWall_Step2; - sprite->callback(sprite); - } - else - { - sprite->callback = AnimDefensiveWall_Step1; - } -} - -static void AnimDefensiveWall_Step1(struct Sprite *sprite) -{ - u8 battler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - if (!sprite->data[7]) - { - sprite->data[7] = 1; - return; - } - - if (IsBattlerSpriteVisible(battler)) - gSprites[gBattlerSpriteIds[battler]].invisible = TRUE; - - battler = BATTLE_PARTNER(battler); - if (IsBattlerSpriteVisible(battler)) - gSprites[gBattlerSpriteIds[battler]].invisible = TRUE; - - sprite->callback = AnimDefensiveWall_Step2; - sprite->callback(sprite); -} - -static void AnimDefensiveWall_Step2(struct Sprite *sprite) -{ - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[3], 16 - sprite->data[3])); - if (sprite->data[3] == 13) - sprite->callback = AnimDefensiveWall_Step3; - else - sprite->data[3]++; -} - -static void AnimDefensiveWall_Step3(struct Sprite *sprite) -{ - u16 color; - u16 startOffset; - int i; - - if (++sprite->data[1] == 2) - { - sprite->data[1] = 0; - startOffset = sprite->data[0]; - color = gPlttBufferFaded[startOffset + 8]; - - for (i = 8; i > 0; i--) - gPlttBufferFaded[startOffset + i] = gPlttBufferFaded[startOffset + i - 1]; - - gPlttBufferFaded[startOffset + 1] = color; - - if (++sprite->data[2] == 16) - sprite->callback = AnimDefensiveWall_Step4; - } -} - -static void AnimDefensiveWall_Step4(struct Sprite *sprite) -{ - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[3], 16 - sprite->data[3])); - - if (--sprite->data[3] == -1) - { - if (!IsContest()) - { - u8 battlerCopy; - u8 battler = battlerCopy = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - - if (IsBattlerSpriteVisible(battler)) - gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; - - battler = BATTLE_PARTNER(battlerCopy); - if (IsBattlerSpriteVisible(battler)) - gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; - } - - sprite->invisible = TRUE; - sprite->callback = AnimDefensiveWall_Step5; - } -} - -static void AnimDefensiveWall_Step5(struct Sprite *sprite) -{ - if (!IsContest()) - { - u8 battlerCopy; - u8 battler = battlerCopy = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - u8 rank = GetBattlerSpriteBGPriorityRank(battler); - int var0 = 1; - u8 toBG_2 = (rank ^ var0) != 0; - - if (IsBattlerSpriteVisible(battler)) - sub_80A477C(toBG_2); - - battler = battlerCopy ^ 2; - if (IsBattlerSpriteVisible(battler)) - sub_80A477C(toBG_2 ^ var0); - } - - sprite->callback = DestroyAnimSprite; -} - -// Animates the sparkle that appears during Reflect or Light Screen/Mirror Coat -static void AnimWallSparkle(struct Sprite *sprite) -{ - if (sprite->data[0] == 0) - { - int arg3 = gBattleAnimArgs[3]; - bool8 respectMonPicOffsets = FALSE; - if (arg3 == 0) - respectMonPicOffsets = TRUE; - - if (!IsContest() && IsDoubleBattle()) - { - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) - { - sprite->pos1.x = 72 - gBattleAnimArgs[0]; - sprite->pos1.y = gBattleAnimArgs[1] + 80; - } - else - { - sprite->pos1.x = gBattleAnimArgs[0] + 176; - sprite->pos1.y = gBattleAnimArgs[1] + 40; - } - } - else - { - if (gBattleAnimArgs[2] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, respectMonPicOffsets); - else - InitSpritePosToAnimTarget(sprite, respectMonPicOffsets); - } - - sprite->data[0]++; - } - else - { - if (sprite->animEnded || sprite->affineAnimEnded) - DestroySpriteAndMatrix(sprite); - } -} - -static void AnimBentSpoon(struct Sprite *sprite) -{ - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - StartSpriteAnim(sprite, 1); - sprite->pos1.x -= 40; - sprite->pos1.y += 10; - sprite->data[1] = -1; - } - else - { - sprite->pos1.x += 40; - sprite->pos1.y -= 10; - sprite->data[1] = 1; - } - - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); - sprite->callback = RunStoredCallbackWhenAnimEnds; -} - -// Used by Amnesia -static void AnimQuestionMark(struct Sprite *sprite) -{ - s16 x = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_WIDTH) / 2; - s16 y = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_HEIGHT) / -2; - - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) - x = -x; - - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2) + x; - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 3) + y; - - if (sprite->pos1.y < 16) - sprite->pos1.y = 16; - - StoreSpriteCallbackInData6(sprite, AnimQuestionMark_Step1); - sprite->callback = RunStoredCallbackWhenAnimEnds; -} - -static void AnimQuestionMark_Step1(struct Sprite *sprite) -{ - sprite->oam.affineMode = ST_OAM_AFFINE_NORMAL; - sprite->affineAnims = sAffineAnims_QuestionMark; - sprite->data[0] = 0; - InitSpriteAffineAnim(sprite); - sprite->callback = AnimQuestionMark_Step2; -} - -static void AnimQuestionMark_Step2(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - if (sprite->affineAnimEnded) - { - FreeOamMatrix(sprite->oam.matrixNum); - sprite->oam.affineMode = ST_OAM_AFFINE_OFF; - sprite->data[1] = 18; - sprite->data[0]++; - } - break; - case 1: - if (--sprite->data[1] == -1) - DestroyAnimSprite(sprite); - break; - } -} - -void AnimTask_MeditateStretchAttacker(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - task->data[0] = spriteId; - PrepareAffineAnimInTaskData(task, spriteId, sAffineAnim_MeditateStretchAttacker); - task->func = AnimTask_MeditateStretchAttacker_Step; -} - -static void AnimTask_MeditateStretchAttacker_Step(u8 taskId) -{ - if (!RunAffineAnimFromTaskData(&gTasks[taskId])) - DestroyAnimVisualTask(taskId); -} - -void AnimTask_Teleport(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); - task->data[0] = spriteId; - task->data[1] = 0; - task->data[2] = 0; - task->data[3] = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 4 : 8; - - PrepareAffineAnimInTaskData(task, task->data[0], sAffineAnim_Teleport); - task->func = AnimTask_Teleport_Step; -} - -static void AnimTask_Teleport_Step(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[1]) - { - case 0: - RunAffineAnimFromTaskData(task); - if (++task->data[2] > 19) - task->data[1]++; - break; - case 1: - if (task->data[3] != 0) - { - gSprites[task->data[0]].pos2.y -= 8; - task->data[3]--; - } - else - { - gSprites[task->data[0]].invisible = TRUE; - gSprites[task->data[0]].pos1.x = 272; - ResetSpriteRotScale(task->data[0]); - DestroyAnimVisualTask(taskId); - } - break; - } -} - -void AnimTask_ImprisonOrbs(u8 taskId) -{ - u16 var0, var1; - - struct Task *task = &gTasks[taskId]; - - task->data[3] = 16; - task->data[4] = 0; - task->data[13] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - - var0 = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_WIDTH) / 3; - var1 = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_HEIGHT) / 3; - task->data[12] = var0 > var1 ? var0 : var1; - - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); - - task->func = AnimTask_ImprisonOrbs_Step; -} - -static void AnimTask_ImprisonOrbs_Step(u8 taskId) -{ - u16 i; - u8 spriteId; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - if (++task->data[1] > 8) - { - task->data[1] = 0; - spriteId = CreateSprite(&gImprisonOrbSpriteTemplate, task->data[13], task->data[14], 0); - task->data[task->data[2] + 8] = spriteId; - if (spriteId != MAX_SPRITES) - { - switch (task->data[2]) - { - case 0: - gSprites[spriteId].pos2.x = task->data[12]; - gSprites[spriteId].pos2.y = -task->data[12]; - break; - case 1: - gSprites[spriteId].pos2.x = -task->data[12]; - gSprites[spriteId].pos2.y = task->data[12]; - break; - case 2: - gSprites[spriteId].pos2.x = task->data[12]; - gSprites[spriteId].pos2.y = task->data[12]; - break; - case 3: - gSprites[spriteId].pos2.x = -task->data[12]; - gSprites[spriteId].pos2.y = -task->data[12]; - break; - } - } - - if (++task->data[2] == 5) - task->data[0]++; - } - break; - case 1: - if (task->data[1] & 1) - task->data[3]--; - else - task->data[4]++; - - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4])); - if (++task->data[1] == 32) - { - for (i = 8; i < 13; i++) - { - if (task->data[i] != 64) - DestroySprite(&gSprites[task->data[i]]); - } - - task->data[0]++; - } - break; - case 2: - task->data[0]++; - break; - case 3: - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - SetGpuReg(REG_OFFSET_BLDCNT, 0); - DestroyAnimVisualTask(taskId); - break; - } -} - -static void sub_810FB60(struct Sprite *sprite) -{ - if (sprite->data[1] > sprite->data[0] - 10) - sprite->invisible = sprite->data[1] & 1; - - if (sprite->data[1] == sprite->data[0]) - DestroyAnimSprite(sprite); - - sprite->data[1]++; -} - -static void AnimRedX(struct Sprite *sprite) -{ - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - { - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - } - - sprite->data[0] = gBattleAnimArgs[1]; - sprite->callback = sub_810FB60; -} - -void AnimTask_SkillSwap(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - if (IsContest()) - { - if (gBattleAnimArgs[0] == ANIM_TARGET) - { - task->data[10] = -10; - task->data[11] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_RIGHT) - 8; - task->data[12] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_TOP) + 8; - task->data[13] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_RIGHT) - 8; - task->data[14] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_TOP) + 8; - } - else - { - task->data[10] = 10; - task->data[11] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_LEFT) + 8; - task->data[12] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_BOTTOM) - 8; - task->data[13] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_LEFT) + 8; - task->data[14] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_BOTTOM) - 8; - } - } - else - { - if (gBattleAnimArgs[0] == 1) - { - task->data[10] = -10; - task->data[11] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_LEFT) + 8; - task->data[12] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_TOP) + 8; - task->data[13] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_LEFT) + 8; - task->data[14] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_TOP) + 8; - } - else - { - task->data[10] = 10; - task->data[11] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_RIGHT) - 8; - task->data[12] = GetBattlerSpriteCoordAttr(gBattleAnimAttacker, BATTLER_COORD_ATTR_BOTTOM) - 8; - task->data[13] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_RIGHT) - 8; - task->data[14] = GetBattlerSpriteCoordAttr(gBattleAnimTarget, BATTLER_COORD_ATTR_BOTTOM) - 8; - } - } - - task->data[1] = 6; - task->func = AnimTask_SkillSwap_Step; -} - -static void AnimTask_SkillSwap_Step(u8 taskId) -{ - u8 spriteId; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - if (++task->data[1] > 6) - { - task->data[1] = 0; - spriteId = CreateSprite(&gSkillSwapOrbSpriteTemplate, task->data[11], task->data[12], 0); - if (spriteId != 64) - { - gSprites[spriteId].data[0] = 16; - gSprites[spriteId].data[2] = task->data[13]; - gSprites[spriteId].data[4] = task->data[14]; - gSprites[spriteId].data[5] = task->data[10]; - - InitAnimArcTranslation(&gSprites[spriteId]); - StartSpriteAffineAnim(&gSprites[spriteId], task->data[2] & 3); - } - - if (++task->data[2] == 12) - task->data[0]++; - } - break; - case 1: - if (++task->data[1] > 17) - DestroyAnimVisualTask(taskId); - break; - } -} - -static void AnimSkillSwapOrb(struct Sprite *sprite) -{ - if (TranslateAnimHorizontalArc(sprite)) - { - FreeOamMatrix(sprite->oam.matrixNum); - DestroySprite(sprite); - } -} - -// The scanline effect that distorts the target during Extrasensory by segmenting the mon vertically and shifting the slices -// arg0: Stage. Stage 0 is a slight right distortion, 1 is a medium left distortion, and 2 is a severe right distortion -void AnimTask_ExtrasensoryDistortion(u8 taskId) -{ - s16 i; - u8 yOffset; - struct ScanlineEffectParams scanlineParams; - struct Task *task = &gTasks[taskId]; - - yOffset = GetBattlerYCoordWithElevation(gBattleAnimTarget); - task->data[14] = yOffset - 32; - - switch (gBattleAnimArgs[0]) - { - case 0: - task->data[11] = 2; - task->data[12] = 5; - task->data[13] = 64; - task->data[15] = yOffset + 32; - break; - case 1: - task->data[11] = 2; - task->data[12] = 5; - task->data[13] = 192; - task->data[15] = yOffset + 32; - break; - case 2: - task->data[11] = 4; - task->data[12] = 4; - task->data[13] = 0; - task->data[15] = yOffset + 32; - break; - } - - if (task->data[14] < 0) - task->data[14] = 0; - - if (GetBattlerSpriteBGPriorityRank(gBattleAnimTarget) == 1) - { - task->data[10] = gBattle_BG1_X; - scanlineParams.dmaDest = ®_BG1HOFS; - } - else - { - task->data[10] = gBattle_BG2_X; - scanlineParams.dmaDest = ®_BG2HOFS; - } - - i = task->data[14]; - while (i <= task->data[14] + 64) - { - gScanlineEffectRegBuffers[0][i] = task->data[10]; - gScanlineEffectRegBuffers[1][i] = task->data[10]; - i++; - } - - scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; - scanlineParams.initState = 1; - scanlineParams.unused9 = 0; - ScanlineEffect_SetParams(scanlineParams); - task->func = AnimTask_ExtrasensoryDistortion_Step; -} - -static void AnimTask_ExtrasensoryDistortion_Step(u8 taskId) -{ - s16 sineIndex, i; - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - sineIndex = task->data[13]; - i = task->data[14]; - while (i <= task->data[15]) - { - s16 var2 = (gSineTable[sineIndex] >> task->data[12]); - if (var2 > 0) - var2 += (task->data[1] & 3); - else if (var2 < 0) - var2 -= (task->data[1] & 3); - - gScanlineEffectRegBuffers[0][i] = task->data[10] + var2; - gScanlineEffectRegBuffers[1][i] = task->data[10] + var2; - sineIndex += task->data[11]; - i++; - } - - if (++task->data[1] > 23) - task->data[0]++; - break; - case 1: - gScanlineEffect.state = 3; - task->data[0]++; - break; - case 2: - DestroyAnimVisualTask(taskId); - break; - } -} - -// Creates a cloned transparent sprite of the battler that grows and then shrinks back to original size. Used by Extrasensory -// arg0: battler -void AnimTask_TransparentCloneGrowAndShrink(u8 taskId) -{ - s16 spriteId; - s16 matrixNum; - struct Task *task = &gTasks[taskId]; - - matrixNum = AllocOamMatrix(); - if (matrixNum == 0xFF) - { - DestroyAnimVisualTask(taskId); - return; - } - - spriteId = CloneBattlerSpriteWithBlend(gBattleAnimArgs[0]); - if (spriteId < 0) - { - FreeOamMatrix(matrixNum); - DestroyAnimVisualTask(taskId); - return; - } - - gSprites[spriteId].callback = SpriteCallbackDummy; - gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_DOUBLE; - gSprites[spriteId].oam.matrixNum = matrixNum; - gSprites[spriteId].affineAnimPaused = 1; - gSprites[spriteId].subpriority++; - SetSpriteRotScale(spriteId, 256, 256, 0); - CalcCenterToCornerVec(&gSprites[spriteId], gSprites[spriteId].oam.shape, gSprites[spriteId].oam.size, gSprites[spriteId].oam.affineMode); - task->data[13] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); - task->data[14] = matrixNum; - task->data[15] = spriteId; - task->func = AnimTask_TransparentCloneGrowAndShrink_Step; -} - -static void AnimTask_TransparentCloneGrowAndShrink_Step(u8 taskId) -{ - struct Task *task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[1] += 4; - task->data[2] = 256 - (gSineTable[task->data[1]] >> 1); - SetSpriteRotScale(task->data[15], task->data[2], task->data[2], 0); - SetBattlerSpriteYOffsetFromOtherYScale(task->data[15], task->data[13]); - if (task->data[1] == 48) - task->data[0]++; - break; - case 1: - task->data[1] -= 4; - task->data[2] = 256 - (gSineTable[task->data[1]] >> 1);; - SetSpriteRotScale(task->data[15], task->data[2], task->data[2], 0); - SetBattlerSpriteYOffsetFromOtherYScale(task->data[15], task->data[13]); - if (task->data[1] == 0) - task->data[0]++; - break; - case 2: - obj_delete_but_dont_free_vram(&gSprites[task->data[15]]); - task->data[0]++; - break; - case 3: - FreeOamMatrix(task->data[14]); - DestroyAnimVisualTask(taskId); - break; - } -} - -static void AnimPsychoBoost(struct Sprite *sprite) -{ - switch (sprite->data[0]) - { - case 0: - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y); - - if (IsContest()) - sprite->pos1.y += 12; - - sprite->data[1] = 8; - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[1], 16 - sprite->data[1])); - sprite->data[0]++; - break; - case 1: - if (sprite->affineAnimEnded) - { - PlaySE12WithPanning(SE_W100, BattleAnimAdjustPanning(-64)); - ChangeSpriteAffineAnim(sprite, 1); - sprite->data[0]++; - } - break; - case 2: - if (sprite->data[2]++ > 1) - { - sprite->data[2] = 0; - sprite->data[1]--; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[1], 16 - sprite->data[1])); - if (sprite->data[1] == 0) - { - sprite->data[0]++; - sprite->invisible = TRUE; - } - } - - sprite->data[3] += 0x380; - sprite->pos2.y -= sprite->data[3] >> 8; - sprite->data[3] &= 0xFF; - break; - case 3: - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - DestroyAnimSprite(sprite); - break; - } -} diff --git a/src/rock.c b/src/rock.c deleted file mode 100644 index ced3e5ba8..000000000 --- a/src/rock.c +++ /dev/null @@ -1,875 +0,0 @@ -#include "global.h" -#include "battle_anim.h" -#include "gpu_regs.h" -#include "graphics.h" -#include "palette.h" -#include "sound.h" -#include "task.h" -#include "trig.h" -#include "constants/rgb.h" -#include "constants/songs.h" - -static void AnimFallingRock(struct Sprite *); -static void AnimFallingRock_Step(struct Sprite *); -static void AnimRockFragment(struct Sprite *); -static void AnimFlyingSandCrescent(struct Sprite *); -static void AnimRaiseSprite(struct Sprite *); -static void AnimTask_Rollout_Step(u8 taskId); -static void AnimRolloutParticle(struct Sprite *); -static void AnimRockTomb(struct Sprite *); -static void AnimRockTomb_Step(struct Sprite *sprite); -static void AnimRockBlastRock(struct Sprite *); -static void AnimRockScatter(struct Sprite *); -static void AnimRockScatter_Step(struct Sprite *sprite); -static void AnimParticleInVortex(struct Sprite *); -static void AnimParticleInVortex_Step(struct Sprite *sprite); -static void AnimTask_LoadSandstormBackground_Step(u8 taskId); -static void sub_8111214(struct Task *task); -static u8 GetRolloutCounter(void); - -static const union AnimCmd sAnim_FlyingRock_0[] = -{ - ANIMCMD_FRAME(32, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_FlyingRock_1[] = -{ - ANIMCMD_FRAME(48, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_FlyingRock_2[] = -{ - ANIMCMD_FRAME(64, 1), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_FlyingRock[] = -{ - sAnim_FlyingRock_0, - sAnim_FlyingRock_1, - sAnim_FlyingRock_2, -}; - -const struct SpriteTemplate gFallingRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_FlyingRock, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFallingRock, -}; - -const struct SpriteTemplate gRockFragmentSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_FlyingRock, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimRockFragment, -}; - -const struct SpriteTemplate gSwirlingDirtSpriteTemplate = -{ - .tileTag = ANIM_TAG_MUD_SAND, - .paletteTag = ANIM_TAG_MUD_SAND, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimParticleInVortex, -}; - -static const union AffineAnimCmd sAffineAnim_Whirlpool[] = -{ - AFFINEANIMCMD_FRAME(0xC0, 0xC0, 0, 0), - AFFINEANIMCMD_FRAME(0x2, 0xFFFD, 0, 5), - AFFINEANIMCMD_FRAME(0xFFFE, 0x3, 0, 5), - AFFINEANIMCMD_JUMP(1), -}; - -static const union AffineAnimCmd *const sAffineAnims_Whirlpool[] = -{ - sAffineAnim_Whirlpool, -}; - -const struct SpriteTemplate gWhirlpoolSpriteTemplate = -{ - .tileTag = ANIM_TAG_WATER_ORB, - .paletteTag = ANIM_TAG_WATER_ORB, - .oam = &gOamData_AffineNormal_ObjBlend_16x16, - .anims = gAnims_WaterMudOrb, - .images = NULL, - .affineAnims = sAffineAnims_Whirlpool, - .callback = AnimParticleInVortex, -}; - -const struct SpriteTemplate gFireSpinSpriteTemplate = -{ - .tileTag = ANIM_TAG_SMALL_EMBER, - .paletteTag = ANIM_TAG_SMALL_EMBER, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gAnims_BasicFire, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimParticleInVortex, -}; - -const struct SpriteTemplate gFlyingSandCrescentSpriteTemplate = -{ - .tileTag = ANIM_TAG_FLYING_DIRT, - .paletteTag = ANIM_TAG_FLYING_DIRT, - .oam = &gOamData_AffineOff_ObjNormal_32x16, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimFlyingSandCrescent, -}; - -static const struct Subsprite sFlyingSandSubsprites[] = -{ - {.x = -16, .y = 0, .shape = SPRITE_SHAPE(32x16), .size = SPRITE_SIZE(32x16), .tileOffset = 0, .priority = 1}, - {.x = 16, .y = 0, .shape = SPRITE_SHAPE(32x16), .size = SPRITE_SIZE(32x16), .tileOffset = 8, .priority = 1}, -}; - -static const struct SubspriteTable sFlyingSandSubspriteTable[] = -{ - {ARRAY_COUNT(sFlyingSandSubsprites), sFlyingSandSubsprites}, -}; - -static const union AnimCmd sAnim_BasicRock_0[] = -{ - ANIMCMD_FRAME(0, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_BasicRock_1[] = -{ - ANIMCMD_FRAME(16, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_WeatherBallRockDown_0[] = -{ - ANIMCMD_FRAME(32, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_WeatherBallRockDown_1[] = -{ - ANIMCMD_FRAME(48, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_TwisterRock_0[] = -{ - ANIMCMD_FRAME(64, 1), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_TwisterRock_1[] = -{ - ANIMCMD_FRAME(80, 1), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_BasicRock[] = -{ - sAnim_BasicRock_0, - sAnim_BasicRock_1, -}; - -static const union AnimCmd *const sAnims_WeatherBallRockDown[] = -{ - sAnim_WeatherBallRockDown_0, - sAnim_WeatherBallRockDown_1, -}; - -static const union AnimCmd *const sAnims_TwisterRock[] = -{ - sAnim_TwisterRock_0, - sAnim_TwisterRock_1, -}; - -const struct SpriteTemplate gAncientPowerRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_BasicRock, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimRaiseSprite, -}; - -const struct SpriteTemplate gRolloutMudSpriteTemplate = -{ - .tileTag = ANIM_TAG_MUD_SAND, - .paletteTag = ANIM_TAG_MUD_SAND, - .oam = &gOamData_AffineOff_ObjNormal_8x8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimRolloutParticle, -}; - -const struct SpriteTemplate gRolloutRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimRolloutParticle, -}; - -const struct SpriteTemplate gRockTombRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_BasicRock, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimRockTomb, -}; - -static const union AffineAnimCmd sAffineAnim_BasicRock_0[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, -5, 5), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd sAffineAnim_BasicRock_1[] = -{ - AFFINEANIMCMD_FRAME(0x0, 0x0, 5, 5), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd *const sAffineAnims_BasicRock[] = -{ - sAffineAnim_BasicRock_0, - sAffineAnim_BasicRock_1, -}; - -const struct SpriteTemplate gRockBlastRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = sAnims_BasicRock, - .images = NULL, - .affineAnims = sAffineAnims_BasicRock, - .callback = AnimRockBlastRock, -}; - -const struct SpriteTemplate gRockScatterSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = sAnims_BasicRock, - .images = NULL, - .affineAnims = sAffineAnims_BasicRock, - .callback = AnimRockScatter, -}; - -const struct SpriteTemplate gTwisterRockSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_TwisterRock, - .images = NULL, - .affineAnims = sAffineAnims_BasicRock, - .callback = AnimMoveTwisterParticle, -}; - -const struct SpriteTemplate gWeatherBallRockDownSpriteTemplate = -{ - .tileTag = ANIM_TAG_ROCKS, - .paletteTag = ANIM_TAG_ROCKS, - .oam = &gOamData_AffineNormal_ObjNormal_32x32, - .anims = sAnims_WeatherBallRockDown, - .images = NULL, - .affineAnims = sAffineAnims_BasicRock, - .callback = AnimWeatherBallDown, -}; - -static void AnimFallingRock(struct Sprite *sprite) -{ - if (gBattleAnimArgs[3] != 0) - SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); - - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += 14; - - StartSpriteAnim(sprite, gBattleAnimArgs[1]); - AnimateSprite(sprite); - - sprite->data[0] = 0; - sprite->data[1] = 0; - sprite->data[2] = 4; - sprite->data[3] = 16; - sprite->data[4] = -70; - sprite->data[5] = gBattleAnimArgs[2]; - - StoreSpriteCallbackInData6(sprite, AnimFallingRock_Step); - sprite->callback = TranslateSpriteInEllipseOverDuration; - sprite->callback(sprite); -} - -static void AnimFallingRock_Step(struct Sprite *sprite) -{ - sprite->pos1.x += sprite->data[5]; - - sprite->data[0] = 192; - sprite->data[1] = sprite->data[5]; - sprite->data[2] = 4; - sprite->data[3] = 32; - sprite->data[4] = -24; - - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); - sprite->callback = TranslateSpriteInEllipseOverDuration; - sprite->callback(sprite); -} - -// Animates the rock particles that are shown on the impact for Rock Blast / Rock Smash -static void AnimRockFragment(struct Sprite *sprite) -{ - StartSpriteAnim(sprite, gBattleAnimArgs[5]); - AnimateSprite(sprite); - - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - sprite->pos1.x -= gBattleAnimArgs[0]; - else - sprite->pos1.x += gBattleAnimArgs[0]; - - sprite->pos1.y += gBattleAnimArgs[1]; - - sprite->data[0] = gBattleAnimArgs[4]; - sprite->data[1] = sprite->pos1.x; - sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; - sprite->data[3] = sprite->pos1.y; - sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[3]; - - InitSpriteDataForLinearTranslation(sprite); - sprite->data[3] = 0; - sprite->data[4] = 0; - - sprite->callback = TranslateSpriteLinearFixedPoint; - StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); -} - -// Swirls particle in vortex. Used for moves like Fire Spin or Sand Tomb -static void AnimParticleInVortex(struct Sprite *sprite) -{ - if (gBattleAnimArgs[6] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, 0); - else - InitSpritePosToAnimTarget(sprite, FALSE); - - sprite->data[0] = gBattleAnimArgs[3]; - sprite->data[1] = gBattleAnimArgs[2]; - sprite->data[2] = gBattleAnimArgs[4]; - sprite->data[3] = gBattleAnimArgs[5]; - - sprite->callback = AnimParticleInVortex_Step; -} - -static void AnimParticleInVortex_Step(struct Sprite *sprite) -{ - sprite->data[4] += sprite->data[1]; - sprite->pos2.y = -(sprite->data[4] >> 8); - sprite->pos2.x = Sin(sprite->data[5], sprite->data[3]); - sprite->data[5] = (sprite->data[5] + sprite->data[2]) & 0xFF; - - if (--sprite->data[0] == -1) - { - DestroyAnimSprite(sprite); - } -} - -void AnimTask_LoadSandstormBackground(u8 taskId) -{ - int var0; - struct BattleAnimBgData animBg; - - var0 = 0; - SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); - SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); - SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); - - if (!IsContest()) - SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); - - gBattle_BG1_X = 0; - gBattle_BG1_Y = 0; - SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); - SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); - - sub_80A6B30(&animBg); - AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Sandstorm, animBg.tilesOffset); - AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_Sandstorm, 0); - LoadCompressedPalette(gBattleAnimSpritePal_FlyingDirt, animBg.paletteId * 16, 32); - - if (gBattleAnimArgs[0] && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - var0 = 1; - - gTasks[taskId].data[0] = var0; - gTasks[taskId].func = AnimTask_LoadSandstormBackground_Step; -} - -static void AnimTask_LoadSandstormBackground_Step(u8 taskId) -{ - struct BattleAnimBgData animBg; - - if (gTasks[taskId].data[0] == 0) - gBattle_BG1_X += -6; - else - gBattle_BG1_X += 6; - - gBattle_BG1_Y += -1; - - switch (gTasks[taskId].data[12]) - { - case 0: - if (++gTasks[taskId].data[10] == 4) - { - gTasks[taskId].data[10] = 0; - gTasks[taskId].data[11]++; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); - if (gTasks[taskId].data[11] == 7) - { - gTasks[taskId].data[12]++; - gTasks[taskId].data[11] = 0; - } - } - break; - case 1: - if (++gTasks[taskId].data[11] == 101) - { - gTasks[taskId].data[11] = 7; - gTasks[taskId].data[12]++; - } - break; - case 2: - if (++gTasks[taskId].data[10] == 4) - { - gTasks[taskId].data[10] = 0; - gTasks[taskId].data[11]--; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); - if (gTasks[taskId].data[11] == 0) - { - gTasks[taskId].data[12]++; - gTasks[taskId].data[11] = 0; - } - } - break; - case 3: - sub_80A6B30(&animBg); - sub_80A6C68(animBg.bgId); - gTasks[taskId].data[12]++; - break; - case 4: - if (!IsContest()) - SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); - - gBattle_BG1_X = 0; - gBattle_BG1_Y = 0; - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); - DestroyAnimVisualTask(taskId); - break; - } -} - -// Animates the sprites that fly diagonally across the screen -// in Sandstorm and Heat Wave. -// arg 0: initial y pixel offset -// arg 1: projectile speed -// arg 2: y pixel drop -// arg 3: ??? unknown (possibly a color bit) -static void AnimFlyingSandCrescent(struct Sprite *sprite) -{ - if (sprite->data[0] == 0) - { - if (gBattleAnimArgs[3] != 0 && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) - { - sprite->pos1.x = 304; - gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - sprite->data[5] = 1; - sprite->oam.matrixNum = ST_OAM_HFLIP; - } - else - { - sprite->pos1.x = -64; - } - - sprite->pos1.y = gBattleAnimArgs[0]; - SetSubspriteTables(sprite, sFlyingSandSubspriteTable); - sprite->data[1] = gBattleAnimArgs[1]; - sprite->data[2] = gBattleAnimArgs[2]; - sprite->data[0]++; - } - else - { - sprite->data[3] += sprite->data[1]; - sprite->data[4] += sprite->data[2]; - sprite->pos2.x += (sprite->data[3] >> 8); - sprite->pos2.y += (sprite->data[4] >> 8); - sprite->data[3] &= 0xFF; - sprite->data[4] &= 0xFF; - - if (sprite->data[5] == 0) - { - if (sprite->pos1.x + sprite->pos2.x > 272) - { - sprite->callback = DestroyAnimSprite; - } - } - else if (sprite->pos1.x + sprite->pos2.x < -32) - { - sprite->callback = DestroyAnimSprite; - } - } -} - -// Animates the rising rocks in Ancient Power. -// arg 0: initial x pixel offset -// arg 1: initial y pixel offset -// arg 2: terminal y offset -// arg 3: duration -// arg 4: sprite size [1,5] -static void AnimRaiseSprite(struct Sprite *sprite) -{ - StartSpriteAnim(sprite, gBattleAnimArgs[4]); - InitSpritePosToAnimAttacker(sprite, 0); - - sprite->data[0] = gBattleAnimArgs[3]; - sprite->data[2] = sprite->pos1.x; - sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[2]; - - sprite->callback = StartAnimLinearTranslation; - StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); -} - -void AnimTask_Rollout(u8 taskId) -{ - u16 var0, var1, var2, var3; - u8 rolloutCounter; - int var5; - s16 pan1, pan2; - struct Task *task; - - task = &gTasks[taskId]; - - var0 = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - var1 = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 24; - var2 = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - var3 = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 24; - - if (BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget) - var3 = var1; - - rolloutCounter = GetRolloutCounter(); - if (rolloutCounter == 1) - task->data[8] = 32; - else - task->data[8] = 48 - (rolloutCounter * 8); - - task->data[0] = 0; - task->data[11] = 0; - task->data[9] = 0; - task->data[12] = 1; - - var5 = task->data[8]; - if (var5 < 0) - var5 += 7; - - task->data[10] = (var5 >> 3) - 1; - - task->data[2] = var0 * 8; - task->data[3] = var1 * 8; - task->data[4] = ((var2 - var0) * 8) / task->data[8]; - task->data[5] = ((var3 - var1) * 8) / task->data[8]; - task->data[6] = 0; - task->data[7] = 0; - - pan1 = BattleAnimAdjustPanning(-64); - pan2 = BattleAnimAdjustPanning(63); - - task->data[13] = pan1; - task->data[14] = (pan2 - pan1) / task->data[8]; - task->data[1] = rolloutCounter; - task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); - - task->func = AnimTask_Rollout_Step; -} - -static void AnimTask_Rollout_Step(u8 taskId) -{ - struct Task *task; - - task = &gTasks[taskId]; - - switch (task->data[0]) - { - case 0: - task->data[6] -= task->data[4]; - task->data[7] -= task->data[5]; - gSprites[task->data[15]].pos2.x = task->data[6] >> 3; - gSprites[task->data[15]].pos2.y = task->data[7] >> 3; - - if (++task->data[9] == 10) - { - task->data[11] = 20; - task->data[0]++; - } - - PlaySE12WithPanning(SE_W029, task->data[13]); - break; - case 1: - if (--task->data[11] == 0) - task->data[0]++; - break; - case 2: - if (--task->data[9] != 0) - { - task->data[6] += task->data[4]; - task->data[7] += task->data[5]; - } - else - { - task->data[6] = 0; - task->data[7] = 0; - task->data[0]++; - } - - gSprites[task->data[15]].pos2.x = task->data[6] >> 3; - gSprites[task->data[15]].pos2.y = task->data[7] >> 3; - break; - case 3: - task->data[2] += task->data[4]; - task->data[3] += task->data[5]; - if (++task->data[9] >= task->data[10]) - { - task->data[9] = 0; - sub_8111214(task); - task->data[13] += task->data[14]; - PlaySE12WithPanning(SE_W091, task->data[13]); - } - - if (--task->data[8] == 0) - { - task->data[0]++; - } - break; - case 4: - if (task->data[11] == 0) - DestroyAnimVisualTask(taskId); - break; - } -} - -static void sub_8111214(struct Task *task) -{ - const struct SpriteTemplate *spriteTemplate; - int tileOffset; - u16 x, y; - u8 spriteId; - - switch (task->data[1]) - { - case 1: - spriteTemplate = &gRolloutMudSpriteTemplate; - tileOffset = 0; - break; - case 2: - case 3: - spriteTemplate = &gRolloutRockSpriteTemplate; - tileOffset = 80; - break; - case 4: - spriteTemplate = &gRolloutRockSpriteTemplate; - tileOffset = 64; - break; - case 5: - spriteTemplate = &gRolloutRockSpriteTemplate; - tileOffset = 48; - break; - default: - return; - } - - x = task->data[2] >> 3; - y = task->data[3] >> 3; - x += (task->data[12] * 4); - - spriteId = CreateSprite(spriteTemplate, x, y, 35); - if (spriteId != MAX_SPRITES) - { - gSprites[spriteId].data[0] = 18; - gSprites[spriteId].data[2] = ((task->data[12] * 20) + x) + (task->data[1] * 3); - gSprites[spriteId].data[4] = y; - gSprites[spriteId].data[5] = -16 - (task->data[1] * 2); - gSprites[spriteId].oam.tileNum += tileOffset; - - InitAnimArcTranslation(&gSprites[spriteId]); - task->data[11]++; - } - - task->data[12] *= -1; -} - -static void AnimRolloutParticle(struct Sprite *sprite) -{ - if (TranslateAnimHorizontalArc(sprite)) - { - u8 taskId = FindTaskIdByFunc(AnimTask_Rollout_Step); - if (taskId != 0xFF) - gTasks[taskId].data[11]--; - - DestroySprite(sprite); - } -} - -static u8 GetRolloutCounter(void) -{ - u8 retVal = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer; - u8 var0 = retVal - 1; - if (var0 > 4) - retVal = 1; - - return retVal; -} - -static void AnimRockTomb(struct Sprite *sprite) -{ - StartSpriteAnim(sprite, gBattleAnimArgs[4]); - - sprite->pos2.x = gBattleAnimArgs[0]; - sprite->data[2] = gBattleAnimArgs[1]; - sprite->data[3] -= gBattleAnimArgs[2]; - sprite->data[0] = 3; - sprite->data[1] = gBattleAnimArgs[3]; - sprite->callback = AnimRockTomb_Step; - sprite->invisible = TRUE; -} - -static void AnimRockTomb_Step(struct Sprite *sprite) -{ - sprite->invisible = FALSE; - if (sprite->data[3] != 0) - { - sprite->pos2.y = sprite->data[2] + sprite->data[3]; - sprite->data[3] += sprite->data[0]; - sprite->data[0]++; - if (sprite->data[3] > 0) - { - sprite->data[3] = 0; - } - } - else - { - if (--sprite->data[1] == 0) - DestroyAnimSprite(sprite); - } -} - -static void AnimRockBlastRock(struct Sprite *sprite) -{ - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) - StartSpriteAffineAnim(sprite, 1); - - TranslateAnimSpriteToTargetMonLocation(sprite); -} - -static void AnimRockScatter(struct Sprite *sprite) -{ - sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); - sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); - sprite->pos1.x += gBattleAnimArgs[0]; - sprite->pos1.y += gBattleAnimArgs[1]; - - sprite->data[1] = gBattleAnimArgs[0]; - sprite->data[2] = gBattleAnimArgs[1]; - sprite->data[5] = gBattleAnimArgs[2]; - - StartSpriteAnim(sprite, gBattleAnimArgs[3]); - sprite->callback = AnimRockScatter_Step; -} - -static void AnimRockScatter_Step(struct Sprite *sprite) -{ - sprite->data[0] += 8; - sprite->data[3] += sprite->data[1]; - sprite->data[4] += sprite->data[2]; - - sprite->pos2.x += sprite->data[3] / 40; - sprite->pos2.y -= Sin(sprite->data[0], sprite->data[5]); - - if (sprite->data[0] > 140) - DestroyAnimSprite(sprite); -} - -void AnimTask_GetSeismicTossDamageLevel(u8 taskId) -{ - if (gAnimMoveDmg < 33) - gBattleAnimArgs[ARG_RET_ID] = 0; - if ((u32)gAnimMoveDmg - 33 < 33) - gBattleAnimArgs[ARG_RET_ID] = 1; - if (gAnimMoveDmg > 65) - gBattleAnimArgs[ARG_RET_ID] = 2; - - DestroyAnimVisualTask(taskId); -} - -void AnimTask_MoveSeismicTossBg(u8 taskId) -{ - if (gTasks[taskId].data[0] == 0) - { - sub_80A6DAC(FALSE); - gTasks[taskId].data[1] = 200; - } - - gBattle_BG3_Y += gTasks[taskId].data[1] / 10; - gTasks[taskId].data[1] -= 3; - - if (gTasks[taskId].data[0] == 120) - { - sub_80A6DAC(TRUE); - DestroyAnimVisualTask(taskId); - } - - gTasks[taskId].data[0]++; -} - -void AnimTask_SeismicTossBgAccelerateDownAtEnd(u8 taskId) -{ - if (gTasks[taskId].data[0] == 0) - { - sub_80A6DAC(FALSE); - gTasks[taskId].data[0]++; - gTasks[taskId].data[2] = gBattle_BG3_Y; - } - - gTasks[taskId].data[1] += 80; - gTasks[taskId].data[1] &= 0xFF; - gBattle_BG3_Y = gTasks[taskId].data[2] + Cos(4, gTasks[taskId].data[1]); - - if (gBattleAnimArgs[ARG_RET_ID] == 0xFFF) - { - gBattle_BG3_Y = 0; - sub_80A6DAC(TRUE); - DestroyAnimVisualTask(taskId); - } -} diff --git a/src/smokescreen.c b/src/smokescreen.c deleted file mode 100644 index 7d83251bc..000000000 --- a/src/smokescreen.c +++ /dev/null @@ -1,217 +0,0 @@ -#include "global.h" -#include "battle_gfx_sfx_util.h" -#include "data.h" -#include "decompress.h" -#include "graphics.h" -#include "sprite.h" -#include "util.h" -#include "constants/pokemon.h" - -static void SmokescreenImpact_Callback(struct Sprite *); -static void SpriteCB_DestroySprite(struct Sprite *sprite); - -// The below data for smokescreen starts and ends with some data that belongs to battle_gfx_sfx_util.c - -const u8 gUnknown_0831C604[] = -{ - [NATURE_HARDY] = 0, - [NATURE_LONELY] = 0, - [NATURE_BRAVE] = 1, - [NATURE_ADAMANT] = 0, - [NATURE_NAUGHTY] = 1, - [NATURE_BOLD] = 1, - [NATURE_DOCILE] = 2, - [NATURE_RELAXED] = 0, - [NATURE_IMPISH] = 0, - [NATURE_LAX] = 0, - [NATURE_TIMID] = 1, - [NATURE_HASTY] = 1, - [NATURE_SERIOUS] = 1, - [NATURE_JOLLY] = 0, - [NATURE_NAIVE] = 2, - [NATURE_MODEST] = 1, - [NATURE_MILD] = 0, - [NATURE_QUIET] = 1, - [NATURE_BASHFUL] = 1, - [NATURE_RASH] = 0, - [NATURE_CALM] = 0, - [NATURE_GENTLE] = 0, - [NATURE_SASSY] = 1, - [NATURE_CAREFUL] = 1, - [NATURE_QUIRKY] = 0, -}; - -static const struct CompressedSpriteSheet gSmokescreenImpactSpriteSheet = -{ - .data = gSmokescreenImpactTiles, .size = 0x180, .tag = 55019 -}; - -static const struct CompressedSpritePalette gSmokescreenlImpactSpritePalette = -{ - .data = gSmokescreenImpactPalette, .tag = 55019 -}; - -static const struct OamData gUnknown_0831C630 = -{ - .y = 0, - .affineMode = ST_OAM_AFFINE_OFF, - .objMode = ST_OAM_OBJ_NORMAL, - .mosaic = 0, - .bpp = ST_OAM_4BPP, - .shape = SPRITE_SHAPE(16x16), - .x = 0, - .matrixNum = 0, - .size = SPRITE_SIZE(16x16), - .tileNum = 0, - .priority = 1, - .paletteNum = 0, - .affineParam = 0 -}; - -static const union AnimCmd gUnknown_0831C638[] = -{ - ANIMCMD_FRAME(0, 4), - ANIMCMD_FRAME(4, 4), - ANIMCMD_FRAME(8, 4), - ANIMCMD_END -}; - -static const union AnimCmd gUnknown_0831C648[] = -{ - ANIMCMD_FRAME(0, 4, .hFlip = TRUE), - ANIMCMD_FRAME(4, 4, .hFlip = TRUE), - ANIMCMD_FRAME(8, 4, .hFlip = TRUE), - ANIMCMD_END -}; - -static const union AnimCmd gUnknown_0831C658[] = -{ - ANIMCMD_FRAME(0, 4, .vFlip = TRUE), - ANIMCMD_FRAME(4, 4, .vFlip = TRUE), - ANIMCMD_FRAME(8, 4, .vFlip = TRUE), - ANIMCMD_END -}; - -static const union AnimCmd gUnknown_0831C668[] = -{ - ANIMCMD_FRAME(0, 4, .hFlip = TRUE, .vFlip = TRUE), - ANIMCMD_FRAME(4, 4, .hFlip = TRUE, .vFlip = TRUE), - ANIMCMD_FRAME(8, 4, .hFlip = TRUE, .vFlip = TRUE), - ANIMCMD_END -}; - -static const union AnimCmd *const gUnknown_0831C678[] = -{ - gUnknown_0831C638, - gUnknown_0831C648, - gUnknown_0831C658, - gUnknown_0831C668, -}; - -static const struct SpriteTemplate gSmokescreenImpactSpriteTemplate = -{ - .tileTag = 55019, - .paletteTag = 55019, - .oam = &gUnknown_0831C630, - .anims = gUnknown_0831C678, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCB_DestroySprite -}; - -const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow = -{ - .data = gEnemyMonShadow_Gfx, .size = 0x80, .tag = 55129 -}; - -static const struct OamData gUnknown_0831C6A8 = -{ - .y = 0, - .affineMode = ST_OAM_AFFINE_OFF, - .objMode = ST_OAM_OBJ_NORMAL, - .mosaic = 0, - .bpp = ST_OAM_4BPP, - .shape = SPRITE_SHAPE(32x8), - .x = 0, - .matrixNum = 0, - .size = SPRITE_SIZE(32x8), - .tileNum = 0, - .priority = 3, - .paletteNum = 0, - .affineParam = 0 -}; - -const struct SpriteTemplate gSpriteTemplate_EnemyShadow = -{ - .tileTag = 55129, - .paletteTag = 55039, - .oam = &gUnknown_0831C6A8, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCB_SetInvisible -}; - -u8 SmokescreenImpact(s16 x, s16 y, u8 a3) -{ - u8 mainSpriteId; - u8 spriteId1, spriteId2, spriteId3, spriteId4; - struct Sprite *mainSprite; - - if (GetSpriteTileStartByTag(gSmokescreenImpactSpriteSheet.tag) == 0xFFFF) - { - LoadCompressedSpriteSheetUsingHeap(&gSmokescreenImpactSpriteSheet); - LoadCompressedSpritePaletteUsingHeap(&gSmokescreenlImpactSpritePalette); - } - - mainSpriteId = CreateInvisibleSpriteWithCallback(SmokescreenImpact_Callback); - mainSprite = &gSprites[mainSpriteId]; - mainSprite->data[1] = a3; - - spriteId1 = CreateSprite(&gSmokescreenImpactSpriteTemplate, x - 16, y - 16, 2); - gSprites[spriteId1].data[0] = mainSpriteId; - mainSprite->data[0]++; - AnimateSprite(&gSprites[spriteId1]); - - spriteId2 = CreateSprite(&gSmokescreenImpactSpriteTemplate, x, y - 16, 2); - gSprites[spriteId2].data[0] = mainSpriteId; - mainSprite->data[0]++; - StartSpriteAnim(&gSprites[spriteId2], 1); - AnimateSprite(&gSprites[spriteId2]); - - spriteId3 = CreateSprite(&gSmokescreenImpactSpriteTemplate, x - 16, y, 2); - gSprites[spriteId3].data[0] = mainSpriteId; - mainSprite->data[0]++; - StartSpriteAnim(&gSprites[spriteId3], 2); - AnimateSprite(&gSprites[spriteId3]); - - spriteId4 = CreateSprite(&gSmokescreenImpactSpriteTemplate, x, y, 2); - gSprites[spriteId4].data[0] = mainSpriteId; - mainSprite->data[0]++; - StartSpriteAnim(&gSprites[spriteId4], 3); - AnimateSprite(&gSprites[spriteId4]); - - return mainSpriteId; -} - -static void SmokescreenImpact_Callback(struct Sprite *sprite) -{ - if (!sprite->data[0]) - { - FreeSpriteTilesByTag(gSmokescreenImpactSpriteSheet.tag); - FreeSpritePaletteByTag(gSmokescreenlImpactSpritePalette.tag); - if (!sprite->data[1]) - DestroySprite(sprite); - else - sprite->callback = SpriteCallbackDummy; - } -} - -static void SpriteCB_DestroySprite(struct Sprite *sprite) -{ - if (sprite->animEnded) - { - gSprites[sprite->data[0]].data[0]--; - DestroySprite(sprite); - } -} diff --git a/src/water.c b/src/water.c deleted file mode 100644 index 5d3e9505b..000000000 --- a/src/water.c +++ /dev/null @@ -1,2219 +0,0 @@ -#include "global.h" -#include "battle.h" -#include "battle_anim.h" -#include "gpu_regs.h" -#include "graphics.h" -#include "palette.h" -#include "random.h" -#include "scanline_effect.h" -#include "sprite.h" -#include "task.h" -#include "trig.h" -#include "util.h" -#include "constants/battle.h" -#include "constants/rgb.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 -const u8 gUnknown_8593C80[] = INCBIN_U8("graphics/unknown/unknown_593C80.4bpp"); -const u8 gUnknown_8593FFC[] = INCBIN_U8("graphics/unknown/unknown_593FFC.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 = Random2() % 240; - y = Random2() % 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] <= 13) - { - sprite->pos2.x++; - 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[ARG_RET_ID] == 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[ARG_RET_ID]; - if (gBattleAnimArgs[ARG_RET_ID] > 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[ARG_RET_ID] = 0; - gTasks[taskId].func = AnimTask_RunSinAnimTimer; -} - -static void AnimTask_RunSinAnimTimer(u8 taskId) -{ - gBattleAnimArgs[ARG_RET_ID] = (gBattleAnimArgs[ARG_RET_ID] + 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_80A6B30(&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 - { - AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_SurfContest, 1); - } - AnimLoadCompressedBgGfx(animBg.bgId, gBattleAnimBgImage_Surf, animBg.tilesOffset); - if (gBattleAnimArgs[0] == 0) - LoadCompressedPalette(gBattleAnimBgPalette_Surf, animBg.paletteId * 16, 32); - else - LoadCompressedPalette(gBattleAnimBackgroundImageMuddyWater_Pal, 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_80A6B30\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 r1, =gBattleAnimBgTilemap_SurfContest\n\ - mov r0, sp\n\ - movs r2, 0x1\n\ - bl AnimLoadCompressedBgTilemapHandleContest\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, =gBattleAnimBackgroundImageMuddyWater_Pal\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_80A6B30(&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_80A6B30\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_80A6C68(1); - sub_80A6C68(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 = (Random2() & 0xFF) | 256; - randData2 = (Random2() & 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_80A805C(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_80A80C8(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_80A805C(task, task->data[15], 224, 0x200, 384, 224, 8); - task->data[3] = 0; - task->data[0]++; - } - break; - case 3: - if (sub_80A80C8(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_80A805C(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_80A80C8(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] = (Random2() & 0x1F) - 16 + sprite->pos1.x; - sprite->data[4] = (Random2() & 0x1F) - 16 + sprite->pos1.y; - sprite->data[5] = ~(Random2() & 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 + (Random2() % 10) - 5; - s16 randomSomethingX = -xDiff + (Random2() % 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 Random2\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 Random2\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 diff --git a/sym_ewram.txt b/sym_ewram.txt index eca090dbd..5e6eef5ef 100644 --- a/sym_ewram.txt +++ b/sym_ewram.txt @@ -79,7 +79,7 @@ .include "src/safari_zone.o" .include "src/item_use.o" .include "src/battle_anim_effects_1.o" - .include "src/dragon.o" + .include "src/battle_anim_dragon.o" .include "src/battle_anim_utility_funcs.o" .include "src/battle_intro.o" .include "src/easy_chat.o" -- cgit v1.2.3