From f5e3464e8306d6f14438d9f05ed04769f0a7429f Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Tue, 7 Oct 2025 14:50:16 -0600 Subject: [PATCH] Fix Brine move anim and document Water Spout anim (#7865) --- data/battle_anim_scripts.s | 2 +- src/battle_anim_water.c | 135 ++++++++++++++++++++++++++++++------- 2 files changed, 113 insertions(+), 24 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index a741c372ea..7de4958345 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -171,7 +171,7 @@ gBattleAnimMove_Brine:: playsewithpan SE_M_DIVE, -64 waitforvisualfinish delay 16 - createvisualtask AnimTask_WaterSpoutRain, 5 + createvisualtask AnimTask_BrineRain, 5 playsewithpan SE_M_SURF, +63 clearmonbg ANIM_DEF_PARTNER blendoff diff --git a/src/battle_anim_water.c b/src/battle_anim_water.c index 490136d116..5674cd5cc7 100644 --- a/src/battle_anim_water.c +++ b/src/battle_anim_water.c @@ -45,6 +45,7 @@ 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_BrineRain_Step(u8); static void AnimTask_WaterSpoutLaunch_Step(u8); static void AnimTask_WaterSpoutRain_Step(u8); static u8 GetWaterSpoutPowerForAnim(void); @@ -1442,24 +1443,97 @@ static void AnimSmallWaterOrb(struct Sprite *sprite) } } +#define tRainState data[0] +#define tWaterSpoutPower data[1] +#define tDropTaskDelay data[2] +#define tDropInitialXPos data[4] +#define tDropXRange data[5] +#define tDropEndYPos data[6] +#define tDropXPos data[7] +#define tSineTableIndex data[8] +#define tCurrentDropSprites data[9] +#define tDropHasHit data[10] +#define tCreatedDropSprites data[11] +#define tMaxDropSprites data[12] +#define tShakeTasksCreated data[13] +#define tDropInitialYPos data[14] + +void AnimTask_BrineRain(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (IsOnPlayerSide(gBattleAnimAttacker)) + { + task->tDropEndYPos = 40; + task->tDropInitialYPos = 0; + } + else + { + task->tDropEndYPos = 90; + task->tDropInitialYPos = 40; + } + task->tDropInitialXPos = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + task->tDropXRange = 40; + task->tDropXPos = task->tDropInitialXPos; + task->tMaxDropSprites = 10; + task->func = AnimTask_BrineRain_Step; +} + +static void AnimTask_BrineRain_Step(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 taskId2; + + switch (task->tRainState) + { + case 0: + if (++task->tDropTaskDelay > 2) + { + task->tDropTaskDelay = 0; + CreateWaterSpoutRainDroplet(task, taskId); + } + if (task->tDropHasHit != FALSE && task->tShakeTasksCreated == FALSE) + { + gBattleAnimArgs[0] = ANIM_TARGET; + gBattleAnimArgs[1] = 0; + gBattleAnimArgs[2] = 12; + taskId2 = CreateTask(AnimTask_HorizontalShake, 80); + if (taskId2 != TASK_NONE) + { + gTasks[taskId2].func(taskId2); + gAnimVisualTaskCount++; + } + task->tShakeTasksCreated = TRUE; + } + if (task->tCreatedDropSprites >= task->tMaxDropSprites) + task->tRainState++; + break; + case 1: + if (task->tCurrentDropSprites == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + void AnimTask_WaterSpoutRain(u8 taskId) { struct Task *task = &gTasks[taskId]; - task->data[1] = GetWaterSpoutPowerForAnim(); + task->tWaterSpoutPower = GetWaterSpoutPowerForAnim(); if (IsOnPlayerSide(gBattleAnimAttacker)) { - task->data[4] = 136; - task->data[6] = 40; + task->tDropInitialXPos = 136; + task->tDropEndYPos = 40; } else { - task->data[4] = 16; - task->data[6] = 80; + task->tDropInitialXPos = 16; + task->tDropEndYPos = 80; } - task->data[5] = 98; - task->data[7] = task->data[4] + 49; - task->data[12] = task->data[1] * 5 + 5; + task->tDropXRange = 98; + task->tDropXPos = task->tDropInitialXPos + 49; + task->tMaxDropSprites = task->tWaterSpoutPower * 5 + 5; + task->tDropInitialYPos = 0; task->func = AnimTask_WaterSpoutRain_Step; } @@ -1468,15 +1542,15 @@ static void AnimTask_WaterSpoutRain_Step(u8 taskId) struct Task *task = &gTasks[taskId]; u8 taskId2; - switch (task->data[0]) + switch (task->tRainState) { case 0: - if (++task->data[2] > 2) + if (++task->tDropTaskDelay > 2) { - task->data[2] = 0; + task->tDropTaskDelay = 0; CreateWaterSpoutRainDroplet(task, taskId); } - if (task->data[10] != 0 && task->data[13] == 0) + if (task->tDropHasHit != FALSE && task->tShakeTasksCreated == FALSE) { gBattleAnimArgs[0] = ANIM_TARGET; gBattleAnimArgs[1] = 0; @@ -1494,13 +1568,13 @@ static void AnimTask_WaterSpoutRain_Step(u8 taskId) gTasks[taskId2].func(taskId2); gAnimVisualTaskCount++; } - task->data[13] = 1; + task->tShakeTasksCreated = TRUE; } - if (task->data[11] >= task->data[12]) - task->data[0]++; + if (task->tCreatedDropSprites >= task->tMaxDropSprites) + task->tRainState++; break; case 1: - if (task->data[9] == 0) + if (task->tCurrentDropSprites == 0) DestroyAnimVisualTask(taskId); break; } @@ -1508,8 +1582,8 @@ static void AnimTask_WaterSpoutRain_Step(u8 taskId) 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); + u16 yPosArg = ((gSineTable[task->tSineTableIndex] + 3) >> 4) + task->tDropEndYPos; + u8 spriteId = CreateSprite(&gSmallWaterOrbSpriteTemplate, task->tDropXPos, task->tDropInitialYPos, 0); if (spriteId != MAX_SPRITES) { @@ -1517,11 +1591,11 @@ static void CreateWaterSpoutRainDroplet(struct Task *task, u8 taskId) gSprites[spriteId].data[5] = yPosArg; gSprites[spriteId].data[6] = taskId; gSprites[spriteId].data[7] = 9; - task->data[9]++; + task->tCurrentDropSprites++; } - 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]; + task->tCreatedDropSprites++; + task->tSineTableIndex = (task->tSineTableIndex + 39) & 0xFF; + task->tDropXPos = (ISO_RANDOMIZE2(task->tDropXPos) % task->tDropXRange) + task->tDropInitialXPos; } static void AnimWaterSpoutRain(struct Sprite *sprite) @@ -1531,7 +1605,7 @@ static void AnimWaterSpoutRain(struct Sprite *sprite) sprite->y += 8; if (sprite->y >= sprite->data[5]) { - gTasks[sprite->data[6]].data[10] = 1; + gTasks[sprite->data[6]].tDropHasHit = TRUE; sprite->data[1] = CreateSprite(&gWaterHitSplatSpriteTemplate, sprite->x, sprite->y, 1); if (sprite->data[1] != MAX_SPRITES) { @@ -1560,6 +1634,21 @@ static void AnimWaterSpoutRainHit(struct Sprite *sprite) } } +#undef tRainState +#undef tWaterSpoutPower +#undef tDropTaskDelay +#undef tDropInitialXPos +#undef tDropXRange +#undef tDropEndYPos +#undef tDropXPos +#undef tSineTableIndex +#undef tCurrentDropSprites +#undef tDropHasHit +#undef tCreatedDropSprites +#undef tMaxDropSprites +#undef tShakeTasksCreated +#undef tDropInitialYPos + void AnimTask_WaterSport(u8 taskId) { struct Task *task = &gTasks[taskId];