diff options
author | PikalaxALT <PikalaxALT@users.noreply.github.com> | 2019-10-12 21:08:06 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-12 21:08:06 -0400 |
commit | 807e03c25d6acd9e5c2bf5337a078b2dfb90f4d9 (patch) | |
tree | f834927206547939d8ed4ee9e62e050ff6c8f4f9 /src | |
parent | c52ba041cb793fc3154ab4244796fd5814bfbf18 (diff) | |
parent | ff795fa8347f111163ef033a4ae132a3a3caf1eb (diff) |
Merge pull request #107 from jiangzhengwenjz/battle
battle (2nd take)
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_anim_mon_movement.c | 28 | ||||
-rw-r--r-- | src/battle_anim_mons.c | 2253 | ||||
-rw-r--r-- | src/battle_anim_sound_tasks.c | 313 | ||||
-rw-r--r-- | src/battle_anim_utility_funcs.c | 946 | ||||
-rw-r--r-- | src/battle_controller_player.c | 4 | ||||
-rw-r--r-- | src/battle_intro.c | 495 | ||||
-rw-r--r-- | src/battle_transition.c | 82 | ||||
-rw-r--r-- | src/bug.c | 462 | ||||
-rw-r--r-- | src/dark.c | 921 | ||||
-rw-r--r-- | src/daycare.c | 4 | ||||
-rw-r--r-- | src/dragon.c | 431 | ||||
-rw-r--r-- | src/flying.c | 1289 | ||||
-rw-r--r-- | src/ghost.c | 1484 | ||||
-rw-r--r-- | src/ground.c | 724 | ||||
-rw-r--r-- | src/normal.c | 916 | ||||
-rw-r--r-- | src/pokemon.c | 1 | ||||
-rw-r--r-- | src/psychic.c | 1083 | ||||
-rw-r--r-- | src/rock.c | 830 |
18 files changed, 12205 insertions, 61 deletions
diff --git a/src/battle_anim_mon_movement.c b/src/battle_anim_mon_movement.c index 88fbce6da..21d07246f 100644 --- a/src/battle_anim_mon_movement.c +++ b/src/battle_anim_mon_movement.c @@ -92,7 +92,7 @@ const struct SpriteTemplate gUnknown_83D4EB4 = // arg 4: frame delay void AnimTask_ShakeMon(u8 taskId) { - u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]); + u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); if (spriteId == 0xFF) DestroyAnimVisualTask(taskId); @@ -150,7 +150,7 @@ void AnimTask_ShakeMon2(u8 taskId) if (gBattleAnimArgs[0] < MAX_BATTLERS_COUNT) { - spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]); + spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); if (spriteId == 0xFF) abort = TRUE; } @@ -228,7 +228,7 @@ static void AnimTask_ShakeMon2Step(u8 taskId) // arg 4: delay void AnimTask_ShakeMonInPlace(u8 taskId) { - u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]); + u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); if (spriteId == 0xFF) DestroyAnimVisualTask(taskId); @@ -290,7 +290,7 @@ static void AnimTask_ShakeMonInPlaceStep(u8 taskId) // arg 4: duration void AnimTask_ShakeAndSinkMon(u8 taskId) { - u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]); + u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); gSprites[spriteId].pos2.x = gBattleAnimArgs[1]; gTasks[taskId].data[0] = spriteId; @@ -331,7 +331,7 @@ void AnimTask_TranslateMonElliptical(u8 taskId) { u8 wavePeriod = 1; u8 i; - u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]); + u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); if (gBattleAnimArgs[4] > 5) gBattleAnimArgs[4] = 5; for (i = 0; i < gBattleAnimArgs[4]; i++) @@ -414,7 +414,7 @@ static void DoVerticalDip(struct Sprite * sprite) { u8 spriteId; sprite->invisible = TRUE; - spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]); + spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[2]); sprite->data[0] = gBattleAnimArgs[0]; sprite->data[1] = 0; sprite->data[2] = gBattleAnimArgs[1]; @@ -581,7 +581,7 @@ void AnimTask_WindUpLunge(u8 taskId) gBattleAnimArgs[1] = -gBattleAnimArgs[1]; gBattleAnimArgs[5] = -gBattleAnimArgs[5]; } - gTasks[taskId].data[0] = GetAnimBankSpriteId(gBattleAnimArgs[0]); + gTasks[taskId].data[0] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); gTasks[taskId].data[1] = gBattleAnimArgs[1] * 256 / gBattleAnimArgs[3]; gTasks[taskId].data[2] = gBattleAnimArgs[2]; gTasks[taskId].data[3] = gBattleAnimArgs[3]; @@ -627,7 +627,7 @@ void sub_80995FC(u8 taskId) { case 0: case 1: - spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]); + spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); break; case 2: if (!IsBattlerSpriteVisible(gBattleAnimAttacker ^ BIT_FLANK)) @@ -678,7 +678,7 @@ void AnimTask_SwayMon(u8 taskId) u8 spriteId; if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - spriteId = GetAnimBankSpriteId(gBattleAnimArgs[4]); + spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[4]); gTasks[taskId].data[0] = gBattleAnimArgs[0]; gTasks[taskId].data[1] = gBattleAnimArgs[1]; gTasks[taskId].data[2] = gBattleAnimArgs[2]; @@ -735,7 +735,7 @@ static void AnimTask_SwayMonStep(u8 taskId) // arg 4: sprite object mode void AnimTask_ScaleMonAndRestore(u8 taskId) { - u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[3]); + u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[3]); PrepareBattlerSpriteForRotScale(spriteId, gBattleAnimArgs[4]); gTasks[taskId].data[0] = gBattleAnimArgs[0]; gTasks[taskId].data[1] = gBattleAnimArgs[1]; @@ -773,7 +773,7 @@ static void AnimTask_ScaleMonAndRestoreStep(u8 taskId) void sub_8099980(u8 taskId) { - u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]); + u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[2]); PrepareBattlerSpriteForRotScale(spriteId, 0); gTasks[taskId].data[1] = 0; gTasks[taskId].data[2] = gBattleAnimArgs[0]; @@ -806,7 +806,7 @@ void sub_8099980(u8 taskId) void sub_8099A78(u8 taskId) { - u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]); + u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[2]); PrepareBattlerSpriteForRotScale(spriteId, 0); gTasks[taskId].data[1] = 0; gTasks[taskId].data[2] = gBattleAnimArgs[0]; @@ -844,7 +844,7 @@ static void sub_8099B54(u8 taskId) gTasks[taskId].data[3] += gTasks[taskId].data[4]; SetSpriteRotScale(gTasks[taskId].data[5], 0x100, 0x100, gTasks[taskId].data[3]); if (gTasks[taskId].data[7]) - sub_80759DC(gTasks[taskId].data[5]); + SetBattlerSpriteYOffsetFromRotation(gTasks[taskId].data[5]); if (++gTasks[taskId].data[1] >= gTasks[taskId].data[2]) { switch (gTasks[taskId].data[6]) @@ -888,7 +888,7 @@ void sub_8099BD4(u8 taskId) gTasks[taskId].data[12] = 0; gTasks[taskId].data[10] = gBattleAnimArgs[3]; gTasks[taskId].data[11] = gBattleAnimArgs[4]; - gTasks[taskId].data[7] = GetAnimBankSpriteId(1); + gTasks[taskId].data[7] = GetAnimBattlerSpriteId(1); gTasks[taskId].data[8] = gSprites[gTasks[taskId].data[7]].pos2.x; gTasks[taskId].data[9] = gSprites[gTasks[taskId].data[7]].pos2.y; gTasks[taskId].data[0] = 0; diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c new file mode 100644 index 000000000..ed9c9bc2b --- /dev/null +++ b/src/battle_anim_mons.c @@ -0,0 +1,2253 @@ +#include "global.h" +#include "battle_anim.h" +#include "bg.h" +#include "data.h" +#include "decompress.h" +#include "dma3.h" +#include "gpu_regs.h" +#include "malloc.h" +#include "palette.h" +#include "pokemon_icon.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "util.h" +#include "constants/battle_anim.h" +#include "constants/species.h" + +#define GET_UNOWN_LETTER(personality) (( \ + (((personality & 0x03000000) >> 24) << 6) \ + | (((personality & 0x00030000) >> 16) << 4) \ + | (((personality & 0x00000300) >> 8) << 2) \ + | (((personality & 0x00000003) >> 0) << 0) \ +) % 28) + +#define IS_DOUBLE_BATTLE() (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + +static u8 GetBattlerSpriteFinal_Y(u8 battlerId, u16 species, bool8 a3); +static void sub_8075658(struct Sprite *sprite); +static void sub_80757E8(struct Sprite *sprite); +static bool8 sub_80758DC(void); +static void sub_8075EF0(struct Sprite *sprite); +static void sub_80760D0(u8 taskId); +static void AnimTask_BlendMonInAndOutSetup(struct Task *task); +static void AnimTask_BlendMonInAndOutStep(u8 taskId); +static u16 GetBattlerYDeltaFromSpriteId(u8 spriteId); +static void sub_8077118(u8 taskId); +static void sub_80771E4(struct Task *task, u8 taskId); +static void sub_8077268(struct Sprite *sprite); +static void sub_80772F4(struct Sprite *sprite); + +static EWRAM_DATA union AffineAnimCmd *sAnimTaskAffineAnim = NULL; +static EWRAM_DATA u32 gUnknown_2037F2C = 0; // not used + +static const struct UCoords8 sBattlerCoords[][4] = +{ + { + { 72, 80 }, + { 176, 40 }, + { 48, 40 }, + { 112, 80 }, + }, + { + { 32, 80 }, + { 200, 40 }, + { 90, 88 }, + { 152, 32 }, + }, +}; + +// One entry for each of the four Castform forms. +const struct MonCoords gCastformFrontSpriteCoords[] = +{ + { .size = 0x44, .y_offset = 17 }, // NORMAL + { .size = 0x66, .y_offset = 9 }, // SUN + { .size = 0x46, .y_offset = 9 }, // RAIN + { .size = 0x86, .y_offset = 8 }, // HAIL +}; + +static const u8 sCastformElevations[] = +{ + 13, // NORMAL + 14, // SUN + 13, // RAIN + 13, // HAIL +}; + +// Y position of the backsprite for each of the four Castform forms. +static const u8 sCastformBackSpriteYCoords[] = +{ + 0, // NORMAL + 0, // SUN + 0, // RAIN + 0, // HAIL +}; + +static const struct SpriteTemplate gUnknown_83AE054[] = +{ + { + .tileTag = 0xD755, + .paletteTag = 0xD755, + .oam = &gOamData_83ACA40, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }, + { + .tileTag = 0xD756, + .paletteTag = 0xD756, + .oam = &gOamData_83ACA40, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + } +}; + +static const struct SpriteSheet gUnknown_83AE084[] = +{ + { gMiscBlank_Gfx, 0x800, 0xD755 }, + { gMiscBlank_Gfx, 0x800, 0xD756 }, +}; + +u8 GetBattlerSpriteCoord(u8 battlerId, u8 coordType) +{ + u8 retVal; + u16 species; + struct BattleSpriteInfo *spriteInfo; + + switch (coordType) + { + case BATTLER_COORD_X: + case BATTLER_COORD_X_2: + retVal = sBattlerCoords[IS_DOUBLE_BATTLE()][GetBattlerPosition(battlerId)].x; + break; + case BATTLER_COORD_Y: + retVal = sBattlerCoords[IS_DOUBLE_BATTLE()][GetBattlerPosition(battlerId)].y; + break; + case BATTLER_COORD_Y_PIC_OFFSET: + case BATTLER_COORD_Y_PIC_OFFSET_DEFAULT: + default: + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = spriteInfo[battlerId].transformSpecies; + } + else + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = spriteInfo[battlerId].transformSpecies; + } + if (coordType == BATTLER_COORD_Y_PIC_OFFSET) + retVal = GetBattlerSpriteFinal_Y(battlerId, species, TRUE); + else + retVal = GetBattlerSpriteFinal_Y(battlerId, species, FALSE); + break; + } + return retVal; +} + +static u8 GetBattlerYDelta(u8 battlerId, u16 species) +{ + u16 letter; + u32 personality; + struct BattleSpriteInfo *spriteInfo; + u8 ret; + u16 coordSpecies; + + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + { + if (species == SPECIES_UNOWN) + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY); + else + personality = gTransformedPersonalities[battlerId]; + letter = GET_UNOWN_LETTER(personality); + if (!letter) + coordSpecies = species; + else + coordSpecies = letter + SPECIES_UNOWN_B - 1; + ret = gMonBackPicCoords[coordSpecies].y_offset; + } + else if (species == SPECIES_CASTFORM) + { + ret = sCastformBackSpriteYCoords[gBattleMonForms[battlerId]]; + } + else if (species > NUM_SPECIES) + { + ret = gMonBackPicCoords[0].y_offset; + } + else + { + ret = gMonBackPicCoords[species].y_offset; + } + } + else + { + if (species == SPECIES_UNOWN) + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY); + else + personality = gTransformedPersonalities[battlerId]; + letter = GET_UNOWN_LETTER(personality); + if (!letter) + coordSpecies = species; + else + coordSpecies = letter + SPECIES_UNOWN_B - 1; + ret = gMonFrontPicCoords[coordSpecies].y_offset; + } + else if (species == SPECIES_CASTFORM) + { + ret = gCastformFrontSpriteCoords[gBattleMonForms[battlerId]].y_offset; + } + else if (species > NUM_SPECIES) + { + ret = gMonFrontPicCoords[0].y_offset; + } + else + { + ret = gMonFrontPicCoords[species].y_offset; + } + } + return ret; +} + +static u8 GetBattlerElevation(u8 battlerId, u16 species) +{ + u8 ret = 0; + + if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT) + { + if (species == SPECIES_CASTFORM) + ret = sCastformElevations[gBattleMonForms[battlerId]]; + else if (species > NUM_SPECIES) + ret = gEnemyMonElevation[0]; + else + ret = gEnemyMonElevation[species]; + } + return ret; +} + +static u8 GetBattlerSpriteFinal_Y(u8 battlerId, u16 species, bool8 a3) +{ + u16 offset; + u8 y; + + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + { + offset = GetBattlerYDelta(battlerId, species); + } + else + { + offset = GetBattlerYDelta(battlerId, species); + offset -= GetBattlerElevation(battlerId, species); + } + y = offset + sBattlerCoords[IS_DOUBLE_BATTLE()][GetBattlerPosition(battlerId)].y; + if (a3) + { + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + y += 8; + if (y > 104) + y = 104; + } + return y; +} + +u8 GetBattlerSpriteCoord2(u8 battlerId, u8 coordType) +{ + u16 species; + struct BattleSpriteInfo *spriteInfo; + + if (coordType == BATTLER_COORD_Y_PIC_OFFSET || coordType == BATTLER_COORD_Y_PIC_OFFSET_DEFAULT) + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + species = gAnimBattlerSpecies[battlerId]; + else + species = spriteInfo[battlerId].transformSpecies; + if (coordType == BATTLER_COORD_Y_PIC_OFFSET) + return GetBattlerSpriteFinal_Y(battlerId, species, TRUE); + else + return GetBattlerSpriteFinal_Y(battlerId, species, FALSE); + } + else + { + return GetBattlerSpriteCoord(battlerId, coordType); + } +} + +u8 GetBattlerSpriteDefault_Y(u8 battlerId) +{ + return GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y_PIC_OFFSET_DEFAULT); +} + +u8 GetSubstituteSpriteDefault_Y(u8 battlerId) +{ + u16 y; + + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + y = GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y) + 16; + else + y = GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y) + 17; + return y; +} + +u8 GetGhostSpriteDefault_Y(u8 battlerId) +{ + if (GetBattlerSide(battlerId) != B_SIDE_OPPONENT) + return GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y_PIC_OFFSET_DEFAULT); + else + return GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y); +} + +u8 GetBattlerYCoordWithElevation(u8 battlerId) +{ + u16 species; + u8 y; + struct BattleSpriteInfo *spriteInfo; + + y = GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y); + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = spriteInfo[battlerId].transformSpecies; + } + else + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = spriteInfo[battlerId].transformSpecies; + } + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + y -= GetBattlerElevation(battlerId, species); + return y; +} + +u8 GetAnimBattlerSpriteId(u8 animBattler) +{ + u8 *sprites; + + if (animBattler == ANIM_ATTACKER) + { + if (IsBattlerSpritePresent(gBattleAnimAttacker)) + { + sprites = gBattlerSpriteIds; + return sprites[gBattleAnimAttacker]; + } + else + { + return 0xFF; + } + } + else if (animBattler == ANIM_TARGET) + { + if (IsBattlerSpritePresent(gBattleAnimTarget)) + { + sprites = gBattlerSpriteIds; + return sprites[gBattleAnimTarget]; + } + else + { + return 0xFF; + } + } + else if (animBattler == ANIM_ATK_PARTNER) + { + if (!IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + return 0xFF; + else + return gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)]; + } + else + { + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimTarget))) + return gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimTarget)]; + else + return 0xFF; + } +} + +void StoreSpriteCallbackInData6(struct Sprite *sprite, SpriteCallback callback) +{ + sprite->data[6] = (u32)(callback) & 0xFFFF; + sprite->data[7] = (u32)(callback) >> 16; +} + +static void SetCallbackToStoredInData6(struct Sprite *sprite) +{ + u32 callback = (u16)sprite->data[6] | (sprite->data[7] << 16); + + sprite->callback = (SpriteCallback)callback; +} + +void TranslateSpriteInCircleOverDuration(struct Sprite *sprite) +{ + if (sprite->data[3]) + { + sprite->pos2.x = Sin(sprite->data[0], sprite->data[1]); + sprite->pos2.y = Cos(sprite->data[0], sprite->data[1]); + sprite->data[0] += sprite->data[2]; + if (sprite->data[0] >= 0x100) + sprite->data[0] -= 0x100; + else if (sprite->data[0] < 0) + sprite->data[0] += 0x100; + --sprite->data[3]; + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +void TranslateSpriteInGrowingCircleOverDuration(struct Sprite *sprite) +{ + if (sprite->data[3]) + { + sprite->pos2.x = Sin(sprite->data[0], (sprite->data[5] >> 8) + sprite->data[1]); + sprite->pos2.y = Cos(sprite->data[0], (sprite->data[5] >> 8) + sprite->data[1]); + sprite->data[0] += sprite->data[2]; + sprite->data[5] += sprite->data[4]; + if (sprite->data[0] >= 0x100) + sprite->data[0] -= 0x100; + else if (sprite->data[0] < 0) + sprite->data[0] += 0x100; + --sprite->data[3]; + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +// not used +static void sub_8074B5C(struct Sprite *sprite) +{ + if (sprite->data[3]) + { + sprite->pos2.x = Sin(sprite->data[0], sprite->data[1]); + sprite->pos2.y = Cos(sprite->data[4], sprite->data[1]); + sprite->data[0] += sprite->data[2]; + sprite->data[4] += sprite->data[5]; + if (sprite->data[0] >= 0x100) + sprite->data[0] -= 0x100; + else if (sprite->data[0] < 0) + sprite->data[0] += 0x100; + if (sprite->data[4] >= 0x100) + sprite->data[4] -= 0x100; + else if (sprite->data[4] < 0) + sprite->data[4] += 0x100; + --sprite->data[3]; + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +void TranslateSpriteInEllipseOverDuration(struct Sprite *sprite) +{ + if (sprite->data[3]) + { + sprite->pos2.x = Sin(sprite->data[0], sprite->data[1]); + sprite->pos2.y = Cos(sprite->data[0], sprite->data[4]); + sprite->data[0] += sprite->data[2]; + if (sprite->data[0] >= 0x100) + sprite->data[0] -= 0x100; + else if (sprite->data[0] < 0) + sprite->data[0] += 0x100; + --sprite->data[3]; + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +// Simply waits until the sprite's data[0] hits zero. +// This is used to let sprite anims or affine anims to run for a designated +// duration. +void WaitAnimForDuration(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + --sprite->data[0]; + else + SetCallbackToStoredInData6(sprite); +} + +static void sub_8074C64(struct Sprite *sprite) +{ + sub_8074C80(sprite); + sprite->callback = TranslateSpriteLinear; + sprite->callback(sprite); +} + +void sub_8074C80(struct Sprite *sprite) +{ + s16 old; + s32 xDiff; + + if (sprite->data[1] > sprite->data[2]) + sprite->data[0] = -sprite->data[0]; + xDiff = sprite->data[2] - sprite->data[1]; + old = sprite->data[0]; + sprite->data[0] = abs(xDiff / sprite->data[0]); + sprite->data[2] = (sprite->data[4] - sprite->data[3]) / sprite->data[0]; + sprite->data[1] = old; +} + +void TranslateSpriteLinear(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + { + --sprite->data[0]; + sprite->pos2.x += sprite->data[1]; + sprite->pos2.y += sprite->data[2]; + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +void TranslateSpriteLinearFixedPoint(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + { + --sprite->data[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; + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +static void TranslateSpriteLinearFixedPointIconFrame(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + { + --sprite->data[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; + } + else + { + SetCallbackToStoredInData6(sprite); + } + + UpdateMonIconFrame(sprite); +} + +// not used +static void sub_8074D80(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x + sprite->pos2.x; + sprite->data[3] = sprite->pos1.y + sprite->pos2.y; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + sprite->callback = sub_8074C64; +} + +void TranslateMonSpriteLinear(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + { + --sprite->data[0]; + gSprites[sprite->data[3]].pos2.x += sprite->data[1]; + gSprites[sprite->data[3]].pos2.y += sprite->data[2]; + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +void TranslateMonSpriteLinearFixedPoint(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + { + --sprite->data[0]; + sprite->data[3] += sprite->data[1]; + sprite->data[4] += sprite->data[2]; + gSprites[sprite->data[5]].pos2.x = sprite->data[3] >> 8; + gSprites[sprite->data[5]].pos2.y = sprite->data[4] >> 8; + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +void TranslateSpriteLinearAndFlicker(struct Sprite *sprite) +{ + if (sprite->data[0] > 0) + { + --sprite->data[0]; + sprite->pos2.x = sprite->data[2] >> 8; + sprite->data[2] += sprite->data[1]; + sprite->pos2.y = sprite->data[4] >> 8; + sprite->data[4] += sprite->data[3]; + if (sprite->data[0] % sprite->data[5] == 0) + { + if (sprite->data[5]) + sprite->invisible ^= 1; + } + } + else + { + SetCallbackToStoredInData6(sprite); + } +} + +void DestroySpriteAndMatrix(struct Sprite *sprite) +{ + FreeSpriteOamMatrix(sprite); + DestroyAnimSprite(sprite); +} + +// not used +static void sub_8074EF4(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x + sprite->pos2.x; + sprite->data[3] = sprite->pos1.y + sprite->pos2.y; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->callback = sub_8074C64; +} + +// not used +static void sub_8074F38(struct Sprite *sprite) +{ + ResetPaletteStructByUid(sprite->data[5]); + DestroySpriteAndMatrix(sprite); +} + +void RunStoredCallbackWhenAffineAnimEnds(struct Sprite *sprite) +{ + if (sprite->affineAnimEnded) + SetCallbackToStoredInData6(sprite); +} + +void RunStoredCallbackWhenAnimEnds(struct Sprite *sprite) +{ + if (sprite->animEnded) + SetCallbackToStoredInData6(sprite); +} + +void DestroyAnimSpriteAndDisableBlend(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimSprite(sprite); +} + +void DestroyAnimVisualTaskAndDisableBlend(u8 taskId) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimVisualTask(taskId); +} + +void SetSpriteCoordsToAnimAttackerCoords(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); +} + +// Sets the initial x offset of the anim sprite depending on the horizontal orientation +// of the two involved mons. +void SetAnimSpriteInitialXOffset(struct Sprite *sprite, s16 xOffset) +{ + u16 attackerX = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); + u16 targetX = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X); + + if (attackerX > targetX) + { + sprite->pos1.x -= xOffset; + } + else if (attackerX < targetX) + { + sprite->pos1.x += xOffset; + } + else + { + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos1.x -= xOffset; + else + sprite->pos1.x += xOffset; + } +} + +void InitAnimArcTranslation(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + InitAnimLinearTranslation(sprite); + sprite->data[6] = 0x8000 / sprite->data[0]; + sprite->data[7] = 0; +} + +bool8 TranslateAnimHorizontalArc(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + return TRUE; + sprite->data[7] += sprite->data[6]; + sprite->pos2.y += Sin((u8)(sprite->data[7] >> 8), sprite->data[5]); + return FALSE; +} + +bool8 TranslateAnimVerticalArc(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + return TRUE; + sprite->data[7] += sprite->data[6]; + sprite->pos2.x += Sin((u8)(sprite->data[7] >> 8), sprite->data[5]); + return FALSE; +} + +void SetSpritePrimaryCoordsFromSecondaryCoords(struct Sprite *sprite) +{ + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = 0; + sprite->pos2.y = 0; +} + +void InitSpritePosToAnimTarget(struct Sprite *sprite, bool8 respectMonPicOffsets) +{ + // Battle anim sprites are automatically created at the anim target's center, which + // is why there is no else clause for the "respectMonPicOffsets" check. + if (!respectMonPicOffsets) + { + sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_X); + sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_Y); + } + SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); + sprite->pos1.y += gBattleAnimArgs[1]; +} + +void InitSpritePosToAnimAttacker(struct Sprite *sprite, bool8 respectMonPicOffsets) +{ + if (!respectMonPicOffsets) + { + sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimAttacker, BATTLER_COORD_X); + sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimAttacker, BATTLER_COORD_Y); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord2(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord2(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } + SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); + sprite->pos1.y += gBattleAnimArgs[1]; +} + +u8 GetBattlerSide(u8 battlerId) +{ + return GET_BATTLER_SIDE2(battlerId); +} + +u8 GetBattlerPosition(u8 battlerId) +{ + return GET_BATTLER_POSITION(battlerId); +} + +u8 GetBattlerAtPosition(u8 position) +{ + u8 i; + + for (i = 0; i < gBattlersCount; ++i) + if (gBattlerPositions[i] == position) + break; + return i; +} + +bool8 IsBattlerSpritePresent(u8 battlerId) +{ + if (gBattlerPositions[battlerId] == 0xFF) + { + return FALSE; + } + else if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + { + if (GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_HP) != 0) + return TRUE; + } + else + { + if (GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_HP) != 0) + return TRUE; + } + return FALSE; +} + +bool8 IsDoubleBattle(void) +{ + return IS_DOUBLE_BATTLE(); +} + +void sub_80752A0(struct BattleAnimBgData *animBgData) +{ + animBgData->bgTiles = gUnknown_2022BB8; + animBgData->bgTilemap = (u16 *)gUnknown_2022BBC; + animBgData->paletteId = 8; + animBgData->bgId = 1; + animBgData->tilesOffset = 0x200; + animBgData->unused = 0; +} + +void sub_80752C8(struct BattleAnimBgData *animBgData, u32 arg1) +{ + if (arg1 == 1) + { + sub_80752A0(animBgData); + } + else + { + animBgData->bgTiles = gUnknown_2022BB8; + animBgData->bgTilemap = (u16 *)gUnknown_2022BBC; + animBgData->paletteId = 9; + animBgData->bgId = 2; + animBgData->tilesOffset = 0x300; + animBgData->unused = 0; + } +} + +void sub_8075300(struct BattleAnimBgData *animBgData, u8 unused) +{ + animBgData->bgTiles = gUnknown_2022BB8; + animBgData->bgTilemap = (u16 *)gUnknown_2022BBC; + if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1) + { + animBgData->paletteId = 8; + animBgData->bgId = 1; + animBgData->tilesOffset = 0x200; + animBgData->unused = 0; + } + else + { + animBgData->paletteId = 9; + animBgData->bgId = 2; + animBgData->tilesOffset = 0x300; + animBgData->unused = 0; + } +} + +void sub_8075358(u32 bgId) +{ + struct BattleAnimBgData animBgData; + + sub_80752C8(&animBgData, bgId); + CpuFill32(0, animBgData.bgTiles, 0x2000); + LoadBgTiles(bgId, animBgData.bgTiles, 0x2000, animBgData.tilesOffset); + FillBgTilemapBufferRect(bgId, 0, 0, 0, 32, 64, 17); + CopyBgTilemapBufferToVram(bgId); +} + +void AnimLoadCompressedBgGfx(u32 bgId, const u32 *src, u32 tilesOffset) +{ + CpuFill32(0, gUnknown_2022BB8, 0x2000); + LZDecompressWram(src, gUnknown_2022BB8); + LoadBgTiles(bgId, gUnknown_2022BB8, 0x2000, tilesOffset); +} + +void InitAnimBgTilemapBuffer(u32 bgId, const void *src) +{ + FillBgTilemapBufferRect(bgId, 0, 0, 0, 32, 64, 17); + CopyToBgTilemapBuffer(bgId, src, 0, 0); +} + +void AnimLoadCompressedBgTilemap(u32 bgId, const u32 *src) +{ + InitAnimBgTilemapBuffer(bgId, src); + CopyBgTilemapBufferToVram(bgId); +} + +u8 sub_8075454(void) +{ + return 2; +} + +void sub_8075458(bool8 arg0) +{ + if (!arg0) + { + SetAnimBgAttribute(3, BG_ANIM_SCREEN_SIZE, 0); + SetAnimBgAttribute(3, BG_ANIM_AREA_OVERFLOW_MODE, 1); + } + else + { + SetAnimBgAttribute(3, BG_ANIM_SCREEN_SIZE, 1); + SetAnimBgAttribute(3, BG_ANIM_AREA_OVERFLOW_MODE, 0); + } +} + +void sub_8075490(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + InitSpriteDataForLinearTranslation(sprite); + sprite->callback = TranslateSpriteLinearFixedPointIconFrame; + sprite->callback(sprite); +} + +void InitSpriteDataForLinearTranslation(struct Sprite *sprite) +{ + s16 x = (sprite->data[2] - sprite->data[1]) << 8; + s16 y = (sprite->data[4] - sprite->data[3]) << 8; + + sprite->data[1] = x / sprite->data[0]; + sprite->data[2] = y / sprite->data[0]; + sprite->data[4] = 0; + sprite->data[3] = 0; +} + +void InitAnimLinearTranslation(struct Sprite *sprite) +{ + s32 x = sprite->data[2] - sprite->data[1]; + s32 y = sprite->data[4] - sprite->data[3]; + bool8 movingLeft = x < 0; + bool8 movingUp = y < 0; + u16 xDelta = abs(x) << 8; + u16 yDelta = abs(y) << 8; + + xDelta = xDelta / sprite->data[0]; + yDelta = yDelta / sprite->data[0]; + + if (movingLeft) + xDelta |= 1; + else + xDelta &= ~1; + + if (movingUp) + yDelta |= 1; + else + yDelta &= ~1; + + sprite->data[1] = xDelta; + sprite->data[2] = yDelta; + sprite->data[4] = 0; + sprite->data[3] = 0; +} + +void StartAnimLinearTranslation(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + InitAnimLinearTranslation(sprite); + sprite->callback = sub_807563C; + sprite->callback(sprite); +} + +void sub_80755B8(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + InitAnimLinearTranslation(sprite); + sprite->callback = sub_8075658; + sprite->callback(sprite); +} + +bool8 AnimTranslateLinear(struct Sprite *sprite) +{ + u16 v1, v2, x, y; + + if (!sprite->data[0]) + return TRUE; + v1 = sprite->data[1]; + v2 = sprite->data[2]; + x = sprite->data[3]; + y = sprite->data[4]; + x += v1; + y += v2; + if (v1 & 1) + sprite->pos2.x = -(x >> 8); + else + sprite->pos2.x = x >> 8; + + if (v2 & 1) + sprite->pos2.y = -(y >> 8); + else + sprite->pos2.y = y >> 8; + sprite->data[3] = x; + sprite->data[4] = y; + --sprite->data[0]; + return FALSE; +} + +void sub_807563C(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + SetCallbackToStoredInData6(sprite); +} + +static void sub_8075658(struct Sprite *sprite) +{ + sub_801236C(sprite); + if (AnimTranslateLinear(sprite)) + SetCallbackToStoredInData6(sprite); +} + +void sub_8075678(struct Sprite *sprite) +{ + s32 v1 = abs(sprite->data[2] - sprite->data[1]) << 8; + + sprite->data[0] = v1 / sprite->data[0]; + InitAnimLinearTranslation(sprite); +} + +void sub_80756A4(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + sub_8075678(sprite); + sprite->callback = sub_807563C; + sprite->callback(sprite); +} + +static void InitAnimFastLinearTranslation(struct Sprite *sprite) +{ + s32 xDiff = sprite->data[2] - sprite->data[1]; + s32 yDiff = sprite->data[4] - sprite->data[3]; + bool8 xSign = xDiff < 0; + bool8 ySign = yDiff < 0; + u16 x2 = abs(xDiff) << 4; + u16 y2 = abs(yDiff) << 4; + + x2 /= sprite->data[0]; + y2 /= sprite->data[0]; + if (xSign) + x2 |= 1; + else + x2 &= ~1; + if (ySign) + y2 |= 1; + else + y2 &= ~1; + sprite->data[1] = x2; + sprite->data[2] = y2; + sprite->data[4] = 0; + sprite->data[3] = 0; +} + +void InitAndRunAnimFastLinearTranslation(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + InitAnimFastLinearTranslation(sprite); + sprite->callback = sub_80757E8; + sprite->callback(sprite); +} + +bool8 AnimFastTranslateLinear(struct Sprite *sprite) +{ + u16 v1, v2, x, y; + + if (!sprite->data[0]) + return TRUE; + v1 = sprite->data[1]; + v2 = sprite->data[2]; + x = sprite->data[3]; + y = sprite->data[4]; + x += v1; + y += v2; + if (v1 & 1) + sprite->pos2.x = -(x >> 4); + else + sprite->pos2.x = x >> 4; + if (v2 & 1) + sprite->pos2.y = -(y >> 4); + else + sprite->pos2.y = y >> 4; + sprite->data[3] = x; + sprite->data[4] = y; + --sprite->data[0]; + return FALSE; +} + +static void sub_80757E8(struct Sprite *sprite) +{ + if (AnimFastTranslateLinear(sprite)) + SetCallbackToStoredInData6(sprite); +} + +void InitAnimFastLinearTranslationWithSpeed(struct Sprite *sprite) +{ + s32 xDiff = abs(sprite->data[2] - sprite->data[1]) << 4; + + sprite->data[0] = xDiff / sprite->data[0]; + InitAnimFastLinearTranslation(sprite); +} + +void sub_8075830(struct Sprite *sprite) +{ + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + InitAnimFastLinearTranslationWithSpeed(sprite); + sprite->callback = sub_80757E8; + sprite->callback(sprite); +} + +void SetSpriteRotScale(u8 spriteId, s16 xScale, s16 yScale, u16 rotation) +{ + s32 i; + struct ObjAffineSrcData src; + struct OamMatrix matrix; + + src.xScale = xScale; + src.yScale = yScale; + src.rotation = rotation; + if (sub_80758DC()) + src.xScale = -src.xScale; + i = gSprites[spriteId].oam.matrixNum; + ObjAffineSet(&src, &matrix, 1, 2); + gOamMatrices[i].a = matrix.a; + gOamMatrices[i].b = matrix.b; + gOamMatrices[i].c = matrix.c; + gOamMatrices[i].d = matrix.d; +} + +static bool8 sub_80758DC(void) +{ + return FALSE; +} + +void PrepareBattlerSpriteForRotScale(u8 spriteId, u8 objMode) +{ + u8 battlerId = gSprites[spriteId].data[0]; + + if (IsBattlerSpriteVisible(battlerId)) + gSprites[spriteId].invisible = FALSE; + gSprites[spriteId].oam.objMode = objMode; + gSprites[spriteId].affineAnimPaused = TRUE; + if (!gSprites[spriteId].oam.affineMode) + gSprites[spriteId].oam.matrixNum = gBattleSpritesDataPtr->healthBoxesData[battlerId].matrixNum; + gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_DOUBLE; + CalcCenterToCornerVec(&gSprites[spriteId], gSprites[spriteId].oam.shape, gSprites[spriteId].oam.size, gSprites[spriteId].oam.affineMode); +} + +void ResetSpriteRotScale(u8 spriteId) +{ + SetSpriteRotScale(spriteId, 0x100, 0x100, 0); + gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL; + gSprites[spriteId].oam.objMode = 0; + gSprites[spriteId].affineAnimPaused = FALSE; + CalcCenterToCornerVec(&gSprites[spriteId], gSprites[spriteId].oam.shape, gSprites[spriteId].oam.size, gSprites[spriteId].oam.affineMode); +} + +// Sets the sprite's y offset equal to the y displacement caused by the +// matrix's rotation. +void SetBattlerSpriteYOffsetFromRotation(u8 spriteId) +{ + u16 matrixNum = gSprites[spriteId].oam.matrixNum; + // The "c" component of the battler sprite matrix contains the sine of the rotation angle divided by some scale amount. + s16 c = gOamMatrices[matrixNum].c; + + if (c < 0) + c = -c; + gSprites[spriteId].pos2.y = c >> 3; +} + +void TrySetSpriteRotScale(struct Sprite *sprite, bool8 recalcCenterVector, s16 xScale, s16 yScale, u16 rotation) +{ + s32 i; + struct ObjAffineSrcData src; + struct OamMatrix matrix; + + if (sprite->oam.affineMode & 1) + { + sprite->affineAnimPaused = TRUE; + if (recalcCenterVector) + CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, sprite->oam.affineMode); + src.xScale = xScale; + src.yScale = yScale; + src.rotation = rotation; + if (sub_80758DC()) + src.xScale = -src.xScale; + i = sprite->oam.matrixNum; + ObjAffineSet(&src, &matrix, 1, 2); + gOamMatrices[i].a = matrix.a; + gOamMatrices[i].b = matrix.b; + gOamMatrices[i].c = matrix.c; + gOamMatrices[i].d = matrix.d; + } +} + +void sub_8075AD8(struct Sprite *sprite) +{ + TrySetSpriteRotScale(sprite, TRUE, 0x100, 0x100, 0); + sprite->affineAnimPaused = FALSE; + CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, sprite->oam.affineMode); +} + +static u16 ArcTan2_(s16 a, s16 b) +{ + return ArcTan2(a, b); +} + +u16 ArcTan2Neg(s16 a, s16 b) +{ + u16 var = ArcTan2_(a, b); + return -var; +} + +void SetGreyscaleOrOriginalPalette(u16 paletteNum, bool8 restoreOriginalColor) +{ + s32 i; + struct PlttData *originalColor; + struct PlttData *destColor; + u16 average; + + paletteNum *= 16; + + if (!restoreOriginalColor) + { + for (i = 0; i < 16; ++i) + { + originalColor = (struct PlttData *)&gPlttBufferUnfaded[paletteNum + i]; + average = originalColor->r + originalColor->g + originalColor->b; + average /= 3; + destColor = (struct PlttData *)&gPlttBufferFaded[paletteNum + i]; + destColor->r = average; + destColor->g = average; + destColor->b = average; + } + } + else + { + CpuCopy32(&gPlttBufferUnfaded[paletteNum], &gPlttBufferFaded[paletteNum], 32); + } +} + +u32 sub_8075BE8(u8 battleBackground, u8 attacker, u8 target, u8 attackerPartner, u8 targetPartner, u8 a6, u8 a7) +{ + u32 selectedPalettes = 0; + u32 shift; + + if (battleBackground) + { + selectedPalettes = 0xe; + } + if (attacker) + { + shift = gBattleAnimAttacker + 16; + selectedPalettes |= 1 << shift; + } + if (target) + { + shift = gBattleAnimTarget + 16; + selectedPalettes |= 1 << shift; + } + if (attackerPartner) + { + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + { + shift = BATTLE_PARTNER(gBattleAnimAttacker) + 16; + selectedPalettes |= 1 << shift; + } + } + if (targetPartner) + { + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimTarget))) + { + shift = BATTLE_PARTNER(gBattleAnimTarget) + 16; + selectedPalettes |= 1 << shift; + } + } + if (a6) + { + selectedPalettes |= 0x100; + } + if (a7) + { + selectedPalettes |= 0x200; + } + return selectedPalettes; +} + +u32 sub_8075CB8(u8 a1, u8 a2, u8 a3, u8 a4) +{ + u32 var = 0; + u32 shift; + + if (a1) + { + if (IsBattlerSpriteVisible(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) + { + var |= 1 << (GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) + 16); + } + } + if (a2) + { + if (IsBattlerSpriteVisible(GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT))) + { + shift = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT) + 16; + var |= 1 << shift; + } + } + if (a3) + { + if (IsBattlerSpriteVisible(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))) + { + shift = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT) + 16; + var |= 1 << shift; + } + } + if (a4) + { + if (IsBattlerSpriteVisible(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT))) + { + shift = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT) + 16; + var |= 1 << shift; + } + } + return var; +} + +u8 sub_8075D80(u8 a1) +{ + return a1; +} + +// not used +static u8 GetBattlerAtPosition_(u8 position) +{ + return GetBattlerAtPosition(position); +} + +void sub_8075D9C(struct Sprite *sprite) +{ + bool8 var; + + if (!sprite->data[0]) + { + if (!gBattleAnimArgs[3]) + var = TRUE; + else + var = FALSE; + if (!gBattleAnimArgs[2]) + InitSpritePosToAnimAttacker(sprite, var); + else + InitSpritePosToAnimTarget(sprite, var); + ++sprite->data[0]; + + } + else if (sprite->animEnded || sprite->affineAnimEnded) + { + DestroySpriteAndMatrix(sprite); + } +} + +// Linearly translates a sprite to a target position on the +// other mon's sprite. +// arg 0: initial x offset +// arg 1: initial y offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: duration +// arg 5: lower 8 bits = location on attacking mon, upper 8 bits = location on target mon pick to target +void TranslateAnimSpriteToTargetMonLocation(struct Sprite *sprite) +{ + bool8 v1; + u8 coordType; + + if (!(gBattleAnimArgs[5] & 0xFF00)) + v1 = TRUE; + else + v1 = FALSE; + if (!(gBattleAnimArgs[5] & 0xFF)) + coordType = BATTLER_COORD_Y_PIC_OFFSET; + else + coordType = BATTLER_COORD_Y; + InitSpritePosToAnimAttacker(sprite, v1); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, coordType) + gBattleAnimArgs[3]; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +void sub_8075E80(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + if (GetBattlerSide(gBattleAnimAttacker)) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[4]; + 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 = sub_8075EF0; +} + +static void sub_8075EF0(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroyAnimSprite(sprite); +} + +void sub_8075F0C(struct Sprite *sprite) +{ + bool8 r4; + u8 battlerId, coordType; + + if (!gBattleAnimArgs[6]) + { + r4 = TRUE; + coordType = BATTLER_COORD_Y_PIC_OFFSET; + } + else + { + r4 = FALSE; + coordType = BATTLER_COORD_Y; + } + if (!gBattleAnimArgs[5]) + { + InitSpritePosToAnimAttacker(sprite, r4); + battlerId = gBattleAnimAttacker; + } + else + { + InitSpritePosToAnimTarget(sprite, r4); + battlerId = gBattleAnimTarget; + } + if (GetBattlerSide(gBattleAnimAttacker)) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + InitSpritePosToAnimTarget(sprite, r4); + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = GetBattlerSpriteCoord(battlerId, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(battlerId, coordType) + gBattleAnimArgs[3]; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +s16 CloneBattlerSpriteWithBlend(u8 animBattler) +{ + u16 i; + u8 spriteId = GetAnimBattlerSpriteId(animBattler); + + if (spriteId != 0xFF) + { + for (i = 0; i < MAX_SPRITES; ++i) + { + if (!gSprites[i].inUse) + { + gSprites[i] = gSprites[spriteId]; + gSprites[i].oam.objMode = ST_OAM_OBJ_BLEND; + gSprites[i].invisible = FALSE; + return i; + } + } + } + return -1; +} + +void obj_delete_but_dont_free_vram(struct Sprite *sprite) +{ + sprite->usingSheet = TRUE; + DestroySprite(sprite); +} + +void sub_8076048(u8 taskId) +{ + s16 v1 = 0, v2 = 0; + + if (gBattleAnimArgs[2] > gBattleAnimArgs[0]) + v2 = 1; + if (gBattleAnimArgs[2] < gBattleAnimArgs[0]) + v2 = -1; + if (gBattleAnimArgs[3] > gBattleAnimArgs[1]) + v1 = 1; + if (gBattleAnimArgs[3] < gBattleAnimArgs[1]) + v1 = -1; + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = gBattleAnimArgs[4]; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = gBattleAnimArgs[0]; + gTasks[taskId].data[4] = gBattleAnimArgs[1]; + gTasks[taskId].data[5] = v2; + gTasks[taskId].data[6] = v1; + gTasks[taskId].data[7] = gBattleAnimArgs[2]; + gTasks[taskId].data[8] = gBattleAnimArgs[3]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gBattleAnimArgs[0], gBattleAnimArgs[1])); + gTasks[taskId].func = sub_80760D0; +} + +static void sub_80760D0(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (++task->data[0] > task->data[1]) + { + task->data[0] = 0; + if (++task->data[2] & 1) + { + if (task->data[3] != task->data[7]) + task->data[3] += task->data[5]; + } + else + { + if (task->data[4] != task->data[8]) + task->data[4] += task->data[6]; + } + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[3], task->data[4])); + if (task->data[3] == task->data[7] && task->data[4] == task->data[8]) + { + DestroyAnimVisualTask(taskId); + return; + } + } +} + +// Linearly blends a mon's sprite colors with a target color with increasing +// strength, and then blends out to the original color. +// arg 0: anim bank +// arg 1: blend color +// arg 2: target blend coefficient +// arg 3: initial delay +// arg 4: number of times to blend in and out +void AnimTask_BlendMonInAndOut(u8 task) +{ + u8 spriteId = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); + + if (spriteId == 0xFF) + { + DestroyAnimVisualTask(task); + return; + } + gTasks[task].data[0] = (gSprites[spriteId].oam.paletteNum * 0x10) + 0x101; + AnimTask_BlendMonInAndOutSetup(&gTasks[task]); +} + +static void AnimTask_BlendMonInAndOutSetup(struct Task *task) +{ + task->data[1] = gBattleAnimArgs[1]; + task->data[2] = 0; + task->data[3] = gBattleAnimArgs[2]; + task->data[4] = 0; + task->data[5] = gBattleAnimArgs[3]; + task->data[6] = 0; + task->data[7] = gBattleAnimArgs[4]; + task->func = AnimTask_BlendMonInAndOutStep; +} + +static void AnimTask_BlendMonInAndOutStep(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (++task->data[4] >= task->data[5]) + { + task->data[4] = 0; + if (!task->data[6]) + { + ++task->data[2]; + BlendPalette(task->data[0], 15, task->data[2], task->data[1]); + if (task->data[2] == task->data[3]) + task->data[6] = 1; + } + else + { + --task->data[2]; + BlendPalette(task->data[0], 15, task->data[2], task->data[1]); + if (!task->data[2]) + { + if (--task->data[7]) + { + task->data[4] = 0; + task->data[6] = 0; + } + else + { + DestroyAnimVisualTask(taskId); + return; + } + } + } + } +} + +void sub_8076288(u8 taskId) +{ + u8 palette = IndexOfSpritePaletteTag(gBattleAnimArgs[0]); + + if (palette == 0xFF) + { + DestroyAnimVisualTask(taskId); + return; + } + gTasks[taskId].data[0] = (palette * 0x10) + 0x101; + AnimTask_BlendMonInAndOutSetup(&gTasks[taskId]); +} + +void PrepareAffineAnimInTaskData(struct Task *task, u8 spriteId, const union AffineAnimCmd *affineAnimCmds) +{ + task->data[7] = 0; + task->data[8] = 0; + task->data[9] = 0; + task->data[15] = spriteId; + task->data[10] = 0x100; + task->data[11] = 0x100; + task->data[12] = 0; + StorePointerInVars(&task->data[13], &task->data[14], affineAnimCmds); + PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_NORMAL); +} + +bool8 RunAffineAnimFromTaskData(struct Task *task) +{ + sAnimTaskAffineAnim = LoadPointerFromVars(task->data[13], task->data[14]) + (task->data[7] << 3); + switch (sAnimTaskAffineAnim->type) + { + default: + if (!sAnimTaskAffineAnim->frame.duration) + { + task->data[10] = sAnimTaskAffineAnim->frame.xScale; + task->data[11] = sAnimTaskAffineAnim->frame.yScale; + task->data[12] = sAnimTaskAffineAnim->frame.rotation; + ++task->data[7]; + ++sAnimTaskAffineAnim; + } + task->data[10] += sAnimTaskAffineAnim->frame.xScale; + task->data[11] += sAnimTaskAffineAnim->frame.yScale; + task->data[12] += sAnimTaskAffineAnim->frame.rotation; + SetSpriteRotScale(task->data[15], task->data[10], task->data[11], task->data[12]); + SetBattlerSpriteYOffsetFromYScale(task->data[15]); + if (++task->data[8] >= sAnimTaskAffineAnim->frame.duration) + { + task->data[8] = 0; + ++task->data[7]; + } + break; + case AFFINEANIMCMDTYPE_JUMP: + task->data[7] = sAnimTaskAffineAnim->jump.target; + break; + case AFFINEANIMCMDTYPE_LOOP: + if (sAnimTaskAffineAnim->loop.count) + { + if (task->data[9]) + { + if (!--task->data[9]) + { + ++task->data[7]; + break; + } + } + else + { + task->data[9] = sAnimTaskAffineAnim->loop.count; + } + if (!task->data[7]) + { + break; + } + while (TRUE) + { + --task->data[7]; + --sAnimTaskAffineAnim; + if (sAnimTaskAffineAnim->type == AFFINEANIMCMDTYPE_LOOP) + { + ++task->data[7]; + return TRUE; + } + if (!task->data[7]) + return TRUE; + } + } + ++task->data[7]; + break; + case AFFINEANIMCMDTYPE_END: + gSprites[task->data[15]].pos2.y = 0; + ResetSpriteRotScale(task->data[15]); + return FALSE; + } + return TRUE; +} + +// Sets the sprite's y offset equal to the y displacement caused by the +// matrix's scale in the y dimension. +void SetBattlerSpriteYOffsetFromYScale(u8 spriteId) +{ + s32 var = 64 - GetBattlerYDeltaFromSpriteId(spriteId) * 2; + u16 matrix = gSprites[spriteId].oam.matrixNum; + s32 var2 = (var << 8) / gOamMatrices[matrix].d; + + if (var2 > 128) + var2 = 128; + gSprites[spriteId].pos2.y = (var - var2) / 2; +} + +// Sets the sprite's y offset equal to the y displacement caused by another sprite +// matrix's scale in the y dimension. +void SetBattlerSpriteYOffsetFromOtherYScale(u8 spriteId, u8 otherSpriteId) +{ + s32 var = 64 - GetBattlerYDeltaFromSpriteId(otherSpriteId) * 2; + u16 matrix = gSprites[spriteId].oam.matrixNum; + s32 var2 = (var << 8) / gOamMatrices[matrix].d; + + if (var2 > 128) + var2 = 128; + gSprites[spriteId].pos2.y = (var - var2) / 2; +} + +static u16 GetBattlerYDeltaFromSpriteId(u8 spriteId) +{ + struct BattleSpriteInfo *spriteInfo; + u8 battlerId = gSprites[spriteId].data[0]; + u16 species; + u16 i; + + for (i = 0; i < MAX_BATTLERS_COUNT; ++i) + { + if (gBattlerSpriteIds[i] == spriteId) + { + if (GetBattlerSide(i) == B_SIDE_PLAYER) + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); + else + species = spriteInfo[battlerId].transformSpecies; + return gMonBackPicCoords[species].y_offset; + } + else + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); + else + species = spriteInfo[battlerId].transformSpecies; + return gMonFrontPicCoords[species].y_offset; + } + } + } + return 64; +} + +void StorePointerInVars(s16 *lo, s16 *hi, const void *ptr) +{ + *lo = ((intptr_t)ptr) & 0xffff; + *hi = (((intptr_t)ptr) >> 16) & 0xffff; +} + +void *LoadPointerFromVars(s16 lo, s16 hi) +{ + return (void *)((u16)lo | ((u16)hi << 16)); +} + +void sub_80765D4(struct Task *task, u8 spriteId, s16 a3, s16 a4, s16 a5, s16 a6, u16 a7) +{ + task->data[8] = a7; + task->data[15] = spriteId; + task->data[9] = a3; + task->data[10] = a4; + task->data[13] = a5; + task->data[14] = a6; + task->data[11] = (a5 - a3) / a7; + task->data[12] = (a6 - a4) / a7; +} + +u8 sub_8076640(struct Task *task) +{ + if (!task->data[8]) + return 0; + if (--task->data[8] != 0) + { + task->data[9] += task->data[11]; + task->data[10] += task->data[12]; + } + else + { + task->data[9] = task->data[13]; + task->data[10] = task->data[14]; + } + SetSpriteRotScale(task->data[15], task->data[9], task->data[10], 0); + if (task->data[8]) + SetBattlerSpriteYOffsetFromYScale(task->data[15]); + else + gSprites[task->data[15]].pos2.y = 0; + return task->data[8]; +} + +void AnimTask_GetFrustrationPowerLevel(u8 taskId) +{ + u16 powerLevel; + + if (gAnimFriendship <= 30) + powerLevel = 0; + else if (gAnimFriendship <= 100) + powerLevel = 1; + else if (gAnimFriendship <= 200) + powerLevel = 2; + else + powerLevel = 3; + gBattleAnimArgs[7] = powerLevel; + DestroyAnimVisualTask(taskId); +} + +// not used +static void sub_80766EC(u8 priority) +{ + if (IsBattlerSpriteVisible(gBattleAnimTarget)) + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].oam.priority = priority; + if (IsBattlerSpriteVisible(gBattleAnimAttacker)) + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].oam.priority = priority; + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimTarget))) + gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimTarget)]].oam.priority = priority; + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)]].oam.priority = priority; +} + +void sub_80767F0(void) +{ + s32 i; + + for (i = 0; i < gBattlersCount; ++i) + { + if (IsBattlerSpriteVisible(i)) + { + gSprites[gBattlerSpriteIds[i]].subpriority = GetBattlerSpriteSubpriority(i); + gSprites[gBattlerSpriteIds[i]].oam.priority = 2; + } + } +} + +u8 GetBattlerSpriteSubpriority(u8 battlerId) +{ + u8 subpriority; + u8 position = GetBattlerPosition(battlerId); + + if (position == B_POSITION_PLAYER_LEFT) + subpriority = 30; + else if (position == B_POSITION_PLAYER_RIGHT) + subpriority = 20; + else if (position == B_POSITION_OPPONENT_LEFT) + subpriority = 40; + else + subpriority = 50; + return subpriority; +} + +u8 GetBattlerSpriteBGPriority(u8 battlerId) +{ + u8 position = GetBattlerPosition(battlerId); + + if (position == B_POSITION_PLAYER_LEFT || position == B_POSITION_OPPONENT_RIGHT) + return GetAnimBgAttribute(2, BG_ANIM_PRIORITY); + else + return GetAnimBgAttribute(1, BG_ANIM_PRIORITY); +} + +u8 GetBattlerSpriteBGPriorityRank(u8 battlerId) +{ + u8 position = GetBattlerPosition(battlerId); + + if (position == B_POSITION_PLAYER_LEFT || position == B_POSITION_OPPONENT_RIGHT) + return 2; + else + return 1; +} + +u8 sub_80768D0(u16 species, bool8 isBackpic, u8 a3, s16 x, s16 y, u8 subpriority, u32 personality, u32 trainerId, u32 battlerId, u32 a10) +{ + u8 spriteId; + u16 sheet = LoadSpriteSheet(&gUnknown_83AE084[a3]); + u16 palette = AllocSpritePalette(gUnknown_83AE054[a3].paletteTag); + + if (gMonSpritesGfxPtr != NULL && gMonSpritesGfxPtr->field_17C == NULL) + gMonSpritesGfxPtr->field_17C = AllocZeroed(0x2000); + if (!isBackpic) + { + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, trainerId, personality), (palette * 0x10) + 0x100, 0x20); + if (a10 == 1 || sub_804455C(5, battlerId) == 1 || gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != 0) + LoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], + gMonSpritesGfxPtr->field_17C, + species, + personality, + TRUE); + else + LoadSpecialPokePic(&gMonFrontPicTable[species], + gMonSpritesGfxPtr->field_17C, + species, + personality, + TRUE); + } + else + { + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, trainerId, personality), (palette * 0x10) + 0x100, 0x20); + if (a10 == 1 || sub_804455C(5, battlerId) == 1 || gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies != 0) + LoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[species], + gMonSpritesGfxPtr->field_17C, + species, + personality, + FALSE); + else + LoadSpecialPokePic(&gMonBackPicTable[species], + gMonSpritesGfxPtr->field_17C, + species, + personality, + FALSE); + } + RequestDma3Copy(gMonSpritesGfxPtr->field_17C, (void *)(OBJ_VRAM0 + (sheet * 0x20)), 0x800, 1); + FREE_AND_SET_NULL(gMonSpritesGfxPtr->field_17C); + if (!isBackpic) + spriteId = CreateSprite(&gUnknown_83AE054[a3], x, y + gMonFrontPicCoords[species].y_offset, subpriority); + else + spriteId = CreateSprite(&gUnknown_83AE054[a3], x, y + gMonBackPicCoords[species].y_offset, subpriority); + return spriteId; +} + +void DestroySpriteAndFreeResources_(struct Sprite *sprite) +{ + DestroySpriteAndFreeResources(sprite); +} + +s16 GetBattlerSpriteCoordAttr(u8 battlerId, u8 attr) +{ + u16 species; + u32 personality; + u16 letter; + u16 unownSpecies; + s32 ret; + const struct MonCoords *coords; + struct BattleSpriteInfo *spriteInfo; + + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + { + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY); + } + else + { + species = spriteInfo[battlerId].transformSpecies; + personality = gTransformedPersonalities[battlerId]; + } + if (species == SPECIES_UNOWN) + { + letter = GET_UNOWN_LETTER(personality); + if (!letter) + unownSpecies = SPECIES_UNOWN; + else + unownSpecies = letter + SPECIES_UNOWN_B - 1; + coords = &gMonBackPicCoords[unownSpecies]; + } + else if (species > NUM_SPECIES) + { + coords = &gMonBackPicCoords[0]; + } + else + { + coords = &gMonBackPicCoords[species]; + } + } + else + { + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + { + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY); + } + else + { + species = spriteInfo[battlerId].transformSpecies; + personality = gTransformedPersonalities[battlerId]; + } + + if (species == SPECIES_UNOWN) + { + letter = GET_UNOWN_LETTER(personality); + if (!letter) + unownSpecies = SPECIES_UNOWN; + else + unownSpecies = letter + SPECIES_UNOWN_B - 1; + coords = &gMonFrontPicCoords[unownSpecies]; + } + else if (species == SPECIES_CASTFORM) + { + coords = &gCastformFrontSpriteCoords[gBattleMonForms[battlerId]]; + } + else if (species > NUM_SPECIES) + { + coords = &gMonFrontPicCoords[0]; + } + else + { + coords = &gMonFrontPicCoords[species]; + } + } + switch (attr) + { + case BATTLER_COORD_ATTR_HEIGHT: + return (coords->size & 0xf) * 8; + case BATTLER_COORD_ATTR_WIDTH: + return (coords->size >> 4) * 8; + case BATTLER_COORD_ATTR_LEFT: + return GetBattlerSpriteCoord(battlerId, BATTLER_COORD_X_2) - ((coords->size >> 4) * 4); + case BATTLER_COORD_ATTR_RIGHT: + return GetBattlerSpriteCoord(battlerId, BATTLER_COORD_X_2) + ((coords->size >> 4) * 4); + case BATTLER_COORD_ATTR_TOP: + return GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y_PIC_OFFSET) - ((coords->size & 0xf) * 4); + case BATTLER_COORD_ATTR_BOTTOM: + return GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y_PIC_OFFSET) + ((coords->size & 0xf) * 4); + case BATTLER_COORD_ATTR_RAW_BOTTOM: + ret = GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y) + 31; + return ret - coords->y_offset; + default: + return 0; + } +} + +void SetAverageBattlerPositions(u8 battlerId, bool8 respectMonPicOffsets, s16 *x, s16 *y) +{ + u8 xCoordType, yCoordType; + s16 battlerX, battlerY; + s16 partnerX, partnerY; + + if (!respectMonPicOffsets) + { + xCoordType = BATTLER_COORD_X; + yCoordType = BATTLER_COORD_Y; + } + else + { + xCoordType = BATTLER_COORD_X_2; + yCoordType = BATTLER_COORD_Y_PIC_OFFSET; + } + battlerX = GetBattlerSpriteCoord(battlerId, xCoordType); + battlerY = GetBattlerSpriteCoord(battlerId, yCoordType); + if (IsDoubleBattle()) + { + partnerX = GetBattlerSpriteCoord(BATTLE_PARTNER(battlerId), xCoordType); + partnerY = GetBattlerSpriteCoord(BATTLE_PARTNER(battlerId), yCoordType); + } + else + { + partnerX = battlerX; + partnerY = battlerY; + } + *x = (battlerX + partnerX) / 2; + *y = (battlerY + partnerY) / 2; +} + +u8 sub_8076E34(s32 battlerId, u8 spriteId, s32 species) +{ + u8 newSpriteId = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy); + + gSprites[newSpriteId] = gSprites[spriteId]; + gSprites[newSpriteId].usingSheet = TRUE; + gSprites[newSpriteId].oam.priority = 0; + gSprites[newSpriteId].oam.objMode = 2; + gSprites[newSpriteId].oam.tileNum = gSprites[spriteId].oam.tileNum; + gSprites[newSpriteId].callback = SpriteCallbackDummy; + return newSpriteId; +} + +void sub_8076ED8(struct Sprite *sprite) +{ + SetSpriteCoordsToAnimAttackerCoords(sprite); + if (GetBattlerSide(gBattleAnimAttacker)) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + sprite->hFlip = TRUE; + } + 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]; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = TranslateSpriteLinearAndFlicker; +} + +void sub_8076F58(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + gBattleAnimArgs[3] *= -1; + } + 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]; + StartSpriteAnim(sprite, gBattleAnimArgs[6]); + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = TranslateSpriteLinearAndFlicker; +} + +void sub_8076FD0(struct Sprite *sprite) +{ + SetSpriteCoordsToAnimAttackerCoords(sprite); + if (GetBattlerSide(gBattleAnimAttacker)) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->callback = RunStoredCallbackWhenAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +void sub_8077030(u8 taskId) +{ + u16 src; + u16 dest; + struct Task *task = &gTasks[taskId]; + + task->data[0] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[1] = ((GetBattlerSide(gBattleAnimAttacker)) != B_SIDE_PLAYER) ? -8 : 8; + task->data[2] = 0; + task->data[3] = 0; + gSprites[task->data[0]].pos2.x -= task->data[0]; + task->data[4] = AllocSpritePalette(10097); + task->data[5] = 0; + dest = (task->data[4] + 0x10) * 0x10; + src = (gSprites[task->data[0]].oam.paletteNum + 0x10) * 0x10; + task->data[6] = GetBattlerSpriteSubpriority(gBattleAnimAttacker); + if (task->data[6] == 20 || task->data[6] == 40) + task->data[6] = 2; + else + task->data[6] = 3; + CpuCopy32(&gPlttBufferUnfaded[src], &gPlttBufferFaded[dest], 0x20); + BlendPalette(dest, 16, gBattleAnimArgs[1], gBattleAnimArgs[0]); + task->func = sub_8077118; +} + +static void sub_8077118(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + switch (task->data[2]) + { + case 0: + sub_80771E4(task, taskId); + gSprites[task->data[0]].pos2.x += task->data[1]; + if (++task->data[3] == 5) + { + --task->data[3]; + ++task->data[2]; + } + break; + case 1: + sub_80771E4(task, taskId); + gSprites[task->data[0]].pos2.x -= task->data[1]; + if (--task->data[3] == 0) + { + gSprites[task->data[0]].pos2.x = 0; + ++task->data[2]; + } + break; + case 2: + if (!task->data[5]) + { + FreeSpritePaletteByTag(ANIM_TAG_BENT_SPOON); + DestroyAnimVisualTask(taskId); + } + break; + } +} + +static void sub_80771E4(struct Task *task, u8 taskId) +{ + s16 spriteId = CloneBattlerSpriteWithBlend(0); + if (spriteId >= 0) + { + gSprites[spriteId].oam.priority = task->data[6]; + gSprites[spriteId].oam.paletteNum = task->data[4]; + gSprites[spriteId].data[0] = 8; + gSprites[spriteId].data[1] = taskId; + gSprites[spriteId].data[2] = spriteId; + gSprites[spriteId].pos2.x = gSprites[task->data[0]].pos2.x; + gSprites[spriteId].callback = sub_8077268; + ++task->data[5]; + } +} + +static void sub_8077268(struct Sprite *sprite) +{ + if (--sprite->data[0] == 0) + { + --gTasks[sprite->data[1]].data[5]; + obj_delete_but_dont_free_vram(sprite); + } +} + +void sub_807729C(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)) + sprite->data[0] = 5; + else + sprite->data[0] = -10; + sprite->data[1] = -40; + sprite->callback = sub_80772F4; +} + +static void sub_80772F4(struct Sprite *sprite) +{ + sprite->data[2] += sprite->data[0]; + sprite->data[3] += sprite->data[1]; + sprite->pos2.x = sprite->data[2] / 10; + sprite->pos2.y = sprite->data[3] / 10; + if (sprite->data[1] < -20) + ++sprite->data[1]; + if (sprite->pos1.y + sprite->pos2.y < -32) + DestroyAnimSprite(sprite); +} + +void sub_8077350(struct Sprite *sprite) +{ + s32 x; + + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[4]; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[5]; + if (!GetBattlerSide(gBattleAnimTarget)) + { + x = (u16)gBattleAnimArgs[4] + 30; + sprite->pos1.x += x; + sprite->pos1.y = gBattleAnimArgs[5] - 20; + } + else + { + x = (u16)gBattleAnimArgs[4] - 30; + sprite->pos1.x += x; + sprite->pos1.y = gBattleAnimArgs[5] - 80; + } + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} diff --git a/src/battle_anim_sound_tasks.c b/src/battle_anim_sound_tasks.c new file mode 100644 index 000000000..e67c91bfa --- /dev/null +++ b/src/battle_anim_sound_tasks.c @@ -0,0 +1,313 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "sound.h" +#include "task.h" +#include "constants/battle_anim.h" +#include "constants/species.h" + +static void sub_80DCE78(u8 taskId); +static void sub_80DCEE4(u8 taskId); +static void sub_80DCFE8(u8 taskId); +static void sub_80DD270(u8 taskId); +static void sub_80DD390(u8 taskId); +static void sub_80DD4D4(u8 taskId); + +void sub_80DCE10(u8 taskId) +{ + s8 pan1, pan2, panIncrement; + + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gTasks[taskId].data[1] = gBattleAnimArgs[1]; + pan1 = BattleAnimAdjustPanning(SOUND_PAN_ATTACKER); + pan2 = BattleAnimAdjustPanning(SOUND_PAN_TARGET); + panIncrement = CalculatePanIncrement(pan1, pan2, 2); + gTasks[taskId].data[2] = pan1; + gTasks[taskId].data[3] = pan2; + gTasks[taskId].data[4] = panIncrement; + gTasks[taskId].data[10] = 10; + gTasks[taskId].func = sub_80DCE78; +} + +static void sub_80DCE78(u8 taskId) +{ + s16 pan = gTasks[taskId].data[2]; + s8 panIncrement = gTasks[taskId].data[4]; + + if (++gTasks[taskId].data[11] == 111) + { + gTasks[taskId].data[10] = 5; + gTasks[taskId].data[11] = 0; + gTasks[taskId].func = sub_80DCEE4; + } + else + { + if (++gTasks[taskId].data[10] == 11) + { + gTasks[taskId].data[10] = 0; + PlaySE12WithPanning(gTasks[taskId].data[0], pan); + } + pan += panIncrement; + gTasks[taskId].data[2] = KeepPanInRange(pan, panIncrement); + } +} + +static void sub_80DCEE4(u8 taskId) +{ + if (++gTasks[taskId].data[10] == 6) + { + s8 pan; + + gTasks[taskId].data[10] = 0; + pan = BattleAnimAdjustPanning(SOUND_PAN_TARGET); + PlaySE12WithPanning(gTasks[taskId].data[1], pan); + if (++gTasks[taskId].data[11] == 2) + DestroyAnimSoundTask(taskId); + } +} + +void mas_80DCF38(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 targetPan = gBattleAnimArgs[2]; + s8 panIncrement = gBattleAnimArgs[3]; + u8 r10 = gBattleAnimArgs[4]; + u8 r7 = gBattleAnimArgs[5]; + u8 r9 = gBattleAnimArgs[6]; + s8 sourcePan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + targetPan = BattleAnimAdjustPanning(targetPan); + panIncrement = CalculatePanIncrement(sourcePan, targetPan, panIncrement); + gTasks[taskId].data[0] = songId; + gTasks[taskId].data[1] = sourcePan; + gTasks[taskId].data[2] = targetPan; + gTasks[taskId].data[3] = panIncrement; + gTasks[taskId].data[4] = r10; + gTasks[taskId].data[5] = r7; + gTasks[taskId].data[6] = r9; + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] = sourcePan; + gTasks[taskId].data[12] = r9; + gTasks[taskId].func = sub_80DCFE8; + sub_80DCFE8(taskId); +} + +static void sub_80DCFE8(u8 taskId) +{ + if (gTasks[taskId].data[12]++ == gTasks[taskId].data[6]) + { + gTasks[taskId].data[12] = 0; + PlaySE12WithPanning(gTasks[taskId].data[0], gTasks[taskId].data[11]); + if (--gTasks[taskId].data[4] == 0) + { + DestroyAnimSoundTask(taskId); + return; + } + } + if (gTasks[taskId].data[10]++ == gTasks[taskId].data[5]) + { + u16 dPan, oldPan; + + gTasks[taskId].data[10] = 0; + dPan = gTasks[taskId].data[3]; + oldPan = gTasks[taskId].data[11] ; + gTasks[taskId].data[11] = dPan + oldPan; + gTasks[taskId].data[11] = KeepPanInRange(gTasks[taskId].data[11], oldPan); + } +} + +void sub_80DD06C(u8 taskId) +{ + u16 species = SPECIES_NONE; + u8 battlerId; + s8 pan = BattleAnimAdjustPanning(SOUND_PAN_ATTACKER); + + // Get wanted battler. + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + battlerId = gBattleAnimAttacker; + else if (gBattleAnimArgs[0] == ANIM_TARGET) + battlerId = gBattleAnimTarget; + else if (gBattleAnimArgs[0] == ANIM_ATK_PARTNER) + battlerId = BATTLE_PARTNER(gBattleAnimAttacker); + else + battlerId = BATTLE_PARTNER(gBattleAnimTarget); + // Check if battler is visible. + if ((gBattleAnimArgs[0] == ANIM_TARGET || gBattleAnimArgs[0] == ANIM_DEF_PARTNER) + && !IsBattlerSpriteVisible(battlerId)) + { + DestroyAnimVisualTask(taskId); + return; + } + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + if (species != SPECIES_NONE) + PlayCry3(species, pan, 3); + DestroyAnimVisualTask(taskId); +} + +void sub_80DD148(u8 taskId) +{ + u16 species = SPECIES_NONE; + u8 battlerId; + s8 pan = BattleAnimAdjustPanning(SOUND_PAN_ATTACKER); + + // Get wanted battler. + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + battlerId = gBattleAnimAttacker; + else if (gBattleAnimArgs[0] == ANIM_TARGET) + battlerId = gBattleAnimTarget; + else if (gBattleAnimArgs[0] == ANIM_ATK_PARTNER) + battlerId = BATTLE_PARTNER(gBattleAnimAttacker); + else + battlerId = BATTLE_PARTNER(gBattleAnimTarget); + // Check if battler is visible. + if ((gBattleAnimArgs[0] == ANIM_TARGET || gBattleAnimArgs[0] == ANIM_DEF_PARTNER) + && !IsBattlerSpriteVisible(battlerId)) + { + DestroyAnimVisualTask(taskId); + return; + } + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gTasks[taskId].data[0] = gBattleAnimArgs[1]; + gTasks[taskId].data[1] = species; + gTasks[taskId].data[2] = pan; + if (species != SPECIES_NONE) + { + if (gBattleAnimArgs[1] == TASK_NONE) + PlayCry3(species, pan, 9); + else + PlayCry3(species, pan, 7); + gTasks[taskId].func = sub_80DD270; + } + else + { + DestroyAnimVisualTask(taskId); + } +} + +static void sub_80DD270(u8 taskId) +{ + u16 species = gTasks[taskId].data[1]; + s8 pan = gTasks[taskId].data[2]; + + if (gTasks[taskId].data[9] < 2) + { + ++gTasks[taskId].data[9]; + } + else if (gTasks[taskId].data[0] == TASK_NONE) + { + if (!IsCryPlaying()) + { + PlayCry3(species, pan, 10); + DestroyAnimVisualTask(taskId); + } + } + else if (!IsCryPlaying()) + { + PlayCry3(species, pan, 8); + DestroyAnimVisualTask(taskId); + } +} + +void sub_80DD2F4(u8 taskId) +{ + if (gTasks[taskId].data[9] < 2) + ++gTasks[taskId].data[9]; + else if (!IsCryPlaying()) + DestroyAnimVisualTask(taskId); +} + +void sub_80DD334(u8 taskId) +{ + u16 species; + s8 pan; + + pan = BattleAnimAdjustPanning(SOUND_PAN_ATTACKER); + species = gAnimBattlerSpecies[gBattleAnimAttacker]; + gTasks[taskId].data[1] = species; + gTasks[taskId].data[2] = pan; + if (species != SPECIES_NONE) + { + PlayCry3(species, pan, 4); + gTasks[taskId].func = sub_80DD390; + } + else + { + DestroyAnimVisualTask(taskId); + } +} + +static void sub_80DD390(u8 taskId) +{ + + if (gTasks[taskId].data[9] < 2) + { + ++gTasks[taskId].data[9]; + } + else if (!IsCryPlaying()) + { + u16 species = gTasks[taskId].data[1]; + s8 pan = gTasks[taskId].data[2]; + + PlayCry3(species, pan, 6); + DestroyAnimVisualTask(taskId); + } +} + +void sub_80DD3DC(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 pan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + PlaySE1WithPanning(songId, pan); + DestroyAnimVisualTask(taskId); +} + +void sub_80DD410(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 pan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + PlaySE2WithPanning(songId, pan); + DestroyAnimVisualTask(taskId); +} + +void sub_80DD444(u8 taskId) +{ + s8 targetPan = gBattleAnimArgs[1]; + s8 panIncrement = gBattleAnimArgs[2]; + u16 r9 = gBattleAnimArgs[3]; + s8 sourcePan = BattleAnimAdjustPanning(gBattleAnimArgs[0]); + + targetPan = BattleAnimAdjustPanning(targetPan); + panIncrement = CalculatePanIncrement(sourcePan, targetPan, panIncrement); + gTasks[taskId].data[1] = sourcePan; + gTasks[taskId].data[2] = targetPan; + gTasks[taskId].data[3] = panIncrement; + gTasks[taskId].data[5] = r9; + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] = sourcePan; + gTasks[taskId].func = sub_80DD4D4; + sub_80DD4D4(taskId); +} + +static void sub_80DD4D4(u8 taskId) +{ + u16 oldPan, panIncrement = gTasks[taskId].data[3]; + + if (gTasks[taskId].data[10]++ == gTasks[taskId].data[5]) + { + gTasks[taskId].data[10] = 0; + oldPan = gTasks[taskId].data[11]; + gTasks[taskId].data[11] = panIncrement + oldPan; + gTasks[taskId].data[11] = KeepPanInRange(gTasks[taskId].data[11], oldPan); + } + gUnknown_2037F24 = gTasks[taskId].data[11]; + if (gTasks[taskId].data[11] == gTasks[taskId].data[2]) + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_anim_utility_funcs.c b/src/battle_anim_utility_funcs.c new file mode 100644 index 000000000..14c5ef6c8 --- /dev/null +++ b/src/battle_anim_utility_funcs.c @@ -0,0 +1,946 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "malloc.h" +#include "palette.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "util.h" +#include "constants/songs.h" + +struct AnimStatsChangeData +{ + u8 battler1; + u8 battler2; + u8 higherPriority; + s16 data[8]; + u16 species; +}; + +static void StartBlendAnimSpriteColor(u8 taskId, u32 selectedPalettes); +static void AnimTask_BlendSpriteColor_Step2(u8 taskId); +static void sub_80BAB78(u8 taskId); +static void sub_80BABD0(u8 taskId); +static void sub_80BACA8(struct Sprite *sprite); +static void sub_80BAF38(u8 taskId); +static void sub_80BB0D8(u8 taskId); +static void sub_80BB2A0(u8 taskId); +static void sub_80BB4B8(u8 taskId); +static void sub_80BB6CC(u8 taskId); +static void sub_80BB790(u32 selectedPalettes, u16 color); +static void sub_80BB8A4(u8 taskId); +static void sub_80BBC2C(u8 taskId); +static void sub_80BC19C(u8 taskId); + +static EWRAM_DATA struct AnimStatsChangeData *sAnimStatsChangeData = NULL; + +static const u16 gUnknown_83E7CC8[] = { RGB(31, 31, 31) }; +const u8 gUnknown_83E7CCA[] = { REG_OFFSET_BG0CNT, REG_OFFSET_BG1CNT, REG_OFFSET_BG2CNT, REG_OFFSET_BG3CNT }; +const u8 gUnknown_83E7CCE[] = { REG_OFFSET_BG0CNT, REG_OFFSET_BG1CNT, REG_OFFSET_BG2CNT, REG_OFFSET_BG3CNT }; + +void sub_80BA7F8(u8 taskId) +{ + u32 selectedPalettes = UnpackSelectedBattleAnimPalettes(gBattleAnimArgs[0]); + + selectedPalettes |= sub_8075CB8((gBattleAnimArgs[0] >> 7) & 1, + (gBattleAnimArgs[0] >> 8) & 1, + (gBattleAnimArgs[0] >> 9) & 1, + (gBattleAnimArgs[0] >> 10) & 1); + StartBlendAnimSpriteColor(taskId, selectedPalettes); +} + +void sub_80BA83C(u8 taskId) +{ + u8 battler; + u32 selectedPalettes; + u8 animBattlers[2]; + + animBattlers[1] = 0xFF; + selectedPalettes = UnpackSelectedBattleAnimPalettes(1); + switch (gBattleAnimArgs[0]) + { + case 2: + selectedPalettes = 0; + // fall through + case 0: + animBattlers[0] = gBattleAnimAttacker; + break; + case 3: + selectedPalettes = 0; + // fall through + case 1: + animBattlers[0] = gBattleAnimTarget; + break; + case 4: + animBattlers[0] = gBattleAnimAttacker; + animBattlers[1] = gBattleAnimTarget; + break; + case 5: + animBattlers[0] = 0xFF; + break; + case 6: + selectedPalettes = 0; + animBattlers[0] = BATTLE_PARTNER(gBattleAnimAttacker); + break; + case 7: + selectedPalettes = 0; + animBattlers[0] = BATTLE_PARTNER(gBattleAnimTarget); + break; + } + for (battler = 0; battler < MAX_BATTLERS_COUNT; ++battler) + { + if (battler != animBattlers[0] + && battler != animBattlers[1] + && IsBattlerSpriteVisible(battler)) + selectedPalettes |= 0x10000 << sub_8075D80(battler); + } + StartBlendAnimSpriteColor(taskId, selectedPalettes); +} + +void AnimTask_SetCamouflageBlend(u8 taskId) +{ + u32 selectedPalettes = UnpackSelectedBattleAnimPalettes(gBattleAnimArgs[0]); + + switch (gBattleTerrain) + { + case BATTLE_TERRAIN_GRASS: + gBattleAnimArgs[4] = RGB(12, 24, 2); + break; + case BATTLE_TERRAIN_LONG_GRASS: + gBattleAnimArgs[4] = RGB(0, 15, 2); + break; + case BATTLE_TERRAIN_SAND: + gBattleAnimArgs[4] = RGB(30, 24, 11); + break; + case BATTLE_TERRAIN_UNDERWATER: + gBattleAnimArgs[4] = RGB(0, 0, 18); + break; + case BATTLE_TERRAIN_WATER: + gBattleAnimArgs[4] = RGB(11, 22, 31); + break; + case BATTLE_TERRAIN_POND: + gBattleAnimArgs[4] = RGB(11, 22, 31); + break; + case BATTLE_TERRAIN_MOUNTAIN: + gBattleAnimArgs[4] = RGB(22, 16, 10); + break; + case BATTLE_TERRAIN_CAVE: + gBattleAnimArgs[4] = RGB(14, 9, 3); + break; + case BATTLE_TERRAIN_BUILDING: + gBattleAnimArgs[4] = RGB(31, 31, 31); + break; + case BATTLE_TERRAIN_PLAIN: + gBattleAnimArgs[4] = RGB(31, 31, 31); + break; + } + StartBlendAnimSpriteColor(taskId, selectedPalettes); +} + +void AnimTask_BlendParticle(u8 taskId) +{ + u8 paletteIndex = IndexOfSpritePaletteTag(gBattleAnimArgs[0]); + u32 selectedPalettes = 1 << (paletteIndex + 16); + + StartBlendAnimSpriteColor(taskId, selectedPalettes); +} + +static void StartBlendAnimSpriteColor(u8 taskId, u32 selectedPalettes) +{ + gTasks[taskId].data[0] = selectedPalettes; + gTasks[taskId].data[1] = selectedPalettes >> 16; + gTasks[taskId].data[2] = gBattleAnimArgs[1]; + gTasks[taskId].data[3] = gBattleAnimArgs[2]; + gTasks[taskId].data[4] = gBattleAnimArgs[3]; + gTasks[taskId].data[5] = gBattleAnimArgs[4]; + gTasks[taskId].data[10] = gBattleAnimArgs[2]; + gTasks[taskId].func = AnimTask_BlendSpriteColor_Step2; + gTasks[taskId].func(taskId); +} + +static void AnimTask_BlendSpriteColor_Step2(u8 taskId) +{ + u32 selectedPalettes; + u16 singlePaletteMask = 0; + + if (gTasks[taskId].data[9] == gTasks[taskId].data[2]) + { + gTasks[taskId].data[9] = 0; + selectedPalettes = gTasks[taskId].data[0] | (gTasks[taskId].data[1] << 16); + while (selectedPalettes) + { + if (selectedPalettes & 1) + BlendPalette(singlePaletteMask, 16, gTasks[taskId].data[10], gTasks[taskId].data[5]); + singlePaletteMask += 0x10; + selectedPalettes >>= 1; + } + if (gTasks[taskId].data[10] < gTasks[taskId].data[4]) + ++gTasks[taskId].data[10]; + else if (gTasks[taskId].data[10] > gTasks[taskId].data[4]) + --gTasks[taskId].data[10]; + else + DestroyAnimVisualTask(taskId); + } + else + { + ++gTasks[taskId].data[9]; + } +} + +void sub_80BAB38(u8 taskId) +{ + BeginHardwarePaletteFade(gBattleAnimArgs[0], + gBattleAnimArgs[1], + gBattleAnimArgs[2], + gBattleAnimArgs[3], + gBattleAnimArgs[4]); + gTasks[taskId].func = sub_80BAB78; +} + +static void sub_80BAB78(u8 taskId) +{ + if (!gPaletteFade.active) + DestroyAnimVisualTask(taskId); +} + +void sub_80BAB98(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[0] = gBattleAnimArgs[0]; + task->data[1] = 0; + task->data[2] = gBattleAnimArgs[1]; + task->data[3] = gBattleAnimArgs[2]; + task->data[4] = gBattleAnimArgs[3]; + task->data[5] = 0; + task->func = sub_80BABD0; +} +static void sub_80BABD0(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (task->data[4]) + { + if (task->data[1]) + { + --task->data[1]; + } + else + { + task->data[6] = CloneBattlerSpriteWithBlend(task->data[0]); + if (task->data[6] >= 0) + { + gSprites[task->data[6]].oam.priority = task->data[0] ? 1 : 2; + gSprites[task->data[6]].data[0] = task->data[3]; + gSprites[task->data[6]].data[1] = taskId; + gSprites[task->data[6]].data[2] = 5; + gSprites[task->data[6]].callback = sub_80BACA8; + ++task->data[5]; + } + --task->data[4]; + task->data[1] = task->data[2]; + } + } + else if (task->data[5] == 0) + { + DestroyAnimVisualTask(taskId); + } +} + +static void sub_80BACA8(struct Sprite *sprite) +{ + if (sprite->data[0]) + { + --sprite->data[0]; + } + else + { + --gTasks[sprite->data[1]].data[sprite->data[2]]; + obj_delete_but_dont_free_vram(sprite); + } +} + +void sub_80BACEC(u8 taskId) +{ + u16 species; + s32 newSpriteId; + u16 var0; + u16 bg1Cnt; + u8 spriteId; + struct BattleAnimBgData animBgData; + + var0 = 0; + 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_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR + | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(8, 12)); + bg1Cnt = GetGpuReg(REG_OFFSET_BG1CNT); + ((struct BgCnt *)&bg1Cnt)->priority = 0; + ((struct BgCnt *)&bg1Cnt)->screenSize = 0; + SetGpuReg(REG_OFFSET_BG1CNT, bg1Cnt); + if (!IsContest()) + { + ((struct BgCnt *)&bg1Cnt)->charBaseBlock = 1; + SetGpuReg(REG_OFFSET_BG1CNT, bg1Cnt); + } + 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 -= 1; + ((struct BgCnt *)&bg1Cnt)->priority = 1; + SetGpuReg(REG_OFFSET_BG1CNT, bg1Cnt); + var0 = 1; + } + } + } + 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(0); + newSpriteId = sub_8076E34(gBattleAnimAttacker, spriteId, species); + sub_80752A0(&animBgData); + AnimLoadCompressedBgTilemap(animBgData.bgId, gFile_graphics_battle_anims_masks_curse_tilemap); + if (IsContest()) + sub_80730C0(animBgData.paletteId, animBgData.bgTilemap, 0, 0); + AnimLoadCompressedBgGfx(animBgData.bgId, gFile_graphics_battle_anims_masks_curse_sheet, animBgData.tilesOffset); + LoadPalette(gUnknown_83E7CC8, animBgData.paletteId * 16 + 1, 2); + gBattle_BG1_X = -gSprites[spriteId].pos1.x + 32; + gBattle_BG1_Y = -gSprites[spriteId].pos1.y + 32; + gTasks[taskId].data[0] = newSpriteId; + gTasks[taskId].data[6] = var0; + gTasks[taskId].func = sub_80BAF38; +} + +static void sub_80BAF38(u8 taskId) +{ + struct BattleAnimBgData animBgData; + struct Sprite *sprite; + u16 bg1Cnt; + + gTasks[taskId].data[10] += 4; + gBattle_BG1_Y -= 4; + if (gTasks[taskId].data[10] == 64) + { + gTasks[taskId].data[10] = 0; + gBattle_BG1_Y += 64; + if (++gTasks[taskId].data[11] == 4) + { + sub_8073128(0); + 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); + if (!IsContest()) + { + bg1Cnt = GetGpuReg(REG_OFFSET_BG1CNT); + ((struct BgCnt *)&bg1Cnt)->charBaseBlock = 0; + SetGpuReg(REG_OFFSET_BG1CNT, bg1Cnt); + } + SetGpuReg(REG_OFFSET_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) ^ DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + sprite = &gSprites[GetAnimBattlerSpriteId(0)]; // unused + sprite = &gSprites[gTasks[taskId].data[0]]; + DestroySprite(sprite); + sub_80752A0(&animBgData); + sub_8075358(animBgData.bgId); + if (gTasks[taskId].data[6] == 1) + ++gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattleAnimAttacker)]].oam.priority; + gBattle_BG1_Y = 0; + DestroyAnimVisualTask(taskId); + } + } +} + +void sub_80BB088(u8 taskId) +{ + u8 i; + + sAnimStatsChangeData = AllocZeroed(sizeof(struct AnimStatsChangeData)); + for (i = 0; i < 8; ++i) + sAnimStatsChangeData->data[i] = gBattleAnimArgs[i]; + gTasks[taskId].func = sub_80BB0D8; +} + +static void sub_80BB0D8(u8 taskId) +{ + if (sAnimStatsChangeData->data[2] == 0) + sAnimStatsChangeData->battler1 = gBattleAnimAttacker; + else + sAnimStatsChangeData->battler1 = gBattleAnimTarget; + sAnimStatsChangeData->battler2 = BATTLE_PARTNER(sAnimStatsChangeData->battler1); + if (IsContest() || (sAnimStatsChangeData->data[3] && !IsBattlerSpriteVisible(sAnimStatsChangeData->battler2))) + sAnimStatsChangeData->data[3] = 0; + 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_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR + | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON); + 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, 0); + SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); + if (IsDoubleBattle() && sAnimStatsChangeData->data[3] == 0) + { + if (GetBattlerPosition(sAnimStatsChangeData->battler1) == B_POSITION_OPPONENT_RIGHT + || GetBattlerPosition(sAnimStatsChangeData->battler1) == B_POSITION_PLAYER_LEFT) + { + if (IsBattlerSpriteVisible(sAnimStatsChangeData->battler2) == TRUE) + { + gSprites[gBattlerSpriteIds[sAnimStatsChangeData->battler2]].oam.priority -= 1; + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + sAnimStatsChangeData->higherPriority = 1; + } + } + } + if (GetBattlerSide(sAnimStatsChangeData->battler1) != B_SIDE_PLAYER) + sAnimStatsChangeData->species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[sAnimStatsChangeData->battler1]], MON_DATA_SPECIES); + else + sAnimStatsChangeData->species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[sAnimStatsChangeData->battler1]], MON_DATA_SPECIES); + gTasks[taskId].func = sub_80BB2A0; +} + +static void sub_80BB2A0(u8 taskId) +{ + struct BattleAnimBgData animBgData; + u8 spriteId, newSpriteId = 0; + u8 battlerSpriteId; + + battlerSpriteId = gBattlerSpriteIds[sAnimStatsChangeData->battler1]; + spriteId = sub_8076E34(sAnimStatsChangeData->battler1, battlerSpriteId, sAnimStatsChangeData->species); + if (sAnimStatsChangeData->data[3]) + { + battlerSpriteId = gBattlerSpriteIds[sAnimStatsChangeData->battler2]; + newSpriteId = sub_8076E34(sAnimStatsChangeData->battler2, battlerSpriteId, sAnimStatsChangeData->species); + } + sub_80752A0(&animBgData); + if (sAnimStatsChangeData->data[0] == 0) + AnimLoadCompressedBgTilemap(animBgData.bgId, gBattleStatMask1_Tilemap); + else + AnimLoadCompressedBgTilemap(animBgData.bgId, gBattleStatMask2_Tilemap); + if (IsContest()) + sub_80730C0(animBgData.paletteId, animBgData.bgTilemap, 0, 0); + AnimLoadCompressedBgGfx(animBgData.bgId, gBattleStatMask_Gfx, animBgData.tilesOffset); + switch (sAnimStatsChangeData->data[1]) + { + case 0: + LoadCompressedPalette(gBattleStatMask2_Pal, animBgData.paletteId * 16, 32); + break; + case 1: + LoadCompressedPalette(gBattleStatMask1_Pal, animBgData.paletteId * 16, 32); + break; + case 2: + LoadCompressedPalette(gBattleStatMask3_Pal, animBgData.paletteId * 16, 32); + break; + case 3: + LoadCompressedPalette(gBattleStatMask4_Pal, animBgData.paletteId * 16, 32); + break; + case 4: + LoadCompressedPalette(gBattleStatMask6_Pal, animBgData.paletteId * 16, 32); + break; + case 5: + LoadCompressedPalette(gBattleStatMask7_Pal, animBgData.paletteId * 16, 32); + break; + case 6: + LoadCompressedPalette(gBattleStatMask8_Pal, animBgData.paletteId * 16, 32); + break; + default: + LoadCompressedPalette(gBattleStatMask5_Pal, animBgData.paletteId * 16, 32); + break; + } + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + if (sAnimStatsChangeData->data[0] == 1) + { + gBattle_BG1_X = 64; + gTasks[taskId].data[1] = -3; + } + else + { + gTasks[taskId].data[1] = 3; + } + + if (sAnimStatsChangeData->data[4] == 0) + { + gTasks[taskId].data[4] = 10; + gTasks[taskId].data[5] = 20; + } + else + { + gTasks[taskId].data[4] = 13; + gTasks[taskId].data[5] = 30; + } + gTasks[taskId].data[0] = spriteId; + gTasks[taskId].data[2] = sAnimStatsChangeData->data[3]; + gTasks[taskId].data[3] = newSpriteId; + gTasks[taskId].data[6] = sAnimStatsChangeData->higherPriority; + gTasks[taskId].data[7] = gBattlerSpriteIds[sAnimStatsChangeData->battler2]; + gTasks[taskId].func = sub_80BB4B8; + if (sAnimStatsChangeData->data[0] == 0) + PlaySE12WithPanning(SE_W287, BattleAnimAdjustPanning2(PAN_SIDE_PLAYER)); + else + PlaySE12WithPanning(SE_W287B, BattleAnimAdjustPanning2(PAN_SIDE_PLAYER)); +} + +static void sub_80BB4B8(u8 taskId) +{ + gBattle_BG1_Y += gTasks[taskId].data[1]; + switch (gTasks[taskId].data[15]) + { + case 0: + if (gTasks[taskId].data[11]++ > 0) + { + gTasks[taskId].data[11] = 0; + ++gTasks[taskId].data[12]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[12], 16 - gTasks[taskId].data[12])); + if (gTasks[taskId].data[12] == gTasks[taskId].data[4]) + ++gTasks[taskId].data[15]; + } + break; + case 1: + if (++gTasks[taskId].data[10] == gTasks[taskId].data[5]) + ++gTasks[taskId].data[15]; + break; + case 2: + if (gTasks[taskId].data[11]++ > 0) + { + gTasks[taskId].data[11] = 0; + --gTasks[taskId].data[12]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[12], 16 - gTasks[taskId].data[12])); + if (gTasks[taskId].data[12] == 0) + { + sub_8073128(0); + ++gTasks[taskId].data[15]; + } + } + break; + case 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_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR + | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_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); + DestroySprite(&gSprites[gTasks[taskId].data[0]]); + if (gTasks[taskId].data[2]) + DestroySprite(&gSprites[gTasks[taskId].data[3]]); + if (gTasks[taskId].data[6] == 1) + ++gSprites[gTasks[taskId].data[7]].oam.priority; + Free(sAnimStatsChangeData); + sAnimStatsChangeData = NULL; + DestroyAnimVisualTask(taskId); + break; + } +} + +void sub_80BB660(u8 taskId) +{ + u32 selectedPalettes = sub_8075CB8(1, 1, 1, 1); + + sub_80BB790(selectedPalettes, 0); + gTasks[taskId].data[14] = selectedPalettes >> 16; + selectedPalettes = sub_8075BE8(1, 0, 0, 0, 0, 0, 0) & 0xFFFF; + sub_80BB790(selectedPalettes, 0xFFFF); + gTasks[taskId].data[15] = selectedPalettes; + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = 0; + gTasks[taskId].func = sub_80BB6CC; +} + +static void sub_80BB6CC(u8 taskId) +{ + u16 i; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + if (++task->data[1] > 6) + { + task->data[1] = 0; + task->data[2] = 16; + ++task->data[0]; + } + break; + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + --task->data[2]; + for (i = 0; i < 16; ++i) + { + if ((task->data[15] >> i) & 1) + { + u16 paletteOffset = i * 16; + BlendPalette(paletteOffset, 16, task->data[2], 0xFFFF); + } + + if ((task->data[14] >> i) & 1) + { + u16 paletteOffset = i * 16 + 0x100; + BlendPalette(paletteOffset, 16, task->data[2], 0); + } + } + + if (task->data[2] == 0) + ++task->data[0]; + } + break; + case 2: + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_80BB790(u32 selectedPalettes, u16 color) +{ + u16 i, curOffset, paletteOffset; + + for (i = 0; i < 32; selectedPalettes >>= 1, ++i) + if (selectedPalettes & 1) + for (curOffset = i * 16, paletteOffset = curOffset; curOffset < paletteOffset + 16; ++curOffset) + gPlttBufferFaded[curOffset] = color; +} + +void sub_80BB7DC(u8 taskId) +{ + s32 j; + u32 battler, selectedPalettes = 0; + + for (battler = 0; battler < MAX_BATTLERS_COUNT; ++battler) + if (gBattleAnimAttacker != battler) + selectedPalettes |= 1 << (battler + 16); + for (j = 5; j != 0; --j) + gBattleAnimArgs[j] = gBattleAnimArgs[j - 1]; + StartBlendAnimSpriteColor(taskId, selectedPalettes); +} + +void sub_80BB82C(u8 taskId) +{ + u8 newTaskId; + + sub_8075458(0); + newTaskId = CreateTask(sub_80BB8A4, 5); + if (gBattleAnimArgs[2] && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + } + gTasks[newTaskId].data[1] = gBattleAnimArgs[0]; + gTasks[newTaskId].data[2] = gBattleAnimArgs[1]; + gTasks[newTaskId].data[3] = gBattleAnimArgs[3]; + ++gTasks[newTaskId].data[0]; + DestroyAnimVisualTask(taskId); +} + +static void sub_80BB8A4(u8 taskId) +{ + gTasks[taskId].data[10] += gTasks[taskId].data[1]; + gTasks[taskId].data[11] += gTasks[taskId].data[2]; + gBattle_BG3_X += gTasks[taskId].data[10] >> 8; + gBattle_BG3_Y += gTasks[taskId].data[11] >> 8; + gTasks[taskId].data[10] &= 0xFF; + gTasks[taskId].data[11] &= 0xFF; + if (gBattleAnimArgs[7] == gTasks[taskId].data[3]) + { + gBattle_BG3_X = 0; + gBattle_BG3_Y = 0; + sub_8075458(1); + DestroyTask(taskId); + } +} + +void AnimTask_GetAttackerSide(u8 taskId) +{ + gBattleAnimArgs[7] = GetBattlerSide(gBattleAnimAttacker); + DestroyAnimVisualTask(taskId); +} + +void AnimTask_GetTargetSide(u8 taskId) +{ + gBattleAnimArgs[7] = GetBattlerSide(gBattleAnimTarget); + DestroyAnimVisualTask(taskId); +} + +void AnimTask_GetTargetIsAttackerPartner(u8 taskId) +{ + gBattleAnimArgs[7] = BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget; + DestroyAnimVisualTask(taskId); +} + +void sub_80BB9B0(u8 taskId) +{ + u16 battler; + + for (battler = 0; battler < MAX_BATTLERS_COUNT; ++battler) + if (battler != gBattleAnimAttacker && IsBattlerSpriteVisible(battler)) + gSprites[gBattlerSpriteIds[battler]].invisible = gBattleAnimArgs[0]; + DestroyAnimVisualTask(taskId); +} + +void sub_80BBA20(u8 taskId, s32 unused, u16 arg2, u8 battler1, u8 arg4, u8 arg5, u8 arg6, u8 arg7, const u32 *gfx, const u32 *tilemap, const u32 *palette) +{ + u16 species; + u8 spriteId, newSpriteId = 0; + u16 bg1Cnt; + struct BattleAnimBgData animBgData; + u8 battler2 = BATTLE_PARTNER(battler1); + + if (IsContest() || (arg4 && !IsBattlerSpriteVisible(battler2))) + arg4 = 0; + 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_BG0 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR + | WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR); + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT2_ALL | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + bg1Cnt = GetGpuReg(REG_OFFSET_BG1CNT); + ((vBgCnt *)&bg1Cnt)->priority = 0; + ((vBgCnt *)&bg1Cnt)->screenSize = 0; + ((vBgCnt *)&bg1Cnt)->areaOverflowMode = 1; + if (!IsContest()) + ((vBgCnt *)&bg1Cnt)->charBaseBlock = 1; + SetGpuReg(REG_OFFSET_BG1CNT, bg1Cnt); + if (GetBattlerSide(battler1) != B_SIDE_PLAYER) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler1]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler1]], MON_DATA_SPECIES); + spriteId = sub_8076E34(battler1, gBattlerSpriteIds[battler1], species); + if (arg4) + newSpriteId = sub_8076E34(battler2, gBattlerSpriteIds[battler2], species); + sub_80752A0(&animBgData); + AnimLoadCompressedBgTilemap(animBgData.bgId, tilemap); + if (IsContest()) + sub_80730C0(animBgData.paletteId, animBgData.bgTilemap, 0, 0); + AnimLoadCompressedBgGfx(animBgData.bgId, gfx, animBgData.tilesOffset); + LoadCompressedPalette(palette, animBgData.paletteId * 16, 32); + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + gTasks[taskId].data[1] = arg2; + gTasks[taskId].data[4] = arg5; + gTasks[taskId].data[5] = arg7; + gTasks[taskId].data[6] = arg6; + gTasks[taskId].data[0] = spriteId; + gTasks[taskId].data[2] = arg4; + gTasks[taskId].data[3] = newSpriteId; + gTasks[taskId].func = sub_80BBC2C; +} + +static void sub_80BBC2C(u8 taskId) +{ + gTasks[taskId].data[13] += gTasks[taskId].data[1] < 0 ? -gTasks[taskId].data[1] : gTasks[taskId].data[1]; + if (gTasks[taskId].data[1] < 0) + gBattle_BG1_Y -= gTasks[taskId].data[13] >> 8; + else + gBattle_BG1_Y += gTasks[taskId].data[13] >> 8; + gTasks[taskId].data[13] &= 0xFF; + switch (gTasks[taskId].data[15]) + { + case 0: + if (gTasks[taskId].data[11]++ >= gTasks[taskId].data[6]) + { + gTasks[taskId].data[11] = 0; + ++gTasks[taskId].data[12]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[12], 16 - gTasks[taskId].data[12])); + if (gTasks[taskId].data[12] == gTasks[taskId].data[4]) + ++gTasks[taskId].data[15]; + } + break; + case 1: + if (++gTasks[taskId].data[10] == gTasks[taskId].data[5]) + ++gTasks[taskId].data[15]; + break; + case 2: + if (gTasks[taskId].data[11]++ >= gTasks[taskId].data[6]) + { + gTasks[taskId].data[11] = 0; + --gTasks[taskId].data[12]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[12], 16 - gTasks[taskId].data[12])); + if (gTasks[taskId].data[12] == 0) + { + sub_8073128(0); + 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); + if (!IsContest()) + { + u16 bg1Cnt = GetGpuReg(REG_OFFSET_BG1CNT); + ((vBgCnt *)&bg1Cnt)->charBaseBlock = 0; + SetGpuReg(REG_OFFSET_BG1CNT, bg1Cnt); + } + SetGpuReg(REG_OFFSET_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) ^ DISPCNT_OBJWIN_ON); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroySprite(&gSprites[gTasks[taskId].data[0]]); + if (gTasks[taskId].data[2]) + DestroySprite(&gSprites[gTasks[taskId].data[3]]); + DestroyAnimVisualTask(taskId); + } + } + break; + } +} + +void AnimTask_GetBattleTerrain(u8 taskId) +{ + gBattleAnimArgs[0] = gBattleTerrain; + DestroyAnimVisualTask(taskId); +} + +void sub_80BBE10(u8 taskId) +{ + gMonSpritesGfxPtr->field_17C = AllocZeroed(0x2000); + DestroyAnimVisualTask(taskId); +} + +void sub_80BBE3C(u8 taskId) +{ + FREE_AND_SET_NULL(gMonSpritesGfxPtr->field_17C); + DestroyAnimVisualTask(taskId); +} + +void sub_80BBE6C(u8 taskId) +{ + u32 selectedPalettes; + s32 paletteIndex = 0; + + if (gBattleAnimArgs[0] == 0) + for (selectedPalettes = sub_8075BE8(1, 0, 0, 0, 0, 0, 0); + (selectedPalettes & 1) == 0; + ++paletteIndex) + selectedPalettes >>= 1; + else if (gBattleAnimArgs[0] == 1) + paletteIndex = gBattleAnimAttacker + 16; + else if (gBattleAnimArgs[0] == 2) + paletteIndex = gBattleAnimTarget + 16; + memcpy(&gMonSpritesGfxPtr->field_17C[gBattleAnimArgs[1] * 16], &gPlttBufferUnfaded[paletteIndex * 16], 32); + DestroyAnimVisualTask(taskId); +} + +void sub_80BBF08(u8 taskId) +{ + u32 selectedPalettes; + s32 paletteIndex = 0; + + if (gBattleAnimArgs[0] == 0) + for (selectedPalettes = sub_8075BE8(1, 0, 0, 0, 0, 0, 0); + (selectedPalettes & 1) == 0; + ++paletteIndex) + selectedPalettes >>= 1; + else if (gBattleAnimArgs[0] == 1) + paletteIndex = gBattleAnimAttacker + 16; + else if (gBattleAnimArgs[0] == 2) + paletteIndex = gBattleAnimTarget + 16; + memcpy(&gPlttBufferUnfaded[paletteIndex * 16], &gMonSpritesGfxPtr->field_17C[gBattleAnimArgs[1] * 16], 32); + DestroyAnimVisualTask(taskId); +} + +void sub_80BBFA4(u8 taskId) +{ + u32 selectedPalettes; + s32 paletteIndex = 0; + + if (gBattleAnimArgs[0] == 0) + for (selectedPalettes = sub_8075BE8(1, 0, 0, 0, 0, 0, 0); + (selectedPalettes & 1) == 0; + ++paletteIndex) + selectedPalettes >>= 1; + else if (gBattleAnimArgs[0] == 1) + paletteIndex = gBattleAnimAttacker + 16; + else if (gBattleAnimArgs[0] == 2) + paletteIndex = gBattleAnimTarget + 16; + memcpy(&gPlttBufferUnfaded[paletteIndex * 16], &gPlttBufferFaded[paletteIndex * 16], 32); + DestroyAnimVisualTask(taskId); +} + +void AnimTask_IsContest(u8 taskId) +{ + if (IsContest()) + gBattleAnimArgs[7] = 1; + else + gBattleAnimArgs[7] = 0; + DestroyAnimVisualTask(taskId); +} + +void sub_80BC060(u8 taskId) +{ + gBattleAnimAttacker = gBattlerTarget; + gBattleAnimTarget = gEffectBattler; + DestroyAnimVisualTask(taskId); +} + +void AnimTask_IsTargetSameSide(u8 taskId) +{ + if (GetBattlerSide(gBattleAnimAttacker) == GetBattlerSide(gBattleAnimTarget)) + gBattleAnimArgs[7] = 1; + else + gBattleAnimArgs[7] = 0; + DestroyAnimVisualTask(taskId); +} + +void sub_80BC0DC(u8 taskId) +{ + gBattleAnimTarget = gBattlerTarget; + DestroyAnimVisualTask(taskId); +} + +void sub_80BC0FC(u8 taskId) +{ + gBattleAnimAttacker = gBattlerAttacker; + gBattleAnimTarget = gEffectBattler; + DestroyAnimVisualTask(taskId); +} + +void sub_80BC12C(u8 taskId) +{ + if (IsContest()) + { + DestroyAnimVisualTask(taskId); + } + else + { + gTasks[taskId].data[0] = gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].invisible; + gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].invisible = 1; + gTasks[taskId].func = sub_80BC19C; + --gAnimVisualTaskCount; + } +} + +static void sub_80BC19C(u8 taskId) +{ + if (gBattleAnimArgs[7] == 0x1000) + { + gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].invisible = (u8)gTasks[taskId].data[0] & 1; + DestroyTask(taskId); + } +} diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 0d827c8db..a9bb5bc6e 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1191,7 +1191,7 @@ static void sub_80303A8(u8 taskId) { s16 *data = gTasks[taskId].data; u8 battlerId = tExpTask_battler; - u16 v5 = sub_80768B0(battlerId); + u16 v5 = GetBattlerSpriteBGPriorityRank(battlerId); bool32 v6 = ((v5 ^ BIT_SIDE)) != B_SIDE_PLAYER; struct Sprite *sprite = &gSprites[gBattlerSpriteIds[battlerId]]; @@ -1222,7 +1222,7 @@ static void sub_80303A8(u8 taskId) u32 battlerIdAlt = battlerId; bool32 v6Alt = v6; - sub_8072E48(battlerIdAlt, v6Alt); + MoveBattlerSpriteToBG(battlerIdAlt, v6Alt); } ++data[15]; break; diff --git a/src/battle_intro.c b/src/battle_intro.c new file mode 100644 index 000000000..93141f2ca --- /dev/null +++ b/src/battle_intro.c @@ -0,0 +1,495 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_setup.h" +#include "bg.h" +#include "gpu_regs.h" +#include "main.h" +#include "scanline_effect.h" +#include "task.h" +#include "trig.h" +#include "constants/trainers.h" + +static EWRAM_DATA u16 sBgCnt = 0; + +extern const u8 gUnknown_83E7CCA[]; +extern const u8 gUnknown_83E7CCE[]; + +static void BattleIntroSlide1(u8 taskId); +static void BattleIntroSlide2(u8 taskId); +static void BattleIntroSlide3(u8 taskId); +static void BattleIntroSlideLink(u8 taskId); + +static const TaskFunc sBattleIntroSlideFuncs[] = +{ + BattleIntroSlide1, // BATTLE_TERRAIN_GRASS + BattleIntroSlide1, // BATTLE_TERRAIN_LONG_GRASS + BattleIntroSlide2, // BATTLE_TERRAIN_SAND + BattleIntroSlide2, // BATTLE_TERRAIN_UNDERWATER + BattleIntroSlide2, // BATTLE_TERRAIN_WATER + BattleIntroSlide1, // BATTLE_TERRAIN_POND + BattleIntroSlide1, // BATTLE_TERRAIN_MOUNTAIN + BattleIntroSlide1, // BATTLE_TERRAIN_CAVE + BattleIntroSlide3, // BATTLE_TERRAIN_BUILDING + BattleIntroSlide3, // BATTLE_TERRAIN_PLAIN +}; + +void SetAnimBgAttribute(u8 bgId, u8 attributeId, u8 value) +{ + if (bgId < 4) + { + sBgCnt = GetGpuReg(gUnknown_83E7CCA[bgId]); + switch (attributeId) + { + case BG_ANIM_SCREEN_SIZE: + ((struct BgCnt *)&sBgCnt)->screenSize = value; + break; + case BG_ANIM_AREA_OVERFLOW_MODE: + ((struct BgCnt *)&sBgCnt)->areaOverflowMode = value; + break; + case BG_ANIM_MOSAIC: + ((struct BgCnt *)&sBgCnt)->mosaic = value; + break; + case BG_ANIM_CHAR_BASE_BLOCK: + ((struct BgCnt *)&sBgCnt)->charBaseBlock = value; + break; + case BG_ANIM_PRIORITY: + ((struct BgCnt *)&sBgCnt)->priority = value; + break; + case BG_ANIM_PALETTES_MODE: + ((struct BgCnt *)&sBgCnt)->palettes = value; + break; + case BG_ANIM_SCREEN_BASE_BLOCK: + ((struct BgCnt *)&sBgCnt)->screenBaseBlock = value; + break; + } + SetGpuReg(gUnknown_83E7CCA[bgId], sBgCnt); + } +} + +s32 GetAnimBgAttribute(u8 bgId, u8 attributeId) +{ + u16 bgCnt; + + if (bgId < 4) + { + bgCnt = GetGpuReg(gUnknown_83E7CCE[bgId]); + switch (attributeId) + { + case BG_ANIM_SCREEN_SIZE: + return ((struct BgCnt *)&bgCnt)->screenSize; + case BG_ANIM_AREA_OVERFLOW_MODE: + return ((struct BgCnt *)&bgCnt)->areaOverflowMode; + case BG_ANIM_MOSAIC: + return ((struct BgCnt *)&bgCnt)->mosaic; + case BG_ANIM_CHAR_BASE_BLOCK: + return ((struct BgCnt *)&bgCnt)->charBaseBlock; + case BG_ANIM_PRIORITY: + return ((struct BgCnt *)&bgCnt)->priority; + case BG_ANIM_PALETTES_MODE: + return ((struct BgCnt *)&bgCnt)->palettes; + case BG_ANIM_SCREEN_BASE_BLOCK: + return ((struct BgCnt *)&bgCnt)->screenBaseBlock; + } + } + return 0; +} + +void HandleIntroSlide(u8 terrain) +{ + u8 taskId; + + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + taskId = CreateTask(BattleIntroSlideLink, 0); + } + else if ((gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON) && gGameVersion != VERSION_RUBY) + { + terrain = BATTLE_TERRAIN_UNDERWATER; + taskId = CreateTask(BattleIntroSlide2, 0); + } + else + { + taskId = CreateTask(sBattleIntroSlideFuncs[terrain], 0); + } + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = terrain; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = 0; + gTasks[taskId].data[5] = 0; + gTasks[taskId].data[6] = 0; +} + +void sub_80BC41C(u8 taskId) +{ + DestroyTask(taskId); + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + gBattle_BG2_X = 0; + gBattle_BG2_Y = 0; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 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); +} + +static void BattleIntroSlide1(u8 taskId) +{ + s32 i; + + gBattle_BG1_X += 6; + switch (gTasks[taskId].data[0]) + { + case 0: + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gTasks[taskId].data[2] = 16; + ++gTasks[taskId].data[0]; + } + else + { + gTasks[taskId].data[2] = 1; + ++gTasks[taskId].data[0]; + } + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + ++gTasks[taskId].data[0]; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); + } + break; + case 2: + gBattle_WIN0V -= 0xFF; + if ((gBattle_WIN0V & 0xFF00) == 0x3000) + { + ++gTasks[taskId].data[0]; + gTasks[taskId].data[2] = 240; + gTasks[taskId].data[3] = 32; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if (gTasks[taskId].data[3]) + { + --gTasks[taskId].data[3]; + } + else + { + if (gTasks[taskId].data[1] == 1) + { + if (gBattle_BG1_Y != 0xFFB0) + gBattle_BG1_Y -= 2; + } + else if (gBattle_BG1_Y != 0xFFC8) + { + gBattle_BG1_Y -= 1; + } + } + if (gBattle_WIN0V & 0xFF00) + gBattle_WIN0V -= 0x3FC; + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + // Scanline settings have already been set in CB2_InitBattleInternal + for (i = 0; i < 80; ++i) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gTasks[taskId].data[2]; + while (i < 160) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i++] = -gTasks[taskId].data[2]; + if (!gTasks[taskId].data[2]) + { + gScanlineEffect.state = 3; + ++gTasks[taskId].data[0]; + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE); + SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 0); + SetBgAttribute(2, BG_ATTR_CHARBASEINDEX, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + } + break; + case 4: + sub_80BC41C(taskId); + break; + } +} + +static void BattleIntroSlide2(u8 taskId) +{ + s32 i; + + switch (gTasks[taskId].data[1]) + { + case 2: + case 4: + gBattle_BG1_X += 8; + break; + case 3: + gBattle_BG1_X += 6; + break; + } + if (gTasks[taskId].data[1] == 4) + { + gBattle_BG1_Y = Cos2(gTasks[taskId].data[6]) / 512 - 8; + if (gTasks[taskId].data[6] < 180) + gTasks[taskId].data[6] += 4; + else + gTasks[taskId].data[6] += 6; + if (gTasks[taskId].data[6] == 360) + gTasks[taskId].data[6] = 0; + } + switch (gTasks[taskId].data[0]) + { + case 0: + gTasks[taskId].data[4] = 16; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gTasks[taskId].data[2] = 16; + ++gTasks[taskId].data[0]; + } + else + { + gTasks[taskId].data[2] = 1; + ++gTasks[taskId].data[0]; + } + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + ++gTasks[taskId].data[0]; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); + } + break; + case 2: + gBattle_WIN0V -= 0xFF; + if ((gBattle_WIN0V & 0xFF00) == 0x3000) + { + ++gTasks[taskId].data[0]; + gTasks[taskId].data[2] = 240; + gTasks[taskId].data[3] = 32; + gTasks[taskId].data[5] = 1; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if (gTasks[taskId].data[3]) + { + if (--gTasks[taskId].data[3] == 0) + { + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(15, 0)); + SetGpuReg(REG_OFFSET_BLDY, 0); + } + } + else if ((gTasks[taskId].data[4] & 0x1F) && --gTasks[taskId].data[5] == 0) + { + gTasks[taskId].data[4] += 0xFF; + gTasks[taskId].data[5] = 4; + } + if (gBattle_WIN0V & 0xFF00) + gBattle_WIN0V -= 0x3FC; + + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + // Scanline settings have already been set in CB2_InitBattleInternal() + for (i = 0; i < 80; ++i) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gTasks[taskId].data[2]; + while (i < 160) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i++] = -gTasks[taskId].data[2]; + if (!gTasks[taskId].data[2]) + { + gScanlineEffect.state = 3; + ++gTasks[taskId].data[0]; + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE); + SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 0); + SetBgAttribute(2, BG_ATTR_CHARBASEINDEX, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + } + break; + case 4: + sub_80BC41C(taskId); + break; + } + if (gTasks[taskId].data[0] != 4) + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[4], 0)); +} + +static void BattleIntroSlide3(u8 taskId) +{ + s32 i; + + gBattle_BG1_X += 8; + switch (gTasks[taskId].data[0]) + { + case 0: + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(8, 8)); + SetGpuReg(REG_OFFSET_BLDY, 0); + gTasks[taskId].data[4] = BLDALPHA_BLEND(8, 8); + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gTasks[taskId].data[2] = 16; + ++gTasks[taskId].data[0]; + } + else + { + gTasks[taskId].data[2] = 1; + ++gTasks[taskId].data[0]; + } + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + ++gTasks[taskId].data[0]; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); + } + break; + case 2: + gBattle_WIN0V -= 0xFF; + if ((gBattle_WIN0V & 0xFF00) == 0x3000) + { + ++gTasks[taskId].data[0]; + gTasks[taskId].data[2] = 240; + gTasks[taskId].data[3] = 32; + gTasks[taskId].data[5] = 1; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if (gTasks[taskId].data[3]) + { + --gTasks[taskId].data[3]; + } + else if ((gTasks[taskId].data[4] & 0xF) && --gTasks[taskId].data[5] == 0) + { + gTasks[taskId].data[4] += 0xFF; + gTasks[taskId].data[5] = 6; + } + if (gBattle_WIN0V & 0xFF00) + gBattle_WIN0V -= 0x3FC; + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + // Scanline settings have already been set in CB2_InitBattleInternal() + for (i = 0; i < 80; ++i) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gTasks[taskId].data[2]; + while (i < 160) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i++] = -gTasks[taskId].data[2]; + if (!gTasks[taskId].data[2]) + { + gScanlineEffect.state = 3; + ++gTasks[taskId].data[0]; + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE); + SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 0); + SetBgAttribute(2, BG_ATTR_CHARBASEINDEX, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + } + break; + case 4: + sub_80BC41C(taskId); + break; + } + if (gTasks[taskId].data[0] != 4) + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[4], 0)); +} + +static void BattleIntroSlideLink(u8 taskId) +{ + s32 i; + + if (gTasks[taskId].data[0] > 1 && !gTasks[taskId].data[4]) + { + u16 var0 = gBattle_BG1_X & 0x8000; + + if (var0 || gBattle_BG1_X < 80) + { + gBattle_BG1_X += 3; + gBattle_BG2_X -= 3; + } + else + { + CpuFill32(0, (void *)BG_SCREEN_ADDR(28), BG_SCREEN_SIZE); + CpuFill32(0, (void *)BG_SCREEN_ADDR(30), BG_SCREEN_SIZE); + gTasks[taskId].data[4] = 1; + } + } + switch (gTasks[taskId].data[0]) + { + case 0: + gTasks[taskId].data[2] = 32; + ++gTasks[taskId].data[0]; + break; + case 1: + if (--gTasks[taskId].data[2] == 0) + { + ++gTasks[taskId].data[0]; + gSprites[gBattleStruct->linkBattleVsSpriteId_V].oam.objMode = ST_OAM_OBJ_WINDOW; + gSprites[gBattleStruct->linkBattleVsSpriteId_V].callback = sub_801182C; + gSprites[gBattleStruct->linkBattleVsSpriteId_S].oam.objMode = ST_OAM_OBJ_WINDOW; + gSprites[gBattleStruct->linkBattleVsSpriteId_S].callback = sub_801182C; + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); + SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WINOBJ_BG_ALL | WINOUT_WINOBJ_OBJ | WINOUT_WINOBJ_CLR | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2); + } + break; + case 2: + gBattle_WIN0V -= 0xFF; + if ((gBattle_WIN0V & 0xFF00) == 0x3000) + { + ++gTasks[taskId].data[0]; + gTasks[taskId].data[2] = 240; + gTasks[taskId].data[3] = 32; + gIntroSlideFlags &= ~1; + } + break; + case 3: + if (gBattle_WIN0V & 0xFF00) + gBattle_WIN0V -= 0x3FC; + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2] -= 2; + // Scanline settings have already been set in CB2_InitBattleInternal() + for (i = 0; i < 80; ++i) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gTasks[taskId].data[2]; + while (i < 160) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i++] = -gTasks[taskId].data[2]; + if (!gTasks[taskId].data[2]) + { + gScanlineEffect.state = 3; + ++gTasks[taskId].data[0]; + SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 0); + SetBgAttribute(2, BG_ATTR_CHARBASEINDEX, 0); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(28) | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_16COLOR | BGCNT_SCREENBASE(30) | BGCNT_TXT512x256); + } + break; + case 4: + sub_80BC41C(taskId); + break; + } +} + +void sub_80BCEF4(s32 bgId, u8 arg1, u8 arg2, u8 battlerPosition, u8 arg4, u8 *arg5, u16 *arg6, u16 tilesOffset) +{ + s32 i, j; + u8 battler = GetBattlerAtPosition(battlerPosition); + s32 offset = tilesOffset; + + CpuCopy16(gMonSpritesGfxPtr->sprites[battlerPosition] + BG_SCREEN_SIZE * gBattleMonForms[battler], arg5, BG_SCREEN_SIZE); + LoadBgTiles(bgId, arg5, 0x1000, tilesOffset); + for (i = arg2; i < arg2 + 8; ++i) + for (j = arg1; j < arg1 + 8; ++j) + arg6[i * 32 + j] = offset++ | (arg4 << 12); + LoadBgTilemap(bgId, arg6, BG_SCREEN_SIZE, 0); +} + +// not used +static void sub_80BCFCC(u8 arg0, u8 arg1, u8 battlerPosition, u8 arg3, u8 arg4, u16 arg5, u8 arg6, u8 arg7) +{ + s32 i, j, offset; + + DmaCopy16(3, gMonSpritesGfxPtr->sprites[battlerPosition] + BG_SCREEN_SIZE * arg3, (void *)BG_SCREEN_ADDR(0) + arg5, BG_SCREEN_SIZE); + offset = (arg5 >> 5) - (arg7 << 9); + for (i = arg1; i < arg1 + 8; ++i) + for (j = arg0; j < arg0 + 8; ++j) + *((u16 *)(BG_VRAM) + (i * 32) + (j + (arg6 << 10))) = offset++ | (arg4 << 12); +} diff --git a/src/battle_transition.c b/src/battle_transition.c index d391b3ed4..19d76fed1 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -857,14 +857,14 @@ static bool8 BT_Phase2BigPokeball_Init(struct Task *task) task->tEva = 0; task-> tTheta = 0; task-> tAmplitude = 0x4000; - sTransitionStructPtr->winIn = 0x3F; + sTransitionStructPtr->winIn = WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR; sTransitionStructPtr->winOut = 0; - sTransitionStructPtr->win0H = 240; - sTransitionStructPtr->win0V = 160; + sTransitionStructPtr->win0H = WIN_RANGE(0, 0xF0); + sTransitionStructPtr->win0V = WIN_RANGE(0, 0xA0); sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG0 | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ | BLDCNT_TGT2_BD; sTransitionStructPtr->bldAlpha = (task->tEvb << 8) | task->tEva; for (i = 0; i < 160; ++i) - gScanlineEffectRegBuffers[1][i] = 240; + gScanlineEffectRegBuffers[1][i] = 0xF0; SetVBlankCallback(VBCB_BT_Phase2BigPokeball1); BT_GetBg0TilemapAndTilesetBase(&tilemapAddr, &tilesetAddr); CpuFill16(0, tilemapAddr, 0x800); @@ -897,7 +897,7 @@ static bool8 BT_Phase2BigPokeball_UpdateWave1IncEva(struct Task *task) ++task->tEva; task->tInterval = 1; // Broken logic. This makes the condition always TRUE. } - sTransitionStructPtr->bldAlpha = (task->tEvb << 8) | task->tEva; + sTransitionStructPtr->bldAlpha = BLDALPHA_BLEND(task->tEva, task->tEvb); // Increment eva until it reaches 50% coeff if (task->tEva > 15) ++task->tState; @@ -1148,13 +1148,11 @@ static bool8 BT_Phase2ClockwiseBlackFade_Init(struct Task *task) BT_InitCtrlBlk(); ScanlineEffect_Clear(); sTransitionStructPtr->winIn = 0; - sTransitionStructPtr->winOut = 0x3F; - sTransitionStructPtr->win0H = 0xF0F1; - sTransitionStructPtr->win0V = 0x00A0; + sTransitionStructPtr->winOut = WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR; + sTransitionStructPtr->win0H = WIN_RANGE(0xF0, 0xF1); + sTransitionStructPtr->win0V = WIN_RANGE(0, 0xA0); for (i = 0; i < 160; ++i) - { - gScanlineEffectRegBuffers[1][i] = 0xF3F4; - } + gScanlineEffectRegBuffers[1][i] = WIN_RANGE(0xF3, 0xF4); SetVBlankCallback(VBCB_BT_Phase2ClockwiseBlackFade); sTransitionStructPtr->trEndPtX = 120; ++task->tState; @@ -1167,7 +1165,7 @@ static bool8 BT_Phase2ClockwiseBlackFade_Step1(struct Task *task) BT_DiagonalSegment_InitParams(sTransitionStructPtr->data, 120, 80, sTransitionStructPtr->trEndPtX, -1, 1, 1); do { - gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = (sTransitionStructPtr->trCurrentPtX + 1) | 0x7800; + gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = WIN_RANGE(0x78, sTransitionStructPtr->trCurrentPtX + 1); } while (!BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE)); @@ -1197,7 +1195,7 @@ static bool8 BT_Phase2ClockwiseBlackFade_Step2(struct Task *task) left = sTransitionStructPtr->trCurrentPtX; right = 240; } - gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = right | (left << 8); + gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = WIN_RANGE2(left, right); if (finished) break; finished = BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE); @@ -1211,7 +1209,7 @@ static bool8 BT_Phase2ClockwiseBlackFade_Step2(struct Task *task) else { while (sTransitionStructPtr->trCurrentPtY < sTransitionStructPtr->trEndPtY) - gScanlineEffectRegBuffers[0][++sTransitionStructPtr->trCurrentPtY] = right | (left << 8); + gScanlineEffectRegBuffers[0][++sTransitionStructPtr->trCurrentPtY] = WIN_RANGE2(left, right); } ++sTransitionStructPtr->vblankDma; return FALSE; @@ -1265,7 +1263,7 @@ static bool8 BT_Phase2ClockwiseBlackFade_Step4(struct Task *task) left = 120; right = sTransitionStructPtr->trCurrentPtX; } - win0H = right | (left << 8); + win0H = WIN_RANGE2(left, right); gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = win0H; if (finished) break; @@ -1280,7 +1278,7 @@ static bool8 BT_Phase2ClockwiseBlackFade_Step4(struct Task *task) else { while (sTransitionStructPtr->trCurrentPtY > sTransitionStructPtr->trEndPtY) - gScanlineEffectRegBuffers[0][--sTransitionStructPtr->trCurrentPtY] = right | (left << 8); + gScanlineEffectRegBuffers[0][--sTransitionStructPtr->trCurrentPtY] = WIN_RANGE2(left, right); } ++sTransitionStructPtr->vblankDma; return FALSE; @@ -1301,7 +1299,7 @@ static bool8 BT_Phase2ClockwiseBlackFade_Step5(struct Task *task) left = 0; right = 240; } - gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = right | (left << 8); + gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = WIN_RANGE2(left, right); } while (!BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE)); sTransitionStructPtr->trEndPtX += 32; @@ -1431,12 +1429,12 @@ static bool8 BT_Phase2BlackWaveToRight_Init(struct Task *task) BT_InitCtrlBlk(); ScanlineEffect_Clear(); - sTransitionStructPtr->winIn = 0x3F; + sTransitionStructPtr->winIn = WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR; sTransitionStructPtr->winOut = 0; - sTransitionStructPtr->win0H = 240; - sTransitionStructPtr->win0V = 160; + sTransitionStructPtr->win0H = WIN_RANGE(0, 0xF0); + sTransitionStructPtr->win0V = WIN_RANGE(0, 0xA0); for (i = 0; i < 160; ++i) - gScanlineEffectRegBuffers[1][i] = 242; + gScanlineEffectRegBuffers[1][i] = WIN_RANGE(0, 0xF2); SetVBlankCallback(VBCB_BT_Phase2BlackWaveToRight); ++task->tState; return TRUE; @@ -1460,7 +1458,7 @@ static bool8 BT_Phase2BlackWaveToRight_UpdateWave(struct Task *task) left = 0; if (left > 240) left = 240; - *winVal = (left << 8) | (0xF1); + *winVal = WIN_RANGE(left, 0xF1); if (left < 240) nextFunc = FALSE; } @@ -2529,10 +2527,10 @@ static bool8 BT_Phase2AntiClockwiseSpiral_Init(struct Task *task) BT_InitCtrlBlk(); ScanlineEffect_Clear(); sTransitionStructPtr->winIn = 0; - sTransitionStructPtr->winOut = 0x3F; - sTransitionStructPtr->win0H = 0x7878; - sTransitionStructPtr->win0V = 0x3070; - sTransitionStructPtr->win1V = 0x1090; + sTransitionStructPtr->winOut = WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR; + sTransitionStructPtr->win0H = WIN_RANGE(0x78, 0x78); + sTransitionStructPtr->win0V = WIN_RANGE(0x30, 0x70); + sTransitionStructPtr->win1V = WIN_RANGE(0x10, 0x90); sTransitionStructPtr->counter = 0; sub_80D1F64(0, 0, FALSE); sub_80D1F64(0, 0, TRUE); @@ -2665,11 +2663,11 @@ static bool8 BT_Phase2Mugshot_Init(struct Task *task) task->tTheta = 0; task->tbg0HOfsOpponent = 1; task->tbg0HOfsPlayer = 239; - sTransitionStructPtr->winIn = 0x3F; - sTransitionStructPtr->winOut = 0x3E; - sTransitionStructPtr->win0V = 160; + sTransitionStructPtr->winIn = WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR; + sTransitionStructPtr->winOut = WININ_WIN0_BG1 | WININ_WIN0_BG2 | WININ_WIN0_BG3 | WININ_WIN0_OBJ | WININ_WIN0_CLR; + sTransitionStructPtr->win0V = WIN_RANGE(0, 0xA0); for (i = 0; i < 160; ++i) - gScanlineEffectRegBuffers[1][i] = 0xF0F1; + gScanlineEffectRegBuffers[1][i] = WIN_RANGE(0xF0, 0xF1); SetVBlankCallback(VBCB_BT_Phase2Mugshot1_Slide); ++task->tState; return FALSE; @@ -2784,7 +2782,7 @@ static bool8 BT_Phase2Mugshot_WaitForPlayerInPlace(struct Task *task) DmaStop(0); memset(gScanlineEffectRegBuffers[0], 0, 320); memset(gScanlineEffectRegBuffers[1], 0, 320); - SetGpuReg(REG_OFFSET_WIN0H, 0xF0); + SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(0, 0xF0)); SetGpuReg(REG_OFFSET_BLDY, 0); ++task->tState; task->tCounter = 0; @@ -3026,9 +3024,9 @@ static bool8 BT_Phase2SlicedScreen_Init(struct Task *task) ScanlineEffect_Clear(); task->tAcc = 256; task->tJerk = 1; - sTransitionStructPtr->winIn = 0x3F; + sTransitionStructPtr->winIn = WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR; sTransitionStructPtr->winOut = 0; - sTransitionStructPtr->win0V = 160; + sTransitionStructPtr->win0V = WIN_RANGE(0, 0xA0); for (i = 0; i < 160; ++i) { gScanlineEffectRegBuffers[1][i] = sTransitionStructPtr->bg123HOfs; @@ -3065,7 +3063,7 @@ static bool8 BT_Phase2SlicedScreen_UpdateOffsets(struct Task *task) else { *ofsBuffer = sTransitionStructPtr->bg123HOfs - task->tSpeed; - *win0HBuffer = (task->tSpeed << 8) | 0xF1; + *win0HBuffer = WIN_RANGE(task->tSpeed, 0xF1); } } if (task->tSpeed > 0xEF) @@ -3126,9 +3124,9 @@ static bool8 BT_Phase2WhiteFadeInStripes_Init(struct Task *task) ScanlineEffect_Clear(); sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_LIGHTEN; sTransitionStructPtr->bldY = 0; - sTransitionStructPtr->winIn = 0x1E; - sTransitionStructPtr->winOut = 0x3F; - sTransitionStructPtr->win0V = 160; + sTransitionStructPtr->winIn = WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ; + sTransitionStructPtr->winOut = WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WININ_WIN0_CLR; + sTransitionStructPtr->win0V = WIN_RANGE(0, 0xA0); for (i = 0; i < 160; ++i) { gScanlineEffectRegBuffers[1][i] = 0; @@ -3180,7 +3178,7 @@ static bool8 BT_Phase2WhiteFadeInStripes_Stop(struct Task *task) sTransitionStructPtr->win0H = 240; sTransitionStructPtr->bldY = 0; sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN; - sTransitionStructPtr->winIn = 0x3F; + sTransitionStructPtr->winIn = WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WININ_WIN0_CLR; sTransitionStructPtr->counter = 0; SetVBlankCallback(VBCB_BT_Phase2WhiteFadeInStripes2); ++task->tState; @@ -3351,11 +3349,11 @@ static bool8 BT_Phase2BlackDoodles_Init(struct Task *task) BT_InitCtrlBlk(); ScanlineEffect_Clear(); - sTransitionStructPtr->winIn = 0x3F; + sTransitionStructPtr->winIn = WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR; sTransitionStructPtr->winOut = 0; - sTransitionStructPtr->win0V = 0xA0; + sTransitionStructPtr->win0V = WIN_RANGE(0, 0xA0); for (i = 0; i < 160; ++i) - gScanlineEffectRegBuffers[0][i] = 0x00F0; + gScanlineEffectRegBuffers[0][i] = WIN_RANGE(0, 0xF0); CpuSet(gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 160); SetVBlankCallback(VBCB_BT_Phase2BlackDoodles); ++task->tState; @@ -3394,7 +3392,7 @@ static bool8 BT_Phase2BlackDoodles_DrawSingleBrush(struct Task *task) if (right <= left) right = left; } - gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = right | (left << 8); + gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = WIN_RANGE2(left, right); if (nextFunc) { ++task->tState; diff --git a/src/bug.c b/src/bug.c new file mode 100644 index 000000000..9b8935744 --- /dev/null +++ b/src/bug.c @@ -0,0 +1,462 @@ +#include "global.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "trig.h" + +static void sub_80B3FAC(struct Sprite *sprite); +static void sub_80B407C(struct Sprite *sprite); +static void AnimTranslateWebThread(struct Sprite *sprite); +static void sub_80B41F8(struct Sprite *sprite); +static void sub_80B42C0(struct Sprite *sprite); +static void AnimTranslateStinger(struct Sprite *sprite); +static void AnimMissileArc(struct Sprite *sprite); +static void sub_80B45D8(struct Sprite *sprite); +static void sub_80B41C0(struct Sprite *sprite); +static void sub_80B4274(struct Sprite *sprite); +static void sub_80B42E8(struct Sprite *sprite); +static void sub_80B4344(struct Sprite *sprite); +static void AnimMissileArcStep(struct Sprite *sprite); + +static const union AffineAnimCmd gUnknown_83E71E8[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 30, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E71F8[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -99, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E7208[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 94, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E7218[] = +{ + gUnknown_83E71E8, + gUnknown_83E71F8, + gUnknown_83E7208, +}; + +const struct SpriteTemplate gUnknown_83E7224 = +{ + .tileTag = ANIM_TAG_HORN_HIT_2, + .paletteTag = ANIM_TAG_HORN_HIT_2, + .oam = &gOamData_83ACAB8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7218, + .callback = sub_80B3FAC, +}; + +static const union AffineAnimCmd gUnknown_83E723C[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -33, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E724C[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 96, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E725C[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -96, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E726C[] = +{ + gUnknown_83E723C, + gUnknown_83E724C, + gUnknown_83E725C, +}; + +const struct SpriteTemplate gUnknown_83E7278 = +{ + .tileTag = ANIM_TAG_NEEDLE, + .paletteTag = ANIM_TAG_NEEDLE, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E726C, + .callback = sub_80B407C, +}; + +const struct SpriteTemplate gWebThreadSpriteTemplate = +{ + .tileTag = ANIM_TAG_WEB_THREAD, + .paletteTag = ANIM_TAG_WEB_THREAD, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimTranslateWebThread, +}; + +const struct SpriteTemplate gUnknown_83E72A8 = +{ + .tileTag = ANIM_TAG_STRING, + .paletteTag = ANIM_TAG_STRING, + .oam = &gOamData_83ACA00, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B41F8, +}; + +static const union AffineAnimCmd gUnknown_83E72C0[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x6, 0x6, 0, 1), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const gUnknown_83E72D8[] = +{ + gUnknown_83E72C0, +}; + +const struct SpriteTemplate gSpiderWebSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPIDER_WEB, + .paletteTag = ANIM_TAG_SPIDER_WEB, + .oam = &gOamData_83ACBC0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E72D8, + .callback = sub_80B42C0, +}; + +const struct SpriteTemplate gLinearStingerSpriteTemplate = +{ + .tileTag = ANIM_TAG_NEEDLE, + .paletteTag = ANIM_TAG_NEEDLE, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimTranslateStinger, +}; + +const struct SpriteTemplate gPinMissileSpriteTemplate = +{ + .tileTag = ANIM_TAG_NEEDLE, + .paletteTag = ANIM_TAG_NEEDLE, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMissileArc, +}; + +const struct SpriteTemplate gIcicleSpearSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICICLE_SPEAR, + .paletteTag = ANIM_TAG_ICICLE_SPEAR, + .oam = &gOamData_83ACA38, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMissileArc, +}; + +static const union AffineAnimCmd gUnknown_83E733C[] = +{ + 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 gUnknown_83E7374[] = +{ + gUnknown_83E733C, +}; + +const struct SpriteTemplate gUnknown_83E7378 = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_83ACB60, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7374, + .callback = sub_80B45D8, +}; + +static void sub_80B3FAC(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 sub_80B407C(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_8075678(sprite); + sprite->data[5] = gBattleAnimArgs[3]; + sprite->callback = sub_80B41C0; +} + +static void sub_80B41C0(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; +} + +static void sub_80B41F8(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 = sub_80B4274; +} + +static void sub_80B4274(struct Sprite *sprite) +{ + if (++sprite->data[0] == 3) + { + sprite->data[0] = 0; + sprite->invisible ^= 1; + } + if (++sprite->data[1] == 51) + { + DestroyAnimSprite(sprite); + } +} + +static void sub_80B42C0(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 = sub_80B42E8; +} + +static void sub_80B42E8(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 = sub_80B4344; + } + } +} + +static void sub_80B4344(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 = AnimMissileArcStep; + sprite->invisible = TRUE; +} + +static void AnimMissileArcStep(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; + s32 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 sub_80B45D8(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == 0) + { + 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 new file mode 100644 index 000000000..7809e538d --- /dev/null +++ b/src/dark.c @@ -0,0 +1,921 @@ +#include "global.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "palette.h" +#include "scanline_effect.h" +#include "trig.h" +#include "util.h" + +static void sub_80B7ACC(struct Sprite *sprite); +static void sub_80B7BD4(struct Sprite *sprite); +static void sub_80B7C88(struct Sprite *sprite); +static void sub_80B86B0(struct Sprite *sprite); +static void sub_80B7954(u8 taskId); +static void sub_80B7A14(u8 taskId); +static void sub_80B7B48(struct Sprite *sprite); +static void sub_80B7C10(struct Sprite *sprite); +static void sub_80B7C50(struct Sprite *sprite); +static void sub_80B7D88(struct Sprite *sprite); +static void sub_80B856C(u8 priority); +static void sub_80B7F58(u8 taskId); +static void sub_80B843C(struct Task *task); +static void sub_80B82C0(u8 taskId); +static void sub_80B8920(u8 taskId); + +const struct SpriteTemplate gUnknown_83E7878 = +{ + .tileTag = ANIM_TAG_TIED_BAG, + .paletteTag = ANIM_TAG_TIED_BAG, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B7ACC, +}; + +static const union AffineAnimCmd gUnknown_83E7890[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E78A0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 32, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E78B0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 64, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E78C0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 96, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E78D0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -128, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E78E0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -96, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E78F0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -64, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E7900[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -32, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E7910[] = +{ + gUnknown_83E7890, + gUnknown_83E78A0, + gUnknown_83E78B0, + gUnknown_83E78C0, + gUnknown_83E78D0, + gUnknown_83E78E0, + gUnknown_83E78F0, + gUnknown_83E7900, +}; + +const struct SpriteTemplate gUnknown_83E7930 = +{ + .tileTag = ANIM_TAG_SHARP_TEETH, + .paletteTag = ANIM_TAG_SHARP_TEETH, + .oam = &gOamData_83ACB60, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7910, + .callback = sub_80B7BD4, +}; + +const struct SpriteTemplate gUnknown_83E7948 = +{ + .tileTag = ANIM_TAG_CLAMP, + .paletteTag = ANIM_TAG_CLAMP, + .oam = &gOamData_83ACB60, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7910, + .callback = sub_80B7BD4, +}; + +static const union AffineAnimCmd gUnknown_83E7960[] = +{ + AFFINEANIMCMD_FRAME(0xC0, 0xC0, 80, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -2, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E7978[] = +{ + AFFINEANIMCMD_FRAME(0xC0, 0xC0, -80, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 2, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E7990[] = +{ + gUnknown_83E7960, + gUnknown_83E7978, +}; + +const struct SpriteTemplate gUnknown_83E7998 = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7990, + .callback = sub_80B7C88, +}; + +static const union AnimCmd gUnknown_83E79B0[] = +{ + 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 gUnknown_83E79C8[] = +{ + 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 gUnknown_83E79E0[] = +{ + gUnknown_83E79B0, + gUnknown_83E79C8, +}; + +const struct SpriteTemplate gUnknown_83E79E8 = +{ + .tileTag = ANIM_TAG_CLAW_SLASH, + .paletteTag = ANIM_TAG_CLAW_SLASH, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E79E0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B86B0, +}; + +void sub_80B78E0(u8 taskId) +{ + s32 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 = sub_80B7954; +} + +static void sub_80B7954(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 sub_80B79DC(u8 taskId) +{ + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gTasks[taskId].data[1] = BLDALPHA_BLEND(0, 16); + gTasks[taskId].func = sub_80B7A14; + SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1]); +} + +static void sub_80B7A14(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 sub_80B7A80(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_80B7ACC(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_80B7B48; + sprite->callback(sprite); +} + +static void sub_80B7B48(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); +} + +static void sub_80B7BD4(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 = sub_80B7C10; +} + +static void sub_80B7C10(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 = sub_80B7C50; +} + +static void sub_80B7C50(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); +} + +static void sub_80B7C88(struct Sprite *sprite) +{ + u8 battler; + s8 xOffset; + + if (gBattleAnimArgs[0] == 0) + 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 = sub_80B7D88; +} + +static void sub_80B7D88(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroySpriteAndMatrix(sprite); +} + +void sub_80B7DA4(u8 taskId) +{ + struct ScanlineEffectParams scanlineParams; + struct BattleAnimBgData animBg; + u16 i; + u8 pos; + s32 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_80752A0(&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_80B856C(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 = sub_80B7F58; +} + +static void sub_80B7F58(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_80B843C(task); + if (task->data[4] < task->data[8]) + ++task->data[0]; + break; + case 2: + task->data[4] -= 8; + sub_80B843C(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 sub_80B8070(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_80752A0(&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_80B856C(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 = sub_80B82C0; + break; + } +} + +static void sub_80B82C0(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_80B843C(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_80B843C(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_80B843C(struct Task *task) +{ + s32 var0, var1, var4; + s16 var2, i; + + 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 < task->data[7]; ++i) + if (i >= 0) + gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = 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_80B856C(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 sub_80B85B8(u8 taskId) +{ + u8 toBG2 = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) ^ 1 ? 1 : 0; + + MoveBattlerSpriteToBG(gBattleAnimAttacker, toBG2); + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].invisible = FALSE; + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + { + MoveBattlerSpriteToBG(gBattleAnimAttacker ^ 2, toBG2 ^ 1); + gSprites[gBattlerSpriteIds[gBattleAnimAttacker ^ 2]].invisible = FALSE; + } + DestroyAnimVisualTask(taskId); +} + +void sub_80B8664(u8 taskId) +{ + u8 toBG2 = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) ^ 1 ? 1 : 0; + + sub_8073128(toBG2); + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + sub_8073128(toBG2 ^ 1); + DestroyAnimVisualTask(taskId); +} + +static void sub_80B86B0(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, 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 (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_8076E34(gBattleAnimAttacker, spriteId, species); + sub_80752A0(&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 = sub_80B8920; +} + +static void sub_80B8920(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, 1); + DestroySprite(&gSprites[gTasks[taskId].data[0]]); + sub_80752A0(&animBg); + sub_8075358(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: 0 grayscale, 1 original +void AnimTask_SetGreyscaleOrOriginalPal(u8 taskId) +{ + u8 spriteId, battler; + bool8 calcSpriteId = FALSE; + u8 position = B_POSITION_PLAYER_LEFT; + + switch (gBattleAnimArgs[0]) + { + case 0: + case 1: + case 2: + case 3: + 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 sub_80B8B38(u8 taskId) +{ + if (gAnimMoveTurn < 2) + gBattleAnimArgs[7] = 0; + if (gAnimMoveTurn == 2) + gBattleAnimArgs[7] = 1; + DestroyAnimVisualTask(taskId); +} diff --git a/src/daycare.c b/src/daycare.c index 837a2c4e6..fede86156 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -2087,7 +2087,7 @@ struct UnkStruct_82349CC u8 field_3; }; -extern const struct UnkStruct_82349CC gUnknown_82349CC[NUM_SPECIES]; +extern const struct UnkStruct_82349CC gMonFrontPicCoords[NUM_SPECIES]; static void SpriteCB_Egg_2(struct Sprite* sprite) { @@ -2101,7 +2101,7 @@ static void SpriteCB_Egg_2(struct Sprite* sprite) sprite->data[0] = 0; species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES); gSprites[sEggHatchData->pokeSpriteID].pos2.x = 0; - gSprites[sEggHatchData->pokeSpriteID].pos2.y = gUnknown_82349CC[species].field_1; + gSprites[sEggHatchData->pokeSpriteID].pos2.y = gMonFrontPicCoords[species].field_1; } else { diff --git a/src/dragon.c b/src/dragon.c new file mode 100644 index 000000000..34f97ba74 --- /dev/null +++ b/src/dragon.c @@ -0,0 +1,431 @@ +#include "global.h" +#include "battle_anim.h" +#include "scanline_effect.h" +#include "task.h" +#include "trig.h" + +static void sub_80B725C(struct Sprite *sprite); +static void sub_80B741C(struct Sprite *sprite); +static void sub_80B73AC(struct Sprite *sprite); +static void sub_80B7448(struct Sprite *sprite); +static void sub_80B77E4(struct Sprite *sprite); +static void sub_80B74D8(struct Sprite *sprite); +static void sub_80B76B0(u8 taskId); +static void sub_80B776C(struct Task *task); +static void sub_80B7894(struct Sprite *sprite); + +static EWRAM_DATA u16 gUnknown_20399A4[7] = {0}; + +static const union AnimCmd gUnknown_83E7710[] = +{ + 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_83E7728[] = +{ + gUnknown_83E7710, +}; + +const struct SpriteTemplate gUnknown_83E772C = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E7728, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B725C, +}; + +static const union AnimCmd gUnknown_83E7744[] = +{ + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd gUnknown_83E7754[] = +{ + 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 gUnknown_83E7764[] = +{ + gUnknown_83E7744, + gUnknown_83E7754, +}; + +static const union AffineAnimCmd gUnknown_83E776C[] = +{ + AFFINEANIMCMD_FRAME(0x50, 0x50, 127, 0), + AFFINEANIMCMD_FRAME(0xD, 0xD, 0, 100), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E7784[] = +{ + AFFINEANIMCMD_FRAME(0x50, 0x50, 0, 0), + AFFINEANIMCMD_FRAME(0xD, 0xD, 0, 100), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E779C[] = +{ + gUnknown_83E776C, + gUnknown_83E7784, +}; + +const struct SpriteTemplate gUnknown_83E77A4 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83ACA98, + .anims = gUnknown_83E7764, + .images = NULL, + .affineAnims = gUnknown_83E779C, + .callback = sub_80B741C, +}; + +const union AnimCmd gUnknown_83E77BC[] = +{ + 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 gUnknown_83E77D4[] = +{ + gUnknown_83E77BC, +}; + +const struct SpriteTemplate gUnknown_83E77D8 = +{ + .tileTag = ANIM_TAG_FIRE_PLUME, + .paletteTag = ANIM_TAG_FIRE_PLUME, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E77D4, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B73AC, +}; + +static const union AnimCmd gUnknown_83E77F0[] = +{ + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E7800[] = +{ + gUnknown_83E77F0, + gUnknown_83E77F0, +}; + +static const union AffineAnimCmd gUnknown_83E7808[] = +{ + AFFINEANIMCMD_FRAME(0x64, 0x64, 127, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E7818[] = +{ + AFFINEANIMCMD_FRAME(0x64, 0x64, 0, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E7828[] = +{ + gUnknown_83E7808, + gUnknown_83E7818, +}; + +const struct SpriteTemplate gUnknown_83E7830 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83ACA98, + .anims = gUnknown_83E7800, + .images = NULL, + .affineAnims = gUnknown_83E7828, + .callback = sub_80B741C, +}; + +const struct SpriteTemplate gUnknown_83E7848 = +{ + .tileTag = ANIM_TAG_HOLLOW_ORB, + .paletteTag = ANIM_TAG_HOLLOW_ORB, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B7448, +}; + +const struct SpriteTemplate gUnknown_83E7860 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E7728, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B77E4, +}; + +static void sub_80B725C(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_80B72F8(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 sub_80B73AC(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); +} + +static void sub_80B741C(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + StartSpriteAffineAnim(sprite, 1); + sub_80B72F8(sprite); +} + +static void sub_80B7448(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 = sub_80B74D8; +} + +static void sub_80B74D8(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; + } +} + +void sub_80B75E0(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 = sub_80B76B0; +} + +static void sub_80B76B0(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_80B776C(task); + break; + case 1: + if (++task->data[1] > 0x3C) + ++task->data[0]; + sub_80B776C(task); + break; + case 2: + if (++task->data[7] > 1) + { + task->data[7] = 0; + if (--task->data[6] == 0) + ++task->data[0]; + } + sub_80B776C(task); + break; + case 3: + gScanlineEffect.state = 3; + ++task->data[0]; + break; + case 4: + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_80B776C(struct Task *task) +{ + u16 i, r3 = task->data[5]; + + 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 sub_80B77E4(struct Sprite *sprite) +{ + s32 i, r6 = (gBattleAnimArgs[2] * 3) / 5; + + 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 = sub_80B7894; + for (i = 0; i < 7; ++i) + gUnknown_20399A4[i] = sprite->data[i]; +} + +static void sub_80B7894(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/flying.c b/src/flying.c new file mode 100644 index 000000000..8c3ccb52a --- /dev/null +++ b/src/flying.c @@ -0,0 +1,1289 @@ +#include "global.h" +#include "battle_anim.h" +#include "palette.h" +#include "trig.h" +#include "constants/battle_anim.h" +#include "random.h" + +static void sub_80B18E4(struct Sprite *sprite); +static void sub_80B1A1C(struct Sprite *sprite); +static void sub_80B1AB8(struct Sprite *sprite); +static void sub_80B1BB0(struct Sprite *sprite); +static void sub_80B1C3C(struct Sprite *sprite); +static void sub_80B1D88(struct Sprite *sprite); +static void sub_80B24C0(struct Sprite *sprite); +static void sub_80B2514(struct Sprite *sprite); +static void sub_80B2780(struct Sprite *sprite); +static void sub_80B2914(struct Sprite *sprite); +static void sub_80B2974(struct Sprite *sprite); +static void sub_80B2A08(struct Sprite *sprite); +static void sub_80B2AF4(struct Sprite *sprite); +static void sub_80B2BD8(struct Sprite *sprite); +static void sub_80B2CE4(struct Sprite *sprite); +static void sub_80B2D64(struct Sprite *sprite); +static void sub_80B190C(struct Sprite *sprite); +static void sub_80B198C(u8 taskId); +static void sub_80B1A9C(struct Sprite *sprite); +static void sub_80B1BF8(struct Sprite *sprite); +static void sub_80B1CC0(struct Sprite *sprite); +static void sub_80B1F94(struct Sprite *sprite); +static void sub_80B268C(struct Sprite *sprite); +static void sub_80B2820(struct Sprite *sprite); +static void sub_80B2A50(struct Sprite *sprite); +static void sub_80B2AB0(struct Sprite *sprite); +static void sub_80B2C88(struct Sprite *sprite); +static void sub_80B2CF8(struct Sprite *sprite); +static void sub_80B2E20(struct Sprite *sprite); + +const struct SpriteTemplate gUnknown_83E6AE8 = +{ + .tileTag = ANIM_TAG_GUST, + .paletteTag = ANIM_TAG_GUST, + .oam = &gOamData_83ACA20, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B18E4, +}; + +static const union AffineAnimCmd gUnknown_83E6B00[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0xA, 0x0, 0, 24), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6B18[] = +{ + gUnknown_83E6B00, +}; + +const struct SpriteTemplate gUnknown_83E6B1C = +{ + .tileTag = ANIM_TAG_GUST, + .paletteTag = ANIM_TAG_GUST, + .oam = &gOamData_83ACA80, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6B18, + .callback = sub_80B1A1C, +}; + +static const union AnimCmd gUnknown_83E6B34[] = +{ + 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 gUnknown_83E6B48[] = +{ + gUnknown_83E6B34, +}; + +const struct SpriteTemplate gUnknown_83E6B4C = +{ + .tileTag = ANIM_TAG_AIR_WAVE_2, + .paletteTag = ANIM_TAG_AIR_WAVE_2, + .oam = &gOamData_83AC9F8, + .anims = gUnknown_83E6B48, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B1AB8, +}; + +static const union AffineAnimCmd gUnknown_83E6B64[] = +{ + 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 gUnknown_83E6B8C[] = +{ + gUnknown_83E6B64, +}; + +static const union AffineAnimCmd gUnknown_83E6B90[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 50, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6B9C[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -40, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6BB0[] = +{ + gUnknown_83E6B90, + gUnknown_83E6B9C, +}; + +const struct SpriteTemplate gUnknown_83E6BB8 = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_83ACAA0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6B8C, + .callback = sub_80B1BB0, +}; + +const struct SpriteTemplate gUnknown_83E6BD0 = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_83ACA40, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6BB0, + .callback = sub_80B1C3C, +}; + +static const union AnimCmd gUnknown_83E6BE8[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E6BF0[] = +{ + ANIMCMD_FRAME(16, 0, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E6BF8[] = +{ + gUnknown_83E6BE8, + gUnknown_83E6BF0, +}; + +const struct SpriteTemplate gUnknown_83E6C00 = +{ + .tileTag = ANIM_TAG_WHITE_FEATHER, + .paletteTag = ANIM_TAG_WHITE_FEATHER, + .oam = &gOamData_83ACA38, + .anims = gUnknown_83E6BF8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B1D88, +}; + +// not used +static const u16 gUnknown_83E6C18[] = INCBIN_U16("graphics/battle_anims/sprites/unk_83E6C18.gbapal"); + +const struct SpriteTemplate gUnknown_83E6C38 = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B24C0, +}; + +const struct SpriteTemplate gUnknown_83E6C50 = +{ + .tileTag = ANIM_TAG_WHITE_FEATHER, + .paletteTag = ANIM_TAG_WHITE_FEATHER, + .oam = &gOamData_83ACA38, + .anims = gUnknown_83E6BF8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2514, +}; + +static const union AnimCmd gUnknown_83E6C68[] = +{ + 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 gUnknown_83E6C80[] = +{ + gUnknown_83E6C68, +}; + +const struct SpriteTemplate gUnknown_83E6C84 = +{ + .tileTag = ANIM_TAG_WHIRLWIND_LINES, + .paletteTag = ANIM_TAG_WHIRLWIND_LINES, + .oam = &gOamData_83AC9F8, + .anims = gUnknown_83E6C80, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2780, +}; + +static const union AffineAnimCmd gUnknown_83E6C9C[] = +{ + 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 gUnknown_83E6CCC[] = +{ + gUnknown_83E6C9C, +}; + +const struct SpriteTemplate gUnknown_83E6CD0 = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_83ACAA0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6CCC, + .callback = sub_80B2914, +}; + +static const union AffineAnimCmd gUnknown_83E6CE8[] = +{ + AFFINEANIMCMD_FRAME(0xA0, 0x100, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6CF8[] = +{ + gUnknown_83E6CE8, +}; + +const struct SpriteTemplate gUnknown_83E6CFC = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_83ACAA0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6CF8, + .callback = sub_80B2974, +}; + +static const union AffineAnimCmd gUnknown_83E6D14[] = +{ + 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 gUnknown_83E6D3C[] = +{ + gUnknown_83E6D14, +}; + +const struct SpriteTemplate gUnknown_83E6D40 = +{ + .tileTag = ANIM_TAG_ROUND_SHADOW, + .paletteTag = ANIM_TAG_ROUND_SHADOW, + .oam = &gOamData_83ACAA0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6D3C, + .callback = sub_80B2A08, +}; + +// not used +static const union AffineAnimCmd gUnknown_83E6D58[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x0, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x20, 0, 12), + AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 11), + AFFINEANIMCMD_END, +}; + +// not used +static const union AffineAnimCmd *const gUnknown_83E6D80[] = +{ + gUnknown_83E6D58, +}; + +const struct SpriteTemplate gUnknown_83E6D7C = +{ + .tileTag = ANIM_TAG_SPLASH, + .paletteTag = ANIM_TAG_SPLASH, + .oam = &gOamData_83ACAA0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2AF4, +}; + +const struct SpriteTemplate gUnknown_83E6D94 = +{ + .tileTag = ANIM_TAG_SWEAT_BEAD, + .paletteTag = ANIM_TAG_SWEAT_BEAD, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2BD8, +}; + +const struct SpriteTemplate gUnknown_83E6DAC = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_83ACB00, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2CE4, +}; + +const struct SpriteTemplate gUnknown_83E6DB4 = +{ + .tileTag = ANIM_TAG_BIRD, + .paletteTag = ANIM_TAG_BIRD, + .oam = &gOamData_83ACAA0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2D64, +}; + +static void sub_80B18E4(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, FALSE); + sprite->pos1.y += 20; + sprite->data[1] = 191; + sprite->callback = sub_80B190C; + sprite->callback(sprite); +} + +static void sub_80B190C(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); +} + +void sub_80B194C(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 = sub_80B198C; +} + +static void sub_80B198C(u8 taskId) +{ + u8 data2; + u16 temp; + s32 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]; + } while (--i > 0); + + gPlttBufferFaded[base + 0x101] = temp; + } + if (--gTasks[taskId].data[0] == 0) + DestroyAnimVisualTask(taskId); +} + +static void sub_80B1A1C(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, sub_80B1A9C); +} + +static void sub_80B1A9C(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + DestroyAnimSprite(sprite); +} + +static void sub_80B1AB8(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 sub_80B1BB0(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->callback = sub_80B1BF8; + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; +} + +static void sub_80B1BF8(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 sub_80B1C3C(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 = sub_80B1CC0; +} + +static void sub_80B1CC0(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 sub_80B1D3C(struct Sprite *sprite) +{ + if (sprite->data[0]-- <= 0) + { + if (sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK) + { + FreeOamMatrix(sprite->oam.matrixNum); + sprite->oam.affineMode = 0; + } + 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 sub_80B1D88(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 = TRUE; + sprite->animEnded = FALSE; + } + } + else + { + sprite->oam.priority = GetBattlerSpriteBGPriority(battler); + data->unkE_0 = 1; + if (data->unk4 & 0x8000) + { + sprite->hFlip ^= 1; + sprite->animNum = sprite->hFlip; + + sprite->animBeginning = TRUE; + sprite->animEnded = FALSE; + } + } + 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]; + if (sprite) + { + gOamMatrices[matrixNum].b = sinVal; + gOamMatrices[matrixNum].c = -sinVal; + } + else // pointless, exactly the same + { + gOamMatrices[matrixNum].b = sinVal; + gOamMatrices[matrixNum].c = -sinVal; + } + sprite->callback = sub_80B1F94; +} + +static void sub_80B1F94(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 = sub_80B1D3C; + } + } +} + +static void sub_80B24C0(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 sub_80B2514(struct Sprite *sprite) +{ + u8 matrixNum; + s16 rn, sinVal; + + sprite->data[1] = gBattleAnimArgs[0]; + sprite->data[2] = gBattleAnimArgs[1]; + sprite->data[3] = gBattleAnimArgs[2]; + if (!IsContest()) + { + if (gBattlerPositions[gBattleAnimTarget] & B_POSITION_OPPONENT_LEFT) + sprite->data[7] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_ATTR_WIDTH) + gBattleAnimArgs[3]; + else + sprite->data[7] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_ATTR_WIDTH) + 40; + if (gBattleAnimArgs[4]) + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget) + 1; + else + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + } + else + { + sprite->data[7] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_ATTR_WIDTH) + gBattleAnimArgs[3]; + } + sprite->data[4] = gSineTable[sprite->data[1] & 0xFF]; + sprite->data[5] = -gSineTable[(sprite->data[1] & 0xFF) + 64]; + sprite->data[6] = 0; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + matrixNum = sprite->oam.matrixNum; + sprite->data[1] = (u16)sprite->data[1] >> 8; + rn = Random(); + if (rn & 0x8000) + sprite->data[1] = 0xFF - sprite->data[1]; + sinVal = gSineTable[sprite->data[1]]; + gOamMatrices[matrixNum].a = gOamMatrices[matrixNum].d = gSineTable[sprite->data[1] + 64]; + gOamMatrices[matrixNum].b = sinVal; + gOamMatrices[matrixNum].c = -sinVal; + sprite->animBeginning = TRUE; + sprite->animEnded = FALSE; + if (rn & 1) + { + sprite->animNum = 1; + sprite->hFlip = TRUE; + } + sprite->callback = sub_80B268C; +} + +static void sub_80B268C(struct Sprite *sprite) +{ + struct FeatherDanceData fData; + struct FeatherDanceData *tData = (struct FeatherDanceData *)sprite->data; + u8 item; + u32 x, y; + + ++sprite->data[0]; + if (sprite->data[0] <= 4) + return; + sprite->pos2.x = (sprite->data[4] * sprite->data[6]) >> 8; + sprite->pos2.y = (sprite->data[5] * sprite->data[6]) >> 8; + sprite->data[6] += sprite->data[3] & 0xFF; + if (sprite->data[6] < (sprite->data[2] & 0xFF)) + return; + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + memcpy(&fData, tData, sizeof(struct FeatherDanceData)); + memset(tData, 0, sizeof(struct FeatherDanceData)); + tData->unk8 = sprite->pos1.y << 8; + tData->unk6 = fData.unk6 >> 8; + tData->unk2 = 0; + tData->unkA = fData.unk2; + if (sprite->animNum != 0) + { + if (tData->unk6 & 8) + tData->unk4 = 0x8001; + else + tData->unk4 = 0x8002; + } + else if (tData->unk6 & 8) + { + tData->unk4 = 1; + } + else + { + tData->unk4 = 2; + } + item = fData.unk4 >> 8; + tData->unkC[0] = item; + tData->unkC[1] = item - 2; + x = (((u16 *)&fData)[7] << 1); + y = (((u16 *)tData)[7] & 1); + ((u16 *)tData)[7] = y | x; + sprite->callback = sub_80B1F94; +} + +static void sub_80B2780(struct Sprite *sprite) +{ + u16 arg; + u8 mult; + + if (!gBattleAnimArgs[2]) + InitSpritePosToAnimAttacker(sprite, 0); + else + InitSpritePosToAnimTarget(sprite, FALSE); + if ((!gBattleAnimArgs[2] && !GetBattlerSide(gBattleAnimAttacker)) + || (gBattleAnimArgs[2] == 1 && !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_80B2820; +} + +static void sub_80B2820(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 sub_80B2868(u8 taskId) +{ + if (!(gTasks[taskId].data[0] % 32)) + { + ++gAnimVisualTaskCount; + gBattleAnimArgs[0] = Sin(gTasks[taskId].data[0], -13); + gBattleAnimArgs[1] = Cos(gTasks[taskId].data[0], -13); + gBattleAnimArgs[2] = 1; + gBattleAnimArgs[3] = 3; + CreateSpriteAndAnimate(&gUnknown_83E7C98, + GetBattlerSpriteCoord(gBattleAnimTarget, 2), + GetBattlerSpriteCoord(gBattleAnimTarget, 3), + 3); + } + gTasks[taskId].data[0] += 8; + if (gTasks[taskId].data[0] > 255) + DestroyAnimVisualTask(taskId); +} + +static void sub_80B2914(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + InitSpritePosToAnimAttacker(sprite, 1); + gSprites[GetAnimBattlerSpriteId(0)].invisible = TRUE; + ++sprite->data[0]; + break; + case 1: + if (sprite->affineAnimEnded) + DestroyAnimSprite(sprite); + break; + } +} + +static void sub_80B2974(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(0)].invisible = FALSE; + DestroyAnimSprite(sprite); + } + break; + } +} + +static void sub_80B2A08(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->callback = sub_80B2A50; + gSprites[GetAnimBattlerSpriteId(0)].invisible = TRUE; +} + +static void sub_80B2A50(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 = sub_80B2AB0; + } +} + +static void sub_80B2AB0(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 sub_80B2AF4(struct Sprite *sprite) +{ + u32 matrixNum; + s32 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_8075AD8(sprite); + DestroyAnimSprite(sprite); + } + break; + } +} + +static void sub_80B2BD8(struct Sprite *sprite) +{ + s32 v1 = 0x1FF & Random(); + s32 v2 = 0x7F & Random(); + + 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 = sub_80B2C88; +} + +static void sub_80B2C88(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_80B2CE4(struct Sprite *sprite) +{ + sprite->data[6] = 0; + sprite->data[7] = 64; + sprite->callback = sub_80B2CF8; +} + +static void sub_80B2CF8(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 != FALSE) + ++sprite->data[0]; + } + break; + case 1: + DestroyAnimSprite(sprite); + break; + } +} + +static void sub_80B2D64(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 = sub_80B2E20; +} + +static void sub_80B2E20(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); +} + +// not used +static void sub_80B2E64(u8 taskId) +{ + if (gBattleAnimArgs[0] == 0) + { + u8 spriteId = GetAnimBattlerSpriteId(0); + + gSprites[spriteId].invisible = TRUE; + } + else + { + u8 spriteId = GetAnimBattlerSpriteId(0); + + gSprites[spriteId].invisible = FALSE; + } + DestroyAnimVisualTask(taskId); +} diff --git a/src/ghost.c b/src/ghost.c new file mode 100644 index 000000000..fbf452af6 --- /dev/null +++ b/src/ghost.c @@ -0,0 +1,1484 @@ +#include "global.h" +#include "battle_anim.h" +#include "bg.h" +#include "gpu_regs.h" +#include "palette.h" +#include "scanline_effect.h" +#include "malloc.h" +#include "graphics.h" +#include "sound.h" +#include "trig.h" +#include "util.h" +#include "decompress.h" +#include "constants/songs.h" + +static void sub_80B5268(struct Sprite *sprite); +static void sub_80B52D0(struct Sprite *sprite); +static void sub_80B5344(struct Sprite *sprite); +static void sub_80B53C0(struct Sprite *sprite); +static void sub_80B5450(struct Sprite *sprite); +static void sub_80B5470(struct Sprite *sprite); +static void sub_80B5570(u8 taskId); +static void sub_80B55C8(u8 taskId); +static void InitAnimShadowBall(struct Sprite *sprite); +static void AnimShadowBallStep(struct Sprite *sprite); +static void sub_80B57F8(struct Sprite *sprite); +static void sub_80B5810(struct Sprite *sprite); +static void sub_80B59D4(u8 taskId); +static void sub_80B5AD4(u8 taskId); +static void sub_80B5D38(u8 taskId); +static void sub_80B5DCC(u8 taskId); +static void sub_80B5EC0(struct Sprite *sprite); +static void sub_80B5FE0(struct Sprite *sprite); +static void sub_80B623C(u8 taskId); +static void sub_80B6468(u8 taskId); +static void sub_80B65F0(u8 taskId); +static void sub_80B664C(struct Sprite *sprite); +static void sub_80B66A8(struct Sprite *sprite); +static void sub_80B6728(struct Sprite *sprite); +static void sub_80B67A0(struct Sprite *sprite); +static void sub_80B67D4(struct Sprite *sprite); +static void sub_80B68A8(struct Sprite *sprite); +static void sub_80B696C(u8 taskId); +static void sub_80B6AF8(struct Sprite *sprite); +static void sub_80B7158(struct Sprite *sprite); +static void sub_80B6BE4(u8 taskId); +static void sub_80B6F30(u8 taskId); +static void sub_80B6FC4(u8 taskId); +static void sub_80B71B0(struct Sprite *sprite); + +static const union AffineAnimCmd gUnknown_83E75A8[] = +{ + AFFINEANIMCMD_FRAME(0x1E, 0x1E, 10, 5), + AFFINEANIMCMD_FRAME(0xFFE2, 0xFFE2, 10, 5), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gUnknown_83E75C0[] = +{ + gUnknown_83E75A8, +}; + +const struct SpriteTemplate gUnknown_83E75C4 = +{ + .tileTag = ANIM_TAG_YELLOW_BALL, + .paletteTag = ANIM_TAG_YELLOW_BALL, + .oam = &gOamData_83ACA90, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E75C0, + .callback = sub_80B5268, +}; + +const struct SpriteTemplate gUnknown_83E75DC = +{ + .tileTag = ANIM_TAG_YELLOW_BALL, + .paletteTag = ANIM_TAG_YELLOW_BALL, + .oam = &gOamData_83ACAF0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B5450, +}; + +static const union AffineAnimCmd gUnknown_83E75F4[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 10, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gUnknown_83E7604[] = +{ + gUnknown_83E75F4, +}; + +const struct SpriteTemplate gShadowBallSpriteTemplate = +{ + .tileTag = ANIM_TAG_SHADOW_BALL, + .paletteTag = ANIM_TAG_SHADOW_BALL, + .oam = &gOamData_83ACA38, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7604, + .callback = InitAnimShadowBall, +}; + +const union AnimCmd gUnknown_83E7620[] = +{ + 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 gUnknown_83E7638[] = +{ + gUnknown_83E7620, +}; + +const struct SpriteTemplate gUnknown_83E763C = +{ + .tileTag = ANIM_TAG_LICK, + .paletteTag = ANIM_TAG_LICK, + .oam = &gOamData_83ACA18, + .anims = gUnknown_83E7638, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B57F8, +}; + +// not used +static const union AffineAnimCmd gUnknown_83E7654[] = +{ + AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0), + AFFINEANIMCMD_END, +}; + +// not used +static const union AffineAnimCmd *const gUnknown_83E7664[] = +{ + gUnknown_83E7654, +}; + +const struct SpriteTemplate gUnknown_83E7668 = +{ + .tileTag = ANIM_TAG_WHITE_SHADOW, + .paletteTag = ANIM_TAG_WHITE_SHADOW, + .oam = &gOamData_83ACB20, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B5EC0, +}; + +const struct SpriteTemplate gUnknown_83E7680 = +{ + .tileTag = ANIM_TAG_NAIL, + .paletteTag = ANIM_TAG_NAIL, + .oam = &gOamData_83ACB18, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B664C, +}; + +const struct SpriteTemplate gUnknown_83E7698 = +{ + .tileTag = ANIM_TAG_GHOSTLY_SPIRIT, + .paletteTag = ANIM_TAG_GHOSTLY_SPIRIT, + .oam = &gOamData_83ACAF8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B67D4, +}; + +const struct SpriteTemplate gUnknown_83E76B0 = +{ + .tileTag = ANIM_TAG_DEVIL, + .paletteTag = ANIM_TAG_DEVIL, + .oam = &gOamData_83ACAF8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B67D4, +}; + +static const union AnimCmd gUnknown_83E76C8[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(8, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(24, 4), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E76DC[] = +{ + gUnknown_83E76C8, +}; + +const struct SpriteTemplate gUnknown_83E76E0 = +{ + .tileTag = ANIM_TAG_PURPLE_FLAME, + .paletteTag = ANIM_TAG_PURPLE_FLAME, + .oam = &gOamData_83ACB38, + .anims = gUnknown_83E76DC, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B6AF8, +}; + +const struct SpriteTemplate gUnknown_83E76F8 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B7158, +}; + +static void sub_80B5268(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_8075678(sprite); + sprite->callback = sub_80B52D0; + sprite->data[6] = 16; + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, sprite->data[6]); +} + +static void sub_80B52D0(struct Sprite *sprite) +{ + s16 r0, r2; + + sub_80B53C0(sprite); + if (AnimTranslateLinear(sprite)) + { + sprite->callback = sub_80B5344; + 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, gUnknown_2037F24); +} + +static void sub_80B5344(struct Sprite *sprite) +{ + s16 r2, 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) && r0 > 0) + PlaySE(SE_W109); + if (sprite->data[6] == 0) + { + sprite->invisible = TRUE; + sprite->callback = DestroyAnimSpriteAndDisableBlend; + } + else + { + sub_80B53C0(sprite); + } +} + +static void sub_80B53C0(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 sub_80B5450(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->callback = sub_80B5470; + sprite->callback(sprite); +} + +static void sub_80B5470(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); +} + +void sub_80B54E8(u8 taskId) +{ + u8 spriteId; + + SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); + spriteId = GetAnimBattlerSpriteId(0); + 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 = sub_80B5570; +} + +static void sub_80B5570(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 = sub_80B55C8; + } +} + +static void sub_80B55C8(u8 taskId) +{ + u8 spriteId; + + if (gTasks[taskId].data[1] > 0) + { + gTasks[taskId].data[1] -= 1; + return; + } + spriteId = GetAnimBattlerSpriteId(0); + 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 InitAnimShadowBall(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 = AnimShadowBallStep; +} + +static void AnimShadowBallStep(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 sub_80B57F8(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->callback = sub_80B5810; +} + +static void sub_80B5810(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]; + } + } +} + +void sub_80B58AC(u8 taskId) +{ + struct Task *task; + + task = &gTasks[taskId]; + task->data[0] = CloneBattlerSpriteWithBlend(1); + 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 = sub_80B59D4; +} + +static void sub_80B59D4(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; + } +} + +void sub_80B5AAC(u8 taskId) +{ + struct Task *task; + + task = &gTasks[taskId]; + task->data[15] = 0; + task->func = sub_80B5AD4; + task->func(taskId); +} + +static void sub_80B5AD4(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(1); + 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(1); + 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 = sub_80B5D38; + ++task->data[15]; + break; + default: + ++task->data[15]; + break; + } +} + +static void sub_80B5D38(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 = sub_80B5DCC; + task->func(taskId); + } +} + +static void sub_80B5DCC(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 rank = GetBattlerSpriteBGPriorityRank(gBattleAnimTarget); + + switch (task->data[15]) + { + case 0: + gScanlineEffect.state = 3; + task->data[14] = GetAnimBattlerSpriteId(1); + 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 sub_80B5EC0(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 = sub_80B5FE0; + sprite->invisible = TRUE; +} + +static void sub_80B5FE0(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 sub_80B6020(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 < 4; ++battler) + { + if (battler != gBattleAnimAttacker + && battler != (gBattleAnimAttacker ^ 2) + && IsBattlerSpriteVisible(battler)) + { + spriteId = CreateSprite(&gUnknown_83E7668, 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 = sub_80B5FE0; + task->data[task->data[12] + 13] = spriteId; + ++task->data[12]; + } + } + } + } + else + { + spriteId = CreateSprite(&gUnknown_83E7668, 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 = sub_80B5FE0; + task->data[13] = spriteId; + task->data[12] = 1; + } + } + task->func = sub_80B623C; +} + +static void sub_80B623C(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 sub_80B63B4(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 = WIN_RANGE(startX, startX); + startY = 40; + gBattle_WIN0V = WIN_RANGE(startY, 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 = sub_80B6468; +} + +static void sub_80B6468(u8 taskId) +{ + s16 step, leftDistance, rightDistance, topDistance, bottomDistance, startX, startY; + u16 left, right, top, bottom, 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_8075BE8(1, 0, 0, 0, 0, 0, 0); + BeginNormalPaletteFade(selectedPalettes, 0, 16, 16, RGB(0, 0, 0)); + gTasks[taskId].func = sub_80B65F0; + } + gBattle_WIN0H = WIN_RANGE(left, right); + gBattle_WIN0V = WIN_RANGE(top, bottom); +} + +static void sub_80B65F0(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 sub_80B664C(struct Sprite *sprite) +{ + s16 xDelta, 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 = sub_80B66A8; +} + +static void sub_80B66A8(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, sub_80B6728); + } + else + { + sprite->data[0] = 40; + } + } + } +} + +static void sub_80B6728(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, BLDALPHA_BLEND2(16 - sprite->data[2], sprite->data[2])); + if (sprite->data[2] == 16) + { + sprite->invisible = TRUE; + sprite->callback = sub_80B67A0; + } + } +} + +static void sub_80B67A0(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + gBattle_WIN0H = 0; + gBattle_WIN0V = 0; + DestroyAnimSprite(sprite); +} + +static void sub_80B67D4(struct Sprite *sprite) +{ + u16 coeffB, 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 = sub_80B68A8; + } + } +} + +static void sub_80B68A8(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimSprite(sprite); +} + +void sub_80B68C8(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 = sub_80B696C; +} + +static void sub_80B696C(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(&gUnknown_83E76E0, 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 sub_80B6AF8(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); + } +} + +void sub_80B6BBC(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[15] = 0; + task->func = sub_80B6BE4; + sub_80B6BE4(taskId); +} + +static void sub_80B6BE4(u8 taskId) +{ + s16 y; + struct BattleAnimBgData animBgData; + struct Task *task = &gTasks[taskId]; + u8 rank = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); + + switch (task->data[15]) + { + case 0: + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 2); + SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 1); + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 16; + task->data[4] = GetAnimBattlerSpriteId(0); + task->data[5] = gSprites[task->data[4]].oam.priority; + task->data[6] = (gSprites[task->data[4]].oam.paletteNum + 16) << 4; + gSprites[task->data[4]].oam.objMode = ST_OAM_OBJ_BLEND; + gSprites[task->data[4]].oam.priority = 3; + task->data[7] = 128; + break; + case 1: + ++task->data[1]; + if (task->data[1] & 1) + return; + BlendPalette(task->data[6], 0x10, task->data[2], RGB(0, 23, 25)); + BlendPalette(task->data[7], 0x10, task->data[2], RGB(0, 23, 25)); + if (task->data[2] <= 11) + { + ++task->data[2]; + return; + } + task->data[1] = 0; + task->data[2] = 0; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); + break; + case 2: + SetAnimBgAttribute(2, BG_ANIM_CHAR_BASE_BLOCK, 1); + SetAnimBgAttribute(2, BG_ANIM_SCREEN_SIZE, 0); + gBattle_BG2_X = 0; + gBattle_BG2_Y = 0; + SetGpuReg(REG_OFFSET_BG2HOFS, gBattle_BG2_X); + SetGpuReg(REG_OFFSET_BG2VOFS, gBattle_BG2_Y); + sub_80752C8(&animBgData, 2); + AnimLoadCompressedBgGfx(animBgData.bgId, gFile_graphics_battle_anims_backgrounds_scary_face_sheet, animBgData.tilesOffset); + LoadCompressedPalette(gFile_graphics_battle_anims_backgrounds_scary_face_palette, 16 * animBgData.paletteId, 0x20); + break; + case 3: + sub_80752C8(&animBgData, 2); + gMonSpritesGfxPtr->field_17C = AllocZeroed(0x2000); + LZDecompressWram(gFile_graphics_battle_anims_backgrounds_scary_face_player_tilemap, gMonSpritesGfxPtr->field_17C); + sub_80730C0(animBgData.paletteId, gMonSpritesGfxPtr->field_17C, 256, 0); + CopyToBgTilemapBufferRect_ChangePalette(animBgData.bgId, gMonSpritesGfxPtr->field_17C, 0, 0, 0x20, 0x20, 0x11); + CopyBgTilemapBufferToVram(2); + FREE_AND_SET_NULL(gMonSpritesGfxPtr->field_17C); + break; + case 4: + ++task->data[1]; + if (task->data[1] & 1) + return; + ++task->data[2]; + --task->data[3]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[2], task->data[3])); + if (task->data[3]) + return; + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 16; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); + break; + case 5: + if (rank == 1) + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); + else + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); + break; + case 6: + y = gSprites[task->data[4]].pos1.y + gSprites[task->data[4]].pos2.y - 0x20; + if (y < 0) + y = 0; + if (rank == 1) + task->data[10] = ScanlineEffect_InitWave(y, y + 0x40, 4, 8, 0, 4, 1); + else + task->data[10] = ScanlineEffect_InitWave(y, y + 0x40, 4, 8, 0, 8, 1); + break; + case 7: + BlendPalette(task->data[7], 0x10, 0xC, RGB(31, 31, 29)); + if (rank == 1) + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); + else + SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); + task->func = sub_80B6F30; + task->data[15] = 0; + break; + } + ++task->data[15]; +} + +static void sub_80B6F30(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + ++task->data[1]; + task->data[8] = task->data[1] & 1; + if (!task->data[8]) + task->data[2] = gSineTable[task->data[1]] / 18; + if (task->data[8] == 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 = sub_80B6FC4; + sub_80B6FC4(taskId); + } +} + +static void sub_80B6FC4(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[15]) + { + case 0: + gScanlineEffect.state = 3; + BlendPalette(task->data[7], 0x10, 0xC, RGB(0, 23, 25)); + break; + case 1: + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0x10, 0)); + task->data[2] = 16; + task->data[3] = 0; + break; + case 2: + --task->data[2]; + ++task->data[3]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(task->data[2], task->data[3])); + if (task->data[3] <= 15) + return; + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 2); + SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); + break; + case 3: + sub_8075358(2); + FillPalette(0, 0x90, 0x20); + SetAnimBgAttribute(2, BG_ANIM_CHAR_BASE_BLOCK, 0); + task->data[1] = 12; + break; + case 4: + BlendPalette(task->data[6], 0x10, task->data[1], RGB(0, 23, 25)); + BlendPalette(task->data[7], 0x10, task->data[1], RGB(0, 23, 25)); + if ( task->data[1] ) + { + --task->data[1]; + return; + } + task->data[1] = 0; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); + break; + case 5: + gSprites[task->data[4]].oam.priority = task->data[5]; + gSprites[task->data[4]].oam.objMode = ST_OAM_OBJ_NORMAL; + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 1); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_NONE); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + DestroyAnimVisualTask(taskId); + break; + } + ++task->data[15]; +} + +static void sub_80B7158(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_80B71B0; + gSprites[sprite->data[5]].pos1.y += 8; +} + +static void sub_80B71B0(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 new file mode 100644 index 000000000..4ae4d8370 --- /dev/null +++ b/src/ground.c @@ -0,0 +1,724 @@ +#include "global.h" +#include "battle_anim.h" +#include "random.h" +#include "scanline_effect.h" +#include "task.h" +#include "trig.h" + +static void AnimBonemerangProjectile(struct Sprite *sprite); +static void AnimBoneHitProjectile(struct Sprite *sprite); +static void AnimDirtScatter(struct Sprite *sprite); +static void AnimMudSportDirt(struct Sprite *sprite); +static void AnimFissureDirtPlumeParticle(struct Sprite *sprite); +static void AnimDigDirtMound(struct Sprite *sprite); +static void AnimBonemerangProjectileStep(struct Sprite *sprite); +static void AnimBonemerangProjectileEnd(struct Sprite *sprite); +static void AnimMudSportDirtRising(struct Sprite *sprite); +static void AnimMudSportDirtFalling(struct Sprite *sprite); +static void sub_80B8ED4(u8 taskId); +static void sub_80B908C(u8 taskId); +static void sub_80B92B8(u8 useBg1, s16 y, s16 endY); +static void sub_80B912C(u8 taskId); +static void sub_80B91B0(u8 taskId); +static void AnimFissureDirtPlumeParticleStep(struct Sprite *sprite); +static void sub_80B9584(u8 taskId); +static void sub_80B967C(u8 taskId); +static void sub_80B9760(struct Task *task); +static void sub_80B98A8(u8 taskId); + +static const union AffineAnimCmd gUnknown_83E7A00[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 15, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd gUnknown_83E7A10[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 20, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gUnknown_83E7A20[] = +{ + gUnknown_83E7A00, +}; + +static const union AffineAnimCmd *const gUnknown_83E7A24[] = +{ + gUnknown_83E7A10, +}; + +const struct SpriteTemplate gUnknown_83E7A28 = +{ + .tileTag = ANIM_TAG_BONE, + .paletteTag = ANIM_TAG_BONE, + .oam = &gOamData_83ACA38, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7A20, + .callback = AnimBonemerangProjectile, +}; + +const struct SpriteTemplate gUnknown_83E7A40 = +{ + .tileTag = ANIM_TAG_BONE, + .paletteTag = ANIM_TAG_BONE, + .oam = &gOamData_83ACA38, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7A24, + .callback = AnimBoneHitProjectile, +}; + +const struct SpriteTemplate gUnknown_83E7A58 = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDirtScatter, +}; + +static const union AnimCmd gUnknown_83E7A70[] = +{ + ANIMCMD_FRAME(1, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E7A78[] = +{ + gUnknown_83E7A70, +}; + +const struct SpriteTemplate gUnknown_83E7A7C = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_83AC9D0, + .anims = gUnknown_83E7A78, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDirtScatter, +}; + +const struct SpriteTemplate gUnknown_83E7A94 = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMudSportDirt, +}; + +const struct SpriteTemplate gUnknown_83E7AAC = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFissureDirtPlumeParticle, +}; + +const struct SpriteTemplate gUnknown_83E7AC4 = +{ + .tileTag = ANIM_TAG_DIRT_MOUND, + .paletteTag = ANIM_TAG_DIRT_MOUND, + .oam = &gOamData_83AC9F8, + .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 = AnimBonemerangProjectileStep; +} + +static void AnimBonemerangProjectileStep(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 = AnimBonemerangProjectileEnd; + } +} + +static void AnimBonemerangProjectileEnd(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 = Random() & 0x1F; + yOffset = Random() & 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 sub_80B8E94(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (gBattleAnimArgs[0] == 0) + task->func = sub_80B8ED4; + else + task->func = sub_80B908C; + task->func(taskId); +} + +static void sub_80B8ED4(u8 taskId) +{ + u8 var0; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[10] = GetAnimBattlerSpriteId(0); + 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_80B92B8(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 sub_80B908C(u8 taskId) +{ + u8 spriteId = GetAnimBattlerSpriteId(0); + + 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 sub_80B90EC(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (gBattleAnimArgs[0] == 0) + task->func = sub_80B912C; + else + task->func = sub_80B91B0; + + task->func(taskId); +} + +static void sub_80B912C(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[10] = GetAnimBattlerSpriteId(0); + 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 sub_80B91B0(u8 taskId) +{ + u8 var0; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[10] = GetAnimBattlerSpriteId(0); + 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_80B92B8(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_80B92B8(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 +static void AnimFissureDirtPlumeParticle(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 = AnimFissureDirtPlumeParticleStep; +} + +static void AnimFissureDirtPlumeParticleStep(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; +} + +void sub_80B94B4(u8 taskId) +{ + u16 i; + struct Task *task = &gTasks[taskId]; + + if (gBattleAnimArgs[1]) + task->data[14] = task->data[15] = gBattleAnimArgs[1] + 3; + else + task->data[14] = task->data[15] = (gAnimMovePower / 10) + 3; + + task->data[3] = gBattleAnimArgs[2]; + switch (gBattleAnimArgs[0]) + { + case 5: + task->data[13] = gBattle_BG3_X; + task->func = sub_80B9584; + break; + case 4: + task->data[13] = 0; + for (i = 0; i < MAX_BATTLERS_COUNT; ++i) + { + if (IsBattlerSpriteVisible(i)) + { + task->data[task->data[13] + 9] = gBattlerSpriteIds[i]; + ++task->data[13]; + } + } + task->func = sub_80B967C; + break; + default: + task->data[9] = GetAnimBattlerSpriteId(gBattleAnimArgs[0]); + if (task->data[9] == 0xFF) + { + DestroyAnimVisualTask(taskId); + } + else + { + task->data[13] = 1; + task->func = sub_80B967C; + } + + break; + } +} + +static void sub_80B9584(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) == 0) + gBattle_BG3_X = task->data[13] + task->data[15]; + else + gBattle_BG3_X = task->data[13] - task->data[15]; + + if (++task->data[2] == task->data[3]) + { + task->data[2] = 0; + --task->data[14]; + ++task->data[0]; + } + } + break; + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + if ((task->data[2] & 1) == 0) + gBattle_BG3_X = task->data[13] + task->data[14]; + else + gBattle_BG3_X = task->data[13] - task->data[14]; + + if (++task->data[2] == 4) + { + task->data[2] = 0; + if (--task->data[14] == 0) + ++task->data[0]; + } + } + break; + case 2: + gBattle_BG3_X = task->data[13]; + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_80B967C(u8 taskId) +{ + u16 i; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + if (++task->data[1] > 1) + { + task->data[1] = 0; + sub_80B9760(task); + if (++task->data[2] == task->data[3]) + { + task->data[2] = 0; + --task->data[14]; + ++task->data[0]; + } + } + break; + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + sub_80B9760(task); + if (++task->data[2] == 4) + { + task->data[2] = 0; + if (--task->data[14] == 0) + ++task->data[0]; + } + } + break; + case 2: + for (i = 0; i < task->data[13]; ++i) + gSprites[task->data[9 + i]].pos2.x = 0; + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_80B9760(struct Task *task) +{ + u16 i, xOffset; + + if ((task->data[2] & 1) == 0) + xOffset = (task->data[14] / 2) + (task->data[14] & 1); + else + xOffset = -(task->data[14] / 2); + for (i = 0; i < task->data[13]; ++i) + gSprites[task->data[9 + i]].pos2.x = xOffset; +} + +void AnimTask_IsPowerOver99(u8 taskId) +{ + gBattleAnimArgs[15] = gAnimMovePower > 99; + DestroyAnimVisualTask(taskId); +} + +void sub_80B9800(u8 taskId) +{ + struct Task *newTask; + u8 battler = (gBattleAnimArgs[0] & 1) ? gBattleAnimTarget : gBattleAnimAttacker; + + if (gBattleAnimArgs[0] > 1) + battler ^= BIT_FLANK; + newTask = &gTasks[CreateTask(sub_80B98A8, 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_80B98A8(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/normal.c b/src/normal.c new file mode 100644 index 000000000..4d86b55a6 --- /dev/null +++ b/src/normal.c @@ -0,0 +1,916 @@ +#include "global.h" +#include "battle_anim.h" +#include "palette.h" +#include "random.h" +#include "task.h" +#include "trig.h" + +static void AnimConfusionDuck(struct Sprite *sprite); +static void AnimSimplePaletteBlend(struct Sprite *sprite); +static void sub_80B9A7C(struct Sprite *sprite); +static void sub_80B9B8C(struct Sprite *sprite); +static void sub_80BA27C(struct Sprite *sprite); +static void sub_80BA560(struct Sprite *sprite); +static void sub_80BA5F8(struct Sprite *sprite); +static void sub_80BA630(struct Sprite *sprite); +static void sub_80BA6C8(struct Sprite *sprite); +static void sub_80BA738(struct Sprite *sprite); +static void sub_80BA780(struct Sprite *sprite); +static void sub_80BA5A8(struct Sprite *sprite); +static void AnimConfusionDuckStep(struct Sprite *sprite); +static void AnimSimplePaletteBlendStep(struct Sprite *sprite); +static void sub_80B9AD0(struct Sprite *sprite); +static void sub_80B9B5C(struct Sprite *sprite); +static void sub_80B9C2C(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount); +static void sub_80B9C7C(u8 taskId); +static void sub_80B9DA0(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount); +static void sub_80B9DF0(u8 taskId); +static void sub_80B9EA8(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount); +static void sub_80B9F04(u8 taskId); +static void sub_80B9FD8(u8 taskId); +static void sub_80BA090(u8 taskId); +static void sub_80BA3CC(void); +static void sub_80BA320(struct Sprite *sprite); +static void sub_80BA4D0(u8 taskId); +static void sub_80BA7BC(struct Sprite *sprite); + + +static const union AnimCmd gUnknown_83E7ADC[] = +{ + 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 gUnknown_83E7AF0[] = +{ + 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 gUnknown_83E7B04[] = +{ + gUnknown_83E7ADC, + gUnknown_83E7AF0, +}; + +const struct SpriteTemplate gConfusionDuckSpriteTemplate = +{ + .tileTag = ANIM_TAG_DUCK, + .paletteTag = ANIM_TAG_DUCK, + .oam = &gOamData_83AC9D0, + .anims = gUnknown_83E7B04, + .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 = sub_80B9A7C, +}; + +static const union AnimCmd gUnknown_83E7B54[] = +{ + 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_83E7B6C[] = +{ + gUnknown_83E7B54, +}; + +const struct SpriteTemplate gUnknown_83E7B70 = +{ + .tileTag = ANIM_TAG_SPARKLE_4, + .paletteTag = ANIM_TAG_SPARKLE_4, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E7B6C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B9B8C, +}; + +const struct SpriteTemplate gUnknown_83E7B88 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80BA27C, +}; + +static const union AffineAnimCmd gUnknown_83E7BA0[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E7BB0[] = +{ + AFFINEANIMCMD_FRAME(0xD8, 0xD8, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E7BC8[] = +{ + AFFINEANIMCMD_FRAME(0xB0, 0xB0, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E7BE0[] = +{ + AFFINEANIMCMD_FRAME(0x80, 0x80, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E7BF8[] = +{ + gUnknown_83E7BA0, + gUnknown_83E7BB0, + gUnknown_83E7BC8, + gUnknown_83E7BE0, +}; + +const struct SpriteTemplate gBasicHitSplatSpriteTemplate = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_83ACB58, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7BF8, + .callback = sub_80BA560, +}; + +const struct SpriteTemplate gUnknown_83E7C20 = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_83ACB58, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7BF8, + .callback = sub_80BA5F8, +}; + +const struct SpriteTemplate gUnknown_83E7C38 = +{ + .tileTag = ANIM_TAG_WATER_IMPACT, + .paletteTag = ANIM_TAG_WATER_IMPACT, + .oam = &gOamData_83ACB58, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7BF8, + .callback = sub_80BA560, +}; + +const struct SpriteTemplate gUnknown_83E7C50 = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_83ACB58, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7BF8, + .callback = sub_80BA630, +}; + +const struct SpriteTemplate gUnknown_83E7C68 = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_83ACB58, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7BF8, + .callback = sub_80BA6C8, +}; + +const struct SpriteTemplate gUnknown_83E7C80 = +{ + .tileTag = ANIM_TAG_CROSS_IMPACT, + .paletteTag = ANIM_TAG_CROSS_IMPACT, + .oam = &gOamData_83ACAF8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80BA738, +}; + +const struct SpriteTemplate gUnknown_83E7C98 = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_83ACA38, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7BF8, + .callback = sub_80BA780, +}; + +const struct SpriteTemplate gUnknown_83E7CB0 = +{ + .tileTag = ANIM_TAG_IMPACT, + .paletteTag = ANIM_TAG_IMPACT, + .oam = &gOamData_83ACB58, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7BF8, + .callback = sub_80BA5A8, +}; + +// 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 = AnimConfusionDuckStep; + sprite->callback(sprite); +} + +static void AnimConfusionDuckStep(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 = AnimSimplePaletteBlendStep; +} + +// 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_8075BE8(battleBackground, attacker, target, attackerPartner, targetPartner, arg5, arg6); +} + +static void AnimSimplePaletteBlendStep(struct Sprite *sprite) +{ + if (!gPaletteFade.active) + DestroyAnimSprite(sprite); +} + +static void sub_80B9A7C(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 = sub_80B9AD0; +} + +static void sub_80B9AD0(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 = sub_80B9B5C; + 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 sub_80B9B5C(struct Sprite *sprite) +{ + u32 selectedPalettes; + + if (!gPaletteFade.active) + { + selectedPalettes = UnpackSelectedBattleAnimPalettes(sprite->data[7]); + BlendPalettes(selectedPalettes, 0, 0); + DestroyAnimSprite(sprite); + } +} + +static void sub_80B9B8C(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); +} + +void sub_80B9BDC(u8 taskId) +{ + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + 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[8] = 0; + sub_80B9C2C(taskId, 0, gTasks[taskId].data[4]); + gTasks[taskId].func = sub_80B9C7C; +} + +static void sub_80B9C2C(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount) +{ + u32 selectedPalettes = UnpackSelectedBattleAnimPalettes(gTasks[taskId].data[0]); + + BeginNormalPaletteFade(selectedPalettes, + gTasks[taskId].data[1], + initialBlendAmount, + targetBlendAmount, + gTasks[taskId].data[5]); + --gTasks[taskId].data[2]; + gTasks[taskId].data[8] ^= 1; +} + +static void sub_80B9C7C(u8 taskId) +{ + u8 initialBlendAmount, targetBlendAmount; + + if (!gPaletteFade.active) + { + if (gTasks[taskId].data[2] > 0) + { + if (gTasks[taskId].data[8] == 0) + { + initialBlendAmount = gTasks[taskId].data[3]; + targetBlendAmount = gTasks[taskId].data[4]; + } + else + { + initialBlendAmount = gTasks[taskId].data[4]; + targetBlendAmount = gTasks[taskId].data[3]; + } + if (gTasks[taskId].data[2] == 1) + targetBlendAmount = 0; + sub_80B9C2C(taskId, initialBlendAmount, targetBlendAmount); + } + else + { + DestroyAnimVisualTask(taskId); + } + } +} + +void sub_80B9CE4(u8 taskId) +{ + s32 battler; + u32 selectedPalettes = 0; + + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + 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[8] = 0; + for (battler = 0; battler < gBattlersCount; ++battler) + if (battler != gBattleAnimAttacker && battler != gBattleAnimTarget) + selectedPalettes |= 1 << (battler + 16); + if (gBattleAnimArgs[0] == 1) + selectedPalettes |= 0xE; + gTasks[taskId].data[9] = selectedPalettes >> 16; + gTasks[taskId].data[10] = selectedPalettes & 0xFF; + sub_80B9DA0(taskId, 0, gTasks[taskId].data[4]); + gTasks[taskId].func = sub_80B9DF0; +} + +static void sub_80B9DA0(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount) +{ + u32 selectedPalettes = ((u16)gTasks[taskId].data[9] << 16) | (u16)gTasks[taskId].data[10]; + + BeginNormalPaletteFade(selectedPalettes, + gTasks[taskId].data[1], + initialBlendAmount, + targetBlendAmount, + gTasks[taskId].data[5]); + --gTasks[taskId].data[2]; + gTasks[taskId].data[8] ^= 1; +} + +static void sub_80B9DF0(u8 taskId) +{ + u8 initialBlendAmount, targetBlendAmount; + + if (!gPaletteFade.active) + { + if (gTasks[taskId].data[2] > 0) + { + if (gTasks[taskId].data[8] == 0) + { + initialBlendAmount = gTasks[taskId].data[3]; + targetBlendAmount = gTasks[taskId].data[4]; + } + else + { + initialBlendAmount = gTasks[taskId].data[4]; + targetBlendAmount = gTasks[taskId].data[3]; + } + + if (gTasks[taskId].data[2] == 1) + targetBlendAmount = 0; + sub_80B9DA0(taskId, initialBlendAmount, targetBlendAmount); + } + else + { + DestroyAnimVisualTask(taskId); + } + } +} + +void sub_80B9E58(u8 taskId) +{ + u8 paletteIndex; + + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + 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[8] = 0; + sub_80B9EA8(taskId, 0, gTasks[taskId].data[4]); + gTasks[taskId].func = sub_80B9F04; +} + +static void sub_80B9EA8(u8 taskId, u8 initialBlendAmount, u8 targetBlendAmount) +{ + u8 paletteIndex = IndexOfSpritePaletteTag(gTasks[taskId].data[0]); + + BeginNormalPaletteFade(1 << (paletteIndex + 16), + gTasks[taskId].data[1], + initialBlendAmount, + targetBlendAmount, + gTasks[taskId].data[5]); + --gTasks[taskId].data[2]; + gTasks[taskId].data[8] ^= 1; +} + +static void sub_80B9F04(u8 taskId) +{ + u8 initialBlendAmount, targetBlendAmount; + + if (!gPaletteFade.active) + { + if (gTasks[taskId].data[2] > 0) + { + if (gTasks[taskId].data[8] == 0) + { + initialBlendAmount = gTasks[taskId].data[3]; + targetBlendAmount = gTasks[taskId].data[4]; + } + else + { + initialBlendAmount = gTasks[taskId].data[4]; + targetBlendAmount = gTasks[taskId].data[3]; + } + + if (gTasks[taskId].data[2] == 1) + targetBlendAmount = 0; + sub_80B9EA8(taskId, initialBlendAmount, targetBlendAmount); + } + else + { + DestroyAnimVisualTask(taskId); + } + } +} + +void sub_80B9F6C(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 = sub_80B9FD8; +} + +static void sub_80B9FD8(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 = sub_80BA090; + 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 sub_80BA090(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 sub_80BA0E8(u8 taskId) +{ + u32 selectedPalettes = 0; + u8 attackerBattler = gBattleAnimAttacker; + u8 targetBattler = gBattleAnimTarget; + + if (gBattleAnimArgs[0] & 0x100) + selectedPalettes = sub_8075BE8(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); +} + +// not used +static void sub_80BA16C(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 sub_80BA27C(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) + sub_80BA3CC(); + sprite->callback = sub_80BA320; +} + +static void sub_80BA320(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 = 0; + DestroyAnimSprite(sprite); + } +} + +static void sub_80BA3CC(void) +{ + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = 0; + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = 0; + if (gBattleAnimArgs[4] == 2) + { + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = 1; + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = 1; + } + else + { + if (gBattleAnimArgs[4] == 0) + gSprites[gBattlerSpriteIds[gBattleAnimAttacker]].coordOffsetEnabled = 1; + else + gSprites[gBattlerSpriteIds[gBattleAnimTarget]].coordOffsetEnabled = 1; + } +} + +void sub_80BA47C(u8 taskId) +{ + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gTasks[taskId].data[1] = gBattleAnimArgs[1]; + gTasks[taskId].data[2] = gBattleAnimArgs[2]; + gTasks[taskId].data[3] = gBattleAnimArgs[3]; + gTasks[taskId].data[8] = gBattleAnimArgs[3]; + gBattle_BG3_X = gBattleAnimArgs[0]; + gBattle_BG3_Y = gBattleAnimArgs[1]; + gTasks[taskId].func = sub_80BA4D0; + gTasks[taskId].func(taskId); +} + +static void sub_80BA4D0(u8 taskId) +{ + if (gTasks[taskId].data[3] == 0) + { + if (gBattle_BG3_X == gTasks[taskId].data[0]) + gBattle_BG3_X = -gTasks[taskId].data[0]; + else + gBattle_BG3_X = gTasks[taskId].data[0]; + + if (gBattle_BG3_Y == -gTasks[taskId].data[1]) + gBattle_BG3_Y = 0; + else + gBattle_BG3_Y = -gTasks[taskId].data[1]; + + gTasks[taskId].data[3] = gTasks[taskId].data[8]; + if (--gTasks[taskId].data[2] == 0) + { + gBattle_BG3_X = 0; + gBattle_BG3_Y = 0; + DestroyAnimVisualTask(taskId); + } + } + else + { + --gTasks[taskId].data[3]; + } +} + +static void sub_80BA560(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); + if (gBattleAnimArgs[2] == 0) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void sub_80BA5A8(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); + if (gBattleAnimArgs[2] == 0) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[4]; + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; + StoreSpriteCallbackInData6(sprite, sub_80B1D3C); +} + +static void sub_80BA5F8(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER && !IsContest()) + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + sub_80BA560(sprite); +} + +static void sub_80BA630(struct Sprite *sprite) +{ + if (gBattleAnimArgs[1] == -1) + gBattleAnimArgs[1] = Random() & 3; + StartSpriteAffineAnim(sprite, gBattleAnimArgs[1]); + if (gBattleAnimArgs[0] == 0) + InitSpritePosToAnimAttacker(sprite, 0); + else + InitSpritePosToAnimTarget(sprite, FALSE); + sprite->pos2.x += (Random() % 48) - 24; + sprite->pos2.y += (Random() % 24) - 12; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; +} + +static void sub_80BA6C8(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 sub_80BA738(struct Sprite *sprite) +{ + if (gBattleAnimArgs[2] == 0) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[3]; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = WaitAnimForDuration; +} + +static void sub_80BA780(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); + if (gBattleAnimArgs[2] == 0) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->callback = sub_80BA7BC; +} + +static void sub_80BA7BC(struct Sprite *sprite) +{ + sprite->invisible ^= 1; + if (sprite->data[0]++ > 12) + DestroyAnimSprite(sprite); +} diff --git a/src/pokemon.c b/src/pokemon.c index 4685dcbcd..1159b1861 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -13,7 +13,6 @@ #include "event_data.h" #include "util.h" #include "pokemon_storage_system.h" -#include "data.h" #include "battle_gfx_sfx_util.h" #include "battle_controllers.h" #include "evolution_scene.h" diff --git a/src/psychic.c b/src/psychic.c new file mode 100644 index 000000000..181f21810 --- /dev/null +++ b/src/psychic.c @@ -0,0 +1,1083 @@ +#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/songs.h" + +static void sub_80B2ECC(struct Sprite *sprite); +static void sub_80B31D0(struct Sprite *sprite); +static void sub_80B3278(struct Sprite *sprite); +static void sub_80B32F4(struct Sprite *sprite); +static void sub_80B37EC(struct Sprite *sprite); +static void sub_80B3A34(struct Sprite *sprite); +static void sub_80B3E84(struct Sprite *sprite); +static void sub_80B300C(struct Sprite *sprite); +static void sub_80B3044(struct Sprite *sprite); +static void sub_80B30B0(struct Sprite *sprite); +static void sub_80B3168(struct Sprite *sprite); +static void sub_80B3384(struct Sprite *sprite); +static void sub_80B33B8(struct Sprite *sprite); +static void sub_80B3454(u8 taskId); +static void sub_80B34DC(u8 taskId); +static void sub_80B3618(u8 taskId); +static void sub_80B3980(u8 taskId); +static void sub_80B3B78(u8 taskId); +static void sub_80B3D78(u8 taskId); + +static const union AffineAnimCmd gUnknown_83E6DDC[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0xFFFE, 0xFFFE, -10, 120), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6DF4[] = +{ + gUnknown_83E6DDC, +}; + +const struct SpriteTemplate gUnknown_83E6DF8 = +{ + .tileTag = ANIM_TAG_SPIRAL, + .paletteTag = ANIM_TAG_SPIRAL, + .oam = &gOamData_83ACB60, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6DF4, + .callback = sub_8075D9C, +}; + +const struct SpriteTemplate gUnknown_83E6E10 = +{ + .tileTag = ANIM_TAG_GREEN_LIGHT_WALL, + .paletteTag = ANIM_TAG_GREEN_LIGHT_WALL, + .oam = &gOamData_83ACB00, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2ECC, +}; + +const struct SpriteTemplate gUnknown_83E6E28 = +{ + .tileTag = ANIM_TAG_BLUE_LIGHT_WALL, + .paletteTag = ANIM_TAG_BLUE_LIGHT_WALL, + .oam = &gOamData_83ACB00, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2ECC, +}; + +const struct SpriteTemplate gUnknown_83E6E40 = +{ + .tileTag = ANIM_TAG_RED_LIGHT_WALL, + .paletteTag = ANIM_TAG_RED_LIGHT_WALL, + .oam = &gOamData_83ACB00, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2ECC, +}; + +const struct SpriteTemplate gUnknown_83E6E58 = +{ + .tileTag = ANIM_TAG_GRAY_LIGHT_WALL, + .paletteTag = ANIM_TAG_GRAY_LIGHT_WALL, + .oam = &gOamData_83ACB00, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2ECC, +}; + +const struct SpriteTemplate gUnknown_83E6E70 = +{ + .tileTag = ANIM_TAG_ORANGE_LIGHT_WALL, + .paletteTag = ANIM_TAG_ORANGE_LIGHT_WALL, + .oam = &gOamData_83ACB00, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B2ECC, +}; + +static const union AnimCmd gUnknown_83E6E88[] = +{ + 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 gUnknown_83E6EA0[] = +{ + gUnknown_83E6E88, +}; + +const struct SpriteTemplate gUnknown_83E6EA4 = +{ + .tileTag = ANIM_TAG_SPARKLE_4, + .paletteTag = ANIM_TAG_SPARKLE_4, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E6EA0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B31D0, +}; + +static const union AnimCmd gUnknown_83E6EBC[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_FRAME(12, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E6ED0[] = +{ + gUnknown_83E6EBC, +}; + +const struct SpriteTemplate gUnknown_83E6ED4 = +{ + .tileTag = ANIM_TAG_SPARKLE_3, + .paletteTag = ANIM_TAG_SPARKLE_3, + .oam = &gOamData_83AC9D0, + .anims = gUnknown_83E6ED0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B31D0, +}; + +const struct SpriteTemplate gUnknown_83E6EEC = +{ + .tileTag = ANIM_TAG_GOLD_RING, + .paletteTag = ANIM_TAG_GOLD_RING, + .oam = &gOamData_83ACA18, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = TranslateAnimSpriteToTargetMonLocation, +}; + +static const union AnimCmd gUnknown_83E6F04[] = +{ + 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, +}; + +const union AnimCmd gUnknown_83E6F44[] = +{ + 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 gUnknown_83E6F84[] = +{ + gUnknown_83E6F04, + gUnknown_83E6F44, +}; + +const struct SpriteTemplate gUnknown_83E6F8C = +{ + .tileTag = ANIM_TAG_BENT_SPOON, + .paletteTag = ANIM_TAG_BENT_SPOON, + .oam = &gOamData_83ACA18, + .anims = gUnknown_83E6F84, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B3278, +}; + +static const union AnimCmd gUnknown_83E6FA4[] = +{ + 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 gUnknown_83E6FC4[] = +{ + gUnknown_83E6FA4, +}; + +static const union AffineAnimCmd gUnknown_83E6FC8[] = +{ + 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 gUnknown_83E6FF0[] = +{ + gUnknown_83E6FC8, +}; + +const struct SpriteTemplate gUnknown_83E6FF4 = +{ + .tileTag = ANIM_TAG_AMNESIA, + .paletteTag = ANIM_TAG_AMNESIA, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E6FC4, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B32F4, +}; + +static const union AffineAnimCmd gUnknown_83E700C[] = +{ + AFFINEANIMCMD_FRAME(-8, 10, 0, 16), + AFFINEANIMCMD_FRAME(18, -18, 0, 16), + AFFINEANIMCMD_FRAME(-20, 16, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E702C[] = +{ + AFFINEANIMCMD_FRAME(64, -4, 0, 20), + AFFINEANIMCMD_FRAME(0, 0, 0, -56), + AFFINEANIMCMD_END, +}; + +static const struct SpriteTemplate gUnknown_83E7044 = +{ + .tileTag = ANIM_TAG_HOLLOW_ORB, + .paletteTag = ANIM_TAG_HOLLOW_ORB, + .oam = &gOamData_83ACAF0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +const struct SpriteTemplate gUnknown_83E705C = +{ + .tileTag = 0x280A, + .paletteTag = 0x280A, + .oam = &gOamData_83AC9E0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B37EC, +}; + +static const union AffineAnimCmd gUnknown_83E7074[] = +{ + AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 8), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd gUnknown_83E708C[] = +{ + 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 gUnknown_83E70B4[] = +{ + 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 gUnknown_83E70DC[] = +{ + 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 gUnknown_83E7104[] = +{ + gUnknown_83E7074, + gUnknown_83E708C, + gUnknown_83E70B4, + gUnknown_83E70DC, +}; + +static const struct SpriteTemplate gUnknown_83E7114 = +{ + .tileTag = ANIM_TAG_BLUEGREEN_ORB, + .paletteTag = ANIM_TAG_BLUEGREEN_ORB, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7104, + .callback = sub_80B3A34, +}; + +static const union AffineAnimCmd gUnknown_83E712C[] = +{ + AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 120), + AFFINEANIMCMD_END_ALT(1), +}; + +static const union AffineAnimCmd *const gUnknown_83E7144[] = +{ + gUnknown_83E712C, +}; + +const struct SpriteTemplate gUnknown_83E7148 = +{ + .tileTag = ANIM_TAG_WHITE_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_WHITE_CIRCLE_OF_LIGHT, + .oam = &gOamData_83ACBC0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E7144, + .callback = sub_8075D9C, +}; + +static const union AffineAnimCmd gUnknown_83E7160[] = +{ + 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 gUnknown_83E71B8[] = +{ + AFFINEANIMCMD_FRAME(0xFFEC, 0x18, 0, 15), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E71C8[] = +{ + gUnknown_83E7160, + gUnknown_83E71B8, +}; + +const struct SpriteTemplate gUnknown_83E71D0 = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_83ACBC0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E71C8, + .callback = sub_80B3E84, +}; + +static void sub_80B2ECC(struct Sprite *sprite) +{ + 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); + s32 var0 = 1; + u8 toBG_2 = (rank ^ var0) != 0; + + if (IsBattlerSpriteVisible(battler)) + MoveBattlerSpriteToBG(battler, toBG_2); + battler = BATTLE_PARTNER(battlerCopy); + if (IsBattlerSpriteVisible(battler)) + MoveBattlerSpriteToBG(battler, toBG_2 ^ var0); + } + 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]; + } + if (IsContest()) + sprite->pos1.y += 9; + sprite->data[0] = 256 + IndexOfSpritePaletteTag(gBattleAnimArgs[2]) * 16; + sprite->callback = sub_80B300C; + sub_80B300C(sprite); +} + +static void sub_80B300C(struct Sprite *sprite) +{ + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(sprite->data[3], 16 - sprite->data[3])); + if (sprite->data[3] == 13) + sprite->callback = sub_80B3044; + else + ++sprite->data[3]; +} + +static void sub_80B3044(struct Sprite *sprite) +{ + u16 color; + u16 startOffset; + s32 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 = sub_80B30B0; + } +} + +static void sub_80B30B0(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 = sub_80B3168; + } +} + +static void sub_80B3168(struct Sprite *sprite) +{ + if (!IsContest()) + { + u8 battlerCopy; + u8 battler = battlerCopy = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + u8 rank = GetBattlerSpriteBGPriorityRank(battler); + s32 var0 = 1; + u8 toBG_2 = (rank ^ var0) != 0; + + if (IsBattlerSpriteVisible(battler)) + sub_8073128(toBG_2); + battler = battlerCopy ^ 2; + if (IsBattlerSpriteVisible(battler)) + sub_8073128(toBG_2 ^ var0); + } + sprite->callback = DestroyAnimSprite; +} + +static void sub_80B31D0(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] == 0) + InitSpritePosToAnimAttacker(sprite, respectMonPicOffsets); + else + InitSpritePosToAnimTarget(sprite, respectMonPicOffsets); + } + + ++sprite->data[0]; + } + else if (sprite->animEnded || sprite->affineAnimEnded) + { + DestroySpriteAndMatrix(sprite); + } +} + +static void sub_80B3278(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; +} + +static void sub_80B32F4(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, sub_80B3384); + sprite->callback = RunStoredCallbackWhenAnimEnds; +} + +static void sub_80B3384(struct Sprite *sprite) +{ + sprite->oam.affineMode = ST_OAM_AFFINE_NORMAL; + sprite->affineAnims = gUnknown_83E6FF0; + sprite->data[0] = 0; + InitSpriteAffineAnim(sprite); + sprite->callback = sub_80B33B8; +} + +static void sub_80B33B8(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 sub_80B3418(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); + + task->data[0] = spriteId; + PrepareAffineAnimInTaskData(task, spriteId, gUnknown_83E700C); + task->func = sub_80B3454; +} + +static void sub_80B3454(u8 taskId) +{ + if (!RunAffineAnimFromTaskData(&gTasks[taskId])) + DestroyAnimVisualTask(taskId); +} + +void sub_80B3480(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], gUnknown_83E702C); + task->func = sub_80B34DC; +} + +static void sub_80B34DC(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 sub_80B3584(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 = sub_80B3618; +} + +static void sub_80B3618(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(&gUnknown_83E7044, 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_80B37A4(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 sub_80B37EC(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == 0) + { + 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_80B37A4; +} + +void sub_80B3834(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (IsContest()) + { + if (gBattleAnimArgs[0] == 1) + { + 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 = sub_80B3980; +} + +static void sub_80B3980(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(&gUnknown_83E7114, 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 sub_80B3A34(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + { + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } +} + +void sub_80B3A58(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; + } + for (i = task->data[14]; i <= task->data[14] + 64; ++i) + { + gScanlineEffectRegBuffers[0][i] = task->data[10]; + gScanlineEffectRegBuffers[1][i] = task->data[10]; + } + scanlineParams.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT; + scanlineParams.initState = 1; + scanlineParams.unused9 = 0; + ScanlineEffect_SetParams(scanlineParams); + task->func = sub_80B3B78; +} + +static void sub_80B3B78(u8 taskId) +{ + s16 sineIndex, i; + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + sineIndex = task->data[13]; + for (i = task->data[14]; i <= task->data[15]; ++i) + { + 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]; + } + if (++task->data[1] > 23) + ++task->data[0]; + break; + case 1: + gScanlineEffect.state = 3; + ++task->data[0]; + break; + case 2: + DestroyAnimVisualTask(taskId); + break; + } +} + +void sub_80B3C78(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 = TRUE; + ++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 = sub_80B3D78; +} + +static void sub_80B3D78(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 sub_80B3E84(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 new file mode 100644 index 000000000..4db903344 --- /dev/null +++ b/src/rock.c @@ -0,0 +1,830 @@ +#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/songs.h" + +static void sub_80B4634(struct Sprite *sprite); +static void sub_80B46F8(struct Sprite *sprite); +static void AnimDirtParticleAcrossScreen(struct Sprite *sprite); +static void AnimRaiseSprite(struct Sprite *sprite); +static void sub_80B4D00(u8 taskId); +static void sub_80B4F78(struct Sprite *sprite); +static void sub_80B4FE4(struct Sprite *sprite); +static void sub_80B5074(struct Sprite *sprite); +static void sub_80B50A0(struct Sprite *sprite); +static void sub_80B477C(struct Sprite *sprite); +static void sub_80B46B4(struct Sprite *sprite); +static void sub_80B47C4(struct Sprite *sprite); +static void sub_80B490C(u8 taskId); +static void sub_80B4E70(struct Task *task); +static u8 sub_80B4FB8(void); +static void sub_80B5024(struct Sprite *sprite); +static void sub_80B50F8(struct Sprite *sprite); + +static const union AnimCmd gUnknown_83E7390[] = +{ + ANIMCMD_FRAME(32, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E7398[] = +{ + ANIMCMD_FRAME(48, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E73A0[] = +{ + ANIMCMD_FRAME(64, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E73A8[] = +{ + gUnknown_83E7390, + gUnknown_83E7398, + gUnknown_83E73A0, +}; + +const struct SpriteTemplate gUnknown_83E73B4 = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E73A8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B4634, +}; + +const struct SpriteTemplate gUnknown_83E73CC = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E73A8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B46F8, +}; + +const struct SpriteTemplate gUnknown_83E73E4 = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B477C, +}; + +static const union AffineAnimCmd gUnknown_83E73FC[] = +{ + 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 gUnknown_83E741C[] = +{ + gUnknown_83E73FC, +}; + +const struct SpriteTemplate gUnknown_83E7420 = +{ + .tileTag = ANIM_TAG_WATER_ORB, + .paletteTag = ANIM_TAG_WATER_ORB, + .oam = &gOamData_83ACB50, + .anims = gUnknown_83E5958, + .images = NULL, + .affineAnims = gUnknown_83E741C, + .callback = sub_80B477C, +}; + +const struct SpriteTemplate gUnknown_83E7438 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5D48, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B477C, +}; + +const struct SpriteTemplate gUnknown_83E7450 = +{ + .tileTag = ANIM_TAG_FLYING_DIRT, + .paletteTag = ANIM_TAG_FLYING_DIRT, + .oam = &gOamData_83AC9F8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDirtParticleAcrossScreen, +}; + +static const struct Subsprite gUnknown_83E7468[] = +{ + { + .x = -16, + .y = 0, + .shape = ST_OAM_H_RECTANGLE, + .size = 2, + .tileOffset = 0, + .priority = 1, + }, + { + .x = 16, + .y = 0, + .shape = ST_OAM_H_RECTANGLE, + .size = 2, + .tileOffset = 8, + .priority = 1, + }, +}; + +static const struct SubspriteTable gUnknown_83E7470[] = +{ + { ARRAY_COUNT(gUnknown_83E7468), gUnknown_83E7468 }, +}; + +static const union AnimCmd gUnknown_83E7478[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E7480[] = +{ + ANIMCMD_FRAME(16, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E7488[] = +{ + ANIMCMD_FRAME(32, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E7490[] = +{ + ANIMCMD_FRAME(48, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E7498[] = +{ + ANIMCMD_FRAME(64, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E74A0[] = +{ + ANIMCMD_FRAME(80, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E74A8[] = +{ + gUnknown_83E7478, + gUnknown_83E7480, +}; + +static const union AnimCmd *const gUnknown_83E74B0[] = +{ + gUnknown_83E7488, + gUnknown_83E7490, +}; + +static const union AnimCmd *const gUnknown_83E74B8[] = +{ + gUnknown_83E7498, + gUnknown_83E74A0, +}; + +const struct SpriteTemplate gUnknown_83E74C0 = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E74A8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRaiseSprite, +}; + +const struct SpriteTemplate gUnknown_83E74D8 = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B4F78, +}; + +const struct SpriteTemplate gUnknown_83E74F0 = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83AC9D8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B4F78, +}; + +const struct SpriteTemplate gUnknown_83E7508 = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E74A8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B4FE4, +}; + +static const union AffineAnimCmd gUnknown_83E7520[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -5, 5), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd gUnknown_83E7530[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 5, 5), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gUnknown_83E7540[] = +{ + gUnknown_83E7520, + gUnknown_83E7530, +}; + +const struct SpriteTemplate gUnknown_83E7548 = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83ACA38, + .anims = gUnknown_83E74A8, + .images = NULL, + .affineAnims = gUnknown_83E7540, + .callback = sub_80B5074, +}; + +const struct SpriteTemplate gUnknown_83E7560 = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83ACA38, + .anims = gUnknown_83E74A8, + .images = NULL, + .affineAnims = gUnknown_83E7540, + .callback = sub_80B50A0, +}; + +const struct SpriteTemplate gUnknown_83E7578 = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E74B8, + .images = NULL, + .affineAnims = gUnknown_83E7540, + .callback = AnimMoveTwisterParticle, +}; + +const struct SpriteTemplate gUnknown_83E7590 = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_83ACA38, + .anims = gUnknown_83E74B0, + .images = NULL, + .affineAnims = gUnknown_83E7540, + .callback = sub_8077350, +}; + +static void sub_80B4634(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, sub_80B46B4); + sprite->callback = TranslateSpriteInEllipseOverDuration; + sprite->callback(sprite); +} + +static void sub_80B46B4(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); +} + +static void sub_80B46F8(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); +} + +static void sub_80B477C(struct Sprite *sprite) +{ + if (gBattleAnimArgs[6] == 0) + 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 = sub_80B47C4; +} + +static void sub_80B47C4(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) +{ + s32 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_80752A0(&animBg); + AnimLoadCompressedBgTilemap(animBg.bgId, gFile_graphics_battle_anims_backgrounds_sandstorm_brew_tilemap); + AnimLoadCompressedBgGfx(animBg.bgId, gFile_graphics_battle_anims_backgrounds_sandstorm_brew_sheet, animBg.tilesOffset); + LoadCompressedPalette(gBattleAnimSpritePal_FlyingDirt, animBg.paletteId * 16, 32); + if (IsContest()) + sub_80730C0(animBg.paletteId, animBg.bgTilemap, 0, 0); + if (gBattleAnimArgs[0] && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + var0 = 1; + gTasks[taskId].data[0] = var0; + gTasks[taskId].func = sub_80B490C; +} + +static void sub_80B490C(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_80752A0(&animBg); + sub_8075358(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 AnimDirtParticleAcrossScreen(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, gUnknown_83E7470); + 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 sub_80B4BD0(u8 taskId) +{ + u16 var0, var1, var2, var3; + u8 var4; + s32 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; + var4 = sub_80B4FB8(); + if (var4 == 1) + task->data[8] = 32; + else + task->data[8] = 48 - (var4 * 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(PAN_SIDE_PLAYER); + pan2 = BattleAnimAdjustPanning(PAN_SIDE_OPPONENT); + task->data[13] = pan1; + task->data[14] = (pan2 - pan1) / task->data[8]; + task->data[1] = var4; + task->data[15] = GetAnimBattlerSpriteId(0); + task->func = sub_80B4D00; +} + +static void sub_80B4D00(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_80B4E70(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_80B4E70(struct Task *task) +{ + const struct SpriteTemplate *spriteTemplate; + s32 var0; + u16 x, y; + u8 spriteId; + + switch (task->data[1]) + { + case 1: + spriteTemplate = &gUnknown_83E74D8; + var0 = 0; + break; + case 2: + case 3: + spriteTemplate = &gUnknown_83E74F0; + var0 = 80; + break; + case 4: + spriteTemplate = &gUnknown_83E74F0; + var0 = 64; + break; + case 5: + spriteTemplate = &gUnknown_83E74F0; + var0 = 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 += var0; + InitAnimArcTranslation(&gSprites[spriteId]); + ++task->data[11]; + } + task->data[12] *= -1; +} + +static void sub_80B4F78(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + { + u8 taskId = FindTaskIdByFunc(sub_80B4D00); + + if (taskId != TASK_NONE) + --gTasks[taskId].data[11]; + DestroySprite(sprite); + } +} + +static u8 sub_80B4FB8(void) +{ + u8 retVal = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer; + u8 var0 = retVal - 1; + + if (var0 > 4) + retVal = 1; + return retVal; +} + +static void sub_80B4FE4(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 = sub_80B5024; + sprite->invisible = TRUE; +} + +static void sub_80B5024(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 sub_80B5074(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + StartSpriteAffineAnim(sprite, 1); + TranslateAnimSpriteToTargetMonLocation(sprite); +} + +static void sub_80B50A0(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 = sub_80B50F8; +} + +static void sub_80B50F8(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[7] = 0; + if ((u32)gAnimMoveDmg - 33 < 33) + gBattleAnimArgs[7] = 1; + if (gAnimMoveDmg > 65) + gBattleAnimArgs[7] = 2; + DestroyAnimVisualTask(taskId); +} + +void sub_80B5188(u8 taskId) +{ + if (gTasks[taskId].data[0] == 0) + { + sub_8075458(0); + 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_8075458(1); + DestroyAnimVisualTask(taskId); + } + ++gTasks[taskId].data[0]; +} + +void sub_80B51EC(u8 taskId) +{ + if (gTasks[taskId].data[0] == 0) + { + sub_8075458(0); + ++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_8075458(1); + DestroyAnimVisualTask(taskId); + } +} |