From 6b0fe47b6ce44fe55ac3abafe27e5d042ee2ae66 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Sat, 29 Jun 2024 01:52:27 +0200 Subject: [PATCH] gimmick not usable repeatably, properly show and hide gimmick indicator, config for hiding hp bar during move anim, reload shadow in ReloadBattlerSprites --- include/battle_gfx_sfx_util.h | 1 + include/battle_interface.h | 2 +- src/battle_anim.c | 34 +++++++++++++++++++++++-- src/battle_anim_effects_1.c | 48 +++++++++-------------------------- src/battle_anim_special.c | 8 +++--- src/battle_gfx_sfx_util.c | 20 ++++++++++----- src/battle_interface.c | 28 +++++++++++++++----- src/battle_main.c | 1 + 8 files changed, 86 insertions(+), 56 deletions(-) diff --git a/include/battle_gfx_sfx_util.h b/include/battle_gfx_sfx_util.h index 6284cd901..05e8b70b4 100644 --- a/include/battle_gfx_sfx_util.h +++ b/include/battle_gfx_sfx_util.h @@ -32,6 +32,7 @@ void HandleLowHpMusicChange(struct Pokemon *mon, u8 battlerId); void BattleStopLowHpSound(void); void HandleBattleLowHpMusicChange(void); void SetBattlerSpriteAffineMode(u8 affineMode); +void CreateEnemyShadowSprite(u32 battler); void LoadAndCreateEnemyShadowSprites(void); void SpriteCB_SetInvisible(struct Sprite *sprite); void SetBattlerShadowSpriteCallback(u8 battlerId, u16 species); diff --git a/include/battle_interface.h b/include/battle_interface.h index 9d30dca6f..a2ed4e212 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -109,7 +109,7 @@ void SetHealthboxSpriteInvisible(u8 healthboxSpriteId); void SetHealthboxSpriteVisible(u8 healthboxSpriteId); void DestoryHealthboxSprite(u8 healthboxSpriteId); void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBankOnly); -void UpdateOamPriorityInAllHealthboxes(u8 priority); +void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHPBoxes); void InitBattlerHealthboxCoords(u8 battlerId); void GetBattlerHealthboxCoords(u8 battler, s16 *x, s16 *y); void UpdateHpTextInHealthbox(u32 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp); diff --git a/src/battle_anim.c b/src/battle_anim.c index 1ddf07274..1f2c97040 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -50,6 +50,7 @@ EWRAM_DATA u8 gBattleAnimAttacker = 0; EWRAM_DATA u8 gBattleAnimTarget = 0; EWRAM_DATA u16 gAnimBattlerSpecies[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gAnimCustomPanning = 0; +EWRAM_DATA static bool8 sAnimHideHpBoxes = FALSE; static void AddSpriteIndex(u16 index); static void ClearSpriteIndex(u16 index); @@ -227,8 +228,36 @@ void LaunchBattleAnimation(u32 animType, u16 animId) } } + sAnimHideHpBoxes = !(animType == ANIM_TYPE_MOVE && animId == MOVE_TRANSFORM); + if (animType != ANIM_TYPE_MOVE) + { + switch (animId) + { + case B_ANIM_TURN_TRAP: + case B_ANIM_LEECH_SEED_DRAIN: + case B_ANIM_MON_HIT: + case B_ANIM_SNATCH_MOVE: + case B_ANIM_FUTURE_SIGHT_HIT: + case B_ANIM_DOOM_DESIRE_HIT: + case B_ANIM_WISH_HEAL: + case B_ANIM_MEGA_EVOLUTION: + case B_ANIM_PRIMAL_REVERSION: + case B_ANIM_ULTRA_BURST: + case B_ANIM_GULP_MISSILE: + case B_ANIM_RAINBOW: + case B_ANIM_SEA_OF_FIRE: + case B_ANIM_SWAMP: + case B_ANIM_TERA_CHARGE: + sAnimHideHpBoxes = TRUE; + break; + default: + sAnimHideHpBoxes = FALSE; + break; + } + } + InitPrioritiesForVisibleBattlers(); - UpdateOamPriorityInAllHealthboxes(0); + UpdateOamPriorityInAllHealthboxes(0, sAnimHideHpBoxes); for (i = 0; i < MAX_BATTLERS_COUNT; i++) { if (GetBattlerSide(i) != B_SIDE_PLAYER) @@ -550,7 +579,8 @@ static void Cmd_end(void) { m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 256); InitPrioritiesForVisibleBattlers(); - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, sAnimHideHpBoxes); + sAnimHideHpBoxes = FALSE; gAnimScriptActive = FALSE; } } diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index f86f0b0e2..c736ac19a 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6578,39 +6578,6 @@ void PrepareDoubleTeamAnim(u32 taskId, u32 animBattler, bool32 forAllySwitch) void AnimTask_DoubleTeam(u8 taskId) { PrepareDoubleTeamAnim(taskId, ANIM_ATTACKER, FALSE); - // TODO: remove old if not needed anymore - // u16 i; - // int obj; - // u16 r3; - // u16 r4; - // struct Task* task = &gTasks[taskId]; - - // task->data[0] = GetAnimBattlerSpriteId(ANIM_ATTACKER); - // task->data[1] = AllocSpritePalette(ANIM_TAG_BENT_SPOON); - // r3 = OBJ_PLTT_ID(task->data[1]); - // r4 = OBJ_PLTT_ID2(gSprites[task->data[0]].oam.paletteNum); - // for (i = 1; i < 16; i++) - // gPlttBufferUnfaded[r3 + i] = gPlttBufferUnfaded[r4 + i]; - - // BlendPalette(r3, 16, 11, RGB_BLACK); - // task->data[3] = 0; - // i = 0; - // while (i < 2 && (obj = CloneBattlerSpriteWithBlend(0)) >= 0) - // { - // gSprites[obj].oam.paletteNum = task->data[1]; - // gSprites[obj].data[0] = 0; - // gSprites[obj].data[1] = i << 7; - // gSprites[obj].data[2] = taskId; - // gSprites[obj].callback = AnimDoubleTeam; - // task->data[3]++; - // i++; - // } - - // task->func = AnimTask_DoubleTeam_Step; - // if (GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker) == 1) - // ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); - // else - // ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); } static inline void SwapStructData(void *s1, void *s2, void *data, u32 size) @@ -6622,12 +6589,21 @@ static inline void SwapStructData(void *s1, void *s2, void *data, u32 size) static void ReloadBattlerSprites(u32 battler, struct Pokemon *party) { + struct Pokemon *mon = &party[gBattlerPartyIndexes[battler]]; BattleLoadMonSpriteGfx(&party[gBattlerPartyIndexes[battler]], battler); CreateBattlerSprite(battler); UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &party[gBattlerPartyIndexes[battler]], HEALTHBOX_ALL); - // If battler is mega evolved / primal reversed, hide the sprite until the move animation finishes. - // TODO: mega indicator - // MegaIndicator_SetVisibilities(gHealthboxSpriteIds[battler], TRUE); + // If battler has an indicator for a gimmick, hide the sprite until the move animation finishes. + UpdateIndicatorVisibilityAndType(gHealthboxSpriteIds[battler], TRUE); + + // Try to recreate shadow sprite + if (gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteId < MAX_SPRITES) + { + DestroySprite(&gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteId]); + gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteId = MAX_SPRITES; + CreateEnemyShadowSprite(battler); + SetBattlerShadowSpriteCallback(battler, GetMonData(mon, MON_DATA_SPECIES)); + } } static void AnimTask_AllySwitchDataSwap(u8 taskId) diff --git a/src/battle_anim_special.c b/src/battle_anim_special.c index 1ea912044..adc31a73a 100644 --- a/src/battle_anim_special.c +++ b/src/battle_anim_special.c @@ -1464,7 +1464,7 @@ static void SpriteCB_ThrowBall_DoClick(struct Sprite *sprite) else if (sprite->data[4] == 95) { gDoingBattleAnim = FALSE; - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, FALSE); m4aMPlayAllStop(); PlaySE(MUS_CAUGHT_INTRO); } @@ -1618,7 +1618,7 @@ static void SpriteCB_ThrowBall_RunBreakOut(struct Sprite *sprite) sprite->data[0] = 0; sprite->callback = BattleAnimObj_SignalEnd; gDoingBattleAnim = FALSE; - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, FALSE); } } @@ -1650,7 +1650,7 @@ static void TrainerBallBlock2(struct Sprite *sprite) sprite->data[0] = 0; sprite->callback = BattleAnimObj_SignalEnd; gDoingBattleAnim = FALSE; - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, FALSE); } } @@ -1681,7 +1681,7 @@ static void GhostBallDodge2(struct Sprite *sprite) sprite->data[0] = 0; sprite->callback = BattleAnimObj_SignalEnd; gDoingBattleAnim = FALSE; - UpdateOamPriorityInAllHealthboxes(1); + UpdateOamPriorityInAllHealthboxes(1, FALSE); } static void LoadBallParticleGfx(u8 ballId) diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 1ccbaeee4..3915e83ed 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -850,19 +850,25 @@ void SetBattlerSpriteAffineMode(u8 affineMode) } } +void CreateEnemyShadowSprite(u32 battler) +{ + gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteId = CreateSprite(&gSpriteTemplate_EnemyShadow, GetBattlerSpriteCoord(battler, BATTLER_COORD_X), GetBattlerSpriteCoord(battler, BATTLER_COORD_Y) + 29, 0xC8); + + if (gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteId < MAX_SPRITES) + gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteId].data[0] = battler; +} + void LoadAndCreateEnemyShadowSprites(void) { - u8 battlerId; + u32 battler; LoadCompressedSpriteSheetUsingHeap(&gSpriteSheet_EnemyShadow); - battlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId = CreateSprite(&gSpriteTemplate_EnemyShadow, GetBattlerSpriteCoord(battlerId, BATTLER_COORD_X), GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y) + 29, 0xC8); - gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId].data[0] = battlerId; + battler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + CreateEnemyShadowSprite(battler); if (IsDoubleBattle()) { - battlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); - gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId = CreateSprite(&gSpriteTemplate_EnemyShadow, GetBattlerSpriteCoord(battlerId, BATTLER_COORD_X), GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y) + 29, 0xC8); - gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerId].shadowSpriteId].data[0] = battlerId; + battler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + CreateEnemyShadowSprite(battler); } } diff --git a/src/battle_interface.c b/src/battle_interface.c index cdea13471..e52938da9 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -616,6 +616,7 @@ void SetHealthboxSpriteInvisible(u8 healthboxSpriteId) gSprites[healthboxSpriteId].invisible = TRUE; gSprites[gSprites[healthboxSpriteId].sHealthBarSpriteId].invisible = TRUE; gSprites[gSprites[healthboxSpriteId].sHealthboxOtherSpriteId].invisible = TRUE; + UpdateIndicatorVisibilityAndType(healthboxSpriteId, TRUE); } void SetHealthboxSpriteVisible(u8 healthboxSpriteId) @@ -623,6 +624,7 @@ void SetHealthboxSpriteVisible(u8 healthboxSpriteId) gSprites[healthboxSpriteId].invisible = FALSE; gSprites[gSprites[healthboxSpriteId].sHealthBarSpriteId].invisible = FALSE; gSprites[gSprites[healthboxSpriteId].sHealthboxOtherSpriteId].invisible = FALSE; + UpdateIndicatorVisibilityAndType(healthboxSpriteId, FALSE); } static void UpdateSpritePos(u8 spriteId, s16 x, s16 y) @@ -642,7 +644,23 @@ void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBattlerO { } -void UpdateOamPriorityInAllHealthboxes(u8 priority) +static void TryToggleHealboxVisibility(u32 priority, u32 healthboxLeftSpriteId, u32 healthboxRightSpriteId, u32 healthbarSpriteId) +{ + bool32 invisible = FALSE; + + if (priority == 0) // start of anim -> make invisible + invisible = TRUE; + else if (priority == 1) // end of anim -> make visible + invisible = FALSE; + + gSprites[healthboxLeftSpriteId].invisible = invisible; + gSprites[healthboxRightSpriteId].invisible = invisible; + gSprites[healthbarSpriteId].invisible = invisible; + + UpdateIndicatorVisibilityAndType(healthboxLeftSpriteId, invisible); +} + +void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHPBoxes) { s32 i; @@ -657,6 +675,9 @@ void UpdateOamPriorityInAllHealthboxes(u8 priority) gSprites[healthbarSpriteId].oam.priority = priority; UpdateIndicatorOamPriority(healthbarSpriteId, priority); + + if (B_HIDE_HEALTHBOX_IN_ANIMS == TRUE && hideHPBoxes && IsBattlerAlive(i)) + TryToggleHealboxVisibility(priority, healthboxSpriteId, healthboxOtherSpriteId, healthbarSpriteId); } } @@ -708,8 +729,6 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) u8 *objVram; u8 battler = gSprites[healthboxSpriteId].sBattlerId; - - DebugPrintfLevel(MGBA_LOG_ERROR, "update: tile = %u", GetIndicatorTileTag(battler)); // Don't print Lv char if mon has a gimmick with an indicator active. if (GetIndicatorTileTag(battler) != TAG_NONE) { @@ -728,9 +747,6 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) UpdateIndicatorVisibilityAndType(healthboxSpriteId, TRUE); } - objVram = ConvertIntToDecimalStringN(text + 2, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); - xPos = 5 * (3 - (objVram - (text + 2))); - windowTileData = AddTextPrinterAndCreateWindowOnHealthbox(text, xPos, 3, &windowId); spriteTileNum = gSprites[healthboxSpriteId].oam.tileNum * TILE_SIZE_4BPP; diff --git a/src/battle_main.c b/src/battle_main.c index da8e26cc2..5c60f4edc 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3148,6 +3148,7 @@ void BattleTurnPassed(void) *(&gBattleStruct->absentBattlerFlags) = gAbsentBattlerFlags; BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG); + AssignUsableGimmicks(); SetShellSideArmCategory(); SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers gBattleMainFunc = HandleTurnActionSelectionState;