gimmick not usable repeatably, properly show and hide gimmick indicator, config for hiding hp bar during move anim, reload shadow in ReloadBattlerSprites

This commit is contained in:
cawtds
2024-06-29 01:52:27 +02:00
parent b8ad2ce1a2
commit 6b0fe47b6c
8 changed files with 86 additions and 56 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;