From 4293dc8a2476a8fae0b44ee1929a58384c00b43c Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Fri, 10 Mar 2023 23:03:51 -0800 Subject: [PATCH] not entirely confident implementation of Dynamax indicator --- data/battle_scripts_1.s | 2 +- .../battle_interface/dynamax_indicator.png | Bin 0 -> 5409 bytes include/battle.h | 1 + include/battle_dynamax.h | 10 ++ include/battle_interface.h | 1 + src/battle_dynamax.c | 164 +++++++++++++++++- src/battle_gfx_sfx_util.c | 1 + src/battle_interface.c | 15 +- 8 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 graphics/battle_interface/dynamax_indicator.png diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index dc1dc1a47c..5977c3321b 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -10618,8 +10618,8 @@ BattleScript_DynamaxBegins:: playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN waitanimation returntoball BS_SCRIPTING - updatedynamax switchinanim BS_SCRIPTING, TRUE + updatedynamax playanimation BS_SCRIPTING, B_ANIM_DYNAMAX_GROWTH waitanimation end diff --git a/graphics/battle_interface/dynamax_indicator.png b/graphics/battle_interface/dynamax_indicator.png new file mode 100644 index 0000000000000000000000000000000000000000..767a71c1ad5ecd03bac3b3b0060582da49f574fa GIT binary patch literal 5409 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 literal 0 HcmV?d00001 diff --git a/include/battle.h b/include/battle.h index f2b9fb04a5..ac60b0c899 100644 --- a/include/battle.h +++ b/include/battle.h @@ -527,6 +527,7 @@ struct DynamaxData { bool8 playerSelect; u8 triggerSpriteId; + u8 indicatorSpriteId[MAX_BATTLERS_COUNT]; bool8 toDynamax[MAX_BATTLERS_COUNT]; bool8 alreadyDynamaxed[NUM_BATTLE_SIDES]; bool8 dynamaxed[MAX_BATTLERS_COUNT]; diff --git a/include/battle_dynamax.h b/include/battle_dynamax.h index 2fcb0ff402..3854d4c032 100644 --- a/include/battle_dynamax.h +++ b/include/battle_dynamax.h @@ -69,10 +69,20 @@ const u8 *GetMaxMoveName(u16 move); void ChooseDamageNonTypesString(u8 type); u32 GetMaxMoveStatusEffect(u16 move); u16 SetMaxMoveEffect(u16 move); + void ChangeDynamaxTriggerSprite(u8 spriteId, u8 animId); void CreateDynamaxTriggerSprite(u8, bool8); void HideDynamaxTriggerSprite(void); bool32 IsDynamaxTriggerSpriteActive(void); void DestroyDynamaxTriggerSprite(void); +void DynamaxIndicator_LoadSpriteGfx(void); +bool32 DynamaxIndicator_ShouldBeInvisible(u32 battlerId); +u8 DynamaxIndicator_GetSpriteId(u32 healthboxSpriteId); +void DynamaxIndicator_SetVisibilities(u32 healthboxId, bool32 invisible); +void DynamaxIndicator_UpdateOamPriorities(u32 healthboxId, u32 oamPriority); +void DynamaxIndicator_UpdateLevel(u32 healthboxId, u32 level); +void DynamaxIndicator_CreateSprite(u32 battlerId, u32 healthboxSpriteId); +void DynamaxIndicator_DestroySprite(u32 healthboxSpriteId); + #endif diff --git a/include/battle_interface.h b/include/battle_interface.h index f222c56e9d..6ea2501b77 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -90,6 +90,7 @@ void DestoryHealthboxSprite(u8 healthboxSpriteId); void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBankOnly); void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHpBoxes); void InitBattlerHealthboxCoords(u8 battler); +void GetBattlerHealthboxCoords(u8 battler, s16 *x, s16 *y); void UpdateHpTextInHealthbox(u32 healthboxSpriteId, u32 maxOrCurrent, s16 currHp, s16 maxHp); void SwapHpBarsWithHpText(void); void ChangeMegaTriggerSprite(u8 spriteId, u8 animId); diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 589e8fd983..c9093dc12c 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -87,6 +87,10 @@ static const struct GMaxMove sGMaxMoveTable[] = extern u8 gMaxMovePowers[MOVES_COUNT]; +// forward declarations +static void SpriteCb_DynamaxTrigger(struct Sprite *); +static void SpriteCb_DynamaxIndicator(struct Sprite *); + // Returns whether a battler is Dynamaxed. bool8 IsDynamaxed(u16 battlerId) { @@ -618,7 +622,7 @@ u16 SetMaxMoveEffect(u16 move) return effect; } -// Sprite Data +// DYNAMAX TRIGGER: static const u8 ALIGNED(4) sDynamaxTriggerGfx[] = INCBIN_U8("graphics/battle_interface/dynamax_trigger.4bpp"); static const u16 sDynamaxTriggerPal[] = INCBIN_U16("graphics/battle_interface/dynamax_trigger.gbapal"); @@ -666,7 +670,6 @@ static const union AnimCmd *const sSpriteAnimTable_DynamaxTrigger[] = sSpriteAnim_DynamaxTriggerOn, }; -static void SpriteCb_DynamaxTrigger(struct Sprite *sprite); static const struct SpriteTemplate sSpriteTemplate_DynamaxTrigger = { .tileTag = TAG_DYNAMAX_TRIGGER_TILE, @@ -799,3 +802,160 @@ void DestroyDynamaxTriggerSprite(void) #undef tBattler #undef tHide + + +// DYNAMAX INDICATOR: +static const u8 ALIGNED(4) sDynamaxIndicatorGfx[] = INCBIN_U8("graphics/battle_interface/dynamax_indicator.4bpp"); +static const u16 sDynamaxIndicatorPal[] = INCBIN_U16("graphics/battle_interface/dynamax_indicator.gbapal"); + +static const struct SpriteSheet sSpriteSheet_DynamaxIndicator = +{ + sDynamaxIndicatorGfx, sizeof(sDynamaxIndicatorGfx), TAG_DYNAMAX_INDICATOR_TILE +}; +static const struct SpritePalette sSpritePalette_DynamaxIndicator = +{ + sDynamaxIndicatorPal, TAG_DYNAMAX_INDICATOR_PAL +}; + +static const struct SpriteSheet sDynamaxIndicator_SpriteSheet[] = +{ + sDynamaxIndicatorGfx, sizeof(sDynamaxIndicatorGfx), TAG_DYNAMAX_INDICATOR_TILE +}; + +static const struct SpritePalette sDynamaxIndicator_SpritePalette[] = +{ + sDynamaxIndicatorPal, TAG_DYNAMAX_INDICATOR_PAL +}; + +static const struct OamData sOamData_DynamaxIndicator = +{ + .shape = SPRITE_SHAPE(16x16), + .size = SPRITE_SIZE(16x16), + .priority = 1, +}; + +static const struct SpriteTemplate sSpriteTemplate_DynamaxIndicator = +{ + .tileTag = TAG_DYNAMAX_INDICATOR_TILE, + .paletteTag = TAG_DYNAMAX_INDICATOR_PAL, + .oam = &sOamData_DynamaxIndicator, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCb_DynamaxIndicator, +}; + +static const s8 sIndicatorPositions[][2] = +{ + [B_POSITION_PLAYER_LEFT] = {52, -9}, + [B_POSITION_OPPONENT_LEFT] = {44, -9}, + [B_POSITION_PLAYER_RIGHT] = {52, -9}, + [B_POSITION_OPPONENT_RIGHT] = {44, -9}, +}; + +// for sprite data fields +#define tBattler data[0] +#define tType data[1] // Indicator type: dynamax +#define tPosX data[2] +#define tLevelXDelta data[3] // X position depends whether level has 3, 2 or 1 digit + +// data fields for healthboxMain +// oam.affineParam holds healthboxRight spriteId +#define hMain_DynamaxIndicatorId data[3] +#define hMain_HealthBarSpriteId data[5] +#define hMain_Battler data[6] +#define hMain_Data7 data[7] + +// data fields for healthboxRight +#define hOther_HealthBoxSpriteId data[5] + +// data fields for healthbar +#define hBar_HealthBoxSpriteId data[5] + +void DynamaxIndicator_LoadSpriteGfx(void) +{ + LoadSpriteSheet(sDynamaxIndicator_SpriteSheet); + LoadSpritePalette(sDynamaxIndicator_SpritePalette); +} + +bool32 DynamaxIndicator_ShouldBeInvisible(u32 battlerId) +{ + return !IsDynamaxed(battlerId); +} + +u8 DynamaxIndicator_GetSpriteId(u32 healthboxSpriteId) +{ + return gBattleStruct->dynamax.indicatorSpriteId[gSprites[healthboxSpriteId].hMain_Battler]; +} + +void DynamaxIndicator_SetVisibilities(u32 healthboxId, bool32 invisible) +{ + u32 i; + u8 spriteId = DynamaxIndicator_GetSpriteId(healthboxId); + u32 battlerId = gSprites[healthboxId].hMain_Battler; + + if (invisible == TRUE) + gSprites[spriteId].invisible = TRUE; + else // Try visible. + gSprites[spriteId].invisible = DynamaxIndicator_ShouldBeInvisible(battlerId); +} + +void DynamaxIndicator_UpdateOamPriorities(u32 healthboxId, u32 oamPriority) +{ + u32 i; + u8 spriteId = DynamaxIndicator_GetSpriteId(healthboxId); + gSprites[spriteId].oam.priority = oamPriority; +} + +void DynamaxIndicator_UpdateLevel(u32 healthboxId, u32 level) +{ + u32 i; + s16 xDelta = 0; + u8 spriteId = DynamaxIndicator_GetSpriteId(healthboxId); + + if (level >= 100) + xDelta -= 4; + else if (level < 10) + xDelta += 5; + + gSprites[spriteId].tLevelXDelta = xDelta; +} + +void DynamaxIndicator_CreateSprite(u32 battlerId, u32 healthboxSpriteId) +{ + u32 position, level; + u8 spriteId; + s16 xHealthbox = 0, y = 0; + s32 x = 0; + + position = GetBattlerPosition(battlerId); + GetBattlerHealthboxCoords(battlerId, &xHealthbox, &y); + + x = sIndicatorPositions[position][0]; + y += sIndicatorPositions[position][1]; + + spriteId = gBattleStruct->dynamax.indicatorSpriteId[battlerId] = CreateSpriteAtEnd(&sSpriteTemplate_DynamaxIndicator, 0, y, 0); + gSprites[spriteId].tBattler = battlerId; + gSprites[spriteId].tPosX = x; + gSprites[spriteId].invisible = TRUE; +} + +void DynamaxIndicator_DestroySprite(u32 healthboxSpriteId) +{ + u8 spriteId = DynamaxIndicator_GetSpriteId(healthboxSpriteId); + DestroySprite(&gSprites[spriteId]); +} + +static void SpriteCb_DynamaxIndicator(struct Sprite *sprite) +{ + u32 battlerId = sprite->tBattler; + + sprite->x = gSprites[gHealthboxSpriteIds[battlerId]].x + sprite->tPosX + sprite->tLevelXDelta; + sprite->x2 = gSprites[gHealthboxSpriteIds[battlerId]].x2; + sprite->y2 = gSprites[gHealthboxSpriteIds[battlerId]].y2; +} + +#undef tBattler +#undef tType +#undef tPosX +#undef tLevelXDelta diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 7203c12e42..bc4fea906c 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -699,6 +699,7 @@ bool8 BattleLoadAllHealthBoxesGfx(u8 state) LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[0]); LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[1]); MegaIndicator_LoadSpritesGfx(); + DynamaxIndicator_LoadSpriteGfx(); } else if (!IsDoubleBattle()) { diff --git a/src/battle_interface.c b/src/battle_interface.c index 8bbd26764b..4e1e71a014 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -785,6 +785,9 @@ u8 CreateBattlerHealthboxSprites(u8 battlerId) // Create mega indicator sprites. MegaIndicator_CreateSprites(battlerId, healthboxLeftSpriteId); + // Create dynamax indicator sprites. + DynamaxIndicator_CreateSprite(battlerId, healthboxLeftSpriteId); + gBattleStruct->ballSpriteIds[0] = MAX_SPRITES; gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; @@ -868,6 +871,7 @@ void SetHealthboxSpriteInvisible(u8 healthboxSpriteId) gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = TRUE; gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = TRUE; MegaIndicator_SetVisibilities(healthboxSpriteId, TRUE); + DynamaxIndicator_SetVisibilities(healthboxSpriteId, TRUE); } void SetHealthboxSpriteVisible(u8 healthboxSpriteId) @@ -876,6 +880,7 @@ void SetHealthboxSpriteVisible(u8 healthboxSpriteId) gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = FALSE; gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = FALSE; MegaIndicator_SetVisibilities(healthboxSpriteId, FALSE); + DynamaxIndicator_SetVisibilities(healthboxSpriteId, FALSE); } static void UpdateSpritePos(u8 spriteId, s16 x, s16 y) @@ -887,6 +892,7 @@ static void UpdateSpritePos(u8 spriteId, s16 x, s16 y) void DestoryHealthboxSprite(u8 healthboxSpriteId) { MegaIndicator_DestroySprites(healthboxSpriteId); + DynamaxIndicator_DestroySprite(healthboxSpriteId); DestroySprite(&gSprites[gSprites[healthboxSpriteId].oam.affineParam]); DestroySprite(&gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId]); DestroySprite(&gSprites[healthboxSpriteId]); @@ -910,6 +916,7 @@ static void TryToggleHealboxVisibility(u32 priority, u32 healthboxLeftSpriteId, gSprites[healthboxRightSpriteId].invisible = invisible; gSprites[healthbarSpriteId].invisible = invisible; MegaIndicator_SetVisibilities(healthboxLeftSpriteId, invisible); + DynamaxIndicator_SetVisibilities(healthboxLeftSpriteId, invisible); } void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHPBoxes) @@ -927,6 +934,7 @@ void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHPBoxes) gSprites[healthbarSpriteId].oam.priority = priority; MegaIndicator_UpdateOamPriorities(healthboxLeftSpriteId, priority); + DynamaxIndicator_UpdateOamPriorities(healthboxLeftSpriteId, priority); #if B_HIDE_HEALTHBOX_IN_ANIMS if (hideHPBoxes && IsBattlerAlive(i)) @@ -983,14 +991,17 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) u8 *objVram; u8 battler = gSprites[healthboxSpriteId].hMain_Battler; - // Don't print Lv char if mon is mega evolved or primal reverted. + // Don't print Lv char if mon is mega evolved or primal reverted or Dynamaxed. if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]] - || gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]) + || gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]] + || IsDynamaxed(battler)) { objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); xPos = 5 * (3 - (objVram - (text + 2))) - 1; MegaIndicator_UpdateLevel(healthboxSpriteId, lvl); MegaIndicator_SetVisibilities(healthboxSpriteId, FALSE); + DynamaxIndicator_UpdateLevel(healthboxSpriteId, lvl); + DynamaxIndicator_SetVisibilities(healthboxSpriteId, FALSE); } else {