diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 34f29950bd31..5e08c7cdb5ca 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1641,6 +1641,10 @@ .macro removeweather callnative BS_RemoveWeather .endm + + .macro applyterastallization + callnative BS_ApplyTerastallization + .endm @ various command changed to more readable macros .macro cancelmultiturnmoves battler:req diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index d5d81cf70927..23697e38ad2b 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -1033,6 +1033,8 @@ gBattleAnims_General:: .4byte General_MagicRoom @ B_ANIM_MAGIC_ROOM .4byte General_Tailwind @ B_ANIM_TAILLWIND .4byte General_Fog @ B_ANIM_FOG_CONTINUES + .4byte General_TeraCharge @ B_ANIM_TERA_CHARGE + .4byte General_TeraActivate @ B_ANIM_TERA_ACTIVATE .align 2 gBattleAnims_Special:: @@ -28316,6 +28318,52 @@ MegaEvolutionParticles: delay 3 return +General_TeraCharge: + loadspritegfx ANIM_TAG_TERA_CRYSTAL + loadspritegfx ANIM_TAG_TERA_SHATTER + loadspritegfx ANIM_TAG_FOCUS_ENERGY + loadspritegfx ANIM_TAG_WHIP_HIT @green color + loadspritegfx ANIM_TAG_SWEAT_BEAD @blue color + loadspritegfx ANIM_TAG_PAW_PRINT @yellow color + monbg ANIM_ATTACKER + setalpha 12, 8 + playsewithpan SE_M_DRAGON_RAGE, SOUND_PAN_ATTACKER + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_ATTACKER, 0, 6, 0, 11, RGB_RED + call RainbowEndureEffect + call RainbowEndureEffect + call RainbowEndureEffect + call RainbowEndureEffect + call RainbowEndureEffect + waitforvisualfinish + playsewithpan SE_M_SOLAR_BEAM, SOUND_PAN_ATTACKER + createsprite gTeraCrystalSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0 + delay 20 + createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA + waitforvisualfinish + call TeraChargeParticles + playsewithpan SE_M_BRICK_BREAK, SOUND_PAN_ATTACKER + clearmonbg ANIM_ATK_PARTNER + blendoff + end + +TeraChargeParticles: + createsprite gTeraCrystalSpreadSpriteTemplate, ANIM_TARGET, 0, 0, -5, 8 + createsprite gTeraCrystalSpreadSpriteTemplate, ANIM_TARGET, 0, 1, 5, 9 + createsprite gTeraCrystalSpreadSpriteTemplate, ANIM_TARGET, 0, 2, 5, -8 + createsprite gTeraCrystalSpreadSpriteTemplate, ANIM_TARGET, 0, 2, -5, -8 + createsprite gTeraCrystalSpreadSpriteTemplate, ANIM_TARGET, 0, 1, -10, 0 + createsprite gTeraCrystalSpreadSpriteTemplate, ANIM_TARGET, 0, 0, 10, 0 + return + +General_TeraActivate: + createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA + createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 + waitforvisualfinish + createvisualtask SoundTask_PlayNormalCry, 0 + clearmonbg ANIM_ATK_PARTNER + blendoff + end + General_RestoreBg: restorebg waitbgfadein diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 24ce3405ebdb..b059800239f4 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -22,10 +22,14 @@ BattleScript_Terastallization:: @ TODO: no string prints in S/V, but right now this helps with clarity - printstring STRINGID_PKMNTERASTALLIZEDINTO - @ TODO: replace this animation - playanimation BS_ATTACKER, B_ANIM_TOTEM_FLARE + printstring STRINGID_PKMNSTORINGENERGY + playanimation BS_ATTACKER, B_ANIM_TERA_CHARGE + waitanimation + applyterastallization + playanimation BS_ATTACKER, B_ANIM_TERA_ACTIVATE waitanimation + printstring STRINGID_PKMNTERASTALLIZEDINTO + waitmessage B_WAIT_TIME_LONG end3 BattleScript_LowerAtkSpAtk:: diff --git a/graphics/battle_anims/sprites/tera_crystal.png b/graphics/battle_anims/sprites/tera_crystal.png new file mode 100644 index 000000000000..e1c406a744a3 Binary files /dev/null and b/graphics/battle_anims/sprites/tera_crystal.png differ diff --git a/graphics/battle_anims/sprites/tera_shatter.png b/graphics/battle_anims/sprites/tera_shatter.png new file mode 100644 index 000000000000..c3f698b9d475 Binary files /dev/null and b/graphics/battle_anims/sprites/tera_shatter.png differ diff --git a/include/battle_terastal.h b/include/battle_terastal.h index 078bf39079fa..c5428b6418be 100644 --- a/include/battle_terastal.h +++ b/include/battle_terastal.h @@ -2,6 +2,7 @@ #define GUARD_BATTLE_TERASTAL_H void PrepareBattlerForTera(u32 battler); +void ApplyBattlerVisualsForTeraAnim(u32 battler); bool32 CanTerastallize(u32 battler); u32 GetBattlerTeraType(u32 battler); bool32 IsTerastallized(u32 battler); diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 162eb11c991f..bde245850818 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -405,6 +405,8 @@ #define ANIM_TAG_SYRUP_SHELL_YELLOW (ANIM_SPRITES_START + 391) #define ANIM_TAG_SYRUP_SPLAT_RED (ANIM_SPRITES_START + 392) #define ANIM_TAG_SYRUP_SPLAT_YELLOW (ANIM_SPRITES_START + 393) +#define ANIM_TAG_TERA_CRYSTAL (ANIM_SPRITES_START + 394) +#define ANIM_TAG_TERA_SHATTER (ANIM_SPRITES_START + 395) // battlers #define ANIM_ATTACKER 0 @@ -568,6 +570,8 @@ #define B_ANIM_MAGIC_ROOM 47 #define B_ANIM_TAILWIND 48 #define B_ANIM_FOG_CONTINUES 49 +#define B_ANIM_TERA_CHARGE 50 +#define B_ANIM_TERA_ACTIVATE 51 // special animations table (gBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/include/graphics.h b/include/graphics.h index e7e884e19403..e8054d08f642 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -2698,6 +2698,10 @@ extern const u32 gBattleAnimSpriteGfx_Punishment[]; extern const u32 gBattleAnimSpritePal_Punishment[]; extern const u32 gBattleAnimSpriteGfx_QuickGuard[]; extern const u32 gBattleAnimSpritePal_QuickGuard[]; +extern const u32 gBattleAnimSpriteGfx_TeraCrystal[]; +extern const u32 gBattleAnimSpritePal_TeraCrystal[]; +extern const u32 gBattleAnimSpriteGfx_TeraShatter[]; +extern const u32 gBattleAnimSpritePal_TeraShatter[]; // New Battle Anim Particles extern const u32 gBattleAnimSpriteGfx_AlphaStone[]; diff --git a/src/battle_anim.c b/src/battle_anim.c index af1a5a262a80..deb56db03678 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -283,6 +283,7 @@ void LaunchBattleAnimation(u32 animType, u32 animId) case B_ANIM_RAINBOW: case B_ANIM_SEA_OF_FIRE: case B_ANIM_SWAMP: + case B_ANIM_TERA_CHARGE: sAnimHideHpBoxes = TRUE; break; default: diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index 5dd91b7f491d..ed2e7457f62e 100644 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -112,6 +112,8 @@ static void AnimTask_OdorSleuthMovementWaitFinish(u8); static void MoveOdorSleuthClone(struct Sprite *); static void AnimTask_TeeterDanceMovement_Step(u8); static void AnimTask_SlackOffSquish_Step(u8); +static void AnimTask_TeraCrystalShatter(struct Sprite *); +static void AnimTask_TeraCrystalShatter_Step(struct Sprite *); const union AnimCmd gScratchAnimCmds[] = { @@ -1257,6 +1259,57 @@ const struct SpriteTemplate gOmegaSymbolSpriteTemplate = .callback = AnimGhostStatusSprite, }; +const struct SpriteTemplate gTeraCrystalSpriteTemplate = +{ + .tileTag = ANIM_TAG_TERA_CRYSTAL, + .paletteTag = ANIM_TAG_TERA_CRYSTAL, + .oam = &gOamData_AffineDouble_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_LusterPurgeCircle, + .callback = AnimSpriteOnMonPos, +}; + +const struct SpriteTemplate gTeraCrystalSpreadSpriteTemplate = +{ + .tileTag = ANIM_TAG_TERA_SHATTER, + .paletteTag = ANIM_TAG_TERA_SHATTER, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimTask_TeraCrystalShatter, +}; + +// Task data for AnimTask_TeraCrystalShatter +#define tCounter data[0] +#define tDX data[6] +#define tDY data[7] + +static void AnimTask_TeraCrystalShatter(struct Sprite *sprite) +{ + sprite->x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X); + sprite->y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y); + sprite->oam.tileNum += gBattleAnimArgs[0] * 4; + + sprite->tCounter = 0; + sprite->tDX = gBattleAnimArgs[1]; + sprite->tDY = gBattleAnimArgs[2]; + + sprite->callback = AnimTask_TeraCrystalShatter_Step; +} + +static void AnimTask_TeraCrystalShatter_Step(struct Sprite *sprite) +{ + sprite->x += sprite->tDX; + sprite->y += sprite->tDY; + + if (++sprite->tCounter > 15) + DestroyAnimSprite(sprite); +} + +#undef tCounter + void AnimBlackSmoke(struct Sprite *sprite) { sprite->x += gBattleAnimArgs[0]; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 405deafaf37b..37a9dc2cf2b7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5136,7 +5136,9 @@ static void PlayAnimation(u32 battler, u8 animId, const u16 *argPtr, const u8 *n || animId == B_ANIM_FORM_CHANGE || animId == B_ANIM_SUBSTITUTE_FADE || animId == B_ANIM_PRIMAL_REVERSION - || animId == B_ANIM_ULTRA_BURST) + || animId == B_ANIM_ULTRA_BURST + || animId == B_ANIM_TERA_CHARGE + || animId == B_ANIM_TERA_ACTIVATE) { BtlController_EmitBattleAnimation(battler, BUFFER_A, animId, &gDisableStructs[battler], *argPtr); MarkBattlerForControllerExec(battler); @@ -16910,3 +16912,11 @@ void BS_RemoveWeather(void) RemoveAllWeather(); gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_ApplyTerastallization(void) +{ + NATIVE_ARGS(); + ApplyBattlerVisualsForTeraAnim(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + diff --git a/src/battle_terastal.c b/src/battle_terastal.c index 8cc03aca5716..16ae6f5e5a0a 100644 --- a/src/battle_terastal.c +++ b/src/battle_terastal.c @@ -18,7 +18,6 @@ void PrepareBattlerForTera(u32 battler) { u32 side = GetBattlerSide(battler); - struct Pokemon *party = GetBattlerParty(battler); u32 index = gBattlerPartyIndexes[battler]; // Update TeraData fields. @@ -34,11 +33,21 @@ void PrepareBattlerForTera(u32 battler) { FlagClear(B_FLAG_TERA_ORB_CHARGED); } +} + +// Applies palette blend and enables UI indicator after animation has played +void ApplyBattlerVisualsForTeraAnim(u32 battler) +{ + struct Pokemon *party = GetBattlerParty(battler); + u32 index = gBattlerPartyIndexes[battler]; // Show indicator and do palette blend. UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &party[index], HEALTHBOX_ALL); BlendPalette(OBJ_PLTT_ID(battler), 16, 8, GetTeraTypeRGB(GetBattlerTeraType(battler))); CpuCopy32(gPlttBufferFaded + OBJ_PLTT_ID(battler), gPlttBufferUnfaded + OBJ_PLTT_ID(battler), PLTT_SIZEOF(16)); + + // We apply the animation behind a white screen, so restore the blended color here to avoid a pop + BlendPalette(OBJ_PLTT_ID(battler), 16, 16, RGB_WHITEALPHA); } // Returns whether a battler can Terastallize. diff --git a/src/data/battle_anim.h b/src/data/battle_anim.h index 77b61584cad8..6b29a7c9efff 100644 --- a/src/data/battle_anim.h +++ b/src/data/battle_anim.h @@ -1454,6 +1454,8 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] = {gBattleAnimSpriteGfx_SyrupShell, 0x2000, ANIM_TAG_SYRUP_SHELL_YELLOW}, {gBattleAnimSpriteGfx_SyrupSplat, 0x400, ANIM_TAG_SYRUP_SPLAT_RED}, {gBattleAnimSpriteGfx_SyrupSplat, 0x400, ANIM_TAG_SYRUP_SPLAT_YELLOW}, + {gBattleAnimSpriteGfx_TeraCrystal, 0x800, ANIM_TAG_TERA_CRYSTAL}, + {gBattleAnimSpriteGfx_TeraShatter, 0x0180, ANIM_TAG_TERA_SHATTER}, }; const struct CompressedSpritePalette gBattleAnimPaletteTable[] = @@ -1909,6 +1911,8 @@ const struct CompressedSpritePalette gBattleAnimPaletteTable[] = {gBattleAnimSpritePal_SyrupYellow, ANIM_TAG_SYRUP_SHELL_YELLOW}, {gBattleAnimSpritePal_SyrupRed, ANIM_TAG_SYRUP_SPLAT_RED}, {gBattleAnimSpritePal_SyrupYellow, ANIM_TAG_SYRUP_SPLAT_YELLOW}, + {gBattleAnimSpritePal_TeraCrystal, ANIM_TAG_TERA_CRYSTAL}, + {gBattleAnimSpritePal_TeraShatter, ANIM_TAG_TERA_SHATTER}, }; const struct BattleAnimBackground gBattleAnimBackgroundTable[] = diff --git a/src/graphics.c b/src/graphics.c index c00bb2c767f4..4f10e0f9656e 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -57,6 +57,12 @@ const u32 gBattleAnimSpritePal_QuickGuard[] = INCBIN_U32("graphics/battle_anims/ const u32 gBattleAnimSpriteGfx_AlphaStone[] = INCBIN_U32("graphics/battle_anims/sprites/alpha_stone.4bpp.lz"); const u32 gBattleAnimSpritePal_AlphaStone[] = INCBIN_U32("graphics/battle_anims/sprites/alpha_stone.gbapal.lz"); +const u32 gBattleAnimSpriteGfx_TeraCrystal[] = INCBIN_U32("graphics/battle_anims/sprites/tera_crystal.4bpp.lz"); +const u32 gBattleAnimSpritePal_TeraCrystal[] = INCBIN_U32("graphics/battle_anims/sprites/tera_crystal.gbapal.lz"); + +const u32 gBattleAnimSpriteGfx_TeraShatter[] = INCBIN_U32("graphics/battle_anims/sprites/tera_shatter.4bpp.lz"); +const u32 gBattleAnimSpritePal_TeraShatter[] = INCBIN_U32("graphics/battle_anims/sprites/tera_shatter.gbapal.lz"); + const u32 gBattleAnimSpriteGfx_Anchor[] = INCBIN_U32("graphics/battle_anims/sprites/anchor.4bpp.lz"); const u32 gBattleAnimSpriteGfx_Apple[] = INCBIN_U32("graphics/battle_anims/sprites/apple.4bpp.lz");