From 0e6894a26f9203fff169580d3e2bd3bed66cd30c Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Mon, 20 Jan 2025 23:23:11 +0100 Subject: [PATCH] expansion sync: battle_anim_normal --- include/palette.h | 2 + src/battle_anim_normal.c | 242 ++++++++++++++++++++++++++++----------- src/palette.c | 39 +++++++ 3 files changed, 219 insertions(+), 64 deletions(-) diff --git a/include/palette.h b/include/palette.h index 57131b1e6..a305704ef 100644 --- a/include/palette.h +++ b/include/palette.h @@ -89,6 +89,8 @@ bool32 BeginNormalPaletteFade(u32 selectedPalettes, s8 delay, u8 startY, u8 targ bool32 BeginTimeOfDayPaletteFade(u32, s8, u8, u8, struct BlendSettings *, struct BlendSettings *, u32, u32); void ResetPaletteFadeControl(void); void InvertPlttBuffer(u32 selectedPalettes); +void TintPlttBuffer(u32 selectedPalettes, s8 r, s8 g, s8 b); +void UnfadePlttBuffer(u32 selectedPalettes); void BeginFastPaletteFade(u32 submode); void BeginHardwarePaletteFade(u32 blendCnt, u32 delay, u32 y, u32 targetY, u32 shouldResetBlendRegisters); void BlendPalettes(u32 selectedPalettes, u8 coeff, u32 color); diff --git a/src/battle_anim_normal.c b/src/battle_anim_normal.c index b203d41a8..d9fc8aa41 100644 --- a/src/battle_anim_normal.c +++ b/src/battle_anim_normal.c @@ -4,32 +4,32 @@ #include "random.h" #include "task.h" #include "trig.h" +#include "constants/rgb.h" -static void AnimConfusionDuck(struct Sprite *sprite); -static void AnimSimplePaletteBlend(struct Sprite *sprite); -static void AnimComplexPaletteBlend(struct Sprite *sprite); -static void AnimCirclingSparkle(struct Sprite *sprite); -static void AnimShakeMonOrBattleTerrain(struct Sprite *sprite); -static void AnimHitSplatHandleInvert(struct Sprite *sprite); -static void AnimHitSplatPersistent(struct Sprite *sprite); -static void AnimConfusionDuck_Step(struct Sprite *sprite); -static void AnimSimplePaletteBlend_Step(struct Sprite *sprite); -static void AnimComplexPaletteBlend_Step1(struct Sprite *sprite); -static void AnimComplexPaletteBlend_Step2(struct Sprite *sprite); -static void BlendColorCycle(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount); -static void AnimTask_BlendColorCycleLoop(u8 taskId); -static void BlendColorCycleExclude(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount); -static void AnimTask_BlendColorCycleExcludeLoop(u8 taskId); -static void BlendColorCycleByTag(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount); -static void AnimTask_BlendColorCycleByTagLoop(u8 taskId); -static void AnimTask_FlashAnimTagWithColor_Step1(u8 taskId); -static void AnimTask_FlashAnimTagWithColor_Step2(u8 taskId); +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 AnimCirclingSparkle(struct Sprite *); +static void AnimShakeMonOrBattleTerrain(struct Sprite *); +static void AnimShakeMonOrBattleTerrain_Step(struct Sprite *); static void AnimShakeMonOrBattleTerrain_UpdateCoordOffsetEnabled(void); -static void AnimShakeMonOrBattleTerrain_Step(struct Sprite *sprite); -static void AnimTask_ShakeBattleTerrain_Step(u8 taskId); +static void AnimHitSplatPersistent(struct Sprite *); +static void AnimHitSplatHandleInvert(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 void AnimMovePowerSwapGuardSwap(struct Sprite *); - static const union AnimCmd sAnim_ConfusionDuck_0[] = { ANIMCMD_FRAME(0, 8), @@ -258,7 +258,7 @@ const struct SpriteTemplate gRandomPosHitSplatSpriteTemplate = .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gAffineAnims_HitSplat, - .callback = AnimHitSplatRandom, + .callback = SpriteCB_RandomCentredHits, }; const struct SpriteTemplate gMonEdgeHitSplatSpriteTemplate = @@ -360,6 +360,7 @@ static void AnimConfusionDuck(struct Sprite *sprite) sprite->data[4] = 0; StartSpriteAnim(sprite, 1); } + sprite->data[3] = gBattleAnimArgs[4]; sprite->callback = AnimConfusionDuck_Step; sprite->callback(sprite); @@ -369,10 +370,12 @@ static void AnimConfusionDuck_Step(struct Sprite *sprite) { sprite->x2 = Cos(sprite->data[0], 30); sprite->y2 = 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); @@ -387,7 +390,6 @@ static void AnimConfusionDuck_Step(struct Sprite *sprite) static void AnimSimplePaletteBlend(struct Sprite *sprite) { u32 selectedPalettes = UnpackSelectedBattlePalettes(gBattleAnimArgs[0]); - BeginNormalPaletteFade(selectedPalettes, gBattleAnimArgs[1], gBattleAnimArgs[2], gBattleAnimArgs[3], gBattleAnimArgs[4]); sprite->invisible = TRUE; sprite->callback = AnimSimplePaletteBlend_Step; @@ -400,17 +402,35 @@ static void AnimSimplePaletteBlend(struct Sprite *sprite) // 2: F_PAL_TARGET, gBattleAnimTarget OBJ palette // 3: F_PAL_ATK_PARTNER, gBattleAnimAttacker partner OBJ palette // 4: F_PAL_DEF_PARTNER, gBattleAnimTarget partner OBJ palette -// 5: F_PAL_ANIM_1, BG palette 8 +// 5: F_PAL_ANIM_1, BG palette 8 (or 14, if in Contest) // 6: F_PAL_ANIM_2, BG palette 9 u32 UnpackSelectedBattlePalettes(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 anim1 = (selector >> 5) & 1; - u8 anim2 = (selector >> 6) & 1; + bool8 battleBackground = selector & 1; + bool8 attacker = (selector >> 1) & 1; + bool8 target = (selector >> 2) & 1; + bool8 attackerPartner = (selector >> 3) & 1; + bool8 targetPartner = (selector >> 4) & 1; + bool8 anim1 = (selector >> 5) & 1; + bool8 anim2 = (selector >> 6) & 1; + u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gAnimMoveIndex); + + switch (moveTarget) + { + case MOVE_TARGET_BOTH: + if (target) + { + targetPartner |= 1; + } + break; + case MOVE_TARGET_FOES_AND_ALLY: + if (target) + { + targetPartner |= 1; + attackerPartner |= 1; + } + break; + } return GetBattlePalettesMask(battleBackground, attacker, target, attackerPartner, targetPartner, anim1, anim2); } @@ -433,6 +453,7 @@ static void AnimComplexPaletteBlend(struct Sprite *sprite) sprite->data[5] = gBattleAnimArgs[5]; sprite->data[6] = gBattleAnimArgs[6]; sprite->data[7] = gBattleAnimArgs[0]; + selectedPalettes = UnpackSelectedBattlePalettes(sprite->data[7]); BlendPalettes(selectedPalettes, gBattleAnimArgs[4], gBattleAnimArgs[3]); sprite->invisible = TRUE; @@ -445,24 +466,28 @@ static void AnimComplexPaletteBlend_Step1(struct Sprite *sprite) if (sprite->data[0] > 0) { - --sprite->data[0]; + sprite->data[0]--; return; } + if (gPaletteFade.active) return; + if (sprite->data[2] == 0) { sprite->callback = AnimComplexPaletteBlend_Step2; return; } + selectedPalettes = UnpackSelectedBattlePalettes(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]; + sprite->data[2]--; } static void AnimComplexPaletteBlend_Step2(struct Sprite *sprite) @@ -725,12 +750,15 @@ void AnimTask_FlashAnimTagWithColor(u8 taskId) 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]); + BeginNormalPaletteFade( + 1 << (paletteIndex + 16), + 0, + gBattleAnimArgs[4], + gBattleAnimArgs[4], + gBattleAnimArgs[3]); + gTasks[taskId].func = AnimTask_FlashAnimTagWithColor_Step1; } @@ -740,32 +768,42 @@ static void AnimTask_FlashAnimTagWithColor_Step1(u8 taskId) if (gTasks[taskId].data[0] > 0) { - --gTasks[taskId].data[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]); + { + 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]); + { + 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]; + gTasks[taskId].data[2]--; } static void AnimTask_FlashAnimTagWithColor_Step2(u8 taskId) @@ -775,7 +813,7 @@ static void AnimTask_FlashAnimTagWithColor_Step2(u8 taskId) if (!gPaletteFade.active) { selectedPalettes = 1 << (IndexOfSpritePaletteTag(gTasks[taskId].data[7]) + 16); - BeginNormalPaletteFade(selectedPalettes, 0, 0, 0, RGB(0, 0, 0)); + BeginNormalPaletteFade(selectedPalettes, 0, 0, 0, RGB_BLACK); DestroyAnimVisualTask(taskId); } } @@ -792,11 +830,75 @@ void AnimTask_InvertScreenColor(u8 taskId) selectedPalettes |= (0x10000 << gBattleAnimTarget); if (gBattleAnimArgs[0] & 0x8 && IsBattlerAlive(BATTLE_PARTNER(gBattleAnimTarget))) selectedPalettes |= (0x10000 << BATTLE_PARTNER(gBattleAnimTarget)); + if (gBattleAnimArgs[0] & 0x10 && IsBattlerAlive(BATTLE_PARTNER(gBattleAnimAttacker))) + selectedPalettes |= (0x10000 << BATTLE_PARTNER(gBattleAnimAttacker)); InvertPlttBuffer(selectedPalettes); DestroyAnimVisualTask(taskId); } +// Unused +#define tTimer data[0] +#define tLength data[1] +#define tFlagsScenery data[2] +#define tFlagsAttacker data[3] +#define tFlagsTarget data[4] +#define tColorR data[5] +#define tColorG data[6] +#define tColorB data[7] +void AnimTask_TintPalettes(u8 taskId) +{ + u8 attackerBattler; + u8 targetBattler; + u8 paletteIndex; + u32 selectedPalettes = 0; + + if (gTasks[taskId].tTimer == 0) + { + gTasks[taskId].tFlagsScenery = gBattleAnimArgs[0]; + gTasks[taskId].tFlagsAttacker = gBattleAnimArgs[1]; + gTasks[taskId].tFlagsTarget = gBattleAnimArgs[2]; + gTasks[taskId].tLength = gBattleAnimArgs[3]; + gTasks[taskId].tColorR = gBattleAnimArgs[4]; + gTasks[taskId].tColorG = gBattleAnimArgs[5]; + gTasks[taskId].tColorB = gBattleAnimArgs[6]; + } + + gTasks[taskId].tTimer++; + attackerBattler = gBattleAnimAttacker; + targetBattler = gBattleAnimTarget; + + if (gTasks[taskId].tFlagsScenery & (1 << 8)) + selectedPalettes = PALETTES_BG; + + if (gTasks[taskId].tFlagsScenery & 1) + { + paletteIndex = IndexOfSpritePaletteTag(gSprites[gHealthboxSpriteIds[attackerBattler]].template->paletteTag); + selectedPalettes |= (1 << paletteIndex) << 16; + } + + if (gTasks[taskId].tFlagsAttacker & (1 << 8)) + selectedPalettes |= (1 << attackerBattler) << 16; + + if (gTasks[taskId].tFlagsTarget & (1 << 8)) + selectedPalettes |= (1 << targetBattler) << 16; + + TintPlttBuffer(selectedPalettes, gTasks[taskId].tColorR, gTasks[taskId].tColorG, gTasks[taskId].tColorB); + if (gTasks[taskId].tTimer == gTasks[taskId].tLength) + { + UnfadePlttBuffer(selectedPalettes); + DestroyAnimVisualTask(taskId); + } +} +#undef tTimer +#undef tLength +#undef tFlagsScenery +#undef tFlagsAttacker +#undef tFlagsTarget +#undef tColorR +#undef tColorG +#undef tColorB + static void AnimShakeMonOrBattleTerrain(struct Sprite *sprite) { u16 var0; @@ -822,11 +924,13 @@ static void AnimShakeMonOrBattleTerrain(struct Sprite *sprite) 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; } @@ -837,10 +941,10 @@ static void AnimShakeMonOrBattleTerrain_Step(struct Sprite *sprite) if (sprite->data[3] > 0) { - --sprite->data[3]; + sprite->data[3]--; if (sprite->data[1] > 0) { - --sprite->data[1]; + sprite->data[1]--; } else { @@ -854,8 +958,11 @@ static void AnimShakeMonOrBattleTerrain_Step(struct Sprite *sprite) *(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) + { + for (i = 0; i < gBattlersCount; i++) gSprites[gBattlerSpriteIds[i]].coordOffsetEnabled = FALSE; + } + DestroyAnimSprite(sprite); } } @@ -864,6 +971,7 @@ static void AnimShakeMonOrBattleTerrain_UpdateCoordOffsetEnabled(void) { gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = FALSE; gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = FALSE; + if (gBattleAnimArgs[4] == 2) { gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = TRUE; @@ -940,10 +1048,11 @@ static void AnimTask_ShakeBattleTerrain_Step(u8 taskId) void AnimHitSplatBasic(struct Sprite *sprite) { StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); - if (gBattleAnimArgs[2] == 0) + if (gBattleAnimArgs[2] == ANIM_ATTACKER) InitSpritePosToAnimAttacker(sprite, TRUE); else InitSpritePosToAnimTarget(sprite, TRUE); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); } @@ -952,10 +1061,11 @@ void AnimHitSplatBasic(struct Sprite *sprite) static void AnimHitSplatPersistent(struct Sprite *sprite) { StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); - if (gBattleAnimArgs[2] == 0) + if (gBattleAnimArgs[2] == ANIM_ATTACKER) InitSpritePosToAnimAttacker(sprite, TRUE); else InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[4]; sprite->callback = RunStoredCallbackWhenAffineAnimEnds; StoreSpriteCallbackInData6(sprite, DestroyAnimSpriteAfterTimer); @@ -967,20 +1077,22 @@ static void AnimHitSplatHandleInvert(struct Sprite *sprite) { if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER && !IsContest()) gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + AnimHitSplatBasic(sprite); } void AnimHitSplatRandom(struct Sprite *sprite) { if (gBattleAnimArgs[1] == -1) - gBattleAnimArgs[1] = Random() & 3; + gBattleAnimArgs[1] = Random2() & 3; + + if (!InitSpritePosToAnimBattler(gBattleAnimArgs[0], sprite, FALSE)) + return; StartSpriteAffineAnim(sprite, gBattleAnimArgs[1]); - if (gBattleAnimArgs[0] == ANIM_ATTACKER) - InitSpritePosToAnimAttacker(sprite, FALSE); - else - InitSpritePosToAnimTarget(sprite, FALSE); - sprite->x2 += (Random() % 48) - 24; - sprite->y2 += (Random() % 24) - 12; + + sprite->x2 += (Random2() % 48) - 24; + sprite->y2 += (Random2() % 24) - 12; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); sprite->callback = RunStoredCallbackWhenAffineAnimEnds; } @@ -1003,6 +1115,7 @@ void AnimCrossImpact(struct Sprite *sprite) InitSpritePosToAnimAttacker(sprite, TRUE); else InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[3]; StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); sprite->callback = WaitAnimForDuration; @@ -1015,6 +1128,7 @@ void AnimFlashingHitSplat(struct Sprite *sprite) InitSpritePosToAnimAttacker(sprite, TRUE); else InitSpritePosToAnimTarget(sprite, TRUE); + sprite->callback = AnimFlashingHitSplat_Step; } diff --git a/src/palette.c b/src/palette.c index 00b9555cc..3eccd7c48 100644 --- a/src/palette.c +++ b/src/palette.c @@ -411,6 +411,45 @@ void InvertPlttBuffer(u32 selectedPalettes) } } +void TintPlttBuffer(u32 selectedPalettes, s8 r, s8 g, s8 b) +{ + u16 paletteOffset = 0; + + while (selectedPalettes) + { + if (selectedPalettes & 1) + { + u32 i; + for (i = 0; i < 16; i++) + { + struct PlttData *data = (struct PlttData *)&gPlttBufferFaded[paletteOffset + i]; + data->r += r; + data->g += g; + data->b += b; + } + } + selectedPalettes >>= 1; + paletteOffset += 16; + } +} + +void UnfadePlttBuffer(u32 selectedPalettes) +{ + u16 paletteOffset = 0; + + while (selectedPalettes) + { + if (selectedPalettes & 1) + { + u8 i; + for (i = 0; i < 16; i++) + gPlttBufferFaded[paletteOffset + i] = gPlttBufferUnfaded[paletteOffset + i]; + } + selectedPalettes >>= 1; + paletteOffset += 16; + } +} + void BeginFastPaletteFade(u32 submode) { gPaletteFade.deltaY = 2;