From 317b52f3f62fe3c0c7d31c0f4ab5645c20e845bc Mon Sep 17 00:00:00 2001 From: AgustinGDLV Date: Fri, 10 Mar 2023 22:05:23 -0800 Subject: [PATCH] added Dynamax trigger sprite --- graphics/battle_interface/dynamax_trigger.png | Bin 0 -> 6864 bytes include/battle.h | 1 + include/battle_dynamax.h | 5 + include/battle_interface.h | 5 + src/battle_controller_player.c | 7 +- src/battle_dynamax.c | 185 ++++++++++++++++++ src/battle_interface.c | 1 + 7 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 graphics/battle_interface/dynamax_trigger.png diff --git a/graphics/battle_interface/dynamax_trigger.png b/graphics/battle_interface/dynamax_trigger.png new file mode 100644 index 0000000000000000000000000000000000000000..18f3a84cff77a8022df1117fb25f71bc37d9a713 GIT binary patch literal 6864 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 F{s&w^Bc=cV literal 0 HcmV?d00001 diff --git a/include/battle.h b/include/battle.h index 91aa7b3f24..f2b9fb04a5 100644 --- a/include/battle.h +++ b/include/battle.h @@ -526,6 +526,7 @@ struct ZMoveData struct DynamaxData { bool8 playerSelect; + u8 triggerSpriteId; 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 29857d9c40..2fcb0ff402 100644 --- a/include/battle_dynamax.h +++ b/include/battle_dynamax.h @@ -69,5 +69,10 @@ 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); #endif diff --git a/include/battle_interface.h b/include/battle_interface.h index e0f30b3097..f222c56e9d 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -53,11 +53,16 @@ enum #define TAG_ALPHA_INDICATOR_TILE 0xD779 #define TAG_OMEGA_INDICATOR_TILE 0xD77A #define TAG_ZMOVE_TRIGGER_TILE 0xD77B +#define TAG_DYNAMAX_TRIGGER_TILE 0xD77C +#define TAG_DYNAMAX_INDICATOR_TILE 0xD77D #define TAG_MEGA_TRIGGER_PAL 0xD777 #define TAG_MEGA_INDICATOR_PAL 0xD778 #define TAG_ALPHA_OMEGA_INDICATOR_PAL 0xD779 // Alpha and Omega indicators use the same palette as each of them only uses 4 different colors. #define TAG_ZMOVE_TRIGGER_PAL 0xD77B +#define TAG_DYNAMAX_TRIGGER_PAL 0xD77C +#define TAG_DYNAMAX_INDICATOR_PAL 0xD77D + enum { diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 6619eaff77..2824944896 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -543,7 +543,7 @@ static void HandleInputShowEntireFieldTargets(void) BtlController_EmitTwoReturnValues(BUFFER_B, 10, gMoveSelectionCursor[gActiveBattler] | RET_DYNAMAX | (gMultiUsePlayerCursor << 8)); else BtlController_EmitTwoReturnValues(BUFFER_B, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8)); - HideMegaTriggerSprite(); + HideTriggerSprites(); PlayerBufferExecCompleted(); } else if (JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59) @@ -824,6 +824,7 @@ static void HandleInputChooseMove(void) gBattleStruct->dynamax.playerSelect ^= 1; MoveSelectionDisplayMoveNames(); MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0); + ChangeDynamaxTriggerSprite(gBattleStruct->dynamax.triggerSpriteId, gBattleStruct->dynamax.playerSelect); PlaySE(SE_SELECT); } } @@ -2892,6 +2893,10 @@ static void PlayerHandleChooseMove(void) CreateMegaTriggerSprite(gActiveBattler, 0); if (!IsZMoveTriggerSpriteActive()) gBattleStruct->zmove.triggerSpriteId = 0xFF; + if (!IsDynamaxTriggerSpriteActive()) + gBattleStruct->dynamax.triggerSpriteId = 0xFF; + if (CanDynamax(gActiveBattler)) // TODO: handle Dynamax + Mega + Z-Move + CreateDynamaxTriggerSprite(gActiveBattler, 0); GetUsableZMoves(gActiveBattler, moveInfo->moves); gBattleStruct->zmove.viable = IsZMoveUsable(gActiveBattler, gMoveSelectionCursor[gActiveBattler]); diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 10f4fd32d6..589e8fd983 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -2,11 +2,14 @@ #include "battle.h" #include "battle_anim.h" #include "battle_controllers.h" +#include "battle_interface.h" #include "battle_scripts.h" #include "battle_script_commands.h" #include "data.h" +#include "graphics.h" #include "pokemon.h" #include "random.h" +#include "sprite.h" #include "string_util.h" #include "util.h" #include "constants/abilities.h" @@ -614,3 +617,185 @@ u16 SetMaxMoveEffect(u16 move) } return effect; } + +// Sprite Data +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"); + +static const struct SpriteSheet sSpriteSheet_DynamaxTrigger = +{ + sDynamaxTriggerGfx, sizeof(sDynamaxTriggerGfx), TAG_DYNAMAX_TRIGGER_TILE +}; +static const struct SpritePalette sSpritePalette_DynamaxTrigger = +{ + sDynamaxTriggerPal, TAG_DYNAMAX_TRIGGER_PAL +}; + +static const struct OamData sOamData_DynamaxTrigger = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd sSpriteAnim_DynamaxTriggerOff[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_DynamaxTriggerOn[] = +{ + ANIMCMD_FRAME(16, 0), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_DynamaxTrigger[] = +{ + sSpriteAnim_DynamaxTriggerOff, + sSpriteAnim_DynamaxTriggerOn, +}; + +static void SpriteCb_DynamaxTrigger(struct Sprite *sprite); +static const struct SpriteTemplate sSpriteTemplate_DynamaxTrigger = +{ + .tileTag = TAG_DYNAMAX_TRIGGER_TILE, + .paletteTag = TAG_DYNAMAX_TRIGGER_PAL, + .oam = &sOamData_DynamaxTrigger, + .anims = sSpriteAnimTable_DynamaxTrigger, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCb_DynamaxTrigger +}; + +// Dynamax Evolution Trigger icon functions. +void ChangeDynamaxTriggerSprite(u8 spriteId, u8 animId) +{ + StartSpriteAnim(&gSprites[spriteId], animId); +} + +#define SINGLES_DYNAMAX_TRIGGER_POS_X_OPTIMAL (30) +#define SINGLES_DYNAMAX_TRIGGER_POS_X_PRIORITY (31) +#define SINGLES_DYNAMAX_TRIGGER_POS_X_SLIDE (15) +#define SINGLES_DYNAMAX_TRIGGER_POS_Y_DIFF (-11) + +#define DOUBLES_DYNAMAX_TRIGGER_POS_X_OPTIMAL (30) +#define DOUBLES_DYNAMAX_TRIGGER_POS_X_PRIORITY (31) +#define DOUBLES_DYNAMAX_TRIGGER_POS_X_SLIDE (15) +#define DOUBLES_DYNAMAX_TRIGGER_POS_Y_DIFF (-4) + +#define tBattler data[0] +#define tHide data[1] + +void CreateDynamaxTriggerSprite(u8 battlerId, u8 palId) +{ + LoadSpritePalette(&sSpritePalette_DynamaxTrigger); + if (GetSpriteTileStartByTag(TAG_DYNAMAX_TRIGGER_TILE) == 0xFFFF) + LoadSpriteSheet(&sSpriteSheet_DynamaxTrigger); + if (gBattleStruct->dynamax.triggerSpriteId == 0xFF) + { + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + gBattleStruct->dynamax.triggerSpriteId = CreateSprite(&sSpriteTemplate_DynamaxTrigger, + gSprites[gHealthboxSpriteIds[battlerId]].x - DOUBLES_DYNAMAX_TRIGGER_POS_X_SLIDE, + gSprites[gHealthboxSpriteIds[battlerId]].y - DOUBLES_DYNAMAX_TRIGGER_POS_Y_DIFF, 0); + else + gBattleStruct->dynamax.triggerSpriteId = CreateSprite(&sSpriteTemplate_DynamaxTrigger, + gSprites[gHealthboxSpriteIds[battlerId]].x - SINGLES_DYNAMAX_TRIGGER_POS_X_SLIDE, + gSprites[gHealthboxSpriteIds[battlerId]].y - SINGLES_DYNAMAX_TRIGGER_POS_Y_DIFF, 0); + } + gSprites[gBattleStruct->dynamax.triggerSpriteId].tBattler = battlerId; + gSprites[gBattleStruct->dynamax.triggerSpriteId].tHide = FALSE; + + ChangeDynamaxTriggerSprite(gBattleStruct->dynamax.triggerSpriteId, palId); +} + +static void SpriteCb_DynamaxTrigger(struct Sprite *sprite) +{ + s32 xSlide, xPriority, xOptimal; + s32 yDiff; + + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + { + xSlide = DOUBLES_DYNAMAX_TRIGGER_POS_X_SLIDE; + xPriority = DOUBLES_DYNAMAX_TRIGGER_POS_X_PRIORITY; + xOptimal = DOUBLES_DYNAMAX_TRIGGER_POS_X_OPTIMAL; + yDiff = DOUBLES_DYNAMAX_TRIGGER_POS_Y_DIFF; + } + else + { + xSlide = SINGLES_DYNAMAX_TRIGGER_POS_X_SLIDE; + xPriority = SINGLES_DYNAMAX_TRIGGER_POS_X_PRIORITY; + xOptimal = SINGLES_DYNAMAX_TRIGGER_POS_X_OPTIMAL; + yDiff = SINGLES_DYNAMAX_TRIGGER_POS_Y_DIFF; + } + + if (sprite->tHide) + { + if (sprite->x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xSlide) + sprite->x++; + + if (sprite->x >= gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xPriority) + sprite->oam.priority = 2; + else + sprite->oam.priority = 1; + + sprite->y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y - yDiff; + sprite->y2 = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y2 - yDiff; + if (sprite->x == gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xSlide) + DestroyDynamaxTriggerSprite(); + } + else + { + if (sprite->x != gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xOptimal) + sprite->x--; + + if (sprite->x >= gSprites[gHealthboxSpriteIds[sprite->tBattler]].x - xPriority) + sprite->oam.priority = 2; + else + sprite->oam.priority = 1; + + sprite->y = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y - yDiff; + sprite->y2 = gSprites[gHealthboxSpriteIds[sprite->tBattler]].y2 - yDiff; + } +} + +bool32 IsDynamaxTriggerSpriteActive(void) +{ + if (GetSpriteTileStartByTag(TAG_DYNAMAX_TRIGGER_TILE) == 0xFFFF) + return FALSE; + else if (IndexOfSpritePaletteTag(TAG_DYNAMAX_TRIGGER_PAL) != 0xFF) + return TRUE; + else + return FALSE; +} + +void HideDynamaxTriggerSprite(void) +{ + if (gBattleStruct->dynamax.triggerSpriteId != 0xFF) + { + ChangeDynamaxTriggerSprite(gBattleStruct->dynamax.triggerSpriteId, 0); + gSprites[gBattleStruct->dynamax.triggerSpriteId].tHide = TRUE; + } +} + +void DestroyDynamaxTriggerSprite(void) +{ + FreeSpritePaletteByTag(TAG_DYNAMAX_TRIGGER_PAL); + FreeSpriteTilesByTag(TAG_DYNAMAX_TRIGGER_TILE); + if (gBattleStruct->dynamax.triggerSpriteId != 0xFF) + DestroySprite(&gSprites[gBattleStruct->dynamax.triggerSpriteId]); + gBattleStruct->dynamax.triggerSpriteId = 0xFF; +} + +#undef tBattler +#undef tHide diff --git a/src/battle_interface.c b/src/battle_interface.c index 35c0e60c63..8bbd26764b 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1413,6 +1413,7 @@ void HideTriggerSprites(void) { HideMegaTriggerSprite(); HideZMoveTriggerSprite(); + HideDynamaxTriggerSprite(); } void DestroyMegaTriggerSprite(void)