From b5fbced6918f2b2bd10367556465690fabcb82d9 Mon Sep 17 00:00:00 2001 From: Jonathan Lin <35115312+LinathanZel@users.noreply.github.com> Date: Thu, 15 May 2025 03:40:02 -0400 Subject: [PATCH] New animations for Mega Evolution, Primal Reversion, Ultra Burst, and Power Construct (#6834) --- data/battle_anim_scripts.s | 147 ++++++++++++++++++++++---- data/battle_scripts_1.s | 15 +++ include/battle_anim.h | 2 + include/battle_anim_scripts.h | 1 + include/battle_scripts.h | 1 + include/constants/battle_anim.h | 3 +- include/constants/battle_string_ids.h | 2 + src/battle_anim.c | 2 + src/battle_anim_effects_3.c | 62 +++++++++-- src/battle_anim_new.c | 69 ++++++++++++ src/battle_message.c | 2 + src/battle_util.c | 9 +- test/battle/gimmick/dynamax.c | 2 +- 13 files changed, 284 insertions(+), 33 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index adab9de89f..8ced318ac7 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -28672,6 +28672,8 @@ gBattleAnimGeneral_MegaEvolution:: loadspritegfx ANIM_TAG_MEGA_STONE loadspritegfx ANIM_TAG_MEGA_PARTICLES loadspritegfx ANIM_TAG_MEGA_SYMBOL + loadspritegfx ANIM_TAG_ELECTRICITY + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_ELECTRICITY, 0, 12, 12, RGB(228, 0, 120) monbg ANIM_ATTACKER setalpha 12, 8 loopsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER, 13, 3 @@ -28685,12 +28687,13 @@ gBattleAnimGeneral_MegaEvolution:: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish + createvisualtask SoundTask_PlayNormalCry, 0 createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 - waitforvisualfinish - createvisualtask SoundTask_PlayNormalCry, 0 - createsprite gMegaSymbolSpriteTemplate ANIM_ATTACKER, 2 + createsprite gMegaSymbolSpriteTemplate ANIM_ATTACKER, 3, 0, 0, ANIM_ATTACKER + delay 2 + call MegaEvolutionSpinEffect waitforvisualfinish clearmonbg ANIM_ATK_PARTNER blendoff @@ -28713,6 +28716,21 @@ MegaEvolutionParticles: delay 3 return +MegaEvolutionSpinEffect: + createsprite gMegaSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 12, 528, 30, 13, 50, 0 + delay 2 + createsprite gMegaSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 0, 480, 20, 16, -46, 0 + delay 2 + createsprite gMegaSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 1, 576, 20, 8, 42, 0 + delay 2 + createsprite gMegaSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 15, 400, 25, 11, -42, 0 + delay 2 + createsprite gMegaSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 12, 512, 25, 16, 46, 0 + delay 2 + createsprite gMegaSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 1, 464, 30, 15, -50, 0 + delay 2 + return + gBattleAnimGeneral_TeraCharge:: loadspritegfx ANIM_TAG_TERA_CRYSTAL loadspritegfx ANIM_TAG_TERA_SHATTER @@ -28859,18 +28877,14 @@ gBattleAnimGeneral_PrimalReversion:: createvisualtask AnimTask_PrimalReversion, 0x5 jumpargeq 0x0, ITEM_RED_ORB, General_PrimalReversion_Omega jumpargeq 0x0, ITEM_BLUE_ORB, General_PrimalReversion_Alpha + goto gBattleAnimGeneral_MegaEvolution General_PrimalReversion_Alpha: loadspritegfx ANIM_TAG_ALPHA_STONE loadspritegfx ANIM_TAG_MEGA_PARTICLES loadspritegfx ANIM_TAG_ALPHA_SYMBOL + loadspritegfx ANIM_TAG_HYDRO_PUMP monbg ANIM_ATTACKER setalpha 12, 8 - loopsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER, 13, 3 - createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_ATTACKER, 0, 6, 0, 11, RGB(31, 31, 11) - call MegaEvolutionParticles - call MegaEvolutionParticles - call MegaEvolutionParticles - waitforvisualfinish playsewithpan SE_M_SOLAR_BEAM, SOUND_PAN_ATTACKER createsprite gAlphaStoneSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0 delay 20 @@ -28879,25 +28893,31 @@ General_PrimalReversion_Alpha: createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 - waitforvisualfinish createvisualtask SoundTask_PlayNormalCry, 0 - createsprite gAlphaSymbolSpriteTemplate ANIM_ATTACKER, 2 + createsprite gAlphaSymbolSpriteTemplate ANIM_ATTACKER, 3, 0, 0, ANIM_ATTACKER + call WaterGeyser + call WaterGeyser waitforvisualfinish clearmonbg ANIM_ATK_PARTNER blendoff end +WaterGeyser: + createsprite gAlphaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, -4, 24 + delay 1 + createsprite gAlphaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, 16, 24 + delay 1 + createsprite gAlphaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, 4, 24 + delay 1 + createsprite gAlphaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, -16, 24 + delay 1 + return General_PrimalReversion_Omega: loadspritegfx ANIM_TAG_OMEGA_STONE loadspritegfx ANIM_TAG_MEGA_PARTICLES loadspritegfx ANIM_TAG_OMEGA_SYMBOL + loadspritegfx ANIM_TAG_SMALL_EMBER monbg ANIM_ATTACKER setalpha 12, 8 - loopsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER, 13, 3 - createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_ATTACKER, 0, 6, 0, 11, RGB(31, 31, 11) - call MegaEvolutionParticles - call MegaEvolutionParticles - call MegaEvolutionParticles - waitforvisualfinish playsewithpan SE_M_SOLAR_BEAM, SOUND_PAN_ATTACKER createsprite gOmegaStoneSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0 delay 20 @@ -28906,13 +28926,82 @@ General_PrimalReversion_Omega: createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 - waitforvisualfinish createvisualtask SoundTask_PlayNormalCry, 0 - createsprite gOmegaSymbolSpriteTemplate ANIM_ATTACKER, 2 + createsprite gOmegaSymbolSpriteTemplate ANIM_ATTACKER, 3, 0, 0, ANIM_ATTACKER + call FireGeyser + call FireGeyser waitforvisualfinish clearmonbg ANIM_ATK_PARTNER blendoff end +FireGeyser: + createsprite gOmegaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, -4, 24 + delay 1 + createsprite gOmegaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, 16, 24 + delay 1 + createsprite gOmegaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, 4, 24 + delay 1 + createsprite gOmegaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, -16, 24 + delay 1 + return + +gBattleAnimGeneral_PowerConstruct:: + loadspritegfx ANIM_TAG_SNORE_Z + loadspritegfx ANIM_TAG_ZYGARDE_HEXES @hexagon + loadspritegfx ANIM_TAG_VERTICAL_HEX @arrow + loadspritegfx ANIM_TAG_FLYING_DIRT + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_SNORE_Z, 0, 10, 10, RGB(8, 20, 26) @Green + monbg ANIM_ATTACKER + setalpha 12, 8 + loopsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER, 13, 3 + call PowerConstructParticles + call PowerConstructParticles + call PowerConstructParticles + waitforvisualfinish + playsewithpan SE_ORB, SOUND_PAN_ATTACKER + createsprite gPowerConstructEmergeSpriteTemplate, ANIM_ATTACKER, 0, 0, 0, 0, 0 + delay 20 + createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA + waitforvisualfinish + createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 + createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA + createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 + createvisualtask SoundTask_PlayNormalCry, 0 + createsprite gZSymbolSpriteTemplate ANIM_ATTACKER, 3, 0, 0, ANIM_ATTACKER + call ZGeyser + call ZGeyser + call ZGeyser + call ZGeyser + waitforvisualfinish + clearmonbg ANIM_ATK_PARTNER + blendoff + end +PowerConstructParticles: + createsprite gPowerConstructSpriteTemplate, ANIM_ATTACKER, 2, 40, -10, 13 + delay 3 + createsprite gPowerConstructSpriteTemplate, ANIM_ATTACKER, 2, -35, -10, 13 + delay 3 + createsprite gPowerConstructSpriteTemplate, ANIM_ATTACKER, 2, 15, -40, 13 + delay 3 + createsprite gPowerConstructSpriteTemplate, ANIM_ATTACKER, 2, -10, -32, 13 + delay 3 + createsprite gPowerConstructSpriteTemplate, ANIM_ATTACKER, 2, 25, -20, 13 + delay 3 + createsprite gPowerConstructSpriteTemplate, ANIM_ATTACKER, 2, -40, -20, 13 + delay 3 + createsprite gPowerConstructSpriteTemplate, ANIM_ATTACKER, 2, 5, -40, 13 + delay 3 + return +ZGeyser: + createsprite gThousandArrowsGreenHexTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, -4, 24 + delay 1 + createsprite gThousandArrowsGreenHexTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, 16, 24 + delay 1 + createsprite gThousandArrowsGreenHexTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, 4, 24 + delay 1 + createsprite gThousandArrowsGreenHexTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, -16, 24 + delay 1 + return gBattleAnimGeneral_UltraBurst:: loadspritegfx ANIM_TAG_ULTRA_BURST_SYMBOL @@ -28920,8 +29009,10 @@ gBattleAnimGeneral_UltraBurst:: loadspritegfx ANIM_TAG_LEAF @green loadspritegfx ANIM_TAG_ELECTRIC_ORBS @charge particles loadspritegfx ANIM_TAG_CIRCLE_OF_LIGHT @psycho boost + loadspritegfx ANIM_TAG_HYDRO_PUMP monbg ANIM_ATTACKER setalpha 12, 8 + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_HYDRO_PUMP, 0, 12, 12, RGB(250, 240, 230) createvisualtask AnimTask_BlendBattleAnimPal, 0xa, (F_PAL_BG | F_PAL_ADJACENT), 0x2, 0x0, 0xF, 0x0000 waitforvisualfinish createvisualtask AnimTask_ElectricChargingParticles, 2, ANIM_ATTACKER, 60, 2, 12 @ charge particles to attacker @@ -28938,18 +29029,32 @@ gBattleAnimGeneral_UltraBurst:: call LightThatBurnsTheSkyGreenSparks call LightThatBurnsTheSkyGreenSparks delay 20 + playsewithpan SE_ORB, SOUND_PAN_ATTACKER createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA - createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 createsprite gUltraBurstSymbolSpriteTemplate, ANIM_ATTACKER, 0x0, 0x0, 0x0, 0x0, 0x0 waitforvisualfinish + createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 - waitforvisualfinish createvisualtask SoundTask_PlayNormalCry, 0 + call LightGeyser + call LightGeyser + call LightGeyser + call LightGeyser waitforvisualfinish clearmonbg ANIM_ATK_PARTNER blendoff end +LightGeyser: + createsprite gAlphaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, -4, 24 + delay 1 + createsprite gAlphaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, 16, 24 + delay 1 + createsprite gAlphaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, 4, 24 + delay 1 + createsprite gAlphaGeyserSpriteTemplate ANIM_ATTACKER, 3, ANIM_ATTACKER, -16, 24 + delay 1 + return gBattleAnimGeneral_AffectionHangedOn:: loadspritegfx ANIM_TAG_RED_HEART diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 1cf302afc4..7a8bc5dd73 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6727,6 +6727,21 @@ BattleScript_PrimalReversion:: switchinabilities BS_SCRIPTING end3 +BattleScript_PowerConstruct:: + flushtextbox + printstring STRINGID_POWERCONSTRUCTPRESENCEOFMANY + waitmessage B_WAIT_TIME_SHORT + copybyte gBattlerAbility, gBattlerAttacker + call BattleScript_AbilityPopUp + handleformchange BS_ATTACKER, 0 + handleformchange BS_ATTACKER, 1 + playanimation BS_ATTACKER, B_ANIM_POWER_CONSTRUCT + waitanimation + handleformchange BS_ATTACKER, 2 + printstring STRINGID_POWERCONSTRUCTTRANSFORM + waitmessage B_WAIT_TIME_SHORT + end3 + BattleScript_UltraBurst:: flushtextbox trytrainerslidezmovemsg diff --git a/include/battle_anim.h b/include/battle_anim.h index 0075010f77..c28546f1e8 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -555,6 +555,8 @@ void AnimDracoMeteorRock(struct Sprite *sprite); void CoreEnforcerLoadBeamTarget(struct Sprite *sprite); void SpriteCB_RandomCentredHits(struct Sprite *sprite); void InitSpritePosToAnimTargetsCentre(struct Sprite *sprite, bool32 respectMonPicOffsets); +extern const union AffineAnimCmd *const gSpriteAffineAnimTable_PrimalSymbol[]; +extern const union AffineAnimCmd *const gSpriteAffineAnimTable_MegaSymbol[]; // battle_anim_bug.c void AnimTranslateStinger(struct Sprite *sprite); diff --git a/include/battle_anim_scripts.h b/include/battle_anim_scripts.h index 6c49788975..0bffbda8ea 100644 --- a/include/battle_anim_scripts.h +++ b/include/battle_anim_scripts.h @@ -1003,6 +1003,7 @@ extern const u8 gBattleAnimGeneral_Fog[]; extern const u8 gBattleAnimGeneral_TeraCharge[]; extern const u8 gBattleAnimGeneral_TeraActivate[]; extern const u8 gBattleAnimGeneral_SimpleHeal[]; +extern const u8 gBattleAnimGeneral_PowerConstruct[]; // special animations extern const u8 gBattleAnimSpecial_LevelUp[]; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 09c98d3c57..406be9a2be 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -519,6 +519,7 @@ extern const u8 BattleScript_BoosterEnergyRet[]; extern const u8 BattleScript_TeraShellDistortingTypeMatchups[]; extern const u8 BattleScript_TeraFormChange[]; extern const u8 BattleScript_SleepClausePreventsEnd[]; +extern const u8 BattleScript_PowerConstruct[]; extern const u8 BattleScript_AbilityProtectsDoesntAffect[]; extern const u8 BattleScript_ImmunityProtected[]; diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index ac312a3c01..c85dcc9fe7 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -586,8 +586,9 @@ #define B_ANIM_TERA_CHARGE 50 #define B_ANIM_TERA_ACTIVATE 51 #define B_ANIM_SIMPLE_HEAL 52 +#define B_ANIM_POWER_CONSTRUCT 53 -#define NUM_B_ANIMS_GENERAL 53 +#define NUM_B_ANIMS_GENERAL 54 // special animations table (sBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 456211c802..8e8503458d 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -736,6 +736,8 @@ enum StringID STRINGID_QUESTIONFORFEITBATTLE, STRINGID_FORFEITBATTLEGAVEMONEY, STRINGID_TOXICSPIKESBADLYPOISONED, + STRINGID_POWERCONSTRUCTPRESENCEOFMANY, + STRINGID_POWERCONSTRUCTTRANSFORM, STRINGID_COUNT }; diff --git a/src/battle_anim.c b/src/battle_anim.c index b8118313dd..bf75d4a142 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -252,6 +252,7 @@ static const u8* const sBattleAnims_General[NUM_B_ANIMS_GENERAL] = [B_ANIM_TERA_CHARGE] = gBattleAnimGeneral_TeraCharge, [B_ANIM_TERA_ACTIVATE] = gBattleAnimGeneral_TeraActivate, [B_ANIM_SIMPLE_HEAL] = gBattleAnimGeneral_SimpleHeal, + [B_ANIM_POWER_CONSTRUCT] = gBattleAnimGeneral_PowerConstruct, }; static const u8* const sBattleAnims_Special[NUM_B_ANIMS_SPECIAL] = @@ -351,6 +352,7 @@ void LaunchBattleAnimation(u32 animType, u32 animId) case B_ANIM_WISH_HEAL: case B_ANIM_MEGA_EVOLUTION: case B_ANIM_PRIMAL_REVERSION: + case B_ANIM_POWER_CONSTRUCT: case B_ANIM_ULTRA_BURST: case B_ANIM_GULP_MISSILE: case B_ANIM_RAINBOW: diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index affa5e7ce3..409244ccac 100644 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -1204,15 +1204,26 @@ const struct SpriteTemplate gMegaParticlesSpriteTemplate = .callback = AnimPowerAbsorptionOrb, }; +const struct SpriteTemplate gMegaSmokeSpriteTemplate = +{ + .tileTag = ANIM_TAG_ELECTRICITY, + .paletteTag = ANIM_TAG_ELECTRICITY, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_ElectricPuff, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimParticleInVortex, +}; + const struct SpriteTemplate gMegaSymbolSpriteTemplate = { .tileTag = ANIM_TAG_MEGA_SYMBOL, .paletteTag = ANIM_TAG_MEGA_SYMBOL, - .oam = &gOamData_AffineOff_ObjBlend_32x32, + .oam = &gOamData_AffineDouble_ObjBlend_32x32, .anims = gDummySpriteAnimTable, .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimGhostStatusSprite, + .affineAnims = gSpriteAffineAnimTable_MegaSymbol, + .callback = AnimSpriteOnMonPos, }; const struct SpriteTemplate gAlphaStoneSpriteTemplate = @@ -1241,22 +1252,55 @@ const struct SpriteTemplate gAlphaSymbolSpriteTemplate = { .tileTag = ANIM_TAG_ALPHA_SYMBOL, .paletteTag = ANIM_TAG_ALPHA_SYMBOL, - .oam = &gOamData_AffineOff_ObjBlend_32x32, + .oam = &gOamData_AffineDouble_ObjBlend_32x32, .anims = gDummySpriteAnimTable, .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimGhostStatusSprite, + .affineAnims = gSpriteAffineAnimTable_PrimalSymbol, + .callback = AnimSpriteOnMonPos, }; const struct SpriteTemplate gOmegaSymbolSpriteTemplate = { .tileTag = ANIM_TAG_OMEGA_SYMBOL, .paletteTag = ANIM_TAG_OMEGA_SYMBOL, - .oam = &gOamData_AffineOff_ObjBlend_32x32, + .oam = &gOamData_AffineDouble_ObjBlend_32x32, .anims = gDummySpriteAnimTable, .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimGhostStatusSprite, + .affineAnims = gSpriteAffineAnimTable_PrimalSymbol, + .callback = AnimSpriteOnMonPos, +}; + +const struct SpriteTemplate gPowerConstructSpriteTemplate = +{ + .tileTag = ANIM_TAG_VERTICAL_HEX, + .paletteTag = ANIM_TAG_ZYGARDE_HEXES, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gPowerAbsorptionOrbAnimTable, + .images = NULL, + .affineAnims = gPowerAbsorptionOrbAffineAnimTable, + .callback = AnimPowerAbsorptionOrb, +}; + +const struct SpriteTemplate gPowerConstructEmergeSpriteTemplate = +{ + .tileTag = ANIM_TAG_VERTICAL_HEX, + .paletteTag = ANIM_TAG_ZYGARDE_HEXES, + .oam = &gOamData_AffineDouble_ObjBlend_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_LusterPurgeCircle, + .callback = AnimSpriteOnMonPos, +}; + +const struct SpriteTemplate gZSymbolSpriteTemplate = +{ + .tileTag = ANIM_TAG_SNORE_Z, + .paletteTag = ANIM_TAG_SNORE_Z, + .oam = &gOamData_AffineDouble_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gSpriteAffineAnimTable_MegaSymbol, + .callback = AnimSpriteOnMonPos, }; const struct SpriteTemplate gTeraCrystalSpriteTemplate = diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 1ecf064be8..35a8bac32e 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -7279,6 +7279,28 @@ const struct SpriteTemplate gMoonUpSpriteTemplate = .callback = AnimWeatherBallUp, }; +const struct SpriteTemplate gAlphaGeyserSpriteTemplate = +{ + .tileTag = ANIM_TAG_HYDRO_PUMP, + .paletteTag = ANIM_TAG_HYDRO_PUMP, + .oam = &gOamData_AffineOff_ObjBlend_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gSpriteAffineAnimTable_PrimalSymbol, + .callback = SpriteCB_Geyser, +}; + +const struct SpriteTemplate gOmegaGeyserSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gSpriteAffineAnimTable_PrimalSymbol, + .callback = SpriteCB_Geyser, +}; + const union AnimCmd gSproutAnimCmds[] = { ANIMCMD_FRAME(96, 5), @@ -9301,3 +9323,50 @@ void AnimTask_RandomBool(u8 taskId) DestroyAnimVisualTask(taskId); } + +// Credit to Skeli +#define PRIMAL_PULSE_SCALE_SIZE 16 +#define PRIMAL_PULSE_FRAME_COUNT 4 +static const union AffineAnimCmd sSpriteAffineAnim_PrimalSymbol[] = +{ + AFFINEANIMCMD_FRAME(16, 16, 0, 0), + AFFINEANIMCMD_FRAME(32, 32, 0, 15), + AFFINEANIMCMD_FRAME(0, 0, 0, 2), + AFFINEANIMCMD_FRAME(-PRIMAL_PULSE_SCALE_SIZE, -PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME( PRIMAL_PULSE_SCALE_SIZE, PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME(-PRIMAL_PULSE_SCALE_SIZE, -PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME( PRIMAL_PULSE_SCALE_SIZE, PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME(-PRIMAL_PULSE_SCALE_SIZE, -PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME( PRIMAL_PULSE_SCALE_SIZE, PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME(-PRIMAL_PULSE_SCALE_SIZE, -PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME( PRIMAL_PULSE_SCALE_SIZE, PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME(-32, -32, 0, 15), //Shrink down again + AFFINEANIMCMD_END, +}; + +const union AffineAnimCmd *const gSpriteAffineAnimTable_PrimalSymbol[] = +{ + sSpriteAffineAnim_PrimalSymbol, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_MegaSymbol[] = +{ + AFFINEANIMCMD_FRAME(16, 16, 0, 0), //Start small + AFFINEANIMCMD_FRAME(32, 32, 0, 15), //Grow sprite + AFFINEANIMCMD_FRAME(0, 0, 0, 2), //Pause + + //Pulsate + AFFINEANIMCMD_FRAME(-PRIMAL_PULSE_SCALE_SIZE, -PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME( PRIMAL_PULSE_SCALE_SIZE, PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME(-PRIMAL_PULSE_SCALE_SIZE, -PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME( PRIMAL_PULSE_SCALE_SIZE, PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME(-PRIMAL_PULSE_SCALE_SIZE, -PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME( PRIMAL_PULSE_SCALE_SIZE, PRIMAL_PULSE_SCALE_SIZE, 0, PRIMAL_PULSE_FRAME_COUNT), + AFFINEANIMCMD_FRAME(-32, -32, 0, 15), //Shrink down again + AFFINEANIMCMD_END, +}; + +const union AffineAnimCmd* const gSpriteAffineAnimTable_MegaSymbol[] = +{ + sSpriteAffineAnim_MegaSymbol, +}; diff --git a/src/battle_message.c b/src/battle_message.c index ca69ed93bb..0f239cb4e6 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -899,6 +899,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_TIMETOGIGANTAMAX] = COMPOUND_STRING("Time to Gigantamax!"), [STRINGID_QUESTIONFORFEITBATTLE] = COMPOUND_STRING("Would you like to give up on this battle and quit now? Quitting the battle is the same as losing the battle."), [STRINGID_FORFEITBATTLEGAVEMONEY] = COMPOUND_STRING("You gave ¥{B_BUFF1} to the winner…{PAUSE_UNTIL_PRESS}"), + [STRINGID_POWERCONSTRUCTPRESENCEOFMANY] = COMPOUND_STRING("You sense the presence of many!"), + [STRINGID_POWERCONSTRUCTTRANSFORM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} transformed into its Complete Forme!"), }; const u16 gTrainerUsedItemStringIds[] = diff --git a/src/battle_util.c b/src/battle_util.c index b8f793db81..bdffa67624 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4285,7 +4285,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 // Fallthrough case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: - case ABILITY_POWER_CONSTRUCT: if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { gBattlerAttacker = battler; @@ -4293,6 +4292,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + case ABILITY_POWER_CONSTRUCT: + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) + { + gBattlerAttacker = battler; + BattleScriptPushCursorAndCallback(BattleScript_PowerConstruct); + effect++; + } + break; case ABILITY_BALL_FETCH: if (gBattleMons[battler].item == ITEM_NONE && gBattleResults.catchAttempts[gLastUsedBall - ITEM_ULTRA_BALL] >= 1 diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index ee12bac875..a929c82068 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -455,7 +455,7 @@ SINGLE_BATTLE_TEST("Dynamax: Dynamaxed Pokemon that changes forms does not gain } SCENE { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_MAX_STRIKE, player); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_POWER_CONSTRUCT, player); } THEN { EXPECT_MUL_EQ(maxHP - hp, GetDynamaxLevelHPMultiplier(0, FALSE), player->maxHP - player->hp); }