From 7edb7bbc234e0658ccc5c3bc7df2f1bce836f984 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sat, 6 Aug 2022 02:25:28 -0400 Subject: [PATCH] Added battle slide-in animation for Pokemon follower. --- include/battle_main.h | 1 + include/pokeball.h | 1 + src/battle_controller_player.c | 35 +++++++++++++++++----- src/battle_main.c | 23 ++++++++++++++ src/data/trainer_graphics/back_pic_anims.h | 28 +++++++++++++++++ src/pokeball.c | 11 +++++++ 6 files changed, 91 insertions(+), 8 deletions(-) diff --git a/include/battle_main.h b/include/battle_main.h index 449131e534..2a6e4bf3d7 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -61,6 +61,7 @@ void SpriteCB_FaintSlideAnim(struct Sprite *sprite); void DoBounceEffect(u8 battlerId, u8 b, s8 c, s8 d); void EndBounceEffect(u8 battlerId, bool8 b); void SpriteCB_PlayerMonFromBall(struct Sprite *sprite); +void SpriteCB_PlayerMonSlideIn(struct Sprite *sprite); void SpriteCB_TrainerThrowObject(struct Sprite *sprite); void AnimSetCenterToCornerVecX(struct Sprite *sprite); void BeginBattleIntroDummy(void); diff --git a/include/pokeball.h b/include/pokeball.h index 1149791b86..3dbd80527f 100644 --- a/include/pokeball.h +++ b/include/pokeball.h @@ -32,6 +32,7 @@ extern const struct SpriteTemplate gBallSpriteTemplates[]; #define POKEBALL_PLAYER_SENDOUT 0xFF #define POKEBALL_OPPONENT_SENDOUT 0xFE +#define POKEBALL_PLAYER_SLIDEIN 0xFD u8 DoPokeballSendOutAnimation(s16 pan, u8 kindOfThrow); void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriortiy, u8 delay, u32 fadePalettes, u16 species); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 954192f0ab..c0e2ff7265 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -10,6 +10,7 @@ #include "battle_tv.h" #include "bg.h" #include "data.h" +#include "event_object_movement.h" #include "item.h" #include "item_menu.h" #include "link.h" @@ -114,7 +115,7 @@ static void Task_UpdateLvlInHealthbox(u8); static void PrintLinkStandbyMsg(void); static u32 CopyPlayerMonData(u8, u8 *); static void SetPlayerMonData(u8); -static void StartSendOutAnim(u8, bool8); +static void StartSendOutAnim(u8, bool8, bool8); static void DoSwitchOutAnimation(void); static void PlayerDoMoveAnimation(void); static void Task_StartSendOutAnim(u8); @@ -2189,11 +2190,29 @@ static void PlayerHandleSwitchInAnim(void) BattleLoadPlayerMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); gActionSelectionCursor[gActiveBattler] = 0; gMoveSelectionCursor[gActiveBattler] = 0; - StartSendOutAnim(gActiveBattler, gBattleBufferA[gActiveBattler][2]); + #ifdef BATTLE_ENGINE + StartSendOutAnim(gActiveBattler, gBattleResources->bufferA[gActiveBattler][2], FALSE); + #else + StartSendOutAnim(gActiveBattler, gBattleBufferA[gActiveBattler][2], FALSE); + #endif gBattlerControllerFuncs[gActiveBattler] = SwitchIn_TryShinyAnimShowHealthbox; } -static void StartSendOutAnim(u8 battlerId, bool8 dontClearSubstituteBit) +// In normal singles, if follower pokemon is out, have it slide in instead of being thrown +static bool8 ShouldDoSlideInAnim(void) { + struct ObjectEvent *followerObj = GetFollowerObject(); + if (!followerObj || followerObj->invisible) + return FALSE; + if (gBattleTypeFlags & ( + BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_FIRST_BATTLE | + BATTLE_TYPE_SAFARI | BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TWO_OPPONENTS | + BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_RECORDED | BATTLE_TYPE_TRAINER_HILL) + ) + return FALSE; + return TRUE; +} + +static void StartSendOutAnim(u8 battlerId, bool8 dontClearSubstituteBit, bool8 doSlideIn) { u16 species; @@ -2221,7 +2240,7 @@ static void StartSendOutAnim(u8 battlerId, bool8 dontClearSubstituteBit) gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; - gSprites[gBattleControllerData[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); + gSprites[gBattleControllerData[battlerId]].data[0] = DoPokeballSendOutAnimation(0, doSlideIn ? POKEBALL_PLAYER_SLIDEIN : POKEBALL_PLAYER_SENDOUT); } static void PlayerHandleReturnMonToBall(void) @@ -2957,7 +2976,7 @@ static void PlayerHandleIntroTrainerBallThrow(void) gSprites[gBattlerSpriteIds[gActiveBattler]].sBattlerId = gActiveBattler; StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[gActiveBattler]], SpriteCB_FreePlayerSpriteLoadMonSprite); - StartSpriteAnim(&gSprites[gBattlerSpriteIds[gActiveBattler]], 1); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[gActiveBattler]], ShouldDoSlideInAnim() ? 2 : 1); paletteNum = AllocSpritePalette(0xD6F8); LoadCompressedPalette(gTrainerBackPicPaletteTable[gSaveBlock2Ptr->playerGender].data, 0x100 + paletteNum * 16, 32); @@ -3004,16 +3023,16 @@ static void Task_StartSendOutAnim(u8 taskId) if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) { gBattleBufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; - StartSendOutAnim(gActiveBattler, FALSE); + StartSendOutAnim(gActiveBattler, FALSE, ShouldDoSlideInAnim()); } else { gBattleBufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; - StartSendOutAnim(gActiveBattler, FALSE); + StartSendOutAnim(gActiveBattler, FALSE, ShouldDoSlideInAnim()); gActiveBattler ^= BIT_FLANK; gBattleBufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; BattleLoadPlayerMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); - StartSendOutAnim(gActiveBattler, FALSE); + StartSendOutAnim(gActiveBattler, FALSE, ShouldDoSlideInAnim()); gActiveBattler ^= BIT_FLANK; } gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox; diff --git a/src/battle_main.c b/src/battle_main.c index f61d5eaae0..6251fa3e81 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -2978,6 +2978,29 @@ void SpriteCB_PlayerMonFromBall(struct Sprite *sprite) BattleAnimateBackSprite(sprite, sprite->sSpeciesId); } +void SpriteCB_PlayerMonSlideIn(struct Sprite *sprite) { + if (sprite->data[3] == 0) { + PlaySE(SE_BALL_TRAY_ENTER); + sprite->data[3]++; + } else if (sprite->data[3] == 1) { + if (sprite->animEnded) + return; + sprite->data[4] = sprite->x; + sprite->x = -33; + sprite->invisible = FALSE; + sprite->data[3]++; + } else if (sprite->data[3] < 27) { + sprite->x += 4; + sprite->data[3]++; + } else { + sprite->data[3] = 0; + sprite->x = sprite->data[4]; + sprite->data[4] = 0; + sprite->callback = SpriteCB_PlayerMonFromBall; + PlayCry_ByMode(sprite->sSpeciesId, -25, CRY_MODE_NORMAL); + } +} + static void SpriteCB_TrainerThrowObject_Main(struct Sprite *sprite) { AnimSetCenterToCornerVecX(sprite); diff --git a/src/data/trainer_graphics/back_pic_anims.h b/src/data/trainer_graphics/back_pic_anims.h index ed12e0cb41..fa55ed7197 100644 --- a/src/data/trainer_graphics/back_pic_anims.h +++ b/src/data/trainer_graphics/back_pic_anims.h @@ -18,6 +18,16 @@ static const union AnimCmd sAnimCmd_May_Steven_1[] = ANIMCMD_END, }; +static const union AnimCmd sAnimCmd_Point_HGSS[] = +{ + ANIMCMD_FRAME(3, 9), + ANIMCMD_FRAME(0, 9), + ANIMCMD_FRAME(2, 24), + ANIMCMD_FRAME(2, 24), + ANIMCMD_FRAME(3, 50), + ANIMCMD_END, +}; + static const union AnimCmd sAnimCmd_Wally_1[] = { ANIMCMD_FRAME(0, 24), @@ -48,6 +58,16 @@ static const union AnimCmd sAnimCmd_Leaf_1[] = ANIMCMD_END, }; +static const union AnimCmd sAnimCmd_Point_HGSS_Red_Leaf[] = +{ + ANIMCMD_FRAME(0, 9), + ANIMCMD_FRAME(1, 9), + ANIMCMD_FRAME(3, 24), + ANIMCMD_FRAME(3, 24), + ANIMCMD_FRAME(0, 50), + ANIMCMD_END, +}; + static const union AnimCmd sAnimCmd_RubySapphireBrendan_1[] = { ANIMCMD_FRAME(0, 24), @@ -72,48 +92,56 @@ static const union AnimCmd *const sBackAnims_Brendan[] = { sAnim_GeneralFrame3, sAnimCmd_Brendan_1, + sAnimCmd_Point_HGSS, }; static const union AnimCmd *const sBackAnims_May[] = { sAnim_GeneralFrame3, sAnimCmd_May_Steven_1, + sAnimCmd_Point_HGSS, }; static const union AnimCmd *const sBackAnims_Red[] = { sAnim_GeneralFrame0, sAnimCmd_Red_1, + sAnimCmd_Point_HGSS_Red_Leaf, }; static const union AnimCmd *const sBackAnims_Leaf[] = { sAnim_GeneralFrame0, sAnimCmd_Leaf_1, + sAnimCmd_Point_HGSS_Red_Leaf, }; static const union AnimCmd *const sBackAnims_RubySapphireBrendan[] = { sAnim_GeneralFrame3, sAnimCmd_RubySapphireBrendan_1, + sAnimCmd_Point_HGSS, }; static const union AnimCmd *const sBackAnims_RubySapphireMay[] = { sAnim_GeneralFrame3, sAnimCmd_RubySapphireMay_1, + sAnimCmd_Point_HGSS, }; static const union AnimCmd *const sBackAnims_Wally[] = { sAnim_GeneralFrame3, sAnimCmd_Wally_1, + sAnimCmd_Point_HGSS, }; static const union AnimCmd *const sBackAnims_Steven[] = { sAnim_GeneralFrame3, sAnimCmd_May_Steven_1, + sAnimCmd_Point_HGSS, }; const union AnimCmd *const *const gTrainerBackAnimsPtrTable[] = diff --git a/src/pokeball.c b/src/pokeball.c index f203633a58..82ae0ee72b 100644 --- a/src/pokeball.c +++ b/src/pokeball.c @@ -380,6 +380,11 @@ static void Task_DoPokeballSendOutAnim(u8 taskId) switch (throwCaseId) { + case POKEBALL_PLAYER_SLIDEIN: // don't actually send out, trigger the slide-in animation + gBattlerTarget = battlerId; + gSprites[ballSpriteId].callback = HandleBallAnimEnd; + gSprites[ballSpriteId].invisible = TRUE; + break; case POKEBALL_PLAYER_SENDOUT: gBattlerTarget = battlerId; gSprites[ballSpriteId].x = 24; @@ -845,6 +850,12 @@ static void HandleBallAnimEnd(struct Sprite *sprite) bool8 affineAnimEnded = FALSE; u8 battlerId = sprite->sBattler; + if (sprite->data[7] == POKEBALL_PLAYER_SLIDEIN) { + gSprites[gBattlerSpriteIds[sprite->sBattler]].callback = SpriteCB_PlayerMonSlideIn; + AnimateSprite(&gSprites[gBattlerSpriteIds[sprite->sBattler]]); + gSprites[gBattlerSpriteIds[sprite->sBattler]].data[1] = 0x1000; + } + gSprites[gBattlerSpriteIds[battlerId]].invisible = FALSE; if (sprite->animEnded) sprite->invisible = TRUE;